1+ /******************************************************************************
2+ * Copyright 2024 The Firmament Authors. All Rights Reserved.
3+ *
4+ * Licensed under the Apache License, Version 2.0 (the "License");
5+ * you may not use this file except in compliance with the License.
6+ * You may obtain a copy of the License at
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
10+ * Unless required by applicable law or agreed to in writing, software
11+ * distributed under the License is distributed on an "AS IS" BASIS,
12+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+ * See the License for the specific language governing permissions and
14+ * limitations under the License.
15+ *****************************************************************************/
16+
17+ #include <firmament.h>
18+
19+ #include "hal/rc/ppm.h"
20+ #include "hal/rc/rc.h"
21+ #include "hal/rc/sbus.h"
22+
23+ #include "cy_pdl.h"
24+ #include "cycfg_peripherals.h"
25+
26+ #ifndef min // mod by prife
27+ #define min (x , y ) (x < y ? x : y)
28+ #endif
29+
30+ #define TIMER_FREQ_HZ 1000000UL
31+
32+ #define RC_CONFIG_DEFAULT \
33+ { \
34+ RC_PROTOCOL_AUTO, /* auto */ \
35+ 6 , /* 6 channel */ \
36+ 0.05f , /* sample time */ \
37+ 1000 , /* minimal 1000us */ \
38+ 2000 , /* maximal 2000us */ \
39+ }
40+
41+ static ppm_decoder_t ppm_decoder ;
42+ static sbus_decoder_t sbus_decoder ;
43+
44+ void RC_TIMER_IRQHandler (void )
45+ {
46+ rt_interrupt_enter ();
47+
48+ uint32_t int_source = Cy_TCPWM_GetInterruptStatusMasked (RC_TIMER_HW , RC_TIMER_NUM );
49+
50+ if (int_source & CY_TCPWM_INT_ON_CC0 ) {
51+ uint32_t capture = Cy_TCPWM_Counter_GetCapture0Val (RC_TIMER_HW , RC_TIMER_NUM ) + 1 ;
52+ // rt_kprintf("%d\n", capture);
53+ ppm_update (& ppm_decoder , capture );
54+ }
55+ Cy_TCPWM_ClearInterrupt (RC_TIMER_HW , RC_TIMER_NUM , CY_TCPWM_INT_ON_CC0 );
56+
57+ rt_interrupt_leave ();
58+ }
59+
60+ static rt_err_t rc_init (rc_dev_t dev )
61+ {
62+ (void )dev ;
63+
64+ RT_TRY (ppm_decoder_init (& ppm_decoder , TIMER_FREQ_HZ ));
65+
66+ if (CY_TCPWM_SUCCESS != Cy_TCPWM_Counter_Init (RC_TIMER_HW , RC_TIMER_NUM , & RC_TIMER_config )) {
67+ return RT_ERROR ;
68+ }
69+
70+ Cy_TCPWM_Counter_Enable (RC_TIMER_HW , RC_TIMER_NUM );
71+ Cy_TCPWM_TriggerStart_Single (RC_TIMER_HW , RC_TIMER_NUM );
72+
73+ Cy_TCPWM_SetInterruptMask (RC_TIMER_HW , RC_TIMER_NUM , CY_TCPWM_INT_ON_CC0 );
74+
75+ cy_stc_sysint_t intr_cfg = {
76+ .intrSrc = RC_TIMER_IRQ ,
77+ .intrPriority = 3U ,
78+ };
79+
80+ if (CY_SYSINT_SUCCESS != Cy_SysInt_Init (& intr_cfg , RC_TIMER_IRQHandler )) {
81+ return RT_ERROR ;
82+ }
83+
84+ NVIC_EnableIRQ (RC_TIMER_IRQ );
85+
86+ return RT_EOK ;
87+ }
88+
89+ static rt_err_t rc_control (rc_dev_t rc , int cmd , void * arg )
90+ {
91+ switch (cmd ) {
92+ case RC_CMD_CHECK_UPDATE : {
93+ uint8_t updated = 0 ;
94+
95+ if (rc -> config .protocol == RC_PROTOCOL_SBUS ) {
96+ updated = sbus_data_ready (& sbus_decoder );
97+ } else if (rc -> config .protocol == RC_PROTOCOL_PPM ) {
98+ updated = ppm_data_ready (& ppm_decoder );
99+ }
100+
101+ * (uint8_t * )arg = updated ;
102+ } break ;
103+
104+ default :
105+ break ;
106+ }
107+
108+ return RT_EOK ;
109+ }
110+
111+ static rt_uint16_t rc_read (rc_dev_t rc , rt_uint16_t chan_mask , rt_uint16_t * chan_val )
112+ {
113+ uint16_t * index = chan_val ;
114+ rt_uint16_t rb = 0 ;
115+
116+ if (rc -> config .protocol == RC_PROTOCOL_SBUS ) {
117+ if (sbus_data_ready (& sbus_decoder ) == 0 ) {
118+ /* no data received, just return */
119+ return 0 ;
120+ }
121+
122+ sbus_lock (& sbus_decoder );
123+
124+ for (uint8_t i = 0 ; i < min (rc -> config .channel_num , sbus_decoder .rc_count ); i ++ ) {
125+ * (index ++ ) = sbus_decoder .sbus_val [i ];
126+ rb += 2 ;
127+ }
128+ sbus_data_clear (& sbus_decoder );
129+
130+ sbus_unlock (& sbus_decoder );
131+ } else if (rc -> config .protocol == RC_PROTOCOL_PPM ) {
132+ if (ppm_data_ready (& ppm_decoder ) == 0 ) {
133+ /* no data received, just return */
134+ return 0 ;
135+ }
136+
137+ ppm_lock (& ppm_decoder );
138+
139+ for (uint8_t i = 0 ; i < min (rc -> config .channel_num , ppm_decoder .total_chan ); i ++ ) {
140+ if (chan_mask & (1 << i )) {
141+ * (index ++ ) = ppm_decoder .ppm_val [i ];
142+ rb += 2 ;
143+ }
144+ }
145+ ppm_data_clear (& ppm_decoder );
146+
147+ ppm_unlock (& ppm_decoder );
148+ }
149+
150+ return rb ;
151+ }
152+
153+ const static struct rc_ops rc_ops = {
154+ .rc_init = rc_init ,
155+ .rc_config = NULL ,
156+ .rc_control = rc_control ,
157+ .rc_read = rc_read ,
158+ };
159+
160+ static struct rc_device rc_dev = {
161+ .config = RC_CONFIG_DEFAULT ,
162+ .ops = & rc_ops ,
163+ };
164+
165+ rt_err_t drv_rc_init (void )
166+ {
167+ RT_TRY (hal_rc_register (& rc_dev , "rc" , RT_DEVICE_FLAG_RDWR , NULL ));
168+ return RT_EOK ;
169+ }
0 commit comments