ssd1306xled.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. /**
  2. * SSD1306xLED - Library for the SSD1306 based OLED/PLED 128x64 displays
  3. *
  4. * @author Neven Boyanov
  5. *
  6. * This is part of the Tinusaur/SSD1306xLED project.
  7. *
  8. * Copyright (c) 2018 Neven Boyanov, The Tinusaur Team. All Rights Reserved.
  9. * Distributed as open source software under MIT License, see LICENSE.txt file.
  10. * Retain in your source code the link http://tinusaur.org to the Tinusaur project.
  11. *
  12. * Source code available at: https://bitbucket.org/tinusaur/ssd1306xled
  13. *
  14. */
  15. // ============================================================================
  16. // ACKNOWLEDGEMENTS:
  17. // - Some code and ideas initially based on "IIC_wtihout_ACK"
  18. // by http://www.14blog.com/archives/1358 (defunct)
  19. // - Init sequence used info from Adafruit_SSD1306.cpp init code.
  20. // ============================================================================
  21. #if defined(__GNUC__)
  22. #include <stdlib.h>
  23. #include <avr/io.h>
  24. #include <avr/pgmspace.h>
  25. #elif defined(__ICCAVR__)
  26. # include <ioavr.h>
  27. # include <intrinsics.h>
  28. # include <stdint.h>
  29. #define PROGMEM __flash
  30. #define pgm_read_byte(a) (*(unsigned char __flash *)(a))
  31. #define pgm_read_word(a) (*(unsigned __flash *)(a))
  32. #endif
  33. #include "ssd1306xled.h"
  34. #include "i2c.h"
  35. // ----------------------------------------------------------------------------
  36. void ssd1306_start_command(void); // Initiate transmission of command
  37. void ssd1306_start_data(void); // Initiate transmission of data
  38. void ssd1306_data_byte(uint8_t); // Transmission 1 byte of data
  39. void ssd1306_stop(void); // Finish transmission
  40. // ----------------------------------------------------------------------------
  41. const uint8_t PROGMEM ssd1306_init_sequence [] = { // Initialization Sequence
  42. 0xAE, // Set Display ON/OFF - AE=OFF, AF=ON
  43. 0xD5, 0xF0, // Set display clock divide ratio/oscillator frequency, set divide ratio
  44. 0xA8, 0x3F, // Set multiplex ratio (1 to 64) ... (height - 1)
  45. 0xD3, 0x00, // Set display offset. 00 = no offset
  46. 0x40 | 0x00, // Set start line address, at 0.
  47. 0x8D, 0x14, // Charge Pump Setting, 14h = Enable Charge Pump
  48. 0x20, 0x00, // Set Memory Addressing Mode - 00=Horizontal, 01=Vertical, 10=Page, 11=Invalid
  49. 0xA0 | 0x01, // Set Segment Re-map
  50. 0xC8, // Set COM Output Scan Direction
  51. 0xDA, 0x12, // Set COM Pins Hardware Configuration - 128x32:0x02, 128x64:0x12
  52. 0x81, 0x3F, // Set contrast control register
  53. 0xD9, 0x22, // Set pre-charge period (0x22 or 0xF1)
  54. 0xDB, 0x20, // Set Vcomh Deselect Level - 0x00: 0.65 x VCC, 0x20: 0.77 x VCC (RESET), 0x30: 0.83 x VCC
  55. 0xA4, // Entire Display ON (resume) - output RAM to display
  56. 0xA6, // Set Normal/Inverse Display mode. A6=Normal; A7=Inverse
  57. 0x2E, // Deactivate Scroll command
  58. 0xAF, // Set Display ON/OFF - AE=OFF, AF=ON
  59. //
  60. 0x22, 0x00, 0x3f, // Set Page Address (start,end)
  61. 0x21, 0x00, 0x7f, // Set Column Address (start,end)
  62. //
  63. // 0xD6, 0x01, // Set Zoom In, 0=disabled, 1=enabled
  64. /*
  65. 0xAE, // Display OFF (sleep mode)
  66. 0x20, 0x00, // Set Memory Addressing Mode - 00=Horizontal, 01=Vertical, , 10=Page, 11=Invalid
  67. 0xB0, // Set Page Start Address for Page Addressing Mode, 0-7
  68. 0xC8, // Set COM Output Scan Direction
  69. 0x00, // ---set low column address
  70. 0x10, // ---set high column address
  71. 0x40, // --set start line address
  72. 0x81, 0x3F, // Set contrast control register
  73. 0xA1, // Set Segment Re-map. A0=address mapped; A1=address 127 mapped.
  74. 0xA6, // Set display mode. A6=Normal; A7=Inverse
  75. 0xA8, 0x3F, // Set multiplex ratio(1 to 64)
  76. 0xA4, // Output RAM to Display - 0xA4=Output follows RAM content; 0xA5,Output ignores RAM content
  77. 0xD3, 0x00, // Set display offset. 00 = no offset
  78. 0xD5, 0xF0, // --set display clock divide ratio/oscillator frequency
  79. 0xD9, 0x22, // Set pre-charge period
  80. 0xDA, 0x12, // Set com pins hardware configuration
  81. 0xDB, 0x20, // --set vcomh, 0x20,0.77xVcc
  82. 0x8D, 0x14, // Charge Pump Setting, 14h = Enable Charge Pump
  83. 0xAF, // Display ON in normal mode
  84. */
  85. };
  86. // ============================================================================
  87. // NOTE: These functions are separate sub-library for handling I2C simplified output.
  88. // NAME: I2CSW - I2C Simple Writer.
  89. // Convenience definitions for manipulating PORTB pins
  90. // NOTE: These definitions are used only internally by the I2CSW library
  91. #define I2CSW_HIGH(PORT) PORTB |= (1 << PORT)
  92. #define I2CSW_LOW(PORT) PORTB &= ~(1 << PORT)
  93. // TO-DO: Implement and use the definitions below.
  94. #define I2CSW_SDA_DDI() // Data direction INPUT (0x17 is DDRB)
  95. #define I2CSW_SDA_DDO() // Data direction OUTPUT
  96. #define I2CSW_SDA_HI() // Port to HIGH
  97. #define I2CSW_SDA_LO() // Port to LOW
  98. #define I2CSW_SCL_DDI() // Data direction INPUT
  99. #define I2CSW_SCL_DDO() // Data direction OUTPUTT
  100. #define I2CSW_SCL_HI() // Port to HIGH
  101. #define I2CSW_SCL_LO() // Port to LOW
  102. // IMPORTANT/NOTE: There is no need to use AVR ASM instructions such as "cbi" and "sbi"
  103. // The compiler optimizes the bit-shift operations to those instructions.
  104. // ============================================================================
  105. void ssd1306_start_command(void)
  106. {
  107. I2C_Start();
  108. I2C_WriteByte(SSD1306_SADDR); // Slave address: R/W(SA0)=0 - write
  109. I2C_WriteByte(0x00); // Control byte: D/C=0 - write command
  110. }
  111. void ssd1306_start_data(void)
  112. {
  113. I2C_Start();
  114. I2C_WriteByte(SSD1306_SADDR); // Slave address, R/W(SA0)=0 - write
  115. I2C_WriteByte(0x40); // Control byte: D/C=1 - write data
  116. }
  117. void ssd1306_data_byte(uint8_t b)
  118. {
  119. I2C_WriteByte(b);
  120. }
  121. void ssd1306_stop(void)
  122. {
  123. I2C_Stop();
  124. }
  125. // ============================================================================
  126. void ssd1306_init(void)
  127. {
  128. ssd1306_start_command(); // Initiate transmission of command
  129. for (uint8_t i = 0; i < sizeof (ssd1306_init_sequence); i++) {
  130. ssd1306_data_byte(pgm_read_byte(&ssd1306_init_sequence[i])); // Send the command out
  131. }
  132. ssd1306_stop(); // Finish transmission of data
  133. }
  134. void ssd1306_setpos(uint8_t x, uint8_t y)
  135. {
  136. ssd1306_start_command();
  137. ssd1306_data_byte(0xb0 | (y & 0x07)); // Set page start address
  138. ssd1306_data_byte(x & 0x0f); // Set the lower nibble of the column start address
  139. ssd1306_data_byte(0x10 | (x >> 4)); // Set the higher nibble of the column start address
  140. ssd1306_stop(); // Finish transmission of data
  141. }
  142. void ssd1306_fill(uint8_t p)
  143. {
  144. ssd1306_setpos(0, 0);
  145. ssd1306_start_data(); // Initiate transmission of data
  146. for (uint16_t i = 128 * 8; i > 0; i--) {
  147. ssd1306_data_byte(p);
  148. }
  149. ssd1306_stop(); // Finish transmission of data
  150. }
  151. void ssd1306_fill4(uint8_t p1, uint8_t p2, uint8_t p3, uint8_t p4)
  152. {
  153. ssd1306_setpos(0, 0);
  154. ssd1306_start_data(); // Initiate transmission of data
  155. for (uint16_t i = 0; i < 128 * 8 / 4; i++) {
  156. ssd1306_data_byte(p1);
  157. ssd1306_data_byte(p2);
  158. ssd1306_data_byte(p3);
  159. ssd1306_data_byte(p4);
  160. }
  161. ssd1306_stop(); // Finish transmission of data
  162. }
  163. // ============================================================================