1
0
Fork 0
mirror of https://github.com/betaflight/betaflight.git synced 2025-07-22 15:55:48 +03:00

Allow the user to specify their serial port scenarios.

This commit is contained in:
Dominic Clifton 2014-05-10 01:57:12 +01:00
parent 5043370b2f
commit 0fd127bf60
8 changed files with 258 additions and 50 deletions

View file

@ -15,28 +15,38 @@
#include "serial_msp.h"
#include "serial_common.h"
#include "config.h"
void mspInit(serialConfig_t *serialConfig);
void cliInit(serialConfig_t *serialConfig);
void resetSerialConfig(serialConfig_t *serialConfig);
// this exists so the user can reference scenarios by a number in the CLI instead of an unuser-friendly bitmask.
const serialPortFunctionScenario_e serialPortScenarios[SERIAL_PORT_SCENARIO_COUNT] = {
SCENARIO_UNUSED,
// common scenarios in order of importance
SCENARIO_MSP_CLI_TELEMETRY_GPS_PASTHROUGH,
SCENARIO_GPS_ONLY,
SCENARIO_SERIAL_RX_ONLY,
SCENARIO_TELEMETRY_ONLY,
// other scenarios
SCENARIO_MSP_CLI_GPS_PASTHROUGH,
SCENARIO_CLI_ONLY,
SCENARIO_GPS_PASSTHROUGH_ONLY,
SCENARIO_MSP_ONLY
};
static serialConfig_t *serialConfig;
static serialPort_t *serialPorts[SERIAL_PORT_COUNT];
static serialPortFunction_t serialPortFunctions[SERIAL_PORT_COUNT] = {
{SERIAL_PORT_USART1, NULL, SCENARIO_MAIN_PORT, FUNCTION_NONE},
{SERIAL_PORT_USART2, NULL, SCENARIO_GPS_AND_TELEMETRY, FUNCTION_NONE},
{SERIAL_PORT_SOFTSERIAL1, NULL, SCENARIO_UNUSED, FUNCTION_NONE},
{SERIAL_PORT_SOFTSERIAL2, NULL, SCENARIO_UNUSED, FUNCTION_NONE}
{SERIAL_PORT_USART1, NULL, SCENARIO_UNUSED, FUNCTION_NONE},
{SERIAL_PORT_USART2, NULL, SCENARIO_UNUSED, FUNCTION_NONE},
{SERIAL_PORT_SOFTSERIAL1, NULL, SCENARIO_UNUSED, FUNCTION_NONE},
{SERIAL_PORT_SOFTSERIAL2, NULL, SCENARIO_UNUSED, FUNCTION_NONE}
};
#if 0 // example using softserial for telemetry, note that it is used because the scenario is more specific than telemetry on usart1
static serialPortFunction_t serialPortFunctions[SERIAL_PORT_COUNT] = {
{SERIAL_PORT_USART1, NULL, SCENARIO_MAIN_PORT, FUNCTION_NONE},
{SERIAL_PORT_USART2, NULL, SCENARIO_GPS_ONLY, FUNCTION_NONE},
{SERIAL_PORT_SOFTSERIAL1, NULL, SCENARIO_TELEMETRY_ONLY, FUNCTION_NONE},
{SERIAL_PORT_SOFTSERIAL2, NULL, SCENARIO_UNUSED, FUNCTION_NONE}
};
#endif
const static serialPortConstraint_t serialPortConstraints[SERIAL_PORT_COUNT] = {
{SERIAL_PORT_USART1, 9600, 115200, SPF_NONE | SPF_SUPPORTS_SBUS_MODE },
{SERIAL_PORT_USART2, 9600, 115200, SPF_SUPPORTS_CALLBACK | SPF_SUPPORTS_SBUS_MODE},
@ -61,23 +71,42 @@ const functionConstraint_t functionConstraints[] = {
#define FUNCTION_CONSTRAINT_COUNT (sizeof(functionConstraints) / sizeof(functionConstraint_t))
typedef struct serialPortSearchResult_s {
bool found;
serialPortIndex_e portIndex;
serialPortFunction_t *portFunction;
const serialPortConstraint_t *portConstraint;
const functionConstraint_t *functionConstraint;
} serialPortSearchResult_t;
static serialPortIndex_e findSerialPortIndexByIdentifier(serialPortIdentifier_e identifier)
uint8_t lookupScenarioIndex(serialPortFunctionScenario_e scenario) {
uint8_t index;
for (index = 0; index < SERIAL_PORT_SCENARIO_COUNT; index++) {
if (serialPortScenarios[index] == scenario) {
break;
}
}
return index;
}
static serialPortIndex_e lookupSerialPortIndexByIdentifier(serialPortIdentifier_e identifier)
{
serialPortIndex_e portIndex;
for (portIndex = 0; portIndex < SERIAL_PORT_COUNT; portIndex++) {
if (serialPortConstraints[portIndex].identifier == identifier) {
return portIndex;
break;
}
}
return portIndex;
}
return SERIAL_PORT_1; // FIXME use failureMode() ? - invalid identifier used.
static uint8_t lookupSerialPortFunctionIndexByIdentifier(serialPortIdentifier_e identifier)
{
uint8_t index;
for (index = 0; index < SERIAL_PORT_COUNT; index++) {
if (serialPortFunctions[index].identifier == identifier) {
break;
}
}
return index;
}
static const functionConstraint_t *findFunctionConstraint(serialPortFunction_e function)
@ -113,7 +142,6 @@ static void sortSerialPortFunctions(serialPortFunction_t *serialPortFunctions, u
qsort(serialPortFunctions, elements, sizeof(serialPortFunction_t), serialPortFunctionMostSpecificFirstComparator);
}
/*
* since this method, and other methods that use it, use a single instance of
* searchPortSearchResult be sure to copy the data out of it before it gets overwritten by another caller.
@ -122,7 +150,6 @@ static void sortSerialPortFunctions(serialPortFunction_t *serialPortFunctions, u
static serialPortSearchResult_t *findSerialPort(serialPortFunction_e function)
{
static serialPortSearchResult_t serialPortSearchResult;
serialPortSearchResult.found = false;
const functionConstraint_t *functionConstraint = findFunctionConstraint(function);
if (!functionConstraint) {
@ -140,9 +167,16 @@ static serialPortSearchResult_t *findSerialPort(serialPortFunction_e function)
continue;
}
uint8_t serialPortIndex = findSerialPortIndexByIdentifier(serialPortFunction->identifier);
uint8_t serialPortIndex = lookupSerialPortIndexByIdentifier(serialPortFunction->identifier);
const serialPortConstraint_t *serialPortConstraint = &serialPortConstraints[serialPortIndex];
if (!canSoftwareSerialBeUsed() && (
serialPortConstraint->identifier == SERIAL_PORT_SOFTSERIAL1 ||
serialPortConstraint->identifier == SERIAL_PORT_SOFTSERIAL2
)) {
continue;
}
if (functionConstraint->requiredSerialPortFeatures != SPF_NONE) {
if (!(serialPortConstraint->feature & functionConstraint->requiredSerialPortFeatures)) {
continue;
@ -155,17 +189,16 @@ static serialPortSearchResult_t *findSerialPort(serialPortFunction_e function)
serialPortSearchResult.portConstraint = serialPortConstraint;
serialPortSearchResult.portFunction = serialPortFunction;
serialPortSearchResult.functionConstraint = functionConstraint;
serialPortSearchResult.found = true;
break;
return &serialPortSearchResult;
}
return &serialPortSearchResult;
return NULL;
}
bool canOpenSerialPort(uint16_t functionMask)
{
serialPortSearchResult_t *result = findSerialPort(functionMask);
return result->found;
return result != NULL;
}
serialPortFunction_t *findSerialPortFunction(uint16_t functionMask)
@ -212,7 +245,7 @@ serialPort_t *openSerialPort(serialPortFunction_e function, serialReceiveCallbac
serialPortSearchResult_t *searchResult = findSerialPort(function);
if (!searchResult->found) {
if (!searchResult) {
return NULL;
}
serialPortIndex_e portIndex = searchResult->portIndex;
@ -284,9 +317,56 @@ void endSerialPortFunction(serialPort_t *port, serialPortFunction_e function)
serialPortFunction->currentFunction = FUNCTION_NONE;
}
bool isSerialConfigValid(serialConfig_t *serialConfig)
{
serialPortSearchResult_t *searchResult;
searchResult = findSerialPort(FUNCTION_MSP);
if (!searchResult) {
return false;
}
searchResult = findSerialPort(FUNCTION_CLI);
if (!searchResult) {
return false;
}
searchResult = findSerialPort(FUNCTION_GPS);
if (feature(FEATURE_GPS) && !searchResult) {
return false;
}
searchResult = findSerialPort(FUNCTION_SERIAL_RX);
if (feature(FEATURE_SERIALRX) && !searchResult) {
return false;
}
searchResult = findSerialPort(FUNCTION_TELEMETRY);
if (feature(FEATURE_TELEMETRY) && !searchResult) {
return false;
}
return true;
}
void applySerialConfigToPortFunctions(serialConfig_t *serialConfig)
{
serialPortFunctions[lookupSerialPortFunctionIndexByIdentifier(SERIAL_PORT_USART1)].scenario = serialPortScenarios[serialConfig->serial_port_1_scenario];
serialPortFunctions[lookupSerialPortFunctionIndexByIdentifier(SERIAL_PORT_USART2)].scenario = serialPortScenarios[serialConfig->serial_port_2_scenario];
serialPortFunctions[lookupSerialPortFunctionIndexByIdentifier(SERIAL_PORT_SOFTSERIAL1)].scenario = serialPortScenarios[serialConfig->serial_port_3_scenario];
serialPortFunctions[lookupSerialPortFunctionIndexByIdentifier(SERIAL_PORT_SOFTSERIAL2)].scenario = serialPortScenarios[serialConfig->serial_port_4_scenario];
}
void serialInit(serialConfig_t *initialSerialConfig)
{
serialConfig = initialSerialConfig;
applySerialConfigToPortFunctions(serialConfig);
if (!isSerialConfigValid(serialConfig)) {
resetSerialConfig(serialConfig);
applySerialConfigToPortFunctions(serialConfig);
}
mspInit(serialConfig);
cliInit(serialConfig);