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/>.
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
;
46 STATIC_UNIT_TESTED rcsplitSwitchState_t switchStates
[BOXCAMERA3
- BOXCAMERA1
+ 1];
48 static uint8_t crc_high_first(uint8_t *ptr
, uint8_t len
)
56 crc
= (crc
<< 1) ^ 0x31;
64 static void sendCtrlCommand(rcsplit_ctrl_argument_e argument
)
66 if (!rcSplitSerialPort
)
69 uint8_t uart_buffer
[5] = {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]
80 uart_buffer
[4] = RCSPLIT_PACKET_TAIL
;
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
)
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
) {
101 uint8_t argument
= RCSPLIT_CTRL_ARGU_INVALID
;
104 argument
= RCSPLIT_CTRL_ARGU_WIFI_BTN
;
107 argument
= RCSPLIT_CTRL_ARGU_POWER_BTN
;
110 argument
= RCSPLIT_CTRL_ARGU_CHANGE_MODE
;
113 argument
= RCSPLIT_CTRL_ARGU_INVALID
;
117 if (argument
!= RCSPLIT_CTRL_ARGU_INVALID
) {
118 sendCtrlCommand(argument
);
119 switchStates
[switchIndex
].isActivated
= true;
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
);
133 rcSplitSerialPort
= openSerialPort(portConfig
->identifier
, FUNCTION_RCSPLIT
, NULL
, 115200, MODE_RXTX
, 0);
136 if (!rcSplitSerialPort
) {
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
;
149 setTaskEnabled(TASK_RCSPLIT
, true);
155 void rcSplitProcess(timeUs_t currentTimeUs
)
157 UNUSED(currentTimeUs
);
159 if (rcSplitSerialPort
== NULL
)
162 // process rcsplit custom mode if has any changed
163 rcSplitProcessMode();