tm1637.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. /*
  2. * SPDX-FileCopyrightText: 2022 Helmut Pozimski <helmut@pozimski.eu>
  3. *
  4. * SPDX-License-Identifier: GPL-2.0-only
  5. */
  6. #include <stdint.h>
  7. #include <driver/gpio.h>
  8. #include "tm1637.h"
  9. #include "freertos/FreeRTOS.h"
  10. #include "freertos/task.h"
  11. #define DATA_COMMAND 0x40
  12. #define DISPLAY_ON_COMMAND 0x88
  13. #define DISPLAY_OFF_COMMAND 0x80
  14. #define ADDRESS_COMMAND 0xC0
  15. static void delay() {
  16. vTaskDelay(1 / portTICK_PERIOD_MS);
  17. }
  18. esp_err_t tm1637_init(tm1637_config *config, uint8_t clk_pin, uint8_t dio_pin, bool show_colon, uint8_t brightness) {
  19. gpio_config_t io_conf;
  20. esp_err_t ret;
  21. io_conf.intr_type = GPIO_INTR_DISABLE;
  22. io_conf.mode = GPIO_MODE_OUTPUT;
  23. io_conf.pin_bit_mask = ((1ULL << clk_pin)) | ((1ULL << dio_pin));
  24. io_conf.pull_down_en = 0;
  25. io_conf.pull_up_en = 0;
  26. ret = gpio_config(&io_conf);
  27. config->clk_pin = clk_pin;
  28. config->dio_pin = dio_pin;
  29. config->show_colon = show_colon;
  30. config->brightness = brightness;
  31. gpio_set_level(dio_pin, 1);
  32. gpio_set_level(clk_pin, 1);
  33. delay();
  34. return ret;
  35. }
  36. static void start_transfer(tm1637_config *config) {
  37. gpio_set_level(config->dio_pin, 0);
  38. delay();
  39. }
  40. static void stop_transfer(tm1637_config *config) {
  41. gpio_set_level(config->dio_pin, 0);
  42. delay();
  43. gpio_set_level(config->clk_pin, 1);
  44. delay();
  45. gpio_set_level(config->dio_pin, 1);
  46. delay();
  47. }
  48. static void write_byte(tm1637_config *config, uint8_t byte) {
  49. uint8_t data = byte;
  50. for (uint8_t i = 0; i < 8; i++) {
  51. gpio_set_level(config->clk_pin, 0);
  52. delay();
  53. gpio_set_level(config->dio_pin, data & 0x01);
  54. delay();
  55. gpio_set_level(config->clk_pin, 1);
  56. delay();
  57. data = data >> 1;
  58. }
  59. gpio_set_level(config->clk_pin, 0);
  60. delay();
  61. gpio_set_level(config->dio_pin, 1);
  62. delay();
  63. gpio_set_level(config->clk_pin, 1);
  64. delay();
  65. gpio_set_direction(config->dio_pin, GPIO_MODE_INPUT);
  66. delay();
  67. int result = -1;
  68. while (result != 0) {
  69. result = gpio_get_level(config->dio_pin);
  70. }
  71. delay();
  72. gpio_set_level(config->clk_pin, 0);
  73. delay();
  74. gpio_set_direction(config->dio_pin, GPIO_MODE_OUTPUT);
  75. delay();
  76. }
  77. void tm1637_set_segment(tm1637_config *config, uint8_t value, uint8_t segment, bool enable_display) {
  78. uint16_t write_value = NUMERALS[value];
  79. if (config->show_colon) {
  80. write_value |= 0x80;
  81. }
  82. start_transfer(config);
  83. write_byte(config, DATA_COMMAND);
  84. stop_transfer(config);
  85. start_transfer(config);
  86. write_byte(config, ADDRESS_COMMAND | segment);
  87. write_byte(config, write_value);
  88. stop_transfer(config);
  89. start_transfer(config);
  90. if (enable_display) {
  91. write_byte(config, DISPLAY_ON_COMMAND | (config->brightness & 0x07));
  92. } else {
  93. write_byte(config, DISPLAY_OFF_COMMAND | (config->brightness & 0x07));
  94. }
  95. stop_transfer(config);
  96. }