Hi J,
Ok that I can understand about the weird byte count then!
I'm still stumped on why adding one character causes it to fail...
Here's the entire code...
#include <Arduino.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// Define function prototypes (so the compiler knows they are there)
void Print_Variables();
void Display_Axis();
void displayMenu(const char*, int , int );
void WaitKey1();
void WaitKey2();
void WaitKey3();
void WaitKey4();
int GetIncDecSelect();
int GetKeyCode();
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
//OLED_SSD1306_Chart display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
char actualThickness; //Line Type?
#define ChartX 34
#define ChartY 16
#define ChartWidth 112
#define ChartHeight 48
#define TopSpace 16
#define BufferSize 128
int rawValue; //Store temp values here
uint16_t scaledValue;
//----------- Keys ---------------------
const int TestKey = 7; //Use this pin to stop execution at points
const int NextKey = 8; //These are the pin numbers that the keys are wired to
const int BeforeKey = 9;
const int IncKey = 10;
const int DecKey = 11;
const int SelectKey = 12;
const int NextKeyCode = 1; //These are the key codes
const int BeforeKeyCode = 2;
const int IncKeyCode = 3;
const int DecKeyCode = 4;
const int SelectKeyCode = 5;
int nextKeyCount; //Accumulate counts of how long a key is down
int beforeKeyCount;
int incKeyCount;
int decKeyCount;
int selectKeyCount;
int nextModeCount; //These count how long mode change keys were pressed
int beforeModeCount;
int KeyCode; //This guy stores the key codes
int thisKeyCode; //This get KeyCode passed to it for use
int thisSelection; //Used to determine where Select happened
// Main Setup Select menu
String Main_Setup_String = " ---- SETUP ----";
const int Num_Main_Menu_Items = 5;
const char* Main_Menu_Items[Num_Main_Menu_Items] = {"Set Lim. + Scale",
"Configure Graph",
"Configure Outs",
"Reset Stats",
"Exit to Run"}; //The last one is always reserved
//as a retrun vector
int currentSelection = 0;
int cursor_position = 0;
int value;
int power_of_10 ;
int digit;
//------------------------------
// Editable Menus
String Lim_Scl_String = " -- Limit and Scale --";
const int& Lim_Scl_Num_Items = 4;
const char* Lim_Scl_Menu_Items[Lim_Scl_Num_Items] = {"Trig. Level:",
"Scale :",
"Zero Mode",
"Exit "};
int Lim_Scl_Values[Lim_Scl_Num_Items-1] = {0, 0};
String Cnfg_Grph_String = " -- Config Graph --";
const int& Cnfg_Grph_Num_Items = 4;
const char* Cnfg_Grph_Menu_Items[Cnfg_Grph_Num_Items] = {"Grph 1:",
"Grph 2",
"Grph 3",
"Exit "};
int Cnfg_Grph_Values[Cnfg_Grph_Num_Items-1] = {0, 0};
String Cnfg_Ana_String = " -- Config Analog --";
const int& Cnfg_Ana_Num_Items = 4;
const char* Cnfg_Ana_Menu_Items[Cnfg_Ana_Num_Items] = {"Analog 1:",
"Analog 2",
"Analog 3",
"Exit "};
int Cnfg_Ana_Values[Cnfg_Ana_Num_Items-1] = {0, 0};
String Rst_Sts_String = " -- Reset Stats --";
const int& Rst_Sts_Num_Items = 4;
const char* Rst_Sts_Menu_Items[Rst_Sts_Num_Items] = {"Stat 1:",
"Stat 2",
"Stat 3",
"Exit "};
int Rst_Sts_Values[Rst_Sts_Num_Items-1] = {0, 0};
int ThisMenuItem;
int ThisDigit;
bool ThisEditMode;
bool exitMenu = false;
int DIGITS_PER_VALUE = 3;
int maxValue;
int minValue;
//Y Axis Struff
int LineX = 30; //These locate the vertical axis
int LineYTop = 16;
int LineYBot = 64;
int vTick = 10 ; //Set to how many ticks you want
int TopYValu = 1000;
int BotYValu = -10;
//----------------------------------
// Buffer Stuff
uint16_t OscBuffer[BufferSize];
int BuffInPtr = 0;
int BuffOutPtr = 0; //Probably will need this later to better syns in/out of the buffer
int ChartUpdateSpeed;
uint32_t currentTime; //Used to time the re-drawing of the trace
uint32_t lastUpdateTime;
int PlotValue;
//-------------------------------
// Mode Stuff
const int MaxModes = 4; //Max Mode number allowed before wrap
int LastMode; //Used to detect mode transitions
int RunMode; // 1 = Run Mode
// 0 = Setup Mode
int setupSel;
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//--------------------------------------------------------------------
// Program Setup
void setup() {
Serial.begin(9600);
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay(); // Clear the display
display.setTextSize(1); // Set text size to 1
display.setTextColor(WHITE); // Set text color to white
//Display_Axis(); //Display the vertical axis (later pass variables?)
//display.display(); //Display it
//while(1);
lastUpdateTime = 0;
RunMode = 0; // Startup in Run Mode thinking we need to update display
LastMode = 99; //Trick it to update the axis
//Add code here to look at a switch to be off to go further
ChartUpdateSpeed = 100; //Set this for test !!!
// Timer 3 setup for 10ms to be used to scan the keypad in the background and other fun things
// Set Timer3 to CTC (Clear Timer on Compare) mode
TCCR3A = 0;
TCCR3B = 0;
TCCR3B |= (1 << WGM32); // set CTC mode
// Set the compare match value to 1562 (10ms with a 16MHz clock and a prescaler of 1024)
OCR3A = 1562;
// Set the prescaler to 1024
TCCR3B |= (1 << CS32) | (1 << CS30);
// Enable the compare match interrupt for Timer3
TIMSK3 |= (1 << OCIE3A);
//------------------------------------------------
// Keypad Stuff
pinMode(NextKey, INPUT_PULLUP); //Define the keys and pullups. This needs to get changed to IC variety
pinMode(BeforeKey, INPUT_PULLUP);
pinMode(IncKey, INPUT_PULLUP);
pinMode(DecKey, INPUT_PULLUP);
pinMode(SelectKey, INPUT_PULLUP);
KeyCode = 0; //Access this variable only through GetKeyCode()
pinMode(TestKey, INPUT_PULLUP);
}
//--------------------------------------------------------------------------------------------------------
//====================================== Main Loop =====================================================
void loop() {
//---------------------------------------------------------------------------------------------------------
// RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
// Run Mode = RunMode = 0
if (RunMode == 0){
if (LastMode > 0){ // If we just came off of setup re-display the axis
display.fillRect(0, 16, 32, ChartHeight, BLACK);
Display_Axis(); //Re-Display the axis
display.display();
LastMode = 0; // Indicate we are fully in Run Mode now
int clrKeyCode = GetKeyCode(); //Clear any old codes
Serial.println(" 1st into Run Mode");
WaitKey();
}
//----------------------------------------------------------------------------------------------------
// Update the display while in Run Mode
uint32_t currentTime = millis();
// See if it's time to update the display with a new plot.
if (currentTime - lastUpdateTime >= ChartUpdateSpeed) {
lastUpdateTime = currentTime;
//----------------------------------------------------------------------
// Read analog input from pin A5 and scale it
rawValue = analogRead(A5);
// Scale the analog 12 bit value to ChartHeight
scaledValue = map(rawValue, 0, 1023, ChartHeight, 1);
//----------------------------------------------------------------------
// Store the scaled value in the circular buffer
OscBuffer[BuffInPtr] = scaledValue;
// Move the buffer pointer by one
BuffInPtr++;
if (BuffInPtr >= BufferSize) { BuffInPtr = 0; } //Check for rollover
//--------------------------------------------------------------------------------------
// Plot the buffer back into the OLED Chart Area
// First clear only the section of the screen for plotting
display.fillRect(ChartX, ChartY, ChartWidth, ChartHeight, BLACK);
// Plot the contents of the buffer into the chart area
BuffOutPtr = BuffInPtr; //Grab a copy of the pointer we used to put the value in
for (int x = 0; x < ChartWidth; x++) { //This loops through the buffer ChartWidth times
BuffOutPtr--; //Decrement the buffer pointer
if (BuffOutPtr < 0) { BuffOutPtr = BufferSize-1; } //If we decremented past the beginning of the buffer
PlotValue = OscBuffer[BuffOutPtr]; //Point to the next element
display.drawPixel(x + ChartX, PlotValue + TopSpace, WHITE);
}
//------------------------------------------------------------------------------
// Display the values on the OLED Display
display.fillRect(0, 0, 128, 16, BLACK); //Clear the upper yellow part first
display.setCursor(20, 0);
display.print("Osc Count: ");
display.print(rawValue); // Adds CRLF
display.setCursor(20, 8);
display.print("Scaled Value: ");
display.print(scaledValue);
display.display();
}
}
//------------------------------------------------------------------------------------------------------------------------
// SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS
//--------------------------------------------------
// Setup Mode
else if (RunMode == 1) { //This is Main Menu "Mode"
//----------------------------------------------------
//If we are just getting here display the main menu
if (LastMode != 1){
currentSelection = 0; //Start st the top of the menu
//displayMenu(Main_Menu_Items, Num_Main_Menu_Items, Main_Setup_String, currentSelection); // Put up the menu
display.clearDisplay();
display.setCursor(0, 0);
display.println(Main_Setup_String); //Display the header
display.display();
int clrKeyCode = GetKeyCode(); //Clear any old codes
LastMode = 1; //Fully in Setup Mode
Serial.println(" 1st into Setup Mode");
WaitKey();
}
// Check for key presses and set the Run Mode accordingly (causes execution to transfer to another menu )
setupSel = GetIncDecSelect(); //See what we got
//Serial.print(setupSel);
if (setupSel == Num_Main_Menu_Items){ RunMode = 0; }
if (setupSel == 1) { RunMode = 2; }
if (setupSel == 2) { RunMode = 3; }
if (setupSel == 3) { RunMode = 4; }
if (setupSel == 4) { RunMode = 5; }
//Serial.println("Inside Setup Loop");
//Test Lines - Adding one more charater to any of these causes program not to launch
//as well as adding 10 bytes to compiled file size (anywhere else I add a charqacter to a string it only add 1 as it should)
Serial.print("1his Ok"); //This works fine
Serial.print("2his Ok"); //This works fine (unless I add one more charcter)
Serial.print("3his Ok"); //This works fine
Serial.print("4his Ok"); //This works fine
//Can't enable this??? This is where I first noticed the problem (when this was uncommented)
//Serial.println(F("Inside Setup Loop"));
WaitKey(); //When it's running we get here no problem
}
//Print this once through the loop to see what's doing
Print_Variables();
} //Main Loop end
//--------------------------------------------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------------------------------------------
// Routines
//------------------------------------------------------------------
// Increment , Decrement, and Select for Menus
// Note: currentSelection is 0 based and thisSelection starts at 1 (they are offset by 1
//such that thisselection (the returned value ) = 0 when there was no valid key)
int GetIncDecSelect(){
thisKeyCode = GetKeyCode(); //See if we have any keyes
thisSelection = 0;
switch (thisKeyCode) {
case IncKeyCode:
if (currentSelection == 0) {
currentSelection = Num_Main_Menu_Items - 1; //Set it back to the bottom
}
else {
currentSelection--; //Just go down 1
}
break;
case DecKeyCode:
if (currentSelection >= Num_Main_Menu_Items-1) {
currentSelection = 0; //Loop to top
}
else {
currentSelection++; //Up one
}
break;
case SelectKeyCode:
thisSelection = currentSelection + 2; // Add in the offset to the position and change to that mode
break;
}
return thisSelection;
}
//--------------------------------------------------------------------------------------------------------------
// Update the display with whatever menu is presented. "currentMenuItem" points to the line to highlight
void displayMenu(const char* menuItems[], int numMenuItems, int currentMenuItem) {
//display.clearDisplay(); //!!! this may be a problem
display.fillRect(0, 16, 128, 48, BLACK); //Clear the lower blue part
display.setTextColor(SSD1306_WHITE);
display.setTextSize(1);
for (int i = 0; i < numMenuItems ; i++) { //Loop till done
if (i == currentMenuItem) {
display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
Serial.println("Reverse Color");
}
display.setCursor(0, i*10 + 16);
display.println(String(i+1) + ". " + menuItems[i]);
display.setTextColor(SSD1306_WHITE);
Serial.println("Standard Color");
// Serial.println(i);
}
display.display();
}
//--------------------------------------------------------------------------------------------------------------
// Display Axis
void Display_Axis(){
int tickSpacing = (LineYBot - LineYTop) / (vTick - 1); //calculate spacing between tick marks
int tickValueSpacing = (LineYTop - LineYBot) / (vTick - 1); //calculate spacing between tick values
//print axis top and bottom values
display.setCursor(0, LineYTop );
display.println(TopYValu);
display.setCursor(0, LineYBot - 8);
display.println(BotYValu);
//draw vertical line
display.drawLine(LineX, LineYTop, LineX, LineYBot, WHITE);
//draw tick marks
for (int i = 0; i < vTick; i++) {
int tickY = LineYTop + i * tickSpacing;
display.drawLine(LineX - 3, tickY, LineX, tickY, WHITE);
}
display.display();
}
//--------------------------------------------------------------------------------------------------------------
// Send out variables for debug
void Print_Variables(){
Serial.print("RunMode: ");
Serial.println(RunMode);
Serial.print("LastMode: ");
Serial.println(LastMode);
Serial.print("KeyCode: ");
Serial.println(KeyCode);
//delay(500);
if (RunMode == 0) { //Main Running
Serial.print("Raw ADC: ");
Serial.println(rawValue);
Serial.print("Scaled Value: ");
Serial.println(scaledValue);
}
if (RunMode == 1) { //Setup Main Menu
Serial.println("Setup Mode");
Serial.print("Setup Current selection: ");
Serial.println(currentSelection);
Serial.print("this key code in Setup: ");
Serial.println(thisKeyCode);
}
else if (RunMode == 2) { //Set Scale and Limits
Serial.println("Set Scale and Limits Mode");
Serial.print("This Menu Item: ");
Serial.println(ThisMenuItem);
Serial.print("This Key Code: ");
Serial.println(thisKeyCode);
Serial.print("This Edit Mode: ");
Serial.println(ThisEditMode);
Serial.print("Max Value: ");
Serial.println(maxValue);
Serial.print("Min Value: ");
Serial.println(minValue);
}
else if (RunMode == 3) { //Configure Graph
Serial.println("Configure Graph Mode");
}
else if (RunMode == 4) { //Reset Stats
Serial.println("Reset Stats");
}
}
//--------------------------------------------------------------------------------------------------------------
void WaitKey(){
Serial.println("Wait...Press button to continue...");
//added another switch for this so as not to mess up key reads
while (digitalRead(TestKey) == HIGH) {
delay(10); // Wait for a short period of time before checking again
}
while (digitalRead(TestKey) == LOW) {
delay(10); // Wait for a short period of time before checking again
}
Serial.println("Button pressed... Code execution resumed.");
}
//--------------------------------------------------------------------------------------------------------------
//
// Interrupt Service Routine for Timer3 compare match A
ISR(TIMER3_COMPA_vect) {
const int keyCountTrig = 2; //Set how many times key needs to be on
//First check if mode keys (Before-Next) are in effect in conjunction with select key.
//This must be first since we require the countes we set last time in here (that they are enough and the user got off the keypad)
if (nextKeyCount >= keyCountTrig && selectKeyCount >= keyCountTrig ) { //If the two keys had been both down long enough
if (digitalRead(NextKey) == HIGH || digitalRead(SelectKey) == HIGH ) { //AND their firnger has come off either one (or both)
if (RunMode >= MaxModes) {
RunMode = 0; //Roll over to Running Mode
}
else {
RunMode++; //Go to forward to the last one
}
}
}
if (beforeKeyCount >= keyCountTrig && selectKeyCount >= keyCountTrig ) { //If the two keys had been both down long enough
if (digitalRead(BeforeKey) == HIGH || digitalRead(SelectKey) == HIGH ) { //AND their finger has come off either one (or both)
if (RunMode > 0) {
RunMode--; //Go to back a Mode
}
else {
RunMode = MaxModes; //Go to backwards to the last one
}
}
}
//Now we need to sort through and prioritize KeyCode from top to last (or none) from last pass through
if (nextKeyCount >= keyCountTrig && digitalRead(NextKey) == HIGH) { //Wait for them to come off the key
KeyCode = NextKeyCode;
} else if (beforeKeyCount >= keyCountTrig && digitalRead(BeforeKey) == HIGH) {
KeyCode = BeforeKeyCode;
} else if (incKeyCount >= keyCountTrig && digitalRead(IncKey) == HIGH) {
KeyCode = IncKeyCode;
} else if (decKeyCount >= keyCountTrig && digitalRead(DecKey) == HIGH) {
KeyCode = DecKeyCode;
}else if (selectKeyCount >= keyCountTrig && digitalRead(SelectKey) == HIGH) {
KeyCode = SelectKeyCode;
} else { } //Do nothing here for now (keyCodes are cleared after GetKeyCode issues them)
// Check each key one by one and count how many times it was on (LOW)
//------------------------------------------------------
if (digitalRead(NextKey) == LOW) { //Next Key Pressed?
nextKeyCount++;
} else {nextKeyCount = 0; } //Reset Count
//------------------------------------------------------
if (digitalRead(BeforeKey ) == LOW) { //Before Key Pressed?
beforeKeyCount++;
} else {beforeKeyCount = 0; } //Reset Count
//------------------------------------------------------
if (digitalRead(IncKey ) == LOW) { //Inc Key Pressed?
incKeyCount++;
} else {incKeyCount = 0; } //Reset Count
//------------------------------------------------------
if (digitalRead(DecKey ) == LOW) { //Dec Key Pressed?
decKeyCount++;
} else {decKeyCount = 0; } //Reset Count
//------------------------------------------------------
if (digitalRead(SelectKey ) == LOW) { //Before Key Pressed?
selectKeyCount++;
} else {selectKeyCount = 0;} //Reset Count
}
//---------------------------------------------------------------------------------------------
//This guy returns key codes to a calling routine. It functions as a latch to get a key code
//and hold it till it's requested (The keyboard 10ms interrupt only sets codes not clears them)
//Only clear KeyCode in the event we actually had a code to pass back (otherwise 0 gets sent back)
int GetKeyCode (){
int thisKey = KeyCode; //Grab the current code
if (thisKey !=0){
KeyCode = 0; //Clear the code
}
return thisKey; //return with the KeyCode we grabbed
}