1//! GBA hardware timers 2 3use crate::apu::Apu; 4use crate::dma::DmaState; 5use crate::interrupts::{InterruptRegisters, InterruptType}; 6use crate::scheduler::{Scheduler, SchedulerEvent}; 7use bincode::{Decode, Encode}; 8use jgenesis_common::num::GetBit; 9use std::{array, cmp}; 10 11#[derive(Debug, Clone, Encode, Decode)] 12struct Timer { 13 idx: u8, 14 enabled: bool, 15 counter: u16, 16 reload: u16, 17 clock_shift: u8, 18 cascading: bool, 19 irq_enabled: bool, 20 pending_reload_write: Option<u16>, 21 pending_control_write: Option<u16>, 22 just_enabled: bool, 23} 24 25impl Timer { 26 fn new(idx: u8) -> Self { 27 Self { 28 idx, 29 enabled: false, 30 counter: 0, 31 reload: 0, 32 clock_shift: 0, 33 cascading: false, 34 irq_enabled: false, 35 pending_reload_write: None, 36 pending_control_write: None, 37 just_enabled: false, 38 } 39 } 40 41 fn tick( 42 &mut self, 43 prev_overflowed: bool, 44 prev_cycles: u64, 45 current_cycles: u64, 46 apu: &mut Apu, 47 interrupts: &mut InterruptRegisters, 48 ) -> bool { 49 if !self.enabled { 50 self.apply_pending_writes(apu); 51 return false; 52 } 53 54 if self.just_enabled { 55 self.just_enabled = false; 56 self.counter = self.reload; 57 self.apply_pending_writes(apu); 58 59 return false; 60 } 61 62 let increment: u64 = if self.cascading { 63 prev_overflowed.into() 64 } else { 65 (current_cycles >> self.clock_shift) - (prev_cycles >> self.clock_shift) 66 }; 67 68 let mut overflowed; 69 (self.counter, overflowed) = self.counter.overflowing_add(increment as u16); 70 overflowed |= increment >= u64::from(u16::MAX); 71 72 if overflowed { 73 self.counter = self.reload; 74 75 if self.irq_enabled { 76 interrupts.set_flag(InterruptType::TIMER[self.idx as usize], current_cycles); 77 } 78 } 79 80 self.apply_pending_writes(apu); 81 82 overflowed 83 } 84 85 fn apply_pending_writes(&mut self, apu: &mut Apu) { 86 if let Some(reload) = self.pending_reload_write.take() { 87 self.apply_reload_write(reload); 88 } 89 90 if let Some(control) = self.pending_control_write.take() { 91 self.apply_control_write(control); 92 } 93 94 if self.idx <= 1 { 95 let frequency = (self.enabled && !self.cascading).then(|| { 96 let increments_per_overflow = 0x10000 - u32::from(self.reload); 97 let cycles_per_overflow = increments_per_overflow << self.clock_shift; 98 (crate::GBA_CLOCK_SPEED as f64) / f64::from(cycles_per_overflow) 99 }); 100 apu.notify_timer_frequency_update(self.idx, frequency); 101 } 102 } 103 104 fn apply_reload_write(&mut self, value: u16) { 105 self.reload = value; 106 107 log::trace!("TM{}CNT_L write: {value:04X} (reload value)", self.idx); 108 } 109 110 fn apply_control_write(&mut self, value: u16) { 111 const CLOCK_SHIFTS: [u8; 4] = [ 112 0, // Divider 1 (16777216 Hz) 113 6, // Divider 64 (262144 Hz) 114 8, // Divider 256 (65536 Hz) 115 10, // Divider 1024 (16384 Hz) 116 ]; 117 118 self.clock_shift = CLOCK_SHIFTS[(value & 3) as usize]; 119 self.cascading = self.idx != 0 && value.bit(2); 120 self.irq_enabled = value.bit(6); 121 122 let prev_enabled = self.enabled; 123 self.enabled = value.bit(7); 124 125 self.just_enabled = !prev_enabled && self.enabled; 126 127 log::trace!("TM{}CNT_H write: {value:04X}", self.idx); 128 log::trace!(" Prescaler divider: {}", 1 << self.clock_shift); 129 log::trace!(" Cascading: {}", self.cascading); 130 log::trace!(" IRQ enabled: {}", self.irq_enabled); 131 log::trace!(" Timer enabled: {}", self.enabled); 132 } 133 134 fn read_control(&self) -> u16 { 135 let divider_bits = if self.clock_shift == 0 { 0 } else { self.clock_shift / 2 - 2 }; 136 137 u16::from(divider_bits) 138 | (u16::from(self.cascading) << 2) 139 | (u16::from(self.irq_enabled) << 6) 140 | (u16::from(self.enabled) << 7) 141 } 142 143 fn next_event_cycles(&self, cycles: u64) -> Option<u64> { 144 if self.pending_reload_write.is_some() 145 || self.pending_control_write.is_some() 146 || self.just_enabled 147 { 148 // Force an update on the next cycle after register writes 149 return Some(cycles + 1); 150 } 151 152 if !self.enabled || self.cascading { 153 // Disabled timers never overflow, and cascading timers can only overflow when another 154 // timer overflows 155 return None; 156 } 157 158 let increments_until_overflow = 0x10000 - u64::from(self.counter); 159 let mut cycles_until_overflow = increments_until_overflow << self.clock_shift; 160 cycles_until_overflow -= cycles & ((1 << self.clock_shift) - 1); 161 162 Some(cycles + cycles_until_overflow) 163 } 164} 165 166#[derive(Debug, Clone, Encode, Decode)] 167pub struct Timers { 168 timers: [Timer; 4], 169 cycles: u64, 170 next_overflow_cycles: u64, 171} 172 173impl Timers { 174 pub fn new() -> Self { 175 Self { 176 timers: array::from_fn(|i| Timer::new(i as u8)), 177 cycles: 0, 178 next_overflow_cycles: u64::MAX, 179 } 180 } 181 182 pub fn step_to( 183 &mut self, 184 cycles: u64, 185 apu: &mut Apu, 186 dma: &mut DmaState, 187 interrupts: &mut InterruptRegisters, 188 scheduler: &mut Scheduler, 189 ) { 190 if cycles < self.next_overflow_cycles { 191 return; 192 } 193 194 self.step_to_internal(cycles, apu, dma, interrupts, scheduler); 195 } 196 197 fn step_to_internal( 198 &mut self, 199 cycles: u64, 200 apu: &mut Apu, 201 dma: &mut DmaState, 202 interrupts: &mut InterruptRegisters, 203 scheduler: &mut Scheduler, 204 ) { 205 while self.cycles < cycles { 206 let tick_cycles = cmp::min(self.next_overflow_cycles, cycles); 207 208 let mut overflowed = false; 209 for (i, timer) in self.timers.iter_mut().enumerate() { 210 overflowed = timer.tick(overflowed, self.cycles, tick_cycles, apu, interrupts); 211 212 if overflowed && i <= 1 { 213 apu.handle_timer_overflow(i, tick_cycles, dma); 214 } 215 } 216 217 self.cycles = tick_cycles; 218 self.update_next_overflow_cycles(scheduler); 219 } 220 } 221 222 fn update_next_overflow_cycles(&mut self, scheduler: &mut Scheduler) { 223 match self.timers.iter().filter_map(|timer| timer.next_event_cycles(self.cycles)).min() { 224 Some(next_overflow_cycles) => { 225 self.next_overflow_cycles = next_overflow_cycles; 226 scheduler 227 .insert_or_update(SchedulerEvent::TimerOverflow, self.next_overflow_cycles); 228 } 229 None => { 230 self.next_overflow_cycles = u64::MAX; 231 scheduler.remove(SchedulerEvent::TimerOverflow); 232 } 233 } 234 } 235 236 pub fn read_register( 237 &mut self, 238 address: u32, 239 cycles: u64, 240 apu: &mut Apu, 241 dma: &mut DmaState, 242 interrupts: &mut InterruptRegisters, 243 scheduler: &mut Scheduler, 244 ) -> u16 { 245 let timer_idx = (address >> 2) & 3; 246 247 if !address.bit(1) { 248 self.step_to_internal(cycles, apu, dma, interrupts, scheduler); 249 log::trace!( 250 "Timer read {address:08X} at cycles {cycles}, counter {:04X}", 251 self.timers[timer_idx as usize].counter 252 ); 253 self.timers[timer_idx as usize].counter 254 } else { 255 self.timers[timer_idx as usize].read_control() 256 } 257 } 258 259 #[allow(clippy::too_many_arguments)] 260 pub fn write_register( 261 &mut self, 262 address: u32, 263 value: u16, 264 cycles: u64, 265 apu: &mut Apu, 266 dma: &mut DmaState, 267 interrupts: &mut InterruptRegisters, 268 scheduler: &mut Scheduler, 269 ) { 270 log::trace!("Timer write {address:08X} {value:04X} at cycles {cycles}"); 271 272 self.step_to_internal(cycles, apu, dma, interrupts, scheduler); 273 274 let timer_idx = (address >> 2) & 3; 275 276 if !address.bit(1) { 277 self.timers[timer_idx as usize].pending_reload_write = Some(value); 278 } else { 279 self.timers[timer_idx as usize].pending_control_write = Some(value); 280 } 281 282 self.update_next_overflow_cycles(scheduler); 283 } 284 285 #[allow(clippy::too_many_arguments)] 286 pub fn write_register_byte( 287 &mut self, 288 address: u32, 289 value: u8, 290 cycles: u64, 291 apu: &mut Apu, 292 dma: &mut DmaState, 293 interrupts: &mut InterruptRegisters, 294 scheduler: &mut Scheduler, 295 ) { 296 log::trace!("Timer byte write {address:08X} {value:02X} at cycles {cycles}"); 297 298 self.step_to_internal(cycles, apu, dma, interrupts, scheduler); 299 300 let timer_idx = (address >> 2) & 3; 301 302 if !address.bit(1) { 303 let mut reload_bytes = self.timers[timer_idx as usize].reload.to_le_bytes(); 304 reload_bytes[(address & 1) as usize] = value; 305 self.timers[timer_idx as usize].pending_reload_write = 306 Some(u16::from_le_bytes(reload_bytes)); 307 } else { 308 let mut control_bytes = self.timers[timer_idx as usize].read_control().to_le_bytes(); 309 control_bytes[(address & 1) as usize] = value; 310 self.timers[timer_idx as usize].pending_control_write = 311 Some(u16::from_le_bytes(control_bytes)); 312 } 313 314 self.update_next_overflow_cycles(scheduler); 315 } 316}