00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "../hardware.h"
00027 #include "../avrdevice.h"
00028 #include "timerprescaler.h"
00029 #include "hwtimer.h"
00030 #include "../helper.h"
00031
00032 using namespace std;
00033
00034 BasicTimerUnit::BasicTimerUnit(AvrDevice *core,
00035 PrescalerMultiplexer *p,
00036 int unit,
00037 IRQLine* tov,
00038 IRQLine* tcap,
00039 ICaptureSource* icapsrc,
00040 int countersize):
00041 Hardware(core),
00042 TraceValueRegister(core, "TIMER" + int2str(unit)),
00043 core(core),
00044 premx(p),
00045 timerOverflow(tov),
00046 timerCapture(tcap),
00047 icapSource(icapsrc)
00048 {
00049
00050 if(countersize != 8 && countersize != 16)
00051 avr_error("wrong parameter: countersize=%d", countersize);
00052 if(countersize == 8)
00053 limit_max = 0xff;
00054 else
00055 limit_max = 0xffff;
00056
00057
00058 icapRegister = 0;
00059
00060
00061 counterTrace = new TraceValue(countersize, GetTraceValuePrefix() + "Counter");
00062 RegisterTraceValue(counterTrace);
00063 counterTrace->set_written(0);
00064
00065
00066 for(int i = 0; i < OCRIDX_maxUnits; i++) {
00067 compareEnable[i] = false;
00068 timerCompare[i] = NULL;
00069 compare_output[i] = NULL;
00070 }
00071
00072
00073 for(int i = 0; i < WGM_tablesize; i++)
00074 wgmfunc[i] = &BasicTimerUnit::WGMFunc_noop;
00075
00076
00077 captureInputState = false;
00078 icapNCcounter = 0;
00079 icapNCstate = false;
00080
00081
00082 Reset();
00083
00084 }
00085
00086 BasicTimerUnit::~BasicTimerUnit() {
00087 delete counterTrace;
00088 }
00089
00090 void BasicTimerUnit::CountTimer() {
00091 vlast_tcnt = vtcnt;
00092 if(updown_counting) {
00093
00094 if(compareEnable[0]) {
00095 if(vlast_tcnt == compare[0])
00096 HandleEvent(EVT_COMPARE_1);
00097 if(compareEnable[1]) {
00098 if(vlast_tcnt == compare[1])
00099 HandleEvent(EVT_COMPARE_2);
00100 if(compareEnable[2]) {
00101 if(vlast_tcnt == compare[2])
00102 HandleEvent(EVT_COMPARE_3);
00103 }
00104 }
00105 }
00106
00107
00108 if(vlast_tcnt == limit_bottom)
00109 HandleEvent(EVT_BOTTOM_REACHED);
00110 else if(vlast_tcnt == limit_top)
00111 HandleEvent(EVT_TOP_REACHED);
00112
00113
00114 if(count_down) {
00115 vtcnt--;
00116 counterTrace->change(vtcnt);
00117 if(vtcnt == limit_bottom)
00118 count_down = false;
00119 } else {
00120 vtcnt++;
00121 counterTrace->change(vtcnt);
00122 if(vtcnt == limit_top)
00123 count_down = true;
00124 }
00125 } else {
00126
00127 vtcnt++;
00128 if(vtcnt > limit_max) {
00129 HandleEvent(EVT_MAX_REACHED);
00130 vtcnt &= limit_max;
00131 }
00132
00133
00134 if(vlast_tcnt == limit_bottom)
00135 HandleEvent(EVT_BOTTOM_REACHED);
00136
00137
00138 if(vlast_tcnt == limit_top)
00139 HandleEvent(EVT_TOP_REACHED);
00140
00141
00142 if(compareEnable[0]) {
00143 if(vlast_tcnt == compare[0])
00144 HandleEvent(EVT_COMPARE_1);
00145 if(compareEnable[1]) {
00146 if(vlast_tcnt == compare[1])
00147 HandleEvent(EVT_COMPARE_2);
00148 if(compareEnable[2]) {
00149 if(vlast_tcnt == compare[2])
00150 HandleEvent(EVT_COMPARE_3);
00151 }
00152 }
00153 }
00154
00155
00156 counterTrace->change(vtcnt);
00157 }
00158 }
00159
00160 void BasicTimerUnit::InputCapture(void) {
00161 if(icapSource != NULL && !WGMuseICR()) {
00162
00163 bool tmp = icapSource->GetSourceState();
00164 if(icapNoiseCanceler) {
00165
00166 if(tmp == icapNCstate) {
00167 if(icapNCcounter < 4) {
00168 icapNCcounter++;
00169 tmp = captureInputState;
00170 }
00171 } else {
00172
00173 icapNCcounter = 0;
00174 icapNCstate = tmp;
00175 tmp = captureInputState;
00176 }
00177 }
00178
00179
00180 if(tmp != captureInputState) {
00181 if(tmp == icapRisingEdge) {
00182
00183 icapRegister = vtcnt;
00184
00185 if(timerCapture)
00186 timerCapture->fireInterrupt();
00187 }
00188 captureInputState = tmp;
00189 }
00190 }
00191 }
00192
00193 void BasicTimerUnit::SetClockMode(int mode) {
00194 cs = mode;
00195 if(cs != 0) {
00196 core->AddToCycleList(this);
00197 } else {
00198 core->RemoveFromCycleList(this);
00199 }
00200 }
00201
00202 void BasicTimerUnit::SetCounter(unsigned long val) {
00203 vtcnt = val;
00204 vlast_tcnt = 0x10000;
00205 counterTrace->change(val);
00206 }
00207
00208 void BasicTimerUnit::SetCompareOutputMode(int idx, COMtype mode) {
00209 com[idx] = mode;
00210 if(compare_output[idx]) {
00211 if(mode == COM_NOOP)
00212 compare_output[idx]->SetUseAlternatePortIfDdrSet(false);
00213 else {
00214 compare_output[idx]->SetUseAlternatePortIfDdrSet(true);
00215 compare_output[idx]->SetAlternatePort(compare_output_state[idx]);
00216 }
00217 }
00218 }
00219
00220 void BasicTimerUnit::SetCompareOutput(int idx) {
00221 COMtype mode = com[idx];
00222 bool new_state, old_state = compare_output_state[idx];
00223 switch(mode) {
00224 case COM_NOOP:
00225 return;
00226
00227 case COM_TOGGLE:
00228 new_state = old_state ? false : true;
00229 break;
00230
00231 case COM_CLEAR:
00232 new_state = false;
00233 break;
00234
00235 case COM_SET:
00236 new_state = true;
00237 break;
00238 }
00239 compare_output_state[idx] = new_state;
00240 if(compare_output[idx] && old_state != new_state)
00241 compare_output[idx]->SetAlternatePort(new_state);
00242 }
00243
00244 void BasicTimerUnit::SetPWMCompareOutput(int idx, bool topOrDown) {
00245 COMtype mode = com[idx];
00246 bool new_state, old_state = compare_output_state[idx];
00247 switch(mode) {
00248 case COM_NOOP:
00249 return;
00250
00251 case COM_TOGGLE:
00252 if((wgm == WGM_FASTPWM_OCRA ||
00253 wgm == WGM_PCPWM_OCRA ||
00254 wgm == WGM_PFCPWM_OCRA) && idx == OCRIDX_A)
00255
00256 SetCompareOutput(OCRIDX_A);
00257 else
00258 avr_warning("COM==1 in PWM mode is reserved!");
00259 break;
00260
00261 case COM_CLEAR:
00262 if(topOrDown)
00263 new_state = true;
00264 else
00265 new_state = false;
00266 break;
00267
00268 case COM_SET:
00269 if(topOrDown)
00270 new_state = false;
00271 else
00272 new_state = true;
00273 break;
00274 }
00275 compare_output_state[idx] = new_state;
00276 if(compare_output[idx] && old_state != new_state)
00277 compare_output[idx]->SetAlternatePort(new_state);
00278 }
00279
00280 void BasicTimerUnit::WGMfunc_normal(CEtype event) {
00281 switch(event) {
00282 case EVT_MAX_REACHED:
00283 timerOverflow->fireInterrupt();
00284 break;
00285
00286 case EVT_COMPARE_1:
00287 if(timerCompare[0]) {
00288 timerCompare[0]->fireInterrupt();
00289 SetCompareOutput(0);
00290 }
00291 break;
00292
00293 case EVT_COMPARE_2:
00294 if(timerCompare[1]) {
00295 timerCompare[1]->fireInterrupt();
00296 SetCompareOutput(1);
00297 }
00298 break;
00299
00300 case EVT_COMPARE_3:
00301 if(timerCompare[2]) {
00302 timerCompare[2]->fireInterrupt();
00303 SetCompareOutput(2);
00304 }
00305 break;
00306
00307 default:
00308 break;
00309 }
00310 }
00311
00312 void BasicTimerUnit::WGMfunc_ctc(CEtype event) {
00313 switch(event) {
00314 case EVT_MAX_REACHED:
00315 timerOverflow->fireInterrupt();
00316 break;
00317
00318 case EVT_TOP_REACHED:
00319 vtcnt = limit_bottom;
00320 break;
00321
00322 case EVT_COMPARE_1:
00323 if(timerCompare[0]) {
00324 timerCompare[0]->fireInterrupt();
00325 SetCompareOutput(0);
00326 }
00327 break;
00328
00329 case EVT_COMPARE_2:
00330 if(timerCompare[1]) {
00331 timerCompare[1]->fireInterrupt();
00332 SetCompareOutput(1);
00333 }
00334 break;
00335
00336 case EVT_COMPARE_3:
00337 if(timerCompare[2]) {
00338 timerCompare[2]->fireInterrupt();
00339 SetCompareOutput(2);
00340 }
00341 break;
00342
00343 default:
00344 break;
00345 }
00346 }
00347
00348 void BasicTimerUnit::WGMfunc_fastpwm(CEtype event) {
00349 switch(event) {
00350 case EVT_TOP_REACHED:
00351
00352 timerOverflow->fireInterrupt();
00353
00354 if(wgm == WGM_FASTPWM_OCRA) {
00355 if(timerCompare[OCRIDX_A])
00356 timerCompare[OCRIDX_A]->fireInterrupt();
00357 } else if(wgm == WGM_FASTPWM_ICR) {
00358 if(timerCapture)
00359 timerCapture->fireInterrupt();
00360 }
00361
00362 for(int i = 0; i < OCRIDX_maxUnits; i++)
00363 SetPWMCompareOutput(i, true);
00364
00365 vtcnt = limit_bottom;
00366 break;
00367
00368 case EVT_BOTTOM_REACHED:
00369
00370 for(int i = 0; i < OCRIDX_maxUnits; i++) {
00371 if(i == OCRIDX_A) {
00372 if(wgm == WGM_FASTPWM_8BIT)
00373
00374 compare[i] = compare_dbl[i] & 0xff;
00375 else if(wgm == WGM_FASTPWM_9BIT)
00376
00377 compare[i] = compare_dbl[i] & 0x1ff;
00378 else if(wgm == WGM_FASTPWM_10BIT)
00379
00380 compare[i] = compare_dbl[i] & 0x3ff;
00381 else if(wgm == WGM_FASTPWM_OCRA)
00382
00383 limit_top = compare_dbl[i];
00384 else
00385 compare[OCRIDX_A] = compare_dbl[OCRIDX_A];
00386 } else
00387 compare[i] = compare_dbl[i];
00388 }
00389 break;
00390
00391 case EVT_COMPARE_1:
00392 if(timerCompare[0] && wgm != WGM_FASTPWM_OCRA) {
00393 timerCompare[0]->fireInterrupt();
00394 SetPWMCompareOutput(0, false);
00395 }
00396 break;
00397
00398 case EVT_COMPARE_2:
00399 if(timerCompare[1]) {
00400 timerCompare[1]->fireInterrupt();
00401 SetPWMCompareOutput(1, false);
00402 }
00403 break;
00404
00405 case EVT_COMPARE_3:
00406 if(timerCompare[2]) {
00407 timerCompare[2]->fireInterrupt();
00408 SetPWMCompareOutput(2, false);
00409 }
00410 break;
00411
00412 default:
00413 break;
00414 }
00415 }
00416
00417 void BasicTimerUnit::WGMfunc_pcpwm(CEtype event) {
00418 switch(event) {
00419 case EVT_TOP_REACHED:
00420
00421 if(wgm == WGM_PCPWM_OCRA) {
00422 if(timerCompare[OCRIDX_A])
00423 timerCompare[OCRIDX_A]->fireInterrupt();
00424 } else if(wgm == WGM_PCPWM_ICR) {
00425 if(timerCapture)
00426 timerCapture->fireInterrupt();
00427 }
00428
00429 for(int i = 0; i < OCRIDX_maxUnits; i++) {
00430 if(i == OCRIDX_A) {
00431 if(wgm == WGM_PCPWM_8BIT)
00432
00433 compare[i] = compare_dbl[i] & 0xff;
00434 else if(wgm == WGM_PCPWM_9BIT)
00435
00436 compare[i] = compare_dbl[i] & 0x1ff;
00437 else if(wgm == WGM_PCPWM_10BIT)
00438
00439 compare[i] = compare_dbl[i] & 0x3ff;
00440 else if(wgm == WGM_PCPWM_OCRA) {
00441
00442 limit_top = compare_dbl[i];
00443
00444 SetPWMCompareOutput(0, false);
00445 } else
00446 compare[OCRIDX_A] = compare_dbl[OCRIDX_A];
00447
00448 } else
00449 compare[i] = compare_dbl[i];
00450 }
00451 break;
00452
00453 case EVT_BOTTOM_REACHED:
00454
00455 timerOverflow->fireInterrupt();
00456 break;
00457
00458 case EVT_COMPARE_1:
00459 if(timerCompare[0] && wgm != WGM_PCPWM_OCRA) {
00460 timerCompare[0]->fireInterrupt();
00461 SetPWMCompareOutput(0, count_down);
00462 }
00463 break;
00464
00465 case EVT_COMPARE_2:
00466 if(timerCompare[1]) {
00467 timerCompare[1]->fireInterrupt();
00468 SetPWMCompareOutput(1, count_down);
00469 }
00470 break;
00471
00472 case EVT_COMPARE_3:
00473 if(timerCompare[2]) {
00474 timerCompare[2]->fireInterrupt();
00475 SetPWMCompareOutput(2, count_down);
00476 }
00477 break;
00478
00479 default:
00480 break;
00481 }
00482 }
00483
00484 void BasicTimerUnit::WGMfunc_pfcpwm(CEtype event) {
00485 switch(event) {
00486 case EVT_TOP_REACHED:
00487
00488 if(wgm == WGM_PFCPWM_OCRA) {
00489 if(timerCompare[OCRIDX_A])
00490 timerCompare[OCRIDX_A]->fireInterrupt();
00491 } else if(wgm == WGM_PFCPWM_ICR) {
00492 if(timerCapture)
00493 timerCapture->fireInterrupt();
00494 }
00495
00496 if(wgm == WGM_PFCPWM_OCRA)
00497 SetPWMCompareOutput(0, false);
00498 break;
00499
00500 case EVT_BOTTOM_REACHED:
00501
00502 timerOverflow->fireInterrupt();
00503
00504 for(int i = 0; i < OCRIDX_maxUnits; i++) {
00505 if(i == OCRIDX_A) {
00506 if(wgm == WGM_PFCPWM_OCRA)
00507
00508 limit_top = compare_dbl[i];
00509 else
00510 compare[OCRIDX_A] = compare_dbl[OCRIDX_A];
00511 } else
00512 compare[i] = compare_dbl[i];
00513 }
00514 break;
00515
00516 case EVT_COMPARE_1:
00517 if(timerCompare[0] && wgm != WGM_PFCPWM_OCRA) {
00518 timerCompare[0]->fireInterrupt();
00519 SetPWMCompareOutput(0, count_down);
00520 }
00521 break;
00522
00523 case EVT_COMPARE_2:
00524 if(timerCompare[1]) {
00525 timerCompare[1]->fireInterrupt();
00526 SetPWMCompareOutput(1, count_down);
00527 }
00528 break;
00529
00530 case EVT_COMPARE_3:
00531 if(timerCompare[2]) {
00532 timerCompare[2]->fireInterrupt();
00533 SetPWMCompareOutput(2, count_down);
00534 }
00535 break;
00536
00537 default:
00538 break;
00539 }
00540 }
00541
00542 void BasicTimerUnit::Reset() {
00543 vtcnt = 0;
00544 limit_bottom = 0;
00545 limit_top = limit_max;
00546 vlast_tcnt = limit_top;
00547 for(int i = 0; i < OCRIDX_maxUnits; i++) {
00548 compare_dbl[i] = 0;
00549 compare[i] = 0;
00550 SetCompareOutputMode(i, COM_NOOP);
00551 compare_output_state[i] = false;
00552 }
00553 SetClockMode(0);
00554 updown_counting = false;
00555 count_down = false;
00556 wgm = WGM_NORMAL;
00557 icapRisingEdge = false;
00558 icapNoiseCanceler = false;
00559 }
00560
00561 unsigned int BasicTimerUnit::CpuCycle() {
00562 if(premx->isClock(cs))
00563 CountTimer();
00564 InputCapture();
00565 return 0;
00566 }
00567
00568 HWTimer8::HWTimer8(AvrDevice *core,
00569 PrescalerMultiplexer *p,
00570 int unit,
00571 IRQLine* tov,
00572 IRQLine* tcompA,
00573 PinAtPort* outA,
00574 IRQLine* tcompB,
00575 PinAtPort* outB):
00576 BasicTimerUnit(core, p, unit, tov, NULL, NULL, 8),
00577 tcnt_reg(this, "TCNT",
00578 this, &HWTimer8::Get_TCNT, &HWTimer8::Set_TCNT),
00579 ocra_reg(this, "OCRA",
00580 this, &HWTimer8::Get_OCRA, &HWTimer8::Set_OCRA),
00581 ocrb_reg(this, "OCRB",
00582 this, &HWTimer8::Get_OCRB, &HWTimer8::Set_OCRB)
00583 {
00584
00585 if(tcompA) {
00586 compareEnable[0] = true;
00587 timerCompare[0] = tcompA;
00588 compare_output[0] = outA;
00589 } else
00590 ocra_reg.releaseTraceValue();
00591 if(tcompB) {
00592 compareEnable[1] = true;
00593 timerCompare[1] = tcompB;
00594 compare_output[1] = outB;
00595 } else
00596 ocrb_reg.releaseTraceValue();
00597
00598
00599 wgmfunc[WGM_NORMAL] = &HWTimer8::WGMfunc_normal;
00600 wgmfunc[WGM_CTC_OCRA] = &HWTimer8::WGMfunc_ctc;
00601 wgmfunc[WGM_FASTPWM_8BIT] = &HWTimer8::WGMfunc_fastpwm;
00602 wgmfunc[WGM_PCPWM_8BIT] = &HWTimer8::WGMfunc_pcpwm;
00603
00604
00605 Reset();
00606 }
00607
00608 void HWTimer8::Reset(void) {
00609 BasicTimerUnit::Reset();
00610 }
00611
00612 void HWTimer8::ChangeWGM(WGMtype mode) {
00613 wgm = mode;
00614 switch(wgm) {
00615 case WGM_NORMAL:
00616 limit_top = limit_max;
00617 updown_counting = false;
00618 break;
00619
00620 case WGM_CTC_OCRA:
00621 limit_top = compare[0];
00622 updown_counting = false;
00623 break;
00624
00625 case WGM_FASTPWM_8BIT:
00626 limit_top = limit_max;
00627 updown_counting = false;
00628 break;
00629
00630 case WGM_PCPWM_8BIT:
00631 limit_top = limit_max;
00632 updown_counting = true;
00633 count_down = false;
00634 break;
00635 }
00636 }
00637
00638 void HWTimer8::SetCompareRegister(int idx, unsigned char val) {
00639 if(WGMisPWM())
00640 compare_dbl[idx] = val;
00641 else {
00642 compare[idx] = val;
00643 compare_dbl[idx] = val;
00644 if(wgm == WGM_CTC_OCRA && idx == 0)
00645
00646
00647 limit_top = val;
00648 }
00649 }
00650
00651 unsigned char HWTimer8::GetCompareRegister(int idx) {
00652 if(WGMisPWM())
00653 return compare_dbl[idx] & 0xff;
00654 else
00655 return compare[idx] & 0xff;
00656 }
00657
00658 HWTimer16::HWTimer16(AvrDevice *core,
00659 PrescalerMultiplexer *p,
00660 int unit,
00661 IRQLine* tov,
00662 IRQLine* tcompA,
00663 PinAtPort* outA,
00664 IRQLine* tcompB,
00665 PinAtPort* outB,
00666 IRQLine* tcompC,
00667 PinAtPort* outC,
00668 IRQLine* ticap,
00669 ICaptureSource* icapsrc):
00670 BasicTimerUnit(core, p, unit, tov, ticap, icapsrc, 16),
00671 tcnt_h_reg(this, "TCNTH",
00672 this, &HWTimer16::Get_TCNTH, &HWTimer16::Set_TCNTH),
00673 tcnt_l_reg(this, "TCNTL",
00674 this, &HWTimer16::Get_TCNTL, &HWTimer16::Set_TCNTL),
00675 ocra_h_reg(this, "OCRAH",
00676 this, &HWTimer16::Get_OCRAH, &HWTimer16::Set_OCRAH),
00677 ocra_l_reg(this, "OCRAL",
00678 this, &HWTimer16::Get_OCRAL, &HWTimer16::Set_OCRAL),
00679 ocrb_h_reg(this, "OCRBH",
00680 this, &HWTimer16::Get_OCRBH, &HWTimer16::Set_OCRBH),
00681 ocrb_l_reg(this, "OCRBL",
00682 this, &HWTimer16::Get_OCRBL, &HWTimer16::Set_OCRBL),
00683 ocrc_h_reg(this, "OCRCH",
00684 this, &HWTimer16::Get_OCRCH, &HWTimer16::Set_OCRCH),
00685 ocrc_l_reg(this, "OCRCL",
00686 this, &HWTimer16::Get_OCRCL, &HWTimer16::Set_OCRCL),
00687 icr_h_reg(this, "ICRH",
00688 this, &HWTimer16::Get_ICRH, &HWTimer16::Set_ICRH),
00689 icr_l_reg(this, "ICRL",
00690 this, &HWTimer16::Get_ICRL, &HWTimer16::Set_ICRL)
00691 {
00692
00693 if(tcompA) {
00694 compareEnable[0] = true;
00695 timerCompare[0] = tcompA;
00696 compare_output[0] = outA;
00697 } else {
00698 ocra_l_reg.releaseTraceValue();
00699 ocra_h_reg.releaseTraceValue();
00700 }
00701 if(tcompB) {
00702 compareEnable[1] = true;
00703 timerCompare[1] = tcompB;
00704 compare_output[1] = outB;
00705 } else {
00706 ocrb_l_reg.releaseTraceValue();
00707 ocrb_h_reg.releaseTraceValue();
00708 }
00709 if(tcompC) {
00710 compareEnable[2] = true;
00711 timerCompare[2] = tcompC;
00712 compare_output[2] = outC;
00713 } else {
00714 ocrc_l_reg.releaseTraceValue();
00715 ocrc_h_reg.releaseTraceValue();
00716 }
00717
00718
00719 wgmfunc[WGM_NORMAL] = &HWTimer16::WGMfunc_normal;
00720 wgmfunc[WGM_CTC_OCRA] = &HWTimer16::WGMfunc_ctc;
00721 wgmfunc[WGM_CTC_ICR] = &HWTimer16::WGMfunc_ctc;
00722 wgmfunc[WGM_FASTPWM_8BIT] = &HWTimer16::WGMfunc_fastpwm;
00723 wgmfunc[WGM_FASTPWM_9BIT] = &HWTimer16::WGMfunc_fastpwm;
00724 wgmfunc[WGM_FASTPWM_10BIT] = &HWTimer16::WGMfunc_fastpwm;
00725 wgmfunc[WGM_FASTPWM_OCRA] = &HWTimer16::WGMfunc_fastpwm;
00726 wgmfunc[WGM_FASTPWM_ICR] = &HWTimer16::WGMfunc_fastpwm;
00727 wgmfunc[WGM_PCPWM_8BIT] = &HWTimer16::WGMfunc_pcpwm;
00728 wgmfunc[WGM_PCPWM_9BIT] = &HWTimer16::WGMfunc_pcpwm;
00729 wgmfunc[WGM_PCPWM_10BIT] = &HWTimer16::WGMfunc_pcpwm;
00730 wgmfunc[WGM_PCPWM_OCRA] = &HWTimer16::WGMfunc_pcpwm;
00731 wgmfunc[WGM_PCPWM_ICR] = &HWTimer16::WGMfunc_pcpwm;
00732 wgmfunc[WGM_PFCPWM_OCRA] = &HWTimer16::WGMfunc_pfcpwm;
00733 wgmfunc[WGM_PFCPWM_ICR] = &HWTimer16::WGMfunc_pfcpwm;
00734
00735
00736 Reset();
00737 }
00738
00739 void HWTimer16::Reset(void) {
00740 BasicTimerUnit::Reset();
00741
00742 accessTempRegister = 0;
00743 }
00744
00745 void HWTimer16::SetCompareRegister(int idx, bool high, unsigned char val) {
00746 unsigned long temp;
00747 if(high) {
00748 accessTempRegister = val;
00749 } else {
00750 temp = (accessTempRegister << 8) + val;
00751 if(WGMisPWM())
00752 compare_dbl[idx] = temp;
00753 else {
00754 compare[idx] = temp;
00755 compare_dbl[idx] = temp;
00756 if(wgm == WGM_CTC_OCRA && idx == 0)
00757
00758
00759 limit_top = temp;
00760 }
00761 }
00762 }
00763
00764 unsigned char HWTimer16::GetCompareRegister(int idx, bool high) {
00765 unsigned long temp;
00766 if(WGMisPWM())
00767 temp = compare_dbl[idx];
00768 else
00769 temp = compare[idx];
00770 if(high)
00771 return (temp >> 8) & 0xff;
00772 else
00773 return temp & 0xff;
00774 }
00775
00776 void HWTimer16::SetComplexRegister(bool is_icr, bool high, unsigned char val) {
00777 if(high) {
00778 if(is_icr && !WGMuseICR())
00779 avr_warning("ICRxH isn't writable in a non-ICR WGM mode");
00780 else
00781 accessTempRegister = val;
00782 } else {
00783 if(is_icr) {
00784 if(WGMuseICR()) {
00785 icapRegister = (accessTempRegister << 8) + val;
00786 if(wgm == WGM_FASTPWM_ICR)
00787 limit_top = icapRegister;
00788 } else
00789 avr_warning("ICRxL isn't writable in a non-ICR WGM mode");
00790 } else
00791 SetCounter((accessTempRegister << 8) + val);
00792 }
00793 }
00794
00795 unsigned char HWTimer16::GetComplexRegister(bool is_icr, bool high) {
00796 if(high)
00797 return accessTempRegister;
00798 else {
00799 if(is_icr) {
00800 accessTempRegister = (icapRegister >> 8) & 0xff;
00801 return icapRegister & 0xff;
00802 } else {
00803 accessTempRegister = (vtcnt >> 8) & 0xff;
00804 return vtcnt & 0xff;
00805 }
00806 }
00807 }
00808
00809 void HWTimer16::ChangeWGM(WGMtype mode) {
00810 wgm = mode;
00811 switch(wgm) {
00812 case WGM_NORMAL:
00813 limit_top = limit_max;
00814 updown_counting = false;
00815 break;
00816
00817 case WGM_CTC_OCRA:
00818 limit_top = compare[0];
00819 updown_counting = false;
00820 break;
00821
00822 case WGM_CTC_ICR:
00823 limit_top = icapRegister;
00824 updown_counting = false;
00825 break;
00826
00827 case WGM_FASTPWM_8BIT:
00828 limit_top = 0xff;
00829 updown_counting = false;
00830 break;
00831
00832 case WGM_FASTPWM_9BIT:
00833 limit_top = 0x1ff;
00834 updown_counting = false;
00835 break;
00836
00837 case WGM_FASTPWM_10BIT:
00838 limit_top = 0x3ff;
00839 updown_counting = false;
00840 break;
00841
00842 case WGM_FASTPWM_OCRA:
00843 limit_top = compare[0];
00844 updown_counting = false;
00845 break;
00846
00847 case WGM_FASTPWM_ICR:
00848 limit_top = icapRegister;
00849 updown_counting = false;
00850 break;
00851
00852 case WGM_PCPWM_8BIT:
00853 limit_top = 0xff;
00854 updown_counting = true;
00855 count_down = false;
00856 break;
00857
00858 case WGM_PCPWM_9BIT:
00859 limit_top = 0x1ff;
00860 updown_counting = true;
00861 count_down = false;
00862 break;
00863
00864 case WGM_PCPWM_10BIT:
00865 limit_top = 0x3ff;
00866 updown_counting = true;
00867 count_down = false;
00868 break;
00869
00870 case WGM_PCPWM_OCRA:
00871 case WGM_PFCPWM_OCRA:
00872 limit_top = compare[0];
00873 updown_counting = true;
00874 count_down = false;
00875 break;
00876
00877 case WGM_PCPWM_ICR:
00878 case WGM_PFCPWM_ICR:
00879 limit_top = icapRegister;
00880 updown_counting = true;
00881 count_down = false;
00882 break;
00883 }
00884 }
00885
00886 HWTimer8_0C::HWTimer8_0C(AvrDevice *core,
00887 PrescalerMultiplexer *p,
00888 int unit,
00889 IRQLine* tov):
00890 HWTimer8(core, p, unit, tov, NULL, NULL, NULL, NULL),
00891 tccr_reg(this, "TCCR",
00892 this, &HWTimer8_0C::Get_TCCR, &HWTimer8_0C::Set_TCCR)
00893 {
00894 ChangeWGM(WGM_NORMAL);
00895 }
00896
00897 void HWTimer8_0C::Set_TCCR(unsigned char val) {
00898 SetClockMode(val & 0x7);
00899 tccr_val = val;
00900 }
00901
00902 void HWTimer8_0C::Reset() {
00903 HWTimer8::Reset();
00904 tccr_val = 0;
00905 }
00906
00907 HWTimer8_1C::HWTimer8_1C(AvrDevice *core,
00908 PrescalerMultiplexer *p,
00909 int unit,
00910 IRQLine* tov,
00911 IRQLine* tcompA,
00912 PinAtPort* outA):
00913 HWTimer8(core, p, unit, tov, tcompA, outA, NULL, NULL),
00914 tccr_reg(this, "TCCR",
00915 this, &HWTimer8_1C::Get_TCCR, &HWTimer8_1C::Set_TCCR) {}
00916
00917 void HWTimer8_1C::Set_TCCR(unsigned char val) {
00918 WGMtype temp;
00919 int raw_wgm = ((val & 0x8) >> 2) + ((val & 0x40) >> 6);
00920 switch(raw_wgm) {
00921 case 0: temp = WGM_NORMAL; break;
00922 case 1: temp = WGM_PCPWM_8BIT; break;
00923 case 2: temp = WGM_CTC_OCRA; break;
00924 case 3: temp = WGM_FASTPWM_8BIT; break;
00925 }
00926 if(wgm != temp)
00927 ChangeWGM((WGMtype)temp);
00928 SetCompareOutputMode(0, (COMtype)((val >> 4) & 0x3));
00929 SetClockMode(val & 0x7);
00930 if(!WGMisPWM() && val & 0x80)
00931
00932 SetCompareOutput(0);
00933
00934 tccr_val = val & 0x7f;
00935 }
00936
00937 void HWTimer8_1C::Reset() {
00938 HWTimer8::Reset();
00939 tccr_val = 0;
00940 }
00941
00942 HWTimer8_2C::HWTimer8_2C(AvrDevice *core,
00943 PrescalerMultiplexer *p,
00944 int unit,
00945 IRQLine* tov,
00946 IRQLine* tcompA,
00947 PinAtPort* outA,
00948 IRQLine* tcompB,
00949 PinAtPort* outB):
00950 HWTimer8(core, p, unit, tov, tcompA, outA, tcompB, outB),
00951 tccra_reg(this, "TCCRA",
00952 this, &HWTimer8_2C::Get_TCCRA, &HWTimer8_2C::Set_TCCRA),
00953 tccrb_reg(this, "TCCRB",
00954 this, &HWTimer8_2C::Get_TCCRB, &HWTimer8_2C::Set_TCCRB) {}
00955
00956 void HWTimer8_2C::Set_WGM(int val) {
00957 WGMtype w;
00958 if(wgm_raw != val) {
00959
00960 switch(val & 0x7) {
00961 case 0: w = WGM_NORMAL; break;
00962 case 1: w = WGM_PCPWM_8BIT; break;
00963 case 2: w = WGM_CTC_OCRA; break;
00964 case 3: w = WGM_FASTPWM_8BIT; break;
00965 case 4: w = WGM_RESERVED; break;
00966 case 5: w = WGM_PCPWM_OCRA; break;
00967 case 6: w = WGM_RESERVED; break;
00968 case 7: w = WGM_FASTPWM_OCRA; break;
00969 }
00970 ChangeWGM(w);
00971
00972 wgm_raw = val;
00973 }
00974 }
00975
00976 void HWTimer8_2C::Set_TCCRA(unsigned char val) {
00977 int temp = wgm_raw;
00978 temp &= ~0x3;
00979 temp += val & 0x3;
00980 Set_WGM(temp);
00981 SetCompareOutputMode(0, (COMtype)((val >> 6) & 0x3));
00982 SetCompareOutputMode(1, (COMtype)((val >> 4) & 0x3));
00983
00984 tccra_val = val;
00985 }
00986
00987 void HWTimer8_2C::Set_TCCRB(unsigned char val) {
00988 int temp = wgm_raw;
00989 temp &= ~0x4;
00990 temp += (val >> 1) & 0x4;
00991 Set_WGM(temp);
00992 SetClockMode(val & 0x7);
00993 if(!WGMisPWM()) {
00994 if(val & 0x80)
00995
00996 SetCompareOutput(0);
00997 if(val & 0x40)
00998
00999 SetCompareOutput(1);
01000 }
01001
01002 tccrb_val = val & 0x3f;
01003 }
01004
01005 void HWTimer8_2C::Reset() {
01006 HWTimer8::Reset();
01007 tccra_val = 0;
01008 tccrb_val = 0;
01009 wgm_raw = 0;
01010 }
01011
01012 HWTimer16_1C::HWTimer16_1C(AvrDevice *core,
01013 PrescalerMultiplexer *p,
01014 int unit,
01015 IRQLine* tov,
01016 IRQLine* tcompA,
01017 PinAtPort* outA,
01018 IRQLine* ticap,
01019 ICaptureSource* icapsrc):
01020 HWTimer16(core, p, unit, tov, tcompA, outA, NULL, NULL, NULL, NULL, ticap, icapsrc),
01021 tccra_reg(this, "TCCRA",
01022 this, &HWTimer16_1C::Get_TCCRA, &HWTimer16_1C::Set_TCCRA),
01023 tccrb_reg(this, "TCCRB",
01024 this, &HWTimer16_1C::Get_TCCRB, &HWTimer16_1C::Set_TCCRB) {}
01025
01026 void HWTimer16_1C::Set_WGM(int val) {
01027 WGMtype w;
01028 if(wgm_raw != val) {
01029
01030 switch(val & 0x7) {
01031 case 0: w = WGM_NORMAL; break;
01032 case 1: w = WGM_PCPWM_8BIT; break;
01033 case 2: w = WGM_PCPWM_9BIT; break;
01034 case 3: w = WGM_PCPWM_10BIT; break;
01035 case 4: w = WGM_CTC_OCRA; break;
01036 case 5: w = WGM_PCPWM_8BIT; break;
01037 case 6: w = WGM_PCPWM_9BIT; break;
01038 case 7: w = WGM_PCPWM_10BIT; break;
01039 }
01040 ChangeWGM(w);
01041
01042 wgm_raw = val;
01043 }
01044 }
01045
01046 void HWTimer16_1C::Set_TCCRA(unsigned char val) {
01047 int temp = wgm_raw;
01048 temp &= ~0x3;
01049 temp += val & 0x3;
01050 Set_WGM(temp);
01051 SetCompareOutputMode(0, (COMtype)((val >> 6) & 0x3));
01052
01053 tccra_val = val;
01054 }
01055
01056 void HWTimer16_1C::Set_TCCRB(unsigned char val) {
01057 int temp = wgm_raw;
01058 temp &= ~0x4;
01059 temp += (val >> 1) & 0x4;
01060 Set_WGM(temp);
01061 SetClockMode(val & 0x7);
01062 icapNoiseCanceler = (val & 0x80) == 0x80;
01063 icapRisingEdge = (val & 0x40) == 0x40;
01064
01065 tccrb_val = val;
01066 }
01067
01068 void HWTimer16_1C::Reset() {
01069 HWTimer16::Reset();
01070 tccra_val = 0;
01071 tccrb_val = 0;
01072 wgm_raw = 0;
01073 }
01074
01075 HWTimer16_2C2::HWTimer16_2C2(AvrDevice *core,
01076 PrescalerMultiplexer *p,
01077 int unit,
01078 IRQLine* tov,
01079 IRQLine* tcompA,
01080 PinAtPort* outA,
01081 IRQLine* tcompB,
01082 PinAtPort* outB,
01083 IRQLine* ticap,
01084 ICaptureSource* icapsrc,
01085 bool is_at8515):
01086 HWTimer16(core, p, unit, tov, tcompA, outA, tcompB, outB, NULL, NULL, ticap, icapsrc),
01087 tccra_reg(this, "TCCRA",
01088 this, &HWTimer16_2C2::Get_TCCRA, &HWTimer16_2C2::Set_TCCRA),
01089 tccrb_reg(this, "TCCRB",
01090 this, &HWTimer16_2C2::Get_TCCRB, &HWTimer16_2C2::Set_TCCRB),
01091 at8515_mode(is_at8515) {}
01092
01093 void HWTimer16_2C2::Set_WGM(int val) {
01094 if(wgm_raw != val) {
01095
01096 if(at8515_mode) {
01097 WGMtype w;
01098 switch(val & 0x7) {
01099 case 0: w = WGM_NORMAL; break;
01100 case 1: w = WGM_PCPWM_8BIT; break;
01101 case 2: w = WGM_PCPWM_9BIT; break;
01102 case 3: w = WGM_PCPWM_10BIT; break;
01103 case 4: w = WGM_CTC_OCRA; break;
01104 case 5: w = WGM_PCPWM_8BIT; break;
01105 case 6: w = WGM_PCPWM_9BIT; break;
01106 case 7: w = WGM_PCPWM_10BIT; break;
01107 }
01108 ChangeWGM(w);
01109 } else
01110 ChangeWGM((WGMtype)val);
01111
01112 wgm_raw = val;
01113 }
01114 }
01115
01116 void HWTimer16_2C2::Set_TCCRA(unsigned char val) {
01117 int temp = wgm_raw;
01118 temp &= ~0x3;
01119 temp += val & 0x3;
01120 Set_WGM(temp);
01121 SetCompareOutputMode(0, (COMtype)((val >> 6) & 0x3));
01122 SetCompareOutputMode(1, (COMtype)((val >> 4) & 0x3));
01123 if(!WGMisPWM() && !at8515_mode) {
01124 if(val & 0x08)
01125
01126 SetCompareOutput(0);
01127 if(val & 0x04)
01128
01129 SetCompareOutput(1);
01130 }
01131
01132 tccra_val = val;
01133 }
01134
01135 void HWTimer16_2C2::Set_TCCRB(unsigned char val) {
01136 int mask = at8515_mode ? 0x4 : 0xc;
01137 int temp = wgm_raw;
01138 temp &= ~mask;
01139 temp += (val >> 1) & mask;
01140 Set_WGM(temp);
01141 SetClockMode(val & 0x7);
01142 icapNoiseCanceler = (val & 0x80) == 0x80;
01143 icapRisingEdge = (val & 0x40) == 0x40;
01144
01145 tccrb_val = val;
01146 }
01147
01148 void HWTimer16_2C2::Reset() {
01149 HWTimer16::Reset();
01150 tccra_val = 0;
01151 tccrb_val = 0;
01152 wgm_raw = 0;
01153 }
01154
01155 HWTimer16_2C3::HWTimer16_2C3(AvrDevice *core,
01156 PrescalerMultiplexer *p,
01157 int unit,
01158 IRQLine* tov,
01159 IRQLine* tcompA,
01160 PinAtPort* outA,
01161 IRQLine* tcompB,
01162 PinAtPort* outB,
01163 IRQLine* ticap,
01164 ICaptureSource* icapsrc):
01165 HWTimer16(core, p, unit, tov, tcompA, outA, tcompB, outB, NULL, NULL, ticap, icapsrc),
01166 tccra_reg(this, "TCCRA",
01167 this, &HWTimer16_2C3::Get_TCCRA, &HWTimer16_2C3::Set_TCCRA),
01168 tccrb_reg(this, "TCCRB",
01169 this, &HWTimer16_2C3::Get_TCCRB, &HWTimer16_2C3::Set_TCCRB),
01170 tccrc_reg(this, "TCCRC",
01171 this, &HWTimer16_2C3::Get_TCCRC, &HWTimer16_2C3::Set_TCCRC) {}
01172
01173 void HWTimer16_2C3::Set_TCCRA(unsigned char val) {
01174 int temp = (int)wgm;
01175 temp &= ~0x3;
01176 temp += val & 0x3;
01177 if(wgm != (WGMtype)temp)
01178 ChangeWGM((WGMtype)temp);
01179 SetCompareOutputMode(0, (COMtype)((val >> 6) & 0x3));
01180 SetCompareOutputMode(1, (COMtype)((val >> 4) & 0x3));
01181
01182 tccra_val = val;
01183 }
01184
01185 void HWTimer16_2C3::Set_TCCRB(unsigned char val) {
01186 int temp = (int)wgm;
01187 temp &= ~0xc;
01188 temp += (val >> 1) & 0xc;
01189 if(wgm != (WGMtype)temp)
01190 ChangeWGM((WGMtype)temp);
01191 SetClockMode(val & 0x7);
01192 icapNoiseCanceler = (val & 0x80) == 0x80;
01193 icapRisingEdge = (val & 0x40) == 0x40;
01194
01195 tccrb_val = val;
01196 }
01197
01198 void HWTimer16_2C3::Set_TCCRC(unsigned char val) {
01199 if(!WGMisPWM()) {
01200 if(val & 0x80)
01201
01202 SetCompareOutput(0);
01203 if(val & 0x40)
01204
01205 SetCompareOutput(1);
01206 }
01207 }
01208
01209 void HWTimer16_2C3::Reset() {
01210 HWTimer16::Reset();
01211 tccra_val = 0;
01212 tccrb_val = 0;
01213 }
01214
01215 HWTimer16_3C::HWTimer16_3C(AvrDevice *core,
01216 PrescalerMultiplexer *p,
01217 int unit,
01218 IRQLine* tov,
01219 IRQLine* tcompA,
01220 PinAtPort* outA,
01221 IRQLine* tcompB,
01222 PinAtPort* outB,
01223 IRQLine* tcompC,
01224 PinAtPort* outC,
01225 IRQLine* ticap,
01226 ICaptureSource* icapsrc):
01227 HWTimer16(core, p, unit, tov, tcompA, outA, tcompB, outB, tcompC, outC, ticap, icapsrc),
01228 tccra_reg(this, "TCCRA",
01229 this, &HWTimer16_3C::Get_TCCRA, &HWTimer16_3C::Set_TCCRA),
01230 tccrb_reg(this, "TCCRB",
01231 this, &HWTimer16_3C::Get_TCCRB, &HWTimer16_3C::Set_TCCRB),
01232 tccrc_reg(this, "TCCRC",
01233 this, &HWTimer16_3C::Get_TCCRC, &HWTimer16_3C::Set_TCCRC) {}
01234
01235 void HWTimer16_3C::Set_TCCRA(unsigned char val) {
01236 int temp = (int)wgm;
01237 temp &= ~0x3;
01238 temp += val & 0x3;
01239 if(wgm != (WGMtype)temp)
01240 ChangeWGM((WGMtype)temp);
01241 SetCompareOutputMode(0, (COMtype)((val >> 6) & 0x3));
01242 SetCompareOutputMode(1, (COMtype)((val >> 4) & 0x3));
01243 SetCompareOutputMode(2, (COMtype)((val >> 2) & 0x3));
01244
01245 tccra_val = val;
01246 }
01247
01248 void HWTimer16_3C::Set_TCCRB(unsigned char val) {
01249 int temp = (int)wgm;
01250 temp &= ~0xc;
01251 temp += (val >> 1) & 0xc;
01252 if(wgm != (WGMtype)temp)
01253 ChangeWGM((WGMtype)temp);
01254 SetClockMode(val & 0x7);
01255 icapNoiseCanceler = (val & 0x80) == 0x80;
01256 icapRisingEdge = (val & 0x40) == 0x40;
01257
01258 tccrb_val = val;
01259 }
01260
01261 void HWTimer16_3C::Set_TCCRC(unsigned char val) {
01262 if(!WGMisPWM()) {
01263 if(val & 0x80)
01264
01265 SetCompareOutput(0);
01266 if(val & 0x40)
01267
01268 SetCompareOutput(1);
01269 if(val & 0x20)
01270
01271 SetCompareOutput(2);
01272 }
01273 }
01274
01275 void HWTimer16_3C::Reset() {
01276 HWTimer16::Reset();
01277 tccra_val = 0;
01278 tccrb_val = 0;
01279 }
01280
01281