2 * This file is part of u360gts, aka amv-open360tracker 32bits:
3 * https://github.com/raul-ortega/amv-open360tracker-32bits
5 * The code below is an adaptation by Raúl Ortega of the original code written by Samuel Brucksch:
6 * https://github.com/SamuelBrucksch/open360tracker
8 * u360gts is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
13 * u360gts is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with u360gts. If not, see <http://www.gnu.org/licenses/>.
24 #include "telemetry.h"
26 void processFrskyPacket(uint8_t *packet
);
27 void parseTelemHubByte(uint8_t c
);
28 int32_t gpsToLong(int8_t neg
, uint16_t bp
, uint16_t ap
);
30 // Enumerate FrSky packet codes
40 #define START_STOP 0x7E
41 #define BYTESTUFF 0x7d
42 #define STUFF_MASK 0x20
44 #define GPS_ALT_BP_ID 0x01
45 #define GPS_ALT_AP_ID 0x09
46 #define BARO_ALT_BP_ID 0x10
47 #define BARO_ALT_AP_ID 0x21
48 #define GPS_LON_BP_ID 0x12
49 #define GPS_LAT_BP_ID 0x13
50 #define GPS_LON_AP_ID 0x1A
51 #define GPS_LAT_AP_ID 0x1B
52 #define GPS_LON_EW_ID 0x22
53 #define GPS_LAT_NS_ID 0x23
56 #define FRSKY_RX_PACKET_SIZE 11
57 uint8_t frskyRxBuffer
[FRSKY_RX_PACKET_SIZE
];
59 #define FRSKYD_LATLON_DIVIDER 100000
62 STATE_DATA_IDLE
, STATE_DATA_START
, STATE_DATA_IN_FRAME
, STATE_DATA_XOR
,
65 static uint8_t dataState
= STATE_DATA_IDLE
;
66 static uint8_t numPktBytes
= 0;
79 int32_t prevTargetLat
= 0;
80 int32_t prevTargetLon
= 0;
90 void frskyd_setLat(void) {
91 int32_t value
= gpsToLong(NS
== 'N' ? 1 : -1, lat_bp
, lat_ap
);
92 if(abs(value
)>180*FRSKYD_LATLON_DIVIDER
) {
96 prevLatBp
= (int16_t)(prevTargetLat
/FRSKYD_LATLON_DIVIDER
);
97 LatBp
= (int16_t)(value
/FRSKYD_LATLON_DIVIDER
);
98 if(prevTargetLat
> value
&& (prevLatBp
-LatBp
)>2 && prevTargetLat
>FRSKYD_LATLON_DIVIDER
) value
=prevTargetLat
;
99 if(prevTargetLat
< value
&& (LatBp
-prevLatBp
)>2 && prevTargetLat
>FRSKYD_LATLON_DIVIDER
) value
=prevTargetLat
;
104 telemetry_lat
= value
*10;
107 void frskyd_setLon(void) {
109 int32_t value
= gpsToLong(EW
== 'E' ? 1 : -1, lon_bp
, lon_ap
);
110 if(abs(value
)>180*FRSKYD_LATLON_DIVIDER
) {
114 prevLonBp
= (int16_t)(prevTargetLon
/FRSKYD_LATLON_DIVIDER
);
115 LonBp
=(int16_t)(value
/FRSKYD_LATLON_DIVIDER
);
116 if(prevTargetLon
> value
&& (prevLonBp
-LonBp
)>2 && prevTargetLon
>FRSKYD_LATLON_DIVIDER
) value
=prevTargetLon
;
117 if(prevTargetLon
< value
&& (LonBp
-prevLonBp
)>2 && prevTargetLon
>FRSKYD_LATLON_DIVIDER
) value
=prevTargetLon
;
121 telemetry_lon
=value
*10;
124 void frskyd_setAlt() {
125 if(((prevAlt
-alt
)>500 || (alt
-prevAlt
)>500) && prevAlt
> 0 && alt
> 0 ) alt
=prevAlt
;
130 void frskyd_setSats() {
131 telemetry_sats
= sats
;
134 void frskyd_encodeTargetData(uint8_t c
) {
136 case STATE_DATA_START
:
138 break; // Remain in userDataStart if possible 0x7e,0x7e doublet found.
140 frskyRxBuffer
[numPktBytes
++] = c
;
141 dataState
= STATE_DATA_IN_FRAME
;
143 case STATE_DATA_IN_FRAME
:
144 if (c
== BYTESTUFF
) {
145 dataState
= STATE_DATA_XOR
; // XOR next byte
148 if (c
== START_STOP
) // end of frame detected
150 processFrskyPacket(frskyRxBuffer
); // FrskyRxBufferReady = 1;
151 dataState
= STATE_DATA_IDLE
;
154 if (numPktBytes
< FRSKY_RX_PACKET_SIZE
)
155 frskyRxBuffer
[numPktBytes
++] = c
;
157 dataState
= STATE_DATA_IDLE
;
162 if (numPktBytes
< FRSKY_RX_PACKET_SIZE
)
163 frskyRxBuffer
[numPktBytes
++] = c
^ STUFF_MASK
;
165 dataState
= STATE_DATA_IDLE
;
168 dataState
= STATE_DATA_IN_FRAME
;
170 case STATE_DATA_IDLE
:
171 if (c
== START_STOP
) {
173 dataState
= STATE_DATA_START
;
179 void processFrskyPacket(uint8_t *packet
) {
182 case LINKPKT
: // A1/A2/RSSI values
183 //maybe we can use RSSI here to start an alarm when RSSI level gets low
186 numBytes
= packet
[1];
189 for (uint8_t i
= 3; i
< numBytes
+3; i
++) {
191 ltm_encodeTargetData(packet[i]);
193 parseTelemHubByte(packet
[i
]);
200 IDLE
= 0, DATA_ID
, DATA_LOW
, DATA_HIGH
, STUFF
= 0x80
203 void parseTelemHubByte(uint8_t c
) {
204 static uint8_t dataId
;
205 static uint8_t byte0
;
206 static STATE state
= IDLE
;
217 state
= (STATE
) (state
- STUFF
);
220 state
= (STATE
) (state
| STUFF
);
223 if (state
== DATA_ID
) {
232 if (state
== DATA_LOW
) {
241 alt
= (int16_t)((c
<< 8) + byte0
);
245 alt
= (int16_t)((c
<< 8) + byte0
);
249 lon_bp
= (c
<< 8) + byte0
;
252 lon_ap
= (c
<< 8) + byte0
;
255 lat_bp
= (c
<< 8) + byte0
;
258 lat_ap
= (c
<< 8) + byte0
;
267 if(telemetry_provider
==1){
270 } else if(telemetry_provider
==2){
276 if ((NS
== 'N' || NS
== 'S') && (EW
== 'E' || EW
== 'W')) {
284 telemetry_failed_cs
++;