Koduino
timer.h
1 
19 #ifndef _timer_h_
20 #define _timer_h_
21 
22 #include "chip.h"
23 #include "types.h"
24 #include "exti.h"
25 #include "gpio.h"
26 
27 #ifdef __cplusplus
28 extern "C"{
29 #endif // __cplusplus
30 
31 extern uint8_t TIMER_IC_PRIORITY;
32 
33 // FUTURE IDEAS?
34 //
35 // pinModeTimer should take another argument: ENCODER_AB, PWM_IN or PWM_OUT
36 // if pwmIn is called and it is in output mode it should be re-inited TIM_ICInit etc. <- function timerInitPulseInPin
37 // if analogWrite is called and it is in input mode it should be re-inited TIM_OC1Init etc. <- timerInitPWMPin
38 
39 
50 void analogWriteResolution(uint8_t nbits);
51 
66 void analogWriteFrequency(uint8_t pin, int freqHz);
67 
77 void analogWriteFloat(uint8_t pin, float duty);
78 
86 void analogWrite(uint8_t pin, uint32_t duty);
87 
106 float pwmIn(uint8_t pin);
107 
108 // To try and reduce position reading bugs, fix pwmIn period
109 // 36000 -> 1ms (1KHz PWM)
110 // Set = 0 to autodetect period
111 // extern int PWM_IN_FIXED_PERIOD;
116 void pwmInExpectedPeriod(int expectedUs);
117 
118 // Helper functions
119 void pwmInRaw(uint8_t name, int *period, int *pulseWidth);
120 
121  // end of addtogroup
123 
124 void timerInit(uint8_t timer, int freqHz);
125 
126 void pinTimerInit(uint8_t pin);
127 
128 // Timer init with period: mostly a helper function
129 void timerInitHelper(uint8_t timer, uint16_t prescaler, uint32_t period);
130 
131 
132 
133 // Helper for each channel
134 static inline void timerCCxISR(TIM_TypeDef *TIMx, TimerChannelData *C, int current, uint32_t currRollover) __attribute__((always_inline, unused));
135 static inline void timerCCxISR(TIM_TypeDef *TIMx, TimerChannelData *C, int current, uint32_t currRollover) {
136  // Is this a pwmIn pin?
137  if (C->bPwmIn == 1) {
138  // Keep track of how many times timer rolled over since last time
139  int newRollovers = currRollover - C->lastRollover;
140  int delta = current + TIMx->ARR * newRollovers - C->risingEdge;
141 
142  if (digitalRead(C->pin)) {
143  // This was a rising edge
144  if (delta > PWM_IN_MAXPERIOD)
145  C->period = delta - TIMx->ARR;
146  else if (delta < PWM_IN_MINPERIOD)
147  C->period = delta + TIMx->ARR;
148  else
149  C->period = delta;
150 
151  C->risingEdge = current;
152  C->lastRollover = currRollover;
153  } else {
154  // This was a falling edge
155  C->pulseWidth = delta;
156 
157  // HACK: sometimes it is greater than the period
158  if (C->pulseWidth > C->period)
159  C->pulseWidth -= C->period;
160  if (C->pulseWidth < 0)
161  C->pulseWidth += C->period;
162  }
163  }
164 }
165 
166 // Main GP timer ISR
167 #if defined(KODUINO_ISRS_INLINE)
168 static inline void timerISR(uint8_t timer) __attribute__((always_inline, unused));
169 #else
170 static inline void timerISR(uint8_t timer);
171 #endif
172 static inline void timerISR(uint8_t timer) {
173  TIM_TypeDef *TIMx = TIMER_MAP[timer].TIMx;
174  TimerInfo *cfg = &TIMER_MAP[timer];
175 
176  // Update for rollover
177  if (TIM_GetITStatus(TIMx, TIM_IT_Update) != RESET) {
178  TIM_ClearITPendingBit(TIMx, TIM_IT_Update);
179  cfg->numRollovers++;
180  }
181 
182  // CCx for pwmIn
183  if (TIM_GetITStatus(TIMx, TIM_IT_CC1) != RESET) {
184  TIM_ClearITPendingBit(TIMx, TIM_IT_CC1);
185  timerCCxISR(TIMx, &cfg->channelData[0], TIM_GetCapture1(TIMx), cfg->numRollovers);
186  }
187  if (TIM_GetITStatus(TIMx, TIM_IT_CC2) != RESET) {
188  TIM_ClearITPendingBit(TIMx, TIM_IT_CC2);
189  timerCCxISR(TIMx, &cfg->channelData[1], TIM_GetCapture2(TIMx), cfg->numRollovers);
190  }
191  if (TIM_GetITStatus(TIMx, TIM_IT_CC3) != RESET) {
192  TIM_ClearITPendingBit(TIMx, TIM_IT_CC3);
193  timerCCxISR(TIMx, &cfg->channelData[2], TIM_GetCapture3(TIMx), cfg->numRollovers);
194  }
195  if (TIM_GetITStatus(TIMx, TIM_IT_CC4) != RESET) {
196  TIM_ClearITPendingBit(TIMx, TIM_IT_CC4);
197  timerCCxISR(TIMx, &cfg->channelData[3], TIM_GetCapture4(TIMx), cfg->numRollovers);
198  }
199 }
200 
201 
202 // Special timer features
203 void complementaryPWM(uint8_t timer, int freqHz, uint16_t deadtime);
204 
205 
206 #ifdef __cplusplus
207 } // extern "C"
208 #endif // __cplusplus
209 
210 #endif
211 
float pwmIn(uint8_t pin)
Read a PWM signal (non-blocking)
Definition: timer.c:129
Definition: types.h:108
static uint8_t digitalRead(uint8_t pin) __attribute__((always_inline
Read a digital pin.
Definition: gpio.h:57
void analogWriteFloat(uint8_t pin, float duty)
Change the PWM duty cycle on a pin.
Definition: timer.c:106
void analogWriteResolution(uint8_t nbits)
Set the resolution for the analogWrite() function.
Definition: timer.c:69
void analogWrite(uint8_t pin, uint32_t duty)
Change the PWM duty cycle on a pin.
Definition: timer.c:125
void pwmInExpectedPeriod(int expectedUs)
Set the expected period for PWM_IN or PWM_IN_EXTI.
Definition: timer.c:40
void analogWriteFrequency(uint8_t pin, int freqHz)
Assign a PWM frequency to the specified pin (default = 1000 Hz)
Definition: timer.c:65