|
|
@@ -486,9 +486,251 @@ describe("MOSCIA Tests...", function(){ |
|
|
|
cia.RS = 0x01; |
|
|
|
expect(cia.DATA & 0x40).to.be.equal(0x00); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
it("Timer B, phi2 Triggered, Interrupt Verification", function(){ |
|
|
|
let cia = new MOSCIA(); |
|
|
|
let tick = (cycles) => { |
|
|
|
for (let i=0; i < cycles; i++) |
|
|
|
cia.phi2 = 1; |
|
|
|
}; |
|
|
|
|
|
|
|
cia.RS = 0x06; |
|
|
|
cia.DATA = 0xFF; |
|
|
|
cia.RS = 0x07; |
|
|
|
cia.DATA = 0x01; |
|
|
|
|
|
|
|
cia.RS = 0x0F; |
|
|
|
// Force latch load into Timer B and activate Timer B |
|
|
|
cia.DATA = cia.DATA | 0x11; |
|
|
|
|
|
|
|
cia.RS = 0x06; |
|
|
|
expect(cia.DATA).to.be.equal(0xFF); |
|
|
|
tick(1); |
|
|
|
expect(cia.DATA).to.be.equal(0xFE); |
|
|
|
tick(1); |
|
|
|
expect(cia.DATA).to.be.equal(0xFD); |
|
|
|
tick(0x0200 - 3); |
|
|
|
expect(cia.DATA).to.be.equal(0x00); |
|
|
|
cia.RS = 0x07; |
|
|
|
expect(cia.DATA).to.be.equal(0x00); |
|
|
|
tick(1); |
|
|
|
expect(cia.DATA).to.be.equal(0x01); |
|
|
|
cia.RS = 0x06; |
|
|
|
expect(cia.DATA).to.be.equal(0xFF); |
|
|
|
|
|
|
|
cia.RS = 0x0D; |
|
|
|
let IC = cia.DATA; |
|
|
|
expect(IC & 0x02).to.be.equal(0x02); |
|
|
|
expect(IC & 0x80).to.be.equal(0x80); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
it("Timer B, CNT Triggered, Underflow report to Port B", function(){ |
|
|
|
let cia = new MOSCIA(); |
|
|
|
let tick = (cycles, cnt) => { |
|
|
|
cnt = (cnt === true); |
|
|
|
for (let i=0; i < cycles; i++){ |
|
|
|
if (cnt) |
|
|
|
cia.CNT = 1; |
|
|
|
cia.phi2 = 1; |
|
|
|
if (cnt) |
|
|
|
cia.CNT = 0; |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
cia.RS = 0x06; |
|
|
|
cia.DATA = 0x08; |
|
|
|
cia.RS = 0x07; |
|
|
|
cia.DATA = 0x00; |
|
|
|
|
|
|
|
cia.RS = 0x0F; |
|
|
|
// Force latch load into Timer B, |
|
|
|
// enable underflow reporting on Port B bit 7, |
|
|
|
// set Timer B to trigger on CNT, |
|
|
|
// and activate Timer B |
|
|
|
cia.DATA = 0x33; |
|
|
|
|
|
|
|
cia.RS = 0x06; |
|
|
|
// First, test a few ticks where CNT is not high. |
|
|
|
expect(cia.DATA).to.be.equal(0x08); // Validate inital timer value. |
|
|
|
tick(1); |
|
|
|
tick(1); |
|
|
|
tick(1); |
|
|
|
tick(1); |
|
|
|
expect(cia.DATA).to.be.equal(0x08); |
|
|
|
|
|
|
|
// Now verify CNT triggers! |
|
|
|
tick(1, true); |
|
|
|
expect(cia.DATA).to.be.equal(0x07); |
|
|
|
tick(1, true); |
|
|
|
expect(cia.DATA).to.be.equal(0x06); |
|
|
|
tick(1, true); |
|
|
|
tick(1, true); |
|
|
|
tick(1, true); |
|
|
|
tick(1, true); |
|
|
|
tick(1, true); |
|
|
|
tick(1, true); |
|
|
|
expect(cia.DATA).to.be.equal(0x00); |
|
|
|
tick(1, true); |
|
|
|
|
|
|
|
// Double check that timer has reset to latch value... |
|
|
|
expect(cia.DATA).to.be.equal(0x08); |
|
|
|
|
|
|
|
// Verify Interrupt (again... but it doesn't hurt!) |
|
|
|
cia.RS = 0x0D; |
|
|
|
let IC = cia.DATA; |
|
|
|
expect(IC & 0x02).to.be.equal(0x02); |
|
|
|
expect(IC & 0x80).to.be.equal(0x80); |
|
|
|
|
|
|
|
// Checking Port B bit 7 which should only go high for 1 cycle! |
|
|
|
cia.RS = 0x01; |
|
|
|
expect(cia.DATA & 0x80).to.be.equal(0x80); |
|
|
|
tick(1, true); |
|
|
|
expect(cia.DATA & 0x80).to.be.equal(0x00); |
|
|
|
|
|
|
|
// Check Port B bit 7 toggling... |
|
|
|
// ------------------------------------------- |
|
|
|
// Force latch load into Timer B, |
|
|
|
// enable underflow reporting on Port B bit 7, |
|
|
|
// setup Port B bit 7 to invert, |
|
|
|
// set Timer B to trigger on CNT, |
|
|
|
// and activate Timer B |
|
|
|
cia.RS = 0x0F; |
|
|
|
cia.DATA = 0x37; |
|
|
|
|
|
|
|
for (let i=0; i < 9; i++) |
|
|
|
tick(1, true); |
|
|
|
cia.RS = 0x06; |
|
|
|
expect(cia.DATA).to.be.equal(0x08); |
|
|
|
|
|
|
|
cia.RS = 0x01; |
|
|
|
expect(cia.DATA & 0x80).to.be.equal(0x80); |
|
|
|
tick(1, true); |
|
|
|
expect(cia.DATA & 0x80).to.be.equal(0x80); |
|
|
|
cia.RS = 0x06; |
|
|
|
expect(cia.DATA).to.be.equal(0x07); |
|
|
|
|
|
|
|
for (let i=0; i < 8; i++) |
|
|
|
tick(1, true); |
|
|
|
expect(cia.DATA).to.be.equal(0x08); |
|
|
|
cia.RS = 0x01; |
|
|
|
expect(cia.DATA & 0x80).to.be.equal(0x00); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
it("Timer B tick on Timer A Underflow (phi2 Triggered)", function(){ |
|
|
|
let cia = new MOSCIA(); |
|
|
|
let tick = (cycle) => { |
|
|
|
for (let i=0; i < cycle; i++) |
|
|
|
cia.phi2 = 1; |
|
|
|
}; |
|
|
|
|
|
|
|
// Setting up Timer A |
|
|
|
cia.RS = 0x04; |
|
|
|
cia.DATA = 0x02; |
|
|
|
cia.RS = 0x0E; |
|
|
|
cia.DATA = 0x11; |
|
|
|
|
|
|
|
// Setting up Timer B |
|
|
|
cia.RS = 0x06; |
|
|
|
cia.DATA = 0x01; |
|
|
|
cia.RS = 0x0F; |
|
|
|
cia.DATA = 0x51; |
|
|
|
|
|
|
|
cia.RS = 0x06; |
|
|
|
// Verify Timer B Low Byte Value |
|
|
|
expect(cia.DATA).to.be.equal(0x01); |
|
|
|
tick(1); |
|
|
|
// Timer B should not have changed. |
|
|
|
expect(cia.DATA).to.be.equal(0x01); |
|
|
|
// Timer A should have ticked down by 1. |
|
|
|
cia.RS = 0x04; |
|
|
|
expect(cia.DATA).to.be.equal(0x01); |
|
|
|
tick(1); tick(1); |
|
|
|
// Timer A should have underflowed and Timer B ticked down by 1 |
|
|
|
expect(cia.DATA).to.be.equal(0x02); |
|
|
|
cia.RS = 0x06; |
|
|
|
expect(cia.DATA).to.be.equal(0x00); |
|
|
|
|
|
|
|
// Check that Timer A triggered interrupt... but Timer B did not! |
|
|
|
cia.RS = 0x0D; |
|
|
|
let IC = cia.DATA; |
|
|
|
expect(IC & 0x01).to.be.equal(0x01); |
|
|
|
expect(IC & 0x02).to.be.equal(0x00); |
|
|
|
|
|
|
|
tick(3); // Run through Timer A once more. |
|
|
|
// Check that both Timer A & B triggered interrupt! |
|
|
|
IC = cia.DATA; |
|
|
|
expect(IC & 0x01).to.be.equal(0x01); |
|
|
|
expect(IC & 0x02).to.be.equal(0x02); |
|
|
|
|
|
|
|
// Both timers should have latched back to their starting values. |
|
|
|
cia.RS = 0x04; |
|
|
|
expect(cia.DATA).to.be.equal(0x02); |
|
|
|
cia.RS = 0x06; |
|
|
|
expect(cia.DATA).to.be.equal(0x01); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
it("Timer B ticks on Timer A Underflow (CNT Triggered for B only)", function(){ |
|
|
|
let cia = new MOSCIA(); |
|
|
|
let tick = (cycle) => { |
|
|
|
for (let i=0; i < cycle; i++) |
|
|
|
cia.phi2 = 1; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
// Setup Timer A (trigger on phi2 only) |
|
|
|
cia.RS = 0x04; |
|
|
|
cia.DATA = 0x02; |
|
|
|
cia.RS = 0x0E; |
|
|
|
cia.DATA = 0x11; |
|
|
|
|
|
|
|
// Setup Timer B (trigger on A underflow and CNT high) |
|
|
|
cia.RS = 0x06; |
|
|
|
cia.DATA = 0x01; |
|
|
|
cia.RS = 0x0F; |
|
|
|
cia.DATA = 0x71; |
|
|
|
|
|
|
|
// Keep CNT low, check that underflowing A *does NOT* tick B. |
|
|
|
cia.CNT = 0; // <-- Just to be sure. |
|
|
|
tick(2); |
|
|
|
// Just make sure we're ticking A |
|
|
|
cia.RS = 0x04; |
|
|
|
expect(cia.DATA).to.be.equal(0x00); |
|
|
|
tick(1); |
|
|
|
expect(cia.DATA).to.be.equal(0x02); |
|
|
|
// Make sure B did not tick! |
|
|
|
cia.RS = 0x06; |
|
|
|
expect(cia.DATA).to.be.equal(0x01); |
|
|
|
|
|
|
|
// Clear interrupt flags |
|
|
|
cia.RS = 0x0D; |
|
|
|
let IC = cia.DATA; |
|
|
|
|
|
|
|
// NOW tick with CNT high! |
|
|
|
cia.CNT = 1; |
|
|
|
tick(3); |
|
|
|
// Checking A rolled over |
|
|
|
cia.RS = 0x04; |
|
|
|
expect(cia.DATA).to.be.equal(0x02); |
|
|
|
// Now checking B ticked... |
|
|
|
cia.RS = 0x06; |
|
|
|
expect(cia.DATA).to.be.equal(0x00); |
|
|
|
// Double check CNT is high |
|
|
|
expect(cia.CNT).to.be.equal(1); |
|
|
|
|
|
|
|
// One more A cycle to check B rolls over! |
|
|
|
tick(3); |
|
|
|
expect(cia.DATA).to.be.equal(0x01); |
|
|
|
cia.RS = 0x04; |
|
|
|
expect(cia.DATA).to.be.equal(0x02); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|