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 "hwuart.h"
00027 #include "helper.h"
00028
00029
00030 #define RXC 0x80
00031 #define TXC 0x40
00032 #define UDRE 0x20
00033 #define FE 0x10
00034 #define OR 0x08
00035 #define DOR 0x08 //same for usart
00036 #define UPE 0x04 //only usart
00037 #define U2X 0x02 //only usart
00038 #define MPCM 0x01 //only usart
00039
00040
00041
00042 #define RXCIE 0x80
00043 #define TXCIE 0x40
00044 #define UDRIE 0x20
00045 #define RXEN 0x10
00046 #define TXEN 0x08
00047 #define CHR9 0x04 //same as ucsz2
00048 #define UCSZ2 0x04
00049 #define RXB8 0x02
00050 #define TXB8 0x01
00051
00052
00053 #define URSEL 0x80
00054 #define UMSEL 0x40
00055 #define UPM1 0x20
00056 #define UPM0 0x10
00057 #define USBS 0x08
00058 #define UCSZ1 0x04
00059 #define UCSZ0 0x02
00060 #define UCPOL 0x01
00061
00062 void HWUart::SetUdr(unsigned char val) {
00063 udrWrite=val;
00064 if ( usr&UDRE) {
00065 usr &=0xff-UDRE;
00066 if (ucr & UDRIE) {
00067 irqSystem->ClearIrqFlag(vectorUdre);
00068 }
00069 }
00070
00071 }
00072
00073 void HWUart::SetUsr(unsigned char val) {
00074 unsigned char usrold=usr;
00075
00076 if ( val & TXC) {
00077 usr &=0xff-TXC;
00078 }
00079
00080 unsigned char irqold= ucr&usrold;
00081 unsigned char irqnew= ucr&usr;
00082
00083
00084 unsigned char changed=irqold^irqnew;
00085 unsigned char setnew= changed&irqnew;
00086 unsigned char clearnew= changed& (~irqnew);
00087
00088 CheckForNewSetIrq(setnew);
00089 CheckForNewClearIrq(clearnew);
00090 }
00091
00092 void HWUart::SetUbrr(unsigned char val) {
00093 ubrr = (ubrr & 0xff00) | val;
00094 }
00095
00096 void HWUart::SetUbrrhi(unsigned char val) {
00097 ubrr = (ubrr & 0xff) | ((val & 0xf) << 8);
00098 }
00099
00100 void HWUart::SetFrameLengthFromRegister() {
00101 if ( ucr&UCSZ2) {
00102 frameLength=9;
00103 } else {
00104 switch (ucsrc & (UCSZ1|UCSZ0) ) {
00105 case 0:
00106 frameLength=5;
00107 break;
00108
00109 case UCSZ0:
00110 frameLength=6;
00111 break;
00112
00113 case UCSZ1:
00114 frameLength=7;
00115 break;
00116
00117 case UCSZ0|UCSZ1:
00118 frameLength=8;
00119 break;
00120 }
00121 }
00122
00123 frameLength--;
00124 }
00125
00126 void HWUart::SetUcr(unsigned char val) {
00127 unsigned char ucrold=ucr;
00128 ucr=val;
00129 SetFrameLengthFromRegister();
00130
00131 if (ucr & TXEN) {
00132 if (txState == TX_FIRST_RUN || txState == TX_SEND_STARTBIT) {
00133 pinTx.SetAlternatePort(1);
00134 }
00135 pinTx.SetAlternateDdr(1);
00136 pinTx.SetUseAlternatePort(1);
00137 pinTx.SetUseAlternateDdr(1);
00138 } else {
00139 pinTx.SetUseAlternateDdr(0);
00140 pinTx.SetUseAlternatePort(0);
00141 }
00142
00143 if (ucr & RXEN) {
00144 pinRx.SetUseAlternateDdr(1);
00145 pinRx.SetAlternateDdr(0);
00146 }
00147
00148
00149 #if 0
00150
00151 if ( ucr & ( RXEN|TXEN) ) {
00152 if ( !(ucrold & (RXEN|TXEN)) ) {
00153 core->AddToCycleList(this);
00154 }
00155 }
00156 #endif
00157
00158 unsigned char irqold= ucrold&usr;
00159 unsigned char irqnew= ucr&usr;
00160
00161
00162 unsigned char changed=irqold^irqnew;
00163 unsigned char setnew= changed&irqnew;
00164 unsigned char clearnew= changed& (~irqnew);
00165
00166 CheckForNewSetIrq(setnew);
00167 CheckForNewClearIrq(clearnew);
00168 }
00169
00170 unsigned int HWUart::CpuCycle() {
00171 baudCnt++;
00172 if(baudCnt >= (ubrr + 1)) {
00173 baudCnt = 0;
00174 CpuCycleRx();
00175 CpuCycleTx();
00176 }
00177
00178
00179 if(regSeq > 0)
00180 regSeq--;
00181
00182 return 0;
00183 }
00184
00185 unsigned int HWUart::CpuCycleRx() {
00186
00187
00188
00189 if ( ucr & RXEN) {
00190
00191 unsigned char usr_old=usr;
00192
00193 switch (rxState) {
00194 case RX_WAIT_FOR_HIGH:
00195 if (pinRx==1) rxState=RX_WAIT_FOR_LOWEDGE;
00196
00197 break;
00198
00199 case RX_WAIT_FOR_LOWEDGE:
00200 if (pinRx==0) rxState=RX_READ_STARTBIT;
00201 cntRxSamples=0;
00202 rxLowCnt=0;
00203 rxHighCnt=0;
00204 break;
00205
00206 case RX_READ_STARTBIT:
00207 cntRxSamples++;
00208 if (cntRxSamples>=8 && cntRxSamples<=10) {
00209 if (pinRx==0) {
00210 rxLowCnt++;
00211 } else {
00212 rxHighCnt++;
00213 }
00214 }
00215 if (cntRxSamples>15) {
00216 if ( rxLowCnt>rxHighCnt) {
00217 cntRxSamples=0;
00218 rxState= RX_READ_DATABIT;
00219 rxDataTmp=0;
00220 rxLowCnt=0;
00221 rxHighCnt=0;
00222 rxBitCnt=0;
00223 } else {
00224 rxState=RX_WAIT_FOR_HIGH;
00225 }
00226 }
00227 break;
00228
00229 case RX_READ_DATABIT:
00230 cntRxSamples++;
00231 if (cntRxSamples>=8 && cntRxSamples<=10) {
00232 if (pinRx==0) {
00233 rxLowCnt++;
00234 } else {
00235 rxHighCnt++;
00236 }
00237 }
00238
00239 if (cntRxSamples>15) {
00240 if ( rxLowCnt<rxHighCnt) {
00241 rxDataTmp|=(1<<rxBitCnt);
00242 readParity^=1;
00243 }
00244
00245 rxBitCnt++;
00246 cntRxSamples=0;
00247 rxLowCnt=0;
00248 rxHighCnt=0;
00249
00250 if (rxBitCnt>frameLength) {
00251 if (ucsrc&UPM1) {
00252 rxState=RX_READ_PARITY;
00253 } else {
00254 rxState=RX_READ_STOPBIT;
00255 }
00256 }
00257
00258 }
00259
00260 break;
00261
00262 case RX_READ_PARITY:
00263 cntRxSamples++;
00264 if (cntRxSamples>=8 && cntRxSamples<=10) {
00265 if (pinRx==0) {
00266 rxLowCnt++;
00267 } else {
00268 rxHighCnt++;
00269 }
00270 }
00271
00272 if (cntRxSamples>15) {
00273 bool actParity;
00274
00275 if ( rxLowCnt<rxHighCnt) {
00276 actParity=1;
00277 } else {
00278 actParity=0;
00279 }
00280
00281 if (ucsrc & UPM0) {
00282 actParity=!actParity;
00283 }
00284
00285 if (readParity==actParity) {
00286 usr&=0xff-UPE;
00287 } else {
00288 usr|=UPE;
00289 }
00290 }
00291 break;
00292
00293
00294
00295 case RX_READ_STOPBIT:
00296 cntRxSamples++;
00297 if (cntRxSamples>=8 && cntRxSamples<=10) {
00298 if (pinRx==0) {
00299 rxLowCnt++;
00300 } else {
00301 rxHighCnt++;
00302 }
00303 }
00304
00305 if (
00306 ((ucsrc&USBS) && (cntRxSamples>16)) ||
00307 ((!(ucsrc&USBS)) && (cntRxSamples>10))
00308 ) {
00309
00310 if ( rxLowCnt<rxHighCnt) {
00311 udrRead=rxDataTmp&0xff;
00312 usr&=0xff-FE;
00313 if ( (ucr & CHR9) !=0 ) {
00314 if ( rxDataTmp&0x100) {
00315 ucr|=RXB8;
00316 } else {
00317 ucr&=0xff-RXB8;
00318 }
00319
00320 }
00321 } else {
00322 usr|=FE;
00323 }
00324 if (ucsrc&USBS) {
00325 cntRxSamples=0;
00326 rxLowCnt=0;
00327 rxHighCnt=0;
00328 rxState= RX_READ_STOPBIT2;
00329 } else {
00330 if (usr&RXC) {
00331 usr|=OR;
00332 }
00333 usr|=RXC;
00334 if (rxLowCnt<rxHighCnt)
00335 rxState = RX_WAIT_FOR_LOWEDGE;
00336 else
00337 rxState = RX_WAIT_FOR_HIGH;
00338 }
00339 }
00340 break;
00341
00342 case RX_READ_STOPBIT2:
00343 cntRxSamples++;
00344 if (cntRxSamples>=8 && cntRxSamples<=10) {
00345 if (pinRx==0) {
00346 rxLowCnt++;
00347 } else {
00348 rxHighCnt++;
00349 }
00350 } else if (cntRxSamples>10) {
00351 if ( rxLowCnt<rxHighCnt) {
00352 usr&=0xff-FE;
00353 } else {
00354 usr|=FE;
00355 }
00356
00357 usr|=RXC;
00358 if (rxLowCnt<rxHighCnt)
00359 rxState = RX_WAIT_FOR_LOWEDGE;
00360 else
00361 rxState = RX_WAIT_FOR_HIGH;
00362 }
00363 break;
00364
00365 case RX_DISABLED:
00366 break;
00367 }
00368
00369
00370 unsigned char irqold= ucr&usr_old;
00371 unsigned char irqnew= ucr&usr;
00372
00373
00374 unsigned char changed=irqold^irqnew;
00375 unsigned char setnew= changed&irqnew;
00376 unsigned char clearnew= changed& (~irqnew);
00377
00378 CheckForNewSetIrq(setnew);
00379 CheckForNewClearIrq(clearnew);
00380
00381 }
00382 return 0;
00383 }
00384
00385 unsigned int HWUart::CpuCycleTx() {
00386
00387
00388
00389 baudCnt16++;
00390 if(baudCnt16 >= 16) {
00391 baudCnt16 = 0;
00392
00393 if (ucr & TXEN ) {
00394
00395
00396 unsigned char usr_old=usr;
00397
00398 if (!(usr & UDRE) ) {
00399 if ((usr & TXC)| (txState==TX_FIRST_RUN)|(txState==TX_FINISH)) {
00400
00401 txDataTmp=udrWrite;
00402 if (ucr & TXB8) {
00403 txDataTmp|=0x100;
00404 }
00405
00406
00407 usr|=UDRE;
00408 usr&=0xff-TXC;
00409 txState=TX_SEND_STARTBIT;
00410 }
00411 }
00412
00413 switch (txState) {
00414 case TX_SEND_STARTBIT:
00415 pinTx.SetAlternatePort(0);
00416 txState=TX_SEND_DATABIT;
00417 txBitCnt=0;
00418 break;
00419
00420 case TX_SEND_DATABIT:
00421 pinTx.SetAlternatePort((txDataTmp&(1<<txBitCnt))>>txBitCnt);
00422 writeParity^= (txDataTmp&(1<<txBitCnt))>>txBitCnt;
00423 txBitCnt++;
00424
00425 if (txBitCnt>frameLength) {
00426 if (ucsrc & (UPM0|UPM1) ) {
00427 txState=TX_SEND_PARITY;
00428 } else {
00429 txState=TX_SEND_STOPBIT;
00430 }
00431 }
00432
00433 break;
00434
00435 case TX_SEND_PARITY:
00436 if( ucsrc & UPM0) {
00437
00438 pinTx.SetAlternatePort(writeParity);
00439 } else {
00440
00441 pinTx.SetAlternatePort(!writeParity);
00442 }
00443 txState=TX_SEND_STOPBIT;
00444 break;
00445
00446
00447 case TX_SEND_STOPBIT:
00448 pinTx.SetAlternatePort(1);
00449
00450 if (ucsrc & USBS) {
00451 txState=TX_SEND_STOPBIT2;
00452 } else {
00453
00454 if (!(usr & UDRE)) {
00455
00456 txDataTmp=udrWrite;
00457 if (ucr & TXB8) {
00458 txDataTmp|=0x100;
00459 }
00460
00461 usr|=UDRE;
00462 txState=TX_SEND_STARTBIT;
00463 }
00464 else
00465 {
00466 txState=TX_AFTER_STOPBIT;
00467 }
00468 }
00469 break;
00470
00471 case TX_SEND_STOPBIT2:
00472 pinTx.SetAlternatePort(1);
00473
00474 if (!(usr & UDRE)) {
00475
00476 txDataTmp=udrWrite;
00477 if (ucr & TXB8) {
00478 txDataTmp|=0x100;
00479 }
00480
00481 usr|=UDRE;
00482 txState=TX_SEND_STARTBIT;
00483 }
00484 else
00485 {
00486 txState=TX_AFTER_STOPBIT;
00487 }
00488 break;
00489
00490 case TX_AFTER_STOPBIT:
00491 usr|=TXC;
00492 txState=TX_FINISH;
00493 break;
00494
00495
00496
00497 case TX_DISABLED:
00498 case TX_FIRST_RUN:
00499 case TX_FINISH:
00500 break;
00501
00502 }
00503
00504
00505
00506 unsigned char irqold= ucr&usr_old;
00507 unsigned char irqnew= ucr&usr;
00508
00509
00510 unsigned char changed=irqold^irqnew;
00511 unsigned char setnew= changed&irqnew;
00512 unsigned char clearnew= changed& (~irqnew);
00513
00514 CheckForNewSetIrq(setnew);
00515 CheckForNewClearIrq(clearnew);
00516
00517 }
00518 }
00519
00520
00521 return 0;
00522 }
00523
00524 HWUart::HWUart(AvrDevice *core,
00525 HWIrqSystem *s,
00526 PinAtPort tx,
00527 PinAtPort rx,
00528 unsigned int rx_interrupt,
00529 unsigned int udre_interrupt,
00530 unsigned int tx_interrupt,
00531 int instance_id):
00532 Hardware(core),
00533 TraceValueRegister(core, "UART" + int2str(instance_id)),
00534 irqSystem(s),
00535 pinTx(tx),
00536 pinRx(rx),
00537 vectorRx(rx_interrupt),
00538 vectorUdre(udre_interrupt),
00539 vectorTx(tx_interrupt),
00540 udr_reg(this, "UDR",
00541 this, &HWUart::GetUdr, &HWUart::SetUdr),
00542 usr_reg(this, "USR",
00543 this, &HWUart::GetUsr, &HWUart::SetUsr),
00544 ucr_reg(this, "UCR",
00545 this, &HWUart::GetUcr, &HWUart::SetUcr),
00546 ucsra_reg(this, "UCSRA",
00547 this, &HWUart::GetUsr, &HWUart::SetUsr),
00548 ucsrb_reg(this, "UCSRB",
00549 this, &HWUart::GetUcr, &HWUart::SetUcr),
00550 ubrr_reg(this, "UBRR",
00551 this, &HWUart::GetUbrr, &HWUart::SetUbrr),
00552 ubrrhi_reg(this, "UBRRHI",
00553 this, &HWUart::GetUbrrhi, &HWUart::SetUbrrhi)
00554 {
00555 irqSystem->DebugVerifyInterruptVector(vectorRx, this);
00556 irqSystem->DebugVerifyInterruptVector(vectorUdre, this);
00557 irqSystem->DebugVerifyInterruptVector(vectorTx, this);
00558
00559 core->AddToCycleList(this);
00560
00561 trace_direct(this, "UDR_write", &udrWrite);
00562 trace_direct(this, "UDR_read", &udrRead);
00563 trace_direct(this, "sUSR", &usr);
00564 trace_direct(this, "sUCR", &ucr);
00565 trace_direct(this, "sUBR", &ubrr);
00566
00567 Reset();
00568 }
00569
00570 unsigned char HWUart::GetUdr() {
00571 if (usr&RXC) {
00572 usr&=0xff-RXC;
00573 if (ucr & RXC) {
00574 irqSystem->ClearIrqFlag(vectorRx);
00575 }
00576 }
00577 return udrRead;
00578 }
00579
00580 unsigned char HWUart::GetUsr() { return usr; }
00581 unsigned char HWUart::GetUcr() { return ucr; }
00582 unsigned char HWUart::GetUbrr() { return ubrr&0xff; }
00583 unsigned char HWUart::GetUbrrhi() { return (ubrr&0xff00)>>8; }
00584
00585 void HWUart::ClearIrqFlag(unsigned int vector){
00586
00587 if (vector == vectorTx) {
00588 usr&=0xff-TXC;
00589 irqSystem->ClearIrqFlag( vectorTx);
00590 }
00591 }
00592
00593 void HWUart::CheckForNewSetIrq(unsigned char val) {
00594 if (val & RXC) { irqSystem->SetIrqFlag(this, vectorRx); }
00595 if (val & UDRE) { irqSystem->SetIrqFlag(this, vectorUdre); }
00596 if (val & TXC) { irqSystem->SetIrqFlag(this, vectorTx); }
00597 }
00598
00599 void HWUart::CheckForNewClearIrq(unsigned char val) {
00600 if (val & RXC) { irqSystem->ClearIrqFlag(vectorRx); }
00601 if (val & UDRE) { irqSystem->ClearIrqFlag(vectorUdre); }
00602 if (val & TXC) { irqSystem->ClearIrqFlag(vectorTx); }
00603 }
00604
00605 void HWUart::Reset() {
00606 udrWrite = 0;
00607 udrRead = 0;
00608 usr = UDRE;
00609 ucr = 0;
00610 ucsrc = UCSZ1 | UCSZ0;
00611 ubrr = 0;
00612 baudCnt = 0;
00613 baudCnt16 = 0;
00614
00615 regSeq = 0;
00616
00617 rxState = RX_WAIT_FOR_LOWEDGE;
00618 txState = TX_FIRST_RUN;
00619
00620 SetFrameLengthFromRegister();
00621 }
00622
00623
00624
00625 void HWUsart::SetUcsrc(unsigned char val) {
00626 ucsrc=val;
00627 SetFrameLengthFromRegister();
00628 }
00629
00630 void HWUsart::SetUcsrcUbrrh(unsigned char val) {
00631 if((val & URSEL) == URSEL) {
00632 SetUcsrc(val & 0x7f);
00633 } else {
00634 SetUbrrhi(val);
00635 }
00636 }
00637
00638 unsigned char HWUsart::GetUcsrc() { return ucsrc; }
00639
00640 unsigned char HWUsart::GetUcsrcUbrrh() {
00641 if(regSeq == 0) {
00642 regSeq = 2;
00643 return GetUbrrhi();
00644 } else {
00645 regSeq = 0;
00646 return GetUcsrc();
00647 }
00648 }
00649
00650 HWUsart::HWUsart(AvrDevice *core,
00651 HWIrqSystem *s,
00652 PinAtPort tx,
00653 PinAtPort rx,
00654 PinAtPort xck,
00655 unsigned int vrx,
00656 unsigned int vudre,
00657 unsigned int vtx,
00658 int instance_id,
00659 bool mxReg):
00660 HWUart(core, s, tx, rx, vrx, vudre, vtx, instance_id),
00661 pinXck(xck),
00662 ucsrc_reg(this, "UCSRC",
00663 this, &HWUsart::GetUcsrc, &HWUsart::SetUcsrc),
00664 ubrrh_reg(this, "UBRRH",
00665 this, &HWUsart::GetUbrrhi, &HWUsart::SetUbrrhi),
00666 ucsrc_ubrrh_reg(this, "UCSRC_UBRRH",
00667 this, &HWUsart::GetUcsrcUbrrh, &HWUsart::SetUcsrcUbrrh)
00668 {
00669 if(mxReg) {
00670 ucsrc_reg.releaseTraceValue();
00671 ubrrh_reg.releaseTraceValue();
00672 } else
00673 ucsrc_ubrrh_reg.releaseTraceValue();
00674
00675 Reset();
00676 }
00677
00678