* add u8g2 and ui libs * add display driver and usage example * not init display in test mode * change todo text * fix removed code * Target f2 (#107) * add ioc for flipperzero f2 * add generated f1 files to f2 * regenerate cubemx * invert initial state of led * blink backligh * shutdown backlight on idle
		
			
				
	
	
		
			750 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			750 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
  
 | 
						|
  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;
 | 
						|
}
 |