Skip to content

Commit 162e0cf

Browse files
SidLeungcalvinatintel
authored andcommitted
Jira-32 and Jira-386. CurieTimerOne lib
1 parent b5c27ae commit 162e0cf

File tree

6 files changed

+544
-0
lines changed

6 files changed

+544
-0
lines changed
+263
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,263 @@
1+
//***************************************************************
2+
//
3+
// Copyright (c) 2015 Intel Corporation. All rights reserved.
4+
//
5+
// This library is free software; you can redistribute it and/or
6+
// modify it under the terms of the GNU Lesser General Public
7+
// License as published by the Free Software Foundation; either
8+
// version 2.1 of the License, or (at your option) any later version.
9+
10+
// This library is distributed in the hope that it will be useful,
11+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
// Lesser General Public License for more details.
14+
15+
// You should have received a copy of the GNU Lesser General Public
16+
// License along with this library; if not, write to the Free Software
17+
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18+
//
19+
//***************************************************************
20+
21+
//***************************************************************
22+
//
23+
// Module: CurieTimer
24+
//
25+
//
26+
// Notes:
27+
//
28+
// - Arc has two timers, Timer-0 is used. Please check the file
29+
// arcv2_timer0.cpp.
30+
//
31+
// Cautions:
32+
// - The module, Tone.cpp, also makes use of Arc Timer-1 which
33+
// is used here.
34+
//
35+
//***************************************************************
36+
37+
38+
#include "CurieTimer.h"
39+
#include <conf.h>
40+
41+
CurieTimer CurieTimerOne;
42+
43+
static void timerOneIsrWrapper(void)
44+
{
45+
CurieTimerOne.timerIsr();
46+
}
47+
static void timerOnePwmCbWrapper(void)
48+
{
49+
CurieTimerOne.pwmCallBack();
50+
}
51+
52+
53+
CurieTimer::CurieTimer(const unsigned int timerNum) :
54+
tickCnt(0), currState(IDLE), userCB(NULL)
55+
{
56+
if(timerNum == 0) {
57+
timerCountAddr = ARC_V2_TMR0_COUNT;
58+
timerControlAddr = ARC_V2_TMR0_CONTROL;
59+
timerLimitAddr = ARC_V2_TMR0_LIMIT;
60+
timerIrqNum = ARCV2_IRQ_TIMER0;
61+
isrFuncPtr = NULL;
62+
pwmCB = NULL;
63+
}
64+
else {
65+
timerCountAddr = ARC_V2_TMR1_COUNT;
66+
timerControlAddr = ARC_V2_TMR1_CONTROL;
67+
timerLimitAddr = ARC_V2_TMR1_LIMIT;
68+
timerIrqNum = ARCV2_IRQ_TIMER1;
69+
isrFuncPtr = &timerOneIsrWrapper;
70+
pwmCB = &timerOnePwmCbWrapper;
71+
}
72+
}
73+
74+
75+
// Method: kill
76+
// Description:
77+
// Set the timer back to power up default condition.
78+
79+
void CurieTimer::kill()
80+
{
81+
interrupt_disable(timerIrqNum); // Disable Timer at controller
82+
aux_reg_write(timerControlAddr, 0); // Disable Timer itself
83+
aux_reg_write(timerLimitAddr, 0);
84+
aux_reg_write(timerCountAddr, 0);
85+
86+
tickCnt = 0;
87+
userCB = NULL;
88+
currState = IDLE;
89+
}
90+
91+
92+
void CurieTimer::attachInterrupt(void (*userCallBack)())
93+
{
94+
unsigned int reg;
95+
96+
// Disable timer interrupt first.
97+
reg = aux_reg_read(timerControlAddr) & ~ARC_TIMER_EN_INTR_BIT_FLAG;
98+
aux_reg_write(timerControlAddr, reg);
99+
100+
// Record the user call back routine.
101+
userCB = userCallBack;
102+
103+
// Let timer interrupt go again.
104+
reg |= ARC_TIMER_EN_INTR_BIT_FLAG;
105+
aux_reg_write(timerControlAddr, reg);
106+
}
107+
108+
109+
unsigned int CurieTimer::rdRstTickCount(void)
110+
{
111+
unsigned int tmp;
112+
113+
tmp = tickCnt;
114+
tickCnt = 0;
115+
return tmp;
116+
}
117+
118+
119+
void CurieTimer::pause(void)
120+
{
121+
if(currState != RUNNING)
122+
return;
123+
124+
pauseCntrl = aux_reg_read(timerControlAddr);
125+
pauseCount = aux_reg_read(timerCountAddr);
126+
127+
interrupt_disable(timerIrqNum); // Disable Timer at controller
128+
aux_reg_write(timerControlAddr, 0); // Disable Timer itself
129+
130+
currState = PAUSED;
131+
}
132+
133+
134+
void CurieTimer::resume(void)
135+
{
136+
if(currState != PAUSED)
137+
return;
138+
139+
aux_reg_write(timerCountAddr, pauseCount);
140+
aux_reg_write(timerControlAddr, pauseCntrl);
141+
currState = RUNNING;
142+
}
143+
144+
145+
// Method: pwmStart
146+
// Kick off a timer as the mean to time a pwm. Calculate the durations of the duty cycle
147+
// and they are loaded into the timer in the pwm call back.
148+
149+
int CurieTimer::pwmStart(unsigned int outputPin, double dutyPercentage, unsigned int periodUsec)
150+
{
151+
unsigned int pwmPeriod;
152+
153+
if(periodUsec == 0)
154+
return -(INVALID_PERIOD);
155+
156+
if((dutyPercentage < 0.0) || (dutyPercentage > 100.0))
157+
return -(INVALID_DUTY_CYCLE);
158+
159+
pwmPin = outputPin;
160+
pinMode(pwmPin, OUTPUT);
161+
162+
if(dutyPercentage == 0.0) {
163+
digitalWrite(pwmPin, LOW);
164+
return SUCCESS;
165+
}
166+
167+
if(dutyPercentage == 100.0) {
168+
digitalWrite(pwmPin, HIGH);
169+
return SUCCESS;
170+
}
171+
172+
pwmPeriod = periodUsec * HZ_USEC;
173+
174+
dutyCycle = (unsigned int)(((double)pwmPeriod / 100.0) * dutyPercentage);
175+
nonDutyCycle = pwmPeriod - dutyCycle;
176+
177+
dutyToggle = true;
178+
digitalWrite(pwmPin, HIGH);
179+
init(dutyCycle, pwmCB);
180+
181+
return SUCCESS;
182+
}
183+
184+
185+
int CurieTimer::pwmStart(unsigned int outputPin, int dutyRange, unsigned int periodUsec)
186+
{
187+
if((dutyRange < 0) || (dutyRange > MAX_DUTY_RANGE))
188+
return -(INVALID_DUTY_CYCLE);
189+
190+
return pwmStart(outputPin, ((double)dutyRange * 100.0)/(double)MAX_DUTY_RANGE, periodUsec);
191+
}
192+
193+
194+
// Method: pwmCallBack
195+
// Software PWM ISR. Timer generates interrupt and calls this method in
196+
// its ISR. This routine is responsible to toggle the PWM signal according
197+
// to duty cycle duration.
198+
199+
inline void CurieTimer::pwmCallBack(void)
200+
{
201+
dutyToggle = !dutyToggle;
202+
203+
digitalWrite(pwmPin, dutyToggle ? HIGH : LOW);
204+
205+
aux_reg_write(timerLimitAddr, dutyToggle ? dutyCycle : nonDutyCycle);
206+
aux_reg_write(timerCountAddr, 0);
207+
}
208+
209+
210+
// Method: init
211+
// Kick off the timer with a period, in Hz, provided. Initialize
212+
// timer to run in non-halt mode, enable timer interrupt. Always install
213+
// the generic ISR and initialize the user call back if provided.
214+
215+
int CurieTimer::init(const unsigned int periodHz,
216+
void (*userCallBack)())
217+
{
218+
if((periodHz == 0) || (periodHz > MAX_PERIOD))
219+
return -(INVALID_PERIOD);
220+
221+
interrupt_disable(timerIrqNum); // Disable Timer at controller
222+
aux_reg_write(timerControlAddr, 0); // Disable Timer itself
223+
224+
if(userCallBack != NULL)
225+
userCB = userCallBack;
226+
aux_reg_write(timerLimitAddr, periodHz); // Load Timer period
227+
228+
aux_reg_write(timerCountAddr, 0); // Reset variables
229+
tickCnt = 0;
230+
231+
if(isrFuncPtr != NULL) { // Enable timer running with interrupt
232+
interrupt_connect(timerIrqNum, isrFuncPtr);
233+
aux_reg_write(timerControlAddr, ARC_TIMER_EN_INTR_BIT_FLAG |
234+
ARC_TIMER_NON_HALT_ONLY_BIT_FLAG);
235+
interrupt_enable(timerIrqNum);
236+
}
237+
else { // Timer runs without interrupt
238+
aux_reg_write(timerControlAddr, ARC_TIMER_NON_HALT_ONLY_BIT_FLAG);
239+
}
240+
241+
currState = RUNNING;
242+
return SUCCESS;
243+
}
244+
245+
246+
// Method: timerIsr
247+
// It's the generic timer ISR. Will call user call back here.
248+
249+
inline void CurieTimer::timerIsr(void)
250+
{
251+
unsigned int reg;
252+
253+
// Clear the interrupt pending bit.
254+
reg = aux_reg_read(timerControlAddr) & ~ARC_TIMER_INTR_PENDING_BIT_FLAG;
255+
aux_reg_write(timerControlAddr, reg);
256+
257+
tickCnt++; // Account for the interrupt
258+
259+
if(userCB != NULL) // Call user ISR if available
260+
userCB();
261+
}
262+
263+

0 commit comments

Comments
 (0)