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