mirror of
https://github.com/JorjBauer/aiie.git
synced 2024-11-25 19:31:36 +00:00
threads conversion
This commit is contained in:
parent
a78b4ff203
commit
e1288db403
12
bios.cpp
12
bios.cpp
@ -7,6 +7,7 @@
|
|||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
|
|
||||||
#ifdef TEENSYDUINO
|
#ifdef TEENSYDUINO
|
||||||
|
#include <TeensyThreads.h>
|
||||||
#include "teensy-paddles.h"
|
#include "teensy-paddles.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -147,14 +148,7 @@ bool BIOS::runUntilDone()
|
|||||||
break;
|
break;
|
||||||
case ACT_SPEED:
|
case ACT_SPEED:
|
||||||
currentCPUSpeedIndex++;
|
currentCPUSpeedIndex++;
|
||||||
#ifdef TEENSYDUINO
|
|
||||||
// The Teensy doesn't have any overhead to spare. Allow slowing
|
|
||||||
// down the virtual CPU, but not speeding it up...
|
|
||||||
currentCPUSpeedIndex %= 2;
|
|
||||||
#else
|
|
||||||
// Other variants can support double and quad speeds.
|
|
||||||
currentCPUSpeedIndex %= 4;
|
currentCPUSpeedIndex %= 4;
|
||||||
#endif
|
|
||||||
switch (currentCPUSpeedIndex) {
|
switch (currentCPUSpeedIndex) {
|
||||||
case CPUSPEED_HALF:
|
case CPUSPEED_HALF:
|
||||||
g_speed = 1023000/2;
|
g_speed = 1023000/2;
|
||||||
@ -296,16 +290,18 @@ uint8_t BIOS::GetAction(int8_t selection)
|
|||||||
#ifndef TEENSYDUINO
|
#ifndef TEENSYDUINO
|
||||||
usleep(100)
|
usleep(100)
|
||||||
#endif
|
#endif
|
||||||
|
threads.delay(1);
|
||||||
;
|
;
|
||||||
// Wait for either a keypress or the reset button to be pressed
|
// Wait for either a keypress or the reset button to be pressed
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TEENSYDUINO
|
#ifdef TEENSYDUINO
|
||||||
|
// FIXME: debounce!
|
||||||
if (digitalRead(RESETPIN) == LOW) {
|
if (digitalRead(RESETPIN) == LOW) {
|
||||||
// wait until it's no longer pressed
|
// wait until it's no longer pressed
|
||||||
while (digitalRead(RESETPIN) == HIGH)
|
while (digitalRead(RESETPIN) == HIGH)
|
||||||
;
|
;
|
||||||
delay(100); // wait long enough for it to debounce
|
threads.delay(100); // wait long enough for it to debounce
|
||||||
// then return an exit code
|
// then return an exit code
|
||||||
return ACT_EXIT;
|
return ACT_EXIT;
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,6 @@ VMui *g_ui;
|
|||||||
int8_t g_volume = 15;
|
int8_t g_volume = 15;
|
||||||
uint8_t g_displayType = 3; // FIXME m_perfectcolor
|
uint8_t g_displayType = 3; // FIXME m_perfectcolor
|
||||||
VMRam g_ram;
|
VMRam g_ram;
|
||||||
volatile bool g_inInterrupt = false;
|
|
||||||
volatile uint8_t g_debugMode = D_NONE;
|
volatile uint8_t g_debugMode = D_NONE;
|
||||||
bool g_prioritizeDisplay = false;
|
bool g_prioritizeDisplay = false;
|
||||||
volatile bool g_biosInterrupt = false;
|
volatile bool g_biosInterrupt = false;
|
||||||
|
@ -47,11 +47,14 @@ extern VMui *g_ui;
|
|||||||
extern int8_t g_volume;
|
extern int8_t g_volume;
|
||||||
extern uint8_t g_displayType;
|
extern uint8_t g_displayType;
|
||||||
extern VMRam g_ram;
|
extern VMRam g_ram;
|
||||||
extern volatile bool g_inInterrupt;
|
|
||||||
extern volatile uint8_t g_debugMode;
|
extern volatile uint8_t g_debugMode;
|
||||||
extern bool g_prioritizeDisplay;
|
extern bool g_prioritizeDisplay;
|
||||||
extern volatile bool g_biosInterrupt;
|
extern volatile bool g_biosInterrupt;
|
||||||
extern uint32_t g_speed;
|
extern uint32_t g_speed;
|
||||||
extern bool g_invertPaddleX;
|
extern bool g_invertPaddleX;
|
||||||
extern bool g_invertPaddleY;
|
extern bool g_invertPaddleY;
|
||||||
|
|
||||||
|
#include <TeensyThreads.h>
|
||||||
|
extern Threads::Mutex spi_lock;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <SPI.h>
|
#include <SPI.h>
|
||||||
#include <TimeLib.h>
|
#include <TimeLib.h>
|
||||||
#include <TimerOne.h>
|
#include <TeensyThreads.h>
|
||||||
|
#include <Bounce2.h>
|
||||||
#include "bios.h"
|
#include "bios.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "applevm.h"
|
#include "applevm.h"
|
||||||
@ -26,9 +27,6 @@
|
|||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
#include "teensy-crash.h"
|
#include "teensy-crash.h"
|
||||||
|
|
||||||
uint32_t nextInstructionMicros;
|
|
||||||
uint32_t startMicros;
|
|
||||||
|
|
||||||
BIOS bios;
|
BIOS bios;
|
||||||
|
|
||||||
// How many microseconds per cycle
|
// How many microseconds per cycle
|
||||||
@ -38,6 +36,17 @@ static time_t getTeensy3Time() { return Teensy3Clock.get(); }
|
|||||||
|
|
||||||
TeensyUSB usb;
|
TeensyUSB usb;
|
||||||
|
|
||||||
|
int cpuThreadId;
|
||||||
|
int displayThreadId;
|
||||||
|
int maintenanceThreadId;
|
||||||
|
int biosThreadId = -1;
|
||||||
|
|
||||||
|
Bounce resetButtonDebouncer = Bounce();
|
||||||
|
Threads::Mutex cpulock; // For the BIOS to suspend CPU cleanly
|
||||||
|
Threads::Mutex displaylock; // For the BIOS to shut down the display cleanly
|
||||||
|
|
||||||
|
volatile bool g_writePrefsFromMainLoop = false;
|
||||||
|
|
||||||
void onKeypress(int unicode)
|
void onKeypress(int unicode)
|
||||||
{
|
{
|
||||||
Serial.print("onKeypress:");
|
Serial.print("onKeypress:");
|
||||||
@ -186,24 +195,29 @@ void setup()
|
|||||||
println("Reading prefs");
|
println("Reading prefs");
|
||||||
readPrefs(); // read from eeprom and set anything we need setting
|
readPrefs(); // read from eeprom and set anything we need setting
|
||||||
|
|
||||||
startMicros = nextInstructionMicros = micros();
|
|
||||||
|
|
||||||
// Debugging: insert a disk on startup...
|
// Debugging: insert a disk on startup...
|
||||||
//((AppleVM *)g_vm)->insertDisk(0, "/A2DISKS/UTIL/mock2dem.dsk", false);
|
//((AppleVM *)g_vm)->insertDisk(0, "/A2DISKS/UTIL/mock2dem.dsk", false);
|
||||||
//((AppleVM *)g_vm)->insertDisk(0, "/A2DISKS/JORJ/disk_s6d1.dsk", false);
|
//((AppleVM *)g_vm)->insertDisk(0, "/A2DISKS/JORJ/disk_s6d1.dsk", false);
|
||||||
// ((AppleVM *)g_vm)->insertDisk(0, "/A2DISKS/GAMES/ALIBABA.DSK", false);
|
// ((AppleVM *)g_vm)->insertDisk(0, "/A2DISKS/GAMES/ALIBABA.DSK", false);
|
||||||
|
|
||||||
// pinMode(56, OUTPUT);
|
|
||||||
// pinMode(57, OUTPUT);
|
|
||||||
|
|
||||||
Serial.print("Free RAM: ");
|
Serial.print("Free RAM: ");
|
||||||
println(FreeRamEstimate());
|
println(FreeRamEstimate());
|
||||||
|
|
||||||
|
resetButtonDebouncer.attach(RESETPIN);
|
||||||
|
resetButtonDebouncer.interval(5); // ms
|
||||||
|
|
||||||
println("free-running");
|
println("free-running");
|
||||||
|
|
||||||
Timer1.initialize(3);
|
threads.setMicroTimer(); // use a 100uS timer instead of a 1mS timer
|
||||||
Timer1.attachInterrupt(runCPU);
|
cpuThreadId = threads.addThread(runCPU);
|
||||||
Timer1.start();
|
displayThreadId = threads.addThread(runDisplay);
|
||||||
|
maintenanceThreadId = threads.addThread(runMaintenance);
|
||||||
|
// Set the relative priorities of the threads by defining how long a "slice"
|
||||||
|
// is for each (in 100uS "ticks")
|
||||||
|
// At a ratio of 50:10:1, we get about 30FPS and 100% CPU speed.
|
||||||
|
threads.setTimeSlice(displayThreadId, 100);
|
||||||
|
threads.setTimeSlice(cpuThreadId, 20);
|
||||||
|
threads.setTimeSlice(maintenanceThreadId, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: move these memory-related functions elsewhere...
|
// FIXME: move these memory-related functions elsewhere...
|
||||||
@ -234,117 +248,89 @@ int heapSize(){
|
|||||||
|
|
||||||
void biosInterrupt()
|
void biosInterrupt()
|
||||||
{
|
{
|
||||||
Timer1.stop();
|
// Make sure the CPU and display don't run while we're in interrupt.
|
||||||
|
Threads::Scope lock1(cpulock);
|
||||||
|
Threads::Scope lock2(displaylock);
|
||||||
|
|
||||||
|
Serial.println("Waiting for button to be released");
|
||||||
// wait for the interrupt button to be released
|
// wait for the interrupt button to be released
|
||||||
while (digitalRead(RESETPIN) == LOW)
|
while (!resetButtonDebouncer.read())
|
||||||
;
|
;
|
||||||
|
|
||||||
|
Serial.println("Invoking BIOS");
|
||||||
// invoke the BIOS
|
// invoke the BIOS
|
||||||
if (bios.runUntilDone()) {
|
if (bios.runUntilDone()) {
|
||||||
// if it returned true, we have something to store persistently in EEPROM.
|
// if it returned true, we have something to store persistently in EEPROM.
|
||||||
writePrefs();
|
// The EEPROM doesn't like to be written to from a thread?
|
||||||
|
Serial.println("Writing prefs");
|
||||||
|
g_writePrefsFromMainLoop = true;
|
||||||
|
while (g_writePrefsFromMainLoop) {
|
||||||
|
Serial.println("Waiting for prefs to be written");
|
||||||
|
delay(100);
|
||||||
|
// wait for write to complete
|
||||||
|
}
|
||||||
// Also might have changed the paddles state
|
// Also might have changed the paddles state
|
||||||
|
Serial.println("Updating paddle state");
|
||||||
TeensyPaddles *tmp = (TeensyPaddles *)g_paddles;
|
TeensyPaddles *tmp = (TeensyPaddles *)g_paddles;
|
||||||
tmp->setRev(g_invertPaddleX, g_invertPaddleY);
|
tmp->setRev(g_invertPaddleX, g_invertPaddleY);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Serial.println("Cleaning up");
|
||||||
// if we turned off debugMode, make sure to clear the debugMsg
|
// if we turned off debugMode, make sure to clear the debugMsg
|
||||||
if (g_debugMode == D_NONE) {
|
if (g_debugMode == D_NONE) {
|
||||||
g_display->debugMsg("");
|
g_display->debugMsg("");
|
||||||
}
|
}
|
||||||
|
|
||||||
// clear the CPU next-step counters
|
// clear the CPU next-step counters
|
||||||
|
#if 0
|
||||||
|
// FIXME: this is to prevent the CPU from racing to catch up, and we need sth in the threads world
|
||||||
g_cpu->cycles = 0;
|
g_cpu->cycles = 0;
|
||||||
nextInstructionMicros = micros();
|
nextInstructionMicros = micros();
|
||||||
startMicros = micros();
|
startMicros = micros();
|
||||||
|
#endif
|
||||||
// Drain the speaker queue (FIXME: a little hacky)
|
// Drain the speaker queue (FIXME: a little hacky)
|
||||||
g_speaker->maintainSpeaker(-1, -1);
|
g_speaker->maintainSpeaker(-1, -1);
|
||||||
|
|
||||||
|
Serial.println("Forcing display redraw");
|
||||||
// Force the display to redraw
|
// Force the display to redraw
|
||||||
g_display->redraw(); // Redraw the UI
|
g_display->redraw(); // Redraw the UI
|
||||||
((AppleDisplay*)(g_vm->vmdisplay))->modeChange(); // force a full re-draw and blit
|
((AppleDisplay*)(g_vm->vmdisplay))->modeChange(); // force a full re-draw and blit
|
||||||
|
|
||||||
|
Serial.println("re-priming keyboard");
|
||||||
// Poll the keyboard before we start, so we can do selftest on startup
|
// Poll the keyboard before we start, so we can do selftest on startup
|
||||||
g_keyboard->maintainKeyboard();
|
g_keyboard->maintainKeyboard();
|
||||||
|
|
||||||
Timer1.start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//bool debugState = false;
|
//bool debugState = false;
|
||||||
//bool debugLCDState = false;
|
//bool debugLCDState = false;
|
||||||
|
|
||||||
|
// FIXME: how often does this really need to run? We can threads.yield() when we're running too quickly
|
||||||
void runCPU()
|
void runMaintenance()
|
||||||
{
|
{
|
||||||
g_inInterrupt = true;
|
uint32_t nextRuntime = 0;
|
||||||
// Debugging: to watch when the speaker is triggered...
|
|
||||||
// static bool debugState = false;
|
|
||||||
// debugState = !debugState;
|
|
||||||
// digitalWrite(56, debugState);
|
|
||||||
|
|
||||||
// Relatively critical timing: CPU needs to run ahead at least 4
|
while (1) {
|
||||||
// cycles, b/c we're calling this interrupt (runCPU, that is) just
|
if (millis() > nextRuntime) {
|
||||||
// about 1/3 as fast as we should; and the speaker is updated
|
nextRuntime = millis() + 100; // FIXME: what's a good time here
|
||||||
// directly from within it, so it needs to be real-ish time.
|
|
||||||
if (micros() > nextInstructionMicros) {
|
|
||||||
// Debugging: to watch when the CPU is triggered...
|
|
||||||
// static bool debugState = false;
|
|
||||||
// debugState = !debugState;
|
|
||||||
// digitalWrite(56, debugState);
|
|
||||||
|
|
||||||
uint8_t executed = g_cpu->Run(24);
|
if (biosThreadId == -1) {
|
||||||
|
// bios is not running; see if it should be
|
||||||
// The CPU of the Apple //e ran at 1.023 MHz. Adjust when we think
|
if (!resetButtonDebouncer.read()) {
|
||||||
// the next instruction should run based on how long the execution
|
|
||||||
// was ((1000/1023) * numberOfCycles) - which is about 97.8%.
|
|
||||||
nextInstructionMicros = startMicros + ((double)g_cpu->cycles * (double)SPEEDCTL);
|
|
||||||
|
|
||||||
((AppleVM *)g_vm)->cpuMaintenance(g_cpu->cycles);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_inInterrupt = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop()
|
|
||||||
{
|
|
||||||
if (digitalRead(RESETPIN) == LOW) {
|
|
||||||
// This is the BIOS interrupt. We immediately act on it.
|
// This is the BIOS interrupt. We immediately act on it.
|
||||||
biosInterrupt();
|
|
||||||
|
biosThreadId = threads.addThread(biosInterrupt);
|
||||||
|
}
|
||||||
|
} else if (threads.getState(biosThreadId) != Threads::RUNNING) {
|
||||||
|
// When the BIOS thread exits, we clean up
|
||||||
|
Serial.println("Cleaing up bios thread");
|
||||||
|
threads.wait(biosThreadId);
|
||||||
|
Serial.println("BIOS thread is cleaned");
|
||||||
|
biosThreadId = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_keyboard->maintainKeyboard();
|
g_keyboard->maintainKeyboard();
|
||||||
usb.maintain();
|
usb.maintain();
|
||||||
|
|
||||||
//debugLCDState = !debugLCDState;
|
|
||||||
//digitalWrite(57, debugLCDState);
|
|
||||||
|
|
||||||
doDebugging();
|
|
||||||
|
|
||||||
// FIXME: this is sometimes *VERY* slow.
|
|
||||||
uint32_t startDisp = millis();
|
|
||||||
uint32_t cpuBefore = g_cpu->cycles;
|
|
||||||
g_ui->blit();
|
|
||||||
g_vm->vmdisplay->lockDisplay();
|
|
||||||
if (g_vm->vmdisplay->needsRedraw()) { // necessary for the VM to redraw
|
|
||||||
// Used to get the dirty rect and blit just that rect. Could still do,
|
|
||||||
// but instead, I'm just wildly wasting resources. MWAHAHAHA
|
|
||||||
// AiieRect what = g_vm->vmdisplay->getDirtyRect();
|
|
||||||
g_vm->vmdisplay->didRedraw();
|
|
||||||
// g_display->blit(what);
|
|
||||||
}
|
|
||||||
g_display->blit(); // Blit the whole thing, including UI area
|
|
||||||
g_vm->vmdisplay->unlockDisplay();
|
|
||||||
uint32_t dispTime = millis() - startDisp;
|
|
||||||
uint32_t cpuAfter = g_cpu->cycles;
|
|
||||||
if (dispTime > 30) {
|
|
||||||
Serial.print("Slow blit: ");
|
|
||||||
Serial.print(dispTime);
|
|
||||||
Serial.print(" cpu ran: ");
|
|
||||||
Serial.println(cpuAfter - cpuBefore);
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned long nextBattCheck = millis() + 30;// debugging
|
static unsigned long nextBattCheck = millis() + 30;// debugging
|
||||||
static int batteryLevel = 0; // static for debugging code! When done
|
static int batteryLevel = 0; // static for debugging code! When done
|
||||||
// debugging, this can become a local
|
// debugging, this can become a local
|
||||||
@ -372,7 +358,7 @@ void loop()
|
|||||||
* 3.46v = 144 - 146
|
* 3.46v = 144 - 146
|
||||||
* 4.21v = 172
|
* 4.21v = 172
|
||||||
*/
|
*/
|
||||||
#if 1
|
#if 0
|
||||||
Serial.print("battery: ");
|
Serial.print("battery: ");
|
||||||
println(batteryLevel);
|
println(batteryLevel);
|
||||||
#endif
|
#endif
|
||||||
@ -385,6 +371,107 @@ void loop()
|
|||||||
batteryLevel = map(batteryLevel, 146, 168, 0, 100);
|
batteryLevel = map(batteryLevel, 146, 168, 0, 100);
|
||||||
g_ui->drawPercentageUIElement(UIePowerPercentage, batteryLevel);
|
g_ui->drawPercentageUIElement(UIePowerPercentage, batteryLevel);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
threads.delay(10);
|
||||||
|
// threads.yield();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: figure out how to limit this to 30 FPS (or whatver) so we can
|
||||||
|
// appropriately use threads.yield()
|
||||||
|
void runDisplay()
|
||||||
|
{
|
||||||
|
while (1) {
|
||||||
|
{
|
||||||
|
Threads::Scope lock(displaylock);
|
||||||
|
doDebugging();
|
||||||
|
|
||||||
|
// FIXME: this is sometimes *VERY* slow.
|
||||||
|
uint32_t startDisp = millis();
|
||||||
|
uint32_t cpuBefore = g_cpu->cycles;
|
||||||
|
g_ui->blit();
|
||||||
|
g_vm->vmdisplay->lockDisplay();
|
||||||
|
if (g_vm->vmdisplay->needsRedraw()) { // necessary for the VM to redraw
|
||||||
|
// Used to get the dirty rect and blit just that rect. Could still do,
|
||||||
|
// but instead, I'm just wildly wasting resources. MWAHAHAHA
|
||||||
|
// AiieRect what = g_vm->vmdisplay->getDirtyRect();
|
||||||
|
g_vm->vmdisplay->didRedraw();
|
||||||
|
// g_display->blit(what);
|
||||||
|
}
|
||||||
|
g_display->blit(); // Blit the whole thing, including UI area
|
||||||
|
g_vm->vmdisplay->unlockDisplay();
|
||||||
|
uint32_t dispTime = millis() - startDisp;
|
||||||
|
uint32_t cpuAfter = g_cpu->cycles;
|
||||||
|
if (dispTime > 75) {
|
||||||
|
Serial.print("Slow blit: ");
|
||||||
|
Serial.print(dispTime);
|
||||||
|
Serial.print(" cpu ran: ");
|
||||||
|
Serial.println(cpuAfter - cpuBefore);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void runCPU()
|
||||||
|
{
|
||||||
|
uint32_t nextInstructionMicros;
|
||||||
|
uint32_t startMicros;
|
||||||
|
startMicros = nextInstructionMicros = micros();
|
||||||
|
|
||||||
|
uint32_t startMillis = millis();
|
||||||
|
|
||||||
|
Serial.println("CPU thread is started");
|
||||||
|
while (1) {
|
||||||
|
// Relatively critical timing: CPU needs to run ahead at least 4
|
||||||
|
// cycles, b/c we're calling this interrupt (runCPU, that is) just
|
||||||
|
// about 1/3 as fast as we should; and the speaker is updated
|
||||||
|
// directly from within it, so it needs to be real-ish time.
|
||||||
|
if (micros() >= nextInstructionMicros) {
|
||||||
|
uint32_t expectedCycles = (micros() - startMicros) * SPEEDCTL;
|
||||||
|
|
||||||
|
uint8_t executed;
|
||||||
|
cpulock.lock(); // Blocking; if the BIOS is running, we stall here
|
||||||
|
executed = g_cpu->Run(24);
|
||||||
|
cpulock.unlock();
|
||||||
|
|
||||||
|
// The CPU of the Apple //e ran at 1.023 MHz. Adjust when we think
|
||||||
|
// the next instruction should run based on how long the execution
|
||||||
|
// was ((1000/1023) * numberOfCycles) - which is about 97.8%.
|
||||||
|
if (expectedCycles > g_cpu->cycles) {
|
||||||
|
nextInstructionMicros = micros();
|
||||||
|
#if 0
|
||||||
|
// show a warning on serial about our current performance
|
||||||
|
double percentage = ((double)g_cpu->cycles / (double)expectedCycles) * 100.0;
|
||||||
|
static uint32_t nextWarningTime = 0;
|
||||||
|
if (millis() > nextWarningTime) {
|
||||||
|
static char buf[100];
|
||||||
|
sprintf(buf, "CPU running at %f%% of %d", percentage, g_speed);
|
||||||
|
Serial.println(buf);
|
||||||
|
nextWarningTime = millis() + 1000;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
nextInstructionMicros = startMicros + ((double)g_cpu->cycles * (double)SPEEDCTL);
|
||||||
|
}
|
||||||
|
|
||||||
|
((AppleVM *)g_vm)->cpuMaintenance(g_cpu->cycles);
|
||||||
|
} else {
|
||||||
|
// threads.yield();
|
||||||
|
threads.delay(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
resetButtonDebouncer.update();
|
||||||
|
|
||||||
|
if (g_writePrefsFromMainLoop) {
|
||||||
|
Serial.println("Writing prefs");
|
||||||
|
writePrefs();
|
||||||
|
g_writePrefsFromMainLoop = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void doDebugging()
|
void doDebugging()
|
||||||
@ -481,10 +568,7 @@ void writePrefs()
|
|||||||
TeensyPrefs np;
|
TeensyPrefs np;
|
||||||
prefs_t p;
|
prefs_t p;
|
||||||
|
|
||||||
g_display->clrScr();
|
Serial.println("writePrefs()");
|
||||||
g_display->drawString(M_SELECTED, 80, 100,"Writing prefs...");
|
|
||||||
g_display->flush();
|
|
||||||
|
|
||||||
p.magic = PREFSMAGIC;
|
p.magic = PREFSMAGIC;
|
||||||
p.prefsSize = sizeof(prefs_t);
|
p.prefsSize = sizeof(prefs_t);
|
||||||
p.version = PREFSVERSION;
|
p.version = PREFSVERSION;
|
||||||
@ -502,7 +586,5 @@ void writePrefs()
|
|||||||
strcpy(p.hd1, ((AppleVM *)g_vm)->HDName(0));
|
strcpy(p.hd1, ((AppleVM *)g_vm)->HDName(0));
|
||||||
strcpy(p.hd2, ((AppleVM *)g_vm)->HDName(1));
|
strcpy(p.hd2, ((AppleVM *)g_vm)->HDName(1));
|
||||||
|
|
||||||
Timer1.stop();
|
|
||||||
bool ret = np.writePrefs(&p);
|
bool ret = np.writePrefs(&p);
|
||||||
Timer1.start();
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user