Hackster is hosting Impact Spotlights: Industrial Automation. Watch the stream live on Thursday!Hackster is hosting Impact Spotlights: Industrial Automation. Stream on Thursday!
JSMSolns
Created February 13, 2020 © GPL3+

Arduino TPMS Jansite (UK)

Monitor for Jansite TPMS sensors

Work in progress136
Arduino TPMS Jansite (UK)

Code

JansiteTPMSDecode

Arduino
#include <Wire.h>
#include <SPI.h>



#include "globals.h"
#include "CC1101.h"
#include "Display.h"
#include "JansiteRead.h"



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



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

  RXByteCount = 0;
  for (i = 0; i < BitCount; i++)
  {
    b = b << 1;
    b = b + IncomingBits[i];
    n++;
    if (n == 8)
    {
      RXBytes[RXByteCount] = b;
      RXByteCount++;
      n = 0;
      b = 0;
    }

  }
  return (RXByteCount);


}

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


  SPI.begin();
  //initialise the CC1101
  CC1101_reset();

  delay(2000);

  Serial.println("Starting...");



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


#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



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


  digitalWrite(LED_RX, LED_ON);
  LEDState = HIGH;

  pinMode(DEBUGPIN, OUTPUT);

#ifndef USE_PROGMEMCRC
  CalulateTable_CRC8();
#endif

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

  InitTPMS();


  digitalWrite(LED_RX, LED_OFF);

  setRxState();
}

void loop() {
  // put your main code here, to run repeatedly:
  int i;
  static long lastts = millis();
  float diff;
  int RXBitCount = 0;
  int ByteCount = 0;
  byte crcResult;



 // TPMS_Changed = Check_TPMS_Timeouts();

  InitDataBuffer();

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

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

//  if (TPMS_Changed)
//  {
//    UpdateDisplay();
//    TPMS_Changed = false;
//  }






}

//void loop() {
//  // put your main code here, to run repeatedly:
//  int i;
//  static long lastts = millis();
//  float diff;
//  int RXBitCount = 0;
//  int ByteCount = 0;
//  byte crcResult;
//  boolean TPMS_Changed;
//
//
//  TPMS_Changed = Check_TPMS_Timeouts();
//
//  InitDataBuffer();
//
//  //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...
//    RXBitCount = ReceiveMessage();
//    if (RXBitCount == 72 )
//    {
//      ByteCount = DecodeBitArray();
//
//      crcResult = Compute_CRC8(ByteCount);
//
//      if (crcResult != 0)
//      {
//        //Serial.print(F("CRC: "));
//        //Serial.println(crcResult, HEX);
//        //Serial.println(F("CRC Check failed"));
//        //PrintData(BitCount);
//      }
//      else
//      {
//        //decode the message...
//        DecodeTPMS();
//        TPMS_Changed = true;  //indicates the display needs to be updated.
//      }
//    }
//
//    if (TPMS_Changed)
//    {
//      UpdateDisplay();
//      TPMS_Changed = false;
//    }
//  }
//
//
//
//
//}

JansiteRead

C Header File
void EdgeInterrupt()
{
  unsigned long ts = micros();
  unsigned long BitTiming;

  if (TimingsIndex == 0)
  {
    //remember the state of the first entry (all other entries will assume to be toggled from this state)
    FirstEdgeState = !digitalRead(RXPin); //if this is a falling edge, the previous state must have been a high
  }

  if (TimingsIndex == MAXTIMINGS)
  {//buffer is full - don't accept further samples
    return;
  }


  BitTiming = ts - LastEdgeTime_us;
  if (BitTiming <= 12)  //ignore glitches
  {
    return;
  }
  if (BitTiming > 0xFFFF)  //timing vbalue exceeds the allocated sample size, so limit the value
    BitTiming = 0xFFFF;

  LastEdgeTime_us = ts;
  //    if ((BitWidth >= 38) && (BitWidth <= 250))
  //    {//ignore out of spec pulses
  Timings[TimingsIndex++] = (unsigned int)(BitTiming & 0xFFFF);
  //    }

  //    digitalWrite(DEBUGPIN,HIGH);
  //    delayMicroseconds(3);
  //    digitalWrite(DEBUGPIN,LOW);




}

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

  TPMS[i].TPMS_ID = 0;
  TPMS[i].lastupdated = 0;

}

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


int GetPreferredIndex(unsigned long ID)
{
  int i;

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

  }
  return (-1);
}



void PrintTimings(byte StartPoint,unsigned int Count)
{
  byte i;

  Serial.print("Initial state = ");
  Serial.println((FirstEdgeState ? "HIGH" : "LOW"));
  
  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 PrintBits(byte StartPoint, unsigned int Count)
{
  byte i;
  for (i = 0; i < Count; i++)
  {
    Serial.print(IncomingBits[StartPoint + i]);
    Serial.print(F(","));
  }
  Serial.println(F(""));
}

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 < 4; i++)
  {
    ClearTPMSData(i);
  }

  UpdateDisplay();

}

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

  if (index >= 4)
    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;
}



boolean Check_TPMS_Timeouts()
{
   byte i;
   boolean ret = false;
    
    //clear any data not updated in the last 5 minutes
  for (i = 0; i < 4; i++)
  {


    if ((TPMS[i].TPMS_ID != 0) && (millis() - TPMS[i].lastupdated > TPMS_TIMEOUT))
    {

      ClearTPMSData(i);
      ret = true;
    }

  }
  return(ret);
}

void DecodeTPMS_PMVC010()
{
  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 <= 3; 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)   ;

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

  Serial.println(F("Toyota PMV-C010"));
  Serial.print(F("ID: "));
  Serial.print(id, HEX);
  Serial.print(F("   Status: "));
  Serial.print(status);
  Serial.print(F("   Temperature (degC): "));
  Serial.print(realtemp, 1);
  Serial.print(F("   Tyre Pressure (kpa): "));
  Serial.print(realpressure * 6.895, 2);
  Serial.print(F("   Tyre Pressure (psi): "));
  Serial.print(realpressure, 2);
  Serial.println(F(""));


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

  }


  #ifdef SHOWDEGUGINFO
     //Serial.println(F(""));
  #endif

}

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 SHOWDEGUGINFO
  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.println(F(""));
//#endif

  //DisplayStatusInfo();

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

  }


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


  //UpdateDisplay();
}


#ifndef USE_PROGMEMCRC
  void CalulateTable_CRC8()
  {
    const byte generator = 0x07;
  
    /* iterate over all byte values 0 - 255 */
    for (int divident = 0; divident < 256; divident++)
    {
      byte currByte = (byte)divident;
      /* calculate the CRC-8 value for current byte */
      for (byte bit = 0; bit < 8; bit++)
      {
        if ((currByte & 0x80) != 0)
        {
          currByte <<= 1;
          currByte ^= generator;
        }
        else
        {
          currByte <<= 1;
        }
      }
      /* store CRC value in lookup table */
      crctable[divident] = currByte;
      Serial.print("0x");
      if (currByte < 16)
         Serial.print("0");
      Serial.print(currByte,HEX);
      Serial.print(", ");
    }
  }
#endif

byte Compute_CRC8( int bcount)
{
  byte crc = 0x80;
  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 */
    #ifdef USE_PROGMEMCRC
        crc = (byte)(pgm_read_byte(&crctable2[data]));
    #else
        crc = (byte)(crctable[data]);
    #endif

  }

  return crc;
}



void ClearRXBuffer()
{
  int i;

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


bool IsValidSync(byte Width)
{
  if (Width >=  175)
  {
    return (true);
  }
  else
  {
    return (false);
  }
}

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

bool IsValidShort(byte Width)
{
  if ((Width >= 35) && (Width <= 70))
  {
    return (true);
  }
  else
  {
    return (false);
  }
}

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

bool IsValidLong(byte Width)
{
  if ((Width >= 70) && (Width <= 120))
  {
    return (true);
  }
  else
  {
    return (false);
  }
}

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

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

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

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


  return (-1);

}

void ConvertTimingsToBits()
{
  int i, j, c;

  bool CurrentState = FirstEdgeState;
  bool ChangeState;

  BitCount = 0;


  for (i = 0; i <= TimingsIndex; i++)
  {
    ChangeState = true;
    if (IsValidShort(Timings[i]) )
    {
      IncomingBits[BitCount++] = CurrentState;
    }

    if (IsValidLong(Timings[i]) )
    {
      IncomingBits[BitCount++] = CurrentState;
      IncomingBits[BitCount++] = CurrentState;
    }

    if (IsTooShort(Timings[i]) )
    { //handle bits around the preamble
      if (BitCount >= 30)
      {
        return;
      }
      else
      {
        if (BitCount == 0)
        {
            ChangeState = true;
        }
        else
        {
            ChangeState = false;
        }
      }
    }

    if (IsTooLong(Timings[i]))
    { //handle bits around the preamble
      if (BitCount < 50)
      {
        c = (int)(Timings[i] / (48 ));
        for (j = 1; j <= c; j++)
        {
          IncomingBits[BitCount++] = CurrentState;
        }
      }
      else
      {
        return;
      }
    }

    if (ChangeState)
      CurrentState = !CurrentState;

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

}



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 SearchLimit, bool CheckInverse)
{
  int i;

  unsigned int ipos = 0;
  unsigned int ppos = 0; // cursor on init pattern
  int limit = BitCount - 3;

  if (SearchLimit < limit)
  {
    limit = SearchLimit;
  }

  while ((ipos < limit) && (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;
    }
  }

  if (CheckInverse)
  {
    ipos = 0;
    ppos = 0;

    while ((ipos < limit) && (ppos < pattern_bits_len))
    {
      if (IncomingBits[ipos] == (bit_at(pattern, ppos) ^ 1))
      {
        ppos++;
        ipos++;
        if (ppos == pattern_bits_len)
        {
          Serial.println("Found inverse pattern");
          return ipos;
        }
      }
      else
      {
        ipos -= ppos;
        ipos++;
        ppos = 0;
      }
    }
  }

  // Not found
  return -1;

}

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)
      return RXByteCount;

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

  }

  return RXByteCount;

}

int DiffManchesterDecode(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];


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

  }
  //Serial.print(F("RXByteCount: "));
  //Serial.println(RXByteCount);
  return RXByteCount;

}

bool ValidateTimings_PMVC010()
{


  byte BitWidth;
  byte BitWidthNext;
  byte BitWidthNextPlus1;
  byte BitWidthPrevious;
  //unsigned long tmp;
  bool WaitingTrailingZeroEdge = false;
  int ret;
  int ManchesterStartPos = -1;
  //    byte pattern[] = { 0xF0 };
  //    int pattern_bits_len = 7;
  byte pattern[] = { 0xCC, 0xAB };
  //byte pattern2[] = { 0x33, 0x54};
  int pattern_bits_len = 16;
  int MCount;



  if (TimingsIndex < 2 + 72)  //header + valid data (minimum)
  { //not enough in the buffer to consider a valid message
    Serial.println(F("Insufficient data in buffer"));
    return false;
  }

  ConvertTimingsToBits();

  //    ManchesterStartPos = FindManchesterStart(pattern, pattern_bits_len);  //look for 1111000
  //    if (ManchesterStartPos == -1)
  //    {
  //       //possible alternative...
  //       ManchesterStartPos = FindManchesterStart(pattern, pattern_bits_len-1);  //look for 111100
  //    }

  ManchesterStartPos = FindManchesterStart(pattern, pattern_bits_len, 100, true);  //look for 1100 1100 1010 1011  F1 (manchester encoded)
//  if (ManchesterStartPos == -1)
//  {
//    //possible alternative...
//    ManchesterStartPos = FindManchesterStart(pattern2, pattern_bits_len, 100, true);  //look for 0011 0011 0101 0100  inverse of F1 (manchester encoded)
//  }

  ManchesterStartPos = ManchesterStartPos - pattern_bits_len;  //move back to beginning of the bit pattern

  if (ManchesterStartPos < 0)
  {
    Serial.println(F("Sync header not found"));
    PrintBits(0,BitCount);
    return false;
  }

  MCount = DiffManchesterDecode(ManchesterStartPos);

  if (MCount >= 9)
  {
    return true;
  }
  else
  {
    Serial.print(F("Insufficient Manchester bytes: "));
    Serial.println(MCount);
    Serial.print(F("Message start: "));
    Serial.println(ManchesterStartPos);
    return false;
  }


}




void ValidateTimings()
{


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

  StartDataIndex = 0;

  if (diff < 72)
  { //not enough in the buffer to consider a valid message
    Serial.println(F("Insufficient data in buffer"));
    return;
  }

  SyncFound = true;

  while ((diff > 0) && (BitCount < 72))
  { //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;
          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;
          }
          else
          {
            //BitTimings[BitIndex] = BitWidth;
            IncomingBits[BitIndex++] = 1;
            BitCount++;
          }
          break;

        case 2:
          SyncFound = true;
          BitIndex = 0;
          BitCount = 0;
          WaitingTrailingZeroEdge = false;
          StartDataIndex = CheckIndex + 1;
          break;
      }
    }
    CheckIndex++;
  }


}



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

}

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

void UpdateStatusInfo()
{

  byte RSSI_Offset = 74;

  FreqOffset = readStatusReg(CC1101_FREQEST);
  DemodLinkQuality = readStatusReg(CC1101_LQI);
  RSSI_Read = readStatusReg(CC1101_RSSI);
  if (RSSI_Read >= 128)
  {
    RSSIvalue = (int)((int)(RSSI_Read - 256) /  2) - RSSI_Offset;
  }
  else
  {
    RSSIvalue = (RSSI_Read / 2) - RSSI_Offset;
  }

}

bool Check_PMV_C010()
{
  byte crcResult;

  if (ValidateTimings_PMVC010() == true)
  {
    crcResult = Compute_CRC8(8);  //calculate CRC over 8 bytes

    if (crcResult != RXBytes[8])  //verify CRC with the 9th byte in the array
    {
      //        Serial.print(F("CRC: "));
      //        Serial.println(crcResult, HEX);
      Serial.println(F("CRC Check failed"));
      PrintTimings(0, TimingsIndex);
      PrintBits(0, TimingsIndex);
      //PrintDecodedData();
      return (false);
    }
    else
    {
      //decode the message...
      DecodeTPMS_PMVC010();
      return (true);
    }
  }
  else
  {
    PrintTimings(0, TimingsIndex);
    PrintBits(0, TimingsIndex);
    //PrintDecodedData();

    return (false);
  }

}

int ReceiveMessage()
{

  //Check bytes in FIFO
  int FIFOcount;
  int resp;
  bool StatusUpdated = false;

  //set up timing of edges using interrupts...
  LastEdgeTime_us = micros();
  CD_Width = micros();
  digitalWrite(LED_RX,LED_ON);
  attachInterrupt(digitalPinToInterrupt(RXPin), EdgeInterrupt, CHANGE);
  while (GetCarrierStatus() == true)
  {
    //get signal strength etc. (once only)
    if (StatusUpdated == false)
    {
      UpdateStatusInfo();
...

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

globals

C Header File
#define USE_PROGMEMCRC 1
#define SHOWDEGUGINFO 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

byte RSSI_Read;

const int CC1101_CS = 10;  // Define the Chip Select pin
const int RXPin = 2;

const int DEBUGPIN = 6;


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

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




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

unsigned int FreqOffset;
unsigned int DemodLinkQuality;
int RSSIvalue;

boolean TPMS_Changed = false;

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



#ifdef USE_PROGMEMCRC
  ////CRCTable
  const byte PROGMEM 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
  };
#else
  static byte crctable[256];
  const byte PROGMEM 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
  };
#endif

struct TPMS_entry
{
  unsigned long TPMS_ID;
  unsigned long lastupdated;
  unsigned int TPMS_Status;
  float TPMS_Pressure;
  float TPMS_Temperature;
} TPMS[MAXTPMS];


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

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)
//while(digitalRead(PORT_SPI_MISO))
// 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     0x0D        // GDO2 Output Pin Configuration - Serial out
#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   0x30        // Packet Automation Control
#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    0xD9        // Modem Configuration (59 = data rate = 20kHz - actual data rate is 10kHz but due to bi-phase coding need to double the rate, RX bandwidth 81.25kHz)
#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    0x22        // Modem Configuration Channel spacing 200kHz
#define CC1101_DEFVAL_MDMCFG0    0xF8        // Modem Configuration
#define CC1101_DEFVAL_DEVIATN    0x25        // Modem Deviation Setting (+/-10.31kHz)
#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 //C6
//#define CC1101_DEFVAL_AGCCTRL1   0x40        // AGC Control
#define CC1101_DEFVAL_AGCCTRL1   0x50        // AGC Control
#define CC1101_DEFVAL_AGCCTRL0   0x40        // 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
  //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_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_DEVIATN,  CC1101_DEFVAL_DEVIATN);
  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

  setCCregs();                          // Reconfigure CC1101
}

boolean GetCarrierStatus()
{
  byte ret;
  ret = readStatusReg(CC1101_PKTSTATUS);
  if ((ret & 0x40) == 0)
  {
    return(false);
  }
  else
  {
    return(true);
  }
}

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

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("Jansite TPMS Monitor");
    display.println("   (JSM Solutions)");
  
  
  }
  
  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.println("      (JSM Solutions)");
  
  
  }

  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)
      {
        dtostrf(TPMS[i].TPMS_Pressure, 3, 1, s);
        //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

Credits

JSMSolns
12 projects • 38 followers
Contact

Comments

Please log in or sign up to comment.