1 /* By Larry Ho Ka Wai @ 23/06/2015*/
9 #include "build/build_config.h"
10 #include "build/debug.h"
11 #include "build/version.h"
15 #include "common/axis.h"
16 #include "common/color.h"
17 #include "common/maths.h"
19 #include "config/config.h"
20 #include "config/config_eeprom.h"
21 #include "config/feature.h"
23 #include "drivers/accgyro/accgyro.h"
24 #include "drivers/compass/compass.h"
25 #include "drivers/bus_i2c.h"
26 #include "drivers/sensor.h"
27 #include "drivers/serial.h"
28 #include "drivers/system.h"
29 #include "drivers/time.h"
30 #include "drivers/timer.h"
32 #include "fc/controlrate_profile.h"
34 #include "fc/rc_adjustments.h"
35 #include "fc/rc_controls.h"
36 #include "fc/runtime_config.h"
38 #include "flight/position.h"
39 #include "flight/failsafe.h"
40 #include "flight/imu.h"
41 #include "flight/mixer.h"
42 #include "flight/pid.h"
43 #include "flight/pid_init.h"
44 #include "flight/servos.h"
46 #include "io/servos.h"
48 #include "io/gimbal.h"
49 #include "io/serial.h"
50 #include "io/ledstrip.h"
51 #include "io/flashfs.h"
52 #include "io/beeper.h"
60 #include "scheduler/scheduler.h"
62 #include "sensors/boardalignment.h"
63 #include "sensors/sensors.h"
64 #include "sensors/battery.h"
65 #include "sensors/acceleration.h"
66 #include "sensors/barometer.h"
67 #include "sensors/compass.h"
68 #include "sensors/gyro.h"
69 #include "sensors/rangefinder.h"
71 #include "telemetry/telemetry.h"
76 #define GPS_POSITION_FRAME_ID 0x02
77 #define GPS_TIME_FRAME_ID 0x03
78 #define FC_ATTITUDE_FRAME_ID 0x1E
79 #define RC_CHANNEL_FRAME_ID 0x15
80 #define CROSSFIRE_RSSI_FRAME_ID 0x14
81 #define CLEANFLIGHT_MODE_FRAME_ID 0x20
83 #define BST_PROTOCOL_VERSION 0
85 #define API_VERSION_MAJOR 1 // increment when major changes are made
86 #define API_VERSION_MINOR 13 // increment when any change is made, reset to zero when major changes are released after changing API_VERSION_MAJOR
88 #define API_VERSION_LENGTH 2
91 // MSP commands for Cleanflight original features
94 #define BST_API_VERSION 1 //out message
95 #define BST_FC_VARIANT 2 //out message
96 #define BST_FC_VERSION 3 //out message
97 #define BST_BOARD_INFO 4 //out message
98 #define BST_BUILD_INFO 5 //out message
100 #define BST_MODE_RANGES 34 //out message Returns all mode ranges
101 #define BST_SET_MODE_RANGE 35 //in message Sets a single mode range
102 #define BST_FEATURE 36
103 #define BST_SET_FEATURE 37
104 #define BST_RX_CONFIG 44
105 #define BST_SET_RX_CONFIG 45
106 #define BST_LED_COLORS 46
107 #define BST_SET_LED_COLORS 47
108 #define BST_LED_STRIP_CONFIG 48
109 #define BST_SET_LED_STRIP_CONFIG 49
110 #define BST_LOOP_TIME 83 //out message Returns FC cycle time i.e looptime parameter
111 #define BST_SET_LOOP_TIME 84 //in message Sets FC cycle time i.e looptime parameter
112 #define BST_RX_MAP 64 //out message Get channel map (also returns number of channels total)
113 #define BST_SET_RX_MAP 65 //in message Set rx map, numchannels to set comes from BST_RX_MAP
114 #define BST_REBOOT 68 //in message Reboot
115 #define BST_DISARM 70 //in message Disarm
116 #define BST_ENABLE_ARM 71 //in message Enable arm
117 #define BST_DEADBAND 72 //out message
118 #define BST_SET_DEADBAND 73 //in message
119 #define BST_FC_FILTERS 74 //out message
120 #define BST_SET_FC_FILTERS 75 //in message
121 #define BST_STATUS 101 //out message cycletime & errors_count & sensor present & box activation & current setting number
122 #define BST_RC_TUNING 111 //out message rc rate, rc expo, rollpitch rate, yaw rate, dyn throttle PID
123 #define BST_SET_RC_TUNING 204 //in message rc rate, rc expo, rollpitch rate, yaw rate, dyn throttle PID, yaw expo
124 #define BST_PID 112 //out message P I D coeff (9 are used currently)
125 #define BST_MISC 114 //out message powermeter trig
126 #define BST_SET_PID 202 //in message P I D coeff (9 are used currently)
127 #define BST_ACC_CALIBRATION 205 //in message no param
128 #define BST_MAG_CALIBRATION 206 //in message no param
129 #define BST_SET_MISC 207 //in message powermeter trig + 8 free for future use
130 #define BST_SELECT_SETTING 210 //in message Select Setting Number (0-2)
131 #define BST_EEPROM_WRITE 250 //in message no param
133 extern volatile uint8_t CRC8
;
134 extern volatile bool coreProReady
;
136 // this is calculated at startup based on enabled features.
137 static uint8_t activeBoxIds
[CHECKBOX_ITEM_COUNT
];
138 // this is the number of filled indexes in above array
139 static uint8_t activeBoxIdCount
= 0;
141 extern float motor_disarmed
[MAX_SUPPORTED_MOTORS
];
143 // cause reboot after BST processing complete
144 static bool isRebootScheduled
= false;
146 typedef struct box_e
{
147 const uint8_t boxId
; // see boxId_e
148 const char *boxName
; // GUI-readable box name
149 const uint8_t permanentId
; //
153 static const box_t boxes
[CHECKBOX_ITEM_COUNT
+ 1] = {
154 { BOXARM
, "ARM;", 0 },
155 { BOXANGLE
, "ANGLE;", 1 },
156 { BOXHORIZON
, "HORIZON;", 2 },
157 //{ BOXVARIO, "VARIO;", 4 },
158 { BOXMAG
, "MAG;", 5 },
159 { BOXHEADFREE
, "HEADFREE;", 6 },
160 { BOXHEADADJ
, "HEADADJ;", 7 },
161 { BOXCAMSTAB
, "CAMSTAB;", 8 },
162 { BOXPASSTHRU
, "PASSTHRU;", 12 },
163 { BOXBEEPERON
, "BEEPER;", 13 },
164 { BOXLEDLOW
, "LEDLOW;", 15 },
165 { BOXCALIB
, "CALIB;", 17 },
166 { BOXOSD
, "OSD DISABLE SW;", 19 },
167 { BOXTELEMETRY
, "TELEMETRY;", 20 },
168 { BOXSERVO1
, "SERVO1;", 23 },
169 { BOXSERVO2
, "SERVO2;", 24 },
170 { BOXSERVO3
, "SERVO3;", 25 },
171 { BOXBLACKBOX
, "BLACKBOX;", 26 },
172 { BOXFAILSAFE
, "FAILSAFE;", 27 },
173 { CHECKBOX_ITEM_COUNT
, NULL
, 0xFF }
176 extern uint8_t readData
[BST_BUFFER_SIZE
];
177 extern uint8_t writeData
[BST_BUFFER_SIZE
];
179 /*************************************************************************************************/
180 uint8_t writeBufferPointer
= 1;
181 static void bstWrite8(uint8_t data
) {
182 writeData
[writeBufferPointer
++] = data
;
183 writeData
[0] = writeBufferPointer
;
186 static void bstWrite16(uint16_t data
)
188 bstWrite8((uint8_t)(data
>> 0));
189 bstWrite8((uint8_t)(data
>> 8));
192 static void bstWrite32(uint32_t data
)
194 bstWrite16((uint16_t)(data
>> 0));
195 bstWrite16((uint16_t)(data
>> 16));
198 uint8_t readBufferPointer
= 4;
199 static uint8_t bstCurrentAddress(void)
204 static uint8_t bstRead8(void)
206 return readData
[readBufferPointer
++] & 0xff;
209 static uint16_t bstRead16(void)
211 uint16_t t
= bstRead8();
212 t
+= (uint16_t)bstRead8() << 8;
216 static uint32_t bstRead32(void)
218 uint32_t t
= bstRead16();
219 t
+= (uint32_t)bstRead16() << 16;
223 static uint8_t bstReadDataSize(void)
225 return readData
[1]-5;
228 static uint8_t bstReadCRC(void)
230 return readData
[readData
[1]+1];
233 static const box_t
*findBoxByPermenantId(uint8_t permenantId
)
236 const box_t
*candidate
;
237 for (boxIndex
= 0; boxIndex
< sizeof(boxes
) / sizeof(box_t
); boxIndex
++) {
238 candidate
= &boxes
[boxIndex
];
239 if (candidate
->permanentId
== permenantId
) {
246 #define IS_ENABLED(mask) (mask == 0 ? 0 : 1)
248 /*************************************************************************************************/
249 #define BST_USB_COMMANDS 0x0A
250 #define BST_GENERAL_HEARTBEAT 0x0B
251 #define BST_USB_DEVICE_INFO_REQUEST 0x04 //Handshake
252 #define BST_USB_DEVICE_INFO_FRAME 0x05 //Handshake
253 #define BST_READ_COMMANDS 0x26
254 #define BST_WRITE_COMMANDS 0x25
255 #define BST_PASSED 0x01
256 #define BST_FAILED 0x00
258 static bool bstSlaveProcessFeedbackCommand(uint8_t bstRequest
)
260 uint32_t i
, tmp
, junk
;
262 switch (bstRequest
) {
263 case BST_API_VERSION
:
264 bstWrite8(BST_PROTOCOL_VERSION
);
266 bstWrite8(API_VERSION_MAJOR
);
267 bstWrite8(API_VERSION_MINOR
);
270 for (i
= 0; i
< BUILD_DATE_LENGTH
; i
++) {
271 bstWrite8(buildDate
[i
]);
273 for (i
= 0; i
< BUILD_TIME_LENGTH
; i
++) {
274 bstWrite8(buildTime
[i
]);
277 for (i
= 0; i
< GIT_SHORT_REVISION_LENGTH
; i
++) {
278 bstWrite8(shortGitRevision
[i
]);
282 bstWrite16(getTaskDeltaTimeUs(TASK_PID
));
284 bstWrite16(i2cGetErrorCounter());
288 bstWrite16(sensors(SENSOR_ACC
) | sensors(SENSOR_BARO
) << 1 | sensors(SENSOR_MAG
) << 2 | sensors(SENSOR_GPS
) << 3 | sensors(SENSOR_RANGEFINDER
) << 4);
289 // BST the flags in the order we delivered them, ignoring BOXNAMES and BOXINDEXES
290 // Requires new Multiwii protocol version to fix
291 // It would be preferable to setting the enabled bits based on BOXINDEX.
293 tmp
= IS_ENABLED(FLIGHT_MODE(ANGLE_MODE
)) << BOXANGLE
|
294 IS_ENABLED(FLIGHT_MODE(HORIZON_MODE
)) << BOXHORIZON
|
295 IS_ENABLED(FLIGHT_MODE(MAG_MODE
)) << BOXMAG
|
296 IS_ENABLED(FLIGHT_MODE(HEADFREE_MODE
)) << BOXHEADFREE
|
297 IS_ENABLED(IS_RC_MODE_ACTIVE(BOXHEADADJ
)) << BOXHEADADJ
|
298 IS_ENABLED(IS_RC_MODE_ACTIVE(BOXCAMSTAB
)) << BOXCAMSTAB
|
299 IS_ENABLED(FLIGHT_MODE(PASSTHRU_MODE
)) << BOXPASSTHRU
|
300 IS_ENABLED(IS_RC_MODE_ACTIVE(BOXBEEPERON
)) << BOXBEEPERON
|
301 IS_ENABLED(IS_RC_MODE_ACTIVE(BOXLEDLOW
)) << BOXLEDLOW
|
302 IS_ENABLED(IS_RC_MODE_ACTIVE(BOXCALIB
)) << BOXCALIB
|
303 IS_ENABLED(IS_RC_MODE_ACTIVE(BOXOSD
)) << BOXOSD
|
304 IS_ENABLED(IS_RC_MODE_ACTIVE(BOXTELEMETRY
)) << BOXTELEMETRY
|
305 IS_ENABLED(ARMING_FLAG(ARMED
)) << BOXARM
|
306 IS_ENABLED(IS_RC_MODE_ACTIVE(BOXBLACKBOX
)) << BOXBLACKBOX
|
307 IS_ENABLED(FLIGHT_MODE(FAILSAFE_MODE
)) << BOXFAILSAFE
;
308 for (i
= 0; i
< activeBoxIdCount
; i
++) {
309 int flag
= (tmp
& (1 << activeBoxIds
[i
]));
314 bstWrite8(getCurrentPidProfileIndex());
317 bstWrite16(getTaskDeltaTimeUs(TASK_PID
));
320 bstWrite8(currentControlRateProfile
->rcRates
[FD_ROLL
]);
321 bstWrite8(currentControlRateProfile
->rcExpo
[FD_ROLL
]);
322 for (i
= 0 ; i
< 3; i
++) {
323 bstWrite8(currentControlRateProfile
->rates
[i
]); // R,P,Y see flight_dynamics_index_t
325 bstWrite8(currentControlRateProfile
->tpa_rate
);
326 bstWrite8(currentControlRateProfile
->thrMid8
);
327 bstWrite8(currentControlRateProfile
->thrExpo8
);
328 bstWrite16(currentControlRateProfile
->tpa_breakpoint
);
329 bstWrite8(currentControlRateProfile
->rcExpo
[FD_YAW
]);
330 bstWrite8(currentControlRateProfile
->rcRates
[FD_YAW
]);
334 for (i
= 0; i
< PID_ITEM_COUNT
; i
++) {
335 bstWrite8(currentPidProfile
->pid
[i
].P
);
336 bstWrite8(currentPidProfile
->pid
[i
].I
);
337 bstWrite8(currentPidProfile
->pid
[i
].D
);
339 pidInitConfig(currentPidProfile
);
341 case BST_MODE_RANGES
:
342 for (i
= 0; i
< MAX_MODE_ACTIVATION_CONDITION_COUNT
; i
++) {
343 const modeActivationCondition_t
*mac
= modeActivationConditions(i
);
344 const box_t
*box
= &boxes
[mac
->modeId
];
345 bstWrite8(box
->permanentId
);
346 bstWrite8(mac
->auxChannelIndex
);
347 bstWrite8(mac
->range
.startStep
);
348 bstWrite8(mac
->range
.endStep
);
352 bstWrite16(rxConfig()->midrc
);
354 bstWrite16(motorConfig()->minthrottle
);
355 bstWrite16(motorConfig()->maxthrottle
);
356 bstWrite16(motorConfig()->mincommand
);
358 bstWrite16(failsafeConfig()->failsafe_throttle
);
361 bstWrite8(gpsConfig()->provider
); // gps_type
362 bstWrite8(0); // TODO gps_baudrate (an index, cleanflight uses a uint32_t
363 bstWrite8(gpsConfig()->sbasMode
); // gps_ubx_sbas
365 bstWrite8(0); // gps_type
366 bstWrite8(0); // TODO gps_baudrate (an index, cleanflight uses a uint32_t
367 bstWrite8(0); // gps_ubx_sbas
369 bstWrite8(0); // legacy - was multiwiiCurrentMeterOutput);
370 bstWrite8(rxConfig()->rssi_channel
);
373 bstWrite16(0); // was mag_declination / 10
375 bstWrite8(voltageSensorADCConfig(VOLTAGE_SENSOR_ADC_VBAT
)->vbatscale
);
376 bstWrite8((batteryConfig()->vbatmincellvoltage
+ 5) / 10);
377 bstWrite8((batteryConfig()->vbatmaxcellvoltage
+ 5) / 10);
378 bstWrite8((batteryConfig()->vbatwarningcellvoltage
+ 5) / 10);
382 bstWrite32(featureMask());
386 bstWrite8(rxConfig()->serialrx_provider
);
387 bstWrite16(rxConfig()->maxcheck
);
388 bstWrite16(rxConfig()->midrc
);
389 bstWrite16(rxConfig()->mincheck
);
390 bstWrite8(rxConfig()->spektrum_sat_bind
);
391 bstWrite16(rxConfig()->rx_min_usec
);
392 bstWrite16(rxConfig()->rx_max_usec
);
396 for (i
= 0; i
< RX_MAPPABLE_CHANNEL_COUNT
; i
++)
397 bstWrite8(rxConfig()->rcmap
[i
]);
403 for (i
= 0; i
< LED_CONFIGURABLE_COLOR_COUNT
; i
++) {
410 case BST_LED_STRIP_CONFIG
:
411 for (i
= 0; i
< LED_MAX_STRIP_LENGTH
; i
++) {
417 bstWrite8(rcControlsConfig()->alt_hold_deadband
);
418 bstWrite8(rcControlsConfig()->alt_hold_fast_change
);
419 bstWrite8(rcControlsConfig()->deadband
);
420 bstWrite8(rcControlsConfig()->yaw_deadband
);
426 // we do not know how to handle the (valid) message, indicate error BST
432 static bool bstSlaveProcessWriteCommand(uint8_t bstWriteCommand
)
437 bool ret
= BST_PASSED
;
438 switch (bstWriteCommand
) {
439 case BST_SELECT_SETTING
:
440 if (!ARMING_FLAG(ARMED
)) {
441 changePidProfile(bstRead8());
444 case BST_SET_LOOP_TIME
:
448 for (i
= 0; i
< PID_ITEM_COUNT
; i
++) {
449 currentPidProfile
->pid
[i
].P
= bstRead8();
450 currentPidProfile
->pid
[i
].I
= bstRead8();
451 currentPidProfile
->pid
[i
].D
= bstRead8();
454 case BST_SET_RC_TUNING
:
455 if (bstReadDataSize() >= 10) {
457 currentControlRateProfile
->rcRates
[FD_ROLL
] = bstRead8();
458 currentControlRateProfile
->rcExpo
[FD_ROLL
] = bstRead8();
459 for (i
= 0; i
< 3; i
++) {
460 currentControlRateProfile
->rates
[i
] = bstRead8();
463 currentControlRateProfile
->tpa_rate
= MIN(rate
, CONTROL_RATE_CONFIG_TPA_MAX
);
464 currentControlRateProfile
->thrMid8
= bstRead8();
465 currentControlRateProfile
->thrExpo8
= bstRead8();
466 currentControlRateProfile
->tpa_breakpoint
= bstRead16();
467 if (bstReadDataSize() >= 11) {
468 currentControlRateProfile
->rcExpo
[FD_YAW
] = bstRead8();
470 if (bstReadDataSize() >= 12) {
471 currentControlRateProfile
->rcRates
[FD_YAW
] = bstRead8();
477 case BST_SET_MODE_RANGE
:
479 if (i
< MAX_MODE_ACTIVATION_CONDITION_COUNT
) {
480 modeActivationCondition_t
*mac
= modeActivationConditionsMutable(i
);
482 const box_t
*box
= findBoxByPermenantId(i
);
484 mac
->modeId
= box
->boxId
;
485 mac
->auxChannelIndex
= bstRead8();
486 mac
->range
.startStep
= bstRead8();
487 mac
->range
.endStep
= bstRead8();
499 if (tmp
< 1600 && tmp
> 1400)
500 rxConfigMutable()->midrc
= tmp
;
502 motorConfigMutable()->minthrottle
= bstRead16();
503 motorConfigMutable()->maxthrottle
= bstRead16();
504 motorConfigMutable()->mincommand
= bstRead16();
506 failsafeConfigMutable()->failsafe_throttle
= bstRead16();
509 gpsConfigMutable()->provider
= bstRead8(); // gps_type
510 bstRead8(); // gps_baudrate
511 gpsConfigMutable()->sbasMode
= bstRead8(); // gps_ubx_sbas
513 bstRead8(); // gps_type
514 bstRead8(); // gps_baudrate
515 bstRead8(); // gps_ubx_sbas
517 bstRead8(); // legacy - was multiwiiCurrentMeterOutput
518 rxConfigMutable()->rssi_channel
= bstRead8();
521 bstRead16(); // was mag_declination / 10
523 voltageSensorADCConfigMutable(VOLTAGE_SENSOR_ADC_VBAT
)->vbatscale
= bstRead8(); // actual vbatscale as intended
524 batteryConfigMutable()->vbatmincellvoltage
= bstRead8() * 10; // vbatlevel_warn1 in MWC2.3 GUI
525 batteryConfigMutable()->vbatmaxcellvoltage
= bstRead8() * 10; // vbatlevel_warn2 in MWC2.3 GUI
526 batteryConfigMutable()->vbatwarningcellvoltage
= bstRead8() * 10; // vbatlevel when buzzer starts to alert
530 case BST_ACC_CALIBRATION
:
531 if (!ARMING_FLAG(ARMED
))
532 accStartCalibration();
537 case BST_MAG_CALIBRATION
:
538 if (!ARMING_FLAG(ARMED
)) {
539 compassStartCalibration();
544 case BST_EEPROM_WRITE
:
545 if (ARMING_FLAG(ARMED
)) {
553 case BST_SET_FEATURE
:
554 featureConfigReplace(bstRead32()); // features bitmap
556 if (featureIsEnabled(FEATURE_RX_SERIAL
)) {
557 serialConfigMutable()->portConfigs
[SERIALRX_UART
].functionMask
= FUNCTION_RX_SERIAL
;
559 serialConfigMutable()->portConfigs
[SERIALRX_UART
].functionMask
= FUNCTION_NONE
;
563 case BST_SET_RX_CONFIG
:
564 rxConfigMutable()->serialrx_provider
= bstRead8();
565 rxConfigMutable()->maxcheck
= bstRead16();
566 rxConfigMutable()->midrc
= bstRead16();
567 rxConfigMutable()->mincheck
= bstRead16();
568 rxConfigMutable()->spektrum_sat_bind
= bstRead8();
569 if (bstReadDataSize() > 8) {
570 rxConfigMutable()->rx_min_usec
= bstRead16();
571 rxConfigMutable()->rx_max_usec
= bstRead16();
575 for (i
= 0; i
< RX_MAPPABLE_CHANNEL_COUNT
; i
++) {
576 rxConfigMutable()->rcmap
[i
] = bstRead8();
581 case BST_SET_LED_COLORS
:
582 //for (i = 0; i < CONFIGURABLE_COLOR_COUNT; i++) {
590 case BST_SET_LED_STRIP_CONFIG
:
593 if (i
>= LED_MAX_STRIP_LENGTH
|| bstReadDataSize() != (1 + 4)) {
597 #if defined(USE_LED_STRIP_STATUS_MODE)
598 ledConfig_t
*ledConfig
= &ledStripStatusModeConfigMutable()->ledConfigs
[i
];
599 *ledConfig
= bstRead32();
600 reevaluateLedConfig();
606 isRebootScheduled
= true;
609 if (ARMING_FLAG(ARMED
)) {
610 disarm(DISARM_REASON_SERIAL_COMMAND
);
612 setArmingDisabled(ARMING_DISABLED_BST
);
615 unsetArmingDisabled(ARMING_DISABLED_BST
);
617 case BST_SET_DEADBAND
:
618 rcControlsConfigMutable()->alt_hold_deadband
= bstRead8();
619 rcControlsConfigMutable()->alt_hold_fast_change
= bstRead8();
620 rcControlsConfigMutable()->deadband
= bstRead8();
621 rcControlsConfigMutable()->yaw_deadband
= bstRead8();
623 case BST_SET_FC_FILTERS
:
624 bstRead16(); // 1KHz sampling no longer supported
628 // we do not know how to handle the (valid) message, indicate error BST
633 if (ret
== BST_FAILED
)
639 static bool bstSlaveUSBCommandFeedback(/*uint8_t bstFeedback*/)
641 bstWrite8(BST_USB_DEVICE_INFO_FRAME
); //Sub CPU Device Info FRAME
642 bstWrite8(sensors(SENSOR_ACC
) | sensors(SENSOR_BARO
) << 1 | sensors(SENSOR_MAG
) << 2 | sensors(SENSOR_GPS
) << 3 | sensors(SENSOR_RANGEFINDER
) << 4);
646 bstWrite8(FC_VERSION_MAJOR
); //Firmware ID
647 bstWrite8(FC_VERSION_MINOR
); //Firmware ID
653 /*************************************************************************************************/
654 #define BST_RESET_TIME 1.2*1000*1000 //micro-seconds
656 uint32_t resetBstTimer
= 0;
657 bool needResetCheck
= true;
659 extern bool cleanflight_data_ready
;
661 void bstProcessInCommand(void)
663 readBufferPointer
= 2;
664 if (bstCurrentAddress() == I2C_ADDR_CLEANFLIGHT_FC
) {
665 if (bstReadCRC() == CRC8
&& bstRead8()==BST_USB_COMMANDS
) {
667 writeBufferPointer
= 1;
668 cleanflight_data_ready
= false;
669 for (i
= 0; i
< BST_BUFFER_SIZE
; i
++) {
672 switch (bstRead8()) {
673 case BST_USB_DEVICE_INFO_REQUEST
:
675 if (bstSlaveUSBCommandFeedback(/*bstRead8()*/))
678 case BST_READ_COMMANDS
:
679 bstWrite8(BST_READ_COMMANDS
);
680 bstSlaveProcessFeedbackCommand(bstRead8());
682 case BST_WRITE_COMMANDS
:
683 bstWrite8(BST_WRITE_COMMANDS
);
684 bstSlaveProcessWriteCommand(bstRead8());
687 // we do not know how to handle the (valid) message, indicate error BST
690 cleanflight_data_ready
= true;
692 } else if (bstCurrentAddress() == 0x00) {
693 if (bstReadCRC() == CRC8
&& bstRead8()==BST_GENERAL_HEARTBEAT
) {
694 resetBstTimer
= micros();
695 needResetCheck
= true;
700 static void resetBstChecker(timeUs_t currentTimeUs
)
702 if (needResetCheck
) {
703 if (currentTimeUs
>= (resetBstTimer
+ BST_RESET_TIME
))
705 bstTimeoutUserCallback();
706 needResetCheck
= false;
711 /*************************************************************************************************/
712 #define UPDATE_AT_02HZ ((1000 * 1000) / 2)
713 static uint32_t next02hzUpdateAt_1
= 0;
715 #define UPDATE_AT_20HZ ((1000 * 1000) / 20)
716 static uint32_t next20hzUpdateAt_1
= 0;
718 static uint8_t sendCounter
= 0;
720 void taskBstMasterProcess(timeUs_t currentTimeUs
)
723 if (currentTimeUs
>= next02hzUpdateAt_1
&& !bstWriteBusy()) {
725 next02hzUpdateAt_1
= currentTimeUs
+ UPDATE_AT_02HZ
;
727 if (currentTimeUs
>= next20hzUpdateAt_1
&& !bstWriteBusy()) {
728 if (sendCounter
== 0)
729 writeRCChannelToBST();
730 else if (sendCounter
== 1)
731 writeRollPitchYawToBST();
735 next20hzUpdateAt_1
= currentTimeUs
+ UPDATE_AT_20HZ
;
738 if (sensors(SENSOR_GPS
) && !bstWriteBusy())
739 writeGpsPositionPrameToBST();
743 bstMasterWriteLoop();
744 if (isRebootScheduled
) {
748 resetBstChecker(currentTimeUs
);
751 /*************************************************************************************************/
752 static uint8_t masterWriteBufferPointer
;
753 static uint8_t masterWriteData
[BST_BUFFER_SIZE
];
755 static void bstMasterStartBuffer(uint8_t address
)
757 masterWriteData
[0] = address
;
758 masterWriteBufferPointer
= 2;
761 static void bstMasterWrite8(uint8_t data
)
763 masterWriteData
[masterWriteBufferPointer
++] = data
;
764 masterWriteData
[1] = masterWriteBufferPointer
;
767 static void bstMasterWrite16(uint16_t data
)
769 bstMasterWrite8((uint8_t)(data
>> 8));
770 bstMasterWrite8((uint8_t)(data
>> 0));
773 /*************************************************************************************************/
774 #define PUBLIC_ADDRESS 0x00
777 static void bstMasterWrite32(uint32_t data
)
779 bstMasterWrite16((uint16_t)(data
>> 16));
780 bstMasterWrite16((uint16_t)(data
>> 0));
783 static int32_t lat
= 0;
784 static int32_t lon
= 0;
785 static uint16_t altM
= 0;
786 static uint8_t numOfSat
= 0;
790 bool writeGpsPositionPrameToBST(void)
792 if ((lat
!= gpsSol
.llh
.lat
) || (lon
!= gpsSol
.llh
.lon
) || (altM
!= (gpsSol
.llh
.altCm
/ 100)) || (numOfSat
!= gpsSol
.numSat
)) {
793 lat
= gpsSol
.llh
.lat
;
794 lon
= gpsSol
.llh
.lon
;
795 altM
= gpsSol
.llh
.altCm
/ 100;
796 numOfSat
= gpsSol
.numSat
;
797 uint16_t speed
= (gpsSol
.groundSpeed
* 9 / 25);
798 uint16_t gpsHeading
= 0;
799 uint16_t altitude
= 0;
800 gpsHeading
= gpsSol
.groundCourse
* 10;
801 altitude
= altM
+ 1000; // To be verified: in m +1000m offset for neg. altitudes?
803 bstMasterStartBuffer(PUBLIC_ADDRESS
);
804 bstMasterWrite8(GPS_POSITION_FRAME_ID
);
805 bstMasterWrite32(lat
);
806 bstMasterWrite32(lon
);
807 bstMasterWrite16(speed
);
808 bstMasterWrite16(gpsHeading
);
809 bstMasterWrite16(altitude
);
810 bstMasterWrite8(numOfSat
);
811 bstMasterWrite8(0x00);
813 return bstMasterWrite(masterWriteData
);
819 bool writeRollPitchYawToBST(void)
821 int16_t X
= -attitude
.values
.pitch
* (M_PIf
/ 1800.0f
) * 10000;
822 int16_t Y
= attitude
.values
.roll
* (M_PIf
/ 1800.0f
) * 10000;
823 int16_t Z
= 0;//radiusHeading * 10000;
825 bstMasterStartBuffer(PUBLIC_ADDRESS
);
826 bstMasterWrite8(FC_ATTITUDE_FRAME_ID
);
831 return bstMasterWrite(masterWriteData
);
834 bool writeRCChannelToBST(void)
837 bstMasterStartBuffer(PUBLIC_ADDRESS
);
838 bstMasterWrite8(RC_CHANNEL_FRAME_ID
);
839 for (i
= 0; i
< (USABLE_TIMER_CHANNEL_COUNT
-1); i
++) {
840 bstMasterWrite16(rcData
[i
]);
843 return bstMasterWrite(masterWriteData
);
846 bool writeFCModeToBST(void)
849 tmp
= IS_ENABLED(ARMING_FLAG(ARMED
)) |
850 IS_ENABLED(FLIGHT_MODE(ANGLE_MODE
)) << 1 |
851 IS_ENABLED(FLIGHT_MODE(HORIZON_MODE
)) << 2 |
852 IS_ENABLED(FLIGHT_MODE(MAG_MODE
)) << 4 |
853 IS_ENABLED(IS_RC_MODE_ACTIVE(BOXAIRMODE
)) << 5 |
854 IS_ENABLED(FLIGHT_MODE(FAILSAFE_MODE
)) << 7;
856 bstMasterStartBuffer(PUBLIC_ADDRESS
);
857 bstMasterWrite8(CLEANFLIGHT_MODE_FRAME_ID
);
858 bstMasterWrite8(tmp
);
859 bstMasterWrite8(sensors(SENSOR_ACC
) | sensors(SENSOR_BARO
) << 1 | sensors(SENSOR_MAG
) << 2 | sensors(SENSOR_GPS
) << 3 | sensors(SENSOR_RANGEFINDER
) << 4);
861 return bstMasterWrite(masterWriteData
);
863 /*************************************************************************************************/