4 #include "oXs_config_basic.h"
5 #include "oXs_config_advanced.h"
6 #include "oXs_config_macros.h"
7 #include "oXs_ms5611.h" // we need the variodata struct
8 #include "oXs_4525.h" // we need the airspeeddata struct
9 #include "oXs_curr.h" // we need the currentdata struct
10 #include "oXs_voltage.h" // we need the arduinodata struct
11 #include "oXs_sdp3x.h" // we need the airspeed data
12 //#include <Arduino.h>
13 #include "oXs_general.h"
16 #if defined(PROTOCOL) && (PROTOCOL == HOTT)
18 // list of oXs measurements that can be selected in the config as telemetry fields.
20 //#define VERTICAL_SPEED 2
22 //#define ALT_OVER_10_SEC 4
29 //#define CURRENTMA 11
31 //#define CELLS_1_2 13
32 //#define CELLS_3_4 14
33 //#define CELLS_5_6 15
35 //#define ALTIMETER_2 17
36 //#define VERTICAL_SPEED_2 18
37 //#define SENSITIVITY_2 19
38 //#define ALT_OVER_10_SEC_2 20
39 //#define AIR_SPEED 21
40 //#define PRANDTL_COMPENSATION 22
41 //#define PPM_VSPEED 23
43 //#define PRANDTL_DTE 25
47 //#define VERTICAL_SPEED_A 29
48 //#define VERTICAL_SPEED_I 30
49 //#define GLIDER_RATIO 31
54 uint8_t volatile active
;
55 uint8_t volatile response
[3];
59 struct t_mbOneData mbData
[16] ;
66 /***************************************************************************************/
67 /* Transmission status */
68 /***************************************************************************************/
75 #define SERIAL_COM_SPEED 19200
77 // Hott protocol v4 delay
78 #define HOTTV4_TX_DELAY 1600 // Delai entre octets
80 // first byte sent by Rx for polling can have 2 values
81 #define HOTT_BINARY_MODE_REQUEST_ID 0x80
82 #define HOTT_TEXT_MODE_REQUEST_ID 0x7f
84 // in binary mode, second byte identifies one of 4 sensor types
85 #define HOTT_TELEMETRY_VARIO_SENSOR_ID 0x89 //Graupner #33601 Vario Module
86 #define HOTT_TELEMETRY_GPS_SENSOR_ID 0x8a //Graupner #33600 Gps module
87 #define HOTTV4_ESC_SENSOR_ID 0x8C
88 #define HOTT_TELEMETRY_GAM_SENSOR_ID 0x8d // General Air Module ID
89 #define HOTT_TELEMETRY_GEA_SENSOR_ID 0x8E // Electric Air Module ID
90 // note : when sensor relies, it sent first 2 bytes with the value = ??????????????? and then it starts a set of bytes depending on the type of sensor.
93 // in text mode, second byte identifies one of 4 sensor types
94 #define HOTT_GPS_SENSOR_TEXT_ID 0xA0 // GPS Module ID
96 #define HOTTV4_VARIO_SENSOR_TEXT_ID 0x90 // Vario Module Text ID
97 #define HOTTV4_GPS_SENSOR_TEXT_ID 0xA0 // GPS Module Text ID
98 #define HOTTV4_ESC_SENSOR_TEXT_ID 0xC0
99 #define HOTTV4_GENERAL_AIR_SENSOR_TEXT_ID 0xD0
100 #define HOTTV4_ELECTRICAL_AIR_SENSOR_TEXT_ID 0xE0 // Electric Air Module Text ID
103 #define HOTTV4_BUTTON_PREV 0x07
104 #define HOTTV4_BUTTON_SET 0x09
105 #define HOTTV4_BUTTON_DEC 0x0B
106 #define HOTTV4_BUTTON_INC 0x0D
107 #define HOTTV4_BUTTON_NEXT 0x0E
108 #define HOTTV4_BUTTON_NIL 0x0F
112 #define TXHOTTDATA_BUFFERSIZE 45
114 // structure of GENERAL AIR MODULE
116 byte start_byte
; //#01 start byte constant value 0x7c
117 byte gam_sensor_id
; //#02 EAM sensort id. constat value 0x8d=GENRAL AIR MODULE
118 byte warning_beeps
; //#03 1=A 2=B ... 0x1a=Z 0 = no alarm
119 /* VOICE OR BIP WARNINGS
120 Alarme sonore A.. Z, octet correspondant 1 à 26
123 0x02 02 B Negative Difference 2 B
124 0x03 03 C Negative Difference 1 C
127 0x06 06 F Min. Sensor 1 temp. F
128 0x07 07 G Min. Sensor 2 temp. G
129 0x08 08 H Max. Sensor 1 temp. H
130 0x09 09 I Max. Sensor 2 temp. I
131 0xA 10 J Max. Sens. 1 voltage J
132 0xB 11 K Max. Sens. 2 voltage K
134 0xD 13 M Positive Difference 2 M
135 0xE 14 N Positive Difference 1 N
136 0xF 15 O Min. Altitude O
137 0x10 16 P Min. Power Voltage P // We use this one for Battery Warning
138 0x11 17 Q Min. Cell voltage Q
139 0x12 18 R Min. Sens. 1 voltage R
140 0x13 19 S Min. Sens. 2 voltage S
141 0x14 20 T Minimum RPM T
143 0x16 22 V Max. used capacity V
144 0x17 23 W Max. Current W
145 0x18 24 X Max. Power Voltage X
146 0x19 25 Y Maximum RPM Y
147 0x1A 26 Z Max. Altitude Z
149 byte sensor_id
; //#04 constant value 0xd0 for GAM, other values for other modules
150 byte alarm_invers1
; //#05 alarm bitmask. Value is displayed inverted
152 // 0 all cell voltage
160 byte alarm_invers2
; //#06 alarm bitmask. Value is displayed inverted
162 // 0 main power current
163 // 1 main power voltage
169 // 7 "ON" sign/text msg active
170 byte cell
[6]; //#7 Volt Cell 1 (in 2 mV increments, 210 == 4.20 V)
171 //#8 Volt Cell 2 (in 2 mV increments, 210 == 4.20 V)
172 //#9 Volt Cell 3 (in 2 mV increments, 210 == 4.20 V)
173 //#10 Volt Cell 4 (in 2 mV increments, 210 == 4.20 V)
174 //#11 Volt Cell 5 (in 2 mV increments, 210 == 4.20 V)
175 //#12 Volt Cell 6 (in 2 mV increments, 210 == 4.20 V)
176 uint16_t Battery1
; //#13 LSB battery 1 voltage LSB value. 0.1V steps. 50 = 5.5V only pos. voltages
178 uint16_t Battery2
; //#15 LSB battery 2 voltage LSB value. 0.1V steps. 50 = 5.5V only pos. voltages
180 byte temperature1
; //#17 Temperature 1. Offset of 20. a value of 20 = 0°C
181 byte temperature2
; //#18 Temperature 2. Offset of 20. a value of 20 = 0°C
182 byte fuel_procent
; //#19 Fuel capacity in %. Values 0--100
183 //graphical display ranges: 0-100% with new firmwares of the radios MX12/MX20/...
184 uint16_t fuel_ml
; //#20 LSB Fuel in ml scale. Full = 65535!
186 uint16_t rpm
; //#22 RPM in 10 RPM steps. 300 = 3000rpm
188 uint16_t altitude
; //#24 altitude in meters. offset of 500, 500 = 0m
190 uint16_t climbrate_L
; //#26 climb rate in 0.01m/s. Value of 30000 = 0.00 m/s
192 byte climbrate3s
; //#28 climb rate in m/3sec. Value of 120 = 0m/3sec
193 uint16_t current
; //#29 current in 0.1A steps 100 == 10,0A
194 //#30 MSB current display only goes up to 99.9 A (continuous)
195 uint16_t main_voltage
; //#31 LSB Main power voltage using 0.1V steps 100 == 10,0V
196 //#32 MSB (Appears in GAM display right as alternate display.)
197 uint16_t batt_cap
; //#33 LSB used battery capacity in 10mAh steps
199 uint16_t speed
; //#35 LSB (air?) speed in km/h(?) we are using ground speed here per default
201 byte min_cell_volt
; //#37 minimum cell voltage in 2mV steps. 124 = 2,48V
202 byte min_cell_volt_num
; //#38 number of the cell with the lowest voltage
203 uint16_t rpm2
; //#39 LSB 2nd RPM in 10 RPM steps. 100 == 1000rpm
205 byte general_error_number
; //#41 General Error Number (Voice Error == 12) TODO: more documentation
206 byte pressure
; //#42 High pressure up to 16bar. 0,1bar scale. 20 == 2.0bar
207 byte version
; //#43 version number (Bytes 35 .43 new but not yet in the record in the display!)
208 byte stop_byte
; //#44 stop byte 0x7D
209 byte parity
; //#45 CHECKSUM CRC/Parity (calculated dynamicaly)
214 uint8_t startByte
; /* Byte 1: 0x7C = Start byte data */
215 uint8_t sensorID
; /* Byte 2: 0x8A = GPS Sensor */
216 uint8_t alarmTone
; /* Byte 3: 0…= warning beeps */
217 uint8_t sensorTextID
; /* Byte 4: 160 0xA0 Sensor ID Neu! */
218 uint8_t alarmInverse1
; /* Byte 5: 01 inverse status */
219 uint8_t alarmInverse2
; /* Byte 6: 00 inverse status status 1 = kein GPS Signal */
220 uint8_t flightDirection
; /* Byte 7: 119 = Flightdir./dir. 1 = 2°; 0° (North), 90° (East), 180° (South), 270° (West) */
221 uint8_t GPSSpeedLow
; /* Byte 8: 8 = /GPS speed low byte 8km/h */
222 uint8_t GPSSpeedHigh
; /* Byte 9: 0 = /GPS speed high byte */
224 uint8_t LatitudeNS
; /* Byte 10: 000 = N = 48°39’988 */
225 uint8_t LatitudeMinLow
; /* Byte 11: 231 0xE7 = 0x12E7 = 4839 */
226 uint8_t LatitudeMinHigh
; /* Byte 12: 018 18 = 0x12 */
227 uint8_t LatitudeSecLow
; /* Byte 13: 171 220 = 0xDC = 0x03DC =0988 */
228 uint8_t LatitudeSecHigh
; /* Byte 14: 016 3 = 0x03 */
230 uint8_t longitudeEW
; /* Byte 15: 000 = E= 9° 25’9360 */
231 uint8_t longitudeMinLow
; /* Byte 16: 150 157 = 0x9D = 0x039D = 0925 */
232 uint8_t longitudeMinHigh
; /* Byte 17: 003 3 = 0x03 */
233 uint8_t longitudeSecLow
; /* Byte 18: 056 144 = 0x90 0x2490 = 9360*/
234 uint8_t longitudeSecHigh
; /* Byte 19: 004 36 = 0x24 */
236 uint8_t distanceLow
; /* Byte 20: 027 123 = /distance low byte 6 = 6 m */
237 uint8_t distanceHigh
; /* Byte 21: 036 35 = /distance high byte */
238 uint8_t altitudeLow
; /* Byte 22: 243 244 = /Altitude low byte 500 = 0m */
239 uint8_t altitudeHigh
; /* Byte 23: 001 1 = /Altitude high byte */
240 uint8_t resolutionLow
; /* Byte 24: 48 = Low Byte m/s resolution 0.01m 48 = 30000 = 0.00m/s (1=0.01m/s) */
241 uint8_t resolutionHigh
; /* Byte 25: 117 = High Byte m/s resolution 0.01m */
242 uint8_t unknow1
; /* Byte 26: 120 = 0m/3s */
243 uint8_t GPSNumSat
; /* Byte 27: GPS.Satelites (number of satelites) (1 byte) */
244 uint8_t GPSFixChar
; /* Byte 28: GPS.FixChar. (GPS fix character. display, if DGPS, 2D oder 3D) (1 byte) */
245 uint8_t HomeDirection
; /* Byte 29: HomeDirection (direction from starting point to Model position) (1 byte) */
246 uint8_t angleXdirection
; /* Byte 30: angle x-direction (1 byte) */
247 uint8_t angleYdirection
; /* Byte 31: angle y-direction (1 byte) */
248 uint8_t angleZdirection
; /* Byte 32: angle z-direction (1 byte) */
249 uint8_t gyroXLow
; /* Byte 33: gyro x low byte (2 bytes) */
250 uint8_t gyroXHigh
; /* Byte 34: gyro x high byte */
251 uint8_t gyroYLow
; /* Byte 35: gyro y low byte (2 bytes) */
252 uint8_t gyroYHigh
; /* Byte 36: gyro y high byte */
253 uint8_t gyroZLow
; /* Byte 37: gyro z low byte (2 bytes) */
254 uint8_t gyroZHigh
; /* Byte 38: gyro z high byte */
255 uint8_t vibration
; /* Byte 39: vibration (1 bytes) */
256 uint8_t Ascii4
; /* Byte 40: 00 ASCII Free Character [4] */
257 uint8_t Ascii5
; /* Byte 41: 00 ASCII Free Character [5] */
258 uint8_t GPS_fix
; /* Byte 42: 00 ASCII Free Character [6], we use it for GPS FIX */
259 uint8_t version
; /* Byte 43: 00 version number */
260 uint8_t endByte
; /* Byte 44: 0x7D Ende byte */
261 uint8_t chksum
; /* Byte 45: Parity Byte */
270 OXS_OUT(uint8_t pinTx
,HardwareSerial
&print
);
272 OXS_OUT(uint8_t pinTx
);
274 VARIODATA
* varioData
;
275 VARIODATA
* varioData_2
;
276 AIRSPEEDDATA
* airSpeedData
;
277 CURRENTDATA
* currentData
;
278 VOLTAGEDATA
* voltageData
;
283 // used by both protocols
286 HardwareSerial
* printer
;
289 void formatAllMultiplexData() ;
290 uint8_t formatOneValue ( uint8_t currentFieldToSend
) ;
291 void setMultiplexNewData( uint16_t id
, int32_t value
, uint8_t alarm
) ;
292 byte
warning_beeps_Hott(void);
296 //extern bool ppmAvailable ;
297 extern struct ONE_MEASUREMENT ppm
;
298 extern struct ONE_MEASUREMENT mainVspeed
; // used to transmit the main Vspeed(calculated based on all set up in config)
299 extern struct ONE_MEASUREMENT compensatedClimbRate
; // used to transmit the compensated Vspeed
300 extern struct ONE_MEASUREMENT switchVSpeed
; // used to transmit the selected Vspeed
301 extern struct ONE_MEASUREMENT averageVSpeed
; // used to transmit the average Vspeed
302 extern struct ONE_MEASUREMENT vSpeedImu
; // used to transmit the Vspeedcalculated based on IMU
304 #if defined(PIN_VOLTAGE) && defined(VFAS_SOURCE)
305 extern struct ONE_MEASUREMENT vfas
;
308 extern struct ONE_MEASUREMENT test1
;
309 extern struct ONE_MEASUREMENT test2
;
310 extern struct ONE_MEASUREMENT test3
;
311 extern struct ONE_MEASUREMENT gliderRatio
;
313 extern uint8_t selectedVario
;
315 extern struct ONE_MEASUREMENT yaw
;
316 extern struct ONE_MEASUREMENT pitch
;
317 extern struct ONE_MEASUREMENT roll
;
320 extern int32_t GPS_lon
; // longitude in degree with 7 decimals, (neg for S)
321 extern int32_t GPS_lat
; // latitude in degree with 7 decimals, (neg for ?)
322 extern bool GPS_latAvailable
;
323 extern int32_t GPS_altitude
; // altitude in mm
324 extern uint16_t GPS_speed_3d
; // speed in cm/s
325 extern uint16_t GPS_speed_2d
; // speed in cm/s
326 extern uint32_t GPS_ground_course
; // degrees with 5 decimals
327 extern uint8_t GPS_numSat
;
328 extern uint16_t GPS_hdop
; // Compute GPS quality signal
329 extern bool GPS_fix
; // true if gps data are available.
332 extern uint8_t GPS_fix_type
;
333 extern int16_t GPS_distance
;
334 extern int16_t GPS_bearing
;
336 extern volatile uint16_t RpmValue
;
337 extern bool RpmAvailable
;
338 #endif // MEASURE_RPM
341 extern volatile uint8_t debug01
;
342 extern volatile uint8_t debug02
;
343 extern volatile uint8_t debug03
;
344 extern volatile uint8_t debug04
;
347 void setHottNewData( struct t_sportData
* volatile pdata
, uint16_t id
, uint32_t value
) ;
348 void initHottUart( ) ;
351 void convertLonLat_Hott( int32_t GPS_LatLon
, uint16_t * degMin
, uint16_t * decimalMin
) ;
354 extern volatile bool RpmSet
;
355 extern volatile uint16_t RpmValue
;
359 #define IDLE 0 // Idle state, both transmit and receive possible.
360 #define TRANSMIT 1 // Transmitting byte.
361 #define TRANSMIT_STOP_BIT 2 // Transmitting stop bit.
362 #define RECEIVE 3 // Receiving byte.
367 //This section chooses the correct timer values for Hott protocol = 19200 baud.
368 #if F_CPU == 20000000L // 20MHz clock
370 #define TICKS2COUNTHOTT (1044) // Ticks between two bits.
371 #define TICKS2WAITONEHOTT (1044) // Wait one bit period.
372 #define TICKS2WAITONE_HALFHOTT (1560) // Wait one and a half bit period.
373 #elif F_CPU == 16000000L // 16MHz clock
374 #define TICKS2COUNTHOTT (834) // Ticks between two bits.
375 #define TICKS2WAITONEHOTT (834) // Wait one bit period.
376 #define TICKS2WAITONE_HALFHOTT (1248) // Wait one and a half bit period.
377 #elif F_CPU == 8000000L // 8MHz clock
378 #define TICKS2COUNTHOTT (417) // Ticks between two bits.
379 #define TICKS2WAITONEHOTT (417) // Wait one bit period.
380 #define TICKS2WAITONE_HALFHOTT (624) // Wait one and a half bit period.
382 #error Unsupported clock speed
387 //#define INTERRUPT_EXEC_CYCL 90 // Cycles to execute interrupt routines from interrupt.
388 //#define INTERRUPT_EARLY_BIAS 32 // Cycles to allow of other interrupts.
389 // INTERRUPT_EARLY_BIAS is to bias the sample point a bit early in case
390 // the Timer 0 interrupt (5.5uS) delays the start bit detection
391 #if F_CPU == 20000000L // 20MHz clock
392 #define INTERRUPT_EXEC_CYCL 112 // Cycles to execute interrupt routines from interrupt.
393 #define INTERRUPT_EARLY_BIAS 40 // Cycles to allow of other interrupts.
394 #elif F_CPU == 16000000L // 16MHz clock
395 #define INTERRUPT_EXEC_CYCL 90 // Cycles to execute interrupt routines from interrupt.
396 #define INTERRUPT_EARLY_BIAS 32 // Cycles to allow of other interrupts.
397 #elif F_CPU == 8000000L // 8MHz clock
398 #define INTERRUPT_EXEC_CYCL 90 // Cycles to execute interrupt routines from interrupt.
399 #define INTERRUPT_EARLY_BIAS 32 // Cycles to allow of other interrupts.
401 #error Unsupported clock speed
404 #define INTERRUPT_ENTRY_TRANSMIT 59 // Cycles in ISR before sending first bit from first byte; Without this correction, first bit is sent 7.4 usec to late at 8 Mhz (so it takes 59 cycles = 7.4 usec * 8)
405 #define INTERRUPT_BETWEEN_TRANSMIT 64 // Cycles in ISR before sending first bit from 2d, 3rd... bytes; Without this correction, first bit is sent 4 usec to late at 16 Mhz (so it takes 64 cycles = 4 usec * 16)
407 // this section define some delays used ; values can be used by any protocol
408 #if F_CPU == 20000000L // 20MHz clock
409 #define DELAY_4000 ((uint16_t)4000.0 * 20.0 /16.0 )
410 #define DELAY_3500 ((uint16_t)3500.0 * 20.0 /16.0 )
411 #define DELAY_2000 ((uint16_t)2000.0 * 20.0 /16.0 )
412 #define DELAY_1600 ((uint16_t)1600.0 * 20.0 /16.0 )
413 #define DELAY_1000 ((uint16_t)1000.0 * 20.0 /16.0 )
414 #define DELAY_400 ((uint16_t)400.0 * 20.0 /16.0 )
415 #define DELAY_100 ((uint16_t)100.0 * 20.0 /16.0 )
417 #elif F_CPU == 16000000L // 16MHz clock
418 #define DELAY_4000 ((uint16_t) (4000L * 16) )
419 #define DELAY_3500 ((uint16_t) (3500L * 16) )
420 #define DELAY_2000 ((uint16_t) (2000L * 16) )
421 #define DELAY_1600 ((uint16_t) (1600L * 16) )
422 #define DELAY_1000 ((uint16_t) (1000L * 16) )
423 #define DELAY_400 ((uint16_t) (400 * 16) )
424 #define DELAY_100 ((uint16_t) (100 * 16) )
425 #elif F_CPU == 8000000L // 8MHz clock
426 #define DELAY_4000 ((uint16_t)4000L * 8 )
427 #define DELAY_3500 ((uint16_t)3500L * 8 )
428 #define DELAY_2000 ((uint16_t)2000 * 8 )
429 #define DELAY_1600 ((uint16_t)1600 * 8 )
430 #define DELAY_1000 ((uint16_t)1000 * 8 )
431 #define DELAY_400 ((uint16_t)400 * 8 )
432 #define DELAY_100 ((uint16_t)100 * 8 )
434 #error Unsupported clock speed
437 #define TCCR TCCR1A //!< Timer/Counter Control Register
438 #define TCCR_P TCCR1B //!< Timer/Counter Control (Prescaler) Register
439 #define OCR OCR1A //!< Output Compare Register
440 #define EXT_IFR EIFR //!< External Interrupt Flag Register
441 #define EXT_ICR EICRA //!< External Interrupt Control Register
444 #define TRXPORT PORTD
447 #define SET_TX_PIN( ) ( TRXPORT |= ( 1 << PIN_SERIALTX ) )
448 #define CLEAR_TX_PIN( ) ( TRXPORT &= ~( 1 << PIN_SERIALTX ) )
449 #define GET_RX_PIN( ) ( TRXPIN & ( 1 << PIN_SERIALTX ) )
451 #define SET_TX_PIN_MB( ) ( TRXDDR &= ~( 1 << PIN_SERIALTX ) ) // in fact we put the port in high impedance because the rx has a pull up resistance
452 #define CLEAR_TX_PIN_MB( ) ( TRXDDR |= ( 1 << PIN_SERIALTX ) ) // in fact we put the port in output mode. PORT is already set to 0 during initialisation
454 // values used by the state ".active"
456 #define NOT_AVAILABLE 1
460 #endif // End of HOTT
461 #endif // OXS_OUT_HOTT_h
464 In Hott protocol, the Rx send a polling to each of the possible sensors (there are 5 types of sensors).
465 Each sensor is in fact polled twice: one asking to reply in a text format and another in a binary format.
466 This version of oXs replies only to the request for a binary format sent to a GAM (general air module)
467 Later on, it would be possible to simulate other types of module (like a GPS, a vario,... )
468 It seems that for binary format, the polling is every 200 msec. Still this strange because the reply of only one sensor takes already about 140 msec (45 bytes * 3msec/byte).
469 When the sensor identifies that it must reply to a polling, it has to wait 5 msec before sending the first byte and afterward it can send all the bytes (45 in total in binary GAM format) keeping 3 msec between each byte.
470 It seems that the delay of 3 msec can be reduced to less than 1 msec.
471 The format of the message is given here above.
472 It is possible to send some info to reverse some fields on the display and to activate some alarms (but this version does not support it)