TM1637.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include "pico/stdlib.h"
  4. #include "hardware/pio.h"
  5. #include "TM1637.h"
  6. #include "tm1637out.pio.h"
  7. const uint8_t digit_seg[] = {
  8. 0b00111111, // 0
  9. 0b00000110, // 1
  10. 0b01011011, // 2
  11. 0b01001111, // 3
  12. 0b01100110, // 4
  13. 0b01101101, // 5
  14. 0b01111101, // 6
  15. 0b00000111, // 7
  16. 0b01111111, // 8
  17. 0b01101111, // 9
  18. };
  19. const uint8_t letter_seg[] = {
  20. 0b01110111, // A
  21. 0b01111100, // b
  22. 0b00111001, // C
  23. 0b01011110, // d
  24. 0b01111001, // E
  25. 0b01110001, // F
  26. 0b00111101, // G
  27. 0b01110110, // H
  28. 0b00000100, // i
  29. 0b00001110, // J
  30. 0b00000000, // K
  31. 0b00111000, // L
  32. 0b00000000, // M
  33. 0b01010100, // n
  34. 0b01011100, // o
  35. 0b01110011, // P
  36. 0b01100111, // q
  37. 0b01010000, // r
  38. 0b01101101, // S
  39. 0b01111000, // t
  40. 0b00011100, // u
  41. 0b00000000, // V
  42. 0b00000000, // W
  43. 0b00000000, // X
  44. 0b01101110, // y
  45. 0b00000000, // z
  46. };
  47. // 先頭のTM1637_tのポインタ
  48. static TM1637_t *first = NULL;
  49. // 文字コード→セグメントコード
  50. uint32_t chr_to_seg(char c)
  51. {
  52. if(c >= '0' && c <= '9')
  53. return digit_seg[c - '0'];
  54. if(c >= 'a' && c <= 'z')
  55. return letter_seg[c - 'a'];
  56. if( c >= 'A' && c <= 'Z')
  57. return letter_seg[c - 'A'];
  58. if( c == ':' || c == '.')
  59. return DOT_SEG;
  60. if( c == '-' )
  61. return MINUS_SEG;
  62. return 0;
  63. }
  64. // TM1637を追加する
  65. int TM1637_add(TM1637_t *next)
  66. {
  67. if (first == NULL) {
  68. first = next;
  69. return 0;
  70. }
  71. TM1637_t *p = first;
  72. while(p->next != NULL)
  73. p = p->next;
  74. p->next = next;
  75. return 0;
  76. }
  77. TM1637_t *TM1637_init(uint8_t sda_base_pin, uint8_t col, uint8_t cont)
  78. {
  79. uint8_t colmns, contrast;
  80. PIO pio;
  81. uint sm, pio_offset;
  82. TM1637_t *p;
  83. // デフォルト値の設定
  84. if(col <= TM1637_MAX_COL && col > 0)
  85. colmns = col;
  86. else
  87. return NULL;
  88. if(cont <= TM1637_MAX_CONTRAST)
  89. contrast = cont;
  90. else
  91. return NULL;
  92. if(pio_claim_free_sm_and_add_program(&tm1637out_program, &pio, &sm, &pio_offset)) {
  93. // PIO初期化
  94. tm1637out_program_init(pio, sm, pio_offset, sda_base_pin, sda_base_pin+1);
  95. // SM起動
  96. pio_sm_set_enabled(pio, sm, true);
  97. }
  98. else // PIOを確保できなかった
  99. return NULL;
  100. // ここまでできたら初期化成功と見て構造体を作成する
  101. p = (TM1637_t *)malloc(sizeof(TM1637_t));
  102. p->colmns = colmns;
  103. p->contrast = contrast;
  104. p->pio = pio;
  105. p->sm = sm;
  106. p->offset = pio_offset;
  107. p->next = NULL;
  108. p->initialized = true;
  109. // 末尾に追加
  110. TM1637_add(p);
  111. // TM1637初期化
  112. // データセット(自動アドレスインクリメント)
  113. pio_sm_put_blocking(pio, sm, TM1637_AUTOINC | STOP_COND);
  114. // アドレス0からカラム数分を0で初期化
  115. pio_sm_put_blocking(pio, sm, TM1637_ADDRSET| 0 );
  116. for(int i = 0; i < colmns; i++) {
  117. uint32_t data = 0;
  118. if( i == (colmns - 1) )
  119. data = STOP_COND;
  120. pio_sm_put_blocking(pio, sm, data);
  121. }
  122. // コントラスト値で表示オン
  123. TM1637_set_contrast(p, contrast);
  124. return p;
  125. }
  126. int TM1637_set_contrast(TM1637_t *p, uint8_t cont)
  127. {
  128. if(cont <= TM1637_MAX_CONTRAST)
  129. p->contrast = cont;
  130. else
  131. return TM1637_ERR_INVALID_PARAM;
  132. pio_sm_put_blocking(p->pio, p->sm, TM1637_DISPON | cont | STOP_COND);
  133. return 0;
  134. }
  135. int TM1637_putchar(TM1637_t *p, char c, bool dot,uint8_t col)
  136. {
  137. if(col >= p->colmns)
  138. return TM1637_ERR_INVALID_PARAM;
  139. // 固定アドレスデータセット
  140. pio_sm_put_blocking(p->pio, p->sm, TM1637_DATASET | STOP_COND);
  141. // アドレス
  142. pio_sm_put_blocking(p->pio, p->sm, TM1637_ADDRSET | col);
  143. // セグメントデータ
  144. pio_sm_put_blocking(p->pio, p->sm, chr_to_seg(c) | (dot ? DOT_SEG : 0) | STOP_COND);
  145. return 0;
  146. }
  147. int TM1637_putstr(TM1637_t *t, char *str)
  148. {
  149. int col = 0, p = 0;
  150. // データセット(自動アドレスインクリメント)
  151. pio_sm_put_blocking(t->pio, t->sm, TM1637_AUTOINC | STOP_COND);
  152. // アドレス0セット
  153. pio_sm_put_blocking(t->pio, t->sm, TM1637_ADDRSET| 0 );
  154. // 文字数分を出力
  155. while(str[col] != '\0') {
  156. uint32_t data = chr_to_seg(str[col++]);
  157. // ドットマーク
  158. if(str[col] == '.' || str[col] == ':') {
  159. data |= DOT_SEG;
  160. col++;
  161. }
  162. // 最後はStop Condition
  163. if(str[col] == '\0' || ++p >= t->colmns) data |= STOP_COND;
  164. pio_sm_put_blocking(t->pio, t->sm, data);
  165. // カラム数に達したら終わり
  166. if( p >= t->colmns )
  167. break;
  168. }
  169. return 0;
  170. }