1 /* *****************************************************************************
2 * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
18 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Except as contained in this notice, the name of Maxim Integrated
23 * Products, Inc. shall not be used except as stated in the Maxim Integrated
24 * Products, Inc. Branding Policy.
25 *
26 * The mere transfer of this software does not imply any licenses
27 * of trade secrets, proprietary technology, copyrights, patents,
28 * trademarks, maskwork rights, or any other form of intellectual
29 * property whatsoever. Maxim Integrated Products, Inc. retains all
30 * ownership rights.
31 *
32 * $Date: 2019-09-11 14:32:22 -0500 (Wed, 11 Sep 2019) $
33 * $Revision: 46047 $
34 *
35 **************************************************************************** */
36
37 /* **** Includes **** */
38 #include "mxc_config.h"
39 #include "mxc_assert.h"
40 #include "mxc_sys.h"
41 #include "tmr.h"
42
43 /* **** Definitions **** */
44
45 /* **** Globals **** */
46
47 /* **** Functions **** */
48
49 /* ************************************************************************** */
TMR_Init(mxc_tmr_regs_t * tmr,tmr_pres_t pres,const sys_cfg_tmr_t * sys_cfg)50 int TMR_Init(mxc_tmr_regs_t *tmr, tmr_pres_t pres, const sys_cfg_tmr_t* sys_cfg)
51 {
52 MXC_ASSERT(tmr);
53
54 int err;
55 // System settigns
56 if((err=SYS_TMR_Init(tmr, sys_cfg)) !=E_NO_ERROR)
57 {
58 return err;
59 }
60
61 // Disable timer and clear settings
62 tmr->cn = 0;
63
64 // Clear interrupt flag
65 tmr->intr = MXC_F_TMR_INTR_IRQ_CLR;
66
67 // Set the prescaler
68 tmr->cn = pres;
69
70 return err;
71 }
72
TMR_Shutdown(mxc_tmr_regs_t * tmr)73 int TMR_Shutdown(mxc_tmr_regs_t *tmr)
74 {
75 MXC_ASSERT(tmr);
76
77 int err;
78 // System settigns
79 if((err=SYS_TMR_Shutdown(tmr)) !=E_NO_ERROR)
80 {
81 return err;
82 }
83
84 // Disable timer and clear settings
85 tmr->cn = 0;
86
87 return err;
88 }
89
90 /* ************************************************************************** */
TMR_Enable(mxc_tmr_regs_t * tmr)91 void TMR_Enable(mxc_tmr_regs_t* tmr)
92 {
93 MXC_ASSERT(tmr);
94
95 tmr->cn |= MXC_F_TMR_CN_TEN;
96 }
97
98 /* ************************************************************************** */
TMR_Disable(mxc_tmr_regs_t * tmr)99 void TMR_Disable(mxc_tmr_regs_t* tmr)
100 {
101 MXC_ASSERT(tmr);
102
103 tmr->cn &= ~(MXC_F_TMR_CN_TEN);
104 }
105
106 /* ************************************************************************** */
TMR_Config(mxc_tmr_regs_t * tmr,const tmr_cfg_t * cfg)107 int TMR_Config(mxc_tmr_regs_t *tmr, const tmr_cfg_t *cfg)
108 {
109 MXC_ASSERT(tmr);
110
111 // Configure the timer
112 tmr->cn = (tmr->cn & ~(MXC_F_TMR_CN_TMODE | MXC_F_TMR_CN_TPOL)) |
113 ((cfg->mode << MXC_F_TMR_CN_TMODE_POS) & MXC_F_TMR_CN_TMODE) |
114 ((cfg->pol << MXC_F_TMR_CN_TPOL_POS) & MXC_F_TMR_CN_TPOL);
115
116 tmr->cnt = 0x1;
117 tmr->cmp = cfg->cmp_cnt;
118
119 return E_NO_ERROR;
120 }
121
122 /* ************************************************************************** */
TMR_PWMConfig(mxc_tmr_regs_t * tmr,const tmr_pwm_cfg_t * cfg)123 int TMR_PWMConfig(mxc_tmr_regs_t *tmr, const tmr_pwm_cfg_t *cfg)
124 {
125 if (cfg->duty_cnt > cfg->per_cnt) {
126 return E_BAD_PARAM;
127 }
128
129 // Configure the timer
130 tmr->cn = (tmr->cn & ~(MXC_F_TMR_CN_TMODE | MXC_F_TMR_CN_TPOL)) |
131 MXC_S_TMR_CN_TMODE_PWM | ((cfg->pol << MXC_F_TMR_CN_TPOL_POS) & MXC_F_TMR_CN_TPOL);
132
133 tmr->cnt = 0x1;
134 tmr->cmp = cfg->per_cnt;
135 tmr->pwm = cfg->duty_cnt;
136
137 return E_NO_ERROR;
138 }
139
140 /* ************************************************************************** */
TMR_PWMSetDuty(mxc_tmr_regs_t * tmr,uint32_t duty)141 int TMR_PWMSetDuty(mxc_tmr_regs_t *tmr, uint32_t duty)
142 {
143 uint32_t cnt;
144
145 // Make sure the new Duty count is less than the period count
146 if (duty > tmr->cmp) {
147 return E_BAD_PARAM;
148 }
149
150 cnt = tmr->cnt; // make sure order of volatile access is known.
151 // Avoid glitching the output
152 if (duty >= tmr->pwm) {
153 // Wait for the count to be in the range of 1 to tmr->pwm
154 while (cnt > tmr->pwm) {
155 cnt = tmr->cnt; // update the volatile access variable
156 }
157 } else {
158 // Wait for the count to pass tmr->pwm
159 while (cnt < tmr->pwm) {
160 cnt = tmr->cnt; // update the volatile access variable
161 }
162 }
163 tmr->pwm = duty;
164
165 return E_NO_ERROR;
166 }
167
168 /* ************************************************************************** */
TMR_PWMSetPeriod(mxc_tmr_regs_t * tmr,uint32_t per)169 int TMR_PWMSetPeriod(mxc_tmr_regs_t *tmr, uint32_t per)
170 {
171 // Make sure the new Duty count is less than the period count
172 if (tmr->pwm > per) {
173 return E_BAD_PARAM;
174 }
175
176 // Wait for the count to be less than the new dut_cnt
177 while (tmr->cnt >= per) {}
178 tmr->cmp = per;
179
180 return E_NO_ERROR;
181 }
182
183
184 /* ************************************************************************** */
TMR_GetCompare(mxc_tmr_regs_t * tmr)185 uint32_t TMR_GetCompare(mxc_tmr_regs_t* tmr)
186 {
187 return tmr->cmp;
188 }
189
190 /* ************************************************************************** */
TMR_GetCapture(mxc_tmr_regs_t * tmr)191 uint32_t TMR_GetCapture(mxc_tmr_regs_t* tmr)
192 {
193 return tmr->pwm;
194 }
195
196 /* ************************************************************************* */
TMR_GetCount(mxc_tmr_regs_t * tmr)197 uint32_t TMR_GetCount(mxc_tmr_regs_t* tmr)
198 {
199 return tmr->cnt;
200 }
201
202 /* ************************************************************************* */
TMR_IntClear(mxc_tmr_regs_t * tmr)203 void TMR_IntClear(mxc_tmr_regs_t* tmr)
204 {
205 tmr->intr = MXC_F_TMR_INTR_IRQ_CLR;
206 }
207
208 /* ************************************************************************* */
TMR_IntStatus(mxc_tmr_regs_t * tmr)209 uint32_t TMR_IntStatus(mxc_tmr_regs_t* tmr)
210 {
211 return tmr->intr;
212 }
213
214 /* ************************************************************************* */
TMR_SetCompare(mxc_tmr_regs_t * tmr,uint32_t cmp_cnt)215 void TMR_SetCompare(mxc_tmr_regs_t *tmr, uint32_t cmp_cnt)
216 {
217 tmr->cmp = cmp_cnt;
218 }
219
220 /* ************************************************************************* */
TMR_SetCount(mxc_tmr_regs_t * tmr,uint32_t cnt)221 void TMR_SetCount(mxc_tmr_regs_t *tmr, uint32_t cnt)
222 {
223 tmr->cnt = cnt;
224 }
225
226 /* ************************************************************************* */
TMR_GetTicks(mxc_tmr_regs_t * tmr,uint32_t time,tmr_unit_t units,uint32_t * ticks)227 int TMR_GetTicks(mxc_tmr_regs_t *tmr, uint32_t time, tmr_unit_t units, uint32_t *ticks)
228 {
229 uint32_t unit_div0, unit_div1;
230 uint32_t timerClock;
231 uint32_t prescale;
232 uint64_t temp_ticks;
233
234 timerClock = SYS_TMR_GetFreq(tmr);
235 prescale = ((tmr->cn & MXC_F_TMR_CN_PRES) >> MXC_F_TMR_CN_PRES_POS)
236 | (((tmr->cn & MXC_F_TMR_CN_PRES3) >> (MXC_F_TMR_CN_PRES3_POS))<<3);
237
238 switch (units) {
239 case TMR_UNIT_NANOSEC:
240 unit_div0 = 1000000;
241 unit_div1 = 1000;
242 break;
243 case TMR_UNIT_MICROSEC:
244 unit_div0 = 1000;
245 unit_div1 = 1000;
246 break;
247 case TMR_UNIT_MILLISEC:
248 unit_div0 = 1;
249 unit_div1 = 1000;
250 break;
251 case TMR_UNIT_SEC:
252 unit_div0 = 1;
253 unit_div1 = 1;
254 break;
255 default:
256 return E_BAD_PARAM;
257 }
258
259 temp_ticks = (uint64_t)time * (timerClock / unit_div0) / (unit_div1 * (1 << (prescale & 0xF)));
260
261 //make sure ticks is within a 32 bit value
262 if (!(temp_ticks & 0xffffffff00000000) && (temp_ticks & 0xffffffff)) {
263 *ticks = temp_ticks;
264 return E_NO_ERROR;
265 }
266
267 return E_INVALID;
268 }
269
270 /* ************************************************************************* */
TMR_GetTime(mxc_tmr_regs_t * tmr,uint32_t ticks,uint32_t * time,tmr_unit_t * units)271 int TMR_GetTime(mxc_tmr_regs_t *tmr, uint32_t ticks, uint32_t *time, tmr_unit_t *units)
272 {
273 uint64_t temp_time = 0;
274 uint32_t timerClock = SYS_TMR_GetFreq(tmr);
275 uint32_t prescale = ((tmr->cn & MXC_F_TMR_CN_PRES) >> MXC_F_TMR_CN_PRES_POS)
276 | (((tmr->cn & MXC_F_TMR_CN_PRES3) >> (MXC_F_TMR_CN_PRES3_POS))<<3);
277
278 temp_time = (uint64_t)ticks * 1000 * (1 << (prescale & 0xF)) / (timerClock / 1000000);
279 if (!(temp_time & 0xffffffff00000000)) {
280 *time = temp_time;
281 *units = TMR_UNIT_NANOSEC;
282 return E_NO_ERROR;
283 }
284
285 temp_time = (uint64_t)ticks * 1000 * (1 << (prescale & 0xF)) / (timerClock / 1000);
286 if (!(temp_time & 0xffffffff00000000)) {
287 *time = temp_time;
288 *units = TMR_UNIT_MICROSEC;
289 return E_NO_ERROR;
290 }
291
292 temp_time = (uint64_t)ticks * 1000 * (1 << (prescale & 0xF)) / timerClock;
293 if (!(temp_time & 0xffffffff00000000)) {
294 *time = temp_time;
295 *units = TMR_UNIT_MILLISEC;
296 return E_NO_ERROR;
297 }
298
299 temp_time = (uint64_t)ticks * (1 << (prescale & 0xF)) / timerClock;
300 if (!(temp_time & 0xffffffff00000000)) {
301 *time = temp_time;
302 *units = TMR_UNIT_SEC;
303 return E_NO_ERROR;
304 }
305
306 return E_INVALID;
307 }
308