11static constexpr unsigned CR_CDS1 = 0x01;
12static constexpr unsigned CR_CDS2 = 0x02;
13static constexpr unsigned CR_CDS = CR_CDS1 | CR_CDS2;
14static constexpr unsigned CR_MR = CR_CDS1 | CR_CDS2;
21static constexpr unsigned CR_WS1 = 0x04;
22static constexpr unsigned CR_WS2 = 0x08;
23static constexpr unsigned CR_WS3 = 0x10;
24static constexpr unsigned CR_WS = CR_WS1 | CR_WS2 | CR_WS3;
35static constexpr unsigned CR_TC1 = 0x20;
36static constexpr unsigned CR_TC2 = 0x40;
37static constexpr unsigned CR_TC = CR_TC1 | CR_TC2;
45static constexpr unsigned CR_RIE = 0x80;
50static constexpr unsigned STAT_RDRF = 0x01;
51static constexpr unsigned STAT_TDRE = 0x02;
52static constexpr unsigned STAT_DCD = 0x04;
53static constexpr unsigned STAT_CTS = 0x08;
54static constexpr unsigned STAT_FE = 0x10;
55static constexpr unsigned STAT_OVRN = 0x20;
56static constexpr unsigned STAT_PE = 0x40;
57static constexpr unsigned STAT_IRQ = 0x80;
61 , syncRecv (motherBoard.getScheduler())
62 , syncTrans(motherBoard.getScheduler())
63 , txClock(EmuTime::zero())
64 , clockFreq(clockFreq_)
65 , rxIRQ(motherBoard, name_ +
"-rx-IRQ")
66 , txIRQ(motherBoard, name_ +
"-tx-IRQ")
67 , outConnector(motherBoard.getPluggingController(), name_ +
"-out")
69 reset(EmuTime::zero());
76 syncRecv .removeSyncPoint();
77 syncTrans.removeSyncPoint();
83 txShiftRegValid =
false;
98 byte result = statusReg;
106 statusReg &=
byte(~(STAT_RDRF | STAT_OVRN));
109 statusReg |= STAT_OVRN;
122 byte diff = value ^ controlReg;
124 if ((value & CR_CDS) == CR_MR) {
129 statusReg |= STAT_TDRE;
132 switch (value & CR_CDS) {
133 case 0: txClock.
setFreq(clockFreq, 1);
break;
134 case 1: txClock.
setFreq(clockFreq, 16);
break;
135 case 2: txClock.
setFreq(clockFreq, 64);
break;
141 if (diff & CR_WS) setDataFormat();
144 rxIRQ.
set(( value & CR_RIE) && (statusReg & STAT_RDRF));
145 txIRQ.
set(((value & CR_TC) == 0x20) && (statusReg & STAT_TDRE));
149void MC6850::setDataFormat()
153 static constexpr std::array<StopBits, 8> stopBits = {
157 outConnector.
setStopBits(stopBits[(controlReg & CR_WS) >> 2]);
160 (controlReg & (CR_WS3 | CR_WS2)) != 0x10,
161 (controlReg & CR_WS1) ?
ODD :
EVEN);
164 static constexpr std::array<byte, 8> len = {
174 charLen = len[(controlReg & CR_WS) >> 2];
179 if ((controlReg & CR_CDS) == CR_MR)
return;
182 statusReg &=
byte(~STAT_TDRE);
185 if (syncTrans.pendingSyncPoint()) {
194 syncTrans.setSyncPoint(txClock.
getTime());
200void MC6850::execTrans(EmuTime::param time)
202 assert(txClock.
getTime() == time);
203 assert((controlReg & CR_CDS) != CR_MR);
205 if (txShiftRegValid) {
206 txShiftRegValid =
false;
207 outConnector.
recvByte(txShiftReg, time);
210 if (statusReg & STAT_TDRE) {
215 statusReg |= STAT_TDRE;
216 if (((controlReg & CR_TC) == 0x20)) txIRQ.
set();
218 txShiftReg = txDataReg;
219 txShiftRegValid =
true;
222 syncTrans.setSyncPoint(txClock.
getTime());
227void MC6850::recvByte(
byte value, EmuTime::param time)
229 assert(acceptsData() && ready());
231 if (statusReg & STAT_RDRF) {
240 statusReg |= STAT_RDRF;
243 if (controlReg & CR_RIE) rxIRQ.
set();
252 syncRecv.setSyncPoint(time + txClock.
getPeriod() * charLen);
256void MC6850::execRecv(EmuTime::param time)
258 assert(acceptsData());
271bool MC6850::acceptsData()
273 return (controlReg & CR_CDS) != CR_MR;
278void MC6850::setDataBits(DataBits )
282void MC6850::setStopBits(StopBits )
286void MC6850::setParityBit(
bool , ParityBit )
294template<
typename Archive>
297 if (ar.versionAtLeast(version, 3)) {
298 ar.template serializeBase<MidiInConnector>(*
this);
299 ar.serialize(
"outConnector", outConnector,
301 "syncRecv", syncRecv,
302 "syncTrans", syncTrans,
309 "txShiftRegValid", txShiftRegValid,
310 "pendingOVRN", pendingOVRN,
312 "rxDataReg", rxDataReg,
313 "txDataReg", txDataReg,
314 "txShiftReg", txShiftReg,
315 "controlReg", controlReg,
316 "statusReg", statusReg);
317 }
else if (ar.versionAtLeast(version, 2)) {
318 ar.serialize(
"control", controlReg);
323 if constexpr (Archive::IS_LOADER) {
EmuDuration getPeriod() const
Returns the length of one clock-cycle.
void reset(EmuTime::param e)
Reset the clock to start ticking at the given time.
void advance(EmuTime::param e)
Advance this clock in time until the last tick which is not past the given time.
void setFreq(unsigned freq)
Change the frequency at which this clock ticks.
EmuTime::param getTime() const
Gets the time at which the last clock tick occurred.
void set()
Set the interrupt request on the bus.
void reset()
Reset the interrupt request on the bus.
bool getState() const
Get the interrupt state.
byte peekStatusReg() const
void reset(EmuTime::param time)
void writeControlReg(byte value, EmuTime::param time)
byte readStatusReg() const
void writeDataReg(byte value, EmuTime::param time)
MC6850(const std::string &name, MSXMotherBoard &motherBoard, unsigned clockFreq)
void serialize(Archive &ar, unsigned version)
MidiInDevice & getPluggedMidiInDev() const
virtual void signal(EmuTime::param time)=0
void setStopBits(StopBits bits) override
void setDataBits(DataBits bits) override
void recvByte(byte value, EmuTime::param time) override
void setParityBit(bool enable, ParityBit parity) override
This file implemented 3 utility functions:
uint8_t byte
8 bit unsigned integer
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)