1 /*
2  * Copyright (c) 2022 HPMicro
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #ifndef HPM_SDM_DRV_H
9 #define HPM_SDM_DRV_H
10 
11 #include "hpm_common.h"
12 #include "hpm_sdm_regs.h"
13 
14 /**
15  * @brief SDM APIs
16  * @defgroup sdm_interface SDM driver APIs
17  * @ingroup sdm_interfaces
18  * @{
19  */
20 
21 /* defined channel mask macro */
22 #define SAMPLING_MODE_MASK (0x7U)
23 #define CHN_SAMPLING_MODE_SHIFT(ch) ((ch) * 3U + SDM_CTRL_CHMD_SHIFT)
24 #define CHN_SAMPLING_MODE_MASK(ch) (SAMPLING_MODE_MASK << CHN_SAMPLING_MODE_SHIFT(ch))
25 
26 #define CH0_EN_MASK (0x1U << SDM_CTRL_CH_EN_SHIFT)
27 #define CHN_EN_MASK(ch) (CH0_EN_MASK << (ch))
28 
29 #define CHN_ERR_MASK(ch) (SDM_INT_EN_CH0ERR_MASK << (ch))
30 #define CHN_DRY_MASK(ch) (SDM_INT_EN_CH0DRY_MASK << (ch))
31 
32 typedef enum {
33    sdm_sampling_rising_clk_edge = 0,
34    sdm_sampling_every_clk_edge = 1,
35    sdm_sampling_manchester_mode = 2,
36    sdm_sampling_falling_clk_edge = 3,
37    sdm_sampling_rising_two_clk_edge = 4,
38    sdm_sampling_falling_two_clk_edge = 5
39 } sdm_sampling_mode_t;
40 
41 typedef enum {
42     sdm_filter_sinc1 = 0,
43     sdm_filter_sinc2 = 1,
44     sdm_filter_sinc3 = 2,
45     sdm_filter_fast_sinc2 = 3
46 } sdm_filter_type_t;
47 
48 typedef struct {
49     uint8_t clk_signal_sync; /* clk sync for channel */
50     uint8_t data_signal_sync; /* data sync for channel */
51     bool interrupt_en;
52 } sdm_control_t;
53 
54 typedef struct {
55     uint8_t sampling_mode;
56     bool enable_err_interrupt;
57     bool enable_data_ready_interrupt;
58 } sdm_channel_common_config_t;
59 
60 typedef struct {
61     uint16_t high_threshold;
62     uint16_t zero_cross_threshold;
63     uint16_t low_threshold;
64 
65     bool en_zero_cross_threshold_int;
66     bool en_clock_invalid_int;
67     bool en_high_threshold_int;
68     bool en_low_threshold_int;
69     uint8_t filter_type;                 /**< sdm_filter_type_t */
70     uint8_t oversampling_rate;           /**< 1 - 32 */
71     uint8_t ignore_invalid_samples;
72     bool enable;
73 } sdm_comparator_config_t;
74 
75 typedef struct {
76     uint8_t fifo_threshold;
77     bool en_fifo_threshold_int;
78     uint8_t manchester_threshold  :8;
79     uint8_t wdg_threshold         :8;
80     uint8_t en_af_int             :1;
81     uint8_t en_data_overflow_int  :1;
82     uint8_t en_cic_data_saturation_int  :1;
83     uint8_t en_data_ready_int           :1;
84     uint8_t sync_source                 :6;
85     uint8_t fifo_clean_on_sync          :1; /**< fifo clean by hardware when fifo interrupt occurred */
86     uint8_t wtsynaclr                   :1;
87     uint8_t wtsynmclr                   :1;
88     uint8_t wtsyncen                    :1;
89     uint8_t output_32bit                :1;
90     uint8_t data_ready_flag_by_fifo     :1;
91     uint8_t enable                      :1;
92 
93     uint8_t filter_type;                 /**< sdm_filter_type_t */
94     bool pwm_signal_sync;
95     uint8_t output_offset;               /**< 16bit mode need configure this */
96     uint16_t oversampling_rate;          /**< 1-256 */
97     uint8_t ignore_invalid_samples;
98 } sdm_filter_config_t;
99 
100 typedef struct {
101     uint32_t count;
102     uint8_t *buff;
103     uint8_t data_len_in_bytes; /* 16bit-2   32bit-4 */
104     bool using_fifo;
105 } sdm_output_config_t;
106 
107 typedef enum {
108     sdm_comparator_no_event = 0,
109     sdm_comparator_event_out_high_threshold = SDM_CH_SCST_CMPH_MASK,
110     sdm_comparator_event_out_low_threshold = SDM_CH_SCST_CMPL_MASK,
111     sdm_comparator_event_hz = SDM_CH_SCST_HZ_MASK,
112     sdm_comparator_event_invalid_clk = SDM_CH_SCST_MF_MASK
113 } sdm_comparator_event_t;
114 
115 typedef enum {
116     sdm_chn0_error_mask = SDM_INT_EN_CH0ERR_MASK,
117     sdm_chn1_error_mask = SDM_INT_EN_CH1ERR_MASK,
118     sdm_chn2_error_mask = SDM_INT_EN_CH2ERR_MASK,
119     sdm_chn3_error_mask = SDM_INT_EN_CH3ERR_MASK,
120     sdm_chn0_data_ready_mask = SDM_INT_EN_CH0DRY_MASK,
121     sdm_chn1_data_ready_mask = SDM_INT_EN_CH1DRY_MASK,
122     sdm_chn2_data_ready_mask = SDM_INT_EN_CH2DRY_MASK,
123     sdm_chn3_data_ready_mask = SDM_INT_EN_CH3DRY_MASK
124 } sdm_channel_int_status_mask_t;
125 
126 typedef enum {
127     sdm_chn0_enable_mask = 1U << SDM_CTRL_CH_EN_SHIFT,
128     sdm_chn1_enable_mask = 1U << (SDM_CTRL_CH_EN_SHIFT + 1U),
129     sdm_chn2_enable_mask = 1U << (SDM_CTRL_CH_EN_SHIFT + 2U),
130     sdm_chn3_enable_mask = 1U << (SDM_CTRL_CH_EN_SHIFT + 3U)
131 } sdm_channel_enable_mask_t;
132 
133 #ifdef __cplusplus
134 extern "C" {
135 #endif
136 
137 /**
138  * @brief sdm enable module interrupt
139  *
140  * @param ptr SDM base address
141  * @param enable true for enable, false for disable
142  */
sdm_enable_module_interrupt(SDM_Type * ptr,bool enable)143 static inline void sdm_enable_module_interrupt(SDM_Type *ptr, bool enable)
144 {
145     if (enable) {
146         ptr->CTRL |= SDM_CTRL_IE_MASK;
147     } else {
148         ptr->CTRL &= ~SDM_CTRL_IE_MASK;
149     }
150 }
151 
152 /**
153  * @brief sdm enable channel
154  *
155  * @param ptr SDM base address
156  * @param ch_index channel index
157  * @param enable true for enable, false for disable
158  */
sdm_enable_channel(SDM_Type * ptr,uint8_t ch_index,bool enable)159 static inline void sdm_enable_channel(SDM_Type *ptr, uint8_t ch_index, bool enable)
160 {
161     if (enable) {
162         ptr->CTRL |= CHN_EN_MASK(ch_index);
163     } else {
164         ptr->CTRL &= ~CHN_EN_MASK(ch_index);
165     }
166 }
167 
168 /**
169  * @brief sdm enable channel by mask
170  *
171  * @note ch_mask supports bitwise or operation, this API could enable multiple channels at the same time
172  *
173  * @param ptr SDM base address
174  * @param ch_mask sdm_channel_enable_mask_t
175  */
sdm_enable_channel_by_mask(SDM_Type * ptr,uint32_t ch_mask)176 static inline void sdm_enable_channel_by_mask(SDM_Type *ptr, uint32_t ch_mask)
177 {
178     ptr->CTRL = (ptr->CTRL & (~SDM_CTRL_CH_EN_MASK)) | ch_mask;
179 }
180 
181 /**
182  * @brief sdm set channel sampling mode
183  *
184  * @param ptr SDM base address
185  * @param ch_index channel index
186  * @param mode sdm_sampling_mode_t
187  */
sdm_set_channel_sampling_mode(SDM_Type * ptr,uint8_t ch_index,sdm_sampling_mode_t mode)188 static inline void sdm_set_channel_sampling_mode(SDM_Type *ptr, uint8_t ch_index, sdm_sampling_mode_t mode)
189 {
190     ptr->CTRL &= ~CHN_SAMPLING_MODE_MASK(ch_index);
191     ptr->CTRL |= mode << (SDM_CTRL_CHMD_SHIFT + ch_index);
192 }
193 
194 /**
195  * @brief sdm enable channel interrupt
196  *
197  * @param ptr SDM base address
198  * @param mask sdm_channel_int_status_mask_t, support bitwise or operation
199  */
sdm_enable_channel_interrupt(SDM_Type * ptr,uint32_t mask)200 static inline void sdm_enable_channel_interrupt(SDM_Type *ptr, uint32_t mask)
201 {
202     ptr->INT_EN |= mask;
203 }
204 
205 /**
206  * @brief sdm get status register value
207  *
208  * @param ptr SDM base address
209  * @return uint32_t sdm status register value
210  */
sdm_get_status(SDM_Type * ptr)211 static inline uint32_t sdm_get_status(SDM_Type *ptr)
212 {
213     return ptr->STATUS;
214 }
215 
216 /**
217  * @brief get channel data ready status
218  *
219  * @param ptr SDM base address
220  * @param ch channel
221  * @return true data ready
222  * @return false not ready
223  */
sdm_get_channel_data_ready_status(SDM_Type * ptr,uint8_t ch)224 static inline bool sdm_get_channel_data_ready_status(SDM_Type *ptr, uint8_t ch)
225 {
226     return (((ptr->STATUS) & CHN_DRY_MASK(ch)) == CHN_DRY_MASK(ch));
227 }
228 
229 /**
230  * @brief get channel error status
231  *
232  * @param ptr SDM base address
233  * @param ch channel
234  * @return true error occur
235  * @return false no error
236  */
sdm_get_channel_data_error_status(SDM_Type * ptr,uint8_t ch)237 static inline bool sdm_get_channel_data_error_status(SDM_Type *ptr, uint8_t ch)
238 {
239     return (((ptr->STATUS) & CHN_ERR_MASK(ch)) == CHN_ERR_MASK(ch));
240 }
241 
242 /**
243  * @brief sdm set channel's fifo threshold
244  *
245  * @param ptr SDM base address
246  * @param ch channel index
247  * @param threshold threshold value
248  */
sdm_set_ch_fifo_threshold(SDM_Type * ptr,uint8_t ch,uint8_t threshold)249 static inline void sdm_set_ch_fifo_threshold(SDM_Type *ptr, uint8_t ch, uint8_t threshold)
250 {
251     ptr->CH[ch].SDFIFOCTRL = SDM_CH_SDFIFOCTRL_THRSH_SET(threshold);
252 }
253 
254 /**
255  * @brief sdm get channel fifo threshold
256  *
257  * @param ptr SDM base address
258  * @param ch channel index
259  * @return uint8_t fifo threshold value
260  */
sdm_get_ch_fifo_threshold(SDM_Type * ptr,uint8_t ch)261 static inline uint8_t sdm_get_ch_fifo_threshold(SDM_Type *ptr, uint8_t ch)
262 {
263     return (uint8_t)(SDM_CH_SDFIFOCTRL_THRSH_GET(ptr->CH[ch].SDFIFOCTRL));
264 }
265 
266 /**
267  * @brief sdm get channel filter status
268  *
269  * @param ptr SDM base address
270  * @param ch channel index
271  * @return uint32_t channel filter status register value
272  */
sdm_get_channel_filter_status(SDM_Type * ptr,uint8_t ch)273 static inline uint32_t sdm_get_channel_filter_status(SDM_Type *ptr, uint8_t ch)
274 {
275     return ptr->CH[ch].SDST;
276 }
277 
278 /**
279  * @brief sdm get channel data count in fifo
280  *
281  * @param ptr SDM base address
282  * @param ch channel index
283  * @return uint8_t data count
284  */
sdm_get_channel_fifo_data_count(SDM_Type * ptr,uint8_t ch)285 static inline uint8_t sdm_get_channel_fifo_data_count(SDM_Type *ptr, uint8_t ch)
286 {
287     return (uint8_t)(SDM_CH_SDST_FILL_GET(ptr->CH[ch].SDST));
288 }
289 
290 /**
291  * @brief sdm get channel filter output data in fifo
292  *
293  * @param ptr SDM base address
294  * @param ch channel index
295  * @return int32_t data
296  */
sdm_get_channel_fifo_data(SDM_Type * ptr,uint8_t ch)297 static inline int32_t sdm_get_channel_fifo_data(SDM_Type *ptr, uint8_t ch)
298 {
299     return ptr->CH[ch].SDFIFO;
300 }
301 
302 /**
303  * @brief sdm get channel input clock cycle count
304  *
305  * @param ptr SDM base address
306  * @param ch channel index
307  * @return uint8_t clock cycle count
308  */
sdm_get_channel_clock_cycle_count(SDM_Type * ptr,uint8_t ch)309 static inline uint8_t sdm_get_channel_clock_cycle_count(SDM_Type *ptr, uint8_t ch)
310 {
311     return (uint8_t)(SDM_CH_SDST_PERIOD_MCLK_GET(ptr->CH[ch].SDST));
312 }
313 
314 /**
315  * @brief sdm get channel comparator data
316  *
317  * @param ptr SDM base address
318  * @param ch channel index
319  * @return uint16_t comparator data
320  */
sdm_get_channel_comparator_data(SDM_Type * ptr,uint8_t ch)321 static inline uint16_t sdm_get_channel_comparator_data(SDM_Type *ptr, uint8_t ch)
322 {
323     return (uint16_t)(ptr->CH[ch].SCAMP);
324 }
325 
326 /**
327  * @brief sdm set channel comparator high threshold
328  *
329  * @param ptr SDM base address
330  * @param ch channel index
331  * @param value high threshold value
332  */
sdm_set_channel_comparator_high_threshold(SDM_Type * ptr,uint8_t ch,uint16_t value)333 static inline void sdm_set_channel_comparator_high_threshold(SDM_Type *ptr, uint8_t ch, uint16_t value)
334 {
335     ptr->CH[ch].SCHTL = value;
336 }
337 
338 /**
339  * @brief sdm set channel comparator zero crossing threshold
340  *
341  * @param ptr SDM base address
342  * @param ch channel index
343  * @param value zero crossing threshold value
344  */
sdm_set_channel_comparator_zero_crossing_threshold(SDM_Type * ptr,uint8_t ch,uint16_t value)345 static inline void sdm_set_channel_comparator_zero_crossing_threshold(SDM_Type *ptr, uint8_t ch, uint16_t value)
346 {
347     ptr->CH[ch].SCHTLZ = value;
348 }
349 
350 /**
351  * @brief sdm set channel comparator low threshold
352  *
353  * @param ptr SDM base address
354  * @param ch channel index
355  * @param value low threshold value
356  */
sdm_set_channel_comparator_low_threshold(SDM_Type * ptr,uint8_t ch,uint16_t value)357 static inline void sdm_set_channel_comparator_low_threshold(SDM_Type *ptr, uint8_t ch, uint16_t value)
358 {
359     ptr->CH[ch].SCLLT = value;
360 }
361 
362 /**
363  * @brief sdm get channel comparator status register value
364  *
365  * @param ptr SDM base address
366  * @param ch channel index
367  * @return uint32_t channel comparator status register value
368  */
sdm_get_channel_comparator_status(SDM_Type * ptr,uint8_t ch)369 static inline uint32_t sdm_get_channel_comparator_status(SDM_Type *ptr, uint8_t ch)
370 {
371     return ptr->CH[ch].SCST;
372 }
373 
374 /**
375  * @brief sdm get default module control
376  *
377  * @param ptr SDM base address
378  * @param control sdm_control_t
379  */
380 void sdm_get_default_module_control(SDM_Type *ptr, sdm_control_t *control);
381 
382 /**
383  * @brief sdm init module
384  *
385  * @param ptr SDM base address
386  * @param control sdm_control_t
387  */
388 void sdm_init_module(SDM_Type *ptr, sdm_control_t *control);
389 
390 /**
391  * @brief sdm get channel common setting
392  *
393  * @param ptr SDM base address
394  * @param config sdm_channel_common_config_t
395  */
396 void sdm_get_channel_common_setting(SDM_Type *ptr, sdm_channel_common_config_t *config);
397 
398 /**
399  * @brief sdm config channel's common setting
400  *
401  * @param ptr SDM base address
402  * @param ch_index channel index
403  * @param config sdm_channel_common_config_t
404  */
405 void sdm_config_channel_common_setting(SDM_Type *ptr, uint8_t ch_index, sdm_channel_common_config_t *config);
406 
407 /**
408  * @brief sdm get channel default filter config
409  *
410  * @param ptr SDM base address
411  * @param filter_config sdm_filter_config_t
412  */
413 void sdm_get_channel_default_filter_config(SDM_Type *ptr, sdm_filter_config_t *filter_config);
414 
415 /**
416  * @brief sdm config channel filter
417  *
418  * @param ptr SDM base address
419  * @param ch_index channel index
420  * @param filter_config sdm_filter_config_t
421  */
422 void sdm_config_channel_filter(SDM_Type *ptr, uint8_t ch_index, sdm_filter_config_t *filter_config);
423 
424 /**
425  * @brief sdm get channel default comparator config
426  *
427  * @param ptr SDM base address
428  * @param cmp_config sdm_comparator_config_t
429  */
430 void sdm_get_channel_default_comparator_config(SDM_Type *ptr, sdm_comparator_config_t *cmp_config);
431 
432 /**
433  * @brief sdm config channel comparator
434  *
435  * @param ptr SDM base address
436  * @param ch_index channel index
437  * @param cmp_config sdm_comparator_config_t
438  */
439 void sdm_config_channel_comparator(SDM_Type *ptr,  uint8_t ch_index, sdm_comparator_config_t *cmp_config);
440 
441 /**
442  * @brief sdm receive one filter data
443  *
444  * @param ptr SDM base address
445  * @param ch_index channel index
446  * @param using_fifo true for getting data from fifo, false for getting data from register
447  * @param data data buff
448  * @param data_len_in_bytes output data len in bytes
449  * @retval hpm_stat_t status_success only if it succeeds
450  */
451 hpm_stat_t sdm_receive_one_filter_data(SDM_Type *ptr, uint8_t ch_index, bool using_fifo, int8_t *data, uint8_t data_len_in_bytes);
452 
453 /**
454  * @brief sdm receive filter data
455  *
456  * @param ptr SDM base address
457  * @param ch_index channel index
458  * @param using_fifo true for getting data from fifo, false for getting data from register
459  * @param data data buff
460  * @param count data count
461  * @param data_len_in_bytes output data len in bytes
462  * @retval hpm_stat_t status_success only if it succeeds
463  */
464 hpm_stat_t sdm_receive_filter_data(SDM_Type *ptr, uint8_t ch_index, bool using_fifo, int8_t *data, uint32_t count, uint8_t data_len_in_bytes);
465 
466 /**
467  * @}
468  */
469 
470 #ifdef __cplusplus
471 }
472 #endif
473 
474 #endif /* HPM_SDM_DRV_H */
475 
476