Board implementations and fixes (#247)

- Implemented Elecrow Crowpanel Basic 5.0"
- Implemented Elecrow Crowpanel Advance 5.0"
- Implemented CYD 2432S032C
- Fix for CYD 4848S040C rendering drift (lower transfer speed)
- Fix for SD card locking mechanism for various boards
This commit is contained in:
Ken Van Hoeylandt
2025-03-14 22:37:09 +01:00
committed by GitHub
parent 21936f7e9e
commit f85d0239ff
64 changed files with 1587 additions and 134 deletions
+1 -1
View File
@@ -42,7 +42,7 @@ bool Ili934xDisplay::start() {
const esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = configuration->resetPin,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_BGR,
.rgb_ele_order = configuration->rgbElementOrder,
.data_endian = LCD_RGB_DATA_ENDIAN_LITTLE,
.bits_per_pixel = 16,
.flags = {
+4 -1
View File
@@ -28,7 +28,8 @@ public:
bool mirrorX = false,
bool mirrorY = false,
bool invertColor = false,
uint32_t bufferSize = 0 // Size in pixel count. 0 means default, which is 1/10 of the screen size
uint32_t bufferSize = 0, // Size in pixel count. 0 means default, which is 1/10 of the screen size,
lcd_rgb_element_order_t rgbElementOrder = LCD_RGB_ELEMENT_ORDER_BGR
) : spiBusHandle(spi_bus_handle),
csPin(csPin),
dcPin(dcPin),
@@ -39,6 +40,7 @@ public:
mirrorY(mirrorY),
invertColor(invertColor),
bufferSize(bufferSize),
rgbElementOrder(rgbElementOrder),
touch(std::move(touch))
{}
@@ -55,6 +57,7 @@ public:
bool mirrorY = false;
bool invertColor = false;
uint32_t bufferSize = 0; // Size in pixel count. 0 means default, which is 1/10 of the screen size
lcd_rgb_element_order_t rgbElementOrder = LCD_RGB_ELEMENT_ORDER_BGR;
std::shared_ptr<tt::hal::touch::TouchDevice> touch;
std::function<void(uint8_t)> _Nullable backlightDutyFunction = nullptr;
};
+56
View File
@@ -0,0 +1,56 @@
# Prerequisites
*.d
# Object files
*.o
*.ko
*.obj
*.elf
# Linker output
*.ilk
*.map
*.exp
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
# Debug files
*.dSYM/
*.su
*.idb
*.pdb
# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf
.vscode/
.idea/
build/
cmake-build-debug-esp-idf/
+7
View File
@@ -0,0 +1,7 @@
file(GLOB_RECURSE SOURCES src/*.c)
idf_component_register(
SRCS ${SOURCES}
INCLUDE_DIRS include
REQUIRES driver
)
+17
View File
@@ -0,0 +1,17 @@
menu "Example Configuration"
config I2C_MASTER_SCL
int "SCL GPIO Num"
default 6 if IDF_TARGET_ESP32C3
default 19 if IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
help
GPIO number for I2C Master clock line.
config I2C_MASTER_SDA
int "SDA GPIO Num"
default 5 if IDF_TARGET_ESP32C3
default 18 if IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
help
GPIO number for I2C Master data line.
endmenu
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 Victor Hogeweij
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+8
View File
@@ -0,0 +1,8 @@
#
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
# project subdirectory.
#
PROJECT_NAME := i2c-simple
include $(IDF_PATH)/make/project.mk
+49
View File
@@ -0,0 +1,49 @@
# I2C Simple Example
(See the README.md file in the upper level 'examples' directory for more information about examples.)
## Overview
This example demonstrates basic usage of I2C driver by reading and writing from a I2C connected sensor:
If you have a new I2C application to go (for example, read the temperature data from external sensor with I2C interface), try this as a basic template, then add your own code.
## How to use example
### Hardware Required
To run this example, you should have one ESP32, ESP32-S or ESP32-C based development board as well as a MPU9250. MPU9250 is a inertial measurement unit, which contains a accelerometer, gyroscope as well as a magnetometer, for more information about it, you can read the [PDF](https://invensense.tdk.com/wp-content/uploads/2015/02/PS-MPU-9250A-01-v1.1.pdf) of this sensor.
#### Pin Assignment:
**Note:** The following pin assignments are used by default, you can change these in the `menuconfig` .
| | SDA | SCL |
| ---------------- | -------------- | -------------- |
| ESP I2C Master | I2C_MASTER_SDA | I2C_MASTER_SCL |
| MPU9250 Sensor | SDA | SCL |
For the actual default value of `I2C_MASTER_SDA` and `I2C_MASTER_SCL` see `Example Configuration` in `menuconfig`.
**Note: ** Theres no need to add an external pull-up resistors for SDA/SCL pin, because the driver will enable the internal pull-up resistors.
### Build and Flash
Enter `idf.py -p PORT flash monitor` to build, flash and monitor the project.
(To exit the serial monitor, type ``Ctrl-]``.)
See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects.
## Example Output
```bash
I (328) i2c-simple-example: I2C initialized successfully
I (338) i2c-simple-example: WHO_AM_I = 71
I (338) i2c-simple-example: I2C unitialized successfully
```
## Troubleshooting
(For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you as soon as possible.)
+3
View File
@@ -0,0 +1,3 @@
#
# Main Makefile. This is basically the same as a component makefile .
#
+6
View File
@@ -0,0 +1,6 @@
# The following lines of boilerplate have to be in your project's CMakeLists
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
set(EXTRA_COMPONENT_DIRS read)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(TCA9534_Examples)
@@ -0,0 +1,59 @@
#include "esp_log.h"
#include "driver/i2c.h"
#include "TCA9534.h"
#define I2C_MASTER_SCL_IO CONFIG_I2C_MASTER_SCL /*!< GPIO number used for I2C master clock */
#define I2C_MASTER_SDA_IO CONFIG_I2C_MASTER_SDA /*!< GPIO number used for I2C master data */
#define I2C_MASTER_NUM 0 /*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip */
#define I2C_MASTER_FREQ_HZ 400000 /*!< I2C master clock frequency */
#define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
#define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
/**
* @brief i2c master initialization
*/
static esp_err_t i2c_master_init(i2c_config_t *conf) {
int i2c_master_port = I2C_MASTER_NUM;
conf->mode = I2C_MODE_MASTER;
conf->master.clk_speed = I2C_MASTER_FREQ_HZ;
conf->sda_io_num = I2C_MASTER_SDA_IO;
conf->scl_io_num = I2C_MASTER_SCL_IO;
conf->sda_pullup_en = GPIO_PULLUP_ENABLE;
conf->scl_pullup_en = GPIO_PULLUP_ENABLE;
i2c_param_config(i2c_master_port, conf);
return i2c_driver_install(i2c_master_port, conf->mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
}
static const char *TAG = "TCA9534-Example";
void app_main(void) {
TCA9534_IO_EXP IO_EXP1;
esp_err_t status = i2c_master_init(&IO_EXP1.i2c_conf);
if (status == ESP_OK) {
ESP_LOGI(TAG, "I2C initialized successfully");
IO_EXP1.I2C_ADDR = 0b0100000;
IO_EXP1.i2c_master_port = I2C_MASTER_NUM;
set_tca9534_io_pin_direction(IO_EXP1, TCA9534_IO0, TCA9534_INPUT);
set_tca9534_io_pin_direction(IO_EXP1, TCA9534_IO1, TCA9534_OUTPUT);
int pin_state = 0;
while (1) {
pin_state = get_io_pin_input_status(IO_EXP1, TCA9534_IO0);
if (pin_state == -1) {
ESP_LOGE(TAG, "Cannot get pin status from TCA9534");
break;
}
set_tca9534_io_pin_output_state(IO_EXP1, TCA9534_IO1, pin_state);
vTaskDelay(100 / portTICK_RATE_MS);
}
ESP_ERROR_CHECK(i2c_driver_delete(I2C_MASTER_NUM));
ESP_LOGI(TAG, "I2C unitialized successfully");
}
}
+170
View File
@@ -0,0 +1,170 @@
#ifndef TCA9534_IDF_TCA9534_H
#define TCA9534_IDF_TCA9534_H
#include <driver/i2c.h>
#include <driver/gpio.h>
#define TCA9534_ERROR -1
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief TCA9534 IO Pins mapping
*/
typedef enum {
TCA9534_IO0,
TCA9534_IO1,
TCA9534_IO2,
TCA9534_IO3,
TCA9534_IO4,
TCA9534_IO5,
TCA9534_IO6,
TCA9534_IO7
} TCA9534_PINS;
/**
* @brief TCA9534 Port direction parameters
*/
typedef enum {
TCA9534_OUTPUT,
TCA9534_INPUT
} TCA9534_PORT_DIRECTION;
/**
* @brief TCA9534 initialization parameters
*/
typedef struct {
uint8_t I2C_ADDR;
int i2c_master_port;
//Only when mode is set to interrupt, otherwise it won't be used..
gpio_num_t interrupt_pin;
TaskHandle_t* interrupt_task;
} TCA9534_IO_EXP;
/**
* @brief Setup interrupts using the builtin IO_EXP_INT pin of the tca9534 and interrupt handler+task
* @param io_exp which contains the gpio pin where IO_EXP_INT is connected(interrupt_pin)
* And optionally contains the task to run when interrupt triggered (interrupt_task) if not defined the
* default handler will be used.
*/
void setup_tca9534_interrupt_handler(TCA9534_IO_EXP* io_exp);
/**
* @brief Get the current input state of the specified input pin (1 or 0)
*
* @param io_exp The io expander instance to read from or write to
* @param io_pin The io expander pin to read the state from
*
* @return
* - 0 Success! Pin is Low
* - 1 Success! Pin is High
* - TCA9534_ERROR(-1) Error! Something went wrong in the process of reading the io expander
*/
int16_t get_io_pin_input_status(TCA9534_IO_EXP* io_exp, TCA9534_PINS io_pin);
/**
* @brief Get the current input state of all the io expander pins
*
* @param io_exp The io expander instance to read from or write to
*
* @return
* - 0x00 - 0xFF Success! Dump of input register, 1 bit is equal to 1 of the physical pins (Lower 8 bits of 16 bits result)
* - TCA9534_ERROR(-1) Error! Something went wrong in the process of reading the io expander
*/
int16_t get_tca9534_all_io_pin_input_status(TCA9534_IO_EXP* io_exp);
/**
* @brief Get the current direction of all the io expander pins
*
* @param io_exp The io expander instance to read from or write to
*
* @return
* - 0x00 - 0xFF Success! Dump of configuration register, 1 bit is equal to 1 of the physical pins (Lower 8 bits of 16 bits result)
* - TCA9534_ERROR(-1) Error! Something went wrong in the process of reading the io expander
*/
int16_t get_all_io_pin_direction(TCA9534_IO_EXP* io_exp);
/**
* @brief Get the current polarity inversion state of all the io expander pins
*
* @param io_exp The io expander instance to read from or write to
*
* @return
* - 0x00 - 0xFF Success! Dump of configuration register, 1 bit is equal to 1 of the physical pins (Lower 8 bits of 16 bits result)
* - TCA9534_ERROR(-1) Error! Something went wrong in the process of reading the io expander
*/
int16_t get_all_io_polarity_inversion(TCA9534_IO_EXP* io_exp);
/**
* @brief Get the current direction of the specified io expander pin
*
* @param io_exp The io expander instance to read from or write to
* @param io_pin The io expander pin to read polarity inversion from
*
* @return
* - 0 Success! Pin is Not inverted
* - 1 Success! Pin is Inverted
* - TCA9534_ERROR(-1) Error! Something went wrong in the process of reading the io expander
*/
int16_t get_io_pin_polarity_inversion(TCA9534_IO_EXP* io_exp, TCA9534_PINS io_pin);
/**
* @brief Get the current direction of the specified physical pin (0 means OUTPUT or 1 means INPUT)
*
* @param io_exp The io expander instance to read from or write to
* @param io_pin The io expander pin to read the state from
*
* @return
* - 0 Success! Pin is OUTPUT
* - 1 Success! Pin is INPUT
* - TCA9534_ERROR(-1) Error! Something went wrong in the process of reading the io expander
*/
int16_t get_io_pin_direction(TCA9534_IO_EXP* io_exp, TCA9534_PINS io_pin);
/**
* @brief Sets all physical pins of the io expander to a specified direction (INPUT or OUTPUT)
*
* @param io_exp The io expander instance to read from or write to
* @param properties The pin direction to be set (INPUT or OUTPUT)
*
* @return
* - ESP_OK Success!
* - ESP_ERR Error!
*/
esp_err_t set_all_tca9534_io_pins_direction(TCA9534_IO_EXP* io_exp, TCA9534_PORT_DIRECTION properties);
/**
* @brief Set physical pin of the io expander to a specified direction (INPUT or OUTPUT)
*
* @param io_exp The io expander instance to read from or write to
* @param io_pin The io expander physical pin to be set
* @param properties The pin direction to be set (INPUT or OUTPUT)
*
* @return
* - ESP_OK Success!
* - ESP_ERR Error!
*/
esp_err_t set_tca9534_io_pin_direction(TCA9534_IO_EXP* io_exp, TCA9534_PINS io_pin, TCA9534_PORT_DIRECTION properties);
/**
* @brief Set physical pin of the io expander to an specified output state (HIGH(1) or LOW(0))
*
* @param io_exp The io expander instance to read from or write to
* @param io_pin The io expander physical pin to be set
* @param state The pin state to be set (1 or 0)
*
* @return
* - ESP_OK Success!
* - ESP_ERR Error!
*
* @note Pin output state can be inverted with the inversion register
*/
esp_err_t set_tca9534_io_pin_output_state(TCA9534_IO_EXP* io_exp, TCA9534_PINS io_pin, uint8_t state);
#ifdef __cplusplus
}
#endif
#endif //TCA9534_IDF_TCA9534_H
+151
View File
@@ -0,0 +1,151 @@
#include "TCA9534.h"
#include "driver/i2c.h"
#include "esp_log.h"
#include <rom/gpio.h>
#define I2C_MASTER_TIMEOUT_MS 1000
#define TCA9534_LIB_TAG "TCA9534"
#define TCA9534_IO_NUM 8
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief TCA9534 Internal configuration and pin registers
*/
typedef enum {
TCA9534_REG_INPUT_PORT,
TCA9534_REG_OUTPUT_PORT,
TCA9534_REG_POLARITY_INVERSION,
TCA9534_REG_CONFIGURATION
} TCA9534_REGISTER;
/**
* @brief Default TCA9534 interrupt task
*/
void TCA9534_default_interrupt_task(void * pvParameters){
ESP_LOGW(TCA9534_LIB_TAG, "No interrupt task defined! Using standard TCA9523 interrupt task!");
TCA9534_IO_EXP* io_exp = (TCA9534_IO_EXP*) pvParameters;
uint32_t io_num;
while(1){
if(xTaskNotifyWait(0,0,&io_num,portTICK_PERIOD_MS) == pdTRUE) {
uint8_t input_status = get_tca9534_all_io_pin_input_status(io_exp);
printf("Current input status (pin : status):\n");
for (uint8_t i = 0; i < TCA9534_IO_NUM; i++)
printf("P%d : %d\n", i, (input_status & (1<<i)) == (1 << i));
}
}
}
/**
* @brief TCA9534 interrupt handler
*/
static void IRAM_ATTR TCA9534_interrupt_handler(void *args){
TCA9534_IO_EXP* io_exp = (TCA9534_IO_EXP*) args;
xTaskNotifyFromISR(*io_exp->interrupt_task, 0, eNoAction, 0);
}
/**
* @brief Setup TCA9534 interrupts
*/
void setup_tca9534_interrupt_handler(TCA9534_IO_EXP* io_exp){
if(io_exp->interrupt_task == NULL){
xTaskCreate(
TCA9534_default_interrupt_task, /* Function that implements the task. */
"NAME", /* Text name for the task. */
2048, /* Stack size in words, not bytes. */
( void * ) io_exp, /* Parameter passed into the task. */
10,/* Priority at which the task is created. */
io_exp->interrupt_task); /* Used to pass out the created task's handle. */
}
gpio_pad_select_gpio(GPIO_NUM_26);
gpio_set_direction(GPIO_NUM_26,GPIO_MODE_INPUT);
gpio_intr_enable(GPIO_NUM_26);
gpio_set_intr_type(io_exp->interrupt_pin, GPIO_INTR_NEGEDGE);
gpio_install_isr_service(0);
gpio_isr_handler_add(io_exp->interrupt_pin, TCA9534_interrupt_handler, (void *)io_exp);
}
esp_err_t write_tca9534_reg(TCA9534_IO_EXP* io_exp, TCA9534_REGISTER cmd, uint8_t data) {
uint8_t write_buffer[2] = {cmd, data};
return i2c_master_write_to_device(io_exp->i2c_master_port, io_exp->I2C_ADDR, write_buffer,
sizeof(write_buffer), I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
}
esp_err_t read_tca9534_reg(TCA9534_IO_EXP* io_exp, TCA9534_REGISTER cmd, uint8_t *read_buff) {
uint8_t reg = cmd;
return i2c_master_write_read_device(io_exp->i2c_master_port, io_exp->I2C_ADDR, &reg,
1, read_buff, 1, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
}
int16_t get_tca9534_all_io_pin_input_status(TCA9534_IO_EXP* io_exp) {
uint8_t result = 0;
esp_err_t status = read_tca9534_reg(io_exp, TCA9534_REG_INPUT_PORT, &result);
return (status == ESP_OK) ? result : TCA9534_ERROR;
}
int16_t get_io_pin_input_status(TCA9534_IO_EXP* io_exp, TCA9534_PINS io_pin) {
int16_t result = get_tca9534_all_io_pin_input_status(io_exp);
if (result != TCA9534_ERROR)
result &= (1 << io_pin);
return (result == (1<< io_pin));
}
int16_t get_all_io_pin_direction(TCA9534_IO_EXP* io_exp) {
uint8_t result;
esp_err_t status = read_tca9534_reg(io_exp, TCA9534_REG_CONFIGURATION, &result);
return (status == ESP_OK) ? result : TCA9534_ERROR;
}
int16_t get_io_pin_direction(TCA9534_IO_EXP* io_exp, TCA9534_PINS io_pin) {
int16_t result = get_all_io_pin_direction(io_exp);
if (result != TCA9534_ERROR)
result &= (1 << io_pin);
return (result == (1<< io_pin));
}
int16_t get_all_io_polarity_inversion(TCA9534_IO_EXP* io_exp) {
uint8_t result;
esp_err_t status = read_tca9534_reg(io_exp, TCA9534_REG_POLARITY_INVERSION, &result);
return (status == ESP_OK) ? result : TCA9534_ERROR;
}
int16_t get_io_pin_polarity_inversion(TCA9534_IO_EXP* io_exp, TCA9534_PINS io_pin) {
int16_t result = get_all_io_polarity_inversion(io_exp);
if (result != TCA9534_ERROR)
result &= (1 << io_pin);
return (result == (1<< io_pin));
}
esp_err_t set_all_tca9534_io_pins_direction(TCA9534_IO_EXP* io_exp, TCA9534_PORT_DIRECTION properties) {
uint8_t dir = (properties == TCA9534_OUTPUT) ? 0x00 : 0xFF;
esp_err_t status = write_tca9534_reg(io_exp, TCA9534_REG_CONFIGURATION, dir);
return status;
}
esp_err_t set_tca9534_io_pin_direction(TCA9534_IO_EXP* io_exp, TCA9534_PINS io_pin, TCA9534_PORT_DIRECTION properties) {
uint8_t port_status = 0;
esp_err_t status = read_tca9534_reg(io_exp, TCA9534_REG_CONFIGURATION, &port_status);
port_status = (properties != TCA9534_OUTPUT) ? (port_status | (1 << io_pin)) : (port_status & ~(1 << io_pin));
status |= write_tca9534_reg(io_exp, TCA9534_REG_CONFIGURATION, port_status);
return status;
}
esp_err_t set_tca9534_io_pin_output_state(TCA9534_IO_EXP* io_exp, TCA9534_PINS io_pin, uint8_t state) {
uint8_t port_status = 0;
esp_err_t status = read_tca9534_reg(io_exp, TCA9534_REG_OUTPUT_PORT, &port_status);
port_status = (state != 0) ? (port_status | (1 << io_pin)) : (port_status & ~(1 << io_pin));
status |= write_tca9534_reg(io_exp, TCA9534_REG_OUTPUT_PORT, port_status);
return status;
}
#ifdef __cplusplus
}
#endif