| cia.RS = 0x01; | cia.RS = 0x01; | ||||
| expect(cia.DATA & 0x40).to.be.equal(0x00); | 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); | |||||
| }); | |||||
| }); | }); | ||||