Adafruit_LEDBackpack.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672
  1. /***************************************************
  2. This is a library for our I2C LED Backpacks
  3. Designed specifically to work with the Adafruit LED Matrix backpacks
  4. ----> http://www.adafruit.com/products/
  5. ----> http://www.adafruit.com/products/
  6. These displays use I2C to communicate, 2 pins are required to
  7. interface. There are multiple selectable I2C addresses. For backpacks
  8. with 2 Address Select pins: 0x70, 0x71, 0x72 or 0x73. For backpacks
  9. with 3 Address Select pins: 0x70 thru 0x77
  10. Adafruit invests time and resources providing this open source code,
  11. please support Adafruit and open-source hardware by purchasing
  12. products from Adafruit!
  13. Written by Limor Fried/Ladyada for Adafruit Industries.
  14. MIT license, all text above must be included in any redistribution
  15. ****************************************************/
  16. #include <Wire.h>
  17. #include "Adafruit_LEDBackpack.h"
  18. #include "Adafruit_GFX.h"
  19. #ifndef _BV
  20. #define _BV(bit) (1<<(bit))
  21. #endif
  22. #ifndef _swap_int16_t
  23. #define _swap_int16_t(a, b) { int16_t t = a; a = b; b = t; }
  24. #endif
  25. static const uint8_t numbertable[] = {
  26. 0x3F, /* 0 */
  27. 0x06, /* 1 */
  28. 0x5B, /* 2 */
  29. 0x4F, /* 3 */
  30. 0x66, /* 4 */
  31. 0x6D, /* 5 */
  32. 0x7D, /* 6 */
  33. 0x07, /* 7 */
  34. 0x7F, /* 8 */
  35. 0x6F, /* 9 */
  36. 0x77, /* a */
  37. 0x7C, /* b */
  38. 0x39, /* C */
  39. 0x5E, /* d */
  40. 0x79, /* E */
  41. 0x71, /* F */
  42. };
  43. static const uint16_t alphafonttable[] PROGMEM = {
  44. 0b0000000000000001,
  45. 0b0000000000000010,
  46. 0b0000000000000100,
  47. 0b0000000000001000,
  48. 0b0000000000010000,
  49. 0b0000000000100000,
  50. 0b0000000001000000,
  51. 0b0000000010000000,
  52. 0b0000000100000000,
  53. 0b0000001000000000,
  54. 0b0000010000000000,
  55. 0b0000100000000000,
  56. 0b0001000000000000,
  57. 0b0010000000000000,
  58. 0b0100000000000000,
  59. 0b1000000000000000,
  60. 0b0000000000000000,
  61. 0b0000000000000000,
  62. 0b0000000000000000,
  63. 0b0000000000000000,
  64. 0b0000000000000000,
  65. 0b0000000000000000,
  66. 0b0000000000000000,
  67. 0b0000000000000000,
  68. 0b0001001011001001,
  69. 0b0001010111000000,
  70. 0b0001001011111001,
  71. 0b0000000011100011,
  72. 0b0000010100110000,
  73. 0b0001001011001000,
  74. 0b0011101000000000,
  75. 0b0001011100000000,
  76. 0b0000000000000000, //
  77. 0b0000000000000110, // !
  78. 0b0000001000100000, // "
  79. 0b0001001011001110, // #
  80. 0b0001001011101101, // $
  81. 0b0000110000100100, // %
  82. 0b0010001101011101, // &
  83. 0b0000010000000000, // '
  84. 0b0010010000000000, // (
  85. 0b0000100100000000, // )
  86. 0b0011111111000000, // *
  87. 0b0001001011000000, // +
  88. 0b0000100000000000, // ,
  89. 0b0000000011000000, // -
  90. 0b0000000000000000, // .
  91. 0b0000110000000000, // /
  92. 0b0000110000111111, // 0
  93. 0b0000000000000110, // 1
  94. 0b0000000011011011, // 2
  95. 0b0000000010001111, // 3
  96. 0b0000000011100110, // 4
  97. 0b0010000001101001, // 5
  98. 0b0000000011111101, // 6
  99. 0b0000000000000111, // 7
  100. 0b0000000011111111, // 8
  101. 0b0000000011101111, // 9
  102. 0b0001001000000000, // :
  103. 0b0000101000000000, // ;
  104. 0b0010010000000000, // <
  105. 0b0000000011001000, // =
  106. 0b0000100100000000, // >
  107. 0b0001000010000011, // ?
  108. 0b0000001010111011, // @
  109. 0b0000000011110111, // A
  110. 0b0001001010001111, // B
  111. 0b0000000000111001, // C
  112. 0b0001001000001111, // D
  113. 0b0000000011111001, // E
  114. 0b0000000001110001, // F
  115. 0b0000000010111101, // G
  116. 0b0000000011110110, // H
  117. 0b0001001000000000, // I
  118. 0b0000000000011110, // J
  119. 0b0010010001110000, // K
  120. 0b0000000000111000, // L
  121. 0b0000010100110110, // M
  122. 0b0010000100110110, // N
  123. 0b0000000000111111, // O
  124. 0b0000000011110011, // P
  125. 0b0010000000111111, // Q
  126. 0b0010000011110011, // R
  127. 0b0000000011101101, // S
  128. 0b0001001000000001, // T
  129. 0b0000000000111110, // U
  130. 0b0000110000110000, // V
  131. 0b0010100000110110, // W
  132. 0b0010110100000000, // X
  133. 0b0001010100000000, // Y
  134. 0b0000110000001001, // Z
  135. 0b0000000000111001, // [
  136. 0b0010000100000000, //
  137. 0b0000000000001111, // ]
  138. 0b0000110000000011, // ^
  139. 0b0000000000001000, // _
  140. 0b0000000100000000, // `
  141. 0b0001000001011000, // a
  142. 0b0010000001111000, // b
  143. 0b0000000011011000, // c
  144. 0b0000100010001110, // d
  145. 0b0000100001011000, // e
  146. 0b0000000001110001, // f
  147. 0b0000010010001110, // g
  148. 0b0001000001110000, // h
  149. 0b0001000000000000, // i
  150. 0b0000000000001110, // j
  151. 0b0011011000000000, // k
  152. 0b0000000000110000, // l
  153. 0b0001000011010100, // m
  154. 0b0001000001010000, // n
  155. 0b0000000011011100, // o
  156. 0b0000000101110000, // p
  157. 0b0000010010000110, // q
  158. 0b0000000001010000, // r
  159. 0b0010000010001000, // s
  160. 0b0000000001111000, // t
  161. 0b0000000000011100, // u
  162. 0b0010000000000100, // v
  163. 0b0010100000010100, // w
  164. 0b0010100011000000, // x
  165. 0b0010000000001100, // y
  166. 0b0000100001001000, // z
  167. 0b0000100101001001, // {
  168. 0b0001001000000000, // |
  169. 0b0010010010001001, // }
  170. 0b0000010100100000, // ~
  171. 0b0011111111111111,
  172. };
  173. void Adafruit_LEDBackpack::setBrightness(uint8_t b) {
  174. if (b > 15) b = 15;
  175. Wire.beginTransmission(i2c_addr);
  176. Wire.write(HT16K33_CMD_BRIGHTNESS | b);
  177. Wire.endTransmission();
  178. }
  179. void Adafruit_LEDBackpack::blinkRate(uint8_t b) {
  180. Wire.beginTransmission(i2c_addr);
  181. if (b > 3) b = 0; // turn off if not sure
  182. Wire.write(HT16K33_BLINK_CMD | HT16K33_BLINK_DISPLAYON | (b << 1));
  183. Wire.endTransmission();
  184. }
  185. Adafruit_LEDBackpack::Adafruit_LEDBackpack(void) {
  186. }
  187. void Adafruit_LEDBackpack::begin(uint8_t _addr = 0x70) {
  188. i2c_addr = _addr;
  189. Wire.begin();
  190. Wire.beginTransmission(i2c_addr);
  191. Wire.write(0x21); // turn on oscillator
  192. Wire.endTransmission();
  193. blinkRate(HT16K33_BLINK_OFF);
  194. setBrightness(15); // max brightness
  195. }
  196. void Adafruit_LEDBackpack::writeDisplay(void) {
  197. Wire.beginTransmission(i2c_addr);
  198. Wire.write((uint8_t)0x00); // start at address $00
  199. for (uint8_t i=0; i<8; i++) {
  200. Wire.write(displaybuffer[i] & 0xFF);
  201. Wire.write(displaybuffer[i] >> 8);
  202. }
  203. Wire.endTransmission();
  204. }
  205. void Adafruit_LEDBackpack::clear(void) {
  206. for (uint8_t i=0; i<8; i++) {
  207. displaybuffer[i] = 0;
  208. }
  209. }
  210. /******************************* QUAD ALPHANUM OBJECT */
  211. Adafruit_AlphaNum4::Adafruit_AlphaNum4(void) {
  212. }
  213. void Adafruit_AlphaNum4::writeDigitRaw(uint8_t n, uint16_t bitmask) {
  214. displaybuffer[n] = bitmask;
  215. }
  216. void Adafruit_AlphaNum4::writeDigitAscii(uint8_t n, uint8_t a, boolean d) {
  217. uint16_t font = pgm_read_word(alphafonttable+a);
  218. displaybuffer[n] = font;
  219. /*
  220. Serial.print(a, DEC);
  221. Serial.print(" / '"); Serial.write(a);
  222. Serial.print("' = 0x"); Serial.println(font, HEX);
  223. */
  224. if (d) displaybuffer[n] |= (1<<14);
  225. }
  226. /******************************* 24 BARGRAPH OBJECT */
  227. Adafruit_24bargraph::Adafruit_24bargraph(void) {
  228. }
  229. void Adafruit_24bargraph::setBar(uint8_t bar, uint8_t color) {
  230. uint16_t a, c;
  231. if (bar < 12)
  232. c = bar / 4;
  233. else
  234. c = (bar - 12) / 4;
  235. a = bar % 4;
  236. if (bar >= 12)
  237. a += 4;
  238. //Serial.print("Ano = "); Serial.print(a); Serial.print(" Cath = "); Serial.println(c);
  239. if (color == LED_RED) {
  240. // Turn on red LED.
  241. displaybuffer[c] |= _BV(a);
  242. // Turn off green LED.
  243. displaybuffer[c] &= ~_BV(a+8);
  244. } else if (color == LED_YELLOW) {
  245. // Turn on red and green LED.
  246. displaybuffer[c] |= _BV(a) | _BV(a+8);
  247. } else if (color == LED_OFF) {
  248. // Turn off red and green LED.
  249. displaybuffer[c] &= ~_BV(a) & ~_BV(a+8);
  250. } else if (color == LED_GREEN) {
  251. // Turn on green LED.
  252. displaybuffer[c] |= _BV(a+8);
  253. // Turn off red LED.
  254. displaybuffer[c] &= ~_BV(a);
  255. }
  256. }
  257. /******************************* 16x8 MATRIX OBJECT */
  258. Adafruit_8x16matrix::Adafruit_8x16matrix(void) : Adafruit_GFX(8, 16) {
  259. }
  260. void Adafruit_8x16matrix::drawPixel(int16_t x, int16_t y, uint16_t color) {
  261. // check rotation, move pixel around if necessary
  262. switch (getRotation()) {
  263. case 2:
  264. _swap_int16_t(x, y);
  265. x = 16 - x - 1;
  266. break;
  267. case 3:
  268. x = 16 - x - 1;
  269. y = 8 - y - 1;
  270. break;
  271. case 0:
  272. _swap_int16_t(x, y);
  273. y = 8 - y - 1;
  274. break;
  275. }
  276. /*
  277. Serial.print("("); Serial.print(x);
  278. Serial.print(","); Serial.print(y);
  279. Serial.println(")");
  280. */
  281. if ((y < 0) || (y >= 8)) return;
  282. if ((x < 0) || (x >= 16)) return;
  283. if (color) {
  284. displaybuffer[y] |= 1 << x;
  285. } else {
  286. displaybuffer[y] &= ~(1 << x);
  287. }
  288. }
  289. /******************************* 16x8 MINI MATRIX OBJECT */
  290. Adafruit_8x16minimatrix::Adafruit_8x16minimatrix(void) : Adafruit_GFX(8, 16) {
  291. }
  292. void Adafruit_8x16minimatrix::drawPixel(int16_t x, int16_t y, uint16_t color) {
  293. if ((y < 0) || (x < 0)) return;
  294. if ((getRotation() % 2 == 0) && ((y >= 16) || (x >= 8))) return;
  295. if ((getRotation() % 2 == 1) && ((x >= 16) || (y >= 8))) return;
  296. // check rotation, move pixel around if necessary
  297. switch (getRotation()) {
  298. case 2:
  299. if (y >= 8) {
  300. x += 8;
  301. y -= 8;
  302. }
  303. _swap_int16_t(x, y);
  304. break;
  305. case 3:
  306. x = 16 - x - 1;
  307. if (x >= 8) {
  308. x -= 8;
  309. y += 8;
  310. }
  311. break;
  312. case 0:
  313. y = 16 - y - 1;
  314. x = 8 - x - 1;
  315. if (y >= 8) {
  316. x += 8;
  317. y -= 8;
  318. }
  319. _swap_int16_t(x, y);
  320. break;
  321. case 1:
  322. y = 8 - y - 1;
  323. if (x >= 8) {
  324. x -= 8;
  325. y += 8;
  326. }
  327. break;
  328. }
  329. if (color) {
  330. displaybuffer[x] |= 1 << y;
  331. } else {
  332. displaybuffer[x] &= ~(1 << y);
  333. }
  334. }
  335. /******************************* 8x8 MATRIX OBJECT */
  336. Adafruit_8x8matrix::Adafruit_8x8matrix(void) : Adafruit_GFX(8, 8) {
  337. }
  338. void Adafruit_8x8matrix::drawPixel(int16_t x, int16_t y, uint16_t color) {
  339. if ((y < 0) || (y >= 8)) return;
  340. if ((x < 0) || (x >= 8)) return;
  341. // check rotation, move pixel around if necessary
  342. switch (getRotation()) {
  343. case 1:
  344. _swap_int16_t(x, y);
  345. x = 8 - x - 1;
  346. break;
  347. case 2:
  348. x = 8 - x - 1;
  349. y = 8 - y - 1;
  350. break;
  351. case 3:
  352. _swap_int16_t(x, y);
  353. y = 8 - y - 1;
  354. break;
  355. }
  356. // wrap around the x
  357. x += 7;
  358. x %= 8;
  359. if (color) {
  360. displaybuffer[y] |= 1 << x;
  361. } else {
  362. displaybuffer[y] &= ~(1 << x);
  363. }
  364. }
  365. /******************************* 8x8 BICOLOR MATRIX OBJECT */
  366. Adafruit_BicolorMatrix::Adafruit_BicolorMatrix(void) : Adafruit_GFX(8, 8) {
  367. }
  368. void Adafruit_BicolorMatrix::drawPixel(int16_t x, int16_t y, uint16_t color) {
  369. if ((y < 0) || (y >= 8)) return;
  370. if ((x < 0) || (x >= 8)) return;
  371. switch (getRotation()) {
  372. case 1:
  373. _swap_int16_t(x, y);
  374. x = 8 - x - 1;
  375. break;
  376. case 2:
  377. x = 8 - x - 1;
  378. y = 8 - y - 1;
  379. break;
  380. case 3:
  381. _swap_int16_t(x, y);
  382. y = 8 - y - 1;
  383. break;
  384. }
  385. if (color == LED_GREEN) {
  386. // Turn on green LED.
  387. displaybuffer[y] |= 1 << x;
  388. // Turn off red LED.
  389. displaybuffer[y] &= ~(1 << (x+8));
  390. } else if (color == LED_RED) {
  391. // Turn on red LED.
  392. displaybuffer[y] |= 1 << (x+8);
  393. // Turn off green LED.
  394. displaybuffer[y] &= ~(1 << x);
  395. } else if (color == LED_YELLOW) {
  396. // Turn on green and red LED.
  397. displaybuffer[y] |= (1 << (x+8)) | (1 << x);
  398. } else if (color == LED_OFF) {
  399. // Turn off green and red LED.
  400. displaybuffer[y] &= ~(1 << x) & ~(1 << (x+8));
  401. }
  402. }
  403. /******************************* 7 SEGMENT OBJECT */
  404. Adafruit_7segment::Adafruit_7segment(void) {
  405. position = 0;
  406. }
  407. void Adafruit_7segment::print(unsigned long n, int base)
  408. {
  409. if (base == 0) write(n);
  410. else printNumber(n, base);
  411. }
  412. void Adafruit_7segment::print(char c, int base)
  413. {
  414. print((long) c, base);
  415. }
  416. void Adafruit_7segment::print(unsigned char b, int base)
  417. {
  418. print((unsigned long) b, base);
  419. }
  420. void Adafruit_7segment::print(int n, int base)
  421. {
  422. print((long) n, base);
  423. }
  424. void Adafruit_7segment::print(unsigned int n, int base)
  425. {
  426. print((unsigned long) n, base);
  427. }
  428. void Adafruit_7segment::println(void) {
  429. position = 0;
  430. }
  431. void Adafruit_7segment::println(char c, int base)
  432. {
  433. print(c, base);
  434. println();
  435. }
  436. void Adafruit_7segment::println(unsigned char b, int base)
  437. {
  438. print(b, base);
  439. println();
  440. }
  441. void Adafruit_7segment::println(int n, int base)
  442. {
  443. print(n, base);
  444. println();
  445. }
  446. void Adafruit_7segment::println(unsigned int n, int base)
  447. {
  448. print(n, base);
  449. println();
  450. }
  451. void Adafruit_7segment::println(long n, int base)
  452. {
  453. print(n, base);
  454. println();
  455. }
  456. void Adafruit_7segment::println(unsigned long n, int base)
  457. {
  458. print(n, base);
  459. println();
  460. }
  461. void Adafruit_7segment::println(double n, int digits)
  462. {
  463. print(n, digits);
  464. println();
  465. }
  466. void Adafruit_7segment::print(double n, int digits)
  467. {
  468. printFloat(n, digits);
  469. }
  470. size_t Adafruit_7segment::write(uint8_t c) {
  471. uint8_t r = 0;
  472. if (c == '\n') position = 0;
  473. if (c == '\r') position = 0;
  474. if ((c >= '0') && (c <= '9')) {
  475. writeDigitNum(position, c-'0');
  476. r = 1;
  477. }
  478. position++;
  479. if (position == 2) position++;
  480. return r;
  481. }
  482. void Adafruit_7segment::writeDigitRaw(uint8_t d, uint8_t bitmask) {
  483. if (d > 4) return;
  484. displaybuffer[d] = bitmask;
  485. }
  486. void Adafruit_7segment::drawColon(boolean state) {
  487. if (state)
  488. displaybuffer[2] = 0x2;
  489. else
  490. displaybuffer[2] = 0;
  491. }
  492. void Adafruit_7segment::writeColon(void) {
  493. Wire.beginTransmission(i2c_addr);
  494. Wire.write((uint8_t)0x04); // start at address $02
  495. Wire.write(displaybuffer[2] & 0xFF);
  496. Wire.write(displaybuffer[2] >> 8);
  497. Wire.endTransmission();
  498. }
  499. void Adafruit_7segment::writeDigitNum(uint8_t d, uint8_t num, boolean dot) {
  500. if (d > 4) return;
  501. writeDigitRaw(d, numbertable[num] | (dot << 7));
  502. }
  503. void Adafruit_7segment::print(long n, int base)
  504. {
  505. printNumber(n, base);
  506. }
  507. void Adafruit_7segment::printNumber(long n, uint8_t base)
  508. {
  509. printFloat(n, 0, base);
  510. }
  511. void Adafruit_7segment::printFloat(double n, uint8_t fracDigits, uint8_t base)
  512. {
  513. uint8_t numericDigits = 4; // available digits on display
  514. boolean isNegative = false; // true if the number is negative
  515. // is the number negative?
  516. if(n < 0) {
  517. isNegative = true; // need to draw sign later
  518. --numericDigits; // the sign will take up one digit
  519. n *= -1; // pretend the number is positive
  520. }
  521. // calculate the factor required to shift all fractional digits
  522. // into the integer part of the number
  523. double toIntFactor = 1.0;
  524. for(int i = 0; i < fracDigits; ++i) toIntFactor *= base;
  525. // create integer containing digits to display by applying
  526. // shifting factor and rounding adjustment
  527. uint32_t displayNumber = n * toIntFactor + 0.5;
  528. // calculate upper bound on displayNumber given
  529. // available digits on display
  530. uint32_t tooBig = 1;
  531. for(int i = 0; i < numericDigits; ++i) tooBig *= base;
  532. // if displayNumber is too large, try fewer fractional digits
  533. while(displayNumber >= tooBig) {
  534. --fracDigits;
  535. toIntFactor /= base;
  536. displayNumber = n * toIntFactor + 0.5;
  537. }
  538. // did toIntFactor shift the decimal off the display?
  539. if (toIntFactor < 1) {
  540. printError();
  541. } else {
  542. // otherwise, display the number
  543. int8_t displayPos = 4;
  544. if (displayNumber) //if displayNumber is not 0
  545. {
  546. for(uint8_t i = 0; displayNumber || i <= fracDigits; ++i) {
  547. boolean displayDecimal = (fracDigits != 0 && i == fracDigits);
  548. writeDigitNum(displayPos--, displayNumber % base, displayDecimal);
  549. if(displayPos == 2) writeDigitRaw(displayPos--, 0x00);
  550. displayNumber /= base;
  551. }
  552. }
  553. else {
  554. writeDigitNum(displayPos--, 0, false);
  555. }
  556. // display negative sign if negative
  557. if(isNegative) writeDigitRaw(displayPos--, 0x40);
  558. // clear remaining display positions
  559. while(displayPos >= 0) writeDigitRaw(displayPos--, 0x00);
  560. }
  561. }
  562. void Adafruit_7segment::printError(void) {
  563. for(uint8_t i = 0; i < SEVENSEG_DIGITS; ++i) {
  564. writeDigitRaw(i, (i == 2 ? 0x00 : 0x40));
  565. }
  566. }