common debugging buffer (fix some memory overruns); consistent timing improvements

This commit is contained in:
Jorj Bauer 2020-07-12 12:46:02 -04:00
parent 816c38209c
commit fb7a64a22f
5 changed files with 67 additions and 64 deletions

View File

@ -17,3 +17,5 @@ volatile bool g_biosInterrupt = false;
uint32_t g_speed = 1023000; // Hz uint32_t g_speed = 1023000; // Hz
bool g_invertPaddleX = false; bool g_invertPaddleX = false;
bool g_invertPaddleY = false; bool g_invertPaddleY = false;
char debugBuf[255];

View File

@ -53,6 +53,8 @@ extern uint32_t g_speed;
extern bool g_invertPaddleX; extern bool g_invertPaddleX;
extern bool g_invertPaddleY; extern bool g_invertPaddleY;
extern char debugBuf[255];
#ifdef TEENSYDUINO #ifdef TEENSYDUINO
#include <TeensyThreads.h> #include <TeensyThreads.h>
extern Threads::Mutex spi_lock; extern Threads::Mutex spi_lock;

View File

@ -83,9 +83,8 @@ void TeensySpeaker::maintainSpeaker()
togmutex.unlock(); togmutex.unlock();
// Now we can safely update the DAC based on the current toggleState // 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); // dac.write((uint8_t) ((v >> 8) & 0xFF), (uint8_t) (v & 0xFF), true);
} }
void TeensySpeaker::beginMixing() void TeensySpeaker::beginMixing()

View File

@ -4,7 +4,7 @@
#include "physicalspeaker.h" #include "physicalspeaker.h"
#include <MCP492X.h> #include <MCP492X.h>
#define SAMPLERATE 8000 #define SAMPLERATE 44100
class TeensySpeaker : public PhysicalSpeaker { class TeensySpeaker : public PhysicalSpeaker {
public: public:

View File

@ -18,6 +18,8 @@
#define DEBUG_TIMING #define DEBUG_TIMING
#define THREADED if (1)
#if F_CPU < 240000000 #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) #pragma AiiE warning: performance will improve if you overclock the Teensy to 240MHz (F_CPU=240MHz) or 256MHz (F_CPU=256MHz)
#endif #endif
@ -78,7 +80,7 @@ void setup()
pinMode(DEBUGPIN, OUTPUT); // for debugging pinMode(DEBUGPIN, OUTPUT); // for debugging
// enableFaultHandler(); // 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 // set the Time library to use Teensy 3.0's RTC to keep time
@ -226,43 +228,43 @@ void biosInterrupt()
g_keyboard->maintainKeyboard(); g_keyboard->maintainKeyboard();
} }
uint32_t spk_nextResetMillis = 0; void runSpeaker(uint32_t now)
uint32_t spk_refreshCount = 0;
uint32_t spk_microsAtStart = micros();
uint32_t spk_microsForNext = 0;
void runSpeaker()
{ {
if (1) { static uint32_t spk_nextResetMicros = 0;
if (micros() >= spk_microsForNext) { 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_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(); ((TeensySpeaker *)g_speaker)->maintainSpeaker();
} }
if (millis() >= spk_nextResetMillis) { if (now >= spk_nextResetMicros) {
spk_nextResetMillis = millis() + 1000;
#ifdef DEBUG_TIMING #ifdef DEBUG_TIMING
static char buf[25];
float pct = (100.0 * (float)spk_refreshCount) / (float)SAMPLERATE; float pct = (100.0 * (float)spk_refreshCount) / (float)SAMPLERATE;
sprintf(buf, "Speaker running at %f%% [%lu]", pct, spk_refreshCount); sprintf(debugBuf, "Speaker running at %f%% [%lu]", pct, spk_refreshCount);
println(buf); println(debugBuf);
#endif #endif
spk_microsAtStart = now;
spk_refreshCount = 0; spk_refreshCount = 0;
spk_microsAtStart = micros(); spk_nextResetMicros = spk_microsAtStart + 1000000;
spk_microsForNext = spk_microsAtStart + ((1000000*spk_refreshCount)/SAMPLERATE); spk_microsForNext = spk_microsAtStart + ((float)1000000.0*((float)spk_refreshCount/(float)SAMPLERATE));
} }
} }
} }
void runMaintenance() void runMaintenance(uint32_t now)
{ {
static uint32_t nextRuntime = 0; static uint32_t nextRuntime = 0;
if (1) { THREADED {
if (millis() >= nextRuntime) { if (now >= nextRuntime) {
nextRuntime = millis() + 100; // FIXME: what's a good time here nextRuntime = now + 100000000; // FIXME: what's a good time here
if (!resetButtonDebouncer.read()) { if (!resetButtonDebouncer.read()) {
// This is the BIOS interrupt. We immediately act on it. // This is the BIOS interrupt. We immediately act on it.
@ -276,22 +278,22 @@ void runMaintenance()
} }
#define TARGET_FPS 30 #define TARGET_FPS 30
void runDisplay() void runDisplay(uint32_t now)
{ {
// When do we want to reset our expectation of "normal"? // 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? // how many full display refreshes have we managed in this second?
static uint32_t refreshCount = 0; static uint32_t refreshCount = 0;
// how many micros until the next frame refresh? // how many micros until the next frame refresh?
static uint32_t microsAtStart = 0; 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; static uint32_t lastFps = 0;
if (1) { THREADED {
// If it's time to draw the next frame, then do so // If it's time to draw the next frame, then do so
if (micros() >= microsForNext) { if (now >= microsForNext) {
refreshCount++; refreshCount++;
microsForNext = microsAtStart + ((1000000*refreshCount)/TARGET_FPS); microsForNext = microsAtStart + (1000000.0*((float)refreshCount/(float)TARGET_FPS));
doDebugging(lastFps); doDebugging(lastFps);
@ -309,15 +311,15 @@ void runDisplay()
} }
// Once a second, start counting all over again // Once a second, start counting all over again
if (millis() >= nextResetMillis) { if (now >= nextResetMicros) {
lastFps = refreshCount; lastFps = refreshCount;
#ifdef DEBUG_TIMING #ifdef DEBUG_TIMING
println("Display running at ", lastFps, " FPS"); println("Display running at ", lastFps, " FPS");
#endif #endif
nextResetMillis = millis() + 1000; nextResetMicros = now + 1000000;
refreshCount = 0; refreshCount = 0;
microsAtStart = micros(); microsAtStart = now;
microsForNext = microsAtStart + ((1000000*refreshCount)/TARGET_FPS); 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 countSinceLast = 0;
static uint32_t microsAtStart = micros(); static uint32_t microsAtStart = micros();
static uint32_t microsForNext = microsAtStart + (countSinceLast * SPEEDCTL); static uint32_t microsForNext = microsAtStart + (countSinceLast * SPEEDCTL);
if (1) { THREADED {
if (micros() >= microsForNext) { if (now >= microsForNext) {
countSinceLast += g_cpu->Run(24); // The CPU runs in bursts of cycles. This '24' is the max burst we perform. 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); ((AppleVM *)g_vm)->cpuMaintenance(g_cpu->cycles);
microsForNext = microsAtStart + (countSinceLast * SPEEDCTL); microsForNext = microsAtStart + (countSinceLast * SPEEDCTL);
} }
if (millis() >= nextResetMillis) { if (now >= nextResetMicros) {
nextResetMillis = millis() + 1000; nextResetMicros = now + 1000000;
#ifdef DEBUG_TIMING #ifdef DEBUG_TIMING
static char buf[25];
float pct = (100.0 * (float)countSinceLast) / (float)g_speed; float pct = (100.0 * (float)countSinceLast) / (float)g_speed;
sprintf(buf, "CPU running at %f%%", pct); sprintf(debugBuf, "CPU running at %f%%", pct);
println(buf); println(debugBuf);
#endif #endif
countSinceLast = 0; countSinceLast = 0;
microsAtStart = micros(); microsAtStart = now;
microsForNext = microsAtStart + (countSinceLast * SPEEDCTL); microsForNext = microsAtStart + (countSinceLast * SPEEDCTL);
} }
} }
} }
void loop() void loop()
{ {
runCPU(); uint32_t now = micros();
runDisplay(); runCPU(now);
runSpeaker(); runDisplay(now);
runMaintenance(); runSpeaker(now);
runMaintenance(now);
} }
void doDebugging(uint32_t lastFps) void doDebugging(uint32_t lastFps)
{ {
char buf[25];
switch (g_debugMode) { switch (g_debugMode) {
case D_SHOWFPS: case D_SHOWFPS:
sprintf(buf, "%lu FPS", lastFps); sprintf(debugBuf, "%lu FPS", lastFps);
g_display->debugMsg(buf); g_display->debugMsg(debugBuf);
break; break;
case D_SHOWMEMFREE: case D_SHOWMEMFREE:
sprintf(buf, "%lu %u", FreeRamEstimate(), heapSize()); sprintf(debugBuf, "%lu %u", FreeRamEstimate(), heapSize());
g_display->debugMsg(buf); g_display->debugMsg(debugBuf);
break; break;
case D_SHOWPADDLES: case D_SHOWPADDLES:
sprintf(buf, "%u %u", g_paddles->paddle0(), g_paddles->paddle1()); sprintf(debugBuf, "%u %u", g_paddles->paddle0(), g_paddles->paddle1());
g_display->debugMsg(buf); g_display->debugMsg(debugBuf);
break; break;
case D_SHOWPC: case D_SHOWPC:
sprintf(buf, "%X", g_cpu->pc); sprintf(debugBuf, "%X", g_cpu->pc);
g_display->debugMsg(buf); g_display->debugMsg(debugBuf);
break; break;
case D_SHOWCYCLES: case D_SHOWCYCLES:
sprintf(buf, "%lX", g_cpu->cycles); sprintf(debugBuf, "%lX", g_cpu->cycles);
g_display->debugMsg(buf); g_display->debugMsg(debugBuf);
break; break;
case D_SHOWTIME: case D_SHOWTIME:
sprintf(buf, "%.2d:%.2d:%.2d", hour(), minute(), second()); sprintf(debugBuf, "%.2d:%.2d:%.2d", hour(), minute(), second());
g_display->debugMsg(buf); g_display->debugMsg(debugBuf);
break; break;
case D_SHOWDSK: case D_SHOWDSK:
{ {
uint8_t sd = ((AppleVM *)g_vm)->disk6->selectedDrive(); uint8_t sd = ((AppleVM *)g_vm)->disk6->selectedDrive();
sprintf(buf, "s %d t %d", sprintf(debugBuf, "s %d t %d",
sd, sd,
((AppleVM *)g_vm)->disk6->headPosition(sd)); ((AppleVM *)g_vm)->disk6->headPosition(sd));
g_display->debugMsg(buf); g_display->debugMsg(debugBuf);
} }
break; break;
} }