#include #include #include #include "display.h" #include "lib_i2c.h" /* * GPIO and delay callback for u8g2/u8x8 display driver */ static u8g2_t u8g2; uint8_t u8x8_gpio_and_delay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) { switch(msg) { case U8X8_MSG_GPIO_AND_DELAY_INIT: // called once during init phase of u8g2/u8x8 // can be used to setup pins printf("TODO: U8X8_MSG_GPIO_AND_DELAY_INIT\n"); break; case U8X8_MSG_DELAY_NANO: // delay arg_int * 1 nano second // at 48MHz 1 cycle = 20ns, 1 nop = 1 cycle // the for lopp takes about 2 cycles per iteration for (int i = 0; i < (arg_int/(20*3)); i++) { asm("nop"); } break; case U8X8_MSG_DELAY_100NANO: // delay arg_int * 100 nano seconds // at 48MHz 1 cycle = 20ns, 1 nop = 1 cycle // the for lopp takes about 2 cycles per iteration for (int i = 0; i < ((arg_int*100)/(20*3)); i++) { asm("nop"); } break; case U8X8_MSG_DELAY_10MICRO: // delay arg_int * 10 micro seconds Delay_Us(arg_int*10); break; case U8X8_MSG_DELAY_MILLI: // delay arg_int * 1 milli second Delay_Ms(arg_int); break; case U8X8_MSG_DELAY_I2C: // arg_int is the I2C speed in 100KHz, e.g. 4 = 400 KHz // arg_int=1: delay by 5us, arg_int = 4: delay by 1.25us printf("TODO: U8X8_MSG_DELAY_I2C\n"); break; case U8X8_MSG_GPIO_D0: // D0 or SPI clock pin: Output level in arg_int //case U8X8_MSG_GPIO_SPI_CLOCK: break; case U8X8_MSG_GPIO_D1: // D1 or SPI data pin: Output level in arg_int //case U8X8_MSG_GPIO_SPI_DATA: break; case U8X8_MSG_GPIO_D2: // D2 pin: Output level in arg_int break; case U8X8_MSG_GPIO_D3: // D3 pin: Output level in arg_int break; case U8X8_MSG_GPIO_D4: // D4 pin: Output level in arg_int break; case U8X8_MSG_GPIO_D5: // D5 pin: Output level in arg_int break; case U8X8_MSG_GPIO_D6: // D6 pin: Output level in arg_int break; case U8X8_MSG_GPIO_D7: // D7 pin: Output level in arg_int break; case U8X8_MSG_GPIO_E: // E/WR pin: Output level in arg_int break; case U8X8_MSG_GPIO_CS: // CS (chip select) pin: Output level in arg_int break; case U8X8_MSG_GPIO_DC: // DC (data/cmd, A0, register select) pin: Output level in arg_int break; case U8X8_MSG_GPIO_RESET: funDigitalWrite(PIN_DISP_RST, arg_int); // Reset pin: Output level in arg_int break; case U8X8_MSG_GPIO_CS1: // CS1 (chip select) pin: Output level in arg_int break; case U8X8_MSG_GPIO_CS2: // CS2 (chip select) pin: Output level in arg_int break; case U8X8_MSG_GPIO_I2C_CLOCK: // arg_int=0: Output low at I2C clock pin // arg_int=1: Input dir with pullup high for I2C clock pin break; case U8X8_MSG_GPIO_I2C_DATA: // arg_int=0: Output low at I2C data pin // arg_int=1: Input dir with pullup high for I2C data pin break; case U8X8_MSG_GPIO_MENU_SELECT: // get menu select pin state u8x8_SetGPIOResult(u8x8, 0); break; case U8X8_MSG_GPIO_MENU_NEXT: // get menu next pin state u8x8_SetGPIOResult(u8x8, 0); break; case U8X8_MSG_GPIO_MENU_PREV: // get menu prev pin state u8x8_SetGPIOResult(u8x8, 0); break; case U8X8_MSG_GPIO_MENU_HOME: // get menu home pin state u8x8_SetGPIOResult(u8x8, 0); break; default: // default return value u8x8_SetGPIOResult(u8x8, 1); break; } return 1; } uint8_t u8x8_byte_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) { static uint8_t buffer[32]; static uint8_t buffer_idx; uint8_t *data; switch(msg) { case U8X8_MSG_BYTE_INIT: break; case U8X8_MSG_BYTE_SEND: data = (uint8_t*)arg_ptr; while (arg_int > 0) { buffer[buffer_idx++] = *data; data++; arg_int--; } break; case U8X8_MSG_BYTE_START_TRANSFER: buffer_idx = 0; break; case U8X8_MSG_BYTE_END_TRANSFER: i2c_sendBytes(I2C_TARGET, u8x8_GetI2CAddress(u8x8) >> 1, buffer, buffer_idx); break; default: return 0; } return 1; } u8g2_t* display_init(void) { #if SSD1306_128X32 && SSD1306_128X32 == 1 u8g2_Setup_ssd1306_i2c_128x32_univision_f(&u8g2, U8G2_R0, u8x8_byte_i2c, u8x8_gpio_and_delay); #elif SSD1312_96X16 && SSD1312_96X16 == 1 // NOTE: display size is wrong, hardware is 96x16, but driver is configured for 120x28 u8g2_Setup_ssd1312_i2c_120x28_f(&u8g2, U8G2_R0, u8x8_byte_i2c, u8x8_gpio_and_delay); #endif // TODO: log errors and return NULL on failure u8g2_InitDisplay(&u8g2); u8g2_SetPowerSave(&u8g2, 0); return &u8g2; }