Skip to content

Commit

Permalink
cdrom: delayed interrupts
Browse files Browse the repository at this point in the history
  • Loading branch information
JaCzekanski committed Oct 19, 2021
1 parent 34a0f65 commit 4d309c9
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 38 deletions.
33 changes: 20 additions & 13 deletions src/device/cdrom/cdrom.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,14 @@ void CDROM::handleSector() {
auto posInTrack = pos - disc->getTrackStart(track);

postInterrupt(1);
writeResponse(stat._reg); // stat
writeResponse(bcd::toBcd(track)); // track
writeResponse(0x01); // index
writeResponse(stat._reg); // stat
writeResponse(bcd::toBcd(track)); // track
writeResponse(0x01); // index
writeResponse(bcd::toBcd(posInTrack.mm)); // minute (disc) <<< invalid
writeResponse(bcd::toBcd(posInTrack.ss) | 0x80); // second (disc) <<< invalid
writeResponse(bcd::toBcd(posInTrack.ff)); // sector (disc)
writeResponse(bcd::toBcd(0)); // peaklo
writeResponse(bcd::toBcd(0)); // peakhi
writeResponse(bcd::toBcd(0)); // peaklo
writeResponse(bcd::toBcd(0)); // peakhi

if (verbose) {
fmt::print("CDROM:CDDA report -> ({})\n", dumpFifo(interruptQueue.peek().response));
Expand Down Expand Up @@ -135,21 +135,25 @@ void CDROM::handleSector() {
}

void CDROM::step(int cycles) {
static int intCycles = 0;

readcnt += cycles;
intCycles += cycles;
busyFor -= cycles;

if (!interruptQueue.is_empty()) {
interruptQueue.ref().delay -= cycles;

if (interruptQueue.peek().delay <= 0) {
status.transmissionBusy = 0;

if (intCycles >= 300) {
intCycles -= 300;
status.transmissionBusy = 0;
if (!interruptQueue.is_empty()) {
if ((interruptEnable & 7) & (interruptQueue.peek().irq & 7)) {
sys->interrupt->trigger(interrupt::CDROM);
}
}
}

if (busyFor < 0) {
status.transmissionBusy = 0;
}

const int sectorsPerSecond = mode.speed ? 150 : 75;
const int cyclesPerSector = timing::CPU_CLOCK / sectorsPerSecond;
for (int i = 0; i < readcnt / cyclesPerSector; i++) {
Expand Down Expand Up @@ -210,7 +214,9 @@ uint8_t CDROM::read(uint32_t address) {
if (status.index == 1 || status.index == 3) { // Interrupt flags
uint8_t _status = 0b11100000;
if (!interruptQueue.is_empty()) {
_status |= interruptQueue.peek().irq & 7;
if (interruptQueue.peek().delay <= 0) {
_status |= interruptQueue.peek().irq & 7;
}
}
if (verbose == 2) fmt::print("CDROM: R INTF: 0x{:02x}\n", _status);
return _status;
Expand Down Expand Up @@ -315,6 +321,7 @@ void CDROM::handleCommand(uint8_t cmd) {
break;
}

busyFor = 1000;
CDROM_params.clear();
status.transmissionBusy = 1;
status.xaFifoEmpty = 0;
Expand Down
29 changes: 24 additions & 5 deletions src/device/cdrom/cdrom.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class CDROM {
void setShell(bool opened) {
shellOpen = opened;

setMode(Mode::None);
setMode(Mode::None);
if (opened) {
motor = false;
}
Expand Down Expand Up @@ -100,10 +100,11 @@ class CDROM {
uint8_t irq;
fifo<uint8_t, 16> response;
bool ack;
int delay;

template <class Archive>
void serialize(Archive& ar) {
ar(irq, response, ack);
ar(irq, response, ack, delay);
}
};

Expand Down Expand Up @@ -165,7 +166,15 @@ class CDROM {
return param;
}

void postInterrupt(int irq) { interruptQueue.add(irq_response_t{.irq = (uint8_t)irq, .response = {}}); }
int busyFor = 0;

void postInterrupt(int irq, int delay = 50000) {
interruptQueue.add(irq_response_t{
.irq = (uint8_t)irq, //
.response = {}, //
.delay = delay //
});
}

std::string dumpFifo(const FIFO& f);
std::pair<int16_t, int16_t> mixSample(std::pair<int16_t, int16_t> sample);
Expand Down Expand Up @@ -193,10 +202,20 @@ class CDROM {
uint8_t read(uint32_t address);
void write(uint32_t address, uint8_t data);

void setShell(bool opened) { stat.setShell(opened); }
void setShell(bool opened) {
stat.setShell(opened);

if (opened) {
if (disc) {
postInterrupt(0x05, 1000);
writeResponse(0x16);
writeResponse(0x08);
}
}
}
bool getShell() const { return stat.getShell(); }
void ackMoreData() {
postInterrupt(1);
postInterrupt(1, 0);
writeResponse(stat._reg);
}

Expand Down
57 changes: 37 additions & 20 deletions src/device/cdrom/commands.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,25 @@ void CDROM::cmdSetloc() {
uint8_t sector = bcd::toBinary(readParam());

seekSector = sector + (second * 75) + (minute * 60 * 75);
if (verbose) fmt::print("CDROM: cmdSetloc(min = {}, sec = {}, sect = {})\n", minute, second, sector);

postInterrupt(3);
writeResponse(stat._reg);
if (!discPresent()) {
postInterrupt(5);
writeResponse(0x11);
writeResponse(0x80);
return;
}

if (verbose) fmt::print("CDROM: cmdSetloc(min = {}, sec = {}, sect = {})\n", minute, second, sector);
postInterrupt(3, 2000);
writeResponse(stat._reg);
}

void CDROM::cmdPlay() {
// Play NOT IMPLEMENTED
disc::Position pos;
if (!CDROM_params.is_empty()) {
int track = readParam(); // param or setloc used
if (track >= (int)disc->getTrackCount()) {
if (track > (int)disc->getTrackCount()) {
fmt::print("CDROM: Invalid PLAY track parameter ({})\n", track);
return;
}
Expand All @@ -50,14 +56,20 @@ void CDROM::cmdPlay() {
}

void CDROM::cmdReadN() {
readSector = seekSector;
if (verbose) fmt::print("CDROM: cmdReadN\n");

if (!discPresent()) {
postInterrupt(5);
writeResponse(0x11);
writeResponse(0x80);
return;
}

readSector = seekSector;
stat.setMode(StatusCode::Mode::Reading);

postInterrupt(3);
postInterrupt(3, 5000);
writeResponse(stat._reg);

if (verbose) fmt::print("CDROM: cmdReadN\n");
}

void CDROM::cmdMotorOn() {
Expand Down Expand Up @@ -98,7 +110,7 @@ void CDROM::cmdPause() {
}

void CDROM::cmdInit() {
postInterrupt(3);
postInterrupt(3, 0x13ce);
writeResponse(stat._reg);

stat.motor = 1;
Expand Down Expand Up @@ -142,7 +154,7 @@ void CDROM::cmdSetmode() {

mode._reg = setmode;

postInterrupt(3);
postInterrupt(3, 2000);
writeResponse(stat._reg);

if (verbose) fmt::print("CDROM: cmdSetmode(0x{:02x})\n", setmode);
Expand Down Expand Up @@ -177,9 +189,7 @@ void CDROM::cmdSeekP() {
postInterrupt(3);
writeResponse(stat._reg);

stat.setMode(StatusCode::Mode::Seeking);

postInterrupt(2);
postInterrupt(2, 500000);
writeResponse(stat._reg);

stat.setMode(StatusCode::Mode::None);
Expand Down Expand Up @@ -222,7 +232,7 @@ void CDROM::cmdGetlocL() {
}

void CDROM::cmdGetlocP() {
postInterrupt(3);
postInterrupt(3, 1000);
writeResponse(lastQ.data[0]); // track
writeResponse(lastQ.data[1]); // index
writeResponse(lastQ.data[2]); // minute (track)
Expand Down Expand Up @@ -284,17 +294,24 @@ void CDROM::cmdGetTD() {
}

void CDROM::cmdSeekL() {
if (verbose) fmt::print("CDROM: cmdSeekL\n");

readSector = seekSector;

postInterrupt(3);
writeResponse(stat._reg);
if (!discPresent()) {
postInterrupt(5);
writeResponse(0x11);
writeResponse(0x80);
return;
}

stat.setMode(StatusCode::Mode::Seeking);
postInterrupt(3, 5000);
writeResponse(stat._reg);

postInterrupt(2);
postInterrupt(2, 500000);
writeResponse(stat._reg);

if (verbose) fmt::print("CDROM: cmdSeekL\n");
stat.setMode(StatusCode::Mode::None);
}

void CDROM::cmdTest() {
Expand Down Expand Up @@ -396,7 +413,7 @@ void CDROM::cmdReadS() {
audio.clear();
stat.setMode(StatusCode::Mode::Reading);

postInterrupt(3);
postInterrupt(3, 500);
writeResponse(stat._reg);

if (verbose) fmt::print("CDROM: cmdReadS\n");
Expand Down

0 comments on commit 4d309c9

Please sign in to comment.