diff options
Diffstat (limited to 'main')
-rw-r--r-- | main/CMakeLists.txt | 3 | ||||
-rw-r--r-- | main/Kconfig.projbuild | 148 | ||||
-rw-r--r-- | main/main.c | 235 |
3 files changed, 302 insertions, 84 deletions
diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index cf2c455..46af1ea 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -1,2 +1,3 @@ idf_component_register(SRCS "main.c" - INCLUDE_DIRS ".") + INCLUDE_DIRS "." + REQUIRES esp_driver_gpio esp_driver_i2c) diff --git a/main/Kconfig.projbuild b/main/Kconfig.projbuild new file mode 100644 index 0000000..18b0727 --- /dev/null +++ b/main/Kconfig.projbuild @@ -0,0 +1,148 @@ +menu "Configuration of the Nixie Screen" + + orsource "$IDF_PATH/examples/common_components/env_caps/$IDF_TARGET/Kconfig.env_caps" + + config MCP_I2C_ADDR + hex "I2C address of mcp23017" + default 0x20 + help + I2C address of `mcp23017`. `mcp23017` has three address pins (`A0`, + `A1`, and `A2`). The address starts from `0x20` (all pins are + grounded), which is the default, and ends at `0x27`. See "3.3.1 + ADDRESSING I2C DEVICES (MCP23017)" in the datasheet. + + config SDA_PIN + int "SDA pin number" + range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX + default 6 + help + Pin number for SDA pin. + + config SCL_PIN + int "SCL pin number" + range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX + default 7 + help + Pin number for SLC pin. + + config MIN + int + default 0 + + config MAX + int + default 7 + + config N0_P0 + int "N0_P0 pin number" + range MIN MAX + default 4 + help + Pin number for N0_P0. + + config N0_P1 + int "N0_P1 pin number" + range MIN MAX + default 5 + help + Pin number for N0_P1. + + config N0_P2 + int "N0_P2 pin number" + range MIN MAX + default 6 + help + Pin number for N0_P2. + + config N0_P3 + int "N0_P3 pin number" + range MIN MAX + default 7 + help + Pin number for N0_P3. + + config N1_P0 + int "N1_P0 pin number" + range MIN MAX + default 0 + help + Pin number for N1_P0. + + config N1_P1 + int "N1_P1 pin number" + range MIN MAX + default 1 + help + Pin number for N1_P1. + + config N1_P2 + int "N1_P2 pin number" + range MIN MAX + default 2 + help + Pin number for N1_P2. + + config N1_P3 + int "N1_P3 pin number" + range MIN MAX + default 3 + help + Pin number for N1_P3. + + config N2_P0 + int "N2_P0 pin number" + range MIN MAX + default 4 + help + Pin number for N2_P0. + + config N2_P1 + int "N2_P1 pin number" + range MIN MAX + default 5 + help + Pin number for N2_P1. + + config N2_P2 + int "N2_P2 pin number" + range MIN MAX + default 6 + help + Pin number for N2_P2. + + config N2_P3 + int "N2_P3 pin number" + range MIN MAX + default 7 + help + Pin number for N2_P3. + + config N3_P0 + int "N3_P0 pin number" + range MIN MAX + default 0 + help + Pin number for N3_P0. + + config N3_P1 + int "N3_P1 pin number" + range MIN MAX + default 1 + help + Pin number for N3_P1. + + config N3_P2 + int "N3_P2 pin number" + range MIN MAX + default 2 + help + Pin number for N3_P2. + + config N3_P3 + int "N3_P3 pin number" + range MIN MAX + default 3 + help + Pin number for N3_P3. + +endmenu
\ No newline at end of file diff --git a/main/main.c b/main/main.c index c44352c..a7f2019 100644 --- a/main/main.c +++ b/main/main.c @@ -1,18 +1,11 @@ #include <stdio.h> #include <unistd.h> #include "driver/gpio.h" +#include "driver/i2c_master.h" -struct Nixie -{ - uint8_t digit; - uint8_t D; - uint8_t C; - uint8_t B; - uint8_t A; -}; - -struct Nixie screen[4]; - +#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 @@ -29,52 +22,116 @@ struct Nixie screen[4]; #define N3_P1 CONFIG_N3_P1 #define N3_P2 CONFIG_N3_P2 #define N3_P3 CONFIG_N3_P3 -#define GPIO_OUTPUT_PIN_SEL ((1ULL<<N0_P0) | (1ULL<<N0_P1) | (1ULL<<N0_P2) | (1ULL<<N0_P3) | (1ULL<<N1_P0) | (1ULL<<N1_P1) | (1ULL<<N1_P2) | (1ULL<<N1_P3) | (1ULL<<N2_P0) | (1ULL<<N2_P1) | (1ULL<<N2_P2) | (1ULL<<N2_P3) | (1ULL<<N3_P0) | (1ULL<<N3_P1) | (1ULL<<N3_P2) | (1ULL<<N3_P3)) -/* - * Let's say, GPIO_OUTPUT_IO_0=18, GPIO_OUTPUT_IO_1=19 - * In binary representation, - * 1ULL<<GPIO_OUTPUT_IO_0 is equal to 0000000000000000000001000000000000000000 and - * 1ULL<<GPIO_OUTPUT_IO_1 is equal to 0000000000000000000010000000000000000000 - * GPIO_OUTPUT_PIN_SEL 0000000000000000000011000000000000000000 - * */ +#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 Nixie screen[4]; +i2c_master_bus_handle_t i2c_bus; +i2c_master_dev_handle_t mcp; + + +esp_err_t write_reg_bit_16(uint8_t reg, bool val, uint8_t bit) +{ + uint8_t buf[3]; + + // 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(uint8_t reg, uint8_t pin, bool mode) +{ + return write_reg_bit_16(reg, mode, pin); +} + +esp_err_t mcp_set_level(uint8_t reg, uint8_t pin, bool val) +{ + return write_reg_bit_16(reg, val, pin); + +} void configure_screen(void) { - //zero-initialize the config structure. - gpio_config_t io_conf = {}; - //disable interrupt - io_conf.intr_type = GPIO_INTR_DISABLE; - //set as output mode - io_conf.mode = GPIO_MODE_OUTPUT; - //bit mask of the pins that you want to set,e.g.GPIO18/19 - io_conf.pin_bit_mask = GPIO_OUTPUT_PIN_SEL; - //disable pull-down mode - io_conf.pull_down_en = 0; - //disable pull-up mode - io_conf.pull_up_en = 0; - //configure GPIO with the given settings - gpio_config(&io_conf); + 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, &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(i2c_bus, &mcp_cfg, &mcp)); + + printf("I2C MCP Configured!\n"); screen[0].digit = 0; + screen[0].reg = REG_GPIOA; screen[0].C = N0_P0; screen[0].B = N0_P1; screen[0].D = N0_P2; screen[0].A = N0_P3; screen[1].digit = 0; + screen[1].reg = REG_GPIOA; screen[1].C = N1_P0; screen[1].B = N1_P1; screen[1].D = N1_P2; screen[1].A = N1_P3; screen[2].digit = 0; + screen[2].reg = REG_GPIOB; screen[2].C = N2_P0; screen[2].B = N2_P1; screen[2].D = N2_P2; screen[2].A = N2_P3; screen[3].digit = 0; + screen[3].reg = REG_GPIOB; screen[3].C = N3_P0; screen[3].B = N3_P1; screen[3].D = N3_P2; screen[3].A = N3_P3; + + for (uint8_t i = 0; i <= 3; ++i) + { + uint8_t reg = REG_IODIRA; + if(i > 1) reg = REG_IODIRB; + mcp_set_mode(reg, screen[i].D, MCP_GPIO_OUTPUT); + mcp_set_mode(reg, screen[i].C, MCP_GPIO_OUTPUT); + mcp_set_mode(reg, screen[i].B, MCP_GPIO_OUTPUT); + mcp_set_mode(reg, screen[i].A, MCP_GPIO_OUTPUT); + } + + + printf("MCP GPIO Configured!\n"); return; } @@ -82,81 +139,93 @@ void set_digit(struct Nixie* n) { switch (n->digit) { case 0: - gpio_set_level(n->D, 0); - gpio_set_level(n->C, 0); - gpio_set_level(n->B, 0); - gpio_set_level(n->A, 0); + mcp_set_level(n->reg, n->D, 0); + mcp_set_level(n->reg, n->C, 0); + mcp_set_level(n->reg, n->B, 0); + mcp_set_level(n->reg, n->A, 0); break; case 1: - gpio_set_level(n->D, 0); - gpio_set_level(n->C, 0); - gpio_set_level(n->B, 0); - gpio_set_level(n->A, 1); + mcp_set_level(n->reg, n->D, 0); + mcp_set_level(n->reg, n->C, 0); + mcp_set_level(n->reg, n->B, 0); + mcp_set_level(n->reg, n->A, 1); break; case 2: - gpio_set_level(n->D, 0); - gpio_set_level(n->C, 0); - gpio_set_level(n->B, 1); - gpio_set_level(n->A, 0); + mcp_set_level(n->reg, n->D, 0); + mcp_set_level(n->reg, n->C, 0); + mcp_set_level(n->reg, n->B, 1); + mcp_set_level(n->reg, n->A, 0); break; case 3: - gpio_set_level(n->D, 0); - gpio_set_level(n->C, 0); - gpio_set_level(n->B, 1); - gpio_set_level(n->A, 1); + mcp_set_level(n->reg, n->D, 0); + mcp_set_level(n->reg, n->C, 0); + mcp_set_level(n->reg, n->B, 1); + mcp_set_level(n->reg, n->A, 1); break; case 4: - gpio_set_level(n->D, 0); - gpio_set_level(n->C, 1); - gpio_set_level(n->B, 0); - gpio_set_level(n->A, 0); - break; - case 5: - gpio_set_level(n->D, 0); - gpio_set_level(n->C, 1); - gpio_set_level(n->B, 0); - gpio_set_level(n->A, 1); - break; - case 6: - gpio_set_level(n->D, 0); - gpio_set_level(n->C, 1); - gpio_set_level(n->B, 1); - gpio_set_level(n->A, 0); + mcp_set_level(n->reg, n->D, 0); + mcp_set_level(n->reg, n->C, 1); + mcp_set_level(n->reg, n->B, 0); + mcp_set_level(n->reg, n->A, 0); + break; + case 5: + mcp_set_level(n->reg, n->D, 0); + mcp_set_level(n->reg, n->C, 1); + mcp_set_level(n->reg, n->B, 0); + mcp_set_level(n->reg, n->A, 1); + break; + case 6: + mcp_set_level(n->reg, n->D, 0); + mcp_set_level(n->reg, n->C, 1); + mcp_set_level(n->reg, n->B, 1); + mcp_set_level(n->reg, n->A, 0); break; case 7: - gpio_set_level(n->D, 0); - gpio_set_level(n->C, 1); - gpio_set_level(n->B, 1); - gpio_set_level(n->A, 1); + mcp_set_level(n->reg, n->D, 0); + mcp_set_level(n->reg, n->C, 1); + mcp_set_level(n->reg, n->B, 1); + mcp_set_level(n->reg, n->A, 1); break; case 8: - gpio_set_level(n->D, 1); - gpio_set_level(n->C, 0); - gpio_set_level(n->B, 0); - gpio_set_level(n->A, 0); + mcp_set_level(n->reg, n->D, 1); + mcp_set_level(n->reg, n->C, 0); + mcp_set_level(n->reg, n->B, 0); + mcp_set_level(n->reg, n->A, 0); break; case 9: - gpio_set_level(n->D, 1); - gpio_set_level(n->C, 0); - gpio_set_level(n->B, 0); - gpio_set_level(n->A, 1); + mcp_set_level(n->reg, n->D, 1); + mcp_set_level(n->reg, n->C, 0); + mcp_set_level(n->reg, n->B, 0); + mcp_set_level(n->reg, n->A, 1); break; default: + mcp_set_level(n->reg, n->D, 1); + mcp_set_level(n->reg, n->C, 1); + mcp_set_level(n->reg, n->B, 1); + mcp_set_level(n->reg, n->A, 1); break; return; } } -void app_main(void) +void test_screen(void) { - printf("N1_P3: %i\n", N1_P3); + printf("Starting up...\n"); configure_screen(); + printf("Screen Configured!\n"); + while(1){ for (uint8_t i = 0; i <= 9; ++i) { - printf("digit: %i\n", i); - screen[0].digit = i; // Update the digit - set_digit(&screen[0]); // Call set_digit function - sleep(1); // Sleep for 2 seconds + for (int j = 0; j < 4; ++j) { + screen[j].digit = (i + j) % 10; // Update the digit cyclically + set_digit(&screen[j]); // Call set_digit function + } + sleep(1); } } } + +void app_main(void) +{ + test_screen(); +}
\ No newline at end of file |