From 042e066a0ccc4c8d6d66d1a8aaecc6cefec6c456 Mon Sep 17 00:00:00 2001 From: Adrian Conlon Date: Sun, 30 Sep 2018 23:07:07 +0100 Subject: [PATCH] Correct status handling in the MC6850, and improve documentation. Signed-off-by: Adrian Conlon --- MC6850/inc/MC6850.h | 173 ++++++++++++++++++++++++++++++++++-------- MC6850/src/MC6850.cpp | Bin 4614 -> 6068 bytes 2 files changed, 143 insertions(+), 30 deletions(-) diff --git a/MC6850/inc/MC6850.h b/MC6850/inc/MC6850.h index 6762a91..495e4c5 100644 --- a/MC6850/inc/MC6850.h +++ b/MC6850/inc/MC6850.h @@ -93,51 +93,164 @@ namespace EightBit { ReceiveInterruptEnable = 0b1, // Triggers on: RDR full, overrun, DCD low -> high }; + // STATUS REGISTER Information on the status of the ACIA is + // available to the MPU by reading the ACIA Status Register. + // This read-only register is selected when RS is low and R/W is high. + // Information stored in this register indicates the status of the + // Transmit Data Register, the Receive Data Register and error logic, + // and the peripheral/modem status inputs of the ACIA enum StatusRegisters { - STATUS_RDRF = 0b1, - STATUS_TDRE = 0b10, - STATUS_DCD = 0b100, - STATUS_CTS = 0b1000, - STATUS_FE = 0b10000, - STATUS_OVRN = 0b100000, - STATUS_PE = 0b1000000, - STATUS_IRQ = 0b10000000, + + // Receive Data Register Full (RDRF), Bit 0 - Receive Data + // Register Full indicates that received data has been + // transferred to the Receive Data Register. RDRF is cleared + // after an MPU read of the Receive Data Register or by a + // master reset. The cleared or empty state indicates that the + // contents of the Receive Data Register are not current. + // Data Carrier Detect being high also causes RDRF to indicate + // empty. + STATUS_RDRF = 0b1, + + // Transmit Data Register Empty (TDRE), Bit 1 - The Transmit + // Data Register Empty bit being set high indicates that the + // Transmit Data Register contents have been transferred and + // that new data may be entered. The low state indicates that + // the register is full and that transmission of a new + // character has not begun since the last write data command. + STATUS_TDRE = 0b10, + + // ___ + // Data Carrier Detect (DCD), Bit 2 - The Data Carrier Detect + // bit will be high when the DCD (low) input from a modem has gone + // high to indicate that a carrier is not present. This bit + // going high causes an Interrupt Request to be generated when + // the Receive Interrupt Enable is set. It remains high after + // the DCD (low) input is returned low until cleared by first reading + // the Status Register and then the Data Register or until a + // master reset occurs. If the DCD (low) input remains high after + // read status and read data or master reset has occurred, the + // interrupt is cleared, the DCD (low) status bit remains high and + // will follow the DCD (low) input. + STATUS_DCD = 0b100, + + // ___ + // Clear-to-Send (CTS), Bit 3 - The Clear-to-Send bit indicates + // the state of the Clear-to-Send input from a modem. A low CTS (low) + // indicates that there is a Clear-to-Send from the modem. In + // the high state, the Transmit Data Register Empty bit is + // inhibited and the Clear-to-Send status bit will be high. + // Master reset does not affect the Clear-to-Send status bit. + STATUS_CTS = 0b1000, + + // Framing Error (FE), Bit 4 - Framing error indicates that the + // received character is improperly framed by a start and a + // stop bit and is detected by the absence of the first stop + // bit. This error indicates a synchronization error, faulty + // transmission, or a break condition. The framing error flag + // is set or reset during the receive data transfer time. + // Therefore, this error indicator is present throughout the + // time that the associated character is available. + STATUS_FE = 0b10000, + + // Receiver Overrun (OVRN), Bit 5- Overrun is an error flag + // that indicates that one or more characters in the data + // stream were lost. That is, a character or a number of + // characters were received but not read from the Receive + // Data Register (RDR) prior to subsequent characters being + // received. The overrun condition begins at the midpoint of + // the last bit of the second character received in succession + // without a read of the RDR having occurred. The Overrun does + // not occur in the Status Register until the valid character + // prior to Overrun has been read. The RDRF bit remains set + // until the Overrun is reset. Character synchronization is + // maintained during the Overrun condition. The Overrun + // indication is reset after the reading of data from the + // Receive Data Register or by a Master Reset. + STATUS_OVRN = 0b100000, + + // Parity Error (PE), Bit 6 - The parity error flag indicates + // that the number of highs {ones) in the character does not + // agree with the preselected odd or even parity. Odd parity + // is defined to be when the total number of ones is odd. The + // parity error indication will be present as long as the data + // character is in the RDR. If no parity is selected, then both + // the transmitter parity generator output and the receiver + // parity check results are inhibited + STATUS_PE = 0b1000000, + + // ___ + // Interrupt Request (IRQ), Bit 7- The IRQ (low) bit indicates the + // state of the IRQ (low) output. Any interrupt condition with its + // applicable enable will be indicated in this status bit. + // Anytime the IRQ (low) output is low the IRQ bit will be high to + // indicate the interrupt or service request status. IRQ (low) is + // cleared by a read operation to the Receive Data Register or + // a write operation to the Transmit Data Register. + STATUS_IRQ = 0b10000000, }; - PinLevel& RXDATA() { return m_RXDATA; } // Receive data, (I) Active high - PinLevel& TXDATA() { return m_TXDATA; } // Transmit data, (O) Active high + // Receive data, (I) Active high + PinLevel& RXDATA() { return m_RXDATA; } - PinLevel& RTS() { return m_RTS; } // Request to send, (O) Active low - PinLevel& CTS() { return m_CTS; } // Clear to send, (I) Active low - PinLevel& DCD() { return m_DCD; } // Data carrier detect, (I) Active low + // Transmit data, (O) Active high + PinLevel& TXDATA() { return m_TXDATA; } - PinLevel& RXCLK() { return m_RXCLK; } // Transmit clock, (I) Active high - PinLevel& TXCLK() { return m_TXCLK; } // Receive clock, (I) Active high + // Request to send, (O) Active low + PinLevel& RTS() { return m_RTS; } + // Clear to send, (I) Active low + PinLevel& CTS() { return m_CTS; } - PinLevel& CS0() { return m_CS0; } // Chip select, bit 0, (I) Active high - PinLevel& CS1() { return m_CS1; } // Chip select, bit 1, (I) Active high - PinLevel& CS2() { return m_CS2; } // Chip select, bit 2, (I) Active low + // Data carrier detect, (I) Active low + PinLevel& DCD() { return m_DCD; } - PinLevel& RS() { return m_RS; } // Register select, (I) Active high - PinLevel& RW() { return m_RW; } // Read/Write, (I) Read high, write low + // Transmit clock, (I) Active high + PinLevel& RXCLK() { return m_RXCLK; } - PinLevel& E() { return m_E; } // ACIA Enable, (I) Active high - PinLevel& IRQ() { return m_IRQ; } // Interrupt request, (O) Active low + // Receive clock, (I) Active high + PinLevel& TXCLK() { return m_TXCLK; } - uint8_t& DATA() { return m_data; } // Data, (I/O) + // Chip select, bit 0, (I) Active high + PinLevel& CS0() { return m_CS0; } + + // Chip select, bit 1, (I) Active high + PinLevel& CS1() { return m_CS1; } + + // Chip select, bit 2, (I) Active low + PinLevel& CS2() { return m_CS2; } + + // Register select, (I) Active high + PinLevel& RS() { return m_RS; } + + // Read/Write, (I) Read high, write low + PinLevel& RW() { return m_RW; } + + // ACIA Enable, (I) Active high + PinLevel& E() { return m_E; } + + // Interrupt request, (O) Active low + PinLevel& IRQ() { return m_IRQ; } + + // Data, (I/O) + uint8_t& DATA() { return m_data; } // Expose these internal registers, so we can update internal state - uint8_t& TDR() { return m_TDR; } // Transmit data register; - uint8_t& RDR() { return m_RDR; } // Receive data register; - void step(int cycles); + // Transmit data register; + uint8_t& TDR() { return m_TDR; } + + // Receive data register; + uint8_t& RDR() { return m_RDR; } + + bool access(); bool selected(); void markTransmitComplete(); void markReceiveStarting(); + std::string dumpStatus(); + Signal Accessing; Signal Accessed; @@ -148,12 +261,10 @@ namespace EightBit { Signal Received; private: - uint8_t& status() { return m_status; } + uint8_t status(); void reset(); - void step(); - void startTransmit(); void markTransmitStarting(); @@ -189,7 +300,9 @@ namespace EightBit { ReceiveControl m_receiveControl; // Status registers - uint8_t m_status; + bool m_statusRDRF = false; + bool m_statusTDRE = true; + bool m_statusOVRN = false; // Data registers uint8_t m_TDR; diff --git a/MC6850/src/MC6850.cpp b/MC6850/src/MC6850.cpp index 5afe40db88468d8c3fd75ce1bf563d182d4c1cdb..827a7fda4e1245927eed3f71ddde39e22810b1d0 100644 GIT binary patch literal 6068 zcmc&&ZEqVz5T36_>VLQx39jO;4Wv{Qih|Qfd}s@ffsd6*>=5CY%04GlrGFjzJUgDu z?)onFIhN4r67SvY%roz^_us!C%7skjR3@^JGZ{%CU3rc5AM!cwuH2Ikq>kpf^yHB| zmIHYZQPxv`3w}eH;~L3KDtQ{XlJ}?Bv$eRepT`fu1oAQ8C-M!1otW4 zkASw6``Gz5aO;5c2+tSzKgH7-BwmCar0dBEaFU)oKEhQ;@i3#90NXXVlCyEyU(!4Y zQs3QZas}E8P;I6OIZ~S{aC03lWDE|a>_PWe@Ix#=)|J|tex>{Xz*A$wv88WXo6BA0XUV06|fgKc!eK zB7G-wf%TIaMxUk@jdy!*=^*>OU$9Jk@-0>;^6WKIQZZ#Fe~Z`WG! zcG-(^Zn5t)-XGlfPqX_N_8FpnmWiJ~1(K6ciw5!we!YVAbcW!Yd|t439vkg=+q_Z7 z+um)IUdd}g=! z9(VU9!}+^_4f+4G@OK@eb+SB%O_n{`y)4aZ*GkvBm!moEa&*0WIa&kEZd~nNhSvj= zV^4N3OY4To;cE9Xw2HWIbR9?a`uypl^43$alXyMyjP)wi?#sbt=m~$W%r{zxIQi%a zC#^+!5B7}W%$A=)J1g9c>$daFuC?X79Zzd*v`uHLI$iHF$=y}cKBC1Z`F39QJfv51 zpWEE^1ShXAa25D&#P1muzPhm+>H7jFGM@R0(5D!?Jk`I!dW^0$!NpF@Jv^mT3Mts< zxN{^Qhj`asJzvIR0S@eu!{yxBgiJeP?w{Bq8r%O@6vjyOB(`}BZsr@cK%9@}t3%kB zUKq*W!Sa@oZrcJm!4u*P7r!wSOAk%){5p7w-&!l2QS{W4YP0>>W!s3?$*1Y8=HCjm rR%wPauH!SO%^Gd0Vm<}7tH0~diH-2gd5YKNpn*QPB77tJ>ZWtk-4=Wmjp<^hf_*d` zh0Y8G5ly^mM1epRNBAqDQjNV7)GAH|U8U<)>?_#k=;~mZJI#=rW3KtW+pkeOKgywA z?bx9M+NC7l%Zt4pKYQ$)bJ@9U3$}i(x5NDH+u)C}C2mOOVohmUKE(+977PsY==kR# k<}AZjrHcgE?|m6Sy?iLS1{hDi_J7nppiQf-pNaO+A48ym?f?J)