#include #include #include #include #include #include #include "RF24.h" // Screen dimensions #define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 128 // Change this to 96 for 1.27" OLED. // You can use any (4 or) 5 pins #define SCLK_PIN 13 #define MOSI_PIN 11 #define MISO_PIN 12 #define DC_PIN 9 // was pin 4 #define CS_PIN 10 // was pin 5 #define RST_PIN 8 // was pin 6 #define RF_CE_PIN 7 // (chicp enable) #define RF_CSN_PIN 6 // (SPI select) // Control Data #define BUTTON_TOP 0 #define BUTTON_BOTTOM 1 #define JOYSTICK_BUTTON A4 #define JOYSTICK_X A6 #define JOYSTICK_Y A5 #include "Programs/Calculator/Calculator.h" #include "Programs/Snake/Snake.h" #include "Programs/Settings/Settings.h" #include "Programs/Asteroids/Asteroids.h" #include "Bitmaps.h" #include "Menu.h" #include "utility.h" Adafruit_SSD1351 tft = Adafruit_SSD1351(SCREEN_WIDTH, SCREEN_HEIGHT, &SPI, CS_PIN, DC_PIN, RST_PIN); RF24 radio(RF_CE_PIN, RF_CSN_PIN); inputData userInputs(BUTTON_TOP, BUTTON_BOTTOM, JOYSTICK_BUTTON); //programID currentProgram = NO_PROGRAM; unsigned long interval=1000; // the time we need to wait unsigned long previousMillis=0; // millis() returns an unsigned long. Program* currentProgram = nullptr; // will be renamed to currentProgram when fully implemented Program* nextProgram = nullptr; struct state { bool SoundEnabled = true; bool RunningProgram = false; bool InMenu = false; bool RadioEnabled = true; } MachineState; void displaySplashScreen(int duration); void getUserInput(inputData* inputs); void requestProgramChange(Program* program); void drawInfoBar(); float normalizeJoystick(int analogValue); void requestProgramChange(Program* program){ nextProgram = program; } // --- STARTUP -- // void setup(void) { Serial.begin(9600); Serial.println("Starting up..."); userInputs.buttonTop.setDebounceTime(25); userInputs.buttonBottom.setDebounceTime(25); userInputs.joyStickButton.setDebounceTime(25); tft.begin(); // spash screen goes here! displaySplashScreen(2000); // show spash for 2 seconds MachineState.InMenu = true; currentProgram = new Menu::Menu(); currentProgram->onEnter(&tft); Serial.println("Start sucsessful"); } // --- PROGRAM LOOP --- // void loop() { // need to loop as fast a possible to maintain framerate and responce time unsigned long currentMillis = millis(); // grab current time // handle program transistion if (nextProgram != nullptr) { if (currentProgram != nullptr) { currentProgram->onExit(); delete currentProgram; } currentProgram = nextProgram; nextProgram = nullptr; if (currentProgram != nullptr){ currentProgram->onEnter(&tft); } } // update current program if (currentProgram != nullptr){ getUserInput(&userInputs); currentProgram->loop(&tft, &userInputs); if (!currentProgram->disableInfoBar){ drawInfoBar(); } } // check if "interval" time has passed (1000 milliseconds) if ((unsigned long)(currentMillis - previousMillis) >= interval) { // do task previousMillis = millis(); } } void getUserInput(inputData *inputs){ // Call the loop() function for each button. This is required by ezButton. inputs->buttonTop.loop(); inputs->buttonBottom.loop(); inputs->joyStickButton.loop(); // The rest of the code can now get button states directly, e.g.: // if (inputs->buttonTop.isPressed()) { ... } // For now, let's keep joystick values simple int rawX = analogRead(JOYSTICK_X); int rawY = analogRead(JOYSTICK_Y); inputs->joyX = normalizeJoystick(rawX); inputs->joyY = normalizeJoystick(rawY); inputs->joystickCommand = COMMAND_NO; // check left/right commands if (rawX < LEFT_THRESHOLD){ inputs->joystickCommand = inputs->joystickCommand | COMMAND_LEFT; } else if (rawX > RIGHT_THRESHOLD){ inputs->joystickCommand = inputs->joystickCommand | COMMAND_RIGHT; } // check up/down commands if (rawY < UP_THRESHOLD){ inputs->joystickCommand = inputs->joystickCommand | COMMAND_UP; } else if (rawY > DOWN_THRESHOLD){ inputs->joystickCommand = inputs->joystickCommand | COMMAND_DOWN; } } void displaySplashScreen(int duration){ // - could play a tune and also show off the capability of the display with some // stylish graphics! maybe even 3d graphics if build a library for it tft.fillScreen(BLACK); tft.drawBitmap(0, 0, spash_screen_BMP, 128, 128, WHITE); tft.setCursor(10, 10); tft.setTextColor(GREEN); tft.println(F("B-TEK Advanced")); tft.setCursor(30, 10); tft.println(F("Booting in progress...")); delay(duration); tft.fillScreen(BLACK); } void drawInfoBar(){ // a bar on the time with data like battery life and current time and wifi status... maybe more (: tft.drawRect(0, 0, 128, 12, RED); tft.setCursor(5, 2); tft.setTextSize(1); tft.setTextColor(WHITE); tft.println(F("20:34")); tft.setCursor(90, 2); tft.println(F("[-->]")); } float normalizeJoystick(int analogValue) { // Account for the dead zone if (abs(analogValue - 512) < JOY_DEAD_ZONE) { return 0.0; } // Shift the range so the center is 0 float shiftedValue = analogValue - 512; return shiftedValue / 512.0; }