|
@@ -0,0 +1,120 @@
|
|
|
+/*
|
|
|
+ * SPDX-FileCopyrightText: 2022 Helmut Pozimski <helmut@pozimski.eu>
|
|
|
+ *
|
|
|
+ * SPDX-License-Identifier: GPL-2.0-only
|
|
|
+ */
|
|
|
+
|
|
|
+#include <stdint.h>
|
|
|
+#include <driver/gpio.h>
|
|
|
+
|
|
|
+#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);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|