tm1637.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  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_COMMAND 0x88
  13. #define ADDRESS_COMMAND 0xC0
  14. // INPUT = 1, OUTPUT = 0
  15. // INPUT = 1, OUTPUT = 0
  16. static void delay() {
  17. vTaskDelay(1 / portTICK_PERIOD_MS);
  18. }
  19. esp_err_t tm1637_init(tm1637_config* config, 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(tm1637_config* config) {
  38. gpio_set_level(config->dio_pin, 0);
  39. delay();
  40. }
  41. static void stop_transfer(tm1637_config* config) {
  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(tm1637_config* config, 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. esp_err_t tm1637_set_segment(tm1637_config* config, uint8_t value, uint8_t segment) {
  79. uint16_t write_value = NUMERALS[value];
  80. if (config->show_colon) {
  81. write_value |= 0x80;
  82. }
  83. start_transfer(config);
  84. write_byte(config, DATA_COMMAND);
  85. stop_transfer(config);
  86. start_transfer(config);
  87. write_byte(config, ADDRESS_COMMAND | segment);
  88. write_byte(config, write_value);
  89. stop_transfer(config);
  90. start_transfer(config);
  91. write_byte(config, DISPLAY_COMMAND | (config->brightness & 0x07));
  92. stop_transfer(config);
  93. return 0;
  94. }