Ugh.
I have removed the F() stuff for now because I need to get this up and running as quickly as possible and I should have plenty of space for my strings, but I still can't get the darn thing working and I have no way of doing serial debugging at this time.
The code is pretty simple, it should work, but the values don't seem to be being read. Specifically SWAP_LEDMODULES is not read. If that one value were read, I would know it.
Also, I've had the program halt and blink and LED if it gets into the swap() functions, and it appears to be gtting into the INT version of the swap() function, but never goes into the BYTE version, even though SWAP_LEDMODULES is a byte type. Any idea why that is?
Here's the code:
First, how the globals are setup:
byte SWAP_LEDMODULES = 0; // 1 = Reverse order of powercell and bargraph LED modules to allow board to be installed in pack.
byte ENABLE_POWERDOWN = 0; // Enable playing the powerdown sund every time the user flips off the Activate switch.
byte BARGRAPH_STANDBY = 2; // Safety on
byte BARGRAPH_IDLE = 1; // Ready to fire
byte BARGRAPH_FIRE = 3; // Black button
byte BARGRAPH_ALTFIRE = 4; // Red button
byte POWERCELL_IDLE = 1; // Fill repeatedly.
int powerupDelay = 750; // Number of milliseconds to wait before playing the powerup sound and continuing with pack animation.
int humFadeTime = 300; // Number of seconds it takes for hum to fade out completely to conserve battery power.
float maxSpeed = 10; // Number of seconds blast stream needs to be used for lights to move at maximum speed and for the pack to overheat.
float currentSpeed = 0; // Roughly the number of seconds the fire button has been held for.
float normalSpeed = 0; // Range [0..1] (currentSpeed / maxSpeed);
float overheatWarning = 2; // Number of seconds warning you get before reaching max speed that you get a warning of impending overheat.
float minPowerDownSoundTime = 3; // Number of seconds fire button needs to be held to get the shortest powerdown sound.
float midPowerDownSoundTime = 5;
float maxPowerDownSoundTime = 7; // Number of seconds fire button needs to be held to get the longest powerdown sound.
// Note that sound played is actually based on how fast cyclotron is moving; these values assume that we're starting from 0.
float heatup_Fire = 0; //0.5; // Rate at which the pack speeds up when firing.
float heatup_AltFire = 1.0; // This could change based on the weapon. For example, a shotgun-like weapon would only add this amount each time it fired.
float heatup_Overload = maxSpeed / 3.0; // We want the overload to max out the pack's speed every time, and it lasts for three seconds, so maxSpeed / 3.0 gives us how much we need to add each second to make that happen.
float heatup_Shotgun = maxSpeed / (8.0 * 0.625); // We want the shotgun to max out the pack's speed after X number of shots, and maxSpeed / (X * seconds of active heatup per shot) gives us how much speed to add each second to accomplish that. (Shotgun only heats up pack for first half second of each shot.)
float cooldown = 0.5; // 1.0 means the pack cools down at the same rate it heats up when firing. 2.0 would make it cooldown twice as fast.
Then the code to read the config file:
// Scan line for keyword and parameter, and update parameter if found.
// Return parameters found on success, 0 on failure.
int scan(char* line, char* keyword, byte& i) {
char format[strlen(keyword) + 5]; // Allow space for " %3s" + null. strlen() returns the number of character up to, but not including null.
char result[7];
//halt(3); NEVER GET HERE
strcpy(format, keyword);
strcat(format, " %3s");
if (sscanf(line, format, result) == 1) {
i = atoi(result);
return 1;
}
}
int scan(char* line, char* keyword, int& i) {
char format[strlen(keyword) + 5]; // Allow space for " %6s" + null. strlen() returns the number of character up to, but not including null.
char result[7];
// halt(3); DO GET HERE
strcpy(format, keyword);
strcat(format, " %6s");
if (sscanf(line, format, result) == 1) {
i = atoi(result);
return 1;
}
}
int scan(char* line, char* keyword, float& f) {
char format[strlen(keyword) + 5];
char result[10];
strcpy(format, keyword);
strcat(format, " %9s");
if (sscanf(line, format, result) == 1) {
f = atof(result);
return 1;
}
}
void readConfigFile() {
char line[256]; // Next line of text in file.
//char fmt[32]; // Temporary variable for holding sscanf format strings read from flash.
char fmt[32]; // Temporary variable for holding sscanf format strings read from flash.
int n = 0; // Next parameter we want.
int tmp; // Holds parameters that need to be modified before being put in another variable.
if (!file.open(root, "PACK.CFG")) { Serial1.println(F("Failed to open PACK.CFG!")); halt(6); } // Error if file does not exist.
// TEST:
//file.fgets(line, sizeof(line));
//if (*line == '#') halt(8);
while (file.fgets(line, sizeof(line))) { // Read lines from the file until we hit the end.
if (*line == '#') continue; // Check first character on line. If comment, skip to next line. (GOT HERE)
if (scan(line, "powerupDelay", powerupDelay)) continue;
if (scan(line, "humFadeTime", humFadeTime)) continue;
if (scan(line, "maxSpeed", maxSpeed)) continue;
if (scan(line, "overheatWarning", overheatWarning)) continue;
if (scan(line, "minPowerDownSoundTime", minPowerDownSoundTime)) continue;
if (scan(line, "midPowerDownSoundTime", midPowerDownSoundTime)) continue;
if (scan(line, "maxPowerDownSoundTime", maxPowerDownSoundTime)) continue;
if (scan(line, "shotgunShotsOverheat", tmp)) { heatup_Shotgun = maxSpeed / (tmp * 0.625); continue; }
if (scan(line, "SWAP_LEDMODULES", SWAP_LEDMODULES)) continue;
if (scan(line, "ENABLE_POWERDOWN", ENABLE_POWERDOWN)) continue;
if (scan(line, "BARGRAPH_STANDBY", BARGRAPH_STANDBY)) continue;
if (scan(line, "BARGRAPH_IDLE", BARGRAPH_IDLE)) continue;
if (scan(line, "BARGRAPH_FIRE", BARGRAPH_FIRE)) continue;
if (scan(line, "BARGRAPH_ALTFIRE", BARGRAPH_ALTFIRE)) continue;
if (scan(line, "POWERCELL_IDLE", POWERCELL_IDLE)) continue;
}
}
And here is the fgets function I added to the fat lib that comes with WaveHC:
Declaration:
int16_t fgets(char* str, int16_t num, char* delim = 0); // Added by me, taken from SdFat lib.
Code:
/**
This method was taken from the SDFat lib.
It does not work exactly like the standard fgets() function. It can take a delimiter to allow you to stop reading when you hit a certain character.
* Get a string from a file.
*
* fgets() reads bytes from a file into the array pointed to by \a str, until
* \a num - 1 bytes are read, or a delimiter is read and transferred to \a str,
* or end-of-file is encountered. The string is then terminated
* with a null byte.
*
* fgets() deletes CR, '\\r', from the string. This insures only a '\\n'
* terminates the string for Windows text files which use CRLF for newline.
*
* \param[out] str Pointer to the array where the string is stored.
* \param[in] num Maximum number of characters to be read
* (including the final null byte). Usually the length
* of the array \a str is used.
* \param[in] delim Optional set of delimiters. The default is "\n".
*
* \return For success fgets() returns the length of the string in \a str.
* If no data is read, fgets() returns zero for EOF or -1 if an error occurred.
**/
int16_t FatReader::fgets(char* str, int16_t num, char* delim) {
char ch;
int16_t n = 0;
int16_t r = -1;
while ((n + 1) < num && (r = read(&ch, 1)) == 1) {
// delete CR
if (ch == '\r') continue;
str[n++] = ch;
if (!delim) {
if (ch == '\n') break;
} else {
if (strchr(delim, ch)) break;
}
}
if (r < 0) {
// read error
return -1;
}
str[n] = '\0';
return n;
}
Pulling my hair out over this. It's probably something really stupidly simple like I didn't pass a pointer right to a function.