From 8cce9c35f37be9202480add526022126fcf02f0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Gassmann?= Date: Thu, 2 May 2024 21:16:41 +0200 Subject: [~] Moved the screen related code in a component --- components/screen/CMakeLists.txt | 3 + components/screen/screen.c | 183 +++++++++++++++++++++++++++++++++++++++ components/screen/screen.h | 55 ++++++++++++ 3 files changed, 241 insertions(+) create mode 100644 components/screen/CMakeLists.txt create mode 100644 components/screen/screen.c create mode 100644 components/screen/screen.h (limited to 'components/screen') diff --git a/components/screen/CMakeLists.txt b/components/screen/CMakeLists.txt new file mode 100644 index 0000000..df343b9 --- /dev/null +++ b/components/screen/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRCS "screen.c" + INCLUDE_DIRS "." + PRIV_REQUIRES esp_driver_gpio esp_driver_i2c) \ No newline at end of file diff --git a/components/screen/screen.c b/components/screen/screen.c new file mode 100644 index 0000000..99f74b0 --- /dev/null +++ b/components/screen/screen.c @@ -0,0 +1,183 @@ +#include "screen.h" + +esp_err_t write_reg_bit_16(i2c_master_dev_handle_t mcp, uint8_t reg, bool val, uint8_t bit) +{ + uint8_t buf[2]; + + // Read the current value from the register + buf[0] = reg; // register address + ESP_ERROR_CHECK(i2c_master_transmit(mcp, &buf[0], sizeof(uint8_t), -1)); + ESP_ERROR_CHECK(i2c_master_receive(mcp, &buf[1], sizeof(uint8_t), -1)); + // Update the value in the buffer + + buf[1] = (buf[1] & ~BV(bit)) | (val ? BV(bit) : 0); + + // Write the updated value back to the register + buf[0] = reg; // Send register address + ESP_ERROR_CHECK(i2c_master_transmit(mcp, &buf[0], sizeof(uint16_t), -1)); + + return ESP_OK; +} + +esp_err_t mcp_set_mode(i2c_master_dev_handle_t mcp, uint8_t reg, uint8_t pin, bool mode) +{ + return write_reg_bit_16(mcp, reg, mode, pin); +} + +esp_err_t mcp_set_level(i2c_master_dev_handle_t mcp, uint8_t reg, uint8_t pin, bool val) +{ + return write_reg_bit_16(mcp, reg, val, pin); +} + +void configure_screen(struct Screen* screen) +{ + i2c_master_bus_config_t i2c_bus_config = { + .clk_source = I2C_CLK_SRC_DEFAULT, + .i2c_port = 0, + .sda_io_num = SDA_PIN, + .scl_io_num = SCL_PIN, + .glitch_ignore_cnt = 7, + .flags.enable_internal_pullup = true, + }; + ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_config, &(screen->i2c_bus))); + + i2c_device_config_t mcp_cfg = { + .dev_addr_length = I2C_ADDR_BIT_LEN_7, + .device_address = MCP_I2C_ADDR, + .scl_speed_hz = 1000000, + }; + ESP_ERROR_CHECK(i2c_master_bus_add_device(screen->i2c_bus, &mcp_cfg, &(screen->mcp))); + + printf("I2C MCP Configured!\n"); + + screen->nixies[0].digit = 0; + screen->nixies[0].reg = REG_GPIOA; + screen->nixies[0].C = N0_P0; + screen->nixies[0].B = N0_P1; + screen->nixies[0].D = N0_P2; + screen->nixies[0].A = N0_P3; + screen->nixies[1].digit = 0; + screen->nixies[1].reg = REG_GPIOA; + screen->nixies[1].C = N1_P0; + screen->nixies[1].B = N1_P1; + screen->nixies[1].D = N1_P2; + screen->nixies[1].A = N1_P3; + screen->nixies[2].digit = 0; + screen->nixies[2].reg = REG_GPIOB; + screen->nixies[2].C = N2_P0; + screen->nixies[2].B = N2_P1; + screen->nixies[2].D = N2_P2; + screen->nixies[2].A = N2_P3; + screen->nixies[3].digit = 0; + screen->nixies[3].reg = REG_GPIOB; + screen->nixies[3].C = N3_P0; + screen->nixies[3].B = N3_P1; + screen->nixies[3].D = N3_P2; + screen->nixies[3].A = N3_P3; + + for (uint8_t i = 0; i <= 3; ++i) + { + mcp_set_mode(screen->mcp, screen->nixies[i].reg, screen->nixies[i].D, MCP_GPIO_OUTPUT); + mcp_set_mode(screen->mcp, screen->nixies[i].reg, screen->nixies[i].C, MCP_GPIO_OUTPUT); + mcp_set_mode(screen->mcp, screen->nixies[i].reg, screen->nixies[i].B, MCP_GPIO_OUTPUT); + mcp_set_mode(screen->mcp, screen->nixies[i].reg, screen->nixies[i].A, MCP_GPIO_OUTPUT); + } + + + printf("MCP GPIO Configured!\n"); + return; +} + +void set_digit(i2c_master_dev_handle_t mcp, struct Nixie* n) +{ + switch (n->digit) { + case 0: + mcp_set_level(mcp, n->reg, n->D, 0); + mcp_set_level(mcp, n->reg, n->C, 0); + mcp_set_level(mcp, n->reg, n->B, 0); + mcp_set_level(mcp, n->reg, n->A, 0); + break; + case 1: + mcp_set_level(mcp, n->reg, n->D, 0); + mcp_set_level(mcp, n->reg, n->C, 0); + mcp_set_level(mcp, n->reg, n->B, 0); + mcp_set_level(mcp, n->reg, n->A, 1); + break; + case 2: + mcp_set_level(mcp, n->reg, n->D, 0); + mcp_set_level(mcp, n->reg, n->C, 0); + mcp_set_level(mcp, n->reg, n->B, 1); + mcp_set_level(mcp, n->reg, n->A, 0); + break; + case 3: + mcp_set_level(mcp, n->reg, n->D, 0); + mcp_set_level(mcp, n->reg, n->C, 0); + mcp_set_level(mcp, n->reg, n->B, 1); + mcp_set_level(mcp, n->reg, n->A, 1); + break; + case 4: + mcp_set_level(mcp, n->reg, n->D, 0); + mcp_set_level(mcp, n->reg, n->C, 1); + mcp_set_level(mcp, n->reg, n->B, 0); + mcp_set_level(mcp, n->reg, n->A, 0); + break; + case 5: + mcp_set_level(mcp, n->reg, n->D, 0); + mcp_set_level(mcp, n->reg, n->C, 1); + mcp_set_level(mcp, n->reg, n->B, 0); + mcp_set_level(mcp, n->reg, n->A, 1); + break; + case 6: + mcp_set_level(mcp, n->reg, n->D, 0); + mcp_set_level(mcp, n->reg, n->C, 1); + mcp_set_level(mcp, n->reg, n->B, 1); + mcp_set_level(mcp, n->reg, n->A, 0); + break; + case 7: + mcp_set_level(mcp, n->reg, n->D, 0); + mcp_set_level(mcp, n->reg, n->C, 1); + mcp_set_level(mcp, n->reg, n->B, 1); + mcp_set_level(mcp, n->reg, n->A, 1); + break; + case 8: + mcp_set_level(mcp, n->reg, n->D, 1); + mcp_set_level(mcp, n->reg, n->C, 0); + mcp_set_level(mcp, n->reg, n->B, 0); + mcp_set_level(mcp, n->reg, n->A, 0); + break; + case 9: + mcp_set_level(mcp, n->reg, n->D, 1); + mcp_set_level(mcp, n->reg, n->C, 0); + mcp_set_level(mcp, n->reg, n->B, 0); + mcp_set_level(mcp, n->reg, n->A, 1); + break; + default: + mcp_set_level(mcp, n->reg, n->D, 1); + mcp_set_level(mcp, n->reg, n->C, 1); + mcp_set_level(mcp, n->reg, n->B, 1); + mcp_set_level(mcp, n->reg, n->A, 1); + break; + return; + } +} + +void test_screen(struct Screen* screen) +{ + while(1){ + for (uint8_t i = 0; i <= 9; ++i) { + for (uint8_t j = 0; j < 4; ++j) { + screen->nixies[j].digit = (i + j) % 10; // Update the digit cyclically + set_digit(screen->mcp, &(screen->nixies[j])); // Call set_digit function + } + sleep(1); + } + } +} + +void display(struct Screen* screen, char digits[4]) +{ + for (uint8_t i = 0; i < 4; ++i) { + screen->nixies[i].digit = digits[i] - '0'; + set_digit(screen->mcp, &(screen->nixies[i])); // Call set_digit function + } +} \ No newline at end of file diff --git a/components/screen/screen.h b/components/screen/screen.h new file mode 100644 index 0000000..b8b951c --- /dev/null +++ b/components/screen/screen.h @@ -0,0 +1,55 @@ +#ifndef SC_H +#define SC_H + +#include +#include +#include "driver/gpio.h" +#include "driver/i2c_master.h" + +#define MCP_I2C_ADDR CONFIG_MCP_I2C_ADDR +#define SDA_PIN CONFIG_SDA_PIN +#define SCL_PIN CONFIG_SCL_PIN +#define N0_P0 CONFIG_N0_P0 +#define N0_P1 CONFIG_N0_P1 +#define N0_P2 CONFIG_N0_P2 +#define N0_P3 CONFIG_N0_P3 +#define N1_P0 CONFIG_N1_P0 +#define N1_P1 CONFIG_N1_P1 +#define N1_P2 CONFIG_N1_P2 +#define N1_P3 CONFIG_N1_P3 +#define N2_P0 CONFIG_N2_P0 +#define N2_P1 CONFIG_N2_P1 +#define N2_P2 CONFIG_N2_P2 +#define N2_P3 CONFIG_N2_P3 +#define N3_P0 CONFIG_N3_P0 +#define N3_P1 CONFIG_N3_P1 +#define N3_P2 CONFIG_N3_P2 +#define N3_P3 CONFIG_N3_P3 +#define MCP_GPIO_OUTPUT 0 +#define REG_IODIRA 0x00 +#define REG_IODIRB 0x01 +#define REG_GPIOA 0x12 +#define REG_GPIOB 0x13 +#define BV(x) (1 << (x)) + +struct Nixie +{ + uint8_t digit; + uint8_t reg; + uint8_t D; + uint8_t C; + uint8_t B; + uint8_t A; +}; + +struct Screen +{ + struct Nixie nixies[4]; + i2c_master_bus_handle_t i2c_bus; + i2c_master_dev_handle_t mcp; +}; + +void configure_screen(struct Screen* screen); +void test_screen(struct Screen* screen); +void display(struct Screen* screen, char digits[4]); +#endif \ No newline at end of file -- cgit v1.2.3