PIC24 Support Libraries
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pic24_timer.c
Go to the documentation of this file.
1 /*
2  * "Copyright (c) 2008 Robert B. Reese, Bryan A. Jones, J. W. Bruce ("AUTHORS")"
3  * All rights reserved.
4  * (R. Reese, reese_AT_ece.msstate.edu, Mississippi State University)
5  * (B. A. Jones, bjones_AT_ece.msstate.edu, Mississippi State University)
6  * (J. W. Bruce, jwbruce_AT_ece.msstate.edu, Mississippi State University)
7  *
8  * Permission to use, copy, modify, and distribute this software and its
9  * documentation for any purpose, without fee, and without written agreement is
10  * hereby granted, provided that the above copyright notice, the following
11  * two paragraphs and the authors appear in all copies of this software.
12  *
13  * IN NO EVENT SHALL THE "AUTHORS" BE LIABLE TO ANY PARTY FOR
14  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
15  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE "AUTHORS"
16  * HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
17  *
18  * THE "AUTHORS" SPECIFICALLY DISCLAIMS ANY WARRANTIES,
19  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
20  * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
21  * ON AN "AS IS" BASIS, AND THE "AUTHORS" HAS NO OBLIGATION TO
22  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
23  *
24  * Please maintain this header in its entirety when copying/modifying
25  * these files.
26  *
27  *
28  */
29 
30 
31 
32 // Documentation for this file. If the \file tag isn't present,
33 // this file won't be documented.
34 /** \file
35  * To do.
36  */
37 
38 #include "pic24_timer.h"
39 #include "pic24_clockfreq.h"
40 #include "pic24_unittest.h"
41 #include "pic24_util.h"
42 
43 /*********************************
44  * Function private to this file *
45  *********************************/
46 
47 
48 /** Converts milliseconds to 16-bit timer ticks.
49  * \param u16_ms Time, in milliseconds, to convert to ticks
50  * \param u16_pre Prescale set for this timer. Note that
51  * \ref getTimerPrescale can easily determine
52  * this.
53  * \return Timer ticks corresponding to the given number of
54  * milliseconds.
55  */
57 // Use a float internally for precision purposes to accomodate wide range of FCY, u16_pre
58  float f_ticks = FCY;
59  uint16_t u16_ticks;
60  f_ticks = (f_ticks*u16_ms)/u16_pre/1000L;
61  ASSERT(f_ticks < 65535.5);
62  u16_ticks = roundFloatToUint16(f_ticks); //back to integer
63  return u16_ticks;
64 }
65 
66 /** Converts microseconds to 16-bit timer ticks.
67  * \param u16_us Time, in microseconds, to convert to ticks
68  * \param u16_pre Prescale set for this timer. Note that
69  * \ref getTimerPrescale can easily determine
70  * this.
71  * \return Timer ticks corresponding to the given number of
72  * microseconds.
73  */
75  // Use a float internally for precision purposes to accomodate wide range of FCY, u16_pre
76  float f_ticks = FCY;
77  uint16_t u16_ticks;
78  f_ticks = (f_ticks*u16_us)/u16_pre/1000000L;
79  ASSERT(f_ticks < 65535.5);
80  u16_ticks = roundFloatToUint16(f_ticks); //back to integer
81  return u16_ticks;
82 
83 }
84 
85 /** Converts microseconds to 32-bit timer ticks.
86  * \param u32_us Time, in microseconds, to convert to ticks
87  * \param u16_pre Prescale set for this timer. Note that
88  * \ref getTimerPrescale can easily determine
89  * this.
90  * \return Timer ticks corresponding to the given number of
91  * microseconds.
92  */
94 // Use a float internally for precision purposes to accomodate wide range of FCY, u16_pre
95  float f_ticks = FCY;
96  uint32_t u32_ticks;
97  f_ticks = (f_ticks*u32_us)/u16_pre/1000000L;
98  u32_ticks = roundFloatToUint32(f_ticks); //back to integer
99  return u32_ticks;
100 }
101 
102 
103 
104 /** Given the TCKPS bitfield, return the timer prescale encoded
105  * by these bits. Use \ref getTimerPrescale as a convenient
106  * way to extract the TCKPS bitfield from a TxCONbits SFT
107  * then call this function.
108  * \param u8_TCKPS TCKPS bitfield from the timer in question
109  * \return Prescale value.
110  */
112  uint16_t au16_prescaleValue[] = { 1, 8, 64, 256 };
113  ASSERT(u8_TCKPS <= 3);
114  return au16_prescaleValue[u8_TCKPS];
115 }
116 
117 /** Converts timer ticks to milliseconds
118  * \param u32_ticks Timer ticks
119  * \param u16_tmrPre Timer prescale value
120  * \return time in milliseconds
121  */
122 uint32_t ticksToMs (uint32_t u32_ticks, uint16_t u16_tmrPre) {
123  //because of the wide range of the numbers, use a float for precision
124  float f_ticks;
125  uint32_t u32_timeMs;
126 
127  f_ticks = u32_ticks; //convert to float
128  f_ticks = ((f_ticks * u16_tmrPre)/FCY) * 1000;
129  u32_timeMs = roundFloatToUint32(f_ticks); //back to int32_t
130  return (u32_timeMs);
131 }
132 
133 
134 /** Converts timer ticks to microseconds
135  * \param u32_ticks Timer ticks
136  * \param u16_tmrPre Timer prescale value
137  * \return time in microseconds
138  */
139 uint32_t ticksToUs (uint32_t u32_ticks, uint16_t u16_tmrPre) {
140  //because of the wide range of the numbers, use a float for precision
141  float f_ticks;
142  uint32_t u32_timeUs;
143 
144  f_ticks = u32_ticks; //convert to float
145  f_ticks = ((f_ticks * u16_tmrPre)/FCY) * 1000000L;
146  u32_timeUs = roundFloatToUint32(f_ticks); //back to int32_t
147  return (u32_timeUs);
148 }
149 
150 /** Converts timer ticks to nanoseconds
151  * \param u32_ticks Timer ticks
152  * \param u16_tmrPre Timer prescale value
153  * \return time in nanoseconds
154  */
155 uint32_t ticksToNs (uint32_t u32_ticks, uint16_t u16_tmrPre) {
156  //because of the wide range of the numbers, use a float for precision
157  float f_ticks;
158  uint32_t u32_timeNs;
159 
160  f_ticks = u32_ticks; //convert to float
161  f_ticks = ((f_ticks * u16_tmrPre)/FCY) * 1000000000L;
162  u32_timeNs = roundFloatToUint32(f_ticks); //back to int32_t
163  return (u32_timeNs);
164 }
165 
166 /** Computes delta ticks between two Timer register captures
167  * Assumes long time interval and thus has a parameter for tracking timer overflows
168  * \param u16_start start tick
169  * \param u16_end end tick
170  * \param u16_tmrPR Timer period register
171  * \param u16_oflows number of timer overflows
172  * \return delta ticks
173  */
174 uint32_t computeDeltaTicksLong(uint16_t u16_start, uint16_t u16_end, uint16_t u16_tmrPR, uint16_t u16_oflows) {
175  uint32_t u32_deltaTicks;
176  if (u16_oflows == 0) u32_deltaTicks = u16_end - u16_start;
177  else {
178  //compute ticks from start to timer overflow
179  u32_deltaTicks = (u16_tmrPR + 1) - u16_start;
180  //add ticks due to overflows = (overflows -1) * ticks_per_overflow
181  u32_deltaTicks += ((((uint32_t) u16_oflows)- 1) * (((uint32_t)u16_tmrPR) + 1)) ;
182  //now add in the delta due to the last capture
183  u32_deltaTicks += u16_end;
184  }
185  return (u32_deltaTicks);
186 }
187 
188 /** Computes delta ticks between two Timer register captures
189  * Assumes the delta time does not exceeds the timer period
190  * \param u16_start start tick
191  * \param u16_end end tick
192  * \param u16_tmrPR Timer period register
193  * \return delta ticks
194  */
195 uint16_t computeDeltaTicks(uint16_t u16_start, uint16_t u16_end, uint16_t u16_tmrPR) {
196  uint16_t u16_deltaTicks;
197  if (u16_end >= u16_start) u16_deltaTicks = u16_end - u16_start;
198  else {
199  //compute ticks from start to timer overflow
200  u16_deltaTicks = (u16_tmrPR + 1) - u16_start;
201  //now add in the delta from overflow to u16_end
202  u16_deltaTicks += u16_end;
203  }
204  return (u16_deltaTicks);
205 }