1 /***************************************************************************//**
2 * \file cy_evtgen.c
3 * \version 1.0
4 *
5 * \brief
6 * Provides API implementation of the Event generator Driver.
7 *
8 ********************************************************************************
9 * \copyright
10 * Copyright 2016-2022 Cypress Semiconductor Corporation. All rights reserved.
11 * You may use this file only in accordance with the license, terms, conditions,
12 * disclaimers, and limitations in the end user license agreement accompanying
13 * the software package with which this file was provided.
14 *******************************************************************************/
15 
16 #include "cy_evtgen.h"
17 
18 #ifdef CY_IP_MXEVTGEN
19 
20 #define RATIO_FRAC_SHIFT   100UL       /* This value is required to shift the fractional comma by two characters.
21                                          It needs for the selection fractional part ratio. */
22 
23 /*******************************************************************************
24 * Function Name: Cy_EvtGen_RatioCalculate
25 ****************************************************************************//**
26 *
27 * Internal function for calculate two part of the RATIO register.
28 *
29 * \param frequencyTick
30 * High frequency of the Event Generator.
31 *
32 * \param frequencyLf
33 * Low frequency of the Event Generator.
34 *
35 * \param ratioInt
36 * The pointer to a variable where the integer part is stored.
37 *
38 * \param ratioFrac
39 * The pointer to a variable where the fractional part is stored.
40 *
41 *******************************************************************************/
Cy_EvtGen_RatioCalculate(uint32_t frequencyTick,uint32_t frequencyLf,uint16_t * ratioInt,uint8_t * ratioFrac)42 static void Cy_EvtGen_RatioCalculate(uint32_t frequencyTick, uint32_t frequencyLf, uint16_t* ratioInt, uint8_t* ratioFrac)
43 {
44     uint32_t tempInt = 0;
45     float tempFrac = (float)frequencyTick / (float)frequencyLf;
46 
47     tempInt = (uint32_t)tempFrac;
48     tempFrac = tempFrac - (float)tempInt;
49     tempFrac = (tempFrac * (float)RATIO_FRAC_SHIFT);
50 
51     *ratioFrac = (uint8_t)tempFrac;
52     *ratioInt = (uint16_t)tempInt;
53 }
54 
55 /*******************************************************************************
56 * Function Name: Cy_EvtGen_Init
57 ****************************************************************************//**
58 *
59 * Initialize the event generator
60 *
61 * \param base
62 * Pointer to structure describing registers
63 *
64 * \param config
65 * Pointer to the event generator config structure base address
66 *
67 * \return
68 * Event generator initialization status
69 *
70 *******************************************************************************/
Cy_EvtGen_Init(EVTGEN_Type * base,const cy_stc_evtgen_config_t * config)71 cy_en_evtgen_status_t Cy_EvtGen_Init(EVTGEN_Type *base, const cy_stc_evtgen_config_t* config)
72 {
73     cy_en_evtgen_status_t ret = CY_EVTGEN_BAD_PARAM;
74 
75     /* Checking input parameter valid */
76     if ((NULL != base) && (NULL != config))
77     {
78         if ((config->frequencyRef != 0UL) && (config->frequencyTick != 0UL))
79         {
80             uint32_t refDiv;
81 
82             /* Setting divider value of clk_ref */
83             refDiv = config->frequencyRef / config->frequencyTick;
84 
85             CY_ASSERT_L1(CY_EVTGEN_IS_DIVIDER_VALID_RANGE(refDiv));
86 
87             if(((config->frequencyRef % config->frequencyTick) == 0UL) && ((refDiv <= 256UL) && (refDiv  > 0UL)))
88             {
89                 CY_MISRA_DEVIATE_LINE('MISRA C-2012 Rule 10.8','Intentional typecast to uint8_t.');
90                 base->REF_CLOCK_CTL = _VAL2FLD(EVTGEN_REF_CLOCK_CTL_INT_DIV, (uint8_t)(refDiv - 1UL));
91 
92                 /* Setting ratio operation */
93                 if(config->ratioControlMode == CY_EVTGEN_RATIO_CONTROL_SW)
94                 {
95                     /* SW control: setting value for ratio value should be ratio between tick_ref_div and clk_lf. */
96                     uint8_t ratioFrac;
97                     uint16_t ratioInt;
98                     Cy_EvtGen_RatioCalculate(config->frequencyTick, config->frequencyLf, &ratioInt, &ratioFrac);
99 
100                     base->RATIO = (_VAL2FLD(EVTGEN_RATIO_FRAC8, ratioFrac)) | (_VAL2FLD(EVTGEN_RATIO_INT16, ratioInt));
101 
102                     /* SW control: valid bit should be set manually. */
103                     base->RATIO_CTL &= ~EVTGEN_RATIO_CTL_DYNAMIC_Msk;
104                     base->RATIO_CTL |= EVTGEN_RATIO_CTL_VALID_Msk;
105                 }
106                 else
107                 {
108                     /* HW control: */
109                     base->RATIO_CTL |= EVTGEN_RATIO_CTL_DYNAMIC_Msk |
110                                     (_VAL2FLD(EVTGEN_RATIO_CTL_DYNAMIC_MODE, config->ratioValueDynamicMode));
111                 }
112                 ret = CY_EVTGEN_SUCCESS;
113             }
114         }
115     }
116     return (ret);
117 }
118 
119 /*******************************************************************************
120 * Function Name: Cy_EvtGen_DeInit
121 ****************************************************************************//**
122 *
123 * Deinitialize event generator
124 *
125 * \param base
126 * Pointer to structure describing registers
127 *
128 *******************************************************************************/
Cy_EvtGen_DeInit(EVTGEN_Type * base)129 void Cy_EvtGen_DeInit(EVTGEN_Type *base)
130 {
131     CY_ASSERT_L1(base);
132 
133     /* Returns block registers into the default state */
134     base->CTL = 0UL;
135     base->REF_CLOCK_CTL = 0UL;
136     base->RATIO = 0UL;
137     base->RATIO_CTL = 0UL;
138     base->INTR_MASK = 0UL;
139     base->INTR_DPSLP_MASK = 0UL;
140 }
141 
142 /*******************************************************************************
143 * Function Name: Cy_EvtGen_InitStruct
144 ****************************************************************************//**
145 *
146 * Initialize a comparator structure
147 *
148 * \param base
149 * Pointer to structure describing registers
150 *
151 * \param structNum
152 * Number of structure to be initialized. Valid range from 0 to 16.
153 *
154 * \param configStruct
155 * Pointer to the event generator structure config structure base address
156 *
157 * \return
158 * Event generator initialization status
159 *
160 *******************************************************************************/
Cy_EvtGen_InitStruct(EVTGEN_Type * base,uint8_t structNum,const cy_stc_evtgen_struct_config_t * configStruct)161 cy_en_evtgen_status_t Cy_EvtGen_InitStruct(EVTGEN_Type *base,
162                                                         uint8_t structNum,
163                                                         const cy_stc_evtgen_struct_config_t* configStruct)
164 {
165     cy_en_evtgen_status_t ret = CY_EVTGEN_BAD_PARAM;
166 
167     /* Checking input parameter valid */
168     if ((NULL != base) && (NULL != configStruct) && (EVTGEN_COMP_STRUCT_NR > structNum))
169     {
170         uint64_t tempCounterValue = 0UL;
171         uint32_t tempCompStructCompCTL = 0UL;
172 
173         tempCompStructCompCTL = base->COMP_STRUCT[structNum].COMP_CTL;
174 
175         if (CY_EVTGEN_DEEPSLEEP_FUNCTIONALITY == configStruct->functionalitySelection)
176         {
177             tempCompStructCompCTL |= EVTGEN_COMP_STRUCT_COMP_CTL_COMP1_EN_Msk;
178         }
179 
180         tempCompStructCompCTL |= EVTGEN_COMP_STRUCT_COMP_CTL_COMP0_EN_Msk |
181                                  (_VAL2FLD(EVTGEN_COMP_STRUCT_COMP_CTL_TR_OUT_EDGE, configStruct->triggerOutEdge)) |
182                                  EVTGEN_COMP_STRUCT_COMP_CTL_ENABLED_Msk;
183 
184         CY_MISRA_DEVIATE_LINE('MISRA C-2012 Rule 10.8','Intentional typecast to uint64_t.');
185         tempCounterValue = (uint64_t) (_FLD2VAL(EVTGEN_COUNTER_INT32, base->COUNTER));
186 
187         /* Setting active comparator value */
188         base->COMP_STRUCT[structNum].COMP0 = (uint32_t) (tempCounterValue + (uint64_t) configStruct->valueActiveComparator);
189 
190         /* Setting deep sleep comparator value */
191         if (CY_EVTGEN_DEEPSLEEP_FUNCTIONALITY == configStruct->functionalitySelection)
192         {
193             base->COMP_STRUCT[structNum].COMP1 = (uint32_t)(tempCounterValue + (uint64_t)configStruct->valueDeepSleepComparator);
194         }
195 
196         /* Setting comparator struct control parameter */
197         base->COMP_STRUCT[structNum].COMP_CTL = tempCompStructCompCTL;
198 
199         Cy_EvtGen_SetStructInterruptMask(base, structNum);
200         if (CY_EVTGEN_DEEPSLEEP_FUNCTIONALITY == configStruct->functionalitySelection)
201         {
202             Cy_EvtGen_SetStructInterruptDeepSleepMask(base, structNum);
203         }
204 
205         ret = CY_EVTGEN_SUCCESS;
206     }
207     return (ret);
208 }
209 
210 /*******************************************************************************
211 * Function Name: Cy_EvtGen_DeinitStruct
212 ****************************************************************************//**
213 *
214 * Deinitialize event generator struct
215 *
216 * \param base
217 * Pointer to structure describing registers
218 *
219 * \param structNum
220 * Number of structure to be de-initialized. Valid range from 0 to 16.
221 *
222 *******************************************************************************/
Cy_EvtGen_DeinitStruct(EVTGEN_Type * base,uint8_t structNum)223 void Cy_EvtGen_DeinitStruct(EVTGEN_Type *base, uint8_t structNum)
224 {
225     CY_ASSERT_L1(CY_EVTGEN_IS_BASE_VALID(base));
226     CY_ASSERT_L1(CY_EVTGEN_IS_STRUCTNUM_VALID(structNum));
227 
228     base->COMP_STRUCT[structNum].COMP_CTL = 0UL;
229     base->COMP_STRUCT[structNum].COMP0 = 0UL;
230     base->COMP_STRUCT[structNum].COMP1 = 0UL;
231 }
232 
233 /*******************************************************************************
234 * Function Name: Cy_EvtGen_UpdateActiveCompValue
235 ****************************************************************************//**
236 *
237 * Update active comparator value corresponding comparator structure.
238 *
239 * \param base
240 * Pointer to structure describing registers
241 *
242 * \param structNum
243 * Number of structure to be update value. Valid range from 0 to 15.
244 *
245 * \param newCompareValue
246 * Value for update active comparator value.
247 *
248 *******************************************************************************/
Cy_EvtGen_UpdateActiveCompValue(EVTGEN_Type * base,uint8_t structNum,uint32_t newCompareValue)249 void Cy_EvtGen_UpdateActiveCompValue(EVTGEN_Type *base, uint8_t structNum, uint32_t newCompareValue)
250 {
251     CY_ASSERT_L1(CY_EVTGEN_IS_STRUCTNUM_VALID(structNum));
252 
253     /* Note: In cases where the current value of the comparator is close to MAX_INT
254     then the update may lead to overflow. Using 64 bit handles this case. Cast to
255     32 bit is safe brings the value to what it will be after the counter overflows. */
256     uint64_t tempCompValue = (uint64_t) EVTGEN0->COMP_STRUCT[structNum].COMP0;
257     tempCompValue += newCompareValue;
258 
259     base->COMP_STRUCT[structNum].COMP_CTL &= ~EVTGEN_COMP_STRUCT_COMP_CTL_COMP0_EN_Msk;
260     base->COMP_STRUCT[structNum].COMP0 = (uint32_t) tempCompValue;
261     base->COMP_STRUCT[structNum].COMP_CTL |= EVTGEN_COMP_STRUCT_COMP_CTL_COMP0_EN_Msk;
262 }
263 
264 /*******************************************************************************
265 * Function Name: Cy_EvtGen_UpdateDeepSleepCompValue
266 ****************************************************************************//**
267 *
268 * Update Deep Sleep comparator value corresponding comparator structure.
269 *
270 * \param base
271 * Pointer to structure describing registers
272 *
273 * \param structNum
274 * Number of structure to be update value. Valid range from 0 to 15.
275 *
276 * \param newCompareValue
277 * Value for update Deep Sleep comparator value.
278 *
279 *******************************************************************************/
Cy_EvtGen_UpdateDeepSleepCompValue(EVTGEN_Type * base,uint8_t structNum,uint32_t newCompareValue)280 void Cy_EvtGen_UpdateDeepSleepCompValue(EVTGEN_Type *base, uint8_t structNum, uint32_t newCompareValue)
281 {
282     CY_ASSERT_L1(CY_EVTGEN_IS_STRUCTNUM_VALID(structNum));
283 
284     /* Note: In cases where the current value of the comparator is close to MAX_INT
285     then the update may lead to overflow. Using 64 bit handles this case. Cast to
286     32 bit is safe brings the value to what it will be after the counter overflows. */
287     uint64_t tempCompValue = (uint64_t) EVTGEN0->COMP_STRUCT[structNum].COMP1;
288     tempCompValue += newCompareValue;
289 
290     base->COMP_STRUCT[structNum].COMP_CTL &= ~EVTGEN_COMP_STRUCT_COMP_CTL_COMP1_EN_Msk;
291     base->COMP_STRUCT[structNum].COMP1 = (uint32_t) tempCompValue;
292     base->COMP_STRUCT[structNum].COMP_CTL |= EVTGEN_COMP_STRUCT_COMP_CTL_COMP1_EN_Msk;
293 }
294 
295 #endif /* CY_IP_MXEVTGEN */
296 
297 /* [] END OF FILE */
298