diff --git a/components/badge23/audio.c b/components/badge23/audio.c index c94a650423388303f553782992e2d2c60499653f..ef37031ff2421a6b83c8142881e34fed426db401 100644 --- a/components/badge23/audio.c +++ b/components/badge23/audio.c @@ -1,10 +1,9 @@ #include "badge23/audio.h" -#include "badge23/lock.h" #include "st3m_scope.h" #include "driver/i2s.h" -#include "driver/i2c.h" +#include "flow3r_bsp_i2c.h" #include <freertos/FreeRTOS.h> #include <freertos/task.h> @@ -15,8 +14,6 @@ #define TIMEOUT_MS 1000 -#define I2C_MASTER_NUM 0 /*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip */ - static void audio_player_task(void* arg); #define DMA_BUFFER_SIZE 64 @@ -74,29 +71,27 @@ static uint8_t max98091_i2c_read(const uint8_t reg) { const uint8_t tx[] = {reg}; uint8_t rx[1]; - xSemaphoreTake(mutex_i2c, portMAX_DELAY); - esp_err_t ret = i2c_master_write_read_device(I2C_MASTER_NUM, 0x10, tx, sizeof(tx), rx, sizeof(rx), TIMEOUT_MS / portTICK_PERIOD_MS); - xSemaphoreGive(mutex_i2c); + flow3r_bsp_i2c_write_read_device(flow3r_i2c_addresses.codec, tx, sizeof(tx), rx, sizeof(rx), TIMEOUT_MS / portTICK_PERIOD_MS); + // TODO(q3k): handle error return rx[0]; } static esp_err_t max98091_i2c_write(const uint8_t reg, const uint8_t data) { const uint8_t tx[] = {reg, data}; - xSemaphoreTake(mutex_i2c, portMAX_DELAY); - esp_err_t ret = i2c_master_write_to_device(I2C_MASTER_NUM, 0x10, tx, sizeof(tx), TIMEOUT_MS / portTICK_PERIOD_MS); - xSemaphoreGive(mutex_i2c); - return ret; + return flow3r_bsp_i2c_write_to_device(flow3r_i2c_addresses.codec, tx, sizeof(tx), TIMEOUT_MS / portTICK_PERIOD_MS); } static esp_err_t max98091_i2c_write_readback(const uint8_t reg, const uint8_t data) { - const uint8_t tx[] = {reg, data}; - xSemaphoreTake(mutex_i2c, portMAX_DELAY); - esp_err_t ret = i2c_master_write_to_device(I2C_MASTER_NUM, 0x10, tx, sizeof(tx), TIMEOUT_MS / portTICK_PERIOD_MS); - xSemaphoreGive(mutex_i2c); - if(max98091_i2c_read(reg) != data) printf("readback of %04X to %02X write failed\n", data, reg); - return ret; + esp_err_t ret = max98091_i2c_write(reg, data); + if (ret != ESP_OK) { + return ret; + } + if (max98091_i2c_read(reg) != data) { + printf("readback of %04X to %02X write failed\n", data, reg); + } + return ESP_OK; } void audio_codec_i2c_write(const uint8_t reg, const uint8_t data) { diff --git a/components/badge23/captouch.c b/components/badge23/captouch.c index 93130ccf28c52032fc7ba055d0d67d08396a85d8..ff2c7b2e15ca85271fbc5094105db4100ea7d3ce 100644 --- a/components/badge23/captouch.c +++ b/components/badge23/captouch.c @@ -1,11 +1,10 @@ //#include <stdio.h> //#include <string.h> #include "esp_log.h" -#include "driver/i2c.h" #include <stdint.h> #include <freertos/FreeRTOS.h> #include <freertos/atomic.h> -#include "badge23/lock.h" +#include "flow3r_bsp_i2c.h" #define PETAL_PAD_TIP 0 #define PETAL_PAD_CCW 1 @@ -38,33 +37,24 @@ static const uint8_t bot_segment_map[] = {3,0,3,0,3,0,0,3,0,3}; //idk static const uint8_t bot_stage_config[] = {0,1,2,3,4,5,6,7,8,9,10,11}; #define DEFAULT_THRES_TOP 2000 #define DEFAULT_THRES_BOT 12000 -#define AD7147_ADDR_TOP 0b101101 -#define AD7147_ADDR_BOT 0b101100 #else #error "captouch not implemented for this badge generation" #endif #if defined(CONFIG_BADGE23_HW_GEN_P4) -#define AD7147_ADDR_TOP 0b101100 -#define AD7147_ADDR_BOT 0b101101 static const uint8_t top_segment_map[] = {1,3,2,2,3,1,1,3,2,1,3,2}; //PETAL_PAD_* static const uint8_t bot_segment_map[] = {3,0,3,0,0,0,3,0,3,1,2,3}; //PETAL_PAD_* #elif defined(CONFIG_BADGE23_HW_GEN_P6) -#define AD7147_ADDR_TOP 0b101100 -#define AD7147_ADDR_BOT 0b101101 static const uint8_t top_segment_map[] = {1,3,2,2,3,1,1,3,2,1,3,2}; //PETAL_PAD_* static const uint8_t bot_segment_map[] = {3,0,3,0,0,0,3,0,3,1,2,3}; //PETAL_PAD_* #elif defined(CONFIG_BADGE23_HW_GEN_P3) -#define AD7147_ADDR_TOP 0b101101 -#define AD7147_ADDR_BOT 0b101100 static const uint8_t top_segment_map[] = {0,1,2, 2,1,0, 0,1,2, 2,1,0}; //PETAL_PAD_* static const uint8_t bot_segment_map[] = {3,0,3,0,0,0,3,0,3, 0,2,1}; //PETAL_PAD_* #endif static const char *TAG = "captouch"; -#define I2C_MASTER_NUM 0 /*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip */ #define AD7147_REG_PWR_CONTROL 0x00 #define AD7147_REG_STAGE_CAL_EN 0x01 @@ -89,7 +79,7 @@ typedef struct{ static petal_t petals[10]; struct ad714x_chip { - uint8_t addr; + flow3r_i2c_address *addr; uint8_t gpio; int pos_afe_offsets[13]; int neg_afe_offsets[13]; @@ -97,29 +87,32 @@ struct ad714x_chip { int stages; }; -static struct ad714x_chip chip_top_rev5 = {.addr = AD7147_ADDR_TOP, .gpio = 15, +static struct ad714x_chip chip_top_rev5 = { + .addr = &flow3r_i2c_addresses.touch_top, + .gpio = 15, .pos_afe_offsets = {4, 2, 2, 2, 2, 3, 4, 2, 2, 2, 2, 0}, - .stages=top_stages}; -static struct ad714x_chip chip_bot_rev5 = {.addr = AD7147_ADDR_BOT, .gpio = 15, + .stages = top_stages, +}; + +static struct ad714x_chip chip_bot_rev5 = { + .addr = &flow3r_i2c_addresses.touch_bottom, + .gpio = 15, .pos_afe_offsets = {3, 2, 1, 1 ,1, 1, 1, 1, 2, 3, 3, 3}, - .stages=bot_stages}; + .stages = bot_stages, +}; static esp_err_t ad714x_i2c_write(const struct ad714x_chip *chip, const uint16_t reg, const uint16_t data) { const uint8_t tx[] = {reg >> 8, reg & 0xFF, data >> 8, data & 0xFF}; - xSemaphoreTake(mutex_i2c, portMAX_DELAY); ESP_LOGI(TAG, "AD7147 write reg %X-> %X", reg, data); - xSemaphoreGive(mutex_i2c); - return i2c_master_write_to_device(I2C_MASTER_NUM, chip->addr, tx, sizeof(tx), TIMEOUT_MS / portTICK_PERIOD_MS); + return flow3r_bsp_i2c_write_to_device(*chip->addr, tx, sizeof(tx), TIMEOUT_MS / portTICK_PERIOD_MS); } static esp_err_t ad714x_i2c_read(const struct ad714x_chip *chip, const uint16_t reg, uint16_t *data, const size_t len) { const uint8_t tx[] = {reg >> 8, reg & 0xFF}; uint8_t rx[len * 2]; - xSemaphoreTake(mutex_i2c, portMAX_DELAY); - esp_err_t ret = i2c_master_write_read_device(I2C_MASTER_NUM, chip->addr, tx, sizeof(tx), rx, sizeof(rx), TIMEOUT_MS / portTICK_PERIOD_MS); - xSemaphoreGive(mutex_i2c); + esp_err_t ret = flow3r_bsp_i2c_write_read_device(*chip->addr, tx, sizeof(tx), rx, sizeof(rx), TIMEOUT_MS / portTICK_PERIOD_MS); for(int i = 0; i < len; i++) { data[i] = (rx[i * 2] << 8) | rx[i * 2 + 1]; } diff --git a/components/badge23/espan.c b/components/badge23/espan.c index a261ca19b8307b04d1c17f7b02cb6bf44feebf08..0929b40b34c425e159417db8fe1a6c15bef65aa4 100644 --- a/components/badge23/espan.c +++ b/components/badge23/espan.c @@ -79,7 +79,6 @@ static void io_slow_task(void * data){ } void locks_init(){ - mutex_i2c = xSemaphoreCreateMutex(); mutex_LED = xSemaphoreCreateMutex(); } diff --git a/components/badge23/include/badge23/lock.h b/components/badge23/include/badge23/lock.h index 4e597f675651f207f26b11c4b883668957dd8c64..5f11a434df4a9ba4ed16abb708a5b92c13f051ee 100644 --- a/components/badge23/include/badge23/lock.h +++ b/components/badge23/include/badge23/lock.h @@ -3,5 +3,4 @@ #include <freertos/FreeRTOS.h> #include <freertos/semphr.h> -SemaphoreHandle_t mutex_i2c; SemaphoreHandle_t mutex_LED; diff --git a/components/badge23/spio.c b/components/badge23/spio.c index f57c80c865801a869a3fb6c9524356b8fc043943..1f1ecc040e8f7d4c851a1e60c9773495805d2144 100644 --- a/components/badge23/spio.c +++ b/components/badge23/spio.c @@ -5,8 +5,9 @@ #include "badge23/lock.h" #include "badge23/audio.h" +#include "flow3r_bsp_i2c.h" + #include "driver/i2c.h" -#define I2C_MASTER_NUM 0 #define TIMEOUT_MS 1000 #if defined(CONFIG_BADGE23_HW_GEN_P1) @@ -77,7 +78,7 @@ static uint8_t badge_link_enabled = 0; * if there's an outside shunt. */ typedef struct{ - uint8_t address; + flow3r_i2c_address *addr; uint8_t is_output_pin; // mask for pins we wish to use as outputs uint8_t read_state; // uint8_t output_state; // goal output state @@ -89,10 +90,8 @@ void _max7321_update(max7321_t *max){ uint8_t rx = 0; uint8_t tx = (~(max->is_output_pin)) | max->output_state; - xSemaphoreTake(mutex_i2c, portMAX_DELAY); - esp_err_t tx_error = i2c_master_write_to_device(I2C_MASTER_NUM, max->address, &tx, sizeof(tx), TIMEOUT_MS / portTICK_PERIOD_MS); - esp_err_t rx_error = i2c_master_read_from_device(I2C_MASTER_NUM, max->address, &rx, sizeof(rx), TIMEOUT_MS / portTICK_PERIOD_MS); - xSemaphoreGive(mutex_i2c); + flow3r_bsp_i2c_write_read_device(*max->addr, &tx, sizeof(tx), &rx, sizeof(rx), TIMEOUT_MS / portTICK_PERIOD_MS); + // TODO(q3k): handle error max->read_state = rx; } @@ -200,8 +199,8 @@ void update_button_state(){ #elif defined(CONFIG_BADGE23_HW_GEN_P3) || defined(CONFIG_BADGE23_HW_GEN_P4) -max7321_t port_expanders[] = { {0b01101110, 0, 255, 255}, - {0b01101101, 0, 255, 255} }; +max7321_t port_expanders[] = { {&flow3r_i2c_addresses.portexp[0], 0, 255, 255}, + {&flow3r_i2c_addresses.portexp[1], 0, 255, 255} }; static void _init_buttons(){ //configure all buttons as pullup @@ -257,8 +256,8 @@ void update_button_state(){ leftbutton = new_leftbutton; } #elif defined(CONFIG_BADGE23_HW_GEN_P6) -max7321_t port_expanders[] = { {0b01101110, 0, 255, 255}, - {0b01101101, 0, 255, 255} }; +max7321_t port_expanders[] = { {&flow3r_i2c_addresses.portexp[0], 0, 255, 255}, + {&flow3r_i2c_addresses.portexp[1], 0, 255, 255} }; static void _init_buttons(){ //configure all buttons as pullup diff --git a/components/flow3r_bsp/CMakeLists.txt b/components/flow3r_bsp/CMakeLists.txt index a15017d094bf85df30f677765b6d4235562999a0..fe5121c1321c8bd4130c5bdb7a6a8a6894dde08b 100644 --- a/components/flow3r_bsp/CMakeLists.txt +++ b/components/flow3r_bsp/CMakeLists.txt @@ -3,6 +3,7 @@ idf_component_register( flow3r_bsp_display.c flow3r_bsp_gc9a01.c flow3r_bsp_hwconfig.c + flow3r_bsp_i2c.c INCLUDE_DIRS . ) diff --git a/components/flow3r_bsp/flow3r_bsp.h b/components/flow3r_bsp/flow3r_bsp.h index 58ff3056c2be94c85eb104faf540899b8079f5bb..a1dceb4702422f257d7cc494631be3327fc6d25a 100644 --- a/components/flow3r_bsp/flow3r_bsp.h +++ b/components/flow3r_bsp/flow3r_bsp.h @@ -1,5 +1,7 @@ #pragma once +#include "flow3r_bsp_i2c.h" + #include <stdint.h> // Initialize badge display. An error will be reported if the initialization @@ -32,4 +34,4 @@ void flow3r_bsp_display_set_backlight(uint8_t percent); #define FLOW3R_BSP_DISPLAY_HEIGHT 240 // Badge hardware generation name, human-readable. -const char *flow3r_bsp_hw_name; \ No newline at end of file +const char *flow3r_bsp_hw_name; diff --git a/components/flow3r_bsp/flow3r_bsp_i2c.c b/components/flow3r_bsp/flow3r_bsp_i2c.c new file mode 100644 index 0000000000000000000000000000000000000000..f1695b81ec086f5953a8a0bc349f0113b7b53471 --- /dev/null +++ b/components/flow3r_bsp/flow3r_bsp_i2c.c @@ -0,0 +1,99 @@ +#include "flow3r_bsp_i2c.h" + +#include "driver/i2c.h" +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" + +static SemaphoreHandle_t mutex; + +static const char *TAG = "flow3r-bsp-i2c"; + +#if defined(CONFIG_BADGE23_HW_GEN_P1) +const flow3r_i2c_addressdef flow3r_i2c_addresses = { + .codec = 0, // p1 has no i2c control channel to codec. + .touch_top = 0x2d, + .touch_bottom = 0x2c, + .portexp = { 0x6e, 0x6d }, +}; +#elif defined(CONFIG_BADGE23_HW_GEN_P3) +const flow3r_i2c_addressdef flow3r_i2c_addresses = { + .codec = 0x10, + .touch_top = 0x2d, + .touch_bottom = 0x2c, + .portexp = { 0x6e, 0x6d }, +}; +#elif defined(CONFIG_BADGE23_HW_GEN_P4) +const flow3r_i2c_addressdef flow3r_i2c_addresses = { + .codec = 0x10, + .touch_top = 0x2c, + .touch_bottom = 0x2d, + .portexp = { 0x6e, 0x6d }, +}; +#elif defined(CONFIG_BADGE23_HW_GEN_P6) +const flow3r_i2c_addressdef flow3r_i2c_addresses = { + .codec = 0x10, + .touch_top = 0x2c, + .touch_bottom = 0x2d, + .portexp = { 0x6e, 0x6d }, +}; +#else +#error "i2c not implemented for this badge generation" +#endif + +#if defined(CONFIG_BADGE23_HW_GEN_P3) || defined(CONFIG_BADGE23_HW_GEN_P4) || defined(CONFIG_BADGE23_HW_GEN_P6) +static i2c_config_t i2c_conf = { + .mode = I2C_MODE_MASTER, + .sda_io_num = 2, + .scl_io_num = 1, + .sda_pullup_en = GPIO_PULLUP_ENABLE, + .scl_pullup_en = GPIO_PULLUP_ENABLE, + .master.clk_speed = 400000, +}; +#elif defined(CONFIG_BADGE23_HW_GEN_P1) +static i2c_config_t i2c_conf = { + .mode = I2C_MODE_MASTER, + .sda_io_num = 10, + .scl_io_num = 9, + .sda_pullup_en = GPIO_PULLUP_ENABLE, + .scl_pullup_en = GPIO_PULLUP_ENABLE, + .master.clk_speed = 400000, +}; +#else +#error "i2c not implemented for this badge generation" +#endif + +void flow3r_bsp_i2c_init(void) { + if (mutex != NULL) { + return; + } + + mutex = xSemaphoreCreateMutex(); + assert(mutex != NULL); + + assert(i2c_param_config(0, &i2c_conf) == ESP_OK); + assert(i2c_driver_install(0, i2c_conf.mode, 0, 0, 0) == ESP_OK); +} + +// Take I2C bus lock. +static void flow3r_bsp_i2c_get(void) { + xSemaphoreTake(mutex, portMAX_DELAY); +} + +// Release I2C bus lock. +static void flow3r_bsp_i2c_put(void) { + xSemaphoreGive(mutex); +} + +esp_err_t flow3r_bsp_i2c_write_to_device(uint8_t address, const uint8_t *buffer, size_t write_size, TickType_t ticks_to_wait) { + flow3r_bsp_i2c_get(); + esp_err_t res = i2c_master_write_to_device(0, address, buffer, write_size, ticks_to_wait); + flow3r_bsp_i2c_put(); + return res; +} + +esp_err_t flow3r_bsp_i2c_write_read_device(uint8_t address, const uint8_t *write_buffer, size_t write_size, uint8_t *read_buffer, size_t read_size, TickType_t ticks_to_wait) { + flow3r_bsp_i2c_get(); + esp_err_t res = i2c_master_write_read_device(0, address, write_buffer, write_size, read_buffer, read_size, ticks_to_wait); + flow3r_bsp_i2c_put(); + return res; +} \ No newline at end of file diff --git a/components/flow3r_bsp/flow3r_bsp_i2c.h b/components/flow3r_bsp/flow3r_bsp_i2c.h new file mode 100644 index 0000000000000000000000000000000000000000..f54ec6428e5cf89b267b8a2e8534015770e769ee --- /dev/null +++ b/components/flow3r_bsp/flow3r_bsp_i2c.h @@ -0,0 +1,38 @@ +#pragma once + +#include "freertos/FreeRTOS.h" + +// Type definition for device addresses on the main I2C bus of flow3r badges. +// This is a 7-bit address, which does not contain an R/W bit. +typedef uint8_t flow3r_i2c_address; + +// I2C addresses of different devices on a flow3r badge. Not all fields are +// applicable to all badge generations. +typedef struct { + // Address of the audio codec. + flow3r_i2c_address codec; + // Address of the captouch controller on the top board. + flow3r_i2c_address touch_top; + // Address of the captouch controller on the bottom board. + flow3r_i2c_address touch_bottom; + // Addresses of the port expander chips. + flow3r_i2c_address portexp[2]; +} flow3r_i2c_addressdef; + +// Global constant defining addresses for the badge generation that this +// firmware has been built for. +extern const flow3r_i2c_addressdef flow3r_i2c_addresses; + +// Initialize the badge's I2C subsystem. Must be called before any other +// flow3r_bsp_i2c_* calls. +void flow3r_bsp_i2c_init(void); + +// Perform a write transaction to a I2C device. +// +// This can be called concurrently from different tassks. +esp_err_t flow3r_bsp_i2c_write_to_device(flow3r_i2c_address address, const uint8_t *buffer, size_t write_size, TickType_t ticks_to_wait); + +// Perform a write-then read transaction on an I2C device. +// +// This can be called concurrently from different tassks. +esp_err_t flow3r_bsp_i2c_write_read_device(flow3r_i2c_address address, const uint8_t *write_buffer, size_t write_size, uint8_t *read_buffer, size_t read_size, TickType_t ticks_to_wait); \ No newline at end of file diff --git a/components/st3m/st3m_board_startup.c b/components/st3m/st3m_board_startup.c index 54f55de76ddac4b654231b3f1db31e4c9f389b4b..256d6966d45bc47d40bf73fef7282fd8a0393f4f 100644 --- a/components/st3m/st3m_board_startup.c +++ b/components/st3m/st3m_board_startup.c @@ -17,8 +17,9 @@ void st3m_board_startup(void) { } flow3r_bsp_display_set_backlight(100); + flow3r_bsp_i2c_init(); st3m_fs_init(); - // Handoff to badge23. - badge23_main(); + // Handoff to badge23. + badge23_main(); } \ No newline at end of file