micro_oled.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691
  1. /* Jim Lindblom @ SparkFun Electronics
  2. * October 26, 2014
  3. * https://github.com/sparkfun/Micro_OLED_Breakout/tree/master/Firmware/Arduino/libraries/SFE_MicroOLED
  4. *
  5. * Modified by:
  6. * Emil Varughese @ Edwin Robotics Pvt. Ltd.
  7. * July 27, 2015
  8. * https://github.com/emil01/SparkFun_Micro_OLED_Arduino_Library/
  9. *
  10. * This code was heavily based around the MicroView library, written by GeekAmmo
  11. * (https://github.com/geekammo/MicroView-Arduino-Library).
  12. *
  13. * Adapted for QMK by:
  14. * Jack Humbert <jack.humb@gmail.com>
  15. * October 11, 2018
  16. *
  17. * This program is free software: you can redistribute it and/or modify
  18. * it under the terms of the GNU General Public License as published by
  19. * the Free Software Foundation, either version 3 of the License, or
  20. * (at your option) any later version.
  21. *
  22. * This program is distributed in the hope that it will be useful,
  23. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  24. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  25. * GNU General Public License for more details.
  26. *
  27. * You should have received a copy of the GNU General Public License
  28. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  29. */
  30. #include "micro_oled.h"
  31. #include <print.h>
  32. #include <stdlib.h>
  33. #include "util/font5x7.h"
  34. #include "util/font8x16.h"
  35. #include "string.h"
  36. #define TOTALFONTS 2
  37. const unsigned char * fonts_pointer[]= { font5x7, font8x16 };
  38. uint8_t foreColor,drawMode,fontWidth, fontHeight, fontType, fontStartChar, fontTotalChar, cursorX, cursorY;
  39. uint16_t fontMapWidth;
  40. #define _BV(x) (1 << (x))
  41. #define swap(a, b) { uint8_t t = a; a = b; b = t; }
  42. uint8_t micro_oled_transfer_buffer[20];
  43. static uint8_t micro_oled_screen_current[LCDWIDTH*LCDWIDTH/8] = { 0 };
  44. /* LCD Memory organised in 64 horizontal pixel and 6 rows of byte
  45. B B .............B -----
  46. y y .............y \
  47. t t .............t \
  48. e e .............e \
  49. 0 1 .............63 \
  50. \
  51. D0 D0.............D0 \
  52. D1 D1.............D1 / ROW 0
  53. D2 D2.............D2 /
  54. D3 D3.............D3 /
  55. D4 D4.............D4 /
  56. D5 D5.............D5 /
  57. D6 D6.............D6 /
  58. D7 D7.............D7 ----
  59. */
  60. #if LCDWIDTH == 64
  61. #if LCDWIDTH == 48
  62. static uint8_t micro_oled_screen_buffer[] = {
  63. // QMK Logo - generated at http://www.majer.ch/lcd/adf_bitmap.php
  64. //64x48 image
  65. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  66. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  67. 0x00, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0x00, 0x00,
  68. 0x00, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0x00, 0x00,
  69. 0x00, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  70. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  71. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  72. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x60, 0x60, 0x60,
  73. 0xF8, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0x1F, 0x1F, 0xFF, 0xFF,
  74. 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x1F, 0xFF, 0xFF, 0xFF,
  75. 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x1F, 0xFF, 0xFF, 0xFF, 0xFE,
  76. 0xFE, 0xF8, 0x60, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00,
  77. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  78. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  79. 0x8C, 0x8C, 0x8C, 0x8C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  80. 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
  81. 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
  82. 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8C, 0x8C, 0x8C, 0x8C,
  83. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  84. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  85. 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x31, 0x31, 0xFF, 0xFF,
  86. 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xF8, 0xF1, 0xE3, 0xE7, 0xCF,
  87. 0xCF, 0xCF, 0xCF, 0x00, 0x00, 0xCF, 0xCF, 0xCF, 0xC7, 0xE7,
  88. 0xE3, 0xF1, 0xF8, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  89. 0x31, 0x31, 0x31, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  90. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  91. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06,
  92. 0x06, 0x06, 0x1F, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  93. 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0xF8, 0xFF,
  94. 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  95. 0xFF, 0x7F, 0x7F, 0x1F, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00,
  96. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  97. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  98. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  99. 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00,
  100. 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00,
  101. 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  102. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  103. 0x00, 0x00, 0x00, 0x00
  104. };
  105. #endif
  106. #elif LCDWIDTH == 128
  107. #if LCDHEIGHT == 32
  108. static uint8_t micro_oled_screen_buffer[LCDWIDTH*LCDWIDTH/8] = {
  109. //128x32 qmk image
  110. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  111. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  112. 0x00, 0x80, 0xC0, 0xE0, 0xE0, 0xFC, 0xFC, 0xE0, 0xFC, 0xFC,
  113. 0xE0, 0xF0, 0xFC, 0xE0, 0xE0, 0xFC, 0xE0, 0xE0, 0xFC, 0xFC,
  114. 0xE0, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  115. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  116. 0x00, 0x00, 0x00, 0xF0, 0x10, 0x10, 0x30, 0xE0, 0x00, 0x00,
  117. 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00,
  118. 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x80,
  119. 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00,
  120. 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80,
  121. 0x80, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  122. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  123. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  124. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0xB2, 0xB2, 0xFF,
  125. 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x03, 0xFF, 0xFF, 0xFF, 0x03,
  126. 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x03, 0xFF, 0xFF, 0xFF,
  127. 0xFF, 0xB7, 0xB2, 0xB2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  128. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  129. 0x00, 0x1F, 0x02, 0x02, 0x03, 0x01, 0x00, 0x06, 0x1F, 0x10,
  130. 0x10, 0x10, 0x1F, 0x06, 0x00, 0x03, 0x1E, 0x18, 0x0F, 0x01,
  131. 0x0F, 0x18, 0x1E, 0x01, 0x00, 0x0F, 0x1F, 0x12, 0x02, 0x12,
  132. 0x13, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x0E, 0x1F, 0x12,
  133. 0x02, 0x12, 0x13, 0x00, 0x00, 0x1F, 0x10, 0x10, 0x10, 0x1F,
  134. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  135. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  136. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  137. 0x00, 0x00, 0x00, 0x00, 0x48, 0x4D, 0x4D, 0xFF, 0xFF, 0xFF,
  138. 0xFF, 0xFF, 0xFE, 0xF8, 0xF9, 0xF3, 0xF3, 0xC0, 0x80, 0xF3,
  139. 0xF3, 0xF3, 0xF9, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xED,
  140. 0x4D, 0x4D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  141. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  142. 0x00, 0xFE, 0x20, 0x10, 0x10, 0xE0, 0xC0, 0x00, 0x70, 0xC0,
  143. 0x00, 0x80, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x0C,
  144. 0x04, 0x04, 0x04, 0x04, 0x1C, 0xF0, 0x00, 0x00, 0xFC, 0x0C,
  145. 0x38, 0xE0, 0x00, 0x00, 0xC0, 0x38, 0x0C, 0xFC, 0x00, 0x00,
  146. 0xFC, 0xFC, 0x60, 0x90, 0x0C, 0x04, 0x00, 0x00, 0x00, 0x00,
  147. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  148. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  149. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  150. 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x07, 0x3F,
  151. 0x3F, 0x07, 0x3F, 0x3F, 0x07, 0x0F, 0x3F, 0x07, 0x07, 0x3F,
  152. 0x07, 0x07, 0x3F, 0x3F, 0x07, 0x07, 0x03, 0x00, 0x00, 0x00,
  153. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  154. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
  155. 0x06, 0x04, 0x04, 0x07, 0x01, 0x00, 0x00, 0x13, 0x1E, 0x03,
  156. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x06, 0x04, 0x04,
  157. 0x04, 0x04, 0x07, 0x0D, 0x08, 0x00, 0x07, 0x00, 0x00, 0x01,
  158. 0x07, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x07,
  159. 0x00, 0x01, 0x03, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  160. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  161. 0x00, 0x00
  162. };
  163. #elif LCDHEIGHT == 64
  164. static uint8_t micro_oled_screen_buffer[LCDWIDTH*LCDWIDTH/8] = {
  165. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  166. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  167. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  168. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  169. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  170. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  171. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  172. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0,
  173. 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00,
  174. 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00,
  175. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  176. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  177. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  178. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  179. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  180. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  181. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  182. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  183. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  184. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  185. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  186. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  187. 0xC0, 0xC0, 0xC0, 0xC0, 0xF8, 0xFC, 0xFC, 0xFE, 0xFE, 0xFF,
  188. 0x7F, 0x7E, 0xFE, 0xFF, 0xFF, 0xFE, 0xFE, 0x7F, 0x7F, 0xFE,
  189. 0xFE, 0xFF, 0xFF, 0xFE, 0x7E, 0x7F, 0xFF, 0xFE, 0xFE, 0xFC,
  190. 0xFC, 0xF8, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00,
  191. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  192. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  193. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  194. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  195. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  196. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  197. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  198. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  199. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  200. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  201. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  202. 0x00, 0x88, 0x88, 0x88, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  203. 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
  204. 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF,
  205. 0xFF, 0xFF, 0xFF, 0xDD, 0x88, 0x88, 0x88, 0x00, 0x00, 0x00,
  206. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  207. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  208. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  209. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  210. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  211. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  212. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  213. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  214. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  215. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  216. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  217. 0x00, 0x00, 0x99, 0x99, 0x99, 0x99, 0xFF, 0xFF, 0xFF, 0xFF,
  218. 0xFF, 0xFF, 0xFE, 0xF8, 0xF0, 0xF3, 0xF3, 0xE7, 0xE7, 0x00,
  219. 0x00, 0xE7, 0xE7, 0xF3, 0xF3, 0xF0, 0xF8, 0xFE, 0xFF, 0xFF,
  220. 0xFF, 0xFF, 0xFF, 0xFF, 0x99, 0x99, 0x99, 0x99, 0x00, 0x00,
  221. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  222. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  223. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  224. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  225. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  226. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  227. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  228. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  229. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  230. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  231. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  232. 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x0F, 0x1F, 0x3F,
  233. 0x3F, 0x3F, 0xFF, 0xFF, 0x3F, 0x3F, 0xFF, 0xFF, 0x3F, 0x3F,
  234. 0xFF, 0xFF, 0x3F, 0x3F, 0xFF, 0xFF, 0x3F, 0x3F, 0xFF, 0xFF,
  235. 0x3F, 0x3F, 0x3F, 0x1F, 0x0F, 0x01, 0x01, 0x01, 0x01, 0x00,
  236. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  237. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  238. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  239. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  240. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  241. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  242. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  243. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  244. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  245. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  246. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  247. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  248. 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x03, 0x01, 0x00,
  249. 0x80, 0x03, 0x03, 0x00, 0x00, 0x01, 0x03, 0x00, 0x80, 0x01,
  250. 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  251. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  252. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  253. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  254. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  255. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  256. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  257. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  258. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  259. 0x00, 0x00, 0x00, 0xFF, 0x11, 0x11, 0x11, 0x0E, 0x00, 0x70,
  260. 0x88, 0x04, 0x04, 0x04, 0xF8, 0x00, 0x00, 0x3C, 0xE0, 0xC0,
  261. 0x38, 0x1C, 0xE0, 0x80, 0x70, 0x0C, 0x00, 0xF8, 0xAC, 0x24,
  262. 0x24, 0x3C, 0x30, 0x00, 0x00, 0xFC, 0x0C, 0x04, 0x00, 0xF8,
  263. 0xAC, 0x24, 0x24, 0x2C, 0x30, 0x00, 0x70, 0xDC, 0x04, 0x04,
  264. 0x88, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
  265. 0x8C, 0x04, 0x04, 0xF8, 0x00, 0x04, 0x3C, 0xE0, 0x80, 0xF0,
  266. 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x83, 0x01, 0x01,
  267. 0x01, 0x81, 0xFE, 0x3C, 0x00, 0x00, 0xFF, 0x03, 0x0E, 0x70,
  268. 0xC0, 0xE0, 0x38, 0x06, 0x03, 0xFF, 0x00, 0x00, 0xFF, 0x18,
  269. 0x38, 0x66, 0xC3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  270. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  271. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  272. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  273. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  274. 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
  275. 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01,
  276. 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01,
  277. 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
  278. 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01,
  279. 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  280. 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03,
  281. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
  282. 0x01, 0x01, 0x01, 0x01, 0x03, 0x02, 0x00, 0x01, 0x00, 0x00,
  283. 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01,
  284. 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
  285. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  286. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  287. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  288. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  289. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  290. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  291. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  292. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  293. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  294. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  295. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  296. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  297. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  298. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  299. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  300. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  301. };
  302. //TODO: generate bitmap of QMK logo here
  303. #endif
  304. #else
  305. //catchall for custom screen szies
  306. static uint8_t micro_oled_screen_buffer[LCDWIDTH*LCDWIDTH/8] = {0};
  307. #endif
  308. void micro_oled_init(void) {
  309. i2c_init();
  310. i2c_start(I2C_ADDRESS_SA0_1);
  311. // Display Init sequence for 64x48 OLED module
  312. send_command(DISPLAYOFF); // 0xAE
  313. send_command(SETDISPLAYCLOCKDIV); // 0xD5
  314. send_command(0x80); // the suggested ratio 0x80
  315. send_command(SETMULTIPLEX); // 0xA8
  316. send_command(LCDHEIGHT - 1);
  317. send_command(SETDISPLAYOFFSET); // 0xD3
  318. send_command(0x00); // no offset
  319. send_command(SETSTARTLINE | 0x00); // line #0
  320. send_command(CHARGEPUMP); // enable charge pump
  321. send_command(0x14);
  322. send_command(NORMALDISPLAY); // 0xA6
  323. send_command(DISPLAYALLONRESUME); // 0xA4
  324. //display at regular orientation
  325. send_command(SEGREMAP | 0x1);
  326. send_command(COMSCANDEC);
  327. //rotate display 180
  328. #ifdef micro_oled_rotate_180
  329. send_command(SEGREMAP);
  330. send_command(COMSCANINC);
  331. #endif
  332. send_command(MEMORYMODE);
  333. send_command(0x10);
  334. send_command(SETCOMPINS); // 0xDA
  335. if (LCDHEIGHT > 32) {
  336. send_command(0x12);
  337. } else {
  338. send_command(0x02);
  339. }
  340. send_command(SETCONTRAST); // 0x81
  341. send_command(0x8F);
  342. send_command(SETPRECHARGE); // 0xd9
  343. send_command(0xF1);
  344. send_command(SETVCOMDESELECT); // 0xDB
  345. send_command(0x40);
  346. send_command(DISPLAYON); //--turn on oled panel
  347. clear_screen(); // Erase hardware memory inside the OLED controller to avoid random data in memory.
  348. send_buffer();
  349. }
  350. void send_command(uint8_t command) {
  351. micro_oled_transfer_buffer[0] = I2C_COMMAND;
  352. micro_oled_transfer_buffer[1] = command;
  353. i2c_transmit(I2C_ADDRESS_SA0_1 << 1, micro_oled_transfer_buffer, 2, 100);
  354. }
  355. void send_data(uint8_t data) {
  356. micro_oled_transfer_buffer[0] = I2C_DATA;
  357. micro_oled_transfer_buffer[1] = data;
  358. i2c_transmit(I2C_ADDRESS_SA0_1 << 1, micro_oled_transfer_buffer, 2, 100);
  359. }
  360. /** \brief Set SSD1306 page address.
  361. Send page address command and address to the SSD1306 OLED controller.
  362. */
  363. void set_page_address(uint8_t address) {
  364. address = (0xB0 | address);
  365. send_command(address);
  366. }
  367. /** \brief Set SSD1306 column address.
  368. Send column address command and address to the SSD1306 OLED controller.
  369. */
  370. void set_column_address(uint8_t address) {
  371. send_command( ( 0x10 | (address >> 4) ) + ((128 - LCDWIDTH) >> 8) );
  372. send_command( 0x0F & address );
  373. }
  374. /** \brief Clear SSD1306's memory.
  375. To clear GDRAM inside the LCD controller.
  376. */
  377. void clear_screen(void) {
  378. for (int i=0;i<8; i++) {
  379. set_page_address(i);
  380. set_column_address(0);
  381. for (int j=0; j<0x80; j++) {
  382. send_data(0);
  383. }
  384. }
  385. }
  386. /** \brief Clear SSD1306's memory.
  387. To clear GDRAM inside the LCD controller.
  388. */
  389. void clear_buffer(void) {
  390. //384
  391. memset(micro_oled_screen_buffer, 0, LCDWIDTH*LCDWIDTH/8);
  392. }
  393. /** \brief Invert display.
  394. The PIXEL_ON color of the display will turn to PIXEL_OFF and the PIXEL_OFF will turn to PIXEL_ON.
  395. */
  396. void invert_screen(bool invert) {
  397. if (invert) {
  398. send_command(INVERTDISPLAY);
  399. } else {
  400. send_command(NORMALDISPLAY);
  401. }
  402. }
  403. /** \brief Set contrast.
  404. OLED contract value from 0 to 255. Note: Contrast level is not very obvious.
  405. */
  406. void set_contrast(uint8_t contrast) {
  407. send_command(SETCONTRAST); // 0x81
  408. send_command(contrast);
  409. }
  410. /** \brief Transfer display buffer.
  411. Sends the updated buffer to the controller - the current status is checked before to save i2c exectution time
  412. */
  413. void send_buffer(void) {
  414. uint8_t i, j;
  415. uint8_t page_addr = 0xFF;
  416. for (i = 0; i < LCDHEIGHT/8; i++) {
  417. uint8_t col_addr = 0xFF;
  418. for (j = 0; j < LCDWIDTH; j++) {
  419. if (micro_oled_screen_buffer[i*LCDWIDTH+j] != micro_oled_screen_current[i*LCDWIDTH+j]) {
  420. if (page_addr != i) {
  421. set_page_address(i);
  422. }
  423. if (col_addr != j) {
  424. set_column_address(j);
  425. }
  426. send_data(micro_oled_screen_buffer[i*LCDWIDTH+j]);
  427. micro_oled_screen_current[i*LCDWIDTH+j] = micro_oled_screen_buffer[i*LCDWIDTH+j];
  428. col_addr = j + 1;
  429. }
  430. }
  431. }
  432. }
  433. /** \brief Draw pixel with color and mode.
  434. Draw color pixel in the screen buffer's x,y position with NORM or XOR draw mode.
  435. */
  436. void draw_pixel(uint8_t x, uint8_t y, uint8_t color, uint8_t mode) {
  437. if ((x<0) || (x>=LCDWIDTH) || (y<0) || (y>=LCDHEIGHT))
  438. return;
  439. if (mode == XOR) {
  440. if (color == PIXEL_ON)
  441. micro_oled_screen_buffer[x + (y/8)*LCDWIDTH] ^= _BV((y%8));
  442. } else {
  443. if (color == PIXEL_ON)
  444. micro_oled_screen_buffer[x + (y/8)*LCDWIDTH] |= _BV((y%8));
  445. else
  446. micro_oled_screen_buffer[x + (y/8)*LCDWIDTH] &= ~_BV((y%8));
  447. }
  448. }
  449. /** \brief Draw line with color and mode.
  450. Draw line using color and mode from x0,y0 to x1,y1 of the screen buffer.
  451. */
  452. void draw_line(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t color, uint8_t mode) {
  453. uint8_t steep = abs(y1 - y0) > abs(x1 - x0);
  454. if (steep) {
  455. swap(x0, y0);
  456. swap(x1, y1);
  457. }
  458. if (x0 > x1) {
  459. swap(x0, x1);
  460. swap(y0, y1);
  461. }
  462. uint8_t dx, dy;
  463. dx = x1 - x0;
  464. dy = abs(y1 - y0);
  465. int8_t err = dx / 2;
  466. int8_t ystep;
  467. if (y0 < y1) {
  468. ystep = 1;
  469. } else {
  470. ystep = -1;}
  471. for (; x0<x1; x0++) {
  472. if (steep) {
  473. draw_pixel(y0, x0, color, mode);
  474. } else {
  475. draw_pixel(x0, y0, color, mode);
  476. }
  477. err -= dy;
  478. if (err < 0) {
  479. y0 += ystep;
  480. err += dx;
  481. }
  482. }
  483. }
  484. /** \brief Draw horizontal line with color and mode.
  485. Draw horizontal line using color and mode from x,y to x+width,y of the screen buffer.
  486. */
  487. void draw_line_hori(uint8_t x, uint8_t y, uint8_t width, uint8_t color, uint8_t mode) {
  488. draw_line(x,y,x+width,y,color,mode);
  489. }
  490. /** \brief Draw vertical line.
  491. Draw vertical line using current fore color and current draw mode from x,y to x,y+height of the screen buffer.
  492. */
  493. void draw_line_vert(uint8_t x, uint8_t y, uint8_t height, bool color, uint8_t mode) {
  494. draw_line(x,y,x,y+height,color,mode);
  495. }
  496. /** \brief Draw rectangle with color and mode.
  497. Draw rectangle using color and mode from x,y to x+width,y+height of the screen buffer.
  498. */
  499. void draw_rect(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t color, uint8_t mode) {
  500. uint8_t tempHeight;
  501. draw_line_hori(x,y, width, color, mode);
  502. draw_line_hori(x,y+height-1, width, color, mode);
  503. tempHeight=height-2;
  504. // skip drawing vertical lines to avoid overlapping of pixel that will
  505. // affect XOR plot if no pixel in between horizontal lines
  506. if (tempHeight<1) return;
  507. draw_line_vert(x,y+1, tempHeight, color, mode);
  508. draw_line_vert(x+width-1, y+1, tempHeight, color, mode);
  509. }
  510. /** \brief Draw rectangle with color and mode.
  511. Draw rectangle using color and mode from x,y to x+width,y+height of the screen buffer.
  512. */
  513. void draw_rect_soft(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t color, uint8_t mode) {
  514. uint8_t tempHeight;
  515. draw_line_hori(x+1,y, width-2, color, mode);
  516. draw_line_hori(x+1,y+height-1, width-2, color, mode);
  517. tempHeight=height-2;
  518. // skip drawing vertical lines to avoid overlapping of pixel that will
  519. // affect XOR plot if no pixel in between horizontal lines
  520. if (tempHeight<1) return;
  521. draw_line_vert(x,y+1, tempHeight, color, mode);
  522. draw_line_vert(x+width-1, y+1, tempHeight, color, mode);
  523. }
  524. /** \brief Draw filled rectangle with color and mode.
  525. Draw filled rectangle using color and mode from x,y to x+width,y+height of the screen buffer.
  526. */
  527. void draw_rect_filled(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t color, uint8_t mode) {
  528. // TODO - need to optimise the memory map draw so that this function will not call pixel one by one
  529. for (int i=x; i<x+width;i++) {
  530. draw_line_vert(i,y, height, color, mode);
  531. }
  532. }
  533. /** \brief Draw filled rectangle with color and mode.
  534. Draw filled rectangle using color and mode from x,y to x+width,y+height of the screen buffer.
  535. */
  536. void draw_rect_filled_soft(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t color, uint8_t mode) {
  537. // TODO - need to optimise the memory map draw so that this function will not call pixel one by one
  538. for (int i=x; i<x+width;i++) {
  539. if (i == x || i == (x + width - 1))
  540. draw_line_vert(i, y+1, height-2, color, mode);
  541. else
  542. draw_line_vert(i, y, height, color, mode);
  543. }
  544. }
  545. /** \brief Draw character with color and mode.
  546. Draw character c using color and draw mode at x,y.
  547. */
  548. void draw_char(uint8_t x, uint8_t y, uint8_t c, uint8_t color, uint8_t mode, uint8_t font) {
  549. // TODO - New routine to take font of any height, at the moment limited to font height in multiple of 8 pixels
  550. uint8_t rowsToDraw,row, tempC;
  551. uint8_t i,j,temp;
  552. uint16_t charPerBitmapRow,charColPositionOnBitmap,charRowPositionOnBitmap,charBitmapStartPosition;
  553. if ((font>=TOTALFONTS) || (font<0))
  554. return;
  555. uint8_t fontType = font;
  556. uint8_t fontWidth = pgm_read_byte(fonts_pointer[fontType]+0);
  557. uint8_t fontHeight = pgm_read_byte(fonts_pointer[fontType]+1);
  558. uint8_t fontStartChar = pgm_read_byte(fonts_pointer[fontType]+2);
  559. uint8_t fontTotalChar = pgm_read_byte(fonts_pointer[fontType]+3);
  560. uint16_t fontMapWidth = (pgm_read_byte(fonts_pointer[fontType]+4)*100)+pgm_read_byte(fonts_pointer[fontType]+5); // two bytes values into integer 16
  561. if ((c<fontStartChar) || (c>(fontStartChar+fontTotalChar-1))) // no bitmap for the required c
  562. return;
  563. tempC=c-fontStartChar;
  564. // each row (in datasheet is call page) is 8 bits high, 16 bit high character will have 2 rows to be drawn
  565. rowsToDraw=fontHeight/8; // 8 is LCD's page size, see SSD1306 datasheet
  566. if (rowsToDraw<=1) rowsToDraw=1;
  567. // the following draw function can draw anywhere on the screen, but SLOW pixel by pixel draw
  568. if (rowsToDraw==1) {
  569. for (i=0;i<fontWidth+1;i++) {
  570. if (i==fontWidth) // this is done in a weird way because for 5x7 font, there is no margin, this code add a margin after col 5
  571. temp=0;
  572. else
  573. temp=pgm_read_byte(fonts_pointer[fontType]+FONTHEADERSIZE+(tempC*fontWidth)+i);
  574. for (j=0;j<8;j++) { // 8 is the LCD's page height (see datasheet for explanation)
  575. if (temp & 0x1) {
  576. draw_pixel(x+i, y+j, color,mode);
  577. }
  578. else {
  579. draw_pixel(x+i, y+j, !color,mode);
  580. }
  581. temp >>=1;
  582. }
  583. }
  584. return;
  585. }
  586. // font height over 8 bit
  587. // take character "0" ASCII 48 as example
  588. charPerBitmapRow = fontMapWidth/fontWidth; // 256/8 =32 char per row
  589. charColPositionOnBitmap = tempC % charPerBitmapRow; // =16
  590. charRowPositionOnBitmap = (int)(tempC/charPerBitmapRow); // =1
  591. charBitmapStartPosition = (charRowPositionOnBitmap * fontMapWidth * (fontHeight/8)) + (charColPositionOnBitmap * fontWidth) ;
  592. // each row on LCD is 8 bit height (see datasheet for explanation)
  593. for(row=0;row<rowsToDraw;row++) {
  594. for (i=0; i<fontWidth;i++) {
  595. temp=pgm_read_byte(fonts_pointer[fontType]+FONTHEADERSIZE+(charBitmapStartPosition+i+(row*fontMapWidth)));
  596. for (j=0;j<8;j++) { // 8 is the LCD's page height (see datasheet for explanation)
  597. if (temp & 0x1) {
  598. draw_pixel(x+i,y+j+(row*8), color, mode);
  599. }
  600. else {
  601. draw_pixel(x+i,y+j+(row*8), !color, mode);
  602. }
  603. temp >>=1;
  604. }
  605. }
  606. }
  607. }
  608. void draw_string(uint8_t x, uint8_t y, char * string, uint8_t color, uint8_t mode, uint8_t font) {
  609. if ((font>=TOTALFONTS) || (font<0))
  610. return;
  611. uint8_t fontType = font;
  612. uint8_t fontWidth = pgm_read_byte(fonts_pointer[fontType]+0);
  613. uint8_t cur_x = x;
  614. for (int i = 0; i < strlen(string); i++) {
  615. draw_char(cur_x, y, string[i], color, mode, font);
  616. cur_x += fontWidth + 1;
  617. }
  618. }