291 lines
9.4 KiB
C
291 lines
9.4 KiB
C
|
#include "esp32_ucglib_hal.h"
|
||
|
|
||
|
static spi_device_handle_t spi_hdl;
|
||
|
static ucg_esp32_hal_t pins;
|
||
|
static uint8_t* buffer_1 = 0;
|
||
|
static uint8_t* buffer_2 = 0;
|
||
|
static uint8_t* buffer_3 = 0;
|
||
|
|
||
|
int16_t ucg_esp32_hal(ucg_t *ucg, int16_t msg, uint16_t arg, uint8_t *data) {
|
||
|
//ESP_LOGI("hal", "spi_byte_cb: Received a msg: %d, arg: %d, arg_ptr: %p",
|
||
|
// msg, arg, data);
|
||
|
switch (msg) {
|
||
|
case UCG_COM_MSG_POWER_UP:
|
||
|
//ESP_LOGI("hal", "UCG_COM_MSG_POWER_UP");
|
||
|
/* "data" is a pointer to ucg_com_info_t structure with the following information: */
|
||
|
/* ((ucg_com_info_t *)data)->serial_clk_speed value in nanoseconds */
|
||
|
/* ((ucg_com_info_t *)data)->parallel_clk_speed value in nanoseconds */
|
||
|
/* "arg" is not used */
|
||
|
|
||
|
/* This message is sent once at the uC startup and for power up. */
|
||
|
/* setup i/o or do any other setup */
|
||
|
;
|
||
|
|
||
|
buffer_1 = (uint8_t*) heap_caps_malloc(1, MALLOC_CAP_DMA);
|
||
|
buffer_2 = (uint8_t*) heap_caps_malloc(1, MALLOC_CAP_DMA);
|
||
|
buffer_3 = (uint8_t*) heap_caps_malloc(1, MALLOC_CAP_DMA);
|
||
|
|
||
|
pins.clk = GPIO_NUM_18;
|
||
|
pins.cs = GPIO_NUM_17;
|
||
|
pins.dc = GPIO_NUM_2;
|
||
|
pins.mosi = GPIO_NUM_23;
|
||
|
pins.reset = GPIO_NUM_14;
|
||
|
|
||
|
gpio_config_t gp_config;
|
||
|
gp_config.intr_type = GPIO_INTR_DISABLE;
|
||
|
gp_config.mode = GPIO_MODE_OUTPUT;
|
||
|
gp_config.pin_bit_mask = ((1ULL << pins.reset) | (1ULL << pins.cs) | (1ULL << pins.dc));
|
||
|
gp_config.pull_down_en = GPIO_PULLDOWN_ENABLE;
|
||
|
gp_config.pull_up_en = GPIO_PULLUP_DISABLE;
|
||
|
gpio_config(&gp_config);
|
||
|
|
||
|
spi_bus_config_t* bus_config;
|
||
|
bus_config = heap_caps_calloc(1, sizeof(spi_bus_config_t), MALLOC_CAP_8BIT);
|
||
|
bus_config->mosi_io_num = pins.mosi;
|
||
|
bus_config->miso_io_num = -1;
|
||
|
bus_config->sclk_io_num = pins.clk;
|
||
|
bus_config->quadwp_io_num = -1;
|
||
|
bus_config->quadhd_io_num = -1;
|
||
|
bus_config->max_transfer_sz = 4094;
|
||
|
bus_config->flags = 0;
|
||
|
bus_config->intr_flags = 0;
|
||
|
esp_err_t err = spi_bus_initialize(VSPI_HOST, bus_config, 1);
|
||
|
if (err != ESP_OK) {
|
||
|
ESP_LOGE("hal", "Could not initialize spi bus...");
|
||
|
switch (err) {
|
||
|
case ESP_ERR_INVALID_ARG:
|
||
|
ESP_LOGE("hal", "ESP_ERR_INVALID_ARG");
|
||
|
break;
|
||
|
case ESP_ERR_INVALID_STATE:
|
||
|
ESP_LOGE("hal", "ESP_ERR_INVALID_STATE");
|
||
|
break;
|
||
|
case ESP_ERR_NO_MEM:
|
||
|
ESP_LOGE("hal", "ESP_ERR_NO_MEM");
|
||
|
break;
|
||
|
default:
|
||
|
ESP_LOGE("hal", "Unknown err!");
|
||
|
}
|
||
|
}
|
||
|
ESP_LOGI("hal", "successfully init bus!");
|
||
|
|
||
|
spi_device_interface_config_t* dev_config;
|
||
|
dev_config = heap_caps_calloc(1, sizeof(spi_device_interface_config_t), MALLOC_CAP_8BIT);
|
||
|
dev_config->address_bits = 0;
|
||
|
dev_config->command_bits = 0;
|
||
|
dev_config->dummy_bits = 0;
|
||
|
dev_config->mode = 0;
|
||
|
dev_config->duty_cycle_pos = 0;
|
||
|
dev_config->cs_ena_posttrans = 0;
|
||
|
dev_config->cs_ena_pretrans = 0;
|
||
|
dev_config->clock_speed_hz = SPI_MASTER_FREQ_40M;
|
||
|
dev_config->spics_io_num = pins.cs;
|
||
|
dev_config->queue_size = 200;
|
||
|
dev_config->flags = 0;
|
||
|
dev_config->pre_cb = NULL;
|
||
|
dev_config->post_cb = NULL;
|
||
|
err = spi_bus_add_device(VSPI_HOST, dev_config, &spi_hdl);
|
||
|
if (err != ESP_OK) {
|
||
|
ESP_LOGE("hal", "Could not initialize spi bus...");
|
||
|
switch (err) {
|
||
|
case ESP_ERR_INVALID_ARG:
|
||
|
ESP_LOGE("hal", "ESP_ERR_INVALID_ARG");
|
||
|
break;
|
||
|
case ESP_ERR_INVALID_STATE:
|
||
|
ESP_LOGE("hal", "ESP_ERR_INVALID_STATE");
|
||
|
break;
|
||
|
case ESP_ERR_NO_MEM:
|
||
|
ESP_LOGE("hal", "ESP_ERR_NO_MEM");
|
||
|
break;
|
||
|
default:
|
||
|
ESP_LOGE("hal", "Unknown err!");
|
||
|
}
|
||
|
}
|
||
|
ESP_LOGI("hal", "successfully init bus device!");
|
||
|
break;
|
||
|
|
||
|
case UCG_COM_MSG_POWER_DOWN:
|
||
|
//ESP_LOGI("hal", "UCG_COM_MSG_POWER_DOWN");
|
||
|
/* "data" and "arg" are not used*/
|
||
|
/* This message is sent for a power down request */
|
||
|
spi_bus_remove_device(spi_hdl);
|
||
|
spi_bus_free(HSPI_HOST);
|
||
|
heap_caps_free(buffer_1);
|
||
|
heap_caps_free(buffer_2);
|
||
|
heap_caps_free(buffer_3);
|
||
|
break;
|
||
|
case UCG_COM_MSG_DELAY:
|
||
|
//ESP_LOGI("hal", "UCG_COM_MSG_DELAY");
|
||
|
/* "data" is not used */
|
||
|
/* "arg" contains the number of microseconds for the delay */
|
||
|
/* By receiving this message, the following code should delay by */
|
||
|
/* "arg" microseconds. One microsecond is 0.000001 second */
|
||
|
//vTaskDelay(arg / portTICK_PERIOD_MS / 100);
|
||
|
break;
|
||
|
case UCG_COM_MSG_CHANGE_RESET_LINE:
|
||
|
//ESP_LOGI("hal", "UCG_COM_MSG_CHANGE_RESET_LINE");
|
||
|
/* "data" is not used */
|
||
|
/* "arg" = 1: set the reset output line to 1 */
|
||
|
/* "arg" = 0: set the reset output line to 0 */
|
||
|
gpio_set_level(pins.reset, arg);
|
||
|
break;
|
||
|
case UCG_COM_MSG_CHANGE_CD_LINE:
|
||
|
//ESP_LOGI("hal", "UCG_COM_MSG_CHANGE_CD_LINE");
|
||
|
/* "ucg->com_status" bit 0 contains the old level for the CD line */
|
||
|
/* "data" is not used */
|
||
|
/* "arg" = 1: set the command/data (a0) output line to 1 */
|
||
|
/* "arg" = 0: set the command/data (a0) output line to 0 */
|
||
|
gpio_set_level(pins.dc, arg);
|
||
|
break;
|
||
|
case UCG_COM_MSG_CHANGE_CS_LINE:
|
||
|
//ESP_LOGI("hal", "UCG_COM_MSG_CHANGE_CS_LINE");
|
||
|
/* "ucg->com_status" bit 1 contains the old level for the CS line */
|
||
|
/* "data" is not used */
|
||
|
/* "arg" = 1: set the chipselect output line to 1 */
|
||
|
/* "arg" = 0: set the chipselect output line to 0 */
|
||
|
gpio_set_level(pins.cs, arg);
|
||
|
break;
|
||
|
case UCG_COM_MSG_SEND_BYTE:
|
||
|
//ESP_LOGI("hal", "UCG_COM_MSG_SEND_BYTE");
|
||
|
/* "data" is not used */
|
||
|
/* "arg" contains one byte, which should be sent to the display */
|
||
|
/* The current status of the CD line is available */
|
||
|
/* in bit 0 of u8g->com_status */
|
||
|
;
|
||
|
*buffer_1 = (uint8_t) arg;
|
||
|
spi_transaction_t transaction;
|
||
|
transaction.addr = 0;
|
||
|
transaction.cmd = 0;
|
||
|
transaction.length = 8;
|
||
|
transaction.rxlength = 0;
|
||
|
transaction.tx_buffer = buffer_1;
|
||
|
transaction.rx_buffer = NULL;
|
||
|
transaction.flags = SPI_TRANS_USE_RXDATA ;
|
||
|
spi_device_transmit(spi_hdl, &transaction);
|
||
|
break;
|
||
|
case UCG_COM_MSG_REPEAT_1_BYTE:
|
||
|
{
|
||
|
ESP_LOGW("hal", "UCG_COM_MSG_REPEAT_1_BYTE");
|
||
|
/* "data[0]" contains one byte */
|
||
|
/* repeat sending the byte in data[0] "arg" times */
|
||
|
/* The current status of the CD line is available */
|
||
|
/* in bit 0 of u8g->com_status */
|
||
|
//spi_transaction_t transaction;
|
||
|
//transaction.length = 8;
|
||
|
//transaction.tx_buffer = data[0];
|
||
|
//transaction.flags = SPI_TRANS_USE_TXDATA;
|
||
|
//int i;
|
||
|
//for (i = 0; i < arg; i++) {
|
||
|
// spi_device_polling_transmit(spi_hdl, &transaction);
|
||
|
//}
|
||
|
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
case UCG_COM_MSG_REPEAT_2_BYTES:
|
||
|
{
|
||
|
ESP_LOGW("hal", "UCG_COM_MSG_REPEAT_2_BYTES");
|
||
|
// spi_transaction_t transaction1;
|
||
|
// transaction.flags = SPI_TRANS_USE_TXDATA;
|
||
|
// transaction.length = 8;
|
||
|
// transaction.tx_buffer = data[0];
|
||
|
// spi_transaction_t transaction2;
|
||
|
// transaction2.flags = SPI_TRANS_USE_TXDATA;
|
||
|
// transaction2.length = 8;
|
||
|
// transaction2.tx_buffer = data[1];
|
||
|
// int i;
|
||
|
// for (i = 0; i < arg; i++) {
|
||
|
// spi_device_polling_transmit(spi_hdl, &transaction1);
|
||
|
// spi_device_polling_transmit(spi_hdl, &transaction2);
|
||
|
// }
|
||
|
/* "data[0]" contains first byte */
|
||
|
/* "data[1]" contains second byte */
|
||
|
/* repeat sending the two bytes "arg" times */
|
||
|
/* The current status of the CD line is available */
|
||
|
/* in bit 0 of u8g->com_status */
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
case UCG_COM_MSG_REPEAT_3_BYTES:
|
||
|
{
|
||
|
//ESP_LOGI("hal", "UCG_COM_MSG_REPEAT_3_BYTES");
|
||
|
/* "data[0]" contains first byte */
|
||
|
/* "data[1]" contains second byte */
|
||
|
/* "data[2]" contains third byte */
|
||
|
/* repeat sending the three bytes "arg" times */
|
||
|
/* The current status of the CD line is available */
|
||
|
/* in bit 0 of u8g->com_status */
|
||
|
buffer_3[0] = data[0];
|
||
|
buffer_3[1] = data[1];
|
||
|
buffer_3[2] = data[2];
|
||
|
spi_transaction_t transaction;
|
||
|
transaction.addr = 0;
|
||
|
transaction.cmd = 0;
|
||
|
transaction.length = 3*8;
|
||
|
transaction.rxlength = 0;
|
||
|
transaction.tx_buffer = buffer_3;
|
||
|
transaction.rx_buffer = NULL;
|
||
|
transaction.flags = SPI_TRANS_USE_RXDATA ;
|
||
|
int i;
|
||
|
for (i = 0; i < arg; i++) {
|
||
|
spi_device_transmit(spi_hdl, &transaction);
|
||
|
}
|
||
|
// spi_transaction_t transaction1;
|
||
|
// transaction1.flags = SPI_TRANS_USE_TXDATA ;
|
||
|
// transaction1.length = 8;
|
||
|
// transaction1.tx_buffer = &data[0];
|
||
|
// spi_transaction_t transaction2;
|
||
|
// transaction2.flags = SPI_TRANS_USE_TXDATA ;
|
||
|
// transaction2.length = 8;
|
||
|
// transaction2.tx_buffer = &data[1];
|
||
|
// spi_transaction_t transaction3;
|
||
|
// transaction3.flags = SPI_TRANS_USE_TXDATA ;
|
||
|
// transaction3.length = 8;
|
||
|
// transaction3.tx_buffer = &data[2];
|
||
|
// int i;
|
||
|
// for (i = 0; i < arg; i++) {
|
||
|
// spi_device_polling_transmit(spi_hdl, &transaction1);
|
||
|
// spi_device_polling_transmit(spi_hdl, &transaction2);
|
||
|
// spi_device_polling_transmit(spi_hdl, &transaction3);
|
||
|
// }
|
||
|
break;
|
||
|
}
|
||
|
case UCG_COM_MSG_SEND_STR:
|
||
|
{
|
||
|
ESP_LOGW("hal", "UCG_COM_MSG_SEND_STR");
|
||
|
/* "data" is an array with "arg" bytes */
|
||
|
/* send "arg" bytes to the display */
|
||
|
spi_transaction_t transaction1;
|
||
|
transaction1.flags = SPI_TRANS_USE_RXDATA | SPI_TRANS_USE_TXDATA ;
|
||
|
transaction1.length = 8*arg;
|
||
|
transaction1.tx_buffer = &data[0];
|
||
|
spi_device_polling_transmit(spi_hdl, &transaction1);
|
||
|
break;
|
||
|
}
|
||
|
case UCG_COM_MSG_SEND_CD_DATA_SEQUENCE:
|
||
|
{
|
||
|
//ESP_LOGW("hal", "UCG_COM_MSG_SEND_CD_DATA_SEQUENCE");
|
||
|
/* "data" is a pointer to two bytes, which contain the cd line */
|
||
|
/* status and display data */
|
||
|
/* "arg" contains the number of these two byte tuples which need to */
|
||
|
/* be analysed and sent. Bellow is a example sequence */
|
||
|
/* The content of bit 0 in u8g->com_status is undefined for this message */
|
||
|
|
||
|
while (arg > 0) {
|
||
|
if (*data != 0) {
|
||
|
if (*data == 1) {
|
||
|
/* set CD (=D/C=A0) line to low */
|
||
|
} else {
|
||
|
/* set CD (=D/C=A0) line to high */
|
||
|
}
|
||
|
}
|
||
|
data++;
|
||
|
/* send *data to the display */
|
||
|
data++;
|
||
|
arg--;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
return 1;
|
||
|
}
|