framebuffer.cc 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878
  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. // The framebuffer is the workhorse: it represents the frame in some internal
  16. // format that is friendly to be dumped to the matrix quickly. Provides methods
  17. // to manipulate the content.
  18. #include "framebuffer-internal.h"
  19. #include <assert.h>
  20. #include <ctype.h>
  21. #include <math.h>
  22. #include <stdint.h>
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include <algorithm>
  27. #include "gpio.h"
  28. namespace rgb_matrix {
  29. namespace internal {
  30. // We need one global instance of a timing correct pulser. There are different
  31. // implementations depending on the context.
  32. static PinPulser *sOutputEnablePulser = NULL;
  33. #ifdef ONLY_SINGLE_SUB_PANEL
  34. # define SUB_PANELS_ 1
  35. #else
  36. # define SUB_PANELS_ 2
  37. #endif
  38. PixelDesignator *PixelDesignatorMap::get(int x, int y) {
  39. if (x < 0 || y < 0 || x >= width_ || y >= height_)
  40. return NULL;
  41. return buffer_ + (y*width_) + x;
  42. }
  43. PixelDesignatorMap::PixelDesignatorMap(int width, int height,
  44. const PixelDesignator &fill_bits)
  45. : width_(width), height_(height), fill_bits_(fill_bits),
  46. buffer_(new PixelDesignator[width * height]) {
  47. }
  48. PixelDesignatorMap::~PixelDesignatorMap() {
  49. delete [] buffer_;
  50. }
  51. // Different panel types use different techniques to set the row address.
  52. // We abstract that away with different implementations of RowAddressSetter
  53. class RowAddressSetter {
  54. public:
  55. virtual ~RowAddressSetter() {}
  56. virtual gpio_bits_t need_bits() const = 0;
  57. virtual void SetRowAddress(GPIO *io, int row) = 0;
  58. };
  59. namespace {
  60. // The default DirectRowAddressSetter just sets the address in parallel
  61. // output lines ABCDE with A the LSB and E the MSB.
  62. class DirectRowAddressSetter : public RowAddressSetter {
  63. public:
  64. DirectRowAddressSetter(int double_rows, const HardwareMapping &h)
  65. : row_mask_(0), last_row_(-1) {
  66. assert(double_rows <= 32); // need to resize row_lookup_
  67. if (double_rows > 16) row_mask_ |= h.e;
  68. if (double_rows > 8) row_mask_ |= h.d;
  69. if (double_rows > 4) row_mask_ |= h.c;
  70. if (double_rows > 2) row_mask_ |= h.b;
  71. row_mask_ |= h.a;
  72. for (int i = 0; i < double_rows; ++i) {
  73. // To avoid the bit-fiddle in the critical path, utilize
  74. // a lookup-table for all possible rows.
  75. gpio_bits_t row_address = (i & 0x01) ? h.a : 0;
  76. row_address |= (i & 0x02) ? h.b : 0;
  77. row_address |= (i & 0x04) ? h.c : 0;
  78. row_address |= (i & 0x08) ? h.d : 0;
  79. row_address |= (i & 0x10) ? h.e : 0;
  80. row_lookup_[i] = row_address;
  81. }
  82. }
  83. virtual gpio_bits_t need_bits() const { return row_mask_; }
  84. virtual void SetRowAddress(GPIO *io, int row) {
  85. if (row == last_row_) return;
  86. io->WriteMaskedBits(row_lookup_[row], row_mask_);
  87. last_row_ = row;
  88. }
  89. private:
  90. gpio_bits_t row_mask_;
  91. gpio_bits_t row_lookup_[32];
  92. int last_row_;
  93. };
  94. // The SM5266RowAddressSetter (ABC Shifter + DE direct) sets bits ABC using
  95. // a 8 bit shifter and DE directly. The panel this works with has 8 SM5266
  96. // shifters (4 for the top 32 rows and 4 for the bottom 32 rows).
  97. // DE is used to select the active shifter
  98. // (rows 1-8/33-40, 9-16/41-48, 17-24/49-56, 25-32/57-64).
  99. // Rows are enabled by shifting in 8 bits (high bit first) with a high bit
  100. // enabling that row. This allows up to 8 rows per group to be active at the
  101. // same time (if they have the same content), but that isn't implemented here.
  102. // BK, DIN and DCK are the designations on the SM5266P datasheet.
  103. // BK = Enable Input, DIN = Serial In, DCK = Clock
  104. class SM5266RowAddressSetter : public RowAddressSetter {
  105. public:
  106. SM5266RowAddressSetter(int double_rows, const HardwareMapping &h)
  107. : row_mask_(h.a | h.b | h.c),
  108. last_row_(-1),
  109. bk_(h.c),
  110. din_(h.b),
  111. dck_(h.a) {
  112. assert(double_rows <= 32); // designed for up to 1/32 panel
  113. if (double_rows > 8) row_mask_ |= h.d;
  114. if (double_rows > 16) row_mask_ |= h.e;
  115. for (int i = 0; i < double_rows; ++i) {
  116. gpio_bits_t row_address = 0;
  117. row_address |= (i & 0x08) ? h.d : 0;
  118. row_address |= (i & 0x10) ? h.e : 0;
  119. row_lookup_[i] = row_address;
  120. }
  121. }
  122. virtual gpio_bits_t need_bits() const { return row_mask_; }
  123. virtual void SetRowAddress(GPIO *io, int row) {
  124. if (row == last_row_) return;
  125. io->SetBits(bk_); // Enable serial input for the shifter
  126. for (int r = 7; r >= 0; r--) {
  127. if (row % 8 == r) {
  128. io->SetBits(din_);
  129. } else {
  130. io->ClearBits(din_);
  131. }
  132. io->SetBits(dck_);
  133. io->SetBits(dck_); // Longer clock time; tested with Pi3
  134. io->ClearBits(dck_);
  135. }
  136. io->ClearBits(bk_); // Disable serial input to keep unwanted bits out of the shifters
  137. last_row_ = row;
  138. // Set bits D and E to enable the proper shifter to display the selected
  139. // row.
  140. io->WriteMaskedBits(row_lookup_[row], row_mask_);
  141. }
  142. private:
  143. gpio_bits_t row_mask_;
  144. int last_row_;
  145. const gpio_bits_t bk_;
  146. const gpio_bits_t din_;
  147. const gpio_bits_t dck_;
  148. gpio_bits_t row_lookup_[32];
  149. };
  150. class ShiftRegisterRowAddressSetter : public RowAddressSetter {
  151. public:
  152. ShiftRegisterRowAddressSetter(int double_rows, const HardwareMapping &h)
  153. : double_rows_(double_rows),
  154. row_mask_(h.a | h.b), clock_(h.a), data_(h.b),
  155. last_row_(-1) {
  156. }
  157. virtual gpio_bits_t need_bits() const { return row_mask_; }
  158. virtual void SetRowAddress(GPIO *io, int row) {
  159. if (row == last_row_) return;
  160. for (int activate = 0; activate < double_rows_; ++activate) {
  161. io->ClearBits(clock_);
  162. if (activate == double_rows_ - 1 - row) {
  163. io->ClearBits(data_);
  164. } else {
  165. io->SetBits(data_);
  166. }
  167. io->SetBits(clock_);
  168. }
  169. io->ClearBits(clock_);
  170. io->SetBits(clock_);
  171. last_row_ = row;
  172. }
  173. private:
  174. const int double_rows_;
  175. const gpio_bits_t row_mask_;
  176. const gpio_bits_t clock_;
  177. const gpio_bits_t data_;
  178. int last_row_;
  179. };
  180. // Issue #823
  181. // An shift register row address setter that does not use B but C for the
  182. // data. Clock is inverted.
  183. class ABCShiftRegisterRowAddressSetter : public RowAddressSetter {
  184. public:
  185. ABCShiftRegisterRowAddressSetter(int double_rows, const HardwareMapping &h)
  186. : double_rows_(double_rows),
  187. row_mask_(h.a | h.c),
  188. clock_(h.a),
  189. data_(h.c),
  190. last_row_(-1) {
  191. }
  192. virtual gpio_bits_t need_bits() const { return row_mask_; }
  193. virtual void SetRowAddress(GPIO *io, int row) {
  194. for (int activate = 0; activate < double_rows_; ++activate) {
  195. io->ClearBits(clock_);
  196. if (activate == double_rows_ - 1 - row) {
  197. io->SetBits(data_);
  198. } else {
  199. io->ClearBits(data_);
  200. }
  201. io->SetBits(clock_);
  202. }
  203. io->SetBits(clock_);
  204. io->ClearBits(clock_);
  205. last_row_ = row;
  206. }
  207. private:
  208. const int double_rows_;
  209. const gpio_bits_t row_mask_;
  210. const gpio_bits_t clock_;
  211. const gpio_bits_t data_;
  212. int last_row_;
  213. };
  214. // The DirectABCDRowAddressSetter sets the address by one of
  215. // row pin ABCD for 32х16 matrix 1:4 multiplexing. The matrix has
  216. // 4 addressable rows. Row is selected by a low level on the
  217. // corresponding row address pin. Other row address pins must be in high level.
  218. //
  219. // Row addr| 0 | 1 | 2 | 3
  220. // --------+---+---+---+---
  221. // Line A | 0 | 1 | 1 | 1
  222. // Line B | 1 | 0 | 1 | 1
  223. // Line C | 1 | 1 | 0 | 1
  224. // Line D | 1 | 1 | 1 | 0
  225. class DirectABCDLineRowAddressSetter : public RowAddressSetter {
  226. public:
  227. DirectABCDLineRowAddressSetter(int double_rows, const HardwareMapping &h)
  228. : last_row_(-1) {
  229. row_mask_ = h.a | h.b | h.c | h.d;
  230. row_lines_[0] = /*h.a |*/ h.b | h.c | h.d;
  231. row_lines_[1] = h.a /*| h.b*/ | h.c | h.d;
  232. row_lines_[2] = h.a | h.b /*| h.c */| h.d;
  233. row_lines_[3] = h.a | h.b | h.c /*| h.d*/;
  234. }
  235. virtual gpio_bits_t need_bits() const { return row_mask_; }
  236. virtual void SetRowAddress(GPIO *io, int row) {
  237. if (row == last_row_) return;
  238. gpio_bits_t row_address = row_lines_[row % 4];
  239. io->WriteMaskedBits(row_address, row_mask_);
  240. last_row_ = row;
  241. }
  242. private:
  243. gpio_bits_t row_lines_[4];
  244. gpio_bits_t row_mask_;
  245. int last_row_;
  246. };
  247. }
  248. const struct HardwareMapping *Framebuffer::hardware_mapping_ = NULL;
  249. RowAddressSetter *Framebuffer::row_setter_ = NULL;
  250. Framebuffer::Framebuffer(int rows, int columns, int parallel,
  251. int scan_mode,
  252. const char *led_sequence, bool inverse_color,
  253. PixelDesignatorMap **mapper)
  254. : rows_(rows),
  255. parallel_(parallel),
  256. height_(rows * parallel),
  257. columns_(columns),
  258. scan_mode_(scan_mode),
  259. inverse_color_(inverse_color),
  260. pwm_bits_(kBitPlanes), do_luminance_correct_(true), brightness_(100),
  261. double_rows_(rows / SUB_PANELS_),
  262. buffer_size_(double_rows_ * columns_ * kBitPlanes * sizeof(gpio_bits_t)),
  263. shared_mapper_(mapper) {
  264. assert(hardware_mapping_ != NULL); // Called InitHardwareMapping() ?
  265. assert(shared_mapper_ != NULL); // Storage should be provided by RGBMatrix.
  266. assert(rows_ >=4 && rows_ <= 64 && rows_ % 2 == 0);
  267. if (parallel > hardware_mapping_->max_parallel_chains) {
  268. fprintf(stderr, "The %s GPIO mapping only supports %d parallel chain%s, "
  269. "but %d was requested.\n", hardware_mapping_->name,
  270. hardware_mapping_->max_parallel_chains,
  271. hardware_mapping_->max_parallel_chains > 1 ? "s" : "", parallel);
  272. abort();
  273. }
  274. assert(parallel >= 1 && parallel <= 6);
  275. bitplane_buffer_ = new gpio_bits_t[double_rows_ * columns_ * kBitPlanes];
  276. // If we're the first Framebuffer created, the shared PixelMapper is
  277. // still NULL, so create one.
  278. // The first PixelMapper represents the physical layout of a standard matrix
  279. // with the specific knowledge of the framebuffer, setting up PixelDesignators
  280. // in a way that they are useful for this Framebuffer.
  281. //
  282. // Newly created PixelMappers then can just re-arrange PixelDesignators
  283. // from the parent PixelMapper opaquely without having to know the details.
  284. if (*shared_mapper_ == NULL) {
  285. // Gather all the bits for given color for fast Fill()s and use the right
  286. // bits according to the led sequence
  287. const struct HardwareMapping &h = *hardware_mapping_;
  288. gpio_bits_t r = h.p0_r1 | h.p0_r2 | h.p1_r1 | h.p1_r2 | h.p2_r1 | h.p2_r2 | h.p3_r1 | h.p3_r2 | h.p4_r1 | h.p4_r2 | h.p5_r1 | h.p5_r2;
  289. gpio_bits_t g = h.p0_g1 | h.p0_g2 | h.p1_g1 | h.p1_g2 | h.p2_g1 | h.p2_g2 | h.p3_g1 | h.p3_g2 | h.p4_g1 | h.p4_g2 | h.p5_g1 | h.p5_g2;
  290. gpio_bits_t b = h.p0_b1 | h.p0_b2 | h.p1_b1 | h.p1_b2 | h.p2_b1 | h.p2_b2 | h.p3_b1 | h.p3_b2 | h.p4_b1 | h.p4_b2 | h.p5_b1 | h.p5_b2;
  291. PixelDesignator fill_bits;
  292. fill_bits.r_bit = GetGpioFromLedSequence('R', led_sequence, r, g, b);
  293. fill_bits.g_bit = GetGpioFromLedSequence('G', led_sequence, r, g, b);
  294. fill_bits.b_bit = GetGpioFromLedSequence('B', led_sequence, r, g, b);
  295. *shared_mapper_ = new PixelDesignatorMap(columns_, height_, fill_bits);
  296. for (int y = 0; y < height_; ++y) {
  297. for (int x = 0; x < columns_; ++x) {
  298. InitDefaultDesignator(x, y, led_sequence, (*shared_mapper_)->get(x, y));
  299. }
  300. }
  301. }
  302. Clear();
  303. }
  304. Framebuffer::~Framebuffer() {
  305. delete [] bitplane_buffer_;
  306. }
  307. // TODO: this should also be parsed from some special formatted string, e.g.
  308. // {addr={22,23,24,25,15},oe=18,clk=17,strobe=4, p0={11,27,7,8,9,10},...}
  309. /* static */ void Framebuffer::InitHardwareMapping(const char *named_hardware) {
  310. if (named_hardware == NULL || *named_hardware == '\0') {
  311. named_hardware = "regular";
  312. }
  313. struct HardwareMapping *mapping = NULL;
  314. for (HardwareMapping *it = matrix_hardware_mappings; it->name; ++it) {
  315. if (strcasecmp(it->name, named_hardware) == 0) {
  316. mapping = it;
  317. break;
  318. }
  319. }
  320. if (!mapping) {
  321. fprintf(stderr, "There is no hardware mapping named '%s'.\nAvailable: ",
  322. named_hardware);
  323. for (HardwareMapping *it = matrix_hardware_mappings; it->name; ++it) {
  324. if (it != matrix_hardware_mappings) fprintf(stderr, ", ");
  325. fprintf(stderr, "'%s'", it->name);
  326. }
  327. fprintf(stderr, "\n");
  328. abort();
  329. }
  330. if (mapping->max_parallel_chains == 0) {
  331. // Auto determine.
  332. struct HardwareMapping *h = mapping;
  333. if ((h->p0_r1 | h->p0_g1 | h->p0_g1 | h->p0_r2 | h->p0_g2 | h->p0_g2) > 0)
  334. ++mapping->max_parallel_chains;
  335. if ((h->p1_r1 | h->p1_g1 | h->p1_g1 | h->p1_r2 | h->p1_g2 | h->p1_g2) > 0)
  336. ++mapping->max_parallel_chains;
  337. if ((h->p2_r1 | h->p2_g1 | h->p2_g1 | h->p2_r2 | h->p2_g2 | h->p2_g2) > 0)
  338. ++mapping->max_parallel_chains;
  339. if ((h->p3_r1 | h->p3_g1 | h->p3_g1 | h->p3_r2 | h->p3_g2 | h->p3_g2) > 0)
  340. ++mapping->max_parallel_chains;
  341. if ((h->p4_r1 | h->p4_g1 | h->p4_g1 | h->p4_r2 | h->p4_g2 | h->p4_g2) > 0)
  342. ++mapping->max_parallel_chains;
  343. if ((h->p5_r1 | h->p5_g1 | h->p5_g1 | h->p5_r2 | h->p5_g2 | h->p5_g2) > 0)
  344. ++mapping->max_parallel_chains;
  345. }
  346. hardware_mapping_ = mapping;
  347. }
  348. /* static */ void Framebuffer::InitGPIO(GPIO *io, int rows, int parallel,
  349. bool allow_hardware_pulsing,
  350. int pwm_lsb_nanoseconds,
  351. int dither_bits,
  352. int row_address_type) {
  353. if (sOutputEnablePulser != NULL)
  354. return; // already initialized.
  355. const struct HardwareMapping &h = *hardware_mapping_;
  356. // Tell GPIO about all bits we intend to use.
  357. gpio_bits_t all_used_bits = 0;
  358. all_used_bits |= h.output_enable | h.clock | h.strobe;
  359. all_used_bits |= h.p0_r1 | h.p0_g1 | h.p0_b1 | h.p0_r2 | h.p0_g2 | h.p0_b2;
  360. if (parallel >= 2) {
  361. all_used_bits |= h.p1_r1 | h.p1_g1 | h.p1_b1 | h.p1_r2 | h.p1_g2 | h.p1_b2;
  362. }
  363. if (parallel >= 3) {
  364. all_used_bits |= h.p2_r1 | h.p2_g1 | h.p2_b1 | h.p2_r2 | h.p2_g2 | h.p2_b2;
  365. }
  366. if (parallel >= 4) {
  367. all_used_bits |= h.p3_r1 | h.p3_g1 | h.p3_b1 | h.p3_r2 | h.p3_g2 | h.p3_b2;
  368. }
  369. if (parallel >= 5) {
  370. all_used_bits |= h.p4_r1 | h.p4_g1 | h.p4_b1 | h.p4_r2 | h.p4_g2 | h.p4_b2;
  371. }
  372. if (parallel >= 6) {
  373. all_used_bits |= h.p5_r1 | h.p5_g1 | h.p5_b1 | h.p5_r2 | h.p5_g2 | h.p5_b2;
  374. }
  375. const int double_rows = rows / SUB_PANELS_;
  376. switch (row_address_type) {
  377. case 0:
  378. row_setter_ = new DirectRowAddressSetter(double_rows, h);
  379. break;
  380. case 1:
  381. row_setter_ = new ShiftRegisterRowAddressSetter(double_rows, h);
  382. break;
  383. case 2:
  384. row_setter_ = new DirectABCDLineRowAddressSetter(double_rows, h);
  385. break;
  386. case 3:
  387. row_setter_ = new ABCShiftRegisterRowAddressSetter(double_rows, h);
  388. break;
  389. case 4:
  390. row_setter_ = new SM5266RowAddressSetter(double_rows, h);
  391. break;
  392. default:
  393. assert(0); // unexpected type.
  394. }
  395. all_used_bits |= row_setter_->need_bits();
  396. // Adafruit HAT identified by the same prefix.
  397. const bool is_some_adafruit_hat = (0 == strncmp(h.name, "adafruit-hat",
  398. strlen("adafruit-hat")));
  399. // Initialize outputs, make sure that all of these are supported bits.
  400. const gpio_bits_t result = io->InitOutputs(all_used_bits,
  401. is_some_adafruit_hat);
  402. assert(result == all_used_bits); // Impl: all bits declared in gpio.cc ?
  403. std::vector<int> bitplane_timings;
  404. uint32_t timing_ns = pwm_lsb_nanoseconds;
  405. for (int b = 0; b < kBitPlanes; ++b) {
  406. bitplane_timings.push_back(timing_ns);
  407. if (b >= dither_bits) timing_ns *= 2;
  408. }
  409. sOutputEnablePulser = PinPulser::Create(io, h.output_enable,
  410. allow_hardware_pulsing,
  411. bitplane_timings);
  412. }
  413. // NOTE: first version for panel initialization sequence, need to refine
  414. // until it is more clear how different panel types are initialized to be
  415. // able to abstract this more.
  416. static void InitFM6126(GPIO *io, const struct HardwareMapping &h, int columns) {
  417. const gpio_bits_t bits_on
  418. = h.p0_r1 | h.p0_g1 | h.p0_b1 | h.p0_r2 | h.p0_g2 | h.p0_b2
  419. | h.p1_r1 | h.p1_g1 | h.p1_b1 | h.p1_r2 | h.p1_g2 | h.p1_b2
  420. | h.p2_r1 | h.p2_g1 | h.p2_b1 | h.p2_r2 | h.p2_g2 | h.p2_b2
  421. | h.p3_r1 | h.p3_g1 | h.p3_b1 | h.p3_r2 | h.p3_g2 | h.p3_b2
  422. | h.p4_r1 | h.p4_g1 | h.p4_b1 | h.p4_r2 | h.p4_g2 | h.p4_b2
  423. | h.p5_r1 | h.p5_g1 | h.p5_b1 | h.p5_r2 | h.p5_g2 | h.p5_b2
  424. | h.a; // Address bit 'A' is always on.
  425. const gpio_bits_t bits_off = h.a;
  426. const gpio_bits_t mask = bits_on | h.strobe;
  427. // Init bits. TODO: customize, as we can do things such as brightness here,
  428. // which would allow more higher quality output.
  429. static const char* init_b12 = "0111111111111111"; // full bright
  430. static const char* init_b13 = "0000000001000000"; // panel on.
  431. io->ClearBits(h.clock | h.strobe);
  432. for (int i = 0; i < columns; ++i) {
  433. gpio_bits_t value = init_b12[i % 16] == '0' ? bits_off : bits_on;
  434. if (i > columns - 12) value |= h.strobe;
  435. io->WriteMaskedBits(value, mask);
  436. io->SetBits(h.clock);
  437. io->ClearBits(h.clock);
  438. }
  439. io->ClearBits(h.strobe);
  440. for (int i = 0; i < columns; ++i) {
  441. gpio_bits_t value = init_b13[i % 16] == '0' ? bits_off : bits_on;
  442. if (i > columns - 13) value |= h.strobe;
  443. io->WriteMaskedBits(value, mask);
  444. io->SetBits(h.clock);
  445. io->ClearBits(h.clock);
  446. }
  447. io->ClearBits(h.strobe);
  448. }
  449. // The FM6217 is very similar to the FM6216.
  450. // FM6217 adds Register 3 to allow for automatic bad pixel supression.
  451. static void InitFM6127(GPIO *io, const struct HardwareMapping &h, int columns) {
  452. const gpio_bits_t bits_r_on= h.p0_r1 | h.p0_r2;
  453. const gpio_bits_t bits_g_on= h.p0_g1 | h.p0_g2;
  454. const gpio_bits_t bits_b_on= h.p0_b1 | h.p0_b2;
  455. const gpio_bits_t bits_on= bits_r_on | bits_g_on | bits_b_on;
  456. const gpio_bits_t bits_off = 0;
  457. const gpio_bits_t mask = bits_on | h.strobe;
  458. static const char* init_b12 = "1111111111001110"; // register 1
  459. static const char* init_b13 = "1110000001100010"; // register 2.
  460. static const char* init_b11 = "0101111100000000"; // register 3.
  461. io->ClearBits(h.clock | h.strobe);
  462. for (int i = 0; i < columns; ++i) {
  463. gpio_bits_t value = init_b12[i % 16] == '0' ? bits_off : bits_on;
  464. if (i > columns - 12) value |= h.strobe;
  465. io->WriteMaskedBits(value, mask);
  466. io->SetBits(h.clock);
  467. io->ClearBits(h.clock);
  468. }
  469. io->ClearBits(h.strobe);
  470. for (int i = 0; i < columns; ++i) {
  471. gpio_bits_t value = init_b13[i % 16] == '0' ? bits_off : bits_on;
  472. if (i > columns - 13) value |= h.strobe;
  473. io->WriteMaskedBits(value, mask);
  474. io->SetBits(h.clock);
  475. io->ClearBits(h.clock);
  476. }
  477. io->ClearBits(h.strobe);
  478. for (int i = 0; i < columns; ++i) {
  479. gpio_bits_t value = init_b11[i % 16] == '0' ? bits_off : bits_on;
  480. if (i > columns - 11) value |= h.strobe;
  481. io->WriteMaskedBits(value, mask);
  482. io->SetBits(h.clock);
  483. io->ClearBits(h.clock);
  484. }
  485. io->ClearBits(h.strobe);
  486. }
  487. /*static*/ void Framebuffer::InitializePanels(GPIO *io,
  488. const char *panel_type,
  489. int columns) {
  490. if (!panel_type || panel_type[0] == '\0') return;
  491. if (strncasecmp(panel_type, "fm6126", 6) == 0) {
  492. InitFM6126(io, *hardware_mapping_, columns);
  493. }
  494. else if (strncasecmp(panel_type, "fm6127", 6) == 0) {
  495. InitFM6127(io, *hardware_mapping_, columns);
  496. }
  497. // else if (strncasecmp(...)) // more init types
  498. else {
  499. fprintf(stderr, "Unknown panel type '%s'; typo ?\n", panel_type);
  500. }
  501. }
  502. bool Framebuffer::SetPWMBits(uint8_t value) {
  503. if (value < 1 || value > kBitPlanes)
  504. return false;
  505. pwm_bits_ = value;
  506. return true;
  507. }
  508. inline gpio_bits_t *Framebuffer::ValueAt(int double_row, int column, int bit) {
  509. return &bitplane_buffer_[ double_row * (columns_ * kBitPlanes)
  510. + bit * columns_
  511. + column ];
  512. }
  513. void Framebuffer::Clear() {
  514. if (inverse_color_) {
  515. Fill(0, 0, 0);
  516. } else {
  517. // Cheaper.
  518. memset(bitplane_buffer_, 0,
  519. sizeof(*bitplane_buffer_) * double_rows_ * columns_ * kBitPlanes);
  520. }
  521. }
  522. // Do CIE1931 luminance correction and scale to output bitplanes
  523. static uint16_t luminance_cie1931(uint8_t c, uint8_t brightness) {
  524. float out_factor = ((1 << internal::Framebuffer::kBitPlanes) - 1);
  525. float v = (float) c * brightness / 255.0;
  526. return roundf(out_factor * ((v <= 8) ? v / 902.3 : pow((v + 16) / 116.0, 3)));
  527. }
  528. struct ColorLookup {
  529. uint16_t color[256];
  530. };
  531. static ColorLookup *CreateLuminanceCIE1931LookupTable() {
  532. ColorLookup *for_brightness = new ColorLookup[100];
  533. for (int c = 0; c < 256; ++c)
  534. for (int b = 0; b < 100; ++b)
  535. for_brightness[b].color[c] = luminance_cie1931(c, b + 1);
  536. return for_brightness;
  537. }
  538. static inline uint16_t CIEMapColor(uint8_t brightness, uint8_t c) {
  539. static ColorLookup *luminance_lookup = CreateLuminanceCIE1931LookupTable();
  540. return luminance_lookup[brightness - 1].color[c];
  541. }
  542. // Non luminance correction. TODO: consider getting rid of this.
  543. static inline uint16_t DirectMapColor(uint8_t brightness, uint8_t c) {
  544. // simple scale down the color value
  545. c = c * brightness / 100;
  546. // shift to be left aligned with top-most bits.
  547. constexpr int shift = internal::Framebuffer::kBitPlanes - 8;
  548. return (shift > 0) ? (c << shift) : (c >> -shift);
  549. }
  550. inline void Framebuffer::MapColors(
  551. uint8_t r, uint8_t g, uint8_t b,
  552. uint16_t *red, uint16_t *green, uint16_t *blue) {
  553. if (do_luminance_correct_) {
  554. *red = CIEMapColor(brightness_, r);
  555. *green = CIEMapColor(brightness_, g);
  556. *blue = CIEMapColor(brightness_, b);
  557. } else {
  558. *red = DirectMapColor(brightness_, r);
  559. *green = DirectMapColor(brightness_, g);
  560. *blue = DirectMapColor(brightness_, b);
  561. }
  562. if (inverse_color_) {
  563. *red = ~(*red);
  564. *green = ~(*green);
  565. *blue = ~(*blue);
  566. }
  567. }
  568. void Framebuffer::Fill(uint8_t r, uint8_t g, uint8_t b) {
  569. uint16_t red, green, blue;
  570. MapColors(r, g, b, &red, &green, &blue);
  571. const PixelDesignator &fill = (*shared_mapper_)->GetFillColorBits();
  572. for (int b = kBitPlanes - pwm_bits_; b < kBitPlanes; ++b) {
  573. uint16_t mask = 1 << b;
  574. gpio_bits_t plane_bits = 0;
  575. plane_bits |= ((red & mask) == mask) ? fill.r_bit : 0;
  576. plane_bits |= ((green & mask) == mask) ? fill.g_bit : 0;
  577. plane_bits |= ((blue & mask) == mask) ? fill.b_bit : 0;
  578. for (int row = 0; row < double_rows_; ++row) {
  579. gpio_bits_t *row_data = ValueAt(row, 0, b);
  580. for (int col = 0; col < columns_; ++col) {
  581. *row_data++ = plane_bits;
  582. }
  583. }
  584. }
  585. }
  586. int Framebuffer::width() const { return (*shared_mapper_)->width(); }
  587. int Framebuffer::height() const { return (*shared_mapper_)->height(); }
  588. void Framebuffer::SetPixel(int x, int y, uint8_t r, uint8_t g, uint8_t b) {
  589. const PixelDesignator *designator = (*shared_mapper_)->get(x, y);
  590. if (designator == NULL) return;
  591. const long pos = designator->gpio_word;
  592. if (pos < 0) return; // non-used pixel marker.
  593. uint16_t red, green, blue;
  594. MapColors(r, g, b, &red, &green, &blue);
  595. gpio_bits_t *bits = bitplane_buffer_ + pos;
  596. const int min_bit_plane = kBitPlanes - pwm_bits_;
  597. bits += (columns_ * min_bit_plane);
  598. const gpio_bits_t r_bits = designator->r_bit;
  599. const gpio_bits_t g_bits = designator->g_bit;
  600. const gpio_bits_t b_bits = designator->b_bit;
  601. const gpio_bits_t designator_mask = designator->mask;
  602. for (uint16_t mask = 1<<min_bit_plane; mask != 1<<kBitPlanes; mask <<=1 ) {
  603. gpio_bits_t color_bits = 0;
  604. if (red & mask) color_bits |= r_bits;
  605. if (green & mask) color_bits |= g_bits;
  606. if (blue & mask) color_bits |= b_bits;
  607. *bits = (*bits & designator_mask) | color_bits;
  608. bits += columns_;
  609. }
  610. }
  611. // Strange LED-mappings such as RBG or so are handled here.
  612. gpio_bits_t Framebuffer::GetGpioFromLedSequence(char col,
  613. const char *led_sequence,
  614. gpio_bits_t default_r,
  615. gpio_bits_t default_g,
  616. gpio_bits_t default_b) {
  617. const char *pos = strchr(led_sequence, col);
  618. if (pos == NULL) pos = strchr(led_sequence, tolower(col));
  619. if (pos == NULL) {
  620. fprintf(stderr, "LED sequence '%s' does not contain any '%c'.\n",
  621. led_sequence, col);
  622. abort();
  623. }
  624. switch (pos - led_sequence) {
  625. case 0: return default_r;
  626. case 1: return default_g;
  627. case 2: return default_b;
  628. }
  629. return default_r; // String too long, should've been caught earlier.
  630. }
  631. void Framebuffer::InitDefaultDesignator(int x, int y, const char *seq,
  632. PixelDesignator *d) {
  633. const struct HardwareMapping &h = *hardware_mapping_;
  634. gpio_bits_t *bits = ValueAt(y % double_rows_, x, 0);
  635. d->gpio_word = bits - bitplane_buffer_;
  636. d->r_bit = d->g_bit = d->b_bit = 0;
  637. if (y < rows_) {
  638. if (y < double_rows_) {
  639. d->r_bit = GetGpioFromLedSequence('R', seq, h.p0_r1, h.p0_g1, h.p0_b1);
  640. d->g_bit = GetGpioFromLedSequence('G', seq, h.p0_r1, h.p0_g1, h.p0_b1);
  641. d->b_bit = GetGpioFromLedSequence('B', seq, h.p0_r1, h.p0_g1, h.p0_b1);
  642. } else {
  643. d->r_bit = GetGpioFromLedSequence('R', seq, h.p0_r2, h.p0_g2, h.p0_b2);
  644. d->g_bit = GetGpioFromLedSequence('G', seq, h.p0_r2, h.p0_g2, h.p0_b2);
  645. d->b_bit = GetGpioFromLedSequence('B', seq, h.p0_r2, h.p0_g2, h.p0_b2);
  646. }
  647. }
  648. else if (y >= rows_ && y < 2 * rows_) {
  649. if (y - rows_ < double_rows_) {
  650. d->r_bit = GetGpioFromLedSequence('R', seq, h.p1_r1, h.p1_g1, h.p1_b1);
  651. d->g_bit = GetGpioFromLedSequence('G', seq, h.p1_r1, h.p1_g1, h.p1_b1);
  652. d->b_bit = GetGpioFromLedSequence('B', seq, h.p1_r1, h.p1_g1, h.p1_b1);
  653. } else {
  654. d->r_bit = GetGpioFromLedSequence('R', seq, h.p1_r2, h.p1_g2, h.p1_b2);
  655. d->g_bit = GetGpioFromLedSequence('G', seq, h.p1_r2, h.p1_g2, h.p1_b2);
  656. d->b_bit = GetGpioFromLedSequence('B', seq, h.p1_r2, h.p1_g2, h.p1_b2);
  657. }
  658. }
  659. else if (y >= 2*rows_ && y < 3 * rows_) {
  660. if (y - 2*rows_ < double_rows_) {
  661. d->r_bit = GetGpioFromLedSequence('R', seq, h.p2_r1, h.p2_g1, h.p2_b1);
  662. d->g_bit = GetGpioFromLedSequence('G', seq, h.p2_r1, h.p2_g1, h.p2_b1);
  663. d->b_bit = GetGpioFromLedSequence('B', seq, h.p2_r1, h.p2_g1, h.p2_b1);
  664. } else {
  665. d->r_bit = GetGpioFromLedSequence('R', seq, h.p2_r2, h.p2_g2, h.p2_b2);
  666. d->g_bit = GetGpioFromLedSequence('G', seq, h.p2_r2, h.p2_g2, h.p2_b2);
  667. d->b_bit = GetGpioFromLedSequence('B', seq, h.p2_r2, h.p2_g2, h.p2_b2);
  668. }
  669. }
  670. else if (y >= 3*rows_ && y < 4 * rows_) {
  671. if (y - 3*rows_ < double_rows_) {
  672. d->r_bit = GetGpioFromLedSequence('R', seq, h.p3_r1, h.p3_g1, h.p3_b1);
  673. d->g_bit = GetGpioFromLedSequence('G', seq, h.p3_r1, h.p3_g1, h.p3_b1);
  674. d->b_bit = GetGpioFromLedSequence('B', seq, h.p3_r1, h.p3_g1, h.p3_b1);
  675. } else {
  676. d->r_bit = GetGpioFromLedSequence('R', seq, h.p3_r2, h.p3_g2, h.p3_b2);
  677. d->g_bit = GetGpioFromLedSequence('G', seq, h.p3_r2, h.p3_g2, h.p3_b2);
  678. d->b_bit = GetGpioFromLedSequence('B', seq, h.p3_r2, h.p3_g2, h.p3_b2);
  679. }
  680. }
  681. else if (y >= 4*rows_ && y < 5 * rows_){
  682. if (y - 4*rows_ < double_rows_) {
  683. d->r_bit = GetGpioFromLedSequence('R', seq, h.p4_r1, h.p4_g1, h.p4_b1);
  684. d->g_bit = GetGpioFromLedSequence('G', seq, h.p4_r1, h.p4_g1, h.p4_b1);
  685. d->b_bit = GetGpioFromLedSequence('B', seq, h.p4_r1, h.p4_g1, h.p4_b1);
  686. } else {
  687. d->r_bit = GetGpioFromLedSequence('R', seq, h.p4_r2, h.p4_g2, h.p4_b2);
  688. d->g_bit = GetGpioFromLedSequence('G', seq, h.p4_r2, h.p4_g2, h.p4_b2);
  689. d->b_bit = GetGpioFromLedSequence('B', seq, h.p4_r2, h.p4_g2, h.p4_b2);
  690. }
  691. }
  692. else {
  693. if (y - 5*rows_ < double_rows_) {
  694. d->r_bit = GetGpioFromLedSequence('R', seq, h.p5_r1, h.p5_g1, h.p5_b1);
  695. d->g_bit = GetGpioFromLedSequence('G', seq, h.p5_r1, h.p5_g1, h.p5_b1);
  696. d->b_bit = GetGpioFromLedSequence('B', seq, h.p5_r1, h.p5_g1, h.p5_b1);
  697. } else {
  698. d->r_bit = GetGpioFromLedSequence('R', seq, h.p5_r2, h.p5_g2, h.p5_b2);
  699. d->g_bit = GetGpioFromLedSequence('G', seq, h.p5_r2, h.p5_g2, h.p5_b2);
  700. d->b_bit = GetGpioFromLedSequence('B', seq, h.p5_r2, h.p5_g2, h.p5_b2);
  701. }
  702. }
  703. d->mask = ~(d->r_bit | d->g_bit | d->b_bit);
  704. }
  705. void Framebuffer::Serialize(const char **data, size_t *len) const {
  706. *data = reinterpret_cast<const char*>(bitplane_buffer_);
  707. *len = buffer_size_;
  708. }
  709. bool Framebuffer::Deserialize(const char *data, size_t len) {
  710. if (len != buffer_size_) return false;
  711. memcpy(bitplane_buffer_, data, len);
  712. return true;
  713. }
  714. void Framebuffer::CopyFrom(const Framebuffer *other) {
  715. if (other == this) return;
  716. memcpy(bitplane_buffer_, other->bitplane_buffer_, buffer_size_);
  717. }
  718. void Framebuffer::DumpToMatrix(GPIO *io, int pwm_low_bit) {
  719. const struct HardwareMapping &h = *hardware_mapping_;
  720. gpio_bits_t color_clk_mask = 0; // Mask of bits while clocking in.
  721. color_clk_mask |= h.p0_r1 | h.p0_g1 | h.p0_b1 | h.p0_r2 | h.p0_g2 | h.p0_b2;
  722. if (parallel_ >= 2) {
  723. color_clk_mask |= h.p1_r1 | h.p1_g1 | h.p1_b1 | h.p1_r2 | h.p1_g2 | h.p1_b2;
  724. }
  725. if (parallel_ >= 3) {
  726. color_clk_mask |= h.p2_r1 | h.p2_g1 | h.p2_b1 | h.p2_r2 | h.p2_g2 | h.p2_b2;
  727. }
  728. if (parallel_ >= 4) {
  729. color_clk_mask |= h.p3_r1 | h.p3_g1 | h.p3_b1 | h.p3_r2 | h.p3_g2 | h.p3_b2;
  730. }
  731. if (parallel_ >= 5) {
  732. color_clk_mask |= h.p4_r1 | h.p4_g1 | h.p4_b1 | h.p4_r2 | h.p4_g2 | h.p4_b2;
  733. }
  734. if (parallel_ >= 6) {
  735. color_clk_mask |= h.p5_r1 | h.p5_g1 | h.p5_b1 | h.p5_r2 | h.p5_g2 | h.p5_b2;
  736. }
  737. color_clk_mask |= h.clock;
  738. // Depending if we do dithering, we might not always show the lowest bits.
  739. const int start_bit = std::max(pwm_low_bit, kBitPlanes - pwm_bits_);
  740. const uint8_t half_double = double_rows_/2;
  741. for (uint8_t row_loop = 0; row_loop < double_rows_; ++row_loop) {
  742. uint8_t d_row;
  743. switch (scan_mode_) {
  744. case 0: // progressive
  745. default:
  746. d_row = row_loop;
  747. break;
  748. case 1: // interlaced
  749. d_row = ((row_loop < half_double)
  750. ? (row_loop << 1)
  751. : ((row_loop - half_double) << 1) + 1);
  752. }
  753. // Rows can't be switched very quickly without ghosting, so we do the
  754. // full PWM of one row before switching rows.
  755. for (int b = start_bit; b < kBitPlanes; ++b) {
  756. gpio_bits_t *row_data = ValueAt(d_row, 0, b);
  757. // While the output enable is still on, we can already clock in the next
  758. // data.
  759. for (int col = 0; col < columns_; ++col) {
  760. const gpio_bits_t &out = *row_data++;
  761. io->WriteMaskedBits(out, color_clk_mask); // col + reset clock
  762. io->SetBits(h.clock); // Rising edge: clock color in.
  763. }
  764. io->ClearBits(color_clk_mask); // clock back to normal.
  765. // OE of the previous row-data must be finished before strobe.
  766. sOutputEnablePulser->WaitPulseFinished();
  767. // Setting address and strobing needs to happen in dark time.
  768. row_setter_->SetRowAddress(io, d_row);
  769. io->SetBits(h.strobe); // Strobe in the previously clocked in row.
  770. io->ClearBits(h.strobe);
  771. // Now switch on for the sleep time necessary for that bit-plane.
  772. sOutputEnablePulser->SendPulse(b);
  773. }
  774. }
  775. }
  776. } // namespace internal
  777. } // namespace rgb_matrix