i2c test and display
This commit is contained in:
parent
9e254e0fb1
commit
dae0fbcbda
9 changed files with 552 additions and 14 deletions
174
fw/display.c
Normal file
174
fw/display.c
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
#include <u8g2.h>
|
||||
#include <ch32fun.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue