PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

189 line
4.5KB

  1. // Specific implementations for unbuffered mode.
  2. // This gets included from inside the template definition in ssd1351.h, which is crazy, but it's the only way I know to make this compile.
  3. MEMBER_REQUIRES(std::is_same<B, NoBuffer>::value)
  4. void drawPixel(int16_t x, int16_t y, const C &color) {
  5. // Drawing pixels directly to the display requires first setting the correct
  6. // video ram position, from x/y to x+1/y+1.
  7. if(x < 0 || x >= W || y < 0 || y >= H) {
  8. return;
  9. }
  10. beginSPITransaction();
  11. setVideoRamPosition(x, y, x+1, y+1);
  12. sendCommandAndContinue(CMD_WRITE_TO_RAM);
  13. pushColor(color, true);
  14. endSPITransaction();
  15. }
  16. MEMBER_REQUIRES(std::is_same<B, NoBuffer>::value)
  17. void updateScreen() {
  18. // An unbuffered display doesn't need to update its screen, but we want to
  19. // supply a common interface for all operational modes.
  20. }
  21. MEMBER_REQUIRES(std::is_same<B, NoBuffer>::value)
  22. void fillScreen(const C &color) {
  23. // Instead of drawing each pixel to the screen with the same color, we make
  24. // use of the fact that fillRect is optimized to only incur a single overhead
  25. // for addressing a cordinate on the display
  26. fillRect(0, 0, W, H, color);
  27. }
  28. MEMBER_REQUIRES(std::is_same<B, NoBuffer>::value)
  29. void drawFastVLine(int16_t x, int16_t y, int16_t h, const C &color) {
  30. // Setting the video ram on the display to only contain a single constrained
  31. // column of data allows us to write vertical lines super fast.
  32. // The x/y position is only set to the start, the display then takes care of
  33. // pointing to the next pixel after the first is written.
  34. if((x >= W) || (y >= H)) {
  35. return;
  36. }
  37. if((y + h - 1) >= H) {
  38. h = H - y;
  39. }
  40. beginSPITransaction();
  41. setVideoRamPosition(x, y, x, y + h - 1);
  42. sendCommandAndContinue(CMD_WRITE_TO_RAM);
  43. while (h-- > 1) {
  44. pushColor(color);
  45. }
  46. pushColor(color, true);
  47. endSPITransaction();
  48. }
  49. MEMBER_REQUIRES(std::is_same<B, NoBuffer>::value)
  50. void drawFastHLine(int16_t x, int16_t y, int16_t w, const C &color) {
  51. // Rudimentary clipping
  52. if((x >= W) || (y >= H)) {
  53. return;
  54. }
  55. if((x + w - 1) >= W) {
  56. w = W - x;
  57. }
  58. beginSPITransaction();
  59. setVideoRamPosition(x, y, x + w - 1, y);
  60. sendCommandAndContinue(CMD_WRITE_TO_RAM);
  61. while (w-- > 1) {
  62. pushColor(color);
  63. }
  64. pushColor(color, true);
  65. endSPITransaction();
  66. }
  67. MEMBER_REQUIRES(std::is_same<B, NoBuffer>::value)
  68. void fillRect(int16_t x, int16_t y, int16_t w, int16_t h, const C &color) {
  69. // rudimentary clipping (drawChar w/big text requires this)
  70. if((x >= W) || (y >= H)) {
  71. return;
  72. }
  73. if((x + w - 1) >= W) {
  74. w = W - x;
  75. }
  76. if((y + h - 1) >= H) {
  77. h = H - y;
  78. }
  79. beginSPITransaction();
  80. setVideoRamPosition(x, y, x + w - 1, y + h - 1);
  81. sendCommandAndContinue(CMD_WRITE_TO_RAM);
  82. for(y = h; y > 0; --y) {
  83. for(x = w; x > 1; --x) {
  84. pushColor(color);
  85. }
  86. pushColor(color, true);
  87. // At the end of every row, end the transaction to give other SPI devices a chance to communicate.
  88. endSPITransaction();
  89. // Start a new transaction, unless this is the last row
  90. if (y) {
  91. beginSPITransaction();
  92. }
  93. }
  94. }
  95. MEMBER_REQUIRES(std::is_same<B, NoBuffer>::value)
  96. void drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, const C &color) {
  97. // Bresenham's algorithm - thx wikpedia
  98. if (y0 == y1) {
  99. if (x1 > x0) {
  100. drawFastHLine(x0, y0, x1 - x0 + 1, color);
  101. } else if (x1 < x0) {
  102. drawFastHLine(x1, y0, x0 - x1 + 1, color);
  103. } else {
  104. drawPixel(x0, y0, color);
  105. }
  106. return;
  107. } else if (x0 == x1) {
  108. if (y1 > y0) {
  109. drawFastVLine(x0, y0, y1 - y0 + 1, color);
  110. } else {
  111. drawFastVLine(x0, y1, y0 - y1 + 1, color);
  112. }
  113. return;
  114. }
  115. bool steep = abs(y1 - y0) > abs(x1 - x0);
  116. if (steep) {
  117. swap(x0, y0);
  118. swap(x1, y1);
  119. }
  120. if (x0 > x1) {
  121. swap(x0, x1);
  122. swap(y0, y1);
  123. }
  124. int16_t dx, dy;
  125. dx = x1 - x0;
  126. dy = abs(y1 - y0);
  127. int16_t err = dx / 2;
  128. int16_t ystep;
  129. if (y0 < y1) {
  130. ystep = 1;
  131. } else {
  132. ystep = -1;
  133. }
  134. int16_t xbegin = x0;
  135. if (steep) {
  136. for (; x0<=x1; x0++) {
  137. err -= dy;
  138. if (err < 0) {
  139. int16_t len = x0 - xbegin;
  140. if (len) {
  141. drawFastVLine(y0, xbegin, len + 1, color);
  142. } else {
  143. drawPixel(y0, x0, color);
  144. }
  145. xbegin = x0 + 1;
  146. y0 += ystep;
  147. err += dx;
  148. }
  149. }
  150. if (x0 > xbegin + 1) {
  151. drawFastVLine(y0, xbegin, x0 - xbegin, color);
  152. }
  153. } else {
  154. for (; x0<=x1; x0++) {
  155. err -= dy;
  156. if (err < 0) {
  157. int16_t len = x0 - xbegin;
  158. if (len) {
  159. drawFastHLine(xbegin, y0, len + 1, color);
  160. } else {
  161. drawPixel(x0, y0, color);
  162. }
  163. xbegin = x0 + 1;
  164. y0 += ystep;
  165. err += dx;
  166. }
  167. }
  168. if (x0 > xbegin + 1) {
  169. drawFastHLine(xbegin, y0, x0 - xbegin, color);
  170. }
  171. }
  172. }