framebuffer-internal.h 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. // -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
  2. // Copyright (C) 2013 Henner Zeller <h.zeller@acm.org>
  3. //
  4. // This program is free software; you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation version 2.
  7. //
  8. // This program is distributed in the hope that it will be useful,
  9. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. // GNU General Public License for more details.
  12. //
  13. // You should have received a copy of the GNU General Public License
  14. // along with this program. If not, see <http://gnu.org/licenses/gpl-2.0.txt>
  15. #ifndef RPI_RGBMATRIX_FRAMEBUFFER_INTERNAL_H
  16. #define RPI_RGBMATRIX_FRAMEBUFFER_INTERNAL_H
  17. #include <stdint.h>
  18. #include <stdlib.h>
  19. #include "hardware-mapping.h"
  20. namespace rgb_matrix {
  21. class GPIO;
  22. class PinPulser;
  23. namespace internal {
  24. class RowAddressSetter;
  25. // An opaque type used within the framebuffer that can be used
  26. // to copy between PixelMappers.
  27. struct PixelDesignator {
  28. PixelDesignator() : gpio_word(-1), r_bit(0), g_bit(0), b_bit(0), mask(~0u){}
  29. long gpio_word;
  30. gpio_bits_t r_bit;
  31. gpio_bits_t g_bit;
  32. gpio_bits_t b_bit;
  33. gpio_bits_t mask;
  34. };
  35. class PixelDesignatorMap {
  36. public:
  37. PixelDesignatorMap(int width, int height, const PixelDesignator &fill_bits);
  38. ~PixelDesignatorMap();
  39. // Get a writable version of the PixelDesignator. Outside Framebuffer used
  40. // by the RGBMatrix to re-assign mappings to new PixelDesignatorMappers.
  41. PixelDesignator *get(int x, int y);
  42. inline int width() const { return width_; }
  43. inline int height() const { return height_; }
  44. // All bits that set red/green/blue pixels; used for Fill().
  45. const PixelDesignator &GetFillColorBits() { return fill_bits_; }
  46. private:
  47. const int width_;
  48. const int height_;
  49. const PixelDesignator fill_bits_; // Precalculated for fill.
  50. PixelDesignator *const buffer_;
  51. };
  52. // Internal representation of the frame-buffer that as well can
  53. // write itself to GPIO.
  54. // Our internal memory layout mimicks as much as possible what needs to be
  55. // written out.
  56. class Framebuffer {
  57. public:
  58. // Maximum usable bitplanes.
  59. //
  60. // 11 bits seems to be a sweet spot in which we still get somewhat useful
  61. // refresh rate and have good color richness. This is the default setting
  62. // However, in low-light situations, we want to be able to scale down
  63. // brightness more, having more bits at the bottom.
  64. // TODO(hzeller): make the default 15 bit or so, but slide the use of
  65. // timing to lower bits if fewer bits requested to not affect the overall
  66. // refresh in that case.
  67. // This needs to be balanced to not create too agressive timing however.
  68. // To be explored in a separete commit.
  69. //
  70. // For now, if someone needs very low level of light, change this to
  71. // say 13 and recompile. Run with --led-pwm-bits=13. Also, consider
  72. // --led-pwm-dither-bits=2 to have the refresh rate not suffer too much.
  73. static constexpr int kBitPlanes = 11;
  74. static constexpr int kDefaultBitPlanes = 11;
  75. Framebuffer(int rows, int columns, int parallel,
  76. int scan_mode,
  77. const char* led_sequence, bool inverse_color,
  78. PixelDesignatorMap **mapper);
  79. ~Framebuffer();
  80. // Initialize GPIO bits for output. Only call once.
  81. static void InitHardwareMapping(const char *named_hardware);
  82. static void InitGPIO(GPIO *io, int rows, int parallel,
  83. bool allow_hardware_pulsing,
  84. int pwm_lsb_nanoseconds,
  85. int dither_bits,
  86. int row_address_type);
  87. static void InitializePanels(GPIO *io, const char *panel_type, int columns);
  88. // Set PWM bits used for output. Default is 11, but if you only deal with
  89. // simple comic-colors, 1 might be sufficient. Lower require less CPU.
  90. // Returns boolean to signify if value was within range.
  91. bool SetPWMBits(uint8_t value);
  92. uint8_t pwmbits() { return pwm_bits_; }
  93. // Map brightness of output linearly to input with CIE1931 profile.
  94. void set_luminance_correct(bool on) { do_luminance_correct_ = on; }
  95. bool luminance_correct() const { return do_luminance_correct_; }
  96. // Set brightness in percent; range=1..100
  97. // This will only affect newly set pixels.
  98. void SetBrightness(uint8_t b) {
  99. brightness_ = (b <= 100 ? (b != 0 ? b : 1) : 100);
  100. }
  101. uint8_t brightness() { return brightness_; }
  102. void DumpToMatrix(GPIO *io, int pwm_bits_to_show);
  103. void Serialize(const char **data, size_t *len) const;
  104. bool Deserialize(const char *data, size_t len);
  105. void CopyFrom(const Framebuffer *other);
  106. // Canvas-inspired methods, but we're not implementing this interface to not
  107. // have an unnecessary vtable.
  108. int width() const;
  109. int height() const;
  110. void SetPixel(int x, int y, uint8_t red, uint8_t green, uint8_t blue);
  111. void Clear();
  112. void Fill(uint8_t red, uint8_t green, uint8_t blue);
  113. private:
  114. static const struct HardwareMapping *hardware_mapping_;
  115. static RowAddressSetter *row_setter_;
  116. // This returns the gpio-bit for given color (one of 'R', 'G', 'B'). This is
  117. // returning the right value in case "led_sequence" is _not_ "RGB"
  118. static gpio_bits_t GetGpioFromLedSequence(char col, const char *led_sequence,
  119. gpio_bits_t default_r,
  120. gpio_bits_t default_g,
  121. gpio_bits_t default_b);
  122. void InitDefaultDesignator(int x, int y, const char *led_sequence,
  123. PixelDesignator *designator);
  124. inline void MapColors(uint8_t r, uint8_t g, uint8_t b,
  125. uint16_t *red, uint16_t *green, uint16_t *blue);
  126. const int rows_; // Number of rows. 16 or 32.
  127. const int parallel_; // Parallel rows of chains. 1 or 2.
  128. const int height_; // rows * parallel
  129. const int columns_; // Number of columns. Number of chained boards * 32.
  130. const int scan_mode_;
  131. const bool inverse_color_;
  132. uint8_t pwm_bits_; // PWM bits to display.
  133. bool do_luminance_correct_;
  134. uint8_t brightness_;
  135. const int double_rows_;
  136. const size_t buffer_size_;
  137. // The frame-buffer is organized in bitplanes.
  138. // Highest level (slowest to cycle through) are double rows.
  139. // For each double-row, we store pwm-bits columns of a bitplane.
  140. // Each bitplane-column is pre-filled IoBits, of which the colors are set.
  141. // Of course, that means that we store unrelated bits in the frame-buffer,
  142. // but it allows easy access in the critical section.
  143. gpio_bits_t *bitplane_buffer_;
  144. inline gpio_bits_t *ValueAt(int double_row, int column, int bit);
  145. PixelDesignatorMap **shared_mapper_; // Storage in RGBMatrix.
  146. };
  147. } // namespace internal
  148. } // namespace rgb_matrix
  149. #endif // RPI_RGBMATRIX_FRAMEBUFFER_INTERNAL_H