|
|
|
|
@ -64,7 +64,7 @@ struct CounterState
|
|
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
static void UpdateCountingEnabled(CounterState& cs);
|
|
|
|
|
static void UpdateCountingEnabled(u32 index, CounterState& cs);
|
|
|
|
|
static void CheckForIRQ(u32 index, u32 old_counter);
|
|
|
|
|
|
|
|
|
|
static void AddSysClkTicks(void*, TickCount sysclk_ticks);
|
|
|
|
|
@ -198,7 +198,7 @@ void Timers::SetGate(u32 timer, bool state)
|
|
|
|
|
UnreachableCode();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UpdateCountingEnabled(cs);
|
|
|
|
|
UpdateCountingEnabled(timer, cs);
|
|
|
|
|
UpdateSysClkEvent();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -432,7 +432,7 @@ void Timers::WriteRegister(u32 offset, u32 value)
|
|
|
|
|
InterruptController::SetLineState(
|
|
|
|
|
static_cast<InterruptController::IRQ>(static_cast<u32>(InterruptController::IRQ::TMR0) + timer_index), false);
|
|
|
|
|
|
|
|
|
|
UpdateCountingEnabled(cs);
|
|
|
|
|
UpdateCountingEnabled(timer_index, cs);
|
|
|
|
|
CheckForIRQ(timer_index, cs.counter);
|
|
|
|
|
UpdateSysClkEvent();
|
|
|
|
|
}
|
|
|
|
|
@ -454,32 +454,41 @@ void Timers::WriteRegister(u32 offset, u32 value)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Timers::UpdateCountingEnabled(CounterState& cs)
|
|
|
|
|
void Timers::UpdateCountingEnabled(u32 index, CounterState& cs)
|
|
|
|
|
{
|
|
|
|
|
if (cs.mode.sync_enable)
|
|
|
|
|
if (index != 2)
|
|
|
|
|
{
|
|
|
|
|
switch (cs.mode.sync_mode)
|
|
|
|
|
if (cs.mode.sync_enable)
|
|
|
|
|
{
|
|
|
|
|
case SyncMode::PauseWhileGateActive:
|
|
|
|
|
cs.counting_enabled = !cs.gate;
|
|
|
|
|
break;
|
|
|
|
|
switch (cs.mode.sync_mode)
|
|
|
|
|
{
|
|
|
|
|
case SyncMode::PauseWhileGateActive:
|
|
|
|
|
cs.counting_enabled = !cs.gate;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case SyncMode::ResetOnGateEnd:
|
|
|
|
|
cs.counting_enabled = true;
|
|
|
|
|
break;
|
|
|
|
|
case SyncMode::ResetOnGateEnd:
|
|
|
|
|
cs.counting_enabled = true;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case SyncMode::ResetAndRunOnGateStart:
|
|
|
|
|
case SyncMode::FreeRunOnGateEnd:
|
|
|
|
|
cs.counting_enabled = cs.gate;
|
|
|
|
|
break;
|
|
|
|
|
case SyncMode::ResetAndRunOnGateStart:
|
|
|
|
|
case SyncMode::FreeRunOnGateEnd:
|
|
|
|
|
cs.counting_enabled = cs.gate;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
UnreachableCode();
|
|
|
|
|
default:
|
|
|
|
|
UnreachableCode();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
cs.counting_enabled = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
cs.counting_enabled = true;
|
|
|
|
|
// Timer 2 doesn't have a gate source. With sync enabled, modes 0/3 stop counting and 1/2 free-run.
|
|
|
|
|
cs.counting_enabled = (!cs.mode.sync_enable || cs.mode.sync_mode == SyncMode::ResetOnGateEnd ||
|
|
|
|
|
cs.mode.sync_mode == SyncMode::ResetAndRunOnGateStart);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cs.external_counting_enabled = cs.use_external_clock && cs.counting_enabled;
|
|
|
|
|
|