JSMSolns
Created July 20, 2021

Arduino UK/US Toyota TPMS Monitor

Work in progress190
Arduino UK/US Toyota TPMS Monitor

Code

globals

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

//#define UK_433MHz 1
//#define Toyota_PMV_C210 1   //should also work for PMV-C010??

#define US_315MHz 1
#define Toyota_PMV_107J 1

//#define USE_BAR
#define SHOWVALIDTPMS 1
#define SHOWDEBUGINFO 1
//#define INCLUDESPARETYRE 1
#define IGNORECHECKSUMERRORS 1


#define I2C_ADDRESS 0x3C

#define LED_RX 17
#define LED_OFF HIGH
#define LED_ON LOW

#define TPMS_TIMEOUT 900000 //(15 * 60 * 1000)  15 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
  #define TYRECOUNT 5
#else
  #define TYRECOUNT 4
#endif

#define PSI2BAR 14.504

// hardware pin configuration
const int CC1101_CS = 10;  // Define the Chip Select pin
#ifdef ARDUINO_AVR_PROMICRO
   #define IsProMicro 1
   const int RXPin = 7;   //must be an ext interrupt pin
#elif ARDUINO_AVR_NANO
   #define IsNano 1
  const int RXPin = 2;   //must be an ext interrupt pin
#endif
const int CDPin = 9;  //if wired, define 'USE_HW_CD' above, otherwise CD pin status is received over SPI
const int DEBUGPIN = 6;

const int MAXBITS = 200;
const int MAXTIMINGS = 255;

//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 uint8_t TimingsIndex = 0;
uint8_t CheckIndex = 0;
bool SyncFound = false;
unsigned long CD_Width;
byte StartDataIndex = 0;
bool TPMS_Changed = false;


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

unsigned int FreqOffset;
unsigned int DemodLinkQuality;
int RSSIvalue;
unsigned int FreqOffsetAcc = 0;


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


//this table (and its order define known TPMS IDs so that they their values are always displayed in the same order
const unsigned long PROGMEM IDLookup[]
{
  0xF1721EB0, 0xF172221F, 
  0xF172223E, 0xF1721E9A, 0xFFFFFFFF
};



  ////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;
  float TPMS_Pressure;
  float TPMS_Temperature;
  int RSSIdBm;
} 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 
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
  };


#elif Toyota_PMV_107J

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
   };   

#endif

const int TestTimings_len = sizeof(TestTimings)/sizeof(TestTimings[0]);

Toyota_PMV_107J

C Header File
#define CDWIDTH_MIN 14500
#define CDWIDTH_MAX 16500
#define EXPECTEDBITCOUNT 66





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


  //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; 

 
  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 ;  //default to psi, kpa would be (pressure1 - 40.0) * 2.48
  realtemp = temp - 40.0;

#ifdef SHOWVALIDTPMS
  Serial.print(F("ID: "));
  Serial.print(id, HEX);
  Serial.print(F("   Status: "));
  Serial.print(status);
  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();

  //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..
      for (i = 0; i < TYRECOUNT; i++)
      {
        if (TPMS[i].TPMS_ID == 0)
        {
          UpdateTPMSData(i, id, status, realtemp, realpressure);
          break;
        }
      }
    }
    else
    { //found a match in the known ID list...
      UpdateTPMSData(prefindex, id, status, realtemp, realpressure);
    }

  }


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


  //UpdateDisplay();
}











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

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


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

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

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

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

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


  return (-1);

}


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;

  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(")");
    #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)
  {
    return(true);
  }
  else
  {
    return(false);
  }
  
}



int ReceiveMessage()
{

  //Check bytes in FIFO
  int FIFOcount;
  int resp;
  int lRSSI;
  bool StatusUpdated = true;
  byte crcResult;
  int ByteCount = 0;



#ifdef USE_TEST_TIMINGS  
  //test set up....
  CD_Width = CDWIDTH_MIN + ((CDWIDTH_MAX - CDWIDTH_MIN)/2);;
  //copy timings to timings array as if they've come from the interrupt
  for (TimingsIndex=0;TimingsIndex<TestTimings_len;TimingsIndex++)
  {
     Timings[TimingsIndex] = TestTimings[TimingsIndex];
  }

#else

  //set up timing of edges using interrupts...
  LastEdgeTime_us = micros();
  CD_Width = LastEdgeTime_us;

  attachInterrupt(digitalPinToInterrupt(RXPin), EdgeInterrupt, CHANGE);
  RSSIvalue = -1000;
  
  while (GetCarrierStatus() == true)
  {
//     if ((micros() - CD_Width) > 10000)
//     {
//        detachInterrupt(digitalPinToInterrupt(RXPin));
//        return(0);
//     }
          
     //get the maximum RSSI value seen during data receive window
     lRSSI = GetRSSI_dbm();
     if (lRSSI > RSSIvalue)
     {
       RSSIvalue = lRSSI;
     }
  }


  //digitalWrite(DEBUGPIN,LOW);
  delayMicroseconds(500);  //there is a delay on the serial data stream so ensure we allow a bit of extra time after CD finishes to ensure all the data is captured
  detachInterrupt(digitalPinToInterrupt(RXPin)); 
  CD_Width = micros() - CD_Width;

#endif

  if ((CD_Width >= CDWIDTH_MIN) && (CD_Width <= CDWIDTH_MAX))
  {
      PulseDebugPin(100);
    #ifdef SHOWDEBUGINFO
       Serial.println(F("Checking.."));
    #endif
    digitalWrite(LED_RX,LED_ON);
    CheckIndex = 0;
    ValidateTimings();
    #ifdef SHOWDEBUGINFO
       Serial.print(F("CD_Width="));
       Serial.println(CD_Width);
       Serial.print(F("TimingsIndex="));
       Serial.println(TimingsIndex);
       Serial.print(F("Checking complete. Bitcount: "));
       Serial.print(BitCount);
       Serial.print(F("  StartDataIndex: "));
       Serial.println(StartDataIndex);
       Serial.print(F(" RSSI(dBm):"));
       Serial.println(RSSIvalue);
       if (BitCount <= EXPECTEDBITCOUNT)
       {
          PrintTimings(0,TimingsIndex+1);
          PrintData(BitCount);
       }
    #endif

    if (BitCount >= EXPECTEDBITCOUNT )
    {
      ByteCount = DecodeBitArray(6);

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

      if (crcResult != RXBytes[8])
      {
        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"));
        //PrintData(BitCount);
        #ifdef IGNORECHECKSUMERRORS
          DecodeTPMS();
          TPMS_Changed = true;  //indicates the display needs to be updated.
        #endif
      }
      else
      {
        //decode the message...
        Serial.println(F("CRC Check OK"));
        DecodeTPMS();
        TPMS_Changed = true;  //indicates the display needs to be updated.
        
        //setIdleState();
        //UpdateFreqOffset();
        //setRxState();
      }
    }

    
    digitalWrite(LED_RX,LED_OFF);
    return (BitCount);
  }
  else
  {
    #ifdef SHOWDEBUGINFO
      if (CD_Width > CDWIDTH_MIN)
      {
       Serial.print(F("CD_Width*="));
       Serial.println(CD_Width);   
       Serial.print(F("TimingsIndex="));
       Serial.println(TimingsIndex);     
      }
    #endif
    return (0);
  }



}

Toyota_PMV_C210

C Header File
#define CDWIDTH_MIN 7600
#define CDWIDTH_MAX 9500
#define EXPECTEDBITCOUNT 72



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

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

  }

  // 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.0;
  realtemp = temp - 40.0;

#ifdef SHOWVALIDTPMS
  Serial.print(F("ID: "));
  Serial.print(id, HEX);
  Serial.print(F("   Status: "));
  Serial.print(status);
  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();

  //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..
      for (i = 0; i < TYRECOUNT; i++)
      {
        if (TPMS[i].TPMS_ID == 0)
        {
          UpdateTPMSData(i, id, status, realtemp, realpressure);
          break;
        }
      }
    }
    else
    { //found a match in the known ID list...
      UpdateTPMSData(prefindex, id, status, realtemp, realpressure);
    }

  }


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


  //UpdateDisplay();
}




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

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


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

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

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

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

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


  return (-1);

}


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;

  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(")");
    #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:
          SyncFound = true;
          BitIndex = 0;
          BitCount = 0;
          WaitingTrailingZeroEdge = false;
          StartDataIndex = CheckIndex + 1;
          break;
      }
    }
    CheckIndex++;
  }


  if (BitCount >= EXPECTEDBITCOUNT)
  {
    return(true);
  }
  else
  {
    return(false);
  }
  
}



int ReceiveMessage()
{

  //Check bytes in FIFO
  int FIFOcount;
  int resp;
  int lRSSI;
  bool StatusUpdated = true;
  byte crcResult;
  int ByteCount = 0;

#ifdef USE_TEST_TIMINGS  
  //test set up....
  CD_Width = CDWIDTH_MIN + ((CDWIDTH_MAX - CDWIDTH_MIN)/2);
  //copy timings to timings array as if they've come from the interrupt
  for (TimingsIndex=0;TimingsIndex<TestTimings_len;TimingsIndex++)
  {
     Timings[TimingsIndex] = TestTimings[TimingsIndex];
  }


#else



  //set up timing of edges using interrupts...
  LastEdgeTime_us = micros();
  CD_Width = LastEdgeTime_us;

  attachInterrupt(digitalPinToInterrupt(RXPin), EdgeInterrupt, CHANGE);
  RSSIvalue = -1000;
  
  while (GetCarrierStatus() == true)
  {
//     if ((micros() - CD_Width) > 10000)
//     {
//        detachInterrupt(digitalPinToInterrupt(RXPin));
//        return(0);
//     }
          
     //get the maximum RSSI value seen during data receive window
     lRSSI = GetRSSI_dbm();
     if (lRSSI > RSSIvalue)
     {
       RSSIvalue = lRSSI;
     }
  }


  //digitalWrite(DEBUGPIN,LOW);
  delayMicroseconds(500);  //there is a delay on the serial data stream so ensure we allow a bit of extra time after CD finishes to ensure all the data is captured
  detachInterrupt(digitalPinToInterrupt(RXPin)); 
  CD_Width = micros() - CD_Width;

#endif
  

  if ((CD_Width >= CDWIDTH_MIN) && (CD_Width <= CDWIDTH_MAX))
  {
      PulseDebugPin(100);
    #ifdef SHOWDEBUGINFO
       Serial.println(F("Checking.."));
    #endif
    digitalWrite(LED_RX,LED_ON);
    CheckIndex = 0;
    ValidateTimings();
    #ifdef SHOWDEBUGINFO
       Serial.print(F("CD_Width="));
       Serial.println(CD_Width);
       Serial.print(F("TimingsIndex="));
       Serial.println(TimingsIndex);
       Serial.print(F("Checking complete. Bitcount: "));
       Serial.print(BitCount);
       Serial.print(F("  StartDataIndex: "));
       Serial.println(StartDataIndex);
       Serial.print(F(" RSSI(dBm):"));
       Serial.println(RSSIvalue);
       if (BitCount <= EXPECTEDBITCOUNT)
       {
          PrintTimings(0,TimingsIndex+1);
          PrintData(BitCount);
       }
    #endif

    if (BitCount == EXPECTEDBITCOUNT )
    {
      ByteCount = DecodeBitArray(0);

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

      if (crcResult != RXBytes[8])
      {
        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"));
        #ifdef IGNORECHECKSUMERRORS
          DecodeTPMS();
          TPMS_Changed = true;  //indicates the display needs to be updated.
        #endif
        //PrintData(BitCount);
      }
      else
      {
        //decode the message...
        Serial.println(F("CRC Check OK"));
        DecodeTPMS();
        TPMS_Changed = true;  //indicates the display needs to be updated.
        
        //setIdleState();
        //UpdateFreqOffset();
        //setRxState();
      }
    }

    
    digitalWrite(LED_RX,LED_OFF);
    return (BitCount);
  }
  else
  {
//    #ifdef SHOWDEBUGINFO
//      if (CD_Width > CDWIDTH_MIN)
//      {
//       Serial.print(F("CD_Width*="));
//       Serial.println(CD_Width);   
//       Serial.print(F("TimingsIndex="));
//       Serial.println(TimingsIndex);     
//      }
//    #endif
    return (0);
  }



}

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  0x0C        // 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    0x43        // Modem Deviation Setting (+/-34.9kHz)



#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_AGCCTRL1   0x40        // AGC Control
#define CC1101_DEFVAL_AGCCTRL1   0x50        // 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)
// 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));
  digitalWrite(CC1101_CS, LOW);
}

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

  //delayMicroseconds(50);
  digitalWrite(CC1101_CS, HIGH);
  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
  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
  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_PKTLEN,  CC1101_DEFVAL_PKTLEN);
  writeReg(CC1101_PKTCTRL1,  CC1101_DEFVAL_PKTCTRL1);
  writeReg(CC1101_PKTCTRL0,  CC1101_DEFVAL_PKTCTRL0);

  // 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);

  // Set default carrier frequency = 433 MHz
#ifdef UK_433MHz
  //setCarrierFreq(carrierFreq);
  writeReg(CC1101_FREQ2,  CC1101_DEFVAL_FREQ2_433);
  writeReg(CC1101_FREQ1,  CC1101_DEFVAL_FREQ1_433);
  writeReg(CC1101_FREQ0,  CC1101_DEFVAL_FREQ0_433);
  writeReg(CC1101_DEVIATN,  CC1101_DEFVAL_DEVIATN_433);
  writeReg(CC1101_MDMCFG4,  CC1101_DEFVAL_MDMCFG4_433);
  writeReg(CC1101_MDMCFG3,  CC1101_DEFVAL_MDMCFG3_433);
#else
   #ifdef US_315MHz
     // US carrier frequency = 315 MHz
      writeReg(CC1101_FREQ2, CC1101_DEFVAL_FREQ2_315);
      writeReg(CC1101_FREQ1, CC1101_DEFVAL_FREQ1_315);
      writeReg(CC1101_FREQ0, CC1101_DEFVAL_FREQ0_315); 
      writeReg(CC1101_DEVIATN,  CC1101_DEFVAL_DEVIATN_315);
      writeReg(CC1101_MDMCFG4,  CC1101_DEFVAL_MDMCFG4_315);
      writeReg(CC1101_MDMCFG3,  CC1101_DEFVAL_MDMCFG3_315);
   #else
      //if nothing set, default to UK
      writeReg(CC1101_FREQ2,  CC1101_DEFVAL_FREQ2_433);
      writeReg(CC1101_FREQ1,  CC1101_DEFVAL_FREQ1_433);
      writeReg(CC1101_FREQ0,  CC1101_DEFVAL_FREQ0_433);
      writeReg(CC1101_DEVIATN,  CC1101_DEFVAL_DEVIATN_433);
      writeReg(CC1101_MDMCFG4,  CC1101_DEFVAL_MDMCFG4_433);
      writeReg(CC1101_MDMCFG3,  CC1101_DEFVAL_MDMCFG3_433);
   #endif
#endif


  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
  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
  delayMicroseconds(5);
  cc1101_Select();                      // Select CC1101
  delayMicroseconds(10);
  cc1101_Deselect();                    // Deselect CC1101
  delayMicroseconds(41);
  cc1101_Select();                      // Select CC1101

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

  cc1101_Deselect();                    // Deselect CC1101


}

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

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);
   }
}

Common

C Header File
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 > 8000)
    BitWidth = 8000;

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

}



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;
}

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;
  }
}

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;

}

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 PrintTimings(byte StartPoint, byte Count)
{
  byte i;
  for (i = 0; i < Count; i++)
  {
    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(byte Count)
{
  byte 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 InitTPMS()
{
  int i;

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

}

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

  if (index >= TYRECOUNT)
    return;

  TPMS[index].TPMS_ID = ID;
  TPMS[index].TPMS_Status = status;
  TPMS[index].lastupdated = millis();
  TPMS[index].TPMS_Temperature = Temperature;
  #ifdef USE_BAR
    TPMS[index].TPMS_Pressure = Pressure/PSI2BAR;
  #else
     TPMS[index].TPMS_Pressure = Pressure;
  #endif
  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);
}

boolean Check_TPMS_Timeouts()
{
   byte i;
   boolean ret = false;
    
    //clear any data not updated in the last 5 minutes
  for (i = 0; i < TYRECOUNT; i++)
  {
//    #ifdef SHOWDEBUGINFO
//      Serial.print(TPMS[i].TPMS_ID, HEX);
//      Serial.print(F("   "));
//    #endif

    if ((TPMS[i].TPMS_ID != 0) && (millis() - TPMS[i].lastupdated > TPMS_TIMEOUT))
    {
//      #ifdef SHOWDEBUGINFO
//         Serial.print(F("Clearing ID "));
//         Serial.println(TPMS[i].TPMS_ID, HEX);
//      #endif
      ClearTPMSData(i);
      ret = true;
    }

  }
  return(ret);
}



int DecodeBitArray( byte ShiftRightBitCount)
{
  //convert 1s and 0s array to byte array
  int i;
  int n = 0;
  byte b = 0;

  n = ShiftRightBitCount;  //pad with this number of 0s to the left
  RXByteCount = 0;
  
  for (i = 0; i < BitCount; i++)
  {
    b = b << 1;
    b = b + IncomingBits[i];
    n++;
    if (n == 8)
    {
      RXBytes[RXByteCount] = b;
      //Serial.print(RXBytes[RXByteCount],HEX);
      //Serial.print(" - ");
      RXByteCount++;
      n = 0;
      b = 0;
    }

  }
  //Serial.println("");
  return (RXByteCount);


}

display

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

#if USE_ADAFRUIT
   #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);
    display.println("Toyota TPMS Monitor");
    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();
  
  }
   
#else
   #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);
    display.println("Toyota TPMS Monitor");
    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;
                      
      }
  }
  
  void UpdateDisplay()
  {
    int i;
    int x = 0;
    int y = 0;
    char s[6];
  
    ShowTitle();
  

  
    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 USE_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);
        display.print("C");
        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));
      }


    }
    
  
  }
#endif

UKUS_Toyota_TPMS_Monitor

Arduino
//Changes:
//V1.0 - Originally published version
//V2.0 - Altered to allow support for spare tyre reporting (although not displayed on LCD display)
//V3.0 - Added #define in globals.h to switch between BAR and PSI
//V4.0 - Now uses synchronous data from CC1101 and option of using either the SPI or the hardware pin for the CD signal (#define USE_HW_CD in globals.h). Also tideied up debug information if required (globals.h #defines)
//V5.0 - Corrected possible sync error when looking for start of data stream. Fix should improve hit rate on valid TPMS detection
//V5.1 - Added freq offset updates (SWRA159) - removed again(makes it worse!)
//V5.1.1 - Added functions for extracting RSSI as dbm
//V6.0 - Added code for options for US (315MHz) or UK (433MHz), also for different sensor types (PMV-C210, PMV-107J)


#define VERSION "6.0"
#define USE_LCDDISPLAY  1

#include <EEPROM.h>
#ifdef USE_LCDDISPLAY 
   #include <Wire.h>
#endif
#include <SPI.h>



#include "globals.h"

#include "CC1101.h"
#ifdef USE_LCDDISPLAY 
   #include "Display.h"
#endif
#include "Common.h"

//#include "ToyotaRead.h"
#ifdef Toyota_PMV_C210
   #include "Toyota_PMV_C210.h"
#else
   #ifdef Toyota_PMV_107J
      #include "Toyota_PMV_107J.h"
   #endif
#endif


void SendDebug(String Mess)
{
  Serial.println(Mess);
}




void setup() {

  byte resp;
  unsigned int t;
  int LEDState = LOW;
  int i;
  int mcount;

  //SPI CC1101 chip select set up
  pinMode(CC1101_CS, OUTPUT);
  digitalWrite(CC1101_CS, HIGH);


  Serial.begin(115200);



  pinMode(LED_RX, OUTPUT);
  pinMode(RXPin, INPUT);
  pinMode(CDPin, INPUT);


  SPI.begin();

  delay(2000);

  Serial.println("Starting...");
  #ifdef IsProMicro
     Serial.println("Arduino Pro Micro");
  #endif
  #ifdef IsNano
     Serial.println("Arduino Nano");
  #endif  

#ifdef USE_TEST_TIMINGS
   Serial.println("Warning: *****   BUILD FOR RUNNING HARD CODED TEST TIMES ONLY - NOT FOR REAL-TIME USE *****");
#endif
  
  //initialise the CC1101

  Serial.print(F("Resetting CC1101 "));
  byte retrycount = 0;
  while (retrycount < 5)
  {
     Serial.print(F("."));
     CC1101_reset();
     if (readConfigReg(0) == 0x29)
        break;
     retrycount++;
  }
  Serial.println("");

  if (readConfigReg(0) == 0x29)
  {
    Serial.println(F("CC1101 reset successful"));
  }
  else
  {
    Serial.println(F("CC1101 reset failed. Try rebooting"));
  }


  ConfigureCC1101();
  Serial.print(F("CC1101 configured for "));
  #ifdef US_315MHz
     Serial.print (F("US (315MHz)"));
  #else
     Serial.print (F("UK (433MHz)"));
  #endif

  #ifdef Toyota_PMV_C210
     Serial.println (F(" and PMV-C210 TPMS sensor"));
  #elif Toyota_PMV_107J
     Serial.println (F(" and PMV-107J TPMS sensor"));
  #endif

  setIdleState();
  digitalWrite(LED_RX, LED_OFF);

  resp = readStatusReg(CC1101_PARTNUM);
  Serial.print(F("Part no: "));
  Serial.println(resp, HEX);

  resp = readStatusReg(CC1101_VERSION);
  Serial.print(F("Version: "));
  Serial.println(resp, HEX);

#ifdef USE_LCDDISPLAY 
  #if USE_ADAFRUIT
    if (!display.begin(SSD1306_EXTERNALVCC, I2C_ADDRESS)) {
      Serial.println(F("SSD1306 allocation failed"));
      for (;;); // Don't proceed, loop forever
    }
  #else
    Wire.begin();
    Wire.setClock(400000L);
    display.begin(&Adafruit128x64, I2C_ADDRESS);
    display.setFont(Adafruit5x7);
  
  #endif
#endif



  Serial.println(F("SSD1306 initialised OK"));


  digitalWrite(LED_RX, LED_ON);
  LEDState = HIGH;

  pinMode(DEBUGPIN, OUTPUT);
  digitalWrite(DEBUGPIN, LOW);


  // Clear the buffer
#ifdef USE_LCDDISPLAY 
  #if USE_ADAFRUIT
    display.clearDisplay();
    display.display();
  #else
    display.clear();
  #endif
#endif

  InitTPMS();


  digitalWrite(LED_RX, LED_OFF);

  setRxState();
}

void loop() {
  // put your main code here, to run repeatedly:
  int i;
  static long lastts = millis();



  #ifdef USE_LCDDISPLAY
     TPMS_Changed = Check_TPMS_Timeouts();
  #endif

  InitDataBuffer();


#ifdef USE_TEST_TIMINGS 
    ReceiveMessage();

    #ifdef USE_LCDDISPLAY
      if (TPMS_Changed)
      {
        UpdateDisplay();
        TPMS_Changed = false;
      }
     #endif
     delay(10000);

#else
  //wait for carrier status to go low
  while (GetCarrierStatus() == true)
  {
  }

  //wait for carrier status to go high  looking for rising edge
  while (GetCarrierStatus() == false)
  {
  }

  if (GetCarrierStatus() == true)
  { //looks like some data coming in...
    ReceiveMessage();

    #ifdef USE_LCDDISPLAY
      if (TPMS_Changed)
      {
        UpdateDisplay();
        TPMS_Changed = false;
      }
    #endif
  }



#endif



}

Credits

JSMSolns
12 projects • 38 followers
Contact

Comments

Please log in or sign up to comment.