diff options
-rw-r--r-- | Cart_Reader/Cart_Reader.ino | 268 | ||||
-rw-r--r-- | Cart_Reader/Config.h | 79 | ||||
-rw-r--r-- | Cart_Reader/MD.ino | 30 | ||||
-rw-r--r-- | Cart_Reader/OSCR.cpp | 188 | ||||
-rw-r--r-- | Cart_Reader/OSCR.h | 34 | ||||
-rw-r--r-- | sd/config.txt | 6 |
6 files changed, 470 insertions, 135 deletions
diff --git a/Cart_Reader/Cart_Reader.ino b/Cart_Reader/Cart_Reader.ino index 11b4940..28eeb48 100644 --- a/Cart_Reader/Cart_Reader.ino +++ b/Cart_Reader/Cart_Reader.ino @@ -66,7 +66,6 @@ *****************************************/
// SD Card
-#include "SdFat.h"
SdFs sd;
FsFile myFile;
#ifdef global_log
@@ -2117,83 +2116,92 @@ int32_t initializeClockOffset() { Setup
*****************************************/
void setup() {
-#if !defined(enable_serial) && defined(ENABLE_UPDATER)
- ClockedSerial.begin(UPD_BAUD);
-#endif
-
// Set Button Pin PG2 to Input
DDRG &= ~(1 << 2);
-#if defined(HW5) && !defined(ENABLE_VSELECT)
- // HW5 has status LED connected to PD7
- // Set LED Pin PD7 to Output
+# if defined(HW5) && !defined(ENABLE_VSELECT)
+ /**
+ * HW5 has status LED connected to PD7
+ * Set LED Pin PD7 to Output
+ **/
DDRD |= (1 << 7);
PORTD |= (1 << 7);
-#elif defined(ENABLE_VSELECT)
+# elif defined(ENABLE_VSELECT)
+ /**
+ * VSELECT uses pin PD7
+ * Set LED Pin PD7 to Output
+ **/
DDRD |= (1 << 7);
-#else
- // HW1/2/3 have button connected to PD7
- // Set Button Pin PD7 to Input
+# else /* !defined(HW5) && !defined(HW5) */
+ /**
+ * HW1-3 have button connected to PD7
+ * Set pin PD7 to input for button
+ **/
DDRD &= ~(1 << 7);
-#endif
- // Activate Internal Pullup Resistors
- //PORTG |= (1 << 2);
- //PORTD |= (1 << 7);
+# endif /* HW5 &| ENABLE_VSELECT */
+
+ // Set power to low to protect carts
+ setVoltage(VOLTS_SET_3V3);
+
+# if defined(ENABLE_3V3FIX)
+ // Set clock high during setup
+ setClockScale(CLKSCALE_16MHZ);
+ delay(10);
+# endif /* ENABLE_3V3FIX */
+# if !defined(enable_serial) && defined(ENABLE_UPDATER)
+ ClockedSerial.begin(UPD_BAUD);
+ printVersionToSerial();
+ ClockedSerial.flush();
+# endif /* ENABLE_UPDATER */
- // Read current folder number out of eeprom
+ // Read current folder number out of the EEPROM
EEPROM_readAnything(0, foldern);
if (foldern < 0) foldern = 0;
-#ifdef enable_LCD
+# ifdef enable_LCD
display.begin();
display.setContrast(40);
display.setFont(u8g2_font_haxrcorp4089_tr);
-#endif
+# endif /* enable_LCD */
-#ifdef enable_neopixel
-#if defined(ENABLE_3V3FIX)
- // Set power high for neopixel
- setVoltage(VOLTS_SET_5V);
- delay(10);
-#endif
+# ifdef enable_neopixel
pixels.begin();
- pixels.clear();
- pixels.setPixelColor(0, pixels.Color(background_color));
- pixels.setPixelColor(1, pixels.Color(0, 0, 100));
- pixels.setPixelColor(2, pixels.Color(0, 0, 100));
- pixels.show();
+ setColor_RGB(0, 0, 100);
// Set TX0 LED Pin(PE1) to Output for status indication during flashing for HW4
-#if !(defined(enable_serial) || defined(HW5))
+# if !(defined(enable_serial) || defined(HW5))
DDRE |= (1 << 1);
-#endif
-#else
-#ifndef enable_LCD
-#ifdef CA_LED
+# endif /* enable_serial */
+# else /* enable_neopixel */
+# ifndef enable_LCD
+# ifdef CA_LED
// Turn LED off
digitalWrite(12, 1);
digitalWrite(11, 1);
digitalWrite(10, 1);
-#endif
+# endif /* CA_LED */
// Configure 4 Pin RGB LED pins as output
DDRB |= (1 << DDB6); // Red LED (pin 12)
DDRB |= (1 << DDB5); // Green LED (pin 11)
DDRB |= (1 << DDB4); // Blue LED (pin 10)
-#endif
-#endif
+# endif /* enable_LCD */
+# endif /* enable_neopixel */
-#ifdef ENABLE_VSELECT
- // Set power to low to protect carts
- setVoltage(VOLTS_SET_3V3);
-#endif
+# ifdef RTC_installed
+ // Start RTC
+ RTCStart();
-#ifdef enable_OLED
+ // Set Date/Time Callback Funtion
+ SdFile::dateTimeCallback(dateTime);
+# endif /* RTC_installed */
+
+# ifdef enable_OLED
display.begin();
//isplay.setContrast(40);
display.setFont(u8g2_font_haxrcorp4089_tr);
-#endif
+# endif /* enable_OLED */
-#ifdef enable_serial
+# ifdef enable_serial
// Serial Begin
Serial.begin(9600);
Serial.println("");
@@ -2201,52 +2209,73 @@ void setup() { Serial.println(F("2023 github.com/sanni"));
// LED Error
setColor_RGB(0, 0, 255);
-#endif
+# endif /* enable_serial */
// Init SD card
if (!sd.begin(SS)) {
display_Clear();
+# ifdef ENABLE_VSELECT
+ print_STR(sd_error_STR, 1);
+ println_Msg(F(""));
+ println_Msg(F("Press button to enable 5V for"));
+ println_Msg(F(" updating firmware..."));
+ display_Update();
+ wait();
+ display_Clear();
+ setVoltage(VOLTS_SET_5V); // Set voltage high for flashing
+ println_Msg(F(" ======== UPDATE MODE ======== "));
+ println_Msg(F("Waiting for update..."));
+ println_Msg(F(""));
+ println_Msg(F("Press button to cancel/restart."));
+ display_Update();
+ wait();
+ resetArduino();
+# else /* !ENABLE_VSELECT */
print_FatalError(sd_error_STR);
+# endif /* ENABLE_VSELECT */
}
-#if !defined(enable_serial) && defined(ENABLE_UPDATER)
- printVersionToSerial();
- ClockedSerial.flush();
-#endif
+# if defined(ENABLE_CONFIG)
+ configInit();
+# if defined(global_log)
+ loggingEnabled = !!configGetLong(F("oscr.logging"), 1);
+# endif /*ENABLE_CONFIG*/
-#ifdef global_log
+ // Change LCD background if config specified
+# ifdef enable_neopixel
+ setColor_RGB(0, 0, 100);
+# endif /* enable_neopixel */
+# endif /* ENABLE_CONFIG */
+
+# ifdef global_log
if (!myLog.open("OSCR_LOG.txt", O_RDWR | O_CREAT | O_APPEND)) {
print_FatalError(sd_error_STR);
}
println_Msg(F(""));
-#if defined(HW1)
+# if defined(HW1)
print_Msg(F("OSCR HW1"));
-#elif defined(HW2)
+# elif defined(HW2)
print_Msg(F("OSCR HW2"));
-#elif defined(HW3)
+# elif defined(HW3)
print_Msg(F("OSCR HW3"));
-#elif defined(HW4)
+# elif defined(HW4)
print_Msg(F("OSCR HW4"));
-#elif defined(HW5)
+# elif defined(HW5)
print_Msg(F("OSCR HW5"));
-#elif defined(SERIAL_MONITOR)
+# elif defined(SERIAL_MONITOR)
print_Msg(F("OSCR Serial"));
-#endif
+# endif /* HWn */
print_Msg(F(" V"));
println_Msg(ver);
-#endif
+# endif /* global_log */
-#ifdef RTC_installed
- // Start RTC
- RTCStart();
-
- // Set Date/Time Callback Funtion
- SdFile::dateTimeCallback(dateTime);
-#endif
-
- // status LED ON
+ // Turn status LED on
statusLED(true);
+# if defined(ENABLE_3V3FIX)
+ setClockScale(CLKSCALE_8MHZ); // Set clock back to low after setup
+# endif /* ENABLE_3V3FIX */
+
// Start menu system
mainMenu();
}
@@ -2273,15 +2302,31 @@ void dataIn() { // Set RGB color
void setColor_RGB(byte r, byte g, byte b) {
#if defined(enable_neopixel)
-#if defined(ENABLE_3V3FIX)
+# if defined(ENABLE_3V3FIX)
if (clock == CS_8MHZ) return;
-#endif
+# endif
// Dim Neopixel LEDs
if (r >= 100) r = 100;
if (g >= 100) g = 100;
if (b >= 100) b = 100;
+
pixels.clear();
+
+# if defined(ENABLE_CONFIG)
+ uint8_t lcdConfColor = configGetLong(F("lcd.confColor"));
+
+ if (lcdConfColor > 0) {
+ uint8_t lcdRed = configGetLong(F("lcd.red"));
+ uint8_t lcdGreen = configGetLong(F("lcd.green"));
+ uint8_t lcdBlue = configGetLong(F("lcd.blue"));
+
+ pixels.setPixelColor(0, pixels.Color(lcdGreen, lcdRed, lcdBlue));
+ } else {
+ pixels.setPixelColor(0, pixels.Color(background_color));
+ }
+# else /* !ENABLE_CONFIG */
pixels.setPixelColor(0, pixels.Color(background_color));
+# endif /* ENABLE_CONFIG */
pixels.setPixelColor(1, pixels.Color(g, r, b));
pixels.setPixelColor(2, pixels.Color(g, r, b));
pixels.show();
@@ -2465,7 +2510,7 @@ void print_Msg(const __FlashStringHelper* string) { Serial.print(string);
#endif
#ifdef global_log
- if (!dont_log) myLog.print(string);
+ if (!dont_log && loggingEnabled) myLog.print(string);
#endif
}
@@ -2494,7 +2539,7 @@ void print_Msg(const char myString[]) { Serial.print(myString);
#endif
#ifdef global_log
- if (!dont_log) myLog.print(myString);
+ if (!dont_log && loggingEnabled) myLog.print(myString);
#endif
}
@@ -2506,7 +2551,7 @@ void print_Msg(long unsigned int message) { Serial.print(message);
#endif
#ifdef global_log
- if (!dont_log) myLog.print(message);
+ if (!dont_log && loggingEnabled) myLog.print(message);
#endif
}
@@ -2518,7 +2563,7 @@ void print_Msg(byte message, int outputFormat) { Serial.print(message, outputFormat);
#endif
#ifdef global_log
- if (!dont_log) myLog.print(message, outputFormat);
+ if (!dont_log && loggingEnabled) myLog.print(message, outputFormat);
#endif
}
@@ -2530,7 +2575,7 @@ void print_Msg(word message, int outputFormat) { Serial.print(message, outputFormat);
#endif
#ifdef global_log
- if (!dont_log) myLog.print(message, outputFormat);
+ if (!dont_log && loggingEnabled) myLog.print(message, outputFormat);
#endif
}
@@ -2542,7 +2587,7 @@ void print_Msg(int message, int outputFormat) { Serial.print(message, outputFormat);
#endif
#ifdef global_log
- if (!dont_log) myLog.print(message, outputFormat);
+ if (!dont_log && loggingEnabled) myLog.print(message, outputFormat);
#endif
}
@@ -2554,7 +2599,7 @@ void print_Msg(long unsigned int message, int outputFormat) { Serial.print(message, outputFormat);
#endif
#ifdef global_log
- if (!dont_log) myLog.print(message, outputFormat);
+ if (!dont_log && loggingEnabled) myLog.print(message, outputFormat);
#endif
}
@@ -2566,7 +2611,7 @@ void print_Msg(String string) { Serial.print(string);
#endif
#ifdef global_log
- if (!dont_log) myLog.print(string);
+ if (!dont_log && loggingEnabled) myLog.print(string);
#endif
}
@@ -2595,7 +2640,7 @@ void println_Msg(String string) { Serial.println(string);
#endif
#ifdef global_log
- if (!dont_log) myLog.println(string);
+ if (!dont_log && loggingEnabled) myLog.println(string);
#endif
}
@@ -2608,7 +2653,7 @@ void println_Msg(byte message, int outputFormat) { Serial.println(message, outputFormat);
#endif
#ifdef global_log
- if (!dont_log) myLog.println(message, outputFormat);
+ if (!dont_log && loggingEnabled) myLog.println(message, outputFormat);
#endif
}
@@ -2638,7 +2683,7 @@ void println_Msg(const char myString[]) { Serial.println(myString);
#endif
#ifdef global_log
- if (!dont_log) myLog.println(myString);
+ if (!dont_log && loggingEnabled) myLog.println(myString);
#endif
}
@@ -2654,7 +2699,7 @@ void println_Msg(const __FlashStringHelper* string) { char myBuffer[15];
strlcpy_P(myBuffer, (char*)string, 15);
if ((strncmp(myBuffer, "Press Button...", 14) != 0) && (strncmp(myBuffer, "Select file", 10) != 0)) {
- if (!dont_log) myLog.println(string);
+ if (!dont_log && loggingEnabled) myLog.println(string);
}
#endif
}
@@ -2668,7 +2713,7 @@ void println_Msg(long unsigned int message) { Serial.println(message);
#endif
#ifdef global_log
- if (!dont_log) myLog.println(message);
+ if (!dont_log && loggingEnabled) myLog.println(message);
#endif
}
@@ -2680,7 +2725,7 @@ void display_Update() { delay(100);
#endif
#ifdef global_log
- if (!dont_log) myLog.flush();
+ if (!dont_log && loggingEnabled) myLog.flush();
#endif
}
@@ -2690,7 +2735,7 @@ void display_Clear() { display.setCursor(0, 8);
#endif
#ifdef global_log
- if (!dont_log) myLog.println("");
+ if (!dont_log && loggingEnabled) myLog.println("");
#endif
}
@@ -2980,41 +3025,50 @@ void checkUpdater() { if (ClockedSerial.available() > 0) {
String cmd = ClockedSerial.readStringUntil('\n');
cmd.trim();
- if (cmd == "VERCHK") {
+ if (cmd == "VERCHK")
+ { // VERCHK: Gets OSCR version and features
delay(500);
printVersionToSerial();
- } else if (cmd == "GETCLOCK") {
-#if defined(ENABLE_3V3FIX)
+ }
+ else if (cmd == "GETCLOCK")
+ { // GETCLOCK: Gets the MEGA's current clock speed.
+# if defined(ENABLE_3V3FIX)
ClockedSerial.print(F("Clock is running at "));
ClockedSerial.print((clock == CS_16MHZ) ? 16UL : 8UL);
ClockedSerial.println(F("MHz"));
-#else
+# else /* !ENABLE_3V3FIX */
ClockedSerial.println(F("Dynamic clock speed (3V3FIX) is not enabled."));
-#endif
- } else if (cmd == "GETVOLTS") {
-#if defined(ENABLE_VSELECT)
+# endif /* ENABLE_3V3FIX */
+ }
+ else if (cmd.substring(1, 8) == "ETVOLTS")
+ { // (G/S)ETVOLTS: Get and set the voltage.
+# if defined(ENABLE_VSELECT)
+ if (cmd != "GETVOLTS") {
+ switch(cmd.substring(9, 10).toInt()) {
+ case 3: setVoltage(VOLTS_SET_3V3); break;
+ case 5: setVoltage(VOLTS_SET_5V); break;
+ }
+ }
ClockedSerial.print(F("Voltage is set to "));
ClockedSerial.print((voltage == VOLTS_SET_5V) ? 5 : 3.3);
ClockedSerial.println(F("V"));
-#else
+# else /* !ENABLE_VSELECT */
ClockedSerial.println(F("Automatic voltage selection (VSELECT) is not enabled."));
-#endif
- } else if (cmd == "GETTIME") {
-#if defined(RTC_installed)
- ClockedSerial.print(F("Current Time: "));
- ClockedSerial.println(RTCStamp());
-#else
- ClockedSerial.println(F("RTC not installed"));
-#endif
- } else if (cmd.substring(0, 7) == "SETTIME") {
-#if defined(RTC_installed)
- ClockedSerial.println(F("Setting Time..."));
- rtc.adjust(DateTime(cmd.substring(8).toInt()));
+# endif /* ENABLE_VSELECT */
+ }
+ // RTC commands
+ else if (cmd.substring(1, 7) == "ETTIME")
+ { // (G/S)ETTIME: Get and set the date/time.
+# if defined(RTC_installed)
+ if (cmd != "GETTIME") {
+ ClockedSerial.println(F("Setting Time..."));
+ rtc.adjust(DateTime(cmd.substring(8).toInt()));
+ }
ClockedSerial.print(F("Current Time: "));
ClockedSerial.println(RTCStamp());
-#else
+# else /* !RTC_installed */
ClockedSerial.println(F("RTC not installed"));
-#endif
+# endif /* RTC_installed */
} else {
ClockedSerial.println(F("OSCR: Unknown Command"));
}
diff --git a/Cart_Reader/Config.h b/Cart_Reader/Config.h index 68080a9..47dce28 100644 --- a/Cart_Reader/Config.h +++ b/Cart_Reader/Config.h @@ -288,9 +288,30 @@ /*==== FIRMWARE OPTIONS ===========================================*/ +/* [ Config File -------------------------------------------------- ] + Allow changing some configuration values via a config file. You + generally can only use the config to set options or disable + certain featuress. It cannot be used to toggle firmware options + on, only off. + + Note For Developers: See OSCR.* for info. + + Filename: config.txt +*/ + +//#define ENABLE_CONFIG + +/****/ + /* [ LCD: Background Color ---------------------------------------- ] Set the backlight color of the LCD if you have one. + Can be set using config: + lcd.confColor=1 + lcd.red=0 + lcd.green=0 + lcd.blue=0 + PARAMETERS: Green, Red, Blue */ @@ -332,6 +353,9 @@ /* [ Logging ------------------------------------------------------ ] Write all info to OSCR_LOG.txt in root dir + + Can be toggled off using config: + oscr.logging=0 */ #define global_log @@ -367,13 +391,26 @@ 0: Output each byte once. Not supported by emulators. (default) 1: Duplicate each byte. Usable by Kega Fusion. 2: Same as 1 + pad with 0xFF so that the file size is 64KB. + + ** + ** DEPRECATED: Use the config file instead. See below. + ** */ //#define use_md_conf /* - Alternatively, define it here by uncommenting and changing the - following line. Setting both allows you to change the default. + Configure how the MD core saves are formatted. + + Can be set using config: + md.sramType=0 + + If config is enabled, this option does nothing -- use the config. + + Options: + 0: Output each byte once. Not supported by emulators. (default) + 1: Duplicate each byte. Usable by Kega Fusion. + 2: Same as 1 + pad with 0xFF so that the file size is 64KB. */ //#define DEFAULT_VALUE_segaSram16bit 0 @@ -404,39 +441,47 @@ You probably shouldn't change this stuff! */ +#if defined(ENABLE_CONFIG) +# define CONFIG_FILE "config.txt" +// Define the max length of the key=value pairs +// Do your best not to have to increase these. +# define CONFIG_KEY_MAX 32 +# define CONFIG_VALUE_MAX 32 +#endif + #if (defined(HW4) || defined(HW5)) -#define enable_LCD -#define enable_neopixel -#define enable_rotary -//#define rotate_counter_clockwise -#define clockgen_installed -#define fastcrc -#define ws_adapter_v2 +# define enable_LCD +# define enable_neopixel +# define enable_rotary +//# define rotate_counter_clockwise +# define clockgen_installed +# define fastcrc +# define ws_adapter_v2 #endif #if (defined(HW2) || defined(HW3)) -#define enable_OLED -#define enable_Button2 -#define clockgen_installed -#define CA_LED -#define fastcrc +# define enable_OLED +# define enable_Button2 +# define clockgen_installed +# define CA_LED +# define fastcrc #endif #if defined(HW1) -#define enable_OLED +# define enable_OLED //#define clockgen_installed //#define fastcrc #endif #if defined(SERIAL_MONITOR) -#define enable_serial +# define enable_serial //#define clockgen_installed //#define fastcrc #endif /* Firmware updater only works with HW3 and HW5 */ #if !(defined(HW5) || defined(HW3)) -#undef ENABLE_UPDATER +# undef ENABLE_UPDATER #endif /* End of settings */ diff --git a/Cart_Reader/MD.ino b/Cart_Reader/MD.ino index a5585dc..c6e7f3e 100644 --- a/Cart_Reader/MD.ino +++ b/Cart_Reader/MD.ino @@ -87,11 +87,20 @@ unsigned long bramSize = 0; // REALTEC MAPPER
boolean realtec = 0;
-#ifndef DEFAULT_VALUE_segaSram16bit
-#define DEFAULT_VALUE_segaSram16bit 0
-#endif
+#if defined(ENABLED_CONFIG)
+
+int segaSram16bit = 0;
+
+#else /* !ENABLED_CONFIG */
+
+# ifndef DEFAULT_VALUE_segaSram16bit
+# define DEFAULT_VALUE_segaSram16bit 0
+# endif /* !DEFAULT_VALUE_segaSram16bit */
+
int segaSram16bit = DEFAULT_VALUE_segaSram16bit;
+#endif /* ENABLED_CONFIG */
+
//*****************************************
// SONIC & KNUCKLES LOCK-ON MODE VARIABLES
// SnKmode :
@@ -111,12 +120,15 @@ static word chksumSonic2 = 0x0635; /******************************************
Configuration
*****************************************/
-#ifdef use_md_conf
+#if defined(use_md_conf) && !defined(ENABLE_CONFIG)
+
+#warning "DEPRECATED: use_md_conf is deprecated. You should use ENABLE_CONFIG instead."
+
void mdLoadConf() {
if (myFile.open("mdconf.txt", O_READ)) {
char line[64];
- int n;
- int i;
+ unsigned int n;
+ unsigned int i;
while ((n = myFile.fgets(line, sizeof(line) - 1)) > 0) {
// preprocess
for (i = 0; i < n; i++) {
@@ -467,9 +479,11 @@ void setup_MD() { // Request 5V
setVoltage(VOLTS_SET_5V);
-#ifdef use_md_conf
+#if defined(ENABLE_CONFIG)
+ segaSram16bit = configGetLong(F("md.sramType"));
+#elif defined(use_md_conf)
mdLoadConf();
-#endif
+#endif /*ENABLE_CONFIG*/
// Set Address Pins to Output
//A0-A7
diff --git a/Cart_Reader/OSCR.cpp b/Cart_Reader/OSCR.cpp index 1965180..70b96be 100644 --- a/Cart_Reader/OSCR.cpp +++ b/Cart_Reader/OSCR.cpp @@ -7,7 +7,10 @@ * Contains various enums, variables, etc, for the main program.
*
* PUBLIC FUNCTIONS :
-* void setClockScale( VOLTS )
+* void setClockScale( ClockScale )
+* VOLTS setVoltage( Voltage )
+* long configGetLong( Key, OnFailure )
+* String configGetStr( Key )
*
* NOTES :
* This file is a WIP, I've been moving things into it on my local working
@@ -32,6 +35,7 @@ * CHANGES :
*
* REF NO VERSION DATE WHO DETAIL
+* 13.2 2024-02-29 Ancyker Add config support
* 12.5 2023-03-29 Ancyker Initial version
*
*H*/
@@ -41,7 +45,7 @@ /*==== VARIABLES ==================================================*/
// Firmware Version
-char ver[5] = "13.1";
+char ver[5] = "13.2";
// Clock speed
unsigned long clock = CS_16MHZ;
@@ -49,6 +53,22 @@ unsigned long clock = CS_16MHZ; // Voltage
VOLTS voltage = VOLTS_SET_5V;
+#if defined(ENABLE_CONFIG)
+
+FsFile configFile;
+bool useConfig = false;
+
+# if defined(global_log)
+// Logging
+bool loggingEnabled = true;
+# endif /* global_log */
+#else /* !ENABLE_CONFIG */
+# if defined(global_log)
+// Logging: Define it as true using a const instead.
+const bool loggingEnabled = true;
+# endif /* global_log */
+#endif /* ENABLE_CONFIG */
+
/*==== /VARIABLES =================================================*/
/*F******************************************************************
@@ -107,7 +127,8 @@ void printVersionToSerial() {} *
* INPUTS :
* PARAMETERS:
-* VOLTS ClockScale Clock scale
+* VOLTS ClockScale Clock scale
+* CLKSCALE ClockScale Clock scale
*
* PROCESS :
* [1] Enable clock prescaler change
@@ -139,6 +160,24 @@ void setClockScale(VOLTS __x) ); /*[2]*/
}
+void setClockScale(CLKSCALE __x)
+{
+ clock = (__x == CLKSCALE_16MHZ ? CS_16MHZ : CS_8MHZ);
+ uint8_t __tmp = _BV(CLKPCE); /*[1]*/
+ __asm__ __volatile__ (
+ "in __tmp_reg__,__SREG__" "\n\t"
+ "cli" "\n\t"
+ "sts %1, %0" "\n\t"
+ "sts %1, %2" "\n\t"
+ "out __SREG__, __tmp_reg__"
+ : /* no outputs */
+ : "d" (__tmp),
+ "M" (_SFR_MEM_ADDR(CLKPR)),
+ "d" (__x)
+ : "r0"
+ ); /*[2]*/
+}
+
/*F******************************************************************
* NAME : VOLTS setVoltage( Voltage )
*
@@ -263,3 +302,146 @@ VOLTS setVoltage(VOLTS newVoltage __attribute__((unused))) { return VOLTS_NOTENABLED;
}
#endif
+
+#if defined(ENABLE_CONFIG)
+
+/*F******************************************************************
+* NAME : void configInit()
+*
+* DESCRIPTION : Setup the config file.
+*
+*F*/
+void configInit() {
+ useConfig = configFile.open(CONFIG_FILE, O_READ);
+}
+
+/*F******************************************************************
+* NAME : uint8_t configFindKey( Key, Value )
+*
+* DESCRIPTION : Search for a key=value pair.
+*
+* INPUTS :
+* PARAMETERS:
+* __FlashStringHelper Key The key to get the value for.
+* char* value Variable to store the value in.
+*
+* OUTPUTS :
+* RETURN :
+* Type: uint8_t Length of the value.
+*
+* PROCESS :
+* [1] Get key length and convert to char array/string.
+* [2] Parse file line by line.
+* [3] Check if key in file matches.
+* [4] Copy string after equals character.
+* [5] Add null terminator.
+*
+* NOTES :
+* You aren't meant to use this function directly. Check the
+* functions configGetStr() and configGetLong().
+*
+*F*/
+uint8_t configFindKey(const __FlashStringHelper* searchKey, char* value) {
+ if (!useConfig) return 0;
+
+ char key[CONFIG_KEY_MAX + 1];
+ char buffer[CONFIG_KEY_MAX + CONFIG_VALUE_MAX + 4];
+ int keyLen = 0;
+ int valueLen = 0;
+
+ keyLen = strlcpy_P(key, reinterpret_cast<const char *>(searchKey), CONFIG_KEY_MAX); /*[1]*/
+
+ configFile.rewind();
+
+ while (configFile.available()) { /*[2]*/
+ int bufferLen = configFile.readBytesUntil('\n', buffer, CONFIG_KEY_MAX + CONFIG_VALUE_MAX + 3);
+
+ if (buffer[bufferLen - 1] == '\r')
+ bufferLen--;
+
+ if (bufferLen > (keyLen + 1)) {
+ if (memcmp(buffer, key, keyLen) == 0) { /*[3]*/
+ if (buffer[keyLen] == '=') { /*[4]*/
+ valueLen = bufferLen - keyLen - 1;
+ memcpy(&value[0], &buffer[keyLen + 1], valueLen);
+ value[valueLen] = '\0'; /*[5]*/
+ break;
+ }
+ }
+ }
+ }
+
+ return valueLen;
+}
+
+/*F******************************************************************
+* NAME : String configGetStr( Key )
+*
+* DESCRIPTION : Return the value of a key as a string.
+*
+* INPUTS :
+* PARAMETERS:
+* __FlashStringHelper Key The key to get the value for.
+*
+* OUTPUTS :
+* RETURN :
+* Type: String The value of the key or an empty string.
+*
+* PROCESS :
+* [1] Find the key via configFindKey().
+* [2] Return empty if nothing was found.
+* [3] Convert to String type.
+*
+* NOTES :
+* You can use this to get strings stored in the config file.
+* Take care when allocating memory for strings. You should
+* probably use malloc for it if it's a global variable. If
+* you do, make sure to free() it after it's not needed.
+*
+*F*/
+String configGetStr(const __FlashStringHelper* key) {
+ if (!useConfig) return {};
+ char value[CONFIG_VALUE_MAX + 1];
+
+ uint8_t valueLen = configFindKey(key, value); /*[1]*/
+ if (valueLen < 1) return {}; /*[2]*/
+
+ String stringVal(value); /*[3]*/
+
+ return stringVal;
+}
+
+/*F******************************************************************
+* NAME : long configGetLong( Key, OnFailure )
+*
+* DESCRIPTION : Return the value of a key as an int/long.
+*
+* INPUTS :
+* PARAMETERS:
+* __FlashStringHelper Key The key to get the value for.
+* int onFail Value to return on failure. (def=0)
+*
+* OUTPUTS :
+* RETURN :
+* Type: int The value of the key or onFail.
+*
+* PROCESS :
+* [1] Find the key via configFindKey().
+* [2] Return onFail if nothing was found.
+* [3] Convert to long int type and return.
+*
+* NOTES :
+* You can specify hex, i.e. 0xFF for 255, if you want to.
+*
+*F*/
+long configGetLong(const __FlashStringHelper* key, int onFail) {
+ if (!useConfig) return onFail;
+ char value[CONFIG_VALUE_MAX + 1];
+
+ uint8_t valueLen = configFindKey(key, value); /*[1]*/
+ if (valueLen < 1) return onFail; /*[2]*/
+
+ return strtol(value, NULL, 0); /*[3]*/
+}
+
+#endif /* ENABLE_CONFIG */
diff --git a/Cart_Reader/OSCR.h b/Cart_Reader/OSCR.h index 8b6e350..5bbe99e 100644 --- a/Cart_Reader/OSCR.h +++ b/Cart_Reader/OSCR.h @@ -10,6 +10,7 @@ #include <Wire.h> #include <avr/pgmspace.h> #include <avr/wdt.h> +#include "SdFat.h" #include "Config.h" @@ -30,6 +31,13 @@ const unsigned long CS_16MHZ = 16000000UL; const unsigned long CS_8MHZ = 8000000UL; // ENUM for VSELECT & 3V3FIX +enum CLKSCALE: uint8_t { + // Paramters to pass to setVoltage() and setClockScale() + CLKSCALE_16MHZ = 0, // ClockScale 0 = 16MHz + CLKSCALE_8MHZ, // ClockScale 1 = 8MHz +}; + +// ENUM for VSELECT & 3V3FIX enum VOLTS: uint8_t { // Paramters to pass to setVoltage() and setClockScale() VOLTS_SET_5V = 0, // 5V parameter [ClockScale 0 = 16MHz, Voltage = 5V] @@ -47,11 +55,37 @@ extern unsigned long clock; extern char ver[5]; extern VOLTS voltage; +#if defined(ENABLE_CONFIG) + /** + * Config File Stuff + * + * You can register GLOBAL configuration variables in this section. + * You should put core-specific config variables in the related file. + **/ + + extern bool useConfig; +# ifdef global_log + extern bool loggingEnabled; +# endif /* global_log */ +#else /* !ENABLE_CONFIG */ +# ifdef global_log + extern const bool loggingEnabled; +# endif /* global_log */ +#endif /* ENABLE_CONFIG */ + /*==== FUNCTIONS ==================================================*/ extern void printVersionToSerial(); extern void setClockScale(VOLTS __x); +extern void setClockScale(CLKSCALE __x); extern VOLTS setVoltage(VOLTS volts); +#if defined(ENABLE_CONFIG) +extern void configInit(); +extern uint8_t configFindKey(const __FlashStringHelper* key, char* value); +extern String configGetStr(const __FlashStringHelper* key); +extern long configGetLong(const __FlashStringHelper* key, int onFail = 0); +#endif /* ENABLE_CONFIG */ + #include "ClockedSerial.h" #endif /* OSCR_H_ */ diff --git a/sd/config.txt b/sd/config.txt new file mode 100644 index 0000000..30fcf4c --- /dev/null +++ b/sd/config.txt @@ -0,0 +1,6 @@ +oscr.logging=1 +lcd.confColor=0 +lcd.red=0 +lcd.green=100 +lcd.blue=0 +md.sramType=0 |