JSMSolns
Published © GPL3+

Arduino TPMS Tyre Pressure Display

Project using Arduino Micro and a CC1101 to receive and display the tyre pressures transmitted by a Toyota (Auris Hybrid) and some others

IntermediateFull instructions provided3 hours19,672
Arduino TPMS Tyre Pressure Display

Things used in this project

Hardware components

Pro Micro - 3.3V/8MHz
SparkFun Pro Micro - 3.3V/8MHz
Make sure this is the 3V3 version!
×1
TI CC1101 Module (387-464MHz)
×1
0.96in I2C 128x64 Yellow & Blue OLED Display Module
×1
USB-A to Micro-USB Cable
USB-A to Micro-USB Cable
×1
Seeeduino Xiao Micro Controller
Alternative to using the Pro Micro (cheaper, smaller, more memory and much faster but still 3v3 I/O)
×1
3v Piezo buzzer
Optional addition if audible alarms required for low/high pressure warnings Please ensure the current drawn by the buzzer is less than the selected processor can sink (usually <7mA). If a larger current is needed, an external drive circuit will be required.
×1
1.8in TFT SPI display 128 x 160 RGB
1.8" TFT SPI display 128 x 160 RGB as alternative to I2C display
×1

Software apps and online services

Arduino IDE
Arduino IDE
Texas Instruments TI SMART RF Studio7
Fusion 360
Autodesk Fusion 360
Used for the enclosure design
Cura
Saleae Logic Analyser Softwre
Used during development

Hand tools and fabrication machines

3D Printer (generic)
3D Printer (generic)
For 3D printing enclosure (if required)

Story

Read more

Custom parts and enclosures

TPMS_Case_Bottom (STL)

TPMS_Case_Top (STL)

3D CAD File - ProMicro

Fusion360 file for case for ProMicro version

CAD view of case bottom

CAD View of Case (showing lid)

3D CAD File - Seeduino Xiao + 1.8" display + PCB

Fusion 360 file for case for Seeduino Xiao and 1.8" display module
Uses PCB designed for this project

3D CAD file - ProMicro

Fusion 360 file for case for ProMicro and I2C display

Schematics

Circuit diagram for Toyota TPMS monitor_ProMicro3v3

Schematic_Toyota_TPMS_Monitor_SeeeduinoXiao

Schematic for Seeeduino Xiao processor

Schematic TPMS using Seeeduino Xiao and 1.8" ST7735 TFT and Buzzer Alarm

Code

cc1101

C Header File
enum RFSTATE
{
  RFSTATE_IDLE = 0,
  RFSTATE_RX,
  RFSTATE_TX
};






//SPIClass spi;

/**
 * Frequency channels
 */
#define NUMBER_OF_FCHANNELS      10

/**
 * Type of transfers
 */
#define WRITE_BURST              0x40
#define READ_SINGLE              0x80
#define READ_BURST               0xC0

/**
 * Type of register
 */
#define CC1101_CONFIG_REGISTER   READ_SINGLE
#define CC1101_STATUS_REGISTER   READ_BURST


/**
 * Buffer and data lengths
 */
#define CCPACKET_BUFFER_LEN        64
#define CCPACKET_DATA_LEN          CCPACKET_BUFFER_LEN - 3

/**
 * Class: CCPACKET
 * 
 * Description:
 * CC1101 data packet class
 */
struct CCPACKET
{
  public:
     //Data length
    unsigned char length;
     // Data buffer
    unsigned char data[CCPACKET_DATA_LEN];
     //* CRC OK flag
    bool crc_ok;
     // Received Strength Signal Indication
    unsigned char rssi;
     // Link Quality Index
    unsigned char lqi;
};



/**
 * Macros
 */

//#define wait_Miso()  delay(3)
void wait_Miso()
{
   unsigned long st = micros();
   while(digitalRead(MISO) == HIGH)
   {
      if (micros() - st > 500)
         break;
   }
}
// Get GDO0 pin state
#define getGDO0state()  digitalRead(PORT_GDO0)
// Wait until GDO0 line goes high
#define wait_GDO0_high()  while(!getGDO0state()) {delay(1);}
// Wait until GDO0 line goes low
#define wait_GDO0_low()  while(getGDO0state()) {delay(1);}



/**
 * PATABLE & FIFO's
 */
#define CC1101_PATABLE           0x3E        // PATABLE address
#define CC1101_TXFIFO            0x3F        // TX FIFO address
#define CC1101_RXFIFO            0x3F        // RX FIFO address

/**
 * Command strobes
 */
#define CC1101_SRES              0x30        // Reset CC1101 chip
#define CC1101_SFSTXON           0x31        // Enable and calibrate frequency synthesizer (if MCSM0.FS_AUTOCAL=1). If in RX (with CCA):
                                             // Go to a wait state where only the synthesizer is running (for quick RX / TX turnaround).
#define CC1101_SXOFF             0x32        // Turn off crystal oscillator
#define CC1101_SCAL              0x33        // Calibrate frequency synthesizer and turn it off. SCAL can be strobed from IDLE mode without
                                             // setting manual calibration mode (MCSM0.FS_AUTOCAL=0)
#define CC1101_SRX               0x34        // Enable RX. Perform calibration first if coming from IDLE and MCSM0.FS_AUTOCAL=1
#define CC1101_STX               0x35        // In IDLE state: Enable TX. Perform calibration first if MCSM0.FS_AUTOCAL=1.
                                             // If in RX state and CCA is enabled: Only go to TX if channel is clear
#define CC1101_SIDLE             0x36        // Exit RX / TX, turn off frequency synthesizer and exit Wake-On-Radio mode if applicable
#define CC1101_SWOR              0x38        // Start automatic RX polling sequence (Wake-on-Radio) as described in Section 19.5 if
                                             // WORCTRL.RC_PD=0
#define CC1101_SPWD              0x39        // Enter power down mode when CSn goes high
#define CC1101_SFRX              0x3A        // Flush the RX FIFO buffer. Only issue SFRX in IDLE or RXFIFO_OVERFLOW states
#define CC1101_SFTX              0x3B        // Flush the TX FIFO buffer. Only issue SFTX in IDLE or TXFIFO_UNDERFLOW states
#define CC1101_SWORRST           0x3C        // Reset real time clock to Event1 value
#define CC1101_SNOP              0x3D        // No operation. May be used to get access to the chip status byte

/**
 * CC1101 configuration registers
 */
#define CC1101_IOCFG2            0x00        // GDO2 Output Pin Configuration
#define CC1101_IOCFG1            0x01        // GDO1 Output Pin Configuration
#define CC1101_IOCFG0            0x02        // GDO0 Output Pin Configuration
#define CC1101_FIFOTHR           0x03        // RX FIFO and TX FIFO Thresholds
#define CC1101_SYNC1             0x04        // Sync Word, High Byte
#define CC1101_SYNC0             0x05        // Sync Word, Low Byte
#define CC1101_PKTLEN            0x06        // Packet Length
#define CC1101_PKTCTRL1          0x07        // Packet Automation Control
#define CC1101_PKTCTRL0          0x08        // Packet Automation Control
#define CC1101_ADDR              0x09        // Device Address
#define CC1101_CHANNR            0x0A        // Channel Number
#define CC1101_FSCTRL1           0x0B        // Frequency Synthesizer Control
#define CC1101_FSCTRL0           0x0C        // Frequency Synthesizer Control
#define CC1101_FREQ2             0x0D        // Frequency Control Word, High Byte
#define CC1101_FREQ1             0x0E        // Frequency Control Word, Middle Byte
#define CC1101_FREQ0             0x0F        // Frequency Control Word, Low Byte
#define CC1101_MDMCFG4           0x10        // Modem Configuration
#define CC1101_MDMCFG3           0x11        // Modem Configuration
#define CC1101_MDMCFG2           0x12        // Modem Configuration
#define CC1101_MDMCFG1           0x13        // Modem Configuration
#define CC1101_MDMCFG0           0x14        // Modem Configuration
#define CC1101_DEVIATN           0x15        // Modem Deviation Setting
#define CC1101_MCSM2             0x16        // Main Radio Control State Machine Configuration
#define CC1101_MCSM1             0x17        // Main Radio Control State Machine Configuration
#define CC1101_MCSM0             0x18        // Main Radio Control State Machine Configuration
#define CC1101_FOCCFG            0x19        // Frequency Offset Compensation Configuration
#define CC1101_BSCFG             0x1A        // Bit Synchronization Configuration
#define CC1101_AGCCTRL2          0x1B        // AGC Control
#define CC1101_AGCCTRL1          0x1C        // AGC Control
#define CC1101_AGCCTRL0          0x1D        // AGC Control
#define CC1101_WOREVT1           0x1E        // High Byte Event0 Timeout
#define CC1101_WOREVT0           0x1F        // Low Byte Event0 Timeout
#define CC1101_WORCTRL           0x20        // Wake On Radio Control
#define CC1101_FREND1            0x21        // Front End RX Configuration
#define CC1101_FREND0            0x22        // Front End TX Configuration
#define CC1101_FSCAL3            0x23        // Frequency Synthesizer Calibration
#define CC1101_FSCAL2            0x24        // Frequency Synthesizer Calibration
#define CC1101_FSCAL1            0x25        // Frequency Synthesizer Calibration
#define CC1101_FSCAL0            0x26        // Frequency Synthesizer Calibration
#define CC1101_RCCTRL1           0x27        // RC Oscillator Configuration
#define CC1101_RCCTRL0           0x28        // RC Oscillator Configuration
#define CC1101_FSTEST            0x29        // Frequency Synthesizer Calibration Control
#define CC1101_PTEST             0x2A        // Production Test
#define CC1101_AGCTEST           0x2B        // AGC Test
#define CC1101_TEST2             0x2C        // Various Test Settings
#define CC1101_TEST1             0x2D        // Various Test Settings
#define CC1101_TEST0             0x2E        // Various Test Settings

/**
 * Status registers
 */
#define CC1101_PARTNUM           0x30        // Chip ID
#define CC1101_VERSION           0x31        // Chip ID
#define CC1101_FREQEST           0x32        // Frequency Offset Estimate from Demodulator
#define CC1101_LQI               0x33        // Demodulator Estimate for Link Quality
#define CC1101_RSSI              0x34        // Received Signal Strength Indication
#define CC1101_MARCSTATE         0x35        // Main Radio Control State Machine State
#define CC1101_WORTIME1          0x36        // High Byte of WOR Time
#define CC1101_WORTIME0          0x37        // Low Byte of WOR Time
#define CC1101_PKTSTATUS         0x38        // Current GDOx Status and Packet Status
#define CC1101_VCO_VC_DAC        0x39        // Current Setting from PLL Calibration Module
#define CC1101_TXBYTES           0x3A        // Underflow and Number of Bytes
#define CC1101_RXBYTES           0x3B        // Overflow and Number of Bytes
#define CC1101_RCCTRL1_STATUS    0x3C        // Last RC Oscillator Calibration Result
#define CC1101_RCCTRL0_STATUS    0x3D        // Last RC Oscillator Calibration Result 


//#define CC1101_DEFVAL_IOCFG2     0x0C        // GDO2 Output Pin Configuration - Serial out (synchronous)
//#define CC1101_DEFVAL_IOCFG1     0x2E        // GDO1 Output Pin Configuration - not used
////#define CC1101_DEFVAL_IOCFG0     0x0D        // GDO0 Output Pin Configuration
//#define CC1101_DEFVAL_IOCFG0     0x0E        // GDO0 Output Pin Configuration - Carrier Sense output
//#define CC1101_DEFVAL_FIFOTHR    0x0F        // RX FIFO and TX FIFO Thresholds - 64 bytes in FIFO
//#define CC1101_DEFVAL_SYNC1      0xD5        // Synchronization word, high byte  11010101 01001111
//#define CC1101_DEFVAL_SYNC0      0x4F        // Synchronization word, low byte
//#define CC1101_DEFVAL_PKTLEN     0x09        // Packet Length
//#define CC1101_DEFVAL_PKTCTRL1   0x00        // Packet Automation Control
//#define CC1101_DEFVAL_PKTCTRL0   0x12 //0x30        // Packet Automation Control - synchronous data
//#define CC1101_DEFVAL_ADDR       0x00        // Device Address
//#define CC1101_DEFVAL_CHANNR     0x00        // Channel Number
//#define CC1101_DEFVAL_FSCTRL1    0x0F        // Frequency Synthesizer Control (was 0x06)
//#define CC1101_DEFVAL_FSCTRL0    0x00        // Frequency Synthesizer Control
//
//// Carrier frequency = 868 MHz (not used)
////#define CC1101_DEFVAL_FREQ2_868  0x21        // Frequency Control Word, High Byte
////#define CC1101_DEFVAL_FREQ1_868  0x65        // Frequency Control Word, Middle Byte
////#define CC1101_DEFVAL_FREQ0_868  0xCC        // Frequency Control Word, Low Byte
//
////// Carrier frequency = 433.8798 MHz
////#define CC1101_DEFVAL_FREQ2_433  0x10        // Frequency Control Word, High Byte
////#define CC1101_DEFVAL_FREQ1_433  0xB0        // Frequency Control Word, Middle Byte
////#define CC1101_DEFVAL_FREQ0_433  0x71        // Frequency Control Word, Low Byte
////#define CC1101_DEFVAL_MDMCFG4_433    0x59        // Modem Configuration (59 = data rate = 20kHz - actual data rate is 10kHz but due to bi-phase coding need to double the rate, RX bandwidth 325kHz)
////#define CC1101_DEFVAL_MDMCFG3_433    0x93        // Modem Configuration (now 93 = data rate = 20kHz)
////#define CC1101_DEFVAL_DEVIATN_433    0x41      // Modem Deviation Setting (+/-28.56kHz)
////
////// Carrier frequency = 315MHz MHz
////#define CC1101_DEFVAL_FREQ2_315  0x0C        // Frequency Control Word, High Byte
////#define CC1101_DEFVAL_FREQ1_315  0x1D        // Frequency Control Word, Middle Byte
////#define CC1101_DEFVAL_FREQ0_315  0x57        // Frequency Control Word, Low Byte
////#define CC1101_DEFVAL_MDMCFG4_315    0x59        // Modem Configuration (59 = data rate = 20kHz - actual data rate is 10kHz but due to bi-phase coding need to double the rate, RX bandwidth 325kHz)
////#define CC1101_DEFVAL_MDMCFG3_315    0x93        // Modem Configuration (now 93 = data rate = 20kHz)
////#define CC1101_DEFVAL_DEVIATN_315    0x40        // Modem Deviation Setting (+/-25.390625)
////
////
////
////#define CC1101_DEFVAL_MDMCFG2    0x10        // Modem Configuration (GFSK, No Sync or Manchester coding)
////
////#define CC1101_DEFVAL_MDMCFG1    0x22        // Modem Configuration Channel spacing 200kHz
////#define CC1101_DEFVAL_MDMCFG0    0xF8        // Modem Configuration
//
//
//#define CC1101_DEFVAL_MCSM2      0x07        // Main Radio Control State Machine Configuration
////#define CC1101_DEFVAL_MCSM1      0x30        // Main Radio Control State Machine Configuration
//#define CC1101_DEFVAL_MCSM1      0x3C        // Main Radio Control State Machine Configuration
//#define CC1101_DEFVAL_MCSM0      0x18        // Main Radio Control State Machine Configuration
//#define CC1101_DEFVAL_FOCCFG     0x16        // Frequency Offset Compensation Configuration
//#define CC1101_DEFVAL_BSCFG      0x6C        // Bit Synchronization Configuration
////////#define CC1101_DEFVAL_AGCCTRL2   0x43        // AGC Control
//////#define CC1101_DEFVAL_AGCCTRL2   0xC6        // AGC Control
////#define CC1101_DEFVAL_AGCCTRL2   0x87       // AGC Control
////////#define CC1101_DEFVAL_AGCCTRL1   0x40        // AGC Control
//////#define CC1101_DEFVAL_AGCCTRL1   0x50        // AGC Control
////#define CC1101_DEFVAL_AGCCTRL1   0x58        // AGC Control
////#define CC1101_DEFVAL_AGCCTRL0   0x80        // AGC Control
//
//#define CC1101_DEFVAL_WOREVT1    0x87        // High Byte Event0 Timeout
//#define CC1101_DEFVAL_WOREVT0    0x6B        // Low Byte Event0 Timeout
//#define CC1101_DEFVAL_WORCTRL    0xFB        // Wake On Radio Control
//#define CC1101_DEFVAL_FREND1     0x56        // Front End RX Configuration
//#define CC1101_DEFVAL_FREND0     0x10        // Front End TX Configuration
//
//#define CC1101_DEFVAL_FSCAL3     0xE9        // Frequency Synthesizer Calibration
//#define CC1101_DEFVAL_FSCAL2     0x2A        // Frequency Synthesizer Calibration
//#define CC1101_DEFVAL_FSCAL1     0x00        // Frequency Synthesizer Calibration
//#define CC1101_DEFVAL_FSCAL0     0x1F        // Frequency Synthesizer Calibration
//
//#define CC1101_DEFVAL_RCCTRL1    0x41        // RC Oscillator Configuration
//#define CC1101_DEFVAL_RCCTRL0    0x00        // RC Oscillator Configuration
//
//#define CC1101_DEFVAL_FSTEST     0x59        // Frequency Synthesizer Calibration Control
//
//#define CC1101_DEFVAL_PTEST      0x7F        // Production Test
//#define CC1101_DEFVAL_AGCTEST    0x3F        // AGC Test
//
//#define CC1101_DEFVAL_TEST2      0x81        // Various Test Settings
//#define CC1101_DEFVAL_TEST1      0x35        // Various Test Settings
//#define CC1101_DEFVAL_TEST0      0x09        // Various Test Settings
//

/**
 * Alias for some default values
 */
#define CCDEF_CHANNR  CC1101_DEFVAL_CHANNR
#define CCDEF_SYNC0  CC1101_DEFVAL_SYNC0
#define CCDEF_SYNC1  CC1101_DEFVAL_SYNC1
#define CCDEF_ADDR  CC1101_DEFVAL_ADDR

/**
 * Macros
 */
// Read CC1101 Config register
#define readConfigReg(regAddr)    readReg(regAddr, CC1101_CONFIG_REGISTER)
// Read CC1101 Status register
#define readStatusReg(regAddr)    readReg(regAddr, CC1101_STATUS_REGISTER)
// Enter Rx state
//#define setRxState()              cmdStrobe(CC1101_SRX)
// Enter Tx state
//#define setTxState()              cmdStrobe(CC1101_STX)
// Enter IDLE state
#define setIdleState()            cmdStrobe(CC1101_SIDLE)
#define StartCalibration()        cmdStrobe(CC1101_SCAL)
// Flush Rx FIFO
#define flushRxFifo()             cmdStrobe(CC1101_SFRX)
// Flush Tx FIFO
#define flushTxFifo()             cmdStrobe(CC1101_SFTX)
// Disable address check
#define disableAddressCheck()     writeReg(CC1101_PKTCTRL1, 0x04)
// Enable address check
#define enableAddressCheck()      writeReg(CC1101_PKTCTRL1, 0x06)
// Disable CCA
#define disableCCA()              writeReg(CC1101_MCSM1, 0)
// Enable CCA
#define enableCCA()               writeReg(CC1101_MCSM1, CC1101_DEFVAL_MCSM1)
// Set PATABLE single byte
#define setTxPowerAmp(setting)    paTableByte = setting
// PATABLE values
#define PA_LowPower               0x60
#define PA_LongDistance           0xC0




// Select (SPI) CC1101
void cc1101_Select(){

  //delayMicroseconds(150);
  //spi.begin();
  //spi.beginTransaction(SPISettings(5000000,MSBFIRST,SPI_MODE0));
  SPI.beginTransaction(SPISettings(5000000,MSBFIRST,SPI_MODE0));
  digitalWrite(CC1101_CS, LOW);
}

void cc1101_Deselect(){
  //spi.end();

  //delayMicroseconds(50);
  digitalWrite(CC1101_CS, HIGH);
  //spi.endTransaction();
  SPI.endTransaction();


}

/**
 * wakeUp
 * 
 * Wake up CC1101 from Power Down state
 */
void wakeUp(void)
{
  cc1101_Select();                      // Select CC1101
  wait_Miso();                          // Wait until MISO goes low
  cc1101_Deselect();                    // Deselect CC1101
}


/**
 * writeReg
 * 
 * Write single register into the CC1101 IC via SPI
 * 
 * 'regAddr'  Register address
 * 'value'  Value to be writen
 */
void writeReg(byte regAddr, byte value) 
{
  cc1101_Select();                      // Select CC1101
  //wait_Miso();                          // Wait until MISO goes low
  SPI.transfer(regAddr);                    // Send register address
  SPI.transfer(value);                      // Send value
  //spi.transfer(regAddr);                    // Send register address
  //spi.transfer(value);                      // Send value
  cc1101_Deselect();                    // Deselect CC1101
}

/**
 * readReg
 * 
 * Read CC1101 register via SPI
 * 
 * 'regAddr'  Register address
 * 'regType'  Type of register: CC1101_CONFIG_REGISTER or CC1101_STATUS_REGISTER
 * 
 * Return:
 *  Data byte returned by the CC1101 IC
 */
byte readReg(byte regAddr, byte regType)
{
  byte addr, val;

  addr = regAddr | regType;
  cc1101_Select();                      // Select CC1101
  //wait_Miso();                          // Wait until MISO goes low
  //spi.transfer(addr);                       // Send register address
  //val = spi.transfer(0x00);                 // Read result
  SPI.transfer(addr);                       // Send register address
  val = SPI.transfer(0x00);                 // Read result
  cc1101_Deselect();                    // Deselect CC1101

  return val;
}

/**
 * setCCregs
 * 
 * Configure CC1101 registers
 */
void setCCregs(void) 
{
  writeReg(CC1101_IOCFG2,  CC1101_DEFVAL_IOCFG2);
  writeReg(CC1101_IOCFG1,  CC1101_DEFVAL_IOCFG1);
  writeReg(CC1101_IOCFG0,  CC1101_DEFVAL_IOCFG0);
  writeReg(CC1101_FIFOTHR,  CC1101_DEFVAL_FIFOTHR);
  writeReg(CC1101_SYNC1,  CC1101_DEFVAL_SYNC1);
  writeReg(CC1101_SYNC0,  CC1101_DEFVAL_SYNC0);
  writeReg(CC1101_PKTLEN,  CC1101_DEFVAL_PKTLEN);
  writeReg(CC1101_PKTCTRL1,  CC1101_DEFVAL_PKTCTRL1);
  writeReg(CC1101_PKTCTRL0,  CC1101_DEFVAL_PKTCTRL0);
  writeReg(CC1101_ADDR,  CC1101_DEFVAL_ADDR);
  writeReg(CC1101_CHANNR,  CC1101_DEFVAL_CHANNR);

  
  // Set default synchronization word
  //setSyncWord(syncWord);

  // Set default device address
  //setDevAddress(devAddress);

  // Set default frequency channel
  //setChannel(channel);
  
  writeReg(CC1101_FSCTRL1,  CC1101_DEFVAL_FSCTRL1);
  writeReg(CC1101_FSCTRL0,  CC1101_DEFVAL_FSCTRL0);

//  // Set default carrier frequency = 868 MHz
//  //setCarrierFreq(carrierFreq);
//  writeReg(CC1101_FREQ2,  CC1101_DEFVAL_FREQ2_868);
//  writeReg(CC1101_FREQ1,  CC1101_DEFVAL_FREQ1_868);
//  writeReg(CC1101_FREQ0,  CC1101_DEFVAL_FREQ0_868);


  writeReg(CC1101_FREQ2,  CC1101_DEFVAL_FREQ2);
  writeReg(CC1101_FREQ1,  CC1101_DEFVAL_FREQ1);
  writeReg(CC1101_FREQ0,  CC1101_DEFVAL_FREQ0);
  writeReg(CC1101_DEVIATN,  CC1101_DEFVAL_DEVIATN);
  writeReg(CC1101_MDMCFG4,  CC1101_DEFVAL_MDMCFG4);
  writeReg(CC1101_MDMCFG3,  CC1101_DEFVAL_MDMCFG3);

  writeReg(CC1101_MDMCFG2,  CC1101_DEFVAL_MDMCFG2);
  writeReg(CC1101_MDMCFG1,  CC1101_DEFVAL_MDMCFG1);
  writeReg(CC1101_MDMCFG0,  CC1101_DEFVAL_MDMCFG0);
 
  writeReg(CC1101_MCSM2,  CC1101_DEFVAL_MCSM2);
  writeReg(CC1101_MCSM1,  CC1101_DEFVAL_MCSM1);
  writeReg(CC1101_MCSM0,  CC1101_DEFVAL_MCSM0);
  writeReg(CC1101_FOCCFG,  CC1101_DEFVAL_FOCCFG);
  writeReg(CC1101_BSCFG,  CC1101_DEFVAL_BSCFG);
  writeReg(CC1101_AGCCTRL2,  CC1101_DEFVAL_AGCCTRL2);
  writeReg(CC1101_AGCCTRL1,  CC1101_DEFVAL_AGCCTRL1);
  writeReg(CC1101_AGCCTRL0,  CC1101_DEFVAL_AGCCTRL0);
  writeReg(CC1101_WOREVT1,  CC1101_DEFVAL_WOREVT1);
  writeReg(CC1101_WOREVT0,  CC1101_DEFVAL_WOREVT0);
  writeReg(CC1101_WORCTRL,  CC1101_DEFVAL_WORCTRL);
  writeReg(CC1101_FREND1,  CC1101_DEFVAL_FREND1);
  writeReg(CC1101_FREND0,  CC1101_DEFVAL_FREND0);
  writeReg(CC1101_FSCAL3,  CC1101_DEFVAL_FSCAL3);
  writeReg(CC1101_FSCAL2,  CC1101_DEFVAL_FSCAL2);
  writeReg(CC1101_FSCAL1,  CC1101_DEFVAL_FSCAL1);
  writeReg(CC1101_FSCAL0,  CC1101_DEFVAL_FSCAL0);
  writeReg(CC1101_RCCTRL1,  CC1101_DEFVAL_RCCTRL1);
  writeReg(CC1101_RCCTRL0,  CC1101_DEFVAL_RCCTRL0);
  writeReg(CC1101_FSTEST,  CC1101_DEFVAL_FSTEST);
  writeReg(CC1101_PTEST,  CC1101_DEFVAL_PTEST);
  writeReg(CC1101_AGCTEST,  CC1101_DEFVAL_AGCTEST);
  writeReg(CC1101_TEST2,  CC1101_DEFVAL_TEST2);
  writeReg(CC1101_TEST1,  CC1101_DEFVAL_TEST1);
  writeReg(CC1101_TEST0,  CC1101_DEFVAL_TEST0);
  
  // Send empty packet
//  CCPACKET packet;
//  packet.length = 0;
//  sendData(packet);
}

/**
 * cmdStrobe
 * 
 * Send command strobe to the CC1101 IC via SPI
 * 
 * 'cmd'  Command strobe
 */     
void cmdStrobe(byte cmd) 
{
  cc1101_Select();                      // Select CC1101
  //wait_Miso();                          // Wait until MISO goes low
  //spi.transfer(cmd);                        // Send strobe command
  SPI.transfer(cmd);                        // Send strobe command
  cc1101_Deselect();                    // Deselect CC1101
}


/**
 * setRxState
 * 
 * Enter Rx state
 */
void setRxState()
{
  cmdStrobe(CC1101_SRX);

}

void setTxState()
{
  cmdStrobe(CC1101_STX);

}


/**
 * reset
 * 
 * Reset CC1101
 */
void CC1101_reset(void) 
{
  cc1101_Deselect();                    // Deselect CC1101
  delay(1);
  cc1101_Select();                      // Select CC1101
  delay(1);
  cc1101_Deselect();                    // Deselect CC1101
  delay(1);
  cc1101_Select();                      // Select CC1101

  wait_Miso();                          // Wait until MISO goes low
  //spi.transfer(CC1101_SRES);                // Send reset command strobe
  SPI.transfer(CC1101_SRES);                // Send reset command strobe
  wait_Miso();                          // Wait until MISO goes low

  cc1101_Deselect();                    // Deselect CC1101


}

void ConfigureCC1101()
{
    setCCregs();                          // Reconfigure CC1101
}

int VerifyCC1101Config()
{
  boolean ret = 0;
   if (readReg(CC1101_IOCFG2,CC1101_CONFIG_REGISTER) !=  CC1101_DEFVAL_IOCFG2)
   {
      Serial.println(readReg(CC1101_IOCFG2,CC1101_CONFIG_REGISTER),HEX);
      return(1);
   }
   if (readReg(CC1101_IOCFG1,CC1101_CONFIG_REGISTER) !=  CC1101_DEFVAL_IOCFG1)
      return(2);
   if (readReg(CC1101_IOCFG0,CC1101_CONFIG_REGISTER) !=  CC1101_DEFVAL_IOCFG0)
      return(3);
   if (readReg(CC1101_FIFOTHR,CC1101_CONFIG_REGISTER) !=  CC1101_DEFVAL_FIFOTHR)
      return(4);
   if (readReg(CC1101_PKTLEN,CC1101_CONFIG_REGISTER) !=  CC1101_DEFVAL_PKTLEN)
      return(5);
   if (readReg(CC1101_PKTCTRL1,CC1101_CONFIG_REGISTER) !=  CC1101_DEFVAL_PKTCTRL1)
      return(6);
   if (readReg(CC1101_PKTCTRL0,CC1101_CONFIG_REGISTER) !=  CC1101_DEFVAL_PKTCTRL0)
      return(7);
   if (readReg(CC1101_FSCTRL1,CC1101_CONFIG_REGISTER) !=  CC1101_DEFVAL_FSCTRL1)
      return(8);
   if (readReg(CC1101_FSCTRL0,CC1101_CONFIG_REGISTER) !=  CC1101_DEFVAL_FSCTRL0)
      return(9);
   if (readReg(CC1101_FREQ2,CC1101_CONFIG_REGISTER) !=  CC1101_DEFVAL_FREQ2)
      return(10);
   if (readReg(CC1101_FREQ1,CC1101_CONFIG_REGISTER) !=  CC1101_DEFVAL_FREQ1)
      return(11);
   if (readReg(CC1101_FREQ0,CC1101_CONFIG_REGISTER) !=  CC1101_DEFVAL_FREQ0)
      return(12);
   if (readReg(CC1101_DEVIATN,CC1101_CONFIG_REGISTER) !=  CC1101_DEFVAL_DEVIATN)
      return(13);
   if (readReg(CC1101_MDMCFG4,CC1101_CONFIG_REGISTER) !=  CC1101_DEFVAL_MDMCFG4)
      return(14);
   if (readReg(CC1101_MDMCFG3,CC1101_CONFIG_REGISTER) !=  CC1101_DEFVAL_MDMCFG3)
      return(15);
   if (readReg(CC1101_MDMCFG2,CC1101_CONFIG_REGISTER) !=  CC1101_DEFVAL_MDMCFG2)
      return(16);
   if (readReg(CC1101_MDMCFG1,CC1101_CONFIG_REGISTER) !=  CC1101_DEFVAL_MDMCFG1)
      return(17);
   if (readReg(CC1101_MDMCFG0,CC1101_CONFIG_REGISTER) !=  CC1101_DEFVAL_MDMCFG0)
      return(18);
   if (readReg(CC1101_MCSM2,CC1101_CONFIG_REGISTER) !=  CC1101_DEFVAL_MCSM2)
      return(19);
   if (readReg(CC1101_MCSM1,CC1101_CONFIG_REGISTER) !=  CC1101_DEFVAL_MCSM1)
      return(20);
   if (readReg(CC1101_MCSM0,CC1101_CONFIG_REGISTER) !=  CC1101_DEFVAL_MCSM0)
      return(21);
   if (readReg(CC1101_FOCCFG,CC1101_CONFIG_REGISTER) !=  CC1101_DEFVAL_FOCCFG)
      return(22);
   if (readReg(CC1101_BSCFG,CC1101_CONFIG_REGISTER) !=  CC1101_DEFVAL_BSCFG)
      return(23);
   if (readReg(CC1101_AGCCTRL2,CC1101_CONFIG_REGISTER) !=  CC1101_DEFVAL_AGCCTRL2)
      return(24);
   if (readReg(CC1101_AGCCTRL1,CC1101_CONFIG_REGISTER) !=  CC1101_DEFVAL_AGCCTRL1)
      return(25);
   if (readReg(CC1101_AGCCTRL0,CC1101_CONFIG_REGISTER) !=  CC1101_DEFVAL_AGCCTRL0)
      return(26);
//   if (readReg(CC1101_IOCFG2,CC1101_CONFIG_REGISTER) !=  CC1101_DEFVAL_IOCFG1)
//      return(27);
//   if (readReg(CC1101_IOCFG2,CC1101_CONFIG_REGISTER) !=  CC1101_DEFVAL_IOCFG1)
//      return(28);      
//   if (readReg(CC1101_IOCFG2,CC1101_CONFIG_REGISTER) !=  CC1101_DEFVAL_IOCFG1);
//      return(29);
      

   return(0);
//  writeReg(CC1101_WOREVT1,  CC1101_DEFVAL_WOREVT1);
//  writeReg(CC1101_WOREVT0,  CC1101_DEFVAL_WOREVT0);
//  writeReg(CC1101_WORCTRL,  CC1101_DEFVAL_WORCTRL);
//  writeReg(CC1101_FREND1,  CC1101_DEFVAL_FREND1);
//  writeReg(CC1101_FREND0,  CC1101_DEFVAL_FREND0);
//  writeReg(CC1101_FSCAL3,  CC1101_DEFVAL_FSCAL3);
//  writeReg(CC1101_FSCAL2,  CC1101_DEFVAL_FSCAL2);
//  writeReg(CC1101_FSCAL1,  CC1101_DEFVAL_FSCAL1);
//  writeReg(CC1101_FSCAL0,  CC1101_DEFVAL_FSCAL0);
//  writeReg(CC1101_RCCTRL1,  CC1101_DEFVAL_RCCTRL1);
//  writeReg(CC1101_RCCTRL0,  CC1101_DEFVAL_RCCTRL0);
//  writeReg(CC1101_FSTEST,  CC1101_DEFVAL_FSTEST);
//  writeReg(CC1101_PTEST,  CC1101_DEFVAL_PTEST);
//  writeReg(CC1101_AGCTEST,  CC1101_DEFVAL_AGCTEST);
//  writeReg(CC1101_TEST2,  CC1101_DEFVAL_TEST2);
//  writeReg(CC1101_TEST1,  CC1101_DEFVAL_TEST1);
//  writeReg(CC1101_TEST0,  CC1101_DEFVAL_TEST0);
}

boolean GetCarrierStatus()
{
#ifndef USE_HW_CD
  byte ret;

  
  ret = readStatusReg(CC1101_PKTSTATUS);

  if ((ret & 0x40) == 0)
  {
    return(false);
  }
  else
  {
    return(true);
  }
#else
    if (digitalRead(CDPin) == HIGH)
    {
      return(true);
    }
    else
    {
      return(false);
    }
#endif
}

void WaitCarrierEnd()
{
   while (GetCarrierStatus() == true)
   {
       //wait for carrier detect to change to low state
       delayMicroseconds(100);
   }
}

byte GetState()
{
  byte ret;
  ret = readStatusReg(CC1101_MARCSTATE);
  return(ret);
}

void Calibrate()
{

    
    Serial.println(F("Calibrating..."));    
//    setIdleState();
//    StartCalibration();
//    delayMicroseconds(100);
//    while(GetState() != 0x01)
//    {};  //wait for idle state
    Serial.println(F("Calibration complete"));

}

byte Get_RX_FIFO_Count()
{
  return(readStatusReg(CC1101_RXBYTES));
}

void Flush_RX_FIFO(bool ReEnableRXMode)
{
   setIdleState();
   flushRxFifo();
   if (ReEnableRXMode)
   {
      setRxState(); 
   }
   
}
bool IsRX_FIFO_Overflow()
{
  if ((Get_RX_FIFO_Count() & 0x80) == 0x80)
  {
    return(true);    
  }
  else
  {
    return(false);
  }
}

byte ReadFIFO()
{
  readStatusReg(CC1101_RXFIFO);
}

Common

C Header File
extern Ticker SignalRefreshTimer;
extern Ticker displayflashtimer;

void PrintIDs()
{
  byte i;
  Serial.print("Preset IDs:  ");
  for(i=0;i<TYRECOUNT;i++)
  {
    Serial.print(IDLookup[i],HEX);
    Serial.print(", ");
  }
  Serial.println("");
}

double PSI_To_BAR(double Pressure_PSI)
{
   return(Pressure_PSI/PSI2BAR);
}

double PSI_To_KPA(double Pressure_PSI)
{
   return(Pressure_PSI * KPA2PSI);
}

double BAR_To_PSI(double Pressure_BAR)
{
   return(Pressure_BAR * PSI2BAR);
}

double KPA_To_PSI(double Pressure_KPA)
{
   return(Pressure_KPA/KPA2PSI);
}

float DegC_To_DegK(float DegC)
{
   return(DegC + 273.15);
}

float DegF_To_DegK(float DegF)
{
   return(DegC_To_DegK(DegF_To_DegC(DegF)));
}

float DegC_To_DegF(float DegC)
{
  return((DegC * 1.8) + 32.0);
}

float DegF_To_DegC(float DegF)
{
   return((DegF-32.0)/1.8);
}


double ConvertPressureForDisplay(double Pressure_PSI)
{
   #ifdef DISPLAY_PRESSURE_AS_BAR
      return(PSI_To_BAR(Pressure_PSI));
   #elif DISPLAY_PRESSURE_AS_KPA
      return(PSI_To_KPA(Pressure_PSI));
   #else
      return(Pressure_PSI);
   #endif
}


void ResetSignalRefreshTimer()
{
   SignalRefreshTimer.start();
}

void EdgeInterrupt()
{
  unsigned long ts = micros();
  unsigned long BitWidth;

  if (TimingsIndex == MAXTIMINGS)
  {
    return;
  }

  if (WaitingFirstEdge)
  {
    if (digitalRead(RXPin) == LOW)
    {
      FirstEdgeIsHighToLow = true;
    }
    else
    {
      FirstEdgeIsHighToLow = false;
    }
  }
  WaitingFirstEdge = false;
    

  BitWidth = ts - LastEdgeTime_us;
//  if (BitWidth <= 12)  //ignore glitches
//  {
//    return;
//  }
  if (BitWidth > 0xFFFF)
  {
    BitWidth = 0xFFFF;
//    Serial.print(ts);
//    Serial.print(" ");
//    Serial.println(LastEdgeTime_us);
  }

  LastEdgeTime_us = ts;
  Timings[TimingsIndex++] = (unsigned int)BitWidth;

}


bool IsTooShort(unsigned int Width)
{
  if (Width < SHORTTIMING_MIN)
  {
    return (true);
  }
  else
  {
    return (false);
  }
}

bool IsTooLong(unsigned int Width)
{
  if (Width > LONGTIMING_MAX)
  {
    return (true);
  }
  else
  {
    return (false);
  }
}




bool IsValidSync(unsigned int Width)
{
  if ((Width >= SYNCTIMING_MIN) && (Width <= SYNCTIMING_MAX))
  {
    return (true);
  }
  else
  {
    return (false);
  }
}

bool IsValidShort(unsigned int Width)
{
  if ((Width >= SHORTTIMING_MIN) && (Width <= SHORTTIMING_MAX))
  {
    return (true);
  }
  else
  {
    return (false);
  }
}


bool IsValidLong(unsigned int Width)
{
  if ((Width >= LONGTIMING_MIN) && (Width <= LONGTIMING_MAX))
  {
    return (true);
  }
  else
  {
    return (false);
  }
}

bool IsEndMarker(unsigned int Width)
{
  if ((Width >= ENDTIMING_MIN) && (Width <= ENDTIMING_MAX))
  {
     return(true);
  }
  else
  {
    return(false);
  }
}


int ValidateBit()
{
  unsigned int BitWidth = Timings[CheckIndex];

  if (IsValidLong(BitWidth))
  {
    return (BITISLONG);
  }

  if (IsValidShort(BitWidth))
  {
    return (BITISSHORT);
  }

  if (IsValidSync(BitWidth))
  {
    return (BITISSYNC);
  }


  return (-1);

}

int ValidateBit(int Index)
{
  unsigned int BitWidth = Timings[Index];

  if (IsValidLong(BitWidth))
  {
    return (BITISLONG);
  }

  if (IsValidShort(BitWidth))
  {
    return (BITISSHORT);
  }

  if (IsValidSync(BitWidth))
  {
    return (BITISSYNC);
  }


  return (BITISUNDEFINED);

}

byte Compute_CRC8( int bcount, byte Poly, byte crc_init )
{
  byte crc = crc_init;
  int c;
  for (c = 0; c < bcount; c++)
  {
    byte b = RXBytes[c];
    /* XOR-in next input byte */
    byte data = (byte)(b ^ crc);
    /* get current CRC value = remainder */
    if (Poly == 0x07)
    {
      crc = (byte)(pgm_read_byte(&CRC8_Poly_07_crctable2[data]));
    }
    else
    {
      if (Poly == 0x13)
      {
        crc = (byte)(pgm_read_byte(&CRC8_Poly_13_crctable2[data]));
      }
    }

  }

  return crc;
}

byte Compute_CRC_XOR(int Start, int bcount, byte crc_init)
{
  byte crc = crc_init;
  int c;

  for (c = Start; c < bcount; c++)
  {
    crc = crc ^ RXBytes[c];
  }
  
  return(crc);
}

byte Compute_CRC_SUM(int Start, int bcount, byte crc_init)
{
  byte crc = crc_init;
  int c;

  for (c = Start; c < bcount; c++)
  {
    crc = crc + RXBytes[c];
  }
  
  return(crc);
}

int GetRSSI_dbm()
{
  byte RSSI_Read;
  byte RSSI_Offset = 74;
  int ret;
  
  RSSI_Read = readStatusReg(CC1101_RSSI);
  if (RSSI_Read >= 128)
  {
    ret = (int)((int)(RSSI_Read - 256) /  2) - RSSI_Offset;
  }
  else
  {
    ret = (RSSI_Read / 2) - RSSI_Offset;
  }
  return(ret);
}

void ClearRXBuffer()
{
  int i;

  for (i = 0; i < sizeof(RXBytes); i++)
  {
    RXBytes[i] = 0;
  }
}



int ManchesterDecode(int StartIndex)
{
   int i;
   bool bit1, bit2;
   byte b = 0;
   byte n = 0;

   RXByteCount = 0;
   for (i = StartIndex; i< BitCount-1;i+=2)
   {
      bit1 = IncomingBits[i];
      bit2 = IncomingBits[i+1];

      if (bit1 == bit2)
      {
//        #ifdef SHOWDEBUGINFO
//           Serial.print(F("Manchester decode exited at index: "));
//           Serial.println(i + StartIndex);
//        #endif
         return RXByteCount;
      }

    b = b << 1;
    b = b + (bit2 == true? 1:0);
    n++;
    if (n == 8)
    {
      RXBytes[RXByteCount] = b;
      RXByteCount++;
      if (RXByteCount >= sizeof(RXBytes))
      {
        return(RXByteCount);
      }
      n = 0;
      b = 0;
    }     
    
   }

   return RXByteCount;

}

int DifferentialManchesterDecode(int StartIndex)
{
   int i;
   bool bit1, bit2, bit3;
   byte b = 0;
   byte n = 0;

   RXByteCount = 0;
   for (i = StartIndex; i< BitCount-1;i+=2)
   {
      bit1 = IncomingBits[i];
      bit2 = IncomingBits[i+1];
      bit3 = IncomingBits[i+2];

      if (bit1 != bit2)
      {
        if (bit2 != bit3)
        {
          b = b << 1;
          b = b + 0;
          n++;
          if (n == 8)
          {
            RXBytes[RXByteCount] = b;
            RXByteCount++;
            n = 0;
            b = 0;
          }          
        }
        else
        {
          bit2 = bit1;
          i+=1;
          break;
        }
      }
      else
      {
        bit2 = 1 - bit1;
        break;
      }
   }


   for (; i< BitCount-1;i+=2)  
   {
      bit1 = IncomingBits[i];

      if (bit1 == bit2)
         return RXByteCount;
      bit2 = IncomingBits[i+1];

      b = b << 1;
      b = b + (bit1 == bit2? 1:0);
      n++;
      if (n == 8)
      {
        RXBytes[RXByteCount] = b;
        RXByteCount++;
        n = 0;
        b = 0;
      } 

     
   }
    
   return RXByteCount;

}

void InvertBitBuffer()
{
   int i;

   for (i = 0;i < BitCount;i++)
   {
      IncomingBits[i] = !IncomingBits[i];
   }
  
}

static inline uint8_t bit_at(const uint8_t *bytes, unsigned bit)

{
    return (uint8_t)(bytes[bit >> 3] >> (7 - (bit & 7)) & 1);
}

int FindManchesterStart(const uint8_t *pattern,int pattern_bits_len )
{
  int i;


  //Renault TMS header pattern
   //const uint8_t pattern[] = {0xAA, 0xA9};
  // int pattern_bits_len = 16;
   unsigned int ipos = 0;
   unsigned int ppos = 0; // cursor on init pattern

   if (BitCount < pattern_bits_len) 
      return -1;

    while ((ipos < BitCount-3) && (ppos < pattern_bits_len)) 
    {
        if (IncomingBits[ipos] == bit_at(pattern, ppos)) 
        {
            ppos++;
            ipos++;
            if (ppos == pattern_bits_len)
                return ipos;
        }
        else 
        {
            ipos -= ppos;
            ipos++;
            ppos = 0;
        }
    }

    // Not found
    return -1;
 
}

void InitDataBuffer()
{
  BitIndex = 0;
  BitCount = 0;
  ValidBlock = false;
  //WaitingTrailingZeroEdge = false;
  WaitingFirstEdge  = true;
  CheckIndex = 0;
  TimingsIndex = 0;
  SyncFound = false;
  //digitalWrite(DEBUGPIN, LOW);

}


void ClearTPMSData(int i)
{
  if (i > TYRECOUNT)
    return;

  TPMS[i].TPMS_ID = 0;
  TPMS[i].lastupdated = 0;
  #ifdef DISPLAY_PRESSURE_AS_BAR
     TPMS[i].TPMS_LowPressureLimit = BAR_To_PSI(PressureLowLimits[i]);
     TPMS[i].TPMS_HighPressureLimit = BAR_To_PSI(PressureHighLimits[i]);
  #elif DISPLAY_PRESSURE_AS_KPA
     TPMS[i].TPMS_LowPressureLimit = KPA_To_PSI(PressureLowLimits[i]);
     TPMS[i].TPMS_HighPressureLimit = KPA_To_PSI(PressureHighLimits[i]);
  #else
     TPMS[i].TPMS_LowPressureLimit = PressureLowLimits[i];
     TPMS[i].TPMS_HighPressureLimit = PressureHighLimits[i];
  #endif



  #ifdef DISPLAY_TEMP_AS_FAHRENHEIT
     TPMS[i].TPMS_LowTemperatureLimit = DegF_To_DegC(TemperatureLowLimits[i]);
     TPMS[i].TPMS_HighTemperatureLimit = DegF_To_DegC(TemperatureHighLimits[i]);  
  #else
     TPMS[i].TPMS_LowTemperatureLimit = TemperatureLowLimits[i];
     TPMS[i].TPMS_HighTemperatureLimit = TemperatureHighLimits[i];
  #endif
  
  TPMS[i].LowPressure = false;
  TPMS[i].HighPressure = false;
  TPMS[i].LowTemperature = false;
  TPMS[i].HighTemperature = false;
  TPMS[i].AudibleAlarmActive = false;
  #ifdef USE_LCDDISPLAY
     if (i < 4)
        ClearDisplayBlock(i);
  #endif
}

void PulseDebugPin(int width_us)
{
  digitalWrite(DEBUGPIN, HIGH);
  delayMicroseconds(width_us);
  digitalWrite(DEBUGPIN, LOW);
}

void UpdateFreqOffset()
{
    FreqOffsetAcc = FreqOffsetAcc + readStatusReg(CC1101_FREQEST);
    writeReg(CC1101_FSCTRL0, FreqOffsetAcc);
    
}



int GetPreferredIndex(unsigned long ID)
{
  int i;

  //for (i = 0; i  < (sizeof(IDLookup) / sizeof(IDLookup[0])); i++)
  for (i = 0; i  < TYRECOUNT; i++)
  {
    if (IDLookup[i] == ID)
    {
      return (i);
    }

  }
  return (-1);
}

void GetPreferredIndexStr(unsigned long ID, char* sptr)
{
  int tmp;
  tmp = GetPreferredIndex(ID);

  switch (tmp % 5)
  {
    case 0:
       strcpy(sptr, "FL");
       break;
    case 1:
       strcpy(sptr, "FR");
       break;
    case 2:
       strcpy(sptr, "RL");
       break; 
    case 3:
       strcpy(sptr, "RR");
       break;
    case 4:
       strcpy(sptr, "SP");
       break;
    default:
       sptr[0] = '\0';
       break;
    
  }
}

void PrintTimings(byte StartPoint, unsigned int Count)
{
  unsigned int i;
  char c[10];
  for (i = 0; i < Count; i++)
  {
    if ((StartPoint == 0) && (i == StartDataIndex))
         Serial.println();
    sprintf(c, "%3d,",Timings[StartPoint + i]);
    Serial.print(c);
    //Serial.print(Timings[StartPoint + i]);
    //Serial.print(F(","));
  }
  Serial.println(F(""));
  //    for (i = 0;i<Count;i++)
  //    {
  //          Serial.print(BitTimings[StartPoint + i]);
  //          Serial.print(",");
  //    }
  //    Serial.println("");


}

void PrintData(int StartPos, unsigned int Count)
{
  unsigned int i, c;
  byte hexdata;
  for (i = StartPos, c = 1; c <= Count; i++, c++)
  {
    Serial.print(IncomingBits[i]);
    hexdata = (hexdata << 1) + IncomingBits[i];
    if (c % 8 == 0)
    {
      Serial.print(F(" ["));
      Serial.print(hexdata, HEX);
      Serial.print(F("] "));
      hexdata = 0;
    }
  }
  Serial.println(F(""));

}

void PrintData(unsigned int Count)
{
   PrintData(0,Count);
//  unsigned int i;
//  byte hexdata;
//  for (i = 0; i < Count; i++)
//  {
//    Serial.print(IncomingBits[i]);
//    hexdata = (hexdata << 1) + IncomingBits[i];
//    if ((i + 1) % 8 == 0)
//    {
//      Serial.print(F(" ["));
//      Serial.print(hexdata, HEX);
//      Serial.print(F("] "));
//      hexdata = 0;
//    }
//  }
//  Serial.println(F(""));
}



void PrintBytes(unsigned int Count)
{
  byte i;

  for (i = 0; i < Count; i++)
  {
    Serial.print(F(" ["));
    Serial.print(RXBytes[i],HEX);
    Serial.print(F("] "));
  }
  Serial.println(F(""));

}
void InitTPMS()
{
  int i;

  for (i = 0; i < TYRECOUNT; i++)
  {
    ClearTPMSData(i);
  }
  #ifdef USE_LCDDISPLAY 
     UpdateDisplay();
     SignalRefreshNeeded = false;
  #endif

}

double GetTempCompensatedPressureLimit(double LimitsPressure, float LimitsTemperature_DegC, float CurrentTemperature_DegC)
{
   return((CurrentTemperature_DegC + DEGC_TO_KELVIN) * (LimitsPressure / (LimitsTemperature_DegC + DEGC_TO_KELVIN)));  // T2 * (P1/T1)
}

bool PressureBelowLowPressureLimit(int TyreIndex)
{
  bool ret = false;

  double RoundedPressure = round(TPMS[TyreIndex].TPMS_Pressure * 10)/10.0;
  float LowLimit = TPMS[TyreIndex].TPMS_LowPressureLimit;
  float Temperature = TPMS[TyreIndex].TPMS_Temperature;
  
  #ifdef ENABLE_PRESSURE_ALARM_TEMPERATURE_COMPENSATION
       LowLimit = GetTempCompensatedPressureLimit(LowLimit, PressureLimitsTemperature,Temperature);   //adjust the limit based on the current temperatue and the temperature defined for the limits setting T2 * (P1/T1)
       LowLimit = round(LowLimit * 10)/10.0;
  #endif

  if (RoundedPressure < LowLimit)
  {
       ret = true;
  }

  return(ret);
  
}

bool PressureAboveHighPressureLimit(int TyreIndex)
{
  bool ret = false;

  double RoundedPressure = round(TPMS[TyreIndex].TPMS_Pressure * 10)/10.0;
  float HighLimit = TPMS[TyreIndex].TPMS_HighPressureLimit;
  float Temperature = TPMS[TyreIndex].TPMS_Temperature;
  
  #ifdef ENABLE_PRESSURE_ALARM_TEMPERATURE_COMPENSATION
       HighLimit = GetTempCompensatedPressureLimit(HighLimit, PressureLimitsTemperature,Temperature);   //adjust the limit based on the current temperatue and the temperature defined for the limits setting T2 * (P1/T1)
       HighLimit = round(HighLimit * 10)/10.0;
  #endif

  if (RoundedPressure > HighLimit)
  {
       ret = true;
  }

  return(ret);
  
}

bool TemperatureBelowLowTemperatureLimit(int TyreIndex)
{
  bool ret = false;

  float LowLimit = TPMS[TyreIndex].TPMS_LowTemperatureLimit;
  float Temperature = round(TPMS[TyreIndex].TPMS_Temperature * 10)/10.0;
  

  if (Temperature < LowLimit)
  {
       ret = true;
  }

  return(ret);
  
}

bool TemperatureAboveHighTemperatureLimit(int TyreIndex)
{
  bool ret = false;

  float HighLimit = TPMS[TyreIndex].TPMS_HighTemperatureLimit;
  float Temperature = round(TPMS[TyreIndex].TPMS_Temperature * 10)/10.0;
  


  if (Temperature > HighLimit)
  {
       ret = true;
  }

  return(ret);
  
}

void UpdateTPMSData(int index, unsigned long ID, unsigned int status, float Temperature, double Pressure)
{

  if (index >= TYRECOUNT)
    return;

  TPMS[index].TPMS_ID = ID;
  TPMS[index].TPMS_Status = status;
  TPMS[index].lastupdated = millis();
  TPMS[index].TPMS_Temperature = Temperature;
  TPMS[index].TPMS_Pressure = Pressure;


  #ifdef ENABLE_PRESSURE_ALARMS
      if (PressureBelowLowPressureLimit(index))
      {
       
        TPMS[index].LowPressure = true;
        #ifdef SHOWDEBUGINFO
           Serial.print(F("Low Pressure warning."));
           Serial.print(F("  Limit: "));
           Serial.print(ConvertPressureForDisplay(TPMS[index].TPMS_LowPressureLimit));
           #ifdef ENABLE_PRESSURE_ALARM_TEMPERATURE_COMPENSATION
              Serial.print(F(" ["));
              Serial.print(ConvertPressureForDisplay(GetTempCompensatedPressureLimit(TPMS[index].TPMS_LowPressureLimit,PressureLimitsTemperature,TPMS[index].TPMS_Temperature)));
              Serial.print(F("]"));
           #endif
           Serial.print(F("  Measured: "));
           Serial.println(ConvertPressureForDisplay(TPMS[index].TPMS_Pressure));
        #endif
      }
      else
      {
        TPMS[index].LowPressure = false;
      }
      
      if (PressureAboveHighPressureLimit(index))
      {
        
        TPMS[index].HighPressure = true;
       #ifdef SHOWDEBUGINFO
           Serial.print(F("High Pressure warning."));
           Serial.print(F("  Limit: "));
           Serial.print(ConvertPressureForDisplay(TPMS[index].TPMS_HighPressureLimit));
           #ifdef ENABLE_PRESSURE_ALARM_TEMPERATURE_COMPENSATION
              Serial.print(F(" ["));
              Serial.print(ConvertPressureForDisplay(GetTempCompensatedPressureLimit(TPMS[index].TPMS_HighPressureLimit,PressureLimitsTemperature,TPMS[index].TPMS_Temperature)));
              Serial.print(F("]"));
           #endif
           Serial.print(F("  Measured: "));
           Serial.println(ConvertPressureForDisplay(TPMS[index].TPMS_Pressure));
        #endif
      }
      else
      {
        TPMS[index].HighPressure = false;
      }

  #endif

  #ifdef ENABLE_TEMPERATURE_ALARMS
      if (TemperatureBelowLowTemperatureLimit(index))
      {      
        TPMS[index].LowTemperature = true;
        #ifdef SHOWDEBUGINFO
           Serial.print(F("Low Temperature warning."));
           #ifdef DISPLAY_TEMP_AS_FAHRENHEIT
             Serial.print(F("  Limit(degF): "));
             Serial.print(DegC_To_DegF(TPMS[index].TPMS_LowTemperatureLimit));
             Serial.print(F("  Measured(degF): "));
             Serial.println(DegC_To_DegF(TPMS[index].TPMS_Temperature));
           #else
             Serial.print(F("  Limit(degC): "));
             Serial.print(TPMS[index].TPMS_LowTemperatureLimit);
             Serial.print(F("  Measured(degC): "));
             Serial.println(TPMS[index].TPMS_Temperature);
           #endif
        #endif
      }
      else
      {
        TPMS[index].LowTemperature = false;
      }
      
      if (TemperatureAboveHighTemperatureLimit(index))
      {
        
       TPMS[index].HighTemperature = true;
        #ifdef SHOWDEBUGINFO
           Serial.print(F("High Temperature warning."));
           #ifdef DISPLAY_TEMP_AS_FAHRENHEIT
             Serial.print(F("  Limit(degF): "));
             Serial.print(DegC_To_DegF(TPMS[index].TPMS_HighTemperatureLimit));
             Serial.print(F("  Measured(degF): "));
             Serial.println(DegC_To_DegF(TPMS[index].TPMS_Temperature));
           #else
             Serial.print(F("  Limit(degC): "));
             Serial.print(TPMS[index].TPMS_HighTemperatureLimit);
             Serial.print(F("  Measured(degC): "));
             Serial.println(TPMS[index].TPMS_Temperature);
           #endif
        #endif
      }
      else
      {
        TPMS[index].HighTemperature = false;
      }

  #endif
  
  bitSet(TPMSChangeBits,index);
  
  TPMS[index].RSSIdBm = RSSIvalue;
}

void DisplayStatusInfo()
{
  Serial.print (F("FreqOffset: "));
  Serial.print (FreqOffset);
  Serial.print (F("  DemodLinkQuality: "));
  Serial.print (DemodLinkQuality);
  Serial.print (F("  RSSI: "));
  Serial.println (RSSIvalue);
}

bool OutOfLimitsPressureCheck()
{

  int i;
  bool ret = false;

  
  #ifdef ENABLE_PRESSURE_ALARMS
      Pressure_Alarm_Active = false;
      
      for (i = 0; i < TYRECOUNT; i++)
      {
    
         if ((TPMS[i].LowPressure == true) || (TPMS[i].HighPressure == true))
         {
           Pressure_Alarm_Active = true;
           #ifdef ENABLE_AUDIBLE_ALARM
              //initiate alarm (initial trigger)
              if (TPMS[i].AudibleAlarmActive == false)
              {
                 StartAlarm();
                 TPMS[i].AudibleAlarmActive = true;
              }
           #endif
         }
         else
         {
              if ((TPMS[i].LowPressure == false) && (TPMS[i].HighPressure == false) && (TPMS[i].LowTemperature == false) && (TPMS[i].HighTemperature == false)) 
              {
                 TPMS[i].AudibleAlarmActive = false;
              }
         }       
       
      }
      
      #ifdef ENABLE_AUDIBLE_ALARM
            if ((Pressure_Alarm_Active == false) && ( Temperature_Alarm_Active == false))  
            {
               if (Audible_Alarm_Running)
                  StopAlarm();
            }
      #endif
      
      return(Pressure_Alarm_Active);

  #else
     Pressure_Alarm_Active = false;
     return(false);   
  #endif

}

bool OutOfLimitsTemperatureCheck()
{

  int i;
  bool ret = false;

 
 
  #ifdef ENABLE_TEMPERATURE_ALARMS
      Temperature_Alarm_Active = false;

      for (i = 0; i < TYRECOUNT; i++)
      {
         if ((TPMS[i].LowTemperature == true) || (TPMS[i].HighTemperature == true))
         {
           Temperature_Alarm_Active = true;
           #ifdef ENABLE_AUDIBLE_ALARM
              
              //initiate alarm (initial trigger)
              if (TPMS[i].AudibleAlarmActive == false)
              {
                 StartAlarm();
                 TPMS[i].AudibleAlarmActive = true;
              }
           #endif
         }
         else
         {          
            if ((TPMS[i].LowPressure == false) && (TPMS[i].HighPressure == false) && (TPMS[i].LowTemperature == false) && (TPMS[i].HighTemperature == false)) 
            {
               TPMS[i].AudibleAlarmActive = false;                         
            }

         }       
       
      }
      
      #ifdef ENABLE_AUDIBLE_ALARM
        if ((Pressure_Alarm_Active == false) && ( Temperature_Alarm_Active == false))    
        {
...

This file has been truncated, please download it to see its full contents.

display

C Header File
//#define USE_ADAFRUIT 1
#define USE_TEXTONLY 1


extern void ResetSignalRefreshTimer();

#ifndef USE_ADAFRUIT

   #include "SSD1306Ascii.h"
   #include "SSD1306AsciiWire.h"

   SSD1306AsciiWire display;


   void ShowTitle()
  {
    //display.clear();
  
    display.set1X();             // Normal 1:1 pixel scale
    //display.setTextColor(WHITE, BLACK);       // Draw white text
  
    display.setCursor(0, 0);
    #ifdef NissanLeaf
       display.println("Nissan Leaf TPMS");
    #elif Dacia
       display.println("Dacia TPMS");
    #elif Renault
       #ifdef Zoe
          display.println("Ren Zoe(early) TPMS");
       #else
          display.println("Renault TPMS");
       #endif
    #elif Citroen
       display.println("Citroen TPMS");
    #elif Citroen
       display.println("Citroen TPMS Monitor");
    #elif Jansite
       display.println("Jansite TPMS Monitor");
    #elif JansiteSolar
       display.println("JSolar TPMS Monitor");
    #elif Citroen
       display.println("Citroen TPMS Monitor");
    #elif PontiacG82009
       display.print("Pontiac G8 TPMS");
    #else
       display.println("Toyota TPMS Monitor");
    #endif
    display.print(" JSM Solutions ");
    display.print(VERSION);
    //display.println(")");
  
  
  }

  char DisplayTimeoutBar(unsigned long TimeSinceLastUpdate)
  {
      int HowCloseToTimeout;
      HowCloseToTimeout = (int)(TimeSinceLastUpdate/(TPMS_TIMEOUT/5));

      switch(HowCloseToTimeout)
      {
        case 0: 
           //return(FONTBAR_7);
           return('5');
           break;
        case 1: 
           //return(FONTBAR_5);
           return('4');
           break;
        case 2: 
           //return(FONTBAR_3);
           return('3');
           break;
        case 3: 
           //return(FONTBAR_2);
           return('2');
           break;
        case 4: 
           //return(FONTBAR_1);
           return('1');
           break;
        default: 
           //return(FONTBAR_0);
           return('0');
           break;
                      
      }
  }


  int GetBlockStartX(byte i)
  {
  

      switch (i)
      {
        case 0:
          return(0);
          break;
        case 1:
          return(59);
          break;
        case 2:
          return(0);
          break;
        case 3:
          return(59);
          break;
      }
  }

  
  int GetBlockStartY(byte i)
  {
  

      switch (i)
      {
        case 0:
          return(2);
          break;
        case 1:
          return(2);
          break;
        case 2:
          return(5);
          break;
        case 3:
          return(5);
          break;
          
      }
  }

  void ClearDisplayBlock(byte i)
  {
     int x,y;

     x = GetBlockStartX(i);
     y = GetBlockStartY(i);

     display.setFont(Adafruit5x7);
     display.set2X();
     display.clearField(x,y,4);
     display.set1X();
     display.clearField(x,y+2,8);
     
  }




  void UpdateBlock(int i)
  {
        int x,y;
        char s[6];
        char t;

        if ((TPMS[i].LowPressure == true) || (TPMS[i].HighPressure == true))
        {
          if (DisplayFlash)
          {
             strcpy(s,"    ");
          }
          else
          {
             #ifdef DISPLAY_PRESSURE_AS_BAR
                dtostrf(PSI_To_BAR(TPMS[i].TPMS_Pressure), 4, 2, s);
             #elif DISPLAY_PRESSURE_AS_KPA
                dtostrf(PSI_To_KPA(TPMS[i].TPMS_Pressure), 3, 0, s);  //rounded to integer value
             #else
                dtostrf(TPMS[i].TPMS_Pressure, 3, 1, s);
             #endif
          }
        }
        else
        {
           #ifdef DISPLAY_PRESSURE_AS_BAR
              dtostrf(PSI_To_BAR(TPMS[i].TPMS_Pressure), 4, 2, s);
           #elif DISPLAY_PRESSURE_AS_KPA
              dtostrf(PSI_To_KPA(TPMS[i].TPMS_Pressure), 3, 0, s);  //rounded to integer value
           #else
              dtostrf(TPMS[i].TPMS_Pressure, 3, 1, s);
           #endif
        }

        
        x = GetBlockStartX(i);
        y = GetBlockStartY(i);
        display.setCursor(x, y);
        
        //sprintf(temperature,"%s F", str_temp);
        //sprintf(s,"%.1f",TPMS[i].TPMS_Pressure);
        //display.invertDisplay(InvertMode);
        display.setFont(Adafruit5x7);
        display.set2X();
        //display.clearField(x,y,4);
        display.print(s);


        display.setCursor(x, y+2);
        display.setFont(Adafruit5x7);
        display.set1X();
        //display.clearField(x,y+2,8);


        #ifdef DISPLAY_TEMP_AS_FAHRENHEIT
           t = 'F';
        #else
           t = 'C';
        #endif

        if ((TPMS[i].LowTemperature == true) || (TPMS[i].HighTemperature == true))
        {
          if (DisplayFlash)
          {
             strcpy(s,"       ");
             display.print(s); 
          }
          else
          {
             #ifdef DISPLAY_TEMP_AS_FAHRENHEIT
                dtostrf(DegC_To_DegF(TPMS[i].TPMS_Temperature), 2, 0, s);
             #else
                dtostrf(TPMS[i].TPMS_Temperature, 2, 0, s);
             #endif
              display.print(" ");
              display.print(s);
              display.setFont(System5x7);
              display.print(char(128));  //degrees symbol
              display.setFont(Adafruit5x7);
             display.print(t);
             display.print("  ");
          }
        }
        else
        {
             #ifdef DISPLAY_TEMP_AS_FAHRENHEIT
                dtostrf(DegC_To_DegF(TPMS[i].TPMS_Temperature), 2, 0, s);
             #else
                dtostrf(TPMS[i].TPMS_Temperature, 2, 0, s);
             #endif
              display.print(" ");
              display.print(s);
              display.setFont(System5x7);
              display.print(char(128));  //degrees symbol
              display.setFont(Adafruit5x7);
             display.print(t);
             display.print("  ");
        }




        
        //dtostrf(TPMS[i].TPMS_Temperature, 2, 0, s);
//        display.print(" ");
//        display.print(s);
//        display.setFont(System5x7);
//        display.print(char(128));  //degrees symbol
//        display.setFont(Adafruit5x7);
//        #ifdef DISPLAY_TEMP_AS_FAHRENHEIT
//           display.print("F");
//        #else
//           display.print("C");
//        #endif
//        display.print("  ");

        //display vertical bar showing how long since last update 7 bars = recent 1 bar = nearing timeout (at timeout it will be removed from display altogether)
        display.setFont(System5x7);          
        display.print(DisplayTimeoutBar(millis() - TPMS[i].lastupdated));
  }
 
  void UpdateDisplay()
  {
    int i;
    int x = 0;
    int y = 0;
    char s[6];
  
    //ShowTitle();

    for (i = 0; i < 4; i++)
    {
      
      if (TPMS[i].TPMS_ID != 0)
      {
          //Only update the areas which need it to keep the timing overheads down
//          if ((TPMS[i].LowPressure == true) || (TPMS[i].HighPressure == true) || (bitRead(TPMSChangeBits,i) == 1) || SignalRefreshNeeded)
//          {
             UpdateBlock(i);
             if ((bitRead(TPMSChangeBits,i) == 1))
             {
                bitClear(TPMSChangeBits,i);
             }

//          }

      }


    }



  
//    for (i = 0; i < 4; i++)
//    {
//      switch (i)
//      {
//        case 0:
//          x = 0;
//          y = 2;
//          break;
//        case 1:
//          x = 59;
//          y = 2;
//          break;
//        case 2:
//          x = 0;
//          y = 5;
//          break;
//        case 3:
//          x = 59;
//          y = 5;
//          break;
//      }
//  
//  
//      display.setCursor(x, y);
//  
//      if (TPMS[i].TPMS_ID != 0)
//      {
////        #ifdef DISPLAY_PRESSURE_AS_BAR
////           dtostrf(TPMS[i].TPMS_Pressure, 4, 2, s);
////        #else
////           dtostrf(TPMS[i].TPMS_Pressure, 3, 1, s);
////        #endif
//        //sprintf(temperature,"%s F", str_temp);
//        //sprintf(s,"%.1f",TPMS[i].TPMS_Pressure);
//        display.setFont(Adafruit5x7);
//        display.set2X();
//        display.print(s);
//
//
//        display.setCursor(x, y+2);
//        display.setFont(Adafruit5x7);
//        display.set1X();
//        dtostrf(TPMS[i].TPMS_Temperature, 2, 0, s);
//        display.print(" ");
//        display.print(s);
//        display.setFont(System5x7);
//        display.print(char(128));  //degrees symbol
//        display.setFont(Adafruit5x7);
//        #ifdef DISPLAY_TEMP_AS_FAHRENHEIT
//           display.print("F");
//        #else
//           display.print("C");
//        #endif
//        
//        display.print("  ");
//
//        //display vertical bar showing how long since last update 7 bars = recent 1 bar = nearing timeout (at timeout it will be removed from display altogether)
//        display.setFont(System5x7);          
//        display.print(DisplayTimeoutBar(millis() - TPMS[i].lastupdated));
//      }
//
//
//    }
    
  
  }

#else
   #include <Adafruit_GFX.h>
   #include <Adafruit_SSD1306.h>


   #define SCREEN_WIDTH 128 // OLED display width, in pixels
   #define SCREEN_HEIGHT 64 // OLED display height, in pixels
   Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT,  &Wire, -1);


  void ShowTitle()
  {
    display.clearDisplay();
    display.setFont(Adafruit5x7);
    display.setTextSize(1);             // Normal 1:1 pixel scale
    display.setTextColor(WHITE, BLACK);       // Draw white text
  
    display.setCursor(0, 0);
    #ifdef NissanLeaf
       display.print("Nissan Leaf TPMS");
    #elif Dacia
       display.print("Dacia TPMS");
    #elif Renault
       display.print("Renault TPMS");
    #elif Citroen
       display.print("Citroen TPMS");
    #elif Citroen
       display.println("Citroen TPMS Monitor");
    #elif Jansite
       display.println("Jansite TPMS Monitor");
    #elif JansiteSolar
       display.println("JSolar TPMS Monitor");
    #elif Citroen
       display.println("Citroen TPMS Monitor");
    #elif PontiacG82009
       display.print("Pontiac G8 TPMS");
    #else
       display.println("Toyota TPMS Monitor");
    #endif
    
    display.print(" JSM Solutions ");
    display.print(VERSION);
    //display.println(")");
  
  
  }
  
  void UpdateDisplay()
  {
    int i;
    int x = 0;
    int y = 0;
    char s[6];
  
    ShowTitle();
    
    display.setFont(Adafruit5x7);
    display.setTextSize(2);
  
    for (i = 0; i < 4; i++)
    {
      switch (i)
      {
        case 0:
          x = 0;
          y = 16;
          break;
        case 1:
          x = 64;
          y = 16;
          break;
        case 2:
          x = 0;
          y = 48;
          break;
        case 3:
          x = 64;
          y = 48;
          break;
      }
  
  
      display.setCursor(x, y);
  
      if (TPMS[i].TPMS_ID != 0)
      {
        dtostrf(TPMS[i].TPMS_Pressure, 3, 1, s);
        //sprintf(temperature,"%s F", str_temp);
        //sprintf(s,"%.1f",TPMS[i].TPMS_Pressure);
        display.print(s);
      }
    }
    display.display();

  
  }
   


#endif

globals

C Header File
#define USE_HW_CD 1
//#define USE_TEST_TIMINGS 1



#define SHOWVALIDTPMS 1
#define SHOWDEBUGINFO 1
//#define IGNORECHECKSUMERRORS 1
#define ALWAYSSHOWTIMINGS 1
//#define SPECIFIC_IDS_ONLY 1

#define I2C_ADDRESS 0x3C


#define LED_OFF HIGH
#define LED_ON LOW

#define TPMS_TIMEOUT 900000 //(15 * 60 * 1000)  15 minutes
#define CAL_PERIOD_MS 3600000 //60 * 60 * 1000  60 minutes

#define FONTBAR_7 123
#define FONTBAR_5 124
#define FONTBAR_3 125
#define FONTBAR_2 126
#define FONTBAR_1 127
#define FONTBAR_0 32


//#ifdef INCLUDESPARETYRE  - nolonger used. If no spare with TPMS, just set the ID to 0xFFFFFFF
//  #define TYRECOUNT 5
//#else
//  #define TYRECOUNT 4
//#endif

#ifdef INCLUDE_WINTER_SET
   #define TYRECOUNT 10
#else
   #define TYRECOUNT 5
#endif

#define PSI2BAR 14.504
#define KPA2PSI 6.895

#define DEGC_TO_KELVIN 273.15

#define BITISLONG 1
#define BITISSHORT 0
#define BITISSYNC 2
#define BITISUNDEFINED -1

// hardware pin configuration

#ifdef ARDUINO_AVR_PROMICRO
   #define PROC_TYPE "Arduino Pro Micro"
   const int RXPin = 7;   //must be an ext interrupt pin
   const int CDPin = 9;  //if wired, define 'USE_HW_CD' above, otherwise CD pin status is received over SPI
   const int CC1101_CS = 10;  // Define the Chip Select pin
   const int AUDIBLE_ALARM_PIN = 8;
   const int DEBUGPIN = 6;
   const int LED_RX = LED_BUILTIN;
   const int MAXBITS =200;
   const int MAXTIMINGS = 255;
#elif ARDUINO_AVR_NANO
   #define PROC_TYPE "Arduino Nano"
   #error Arduino Nano doesn't have sufficient RAM (only 2k) to run this program. Switch to another board type e.g. Arduino Nano 33 IOT. 
//   const int RXPin = 2;   //must be an ext interrupt pin
//   const int CDPin = 9;  //if wired, define 'USE_HW_CD' above, otherwise CD pin status is received over SPI
//   const int CC1101_CS = 10;  // Define the Chip Select pin
//   const int AUDIBLE_ALARM_PIN = 8;
//   const int DEBUGPIN = 6;
//   const int LED_RX = LED_BUILTIN;
//   const int MAXBITS = 200;
//   const int MAXTIMINGS = 255;
#elif ARDUINO_SEEED_XIAO_M0
   #define PROC_TYPE "Seeeduino Xiao"
   const int RXPin = 1;   //must be an ext interrupt pin
   const int CDPin = 0;  //if wired, define 'USE_HW_CD' above, otherwise CD pin status is received over SPI
   const int CC1101_CS = 2;  // Define the Chip Select pin
   const int AUDIBLE_ALARM_PIN = 7;
   const int DEBUGPIN = 12;  //use the TX LED pin
   const int LED_RX = LED_BUILTIN;
   const int MAXBITS = 1000;
   const int MAXTIMINGS = 900;
#elif ARDUINO_SAMD_NANO_33_IOT
   #define PROC_TYPE "Arduino Nano 33 IOT"
   const int RXPin = 2;   //must be an ext interrupt pin
   const int CDPin = 9;  //if wired, define 'USE_HW_CD' above, otherwise CD pin status is received over SPI
   const int CC1101_CS = 10;  // Define the Chip Select pin
   const int AUDIBLE_ALARM_PIN = 8;
   const int DEBUGPIN = 6;
   const int LED_RX = LED_BUILTIN;
   const int MAXBITS = 1000;
   const int MAXTIMINGS = 900;
   #include <avr/dtostrf.h>
#else
   #error No configuration set up for this processor type in globals.h
#endif

#define AUDIBLE_ALARM_ON_TIME_MS 500
#define AUDIBLE_ALARM_OFF_TIME_MS 1000
#define AUDIBLE_ALARM_ONOFF_COUNT 5
#define AUDIBLE_ALARM_REMINDER_TIME_MS 1800000L //30 x 60 x 1000 (repeat alarm after 30 minutes) - Set to zero for no reminders. Note: value must be > (AUDIBLE_ALARM_ON_TIME_MS + AUDIBLE_ALARM_OFF_TIME_MS) * AUDIBLE_ALARM_ONOFF_COUNT


//const long Tlong_us = 100;
//const long Tshort_us = Tlong_us/2;
const int Ttol_l_us = 25;
const int Ttol_s_us = 13;
volatile static unsigned long LastEdgeTime_us = 0;

volatile static bool ValidBlock = false;
volatile static bool WaitingFirstEdge = true;
volatile unsigned int Timings[MAXTIMINGS+1];
volatile bool FirstEdgeIsHighToLow;


volatile unsigned int TimingsIndex = 0;
unsigned int CheckIndex = 0;
bool SyncFound = false;
unsigned long CD_Width;
int StartDataIndex = 0;
bool TPMS_Changed = false;
bool Pressure_Alarm_Active = false;
bool Temperature_Alarm_Active = false;
bool Audible_Alarm_On = false;
bool Audible_AlarmPin_Active = LOW;
int Audible_Alarm_Cycle_Countdown = 0;
bool Audible_Alarm_Running = false;

unsigned long DisplayTimer =0;
boolean DisplayFlash  = false;
boolean DisplayFlashExpired = false;
boolean SignalRefreshNeeded = false;
//const unsigned long  DISPLAYFLASHREFRESHTIMING = 1000;  //pressures warning flash rate
const unsigned int NOBLANK_MS = 1500;  //pressures warning flash rate (on time)
const unsigned int BLANK_MS = 500;  //pressures warning flash rate (off time)
const unsigned long  SIGNALREFRESHTIMING = 20000;  //force screen update so that signal bar can be updated if needed
byte TPMSChangeBits = 0;


bool IncomingBits[MAXBITS]; 
unsigned int BitIndex = 0;
unsigned int BitCount = 0;

unsigned int FreqOffset;
unsigned int DemodLinkQuality;
int RSSIvalue;
unsigned int FreqOffsetAcc = 0;
unsigned long LastCalTime;
char Ref[3];

int RawCount = 0;
//byte ManchesterRX[64];  //holds received Manchester byte message (converted from the rawdata)
byte RXBytes[20];  //holds the raw incoming databytes from the CC1101 serial port
int RXByteCount;
unsigned long IncomingAddress;

//function declataions
extern bool ValidateTimings();
extern bool ReceiveMessage();
extern void DecodeTPMS();



//this table (and its order define known TPMS IDs so that they their values are always displayed in the same order
const unsigned long  IDLookup[] =
{
  FRONT_LEFT, FRONT_RIGHT, 
  REAR_LEFT, REAR_RIGHT, 
  SPARE,
  WINTER_FRONT_LEFT, WINTER_FRONT_RIGHT, 
  WINTER_REAR_LEFT, WINTER_REAR_RIGHT, 
  WINTER_SPARE,  
};





  ////CRCTable
  const byte PROGMEM CRC8_Poly_07_crctable2[] =
  {
  
      0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15, 0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D,
      0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65, 0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D,
      0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB, 0xF2, 0xF5, 0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD,
      0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85, 0xA8, 0xAF, 0xA6, 0xA1, 0xB4, 0xB3, 0xBA, 0xBD,
      0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2, 0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA,
      0xB7, 0xB0, 0xB9, 0xBE, 0xAB, 0xAC, 0xA5, 0xA2, 0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A,
      0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32, 0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A,
      0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42, 0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A,
      0x89, 0x8E, 0x87, 0x80, 0x95, 0x92, 0x9B, 0x9C, 0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4,
      0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC, 0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3, 0xD4,
      0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C, 0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44,
      0x19, 0x1E, 0x17, 0x10, 0x05, 0x02, 0x0B, 0x0C, 0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34,
      0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B, 0x76, 0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63,
      0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B, 0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13,
      0xAE, 0xA9, 0xA0, 0xA7, 0xB2, 0xB5, 0xBC, 0xBB, 0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83,
      0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB, 0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3
  };

  const byte PROGMEM CRC8_Poly_13_crctable2[] =
  {
  
        0x00, 0x13, 0x26, 0x35, 0x4C, 0x5F, 0x6A, 0x79, 0x98, 0x8B, 0xBE, 0xAD, 0xD4, 0xC7, 0xF2, 0xE1,
        0x23, 0x30, 0x05, 0x16, 0x6F, 0x7C, 0x49, 0x5A, 0xBB, 0xA8, 0x9D, 0x8E, 0xF7, 0xE4, 0xD1, 0xC2,
        0x46, 0x55, 0x60, 0x73, 0x0A, 0x19, 0x2C, 0x3F, 0xDE, 0xCD, 0xF8, 0xEB, 0x92, 0x81, 0xB4, 0xA7,
        0x65, 0x76, 0x43, 0x50, 0x29, 0x3A, 0x0F, 0x1C, 0xFD, 0xEE, 0xDB, 0xC8, 0xB1, 0xA2, 0x97, 0x84,
        0x8C, 0x9F, 0xAA, 0xB9, 0xC0, 0xD3, 0xE6, 0xF5, 0x14, 0x07, 0x32, 0x21, 0x58, 0x4B, 0x7E, 0x6D,
        0xAF, 0xBC, 0x89, 0x9A, 0xE3, 0xF0, 0xC5, 0xD6, 0x37, 0x24, 0x11, 0x02, 0x7B, 0x68, 0x5D, 0x4E,
        0xCA, 0xD9, 0xEC, 0xFF, 0x86, 0x95, 0xA0, 0xB3, 0x52, 0x41, 0x74, 0x67, 0x1E, 0x0D, 0x38, 0x2B,
        0xE9, 0xFA, 0xCF, 0xDC, 0xA5, 0xB6, 0x83, 0x90, 0x71, 0x62, 0x57, 0x44, 0x3D, 0x2E, 0x1B, 0x08,
        0x0B, 0x18, 0x2D, 0x3E, 0x47, 0x54, 0x61, 0x72, 0x93, 0x80, 0xB5, 0xA6, 0xDF, 0xCC, 0xF9, 0xEA,
        0x28, 0x3B, 0x0E, 0x1D, 0x64, 0x77, 0x42, 0x51, 0xB0, 0xA3, 0x96, 0x85, 0xFC, 0xEF, 0xDA, 0xC9,
        0x4D, 0x5E, 0x6B, 0x78, 0x01, 0x12, 0x27, 0x34, 0xD5, 0xC6, 0xF3, 0xE0, 0x99, 0x8A, 0xBF, 0xAC,
        0x6E, 0x7D, 0x48, 0x5B, 0x22, 0x31, 0x04, 0x17, 0xF6, 0xE5, 0xD0, 0xC3, 0xBA, 0xA9, 0x9C, 0x8F,
        0x87, 0x94, 0xA1, 0xB2, 0xCB, 0xD8, 0xED, 0xFE, 0x1F, 0x0C, 0x39, 0x2A, 0x53, 0x40, 0x75, 0x66,
        0xA4, 0xB7, 0x82, 0x91, 0xE8, 0xFB, 0xCE, 0xDD, 0x3C, 0x2F, 0x1A, 0x09, 0x70, 0x63, 0x56, 0x45,
        0xC1, 0xD2, 0xE7, 0xF4, 0x8D, 0x9E, 0xAB, 0xB8, 0x59, 0x4A, 0x7F, 0x6C, 0x15, 0x06, 0x33, 0x20,
        0xE2, 0xF1, 0xC4, 0xD7, 0xAE, 0xBD, 0x88, 0x9B, 0x7A, 0x69, 0x5C, 0x4F, 0x36, 0x25, 0x10, 0x03
  };

struct TPMS_entry
{
  unsigned long TPMS_ID;
  unsigned long lastupdated;
  unsigned int TPMS_Status;
  double TPMS_Pressure;
  float TPMS_Temperature;
  float TPMS_LowTemperatureLimit;
  float TPMS_HighTemperatureLimit;
  double TPMS_LowPressureLimit;
  double TPMS_HighPressureLimit;
  boolean LowPressure;
  boolean HighPressure;
  boolean LowTemperature;
  boolean HighTemperature;
  int RSSIdBm;
  boolean AudibleAlarmActive;
} TPMS[TYRECOUNT];


enum RXStates
{
  Waiting_Byte33 = 0,
  Got_Byte33,
  Got_Byte55,
  Got_Byte53,
  Manch1,
  Manch2
};


//following tables useful for testing/debugging the software without the need to receive actual hardware data
//can be turned on/off using the #define USE_TEST_TIMINGS at the top of this include file

#ifdef Toyota_PMV_C210 

   #ifdef UK_433MHz
//    const unsigned int TestTimings[] =
//      {
//        24,264,104,448,48,200,96,104,96,96,56,48,48,48,56,48,96,48,56,96,96,104,48,48,48,56,96,48,
//        48,56,56,40,48,56,48,96,96,104,96,48,56,96,48,48,56,48,96,104,48,48,96,56,48,96,104,48,48,
//        48,48,104,96,104,96,96,56,48,96,56,48,48,48,48,48,104,96,56,48,48,48,48,56,48,48,48,48,56,
//        48,48,56,40,56,48,48,96,104,48,48,48,56,48,48,48,56,48,48,96,104,96,48,56,96,104,56,56,104,
//        96,408
//      };

      const unsigned int TestTimings[] =
      {
      52,56,44,56,44,52,48,52,100,196,96,100,104,96,56,40,60,40,60,44,52,44,108,44,52,92,112,88,56,44,52,48,104,96,96,100,104,44,56,92,104,48,52,96,104,44,56,92,56,44,104,44,56,92,104,48,52,44,60,40,60,92,104,92,48,52,100,52,44,52,56,100,92,100,52,52,48,48,104,48,48,100,92,56,52,48,52,44,52,48,52,96,100,100,48,48,52,56,48,44,100,56,48,44,56,92,48,52,56,44,96,52,56,44,56,44,52
      };
      
       const bool FirstTimingIsLow = true;
   #endif


   
#elif Renault 

   #ifdef UK_433MHz
//    const unsigned int TestTimings[] =
//      {
//       
//        350,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,100,50,
//        50,50,50,100,100,50,50,100,50,50,100,100,
//        100,100,50,50,50,50,100,100,100,100,
//        50,50,100,50,50,100,100,100,50,50,50,50,
//        100,50,50,50,50,50,50,100,50,50,100,50,
//        50,50,50,100,100,100,100,50,50,50,50,100,
//        100,50,50,50,50,50,50,100,100,100,100,
//        50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
//        50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
//        50,100,100,50,50,50,50,50,50,50,50,50,50,50,
//        300,50,50,50,50,50
//      };
//    const bool FirstTimingIsLow = true;
//   #endif



    const unsigned int TestTimings[] =
      {
          364,60,44,56,52,52,52,52,52,52,52,52,52,52,52,56,52,52,52,52,52,52,52,52,52,52,52,52,52,104,52,52,52,52,104,108,52,52,104,52,52,104,104,104,104,104,52,52,52,52,108,52,52,52,52,52,52,104,52,52,104,104,52,52,104,52,56,104,52,52,104,52,52,104,52,52,52,52,104,52,52,104,108,104,52,52,52,52,52,52,104,52,52,52,52,104,108,100,108,52,52,104,52,52,52,52,52,52,52,52,52,52,52,52,52,56,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,104,52,56,104,52,52,104,52,52,52,52,104,264,      
      };
       const bool FirstTimingIsLow = true;
   #endif


   
#elif Citroen 

   #ifdef UK_433MHz
    const unsigned int TestTimings[] =
      {
         350,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,100,
         100,50,50,50,50,100,50,50,50,50,100,50,50,
         100,100,50,50,50,50,100,50,50,100,50,50,50,
         50,50,50,50,50,50,50,50,50,100,100,100,100,
         50,50,50,50,50,50,50,50,100,100,50,50,50,50,
         100,100,50,50,50,50,100,100,100,50,50,100,
         100,100,50,50,50,50,50,50,50,50,50,50,50,50,
         100,100,50,50,50,50,50,50,50,50,50,50,100,
         100,50,50,50,50,100,50,50,50,50,100,50,50,
         50,50,50,50,50,50,50,50,50,50,100,100,50,
         50,50,50,50,50,100,50,50,50,50,100,50,
         300,50,50,50,50,50
      };
       const bool FirstTimingIsLow = true;
   #endif

   
      
#elif Toyota_PMV_107J

   #ifdef US_315MHz
//    const unsigned int TestTimings[] =
//      {
//        32,52,152,52,100,708,556,200,204,204,100,100,204,200,104,100,200,204,200,204,204,100,100,
//        100,100,204,204,100,100,100,100,204,100,100,204,204,100,100,200,204,100,104,200,100,104,
//        100,100,100,100,104,100,204,100,100,100,104,100,100,104,100,200,100,104,100,100,100,104,
//        200,100,104,200,204,100,100,200,204,204,100,100,204,100,100,104,100,200,104,100,100,100,
//        104,100,100,100,100,104,200,104,100,200,104,100,100,100,204,100,104,100,104,100,100,152,
//        932,52,0
//       }; 
//    const unsigned int TestTimings[] =
//      {
//          36,1452,204,200,104,100,200,204,100,100,204,200,204,204,200,100,100,104,100,204,200,100,
//          100,104,100,204,100,100,200,204,100,100,204,204,100,100,204,100,100,100,104,100,100,100,
//          100,204,204,200,100,104,100,100,100,104,200,100,104,200,100,104,200,100,104,200,204,100,
//          100,204,100,100,204,100,100,200,104,100,204,100,100,100,104,100,100,100,104,200,204,200,
//          200,204,204,200,104,100,204,200,152,100
//
//      }; 
     const unsigned int TestTimings[] =
      {

            628,612,200,100,104,200,200,204,200,100,104,100,100,200,204,200,204,100,100,100,104,100,
            100,100,100,204,100,100,204,100,100,204,200,100,104,200,100,100,104,100,100,100,100,104,
            100,100,100,100,204,200,104,100,100,100,100,104,200,100,100,104,100,100,100,104,100,100,
            100,204,100,100,100,100,204,200,204,200,204,100,100,200,104,100,200,100,104,100,100,100,
            104,100,100,100,100,104,100,200,204,100,100,204,100,100,100,100,204,100,100,164,740
      };

    const bool FirstTimingIsLow = true;
   #endif 


  
#elif Ford 

   #ifdef UK_433MHz

    const unsigned int TestTimings[] =
      {
            52,56,48,56,48,56,48,56,48,56,48,56,52,52,48,56,48,56,48,56,48,56,48,52,52,52,52,52,
            52,104,104,104,104,52,52,52,52,104,104,104,52,52,52,52,104,104,104,52,52,104,52,52,
            100,52,52,52,52,52,52,104,104,104,52,52,104,104,52,52,104,104,104,52,52,104,52,52,
            100,56,48,52,52,104,104,104,104,104,52,52,104,52,52,52,52,52,52,52,52,104,104,104,
            104,52,52,52,52,104,48,52,104,52,52,52,52,52,52,104,52,52,52,52,104,104,80
      };
       const bool FirstTimingIsLow = true;
   #endif
   


#elif Jansite

   #ifdef UK_433MHz

//    const unsigned int TestTimings[] =
//      {
//            52,56,48,56,48,56,52,52,52,52,52,52,52,52,52,52,52,52,56,52,52,52,52,52,52,52,52,
//            52,52,52,52,52,56,52,52,52,52,52,52,52,52,52,52,52,52,56,52,52,52,52,52,52,52,52,
//            52,52,52,52,56,52,52,52,52,52,52,52,52,52,52,52,52,52,52,56,52,52,52,52,52,52,52,
//            52,52,52,52,52,52,56,52,52,52,52,52,52,52,52,52,52,52,52,52,56,52,52,52,52,52,52,
//            52,52,52,52,52,52,56,52,52,52,52,52,52,52,52,52,52,52,52,52,52,56,52,52,52,52,52,
//            52,52,52,52,52,52,52,52,56,52,52,52,52,52,52,52,52,52,52,52,52,52,56,52,52,52,52,
//            52,52,52,52,52,52,52,52,56,52,52,52,52,52,52,52,52,52,52,52,52,52,56,52,52,52,52,
//            52,52,52,52,52,52,52,52,52,56,52,52,52,52,52,52,52,52,52,52,52,52,52,52,56,52,52,
//            52,52,52,52,52,52,52,52,52,52,56,52,52,52,52,52,52,52,52,52,52,52,52,52,56,52,52,
//            52,52,52,52,52,52,52,52,52,52,52,56,52,52,52,52,52,52,52,52,52,52,52,52,52,52,56,
//            52,52,52,52,52,52,52,52,52,52,52,52,52,52,56,52,52,52,52,52,52,52,52,52,52,52,52,
//            52,56,52,52,52,104,104,104,104,104,108,104,104,104,52,52,104,104,104,108,52,52,104,
//            104,52,52,52,52,52,52,104,56,52,104,52,52,52,52,104,52,52,104,52,56,104,52,52,104,
//            104,52,52,52,52,108,52,52,104,104,104,52,52,52,52,104,108,52,52,104,104,52,52,52,
//            52,52,52,104,52,56,104,52,52,104,104,52,52,52,52,104,56,52,52,52,52,52,52,52,52,
//            52,52,52,52,52,56,52,52,52,52,52,52,52,52,52,52,52,52,52,56,52,52,52,52,52,52,52,
//            52,52,52,52,52,52,52,56,52,104,104,104,104,104,104,108,104,104,52,52,104,104,104,
//            104,56,52,104,104,52,52,52,52,52,52,104,56,52,104,52,52,52,52,104,52,52,104,56,48,
//            108,52,52,104,104,52,52,52,52,104,56,52,104,104,104,52,52,52,52,104,104,56,52,104,
//            104,52,52,52,52,52,52,104,56,52,104,52,52,104,104,52,52,52,52
//      };

    const unsigned int TestTimings[] =
      {
            52,64,40,64,44,52,52,52,52,56,48,56,52,52,52,52,52,52,52,52,52,52,52,56,52,52,52,
52,52,52,52,52,52,52,52,52,56,52,52,52,52,52,52,52,52,52,52,52,52,52,56,52,52,52,52,
52,52,52,52,52,52,52,52,56,52,52,52,52,52,52,52,52,52,52,52,52,52,56,52,52,52,52,52,
52,52,52,52,52,52,56,52,52,52,52,52,52,52,52,52,52,52,52,56,52,52,52,52,52,52,52,52,
52,52,52,52,52,56,52,52,52,52,52,52,52,52,52,52,52,52,56,52,52,52,52,52,52,52,52,52,
52,52,52,56,52,52,52,52,52,52,52,52,52,52,52,52,52,52,56,52,52,52,52,52,52,52,52,52,
52,52,52,56,52,52,52,52,52,52,52,52,52,52,52,52,56,52,52,52,52,52,52,52,52,52,52,52,
52,56,52,52,52,52,52,52,52,52,52,52,52,56,52,52,52,52,52,52,52,52,52,52,52,52,52,56,
52,52,52,52,52,52,52,52,52,52,52,52,56,52,52,52,52,52,52,52,52,52,52,52,52,52,56,52,
52,52,52,52,52,52,52,52,52,52,56,52,52,52,52,52,52,52,52,52,52,52,52,52,56,52,52,52,
52,52,52,52,52,52,52,52,52,52,56,52,52,52,52,52,52,52,52,52,52,52,52,108,104,52,52,52,
52,104,104,104,108,104,52,52,104,52,52,52,52,104,52,52,108,104,104,52,52,52,52,52,52,104,108,104,
104,104,104,52,52,104,108,104,104,52,52,52,52,52,52,52,52,52,52,52,56,52,52,52,52,52,52,52,
52,104,104,56,52,52,52,104,52,52,104,104,104,108,104,104,104,104,104,52,52,104,56,52,52,52,52,52,
52,52,52,52,52,52,52,52,56,52,52,52,52,52,52,52,52,52,52,52,56,52,52,52,52,52,52,52,
52,52,52,52,52,56,52,52,52,52,52,104,104,52,52,52,52,108,104,104,104,104,52,52,104,52,52,56,
52,104,52,52,104,104,104,52,52,52,56,52,52,104,104,104,104,104,104,56,52,104,104,104,104,52,52,52,
52,56,52,52,52,52,52,52,52,52,52,52,52,52,52,56,52,104,104,52,52,52,52,104,52,52,108,104,
104,104,104,104,104,108,104,52,52,160 
       
       };     
       const bool FirstTimingIsLow = false;
   #endif


#elif JansiteSolar
    #ifdef UK_433MHz

    const unsigned int TestTimings[] =
      {
40,48,56,48,56,48,56,52,52,52,52,52,52,52,52,52,52,52,52,52,56,52,52,52,52,52,52,52,
52,52,52,52,52,52,52,52,56,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,56,52,52,
52,52,52,52,52,52,52,52,52,52,52,52,52,56,52,52,52,52,52,52,52,52,52,52,52,52,52,52,
52,56,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,56,48,56,52,52,52,52,52,52,52,52,
52,52,52,52,52,52,52,56,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,56,52,52,52,52,
52,52,52,52,52,52,52,52,52,52,52,56,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,56,
52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,56,52,52,52,52,52,52,52,52,52,52,
52,52,52,52,52,56,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,56,52,52,52,52,52,52,
52,52,52,52,52,52,52,52,52,56,48,56,52,52,52,52,52,52,52,52,52,52,52,52,52,52,56,52,
52,52,52,52,52,52,52,52,104,104,52,52,56,52,104,104,104,52,52,104,52,52,104,56,52,104,52,52,
52,52,52,52,104,104,52,56,100,108,52,52,104,52,52,52,52,104,104,104,108,104,104,52,52,52,52,52,
52,52,56,48,52,108,104,52,52,52,52,52,52,52,52,52,52,52,52,56,52,52,52,52,52,104,104,52,
52,104,52,56,104,52,52,52,52,104,104,104,104,104,108,52,52,52,52,52,52,52,52,52,52,52,52,52,
52,52,56,52,52,104,104,104,52,52,104,52,52,108,52,52,52,52,104,104,104,52,52,52,52,52,52,108,
748,32


       };     
       const bool FirstTimingIsLow = true;
   #endif   

#endif

#ifdef USE_TEST_TIMINGS
      const int TestTimings_len = sizeof(TestTimings)/sizeof(TestTimings[0]);
#endif

Toyota_PMV_107J

C Header File
#ifdef UK_433MHz


     #define EXPECTEDBITCOUNT 66
     #define EXPECTEDBYTECOUNT 9     

    //these 433MHz timings are guesses and not proven
    
    #define CDWIDTH_MIN 7600
    #define CDWIDTH_MAX 9500
    
    #define SHORTTIMING_MIN 40
    #define SHORTTIMING_MAX 79
    #define LONGTIMING_MIN 80
    #define LONGTIMING_MAX 120
    #define SYNCTIMING_MIN 175
    #define SYNCTIMING_MAX 1200
    
    #define ENDTIMING_MIN  0
    #define ENDTIMING_MAX  0

      
    #define CC1101_DEFVAL_IOCFG2     0x0C        // GDO2 Output Pin Configuration - Serial out (synchronous)
    #define CC1101_DEFVAL_IOCFG1     0x2E        // GDO1 Output Pin Configuration - not used
    #define CC1101_DEFVAL_IOCFG0     0x0E        // GDO0 Output Pin Configuration - Carrier Sense output
    #define CC1101_DEFVAL_FIFOTHR    0x0F        // RX FIFO and TX FIFO Thresholds - 64 bytes in FIFO
    #define CC1101_DEFVAL_SYNC1      0xD5        // Synchronization word, high byte  11010101 01001111
    #define CC1101_DEFVAL_SYNC0      0x4F        // Synchronization word, low byte
    #define CC1101_DEFVAL_PKTLEN     0x09        // Packet Length
    #define CC1101_DEFVAL_PKTCTRL1   0x00        // Packet Automation Control
    #define CC1101_DEFVAL_PKTCTRL0   0x12 //0x30        // Packet Automation Control - synchronous data
    #define CC1101_DEFVAL_ADDR       0x00        // Device Address
    #define CC1101_DEFVAL_CHANNR     0x00        // Channel Number
    #define CC1101_DEFVAL_FSCTRL1    0x0F        // Frequency Synthesizer Control (was 0x06)
    #define CC1101_DEFVAL_FSCTRL0    0x00        // Frequency Synthesizer Control
    
    // Carrier frequency = 433.919830 MHz
    #define CC1101_DEFVAL_FREQ2  0x10        // Frequency Control Word, High Byte
    #define CC1101_DEFVAL_FREQ1  0xB0        // Frequency Control Word, Middle Byte
    #define CC1101_DEFVAL_FREQ0  0x71        // Frequency Control Word, Low Byte

    #define CC1101_DEFVAL_DEVIATN    0x40      // Modem Deviation Setting (+/-25.390625kHz)

    #define CC1101_DEFVAL_MDMCFG4    0x59        // Modem Configuration (59 = data rate = 20kHz - actual data rate is 10kHz but due to bi-phase coding need to double the rate, RX bandwidth 325kHz)
    #define CC1101_DEFVAL_MDMCFG3    0x93        // Modem Configuration (now 93 = data rate = 20kHz)
    #define CC1101_DEFVAL_MDMCFG2    0x10        // Modem Configuration (GFSK, No Sync or Manchester coding)
    #define CC1101_DEFVAL_MDMCFG1    0x21        // Modem Configuration Channel spacing 100kHz
    #define CC1101_DEFVAL_MDMCFG0    0xF8        // Modem Configuration      
    #define CC1101_DEFVAL_AGCCTRL2   0x87       // AGC Control
    #define CC1101_DEFVAL_AGCCTRL1   0x58        // AGC Control
    #define CC1101_DEFVAL_AGCCTRL0   0x80        // AGC Control
    
    #define CC1101_DEFVAL_MCSM2      0x07        // Main Radio Control State Machine Configuration
    #define CC1101_DEFVAL_MCSM1      0x3C        // Main Radio Control State Machine Configuration
    #define CC1101_DEFVAL_MCSM0      0x18        // Main Radio Control State Machine Configuration
    #define CC1101_DEFVAL_FOCCFG     0x16        // Frequency Offset Compensation Configuration
    #define CC1101_DEFVAL_BSCFG      0x6C        // Bit Synchronization Configuration

    
    #define CC1101_DEFVAL_WOREVT1    0x87        // High Byte Event0 Timeout
    #define CC1101_DEFVAL_WOREVT0    0x6B        // Low Byte Event0 Timeout
    #define CC1101_DEFVAL_WORCTRL    0xFB        // Wake On Radio Control
    #define CC1101_DEFVAL_FREND1     0x56        // Front End RX Configuration
    #define CC1101_DEFVAL_FREND0     0x10        // Front End TX Configuration
    
    #define CC1101_DEFVAL_FSCAL3     0xE9        // Frequency Synthesizer Calibration
    #define CC1101_DEFVAL_FSCAL2     0x2A        // Frequency Synthesizer Calibration
    #define CC1101_DEFVAL_FSCAL1     0x00        // Frequency Synthesizer Calibration
    #define CC1101_DEFVAL_FSCAL0     0x1F        // Frequency Synthesizer Calibration
    
    #define CC1101_DEFVAL_RCCTRL1    0x41        // RC Oscillator Configuration
    #define CC1101_DEFVAL_RCCTRL0    0x00        // RC Oscillator Configuration
    
    #define CC1101_DEFVAL_FSTEST     0x59        // Frequency Synthesizer Calibration Control
    
    #define CC1101_DEFVAL_PTEST      0x7F        // Production Test
    #define CC1101_DEFVAL_AGCTEST    0x3F        // AGC Test
    
    #define CC1101_DEFVAL_TEST2      0x81        // Various Test Settings
    #define CC1101_DEFVAL_TEST1      0x35        // Various Test Settings
    #define CC1101_DEFVAL_TEST0      0x09        // Various Test Settings



      
 
#elif US_315MHz


    //these 315MHz timings are guesses and not proven
    

      #define EXPECTEDBITCOUNT 67
      #define EXPECTEDBYTECOUNT 9
          
      #define CDWIDTH_MIN 13500
      #define CDWIDTH_MAX 17500
    
      #define SHORTTIMING_MIN 80
      #define SHORTTIMING_MAX 139
      #define LONGTIMING_MIN 166
      #define LONGTIMING_MAX 250
      #define SYNCTIMING_MIN 350
      #define SYNCTIMING_MAX 1500

      #define ENDTIMING_MIN  140
      #define ENDTIMING_MAX  165


    #define CC1101_DEFVAL_IOCFG2     0x0C        // GDO2 Output Pin Configuration - Serial out (synchronous)
    #define CC1101_DEFVAL_IOCFG1     0x2E        // GDO1 Output Pin Configuration - not used
    #define CC1101_DEFVAL_IOCFG0     0x0E        // GDO0 Output Pin Configuration - Carrier Sense output
    #define CC1101_DEFVAL_FIFOTHR    0x0F        // RX FIFO and TX FIFO Thresholds - 64 bytes in FIFO
    #define CC1101_DEFVAL_SYNC1      0xD5        // Synchronization word, high byte  11010101 01001111
    #define CC1101_DEFVAL_SYNC0      0x4F        // Synchronization word, low byte
    #define CC1101_DEFVAL_PKTLEN     0x09        // Packet Length
    #define CC1101_DEFVAL_PKTCTRL1   0x00        // Packet Automation Control
    #define CC1101_DEFVAL_PKTCTRL0   0x12 //0x30        // Packet Automation Control - synchronous data
    #define CC1101_DEFVAL_ADDR       0x00        // Device Address
    #define CC1101_DEFVAL_CHANNR     0x00        // Channel Number
    #define CC1101_DEFVAL_FSCTRL1    0x0F        // Frequency Synthesizer Control (was 0x06)
    #define CC1101_DEFVAL_FSCTRL0    0x00        // Frequency Synthesizer Control
    
    // Carrier frequency = 314.979828 MHz
    #define CC1101_DEFVAL_FREQ2  0x0C        // Frequency Control Word, High Byte
    #define CC1101_DEFVAL_FREQ1  0x1D        // Frequency Control Word, Middle Byte
    #define CC1101_DEFVAL_FREQ0  0x57        // Frequency Control Word, Low Byte
      
    #define CC1101_DEFVAL_DEVIATN    0x40      // Modem Deviation Setting (+/-25.390625kHz)

    #define CC1101_DEFVAL_MDMCFG4    0x59        // Modem Configuration (59 = data rate = 20kHz - actual data rate is 10kHz but due to bi-phase coding need to double the rate, RX bandwidth 101.562500kHz)
    #define CC1101_DEFVAL_MDMCFG3    0x93        // Modem Configuration (now 93 = data rate = 20kHz)
    #define CC1101_DEFVAL_MDMCFG2    0x10        // Modem Configuration (GFSK, No Sync or Manchester coding)
    #define CC1101_DEFVAL_MDMCFG1    0x21        // Modem Configuration Channel spacing 100kHz
    #define CC1101_DEFVAL_MDMCFG0    0xF8        // Modem Configuration      
    #define CC1101_DEFVAL_AGCCTRL2   0x87       // AGC Control
    #define CC1101_DEFVAL_AGCCTRL1   0x58        // AGC Control
    #define CC1101_DEFVAL_AGCCTRL0   0x80        // AGC Control
    
    #define CC1101_DEFVAL_MCSM2      0x07        // Main Radio Control State Machine Configuration
    #define CC1101_DEFVAL_MCSM1      0x3C        // Main Radio Control State Machine Configuration
    #define CC1101_DEFVAL_MCSM0      0x18        // Main Radio Control State Machine Configuration
    #define CC1101_DEFVAL_FOCCFG     0x16        // Frequency Offset Compensation Configuration
    #define CC1101_DEFVAL_BSCFG      0x6C        // Bit Synchronization Configuration

    
    #define CC1101_DEFVAL_WOREVT1    0x87        // High Byte Event0 Timeout
    #define CC1101_DEFVAL_WOREVT0    0x6B        // Low Byte Event0 Timeout
    #define CC1101_DEFVAL_WORCTRL    0xFB        // Wake On Radio Control
    #define CC1101_DEFVAL_FREND1     0x56        // Front End RX Configuration
    #define CC1101_DEFVAL_FREND0     0x10        // Front End TX Configuration
    
    #define CC1101_DEFVAL_FSCAL3     0xE9        // Frequency Synthesizer Calibration
    #define CC1101_DEFVAL_FSCAL2     0x2A        // Frequency Synthesizer Calibration
    #define CC1101_DEFVAL_FSCAL1     0x00        // Frequency Synthesizer Calibration
    #define CC1101_DEFVAL_FSCAL0     0x1F        // Frequency Synthesizer Calibration
    
    #define CC1101_DEFVAL_RCCTRL1    0x41        // RC Oscillator Configuration
    #define CC1101_DEFVAL_RCCTRL0    0x00        // RC Oscillator Configuration
    
    #define CC1101_DEFVAL_FSTEST     0x59        // Frequency Synthesizer Calibration Control
    
    #define CC1101_DEFVAL_PTEST      0x7F        // Production Test
    #define CC1101_DEFVAL_AGCTEST    0x3F        // AGC Test
    
    #define CC1101_DEFVAL_TEST2      0x81        // Various Test Settings
    #define CC1101_DEFVAL_TEST1      0x35        // Various Test Settings
    #define CC1101_DEFVAL_TEST0      0x09        // Various Test Settings


#endif



void DecodeTPMS()
{
  int i;
  unsigned long id = 0;
  unsigned int status, pressure1, pressure2, temp, battery_low, counter, failed;
   double realpressure;
  float realtemp;
  bool IDFound = false;

  


  //note: incoming bit stream has been shifted right by 6 bits in DecodeBitArray to give integral number of bytes (for checksum)

  id = (unsigned long)(RXBytes[0]) << 26| (unsigned long)(RXBytes[1]) << 18 | (unsigned long)(RXBytes[2]) << 10 | (unsigned long)(RXBytes[3]) << 2 | (unsigned long)(RXBytes[4]) >> 6; 
  id = id & 0xFFFFFFF;

  GetPreferredIndexStr(id, Ref);
 
  status = RXBytes[4] & 0x3f; // status bits and 0 filler

  battery_low = (RXBytes[4] & 0x20) >> 5;
  counter = (RXBytes[4] & 0x18) >> 3;
  failed = RXBytes[4] & 0x01;

  pressure1 = RXBytes[5];
  pressure2 = RXBytes[6] ^ 0xff;
  temp = RXBytes[7];
  




  if (pressure1 != pressure2)
  {
    Serial.println(F("Pressure check mis-match"));
    return;
  }

  realpressure = (pressure1 - 40) * 0.363 - .735;  //default to psi, kpa would be (pressure1 - 40.0) * 2.48
  if (realpressure < 0.0)
    realpressure = 0.0;
  realtemp = temp - 40.0;
//  #ifdef DISPLAY_TEMP_AS_FAHRENHEIT
//     realtemp = ((realtemp * 9.0)/5.0) + 32.0;
//  #endif

#ifdef SHOWVALIDTPMS
  Serial.print(F("Pos: "));
  Serial.print(Ref);
  Serial.print(F("   ID: "));
  Serial.print(id, HEX);
  Serial.print(F("   Status: 0x"));
  Serial.print(status,HEX);
  Serial.print(F(" [Battery status: "));
  Serial.print(battery_low);
  Serial.print(F("   Counter: "));
  Serial.print(counter);
  Serial.print(F("   Failed status: "));
  Serial.print(failed);  
  Serial.print(F("]   Temperature: "));
  Serial.print(realtemp);
  Serial.print(F("   Tyre Pressure: "));
  Serial.print(realpressure);
  Serial.print(F(" (psi)  "));
  Serial.print(realpressure/PSI2BAR);
  Serial.print(F(" (bar)"));
  Serial.println(F(""));
#endif

  //DisplayStatusInfo();


  MatchIDandUpdate(id,status, realtemp, realpressure);



  #ifdef SHOWVALIDTPMS
     Serial.println(F(""));
  #endif


  //UpdateDisplay();
}




bool ValidateTimings()
{


  unsigned int BitWidth;
  unsigned int BitWidthNext;
  unsigned int BitWidthNextPlus1;
  unsigned int BitWidthPrevious;
  unsigned int diff = TimingsIndex - CheckIndex;
  //unsigned long tmp;
  bool WaitingTrailingZeroEdge = false;
  int ret;
  byte SyncCount;
  int ByteCount = 0;
  byte crcResult = 0;
  bool TailFound = false;
  int Index;

  StartDataIndex = 0;

  if (diff < EXPECTEDBITCOUNT)
  { //not enough in the buffer to consider a valid message
    #ifdef SHOWDEBUGINFO
      Serial.print(F("Insufficient data in buffer ("));
      Serial.print(diff);
      Serial.println(F(")"));
    #endif
    return(false);
  }


  //start from back of buffer and find first 'stop' marker (~150) which also has a valid data bit just before it
  for (Index = TimingsIndex-1; Index >= 0; Index--)
  {
     BitWidth = Timings[Index];
     BitWidthPrevious = Timings[Index-1];
     if (IsEndMarker(BitWidth) && (IsValidLong(BitWidthPrevious) || IsValidShort(BitWidthPrevious)))
     {
        TailFound = true;
        Index--;
        break;
     }
    
  }



  if (TailFound == false)
  {
    #ifdef SHOWDEBUGINFO
      Serial.println(F("No valid bits found in data input"));
    #endif
    return(false);    
  }


  BitIndex = EXPECTEDBITCOUNT -1;
  BitCount = 0;
   
  while ((Index > 0) && (BitCount < EXPECTEDBITCOUNT))
  { //something in buffer to process...
    StartDataIndex = Index;
    ret = ValidateBit(Index);
    switch (ret)
    {
        case BITISUNDEFINED:
          //invalid bit
          return(false);
          break;

        case BITISSHORT:
          if (WaitingTrailingZeroEdge)
          {
            //BitTimings[BitIndex] = BitWidth;
            IncomingBits[BitIndex--] = 0;
            BitCount++;
            WaitingTrailingZeroEdge = false;
          }
          else
          {
            WaitingTrailingZeroEdge = true;
          }
          break;

        case BITISLONG:
          if (WaitingTrailingZeroEdge)
          { //shouldn't get a long pulse when waiting for the second short pulse (i.e. expecting bit = 0)
            //try to resync from here?
            return(false);
          }
          else
          {
            //BitTimings[BitIndex] = BitWidth;
            IncomingBits[BitIndex--] = 1;
            BitCount++;
          }
          break;

        case 2:
          return(false);
          break;
      }
    
    Index--;
  }


  if (BitCount == EXPECTEDBITCOUNT)
  {

      ByteCount = DecodeBitArray(6);

      crcResult = Compute_CRC8(8,0x13, 0x00);

      if (crcResult != RXBytes[8])
      {
         #ifdef SHOWDEBUGINFO
          Serial.print(F("CRC calc: "));
          Serial.println(crcResult, HEX);
          Serial.print(F("  CRC rcvd: "));
          Serial.println(RXBytes[8], HEX);
          Serial.println(F("CRC Check failed"));
        #endif
        //PrintData(BitCount);
        #ifdef IGNORECHECKSUMERRORS
          DecodeTPMS();
          TPMS_Changed = true;  //indicates the display needs to be updated.
        #endif
        return(false);
      }
      else
      {
        //decode the message...
        Serial.println(F("CRC Check OK"));
        DecodeTPMS();
        TPMS_Changed = true;  //indicates the display needs to be updated.
        return(true);
      }


  }
  else
  {
    return(false);
  }

  
}
  

bool ValidateTimings_Old()
{


  unsigned int BitWidth;
  unsigned int BitWidthNext;
  unsigned int BitWidthNextPlus1;
  unsigned int BitWidthPrevious;
  unsigned int diff = TimingsIndex - CheckIndex;
  //unsigned long tmp;
  bool WaitingTrailingZeroEdge = false;
  int ret;
  byte SyncCount;
  int ByteCount = 0;
  byte crcResult = 0;

  StartDataIndex = 0;

  if (diff < EXPECTEDBITCOUNT)
  { //not enough in the buffer to consider a valid message
    #ifdef SHOWDEBUGINFO
      Serial.print(F("Insufficient data in buffer ("));
      Serial.print(diff);
      Serial.println(F(")"));
    #endif
    return(false);
  }

  SyncFound = false;
  SyncCount = 0;

  while ((diff > 0) && (BitCount < EXPECTEDBITCOUNT))
  { //something in buffer to process...
    diff = TimingsIndex - CheckIndex;

    BitWidth = Timings[CheckIndex];

    if (SyncFound == false)
    {
      switch (SyncCount)
      {
        case 0:
          if (IsValidSync(BitWidth))
          {
            //SyncFound = true;
            SyncCount++;
            StartDataIndex = CheckIndex + 1;
          }
        case 1:
          if (IsValidSync(BitWidth))
          {//second sync bit, so stay in this state
            StartDataIndex = CheckIndex + 1;
          }
          else
          {
            if (IsValidLong(BitWidth))
            {//valid final sync bit
              SyncFound = true;
              BitIndex = 0;
              BitCount = 0;
              WaitingTrailingZeroEdge = false;
              StartDataIndex = CheckIndex + 1;
            }
            else
            {//invalid bit so go back to look for initial sync bit again
              SyncCount= 0;
              StartDataIndex = CheckIndex + 1;                         
            }
          }
        
      }

    }
    else
    {
      ret = ValidateBit();
      switch (ret)
      {
        case -1:
          //invalid bit
//          BitIndex = 0;
//          BitCount = 0;
//          WaitingTrailingZeroEdge = false;
//          StartDataIndex = CheckIndex + 1;
          SyncFound = false;
          SyncCount = 0;
          break;

        case 0:
          if (WaitingTrailingZeroEdge)
          {
            //BitTimings[BitIndex] = BitWidth;
            IncomingBits[BitIndex++] = 0;
            BitCount++;
            WaitingTrailingZeroEdge = false;
          }
          else
          {
            WaitingTrailingZeroEdge = true;
          }
          break;

        case 1:
          if (WaitingTrailingZeroEdge)
          { //shouldn't get a long pulse when waiting for the second short pulse (i.e. expecting bit = 0)
            //try to resync from here?
            BitIndex = 0;
            BitCount = 0;
            WaitingTrailingZeroEdge = false;
            CheckIndex--;  //recheck this entry
            //StartDataIndex = CheckIndex + 1;
            StartDataIndex = CheckIndex;
            SyncFound = false;
            SyncCount = 0;
          }
          else
          {
            //BitTimings[BitIndex] = BitWidth;
            IncomingBits[BitIndex++] = 1;
            BitCount++;
          }
          break;

        case 2:
          SyncFound = false;
          SyncCount = 0;
          CheckIndex--;  //recheck this entry
          BitIndex = 0;
          BitCount = 0;
          WaitingTrailingZeroEdge = false;
          StartDataIndex = CheckIndex;
          break;
      }
    }
    CheckIndex++;
  }


  if (BitCount >= EXPECTEDBITCOUNT)
  {

      ByteCount = DecodeBitArray(6);

      crcResult = Compute_CRC8(8,0x13, 0x00);

      if (crcResult != RXBytes[8])
      {
         #ifdef SHOWDEBUGINFO
          Serial.print(F("CRC calc: "));
          Serial.println(crcResult, HEX);
          Serial.print(F("  CRC rcvd: "));
          Serial.println(RXBytes[8], HEX);
          Serial.println(F("CRC Check failed"));
        #endif
        //PrintData(BitCount);
        #ifdef IGNORECHECKSUMERRORS
          DecodeTPMS();
          TPMS_Changed = false;  //don't update display for csum error
        #endif
      }
      else
      {
        //decode the message...
        Serial.println(F("CRC Check OK"));
        DecodeTPMS();
        TPMS_Changed = true;  //indicates the display needs to be updated.
      }

    
      return(true);
  }
  else
  {
    return(false);
  }
  
}

Toyota_PMV_C210

C Header File
#ifdef UK_433MHz


    #define EXPECTEDBITCOUNT 72
    #define EXPECTEDBYTECOUNT 9
    #define SYNCBITS 11
  
    #define CDWIDTH_MIN 7000
    #define CDWIDTH_MAX 10500
  
    #define SHORTTIMING_MIN 40
    #define SHORTTIMING_NOM 50
    #define SHORTTIMING_MAX 79
    #define LONGTIMING_MIN 80
    #define LONGTIMING_MAX 120
    #define SYNCTIMING_MIN 175
    #define SYNCTIMING_MAX 1200
  
    #define ENDTIMING_MIN  0
    #define ENDTIMING_MAX  0


    #define CC1101_DEFVAL_IOCFG2     0x0C        // GDO2 Output Pin Configuration - Serial out (synchronous)
    #define CC1101_DEFVAL_IOCFG1     0x2E        // GDO1 Output Pin Configuration - not used
    #define CC1101_DEFVAL_IOCFG0     0x0E        // GDO0 Output Pin Configuration - Carrier Sense output
    #define CC1101_DEFVAL_FIFOTHR    0x0F        // RX FIFO and TX FIFO Thresholds - 64 bytes in FIFO
    #define CC1101_DEFVAL_SYNC1      0xD5        // Synchronization word, high byte  11010101 01001111
    #define CC1101_DEFVAL_SYNC0      0x4F        // Synchronization word, low byte
    #define CC1101_DEFVAL_PKTLEN     0x09        // Packet Length
    #define CC1101_DEFVAL_PKTCTRL1   0x00        // Packet Automation Control
    #define CC1101_DEFVAL_PKTCTRL0   0x12 //0x30        // Packet Automation Control - synchronous data
    #define CC1101_DEFVAL_ADDR       0x00        // Device Address
    #define CC1101_DEFVAL_CHANNR     0x00        // Channel Number
    #define CC1101_DEFVAL_FSCTRL1    0x0F        // Frequency Synthesizer Control (was 0x06)
    #define CC1101_DEFVAL_FSCTRL0    0x00        // Frequency Synthesizer Control
    
    // Carrier frequency = 433.919830 MHz
    #define CC1101_DEFVAL_FREQ2  0x10        // Frequency Control Word, High Byte
    #define CC1101_DEFVAL_FREQ1  0xB0        // Frequency Control Word, Middle Byte
    #define CC1101_DEFVAL_FREQ0  0x71        // Frequency Control Word, Low Byte

    #define CC1101_DEFVAL_DEVIATN    0x40      // Modem Deviation Setting (+/-25.390625kHz)

    #define CC1101_DEFVAL_MDMCFG4    0x59        // Modem Configuration (59 = data rate = 20kHz - actual data rate is 10kHz but due to bi-phase coding need to double the rate, RX bandwidth 325kHz)
    #define CC1101_DEFVAL_MDMCFG3    0x93        // Modem Configuration (now 93 = data rate = 20kHz)
    #define CC1101_DEFVAL_MDMCFG2    0x10        // Modem Configuration (GFSK, No Sync or Manchester coding)
    #define CC1101_DEFVAL_MDMCFG1    0x21        // Modem Configuration Channel spacing 100kHz
    #define CC1101_DEFVAL_MDMCFG0    0xF8        // Modem Configuration      
    #define CC1101_DEFVAL_AGCCTRL2   0x87       // AGC Control
    #define CC1101_DEFVAL_AGCCTRL1   0x58        // AGC Control
    #define CC1101_DEFVAL_AGCCTRL0   0x80        // AGC Control
    
    #define CC1101_DEFVAL_MCSM2      0x07        // Main Radio Control State Machine Configuration
    #define CC1101_DEFVAL_MCSM1      0x3C        // Main Radio Control State Machine Configuration
    #define CC1101_DEFVAL_MCSM0      0x18        // Main Radio Control State Machine Configuration
    #define CC1101_DEFVAL_FOCCFG     0x16        // Frequency Offset Compensation Configuration
    #define CC1101_DEFVAL_BSCFG      0x6C        // Bit Synchronization Configuration

    
    #define CC1101_DEFVAL_WOREVT1    0x87        // High Byte Event0 Timeout
    #define CC1101_DEFVAL_WOREVT0    0x6B        // Low Byte Event0 Timeout
    #define CC1101_DEFVAL_WORCTRL    0xFB        // Wake On Radio Control
    #define CC1101_DEFVAL_FREND1     0x56        // Front End RX Configuration
    #define CC1101_DEFVAL_FREND0     0x10        // Front End TX Configuration
    
    #define CC1101_DEFVAL_FSCAL3     0xE9        // Frequency Synthesizer Calibration
    #define CC1101_DEFVAL_FSCAL2     0x2A        // Frequency Synthesizer Calibration
    #define CC1101_DEFVAL_FSCAL1     0x00        // Frequency Synthesizer Calibration
    #define CC1101_DEFVAL_FSCAL0     0x1F        // Frequency Synthesizer Calibration
    
    #define CC1101_DEFVAL_RCCTRL1    0x41        // RC Oscillator Configuration
    #define CC1101_DEFVAL_RCCTRL0    0x00        // RC Oscillator Configuration
    
    #define CC1101_DEFVAL_FSTEST     0x59        // Frequency Synthesizer Calibration Control
    
    #define CC1101_DEFVAL_PTEST      0x7F        // Production Test
    #define CC1101_DEFVAL_AGCTEST    0x3F        // AGC Test
    
    #define CC1101_DEFVAL_TEST2      0x81        // Various Test Settings
    #define CC1101_DEFVAL_TEST1      0x35        // Various Test Settings
    #define CC1101_DEFVAL_TEST0      0x09        // Various Test Settings



      
 
#elif US_315MHz


    //these 315MHz timings are guesses and not proven
    
    #define EXPECTEDBITCOUNT 72
    #define EXPECTEDBYTECOUNT 9
    #define SYNCBITS 11
    
    #define CDWIDTH_MIN 7000
    #define CDWIDTH_MAX 10500
    
    #define SHORTTIMING_MIN 40
    #define SHORTTIMING_NOM 50
    #define SHORTTIMING_MAX 79
    #define LONGTIMING_MIN 80
    #define LONGTIMING_MAX 120
    #define SYNCTIMING_MIN 175
    #define SYNCTIMING_MAX 1200
    
    #define ENDTIMING_MIN  0
    #define ENDTIMING_MAX  0


    #define CC1101_DEFVAL_IOCFG2     0x0C        // GDO2 Output Pin Configuration - Serial out (synchronous)
    #define CC1101_DEFVAL_IOCFG1     0x2E        // GDO1 Output Pin Configuration - not used
    #define CC1101_DEFVAL_IOCFG0     0x0E        // GDO0 Output Pin Configuration - Carrier Sense output
    #define CC1101_DEFVAL_FIFOTHR    0x0F        // RX FIFO and TX FIFO Thresholds - 64 bytes in FIFO
    #define CC1101_DEFVAL_SYNC1      0xD5        // Synchronization word, high byte  11010101 01001111
    #define CC1101_DEFVAL_SYNC0      0x4F        // Synchronization word, low byte
    #define CC1101_DEFVAL_PKTLEN     0x09        // Packet Length
    #define CC1101_DEFVAL_PKTCTRL1   0x00        // Packet Automation Control
    #define CC1101_DEFVAL_PKTCTRL0   0x12 //0x30        // Packet Automation Control - synchronous data
    #define CC1101_DEFVAL_ADDR       0x00        // Device Address
    #define CC1101_DEFVAL_CHANNR     0x00        // Channel Number
    #define CC1101_DEFVAL_FSCTRL1    0x0F        // Frequency Synthesizer Control (was 0x06)
    #define CC1101_DEFVAL_FSCTRL0    0x00        // Frequency Synthesizer Control
    
    // Carrier frequency = 314.979828 MHz
    #define CC1101_DEFVAL_FREQ2  0x0C        // Frequency Control Word, High Byte
    #define CC1101_DEFVAL_FREQ1  0x1D        // Frequency Control Word, Middle Byte
    #define CC1101_DEFVAL_FREQ0  0x57        // Frequency Control Word, Low Byte
      
    #define CC1101_DEFVAL_DEVIATN    0x40      // Modem Deviation Setting (+/-25.390625kHz)

    #define CC1101_DEFVAL_MDMCFG4    0x59        // Modem Configuration (59 = data rate = 20kHz - actual data rate is 10kHz but due to bi-phase coding need to double the rate, RX bandwidth 101.562500kHz)
    #define CC1101_DEFVAL_MDMCFG3    0x93        // Modem Configuration (now 93 = data rate = 20kHz)
    #define CC1101_DEFVAL_MDMCFG2    0x10        // Modem Configuration (GFSK, No Sync or Manchester coding)
    #define CC1101_DEFVAL_MDMCFG1    0x21        // Modem Configuration Channel spacing 100kHz
    #define CC1101_DEFVAL_MDMCFG0    0xF8        // Modem Configuration      
    #define CC1101_DEFVAL_AGCCTRL2   0x87       // AGC Control
    #define CC1101_DEFVAL_AGCCTRL1   0x58        // AGC Control
    #define CC1101_DEFVAL_AGCCTRL0   0x80        // AGC Control
    
    #define CC1101_DEFVAL_MCSM2      0x07        // Main Radio Control State Machine Configuration
    #define CC1101_DEFVAL_MCSM1      0x3C        // Main Radio Control State Machine Configuration
    #define CC1101_DEFVAL_MCSM0      0x18        // Main Radio Control State Machine Configuration
    #define CC1101_DEFVAL_FOCCFG     0x16        // Frequency Offset Compensation Configuration
    #define CC1101_DEFVAL_BSCFG      0x6C        // Bit Synchronization Configuration

    
    #define CC1101_DEFVAL_WOREVT1    0x87        // High Byte Event0 Timeout
    #define CC1101_DEFVAL_WOREVT0    0x6B        // Low Byte Event0 Timeout
    #define CC1101_DEFVAL_WORCTRL    0xFB        // Wake On Radio Control
    #define CC1101_DEFVAL_FREND1     0x56        // Front End RX Configuration
    #define CC1101_DEFVAL_FREND0     0x10        // Front End TX Configuration
    
    #define CC1101_DEFVAL_FSCAL3     0xE9        // Frequency Synthesizer Calibration
    #define CC1101_DEFVAL_FSCAL2     0x2A        // Frequency Synthesizer Calibration
    #define CC1101_DEFVAL_FSCAL1     0x00        // Frequency Synthesizer Calibration
    #define CC1101_DEFVAL_FSCAL0     0x1F        // Frequency Synthesizer Calibration
    
    #define CC1101_DEFVAL_RCCTRL1    0x41        // RC Oscillator Configuration
    #define CC1101_DEFVAL_RCCTRL0    0x00        // RC Oscillator Configuration
    
    #define CC1101_DEFVAL_FSTEST     0x59        // Frequency Synthesizer Calibration Control
    
    #define CC1101_DEFVAL_PTEST      0x7F        // Production Test
    #define CC1101_DEFVAL_AGCTEST    0x3F        // AGC Test
    
    #define CC1101_DEFVAL_TEST2      0x81        // Various Test Settings
    #define CC1101_DEFVAL_TEST1      0x35        // Various Test Settings
    #define CC1101_DEFVAL_TEST0      0x09        // Various Test Settings


#endif

void DecodeTPMS()
{
  int i;
  unsigned long id = 0;
  unsigned int status, pressure1, pressure2, temp;
   double realpressure;
  float realtemp;
  bool IDFound = false;


  for (i = 0; i < 4; i++)
  {
    id = id << 8;
    id = id + RXBytes[i];

  }

  id = id & 0xFFFFFFF;

  GetPreferredIndexStr(id, Ref);

  // id = (unsigned)RXBytes[0] << 24 | RXBytes[1] << 16 | RXBytes[2] << 8 | RXBytes[3];

  status = (RXBytes[4] & 0x80) | (RXBytes[6] & 0x7f); // status bit and 0 filler

  pressure1 = (RXBytes[4] & 0x7f) << 1 | RXBytes[5] >> 7;

  temp = (RXBytes[5] & 0x7f) << 1 | RXBytes[6] >> 7;

  pressure2 = RXBytes[7] ^ 0xff;



  if (pressure1 != pressure2)
  {
    Serial.println(F("Pressure check mis-match"));
    return;
  }

  realpressure = pressure1 * 0.25 - 7.35;
  if (realpressure < 0) 
     realpressure = 0.0;
  realtemp = temp - 40.0;
//#ifdef DISPLAY_TEMP_AS_FAHRENHEIT
//  realtemp = ((realtemp * 9.0)/5.0) + 32.0;
//#endif


#ifdef SHOWVALIDTPMS
  Serial.print(F("Pos: "));
  Serial.print(Ref);
  Serial.print(F("   ID: "));
  Serial.print(id, HEX);
  Serial.print(F("   Status: 0x"));
  Serial.print(status,HEX);
  Serial.print(F("   Temperature: "));
  Serial.print(realtemp);
  Serial.print(F("   Tyre Pressure: "));
  Serial.print(realpressure);
  Serial.print(F(" (psi)  "));
  Serial.print(realpressure/PSI2BAR);
  Serial.print(F(" (bar)"));
  Serial.println(F(""));
#endif

  //DisplayStatusInfo();

  MatchIDandUpdate(id,status, realtemp, realpressure);

//  //update the array of tyres data
//  for (i = 0; i < TYRECOUNT; i++)
//  { //find a matching ID if it already exists
//    if (id == TPMS[i].TPMS_ID)
//    {
//      UpdateTPMSData(i, id, status, realtemp, realpressure);
//      IDFound = true;
//      break;
//    }
//
//  }
//
//  //no matching IDs in the array, so see if there is an empty slot to add it into, otherwise, ignore it.
//  if (IDFound == false)
//  {
//
//    prefindex = GetPreferredIndex(id);
//    if (prefindex == -1)
//    { //not found a specified index, so use the next available one..
//      #ifndef SPECIFIC_IDS_ONLY 
//        for (i = 0; i < TYRECOUNT; i++)
//        {
//          if (TPMS[i].TPMS_ID == 0)
//          {
//            UpdateTPMSData(i, id, status, realtemp, realpressure);
//            break;
//          }
//        }
//      #endif
//    }
//    else
//    { //found a match in the known ID list...
//      UpdateTPMSData(prefindex, id, status, realtemp, realpressure);
//    }
//
//  }


  #ifdef SHOWVALIDTPMS
     Serial.println(F(""));
  #endif


  //UpdateDisplay();
}








bool ValidateTimings()
{


  unsigned int BitWidth;
  unsigned int BitWidthNext;
  unsigned int BitWidthNextPlus1;
  unsigned int BitWidthPrevious;
  unsigned int diff = TimingsIndex - CheckIndex;
  //unsigned long tmp;
  bool WaitingTrailingZeroEdge = false;
  int ret;
  int ByteCount = 0;
  byte crcResult = 0;

  StartDataIndex = 0;

  if (diff < EXPECTEDBITCOUNT)
  { //not enough in the buffer to consider a valid message
    #ifdef SHOWDEBUGINFO
      Serial.print(F("Insufficient data in buffer ("));
      Serial.print(diff);
      Serial.println(F(")"));
    #endif
    return(false);
  }

  SyncFound = false;

  while ((diff > 0) && (BitCount < EXPECTEDBITCOUNT))
  { //something in buffer to process...
    diff = TimingsIndex - CheckIndex;

    BitWidth = Timings[CheckIndex];

    if (SyncFound == false)
    {
      if (IsValidSync(BitWidth))
      {
        SyncFound = true;
        BitIndex = 0;
        BitCount = 0;
        WaitingTrailingZeroEdge = false;
        StartDataIndex = CheckIndex + 1;
      }

    }
    else
    {
      ret = ValidateBit();
      switch (ret)
      {
        case -1:
          //invalid bit
//          BitIndex = 0;
//          BitCount = 0;
//          WaitingTrailingZeroEdge = false;
//          StartDataIndex = CheckIndex + 1;
          SyncFound = false;
          break;

        case 0:
          if (WaitingTrailingZeroEdge)
          {
            //BitTimings[BitIndex] = BitWidth;
            IncomingBits[BitIndex++] = 0;
            BitCount++;
            WaitingTrailingZeroEdge = false;
          }
          else
          {
            WaitingTrailingZeroEdge = true;
          }
          break;

        case 1:
          if (WaitingTrailingZeroEdge)
          { //shouldn't get a long pulse when waiting for the second short pulse (i.e. expecting bit = 0)
            //try to resync from here?
            BitIndex = 0;
            BitCount = 0;
            WaitingTrailingZeroEdge = false;
            CheckIndex--;  //recheck this entry
            StartDataIndex = CheckIndex + 1;
            SyncFound = false;
          }
          else
          {
            //BitTimings[BitIndex] = BitWidth;
            IncomingBits[BitIndex++] = 1;
            BitCount++;
          }
          break;

        case 2:
          if ((SyncFound == true) && (BitCount > 50))
          {
             return(false);
          }
          else
          {
            SyncFound = true;
            BitIndex = 0;
            BitCount = 0;
            WaitingTrailingZeroEdge = false;
            StartDataIndex = CheckIndex + 1;
            break;
          }
      }
    }
    CheckIndex++;
  }


  if (BitCount >= EXPECTEDBITCOUNT)
  {

      ByteCount = DecodeBitArray(0);

      crcResult = Compute_CRC8(8,0x7, 0x80);

      if (crcResult != RXBytes[8])
      {
        #ifdef SHOWDEBUGINFO
          Serial.print(F("CRC calc: "));
          Serial.println(crcResult, HEX);
          Serial.print(F("  CRC rcvd: "));
          Serial.println(RXBytes[8], HEX);
          Serial.println(F("CRC Check failed"));
        #endif
        #ifdef IGNORECHECKSUMERRORS
          DecodeTPMS();
          TPMS_Changed = false;  //don't update display for csum error
        #endif
        //PrintData(BitCount);
        return(false);
      }
      else
      {
        //decode the message...
        
        #ifdef SHOWDEBUGINFO
           Serial.println(F("CRC Check OK"));
        #endif
        DecodeTPMS();
        TPMS_Changed = true;  //indicates the display needs to be updated.
        return(true);
        
      }
    
    

  }
  else
  {
    return(false);
  }
  
}

Renault

C Header File
#ifdef UK_433MHz



  #ifndef Zoe
    #define EXPECTEDBITCOUNT 72
    #define EXPECTEDBYTECOUNT 9
    
    #define SYNCBITS 16
    
    #define CDWIDTH_MIN 8500
    #define CDWIDTH_MAX 11500
    
    #define SHORTTIMING_MIN 35
    #define SHORTTIMING_MAX 79
    #define LONGTIMING_MIN 80
    #define LONGTIMING_MAX 120
    #define SYNCTIMING_MIN 175
    #define SYNCTIMING_MAX 1200
    
    #define ENDTIMING_MIN  0
    #define ENDTIMING_MAX  0


    #define CC1101_DEFVAL_IOCFG2     0x0C        // GDO2 Output Pin Configuration - Serial out (synchronous)
    #define CC1101_DEFVAL_IOCFG1     0x2E        // GDO1 Output Pin Configuration - not used
    //#define CC1101_DEFVAL_IOCFG0     0x0D        // GDO0 Output Pin Configuration
    #define CC1101_DEFVAL_IOCFG0     0x0E        // GDO0 Output Pin Configuration - Carrier Sense output
    #define CC1101_DEFVAL_FIFOTHR    0x0F        // RX FIFO and TX FIFO Thresholds - 64 bytes in FIFO
    #define CC1101_DEFVAL_SYNC1      0xD5        // Synchronization word, high byte  11010101 01001111
    #define CC1101_DEFVAL_SYNC0      0x4F        // Synchronization word, low byte
    #define CC1101_DEFVAL_PKTLEN     0x09        // Packet Length
    #define CC1101_DEFVAL_PKTCTRL1   0x00        // Packet Automation Control
    #define CC1101_DEFVAL_PKTCTRL0   0x12 //0x30        // Packet Automation Control - synchronous data
    #define CC1101_DEFVAL_ADDR       0x00        // Device Address
    #define CC1101_DEFVAL_CHANNR     0x00        // Channel Number
    #define CC1101_DEFVAL_FSCTRL1    0x0F        // Frequency Synthesizer Control (was 0x06)
    #define CC1101_DEFVAL_FSCTRL0    0x00        // Frequency Synthesizer Control
    
    // Carrier frequency = 433.919830 MHz
    #define CC1101_DEFVAL_FREQ2  0x10        // Frequency Control Word, High Byte
    #define CC1101_DEFVAL_FREQ1  0xB0        // Frequency Control Word, Middle Byte
    #define CC1101_DEFVAL_FREQ0  0x0C        // Frequency Control Word, Low Byte

    #define CC1101_DEFVAL_DEVIATN    0x41      // Modem Deviation Setting 

    #define CC1101_DEFVAL_MDMCFG4    0x59        // Modem Configuration (59 = data rate = 20kHz - actual data rate is 10kHz but due to bi-phase coding need to double the rate, RX bandwidth 325kHz)
    #define CC1101_DEFVAL_MDMCFG3    0x93        // Modem Configuration (now 93 = data rate = 20kHz)
    #define CC1101_DEFVAL_MDMCFG2    0x10        // Modem Configuration (GFSK, No Sync or Manchester coding)
    #define CC1101_DEFVAL_MDMCFG1    0x21        // Modem Configuration Channel spacing 100kHz
    #define CC1101_DEFVAL_MDMCFG0    0xF8        // Modem Configuration      
    #define CC1101_DEFVAL_AGCCTRL2   0x87       // AGC Control
    #define CC1101_DEFVAL_AGCCTRL1   0x58        // AGC Control
    #define CC1101_DEFVAL_AGCCTRL0   0x80        // AGC Control
    
    #define CC1101_DEFVAL_MCSM2      0x07        // Main Radio Control State Machine Configuration
    #define CC1101_DEFVAL_MCSM1      0x3C        // Main Radio Control State Machine Configuration
    #define CC1101_DEFVAL_MCSM0      0x18        // Main Radio Control State Machine Configuration
    #define CC1101_DEFVAL_FOCCFG     0x16        // Frequency Offset Compensation Configuration
    #define CC1101_DEFVAL_BSCFG      0x6C        // Bit Synchronization Configuration

    
    #define CC1101_DEFVAL_WOREVT1    0x87        // High Byte Event0 Timeout
    #define CC1101_DEFVAL_WOREVT0    0x6B        // Low Byte Event0 Timeout
    #define CC1101_DEFVAL_WORCTRL    0xFB        // Wake On Radio Control
    #define CC1101_DEFVAL_FREND1     0x56        // Front End RX Configuration
    #define CC1101_DEFVAL_FREND0     0x10        // Front End TX Configuration
    
    #define CC1101_DEFVAL_FSCAL3     0xE9        // Frequency Synthesizer Calibration
    #define CC1101_DEFVAL_FSCAL2     0x2A        // Frequency Synthesizer Calibration
    #define CC1101_DEFVAL_FSCAL1     0x00        // Frequency Synthesizer Calibration
    #define CC1101_DEFVAL_FSCAL0     0x1F        // Frequency Synthesizer Calibration
    
    #define CC1101_DEFVAL_RCCTRL1    0x41        // RC Oscillator Configuration
    #define CC1101_DEFVAL_RCCTRL0    0x00        // RC Oscillator Configuration
    
    #define CC1101_DEFVAL_FSTEST     0x59        // Frequency Synthesizer Calibration Control
    
    #define CC1101_DEFVAL_PTEST      0x7F        // Production Test
    #define CC1101_DEFVAL_AGCTEST    0x3F        // AGC Test
    
    #define CC1101_DEFVAL_TEST2      0x81        // Various Test Settings
    #define CC1101_DEFVAL_TEST1      0x35        // Various Test Settings
    #define CC1101_DEFVAL_TEST0      0x09        // Various Test Settings

  #else
  //Renault Zoe...
    #define EXPECTEDBITCOUNT 64
    #define EXPECTEDBYTECOUNT 8
    
    #define SYNCBITS 16
    
    #define CDWIDTH_MIN 8500
    #define CDWIDTH_MAX 11500
    
    #define SHORTTIMING_MIN 35
    #define SHORTTIMING_MAX 79
    #define LONGTIMING_MIN 80
    #define LONGTIMING_MAX 120
    #define SYNCTIMING_MIN 175
    #define SYNCTIMING_MAX 1200
    
    #define ENDTIMING_MIN  0
    #define ENDTIMING_MAX  0


    #define CC1101_DEFVAL_IOCFG2     0x0C        // GDO2 Output Pin Configuration - Serial out (synchronous)
    #define CC1101_DEFVAL_IOCFG1     0x2E        // GDO1 Output Pin Configuration - not used
    //#define CC1101_DEFVAL_IOCFG0     0x0D        // GDO0 Output Pin Configuration
    #define CC1101_DEFVAL_IOCFG0     0x0E        // GDO0 Output Pin Configuration - Carrier Sense output
    #define CC1101_DEFVAL_FIFOTHR    0x0F        // RX FIFO and TX FIFO Thresholds - 64 bytes in FIFO
    #define CC1101_DEFVAL_SYNC1      0xD5        // Synchronization word, high byte  11010101 01001111
    #define CC1101_DEFVAL_SYNC0      0x4F        // Synchronization word, low byte
    #define CC1101_DEFVAL_PKTLEN     0x09        // Packet Length
    #define CC1101_DEFVAL_PKTCTRL1   0x00        // Packet Automation Control
    #define CC1101_DEFVAL_PKTCTRL0   0x12 //0x30        // Packet Automation Control - synchronous data
    #define CC1101_DEFVAL_ADDR       0x00        // Device Address
    #define CC1101_DEFVAL_CHANNR     0x00        // Channel Number
    #define CC1101_DEFVAL_FSCTRL1    0x0F        // Frequency Synthesizer Control (was 0x06)
    #define CC1101_DEFVAL_FSCTRL0    0x00        // Frequency Synthesizer Control
    
    // Carrier frequency = 433.919830 MHz
    #define CC1101_DEFVAL_FREQ2  0x10        // Frequency Control Word, High Byte
    #define CC1101_DEFVAL_FREQ1  0xB0        // Frequency Control Word, Middle Byte
    #define CC1101_DEFVAL_FREQ0  0x0C        // Frequency Control Word, Low Byte

    #define CC1101_DEFVAL_DEVIATN    0x41      // Modem Deviation Setting 

    #define CC1101_DEFVAL_MDMCFG4    0x59        // Modem Configuration (59 = data rate = 20kHz - actual data rate is 10kHz but due to bi-phase coding need to double the rate, RX bandwidth 325kHz)
    #define CC1101_DEFVAL_MDMCFG3    0x93        // Modem Configuration (now 93 = data rate = 20kHz)
    #define CC1101_DEFVAL_MDMCFG2    0x10        // Modem Configuration (GFSK, No Sync or Manchester coding)
    #define CC1101_DEFVAL_MDMCFG1    0x21        // Modem Configuration Channel spacing 100kHz
    #define CC1101_DEFVAL_MDMCFG0    0xF8        // Modem Configuration      
    #define CC1101_DEFVAL_AGCCTRL2   0x87       // AGC Control
    #define CC1101_DEFVAL_AGCCTRL1   0x58        // AGC Control
    #define CC1101_DEFVAL_AGCCTRL0   0x80        // AGC Control
    
    #define CC1101_DEFVAL_MCSM2      0x07        // Main Radio Control State Machine Configuration
    #define CC1101_DEFVAL_MCSM1      0x3C        // Main Radio Control State Machine Configuration
    #define CC1101_DEFVAL_MCSM0      0x18        // Main Radio Control State Machine Configuration
    #define CC1101_DEFVAL_FOCCFG     0x16        // Frequency Offset Compensation Configuration
    #define CC1101_DEFVAL_BSCFG      0x6C        // Bit Synchronization Configuration

    
    #define CC1101_DEFVAL_WOREVT1    0x87        // High Byte Event0 Timeout
    #define CC1101_DEFVAL_WOREVT0    0x6B        // Low Byte Event0 Timeout
    #define CC1101_DEFVAL_WORCTRL    0xFB        // Wake On Radio Control
    #define CC1101_DEFVAL_FREND1     0x56        // Front End RX Configuration
    #define CC1101_DEFVAL_FREND0     0x10        // Front End TX Configuration
    
    #define CC1101_DEFVAL_FSCAL3     0xE9        // Frequency Synthesizer Calibration
    #define CC1101_DEFVAL_FSCAL2     0x2A        // Frequency Synthesizer Calibration
    #define CC1101_DEFVAL_FSCAL1     0x00        // Frequency Synthesizer Calibration
    #define CC1101_DEFVAL_FSCAL0     0x1F        // Frequency Synthesizer Calibration
    
    #define CC1101_DEFVAL_RCCTRL1    0x41        // RC Oscillator Configuration
    #define CC1101_DEFVAL_RCCTRL0    0x00        // RC Oscillator Configuration
    
    #define CC1101_DEFVAL_FSTEST     0x59        // Frequency Synthesizer Calibration Control
    
    #define CC1101_DEFVAL_PTEST      0x7F        // Production Test
    #define CC1101_DEFVAL_AGCTEST    0x3F        // AGC Test
    
    #define CC1101_DEFVAL_TEST2      0x81        // Various Test Settings
    #define CC1101_DEFVAL_TEST1      0x35        // Various Test Settings
    #define CC1101_DEFVAL_TEST0      0x09        // Various Test Settings



  #endif

      
 
#elif US_315MHz


   #error Renault timings not defined for 315MHz


#endif


void DecodeTPMS()
{
  int i;
  unsigned long id = 0;
  unsigned int status, pressure1, pressure2, temp;
   double realpressure;
  float realtemp;
  bool IDFound = false;



  #ifdef Zoe
    for (i = 0; i <= 2; i++)
    {
      id = id << 8;
      id = id + RXBytes[i];
  
    }
  #else
    for (i = 5; i >= 3; i--)
    {
      id = id << 8;
      id = id + RXBytes[i];
  
    }
  #endif



  // id = (unsigned)RXBytes[0] << 24 | RXBytes[1] << 16 | RXBytes[2] << 8 | RXBytes[3];
  GetPreferredIndexStr(id, Ref);

  #ifdef Zoe
     status = (((unsigned int)RXBytes[3]) << 8) | RXBytes[6];
     pressure1 = RXBytes[4] ;
     temp = RXBytes[5];
     pressure2 = pressure1;
     realpressure = pressure1 * 0.2;  //psi
     realtemp = temp - 50.0;
  #else
     status = RXBytes[0] >> 2;
     pressure1 = (RXBytes[0] & 0x03)  << 8 | RXBytes[1];
     temp = RXBytes[2];
     pressure2 = pressure1;
     realpressure = pressure1 * 0.75;  //kpa
     realpressure = realpressure * 0.145038;  //psi
      realtemp = temp - 30.0;
  #endif

  if (pressure1 != pressure2)
  {
    #ifdef SHOWDEBUGINFO
       Serial.println(F("Pressure check mis-match"));
    #endif
    return;
  }

//  #ifdef DISPLAY_TEMP_AS_FAHRENHEIT
//     realtemp = ((realtemp * 9.0)/5.0) + 32.0;
//  #endif

#ifdef SHOWVALIDTPMS
  Serial.print(F("Pos: "));
  Serial.print(Ref);
  Serial.print(F("   ID: "));
  Serial.print(id, HEX);
  #ifdef Zoe
     Serial.print(F("   Status?????: 0x"));
  #else
     Serial.print(F("   Status: 0x"));
  #endif
  Serial.print(status,HEX);
  Serial.print(F("   Temperature: "));
  Serial.print(realtemp);
  Serial.print(F("   Tyre Pressure: "));
  Serial.print(realpressure);
  Serial.println(F(""));
#endif

  //DisplayStatusInfo();


  MatchIDandUpdate(id,status, realtemp, realpressure);



  #ifdef SHOWVALIDTPMS
     Serial.println(F(""));
  #endif


  //UpdateDisplay();
}




void ConvertTimingsToBits()
{
   int i;
   
   //bool CurrentState = FirstEdgeState;
   bool CurrentState = FirstEdgeIsHighToLow?true:false;
   BitCount = 0;
   

   for (i=0;i<= TimingsIndex;i++)
   {
      if (IsValidShort(Timings[i]) )
      {
         IncomingBits[BitCount++] = CurrentState;
      }
      else
      {
        if (IsValidLong(Timings[i]) )
        {
           IncomingBits[BitCount++] = CurrentState;
           IncomingBits[BitCount++] = CurrentState;
        }
        else
        {
          if (IsTooShort(Timings[i] ) || IsTooLong(Timings[i] ) )
          {
            
             if (i < TimingsIndex/2)  //enough bits in the buffer to continue trying?
             { //invalid bit timing, reset
                 
                 BitCount = 0;
             }
             else
             {// end the conversion
                //assume an end bit
                if (IsTooLong(Timings[i]) )
                {
                  IncomingBits[BitCount++] = CurrentState;
                }
//                #ifdef SHOWDEBUGINFO
//                   Serial.print(F("ConvertTimingsToBits exited at index: "));
//                   Serial.print(i);
//                   Serial.print(F(" bitcount: "));
//                   Serial.print(BitCount);
//                   Serial.print(F("  Timing value = "));
//                   Serial.println(Timings[i]);
//                #endif
                return;
             }
          }
        }
      }
      CurrentState = !CurrentState;

      if (BitCount >= MAXBITS-1) 
      {
         #ifdef SHOWDEBUGINFO
            Serial.println(F("Exited ConvertTimingsToBits with botcount > MAXBITS-1"));
         #endif
         return;
      }
   }
  
}



bool ValidateTimings()
{


  byte BitWidth;
  byte BitWidthNext;
  byte BitWidthNextPlus1;
  byte BitWidthPrevious;
  byte diff = TimingsIndex - CheckIndex;
  //unsigned long tmp;
  bool WaitingTrailingZeroEdge = false;
  int ret;
  int ManchesterStartPos = -1;
  byte ByteCount = 0;
  byte crcResult;

  StartDataIndex = 0;

  if (TimingsIndex < (SYNCBITS + EXPECTEDBITCOUNT) ) //header + valid data (minimum)
  { //not enough in the buffer to consider a valid message
    #ifdef SHOWDEBUGINFO
       Serial.println(F("Insufficient data in buffer"));
    #endif
    return (false);
  }

  if (TimingsIndex > 200)  //header + valid data (minimum)
  { //not enough in the buffer to consider a valid message
    #ifdef SHOWDEBUGINFO
       Serial.println(F("Excessive data in buffer"));
    #endif
    return (false);
  }

  //Serial.print("Timings index = ");
  //Serial.println(TimingsIndex);

  ConvertTimingsToBits();

  InvertBitBuffer();
  
  const uint8_t pattern[] = {0xAA, 0xA9}; 
  ManchesterStartPos = FindManchesterStart(pattern,16 );
  StartDataIndex = ManchesterStartPos;

  if (ManchesterStartPos == -1 )
  {
    InvertBitBuffer();
    ManchesterStartPos = FindManchesterStart(pattern,16 );
    StartDataIndex = ManchesterStartPos;
  
    if (ManchesterStartPos == -1 )
    {    
      #ifdef SHOWDEBUGINFO
         Serial.println(F("Renault header not found"));
      #endif
      return (false);   
    }
  }

  ByteCount = ManchesterDecode(ManchesterStartPos);
  if (ByteCount >= EXPECTEDBYTECOUNT)
  {
      
      //check the checksum...
      #ifdef Zoe
         crcResult = Compute_CRC_XOR(0,EXPECTEDBYTECOUNT, 0x00);
      #else
         crcResult = Compute_CRC8(EXPECTEDBYTECOUNT, 0x07, 0x00);
      #endif
      if (crcResult != 0)
      {
        #ifdef SHOWDEBUGINFO
           Serial.println(F("CRC Check failed"));
        #endif
        #ifdef IGNORECHECKSUMERRORS
          DecodeTPMS();
          TPMS_Changed = false;  //don't update display for csum error
        #endif
        return(false);
      }
      else
      {
         #ifdef SHOWDEBUGINFO
           Serial.println(F("CRC Check OK"));
         #endif
        //decode the message...
        DecodeTPMS();
        TPMS_Changed = true;  //indicates the display needs to be updated.
        return(true);
      }


  }
  else
  {
    #ifdef SHOWDEBUGINFO
       Serial.print(F("Insufficient bytes: "));
       Serial.print(ByteCount);
       Serial.print(F(" received, expected at least: "));
       Serial.println(EXPECTEDBYTECOUNT);
       PrintTimings(0,ByteCount * 8);
    #endif
    return (false);
  }


}

Citroen

C Header File
      
     
#ifdef UK_433MHz



    #define EXPECTEDBITCOUNT 80
    #define EXPECTEDBYTECOUNT 10
    
    #define SYNCBITS 16
    
    #define CDWIDTH_MIN 9500
    #define CDWIDTH_MAX 11500
    
    #define SHORTTIMING_MIN 35
    #define SHORTTIMING_MAX 79
    #define LONGTIMING_MIN 80
    #define LONGTIMING_MAX 120
    #define SYNCTIMING_MIN 175
    #define SYNCTIMING_MAX 1200
    
    #define ENDTIMING_MIN  0
    #define ENDTIMING_MAX  0


    #define CC1101_DEFVAL_IOCFG2     0x0C        // GDO2 Output Pin Configuration - Serial out (synchronous)
    #define CC1101_DEFVAL_IOCFG1     0x2E        // GDO1 Output Pin Configuration - not used
    #define CC1101_DEFVAL_IOCFG0     0x0E        // GDO0 Output Pin Configuration - Carrier Sense output
    #define CC1101_DEFVAL_FIFOTHR    0x0F        // RX FIFO and TX FIFO Thresholds - 64 bytes in FIFO
    #define CC1101_DEFVAL_SYNC1      0xD5        // Synchronization word, high byte  11010101 01001111
    #define CC1101_DEFVAL_SYNC0      0x4F        // Synchronization word, low byte
    #define CC1101_DEFVAL_PKTLEN     0x09        // Packet Length
    #define CC1101_DEFVAL_PKTCTRL1   0x00        // Packet Automation Control
    #define CC1101_DEFVAL_PKTCTRL0   0x12 //0x30        // Packet Automation Control - synchronous data
    #define CC1101_DEFVAL_ADDR       0x00        // Device Address
    #define CC1101_DEFVAL_CHANNR     0x00        // Channel Number
    #define CC1101_DEFVAL_FSCTRL1    0x0F        // Frequency Synthesizer Control (was 0x06)
    #define CC1101_DEFVAL_FSCTRL0    0x00        // Frequency Synthesizer Control
    
    // Carrier frequency = 433.919830 MHz
    #define CC1101_DEFVAL_FREQ2  0x10        // Frequency Control Word, High Byte
    #define CC1101_DEFVAL_FREQ1  0xB0        // Frequency Control Word, Middle Byte
    #define CC1101_DEFVAL_FREQ0  0x71        // Frequency Control Word, Low Byte

    #define CC1101_DEFVAL_DEVIATN    0x40      // Modem Deviation Setting (+/-25.390625kHz)

    #define CC1101_DEFVAL_MDMCFG4    0x59        // Modem Configuration (59 = data rate = 20kHz - actual data rate is 10kHz but due to bi-phase coding need to double the rate, RX bandwidth 325kHz)
    #define CC1101_DEFVAL_MDMCFG3    0x93        // Modem Configuration (now 93 = data rate = 20kHz)
    #define CC1101_DEFVAL_MDMCFG2    0x10        // Modem Configuration (GFSK, No Sync or Manchester coding)
    #define CC1101_DEFVAL_MDMCFG1    0x21        // Modem Configuration Channel spacing 100kHz
    #define CC1101_DEFVAL_MDMCFG0    0xF8        // Modem Configuration      
    #define CC1101_DEFVAL_AGCCTRL2   0x87       // AGC Control
    #define CC1101_DEFVAL_AGCCTRL1   0x58        // AGC Control
    #define CC1101_DEFVAL_AGCCTRL0   0x80        // AGC Control
    
    #define CC1101_DEFVAL_MCSM2      0x07        // Main Radio Control State Machine Configuration
    #define CC1101_DEFVAL_MCSM1      0x3C        // Main Radio Control State Machine Configuration
    #define CC1101_DEFVAL_MCSM0      0x18        // Main Radio Control State Machine Configuration
    #define CC1101_DEFVAL_FOCCFG     0x16        // Frequency Offset Compensation Configuration
    #define CC1101_DEFVAL_BSCFG      0x6C        // Bit Synchronization Configuration

    
    #define CC1101_DEFVAL_WOREVT1    0x87        // High Byte Event0 Timeout
    #define CC1101_DEFVAL_WOREVT0    0x6B        // Low Byte Event0 Timeout
    #define CC1101_DEFVAL_WORCTRL    0xFB        // Wake On Radio Control
    #define CC1101_DEFVAL_FREND1     0x56        // Front End RX Configuration
    #define CC1101_DEFVAL_FREND0     0x10        // Front End TX Configuration
    
    #define CC1101_DEFVAL_FSCAL3     0xE9        // Frequency Synthesizer Calibration
    #define CC1101_DEFVAL_FSCAL2     0x2A        // Frequency Synthesizer Calibration
    #define CC1101_DEFVAL_FSCAL1     0x00        // Frequency Synthesizer Calibration
    #define CC1101_DEFVAL_FSCAL0     0x1F        // Frequency Synthesizer Calibration
    
    #define CC1101_DEFVAL_RCCTRL1    0x41        // RC Oscillator Configuration
    #define CC1101_DEFVAL_RCCTRL0    0x00        // RC Oscillator Configuration
    
    #define CC1101_DEFVAL_FSTEST     0x59        // Frequency Synthesizer Calibration Control
    
    #define CC1101_DEFVAL_PTEST      0x7F        // Production Test
    #define CC1101_DEFVAL_AGCTEST    0x3F        // AGC Test
    
    #define CC1101_DEFVAL_TEST2      0x81        // Various Test Settings
    #define CC1101_DEFVAL_TEST1      0x35        // Various Test Settings
    #define CC1101_DEFVAL_TEST0      0x09        // Various Test Settings



      
 
#elif US_315MHz


         #error Citroen timings not defined for 315MHz


#endif      



void DecodeTPMS()
{
  int i;
  unsigned long id = 0;
  unsigned int status, state, pressure1, pressure2, temp, flags, repeat, battery;
  double realpressure;
  float realtemp;
  bool IDFound = false;

  

  for (i = 1; i <= 4; i++)
  {
    id = id << 8;
    id = id + RXBytes[i];

  }

  // id = (unsigned)RXBytes[0] << 24 | RXBytes[1] << 16 | RXBytes[2] << 8 | RXBytes[3];
  GetPreferredIndexStr(id, Ref);
  
  state = RXBytes[0];

  pressure1 = RXBytes[6];

  temp = RXBytes[7];

  pressure2 = pressure1;

  battery = RXBytes[8];
  status = RXBytes[5];
  flags = RXBytes[5] >>4;
  repeat = RXBytes[5] & 0x0F;



  if (pressure1 != pressure2)
  {
    Serial.println(F("Pressure check mis-match"));
    return;
  }

  realpressure = pressure1 * 1.364;  //kpa
  realpressure = realpressure * 0.145038;  //psi
  realtemp = temp - 50.0;
//  #ifdef DISPLAY_TEMP_AS_FAHRENHEIT
//     realtemp = ((realtemp * 9.0)/5.0) + 32.0;
//  #endif
  
#ifdef SHOWVALIDTPMS
  Serial.print(F("Pos: "));
  Serial.print(Ref);
  Serial.print(F("   ID: "));
  Serial.print(id, HEX);
  Serial.print(F("   State: 0x"));
  Serial.print(state,HEX);
  Serial.print(F("   Status: 0x"));
  Serial.print(status,HEX);
  Serial.print(F("   ["));
  Serial.print(F("Flags: 0x"));
  Serial.print(flags,HEX);
  Serial.print(F("   Repeat: "));
  Serial.print(repeat);
  Serial.print(F("]"));
  Serial.print(F("   Battery(?): "));
  Serial.print(battery);
  Serial.print(F("   Temperature: "));
  Serial.print(realtemp);
  Serial.print(F("   Tyre Pressure: "));
  Serial.print(realpressure);
  Serial.println(F(""));
#endif

  //DisplayStatusInfo();

   MatchIDandUpdate(id,status, realtemp, realpressure);
   
  #ifdef SHOWVALIDTPMS
     Serial.println(F(""));
  #endif


  //UpdateDisplay();
}








void ConvertTimingsToBits()
{
   int i;
   
   //bool CurrentState = FirstEdgeState;
   bool CurrentState = FirstEdgeIsHighToLow?true:false;
   BitCount = 0;
   

   for (i=0;i<= TimingsIndex;i++)
   {
      if (IsValidShort(Timings[i]) )
      {
         IncomingBits[BitCount++] = CurrentState;
      }
      else
      {
        if (IsValidLong(Timings[i]) )
        {
           IncomingBits[BitCount++] = CurrentState;
           IncomingBits[BitCount++] = CurrentState;
        }
        else
        {
          if (IsTooShort(Timings[i] ) || IsTooLong(Timings[i] ) )
          {
            
             if (i < TimingsIndex/2)  //enough bits in the buffer to continue trying?
             { //invalid bit timing, reset
               
                 BitCount = 0;
             }
             else
             {// end the conversion
                return;
             }
          }
        }
      }
      CurrentState = !CurrentState;

      if (BitCount >= MAXBITS-1) 
      {
         return;
      }
   }
  
}




bool ValidateTimings()
{


  byte BitWidth;
  byte BitWidthNext;
  byte BitWidthNextPlus1;
  byte BitWidthPrevious;
  byte diff = TimingsIndex - CheckIndex;
  //unsigned long tmp;
  bool WaitingTrailingZeroEdge = false;
  int ret;
  int ManchesterStartPos = -1;
  byte ByteCount = 0;
  byte crcResult = 0;

  StartDataIndex = 0;

  if (TimingsIndex < (SYNCBITS + EXPECTEDBITCOUNT) )  //header + valid data (minimum)
  { //not enough in the buffer to consider a valid message
    #ifdef SHOWDEBUGINFO
       Serial.println(F("Insufficient data in buffer"));
    #endif
    return(false);
  }

  if (TimingsIndex > 200)  //header + valid data (minimum)
  { //not enough in the buffer to consider a valid message
    #ifdef SHOWDEBUGINFO
       Serial.println(F("Excessive data in buffer"));
    #endif
    return(false);
  }

  //Serial.print("Timings index = ");
  //Serial.println(TimingsIndex);

  ConvertTimingsToBits();

  //InvertBitBuffer();

  const uint8_t pattern[] = {0xAA, 0xA9};
  ManchesterStartPos = FindManchesterStart(pattern, 16);
  StartDataIndex = ManchesterStartPos;

  if (ManchesterStartPos == -1 )
  {
    #ifdef SHOWDEBUGINFO
       Serial.println(F("Citroen header not found"));
    #endif

    return(false);   
//  }
//  else
//  {
//     #ifdef SHOWDEBUGINFO
//       Serial.print("Timings index = ");
//       Serial.println(TimingsIndex);
//       Serial.print("CD Width = ");
//       Serial.println(CD_Width);
//       Serial.print("Bit count = ");
//       Serial.println(BitCount);
//       PrintTimings(0,TimingsIndex);
//       PrintData(BitCount);
//    #endif 
  }

  ByteCount = ManchesterDecode(ManchesterStartPos);
  if (ByteCount == EXPECTEDBYTECOUNT)
  {

       crcResult = Compute_CRC_XOR(1,EXPECTEDBYTECOUNT-1, 0x00);  //Checksum, XOR bytes 1 to 9 = 0
       if (crcResult != 0)
      {
         Serial.println(F("CRC Check failed"));
        #ifdef IGNORECHECKSUMERRORS
          DecodeTPMS();
          TPMS_Changed = false;  //don't update display for csum error
        #endif
        return(false);
      }
      else
      {
        Serial.println(F("CRC Check OK"));
        //decode the message...
        DecodeTPMS();
        TPMS_Changed = true;  //indicates the display needs to be updated.
        return(true);
      }
     
  }
  else
  {
    return(false);
  }


}


//int ReceiveMessage()
//{
//
//  //Check bytes in FIFO
//  int FIFOcount;
//  int resp;
//  bool ValidMessage = false;
//  int lRSSI;
//  byte crcResult;
//
//
//#ifdef USE_TEST_TIMINGS  
//  //test set up....
//  CD_Width = CDWIDTH_MIN + ((CDWIDTH_MAX - CDWIDTH_MIN)/2);;
//  //Serial.println("Test setup");
//  //copy timings to timings array as if they've come from the interrupt
//  for (TimingsIndex=0;TimingsIndex<TestTimings_len;TimingsIndex++)
//  {
//     Timings[TimingsIndex] = TestTimings[TimingsIndex];
//  }
//  FirstEdgeIsHighToLow = true;
//
//#else
//
//
//  //set up timing of edges using interrupts...
//  LastEdgeTime_us = micros();
//  CD_Width = micros();
//
//  attachInterrupt(digitalPinToInterrupt(RXPin), EdgeInterrupt, CHANGE);
//  while (GetCarrierStatus() == true)
//  {
//
//     //get the maximum RSSI value seen during data receive window
//     lRSSI = GetRSSI_dbm();
//     if (lRSSI > RSSIvalue)
//     {
//       RSSIvalue = lRSSI;
//     }
//  }
//  detachInterrupt(digitalPinToInterrupt(RXPin));
//
//  //digitalWrite(DEBUGPIN,LOW);
//
//  CD_Width = micros() - CD_Width;
//
//
//#endif
//
//  if ((CD_Width >= CDWIDTH_MIN) && (CD_Width <= CDWIDTH_MAX))
//  {
//    
//
//    //Serial.println(F("Checking"));
//    digitalWrite(LED_RX,LED_ON);
//    CheckIndex = 0;
//    ValidMessage = ValidateTimings();
//
//
//    #ifdef SHOWDEBUGINFO
//       Serial.print("Timings index = ");
//       Serial.println(TimingsIndex);
//       Serial.print("CD Width = ");
//       Serial.println(CD_Width);
//       PrintTimings(0,TimingsIndex);
//    #endif
//
//    if (ValidMessage)
//    {
//       crcResult = Compute_CRC_XOR(1,EXPECTEDBYTECOUNT-1, 0x00);  //Checksum, XOR bytes 1 to 9 = 0
//       if (crcResult != 0)
//      {
//         Serial.println(F("CRC Check failed"));
//        #ifdef IGNORECHECKSUMERRORS
//          DecodeTPMS();
//          TPMS_Changed = true;  //indicates the display needs to be updated.
//        #endif
//      }
//      else
//      {
//        Serial.println(F("CRC Check OK"));
//        //decode the message...
//        DecodeTPMS();
//        TPMS_Changed = true;  //indicates the display needs to be updated.
//      }
//    }
//    digitalWrite(LED_RX,LED_OFF);
//    return bitcount;
//  }
//  else
//  {
//    return(0);
//  }
//
//
//
//}

Configs

C Header File
//Select the display type being used:
#define USE_1_INCH_YB_I2C_DISPLAY 1
//#define USE_2_INCH_ST7753_DISPLAY 1
//#define USE_2_INCH_ST7789_DISPLAY 1  //(round display)


//Receive frequency
#define UK_433MHz 1
//#define US_315MHz 1

//Vehicle/sensor type
#define Toyota_PMV_C210 1   //should also work for PMV-C010??
//#define Toyota_PMV_107J 1
//#define Renault 1
//#define Zoe 1   //for Renault Zoe 09/2012 to 06/2019 only
//#define Dacia 1
//#define NissanLeaf 1
//#define Citroen 1
//#define PontiacG82009 1

//#define Ford 1
//Possible Ford variants..
//#define Ford_FSeries_SD 1
//#define Ford_FSeries_2006_2008 1
#define Ford_OtherVariants 1



//#define Jansite 1  //requires bigger buffer sizes - won't work on ProMicro or Nano?
//#define JansiteSolar 1   //requires bigger buffer sizes - won't work on ProMicro or Nano?


#ifdef Ford_FSeries_SD
   #define FordType 2
#elif Ford_FSeries_2006_2008
   #define FordType 1
#else
   #define FordType 0
#endif



////#define INCLUDESPARETYRE 1    - nolonger used. If no spare with TPMS, just set the ID to 0xFFFFFFF
//#define INCLUDE_WINTER_SET 1

//Pressure display and limits units (default is PSI and deg C if these not set)
//#define DISPLAY_PRESSURE_AS_BAR 1
//#define DISPLAY_PRESSURE_AS_KPA 1
//#define DISPLAY_TEMP_AS_FAHRENHEIT 1  //if uncommented,temperature is displayed as deg F, otherwise displayed as deg C

#define ENABLE_PRESSURE_ALARMS 1
#define ENABLE_TEMPERATURE_ALARMS 1

#define ENABLE_AUDIBLE_ALARM 1

#define ENABLE_PRESSURE_ALARM_TEMPERATURE_COMPENSATION 1


#if defined(USE_2_INCH_ST7753_DISPLAY) || defined(USE_2_INCH_ST7789_DISPLAY) || defined(USE_1_INCH_YB_I2C_DISPLAY)
   #define USE_LCDDISPLAY 1
#endif

//config checks...

#if defined(UK_433MHz) && defined(US_315MHz)
   #error Cannot define both 433MHz and 315MHz simultaneously
#endif

#if !defined(UK_433MHz) && !defined(US_315MHz)
   #error Must define either 433MHz or 315MHz
#endif


#if defined(USE_LCDDISPLAY) && (defined(USE_2_INCH_ST7753_DISPLAY) || defined(USE_2_INCH_ST7789_DISPLAY)) && defined(ARDUINO_AVR_PROMICRO)
   #error ProMicro doesn't have enough memory for this display!
#endif

//tyre IDs for vehicle....(may need to prefix known IDs with leading 'F' to match reception)
#ifdef NissanLeaf
  #define FRONT_LEFT  0x02BB910L
  #define FRONT_RIGHT 0x02BB929L
  #define REAR_LEFT   0x02BB90EL
  #define REAR_RIGHT  0x02BB91AL
  #define SPARE       0x0FFFFFFFL
  #define WINTER_FRONT_LEFT  0x02BB910L
  #define WINTER_FRONT_RIGHT 0x02BB929L
  #define WINTER_REAR_LEFT   0x02BB90EL
  #define WINTER_REAR_RIGHT  0x02BB91AL
  #define WINTER_SPARE       0x0FFFFFFFL
#else
  #define FRONT_LEFT  0x01721EB0L
  #define FRONT_RIGHT 0x0172221FL
  #define REAR_LEFT   0x0172223EL
  #define REAR_RIGHT  0x01721E9AL
  #define SPARE       0x01FFFFFFL
  #define WINTER_FRONT_LEFT  0x02721EB0L
  #define WINTER_FRONT_RIGHT 0x0272221FL
  #define WINTER_REAR_LEFT   0x0272223EL
  #define WINTER_REAR_RIGHT  0x02721E9AL
  #define WINTER_SPARE       0x0FFFFFFFL
#endif



int Ford_SensorType = FordType;  //3 different types seen, select 0,1,2 to match the pressure readings


#ifdef NissanLeaf
    const float PressureLimitsTemperature = 20;
    const  double PressureLowLimits[]
    {
      33, 33, 
      33, 33,
      33
    };
    
    const double  PressureHighLimits[]
    {
      40, 40, 
      40, 40, 
      40
    };
    
    //set temperature limits to Fahrenheit or Centigrade depending on DISPLAY_TEMP_AS_FAHRENHEIT setting (will be converted to centigrade when loading if required)
    const float  TemperatureLowLimits[]
    {
      -10, -10, 
      -10, -10,
      -10
    };
    
    const float  TemperatureHighLimits[]
    {
      40, 40, 
      40, 40,
      40
    };



#else
    const float PressureLimitsTemperature = 20;
    const  double PressureLowLimits[]
    {
      30, 30, 
      30, 30,
      30
    };
    
    const double  PressureHighLimits[]
    {
      33, 33, 
      33, 33,
      33
    };
    
    //set temperature limits to Fahrenheit or Centigrade depending on DISPLAY_TEMP_AS_FAHRENHEIT setting (will be converted to centigrade when loading if required)
    const float  TemperatureLowLimits[]
    {
      -10, -10, 
      -10, -10,
      -10
    };
    
    const float  TemperatureHighLimits[]
    {
      33, 33, 
      33, 33,
      33
    };

#endif

Ford

C Header File
#ifdef UK_433MHz

   

    #define EXPECTEDBITCOUNT 64
    #define EXPECTEDBYTECOUNT 8
    
    #define SYNCBITS 16
    
    #define CDWIDTH_MIN 7600
    #define CDWIDTH_MAX 10000
    
    #define SHORTTIMING_MIN 35
    #define SHORTTIMING_MAX 79
    #define LONGTIMING_MIN 80
    #define LONGTIMING_MAX 120
    #define SYNCTIMING_MIN 175
    #define SYNCTIMING_MAX 1200
    
    #define ENDTIMING_MIN  0
    #define ENDTIMING_MAX  0
    

    #define CC1101_DEFVAL_IOCFG2     0x0C        // GDO2 Output Pin Configuration - Serial out (synchronous)
    #define CC1101_DEFVAL_IOCFG1     0x2E        // GDO1 Output Pin Configuration - not used
    #define CC1101_DEFVAL_IOCFG0     0x0E        // GDO0 Output Pin Configuration - Carrier Sense output
    #define CC1101_DEFVAL_FIFOTHR    0x0F        // RX FIFO and TX FIFO Thresholds - 64 bytes in FIFO
    #define CC1101_DEFVAL_SYNC1      0xD5        // Synchronization word, high byte  11010101 01001111
    #define CC1101_DEFVAL_SYNC0      0x4F        // Synchronization word, low byte
    #define CC1101_DEFVAL_PKTLEN     0x09        // Packet Length
    #define CC1101_DEFVAL_PKTCTRL1   0x00        // Packet Automation Control
    #define CC1101_DEFVAL_PKTCTRL0   0x12 //0x30        // Packet Automation Control - synchronous data
    #define CC1101_DEFVAL_ADDR       0x00        // Device Address
    #define CC1101_DEFVAL_CHANNR     0x00        // Channel Number
    #define CC1101_DEFVAL_FSCTRL1    0x0F        // Frequency Synthesizer Control (was 0x06)
    #define CC1101_DEFVAL_FSCTRL0    0x00        // Frequency Synthesizer Control
    
    // Carrier frequency = 433.919830 MHz
    #define CC1101_DEFVAL_FREQ2  0x10        // Frequency Control Word, High Byte
    #define CC1101_DEFVAL_FREQ1  0xB0        // Frequency Control Word, Middle Byte
    #define CC1101_DEFVAL_FREQ0  0x71        // Frequency Control Word, Low Byte

    #define CC1101_DEFVAL_DEVIATN    0x40      // Modem Deviation Setting (+/-25.390625kHz)

    #define CC1101_DEFVAL_MDMCFG4    0x59        // Modem Configuration (59 = data rate = 20kHz - actual data rate is 10kHz but due to bi-phase coding need to double the rate, RX bandwidth 325kHz)
    #define CC1101_DEFVAL_MDMCFG3    0x93        // Modem Configuration (now 93 = data rate = 20kHz)
    #define CC1101_DEFVAL_MDMCFG2    0x10        // Modem Configuration (GFSK, No Sync or Manchester coding)
    #define CC1101_DEFVAL_MDMCFG1    0x21        // Modem Configuration Channel spacing 100kHz
    #define CC1101_DEFVAL_MDMCFG0    0xF8        // Modem Configuration      
    #define CC1101_DEFVAL_AGCCTRL2   0x87       // AGC Control
    #define CC1101_DEFVAL_AGCCTRL1   0x58        // AGC Control
    #define CC1101_DEFVAL_AGCCTRL0   0x80        // AGC Control
    
    #define CC1101_DEFVAL_MCSM2      0x07        // Main Radio Control State Machine Configuration
    #define CC1101_DEFVAL_MCSM1      0x3C        // Main Radio Control State Machine Configuration
    #define CC1101_DEFVAL_MCSM0      0x18        // Main Radio Control State Machine Configuration
    #define CC1101_DEFVAL_FOCCFG     0x16        // Frequency Offset Compensation Configuration
    #define CC1101_DEFVAL_BSCFG      0x6C        // Bit Synchronization Configuration

    
    #define CC1101_DEFVAL_WOREVT1    0x87        // High Byte Event0 Timeout
    #define CC1101_DEFVAL_WOREVT0    0x6B        // Low Byte Event0 Timeout
    #define CC1101_DEFVAL_WORCTRL    0xFB        // Wake On Radio Control
    #define CC1101_DEFVAL_FREND1     0x56        // Front End RX Configuration
    #define CC1101_DEFVAL_FREND0     0x10        // Front End TX Configuration
    
    #define CC1101_DEFVAL_FSCAL3     0xE9        // Frequency Synthesizer Calibration
    #define CC1101_DEFVAL_FSCAL2     0x2A        // Frequency Synthesizer Calibration
    #define CC1101_DEFVAL_FSCAL1     0x00        // Frequency Synthesizer Calibration
    #define CC1101_DEFVAL_FSCAL0     0x1F        // Frequency Synthesizer Calibration
    
    #define CC1101_DEFVAL_RCCTRL1    0x41        // RC Oscillator Configuration
    #define CC1101_DEFVAL_RCCTRL0    0x00        // RC Oscillator Configuration
    
    #define CC1101_DEFVAL_FSTEST     0x59        // Frequency Synthesizer Calibration Control
    
    #define CC1101_DEFVAL_PTEST      0x7F        // Production Test
    #define CC1101_DEFVAL_AGCTEST    0x3F        // AGC Test
    
    #define CC1101_DEFVAL_TEST2      0x81        // Various Test Settings
    #define CC1101_DEFVAL_TEST1      0x35        // Various Test Settings
    #define CC1101_DEFVAL_TEST0      0x09        // Various Test Settings



      
 
#elif US_315MHz

    
    #define EXPECTEDBITCOUNT 64
    #define EXPECTEDBYTECOUNT 8
    
    #define SYNCBITS 16
    
    #define CDWIDTH_MIN 7600
    #define CDWIDTH_MAX 10000
    
    #define SHORTTIMING_MIN 35
    #define SHORTTIMING_MAX 79
    #define LONGTIMING_MIN 80
    #define LONGTIMING_MAX 120
    #define SYNCTIMING_MIN 175
    #define SYNCTIMING_MAX 1200
    
    #define ENDTIMING_MIN  0
    #define ENDTIMING_MAX  0
     

    #define CC1101_DEFVAL_IOCFG2     0x0C        // GDO2 Output Pin Configuration - Serial out (synchronous)
    #define CC1101_DEFVAL_IOCFG1     0x2E        // GDO1 Output Pin Configuration - not used
    #define CC1101_DEFVAL_IOCFG0     0x0E        // GDO0 Output Pin Configuration - Carrier Sense output
    #define CC1101_DEFVAL_FIFOTHR    0x0F        // RX FIFO and TX FIFO Thresholds - 64 bytes in FIFO
    #define CC1101_DEFVAL_SYNC1      0xD5        // Synchronization word, high byte  11010101 01001111
    #define CC1101_DEFVAL_SYNC0      0x4F        // Synchronization word, low byte
    #define CC1101_DEFVAL_PKTLEN     0x09        // Packet Length
    #define CC1101_DEFVAL_PKTCTRL1   0x00        // Packet Automation Control
    #define CC1101_DEFVAL_PKTCTRL0   0x12 //0x30        // Packet Automation Control - synchronous data
    #define CC1101_DEFVAL_ADDR       0x00        // Device Address
    #define CC1101_DEFVAL_CHANNR     0x00        // Channel Number
    #define CC1101_DEFVAL_FSCTRL1    0x0F        // Frequency Synthesizer Control (was 0x06)
    #define CC1101_DEFVAL_FSCTRL0    0x00        // Frequency Synthesizer Control
    
    // Carrier frequency = 314.979828 MHz
    #define CC1101_DEFVAL_FREQ2  0x0C        // Frequency Control Word, High Byte
    #define CC1101_DEFVAL_FREQ1  0x1D        // Frequency Control Word, Middle Byte
    #define CC1101_DEFVAL_FREQ0  0x57        // Frequency Control Word, Low Byte
      
    #define CC1101_DEFVAL_DEVIATN    0x40      // Modem Deviation Setting (+/-25.390625kHz)

    #define CC1101_DEFVAL_MDMCFG4    0x59        // Modem Configuration (59 = data rate = 20kHz - actual data rate is 10kHz but due to bi-phase coding need to double the rate, RX bandwidth 101.562500kHz)
    #define CC1101_DEFVAL_MDMCFG3    0x93        // Modem Configuration (now 93 = data rate = 20kHz)
    #define CC1101_DEFVAL_MDMCFG2    0x10        // Modem Configuration (GFSK, No Sync or Manchester coding)
    #define CC1101_DEFVAL_MDMCFG1    0x21        // Modem Configuration Channel spacing 100kHz
    #define CC1101_DEFVAL_MDMCFG0    0xF8        // Modem Configuration      
    #define CC1101_DEFVAL_AGCCTRL2   0x87       // AGC Control
    #define CC1101_DEFVAL_AGCCTRL1   0x58        // AGC Control
    #define CC1101_DEFVAL_AGCCTRL0   0x80        // AGC Control
    
    #define CC1101_DEFVAL_MCSM2      0x07        // Main Radio Control State Machine Configuration
    #define CC1101_DEFVAL_MCSM1      0x3C        // Main Radio Control State Machine Configuration
    #define CC1101_DEFVAL_MCSM0      0x18        // Main Radio Control State Machine Configuration
    #define CC1101_DEFVAL_FOCCFG     0x16        // Frequency Offset Compensation Configuration
    #define CC1101_DEFVAL_BSCFG      0x6C        // Bit Synchronization Configuration

    
    #define CC1101_DEFVAL_WOREVT1    0x87        // High Byte Event0 Timeout
    #define CC1101_DEFVAL_WOREVT0    0x6B        // Low Byte Event0 Timeout
    #define CC1101_DEFVAL_WORCTRL    0xFB        // Wake On Radio Control
    #define CC1101_DEFVAL_FREND1     0x56        // Front End RX Configuration
    #define CC1101_DEFVAL_FREND0     0x10        // Front End TX Configuration
    
    #define CC1101_DEFVAL_FSCAL3     0xE9        // Frequency Synthesizer Calibration
    #define CC1101_DEFVAL_FSCAL2     0x2A        // Frequency Synthesizer Calibration
    #define CC1101_DEFVAL_FSCAL1     0x00        // Frequency Synthesizer Calibration
    #define CC1101_DEFVAL_FSCAL0     0x1F        // Frequency Synthesizer Calibration
    
    #define CC1101_DEFVAL_RCCTRL1    0x41        // RC Oscillator Configuration
    #define CC1101_DEFVAL_RCCTRL0    0x00        // RC Oscillator Configuration
    
    #define CC1101_DEFVAL_FSTEST     0x59        // Frequency Synthesizer Calibration Control
    
    #define CC1101_DEFVAL_PTEST      0x7F        // Production Test
    #define CC1101_DEFVAL_AGCTEST    0x3F        // AGC Test
    
    #define CC1101_DEFVAL_TEST2      0x81        // Various Test Settings
    #define CC1101_DEFVAL_TEST1      0x35        // Various Test Settings
    #define CC1101_DEFVAL_TEST0      0x09        // Various Test Settings


#endif

void DecodeTPMS()
{
  int i;
  unsigned long id = 0;
  unsigned int status, pressure1, pressure2, temp;
  double realpressure;
  double realtemp;
  bool IDFound = false;
  byte SensorType;


  for (i = 0; i <= 3; i++)
  {
    id = id << 8;
    id = id + RXBytes[i];

  }

  GetPreferredIndexStr(id, Ref);

  // id = (unsigned)RXBytes[0] << 24 | RXBytes[1] << 16 | RXBytes[2] << 8 | RXBytes[3];

  status = RXBytes[0] >> 2;

  pressure1 = ((RXBytes[6] & 0x20)  << 3) | RXBytes[4];

  temp = RXBytes[5];

  pressure2 = pressure1;



  if (pressure1 != pressure2)
  {
    #ifdef SHOWDEBUGINFO
       Serial.println(F("Pressure check mis-match"));
    #endif
    return;
  }

// if (pressure1 < 90)
//  {
//    realpressure =  (pressure1 * 0.2496) - 0.0582;  //psi
//  }
//  else
//  {
//    //realpressure = 6.8 + (pressure1 * 0.2122727273);  //psi
//    realpressure = (RXBytes[4] * 0.4497) - 0.0441;  //psi  //Ford F-Series SD 01/2009-05/2010 (315MHz)
//  }

  //SensorType = RXBytes[6] >> 5;  //this is a guess! Upper 3 bits represents the sensor variation? Also, RXByte[6] bit 0 when clear indicates a triggered response, when set, this is an untriggered response???
  SensorType = Ford_SensorType;

  switch (SensorType)
  {
     case 0:
           realpressure =  ((double)RXBytes[4] * 0.25);  //psi  //Ford F-Series 01/2009-12/2014 (315MHz)
                                                                //Ford F-Series 01/2017-12/2020 (315MHz)
           break;
     case 1:
           realpressure = ((double)RXBytes[4] * 0.45);  //psi //Ford F-Series SD 01/2009-05/2010 (315MHz)
           break;
     case 2:
           realpressure = ((double)RXBytes[4] * 0.20);  //psi //Ford F-Series 01/2006-12/2008 (315MHz)
           break;

     default:
           realpressure = 6.8 + ((double)pressure1 * 0.2122727273);  //psi
           break;
  }
  if (realpressure < 0)
     realpressure = 0.0;

  realtemp = temp - 56;
//  #ifdef DISPLAY_TEMP_AS_FAHRENHEIT
//     realtemp = ((realtemp * 9.0)/5.0) + 32.0;
//  #endif
  //realtemp = (temp - 32.0) * 0.5555556;



#ifdef SHOWVALIDTPMS
  Serial.print(F("Pos: "));
  Serial.print(Ref);
  Serial.print(F("   ID: "));
  Serial.print(id, HEX);
  Serial.print(F("   Status????: 0x"));
  Serial.print(status,HEX);
  Serial.print(F("   Temperature: "));
  Serial.print(realtemp);
  Serial.print(F("   Tyre Pressure????: "));
  Serial.print(realpressure);
  Serial.print(F("   Sensor type????: "));
  Serial.print(SensorType);
  Serial.print(F("   Byte 4 dec: "));
  Serial.print(RXBytes[4]);
  Serial.print(F("   Byte 4  hex: "));
  Serial.print(RXBytes[4], HEX);
  Serial.print(F("   Byte 6 dec: "));
  Serial.print(RXBytes[6]);
  Serial.print(F("   Byte 6  hex: "));
  Serial.print(RXBytes[6], HEX);
  Serial.print(F("   Pressure bits dec: "));
  Serial.print(pressure1);
  Serial.print(F("   Pressure bits hex: "));
  Serial.print(pressure1, HEX);  
  Serial.println(F(""));
#endif

  //DisplayStatusInfo();

   MatchIDandUpdate(id,status, realtemp, realpressure);
   

  #ifdef SHOWVALIDTPMS
     Serial.println(F(""));
  #endif


  //UpdateDisplay();
}






void ConvertTimingsToBits()
{
   int i;
   
   //bool CurrentState = FirstEdgeState;
   bool CurrentState = FirstEdgeIsHighToLow?true:false;
   BitCount = 0;
   

   for (i=0;i<= TimingsIndex;i++)
   {
      if (IsValidShort(Timings[i]) )
      {
         IncomingBits[BitCount++] = CurrentState;
      }
      else
      {
        if (IsValidLong(Timings[i]) )
        {
           IncomingBits[BitCount++] = CurrentState;
           IncomingBits[BitCount++] = CurrentState;
        }
        else
        {
          if (IsTooShort(Timings[i] ) || IsTooLong(Timings[i] ) )
          {
            
             if (i < TimingsIndex/2)  //enough bits in the buffer to continue trying?
             { //invalid bit timing, reset
                 
                 BitCount = 0;
             }
             else
             {// end the conversion
                //assume an end bit
                if (IsTooLong(Timings[i]) )
                {
                  IncomingBits[BitCount++] = CurrentState;
                }
//                #ifdef SHOWDEBUGINFO
//                   Serial.print(F("ConvertTimingsToBits exited at index: "));
//                   Serial.print(i);
//                   Serial.print(F(" bitcount: "));
//                   Serial.print(BitCount);
//                   Serial.print(F("  Timing value = "));
//                   Serial.println(Timings[i]);
//                #endif
                return;
             }
          }
        }
      }
      CurrentState = !CurrentState;

      if (BitCount >= MAXBITS-1) 
      {
         #ifdef SHOWDEBUGINFO
            Serial.println(F("Exited ConvertTimingsToBits with botcount > MAXBITS-1"));
         #endif
         return;
      }
   }
  
}



bool ValidateTimings()
{


  byte BitWidth;
  byte BitWidthNext;
  byte BitWidthNextPlus1;
  byte BitWidthPrevious;
  byte diff = TimingsIndex - CheckIndex;
  //unsigned long tmp;
  bool WaitingTrailingZeroEdge = false;
  int ret;
  int ManchesterStartPos = -1;
  byte ByteCount = 0;
  byte crcResult;

  StartDataIndex = 0;

  if (TimingsIndex < (SYNCBITS + EXPECTEDBITCOUNT) ) //header + valid data (minimum)
  { //not enough in the buffer to consider a valid message
    #ifdef SHOWDEBUGINFO
       Serial.println(F("Insufficient data in buffer"));
    #endif
    return (false);
  }

  if (TimingsIndex > 200)  //header + valid data (minimum)
  { //not enough in the buffer to consider a valid message
    #ifdef SHOWDEBUGINFO
       Serial.println(F("Excessive data in buffer"));
    #endif
    return (false);
  }

  //Serial.print("Timings index = ");
  //Serial.println(TimingsIndex);

  ConvertTimingsToBits();

  InvertBitBuffer();
   
  const uint8_t pattern[] = {0xAA, 0xA9};
  ManchesterStartPos = FindManchesterStart(pattern, 16);
  StartDataIndex = ManchesterStartPos;

  if (ManchesterStartPos == -1 )
  {
    #ifdef SHOWDEBUGINFO
       Serial.println(F("Header not found"));
    #endif

    return (false);   
//  }
//  else
//  {
//     #ifdef SHOWDEBUGINFO
//       Serial.print("Timings index = ");
//       Serial.println(TimingsIndex);
//       Serial.print("CD Width = ");
//       Serial.println(CD_Width);
//       Serial.print("Bit count = ");
//       Serial.println(BitCount);
//       PrintTimings(0,TimingsIndex);
//       PrintData(BitCount);
//    #endif 
  }

  ByteCount = ManchesterDecode(ManchesterStartPos);
  if (ByteCount >= EXPECTEDBYTECOUNT)
  {
      
      //check the checksum...
      crcResult = Compute_CRC_SUM(0,7,  0x00);
      if (crcResult != RXBytes[7])
      {
         #ifdef SHOWDEBUGINFO
          Serial.print(F("CRC calc: "));
          Serial.print(crcResult, HEX);
          Serial.print(F("  CRC rcvd: "));
          Serial.println(RXBytes[7], HEX);
          Serial.println(F("CRC Check failed"));
        #endif
        #ifdef IGNORECHECKSUMERRORS
          DecodeTPMS();
          TPMS_Changed = false;  //don't update display for csum error
        #endif
        return(false);
      }
      else
      {
         #ifdef SHOWDEBUGINFO
           Serial.println(F("CRC Check OK"));
         #endif
        //decode the message...
        DecodeTPMS();
        TPMS_Changed = true;  //indicates the display needs to be updated.
        return(true);
      }


  }
  else
  {
    #ifdef SHOWDEBUGINFO
       Serial.print(F("Insufficient bytes: "));
       Serial.print(ByteCount);
       Serial.print(F(" received, expected at least: "));
       Serial.println(EXPECTEDBYTECOUNT);
       PrintTimings(0,ByteCount * 8);
    #endif
    return (false);
  }


}

Jansite

C Header File
#ifdef UK_433MHz


    #define EXPECTEDBITCOUNT 56
    #define EXPECTEDBYTECOUNT 7
    
    #define SYNCBITS 16
    
    #define CDWIDTH_MIN 30000
    #define CDWIDTH_MAX 31000
  
    #define SHORTTIMING_MIN 35
    #define SHORTTIMING_MAX 79
    #define LONGTIMING_MIN 80
    #define LONGTIMING_MAX 120
    #define SYNCTIMING_MIN 175
    #define SYNCTIMING_MAX 1200
    
    #define ENDTIMING_MIN  0
    #define ENDTIMING_MAX  0



    #define CC1101_DEFVAL_IOCFG2     0x0C        // GDO2 Output Pin Configuration - Serial out (synchronous)
    #define CC1101_DEFVAL_IOCFG1     0x2E        // GDO1 Output Pin Configuration - not used
    #define CC1101_DEFVAL_IOCFG0     0x0E        // GDO0 Output Pin Configuration - Carrier Sense output
    #define CC1101_DEFVAL_FIFOTHR    0x0F        // RX FIFO and TX FIFO Thresholds - 64 bytes in FIFO
    #define CC1101_DEFVAL_SYNC1      0xD5        // Synchronization word, high byte  11010101 01001111
    #define CC1101_DEFVAL_SYNC0      0x4F        // Synchronization word, low byte
    #define CC1101_DEFVAL_PKTLEN     0x09        // Packet Length
    #define CC1101_DEFVAL_PKTCTRL1   0x00        // Packet Automation Control
    #define CC1101_DEFVAL_PKTCTRL0   0x12 //0x30        // Packet Automation Control - synchronous data
    #define CC1101_DEFVAL_ADDR       0x00        // Device Address
    #define CC1101_DEFVAL_CHANNR     0x00        // Channel Number
    #define CC1101_DEFVAL_FSCTRL1    0x0F        // Frequency Synthesizer Control (was 0x06)
    #define CC1101_DEFVAL_FSCTRL0    0x00        // Frequency Synthesizer Control
    
    // Carrier frequency = 433.919830 MHz
    #define CC1101_DEFVAL_FREQ2  0x10        // Frequency Control Word, High Byte
    #define CC1101_DEFVAL_FREQ1  0xB0        // Frequency Control Word, Middle Byte
    #define CC1101_DEFVAL_FREQ0  0x71        // Frequency Control Word, Low Byte

    #define CC1101_DEFVAL_DEVIATN    0x40      // Modem Deviation Setting (+/-25.390625kHz)

    #define CC1101_DEFVAL_MDMCFG4    0x59        // Modem Configuration (59 = data rate = 20kHz - actual data rate is 10kHz but due to bi-phase coding need to double the rate, RX bandwidth 325kHz)
    #define CC1101_DEFVAL_MDMCFG3    0x93        // Modem Configuration (now 93 = data rate = 20kHz)
    #define CC1101_DEFVAL_MDMCFG2    0x10        // Modem Configuration (GFSK, No Sync or Manchester coding)
    #define CC1101_DEFVAL_MDMCFG1    0x21        // Modem Configuration Channel spacing 100kHz
    #define CC1101_DEFVAL_MDMCFG0    0xF8        // Modem Configuration      
    #define CC1101_DEFVAL_AGCCTRL2   0x87       // AGC Control
    #define CC1101_DEFVAL_AGCCTRL1   0x58        // AGC Control
    #define CC1101_DEFVAL_AGCCTRL0   0x80        // AGC Control
    
    #define CC1101_DEFVAL_MCSM2      0x07        // Main Radio Control State Machine Configuration
    #define CC1101_DEFVAL_MCSM1      0x3C        // Main Radio Control State Machine Configuration
    #define CC1101_DEFVAL_MCSM0      0x18        // Main Radio Control State Machine Configuration
    #define CC1101_DEFVAL_FOCCFG     0x16        // Frequency Offset Compensation Configuration
    #define CC1101_DEFVAL_BSCFG      0x6C        // Bit Synchronization Configuration

    
    #define CC1101_DEFVAL_WOREVT1    0x87        // High Byte Event0 Timeout
    #define CC1101_DEFVAL_WOREVT0    0x6B        // Low Byte Event0 Timeout
    #define CC1101_DEFVAL_WORCTRL    0xFB        // Wake On Radio Control
    #define CC1101_DEFVAL_FREND1     0x56        // Front End RX Configuration
    #define CC1101_DEFVAL_FREND0     0x10        // Front End TX Configuration
    
    #define CC1101_DEFVAL_FSCAL3     0xE9        // Frequency Synthesizer Calibration
    #define CC1101_DEFVAL_FSCAL2     0x2A        // Frequency Synthesizer Calibration
    #define CC1101_DEFVAL_FSCAL1     0x00        // Frequency Synthesizer Calibration
    #define CC1101_DEFVAL_FSCAL0     0x1F        // Frequency Synthesizer Calibration
    
    #define CC1101_DEFVAL_RCCTRL1    0x41        // RC Oscillator Configuration
    #define CC1101_DEFVAL_RCCTRL0    0x00        // RC Oscillator Configuration
    
    #define CC1101_DEFVAL_FSTEST     0x59        // Frequency Synthesizer Calibration Control
    
    #define CC1101_DEFVAL_PTEST      0x7F        // Production Test
    #define CC1101_DEFVAL_AGCTEST    0x3F        // AGC Test
    
    #define CC1101_DEFVAL_TEST2      0x81        // Various Test Settings
    #define CC1101_DEFVAL_TEST1      0x35        // Various Test Settings
    #define CC1101_DEFVAL_TEST0      0x09        // Various Test Settings



      
 
#elif US_315MHz


  #error Jansite timings not defined for 315MHz

#endif


void DecodeTPMS()
{
  int i;
  unsigned long id = 0;
  unsigned int status, pressure1, pressure2, temp;
   double realpressure;
  float realtemp;
  bool IDFound = false;


  for (i = 0; i <= 3; i++)
  {
    id = id << 8;
    id = id + RXBytes[i];

  }
  id = (id >> 4) & 0xFFFFFFFL;
  GetPreferredIndexStr(id, Ref);

  // id = (unsigned)RXBytes[0] << 24 | RXBytes[1] << 16 | RXBytes[2] << 8 | RXBytes[3];

  status = RXBytes[3] & 0x0F;

  pressure1 = RXBytes[4];

  temp = RXBytes[5];

  pressure2 = pressure1;



  if (pressure1 != pressure2)
  {
    #ifdef SHOWDEBUGINFO
       Serial.println(F("Pressure check mis-match"));
    #endif
    return;
  }

  realpressure = pressure1 * 1.7;  //kpa
  realpressure = realpressure * 0.145038;  //psi
  realtemp = temp - 50.0;
//  #ifdef DISPLAY_TEMP_AS_FAHRENHEIT
//     realtemp = ((realtemp * 9.0)/5.0) + 32.0;
//  #endif
  
  //realtemp = (temp - 32.0) * 0.5555556;

#ifdef SHOWVALIDTPMS
  Serial.print(F("Pos: "));
  Serial.print(Ref);
  Serial.print(F("   ID: "));
  Serial.print(id, HEX);
  Serial.print(F("   Status????: 0x"));
  Serial.print(status,HEX);
  Serial.print(F("   Temperature????: "));
  Serial.print(realtemp);
  Serial.print(F("   Tyre Pressure????: "));
  Serial.print(realpressure);
  Serial.println(F(""));
#endif

  //DisplayStatusInfo();
  MatchIDandUpdate(id,status, realtemp, realpressure);
  
 
  #ifdef SHOWVALIDTPMS
     Serial.println(F(""));
  #endif


  //UpdateDisplay();
}






void ConvertTimingsToBits()
{
   int i;
   
   //bool CurrentState = FirstEdgeState;
   bool CurrentState = FirstEdgeIsHighToLow?true:false;
   BitCount = 0;
   

   for (i=0;i<= TimingsIndex;i++)
   {
      if (IsValidShort(Timings[i]) )
      {
         IncomingBits[BitCount++] = CurrentState;
      }
      else
      {
        if (IsValidLong(Timings[i]) )
        {
           IncomingBits[BitCount++] = CurrentState;
           IncomingBits[BitCount++] = CurrentState;
        }
        else
        {
          if (IsTooShort(Timings[i] ) || IsTooLong(Timings[i] ) )
          {
            
             if (i < TimingsIndex/2)  //enough bits in the buffer to continue trying?
             { //invalid bit timing, reset
                 
                 BitCount = 0;
             }
             else
             {// end the conversion
                //assume an end bit
                if (IsTooLong(Timings[i]) )
                {
                  IncomingBits[BitCount++] = CurrentState;
                }
//                #ifdef SHOWDEBUGINFO
//                   Serial.print(F("ConvertTimingsToBits exited at index: "));
//                   Serial.print(i);
//                   Serial.print(F(" bitcount: "));
//                   Serial.print(BitCount);
//                   Serial.print(F("  Timing value = "));
//                   Serial.println(Timings[i]);
//                #endif
                return;
             }
          }
        }
      }
      CurrentState = !CurrentState;

      if (BitCount >= MAXBITS-1) 
      {
         #ifdef SHOWDEBUGINFO
            Serial.println(F("Exited ConvertTimingsToBits with botcount > MAXBITS-1"));
         #endif
         return;
      }
   }
  
}



bool ValidateTimings()
{


  byte BitWidth;
  byte BitWidthNext;
  byte BitWidthNextPlus1;
  byte BitWidthPrevious;
  byte diff = TimingsIndex - CheckIndex;
  //unsigned long tmp;
  bool WaitingTrailingZeroEdge = false;
  int ret;
  int ManchesterStartPos = -1;
  byte ByteCount = 0;
  byte crcResult;

  StartDataIndex = 0;

  if (TimingsIndex < (SYNCBITS + EXPECTEDBITCOUNT) ) //header + valid data (minimum)
  { //not enough in the buffer to consider a valid message
    #ifdef SHOWDEBUGINFO
       Serial.println(F("Insufficient data in buffer"));
    #endif
    return (false);
  }

//  if (TimingsIndex > 200)  //header + valid data (minimum)
//  { //not enough in the buffer to consider a valid message
//    #ifdef SHOWDEBUGINFO
//       Serial.println(F("Excessive data in buffer"));
//    #endif
//    return (false);
//  }

  //Serial.print("Timings index = ");
  //Serial.println(TimingsIndex);

  ConvertTimingsToBits();

  InvertBitBuffer();

  const uint8_t pattern[] = {0xAA,0xAA, 0xA9};
  ManchesterStartPos = FindManchesterStart(pattern, 24);
  StartDataIndex = ManchesterStartPos;

  if (ManchesterStartPos == -1 )
  {
    #ifdef SHOWDEBUGINFO
       Serial.println(F("Header not found"));
    #endif

    return (false);   
//  }
//  else
//  {
//     #ifdef SHOWDEBUGINFO
//       Serial.print("Timings index = ");
//       Serial.println(TimingsIndex);
//       Serial.print("CD Width = ");
//       Serial.println(CD_Width);
//       Serial.print("Bit count = ");
//       Serial.println(BitCount);
//       PrintTimings(0,TimingsIndex);
//       PrintData(BitCount);
//    #endif 
  }

  ByteCount = ManchesterDecode(ManchesterStartPos);
  if (ByteCount >= EXPECTEDBYTECOUNT)
  {
      
      //check the checksum...
      crcResult = Compute_CRC_SUM(0,6,  0x00);
      if (crcResult != RXBytes[6])
      {
         #ifdef SHOWDEBUGINFO
          Serial.print(F("CRC calc: "));
          Serial.print(crcResult, HEX);
          Serial.print(F("  CRC rcvd: "));
          Serial.println(RXBytes[6], HEX);
          Serial.println(F("CRC Check failed"));
          PrintBytes(7);
          #endif
        #ifdef IGNORECHECKSUMERRORS
          DecodeTPMS();
          TPMS_Changed = false;  //don't update display for csum error
        #endif
        return(false);
      }
      else
      {
         #ifdef SHOWDEBUGINFO
           Serial.println(F("CRC Check OK"));
         #endif
        //decode the message...
        DecodeTPMS();
        TPMS_Changed = true;  //indicates the display needs to be updated.
        return(true);
      }


  }
  else
  {
    #ifdef SHOWDEBUGINFO
       Serial.print(F("Insufficient bytes: "));
       Serial.print(ByteCount);
       Serial.print(F(" received, expected at least: "));
       Serial.println(EXPECTEDBYTECOUNT);
       PrintTimings(0,ByteCount * 8);
    #endif
    return (false);
  }


}

JansiteSolar

C Header File
#ifdef UK_433MHz

    
    #define EXPECTEDBITCOUNT 88
    #define EXPECTEDBYTECOUNT 11
    
    #define SYNCBITS 24
    
    #define CDWIDTH_MIN 20000
    #define CDWIDTH_MAX 25000
    
    #define SHORTTIMING_MIN 35
    #define SHORTTIMING_MAX 79
    #define LONGTIMING_MIN 80
    #define LONGTIMING_MAX 120
    #define SYNCTIMING_MIN 175
    #define SYNCTIMING_MAX 1200
    
    #define ENDTIMING_MIN  0
    #define ENDTIMING_MAX  0


    #define CC1101_DEFVAL_IOCFG2     0x0C        // GDO2 Output Pin Configuration - Serial out (synchronous)
    #define CC1101_DEFVAL_IOCFG1     0x2E        // GDO1 Output Pin Configuration - not used
    #define CC1101_DEFVAL_IOCFG0     0x0E        // GDO0 Output Pin Configuration - Carrier Sense output
    #define CC1101_DEFVAL_FIFOTHR    0x0F        // RX FIFO and TX FIFO Thresholds - 64 bytes in FIFO
    #define CC1101_DEFVAL_SYNC1      0xD5        // Synchronization word, high byte  11010101 01001111
    #define CC1101_DEFVAL_SYNC0      0x4F        // Synchronization word, low byte
    #define CC1101_DEFVAL_PKTLEN     0x09        // Packet Length
    #define CC1101_DEFVAL_PKTCTRL1   0x00        // Packet Automation Control
    #define CC1101_DEFVAL_PKTCTRL0   0x12 //0x30        // Packet Automation Control - synchronous data
    #define CC1101_DEFVAL_ADDR       0x00        // Device Address
    #define CC1101_DEFVAL_CHANNR     0x00        // Channel Number
    #define CC1101_DEFVAL_FSCTRL1    0x0F        // Frequency Synthesizer Control (was 0x06)
    #define CC1101_DEFVAL_FSCTRL0    0x00        // Frequency Synthesizer Control
    
    // Carrier frequency = 433.919830 MHz
    #define CC1101_DEFVAL_FREQ2  0x10        // Frequency Control Word, High Byte
    #define CC1101_DEFVAL_FREQ1  0xB0        // Frequency Control Word, Middle Byte
    #define CC1101_DEFVAL_FREQ0  0x71        // Frequency Control Word, Low Byte

    #define CC1101_DEFVAL_DEVIATN    0x40      // Modem Deviation Setting (+/-25.390625kHz)

    #define CC1101_DEFVAL_MDMCFG4    0x59        // Modem Configuration (59 = data rate = 20kHz - actual data rate is 10kHz but due to bi-phase coding need to double the rate, RX bandwidth 325kHz)
    #define CC1101_DEFVAL_MDMCFG3    0x93        // Modem Configuration (now 93 = data rate = 20kHz)
    #define CC1101_DEFVAL_MDMCFG2    0x10        // Modem Configuration (GFSK, No Sync or Manchester coding)
    #define CC1101_DEFVAL_MDMCFG1    0x21        // Modem Configuration Channel spacing 100kHz
    #define CC1101_DEFVAL_MDMCFG0    0xF8        // Modem Configuration      
    #define CC1101_DEFVAL_AGCCTRL2   0x87       // AGC Control
    #define CC1101_DEFVAL_AGCCTRL1   0x58        // AGC Control
    #define CC1101_DEFVAL_AGCCTRL0   0x80        // AGC Control
    
    #define CC1101_DEFVAL_MCSM2      0x07        // Main Radio Control State Machine Configuration
    #define CC1101_DEFVAL_MCSM1      0x3C        // Main Radio Control State Machine Configuration
    #define CC1101_DEFVAL_MCSM0      0x18        // Main Radio Control State Machine Configuration
    #define CC1101_DEFVAL_FOCCFG     0x16        // Frequency Offset Compensation Configuration
    #define CC1101_DEFVAL_BSCFG      0x6C        // Bit Synchronization Configuration

    
    #define CC1101_DEFVAL_WOREVT1    0x87        // High Byte Event0 Timeout
    #define CC1101_DEFVAL_WOREVT0    0x6B        // Low Byte Event0 Timeout
    #define CC1101_DEFVAL_WORCTRL    0xFB        // Wake On Radio Control
    #define CC1101_DEFVAL_FREND1     0x56        // Front End RX Configuration
    #define CC1101_DEFVAL_FREND0     0x10        // Front End TX Configuration
    
    #define CC1101_DEFVAL_FSCAL3     0xE9        // Frequency Synthesizer Calibration
    #define CC1101_DEFVAL_FSCAL2     0x2A        // Frequency Synthesizer Calibration
    #define CC1101_DEFVAL_FSCAL1     0x00        // Frequency Synthesizer Calibration
    #define CC1101_DEFVAL_FSCAL0     0x1F        // Frequency Synthesizer Calibration
    
    #define CC1101_DEFVAL_RCCTRL1    0x41        // RC Oscillator Configuration
    #define CC1101_DEFVAL_RCCTRL0    0x00        // RC Oscillator Configuration
    
    #define CC1101_DEFVAL_FSTEST     0x59        // Frequency Synthesizer Calibration Control
    
    #define CC1101_DEFVAL_PTEST      0x7F        // Production Test
    #define CC1101_DEFVAL_AGCTEST    0x3F        // AGC Test
    
    #define CC1101_DEFVAL_TEST2      0x81        // Various Test Settings
    #define CC1101_DEFVAL_TEST1      0x35        // Various Test Settings
    #define CC1101_DEFVAL_TEST0      0x09        // Various Test Settings



      
 
#elif US_315MHz


     #error Jansite Solar timings not defined for 315MHz


#endif

void DecodeTPMS()
{
  int i;
  unsigned long id = 0;
  unsigned int status, pressure1, pressure2, temp;
   double realpressure;
  float realtemp;
  bool IDFound = false;


  for (i = 0; i <= 3; i++)
  {
    id = id << 8;
    id = id + RXBytes[i];

  }
  id = (id >> 4) & 0xFFFFFFFL;
  GetPreferredIndexStr(id, Ref);
  

  // id = (unsigned)RXBytes[0] << 24 | RXBytes[1] << 16 | RXBytes[2] << 8 | RXBytes[3];

  status = RXBytes[3] & 0x0F;

  pressure1 = RXBytes[4];

  temp = RXBytes[5];

  pressure2 = pressure1;



  if (pressure1 != pressure2)
  {
    #ifdef SHOWDEBUGINFO
       Serial.println(F("Pressure check mis-match"));
    #endif
    return;
  }

  realpressure = pressure1 * 1.7;  //kpa
  realpressure = realpressure * 0.145038;  //psi
  realtemp = temp - 50.0;
//  #ifdef DISPLAY_TEMP_AS_FAHRENHEIT
//     realtemp = ((realtemp * 9.0)/5.0) + 32.0;
//  #endif  
  //realtemp = (temp - 32.0) * 0.5555556;

#ifdef SHOWVALIDTPMS
  Serial.print(F("Pos: "));
  Serial.print(Ref);
  Serial.print(F("   ID: "));
  Serial.print(id, HEX);
  Serial.print(F("   Status????: 0x"));
  Serial.print(status,HEX);
  Serial.print(F("   Temperature????: "));
  Serial.print(realtemp);
  Serial.print(F("   Tyre Pressure????: "));
  Serial.print(realpressure);
  Serial.println(F(""));
#endif

  //DisplayStatusInfo();


  MatchIDandUpdate(id,status, realtemp, realpressure);

  #ifdef SHOWVALIDTPMS
     Serial.println(F(""));
  #endif


  //UpdateDisplay();
}





void ConvertTimingsToBits()
{
   int i;
   
   //bool CurrentState = FirstEdgeState;
   bool CurrentState = FirstEdgeIsHighToLow?true:false;
   BitCount = 0;
   

   for (i=0;i<= TimingsIndex;i++)
   {
      if (IsValidShort(Timings[i]) )
      {
         IncomingBits[BitCount++] = CurrentState;
      }
      else
      {
        if (IsValidLong(Timings[i]) )
        {
           IncomingBits[BitCount++] = CurrentState;
           IncomingBits[BitCount++] = CurrentState;
        }
        else
        {
          if (IsTooShort(Timings[i] ) || IsTooLong(Timings[i] ) )
          {
            
             if (i < TimingsIndex/2)  //enough bits in the buffer to continue trying?
             { //invalid bit timing, reset
                 
                 BitCount = 0;
             }
             else
             {// end the conversion
                //assume an end bit
                if (IsTooLong(Timings[i]) )
                {
                  IncomingBits[BitCount++] = CurrentState;
                }
//                #ifdef SHOWDEBUGINFO
//                   Serial.print(F("ConvertTimingsToBits exited at index: "));
//                   Serial.print(i);
//                   Serial.print(F(" bitcount: "));
//                   Serial.print(BitCount);
//                   Serial.print(F("  Timing value = "));
//                   Serial.println(Timings[i]);
//                #endif
                return;
             }
          }
        }
      }
      CurrentState = !CurrentState;

      if (BitCount >= MAXBITS-1) 
      {
         #ifdef SHOWDEBUGINFO
            Serial.println(F("Exited ConvertTimingsToBits with botcount > MAXBITS-1"));
         #endif
         return;
      }
   }
  
}



bool ValidateTimings()
{


  byte BitWidth;
  byte BitWidthNext;
  byte BitWidthNextPlus1;
  byte BitWidthPrevious;
  byte diff = TimingsIndex - CheckIndex;
  //unsigned long tmp;
  bool WaitingTrailingZeroEdge = false;
  int ret;
  int ManchesterStartPos = -1;
  byte ByteCount = 0;
  byte crcResult;

  StartDataIndex = 0;

  if (TimingsIndex < (SYNCBITS + EXPECTEDBITCOUNT) ) //header + valid data (minimum)
  { //not enough in the buffer to consider a valid message
    #ifdef SHOWDEBUGINFO
       Serial.println(F("Insufficient data in buffer"));
    #endif
    return (false);
  }

//  if (TimingsIndex > 200)  //header + valid data (minimum)
//  { //not enough in the buffer to consider a valid message
//    #ifdef SHOWDEBUGINFO
//       Serial.println(F("Excessive data in buffer"));
//    #endif
//    return (false);
//  }

  //Serial.print("Timings index = ");
  //Serial.println(TimingsIndex);

  ConvertTimingsToBits();

  //InvertBitBuffer();

  const uint8_t pattern[] = {0xA6,0xA6, 0x5A};
  ManchesterStartPos = FindManchesterStart(pattern, 24);
  StartDataIndex = ManchesterStartPos;

  if (ManchesterStartPos == -1 )
  {
    #ifdef SHOWDEBUGINFO
       Serial.println(F("Header not found"));
    #endif

    return (false);   
//  }
//  else
//  {
//     #ifdef SHOWDEBUGINFO
//       Serial.print("Timings index = ");
//       Serial.println(TimingsIndex);
//       Serial.print("CD Width = ");
//       Serial.println(CD_Width);
//       Serial.print("Bit count = ");
//       Serial.println(BitCount);
//       PrintTimings(0,TimingsIndex);
//       PrintData(BitCount);
//    #endif 
  }

  ByteCount = ManchesterDecode(ManchesterStartPos);
  if (ByteCount >= EXPECTEDBYTECOUNT)
  {
      
      //check the checksum...
      crcResult = Compute_CRC_SUM(0,6,  0x00);
      if (crcResult != RXBytes[6])
      {
         #ifdef SHOWDEBUGINFO
          Serial.print(F("CRC calc: "));
          Serial.print(crcResult, HEX);
          Serial.print(F("  CRC rcvd: "));
          Serial.println(RXBytes[6], HEX);
          Serial.println(F("CRC Check failed"));
          PrintBytes(7);
          #endif
        #ifdef IGNORECHECKSUMERRORS
          DecodeTPMS();
          TPMS_Changed = false;  //don't update display for csum error
        #endif
        return(false);
      }
      else
      {
         #ifdef SHOWDEBUGINFO
           Serial.println(F("CRC Check OK"));
         #endif
        //decode the message...
        DecodeTPMS();
        TPMS_Changed = true;  //indicates the display needs to be updated.
        return(true);
      }


  }
  else
  {
    #ifdef SHOWDEBUGINFO
       Serial.print(F("Insufficient bytes: "));
       Serial.print(ByteCount);
       Serial.print(F(" received, expected at least: "));
       Serial.println(EXPECTEDBYTECOUNT);
       PrintTimings(0,ByteCount * 8);
    #endif
    return (false);
  }


}

bitmap

C Header File
Background car image used on ST7735 display
// '128x60 car', 160x128px
const unsigned char car_bmp_128x60_car [] 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0xff, 0x20, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x3f, 0xff, 0xc8, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x04, 0x7f, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x18, 0x7f, 0xff, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xff, 0xff, 0xf0, 0x80, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 
  0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x5f, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x9f, 0xff, 0xdf, 0xd0, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0xff, 0xef, 
  0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x7e, 0xff, 0xff, 0xf7, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xf7, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x7f, 0xff, 0xff, 0xff, 
  0xf7, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 
  0x7f, 0xff, 0xff, 0xff, 0xf7, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x1f, 0x7f, 0xff, 0xff, 0xff, 0xf7, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x7f, 0xff, 0xff, 0xff, 0xf7, 0xc0, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x7f, 0xff, 0xff, 0xff, 
  0xf7, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 
  0x7f, 0xff, 0xff, 0xff, 0xf7, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x1f, 0x7f, 0xff, 0xff, 0xff, 0xf7, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x7f, 0xf0, 0x00, 0xff, 0xf7, 0xc0, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x7f, 0xc0, 0x00, 0x3f, 
  0xe7, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 
  0x7f, 0x00, 0x00, 0x0f, 0xe7, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x1f, 0x7c, 0x00, 0x00, 0x03, 0xf7, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x7c, 0x00, 0x00, 0x01, 0xf7, 0xc0, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x78, 0x00, 0x00, 0x01, 
  0xf7, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x78, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x01, 
  0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x7c, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x7c, 0x00, 0x00, 0x01, 0xec, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xec, 0x00, 0x00, 0x01, 
  0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 
  0xec, 0x00, 0x00, 0x03, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x02, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x66, 0x00, 0x00, 0x06, 0x7e, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0xff, 0xff, 0xfe, 
  0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x67, 0xff, 0xff, 0xfe, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x63, 0xff, 0xff, 0xfe, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0xff, 0xff, 0xfe, 0x70, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0xff, 0xff, 0xfe, 
  0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x63, 0xff, 0xff, 0xfc, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x63, 0xff, 0xff, 0xfc, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0xff, 0xff, 0xfc, 0x70, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0xff, 0xff, 0xfc, 
  0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x63, 0xff, 0xff, 0xfc, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x63, 0xff, 0xff, 0xfc, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0xff, 0xff, 0xfc, 0x70, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0xff, 0xff, 0xfc, 
  0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x63, 0xff, 0xff, 0xfc, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x61, 0xff, 0xff, 0xfc, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0xff, 0xff, 0xf8, 0x60, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0xff, 0xff, 0xf8, 
  0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0xe3, 0xff, 0xff, 0xfc, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0xe3, 0xff, 0xff, 0xfc, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe3, 0xff, 0xff, 0xfc, 0x60, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe3, 0xff, 0xff, 0xfc, 
  0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 
  0x63, 0xff, 0xff, 0xfc, 0x67, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x1f, 0x73, 0xff, 0xff, 0xfc, 0xf7, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x7b, 0xff, 0xff, 0xfd, 0xf7, 0xc0, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x7f, 0xff, 0xff, 0xfd, 
  0xf7, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 
  0x7f, 0xff, 0xff, 0xff, 0xf7, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x1f, 0x7f, 0xff, 0xff, 0xff, 0xf7, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x7f, 0x80, 0x00, 0x1f, 0xf7, 0xc0, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x7f, 0x00, 0x00, 0x0f, 
  0xf7, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 
  0x7d, 0x00, 0x00, 0x09, 0xf7, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x1f, 0x7f, 0x00, 0x00, 0x0f, 0xf7, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x7f, 0x00, 0x00, 0x0f, 0xf7, 0xc0, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, <