#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 (or 0x48) 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] proposed extension } ; } ; union { uint32_t SeqMsg; struct { 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] proposed extension } ; } ; union { uint8_t TypeByte; struct { uint8_t AcftType:4; // [] lower nibble is the aircraft-type like for FLARM/OGN, upper nibble possibly retransmit flag uint8_t Relay :4; // to be worked out: 1 or 2 signal some kind of relay // bool Relay :1; // relay flag (by ground station) // bool OGN :1; // for packets produced by OGN-Tracker - proposed extension // uint8_t AddrType:2; // address-type for OGN packets (if OGN==1) - proposed extension } ; } ; 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 /* , bool Ext=0 */ ) // convert from an OGN packet { Clear(); Address = Packet.Header.Address; // [24-bit] if(Packet.Header.NonPos) return 0; // encode only position packets AcftType = Packet.Position.AcftType; // [4-bit] aircraft-type Altitude = Packet.DecodeAltitude(); // [m] Heading = Packet.DecodeHeading()/10; // [deg] Speed = (398*(int32_t)Packet.DecodeSpeed()+1024)>>11; // [0.1m/s] => [kts] Latitude = 0.0001f/60*Packet.DecodeLatitude(); // [deg] Longitude = 0.0001f/60*Packet.DecodeLongitude(); // [deg] /* if(Ext) { OGN=1; // extended data flag AddrType = Packet.Header.AddrType; // [2-bit] Relay = Packet.Header.Relay; // relay flag // Time = Packet.Position.Time; // [sec] int32_t ClimbRate = Packet.DecodeClimbRate(); // [0.1m/s] ClimbRate = (ClimbRate*315+512)>>10; // [64fpm] if(ClimbRate>127) ClimbRate=127; else if(ClimbRate<(-127)) ClimbRate=(-127); Climb = ClimbRate; } */ SeqMsg = 0; setCRC(); return 1; } int WriteStxJSON(char *JSON) const { int Len=0; Len+=Format_String(JSON+Len, "\"addr\":\""); Len+=Format_Hex(JSON+Len, (uint8_t) (Address>>16)); Len+=Format_Hex(JSON+Len, (uint16_t)(Address)); JSON[Len++]='\"'; Len+=Format_String(JSON+Len, ",\"addr_type\":"); JSON[Len++] = HexDigit(getAddrType()); Len+=Format_String(JSON+Len, ",\"acft_type\":\""); JSON[Len++] = HexDigit(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[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", Latitude, Longitude, Altitude); Len+=sprintf(JSON+Len, ",\"track_deg\":%d,\"speed_mps\":%3.1f", Heading, 0.514*Speed); // if(OGN) Len+=sprintf(JSON+Len, ",\"climb_mps\":%3.1f", 0.32512*Climb); return Len; } uint8_t Dump(char *Out) { uint8_t Len=0; for(int Idx=0; Idx=300000000) return Time; return Time-1; } int WriteStxJSON(char *JSON) const { int Len = PAW_Packet::WriteStxJSON(JSON); uint32_t PosTime=Time; if(nsTime<300000000) PosTime--; // if(OGN) // { } 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); return Len; } } ; #endif // __PAW_H__