From 57ce10418f29a01a82c9f27423421d64abd26706 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Fri, 20 Dec 2019 23:33:14 -0500 Subject: [PATCH] Switches prescale logic, the better to deal with changes in prescaler. According to my assumptions about the behaviour, anyway. --- Components/68901/MFP68901.cpp | 33 +++++++++++++++---- Components/68901/MFP68901.hpp | 2 +- .../Clock Signal.xcodeproj/project.pbxproj | 2 +- 3 files changed, 29 insertions(+), 8 deletions(-) diff --git a/Components/68901/MFP68901.cpp b/Components/68901/MFP68901.cpp index efb1de927..95c2a1992 100644 --- a/Components/68901/MFP68901.cpp +++ b/Components/68901/MFP68901.cpp @@ -8,6 +8,7 @@ #include "MFP68901.hpp" +#include #include #define LOG_PREFIX "[MFP] " @@ -179,12 +180,26 @@ void MFP68901::run_for(HalfCycles time) { cycles_left_ += time; const int cycles = int(cycles_left_.flush().as_integral()); + if(!cycles) return; + for(int c = 0; c < 4; ++c) { if(timers_[c].mode >= TimerMode::Delay) { - const int dividend = (cycles + timers_[c].prescale - timers_[c].divisor); - const int decrements = dividend / timers_[c].prescale; - timers_[c].divisor = timers_[c].prescale - (dividend % timers_[c].prescale); - if(decrements) decrement_timer(c, decrements); + // This code applies the timer prescaling only. prescale_count is used to count + // upwards rather than downwards for simplicity, but on the real hardware it's + // pretty safe to assume it actually counted downwards. So the clamp to 0 is + // because gymnastics may need to occur when the prescale value is altered, e.g. + // if a prescale of 256 is set and the prescale_count is currently 2 then the + // counter should roll over in 254 cycles. If the user at that point changes the + // prescale_count to 1 then the counter will need to be altered to -253 and + // allowed to keep counting up until it crosses both 0 and 1. + const int dividend = timers_[c].prescale_count + cycles; + const int decrements = std::max(dividend / timers_[c].prescale, 0); + if(decrements) { + decrement_timer(c, decrements); + timers_[c].prescale_count = dividend % timers_[c].prescale; + } else { + timers_[c].prescale_count += cycles; + } } } } @@ -198,11 +213,17 @@ HalfCycles MFP68901::get_next_sequence_point() { void MFP68901::set_timer_mode(int timer, TimerMode mode, int prescale, bool reset_timer) { LOG("Timer " << timer << " mode set: " << int(mode) << "; prescale: " << prescale); timers_[timer].mode = mode; - timers_[timer].prescale = prescale; if(reset_timer) { - timers_[timer].divisor = prescale; + timers_[timer].prescale_count = 0; timers_[timer].value = timers_[timer].reload_value; + } else { + // This hoop is because the prescale_count here goes upward but I'm assuming it goes downward in + // real hardware. Therefore this deals with the "switched to a lower prescaling" case whereby the + // old cycle should be allowed naturally to expire. + timers_[timer].prescale_count = prescale - (timers_[timer].prescale - timers_[timer].prescale_count); } + + timers_[timer].prescale = prescale; } void MFP68901::set_timer_data(int timer, uint8_t value) { diff --git a/Components/68901/MFP68901.hpp b/Components/68901/MFP68901.hpp index d49fe55bb..974e195e7 100644 --- a/Components/68901/MFP68901.hpp +++ b/Components/68901/MFP68901.hpp @@ -93,7 +93,7 @@ class MFP68901: public ClockingHint::Source { uint8_t value = 0; uint8_t reload_value = 0; int prescale = 1; - int divisor = 1; + int prescale_count = 1; bool event_input = false; } timers_[4]; uint8_t timer_ab_control_[2] = { 0, 0 }; diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index e7513b49a..3c527c9e1 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -4916,7 +4916,7 @@ "$(USER_LIBRARY_DIR)/Frameworks", ); GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_OPTIMIZATION_LEVEL = 3; + GCC_OPTIMIZATION_LEVEL = fast; MACOSX_DEPLOYMENT_TARGET = 10.12; PRODUCT_NAME = "$(TARGET_NAME)"; };