#include <BfButton.h>
#include <LiquidCrystal.h>
#include "SimpleMenu.h"
bool inMenu = true;
int valueA, valueB, valueC, mainValue;
void function(){};
int btnPin=6; //GPIO #3-Push button on encoder
int DT=5; //GPIO #4-DT on encoder (Output B)
int CLK=4; //GPIO #5-CLK on encoder (Output A)
BfButton btn(BfButton::STANDALONE_DIGITAL, btnPin, true, LOW);
LiquidCrystal lcd(12, 11, 10, 9, 8, 7);
int counter = 0;
int angle = 0;
int aState;
int aLastState;
const int alphabetSize = 26;
char lowerCase[alphabetSize];
char upperCase[alphabetSize];
int cursorPos = 0;
int charPos = 0;
SimpleMenu MenuSub[3] = {
SimpleMenu("Sensitivity",&mainValue),
SimpleMenu("Char map",&function),
SimpleMenu("Credits",MenuSub)
};
SimpleMenu Menu[3] = {
SimpleMenu("Write mode",&writeMode),
SimpleMenu("Settings",&valueB),
SimpleMenu("Save to SD",&valueC)
};
SimpleMenu TopMenu(3,Menu);
enum StateType{
UPCASE,
LOWCASE,
SPECIAL,
};
enum MenuModes{
WRITE,
SETTINGS,
MENU,
};
void display(SimpleMenu *_menu)
{
inMenu = true;
lcd.clear();
lcd.print(">");
lcd.print(_menu->name);
SimpleMenu *next = TopMenu.next();
if(next != NULL)
{
lcd.setCursor(1,1);
lcd.print(next->name);
}
}
void displayValue(SimpleMenu *_menu)
{
lcd.clear();
lcd.print(_menu->name);
lcd.setCursor(0,1);
lcd.print(_menu->getValue());
}
StateType state = LOWCASE;
MenuModes Mode = MENU;
//Button press hanlding function
void pressHandler (BfButton *btn, BfButton::press_pattern_t pattern) {
switch (pattern) {
case BfButton::SINGLE_PRESS:
Serial.println("Single push");
cursorPos ++;
if(inMenu == true){
inMenu = false;
lcd.clear();
TopMenu.select();
break;
}
break;
case BfButton::DOUBLE_PRESS:
Serial.println("Double push");
if(state == LOWCASE){
state = UPCASE;
}
else{
state = LOWCASE;
}
break;
case BfButton::LONG_PRESS:
Serial.println("Long push");
break;
}
}
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
lcd.begin(16, 2);
pinMode(CLK,INPUT_PULLUP);
pinMode(DT,INPUT_PULLUP);
aLastState = digitalRead(CLK);
for (int i = 0; i < alphabetSize; i++) {
lowerCase[i] = 'a' + i;
}
for (int i = 0; i < alphabetSize; i++) {
upperCase[i] = 'A' + i;
}
TopMenu.begin(display,displayValue);
//Button settings
btn.onPress(pressHandler)
.onDoublePress(pressHandler) // default timeout
.onPressFor(pressHandler, 1000); // custom timeout for 1 second
}
void writeMode(){
while(inMenu == false){ // put your main code here, to run repeatedly:
//Wait for button press to execute commands
btn.read();
aState = digitalRead(CLK);
//Encoder rotation tracking
if (aState != aLastState) {
if (digitalRead(DT) != aState) {
if (digitalRead(CLK) == LOW) { // Check the state of CLK to ensure a full step
charPos++;
if (charPos >= alphabetSize) {
charPos = 0;
}
}
} else {
if (digitalRead(CLK) == LOW) { // Check the state of CLK to ensure a full step
charPos--;
if (charPos < 0) {
charPos = alphabetSize - 1;
}
}
}
if (charPos < 0 ) {
charPos = alphabetSize;
}
}
switch(state){
case UPCASE:
lcd.print(upperCase[charPos]);
break;
case LOWCASE:
lcd.print(lowerCase[charPos]);
break;
}
aLastState = aState;
lcd.setCursor(cursorPos, 0);
}
}
void menuMode(){
while (inMenu == true)
{
btn.read();
aState = digitalRead(CLK);
if (aState != aLastState) {
if (digitalRead(DT) != aState) {
if (digitalRead(CLK) == LOW) { // Check the state of CLK to ensure a full step
TopMenu.down();
}
} else {
if (digitalRead(CLK) == LOW) { // Check the state of CLK to ensure a full step
TopMenu.up();
}
}
}
aLastState = aState;
}
}
void loop() {
switch(Mode){
case WRITE:
writeMode();
break;
case MENU:
menuMode();
break;
}
}