From 014d1ca0dbb55a9549ab46a0368edb1c6c918f88 Mon Sep 17 00:00:00 2001 From: jaenrig-ifx Date: Mon, 7 Jun 2021 08:51:50 +0200 Subject: [PATCH] Removed previous example project folder --- TLD5542-1LED_DRV_V1.02/BitBang_I2C.cpp | 1108 ------ TLD5542-1LED_DRV_V1.02/BitBang_I2C.h | 108 - TLD5542-1LED_DRV_V1.02/OneBitDisplay.cpp | 3469 ----------------- TLD5542-1LED_DRV_V1.02/OneBitDisplay.h | 358 -- .../TLD5542-1LED_DRV_V1.02.ino | 818 ---- .../TLD5542_1_Func_Layer.cpp | 376 -- TLD5542-1LED_DRV_V1.02/TLD5542_1_Func_Layer.h | 104 - .../TLD5542_1_Reg_Layer.cpp | 750 ---- TLD5542-1LED_DRV_V1.02/TLD5542_1_Reg_Layer.h | 470 --- 9 files changed, 7561 deletions(-) delete mode 100755 TLD5542-1LED_DRV_V1.02/BitBang_I2C.cpp delete mode 100755 TLD5542-1LED_DRV_V1.02/BitBang_I2C.h delete mode 100755 TLD5542-1LED_DRV_V1.02/OneBitDisplay.cpp delete mode 100755 TLD5542-1LED_DRV_V1.02/OneBitDisplay.h delete mode 100755 TLD5542-1LED_DRV_V1.02/TLD5542-1LED_DRV_V1.02.ino delete mode 100755 TLD5542-1LED_DRV_V1.02/TLD5542_1_Func_Layer.cpp delete mode 100755 TLD5542-1LED_DRV_V1.02/TLD5542_1_Func_Layer.h delete mode 100755 TLD5542-1LED_DRV_V1.02/TLD5542_1_Reg_Layer.cpp delete mode 100755 TLD5542-1LED_DRV_V1.02/TLD5542_1_Reg_Layer.h diff --git a/TLD5542-1LED_DRV_V1.02/BitBang_I2C.cpp b/TLD5542-1LED_DRV_V1.02/BitBang_I2C.cpp deleted file mode 100755 index cdbe1f7..0000000 --- a/TLD5542-1LED_DRV_V1.02/BitBang_I2C.cpp +++ /dev/null @@ -1,1108 +0,0 @@ -// -// Bit Bang I2C library -// Copyright (c) 2018-2019 BitBank Software, Inc. -// Written by Larry Bank (bitbank@pobox.com) -// Project started 10/12/2018 -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -#ifdef _LINUX_ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#define PROGMEM -#define false 0 -#define true 1 -#define memcpy_P memcpy -#define INPUT 1 -#define OUTPUT 2 - -// maps RPI pins to BCM GPIO numbers -const int iRPIPins[] = {-1,-1,-1,2,-1,3,-1,4,14,-1, - 15,17,18,27,-1,22,23,-1,24,10, - -1,9,25,11,8,-1,7,0,1,5, - -1,6,12,13,-1,19,16,26,20,-1, - 21}; - -#else // Arduino -#include -#ifndef __AVR_ATtiny85__ -#include -#endif -#ifdef W600_EV -#include -#define VARIANT_MCK 80000000ul -#endif -#endif // _LINUX_ -#include "BitBang_I2C.h" -//static int iSCL, iSDA; // keep requested pin numbers in private statics -//static int iDelay; // bit delay in ms for the requested clock rate -#if defined ( __AVR__ ) && !defined( ARDUINO_ARCH_MEGAAVR ) -volatile uint8_t *iDDR_SCL, *iPort_SCL_Out; -volatile uint8_t *iDDR_SDA, *iPort_SDA_In, *iPort_SDA_Out; -uint8_t iSDABit, iSCLBit; -#endif -#ifdef FUTURE -//#else // must be a 32-bit MCU -volatile uint32_t *iDDR_SCL, *iPort_SCL_Out; -volatile uint32_t *iDDR_SDA, *iPort_SDA_In, *iPort_SDA_Out; -uint32_t iSDABit, iSCLBit; -#endif - -#if defined ( __AVR__ ) && !defined( ARDUINO_ARCH_MEGAAVR ) -uint8_t getPinInfo(uint8_t pin, volatile uint8_t **iDDR, volatile uint8_t **iPort, int bInput) -{ - uint8_t port, bit; - - port = (pin & 0xf0); // hex port (A,B,D,E,F) - bit = pin & 0x7; - switch (port) - { -#ifdef PORTE - case 0xE0: - *iPort = (bInput) ? &PINE : &PORTE; - *iDDR = &DDRE; - break; -#endif -#ifdef PORTF - case 0xF0: - *iPort = (bInput) ? &PINF : &PORTF; - *iDDR = &DDRF; - break; -#endif -#ifdef PORTG - case 0xA0: // really port G - *iPort = (bInput) ? &PING : &PORTG; - *iDDR = &DDRG; - break; -#endif -#ifdef PORTC - case 0xC0: - *iPort = (bInput) ? &PINC : &PORTC; - *iDDR = &DDRC; - break; -#endif -#ifdef PORTB - case 0xB0: - *iPort = (bInput) ? &PINB : &PORTB; - *iDDR = &DDRB; - break; -#endif -#ifdef PORTD - case 0xD0: - *iPort = (bInput) ? &PIND : &PORTD; - *iDDR = &DDRD; - break; -#endif - } - return bit; -} /* getPinInfo() */ -#endif - -//#else // 32-bit version -#ifdef FUTURE -uint32_t getPinInfo(uint8_t pin, volatile uint32_t **iDDR, volatile uint32_t **iPort, int bInput) -{ - uint32_t port, bit; - - if (pin <= 0xbf) // port 0 - { - *iPort = (bInput) ? ®_PORT_IN0 : ®_PORT_OUT0; - *iDDR = ®_PORT_DIR0; - } - else if (pin <= 0xdf) // port 1 - { - *iPort = (bInput) ? ®_PORT_IN1 : ®_PORT_OUT1; - *iDDR = ®_PORT_DIR1; - } - else return 0xffffffff; // invalid - bit = pin & 0x1f; - return bit; -} /* getPinInfo() */ -#endif // __AVR__ - -inline uint8_t SDA_READ(uint8_t iSDA) -{ -#if defined ( __AVR__ ) && !defined( ARDUINO_ARCH_MEGAAVR ) - if (iSDA >= 0xa0) // direct pin numbering - { - if (*iPort_SDA_In & iSDABit) - return HIGH; - else - return LOW; - } - else -#endif - { -#ifndef __AVR_ATtiny85__ -#ifdef W600_EV - return w600DigitalRead(iSDA); -#else -#ifdef _LINUX_ - return gpioRead(iSDA); -#else - return digitalRead(iSDA); -#endif // _LINUX -#endif -#endif - } - return 0; // fall through? -} -inline void SCL_HIGH(uint8_t iSCL) -{ -#if defined ( __AVR__ ) && !defined( ARDUINO_ARCH_MEGAAVR ) - if (iSCL >= 0xa0) // direct pin numbering - { - *iDDR_SCL &= ~iSCLBit; - } - else -#endif - { -#ifndef __AVR_ATtiny85__ -#ifdef W600_EV - w600PinMode(iSCL, GPIO_INPUT); -#else -#ifdef _LINUX_ - gpioSetMode(iSCL, PI_INPUT); -#else - pinMode(iSCL, INPUT); -#endif // _LINUX_ -#endif -#endif - } -} - -inline void SCL_LOW(uint8_t iSCL) -{ -#if defined ( __AVR__ ) && !defined( ARDUINO_ARCH_MEGAAVR ) - if (iSCL >= 0xa0) // direct pin numbering - { - *iDDR_SCL |= iSCLBit; - } - else -#endif - { -#ifndef __AVR_ATtiny85__ -#ifdef W600_EV - w600PinMode(iSCL, GPIO_OUTPUT); - w600DigitalWrite(iSCL, LOW); -#else -#ifdef _LINUX_ - gpioSetMode(iSCL, PI_OUTPUT); -#else - pinMode(iSCL, OUTPUT); -#endif // _LINUX_ -#endif -#endif - } -} - -inline void SDA_HIGH(uint8_t iSDA) -{ -#if defined ( __AVR__ ) && !defined( ARDUINO_ARCH_MEGAAVR ) - if (iSDA >= 0xa0) // direct pin numbering - { - *iDDR_SDA &= ~iSDABit; - } - else -#endif - { -#ifndef __AVR_ATtiny85__ -#ifdef W600_EV - w600PinMode(iSDA, GPIO_INPUT); -#else -#ifdef _LINUX_ - gpioSetMode(iSDA, PI_INPUT); -#else - pinMode(iSDA, INPUT); -#endif // _LINUX_ -#endif -#endif - } -} - -inline void SDA_LOW(uint8_t iSDA) -{ -#if defined ( __AVR__ ) && !defined( ARDUINO_ARCH_MEGAAVR ) - if (iSDA >= 0xa0) // direct pin numbering - { - *iDDR_SDA |= iSDABit; - } - else -#endif - { -#ifndef __AVR_ATtiny85__ -#ifdef W600_EV - w600PinMode(iSDA, GPIO_OUTPUT); - w600DigitalWrite(iSDA, LOW); -#else -#ifdef _LINUX_ - gpioSetMode(iSDA, PI_OUTPUT); -#else - pinMode(iSDA, OUTPUT); -#endif // _LINUX_ -#endif -#endif - } -} - -void inline sleep_us(int iDelay) -{ -#ifdef __AVR_ATtiny85__ - iDelay *= 2; - while (iDelay) - { - __asm__ __volatile__ ( - "nop" "\n\t" - "nop"); //just waiting 2 cycle - iDelay--; - } -#else - if (iDelay > 0) -#ifdef _LINUX_ - gpioDelay(iDelay); -#else - delayMicroseconds(iDelay); -#endif // _LINUX -#endif -} -#ifndef __AVR_ATtiny85__ -// Transmit a byte and read the ack bit -// if we get a NACK (negative acknowledge) return 0 -// otherwise return 1 for success -// -static inline int i2cByteOut(BBI2C *pI2C, uint8_t b) -{ -uint8_t i, ack; -uint8_t iSDA = pI2C->iSDA; -uint8_t iSCL = pI2C->iSCL; // in case of bad C compiler -int iDelay = pI2C->iDelay; - - for (i=0; i<8; i++) - { - if (b & 0x80) - SDA_HIGH(iSDA); // set data line to 1 - else - SDA_LOW(iSDA); // set data line to 0 - SCL_HIGH(iSCL); // clock high (slave latches data) - sleep_us(iDelay); - SCL_LOW(iSCL); // clock low - b <<= 1; - sleep_us(iDelay); - } // for i -// read ack bit - SDA_HIGH(iSDA); // set data line for reading - SCL_HIGH(iSCL); // clock line high - sleep_us(iDelay); // DEBUG - delay/2 - ack = SDA_READ(iSDA); - SCL_LOW(iSCL); // clock low - sleep_us(iDelay); // DEBUG - delay/2 - SDA_LOW(iSDA); // data low - return (ack == 0) ? 1:0; // a low ACK bit means success -} /* i2cByteOut() */ -#endif - -#if defined ( __AVR__ ) && !defined( ARDUINO_ARCH_MEGAAVR ) -#define SDA_LOW_AVR *iDDR_sda |= sdabit; -#define SDA_HIGH_AVR *iDDR_sda &= ~sdabit; -#define SCL_LOW_AVR *iDDR_scl |= sclbit; -#define SCL_HIGH_AVR *iDDR_scl &= ~sclbit; -#define SDA_READ_AVR (*iPort_SDA_In & sdabit) -static inline int i2cByteOutAVR(BBI2C *pI2C, uint8_t b) -{ -uint8_t i, ack; -uint8_t *iDDR_sda = (uint8_t *)iDDR_SDA; // Put in local variables to avoid reading -uint8_t *iDDR_scl = (uint8_t *)iDDR_SCL; // from volatile pointer vars each time -uint8_t sdabit = iSDABit; -uint8_t sclbit = iSCLBit; - - for (i=0; i<8; i++) - { - if (b & 0x80) - SDA_HIGH_AVR // set data line to 1 - else - SDA_LOW_AVR // set data line to 0 - SCL_HIGH_AVR // clock high (slave latches data) - sleep_us(pI2C->iDelay); - SCL_LOW_AVR // clock low - b <<= 1; - } // for i -// read ack bit - SDA_HIGH_AVR // set data line for reading - SCL_HIGH_AVR // clock line high -// sleep_us(iDelay); // DEBUG - delay/2 - ack = SDA_READ_AVR; - SCL_LOW_AVR // clock low -// sleep_us(iDelay); // DEBUG - delay/2 - SDA_LOW_AVR // data low - return (ack == 0) ? 1:0; // a low ACK bit means success -} /* i2cByteOutAVR() */ - -#define BOTH_LOW_FAST *iDDR = both_low; -#define BOTH_HIGH_FAST *iDDR = both_high; -#define SCL_HIGH_FAST *iDDR = scl_high; -#define SDA_HIGH_FAST *iDDR = sda_high; -#define SDA_READ_FAST *iDDR & iSDABit; -static inline int i2cByteOutAVRFast(BBI2C *pI2C, uint8_t b) -{ -uint8_t i, ack; -uint8_t *iDDR = (uint8_t *)iDDR_SDA; // Put in local variables to avoid reading -uint8_t bOld = *iDDR; // current value -uint8_t both_low = bOld | iSDABit | iSCLBit; -uint8_t both_high = bOld & ~(iSDABit | iSCLBit); -uint8_t scl_high = (bOld | iSDABit) & ~iSCLBit; -uint8_t sda_high = (bOld | iSCLBit) & ~iSDABit; - - BOTH_LOW_FAST // start with both lines set to 0 - for (i=0; i<8; i++) - { - if (b & 0x80) - { - SDA_HIGH_FAST // set data line to 1 - sleep_us(pI2C->iDelay); - BOTH_HIGH_FAST // rising edge clocks data - } - else // more probable case (0) = shortest code path - { - SCL_HIGH_FAST // clock high (slave latches data) - } - sleep_us(pI2C->iDelay); - BOTH_LOW_FAST // clock low - b <<= 1; - } // for i -// read ack bit - SDA_HIGH_FAST // set data line for reading - BOTH_HIGH_FAST // clock line high - sleep_us(pI2C->iDelay); // DEBUG - delay/2 - ack = SDA_READ_FAST; - BOTH_LOW_FAST // clock low -// sleep_us(pI2C->iDelay); // DEBUG - delay/2 -// SDA_LOW_AVR // data low - return (ack == 0) ? 1:0; // a low ACK bit means success -} /* i2cByteOutAVR() */ -#endif // __AVR__ - -#ifndef __AVR_ATtiny85__ -static inline int i2cByteOutFast(BBI2C *pI2C, uint8_t b) -{ -uint8_t i, ack, iSDA, iSCL; -int iDelay; - - iSDA = pI2C->iSDA; - iSCL = pI2C->iSCL; - iDelay = pI2C->iDelay; - - if (b & 0x80) - SDA_HIGH(iSDA); // set data line to 1 - else - SDA_LOW(iSDA); // set data line to 0 - for (i=0; i<8; i++) - { - SCL_HIGH(iSCL); // clock high (slave latches data) - sleep_us(iDelay); - SCL_LOW(iSCL); // clock low - sleep_us(iDelay); - } // for i -// read ack bit - SDA_HIGH(iSDA); // set data line for reading - SCL_HIGH(iSCL); // clock line high - sleep_us(pI2C->iDelay); // DEBUG - delay/2 - ack = SDA_READ(iSDA); - SCL_LOW(iSCL); // clock low - sleep_us(pI2C->iDelay); // DEBUG - delay/2 - SDA_LOW(iSDA); // data low - return (ack == 0) ? 1:0; // a low ACK bit means success -} /* i2cByteOutFast() */ -#endif - -// -// Receive a byte and read the ack bit -// if we get a NACK (negative acknowledge) return 0 -// otherwise return 1 for success -// -static inline uint8_t i2cByteIn(BBI2C *pI2C, uint8_t bLast) -{ -uint8_t i; -uint8_t b = 0; - - SDA_HIGH(pI2C->iSDA); // set data line as input - for (i=0; i<8; i++) - { - sleep_us(pI2C->iDelay); // wait for data to settle - SCL_HIGH(pI2C->iSCL); // clock high (slave latches data) - b <<= 1; - if (SDA_READ(pI2C->iSDA) != 0) // read the data bit - b |= 1; // set data bit - SCL_LOW(pI2C->iSCL); // cloc low - } // for i - if (bLast) - { - SDA_HIGH(pI2C->iSDA); - } // last byte sends a NACK} - else - SDA_LOW(pI2C->iSDA); - SCL_HIGH(pI2C->iSCL); // clock high - sleep_us(pI2C->iDelay); - SCL_LOW(pI2C->iSCL); // clock low to send ack - sleep_us(pI2C->iDelay); - SDA_LOW(pI2C->iSDA); // data low - return b; -} /* i2cByteIn() */ - -// -// Send I2C STOP condition -// -static inline void i2cEnd(BBI2C *pI2C) -{ - SDA_LOW(pI2C->iSDA); // data line low - sleep_us(pI2C->iDelay); - SCL_HIGH(pI2C->iSCL); // clock high - sleep_us(pI2C->iDelay); - SDA_HIGH(pI2C->iSDA); // data high - sleep_us(pI2C->iDelay); -} /* i2cEnd() */ - - -static inline int i2cBegin(BBI2C *pI2C, uint8_t addr, uint8_t bRead) -{ - int rc; - SDA_LOW(pI2C->iSDA); // data line low first - sleep_us(pI2C->iDelay); - SCL_LOW(pI2C->iSCL); // then clock line low is a START signal - addr <<= 1; - if (bRead) - addr++; // set read bit -#ifdef __AVR_ATtiny85__ - rc = i2cByteOutAVR(pI2C, addr); -#else - rc = i2cByteOut(pI2C, addr); // send the slave address and R/W bit -#endif - return rc; -} /* i2cBegin() */ - - -static inline int i2cWrite(BBI2C *pI2C, uint8_t *pData, int iLen) -{ -uint8_t b; -int rc, iOldLen = iLen; - - rc = 1; - while (iLen && rc == 1) - { - b = *pData++; -#ifdef __AVR_ATtiny85__ - rc = i2cByteOutAVRFast(pI2C, b); -#else -#if defined ( __AVR__ ) && !defined( ARDUINO_ARCH_MEGAAVR ) - if (pI2C->iSDA >= 0xa0) - { - rc = i2cByteOutAVRFast(pI2C, b); - } - else -#endif - { - if (b == 0xff || b == 0) - rc = i2cByteOutFast(pI2C, b); // speed it up a bit more if all bits are == - else - rc = i2cByteOut(pI2C, b); - } -#endif - if (rc == 1) // success - iLen--; - } // for each byte - return (rc == 1) ? (iOldLen - iLen) : 0; // 0 indicates bad ack from sending a byte -} /* i2cWrite() */ - -static inline void i2cRead(BBI2C *pI2C, uint8_t *pData, int iLen) -{ - while (iLen--) - { - *pData++ = i2cByteIn(pI2C, iLen == 0); - } // for each byte -} /* i2cRead() */ -// -// Initialize the I2C BitBang library -// Pass the pin numbers used for SDA and SCL -// as well as the clock rate in Hz -// -void I2CInit(BBI2C *pI2C, uint32_t iClock) -{ -#ifdef _LINUX_ - if (gpioInitialise() < 0) - { - printf("pigpio failed to initialize\n"); - return; - } -#endif - if (pI2C == NULL) return; - - if (pI2C->bWire) // use Wire library - { -#if !defined( _LINUX_ ) && !defined( __AVR_ATtiny85__ ) -#if defined(TEENSYDUINO) || defined( __AVR__ ) || defined( NRF52 ) || defined ( ARDUINO_ARCH_NRF52840 ) - Wire.begin(); -#else - if (pI2C->iSDA == 0xff || pI2C->iSCL == 0xff) - Wire.begin(); - else - Wire.begin(pI2C->iSDA, pI2C->iSCL); -#endif - Wire.setClock(iClock); -#endif -#ifdef _LINUX_ - { - char filename[32]; - sprintf(filename, "/dev/i2c-%d", pI2C->iBus); - if ((pI2C->file_i2c = open(filename, O_RDWR)) < 0) - return; - } -#endif // _LINUX_ - return; - } - if (pI2C->iSDA < 0xa0) - { -#if !defined ( __AVR_ATtiny85__ ) && !defined( _LINUX_ ) -#ifdef W600_EV - w600PinMode(pI2C->iSDA, GPIO_OUTPUT); - w600PinMode(pI2C->iSCL, GPIO_OUTPUT); - w600DigitalWrite(pI2C->iSDA, LOW); // setting low = enabling as outputs - w600DigitalWrite(pI2C->iSCL, LOW); - w600PinMode(pI2C->iSDA, GPIO_INPUT); // let the lines float (tri-state) - w600PinMode(pI2C->iSCL, GPIO_INPUT); -#else // generic - pinMode(pI2C->iSDA, OUTPUT); - pinMode(pI2C->iSCL, OUTPUT); - digitalWrite(pI2C->iSDA, LOW); // setting low = enabling as outputs - digitalWrite(pI2C->iSCL, LOW); - pinMode(pI2C->iSDA, INPUT); // let the lines float (tri-state) - pinMode(pI2C->iSCL, INPUT); -#endif -#endif -#ifdef _LINUX_ - // use PIGPIO - // convert pin numbers to BCM numbers for PIGPIO - pI2C->iSDA = iRPIPins[pI2C->iSDA]; - pI2C->iSCL = iRPIPins[pI2C->iSCL]; - gpioWrite(pI2C->iSDA, 0); - gpioWrite(pI2C->iSCL, 0); - gpioSetMode(pI2C->iSDA, PI_INPUT); -// gpioSetPullUpDown(pI2C->iSDA, PI_PUD_UP); - gpioSetMode(pI2C->iSCL, PI_INPUT); -// gpioSetPullUpDown(pI2C->iSCL, PI_PUD_UP); -#endif // _LINUX_ - } -#if defined ( __AVR__ ) && !defined( ARDUINO_ARCH_MEGAAVR ) - else // direct pin mode, get port address and bit - { -// iSDABit = 1 << (pI2C->iSDA & 0x7); - iSDABit = 1 << getPinInfo(pI2C->iSDA, &iDDR_SDA, &iPort_SDA_Out, 0); - getPinInfo(pI2C->iSDA, &iDDR_SDA, &iPort_SDA_In, 1); -// iSCLBit = 1 << (pI2C->iSCL & 0x7); - iSCLBit = 1 << getPinInfo(pI2C->iSCL, &iDDR_SCL, &iPort_SCL_Out, 0); - *iDDR_SDA &= ~iSDABit; // pinMode input - *iDDR_SCL &= ~iSCLBit; // pinMode input - *iPort_SDA_Out &= ~iSDABit; // digitalWrite SDA LOW - *iPort_SCL_Out &= ~iSCLBit; // digitalWrite SCL LOW - } -#endif // __AVR__ - // For now, we only support 100, 400 or 800K clock rates - // all other values default to 100K -#ifdef _LINUX_ - pI2C->iDelay = 1000000 / iClock; - if (pI2C->iDelay < 1) pI2C->iDelay = 1; -#else - if (iClock >= 1000000) - pI2C->iDelay = 0; // the code execution is enough delay - else if (iClock >= 800000) - pI2C->iDelay = 1; - else if (iClock >= 400000) - pI2C->iDelay = 2; - else if (iClock >= 100000) - pI2C->iDelay = 10; - else pI2C->iDelay = (uint16_t)(1000000 / iClock); -#endif // _LINUX_ -} /* i2cInit() */ -// -// Test a specific I2C address to see if a device responds -// returns 0 for no response, 1 for a response -// -uint8_t I2CTest(BBI2C *pI2C, uint8_t addr) -{ -uint8_t response = 0; - - if (pI2C->bWire) - { -#if !defined( _LINUX_ ) && !defined( __AVR_ATtiny85__ ) - // We use the return value of - // the Write.endTransmisstion to see if - // a device did acknowledge to the address. - Wire.beginTransmission(addr); - response = !Wire.endTransmission(); -#endif -#ifdef _LINUX_ - if (ioctl(pI2C->file_i2c, I2C_SLAVE, addr) >= 0) - response = 1; -#endif - return response; - } - if (i2cBegin(pI2C, addr, 0)) // try to write to the given address - { - response = 1; - } - i2cEnd(pI2C); - return response; -} /* I2CTest() */ -// -// Scans for I2C devices on the bus -// returns a bitmap of devices which are present (128 bits = 16 bytes, LSB first) -// A set bit indicates that a device responded at that address -// -void I2CScan(BBI2C *pI2C, uint8_t *pMap) -{ - int i; - for (i=0; i<16; i++) // clear the bitmap - pMap[i] = 0; - for (i=1; i<128; i++) // try every address - { - if (I2CTest(pI2C, i)) - { - pMap[i >> 3] |= (1 << (i & 7)); - } - } -} /* I2CScan() */ -// -// Write I2C data -// quits if a NACK is received and returns 0 -// otherwise returns the number of bytes written -// -int I2CWrite(BBI2C *pI2C, uint8_t iAddr, uint8_t *pData, int iLen) -{ - int rc = 0; - - if (pI2C->bWire) - { -#if !defined ( _LINUX_ ) && !defined( __AVR_ATtiny85__ ) - Wire.beginTransmission(iAddr); - Wire.write(pData, (uint8_t)iLen); - rc = !Wire.endTransmission(); -#endif -#ifdef _LINUX_ - if (ioctl(pI2C->file_i2c, I2C_SLAVE, iAddr) >= 0) - { - if (write(pI2C->file_i2c, pData, iLen) >= 0) - rc = 1; - } -#endif // _LINUX_ - return rc; - } - rc = i2cBegin(pI2C, iAddr, 0); - if (rc == 1) // slave sent ACK for its address - { - rc = i2cWrite(pI2C, pData, iLen); - } - i2cEnd(pI2C); - return rc; // returns the number of bytes sent or 0 for error -} /* I2CWrite() */ -// -// Read N bytes starting at a specific I2C internal register -// -int I2CReadRegister(BBI2C *pI2C, uint8_t iAddr, uint8_t u8Register, uint8_t *pData, int iLen) -{ - int rc; - - if (pI2C->bWire) // use the wire library - { - int i = 0; -#if !defined( _LINUX_ ) && !defined( __AVR_ATtiny85__ ) - Wire.beginTransmission(iAddr); - Wire.write(u8Register); - Wire.endTransmission(); - Wire.requestFrom(iAddr, (uint8_t)iLen); - while (i < iLen) - { - pData[i++] = Wire.read(); - } -#endif -#ifdef _LINUX_ - if (ioctl(pI2C->file_i2c, I2C_SLAVE, iAddr) >= 0) - { - write(pI2C->file_i2c, &u8Register, 1); - i = read(pI2C->file_i2c, pData, iLen); - } -#endif // _LINUX_ - return (i > 0); - } - rc = i2cBegin(pI2C, iAddr, 0); // start a write operation - if (rc == 1) // slave sent ACK for its address - { - rc = i2cWrite(pI2C, &u8Register, 1); // write the register we want to read from - if (rc == 1) - { - i2cEnd(pI2C); - rc = i2cBegin(pI2C, iAddr, 1); // start a read operation - if (rc == 1) - { - i2cRead(pI2C, pData, iLen); - } - } - } - i2cEnd(pI2C); - return rc; // returns 1 for success, 0 for error -} /* I2CReadRegister() */ - -// -// Read N bytes -// -int I2CRead(BBI2C *pI2C, uint8_t iAddr, uint8_t *pData, int iLen) -{ - int rc; - - if (pI2C->bWire) // use the wire library - { - int i = 0; -#if !defined( _LINUX_ ) && !defined( __AVR_ATtiny85__ ) - Wire.requestFrom(iAddr, (uint8_t)iLen); - while (i < iLen) - { - pData[i++] = Wire.read(); - } -#endif -#ifdef _LINUX_ - if (ioctl(pI2C->file_i2c, I2C_SLAVE, iAddr) >= 0) - { - i = read(pI2C->file_i2c, pData, iLen); - } -#endif // _LINUX_ - return (i > 0); - } - rc = i2cBegin(pI2C, iAddr, 1); - if (rc == 1) // slave sent ACK for its address - { - i2cRead(pI2C, pData, iLen); - } - i2cEnd(pI2C); - return rc; // returns 1 for success, 0 for error -} /* I2CRead() */ -// -// Figure out what device is at that address -// returns the enumerated value -// -int I2CDiscoverDevice(BBI2C *pI2C, uint8_t i) -{ -uint8_t j, cTemp[8]; -int iDevice = DEVICE_UNKNOWN; - - if (i == 0x3c || i == 0x3d) // Probably an OLED display - { - I2CReadRegister(pI2C, i, 0x00, cTemp, 1); - cTemp[0] &= 0xbf; // mask off power on/off bit - if (cTemp[0] == 0x8) // SH1106 - iDevice = DEVICE_SH1106; - else if (cTemp[0] == 3 || cTemp[0] == 6) - iDevice = DEVICE_SSD1306; - return iDevice; - } - if (i >= 0x40 && i <= 0x4f) // check for TI INA219 power measurement sensor - { - I2CReadRegister(pI2C, i, 0x00, cTemp, 2); - if (cTemp[0] == 0x39 && cTemp[1] == 0x9f) - return DEVICE_INA219; - } -// else if (i == 0x5b) // MLX90615? -// { -// I2CReadRegister(pI2C, i, 0x10, cTemp, 3); -// for (j=0; j<3; j++) Serial.println(cTemp[j], HEX); -// } - // try to identify it from the known devices using register contents - { - // Check for TI HDC1080 - I2CReadRegister(pI2C, i, 0xff, cTemp, 2); - if (cTemp[0] == 0x10 && cTemp[1] == 0x50) - return DEVICE_HDC1080; - - // Check for VL53L0X - I2CReadRegister(pI2C, i, 0xc0, cTemp, 3); - if (cTemp[0] == 0xee && cTemp[1] == 0xaa && cTemp[2] == 0x10) - return DEVICE_VL53L0X; - - // Check for CCS811 - I2CReadRegister(pI2C, i, 0x20, cTemp, 1); - if (cTemp[0] == 0x81) // Device ID - return DEVICE_CCS811; - - // Check for LIS3DSH accelerometer from STMicro - I2CReadRegister(pI2C, i, 0x0f, cTemp, 1); - if (cTemp[0] == 0x3f) // WHO_AM_I - return DEVICE_LIS3DSH; - - // Check for LIS3DH accelerometer from STMicro - I2CReadRegister(pI2C, i, 0x0f, cTemp, 1); - if (cTemp[0] == 0x33) // WHO_AM_I - return DEVICE_LIS3DH; - - // Check for LSM9DS1 magnetometer/gyro/accel sensor from STMicro - I2CReadRegister(pI2C, i, 0x0f, cTemp, 1); - if (cTemp[0] == 0x68) // WHO_AM_I - return DEVICE_LSM9DS1; - - // Check for LPS25H pressure sensor from STMicro - I2CReadRegister(pI2C, i, 0x0f, cTemp, 1); - if (cTemp[0] == 0xbd) // WHO_AM_I - return DEVICE_LPS25H; - - // Check for HTS221 temp/humidity sensor from STMicro - I2CReadRegister(pI2C, i, 0x0f, cTemp, 1); - if (cTemp[0] == 0xbc) // WHO_AM_I - return DEVICE_HTS221; - - // Check for MAG3110 - I2CReadRegister(pI2C, i, 0x07, cTemp, 1); - if (cTemp[0] == 0xc4) // WHO_AM_I - return DEVICE_MAG3110; - - // Check for LM8330 keyboard controller - I2CReadRegister(pI2C, i, 0x80, cTemp, 2); - if (cTemp[0] == 0x0 && cTemp[1] == 0x84) // manufacturer code + software revision - return DEVICE_LM8330; - - // Check for MAX44009 - if (i == 0x4a || i == 0x4b) - { - for (j=0; j<8; j++) - I2CReadRegister(pI2C, i, j, &cTemp[j], 1); // check for power-up reset state of registers - if ((cTemp[2] == 3 || cTemp[2] == 2) && cTemp[6] == 0 && cTemp[7] == 0xff) - return DEVICE_MAX44009; - } - - // Check for ADS1115 - I2CReadRegister(pI2C, i, 0x02, cTemp, 2); // Lo_thresh defaults to 0x8000 - I2CReadRegister(pI2C, i, 0x03, &cTemp[2], 2); // Hi_thresh defaults to 0x7fff - if (cTemp[0] == 0x80 && cTemp[1] == 0x00 && cTemp[2] == 0x7f && cTemp[3] == 0xff) - return DEVICE_ADS1115; - - // Check for MCP9808 - I2CReadRegister(pI2C, i, 0x06, cTemp, 2); // manufacturer ID && get device ID/revision - I2CReadRegister(pI2C, i, 0x07, &cTemp[2], 2); // need to read them individually - if (cTemp[0] == 0 && cTemp[1] == 0x54 && cTemp[2] == 0x04 && cTemp[3] == 0x00) - return DEVICE_MCP9808; - - // Check for BMP280/BME280 - I2CReadRegister(pI2C, i, 0xd0, cTemp, 1); - if (cTemp[0] == 0x55) // BMP180 - return DEVICE_BMP180; - else if (cTemp[0] == 0x58) - return DEVICE_BMP280; - else if (cTemp[0] == 0x60) // BME280 - return DEVICE_BME280; - - // Check for LSM6DS3 - I2CReadRegister(pI2C, i, 0x0f, cTemp, 1); // WHO_AM_I - if (cTemp[0] == 0x69) - return DEVICE_LSM6DS3; - - // Check for ADXL345 - I2CReadRegister(pI2C, i, 0x00, cTemp, 1); // DEVID - if (cTemp[0] == 0xe5) - return DEVICE_ADXL345; - - // Check for MPU-60x0i, MPU-688x, and MPU-9250 - I2CReadRegister(pI2C, i, 0x75, cTemp, 1); - if (cTemp[0] == (i & 0xfe)) // Current I2C address (low bit set to 0) - return DEVICE_MPU6000; - else if (cTemp[0] == 0x71) - return DEVICE_MPU9250; - else if (cTemp[0] == 0x19) - return DEVICE_MPU6886; - - // Check for DS3231 RTC - I2CReadRegister(pI2C, i, 0x0e, cTemp, 1); // read the control register - if (i == 0x68 && cTemp[0] == 0x1c) // fixed I2C address and power on reset value - return DEVICE_DS3231; - } - return iDevice; -} /* I2CDiscoverDevice() */ - - -//******************************************** INFINEON modified functions ****************************************** - -// -// Receive a byte and read the ack bit -// if we get a NACK (negative acknowledge) return 0 -// otherwise return 1 for success -// -static inline uint8_t i2cByteInCyp(BBI2C *pI2C, uint8_t bLast) -{ -uint8_t i; -uint8_t b = 0; - - SDA_HIGH(pI2C->iSDA); // set data line as input - for (i=0; i<8; i++) - { - sleep_us(pI2C->iDelay); // wait for data to settle - SCL_HIGH(pI2C->iSCL); // clock high (slave latches data) - b <<= 1; - if (SDA_READ(pI2C->iSDA) != 0) // read the data bit - b |= 1; // set data bit - SCL_LOW(pI2C->iSCL); // cloc low - } // for i - if (bLast) - { - sleep_us(200);// debug Fabio - SDA_HIGH(pI2C->iSDA); - Serial.println("byteIn "); - } // last byte sends a NACK} - else - SDA_LOW(pI2C->iSDA); - SCL_HIGH(pI2C->iSCL); // clock high - sleep_us(pI2C->iDelay); - sleep_us(200);// debug Litix Shield - SCL_LOW(pI2C->iSCL); // clock low to send ack - sleep_us(pI2C->iDelay); - sleep_us(200);// debug Litix Shield - SDA_LOW(pI2C->iSDA); // data low - return b; -} /* i2cByteIn() */ - -static inline void i2cReadCyp(BBI2C *pI2C, uint8_t *pData, int iLen) -{ - while (iLen--) - { - *pData++ = i2cByteInCyp(pI2C, iLen == 0); - } // for each byte -} /* i2cRead() */ - -// Transmit a byte and read the ack bit -// if we get a NACK (negative acknowledge) return 0 -// otherwise return 1 for success -// -static inline int i2cByteOutCyp(BBI2C *pI2C, uint8_t b) -{ -uint8_t i, ack; -uint8_t iSDA = pI2C->iSDA; -uint8_t iSCL = pI2C->iSCL; // in case of bad C compiler -int iDelay = pI2C->iDelay; - - for (i=0; i<8; i++) - { - if (b & 0x80) - SDA_HIGH(iSDA); // set data line to 1 - else - SDA_LOW(iSDA); // set data line to 0 - SCL_HIGH(iSCL); // clock high (slave latches data) - sleep_us(iDelay); - SCL_LOW(iSCL); // clock low - b <<= 1; - sleep_us(iDelay); - } // for i - // read ack bit - SDA_HIGH(iSDA); // set data line for reading - SCL_HIGH(iSCL); // clock line high - sleep_us(iDelay); // DEBUG - delay/2 - sleep_us(200); // debug Fabio - ack = SDA_READ(iSDA); - SCL_LOW(iSCL); // clock low - sleep_us(iDelay); // DEBUG - delay/2 - SDA_LOW(iSDA); // data low - return (ack == 0) ? 1:0; // a low ACK bit means success -} /* i2cByteOut() */ - - - - -static inline int i2cBeginCyp(BBI2C *pI2C, uint8_t addr, uint8_t bRead) -{ - int rc; - SDA_LOW(pI2C->iSDA); // data line low first - sleep_us(pI2C->iDelay); - SCL_LOW(pI2C->iSCL); // then clock line low is a START signal - addr <<= 1; - if (bRead) - addr++; // set read bit - - rc = i2cByteOutCyp(pI2C, addr); // send the slave address and R/W bit - - return rc; -} /* i2cBegin() */ - - -static inline int i2cWriteCyp(BBI2C *pI2C, uint8_t *pData, int iLen) -{ -uint8_t b; -int rc, iOldLen = iLen; - - rc = 1; - while (iLen && rc == 1) - { - b = *pData++; - rc = i2cByteOutCyp(pI2C, b); - if (rc == 1) // success - { - sleep_us(200);// debug Fabio - iLen--; - } - } // for each byte - return (rc == 1) ? (iOldLen - iLen) : 0; // 0 indicates bad ack from sending a byte -} /* i2cWrite() */ - - -// -// Read N bytes starting at a specific I2C internal register -// -int I2CReadRegister16(BBI2C *pI2C, uint8_t iAddr, uint8_t *uRegister, uint8_t *pData, int iLen) -{ - int rc; - - rc = i2cBeginCyp(pI2C, iAddr, 0); // start a write operation: send slave address+write bit (0) - - if (rc == 1) // slave sent ACK for its address - { - rc = i2cWriteCyp(pI2C, uRegister, 2); // write the register we want to read from - if (rc == 2) // if both the bytes of the reg adress has been sent - { - i2cEnd(pI2C); - rc = i2cBeginCyp(pI2C, iAddr, 1); // start a read operation - if (rc == 1) - { - i2cReadCyp(pI2C, pData, iLen); - } - } - - } - i2cEnd(pI2C); - - return rc; // returns 1 for success, 0 for error -} /* I2CReadRegister() */ - -// -// Read N bytes -// -int I2CReadCyp(BBI2C *pI2C, uint8_t iAddr, uint8_t *pData, int iLen) -{ - int rc; - - rc = i2cBegin(pI2C, iAddr, 1); - if (rc == 1) // slave sent ACK for its address - { - i2cReadCyp(pI2C, pData, iLen); - } - i2cEnd(pI2C); - return rc; // returns 1 for success, 0 for error -} /* I2CRead() */ diff --git a/TLD5542-1LED_DRV_V1.02/BitBang_I2C.h b/TLD5542-1LED_DRV_V1.02/BitBang_I2C.h deleted file mode 100755 index 33eb68e..0000000 --- a/TLD5542-1LED_DRV_V1.02/BitBang_I2C.h +++ /dev/null @@ -1,108 +0,0 @@ -// -// Bit Bang I2C library -// Copyright (c) 2018 BitBank Software, Inc. -// Written by Larry Bank (bitbank@pobox.com) -// Project started 10/12/2018 -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -#ifndef __BITBANG_I2C__ -#define __BITBANG_I2C__ -// supported devices -enum { - DEVICE_UNKNOWN = 0, - DEVICE_SSD1306, - DEVICE_SH1106, - DEVICE_VL53L0X, - DEVICE_BMP180, - DEVICE_BMP280, - DEVICE_BME280, - DEVICE_MPU6000, - DEVICE_MPU9250, - DEVICE_MCP9808, - DEVICE_LSM6DS3, - DEVICE_ADXL345, - DEVICE_ADS1115, - DEVICE_MAX44009, - DEVICE_MAG3110, - DEVICE_CCS811, - DEVICE_HTS221, - DEVICE_LPS25H, - DEVICE_LSM9DS1, - DEVICE_LM8330, - DEVICE_DS3231, - DEVICE_LIS3DH, - DEVICE_LIS3DSH, - DEVICE_INA219, - DEVICE_SHT3X, - DEVICE_HDC1080, - DEVICE_MPU6886 -}; - -typedef struct mybbi2c -{ -uint8_t iSDA, iSCL; // pin numbers (0xff = disabled) -uint8_t bWire; // use the Wire library -uint8_t iSDABit, iSCLBit; // bit numbers of the ports -uint32_t iDelay; -#ifdef _LINUX_ -int file_i2c; -int iBus; -#else -volatile uint32_t *pSDADDR, *pSDAPORT; // data direction and port register addr -volatile uint32_t *pSCLDDR, *pSCLPORT; -#endif -} BBI2C; -// -// Read N bytes -// -int I2CRead(BBI2C *pI2C, uint8_t iAddr, uint8_t *pData, int iLen); - -int I2CReadRegister16(BBI2C *pI2C, uint8_t iAddr, uint8_t *uRegister, uint8_t *pData, int iLen);// DEBUG: modified for 16 bit read - -// -// Read N bytes starting at a specific I2C internal register -// -int I2CReadRegister(BBI2C *pI2C, uint8_t iAddr, uint8_t u8Register, uint8_t *pData, int iLen); -// -// Write I2C data -// quits if a NACK is received and returns 0 -// otherwise returns the number of bytes written -// -int I2CWrite(BBI2C *pI2C, uint8_t iAddr, uint8_t *pData, int iLen); -// -// Scans for I2C devices on the bus -// returns a bitmap of devices which are present (128 bits = 16 bytes, LSB first) -// -// Test if an address responds -// returns 0 if no response, 1 if it responds -// -uint8_t I2CTest(BBI2C *pI2C, uint8_t addr); - -// A set bit indicates that a device responded at that address -// -void I2CScan(BBI2C *pI2C, uint8_t *pMap); -// -// Initialize the I2C BitBang library -// Pass the pin numbers used for SDA and SCL -// as well as the clock rate in Hz -// -void I2CInit(BBI2C *pI2C, uint32_t iClock); -// -// Figure out what device is at that address -// returns the enumerated value -// -int I2CDiscoverDevice(BBI2C *pI2C, uint8_t i); - -#endif //__BITBANG_I2C__ diff --git a/TLD5542-1LED_DRV_V1.02/OneBitDisplay.cpp b/TLD5542-1LED_DRV_V1.02/OneBitDisplay.cpp deleted file mode 100755 index ebf46fa..0000000 --- a/TLD5542-1LED_DRV_V1.02/OneBitDisplay.cpp +++ /dev/null @@ -1,3469 +0,0 @@ -// -// OneBitDisplay (OLED+LCD library) -// Copyright (c) 2020 BitBank Software, Inc. -// Written by Larry Bank (bitbank@pobox.com) -// Project started 3/23/2020 -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#ifdef _LINUX_ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#define PROGMEM -#define false 0 -#define true 1 -#define memcpy_P memcpy -static int file_i2c = 0; - -#else // Arduino - -#include -#ifdef __AVR__ -#include -#endif -#include - -#ifdef HAL_ESP32_HAL_H_ -// Bluetooth support -#include -#include -#include -static BLEUUID serviceUUID("0000fea0-0000-1000-8000-00805f9b34fb"); //Service -static BLEUUID dataUUID("0000fea1-0000-1000-8000-00805f9b34fb"); // data characteristic -static BLEUUID nameUUID("0000fea2-0000-1000-8000-00805f9b34fb"); // name characteristic -std::string VD_BLE_Name = "VirtualDisplay"; -char Scanned_BLE_Name[32]; -String Scanned_BLE_Address; -BLEScanResults foundDevices; -static BLEAddress *Server_BLE_Address; -volatile boolean paired = false; //boolean variable to togge light -BLEServer *pServer; -BLEScan *pBLEScan; -BLEService *pService; -BLERemoteCharacteristic *pCharacteristicData, *pCharacteristicName; -static int bConnected = 0; -#endif // HAL_ESP32_HAL_H_ - -// Bluetooth support for Nano 33 BLE -#ifdef ARDUINO_ARDUINO_NANO33BLE -#include - -static BLEDevice peripheral; -static BLEService prtService; -static BLECharacteristic pCharacteristicData, pCharacteristicName; -static int bConnected = 0; -#endif // Nano 33 BLE - -#endif // _LINUX_ -#include "OneBitDisplay.h" - -const uint8_t ucMirror[256] PROGMEM = - {0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240, - 8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248, - 4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244, - 12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252, - 2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242, - 10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250, - 6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246, - 14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254, - 1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241, - 9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249, - 5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245, - 13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253, - 3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243, - 11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251, - 7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247, - 15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255}; - -const uint8_t ucFont[]PROGMEM = { -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x5f,0x5f,0x06,0x00,0x00, -0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00,0x14,0x7f,0x7f,0x14,0x7f,0x7f,0x14,0x00, - 0x24,0x2e,0x2a,0x6b,0x6b,0x3a,0x12,0x00,0x46,0x66,0x30,0x18,0x0c,0x66,0x62,0x00, - 0x30,0x7a,0x4f,0x5d,0x37,0x7a,0x48,0x00,0x00,0x04,0x07,0x03,0x00,0x00,0x00,0x00, - 0x00,0x1c,0x3e,0x63,0x41,0x00,0x00,0x00,0x00,0x41,0x63,0x3e,0x1c,0x00,0x00,0x00, - 0x08,0x2a,0x3e,0x1c,0x1c,0x3e,0x2a,0x08,0x00,0x08,0x08,0x3e,0x3e,0x08,0x08,0x00, - 0x00,0x00,0x80,0xe0,0x60,0x00,0x00,0x00,0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x00, - 0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x60,0x30,0x18,0x0c,0x06,0x03,0x01,0x00, - 0x3e,0x7f,0x59,0x4d,0x47,0x7f,0x3e,0x00,0x40,0x42,0x7f,0x7f,0x40,0x40,0x00,0x00, - 0x62,0x73,0x59,0x49,0x6f,0x66,0x00,0x00,0x22,0x63,0x49,0x49,0x7f,0x36,0x00,0x00, - 0x18,0x1c,0x16,0x53,0x7f,0x7f,0x50,0x00,0x27,0x67,0x45,0x45,0x7d,0x39,0x00,0x00, - 0x3c,0x7e,0x4b,0x49,0x79,0x30,0x00,0x00,0x03,0x03,0x71,0x79,0x0f,0x07,0x00,0x00, - 0x36,0x7f,0x49,0x49,0x7f,0x36,0x00,0x00,0x06,0x4f,0x49,0x69,0x3f,0x1e,0x00,0x00, - 0x00,0x00,0x00,0x66,0x66,0x00,0x00,0x00,0x00,0x00,0x80,0xe6,0x66,0x00,0x00,0x00, - 0x08,0x1c,0x36,0x63,0x41,0x00,0x00,0x00,0x00,0x14,0x14,0x14,0x14,0x14,0x14,0x00, - 0x00,0x41,0x63,0x36,0x1c,0x08,0x00,0x00,0x00,0x02,0x03,0x59,0x5d,0x07,0x02,0x00, - 0x3e,0x7f,0x41,0x5d,0x5d,0x5f,0x0e,0x00,0x7c,0x7e,0x13,0x13,0x7e,0x7c,0x00,0x00, - 0x41,0x7f,0x7f,0x49,0x49,0x7f,0x36,0x00,0x1c,0x3e,0x63,0x41,0x41,0x63,0x22,0x00, - 0x41,0x7f,0x7f,0x41,0x63,0x3e,0x1c,0x00,0x41,0x7f,0x7f,0x49,0x5d,0x41,0x63,0x00, - 0x41,0x7f,0x7f,0x49,0x1d,0x01,0x03,0x00,0x1c,0x3e,0x63,0x41,0x51,0x33,0x72,0x00, - 0x7f,0x7f,0x08,0x08,0x7f,0x7f,0x00,0x00,0x00,0x41,0x7f,0x7f,0x41,0x00,0x00,0x00, - 0x30,0x70,0x40,0x41,0x7f,0x3f,0x01,0x00,0x41,0x7f,0x7f,0x08,0x1c,0x77,0x63,0x00, - 0x41,0x7f,0x7f,0x41,0x40,0x60,0x70,0x00,0x7f,0x7f,0x0e,0x1c,0x0e,0x7f,0x7f,0x00, - 0x7f,0x7f,0x06,0x0c,0x18,0x7f,0x7f,0x00,0x1c,0x3e,0x63,0x41,0x63,0x3e,0x1c,0x00, - 0x41,0x7f,0x7f,0x49,0x09,0x0f,0x06,0x00,0x1e,0x3f,0x21,0x31,0x61,0x7f,0x5e,0x00, - 0x41,0x7f,0x7f,0x09,0x19,0x7f,0x66,0x00,0x26,0x6f,0x4d,0x49,0x59,0x73,0x32,0x00, - 0x03,0x41,0x7f,0x7f,0x41,0x03,0x00,0x00,0x7f,0x7f,0x40,0x40,0x7f,0x7f,0x00,0x00, - 0x1f,0x3f,0x60,0x60,0x3f,0x1f,0x00,0x00,0x3f,0x7f,0x60,0x30,0x60,0x7f,0x3f,0x00, - 0x63,0x77,0x1c,0x08,0x1c,0x77,0x63,0x00,0x07,0x4f,0x78,0x78,0x4f,0x07,0x00,0x00, - 0x47,0x63,0x71,0x59,0x4d,0x67,0x73,0x00,0x00,0x7f,0x7f,0x41,0x41,0x00,0x00,0x00, - 0x01,0x03,0x06,0x0c,0x18,0x30,0x60,0x00,0x00,0x41,0x41,0x7f,0x7f,0x00,0x00,0x00, - 0x08,0x0c,0x06,0x03,0x06,0x0c,0x08,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, - 0x00,0x00,0x03,0x07,0x04,0x00,0x00,0x00,0x20,0x74,0x54,0x54,0x3c,0x78,0x40,0x00, - 0x41,0x7f,0x3f,0x48,0x48,0x78,0x30,0x00,0x38,0x7c,0x44,0x44,0x6c,0x28,0x00,0x00, - 0x30,0x78,0x48,0x49,0x3f,0x7f,0x40,0x00,0x38,0x7c,0x54,0x54,0x5c,0x18,0x00,0x00, - 0x48,0x7e,0x7f,0x49,0x03,0x06,0x00,0x00,0x98,0xbc,0xa4,0xa4,0xf8,0x7c,0x04,0x00, - 0x41,0x7f,0x7f,0x08,0x04,0x7c,0x78,0x00,0x00,0x44,0x7d,0x7d,0x40,0x00,0x00,0x00, - 0x60,0xe0,0x80,0x84,0xfd,0x7d,0x00,0x00,0x41,0x7f,0x7f,0x10,0x38,0x6c,0x44,0x00, - 0x00,0x41,0x7f,0x7f,0x40,0x00,0x00,0x00,0x7c,0x7c,0x18,0x78,0x1c,0x7c,0x78,0x00, - 0x7c,0x78,0x04,0x04,0x7c,0x78,0x00,0x00,0x38,0x7c,0x44,0x44,0x7c,0x38,0x00,0x00, - 0x84,0xfc,0xf8,0xa4,0x24,0x3c,0x18,0x00,0x18,0x3c,0x24,0xa4,0xf8,0xfc,0x84,0x00, - 0x44,0x7c,0x78,0x4c,0x04,0x0c,0x18,0x00,0x48,0x5c,0x54,0x74,0x64,0x24,0x00,0x00, - 0x04,0x04,0x3e,0x7f,0x44,0x24,0x00,0x00,0x3c,0x7c,0x40,0x40,0x3c,0x7c,0x40,0x00, - 0x1c,0x3c,0x60,0x60,0x3c,0x1c,0x00,0x00,0x3c,0x7c,0x60,0x30,0x60,0x7c,0x3c,0x00, - 0x44,0x6c,0x38,0x10,0x38,0x6c,0x44,0x00,0x9c,0xbc,0xa0,0xa0,0xfc,0x7c,0x00,0x00, - 0x4c,0x64,0x74,0x5c,0x4c,0x64,0x00,0x00,0x08,0x08,0x3e,0x77,0x41,0x41,0x00,0x00, - 0x00,0x00,0x00,0x77,0x77,0x00,0x00,0x00,0x41,0x41,0x77,0x3e,0x08,0x08,0x00,0x00, - 0x02,0x03,0x01,0x03,0x02,0x03,0x01,0x00,0x70,0x78,0x4c,0x46,0x4c,0x78,0x70,0x00}; -// AVR MCUs have very little memory; save 6K of FLASH by stretching the 'normal' -// font instead of using this large font -#ifndef __AVR__ -const uint8_t ucBigFont[]PROGMEM = { - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0xfc,0xfc,0xff,0xff,0xff,0xff,0xfc,0xfc,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0x3f,0x3f,0x3f,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x0f,0x0f,0x0f,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00,0xc0,0xc0,0xc0,0xc0,0x00,0x00, - 0x00,0x00,0x0f,0x0f,0x3f,0x3f,0x00,0x00,0x00,0x00,0x3f,0x3f,0x0f,0x0f,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0xc0,0xc0,0xfc,0xfc,0xfc,0xfc,0xc0,0xc0,0xfc,0xfc,0xfc,0xfc,0xc0,0xc0,0x00,0x00, - 0xc0,0xc0,0xff,0xff,0xff,0xff,0xc0,0xc0,0xff,0xff,0xff,0xff,0xc0,0xc0,0x00,0x00, - 0x00,0x00,0x0f,0x0f,0x0f,0x0f,0x00,0x00,0x0f,0x0f,0x0f,0x0f,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xf0,0xf0,0xf0,0x00,0x00,0x00,0x00,0x00,0x00, - 0xfc,0xfc,0xff,0xff,0x03,0x03,0x03,0x03,0x03,0x03,0x0f,0x0f,0x3c,0x3c,0x00,0x00, - 0xf0,0xf0,0xc3,0xc3,0x03,0x03,0x03,0x03,0x03,0x03,0xff,0xff,0xfc,0xfc,0x00,0x00, - 0x00,0x00,0x03,0x03,0x03,0x03,0x3f,0x3f,0x3f,0x3f,0x03,0x03,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0xf0,0xf0,0xf0,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xc0,0xf0,0xf0,0x00,0x00, - 0x00,0x00,0xc0,0xc0,0xf0,0xf0,0x3c,0x3c,0x0f,0x0f,0x03,0x03,0x00,0x00,0x00,0x00, - 0x0f,0x0f,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x0f,0x0f,0x0f,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x3c,0x3c,0xff,0xff,0xc3,0xc3,0xff,0xff,0x3c,0x3c,0x00,0x00,0x00,0x00, - 0xfc,0xfc,0xff,0xff,0x03,0x03,0x0f,0x0f,0xfc,0xfc,0xff,0xff,0x03,0x03,0x00,0x00, - 0x03,0x03,0x0f,0x0f,0x0c,0x0c,0x0c,0x0c,0x03,0x03,0x0f,0x0f,0x0c,0x0c,0x00,0x00, - 0x00,0x00,0x00,0x00,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x30,0x30,0x3f,0x3f,0x0f,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0xf0,0xf0,0xfc,0xfc,0x0f,0x0f,0x03,0x03,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x0f,0x0f,0x0c,0x0c,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x03,0x03,0x0f,0x0f,0xfc,0xfc,0xf0,0xf0,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x0c,0x0c,0x0f,0x0f,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00,0xc0,0xc0,0xc0,0xc0,0x00,0x00, - 0x0c,0x0c,0xcc,0xcc,0xff,0xff,0x3f,0x3f,0x3f,0x3f,0xff,0xff,0xcc,0xcc,0x0c,0x0c, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x0c,0x0c,0x0c,0x0c,0xff,0xff,0xff,0xff,0x0c,0x0c,0x0c,0x0c,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x30,0x30,0x3f,0x3f,0x0f,0x0f,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x0f,0x0f,0x0f,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xc0,0xf0,0xf0,0x00,0x00, - 0x00,0x00,0xc0,0xc0,0xf0,0xf0,0x3c,0x3c,0x0f,0x0f,0x03,0x03,0x00,0x00,0x00,0x00, - 0x0f,0x0f,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0xfc,0xfc,0xff,0xff,0x03,0x03,0x03,0x03,0xc3,0xc3,0xff,0xff,0xfc,0xfc,0x00,0x00, - 0xff,0xff,0xff,0xff,0x30,0x30,0x0f,0x0f,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00, - 0x03,0x03,0x0f,0x0f,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0f,0x0f,0x03,0x03,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x30,0x30,0x3c,0x3c,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x0c,0x0c,0x0c,0x0c,0x0f,0x0f,0x0f,0x0f,0x0c,0x0c,0x0c,0x0c,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x0c,0x0c,0x0f,0x0f,0x03,0x03,0x03,0x03,0xc3,0xc3,0xff,0xff,0x3c,0x3c,0x00,0x00, - 0xc0,0xc0,0xf0,0xf0,0x3c,0x3c,0x0f,0x0f,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00, - 0x0f,0x0f,0x0f,0x0f,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0f,0x0f,0x0f,0x0f,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x0c,0x0c,0x0f,0x0f,0x03,0x03,0x03,0x03,0x03,0x03,0xff,0xff,0xfc,0xfc,0x00,0x00, - 0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x03,0x03,0xff,0xff,0xfc,0xfc,0x00,0x00, - 0x03,0x03,0x0f,0x0f,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0f,0x0f,0x03,0x03,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0xc0,0xc0,0xf0,0xf0,0x3c,0x3c,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00, - 0x0f,0x0f,0x0f,0x0f,0x0c,0x0c,0x0c,0x0c,0xff,0xff,0xff,0xff,0x0c,0x0c,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x0c,0x0f,0x0f,0x0f,0x0f,0x0c,0x0c,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0xff,0xff,0xff,0xff,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x00,0x00, - 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x0f,0x0f,0xff,0xff,0xfc,0xfc,0x00,0x00, - 0x03,0x03,0x0f,0x0f,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0f,0x0f,0x03,0x03,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0xf0,0xf0,0xfc,0xfc,0x0f,0x0f,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00, - 0xff,0xff,0xff,0xff,0x03,0x03,0x03,0x03,0x03,0x03,0xff,0xff,0xfc,0xfc,0x00,0x00, - 0x03,0x03,0x0f,0x0f,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0f,0x0f,0x03,0x03,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x0f,0x0f,0x0f,0x0f,0x03,0x03,0x03,0x03,0x03,0x03,0xff,0xff,0xff,0xff,0x00,0x00, - 0x00,0x00,0x00,0x00,0xf0,0xf0,0xfc,0xfc,0x0f,0x0f,0x03,0x03,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x0f,0x0f,0x0f,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0xfc,0xfc,0xff,0xff,0x03,0x03,0x03,0x03,0x03,0x03,0xff,0xff,0xfc,0xfc,0x00,0x00, - 0xfc,0xfc,0xff,0xff,0x03,0x03,0x03,0x03,0x03,0x03,0xff,0xff,0xfc,0xfc,0x00,0x00, - 0x03,0x03,0x0f,0x0f,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0f,0x0f,0x03,0x03,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0xfc,0xfc,0xff,0xff,0x03,0x03,0x03,0x03,0x03,0x03,0xff,0xff,0xfc,0xfc,0x00,0x00, - 0x00,0x00,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0xff,0xff,0xff,0xff,0x00,0x00, - 0x00,0x00,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0f,0x0f,0x03,0x03,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xf0,0xf0,0xf0,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xf0,0xf0,0xf0,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x0c,0x0c,0x0f,0x0f,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xc0,0xf0,0xf0,0x3c,0x3c,0x0c,0x0c,0x00,0x00, - 0x00,0x00,0x0c,0x0c,0x3f,0x3f,0xf3,0xf3,0xc0,0xc0,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x0f,0x0f,0x0c,0x0c,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x0c,0x0c,0x3c,0x3c,0xf0,0xf0,0xc0,0xc0,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xc0,0xf3,0xf3,0x3f,0x3f,0x0c,0x0c,0x00,0x00, - 0x00,0x00,0x0c,0x0c,0x0f,0x0f,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x3c,0x3c,0x3f,0x3f,0x03,0x03,0x03,0x03,0xc3,0xc3,0xff,0xff,0x3c,0x3c,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0x3f,0x3f,0x3f,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x0f,0x0f,0x0f,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0xf0,0xf0,0xfc,0xfc,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0xfc,0xfc,0xf0,0xf0,0x00,0x00, - 0xff,0xff,0xff,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x3f,0x00,0x00, - 0x03,0x03,0x0f,0x0f,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0xc0,0xc0,0xf0,0xf0,0x3c,0x3c,0x0f,0x0f,0x3c,0x3c,0xf0,0xf0,0xc0,0xc0,0x00,0x00, - 0xff,0xff,0xff,0xff,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0xff,0xff,0xff,0xff,0x00,0x00, - 0x0f,0x0f,0x0f,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x0f,0x0f,0x0f,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x03,0x03,0xff,0xff,0xff,0xff,0x03,0x03,0x03,0x03,0xff,0xff,0xfc,0xfc,0x00,0x00, - 0x00,0x00,0xff,0xff,0xff,0xff,0x03,0x03,0x03,0x03,0xff,0xff,0xfc,0xfc,0x00,0x00, - 0x0c,0x0c,0x0f,0x0f,0x0f,0x0f,0x0c,0x0c,0x0c,0x0c,0x0f,0x0f,0x03,0x03,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0xf0,0xf0,0xfc,0xfc,0x0f,0x0f,0x03,0x03,0x03,0x03,0x0f,0x0f,0x3c,0x3c,0x00,0x00, - 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xc0,0x00,0x00, - 0x00,0x00,0x03,0x03,0x0f,0x0f,0x0c,0x0c,0x0c,0x0c,0x0f,0x0f,0x03,0x03,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x03,0x03,0xff,0xff,0xff,0xff,0x03,0x03,0x0f,0x0f,0xfc,0xfc,0xf0,0xf0,0x00,0x00, - 0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00, - 0x0c,0x0c,0x0f,0x0f,0x0f,0x0f,0x0c,0x0c,0x0f,0x0f,0x03,0x03,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x03,0x03,0xff,0xff,0xff,0xff,0x03,0x03,0xc3,0xc3,0x0f,0x0f,0x3f,0x3f,0x00,0x00, - 0x00,0x00,0xff,0xff,0xff,0xff,0x03,0x03,0x0f,0x0f,0x00,0x00,0xc0,0xc0,0x00,0x00, - 0x0c,0x0c,0x0f,0x0f,0x0f,0x0f,0x0c,0x0c,0x0c,0x0c,0x0f,0x0f,0x0f,0x0f,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x03,0x03,0xff,0xff,0xff,0xff,0x03,0x03,0xc3,0xc3,0x0f,0x0f,0x3f,0x3f,0x00,0x00, - 0x00,0x00,0xff,0xff,0xff,0xff,0x03,0x03,0x0f,0x0f,0x00,0x00,0x00,0x00,0x00,0x00, - 0x0c,0x0c,0x0f,0x0f,0x0f,0x0f,0x0c,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0xf0,0xf0,0xfc,0xfc,0x0f,0x0f,0x03,0x03,0x03,0x03,0x0f,0x0f,0x3c,0x3c,0x00,0x00, - 0xff,0xff,0xff,0xff,0x00,0x00,0x0c,0x0c,0x0c,0x0c,0xfc,0xfc,0xfc,0xfc,0x00,0x00, - 0x00,0x00,0x03,0x03,0x0f,0x0f,0x0c,0x0c,0x0c,0x0c,0x03,0x03,0x0f,0x0f,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00, - 0xff,0xff,0xff,0xff,0x03,0x03,0x03,0x03,0x03,0x03,0xff,0xff,0xff,0xff,0x00,0x00, - 0x0f,0x0f,0x0f,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x0f,0x0f,0x0f,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x03,0x03,0xff,0xff,0xff,0xff,0x03,0x03,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x0c,0x0c,0x0f,0x0f,0x0f,0x0f,0x0c,0x0c,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0xff,0xff,0xff,0xff,0x03,0x03,0x00,0x00, - 0xf0,0xf0,0xf0,0xf0,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00, - 0x03,0x03,0x0f,0x0f,0x0c,0x0c,0x0c,0x0c,0x0f,0x0f,0x03,0x03,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x03,0x03,0xff,0xff,0xff,0xff,0x00,0x00,0xf0,0xf0,0xff,0xff,0x0f,0x0f,0x00,0x00, - 0x00,0x00,0xff,0xff,0xff,0xff,0x0f,0x0f,0x3f,0x3f,0xf0,0xf0,0xc0,0xc0,0x00,0x00, - 0x0c,0x0c,0x0f,0x0f,0x0f,0x0f,0x00,0x00,0x00,0x00,0x0f,0x0f,0x0f,0x0f,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x03,0x03,0xff,0xff,0xff,0xff,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xc0,0x00,0x00, - 0x0c,0x0c,0x0f,0x0f,0x0f,0x0f,0x0c,0x0c,0x0c,0x0c,0x0f,0x0f,0x0f,0x0f,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0xff,0xff,0xff,0xff,0xfc,0xfc,0xf0,0xf0,0xfc,0xfc,0xff,0xff,0xff,0xff,0x00,0x00, - 0xff,0xff,0xff,0xff,0x00,0x00,0x03,0x03,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00, - 0x0f,0x0f,0x0f,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x0f,0x0f,0x0f,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0xff,0xff,0xff,0xff,0xfc,0xfc,0xf0,0xf0,0xc0,0xc0,0xff,0xff,0xff,0xff,0x00,0x00, - 0xff,0xff,0xff,0xff,0x00,0x00,0x03,0x03,0x0f,0x0f,0xff,0xff,0xff,0xff,0x00,0x00, - 0x0f,0x0f,0x0f,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x0f,0x0f,0x0f,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0xf0,0xf0,0xfc,0xfc,0x0f,0x0f,0x03,0x03,0x0f,0x0f,0xfc,0xfc,0xf0,0xf0,0x00,0x00, - 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00, - 0x00,0x00,0x03,0x03,0x0f,0x0f,0x0c,0x0c,0x0f,0x0f,0x03,0x03,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x03,0x03,0xff,0xff,0xff,0xff,0x03,0x03,0x03,0x03,0xff,0xff,0xfc,0xfc,0x00,0x00, - 0x00,0x00,0xff,0xff,0xff,0xff,0x03,0x03,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0x00, - 0x0c,0x0c,0x0f,0x0f,0x0f,0x0f,0x0c,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0xfc,0xfc,0xff,0xff,0x03,0x03,0x03,0x03,0x03,0x03,0xff,0xff,0xfc,0xfc,0x00,0x00, - 0xff,0xff,0xff,0xff,0x00,0x00,0xc0,0xc0,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00, - 0x03,0x03,0x0f,0x0f,0x0c,0x0c,0x0f,0x0f,0xff,0xff,0xff,0xff,0xc3,0xc3,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x03,0x03,0xff,0xff,0xff,0xff,0x03,0x03,0x03,0x03,0xff,0xff,0xfc,0xfc,0x00,0x00, - 0x00,0x00,0xff,0xff,0xff,0xff,0x03,0x03,0x0f,0x0f,0xff,0xff,0xf0,0xf0,0x00,0x00, - 0x0c,0x0c,0x0f,0x0f,0x0f,0x0f,0x00,0x00,0x00,0x00,0x0f,0x0f,0x0f,0x0f,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x3c,0x3c,0xff,0xff,0xc3,0xc3,0x03,0x03,0x03,0x03,0x3f,0x3f,0x3c,0x3c,0x00,0x00, - 0xc0,0xc0,0xc0,0xc0,0x03,0x03,0x03,0x03,0x0f,0x0f,0xfc,0xfc,0xf0,0xf0,0x00,0x00, - 0x03,0x03,0x0f,0x0f,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0f,0x0f,0x03,0x03,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x3f,0x3f,0x0f,0x0f,0xff,0xff,0xff,0xff,0x0f,0x0f,0x3f,0x3f,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x0c,0x0c,0x0f,0x0f,0x0f,0x0f,0x0c,0x0c,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00, - 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00, - 0x03,0x03,0x0f,0x0f,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0f,0x0f,0x03,0x03,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00, - 0x3f,0x3f,0xff,0xff,0xc0,0xc0,0x00,0x00,0xc0,0xc0,0xff,0xff,0x3f,0x3f,0x00,0x00, - 0x00,0x00,0x00,0x00,0x03,0x03,0x0f,0x0f,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00, - 0xff,0xff,0xff,0xff,0xc0,0xc0,0xfc,0xfc,0xc0,0xc0,0xff,0xff,0xff,0xff,0x00,0x00, - 0x00,0x00,0x0f,0x0f,0x0f,0x0f,0x00,0x00,0x0f,0x0f,0x0f,0x0f,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x0f,0x0f,0xff,0xff,0xf0,0xf0,0x00,0x00,0xf0,0xf0,0xff,0xff,0x0f,0x0f,0x00,0x00, - 0x00,0x00,0xf0,0xf0,0xff,0xff,0x0f,0x0f,0xff,0xff,0xf0,0xf0,0x00,0x00,0x00,0x00, - 0x0f,0x0f,0x0f,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x0f,0x0f,0x0f,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00, - 0x00,0x00,0x00,0x00,0x03,0x03,0xff,0xff,0xff,0xff,0x03,0x03,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x0c,0x0c,0x0f,0x0f,0x0f,0x0f,0x0c,0x0c,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x3f,0x3f,0x0f,0x0f,0x03,0x03,0x03,0x03,0xc3,0xc3,0xff,0xff,0x3f,0x3f,0x00,0x00, - 0xc0,0xc0,0xf0,0xf0,0x3c,0x3c,0x0f,0x0f,0x03,0x03,0x00,0x00,0xc0,0xc0,0x00,0x00, - 0x0f,0x0f,0x0f,0x0f,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0f,0x0f,0x0f,0x0f,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x0f,0x0f,0x0f,0x0f,0x0c,0x0c,0x0c,0x0c,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0xfc,0xfc,0xf0,0xf0,0xc0,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x03,0x03,0x0f,0x0f,0x3f,0x3f,0xfc,0xfc,0xf0,0xf0,0xc0,0xc0,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x0f,0x0f,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x0c,0x0c,0x0c,0x0c,0x0f,0x0f,0x0f,0x0f,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0xc0,0xc0,0xf0,0xf0,0xc0,0xc0,0x00,0x00,0x00,0x00,0x00,0x00, - 0x0c,0x0c,0x0f,0x0f,0x03,0x03,0x00,0x00,0x03,0x03,0x0f,0x0f,0x0c,0x0c,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, - 0x00,0x00,0x00,0x00,0xf0,0xf0,0xf0,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00,0x00,0x00, - 0xf0,0xf0,0xfc,0xfc,0x0c,0x0c,0x0c,0x0c,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00, - 0x03,0x03,0x0f,0x0f,0x0c,0x0c,0x0c,0x0c,0x03,0x03,0x0f,0x0f,0x0c,0x0c,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x03,0x03,0xff,0xff,0xff,0xff,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x03,0x03,0xff,0xff,0xfc,0xfc,0x00,0x00, - 0x0c,0x0c,0x0f,0x0f,0x03,0x03,0x0c,0x0c,0x0c,0x0c,0x0f,0x0f,0x03,0x03,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00, - 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x00,0x00, - 0x03,0x03,0x0f,0x0f,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0f,0x0f,0x03,0x03,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0xc0,0xc0,0xc3,0xc3,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00, - 0xfc,0xfc,0xff,0xff,0x03,0x03,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00, - 0x03,0x03,0x0f,0x0f,0x0c,0x0c,0x0c,0x0c,0x03,0x03,0x0f,0x0f,0x0c,0x0c,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00, - 0xff,0xff,0xff,0xff,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0f,0x0f,0x0f,0x0f,0x00,0x00, - 0x03,0x03,0x0f,0x0f,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0f,0x0f,0x03,0x03,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0xfc,0xfc,0xff,0xff,0x03,0x03,0x0f,0x0f,0x3c,0x3c,0x00,0x00,0x00,0x00, - 0x03,0x03,0xff,0xff,0xff,0xff,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x0c,0x0c,0x0f,0x0f,0x0f,0x0f,0x0c,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0xc0,0xc0,0xc0,0xc0,0x00,0x00, - 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00, - 0xc3,0xc3,0xcf,0xcf,0x0c,0x0c,0x0c,0x0c,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00, - 0x00,0x00,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00, - 0x03,0x03,0xff,0xff,0xff,0xff,0x00,0x00,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00, - 0x00,0x00,0xff,0xff,0xff,0xff,0x03,0x03,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00, - 0x0c,0x0c,0x0f,0x0f,0x0f,0x0f,0x00,0x00,0x00,0x00,0x0f,0x0f,0x0f,0x0f,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0xc0,0xc0,0xcf,0xcf,0xcf,0xcf,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x0c,0x0c,0x0f,0x0f,0x0f,0x0f,0x0c,0x0c,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xc0,0xcf,0xcf,0xcf,0xcf,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00, - 0x00,0x00,0xf0,0xf0,0xf0,0xf0,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00, - 0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0x00, - 0x03,0x03,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xc0,0xc0,0xc0,0xc0,0x00,0x00, - 0x00,0x00,0xff,0xff,0xff,0xff,0x3c,0x3c,0xff,0xff,0xc3,0xc3,0x00,0x00,0x00,0x00, - 0x0c,0x0c,0x0f,0x0f,0x0f,0x0f,0x00,0x00,0x00,0x00,0x0f,0x0f,0x0f,0x0f,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x03,0x03,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x0c,0x0c,0x0f,0x0f,0x0f,0x0f,0x0c,0x0c,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00, - 0xff,0xff,0xff,0xff,0x03,0x03,0xff,0xff,0x03,0x03,0xff,0xff,0xff,0xff,0x00,0x00, - 0x0f,0x0f,0x0f,0x0f,0x00,0x00,0x0f,0x0f,0x00,0x00,0x0f,0x0f,0x0f,0x0f,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0xc0,0xc0,0xc0,0xc0,0x00,0x00,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00, - 0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00, - 0x00,0x00,0x0f,0x0f,0x0f,0x0f,0x00,0x00,0x00,0x00,0x0f,0x0f,0x0f,0x0f,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00, - 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00, - 0x03,0x03,0x0f,0x0f,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0f,0x0f,0x03,0x03,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0xc0,0xc0,0xc0,0xc0,0x00,0x00,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00, - 0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00, - 0x00,0x00,0xff,0xff,0xff,0xff,0x0c,0x0c,0x0c,0x0c,0x0f,0x0f,0x03,0x03,0x00,0x00, - 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0xc0,0xc0,0xc0,0xc0,0x00,0x00, - 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00, - 0x03,0x03,0x0f,0x0f,0x0c,0x0c,0x0c,0x0c,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x00,0x00, - 0xc0,0xc0,0xc0,0xc0,0x00,0x00,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00, - 0x00,0x00,0xff,0xff,0xff,0xff,0x03,0x03,0x00,0x00,0x03,0x03,0x0f,0x0f,0x00,0x00, - 0x0c,0x0c,0x0f,0x0f,0x0f,0x0f,0x0c,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00, - 0x03,0x03,0x0f,0x0f,0x3c,0x3c,0x30,0x30,0xf0,0xf0,0xc3,0xc3,0x03,0x03,0x00,0x00, - 0x03,0x03,0x0f,0x0f,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0f,0x0f,0x03,0x03,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0xc0,0xc0,0xc0,0xc0,0xfc,0xfc,0xff,0xff,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x03,0x03,0x0f,0x0f,0x0c,0x0c,0x0f,0x0f,0x03,0x03,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00, - 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00, - 0x03,0x03,0x0f,0x0f,0x0c,0x0c,0x0c,0x0c,0x03,0x03,0x0f,0x0f,0x0c,0x0c,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00,0xc0,0xc0,0xc0,0xc0,0x00,0x00, - 0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00, - 0x00,0x00,0x00,0x00,0x03,0x03,0x0f,0x0f,0x0f,0x0f,0x03,0x03,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xc0,0xc0,0xc0,0x00,0x00, - 0xff,0xff,0xff,0xff,0x00,0x00,0xf0,0xf0,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00, - 0x03,0x03,0x0f,0x0f,0x0f,0x0f,0x03,0x03,0x0f,0x0f,0x0f,0x0f,0x03,0x03,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xc0,0xc0,0xc0,0x00,0x00, - 0x00,0x00,0x03,0x03,0xff,0xff,0xfc,0xfc,0xff,0xff,0x03,0x03,0x00,0x00,0x00,0x00, - 0x0c,0x0c,0x0f,0x0f,0x03,0x03,0x00,0x00,0x03,0x03,0x0f,0x0f,0x0c,0x0c,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xc0,0xc0,0xc0,0x00,0x00, - 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00, - 0x03,0x03,0x0f,0x0f,0x0c,0x0c,0x0c,0x0c,0xcc,0xcc,0xff,0xff,0x3f,0x3f,0x00,0x00, - 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00, - 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00, - 0x03,0x03,0xc3,0xc3,0xf0,0xf0,0x3c,0x3c,0x0f,0x0f,0x03,0x03,0x00,0x00,0x00,0x00, - 0x0f,0x0f,0x0f,0x0f,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0f,0x0f,0x0f,0x0f,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xfc,0xff,0xff,0x03,0x03,0x03,0x03,0x00,0x00, - 0x00,0x00,0x03,0x03,0x03,0x03,0xff,0xff,0xfc,0xfc,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x0f,0x0f,0x0c,0x0c,0x0c,0x0c,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xfc,0xfc,0xfc,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x0f,0x0f,0x0f,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x03,0x03,0x03,0x03,0xff,0xff,0xfc,0xfc,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xfc,0xff,0xff,0x03,0x03,0x03,0x03,0x00,0x00, - 0x00,0x00,0x0c,0x0c,0x0c,0x0c,0x0f,0x0f,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x0c,0x0c,0x0f,0x0f,0x03,0x03,0x0f,0x0f,0x0c,0x0c,0x0f,0x0f,0x03,0x03,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0xc0,0xc0,0xf0,0xf0,0xc0,0xc0,0x00,0x00,0x00,0x00,0x00,0x00, - 0xfc,0xfc,0xff,0xff,0x03,0x03,0x00,0x00,0x03,0x03,0xff,0xff,0xfc,0xfc,0x00,0x00, - 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; -#endif // !__AVR__ - - // 5x7 font (in 6x8 cell) -const uint8_t ucSmallFont[]PROGMEM = { -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x5f,0x06,0x00,0x00,0x07,0x03,0x00, -0x07,0x03,0x00,0x24,0x7e,0x24,0x7e,0x24,0x00,0x24,0x2b,0x6a,0x12,0x00,0x00,0x63, -0x13,0x08,0x64,0x63,0x00,0x36,0x49,0x56,0x20,0x50,0x00,0x00,0x07,0x03,0x00,0x00, -0x00,0x00,0x3e,0x41,0x00,0x00,0x00,0x00,0x41,0x3e,0x00,0x00,0x00,0x08,0x3e,0x1c, - 0x3e,0x08,0x00,0x08,0x08,0x3e,0x08,0x08,0x00,0x00,0xe0,0x60,0x00,0x00,0x00,0x08, - 0x08,0x08,0x08,0x08,0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x20,0x10,0x08,0x04,0x02, - 0x00,0x3e,0x51,0x49,0x45,0x3e,0x00,0x00,0x42,0x7f,0x40,0x00,0x00,0x62,0x51,0x49, - 0x49,0x46,0x00,0x22,0x49,0x49,0x49,0x36,0x00,0x18,0x14,0x12,0x7f,0x10,0x00,0x2f, - 0x49,0x49,0x49,0x31,0x00,0x3c,0x4a,0x49,0x49,0x30,0x00,0x01,0x71,0x09,0x05,0x03, - 0x00,0x36,0x49,0x49,0x49,0x36,0x00,0x06,0x49,0x49,0x29,0x1e,0x00,0x00,0x6c,0x6c, - 0x00,0x00,0x00,0x00,0xec,0x6c,0x00,0x00,0x00,0x08,0x14,0x22,0x41,0x00,0x00,0x24, - 0x24,0x24,0x24,0x24,0x00,0x00,0x41,0x22,0x14,0x08,0x00,0x02,0x01,0x59,0x09,0x06, - 0x00,0x3e,0x41,0x5d,0x55,0x1e,0x00,0x7e,0x11,0x11,0x11,0x7e,0x00,0x7f,0x49,0x49, - 0x49,0x36,0x00,0x3e,0x41,0x41,0x41,0x22,0x00,0x7f,0x41,0x41,0x41,0x3e,0x00,0x7f, - 0x49,0x49,0x49,0x41,0x00,0x7f,0x09,0x09,0x09,0x01,0x00,0x3e,0x41,0x49,0x49,0x7a, - 0x00,0x7f,0x08,0x08,0x08,0x7f,0x00,0x00,0x41,0x7f,0x41,0x00,0x00,0x30,0x40,0x40, - 0x40,0x3f,0x00,0x7f,0x08,0x14,0x22,0x41,0x00,0x7f,0x40,0x40,0x40,0x40,0x00,0x7f, - 0x02,0x04,0x02,0x7f,0x00,0x7f,0x02,0x04,0x08,0x7f,0x00,0x3e,0x41,0x41,0x41,0x3e, - 0x00,0x7f,0x09,0x09,0x09,0x06,0x00,0x3e,0x41,0x51,0x21,0x5e,0x00,0x7f,0x09,0x09, - 0x19,0x66,0x00,0x26,0x49,0x49,0x49,0x32,0x00,0x01,0x01,0x7f,0x01,0x01,0x00,0x3f, - 0x40,0x40,0x40,0x3f,0x00,0x1f,0x20,0x40,0x20,0x1f,0x00,0x3f,0x40,0x3c,0x40,0x3f, - 0x00,0x63,0x14,0x08,0x14,0x63,0x00,0x07,0x08,0x70,0x08,0x07,0x00,0x71,0x49,0x45, - 0x43,0x00,0x00,0x00,0x7f,0x41,0x41,0x00,0x00,0x02,0x04,0x08,0x10,0x20,0x00,0x00, - 0x41,0x41,0x7f,0x00,0x00,0x04,0x02,0x01,0x02,0x04,0x00,0x80,0x80,0x80,0x80,0x80, - 0x00,0x00,0x03,0x07,0x00,0x00,0x00,0x20,0x54,0x54,0x54,0x78,0x00,0x7f,0x44,0x44, - 0x44,0x38,0x00,0x38,0x44,0x44,0x44,0x28,0x00,0x38,0x44,0x44,0x44,0x7f,0x00,0x38, - 0x54,0x54,0x54,0x08,0x00,0x08,0x7e,0x09,0x09,0x00,0x00,0x18,0xa4,0xa4,0xa4,0x7c, - 0x00,0x7f,0x04,0x04,0x78,0x00,0x00,0x00,0x00,0x7d,0x40,0x00,0x00,0x40,0x80,0x84, - 0x7d,0x00,0x00,0x7f,0x10,0x28,0x44,0x00,0x00,0x00,0x00,0x7f,0x40,0x00,0x00,0x7c, - 0x04,0x18,0x04,0x78,0x00,0x7c,0x04,0x04,0x78,0x00,0x00,0x38,0x44,0x44,0x44,0x38, - 0x00,0xfc,0x44,0x44,0x44,0x38,0x00,0x38,0x44,0x44,0x44,0xfc,0x00,0x44,0x78,0x44, - 0x04,0x08,0x00,0x08,0x54,0x54,0x54,0x20,0x00,0x04,0x3e,0x44,0x24,0x00,0x00,0x3c, - 0x40,0x20,0x7c,0x00,0x00,0x1c,0x20,0x40,0x20,0x1c,0x00,0x3c,0x60,0x30,0x60,0x3c, - 0x00,0x6c,0x10,0x10,0x6c,0x00,0x00,0x9c,0xa0,0x60,0x3c,0x00,0x00,0x64,0x54,0x54, - 0x4c,0x00,0x00,0x08,0x3e,0x41,0x41,0x00,0x00,0x00,0x00,0x77,0x00,0x00,0x00,0x00, - 0x41,0x41,0x3e,0x08,0x00,0x02,0x01,0x02,0x01,0x00,0x00,0x3c,0x26,0x23,0x26,0x3c}; - -// Initialization sequences -const unsigned char oled128_initbuf[] = {0x00, 0xae,0xdc,0x00,0x81,0x40, - 0xa1,0xc8,0xa8,0x7f,0xd5,0x50,0xd9,0x22,0xdb,0x35,0xb0,0xda,0x12, - 0xa4,0xa6,0xaf}; - -const unsigned char oled64_initbuf[]={0x00,0xae,0xa8,0x3f,0xd3,0x00,0x40,0xa1,0xc8, - 0xda,0x12,0x81,0xff,0xa4,0xa6,0xd5,0x80,0x8d,0x14, - 0xaf,0x20,0x02}; - -const unsigned char oled32_initbuf[] = { -0x00,0xae,0xd5,0x80,0xa8,0x1f,0xd3,0x00,0x40,0x8d,0x14,0xa1,0xc8,0xda,0x02, -0x81,0x7f,0xd9,0xf1,0xdb,0x40,0xa4,0xa6,0xaf}; - -const unsigned char oled72_initbuf[]={0x00,0xae,0xa8,0x3f,0xd3,0x00,0x40,0xa1,0xc8, - 0xda,0x12,0x81,0xff,0xad,0x30,0xd9,0xf1,0xa4,0xa6,0xd5,0x80,0x8d,0x14, - 0xaf,0x20,0x02}; - -const unsigned char uc1701_initbuf[] = {0xe2, 0x40, 0xa0, 0xc8, 0xa2, 0x2c, 0x2e, 0x2f, 0xf8, 0x00, 0x23, 0x81, 0x28, 0xac, 0x00, 0xa6}; - -const unsigned char hx1230_initbuf[] = {0x2f, 0x90, 0xa6, 0xa4, 0xaf, 0x40, 0xb0, 0x10, 0x00}; -const unsigned char nokia5110_initbuf[] = {0x21, 0xa4, 0xb1, 0x04,0x14,0x20,0x0c}; - -#define MAX_CACHE 192 -static uint8_t u8Cache[MAX_CACHE]; // for faster character drawing -static volatile uint8_t u8End = 0; -static void obdCachedFlush(OBDISP *pOBD, int bRender); -static void obdCachedWrite(OBDISP *pOBD, uint8_t *pData, uint8_t u8Len, int bRender); -void obdSetPosition(OBDISP *pOBD, int x, int y, int bRender); -void obdWriteCommand(OBDISP *pOBD, unsigned char c); -void obdWriteDataBlock(OBDISP *pOBD, unsigned char *ucBuf, int iLen, int bRender); -void InvertBytes(uint8_t *pData, uint8_t bLen); -static void SPI_BitBang(OBDISP *pOBD, uint8_t *pData, int iLen, uint8_t iMOSIPin, uint8_t iSCKPin); -// wrapper/adapter functions to make the code work on Linux -#ifdef _LINUX_ -static uint8_t pgm_read_byte(uint8_t *ptr) -{ - return *ptr; -} -static int16_t pgm_read_word(uint8_t *ptr) -{ - return ptr[0] + (ptr[1]<<8); -} -int I2CReadRegister(BBI2C *pI2C, uint8_t addr, uint8_t reg, uint8_t *pBuf, int iLen) -{ -int rc; - rc = write(file_i2c, ®, 1); - rc = read(file_i2c, pBuf, iLen); - return (rc > 0); -} -int I2CRead(BBI2C *pI2C, uint8_t addr, uint8_t *pBuf, int iLen) -{ -int rc; - rc = read(file_i2c, pBuf, iLen); - return (rc > 0); -} -int I2CInit(BBI2C *pI2C, int32_t iSpeed) -{ -char filename[32]; - - sprintf(filename, "/dev/i2c-%d", iSDAPin); // I2C bus number passed in SDA pin - if ((file_i2c = open(filename, O_RDWR)) < 0) - return 1; - if (ioctl(file_i2c, I2C_SLAVE, iSCLPin) < 0) // set slave address - { - close(file_i2c); - file_i2c = 0; - return 1; - } - return 0; -} -#endif // _LINUX_ - -// Wrapper function to write I2C data -#ifdef _LINUX_ -static void _I2CWrite(BBI2C *pI2C, unsigned char *pData, int iLen) -{ - write(file_i2c, pData, iLen); -} -#else // Arduino -static void _I2CWrite(OBDISP *pOBD, unsigned char *pData, int iLen) -{ -#if !defined( __AVR_ATtiny85__ ) - if (pOBD->com_mode == COM_SPI) // we're writing to SPI, treat it differently - { - if (pOBD->type != SHARP_144x168) - { - digitalWrite(pOBD->iDCPin, (pData[0] == 0) ? LOW : HIGH); // data versus command - digitalWrite(pOBD->iCSPin, LOW); - } -#ifdef HAL_ESP32_HAL_H_ - { - uint8_t ucTemp[1024]; - SPI.transferBytes(&pData[1], ucTemp, iLen-1); - } -#else - SPI.transfer(&pData[1], iLen-1); -#endif - if (pOBD->type != SHARP_144x168) - digitalWrite(pOBD->iCSPin, HIGH); - } - else // must be I2C -#endif // !ATtiny85 - { - if (pOBD->bbi2c.bWire && iLen > 32) // Hardware I2C has write length limits - { - iLen--; // don't count the 0x40 byte the first time through - while (iLen >= 31) // max 31 data byes + data introducer - { - I2CWrite(&pOBD->bbi2c, pOBD->oled_addr, pData, 32); - iLen -= 31; - pData += 31; - pData[0] = 0x40; - } - if (iLen) iLen++; // If remaining data, add the last 0x40 byte - } - if (iLen) // if any data remaining - { - I2CWrite(&pOBD->bbi2c, pOBD->oled_addr, pData, iLen); - } - } // I2C -} /* _I2CWrite() */ -#endif // _LINUX_ - -// -// Create a virtual display of any size -// The memory buffer must be provided at the time of creation -// -void obdCreateVirtualDisplay(OBDISP *pOBD, int width, int height, uint8_t *buffer) -{ - if (pOBD != NULL && buffer != NULL) - { - pOBD->width = width; - pOBD->height = height; - pOBD->type = LCD_VIRTUAL; - pOBD->ucScreen = buffer; - pOBD->iCursorX = pOBD->iCursorY = 0; - pOBD->iScreenOffset = 0; - } -} /* obdCreateVirtualDisplay() */ -// -// Draw the contents of a memory buffer onto a display -// The sub-window will be clipped if it specifies too large an area -// for the destination display. The source OBDISP structure must have -// a valid back buffer defined -// The top and bottom destination edges will be drawn on byte boundaries (8 rows) -// The source top/bot edges can be on pixel boundaries -// This can be used for partial screen updates -// -void obdDumpWindow(OBDISP *pOBDSrc, OBDISP *pOBDDest, int srcx, int srcy, int destx, int desty, int width, int height) -{ -uint8_t *s,ucTemp[32]; // temp buffer to gather source pixels -int x, y, tx, i; -int iPitch; - - if (pOBDSrc == NULL || pOBDDest == NULL || pOBDSrc->ucScreen == NULL) - return; // invalid pointers - if (width > pOBDDest->width) - width = pOBDDest->width; - if (height > pOBDDest->height) - height = pOBDDest->height; - iPitch = pOBDSrc->width; - if (iPitch < 128) iPitch = 128; - for (y=0; yucScreen[((srcy+y)/8)*iPitch + srcx+x]; - if (srcy & 7) // need to shift the bits to get 8 rows of src data - { - uint8_t uc, ucShift = srcy & 7; - for (i=0; i> ucShift; - uc |= s[iPitch] << (7-ucShift); - ucTemp[i] = uc; - } - obdCachedWrite(pOBDDest, ucTemp, tx, 1); - } - else - { // simpler case - obdCachedWrite(pOBDDest, s, tx, 1); // just copy it - } - } // for x - } // for y - obdCachedFlush(pOBDDest, 1); -} /* obdDumpWindow() */ - -static void obdCachedFlush(OBDISP *pOBD, int bRender) -{ - if (u8End > 0) { - obdWriteDataBlock(pOBD, u8Cache, u8End, bRender); - u8End = 0; - } -} /* obdCachedFlush() */ - -static void obdCachedWrite(OBDISP *pOBD, uint8_t *pData, uint8_t u8Len, int bRender) -{ - if (u8End + u8Len > MAX_CACHE) // need to flush it - { - obdCachedFlush(pOBD, bRender); // write the old data - } - memcpy(&u8Cache[u8End], pData, u8Len); - u8End += u8Len; - -} /* obdCachedWrite() */ -// -// Turn the display on or off -// -void obdPower(OBDISP *pOBD, int bOn) -{ -uint8_t ucCMD; - - if (pOBD->type == LCD_NOKIA5110) - ucCMD = (bOn) ? 0x20 : 0x24; - else // all other supported displays - ucCMD = (bOn) ? 0xaf : 0xae; - obdWriteCommand(pOBD, ucCMD); -} /* obdPower() */ -#if !defined( _LINUX_ ) - -// Controls the LED backlight -void obdBacklight(OBDISP *pOBD, int bOn) -{ - if (pOBD->iLEDPin != 0xff) - { - digitalWrite(pOBD->iLEDPin, (bOn) ? HIGH:LOW); - } -} /* obdBacklight() */ - -// Sets the D/C pin to data or command mode -static void obdSetDCMode(OBDISP *pOBD, int iMode) -{ - if (pOBD->iDCPin == 0xff) // 9-bit SPI - pOBD->mode = (uint8_t)iMode; - else // set the GPIO line - digitalWrite(pOBD->iDCPin, (iMode == MODE_DATA)); -} /* obdSetDCMode() */ - -// -// Send the command sequence to power up the LCDs -static void LCDPowerUp(OBDISP *pOBD) -{ - int iLen; - uint8_t *s; - obdSetDCMode(pOBD, MODE_COMMAND); - digitalWrite(pOBD->iCSPin, LOW); - if (pOBD->type == LCD_UC1701 || pOBD->type == LCD_UC1609) - { - s = (uint8_t *)uc1701_initbuf; - iLen = sizeof(uc1701_initbuf); - } - else if (pOBD->type == LCD_HX1230) - { - s = (uint8_t *)hx1230_initbuf; - iLen = sizeof(hx1230_initbuf); - } - else // Nokia 5110 - { - s = (uint8_t *)nokia5110_initbuf; - iLen = sizeof(nokia5110_initbuf); - } - if (pOBD->iMOSIPin == 0xff) - SPI.transfer(s, iLen); - else - SPI_BitBang(pOBD, (uint8_t *)uc1701_initbuf, iLen, pOBD->iMOSIPin, pOBD->iCLKPin); - delay(100); - obdWriteCommand(pOBD, 0xa5); - delay(100); - obdWriteCommand(pOBD, 0xa4); - obdWriteCommand(pOBD, 0xaf); - digitalWrite(pOBD->iCSPin, HIGH); - obdSetDCMode(pOBD, MODE_DATA); -} /* LCDPowerUp() */ - -// -// Initialize the display controller on an SPI bus -// -void obdSPIInit(OBDISP *pOBD, int iType, int iDC, int iCS, int iReset, int iMOSI, int iCLK, int iLED, int bFlip, int bInvert, int bBitBang, int32_t iSpeed) -{ -uint8_t uc[32], *s; -int iLen; - - pOBD->ucScreen = NULL; // start with no backbuffer; user must provide one later - pOBD->iDCPin = iDC; - pOBD->iCSPin = iCS; - pOBD->iMOSIPin = iMOSI; - pOBD->iCLKPin = iCLK; - pOBD->iLEDPin = iLED; - pOBD->type = iType; - pOBD->flip = bFlip; - pOBD->invert = bInvert; - pOBD->wrap = 0; // default - disable text wrap - pOBD->com_mode = COM_SPI; // communication mode - if (pOBD->iDCPin != 0xff) // Note - not needed on Sharp Memory LCDs - pinMode(pOBD->iDCPin, OUTPUT); - pinMode(pOBD->iCSPin, OUTPUT); - digitalWrite(pOBD->iCSPin, (pOBD->type != SHARP_144x168)); - if (bBitBang) - { - pinMode(iMOSI, OUTPUT); - pinMode(iCLK, OUTPUT); - } - - // Reset it - if (iReset != -1) - { - pinMode(iReset, OUTPUT); - digitalWrite(iReset, LOW); - delay(50); - digitalWrite(iReset, HIGH); - delay(50); - } - if (iLED != -1) - { - pinMode(iLED, OUTPUT); - } -// Initialize SPI - if (!bBitBang) { - pOBD->iMOSIPin = 0xff; // mark it as hardware SPI - SPI.begin(); - SPI.beginTransaction(SPISettings(iSpeed, MSBFIRST, SPI_MODE0)); - // SPI.setClockDivider(16); - // SPI.setBitOrder(MSBFIRST); - // SPI.setDataMode(SPI_MODE0); - } - - pOBD->width = 128; // assume 128x64 - pOBD->height = 64; - if (iType == SHARP_144x168) - { - pOBD->width = 168; - pOBD->height = 144; - pOBD->iDCPin = 0xff; // no D/C wire on this display - } - else if (iType == LCD_UC1609) - { - pOBD->width = 192; - pOBD->height = 64; - } - else if (iType == LCD_HX1230) - { - pOBD->width = 96; - pOBD->height = 68; - pOBD->iDCPin = 0xff; // flag this as being 3-wire SPI - } - else if (iType == LCD_NOKIA5110) - { - pOBD->width = 84; - pOBD->height = 48; - } - else if (iType == OLED_96x16) - { - pOBD->width = 96; - pOBD->height = 16; - } - else if (iType == OLED_128x32) - pOBD->height = 32; - else if (iType == OLED_128x128) - pOBD->height = 128; - else if (iType == OLED_64x32) - { - pOBD->width = 64; - pOBD->height = 32; - } - else if (iType == OLED_72x40) - { - pOBD->width = 72; - pOBD->height = 40; - } - if (iType == OLED_128x32 || iType == OLED_96x16) - { - s = (uint8_t *)oled32_initbuf; - iLen = sizeof(oled32_initbuf); - } - else if (iType == OLED_128x128) - { - s = (uint8_t *)oled128_initbuf; - iLen = sizeof(oled128_initbuf); - } - else if (iType < LCD_UC1701) - { - s = (uint8_t *)oled64_initbuf; - iLen = sizeof(oled64_initbuf); - } - // OLED - if (iType < LCD_UC1701) - { - memcpy(uc, s, iLen); // do it from RAM - _I2CWrite(pOBD, s, iLen); - - if (bInvert) - { - uc[0] = 0; // command - uc[1] = 0xa7; // invert command - _I2CWrite(pOBD, uc, 2); - } - if (bFlip) // rotate display 180 - { - uc[0] = 0; // command - uc[1] = 0xa0; - _I2CWrite(pOBD, uc, 2); - uc[0] = 0; - uc[1] = 0xc0; - _I2CWrite(pOBD, uc, 2); - } - } // OLED - if (iType == LCD_UC1701 || iType == LCD_HX1230) - { - uint8_t cCOM = 0xc0; - - LCDPowerUp(pOBD); - if (iType == LCD_HX1230) - { - obdSetContrast(pOBD, 0); // contrast of 0 looks good - cCOM = 0xc8; - } - if (bFlip) // flip horizontal + vertical - { - obdWriteCommand(pOBD, 0xa1); // set SEG direction (A1 to flip horizontal) - obdWriteCommand(pOBD, cCOM); // set COM direction (C0 to flip vert) - } - if (bInvert) - { - obdWriteCommand(pOBD, 0xa7); // set inverted pixel mode - } - } - if (iType == LCD_UC1609) - { - obdWriteCommand(pOBD, 0xe2); // system reset - obdWriteCommand(pOBD, 0xa0); // set frame rate to 76fps - obdWriteCommand(pOBD, 0xeb); // set BR - obdWriteCommand(pOBD, 0x2f); // set Power Control - obdWriteCommand(pOBD, 0xc4); // set LCD mapping control - obdWriteCommand(pOBD, 0x81); // set PM - obdWriteCommand(pOBD, 0x90); // set contrast to 144 - obdWriteCommand(pOBD, 0xaf); // display enable - if (bFlip) // flip horizontal + vertical - { - obdWriteCommand(pOBD, 0xa1); // set SEG direction (A1 to flip horizontal) - obdWriteCommand(pOBD, 0xc2); // set COM direction (C0 to flip vert) - } - if (bInvert) - { - obdWriteCommand(pOBD, 0xa7); // set inverted pixel mode - } - - } -} /* obdSPIInit() */ -#endif -// Currently only supported on ESP32 -#ifdef HAL_ESP32_HAL_H_ -// Called for each device found during a BLE scan by the client -class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks -{ - void onResult(BLEAdvertisedDevice advertisedDevice) { - Serial.printf("Scan Result: %s \n", advertisedDevice.toString().c_str()); - if (Scanned_BLE_Name[0] == 0 && strcmp(VD_BLE_Name.c_str(), advertisedDevice.getName().c_str()) == 0) { // this is what we want - Server_BLE_Address = new BLEAddress(advertisedDevice.getAddress()); - Scanned_BLE_Address = Server_BLE_Address->toString().c_str(); - strcpy(Scanned_BLE_Name, advertisedDevice.getName().c_str()); - Serial.printf("Found what we're looking for!\n"); - pBLEScan->stop(); // stop scanning - } - } -}; - -// When the scan has found the BLE server device name we're looking for, we try to connect -bool connectToserver (BLEAddress pAddress) -{ - BLEClient* pClient = BLEDevice::createClient(); - Serial.println(" - Created client"); - - // Connect to the BLE Server. - pClient->connect(pAddress, BLE_ADDR_TYPE_RANDOM); // needed for iOS/Android/MacOS - Serial.print(" - Connected to "); Serial.println(VD_BLE_Name.c_str()); - // Obtain a reference to the service we are after in the remote BLE server. - BLERemoteService* pRemoteService = pClient->getService(serviceUUID); - Serial.println("Returned from getService()"); - if (pRemoteService != NULL) - { - Serial.println(" - Found our service"); - if (pClient->isConnected()) - { - Serial.println(" - We're connected"); - // Obtain a reference to the characteristic in the service of the remote BLE server. - pCharacteristicData = pRemoteService->getCharacteristic(dataUUID); - if (pCharacteristicData != nullptr) - { - Serial.println(" - Found our data characteristic"); - } - pCharacteristicName = pRemoteService->getCharacteristic(nameUUID); - if (pCharacteristicName != nullptr) - { - Serial.println(" - Found our name characteristic"); - } - return true; - } // client is connected - } // if remote service is not NULL - return false; -} /* connectToserver() */ - -// -// Initialize the BLE connection to the virtual display server -// -static int _BLEInit(char *name) -{ - - bConnected = 0; - pCharacteristicData = NULL; - pCharacteristicName = NULL; - BLEDevice::init("OneBitDisplay"); - Scanned_BLE_Name[0] = 0; - pBLEScan = BLEDevice::getScan(); //create new scan - pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks()); //Call the class that is defined above - pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster - foundDevices = pBLEScan->start(3); //Scan for 3 seconds to find the Fitness band - - while (!paired && foundDevices.getCount() >= 1) - { - if (strcmp(Scanned_BLE_Name,VD_BLE_Name.c_str()) == 0) // found the device we want - { -// pBLEScan->stop(); // stop scanning - yield(); - Serial.println("Found Device :-)... connecting to Server as client"); - Scanned_BLE_Name[0] = 0; // don't reconnect until we scan again - if (connectToserver(*Server_BLE_Address)) - { - paired = true; - break; - } - } - } - if (pCharacteristicName != nullptr) - { - bConnected = 1; - pCharacteristicName->writeValue((uint8_t *)name, strlen(name), false); // we don't expect a response - } - return 0; -} /* _BLEInit() */ -#endif // ESP32 - -#ifdef ARDUINO_ARDUINO_NANO33BLE -// -// Initialize the BLE connection to the virtual display server -// -static int _BLEInit(char *name) -{ -unsigned long ulTime; -int bFound = 0; - -Serial.println("Entering _BLEInit()"); - - bConnected = 0; - Serial.println("About to call BLE.begin()"); - BLE.begin(); - BLE.setLocalName("Nano33BLE"); - Serial.println("About to start scan"); - BLE.scanForName("VirtualDisplay", true); - ulTime = millis(); - while (!bFound && (millis() - ulTime) < 5000UL) - { - // check if a peripheral has been discovered - peripheral = BLE.available(); - if (peripheral) - { - // discovered a peripheral, print out address, local name, and advertised service - Serial.print("Found "); - Serial.print(peripheral.address()); - Serial.print(" '"); - Serial.print(peripheral.localName()); - Serial.print("' "); - Serial.print(peripheral.advertisedServiceUuid()); - Serial.println(); - if (memcmp(peripheral.localName().c_str(), "VirtualDisplay", 14) == 0) - { // found the one we're looking for - BLE.stopScan(); - bFound = 1; - } // found it in scan - } // peripheral located - else - { - delay(50); - } - } // while scanning - if (bFound) - { - // Connect to the BLE Server. - Serial.println("connection attempt..."); - if (peripheral.connect()) - { - Serial.println("Connected!"); - peripheral.discoverAttributes(); - if (peripheral.discoverService("fea0")) - { - Serial.println("Discovered fea0 service"); - prtService = peripheral.service("0000fea0-0000-1000-8000-00805f9b34fb"); // get the virtual display service - if (prtService) -// if (1) - { - Serial.println("Got the service"); - pCharacteristicData = prtService.characteristic("0000fea1-0000-1000-8000-00805f9b34fb"); - pCharacteristicName = prtService.characteristic("0000fea2-0000-1000-8000-00805f9b34fb"); - if (pCharacteristicData) - { - Serial.println("Got the characteristics"); - Serial.print("Properties = 0x"); - Serial.println(pCharacteristicData.properties(), HEX); - bConnected = 1; - } - } else { - Serial.println("Couldn't get service"); - } - } - } - } - if (bConnected) - { - pCharacteristicName.writeValue((uint8_t *)name, strlen(name)); // we don't expect a response - } - return 0; -} /* _BLEInit() */ -#endif // Nano 33 BLE -#if defined(HAL_ESP32_HAL_H_) || defined (ARDUINO_ARDUINO_NANO33BLE) -// -// Initializes a virtual display over BLE -// Currently only OLED_128x64 is supported -// -int obdBLEInit(OBDISP *pOBD, int iType, int bFlip, int bInvert, char *name) -{ - pOBD->ucScreen = NULL; - pOBD->type = iType; - pOBD->flip = bFlip; - pOBD->wrap = 0; - pOBD->com_mode = COM_BLE; // Bluetooth Low Energy mode - pOBD->width = 128; // DEBUG - pOBD->height = 64; - - return _BLEInit(name); // initialize the BLE connection -} /* obdBLEInit() */ -#endif // ESP32 and Nano 33 BLE -// -// Initializes a virtual display over UART -// Currently only OLED_128x64 is supported -// -#ifndef W600_EV -int obdUARTInit(OBDISP *pOBD, int iType, int bFlip, int bInvert, unsigned long ulSpeed) -{ - pOBD->ucScreen = NULL; - pOBD->type = iType; - pOBD->flip = bFlip; - pOBD->invert = bInvert; - pOBD->wrap = 0; - pOBD->com_mode = COM_UART; - pOBD->width = 128; // DEBUG - pOBD->height = 64; - Serial.begin(ulSpeed); - - return 0; -} /* obdUARTInit() */ -#endif // W600_EV -// -// Initializes the OLED controller into "page mode" -// -int obdI2CInit(OBDISP *pOBD, int iType, int iAddr, int bFlip, int bInvert, int bWire, int sda, int scl, int reset, int32_t iSpeed) -{ -unsigned char uc[4]; -int rc = OLED_NOT_FOUND; - - pOBD->ucScreen = NULL; // reset backbuffer; user must provide one later - pOBD->type = iType; - pOBD->flip = bFlip; - pOBD->invert = bInvert; - pOBD->wrap = 0; // default - disable text wrap - pOBD->bbi2c.iSDA = sda; - pOBD->bbi2c.iSCL = scl; - pOBD->bbi2c.bWire = bWire; - pOBD->com_mode = COM_I2C; // communication mode - - I2CInit(&pOBD->bbi2c, iSpeed); // on Linux, SDA = bus number, SCL = device address -#ifdef _LINUX_ - pOBD->oled_addr = (uint8_t)scl; -#else - // Reset it - if (reset != -1) - { - pinMode(reset, OUTPUT); - digitalWrite(reset, HIGH); - delay(50); - digitalWrite(reset, LOW); - delay(50); - digitalWrite(reset, HIGH); - delay(10); - } - // find the device address if requested - if (iAddr == -1 || iAddr == 0 || iAddr == 0xff) // find it - { - I2CTest(&pOBD->bbi2c, 0x3c); - if (I2CTest(&pOBD->bbi2c, 0x3c)) - pOBD->oled_addr = 0x3c; - else if (I2CTest(&pOBD->bbi2c, 0x3d)) - pOBD->oled_addr = 0x3d; - else - return rc; // no display found! - } - else - { - pOBD->oled_addr = iAddr; - I2CTest(&pOBD->bbi2c, iAddr); - if (!I2CTest(&pOBD->bbi2c, iAddr)) - return rc; // no display found - } -#endif - // Detect the display controller (SSD1306, SH1107 or SH1106) - uint8_t u = 0; - I2CReadRegister(&pOBD->bbi2c, pOBD->oled_addr, 0x00, &u, 1); // read the status register - u &= 0x0f; // mask off power on/off bit - if ((u == 0x7 || u == 0xf) && pOBD->type == OLED_128x128) // SH1107 - { // A single SSD1306 display returned 7, so only act on it if the - // user specified that they're working with a 128x128 display - rc = OLED_SH1107_3C; - bFlip = !bFlip; // SH1107 seems to have this reversed from the usual direction - } - else if (u == 0x8) // SH1106 - { - rc = OLED_SH1106_3C; - pOBD->type = OLED_132x64; // needs to be treated a little differently - } - else if (u == 3 || u == 6 || u == 7) // 7=128x64(rare),6=128x64 display, 3=smaller - { - rc = OLED_SSD1306_3C; - } - if (pOBD->oled_addr == 0x3d) - rc++; // return the '3D' version of the type - - if (iType == OLED_128x32 || iType == OLED_96x16) - _I2CWrite(pOBD,(unsigned char *)oled32_initbuf, sizeof(oled32_initbuf)); - else if (iType == OLED_128x128) - _I2CWrite(pOBD,(unsigned char *)oled128_initbuf, sizeof(oled128_initbuf)); - else if (iType == OLED_72x40) - _I2CWrite(pOBD,(unsigned char *)oled72_initbuf, sizeof(oled72_initbuf)); - else // 132x64, 128x64 and 64x32 - _I2CWrite(pOBD,(unsigned char *)oled64_initbuf, sizeof(oled64_initbuf)); - if (bInvert) - { - uc[0] = 0; // command - uc[1] = 0xa7; // invert command - _I2CWrite(pOBD,uc, 2); - } - if (bFlip) // rotate display 180 - { - uc[0] = 0; // command - uc[1] = 0xa0; - _I2CWrite(pOBD,uc, 2); - uc[1] = 0xc0; - _I2CWrite(pOBD,uc, 2); - } - pOBD->width = 128; // assume 128x64 - pOBD->height = 64; - if (iType == OLED_96x16) - { - pOBD->width = 96; - pOBD->height = 16; - } - else if (iType == OLED_128x32) - pOBD->height = 32; - else if (iType == OLED_128x128) - pOBD->height = 128; - else if (iType == OLED_64x32) - { - pOBD->width = 64; - pOBD->height = 32; - } - else if (iType == OLED_72x40) - { - pOBD->width = 72; - pOBD->height = 40; - } - return rc; -} /* obdInit() */ -// -// Sends a command to turn on or off the OLED display -// -void oledPower(OBDISP *pOBD, uint8_t bOn) -{ - if (bOn) - obdWriteCommand(pOBD, 0xaf); // turn on OLED - else - obdWriteCommand(pOBD, 0xae); // turn off OLED -} /* oledPower() */ - -// -// Bit Bang the data on GPIO pins -// -static void SPI_BitBang(OBDISP *pOBD, uint8_t *pData, int iLen, uint8_t iMOSIPin, uint8_t iSCKPin) -{ -int i; -uint8_t c; -// We can access the GPIO ports much quicker on AVR by directly manipulating -// the port registers -#ifdef __AVR__ -volatile uint8_t *outSCK, *outMOSI; // port registers for fast I/O -uint8_t port, bitSCK, bitMOSI; // bit mask for the chosen pins - - port = digitalPinToPort(iMOSIPin); - outMOSI = portOutputRegister(port); - bitMOSI = digitalPinToBitMask(iMOSIPin); - port = digitalPinToPort(iSCKPin); - outSCK = portOutputRegister(port); - bitSCK = digitalPinToBitMask(iSCKPin); - -#endif - - while (iLen) - { - c = *pData++; - if (pOBD->iDCPin == 0xff) // 3-wire SPI, write D/C bit first - { -#ifdef __AVR__ - if (pOBD->mode == MODE_DATA) - *outMOSI |= bitMOSI; - else - *outMOSI &= ~bitMOSI; - *outSCK |= bitSCK; // toggle clock - *outSCK &= ~bitSCK; // no delay needed on SPI devices since AVR is slow -#else - digitalWrite(iMOSIPin, (pOBD->mode == MODE_DATA)); - digitalWrite(iSCKPin, HIGH); - delayMicroseconds(0); - digitalWrite(iSCKPin, LOW); -#endif - } - if (c == 0 || c == 0xff) // quicker for all bits equal - { -#ifdef __AVR__ - if (c & 1) - *outMOSI |= bitMOSI; - else - *outMOSI &= ~bitMOSI; - for (i=0; i<8; i++) - { - *outSCK |= bitSCK; - *outSCK &= ~bitSCK; - } -#else - digitalWrite(iMOSIPin, (c & 1)); - for (i=0; i<8; i++) - { - digitalWrite(iSCKPin, HIGH); - delayMicroseconds(0); - digitalWrite(iSCKPin, LOW); - } -#endif - } - else - { - for (i=0; i<8; i++) - { -#ifdef __AVR__ - if (c & 0x80) // MSB first - *outMOSI |= bitMOSI; - else - *outMOSI &= ~bitMOSI; - *outSCK |= bitSCK; - c <<= 1; - *outSCK &= ~bitSCK; -#else - digitalWrite(iMOSIPin, (c & 0x80) != 0); // MSB first - digitalWrite(iSCKPin, HIGH); - c <<= 1; - delayMicroseconds(0); - digitalWrite(iSCKPin, LOW); -#endif - } - } - iLen--; - } -} /* SPI_BitBang() */ - -// Send a single byte command to the OLED controller -void obdWriteCommand(OBDISP *pOBD, unsigned char c) -{ -unsigned char buf[4]; - -#if defined(HAL_ESP32_HAL_H_) || defined (ARDUINO_ARDUINO_NANO33BLE) - if (pOBD->com_mode == COM_BLE) { // Bluetooth - buf[0] = 0x00; // cmd - buf[1] = c; // command byte - if (bConnected) { -#ifdef HAL_ESP32_HAL_H_ - pCharacteristicData->writeValue(buf, 2, false); -#else - pCharacteristicData.writeValue(buf, 2); -#endif - } - } -#endif // ESP32 & Nano 33 - - if (pOBD->com_mode == COM_I2C) {// I2C device - buf[0] = 0x00; // command introducer - buf[1] = c; - _I2CWrite(pOBD, buf, 2); -#ifndef W600_EV - } else if (pOBD->com_mode == COM_UART) { - buf[0] = 2; // length of data to com - buf[1] = 0x00; // command - buf[2] = c; // command byte - Serial.write(buf, 3); -#endif // W600_EV - } else { // must be SPI - obdSetDCMode(pOBD, MODE_COMMAND); - digitalWrite(pOBD->iCSPin, LOW); - if (pOBD->iMOSIPin == 0xff) - SPI.transfer(c); - else - SPI_BitBang(pOBD, &c, 1, pOBD->iMOSIPin, pOBD->iCLKPin); - digitalWrite(pOBD->iCSPin, HIGH); - obdSetDCMode(pOBD, MODE_DATA); - } -} /* obdWriteCommand() */ - -static void obdWriteCommand2(OBDISP *pOBD, unsigned char c, unsigned char d) -{ -unsigned char buf[4]; - -#if defined(HAL_ESP32_HAL_H_) || defined (ARDUINO_ARDUINO_NANO33BLE) - if (pOBD->com_mode == COM_BLE) { // Bluetooth - buf[0] = 0x00; // cmd - buf[1] = c; // command byte - buf[2] = d; - if (bConnected) { -#ifdef HAL_ESP32_HAL_H_ - pCharacteristicData->writeValue(buf, 3, false); -#else - pCharacteristicData.writeValue(buf, 3); -#endif - } - } -#endif // ESP32 & Nano 33 - - if (pOBD->com_mode == COM_I2C) {// I2C device - buf[0] = 0x00; - buf[1] = c; - buf[2] = d; - _I2CWrite(pOBD, buf, 3); -#ifndef W600_EV - } else if (pOBD->com_mode == COM_UART) { - buf[0] = 3; // length - buf[1] = 0x00; - buf[2] = c; - buf[3] = d; - Serial.write(buf, 4); -#endif // W600_EV - } else { // must be SPI - obdWriteCommand(pOBD, c); - obdWriteCommand(pOBD, d); - } -} /* obdWriteCommand2() */ - -// -// Sets the brightness (0=off, 255=brightest) -// -void obdSetContrast(OBDISP *pOBD, unsigned char ucContrast) -{ - if (pOBD->type == LCD_HX1230) - { // valid values are 0-31, so scale it - ucContrast >>= 3; - obdWriteCommand(pOBD, 0x80 + ucContrast); - } - else if (pOBD->type == LCD_NOKIA5110) - { - // we allow values of 0xb0-0xbf, so shrink the range - ucContrast >>= 4; - obdWriteCommand(pOBD, 0x21); // set advanced command mode - obdWriteCommand(pOBD, 0xb0 | ucContrast); - obdWriteCommand(pOBD, 0x20); // set simple command mode - } - else // OLEDs + UC1701 - obdWriteCommand2(pOBD, 0x81, ucContrast); -} /* obdSetContrast() */ -// -// Scroll the internal buffer by 1 scanline (up/down) -// width is in pixels, lines is group of 8 rows -// -int obdScrollBuffer(OBDISP *pOBD, int iStartCol, int iEndCol, int iStartRow, int iEndRow, int bUp) -{ - uint8_t b, *s; - int col, row; - int iPitch; - - if (iStartCol < 0 || iStartCol >= pOBD->width || iEndCol < 0 || iEndCol > pOBD->width || iStartCol > iEndCol) // invalid - return -1; - if (iStartRow < 0 || iStartRow >= (pOBD->height/8) || iEndRow < 0 || iEndRow >= (pOBD->height/8) || iStartRow > iEndRow) - return -1; - iPitch = pOBD->width; - if (iPitch < 128) iPitch = 128; - if (bUp) - { - for (row=iStartRow; row<=iEndRow; row++) - { - s = &pOBD->ucScreen[(row * iPitch) + iStartCol]; - for (col=iStartCol; col<=iEndCol; col++) - { - b = *s; - b >>= 1; // scroll pixels 'up' - if (row < iEndRow) - b |= (s[iPitch] << 7); // capture pixel of row below, except for last row - *s++ = b; - } // for col - } // for row - } // up - else // down - { - for (row=iEndRow; row>=iStartRow; row--) - { - s = &pOBD->ucScreen[(row * iPitch)+iStartCol]; - for (col=iStartCol; col<=iEndCol; col++) - { - b = *s; - b <<= 1; // scroll down - if (row > iStartRow) - b |= (s[-iPitch] >> 7); // capture pixel of row above - *s++ = b; - } // for col - } // for row - } - return 0; -} /* obdScrollBuffer() */ -// -// Send commands to position the "cursor" (aka memory write address) -// to the given row and column -// -void obdSetPosition(OBDISP *pOBD, int x, int y, int bRender) -{ -unsigned char buf[4]; -int iPitch = pOBD->width; - - obdCachedFlush(pOBD, bRender); // flush any cached data first - - if (iPitch < 128) iPitch = 128; - pOBD->iScreenOffset = (y*iPitch)+x; - - if (pOBD->type == LCD_VIRTUAL || pOBD->type == SHARP_144x168) - return; // nothing to do - if (!bRender) - return; // don't send the commands to the OLED if we're not rendering the graphics now - if (pOBD->type == LCD_NOKIA5110) - { - obdWriteCommand(pOBD, 0x40 | y); - obdWriteCommand(pOBD, 0x80 | x); - return; - } - if (pOBD->type == OLED_64x32) // visible display starts at column 32, row 4 - { - x += 32; // display is centered in VRAM, so this is always true - if (pOBD->flip == 0) // non-flipped display starts from line 4 - y += 4; - } - else if (pOBD->type == OLED_132x64) // SH1106 has 128 pixels centered in 132 - { - x += 2; - } - else if (pOBD->type == OLED_96x16) // visible display starts at line 2 - { // mapping is a bit strange on the 96x16 OLED - if (pOBD->flip) - x += 32; - else - y += 2; - } - else if (pOBD->type == OLED_72x40) // starts at x=28,y=3 - { - x += 28; - if (!pOBD->flip) - { - y += 3; - } - } - if (pOBD->com_mode == COM_I2C) { // I2C device - buf[0] = 0x00; // command introducer - buf[1] = 0xb0 | y; // set page to Y - buf[2] = x & 0xf; // lower column address - buf[3] = 0x10 | (x >> 4); // upper column addr - _I2CWrite(pOBD, buf, 4); - } else { // SPI mode - obdWriteCommand(pOBD, 0xb0 | y); // set Y - obdWriteCommand(pOBD, 0x10 | (x >> 4)); // set X MSB - obdWriteCommand(pOBD, 0x00 | (x & 0xf)); // set X LSB - } -} /* obdSetPosition() */ - -// -// Write a block of pixel data to the OLED -// Length can be anything from 1 to 1024 (whole display) -// -void obdWriteDataBlock(OBDISP *pOBD, unsigned char *ucBuf, int iLen, int bRender) -{ -unsigned char ucTemp[196]; -int iPitch, iBufferSize; - - iPitch = pOBD->width; - if (iPitch < 128) iPitch = 128; - iBufferSize = iPitch * (pOBD->height / 8); - -// Keep a copy in local buffer -if (pOBD->ucScreen && (iLen + pOBD->iScreenOffset) <= iBufferSize) -{ - memcpy(&pOBD->ucScreen[pOBD->iScreenOffset], ucBuf, iLen); - pOBD->iScreenOffset += iLen; - // wrap around ? - if (pOBD->iScreenOffset >= iBufferSize) - pOBD->iScreenOffset -= iBufferSize; -} -if (pOBD->type == LCD_VIRTUAL || pOBD->type == SHARP_144x168) - return; // nothing else to do -// Copying the data has the benefit in SPI mode of not letting -// the original data get overwritten by the SPI.transfer() function - if (bRender) - { -#if defined(HAL_ESP32_HAL_H_) || defined (ARDUINO_ARDUINO_NANO33BLE) - if (pOBD->com_mode == COM_BLE) { // Bluetooth - if (bConnected) { - ucTemp[0] = 0x40; // data command - memcpy(&ucTemp[1], ucBuf, iLen); -#ifdef HAL_ESP32_HAL_H_ - pCharacteristicData->writeValue(ucTemp, iLen+1, false); -#else - pCharacteristicData.writeValue(ucTemp, iLen+1); -#endif - } - } -#endif // ESP32 & Nano 33 - - if (pOBD->com_mode == COM_SPI) // SPI/Bit Bang - { - digitalWrite(pOBD->iCSPin, LOW); - if (pOBD->iMOSIPin != 0xff) // Bit Bang - SPI_BitBang(pOBD, ucBuf, iLen, pOBD->iMOSIPin, pOBD->iCLKPin); - else - SPI.transfer(ucBuf, iLen); - digitalWrite(pOBD->iCSPin, HIGH); - } -#ifndef W600_EV - else if (pOBD->com_mode == COM_UART) - { - ucTemp[0] = iLen+1; // data length - ucTemp[1] = 0x40; - memcpy(&ucTemp[2], ucBuf, iLen); - Serial.write(ucTemp, iLen+2); - } -#endif // W600_EV - else // I2C - { - ucTemp[0] = 0x40; // data command - memcpy(&ucTemp[1], ucBuf, iLen); - _I2CWrite(pOBD, ucTemp, iLen+1); - } - } -} /* obdWriteDataBlock() */ -// -// Byte operands for compressing the data -// The first 2 bits are the type, followed by the counts -#define OP_MASK 0xc0 -#define OP_SKIPCOPY 0x00 -#define OP_COPYSKIP 0x40 -#define OP_REPEATSKIP 0x80 -#define OP_REPEAT 0xc0 -// -// Write a block of flash memory to the display -// -void oledWriteFlashBlock(OBDISP *pOBD, uint8_t *s, int iLen) -{ -int j; -int iWidthMask = pOBD->width -1; -int iSizeMask = ((pOBD->width * pOBD->height)/8) - 1; -int iWidthShift = (pOBD->width == 128) ? 7:6; // assume 128 or 64 wide -uint8_t ucTemp[128]; - - while (((pOBD->iScreenOffset & iWidthMask) + iLen) >= pOBD->width) // if it will hit the page end - { - j = pOBD->width - (pOBD->iScreenOffset & iWidthMask); // amount we can write in one shot - memcpy_P(ucTemp, s, j); - obdWriteDataBlock(pOBD, ucTemp, j, 1); - s += j; - iLen -= j; - pOBD->iScreenOffset = (pOBD->iScreenOffset + j) & iSizeMask; - obdSetPosition(pOBD, pOBD->iScreenOffset & iWidthMask, (pOBD->iScreenOffset >> iWidthShift), 1); - } // while it needs some help - memcpy_P(ucTemp, s, iLen); - obdWriteDataBlock(pOBD, ucTemp, iLen, 1); - pOBD->iScreenOffset = (pOBD->iScreenOffset + iLen) & iSizeMask; -} /* oledWriteFlashBlock() */ - -// -// Write a repeating byte to the display -// -void obdRepeatByte(OBDISP *pOBD, uint8_t b, int iLen) -{ -int j; -int iWidthMask = pOBD->width -1; -int iWidthShift = (pOBD->width == 128) ? 7:6; // assume 128 or 64 pixels wide -int iSizeMask = ((pOBD->width * pOBD->height)/8) -1; -uint8_t ucTemp[128]; - - memset(ucTemp, b, (iLen > 128) ? 128:iLen); - while (((pOBD->iScreenOffset & iWidthMask) + iLen) >= pOBD->width) // if it will hit the page end - { - j = pOBD->width - (pOBD->iScreenOffset & iWidthMask); // amount we can write in one shot - obdWriteDataBlock(pOBD, ucTemp, j, 1); - iLen -= j; - pOBD->iScreenOffset = (pOBD->iScreenOffset + j) & iSizeMask; - obdSetPosition(pOBD, pOBD->iScreenOffset & iWidthMask, (pOBD->iScreenOffset >> iWidthShift), 1); - } // while it needs some help - obdWriteDataBlock(pOBD, ucTemp, iLen, 1); - pOBD->iScreenOffset += iLen; -} /* obdRepeatByte() */ - -// -// Play a frame of animation data -// The animation data is assumed to be encoded for a full frame of the display -// Given the pointer to the start of the compressed data, -// it returns the pointer to the start of the next frame -// Frame rate control is up to the calling program to manage -// When it finishes the last frame, it will start again from the beginning -// -uint8_t * obdPlayAnimFrame(OBDISP *pOBD, uint8_t *pAnimation, uint8_t *pCurrent, int iLen) -{ -uint8_t *s; -int i, j; -unsigned char b, bCode; -int iBufferSize = (pOBD->width * pOBD->height)/8; // size in bytes of the display devce -int iWidthMask, iWidthShift; - - iWidthMask = pOBD->width - 1; - iWidthShift = (pOBD->width == 128) ? 7:6; // 128 or 64 pixels wide - if (pCurrent == NULL || pCurrent > pAnimation + iLen) - return NULL; // invalid starting point - - s = (uint8_t *)pCurrent; // start of animation data - i = 0; - obdSetPosition(pOBD, 0,0,1); - while (i < iBufferSize) // run one frame - { - bCode = pgm_read_byte(s++); - switch (bCode & OP_MASK) // different compression types - { - case OP_SKIPCOPY: // skip/copy - if (bCode == OP_SKIPCOPY) // big skip - { - b = pgm_read_byte(s++); - i += b + 1; - obdSetPosition(pOBD, i & iWidthMask, (i >> iWidthShift), 1); - } - else // skip/copy - { - if (bCode & 0x38) - { - i += ((bCode & 0x38) >> 3); // skip amount - obdSetPosition(pOBD, i & iWidthMask, (i >> iWidthShift), 1); - } - if (bCode & 7) - { - oledWriteFlashBlock(pOBD, s, bCode & 7); - s += (bCode & 7); - i += bCode & 7; - } - } - break; - case OP_COPYSKIP: // copy/skip - if (bCode == OP_COPYSKIP) // big copy - { - b = pgm_read_byte(s++); - j = b + 1; - oledWriteFlashBlock(pOBD, s, j); - s += j; - i += j; - } - else - { - j = ((bCode & 0x38) >> 3); - if (j) - { - oledWriteFlashBlock(pOBD, s, j); - s += j; - i += j; - } - if (bCode & 7) - { - i += (bCode & 7); // skip - obdSetPosition(pOBD, i & iWidthMask, (i >> iWidthShift), 1); - } - } - break; - case OP_REPEATSKIP: // repeat/skip - j = (bCode & 0x38) >> 3; // repeat count - b = pgm_read_byte(s++); - obdRepeatByte(pOBD, b, j); - i += j; - if (bCode & 7) - { - i += (bCode & 7); // skip amount - obdSetPosition(pOBD, i & iWidthMask, (i >> iWidthShift), 1); - } - break; - - case OP_REPEAT: - j = (bCode & 0x3f) + 1; - b = pgm_read_byte(s++); - obdRepeatByte(pOBD, b, j); - i += j; - break; - } // switch on code type - } // while rendering a frame - if (s >= pAnimation + iLen) // we've hit the end, restart from the beginning - s = pAnimation; - return s; // return pointer to start of next frame -} /* obdPlayAnimFrame() */ -// -// Draw a sprite of any size in any position -// If it goes beyond the left/right or top/bottom edges -// it's trimmed to show the valid parts -// This function requires a back buffer to be defined -// The priority color (0 or 1) determines which color is painted -// when a 1 is encountered in the source image. -// -void obdDrawSprite(OBDISP *pOBD, uint8_t *pSprite, int cx, int cy, int iPitch, int x, int y, uint8_t iPriority) -{ - int tx, ty, dx, dy, iStartX; - uint8_t *s, *d, uc, pix, ucSrcMask, ucDstMask; - int iLocalPitch; - - iLocalPitch = pOBD->width; - if (iLocalPitch < 128) iLocalPitch = 128; - - if (x+cx < 0 || y+cy < 0 || x >= pOBD->width || y >= pOBD->height || pOBD->ucScreen == NULL) - return; // no backbuffer or out of bounds - dy = y; // destination y - if (y < 0) // skip the invisible parts - { - cy += y; - y = -y; - pSprite += (y * iPitch); - dy = 0; - } - if (y + cy > pOBD->height) - cy = pOBD->height - y; - iStartX = 0; - dx = x; - if (x < 0) - { - cx += x; - x = -x; - iStartX = x; - dx = 0; - } - if (x + cx > pOBD->width) - cx = pOBD->width - x; - for (ty=0; ty> 3]; - d = &pOBD->ucScreen[(dy>>3) * iLocalPitch + dx]; - ucSrcMask = 0x80 >> (iStartX & 7); - pix = *s++; - ucDstMask = 1 << (dy & 7); - if (iPriority) // priority color is 1 - { - for (tx=0; tx>= 1; - if (ucSrcMask == 0) // read next byte - { - ucSrcMask = 0x80; - pix = *s++; - } - } // for tx - } // priorty color 1 - else - { - for (tx=0; tx>= 1; - if (ucSrcMask == 0) // read next byte - { - ucSrcMask = 0x80; - pix = *s++; - } - } // for tx - } // priority color 0 - dy++; - pSprite += iPitch; - } // for ty -} /* obdDrawSprite() */ -// -// Draw a 16x16 tile in any of 4 rotated positions -// Assumes input image is laid out like "normal" graphics with -// the MSB on the left and 2 bytes per line -// On AVR, the source image is assumed to be in FLASH memory -// The function can draw the tile on byte boundaries, so the x value -// can be from 0 to width-16 and y can be from 0 to (height/8)-2 -// -void obdDrawTile(OBDISP *pOBD, const uint8_t *pTile, int x, int y, int iRotation, int bInvert, int bRender) -{ - uint8_t ucTemp[32]; // prepare LCD data here - uint8_t i, j, k, iOffset, ucMask, uc, ucPixels; - uint8_t bFlipX=0, bFlipY=0; - int iPitch; - - iPitch = pOBD->width; - if (iPitch < 128) iPitch = 128; - if (x < 0 || y < 0 || y > (pOBD->height/8)-2 || x > pOBD->width-16) - return; // out of bounds - if (pTile == NULL) return; // bad pointer; really? :( - if (iRotation == ANGLE_180 || iRotation == ANGLE_270 || iRotation == ANGLE_FLIPX) - bFlipX = 1; - if (iRotation == ANGLE_180 || iRotation == ANGLE_270 || iRotation == ANGLE_FLIPY) - bFlipY = 1; - - memset(ucTemp, 0, sizeof(ucTemp)); // we only set white pixels, so start from black - if (iRotation == ANGLE_0 || iRotation == ANGLE_180 || iRotation == ANGLE_FLIPX || iRotation == ANGLE_FLIPY) - { - for (j=0; j<16; j++) // y - { - for (i=0; i<16; i+=8) // x - { - ucPixels = pgm_read_byte((uint8_t*)pTile++); - ucMask = 0x80; // MSB is the first source pixel - for (k=0; k<8; k++) - { - if (ucPixels & ucMask) // translate the pixel - { - if (bFlipY) - uc = 0x80 >> (j & 7); - else - uc = 1 << (j & 7); - iOffset = i+k; - if (bFlipX) iOffset = 15-iOffset; - iOffset += (j & 8)<<1; // top/bottom half of output - if (bFlipY) - iOffset ^= 16; - ucTemp[iOffset] |= uc; - } - ucMask >>= 1; - } // for k - } // for i - } // for j - } - else // rotated 90/270 - { - for (j=0; j<16; j++) // y - { - for (i=0; i<16; i+=8) // x - { - ucPixels = pgm_read_byte((uint8_t*)pTile++); - ucMask = 0x80; // MSB is the first source pixel - for (k=0; k<8; k++) - { - if (ucPixels & ucMask) // translate the pixel - { - if (bFlipY) - uc = 0x80 >> k; - else - uc = 1 << k; - iOffset = 15-j; - if (bFlipX) iOffset = 15-iOffset; - iOffset += i<<1; // top/bottom half of output - if (bFlipY) - iOffset ^= 16; - ucTemp[iOffset] |= uc; - } - ucMask >>= 1; - } // for k - } // for i - } // for j - } - if (bInvert) InvertBytes(ucTemp, 32); - // Send the data to the display - obdSetPosition(pOBD, x, y, bRender); - obdWriteDataBlock(pOBD, ucTemp, 16, bRender); // top half - obdSetPosition(pOBD, x,y+1, bRender); - obdWriteDataBlock(pOBD, &ucTemp[16], 16, bRender); // bottom half -} /* obdDrawTile() */ - -// Set (or clear) an individual pixel -// The local copy of the frame buffer is used to avoid -// reading data from the display controller -int obdSetPixel(OBDISP *pOBD, int x, int y, unsigned char ucColor, int bRender) -{ -int i; -unsigned char uc, ucOld; -int iPitch, iSize; - - iPitch = pOBD->width; - if (iPitch < 128) iPitch = 128; - iSize = iPitch * (pOBD->height/8); - - i = ((y >> 3) * iPitch) + x; - if (i < 0 || i > iSize-1) // off the screen - return -1; - obdSetPosition(pOBD, x, y>>3, bRender); - - if (pOBD->ucScreen) - uc = ucOld = pOBD->ucScreen[i]; - else if (pOBD->type == OLED_132x64 || pOBD->type == OLED_128x128) // SH1106/SH1107 can read data - { - uint8_t ucTemp[3]; - ucTemp[0] = 0x80; // one command - ucTemp[1] = 0xE0; // read_modify_write - ucTemp[2] = 0xC0; // one data - _I2CWrite(pOBD, ucTemp, 3); - - // read a dummy byte followed by the data byte we want - I2CRead(&pOBD->bbi2c, pOBD->oled_addr, ucTemp, 2); - uc = ucOld = ucTemp[1]; // first byte is garbage - } - else - uc = ucOld = 0; - - uc &= ~(0x1 << (y & 7)); - if (ucColor) - { - uc |= (0x1 << (y & 7)); - } - if (uc != ucOld) // pixel changed - { -// obdSetPosition(x, y>>3); - if (pOBD->ucScreen) - { - obdWriteDataBlock(pOBD, &uc, 1, bRender); - pOBD->ucScreen[i] = uc; - } - else if (pOBD->type == OLED_132x64 || pOBD->type == OLED_128x128) // end the read_modify_write operation - { - uint8_t ucTemp[4]; - ucTemp[0] = 0xc0; // one data - ucTemp[1] = uc; // actual data - ucTemp[2] = 0x80; // one command - ucTemp[3] = 0xEE; // end read_modify_write operation - _I2CWrite(pOBD, ucTemp, 4); - } - } - return 0; -} /* obdSetPixel() */ - -// -// Invert font data -// -void InvertBytes(uint8_t *pData, uint8_t bLen) -{ -uint8_t i; - for (i=0; iwidth; - if (iDestPitch < 128) iDestPitch = 128; - i16 = pgm_read_word(pBMP); - if (i16 != 0x4d42) // must start with 'BM' - return -1; // not a BMP file - cx = pgm_read_word(pBMP + 18); - if (cx + dx > pOBD->width) // must fit on the display - return -1; - cy = pgm_read_word(pBMP + 22); - if (cy < 0) cy = -cy; - else bFlipped = true; - if (cy + dy > pOBD->height) // must fit on the display - return -1; - i16 = pgm_read_word(pBMP + 28); - if (i16 != 1) // must be 1 bit per pixel - return -1; - iOffBits = pgm_read_word(pBMP + 10); - iPitch = ((cx>>3) + 3) & 0xfffc; // must be DWORD aligned - if (bFlipped) - { - iOffBits += ((cy-1) * iPitch); // start from bottom - iPitch = -iPitch; - } - - for (y=0; yucScreen) - d = &pOBD->ucScreen[(((y+dy)>>3)*iDestPitch)+dx]; - else - { - d = u8Cache; - if ((y & 7) == 0) - memset(u8Cache, 0, sizeof(u8Cache)); - } - s = &pBMP[iOffBits + (y*iPitch)]; - src_mask = 0; - for (x=0; x>= 1; - } // for x - if (pOBD->ucScreen == NULL && ((y & 7) == 7 || y == cy-1)) // dump to LCD - { - obdSetPosition(pOBD, dx, (y+dy)>>3, 1); - obdWriteDataBlock(pOBD, u8Cache, cx, 1); - } - } // for y - return 0; -} /* obdLoadBMP() */ -// -// Set the current cursor position -// The column represents the pixel column (0-127) -// The row represents the text row (0-7) -// -void obdSetCursor(OBDISP *pOBD, int x, int y) -{ - pOBD->iCursorX = x; - pOBD->iCursorY = y; -} /* obdSetCursor() */ -// -// Turn text wrap on or off for the oldWriteString() function -// -void obdSetTextWrap(OBDISP *pOBD, int bWrap) -{ - pOBD->wrap = bWrap; -} /* obdSetTextWrap() */ -// -// Draw a string with a fractional scale in both dimensions -// the scale is a 16-bit integer with and 8-bit fraction and 8-bit mantissa -// To draw at 1x scale, set the scale factor to 256. To draw at 2x, use 512 -// The output must be drawn into a memory buffer, not directly to the display -// -int obdScaledString(OBDISP *pOBD, int x, int y, char *szMsg, int iSize, int bInvert, int iXScale, int iYScale) -{ -uint32_t row, col, dx, dy; -uint32_t sx, sy; -uint8_t c, uc, *d; -const uint8_t *s; -uint8_t ucTemp[16]; -int tx, ty, bit, iFontOff; -int iPitch, iOffset; -int iFontWidth; - - if (iXScale == 0 || iYScale == 0 || szMsg == NULL || pOBD == NULL || pOBD->ucScreen == NULL || x < 0 || y < 0 || x >= pOBD->width-1 || y >= pOBD->height-1) - return -1; // invalid display structure - if (iSize != FONT_NORMAL && iSize != FONT_SMALL) - return -1; // only on the small fonts (for now) - iFontWidth = (iSize == FONT_SMALL) ? 6:8; - s = (iSize == FONT_SMALL) ? ucSmallFont : ucFont; - iPitch = pOBD->width; - if (iPitch < 128) iPitch = 128; - dx = (iFontWidth * iXScale) >> 8; // width of each character - dy = (8 * iYScale) >> 8; // height of each character - sx = 65536 / iXScale; // turn the scale into an accumulator value - sy = 65536 / iYScale; - while (*szMsg && x < pOBD->width) { - c = *szMsg++; // debug - start with normal font - iFontOff = (int)(c-32) * iFontWidth; - // we can't directly use the pointer to FLASH memory, so copy to a local buffer - memcpy_P(ucTemp, &s[iFontOff], iFontWidth); - if (bInvert) InvertBytes(ucTemp, iFontWidth); - col = 0; - if (x+dx >= (uint32_t)pOBD->width) // we've hit the right edge - dx = pOBD->width - x; // draw partial character - for (tx=0; tx<(int)dx; tx++) { - row = 0; - uc = ucTemp[col >> 8]; - d = &pOBD->ucScreen[(y >> 3) * iPitch + x + tx]; - for (ty=0; ty<(int)dy; ty++) { - bit = row >> 8; - iOffset = (ty >> 3) * iPitch; - if (uc & (1 << bit)) - d[iOffset] |= (1 << (ty & 7)); - else - d[iOffset] &= ~(1 << (ty & 7)); - row += sy; // add fractional increment to source row of character - } // for ty - col += sx; // add fractional increment to source column - } // for tx - x += dx; - } // while (*szMsg) - return 0; -} /* obdScaledString() */ - -// -// Draw a string of normal (8x8), small (6x8) or large (16x32) characters -// At the given col+row -// -int obdWriteString(OBDISP *pOBD, int iScroll, int x, int y, char *szMsg, int iSize, int bInvert, int bRender) -{ -int i, iFontOff, iLen, iFontSkip; -unsigned char c, *s, ucTemp[40]; - - if (x == -1 || y == -1) // use the cursor position - { - x = pOBD->iCursorX; y = pOBD->iCursorY; - } - else - { - pOBD->iCursorX = x; pOBD->iCursorY = y; // set the new cursor position - } - if (pOBD->iCursorX >= pOBD->width || pOBD->iCursorY >= pOBD->height / 8) - return -1; // can't draw off the display - - obdSetPosition(pOBD, pOBD->iCursorX, pOBD->iCursorY, bRender); - if (iSize == FONT_NORMAL) // 8x8 font - { - i = 0; - iFontSkip = iScroll & 7; // number of columns to initially skip - while (pOBD->iCursorX < pOBD->width && szMsg[i] != 0 && pOBD->iCursorY < pOBD->height / 8) - { - if (iScroll < 8) // only display visible characters - { - c = (unsigned char)szMsg[i]; - iFontOff = (int)(c-32) * 8; - // we can't directly use the pointer to FLASH memory, so copy to a local buffer - memcpy_P(ucTemp, &ucFont[iFontOff], 8); - if (bInvert) InvertBytes(ucTemp, 8); - iLen = 8 - iFontSkip; - if (pOBD->iCursorX + iLen > pOBD->width) // clip right edge - iLen = pOBD->width - pOBD->iCursorX; - obdCachedWrite(pOBD, &ucTemp[iFontSkip], iLen, bRender); -// obdWriteDataBlock(pOBD, &ucTemp[iFontSkip], iLen, bRender); // write character pattern - pOBD->iCursorX += iLen; - if (pOBD->iCursorX >= pOBD->width-7 && pOBD->wrap) // word wrap enabled? - { - pOBD->iCursorX = 0; // start at the beginning of the next line - pOBD->iCursorY++; - obdSetPosition(pOBD, pOBD->iCursorX, pOBD->iCursorY, bRender); - } - iFontSkip = 0; - } - iScroll -= 8; - i++; - } // while - obdCachedFlush(pOBD, bRender); // write any remaining data - return 0; - } // 8x8 -#ifndef __AVR__ - else if (iSize == FONT_LARGE) // 16x32 font - { - i = 0; - iFontSkip = iScroll & 15; // number of columns to initially skip - while (pOBD->iCursorX < pOBD->width && pOBD->iCursorY < (pOBD->height / 8)-3 && szMsg[i] != 0) - { - if (iScroll < 16) // if characters are visible - { - s = (unsigned char *)&ucBigFont[(unsigned char)(szMsg[i]-32)*64]; - iLen = 16 - iFontSkip; - if (pOBD->iCursorX + iLen > pOBD->width) // clip right edge - iLen = pOBD->width - pOBD->iCursorX; - // we can't directly use the pointer to FLASH memory, so copy to a local buffer - obdSetPosition(pOBD, pOBD->iCursorX, pOBD->iCursorY, bRender); - memcpy_P(ucTemp, s, 16); - if (bInvert) InvertBytes(ucTemp, 16); - obdWriteDataBlock(pOBD, &ucTemp[iFontSkip], iLen, bRender); // write character pattern - obdSetPosition(pOBD, pOBD->iCursorX, pOBD->iCursorY+1, bRender); - memcpy_P(ucTemp, s+16, 16); - if (bInvert) InvertBytes(ucTemp, 16); - obdWriteDataBlock(pOBD, &ucTemp[iFontSkip], iLen, bRender); // write character pattern - if (pOBD->iCursorY <= 5) - { - obdSetPosition(pOBD, pOBD->iCursorX, pOBD->iCursorY+2, bRender); - memcpy_P(ucTemp, s+32, 16); - if (bInvert) InvertBytes(ucTemp, 16); - obdWriteDataBlock(pOBD, &ucTemp[iFontSkip], iLen, bRender); // write character pattern - } - if (pOBD->iCursorY <= 4) - { - obdSetPosition(pOBD, pOBD->iCursorX, pOBD->iCursorY+3, bRender); - memcpy_P(ucTemp, s+48, 16); - if (bInvert) InvertBytes(ucTemp, 16); - obdWriteDataBlock(pOBD, &ucTemp[iFontSkip], iLen, bRender); // write character pattern - } - pOBD->iCursorX += iLen; - if (pOBD->iCursorX >= pOBD->width-15 && pOBD->wrap) // word wrap enabled? - { - pOBD->iCursorX = 0; // start at the beginning of the next line - pOBD->iCursorY+=4; - } - iFontSkip = 0; - } // if character visible from scrolling - iScroll -= 16; - i++; - } // while - return 0; - } // 16x32 -#endif // !__AVR__ - else if (iSize == FONT_STRETCHED) // 8x8 stretched to 16x16 - { - i = 0; - iFontSkip = iScroll & 15; // number of columns to initially skip - while (pOBD->iCursorX < pOBD->width && pOBD->iCursorY < (pOBD->height/8)-1 && szMsg[i] != 0) - { -// stretch the 'normal' font instead of using the big font - if (iScroll < 16) // if characters are visible - { - int tx, ty; - c = szMsg[i] - 32; - unsigned char uc1, uc2, ucMask, *pDest; - s = (unsigned char *)&ucFont[(int)c*8]; - memcpy_P(ucTemp, s, 8); - if (bInvert) - InvertBytes(ucTemp, 8); - // Stretch the font to double width + double height - memset(&ucTemp[8], 0, 32); // write 32 new bytes - for (tx=0; tx<8; tx++) - { - ucMask = 3; - pDest = &ucTemp[8+tx*2]; - uc1 = uc2 = 0; - c = ucTemp[tx]; - for (ty=0; ty<4; ty++) - { - if (c & (1 << ty)) // a bit is set - uc1 |= ucMask; - if (c & (1 << (ty + 4))) - uc2 |= ucMask; - ucMask <<= 2; - } - pDest[0] = uc1; - pDest[1] = uc1; // double width - pDest[16] = uc2; - pDest[17] = uc2; - } - iLen = 16 - iFontSkip; - if (pOBD->iCursorX + iLen > pOBD->width) // clip right edge - iLen = pOBD->width - pOBD->iCursorX; - obdSetPosition(pOBD, pOBD->iCursorX, pOBD->iCursorY, bRender); - obdWriteDataBlock(pOBD, &ucTemp[8+iFontSkip], iLen, bRender); - obdSetPosition(pOBD, pOBD->iCursorX, pOBD->iCursorY+1, bRender); - obdWriteDataBlock(pOBD, &ucTemp[24+iFontSkip], iLen, bRender); - pOBD->iCursorX += iLen; - if (pOBD->iCursorX >= pOBD->width-15 && pOBD->wrap) // word wrap enabled? - { - pOBD->iCursorX = 0; // start at the beginning of the next line - pOBD->iCursorY += 2; - obdSetPosition(pOBD, pOBD->iCursorX, pOBD->iCursorY, bRender); - } - iFontSkip = 0; - } // if characters are visible - iScroll -= 16; - i++; - } // while - return 0; - } // 16x16 - else if (iSize == FONT_SMALL) // 6x8 font - { - i = 0; - iFontSkip = iScroll % 6; - while (pOBD->iCursorX < pOBD->width && pOBD->iCursorY < (pOBD->height/8) && szMsg[i] != 0) - { - if (iScroll < 6) // if characters are visible - { - c = szMsg[i] - 32; - // we can't directly use the pointer to FLASH memory, so copy to a local buffer - memcpy_P(ucTemp, &ucSmallFont[(int)c*6], 6); - if (bInvert) InvertBytes(ucTemp, 6); - iLen = 6 - iFontSkip; - if (pOBD->iCursorX + iLen > pOBD->width) // clip right edge - iLen = pOBD->width - pOBD->iCursorX; - obdCachedWrite(pOBD, &ucTemp[iFontSkip], iLen, bRender); -// obdWriteDataBlock(pOBD, &ucTemp[iFontSkip], iLen, bRender); // write character pattern - pOBD->iCursorX += iLen; - iFontSkip = 0; - if (pOBD->iCursorX >= pOBD->width-5 && pOBD->wrap) // word wrap enabled? - { - pOBD->iCursorX = 0; // start at the beginning of the next line - pOBD->iCursorY++; - obdSetPosition(pOBD, pOBD->iCursorX, pOBD->iCursorY, bRender); - } - } // if characters are visible - iScroll -= 6; - i++; - } - obdCachedFlush(pOBD, bRender); // write any remaining data - return 0; - } // 6x8 - return -1; // invalid size -} /* obdWriteString() */ -// -// Get the width of text in a custom font -// -void obdGetStringBox(GFXfont *pFont, char *szMsg, int *width, int *top, int *bottom) -{ -int cx = 0; -int c, i = 0; -GFXglyph *pGlyph; -int miny, maxy; - - if (width == NULL || top == NULL || bottom == NULL || pFont == NULL || szMsg == NULL) return; // bad pointers - miny = 100; maxy = 0; - while (szMsg[i]) { - c = szMsg[i++]; - if (c < pFont->first || c > pFont->last) // undefined character - continue; // skip it - c -= pFont->first; // first char of font defined - pGlyph = &pFont->glyph[c]; - cx += pGlyph->xAdvance; - if (pGlyph->yOffset < miny) miny = pGlyph->yOffset; - if (pGlyph->height+pGlyph->yOffset > maxy) maxy = pGlyph->height+pGlyph->yOffset; - } - *width = cx; - *top = miny; - *bottom = maxy; -} /* obdGetStringBox() */ - -// -// Draw a string of characters in a custom font -// A back buffer must be defined -// -int obdWriteStringCustom(OBDISP *pOBD, GFXfont *pFont, int x, int y, char *szMsg, uint8_t ucColor) -{ -int i, end_y, dx, dy, tx, ty, c, iBitOff; -uint8_t *s, *d, bits, ucMask, ucClr, uc; -GFXfont font; -GFXglyph glyph, *pGlyph; -int iPitch; - - if (pOBD == NULL || pFont == NULL || pOBD->ucScreen == NULL || x < 0) - return -1; - iPitch = pOBD->width; - if (iPitch < 128) iPitch = 128; - // in case of running on AVR, get copy of data from FLASH - memcpy_P(&font, pFont, sizeof(font)); - pGlyph = &glyph; - - i = 0; - while (szMsg[i] && x < pOBD->width) - { - c = szMsg[i++]; - if (c < font.first || c > font.last) // undefined character - continue; // skip it - c -= font.first; // first char of font defined - memcpy_P(&glyph, &font.glyph[c], sizeof(glyph)); - dx = x + pGlyph->xOffset; // offset from character UL to start drawing - dy = y + pGlyph->yOffset; - s = font.bitmap + pGlyph->bitmapOffset; // start of bitmap data - // Bitmap drawing loop. Image is MSB first and each pixel is packed next - // to the next (continuing on to the next character line) - iBitOff = 0; // bitmap offset (in bits) - bits = uc = 0; // bits left in this font byte - end_y = dy + pGlyph->height; - if (dy < 0) { // skip these lines - iBitOff += (pGlyph->width * (-dy)); - dy = 0; - } - for (ty=dy; tyheight; ty++) { - ucMask = 1<<(ty & 7); // destination bit number for this line - ucClr = (ucColor) ? ucMask : 0; - d = &pOBD->ucScreen[(ty >> 3) * iPitch + dx]; // internal buffer dest - for (tx=0; txwidth; tx++) { - if (uc == 0) { // need to read more font data - tx += bits; // skip any remaining 0 bits - uc = pgm_read_byte(&s[iBitOff>>3]); // get more font bitmap data - bits = 8 - (iBitOff & 7); // we might not be on a byte boundary - iBitOff += bits; // because of a clipped line - uc <<= (8-bits); - if (tx >= pGlyph->width) { - while(tx >= pGlyph->width) { // rolls into next line(s) - tx -= pGlyph->width; - ty++; - } - if (ty >= end_y || ty >= pOBD->height) { // we're past the end - tx = pGlyph->width; - continue; // exit this character cleanly - } - // need to recalculate mask and offset in case Y changed - ucMask = 1<<(ty & 7); // destination bit number for this line - ucClr = (ucColor) ? ucMask : 0; - d = &pOBD->ucScreen[(ty >> 3) * iPitch + dx]; // internal buffer dest - } - } // if we ran out of bits - if (uc & 0x80) { // set pixel - if (ucClr) - d[tx] |= ucMask; - else - d[tx] &= ~ucMask; - } - bits--; // next bit - uc <<= 1; - } // for x - } // for y - x += pGlyph->xAdvance; // width of this character - } // while drawing characters - return 0; -} /* obdWriteStringCustom() */ - -// -// Render a sprite/rectangle of pixels from a provided buffer to the display. -// The row values refer to byte rows, not pixel rows due to the memory -// layout of OLEDs and LCDs. -// returns 0 for success, -1 for invalid parameter -// -int obdDrawGFX(OBDISP *pOBD, uint8_t *pBuffer, int iSrcCol, int iSrcRow, int iDestCol, int iDestRow, int iWidth, int iHeight, int iSrcPitch) -{ - int y; - - if (iSrcCol < 0 || iSrcCol >= pOBD->width || iSrcRow < 0 || iSrcRow > (pOBD->height/8)-1 || iDestCol < 0 || iDestCol >= pOBD->width || iDestRow < 0 || iDestRow >= (pOBD->height >> 3) || iSrcPitch <= 0) - return -1; // invalid - - for (y=iSrcRow; yinvert) ? 0x00 : 0xff; - digitalWrite(pOBD->iCSPin, HIGH); // active high - - ucStart = 0x80; // write command - if (ucVCOM) - ucStart |= 0x40; // VCOM bit - ucLineBuf[1] = ucStart; - // this code assumes I2C, so the first byte is ignored - _I2CWrite(pOBD, ucLineBuf, 2); // write command(01) + vcom(02) - ucVCOM = !ucVCOM; // need to toggle this each transaction - - // We need to flip and invert the image in code because the Sharp memory LCD - // controller only has the simplest of commands for data writing - if (pOBD->flip) - { - for (x=0; x<168; x++) // we have to write the memory in the wrong direction - { - s = &pBuffer[x + (17*168)]; // point to last line first - d = &ucLineBuf[2]; - ucLineBuf[1] = pgm_read_byte(&ucMirror[x+1]); // current line number - for (y=0; y<144/8; y++) // - { - c = s[0] ^ ucInvert; // we need to brute-force invert it - *d++ = c; - s -= 168; - } // for y - // write this line to the display - ucLineBuf[20] = 0; // end of line - _I2CWrite(pOBD, ucLineBuf, 21); - } // for x - } - else // normal orientation - { - for (x=0; x<168; x++) // we have to write the memory in the wrong direction - { - s = &pBuffer[167-x]; // point to last line first - d = &ucLineBuf[2]; - ucLineBuf[1] = pgm_read_byte(&ucMirror[x+1]); // current line number - for (y=0; y<144/8; y++) // - { - c = s[0] ^ ucInvert; // we need to brute-force invert it - *d++ = pgm_read_byte(&ucMirror[c]); - s += 168; - } // for y - // write this line to the display - ucLineBuf[20] = 0; // end of line - _I2CWrite(pOBD, ucLineBuf, 21); - } // for x - } - ucLineBuf[1] = 0; - _I2CWrite(pOBD, ucLineBuf, 2); // final transfer - digitalWrite(pOBD->iCSPin, LOW); // de-activate -} /* SharpDumpBuffer() */ -// -// Dump a screen's worth of data directly to the display -// Try to speed it up by comparing the new bytes with the existing buffer -// -void obdDumpBuffer(OBDISP *pOBD, uint8_t *pBuffer) -{ -int x, y, iPitch; -int iLines, iCols; -uint8_t bNeedPos; -uint8_t *pSrc = pOBD->ucScreen; - - iPitch = pOBD->width; - if (iPitch < 128) - iPitch = 128; - if (pOBD->type == LCD_VIRTUAL) // wrong function for this type of display - return; - if (pBuffer == NULL) // dump the internal buffer if none is given - pBuffer = pOBD->ucScreen; - if (pBuffer == NULL) - return; // no backbuffer and no provided buffer - - if (pOBD->type == SHARP_144x168) // special case for Sharp Memory LCD - { - SharpDumpBuffer(pOBD, pBuffer); - return; - } - iLines = pOBD->height >> 3; - iCols = pOBD->width >> 4; - for (y=0; yucScreen == NULL || pBuffer == pSrc || memcmp(pSrc, pBuffer, 16) != 0) // doesn't match, need to send it - { - if (bNeedPos) // need to reposition output cursor? - { - bNeedPos = 0; - obdCachedFlush(pOBD, 1); - obdSetPosition(pOBD, x*16, y, 1); - } - obdCachedWrite(pOBD, pBuffer, 16, 1); - } - else - { - bNeedPos = 1; // we're skipping a block, so next time will need to set the new position - } - pSrc += 16; - pBuffer += 16; - } // for x - pSrc += (iPitch - pOBD->width); // for narrow displays, skip to the next line - pBuffer += (iPitch - pOBD->width); - } // for y - obdCachedFlush(pOBD, 1); -} /* obdDumpBuffer() */ -// -// Fill the frame buffer with a byte pattern -// e.g. all off (0x00) or all on (0xff) -// -void obdFill(OBDISP *pOBD, unsigned char ucData, int bRender) -{ -uint8_t y; -uint8_t iLines; - - pOBD->iCursorX = pOBD->iCursorY = 0; - if (pOBD->type == LCD_VIRTUAL || pOBD->type == SHARP_144x168) // pure memory, handle it differently - { - if (pOBD->ucScreen) - memset(pOBD->ucScreen, ucData, pOBD->width * (pOBD->height/8)); - return; - } - iLines = pOBD->height >> 3; - memset(u8Cache, ucData, pOBD->width); - - for (y=0; ywidth, bRender); - } // for y - if (pOBD->ucScreen) - memset(pOBD->ucScreen, ucData, (pOBD->width * pOBD->height)/8); -} /* obdFill() */ - -// -// Provide or revoke a back buffer for your OLED graphics -// This allows you to manage the RAM used by ss_oled on tiny -// embedded platforms like the ATmega series -// Pass NULL to revoke the buffer. Make sure you provide a buffer -// large enough for your display (e.g. 128x64 needs 1K - 1024 bytes) -// -void obdSetBackBuffer(OBDISP *pOBD, uint8_t *pBuffer) -{ - pOBD->ucScreen = pBuffer; -} /* obdSetBackBuffer() */ - -void obdDrawLine(OBDISP *pOBD, int x1, int y1, int x2, int y2, uint8_t ucColor, int bRender) -{ - int temp; - int dx = x2 - x1; - int dy = y2 - y1; - int error; - uint8_t *p, *pStart, mask, bOld, bNew; - int xinc, yinc; - int y, x; - int iPitch = pOBD->width; - - if (iPitch < 128) iPitch = 128; // use 128 for tiny displays too - - if (x1 < 0 || x2 < 0 || y1 < 0 || y2 < 0 || x1 >= pOBD->width || x2 >= pOBD->width || y1 >= pOBD->height || y2 >= pOBD->height) - return; - - if(abs(dx) > abs(dy)) { - // X major case - if(x2 < x1) { - dx = -dx; - temp = x1; - x1 = x2; - x2 = temp; - temp = y1; - y1 = y2; - y2 = temp; - } - - y = y1; - dy = (y2 - y1); - error = dx >> 1; - yinc = 1; - if (dy < 0) - { - dy = -dy; - yinc = -1; - } - p = pStart = &pOBD->ucScreen[x1 + ((y >> 3) * iPitch)]; // point to current spot in back buffer - mask = 1 << (y & 7); // current bit offset - for(x=x1; x1 <= x2; x1++) { - if (ucColor) - *p++ |= mask; // set pixel and increment x pointer - else - *p++ &= ~mask; - error -= dy; - if (error < 0) - { - error += dx; - if (yinc > 0) - mask <<= 1; - else - mask >>= 1; - if (mask == 0) // we've moved outside the current row, write the data we changed - { - obdSetPosition(pOBD, x, y>>3, bRender); - obdWriteDataBlock(pOBD, pStart, (int)(p-pStart), bRender); // write the row we changed - x = x1+1; // we've already written the byte at x1 - y1 = y+yinc; - p += (yinc > 0) ? iPitch : -iPitch; - pStart = p; - mask = 1 << (y1 & 7); - } - y += yinc; - } - } // for x1 - if (p != pStart) // some data needs to be written - { - obdSetPosition(pOBD, x, y>>3, bRender); - obdWriteDataBlock(pOBD, pStart, (int)(p-pStart), bRender); - } - } - else { - // Y major case - if(y1 > y2) { - dy = -dy; - temp = x1; - x1 = x2; - x2 = temp; - temp = y1; - y1 = y2; - y2 = temp; - } - - p = &pOBD->ucScreen[x1 + ((y1 >> 3) * iPitch)]; // point to current spot in back buffer - bOld = bNew = p[0]; // current data at that address - mask = 1 << (y1 & 7); // current bit offset - dx = (x2 - x1); - error = dy >> 1; - xinc = 1; - if (dx < 0) - { - dx = -dx; - xinc = -1; - } - for(x = x1; y1 <= y2; y1++) { - if (ucColor) - bNew |= mask; // set the pixel - else - bNew &= ~mask; - error -= dx; - mask <<= 1; // y1++ - if (mask == 0) // we're done with this byte, write it if necessary - { - if (bOld != bNew) - { - p[0] = bNew; // save to RAM - obdSetPosition(pOBD, x, y1>>3, bRender); - obdWriteDataBlock(pOBD, &bNew, 1, bRender); - } - p += 128; // next line - bOld = bNew = p[0]; - mask = 1; // start at LSB again - } - if (error < 0) - { - error += dy; - if (bOld != bNew) // write the last byte we modified if it changed - { - p[0] = bNew; // save to RAM - obdSetPosition(pOBD, x, y1>>3, bRender); - obdWriteDataBlock(pOBD, &bNew, 1, bRender); - } - p += xinc; - x += xinc; - bOld = bNew = p[0]; - } - } // for y - if (bOld != bNew) // write the last byte we modified if it changed - { - p[0] = bNew; // save to RAM - obdSetPosition(pOBD, x, y2>>3, bRender); - obdWriteDataBlock(pOBD, &bNew, 1, bRender); - } - } // y major case -} /* obdDrawLine() */ - -// -// For drawing ellipses, a circle is drawn and the x and y pixels are scaled by a 16-bit integer fraction -// This function draws a single pixel and scales its position based on the x/y fraction of the ellipse -// -static void DrawScaledPixel(OBDISP *pOBD, int iCX, int iCY, int x, int y, int32_t iXFrac, int32_t iYFrac, uint8_t ucColor) -{ - uint8_t *d, ucMask; - int iPitch; - - iPitch = pOBD->width; - if (iPitch < 128) iPitch = 128; - if (iXFrac != 0x10000) x = ((x * iXFrac) >> 16); - if (iYFrac != 0x10000) y = ((y * iYFrac) >> 16); - x += iCX; y += iCY; - if (x < 0 || x >= pOBD->width || y < 0 || y >= pOBD->height) - return; // off the screen - d = &pOBD->ucScreen[((y >> 3)*iPitch) + x]; - ucMask = 1 << (y & 7); - if (ucColor) - *d |= ucMask; - else - *d &= ~ucMask; -} /* DrawScaledPixel() */ -// -// For drawing filled ellipses -// -static void DrawScaledLine(OBDISP *pOBD, int iCX, int iCY, int x, int y, int32_t iXFrac, int32_t iYFrac, uint8_t ucColor) -{ - int iLen, x2; - uint8_t *d, ucMask; - int iPitch; - - iPitch = pOBD->width; - if (iPitch < 128) iPitch = 128; - if (iXFrac != 0x10000) x = ((x * iXFrac) >> 16); - if (iYFrac != 0x10000) y = ((y * iYFrac) >> 16); - iLen = x*2; - x = iCX - x; y += iCY; - x2 = x + iLen; - if (y < 0 || y >= pOBD->height) - return; // completely off the screen - if (x < 0) x = 0; - if (x2 >= pOBD->width) x2 = pOBD->width-1; - iLen = x2 - x + 1; // new length - d = &pOBD->ucScreen[((y >> 3)*iPitch) + x]; - ucMask = 1 << (y & 7); - if (ucColor) // white - { - for (; iLen > 0; iLen--) - *d++ |= ucMask; - } - else // black - { - for (; iLen > 0; iLen--) - *d++ &= ~ucMask; - } -} /* DrawScaledLine() */ -// -// Draw the 8 pixels around the Bresenham circle -// (scaled to make an ellipse) -// -static void BresenhamCircle(OBDISP *pOBD, int iCX, int iCY, int x, int y, int32_t iXFrac, int32_t iYFrac, uint8_t ucColor, uint8_t bFill) -{ - if (bFill) // draw a filled ellipse - { - // for a filled ellipse, draw 4 lines instead of 8 pixels - DrawScaledLine(pOBD, iCX, iCY, x, y, iXFrac, iYFrac, ucColor); - DrawScaledLine(pOBD, iCX, iCY, x, -y, iXFrac, iYFrac, ucColor); - DrawScaledLine(pOBD, iCX, iCY, y, x, iXFrac, iYFrac, ucColor); - DrawScaledLine(pOBD, iCX, iCY, y, -x, iXFrac, iYFrac, ucColor); - } - else // draw 8 pixels around the edges - { - DrawScaledPixel(pOBD, iCX, iCY, x, y, iXFrac, iYFrac, ucColor); - DrawScaledPixel(pOBD, iCX, iCY, -x, y, iXFrac, iYFrac, ucColor); - DrawScaledPixel(pOBD, iCX, iCY, x, -y, iXFrac, iYFrac, ucColor); - DrawScaledPixel(pOBD, iCX, iCY, -x, -y, iXFrac, iYFrac, ucColor); - DrawScaledPixel(pOBD, iCX, iCY, y, x, iXFrac, iYFrac, ucColor); - DrawScaledPixel(pOBD, iCX, iCY, -y, x, iXFrac, iYFrac, ucColor); - DrawScaledPixel(pOBD, iCX, iCY, y, -x, iXFrac, iYFrac, ucColor); - DrawScaledPixel(pOBD, iCX, iCY, -y, -x, iXFrac, iYFrac, ucColor); - } -} /* BresenhamCircle() */ - -// -// Draw an outline or filled ellipse -// -void obdEllipse(OBDISP *pOBD, int iCenterX, int iCenterY, int32_t iRadiusX, int32_t iRadiusY, uint8_t ucColor, uint8_t bFilled) -{ - int32_t iXFrac, iYFrac; - int iRadius, iDelta, x, y; - - if (pOBD == NULL || pOBD->ucScreen == NULL) - return; // must have back buffer defined - if (iRadiusX <= 0 || iRadiusY <= 0) return; // invalid radii - - if (iRadiusX > iRadiusY) // use X as the primary radius - { - iRadius = iRadiusX; - iXFrac = 65536; - iYFrac = (iRadiusY * 65536) / iRadiusX; - } - else - { - iRadius = iRadiusY; - iXFrac = (iRadiusX * 65536) / iRadiusY; - iYFrac = 65536; - } - iDelta = 3 - (2 * iRadius); - x = 0; y = iRadius; - while (x <= y) - { - BresenhamCircle(pOBD, iCenterX, iCenterY, x, y, iXFrac, iYFrac, ucColor, bFilled); - x++; - if (iDelta < 0) - { - iDelta += (4*x) + 6; - } - else - { - iDelta += 4 * (x-y) + 10; - y--; - } - } -} /* obdEllipse() */ -// -// Draw an outline or filled rectangle -// -void obdRectangle(OBDISP *pOBD, int x1, int y1, int x2, int y2, uint8_t ucColor, uint8_t bFilled) -{ - uint8_t *d, ucMask, ucMask2; - int tmp, iOff; - int iPitch; - - if (pOBD == NULL || pOBD->ucScreen == NULL) - return; // only works with a back buffer - if (x1 < 0 || y1 < 0 || x2 < 0 || y2 < 0 || - x1 >= pOBD->width || y1 >= pOBD->height || x2 >= pOBD->width || y2 >= pOBD->height) return; // invalid coordinates - iPitch = pOBD->width; - if (iPitch < 128) iPitch = 128; - // Make sure that X1/Y1 is above and to the left of X2/Y2 - // swap coordinates as needed to make this true - if (x2 < x1) - { - tmp = x1; - x1 = x2; - x2 = tmp; - } - if (y2 < y1) - { - tmp = y1; - y1 = y2; - y2 = tmp; - } - if (bFilled) - { - int x, y, iMiddle; - iMiddle = (y2 >> 3) - (y1 >> 3); - ucMask = 0xff << (y1 & 7); - if (iMiddle == 0) // top and bottom lines are in the same row - ucMask &= (0xff >> (7-(y2 & 7))); - d = &pOBD->ucScreen[(y1 >> 3)*iPitch + x1]; - // Draw top - for (x = x1; x <= x2; x++) - { - if (ucColor) - *d |= ucMask; - else - *d &= ~ucMask; - d++; - } - if (iMiddle > 1) // need to draw middle part - { - ucMask = (ucColor) ? 0xff : 0x00; - for (y=1; yucScreen[(y1 >> 3)*iPitch + x1 + (y*iPitch)]; - for (x = x1; x <= x2; x++) - *d++ = ucMask; - } - } - if (iMiddle >= 1) // need to draw bottom part - { - ucMask = 0xff >> (7-(y2 & 7)); - d = &pOBD->ucScreen[(y2 >> 3)*iPitch + x1]; - for (x = x1; x <= x2; x++) - { - if (ucColor) - *d++ |= ucMask; - else - *d++ &= ~ucMask; - } - } - } - else // outline - { - // see if top and bottom lines are within the same byte rows - d = &pOBD->ucScreen[(y1 >> 3)*iPitch + x1]; - if ((y1 >> 3) == (y2 >> 3)) - { - ucMask2 = 0xff << (y1 & 7); // L/R end masks - ucMask = 1 << (y1 & 7); - ucMask |= 1 << (y2 & 7); - ucMask2 &= (0xff >> (7-(y2 & 7))); - if (ucColor) - { - *d++ |= ucMask2; // start - x1++; - for (; x1 < x2; x1++) - *d++ |= ucMask; - if (x1 <= x2) - *d++ |= ucMask2; // right edge - } - else - { - *d++ &= ~ucMask2; - x1++; - for (; x1 < x2; x1++) - *d++ &= ~ucMask; - if (x1 <= x2) - *d++ &= ~ucMask2; // right edge - } - } - else - { - int y; - // L/R sides - iOff = (x2 - x1); - ucMask = 1 << (y1 & 7); - for (y=y1; y <= y2; y++) - { - if (ucColor) { - *d |= ucMask; - d[iOff] |= ucMask; - } else { - *d &= ~ucMask; - d[iOff] &= ~ucMask; - } - ucMask <<= 1; - if (ucMask == 0) { - ucMask = 1; - d += iPitch; - } - } - // T/B sides - ucMask = 1 << (y1 & 7); - ucMask2 = 1 << (y2 & 7); - x1++; - d = &pOBD->ucScreen[(y1 >> 3)*iPitch + x1]; - iOff = (y2 >> 3) - (y1 >> 3); - iOff *= iPitch; - for (; x1 < x2; x1++) - { - if (ucColor) { - *d |= ucMask; - d[iOff] |= ucMask2; - } else { - *d &= ~ucMask; - d[iOff] &= ~ucMask2; - } - d++; - } - } - } // outline -} /* obdRectangle() */ - -// A valid CW or CCW move returns 1 or -1, invalid returns 0. -static int obdMenuReadRotary(SIMPLEMENU *sm) { -static int8_t rot_enc_table[] = {0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0}; -uint8_t c; -int rc = 0; - - - sm->prevNextCode <<= 2; - if (digitalRead(sm->u8Dn) == sm->iPressed) - sm->prevNextCode |= 0x02; - if (digitalRead(sm->u8Up) == sm->iPressed) - sm->prevNextCode |= 0x01; - sm->prevNextCode &= 0x0f; - - // If valid then store as 16 bit data. - if (rot_enc_table[sm->prevNextCode]) { - sm->store <<= 4; - sm->store |= sm->prevNextCode; - c = sm->store & 0xff; - //if (store==0xd42b) return 1; - //if (store==0xe817) return -1; - if ((c & 0xf) == 2) rc = -1; - else if ((c & 0xf) == 1) rc = 1; - } -// Serial.printf("store = 0x%04x, val = %d\n", sm->store, rc); - return rc; -} /* obdMenuReadRotary() */ - -// -// Initialize the simple menu structure -// -int obdMenuInit(OBDISP *pOBD, SIMPLEMENU *sm, char **pText, int iFontSize, int bCenter, int btnUp, int btnDn, int btnEnter, int iPressedState, int bIsRotary) -{ - int iLen; - if (sm == NULL || pText == NULL) return 0; - sm->pOBD = pOBD; - sm->u8Up = btnUp; // pin numbers of the action buttons - sm->u8Dn = btnDn; // or rotary A line - sm->u8Enter = btnEnter; // or rotary B line - sm->bIsRotary = bIsRotary; - sm->u8BtnState = 0; // no active buttons to start - sm->iPressed = iPressedState; // active state of a pressed button - sm->bCenter = bCenter; - sm->iFontSize = iFontSize; - sm->pMenuText = pText; - sm->iMenuIndex = 0; // start at first item - sm->iDispX = 128; // DEBUG - sm->iDispY = 64; // DEBUG - sm->bOneButton = (btnDn == -1 && btnEnter == -1); // only 1 button defined - sm->pfnCallback = NULL; - sm->prevNextCode = 0; - sm->store = 0; - iLen = 0; - while (pText[iLen] != NULL) { - iLen++; - } - sm->iMenuLen = iLen-1; // don't count the title text - return 1; // success -} /* obdMenuInit() */ - -// -// Get the text and centering position for -// a specific menu item -// returns the X position -// -static int obdMenuGetItem(SIMPLEMENU *sm, int iItem, char *szText) -{ - int x, cx, len; - - if (iItem > sm->iMenuLen) - return -1; // invalid request - - if (sm->iFontSize == FONT_SMALL) - cx = 6; - else if (sm->iFontSize == FONT_NORMAL) - cx = 8; - else cx = 16; - strcpy(szText, sm->pMenuText[iItem]); - if (sm->pfnCallback && iItem > 0) // don't add callback for menu title - { - strcat(szText, " "); - strcat(szText, (*sm->pfnCallback)(iItem-1)); - } - x = 0; - if (sm->bCenter || iItem == 0) // always center the menu title - { - len = strlen(szText); - x = (sm->iDispX - (len * cx)) / 2; - } - return x; -} /* obdMenuGetItem() */ - -// -// Erase the display and show the given menu -// -void obdMenuShow(SIMPLEMENU *sm, int iItem) -{ -int i, x, iCount, iStart = 0; -int iFirst, iLast; -char szTemp[64]; - - iCount = (sm->iDispY / 8) - 1; // DEBUG - number of visible menu lines - iFirst = iLast = iItem; - if (iItem == -1) // show the entire menu - { - obdFill(sm->pOBD, 0, 0); - x = obdMenuGetItem(sm, 0, szTemp); // get the title text - obdMenuShowItem(sm->pOBD, x, 0, szTemp, 0, 0, sm->iFontSize, 0); // show title - iFirst = 0; - iLast = iCount-1; - } - if (sm->iMenuIndex >= iCount) // needs to scroll up - iStart = sm->iMenuIndex - (iCount-1); - if (sm->iMenuIndex < 0 || sm->iMenuIndex+iCount > sm->iMenuLen) { // invalid - sm->iMenuIndex = 0; - iStart = 0; - } - - for (i=iFirst; i<=iLast && i+iStart < sm->iMenuLen; i++) // draw the visible menu lines - { - x = obdMenuGetItem(sm, i + iStart + 1, szTemp); - if (x >= 0) // display if valid - obdMenuShowItem(sm->pOBD, x, i+1, szTemp, (i+iStart == sm->iMenuIndex), (iFirst==iLast), sm->iFontSize, (iFirst==iLast)); - } - if (iItem == -1) // now the display it in one shot - obdDumpBuffer(sm->pOBD, NULL); -} /* obdMenuShow() */ - -// -// Set a callback function to return custom info/status -// for each menu item -// -void obdMenuSetCallback(SIMPLEMENU *sm, SIMPLECALLBACK pfnCallBack) -{ - if (sm != NULL) - sm->pfnCallback = pfnCallBack; -} /* obdMenuSetCallback() */ -// -// Display the text of a single menu item -// optionally erases what's under it to prevent left-over text when the length changes -// -void obdMenuShowItem(OBDISP *pOBD, int x, int y, char *szText, int bInvert, int bErase, int iFontSize, int bRender) -{ - static char *szBlank = (char *)" "; - if (bErase) - obdWriteString(pOBD, 0, 0, y, szBlank, iFontSize, 0, bRender); // erase old info - obdWriteString(pOBD, 0, x, y, szText, iFontSize, bInvert, bRender); -} /* obdMenuShowItem() */ - -// -// Flash a menu item when it is selected -// -static void obdMenuFlash(SIMPLEMENU *sm, int iItem) -{ -int x, y, i, iCount; -char szTemp[64]; - - iCount = (sm->iDispY / 8) - 1; // DEBUG - number of visible menu lines - y = iItem+1; - if (y > iCount) // max bottom line - y = iCount; - - x = obdMenuGetItem(sm, iItem+1, szTemp); - if (x < 0) return; // invalid request - - for (i=0; i<3; i++) - { - obdMenuShowItem(sm->pOBD, x, y, szTemp, 0, 0, sm->iFontSize, 1); // show non-inverted - delay(200); - obdMenuShowItem(sm->pOBD, x, y, szTemp, 1, 0, sm->iFontSize, 1); // show inverted - delay(200); - } -} /* obdMenuFlash() */ - -// -// Change the menu index incrementally -// redraws the minimum amount of screen to show the new info -// (this prevents flicker/flash and saves battery life) -// returns the new menu index -// -int obdMenuDelta(SIMPLEMENU *sm, int iDelta) -{ - int i, x, iNewIndex, iCount; - int iStart1, iStart2; - char szTemp[64]; - - if (iDelta == 0) return sm->iMenuIndex; // nothing to do - - iNewIndex = sm->iMenuIndex + iDelta; - if (!sm->bOneButton && (iNewIndex < 0 || iNewIndex >= sm->iMenuLen)) // no change possible, exit - return sm->iMenuIndex; // unchanged - // If we are using a single button, wrap around the ends - if (iNewIndex < 0) iNewIndex = (sm->iMenuLen - 1); - else if (iNewIndex > sm->iMenuLen-1) iNewIndex = 0; - - iCount = (sm->iDispY / 8) - 1; // DEBUG - number of visible menu lines - iStart1 = iStart2 = 0; - if (sm->iMenuIndex > iCount-1) - iStart1 = sm->iMenuIndex - (iCount-1); - if (iNewIndex > iCount-1) // needs to scroll up - iStart2 = iNewIndex - (iCount-1); - if (iStart1 != iStart2) // need to redraw all items - { - for (i=0; i= 0) - obdMenuShowItem(sm->pOBD, x, i+1, szTemp, (i+iStart2 == iNewIndex), 1, sm->iFontSize, 0); - } - obdDumpBuffer(sm->pOBD, NULL); - } - else // need to redraw only the new and old items - { - i = sm->iMenuIndex - iStart1; - x = obdMenuGetItem(sm, sm->iMenuIndex+1, szTemp); - if (x >= 0) - obdMenuShowItem(sm->pOBD, x, i+1, szTemp, 0, 0, sm->iFontSize, 1); - i = iNewIndex - iStart2; - x = obdMenuGetItem(sm, iNewIndex+1, szTemp); - if (x >= 0) - obdMenuShowItem(sm->pOBD, x, i+1, szTemp, 1, 0, sm->iFontSize, 1); - } - sm->iMenuIndex = iNewIndex; - return iNewIndex; -} /* obdMenuDelta() */ - -// -// With the given setup, check for button presses -// and act accordingly -// returns -1 for normal interactions and the menu item index if the user presses the ENTER button -// -// time in milliseconds for a long press -#define MENU_LONG_PRESS 600 -int obdMenuRun(SIMPLEMENU *sm) -{ -uint8_t buttons = 0; -unsigned long ul; -int iDelta, rc = -1; - - if (sm->bIsRotary) { // read the rotary encoder - if (digitalRead(sm->u8Enter) == sm->iPressed) { - buttons |= 1; // pressed - if (buttons != sm->u8BtnState) - rc = sm->iMenuIndex; // user pressed ENTER, return current menu index - } else { // check for rotary encoder activity - iDelta = obdMenuReadRotary(sm); - obdMenuDelta(sm, iDelta); - } - sm->u8BtnState = buttons; - } else { -// check the button states - if (digitalRead(sm->u8Up) == sm->iPressed) - buttons |= 1; - if (buttons != sm->u8BtnState) // something changed - { - if (sm->bOneButton) // different logic for a single button system - { - if (sm->u8BtnState == 0 && buttons == 1) // up button just pressed - { - sm->ulPressTime = millis(); // record the press time - } - if (sm->u8BtnState == 1 && buttons == 0) // up button just released - { - ul = millis() - sm->ulPressTime; - if (ul < MENU_LONG_PRESS) // short press = navigate menu - obdMenuDelta(sm, 1); - else // treat it like a long press - rc = sm->iMenuIndex; // action - } - } - else // 3 button setup (UP/DOWN/ENTER) - { - if (digitalRead(sm->u8Dn) == sm->iPressed) - buttons |= 2; - if (digitalRead(sm->u8Enter) == sm->iPressed) - rc = sm->iMenuIndex; // user pressed ENTER, return current menu index - if ((sm->u8BtnState & 1) == 0 && (buttons & 1) == 1) // Up button pressed - { - obdMenuDelta(sm, -1); - } - if ((sm->u8BtnState & 2) == 0 && (buttons & 2) == 2) // Down button pressed - { - obdMenuDelta(sm, 1); - } - } - sm->u8BtnState = buttons; // save the latest state - } - } - if (rc != -1) // selected - obdMenuFlash(sm, sm->iMenuIndex); - return rc; -} /* obdMenuRun() */ diff --git a/TLD5542-1LED_DRV_V1.02/OneBitDisplay.h b/TLD5542-1LED_DRV_V1.02/OneBitDisplay.h deleted file mode 100755 index c390b8b..0000000 --- a/TLD5542-1LED_DRV_V1.02/OneBitDisplay.h +++ /dev/null @@ -1,358 +0,0 @@ -#ifndef __ONEBITDISPLAY__ -#define __ONEBITDISPLAY__ - -#include "BitBang_I2C.h" - -// Proportional font data taken from Adafruit_GFX library -/// Font data stored PER GLYPH -#ifndef _ADAFRUIT_GFX_H -typedef struct { - uint16_t bitmapOffset; ///< Pointer into GFXfont->bitmap - uint8_t width; ///< Bitmap dimensions in pixels - uint8_t height; ///< Bitmap dimensions in pixels - uint8_t xAdvance; ///< Distance to advance cursor (x axis) - int8_t xOffset; ///< X dist from cursor pos to UL corner - int8_t yOffset; ///< Y dist from cursor pos to UL corner -} GFXglyph; - -/// Data stored for FONT AS A WHOLE -typedef struct { - uint8_t *bitmap; ///< Glyph bitmaps, concatenated - GFXglyph *glyph; ///< Glyph array - uint8_t first; ///< ASCII extents (first char) - uint8_t last; ///< ASCII extents (last char) - uint8_t yAdvance; ///< Newline distance (y axis) -} GFXfont; -#endif // _ADAFRUIT_GFX_H - -typedef struct obdstruct -{ -uint8_t oled_addr; // requested address or 0xff for automatic detection -uint8_t wrap, flip, invert, type; -uint8_t *ucScreen; -int iCursorX, iCursorY; -int width, height; -int iScreenOffset; -BBI2C bbi2c; -uint8_t com_mode; // communication mode (I2C / SPI) -uint8_t mode; // data/command mode for 9-bit SPI -uint8_t iDCPin, iMOSIPin, iCLKPin, iCSPin; -uint8_t iLEDPin; // backlight -uint8_t bBitBang; -} OBDISP; - -typedef char * (*SIMPLECALLBACK)(int iMenuItem); - -typedef struct smenu { - uint8_t u8Up, u8Dn, u8Enter; // button pin numbers - uint8_t bIsRotary; // rotary encoder or up/down buttons? - uint8_t bCenter; // center all menu text if true - uint8_t u8BtnState; // state of all buttons - uint8_t bOneButton; // flag indicating the menu operates from a single button - uint8_t prevNextCode; // rotary encoder state machine - int iMenuIndex; // current menu index - int iMenuLen; // number of entries in the menu (calculated at startup) - char **pMenuText; // string array with menu title and text - int iFontSize; - int iPressed; // polarity of button pressed state - unsigned long ulPressTime; // time in millis when button was pressed - int iDispX, iDispY; // display width/height in pixels - SIMPLECALLBACK pfnCallback; - OBDISP *pOBD; // display structureme - uint16_t store; -} SIMPLEMENU; - -// Make the Linux library interface C instead of C++ -#if defined(_LINUX_) && defined(__cplusplus) -extern "C" { -#endif - -typedef enum -{ - MODE_DATA = 0, - MODE_COMMAND -} DC_MODE; - -typedef enum -{ - COM_I2C = 0, - COM_SPI, - COM_BLE, - COM_UART -} COM_MODE; - -// These are defined the same in my SPI_LCD library -#ifndef SPI_LCD_H - -// 4 possible font sizes: 8x8, 16x32, 6x8, 16x16 (stretched from 8x8) -enum { - FONT_NORMAL = 0, - FONT_LARGE, - FONT_SMALL, - FONT_STRETCHED -}; -#endif - -// Display type for init function -enum { - OLED_128x128 = 1, - OLED_128x32, - OLED_128x64, - OLED_132x64, - OLED_64x32, - OLED_96x16, - OLED_72x40, - LCD_UC1701, - LCD_UC1609, - LCD_HX1230, - LCD_NOKIA5110, - LCD_VIRTUAL, - SHARP_144x168 -}; - -// Rotation and flip angles to draw tiles -enum { - ANGLE_0=0, - ANGLE_90, - ANGLE_180, - ANGLE_270, - ANGLE_FLIPX, - ANGLE_FLIPY -}; - -// Return value from obd obdI2CInit() -enum { - OLED_NOT_FOUND = -1, // no display found - OLED_SSD1306_3C, // SSD1306 found at 0x3C - OLED_SSD1306_3D, // SSD1306 found at 0x3D - OLED_SH1106_3C, // SH1106 found at 0x3C - OLED_SH1106_3D, // SH1106 found at 0x3D - OLED_SH1107_3C, // SH1107 - OLED_SH1107_3D, - LCD_OK, - LCD_ERROR -}; -// -// Create a virtual display of any size -// The memory buffer must be provided at the time of creation -// -void obdCreateVirtualDisplay(OBDISP *pOBD, int width, int height, uint8_t *buffer); -// -// Draw the contents of a memory buffer onto a display -// The sub-window will be clipped if it specifies too large an area -// for the destination display. The source OBDISP structure must have -// a valid back buffer defined -// The top and bottom destination edges will be drawn on byte boundaries (8 rows) -// The source top/bot edges can be on pixel boundaries -// -void obdDumpWindow(OBDISP *pOBDSrc, OBDISP *pOBDDest, int srcx, int srcy, int destx, int desty, int width, int height); -// -// Initializes a virtual display over BLE -// Currently only OLED_128x64 is supported -// -int obdBLEInit(OBDISP *pOBD, int iType, int bFlip, int bInvert, char *name); -// -// Initializes a virtual display over BLE -// Currently only OLED_128x64 is supported -// -int obdUARTInit(OBDISP *pOBD, int iType, int bFlip, int bInvert, unsigned long ulSpeed); - -// -// Initializes the display controller into "page mode" on I2C -// If SDAPin and SCLPin are not -1, then bit bang I2C on those pins -// Otherwise use the Wire library. -// If you don't need to use a separate reset pin, set it to -1 -// -int obdI2CInit(OBDISP *pOBD, int iType, int iAddr, int bFlip, int bInvert, int bWire, int iSDAPin, int iSCLPin, int iResetPin, int32_t iSpeed); -// -// Initialize an SPI version of the display -// -void obdSPIInit(OBDISP *pOBD, int iType, int iDC, int iCS, int iReset, int iMOSI, int iCLK, int iLED, int bFlip, int bInvert, int iBitBang, int32_t iSpeed); - -// -// Provide or revoke a back buffer for your OLED graphics -// This allows you to manage the RAM used by ss_oled on tiny -// embedded platforms like the ATmega series -// Pass NULL to revoke the buffer. Make sure you provide a buffer -// large enough for your display (e.g. 128x64 needs 1K - 1024 bytes) -// -void obdSetBackBuffer(OBDISP *pOBD, uint8_t *pBuffer); -// -// Sets the brightness (0=off, 255=brightest) -// -void obdSetContrast(OBDISP *pOBD, unsigned char ucContrast); -// -// Load a 1-bpp Windows bitmap -// Pass the pointer to the beginning of the BMP file -// First pass version assumes a full screen bitmap -// -int obdLoadBMP(OBDISP *pOBD, uint8_t *pBMP, int x, int y, int bInvert); -// -// Power up/down the display -// useful for low power situations -// -void obdPower(OBDISP *pOBD, int bOn); -// -// Set the current cursor position -// The column represents the pixel column (0-127) -// The row represents the text row (0-7) -// -void obdSetCursor(OBDISP *pOBD, int x, int y); - -// -// Turn text wrap on or off for the obdWriteString() function -// -void obdSetTextWrap(OBDISP *pOBD, int bWrap); -// -// Draw a string of normal (8x8), small (6x8) or large (16x32) characters -// At the given col+row with the given scroll offset. The scroll offset allows you to -// horizontally scroll text which does not fit on the width of the display. The offset -// represents the pixels to skip when drawing the text. An offset of 0 starts at the beginning -// of the text. -// The system remembers where the last text was written (the cursor position) -// To continue writing from the last position, set the x,y values to -1 -// The text can optionally wrap around to the next line by calling oledSetTextWrap(true); -// otherwise text which would go off the right edge will not be drawn and the cursor will -// be left "off screen" until set to a new position explicitly -// -// Returns 0 for success, -1 for invalid parameter -// -int obdWriteString(OBDISP *pOBD, int iScrollX, int x, int y, char *szMsg, int iSize, int bInvert, int bRender); -// -// Draw a string with a fractional scale in both dimensions -// the scale is a 16-bit integer with and 8-bit fraction and 8-bit mantissa -// To draw at 1x scale, set the scale factor to 256. To draw at 2x, use 512 -// The output must be drawn into a memory buffer, not directly to the display -// -int obdScaledString(OBDISP *pOBD, int x, int y, char *szMsg, int iSize, int bInvert, int iXScale, int iYScale); -// -// Draw a string in a proportional font you supply -// Requires a back buffer -// -int obdWriteStringCustom(OBDISP *pOBD, GFXfont *pFont, int x, int y, char *szMsg, uint8_t ucColor); -// -// Get the width of text in a custom font -// -void obdGetStringBox(GFXfont *pFont, char *szMsg, int *width, int *top, int *bottom); -// -// Fill the frame buffer with a byte pattern -// e.g. all off (0x00) or all on (0xff) -// -void obdFill(OBDISP *pOBD, unsigned char ucData, int bRender); -// -// Set (or clear) an individual pixel -// The local copy of the frame buffer is used to avoid -// reading data from the display controller -// (which isn't possible in most configurations) -// This function needs the USE_BACKBUFFER macro to be defined -// otherwise, new pixels will erase old pixels within the same byte -// -int obdSetPixel(OBDISP *pOBD, int x, int y, unsigned char ucColor, int bRender); -// -// Dump an entire custom buffer to the display -// useful for custom animation effects -// -void obdDumpBuffer(OBDISP *pOBD, uint8_t *pBuffer); -// -// Render a window of pixels from a provided buffer or the library's internal buffer -// to the display. The row values refer to byte rows, not pixel rows due to the memory -// layout of OLEDs. Pass a src pointer of NULL to use the internal backing buffer -// returns 0 for success, -1 for invalid parameter -// -int obdDrawGFX(OBDISP *pOBD, uint8_t *pSrc, int iSrcCol, int iSrcRow, int iDestCol, int iDestRow, int iWidth, int iHeight, int iSrcPitch); - -// -// Draw a line between 2 points -// -void obdDrawLine(OBDISP *pOBD, int x1, int y1, int x2, int y2, uint8_t ucColor, int bRender); -// -// Play a frame of animation data -// The animation data is assumed to be encoded for a full frame of the display -// Given the pointer to the start of the compressed data, -// it returns the pointer to the start of the next frame -// Frame rate control is up to the calling program to manage -// When it finishes the last frame, it will start again from the beginning -// -uint8_t * obdPlayAnimFrame(OBDISP *pOBD, uint8_t *pAnimation, uint8_t *pCurrent, int iLen); -void obdWriteCommand(OBDISP *pOBD, unsigned char c); -void obdSetPosition(OBDISP *pOBD, int x, int y, int bRender); -void obdWriteDataBlock(OBDISP *pOBD, unsigned char *ucBuf, int iLen, int bRender); -// -// Scroll the internal buffer by 1 scanline (up/down) -// width is in pixels, lines is group of 8 rows -// Returns 0 for success, -1 for invalid parameter -// -int obdScrollBuffer(OBDISP *pOBD, int iStartCol, int iEndCol, int iStartRow, int iEndRow, int bUp); -// -// Draw a sprite of any size in any position -// If it goes beyond the left/right or top/bottom edges -// it's trimmed to show the valid parts -// This function requires a back buffer to be defined -// The priority color (0 or 1) determines which color is painted -// when a 1 is encountered in the source image. -// e.g. when 0, the input bitmap acts like a mask to clear -// the destination where bits are set. -// -void obdDrawSprite(OBDISP *pOBD, uint8_t *pSprite, int cx, int cy, int iPitch, int x, int y, uint8_t iPriority); -// -// Draw a 16x16 tile in any of 4 rotated positions -// Assumes input image is laid out like "normal" graphics with -// the MSB on the left and 2 bytes per line -// On AVR, the source image is assumed to be in FLASH memory -// The function can draw the tile on byte boundaries, so the x value -// can be from 0 to 112 and y can be from 0 to 6 -// -void obdDrawTile(OBDISP *pOBD, const uint8_t *pTile, int x, int y, int iRotation, int bInvert, int bRender); -// -// Draw an outline or filled ellipse -// -void obdEllipse(OBDISP *pOBD, int iCenterX, int iCenterY, int32_t iRadiusX, int32_t iRadiusY, uint8_t ucColor, uint8_t bFilled); -// -// Draw an outline or filled rectangle -// -void obdRectangle(OBDISP *pOBD, int x1, int y1, int x2, int y2, uint8_t ucColor, uint8_t bFilled); - -// -// Turn the LCD backlight on or off -// -void obdBacklight(OBDISP *pODB, int bOn); - -// -// Menu functions -// -// Initialize the simple menu structure -// -int obdMenuInit(OBDISP *pOBD, SIMPLEMENU *sm, char **pText, int iFontSize, int bCenter, int btnUp, int btnDn, int btnEnter, int iPressedState, int bIsRotary); -// -// Erase the display and show the given menu -// -void obdMenuShow(SIMPLEMENU *sm, int iItem); -// -// Set a callback function to return custom info/status -// for each menu item -// -void obdMenuSetCallback(SIMPLEMENU *sm, SIMPLECALLBACK pfnCallBack); -// -// Display the text of a single menu item -// optionally erases what's under it to prevent left-over text when the length changes -// -void obdMenuShowItem(OBDISP *pOBD, int x, int y, char *szText, int bInvert, int bErase, int iFontSize, int bRender); -// -// Change the menu index incrementally -// redraws the minimum amount of screen to show the new info -// (this prevents flicker/flash and saves battery life) -// returns the new menu index -// -int obdMenuDelta(SIMPLEMENU *sm, int iDelta); -// -// With the given setup, check for button presses -// and act accordingly -// returns -1 for normal interactions and the menu item index if the user presses the ENTER button -// -int obdMenuRun(SIMPLEMENU *sm); - -#if defined(_LINUX_) && defined(__cplusplus) -} -#endif // _LINUX_ - -#endif // __ONEBITDISPLAY__ diff --git a/TLD5542-1LED_DRV_V1.02/TLD5542-1LED_DRV_V1.02.ino b/TLD5542-1LED_DRV_V1.02/TLD5542-1LED_DRV_V1.02.ino deleted file mode 100755 index 0129c7d..0000000 --- a/TLD5542-1LED_DRV_V1.02/TLD5542-1LED_DRV_V1.02.ino +++ /dev/null @@ -1,818 +0,0 @@ -/* - TLD5542-1LED DRIVER SKETCH - - Copyright (c) 2015, Infineon Technologies AG - All rights reserved. - - This sketch implement an LED driver, powered by USB-C PD power adapter, or by a standard power supply - The hardware is the TLD5542-1CHG_USB_SHIELD with OLED display, it has to be plugged on Arduino UNO board - The sketch communicates with the USB barrel cable replacement IC (CYPD3177)and retrieve the maximum - current/Voltage profile available at the USB C power supply. - it is possible to limit the maximum input power sinked by the shield with a user parameter - - Redistribution and use in source and binary forms, with or without modification,are permitted - - 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. - - V1.00 2021/03/13 Initial release - V1.01 2021/04/13 introduced IIN limiter in powerGood function - V1.02 2021/05/05 introduced shield jumpers check -*/ - -// ************************* LIBRARY INCLUDE ********************************* -#include "TLD5542_1_Reg_Layer.h" -#include "TLD5542_1_Func_Layer.h" -#include -#include -#include "OneBitDisplay.h" -#include "BitBang_I2C.h" -#include -#include - -// ************************* HARDWARE DEFINES ********************************* -// ************(SHUNT RESISTORS, VOLTAGE DIVIDERS, REFERENECE VOLTAGE) ****** - -#define RSHO 30 // [mOhm]output current shunt -#define RIIN 80 // [mOhm/10] E.G. 7.5 mOhm write 75 Schematic S05 resitance is 80mOhm -#define RVOFBL 10000UL // [Ohm]Vout ADC resistor divider, lower resistor -#define RVOFBH 100000UL // [Ohm]Vout ADC resistor divider, upper resistor -#define RVIFBL 10000UL // [Ohm]Vin ADC resistor divider, lower resistor -#define RVIFBH 100000UL // [Ohm]Vin ADC resistor divider, upper resistor -#define RVFBH_CAL 100000UL// [Ohm]upper resistor divider for ADC offset calibration (providing 1/11 of VREF) -#define RVFBL_CAL 10000UL // [Ohm]lower resistor divider for ADC offset calibration (providing 1/11 of VREF) -#define REFVOLT 4096UL // [mV]VREF voltage applied to VREF pin -#define IINQUIESCENT 30 // [mA]quiescent current of the shield including arduino shield with OLED ON and TLD5542-1 ON (PWMI = 0) -#define IOUTMON_ZERO 200 // [mV]IOUTMON theorical voltage at zero output current - -// ************************* PIN definition ********************************* -#define CSN_TLD_PIN 10 // TLD5542-1 chip select -#define TLD_EN_PIN 2 // TLD5542-1 Enable pin -#define TLD_PWMI_PIN 3 // TLD5542-1 PWMI pin -#define BUZZER 5 // Buzzer piezo -#define SDA_PIN 8 // Use -1 for the Wire library default pins or specify the pin numbers to use with bit banging on any GPIO pins -#define SCL_PIN 9 // Use -1 for the Wire library default pins or specify the pin numbers to use with bit banging on any GPIO pins -#define GHRG_EN_PIN 4 // Output mosfet to the battery, set to high to enable charge and voltage reading -#define AN_VOUT_PIN A1 // Output voltage sensing on Vdivider -#define AN_VIN_PIN A2 // Input voltage sensing on Vdivider -#define AN_IOUT_PIN A3 // Output current, ADC connected to connected to TLD5542-1 IOUTMON pin (could be eventually skipped and used for NTC) -#define AN_IIN_PIN A4 // Output current, ADC connected to connected to TLD5542-1 IINMON pin -#define AN_KEY_PIN A0 // Keyboard voltage divider -#define AN_CAL A5 // ADC offset calibration input should be VREF applied to RVFBH_CAL and RVFBL_CAL voltage divider - -// ************************* System defines ********************************* -#define VIN_MIN 9000 // minimum input voltage -#define VIN_MAX 30000// MAX input voltage -#define VO_MIN 3500 // minimum output voltage, do not set lower. if lower value is needed then bypass reverse protection mosfet Q6 on the TLd5542-1CHG_SHILED schematic version S05 -#define VOUT_OVERV 30000// MAX output voltage, during open load, with resistor divider on VFB RFBL=10k RFBH=220k it would be 30,6V, use 30V as threshold to detect if no load is connected -#define VO_SHORT 3000 // output voltage below this value is considered a short. -#define IO_MAX (150000/RSHO)// [mA]Max output current -#define IO_MIN (IO_MAX/20)// [mA]Min output current -#define PIN_MIN 10 // minimum input power -#define PIN_MAX 65 // MAX input power, available only at 20V input voltage -#define DUTY_MIN 2 // minimum Duty cycler -#define DUTY_MAX 100 // MAX Duty Cycle -#define IIN_MAX 5500// [mA] MAX input current , limited to 6.2 A (peak includes ripple ) in buck boost and 9.3A in booost mode by the RSWCS 8mOhm resistor on the TLD5542-1CHG_SHIELD -#define RESCAN_DELAY 10 // [ms] -#define KEY_SOUND_MS 10 -#define REPEAT_TOUCH_MS 100 // [ms] start repeating key on a long touch after this period -#define INCREASE_STEP_MA 250// power derating derating output current increase steps (V target / STEP) -#define DECREASE_STEP_MV 250// power derating derating output current decrease steps (V target / STEP) -#define IO_STEP IO_MAX/20// output voltage inc/dec step - -#define EEPROM_INIT 0xFECA //dummy word used to check if user parameters has been written on the EEPROM at least once, in LED DRV (use different on other sketches) - -// ******************** TYPE DEFINITIONS ************************************ - -// BUZZER FREQUENCIES ENUM -// allowed frequencies [Hz] for use with specific buzzer (PS1240P02BT) to achieve higher efficiency -typedef enum freqEnum -{ - FREQ_LOW = 1500, - FREQ_MID_LOW = 2500, - FREQ_MID = 4000, - FREQ_HIGH = 5000, - }frequency; - -// key buttons defines ENUM -// allowed frequencies [Hz] for use with specific buzzer (PS1240P02BT) to achieve higher efficiency. -enum keyEnum -{ - btnNONE =0, - btnENTER =1, - btnUP =2, - btnDOWN =3, - btnMODE =4, - }; - -// FSM machine states -typedef enum FSMstateEnum// charger finite state machine states enum -{ SELF_CHECK, - INIT, - OUTPUT_ON, - FAULT -}FSMstate; - -// chgErrEnum: Possible error code on the charger enum -// being in different bit position it is easy to distinguish when multiple error are happening -enum chgErrEnum -{ NO_ERROR = 0x0000,// task, or function performed without errors - ERR_SPI = 0x0001,// SPI bus error - ERR_IN_VOLT = 0x0002,// input voltage error - ERR_TLD = 0x0004,// TLD5542-1 error - ERR_SHORT = 0x0008,// short circuit at the output - ERR_BAT_OUT = 0x0010,// battery connected at the output of a voltage regulator - ERR_SHIELD = 0x0020,// battery connected at the output of a voltage regulator - ERR_OPEN = 0x0040,// short circuit at the output - ERR_GENERIC = 0X8000 // generic error -}; - -//paramIndex enum: selectable user paramenters index, while navigating in the charger setup menu -enum paramIndex -{ PARAM_IOUT, // SET output voltage - PARAM_PI_MAX, // maximum charger input current - PARAM_DUTY, - MAX_PARAM}; - -//userVarType: struct that contains all the user set variables -typedef struct { - unsigned int IoNom; // [mV] Nominal requested output voltage (will be lowered in case max power is exceeded) - unsigned int PiMax; //[W] max input power - unsigned int Duty; //[%] max input power -}userVarType; - -//chrgVarType: struct that contains all the charger variables -typedef struct { - unsigned int IiMon; - unsigned int outON;// indicate if the output is on - unsigned int IoMon;// ADC reading from the TLD5542-1 IOUTMON pin - unsigned int VoMon; - unsigned int IoSet; // [mV] Set output voltage - unsigned int ViMon; - unsigned int PinMon; - uint8 tldStatus; - chgErrEnum err; - uint32_t usbPDOcurr=0xDEADBEEF; - uint16_t USBmAMax; - uint16_t USBVout; -}chrgVarType; - -// ******************** GLOBAL VARIABLE DECLARATIONS ************************** -int ADCoffs =0; // arduino offset in mV, calculated by -int iInMonOffs =0; // TLD5542-1 iinmonitor offset -int iOutMonOffs =0 ;// TLD5542-1 iinmonitor offset -userVarType userVar{1000, // [mA] default output current - 50, // [W]default input power - 100}; // [%] default pwm % -chrgVarType chrgVar; - -// USB BCR device instance CYPD3177 -BBI2C bbi2c_CYP; // I2C instance for CYPD3177 USB BCR device -#define CYP_I2C_ADDR 0x08 -#define CYP_CURRENT_PDO_ADDR 0x1010 -#define BITMASK10 0x03FF -#define CURRENT_PDO_ADDRH 0x10 // current PDO register address highest 8 bits -#define CURRENT_PDO_ADDRL 0x10 // current PDO register address highest 8 bits - -//OLED DISPLAY instance -static uint8_t *ucBackBuffer = NULL; -OBDISP obd; -char sTmp[32];// temporary string for OLED writing -#define RESET_PIN -1 // let OneBitDisplay figure out the display address. Set this to -1 to disable or the GPIO pin number connected to the reset line -#define OLED_ADDR -1 // unknown OLED address, use I2C discovery -#define FLIP180 0 // don't rotate the display -#define INVERT 0 // don't invert the display -#define USE_HW_I2C 0 // Bit-Bang the I2C bus -#define MY_OLED OLED_128x64 -#define OLED_WIDTH 128 -#define OLED_HEIGHT 64 - -// ******************** FUNCTION DECLARATIONS ******************************* -uint16 readVoltageDivider(int AnalogInput, uint16 rvfbl, uint16 rvfbh); -int read_buttons(); -void setParam(int lcd_key,int paramNum ); -void calADCoffset(); -void calIINMON_IOUTMONoffset(); -uint16 readADCWithOffs(int AnalogInput); -int readIinMon(); -uint16 touchSingle(); - -// ******************** FUNCTION DEFINITIONs ******************************* -void setup() -{ - int tmp, rc; - uint8_t reg_addr[2]= {CURRENT_PDO_ADDRH,CURRENT_PDO_ADDRL};// USB BCR CYPD3177 Register Address of the USB-PD CURRENT_PDO register, where it is present the max current and voltage provided on the USB-PD adater(B19..B10 voltage in 50mV unit) B9..B0 Max current in 10mA units - uint8_t reg_data[4]= {0xDE,0xAD,0xBE,0xEF};// Dummy word to be overwritten when a register is read correctly - int ret_read; - - onSound(); // generate wake up sound - analogReference(EXTERNAL);// set analog reference external - - // Setup for the parameters for SPI communication, set CSN and EN pins as outputs and set EN to High - Serial.begin(9600); // sets the baud rate for communication with the computer to 9600 bauds - pinMode(CSN_TLD_PIN, OUTPUT); // sets CSN as output - digitalWrite(CSN_TLD_PIN, HIGH); // prepare CSN = high o be ready for the first SPI command - pinMode(TLD_EN_PIN, OUTPUT); // sets EN as output - pinMode(TLD_PWMI_PIN, OUTPUT); // sets PWMI as output - pinMode(LED_BUILTIN, OUTPUT); - pinMode(GHRG_EN_PIN, OUTPUT); // - pinMode(AN_IIN_PIN, INPUT); - pinMode(BUZZER, OUTPUT); // Set buzzer - pin as an output - - //setup OLED: If SDA and SCL pins are specified, they would be bit-banged in software, otherwise uses standard I2C bus at 400Khz - rc = obdI2CInit(&obd, MY_OLED, OLED_ADDR, FLIP180, INVERT, USE_HW_I2C, SDA_PIN, SCL_PIN, RESET_PIN, 800000L); - - if (rc != OLED_NOT_FOUND){ - obdSetBackBuffer(&obd, ucBackBuffer); - obdFill(&obd, 0x0, 1);//clear OLED - obdWriteString(&obd, 0,0,0,(char *)" LITIX ", FONT_NORMAL, 0, 1); - obdWriteString(&obd, 0,0,2,(char *)" TLD5542-1 ", FONT_NORMAL, 0, 1); - obdWriteString(&obd, 0,0,4,(char *)" LED DRIVER", FONT_NORMAL, 0, 1); - obdWriteString(&obd, 0,0,6,(char *)" V1.02 ", FONT_NORMAL, 0, 1); - delay(2000); - } - - // setup I2C bitbang library pins for CYPD3177 USB BCR chip - bbi2c_CYP.bWire = 0; // use bit banging - bbi2c_CYP.iSDA = 6; // SDA on GPIO pin - bbi2c_CYP.iSCL = 7; // SCL on GPIO pin - I2CInit(&bbi2c_CYP, 100000); // SDA=pin 10, SCL=pin 11, 100K clock - I2CReadRegister16(&bbi2c_CYP, CYP_I2C_ADDR, ®_addr[0] , reg_data, 4); - chrgVar.usbPDOcurr = (unsigned long)reg_data[0]|(unsigned long)reg_data[1]<<8 | (unsigned long)reg_data[2]<<16 | (unsigned long)reg_data[3]<<24; // combine the 4 read byte - chrgVar.USBmAMax = ((chrgVar.usbPDOcurr )& BITMASK10)*10; // first 10 bits of PDO are mA expressed in [10mA] - chrgVar.USBVout = (((chrgVar.usbPDOcurr>>10 )& BITMASK10)*50)/1000; // second 10 bits of PDO are V expressed in [50mV] - - SPI.begin(); // Initializes the SPI bus for the TLD5542-1 (not really mandatory because OLED library it is intializing) - - calADCoffset(); //calculate ADC offset based on AN_CAL expected voltage - calIINMON_IOUTMONoffset();//calculate IINMON offset -} - -// void sound: generate a beep on the buzzer, at freq frequency -// it is using the enum in order to force the user using resoinances of buzzer -void sound(frequency freq,int ms) -{ - tone(BUZZER, freq); // Send 1KHz sound signal... - delay(ms );// call delay not in power safe - noTone(BUZZER);// stop sound (by stopping compare module) -} -// function onSound: generates "enabling" sound withthe buzzer. E.G. use when the device wakes up -void offSound() -{ - sound(FREQ_HIGH, 60); - delay (60);// pause between each sound - sound(FREQ_LOW, 60); -} -// function offSound: generates "disabling" sound. E.G. use when battery is detached -void onSound() -{ - sound(FREQ_LOW, 60); - delay (60);// pause between each sound - sound(FREQ_HIGH, 60); -} - -// showScreenADC:use when testing the HW for debugging. -// shows ADC readings, exit if a button is pressed -// NOTE: it leaves TLD5542-1 ON -void showScreenADC() -{ - int lcd_key; - uint16 anVout,anVin,anIout, anIin,anKey,anCal,anIinTMP; - uint16 anVoutRaw,anVinRaw,anIoutRaw, anIinRaw,anKeyRaw; - static int i = 0; // counter to show ADC sample count - - digitalWrite(TLD_PWMI_PIN, LOW); // ensure PWMI =0 - digitalWrite(TLD_EN_PIN, HIGH); // turn ON the TLD5542-1 to have IOUTMON - while(1){ - // update adc radings input and output - anVout = readVoltageDivider(AN_VOUT_PIN,(uint32)RVOFBL, (uint32)RVOFBH); - anVin = readVoltageDivider(AN_VIN_PIN,(uint32)RVIFBL,(uint32)RVIFBH); - anIin = readADCWithOffs(AN_IIN_PIN); // read IinMon in mV - anKey = readADCWithOffs(AN_KEY_PIN); - anCal = readADCWithOffs(AN_CAL); - - chrgVar.IiMon = readIinMon();// read iinmon only when TLD5542-1 is enabled - - char outstr[15]; - static int paramNum = 0 ; - i = i+1; // increase ADC refresh count - - obdWriteString(&obd, 0,0,0,sTmp , FONT_NORMAL, 0, 1); - sprintf(sTmp, "anVout %dmV ",anVout); - obdWriteString(&obd, 0,0,1,sTmp , FONT_NORMAL, 0, 1); - sprintf(sTmp, "anVin %dmV ",anVin); - obdWriteString(&obd, 0,0,2,sTmp , FONT_NORMAL, 0, 1); - sprintf(sTmp, "anKey %dmV ",anKey); - obdWriteString(&obd, 0,0,3,sTmp , FONT_NORMAL, 0, 1); - sprintf(sTmp, "Ii %dmV %dmA ",anIin,chrgVar.IiMon); - obdWriteString(&obd, 0,0,5,sTmp , FONT_NORMAL, 0, 1); - sprintf(sTmp, "anCAl %dmV ",anCal); - obdWriteString(&obd, 0,0,6,sTmp , FONT_NORMAL, 0, 1); - sprintf(sTmp, "offs %dmV ",ADCoffs); - obdWriteString(&obd, 0,0,7,sTmp , FONT_NORMAL, 0, 1); - - lcd_key = touchSingle();// uncomment if you want to remain in this loop until a button is pressed - if (lcd_key != btnNONE) // exit loop if a button is pressed - break; - delay(300); - }; -} - -// showScreenSetup: Draws main screen information on OLED display highlighting selected parameter. -// increments and decrement selected parameter calling setParam() -// @param: lcd_key UP/DOWN increase decrease parameter MODE:change selected parameter -void showScreenSetup( int lcd_key) -{ - char outstr[15]; - uint8 invert=0; - static int paramNum = PARAM_IOUT ; - - obdWriteString(&obd, 0,0,0,(char*)"LED DRIVER" , FONT_NORMAL, 0, 1); - if(chrgVar.outON == 1) - sprintf(sTmp, " (ON) " ); - else - sprintf(sTmp, " (OFF)"); - obdWriteString(&obd, 0,-1,-1,sTmp , FONT_NORMAL, 0, 1); - - obdWriteString(&obd, 0,0,2,(char*)" Io PiMax Duty", FONT_NORMAL, 0, 1); // use previous cursor position - - invert = (paramNum == PARAM_IOUT); - sprintf(sTmp, "%d.%02dA",userVar.IoNom/1000,(userVar.IoNom%1000)/10); - obdWriteString(&obd, 0,0,3,sTmp , FONT_NORMAL, invert, 1); // use previous cursor position - - invert = (paramNum == PARAM_PI_MAX); - sprintf(sTmp, " %dW ",userVar.PiMax); - obdWriteString(&obd, 0,-1,3,sTmp , FONT_NORMAL, invert, 1); // use previous cursor position - - invert = (paramNum == PARAM_DUTY); - sprintf(sTmp, " %d%% ",userVar.Duty); - obdWriteString(&obd, 0,-1,3,sTmp , FONT_NORMAL, invert, 1); // use previous cursor position - - if(chrgVar.USBmAMax !=0){ // USB-C with power delivery is applied show maximum power - sprintf(sTmp, "USB %dmA %dV ",chrgVar.USBmAMax,chrgVar.USBVout); - obdWriteString(&obd, 0,0,5,sTmp , FONT_NORMAL, 0, 1); - } - - sprintf(sTmp, "Pi%dW ",chrgVar.PinMon ); - obdWriteString(&obd, 0,0,6,sTmp , FONT_NORMAL, 0, 1); - sprintf(sTmp, "Ii%dmA ", chrgVar.IiMon ); - obdWriteString(&obd, 0,10*6,6,sTmp , FONT_NORMAL, 0, 1); - sprintf(sTmp, "%d.%02dVi %d.%02dVo ",chrgVar.ViMon/1000,(chrgVar.ViMon%1000)/10,chrgVar.VoMon/1000,(chrgVar.VoMon%1000)/10);// show also Vout to double check before pressing start - obdWriteString(&obd, 0,0,7,sTmp , FONT_NORMAL, 0, 1); - - switch(lcd_key) //Switch that select the parameter(btnLEFT) and modify it (with btnUP btnDOWN) - { - case btnMODE:// change which parameter will be modified - paramNum++; - if (paramNum>=MAX_PARAM) - paramNum=0; - break; - case btnUP: // change the parameter value - case btnDOWN:// change the parameter value - setParam(lcd_key, paramNum ); - break; - } -} - -// setParam: increments and decrement selected parameter calling incDec() -// @param: lcd_key UP/DOWN increase decrease parameter -void setParam(int lcd_key, int paramNum ) -{ - switch(paramNum){ - case PARAM_IOUT:// mV - userVar.IoNom = incDec(userVar.IoNom, IO_MAX, IO_MIN ,IO_STEP, lcd_key ); - break; - case PARAM_PI_MAX: - userVar.PiMax = incDec(userVar.PiMax, PIN_MAX, PIN_MIN,5, lcd_key ); - break; - case PARAM_DUTY: - userVar.Duty = incDec(userVar.Duty, DUTY_MAX, DUTY_MIN,2, lcd_key ); - break; - } -} - -// incDec: increment or decrement input value wrapping around on Max val -// @param: input, input number to be incremented/decremented -// @param: limit_max, upper limit for incrementing -// @param: limit_min, lower limit for decrementing -// @param: increment, increment step -// @param: key, keyboard input: btnUP increase , btnDWN decrease -unsigned int incDec(uint16 input, uint16 limit_max,uint16 limit_min, uint16 increment, uint16 key) -{ - if (key==btnUP ) - if (input<=limit_max-increment) - input+=increment; - else - input=limit_max; - if (key==btnDOWN ) - if(input>=limit_min+increment ) - input-=increment; - else - input=limit_min; - return input; -} - -// printError: prints the error string message, on the OLED, in the given x,y position -void printError(int x, int y) -{ - switch(chrgVar.err){ - case NO_ERROR: - sprintf(sTmp, "NO ERROR "); - break; - case ERR_SPI: - sprintf(sTmp, "ERR SPI "); - break; - case ERR_IN_VOLT: - sprintf(sTmp, "ERR IN VOLT "); - break; - case ERR_TLD: - sprintf(sTmp, "TLD5542-1 ERR "); - break; - case ERR_SHORT: - sprintf(sTmp, "OUTPUT SHORT "); - break; - case ERR_OPEN: - sprintf(sTmp, "OUTPUT OPEN "); - break; - case ERR_BAT_OUT: - sprintf(sTmp, "HIGH OUT VOLT "); - break; - case ERR_SHIELD: - sprintf(sTmp, "ERR SHIELD VREG "); - break; - case ERR_GENERIC: - sprintf(sTmp, "GENERIC ERROR"); - break; - default: - sprintf(sTmp, "unknown ERR"); - break; - } - obdWriteString(&obd, 0,x,y,sTmp , FONT_NORMAL, 0, 1); -} - -// powerGood: check if input power and current are below the max rating of the board -// @return: return true if the input power and current are below the Max limits -bool powerGood() -{ - bool powerGood = true; - if ( chrgVar.PinMon > userVar.PiMax){ // check if maximum input power has been exceeded - sprintf(sTmp, " -Pin limited- ",userVar.PiMax ); - powerGood = false; - } - else - if ( chrgVar.IiMon > IIN_MAX){ // if maximum input current has been exceeded - sprintf(sTmp, " -Iin limited- ",userVar.PiMax ); // then display warning in the OLED - powerGood = false; - } - else - sprintf(sTmp, " ",userVar.PiMax ); // delete warning in the OLED - obdWriteString(&obd, 0,0,1,sTmp , FONT_NORMAL, 0, 1); - return powerGood; -} - -// verifyShieldJmpCurr: verify if the shield has been configured as current reglator and not as Voltage reg by applying little output current pulse -// with disconnected load (GHRG_EN_PIN=low),if the shield is configured in current regulator mode the output voltage without load will jump to the overvoltage -// while if it is configured in voltage mode, the low analog dimming will produce a low voltage -bool verifyShieldJmpCurr() -{ - digitalWrite(GHRG_EN_PIN, LOW); //disable battery mosfet before performing Shield HW test (short current pulse in open load) - digitalWrite(TLD_PWMI_PIN, HIGH); // turn ON PWMI - TLD5542_1_analogDimmingCurrentRegulator(500,RSHO); // set current to a very low value, if the shield is configured in current regulator mode the output voltage without load will jump to the overvotlage anyway - delay(50); //wait for vout to rise to the overvoltage , if the shield is correctly configured as current generator - chrgVar.VoMon=readVoltageDivider(AN_VOUT_PIN,(uint32)RVOFBL, (uint32)RVOFBH); - digitalWrite(TLD_PWMI_PIN, LOW); // turn OFF PWMI - delay(200); //wait for Vout to be discharged a little from the overvoltage point - if(chrgVar.VoMon > VOUT_OVERV) // if vout reached the overvoltage the shield is configured correctly **** - return true; - else - return false; -} - -// loop: MAIN LOOP -void loop() -{ - static FSMstateEnum state = SELF_CHECK, prevState;// finite state machine current state and previous state - int lcd_key = btnNONE; - uint32 PinMon; - static uint16 tmp; - - // update adc radings input and output - chrgVar.VoMon = readVoltageDivider(AN_VOUT_PIN,(uint32)RVOFBL, (uint32)RVOFBH); - chrgVar.ViMon = readVoltageDivider(AN_VIN_PIN,(uint32)RVIFBL,(uint32)RVIFBH); - if (digitalRead(TLD_EN_PIN)==1){ - chrgVar.IiMon = readIinMon(); // read iinmon only when TLD5542-1 is enabled - chrgVar.PinMon= ((uint32)chrgVar.IiMon * (uint32)chrgVar.ViMon)/1000000; - } - else{ // if TLD5542-1 is off, I In monitor is not working, so set to 0 - chrgVar.IiMon = 0; - chrgVar.PinMon= 0; - } - - // check if input voltage is OK - if (chrgVar.ViMon < VIN_MIN || chrgVar.ViMon > VIN_MAX ){// if VIN it is not on the allowed range, sigal it and go to FAULT state - chrgVar.err = ERR_IN_VOLT; - state=FAULT; - } - //showScreenADC(); // debug use only to check ADC accuracy during debug - lcd_key = touchSingle();// read keypad - - if (state != prevState) // every time FSM machine change state - obdFill(&obd, 0x0, 1);// clear display - prevState = state; // update FSM state history, in order to detect if state has been changed - - switch(state){ - case SELF_CHECK: // check if HW is working - digitalWrite(TLD_PWMI_PIN, LOW); // turn off PWMI - digitalWrite(TLD_EN_PIN, HIGH); // turn ON the TLD5542-1 - delay(5); - TLD5542_1_Sync_Read_Register(TLD5542_1_STANDARD_DIAGNOSIS_ADDR); - chrgVar.tldStatus = tld5542_1.STANDARD_DIAGNOSIS.STATE; - obdFill(&obd, 0x0, 1);//clear OLED - if(chrgVar.tldStatus!=TLD5542_1_ACTIVE ){ - chrgVar.err = ERR_TLD; - state=FAULT; - } - else{ - if(chrgVar.VoMon if offset is negative means that the ADC reads less than real value, -// offset has to be subtracted from the read to obtain offset free reading: real = ADCread-offs -void calADCoffset() -{ - static uint32 readOffsCal,offsRef; - int lcd_key=btnNONE; - - obdFill(&obd, 0x0, 1);//clear OLED - //calibrate ADC using CSN_A5 pin - readOffsCal = readRaw(AN_CAL);// read pure ADC value on A5 - // calcualte voltage at the pin should be (reference scaled by res divider) - offsRef = ((uint32)REFVOLT * (uint32)RVFBL_CAL)/((uint32)RVFBH_CAL+(uint32)RVFBL_CAL); // [mV] - //offsRef =0;//debug restore previous line - ADCoffs = readOffsCal - offsRef; -} - -// calIINMON_IOUTMONoffset: calculate offset, from typical values on TLD5542-1 IINMON and IOUTMON pins -// offset = read - ideal => if offset is negative means that the ADC reads less than expected, -// offset have to be subtracted from the real = read-offs -void calIINMON_IOUTMONoffset() -{ - uint32 readOffs,tmp; - int lcd_key; - - obdFill(&obd, 0x0, 1);//clear OLED - - digitalWrite(TLD_PWMI_PIN, LOW); // disable PWMI on TLD5542-1 - digitalWrite(TLD_EN_PIN, HIGH); // turn ON the TLD5542-1 - delay(50); // wait for the TLD5542-1 to power up and power consumption to stabilize - - tmp =readADCWithOffs(AN_IIN_PIN);// read ADC value on IINMON, with ADC offset compensated - readOffs =((uint32)tmp*1000)/(RIIN*2);// calculate readed current from IINMON ( RIIN is in [mA/10) , since current has to be in milliampere=> to multiply by 1000) - iInMonOffs =readOffs - IINQUIESCENT; - - // DEBUG: print calibration values - /* sprintf(sTmp, "iimonraw=%d ",tmp); - obdWriteString(&obd, 0,0,0,sTmp , FONT_NORMAL, 0, 1); - sprintf(sTmp, "iInMonMA= %dmA ",readOffs); - obdWriteString(&obd, 0,0,1,sTmp , FONT_NORMAL, 0, 1); - sprintf(sTmp, "iInMonOffs = %dmV ",iInMonOffs); - obdWriteString(&obd, 0,0,2,sTmp , FONT_NORMAL, 0, 1); - delay (4000); - */ - tmp = readADCWithOffs(AN_IOUT_PIN);// read ADC value on IOUTMO, with ADC offset compensated - iOutMonOffs = tmp - IOUTMON_ZERO; -/* DEBUG: print calibration values - sprintf(sTmp, "iOmonraw=%d ",tmp); - obdWriteString(&obd, 0,0,3,sTmp , FONT_NORMAL, 0, 1); - sprintf(sTmp, "iOMonOffs = %dmV ",iOutMonOffs); - obdWriteString(&obd, 0,0,4,sTmp , FONT_NORMAL, 0, 1); - delay(200); // wait to show acquired offsets on display -*/ - digitalWrite(TLD_EN_PIN, LOW); // turn OFF the TLD5542-1 -} - -// read_buttons: Read the keypad buttons on AN_KEY_PIN resistor divider, with debounce -// buttons are supposed to be pressed individually (not more than one simultaneously) -// Buttons are producing 5/6 steps of 5V :0,83V 1,66V 2.5V 3.33V -// @returns: return the pressed button currespondent ENUM -int read_buttons() -{ - uint32 adc_key_mV,tmp; - int key; - - adc_key_mV = readADCWithOffs(AN_KEY_PIN); // read the value from the sensor - // debounce loop, prevents reading on changing keypad - while(1){ - delay(1); - tmp = readADCWithOffs(AN_KEY_PIN); // store keypad ADC in temporary variable, - if ( (adc_key_mV >= (tmp - tmp/16 ) ) && (adc_key_mV <= (tmp + tmp/16 ) ) ) //if the value is not changed (by 1/16) from the last read, means that it is constant - break; //so exit the keyboard debounce loop - else - adc_key_mV = tmp; - }; - readADCWithOffs(AN_KEY_PIN); // read the value from the sensor - - // Buttons are producing aproximately 1/6 steps of 5V: btnNONE=0V btnENTER=0,83V btnUP=1,66V btnDOWN=2.5V btnMODE=3.33V - if (adc_key_mV < 400) return btnNONE; // btnNONE produced voltage is 0V - if (adc_key_mV < 1400) return btnENTER; // btnENTER produced voltage is 830mV - if (adc_key_mV < 2000) return btnUP; // ... - if (adc_key_mV < 2700) return btnDOWN; - return btnMODE; // Highest voltage is produce by btnMODE -} - -// read touch keypad, if a key is pressed , emit a beep , wait 300ms for release -// if key remain pressed longer than REPEAT_TOUCH_MS exit returning the key that was pressed -uint16 touchSingle() -{ - uint16 scan=0,tmp; - static uint16 memory=0;// used to memorize last pressed button - static uint16 stillTouch = 0; - - scan = read_buttons();// read keypad - - if (scan!=btnNONE){ - if(memory!=scan){ - delay(2); - stillTouch=0; - } - - while(1){ // cycle will stop when all keys are released, or after REPEAT_TOUCH_MS to repeat a key - stillTouch++; - delay(RESCAN_DELAY);// count rescan delay before rescanning - if (stillTouch > (REPEAT_TOUCH_MS/RESCAN_DELAY)){ - memory=scan; - delay (2);// rescan delay - break; - } - - tmp = read_buttons();// read keypad - if (tmp==btnNONE) // check No keys are pressed - break; // break while (to return memorized scan) - scan = tmp; // otherwise update scan - } - } - else{ - stillTouch=0; - memory=0; - } - return scan;// return last released pressed button -} - -// readIinMon: reads TLD5542-1 IINMON pin and calculate input current using datasheet formula -// prerequisite: call calIINMON_IOUTMONoffset() to remove offset from IINMON read -int readIinMon() // return IIN in mA -{ - int iinMon; - - iinMon = readADCWithOffs(AN_IIN_PIN); - iinMon = ((long)iinMon*1000)/(RIIN*2) - iInMonOffs;// RIIN is in milliOhm, since current has to be in milliampere , we need to multiply by 1000 - - if (iinMon < 0) - iinMon = 0; - return iinMon; -} - -// readADCWithOffs: read raw ADC value -// no voltage divider moltiplication applied, only oversampling -// @param:AnalogInput, which ADC input is read -uint16 readADCWithOffs(int AnalogInput) -{ - uint32 voltage = 0; // sum of samples taken - - voltage=readRaw(AnalogInput)-ADCoffs; - if (voltage <= -ADCoffs) //If offset is negative , reading can not provide values below that offset (unused analog range) - voltage= 0; - - return voltage; -} - -// readVoltageDivider: read the voltage applied to an ADC by a voltage divider -// @param:AnalogInput , at which ADC input is connected the voltage divider -// @param:rvfbl low side resistor on the voltage divider -// @param:rvfbh high side resistor on the voltage divider -// @returns: voltage applied to the voltage divider [mV] -uint16 readVoltageDivider(int AnalogInput, uint32 rvfbl,uint32 rvfbh) -{ - uint32 sum = 0; // sum of samples taken - unsigned char sample_count = 0; // current sample number - uint32 voltage = 0; // calculated voltage - - // calculate the voltage, refVolt is the calibrated reference voltage in [V] - voltage =readRaw(AnalogInput) - ADCoffs; // 1023 - if (voltage == -ADCoffs) //If offset is negative , reading can not provide values below that offset (unused analog range) - voltage= 0; - voltage = (voltage * (rvfbl+rvfbh))/rvfbl; - - return voltage; -} - -// readRaw: returns adc read in [mV], oversampling NUM_SAMPLES[16] times -// no offset removed or voltage divider, only oversampling -// @param:AnalogInput, which ADC input is read -uint16 readRaw(int AnalogInput) -{ - uint32 sum = 0; // sum of samples taken - unsigned char sample_count = 0; // current sample number - uint16 voltage = 0; // calculated voltage - - #define NUM_SAMPLES 16 - while (sample_count < NUM_SAMPLES) { - sum += analogRead(AnalogInput); - sample_count++; - }; - voltage = ( ((sum * REFVOLT)>>4)/1024 ); // shift by 4 if NUM_SAMPLES is 16 - - return voltage; -} diff --git a/TLD5542-1LED_DRV_V1.02/TLD5542_1_Func_Layer.cpp b/TLD5542-1LED_DRV_V1.02/TLD5542_1_Func_Layer.cpp deleted file mode 100755 index 95c5a2c..0000000 --- a/TLD5542-1LED_DRV_V1.02/TLD5542_1_Func_Layer.cpp +++ /dev/null @@ -1,376 +0,0 @@ -/* - *********************************************************************************************************************** - * - * Copyright (c) 2015, Infineon Technologies AG - * 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. - * - * Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote - * products derived from this software without specific prior written permission. - * - * 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. - * - **********************************************************************************************************************/ -/** - * \file TLD5542_1_Func_Layer.c - * - * \brief TLD5542_1 Functional Layer Source Code - * - * \version V0.0.1 - * \date 18 Mar 2020 - * - * \note - */ - -/******************************************************************************* -** Author(s) Identity ** -******************************************************************************** -** ** -** Initials Name ** -** ---------------------------------------------------------------------------** -** AT Alberto Trentin ** -** ** -*******************************************************************************/ - -/******************************************************************************* -** Revision Control History ** -*******************************************************************************/ -/* - - */ - -#include "TLD5542_1_Func_Layer.h" -#include - - - -/** @brief Controls the regulated output current when TLD5542-1QV is used as current regulator - * \param[in] iout_mA target output current - * \param[in] rfb_mOhm output current shunt sense resistor (see Figure 44 TLD5542-1QV datasheet) - * \return TLD5542-1QV status - * \note TLD5542-1QV Chapter 8, Analog Dimming and Limp Home, Chapter 13 Application information -*/ -TLD5542_1_STATUS TLD5542_1_analogDimmingCurrentRegulator(uint32 iout_mA, uint32 rfb_mOhm){ - - /*Using Register Layer APIs and Defines*/ - uint32 adim_reg = (uint32)((iout_mA * rfb_mOhm * TLD5542_1_ADIM_FS)/TLD5542_1_VFHB_VFBL_REF_uV)+1; - - - if(adim_reg > TLD5542_1_ADIM_FS){ - adim_reg = TLD5542_1_ADIM_FS; - } - - /*Register APIs*/ - tld5542_1.LEDCURRADIM.ADIMVAL = (uint8) adim_reg; - return (TLD5542_1_Sync_Write_Register(TLD5542_1_LEDCURRADIM_ADDR)); - -} - -/** @brief Controls the regulated output voltage when TLD5542-1QV is used as voltage regulator - * \param[in] vout_mV target output voltage - * \param[in] rfb1_Ohm output voltage sense resistor 1 connected to FBH (see Figure 45 TLD5542-1QV datasheet) - * \param[in] rfb2_Ohm output voltage sense resistor 2 Connected to FBL (see Figure 45 TLD5542-1QV datasheet) - * \return TLD5542-1QV status - * \note TLD5542-1QV Chapter 8, Analog Dimming and Limp Home, Chapter 13 Application information -*/ -TLD5542_1_STATUS TLD5542_1_analogDimmingVoltageRegulator(uint32 vout_mV, uint32 rfb2_Ohm, uint32 rfb1_Ohm){ - - //uint32 vfbhvfbl_uV = (((vout_mV * 1000) + (TLD5542_1_IFBL * rfb1_Ohm)) / (rfb1_Ohm + rfb2_Ohm)) * rfb1_Ohm; - uint32 vfbhvfbl_uV = ((vout_mV * 1000*rfb1_Ohm)/(rfb1_Ohm + rfb2_Ohm)) + rfb1_Ohm*TLD5542_1_IFBL; - uint32 adim_reg = ( (vfbhvfbl_uV * TLD5542_1_ADIM_FS)/TLD5542_1_VFHB_VFBL_REF_uV) +1; - - - if(adim_reg > TLD5542_1_ADIM_FS){ - adim_reg = TLD5542_1_ADIM_FS; - } - - tld5542_1.LEDCURRADIM.ADIMVAL = (uint8) adim_reg; - - Serial.print(adim_reg, HEX);// DEBUG - Serial.println(" ADIMREG");// DEBUG - - - return (TLD5542_1_Sync_Write_Register(TLD5542_1_LEDCURRADIM_ADDR)); -} - - -/** @brief Configure Flat spectrum according with options proposed by TLD5542_1_FLATSPECTRUMMODE enum - * \param[in] fsmode flat spectrum configuration - * \return TLD5542-1QV status - * \note TLD5542-1QV Chapter 11, Infineon FLAT SPECTRUM Feature set -*/ - -TLD5542_1_STATUS TLD5542_1_flatSpectrum(TLD5542_1_FLATSPECTRUMMODE fsmode){ - - switch(fsmode){ - case OFF: - tld5542_1.SWTMOD.ENSPREAD = TLD5542_1_SWTMOD_ENSPREAD_DISABLE_SSM; - break; - case FM12KHZ_FEDEV8: - tld5542_1.SWTMOD.ENSPREAD = TLD5542_1_SWTMOD_ENSPREAD_ENABLE_SSM; - tld5542_1.SWTMOD.FMSPREAD = TLD5542_1_SWTMOD_FMSPREAD_12kHz; - tld5542_1.SWTMOD.FDEVSPREAD = TLD5542_1_SWTMOD_FDEVSPREAD_8_PERC; - break; - case FM12KHZ_FEDEV16: - tld5542_1.SWTMOD.ENSPREAD = TLD5542_1_SWTMOD_ENSPREAD_ENABLE_SSM; - tld5542_1.SWTMOD.FMSPREAD = TLD5542_1_SWTMOD_FMSPREAD_12kHz; - tld5542_1.SWTMOD.FDEVSPREAD = TLD5542_1_SWTMOD_FDEVSPREAD_16_PERC; - break; - case FM18KHZ_FEDEV8: - tld5542_1.SWTMOD.ENSPREAD = TLD5542_1_SWTMOD_ENSPREAD_ENABLE_SSM; - tld5542_1.SWTMOD.FMSPREAD = TLD5542_1_SWTMOD_FMSPREAD_18kHz; - tld5542_1.SWTMOD.FDEVSPREAD = TLD5542_1_SWTMOD_FDEVSPREAD_8_PERC; - break; - case FM18KHZ_FEDEV16: - tld5542_1.SWTMOD.ENSPREAD = TLD5542_1_SWTMOD_ENSPREAD_ENABLE_SSM; - tld5542_1.SWTMOD.FMSPREAD = TLD5542_1_SWTMOD_FMSPREAD_18kHz; - tld5542_1.SWTMOD.FDEVSPREAD = TLD5542_1_SWTMOD_FDEVSPREAD_16_PERC; - break; - default: - /*no action*/ - break; - } - - return (TLD5542_1_Sync_Write_Register(TLD5542_1_SWTMOD_ADDR)); -} - - -/** @brief Executes current monitor routine - * - * Starts the current monitor routine with appropriate SPI commands. Polling EOMON flag until the rotuine is finished - * \return TLD5542-1QV status - * \note TLD5542-1QV Chapter 10.4 and 10.5, Input current Monitoring , Output current Monitoring -*/ - -TLD5542_1_STATUS TLD5542_1_currentMonitorRoutine(void){ - TLD5542_1_STATUS status; - uint8 count = 0; - - /*To execute the current monitor routine the CURRMON.SOMON bit has to be set HIGH and the result is ready when CURRMON.EOMON is read HIGH*/ - tld5542_1.CURRMON.EOMON = TLD5542_1_CURRMON_SOMON_START; - status = TLD5542_1_Sync_Write_Register(TLD5542_1_CURRMON_ADDR); - - if(status == TLD5542_1_ACTIVE){ - /*When CURRMON.SOMON bit is set to HIGH both input and output current monitor routines are executed in parallel.*/ - do{ - count ++; - status = TLD5542_1_Sync_Write_Register(TLD5542_1_CURRMON_ADDR); - }while((count < TLD5542_1_CURRMON_TIMEOUT) && (status == TLD5542_1_ACTIVE) && (tld5542_1.CURRMON.EOMON == TLD5542_1_CURRMON_EOMON_NOT_PERFORMED)); - } - - return status; -} - - -/** @brief Executes current calibration routine - * Starts the calibration routine with appropriate SPI commands. Waits the time needed to internally execute the rotuine (250u). - * Polling EOCAL flag until the rotuine is finished - * Before calling this service the user shall prepare TLD5542-1QV as described by the datasheet: - * power the Load with a low analog dimming value (for example 10%) - * Set PWMI = LOW and disconnect the Load at the same time (to avoid Vout drifts from operating conditions and bring the output current to 0)d - * \return TLD5542-1QV status - * \note TLD5542-1QV Chapter 8.2, LED current calibration procedure -*/ - -TLD5542_1_STATUS TLD5542_1_currentCalibrationRoutine(void){ - TLD5542_1_STATUS status; - uint8 count = 0; - - /*uC enables the calibration routine: DVCCTRL.ENCAL = HIGH. When ENCAL = HIGH: the calibration results coming from the routine is used by internal - circuitery and can be read back from LEDCURRCAL.CALIBVAL - */ - tld5542_1.DVCCTRL.ENCAL = TLD5542_1_DVCCTRL_ENCAL_CALIB_AUTO_PROC; - status = TLD5542_1_Sync_Write_Register(TLD5542_1_DVCCTRL_ADDR); - - /*uC starts the calibration routine: LEDCURRCAL.SOCAL = HIGH */ - if(status == TLD5542_1_ACTIVE){ - tld5542_1.LEDCURRCAL.SOCAL = TLD5542_1_LEDCURRCAL_SOCAL_START_CALIB; - status = TLD5542_1_Sync_Write_Register(TLD5542_1_LEDCURRCAL_ADDR); - } - - //waiting time (needed to internally perform the calibration rotuine) --> approx 200us - delay(TLD5542_1_TCALIBEXE); - - if(status == TLD5542_1_ACTIVE){ - /*polling LEDCURRCAL.EOCAL. TLD5542-1QV will set the flag: LEDUCRRCAL.EOCAL = HIGH, when calibration routine has finished*/ - do{ - count ++; - status = TLD5542_1_Sync_Write_Register(TLD5542_1_LEDCURRCAL_ADDR ); - }while((count < TLD5542_1_LEDCURRCAL_TIMEOUT) && (status == TLD5542_1_ACTIVE) && (tld5542_1.LEDCURRCAL.EOCAL == TLD5542_1_LEDCURRCAL_EOCAL_CALIB_NOT_PERFORMED)); - } - - return status; -} - -/** @brief Calculates the best MFS num,den to fit the desired voutF/VoutI ratio. - * - * All the possibile num/den combiantions and the correspondent ratio are stored in a static array (i.e num=9, den=14 --> ratio=643), sorted by ratio - * descending order. The function implements a formula to approximate the position of the ratio (voutF/voutI) in the array. After that an iterative loop - * is used to find out the ratio which most fits the requested one (voutF/voutI). - * \param[in,out] num MFS numerator - * \param[in,out] den MFS denominator - * \param[in] voutinital_mV, \[mV\] measured output voltage before jump - * \param[in] voutfinal_mV \[mV\] target output voltage after jump -* \note TLD5542-1QV Chapter 6.5, Fast Output Discharge Operation Mode - Multi Floating Switches Topology: Set the target Cout Discharge voltage -*/ -void TLD5542_1_mfsNumDenCalc(uint8 *num, uint8 *den, uint32 voutinital_mV, uint32 voutfinal_mV){ - static uint16 ratioLUT [64][3] = - {{12,13,923} ,{10,11,909} ,{9,10,900} ,{8,9,889} ,{7,8,875} ,{6,7,857} ,{11,13,846} ,{5,6,833} ,{9,11,818} ,{4,5,800}, - {11,14,786} ,{7,9,778} ,{10,13,769} ,{3,4,750} ,{11,15,733} ,{8,11,727} ,{5,7,714} ,{7,10,700} ,{9,13,692} ,{2,3,667}, - {9,14,643} ,{7,11,636} ,{5,8,625} ,{8,13,615} ,{3,5,600} ,{4,7,571} ,{5,9,556} ,{6,11,545} ,{7,13,538} ,{8,15,533}, - {1,2,500} ,{7,15,467} ,{6,13,462} ,{5,11,455} ,{4,9,444} ,{3,7,429} ,{2,5,400} ,{5,13,385} ,{3,8,375} ,{4,11,364}, - {5,14,357} ,{1,3,333} ,{4,13,308} ,{3,10,300} ,{2,7,286} ,{3,11,273} ,{4,15,267} ,{1,4,250} ,{3,13,231} ,{2,9,222} , - {3,14,214} ,{1,5,200} ,{2,11,182} ,{1,6,167} ,{2,13,154} ,{1,7,143} ,{2,15,133} ,{1,8,125} ,{1,9,111} ,{1,10,100}, - {1,11,91} ,{1,13,77} ,{1,14,71} ,{1,15,67} - }; - uint32 pos = 0; - bool eos = false; - uint32 ratioTarget = (voutfinal_mV * 1000) / voutinital_mV; - - if (ratioTarget >= 1000){ - *num = 15u; - *den = 1u; - }else if(ratioTarget >= 923){ - *num = 12u; - *den = 13u; - }else if (ratioTarget <= 67){ - *num = 1u; - *den = 15u; - }else{ - pos = ((930 - ratioTarget) << 4) / 229; //formula to calculate the approximated position of the requested ratio Target in the LUT - do{ - if(ratioLUT[pos][2] > ratioTarget){ - pos++; - }else{ - if((ratioLUT[pos-1][2] > ratioTarget)){ - eos = true; - }else{ - pos--; - } - } - }while(eos == false); - *num = (uint8) ratioLUT[pos][0]; - *den = (uint8) ratioLUT[pos][1]; - } -} - - - -/** @brief Calculates the mfsdly value needed to discharghe Cout to a desired final vcomp. - * - * dVcomp = (vcompinitial_mV - vcompfinal_mV ) is translated into TLD5542.MFSSETUP2.MSFDLY value according with system param (CCOMP, FSW, IEA_NEG) - * \param[in] vcompinitial_mV [mV] measured vcomp before initia MFS - * \param[in] vcompfinal_mV [mV] desired vcomp after the end of MFS - * \param[in] ccomp_nF [nF] TLD5542 compensation capacitor value - * \param[in] fsw_kHz [kHz] TLD5542 switching frequency - * \return mfsdly TLD5542 register value to set Ccomp discharge time - * \note TLD5542-1QV Chapter 6.5, Fast Output Discharge Operation Mode - Multi Floating Switches Topology: Preparation Time tprep - * \note mfsdly calculation involves TLD5542-1QV device parameters: compensation capacitor CCOMP[nF], switching frequency fsw[kHz] and - * internal error amplifier current IEA_neg [uA] which may depend on temperature and nominal value accuracy. - * Underestimating mfsdly is source of overshoot while overestimating mfsdly may produces undershoot. - * These variations shall be compensated, for example by reading (periodically) vcomp at the end of mfs and compare with the - * target mfs->vcompfinal_mV. The differnce beetween obtaind values and target can be used to adjust mfsdly calcualtion. -*/ -uint8 TLD5542_1_mfsdlyCalc(uint32 vcompinitial_mV, uint32 vcompfinal_mV, uint32 ccomp_nF, uint32 fsw_kHz){ - uint32 mfsdly = 0; - uint32 tprep_us = 0; - - - if(vcompfinal_mV < vcompinitial_mV){ /*discharge ccomp only when dvcomp > 0 --> vcompF < vcompI*/ - - tprep_us = ((vcompinitial_mV - vcompfinal_mV) * ccomp_nF) / TLD5542_1_IEA_NEG; /*(dvcomp[mV] * ccomp[nF]) / iea_neg[uA] --> u[s]*/ - - mfsdly = ((tprep_us * fsw_kHz) / 1000); /* Euqation 6.7 --> 2+mfsdly = tprep*fsw [us] * [kHz*/ - - if(mfsdly > TLD5542_1_MAX_MFSDLY){ /*be sure mfsdly is not exceeding the maximum allowed value*/ - mfsdly = TLD5542_1_MAX_MFSDLY; - }else if(mfsdly >= 2){ - mfsdly = mfsdly - 2; - }else{} - } - return (uint8) mfsdly; -} - - -/** @brief Sends SPI commands to execute Fast Discharge (denominator, mfsdly, numerator + SOMFS). - * - * The first SPI command to set MFS denominator (LEDCHAIN) is sent out. - * The second SPI command to set MFS mfsdly is sent out - * The third SPI command to set MFS numerator (LEDCHAIN) and start MFS routine (SOMFS) is sent out only when mfsstarttrigger flag becomes false. - * Delay to ensure tsample of FILT capacitor is applied beetween the second and the third SPI command - * \param[in] numerator - * \param[in] denumerator - * \param[in] mfsdly - * \param[in] mfsstarttrigger flag to synchronize SOMFS SPI command - * \return TLD5542-1QV status - * \note TLD5542-1QV Chapter 6.5, Fast Output Discharge Operation Mode - Multi Floating Switches Topology -*/ -TLD5542_1_STATUS TLD5542_1_fastDischargeMFS(uint8 numerator, uint8 denominator, uint8 mfsdly, const bool *waitmfstrigger){ - TLD5542_1_STATUS status; - - tld5542_1.MFSSETUP1.SOMFS = TLD5542_1_MFSSETUP1_SOMFS_NOT_ACTIVE; - - if(denominator > 15){ - tld5542_1.MFSSETUP1.LEDCHAIN = 0x0u; - }else{ - tld5542_1.MFSSETUP1.LEDCHAIN = denominator; - } - - status = TLD5542_1_Sync_Write_Register(TLD5542_1_MFSSETUP1_ADDR); - - if(status == TLD5542_1_ACTIVE){ - tld5542_1.MFSSETUP2.MFSDLY = mfsdly; - status = TLD5542_1_Sync_Write_Register(TLD5542_1_MFSSETUP2_ADDR); - } - - /*The time interval between the Ratio Denominator and Numerator SPI commands (tsample), needs to be long enough to sample - the Initial Voltage of the F.D. in the FILT capacitor. (i.e. with CFILT 220pF, tsmaple > 11 us)*/ - delay(TLD5542_1_TSAMPLEFILT); - - if(status == TLD5542_1_ACTIVE){ - if(numerator > 15){ - tld5542_1.MFSSETUP1.LEDCHAIN = 0x0u; - }else{ - tld5542_1.MFSSETUP1.LEDCHAIN = numerator; - } - tld5542_1.MFSSETUP1.SOMFS = TLD5542_1_MFSSETUP1_SOMFS_ACTIVE; - - while(*waitmfstrigger == true){}; /*wait until boolean trigger to synchronize mfs becomes true*/ - - status = TLD5542_1_Sync_Write_Register(TLD5542_1_MFSSETUP1_ADDR); - } - - return status; -} - - -/** @brief Calculates mfs core controles (mfsdly, num, den) and sends SPI command to execute Fast Discharge - * - * Calculates numerator denominator and mfsdly using data stored into mfs struct. The - * \param[in] mfs collect necessary information to execute mfs - * \param[in] mfsstarttrigger flag to syncronize SOMFS SPI command - * \return TLD5542-1QV status - * \note TLD5542-1QV Chapter 6.5, Fast Output Discharge Operation Mode - Multi Floating Switches Topology -*/ -TLD5542_1_STATUS TLD5542_1_advFastDischargeMFS(const MFS_type* mfs, const bool *waitmfstrigger){ - uint8 numerator, denominator, mfsdly; - - TLD5542_1_mfsNumDenCalc(&numerator, &denominator, mfs->voutinitial_mV, mfs->voutfinal_mV); - mfsdly = TLD5542_1_mfsdlyCalc(mfs->vcompinitial_mV, mfs->vcompfinal_mV, mfs->ccomp_nF, mfs->fsw_kHz); - - return (TLD5542_1_fastDischargeMFS(numerator, denominator, mfsdly, waitmfstrigger)); -} diff --git a/TLD5542-1LED_DRV_V1.02/TLD5542_1_Func_Layer.h b/TLD5542-1LED_DRV_V1.02/TLD5542_1_Func_Layer.h deleted file mode 100755 index a91ce8a..0000000 --- a/TLD5542-1LED_DRV_V1.02/TLD5542_1_Func_Layer.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - *********************************************************************************************************************** - * - * Copyright (c) 2015, Infineon Technologies AG - * 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. - * - * Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote - * products derived from this software without specific prior written permission. - * - * 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. - * - **********************************************************************************************************************/ -/** - * \file TLD5542_1_Func_Layer.h - * - * \brief TLD5542_1 Functional Layer Header - * - * \version V0.0.1 - * \date 18 Mar 2020 - * - * \note - */ - -/******************************************************************************* -** Author(s) Identity ** -******************************************************************************** -** ** -** Initials Name ** -** ---------------------------------------------------------------------------** -** AT Alberto Trentin ** -** ** -*******************************************************************************/ - -/******************************************************************************* -** Revision Control History ** -*******************************************************************************/ -/* - - */ - -#ifndef TLD5542_1_FUNCLAYER_H -#define TLD5542_1_FUNCLAYER_H /**< @brief prevent the contents of TLD5542_1_Func_Layer.h being included more than once*/ - -#include "TLD5542_1_Reg_Layer.h" -//#include "PowerFlex_HAL_Layer.h" - -#define TLD5542_1_VFHB_VFBL_REF_uV 150000UL /**< @brief TLD5542-1QV control loop reference voltage at 100% analog dimming (ADIMVAL 240) [uV]*/ -#define TLD5542_1_ADIM_FS 240UL /**< @brief TLD5542-1QV analog dimming full scale value (100%)*/ -#define TLD5542_1_MAX_MFSDLY 0xFFUL /**< @brief TLD5542-1QV MFSDLY maximum value*/ -#define TLD5542_1_IEA_NEG 56UL /**< @brief TLD5542-1QV error amplifiere neagtive saturation current A6 sense Amp -sat current [uA] */ -#define TLD5542_1_TSAMPLEFILT 11UL /**< @brief TLD5542-1QV Required time interval between the mfs Denominator and Numerator SPI commands */ -#define TLD5542_1_TCALIBEXE 250UL /**< @brief TLD5542-1QV time to internally perform the calibration routine*/ -#define TLD5542_1_LEDCURRCAL_TIMEOUT 100UL /**< @brief Maximum number of consecutive LEDCURRCAL SPI readout before stopping CURRMON.EOCAL polling*/ -#define TLD5542_1_CURRMON_TIMEOUT 8UL /**< @brief Maximum number of consecutive CURRMON SPI readout before stopping CURRMON.EOMON polling*/ -#define TLD5542_1_IFBL 30UL /**< @brief FBL leakage current typ.*/ - -typedef enum{ - OFF = 0, - FM12KHZ_FEDEV8 = 1, - FM12KHZ_FEDEV16 = 2, - FM18KHZ_FEDEV8 = 3, - FM18KHZ_FEDEV16 = 4 -}TLD5542_1_FLATSPECTRUMMODE; /**< @brief Possible Flat Spectrum feature configuration */ - - -typedef struct{ - uint32 voutinitial_mV; /**< @brief Cout (output capacitor) voltage before starting FD [mV]*/ - uint32 vcompinitial_mV; /**< @brief Ccomp (compensation capacitor) voltage before starting Fast Discahrge procedure [mV]*/ - uint32 voutfinal_mV; /**< @brief Target Cout (output capacitor) voltage after the end of Fast Discharge procedure [mV]*/ - uint32 vcompfinal_mV; /**< @brief Target Ccomp (compensation capacitor) voltage after the end of Fast Discharge procedure [mV]*/ - uint32 ccomp_nF; /**< @brief TLD5542-1QV Ccomp (compensation capacitor) value [nF] */ - uint32 fsw_kHz; /**< @brief TLD5542-1QV Switching frequency [kHz]*/ -}MFS_type; /**< @brief Contains information to calculate mfs core control used Fast Discharge procedure */ - -TLD5542_1_STATUS TLD5542_1_analogDimmingCurrentRegulator(uint32 iout_mA, uint32 rfb_mOhm); -TLD5542_1_STATUS TLD5542_1_analogDimmingVoltageRegulator(uint32 vout_mV, uint32 rfb1_Ohm, uint32 rfb2_Ohm); - -TLD5542_1_STATUS TLD5542_1_flatSpectrum(TLD5542_1_FLATSPECTRUMMODE fsmode); - -TLD5542_1_STATUS TLD5542_1_currentMonitorRoutine(void); - -TLD5542_1_STATUS TLD5542_1_currentCalibrationRoutine(void); - -uint8 TLD5542_1_mfsdlyCalc(uint32 vcompinitial_mV, uint32 vcompfinal_mV, uint32 ccomp_nF, uint32 fsw_kHz); -void TLD5542_1_mfsNumDenCalc(uint8 *num, uint8 *den, uint32 voutinital_mV, uint32 voutfinal_mV); -TLD5542_1_STATUS TLD5542_1_fastDischargeMFS(uint8 numerator, uint8 denominator, uint8 mfsdly, const bool *waitmfstrigger); -TLD5542_1_STATUS TLD5542_1_advFastDischargeMFS(const MFS_type* mfs, const bool *waitmfstrigger); - -#endif /* TLD5542_1_FUNCLAYER_H */ diff --git a/TLD5542-1LED_DRV_V1.02/TLD5542_1_Reg_Layer.cpp b/TLD5542-1LED_DRV_V1.02/TLD5542_1_Reg_Layer.cpp deleted file mode 100755 index a4cefd1..0000000 --- a/TLD5542-1LED_DRV_V1.02/TLD5542_1_Reg_Layer.cpp +++ /dev/null @@ -1,750 +0,0 @@ -/* - *********************************************************************************************************************** - * - * Copyright (c) 2015, Infineon Technologies AG - * 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. - * - * Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote - * products derived from this software without specific prior written permission. - * - * 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. - * - **********************************************************************************************************************/ -/** - * \file TLD5542_1_Reg_Layer.c - * - * \brief TLD5542_1 Register Layer Source Code - * - * \version V0.0.1 - * \date 18 Mar 2020 - * - * \note - */ - -/******************************************************************************* -** Author(s) Identity ** -******************************************************************************** -** ** -** Initials Name ** -** ---------------------------------------------------------------------------** -** AT Alberto Trentin ** -** ** -*******************************************************************************/ - -/******************************************************************************* -** Revision Control History ** -*******************************************************************************/ -/* - - */ - -#include "TLD5542_1_Reg_Layer.h" -#include -#include - -// set pin 10 as the slave select for the digital pot: -#define CSN_TLD_PIN 10 - -/***************************************************************************** - Global Defines declaration -*****************************************************************************/ - -#define POWERFLEX_SPI_STANDARD_DIAGNOSIS_MSG 0x0001U /**< @brief TLD5542-1QV/TLD5501-2QV SPI frame to request STD readout*/ -#define POWERFLEX_SPI_STANDARD_DIAGNOSIS_B15_MASK 0x8000U /**< @brief TLD5542-1QV/TLD5501-2QV SPI frame mask to identify SPI STD response (MSB = HIGH)*/ - -#define POWERFLEX_SPI_ACTION_WRITE 0x8000U /**< @brief TLD5542-1QV/TLD5501-2QV SPI frame mask to set SPI WRITE ACTION (MSB = HIGH)*/ -#define POWERFLEX_SPI_ACTION_READ 0x0000U /**< @brief TLD5542-1QV/TLD5501-2QV SPI frame mask to set SPI WRITE ACTION (MSB = LOW)*/ - -#define POWERFLEX_SPI_ADDRESS_OFFSET_SHIFT 8U /**< @brief TLD5542-1QV/TLD5501-2QV SPI frame ADDRESS [b15-b8] postion offset */ -#define POWERFLEX_SPI_ADDRESS_MASK 0x7F00U /**< @brief TLD5542-1QV/TLD5501-2QV SPI frame mask to identify register address [b14-b8]*/ -#define POWERFLEX_SPI_DATA_MASK 0x00FFU /**< @brief TLD5542-1QV/TLD5501-2QV SPI frame mask to identify register data [b7-b0]*/ - - - -/***************************************************************************** - Global Variable declaration -*****************************************************************************/ - -TLD5542_1_Type tld5542_1 = { -0,/*RESERVED*/ -{0x00u,0x00u,0x00u,0x00u,0x00u,0x00u,0x00u,0x00u,0x00u,0x00u,0x00u,0x00u,0x00u},/*STANDARD_DIAGNOSIS_REG_T: TW, TSD, SHRTLED, LEDCUR, IVCCUVLO, OUTOVM, EOCAL, EOMFS, EOMON, TER, STATE, UVLORST, SWRST_BSTUV, fault, reset*/ -{0xF0}, /*LEDCURRADIM_REG_T: ADIMVAL*/ -{0x00,0x00,0x00,0x00}, /*LEDCURRCAL_REG_T: CALIBVAL, EOCAL, SOCAL, DAC_OFF*/ -{0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /*SWTMOD_REG_T: FDEVSPREAD, FMSPREAD, ENSPREAD, S2G_OFF, VFB_VIN_OFF, CCM4EVER, DCM_EN*/ -{0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /*DVCCTRL_REG_T: IDLE, SWRST, CLRLAT, ENCAL, SLOPE, EA_GM, EA_IOUT*/ -{0x08,0x00,0x00,0x00,0x00}, /*MFSSETUP1_REG_T: LEDCHAIN, EOMFS, SOMFS, ILIM_HALF_MFS, EA_IOUT_MFS*/ -{0x80}, /*MFSSETUP2_REG_T: MFSDLY*/ -{0x00,0x00,0x00,0x00}, /*CURRMON_REG_T: */ -{0x00,0x01}, /*REGUSETMON_REG_T*/ -{0x00,0x00,0x00} /*MUXCTRL_REG_T*/ -}; /**< @brief represent a local copy of the entire TLD5542-1QV register bank in the MCU memory*/ - -static const TLD5542_1_Type tld5542_1_default = { -0,/*RESERVED*/ -{0x00u,0x00u,0x00u,0x00u,0x00u,0x00u,0x00u,0x00u,0x00u,0x00u,0x00u,0x00u,0x00u},/*STANDARD_DIAGNOSIS_REG_T: TW, TSD, SHRTLED, LEDCUR, IVCCUVLO, OUTOVM, EOCAL, EOMFS, EOMON, TER, STATE, UVLORST, SWRST_BSTUV, fault, reset*/ -{0xF0}, /*LEDCURRADIM_REG_T: ADIMVAL*/ -{0x00,0x00,0x00,0x00}, /*LEDCURRCAL_REG_T: CALIBVAL, EOCAL, SOCAL, DAC_OFF*/ -{0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /*SWTMOD_REG_T: FDEVSPREAD, FMSPREAD, ENSPREAD, S2G_OFF, VFB_VIN_OFF, CCM4EVER, DCM_EN*/ -{0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /*DVCCTRL_REG_T: IDLE, SWRST, CLRLAT, ENCAL, SLOPE, EA_GM, EA_IOUT*/ -{0x08,0x00,0x00,0x00,0x00}, /*MFSSETUP1_REG_T: LEDCHAIN, EOMFS, SOMFS, ILIM_HALF_MFS, EA_IOUT_MFS*/ -{0x80}, /*MFSSETUP2_REG_T: MFSDLY*/ -{0x00,0x00,0x00,0x00}, /*CURRMON_REG_T: */ -{0x00,0x01}, /*REGUSETMON_REG_T*/ -{0x00,0x00,0x00} /*MUXCTRL_REG_T*/ -}; /**< @brief Rappresent TLD5542-1QV default values. It is used to initialize tld5542_1*/ - - -/***************************************************************************** - Local Functions declaration -*****************************************************************************/ - -static uint16 TLD5542_1_set_SPI_command(TLD5542_1_REG_ADDRESS regadd, TLD5542_1_CMD_TYPE rw); -static void TLD5542_1_get_SPI_response(uint16 response, TLD5542_1_STATUS *status); - -static void TLD5542_1_get_StandardDiagnosisCmd(TLD5542_1_STANDARD_DIAGNOSIS_REG_T *stdreg, uint16 std, TLD5542_1_STATUS *status); - -static void TLD5542_1_set_LedcurradimCmd(const TLD5542_1_LEDCURRADIM_REG_T* ledcurradimreg, uint8 *msb, uint8 *lsb, TLD5542_1_CMD_TYPE rw); -static void TLD5542_1_get_LedcurradimCmd(TLD5542_1_LEDCURRADIM_REG_T* ledcurradimreg, uint8 data); - -static void TLD5542_1_set_LedcurrcalCmd(const TLD5542_1_LEDCURRCAL_REG_T* ledcurrcalreg, uint8 *msb, uint8 *lsb, TLD5542_1_CMD_TYPE rw); -static void TLD5542_1_get_LedcurrcalCmd(TLD5542_1_LEDCURRCAL_REG_T* ledcurrcalreg, uint8 data); - -static void TLD5542_1_set_SwtmodCmd(const TLD5542_1_SWTMOD_REG_T* swtmodreg, uint8 *msb, uint8 *lsb, TLD5542_1_CMD_TYPE rw); -static void TLD5542_1_get_SwtmodCmd(TLD5542_1_SWTMOD_REG_T* swtmodreg, uint8 data); - -static void TLD5542_1_set_DvcctrlCmd(const TLD5542_1_DVCCTRL_REG_T* dvcctrlreg, uint8 *msb, uint8 *lsb, TLD5542_1_CMD_TYPE rw); -static void TLD5542_1_get_DvcctrlCmd(TLD5542_1_DVCCTRL_REG_T* dvcctrlreg, uint8 data); - -static void TLD5542_1_set_Mfssetup1Cmd(const TLD5542_1_MFSSETUP1_REG_T* mfssetup1reg, uint8 *msb, uint8 *lsb, TLD5542_1_CMD_TYPE rw); -static void TLD5542_1_get_Mfssetup1Cmd(TLD5542_1_MFSSETUP1_REG_T* mfssetup1reg, uint8 data); - -static void TLD5542_1_set_Mfssetup2Cmd(const TLD5542_1_MFSSETUP2_REG_T* mfssetup2reg, uint8 *msb, uint8 *lsb, TLD5542_1_CMD_TYPE rw); -static void TLD5542_1_get_Mfssetup2Cmd(TLD5542_1_MFSSETUP2_REG_T* mfssetup2reg, uint8 data); - -static void TLD5542_1_set_CurrmonCmd(const TLD5542_1_CURRMON_REG_T* currmonreg, uint8 *msb, uint8 *lsb, TLD5542_1_CMD_TYPE rw); -static void TLD5542_1_get_CurrmonCmd(TLD5542_1_CURRMON_REG_T* currmonreg, uint8 data); - -static void TLD5542_1_set_RegusetmonCmd(const TLD5542_1_REGUSETMON_REG_T* regusetmonreg, uint8 *msb, uint8 *lsb, TLD5542_1_CMD_TYPE rw); -static void TLD5542_1_get_RegusetmonCmd(TLD5542_1_REGUSETMON_REG_T* regusetmonreg, uint8 data); - -static void TLD5542_1_set_MuxctrlCmd(const TLD5542_1_MUXCTRL_REG_T* muxctrlreg, uint8 *msb, uint8 *lsb, TLD5542_1_CMD_TYPE rw); -static void TLD5542_1_get_MuxctrlCmd(TLD5542_1_MUXCTRL_REG_T* muxctrlreg, uint8 data); - - -/***************************************************************************** - Local Defines declaration -*****************************************************************************/ - - -/* ============================================================================================================= */ -/* ================ TLD5542_1 REG ADDRESS ================ */ -/* ============================================================================================================= */ - -#define TLD5542_1_STANDARDSIAGNOSIS_ADDR_MSB (0x00U) -#define TLD5542_1_LEDCURRADIM_ADDR_MSB (0x00U) -#define TLD5542_1_LEDCURRCAL_ADDR_MSB (0x03U) -#define TLD5542_1_SWTMOD_ADDR_MSB (0x05U) -#define TLD5542_1_DVCCTRL_ADDR_MSB (0x06U) -#define TLD5542_1_MFSSETUP1_ADDR_MSB (0x09U) -#define TLD5542_1_MFSSETUP2_ADDR_MSB (0x0AU) -#define TLD5542_1_CURRMON_ADDR_MSB (0x0CU) -#define TLD5542_1_REGUSETMON_ADDR_MSB (0x0FU) -#define TLD5542_1_MUXCTRL_ADDR_MSB (0x7EU) - -#define TLD5542_1_STANDARDSIAGNOSIS_ADDR_LSB (0x01U) -#define TLD5542_1_LEDCURRADIM_ADDR_LSB (0x00U) -#define TLD5542_1_LEDCURRCAL_ADDR_LSB (0x00U) -#define TLD5542_1_SWTMOD_ADDR_LSB (0x00U) -#define TLD5542_1_DVCCTRL_ADDR_LSB (0x00U) -#define TLD5542_1_MFSSETUP1_ADDR_LSB (0x00U) -#define TLD5542_1_MFSSETUP2_ADDR_LSB (0x00U) -#define TLD5542_1_CURRMON_ADDR_LSB (0x00U) -#define TLD5542_1_REGUSETMON_ADDR_LSB (0x00U) -#define TLD5542_1_MUXCTRL_ADDR_LSB (0x00U) - -/* ============================================================================================================= */ -/* ================ TLD5542_1 REG POS and MASK ================ */ -/* ============================================================================================================= */ - -/* ===================================== STANDARD DIAGNOSIS ==================================================== */ -#define TLD5542_1_STD_SWRST_BSTUV_Pos (14UL) /**< @brief TLD5542_1 STANDARD DIAGNOSIS: SWRST_BSTUV (Bit 14-14*/ -#define TLD5542_1_STD_SWRST_BSTUV_Msk (0x4000UL) /**< @brief TLD5542_1 STANDARD DIAGNOSIS: SWRST_BSTUV (Bitfield-Mask: 0x4000)*/ -#define TLD5542_1_STD_UVLORST_Pos (13U) /**< @brief TLD5542_1 STANDARD DIAGNOSIS: UVLRST (Bit 13-13*/ -#define TLD5542_1_STD_UVLORST_Msk (0x2000UL) /**< @brief TLD5542_1 STANDARD DIAGNOSIS: UVLRST (Bitfield-Mask: 0x2000)*/ -#define TLD5542_1_STD_STATE_Pos (11U) /**< @brief TLD5542_1 STANDARD DIAGNOSIS: STATE (Bit 12-11*/ -#define TLD5542_1_STD_STATE_Msk (0x1800UL) /**< @brief TLD5542_1 STANDARD DIAGNOSIS: STATE (Bitfield-Mask: 0x1800)*/ -#define TLD5542_1_STD_TER_Pos (10U) /**< @brief TLD5542_1 STANDARD DIAGNOSIS: TER (Bit 10-10*/ -#define TLD5542_1_STD_TER_Msk (0x0400UL) /**< @brief TLD5542_1 STANDARD DIAGNOSIS: TER (Bitfield-Mask: 0x0400)*/ -#define TLD5542_1_STD_EOMON_Pos (9U) /**< @brief TLD5542_1 STANDARD DIAGNOSIS: EOMON (Bit 9-9*/ -#define TLD5542_1_STD_EOMON_Msk (0x0200UL) /**< @brief TLD5542_1 STANDARD DIAGNOSIS: EOMON (Bitfield-Mask: 0x0200)*/ -#define TLD5542_1_STD_EOMFS_Pos (8U) /**< @brief TLD5542_1 STANDARD DIAGNOSIS: EOMFS (Bit 8-8*/ -#define TLD5542_1_STD_EOMFS_Msk (0x0100UL) /**< @brief TLD5542_1 STANDARD DIAGNOSIS: EOMFS (Bitfield-Mask: 0x0100)*/ -#define TLD5542_1_STD_EOCAL_Pos (7U) /**< @brief TLD5542_1 STANDARD DIAGNOSIS: EOCAL (Bit 7-7*/ -#define TLD5542_1_STD_EOCAL_Msk (0x0080UL) /**< @brief TLD5542_1 STANDARD DIAGNOSIS: EOCAL (Bitfield-Mask: 0x0080)*/ -#define TLD5542_1_STD_OUTOV_Pos (5U) /**< @brief TLD5542_1 STANDARD DIAGNOSIS: OUTOV (Bit 5-5*/ -#define TLD5542_1_STD_OUTOV_Msk (0x0020UL) /**< @brief TLD5542_1 STANDARD DIAGNOSIS: OUTOV (Bitfield-Mask: 0x0020)*/ -#define TLD5542_1_STD_IVCCUVLO_Pos (4U) /**< @brief TLD5542_1 STANDARD DIAGNOSIS: IVCCUVLO (Bit 4-4*/ -#define TLD5542_1_STD_IVCCUVLO_Msk (0x0010UL) /**< @brief TLD5542_1 STANDARD DIAGNOSIS: IVCCUVLO (Bitfield-Mask: 0x0010)*/ -#define TLD5542_1_STD_LEDCUR_Pos (3U) /**< @brief TLD5542_1 STANDARD DIAGNOSIS: LEDCURR (Bit 3-3*/ -#define TLD5542_1_STD_LEDCUR_Msk (0x0008UL) /**< @brief TLD5542_1 STANDARD DIAGNOSIS: LEDCURR (Bitfield-Mask: 0x0008)*/ -#define TLD5542_1_STD_SHRTLED_Pos (2U) /**< @brief TLD5542_1 STANDARD DIAGNOSIS: SHRTLED (Bit 2-2*/ -#define TLD5542_1_STD_SHRTLED_Msk (0x0004UL) /**< @brief TLD5542_1 STANDARD DIAGNOSIS: SHRTLED (Bitfield-Mask: 0x0004*/ -#define TLD5542_1_STD_TSD_Pos (1U) /**< @brief TLD5542_1 STANDARD DIAGNOSIS: TSD (Bit 1-1*/ -#define TLD5542_1_STD_TSD_Msk (0x0002UL) /**< @brief TLD5542_1 STANDARD DIAGNOSIS: TSD (Bitfield-Mask: 0x0002)*/ -#define TLD5542_1_STD_TW_Pos (0U) /**< @brief TLD5542_1 STANDARD DIAGNOSIS: TW (Bit 0-0*/ -#define TLD5542_1_STD_TW_Msk (0x0001UL) /**< @brief TLD5542_1 STANDARD DIAGNOSIS: TW (Bitfield-Mask: 0x0001)*/ -#define TLD5542_1_STD_ERROR_Msk (0x6437UL) /**< @brief TLD5542_1 STANDARD DIAGNOSIS: SWRST_BSTUV & UVLORST & TER & IVCCUVLO & TSD & TW & SHRTLED (Bitfield-Mask: 0x6413)*/ -//#define TLD5542_1_STD_ERROR_Msk (0x6413UL) /**< @brief TLD5542_1 STANDARD DIAGNOSIS: SWRST_BSTUV & UVLORST & TER & IVCCUVLO & TSD & TW (Bitfield-Mask: 0x6413)*/ -#define TLD5542_1_STD_RESET_Msk (0x4400UL) /**< @brief TLD5542_1 STANDARD DIAGNOSIS: SWRST_BSTUV & TER (Bitfield-Mask: 0x4400)*/ -/* ========================================= LEDCURRADIM ======================================================= */ -#define TLD5542_1_LEDCURRADIM_ADIMVAL_Pos (0U) /**< @brief TLD5542_1 LEDCURRADIM: ADIMVAL (Bit 7-0*/ -#define TLD5542_1_LEDCURRADIM_ADIMVAL_Msk (0xFFU) /**< @brief TLD5542_1 LEDCURRADIM: ADIMVAL (Bitfield-Mask: 0xFF)*/ -/* ========================================== LEDCURRCAL ======================================================= */ -#define TLD5542_1_LEDCURRCAL_DAC_OFF_Pos (6U) /**< @brief TLD5542_1 LEDCURRCAL: DAC_OFF (Bit 6)*/ -#define TLD5542_1_LEDCURRCAL_DAC_OFF_Msk (0x40U) /**< @brief TLD5542_1 LEDCURRCAL: DAC_OFF (Bitfield-Mask: 0x40)*/ -#define TLD5542_1_LEDCURRCAL_SOCAL_Pos (5U) /**< @brief TLD5542_1 LEDCURRCAL: SOCAL (Bit 5)*/ -#define TLD5542_1_LEDCURRCAL_SOCAL_Msk (0x20U) /**< @brief TLD5542_1 LEDCURRCAL: SOCAL (Bitfield-Mask: 0x20)*/ -#define TLD5542_1_LEDCURRCAL_EOCAL_Pos (4U) /**< @brief TLD5542_1 LEDCURRCAL: EOCAL (Bit 4)*/ -#define TLD5542_1_LEDCURRCAL_EOCAL_Msk (0x10U) /**< @brief TLD5542_1 LEDCURRCAL: EOCAL (Bitfield-Mask: 0x10)*/ -#define TLD5542_1_LEDCURRCAL_CALIBVAL_Pos (0U) /**< @brief TLD5542_1 LEDCURRCAL: CALIBVAL (Bit 3-0)*/ -#define TLD5542_1_LEDCURRCAL_CALIBVAL_Msk (0x0FU) /**< @brief TLD5542_1 LEDCURRCAL: CALIBVAL (Bitfield-Mask: 0x0F)*/ -/* ============================================ SWTMOD ========================================================= */ -#define TLD5542_1_SWTMOD_DCM_EN_Pos (6U) /**< @brief TLD5542_1 SWTMOD: DCM_EN (Bit 6)*/ -#define TLD5542_1_SWTMOD_DCM_EN_Msk (0x40U) /**< @brief TLD5542_1 SWTMOD: DCM_EN (Bitfield-Mask: 0x40)*/ -#define TLD5542_1_SWTMOD_CCM4EVER_Pos (5U) /**< @brief TLD5542_1 SWTMOD: CCM4EVER (Bit 5)*/ -#define TLD5542_1_SWTMOD_CCM4EVER_Msk (0x20U) /**< @brief TLD5542_1 SWTMOD: CCM4EVER (Bitfield-Mask: 0x20)*/ -#define TLD5542_1_SWTMOD_VFB_VIN_OFF_Pos (4U) /**< @brief TLD5542_1 SWTMOD: VFB_VIN_OFF (Bit 4)*/ -#define TLD5542_1_SWTMOD_VFB_VIN_OFF_Msk (0x10U) /**< @brief TLD5542_1 SWTMOD: VFB_VIN_OFF (Bitfield-Mask: 0x10)*/ -#define TLD5542_1_SWTMOD_S2G_OFF_Pos (3U) /**< @brief TLD5542_1 SWTMOD: S2G_OFF (Bit 3)*/ -#define TLD5542_1_SWTMOD_S2G_OFF_Msk (0x08U) /**< @brief TLD5542_1 SWTMOD: S2G_OFF (Bitfield-Mask: 0x08)*/ -#define TLD5542_1_SWTMOD_ENSPREAD_Pos (2U) /**< @brief TLD5542_1 SWTMOD: ENSPREAD (Bit 2)*/ -#define TLD5542_1_SWTMOD_ENSPREAD_Msk (0x04U) /**< @brief TLD5542_1 SWTMOD: ENSPREAD (Bitfield-Mask: 0x04)*/ -#define TLD5542_1_SWTMOD_FMSPREAD_Pos (1U) /**< @brief TLD5542_1 SWTMOD: FMSPREAD (Bit 1)*/ -#define TLD5542_1_SWTMOD_FMSPREAD_Msk (0x02U) /**< @brief TLD5542_1 SWTMOD: FMSPREAD (Bitfield-Mask: 0x02)*/ -#define TLD5542_1_SWTMOD_FDEVSPREAD_Pos (0U) /**< @brief TLD5542_1 SWTMOD: FDEVSPREAD (Bit 0)*/ -#define TLD5542_1_SWTMOD_FDEVSPREAD_Msk (0x01U) /**< @brief TLD5542_1 SWTMOD: FDEVSPREAD (Bitfield-Mask: 0x01)*/ -/* =========================================== DVCCTRL ========================================================= */ -#define TLD5542_1_DVCCTRL_EA_IOUT_Pos (7U) /**< @brief TLD5542_1 DVCCTRL: EA_IOUT (Bit 7)*/ -#define TLD5542_1_DVCCTRL_EA_IOUT_Msk (0x80U) /**< @brief TLD5542_1 DVCCTRL: EA_IOUT (Bitfield-Mask: 0x80)*/ -#define TLD5542_1_DVCCTRL_EA_GM_Pos (6U) /**< @brief TLD5542_1 DVCCTRL: EA_GM (Bit 6)*/ -#define TLD5542_1_DVCCTRL_EA_GM_Msk (0x40U) /**< @brief TLD5542_1 DVCCTRL: EA_GM (Bitfield-Mask: 0x40)*/ -#define TLD5542_1_DVCCTRL_SLOPE_Pos (4U) /**< @brief TLD5542_1 DVCCTRL: SLOPE (Bit 5-4)*/ -#define TLD5542_1_DVCCTRL_SLOPE_Msk (0x30U) /**< @brief TLD5542_1 DVCCTRL: SLOPE (Bitfield-Mask: 0x30) */ -#define TLD5542_1_DVCCTRL_ENCAL_Pos (3U) /**< @brief TLD5542_1 DVCCTRL: ENCAL (Bit 3)*/ -#define TLD5542_1_DVCCTRL_ENCAL_Msk (0x08U) /**< @brief TLD5542_1 DVCCTRL: ENCAL (Bitfield-Mask: 0x08)*/ -#define TLD5542_1_DVCCTRL_CLRLAT_Pos (2U) /**< @brief TLD5542_1 DVCCTRL: CLRLAT (Bit 2)*/ -#define TLD5542_1_DVCCTRL_CLRLAT_Msk (0x04U) /**< @brief TLD5542_1 DVCCTRL: CLRLAT (Bitfield-Mask: 0x04)*/ -#define TLD5542_1_DVCCTRL_SWRST_Pos (1U) /**< @brief TLD5542_1 DVCCTRL: SWRST (Bit 1)*/ -#define TLD5542_1_DVCCTRL_SWRST_Msk (0x02U) /**< @brief TLD5542_1 DVCCTRL: SWRST (Bitfield-Mask: 0x02)*/ -#define TLD5542_1_DVCCTRL_IDLE_Pos (0U) /**< @brief TLD5542_1 DVCCTRL: IDLE (Bit 0)*/ -#define TLD5542_1_DVCCTRL_IDLE_Msk (0x01U) /**< @brief TLD5542_1 DVCCTRL: IDLE (Bitfield-Mask: 0x01)*/ -/* ========================================== MFSSETUP1 ======================================================== */ -#define TLD5542_1_MFSSETUP1_EA_IOUT_MFS_Pos (7U) /**< @brief TLD5542_1 MFSSETUP1: EA_IOUT_MFS (Bit 7)*/ -#define TLD5542_1_MFSSETUP1_EA_IOUT_MFS_Msk (0x80U) /**< @brief TLD5542_1 MFSSETUP1: EA_IOUT_MFS (Bitfield-Mask: 0x80)*/ -#define TLD5542_1_MFSSETUP1_ILIM_HALF_MFS_Pos (6U) /**< @brief TLD5542_1 MFSSETUP1: ILIM_HALF_MFS (Bit 6)*/ -#define TLD5542_1_MFSSETUP1_ILIM_HALF_MFS_Msk (0x40U) /**< @brief TLD5542_1 MFSSETUP1: ILIM_HALF_MFS (Bitfield-Mask: 0x40)*/ -#define TLD5542_1_MFSSETUP1_SOMFS_Pos (5U) /**< @brief TLD5542_1 MFSSETUP1: SOMFS_MFS (Bit 5)*/ -#define TLD5542_1_MFSSETUP1_SOMFS_Msk (0x20U) /**< @brief TLD5542_1 MFSSETUP1: SOMFS_MFS (Bitfield-Mask: 0x20)*/ -#define TLD5542_1_MFSSETUP1_EOMFS_Pos (4U) /**< @brief TLD5542_1 MFSSETUP1: EOMFS_MFS (Bit 4)*/ -#define TLD5542_1_MFSSETUP1_EOMFS_Msk (0x10U) /**< @brief TLD5542_1 MFSSETUP1: EOMFS_MFS (Bitfield-Mask: 0x10)*/ -#define TLD5542_1_MFSSETUP1_LEDCHAIN_Pos (0U) /**< @brief TLD5542_1 MFSSETUP1: LEDCHAIN (Bit 3-0)*/ -#define TLD5542_1_MFSSETUP1_LEDCHAIN_Msk (0x0FU) /**< @brief TLD5542_1 MFSSETUP1: LEDCHAIN (Bitfield-Mask: 0x0F)*/ -/* ========================================= MFSSETUP2 ========================================================= */ -#define TLD5542_1_MFSSETUP2_MFSDLY_Pos (0U) /**< @brief TLD5542_1 MFSSETUP2: MFSDLY (Bit 7-0)*/ -#define TLD5542_1_MFSSETUP2_MFSDLY_Msk (0xFFU) /**< @brief TLD5542_1 MFSSETUP2: MFSDLY (Bitfield-Mask: 0xFF)*/ -/* ========================================== CURRMON ========================================================== */ -#define TLD5542_1_CURRMON_SOMON_Pos (5U) /**< @brief TLD5542_1 CURRMON: SOMON (Bit 5)*/ -#define TLD5542_1_CURRMON_SOMON_Msk (0x20U) /**< @brief TLD5542_1 CURRMON: SOMON (Bitfield-Mask: 0x20)*/ -#define TLD5542_1_CURRMON_EOMON_Pos (4U) /**< @brief TLD5542_1 CURRMON: EOMON (Bit 4)*/ -#define TLD5542_1_CURRMON_EOMON_Msk (0x10U) /**< @brief TLD5542_1 CURRMON: EOMON (Bitfield-Mask: 0x10)*/ -#define TLD5542_1_CURRMON_INCURR_Pos (2U) /**< @brief TLD5542_1 CURRMON: INCURR (Bit 3-2)*/ -#define TLD5542_1_CURRMON_INCURR_Msk (0x0CU) /**< @brief TLD5542_1 CURRMON: INCURR (Bitfield-Mask: 0x0C)*/ -#define TLD5542_1_CURRMON_LEDCURR_Pos (0U) /**< @brief TLD5542_1 CURRMON: LEDCURR (Bit 1-0)*/ -#define TLD5542_1_CURRMON_LEDCURR_Msk (0x03U) /**< @brief TLD5542_1 CURRMON: LEDCURR (Bitfield-Mask: 0x03)*/ -/* ========================================= REGUSETMON ======================================================= */ -#define TLD5542_1_REGUSETMON_REGUMODFB_Pos (2U) /**< @brief TLD5542_1 REGUSETMON: REGUMODFB (Bit 3-2)*/ -#define TLD5542_1_REGUSETMON_REGUMODFB_Msk (0x0CU) /**< @brief TLD5542_1 REGUSETMON: REGUMODFB (Bitfield-Mask: 0x0C)*/ -#define TLD5542_1_REGUSETMON_BB_BST_CMP_Pos (0U) /**< @brief TLD5542_1 REGUSETMON: BB_BST_CMP (Bit 1-0)*/ -#define TLD5542_1_REGUSETMON_BB_BST_CMP_Msk (0x03U) /**< @brief TLD5542_1 REGUSETMON: BB_BST_CMP (Bitfield-Mask: 0x03)*/ -/* ========================================== MUXCTRL ========================================================= */ -#define TLD5542_1_MUXCTRL_MFS_REF_Pos (7U) /**< @brief TLD5542_1 MUXCTRL: MFS_REF (Bit 7)*/ -#define TLD5542_1_MUXCTRL_MFS_REF_Msk (0x80U) /**< @brief TLD5542_1 MUXCTRL: MFS_REF (Bitfield-Mask: 0x80)*/ -#define TLD5542_1_MUXCTRL_AMUX_EN_Pos (6U) /**< @brief TLD5542_1 MUXCTRL: AMUX_EN (Bit 6)*/ -#define TLD5542_1_MUXCTRL_AMUX_EN_Msk (0x40U) /**< @brief TLD5542_1 MUXCTRL: AMUX_EN (Bitfield-Mask: 0x40)*/ -#define TLD5542_1_MUXCTRL_SO_MUX_SEL_Pos (0U) /**< @brief TLD5542_1 MUXCTRL: SO_MUX_SEL (Bit 5-0)*/ -#define TLD5542_1_MUXCTRL_SO_MUX_SEL_Msk (0x3FU) /**< @brief TLD5542_1 MUXCTRL: SO_MUX_SEL (Bitfield-Mask: 0x3F)*/ - -/***************************************************************************** - Global Functions definition -*****************************************************************************/ - -/** @brief Resets the global variable tld5542_1 with TLD5542-1QV SPI registers default values (see datasheet 12.6.2- Table14 of TLD5542-1QV datasheet).*/ -void TLD5542_1_resetRegMapLocalCopy(void){ - tld5542_1 = tld5542_1_default; -} - - -void printByte(byte printByte) // This function writes to the serial monitor the value of the byte printByte in binary form -{ - for (int i = 7; i >= 0; i--) - { - Serial.print(bitRead(printByte, i)); - } - Serial.print("\t"); -} - - -bool PowerFlex_Sync_Write_Register(uint16 cmd, uint16 *response){ - bool statusSpi = true; - //Arduino : set SPI speed and mode for powerFlex, - SPI.beginTransaction(SPISettings(2000000, MSBFIRST, SPI_MODE1)); - - digitalWrite(CSN_TLD_PIN, LOW); // take the CSN pin low to select the chip: - byte tmp= cmd>>8; //extract first byte - byte byte0 = SPI.transfer(tmp); // send address byte to the TLE94112 and store the received byte to byte 0 - tmp= cmd&0X00FF; // extract second byte - byte byte1 = SPI.transfer(tmp); // send data byte to the TLE94112 and store the received byte to byte 1 - digitalWrite(CSN_TLD_PIN, HIGH); // take the CSN pin high to terminate the SPI frame - //Arduino - SPI.endTransaction();// stop using SPI bus, allow other libraries to use the SPI bus - - *response= (uint16)byte0<<8 |(uint16)byte1; - return statusSpi; -} - - -/** @brief Transmits a synchronous SPI frame to write an SPI register (user code is blocked during SPI transmission). Received response is used to updated tld5542_1 global variable. - * - *Generates the SPI frame to updated the register using data stored into tld5542_1. Communicate the SPI frame using synchronous APIs offered by - *communication layer. When transmission is over updates tld5542_1 with the received SPI response - *\param[in] regAdd Unique identifier of the TLD5542-1QV SPI register address - *\return TLD5542-1QV status, Quick evaluation of SPI communication -*/ -TLD5542_1_STATUS TLD5542_1_Sync_Write_Register(TLD5542_1_REG_ADDRESS regadd){ - TLD5542_1_STATUS status = TLD5542_1_UNKNOWN; - uint16 response; - uint16 cmd = TLD5542_1_set_SPI_command(regadd, TLD5542_1_WRITE_CMD); - - if(PowerFlex_Sync_Write_Register(cmd, &response) == true){ - TLD5542_1_get_SPI_response(response, &status); - }else{ - status = TLD5542_1_SPI_NOT_OK; - } - - return status; -} - - -/** @brief Transmits one or two synchronous SPI frames to read a SPI register and returns the received SPI responses (user code is blocked during SPI transmissions). - * - *Puts cmd in the SPI transmission buffer. Starts a synchronous SPI transmission. When transmission is over gets the SPI response from the SPI receiver buffer. - *Puts a read STANDARD DIAGNOSIS command in the SPI transmission buffer. Starts a synchronous SPI transmission. When transmission is over gets the SPI response from the SPI receiver buffer. - *The second response shall contain register content requested with the first SPI transmission (cmd). - *If cmd is a STANDARD DIAGNOSIS request and response1 is a STANDARD DIAGNOSIS response, the second SPI frame is not transmitted and response2 is set equal to response1. - *\note TLD5542-1QV and TLD5501-2QV responds with a register content when it has been requested with the previous SPI transmission. In all other cases responds with STANDARD DIAGNOSIS. - *\note See SPI Protocol (chapter 12.5 of TLD5542-1QV/TLD5501-2QV datasheets) - *\param[in] cmd SPI (read register) frame to be transmitted - *\param[in, out] response1 received SPI response to the first (cmd, read register) SPI request - *\param[in, out] response2 received SPI response to the second (STANDARD DIAGNSIS, read register) SPI request - *\return status, true when the activity has been successfully executed, false when the activity has not been executed -*/ -bool PowerFlex_Sync_Read_Register(uint16 cmd, uint16 *response1, uint16 *response2){ - bool statusSpi = false; - if(PowerFlex_Sync_Write_Register(cmd, response1) == true) - { - if((cmd == POWERFLEX_SPI_STANDARD_DIAGNOSIS_MSG) && ((*response1 & POWERFLEX_SPI_STANDARD_DIAGNOSIS_B15_MASK) == 0)){ /*requested register is STANDARD DIAG and received response to the first SPI frame is STANDARD DIAG*/ - *response2 = *response1; - statusSpi = true; - }else{ /*requested register is not STANDARD DIAG or received response to the first SPI command is not standard diagnosis*/ - if(PowerFlex_Sync_Write_Register(POWERFLEX_SPI_STANDARD_DIAGNOSIS_MSG, response2) == true){ - statusSpi = true; - } - } - } - return statusSpi; -} - -/** @brief Transmits one or two consecutive synchronous SPI frame to read an SPI register (user code is blocked during SPI transmissions). Received response is used to updated tld5542_1 global variable - * - *Generates and communicate a first SPI frame to read the requested register - *generates and communicate a second SPI frame to get the register content requested with the first SPI frame - *both SPI communications use synchronous APIs offered by communication layer. - *when transmissions are over updates tld5542_1 with both received SPI responses - *if requested register is STANDARD DIAG the second SPI frame may not be necessary since STARNDARD DIAG is the TLD5542-1QV default SPI response. - *Therefore it may be already received as response of the first SPI communication. - *\param[in] regAdd Unique identifier of the TLD5542-1QV SPI register address - *\return TLD5542-1QV status, Quick evaluation of SPI communication - *\note See SPI Protocol (chapter 12.5 of TLD5542-1QV datasheets) -*/ -TLD5542_1_STATUS TLD5542_1_Sync_Read_Register(TLD5542_1_REG_ADDRESS regadd){ - TLD5542_1_STATUS status = TLD5542_1_UNKNOWN; - uint16 response1, response2; - uint16 cmd = TLD5542_1_set_SPI_command(regadd, TLD5542_1_READ_CMD); - - //ARduino: set SPI speed and mode for powerFlex, - SPI.beginTransaction(SPISettings(2000000, MSBFIRST, SPI_MODE1)); - - if(PowerFlex_Sync_Read_Register(cmd, &response1, &response2) == true){ - TLD5542_1_get_SPI_response(response1, &status); - TLD5542_1_get_SPI_response(response2, &status); - }else{ - status = TLD5542_1_SPI_NOT_OK; - } - - //Arduino - SPI.endTransaction();// stop using SPI bus, allow other libraries to use the SPI bus - - return status; -} - - - - -/***************************************************************************** - Local Functions definition -*****************************************************************************/ - -/** @brief Generates the appropriate SPI frame to write/read an SPI register - *when rw = TLD5542_1_WRITE_CMD generates the SPI frame to updated the register using data stored into tld5542_1, when rw = TLD5542_1_READ_CMD generates the SPI frame to read the - *register. - *\param[in] regAdd Unique identifier of the TLD5542-1QV SPI register address - *\param[in] rw Unique identifier of SPI frame type: TLD5542_1_READ_CMD or TLD5542_1_WRITE_CMD - *\return cmd generated SPI frame to be transmitted -*/ -static uint16 TLD5542_1_set_SPI_command(TLD5542_1_REG_ADDRESS regadd, TLD5542_1_CMD_TYPE rw){ - uint8 msb, lsb; - uint16 cmd; - - switch(regadd){ - case TLD5542_1_STANDARD_DIAGNOSIS_ADDR: - msb = TLD5542_1_STANDARDSIAGNOSIS_ADDR_MSB; - lsb = TLD5542_1_STANDARDSIAGNOSIS_ADDR_LSB; - break; - case TLD5542_1_LEDCURRADIM_ADDR: - TLD5542_1_set_LedcurradimCmd(&tld5542_1.LEDCURRADIM, &msb, &lsb, rw); - break; - case TLD5542_1_LEDCURRCAL_ADDR: - TLD5542_1_set_LedcurrcalCmd(&tld5542_1.LEDCURRCAL, &msb, &lsb, rw); - break; - case TLD5542_1_SWTMOD_ADDR: - TLD5542_1_set_SwtmodCmd(&tld5542_1.SWTMOD, &msb, &lsb, rw); - break; - case TLD5542_1_DVCCTRL_ADDR: - TLD5542_1_set_DvcctrlCmd(&tld5542_1.DVCCTRL, &msb, &lsb, rw); - break; - case TLD5542_1_MFSSETUP1_ADDR: - TLD5542_1_set_Mfssetup1Cmd(&tld5542_1.MFSSETUP1, &msb, &lsb, rw); - break; - case TLD5542_1_MFSSETUP2_ADDR: - TLD5542_1_set_Mfssetup2Cmd(&tld5542_1.MFSSETUP2, &msb, &lsb, rw); - break; - case TLD5542_1_CURRMON_ADDR: - TLD5542_1_set_CurrmonCmd(&tld5542_1.CURRMON, &msb, &lsb, rw); - break; - case TLD5542_1_REGUSETMON_ADDR: - TLD5542_1_set_RegusetmonCmd(&tld5542_1.REGUSETMON, &msb, &lsb, rw); - break; - case TLD5542_1_MUXCTRL_ADDR: - TLD5542_1_set_MuxctrlCmd(&tld5542_1.MUXCTRL, &msb, &lsb, rw); - break; - default: - /*no action*/ - break; - } - - if((rw == TLD5542_1_READ_CMD) || (regadd == TLD5542_1_STANDARD_DIAGNOSIS_ADDR)){ /*read command*/ - cmd = ((((uint16) msb << POWERFLEX_SPI_ADDRESS_OFFSET_SHIFT) & POWERFLEX_SPI_ADDRESS_MASK) | (POWERFLEX_SPI_ACTION_READ) | ((uint16) lsb)); - }else{ /*write command*/ - cmd = ((((uint16) msb << POWERFLEX_SPI_ADDRESS_OFFSET_SHIFT) & POWERFLEX_SPI_ADDRESS_MASK) | (POWERFLEX_SPI_ACTION_WRITE) | ((uint16) lsb)); - } - - return cmd; -} - -/** @brief Updates the gloabal vatiable tld5542_1 according with the received SPI response - *when recived SPI repononse is STANDARD DIAGNOSIS offers a quick evaluation of TLD5542-1QV status. Reporting device power state, communication errors or - *Fault conditions. - *\param[in] regAdd Unique identifier of the TLD5542-1QV SPI register address - *\param[in,out] status, Quick evaluation of SPI communication -*/ -static void TLD5542_1_get_SPI_response(uint16 response, TLD5542_1_STATUS *status){ - uint8 addr, data; - - if((response & POWERFLEX_SPI_STANDARD_DIAGNOSIS_B15_MASK) == 0){/*MSB will be low in case of standard diag response */ - TLD5542_1_get_StandardDiagnosisCmd(&tld5542_1.STANDARD_DIAGNOSIS, response, status); - }else{ - addr = (uint8) ((response & POWERFLEX_SPI_ADDRESS_MASK) >> POWERFLEX_SPI_ADDRESS_OFFSET_SHIFT); - data = (uint8) ((response & POWERFLEX_SPI_DATA_MASK)); - switch(addr){ - case TLD5542_1_LEDCURRADIM_ADDR_MSB: - TLD5542_1_get_LedcurradimCmd(&tld5542_1.LEDCURRADIM, data); - break; - case TLD5542_1_LEDCURRCAL_ADDR_MSB: - TLD5542_1_get_LedcurrcalCmd(&tld5542_1.LEDCURRCAL, data); - break; - case TLD5542_1_SWTMOD_ADDR_MSB: - TLD5542_1_get_SwtmodCmd(&tld5542_1.SWTMOD, data); - break; - case TLD5542_1_DVCCTRL_ADDR_MSB: - TLD5542_1_get_DvcctrlCmd(&tld5542_1.DVCCTRL, data); - break; - case TLD5542_1_MFSSETUP1_ADDR_MSB: - TLD5542_1_get_Mfssetup1Cmd(&tld5542_1.MFSSETUP1, data); - break; - case TLD5542_1_MFSSETUP2_ADDR_MSB: - TLD5542_1_get_Mfssetup2Cmd(&tld5542_1.MFSSETUP2, data); - break; - case TLD5542_1_CURRMON_ADDR_MSB: - TLD5542_1_get_CurrmonCmd(&tld5542_1.CURRMON, data); - break; - case TLD5542_1_REGUSETMON_ADDR_MSB: - TLD5542_1_get_RegusetmonCmd(&tld5542_1.REGUSETMON, data); - break; - case TLD5542_1_MUXCTRL_ADDR_MSB: - TLD5542_1_get_MuxctrlCmd(&tld5542_1.MUXCTRL, data); - break; - default: - *status = TLD5542_1_SPI_NOT_OK; - break; - } - } -} - -/** @brief Update tld5542_1 STANDARD DIAGNOSIS field with SPI response (std) and evaluates the status of TLD5542-1QV. - *\param[in,out] stdreg STANDARD_DIAGNOSIS register - *\param[in] std Standard Diagnosis SPI command - *\param[in,out] status, Quick evaluation of SPI communication - * \returns TLD5542-1QV status -*/ -static void TLD5542_1_get_StandardDiagnosisCmd(TLD5542_1_STANDARD_DIAGNOSIS_REG_T *stdreg, uint16 std, TLD5542_1_STATUS *status){ - - stdreg->TW = (uint8) ((std & TLD5542_1_STD_TW_Msk) >> TLD5542_1_STD_TW_Pos); - stdreg->TSD = (uint8) ((std & TLD5542_1_STD_TSD_Msk) >> TLD5542_1_STD_TSD_Pos); - stdreg->SHRTLED = (uint8) ((std & TLD5542_1_STD_SHRTLED_Msk) >> TLD5542_1_STD_SHRTLED_Pos); - stdreg->LEDCUR = (uint8) ((std & TLD5542_1_STD_LEDCUR_Msk) >> TLD5542_1_STD_LEDCUR_Pos); - stdreg->IVCCUVLO = (uint8) ((std & TLD5542_1_STD_IVCCUVLO_Msk) >> TLD5542_1_STD_IVCCUVLO_Pos); - stdreg->OUTOV = (uint8) ((std & TLD5542_1_STD_OUTOV_Msk) >> TLD5542_1_STD_OUTOV_Pos); - stdreg->EOCAL = (uint8) ((std & TLD5542_1_STD_EOCAL_Msk) >> TLD5542_1_STD_EOCAL_Pos); - stdreg->EOMFS = (uint8) ((std & TLD5542_1_STD_EOMFS_Msk) >> TLD5542_1_STD_EOMFS_Pos); - stdreg->EOMON = (uint8) ((std & TLD5542_1_STD_EOMON_Msk) >> TLD5542_1_STD_EOMON_Pos); - stdreg->TER = (uint8) ((std & TLD5542_1_STD_TER_Msk) >> TLD5542_1_STD_TER_Pos); - stdreg->STATE = (uint8) ((std & TLD5542_1_STD_STATE_Msk) >> TLD5542_1_STD_STATE_Pos); - stdreg->UVLORST = (uint8) ((std & TLD5542_1_STD_UVLORST_Msk) >> TLD5542_1_STD_UVLORST_Pos); - stdreg->SWRST_BSTUV = (uint8) ((std & TLD5542_1_STD_SWRST_BSTUV_Msk) >> TLD5542_1_STD_SWRST_BSTUV_Pos); - - if(stdreg->STATE == TLD5542_1_STD_STATE_ACTIVE){ - *status = TLD5542_1_ACTIVE; - }else if(stdreg->STATE == TLD5542_1_STD_STATE_IDLE){ - *status = TLD5542_1_IDLE; - }else if(stdreg->STATE == TLD5542_1_STD_STATE_LIMPHOME){ - *status = TLD5542_1_LIMPHOME; - }else{ - *status = TLD5542_1_RESERVED; - } - - if((std & TLD5542_1_STD_RESET_Msk) != 0x0000){ - *status = TLD5542_1_RESET; - }else if(((std & TLD5542_1_STD_ERROR_Msk) != 0x0000)){ - *status = TLD5542_1_ERROR; - }else{} -} - - -static void TLD5542_1_set_LedcurradimCmd(const TLD5542_1_LEDCURRADIM_REG_T* ledcurradimreg, uint8 *msb, uint8 *lsb, TLD5542_1_CMD_TYPE rw){ - *msb = TLD5542_1_LEDCURRADIM_ADDR_MSB; - - if(rw == TLD5542_1_READ_CMD){ - *lsb = TLD5542_1_LEDCURRADIM_ADDR_LSB; - }else{ - *lsb = 0x00; - *lsb |= (uint8) ((ledcurradimreg->ADIMVAL << TLD5542_1_LEDCURRADIM_ADIMVAL_Pos) & TLD5542_1_LEDCURRADIM_ADIMVAL_Msk); - } -} - -static void TLD5542_1_get_LedcurradimCmd(TLD5542_1_LEDCURRADIM_REG_T* ledcurradimreg, uint8 data){ - ledcurradimreg->ADIMVAL = (uint8) ((data & TLD5542_1_LEDCURRADIM_ADIMVAL_Msk) >> TLD5542_1_LEDCURRADIM_ADIMVAL_Pos); -} - -static void TLD5542_1_set_LedcurrcalCmd(const TLD5542_1_LEDCURRCAL_REG_T* ledcurrcalreg, uint8 *msb, uint8 *lsb, TLD5542_1_CMD_TYPE rw){ - *msb = TLD5542_1_LEDCURRCAL_ADDR_MSB; - - if(rw == TLD5542_1_READ_CMD){ - *lsb = TLD5542_1_LEDCURRCAL_ADDR_LSB; - }else{ - *lsb = 0x00; - *lsb |= (uint8) (( ledcurrcalreg->CALIBVAL << TLD5542_1_LEDCURRCAL_CALIBVAL_Pos) & TLD5542_1_LEDCURRCAL_CALIBVAL_Msk); - *lsb |= (uint8) (( ledcurrcalreg->SOCAL << TLD5542_1_LEDCURRCAL_SOCAL_Pos) & TLD5542_1_LEDCURRCAL_SOCAL_Msk); - *lsb |= (uint8) (( ledcurrcalreg->DAC_OFF << TLD5542_1_LEDCURRCAL_DAC_OFF_Pos) & TLD5542_1_LEDCURRCAL_DAC_OFF_Msk); - } -} - -static void TLD5542_1_get_LedcurrcalCmd(TLD5542_1_LEDCURRCAL_REG_T* ledcurrcalreg, uint8 data){ - ledcurrcalreg->CALIBVAL = (uint8) ((data & TLD5542_1_LEDCURRCAL_CALIBVAL_Msk) >> TLD5542_1_LEDCURRCAL_CALIBVAL_Pos); - ledcurrcalreg->EOCAL = (uint8) ((data & TLD5542_1_LEDCURRCAL_EOCAL_Msk) >> TLD5542_1_LEDCURRCAL_EOCAL_Pos); - ledcurrcalreg->SOCAL = (uint8) ((data & TLD5542_1_LEDCURRCAL_SOCAL_Msk) >> TLD5542_1_LEDCURRCAL_SOCAL_Pos); - ledcurrcalreg->DAC_OFF = (uint8) ((data & TLD5542_1_LEDCURRCAL_DAC_OFF_Msk) >> TLD5542_1_LEDCURRCAL_DAC_OFF_Pos); -} - -static void TLD5542_1_set_SwtmodCmd(const TLD5542_1_SWTMOD_REG_T* swtmodreg, uint8 *msb, uint8 *lsb, TLD5542_1_CMD_TYPE rw){ - *msb = TLD5542_1_SWTMOD_ADDR_MSB; - - if(rw == TLD5542_1_READ_CMD){ - *lsb = TLD5542_1_SWTMOD_ADDR_LSB; - }else{ - *lsb = 0x00; - *lsb |= (uint8) (( swtmodreg->FDEVSPREAD << TLD5542_1_SWTMOD_FDEVSPREAD_Pos) & TLD5542_1_SWTMOD_FDEVSPREAD_Msk); - *lsb |= (uint8) (( swtmodreg->FMSPREAD << TLD5542_1_SWTMOD_FMSPREAD_Pos) & TLD5542_1_SWTMOD_FMSPREAD_Msk); - *lsb |= (uint8) (( swtmodreg->ENSPREAD << TLD5542_1_SWTMOD_ENSPREAD_Pos) & TLD5542_1_SWTMOD_ENSPREAD_Msk); - *lsb |= (uint8) (( swtmodreg->S2G_OFF << TLD5542_1_SWTMOD_S2G_OFF_Pos) & TLD5542_1_SWTMOD_S2G_OFF_Msk); - *lsb |= (uint8) (( swtmodreg->VFB_VIN_OFF << TLD5542_1_SWTMOD_VFB_VIN_OFF_Pos) & TLD5542_1_SWTMOD_VFB_VIN_OFF_Msk); - *lsb |= (uint8) (( swtmodreg->CCM_4EVER << TLD5542_1_SWTMOD_CCM4EVER_Pos) & TLD5542_1_SWTMOD_CCM4EVER_Msk); - *lsb |= (uint8) (( swtmodreg->DCM_EN << TLD5542_1_SWTMOD_DCM_EN_Pos) & TLD5542_1_SWTMOD_DCM_EN_Msk); - - } -} - -static void TLD5542_1_get_SwtmodCmd(TLD5542_1_SWTMOD_REG_T* swtmodreg, uint8 data){ - swtmodreg->FDEVSPREAD = (uint8) ((data & TLD5542_1_SWTMOD_FDEVSPREAD_Msk) >> TLD5542_1_SWTMOD_FDEVSPREAD_Pos); - swtmodreg->FMSPREAD = (uint8) ((data & TLD5542_1_SWTMOD_FMSPREAD_Msk) >> TLD5542_1_SWTMOD_FMSPREAD_Pos); - swtmodreg->ENSPREAD = (uint8) ((data & TLD5542_1_SWTMOD_ENSPREAD_Msk) >> TLD5542_1_SWTMOD_ENSPREAD_Pos); - swtmodreg->S2G_OFF = (uint8) ((data & TLD5542_1_SWTMOD_S2G_OFF_Msk) >> TLD5542_1_SWTMOD_S2G_OFF_Pos); - swtmodreg->VFB_VIN_OFF = (uint8) ((data & TLD5542_1_SWTMOD_VFB_VIN_OFF_Msk) >> TLD5542_1_SWTMOD_VFB_VIN_OFF_Pos); - swtmodreg->CCM_4EVER = (uint8) ((data & TLD5542_1_SWTMOD_CCM4EVER_Msk) >> TLD5542_1_SWTMOD_CCM4EVER_Pos); - swtmodreg->DCM_EN = (uint8) ((data & TLD5542_1_SWTMOD_DCM_EN_Msk) >> TLD5542_1_SWTMOD_DCM_EN_Pos); -} - - -static void TLD5542_1_set_DvcctrlCmd(const TLD5542_1_DVCCTRL_REG_T* dvcctrlreg, uint8 *msb, uint8 *lsb, TLD5542_1_CMD_TYPE rw){ - *msb = TLD5542_1_DVCCTRL_ADDR_MSB; - - if(rw == TLD5542_1_READ_CMD){ - *lsb = TLD5542_1_DVCCTRL_ADDR_LSB; - }else{ - *lsb = 0x00; - *lsb |= (uint8) (( dvcctrlreg->IDLE << TLD5542_1_DVCCTRL_IDLE_Pos) & TLD5542_1_DVCCTRL_IDLE_Msk); - *lsb |= (uint8) (( dvcctrlreg->SWRST << TLD5542_1_DVCCTRL_SWRST_Pos) & TLD5542_1_DVCCTRL_SWRST_Msk); - *lsb |= (uint8) (( dvcctrlreg->CLRLAT << TLD5542_1_DVCCTRL_CLRLAT_Pos) & TLD5542_1_DVCCTRL_CLRLAT_Msk); - *lsb |= (uint8) (( dvcctrlreg->ENCAL << TLD5542_1_DVCCTRL_ENCAL_Pos) & TLD5542_1_DVCCTRL_ENCAL_Msk); - *lsb |= (uint8) (( dvcctrlreg->SLOPE << TLD5542_1_DVCCTRL_SLOPE_Pos) & TLD5542_1_DVCCTRL_SLOPE_Msk); - *lsb |= (uint8) (( dvcctrlreg->EA_GM << TLD5542_1_DVCCTRL_EA_GM_Pos) & TLD5542_1_DVCCTRL_EA_GM_Msk); - *lsb |= (uint8) (( dvcctrlreg->EA_IOUT << TLD5542_1_DVCCTRL_EA_IOUT_Pos) & TLD5542_1_DVCCTRL_EA_IOUT_Msk); - } -} - -static void TLD5542_1_get_DvcctrlCmd(TLD5542_1_DVCCTRL_REG_T* dvcctrlreg, uint8 data){ - dvcctrlreg->IDLE = (uint8) ((data & TLD5542_1_DVCCTRL_IDLE_Msk) >> TLD5542_1_DVCCTRL_IDLE_Pos); - dvcctrlreg->SWRST = (uint8) ((data & TLD5542_1_DVCCTRL_SWRST_Msk) >> TLD5542_1_DVCCTRL_SWRST_Pos); - dvcctrlreg->CLRLAT = (uint8) ((data & TLD5542_1_DVCCTRL_CLRLAT_Msk) >> TLD5542_1_DVCCTRL_CLRLAT_Pos); - dvcctrlreg->ENCAL = (uint8) ((data & TLD5542_1_DVCCTRL_ENCAL_Msk) >> TLD5542_1_DVCCTRL_ENCAL_Pos); - dvcctrlreg->SLOPE = (uint8) ((data & TLD5542_1_DVCCTRL_SLOPE_Msk) >> TLD5542_1_DVCCTRL_SLOPE_Pos); - dvcctrlreg->EA_GM = (uint8) ((data & TLD5542_1_DVCCTRL_EA_GM_Msk) >> TLD5542_1_DVCCTRL_EA_GM_Pos); - dvcctrlreg->EA_IOUT = (uint8) ((data & TLD5542_1_DVCCTRL_EA_IOUT_Msk) >> TLD5542_1_DVCCTRL_EA_IOUT_Pos); -} - -static void TLD5542_1_set_Mfssetup1Cmd(const TLD5542_1_MFSSETUP1_REG_T* mfssetup1reg, uint8 *msb, uint8 *lsb, TLD5542_1_CMD_TYPE rw){ - *msb = TLD5542_1_MFSSETUP1_ADDR_MSB; - - if(rw == TLD5542_1_READ_CMD){ - *lsb = TLD5542_1_MFSSETUP1_ADDR_LSB; - }else{ - *lsb = 0x00; - *lsb |= (uint8) (( mfssetup1reg->LEDCHAIN << TLD5542_1_MFSSETUP1_LEDCHAIN_Pos) & TLD5542_1_MFSSETUP1_LEDCHAIN_Msk); - *lsb |= (uint8) (( mfssetup1reg->SOMFS << TLD5542_1_MFSSETUP1_SOMFS_Pos) & TLD5542_1_MFSSETUP1_SOMFS_Msk); - *lsb |= (uint8) (( mfssetup1reg->ILIM_HALF_MFS << TLD5542_1_MFSSETUP1_ILIM_HALF_MFS_Pos) & TLD5542_1_MFSSETUP1_ILIM_HALF_MFS_Msk); - *lsb |= (uint8) (( mfssetup1reg->EA_IOUT_MFS << TLD5542_1_MFSSETUP1_EA_IOUT_MFS_Pos) & TLD5542_1_MFSSETUP1_EA_IOUT_MFS_Msk); - } -} - -static void TLD5542_1_get_Mfssetup1Cmd(TLD5542_1_MFSSETUP1_REG_T* mfssetup1reg, uint8 data){ - mfssetup1reg->LEDCHAIN = (uint8) ((data & TLD5542_1_MFSSETUP1_LEDCHAIN_Msk) >> TLD5542_1_MFSSETUP1_LEDCHAIN_Pos); - mfssetup1reg->EOMFS = (uint8) ((data & TLD5542_1_MFSSETUP1_EOMFS_Msk) >> TLD5542_1_MFSSETUP1_EOMFS_Pos); - mfssetup1reg->SOMFS = (uint8) ((data & TLD5542_1_MFSSETUP1_SOMFS_Msk) >> TLD5542_1_MFSSETUP1_SOMFS_Pos); - mfssetup1reg->ILIM_HALF_MFS = (uint8) ((data & TLD5542_1_MFSSETUP1_ILIM_HALF_MFS_Msk) >> TLD5542_1_MFSSETUP1_ILIM_HALF_MFS_Pos); - mfssetup1reg->EA_IOUT_MFS = (uint8) ((data & TLD5542_1_MFSSETUP1_EA_IOUT_MFS_Msk) >> TLD5542_1_MFSSETUP1_EA_IOUT_MFS_Pos); -} - - -static void TLD5542_1_set_Mfssetup2Cmd(const TLD5542_1_MFSSETUP2_REG_T* mfssetup2reg, uint8 *msb, uint8 *lsb, TLD5542_1_CMD_TYPE rw){ - *msb = TLD5542_1_MFSSETUP2_ADDR_MSB; - - if(rw == TLD5542_1_READ_CMD){ - *lsb = TLD5542_1_MFSSETUP2_ADDR_LSB; - }else{ - *lsb = 0x00; - *lsb |= (uint8) (( mfssetup2reg->MFSDLY << TLD5542_1_MFSSETUP2_MFSDLY_Pos) & TLD5542_1_MFSSETUP2_MFSDLY_Msk); - } -} - -static void TLD5542_1_get_Mfssetup2Cmd(TLD5542_1_MFSSETUP2_REG_T* mfssetup2reg, uint8 data){ - mfssetup2reg->MFSDLY = (uint8) ((data & TLD5542_1_MFSSETUP2_MFSDLY_Msk) >> TLD5542_1_MFSSETUP2_MFSDLY_Pos); -} - - -static void TLD5542_1_set_CurrmonCmd(const TLD5542_1_CURRMON_REG_T* currmonreg, uint8 *msb, uint8 *lsb, TLD5542_1_CMD_TYPE rw){ - *msb = TLD5542_1_CURRMON_ADDR_MSB; - - if(rw == TLD5542_1_READ_CMD){ - *lsb = TLD5542_1_CURRMON_ADDR_LSB; - }else{ - *lsb = 0x00; - *lsb |= (uint8) (( currmonreg->SOMON << TLD5542_1_CURRMON_SOMON_Pos) & TLD5542_1_CURRMON_SOMON_Msk); - } -} - -static void TLD5542_1_get_CurrmonCmd(TLD5542_1_CURRMON_REG_T* currmonreg, uint8 data){ - currmonreg->LEDCURR = (uint8) ((data & TLD5542_1_CURRMON_LEDCURR_Msk) >> TLD5542_1_CURRMON_LEDCURR_Pos); - currmonreg->INCURR = (uint8) ((data & TLD5542_1_CURRMON_INCURR_Msk) >> TLD5542_1_CURRMON_INCURR_Pos); - currmonreg->EOMON = (uint8) ((data & TLD5542_1_CURRMON_EOMON_Msk) >> TLD5542_1_CURRMON_EOMON_Pos); - currmonreg->SOMON = (uint8) ((data & TLD5542_1_CURRMON_SOMON_Msk) >> TLD5542_1_CURRMON_SOMON_Pos); -} - -static void TLD5542_1_set_RegusetmonCmd(const TLD5542_1_REGUSETMON_REG_T* regusetmonreg, uint8 *msb, uint8 *lsb, TLD5542_1_CMD_TYPE rw){ - *msb = TLD5542_1_REGUSETMON_ADDR_MSB; - - if(rw == TLD5542_1_READ_CMD){ - *lsb = TLD5542_1_REGUSETMON_ADDR_LSB; - }else{ - *lsb = 0x00; - *lsb |= (uint8) (( regusetmonreg->BB_BST_CMP << TLD5542_1_REGUSETMON_BB_BST_CMP_Pos) & TLD5542_1_REGUSETMON_BB_BST_CMP_Msk); - } -} - -static void TLD5542_1_get_RegusetmonCmd(TLD5542_1_REGUSETMON_REG_T* regusetmonreg, uint8 data){ - regusetmonreg->BB_BST_CMP = (uint8) ((data & TLD5542_1_REGUSETMON_BB_BST_CMP_Msk) >> TLD5542_1_REGUSETMON_BB_BST_CMP_Pos); - regusetmonreg->REGUMODFB = (uint8) ((data & TLD5542_1_REGUSETMON_REGUMODFB_Msk) >> TLD5542_1_REGUSETMON_REGUMODFB_Pos); -} - - -static void TLD5542_1_set_MuxctrlCmd(const TLD5542_1_MUXCTRL_REG_T* muxctrlreg, uint8 *msb, uint8 *lsb, TLD5542_1_CMD_TYPE rw){ - *msb = TLD5542_1_MUXCTRL_ADDR_MSB; - - if(rw == TLD5542_1_READ_CMD){ - *lsb = TLD5542_1_MUXCTRL_ADDR_LSB; - }else{ - *lsb = 0x00; - *lsb |= (uint8) (( muxctrlreg->SO_MUX_SEL << TLD5542_1_MUXCTRL_SO_MUX_SEL_Pos) & TLD5542_1_MUXCTRL_SO_MUX_SEL_Msk); - *lsb |= (uint8) (( muxctrlreg->AMUX_EN << TLD5542_1_MUXCTRL_AMUX_EN_Pos) & TLD5542_1_MUXCTRL_AMUX_EN_Msk); - *lsb |= (uint8) (( muxctrlreg->MFS_REF << TLD5542_1_MUXCTRL_MFS_REF_Pos) & TLD5542_1_MUXCTRL_MFS_REF_Msk); - } -} - -static void TLD5542_1_get_MuxctrlCmd(TLD5542_1_MUXCTRL_REG_T* muxctrlreg, uint8 data){ - muxctrlreg->SO_MUX_SEL = (uint8) ((data & TLD5542_1_MUXCTRL_SO_MUX_SEL_Msk) >> TLD5542_1_MUXCTRL_SO_MUX_SEL_Pos); - muxctrlreg->AMUX_EN = (uint8) ((data & TLD5542_1_MUXCTRL_AMUX_EN_Msk) >> TLD5542_1_MUXCTRL_AMUX_EN_Pos); - muxctrlreg->MFS_REF = (uint8) ((data & TLD5542_1_MUXCTRL_MFS_REF_Msk) >> TLD5542_1_MUXCTRL_MFS_REF_Pos); -} diff --git a/TLD5542-1LED_DRV_V1.02/TLD5542_1_Reg_Layer.h b/TLD5542-1LED_DRV_V1.02/TLD5542_1_Reg_Layer.h deleted file mode 100755 index 3e9ebdb..0000000 --- a/TLD5542-1LED_DRV_V1.02/TLD5542_1_Reg_Layer.h +++ /dev/null @@ -1,470 +0,0 @@ -/* - *********************************************************************************************************************** - * - * Copyright (c) 2015, Infineon Technologies AG - * 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. - * - * Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote - * products derived from this software without specific prior written permission. - * - * 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. - * - **********************************************************************************************************************/ -/** - * \file TLD5542_1_Reg_Layer.h - * - * \brief TLD5542_1 Register Layer Functions - * - * \version V0.0.1 - * \date 18. Mar 2020 - * - * \note - */ - -/******************************************************************************* -** Author(s) Identity ** -******************************************************************************** -** ** -** Initials Name ** -** ---------------------------------------------------------------------------** -** AT Alberto Trentin ** -** ** -*******************************************************************************/ - -/******************************************************************************* -** Revision Control History ** -*******************************************************************************/ -/* - */ - -#ifndef TLD5542_1_REGLAYER_H -#define TLD5542_1_REGLAYER_H /**< @brief prevent the contents of TLD5542_1_Reg_Layer.h being included more than once*/ - -#include - -typedef unsigned char uint8; /**< \brief 8 bit unsigned value */ -typedef unsigned int uint16; /**< \brief 16 bit unsigned value */ -typedef unsigned long uint32; /**< \brief 32 bit unsigned value */ - -typedef signed char sint8; /**< \brief 8 bit signed value */ -typedef signed int sint16; /**< \brief 16 bit signed value */ -typedef signed long sint32; /**< \brief 32 bit signed value */ - -typedef float float32; /**< \brief 32 bit float value */ -typedef double float64; /**< \brief 64 bit float value */ - -typedef short FixPoint16; /**< \brief 16 bit fix point value */ -typedef long FixPoint32; /**< \brief 32 bit fix point value */ - - -/***************************************************************************** - Global Typedef declaration -*****************************************************************************/ -typedef enum{ - TLD5542_1_STANDARD_DIAGNOSIS_ADDR = 1, /**< @brief Standard Diagnosis Register*/ - TLD5542_1_LEDCURRADIM_ADDR = 0, /**< @brief LED Current Configuration Register*/ - TLD5542_1_LEDCURRCAL_ADDR = 3, /**< @brief LED Current Accuracy Trimming Configuration Register*/ - TLD5542_1_SWTMOD_ADDR = 5, /**< @brief Switching Mode Configuration Register*/ - TLD5542_1_DVCCTRL_ADDR = 6, /**< @brief Device Control Register */ - TLD5542_1_MFSSETUP1_ADDR = 9, /**< @brief Multifloat Switch configuration Register */ - TLD5542_1_MFSSETUP2_ADDR = 10, /**< @brief Multifloatswitch configuration register 2 (delay time programming)*/ - TLD5542_1_CURRMON_ADDR = 12, /**< @brief Current Monitor Register */ - TLD5542_1_REGUSETMON_ADDR = 15, /**< @brief Regulation Setup And Monitor Register*/ - TLD5542_1_MUXCTRL_ADDR = 16, /**< @brief Internal Muxes Configuration Register*/ -}TLD5542_1_REG_ADDRESS; /**< @brief Univocally identify each TLD5542-1QV register*/ - -typedef enum{ - TLD5542_1_READ_CMD = 0, /**< @brief read SPI frame. Both MSB [b15] and LSB [b0] are set low*/ - TLD5542_1_WRITE_CMD = 1, /**< @brief write SPI frame. MSB [b15] is set high*/ -}TLD5542_1_CMD_TYPE; /**< @brief Univocally identify the type of SPI command*/ - -typedef enum{ - TLD5542_1_RESERVED = 0, /**< @brief TLD5542-1QV STD.STATE (operation status) is reserved and no fault (except for OUTOV abnd SHRTELD) has been reported*/ - TLD5542_1_LIMPHOME = 1, /**< @brief TLD5542-1QV STD.STATE (operation status) is limphome and no fault (except for OUTOV abnd SHRTELD) has been reported*/ - TLD5542_1_ACTIVE = 2, /**< @brief TLD5542-1QV STD.STATE (operation status) is active and no fault (except for OUTOV abnd SHRTELD) has been reported*/ - TLD5542_1_IDLE = 3, /**< @brief TLD5542-1QV STD.STATE (operation status) is idle and no fault (except for OUTOV abnd SHRTELD) has been reported*/ - TLD5542_1_ERROR = 4, /**< @brief At least one TLD5542-1QV fault beetween(SWRST_BSTUV, UVLORST, TER, IVCCUVLO, TSD, TW has been reported). OUTOV and SHRTLED are ignored*/ - TLD5542_1_RESET = 5, /**< @brief TLD5542-1QV has been resetted since the last SPI readout (SWRST_BSTUV and TER flags are high)*/ - TLD5542_1_SPI_NOT_OK = 6, /**< @brief requested SPI activity has not been accepted*/ - TLD5542_1_UNKNOWN = 7, /**< @brief Received command is not a standard diagnosis*/ -}TLD5542_1_STATUS; /**< @brief Briefly sumarize the status of TLD5542-1QV according with the recived SPI standard diagnosis*/ - - -/* ============================================================================================================= */ -/* ================ TLD5542-1QV Specific Peripheral Section ================ */ -/* ============================================================================================================= */ - -typedef struct { - uint8 ADIMVAL ; /**<@brief [7..0] Analog dimming value*/ -} TLD5542_1_LEDCURRADIM_REG_T ;/**< @brief LED Current Configuration Register*/ - - -typedef struct { - uint8 CALIBVAL ; /**< @brief [3..0] LED current calibration value definition*/ - uint8 EOCAL ; /**< @brief [4..4] End of calibration routine signalling bit*/ - uint8 SOCAL ; /**< @brief [5..5] Start of calibration routine signalling bit*/ - uint8 DAC_OFF ; /**< @brief [6..6] Switch OFF internal analog dimming DAC bit*/ -} TLD5542_1_LEDCURRCAL_REG_T ;/**< @brief LED Current Accuracy Trimming Configuration Register*/ - - -typedef struct { - uint8 FDEVSPREAD ; /**< @brief [0..0] Deviation Frequency fDEV definition*/ - uint8 FMSPREAD ; /**< @brief [1..1] Frequency Modulation Frequency fFM definition*/ - uint8 ENSPREAD ; /**< @brief [2..2] Enable Spread Spectrum feature*/ - uint8 S2G_OFF ; /**< @brief [3..3] Short to GND protection enable Bit*/ - uint8 VFB_VIN_OFF ; /**< @brief [4..4] Vin Feedback Enable on VFB_VIN pin*/ - uint8 CCM_4EVER ; /**< @brief [5..5] Forced Continuous Conduction Mode*/ - uint8 DCM_EN ; /**< @brief [6..6] Enable Bit to allow DCM regulation (MOSFET M4 control)*/ -} TLD5542_1_SWTMOD_REG_T ;/**< @brief Switching Mode Configuration Register*/ - - -typedef struct { - uint8 IDLE ; /**< @brief [0..0] IDLE mode configuration bit*/ - uint8 SWRST ; /**< @brief [1..1] Software reset bit*/ - uint8 CLRLAT ; /**< @brief [2..2] Clear Latch bit*/ - uint8 ENCAL ; /**< @brief [3..3] Enable automatic output current calibration bit*/ - uint8 SLOPE ; /**< @brief [5..4] slope compensation strenght*/ - uint8 EA_GM ; /**< @brief [6..6] Increase the gain of the error amplifier, active only when output current is below 80% of target (i.e. < VFBH_FBL_EA )*/ - uint8 EA_IOUT ; /**< @brief [7..7] Bit to decrease the saturation current of the error amplifier in current mode control loop*/ -} TLD5542_1_DVCCTRL_REG_T ;/**< @brief Device Control Register */ - - -typedef struct { - uint8 LEDCHAIN ; /**< @brief [3..0] MFS ratio bits: set MFS jump ratio*/ - uint8 EOMFS ; /**< @brief [4..4] End of MFS routine bit*/ - uint8 SOMFS ; /**< @brief [5..5] Start of MFS routine bit*/ - uint8 ILIM_HALF_MFS ; /**< @brief [6..6] Bit to decrease the Switch Current Limit (ISwLim) during F.D. operation*/ - uint8 EA_IOUT_MFS ; /**< @brief [7..7] Bit to decrease the saturation current of the error amplifier (A6) in current mode control loop only during MFS routin*/ -} TLD5542_1_MFSSETUP1_REG_T ; /**< @brief Multifloat Switch configuration Register */ - - -typedef struct { - uint8 MFSDLY ; /**< @brief [7..0] delay time programming*/ -} TLD5542_1_MFSSETUP2_REG_T ; /**< @brief Multifloatswitch configuration register 2 (delay time programming)*/ - - -typedef struct { - uint8 LEDCURR ; /**< @brief [1..0] Status of the LED Current bits*/ - uint8 INCURR ; /**< @brief [3..2] Status of the Input Current bits*/ - uint8 EOMON ; /**< @brief [4..4] End of LED/Input Current Monitoring bit*/ - uint8 SOMON ; /**< @brief [5..5] Start of LED/Input Current Monitoring bit*/ -} TLD5542_1_CURRMON_REG_T ; /**< @brief Current Monitor Register */ - - -typedef struct { - uint8 BB_BST_CMP ; /**< @brief [1..0] Buck boost to Boost transition compensation level*/ - uint8 REGUMODFB ; /**< @brief [3..2] Feedback of Regulation Mode bits*/ -} TLD5542_1_REGUSETMON_REG_T ; /**< @brief Regulation Setup And Monitor Register*/ - - -typedef struct { - uint8 SO_MUX_SEL ; /**< @brief [5..0] Digital Multiplexer selector, output on SO pin*/ - uint8 AMUX_EN ; /**< @brief [3..2] Analog Mux enable, output on FILT pin*/ - uint8 MFS_REF ; /**< @brief [3..2] MFS reference to FILT pin Path Enable*/ -} TLD5542_1_MUXCTRL_REG_T; /**< @brief Internal Muxes Configuration Register*/ - - -typedef struct { - uint8 TW ; /**< @brief [0..0] Over Temperature Warning*/ - uint8 TSD ; /**< @brief [1..1] Over Temperature Shutdown*/ - uint8 SHRTLED ; /**< @brief [2..2] Shorted LED Diagnosis*/ - uint8 LEDCUR ; /**< @brief [3..3] LED Current Flag (see LEDCUR pin description Chapter10.5)*/ - uint8 IVCCUVLO ; /**< @brief [4..4] IVCC or IVCC_EXT Undervoltage Lockout Monitor*/ - uint8 OUTOV ; /**< @brief [5..5] Output overvoltage Monitor*/ - uint8 EOCAL ; /**< @brief [7..7] End of Calibration Routine*/ - uint8 EOMFS ; /**< @brief [8..8] End of MFS Routine Bit*/ - uint8 EOMON ; /**< @brief [9..9] End of LED/Input Current Monitor Routine Bit*/ - uint8 TER ; /**< @brief [10..10] Transmission Error*/ - uint8 STATE ; /**< @brief [12..11] Operative State Monitor*/ - uint8 UVLORST ; /**< @brief [13..13] VDD OR VEN/INUVLO Undervoltage Monitor*/ - uint8 SWRST_BSTUV ; /**< @brief [14..14] SWRST OR VBSTx-VSWNx_UVth Monitor*/ -} TLD5542_1_STANDARD_DIAGNOSIS_REG_T; /**< @brief Standard Diagnosis */ - - -typedef struct{ - uint8 RESERVED; /**< @brief Not used*/ - TLD5542_1_STANDARD_DIAGNOSIS_REG_T STANDARD_DIAGNOSIS; /**< @brief The Standard Diagnosis reports several diagnostic informations and the status of the device and the utility routine*/ - TLD5542_1_LEDCURRADIM_REG_T LEDCURRADIM; /**< @brief LED Current Configuration Register*/ - TLD5542_1_LEDCURRCAL_REG_T LEDCURRCAL; /**< @brief LED Current Accuracy Trimming Configuration Register*/ - TLD5542_1_SWTMOD_REG_T SWTMOD; /**< @brief Switching Mode Configuration Register*/ - TLD5542_1_DVCCTRL_REG_T DVCCTRL; /**< @brief Device Control Register */ - TLD5542_1_MFSSETUP1_REG_T MFSSETUP1; /**< @brief Multifloat Switch configuration Register */ - TLD5542_1_MFSSETUP2_REG_T MFSSETUP2; /**< @brief Multifloatswitch configuration register 2 (delay time programming)*/ - TLD5542_1_CURRMON_REG_T CURRMON; /**< @brief Current Monitor Register */ - TLD5542_1_REGUSETMON_REG_T REGUSETMON; /**< @brief Regulation Setup And Monitor Register*/ - TLD5542_1_MUXCTRL_REG_T MUXCTRL; /**< @brief Internal Muxes Configuration Register*/ -} TLD5542_1_Type; /**< @brief represent a local copy of the entire TLD5542-1QV register bank in the MCU memory*/ - - -/***************************************************************************** - Global Variables declaration -*****************************************************************************/ -extern TLD5542_1_Type tld5542_1; - - -/***************************************************************************** - Global Functions declaration -*****************************************************************************/ -void TLD5542_1_resetRegMapLocalCopy(void); - -/*syncronous SPI transmission*/ -TLD5542_1_STATUS TLD5542_1_Sync_Write_Register(TLD5542_1_REG_ADDRESS regadd); -TLD5542_1_STATUS TLD5542_1_Sync_Read_Register(TLD5542_1_REG_ADDRESS regadd); - -/*asyncronous SPI transmission*/ -TLD5542_1_STATUS TLD5542_1_Async_Transmit_Command(TLD5542_1_REG_ADDRESS regadd, TLD5542_1_CMD_TYPE rw); -TLD5542_1_STATUS TLD5542_1_Async_Get_Response(void); -bool TLD5542_1_Async_EoTx_Notification(void); - -void TLD5542_1_testwrite(void); -void TLD5542_1_testread(void); - -/***************************************************************************** - Global Defines declaration -*****************************************************************************/ - -/* ============================================================================================================= */ -/* ================ TLD5542_1 BITFIELDS VALUES ================ */ -/* ============================================================================================================= */ - -/** ------------------------------------------------------------------------------------------------------------**/ -/* LEDCURRCAL: LED Current Accuracy Trimming Configuration Register*/ -/** ------------------------------------------------------------------------------------------------------------**/ - -/* bit 6 r/w, Switch OFF internal analog dimming DAC bit*/ -#define TLD5542_1_LEDCURRCAL_DAC_OFF_ENABLE_DAC 0U /**< @brief (default) internal DAC active */ -#define TLD5542_1_LEDCURRCAL_DAC_OFF_DISABLE_DAC 1U /**< @brief internal DAC inactive and analog dimming error amplifier mapped to SET pin */ - -/* bit 5 r/w, Start of calibration routine signalling bit*/ -#define TLD5542_1_LEDCURRCAL_SOCAL_NO_CALIB_STARTED 0U /**< @brief (default) no calibration routine started */ -#define TLD5542_1_LEDCURRCAL_SOCAL_START_CALIB 1U /**< @brief calibration routine start (autoclear) */ - - -/* bit 4 r, End of calibration routine signalling bit*/ -#define TLD5542_1_LEDCURRCAL_EOCAL_CALIB_NOT_PERFORMED 0U /**< @brief (default) calibration routine not completed, not successfully performed or never run */ -#define TLD5542_1_LEDCURRCAL_EOCAL_CALIB_PERFORMED 1U /**< @brief calibration successfully performed (is reset to 0B when SOCAL is set to 1B) */ - -/** ------------------------------------------------------------------------------------------------------------**/ -/* SWTMOD: Switching Mode Configuration Register */ -/** ------------------------------------------------------------------------------------------------------------**/ - -/* bit 6 r/w, Enable Bit to allow DCM regulation (MOSFET M4 control)*/ -#define TLD5542_1_SWTMOD_DCM_EN_DISABLE_DCM 0U /**< @brief (default) DCM is disabled (M4 alternately switching) */ -#define TLD5542_1_SWTMOD_DCM_EN_ENABLE_DCM 1U /**< @brief DCM is enabled (M4 is permanently OFF) */ - -/* bit 5 r/w, Forced Continuous Conduction Mode*/ -#define TLD5542_1_SWTMOD_CCM_4EVER_AFTER_SS 0U /**< @brief (default) Forced CCM after soft start finish */ -#define TLD5542_1_SWTMOD_CCM_4EVER_DURING_SS 1U /**< @brief Forced CCM even during soft start ramp up */ - -/* bit 4 r/w, Vin Feedback Enable on VFB_VIN pin*/ -#define TLD5542_1_SWTMOD_VFB_VIN_OFF_ENABLE 0U /**< @brief (default) Enable Vin Feedback */ -#define TLD5542_1_SWTMOD_VFB_VIN_OFF_DISABLE 1U /**< @brief Disable Vin Feedback */ - -/* bit 3 r/w, Short to GND protection enable Bit*/ -#define TLD5542_1_SWTMOD_S2G_OFF_ENABLE_PROTECTION 0U /**< @brief (default) Short to ground protection enabled */ -#define TLD5542_1_SWTMOD_S2G_OFF_DISABLE_PROTECTION 1U /**< @brief Short to ground protection disabled */ - -/* bit 2 r/w, Enable Spread Spectrum feature*/ -#define TLD5542_1_SWTMOD_ENSPREAD_DISABLE_SSM 0U /**< @brief (default) Spread Spectrum modulation disabled */ -#define TLD5542_1_SWTMOD_ENSPREAD_ENABLE_SSM 1U /**< @brief Spread Spectrum modulation enabled */ - -/* bit 1 r/w, Frequency Modulation Frequency fFM definition*/ -#define TLD5542_1_SWTMOD_FMSPREAD_12kHz 0U /**< @brief (default) 12 kHz */ -#define TLD5542_1_SWTMOD_FMSPREAD_18kHz 1U /**< @brief 18 kHz */ - -/* bit 0 r/w, Switching Mode Configuration Register*/ -#define TLD5542_1_SWTMOD_FDEVSPREAD_16_PERC 0U /**< @brief (default) +- 16% of fSW */ -#define TLD5542_1_SWTMOD_FDEVSPREAD_8_PERC 1U /**< @brief +- 8% of fSW */ - - - -/** ---------------------------------------------------------------------------------------------------------------------**/ -/* DVCCTRL: Device Control Register */ -/** ---------------------------------------------------------------------------------------------------------------------**/ - -/* bit 7 r/w, Bit to decrease the saturation current of the error */ -#define TLD5542_1_DVCCTRL_EA_IOUT_NOT_REDUCED 0U /**< @brief (default) inactive */ -#define TLD5542_1_DVCCTRL_EA_IOUT_REDUCED_TO_10uA 1U /**< @brief active: error amplifier saturation current reduced to 10uA*/ - -/* bit 6 r/w, Increase the gain of the error amplifier, active only when output current is below 80% of target (i.e. < VFBH_FBL_EA ) */ -#define TLD5542_1_DVCCTRL_EA_GM_INACTIVE 0U /**< @brief (default) inactive */ -#define TLD5542_1_DVCCTRL_EA_GM_BOOST_TO_1420uS 1U /**< @brief IFBxgm boosted to 1420uS */ - -/* bit 5:4 r/w, slope compensation strenght */ -#define TLD5542_1_DVCCTRL_SLOPE_NOMINAL 0U /**< @brief (default) Nominal */ -#define TLD5542_1_DVCCTRL_SLOPE_PLUS_25_PERC 1U /**< @brief +25% */ -#define TLD5542_1_DVCCTRL_SLOPE_MINUS_50_PERC 2U /**< @brief -50% */ -#define TLD5542_1_DVCCTRL_SLOPE_MINUS_25_PERC 3U /**< @brief -25% */ - -/* bit 3 r/w, Enable automatic output current calibration bit */ -#define TLD5542_1_DVCCTRL_ENCAL_CALIB_SPI 0U /**< @brief (default) DAC takes CALIBVAL from SPI registers */ -#define TLD5542_1_DVCCTRL_ENCAL_CALIB_AUTO_PROC 1U /**< @brief DAC takes CALIBVAL from last completed automatic calibration procedure; SOCAL Bit can be set */ - -/* bit 2 r/w, Clear Latch bit */ -#define TLD5542_1_DVCCTRL_CLRLAT_NORMAL_OP 0U /**< @brief (default) normal operation */ -#define TLD5542_1_DVCCTRL_CLRLAT_EXECUTE 1U /**< @brief execute CLRLAT command */ - -/* bit 1 r/w, Software reset bit */ -#define TLD5542_1_DVCCTRL_SWRST_NORMAL_OP 0U /**< @brief (default) normal operation */ -#define TLD5542_1_DVCCTRL_SWRST_EXECUTE 1U /**< @brief execute reset command */ - -/* bit 0 r/w, IDLE mode configuration bit */ -#define TLD5542_1_DVCCTRL_IDLE_ACTIVE 0U /**< @brief (default) ACTIVE mode */ -#define TLD5542_1_DVCCTRL_IDLE_IDLE 1U /**< @brief IDLE mode */ - - - -/** ----------------------------------------------------------------------------------------------------------------**/ -/* MFSSETUP1: Multifloat Switch configuration Register */ -/** ----------------------------------------------------------------------------------------------------------------*/ - -/* bit 7 r/w, Bit to decrease the saturation current of the error amplifier (A6) in current mode control loop only during MFS routine */ -#define TLD5542_1_MFSSETUP1_EA_IOUT_MFS_NORMAL 0U /**< @brief (default) inactive */ -#define TLD5542_1_MFSSETUP1_EA_IOUT_MFS_REDUCED_TO_20_PERC 1U /**< @brief active: error amplifier current reduced to 20% */ - -/* bit 6 r/w, Bit to decrease the Switch Current Limit (ISwLim) during F.D. operation*/ -#define TLD5542_1_MFSSETUP1_ILIM_HALF_REDUCED_TO_2_3 0U /**< @brief (default)inactive ISwLim = 2/3of default value */ -#define TLD5542_1_MFSSETUP1_ILIM_HALF_REDUCED_TO_1_2 1U /**< @brief ISwLim reduced to 1/2of default value */ - -/* bit 5 r/w, Start of MFS routine biT*/ -#define TLD5542_1_MFSSETUP1_SOMFS_NOT_ACTIVE 0U /**< @brief (default) MFS routine not activated */ -#define TLD5542_1_MFSSETUP1_SOMFS_ACTIVE 1U /**< @brief MFS routine activated */ - -/* bit 4 r, End of MFS routine bit*/ -#define TLD5542_1_MFSSETUP1_EOMFS_NOT_PERFORMED 0U /**< @brief (default) MFS routine not completed, not successfully performed or never run */ -#define TLD5542_1_MFSSETUP1_EOMFS_PERFORMED 1U /**< @brief MFS routine successfully performed (is reset to 0B when SOMFS is set to 1B) */ - - - -/** ----------------------------------------------------------------------------------------------------------------**/ -/* CURRMON: Current Monitor Register */ -/** ----------------------------------------------------------------------------------------------------------------**/ - -/* bit 5 r/w, Start of LED/Input Current Monitoring bit */ -#define TLD5542_1_CURRMON_SOMON_NOT_STARTED 0U /**< @brief (default) Current monitor routine not started */ -#define TLD5542_1_CURRMON_SOMON_START 1U /**< @brief Start of the current monitor routine */ - -/* bit 4 r, End of LED/Input Current Monitoring bit */ -#define TLD5542_1_CURRMON_EOMON_NOT_PERFORMED 0U /**< @brief (default) Current monitoring routine not completed, not successfully performed or never run */ -#define TLD5542_1_CURRMON_EOMON_PERFORMED 1U /**< @brief Current Monitor routine successfully performed (is reset to 0B when SOMON is set to 1B) */ - -/* bit 3:2 r Status of the Input Current bits */ -#define TLD5542_1_CURRMON_INCURR_BETWEEN_75_90_PERC 0U /**< @brief (default) Input current between 75% and 90% of Limit */ -#define TLD5542_1_CURRMON_INCURR_ABOVE_90_PERC 1U /**< @brief Input current between 90% and the Limit */ -#define TLD5542_1_CURRMON_INCURR_BETWEEN_60_75_PERC 2U /**< @brief Input current between 60% and 75% of Limit */ -#define TLD5542_1_CURRMON_INCURR_BELOW_60_PERC 3U /**< @brief Input current below 60% of Limit */ - -/* bit 1:0 r, Status of the LED Current bits */ -#define TLD5542_1_CURRMON_LEDCURR_BETWEEN_100_125_PERC 0U /**< @brief (default) LED current between Target and +25% (100% - 125%) */ -#define TLD5542_1_CURRMON_LEDCURR_ABOVE_125_PERC 1U /**< @brief LED current above +25% of Target (> 125%) */ -#define TLD5542_1_CURRMON_LEDCURR_BETWEEN_75_100_PERC 2U /**< @brief LED current between Target and -25% (75% - 100%) */ -#define TLD5542_1_CURRMON_LEDCURR_BELOW_75_PERC 3U /**< @brief LED current below -25% of Target (<75%) */ - - - -/** -------------------------------------------------------------------------------------------------------------**/ -/* REGUSTEMON: Regulation Setup And Monitor Register */ -/** --------------------------------------------------------------------------------------------------------------*/ -/* bit 3:2 r, Feedback of Regulation Mode bits */ -#define TLD5542_1_REGUSTEMON_REGUMODFB_BUCK 1U /**< @brief (default) buck */ -#define TLD5542_1_REGUSTEMON_REGUMODFB_BOOST 2U /**< @brief Boost */ -#define TLD5542_1_REGUSTEMON_REGUMODFB_BUCK_BOOST 3U /**< @brief Buck-Boost */ - -/* bit 1:0 r/w, Buck boost to Boost transition compensation level */ -#define TLD5542_1_REGUSTEMON_BB_BST_CMP_MIN 0U /**< @brief (default) Min compensation: useful when low switching frequencies are selected */ -#define TLD5542_1_REGUSTEMON_BB_BST_CMP_LOW 1U /**< @brief Low compensation: I.E. adopted @fSW=250kHz */ -#define TLD5542_1_REGUSTEMON_BB_BST_CMP_MID 2U /**< @brief Mid compensation: I.E. adopted @fSW=400kHz */ -#define TLD5542_1_REGUSTEMON_BB_BST_CMP_MAX 3U /**< @brief Max compensation: useful when high switching frequencies are selected I.E. @fSW=500kHz */ - - - -/** ------------------------------------------------------------------------------------------------------------**/ -/* MUXCTRL: Internal Muxes Configuration Register */ -/** ------------------------------------------------------------------------------------------------------------**/ - -/* bit 7 r/w, MFS reference to FILT pin Path Enable */ -#define TLD5542_1_MUXCTRL_MSF_REF_PATH_DISABLED 0U /**< @brief (default) path disabled */ -#define TLD5542_1_MUXCTRL_MSF_REF_PATH_ENABLED 1U /**< @brief Path Enabled */ - -/* bit 6 r/w, Analog Mux enable, output on FILT pin */ -#define TLD5542_1_MUXCTRL_AMUX_EN_DISABLED 0U /**< @brief (default) Analog Mux disabled */ -#define TLD5542_1_MUXCTRL_AMUX_EN_ENABLED 1U /**< @brief Analog Mux enabled */ - -/* bit 6 r/w, Analog Mux enable, output on FILT pin */ -#define TLD5542_1_MUXCTRL_SO_MUX_SEL_SO_AS_SPI 0U /**< @brief (default) Analog Mux disabled */ -#define TLD5542_1_MUXCTRL_SO_MUX_SEL_SO_AS_INTERNAL_CLK 4U /**< @brief Analog Mux enabled */ - -/** ------------------------------------------------------------------------------------------------------------**/ -/* STANDARD DIAGNOSIS: The Standard Diagnosis reports several diagnostic informations and the status of the device and the utility routines */ -/** ------------------------------------------------------------------------------------------------------------**/ - -/* bit 14 r, SWRST OR VBSTx-VSWNx_UVth Monitor */ -#define TLD5542_1_STD_SWRST_BSTUV_NOT_OCCURED 0U /**< @brief no SWRST or undervoltage on the Gate Drivers occured */ -#define TLD5542_1_STD_SWRST_BSTUV_OCCURED 1U /**< @brief there was at least one SWRST since last readout OR an undervoltage condition at the gate drivers is occurred */ - -/* bit 13 r, VDD OR VEN/INUVLO Undervoltage Monitor*/ -#define TLD5542_1_STD_UVLORST_NOT_OCCURED 0U /**< @brief there was no VDD OR VEN/INUVLO undervoltage since last readout */ -#define TLD5542_1_STD_UVLORST_OCCURED 1U /**< @brief there was at least one VDD undervoltage OR VEN/INUVLO undervoltage condition since last readout */ - -/* bit 12:11 r, Operative State Monitor*/ -#define TLD5542_1_STD_STATE_RESERVED 0U /**< @brief (reserved) */ -#define TLD5542_1_STD_STATE_LIMPHOME 1U /**< @brief Limp Home Mode */ -#define TLD5542_1_STD_STATE_ACTIVE 2U /**< @brief Active Mode*/ -#define TLD5542_1_STD_STATE_IDLE 3U /**< @brief Idle Mode*/ - -/* bit 10 r, Operative State Monitor*/ -#define TLD5542_1_STD_TER_TX_SUCCESS 0U /**< @brief Previous transmission was successful (modulo 16 + n*8 clocks received, where n = 0, 1, 2...) */ -#define TLD5542_1_STD_TER_TX_FAILED 1U /**< @brief Previous transmission failed or first transmission after reset */ - -/* bit 9 r, Operative State Monitor*/ -#define TLD5542_1_STD_EOMON_NOT_PERFORMED 0U /**< @brief Current monitoring routine not completed, not successfully performed or never run */ -#define TLD5542_1_STD_EOMON_PERFORMED 1U /**< @brief Current Monitor routine successfully performed (is reset to 0B when SOMON is set to 1B) */ - -/* bit 8 r, End of MFS routine bit*/ -#define TLD5542_1_STD_EOMFS_NOT_PERFORMED 0U /**< @brief (default) MFS routine not completed, not successfully performed or never run */ -#define TLD5542_1_STD_EOMFS_PERFORMED 1U /**< @brief MFS routine successfully performed (is reset to 0B when SOMFS is set to 1B)*/ - -/* bit 7 r, End of calibration routine signalling bit*/ -#define TLD5542_1_STD_EOCAL_CALIB_NOT_PERFORMED 0U /**< @brief (default) calibration routine not completed, not successfully performed or never run */ -#define TLD5542_1_STD_EOCAL_CALIB_PERFORMED 1U /**< @brief calibration successfully performed (is reset to 0B when SOCAL is set to 1B) */ - -/* bit 5 r, Output overvoltage Monitor*/ -#define TLD5542_1_STD_OUTOV_OUTPUT_OVERVOLTAGE_NOT_OCCURED 0U /**< @brief Output overvoltage not detected since last readout */ -#define TLD5542_1_STD_OUTOV_OUTPUT_OVERVOLTAGE_OCCURED 1U /**< @brief Output overvoltage was detected since last readout*/ - -/* bit 4 r, IVCC or IVCC_EXT Undervoltage Lockout Monitor*/ -#define TLD5542_1_STD_IVCCUVLO_UNDERVOLTAGE_NOT_OCCURED 0U /**< @brief IVCC and IVCC_EXT above VIVCC_RTH,d or VIVCC_EXT_RTH,d threshold since last readout */ -#define TLD5542_1_STD_IVCCUVLO_UNDERVOLTAGE_OCCURED 1U /**< @brief Undervoltage on IVCC or IVCC_EXT occurred since last readout*/ - -/* bit 3 r, LED Current Flag (see LEDCUR pin description Chapter10.5) */ -#define TLD5542_1_STD_LEDCUR_NOT_DETECTED 0U /**< @brief LED current not detected*/ -#define TLD5542_1_STD_LEDCUR_DETECTED 1U /**< @brief LED current detected*/ - -/* bit 2 r, Shorted LED Diagnosis */ -#define TLD5542_1_STD_SHRTLED_OUTPUT_SHORT_CIRCUIT_NOT_OCCURED 0U /**< @brief Short circuit condition not detected since last readout*/ -#define TLD5542_1_STD_SHRTLED_OUTPUT_SHORT_CIRCUIT_OCCURED 1U /**< @brief Short circuit condition detected since last readout*/ - -/* bit 1 r, Over Temperature Shutdown */ -#define TLD5542_1_STD_TSD_OVERTEMPERATURE_NOT_OCCURED 0U /**< @brief Tj below temperature shutdown threshold */ -#define TLD5542_1_STD_TSD_OVERTEMPERATURE_OCCURED 1U /**< @brief Overtemperature condition detected since last readout*/ - -/* bit 1 r, Over Temperature Shutdown */ -#define TLD5542_1_STD_TW_TEMP_WARNING_NOT_OCCURED 0U /**< @brief Tj below temperature shutdown threshold */ -#define TLD5542_1_STD_TW_TEMP_WARNING_OCCURED 1U /**< @brief Overtemperature condition detected since last readout*/ - -#endif /* TLD5542_1_REGLAYER_H */