//----------------------------------------------------------------------------------- // decode a lapRF packet received from the gate // void decodePacket() { int numRecords = 0; rxStream = unescapeBuffer(rxStream); BinaryReader br = new BinaryReader(rxStream); BinaryWriter bw = new BinaryWriter(rxStream); // read the header // rxStream.Seek(0, SeekOrigin.Begin); Byte sor = br.ReadByte(); UInt16 len = br.ReadUInt16(); UInt16 packetCRC = br.ReadUInt16(); // record the sent CRC before we zero it out to recompute it laprf_type_of_record typeOfRecord = (laprf_type_of_record)br.ReadUInt16(); // zero the CRC before computing it // rxStream.Seek(3, SeekOrigin.Begin); bw.Write((UInt16)0x0000); if (sor == SOR && len < MAX_RXPACKET_LEN) { UInt16 computedCRC = crcCalc.compute_crc16(rxStream.ToArray(), (int)rxStream.Length); if (computedCRC == packetCRC) { ++recordGoodPackets; // seek just past the header rxStream.Seek(7, SeekOrigin.Begin); if (typeOfRecord == laprf_type_of_record.LAPRF_TOR_RFSETUP) { Debug.Print("RFSetup"); Byte[] ar = rxStream.GetBuffer(); Debug.Print("{0}", ar.Length); } // now we can decode the packet contents // while (decodeRecord(typeOfRecord, br) == true) { ++numRecords; } ++recordCount; } else { ++recordCRCMismatchCount; Debug.Print("CRC Mismatch {0} {1}", computedCRC, packetCRC); } } else { Debug.Print("bad header"); } }
//----------------------------------------------------------------------------------- // build packet to send out to the gate and fill output buffer public void prepare_sendable_packet(laprf_type_of_record recordType) { dataStream = new MemoryStream(); dataStreamWriter = new BinaryWriter(dataStream); dataStreamWriter.Write((Byte)SOR); dataStreamWriter.Write((UInt16)0); // length placeholder dataStreamWriter.Write((UInt16)0); // CRC placeholder dataStreamWriter.Write((UInt16)recordType); // type of record }
//----------------------------------------------------------------------------------- // decode a single record within a lapRF packet // Boolean decodeRecord(laprf_type_of_record typeOfRecord, BinaryReader br) { UInt32 passingNumber; UInt64 rtcTime; Byte pilotId; UInt32 minLapTime; // read the field of record header // if (br.BaseStream.Position >= br.BaseStream.Length) { return(false); } Byte signature = br.ReadByte(); if (signature == EOR) { return(false); } Byte numBytes = br.ReadByte(); int recordLength = 2 + numBytes; // total size of record switch (typeOfRecord) { case laprf_type_of_record.LAPRF_TOR_PASSING: switch (signature) { case 0x01: // re-use transponder ID for slot number pilotId = br.ReadByte(); // 1-based, index 0 not used Debug.Print("LAPRF_TOR_PASSING pilot {0}", pilotId); currentPassingRecord.pilotId = pilotId; currentPassingRecord.bValid = true; // not really true... break; case 0x21: if (numBytes == 4) { passingNumber = br.ReadUInt32(); currentPassingRecord.passingNumber = passingNumber; Debug.Print("LAPRF_TOR_PASSING # {0}", passingNumber); currentPassingRecord.bValid = true; // not really true... } break; case 0x02: // RTC_TIME if (numBytes == 8) { rtcTime = br.ReadUInt64(); currentPassingRecord.rtcTime = rtcTime; Debug.Print("LAPRF_TOR_PASSING time {0}", rtcTime); currentPassingRecord.bValid = true; // not really true... // store the passing record in a queue (FIFO) passingRecords.Enqueue(currentPassingRecord); } break; } break; case laprf_type_of_record.LAPRF_TOR_STATUS: lastStatusDate = DateTime.Now; switch (signature) { case 0x01: // re-use transponder ID for slot number currentRssiSlot = br.ReadByte(); // 1-based, index 0 not used Debug.Print("LAPRF_TOR_STATUS {0}", currentRssiSlot); break; case 0x03: // status flags UInt16 dummy = br.ReadUInt16(); break; case 0x21: // INPUT_VOLTAGE if (numBytes == 2) { UInt16 voltagemV = br.ReadUInt16(); batteryVoltage = voltagemV / 1000.0f; Debug.Print("LAPRF_TOR_STATUS voltage {0}", voltagemV); } break; case 0x22: // Instantaneous RSSI if (numBytes == 4) { float rssiLevel = br.ReadSingle(); rssiPerSlot[currentRssiSlot].lastRssi = rssiLevel; Debug.Print("LAPRF_TOR_STATUS rssi {0}", rssiLevel); } break; case 0x23: // Gate State if (numBytes == 1) { Byte gateState = br.ReadByte(); Debug.Print("GateState det # {0}", gateState); } break; case 0x24: // Number of detections (passing records) if (numBytes == 4) { UInt32 detectionCount = br.ReadUInt32(); Debug.Print("LAPRF_TOR_STATUS det # {0}", detectionCount); } break; } break; case laprf_type_of_record.LAPRF_TOR_RSSI: switch (signature) { case 0x01: // re-use transponder ID for slot number currentRssiSlot = br.ReadByte(); // 1-based, index 0 not used Debug.Print("LAPRF_TOR_RSSI {0}", currentRssiSlot); break; case 0x20: // min rssi, 4 byte float rssiPerSlot[currentRssiSlot].minRssi = br.ReadSingle(); Debug.Print(" min {0}", rssiPerSlot[currentRssiSlot].minRssi); break; case 0x21: // max rssi, 4 byte float rssiPerSlot[currentRssiSlot].maxRssi = br.ReadSingle(); Debug.Print(" max {0}", rssiPerSlot[currentRssiSlot].maxRssi); break; case 0x22: // mean rssi, 4 byte float rssiPerSlot[currentRssiSlot].meanRssi = br.ReadSingle(); Debug.Print(" mean {0}", rssiPerSlot[currentRssiSlot].meanRssi); break; case 0x07: // sample count, 4 byte int // TBD break; } break; case laprf_type_of_record.LAPRF_TOR_RFSETUP: // read and write switch (signature) { case 0x01: // re-use transponder ID for slot number currentSetupSlot = br.ReadByte(); // 1-based, index 0 not used if (currentSetupSlot > MAX_SLOTS) { currentSetupSlot = 0; // default to zero if confused } Debug.Print("LAPRF_TOR_RFSETUP {0}", currentSetupSlot); break; case 0x20: // Enabled rfSetupPerSlot[currentSetupSlot].bEnabled = br.ReadUInt16(); Debug.Print(" enabled {0}", rfSetupPerSlot[currentSetupSlot].bEnabled); break; case 0x21: // Channel rfSetupPerSlot[currentSetupSlot].channel = br.ReadUInt16(); break; case 0x22: // Band rfSetupPerSlot[currentSetupSlot].band = br.ReadUInt16(); break; case 0x24: // Attenuation rfSetupPerSlot[currentSetupSlot].attenuation = br.ReadUInt16(); break; case 0x25: // Frequency //rfSetupPerSlot[currentSetupSlot].frequency = br.ReadUInt16(); Debug.Print(" freq {0}", br.ReadUInt16()); break; } break; case laprf_type_of_record.LAPRF_TOR_SETTINGS: // read and write switch (signature) { case 0x26: // re-use transponder ID for slot number minLapTime = br.ReadUInt32(); Debug.Print("LAPRF_TOR_SETTINGS minLapTime {0}", minLapTime); break; } break; } return(true); }