Skip to content
Snippets Groups Projects
Commit c57a8abf authored by q3k's avatar q3k Committed by ch3
Browse files

components/flow3r_bsp: init i2c library

This moves all I2C addresses and locking logic into the BSP.
parent 62217440
No related branches found
No related tags found
No related merge requests found
#include "badge23/audio.h" #include "badge23/audio.h"
#include "badge23/lock.h"
#include "st3m_scope.h" #include "st3m_scope.h"
#include "driver/i2s.h" #include "driver/i2s.h"
#include "driver/i2c.h" #include "flow3r_bsp_i2c.h"
#include <freertos/FreeRTOS.h> #include <freertos/FreeRTOS.h>
#include <freertos/task.h> #include <freertos/task.h>
...@@ -15,8 +14,6 @@ ...@@ -15,8 +14,6 @@
#define TIMEOUT_MS 1000 #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); static void audio_player_task(void* arg);
#define DMA_BUFFER_SIZE 64 #define DMA_BUFFER_SIZE 64
...@@ -74,30 +71,28 @@ static uint8_t max98091_i2c_read(const uint8_t reg) ...@@ -74,30 +71,28 @@ static uint8_t max98091_i2c_read(const uint8_t reg)
{ {
const uint8_t tx[] = {reg}; const uint8_t tx[] = {reg};
uint8_t rx[1]; uint8_t rx[1];
xSemaphoreTake(mutex_i2c, portMAX_DELAY); flow3r_bsp_i2c_write_read_device(flow3r_i2c_addresses.codec, tx, sizeof(tx), rx, sizeof(rx), TIMEOUT_MS / portTICK_PERIOD_MS);
esp_err_t ret = i2c_master_write_read_device(I2C_MASTER_NUM, 0x10, tx, sizeof(tx), rx, sizeof(rx), TIMEOUT_MS / portTICK_PERIOD_MS); // TODO(q3k): handle error
xSemaphoreGive(mutex_i2c);
return rx[0]; return rx[0];
} }
static esp_err_t max98091_i2c_write(const uint8_t reg, const uint8_t data) static esp_err_t max98091_i2c_write(const uint8_t reg, const uint8_t data)
{ {
const uint8_t tx[] = {reg, data}; const uint8_t tx[] = {reg, data};
xSemaphoreTake(mutex_i2c, portMAX_DELAY); return flow3r_bsp_i2c_write_to_device(flow3r_i2c_addresses.codec, tx, sizeof(tx), TIMEOUT_MS / portTICK_PERIOD_MS);
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;
} }
static esp_err_t max98091_i2c_write_readback(const uint8_t reg, const uint8_t data) static esp_err_t max98091_i2c_write_readback(const uint8_t reg, const uint8_t data)
{ {
const uint8_t tx[] = {reg, data}; esp_err_t ret = max98091_i2c_write(reg, data);
xSemaphoreTake(mutex_i2c, portMAX_DELAY); if (ret != ESP_OK) {
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; 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) { void audio_codec_i2c_write(const uint8_t reg, const uint8_t data) {
max98091_i2c_write_readback(reg, data); max98091_i2c_write_readback(reg, data);
......
//#include <stdio.h> //#include <stdio.h>
//#include <string.h> //#include <string.h>
#include "esp_log.h" #include "esp_log.h"
#include "driver/i2c.h"
#include <stdint.h> #include <stdint.h>
#include <freertos/FreeRTOS.h> #include <freertos/FreeRTOS.h>
#include <freertos/atomic.h> #include <freertos/atomic.h>
#include "badge23/lock.h" #include "flow3r_bsp_i2c.h"
#define PETAL_PAD_TIP 0 #define PETAL_PAD_TIP 0
#define PETAL_PAD_CCW 1 #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 ...@@ -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}; 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_TOP 2000
#define DEFAULT_THRES_BOT 12000 #define DEFAULT_THRES_BOT 12000
#define AD7147_ADDR_TOP 0b101101
#define AD7147_ADDR_BOT 0b101100
#else #else
#error "captouch not implemented for this badge generation" #error "captouch not implemented for this badge generation"
#endif #endif
#if defined(CONFIG_BADGE23_HW_GEN_P4) #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 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_* 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) #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 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_* 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) #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 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_* static const uint8_t bot_segment_map[] = {3,0,3,0,0,0,3,0,3, 0,2,1}; //PETAL_PAD_*
#endif #endif
static const char *TAG = "captouch"; 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_PWR_CONTROL 0x00
#define AD7147_REG_STAGE_CAL_EN 0x01 #define AD7147_REG_STAGE_CAL_EN 0x01
...@@ -89,7 +79,7 @@ typedef struct{ ...@@ -89,7 +79,7 @@ typedef struct{
static petal_t petals[10]; static petal_t petals[10];
struct ad714x_chip { struct ad714x_chip {
uint8_t addr; flow3r_i2c_address *addr;
uint8_t gpio; uint8_t gpio;
int pos_afe_offsets[13]; int pos_afe_offsets[13];
int neg_afe_offsets[13]; int neg_afe_offsets[13];
...@@ -97,29 +87,32 @@ struct ad714x_chip { ...@@ -97,29 +87,32 @@ struct ad714x_chip {
int stages; 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}, .pos_afe_offsets = {4, 2, 2, 2, 2, 3, 4, 2, 2, 2, 2, 0},
.stages=top_stages}; .stages = top_stages,
static struct ad714x_chip chip_bot_rev5 = {.addr = AD7147_ADDR_BOT, .gpio = 15, };
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}, .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) 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}; 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); ESP_LOGI(TAG, "AD7147 write reg %X-> %X", reg, data);
xSemaphoreGive(mutex_i2c); return flow3r_bsp_i2c_write_to_device(*chip->addr, tx, sizeof(tx), TIMEOUT_MS / portTICK_PERIOD_MS);
return i2c_master_write_to_device(I2C_MASTER_NUM, 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) 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}; const uint8_t tx[] = {reg >> 8, reg & 0xFF};
uint8_t rx[len * 2]; uint8_t rx[len * 2];
xSemaphoreTake(mutex_i2c, portMAX_DELAY); esp_err_t ret = flow3r_bsp_i2c_write_read_device(*chip->addr, tx, sizeof(tx), rx, sizeof(rx), TIMEOUT_MS / portTICK_PERIOD_MS);
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);
for(int i = 0; i < len; i++) { for(int i = 0; i < len; i++) {
data[i] = (rx[i * 2] << 8) | rx[i * 2 + 1]; data[i] = (rx[i * 2] << 8) | rx[i * 2 + 1];
} }
......
...@@ -79,7 +79,6 @@ static void io_slow_task(void * data){ ...@@ -79,7 +79,6 @@ static void io_slow_task(void * data){
} }
void locks_init(){ void locks_init(){
mutex_i2c = xSemaphoreCreateMutex();
mutex_LED = xSemaphoreCreateMutex(); mutex_LED = xSemaphoreCreateMutex();
} }
......
...@@ -3,5 +3,4 @@ ...@@ -3,5 +3,4 @@
#include <freertos/FreeRTOS.h> #include <freertos/FreeRTOS.h>
#include <freertos/semphr.h> #include <freertos/semphr.h>
SemaphoreHandle_t mutex_i2c;
SemaphoreHandle_t mutex_LED; SemaphoreHandle_t mutex_LED;
...@@ -5,8 +5,9 @@ ...@@ -5,8 +5,9 @@
#include "badge23/lock.h" #include "badge23/lock.h"
#include "badge23/audio.h" #include "badge23/audio.h"
#include "flow3r_bsp_i2c.h"
#include "driver/i2c.h" #include "driver/i2c.h"
#define I2C_MASTER_NUM 0
#define TIMEOUT_MS 1000 #define TIMEOUT_MS 1000
#if defined(CONFIG_BADGE23_HW_GEN_P1) #if defined(CONFIG_BADGE23_HW_GEN_P1)
...@@ -77,7 +78,7 @@ static uint8_t badge_link_enabled = 0; ...@@ -77,7 +78,7 @@ static uint8_t badge_link_enabled = 0;
* if there's an outside shunt. * if there's an outside shunt.
*/ */
typedef struct{ 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 is_output_pin; // mask for pins we wish to use as outputs
uint8_t read_state; // uint8_t read_state; //
uint8_t output_state; // goal output state uint8_t output_state; // goal output state
...@@ -89,10 +90,8 @@ void _max7321_update(max7321_t *max){ ...@@ -89,10 +90,8 @@ void _max7321_update(max7321_t *max){
uint8_t rx = 0; uint8_t rx = 0;
uint8_t tx = (~(max->is_output_pin)) | max->output_state; uint8_t tx = (~(max->is_output_pin)) | max->output_state;
xSemaphoreTake(mutex_i2c, portMAX_DELAY); flow3r_bsp_i2c_write_read_device(*max->addr, &tx, sizeof(tx), &rx, sizeof(rx), TIMEOUT_MS / portTICK_PERIOD_MS);
esp_err_t tx_error = i2c_master_write_to_device(I2C_MASTER_NUM, max->address, &tx, sizeof(tx), TIMEOUT_MS / portTICK_PERIOD_MS); // TODO(q3k): handle error
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);
max->read_state = rx; max->read_state = rx;
} }
...@@ -200,8 +199,8 @@ void update_button_state(){ ...@@ -200,8 +199,8 @@ void update_button_state(){
#elif defined(CONFIG_BADGE23_HW_GEN_P3) || defined(CONFIG_BADGE23_HW_GEN_P4) #elif defined(CONFIG_BADGE23_HW_GEN_P3) || defined(CONFIG_BADGE23_HW_GEN_P4)
max7321_t port_expanders[] = { {0b01101110, 0, 255, 255}, max7321_t port_expanders[] = { {&flow3r_i2c_addresses.portexp[0], 0, 255, 255},
{0b01101101, 0, 255, 255} }; {&flow3r_i2c_addresses.portexp[1], 0, 255, 255} };
static void _init_buttons(){ static void _init_buttons(){
//configure all buttons as pullup //configure all buttons as pullup
...@@ -257,8 +256,8 @@ void update_button_state(){ ...@@ -257,8 +256,8 @@ void update_button_state(){
leftbutton = new_leftbutton; leftbutton = new_leftbutton;
} }
#elif defined(CONFIG_BADGE23_HW_GEN_P6) #elif defined(CONFIG_BADGE23_HW_GEN_P6)
max7321_t port_expanders[] = { {0b01101110, 0, 255, 255}, max7321_t port_expanders[] = { {&flow3r_i2c_addresses.portexp[0], 0, 255, 255},
{0b01101101, 0, 255, 255} }; {&flow3r_i2c_addresses.portexp[1], 0, 255, 255} };
static void _init_buttons(){ static void _init_buttons(){
//configure all buttons as pullup //configure all buttons as pullup
......
...@@ -3,6 +3,7 @@ idf_component_register( ...@@ -3,6 +3,7 @@ idf_component_register(
flow3r_bsp_display.c flow3r_bsp_display.c
flow3r_bsp_gc9a01.c flow3r_bsp_gc9a01.c
flow3r_bsp_hwconfig.c flow3r_bsp_hwconfig.c
flow3r_bsp_i2c.c
INCLUDE_DIRS INCLUDE_DIRS
. .
) )
#pragma once #pragma once
#include "flow3r_bsp_i2c.h"
#include <stdint.h> #include <stdint.h>
// Initialize badge display. An error will be reported if the initialization // Initialize badge display. An error will be reported if the initialization
......
#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
#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
...@@ -17,6 +17,7 @@ void st3m_board_startup(void) { ...@@ -17,6 +17,7 @@ void st3m_board_startup(void) {
} }
flow3r_bsp_display_set_backlight(100); flow3r_bsp_display_set_backlight(100);
flow3r_bsp_i2c_init();
st3m_fs_init(); st3m_fs_init();
// Handoff to badge23. // Handoff to badge23.
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment