ssd1306.c 4.6 KB

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