Skip to content

Commit 5a54c91

Browse files
committed
Timer: improve timers
1 parent 2931c37 commit 5a54c91

File tree

2 files changed

+243
-63
lines changed

2 files changed

+243
-63
lines changed

hardware/zpuino/zpu20/cores/zpuino/Timer.cpp

+152-52
Original file line numberDiff line numberDiff line change
@@ -2,55 +2,155 @@
22
#include <register.h>
33
#include <zpuino.h>
44

5-
void TimerClass::begin()
6-
{
7-
TMR1CTL = BIT(TCTLENA)|BIT(TCTLCCM)|BIT(TCTLDIR);
8-
}
9-
/*
10-
void TimerClass::setPWMFrequency(long int hz)
11-
{
12-
const int dividers[8] = {
13-
1,2,4,8,16,64,256,1024
14-
};
15-
16-
int i;
17-
18-
for (i=0;i<8;i++) {
19-
long count = CLK_FREQ/dividers[i];
20-
count /= hz;
21-
if (count<65535) {
22-
TMR1CNT=0;
23-
TMR1CMP=count;
24-
TMR1OCR=count>>1;
25-
TMR1CTL &= ~(BIT(TCTLCP0)|BIT(TCTLCP1)|BIT(TCTLCP2));
26-
TMR1CTL |= (i<<TCTLCP0);
27-
return;
28-
}
29-
}
30-
}
31-
*/
32-
33-
void TimerClass::setPWMDuty(uint8_t val)
34-
{
35-
long cmp = count;
36-
cmp *= val;
37-
cmp >>= 8;
38-
// TMR1OCR=cmp;
39-
}
40-
41-
void TimerClass::setPWMFrequency(long int hz)
42-
{
43-
count = (CLK_FREQ / hz) -1 ;
44-
TMR1CNT=0;
45-
TMR1CMP=count;
46-
// TMR1OCR=count>>1;
47-
TMR1CTL &= ~(BIT(TCTLCP0)|BIT(TCTLCP1)|BIT(TCTLCP2));
48-
//TMR1CTL |= (i<<TCTLCP0);
49-
}
50-
51-
void TimerClass::setPWMOutputPin(int pin)
52-
{
53-
pinMode(pin,OUTPUT);
54-
pinModePPS(pin,HIGH);
55-
outputPinForFunction( pin, IOPIN_TIMER1_OC);
56-
}
5+
#define VENDOR_ZPUINO 0x08
6+
#define PRODUCT_ZPUINO_TIMERS 0x13
7+
8+
namespace ZPUino {
9+
10+
Timers_class::Timers_class(): m_pwmTimerPtr(0), m_intrTimerPtr(0)
11+
{
12+
}
13+
14+
void Timers_class::begin()
15+
{
16+
if (deviceBegin(VENDOR_ZPUINO, PRODUCT_ZPUINO_TIMERS)==0) {
17+
m_timer0.begin( getBaseRegister(), getSlot() );
18+
m_timer1.begin( getBaseRegister() + 64, getSlot()+1);
19+
}
20+
}
21+
22+
int TimerInstance_class::setPeriodMilliseconds(unsigned ms) {
23+
unsigned maxvalue = (1<<getSize())-1;
24+
unsigned cmp=0;
25+
26+
if (hasPrescaler()) {
27+
int i;
28+
for (i=0;i<8;i++) {
29+
unsigned long count = CLK_FREQ/timerPrescalerDividers[i]; /* This is one second */
30+
cmp = count / ms;
31+
if (cmp<maxvalue)
32+
break;
33+
}
34+
} else {
35+
unsigned long count = CLK_FREQ; /* This is one second */
36+
cmp = count/ms;
37+
if (cmp>maxvalue)
38+
cmp=0;
39+
}
40+
if (cmp==0)
41+
return -1;
42+
43+
/* Apply */
44+
setComparator(cmp);
45+
setCounter(0);
46+
return 0;
47+
}
48+
49+
50+
51+
52+
/*
53+
void TimerClass::setPWMFrequency(long int hz)
54+
{
55+
const int dividers[8] = {
56+
1,2,4,8,16,64,256,1024
57+
};
58+
59+
int i;
60+
61+
for (i=0;i<8;i++) {
62+
long count = CLK_FREQ/dividers[i];
63+
count /= hz;
64+
if (count<65535) {
65+
TMR1CNT=0;
66+
TMR1CMP=count;
67+
TMR1OCR=count>>1;
68+
TMR1CTL &= ~(BIT(TCTLCP0)|BIT(TCTLCP1)|BIT(TCTLCP2));
69+
TMR1CTL |= (i<<TCTLCP0);
70+
return;
71+
}
72+
}
73+
}
74+
*/
75+
#if 0
76+
void TimerClass::setPWMDuty(uint8_t val)
77+
{
78+
long cmp = count;
79+
cmp *= val;
80+
cmp >>= 8;
81+
// TMR1OCR=cmp;
82+
}
83+
84+
void TimerClass::setPWMFrequency(long int hz)
85+
{
86+
count = (CLK_FREQ / hz) -1 ;
87+
TMR1CNT=0;
88+
TMR1CMP=count;
89+
// TMR1OCR=count>>1;
90+
TMR1CTL &= ~(BIT(TCTLCP0)|BIT(TCTLCP1)|BIT(TCTLCP2));
91+
//TMR1CTL |= (i<<TCTLCP0);
92+
}
93+
94+
void TimerClass::setPWMOutputPin(int pin)
95+
{
96+
pinMode(pin,OUTPUT);
97+
pinModePPS(pin,HIGH);
98+
outputPinForFunction( pin, IOPIN_TIMER1_OC);
99+
}
100+
#endif
101+
102+
int Timers_class::singleShot( int msec, void (*function)(void*), void *arg )
103+
{
104+
/* get a free timer */
105+
TimerInstance_class *tmr = getFreeTimer();
106+
107+
if (0==tmr)
108+
return -1;
109+
110+
m_intrTimerPtr = tmr;
111+
112+
return attachInterrupt(tmr->getInterruptLine(), &timerInterruptHandlerSS, (void*)this);
113+
}
114+
115+
int Timers_class::singleShot( int msec, void (*function)(void))
116+
{
117+
return singleShot(msec, (void(*)(void*))function, 0);
118+
}
119+
120+
int Timers_class::periodic( int msec, bool (*function)(void*), void *arg )
121+
{
122+
TimerInstance_class *tmr = getFreeTimer();
123+
124+
if (0==tmr)
125+
return -1;
126+
127+
m_intrTimerPtr = tmr;
128+
129+
return attachInterrupt(tmr->getInterruptLine(), &timerInterruptHandler, (void*)this);
130+
}
131+
132+
int Timers_class::periodic( int msec, bool (*function)(void) )
133+
{
134+
return periodic(msec, (bool(*)(void*))function, 0);
135+
}
136+
137+
void Timers_class::timerInterruptHandler(void *arg)
138+
{
139+
Timers_class *hclass = static_cast<Timers_class*>(arg);
140+
if (!hclass->handleInterrupt()) {
141+
hclass->m_intrTimerPtr->stop();
142+
detachInterrupt(hclass->m_intrTimerPtr->getInterruptLine());
143+
hclass->m_intrTimerPtr=0;
144+
}
145+
}
146+
147+
void Timers_class::timerInterruptHandlerSS(void *arg)
148+
{
149+
Timers_class *hclass = static_cast<Timers_class*>(arg);
150+
hclass->handleInterrupt();
151+
hclass->m_intrTimerPtr->stop();
152+
detachInterrupt(hclass->m_intrTimerPtr->getInterruptLine());
153+
hclass->m_intrTimerPtr=0;
154+
}
155+
156+
};

hardware/zpuino/zpu20/cores/zpuino/Timer.h

+91-11
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,98 @@
22
#define __TIMER_H__
33

44
#include <zpuino-types.h>
5+
#include <register.h>
6+
#include <BaseDevice.h>
57

6-
7-
class TimerClass
8+
namespace ZPUino
89
{
9-
public:
10-
void begin();
11-
void setPWMFrequency(long int hz);
12-
void setPWMOutputPin(int);
13-
void setPWMDuty(uint8_t val);
14-
15-
protected:
16-
long count;
17-
};
10+
const int timerPrescalerDividers[8] = {
11+
1,2,4,8,16,64,256,1024
12+
};
13+
14+
class TimerInstance_class: public REGAccess
15+
{
16+
public:
17+
void begin(register_t base, int intline) {
18+
REGAccess::begin(base);
19+
m_intline=intline;
20+
/* Set up sane defaults */
21+
setUpDirection(true);
22+
setClearOnCompare(true);
23+
}
24+
int getInterruptLine() const {
25+
return m_intline;
26+
}
27+
bool hasPrescaler() {
28+
return REG(128) & (1<<10);
29+
}
30+
bool hasTSC() {
31+
return REG(128) & (1<<8);
32+
}
33+
bool hasBuffers() {
34+
return REG(128) & (1<<9);
35+
}
36+
int getNumberOfComparators() {
37+
return (REG(128)>>16) & 0xff;
38+
}
39+
int getSize() {
40+
return REG(128) & 0xff;
41+
}
42+
void setCounter(unsigned value) {
43+
REG(ROFF_TMR0CNT)=value;
44+
}
45+
void setComparator(unsigned value) {
46+
REG(ROFF_TMR0CMP)=value;
47+
}
48+
void setUpDirection(bool value) {
49+
REG(ROFF_TMR0CTL).bit(TCTLDIR) = value;
50+
}
51+
void setClearOnCompare(bool value) {
52+
REG(ROFF_TMR0CTL).bit(TCTLCCM) = value;
53+
}
54+
int setPeriodMilliseconds(unsigned ms);
55+
56+
void start() {
57+
REG(ROFF_TMR0CTL).setBit(TCTLENA);
58+
}
59+
void stop() {
60+
REG(ROFF_TMR0CTL).clearBit(TCTLENA);
61+
}
1862

63+
private:
64+
//bool m_interruptAttached;
65+
int m_intline;
66+
};
67+
68+
class Timers_class: public BaseDevice
69+
{
70+
public:
71+
Timers_class();
72+
void begin();
73+
void setPWMFrequency(long int hz);
74+
void setPWMOutputPin(int);
75+
void setPWMDuty(uint8_t val);
76+
77+
int singleShot( int msec, void (*function)(void*), void *arg );
78+
int singleShot( int msec, void (*function)(void));
79+
int periodic( int msec, bool (*function)(void*), void *arg );
80+
int periodic( int msec, bool (*function)(void) );
81+
82+
void cancel();
83+
private:
84+
int installTimerInterruptHandler(int line);
85+
static void timerInterruptHandler(void *arg);
86+
static void timerInterruptHandlerSS(void *arg);
87+
bool handleInterrupt();
88+
protected:
89+
void isAvailable(TimerInstance_class*cptr);
90+
TimerInstance_class *getFreeTimer();
91+
protected:
92+
TimerInstance_class m_timer0, m_timer1;
93+
TimerInstance_class *m_pwmTimerPtr, *m_intrTimerPtr;
94+
void *m_timerArg;
95+
bool (*m_timerFunc)(void*);
96+
unsigned m_timerlock;
97+
};
98+
};
1999
#endif

0 commit comments

Comments
 (0)