NTP clock made with ESP-12 (ESP8266) and 16-char TM1640 (JY-LM1640)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

LM1640Display.cpp 9.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. // Inspired by LM1640Display, Author: avishorp@gmail.com, https://github.com/avishorp/TM1637
  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 "LM1640Display.h"
  22. #include <Arduino.h>
  23. #define TM1637_I2C_COMM1 0b01000000
  24. #define TM1637_I2C_COMM2 0b11000000
  25. #define TM1637_I2C_COMM3 0b10000000
  26. #define S7_DP 0x0080
  27. //
  28. // A
  29. // ---
  30. // F | | B
  31. // -G-
  32. // E | | C
  33. // ---
  34. // D
  35. const uint8_t digitToSegment[] = {
  36. // XGFEDCBA
  37. 0b00111111, // 0
  38. 0b00000110, // 1
  39. 0b01011011, // 2
  40. 0b01001111, // 3
  41. 0b01100110, // 4
  42. 0b01101101, // 5
  43. 0b01111101, // 6
  44. 0b00000111, // 7
  45. 0b01111111, // 8
  46. 0b01101111, // 9
  47. 0b01110111, // A
  48. 0b01111100, // b
  49. 0b00111001, // C
  50. 0b01011110, // d
  51. 0b01111001, // E
  52. 0b01110001 // F
  53. };
  54. const uint8_t clr[] = {
  55. // XGFEDCBA
  56. 0b00000000, // 0
  57. 0b00000000, // 1
  58. 0b00000000, // 2
  59. 0b00000000, // 3
  60. 0b00000000, // 4
  61. 0b00000000, // 5
  62. 0b00000000, // 6
  63. 0b00000000, // 7
  64. 0b00000000, // 8
  65. 0b00000000, // 9
  66. 0b00000000, // A
  67. 0b00000000, // b
  68. 0b00000000, // C
  69. 0b00000000, // d
  70. 0b00000000, // E
  71. 0b00000000 // F
  72. };
  73. const short FONT_7S[] = {
  74. C7_SPC, //32 0x20, Space
  75. C7_EXC,
  76. C7_QTE,
  77. C7_HSH,
  78. C7_DLR,
  79. C7_PCT,
  80. C7_AMP,
  81. C7_ACC,
  82. C7_LBR,
  83. C7_RBR,
  84. C7_MLT,
  85. C7_PLS,
  86. C7_CMA,
  87. C7_MIN,
  88. C7_DPT,
  89. C7_RS,
  90. C7_0, //48 0x30
  91. C7_1,
  92. C7_2,
  93. C7_3,
  94. C7_4,
  95. C7_5,
  96. C7_6,
  97. C7_7,
  98. C7_8,
  99. C7_9,
  100. C7_COL, //58 0x3A
  101. C7_SCL,
  102. C7_LT,
  103. C7_EQ,
  104. C7_GT,
  105. C7_QM,
  106. C7_AT, //64 0x40
  107. C7_A, //65 0x41, A
  108. C7_B,
  109. C7_C,
  110. C7_D,
  111. C7_E,
  112. C7_F,
  113. C7_G,
  114. C7_H,
  115. C7_I,
  116. C7_J,
  117. C7_K,
  118. C7_L,
  119. C7_M,
  120. C7_N,
  121. C7_O,
  122. C7_P,
  123. C7_Q,
  124. C7_R,
  125. C7_S,
  126. C7_T,
  127. C7_U,
  128. C7_V,
  129. C7_W,
  130. C7_X,
  131. C7_Y,
  132. C7_Z, //90 0x5A, Z
  133. C7_SBL, //91 0x5B
  134. C7_LS,
  135. C7_SBR,
  136. C7_PWR,
  137. C7_UDS,
  138. C7_ACC,
  139. C7_A, //97 0x61, A replacing a
  140. C7_B,
  141. C7_C,
  142. C7_D,
  143. C7_E,
  144. C7_F,
  145. C7_G,
  146. C7_H,
  147. C7_I,
  148. C7_J,
  149. C7_K,
  150. C7_L,
  151. C7_M,
  152. C7_N,
  153. C7_O,
  154. C7_P,
  155. C7_Q,
  156. C7_R,
  157. C7_S,
  158. C7_T,
  159. C7_U,
  160. C7_V,
  161. C7_W,
  162. C7_X,
  163. C7_Y,
  164. C7_Z, // 122 0x7A, Z replacing z
  165. C7_CBL, // 123 0x7B
  166. C7_OR,
  167. C7_CBR,
  168. C7_TLD,
  169. C7_DEL // 127
  170. };
  171. LM1640Display::LM1640Display(uint8_t pinClk, uint8_t pinDIO)
  172. {
  173. // Copy the pin numbers
  174. m_pinClk = pinClk;
  175. m_pinDIO = pinDIO;
  176. // Set the pin direction and default value.
  177. // Both pins are set as inputs, allowing the pull-up resistors to pull them up
  178. pinMode(m_pinClk, INPUT);
  179. pinMode(m_pinDIO,INPUT);
  180. digitalWrite(m_pinClk, LOW);
  181. digitalWrite(m_pinDIO, LOW);
  182. }
  183. void LM1640Display::setBrightness(uint8_t brightness, bool on)
  184. {
  185. m_brightness = (brightness & 0x7) | (on? 0x08 : 0x00);
  186. }
  187. void LM1640Display::clear(uint8_t length)
  188. {
  189. setSegments(clr, length, 0);
  190. }
  191. void LM1640Display::setSegments(const uint8_t segments[], uint8_t length, uint8_t pos)
  192. {
  193. // Write COMM1
  194. start();
  195. writeByte(TM1637_I2C_COMM1);
  196. stop();
  197. // Write COMM2 + first digit address
  198. start();
  199. writeByte(TM1637_I2C_COMM2 + (pos & 0x03));
  200. // Write the data bytes
  201. for (uint8_t k=0; k < length; k++)
  202. writeByte(segments[k]);
  203. stop();
  204. // Write COMM3 + brightness
  205. start();
  206. writeByte(TM1637_I2C_COMM3 + (m_brightness & 0x0f));
  207. stop();
  208. }
  209. //void LM1640Display::showNumberDec(int num, bool leading_zero, uint8_t length, uint8_t pos)
  210. void LM1640Display::showString(char str[]){
  211. // ensure str is 16 chars long
  212. uint8_t digits[SIZE];
  213. int to = strlen(str);
  214. for(int8_t k = 0; k < to; k++) {
  215. digits[k] = encodeChar(str[k]);
  216. }
  217. if (to < 16){
  218. for(int8_t k = to; k < 16; k++) {
  219. digits[k] = 0;
  220. }
  221. }
  222. setSegments(digits, 16, 0);
  223. }
  224. void LM1640Display::showNumberDec(int num, bool leading_zero, uint8_t length, uint8_t pos)
  225. {
  226. uint8_t digits[length];
  227. const static int divisors[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 10000000000};
  228. bool leading = true;
  229. for(int8_t k = 0; k < length; k++) {
  230. if (leading_zero){
  231. digits[k] = encodeDigit(0);
  232. }
  233. else{
  234. digits[k] = 0;
  235. }
  236. }
  237. for(int8_t k = 5; k < 16; k++) {
  238. int divisor = divisors[16 - k - 1];
  239. int d = num / divisor;
  240. uint8_t digit = 0;
  241. if (d == 0) {
  242. if (leading_zero || !leading)
  243. digit = encodeDigit(d);
  244. else
  245. digit = 0;
  246. }
  247. else {
  248. digit = encodeDigit(d);
  249. num -= d * divisor;
  250. leading = false;
  251. }
  252. digits[k] = digit;
  253. }
  254. setSegments(digits, length, pos);
  255. }
  256. void LM1640Display::bitDelay()
  257. {
  258. delayMicroseconds(100);
  259. }
  260. void LM1640Display::start()
  261. {
  262. pinMode(m_pinDIO, OUTPUT);
  263. bitDelay();
  264. }
  265. void LM1640Display::stop()
  266. {
  267. pinMode(m_pinDIO, OUTPUT); //LOW
  268. bitDelay();
  269. pinMode(m_pinClk, INPUT); // HIGH
  270. bitDelay();
  271. pinMode(m_pinDIO, INPUT); // HIGH
  272. bitDelay();
  273. }
  274. bool LM1640Display::writeByte(uint8_t b)
  275. {
  276. uint8_t data = b;
  277. //Serial.print("DATA: ");
  278. //Serial.println(data);
  279. // 8 Data Bits
  280. for(uint8_t i = 0; i < 8; i++) {
  281. // CLK low
  282. pinMode(m_pinClk, OUTPUT);
  283. bitDelay();
  284. uint8_t heisan = data & 0x01;
  285. // Set data bit
  286. if (heisan) // HIGH
  287. pinMode(m_pinDIO, INPUT);
  288. else //LOW
  289. pinMode(m_pinDIO, OUTPUT);
  290. bitDelay();
  291. // CLK high
  292. pinMode(m_pinClk, INPUT);
  293. bitDelay();
  294. data = data >> 1;
  295. }
  296. // CLK to zero
  297. pinMode(m_pinClk, OUTPUT); // LOW
  298. bitDelay();
  299. return true;
  300. }
  301. uint8_t LM1640Display::encodeDigit(uint8_t digit)
  302. {
  303. return digitToSegment[digit];
  304. }
  305. uint8_t LM1640Display::encodeChar(char ch)
  306. {
  307. return FONT_7S[ch-32];
  308. }