1 /*
2  * Copyright (c) 2006-2023, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2022-07-28     Rbb666       first version
9  */
10 
11 #include <rtthread.h>
12 #include "drv_common.h"
13 
14 #ifdef BSP_USING_SLIDER
15 #include "cycfg_capsense.h"
16 
17 #define CAPSENSE_INTR_PRIORITY      (7u)
18 #define EZI2C_INTR_PRIORITY         (6u)
19 
20 /* Allowed duty cycle for maximum brightness */
21 #define LED_MAX_BRIGHTNESS      (100u)
22 
23 /* Allowed duty cycle for minimum brightness*/
24 #define LED_MIN_BRIGHTNESS      (0u)
25 
26 #define GET_DUTY_CYCLE(x)       (1 * 1000 * 1000 - x * 10 * 1000)
27 
28 typedef enum
29 {
30     LED_OFF,
31     LED_ON
32 } led_state_t;
33 
34 typedef struct
35 {
36     led_state_t state;
37     uint32_t brightness;
38 } led_data_t;
39 
40 static rt_sem_t trans_done_semphr = RT_NULL;
41 
42 #ifndef RT_USING_PWM
43     #error You need enable PWM to use this sample
44 #else
45     #define PWM_DEV_NAME "pwm0"
46     #define PWM_DEV_CHANNEL 3
47     static struct rt_device_pwm *pwm_dev;
48 #endif
49 
capsense_isr(void)50 static void capsense_isr(void)
51 {
52     /* enter interrupt */
53     rt_interrupt_enter();
54 
55     Cy_CapSense_InterruptHandler(CYBSP_CSD_HW, &cy_capsense_context);
56 
57     /* leave interrupt */
58     rt_interrupt_leave();
59 }
60 
capsense_callback(cy_stc_active_scan_sns_t * ptrActiveScan)61 void capsense_callback(cy_stc_active_scan_sns_t *ptrActiveScan)
62 {
63     rt_sem_release(trans_done_semphr);
64 }
65 
initialize_capsense(void)66 static uint32_t initialize_capsense(void)
67 {
68     uint32_t status = CYRET_SUCCESS;
69 
70     /* CapSense interrupt configuration parameters */
71     static const cy_stc_sysint_t capSense_intr_config =
72     {
73         .intrSrc = csd_interrupt_IRQn,
74         .intrPriority = CAPSENSE_INTR_PRIORITY,
75     };
76 
77     /* Capture the CSD HW block and initialize it to the default state. */
78     status = Cy_CapSense_Init(&cy_capsense_context);
79     if (CYRET_SUCCESS != status)
80     {
81         return status;
82     }
83 
84     /* Initialize CapSense interrupt */
85     cyhal_system_set_isr(csd_interrupt_IRQn, csd_interrupt_IRQn, CAPSENSE_INTR_PRIORITY, &capsense_isr);
86     NVIC_ClearPendingIRQ(capSense_intr_config.intrSrc);
87     NVIC_EnableIRQ(capSense_intr_config.intrSrc);
88 
89     /* Initialize the CapSense firmware modules. */
90     status = Cy_CapSense_Enable(&cy_capsense_context);
91     if (CYRET_SUCCESS != status)
92     {
93         return status;
94     }
95 
96     /* Assign a callback function to indicate end of CapSense scan. */
97     status = Cy_CapSense_RegisterCallback(CY_CAPSENSE_END_OF_SCAN_E,
98                                           capsense_callback, &cy_capsense_context);
99     if (CYRET_SUCCESS != status)
100     {
101         return status;
102     }
103 
104     return status;
105 }
106 
Slider_Init(void)107 void Slider_Init(void)
108 {
109     cy_rslt_t result;
110 
111     result = initialize_capsense();
112 
113     if (CYRET_SUCCESS != result)
114     {
115         /* Halt the CPU if CapSense initialization failed */
116         RT_ASSERT(0);
117     }
118 
119     /* Initiate first scan */
120     Cy_CapSense_ScanAllWidgets(&cy_capsense_context);
121 
122     trans_done_semphr = rt_sem_create("slider_sem", 1, RT_IPC_FLAG_PRIO);
123     if (trans_done_semphr == RT_NULL)
124     {
125         rt_kprintf("create transform done semphr failed.\n");
126         RT_ASSERT(0);
127         return;
128     }
129 
130 #ifdef BSP_USING_PWM0_PORT13
131     /* Initiate PWM*/
132     pwm_dev = (struct rt_device_pwm *)rt_device_find(PWM_DEV_NAME);
133 
134     if (pwm_dev == RT_NULL)
135     {
136         rt_kprintf("PWM init failed! can't find %s device!\n", PWM_DEV_NAME);
137         RT_ASSERT(0);
138     }
139 
140     /*default   period:1ms    pulse:0*/
141     rt_pwm_set(pwm_dev, PWM_DEV_CHANNEL, 1 * 1000 * 1000, 1 * 1000 * 1000);
142     rt_pwm_enable(pwm_dev, PWM_DEV_CHANNEL);
143 #endif
144 }
145 
update_led_state(led_data_t * ledData)146 void update_led_state(led_data_t *ledData)
147 {
148     if (ledData->brightness >= 0)
149     {
150         uint32_t brightness = (ledData->brightness < LED_MIN_BRIGHTNESS) ? LED_MIN_BRIGHTNESS : ledData->brightness;
151 
152         /* Drive the LED with brightness */
153         rt_pwm_set(pwm_dev, PWM_DEV_CHANNEL, 1 * 1000 * 1000, GET_DUTY_CYCLE(brightness));
154     }
155 }
156 
process_touch(void)157 static void process_touch(void)
158 {
159     cy_stc_capsense_touch_t *slider_touch_info;
160     uint16_t slider_pos;
161     uint8_t slider_touch_status;
162     bool led_update_req = false;
163 
164     static uint16_t slider_pos_prev;
165     static led_data_t led_data = {LED_ON, LED_MAX_BRIGHTNESS};
166 
167     /* Get slider status */
168     slider_touch_info = Cy_CapSense_GetTouchInfo(
169                             CY_CAPSENSE_LINEARSLIDER0_WDGT_ID, &cy_capsense_context);
170     slider_touch_status = slider_touch_info->numPosition;
171     slider_pos = slider_touch_info->ptrPosition->x;
172 
173     /* Detect the new touch on slider */
174     if ((RT_NULL != slider_touch_status) &&
175             (slider_pos != slider_pos_prev))
176     {
177         led_data.brightness = (slider_pos * 100)
178                               / cy_capsense_context.ptrWdConfig[CY_CAPSENSE_LINEARSLIDER0_WDGT_ID].xResolution;
179 
180         led_update_req = true;
181     }
182 
183 #ifndef RT_USING_PWM
184 #error You need enable PWM to use this sample
185 #else
186     /* Update the LED state if requested */
187     if (led_update_req)
188     {
189         update_led_state(&led_data);
190     }
191 #endif
192     slider_pos_prev = slider_pos;
193 }
194 
Slider_thread_entry(void * parameter)195 static void Slider_thread_entry(void *parameter)
196 {
197     Slider_Init();
198 
199     for (;;)
200     {
201         rt_sem_take(trans_done_semphr, RT_WAITING_FOREVER);
202 
203         /* Process all widgets */
204         Cy_CapSense_ProcessAllWidgets(&cy_capsense_context);
205 
206         /* Process touch input */
207         process_touch();
208 
209         /* Establishes synchronized operation between the CapSense
210          * middleware and the CapSense Tuner tool.
211          */
212         Cy_CapSense_RunTuner(&cy_capsense_context);
213 
214         /* Initiate next scan */
215         Cy_CapSense_ScanAllWidgets(&cy_capsense_context);
216 
217         rt_thread_mdelay(50);
218     }
219 }
220 
Slider_ctrl_sample(void)221 int Slider_ctrl_sample(void)
222 {
223     rt_err_t ret = RT_EOK;
224 
225     rt_thread_t thread = rt_thread_create("slider_th",
226                                           Slider_thread_entry,
227                                           RT_NULL,
228                                           1024,
229                                           25,
230                                           10);
231     if (thread != RT_NULL)
232     {
233         rt_thread_startup(thread);
234     }
235     else
236     {
237         ret = -RT_ERROR;
238     }
239 
240     return ret;
241 }
242 MSH_CMD_EXPORT(Slider_ctrl_sample, Slider sample to ctrl led);
243 #endif
244