Class: PSX::Timers
- Inherits:
-
Object
- Object
- PSX::Timers
- Defined in:
- lib/psx/timers.rb
Overview
Root Counters (Timers) Timer 0: Pixel clock / Dot clock Timer 1: Horizontal retrace Timer 2: System clock / 8
Defined Under Namespace
Classes: Timer
Constant Summary collapse
- NUM_TIMERS =
3- MODE_SYNC_ENABLE =
Mode register bits
0x0001- MODE_SYNC_MODE =
Sync enable
0x0006- MODE_RESET_TARGET =
Sync mode (bits 1-2)
0x0008- MODE_IRQ_TARGET =
Reset counter on target
0x0010- MODE_IRQ_OVERFLOW =
IRQ when target reached
0x0020- MODE_IRQ_REPEAT =
IRQ on overflow
0x0040- MODE_IRQ_TOGGLE =
Repeat IRQ
0x0080- MODE_CLOCK_SOURCE =
Toggle IRQ bit
0x0300- MODE_IRQ_FLAG =
Clock source (bits 8-9)
0x0400- MODE_TARGET_REACHED =
IRQ flag (bit 10, read-only)
0x0800- MODE_OVERFLOW =
Target reached (bit 11)
0x1000
Instance Method Summary collapse
-
#hblank ⇒ Object
Call on HBlank.
-
#initialize(interrupts: nil) ⇒ Timers
constructor
A new instance of Timers.
- #read(offset) ⇒ Object
-
#tick(cycles = 1) ⇒ Object
Call this periodically to advance timers cycles: number of CPU cycles elapsed.
-
#vblank ⇒ Object
Call on VBlank to update timer 1.
- #write(offset, value) ⇒ Object
Constructor Details
#initialize(interrupts: nil) ⇒ Timers
Returns a new instance of Timers.
105 106 107 108 109 |
# File 'lib/psx/timers.rb', line 105 def initialize(interrupts: nil) @interrupts = interrupts @timers = Array.new(NUM_TIMERS) { Timer.new } @system_counter = 0 end |
Instance Method Details
#hblank ⇒ Object
Call on HBlank
171 172 173 |
# File 'lib/psx/timers.rb', line 171 def hblank # Timer 0 and 1 can sync to hblank end |
#read(offset) ⇒ Object
111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/psx/timers.rb', line 111 def read(offset) timer_num = offset / 0x10 reg = offset % 0x10 return 0 if timer_num >= NUM_TIMERS timer = @timers[timer_num] case reg when 0x00 then timer.read_counter when 0x04 then timer.read_mode when 0x08 then timer.read_target else 0 end end |
#tick(cycles = 1) ⇒ Object
Call this periodically to advance timers cycles: number of CPU cycles elapsed
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
# File 'lib/psx/timers.rb', line 142 def tick(cycles = 1) @system_counter += cycles # Timer 2 runs at system clock / 8 timer2_ticks = @system_counter / 8 if timer2_ticks > 0 if @timers[2].tick(timer2_ticks) @interrupts&.request(Interrupts::IRQ_TIMER2) end @system_counter %= 8 end # Timer 0 and 1 are typically synced to GPU # For simplicity, run them at a fixed rate if @timers[0].tick(cycles) @interrupts&.request(Interrupts::IRQ_TIMER0) end if @timers[1].tick(cycles / 8) # Slower for hblank timing @interrupts&.request(Interrupts::IRQ_TIMER1) end end |
#vblank ⇒ Object
Call on VBlank to update timer 1
166 167 168 |
# File 'lib/psx/timers.rb', line 166 def vblank # Timer 1 often syncs to vblank end |
#write(offset, value) ⇒ Object
126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/psx/timers.rb', line 126 def write(offset, value) timer_num = offset / 0x10 reg = offset % 0x10 return if timer_num >= NUM_TIMERS timer = @timers[timer_num] case reg when 0x00 then timer.write_counter(value) when 0x04 then timer.write_mode(value) when 0x08 then timer.write_target(value) end end |