From fb7a64a22f383049d0eeeda3ef373e4304f63968 Mon Sep 17 00:00:00 2001 From: Jorj Bauer Date: Sun, 12 Jul 2020 12:46:02 -0400 Subject: [PATCH] common debugging buffer (fix some memory overruns); consistent timing improvements --- globals.cpp | 2 + globals.h | 2 + teensy/teensy-speaker.cpp | 3 +- teensy/teensy-speaker.h | 2 +- teensy/teensy.ino | 122 +++++++++++++++++++------------------- 5 files changed, 67 insertions(+), 64 deletions(-) diff --git a/globals.cpp b/globals.cpp index 3ad428c..e9e683d 100644 --- a/globals.cpp +++ b/globals.cpp @@ -17,3 +17,5 @@ volatile bool g_biosInterrupt = false; uint32_t g_speed = 1023000; // Hz bool g_invertPaddleX = false; bool g_invertPaddleY = false; + +char debugBuf[255]; diff --git a/globals.h b/globals.h index 2a6b5aa..d340f73 100644 --- a/globals.h +++ b/globals.h @@ -53,6 +53,8 @@ extern uint32_t g_speed; extern bool g_invertPaddleX; extern bool g_invertPaddleY; +extern char debugBuf[255]; + #ifdef TEENSYDUINO #include extern Threads::Mutex spi_lock; diff --git a/teensy/teensy-speaker.cpp b/teensy/teensy-speaker.cpp index 2a12593..8380697 100644 --- a/teensy/teensy-speaker.cpp +++ b/teensy/teensy-speaker.cpp @@ -83,9 +83,8 @@ void TeensySpeaker::maintainSpeaker() togmutex.unlock(); // Now we can safely update the DAC based on the current toggleState - // uint16_t v = (toggleState ? 0xFFF : 0x000); + uint16_t v = (toggleState ? 0xFFF : 0x000); // dac.write((uint8_t) ((v >> 8) & 0xFF), (uint8_t) (v & 0xFF), true); - } void TeensySpeaker::beginMixing() diff --git a/teensy/teensy-speaker.h b/teensy/teensy-speaker.h index 58b83e3..ef0ad86 100644 --- a/teensy/teensy-speaker.h +++ b/teensy/teensy-speaker.h @@ -4,7 +4,7 @@ #include "physicalspeaker.h" #include -#define SAMPLERATE 8000 +#define SAMPLERATE 44100 class TeensySpeaker : public PhysicalSpeaker { public: diff --git a/teensy/teensy.ino b/teensy/teensy.ino index 12e4e67..b477090 100644 --- a/teensy/teensy.ino +++ b/teensy/teensy.ino @@ -18,6 +18,8 @@ #define DEBUG_TIMING +#define THREADED if (1) + #if F_CPU < 240000000 #pragma AiiE warning: performance will improve if you overclock the Teensy to 240MHz (F_CPU=240MHz) or 256MHz (F_CPU=256MHz) #endif @@ -78,7 +80,7 @@ void setup() pinMode(DEBUGPIN, OUTPUT); // for debugging // enableFaultHandler(); - SCB_SHCSR |= SCB_SHCSR_BUSFAULTENA | SCB_SHCSR_USGFAULTENA | SCB_SHCSR_MEMFAULTENA; +// SCB_SHCSR |= SCB_SHCSR_BUSFAULTENA | SCB_SHCSR_USGFAULTENA | SCB_SHCSR_MEMFAULTENA; // set the Time library to use Teensy 3.0's RTC to keep time @@ -226,43 +228,43 @@ void biosInterrupt() g_keyboard->maintainKeyboard(); } -uint32_t spk_nextResetMillis = 0; -uint32_t spk_refreshCount = 0; -uint32_t spk_microsAtStart = micros(); -uint32_t spk_microsForNext = 0; -void runSpeaker() +void runSpeaker(uint32_t now) { - if (1) { - if (micros() >= spk_microsForNext) { + static uint32_t spk_nextResetMicros = 0; + static uint32_t spk_refreshCount = 0; + static uint32_t spk_microsAtStart = micros(); + static uint32_t spk_microsForNext = 0; + + THREADED { + if (now >= spk_microsForNext) { spk_refreshCount++; - spk_microsForNext = spk_microsAtStart + ((1000000*spk_refreshCount)/SAMPLERATE); + spk_microsForNext = spk_microsAtStart + ((float)1000000.0*((float)spk_refreshCount/(float)SAMPLERATE)); ((TeensySpeaker *)g_speaker)->maintainSpeaker(); } - if (millis() >= spk_nextResetMillis) { - spk_nextResetMillis = millis() + 1000; + if (now >= spk_nextResetMicros) { #ifdef DEBUG_TIMING - static char buf[25]; float pct = (100.0 * (float)spk_refreshCount) / (float)SAMPLERATE; - sprintf(buf, "Speaker running at %f%% [%lu]", pct, spk_refreshCount); - println(buf); + sprintf(debugBuf, "Speaker running at %f%% [%lu]", pct, spk_refreshCount); + println(debugBuf); #endif - + + spk_microsAtStart = now; spk_refreshCount = 0; - spk_microsAtStart = micros(); - spk_microsForNext = spk_microsAtStart + ((1000000*spk_refreshCount)/SAMPLERATE); + spk_nextResetMicros = spk_microsAtStart + 1000000; + spk_microsForNext = spk_microsAtStart + ((float)1000000.0*((float)spk_refreshCount/(float)SAMPLERATE)); } } } -void runMaintenance() +void runMaintenance(uint32_t now) { static uint32_t nextRuntime = 0; - if (1) { - if (millis() >= nextRuntime) { - nextRuntime = millis() + 100; // FIXME: what's a good time here + THREADED { + if (now >= nextRuntime) { + nextRuntime = now + 100000000; // FIXME: what's a good time here if (!resetButtonDebouncer.read()) { // This is the BIOS interrupt. We immediately act on it. @@ -276,22 +278,22 @@ void runMaintenance() } #define TARGET_FPS 30 -void runDisplay() +void runDisplay(uint32_t now) { // When do we want to reset our expectation of "normal"? - static uint32_t nextResetMillis = 0; + static uint32_t nextResetMicros = 0; // how many full display refreshes have we managed in this second? static uint32_t refreshCount = 0; // how many micros until the next frame refresh? static uint32_t microsAtStart = 0; - static uint32_t microsForNext = micros() + 1000000/TARGET_FPS; // (1000000 us/second) / (frames/second) = us/frame + static uint32_t microsForNext = micros(); static uint32_t lastFps = 0; - if (1) { + THREADED { // If it's time to draw the next frame, then do so - if (micros() >= microsForNext) { + if (now >= microsForNext) { refreshCount++; - microsForNext = microsAtStart + ((1000000*refreshCount)/TARGET_FPS); + microsForNext = microsAtStart + (1000000.0*((float)refreshCount/(float)TARGET_FPS)); doDebugging(lastFps); @@ -309,15 +311,15 @@ void runDisplay() } // Once a second, start counting all over again - if (millis() >= nextResetMillis) { + if (now >= nextResetMicros) { lastFps = refreshCount; #ifdef DEBUG_TIMING println("Display running at ", lastFps, " FPS"); #endif - nextResetMillis = millis() + 1000; + nextResetMicros = now + 1000000; refreshCount = 0; - microsAtStart = micros(); - microsForNext = microsAtStart + ((1000000*refreshCount)/TARGET_FPS); + microsAtStart = now; + microsForNext = microsAtStart + (1000000.0*((float)refreshCount/(float)TARGET_FPS)); } } } @@ -337,80 +339,78 @@ void runDebouncer() } } -void runCPU() +void runCPU(uint32_t now) { - static uint32_t nextResetMillis = 0; + static uint32_t nextResetMicros = 0; static uint32_t countSinceLast = 0; static uint32_t microsAtStart = micros(); static uint32_t microsForNext = microsAtStart + (countSinceLast * SPEEDCTL); - if (1) { - if (micros() >= microsForNext) { + THREADED { + if (now >= microsForNext) { countSinceLast += g_cpu->Run(24); // The CPU runs in bursts of cycles. This '24' is the max burst we perform. ((AppleVM *)g_vm)->cpuMaintenance(g_cpu->cycles); microsForNext = microsAtStart + (countSinceLast * SPEEDCTL); } - if (millis() >= nextResetMillis) { - nextResetMillis = millis() + 1000; + if (now >= nextResetMicros) { + nextResetMicros = now + 1000000; #ifdef DEBUG_TIMING - static char buf[25]; float pct = (100.0 * (float)countSinceLast) / (float)g_speed; - sprintf(buf, "CPU running at %f%%", pct); - println(buf); + sprintf(debugBuf, "CPU running at %f%%", pct); + println(debugBuf); #endif countSinceLast = 0; - microsAtStart = micros(); + microsAtStart = now; microsForNext = microsAtStart + (countSinceLast * SPEEDCTL); } - } } void loop() { - runCPU(); - runDisplay(); - runSpeaker(); - runMaintenance(); + uint32_t now = micros(); + runCPU(now); + runDisplay(now); + runSpeaker(now); + runMaintenance(now); } void doDebugging(uint32_t lastFps) { - char buf[25]; switch (g_debugMode) { case D_SHOWFPS: - sprintf(buf, "%lu FPS", lastFps); - g_display->debugMsg(buf); + sprintf(debugBuf, "%lu FPS", lastFps); + g_display->debugMsg(debugBuf); break; case D_SHOWMEMFREE: - sprintf(buf, "%lu %u", FreeRamEstimate(), heapSize()); - g_display->debugMsg(buf); + sprintf(debugBuf, "%lu %u", FreeRamEstimate(), heapSize()); + g_display->debugMsg(debugBuf); break; case D_SHOWPADDLES: - sprintf(buf, "%u %u", g_paddles->paddle0(), g_paddles->paddle1()); - g_display->debugMsg(buf); + sprintf(debugBuf, "%u %u", g_paddles->paddle0(), g_paddles->paddle1()); + g_display->debugMsg(debugBuf); break; case D_SHOWPC: - sprintf(buf, "%X", g_cpu->pc); - g_display->debugMsg(buf); + sprintf(debugBuf, "%X", g_cpu->pc); + g_display->debugMsg(debugBuf); break; case D_SHOWCYCLES: - sprintf(buf, "%lX", g_cpu->cycles); - g_display->debugMsg(buf); + sprintf(debugBuf, "%lX", g_cpu->cycles); + g_display->debugMsg(debugBuf); break; case D_SHOWTIME: - sprintf(buf, "%.2d:%.2d:%.2d", hour(), minute(), second()); - g_display->debugMsg(buf); + sprintf(debugBuf, "%.2d:%.2d:%.2d", hour(), minute(), second()); + g_display->debugMsg(debugBuf); break; case D_SHOWDSK: { uint8_t sd = ((AppleVM *)g_vm)->disk6->selectedDrive(); - sprintf(buf, "s %d t %d", + sprintf(debugBuf, "s %d t %d", sd, ((AppleVM *)g_vm)->disk6->headPosition(sd)); - g_display->debugMsg(buf); + g_display->debugMsg(debugBuf); } break; }