From 1580a3ba2bc82c490a43c93bb7fe1be1b0ba7390 Mon Sep 17 00:00:00 2001 From: Shachar Shemesh Date: Sun, 22 Oct 2023 22:03:01 +0300 Subject: [PATCH] Initial implementation of 6522::Timer1 --- mos6522.cpp | 45 +++++++++++++++++++++++++++++++++++++++++++++ mos6522.h | 13 +++++++++++++ 2 files changed, 58 insertions(+) diff --git a/mos6522.cpp b/mos6522.cpp index 2c765a5..57118bd 100644 --- a/mos6522.cpp +++ b/mos6522.cpp @@ -2,6 +2,24 @@ void Mos6522::main() { while(true) { + timer1--; + + if( timer1==0 ) { + if( aux_ctrl_reg & (1<<7) ) { + if( timer1_int_armed ) + orb ^= 0x80; // XXX check whether affects ORB on real chip + } + + if( aux_ctrl_reg & (1<<6) ) { + set_intr( Interrupts::T1 ); + timer1 = timer1_latch_high << 8 | timer1_latch_low; + } else { + if( timer1_int_armed ) { + set_intr( Interrupts::T1 ); + timer1_int_armed = false; + } + } + } //systemClock.tick(); } } @@ -16,6 +34,17 @@ uint8_t Mos6522::read(Addr registerSelect) { return ddrb; case 0x03: return ddra; + case 0x04: + reset_intr( Interrupts::T1 ); + return timer1 & 0xff; + case 0x05: + return timer1 >> 8; + case 0x06: + return timer1_latch_low; + case 0x07: + return timer1_latch_high; + case 0x0a: + return aux_ctrl_reg; } } @@ -37,6 +66,22 @@ void Mos6522::write(Addr registerSelect, uint8_t data) { ddra = data; update_output_a(); break; + case 0x04: + case 0x06: + timer1_latch_low = data; + break; + case 0x05: + timer1_latch_high = data; + timer1 = timer1_latch_high << 8 | timer1_latch_low; + reset_intr( Interrupts::T1 ); + break; + case 0x07: + timer1_latch_high = data; + reset_intr( Interrupts::T1 ); + break; + case 0x0a: + aux_ctrl_reg = data; + break; } } diff --git a/mos6522.h b/mos6522.h index e2e7cd5..b00f066 100644 --- a/mos6522.h +++ b/mos6522.h @@ -8,8 +8,18 @@ class Mos6522 { Mos6522Interface &interface_; SystemClock &systemClock_; + // Registers uint8_t orb = 0, irb = 0, ddrb = 0; uint8_t ora = 0, ira = 0, ddra = 0; + + uint16_t timer1 = 0; + uint8_t timer1_latch_low = 0, timer1_latch_high = 0; + bool timer1_int_armed = false; + + uint8_t aux_ctrl_reg = 0; // ACR + + enum class Interrupts { T1 }; + uint8_t intr = 0; public: enum class Port { A=0, B=1 }; @@ -30,4 +40,7 @@ class Mos6522 { private: void update_output_a(); void update_output_b(); + + void reset_intr( Interrupts intr ); + void set_intr( Interrupts intr ); };