2018-09-22 22:11:13 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <cstdint>
|
|
|
|
|
2018-09-23 12:14:10 +00:00
|
|
|
#include <Chip.h>
|
2018-09-24 07:29:11 +00:00
|
|
|
#include <Signal.h>
|
2018-09-22 22:11:13 +00:00
|
|
|
|
|
|
|
namespace EightBit {
|
2018-09-23 12:14:10 +00:00
|
|
|
class mc6850 : public Chip {
|
2018-09-22 22:11:13 +00:00
|
|
|
public:
|
|
|
|
// +--------+----------------------------------------------------------------------------------+
|
|
|
|
// | | Buffer address |
|
|
|
|
// | +------------------+------------------+--------------------+-----------------------+
|
|
|
|
// | | _ | _ | _ | _ |
|
2018-09-22 23:08:16 +00:00
|
|
|
// | Data | RS * R/W | RS * R/W | RS * R/W | RS * R/W |
|
2018-09-22 22:11:13 +00:00
|
|
|
// | Bus | (high)(low) | (high)(high) | (low)(low) | (low)(low) |
|
2018-09-22 23:08:16 +00:00
|
|
|
// | Line | Transmit | Receive | | |
|
2018-09-23 12:14:10 +00:00
|
|
|
// | Number | Data | Data | Control | Status |
|
|
|
|
// | | Register | Register | register | register |
|
2018-09-22 22:11:13 +00:00
|
|
|
// | +------------------+------------------+--------------------+-----------------------+
|
2018-09-23 12:14:10 +00:00
|
|
|
// | | (Write only) + (Read only) + (Write only) | (Read only) |
|
2018-09-22 22:11:13 +00:00
|
|
|
// +--------+------------------+------------------+--------------------+-----------------------+
|
|
|
|
// | 0 | Data bit 0* | Data bit 0 | Counter divide | Receive data register |
|
|
|
|
// | | | | select 1 (CR0) | full (RDRF) |
|
|
|
|
// +--------+------------------+------------------+--------------------+-----------------------+
|
|
|
|
// | 1 | Data bit 1 | Data bit 1 | Counter divide | Transmit data register|
|
|
|
|
// | | | | select 2 (CR1) | empty (TDRE) |
|
|
|
|
// +--------+------------------+------------------+--------------------+-----------------------+
|
|
|
|
// | 2 | Data bit 2 | Data bit 2 | Word select 1 | Data carrier detect |
|
|
|
|
// | | | | (CR2) | (DCD active) |
|
|
|
|
// +--------+------------------+------------------+--------------------+-----------------------+
|
|
|
|
// | 3 | Data bit 3 | Data bit 3 | Word select 1 | Clear to send |
|
|
|
|
// | | | | (CR3) | (CTS active) |
|
|
|
|
// +--------+------------------+------------------+--------------------+-----------------------+
|
|
|
|
// | 4 | Data bit 4 | Data bit 4 | Word select 1 | Framing error |
|
|
|
|
// | | | | (CR4) | (FE) |
|
|
|
|
// +--------+------------------+------------------+--------------------+-----------------------+
|
|
|
|
// | 5 | Data bit 5 | Data bit 5 | Transmit control 1 | Receiver overrun |
|
|
|
|
// | | | | (CR5) | (OVRN) |
|
|
|
|
// +--------+------------------+------------------+--------------------+-----------------------+
|
|
|
|
// | 6 | Data bit 6 | Data bit 6 | Transmit control 2 | Parity error (PE) |
|
2018-09-22 23:08:16 +00:00
|
|
|
// | | | | (CR6) | |
|
2018-09-22 22:11:13 +00:00
|
|
|
// +--------+------------------+------------------+--------------------+-----------------------+
|
|
|
|
// | 7 | Data bit 7*** | Data bit 7** | Receive interrupt | Interrupt request |
|
|
|
|
// | | | | enable (CR7) | (IRQ active) |
|
|
|
|
// +--------+------------------+------------------+--------------------+-----------------------+
|
|
|
|
// * Leading bit = LSB = Bit 0
|
|
|
|
// ** Data bit will be zero in 7-bit plus parity modes
|
|
|
|
// *** Data bit is "don't case" in 7-bit plus parity modes
|
|
|
|
|
2018-09-23 12:14:10 +00:00
|
|
|
enum ControlRegisters {
|
|
|
|
CR0 = 0b1,
|
|
|
|
CR1 = 0b10,
|
|
|
|
CR2 = 0b100,
|
|
|
|
CR3 = 0b1000,
|
|
|
|
CR4 = 0b10000,
|
|
|
|
CR5 = 0b100000,
|
|
|
|
CR6 = 0b1000000,
|
|
|
|
CR7 = 0b10000000
|
|
|
|
};
|
|
|
|
|
|
|
|
enum StatusRegisters {
|
2018-09-25 22:55:14 +00:00
|
|
|
STATUS_RDRF = 0b1,
|
|
|
|
STATUS_TDRE = 0b10,
|
|
|
|
STATUS_DCD = 0b100,
|
|
|
|
STATUS_CTS = 0b1000,
|
|
|
|
STATUS_FE = 0b10000,
|
|
|
|
STATUS_OVRN = 0b100000,
|
|
|
|
STATUS_PE = 0b1000000,
|
|
|
|
STATUS_IRQ = 0b10000000,
|
2018-09-23 12:14:10 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
PinLevel& RXDATA() { return m_RXDATA; } // Receive data, (I) Active high
|
|
|
|
PinLevel& TXDATA() { return m_TXDATA; } // Transmit data, (O) Active high
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
PinLevel& RXCLK() { return m_RXCLK; } // Transmit clock, (I) Active high
|
|
|
|
PinLevel& TXCLK() { return m_TXCLK; } // Receive clock, (I) Active high
|
|
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
PinLevel& RS() { return m_RS; } // Register select, (I) Active high
|
|
|
|
PinLevel& RW() { return m_RW; } // Read/Write, (I) Read high, write low
|
|
|
|
|
|
|
|
PinLevel& E() { return m_E; } // ACIA Enable, (I) Active high
|
|
|
|
PinLevel& IRQ() { return m_IRQ; } // Interrupt request, (O) Active low
|
|
|
|
|
|
|
|
uint8_t& DATA() { return m_data; } // Data, (I/O)
|
|
|
|
|
2018-09-25 22:55:14 +00:00
|
|
|
// 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;
|
|
|
|
|
2018-09-23 12:14:10 +00:00
|
|
|
void step(int cycles);
|
2018-09-22 22:11:13 +00:00
|
|
|
|
2018-09-25 22:55:14 +00:00
|
|
|
void markTransmitComplete();
|
|
|
|
void markReceiveStarting();
|
2018-09-24 07:29:11 +00:00
|
|
|
|
|
|
|
Signal<EventArgs> Accessing;
|
|
|
|
Signal<EventArgs> Accessed;
|
|
|
|
|
|
|
|
Signal<EventArgs> Transmitting;
|
|
|
|
Signal<EventArgs> Transmitted;
|
|
|
|
|
|
|
|
Signal<EventArgs> Receiving;
|
|
|
|
Signal<EventArgs> Received;
|
2018-09-23 19:31:55 +00:00
|
|
|
|
2018-09-23 12:14:10 +00:00
|
|
|
private:
|
2018-09-23 19:31:55 +00:00
|
|
|
uint8_t& status() { return m_status; }
|
|
|
|
|
2018-09-23 12:14:10 +00:00
|
|
|
bool selected();
|
2018-09-22 22:11:13 +00:00
|
|
|
|
2018-09-23 12:14:10 +00:00
|
|
|
void reset();
|
2018-09-22 22:11:13 +00:00
|
|
|
|
2018-09-23 12:14:10 +00:00
|
|
|
void step();
|
2018-09-22 22:11:13 +00:00
|
|
|
|
2018-09-25 22:55:14 +00:00
|
|
|
void startTransmit();
|
|
|
|
void markTransmitStarting();
|
|
|
|
|
|
|
|
void completeReceive();
|
|
|
|
void markReceiveComplete();
|
2018-09-23 19:31:55 +00:00
|
|
|
|
2018-09-23 12:14:10 +00:00
|
|
|
PinLevel m_RXDATA;
|
|
|
|
PinLevel m_TXDATA;
|
2018-09-22 22:11:13 +00:00
|
|
|
|
2018-09-23 12:14:10 +00:00
|
|
|
PinLevel m_RTS;
|
|
|
|
PinLevel m_CTS;
|
|
|
|
PinLevel m_DCD;
|
2018-09-22 22:11:13 +00:00
|
|
|
|
2018-09-23 12:14:10 +00:00
|
|
|
PinLevel m_RXCLK;
|
|
|
|
PinLevel m_TXCLK;
|
2018-09-22 22:11:13 +00:00
|
|
|
|
2018-09-23 12:14:10 +00:00
|
|
|
PinLevel m_CS0;
|
|
|
|
PinLevel m_CS1;
|
|
|
|
PinLevel m_CS2;
|
2018-09-22 22:11:13 +00:00
|
|
|
|
2018-09-23 12:14:10 +00:00
|
|
|
PinLevel m_RS;
|
|
|
|
PinLevel m_RW;
|
2018-09-22 22:11:13 +00:00
|
|
|
|
2018-09-23 12:14:10 +00:00
|
|
|
PinLevel m_E;
|
|
|
|
PinLevel m_IRQ;
|
2018-09-22 22:11:13 +00:00
|
|
|
|
|
|
|
uint8_t m_data;
|
|
|
|
|
2018-09-23 12:14:10 +00:00
|
|
|
// Control registers
|
|
|
|
int m_counterDivide;
|
|
|
|
int m_wordConfiguration;
|
2018-09-25 22:55:14 +00:00
|
|
|
int m_transmitControl;
|
2018-09-23 12:14:10 +00:00
|
|
|
int m_receiveControl;
|
2018-09-22 22:11:13 +00:00
|
|
|
|
2018-09-23 12:14:10 +00:00
|
|
|
// Status registers
|
2018-09-23 19:31:55 +00:00
|
|
|
uint8_t m_status;
|
|
|
|
|
|
|
|
// Data registers
|
|
|
|
uint8_t m_TDR;
|
|
|
|
uint8_t m_RDR;
|
|
|
|
|
2018-09-24 07:29:11 +00:00
|
|
|
bool m_powered = false;
|
2018-09-22 22:11:13 +00:00
|
|
|
};
|
|
|
|
}
|