Adafruit_SSD1306.cpp 44 KB

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