📄 serialport.cpp
字号:
case LSR_TX_HOLDING_EMPTY_MASK|LSR_TX_EMPTY_MASK: // bad case there must have been one case LSR_TX_HOLDING_EMPTY_MASK: case LSR_TX_EMPTY_MASK: // holding full but workreg empty impossible LOG_MSG("Internal error in serial port(1)(0x%x).",LSR); break; case 0: // THR is empty now. LSR |= LSR_TX_HOLDING_EMPTY_MASK; // trigger interrupt rise (TX_PRIORITY); break; }}/*****************************************************************************//* ByteTransmitted: When a byte was sent, notify here. **//*****************************************************************************/void CSerial::ByteTransmitted () { switch(LSR&(LSR_TX_HOLDING_EMPTY_MASK|LSR_TX_EMPTY_MASK)) { case LSR_TX_HOLDING_EMPTY_MASK|LSR_TX_EMPTY_MASK: // bad case there must have been one case LSR_TX_EMPTY_MASK: // holding full but workreg empty impossible LOG_MSG("Internal error in serial port(2)."); break; case LSR_TX_HOLDING_EMPTY_MASK: // now both are empty LSR |= LSR_TX_EMPTY_MASK; break; case 0: // now one is empty, send the other one LSR |= LSR_TX_HOLDING_EMPTY_MASK; if (loopback) { loopback_data=THR; setEvent(SERIAL_TX_LOOPBACK_EVENT, bytetime); } else { #if SERIAL_DEBUG if(dbg_serialtraffic) fprintf(debugfp,THR<0x10? "%12.3f tx 0x%02x (%u) (from THR)\r\n": "%12.3f tx 0x%02x (%c) (from THR)\r\n", PIC_FullIndex(),THR, THR); #endif transmitByte(THR,false); } // It's ok here. rise (TX_PRIORITY); break; }}/*****************************************************************************//* Transmit Holding Register, also LSB of Divisor Latch (r/w) **//*****************************************************************************/void CSerial::Write_THR (Bit8u data) { // 0-7 transmit data if ((LCR & LCR_DIVISOR_Enable_MASK)) { // write to DLL baud_divider&=0xFF00; baud_divider |= data; changeLineProperties(); } else { // write to THR clear (TX_PRIORITY); switch(LSR&(LSR_TX_HOLDING_EMPTY_MASK|LSR_TX_EMPTY_MASK)) { case 0: // both full - overflow#if SERIAL_DEBUG if(dbg_serialtraffic) fprintf(debugfp, "%12.3f tx overflow\r\n", PIC_FullIndex());#endif // overwrite THR THR = data; break; case LSR_TX_EMPTY_MASK: // holding full but workreg empty impossible LOG_MSG("Internal error in serial port(3)."); break; case LSR_TX_HOLDING_EMPTY_MASK: // now both are full LSR &= (~LSR_TX_HOLDING_EMPTY_MASK); THR = data; break; case LSR_TX_HOLDING_EMPTY_MASK|LSR_TX_EMPTY_MASK: // both are full until the first delay has passed THR=data; LSR &= (~LSR_TX_EMPTY_MASK); LSR &= (~LSR_TX_HOLDING_EMPTY_MASK); if(loopback) setEvent(SERIAL_THR_LOOPBACK_EVENT, bytetime/10); else { #if SERIAL_DEBUG if(dbg_serialtraffic) fprintf(debugfp,data<0x10? "%12.3f tx 0x%02x (%u)\r\n": "%12.3f tx 0x%02x (%c)\r\n", PIC_FullIndex(),data, data);#endif transmitByte (data,true); } // triggered // when holding gets empty // rise (TX_PRIORITY); break; } }}/*****************************************************************************//* Receive Holding Register, also LSB of Divisor Latch (r/w) **//*****************************************************************************/Bitu CSerial::Read_RHR () { // 0-7 received data if ((LCR & LCR_DIVISOR_Enable_MASK)) return baud_divider&0xff; else { clear (RX_PRIORITY); LSR &= (~LSR_RX_DATA_READY_MASK); return RHR; }}/*****************************************************************************//* Interrupt Enable Register, also MSB of Divisor Latch (r/w) **//*****************************************************************************/// Modified by:// - writing to it.Bitu CSerial::Read_IER () { // 0 receive holding register (byte received) // 1 transmit holding register (byte sent) // 2 receive line status (overrun, parity error, frame error, break) // 3 modem status // 4-7 0 if (LCR & LCR_DIVISOR_Enable_MASK) return baud_divider>>8; else return IER;}void CSerial::Write_IER (Bit8u data) { if ((LCR & LCR_DIVISOR_Enable_MASK)) { // write to DLM baud_divider&=0xff; baud_divider |= ((Bit16u)data)<<8; changeLineProperties(); } else { IER = data&0xF; if ((LSR & LSR_TX_HOLDING_EMPTY_MASK) && (IER&TX_PRIORITY)) waiting_interrupts |= TX_PRIORITY; ComputeInterrupts(); }}/*****************************************************************************//* Interrupt Status Register (r) **//*****************************************************************************/// modified by:// - incoming interrupts// - loopback modeBitu CSerial::Read_ISR () { // 0 0:interrupt pending 1: no interrupt // 1-3 identification // 011 LSR // 010 RXRDY // 001 TXRDY // 000 MSR // 4-7 0 if(IER&Modem_Status_INT_Enable_MASK) updateMSR(); Bit8u retval = ISR; // clear changes ISR!! mean.. if(ISR==ISR_TX_VAL) clear (TX_PRIORITY); return retval;}void CSerial::Write_FCR (Bit8u data) { if((!fifo_warn) && (data&0x1)) { fifo_warn=true; LOG_MSG("Serial%d: Warning: Tried to activate FIFO.",COMNUMBER); }}/*****************************************************************************//* Line Control Register (r/w) **//*****************************************************************************/// signal decoder configuration:// - parity, stopbits, word length// - send break// - switch between RHR/THR and baud rate registers// Modified by:// - writing to it.Bitu CSerial::Read_LCR () { // 0-1 word length // 2 stop bits // 3 parity enable // 4-5 parity type // 6 set break // 7 divisor latch enable return LCR;}void CSerial::Write_LCR (Bit8u data) { Bit8u lcr_old = LCR; LCR = data; if (((data ^ lcr_old) & LCR_PORTCONFIG_MASK) != 0) { changeLineProperties(); } if (((data ^ lcr_old) & LCR_BREAK_MASK) != 0) { if(!loopback) setBreak ((LCR & LCR_BREAK_MASK)!=0); else { // TODO: set loopback break event to reveiveError after }#if SERIAL_DEBUG if(dbg_serialtraffic) fprintf(debugfp,((LCR & LCR_BREAK_MASK)!=0)? "%12.3f break on.\r\n": "%12.3f break off.\r\n", PIC_FullIndex());#endif }}/*****************************************************************************//* Modem Control Register (r/w) **//*****************************************************************************/// Set levels of RTS and DTR, as well as loopback-mode.// Modified by: // - writing to it.Bitu CSerial::Read_MCR () { // 0 -DTR // 1 -RTS // 2 -OP1 // 3 -OP2 // 4 loopback enable // 5-7 0 Bit8u retval=0; if(dtr) retval|=MCR_DTR_MASK; if(rts) retval|=MCR_RTS_MASK; if(op1) retval|=MCR_OP1_MASK; if(op2) retval|=MCR_OP2_MASK; if(loopback) retval|=MCR_LOOPBACK_Enable_MASK; return retval;}void CSerial::Write_MCR (Bit8u data) { // WARNING: At the time setRTSDTR is called rts and dsr members are still wrong. bool temp_dtr = data & MCR_DTR_MASK? true:false; bool temp_rts = data & MCR_RTS_MASK? true:false; bool temp_op1 = data & MCR_OP1_MASK? true:false; bool temp_op2 = data & MCR_OP2_MASK? true:false; bool temp_loopback = data & MCR_LOOPBACK_Enable_MASK? true:false; if(loopback!=temp_loopback) { if(temp_loopback) setRTSDTR(false,false); else setRTSDTR(temp_rts,temp_dtr); } if (temp_loopback) { // is on: // DTR->DSR // RTS->CTS // OP1->RI // OP2->CD if(temp_dtr!=dtr && !d_dsr) { d_dsr=true; rise (MSR_PRIORITY); } if(temp_rts!=rts && !d_cts) { d_cts=true; rise (MSR_PRIORITY); } if(temp_op1!=op1 && !d_ri) { // interrupt only at trailing edge if(!temp_op1) { d_ri=true; rise (MSR_PRIORITY); } } if(temp_op2!=op2 && !d_cd) { d_cd=true; rise (MSR_PRIORITY); } } else { // loopback is off if(temp_rts!=rts) { // RTS difference if(temp_dtr!=dtr) { // both difference#if SERIAL_DEBUG if(dbg_modemcontrol) { fprintf(debugfp,temp_rts?"%12.3f RTS on.\r\n": "%12.3f RTS off.\r\n", PIC_FullIndex()); fprintf(debugfp,temp_dtr?"%12.3f DTR on.\r\n": "%12.3f DTR off.\r\n", PIC_FullIndex()); }#endif setRTSDTR(temp_rts, temp_dtr); } else { // only RTS#if SERIAL_DEBUG if(dbg_modemcontrol) fprintf(debugfp,temp_rts?"%12.3f RTS on.\r\n":"%12.3f RTS off.\r\n", PIC_FullIndex());#endif setRTS(temp_rts); } } else if(temp_dtr!=dtr) { // only DTR#if SERIAL_DEBUG if(dbg_modemcontrol) fprintf(debugfp,temp_dtr?"%12.3f DTR on.\r\n":"%12.3f DTR off.\r\n", PIC_FullIndex());#endif setDTR(temp_dtr); } } dtr=temp_dtr; rts=temp_rts; op1=temp_op1; op2=temp_op2; loopback=temp_loopback;}/*****************************************************************************//* Line Status Register (r) **//*****************************************************************************/// errors, tx registers status, rx register status// modified by:// - event from real serial port// - loopbackBitu CSerial::Read_LSR () { Bitu retval = LSR; LSR &= (~LSR_ERROR_MASK); // clear error bits on read clear (ERROR_PRIORITY); return retval;}void CSerial::Write_MSR (Bit8u val) { d_cts = (val&MSR_dCTS_MASK)?true:false; d_dsr = (val&MSR_dDSR_MASK)?true:false; d_cd = (val&MSR_dCD_MASK)?true:false; d_ri = (val&MSR_dRI_MASK)?true:false;}/*****************************************************************************//* Modem Status Register (r) **//*****************************************************************************/// Contains status of the control input lines (CD, RI, DSR, CTS) and// their "deltas": if level changed since last read delta = 1.// modified by:// - real values// - write operation to MCR in loopback modeBitu CSerial::Read_MSR () { Bit8u retval=0; if (loopback) { if (rts) retval |= MSR_CTS_MASK; if (dtr) retval |= MSR_DSR_MASK; if (op1) retval |= MSR_RI_MASK; if (op2) retval |= MSR_CD_MASK; } else { updateMSR(); if (cd) retval |= MSR_CD_MASK; if (ri) retval |= MSR_RI_MASK; if (dsr) retval |= MSR_DSR_MASK; if (cts) retval |= MSR_CTS_MASK; } // new delta flags if(d_cd) retval|=MSR_dCD_MASK; if(d_ri) retval|=MSR_dRI_MASK; if(d_cts) retval|=MSR_dCTS_MASK; if(d_dsr) retval|=MSR_dDSR_MASK; d_cd = false; d_ri = false; d_cts = false; d_dsr = false; clear (MSR_PRIORITY); return retval;}/*****************************************************************************//* Scratchpad Register (r/w) **//*****************************************************************************/// Just a memory register. Not much to do here.Bitu CSerial::Read_SPR () { return SPR;}void CSerial::Write_SPR (Bit8u data) { SPR = data;}/*****************************************************************************//* Write_reserved **//*****************************************************************************/void CSerial::Write_reserved (Bit8u data, Bit8u address) { /*LOG_UART("Serial%d: Write to reserved register, value 0x%x, register %x", COMNUMBER, data, address);*/}/*****************************************************************************//* MCR Access: returns cirquit state as boolean. **/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -