123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347 |
- /*
- Functions for integrating U8glib into the nodemcu platform.
- */
- #include "lauxlib.h"
- #include "platform.h"
- #include "c_stdlib.h"
- #include "u8g.h"
- #include "u8g_glue.h"
- // ------------------------------------------------------------
- // comm functions
- //
- #define I2C_CMD_MODE 0x000
- #define I2C_DATA_MODE 0x040
- #define ESP_I2C_ID 0
- static uint8_t do_i2c_start(uint8_t id, uint8_t sla)
- {
- platform_i2c_send_start( id );
- // ignore return value -> tolerate missing ACK
- platform_i2c_send_address( id, sla, PLATFORM_I2C_DIRECTION_TRANSMITTER );
- return 1;
- }
- static uint8_t u8g_com_esp8266_ssd_start_sequence(struct _lu8g_userdata_t *lu8g)
- {
- /* are we requested to set the a0 state? */
- if ( lu8g->u8g.pin_list[U8G_PI_SET_A0] == 0 )
- return 1;
- /* setup bus, might be a repeated start */
- if ( do_i2c_start( ESP_I2C_ID, lu8g->i2c_addr ) == 0 )
- return 0;
- if ( lu8g->u8g.pin_list[U8G_PI_A0_STATE] == 0 )
- {
- // ignore return value -> tolerate missing ACK
- if ( platform_i2c_send_byte( ESP_I2C_ID, I2C_CMD_MODE ) == 0 )
- ; //return 0;
- }
- else
- {
- platform_i2c_send_byte( ESP_I2C_ID, I2C_DATA_MODE );
- }
- lu8g->u8g.pin_list[U8G_PI_SET_A0] = 0;
- return 1;
- }
- static void lu8g_digital_write( struct _lu8g_userdata_t *lu8g, uint8_t pin_index, uint8_t value )
- {
- uint8_t pin;
- pin = lu8g->u8g.pin_list[pin_index];
- if ( pin != U8G_PIN_NONE )
- platform_gpio_write( pin, value );
- }
- void u8g_Delay(u8g_t *u8g, uint16_t msec)
- {
- struct _lu8g_userdata_t *lu8g = (struct _lu8g_userdata_t *)u8g;
- const uint16_t chunk = 50;
- if (lu8g->use_delay == 0)
- return;
- while (msec > chunk)
- {
- os_delay_us( chunk*1000 );
- msec -= chunk;
- }
- if (msec > 0)
- os_delay_us( msec*1000 );
- }
- void u8g_MicroDelay(void)
- {
- os_delay_us( 1 );
- }
- void u8g_10MicroDelay(void)
- {
- os_delay_us( 10 );
- }
- uint8_t u8g_com_esp8266_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr)
- {
- struct _lu8g_userdata_t *lu8g = (struct _lu8g_userdata_t *)u8g;
- switch(msg)
- {
- case U8G_COM_MSG_STOP:
- break;
-
- case U8G_COM_MSG_INIT:
- // we assume that the SPI interface was already initialized
- // just care for the /CS and D/C pins
- lu8g_digital_write( lu8g, U8G_PI_CS, PLATFORM_GPIO_HIGH );
- platform_gpio_mode( lu8g->u8g.pin_list[U8G_PI_CS], PLATFORM_GPIO_OUTPUT, PLATFORM_GPIO_FLOAT );
- platform_gpio_mode( lu8g->u8g.pin_list[U8G_PI_A0], PLATFORM_GPIO_OUTPUT, PLATFORM_GPIO_FLOAT );
- break;
-
- case U8G_COM_MSG_ADDRESS: /* define cmd (arg_val = 0) or data mode (arg_val = 1) */
- lu8g_digital_write( lu8g, U8G_PI_A0, arg_val == 0 ? PLATFORM_GPIO_LOW : PLATFORM_GPIO_HIGH );
- break;
- case U8G_COM_MSG_CHIP_SELECT:
- if (arg_val == 0)
- {
- /* disable */
- lu8g_digital_write( lu8g, U8G_PI_CS, PLATFORM_GPIO_HIGH );
- }
- else
- {
- /* enable */
- lu8g_digital_write( lu8g, U8G_PI_CS, PLATFORM_GPIO_LOW );
- }
- break;
-
- case U8G_COM_MSG_RESET:
- if ( lu8g->u8g.pin_list[U8G_PI_RESET] != U8G_PIN_NONE )
- lu8g_digital_write( lu8g, U8G_PI_RESET, arg_val == 0 ? PLATFORM_GPIO_LOW : PLATFORM_GPIO_HIGH );
- break;
-
- case U8G_COM_MSG_WRITE_BYTE:
- platform_spi_send( 1, 8, arg_val );
- break;
-
- case U8G_COM_MSG_WRITE_SEQ:
- case U8G_COM_MSG_WRITE_SEQ_P:
- {
- register uint8_t *ptr = arg_ptr;
- while( arg_val > 0 )
- {
- platform_spi_send( 1, 8, *ptr++ );
- arg_val--;
- }
- }
- break;
- }
- return 1;
- }
- uint8_t u8g_com_esp8266_ssd_i2c_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr)
- {
- struct _lu8g_userdata_t *lu8g = (struct _lu8g_userdata_t *)u8g;
- switch(msg)
- {
- case U8G_COM_MSG_INIT:
- // we assume that the i2c bus was already initialized
- //u8g_i2c_init(u8g->pin_list[U8G_PI_I2C_OPTION]);
- break;
-
- case U8G_COM_MSG_STOP:
- break;
- case U8G_COM_MSG_RESET:
- /* Currently disabled, but it could be enable. Previous restrictions have been removed */
- /* u8g_com_arduino_digital_write(u8g, U8G_PI_RESET, arg_val); */
- break;
-
- case U8G_COM_MSG_CHIP_SELECT:
- lu8g->u8g.pin_list[U8G_PI_A0_STATE] = 0;
- lu8g->u8g.pin_list[U8G_PI_SET_A0] = 1; /* force a0 to set again, also forces start condition */
- if ( arg_val == 0 )
- {
- /* disable chip, send stop condition */
- platform_i2c_send_stop( ESP_I2C_ID );
- }
- else
- {
- /* enable, do nothing: any byte writing will trigger the i2c start */
- }
- break;
- case U8G_COM_MSG_WRITE_BYTE:
- //u8g->pin_list[U8G_PI_SET_A0] = 1;
- if ( u8g_com_esp8266_ssd_start_sequence(lu8g) == 0 )
- return platform_i2c_send_stop( ESP_I2C_ID ), 0;
- // ignore return value -> tolerate missing ACK
- if ( platform_i2c_send_byte( ESP_I2C_ID, arg_val) == 0 )
- ; //return platform_i2c_send_stop( ESP_I2C_ID ), 0;
- // platform_i2c_send_stop( ESP_I2C_ID );
- break;
-
- case U8G_COM_MSG_WRITE_SEQ:
- case U8G_COM_MSG_WRITE_SEQ_P:
- //u8g->pin_list[U8G_PI_SET_A0] = 1;
- if ( u8g_com_esp8266_ssd_start_sequence(lu8g) == 0 )
- return platform_i2c_send_stop( ESP_I2C_ID ), 0;
- {
- register uint8_t *ptr = arg_ptr;
- while( arg_val > 0 )
- {
- // ignore return value -> tolerate missing ACK
- if ( platform_i2c_send_byte( ESP_I2C_ID, *ptr++) == 0 )
- ; //return platform_i2c_send_stop( ESP_I2C_ID ), 0;
- arg_val--;
- }
- }
- // platform_i2c_send_stop( ESP_I2C_ID );
- break;
- case U8G_COM_MSG_ADDRESS: /* define cmd (arg_val = 0) or data mode (arg_val = 1) */
- lu8g->u8g.pin_list[U8G_PI_A0_STATE] = arg_val;
- lu8g->u8g.pin_list[U8G_PI_SET_A0] = 1; /* force a0 to set again */
-
- break;
- }
- return 1;
- }
- // ***************************************************************************
- // Generic framebuffer device and RLE comm driver
- //
- uint8_t u8g_dev_gen_fb_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, void *arg)
- {
- switch(msg)
- {
- case U8G_DEV_MSG_PAGE_FIRST:
- // tell comm driver to start new framebuffer
- u8g_SetChipSelect(u8g, dev, 1);
- break;
- case U8G_DEV_MSG_PAGE_NEXT:
- {
- u8g_pb_t *pb = (u8g_pb_t *)(dev->dev_mem);
- if ( u8g_pb_WriteBuffer(pb, u8g, dev) == 0 )
- return 0;
- }
- break;
- }
- return u8g_dev_pb8v1_base_fn(u8g, dev, msg, arg);
- }
- static int bit_at( uint8_t *buf, int line, int x )
- {
- uint8_t byte = buf[x];
- return buf[x] & (1 << line) ? 1 : 0;
- }
- struct _lu8g_fbrle_item
- {
- uint8_t start_x;
- uint8_t len;
- };
- struct _lu8g_fbrle_line
- {
- uint8_t num_valid;
- struct _lu8g_fbrle_item items[0];
- };
- uint8_t u8g_com_esp8266_fbrle_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr)
- {
- struct _lu8g_userdata_t *lud = (struct _lu8g_userdata_t *)u8g;
- switch(msg)
- {
- case U8G_COM_MSG_INIT:
- // allocate memory -> done
- // init buffer
- break;
- case U8G_COM_MSG_CHIP_SELECT:
- if (arg_val == 1) {
- // new frame starts
- if (lud->cb_ref != LUA_NOREF) {
- // fire callback with nil argument
- lua_State *L = lua_getstate();
- lua_rawgeti( L, LUA_REGISTRYINDEX, lud->cb_ref );
- lua_pushnil( L );
- lua_call( L, 1, 0 );
- }
- }
- break;
- case U8G_COM_MSG_WRITE_SEQ:
- case U8G_COM_MSG_WRITE_SEQ_P:
- {
- uint8_t xwidth = u8g->pin_list[U8G_PI_EN];
- size_t fbrle_line_size = sizeof( struct _lu8g_fbrle_line ) + sizeof( struct _lu8g_fbrle_item ) * (xwidth/2);
- int num_lines = arg_val / (xwidth/8);
- uint8_t *buf = (uint8_t *)arg_ptr;
- struct _lu8g_fbrle_line *fbrle_line;
- if (!(fbrle_line = (struct _lu8g_fbrle_line *)c_malloc( fbrle_line_size ))) {
- break;
- }
- for (int line = 0; line < num_lines; line++) {
- int start_run = -1;
- fbrle_line->num_valid = 0;
- for (int x = 0; x < xwidth; x++) {
- if (bit_at( buf, line, x ) == 0) {
- if (start_run >= 0) {
- // inside run, end it and enter result
- fbrle_line->items[fbrle_line->num_valid].start_x = start_run;
- fbrle_line->items[fbrle_line->num_valid++].len = x - start_run;
- //NODE_ERR( " line: %d x: %d len: %d\n", line, start_run, x - start_run );
- start_run = -1;
- }
- } else {
- if (start_run < 0) {
- // outside run, start it
- start_run = x;
- }
- }
- if (fbrle_line->num_valid >= xwidth/2) break;
- }
- // active run?
- if (start_run >= 0 && fbrle_line->num_valid < xwidth/2) {
- fbrle_line->items[fbrle_line->num_valid].start_x = start_run;
- fbrle_line->items[fbrle_line->num_valid++].len = xwidth - start_run;
- }
- // line done, trigger callback
- if (lud->cb_ref != LUA_NOREF) {
- lua_State *L = lua_getstate();
- lua_rawgeti( L, LUA_REGISTRYINDEX, lud->cb_ref );
- lua_pushlstring( L, (const char *)fbrle_line, fbrle_line_size );
- lua_call( L, 1, 0 );
- }
- }
- c_free( fbrle_line );
- }
- break;
- }
- return 1;
- }
|