TM1637Display.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. // Author: avishorp@gmail.com
  2. //
  3. // This library is free software; you can redistribute it and/or
  4. // modify it under the terms of the GNU Lesser General Public
  5. // License as published by the Free Software Foundation; either
  6. // version 2.1 of the License, or (at your option) any later version.
  7. //
  8. // This library is distributed in the hope that it will be useful,
  9. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. // Lesser General Public License for more details.
  12. //
  13. // You should have received a copy of the GNU Lesser General Public
  14. // License along with this library; if not, write to the Free Software
  15. // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. extern "C" {
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include <inttypes.h>
  20. }
  21. #include <TM1637Display.h>
  22. #include <Arduino.h>
  23. #define TM1637_I2C_COMM1 0x40
  24. #define TM1637_I2C_COMM2 0xC0
  25. #define TM1637_I2C_COMM3 0x80
  26. //
  27. // A
  28. // ---
  29. // F | | B
  30. // -G-
  31. // E | | C
  32. // ---
  33. // D
  34. const uint8_t digitToSegment[] = {
  35. // XGFEDCBA
  36. 0b00111111, // 0
  37. 0b00000110, // 1
  38. 0b01011011, // 2
  39. 0b01001111, // 3
  40. 0b01100110, // 4
  41. 0b01101101, // 5
  42. 0b01111101, // 6
  43. 0b00000111, // 7
  44. 0b01111111, // 8
  45. 0b01101111, // 9
  46. 0b01110111, // A
  47. 0b01111100, // b
  48. 0b00111001, // C
  49. 0b01011110, // d
  50. 0b01111001, // E
  51. 0b01110001 // F
  52. };
  53. TM1637Display::TM1637Display(uint8_t pinClk, uint8_t pinDIO)
  54. {
  55. // Copy the pin numbers
  56. m_pinClk = pinClk;
  57. m_pinDIO = pinDIO;
  58. // Set the pin direction and default value.
  59. // Both pins are set as inputs, allowing the pull-up resistors to pull them up
  60. pinMode(m_pinClk, INPUT);
  61. pinMode(m_pinDIO,INPUT);
  62. digitalWrite(m_pinClk, LOW);
  63. digitalWrite(m_pinDIO, LOW);
  64. }
  65. void TM1637Display::setBrightness(uint8_t brightness, bool on)
  66. {
  67. m_brightness = (brightness & 0x7) | (on? 0x08 : 0x00);
  68. }
  69. void TM1637Display::setColon(bool colon)
  70. {
  71. m_colon = colon;
  72. }
  73. void TM1637Display::setSegments(const uint8_t segments[], uint8_t length, uint8_t pos)
  74. {
  75. // Write COMM1
  76. start();
  77. writeByte(TM1637_I2C_COMM1);
  78. stop();
  79. // Write COMM2 + first digit address
  80. start();
  81. writeByte(TM1637_I2C_COMM2 + (pos & 0x03));
  82. // Write the data bytes
  83. uint8_t currentByte = 0x00;
  84. for (uint8_t k=0; k < length; k++) {
  85. currentByte = segments[k] & 0x7f;
  86. if(k == COLON_POSITION){
  87. if(m_colon){
  88. currentByte |= 0x80;
  89. }
  90. }
  91. writeByte(currentByte);
  92. }
  93. stop();
  94. // Write COMM3 + brightness
  95. start();
  96. writeByte(TM1637_I2C_COMM3 + (m_brightness & 0x0f));
  97. stop();
  98. }
  99. void TM1637Display::showNumberDec(int num, bool leading_zero, uint8_t length, uint8_t pos)
  100. {
  101. showNumberDecEx(num, 0, leading_zero, length, pos);
  102. }
  103. void TM1637Display::showNumberDecEx(int num, uint8_t dots, bool leading_zero,
  104. uint8_t length, uint8_t pos)
  105. {
  106. uint8_t digits[4];
  107. const static int divisors[] = { 1, 10, 100, 1000 };
  108. bool leading = true;
  109. for(int8_t k = 0; k < 4; k++) {
  110. int divisor = divisors[4 - 1 - k];
  111. int d = num / divisor;
  112. uint8_t digit = 0;
  113. if (d == 0) {
  114. if (leading_zero || !leading || (k == 3))
  115. digit = encodeDigit(d);
  116. else
  117. digit = 0;
  118. }
  119. else {
  120. digit = encodeDigit(d);
  121. num -= d * divisor;
  122. leading = false;
  123. }
  124. // Add the decimal point/colon to the digit
  125. digit |= (dots & 0x80);
  126. dots <<= 1;
  127. digits[k] = digit;
  128. }
  129. setSegments(digits + (4 - length), length, pos);
  130. }
  131. void TM1637Display::bitDelay()
  132. {
  133. delayMicroseconds(50);
  134. }
  135. void TM1637Display::start()
  136. {
  137. pinMode(m_pinDIO, OUTPUT);
  138. bitDelay();
  139. }
  140. void TM1637Display::stop()
  141. {
  142. pinMode(m_pinDIO, OUTPUT);
  143. bitDelay();
  144. pinMode(m_pinClk, INPUT);
  145. bitDelay();
  146. pinMode(m_pinDIO, INPUT);
  147. bitDelay();
  148. }
  149. bool TM1637Display::writeByte(uint8_t b)
  150. {
  151. uint8_t data = b;
  152. // 8 Data Bits
  153. for(uint8_t i = 0; i < 8; i++) {
  154. // CLK low
  155. pinMode(m_pinClk, OUTPUT);
  156. bitDelay();
  157. // Set data bit
  158. if (data & 0x01)
  159. pinMode(m_pinDIO, INPUT);
  160. else
  161. pinMode(m_pinDIO, OUTPUT);
  162. bitDelay();
  163. // CLK high
  164. pinMode(m_pinClk, INPUT);
  165. bitDelay();
  166. data = data >> 1;
  167. }
  168. // Wait for acknowledge
  169. // CLK to zero
  170. pinMode(m_pinClk, OUTPUT);
  171. pinMode(m_pinDIO, INPUT);
  172. bitDelay();
  173. // CLK to high
  174. pinMode(m_pinClk, INPUT);
  175. bitDelay();
  176. uint8_t ack = digitalRead(m_pinDIO);
  177. if (ack == 0)
  178. pinMode(m_pinDIO, OUTPUT);
  179. bitDelay();
  180. pinMode(m_pinClk, OUTPUT);
  181. bitDelay();
  182. return ack;
  183. }
  184. uint8_t TM1637Display::encodeDigit(uint8_t digit)
  185. {
  186. return digitToSegment[digit & 0x0f];
  187. }