X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fv6821.cpp;fp=src%2Fv6821.cpp;h=0476beead78bb1d6251ea5371b66b0fb5c95c6e4;hb=8dafbf94c7bc84dae635f9dabfc9be5424e49e68;hp=0000000000000000000000000000000000000000;hpb=e3ad811139308bfe8a818cf5e42e7553785fea82;p=stargem2 diff --git a/src/v6821.cpp b/src/v6821.cpp new file mode 100644 index 0000000..0476bee --- /dev/null +++ b/src/v6821.cpp @@ -0,0 +1,165 @@ +// +// Virtual 6821 Peripheral Interface Adapter (PIA) Emulator v1.0 +// +// by James Hammons +// (C) 2022 Underground Software +// +// JLH = James Hammons +// +// WHO WHEN WHAT +// --- ---------- ------------------------------------------------------------ +// JLH 12/27/2022 Created this file. :-) + +#include "v6821.h" + +//#include "log.h" +//#include "v6809.h" + +// A "1" bit in the DDR means that line is an output + +V6821PIA::V6821PIA(): ddra(0), ddrb(0), pa(0), pb(0), cra(0), crb(0), ora(0), orb(0), ca1(false), ca2(false), cb1(false), cb2(false), irqa1(false), irqa2(false), irqb1(false), irqb2(false), irqaState(false), irqbState(false), IRQA(NULL), IRQB(NULL) +{ +} + +V6821PIA::V6821PIA(void (* a)(bool), void (*b)(bool)): ddra(0), ddrb(0), pa(0), pb(0), cra(0), crb(0), ora(0), orb(0), ca1(false), ca2(false), cb1(false), cb2(false), irqa1(false), irqa2(false), irqb1(false), irqb2(false), irqaState(false), irqbState(false), IRQA(a), IRQB(b) +{ +} + +void V6821PIA::Reset(void) +{ +} + +uint8_t V6821PIA::Read(uint8_t addr) +{ + switch (addr & 0x03) + { + case 0: + if (cra & 0x04) + { + // IRQ flags are implicitly cleared by a read + irqa1 = irqa2 = false; + HandleIRQs(); + + return pa & ~ddra; + } + + return ddra; + + case 1: + return cra | (irqa1 ? 0x80 : 0x00) | (irqa2 ? 0x40 : 0x00); + + case 2: + if (crb & 0x04) + { + // IRQ flags are implicitly cleared by a read + irqb1 = irqb2 = false; + HandleIRQs(); + + return pb & ~ddrb; + } + + return ddrb; + + case 3: + return crb | (irqb1 ? 0x80 : 0x00) | (irqb2 ? 0x40 : 0x00); + } + + // This is only here to silence the the compiler... :-/ + return 0xFF; +} + +void V6821PIA::Write(uint8_t addr, uint8_t data) +{ + switch (addr & 0x03) + { + case 0: + if (cra & 0x04) + pa = data; + else + ddra = data; + + break; + + case 1: + cra = data & 0x3F; // Bits 6-7 are RO + HandleIRQs(); + break; + + case 2: + if (crb & 0x04) + pb = data; + else + ddrb = data; + + break; + + case 3: + crb = data & 0x3F; // Bits 6-7 are RO + HandleIRQs(); + } +} + +void V6821PIA::CA1(bool state) +{ + // Do nothing if nothing changed... + if (ca1 == state) + return; + + // Check if there's been a transition (bit 1 = lo to hi transition) + if ((state && (cra & 0x02)) || (!state && !(cra & 0x02))) + { + irqa1 = true; + HandleIRQs(); + } + + ca1 = state; +} + +void V6821PIA::CA2(bool state) +{ + ca2 = state; +} + +void V6821PIA::CB1(bool state) +{ + // Do nothing if nothing changed... + if (cb1 == state) + return; + + // Check if there's been a transition (bit 1 = lo to hi transition) + if ((state && (crb & 0x02)) || (!state && !(crb & 0x02))) + { + irqb1 = true; + HandleIRQs(); + } + + cb1 = state; +} + +void V6821PIA::CB2(bool state) +{ + cb2 = state; +} + +void V6821PIA::HandleIRQs(void) +{ + bool newState = (irqa1 && (cra & 0x01)) || (irqa2 && (cra & 0x08)); + + if (newState != irqaState) + { + irqaState = newState; + + if (IRQA) + IRQA(irqaState); + } + + newState = (irqb1 && (crb & 0x01)) || (irqb2 && (crb & 0x08)); + + if (newState != irqbState) + { + irqbState = newState; + + if (IRQB) + IRQB(irqbState); + } +}