* Makefile, Scripts: new linter * About: remove ID from IC * Firmware: remove double define for DIVC/DIVR * Scripts: check folder names too. Docker: replace syntax check with make lint. * Reformat Sources and Migrate to new file naming convention * Docker: symlink clang-format-12 to clang-format * Add coding style guide
		
			
				
	
	
		
			684 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			684 lines
		
	
	
		
			22 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;
 | 
						|
}
 |