mirror of https://github.com/jscrane/r65emu.git
refactoring peripherals (#21)
This commit is contained in:
parent
972626cffd
commit
67ff1567af
8
acia.cpp
8
acia.cpp
|
@ -4,8 +4,8 @@
|
|||
#include "serialio.h"
|
||||
#include "acia.h"
|
||||
|
||||
void acia::operator=(uint8_t b) {
|
||||
if (_acc & 1) {
|
||||
void ACIA::write(Memory::address a, uint8_t b) {
|
||||
if (a & 1) {
|
||||
_device->write(b);
|
||||
return;
|
||||
}
|
||||
|
@ -42,8 +42,8 @@ void acia::operator=(uint8_t b) {
|
|||
// FIXME: more
|
||||
}
|
||||
|
||||
acia::operator uint8_t() {
|
||||
if (_acc & 1)
|
||||
uint8_t ACIA::read(Memory::address a) {
|
||||
if (a & 1)
|
||||
return _device->read();
|
||||
|
||||
return _device->more()? rdrf | tdre: tdre;
|
||||
|
|
12
acia.h
12
acia.h
|
@ -1,12 +1,14 @@
|
|||
#ifndef __ACIA_H__
|
||||
#define __ACIA_H__
|
||||
|
||||
class acia: public Memory::Device {
|
||||
public:
|
||||
void operator= (uint8_t);
|
||||
operator uint8_t();
|
||||
// Motorola 6850 ACIA
|
||||
|
||||
acia(serialio &d): Memory::Device(256), _device(&d) {}
|
||||
class ACIA {
|
||||
public:
|
||||
void write(Memory::address, uint8_t);
|
||||
uint8_t read(Memory::address);
|
||||
|
||||
ACIA(serialio &d): _device(&d) {}
|
||||
|
||||
// status bits
|
||||
//
|
||||
|
|
|
@ -0,0 +1,179 @@
|
|||
#include <Arduino.h>
|
||||
#include <memory.h>
|
||||
#include "pia.h"
|
||||
|
||||
// see: https://github.com/mamedev/mame/blob/master/src/devices/machine/6821pia.cpp
|
||||
// and: https://github.com/mamedev/mame/blob/master/src/devices/machine/6821pia.h
|
||||
|
||||
inline bool c1_low_to_high(uint8_t cr) { return cr & 0x02; }
|
||||
|
||||
inline bool c1_high_to_low(uint8_t cr) { return !c1_low_to_high(cr); }
|
||||
|
||||
inline bool c2_output(uint8_t cr) { return cr & 0x20; }
|
||||
|
||||
inline bool c2_input(uint8_t cr) { return !c2_input(cr); }
|
||||
|
||||
inline bool c2_low_to_high(uint8_t cr) { return cr & 0x10; }
|
||||
|
||||
inline bool c2_high_to_low(uint8_t cr) { return !c2_low_to_high(cr); }
|
||||
|
||||
inline bool output_selected(uint8_t cr) { return cr & 0x04; }
|
||||
|
||||
void PIA::write(Memory::address a, uint8_t b) {
|
||||
#if defined(DEBUGGING)
|
||||
Serial.print(millis());
|
||||
Serial.print(" > ");
|
||||
Serial.print(a, 16);
|
||||
Serial.print(' ');
|
||||
Serial.println(b, 16);
|
||||
#endif
|
||||
switch(a % 4) {
|
||||
case 0:
|
||||
output_selected(cra)? write_porta(b): write_ddra(b);
|
||||
break;
|
||||
case 1:
|
||||
write_cra(b);
|
||||
break;
|
||||
case 2:
|
||||
output_selected(crb)? write_portb(b): write_ddrb(b);
|
||||
break;
|
||||
case 3:
|
||||
write_crb(b);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t PIA::read(Memory::address a) {
|
||||
#if defined(DEBUGGING)
|
||||
Serial.print(millis());
|
||||
Serial.print(" < ");
|
||||
Serial.println(a, 16);
|
||||
#endif
|
||||
switch (a % 4) {
|
||||
case 0:
|
||||
return output_selected(cra)? read_porta(): read_ddra();
|
||||
case 1:
|
||||
return read_cra();
|
||||
case 2:
|
||||
return output_selected(crb)? read_portb(): read_ddrb();
|
||||
case 3:
|
||||
return read_crb();
|
||||
}
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
void PIA::checkpoint(Stream &s) {
|
||||
s.write(crb);
|
||||
s.write(outb);
|
||||
s.write(inb);
|
||||
s.write(ddrb);
|
||||
s.write(cra);
|
||||
s.write(outa);
|
||||
s.write(ina);
|
||||
s.write(ddra);
|
||||
s.write(irq_b1);
|
||||
s.write(irq_b2);
|
||||
s.write(irq_a1);
|
||||
s.write(irq_a2);
|
||||
s.write(cb1);
|
||||
s.write(cb2);
|
||||
s.write(ca1);
|
||||
s.write(ca2);
|
||||
}
|
||||
|
||||
void PIA::restore(Stream &s) {
|
||||
crb = s.read();
|
||||
outb = s.read();
|
||||
inb = s.read();
|
||||
ddrb = s.read();
|
||||
cra = s.read();
|
||||
outa = s.read();
|
||||
ina = s.read();
|
||||
ddra = s.read();
|
||||
irq_b1 = s.read();
|
||||
irq_b2 = s.read();
|
||||
irq_a1 = s.read();
|
||||
irq_a2 = s.read();
|
||||
cb1 = s.read();
|
||||
cb2 = s.read();
|
||||
ca1 = s.read();
|
||||
ca2 = s.read();
|
||||
}
|
||||
|
||||
void PIA::write_ca1(bool state) {
|
||||
|
||||
if (ca1 == state)
|
||||
return;
|
||||
|
||||
if ((state && c1_low_to_high(cra)) || (!state && c1_high_to_low(cra)))
|
||||
irq_a1 = true;
|
||||
|
||||
ca1 = state;
|
||||
}
|
||||
|
||||
void PIA::write_ca2(bool state) {
|
||||
|
||||
if (ca2 == state || !c2_input(cra))
|
||||
return;
|
||||
|
||||
if ((state && c2_low_to_high(cra)) || (!state && c2_high_to_low(cra)))
|
||||
irq_a2 = true;
|
||||
|
||||
ca2 = state;
|
||||
}
|
||||
|
||||
void PIA::write_cb1(bool state) {
|
||||
|
||||
if (cb1 == state)
|
||||
return;
|
||||
|
||||
if ((state && c1_low_to_high(crb)) || (!state && c1_high_to_low(crb)))
|
||||
irq_b1 = true;
|
||||
|
||||
cb1 = state;
|
||||
}
|
||||
|
||||
void PIA::write_cb2(bool state) {
|
||||
|
||||
if (cb2 == state || !c2_input(crb))
|
||||
return;
|
||||
|
||||
if ((state && c2_low_to_high(crb)) || (!state && c2_high_to_low(crb)))
|
||||
irq_b2 = true;
|
||||
|
||||
cb2 = state;
|
||||
}
|
||||
|
||||
uint8_t PIA::read_cra() {
|
||||
uint8_t b = cra;
|
||||
|
||||
if (irq_a1)
|
||||
b |= IRQ1;
|
||||
|
||||
if (irq_a2 && c2_input(cra))
|
||||
b |= IRQ2;
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
uint8_t PIA::read_crb() {
|
||||
uint8_t b = crb;
|
||||
|
||||
if (irq_b1)
|
||||
b |= IRQ1;
|
||||
|
||||
if (irq_b2 && c2_input(crb))
|
||||
b |= IRQ2;
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
uint8_t PIA::read_porta() {
|
||||
irq_a1 = irq_a2 = false;
|
||||
return (ina & ~ddra) | (outa & ddra);
|
||||
}
|
||||
|
||||
uint8_t PIA::read_portb() {
|
||||
irq_b1 = irq_b2 = false;
|
||||
return (inb & ~ddrb) | (outb & ddrb);
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
#ifndef __PIA_H__
|
||||
#define __PIA_H__
|
||||
|
||||
// Motorola 6820 / 6821 PIA
|
||||
// https://en.wikipedia.org/wiki/Peripheral_Interface_Adapter
|
||||
class PIA {
|
||||
public:
|
||||
PIA(): outb(0), inb(0), crb(0), outa(0), ina(0), cra(0), ddrb(0), ddra(0),
|
||||
ca1(false), ca2(false), cb1(false), cb2(false),
|
||||
irq_a1(false), irq_a2(false), irq_b1(false), irq_b2(false) {}
|
||||
|
||||
virtual void reset() {
|
||||
outb = inb = crb = ddrb = outa = ina = cra = ddra = 0;
|
||||
irq_a1 = irq_a2 = irq_b1 = irq_b2 = ca1 = ca2 = cb1 = cb2 = false;
|
||||
}
|
||||
|
||||
// device memory interface
|
||||
void write(Memory::address, uint8_t);
|
||||
uint8_t read(Memory::address);
|
||||
|
||||
void checkpoint(Stream &);
|
||||
void restore(Stream &);
|
||||
|
||||
// device input (external) interface
|
||||
void write_porta_in(uint8_t b) { ina = b; }
|
||||
void write_ca1(bool);
|
||||
void write_ca2(bool);
|
||||
void write_portb_in(uint8_t b) { inb = b; }
|
||||
void write_cb1(bool);
|
||||
void write_cb2(bool);
|
||||
|
||||
static const uint8_t IRQ1 = 0x80;
|
||||
static const uint8_t IRQ2 = 0x40;
|
||||
|
||||
protected:
|
||||
// overrideable device memory interface
|
||||
virtual uint8_t read_ddra() { return ddra; }
|
||||
virtual uint8_t read_porta();
|
||||
virtual uint8_t read_cra();
|
||||
virtual uint8_t read_ddrb() { return ddrb; }
|
||||
virtual uint8_t read_portb();
|
||||
virtual uint8_t read_crb();
|
||||
|
||||
virtual void write_ddra(uint8_t b) { ddra = b; }
|
||||
virtual void write_porta(uint8_t b) { outa = b; }
|
||||
virtual void write_cra(uint8_t b) { cra = (b & 0x3f); }
|
||||
virtual void write_ddrb(uint8_t b) { ddrb = b; }
|
||||
virtual void write_portb(uint8_t b) { outb = b; }
|
||||
virtual void write_crb(uint8_t b) { crb = (b & 0x3f); }
|
||||
|
||||
private:
|
||||
uint8_t cra, ina, outa, ddra;
|
||||
uint8_t crb, inb, outb, ddrb;
|
||||
bool ca1, ca2, irq_a1, irq_a2;
|
||||
bool cb1, cb2, irq_b1, irq_b2;
|
||||
};
|
||||
#endif
|
Loading…
Reference in New Issue