#include <Arduino.h> // required by platformIO
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
//#define SSD1306_NO_SPLASH
// ----------------------------------------------------------------
// S E T T I N G S
// ----------------------------------------------------------------
// Arduino Mega
#define ENCODER_CLK 2 // Rotary encoder gpio pin
#define ENCODER_DT 3 // Rotary encoder gpio pin
// #define ENCODER_SW 4 // Rotary encoder button gpio pin
#define OLEDC 0 // oled clock pin (set to 0 for default)
#define OLEDD 0 // oled data pin
#define OLEDE 0 // oled enable pin
// oLED
#define OLED_ADDR 0x3C // OLED i2c address
#define SCREEN_WIDTH 128 // OLED display width, in pixels (usually 128)
#define SCREEN_HEIGHT 64 // OLED display height, in pixels (64 for larger oLEDs)
#define OLED_RESET -1 // Reset pin gpio (or -1 if sharing Arduino reset pin)
// Misc
const int serialDebug = 1;
const int iLED = 2; // onboard indicator led gpio pin
#define BUTTONPRESSEDSTATE 0 // rotary encoder gpio pin logic level when the button is pressed (usually 0)
#define DEBOUNCEDELAY 20 // debounce delay for button inputs
const int menuTimeout = 10; // menu inactivity timeout (seconds)
const bool menuLargeText = 0; // show larger text when possible (if struggling to read the small text)
const int maxmenuItems = 12; // max number of items used in any of the menus (keep as low as possible to save memory)
const int topLine = 14; // y position of lower area of the display (18 with two colour displays)
const byte lineSpace1 = 9; // line spacing for textsize 1 (small text)
//const byte lineSpace2 = 17; // line spacing for textsize 2 (large text)
const int displayMaxLines = 6; // max lines that can be displayed in lower section of display in textsize1 (5 on larger oLeds)
const int MaxmenuTitleLength = 10; // max characters per line when using text size 2 (usually 10)
int partsCount[] = {0,0,0,0,0,0};
int counter = 0; // part of encoder code
const byte buttonPins[] = {7, 6, 5}; // UP, DOWN
// -------------------------------------------------------------------------------------------------
// forward declarations
//void doEncoder();
void demoMenu();
void menuActions();
//void value1();
void menuValues();
void reUpdateButton();
void serviceMenu();
int serviceValue(bool _blocking);
void createList(String _title, int _noOfElements, String *_list);
void displayMessage(String _title, String _message);
void resetMenu();
// menus
// modes that the menu system can be in
enum menuModes {
off, // display is off
menu, // a menu is active
value, // 'enter a value' none blocking is active
message, // displaying a message
blocking // a blocking procedure is in progress (see enter value)
};
menuModes menuMode = off; // default mode at startup is off
struct oledMenus {
// menu
String menuTitle = ""; // the title of active mode
int noOfmenuItems = 0; // number if menu items in the active menu
int selectedMenuItem = 0; // when a menu item is selected it is flagged here until actioned and cleared
int highlightedMenuItem = 0; // which item is curently highlighted in the menu
String menuItems[maxmenuItems+1]; // store for the menu item titles
uint32_t lastMenuActivity = 0; // time the menu last saw any activity (used for timeout)
// 'enter a value'
int mValueEntered = 0; // store for number entered by value entry menu
int mValueLow = 0; // lowest allowed value
int mValueHigh = 0; // highest allowed value
int mValueStep = 0; // step size when encoder is turned
};
oledMenus oledMenu;
struct selectButtons {
//volatile int encoder0Pos = 0; // current value selected with rotary encoder (updated by interrupt routine)
//volatile bool encoderPrevA; // used to debounced rotary encoder
//volatile bool encoderPrevB; // used to debounced rotary encoder
uint32_t reLastButtonChange = 0; // last time state of button changed (for debouncing)
bool btnPrevButton = 0; // used to debounce button
int reButtonDebounced = 0; // debounced current button state (1 when pressed)
const bool reButtonPressedState = BUTTONPRESSEDSTATE; // the logic level when the button is pressed
const uint32_t reDebounceDelay = DEBOUNCEDELAY; // button debounce delay setting
bool reButtonPressed = 0; // flag set when the button is pressed (it has to be manually reset)
};
selectButtons selectButton;
// oled SSD1306 display connected to I2C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// -------------------------------------------------------------------------------------------------
// The custom menus go below here
// -------------------------------------------------------------------------------------------------
// Start the default menu
void defaultMenu() {
demoMenu();
}
// -----------------------------------------------
// a demonstration of how to create a menu
// when an item is selected it is actioned in menuActions()
void demoMenu() {
resetMenu(); // clear any previous menu
menuMode = menu; // enable menu mode
oledMenu.noOfmenuItems = 4; // set the number of items in this menu
oledMenu.menuTitle = "demo_menu"; // menus title (used to identify it)
oledMenu.menuItems[1] = "Count/Reset";
oledMenu.menuItems[2] = "Parts Pitch";
oledMenu.menuItems[3] = "Before";
oledMenu.menuItems[4] = "After";
oledMenu.menuItems[5] = "Total";
} // demoMenu
// Actions for menu selections are put in here
// note: it would probably be better to put these in their own seperate procedures but I have kept
// them all in this one place to make it easier to follow
void menuActions() {
if (oledMenu.menuTitle == "demo_menu") { // actions when an item is selected in "demo_menu"
// parts pitch list option
if (oledMenu.menuTitle == "demo_menu" && oledMenu.selectedMenuItem == 2) {
if (serialDebug) Serial.println("demo_menu: create menu from a list");
String tList[]={"2", "4", "8", "12", "16", "20", "24"};
createList("demo_list", 7, &tList[0]);
}
// Count/Reset option
if (oledMenu.selectedMenuItem == 1) {
resetMenu();
if (partsCount[1] == (partsCount[3] + partsCount[4])) {
menuMode = value; oledMenu.menuTitle = "Before & After/Reset"; oledMenu.mValueLow = 0; oledMenu.mValueHigh = 1; oledMenu.mValueStep = 1; oledMenu.mValueEntered = 1; // set parameters
}else{
menuMode = value; oledMenu.menuTitle = "Count/Reset"; oledMenu.mValueLow = 0; oledMenu.mValueHigh = 1; oledMenu.mValueStep = 1; oledMenu.mValueEntered = 1; // set parameters
}
}
/* // demonstrate usage of 'enter a value' (none blocking)
if (oledMenu.selectedMenuItem == 6) {
if (serialDebug) Serial.println("demo_menu: none blocking enter value");
resetMenu();
value1(); // enter a value selected
}*/
// Enter a Before count menu
if (oledMenu.selectedMenuItem == 3) {
//if (serialDebug) Serial.println("demo_menu: blocking enter a value");
// set perameters
resetMenu();
menuMode = value;
oledMenu.menuTitle = "ENTER BEFORE COUNT";
oledMenu.mValueLow = 0;
oledMenu.mValueHigh = 50;
oledMenu.mValueStep = 1;
oledMenu.mValueEntered = 10;
int tEntered = serviceValue(1); // request value
partsCount[3] = tEntered;
Serial.println("The BEFORE COUNT entered was " + String(tEntered));
defaultMenu();
}
// Enter an After count menu
if (oledMenu.selectedMenuItem == 4) {
//if (serialDebug) Serial.println("demo_menu: blocking enter a value");
// set perameters
resetMenu();
menuMode = value;
oledMenu.menuTitle = "ENTER AFTER COUNT";
oledMenu.mValueLow = 0;
oledMenu.mValueHigh = 50;
oledMenu.mValueStep = 1;
oledMenu.mValueEntered = 10;
int tEntered = serviceValue(1); // request value
partsCount[4] = tEntered;
Serial.println("The AFTER COUNT entered was " + String(tEntered));
defaultMenu();
}
/*// demonstrate usage of message
if (oledMenu.selectedMenuItem == 7) {
if (serialDebug) Serial.println("demo_menu: message");
displayMessage("Message", "Hello\nThis is a demo\nmessage."); // 21 chars per line, "\n" = next line
}*/
/*// turn menu/oLED off
else if (oledMenu.selectedMenuItem == 8) {
if (serialDebug) Serial.println("demo_menu: menu off");
resetMenu(); // turn menus off
}*/
oledMenu.selectedMenuItem = 0; // clear menu item selected flag as it has been actioned
}
// actions when an item is selected in the Parts Pitch menu
if (oledMenu.menuTitle == "demo_list") {
/*// back to main menu
if (oledMenu.selectedMenuItem == 1) {
if (serialDebug) Serial.println("demo_list: back to main menu");
defaultMenu();
}*/
oledMenu.selectedMenuItem = 0; // clear menu item selected flag as it has been actioned
}
} // menuActions
// -----------------------------------------------
/*// demonstration of how to enter a value
void value1() {
resetMenu(); // clear any previous menu
menuMode = value; // enable value entry
oledMenu.menuTitle = "demo_value"; // title (used to identify which number was entered)
oledMenu.mValueLow = 0; // minimum value allowed
oledMenu.mValueHigh = 100; // maximum value allowed
oledMenu.mValueStep = 1; // step size
oledMenu.mValueEntered = 50; // starting value
}*/
// actions for value entered put in here
void menuValues() {
// action for "demo_value"
if (oledMenu.menuTitle == "demo_value") {
String tString = String(oledMenu.mValueEntered);
if (serialDebug) Serial.println("demo_value: The value entered was " + tString);
displayMessage("ENTERED", "\nYou entered\nthe value\n " + tString);
// alternatively use 'resetMenu()' here to turn menus off after value entered - or use 'defaultMenu()' to re-start the default menu
}
// action for "Yes or No" - Reset -
if ((oledMenu.menuTitle == "Count/Reset") || (oledMenu.menuTitle == "Before & After/Reset")) {
//String tString = String(oledMenu.mValueEntered);
if ((oledMenu.mValueEntered == 1) && (oledMenu.menuTitle == "Count/Reset")) resetCounter();
if ((oledMenu.mValueEntered == 1) && (oledMenu.menuTitle == "Before & After/Reset")) resetBeforeAfter();
if (serialDebug) Serial.println("Reset: Yes No selection was " + String(oledMenu.mValueEntered));
defaultMenu();
}
}
// -------------------------------------------------------------------------------------------------
// custom menus go above here
// -------------------------------------------------------------------------------------------------
// ----------------------------------------------------------------
// Reset -setup
// ----------------------------------------------------------------
// called from main setup
void setup() {
Serial.begin(115200); while (!Serial); delay(50); // start serial comms
Serial.println("\n\n\nStarting menu demo\n");
pinMode(iLED, OUTPUT); // onboard indicator led
for (byte i = 0; i < 3; i++) {
pinMode(buttonPins[i], INPUT_PULLUP);
}
randomSeed(analogRead(A0));
// Initialize encoder pins
pinMode(ENCODER_CLK, INPUT);
pinMode(ENCODER_DT, INPUT);
//pinMode(ENCODER_SW, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(ENCODER_CLK), readEncoder, FALLING);
// initialise the oled display
// enable pin
if (OLEDE != 0) {
pinMode(OLEDE , OUTPUT);
digitalWrite(OLEDE, HIGH);
}
if (0 == OLEDC) Wire.begin();
//else Wire.begin(OLEDD, OLEDC);
if(!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) {
if (serialDebug) Serial.println(("\nError initialising the oled display"));
}
Wire.setClock(100000);
// Interrupt for reading the rotary encoder position
// rotaryEncoder.encoder0Pos = 0;
//attachInterrupt(digitalPinToInterrupt(encoder0PinA), doEncoder, CHANGE);
partsCount[2] = 4;
defaultMenu(); // start the default menu
// display greeting message - pressing button will start menu
// displayMessage("STARTED", "BasicWebserver\nsketch");
}
void readEncoder() {
int dtValue = digitalRead(ENCODER_DT);
if (dtValue == HIGH) {
counter++; // Clockwise
}
if (dtValue == LOW) {
counter--; // Counterclockwise
if (counter < 0) counter = 0;
}
}
// Get the counter value, disabling interrupts.
// This make sure readEncoder() doesn't change the value
// while we're reading it.
int getCounter() {
int result;
noInterrupts();
result = counter;
interrupts();
//if (serialDebug) Serial.println(("getCounter = " + result));
return result;
}
int getParts() {
int result;
noInterrupts();
result = counter / partsCount[2];
interrupts();
//if (serialDebug) Serial.println(("getParts = " + result));
return result;
}
void resetCounter() {
noInterrupts();
counter = 0;
interrupts();
}
void resetBeforeAfter() {
noInterrupts();
partsCount[3] = 0;
partsCount[4] = 0;
interrupts();
}
// ----------------------------------------------------------------
// -loop
// ----------------------------------------------------------------
// called from main loop
void loop() {
if (counter == 0) partsCount[0] = 0; partsCount[1] = 0;
//if (partsCount[1] == (partsCount[3] + partsCount[4]));
int cValue = getCounter() + partsCount[3] + partsCount[4];
if (partsCount[2] == 2) {
partsCount[0] = cValue * partsCount[2];
}else{
partsCount[0] = cValue / (partsCount[2] / 4);
}
partsCount[1] = cValue;
reUpdateButton(); // update rotary encoder button status (if pressed activate default menu)
menuUpdate(); // update or action the oled menu
// flash onboard led
static uint32_t ledTimer = millis();
if ( (unsigned long)(millis() - ledTimer) > 500 ) {
digitalWrite(iLED, !digitalRead(iLED));
ledTimer = millis();
}
//if (digitalRead(ENCODER_SW) == LOW) {
//resetCounter();
//}
delay(10);
} // oledLoop
// ----------------------------------------------------------------
// -button debounce
// ----------------------------------------------------------------
// update rotary encoder current button status
void reUpdateButton() {
//byte buttonPin = buttonPins[2];
// if (digitalRead(buttonPin) == LOW) {
bool tReading = digitalRead(buttonPins[2]); //digitalRead(encoder0Press); // read current button state
if (tReading != selectButton.btnPrevButton) selectButton.reLastButtonChange = millis(); // if it has changed reset timer
if ( (unsigned long)(millis() - selectButton.reLastButtonChange) > selectButton.reDebounceDelay ) { // if button state is stable
if (selectButton.btnPrevButton == selectButton.reButtonPressedState) {
if (selectButton.reButtonDebounced == 0) { // if the button has been pressed
selectButton.reButtonPressed = 1; // flag set when the button has been pressed
if (menuMode == off) defaultMenu(); // if the display is off start the default menu
}
selectButton.reButtonDebounced = 1; // debounced button status (1 when pressed)
} else {
selectButton.reButtonDebounced = 0;
}
}
selectButton.btnPrevButton = tReading; // update last state read
}
//void drawCounts() {
//display.setTextSize(1);
//display.setTextColor(SSD1306_WHITE);
//display.setCursor(2,2);
//display.print(F("Count:"));
//display.println(getCounter());
//partsCount[1] = getCounter();
//}
//void drawParts() {
//display.setTextSize(1);
//display.setTextColor(SSD1306_WHITE);
//display.setCursor(2,12);
//display.print(F("Parts"));
//display.setCursor(2,30);
//display.println(getParts());
//partsCount[1] = getParts();
//}
// ----------------------------------------------------------------
// -update the active menu
// ----------------------------------------------------------------
void menuUpdate() {
if (menuMode == off) return; // if menu system is turned off do nothing more
// if no recent activity then turn oled off
//if ( (unsigned long)(millis() - oledMenu.lastMenuActivity) > (menuTimeout * 1000) ) {
// resetMenu();
// return;
// }
switch (menuMode) {
// if there is an active menu
case menu:
serviceMenu();
menuActions();
break;
// if there is an active none blocking 'enter value'
case value:
serviceValue(1);
if (selectButton.reButtonPressed) { // if the button has been pressed
menuValues(); // a value has been entered so action it
break;
}
// if a message is being displayed
case message:
if (selectButton.reButtonPressed == 1) defaultMenu(); // if button has been pressed return to default menu
break;
}
}
// ----------------------------------------------------------------
// -service active menu
// ----------------------------------------------------------------
void serviceMenu() {
// rotary encoder Counter
// if (rotaryEncoder.encoder0Pos >= itemTrigger) {
//byte buttonPin = buttonPins[0];
if (digitalRead(buttonPins[0]) == LOW) {
//rotaryEncoder.encoder0Pos -= itemTrigger;
oledMenu.highlightedMenuItem++;
oledMenu.lastMenuActivity = millis(); // log time
delay(200);
}
//if (rotaryEncoder.encoder0Pos <= -itemTrigger) {
//buttonPin = buttonPins[1];
if (digitalRead(buttonPins[1]) == LOW) {
//rotaryEncoder.encoder0Pos += itemTrigger;
oledMenu.highlightedMenuItem--;
oledMenu.lastMenuActivity = millis(); // log time
delay(200);
}
if (selectButton.reButtonPressed == 1) {
oledMenu.selectedMenuItem = oledMenu.highlightedMenuItem; // flag that the item has been selected
oledMenu.lastMenuActivity = millis(); // log time
if (oledMenu.menuTitle == "demo_list") partsCount[2] = oledMenu.menuItems[oledMenu.highlightedMenuItem].toInt();
if (serialDebug) Serial.println("menu '" + oledMenu.menuTitle + "' item '" + oledMenu.menuItems[oledMenu.highlightedMenuItem] + "' selected");
delay(200);
if (oledMenu.menuTitle == "demo_list") { //added if statment to end parts pitch selection
defaultMenu();
}
}
const int _centreLine = displayMaxLines / 2; // mid list point
display.clearDisplay();
display.setTextColor(WHITE);
// verify valid highlighted item
if (oledMenu.highlightedMenuItem > oledMenu.noOfmenuItems) oledMenu.highlightedMenuItem = oledMenu.noOfmenuItems;
if (oledMenu.highlightedMenuItem < 1) oledMenu.highlightedMenuItem = 1;
// title
display.setCursor(2, 0);
if (menuLargeText) {
display.setTextSize(2);
display.println(oledMenu.menuItems[oledMenu.highlightedMenuItem].substring(0, MaxmenuTitleLength));
} else {
if (oledMenu.menuTitle.length() > MaxmenuTitleLength) display.setTextSize(1);
else display.setTextSize(1);
display.setCursor(1, 3);
if (oledMenu.menuTitle == "demo_list") display.println("PARTS PITCH");
else display.println("PART COUNT");
}
display.drawLine(0, topLine-1, display.width(), topLine-1, WHITE); // draw horizontal line under title
// menu
display.setTextSize(1);
//display.setCursor(0, topLine);
display.setCursor(0, 15);
int lineSpace = 0;
if (oledMenu.menuTitle == "demo_list") { //Parts Pitch list
for (int i=1; i <= displayMaxLines; i++) {
int item = oledMenu.highlightedMenuItem - _centreLine + i+2;
if (item == oledMenu.highlightedMenuItem) display.setTextColor(BLACK, WHITE);
else display.setTextColor(WHITE);
if (item > 0 && item <= oledMenu.noOfmenuItems) display.println(" " + oledMenu.menuItems[item] + " mm");
//else display.println(" ");
//if (serialDebug) Serial.println("List item = " + i );
}
/* for (int i=1; i <= displayMaxLines + 3; i++) {
//int item = oledMenu.highlightedMenuItem - _centreLine + i + 1;
int item = oledMenu.highlightedMenuItem - _centreLine + i + 1;
if (item == oledMenu.highlightedMenuItem) display.setTextColor(BLACK, WHITE);
else display.setTextColor(WHITE);
if (item > 0 && item <= 7) display.println(" " + oledMenu.menuItems[item] + " mm");
else display.println(" ");
//if (serialDebug) Serial.println("item = " + String(item));
}*/
}else{ // regular menu list
display.drawRect(62, 0, 66, 14, SSD1306_WHITE);
display.setCursor(72, 3);
display.println(partsCount[0]);
display.drawRect(80, 13, 48, 11, SSD1306_WHITE);
display.drawRect(80, 23, 48, 11, SSD1306_WHITE);
display.drawRect(80, 33, 48, 11, SSD1306_WHITE);
display.drawRect(80, 43, 48, 11, SSD1306_WHITE);
//display.drawRect(80, 53, 48, 11, SSD1306_WHITE);
display.setCursor(2, 55); display.println(" Pertech Industries");
display.setCursor(98, 25);
display.println("mm");
for (int i=1; i <= displayMaxLines; i++) {
//int item = oledMenu.highlightedMenuItem - _centreLine + i+2;
if (i == oledMenu.highlightedMenuItem) display.setTextColor(BLACK, WHITE);
else display.setTextColor(WHITE);
lineSpace = lineSpace + 10;
//if (i == 1) display.setCursor(1, lineSpace + 5);
//else display.setCursor(1, lineSpace + 5);
display.setCursor(1, lineSpace + 5);
//display.setCursor(0, lineSpace + 10);
if (i> 0 && i <= oledMenu.noOfmenuItems) display.println(oledMenu.menuItems[i]);
//else display.println(" ");
// values for counts
display.setCursor(84, lineSpace + 5);
display.setTextColor(WHITE);
//if (i < 5) display.println(partsCount[i]);
display.println(partsCount[i]);
//if (i == 4) display.setCursor(2, 53); display.println(" Pertech Industries");
}
}
//// how to display some updating info. on the menu screen
//display.setCursor(80, 25);
//display.println(millis());
display.display();
}
// ----------------------------------------------------------------
// -service value entry
// ----------------------------------------------------------------
// if _blocking set to 1 then all other tasks are stopped until a value is entered
int serviceValue(bool _blocking) {
const int _valueSpacingX = 30; // spacing for the displayed value y position
const int _valueSpacingY = 5; // spacing for the displayed value y position
if (_blocking) {
menuMode = blocking;
oledMenu.lastMenuActivity = millis(); // log time of last activity (for timeout)
}
uint32_t tTime;
do {
//buttons selected
//byte buttonPin = buttonPins[0];
if (digitalRead(buttonPins[0]) == LOW) {
//rotaryEncoder.encoder0Pos -= itemTrigger;
oledMenu.mValueEntered-= oledMenu.mValueStep;
oledMenu.lastMenuActivity = millis(); // log time
delay(200);
}
//buttonPin = buttonPins[1];
if (digitalRead(buttonPins[1]) == LOW) {
//rotaryEncoder.encoder0Pos += itemTrigger;
oledMenu.mValueEntered+= oledMenu.mValueStep;
oledMenu.lastMenuActivity = millis(); // log time
delay(200);
}
if (oledMenu.mValueEntered < oledMenu.mValueLow) {
oledMenu.mValueEntered = oledMenu.mValueLow;
oledMenu.lastMenuActivity = millis(); // log time
}
if (oledMenu.mValueEntered > oledMenu.mValueHigh) {
oledMenu.mValueEntered = oledMenu.mValueHigh;
oledMenu.lastMenuActivity = millis(); // log time
}
display.clearDisplay();
display.setTextColor(WHITE);
// title
display.setCursor(0, 0);
if (oledMenu.menuTitle.length() > MaxmenuTitleLength) display.setTextSize(1);
else display.setTextSize(2);
display.println(oledMenu.menuTitle);
display.drawLine(0, topLine, display.width(), topLine, WHITE); // draw horizontal line under title
// value selected
display.setCursor(_valueSpacingX, topLine + _valueSpacingY);
display.setTextSize(3);
if ((oledMenu.menuTitle == "Count/Reset") || (oledMenu.menuTitle == "Before & After/Reset")) {
if (oledMenu.mValueEntered == 1) display.println("YES");
else display.println("NO");
}else{
display.println(oledMenu.mValueEntered);
}
// range
display.setCursor(0, display.height() - lineSpace1 - 1 ); // bottom of display
display.setTextSize(1);
if (oledMenu.menuTitle == "Count/Reset") {
display.println("YES or NO");
}else{
display.println(String(oledMenu.mValueLow) + " to " + String(oledMenu.mValueHigh));
//display.println("Yes or No");
}
// bar
int Tlinelength = map(oledMenu.mValueEntered, oledMenu.mValueLow, oledMenu.mValueHigh, 0 , display.width());
//display.drawLine(0, display.height()-1, Tlinelength, display.height()-1, WHITE);
display.display();
reUpdateButton(); // check status of button
tTime = (unsigned long)(millis() - oledMenu.lastMenuActivity); // time since last activity
} while (_blocking && selectButton.reButtonPressed == 0 && tTime < (menuTimeout * 1000)); // if in blocking mode repeat until button is pressed or timeout
if (_blocking) menuMode = off;
return oledMenu.mValueEntered; // used when in blocking mode
}
// ----------------------------------------------------------------
// -list create
// ----------------------------------------------------------------
// create a menu from a list
// String tList[]={"2mm", "4mm", "8mm", "12mm", "16mm", "20mm", "24mm"};
// createList("demo_list", 6, &tList[0]);
void createList(String _title, int _noOfElements, String *_list) {
resetMenu(); // clear any previous menu
menuMode = menu; // enable menu mode
oledMenu.noOfmenuItems = _noOfElements; // set the number of items in this menu
oledMenu.menuTitle = _title; // menus title (used to identify it)
for (int i=1; i <= _noOfElements; i++) {
oledMenu.menuItems[i] = _list[i-1]; // set the menu items
//if (serialDebug) Serial.println(oledMenu.menuItems[i] + " = " + _list[i]);
}
}
// ----------------------------------------------------------------
// -message display
// ----------------------------------------------------------------
// 21 characters per line, use "\n" for next line
// assistant: < line 1 >< line 2 >< line 3 >< line 4 >
void displayMessage(String _title, String _message) {
resetMenu();
menuMode = message;
display.clearDisplay();
display.setTextColor(WHITE);
// title
display.setCursor(0, 0);
if (menuLargeText) {
display.setTextSize(2);
display.println(_title.substring(0, MaxmenuTitleLength));
} else {
if (_title.length() > MaxmenuTitleLength) display.setTextSize(1);
else display.setTextSize(2);
display.println(_title);
}
// message
display.setCursor(0, topLine);
display.setTextSize(1);
display.println(_message);
display.display();
}
// ----------------------------------------------------------------
// -reset menu system
// ----------------------------------------------------------------
void resetMenu() {
// reset all menu variables / flags
menuMode = off;
oledMenu.selectedMenuItem = 0;
//rotaryEncoder.encoder0Pos = 0;
oledMenu.noOfmenuItems = 0;
oledMenu.menuTitle = "";
oledMenu.highlightedMenuItem = 0;
oledMenu.mValueEntered = 0;
selectButton.reButtonPressed = 0;
oledMenu.lastMenuActivity = millis(); // log time
// clear oled display
display.clearDisplay();
display.display();
}
// ----------------------------------------------------------------
// -interrupt for rotary encoder
// ----------------------------------------------------------------
// rotary encoder interrupt routine to update position counter when turned
// interrupt info: https://www.gammon.com.au/forum/bbshowpost.php?id=11488
/*void doEncoder() {
bool pinA = digitalRead(encoder0PinA);
bool pinB = digitalRead(encoder0PinB);
if ( (rotaryEncoder.encoderPrevA == pinA && rotaryEncoder.encoderPrevB == pinB) ) return; // no change since last time (i.e. reject bounce)
// same direction (alternating between 0,1 and 1,0 in one direction or 1,1 and 0,0 in the other direction)
if (rotaryEncoder.encoderPrevA == 1 && rotaryEncoder.encoderPrevB == 0 && pinA == 0 && pinB == 1) rotaryEncoder.encoder0Pos -= 1;
else if (rotaryEncoder.encoderPrevA == 0 && rotaryEncoder.encoderPrevB == 1 && pinA == 1 && pinB == 0) rotaryEncoder.encoder0Pos -= 1;
else if (rotaryEncoder.encoderPrevA == 0 && rotaryEncoder.encoderPrevB == 0 && pinA == 1 && pinB == 1) rotaryEncoder.encoder0Pos += 1;
else if (rotaryEncoder.encoderPrevA == 1 && rotaryEncoder.encoderPrevB == 1 && pinA == 0 && pinB == 0) rotaryEncoder.encoder0Pos += 1;
// change of direction
else if (rotaryEncoder.encoderPrevA == 1 && rotaryEncoder.encoderPrevB == 0 && pinA == 0 && pinB == 0) rotaryEncoder.encoder0Pos += 1;
else if (rotaryEncoder.encoderPrevA == 0 && rotaryEncoder.encoderPrevB == 1 && pinA == 1 && pinB == 1) rotaryEncoder.encoder0Pos += 1;
else if (rotaryEncoder.encoderPrevA == 0 && rotaryEncoder.encoderPrevB == 0 && pinA == 1 && pinB == 0) rotaryEncoder.encoder0Pos -= 1;
else if (rotaryEncoder.encoderPrevA == 1 && rotaryEncoder.encoderPrevB == 1 && pinA == 0 && pinB == 1) rotaryEncoder.encoder0Pos -= 1;
//else if (serialDebug) Serial.println("Error: invalid rotary encoder pin state - prev=" + String(rotaryEncoder.encoderPrevA) + ","
// + String(rotaryEncoder.encoderPrevB) + " new=" + String(pinA) + "," + String(pinB));
// update previous readings
rotaryEncoder.encoderPrevA = pinA;
rotaryEncoder.encoderPrevB = pinB;
}*/
// ---------------------------------------------- end ----------------------------------------------