Adafruit_SSD1306.cpp 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199
  1. /*!
  2. * @file Adafruit_SSD1306.cpp
  3. *
  4. * @mainpage Arduino library for monochrome OLEDs based on SSD1306 drivers.
  5. *
  6. * @section intro_sec Introduction
  7. *
  8. * This is documentation for Adafruit's SSD1306 library for monochrome
  9. * OLED displays: http://www.adafruit.com/category/63_98
  10. *
  11. * These displays use I2C or SPI to communicate. I2C requires 2 pins
  12. * (SCL+SDA) and optionally a RESET pin. SPI requires 4 pins (MOSI, SCK,
  13. * select, data/command) and optionally a reset pin. Hardware SPI or
  14. * 'bitbang' software SPI are both supported.
  15. *
  16. * Adafruit invests time and resources providing this open source code,
  17. * please support Adafruit and open-source hardware by purchasing
  18. * products from Adafruit!
  19. *
  20. * @section dependencies Dependencies
  21. *
  22. * This library depends on <a
  23. * href="https://github.com/adafruit/Adafruit-GFX-Library"> Adafruit_GFX</a>
  24. * being present on your system. Please make sure you have installed the latest
  25. * version before using this library.
  26. *
  27. * @section author Author
  28. *
  29. * Written by Limor Fried/Ladyada for Adafruit Industries, with
  30. * contributions from the open source community.
  31. *
  32. * @section license License
  33. *
  34. * BSD license, all text above, and the splash screen included below,
  35. * must be included in any redistribution.
  36. *
  37. */
  38. #if defined(__AVR__) || defined(ARDUINO_ARCH_RTTHREAD)
  39. #include <avr/pgmspace.h>
  40. #elif defined(ARDUINO_ARDUINO_NANO33BLE) || \
  41. defined(ARDUINO_ARCH_MBED_RP2040) || defined(ARDUINO_ARCH_RP2040)
  42. #include <api/deprecated-avr-comp/avr/pgmspace.h>
  43. #elif defined(ESP8266) || defined(ESP32)
  44. #include <pgmspace.h>
  45. #else
  46. #define pgm_read_byte(addr) \
  47. (*(const unsigned char *)(addr)) ///< PROGMEM workaround for non-AVR
  48. #endif
  49. #if !defined(__ARM_ARCH) && !defined(ENERGIA) && !defined(ESP8266) && \
  50. !defined(ESP32) && !defined(__arc__) && !defined(__RL78__) && \
  51. !defined(CH32V20x) && !defined(PICO_RISCV)
  52. #include <util/delay.h>
  53. #endif
  54. #include "Adafruit_SSD1306.h"
  55. #include "splash.h"
  56. #include <Adafruit_GFX.h>
  57. // SOME DEFINES AND STATIC VARIABLES USED INTERNALLY -----------------------
  58. #if defined(I2C_BUFFER_LENGTH)
  59. #define WIRE_MAX min(256, I2C_BUFFER_LENGTH) ///< Particle or similar Wire lib
  60. #elif defined(BUFFER_LENGTH)
  61. #define WIRE_MAX min(256, BUFFER_LENGTH) ///< AVR or similar Wire lib
  62. #elif defined(SERIAL_BUFFER_SIZE)
  63. #define WIRE_MAX \
  64. min(255, SERIAL_BUFFER_SIZE - 1) ///< Newer Wire uses RingBuffer
  65. #else
  66. #define WIRE_MAX 32 ///< Use common Arduino core default
  67. #endif
  68. #define ssd1306_swap(a, b) \
  69. (((a) ^= (b)), ((b) ^= (a)), ((a) ^= (b))) ///< No-temp-var swap operation
  70. #if ARDUINO >= 100
  71. #define WIRE_WRITE wire->write ///< Wire write function in recent Arduino lib
  72. #else
  73. #define WIRE_WRITE wire->send ///< Wire write function in older Arduino lib
  74. #endif
  75. #ifdef HAVE_PORTREG
  76. #define SSD1306_SELECT *csPort &= ~csPinMask; ///< Device select
  77. #define SSD1306_DESELECT *csPort |= csPinMask; ///< Device deselect
  78. #define SSD1306_MODE_COMMAND *dcPort &= ~dcPinMask; ///< Command mode
  79. #define SSD1306_MODE_DATA *dcPort |= dcPinMask; ///< Data mode
  80. #else
  81. #define SSD1306_SELECT digitalWrite(csPin, LOW); ///< Device select
  82. #define SSD1306_DESELECT digitalWrite(csPin, HIGH); ///< Device deselect
  83. #define SSD1306_MODE_COMMAND digitalWrite(dcPin, LOW); ///< Command mode
  84. #define SSD1306_MODE_DATA digitalWrite(dcPin, HIGH); ///< Data mode
  85. #endif
  86. #if (ARDUINO >= 157) && !defined(ARDUINO_STM32_FEATHER)
  87. #define SETWIRECLOCK wire->setClock(wireClk) ///< Set before I2C transfer
  88. #define RESWIRECLOCK wire->setClock(restoreClk) ///< Restore after I2C xfer
  89. #else // setClock() is not present in older Arduino Wire lib (or WICED)
  90. #define SETWIRECLOCK ///< Dummy stand-in define
  91. #define RESWIRECLOCK ///< keeps compiler happy
  92. #endif
  93. #if defined(SPI_HAS_TRANSACTION)
  94. #define SPI_TRANSACTION_START spi->beginTransaction(spiSettings) ///< Pre-SPI
  95. #define SPI_TRANSACTION_END spi->endTransaction() ///< Post-SPI
  96. #else // SPI transactions likewise not present in older Arduino SPI lib
  97. #define SPI_TRANSACTION_START ///< Dummy stand-in define
  98. #define SPI_TRANSACTION_END ///< keeps compiler happy
  99. #endif
  100. // The definition of 'transaction' is broadened a bit in the context of
  101. // this library -- referring not just to SPI transactions (if supported
  102. // in the version of the SPI library being used), but also chip select
  103. // (if SPI is being used, whether hardware or soft), and also to the
  104. // beginning and end of I2C transfers (the Wire clock may be sped up before
  105. // issuing data to the display, then restored to the default rate afterward
  106. // so other I2C device types still work). All of these are encapsulated
  107. // in the TRANSACTION_* macros.
  108. // Check first if Wire, then hardware SPI, then soft SPI:
  109. #define TRANSACTION_START \
  110. if (wire) { \
  111. SETWIRECLOCK; \
  112. } else { \
  113. if (spi) { \
  114. SPI_TRANSACTION_START; \
  115. } \
  116. SSD1306_SELECT; \
  117. } ///< Wire, SPI or bitbang transfer setup
  118. #define TRANSACTION_END \
  119. if (wire) { \
  120. RESWIRECLOCK; \
  121. } else { \
  122. SSD1306_DESELECT; \
  123. if (spi) { \
  124. SPI_TRANSACTION_END; \
  125. } \
  126. } ///< Wire, SPI or bitbang transfer end
  127. // CONSTRUCTORS, DESTRUCTOR ------------------------------------------------
  128. /*!
  129. @brief Constructor for I2C-interfaced SSD1306 displays.
  130. @param w
  131. Display width in pixels
  132. @param h
  133. Display height in pixels
  134. @param twi
  135. Pointer to an existing TwoWire instance (e.g. &Wire, the
  136. microcontroller's primary I2C bus).
  137. @param rst_pin
  138. Reset pin (using Arduino pin numbering), or -1 if not used
  139. (some displays might be wired to share the microcontroller's
  140. reset pin).
  141. @param clkDuring
  142. Speed (in Hz) for Wire transmissions in SSD1306 library calls.
  143. Defaults to 400000 (400 KHz), a known 'safe' value for most
  144. microcontrollers, and meets the SSD1306 datasheet spec.
  145. Some systems can operate I2C faster (800 KHz for ESP32, 1 MHz
  146. for many other 32-bit MCUs), and some (perhaps not all)
  147. SSD1306's can work with this -- so it's optionally be specified
  148. here and is not a default behavior. (Ignored if using pre-1.5.7
  149. Arduino software, which operates I2C at a fixed 100 KHz.)
  150. @param clkAfter
  151. Speed (in Hz) for Wire transmissions following SSD1306 library
  152. calls. Defaults to 100000 (100 KHz), the default Arduino Wire
  153. speed. This is done rather than leaving it at the 'during' speed
  154. because other devices on the I2C bus might not be compatible
  155. with the faster rate. (Ignored if using pre-1.5.7 Arduino
  156. software, which operates I2C at a fixed 100 KHz.)
  157. @return Adafruit_SSD1306 object.
  158. @note Call the object's begin() function before use -- buffer
  159. allocation is performed there!
  160. */
  161. Adafruit_SSD1306::Adafruit_SSD1306(uint8_t w, uint8_t h, TwoWire *twi,
  162. int8_t rst_pin, uint32_t clkDuring,
  163. uint32_t clkAfter)
  164. : Adafruit_GFX(w, h), spi(NULL), wire(twi ? twi : &Wire), buffer(NULL),
  165. mosiPin(-1), clkPin(-1), dcPin(-1), csPin(-1), rstPin(rst_pin)
  166. #if ARDUINO >= 157
  167. ,
  168. wireClk(clkDuring), restoreClk(clkAfter)
  169. #endif
  170. {
  171. }
  172. /*!
  173. @brief Constructor for SPI SSD1306 displays, using software (bitbang)
  174. SPI.
  175. @param w
  176. Display width in pixels
  177. @param h
  178. Display height in pixels
  179. @param mosi_pin
  180. MOSI (master out, slave in) pin (using Arduino pin numbering).
  181. This transfers serial data from microcontroller to display.
  182. @param sclk_pin
  183. SCLK (serial clock) pin (using Arduino pin numbering).
  184. This clocks each bit from MOSI.
  185. @param dc_pin
  186. Data/command pin (using Arduino pin numbering), selects whether
  187. display is receiving commands (low) or data (high).
  188. @param rst_pin
  189. Reset pin (using Arduino pin numbering), or -1 if not used
  190. (some displays might be wired to share the microcontroller's
  191. reset pin).
  192. @param cs_pin
  193. Chip-select pin (using Arduino pin numbering) for sharing the
  194. bus with other devices. Active low.
  195. @return Adafruit_SSD1306 object.
  196. @note Call the object's begin() function before use -- buffer
  197. allocation is performed there!
  198. */
  199. Adafruit_SSD1306::Adafruit_SSD1306(uint8_t w, uint8_t h, int8_t mosi_pin,
  200. int8_t sclk_pin, int8_t dc_pin,
  201. int8_t rst_pin, int8_t cs_pin)
  202. : Adafruit_GFX(w, h), spi(NULL), wire(NULL), buffer(NULL),
  203. mosiPin(mosi_pin), clkPin(sclk_pin), dcPin(dc_pin), csPin(cs_pin),
  204. rstPin(rst_pin) {}
  205. /*!
  206. @brief Constructor for SPI SSD1306 displays, using native hardware SPI.
  207. @param w
  208. Display width in pixels
  209. @param h
  210. Display height in pixels
  211. @param spi_ptr
  212. Pointer to an existing SPIClass instance (e.g. &SPI, the
  213. microcontroller's primary SPI bus).
  214. @param dc_pin
  215. Data/command pin (using Arduino pin numbering), selects whether
  216. display is receiving commands (low) or data (high).
  217. @param rst_pin
  218. Reset pin (using Arduino pin numbering), or -1 if not used
  219. (some displays might be wired to share the microcontroller's
  220. reset pin).
  221. @param cs_pin
  222. Chip-select pin (using Arduino pin numbering) for sharing the
  223. bus with other devices. Active low.
  224. @param bitrate
  225. SPI clock rate for transfers to this display. Default if
  226. unspecified is 8000000UL (8 MHz).
  227. @return Adafruit_SSD1306 object.
  228. @note Call the object's begin() function before use -- buffer
  229. allocation is performed there!
  230. */
  231. Adafruit_SSD1306::Adafruit_SSD1306(uint8_t w, uint8_t h, SPIClass *spi_ptr,
  232. int8_t dc_pin, int8_t rst_pin, int8_t cs_pin,
  233. uint32_t bitrate)
  234. : Adafruit_GFX(w, h), spi(spi_ptr ? spi_ptr : &SPI), wire(NULL),
  235. buffer(NULL), mosiPin(-1), clkPin(-1), dcPin(dc_pin), csPin(cs_pin),
  236. rstPin(rst_pin) {
  237. #ifdef SPI_HAS_TRANSACTION
  238. spiSettings = SPISettings(bitrate, MSBFIRST, SPI_MODE0);
  239. #endif
  240. }
  241. /*!
  242. @brief DEPRECATED constructor for SPI SSD1306 displays, using software
  243. (bitbang) SPI. Provided for older code to maintain compatibility
  244. with the current library. Screen size is determined by enabling
  245. one of the SSD1306_* size defines in Adafruit_SSD1306.h. New
  246. code should NOT use this.
  247. @param mosi_pin
  248. MOSI (master out, slave in) pin (using Arduino pin numbering).
  249. This transfers serial data from microcontroller to display.
  250. @param sclk_pin
  251. SCLK (serial clock) pin (using Arduino pin numbering).
  252. This clocks each bit from MOSI.
  253. @param dc_pin
  254. Data/command pin (using Arduino pin numbering), selects whether
  255. display is receiving commands (low) or data (high).
  256. @param rst_pin
  257. Reset pin (using Arduino pin numbering), or -1 if not used
  258. (some displays might be wired to share the microcontroller's
  259. reset pin).
  260. @param cs_pin
  261. Chip-select pin (using Arduino pin numbering) for sharing the
  262. bus with other devices. Active low.
  263. @return Adafruit_SSD1306 object.
  264. @note Call the object's begin() function before use -- buffer
  265. allocation is performed there!
  266. */
  267. Adafruit_SSD1306::Adafruit_SSD1306(int8_t mosi_pin, int8_t sclk_pin,
  268. int8_t dc_pin, int8_t rst_pin, int8_t cs_pin)
  269. : Adafruit_GFX(SSD1306_LCDWIDTH, SSD1306_LCDHEIGHT), spi(NULL), wire(NULL),
  270. buffer(NULL), mosiPin(mosi_pin), clkPin(sclk_pin), dcPin(dc_pin),
  271. csPin(cs_pin), rstPin(rst_pin) {}
  272. /*!
  273. @brief DEPRECATED constructor for SPI SSD1306 displays, using native
  274. hardware SPI. Provided for older code to maintain compatibility
  275. with the current library. Screen size is determined by enabling
  276. one of the SSD1306_* size defines in Adafruit_SSD1306.h. New
  277. code should NOT use this. Only the primary SPI bus is supported,
  278. and bitrate is fixed at 8 MHz.
  279. @param dc_pin
  280. Data/command pin (using Arduino pin numbering), selects whether
  281. display is receiving commands (low) or data (high).
  282. @param rst_pin
  283. Reset pin (using Arduino pin numbering), or -1 if not used
  284. (some displays might be wired to share the microcontroller's
  285. reset pin).
  286. @param cs_pin
  287. Chip-select pin (using Arduino pin numbering) for sharing the
  288. bus with other devices. Active low.
  289. @return Adafruit_SSD1306 object.
  290. @note Call the object's begin() function before use -- buffer
  291. allocation is performed there!
  292. */
  293. Adafruit_SSD1306::Adafruit_SSD1306(int8_t dc_pin, int8_t rst_pin, int8_t cs_pin)
  294. : Adafruit_GFX(SSD1306_LCDWIDTH, SSD1306_LCDHEIGHT), spi(&SPI), wire(NULL),
  295. buffer(NULL), mosiPin(-1), clkPin(-1), dcPin(dc_pin), csPin(cs_pin),
  296. rstPin(rst_pin) {
  297. #ifdef SPI_HAS_TRANSACTION
  298. spiSettings = SPISettings(8000000, MSBFIRST, SPI_MODE0);
  299. #endif
  300. }
  301. /*!
  302. @brief DEPRECATED constructor for I2C SSD1306 displays. Provided for
  303. older code to maintain compatibility with the current library.
  304. Screen size is determined by enabling one of the SSD1306_* size
  305. defines in Adafruit_SSD1306.h. New code should NOT use this.
  306. Only the primary I2C bus is supported.
  307. @param rst_pin
  308. Reset pin (using Arduino pin numbering), or -1 if not used
  309. (some displays might be wired to share the microcontroller's
  310. reset pin).
  311. @return Adafruit_SSD1306 object.
  312. @note Call the object's begin() function before use -- buffer
  313. allocation is performed there!
  314. */
  315. Adafruit_SSD1306::Adafruit_SSD1306(int8_t rst_pin)
  316. : Adafruit_GFX(SSD1306_LCDWIDTH, SSD1306_LCDHEIGHT), spi(NULL), wire(&Wire),
  317. buffer(NULL), mosiPin(-1), clkPin(-1), dcPin(-1), csPin(-1),
  318. rstPin(rst_pin) {}
  319. /*!
  320. @brief Destructor for Adafruit_SSD1306 object.
  321. */
  322. Adafruit_SSD1306::~Adafruit_SSD1306(void) {
  323. if (buffer) {
  324. free(buffer);
  325. buffer = NULL;
  326. }
  327. }
  328. // LOW-LEVEL UTILS ---------------------------------------------------------
  329. // Issue single byte out SPI, either soft or hardware as appropriate.
  330. // SPI transaction/selection must be performed in calling function.
  331. /*!
  332. @brief Write a single byte to the SPI port.
  333. @param d
  334. Data byte to be written.
  335. @return void
  336. @note See HAVE_PORTREG which defines if the method uses a port or bit-bang
  337. method
  338. */
  339. inline void Adafruit_SSD1306::SPIwrite(uint8_t d) {
  340. if (spi) {
  341. (void)spi->transfer(d);
  342. } else {
  343. for (uint8_t bit = 0x80; bit; bit >>= 1) {
  344. #ifdef HAVE_PORTREG
  345. if (d & bit)
  346. *mosiPort |= mosiPinMask;
  347. else
  348. *mosiPort &= ~mosiPinMask;
  349. *clkPort |= clkPinMask; // Clock high
  350. *clkPort &= ~clkPinMask; // Clock low
  351. #else
  352. digitalWrite(mosiPin, d & bit);
  353. digitalWrite(clkPin, HIGH);
  354. digitalWrite(clkPin, LOW);
  355. #endif
  356. }
  357. }
  358. }
  359. /*!
  360. @brief Issue single command to SSD1306, using I2C or hard/soft SPI as
  361. needed. Because command calls are often grouped, SPI transaction and
  362. selection must be started/ended in calling function for efficiency. This is a
  363. protected function, not exposed (see ssd1306_command() instead).
  364. @param c
  365. the command character to send to the display.
  366. Refer to ssd1306 data sheet for commands
  367. @return None (void).
  368. @note
  369. */
  370. void Adafruit_SSD1306::ssd1306_command1(uint8_t c) {
  371. if (wire) { // I2C
  372. wire->beginTransmission(i2caddr);
  373. WIRE_WRITE((uint8_t)0x00); // Co = 0, D/C = 0
  374. WIRE_WRITE(c);
  375. wire->endTransmission();
  376. } else { // SPI (hw or soft) -- transaction started in calling function
  377. SSD1306_MODE_COMMAND
  378. SPIwrite(c);
  379. }
  380. }
  381. /*!
  382. @brief Issue list of commands to SSD1306, same rules as above re:
  383. transactions. This is a protected function, not exposed.
  384. @param c
  385. pointer to list of commands
  386. @param n
  387. number of commands in the list
  388. @return None (void).
  389. @note
  390. */
  391. void Adafruit_SSD1306::ssd1306_commandList(const uint8_t *c, uint8_t n) {
  392. if (wire) { // I2C
  393. wire->beginTransmission(i2caddr);
  394. WIRE_WRITE((uint8_t)0x00); // Co = 0, D/C = 0
  395. uint16_t bytesOut = 1;
  396. while (n--) {
  397. if (bytesOut >= WIRE_MAX) {
  398. wire->endTransmission();
  399. wire->beginTransmission(i2caddr);
  400. WIRE_WRITE((uint8_t)0x00); // Co = 0, D/C = 0
  401. bytesOut = 1;
  402. }
  403. WIRE_WRITE(pgm_read_byte(c++));
  404. bytesOut++;
  405. }
  406. wire->endTransmission();
  407. } else { // SPI -- transaction started in calling function
  408. SSD1306_MODE_COMMAND
  409. while (n--)
  410. SPIwrite(pgm_read_byte(c++));
  411. }
  412. }
  413. // A public version of ssd1306_command1(), for existing user code that
  414. // might rely on that function. This encapsulates the command transfer
  415. // in a transaction start/end, similar to old library's handling of it.
  416. /*!
  417. @brief Issue a single low-level command directly to the SSD1306
  418. display, bypassing the library.
  419. @param c
  420. Command to issue (0x00 to 0xFF, see datasheet).
  421. @return None (void).
  422. */
  423. void Adafruit_SSD1306::ssd1306_command(uint8_t c) {
  424. TRANSACTION_START
  425. ssd1306_command1(c);
  426. TRANSACTION_END
  427. }
  428. // ALLOCATE & INIT DISPLAY -------------------------------------------------
  429. /*!
  430. @brief Allocate RAM for image buffer, initialize peripherals and pins.
  431. @param vcs
  432. VCC selection. Pass SSD1306_SWITCHCAPVCC to generate the display
  433. voltage (step up) from the 3.3V source, or SSD1306_EXTERNALVCC
  434. otherwise. Most situations with Adafruit SSD1306 breakouts will
  435. want SSD1306_SWITCHCAPVCC.
  436. @param addr
  437. I2C address of corresponding SSD1306 display (or pass 0 to use
  438. default of 0x3C for 128x32 display, 0x3D for all others).
  439. SPI displays (hardware or software) do not use addresses, but
  440. this argument is still required (pass 0 or any value really,
  441. it will simply be ignored). Default if unspecified is 0.
  442. @param reset
  443. If true, and if the reset pin passed to the constructor is
  444. valid, a hard reset will be performed before initializing the
  445. display. If using multiple SSD1306 displays on the same bus, and
  446. if they all share the same reset pin, you should only pass true
  447. on the first display being initialized, false on all others,
  448. else the already-initialized displays would be reset. Default if
  449. unspecified is true.
  450. @param periphBegin
  451. If true, and if a hardware peripheral is being used (I2C or SPI,
  452. but not software SPI), call that peripheral's begin() function,
  453. else (false) it has already been done in one's sketch code.
  454. Cases where false might be used include multiple displays or
  455. other devices sharing a common bus, or situations on some
  456. platforms where a nonstandard begin() function is available
  457. (e.g. a TwoWire interface on non-default pins, as can be done
  458. on the ESP8266 and perhaps others).
  459. @return true on successful allocation/init, false otherwise.
  460. Well-behaved code should check the return value before
  461. proceeding.
  462. @note MUST call this function before any drawing or updates!
  463. */
  464. bool Adafruit_SSD1306::begin(uint8_t vcs, uint8_t addr, bool reset,
  465. bool periphBegin) {
  466. if ((!buffer) && !(buffer = (uint8_t *)malloc(WIDTH * ((HEIGHT + 7) / 8))))
  467. return false;
  468. clearDisplay();
  469. #ifndef SSD1306_NO_SPLASH
  470. if (HEIGHT > 32) {
  471. drawBitmap((WIDTH - splash1_width) / 2, (HEIGHT - splash1_height) / 2,
  472. splash1_data, splash1_width, splash1_height, 1);
  473. } else {
  474. drawBitmap((WIDTH - splash2_width) / 2, (HEIGHT - splash2_height) / 2,
  475. splash2_data, splash2_width, splash2_height, 1);
  476. }
  477. #endif
  478. vccstate = vcs;
  479. // Setup pin directions
  480. if (wire) { // Using I2C
  481. // If I2C address is unspecified, use default
  482. // (0x3C for 32-pixel-tall displays, 0x3D for all others).
  483. i2caddr = addr ? addr : ((HEIGHT == 32) ? 0x3C : 0x3D);
  484. // TwoWire begin() function might be already performed by the calling
  485. // function if it has unusual circumstances (e.g. TWI variants that
  486. // can accept different SDA/SCL pins, or if two SSD1306 instances
  487. // with different addresses -- only a single begin() is needed).
  488. if (periphBegin)
  489. wire->begin();
  490. } else { // Using one of the SPI modes, either soft or hardware
  491. pinMode(dcPin, OUTPUT); // Set data/command pin as output
  492. pinMode(csPin, OUTPUT); // Same for chip select
  493. #ifdef HAVE_PORTREG
  494. dcPort = (PortReg *)portOutputRegister(digitalPinToPort(dcPin));
  495. dcPinMask = digitalPinToBitMask(dcPin);
  496. csPort = (PortReg *)portOutputRegister(digitalPinToPort(csPin));
  497. csPinMask = digitalPinToBitMask(csPin);
  498. #endif
  499. SSD1306_DESELECT
  500. if (spi) { // Hardware SPI
  501. // SPI peripheral begin same as wire check above.
  502. if (periphBegin)
  503. spi->begin();
  504. } else { // Soft SPI
  505. pinMode(mosiPin, OUTPUT); // MOSI and SCLK outputs
  506. pinMode(clkPin, OUTPUT);
  507. #ifdef HAVE_PORTREG
  508. mosiPort = (PortReg *)portOutputRegister(digitalPinToPort(mosiPin));
  509. mosiPinMask = digitalPinToBitMask(mosiPin);
  510. clkPort = (PortReg *)portOutputRegister(digitalPinToPort(clkPin));
  511. clkPinMask = digitalPinToBitMask(clkPin);
  512. *clkPort &= ~clkPinMask; // Clock low
  513. #else
  514. digitalWrite(clkPin, LOW); // Clock low
  515. #endif
  516. }
  517. }
  518. // Reset SSD1306 if requested and reset pin specified in constructor
  519. if (reset && (rstPin >= 0)) {
  520. pinMode(rstPin, OUTPUT);
  521. digitalWrite(rstPin, HIGH);
  522. delay(1); // VDD goes high at start, pause for 1 ms
  523. digitalWrite(rstPin, LOW); // Bring reset low
  524. delay(10); // Wait 10 ms
  525. digitalWrite(rstPin, HIGH); // Bring out of reset
  526. }
  527. TRANSACTION_START
  528. // Init sequence
  529. static const uint8_t PROGMEM init1[] = {SSD1306_DISPLAYOFF, // 0xAE
  530. SSD1306_SETDISPLAYCLOCKDIV, // 0xD5
  531. 0x80, // the suggested ratio 0x80
  532. SSD1306_SETMULTIPLEX}; // 0xA8
  533. ssd1306_commandList(init1, sizeof(init1));
  534. ssd1306_command1(HEIGHT - 1);
  535. static const uint8_t PROGMEM init2[] = {SSD1306_SETDISPLAYOFFSET, // 0xD3
  536. 0x0, // no offset
  537. SSD1306_SETSTARTLINE | 0x0, // line #0
  538. SSD1306_CHARGEPUMP}; // 0x8D
  539. ssd1306_commandList(init2, sizeof(init2));
  540. ssd1306_command1((vccstate == SSD1306_EXTERNALVCC) ? 0x10 : 0x14);
  541. static const uint8_t PROGMEM init3[] = {SSD1306_MEMORYMODE, // 0x20
  542. 0x00, // 0x0 act like ks0108
  543. SSD1306_SEGREMAP | 0x1,
  544. SSD1306_COMSCANDEC};
  545. ssd1306_commandList(init3, sizeof(init3));
  546. uint8_t comPins = 0x02;
  547. contrast = 0x8F;
  548. if ((WIDTH == 128) && (HEIGHT == 32)) {
  549. comPins = 0x02;
  550. contrast = 0x8F;
  551. } else if ((WIDTH == 128) && (HEIGHT == 64)) {
  552. comPins = 0x12;
  553. contrast = (vccstate == SSD1306_EXTERNALVCC) ? 0x9F : 0xCF;
  554. } else if ((WIDTH == 96) && (HEIGHT == 16)) {
  555. comPins = 0x2; // ada x12
  556. contrast = (vccstate == SSD1306_EXTERNALVCC) ? 0x10 : 0xAF;
  557. } else if ((WIDTH == 64) && (HEIGHT == 32)) {
  558. comPins = 0x12; // ada x12
  559. contrast = (vccstate == SSD1306_EXTERNALVCC) ? 0x10 : 0xCF;
  560. } else {
  561. // Other screen varieties -- TBD
  562. }
  563. ssd1306_command1(SSD1306_SETCOMPINS);
  564. ssd1306_command1(comPins);
  565. ssd1306_command1(SSD1306_SETCONTRAST);
  566. ssd1306_command1(contrast);
  567. ssd1306_command1(SSD1306_SETPRECHARGE); // 0xd9
  568. ssd1306_command1((vccstate == SSD1306_EXTERNALVCC) ? 0x22 : 0xF1);
  569. static const uint8_t PROGMEM init5[] = {
  570. SSD1306_SETVCOMDETECT, // 0xDB
  571. 0x40,
  572. SSD1306_DISPLAYALLON_RESUME, // 0xA4
  573. SSD1306_NORMALDISPLAY, // 0xA6
  574. SSD1306_DEACTIVATE_SCROLL,
  575. SSD1306_DISPLAYON}; // Main screen turn on
  576. ssd1306_commandList(init5, sizeof(init5));
  577. TRANSACTION_END
  578. return true; // Success
  579. }
  580. // DRAWING FUNCTIONS -------------------------------------------------------
  581. /*!
  582. @brief Set/clear/invert a single pixel. This is also invoked by the
  583. Adafruit_GFX library in generating many higher-level graphics
  584. primitives.
  585. @param x
  586. Column of display -- 0 at left to (screen width - 1) at right.
  587. @param y
  588. Row of display -- 0 at top to (screen height -1) at bottom.
  589. @param color
  590. Pixel color, one of: SSD1306_BLACK, SSD1306_WHITE or
  591. SSD1306_INVERSE.
  592. @return None (void).
  593. @note Changes buffer contents only, no immediate effect on display.
  594. Follow up with a call to display(), or with other graphics
  595. commands as needed by one's own application.
  596. */
  597. void Adafruit_SSD1306::drawPixel(int16_t x, int16_t y, uint16_t color) {
  598. if ((x >= 0) && (x < width()) && (y >= 0) && (y < height())) {
  599. // Pixel is in-bounds. Rotate coordinates if needed.
  600. switch (getRotation()) {
  601. case 1:
  602. ssd1306_swap(x, y);
  603. x = WIDTH - x - 1;
  604. break;
  605. case 2:
  606. x = WIDTH - x - 1;
  607. y = HEIGHT - y - 1;
  608. break;
  609. case 3:
  610. ssd1306_swap(x, y);
  611. y = HEIGHT - y - 1;
  612. break;
  613. }
  614. switch (color) {
  615. case SSD1306_WHITE:
  616. buffer[x + (y / 8) * WIDTH] |= (1 << (y & 7));
  617. break;
  618. case SSD1306_BLACK:
  619. buffer[x + (y / 8) * WIDTH] &= ~(1 << (y & 7));
  620. break;
  621. case SSD1306_INVERSE:
  622. buffer[x + (y / 8) * WIDTH] ^= (1 << (y & 7));
  623. break;
  624. }
  625. }
  626. }
  627. /*!
  628. @brief Clear contents of display buffer (set all pixels to off).
  629. @return None (void).
  630. @note Changes buffer contents only, no immediate effect on display.
  631. Follow up with a call to display(), or with other graphics
  632. commands as needed by one's own application.
  633. */
  634. void Adafruit_SSD1306::clearDisplay(void) {
  635. memset(buffer, 0, WIDTH * ((HEIGHT + 7) / 8));
  636. }
  637. /*!
  638. @brief Draw a horizontal line. This is also invoked by the Adafruit_GFX
  639. library in generating many higher-level graphics primitives.
  640. @param x
  641. Leftmost column -- 0 at left to (screen width - 1) at right.
  642. @param y
  643. Row of display -- 0 at top to (screen height -1) at bottom.
  644. @param w
  645. Width of line, in pixels.
  646. @param color
  647. Line color, one of: SSD1306_BLACK, SSD1306_WHITE or SSD1306_INVERSE.
  648. @return None (void).
  649. @note Changes buffer contents only, no immediate effect on display.
  650. Follow up with a call to display(), or with other graphics
  651. commands as needed by one's own application.
  652. */
  653. void Adafruit_SSD1306::drawFastHLine(int16_t x, int16_t y, int16_t w,
  654. uint16_t color) {
  655. bool bSwap = false;
  656. switch (rotation) {
  657. case 1:
  658. // 90 degree rotation, swap x & y for rotation, then invert x
  659. bSwap = true;
  660. ssd1306_swap(x, y);
  661. x = WIDTH - x - 1;
  662. break;
  663. case 2:
  664. // 180 degree rotation, invert x and y, then shift y around for height.
  665. x = WIDTH - x - 1;
  666. y = HEIGHT - y - 1;
  667. x -= (w - 1);
  668. break;
  669. case 3:
  670. // 270 degree rotation, swap x & y for rotation,
  671. // then invert y and adjust y for w (not to become h)
  672. bSwap = true;
  673. ssd1306_swap(x, y);
  674. y = HEIGHT - y - 1;
  675. y -= (w - 1);
  676. break;
  677. }
  678. if (bSwap)
  679. drawFastVLineInternal(x, y, w, color);
  680. else
  681. drawFastHLineInternal(x, y, w, color);
  682. }
  683. /*!
  684. @brief Draw a horizontal line with a width and color. Used by public
  685. methods drawFastHLine,drawFastVLine
  686. @param x
  687. Leftmost column -- 0 at left to (screen width - 1) at right.
  688. @param y
  689. Row of display -- 0 at top to (screen height -1) at bottom.
  690. @param w
  691. Width of line, in pixels.
  692. @param color
  693. Line color, one of: SSD1306_BLACK, SSD1306_WHITE or
  694. SSD1306_INVERSE.
  695. @return None (void).
  696. @note Changes buffer contents only, no immediate effect on display.
  697. Follow up with a call to display(), or with other graphics
  698. commands as needed by one's own application.
  699. */
  700. void Adafruit_SSD1306::drawFastHLineInternal(int16_t x, int16_t y, int16_t w,
  701. uint16_t color) {
  702. if ((y >= 0) && (y < HEIGHT)) { // Y coord in bounds?
  703. if (x < 0) { // Clip left
  704. w += x;
  705. x = 0;
  706. }
  707. if ((x + w) > WIDTH) { // Clip right
  708. w = (WIDTH - x);
  709. }
  710. if (w > 0) { // Proceed only if width is positive
  711. uint8_t *pBuf = &buffer[(y / 8) * WIDTH + x], mask = 1 << (y & 7);
  712. switch (color) {
  713. case SSD1306_WHITE:
  714. while (w--) {
  715. *pBuf++ |= mask;
  716. };
  717. break;
  718. case SSD1306_BLACK:
  719. mask = ~mask;
  720. while (w--) {
  721. *pBuf++ &= mask;
  722. };
  723. break;
  724. case SSD1306_INVERSE:
  725. while (w--) {
  726. *pBuf++ ^= mask;
  727. };
  728. break;
  729. }
  730. }
  731. }
  732. }
  733. /*!
  734. @brief Draw a vertical line. This is also invoked by the Adafruit_GFX
  735. library in generating many higher-level graphics primitives.
  736. @param x
  737. Column of display -- 0 at left to (screen width -1) at right.
  738. @param y
  739. Topmost row -- 0 at top to (screen height - 1) at bottom.
  740. @param h
  741. Height of line, in pixels.
  742. @param color
  743. Line color, one of: SSD1306_BLACK, SSD1306_WHITE or SSD1306_INVERSE.
  744. @return None (void).
  745. @note Changes buffer contents only, no immediate effect on display.
  746. Follow up with a call to display(), or with other graphics
  747. commands as needed by one's own application.
  748. */
  749. void Adafruit_SSD1306::drawFastVLine(int16_t x, int16_t y, int16_t h,
  750. uint16_t color) {
  751. bool bSwap = false;
  752. switch (rotation) {
  753. case 1:
  754. // 90 degree rotation, swap x & y for rotation,
  755. // then invert x and adjust x for h (now to become w)
  756. bSwap = true;
  757. ssd1306_swap(x, y);
  758. x = WIDTH - x - 1;
  759. x -= (h - 1);
  760. break;
  761. case 2:
  762. // 180 degree rotation, invert x and y, then shift y around for height.
  763. x = WIDTH - x - 1;
  764. y = HEIGHT - y - 1;
  765. y -= (h - 1);
  766. break;
  767. case 3:
  768. // 270 degree rotation, swap x & y for rotation, then invert y
  769. bSwap = true;
  770. ssd1306_swap(x, y);
  771. y = HEIGHT - y - 1;
  772. break;
  773. }
  774. if (bSwap)
  775. drawFastHLineInternal(x, y, h, color);
  776. else
  777. drawFastVLineInternal(x, y, h, color);
  778. }
  779. /*!
  780. @brief Draw a vertical line with a width and color. Used by public method
  781. drawFastHLine,drawFastVLine
  782. @param x
  783. Leftmost column -- 0 at left to (screen width - 1) at right.
  784. @param __y
  785. Row of display -- 0 at top to (screen height -1) at bottom.
  786. @param __h height of the line in pixels
  787. @param color
  788. Line color, one of: SSD1306_BLACK, SSD1306_WHITE or
  789. SSD1306_INVERSE.
  790. @return None (void).
  791. @note Changes buffer contents only, no immediate effect on display.
  792. Follow up with a call to display(), or with other graphics
  793. commands as needed by one's own application.
  794. */
  795. void Adafruit_SSD1306::drawFastVLineInternal(int16_t x, int16_t __y,
  796. int16_t __h, uint16_t color) {
  797. if ((x >= 0) && (x < WIDTH)) { // X coord in bounds?
  798. if (__y < 0) { // Clip top
  799. __h += __y;
  800. __y = 0;
  801. }
  802. if ((__y + __h) > HEIGHT) { // Clip bottom
  803. __h = (HEIGHT - __y);
  804. }
  805. if (__h > 0) { // Proceed only if height is now positive
  806. // this display doesn't need ints for coordinates,
  807. // use local byte registers for faster juggling
  808. uint8_t y = __y, h = __h;
  809. uint8_t *pBuf = &buffer[(y / 8) * WIDTH + x];
  810. // do the first partial byte, if necessary - this requires some masking
  811. uint8_t mod = (y & 7);
  812. if (mod) {
  813. // mask off the high n bits we want to set
  814. mod = 8 - mod;
  815. // note - lookup table results in a nearly 10% performance
  816. // improvement in fill* functions
  817. // uint8_t mask = ~(0xFF >> mod);
  818. static const uint8_t PROGMEM premask[8] = {0x00, 0x80, 0xC0, 0xE0,
  819. 0xF0, 0xF8, 0xFC, 0xFE};
  820. uint8_t mask = pgm_read_byte(&premask[mod]);
  821. // adjust the mask if we're not going to reach the end of this byte
  822. if (h < mod)
  823. mask &= (0XFF >> (mod - h));
  824. switch (color) {
  825. case SSD1306_WHITE:
  826. *pBuf |= mask;
  827. break;
  828. case SSD1306_BLACK:
  829. *pBuf &= ~mask;
  830. break;
  831. case SSD1306_INVERSE:
  832. *pBuf ^= mask;
  833. break;
  834. }
  835. pBuf += WIDTH;
  836. }
  837. if (h >= mod) { // More to go?
  838. h -= mod;
  839. // Write solid bytes while we can - effectively 8 rows at a time
  840. if (h >= 8) {
  841. if (color == SSD1306_INVERSE) {
  842. // separate copy of the code so we don't impact performance of
  843. // black/white write version with an extra comparison per loop
  844. do {
  845. *pBuf ^= 0xFF; // Invert byte
  846. pBuf += WIDTH; // Advance pointer 8 rows
  847. h -= 8; // Subtract 8 rows from height
  848. } while (h >= 8);
  849. } else {
  850. // store a local value to work with
  851. uint8_t val = (color != SSD1306_BLACK) ? 255 : 0;
  852. do {
  853. *pBuf = val; // Set byte
  854. pBuf += WIDTH; // Advance pointer 8 rows
  855. h -= 8; // Subtract 8 rows from height
  856. } while (h >= 8);
  857. }
  858. }
  859. if (h) { // Do the final partial byte, if necessary
  860. mod = h & 7;
  861. // this time we want to mask the low bits of the byte,
  862. // vs the high bits we did above
  863. // uint8_t mask = (1 << mod) - 1;
  864. // note - lookup table results in a nearly 10% performance
  865. // improvement in fill* functions
  866. static const uint8_t PROGMEM postmask[8] = {0x00, 0x01, 0x03, 0x07,
  867. 0x0F, 0x1F, 0x3F, 0x7F};
  868. uint8_t mask = pgm_read_byte(&postmask[mod]);
  869. switch (color) {
  870. case SSD1306_WHITE:
  871. *pBuf |= mask;
  872. break;
  873. case SSD1306_BLACK:
  874. *pBuf &= ~mask;
  875. break;
  876. case SSD1306_INVERSE:
  877. *pBuf ^= mask;
  878. break;
  879. }
  880. }
  881. }
  882. } // endif positive height
  883. } // endif x in bounds
  884. }
  885. /*!
  886. @brief Return color of a single pixel in display buffer.
  887. @param x
  888. Column of display -- 0 at left to (screen width - 1) at right.
  889. @param y
  890. Row of display -- 0 at top to (screen height -1) at bottom.
  891. @return true if pixel is set (usually SSD1306_WHITE, unless display invert
  892. mode is enabled), false if clear (SSD1306_BLACK).
  893. @note Reads from buffer contents; may not reflect current contents of
  894. screen if display() has not been called.
  895. */
  896. bool Adafruit_SSD1306::getPixel(int16_t x, int16_t y) {
  897. if ((x >= 0) && (x < width()) && (y >= 0) && (y < height())) {
  898. // Pixel is in-bounds. Rotate coordinates if needed.
  899. switch (getRotation()) {
  900. case 1:
  901. ssd1306_swap(x, y);
  902. x = WIDTH - x - 1;
  903. break;
  904. case 2:
  905. x = WIDTH - x - 1;
  906. y = HEIGHT - y - 1;
  907. break;
  908. case 3:
  909. ssd1306_swap(x, y);
  910. y = HEIGHT - y - 1;
  911. break;
  912. }
  913. return (buffer[x + (y / 8) * WIDTH] & (1 << (y & 7)));
  914. }
  915. return false; // Pixel out of bounds
  916. }
  917. /*!
  918. @brief Get base address of display buffer for direct reading or writing.
  919. @return Pointer to an unsigned 8-bit array, column-major, columns padded
  920. to full byte boundary if needed.
  921. */
  922. uint8_t *Adafruit_SSD1306::getBuffer(void) { return buffer; }
  923. // REFRESH DISPLAY ---------------------------------------------------------
  924. /*!
  925. @brief Push data currently in RAM to SSD1306 display.
  926. @return None (void).
  927. @note Drawing operations are not visible until this function is
  928. called. Call after each graphics command, or after a whole set
  929. of graphics commands, as best needed by one's own application.
  930. */
  931. void Adafruit_SSD1306::display(void) {
  932. TRANSACTION_START
  933. static const uint8_t PROGMEM dlist1[] = {
  934. SSD1306_PAGEADDR,
  935. 0, // Page start address
  936. 0xFF, // Page end (not really, but works here)
  937. SSD1306_COLUMNADDR}; // Column start address
  938. ssd1306_commandList(dlist1, sizeof(dlist1));
  939. if (WIDTH == 64) {
  940. ssd1306_command1(0x20); // Column start
  941. ssd1306_command1(0x20 + WIDTH - 1); // Column end address
  942. } else {
  943. ssd1306_command1(0); // Column start
  944. ssd1306_command1((WIDTH - 1)); // Column end address
  945. }
  946. #if defined(ESP8266)
  947. // ESP8266 needs a periodic yield() call to avoid watchdog reset.
  948. // With the limited size of SSD1306 displays, and the fast bitrate
  949. // being used (1 MHz or more), I think one yield() immediately before
  950. // a screen write and one immediately after should cover it. But if
  951. // not, if this becomes a problem, yields() might be added in the
  952. // 32-byte transfer condition below.
  953. yield();
  954. #endif
  955. uint16_t count = WIDTH * ((HEIGHT + 7) / 8);
  956. uint8_t *ptr = buffer;
  957. if (wire) { // I2C
  958. wire->beginTransmission(i2caddr);
  959. WIRE_WRITE((uint8_t)0x40);
  960. uint16_t bytesOut = 1;
  961. while (count--) {
  962. if (bytesOut >= WIRE_MAX) {
  963. wire->endTransmission();
  964. wire->beginTransmission(i2caddr);
  965. WIRE_WRITE((uint8_t)0x40);
  966. bytesOut = 1;
  967. }
  968. WIRE_WRITE(*ptr++);
  969. bytesOut++;
  970. }
  971. wire->endTransmission();
  972. } else { // SPI
  973. SSD1306_MODE_DATA
  974. while (count--)
  975. SPIwrite(*ptr++);
  976. }
  977. TRANSACTION_END
  978. #if defined(ESP8266)
  979. yield();
  980. #endif
  981. }
  982. // SCROLLING FUNCTIONS -----------------------------------------------------
  983. /*!
  984. @brief Activate a right-handed scroll for all or part of the display.
  985. @param start
  986. First row.
  987. @param stop
  988. Last row.
  989. @return None (void).
  990. */
  991. // To scroll the whole display, run: display.startscrollright(0x00, 0x0F)
  992. void Adafruit_SSD1306::startscrollright(uint8_t start, uint8_t stop) {
  993. TRANSACTION_START
  994. static const uint8_t PROGMEM scrollList1a[] = {
  995. SSD1306_RIGHT_HORIZONTAL_SCROLL, 0X00};
  996. ssd1306_commandList(scrollList1a, sizeof(scrollList1a));
  997. ssd1306_command1(start);
  998. ssd1306_command1(0X00);
  999. ssd1306_command1(stop);
  1000. static const uint8_t PROGMEM scrollList1b[] = {0X00, 0XFF,
  1001. SSD1306_ACTIVATE_SCROLL};
  1002. ssd1306_commandList(scrollList1b, sizeof(scrollList1b));
  1003. TRANSACTION_END
  1004. }
  1005. /*!
  1006. @brief Activate a left-handed scroll for all or part of the display.
  1007. @param start
  1008. First row.
  1009. @param stop
  1010. Last row.
  1011. @return None (void).
  1012. */
  1013. // To scroll the whole display, run: display.startscrollleft(0x00, 0x0F)
  1014. void Adafruit_SSD1306::startscrollleft(uint8_t start, uint8_t stop) {
  1015. TRANSACTION_START
  1016. static const uint8_t PROGMEM scrollList2a[] = {SSD1306_LEFT_HORIZONTAL_SCROLL,
  1017. 0X00};
  1018. ssd1306_commandList(scrollList2a, sizeof(scrollList2a));
  1019. ssd1306_command1(start);
  1020. ssd1306_command1(0X00);
  1021. ssd1306_command1(stop);
  1022. static const uint8_t PROGMEM scrollList2b[] = {0X00, 0XFF,
  1023. SSD1306_ACTIVATE_SCROLL};
  1024. ssd1306_commandList(scrollList2b, sizeof(scrollList2b));
  1025. TRANSACTION_END
  1026. }
  1027. /*!
  1028. @brief Activate a diagonal scroll for all or part of the display.
  1029. @param start
  1030. First row.
  1031. @param stop
  1032. Last row.
  1033. @return None (void).
  1034. */
  1035. // display.startscrolldiagright(0x00, 0x0F)
  1036. void Adafruit_SSD1306::startscrolldiagright(uint8_t start, uint8_t stop) {
  1037. TRANSACTION_START
  1038. static const uint8_t PROGMEM scrollList3a[] = {
  1039. SSD1306_SET_VERTICAL_SCROLL_AREA, 0X00};
  1040. ssd1306_commandList(scrollList3a, sizeof(scrollList3a));
  1041. ssd1306_command1(HEIGHT);
  1042. static const uint8_t PROGMEM scrollList3b[] = {
  1043. SSD1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL, 0X00};
  1044. ssd1306_commandList(scrollList3b, sizeof(scrollList3b));
  1045. ssd1306_command1(start);
  1046. ssd1306_command1(0X00);
  1047. ssd1306_command1(stop);
  1048. static const uint8_t PROGMEM scrollList3c[] = {0X01, SSD1306_ACTIVATE_SCROLL};
  1049. ssd1306_commandList(scrollList3c, sizeof(scrollList3c));
  1050. TRANSACTION_END
  1051. }
  1052. /*!
  1053. @brief Activate alternate diagonal scroll for all or part of the display.
  1054. @param start
  1055. First row.
  1056. @param stop
  1057. Last row.
  1058. @return None (void).
  1059. */
  1060. // To scroll the whole display, run: display.startscrolldiagleft(0x00, 0x0F)
  1061. void Adafruit_SSD1306::startscrolldiagleft(uint8_t start, uint8_t stop) {
  1062. TRANSACTION_START
  1063. static const uint8_t PROGMEM scrollList4a[] = {
  1064. SSD1306_SET_VERTICAL_SCROLL_AREA, 0X00};
  1065. ssd1306_commandList(scrollList4a, sizeof(scrollList4a));
  1066. ssd1306_command1(HEIGHT);
  1067. static const uint8_t PROGMEM scrollList4b[] = {
  1068. SSD1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL, 0X00};
  1069. ssd1306_commandList(scrollList4b, sizeof(scrollList4b));
  1070. ssd1306_command1(start);
  1071. ssd1306_command1(0X00);
  1072. ssd1306_command1(stop);
  1073. static const uint8_t PROGMEM scrollList4c[] = {0X01, SSD1306_ACTIVATE_SCROLL};
  1074. ssd1306_commandList(scrollList4c, sizeof(scrollList4c));
  1075. TRANSACTION_END
  1076. }
  1077. /*!
  1078. @brief Cease a previously-begun scrolling action.
  1079. @return None (void).
  1080. */
  1081. void Adafruit_SSD1306::stopscroll(void) {
  1082. TRANSACTION_START
  1083. ssd1306_command1(SSD1306_DEACTIVATE_SCROLL);
  1084. TRANSACTION_END
  1085. }
  1086. // OTHER HARDWARE SETTINGS -------------------------------------------------
  1087. /*!
  1088. @brief Enable or disable display invert mode (white-on-black vs
  1089. black-on-white).
  1090. @param i
  1091. If true, switch to invert mode (black-on-white), else normal
  1092. mode (white-on-black).
  1093. @return None (void).
  1094. @note This has an immediate effect on the display, no need to call the
  1095. display() function -- buffer contents are not changed, rather a
  1096. different pixel mode of the display hardware is used. When
  1097. enabled, drawing SSD1306_BLACK (value 0) pixels will actually draw
  1098. white, SSD1306_WHITE (value 1) will draw black.
  1099. */
  1100. void Adafruit_SSD1306::invertDisplay(bool i) {
  1101. TRANSACTION_START
  1102. ssd1306_command1(i ? SSD1306_INVERTDISPLAY : SSD1306_NORMALDISPLAY);
  1103. TRANSACTION_END
  1104. }
  1105. /*!
  1106. @brief Dim the display.
  1107. @param dim
  1108. true to enable lower brightness mode, false for full brightness.
  1109. @return None (void).
  1110. @note This has an immediate effect on the display, no need to call the
  1111. display() function -- buffer contents are not changed.
  1112. */
  1113. void Adafruit_SSD1306::dim(bool dim) {
  1114. // the range of contrast to too small to be really useful
  1115. // it is useful to dim the display
  1116. TRANSACTION_START
  1117. ssd1306_command1(SSD1306_SETCONTRAST);
  1118. ssd1306_command1(dim ? 0 : contrast);
  1119. TRANSACTION_END
  1120. }