Skip to content

Commit

Permalink
Jira-528. Make CurieTimerOne library to be compatible with the TimerO…
Browse files Browse the repository at this point in the history
…ne library originated from Paul. Created methods that have the same name and functionalities as in the TimerOne library.
  • Loading branch information
SidLeung authored and calvinatintel committed Mar 17, 2016
1 parent 98ee736 commit 38a508e
Show file tree
Hide file tree
Showing 4 changed files with 168 additions and 52 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#include <CurieTimerOne.h>

const int blinkPin = 13;

void setup(void)
{
CurieTimerOne.initialize(50000);
Serial.begin(9600);
}

void loop(void)
{
unsigned int range;

Serial.println("PWM blink: low -> high duty cycle");

for (float dutyCycle = 5.0; dutyCycle <= 100.0; dutyCycle++) {
range = (dutyCycle / 100) * 1023;
CurieTimerOne.pwm(blinkPin, range);
delay(50);
}

Serial.println("PWM blink: high -> low duty cycle");

for (float dutyCycle = 100.0; dutyCycle > 5.0; dutyCycle--) {
range = (dutyCycle / 100) * 1023;
CurieTimerOne.setPwmDuty(blinkPin, range);
delay(50);
}
}
30 changes: 18 additions & 12 deletions libraries/CurieTimerOne/keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,24 @@ CurieTimer KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
start KEYWORD2
restart KEYWORD2
kill KEYWORD2
attachInterrupt KEYWORD2
detachInterrupt KEYWORD2
readTickCount KEYWORD2
rdRstTickCount KEYWORD2
pause KEYWORD2
resume KEYWORD2
pwmStart KEYWORD2
pwmStop KEYWORD2
initialize KEYWORD2
setPeriod KEYWORD2
start KEYWORD2
stop KEYWORD2
restart KEYWORD2
resume KEYWORD2
setPwmDuty KEYWORD2
pwm KEYWORD2
disablePwm KEYWORD2
attachInterrupt KEYWORD2
detachInterrupt KEYWORD2
kill KEYWORD2
readTickCount KEYWORD2
rdRstTickCount KEYWORD2
pause KEYWORD2
pwmStart KEYWORD2
pwmStop KEYWORD2
#######################################
# Instances (KEYWORD2)
#######################################
CurieTimerOne KEYWORD2
CurieTimerOne KEYWORD2
65 changes: 41 additions & 24 deletions libraries/CurieTimerOne/src/CurieTimerOne.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,25 +50,15 @@ static void timerOnePwmCbWrapper(void)
}


CurieTimer::CurieTimer(const unsigned int timerNum) :
CurieTimer::CurieTimer() :
tickCnt(0), currState(IDLE), userCB(NULL)
{
if(timerNum == 0) {
timerCountAddr = ARC_V2_TMR0_COUNT;
timerControlAddr = ARC_V2_TMR0_CONTROL;
timerLimitAddr = ARC_V2_TMR0_LIMIT;
timerIrqNum = ARCV2_IRQ_TIMER0;
isrFuncPtr = NULL;
pwmCB = NULL;
}
else {
timerCountAddr = ARC_V2_TMR1_COUNT;
timerControlAddr = ARC_V2_TMR1_CONTROL;
timerLimitAddr = ARC_V2_TMR1_LIMIT;
timerIrqNum = ARCV2_IRQ_TIMER1;
isrFuncPtr = &timerOneIsrWrapper;
pwmCB = &timerOnePwmCbWrapper;
}
timerCountAddr = ARC_V2_TMR1_COUNT;
timerControlAddr = ARC_V2_TMR1_CONTROL;
timerLimitAddr = ARC_V2_TMR1_LIMIT;
timerIrqNum = ARCV2_IRQ_TIMER1;
isrFuncPtr = &timerOneIsrWrapper;
pwmCB = &timerOnePwmCbWrapper;
}


Expand All @@ -86,6 +76,7 @@ void CurieTimer::kill()
tickCnt = 0;
userCB = NULL;
currState = IDLE;
pauseCntrl = pauseCount = pwmPin = dutyCycle = nonDutyCycle = periodInUsec = 0;
}


Expand Down Expand Up @@ -154,25 +145,26 @@ int CurieTimer::pwmStart(unsigned int outputPin, double dutyPercentage, unsigned
unsigned int pwmPeriod;

// Safe guard against periodUsec overflow when convert to hz.
if((periodUsec == 0) || (periodUsec >= MAX_PERIOD))
if((periodUsec == 0) || (periodUsec >= MAX_PERIOD_USEC))
return -(INVALID_PERIOD);

if((dutyPercentage < 0.0) || (dutyPercentage > 100.0))
return -(INVALID_DUTY_CYCLE);

periodInUsec = periodUsec;
pwmPin = outputPin;
pinMode(pwmPin, OUTPUT);

if(dutyPercentage == 0.0) {
// If PWM is already running, reset the timer and set pin to LOW
kill();
// If PWM is already running, pause to stop it from interfering, and set pin to LOW
pause();
digitalWrite(pwmPin, LOW);
return SUCCESS;
}

if(dutyPercentage == 100.0) {
// If PWM is already running, reset the timer and set pin to HIGH
kill();
// If PWM is already running, pause to stop it from interfering, and set pin to HIGH
pause();
digitalWrite(pwmPin, HIGH);
return SUCCESS;
}
Expand Down Expand Up @@ -204,7 +196,7 @@ int CurieTimer::pwmStart(unsigned int outputPin, int dutyRange, unsigned int per
if((dutyRange < 0) || (dutyRange > MAX_DUTY_RANGE))
return -(INVALID_DUTY_CYCLE);

return pwmStart(outputPin, ((double)dutyRange * 100.0)/(double)MAX_DUTY_RANGE, periodUsec);
return pwmStart(outputPin, ((double)dutyRange/(double)MAX_DUTY_RANGE) * 100.0, periodUsec);
}


Expand All @@ -224,6 +216,31 @@ inline void CurieTimer::pwmCallBack(void)
}


// Method: setPeriod
// This method is for making this library backward compatible to the AVR
// TimerOne library. The routine changs the time period by pausing the timer
// and resume it with the new period. This is not timer re-initialization.

void CurieTimer::setPeriod(unsigned long microseconds)
{
unsigned int periodHz;

if((microseconds == 0) || (microseconds > MAX_PERIOD_USEC))
microseconds = 1000000;

periodInUsec = microseconds;
periodHz = microseconds * HZ_USEC;
pause();

aux_reg_write(timerLimitAddr, periodHz); // Load Timer period

if(pauseCount >= periodHz)
pauseCount = 0;

resume();
}


// Method: init
// Kick off the timer with a period, in Hz, provided. Initialize
// timer to run in non-halt mode, enable timer interrupt. Always install
Expand All @@ -232,7 +249,7 @@ inline void CurieTimer::pwmCallBack(void)
int CurieTimer::init(const unsigned int periodHz,
void (*userCallBack)())
{
if((periodHz == 0) || (periodHz > MAX_PERIOD))
if((periodHz == 0) || (periodHz > MAX_PERIOD_HZ))
return -(INVALID_PERIOD);

interrupt_disable(timerIrqNum); // Disable Timer at controller
Expand Down
95 changes: 79 additions & 16 deletions libraries/CurieTimerOne/src/CurieTimerOne.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,8 @@

// Timer-1 is clocked at ARCV2_TIMER1_CLOCK_FREQ defined in conf.h
const unsigned int HZ_USEC = (ARCV2_TIMER1_CLOCK_FREQ / 1000000); // Hz per micro second.
const unsigned int MAX_PERIOD = (0x0FFFFFFFF / HZ_USEC);

// The two ARC timers.
const unsigned int ARC_TIMER_0 = 0;
const unsigned int ARC_TIMER_1 = 1;
const unsigned int MAX_PERIOD_HZ = 0x0FFFFFFFF;
const unsigned int MAX_PERIOD_USEC = (MAX_PERIOD_HZ / HZ_USEC);

// Duty cycle range.
const int MAX_DUTY_RANGE = 1023;
Expand Down Expand Up @@ -80,21 +77,91 @@ typedef enum {
// Class: CurieTimer
//
// Description:
// This class describes the functionalities of a Arc Timer. It has the knowledge
// of only 2 timers available in the h/w - a limitation. The timers are sourced by
// a 32 HHz clock, a constant, used in this class, defined in the conf.h file.
// This class describes the functionalities of a Arc Timer, in particular, timer-1.
// Timer-0 is not available for this module to utilize. The timers are clocked by
// a 32 HHz source and have 32-bit counters.
//

class CurieTimer
{
public:
// Constructor. Default is timer-1.
CurieTimer(const unsigned int timerNum = ARC_TIMER_1);
// Constructor.
CurieTimer();

// The following methods are similar to the ones found in the AVR TimerOne library.

//****************************
// Configuration
//****************************

inline void initialize(unsigned long microseconds = 1000000) {
if((microseconds == 0) || (microseconds > MAX_PERIOD_USEC))
microseconds = 1000000;
periodInUsec = microseconds;
init( (microseconds * HZ_USEC), NULL );
}

void setPeriod(unsigned long microseconds);

//****************************
// Run Control
//****************************

inline void start(void) {
pause();
pauseCount = 0;
resume();
}

inline void stop(void) { return pause(); }

inline void restart(void) { start(); }

// Resume the timer from where it was paused.
void resume(void);

//****************************
// PWM outputs
//****************************

inline void setPwmDuty(char pin, unsigned int duty) {
pwmStart( pin, (int) duty, periodInUsec );
}

inline void pwm(char pin, unsigned int duty) {
pwmStart( pin, (int) duty, periodInUsec );
}

inline void pwm(char pin, unsigned int duty, unsigned long microseconds) {
pwmStart( pin, (int) duty, microseconds );
}

inline void disablePwm(char pin) {
pwmStop();
}

//****************************
// Interrupt Function
//****************************

void attachInterrupt(void (*isr)());

inline void attachInterrupt(void (*isr)(), unsigned long microseconds) {
attachInterrupt( isr );
setPeriod( microseconds );
}

inline void detachInterrupt(void) { attachInterrupt(NULL); };

/////////
// The following are additional methods provided by Intel for the Curie platform.
////////

// Set up the timer with the input period, in usec, and the call back routine.
// Period stays with the timer until it is killed or re/start another round.
inline int start(const unsigned int timerPeriodUsec = 0,
inline int start(const unsigned int timerPeriodUsec,
void (*userCallBack)() = NULL) {
periodInUsec = timerPeriodUsec;
return( init((timerPeriodUsec * HZ_USEC), userCallBack) ); }

// Restarting the timer, start counter from 0.
Expand All @@ -104,8 +171,6 @@ class CurieTimer
void kill(void);

// Attach or detach the user call back routine.
void attachInterrupt(void (*userCallBack)());
void detachInterrupt(void) { return attachInterrupt(NULL); };

// Timer interrupt count.
inline unsigned int readTickCount(void) { return tickCnt; }
Expand All @@ -114,9 +179,6 @@ class CurieTimer

// Pausing the timer = no count up, no interrupt.
void pause(void);
inline void stop(void) { return pause(); }
// Resume the timer from where it was paused.
void resume(void);

// Start software PWM. Note that the timer is consumed once PWM is set.
int pwmStart(unsigned int outputPin, double dutyPercentage, unsigned int periodUsec);
Expand Down Expand Up @@ -148,6 +210,7 @@ class CurieTimer
unsigned int pwmPin;
unsigned int dutyCycle;
unsigned int nonDutyCycle;
unsigned int periodInUsec;

void (*isrFuncPtr)();
void (*userCB)();
Expand Down

0 comments on commit 38a508e

Please sign in to comment.