//8CH RC Transmitter with OLED display interface for Menu Options i.e Reverse, Borders, Elevon, Servo Trim, Battery & Factory Reset.
 //The Transmitter now has got STM32F103 aka BluePil and is an upgrade version of the previous with Nano and NRF24LO1.
 //by Neel. 10.01.2024

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
//#include <EEPROM.h>
#include "icon_arrays.h"  //header file contains OLED icon/images arrays

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3c ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
//
//See icon_arrays.h for icon & images arrays
//
  const int potPin = A0; int potVal; int value; //for debugging & testing only.
   // pins for buttons >>  dn, up, back/cancel, select/Ok >> Wokwi Btn Color GRN,YLW,BLU,RED
  const byte dnKey = 9; const byte upKey = 10; const byte bacKey = 11; const byte selKey = 12; // pins for buttons up, dn, back, select
  byte page1 = 0;   //Main Menu page switch case  // Menu Options i.e Reverse, Borders, Elevon, Servo Trim, Battery & Factory Reset Transmitter
  byte page2 = 0;   //Reverse menu switch case  // Channel Reverse function To Opposite movement of servo 
  byte page3 = 0;   //Boarders menu switch case  // set the PWM maximun & minimum // Servo max-min movement
  byte page4 = 0;   //Elevon menu switch case // Elevon menu is for Mixing Roll & Pitch for deltaWings
   //Current menus status. // 0 = not selected & 1 = selected.
  bool menuStatus = 0; bool reverseStatus = 0; bool borderStatus = 0; bool elevonStatus = 0; bool offsetStatus = 0; 
  bool trimStaus = 0; bool batteryStatus = 0; bool resetStatus = 0; //Current menus/sub menu status for entering concern menu while loop      
   // Channels Border Set.
  int rollMax=255; int rollMin=0; int pitchMax=255; int pitchMin=0;   // Max & Min Borders for servo movement called in Border_Map Function
  int thtMax=255; int thtMin=255; int yawMax=255; int yawMin=0;
   // Channels Reverse Status.
  bool revCh1 = false; bool revCh2 = false; bool revCh3 = false; bool revCh4 = false;   // Channels Reverse Status.
  bool revCh5 = false; bool revCh6 = false; bool revCh7 = false; bool revCh8 = false;
   // Elevon Status
  bool elevonMix = false;       // Elevon mode status. //True = Activated,
  byte offsetMix = 50;         // Roll+Pitch mix offset in %, default 50%, 
  
  
  
 
  
void setup() {
  pinMode(dnKey, INPUT_PULLUP);
  pinMode(upKey, INPUT_PULLUP);
  pinMode(bacKey, INPUT_PULLUP);
  pinMode(selKey, INPUT_PULLUP);
  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }

  
  setupGreet();
  delay(1000);
  display.clearDisplay();
}

void loop() {
  //
  //Put Transmitter Main Code Here
  //
  mainPage();  // main ch value page default screen i.e home page

  checkMenuStatus();

  while (menuStatus==1 ){ // menu page after press select button
   menuCheck();
   updateMenu();
   checkMenuStatus();
   checkReverseStatus();
   checkBorderStatus();
   checkElevonStatus();
   checkBorderStatus();
   checkBatteryStatus();
   checkResetStatus();

    while(reverseStatus==1){                //sub menu Reverse Page //menuPage/reversePage
     reverseCheck();
     updateReverse();
     checkReverseStatus();
    }

    while(borderStatus==1){         //sub menu Borders Page //menuPage/BordersPage
     borderCheck();       
     updateBorder();
     checkBorderStatus();
    }
    while(elevonStatus==1){                 //sub menu Elevon Page //menuPage/elevonPage
     elevonCheck();
     updateElevon();
     checkElevonStatus();
     checkOffsetStatus();
     while(offsetStatus==1){              //menuPage/eleronPage/offsetPage         
      offsetPage();
      checkOffsetStatus();
     }
    }
    while(batteryStatus==1){         //sub menu Battery Page //menuPage/BatteryPage
     batteryPage();       
     checkBatteryStatus();
    }
    while(resetStatus==1){         //sub menu Battery Page //menuPage/BatteryPage
     resetPage();       
     checkResetStatus();
    }
    
   }//main while loop end
  
  }//loop end
  
  

void checkBorderStatus(){
 if(page1==2){
  if (!digitalRead(selKey) && borderStatus==0){
      borderPage();
      borderStatus=1;
      while (!digitalRead(selKey));
      }
      else if (!digitalRead(bacKey) && borderStatus==1){
    menuPage();
    borderStatus=0;
    page3 =1;
    page1=1;
    while (!digitalRead(bacKey));
  }
 }
}  
void borderCheck(){
  if (!digitalRead(upKey)){       //When Button is Pressed change screen page 
    page3--;
    while (!digitalRead(upKey));
  }
  if (!digitalRead(dnKey)){       //When Button is Pressed change screen page 
    page3++;
    while (!digitalRead(dnKey));
  }
}
void updateBorder(){
 switch(page3){
    case 0:
    page3=1;
      break;
      
    case 1:
      borderPage();
      break;

    case 2:
      borCh2();
      break;

    case 3:
      borCh3();
      break;
    case 4:
      borCh4();
      break;
    case 5:
      borderPage();
      page3=1;
      break;
 }
}
void borderPage(){      
 display.clearDisplay();
 display.drawRect(14, 2, 58, 13, 1);
 display.drawRect(14, 17, 58, 13, 1);
 display.drawBitmap(4, 6, image_ButtonRight_4x7_bits, 4, 7, 1);
 display.drawRect(14, 32, 58, 13, 1);
 display.drawRect(14, 47, 58, 13, 1);
 display.setTextColor(1);
 display.setTextSize(1);
 display.setCursor(25, 5);
 display.setTextWrap(false);
 display.print("Ch - 1");
 display.setTextColor(1);
 display.setTextSize(1);
 display.setCursor(25, 20);
 display.setTextWrap(false);
 display.print("Ch - 2");
 display.setTextColor(1);
 display.setTextSize(1);
 display.setCursor(25, 35);
 display.setTextWrap(false);
 display.print("Ch - 3");
 display.setTextColor(1);
 display.setTextSize(1);
 display.setCursor(25, 50);
 display.setTextWrap(false);
 display.print("Ch - 4");
 display.drawRect(81, 2, 39, 13, 1);
 display.drawRect(81, 17, 39, 13, 1);
 display.drawRect(81, 32, 39, 13, 1);
 display.drawRect(81, 47, 39, 13, 1);
 display.setTextColor(1);
 display.setTextSize(1);
 display.setCursor(90, 5);
 display.setTextWrap(false);
 display.print("ROLL");
 display.setTextColor(1);
 display.setTextSize(1);
 display.setCursor(86, 20);
 display.setTextWrap(false);
 display.print("PITCH");
 display.setTextColor(1);
 display.setTextSize(1);
 display.setCursor(86, 35);
 display.setTextWrap(false);
 display.print("THRTL");
 display.setTextColor(1);
 display.setTextSize(1);
 display.setCursor(92, 50);
 display.setTextWrap(false);
 display.print("YAW");
 display.display();
}
void borCh2(){
  display.clearDisplay();
 display.drawRect(14, 2, 58, 13, 1);
 display.drawRect(14, 17, 58, 13, 1);
 display.drawBitmap(4, 20, image_ButtonRight_4x7_bits, 4, 7, 1);
 display.drawRect(14, 32, 58, 13, 1);
 display.drawRect(14, 47, 58, 13, 1);
 display.setTextColor(1);
 display.setTextSize(1);
 display.setCursor(25, 5);
 display.setTextWrap(false);
 display.print("Ch - 1");
 display.setTextColor(1);
 display.setTextSize(1);
 display.setCursor(25, 20);
 display.setTextWrap(false);
 display.print("Ch - 2");
 display.setTextColor(1);
 display.setTextSize(1);
 display.setCursor(25, 35);
 display.setTextWrap(false);
 display.print("Ch - 3");
 display.setTextColor(1);
 display.setTextSize(1);
 display.setCursor(25, 50);
 display.setTextWrap(false);
 display.print("Ch - 4");
 display.drawRect(81, 2, 39, 13, 1);
 display.drawRect(81, 17, 39, 13, 1);
 display.drawRect(81, 32, 39, 13, 1);
 display.drawRect(81, 47, 39, 13, 1);
 display.setTextColor(1);
 display.setTextSize(1);
 display.setCursor(90, 5);
 display.setTextWrap(false);
 display.print("ROLL");
 display.setTextColor(1);
 display.setTextSize(1);
 display.setCursor(86, 20);
 display.setTextWrap(false);
 display.print("PITCH");
 display.setTextColor(1);
 display.setTextSize(1);
 display.setCursor(86, 35);
 display.setTextWrap(false);
 display.print("THRTL");
 display.setTextColor(1);
 display.setTextSize(1);
 display.setCursor(92, 50);
 display.setTextWrap(false);
 display.print("YAW");
 display.display();
}
void borCh3(){
  display.clearDisplay();
 display.drawRect(14, 2, 58, 13, 1);
 display.drawRect(14, 17, 58, 13, 1);
 display.drawBitmap(4, 35, image_ButtonRight_4x7_bits, 4, 7, 1);
 display.drawRect(14, 32, 58, 13, 1);
 display.drawRect(14, 47, 58, 13, 1);
 display.setTextColor(1);
 display.setTextSize(1);
 display.setCursor(25, 5);
 display.setTextWrap(false);
 display.print("Ch - 1");
 display.setTextColor(1);
 display.setTextSize(1);
 display.setCursor(25, 20);
 display.setTextWrap(false);
 display.print("Ch - 2");
 display.setTextColor(1);
 display.setTextSize(1);
 display.setCursor(25, 35);
 display.setTextWrap(false);
 display.print("Ch - 3");
 display.setTextColor(1);
 display.setTextSize(1);
 display.setCursor(25, 50);
 display.setTextWrap(false);
 display.print("Ch - 4");
 display.drawRect(81, 2, 39, 13, 1);
 display.drawRect(81, 17, 39, 13, 1);
 display.drawRect(81, 32, 39, 13, 1);
 display.drawRect(81, 47, 39, 13, 1);
 display.setTextColor(1);
 display.setTextSize(1);
 display.setCursor(90, 5);
 display.setTextWrap(false);
 display.print("ROLL");
 display.setTextColor(1);
 display.setTextSize(1);
 display.setCursor(86, 20);
 display.setTextWrap(false);
 display.print("PITCH");
 display.setTextColor(1);
 display.setTextSize(1);
 display.setCursor(86, 35);
 display.setTextWrap(false);
 display.print("THRTL");
 display.setTextColor(1);
 display.setTextSize(1);
 display.setCursor(92, 50);
 display.setTextWrap(false);
 display.print("YAW");
 display.display();
}
void borCh4(){
  display.clearDisplay();
 display.drawRect(14, 2, 58, 13, 1);
 display.drawRect(14, 17, 58, 13, 1);
 display.drawBitmap(4, 50, image_ButtonRight_4x7_bits, 4, 7, 1);
 display.drawRect(14, 32, 58, 13, 1);
 display.drawRect(14, 47, 58, 13, 1);
 display.setTextColor(1);
 display.setTextSize(1);
 display.setCursor(25, 5);
 display.setTextWrap(false);
 display.print("Ch - 1");
 display.setTextColor(1);
 display.setTextSize(1);
 display.setCursor(25, 20);
 display.setTextWrap(false);
 display.print("Ch - 2");
 display.setTextColor(1);
 display.setTextSize(1);
 display.setCursor(25, 35);
 display.setTextWrap(false);
 display.print("Ch - 3");
 display.setTextColor(1);
 display.setTextSize(1);
 display.setCursor(25, 50);
 display.setTextWrap(false);
 display.print("Ch - 4");
 display.drawRect(81, 2, 39, 13, 1);
 display.drawRect(81, 17, 39, 13, 1);
 display.drawRect(81, 32, 39, 13, 1);
 display.drawRect(81, 47, 39, 13, 1);
 display.setTextColor(1);
 display.setTextSize(1);
 display.setCursor(90, 5);
 display.setTextWrap(false);
 display.print("ROLL");
 display.setTextColor(1);
 display.setTextSize(1);
 display.setCursor(86, 20);
 display.setTextWrap(false);
 display.print("PITCH");
 display.setTextColor(1);
 display.setTextSize(1);
 display.setCursor(86, 35);
 display.setTextWrap(false);
 display.print("THRTL");
 display.setTextColor(1);
 display.setTextSize(1);
 display.setCursor(92, 50);
 display.setTextWrap(false);
 display.print("YAW");
 display.display();
}
void borRoll(){
 display.clearDisplay(); 
 display.setTextColor(1);
 display.setTextSize(1);
 display.setCursor(8, 5);
 display.setTextWrap(false);
 display.print("Ch-1 Roll Min - Max");
 display.setTextColor(1);
 display.setTextSize(2);
 display.setCursor(15, 20);
 display.setTextWrap(false);
 display.print("Max-");
 display.drawLine(3, 14, 124, 14, 1);
 display.setTextColor(1);
 display.setTextSize(2);
 display.setCursor(15, 44);
 display.setTextWrap(false);
 display.print("Min-");
 display.setTextColor(1);
 display.setTextSize(2);
 display.setCursor(74, 20);
 display.setTextWrap(false);
 display.print("255");
 display.setTextColor(1);
 display.setTextSize(2);
 display.setCursor(76, 44);
 display.setTextWrap(false);
 display.print("0");
 display.drawBitmap(7, 24, image_ButtonRight_4x7_bits, 4, 7, 1);
 display.drawRect(2, 2, 124, 60, 1);
 display.display();
}
void trimPage(){                // Temporarey Under Construction
  display.clearDisplay();
 display.setTextColor(1);
 display.setTextSize(1);
 display.setCursor(10, 8);
 display.setTextWrap(false);
 display.print("THIS PAGE IS UNDER");
 display.setTextColor(1);
 display.setTextSize(1);
 display.setCursor(28, 24);
 display.setTextWrap(false);
 display.print("CONSTRUCTION");
 display.setTextColor(1);
 display.setTextSize(3);
 display.setCursor(36, 38);
 display.setTextWrap(false);
 display.print("(!)");
 display.display();
}