Transmit blackbox header slower on faster looptimes to avoid errors
This commit is contained in:
parent
a64fcfe960
commit
a43ae266f5
|
@ -248,13 +248,23 @@ extern uint8_t motorCount;
|
||||||
//From mw.c:
|
//From mw.c:
|
||||||
extern uint32_t currentTime;
|
extern uint32_t currentTime;
|
||||||
|
|
||||||
static const int SERIAL_CHUNK_SIZE = 16;
|
// How many bytes should we transmit per loop iteration?
|
||||||
|
static uint8_t serialChunkSize = 16;
|
||||||
|
|
||||||
static BlackboxState blackboxState = BLACKBOX_STATE_DISABLED;
|
static BlackboxState blackboxState = BLACKBOX_STATE_DISABLED;
|
||||||
|
|
||||||
static uint32_t startTime;
|
static struct {
|
||||||
static unsigned int headerXmitIndex;
|
uint32_t headerIndex;
|
||||||
static int fieldXmitIndex;
|
|
||||||
|
/* Since these fields are used during different blackbox states (never simultaneously) we can
|
||||||
|
* overlap them to save on RAM
|
||||||
|
*/
|
||||||
|
union {
|
||||||
|
int fieldIndex;
|
||||||
|
int serialBudget;
|
||||||
|
uint32_t startTime;
|
||||||
|
} u;
|
||||||
|
} xmitState;
|
||||||
|
|
||||||
static uint32_t blackboxIteration;
|
static uint32_t blackboxIteration;
|
||||||
static uint32_t blackboxPFrameIndex, blackboxIFrameIndex;
|
static uint32_t blackboxPFrameIndex, blackboxIFrameIndex;
|
||||||
|
@ -633,17 +643,17 @@ static void blackboxSetState(BlackboxState newState)
|
||||||
//Perform initial setup required for the new state
|
//Perform initial setup required for the new state
|
||||||
switch (newState) {
|
switch (newState) {
|
||||||
case BLACKBOX_STATE_SEND_HEADER:
|
case BLACKBOX_STATE_SEND_HEADER:
|
||||||
startTime = millis();
|
xmitState.headerIndex = 0;
|
||||||
headerXmitIndex = 0;
|
xmitState.u.startTime = millis();
|
||||||
break;
|
break;
|
||||||
case BLACKBOX_STATE_SEND_FIELDINFO:
|
case BLACKBOX_STATE_SEND_FIELDINFO:
|
||||||
case BLACKBOX_STATE_SEND_GPS_G_HEADERS:
|
case BLACKBOX_STATE_SEND_GPS_G_HEADERS:
|
||||||
case BLACKBOX_STATE_SEND_GPS_H_HEADERS:
|
case BLACKBOX_STATE_SEND_GPS_H_HEADERS:
|
||||||
headerXmitIndex = 0;
|
xmitState.headerIndex = 0;
|
||||||
fieldXmitIndex = -1;
|
xmitState.u.fieldIndex = -1;
|
||||||
break;
|
break;
|
||||||
case BLACKBOX_STATE_SEND_SYSINFO:
|
case BLACKBOX_STATE_SEND_SYSINFO:
|
||||||
headerXmitIndex = 0;
|
xmitState.headerIndex = 0;
|
||||||
break;
|
break;
|
||||||
case BLACKBOX_STATE_RUNNING:
|
case BLACKBOX_STATE_RUNNING:
|
||||||
blackboxIteration = 0;
|
blackboxIteration = 0;
|
||||||
|
@ -856,6 +866,15 @@ static void configureBlackboxPort(void)
|
||||||
previousBaudRate = blackboxPort->baudRate;
|
previousBaudRate = blackboxPort->baudRate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We want to write at about 7200 bytes per second to give the OpenLog a good chance to save to disk. If
|
||||||
|
* about looptime microseconds elapse between our writes, this is the budget of how many bytes we should
|
||||||
|
* transmit with each write.
|
||||||
|
*
|
||||||
|
* 9 / 1250 = 7200 / 1000000
|
||||||
|
*/
|
||||||
|
serialChunkSize = max((masterConfig.looptime * 9) / 1250, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void releaseBlackboxPort(void)
|
static void releaseBlackboxPort(void)
|
||||||
|
@ -983,7 +1002,7 @@ static void loadBlackboxState(void)
|
||||||
* Provide an array 'conditions' of FlightLogFieldCondition enums if you want these conditions to decide whether a field
|
* Provide an array 'conditions' of FlightLogFieldCondition enums if you want these conditions to decide whether a field
|
||||||
* should be included or not. Otherwise provide NULL for this parameter and NULL for secondCondition.
|
* should be included or not. Otherwise provide NULL for this parameter and NULL for secondCondition.
|
||||||
*
|
*
|
||||||
* Set headerXmitIndex to 0 and fieldXmitIndex to -1 before calling for the first time.
|
* Set xmitState.headerIndex to 0 and xmitState.u.fieldIndex to -1 before calling for the first time.
|
||||||
*
|
*
|
||||||
* secondFieldDefinition and secondCondition element pointers need to be provided in order to compute the stride of the
|
* secondFieldDefinition and secondCondition element pointers need to be provided in order to compute the stride of the
|
||||||
* fieldDefinition and secondCondition arrays.
|
* fieldDefinition and secondCondition arrays.
|
||||||
|
@ -1003,23 +1022,23 @@ static bool sendFieldDefinition(const char * const *headerNames, unsigned int he
|
||||||
* We're chunking up the header data so we don't exceed our datarate. So we'll be called multiple times to transmit
|
* We're chunking up the header data so we don't exceed our datarate. So we'll be called multiple times to transmit
|
||||||
* the whole header.
|
* the whole header.
|
||||||
*/
|
*/
|
||||||
if (fieldXmitIndex == -1) {
|
if (xmitState.u.fieldIndex == -1) {
|
||||||
if (headerXmitIndex >= headerCount)
|
if (xmitState.headerIndex >= headerCount)
|
||||||
return false; //Someone probably called us again after we had already completed transmission
|
return false; //Someone probably called us again after we had already completed transmission
|
||||||
|
|
||||||
charsWritten = blackboxPrint("H Field ");
|
charsWritten = blackboxPrint("H Field ");
|
||||||
charsWritten += blackboxPrint(headerNames[headerXmitIndex]);
|
charsWritten += blackboxPrint(headerNames[xmitState.headerIndex]);
|
||||||
charsWritten += blackboxPrint(":");
|
charsWritten += blackboxPrint(":");
|
||||||
|
|
||||||
fieldXmitIndex++;
|
xmitState.u.fieldIndex++;
|
||||||
needComma = false;
|
needComma = false;
|
||||||
} else
|
} else
|
||||||
charsWritten = 0;
|
charsWritten = 0;
|
||||||
|
|
||||||
for (; fieldXmitIndex < fieldCount && charsWritten < SERIAL_CHUNK_SIZE; fieldXmitIndex++) {
|
for (; xmitState.u.fieldIndex < fieldCount && charsWritten < serialChunkSize; xmitState.u.fieldIndex++) {
|
||||||
def = (const blackboxFieldDefinition_t*) ((const char*)fieldDefinitions + definitionStride * fieldXmitIndex);
|
def = (const blackboxFieldDefinition_t*) ((const char*)fieldDefinitions + definitionStride * xmitState.u.fieldIndex);
|
||||||
|
|
||||||
if (!conditions || testBlackboxCondition(conditions[conditionsStride * fieldXmitIndex])) {
|
if (!conditions || testBlackboxCondition(conditions[conditionsStride * xmitState.u.fieldIndex])) {
|
||||||
if (needComma) {
|
if (needComma) {
|
||||||
blackboxWrite(',');
|
blackboxWrite(',');
|
||||||
charsWritten++;
|
charsWritten++;
|
||||||
|
@ -1027,16 +1046,16 @@ static bool sendFieldDefinition(const char * const *headerNames, unsigned int he
|
||||||
needComma = true;
|
needComma = true;
|
||||||
|
|
||||||
// The first header is a field name
|
// The first header is a field name
|
||||||
if (headerXmitIndex == 0) {
|
if (xmitState.headerIndex == 0) {
|
||||||
charsWritten += blackboxPrint(def->name);
|
charsWritten += blackboxPrint(def->name);
|
||||||
} else {
|
} else {
|
||||||
//The other headers are integers
|
//The other headers are integers
|
||||||
if (def->arr[headerXmitIndex - 1] >= 10) {
|
if (def->arr[xmitState.headerIndex - 1] >= 10) {
|
||||||
blackboxWrite(def->arr[headerXmitIndex - 1] / 10 + '0');
|
blackboxWrite(def->arr[xmitState.headerIndex - 1] / 10 + '0');
|
||||||
blackboxWrite(def->arr[headerXmitIndex - 1] % 10 + '0');
|
blackboxWrite(def->arr[xmitState.headerIndex - 1] % 10 + '0');
|
||||||
charsWritten += 2;
|
charsWritten += 2;
|
||||||
} else {
|
} else {
|
||||||
blackboxWrite(def->arr[headerXmitIndex - 1] + '0');
|
blackboxWrite(def->arr[xmitState.headerIndex - 1] + '0');
|
||||||
charsWritten++;
|
charsWritten++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1044,85 +1063,115 @@ static bool sendFieldDefinition(const char * const *headerNames, unsigned int he
|
||||||
}
|
}
|
||||||
|
|
||||||
// Did we complete this line?
|
// Did we complete this line?
|
||||||
if (fieldXmitIndex == fieldCount) {
|
if (xmitState.u.fieldIndex == fieldCount) {
|
||||||
blackboxWrite('\n');
|
blackboxWrite('\n');
|
||||||
headerXmitIndex++;
|
xmitState.headerIndex++;
|
||||||
fieldXmitIndex = -1;
|
xmitState.u.fieldIndex = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return headerXmitIndex < headerCount;
|
return xmitState.headerIndex < headerCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transmit a portion of the system information headers. Begin with a xmitIndex of 0. Returns the next xmitIndex to
|
* Transmit a portion of the system information headers. Call the first time with xmitState.headerIndex == 0. Returns
|
||||||
* call with, or -1 if transmission is complete.
|
* true iff transmission is complete, otherwise call again later to continue transmission.
|
||||||
*/
|
*/
|
||||||
static int blackboxWriteSysinfo(int xmitIndex)
|
static bool blackboxWriteSysinfo()
|
||||||
{
|
{
|
||||||
union floatConvert_t {
|
union floatConvert_t {
|
||||||
float f;
|
float f;
|
||||||
uint32_t u;
|
uint32_t u;
|
||||||
} floatConvert;
|
} floatConvert;
|
||||||
|
|
||||||
switch (xmitIndex) {
|
if (xmitState.headerIndex == 0) {
|
||||||
|
xmitState.u.serialBudget = 0;
|
||||||
|
xmitState.headerIndex = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// How many bytes can we afford to transmit this loop?
|
||||||
|
xmitState.u.serialBudget = min(xmitState.u.serialBudget + serialChunkSize, 64);
|
||||||
|
|
||||||
|
// Most headers will consume at least 20 bytes so wait until we've built up that much link budget
|
||||||
|
if (xmitState.u.serialBudget < 20) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (xmitState.headerIndex) {
|
||||||
case 0:
|
case 0:
|
||||||
blackboxPrintf("H Firmware type:Cleanflight\n");
|
//Shouldn't ever get here
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
// Pause to allow more time for previous to transmit (it exceeds our chunk size)
|
blackboxPrintf("H Firmware type:Cleanflight\n");
|
||||||
|
|
||||||
|
xmitState.u.serialBudget -= strlen("H Firmware type:Cleanflight\n");
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
blackboxPrintf("H Firmware revision:%s\n", shortGitRevision);
|
blackboxPrintf("H Firmware revision:%s\n", shortGitRevision);
|
||||||
|
|
||||||
|
/* Don't need to be super exact about the budget so don't mind the fact that we're including the length of
|
||||||
|
* the placeholder "%s"
|
||||||
|
*/
|
||||||
|
xmitState.u.serialBudget -= strlen("H Firmware revision:%s\n") + strlen(shortGitRevision);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
// Pause to allow more time for previous to transmit
|
blackboxPrintf("H Firmware date:%s %s\n", buildDate, buildTime);
|
||||||
|
|
||||||
|
xmitState.u.serialBudget -= strlen("H Firmware date:%s %s\n") + strlen(buildDate) + strlen(buildTime);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
blackboxPrintf("H Firmware date:%s %s\n", buildDate, buildTime);
|
blackboxPrintf("H P interval:%d/%d\n", masterConfig.blackbox_rate_num, masterConfig.blackbox_rate_denom);
|
||||||
|
|
||||||
|
xmitState.u.serialBudget -= strlen("H P interval:%d/%d\n");
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
// Pause to allow more time for previous to transmit
|
blackboxPrintf("H rcRate:%d\n", masterConfig.controlRateProfiles[masterConfig.current_profile_index].rcRate8);
|
||||||
|
|
||||||
|
xmitState.u.serialBudget -= strlen("H rcRate:%d\n");
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
blackboxPrintf("H P interval:%d/%d\n", masterConfig.blackbox_rate_num, masterConfig.blackbox_rate_denom);
|
blackboxPrintf("H minthrottle:%d\n", masterConfig.escAndServoConfig.minthrottle);
|
||||||
|
|
||||||
|
xmitState.u.serialBudget -= strlen("H minthrottle:%d\n");
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
blackboxPrintf("H rcRate:%d\n", masterConfig.controlRateProfiles[masterConfig.current_profile_index].rcRate8);
|
blackboxPrintf("H maxthrottle:%d\n", masterConfig.escAndServoConfig.maxthrottle);
|
||||||
|
|
||||||
|
xmitState.u.serialBudget -= strlen("H maxthrottle:%d\n");
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
blackboxPrintf("H minthrottle:%d\n", masterConfig.escAndServoConfig.minthrottle);
|
|
||||||
break;
|
|
||||||
case 9:
|
|
||||||
blackboxPrintf("H maxthrottle:%d\n", masterConfig.escAndServoConfig.maxthrottle);
|
|
||||||
break;
|
|
||||||
case 10:
|
|
||||||
floatConvert.f = gyro.scale;
|
floatConvert.f = gyro.scale;
|
||||||
blackboxPrintf("H gyro.scale:0x%x\n", floatConvert.u);
|
blackboxPrintf("H gyro.scale:0x%x\n", floatConvert.u);
|
||||||
|
|
||||||
|
xmitState.u.serialBudget -= strlen("H gyro.scale:0x%x\n") + 6;
|
||||||
|
break;
|
||||||
|
case 9:
|
||||||
|
blackboxPrintf("H acc_1G:%u\n", acc_1G);
|
||||||
|
|
||||||
|
xmitState.u.serialBudget -= strlen("H acc_1G:%u\n");
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
blackboxPrintf("H vbatscale:%u\n", masterConfig.batteryConfig.vbatscale);
|
||||||
|
|
||||||
|
xmitState.u.serialBudget -= strlen("H vbatscale:%u\n");
|
||||||
break;
|
break;
|
||||||
case 11:
|
case 11:
|
||||||
blackboxPrintf("H acc_1G:%u\n", acc_1G);
|
|
||||||
break;
|
|
||||||
case 12:
|
|
||||||
blackboxPrintf("H vbatscale:%u\n", masterConfig.batteryConfig.vbatscale);
|
|
||||||
break;
|
|
||||||
case 13:
|
|
||||||
blackboxPrintf("H vbatcellvoltage:%u,%u,%u\n", masterConfig.batteryConfig.vbatmincellvoltage,
|
blackboxPrintf("H vbatcellvoltage:%u,%u,%u\n", masterConfig.batteryConfig.vbatmincellvoltage,
|
||||||
masterConfig.batteryConfig.vbatwarningcellvoltage, masterConfig.batteryConfig.vbatmaxcellvoltage);
|
masterConfig.batteryConfig.vbatwarningcellvoltage, masterConfig.batteryConfig.vbatmaxcellvoltage);
|
||||||
|
|
||||||
|
xmitState.u.serialBudget -= strlen("H vbatcellvoltage:%u,%u,%u\n");
|
||||||
break;
|
break;
|
||||||
case 14:
|
case 12:
|
||||||
//Pause
|
|
||||||
break;
|
|
||||||
case 15:
|
|
||||||
blackboxPrintf("H vbatref:%u\n", vbatReference);
|
blackboxPrintf("H vbatref:%u\n", vbatReference);
|
||||||
break;
|
|
||||||
case 16:
|
xmitState.u.serialBudget -= strlen("H vbatref:%u\n");
|
||||||
// One more pause for good luck
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -1;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return xmitIndex + 1;
|
xmitState.headerIndex++;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Beep the buzzer and write the current time to the log as a synchronization point
|
// Beep the buzzer and write the current time to the log as a synchronization point
|
||||||
|
@ -1147,26 +1196,26 @@ static void blackboxPlaySyncBeep()
|
||||||
|
|
||||||
void handleBlackbox(void)
|
void handleBlackbox(void)
|
||||||
{
|
{
|
||||||
int i, result;
|
int i;
|
||||||
|
|
||||||
switch (blackboxState) {
|
switch (blackboxState) {
|
||||||
case BLACKBOX_STATE_SEND_HEADER:
|
case BLACKBOX_STATE_SEND_HEADER:
|
||||||
//On entry of this state, headerXmitIndex is 0 and startTime is intialised
|
//On entry of this state, xmitState.headerIndex is 0 and startTime is intialised
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Once the UART has had time to init, transmit the header in chunks so we don't overflow our transmit
|
* Once the UART has had time to init, transmit the header in chunks so we don't overflow our transmit
|
||||||
* buffer.
|
* buffer.
|
||||||
*/
|
*/
|
||||||
if (millis() > startTime + 100) {
|
if (millis() > xmitState.u.startTime + 100) {
|
||||||
for (i = 0; i < SERIAL_CHUNK_SIZE && blackboxHeader[headerXmitIndex] != '\0'; i++, headerXmitIndex++)
|
for (i = 0; i < serialChunkSize && blackboxHeader[xmitState.headerIndex] != '\0'; i++, xmitState.headerIndex++)
|
||||||
blackboxWrite(blackboxHeader[headerXmitIndex]);
|
blackboxWrite(blackboxHeader[xmitState.headerIndex]);
|
||||||
|
|
||||||
if (blackboxHeader[headerXmitIndex] == '\0')
|
if (blackboxHeader[xmitState.headerIndex] == '\0')
|
||||||
blackboxSetState(BLACKBOX_STATE_SEND_FIELDINFO);
|
blackboxSetState(BLACKBOX_STATE_SEND_FIELDINFO);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case BLACKBOX_STATE_SEND_FIELDINFO:
|
case BLACKBOX_STATE_SEND_FIELDINFO:
|
||||||
//On entry of this state, headerXmitIndex is 0 and fieldXmitIndex is -1
|
//On entry of this state, xmitState.headerIndex is 0 and xmitState.u.fieldIndex is -1
|
||||||
if (!sendFieldDefinition(blackboxMainHeaderNames, ARRAY_LENGTH(blackboxMainHeaderNames), blackboxMainFields, blackboxMainFields + 1,
|
if (!sendFieldDefinition(blackboxMainHeaderNames, ARRAY_LENGTH(blackboxMainHeaderNames), blackboxMainFields, blackboxMainFields + 1,
|
||||||
ARRAY_LENGTH(blackboxMainFields), &blackboxMainFields[0].condition, &blackboxMainFields[1].condition)) {
|
ARRAY_LENGTH(blackboxMainFields), &blackboxMainFields[0].condition, &blackboxMainFields[1].condition)) {
|
||||||
#ifdef GPS
|
#ifdef GPS
|
||||||
|
@ -1179,28 +1228,26 @@ void handleBlackbox(void)
|
||||||
break;
|
break;
|
||||||
#ifdef GPS
|
#ifdef GPS
|
||||||
case BLACKBOX_STATE_SEND_GPS_H_HEADERS:
|
case BLACKBOX_STATE_SEND_GPS_H_HEADERS:
|
||||||
//On entry of this state, headerXmitIndex is 0 and fieldXmitIndex is -1
|
//On entry of this state, xmitState.headerIndex is 0 and xmitState.u.fieldIndex is -1
|
||||||
if (!sendFieldDefinition(blackboxGPSHHeaderNames, ARRAY_LENGTH(blackboxGPSHHeaderNames), blackboxGpsHFields, blackboxGpsHFields + 1,
|
if (!sendFieldDefinition(blackboxGPSHHeaderNames, ARRAY_LENGTH(blackboxGPSHHeaderNames), blackboxGpsHFields, blackboxGpsHFields + 1,
|
||||||
ARRAY_LENGTH(blackboxGpsHFields), NULL, 0)) {
|
ARRAY_LENGTH(blackboxGpsHFields), NULL, NULL)) {
|
||||||
blackboxSetState(BLACKBOX_STATE_SEND_GPS_G_HEADERS);
|
blackboxSetState(BLACKBOX_STATE_SEND_GPS_G_HEADERS);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case BLACKBOX_STATE_SEND_GPS_G_HEADERS:
|
case BLACKBOX_STATE_SEND_GPS_G_HEADERS:
|
||||||
//On entry of this state, headerXmitIndex is 0 and fieldXmitIndex is -1
|
//On entry of this state, xmitState.headerIndex is 0 and xmitState.u.fieldIndex is -1
|
||||||
if (!sendFieldDefinition(blackboxGPSGHeaderNames, ARRAY_LENGTH(blackboxGPSGHeaderNames), blackboxGpsGFields, blackboxGpsGFields + 1,
|
if (!sendFieldDefinition(blackboxGPSGHeaderNames, ARRAY_LENGTH(blackboxGPSGHeaderNames), blackboxGpsGFields, blackboxGpsGFields + 1,
|
||||||
ARRAY_LENGTH(blackboxGpsGFields), NULL, 0)) {
|
ARRAY_LENGTH(blackboxGpsGFields), NULL, NULL)) {
|
||||||
blackboxSetState(BLACKBOX_STATE_SEND_SYSINFO);
|
blackboxSetState(BLACKBOX_STATE_SEND_SYSINFO);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case BLACKBOX_STATE_SEND_SYSINFO:
|
case BLACKBOX_STATE_SEND_SYSINFO:
|
||||||
//On entry of this state, headerXmitIndex is 0
|
//On entry of this state, xmitState.headerIndex is 0
|
||||||
result = blackboxWriteSysinfo(headerXmitIndex);
|
|
||||||
|
|
||||||
if (result == -1)
|
//Keep writing chunks of the system info headers until it returns true to signal completion
|
||||||
|
if (blackboxWriteSysinfo())
|
||||||
blackboxSetState(BLACKBOX_STATE_PRERUN);
|
blackboxSetState(BLACKBOX_STATE_PRERUN);
|
||||||
else
|
|
||||||
headerXmitIndex = result;
|
|
||||||
break;
|
break;
|
||||||
case BLACKBOX_STATE_PRERUN:
|
case BLACKBOX_STATE_PRERUN:
|
||||||
blackboxPlaySyncBeep();
|
blackboxPlaySyncBeep();
|
||||||
|
|
Loading…
Reference in New Issue