From 5aa91dd9a8320d9d6a5484f845f77557ba05de8f Mon Sep 17 00:00:00 2001 From: Pawel Jalocha Date: Mon, 30 Nov 2020 18:47:13 +0000 Subject: [PATCH] PilotAware packet definition --- main/paw.h | 209 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 209 insertions(+) create mode 100644 main/paw.h diff --git a/main/paw.h b/main/paw.h new file mode 100644 index 0000000..c067d99 --- /dev/null +++ b/main/paw.h @@ -0,0 +1,209 @@ +#ifndef __PAW_H__ +#define __PAW_H__ + +#include +#include + +#include "ogn1.h" +#include "format.h" + +class PAW_Packet +{ public: + static const uint8_t Size = 24; + union + { uint8_t Byte[Size]; // 24 bytes per packet, counting the internal CRC but not the external one + struct + { union + { uint32_t AddrWord; + struct + { uint8_t Sync : 8; // the first (thus lowest) byte is the "sync" = '$' = 0x24 + uint32_t Address:24; // 24-bit address: can be ICAO or internally produced + } ; + } ; + float Longitude; // [deg] + float Latitude; // [deg] + uint16_t Altitude; // [m] + union + { uint16_t HeadWord; + struct + { uint16_t Heading:9; // [deg] + int8_t Climb :7; // [64fpm] + } ; + } ; + uint8_t Seq; // sequence number to transmit longer messages + uint8_t Msg[3]; // 3-byte part of the longer message + union + { uint16_t SpeedWord; + struct + { uint16_t Speed:10; // [kt] + uint8_t Time : 6; // [sec] + } ; + } ; + union + { uint8_t TypeByte; + struct + { uint8_t AcftType:4; // [] lower nibble is the aircraft-type like for FLARM/OGN, upper nibble possibly retransmit flag + bool Relay :1; // relay flag (by ground station) + bool OGN :1; // for packets produced by OGN-Tracker + uint8_t AddrType:2; // address-type for OGN packets (if OGN==1) + } ; + } ; + uint8_t CRC; // internal CRC: a XOR of all bytes + } ; + } ; + + public: + void Copy(const uint8_t *Data) { memcpy(Byte, Data, Size); } + void Clear(void) + { Byte[0]=0x24; + for(int Idx=1; Idx>8; } // remove the sync '$' + // void setAddress(uint32_t Addr) { Address = (Addr<<8) | 0x24; } // set new address and set the '$' sync char + + int Copy(const OGN1_Packet &Packet) + { Clear(); + OGN = 1; + Address = Packet.Header.Address; + AddrType = Packet.Header.AddrType; + Relay = Packet.Header.Relay; + if(Packet.Header.NonPos) return 0; + AcftType = Packet.Position.AcftType; + Altitude = Packet.DecodeAltitude(); + Heading = Packet.DecodeHeading()/10; + Speed = (398*(int32_t)Packet.DecodeSpeed()+1024)>>11; // [0.1m/s] => [kts] + Latitude = 0.0001f/60*Packet.DecodeLatitude(); + Longitude = 0.0001f/60*Packet.DecodeLongitude(); + setCRC(); return 1; } + + uint8_t Dump(char *Out) + { uint8_t Len=0; + for(int Idx=0; Idx>16)); + Len+=Format_Hex(JSON+Len, (uint16_t)(Address)); + JSON[Len++]='\"'; + Len+=Format_String(JSON+Len, ",\"addr_type\":"); + JSON[Len++] = HexDigit(Packet.getAddrType()); + Len+=Format_String(JSON+Len, ",\"acft_type\":\""); + JSON[Len++] = HexDigit(Packet.AcftType); + JSON[Len++]='\"'; + Len+=Format_String(JSON+Len, ",\"acft_cat\":\""); // GDL90 aircraft category + // no-info, glider, tow, heli, parachute, drop-plane, hang-glider, para-glider, powered, jet, UFO, balloon, Zeppelin, UAV, ground vehicle, static } ; + const uint8_t AcftCat[16] = { 0, 9, 1, 7, 11, 1, 12, 12, 1, 2, 0, 10, 10, 14, 18, 19 } ; + Len+=Format_Hex(JSON+Len, AcftCat[Packet.AcftType]); + JSON[Len++]='\"'; + uint32_t PosTime=Time; if(nsTime<300000000) PosTime--; + Len+=Format_String(JSON+Len, ",\"time\":"); + Len+=Format_UnsDec(JSON+Len, PosTime); + int64_t RxTime=(int64_t)Time-PosTime; RxTime*=1000; RxTime+=nsTime/1000000; + Len+=Format_String(JSON+Len, ",\"rx_time\":"); + Len+=Format_SignDec(JSON+Len, RxTime, 4, 3, 1); + Len+=sprintf(JSON+Len, ",\"lat_deg\":%8.7f,\"lon_deg\":%8.7f,\"alt_msl_m\":%d", Packet.Latitude, Packet.Longitude, Packet.Altitude); + Len+=sprintf(JSON+Len, ",\"track_deg\":%d,\"speed_mps\":%3.1f", Packet.Heading, 0.514*Packet.Speed); + return Len; } + +} ; + +#endif // __PAW_H__