mirror of https://github.com/JorjBauer/aiie.git
common debugging buffer (fix some memory overruns); consistent timing improvements
This commit is contained in:
parent
816c38209c
commit
fb7a64a22f
|
@ -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];
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue