OLED_SSD1306_ATY.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. /**
  2. * @file OLED_SSD1306_ATY.c
  3. *
  4. * @param Project DEVICE_GENERAL_ATY_LIB
  5. *
  6. * @author ATY
  7. *
  8. * @copyright
  9. * - Copyright 2017 - 2026 MZ-ATY
  10. * - This code follows:
  11. * - MZ-ATY Various Contents Joint Statement -
  12. * <a href="https://mengze.top/MZ-ATY_VCJS">
  13. * https://mengze.top/MZ-ATY_VCJS</a>
  14. * - CC 4.0 BY-NC-SA -
  15. * <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">
  16. * https://creativecommons.org/licenses/by-nc-sa/4.0/</a>
  17. * - Your use will be deemed to have accepted the terms of this statement.
  18. *
  19. * @brief Dev-style implementation for SSD1306 OLED display (I2C)
  20. *
  21. * @version
  22. * - 2_00_251112 > ATY
  23. * -# Refactor to Dev-style interface with platform-agnostic callbacks
  24. ********************************************************************************
  25. */
  26. #ifndef __OLED_SSD1306_ATY_C
  27. #define __OLED_SSD1306_ATY_C
  28. #include "OLED_SSD1306_ATY.h"
  29. /* ------------------------ Dev-style helpers & APIs ------------------------ */
  30. static int _oled_write_cmd(OLED_SSD1306_ATY_Dev* dev, uint8_t cmd)
  31. {
  32. if(!dev || !dev->i2c_write) return -1;
  33. uint8_t buf[2] = {0x00, cmd};
  34. return dev->i2c_write(dev->addr, buf, 2, dev->channel);
  35. }
  36. static int _oled_write_data(OLED_SSD1306_ATY_Dev* dev, const uint8_t* data, uint16_t len)
  37. {
  38. if(!dev || !dev->i2c_write || !data || len == 0) return -1;
  39. /* 简洁起见,逐字节发送(0x40 + data),兼容性强 */
  40. for(uint16_t i = 0; i < len; i++)
  41. {
  42. uint8_t buf[2] = {0x40, data[i]};
  43. int rc = dev->i2c_write(dev->addr, buf, 2, dev->channel);
  44. if(rc) return rc;
  45. }
  46. return 0;
  47. }
  48. void OLED_SSD1306_SetPosDev(OLED_SSD1306_ATY_Dev* dev, uint8_t x, uint8_t y)
  49. {
  50. if(!dev) return;
  51. _oled_write_cmd(dev, (uint8_t)(0xb0 + y));
  52. _oled_write_cmd(dev, (uint8_t)(((x & 0xf0) >> 4) | 0x10));
  53. _oled_write_cmd(dev, (uint8_t)((x & 0x0f) | 0x01));
  54. }
  55. void OLED_SSD1306_FillScreenDev(OLED_SSD1306_ATY_Dev* dev, uint8_t fillData)
  56. {
  57. if(!dev) return;
  58. for(uint8_t y = 0; y < 8; y++)
  59. {
  60. _oled_write_cmd(dev, (uint8_t)(0xb0 + y));
  61. _oled_write_cmd(dev, 0x01);
  62. _oled_write_cmd(dev, 0x10);
  63. for(uint8_t x = 0; x < X_WIDTH; x++)
  64. {
  65. _oled_write_data(dev, &fillData, 1);
  66. }
  67. }
  68. }
  69. void OLED_SSD1306_DrawChar8x16Dev(OLED_SSD1306_ATY_Dev* dev, uint8_t x, uint8_t y, const uint8_t symbol[])
  70. {
  71. if(!dev || !symbol) return;
  72. if(x > 120) { x = 0; y += 2; }
  73. OLED_SSD1306_SetPosDev(dev, x, y);
  74. _oled_write_data(dev, symbol, 8);
  75. OLED_SSD1306_SetPosDev(dev, x, (uint8_t)(y + 1));
  76. _oled_write_data(dev, symbol + 8, 8);
  77. }
  78. void OLED_SSD1306_DrawChar16x16Dev(OLED_SSD1306_ATY_Dev* dev, uint8_t x, uint8_t y, const uint8_t symbol[])
  79. {
  80. if(!dev || !symbol) return;
  81. if(x > 120) { x = 0; y += 2; }
  82. OLED_SSD1306_SetPosDev(dev, x, y);
  83. _oled_write_data(dev, symbol, 16);
  84. OLED_SSD1306_SetPosDev(dev, x, (uint8_t)(y + 1));
  85. _oled_write_data(dev, symbol + 16, 16);
  86. }
  87. void OLED_SSD1306_DrawString8x16Dev(OLED_SSD1306_ATY_Dev* dev, uint8_t x, uint8_t y, const char* str, const uint8_t* font)
  88. {
  89. if(!dev || !str || !font) return;
  90. uint8_t xi = x, yi = y;
  91. for(const char* p = str; *p; ++p)
  92. {
  93. if(xi > 120) { xi = 0; yi = (uint8_t)(yi + 2); }
  94. if(yi > 6) break;
  95. const uint8_t* glyph = font + (((uint8_t)(*p) - 32) * 16);
  96. OLED_SSD1306_DrawChar8x16Dev(dev, xi, yi, glyph);
  97. xi = (uint8_t)(xi + 8);
  98. }
  99. }
  100. int OLED_SSD1306_WriteCmdDev(OLED_SSD1306_ATY_Dev* dev, uint8_t cmd)
  101. {
  102. return _oled_write_cmd(dev, cmd);
  103. }
  104. int OLED_SSD1306_WriteDataDev(OLED_SSD1306_ATY_Dev* dev, const uint8_t* data, uint16_t len)
  105. {
  106. return _oled_write_data(dev, data, len);
  107. }
  108. void OLED_SSD1306_InitDev(OLED_SSD1306_ATY_Dev* dev, uint8_t addr, uint8_t channel)
  109. {
  110. if(!dev) return;
  111. dev->addr = addr;
  112. dev->channel = channel;
  113. if(dev->lock) dev->lock(1);
  114. /* 0.91" 128x32 init sequence */
  115. _oled_write_cmd(dev, 0xAE);
  116. _oled_write_cmd(dev, 0x20);
  117. _oled_write_cmd(dev, 0x00);
  118. _oled_write_cmd(dev, 0xb0);
  119. _oled_write_cmd(dev, 0xc8);
  120. _oled_write_cmd(dev, 0x00);
  121. _oled_write_cmd(dev, 0x10);
  122. _oled_write_cmd(dev, 0x40);
  123. _oled_write_cmd(dev, 0x81);
  124. _oled_write_cmd(dev, 0xdf);
  125. _oled_write_cmd(dev, 0xa1);
  126. _oled_write_cmd(dev, 0xa6);
  127. _oled_write_cmd(dev, 0xa8);
  128. _oled_write_cmd(dev, 0x1F);
  129. _oled_write_cmd(dev, 0xa4);
  130. _oled_write_cmd(dev, 0xd3);
  131. _oled_write_cmd(dev, 0x00);
  132. _oled_write_cmd(dev, 0xd5);
  133. _oled_write_cmd(dev, 0xf0);
  134. _oled_write_cmd(dev, 0xd9);
  135. _oled_write_cmd(dev, 0x22);
  136. _oled_write_cmd(dev, 0xda);
  137. _oled_write_cmd(dev, 0x12);
  138. _oled_write_cmd(dev, 0xdb);
  139. _oled_write_cmd(dev, 0x20);
  140. _oled_write_cmd(dev, 0x8d);
  141. _oled_write_cmd(dev, 0x14);
  142. _oled_write_cmd(dev, 0xDA);
  143. _oled_write_cmd(dev, 0x02);
  144. _oled_write_cmd(dev, 0xaf);
  145. OLED_SSD1306_FillScreenDev(dev, 0x00);
  146. OLED_SSD1306_SetPosDev(dev, 0, 0);
  147. if(dev->lock) dev->lock(0);
  148. }
  149. /* ------------------------ Legacy implementation (disabled) ------------------------ */
  150. #if 0
  151. void OLED_WriteData(uint8_t oledData)
  152. {
  153. I2C_Start();
  154. I2C_WriteByte(0x78); //Slave address,SA0=0
  155. I2C_WriteByte(0x40);
  156. I2C_WriteByte(oledData);
  157. I2C_Stop();
  158. }
  159. void OLED_WriteCmd(uint8_t oledCmd)
  160. {
  161. I2C_Start();
  162. I2C_WriteByte(0x78); //Slave address,SA0=0
  163. I2C_WriteByte(0x00);
  164. I2C_WriteByte(oledCmd);
  165. I2C_Stop();
  166. }
  167. void OLED_SetPos(uint8_t x, uint8_t y)
  168. {
  169. OLED_WriteCmd(0xb0 + y);
  170. OLED_WriteCmd(((x & 0xf0) >> 4) | 0x10);
  171. OLED_WriteCmd((x & 0x0f) | 0x01);
  172. }
  173. void OLED_FillScreen(uint8_t fillData)
  174. {
  175. uint8_t y, x;
  176. for(y = 0; y < 8; y++)
  177. {
  178. OLED_WriteCmd(0xb0 + y);
  179. OLED_WriteCmd(0x01);
  180. OLED_WriteCmd(0x10);
  181. for(x = 0; x < X_WIDTH; x++)
  182. OLED_WriteData(fillData);
  183. }
  184. }
  185. void OLED_Init(void)
  186. {
  187. // uint16_t i = 0;
  188. // for(i = 0; i < 5000; i++){}
  189. // DelayNms(50);
  190. // OLED_WriteCmd(0xae); // Turn off oled panel
  191. // OLED_WriteCmd(0x00); // Set low column address
  192. // OLED_WriteCmd(0x10); // Set high column address
  193. // OLED_WriteCmd(0x40); // Set start line address, Set Mapping RAM Display Start Line (0x00~0x3F)
  194. // OLED_WriteCmd(0x81); // Set contrast control register
  195. // OLED_WriteCmd(BRIGHTNESS); // Set SEG Output Current Brightness
  196. // OLED_WriteCmd(0xa1); // Set SEG/Column Mapping, 0xa0 reverse x, 0xa1 normal x
  197. // OLED_WriteCmd(0xc8); // Set COM/Row Scan Direction, 0xc0 reverse y, 0xc8 normal y
  198. // OLED_WriteCmd(0xa6); // Set normal display
  199. // OLED_WriteCmd(0xa8); // Set multiplex ratio(1 to 64)
  200. // OLED_WriteCmd(0x3f); // 1/64 duty
  201. // OLED_WriteCmd(0xd3); // Set display offset Shift Mapping RAM Counter (0x00~0x3F)
  202. // OLED_WriteCmd(0x00); // Not offset
  203. // OLED_WriteCmd(0xd5); // Set display clock divide ratio/oscillator frequency
  204. // OLED_WriteCmd(0x80); // Set divide ratio, Set Clock as 100 Frames/Sec
  205. // OLED_WriteCmd(0xd9); // Set pre-charge period
  206. // OLED_WriteCmd(0xf1); // Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
  207. // OLED_WriteCmd(0xda); // Set com pins hardware configuration
  208. // OLED_WriteCmd(0x12);
  209. // OLED_WriteCmd(0xdb); // Set vcomh
  210. // OLED_WriteCmd(0x40); // Set VCOM Deselect Level
  211. // OLED_WriteCmd(0x20); // Set Page Addressing Mode (0x00/0x01/0x02)
  212. // OLED_WriteCmd(0x02); //
  213. // OLED_WriteCmd(0x8d); // Set Charge Pump enable/disable
  214. // OLED_WriteCmd(0x14); // Set(0x10) disable
  215. // OLED_WriteCmd(0xa4); // Disable Entire Display On (0xa4/0xa5)
  216. // OLED_WriteCmd(0xa6); // Disable Inverse Display On (0xa6/a7)
  217. // OLED_WriteCmd(0xaf); // Turn on oled panel
  218. // OLED_FillScreen(0x00); // Clear screen
  219. // OLED_SetPos(0, 0); // Reset origin
  220. // 0.91
  221. OLED_WriteCmd(0xAE);
  222. OLED_WriteCmd(0x20);
  223. OLED_WriteCmd(0x00);
  224. OLED_WriteCmd(0xb0);
  225. OLED_WriteCmd(0xc8);
  226. OLED_WriteCmd(0x00);
  227. OLED_WriteCmd(0x10);
  228. OLED_WriteCmd(0x40);
  229. OLED_WriteCmd(0x81);
  230. OLED_WriteCmd(0xdf);
  231. OLED_WriteCmd(0xa1);
  232. OLED_WriteCmd(0xa6);
  233. OLED_WriteCmd(0xa8);
  234. OLED_WriteCmd(0x1F);
  235. OLED_WriteCmd(0xa4);
  236. OLED_WriteCmd(0xd3);
  237. OLED_WriteCmd(0x00);
  238. OLED_WriteCmd(0xd5);
  239. OLED_WriteCmd(0xf0);
  240. OLED_WriteCmd(0xd9);
  241. OLED_WriteCmd(0x22);
  242. OLED_WriteCmd(0xda);
  243. OLED_WriteCmd(0x12);
  244. OLED_WriteCmd(0xdb);
  245. OLED_WriteCmd(0x20);
  246. OLED_WriteCmd(0x8d);
  247. OLED_WriteCmd(0x14);
  248. OLED_WriteCmd(0xDA);
  249. OLED_WriteCmd(0x02);
  250. OLED_WriteCmd(0xaf);
  251. OLED_FillScreen(0x00); // Clear screen
  252. OLED_SetPos(0, 0); // Reset origin
  253. }
  254. void OLED_DrawChar8x16(uint8_t x, uint8_t y, uint8_t symbol[])
  255. {
  256. uint8_t i = 0;
  257. if(x > 120) // If x large than max width, then move to next line begining
  258. {
  259. x = 0;
  260. y += 2;
  261. }
  262. OLED_SetPos(x, y);
  263. for(i = 0; i < 8; i++)
  264. {
  265. OLED_WriteData(symbol[i]);
  266. }
  267. OLED_SetPos(x, y + 1);
  268. for(i = 0; i < 8; i++)
  269. {
  270. OLED_WriteData(symbol[i + 8]);
  271. }
  272. }
  273. void OLED_DrawChar16x16(uint8_t x, uint8_t y, uint8_t symbol[])
  274. {
  275. uint8_t i = 0;
  276. if(x > 120) // If x large than max width, then move to next line begining
  277. {
  278. x = 0;
  279. y += 2;
  280. }
  281. OLED_SetPos(x, y);
  282. for(i = 0; i < 16; i++)
  283. {
  284. OLED_WriteData(symbol[i]);
  285. }
  286. OLED_SetPos(x, y + 1);
  287. for(i = 0; i < 16; i++)
  288. {
  289. OLED_WriteData(symbol[i + 16]);
  290. }
  291. }
  292. // void OLED_DrawString8x16(uint8_t x, uint8_t y, uint8_t* str, uint8_t len, uint8_t* font)
  293. // {
  294. // uint8_t i = 0;
  295. // for(i = 0; i < len; i++)
  296. // {
  297. // if(x > 120)
  298. // {
  299. // x = 0;
  300. // y += 2;
  301. // }
  302. // if(y > 6)
  303. // break;
  304. // OLED_DrawChar8x16(x, y, font + ((str[i] - 32) * 16));
  305. // x += 8;
  306. // }
  307. // }
  308. uint8_t NumToChar(uint8_t num)
  309. {
  310. if(num >= 0 && num <= 9)
  311. return num + 32 + 16;
  312. return num; // Not a number between 0-9
  313. }
  314. void OLED_DisNumber(uint8_t x, uint8_t y, uint8_t disData)
  315. {
  316. OLED_SetPos(x, y);
  317. OLED_DrawChar8x16(x, y, FontSongTi8x16 + ((NumToChar(disData) - 32) * 16));
  318. }
  319. void OLED_DisValue(uint8_t x, uint8_t y, uint8_t* disData, uint8_t disLength)
  320. {
  321. uint8_t i = 0;
  322. for(i = 0; i < disLength; i++)
  323. {
  324. OLED_SetPos(x, y);
  325. OLED_DrawChar8x16(x, y, FontSongTi8x16 + ((NumToChar(disData[i]) - 32) * 16));
  326. x += 8;
  327. }
  328. }
  329. void OLED_Dis_Welcom(void)
  330. {
  331. uint8_t beginX = 28, beginY = 2;
  332. OLED_DrawString8x16(0, 0, "I. Astrol", FontSongTi8x16);
  333. // OLED_DrawString8x16(0, 16, "HT", 2, FontSongTi8x16);
  334. }
  335. // todo: not tested
  336. #endif /* legacy implementation disabled in Dev refactor */
  337. #endif /* __OLED_SSD1306_ATY_C */