From eaa74ebf87e58d60265b7fd2ef65b900ef85f836 Mon Sep 17 00:00:00 2001 From: NilsForssen Date: Tue, 3 Aug 2021 01:48:52 +0200 Subject: [PATCH] Update --- components/u8g2 | 1 + main/Audiolib.cpp | 34 +++++- main/Audiolib.h | 35 +++++- main/CMakeLists.txt | 2 +- main/Peripherals.cpp | 5 +- main/Peripherals.h | 21 ++-- main/main.cpp | 253 ++++++++++++++++++++++------------------ main/u8g2_esp32_hal.cpp | 239 +++++++++++++++++++++++++++++++++++++ main/u8g2_esp32_hal.h | 41 +++++++ 9 files changed, 488 insertions(+), 143 deletions(-) create mode 160000 components/u8g2 create mode 100644 main/u8g2_esp32_hal.cpp create mode 100644 main/u8g2_esp32_hal.h diff --git a/components/u8g2 b/components/u8g2 new file mode 160000 index 0000000..7b2b60f --- /dev/null +++ b/components/u8g2 @@ -0,0 +1 @@ +Subproject commit 7b2b60f4184acb8524142061e306d916e7e34ebd diff --git a/main/Audiolib.cpp b/main/Audiolib.cpp index aeae0b0..29a0226 100644 --- a/main/Audiolib.cpp +++ b/main/Audiolib.cpp @@ -5,15 +5,21 @@ void a2d_cb_redirect(esp_a2d_cb_event_t, esp_a2d_cb_param_t *); void a2d_data_cb_redirect(const uint8_t *, uint32_t); void avrc_cb_redirect(esp_avrc_ct_cb_event_t, esp_avrc_ct_cb_param_t *); -Audiolib::Audiolib(const char *device_name) +static al_event_cb_param_t sending_param; + +static bool sent_title = false; +static bool sent_artist = false; +static bool sent_album = false; + +Audiolib::Audiolib(const char *device_name, void (*on_change)(al_event_cb_t, al_event_cb_param_t*)) { _devname = device_name; Audiolib_redirect = this; + this->on_change_cb = on_change; } void Audiolib::start() { - nvs_flash_init(); esp_bt_controller_config_t cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); @@ -118,14 +124,31 @@ void Audiolib::avrc_cb(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t *par { case ESP_AVRC_MD_ATTR_TITLE: title = text; + sent_title = true; break; case ESP_AVRC_MD_ATTR_ARTIST: artist = text; + sent_artist = true; break; case ESP_AVRC_MD_ATTR_ALBUM: album = text; + sent_album = true; break; } + if (sent_title && sent_artist && sent_album) { + sending_param.metadata = { + .title = this->title, + .artist = this->artist, + .album = this->album, + }; + + on_change_cb(AL_META_UPDATE, &sending_param); + + sent_title = false; + sent_artist = false; + sent_album = false; + } + break; case ESP_AVRC_CT_PLAY_STATUS_RSP_EVT: printf("AVRC, Play status\n"); @@ -142,19 +165,18 @@ void Audiolib::avrc_cb(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t *par printf("AVRC, play status change\n"); switch(param->change_ntf.event_parameter.playback) { case ESP_AVRC_PLAYBACK_STOPPED: - playing = false; printf("AVRC, Playback stopped\n"); + on_change_cb(AL_STOPPED, NULL); break; case ESP_AVRC_PLAYBACK_PLAYING: - playing = true; printf("AVRC, Playback playing\n"); + on_change_cb(AL_PLAYING, NULL); break; case ESP_AVRC_PLAYBACK_PAUSED: - playing = false; printf("AVRC, Playback paused\n"); + on_change_cb(AL_PAUSED, NULL); break; case ESP_AVRC_PLAYBACK_ERROR: - playing = false; printf("AVRC, Playback erorr\n"); break; default: diff --git a/main/Audiolib.h b/main/Audiolib.h index 5fc6c91..916546c 100644 --- a/main/Audiolib.h +++ b/main/Audiolib.h @@ -27,18 +27,34 @@ typedef enum { PEAK } filter_t; +typedef enum { + AL_CONNECTED, + AL_DISCONNECTED, + AL_PLAYING, + AL_PAUSED, + AL_STOPPED, + AL_META_UPDATE +} al_event_cb_t; + +typedef union { + + struct al_meta_update_cb_param_t { + char* title; + char* artist; + char* album; + } metadata; + +} al_event_cb_param_t; + class Audiolib; class Filter; struct CombinedChannelFilter; + + class Audiolib { public: - char* title = (char*)""; - char* artist = (char*)""; - char* album = (char*)""; - bool playing = false; - - Audiolib(const char* device_name); + Audiolib(const char* device_name, void (*)(al_event_cb_t, al_event_cb_param_t*)); void start(); void stop(); @@ -66,6 +82,13 @@ public: private: + + char* title = (char*)""; + char* artist = (char*)""; + char* album = (char*)""; + + void (*on_change_cb)(al_event_cb_t, al_event_cb_param_t*); + void getMeta(); uint16_t supportedNotifications = 0x00; bool _filtering = true; diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 4f6aa19..54f9ce8 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -1,2 +1,2 @@ -idf_component_register(SRCS "Peripherals.cpp" "Audiolib.cpp" "main.cpp" +idf_component_register(SRCS "Peripherals.cpp" "Audiolib.cpp" "main.cpp" "u8g2_esp32_hal.cpp" INCLUDE_DIRS ".") \ No newline at end of file diff --git a/main/Peripherals.cpp b/main/Peripherals.cpp index 94d270d..3bb459b 100644 --- a/main/Peripherals.cpp +++ b/main/Peripherals.cpp @@ -1,8 +1,5 @@ #include "Peripherals.h" -static const adc_atten_t atten = ADC_ATTEN_DB_0; -static const adc_bits_width_t width = ADC_WIDTH_BIT_12; - Potentiometer::Potentiometer(const int min, const int max, update_callback_t update_ntfy) : Potentiometer(ADC_UNIT_1, ADC_CHANNEL_1, min, max, update_ntfy) {} @@ -90,4 +87,4 @@ int Potentiometer::update() { float Potentiometer::get_percent() { int raw = get_raw(); return ((float)raw / (4096)) * 100; -} \ No newline at end of file +} diff --git a/main/Peripherals.h b/main/Peripherals.h index d65d612..45e213c 100644 --- a/main/Peripherals.h +++ b/main/Peripherals.h @@ -1,6 +1,5 @@ #include "driver/adc.h" #include "esp_adc_cal.h" -#include "esp_adc_cal.h" #ifndef Peripherals_H #define Peripherals_H @@ -9,16 +8,13 @@ #define VREF 1100 #define AVERAGESUM 5 +#define atten ADC_ATTEN_DB_2_5 +#define width ADC_WIDTH_BIT_12 + typedef void(*update_callback_t)(float); class Potentiometer { public: - adc_unit_t adc_unit; - adc_channel_t adc_channel; - int min_raw; - int max_raw; - update_callback_t on_change; - int prev_raw; Potentiometer(const int, const int, update_callback_t = NULL); Potentiometer(const adc_unit_t, const adc_channel_t, const int, const int, update_callback_t = NULL); int get_raw(); @@ -26,13 +22,16 @@ public: float get_percent(); private: - + adc_unit_t adc_unit; + adc_channel_t adc_channel; + int min_raw; + int max_raw; + update_callback_t on_change; + int prev_raw; + static bool init_adc(const adc_unit_t, const adc_channel_t); static void check_efuse(); static void print_char_val_type(esp_adc_cal_value_t); - - - }; diff --git a/main/main.cpp b/main/main.cpp index a63c063..27dbf6d 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -3,8 +3,9 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "driver/gpio.h" -#include - +#include "u8g2.h" +#include "u8g2_esp32_hal.h" +#include "cstring" //void updateFilter(const uint8_t, float*, float*, CombinedChannelFilter*); Potentiometer* pot1 = new Potentiometer(ADC_UNIT_2, ADC_CHANNEL_5, 70, 1010); //65/66 -> 572/573 -> 1019 @@ -12,18 +13,53 @@ Potentiometer* pot1 = new Potentiometer(ADC_UNIT_2, ADC_CHANNEL_5, 70, 1010); // //Potentiometer* pot3 = new Potentiometer(ADC1_CHANNEL_6, 38, 988); //Potentiometer* pot4 = new Potentiometer(ADC1_CHANNEL_7, 29, 990); -int sample_pot_percent(const adc1_channel_t*, float*); - -Audiolib Audiosource = Audiolib("Bluetooth Speaker"); - CombinedChannelFilter* highshelf_filter = new CombinedChannelFilter(new Filter(HIGHSHELF, 2000, 44100, 0.8, 0), new Filter(HIGHSHELF, 2000, 44100, 0.8, 0)); CombinedChannelFilter* lowshelf_filter = new CombinedChannelFilter(new Filter(LOWSHELF, 250, 44100, 0.8, 0), new Filter(LOWSHELF, 250, 44100, 0.8, 0)); CombinedChannelFilter* highpass_filter = new CombinedChannelFilter(new Filter(LOWPASS, 8000, 44100, 0.75, 0), new Filter(LOWPASS, 8000, 44100, 0.75, 0)); CombinedChannelFilter* lowpass_filter = new CombinedChannelFilter(new Filter(HIGHPASS, 60, 44100, 0.75, 0), new Filter(HIGHPASS, 60, 44100, 0.75, 0)); CombinedChannelFilter* peak_filter = new CombinedChannelFilter(new Filter(PEAK, 700, 44100, 0.8, 0), new Filter(PEAK, 700, 44100, 0.8, 0)); +u8g2_t u8g2; +u8g2_uint_t displayHeight = u8g2_GetDisplayHeight(&u8g2); +u8g2_uint_t displayWidth = u8g2_GetDisplayWidth(&u8g2); + +u8g2_esp32_hal_t u8g2_esp32_hal; + +struct timeval tv_now; + +static int x; +static char* text; +static int textWidth; +static bool scrolling = false; +static connected = false; + +void scrollText(char*); +void update_display(al_event_cb_t, al_event_cb_param_t*); +void draw_string(char* string, int x = 0); + +Audiolib Audiosource = Audiolib("Titta vad jag heter", &update_display); + extern "C" { void app_main(void){ + + + u8g2_esp32_hal.sda = GPIO_NUM_32; + u8g2_esp32_hal.scl = GPIO_NUM_33; + u8g2_esp32_hal_init(u8g2_esp32_hal); + + + u8g2_Setup_ssd1306_i2c_128x32_univision_f( + &u8g2, + U8G2_R0, + u8g2_esp32_i2c_byte_cb, + u8g2_esp32_gpio_and_delay_cb); + + u8x8_SetI2CAddress(&u8g2.u8x8, 0x3C); + u8g2_InitDisplay(&u8g2); + u8g2_SetPowerSave(&u8g2, 0); + u8g2_SetFont(&u8g2, u8g2_font_ncenR24_tf); + + Audiosource.set_I2S(26, 27, 25); Audiosource.add_combined_filter(highpass_filter); @@ -34,123 +70,110 @@ extern "C" { Audiosource.start(); while (true) { - //printf("%d\n", pot1->update()); - printf("%d\n", pot1->update()); - printf("%f\n", pot1->get_percent()); + while (connected) { + + + + + + } + draw(); vTaskDelay(pdMS_TO_TICKS(100)); } } } +void draw() { + u8g2_ClearBuffer(&u8g2); + u8g2_DrawStr(&u8g2, x, 32, text); + u8g2_SendBuffer(&ug82); +} -int sample_pot_percent(const adc1_channel_t* adc_channel, float* pot_val) { - float adc_val = 0; - for (int i = 0; i < 100; i++) { - adc_val += adc1_get_raw(*adc_channel); +void scrollText(char* text) { + u8g2_ClearBuffer(&u8g2); + u8g2_DrawStr(&u8g2, x, 32, text); + u8g2_SendBuffer(&u8g2); + if (x == 0) { + vTaskDelay(pdMS_TO_TICKS(990)); + } + + if ((textWidth + x) > u8g2_GetDisplayWidth(&u8g2)) { + x -= 1; } - adc_val = adc_val/100; - if (*pot_val == 0) { - *pot_val = adc_val; + + else { + x = 0; + vTaskDelay(pdMS_TO_TICKS(990)); } - *pot_val = (adc_val + (9*(*pot_val)) ) / 10; + vTaskDelay(pdMS_TO_TICKS(10)); +} - printf("%f\n", round(*pot_val) ); - return 1; +void update_display(al_event_cb_t event, al_event_cb_param_t* param) { + x = 0; + switch (event) { + case AL_CONNECTED: + scrolling = true; + text = (char*) "Connected!"; + printf("AL, Connected\n"); + connected = true; + break; + + case AL_DISCONNECTED: + scrolling = true; + text = (char*) "Disconnected!"; + printf("AL, Disconnected\n"); + break; + + case AL_PLAYING: + scrolling = false; + text = (char*) "PLAY"; + printf("AL, Playing\n"); + break; + + case AL_PAUSED: + scrolling = false; + text = (char*) "PAUSE"; + printf("AL, Paused\n"); + break; + + case AL_STOPPED: + printf("AL, Stopped\n"); + break; + + case AL_META_UPDATE: + scrolling = true; + + int titleLen = strlen(param->metadata.title); + int artistLen = strlen(param->metadata.artist); + + text = (char*) malloc(titleLen + artistLen + 3 + 1); //Maybe runaway pointer every time this is done? + memcpy(text, param->metadata.title, titleLen); + memcpy(text + titleLen, (char*)" - ", 3); + memcpy(text + titleLen + 3, param->metadata.artist, artistLen); + *(text + titleLen + 3 + artistLen) = *"\0"; + + textWidth = u8g2_GetUTF8Width(&u8g2, text); + printf("%d\n", textWidth); + printf("%s\n", text); + + printf("AL, Meta_Update\n"); + break; + } } -// void setup() -// { -// pinMode(BUTTON1, INPUT); -// pinMode(BUTTON2, INPUT); -// pinMode(BUTTON3, INPUT); - -// analogReadResolution(12); -// Serial.begin(115200); -// Audiosource.set_I2S(26, 27, 25); - -// Audiosource.add_combined_filter(highpass_filter); -// Audiosource.add_combined_filter(lowshelf_filter); -// Audiosource.add_combined_filter(peak_filter); -// Audiosource.add_combined_filter(highshelf_filter); -// Audiosource.add_combined_filter(lowpass_filter); - -// Audiosource.start(); -// } - -// void loop() -// { -// currentMillis = millis(); -// if (currentMillis - previousPotMillis >= potPollInterval) -// { -// previousPotMillis = currentMillis; -// updateFilter(POT1, &pot1val, &filter1gain, highshelf_filter); -// updateFilter(POT2, &pot2val, &filter2gain, peak_filter); -// updateFilter(POT3, &pot3val, &filter3gain, lowshelf_filter); -// } -// currentMillis = millis(); -// if (currentMillis - previousButtonMillis >= buttonPollInterval) -// { -// previousButtonMillis = currentMillis; -// if (digitalRead(BUTTON1)) -// { -// if (!prevButton1) -// { -// printf("Start filter\n"); // Button 1 -// prevButton1 = true; -// Audiosource.start_filter(); -// } -// } -// else -// { -// prevButton1 = false; -// } -// if (digitalRead(BUTTON2)) -// { -// if (!prevButton2) -// { -// printf("Stop filter\n"); // Button 2 -// prevButton2 = true; -// Audiosource.stop_filter(); -// } -// } -// else -// { -// prevButton2 = false; -// } -// if (digitalRead(BUTTON3)) -// { -// if (!prevButton3) -// { -// printf("Button3\n"); // Button 3 -// Audiosource.pause(); -// printf("%s, %s, %s\n", Audiosource.title, Audiosource.artist, Audiosource.album); -// prevButton3 = true; -// } -// } -// else -// { -// prevButton3 = false; -// } -// } -// } - -// void updateFilter(const adc_channel_t adc_channel, float* potVal, float* prevGain, CombinedChannelFilter* filter) -// { -// *potVal = ((float(adc1_get_raw(adc_channel_1) adc_channel) * 20.00002 / 4095) - 10.00001 + (4*(*potVal))) / 5; - -// printf - -// if (!int(((fabs(*potVal)) * 2) + 0.75) * ((*potVal > 0) - (*potVal < 0))){ -// if (*prevGain != 0){ -// *prevGain = 0; -// filter->update(*prevGain); -// } -// return; -// } -// float diff = fabs(*potVal) - fabs(*prevGain); -// if (diff >= gainStep || diff <= -gainStep) { -// *prevGain = float(int(((fabs(*potVal)) * 2) + 0.5)) / 2 * ((*potVal > 0) - (*potVal < 0)); -// filter->update(*prevGain); -// return; -// } -// } + +/* +int substr(char* string, int startPixel, int totPixels) { + + int len = strlen(strin); + int newlen = (int) len/2; + + char* newstr = (char*) malloc(newlen + 1); + memcpy(newstr, &str[start], newlen); + newstr[newlen] = *"\0"; + + + if (pixels > u8g2_GetUTF8Width((int) len/2) + for (int i = 0; i < strlen(string)) + +}*/ \ No newline at end of file diff --git a/main/u8g2_esp32_hal.cpp b/main/u8g2_esp32_hal.cpp new file mode 100644 index 0000000..d44fef0 --- /dev/null +++ b/main/u8g2_esp32_hal.cpp @@ -0,0 +1,239 @@ +#include +#include + +#include "sdkconfig.h" +#include "esp_log.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#include "u8g2_esp32_hal.h" + +static const char *TAG = "u8g2_esp32_hal"; +static const unsigned int I2C_TIMEOUT_MS = 1000; + +static spi_device_handle_t handle_spi; // SPI handle. +static i2c_cmd_handle_t handle_i2c; // I2C handle. +static u8g2_esp32_hal_t u8g2_esp32_hal; // HAL state data. + +#undef ESP_ERROR_CHECK +#define ESP_ERROR_CHECK(x) do { esp_err_t rc = (x); if (rc != ESP_OK) { ESP_LOGE("err", "esp_err_t = %d", rc); assert(0 && #x);} } while(0); + +/* + * Initialze the ESP32 HAL. + */ +void u8g2_esp32_hal_init(u8g2_esp32_hal_t u8g2_esp32_hal_param) { + u8g2_esp32_hal = u8g2_esp32_hal_param; +} // u8g2_esp32_hal_init + +/* + * HAL callback function as prescribed by the U8G2 library. This callback is invoked + * to handle SPI communications. + */ +uint8_t u8g2_esp32_spi_byte_cb(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) { + ESP_LOGD(TAG, "spi_byte_cb: Received a msg: %d, arg_int: %d, arg_ptr: %p", msg, arg_int, arg_ptr); + switch(msg) { + case U8X8_MSG_BYTE_SET_DC: + if (u8g2_esp32_hal.dc != U8G2_ESP32_HAL_UNDEFINED) { + gpio_set_level(u8g2_esp32_hal.dc, arg_int); + } + break; + + case U8X8_MSG_BYTE_INIT: { + if (u8g2_esp32_hal.clk == U8G2_ESP32_HAL_UNDEFINED || + u8g2_esp32_hal.mosi == U8G2_ESP32_HAL_UNDEFINED || + u8g2_esp32_hal.cs == U8G2_ESP32_HAL_UNDEFINED) { + break; + } + + spi_bus_config_t bus_config; + memset(&bus_config, 0, sizeof(spi_bus_config_t)); + bus_config.sclk_io_num = u8g2_esp32_hal.clk; // CLK + bus_config.mosi_io_num = u8g2_esp32_hal.mosi; // MOSI + bus_config.miso_io_num = -1; // MISO + bus_config.quadwp_io_num = -1; // Not used + bus_config.quadhd_io_num = -1; // Not used + //ESP_LOGI(TAG, "... Initializing bus."); + ESP_ERROR_CHECK(spi_bus_initialize(HSPI_HOST, &bus_config, 1)); + + spi_device_interface_config_t dev_config; + memset(&dev_config, 0, sizeof(spi_device_interface_config_t)); +// 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 = 10000; + dev_config.spics_io_num = u8g2_esp32_hal.cs; +// dev_config.flags = 0; + dev_config.queue_size = 200; +// dev_config.pre_cb = NULL; +// dev_config.post_cb = NULL; + //ESP_LOGI(TAG, "... Adding device bus."); + ESP_ERROR_CHECK(spi_bus_add_device(HSPI_HOST, &dev_config, &handle_spi)); + + break; + } + + case U8X8_MSG_BYTE_SEND: { + spi_transaction_t trans_desc; + trans_desc.addr = 0; + trans_desc.cmd = 0; + trans_desc.flags = 0; + trans_desc.length = 8 * arg_int; // Number of bits NOT number of bytes. + trans_desc.rxlength = 0; + trans_desc.tx_buffer = arg_ptr; + trans_desc.rx_buffer = NULL; + + //ESP_LOGI(TAG, "... Transmitting %d bytes.", arg_int); + ESP_ERROR_CHECK(spi_device_transmit(handle_spi, &trans_desc)); + break; + } + } + return 0; +} // u8g2_esp32_spi_byte_cb + +/* + * HAL callback function as prescribed by the U8G2 library. This callback is invoked + * to handle I2C communications. + */ +uint8_t u8g2_esp32_i2c_byte_cb(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) { + ESP_LOGD(TAG, "i2c_cb: Received a msg: %d, arg_int: %d, arg_ptr: %p", msg, arg_int, arg_ptr); + + switch(msg) { + case U8X8_MSG_BYTE_SET_DC: //32 + if (u8g2_esp32_hal.dc != U8G2_ESP32_HAL_UNDEFINED) { + gpio_set_level(u8g2_esp32_hal.dc, arg_int); + } + break; + + case U8X8_MSG_BYTE_INIT: //20 + if (u8g2_esp32_hal.sda == U8G2_ESP32_HAL_UNDEFINED || + u8g2_esp32_hal.scl == U8G2_ESP32_HAL_UNDEFINED) { + break; + } + //i2c_driver_delete(I2C_MASTER_NUM); // delete if already installed + i2c_config_t conf; + memset(&conf, 0, sizeof(i2c_config_t)); + conf.mode = I2C_MODE_MASTER; + ESP_LOGI(TAG, "sda_io_num %d", u8g2_esp32_hal.sda); + conf.sda_io_num = u8g2_esp32_hal.sda; + //conf.sda_pullup_en = GPIO_PULLUP_ENABLE; + conf.sda_pullup_en = GPIO_PULLUP_DISABLE; // External pull-up required, 3K3 for Vcc=3.3V + ESP_LOGI(TAG, "scl_io_num %d", u8g2_esp32_hal.scl); + conf.scl_io_num = u8g2_esp32_hal.scl; + //conf.scl_pullup_en = GPIO_PULLUP_ENABLE; + conf.scl_pullup_en = GPIO_PULLUP_DISABLE; // External pull-up required, 3K3 for Vcc=3.3V + ESP_LOGI(TAG, "clk_speed %d", I2C_MASTER_FREQ_HZ); + conf.master.clk_speed = I2C_MASTER_FREQ_HZ; + ESP_LOGI(TAG, "clk_flags 0x%X", conf.clk_flags); + ESP_LOGI(TAG, "i2c_param_config %d", conf.mode); + ESP_ERROR_CHECK(i2c_param_config(I2C_MASTER_NUM, &conf)); + ESP_LOGI(TAG, "i2c_driver_install for I2C bus %d", I2C_MASTER_NUM); + ESP_ERROR_CHECK(i2c_driver_install(I2C_MASTER_NUM, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0)); + ESP_LOGI(TAG, "i2c_driver_install done."); + break; + + case U8X8_MSG_BYTE_SEND: { //23 + uint8_t* data_ptr = (uint8_t*)arg_ptr; + ESP_LOG_BUFFER_HEXDUMP(TAG, data_ptr, arg_int, ESP_LOG_VERBOSE); + + while( arg_int > 0 ) { + ESP_ERROR_CHECK(i2c_master_write_byte(handle_i2c, *data_ptr, ACK_CHECK_EN)); + data_ptr++; + arg_int--; + } + } + break; + + case U8X8_MSG_BYTE_START_TRANSFER: { //24 + uint8_t i2c_address = u8x8_GetI2CAddress(u8x8); + handle_i2c = i2c_cmd_link_create(); + ESP_LOGD(TAG, "Start I2C transfer to 0x%02X", i2c_address); + ESP_ERROR_CHECK(i2c_master_start(handle_i2c)); + ESP_ERROR_CHECK(i2c_master_write_byte(handle_i2c, ((i2c_address << 1) | I2C_MASTER_WRITE), ACK_CHECK_EN)); + } + break; + + case U8X8_MSG_BYTE_END_TRANSFER: //25 + ESP_LOGD(TAG, "End I2C transfer."); + ESP_ERROR_CHECK(i2c_master_stop(handle_i2c)); + ESP_ERROR_CHECK(i2c_master_cmd_begin(I2C_MASTER_NUM, handle_i2c, I2C_TIMEOUT_MS / portTICK_RATE_MS)); + i2c_cmd_link_delete(handle_i2c); + break; + } + return 0; +} // u8g2_esp32_i2c_byte_cb + + +/* + * HAL callback function as prescribed by the U8G2 library. This callback is invoked + * to handle callbacks for GPIO and delay functions. + */ +uint8_t u8g2_esp32_gpio_and_delay_cb(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) { + ESP_LOGD(TAG, "gpio_and_delay_cb: Received a msg: %d, arg_int: %d, arg_ptr: %p", msg, arg_int, arg_ptr); + + switch(msg) { + // Initialize the GPIO and DELAY HAL functions. If the pins for DC and RESET have been + // specified then we define those pins as GPIO outputs. + case U8X8_MSG_GPIO_AND_DELAY_INIT: { + uint64_t bitmask = 0; + if (u8g2_esp32_hal.dc != U8G2_ESP32_HAL_UNDEFINED) { + bitmask = bitmask | (1ull<