components/u8g2/csrc/u8x8_cad.c

changeset 0
88d965579617
--- /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;
+}

mercurial