Display.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582
  1. /*
  2. This program is free software: you can redistribute it and/or modify
  3. it under the terms of the GNU General Public License as published by
  4. the Free Software Foundation, either version 3 of the License, or
  5. (at your option) any later version.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9. GNU General Public License for more details.
  10. You should have received a copy of the GNU General Public License
  11. along with this program. If not, see <http://www.gnu.org/licenses/>.
  12. */
  13. /* Notify display driver for 128 x 64 pixel displays */
  14. #include "Display.h"
  15. #include "Display_SH1106_I2C.h"
  16. #include "Display_SSD1306_I2C.h"
  17. #include "Display_SITL.h"
  18. #include "AP_Notify.h"
  19. #include <stdio.h>
  20. #include <AP_GPS/AP_GPS.h>
  21. #include <AP_BattMonitor/AP_BattMonitor.h>
  22. #include <utility>
  23. extern const AP_HAL::HAL& hal;
  24. // Bit Map
  25. // Rotate right 90 degrees
  26. // Ex: 0x7C, 0x12, 0x11, 0x12, 0x7C, // 'A'
  27. // 0XXXXX00
  28. // 000X00X0
  29. // 000X000X
  30. // 000X00X0
  31. // 0XXXXX00
  32. static const uint8_t _font[] = {
  33. #ifdef AP_NOTIFY_DISPLAY_USE_EMOJI
  34. // 0x Group
  35. 0x00, 0x00, 0x00, 0x00, 0x00, // 00
  36. 0x3E, 0x5B, 0x4F, 0x5B, 0x3E, // 01
  37. 0x3E, 0x6B, 0x4F, 0x6B, 0x3E, // 02
  38. 0x1C, 0x3E, 0x7C, 0x3E, 0x1C, // 03
  39. 0x18, 0x3C, 0x7E, 0x3C, 0x18, // 04
  40. 0x1C, 0x57, 0x7D, 0x57, 0x1C, // 05
  41. 0x1C, 0x5E, 0x7F, 0x5E, 0x1C, // 06
  42. 0x00, 0x18, 0x3C, 0x18, 0x00, // 07
  43. 0xFF, 0xE7, 0xC3, 0xE7, 0xFF, // 08
  44. 0x00, 0x18, 0x24, 0x18, 0x00, // 09
  45. 0xFF, 0xE7, 0xDB, 0xE7, 0xFF, // 0A
  46. 0x30, 0x48, 0x3A, 0x06, 0x0E, // 0B
  47. 0x26, 0x29, 0x79, 0x29, 0x26, // 0C
  48. 0x40, 0x7F, 0x05, 0x05, 0x07, // 0D
  49. 0x40, 0x7F, 0x05, 0x25, 0x3F, // 0E
  50. 0x5A, 0x3C, 0xE7, 0x3C, 0x5A, // 0F
  51. // 1x Group
  52. 0x7F, 0x3E, 0x1C, 0x1C, 0x08, // 10
  53. 0x08, 0x1C, 0x1C, 0x3E, 0x7F, // 11
  54. 0x14, 0x22, 0x7F, 0x22, 0x14, // 12
  55. 0x5F, 0x5F, 0x00, 0x5F, 0x5F, // 13
  56. 0x06, 0x09, 0x7F, 0x01, 0x7F, // 14
  57. 0x00, 0x66, 0x89, 0x95, 0x6A, // 15
  58. 0x60, 0x60, 0x60, 0x60, 0x60, // 16
  59. 0x94, 0xA2, 0xFF, 0xA2, 0x94, // 17
  60. 0x08, 0x04, 0x7E, 0x04, 0x08, // 18
  61. 0x10, 0x20, 0x7E, 0x20, 0x10, // 19
  62. 0x08, 0x08, 0x2A, 0x1C, 0x08, // 1A
  63. 0x08, 0x1C, 0x2A, 0x08, 0x08, // 1B
  64. 0x1E, 0x10, 0x10, 0x10, 0x10, // 1C
  65. 0x0C, 0x1E, 0x0C, 0x1E, 0x0C, // 1D
  66. 0x30, 0x38, 0x3E, 0x38, 0x30, // 1E
  67. 0x06, 0x0E, 0x3E, 0x0E, 0x06, // 1F
  68. #endif
  69. // 2x Group
  70. 0x00, 0x00, 0x00, 0x00, 0x00, // ' '
  71. 0x00, 0x00, 0x5F, 0x00, 0x00, // '!'
  72. 0x00, 0x07, 0x00, 0x07, 0x00, // '"'
  73. 0x14, 0x7F, 0x14, 0x7F, 0x14, // '#'
  74. 0x24, 0x2A, 0x7F, 0x2A, 0x12, // '$'
  75. 0x23, 0x13, 0x08, 0x64, 0x62, // '%'
  76. 0x36, 0x49, 0x56, 0x20, 0x50, // '&'
  77. 0x00, 0x08, 0x07, 0x03, 0x00, // '''
  78. 0x00, 0x1C, 0x22, 0x41, 0x00, // '('
  79. 0x00, 0x41, 0x22, 0x1C, 0x00, // ')'
  80. 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, // '*'
  81. 0x08, 0x08, 0x3E, 0x08, 0x08, // '+'
  82. 0x00, 0x80, 0x70, 0x30, 0x00, // ','
  83. 0x08, 0x08, 0x08, 0x08, 0x08, // '-'
  84. 0x00, 0x00, 0x60, 0x60, 0x00, // '.'
  85. 0x20, 0x10, 0x08, 0x04, 0x02, // '/'
  86. // 3x Group
  87. 0x3E, 0x51, 0x49, 0x45, 0x3E, // '0'
  88. 0x00, 0x42, 0x7F, 0x40, 0x00, // '1'
  89. 0x72, 0x49, 0x49, 0x49, 0x46, // '2'
  90. 0x21, 0x41, 0x49, 0x4D, 0x33, // '3'
  91. 0x18, 0x14, 0x12, 0x7F, 0x10, // '4'
  92. 0x27, 0x45, 0x45, 0x45, 0x39, // '5'
  93. 0x3C, 0x4A, 0x49, 0x49, 0x31, // '6'
  94. 0x41, 0x21, 0x11, 0x09, 0x07, // '7'
  95. 0x36, 0x49, 0x49, 0x49, 0x36, // '8'
  96. 0x46, 0x49, 0x49, 0x29, 0x1E, // '9'
  97. 0x00, 0x00, 0x14, 0x00, 0x00, // ':'
  98. 0x00, 0x40, 0x34, 0x00, 0x00, // ';'
  99. 0x00, 0x08, 0x14, 0x22, 0x41, // '<'
  100. 0x14, 0x14, 0x14, 0x14, 0x14, // '='
  101. 0x00, 0x41, 0x22, 0x14, 0x08, // '>'
  102. 0x02, 0x01, 0x59, 0x09, 0x06, // '?'
  103. // 4x Group
  104. 0x3E, 0x41, 0x5D, 0x59, 0x4E, // '@'
  105. 0x7C, 0x12, 0x11, 0x12, 0x7C, // 'A'
  106. 0x7F, 0x49, 0x49, 0x49, 0x36, // 'B'
  107. 0x3E, 0x41, 0x41, 0x41, 0x22, // 'C'
  108. 0x7F, 0x41, 0x41, 0x41, 0x3E, // 'D'
  109. 0x7F, 0x49, 0x49, 0x49, 0x41, // 'E'
  110. 0x7F, 0x09, 0x09, 0x09, 0x01, // 'F'
  111. 0x3E, 0x41, 0x41, 0x51, 0x73, // 'G'
  112. 0x7F, 0x08, 0x08, 0x08, 0x7F, // 'H'
  113. 0x00, 0x41, 0x7F, 0x41, 0x00, // 'I'
  114. 0x20, 0x40, 0x41, 0x3F, 0x01, // 'J'
  115. 0x7F, 0x08, 0x14, 0x22, 0x41, // 'K'
  116. 0x7F, 0x40, 0x40, 0x40, 0x40, // 'L'
  117. 0x7F, 0x02, 0x1C, 0x02, 0x7F, // 'M'
  118. 0x7F, 0x04, 0x08, 0x10, 0x7F, // 'N'
  119. 0x3E, 0x41, 0x41, 0x41, 0x3E, // 'O'
  120. // 5x Group
  121. 0x7F, 0x09, 0x09, 0x09, 0x06, // 'P'
  122. 0x3E, 0x41, 0x51, 0x21, 0x5E, // 'Q'
  123. 0x7F, 0x09, 0x19, 0x29, 0x46, // 'R'
  124. 0x26, 0x49, 0x49, 0x49, 0x32, // 'S'
  125. 0x03, 0x01, 0x7F, 0x01, 0x03, // 'T'
  126. 0x3F, 0x40, 0x40, 0x40, 0x3F, // 'U'
  127. 0x1F, 0x20, 0x40, 0x20, 0x1F, // 'V'
  128. 0x3F, 0x40, 0x38, 0x40, 0x3F, // 'W'
  129. 0x63, 0x14, 0x08, 0x14, 0x63, // 'X'
  130. 0x03, 0x04, 0x78, 0x04, 0x03, // 'Y'
  131. 0x61, 0x59, 0x49, 0x4D, 0x43, // 'Z'
  132. 0x00, 0x7F, 0x41, 0x41, 0x41, // '['
  133. 0x02, 0x04, 0x08, 0x10, 0x20, // '\'
  134. 0x00, 0x41, 0x41, 0x41, 0x7F, // ']'
  135. 0x04, 0x02, 0x01, 0x02, 0x04, // '^'
  136. 0x40, 0x40, 0x40, 0x40, 0x40, // '_'
  137. // 6x Group
  138. 0x00, 0x03, 0x07, 0x08, 0x00, // '`'
  139. 0x20, 0x54, 0x54, 0x78, 0x40, // 'a'
  140. 0x7F, 0x28, 0x44, 0x44, 0x38, // 'b'
  141. 0x38, 0x44, 0x44, 0x44, 0x28, // 'c'
  142. 0x38, 0x44, 0x44, 0x28, 0x7F, // 'd'
  143. 0x38, 0x54, 0x54, 0x54, 0x18, // 'e'
  144. 0x00, 0x08, 0x7E, 0x09, 0x02, // 'f'
  145. 0x18, 0xA4, 0xA4, 0x9C, 0x78, // 'g'
  146. 0x7F, 0x08, 0x04, 0x04, 0x78, // 'h'
  147. 0x00, 0x44, 0x7D, 0x40, 0x00, // 'i'
  148. 0x20, 0x40, 0x40, 0x3D, 0x00, // 'j'
  149. 0x7F, 0x10, 0x28, 0x44, 0x00, // 'k'
  150. 0x00, 0x41, 0x7F, 0x40, 0x00, // 'l'
  151. 0x7C, 0x04, 0x78, 0x04, 0x78, // 'm'
  152. 0x7C, 0x08, 0x04, 0x04, 0x78, // 'n'
  153. 0x38, 0x44, 0x44, 0x44, 0x38, // 'o'
  154. // 7x Group
  155. 0xFC, 0x18, 0x24, 0x24, 0x18, // 'p'
  156. 0x18, 0x24, 0x24, 0x18, 0xFC, // 'q'
  157. 0x7C, 0x08, 0x04, 0x04, 0x08, // 'r'
  158. 0x48, 0x54, 0x54, 0x54, 0x24, // 's'
  159. 0x04, 0x04, 0x3F, 0x44, 0x24, // 't'
  160. 0x3C, 0x40, 0x40, 0x20, 0x7C, // 'u'
  161. 0x1C, 0x20, 0x40, 0x20, 0x1C, // 'v'
  162. 0x3C, 0x40, 0x30, 0x40, 0x3C, // 'w'
  163. 0x44, 0x28, 0x10, 0x28, 0x44, // 'x'
  164. 0x4C, 0x90, 0x90, 0x90, 0x7C, // 'y'
  165. 0x44, 0x64, 0x54, 0x4C, 0x44, // 'z'
  166. 0x00, 0x08, 0x36, 0x41, 0x00, // '{'
  167. 0x00, 0x00, 0x77, 0x00, 0x00, // '|'
  168. 0x00, 0x41, 0x36, 0x08, 0x00, // '}'
  169. 0x02, 0x01, 0x02, 0x04, 0x02, // '~'
  170. #ifdef AP_NOTIFY_DISPLAY_USE_EMOJI
  171. 0x3C, 0x26, 0x23, 0x26, 0x3C, // 7F
  172. // 8x Group
  173. 0x1E, 0xA1, 0xA1, 0x61, 0x12, // 80
  174. 0x3A, 0x40, 0x40, 0x20, 0x7A, // 81
  175. 0x38, 0x54, 0x54, 0x55, 0x59, // 82
  176. 0x21, 0x55, 0x55, 0x79, 0x41, // 83
  177. 0x22, 0x54, 0x54, 0x78, 0x42, // 84
  178. 0x21, 0x55, 0x54, 0x78, 0x40, // 85
  179. 0x20, 0x54, 0x55, 0x79, 0x40, // 86
  180. 0x0C, 0x1E, 0x52, 0x72, 0x12, // 87
  181. 0x39, 0x55, 0x55, 0x55, 0x59, // 88
  182. 0x39, 0x54, 0x54, 0x54, 0x59, // 89
  183. 0x39, 0x55, 0x54, 0x54, 0x58, // 8A
  184. 0x00, 0x00, 0x45, 0x7C, 0x41, // 8B
  185. 0x00, 0x02, 0x45, 0x7D, 0x42, // 8C
  186. 0x00, 0x01, 0x45, 0x7C, 0x40, // 8D
  187. 0x7D, 0x12, 0x11, 0x12, 0x7D, // 8E
  188. 0xF0, 0x28, 0x25, 0x28, 0xF0, // 8F
  189. // 9x Group
  190. 0x7C, 0x54, 0x55, 0x45, 0x00, // 90
  191. 0x20, 0x54, 0x54, 0x7C, 0x54, // 91
  192. 0x7C, 0x0A, 0x09, 0x7F, 0x49, // 92
  193. 0x32, 0x49, 0x49, 0x49, 0x32, // 93
  194. 0x3A, 0x44, 0x44, 0x44, 0x3A, // 94
  195. 0x32, 0x4A, 0x48, 0x48, 0x30, // 95
  196. 0x3A, 0x41, 0x41, 0x21, 0x7A, // 96
  197. 0x3A, 0x42, 0x40, 0x20, 0x78, // 97
  198. 0x00, 0x9D, 0xA0, 0xA0, 0x7D, // 98
  199. 0x3D, 0x42, 0x42, 0x42, 0x3D, // 99
  200. 0x3D, 0x40, 0x40, 0x40, 0x3D, // 9A
  201. 0x3C, 0x24, 0xFF, 0x24, 0x24, // 9B
  202. 0x48, 0x7E, 0x49, 0x43, 0x66, // 9C
  203. 0x2B, 0x2F, 0xFC, 0x2F, 0x2B, // 9D
  204. 0xFF, 0x09, 0x29, 0xF6, 0x20, // 9E
  205. 0xC0, 0x88, 0x7E, 0x09, 0x03, // 9F
  206. // Ax Group
  207. 0x20, 0x54, 0x54, 0x79, 0x41, // A0
  208. 0x00, 0x00, 0x44, 0x7D, 0x41, // A1
  209. 0x30, 0x48, 0x48, 0x4A, 0x32, // A2
  210. 0x38, 0x40, 0x40, 0x22, 0x7A, // A3
  211. 0x00, 0x7A, 0x0A, 0x0A, 0x72, // A4
  212. 0x7D, 0x0D, 0x19, 0x31, 0x7D, // A5
  213. 0x26, 0x29, 0x29, 0x2F, 0x28, // A6
  214. 0x26, 0x29, 0x29, 0x29, 0x26, // A7
  215. 0x30, 0x48, 0x4D, 0x40, 0x20, // A8
  216. 0x38, 0x08, 0x08, 0x08, 0x08, // A9
  217. 0x08, 0x08, 0x08, 0x08, 0x38, // AA
  218. 0x2F, 0x10, 0xC8, 0xAC, 0xBA, // AB
  219. 0x2F, 0x10, 0x28, 0x34, 0xFA, // AC
  220. 0x00, 0x00, 0x7B, 0x00, 0x00, // AD
  221. 0x08, 0x14, 0x2A, 0x14, 0x22, // AE
  222. 0x22, 0x14, 0x2A, 0x14, 0x08, // AF
  223. // Bx Group
  224. 0x55, 0x00, 0x55, 0x00, 0x55, // B0
  225. 0xAA, 0x55, 0xAA, 0x55, 0xAA, // B1
  226. 0xFF, 0x55, 0xFF, 0x55, 0xFF, // B2
  227. 0x00, 0x00, 0x00, 0xFF, 0x00, // B3
  228. 0x10, 0x10, 0x10, 0xFF, 0x00, // B4
  229. 0x14, 0x14, 0x14, 0xFF, 0x00, // B5
  230. 0x10, 0x10, 0xFF, 0x00, 0xFF, // B6
  231. 0x10, 0x10, 0xF0, 0x10, 0xF0, // B7
  232. 0x14, 0x14, 0x14, 0xFC, 0x00, // B8
  233. 0x14, 0x14, 0xF7, 0x00, 0xFF, // B9
  234. 0x00, 0x00, 0xFF, 0x00, 0xFF, // BA
  235. 0x14, 0x14, 0xF4, 0x04, 0xFC, // BB
  236. 0x14, 0x14, 0x17, 0x10, 0x1F, // BC
  237. 0x10, 0x10, 0x1F, 0x10, 0x1F, // BD
  238. 0x14, 0x14, 0x14, 0x1F, 0x00, // BE
  239. 0x10, 0x10, 0x10, 0xF0, 0x00, // BF
  240. // Cx Group
  241. 0x00, 0x00, 0x00, 0x1F, 0x10, // C0
  242. 0x10, 0x10, 0x10, 0x1F, 0x10, // C1
  243. 0x10, 0x10, 0x10, 0xF0, 0x10, // C2
  244. 0x00, 0x00, 0x00, 0xFF, 0x10, // C3
  245. 0x10, 0x10, 0x10, 0x10, 0x10, // C4
  246. 0x10, 0x10, 0x10, 0xFF, 0x10, // C5
  247. 0x00, 0x00, 0x00, 0xFF, 0x14, // C6
  248. 0x00, 0x00, 0xFF, 0x00, 0xFF, // C7
  249. 0x00, 0x00, 0x1F, 0x10, 0x17, // C8
  250. 0x00, 0x00, 0xFC, 0x04, 0xF4, // C9
  251. 0x14, 0x14, 0x17, 0x10, 0x17, // CA
  252. 0x14, 0x14, 0xF4, 0x04, 0xF4, // CB
  253. 0x00, 0x00, 0xFF, 0x00, 0xF7, // CC
  254. 0x14, 0x14, 0x14, 0x14, 0x14, // CD
  255. 0x14, 0x14, 0xF7, 0x00, 0xF7, // CE
  256. 0x14, 0x14, 0x14, 0x17, 0x14, // CF
  257. // Dx Group
  258. 0x10, 0x10, 0x1F, 0x10, 0x1F, // D0
  259. 0x14, 0x14, 0x14, 0xF4, 0x14, // D1
  260. 0x10, 0x10, 0xF0, 0x10, 0xF0, // D2
  261. 0x00, 0x00, 0x1F, 0x10, 0x1F, // D3
  262. 0x00, 0x00, 0x00, 0x1F, 0x14, // D4
  263. 0x00, 0x00, 0x00, 0xFC, 0x14, // D5
  264. 0x00, 0x00, 0xF0, 0x10, 0xF0, // D6
  265. 0x10, 0x10, 0xFF, 0x10, 0xFF, // D7
  266. 0x14, 0x14, 0x14, 0xFF, 0x14, // D8
  267. 0x10, 0x10, 0x10, 0x1F, 0x00, // D9
  268. 0x00, 0x00, 0x00, 0xF0, 0x10, // DA
  269. 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // DB
  270. 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, // DC
  271. 0xFF, 0xFF, 0xFF, 0x00, 0x00, // DD
  272. 0x00, 0x00, 0x00, 0xFF, 0xFF, // DE
  273. 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, // DF
  274. // Ex Group
  275. 0x38, 0x44, 0x44, 0x38, 0x44, // E0
  276. 0xFC, 0x4A, 0x4A, 0x4A, 0x34, // E1
  277. 0x7E, 0x02, 0x02, 0x06, 0x06, // E2
  278. 0x02, 0x7E, 0x02, 0x7E, 0x02, // E3
  279. 0x63, 0x55, 0x49, 0x41, 0x63, // E4
  280. 0x38, 0x44, 0x44, 0x3C, 0x04, // E5
  281. 0x40, 0x7E, 0x20, 0x1E, 0x20, // E6
  282. 0x06, 0x02, 0x7E, 0x02, 0x02, // E7
  283. 0x99, 0xA5, 0xE7, 0xA5, 0x99, // E8
  284. 0x1C, 0x2A, 0x49, 0x2A, 0x1C, // E9
  285. 0x4C, 0x72, 0x01, 0x72, 0x4C, // EA
  286. 0x30, 0x4A, 0x4D, 0x4D, 0x30, // EB
  287. 0x30, 0x48, 0x78, 0x48, 0x30, // EC
  288. 0xBC, 0x62, 0x5A, 0x46, 0x3D, // ED
  289. 0x3E, 0x49, 0x49, 0x49, 0x00, // EE
  290. 0x7E, 0x01, 0x01, 0x01, 0x7E, // EF
  291. // Fx Group
  292. 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, // F0
  293. 0x44, 0x44, 0x5F, 0x44, 0x44, // F1
  294. 0x40, 0x51, 0x4A, 0x44, 0x40, // F2
  295. 0x40, 0x44, 0x4A, 0x51, 0x40, // F3
  296. 0x00, 0x00, 0xFF, 0x01, 0x03, // F4
  297. 0xE0, 0x80, 0xFF, 0x00, 0x00, // F5
  298. 0x08, 0x08, 0x6B, 0x6B, 0x08, // F6
  299. 0x36, 0x12, 0x36, 0x24, 0x36, // F7
  300. 0x06, 0x0F, 0x09, 0x0F, 0x06, // F8
  301. 0x00, 0x00, 0x18, 0x18, 0x00, // F9
  302. 0x00, 0x00, 0x10, 0x10, 0x00, // FA
  303. 0x30, 0x40, 0xFF, 0x01, 0x01, // FB
  304. 0x00, 0x1F, 0x01, 0x01, 0x1E, // FC
  305. 0x00, 0x19, 0x1D, 0x17, 0x12, // FD
  306. 0x00, 0x3C, 0x3C, 0x3C, 0x3C, // FE
  307. 0x00, 0x00, 0x00, 0x00, 0x00 // FF
  308. #endif
  309. };
  310. #ifdef AP_NOTIFY_DISPLAY_USE_EMOJI
  311. static_assert(ARRAY_SIZE(_font) == 1280, "_font is correct size");
  312. #else
  313. static_assert(ARRAY_SIZE(_font) == 475, "_font is correct size");
  314. #endif
  315. bool Display::init(void)
  316. {
  317. // exit immediately if already initialised
  318. if (_driver != nullptr) {
  319. return true;
  320. }
  321. // initialise driver
  322. FOREACH_I2C(i) {
  323. switch (pNotify->_display_type) {
  324. case DISPLAY_SSD1306: {
  325. _driver = Display_SSD1306_I2C::probe(std::move(hal.i2c_mgr->get_device(i, NOTIFY_DISPLAY_I2C_ADDR)));
  326. break;
  327. }
  328. case DISPLAY_SH1106: {
  329. _driver = Display_SH1106_I2C::probe(std::move(hal.i2c_mgr->get_device(i, NOTIFY_DISPLAY_I2C_ADDR)));
  330. break;
  331. }
  332. case DISPLAY_SITL: {
  333. #ifdef WITH_SITL_OSD
  334. _driver = Display_SITL::probe(); // never fails
  335. #elif CONFIG_HAL_BOARD == HAL_BOARD_SITL
  336. ::fprintf(stderr, "SITL Display ineffective without --osd\n");
  337. #endif
  338. break;
  339. }
  340. case DISPLAY_OFF:
  341. default:
  342. break;
  343. }
  344. if (_driver != nullptr) {
  345. break;
  346. }
  347. }
  348. if (_driver == nullptr) {
  349. return false;
  350. }
  351. // update all on display
  352. update_all();
  353. _driver->hw_update();
  354. return true;
  355. }
  356. void Display::update()
  357. {
  358. // max update frequency 2Hz
  359. static uint8_t timer = 0;
  360. if (timer++ < 25) {
  361. return;
  362. }
  363. timer = 0;
  364. if (AP_Notify::flags.armed) {
  365. if (_screenpage != 1) {
  366. _driver->clear_screen();
  367. update_arm(3);
  368. _screenpage = 1;
  369. _driver->hw_update(); //update hw once , do not transmition to display in fly
  370. }
  371. return;
  372. }
  373. if (_screenpage != 2) {
  374. _driver->clear_screen(); //once clear screen when page changed
  375. _screenpage = 2;
  376. }
  377. update_all();
  378. _driver->hw_update(); //update at 2 Hz in disarmed mode
  379. }
  380. void Display::update_all()
  381. {
  382. update_text(0);
  383. update_mode(1);
  384. update_battery(2);
  385. update_gps(3);
  386. //update_gps_sats(4);
  387. update_prearm(4);
  388. update_ekf(5);
  389. }
  390. void Display::draw_text(uint16_t x, uint16_t y, const char* c)
  391. {
  392. if (nullptr == c) {
  393. return;
  394. }
  395. while (*c != 0) {
  396. #ifndef AP_NOTIFY_DISPLAY_USE_EMOJI
  397. if (*c >= ' ' && *c <= '~') {
  398. draw_char(x, y, *c - ' ');
  399. } else {
  400. // convert oob characters to spaces
  401. draw_char(x, y, 0);
  402. }
  403. #else
  404. draw_char(x, y, *c);
  405. #endif
  406. x += 7;
  407. c++;
  408. }
  409. }
  410. void Display::draw_char(uint16_t x, uint16_t y, const char c)
  411. {
  412. uint8_t line;
  413. // draw char to pixel
  414. for (uint8_t i = 0; i < 6; i++) {
  415. if (i == 5) {
  416. line = 0;
  417. } else {
  418. line = _font[(c * 5) + i];
  419. }
  420. for (uint8_t j = 0; j < 8; j++) {
  421. if (line & 1) {
  422. _driver->set_pixel(x + i, y + j);
  423. } else {
  424. _driver->clear_pixel(x + i, y + j);
  425. }
  426. line >>= 1;
  427. }
  428. }
  429. }
  430. void Display::update_arm(uint8_t r)
  431. {
  432. if (AP_Notify::flags.armed) {
  433. draw_text(COLUMN(0), ROW(r), ">>>>> ARMED! <<<<<");
  434. } else {
  435. draw_text(COLUMN(0), ROW(r), " disarmed ");
  436. }
  437. }
  438. void Display::update_prearm(uint8_t r)
  439. {
  440. if (AP_Notify::flags.pre_arm_check) {
  441. draw_text(COLUMN(0), ROW(r), "Prearm: passed ");
  442. } else {
  443. draw_text(COLUMN(0), ROW(r), "Prearm: failed ");
  444. }
  445. }
  446. void Display::update_gps(uint8_t r)
  447. {
  448. static const char * gpsfixname[] = {"Other", "NoGPS","NoFix","2D","3D","DGPS", "RTK f", "RTK F"};
  449. char msg [DISPLAY_MESSAGE_SIZE];
  450. const char * fixname;
  451. switch (AP_Notify::flags.gps_status) {
  452. case AP_GPS::NO_GPS:
  453. fixname = gpsfixname[1];
  454. break;
  455. case AP_GPS::NO_FIX:
  456. fixname = gpsfixname[2];
  457. break;
  458. case AP_GPS::GPS_OK_FIX_2D:
  459. fixname = gpsfixname[3];
  460. break;
  461. case AP_GPS::GPS_OK_FIX_3D:
  462. fixname = gpsfixname[4];
  463. break;
  464. case AP_GPS::GPS_OK_FIX_3D_DGPS:
  465. fixname = gpsfixname[5];
  466. break;
  467. case AP_GPS::GPS_OK_FIX_3D_RTK_FLOAT:
  468. fixname = gpsfixname[6];
  469. break;
  470. case AP_GPS::GPS_OK_FIX_3D_RTK_FIXED:
  471. fixname = gpsfixname[7];
  472. break;
  473. default:
  474. fixname = gpsfixname[0];
  475. break;
  476. }
  477. snprintf(msg, DISPLAY_MESSAGE_SIZE, "GPS:%-5s Sats:%2u", fixname, (unsigned)AP_Notify::flags.gps_num_sats) ;
  478. draw_text(COLUMN(0), ROW(r), msg);
  479. }
  480. void Display::update_gps_sats(uint8_t r)
  481. {
  482. draw_text(COLUMN(0), ROW(r), "Sats:");
  483. draw_char(COLUMN(8), ROW(r), (AP_Notify::flags.gps_num_sats / 10) + '0');
  484. draw_char(COLUMN(9), ROW(r), (AP_Notify::flags.gps_num_sats % 10) + '0');
  485. }
  486. void Display::update_ekf(uint8_t r)
  487. {
  488. if (AP_Notify::flags.ekf_bad) {
  489. draw_text(COLUMN(0), ROW(r), "EKF: fail");
  490. } else {
  491. draw_text(COLUMN(0), ROW(r), "EKF: ok ");
  492. }
  493. }
  494. void Display::update_battery(uint8_t r)
  495. {
  496. char msg [DISPLAY_MESSAGE_SIZE];
  497. snprintf(msg, DISPLAY_MESSAGE_SIZE, "BAT1: %4.2fV", (double)AP::battery().voltage()) ;
  498. draw_text(COLUMN(0), ROW(r), msg);
  499. }
  500. void Display::update_mode(uint8_t r)
  501. {
  502. char msg [DISPLAY_MESSAGE_SIZE];
  503. if (pNotify->get_flight_mode_str()) {
  504. snprintf(msg, DISPLAY_MESSAGE_SIZE, "Mode: %s", pNotify->get_flight_mode_str()) ;
  505. draw_text(COLUMN(0), ROW(r), msg);
  506. }
  507. }
  508. void Display::update_text_empty(uint8_t r)
  509. {
  510. char msg [DISPLAY_MESSAGE_SIZE] = {};
  511. memset(msg, ' ', sizeof(msg)-1);
  512. _movedelay = 0;
  513. _mstartpos = 0;
  514. draw_text(COLUMN(0), ROW(r), msg);
  515. }
  516. void Display::update_text(uint8_t r)
  517. {
  518. char msg [DISPLAY_MESSAGE_SIZE] = {};
  519. char txt [NOTIFY_TEXT_BUFFER_SIZE] = {};
  520. const bool text_is_valid = AP_HAL::millis() - pNotify->_send_text_updated_millis < _send_text_valid_millis;
  521. if (!text_is_valid) {
  522. update_text_empty(r);
  523. return;
  524. }
  525. if (_movedelay > 0) {
  526. _movedelay--;
  527. return;
  528. }
  529. snprintf(txt, sizeof(txt), "%s", pNotify->get_text());
  530. memset(msg, ' ', sizeof(msg)-1); // leave null termination
  531. const uint8_t len = strlen(&txt[_mstartpos]);
  532. const uint8_t to_copy = (len < sizeof(msg)-1) ? len : (sizeof(msg)-1);
  533. memcpy(msg, &txt[_mstartpos], to_copy);
  534. if (len <= sizeof(msg)-1) {
  535. // end-of-message reached; pause scrolling a while
  536. _movedelay = 4;
  537. // reset startpos so we start scrolling from the start again:
  538. _mstartpos = 0;
  539. } else {
  540. _mstartpos++;
  541. }
  542. draw_text(COLUMN(0), ROW(0), msg);
  543. }