/* * SPDX-FileCopyrightText: 2022 Helmut Pozimski * * SPDX-License-Identifier: GPL-2.0-only */ #include #include #include "tm1637.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #define DATA_COMMAND 0x40 #define DISPLAY_ON_COMMAND 0x88 #define DISPLAY_OFF_COMMAND 0x80 #define ADDRESS_COMMAND 0xC0 static void delay() { vTaskDelay(1 / portTICK_PERIOD_MS); } esp_err_t tm1637_init(tm1637_config *config, uint8_t clk_pin, uint8_t dio_pin, bool show_colon, uint8_t brightness) { gpio_config_t io_conf; esp_err_t ret; io_conf.intr_type = GPIO_INTR_DISABLE; io_conf.mode = GPIO_MODE_OUTPUT; io_conf.pin_bit_mask = ((1ULL << clk_pin)) | ((1ULL << dio_pin)); io_conf.pull_down_en = 0; io_conf.pull_up_en = 0; ret = gpio_config(&io_conf); config->clk_pin = clk_pin; config->dio_pin = dio_pin; config->show_colon = show_colon; config->brightness = brightness; gpio_set_level(dio_pin, 1); gpio_set_level(clk_pin, 1); delay(); return ret; } static void start_transfer(tm1637_config *config) { gpio_set_level(config->dio_pin, 0); delay(); } static void stop_transfer(tm1637_config *config) { gpio_set_level(config->dio_pin, 0); delay(); gpio_set_level(config->clk_pin, 1); delay(); gpio_set_level(config->dio_pin, 1); delay(); } static void write_byte(tm1637_config *config, uint8_t byte) { uint8_t data = byte; for (uint8_t i = 0; i < 8; i++) { gpio_set_level(config->clk_pin, 0); delay(); gpio_set_level(config->dio_pin, data & 0x01); delay(); gpio_set_level(config->clk_pin, 1); delay(); data = data >> 1; } gpio_set_level(config->clk_pin, 0); delay(); gpio_set_level(config->dio_pin, 1); delay(); gpio_set_level(config->clk_pin, 1); delay(); gpio_set_direction(config->dio_pin, GPIO_MODE_INPUT); delay(); int result = -1; while (result != 0) { result = gpio_get_level(config->dio_pin); } delay(); gpio_set_level(config->clk_pin, 0); delay(); gpio_set_direction(config->dio_pin, GPIO_MODE_OUTPUT); delay(); } void tm1637_set_segment(tm1637_config *config, uint8_t value, uint8_t segment, bool enable_display) { uint16_t write_value = NUMERALS[value]; if (config->show_colon) { write_value |= 0x80; } start_transfer(config); write_byte(config, DATA_COMMAND); stop_transfer(config); start_transfer(config); write_byte(config, ADDRESS_COMMAND | segment); write_byte(config, write_value); stop_transfer(config); start_transfer(config); if (enable_display) { write_byte(config, DISPLAY_ON_COMMAND | (config->brightness & 0x07)); } else { write_byte(config, DISPLAY_OFF_COMMAND | (config->brightness & 0x07)); } stop_transfer(config); }