2017-11-18 21:29:57 +01:00
|
|
|
|
2018-07-29 12:43:42 +02:00
|
|
|
// Do not use the code from u8g2 submodule and skip the complete source here
|
|
|
|
// if the u8g2 module is not selected.
|
|
|
|
// Reason: The whole u8g2 submodule code tree might not even exist in this case.
|
|
|
|
#include "user_modules.h"
|
|
|
|
#ifdef LUA_USE_MODULES_U8G2
|
|
|
|
|
2017-11-18 21:29:57 +01:00
|
|
|
#include <string.h>
|
2019-07-21 23:58:21 +02:00
|
|
|
#include <stdlib.h>
|
2017-11-18 21:29:57 +01:00
|
|
|
|
|
|
|
#include "platform.h"
|
2019-07-23 22:22:59 +02:00
|
|
|
#include "user_interface.h"
|
2017-11-18 21:29:57 +01:00
|
|
|
|
|
|
|
#define U8X8_USE_PINS
|
2019-04-28 15:45:04 +02:00
|
|
|
#define U8X8_WITH_USER_PTR
|
2017-11-18 21:29:57 +01:00
|
|
|
#include "u8x8_nodemcu_hal.h"
|
|
|
|
|
2018-11-13 13:18:03 +01:00
|
|
|
// static variables containing info about the i2c link
|
|
|
|
// TODO: move to user space in u8x8_t once available
|
|
|
|
typedef struct {
|
|
|
|
uint8_t id;
|
|
|
|
} hal_i2c_t;
|
|
|
|
|
|
|
|
// static variables containing info about the spi link
|
|
|
|
// TODO: move to user space in u8x8_t once available
|
|
|
|
typedef struct {
|
|
|
|
uint8_t host;
|
|
|
|
//spi_device_handle_t device;
|
|
|
|
uint8_t last_dc;
|
|
|
|
struct {
|
|
|
|
uint8_t *data;
|
|
|
|
size_t size, used;
|
|
|
|
} buffer;
|
|
|
|
} hal_spi_t;
|
|
|
|
|
|
|
|
|
|
|
|
static void flush_buffer_spi( hal_spi_t *hal )
|
|
|
|
{
|
|
|
|
if (hal->buffer.data && hal->buffer.used > 0) {
|
|
|
|
platform_spi_blkwrite( hal->host, hal->buffer.used, hal->buffer.data );
|
|
|
|
|
|
|
|
hal->buffer.used = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void force_flush_buffer(u8x8_t *u8x8)
|
|
|
|
{
|
|
|
|
// spi hal has a buffer that can be flushed
|
|
|
|
if (u8x8->byte_cb == u8x8_byte_nodemcu_spi) {
|
2019-04-28 15:45:04 +02:00
|
|
|
hal_spi_t *hal = u8x8->user_ptr;
|
2018-11-13 13:18:03 +01:00
|
|
|
flush_buffer_spi( hal );
|
|
|
|
}
|
|
|
|
}
|
2017-11-18 21:29:57 +01:00
|
|
|
|
|
|
|
uint8_t u8x8_gpio_and_delay_nodemcu(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
|
|
|
{
|
|
|
|
uint32_t temp;
|
|
|
|
|
|
|
|
switch(msg)
|
|
|
|
{
|
|
|
|
case U8X8_MSG_GPIO_AND_DELAY_INIT: // called once during init phase of u8g2/u8x8
|
|
|
|
// can be used to setup pins
|
|
|
|
for (int idx = 0; idx < U8X8_PIN_OUTPUT_CNT; idx++) {
|
|
|
|
if (u8x8->pins[idx] != U8X8_PIN_NONE) {
|
|
|
|
// configure pin as output
|
|
|
|
if (idx == U8X8_PIN_I2C_CLOCK || idx == U8X8_PIN_I2C_DATA) {
|
|
|
|
platform_gpio_mode( u8x8->pins[idx], PLATFORM_GPIO_OPENDRAIN, PLATFORM_GPIO_PULLUP );
|
|
|
|
} else {
|
|
|
|
platform_gpio_mode( u8x8->pins[idx], PLATFORM_GPIO_OUTPUT, PLATFORM_GPIO_FLOAT );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case U8X8_MSG_DELAY_NANO: // delay arg_int * 1 nano second
|
2018-11-13 13:18:03 +01:00
|
|
|
force_flush_buffer(u8x8);
|
2017-11-18 21:29:57 +01:00
|
|
|
os_delay_us( 1 );
|
2019-02-17 19:26:29 +01:00
|
|
|
break;
|
2017-11-18 21:29:57 +01:00
|
|
|
|
|
|
|
case U8X8_MSG_DELAY_100NANO: // delay arg_int * 100 nano seconds
|
2018-11-13 13:18:03 +01:00
|
|
|
force_flush_buffer(u8x8);
|
2017-11-18 21:29:57 +01:00
|
|
|
temp = arg_int * 100;
|
|
|
|
temp /= 1000;
|
|
|
|
os_delay_us( temp > 0 ? temp : 1 );
|
|
|
|
break;
|
|
|
|
|
|
|
|
case U8X8_MSG_DELAY_10MICRO: // delay arg_int * 10 micro seconds
|
2018-11-13 13:18:03 +01:00
|
|
|
force_flush_buffer(u8x8);
|
2017-11-18 21:29:57 +01:00
|
|
|
os_delay_us( arg_int * 10 );
|
|
|
|
break;
|
|
|
|
|
|
|
|
case U8X8_MSG_DELAY_MILLI: // delay arg_int * 1 milli second
|
2018-11-13 13:18:03 +01:00
|
|
|
force_flush_buffer(u8x8);
|
2017-11-18 21:29:57 +01:00
|
|
|
os_delay_us( arg_int * 1000 );
|
2018-10-07 22:46:56 +02:00
|
|
|
system_soft_wdt_feed();
|
2017-11-18 21:29:57 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case U8X8_MSG_DELAY_I2C: // arg_int is the I2C speed in 100KHz, e.g. 4 = 400 KHz
|
2018-11-13 13:18:03 +01:00
|
|
|
force_flush_buffer(u8x8);
|
2017-11-18 21:29:57 +01:00
|
|
|
temp = 5000 / arg_int; // arg_int=1: delay by 5us, arg_int = 4: delay by 1.25us
|
|
|
|
temp /= 1000;
|
|
|
|
os_delay_us( temp > 0 ? temp : 1 );
|
|
|
|
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
|
|
|
|
platform_gpio_write( u8x8_GetPinValue( u8x8, msg ), arg_int );
|
|
|
|
break;
|
|
|
|
case U8X8_MSG_GPIO_DC: // DC (data/cmd, A0, register select) pin: Output level in arg_int
|
|
|
|
platform_gpio_write( u8x8_GetPinValue( u8x8, msg ), arg_int );
|
|
|
|
break;
|
|
|
|
case U8X8_MSG_GPIO_RESET: // Reset pin: Output level in arg_int
|
|
|
|
if (u8x8_GetPinValue( u8x8, msg ) != U8X8_PIN_NONE)
|
|
|
|
platform_gpio_write( u8x8_GetPinValue(u8x8, msg), 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
|
|
|
|
// for SW comm routine
|
|
|
|
platform_gpio_write( u8x8_GetPinValue( u8x8, msg ), arg_int );
|
|
|
|
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
|
|
|
|
// for SW comm routine
|
|
|
|
platform_gpio_write( u8x8_GetPinValue( u8x8, msg ), arg_int );
|
|
|
|
break;
|
|
|
|
|
|
|
|
case U8X8_MSG_GPIO_MENU_SELECT:
|
|
|
|
case U8X8_MSG_GPIO_MENU_NEXT:
|
|
|
|
case U8X8_MSG_GPIO_MENU_PREV:
|
|
|
|
case U8X8_MSG_GPIO_MENU_HOME:
|
|
|
|
u8x8_SetGPIOResult( u8x8, /* get menu select pin state */ 0 );
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
u8x8_SetGPIOResult( u8x8, 1 ); // default return value
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t u8x8_byte_nodemcu_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
|
|
|
{
|
|
|
|
uint8_t *data;
|
2019-04-28 15:45:04 +02:00
|
|
|
hal_i2c_t *hal = u8x8->user_ptr;
|
2019-02-17 19:26:29 +01:00
|
|
|
|
2017-11-18 21:29:57 +01:00
|
|
|
switch(msg) {
|
|
|
|
case U8X8_MSG_BYTE_SEND:
|
2018-10-20 10:29:29 +02:00
|
|
|
if (hal->id < NUM_I2C) {
|
2017-11-18 21:29:57 +01:00
|
|
|
data = (uint8_t *)arg_ptr;
|
2019-02-17 19:26:29 +01:00
|
|
|
|
2017-11-18 21:29:57 +01:00
|
|
|
while( arg_int > 0 ) {
|
2018-10-20 10:29:29 +02:00
|
|
|
platform_i2c_send_byte( hal->id, *data );
|
2017-11-18 21:29:57 +01:00
|
|
|
data++;
|
|
|
|
arg_int--;
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
// invalid id
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case U8X8_MSG_BYTE_INIT:
|
|
|
|
{
|
2019-04-28 15:45:04 +02:00
|
|
|
// the user pointer initially contains the i2c id
|
2017-11-18 21:29:57 +01:00
|
|
|
int id = (int)hal;
|
2019-07-21 23:58:21 +02:00
|
|
|
if (!(hal = malloc( sizeof ( hal_i2c_t ) )))
|
2017-11-18 21:29:57 +01:00
|
|
|
return 0;
|
|
|
|
hal->id = id;
|
2019-04-28 15:45:04 +02:00
|
|
|
u8x8->user_ptr = hal;
|
2017-11-18 21:29:57 +01:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case U8X8_MSG_BYTE_SET_DC:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case U8X8_MSG_BYTE_START_TRANSFER:
|
2018-10-20 10:29:29 +02:00
|
|
|
if (hal->id < NUM_I2C) {
|
|
|
|
platform_i2c_send_start( hal->id );
|
|
|
|
platform_i2c_send_address( hal->id, u8x8_GetI2CAddress(u8x8), PLATFORM_I2C_DIRECTION_TRANSMITTER );
|
2017-11-18 21:29:57 +01:00
|
|
|
|
|
|
|
} else {
|
|
|
|
// invalid id
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case U8X8_MSG_BYTE_END_TRANSFER:
|
2018-10-20 10:29:29 +02:00
|
|
|
if (hal->id < NUM_I2C) {
|
|
|
|
platform_i2c_send_stop( hal->id );
|
2017-11-18 21:29:57 +01:00
|
|
|
|
|
|
|
} else {
|
|
|
|
// invalid id
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t u8x8_byte_nodemcu_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
|
|
|
{
|
2019-04-28 15:45:04 +02:00
|
|
|
hal_spi_t *hal = u8x8->user_ptr;
|
2019-02-17 19:26:29 +01:00
|
|
|
|
2017-11-18 21:29:57 +01:00
|
|
|
switch(msg) {
|
|
|
|
case U8X8_MSG_BYTE_INIT:
|
|
|
|
{
|
|
|
|
/* disable chipselect */
|
|
|
|
u8x8_gpio_SetCS( u8x8, u8x8->display_info->chip_disable_level );
|
|
|
|
|
2019-04-28 15:45:04 +02:00
|
|
|
// the user pointer initially contains the spi host id
|
2017-11-18 21:29:57 +01:00
|
|
|
int host = (int)hal;
|
2019-07-21 23:58:21 +02:00
|
|
|
if (!(hal = malloc( sizeof ( hal_spi_t ) )))
|
2017-11-18 21:29:57 +01:00
|
|
|
return 0;
|
|
|
|
hal->host = host;
|
2019-04-28 15:45:04 +02:00
|
|
|
u8x8->user_ptr = hal;
|
2018-11-13 13:18:03 +01:00
|
|
|
hal->buffer.data = NULL;
|
2017-11-18 21:29:57 +01:00
|
|
|
|
|
|
|
hal->last_dc = 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case U8X8_MSG_BYTE_SET_DC:
|
|
|
|
if (hal->last_dc != arg_int)
|
|
|
|
flush_buffer_spi( hal );
|
|
|
|
|
|
|
|
u8x8_gpio_SetDC( u8x8, arg_int );
|
|
|
|
hal->last_dc = arg_int;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case U8X8_MSG_BYTE_START_TRANSFER:
|
|
|
|
hal->buffer.size = 256;
|
2019-07-21 23:58:21 +02:00
|
|
|
if (!(hal->buffer.data = (uint8_t *)malloc( hal->buffer.size )))
|
2017-11-18 21:29:57 +01:00
|
|
|
return 0;
|
|
|
|
hal->buffer.used = 0;
|
|
|
|
|
|
|
|
u8x8_gpio_SetCS( u8x8, u8x8->display_info->chip_enable_level );
|
|
|
|
break;
|
|
|
|
|
|
|
|
case U8X8_MSG_BYTE_SEND:
|
|
|
|
if (!hal->buffer.data)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
while (hal->buffer.size - hal->buffer.used < arg_int) {
|
|
|
|
hal->buffer.size *= 2;
|
|
|
|
uint8_t *tmp;
|
2019-07-21 23:58:21 +02:00
|
|
|
if (!(tmp = (uint8_t *)malloc( hal->buffer.size ))) {
|
|
|
|
free( hal->buffer.data );
|
2017-11-18 21:29:57 +01:00
|
|
|
hal->buffer.data = NULL;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
os_memcpy( tmp, hal->buffer.data, hal->buffer.used );
|
2019-07-21 23:58:21 +02:00
|
|
|
free( hal->buffer.data );
|
2017-11-18 21:29:57 +01:00
|
|
|
hal->buffer.data = tmp;
|
|
|
|
}
|
|
|
|
os_memcpy( hal->buffer.data + hal->buffer.used, arg_ptr, arg_int );
|
|
|
|
hal->buffer.used += arg_int;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case U8X8_MSG_BYTE_END_TRANSFER:
|
|
|
|
if (!hal->buffer.data)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
flush_buffer_spi( hal );
|
|
|
|
|
|
|
|
u8x8_gpio_SetCS( u8x8, u8x8->display_info->chip_disable_level );
|
|
|
|
|
2019-07-21 23:58:21 +02:00
|
|
|
free( hal->buffer.data );
|
2018-11-13 13:18:03 +01:00
|
|
|
hal->buffer.data = NULL;
|
2017-11-18 21:29:57 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
2018-07-29 12:43:42 +02:00
|
|
|
|
|
|
|
#endif /* LUA_USE_MODULES_U8G2 */
|