1
0

ssd1306.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. #include "ssd1306.h"
  2. #include "ssd1306_driver.h"
  3. #include "esp_log.h"
  4. #include "stdlib.h"
  5. #include "string.h"
  6. #include "config.h"
  7. #include "fonts.h"
  8. #ifdef ENABLE_SSD1306
  9. static uint8_t SSD1306_Buffer[SSD1306_WIDTH * SSD1306_HEIGHT / 8];
  10. typedef struct {
  11. uint16_t CurrentX;
  12. uint16_t CurrentY;
  13. uint8_t Inverted;
  14. uint8_t Initialized;
  15. } SSD1306_t;
  16. /* Private variable */
  17. static SSD1306_t SSD1306;
  18. void SSD1306_SetPosition(const int x, const int y) {
  19. SSD1306.CurrentX = x;
  20. SSD1306.CurrentY = y;
  21. }
  22. void SSD1306_Clear() {
  23. memset(SSD1306_Buffer,0,SSD1306_WIDTH * SSD1306_HEIGHT / 8);
  24. }
  25. void SSD1306_DrawPixel(uint16_t x, uint16_t y, SSD1306_COLOR_t color) {
  26. if (
  27. x >= SSD1306_WIDTH ||
  28. y >= SSD1306_HEIGHT
  29. ) {
  30. return;
  31. }
  32. if (color == SSD1306_COLOR_WHITE) {
  33. SSD1306_Buffer[x + (y / 8) * SSD1306_WIDTH] |= 1 << (y % 8);
  34. } else {
  35. SSD1306_Buffer[x + (y / 8) * SSD1306_WIDTH] &= ~(1 << (y % 8));
  36. }
  37. }
  38. char SSD1306_Putc(char ch, const FontDef_t* Font, SSD1306_COLOR_t color) {
  39. uint32_t i, b, j;
  40. /* Check available space in LCD */
  41. if (
  42. SSD1306_WIDTH <= (SSD1306.CurrentX + Font->FontWidth) ||
  43. SSD1306_HEIGHT <= (SSD1306.CurrentY + Font->FontHeight)
  44. ) {
  45. /* Error */
  46. return 0;
  47. }
  48. /* Go through font */
  49. for (i = 0; i < Font->FontHeight; i++) {
  50. b = Font->data[(ch - 32) * Font->FontHeight + i];
  51. for (j = 0; j < Font->FontWidth; j++) {
  52. if ((b << j) & 0x8000) {
  53. SSD1306_DrawPixel(SSD1306.CurrentX + j, (SSD1306.CurrentY + i), (SSD1306_COLOR_t) color);
  54. } else {
  55. SSD1306_DrawPixel(SSD1306.CurrentX + j, (SSD1306.CurrentY + i), (SSD1306_COLOR_t)!color);
  56. }
  57. }
  58. }
  59. /* Increase pointer */
  60. SSD1306.CurrentX += Font->FontWidth;
  61. /* Return character written */
  62. return ch;
  63. }
  64. char SSD1306_Puts(char* str, FontDef_t* Font, SSD1306_COLOR_t color) {
  65. /* Write characters */
  66. while (*str) {
  67. /* Write character by character */
  68. if (SSD1306_Putc(*str, Font, color) != *str) {
  69. /* Return error */
  70. return *str;
  71. }
  72. /* Increase string pointer */
  73. str++;
  74. }
  75. /* Everything OK, zero should be returned */
  76. return *str;
  77. }
  78. void SSD1306_DrawVertLine(const uint8_t y, const uint8_t x1, const uint8_t x2) {
  79. for(uint8_t x=x1; x<x2; x++) SSD1306_DrawPixel(x,y,SSD1306_COLOR_WHITE);
  80. }
  81. void SSD1306_UpdateScreen(void) {
  82. uint8_t m;
  83. for (m = 0; m < 8; m++) {
  84. uint8_t configMsg[] = {
  85. PAGE_START_ADDR+m, // set page range:
  86. 0x00, // y / 8
  87. 0x10, // y / 8
  88. };
  89. i2c_tx_cmd(configMsg, sizeof configMsg);
  90. i2c_tx_data(&SSD1306_Buffer[SSD1306_WIDTH * m], SSD1306_WIDTH);
  91. }
  92. }
  93. esp_err_t oled_ssd1306_init() {
  94. i2c_cmd_handle_t cmd = i2c_cmd_link_create();
  95. i2c_master_start(cmd);
  96. i2c_master_write_byte(cmd, (SSD1306_OLED_ADDR << 1) | WRITE_BIT, ACK_CHECK_EN);
  97. // Initialization (page 64)
  98. // The next bytes are commands
  99. i2c_master_write_byte(cmd, COMMAND_MODE, ACK_CHECK_EN);
  100. // Mux Ratio
  101. i2c_master_write_byte(cmd, MULTIPLEX_RATIO, ACK_CHECK_EN);
  102. i2c_master_write_byte(cmd, 0x3F, ACK_CHECK_EN);
  103. // Set display offset
  104. i2c_master_write_byte(cmd, DISPLAY_OFFSET, ACK_CHECK_EN);
  105. i2c_master_write_byte(cmd, 0x00, ACK_CHECK_EN);
  106. // Set display line start
  107. i2c_master_write_byte(cmd, DISPLAY_LINE_START, ACK_CHECK_EN);
  108. i2c_master_write_byte(cmd, 0x00, ACK_CHECK_EN);
  109. // Set Segment re-map
  110. i2c_master_write_byte(cmd, SEGMENT_REMAP, ACK_CHECK_EN);
  111. // Set COM output scan dir
  112. i2c_master_write_byte(cmd, COM_OUTPUT_SCAN_DIR, ACK_CHECK_EN);
  113. i2c_master_write_byte(cmd, 0x00, ACK_CHECK_EN);
  114. // Set COM pins hardware config
  115. i2c_master_write_byte(cmd, COM_PINS_HARDWARE_CONFIG, ACK_CHECK_EN);
  116. i2c_master_write_byte(cmd, 0x12, ACK_CHECK_EN);
  117. // Set contrast Control
  118. i2c_master_write_byte(cmd, CONTRAST_CONTROL, ACK_CHECK_EN);
  119. i2c_master_write_byte(cmd, 0x7F, ACK_CHECK_EN);
  120. i2c_master_write_byte(cmd, DEACTIVATE_SCROLL, ACK_CHECK_EN);
  121. // Disable entire display ON
  122. i2c_master_write_byte(cmd, DISABLE_ENTIRE_DISPLAY, ACK_CHECK_EN);
  123. // Set normal display
  124. i2c_master_write_byte(cmd, NORMAL_DISPLAY, ACK_CHECK_EN);
  125. // Set OSC frequency
  126. i2c_master_write_byte(cmd, DISPLAY_CLK_RATIO, ACK_CHECK_EN);
  127. i2c_master_write_byte(cmd, 0x80, ACK_CHECK_EN);
  128. // Enable charge pump regulator
  129. i2c_master_write_byte(cmd, CHARGE_PUMP_SET, ACK_CHECK_EN);
  130. i2c_master_write_byte(cmd, 0x14, ACK_CHECK_EN);
  131. // Display on
  132. i2c_master_write_byte(cmd, DISPLAY_ON, ACK_CHECK_EN);
  133. // Stop bit
  134. i2c_master_stop(cmd);
  135. esp_err_t ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_RATE_MS);
  136. i2c_cmd_link_delete(cmd);
  137. SSD1306.CurrentX = 0;
  138. SSD1306.CurrentY = 0;
  139. SSD1306.Initialized = 1;
  140. return ret;
  141. }
  142. #endif