/** ****************************************************************************** * @addtogroup OpenPilotModules OpenPilot Modules * @{ * @addtogroup RadioComBridgeModule Com Port to Radio Bridge Module * @brief Bridge Com and Radio ports * @{ * * @file RadioComBridge.c * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012. * @brief Bridges selected Com Port to the COM VCP emulated serial port * @see The GNU Public License (GPL) Version 3 * *****************************************************************************/ /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ // **************** #include #include #include #include #include #include #include #include #include #include #if defined(PIOS_INCLUDE_FLASH_EEPROM) #include #endif #include // External functions void PIOS_InitUartMainPort(); void PIOS_InitUartFlexiPort(); void PIOS_InitPPMMainPort(bool input); void PIOS_InitPPMFlexiPort(bool input); // **************** // Private constants #define STACK_SIZE_BYTES 150 #define TASK_PRIORITY (tskIDLE_PRIORITY + 1) #define MAX_RETRIES 2 #define RETRY_TIMEOUT_MS 20 #define EVENT_QUEUE_SIZE 10 #define MAX_PORT_DELAY 200 #define EV_SEND_ACK 0x20 #define EV_SEND_NACK 0x30 // **************** // Private types typedef struct { // The task handles. xTaskHandle telemetryTxTaskHandle; xTaskHandle telemetryRxTaskHandle; xTaskHandle radioTxTaskHandle; xTaskHandle radioRxTaskHandle; // The UAVTalk connection on the com side. UAVTalkConnection outUAVTalkCon; UAVTalkConnection inUAVTalkCon; // Queue handles. xQueueHandle gcsEventQueue; xQueueHandle uavtalkEventQueue; // Error statistics. uint32_t comTxErrors; uint32_t comTxRetries; uint32_t UAVTalkErrors; uint32_t droppedPackets; // Should we parse UAVTalk? bool parseUAVTalk; // We can only configure the hardware once. bool configured; // The current configured uart speed OPLinkSettingsComSpeedOptions comSpeed; } RadioComBridgeData; // **************** // Private functions static void telemetryTxTask(void *parameters); static void telemetryRxTask(void *parameters); static void radioTxTask(void *parameters); static void radioRxTask(void *parameters); static int32_t UAVTalkSendHandler(uint8_t *buf, int32_t length); static int32_t RadioSendHandler(uint8_t *buf, int32_t length); static void ProcessInputStream(UAVTalkConnection connectionHandle, uint8_t rxbyte); static void queueEvent(xQueueHandle queue, void *obj, uint16_t instId, UAVObjEventType type); static void configureComCallback(OPLinkSettingsRemoteMainPortOptions main_port, OPLinkSettingsRemoteFlexiPortOptions flexi_port, OPLinkSettingsRemoteVCPPortOptions vcp_port, OPLinkSettingsComSpeedOptions com_speed, uint32_t min_frequency, uint32_t max_frequency, uint32_t channel_spacing); static void updateSettings(); // **************** // Private variables static RadioComBridgeData *data; /** * Start the module * * @return -1 if initialisation failed, 0 on success */ static int32_t RadioComBridgeStart(void) { if (data) { // Configure the com port configuration callback PIOS_RFM22B_SetComConfigCallback(pios_rfm22b_id, &configureComCallback); // Get the settings. OPLinkSettingsData oplinkSettings; OPLinkSettingsGet(&oplinkSettings); // Set the baudrates, etc. bool is_coordinator = PIOS_RFM22B_IsCoordinator(pios_rfm22b_id); if (is_coordinator) { // Set the frequency range. PIOS_RFM22B_SetFrequencyRange(pios_rfm22b_id, oplinkSettings.MinFrequency, oplinkSettings.MaxFrequency, oplinkSettings.ChannelSpacing); // Reinitilize the modem. PIOS_RFM22B_Reinit(pios_rfm22b_id); // We will not parse/send UAVTalk if any ports are configured as Serial (except for over the USB HID port). data->parseUAVTalk = ((oplinkSettings.MainPort != OPLINKSETTINGS_MAINPORT_SERIAL) && (oplinkSettings.FlexiPort != OPLINKSETTINGS_FLEXIPORT_SERIAL) && (oplinkSettings.VCPPort != OPLINKSETTINGS_VCPPORT_SERIAL)); } // Set the maximum radio RF power. switch (oplinkSettings.MaxRFPower) { case OPLINKSETTINGS_MAXRFPOWER_125: PIOS_RFM22B_SetTxPower(pios_rfm22b_id, RFM22_tx_pwr_txpow_0); break; case OPLINKSETTINGS_MAXRFPOWER_16: PIOS_RFM22B_SetTxPower(pios_rfm22b_id, RFM22_tx_pwr_txpow_1); break; case OPLINKSETTINGS_MAXRFPOWER_316: PIOS_RFM22B_SetTxPower(pios_rfm22b_id, RFM22_tx_pwr_txpow_2); break; case OPLINKSETTINGS_MAXRFPOWER_63: PIOS_RFM22B_SetTxPower(pios_rfm22b_id, RFM22_tx_pwr_txpow_3); break; case OPLINKSETTINGS_MAXRFPOWER_126: PIOS_RFM22B_SetTxPower(pios_rfm22b_id, RFM22_tx_pwr_txpow_4); break; case OPLINKSETTINGS_MAXRFPOWER_25: PIOS_RFM22B_SetTxPower(pios_rfm22b_id, RFM22_tx_pwr_txpow_5); break; case OPLINKSETTINGS_MAXRFPOWER_50: PIOS_RFM22B_SetTxPower(pios_rfm22b_id, RFM22_tx_pwr_txpow_6); break; case OPLINKSETTINGS_MAXRFPOWER_100: PIOS_RFM22B_SetTxPower(pios_rfm22b_id, RFM22_tx_pwr_txpow_7); break; default: // do nothing break; } // Set the initial frequency. PIOS_RFM22B_SetInitialFrequency(pios_rfm22b_id, oplinkSettings.InitFrequency); // Start the primary tasks for receiving/sending UAVTalk packets from the GCS. xTaskCreate(telemetryTxTask, (signed char *)"telemetryTxTask", STACK_SIZE_BYTES, NULL, TASK_PRIORITY, &(data->telemetryTxTaskHandle)); xTaskCreate(telemetryRxTask, (signed char *)"telemetryRxTask", STACK_SIZE_BYTES, NULL, TASK_PRIORITY, &(data->telemetryRxTaskHandle)); xTaskCreate(radioTxTask, (signed char *)"radioTxTask", STACK_SIZE_BYTES, NULL, TASK_PRIORITY, &(data->radioTxTaskHandle)); xTaskCreate(radioRxTask, (signed char *)"radioRxTask", STACK_SIZE_BYTES, NULL, TASK_PRIORITY, &(data->radioRxTaskHandle)); // Register the watchdog timers. #ifdef PIOS_INCLUDE_WDG PIOS_WDG_RegisterFlag(PIOS_WDG_TELEMETRYTX); PIOS_WDG_RegisterFlag(PIOS_WDG_TELEMETRYRX); PIOS_WDG_RegisterFlag(PIOS_WDG_RADIOTX); PIOS_WDG_RegisterFlag(PIOS_WDG_RADIORX); #endif return 0; } return -1; } /** * Initialise the module * * @return -1 if initialisation failed on success */ static int32_t RadioComBridgeInitialize(void) { // allocate and initialize the static data storage only if module is enabled data = (RadioComBridgeData *)pvPortMalloc(sizeof(RadioComBridgeData)); if (!data) { return -1; } // Initialize the UAVObjects that we use OPLinkStatusInitialize(); ObjectPersistenceInitialize(); // Initialise UAVTalk data->outUAVTalkCon = UAVTalkInitialize(&UAVTalkSendHandler); data->inUAVTalkCon = UAVTalkInitialize(&RadioSendHandler); // Initialize the queues. data->uavtalkEventQueue = xQueueCreate(EVENT_QUEUE_SIZE, sizeof(UAVObjEvent)); // Configure our UAVObjects for updates. UAVObjConnectQueue(UAVObjGetByID(OPLINKSTATUS_OBJID), data->uavtalkEventQueue, EV_UPDATED | EV_UPDATED_MANUAL | EV_UPDATE_REQ); UAVObjConnectQueue(UAVObjGetByID(OBJECTPERSISTENCE_OBJID), data->uavtalkEventQueue, EV_UPDATED | EV_UPDATED_MANUAL); #if defined(PIOS_INCLUDE_RFM22B_GCSRECEIVER) UAVObjConnectQueue(UAVObjGetByID(GCSRECEIVER_OBJID), data->uavtalkEventQueue, EV_UPDATED | EV_UPDATED_MANUAL | EV_UPDATE_REQ); #endif // Initialize the statistics. data->comTxErrors = 0; data->comTxRetries = 0; data->UAVTalkErrors = 0; data->parseUAVTalk = true; data->configured = false; data->comSpeed = OPLINKSETTINGS_COMSPEED_9600; PIOS_COM_RADIO = PIOS_COM_RFM22B; return 0; } MODULE_INITCALL(RadioComBridgeInitialize, RadioComBridgeStart) /** * Telemetry transmit task, regular priority * * @param[in] parameters The task parameters */ static void telemetryTxTask(__attribute__((unused)) void *parameters) { UAVObjEvent ev; // Loop forever while (1) { #ifdef PIOS_INCLUDE_WDG PIOS_WDG_UpdateFlag(PIOS_WDG_TELEMETRYTX); #endif // Wait for queue message if (xQueueReceive(data->uavtalkEventQueue, &ev, MAX_PORT_DELAY) == pdTRUE) { if ((ev.event == EV_UPDATED) || (ev.event == EV_UPDATE_REQ)) { // Send update (with retries) uint32_t retries = 0; int32_t success = -1; while (retries < MAX_RETRIES && success == -1) { success = UAVTalkSendObject(data->outUAVTalkCon, ev.obj, 0, 0, RETRY_TIMEOUT_MS) == 0; if (!success) { ++retries; } } data->comTxRetries += retries; } else if (ev.event == EV_SEND_ACK) { // Send the ACK uint32_t retries = 0; int32_t success = -1; while (retries < MAX_RETRIES && success == -1) { success = UAVTalkSendAck(data->outUAVTalkCon, ev.obj, ev.instId) == 0; if (!success) { ++retries; } } data->comTxRetries += retries; } else if (ev.event == EV_SEND_NACK) { // Send the NACK uint32_t retries = 0; int32_t success = -1; while (retries < MAX_RETRIES && success == -1) { success = UAVTalkSendNack(data->outUAVTalkCon, UAVObjGetID(ev.obj)) == 0; if (!success) { ++retries; } } data->comTxRetries += retries; } } } } /** * Radio tx task. Receive data packets from the com port and send to the radio. * * @param[in] parameters The task parameters */ static void radioTxTask(__attribute__((unused)) void *parameters) { // Task loop while (1) { #ifdef PIOS_INCLUDE_WDG PIOS_WDG_UpdateFlag(PIOS_WDG_RADIOTX); #endif // Wait until the com port is available. if (data->parseUAVTalk || !PIOS_COM_TELEMETRY) { vTaskDelay(5); continue; } // Read from the com port. uint8_t serial_data[1]; uint16_t bytes_to_process = PIOS_COM_ReceiveBuffer(PIOS_COM_TELEMETRY, serial_data, sizeof(serial_data), MAX_PORT_DELAY); if (bytes_to_process > 0) { PIOS_COM_SendBufferNonBlocking(PIOS_COM_RADIO, serial_data, bytes_to_process); } } } /** * Radio rx task. Receive data packets from the radio and pass them on. * * @param[in] parameters The task parameters */ static void radioRxTask(__attribute__((unused)) void *parameters) { // Task loop while (1) { #ifdef PIOS_INCLUDE_WDG PIOS_WDG_UpdateFlag(PIOS_WDG_RADIORX); #endif uint8_t serial_data[1]; uint16_t bytes_to_process = PIOS_COM_ReceiveBuffer(PIOS_COM_RADIO, serial_data, sizeof(serial_data), MAX_PORT_DELAY); if (bytes_to_process > 0) { // Either pass the data through the UAVTalk parser, or just send it to the radio (if we're doing raw comms). if (data->parseUAVTalk) { for (uint8_t i = 0; i < bytes_to_process; i++) { if (UAVTalkRelayInputStream(data->outUAVTalkCon, serial_data[i]) == UAVTALK_STATE_ERROR) { data->UAVTalkErrors++; } } } else if (PIOS_COM_TELEMETRY) { PIOS_COM_SendBufferNonBlocking(PIOS_COM_TELEMETRY, serial_data, bytes_to_process); } } } } /** * Receive telemetry from the USB/COM port. * * @param[in] parameters The task parameters */ static void telemetryRxTask(__attribute__((unused)) void *parameters) { // Task loop while (1) { uint32_t inputPort = data->parseUAVTalk ? PIOS_COM_TELEMETRY : 0; #ifdef PIOS_INCLUDE_WDG PIOS_WDG_UpdateFlag(PIOS_WDG_TELEMETRYRX); #endif #if defined(PIOS_INCLUDE_USB) // Determine output port (USB takes priority over telemetry port) if (PIOS_USB_CheckAvailable(0) && PIOS_COM_TELEM_USB_HID) { inputPort = PIOS_COM_TELEM_USB_HID; } #endif /* PIOS_INCLUDE_USB */ if (inputPort) { uint8_t serial_data[1]; uint16_t bytes_to_process = PIOS_COM_ReceiveBuffer(inputPort, serial_data, sizeof(serial_data), MAX_PORT_DELAY); if (bytes_to_process > 0) { for (uint8_t i = 0; i < bytes_to_process; i++) { ProcessInputStream(data->inUAVTalkCon, serial_data[i]); } } } else { vTaskDelay(5); } } } /** * Transmit data buffer to the com port. * * @param[in] buf Data buffer to send * @param[in] length Length of buffer * @return -1 on failure * @return number of bytes transmitted on success */ static int32_t UAVTalkSendHandler(uint8_t *buf, int32_t length) { uint32_t outputPort = data->parseUAVTalk ? PIOS_COM_TELEMETRY : 0; #if defined(PIOS_INCLUDE_USB) // Determine output port (USB takes priority over telemetry port) if (PIOS_COM_TELEM_USB_HID && PIOS_COM_Available(PIOS_COM_TELEM_USB_HID)) { outputPort = PIOS_COM_TELEM_USB_HID; } #endif /* PIOS_INCLUDE_USB */ if (outputPort) { return PIOS_COM_SendBufferNonBlocking(outputPort, buf, length); } else { return -1; } } /** * Transmit data buffer to the com port. * * @param[in] buf Data buffer to send * @param[in] length Length of buffer * @return -1 on failure * @return number of bytes transmitted on success */ static int32_t RadioSendHandler(uint8_t *buf, int32_t length) { uint32_t outputPort = PIOS_COM_RADIO; // Don't send any data unless the radio port is available. if (outputPort && PIOS_COM_Available(outputPort)) { return PIOS_COM_SendBufferNonBlocking(outputPort, buf, length); } else { // For some reason, if this function returns failure, it prevents saving settings. return length; } } /** * Process a byte of data received * * @param[in] connectionHandle The UAVTalk connection handle * @param[in] rxbyte The received byte. */ static void ProcessInputStream(UAVTalkConnection connectionHandle, uint8_t rxbyte) { // Keep reading until we receive a completed packet. UAVTalkRxState state = UAVTalkRelayInputStream(connectionHandle, rxbyte); UAVTalkConnectionData *connection = (UAVTalkConnectionData *)(connectionHandle); UAVTalkInputProcessor *iproc = &(connection->iproc); if (state == UAVTALK_STATE_COMPLETE) { // Is this a local UAVObject? // We only generate GcsReceiver ojects, we don't consume them. if ((iproc->obj != NULL) && (iproc->objId != GCSRECEIVER_OBJID)) { // We treat the ObjectPersistence object differently if (iproc->objId == OBJECTPERSISTENCE_OBJID) { // Unpack object, if the instance does not exist it will be created! UAVObjUnpack(iproc->obj, iproc->instId, connection->rxBuffer); // Get the ObjectPersistence object. ObjectPersistenceData obj_per; ObjectPersistenceGet(&obj_per); // Is this concerning or setting object? if (obj_per.ObjectID == OPLINKSETTINGS_OBJID) { // Queue up the ACK. queueEvent(data->uavtalkEventQueue, (void *)iproc->obj, iproc->instId, EV_SEND_ACK); // Is this a save, load, or delete? bool success = true; switch (obj_per.Operation) { case OBJECTPERSISTENCE_OPERATION_LOAD: { #if defined(PIOS_INCLUDE_FLASH_LOGFS_SETTINGS) // Load the settings. void *obj = UAVObjGetByID(obj_per.ObjectID); if (obj == 0) { success = false; } else { // Load selected instance success = (UAVObjLoad(obj, obj_per.InstanceID) == 0); } #endif break; } case OBJECTPERSISTENCE_OPERATION_SAVE: { #if defined(PIOS_INCLUDE_FLASH_LOGFS_SETTINGS) void *obj = UAVObjGetByID(obj_per.ObjectID); if (obj == 0) { success = false; } else { // Save selected instance success = UAVObjSave(obj, obj_per.InstanceID) == 0; } #endif break; } case OBJECTPERSISTENCE_OPERATION_DELETE: { #if defined(PIOS_INCLUDE_FLASH_LOGFS_SETTINGS) void *obj = UAVObjGetByID(obj_per.ObjectID); if (obj == 0) { success = false; } else { // Save selected instance success = UAVObjDelete(obj, obj_per.InstanceID) == 0; } #endif break; } default: break; } if (success == true) { obj_per.Operation = OBJECTPERSISTENCE_OPERATION_COMPLETED; ObjectPersistenceSet(&obj_per); } } } else { switch (iproc->type) { case UAVTALK_TYPE_OBJ: // Unpack object, if the instance does not exist it will be created! UAVObjUnpack(iproc->obj, iproc->instId, connection->rxBuffer); break; case UAVTALK_TYPE_OBJ_REQ: // Queue up an object send request. queueEvent(data->uavtalkEventQueue, (void *)iproc->obj, iproc->instId, EV_UPDATE_REQ); break; case UAVTALK_TYPE_OBJ_ACK: if (UAVObjUnpack(iproc->obj, iproc->instId, connection->rxBuffer) == 0) { // Queue up an ACK queueEvent(data->uavtalkEventQueue, (void *)iproc->obj, iproc->instId, EV_SEND_ACK); } break; } } } } else if (state == UAVTALK_STATE_ERROR) { data->UAVTalkErrors++; // Send a NACK if required. if ((iproc->obj) && (iproc->type == UAVTALK_TYPE_OBJ_ACK)) { // Queue up a NACK queueEvent(data->uavtalkEventQueue, iproc->obj, iproc->instId, EV_SEND_NACK); } } } /** * Queue and event into an event queue. * * @param[in] queue The event queue * @param[in] obj The data pointer * @param[in] type The event type */ static void queueEvent(xQueueHandle queue, void *obj, uint16_t instId, UAVObjEventType type) { UAVObjEvent ev; ev.obj = (UAVObjHandle)obj; ev.instId = instId; ev.event = type; xQueueSend(queue, &ev, portMAX_DELAY); } /** * Configure the output port based on a configuration event from the remote coordinator. * * @param[in] com_port The com port to configure * @param[in] com_speed The com port speed */ static void configureComCallback(OPLinkSettingsRemoteMainPortOptions main_port, OPLinkSettingsRemoteFlexiPortOptions flexi_port, OPLinkSettingsRemoteVCPPortOptions vcp_port, OPLinkSettingsComSpeedOptions com_speed, uint32_t min_frequency, uint32_t max_frequency, uint32_t channel_spacing) { // Update the com baud rate data->comSpeed = com_speed; // Set the output main/flexi/vcp port and speed. bool is_coordinator = PIOS_RFM22B_IsCoordinator(pios_rfm22b_id); if (!is_coordinator) { // Get the settings. OPLinkSettingsData oplinkSettings; OPLinkSettingsGet(&oplinkSettings); switch (main_port) { case OPLINKSETTINGS_REMOTEMAINPORT_DISABLED: oplinkSettings.MainPort = OPLINKSETTINGS_MAINPORT_DISABLED; break; case OPLINKSETTINGS_REMOTEMAINPORT_SERIAL: oplinkSettings.MainPort = OPLINKSETTINGS_MAINPORT_SERIAL; break; case OPLINKSETTINGS_REMOTEMAINPORT_PPM: oplinkSettings.MainPort = OPLINKSETTINGS_MAINPORT_PPM; break; } switch (flexi_port) { case OPLINKSETTINGS_REMOTEFLEXIPORT_DISABLED: oplinkSettings.FlexiPort = OPLINKSETTINGS_FLEXIPORT_DISABLED; break; case OPLINKSETTINGS_REMOTEFLEXIPORT_SERIAL: oplinkSettings.FlexiPort = OPLINKSETTINGS_FLEXIPORT_SERIAL; break; case OPLINKSETTINGS_REMOTEFLEXIPORT_PPM: oplinkSettings.FlexiPort = OPLINKSETTINGS_FLEXIPORT_PPM; break; } switch (vcp_port) { case OPLINKSETTINGS_REMOTEVCPPORT_DISABLED: oplinkSettings.VCPPort = OPLINKSETTINGS_VCPPORT_DISABLED; break; case OPLINKSETTINGS_REMOTEVCPPORT_SERIAL: oplinkSettings.VCPPort = OPLINKSETTINGS_VCPPORT_SERIAL; break; } // Set the frequency range. PIOS_RFM22B_SetFrequencyRange(pios_rfm22b_id, min_frequency, max_frequency, channel_spacing); // We will not parse/send UAVTalk if any ports are configured as Serial (except for over the USB HID port). data->parseUAVTalk = ((oplinkSettings.MainPort != OPLINKSETTINGS_MAINPORT_SERIAL) && (oplinkSettings.FlexiPort != OPLINKSETTINGS_FLEXIPORT_SERIAL) && (oplinkSettings.VCPPort != OPLINKSETTINGS_VCPPORT_SERIAL)); // Update the OPLinkSettings object. OPLinkSettingsSet(&oplinkSettings); } // Perform the update. updateSettings(); } /** * Update the oplink settings. */ static void updateSettings() { // Get the settings. OPLinkSettingsData oplinkSettings; OPLinkSettingsGet(&oplinkSettings); // We can only configure the hardware once. if (data->configured) { return; } data->configured = true; // Configure the main port bool is_coordinator = PIOS_RFM22B_IsCoordinator(pios_rfm22b_id); switch (oplinkSettings.MainPort) { case OPLINKSETTINGS_MAINPORT_TELEMETRY: case OPLINKSETTINGS_MAINPORT_SERIAL: /* Configure the main port for uart serial */ PIOS_InitUartMainPort(); PIOS_COM_TELEMETRY = PIOS_COM_TELEM_UART_MAIN; break; case OPLINKSETTINGS_MAINPORT_PPM: PIOS_InitPPMMainPort(is_coordinator); break; case OPLINKSETTINGS_MAINPORT_DISABLED: break; } // Configure the flexi port switch (oplinkSettings.FlexiPort) { case OPLINKSETTINGS_FLEXIPORT_TELEMETRY: case OPLINKSETTINGS_FLEXIPORT_SERIAL: /* Configure the flexi port as uart serial */ PIOS_InitUartFlexiPort(); PIOS_COM_TELEMETRY = PIOS_COM_TELEM_UART_FLEXI; break; case OPLINKSETTINGS_FLEXIPORT_PPM: PIOS_InitPPMFlexiPort(is_coordinator); break; case OPLINKSETTINGS_FLEXIPORT_DISABLED: break; } // Configure the USB VCP port switch (oplinkSettings.VCPPort) { case OPLINKSETTINGS_VCPPORT_SERIAL: PIOS_COM_TELEMETRY = PIOS_COM_TELEM_USB_VCP; break; case OPLINKSETTINGS_VCPPORT_DISABLED: break; } // Update the com baud rate. uint32_t comBaud = 9600; switch (data->comSpeed) { case OPLINKSETTINGS_COMSPEED_2400: comBaud = 2400; break; case OPLINKSETTINGS_COMSPEED_4800: comBaud = 4800; break; case OPLINKSETTINGS_COMSPEED_9600: comBaud = 9600; break; case OPLINKSETTINGS_COMSPEED_19200: comBaud = 19200; break; case OPLINKSETTINGS_COMSPEED_38400: comBaud = 38400; break; case OPLINKSETTINGS_COMSPEED_57600: comBaud = 57600; break; case OPLINKSETTINGS_COMSPEED_115200: comBaud = 115200; break; } if (PIOS_COM_RADIO) { PIOS_COM_ChangeBaud(PIOS_COM_RADIO, comBaud); } if (PIOS_COM_TELEMETRY) { PIOS_COM_ChangeBaud(PIOS_COM_TELEMETRY, comBaud); } }