tm1637.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  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 tm1637_config config;
  16. static void delay() {
  17. vTaskDelay(1 / portTICK_PERIOD_MS);
  18. }
  19. esp_err_t tm1637_init(uint8_t clk_pin, uint8_t dio_pin, bool show_colon, uint8_t brightness) {
  20. gpio_config_t io_conf;
  21. esp_err_t ret;
  22. io_conf.intr_type = GPIO_INTR_DISABLE;
  23. io_conf.mode = GPIO_MODE_OUTPUT;
  24. io_conf.pin_bit_mask = ((1ULL << clk_pin)) | ((1ULL << dio_pin));
  25. io_conf.pull_down_en = 0;
  26. io_conf.pull_up_en = 0;
  27. ret = gpio_config(&io_conf);
  28. config.clk_pin = clk_pin;
  29. config.dio_pin = dio_pin;
  30. config.show_colon = show_colon;
  31. config.brightness = brightness;
  32. gpio_set_level(dio_pin, 1);
  33. gpio_set_level(clk_pin, 1);
  34. delay();
  35. return ret;
  36. }
  37. static void start_transfer() {
  38. gpio_set_level(config.dio_pin, 0);
  39. delay();
  40. }
  41. static void stop_transfer() {
  42. gpio_set_level(config.dio_pin, 0);
  43. delay();
  44. gpio_set_level(config.clk_pin, 1);
  45. delay();
  46. gpio_set_level(config.dio_pin, 1);
  47. delay();
  48. }
  49. static void write_byte(uint8_t byte) {
  50. uint8_t data = byte;
  51. for (uint8_t i = 0; i < 8; i++) {
  52. gpio_set_level(config.clk_pin, 0);
  53. delay();
  54. gpio_set_level(config.dio_pin, data & 0x01);
  55. delay();
  56. gpio_set_level(config.clk_pin, 1);
  57. delay();
  58. data = data >> 1;
  59. }
  60. gpio_set_level(config.clk_pin, 0);
  61. delay();
  62. gpio_set_level(config.dio_pin, 1);
  63. delay();
  64. gpio_set_level(config.clk_pin, 1);
  65. delay();
  66. gpio_set_direction(config.dio_pin, GPIO_MODE_INPUT);
  67. delay();
  68. int result = -1;
  69. while (result != 0) {
  70. result = gpio_get_level(config.dio_pin);
  71. }
  72. delay();
  73. gpio_set_level(config.clk_pin, 0);
  74. delay();
  75. gpio_set_direction(config.dio_pin, GPIO_MODE_OUTPUT);
  76. delay();
  77. }
  78. void tm1637_set_segment(uint8_t value, uint8_t segment, bool enable_display) {
  79. uint16_t write_value = NUMERALS[value];
  80. if (config.show_colon) {
  81. write_value |= 0x80;
  82. }
  83. start_transfer();
  84. write_byte(DATA_COMMAND);
  85. stop_transfer();
  86. start_transfer();
  87. write_byte(ADDRESS_COMMAND | segment);
  88. write_byte(write_value);
  89. stop_transfer();
  90. start_transfer();
  91. if (enable_display) {
  92. write_byte(DISPLAY_ON_COMMAND | (config.brightness & 0x07));
  93. } else {
  94. write_byte(DISPLAY_OFF_COMMAND | (config.brightness & 0x07));
  95. }
  96. stop_transfer();
  97. }