Fix unused param, add PERIPH_DRIVER flag for F4, tidied up F1 and F3 in prep.
[betaflight.git] / src / main / io / rcsplit.c
blobce195cd9061fbf0a2a881c712b6fd158714f97dd
1 /*
2 * This file is part of Cleanflight.
4 * Cleanflight is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * Cleanflight is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
18 #include <stdbool.h>
19 #include <stdint.h>
20 #include <stdio.h>
21 #include <ctype.h>
23 #include <platform.h>
25 #include "common/utils.h"
27 #include "config/parameter_group.h"
28 #include "config/parameter_group_ids.h"
30 #include "drivers/serial.h"
32 #include "fc/rc_controls.h"
33 #include "fc/rc_modes.h"
35 #include "io/beeper.h"
36 #include "io/rcsplit.h"
37 #include "io/serial.h"
39 #include "scheduler/scheduler.h"
42 // communicate with camera device variables
43 STATIC_UNIT_TESTED serialPort_t *rcSplitSerialPort = NULL;
44 STATIC_UNIT_TESTED rcsplitState_e cameraState = RCSPLIT_STATE_UNKNOWN;
45 // only for unit test
46 STATIC_UNIT_TESTED rcsplitSwitchState_t switchStates[BOXCAMERA3 - BOXCAMERA1 + 1];
48 static uint8_t crc_high_first(uint8_t *ptr, uint8_t len)
50 uint8_t i;
51 uint8_t crc=0x00;
52 while (len--) {
53 crc ^= *ptr++;
54 for (i=8; i>0; --i) {
55 if (crc & 0x80)
56 crc = (crc << 1) ^ 0x31;
57 else
58 crc = (crc << 1);
61 return (crc);
64 static void sendCtrlCommand(rcsplit_ctrl_argument_e argument)
66 if (!rcSplitSerialPort)
67 return ;
69 uint8_t uart_buffer[5] = {0};
70 uint8_t crc = 0;
72 uart_buffer[0] = RCSPLIT_PACKET_HEADER;
73 uart_buffer[1] = RCSPLIT_PACKET_CMD_CTRL;
74 uart_buffer[2] = argument;
75 uart_buffer[3] = RCSPLIT_PACKET_TAIL;
76 crc = crc_high_first(uart_buffer, 4);
78 // build up a full request [header]+[command]+[argument]+[crc]+[tail]
79 uart_buffer[3] = crc;
80 uart_buffer[4] = RCSPLIT_PACKET_TAIL;
82 // write to device
83 serialWriteBuf(rcSplitSerialPort, uart_buffer, 5);
86 static void rcSplitProcessMode()
88 // if the device not ready, do not handle any mode change event
89 if (RCSPLIT_STATE_IS_READY != cameraState)
90 return ;
92 for (boxId_e i = BOXCAMERA1; i <= BOXCAMERA3; i++) {
93 uint8_t switchIndex = i - BOXCAMERA1;
94 if (IS_RC_MODE_ACTIVE(i)) {
95 // check last state of this mode, if it's true, then ignore it.
96 // Here is a logic to make a toggle control for this mode
97 if (switchStates[switchIndex].isActivated) {
98 continue;
101 uint8_t argument = RCSPLIT_CTRL_ARGU_INVALID;
102 switch (i) {
103 case BOXCAMERA1:
104 argument = RCSPLIT_CTRL_ARGU_WIFI_BTN;
105 break;
106 case BOXCAMERA2:
107 argument = RCSPLIT_CTRL_ARGU_POWER_BTN;
108 break;
109 case BOXCAMERA3:
110 argument = RCSPLIT_CTRL_ARGU_CHANGE_MODE;
111 break;
112 default:
113 argument = RCSPLIT_CTRL_ARGU_INVALID;
114 break;
117 if (argument != RCSPLIT_CTRL_ARGU_INVALID) {
118 sendCtrlCommand(argument);
119 switchStates[switchIndex].isActivated = true;
121 } else {
122 switchStates[switchIndex].isActivated = false;
127 bool rcSplitInit(void)
129 // found the port config with FUNCTION_RUNCAM_SPLIT_CONTROL
130 // User must set some UART inteface with RunCam Split at peripherals column in Ports tab
131 serialPortConfig_t *portConfig = findSerialPortConfig(FUNCTION_RCSPLIT);
132 if (portConfig) {
133 rcSplitSerialPort = openSerialPort(portConfig->identifier, FUNCTION_RCSPLIT, NULL, 115200, MODE_RXTX, 0);
136 if (!rcSplitSerialPort) {
137 return false;
140 // set init value to true, to avoid the action auto run when the flight board start and the switch is on.
141 for (boxId_e i = BOXCAMERA1; i <= BOXCAMERA3; i++) {
142 uint8_t switchIndex = i - BOXCAMERA1;
143 switchStates[switchIndex].isActivated = true;
146 cameraState = RCSPLIT_STATE_IS_READY;
148 #ifdef USE_RCSPLIT
149 setTaskEnabled(TASK_RCSPLIT, true);
150 #endif
152 return true;
155 void rcSplitProcess(timeUs_t currentTimeUs)
157 UNUSED(currentTimeUs);
159 if (rcSplitSerialPort == NULL)
160 return ;
162 // process rcsplit custom mode if has any changed
163 rcSplitProcessMode();