4 #include "ImplementationException.h"
7 bit_CS0
= 0, /* timer/counter clock select bit 0 */
10 bit_ICES
= 6, /* input capture edge select */
11 bit_ICNC
= 7, /* input capture noise canceler (4 CKs) */
15 mask_CS0
= 1 << bit_CS0
,
16 mask_CS1
= 1 << bit_CS1
,
17 mask_CS2
= 1 << bit_CS2
,
18 mask_ICES
= 1 << bit_ICES
,
19 mask_ICNC
= 1 << bit_ICNC
,
20 mask_CS
= (mask_CS0
| mask_CS1
| mask_CS2
),
24 CS_STOP
= 0x00, /* Stop, the Timer/Counter is stopped */
25 CS_CK
= 0x01, /* CK */
26 CS_CK_8
= 0x02, /* CK/8 */
27 CS_CK_64
= 0x03, /* CK/64 */
28 CS_CK_256
= 0x04, /* CK/256 */
29 CS_CK_1024
= 0x05, /* CK/1024 */
30 CS_EXT_FALL
= 0x06, /* External Pin Tn, falling edge */
31 CS_EXT_RISE
= 0x07, /* External Pin Tn, rising edge */
48 mask_WGM
= (WGM1
|WGM0
),
49 mask_COM
= (COM1
|COM0
),
66 MODE_FASTPWM_ICR
= 14,
80 #define overflow() *tifr |= tovmask
81 #define compareMatch() *tifr |= ocfmask
83 class OutputCompareUnit16
: public Hardware
{
85 OutputCompareUnit16();
89 word
value() const { return ocrBuf
; }
90 void forceOutputCompare(word tcnt
);
91 void compareMatchOutput(word tcnt
);
95 unsigned char compareMode
;
102 void OutputCompareUnit16::flush() {
103 ocrBuf
= (ocrh
->get() << 8) || ocrl
->get();
106 void OutputCompareUnit16::forceOutputCompare(word tcnt
) {
107 compareMatchOutput( tcnt
);
110 // compareMode = val & mask_COM;
112 void OutputCompareUnit16::compareMatchOutput(word tcnt
) {
113 // the non-PWM modes are NORMAL and CTC
114 // under NORMAL, there is no pin action for a compare match
115 // under CTC, the action is to clear the pin.
116 if( tcnt
== ocrBuf
) {
117 switch( compareMode
) {
122 //outputComparePin.toggle();
126 //outputComparePin.low();
130 //outputComparePin.high();
138 bool Timer16::attachReg(const char *name
, IORegister
*reg
) {
139 if( strcmp(name
, "tcntl") == 0 ) {
141 reg
->registerHW(this);
142 } else if( strcmp(name
, "tcnth") == 0 )
144 else if( strcmp(name
, "tccr") == 0 ) {
146 reg
->registerHW(this);
147 } else if( strcmp(name
, "tifr") == 0 )
155 void Timer16::regChanged( IORegister
*reg
) {
157 unsigned char val
= tccr
->get();
160 unsigned char timerModeNew
= val
& mask_WGM
;
161 if( timerMode
!= timerModeNew
)
163 timerMode
= timerModeNew
;
166 ;//for(int cntr = 0; cntr < compareUnits.size(); cntr++ )
167 // TODO compareUnits[cntr].forceOutputCompare(tcnt);
168 } else if( reg
== tcntl
) {
169 tcnt
|= (tcnth
->get()<<8) | tcntl
->get();
170 blockCompareMatch
= true;
174 void Timer16::setClock(unsigned char tccr
) {
175 byte clk
= tccr
& mask_CS
;
178 bus
.clearBreak(this);
203 throw util::ImplementationException(
204 "external timer/counter sources not implemented" );
207 bus
.setBreakDelta(period
, this);
210 void Timer16::step() {
211 static const word TOP
[] = {
212 0xffff, 0x00ff, 0x01ff, 0x03ff, 0, 0x0ff, 0x01ff, 0x03ff
214 static const word MAX
= 0xffff;
219 word tcntSave
= tcnt
;
222 switch( timerMode
) {
224 if( tcnt
== TOP
[timerMode
] ) {
233 if( (tcnt
== TOP
[timerMode
]) && (direction
== +1) ) {
236 } else if( (tcnt
== 0) && (direction
== -1) ) {
243 if( tcnt
== compareA
) {
245 } else if( tcnt
== MAX
) {
252 case MODE_FASTPWM_10
:
253 if( tcnt
== TOP
[timerMode
] ) {
260 case MODE_PWM_PNF_ICR
:
261 if( (tcnt
== compareI
) && (direction
== +1) ) {
263 } else if( (tcnt
== 0) && (direction
== -1) ) {
270 case MODE_PWM_PNF_OCR
:
271 if( (tcnt
== compareA
) && (direction
== +1) ) {
273 } else if( (tcnt
== 0) && (direction
== -1) ) {
281 if( (tcnt
== compareI
) && (direction
== +1) ) {
284 } else if( (tcnt
== 0) && (direction
== -1) ) {
291 if( (tcnt
== compareI
) && (direction
== +1) ) {
294 } else if( (tcnt
== 0) && (direction
== -1) ) {
301 if( tcnt
== compareI
) {
303 } else if( tcnt
== MAX
) {
308 case MODE_FASTPWM_ICR
:
309 if( tcnt
== compareI
) {
316 case MODE_FASTPWM_OCR
:
317 if( tcnt
== compareI
) {
327 if( ! blockCompareMatch
)
328 ;//for(int cntr = 0; cntr < compareUnits.size(); cntr++ )
329 // TODO compareUnits[cntr].compare(tcntSave);
330 blockCompareMatch
= false;
332 tcntl
->set( tcnt
& 0xff );
333 tcnth
->set( (tcnt
>> 8) & 0xff );
334 bus
.setBreakDelta(period
, this);
337 void Timer16::flushOCRn() {
339 //for(int cntr = 0; cntr < compareUnits.size(); cntr++ )
340 // compareUnits[cntr].flush();