#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; }