Added ability to use config file for some options.

A sample `config.txt` is in the SD folder. Currently the option is disabled by default and must be enabled.

Also:
* Eliminated the 5V spike at boot when VSELECT is installed and enabled. See discussion #906
* Fixed a warning in `MD.ino`
* Did some code cleanup, more cleanup to come.
This commit is contained in:
Ancyker 2024-02-29 17:52:04 -05:00
parent 35eca2a9f4
commit 3468703a51
6 changed files with 470 additions and 135 deletions

View File

@ -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);
// Read current folder number out of eeprom
# 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 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)
# 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
} else if (cmd.substring(0, 7) == "SETTIME") {
#if defined(RTC_installed)
ClockedSerial.println(F("Setting Time..."));
rtc.adjust(DateTime(cmd.substring(8).toInt()));
ClockedSerial.print(F("Current Time: "));
ClockedSerial.println(RTCStamp());
#else
ClockedSerial.println(F("RTC not installed"));
#endif
# endif /* RTC_installed */
} else {
ClockedSerial.println(F("OSCR: Unknown Command"));
}

View File

@ -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 */

View File

@ -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

View File

@ -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 */

View File

@ -10,6 +10,7 @@
#include <Wire.h>
#include <avr/pgmspace.h>
#include <avr/wdt.h>
#include "SdFat.h"
#include "Config.h"
@ -29,6 +30,13 @@ const uint16_t UPD_BAUD = 9600;
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()
@ -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_ */

6
sd/config.txt Normal file
View File

@ -0,0 +1,6 @@
oscr.logging=1
lcd.confColor=0
lcd.red=0
lcd.green=100
lcd.blue=0
md.sramType=0