diff --git a/inc/sp140/display.h b/inc/sp140/display.h index 1f46eca..c99b92b 100644 --- a/inc/sp140/display.h +++ b/inc/sp140/display.h @@ -64,7 +64,7 @@ extern float wattHoursUsed; // Set up the display and show splash screen void setupDisplay(const STR_DEVICE_DATA_140_V1& deviceData, const HardwareConfig& board_config); -void displayMeta(const STR_DEVICE_DATA_140_V1& deviceData, int duration = 2000); +void displayMeta(const STR_DEVICE_DATA_140_V1& deviceData, int duration = 1500); // Clear screen and reset properties void resetRotation(unsigned int orientation); diff --git a/inc/sp140/globals.h b/inc/sp140/globals.h index 0937eef..3bde5e0 100644 --- a/inc/sp140/globals.h +++ b/inc/sp140/globals.h @@ -13,9 +13,6 @@ bool throttledFlag = true; float watts = 0; float wattHoursUsed = 0; -// sensor states -bool vibePresent = false; - int16_t _amps = 0; Servo esc; // Creating a servo class with name of esc diff --git a/inc/sp140/vibration.h b/inc/sp140/vibration.h new file mode 100644 index 0000000..d7971e9 --- /dev/null +++ b/inc/sp140/vibration.h @@ -0,0 +1,14 @@ +#ifndef INC_SP140_VIBRATION_H_ +#define INC_SP140_VIBRATION_H_ + +#include + +// Initialize the vibration motor +bool initVibeMotor(); + +// Notify with vibration +void pulseVibeMotor(); + +// Run a vibration sequence +bool runVibePattern(const unsigned int sequence[], int siz); +#endif // INC_SP140_VIBRATION_H_ diff --git a/src/sp140/display.cpp b/src/sp140/display.cpp index 6527cbb..ccc614f 100644 --- a/src/sp140/display.cpp +++ b/src/sp140/display.cpp @@ -84,14 +84,24 @@ void resetRotation(unsigned int rotation) { display->setRotation(rotation); // 1=right hand, 3=left hand } -// Show splash screen +// Show splash screen with animated text void displayMeta(const STR_DEVICE_DATA_140_V1& deviceData, int duration) { display->fillScreen(currentTheme->default_bg); display->setTextSize(1); display->setFont(&FreeSansBold12pt7b); display->setTextColor(currentTheme->default_text); - display->setCursor(25, 30); - display->println("OpenPPG"); + + // Animate "OpenPPG" text + const char* text = "OpenPPG"; + int x = 25; + int y = 30; + for (int i = 0; text[i] != '\0'; i++) { + display->setCursor(x, y); + display->print(text[i]); + x += display->getCursorX() - x; // Move cursor to the right + delay(100); // Adjust delay for animation speed + } + display->setFont(&Open_Sans_Reg_16); display->setTextSize(1); display->setCursor(60, 60); @@ -174,7 +184,7 @@ void updateDisplay( canvas.fillRect(0, 0, 1, 2, currentTheme->ui_accent); canvas.fillRect(0, 30, 1, 2, currentTheme->ui_accent); - // Display battery percent + // Display battery percent canvas.setCursor(108, 10 + FONT_HEIGHT_OFFSET); canvas.setTextColor(currentTheme->default_text); if (batteryPercent > 0) { @@ -273,7 +283,7 @@ void updateDisplay( float escTemp; escTemp = escTelemetry.temperatureC; - if (escTemp >= 100) { canvas.setTextColor(currentTheme->error_text); } // If temperature is over 100C, display in red. + if (escTemp >= 100) { canvas.setTextColor(currentTheme->error_text); } // If temperature is 100C+, display in red. if (escTemp == __FLT_MIN__ || escTemp == 0.0) { // If temperature is not available, display a question mark. canvas.printf("?%c", 247); } else { // Otherwise, display the temperature. (in degrees C) diff --git a/src/sp140/sp140-helpers.ino b/src/sp140/sp140-helpers.ino index 802b7e1..7ad394d 100644 --- a/src/sp140/sp140-helpers.ino +++ b/src/sp140/sp140-helpers.ino @@ -5,18 +5,6 @@ void initBuzz() { pinMode(board_config.buzzer_pin, OUTPUT); } -// initialize the vibration motor -bool initVibe() { - if (!board_config.enable_vib) { return false; } - if (!vibe.begin(&Wire1)) { return false; } - - vibe.selectLibrary(1); - vibe.setMode(DRV2605_MODE_INTTRIG); - vibrateNotify(); // initial boot vibration - - return true; -} - // on boot check for button to switch mode void modeSwitch(bool update_display) { // 0=CHILL 1=SPORT 2=LUDICROUS?! @@ -213,14 +201,6 @@ void printRawSentence() { Serial.println(); } -void vibrateNotify() { - if (!board_config.enable_vib) { return; } - - vibe.setWaveform(0, 15); // 1 through 117 (see example sketch) - vibe.setWaveform(1, 0); - vibe.go(); -} - // throttle easing function based on threshold/performance mode int limitedThrottle(int current, int last, int threshold) { if (current - last >= threshold) { // accelerating too fast. limit diff --git a/src/sp140/sp140.ino b/src/sp140/sp140.ino index d2eeab0..97f99fd 100644 --- a/src/sp140/sp140.ino +++ b/src/sp140/sp140.ino @@ -16,7 +16,6 @@ #include "../../inc/sp140/structs.h" // data structs #include // button clicks -#include // haptic controller #include #include // smooth out readings #include // smoothing for throttle @@ -43,6 +42,7 @@ #include "../../inc/sp140/display.h" #include "../../inc/sp140/altimeter.h" +#include "../../inc/sp140/vibration.h" using namespace ace_button; @@ -51,8 +51,6 @@ UBaseType_t uxCoreAffinityMask1 = (1 << 1); // Core 1 HardwareConfig board_config; -Adafruit_DRV2605 vibe; - // USB WebUSB object #ifdef USE_TINYUSB Adafruit_USBD_WebUSB usb_web; @@ -375,7 +373,9 @@ void setup140() { Wire1.setSDA(A0); // Have to use Wire1 because pins are assigned that in hardware Wire1.setSCL(A1); setupAltimeter(board_config.alt_wire); - vibePresent = initVibe(); + if (board_config.enable_vib) { + initVibeMotor(); + } } // main loop - everything runs in threads @@ -422,8 +422,8 @@ void resumeLEDTask() { void runDisarmAlert() { u_int16_t disarm_melody[] = { 2093, 1976, 880 }; - const unsigned int disarm_vibes[] = { 100, 0 }; - runVibe(disarm_vibes, 3); + const unsigned int disarm_vibes[] = { 78, 49 }; + runVibePattern(disarm_vibes, 2); playMelody(disarm_melody, 3); } @@ -592,7 +592,7 @@ int averagePotBuffer() { // get the PPG ready to fly bool armSystem() { uint16_t arm_melody[] = { 1760, 1976, 2093 }; - const unsigned int arm_vibes[] = { 70, 33, 0 }; + const unsigned int arm_vibes[] = { 1, 85, 1, 85, 1, 85, 1 }; esc.writeMicroseconds(ESC_DISARMED_PWM); // initialize the signal to low @@ -602,7 +602,7 @@ bool armSystem() { vTaskSuspend(blinkLEDTaskHandle); setLEDs(HIGH); // solid LED while armed - runVibe(arm_vibes, 3); + runVibePattern(arm_vibes, 7); playMelody(arm_melody, 3); return true; @@ -617,11 +617,24 @@ bool throttleEngaged() { return false; } -void playCruiseSound() { - vibrateNotify(); - if (ENABLE_BUZ) { - uint16_t notify_melody[] = { 900, 900 }; - playMelody(notify_melody, 2); + +void setCruise() { + // IDEA: fill a "cruise indicator" as long press activate happens + // or gradually change color from blue to yellow with time + if (!throttleSafe()) { // using pot/throttle + cruisedPotVal = pot->getValue(); // save current throttle val + cruisedAtMillis = millis(); // start timer + // throttle handle runs fast and a lot. need to set the timer before + // setting cruise so its updated in time + // TODO since these values are accessed in another task make sure memory safe + cruising = true; + pulseVibeMotor(); + + if (ENABLE_BUZ) { + uint16_t notify_melody[] = { 900, 900 }; + playMelody(notify_melody, 2); + } + } } @@ -629,11 +642,12 @@ void afterCruiseStart() { cruisedPotVal = pot->getValue(); cruisedAtMillis = millis(); playCruiseSound(); -} + pulseVibeMotor(); -void afterCruiseEnd() { - cruisedPotVal = 0; - playCruiseSound(); + if (ENABLE_BUZ) { + uint16_t notify_melody[] = { 500, 500 }; + playMelody(notify_melody, 2); + } } unsigned long prevPwrMillis = 0; diff --git a/src/sp140/utilities.ino b/src/sp140/utilities.ino index 0f1c968..05e90e2 100644 --- a/src/sp140/utilities.ino +++ b/src/sp140/utilities.ino @@ -61,16 +61,6 @@ void blinkLED() { setLEDs(ledState); } -bool runVibe(const unsigned int sequence[], int siz) { - if (!vibePresent) { return false; } - - for (int thisVibe = 0; thisVibe < siz; thisVibe++) { - vibe.setWaveform(thisVibe, sequence[thisVibe]); - } - vibe.go(); - return true; -} - /** * Plays a melody using a piezo buzzer. * diff --git a/src/sp140/vibration.cpp b/src/sp140/vibration.cpp new file mode 100644 index 0000000..cb1de5a --- /dev/null +++ b/src/sp140/vibration.cpp @@ -0,0 +1,34 @@ +#include "sp140/vibration.h" +#include "sp140/structs.h" +#include + +Adafruit_DRV2605 vibeMotor; + +bool vibeMotorInitialized = false; + +bool initVibeMotor() { + if (!vibeMotor.begin(&Wire1)) { return false; } + vibeMotor.selectLibrary(3); + vibeMotor.setMode(DRV2605_MODE_INTTRIG); + vibeMotorInitialized = true; + + pulseVibeMotor(); // initial boot vibration + return true; +} + +void pulseVibeMotor() { + const unsigned int pulsePattern[] = { 14, 1, 14 }; + runVibePattern(pulsePattern, 3); +} + +bool runVibePattern(const unsigned int pattern[], int patternSize) { + if (!vibeMotorInitialized) { return false; } + + for (int i = 0; i < patternSize; i++) { + vibeMotor.setWaveform(i, pattern[i]); + } + // add one extra empty cycle to ensure the motor is off at the end + vibeMotor.setWaveform(patternSize, 0); + vibeMotor.go(); + return true; +}