Adafruit_SSD1306.cpp 44 KB

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