--- /dev/null
+Subproject commit 7b2b60f4184acb8524142061e306d916e7e34ebd
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();
{
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");
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:
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();
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;
-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
#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) {}
float Potentiometer::get_percent() {
int raw = get_raw();
return ((float)raw / (4096)) * 100;
-}
\ No newline at end of file
+}
#include "driver/adc.h"
#include "esp_adc_cal.h"
-#include "esp_adc_cal.h"
#ifndef Peripherals_H
#define Peripherals_H
#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();
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);
-
-
-
};
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
-#include <cmath>
-
+#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
//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);
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
--- /dev/null
+#include <stdio.h>
+#include <string.h>
+
+#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<<u8g2_esp32_hal.dc);
+ }
+ if (u8g2_esp32_hal.reset != U8G2_ESP32_HAL_UNDEFINED) {
+ bitmask = bitmask | (1ull<<u8g2_esp32_hal.reset);
+ }
+ if (u8g2_esp32_hal.cs != U8G2_ESP32_HAL_UNDEFINED) {
+ bitmask = bitmask | (1ull<<u8g2_esp32_hal.cs);
+ }
+
+ if (bitmask==0) {
+ break;
+ }
+ gpio_config_t gpioConfig;
+ gpioConfig.pin_bit_mask = bitmask;
+ gpioConfig.mode = GPIO_MODE_OUTPUT;
+ gpioConfig.pull_up_en = GPIO_PULLUP_DISABLE;
+ gpioConfig.pull_down_en = GPIO_PULLDOWN_ENABLE;
+ gpioConfig.intr_type = GPIO_INTR_DISABLE;
+ gpio_config(&gpioConfig);
+ break;
+ }
+
+ // Set the GPIO reset pin to the value passed in through arg_int.
+ case U8X8_MSG_GPIO_RESET:
+ if (u8g2_esp32_hal.reset != U8G2_ESP32_HAL_UNDEFINED) {
+ gpio_set_level(u8g2_esp32_hal.reset, arg_int);
+ }
+ break;
+ // Set the GPIO client select pin to the value passed in through arg_int.
+ case U8X8_MSG_GPIO_CS:
+ if (u8g2_esp32_hal.cs != U8G2_ESP32_HAL_UNDEFINED) {
+ gpio_set_level(u8g2_esp32_hal.cs, arg_int);
+ }
+ break;
+ // Set the Software I²C pin to the value passed in through arg_int.
+ case U8X8_MSG_GPIO_I2C_CLOCK:
+ if (u8g2_esp32_hal.scl != U8G2_ESP32_HAL_UNDEFINED) {
+ gpio_set_level(u8g2_esp32_hal.scl, arg_int);
+// printf("%c",(arg_int==1?'C':'c'));
+ }
+ break;
+ // Set the Software I²C pin to the value passed in through arg_int.
+ case U8X8_MSG_GPIO_I2C_DATA:
+ if (u8g2_esp32_hal.sda != U8G2_ESP32_HAL_UNDEFINED) {
+ gpio_set_level(u8g2_esp32_hal.sda, arg_int);
+// printf("%c",(arg_int==1?'D':'d'));
+ }
+ break;
+
+ // Delay for the number of milliseconds passed in through arg_int.
+ case U8X8_MSG_DELAY_MILLI:
+ vTaskDelay(arg_int/portTICK_PERIOD_MS);
+ break;
+ }
+ return 0;
+} // u8g2_esp32_gpio_and_delay_cb
--- /dev/null
+/*
+ * u8g2_esp32_hal.h
+ *
+ * Created on: Feb 12, 2017
+ * Author: kolban
+ */
+
+#ifndef U8G2_ESP32_HAL_H_
+#define U8G2_ESP32_HAL_H_
+#include "u8g2.h"
+
+#include "driver/gpio.h"
+#include "driver/spi_master.h"
+#include "driver/i2c.h"
+
+#define U8G2_ESP32_HAL_UNDEFINED GPIO_NUM_NC
+
+#define I2C_MASTER_NUM I2C_NUM_1 // I2C port number for master dev
+#define I2C_MASTER_TX_BUF_DISABLE 0 // I2C master do not need buffer
+#define I2C_MASTER_RX_BUF_DISABLE 0 // I2C master do not need buffer
+#define I2C_MASTER_FREQ_HZ 1200000 // I2C master clock frequency
+#define ACK_CHECK_EN 0x1 // I2C master will check ack from slave
+#define ACK_CHECK_DIS 0x0 // I2C master will not check ack from slave
+
+typedef struct {
+ gpio_num_t clk;
+ gpio_num_t mosi;
+ gpio_num_t sda; // data for I²C
+ gpio_num_t scl; // clock for I²C
+ gpio_num_t cs;
+ gpio_num_t reset;
+ gpio_num_t dc;
+} u8g2_esp32_hal_t ;
+
+#define U8G2_ESP32_HAL_DEFAULT {U8G2_ESP32_HAL_UNDEFINED, U8G2_ESP32_HAL_UNDEFINED, U8G2_ESP32_HAL_UNDEFINED, U8G2_ESP32_HAL_UNDEFINED, U8G2_ESP32_HAL_UNDEFINED, U8G2_ESP32_HAL_UNDEFINED, U8G2_ESP32_HAL_UNDEFINED }
+
+void u8g2_esp32_hal_init(u8g2_esp32_hal_t u8g2_esp32_hal_param);
+uint8_t u8g2_esp32_spi_byte_cb(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
+uint8_t u8g2_esp32_i2c_byte_cb(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
+uint8_t u8g2_esp32_gpio_and_delay_cb(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
+#endif /* U8G2_ESP32_HAL_H_ */