MENU_3_LAYER_ST7920.zip (18.4 KB)
Hello programming gurus,
I'm upgrading my rc transmitter to esp32 from Arduino
And as i have more memory and speed i wanted to have a menu for details and model selection...i got an menu example from internet but it is compatible with Arduino only because it is using timer and interrupts...and I'm not familiar with these... i want to modify this menu code to work with an esp32
Original setup is using :-
Arduino
Glcd 128*64 (spi mode)
Rotary encoder
And i have tested it as well..
Setup i want :-
Esp32 (i have DOIT esp32 dev module)
Glcd 128*64 (spi mode)
Rotary encoder (STANDARD ONE)
(Glcd works with esp32 )
Can someone please modify this sketch to work with esp32.
// ========================================================
// INCLUDES
// ========================================================
// for display
#include <U8g2lib.h>
// for timer
#include <TimerOne.h>
// for rotary encoder
#include <Rotary.h>
// ========================================================
// pin config
// ========================================================
// Rotary encoder with switch
#define ROTARY_SWITCH 4 // A1
#define ROTARY_PIN1 2
#define ROTARY_PIN2 3
#define ROTARY_ACCEL_OFFSET1 20
#define ROTARY_ACCEL_OFFSET2 50
#define ROTARY_ACCEL_OFFSET3 70
unsigned long rotaryLastMove;
bool rotaryButtonPressed = false;
// ========================================================
// INITS
// ========================================================
// Display
U8G2_ST7920_128X64_F_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* CS=*/ 10, /* reset=*/ 8);
// Rotary Encoder
Rotary rotary = Rotary(ROTARY_PIN1, ROTARY_PIN2);
// ========================================================
// DEFAULTS
// ========================================================
// Timer
#define TIMER 100
// Display and menu stuff
int displayCurrentPage = 0;
bool setNeedsDisplay = true;
// Main menu fixed to 3 items, left, center, right...
#define MENU_SELECTED_TIMEOUT 40000
#define MENU_POS_Y 62
#define MENU_POS_Y_HIDDEN 76
#define MENU_ANIMATION_PIXEL_STEP 5
String menuItems[3] = {"HOME", "NETWORK", "SETUP"};
int menuActive = 1; // left active
int menuSelected = menuActive; // selected
bool menuPageMode = false; // true => rotary encoder control page and not menu
// Menu animation
bool menuAnimationRunning = false;
int menuPosY = MENU_POS_Y;
// Test slider
int sliderPosX = 64;
// ========================================================
// PAGES STUFF
// ========================================================
#define SETUP_MENU_ITEMS 9
char *setupMenuItems[SETUP_MENU_ITEMS] = {"CHINOOK", "HELI-COPTER", "BI-COPTER", "TRI-COPTER", "QUAD-COPTER", "RC-PLANE", "RC-JET V-1","RC-CAR V-2", "VERSION"};
int setupMenuSelected = 1;
// ========================================================
// SETUP
// ========================================================
void setup() {
// put your setup code here, to run once:
// Menu Button
pinMode(ROTARY_SWITCH, INPUT);
digitalWrite(ROTARY_SWITCH, INPUT_PULLUP);
// OLED Display
u8g2.begin();
setNeedsDisplay = true;
Timer1.initialize(TIMER);
Timer1.attachInterrupt(timerEvent);
//delay(1000);
}
// ========================================================
// LOOP
// ========================================================
void loop() {
// put your main code here, to run repeatedly:
if (menuAnimationRunning) {
if (menuPageMode && menuPosY < MENU_POS_Y_HIDDEN) {
// do animation
menuPosY = menuPosY + MENU_ANIMATION_PIXEL_STEP;
setNeedsDisplay = true;
}
if (!menuPageMode && menuPosY > MENU_POS_Y) {
// do animation
menuPosY = menuPosY - MENU_ANIMATION_PIXEL_STEP;
setNeedsDisplay = true;
}
}
if (menuAnimationRunning && (menuPosY == MENU_POS_Y || menuPosY == MENU_POS_Y_HIDDEN)) {
// looks like animation is done
menuAnimationRunning = false;
}
if (setNeedsDisplay) {
noInterrupts();
displayRenderCurrentPage();
setNeedsDisplay = false;
interrupts();
}
}
// ========================================================
// TIMER
// ========================================================
void timerEvent() {
// Menu logic
unsigned long timeOffset = millis() - rotaryLastMove;
if (timeOffset > MENU_SELECTED_TIMEOUT) {
// deselect menu
menuSelected = menuActive;
rotaryLastMove = millis();
setNeedsDisplay = true;
}
// Rotary Encoder
unsigned char result = rotary.process();
if (result) {
if (!menuPageMode) {
if (result == DIR_CW) {
// right
if (menuSelected < 3) {
menuSelected++;
}
} else {
// left
if (menuSelected > 1) {
menuSelected--;
}
}
setNeedsDisplay = true;
} else {
// Acceleration
byte acceleration = 1;
unsigned long timeOffset = millis() - rotaryLastMove;
//Serial.println(timeOffset);
if (displayCurrentPage == 0 || displayCurrentPage == 1) {
if (timeOffset < ROTARY_ACCEL_OFFSET1) {
acceleration = 16;
} else if (timeOffset < ROTARY_ACCEL_OFFSET2) {
acceleration = 4;
} else if (timeOffset < ROTARY_ACCEL_OFFSET3) {
acceleration = 2;
}
// Development test => control slider
if (result == DIR_CW) {
// right
if (sliderPosX < 128) {
sliderPosX = sliderPosX + acceleration;
}
} else {
// left
if (sliderPosX > 0) {
sliderPosX = sliderPosX - acceleration;
}
}
setNeedsDisplay = true;
}
if (displayCurrentPage == 2) {
if (result == DIR_CW) {
// right
setupMenuSelected++;
} else {
// left
setupMenuSelected--;
}
if (setupMenuSelected > SETUP_MENU_ITEMS - 1) {
setupMenuSelected = SETUP_MENU_ITEMS - 1;
}
if (setupMenuSelected < 1) {
setupMenuSelected = 0;
}
setNeedsDisplay = true;
}
}
rotaryLastMove = millis();
}
// Rotary button
if (buttonEvent()) {
rotaryLastMove = millis();
if (menuActive == menuSelected) {
if (!menuPageMode) {
// give controls to page (button press on selected page)
menuPageMode = true;
menuAnimationRunning = true;
sliderPosX = 64;
setNeedsDisplay = true;
#ifdef DEBUG
Serial.println("PAGE MODE ON");
#endif
} else {
menuPageMode = false;
menuAnimationRunning = true;
setNeedsDisplay = true;
sliderPosX = 64;
setupMenuSelected = 0;
#ifdef DEBUG
Serial.println("PAGE MODE OFF");
#endif
}
}
if (!menuPageMode) {
menuActive = menuSelected;
if (menuActive == 1) {
displayCurrentPage = 0;
}
if (menuActive == 2) {
displayCurrentPage = 1;
}
if (menuActive == 3) {
displayCurrentPage = 2;
}
setNeedsDisplay = true;
}
}
// Action button => reset page mode during development
#ifdef BUTTON1_PIN
if (digitalRead(BUTTON1_PIN) == 0 && menuPageMode) {
menuPageMode = false;
menuAnimationRunning = true;
setNeedsDisplay = true;
sliderPosX = 64;
#ifdef DEBUG
Serial.println("PAGE MODE OFF");
#endif
}
#endif
}
// ========================================================
// MENU BUTTON
// ========================================================
bool buttonEvent() {
bool result = false;
bool menuButton = false;
if (digitalRead(ROTARY_SWITCH) == 1) {
menuButton = true;
}
if (menuButton && !rotaryButtonPressed) {
rotaryButtonPressed = true;
} else if (!menuButton && rotaryButtonPressed) {
rotaryButtonPressed = false;
result = true;
// FIXME: debounce for try, check if it's really needed
//delay(4);
}
return result;
}
// ========================================================
// DISPLAY - Screen Drawing
// ========================================================
void displayRenderCurrentPage() {
// OLED Display update
u8g2.firstPage();
do {
if (displayCurrentPage == 0) {
u8g2.setFont(u8g2_font_8x13B_tr);
u8g2.drawStr(0, 12, "HOME");
}
if (displayCurrentPage == 1) {
u8g2.setFont(u8g2_font_8x13B_tr);
u8g2.drawStr(0, 12, "SETTINGS");
}
if (displayCurrentPage == 2) {
if (!menuPageMode) {
u8g2.setFont(u8g2_font_8x13B_tr);
u8g2.drawStr(0, 10, "models available");
u8g2.setFont(u8g2_font_5x7_tr);
u8g2.drawStr(0, 18, "1) CHINOOK");
u8g2.drawStr(0, 25, "2) HELICOPTER");
u8g2.drawStr(0, 32, "3) BI-COPTER");
u8g2.drawStr(0, 39, "4) TRI-COPTER");
u8g2.drawStr(0, 46, "5) QUADCOPTER");
u8g2.drawStr(70, 18, "6) AIRPLANE");
u8g2.drawStr(70, 25, "7) RC-JET");
u8g2.drawStr(70, 32, "8) RC-CAR");
} else {
drawPageMenu();
if (setupMenuSelected == 0) {
u8g2.setFont(u8g2_font_5x7_tr);
u8g2.drawStr(0, 28, "CHINOOK");
u8g2.drawStr(0, 38, "PRESS TO SELECT");
}
if (setupMenuSelected == 1) {
u8g2.setFont(u8g2_font_5x7_tr);
u8g2.drawStr(0, 28, "HELICOPTER");
u8g2.drawStr(0, 38, "PRESS TO SELECT");
}
if (setupMenuSelected == 2) {
u8g2.setFont(u8g2_font_5x7_tr);
u8g2.drawStr(0, 28, "BI-COPTER");
u8g2.drawStr(0, 38, "PRESS TO SELECT");
}
if (setupMenuSelected == 3) {
u8g2.setFont(u8g2_font_5x7_tr);
u8g2.drawStr(0, 28, "TRI-COPTER");
u8g2.drawStr(0, 38, "PRESS TO SELECT");
}
if (setupMenuSelected == 4) {
u8g2.setFont(u8g2_font_5x7_tr);
u8g2.drawStr(0, 28, "QUADCOPTER");
u8g2.drawStr(0, 38, "PRESS TO SELECT");
}
if (setupMenuSelected == 5) {
u8g2.setFont(u8g2_font_5x7_tr);
u8g2.drawStr(0, 28, "AIRPLANE");
u8g2.drawStr(0, 38, "PRESS TO SELECT");
}
if (setupMenuSelected == 6) {
u8g2.setFont(u8g2_font_5x7_tr);
u8g2.drawStr(0, 28, "RC-JET");
u8g2.drawStr(0, 38, "PRESS TO SELECT");
}
if (setupMenuSelected == 7) {
u8g2.setFont(u8g2_font_5x7_tr);
u8g2.drawStr(0, 28, "RC-CAR");
u8g2.drawStr(0, 38, "PRESS TO SELECT");
}
if (setupMenuSelected == 8) {
// Version & Info
u8g2.setFont(u8g2_font_5x7_tr);
u8g2.setCursor(0, 28);
u8g2.print("RC TRANSMITTER");
u8g2.setCursor(0, 38);
u8g2.print("SW-VER. - 0.1");
u8g2.setCursor(0, 48);
u8g2.print("HW-VER. - 2.0");
u8g2.setCursor(0, 58);
u8g2.print("BY- VARUN SINGH");
}
}
}
if (displayCurrentPage == 0 || displayCurrentPage == 1) {
u8g2.setFont(u8g2_font_5x7_tr);
if (menuPageMode) {
u8g2.drawStr(0, 28, "ROTARY CONTROL ON PAGE");
u8g2.setCursor(0, 46);
u8g2.print("VALUE ");
u8g2.print(sliderPosX);
} else {
u8g2.drawStr(0, 28, "ROTARY CONTROL ON MENU");
}
drawSlider(31);
}
drawMenuBar();
} while ( u8g2.nextPage() );
}
void drawPageMenu() {
u8g2.setFont(u8g2_font_5x7_tr);
if (displayCurrentPage == 2) {
// center text
u8g2.drawRBox(36, 0, 58, 10, 2); //(x,y,w,h,r)
u8g2.setDrawColor(0);
u8g2.setCursor(38, 8);
u8g2.print(setupMenuItems[setupMenuSelected]);
u8g2.setDrawColor(1);
bool drawLeftTriangle = false;
bool drawRightTriangle = false;
if (setupMenuSelected < SETUP_MENU_ITEMS - 1) {
drawRightTriangle = true;
}
if (setupMenuSelected > 0) {
drawLeftTriangle = true;
}
if (drawLeftTriangle) {
// Triangle left
u8g2.drawTriangle(4, 1, 4, 9, 0, 5);
}
if (drawRightTriangle) {
// Triangle right
u8g2.drawTriangle(128 - 5, 1, 128 - 5, 9, 127, 5);
}
//u8g2.drawHLine(0, 10, 128);
}
}
void drawSlider(int yPos) {
u8g2.drawFrame(0, yPos, 128, 6);
if (sliderPosX < 1) {
sliderPosX = 0;
}
if (sliderPosX > 128) {
sliderPosX = 128;
}
u8g2.drawVLine(sliderPosX, yPos, 6);
}
void drawMenuBar() {
int textY = menuPosY;
u8g2.setFont(u8g2_font_5x7_tr);
u8g2.setDrawColor(1);
if (textY < MENU_POS_Y_HIDDEN) {
// left menu==================================================================================================
if (menuActive == 1) {
u8g2.drawRBox(0, 53, 25, 11, 2); //(x,y,w,h,r)
u8g2.setDrawColor(0);
}
if (menuActive != menuSelected && menuSelected == 1) {
u8g2.drawRFrame(0, 53, 25, 11, 2); //(x,y,w,h,r)
u8g2.setDrawColor(1);
}
u8g2.setCursor(3, 62);
u8g2.print("HOME");
u8g2.setDrawColor(1);
// center menu=================================================================================================
if (menuActive == 2) {
u8g2.drawRBox(45, 53, 40, 11, 2); //(x,y,w,h,r)
u8g2.setDrawColor(0);
}
if (menuActive != menuSelected && menuSelected == 2) {
u8g2.drawRFrame(45, 53, 40, 11, 2); //(x,y,w,h,r)
u8g2.setDrawColor(1);
}
u8g2.setCursor(48, 62);
u8g2.print("SETTING");
u8g2.setDrawColor(1);
// right menu==================================================================================================
if (menuActive == 3) {
u8g2.drawRBox(104, 53, 24, 11, 2); //(x,y,w,h,r)
u8g2.setDrawColor(0);
}
if (menuActive != menuSelected && menuSelected == 3) {
u8g2.drawRFrame(104, 53, 24, 11, 2); //(x,y,w,h,r)
u8g2.setDrawColor(1);
}
u8g2.setCursor(107, 62);
u8g2.print("MODE");
u8g2.setDrawColor(1);
}
}