Prototype 4

This commit is contained in:
Renze Nicolai 2022-04-23 04:00:55 +02:00
parent fd5d4da353
commit e42aefed7f
17 changed files with 463 additions and 284 deletions

View file

@ -5,7 +5,6 @@ idf_component_register(
"appfs" "appfs"
"bus-i2c" "bus-i2c"
"i2c-bno055" "i2c-bno055"
"i2c-pca9555"
"pax-graphics" "pax-graphics"
"renze-graphics" "renze-graphics"
"sdcard" "sdcard"

View file

@ -8,42 +8,45 @@
static const char *TAG = "hardware"; static const char *TAG = "hardware";
static PCA9555 dev_pca9555 = {0};
static BNO055 dev_bno055 = {0}; static BNO055 dev_bno055 = {0};
static ILI9341 dev_ili9341 = {0}; static ILI9341 dev_ili9341 = {0};
static ICE40 dev_ice40 = {0}; static ICE40 dev_ice40 = {0};
static RP2040 dev_rp2040 = {0}; static RP2040 dev_rp2040 = {0};
esp_err_t ice40_get_done_wrapper(bool* done) { esp_err_t ice40_get_done_wrapper(bool* done) {
return pca9555_get_gpio_value(&dev_pca9555, PCA9555_PIN_FPGA_CDONE, done); uint8_t buttons[2];
esp_err_t res = rp2040_read_buttons(&dev_rp2040, buttons);
if (res != ESP_OK) return res;
*done = !((buttons[0] >> 5) & 0x01);
printf("FPGA done is %u\n", *done);
return ESP_OK;
} }
esp_err_t ice40_set_reset_wrapper(bool reset) { esp_err_t ice40_set_reset_wrapper(bool reset) {
return pca9555_set_gpio_value(&dev_pca9555, PCA9555_PIN_FPGA_RESET, reset); printf("FPGA reset set to %u\n", reset);
esp_err_t res = rp2040_set_fpga(&dev_rp2040, reset);
vTaskDelay(100 / portTICK_PERIOD_MS);
return res;
} }
void ili9341_set_lcd_mode(bool mode) { void ili9341_set_lcd_mode(bool mode) {
ESP_LOGI(TAG, "LCD mode switch to %s", mode ? "FPGA" : "ESP32"); ESP_LOGI(TAG, "LCD mode switch to %s", mode ? "FPGA" : "ESP32");
rp2040_set_lcd_mode(&dev_rp2040, (lcd_mode_t) mode); esp_err_t res = gpio_set_level(GPIO_LCD_MODE, mode);
if (res != ESP_OK) {
ESP_LOGE(TAG, "Setting LCD mode failed");
}
} }
static esp_err_t _bus_init() { static esp_err_t _bus_init() {
esp_err_t res; esp_err_t res;
// System I2C bus // I2C bus
res = i2c_init(I2C_BUS_SYS, GPIO_I2C_SYS_SDA, GPIO_I2C_SYS_SCL, I2C_SPEED_SYS, false, false); res = i2c_init(I2C_BUS_SYS, GPIO_I2C_SYS_SDA, GPIO_I2C_SYS_SCL, I2C_SPEED_SYS, false, false);
if (res != ESP_OK) { if (res != ESP_OK) {
ESP_LOGE(TAG, "Initializing system I2C bus failed"); ESP_LOGE(TAG, "Initializing system I2C bus failed");
return res; return res;
} }
// User I2C bus
res = i2c_init(I2C_BUS_EXT, GPIO_I2C_EXT_SDA, GPIO_I2C_EXT_SCL, I2C_SPEED_EXT, false, false);
if (res != ESP_OK) {
ESP_LOGE(TAG, "Initializing user I2C bus failed");
return res;
}
// SPI bus // SPI bus
spi_bus_config_t busConfiguration = {0}; spi_bus_config_t busConfiguration = {0};
busConfiguration.mosi_io_num = GPIO_SPI_MOSI; busConfiguration.mosi_io_num = GPIO_SPI_MOSI;
@ -63,7 +66,8 @@ static esp_err_t _bus_init() {
// Board init // Board init
esp_err_t board_init() { esp_err_t board_init(bool* aLcdReady) {
if (aLcdReady != NULL) *aLcdReady = false;
esp_err_t res; esp_err_t res;
// Interrupts // Interrupts
@ -77,10 +81,36 @@ esp_err_t board_init() {
res = _bus_init(); res = _bus_init();
if (res != ESP_OK) return res; if (res != ESP_OK) return res;
// LCD display
dev_ili9341.spi_bus = SPI_BUS;
dev_ili9341.pin_cs = GPIO_SPI_CS_LCD;
dev_ili9341.pin_dcx = GPIO_SPI_DC_LCD;
dev_ili9341.pin_reset = GPIO_LCD_RESET;
dev_ili9341.rotation = 1;
dev_ili9341.color_mode = true; // Blue and red channels are swapped
dev_ili9341.spi_speed = 60000000; // 60MHz
dev_ili9341.spi_max_transfer_size = SPI_MAX_TRANSFER_SIZE;
dev_ili9341.callback = ili9341_set_lcd_mode; // Callback for changing LCD mode between ESP32 and FPGA
res = gpio_set_direction(GPIO_LCD_MODE, GPIO_MODE_OUTPUT);
if (res != ESP_OK) {
ESP_LOGE(TAG, "Initializing LCD mode GPIO failed");
return res;
}
res = ili9341_init(&dev_ili9341);
if (res != ESP_OK) {
ESP_LOGE(TAG, "Initializing LCD failed");
return res;
}
if (aLcdReady != NULL) *aLcdReady = true;
// RP2040 co-processor // RP2040 co-processor
dev_rp2040.i2c_bus = I2C_BUS_SYS; dev_rp2040.i2c_bus = I2C_BUS_SYS;
dev_rp2040.i2c_address = RP2040_ADDR; dev_rp2040.i2c_address = RP2040_ADDR;
dev_rp2040.pin_interrupt = GPIO_INT_RP2040; dev_rp2040.pin_interrupt = GPIO_INT_RP2040;
dev_rp2040.queue = xQueueCreate(8, sizeof(rp2040_input_message_t));
res = rp2040_init(&dev_rp2040); res = rp2040_init(&dev_rp2040);
if (res != ESP_OK) { if (res != ESP_OK) {
@ -88,45 +118,13 @@ esp_err_t board_init() {
return res; return res;
} }
// PCA9555 IO expander on system I2C bus
res = pca9555_init(&dev_pca9555, I2C_BUS_SYS, PCA9555_ADDR, GPIO_INT_PCA9555);
if (res != ESP_OK) {
ESP_LOGE(TAG, "Initializing PCA9555 failed");
return res;
}
res = pca9555_set_gpio_direction(&dev_pca9555, PCA9555_PIN_FPGA_RESET, true);
if (res != ESP_OK) {
ESP_LOGE(TAG, "Setting the FPGA reset pin on the PCA9555 to output failed");
return res;
}
res = pca9555_set_gpio_value(&dev_pca9555, PCA9555_PIN_FPGA_RESET, false);
if (res != ESP_OK) {
ESP_LOGE(TAG, "Setting the FPGA reset pin on the PCA9555 to low failed");
return res;
}
pca9555_set_gpio_polarity(&dev_pca9555, PCA9555_PIN_BTN_START, true);
pca9555_set_gpio_polarity(&dev_pca9555, PCA9555_PIN_BTN_SELECT, true);
pca9555_set_gpio_polarity(&dev_pca9555, PCA9555_PIN_BTN_MENU, true);
pca9555_set_gpio_polarity(&dev_pca9555, PCA9555_PIN_BTN_HOME, true);
pca9555_set_gpio_polarity(&dev_pca9555, PCA9555_PIN_BTN_JOY_LEFT, true);
pca9555_set_gpio_polarity(&dev_pca9555, PCA9555_PIN_BTN_JOY_PRESS, true);
pca9555_set_gpio_polarity(&dev_pca9555, PCA9555_PIN_BTN_JOY_DOWN, true);
pca9555_set_gpio_polarity(&dev_pca9555, PCA9555_PIN_BTN_JOY_UP, true);
pca9555_set_gpio_polarity(&dev_pca9555, PCA9555_PIN_BTN_JOY_RIGHT, true);
pca9555_set_gpio_polarity(&dev_pca9555, PCA9555_PIN_BTN_BACK, true);
pca9555_set_gpio_polarity(&dev_pca9555, PCA9555_PIN_BTN_ACCEPT, true);
dev_pca9555.pin_state = 0;
// FPGA // FPGA
dev_ice40.spi_bus = SPI_BUS; dev_ice40.spi_bus = SPI_BUS;
dev_ice40.pin_cs = GPIO_SPI_CS_FPGA; dev_ice40.pin_cs = GPIO_SPI_CS_FPGA;
dev_ice40.pin_done = -1; dev_ice40.pin_done = -1;
dev_ice40.pin_reset = -1; dev_ice40.pin_reset = -1;
dev_ice40.pin_int = GPIO_INT_FPGA; dev_ice40.pin_int = GPIO_INT_FPGA;
dev_ice40.spi_speed = 23000000; // 23MHz dev_ice40.spi_speed = 10000000; // 10 MHz //23000000; // 23MHz
dev_ice40.spi_max_transfer_size = SPI_MAX_TRANSFER_SIZE; dev_ice40.spi_max_transfer_size = SPI_MAX_TRANSFER_SIZE;
dev_ice40.get_done = ice40_get_done_wrapper; dev_ice40.get_done = ice40_get_done_wrapper;
dev_ice40.set_reset = ice40_set_reset_wrapper; dev_ice40.set_reset = ice40_set_reset_wrapper;
@ -137,23 +135,6 @@ esp_err_t board_init() {
return res; return res;
} }
// LCD display
dev_ili9341.spi_bus = SPI_BUS;
dev_ili9341.pin_cs = GPIO_SPI_CS_LCD;
dev_ili9341.pin_dcx = GPIO_SPI_DC_LCD;
dev_ili9341.pin_reset = -1;
dev_ili9341.rotation = 1;
dev_ili9341.color_mode = true; // Blue and red channels are swapped
dev_ili9341.spi_speed = 60000000; // 60MHz
dev_ili9341.spi_max_transfer_size = SPI_MAX_TRANSFER_SIZE;
dev_ili9341.callback = ili9341_set_lcd_mode; // Callback for changing LCD mode between ESP32 and FPGA
res = ili9341_init(&dev_ili9341);
if (res != ESP_OK) {
ESP_LOGE(TAG, "Initializing LCD failed");
return res;
}
// BNO055 sensor on system I2C bus // BNO055 sensor on system I2C bus
res = bno055_init(&dev_bno055, I2C_BUS_SYS, BNO055_ADDR, GPIO_INT_BNO055, true); res = bno055_init(&dev_bno055, I2C_BUS_SYS, BNO055_ADDR, GPIO_INT_BNO055, true);
@ -164,10 +145,6 @@ esp_err_t board_init() {
return res; return res;
} }
PCA9555* get_pca9555() {
return &dev_pca9555;
}
BNO055* get_bno055() { BNO055* get_bno055() {
return &dev_bno055; return &dev_bno055;
} }

View file

@ -3,52 +3,35 @@
#include <sdkconfig.h> #include <sdkconfig.h>
#include <esp_err.h> #include <esp_err.h>
#include <driver/spi_master.h> #include <driver/spi_master.h>
#include "pca9555.h"
#include "bno055.h" #include "bno055.h"
#include "ili9341.h" #include "ili9341.h"
#include "ice40.h" #include "ice40.h"
#include "rp2040.h" #include "rp2040.h"
// Interrupts // Interrupts
#define GPIO_INT_RP2040 0 #define GPIO_INT_RP2040 34
#define GPIO_INT_PCA9555 34
#define GPIO_INT_BNO055 36 #define GPIO_INT_BNO055 36
#define GPIO_INT_FPGA 39 #define GPIO_INT_FPGA 39
// SD card // SD card
#define SD_PWR 5 #define SD_PWR 19 // Also LED power
#define SD_D0 2 #define SD_D0 2
#define SD_CLK 14 #define SD_CLK 14
#define SD_CMD 15 #define SD_CMD 15
// LEDs
#define GPIO_LED_DATA 5
// I2S audio // I2S audio
#define GPIO_I2S_CLK 14 #define GPIO_I2S_CLK 14
#define GPIO_I2S_DATA 13 #define GPIO_I2S_DATA 13
#define GPIO_I2S_LR 4 #define GPIO_I2S_LR 4
// System I2C bus // I2C bus
#define GPIO_I2C_SYS_SCL 21 #define GPIO_I2C_SYS_SCL 21
#define GPIO_I2C_SYS_SDA 22 #define GPIO_I2C_SYS_SDA 22
#define I2C_BUS_SYS 0 #define I2C_BUS_SYS 0
#define I2C_SPEED_SYS 20000 // 20 kHz #define I2C_SPEED_SYS 8000 // 8 kHz //20000 // 20 kHz
// PCA9555 IO expander
#define PCA9555_ADDR 0x26
#define PCA9555_PIN_RP2040_RESET 0
#define PCA9555_PIN_RP2040_BOOTSEL 1
#define PCA9555_PIN_FPGA_RESET 2
#define PCA9555_PIN_FPGA_CDONE 3
#define PCA9555_PIN_BTN_START 5
#define PCA9555_PIN_BTN_SELECT 6
#define PCA9555_PIN_BTN_MENU 7
#define PCA9555_PIN_BTN_HOME 8
#define PCA9555_PIN_BTN_JOY_LEFT 9
#define PCA9555_PIN_BTN_JOY_PRESS 10
#define PCA9555_PIN_BTN_JOY_DOWN 11
#define PCA9555_PIN_BTN_JOY_UP 12
#define PCA9555_PIN_BTN_JOY_RIGHT 13
#define PCA9555_PIN_BTN_BACK 14
#define PCA9555_PIN_BTN_ACCEPT 15
// RP2040 co-processor // RP2040 co-processor
#define RP2040_ADDR 0x17 #define RP2040_ADDR 0x17
@ -56,27 +39,24 @@
// BNO055 sensor // BNO055 sensor
#define BNO055_ADDR 0x28 #define BNO055_ADDR 0x28
// User I2C bus
#define GPIO_I2C_EXT_SCL 25
#define GPIO_I2C_EXT_SDA 26
#define I2C_BUS_EXT 1
#define I2C_SPEED_EXT 100000 // 100 kHz
// SPI bus // SPI bus
#define GPIO_SPI_CLK 18 #define GPIO_SPI_CLK 18
#define GPIO_SPI_MOSI 23 #define GPIO_SPI_MOSI 23
#define GPIO_SPI_MISO 35 #define GPIO_SPI_MISO 35
#define GPIO_SPI_CS_RP2040 19 #define GPIO_SPI_CS_RP2040 19
#define GPIO_SPI_CS_FPGA 27 #define GPIO_SPI_CS_FPGA 27
#define GPIO_SPI_CS_LCD 32
#define GPIO_SPI_DC_LCD 33
#define SPI_BUS VSPI_HOST #define SPI_BUS VSPI_HOST
#define SPI_MAX_TRANSFER_SIZE 4094 #define SPI_MAX_TRANSFER_SIZE 4094
#define SPI_DMA_CHANNEL 2 #define SPI_DMA_CHANNEL 2
esp_err_t board_init(); // LCD display
#define GPIO_LCD_RESET 25
#define GPIO_LCD_MODE 26
#define GPIO_SPI_CS_LCD 32
#define GPIO_SPI_DC_LCD 33
esp_err_t board_init(bool* aLcdReady);
PCA9555* get_pca9555();
BNO055* get_bno055(); BNO055* get_bno055();
ILI9341* get_ili9341(); ILI9341* get_ili9341();
ICE40* get_ice40(); ICE40* get_ice40();

View file

@ -11,12 +11,52 @@
static const char *TAG = "RP2040"; static const char *TAG = "RP2040";
inline void _send_input_change(RP2040* device, uint8_t input, bool value) {
rp2040_input_message_t message;
message.input = input;
message.state = value;
xQueueSend(device->queue, &message, portMAX_DELAY);
}
void rp2040_intr_task(void *arg) {
RP2040* device = (RP2040*) arg;
uint32_t state;
while (1) {
if (xSemaphoreTake(device->_intr_trigger, portMAX_DELAY)) {
esp_err_t res = i2c_read_reg(device->i2c_bus, device->i2c_address, RP2040_REG_INPUT1, (uint8_t*) &state, 4);
if (res != ESP_OK) {
ESP_LOGE(TAG, "RP2040 interrupt task failed to read from RP2040");
continue;
}
ESP_LOGW(TAG, "RP2040 input state %08x", state);
uint16_t interrupt = state >> 16;
uint16_t values = state & 0xFFFF;
for (uint8_t index = 0; index < 16; index++) {
if ((interrupt >> index) & 0x01) {
_send_input_change(device, index, (values >> index) & 0x01);
}
}
vTaskDelay(10 / portTICK_PERIOD_MS);
}
}
}
void rp2040_intr_handler(void *arg) {
/* in interrupt handler context */
RP2040* device = (RP2040*) arg;
xSemaphoreGiveFromISR(device->_intr_trigger, NULL);
}
esp_err_t rp2040_init(RP2040* device) { esp_err_t rp2040_init(RP2040* device) {
esp_err_t res; esp_err_t res;
uint8_t firmware_version; uint8_t firmware_version;
res = rp2040_get_firmware_version(device, &firmware_version); res = rp2040_get_firmware_version(device, &firmware_version);
if (res != ESP_OK) return res; if (res != ESP_OK) {
ESP_LOGE(TAG, "Failed to read firmware version");
return res;
}
if (firmware_version != 1) { if (firmware_version != 1) {
ESP_LOGE(TAG, "Unsupported RP2040 firmware version (%u) found", firmware_version); ESP_LOGE(TAG, "Unsupported RP2040 firmware version (%u) found", firmware_version);
@ -24,11 +64,41 @@ esp_err_t rp2040_init(RP2040* device) {
} }
res = i2c_read_reg(device->i2c_bus, device->i2c_address, RP2040_REG_GPIO_DIR, &device->_gpio_direction, 1); res = i2c_read_reg(device->i2c_bus, device->i2c_address, RP2040_REG_GPIO_DIR, &device->_gpio_direction, 1);
if (res != ESP_OK) return res; if (res != ESP_OK) {
ESP_LOGE(TAG, "Failed to read GPIO direction");
return res;
}
res = i2c_read_reg(device->i2c_bus, device->i2c_address, RP2040_REG_GPIO_OUT, &device->_gpio_value, 1); res = i2c_read_reg(device->i2c_bus, device->i2c_address, RP2040_REG_GPIO_OUT, &device->_gpio_value, 1);
if (res != ESP_OK) {
ESP_LOGE(TAG, "Failed to read GPIO state");
return res;
}
//Create interrupt trigger
device->_intr_trigger = xSemaphoreCreateBinary();
if (device->_intr_trigger == NULL) return ESP_ERR_NO_MEM;
//Attach interrupt to interrupt pin
if (device->pin_interrupt >= 0) {
res = gpio_isr_handler_add(device->pin_interrupt, rp2040_intr_handler, (void*) device);
if (res != ESP_OK) return res; if (res != ESP_OK) return res;
gpio_config_t io_conf = {
.intr_type = GPIO_INTR_NEGEDGE,
.mode = GPIO_MODE_INPUT,
.pin_bit_mask = 1LL << device->pin_interrupt,
.pull_down_en = 0,
.pull_up_en = 1,
};
res = gpio_config(&io_conf);
if (res != ESP_OK) return res;
xTaskCreate(&rp2040_intr_task, "RP2040 interrupt", 4096, (void*) device, 10, &device->_intr_task_handle);
xSemaphoreGive(device->_intr_trigger);
}
return ESP_OK; return ESP_OK;
} }
@ -68,22 +138,6 @@ esp_err_t rp2040_set_gpio_value(RP2040* device, uint8_t gpio, bool value) {
return i2c_write_reg_n(device->i2c_bus, device->i2c_address, RP2040_REG_GPIO_OUT, &device->_gpio_value, 1); return i2c_write_reg_n(device->i2c_bus, device->i2c_address, RP2040_REG_GPIO_OUT, &device->_gpio_value, 1);
} }
esp_err_t rp2040_get_lcd_mode(RP2040* device, lcd_mode_t* mode) {
return i2c_read_reg(device->i2c_bus, device->i2c_address, RP2040_REG_LCD_MODE, (uint8_t*) mode, 1);
}
esp_err_t rp2040_set_lcd_mode(RP2040* device, lcd_mode_t mode) {
esp_err_t res;
lcd_mode_t verification;
do {
res = i2c_write_reg_n(device->i2c_bus, device->i2c_address, RP2040_REG_LCD_MODE, (uint8_t*) &mode, 1);
if (res != ESP_OK) return res;
res = rp2040_get_lcd_mode(device, &verification);
if (res != ESP_OK) return res;
} while (verification != mode);
return res;
}
esp_err_t rp2040_get_lcd_backlight(RP2040* device, uint8_t* brightness) { esp_err_t rp2040_get_lcd_backlight(RP2040* device, uint8_t* brightness) {
return i2c_read_reg(device->i2c_bus, device->i2c_address, RP2040_REG_LCD_BACKLIGHT, brightness, 1); return i2c_read_reg(device->i2c_bus, device->i2c_address, RP2040_REG_LCD_BACKLIGHT, brightness, 1);
} }
@ -92,44 +146,11 @@ esp_err_t rp2040_set_lcd_backlight(RP2040* device, uint8_t brightness) {
return i2c_write_reg_n(device->i2c_bus, device->i2c_address, RP2040_REG_LCD_BACKLIGHT, &brightness, 1); return i2c_write_reg_n(device->i2c_bus, device->i2c_address, RP2040_REG_LCD_BACKLIGHT, &brightness, 1);
} }
esp_err_t rp2040_get_led_mode(RP2040* device, bool* enabled, bool* automatic_flush) { esp_err_t rp2040_set_fpga(RP2040* device, bool enabled) {
uint8_t value; uint8_t value = enabled ? 0x01 : 0x00;
esp_err_t res = i2c_read_reg(device->i2c_bus, device->i2c_address, RP2040_REG_LED_MODE, &value, 1); return i2c_write_reg_n(device->i2c_bus, device->i2c_address, RP2040_REG_FPGA, &value, 1);
if (res != ESP_OK) return res;
*enabled = (value >> 0) & 0x01;
*automatic_flush = (value >> 1) & 0x01;
return ESP_OK;
} }
esp_err_t rp2040_set_led_mode(RP2040* device, bool enabled, bool automatic_flush) { esp_err_t rp2040_read_buttons(RP2040* device, uint16_t* value) {
uint8_t value = enabled | (automatic_flush << 1); return i2c_read_reg(device->i2c_bus, device->i2c_address, RP2040_REG_INPUT1, (uint8_t*) value, 2);
return i2c_write_reg_n(device->i2c_bus, device->i2c_address, RP2040_REG_LED_MODE, &value, 1);
}
esp_err_t rp2040_get_led_value(RP2040* device, uint8_t led, uint8_t* red, uint8_t* green, uint8_t* blue) {
if (led > 5) return ESP_ERR_NOT_FOUND;
uint8_t value[3];
esp_err_t res = i2c_read_reg(device->i2c_bus, device->i2c_address, RP2040_REG_LED_R0 + (led * 3), value, 3);
if (res != ESP_OK) return res;
*red = value[0];
*green = value[1];
*blue = value[2];
return ESP_OK;
}
esp_err_t rp2040_set_led_value(RP2040* device, uint8_t led, uint8_t red, uint8_t green, uint8_t blue) {
if (led > 5) return ESP_ERR_NOT_FOUND;
uint8_t value[3];
value[0] = red;
value[1] = green;
value[2] = blue;
return i2c_write_reg_n(device->i2c_bus, device->i2c_address, RP2040_REG_LED_R0 + (led * 3), value, 3);
}
esp_err_t rp2040_get_led_values(RP2040* device, uint8_t* buffer) {
return i2c_read_reg(device->i2c_bus, device->i2c_address, RP2040_REG_LED_R0, buffer, 15);
}
esp_err_t rp2040_set_led_values(RP2040* device, uint8_t* buffer) {
return i2c_write_reg_n(device->i2c_bus, device->i2c_address, RP2040_REG_LED_R0, buffer, 15);
} }

View file

@ -6,36 +6,106 @@
#include <freertos/FreeRTOS.h> #include <freertos/FreeRTOS.h>
#include <freertos/semphr.h> #include <freertos/semphr.h>
#include <freertos/task.h> #include <freertos/task.h>
#include <freertos/queue.h>
enum { enum {
RP2040_REG_FW_VER = 0, RP2040_REG_FW_VER = 0,
RP2040_REG_GPIO_DIR, RP2040_REG_GPIO_DIR,
RP2040_REG_GPIO_IN, RP2040_REG_GPIO_IN,
RP2040_REG_GPIO_OUT, RP2040_REG_GPIO_OUT,
RP2040_REG_LCD_MODE,
RP2040_REG_LCD_BACKLIGHT, RP2040_REG_LCD_BACKLIGHT,
RP2040_REG_LED_MODE, RP2040_REG_FPGA,
RP2040_REG_LED_R0, RP2040_REG_INPUT1,
RP2040_REG_LED_G0, RP2040_REG_INPUT2,
RP2040_REG_LED_B0, RP2040_REG_INTERRUPT1,
RP2040_REG_LED_R1, RP2040_REG_INTERRUPT2,
RP2040_REG_LED_G1, RP2040_REG_ADC_TRIGGER,
RP2040_REG_LED_B1, RP2040_REG_ADC_VALUE_VUSB1,
RP2040_REG_LED_R2, RP2040_REG_ADC_VALUE_VUSB2,
RP2040_REG_LED_G2, RP2040_REG_ADC_VALUE_VBAT1,
RP2040_REG_LED_B2, RP2040_REG_ADC_VALUE_VBAT2,
RP2040_REG_LED_R3, RP2040_REG_USB,
RP2040_REG_LED_G3, RP2040_REG_SCRATCH0, // Used by the ESP32 to store boot parameters, can also be read and written to from WebUSB
RP2040_REG_LED_B3, RP2040_REG_SCRATCH1,
RP2040_REG_LED_R4, RP2040_REG_SCRATCH2,
RP2040_REG_LED_G4, RP2040_REG_SCRATCH3,
RP2040_REG_LED_B4, RP2040_REG_SCRATCH4,
RP2040_REG_SCRATCH5,
RP2040_REG_SCRATCH6,
RP2040_REG_SCRATCH7,
RP2040_REG_SCRATCH8,
RP2040_REG_SCRATCH9,
RP2040_REG_SCRATCH10,
RP2040_REG_SCRATCH11,
RP2040_REG_SCRATCH12,
RP2040_REG_SCRATCH13,
RP2040_REG_SCRATCH14,
RP2040_REG_SCRATCH15,
RP2040_REG_SCRATCH16,
RP2040_REG_SCRATCH17,
RP2040_REG_SCRATCH18,
RP2040_REG_SCRATCH19,
RP2040_REG_SCRATCH20,
RP2040_REG_SCRATCH21,
RP2040_REG_SCRATCH22,
RP2040_REG_SCRATCH23,
RP2040_REG_SCRATCH24,
RP2040_REG_SCRATCH25,
RP2040_REG_SCRATCH26,
RP2040_REG_SCRATCH27,
RP2040_REG_SCRATCH28,
RP2040_REG_SCRATCH29,
RP2040_REG_SCRATCH30,
RP2040_REG_SCRATCH31,
RP2040_REG_SCRATCH32,
RP2040_REG_SCRATCH33,
RP2040_REG_SCRATCH34,
RP2040_REG_SCRATCH35,
RP2040_REG_SCRATCH36,
RP2040_REG_SCRATCH37,
RP2040_REG_SCRATCH38,
RP2040_REG_SCRATCH39,
RP2040_REG_SCRATCH40,
RP2040_REG_SCRATCH41,
RP2040_REG_SCRATCH42,
RP2040_REG_SCRATCH43,
RP2040_REG_SCRATCH44,
RP2040_REG_SCRATCH45,
RP2040_REG_SCRATCH46,
RP2040_REG_SCRATCH47,
RP2040_REG_SCRATCH48,
RP2040_REG_SCRATCH49,
RP2040_REG_SCRATCH50,
RP2040_REG_SCRATCH51,
RP2040_REG_SCRATCH52,
RP2040_REG_SCRATCH53,
RP2040_REG_SCRATCH54,
RP2040_REG_SCRATCH55,
RP2040_REG_SCRATCH56,
RP2040_REG_SCRATCH57,
RP2040_REG_SCRATCH58,
RP2040_REG_SCRATCH59,
RP2040_REG_SCRATCH60,
RP2040_REG_SCRATCH61,
RP2040_REG_SCRATCH62,
RP2040_REG_SCRATCH63
}; };
typedef enum { enum {
LCD_MODE_SPI = 0, RP2040_INPUT_BUTTON_HOME = 0,
LCD_MODE_PARALLEL = 1 RP2040_INPUT_BUTTON_MENU,
} lcd_mode_t; RP2040_INPUT_BUTTON_START,
RP2040_INPUT_BUTTON_ACCEPT,
RP2040_INPUT_BUTTON_BACK,
RP2040_INPUT_FPGA_CDONE,
RP2040_INPUT_BATTERY_CHARGING,
RP2040_INPUT_BUTTON_SELECT,
RP2040_INPUT_JOYSTICK_LEFT,
RP2040_INPUT_JOYSTICK_PRESS,
RP2040_INPUT_JOYSTICK_DOWN,
RP2040_INPUT_JOYSTICK_UP,
RP2040_INPUT_JOYSTICK_RIGHT
};
typedef void (*rp2040_intr_t)(); typedef void (*rp2040_intr_t)();
@ -43,14 +113,19 @@ typedef struct {
int i2c_bus; int i2c_bus;
int i2c_address; int i2c_address;
int pin_interrupt; int pin_interrupt;
xQueueHandle queue;
rp2040_intr_t _intr_handler; rp2040_intr_t _intr_handler;
TaskHandle_t _intr_task_handle; TaskHandle_t _intr_task_handle;
xSemaphoreHandle _intr_trigger; xSemaphoreHandle _intr_trigger;
xSemaphoreHandle _mux;
uint8_t _gpio_direction; uint8_t _gpio_direction;
uint8_t _gpio_value; uint8_t _gpio_value;
} RP2040; } RP2040;
typedef struct _rp2040_input_message {
uint8_t input;
bool state;
} rp2040_input_message_t;
esp_err_t rp2040_init(RP2040* device); esp_err_t rp2040_init(RP2040* device);
esp_err_t rp2040_get_firmware_version(RP2040* device, uint8_t* version); esp_err_t rp2040_get_firmware_version(RP2040* device, uint8_t* version);
@ -61,17 +136,9 @@ esp_err_t rp2040_set_gpio_dir(RP2040* device, uint8_t gpio, bool direction);
esp_err_t rp2040_get_gpio_value(RP2040* device, uint8_t gpio, bool* value); esp_err_t rp2040_get_gpio_value(RP2040* device, uint8_t gpio, bool* value);
esp_err_t rp2040_set_gpio_value(RP2040* device, uint8_t gpio, bool value); esp_err_t rp2040_set_gpio_value(RP2040* device, uint8_t gpio, bool value);
esp_err_t rp2040_get_lcd_mode(RP2040* device, lcd_mode_t* mode);
esp_err_t rp2040_set_lcd_mode(RP2040* device, lcd_mode_t mode);
esp_err_t rp2040_get_lcd_backlight(RP2040* device, uint8_t* brightness); esp_err_t rp2040_get_lcd_backlight(RP2040* device, uint8_t* brightness);
esp_err_t rp2040_set_lcd_backlight(RP2040* device, uint8_t brightness); esp_err_t rp2040_set_lcd_backlight(RP2040* device, uint8_t brightness);
esp_err_t rp2040_get_led_mode(RP2040* device, bool* enabled, bool* automatic_flush); esp_err_t rp2040_set_fpga(RP2040* device, bool enabled);
esp_err_t rp2040_set_led_mode(RP2040* device, bool enabled, bool automatic_flush);
esp_err_t rp2040_get_led_value(RP2040* device, uint8_t led, uint8_t* red, uint8_t* green, uint8_t* blue); esp_err_t rp2040_read_buttons(RP2040* device, uint16_t* value);
esp_err_t rp2040_set_led_value(RP2040* device, uint8_t led, uint8_t red, uint8_t green, uint8_t blue);
esp_err_t rp2040_get_led_values(RP2040* device, uint8_t* buffer); // Expects a buffer that can fit 15 bytes (R, G, B * 5 LEDs)
esp_err_t rp2040_set_led_values(RP2040* device, uint8_t* buffer); // Expects a buffer that can contains 15 bytes (R, G, B * 5 LEDs)

@ -1 +1 @@
Subproject commit 1c2b5241dd00d2fddb45d20f3c4a426fa379fa95 Subproject commit 4263f4f60d3d410ebf2ae88a7a26b23bd08eedde

@ -1 +1 @@
Subproject commit c83ac9b467d73595ebd6f15f6f444068fe2d3198 Subproject commit 4bc90991a83df4e733705cc7c89906c64756e0f2

View file

@ -0,0 +1,4 @@
idf_component_register(
SRCS "ws2812.c"
INCLUDE_DIRS include
)

View file

@ -0,0 +1,35 @@
#pragma once
#include <stdint.h>
#include <esp_err.h>
#include <driver/gpio.h>
__BEGIN_DECLS
/**
* Initialize the leds driver. (configure SPI bus and GPIO pins)
* @return ESP_OK on success; any other value indicates an error
*/
extern esp_err_t ws2812_init(gpio_num_t aGpioPin);
/**
* Enable power to the leds bar.
* @return ESP_OK on success; any other value indicates an error
*/
extern esp_err_t ws2812_enable(int gpio_pin);
/**
* Disable power to the leds bar.
* @return ESP_OK on success; any other value indicates an error
*/
extern esp_err_t ws2812_disable(void);
/**
* Send color-data to the leds bus.
* @param data the data-bytes to send on the bus.
* @param len the data-length.
* @return ESP_OK on success; any other value indicates an error
*/
extern esp_err_t ws2812_send_data(uint8_t *data, int len);
__END_DECLS

124
components/ws2812/ws2812.c Normal file
View file

@ -0,0 +1,124 @@
//This driver uses the ESP32 RMT peripheral to drive "Neopixel" compatible LEDs
//The usage of the RMT peripheral has been implemented using work by JSchaenzie:
//you can find his work at https://github.com/JSchaenzle/ESP32-NeoPixel-WS2812-RMT
#include <sdkconfig.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <esp_err.h>
#include <esp_log.h>
#include <driver/gpio.h>
#include <driver/rmt.h>
static const char *TAG = "ws2812";
#define WS2812_RMT_CHANNEL RMT_CHANNEL_0
#define T0H 14 // 0 bit high time
#define T1H 52 // 1 bit high time
#define TL 52 // low time for either bit
static bool gActive = false;
rmt_item32_t* gBuffer = NULL;
int gBufferLength = 0;
gpio_num_t gPin;
esp_err_t ws2812_init(gpio_num_t aGpioPin) {
if (gActive) return ESP_OK;
gpio_config_t io_conf = {
.intr_type = GPIO_INTR_DISABLE,
.mode = GPIO_MODE_OUTPUT,
.pin_bit_mask = 1LL << aGpioPin,
.pull_down_en = 0,
.pull_up_en = 0,
};
esp_err_t res = gpio_config(&io_conf);
if (res != ESP_OK) return res;
rmt_config_t config;
config.rmt_mode = RMT_MODE_TX;
config.channel = WS2812_RMT_CHANNEL;
config.gpio_num = aGpioPin;
config.mem_block_num = 3;
config.tx_config.loop_en = false;
config.tx_config.carrier_en = false;
config.tx_config.idle_output_en = true;
config.tx_config.idle_level = 0;
config.clk_div = 2;
res = rmt_config(&config);
if (res != ESP_OK) return res;
res = rmt_driver_install(config.channel, 0, 0);
if (res != ESP_OK) return res;
gActive = true;
gPin = aGpioPin;
return ESP_OK;
}
esp_err_t ws2812_deinit(void) {
if (!gActive) return ESP_OK;
esp_err_t res = rmt_driver_uninstall(WS2812_RMT_CHANNEL);
if (res != ESP_OK) return res;
gpio_config_t io_conf = {
.intr_type = GPIO_INTR_DISABLE,
.mode = GPIO_MODE_INPUT,
.pin_bit_mask = 1LL << gPin,
.pull_down_en = 0,
.pull_up_en = 0,
};
res = gpio_config(&io_conf);
if (res != ESP_OK) return res;
gActive = false;
return ESP_OK;
}
esp_err_t ws2812_prepare_data(uint8_t *data, int len)
{
if (gBuffer != NULL) return ESP_FAIL;
gBuffer = calloc(len * 8, sizeof(rmt_item32_t));
if (gBuffer == NULL) return ESP_FAIL;
gBufferLength = len * 8;
for (uint32_t pos = 0; pos < len; pos++) {
uint32_t mask = 1 << 7;
for (uint8_t i = 0; i < 8; i++) {
bool bit = data[pos] & mask;
gBuffer[pos*8 + i] = bit ?
(rmt_item32_t){{{T1H, 1, TL, 0}}} :
(rmt_item32_t){{{T0H, 1, TL, 0}}};
mask >>= 1;
}
}
return ESP_OK;
}
esp_err_t ws2812_free_data() {
if (!gBuffer) return ESP_FAIL;
free(gBuffer);
gBuffer = NULL;
gBufferLength = 0;
return ESP_OK;
}
esp_err_t ws2812_send_data(uint8_t *data, int len)
{
if (!gActive) return ESP_FAIL;
esp_err_t res = ws2812_prepare_data(data, len);
if (res != ESP_OK) return res;
res = rmt_write_items(WS2812_RMT_CHANNEL, gBuffer, gBufferLength, false);
if (res != ESP_OK) {
ws2812_free_data();
return res;
}
res = rmt_wait_tx_done(WS2812_RMT_CHANNEL, portMAX_DELAY);
if (res != ESP_OK) {
ws2812_free_data();
return res;
}
res = ws2812_free_data();
return res;
}

View file

@ -1,4 +1,4 @@
idf_component_register( idf_component_register(
SRCS "main.c" "menu.c" "fpga_test.c" "pax_keyboard.c" "button_wrapper.c" "system_wrapper.c" "appfs_wrapper.c" "graphics_wrapper.c" "settings.c" "wifi_connection.c" SRCS "main.c" "menu.c" "fpga_test.c" "pax_keyboard.c" "system_wrapper.c" "appfs_wrapper.c" "graphics_wrapper.c" "settings.c" "wifi_connection.c"
INCLUDE_DIRS "." "include" INCLUDE_DIRS "." "include"
) )

View file

@ -1,25 +0,0 @@
#include "button_wrapper.h"
xQueueHandle queue;
void button_handler(uint8_t pin, bool value) {
button_message_t message;
message.button = pin;
message.state = value;
xQueueSend(queue, &message, portMAX_DELAY);
}
void button_init(PCA9555* aPca9555, xQueueHandle aQueue) {
queue = aQueue;
pca9555_set_interrupt_handler(aPca9555, PCA9555_PIN_BTN_START, button_handler);
pca9555_set_interrupt_handler(aPca9555, PCA9555_PIN_BTN_SELECT, button_handler);
pca9555_set_interrupt_handler(aPca9555, PCA9555_PIN_BTN_MENU, button_handler);
pca9555_set_interrupt_handler(aPca9555, PCA9555_PIN_BTN_HOME, button_handler);
pca9555_set_interrupt_handler(aPca9555, PCA9555_PIN_BTN_JOY_LEFT, button_handler);
pca9555_set_interrupt_handler(aPca9555, PCA9555_PIN_BTN_JOY_PRESS, button_handler);
pca9555_set_interrupt_handler(aPca9555, PCA9555_PIN_BTN_JOY_DOWN, button_handler);
pca9555_set_interrupt_handler(aPca9555, PCA9555_PIN_BTN_JOY_UP, button_handler);
pca9555_set_interrupt_handler(aPca9555, PCA9555_PIN_BTN_JOY_RIGHT, button_handler);
pca9555_set_interrupt_handler(aPca9555, PCA9555_PIN_BTN_BACK, button_handler);
pca9555_set_interrupt_handler(aPca9555, PCA9555_PIN_BTN_ACCEPT, button_handler);
}

View file

@ -7,8 +7,8 @@
#include "fpga.h" #include "fpga.h"
#include "ili9341.h" #include "ili9341.h"
#include "ice40.h" #include "ice40.h"
#include "rp2040.h"
#include "hardware.h" #include "hardware.h"
#include "button_wrapper.h"
static const char *TAG = "fpga_test"; static const char *TAG = "fpga_test";
@ -139,12 +139,12 @@ void fpga_test(ILI9341* ili9341, ICE40* ice40, xQueueHandle buttonQueue) {
bool waitForChoice = true; bool waitForChoice = true;
while (waitForChoice) { while (waitForChoice) {
button_message_t buttonMessage = {0}; rp2040_input_message_t buttonMessage = {0};
printf("Waiting for button press...\n"); printf("Waiting for button press...\n");
if (xQueueReceive(buttonQueue, &buttonMessage, portMAX_DELAY) == pdTRUE) { if (xQueueReceive(buttonQueue, &buttonMessage, portMAX_DELAY) == pdTRUE) {
printf("Button: %u, %u\n", buttonMessage.button, buttonMessage.state); printf("Button: %u, %u\n", buttonMessage.input, buttonMessage.state);
if (buttonMessage.state) { if (buttonMessage.state) {
switch(buttonMessage.button) { /*switch(buttonMessage.button) {
case PCA9555_PIN_BTN_HOME: case PCA9555_PIN_BTN_HOME:
case PCA9555_PIN_BTN_MENU: case PCA9555_PIN_BTN_MENU:
case PCA9555_PIN_BTN_BACK: case PCA9555_PIN_BTN_BACK:
@ -156,7 +156,7 @@ void fpga_test(ILI9341* ili9341, ICE40* ice40, xQueueHandle buttonQueue) {
break; break;
default: default:
break; break;
} }*/
} }
} }
} }

View file

@ -2,7 +2,7 @@
#include "graphics_wrapper.h" #include "graphics_wrapper.h"
#include "hardware.h" #include "hardware.h"
#include "pax_keyboard.h" #include "pax_keyboard.h"
#include "button_wrapper.h" #include "rp2040.h"
void render_message(pax_buf_t *aBuffer, char* message, float aPosX, float aPosY, float aWidth, float aHeight) { void render_message(pax_buf_t *aBuffer, char* message, float aPosX, float aPosY, float aWidth, float aHeight) {
pax_col_t fgColor = 0xFFFF0000; pax_col_t fgColor = 0xFFFF0000;
@ -70,68 +70,68 @@ bool keyboard(xQueueHandle buttonQueue, pax_buf_t* aBuffer, ILI9341* ili9341, ui
bool running = true; bool running = true;
while (running) { while (running) {
button_message_t buttonMessage = {0}; rp2040_input_message_t buttonMessage = {0};
if (xQueueReceive(buttonQueue, &buttonMessage, 16 / portTICK_PERIOD_MS) == pdTRUE) { if (xQueueReceive(buttonQueue, &buttonMessage, 16 / portTICK_PERIOD_MS) == pdTRUE) {
uint8_t pin = buttonMessage.button; uint8_t pin = buttonMessage.input;
bool value = buttonMessage.state; bool value = buttonMessage.state;
switch(pin) { switch(pin) {
case PCA9555_PIN_BTN_JOY_DOWN: case RP2040_INPUT_JOYSTICK_DOWN:
if (value) { if (value) {
pkb_press(&kb_ctx, PKB_DOWN); pkb_press(&kb_ctx, PKB_DOWN);
} else { } else {
pkb_release(&kb_ctx, PKB_DOWN); pkb_release(&kb_ctx, PKB_DOWN);
} }
break; break;
case PCA9555_PIN_BTN_JOY_UP: case RP2040_INPUT_JOYSTICK_UP:
if (value) { if (value) {
pkb_press(&kb_ctx, PKB_UP); pkb_press(&kb_ctx, PKB_UP);
} else { } else {
pkb_release(&kb_ctx, PKB_UP); pkb_release(&kb_ctx, PKB_UP);
} }
break; break;
case PCA9555_PIN_BTN_JOY_LEFT: case RP2040_INPUT_JOYSTICK_LEFT:
if (value) { if (value) {
pkb_press(&kb_ctx, PKB_LEFT); pkb_press(&kb_ctx, PKB_LEFT);
} else { } else {
pkb_release(&kb_ctx, PKB_LEFT); pkb_release(&kb_ctx, PKB_LEFT);
} }
break; break;
case PCA9555_PIN_BTN_JOY_RIGHT: case RP2040_INPUT_JOYSTICK_RIGHT:
if (value) { if (value) {
pkb_press(&kb_ctx, PKB_RIGHT); pkb_press(&kb_ctx, PKB_RIGHT);
} else { } else {
pkb_release(&kb_ctx, PKB_RIGHT); pkb_release(&kb_ctx, PKB_RIGHT);
} }
break; break;
case PCA9555_PIN_BTN_JOY_PRESS: case RP2040_INPUT_JOYSTICK_PRESS:
if (value) { if (value) {
pkb_press(&kb_ctx, PKB_SHIFT); pkb_press(&kb_ctx, PKB_SHIFT);
} else { } else {
pkb_release(&kb_ctx, PKB_SHIFT); pkb_release(&kb_ctx, PKB_SHIFT);
} }
break; break;
case PCA9555_PIN_BTN_ACCEPT: case RP2040_INPUT_BUTTON_ACCEPT:
if (value) { if (value) {
pkb_press(&kb_ctx, PKB_CHARSELECT); pkb_press(&kb_ctx, PKB_CHARSELECT);
} else { } else {
pkb_release(&kb_ctx, PKB_CHARSELECT); pkb_release(&kb_ctx, PKB_CHARSELECT);
} }
break; break;
case PCA9555_PIN_BTN_BACK: case RP2040_INPUT_BUTTON_BACK:
if (value) { if (value) {
pkb_press(&kb_ctx, PKB_DELETE_BEFORE); pkb_press(&kb_ctx, PKB_DELETE_BEFORE);
} else { } else {
pkb_release(&kb_ctx, PKB_DELETE_BEFORE); pkb_release(&kb_ctx, PKB_DELETE_BEFORE);
} }
break; break;
case PCA9555_PIN_BTN_SELECT: case RP2040_INPUT_BUTTON_SELECT:
if (value) { if (value) {
pkb_press(&kb_ctx, PKB_MODESELECT); pkb_press(&kb_ctx, PKB_MODESELECT);
} else { } else {
pkb_release(&kb_ctx, PKB_MODESELECT); pkb_release(&kb_ctx, PKB_MODESELECT);
} }
break; break;
case PCA9555_PIN_BTN_HOME: case RP2040_INPUT_BUTTON_HOME:
if (value) { if (value) {
running = false; running = false;
} }

View file

@ -1,15 +0,0 @@
#pragma once
#include <stdio.h>
#include <string.h>
#include <sdkconfig.h>
#include <freertos/FreeRTOS.h>
#include <freertos/queue.h>
#include "hardware.h"
typedef struct _button_message {
uint8_t button;
bool state;
} button_message_t;
void button_init(PCA9555* aPca9555, xQueueHandle aQueue);

View file

@ -21,13 +21,14 @@
#include "fpga_test.h" #include "fpga_test.h"
#include "menu.h" #include "menu.h"
#include "button_wrapper.h"
#include "system_wrapper.h" #include "system_wrapper.h"
#include "graphics_wrapper.h" #include "graphics_wrapper.h"
#include "appfs_wrapper.h" #include "appfs_wrapper.h"
#include "settings.h" #include "settings.h"
#include "wifi_connection.h" #include "wifi_connection.h"
#include "ws2812.h"
static const char *TAG = "main"; static const char *TAG = "main";
typedef enum action { typedef enum action {
@ -85,24 +86,24 @@ void menu_launcher(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341* ili
menu_args_t* menuArgs = NULL; menu_args_t* menuArgs = NULL;
while (1) { while (1) {
button_message_t buttonMessage = {0}; rp2040_input_message_t buttonMessage = {0};
if (xQueueReceive(buttonQueue, &buttonMessage, 16 / portTICK_PERIOD_MS) == pdTRUE) { if (xQueueReceive(buttonQueue, &buttonMessage, 16 / portTICK_PERIOD_MS) == pdTRUE) {
uint8_t pin = buttonMessage.button; uint8_t pin = buttonMessage.input;
bool value = buttonMessage.state; bool value = buttonMessage.state;
switch(pin) { switch(pin) {
case PCA9555_PIN_BTN_JOY_DOWN: case RP2040_INPUT_JOYSTICK_DOWN:
if (value) { if (value) {
menu_navigate_next(menu); menu_navigate_next(menu);
render = true; render = true;
} }
break; break;
case PCA9555_PIN_BTN_JOY_UP: case RP2040_INPUT_JOYSTICK_UP:
if (value) { if (value) {
menu_navigate_previous(menu); menu_navigate_previous(menu);
render = true; render = true;
} }
break; break;
case PCA9555_PIN_BTN_ACCEPT: case RP2040_INPUT_BUTTON_ACCEPT:
if (value) { if (value) {
menuArgs = menu_get_callback_args(menu, menu_get_position(menu)); menuArgs = menu_get_callback_args(menu, menu_get_position(menu));
} }
@ -155,24 +156,24 @@ void menu_wifi_settings(xQueueHandle buttonQueue, pax_buf_t* pax_buffer, ILI9341
menu_args_t* menuArgs = NULL; menu_args_t* menuArgs = NULL;
while (1) { while (1) {
button_message_t buttonMessage = {0}; rp2040_input_message_t buttonMessage = {0};
if (xQueueReceive(buttonQueue, &buttonMessage, 16 / portTICK_PERIOD_MS) == pdTRUE) { if (xQueueReceive(buttonQueue, &buttonMessage, 16 / portTICK_PERIOD_MS) == pdTRUE) {
uint8_t pin = buttonMessage.button; uint8_t pin = buttonMessage.input;
bool value = buttonMessage.state; bool value = buttonMessage.state;
switch(pin) { switch(pin) {
case PCA9555_PIN_BTN_JOY_DOWN: case RP2040_INPUT_JOYSTICK_DOWN:
if (value) { if (value) {
menu_navigate_next(menu); menu_navigate_next(menu);
render = true; render = true;
} }
break; break;
case PCA9555_PIN_BTN_JOY_UP: case RP2040_INPUT_JOYSTICK_UP:
if (value) { if (value) {
menu_navigate_previous(menu); menu_navigate_previous(menu);
render = true; render = true;
} }
break; break;
case PCA9555_PIN_BTN_ACCEPT: case RP2040_INPUT_BUTTON_ACCEPT:
if (value) { if (value) {
menuArgs = menu_get_callback_args(menu, menu_get_position(menu)); menuArgs = menu_get_callback_args(menu, menu_get_position(menu));
} }
@ -204,15 +205,6 @@ void app_main(void) {
esp_err_t res; esp_err_t res;
/* Initialize memory */ /* Initialize memory */
xQueueHandle buttonQueue = xQueueCreate(10, sizeof(button_message_t));
if (buttonQueue == NULL) {
ESP_LOGE(TAG, "Failed to allocate queue");
restart();
}
uint8_t* framebuffer = heap_caps_malloc(ILI9341_BUFFER_SIZE, MALLOC_CAP_8BIT); uint8_t* framebuffer = heap_caps_malloc(ILI9341_BUFFER_SIZE, MALLOC_CAP_8BIT);
if (framebuffer == NULL) { if (framebuffer == NULL) {
ESP_LOGE(TAG, "Failed to allocate framebuffer"); ESP_LOGE(TAG, "Failed to allocate framebuffer");
@ -232,9 +224,14 @@ void app_main(void) {
/* Initialize hardware */ /* Initialize hardware */
res = board_init(); bool lcdReady = false;
res = board_init(&lcdReady);
if (res != ESP_OK) { if (res != ESP_OK) {
if (lcdReady) {
ILI9341* ili9341 = get_ili9341();
graphics_task(pax_buffer, ili9341, framebuffer, NULL, "HARDWARE ERROR");
}
printf("Failed to initialize hardware!\n"); printf("Failed to initialize hardware!\n");
restart(); restart();
} }
@ -243,12 +240,6 @@ void app_main(void) {
ICE40* ice40 = get_ice40(); ICE40* ice40 = get_ice40();
BNO055* bno055 = get_bno055(); BNO055* bno055 = get_bno055();
RP2040* rp2040 = get_rp2040(); RP2040* rp2040 = get_rp2040();
PCA9555* pca9555 = get_pca9555();
graphics_task(pax_buffer, ili9341, framebuffer, NULL, "Button init...");
button_init(pca9555, buttonQueue);
rp2040_set_led_mode(rp2040, true, true);
graphics_task(pax_buffer, ili9341, framebuffer, NULL, "AppFS init..."); graphics_task(pax_buffer, ili9341, framebuffer, NULL, "AppFS init...");
res = appfs_init(); res = appfs_init();
@ -276,15 +267,37 @@ void app_main(void) {
graphics_task(pax_buffer, ili9341, framebuffer, NULL, "SD card mounted"); graphics_task(pax_buffer, ili9341, framebuffer, NULL, "SD card mounted");
} }
ws2812_init(GPIO_LED_DATA);
uint8_t ledBuffer[15] = {50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
ws2812_send_data(ledBuffer, sizeof(ledBuffer));
//fpga_test(ili9341, ice40, rp2040->queue);
/*while (true) {
uint16_t state;
rp2040_read_buttons(rp2040, &state);
printf("Button state: %04X\n", state);
vTaskDelay(100 / portTICK_PERIOD_MS);
ledBuffer[1] = 255;
ws2812_send_data(ledBuffer, sizeof(ledBuffer));
vTaskDelay(200 / portTICK_PERIOD_MS);
ledBuffer[1] = 0;
ledBuffer[0] = 255;
ws2812_send_data(ledBuffer, sizeof(ledBuffer));
fpga_test(ili9341, ice40, rp2040->queue);
ledBuffer[0] = 0;
ws2812_send_data(ledBuffer, sizeof(ledBuffer));
}*/
while (true) { while (true) {
menu_action_t menu_action; menu_action_t menu_action;
appfs_handle_t appfs_fd; appfs_handle_t appfs_fd;
menu_launcher(buttonQueue, pax_buffer, ili9341, framebuffer, &menu_action, &appfs_fd); menu_launcher(rp2040->queue, pax_buffer, ili9341, framebuffer, &menu_action, &appfs_fd);
if (menu_action == ACTION_APPFS) { if (menu_action == ACTION_APPFS) {
appfs_boot_app(appfs_fd); appfs_boot_app(appfs_fd);
} else if (menu_action == ACTION_FPGA) { } else if (menu_action == ACTION_FPGA) {
graphics_task(pax_buffer, ili9341, framebuffer, NULL, "FPGA TEST"); graphics_task(pax_buffer, ili9341, framebuffer, NULL, "FPGA TEST");
fpga_test(ili9341, ice40, buttonQueue); fpga_test(ili9341, ice40, rp2040->queue);
} else if (menu_action == ACTION_INSTALLER) { } else if (menu_action == ACTION_INSTALLER) {
graphics_task(pax_buffer, ili9341, framebuffer, NULL, "INSTALLER"); graphics_task(pax_buffer, ili9341, framebuffer, NULL, "INSTALLER");
//appfs_store_app(); //appfs_store_app();
@ -313,7 +326,7 @@ void app_main(void) {
graphics_task(pax_buffer, ili9341, framebuffer, NULL, "Firmware update..."); graphics_task(pax_buffer, ili9341, framebuffer, NULL, "Firmware update...");
} else if (menu_action == ACTION_SETTINGS) { } else if (menu_action == ACTION_SETTINGS) {
while (true) { while (true) {
menu_wifi_settings(buttonQueue, pax_buffer, ili9341, framebuffer, &menu_action); menu_wifi_settings(rp2040->queue, pax_buffer, ili9341, framebuffer, &menu_action);
if (menu_action == ACTION_WIFI_MANUAL) { if (menu_action == ACTION_WIFI_MANUAL) {
nvs_handle_t handle; nvs_handle_t handle;
nvs_open("system", NVS_READWRITE, &handle); nvs_open("system", NVS_READWRITE, &handle);
@ -335,9 +348,9 @@ void app_main(void) {
if (res != ESP_OK) strcpy(password, ""); if (res != ESP_OK) strcpy(password, "");
} }
} }
bool accepted = keyboard(buttonQueue, pax_buffer, ili9341, framebuffer, 30, 30, pax_buffer->width - 60, pax_buffer->height - 60, "WiFi SSID", "Press HOME to exit", ssid, sizeof(ssid)); bool accepted = keyboard(rp2040->queue, pax_buffer, ili9341, framebuffer, 30, 30, pax_buffer->width - 60, pax_buffer->height - 60, "WiFi SSID", "Press HOME to exit", ssid, sizeof(ssid));
if (accepted) { if (accepted) {
accepted = keyboard(buttonQueue, pax_buffer, ili9341, framebuffer, 30, 30, pax_buffer->width - 60, pax_buffer->height - 60, "WiFi password", "Press HOME to exit", password, sizeof(password)); accepted = keyboard(rp2040->queue, pax_buffer, ili9341, framebuffer, 30, 30, pax_buffer->width - 60, pax_buffer->height - 60, "WiFi password", "Press HOME to exit", password, sizeof(password));
} }
if (accepted) { if (accepted) {
nvs_set_str(handle, "wifi.ssid", ssid); nvs_set_str(handle, "wifi.ssid", ssid);

View file

@ -8,7 +8,6 @@
#include "ili9341.h" #include "ili9341.h"
#include "ice40.h" #include "ice40.h"
#include "hardware.h" #include "hardware.h"
#include "button_wrapper.h"
static const char *TAG = "settings"; static const char *TAG = "settings";