diff -r 000000000000 -r 88d965579617 components/u8g2/csrc/u8x8_cad.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/components/u8g2/csrc/u8x8_cad.c Tue Oct 08 12:00:31 2019 +0200 @@ -0,0 +1,749 @@ +/* + + u8x8_cad.c + + "command arg data" interface to the graphics controller + + Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/) + + Copyright (c) 2016, olikraus@gmail.com + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list + of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or other + materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + The following sequence must be used for any data, which is set to the display: + + + uint8_t u8x8_cad_StartTransfer(u8x8_t *u8x8) + + any of the following calls + uint8_t u8x8_cad_SendCmd(u8x8_t *u8x8, uint8_t cmd) + uint8_t u8x8_cad_SendArg(u8x8_t *u8x8, uint8_t arg) + uint8_t u8x8_cad_SendData(u8x8_t *u8x8, uint8_t cnt, uint8_t *data) + + uint8_t u8x8_cad_EndTransfer(u8x8_t *u8x8) + + + +*/ +/* +uint8_t u8x8_cad_template(u8x8_t *u8x8, uint8_t msg, uint16_t arg_int, void *arg_ptr) +{ + uint8_t i; + + switch(msg) + { + case U8X8_MSG_CAD_SEND_CMD: + u8x8_mcd_byte_SetDC(mcd->next, 1); + u8x8_mcd_byte_Send(mcd->next, arg_int); + break; + case U8X8_MSG_CAD_SEND_ARG: + u8x8_mcd_byte_SetDC(mcd->next, 1); + u8x8_mcd_byte_Send(mcd->next, arg_int); + break; + case U8X8_MSG_CAD_SEND_DATA: + u8x8_mcd_byte_SetDC(mcd->next, 0); + for( i = 0; i < 8; i++ ) + u8x8_mcd_byte_Send(mcd->next, ((uint8_t *)arg_ptr)[i]); + break; + case U8X8_MSG_CAD_RESET: + return mcd->next->cb(mcd->next, msg, arg_int, arg_ptr); + case U8X8_MSG_CAD_START_TRANSFER: + return mcd->next->cb(mcd->next, msg, arg_int, arg_ptr); + case U8X8_MSG_CAD_END_TRANSFER: + return mcd->next->cb(mcd->next, msg, arg_int, arg_ptr); + default: + break; + } + return 1; +} + +*/ + +#include "u8x8.h" + +uint8_t u8x8_cad_SendCmd(u8x8_t *u8x8, uint8_t cmd) +{ + return u8x8->cad_cb(u8x8, U8X8_MSG_CAD_SEND_CMD, cmd, NULL); +} + +uint8_t u8x8_cad_SendArg(u8x8_t *u8x8, uint8_t arg) +{ + return u8x8->cad_cb(u8x8, U8X8_MSG_CAD_SEND_ARG, arg, NULL); +} + +uint8_t u8x8_cad_SendMultipleArg(u8x8_t *u8x8, uint8_t cnt, uint8_t arg) +{ + while( cnt > 0 ) + { + u8x8->cad_cb(u8x8, U8X8_MSG_CAD_SEND_ARG, arg, NULL); + cnt--; + } + return 1; +} + +uint8_t u8x8_cad_SendData(u8x8_t *u8x8, uint8_t cnt, uint8_t *data) +{ + return u8x8->cad_cb(u8x8, U8X8_MSG_CAD_SEND_DATA, cnt, data); +} + +uint8_t u8x8_cad_StartTransfer(u8x8_t *u8x8) +{ + return u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 0, NULL); +} + +uint8_t u8x8_cad_EndTransfer(u8x8_t *u8x8) +{ + return u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 0, NULL); +} + +void u8x8_cad_vsendf(u8x8_t * u8x8, const char *fmt, va_list va) +{ + uint8_t d; + u8x8_cad_StartTransfer(u8x8); + while( *fmt != '\0' ) + { + d = (uint8_t)va_arg(va, int); + switch(*fmt) + { + case 'a': u8x8_cad_SendArg(u8x8, d); break; + case 'c': u8x8_cad_SendCmd(u8x8, d); break; + case 'd': u8x8_cad_SendData(u8x8, 1, &d); break; + } + fmt++; + } + u8x8_cad_EndTransfer(u8x8); +} + +void u8x8_SendF(u8x8_t * u8x8, const char *fmt, ...) +{ + va_list va; + va_start(va, fmt); + u8x8_cad_vsendf(u8x8, fmt, va); + va_end(va); +} + +/* + 21 c send command c + 22 a send arg a + 23 d send data d + 24 CS on + 25 CS off + 254 milli delay by milliseconds + 255 end of sequence +*/ + +void u8x8_cad_SendSequence(u8x8_t *u8x8, uint8_t const *data) +{ + uint8_t cmd; + uint8_t v; + + for(;;) + { + cmd = *data; + data++; + switch( cmd ) + { + case U8X8_MSG_CAD_SEND_CMD: + case U8X8_MSG_CAD_SEND_ARG: + v = *data; + u8x8->cad_cb(u8x8, cmd, v, NULL); + data++; + break; + case U8X8_MSG_CAD_SEND_DATA: + v = *data; + u8x8_cad_SendData(u8x8, 1, &v); + data++; + break; + case U8X8_MSG_CAD_START_TRANSFER: + case U8X8_MSG_CAD_END_TRANSFER: + u8x8->cad_cb(u8x8, cmd, 0, NULL); + break; + case 0x0fe: + v = *data; + u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_MILLI, v); + data++; + break; + default: + return; + } + } +} + + +uint8_t u8x8_cad_empty(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) +{ + switch(msg) + { + case U8X8_MSG_CAD_SEND_CMD: + u8x8_byte_SendByte(u8x8, arg_int); + break; + case U8X8_MSG_CAD_SEND_ARG: + u8x8_byte_SendByte(u8x8, arg_int); + break; + case U8X8_MSG_CAD_SEND_DATA: + case U8X8_MSG_CAD_INIT: + case U8X8_MSG_CAD_START_TRANSFER: + case U8X8_MSG_CAD_END_TRANSFER: + return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr); + default: + return 0; + } + return 1; +} + + +/* + convert to bytes by using + dc = 1 for commands and args and + dc = 0 for data +*/ +uint8_t u8x8_cad_110(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) +{ + switch(msg) + { + case U8X8_MSG_CAD_SEND_CMD: + u8x8_byte_SetDC(u8x8, 1); + u8x8_byte_SendByte(u8x8, arg_int); + break; + case U8X8_MSG_CAD_SEND_ARG: + u8x8_byte_SetDC(u8x8, 1); + u8x8_byte_SendByte(u8x8, arg_int); + break; + case U8X8_MSG_CAD_SEND_DATA: + u8x8_byte_SetDC(u8x8, 0); + //u8x8_byte_SendBytes(u8x8, arg_int, arg_ptr); + //break; + /* fall through */ + case U8X8_MSG_CAD_INIT: + case U8X8_MSG_CAD_START_TRANSFER: + case U8X8_MSG_CAD_END_TRANSFER: + return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr); + default: + return 0; + } + return 1; +} + +/* + convert to bytes by using + dc = 1 for commands and args and + dc = 0 for data + t6963 +*/ +uint8_t u8x8_cad_100(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) +{ + switch(msg) + { + case U8X8_MSG_CAD_SEND_CMD: + u8x8_byte_SetDC(u8x8, 1); + u8x8_byte_SendByte(u8x8, arg_int); + break; + case U8X8_MSG_CAD_SEND_ARG: + u8x8_byte_SetDC(u8x8, 0); + u8x8_byte_SendByte(u8x8, arg_int); + break; + case U8X8_MSG_CAD_SEND_DATA: + u8x8_byte_SetDC(u8x8, 0); + //u8x8_byte_SendBytes(u8x8, arg_int, arg_ptr); + //break; + /* fall through */ + case U8X8_MSG_CAD_INIT: + case U8X8_MSG_CAD_START_TRANSFER: + case U8X8_MSG_CAD_END_TRANSFER: + return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr); + default: + return 0; + } + return 1; +} + +/* + convert to bytes by using + dc = 0 for commands and args and + dc = 1 for data +*/ +uint8_t u8x8_cad_001(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) +{ + switch(msg) + { + case U8X8_MSG_CAD_SEND_CMD: + u8x8_byte_SetDC(u8x8, 0); + u8x8_byte_SendByte(u8x8, arg_int); + break; + case U8X8_MSG_CAD_SEND_ARG: + u8x8_byte_SetDC(u8x8, 0); + u8x8_byte_SendByte(u8x8, arg_int); + break; + case U8X8_MSG_CAD_SEND_DATA: + u8x8_byte_SetDC(u8x8, 1); + //u8x8_byte_SendBytes(u8x8, arg_int, arg_ptr); + //break; + /* fall through */ + case U8X8_MSG_CAD_INIT: + case U8X8_MSG_CAD_START_TRANSFER: + case U8X8_MSG_CAD_END_TRANSFER: + return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr); + default: + return 0; + } + return 1; +} + +/* + convert to bytes by using + dc = 0 for commands + dc = 1 for args and data +*/ +uint8_t u8x8_cad_011(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) +{ + switch(msg) + { + case U8X8_MSG_CAD_SEND_CMD: + u8x8_byte_SetDC(u8x8, 0); + u8x8_byte_SendByte(u8x8, arg_int); + break; + case U8X8_MSG_CAD_SEND_ARG: + u8x8_byte_SetDC(u8x8, 1); + u8x8_byte_SendByte(u8x8, arg_int); + break; + case U8X8_MSG_CAD_SEND_DATA: + u8x8_byte_SetDC(u8x8, 1); + //u8x8_byte_SendBytes(u8x8, arg_int, arg_ptr); + //break; + /* fall through */ + case U8X8_MSG_CAD_INIT: + case U8X8_MSG_CAD_START_TRANSFER: + case U8X8_MSG_CAD_END_TRANSFER: + return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr); + default: + return 0; + } + return 1; +} + +/* cad procedure for the ST7920 in SPI mode */ +/* u8x8_byte_SetDC is not used */ +uint8_t u8x8_cad_st7920_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) +{ + uint8_t *data; + uint8_t b; + uint8_t i; + static uint8_t buf[16]; + uint8_t *ptr; + + switch(msg) + { + case U8X8_MSG_CAD_SEND_CMD: + u8x8_byte_SendByte(u8x8, 0x0f8); + u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, 1); + u8x8_byte_SendByte(u8x8, arg_int & 0x0f0); + u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, 1); + u8x8_byte_SendByte(u8x8, arg_int << 4); + u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, 1); + break; + case U8X8_MSG_CAD_SEND_ARG: + u8x8_byte_SendByte(u8x8, 0x0f8); + u8x8_byte_SendByte(u8x8, arg_int & 0x0f0); + u8x8_byte_SendByte(u8x8, arg_int << 4); + break; + case U8X8_MSG_CAD_SEND_DATA: + + u8x8_byte_SendByte(u8x8, 0x0fa); + u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, 1); + + /* this loop should be optimized: multiple bytes should be sent */ + /* u8x8_byte_SendBytes(u8x8, arg_int, arg_ptr); */ + data = (uint8_t *)arg_ptr; + + /* the following loop increases speed by 20% */ + while( arg_int >= 8 ) + { + i = 8; + ptr = buf; + do + { + b = *data++; + *ptr++= b & 0x0f0; + b <<= 4; + *ptr++= b; + i--; + } while( i > 0 ); + arg_int -= 8; + u8x8_byte_SendBytes(u8x8, 16, buf); + } + + + while( arg_int > 0 ) + { + b = *data; + u8x8_byte_SendByte(u8x8, b & 0x0f0); + u8x8_byte_SendByte(u8x8, b << 4); + data++; + arg_int--; + } + u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, 1); + break; + case U8X8_MSG_CAD_INIT: + case U8X8_MSG_CAD_START_TRANSFER: + case U8X8_MSG_CAD_END_TRANSFER: + return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr); + default: + return 0; + } + return 1; +} + + +/* cad procedure for the SSD13xx family in I2C mode */ +/* this procedure is also used by the ST7588 */ +/* u8x8_byte_SetDC is not used */ +/* U8X8_MSG_BYTE_START_TRANSFER starts i2c transfer, U8X8_MSG_BYTE_END_TRANSFER stops transfer */ +/* After transfer start, a full byte indicates command or data mode */ + +static void u8x8_i2c_data_transfer(u8x8_t *u8x8, uint8_t arg_int, void *arg_ptr) U8X8_NOINLINE; +static void u8x8_i2c_data_transfer(u8x8_t *u8x8, uint8_t arg_int, void *arg_ptr) +{ + u8x8_byte_StartTransfer(u8x8); + u8x8_byte_SendByte(u8x8, 0x040); + u8x8->byte_cb(u8x8, U8X8_MSG_CAD_SEND_DATA, arg_int, arg_ptr); + u8x8_byte_EndTransfer(u8x8); +} + +/* classic version: will put a start/stop condition around each command and arg */ +uint8_t u8x8_cad_ssd13xx_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) +{ + uint8_t *p; + switch(msg) + { + case U8X8_MSG_CAD_SEND_CMD: + case U8X8_MSG_CAD_SEND_ARG: + /* 7 Nov 2016: Can this be improved? */ + //u8x8_byte_SetDC(u8x8, 0); + u8x8_byte_StartTransfer(u8x8); + //u8x8_byte_SendByte(u8x8, u8x8_GetI2CAddress(u8x8)); + u8x8_byte_SendByte(u8x8, 0x000); + u8x8_byte_SendByte(u8x8, arg_int); + u8x8_byte_EndTransfer(u8x8); + break; + case U8X8_MSG_CAD_SEND_DATA: + //u8x8_byte_SetDC(u8x8, 1); + + /* the FeatherWing OLED with the 32u4 transfer of long byte */ + /* streams was not possible. This is broken down to */ + /* smaller streams, 32 seems to be the limit... */ + /* I guess this is related to the size of the Wire buffers in Arduino */ + /* Unfortunately, this can not be handled in the byte level drivers, */ + /* so this is done here. Even further, only 24 bytes will be sent, */ + /* because there will be another byte (DC) required during the transfer */ + p = arg_ptr; + while( arg_int > 24 ) + { + u8x8_i2c_data_transfer(u8x8, 24, p); + arg_int-=24; + p+=24; + } + u8x8_i2c_data_transfer(u8x8, arg_int, p); + break; + case U8X8_MSG_CAD_INIT: + /* apply default i2c adr if required so that the start transfer msg can use this */ + if ( u8x8->i2c_address == 255 ) + u8x8->i2c_address = 0x078; + return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr); + case U8X8_MSG_CAD_START_TRANSFER: + case U8X8_MSG_CAD_END_TRANSFER: + /* cad transfer commands are ignored */ + break; + default: + return 0; + } + return 1; +} + + +/* fast version with reduced data start/stops, issue 735 */ +uint8_t u8x8_cad_ssd13xx_fast_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) +{ + static uint8_t in_transfer = 0; + uint8_t *p; + switch(msg) + { + case U8X8_MSG_CAD_SEND_CMD: + /* improved version, takeover from ld7032 */ + /* assumes, that the args of a command is not longer than 31 bytes */ + /* speed improvement is about 4% compared to the classic version */ + if ( in_transfer != 0 ) + u8x8_byte_EndTransfer(u8x8); + + u8x8_byte_StartTransfer(u8x8); + u8x8_byte_SendByte(u8x8, 0x000); /* cmd byte for ssd13xx controller */ + u8x8_byte_SendByte(u8x8, arg_int); + in_transfer = 1; + /* lightning version: can replace the improved version from above */ + /* the drawback of the lightning version is this: The complete init sequence */ + /* must fit into the 32 byte Arduino Wire buffer, which might not always be the case */ + /* speed improvement is about 6% compared to the classic version */ + // if ( in_transfer == 0 ) + // { + // u8x8_byte_StartTransfer(u8x8); + // u8x8_byte_SendByte(u8x8, 0x000); /* cmd byte for ssd13xx controller */ + // in_transfer = 1; + // } + //u8x8_byte_SendByte(u8x8, arg_int); + break; + case U8X8_MSG_CAD_SEND_ARG: + u8x8_byte_SendByte(u8x8, arg_int); + break; + case U8X8_MSG_CAD_SEND_DATA: + if ( in_transfer != 0 ) + u8x8_byte_EndTransfer(u8x8); + + + /* the FeatherWing OLED with the 32u4 transfer of long byte */ + /* streams was not possible. This is broken down to */ + /* smaller streams, 32 seems to be the limit... */ + /* I guess this is related to the size of the Wire buffers in Arduino */ + /* Unfortunately, this can not be handled in the byte level drivers, */ + /* so this is done here. Even further, only 24 bytes will be sent, */ + /* because there will be another byte (DC) required during the transfer */ + p = arg_ptr; + while( arg_int > 24 ) + { + u8x8_i2c_data_transfer(u8x8, 24, p); + arg_int-=24; + p+=24; + } + u8x8_i2c_data_transfer(u8x8, arg_int, p); + in_transfer = 0; + break; + case U8X8_MSG_CAD_INIT: + /* apply default i2c adr if required so that the start transfer msg can use this */ + if ( u8x8->i2c_address == 255 ) + u8x8->i2c_address = 0x078; + return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr); + case U8X8_MSG_CAD_START_TRANSFER: + in_transfer = 0; + break; + case U8X8_MSG_CAD_END_TRANSFER: + if ( in_transfer != 0 ) + u8x8_byte_EndTransfer(u8x8); + in_transfer = 0; + break; + default: + return 0; + } + return 1; +} + + + +/* the st75256 i2c driver is a copy of the ssd13xx driver, but with arg=1 */ +/* modified from cad001 (ssd13xx) to cad011 */ +uint8_t u8x8_cad_st75256_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) +{ + uint8_t *p; + switch(msg) + { + case U8X8_MSG_CAD_SEND_CMD: + u8x8_byte_StartTransfer(u8x8); + u8x8_byte_SendByte(u8x8, 0x000); + u8x8_byte_SendByte(u8x8, arg_int); + u8x8_byte_EndTransfer(u8x8); + break; + case U8X8_MSG_CAD_SEND_ARG: + u8x8_byte_StartTransfer(u8x8); + u8x8_byte_SendByte(u8x8, 0x040); + u8x8_byte_SendByte(u8x8, arg_int); + u8x8_byte_EndTransfer(u8x8); + break; + case U8X8_MSG_CAD_SEND_DATA: + /* see ssd13xx driver */ + p = arg_ptr; + while( arg_int > 24 ) + { + u8x8_i2c_data_transfer(u8x8, 24, p); + arg_int-=24; + p+=24; + } + u8x8_i2c_data_transfer(u8x8, arg_int, p); + break; + case U8X8_MSG_CAD_INIT: + /* apply default i2c adr if required so that the start transfer msg can use this */ + if ( u8x8->i2c_address == 255 ) + u8x8->i2c_address = 0x078; /* ST75256, often this is 0x07e */ + return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr); + case U8X8_MSG_CAD_START_TRANSFER: + case U8X8_MSG_CAD_END_TRANSFER: + /* cad transfer commands are ignored */ + break; + default: + return 0; + } + return 1; +} + +/* cad i2c procedure for the ld7032 controller */ +/* Issue https://github.com/olikraus/u8g2/issues/865 mentiones, that I2C does not work */ +/* Workaround is to remove the while loop (or increase the value in the condition) */ +uint8_t u8x8_cad_ld7032_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) +{ + static uint8_t in_transfer = 0; + uint8_t *p; + switch(msg) + { + case U8X8_MSG_CAD_SEND_CMD: + if ( in_transfer != 0 ) + u8x8_byte_EndTransfer(u8x8); + u8x8_byte_StartTransfer(u8x8); + u8x8_byte_SendByte(u8x8, arg_int); + in_transfer = 1; + break; + case U8X8_MSG_CAD_SEND_ARG: + u8x8_byte_SendByte(u8x8, arg_int); + break; + case U8X8_MSG_CAD_SEND_DATA: + //u8x8_byte_SetDC(u8x8, 1); + + /* the FeatherWing OLED with the 32u4 transfer of long byte */ + /* streams was not possible. This is broken down to */ + /* smaller streams, 32 seems to be the limit... */ + /* I guess this is related to the size of the Wire buffers in Arduino */ + /* Unfortunately, this can not be handled in the byte level drivers, */ + /* so this is done here. Even further, only 24 bytes will be sent, */ + /* because there will be another byte (DC) required during the transfer */ + p = arg_ptr; + while( arg_int > 24 ) + { + u8x8->byte_cb(u8x8, U8X8_MSG_CAD_SEND_DATA, 24, p); + arg_int-=24; + p+=24; + u8x8_byte_EndTransfer(u8x8); + u8x8_byte_StartTransfer(u8x8); + u8x8_byte_SendByte(u8x8, 0x08); /* data write for LD7032 */ + } + u8x8->byte_cb(u8x8, U8X8_MSG_CAD_SEND_DATA, arg_int, p); + break; + case U8X8_MSG_CAD_INIT: + /* apply default i2c adr if required so that the start transfer msg can use this */ + if ( u8x8->i2c_address == 255 ) + u8x8->i2c_address = 0x060; + return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr); + case U8X8_MSG_CAD_START_TRANSFER: + in_transfer = 0; + break; + case U8X8_MSG_CAD_END_TRANSFER: + if ( in_transfer != 0 ) + u8x8_byte_EndTransfer(u8x8); + break; + default: + return 0; + } + return 1; +} + +/* cad procedure for the UC16xx family in I2C mode */ +/* u8x8_byte_SetDC is not used */ +/* DC bit is encoded into the adr byte */ +uint8_t u8x8_cad_uc16xx_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) +{ + static uint8_t in_transfer = 0; + static uint8_t is_data = 0; + uint8_t *p; + switch(msg) + { + case U8X8_MSG_CAD_SEND_CMD: + case U8X8_MSG_CAD_SEND_ARG: + if ( in_transfer != 0 ) + { + if ( is_data != 0 ) + { + /* transfer mode is active, but data transfer */ + u8x8_byte_EndTransfer(u8x8); + /* clear the lowest two bits of the adr */ + u8x8_SetI2CAddress( u8x8, u8x8_GetI2CAddress(u8x8)&0x0fc ); + u8x8_byte_StartTransfer(u8x8); + } + } + else + { + /* clear the lowest two bits of the adr */ + u8x8_SetI2CAddress( u8x8, u8x8_GetI2CAddress(u8x8)&0x0fc ); + u8x8_byte_StartTransfer(u8x8); + } + u8x8_byte_SendByte(u8x8, arg_int); + in_transfer = 1; + break; + case U8X8_MSG_CAD_SEND_DATA: + if ( in_transfer != 0 ) + { + if ( is_data == 0 ) + { + /* transfer mode is active, but data transfer */ + u8x8_byte_EndTransfer(u8x8); + /* clear the lowest two bits of the adr */ + u8x8_SetI2CAddress( u8x8, (u8x8_GetI2CAddress(u8x8)&0x0fc)|2 ); + u8x8_byte_StartTransfer(u8x8); + } + } + else + { + /* clear the lowest two bits of the adr */ + u8x8_SetI2CAddress( u8x8, (u8x8_GetI2CAddress(u8x8)&0x0fc)|2 ); + u8x8_byte_StartTransfer(u8x8); + } + in_transfer = 1; + + p = arg_ptr; + while( arg_int > 24 ) + { + u8x8->byte_cb(u8x8, U8X8_MSG_CAD_SEND_DATA, 24, p); + arg_int-=24; + p+=24; + u8x8_byte_EndTransfer(u8x8); + u8x8_byte_StartTransfer(u8x8); + } + u8x8->byte_cb(u8x8, U8X8_MSG_CAD_SEND_DATA, arg_int, p); + + break; + case U8X8_MSG_CAD_INIT: + /* apply default i2c adr if required so that the start transfer msg can use this */ + if ( u8x8->i2c_address == 255 ) + u8x8->i2c_address = 0x070; + return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr); + case U8X8_MSG_CAD_START_TRANSFER: + in_transfer = 0; + /* actual start is delayed, because we do not whether this is data or cmd transfer */ + break; + case U8X8_MSG_CAD_END_TRANSFER: + if ( in_transfer != 0 ) + u8x8_byte_EndTransfer(u8x8); + in_transfer = 0; + break; + default: + return 0; + } + return 1; +}