diff --git a/src/driver/frankencnc.hal b/src/driver/frankencnc.hal index 8b6ce7a..285a9a6 100644 --- a/src/driver/frankencnc.hal +++ b/src/driver/frankencnc.hal @@ -131,13 +131,11 @@ net spindle-at-speed spindle.0.at-speed <= rp2040_eth.0.spindle.0.at-speed # GPIO setp rp2040_eth.0.gpio.00.type [RP2040_ETH_GPIO_TYPES]GPIO_TYPE_NATIVE_OUT_DEBUG setp rp2040_eth.0.gpio.00.index 6 -setp rp2040_eth.0.gpio.00.out 1 -setp rp2040_eth.0.gpio.00.out-invert false +setp rp2040_eth.0.gpio.00.in 0 setp rp2040_eth.0.gpio.01.type [RP2040_ETH_GPIO_TYPES]GPIO_TYPE_NATIVE_OUT_DEBUG setp rp2040_eth.0.gpio.01.index 7 -setp rp2040_eth.0.gpio.01.out 1 -setp rp2040_eth.0.gpio.01.out-invert true +setp rp2040_eth.0.gpio.01.in 0 setp rp2040_eth.0.gpio.02.type [RP2040_ETH_GPIO_TYPES]GPIO_TYPE_NATIVE_IN_DEBUG setp rp2040_eth.0.gpio.02.index 8 diff --git a/src/driver/rp2040_gpio_types.ini b/src/driver/rp2040_gpio_types.ini index 86bb2b9..ff092c8 100644 --- a/src/driver/rp2040_gpio_types.ini +++ b/src/driver/rp2040_gpio_types.ini @@ -8,4 +8,5 @@ GPIO_TYPE_NATIVE_OUT_DEBUG = 3 GPIO_TYPE_NATIVE_IN_DEBUG = 4 GPIO_TYPE_I2C_MCP_OUT = 5 GPIO_TYPE_I2C_MCP_IN = 6 +GPIO_TYPE_I2C_MCP_IN_PULLUP = 7 diff --git a/src/driver/rp2040_network.c b/src/driver/rp2040_network.c index 051db70..fa83ae9 100644 --- a/src/driver/rp2040_network.c +++ b/src/driver/rp2040_network.c @@ -249,6 +249,7 @@ uint16_t serialize_gpio(struct NWBuffer* buffer, skeleton_t* data) { case GPIO_TYPE_NATIVE_IN_DEBUG: case GPIO_TYPE_NATIVE_IN: case GPIO_TYPE_I2C_MCP_IN: + case GPIO_TYPE_I2C_MCP_IN_PULLUP: current_value = *data->gpio_data_in[gpio]; break; case GPIO_TYPE_NATIVE_OUT: @@ -266,10 +267,11 @@ uint16_t serialize_gpio(struct NWBuffer* buffer, skeleton_t* data) { if(current_value != received_value) { switch(*data->gpio_type[gpio]) { case GPIO_TYPE_NATIVE_IN_DEBUG: - printf("DBG: GPIO IN: %u val: %u\n", gpio, current_value); + printf("DBG: GPIO OUT: %u val: %u\n", gpio, current_value); // Note: no break here. case GPIO_TYPE_NATIVE_IN: case GPIO_TYPE_I2C_MCP_IN: + case GPIO_TYPE_I2C_MCP_IN_PULLUP: // Network update to apply. *data->gpio_data_in[gpio] = received_value; *data->gpio_data_in_not[gpio] = !received_value; @@ -278,7 +280,7 @@ uint16_t serialize_gpio(struct NWBuffer* buffer, skeleton_t* data) { confirmation_pending[bank] = true; break; case GPIO_TYPE_NATIVE_OUT_DEBUG: - printf("DBG: GPIO OUT: %u val: %u\n", gpio, current_value); + printf("DBG: GPIO IN: %u val: %u\n", gpio, current_value); // Note: no break here. case GPIO_TYPE_NATIVE_OUT: case GPIO_TYPE_I2C_MCP_OUT: diff --git a/src/rp2040/CMakeLists.txt b/src/rp2040/CMakeLists.txt index d91ca63..c375762 100644 --- a/src/rp2040/CMakeLists.txt +++ b/src/rp2040/CMakeLists.txt @@ -26,6 +26,8 @@ target_sources( network.c core0.c core1.c + i2c.c + mcp23017.c modbus.c modbus_fuling.c modbus_huanyang.c @@ -44,6 +46,7 @@ target_link_libraries( hardware_spi hardware_dma hardware_pio + hardware_i2c ETHERNET_FILES IOLIBRARY_FILES LOOPBACK_FILES diff --git a/src/rp2040/core0.c b/src/rp2040/core0.c index bdc8efc..3cc7523 100644 --- a/src/rp2040/core0.c +++ b/src/rp2040/core0.c @@ -6,6 +6,7 @@ #include "messages.h" #include "buffer.h" #include "gpio.h" +#include "i2c.h" #include "modbus.h" @@ -306,12 +307,12 @@ bool unpack_gpio_config( uint8_t index = message->index; uint8_t address = message->address; - printf("Configuring gpio. type: %u\tindex: %u\taddress: %u\tcount: %u\n", - gpio_type, index, address, gpio_count); + printf("%u Configuring gpio: %u\t%u\n", *received_count, gpio_type, gpio_count); - config.gpio[gpio_count].type = gpio_type; - config.gpio[gpio_count].index = index; - config.gpio[gpio_count].address = address; + volatile struct ConfigGPIO *cfg = &config.gpio[gpio_count]; + cfg->type = gpio_type; + cfg->index = index; + cfg->address = address; switch(gpio_type) { case GPIO_TYPE_NATIVE_OUT: @@ -331,6 +332,18 @@ bool unpack_gpio_config( gpio_set_dir(index, GPIO_IN); gpio_pull_up(index); break; + case GPIO_TYPE_I2C_MCP_OUT: + case GPIO_TYPE_I2C_MCP_IN: + case GPIO_TYPE_I2C_MCP_IN_PULLUP: + { + int i2c = gpio_i2c_mcp_alloc(address); + if (i2c >= 0) { + i2c_gpio_set_pin_config(&i2c_gpio, i2c, index, gpio_type); + } else { + printf("Error: Too many I2C addresses\n"); + } + break; + } default: break; } diff --git a/src/rp2040/core1.c b/src/rp2040/core1.c index 621b22d..f5a5913 100644 --- a/src/rp2040/core1.c +++ b/src/rp2040/core1.c @@ -13,8 +13,10 @@ #include "core1.h" #include "config.h" +#include "i2c.h" #include "pio.h" +struct i2c_gpio_state i2c_gpio; void update_all_joint() { static uint32_t metric = 0; @@ -34,6 +36,7 @@ void update_all_joint() { if(dt > update_period_us * MAX_MISSED_PACKET) { break; } + i2c_gpio_poll(&i2c_gpio); } if(tick == last_tick) { // Didn't receive tick semaphore. @@ -68,6 +71,7 @@ void update_all_joint() { for(uint8_t joint = 0; joint < MAX_JOINT; joint++) { do_steps(joint, update_period_us); } + i2c_gpio_poll(&i2c_gpio); } void core1_main() { @@ -78,6 +82,7 @@ void core1_main() { void init_core1() { printf("core0: Initializing.\n"); + i2c_gpio_init(&i2c_gpio); if(MAX_JOINT > 4) { printf("ERROR: Maximum joint count: 4. Configured: %u\n", MAX_JOINT); diff --git a/src/rp2040/gpio.c b/src/rp2040/gpio.c index c50f3cd..54dcc73 100644 --- a/src/rp2040/gpio.c +++ b/src/rp2040/gpio.c @@ -1,8 +1,9 @@ #include #include -#include "gpio.h" #include "config.h" +#include "gpio.h" +#include "i2c.h" #include "messages.h" #ifdef BUILD_TESTS @@ -32,22 +33,23 @@ void update_gpio_config( printf("ERROR: Higher than MAX_GPIO requested. %u\n", gpio); return; } + volatile struct ConfigGPIO *cfg = &config.gpio[gpio]; if(type != NULL) { - config.gpio[gpio].type = *type; + cfg->type = *type; } if(index != NULL) { if(*index > 32) { printf("WARN: GPIO index out of range. Add: %u Index: %u\n", *address, *index); } else { - config.gpio[gpio].index = *index; + cfg->index = *index; } } if(address != NULL) { - config.gpio[gpio].address = *address; + cfg->address = *address; } if(value != NULL) { - config.gpio[gpio].value = *value; + cfg->value = *value; } } @@ -97,7 +99,7 @@ void gpio_set_values(const uint8_t bank, uint32_t values) { switch(config.gpio[gpio].type) { case GPIO_TYPE_NATIVE_OUT_DEBUG: - printf("DBG GPIO OUT: %u IO: %u val: %u\n", gpio, index, new_value); + printf("DBG GPIO: %u IO: %u val: %u\n", gpio, index, new_value); // Note: no break. case GPIO_TYPE_NATIVE_OUT: gpio_local_set_out_pin(index, new_value); @@ -122,68 +124,57 @@ bool gpio_local_get_pin(uint32_t index) { return gpio_get(index); } -/* Happens before iterating through gpio data. - * Do any i2c required operations here. */ -void gpio_i2c_mcp_prepare() { - for(uint8_t i2c_bucket = 0; i2c_bucket < MAX_I2C_MCP; i2c_bucket++) { - // uint8_t i2c_address = gpio_i2c_mcp_addresses[i2c_bucket]; - // TODO: Any other MCP implementation here. +int gpio_i2c_mcp_alloc(uint8_t address) { + int i2c = 0, i2c_free = -1; + for(i2c = 0; i2c < MAX_I2C_MCP; i2c++) { + if(gpio_i2c_mcp_addresses[i2c] == address) { + return i2c; + } + if(gpio_i2c_mcp_addresses[i2c] == 0xFF && i2c_free == -1) { + i2c_free = i2c; + } } + if (i2c_free != -1) { + gpio_i2c_mcp_addresses[i2c_free] = address; + i2c_gpio.config[i2c_free].i2c_address = address; + i2c_gpio.config[i2c_free].type = I2CGPIO_TYPE_MCP23017; + } + return i2c_free; } /* Find all GPIO pins sharing the same i2c address and put */ void gpio_i2c_mcp_set_out_pin(uint8_t index, uint8_t address, bool new_value) { // Find which slot this i2c address is being stored in. - uint8_t i2c = MAX_I2C_MCP; - for(i2c = 0; i2c < MAX_I2C_MCP; i2c++) { - if(gpio_i2c_mcp_addresses[i2c] == address) { - break; - } - if (gpio_i2c_mcp_addresses[i2c] == 0xff) { - // Haven't found this address yet. - // Since this buffer slot is empty, use it for this address. - gpio_i2c_mcp_addresses[i2c] = address; - break; - } - } + int i2c = gpio_i2c_mcp_alloc(address); - if(i2c >= MAX_I2C_MCP) { + if(i2c == -1) { printf("WARN: Too may i2c addresses. Add: %u Index: %u\n", address, index); return; } // Add new_value to buffer to be sent to this i2c address. + uint8_t bindex = (index >> 3) & 1; + uint8_t bitmask = 0x1 << (index & 7); + uint8_t *data = &i2c_gpio.config[i2c].output_data[bindex]; if(new_value) { - gpio_i2c_mcp_indexes[i2c] |= (0x1 << index); + *data |= bitmask; } else { - gpio_i2c_mcp_indexes[i2c] &= (~(0x1 << index)); + *data &= ~bitmask; } } -/* Happens after iterating through GPIO data. - * Do any i2c required operations here. */ -void gpio_i2c_mcp_tranceive() { - for(uint8_t i2c_bucket = 0; i2c_bucket < MAX_I2C_MCP; i2c_bucket++) { - // Write gpio_i2c_mcp_indexes[i2c] as output - // then read inputs into same buffer. - uint8_t values = gpio_i2c_mcp_indexes[i2c_bucket]; - uint8_t address = gpio_i2c_mcp_addresses[i2c_bucket]; - // TODO: Send values to the i2c connected MCP. - printf("i2c addr: %u values: %#04x\n", address, values); - - // TODO: Read i2c data into gpio_i2c_mcp_indexes[MAX_I2C_MCP] for later - // UDP transmission. - } -} - -bool gpio_i2c_mcp_get_pin(uint8_t index, uint8_t address) { - for(uint8_t i2c = 0; i2c < MAX_I2C_MCP; i2c++) { - if(gpio_i2c_mcp_addresses[i2c] == address) { - return gpio_i2c_mcp_indexes[i2c] | (0x1 << index); - } +bool gpio_i2c_mcp_get_pin(uint8_t index, uint8_t address, uint8_t pullup) { + int i2c = gpio_i2c_mcp_alloc(address); + if(i2c == -1) { + printf("WARN: Too may i2c addresses. Add: %u Index: %u\n", address, index); + return false; } - return 0; + uint8_t bindex = (index >> 3) & 1; + uint8_t bmask = (1 << (index & 7)); + uint8_t data = i2c_gpio.config[i2c].input_data[bindex]; + //printf("%02x:%d = %d [%02x, %02x]\n", address, index, (data & bmask), data, bmask); + return data & bmask ? 1 : 0; } /* Pack GPIO inputs in buffer for UDP transmission. */ @@ -209,7 +200,7 @@ void gpio_serialize(struct NWBuffer* tx_buf, size_t* tx_buf_len) { get_gpio_config(gpio, &type, &index, &address, &previous_value); - switch(config.gpio[gpio].type) { + switch(type) { case GPIO_TYPE_NATIVE_IN_DEBUG: case GPIO_TYPE_NATIVE_IN: new_value = gpio_local_get_pin(index); @@ -221,7 +212,8 @@ void gpio_serialize(struct NWBuffer* tx_buf, size_t* tx_buf_len) { } break; case GPIO_TYPE_I2C_MCP_IN: - new_value = gpio_i2c_mcp_get_pin(index, address); + case GPIO_TYPE_I2C_MCP_IN_PULLUP: + new_value = gpio_i2c_mcp_get_pin(index, address, type == GPIO_TYPE_I2C_MCP_IN_PULLUP); if(previous_value != new_value) { to_send[bank] = true; config.gpio_confirmation_pending[bank] = true; @@ -242,20 +234,20 @@ void gpio_serialize(struct NWBuffer* tx_buf, size_t* tx_buf_len) { reply.type = REPLY_GPIO; for(uint8_t bank = 0; bank < MAX_GPIO_BANK; bank++) { - if(! config.gpio_confirmation_pending[bank]) { - continue; - } + if(! config.gpio_confirmation_pending[bank]) { + continue; + } - reply.bank = bank; - reply.values = values[bank]; - reply.confirmation_pending = to_send[bank]; + reply.bank = bank; + reply.values = values[bank]; + reply.confirmation_pending = to_send[bank]; - *tx_buf_len = pack_nw_buff(tx_buf, &reply, sizeof(reply)); + *tx_buf_len = pack_nw_buff(tx_buf, &reply, sizeof(reply)); - if(! *tx_buf_len) { - printf("WARN: TX length greater than buffer size. gpio bank: %u\n", bank); - return; - } + if(! *tx_buf_len) { + printf("WARN: TX length greater than buffer size. gpio bank: %u\n", bank); + return; + } } } diff --git a/src/rp2040/gpio.h b/src/rp2040/gpio.h index ee04ba5..1d4cc60 100644 --- a/src/rp2040/gpio.h +++ b/src/rp2040/gpio.h @@ -30,14 +30,11 @@ void gpio_set_values(const uint8_t bank, uint32_t values); void gpio_local_set_out_pin(uint8_t index, bool new_value); -/* Happens before gpio data destined for i2c has been gathered. */ -void gpio_i2c_mcp_prepare(); - /* Put i2c data in temporary buffer pending gpio_i2c_mcp_tranceive() being called. */ void gpio_i2c_mcp_set_out_pin(uint8_t index, uint8_t address, bool new_value); -/* Happens after all gpio data destined for i2c has been gathered. */ -void gpio_i2c_mcp_tranceive(); +/* Convert I2C address to the slot number */ +int gpio_i2c_mcp_alloc(uint8_t address); /* Pack GPIO inputs in buffer for UDP transmission. */ void gpio_serialize(struct NWBuffer* tx_buf, size_t* tx_buf_len); diff --git a/src/shared/messages.h b/src/shared/messages.h index d4a386d..fbc5104 100644 --- a/src/shared/messages.h +++ b/src/shared/messages.h @@ -210,5 +210,6 @@ union ReplyAny { #define GPIO_TYPE_NATIVE_IN_DEBUG 4 #define GPIO_TYPE_I2C_MCP_OUT 5 #define GPIO_TYPE_I2C_MCP_IN 6 +#define GPIO_TYPE_I2C_MCP_IN_PULLUP 7 #endif // UPDATE_TYPES__H