Advertisement
Sabersense

WIP Prop...

Nov 30th, 2024
27
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 30.99 KB | None | 0 0
  1. #ifndef PROPS_SABER_SABERSENSE_BUTTONS_H
  2. #define PROPS_SABER_SABERSENSE_BUTTONS_H
  3.  
  4.  
  5. #ifdef SABERSENSE_ARRAY_SELECTOR
  6. #ifndef SABERSENSE_NUM_ARRAYS // No default number of arrays - must be defined in config.
  7. #error "SABERSENSE_NUM_ARRAYS x must be defined in the config file."
  8. #endif
  9.  
  10. #ifdef SABERSENSE_BLADE_ID // Only one Sabersense BladeID standard permitted.
  11. #error "SABERSENSE_ARRAY_SELECTOR and SABERSENSE_BLADE_ID cannot be defined at the same time."
  12. #endif
  13.  
  14. // Function to play the corresponding sound.
  15. void PlaySound(const char* sound) {
  16. RefPtr<BufferedWavPlayer> player = GetFreeWavPlayer();
  17. if (player) {
  18. if (!player->PlayInCurrentDir(sound)) {
  19. player->Play(sound);
  20. }
  21. }
  22. }
  23.  
  24. struct SabersenseArraySelector {
  25. static int return_value; // Tracks the current array index.
  26. static const int sabersense_num_arrays = SABERSENSE_NUM_ARRAYS;
  27. static bool shouldPlaySound; // Flag to control if sound should be played.
  28. static unsigned long lastSwitchTime; // Track time of the last array switch.
  29. static const unsigned long soundDelay = 50; // Delay in ms before playing sound after switch.
  30. static bool isSwitchingInProgress; // Flag to indicate if array switch is in progress.
  31.  
  32. float id() {
  33. return return_value;
  34. }
  35.  
  36. // Forward cycle through arrays...
  37. static void cycleForward() {
  38. isSwitchingInProgress = true; // Mark that the switch is in progress.
  39. return_value = (return_value + 1) % sabersense_num_arrays;
  40. shouldPlaySound = true;
  41. lastSwitchTime = millis();
  42. isSwitchingInProgress = false; // Mark that the switch is complete.
  43. }
  44.  
  45. // Backward cycle through arrays.
  46. static void cycleBackward() {
  47. isSwitchingInProgress = true; // Mark that the switch is in progress
  48. return_value = (return_value - 1 + sabersense_num_arrays) % sabersense_num_arrays; // Ensures wrap.
  49. shouldPlaySound = true;
  50. lastSwitchTime = millis();
  51. isSwitchingInProgress = false; // Mark that the switch is complete.
  52. }
  53.  
  54. // Function to play corresponding sound file based on array index.
  55. static void playArraySound(int arrayIndex) {
  56. const char* soundFile = nullptr;
  57. switch (arrayIndex) {
  58. // Maximum of eight arrays possible.
  59. case 0: soundFile = "array1.wav"; break;
  60. case 1: soundFile = "array2.wav"; break;
  61. case 2: soundFile = "array3.wav"; break;
  62. case 3: soundFile = "array4.wav"; break;
  63. case 4: soundFile = "array5.wav"; break;
  64. case 5: soundFile = "array6.wav"; break;
  65. case 6: soundFile = "array7.wav"; break;
  66. case 7: soundFile = "array8.wav"; break;
  67. default: return; // No sound for invalid array index.
  68. }
  69. PlaySound(soundFile); // Calls custom PlaySound function.
  70. }
  71.  
  72. // Function to check enough time has passed to play the sound.
  73. static void checkAndPlaySound() {
  74. if (shouldPlaySound && !isSwitchingInProgress && (millis() - lastSwitchTime >= soundDelay)) {
  75. playArraySound(return_value); // Play sound for the current array.
  76. shouldPlaySound = false; // Reset flag after sound is played.
  77. }
  78. }
  79.  
  80. // Loop function, needs to be called periodically.
  81. static void loop() {
  82. checkAndPlaySound(); // Check if sound should be played after switching arrays.
  83. }
  84.  
  85. // This update function is a more explicit name for the periodic call.
  86. static void update() {
  87. // The `update` method is meant to be called periodically in your main loop
  88. // and will invoke the `loop()` method internally.
  89. loop(); // This ensures periodic checks for sound playing.
  90. }
  91. };
  92.  
  93. // Static member initialization
  94. int SabersenseArraySelector::return_value = 0; // Start with the first array (index 0).
  95. bool SabersenseArraySelector::shouldPlaySound = false; // Flag to control sound playback.
  96. unsigned long SabersenseArraySelector::lastSwitchTime = 0; // Track time of array switch.
  97. bool SabersenseArraySelector::isSwitchingInProgress = false; // Flag for switch status.
  98.  
  99. #undef BLADE_ID_CLASS_INTERNAL
  100. #define BLADE_ID_CLASS_INTERNAL SabersenseArraySelector
  101. #undef BLADE_ID_CLASS
  102. #define BLADE_ID_CLASS SabersenseArraySelector
  103. #endif
  104.  
  105.  
  106.  
  107.  
  108.  
  109.  
  110.  
  111.  
  112.  
  113.  
  114. void NextBladeArray() {
  115. current_config = blades + (current_config - blades + 1) % NELEM(blades);
  116. FakeFindBladeAgain();
  117. // option if no array.wavs used, play font.wav instead
  118. // SaberBase::DoNewFont();
  119. SFX_array.Select(current_config - blades);
  120. hybrid_font.PlayCommon(&SFX_array);
  121. }
  122.  
  123. // Manual Blade Array Selection version of FindBladeAgain()
  124. void FakeFindBladeAgain() {
  125. // Do everything FindBladeAgain() and FindBlade() do, except for recalculating best_config
  126. ONCEPERBLADE(UNSET_BLADE_STYLE)
  127.  
  128. #undef DEACTIVATE
  129. #define DEACTIVATE(N) do { \
  130. if (current_config->blade##N) \
  131. current_config->blade##N->Deactivate(); \
  132. } while(0);
  133.  
  134. ONCEPERBLADE(DEACTIVATE);
  135. SaveVolumeIfNeeded();
  136.  
  137. #undef ACTIVATE
  138. #define ACTIVATE(N) do { \
  139. if (!current_config->blade##N) { \
  140. goto bad_blade; \
  141. } \
  142. current_config->blade##N->Activate(N); \
  143. } while(0);
  144.  
  145. ONCEPERBLADE(ACTIVATE);
  146. RestoreGlobalState();
  147.  
  148. #ifdef SAVE_PRESET
  149. ResumePreset();
  150. #else
  151. SetPreset(0, false);
  152. #endif // SAVE_PRESET
  153. return;
  154.  
  155. #if NUM_BLADES != 0
  156. bad_blade:
  157. ProffieOSErrors::error_in_blade_array();
  158. #endif
  159. }
  160.  
  161.  
  162.  
  163.  
  164.  
  165.  
  166.  
  167.  
  168.  
  169.  
  170.  
  171.  
  172. #include "prop_base.h"
  173. #include "../sound/hybrid_font.h"
  174.  
  175. #undef PROP_TYPE
  176. #define PROP_TYPE SabersenseButtons
  177.  
  178. #ifndef MOTION_TIMEOUT
  179. #define MOTION_TIMEOUT 60 * 15 * 1000
  180. #endif
  181.  
  182. #ifndef SABERSENSE_SWING_ON_SPEED
  183. #define SABERSENSE_SWING_ON_SPEED 250
  184. #endif
  185.  
  186. #ifndef SABERSENSE_LOCKUP_DELAY
  187. #define SABERSENSE_LOCKUP_DELAY 200
  188. #endif
  189.  
  190. #ifndef SABERSENSE_FORCE_PUSH_LENGTH
  191. #define SABERSENSE_FORCE_PUSH_LENGTH 5
  192. #endif
  193.  
  194. #ifndef BUTTON_DOUBLE_CLICK_TIMEOUT
  195. #define BUTTON_DOUBLE_CLICK_TIMEOUT 300
  196. #endif
  197.  
  198. #ifndef BUTTON_SHORT_CLICK_TIMEOUT
  199. #define BUTTON_SHORT_CLICK_TIMEOUT 300
  200. #endif
  201.  
  202. #ifndef BUTTON_HELD_TIMEOUT
  203. #define BUTTON_HELD_TIMEOUT 300
  204. #endif
  205.  
  206. #ifndef BUTTON_HELD_MEDIUM_TIMEOUT
  207. #define BUTTON_HELD_MEDIUM_TIMEOUT 1000
  208. #endif
  209.  
  210. #ifndef BUTTON_HELD_LONG_TIMEOUT
  211. #define BUTTON_HELD_LONG_TIMEOUT 2000
  212. #endif
  213.  
  214. #ifdef SABERSENSE_SWING_ON
  215. #define SABERSENSE_SWING_GESTURE
  216. #endif
  217.  
  218. #ifdef SABERSENSE_STAB_ON
  219. #define SABERSENSE_STAB_GESTURE
  220. #endif
  221.  
  222. #ifdef SABERSENSE_TWIST_ON
  223. #define SABERSENSE_TWIST_GESTURE
  224. #endif
  225.  
  226. #ifdef SABERSENSE_THRUST_ON
  227. #define SABERSENSE_THRUST_GESTURE
  228. #endif
  229.  
  230. EFFECT(dim); // for EFFECT_POWERSAVE
  231. EFFECT(battery); // for EFFECT_BATTERY_LEVEL
  232. EFFECT(vmbegin); // for Begin Volume Menu
  233. EFFECT(vmend); // for End Volume Menu
  234. EFFECT(volup); // for increse volume
  235. EFFECT(voldown); // for decrease volume
  236. EFFECT(volmin); // for minimum volume reached
  237. EFFECT(volmax); // for maximum volume reached
  238. EFFECT(faston); // for EFFECT_FAST_ON
  239. EFFECT(blstbgn); // for Begin Multi-Blast
  240. EFFECT(blstend); // for End Multi-Blast
  241. #ifdef SABERSENSE_OS7_LEGACY_SUPPORT
  242. EFFECT(quote); // for playing quotes. Required for ProffieOS 7.x.
  243. EFFECT(array); // for playing array idents. Required for ProffieOS 7.x.
  244. #endif
  245.  
  246.  
  247. // The Saber class implements the basic states and actions
  248. // for the saber.
  249. class SabersenseButtons : public PROP_INHERIT_PREFIX PropBase {
  250. public:
  251. SabersenseButtons() : PropBase() {}
  252. const char* name() override { return "SabersenseButtons"; }
  253.  
  254. void Loop() override {
  255. PropBase::Loop();
  256. DetectTwist();
  257. Vec3 mss = fusor.mss();
  258. if (SaberBase::IsOn()) {
  259. DetectSwing();
  260. if (auto_lockup_on_ &&
  261. !swinging_ &&
  262. fusor.swing_speed() > 120 &&
  263. millis() - clash_impact_millis_ > SABERSENSE_LOCKUP_DELAY &&
  264. SaberBase::Lockup()) {
  265. SaberBase::DoEndLockup();
  266. SaberBase::SetLockup(SaberBase::LOCKUP_NONE);
  267. auto_lockup_on_ = false;
  268. }
  269. if (auto_melt_on_ &&
  270. !swinging_ &&
  271. fusor.swing_speed() > 60 &&
  272. millis() - clash_impact_millis_ > SABERSENSE_LOCKUP_DELAY &&
  273. SaberBase::Lockup()) {
  274. SaberBase::DoEndLockup();
  275. SaberBase::SetLockup(SaberBase::LOCKUP_NONE);
  276. auto_melt_on_ = false;
  277. }
  278.  
  279. // EVENT_PUSH
  280. if (fabs(mss.x) < 3.0 &&
  281. mss.y * mss.y + mss.z * mss.z > 70 &&
  282. fusor.swing_speed() < 30 &&
  283. fabs(fusor.gyro().x) < 10) {
  284. if (millis() - push_begin_millis_ > SABERSENSE_FORCE_PUSH_LENGTH) {
  285. Event(BUTTON_NONE, EVENT_PUSH);
  286. push_begin_millis_ = millis();
  287. }
  288. } else {
  289. push_begin_millis_ = millis();
  290. }
  291. } else {
  292. // EVENT_SWING - Swing On gesture control to allow fine tuning of speed needed to ignite
  293. if (millis() - saber_off_time_ < MOTION_TIMEOUT) {
  294. SaberBase::RequestMotion();
  295. if (swinging_ && fusor.swing_speed() < 90) {
  296. swinging_ = false;
  297. }
  298. if (!swinging_ && fusor.swing_speed() > SABERSENSE_SWING_ON_SPEED) {
  299. swinging_ = true;
  300. Event(BUTTON_NONE, EVENT_SWING);
  301. }
  302. }
  303. // EVENT_THRUST
  304. if (mss.y * mss.y + mss.z * mss.z < 16.0 &&
  305. mss.x > 14 &&
  306. fusor.swing_speed() < 150) {
  307. if (millis() - thrust_begin_millis_ > 15) {
  308. Event(BUTTON_NONE, EVENT_THRUST);
  309. thrust_begin_millis_ = millis();
  310. }
  311. } else {
  312. thrust_begin_millis_ = millis();
  313. }
  314. }
  315. }
  316.  
  317. // Volume Menu
  318. void VolumeUp() {
  319. STDOUT.println("Volume up");
  320. if (dynamic_mixer.get_volume() < VOLUME) {
  321. dynamic_mixer.set_volume(std::min<int>(VOLUME + VOLUME * 0.1,
  322. dynamic_mixer.get_volume() + VOLUME * 0.10));
  323. if (SFX_volup) {
  324. hybrid_font.PlayCommon(&SFX_volup);
  325. } else {
  326. beeper.Beep(0.5, 2000);
  327. }
  328. STDOUT.print("Volume Up - Current Volume: ");
  329. STDOUT.println(dynamic_mixer.get_volume());
  330. } else {
  331. // Cycle through ends of Volume Menu option
  332. #ifdef VOLUME_MENU_CYCLE
  333. if (!max_vol_reached_) {
  334. if (SFX_volmax) {
  335. hybrid_font.PlayCommon(&SFX_volmax);
  336. } else {
  337. beeper.Beep(0.5, 3000);
  338. }
  339. STDOUT.print("Maximum Volume: ");
  340. max_vol_reached_ = true;
  341. } else {
  342. dynamic_mixer.set_volume(std::max<int>(VOLUME * 0.1,
  343. dynamic_mixer.get_volume() - VOLUME * 0.90));
  344. if (SFX_volmin) {
  345. hybrid_font.PlayCommon(&SFX_volmin);
  346. } else {
  347. beeper.Beep(0.5, 1000);
  348. }
  349. STDOUT.print("Minimum Volume: ");
  350. max_vol_reached_ = false;
  351. }
  352. #else
  353. if (SFX_volmax) {
  354. hybrid_font.PlayCommon(&SFX_volmax);
  355. } else {
  356. beeper.Beep(0.5, 3000);
  357. }
  358. STDOUT.print("Maximum Volume: ");
  359. #endif
  360. }
  361. }
  362.  
  363. void VolumeDown() {
  364. STDOUT.println("Volume Down");
  365. if (dynamic_mixer.get_volume() > (0.10 * VOLUME)) {
  366. dynamic_mixer.set_volume(std::max<int>(VOLUME * 0.1,
  367. dynamic_mixer.get_volume() - VOLUME * 0.10));
  368. if (SFX_voldown) {
  369. hybrid_font.PlayCommon(&SFX_voldown);
  370. } else {
  371. beeper.Beep(0.5, 2000);
  372. }
  373. STDOUT.print("Volume Down - Current Volume: ");
  374. STDOUT.println(dynamic_mixer.get_volume());
  375. } else {
  376. #ifdef VOLUME_MENU_CYCLE
  377. if (!min_vol_reached_) {
  378. if (SFX_volmin) {
  379. hybrid_font.PlayCommon(&SFX_volmin);
  380. } else {
  381. beeper.Beep(0.5, 1000);
  382. }
  383. STDOUT.print("Minimum Volume: ");
  384. min_vol_reached_ = true;
  385. } else {
  386. dynamic_mixer.set_volume(VOLUME);
  387. if (SFX_volmax) {
  388. hybrid_font.PlayCommon(&SFX_volmax);
  389. } else {
  390. beeper.Beep(0.5, 3000);
  391. }
  392. STDOUT.print("Maximum Volume: ");
  393. min_vol_reached_ = false;
  394. }
  395. #else
  396. if (SFX_volmin) {
  397. hybrid_font.PlayCommon(&SFX_volmin);
  398. } else {
  399. beeper.Beep(0.5, 1000);
  400. }
  401. STDOUT.print("Minimum Volume: ");
  402. #endif
  403.  
  404. }
  405. }
  406.  
  407. void PlaySound(const char* sound) {
  408. RefPtr<BufferedWavPlayer> player = GetFreeWavPlayer();
  409. if (player) {
  410. if (!player->PlayInCurrentDir(sound)) player->Play(sound);
  411. }
  412. }
  413.  
  414. bool Event2(enum BUTTON button, EVENT event, uint32_t modifiers) override {
  415. switch (EVENTID(button, event, modifiers)) {
  416. case EVENTID(BUTTON_POWER, EVENT_PRESSED, MODE_ANY_BUTTON | MODE_ON):
  417. case EVENTID(BUTTON_POWER, EVENT_PRESSED, MODE_ANY_BUTTON | MODE_OFF):
  418. case EVENTID(BUTTON_AUX, EVENT_PRESSED, MODE_ANY_BUTTON | MODE_ON):
  419. case EVENTID(BUTTON_AUX, EVENT_PRESSED, MODE_ANY_BUTTON | MODE_OFF):
  420. SaberBase::RequestMotion();
  421. #ifdef SABERSENSE_BUTTON_CLICKER
  422. // Intended for Scavenger hilt where wheel makes tactile feel difficult.
  423. PlaySound("press.wav"); // Requires press.wav file to work.
  424. #endif
  425. return false;
  426. case EVENTID(BUTTON_POWER, EVENT_RELEASED, MODE_ANY_BUTTON | MODE_ON):
  427. case EVENTID(BUTTON_POWER, EVENT_RELEASED, MODE_ANY_BUTTON | MODE_OFF):
  428. case EVENTID(BUTTON_AUX, EVENT_RELEASED, MODE_ANY_BUTTON | MODE_ON):
  429. case EVENTID(BUTTON_AUX, EVENT_RELEASED, MODE_ANY_BUTTON | MODE_OFF):
  430. #ifdef SABERSENSE_BUTTON_CLICKER
  431. // Intended for Scavenger hilt where wheel makes tactile feel difficult.
  432. PlaySound("release.wav"); // Requires release.wav file to work.
  433. #endif
  434. if (SaberBase::Lockup()) {
  435. SaberBase::DoEndLockup();
  436. SaberBase::SetLockup(SaberBase::LOCKUP_NONE);
  437. return true;
  438. } else {
  439. return false;
  440. }
  441.  
  442. case EVENTID(BUTTON_AUX, EVENT_PRESSED, MODE_ON):
  443. case EVENTID(BUTTON_AUX2, EVENT_PRESSED, MODE_ON):
  444. if (accel_.x < -0.15) {
  445. pointing_down_ = true;
  446. } else {
  447. pointing_down_ = false;
  448. }
  449. return true;
  450.  
  451. // Gesture Controls
  452. #ifdef SABERSENSE_SWING_ON
  453. case EVENTID(BUTTON_NONE, EVENT_SWING, MODE_OFF):
  454. // Due to motion chip startup on boot creating false ignition we delay Swing On at boot for 3000ms
  455. if (millis() > 3000) {
  456. FastOn();
  457. }
  458. return true;
  459. #endif
  460.  
  461. #ifdef SABERSENSE_TWIST_ON
  462. case EVENTID(BUTTON_NONE, EVENT_TWIST, MODE_OFF):
  463. // Delay twist events to prevent false trigger from over twisting
  464. if (millis() - last_twist_ > 2000 &&
  465. millis() - saber_off_time_ > 1000) {
  466. FastOn();
  467. last_twist_ = millis();
  468. }
  469. return true;
  470. #endif
  471.  
  472. #ifdef SABERSENSE_TWIST_OFF
  473. case EVENTID(BUTTON_NONE, EVENT_TWIST, MODE_ON):
  474. // Delay twist events to prevent false trigger from over twisting
  475. if (millis() - last_twist_ > 3000) {
  476. Off();
  477. last_twist_ = millis();
  478. saber_off_time_ = millis();
  479. }
  480. return true;
  481. #endif
  482.  
  483. #ifdef SABERSENSE_STAB_ON
  484. case EVENTID(BUTTON_NONE, EVENT_STAB, MODE_OFF):
  485. if (millis() - saber_off_time_ > 1000) {
  486. FastOn();
  487. }
  488. return true;
  489. #endif
  490.  
  491. #ifdef SABERSENSE_THRUST_ON
  492. case EVENTID(BUTTON_NONE, EVENT_THRUST, MODE_OFF):
  493. if (millis() - saber_off_time_ > 1000) {
  494. FastOn();
  495. }
  496. return true;
  497. #endif
  498.  
  499. // Multiple Skips only available with 2 button installs.
  500. // Skips forward five fonts if pointing up, skips back five fonts if pointing down.
  501. case EVENTID(BUTTON_AUX, EVENT_SECOND_SAVED_CLICK_SHORT, MODE_OFF):
  502. // backwards if pointing down
  503. SetPreset(current_preset_.preset_num + (fusor.angle1() < -M_PI / 4 ? -5 : 5), true);
  504. #ifdef SAVE_PRESET
  505. SaveState(current_preset_.preset_num);
  506. #endif
  507. return true;
  508.  
  509. // Skips forward ten fonts if pointing up, skips back ten fonts if pointing down.
  510. case EVENTID(BUTTON_AUX, EVENT_THIRD_SAVED_CLICK_SHORT, MODE_OFF):
  511. // backwards if pointing down
  512. SetPreset(current_preset_.preset_num + (fusor.angle1() < -M_PI / 4 ? -10 : 10), true);
  513. #ifdef SAVE_PRESET
  514. SaveState(current_preset_.preset_num);
  515. #endif
  516. return true;
  517.  
  518. // Saber ON AND Volume Adjust.
  519. case EVENTID(BUTTON_POWER, EVENT_FIRST_SAVED_CLICK_SHORT, MODE_OFF):
  520. IgnoreClash(50); // Hopefully prevents false clashes due to 'clicky' button.
  521. // Low threshold so as not to conflict with 1-button lockup or volume menu.
  522. if (!mode_volume_) {
  523. On();
  524. } else {
  525. if (fusor.angle1() > 0) {
  526. VolumeUp();
  527. } else {
  528. VolumeDown();
  529. }
  530. }
  531. return true;
  532.  
  533. // Modified 2 button 'next/previous preset' AND volume down,
  534. // to align with multiple skips above.
  535. // Forward one font pointing up, back one font pointing down.
  536. case EVENTID(BUTTON_AUX, EVENT_FIRST_SAVED_CLICK_SHORT, MODE_OFF):
  537. // backwards if pointing down
  538. if (!mode_volume_) {
  539. SetPreset(current_preset_.preset_num + (fusor.angle1() < -M_PI / 4 ? -1 : 1), true);
  540. } else {
  541. VolumeDown();
  542. }
  543. #ifdef SAVE_PRESET
  544. SaveState(current_preset_.preset_num);
  545. #endif
  546. return true;
  547.  
  548. // 1 button 'next/previous preset' command.
  549. // Forward one font pointing up, back one font pointing down.
  550. #if NUM_BUTTONS == 1
  551. #ifndef SABERSENSE_SWAP_MUTE_PRESET_1B
  552. case EVENTID(BUTTON_POWER, EVENT_SECOND_HELD, MODE_OFF):
  553. #else
  554. case EVENTID(BUTTON_POWER, EVENT_FIRST_CLICK_LONG, MODE_OFF):
  555. #endif
  556. // backwards if pointing down
  557. if (!mode_volume_) {
  558. SetPreset(current_preset_.preset_num + (fusor.angle1() < -M_PI / 4 ? -1 : 1), true);
  559. } else {
  560. VolumeDown();
  561. }
  562. #ifdef SAVE_PRESET
  563. SaveState(current_preset_.preset_num);
  564. #endif
  565. return true;
  566. #endif
  567.  
  568.  
  569. // 1 Button skips to first preset (up) or last preset (down)
  570. // or middle preset if horizontal:
  571. #if NUM_BUTTONS == 2
  572. case EVENTID(BUTTON_AUX, EVENT_FIRST_HELD_LONG, MODE_OFF):
  573. #endif
  574. case EVENTID(BUTTON_POWER, EVENT_FIRST_HELD_LONG, MODE_OFF):
  575. #define DEGREES_TO_RADIANS (M_PI / 180)
  576. if (fusor.angle1() > 45 * DEGREES_TO_RADIANS) {
  577. // If pointing up
  578. SetPreset(0, true);
  579. } else if (fusor.angle1() < -45 * DEGREES_TO_RADIANS) {
  580. // If pointing down
  581. SetPreset(-1, true);
  582. } else {
  583. // If horizontal
  584. CurrentPreset tmp;
  585. tmp.SetPreset(-1);
  586. SetPreset(tmp.preset_num / 2, true);
  587. }
  588. #ifdef SAVE_PRESET
  589. SaveState(current_preset_.preset_num);
  590. #endif
  591. return true;
  592.  
  593. // 1 and 2 button: Previous Preset, retained legacy control.
  594. #if NUM_BUTTONS == 2
  595. case EVENTID(BUTTON_POWER, EVENT_CLICK_SHORT, MODE_OFF | BUTTON_AUX):
  596. #endif
  597. if (!mode_volume_) {
  598. previous_preset();
  599. }
  600. return true;
  601.  
  602. // Skips to first preset (up) or last (battery or charge) preset (down)
  603. // or middle preset if horizontal:
  604. #if NUM_BUTTONS == 2
  605. // 2 button: First Preset
  606. case EVENTID(BUTTON_AUX, EVENT_HELD_LONG, MODE_OFF):
  607. #endif
  608. #define DEGREES_TO_RADIANS (M_PI / 180)
  609. if (fusor.angle1() > 45 * DEGREES_TO_RADIANS) {
  610. // If pointing up
  611. SetPreset(0, true);
  612. } else if (fusor.angle1() < -45 * DEGREES_TO_RADIANS) {
  613. // If pointing down
  614. SetPreset(-1, true);
  615. } else {
  616. // If horizontal
  617. CurrentPreset tmp;
  618. tmp.SetPreset(-1);
  619. SetPreset(tmp.preset_num / 2, true);
  620. }
  621. #ifdef SAVE_PRESET
  622. SaveState(current_preset_.preset_num);
  623. #endif
  624. return true;
  625.  
  626. // Manual blade array selector.
  627. #ifdef SABERSENSE_ARRAY_SELECTOR
  628. case EVENTID(BUTTON_POWER, EVENT_THIRD_SAVED_CLICK_SHORT, MODE_OFF):
  629. // Cycles through blade arrays regardless of BladeID status.
  630. if (fusor.angle1() > 0) {
  631. // Cycles forward...
  632. SabersenseArraySelector::cycleForward();
  633. } else {
  634. // Cycles backward.
  635. SabersenseArraySelector::cycleBackward();
  636. }
  637. FindBladeAgain();
  638. SabersenseArraySelector::checkAndPlaySound();
  639. return true;
  640. #endif
  641. /*
  642. #ifdef SABERSENSE_BLADE_ID
  643. case EVENTID(BUTTON_POWER, EVENT_THIRD_SAVED_CLICK_SHORT, MODE_OFF):
  644. FindBladeAgain(); // Perform the scan and find the blade ID
  645. Serial.println("Switching blade...");
  646. SabersenseBladeID::switchBlade(SabersenseBladeID::return_value); // Directly switch the blade and play the sound
  647. return true;
  648. #endif
  649. */
  650.  
  651.  
  652.  
  653.  
  654.  
  655.  
  656.  
  657. #ifdef SABERSENSE_BLADE_ID
  658. case EVENTID(BUTTON_POWER, EVENT_THIRD_SAVED_CLICK_SHORT, MODE_OFF):
  659. NextBladeArray()
  660. // TriggerBladeID();
  661. return true;
  662. #endif
  663.  
  664.  
  665.  
  666.  
  667.  
  668.  
  669.  
  670.  
  671.  
  672.  
  673.  
  674.  
  675.  
  676.  
  677.  
  678.  
  679.  
  680.  
  681. // Activate Muted 1 Button
  682. #if NUM_BUTTONS == 1
  683. #ifndef SABERSENSE_SWAP_MUTE_PRESET_1B
  684. case EVENTID(BUTTON_POWER, EVENT_FIRST_CLICK_LONG, MODE_OFF):
  685. #else
  686. case EVENTID(BUTTON_POWER, EVENT_SECOND_HELD, MODE_OFF):
  687. #endif
  688. if (SetMute(true)) {
  689. unmute_on_deactivation_ = true;
  690. On();
  691. }
  692. return true;
  693. #endif
  694.  
  695. // Activate Muted 2 Button
  696. #if NUM_BUTTONS == 2
  697. case EVENTID(BUTTON_POWER, EVENT_FIRST_CLICK_LONG, MODE_OFF):
  698. if (SetMute(true)) {
  699. unmute_on_deactivation_ = true;
  700. On();
  701. }
  702. return true;
  703. #endif
  704.  
  705. // Turn Blade OFF
  706. #if NUM_BUTTONS > 1
  707. // 2 button
  708. case EVENTID(BUTTON_POWER, EVENT_FIRST_HELD_MEDIUM, MODE_ON):
  709. #else
  710. // 1 button
  711. case EVENTID(BUTTON_POWER, EVENT_FIRST_HELD_LONG, MODE_ON):
  712. #endif
  713. if (!SaberBase::Lockup()) {
  714. #ifndef DISABLE_COLOR_CHANGE
  715. if (SaberBase::GetColorChangeMode() != SaberBase::COLOR_CHANGE_MODE_NONE) {
  716. // Just exit color change mode.
  717. // Don't turn saber off.
  718. ToggleColorChangeMode();
  719. } else {
  720. Off();
  721. }
  722. }
  723. saber_off_time_ = millis();
  724. swing_blast_ = false;
  725. return true;
  726. #endif
  727.  
  728. // Character Quote and Force Effect, Blade ON.
  729. // Hilt pointed UP for Character Quote, plays sequentially,
  730. // Hilt pointed DOWN for Force Effect, plays randomly.
  731. case EVENTID(BUTTON_POWER, EVENT_SECOND_SAVED_CLICK_SHORT, MODE_ON):
  732. #ifndef SABERSENSE_FLIP_AUDIO_PLAYERS
  733. // Define reverses UP/DOWN options for QUOTE/FORCE/TRACK audio player.
  734. // Quote player points upwards.
  735. if (SFX_quote) {
  736. if (fusor.angle1() > 0) {
  737. SFX_quote.SelectNext();
  738. SaberBase::DoEffect(EFFECT_QUOTE, 0);
  739. } else {
  740. SaberBase::DoForce(); // Force effect for hilt pointed DOWN.
  741. }
  742. } else {
  743. SaberBase::DoForce(); // Fallback: play force effect if no quotes are available.
  744. }
  745. return true;
  746. #else
  747. // Quote player points downwards.
  748. if (SFX_quote) {
  749. if (fusor.angle1() < 0) {
  750. SFX_quote.SelectNext();
  751. SaberBase::DoEffect(EFFECT_QUOTE, 0);
  752. } else {
  753. SaberBase::DoForce(); // Force effect for hilt pointed DOWN.
  754. }
  755. } else {
  756. SaberBase::DoForce(); // Fallback: play force effect if no quotes are available.
  757. }
  758. return true;
  759. #endif
  760.  
  761. // Character Quote and Music Track, Blade OFF.
  762. // Play sequential quote pointing up, play music track pointing down.
  763. case EVENTID(BUTTON_POWER, EVENT_SECOND_SAVED_CLICK_SHORT, MODE_OFF):
  764. #ifndef SABERSENSE_FLIP_AUDIO_PLAYERS
  765. // Define reverses UP/DOWN options for QUOTE/FORCE/TRACK audio players.
  766. // Quote player points upwards.
  767. if (SFX_quote) {
  768. if (fusor.angle1() > 0) {
  769. SFX_quote.SelectNext();
  770. SaberBase::DoEffect(EFFECT_QUOTE, 0);
  771. } else {
  772. StartOrStopTrack(); // Play track for hilt pointed DOWN.
  773. }
  774. } else {
  775. StartOrStopTrack(); // Fallback: play track if no quotes are available.
  776. }
  777. return true;
  778. #else
  779. // Quote player points downwards.
  780. if (SFX_quote) {
  781. if (fusor.angle1() < 0) {
  782. SFX_quote.SelectNext();
  783. SaberBase::DoEffect(EFFECT_QUOTE, 0);
  784. } else {
  785. StartOrStopTrack(); // Play track for hilt pointed DOWN.
  786. }
  787. } else {
  788. StartOrStopTrack(); // Fallback: play track if no quotes are available.
  789. }
  790. return true;
  791. #endif
  792.  
  793. // Colour Change.
  794. // 1 and 2 button modes.
  795. #ifndef DISABLE_COLOR_CHANGE
  796. case EVENTID(BUTTON_POWER, EVENT_THIRD_SAVED_CLICK_SHORT, MODE_ON):
  797. ToggleColorChangeMode();
  798. return true;
  799. // 2 button mode only.
  800. #if NUM_BUTTONS == 2
  801. case EVENTID(BUTTON_AUX, EVENT_CLICK_SHORT, MODE_ON | BUTTON_POWER):
  802. ToggleColorChangeMode();
  803. return true;
  804. #endif
  805. #endif
  806.  
  807. // Blaster Deflection
  808. #if NUM_BUTTONS == 1
  809. // 1 button
  810. case EVENTID(BUTTON_POWER, EVENT_FIRST_SAVED_CLICK_SHORT, MODE_ON):
  811. #else
  812. // 2 button
  813. case EVENTID(BUTTON_AUX, EVENT_CLICK_SHORT, MODE_ON):
  814. case EVENTID(BUTTON_AUX, EVENT_FIRST_SAVED_CLICK_SHORT, MODE_ON):
  815. #endif
  816. swing_blast_ = false;
  817. SaberBase::DoBlast();
  818. return true;
  819.  
  820. // Multi-Blaster Deflection mode
  821. case EVENTID(BUTTON_NONE, EVENT_SWING, MODE_ON | BUTTON_POWER):
  822. swing_blast_ = !swing_blast_;
  823. if (swing_blast_) {
  824. if (SFX_blstbgn) {
  825. hybrid_font.PlayCommon(&SFX_blstbgn);
  826. } else {
  827. hybrid_font.SB_Effect(EFFECT_BLAST, 0);
  828. }
  829. } else {
  830. if (SFX_blstend) {
  831. hybrid_font.PlayCommon(&SFX_blstend);
  832. } else {
  833. hybrid_font.SB_Effect(EFFECT_BLAST, 0);
  834. }
  835. }
  836. return true;
  837.  
  838. case EVENTID(BUTTON_NONE, EVENT_SWING, MODE_ON):
  839. if (swing_blast_) {
  840. SaberBase::DoBlast();
  841. }
  842. return true;
  843.  
  844. // Lockup
  845. #if NUM_BUTTONS == 1
  846. // 1 button lockup
  847. case EVENTID(BUTTON_NONE, EVENT_CLASH, MODE_ON | BUTTON_POWER):
  848. #else
  849. #ifndef SABERSENSE_NO_LOCKUP_HOLD
  850. // 2 button lockup
  851. case EVENTID(BUTTON_AUX, EVENT_FIRST_HELD, MODE_ON):
  852. #else
  853. case EVENTID(BUTTON_NONE, EVENT_CLASH, MODE_ON | BUTTON_AUX):
  854. #endif
  855. #endif
  856. if (accel_.x < -0.15) {
  857. SaberBase::SetLockup(SaberBase::LOCKUP_DRAG);
  858. } else {
  859. SaberBase::SetLockup(SaberBase::LOCKUP_NORMAL);
  860. }
  861. swing_blast_ = false;
  862. SaberBase::DoBeginLockup();
  863. return true;
  864. break;
  865.  
  866. // Lightning Block, 1 and 2 button.
  867. case EVENTID(BUTTON_POWER, EVENT_SECOND_HELD, MODE_ON):
  868. SaberBase::SetLockup(SaberBase::LOCKUP_LIGHTNING_BLOCK);
  869. swing_blast_ = false;
  870. SaberBase::DoBeginLockup();
  871. return true;
  872. break;
  873.  
  874. // Melt
  875. case EVENTID(BUTTON_NONE, EVENT_STAB, MODE_ON | BUTTON_POWER):
  876. SaberBase::SetLockup(SaberBase::LOCKUP_MELT);
  877. swing_blast_ = false;
  878. SaberBase::DoBeginLockup();
  879. return true;
  880. break;
  881.  
  882. case EVENTID(BUTTON_AUX2, EVENT_PRESSED, MODE_OFF):
  883. SaberBase::RequestMotion();
  884. return true;
  885.  
  886. // Enter Volume MENU
  887. #if NUM_BUTTONS == 1
  888. // 1 button
  889. case EVENTID(BUTTON_NONE, EVENT_CLASH, MODE_OFF | BUTTON_POWER):
  890. #else
  891. // 2 button
  892. case EVENTID(BUTTON_AUX, EVENT_CLICK_SHORT, MODE_OFF | BUTTON_POWER):
  893.  
  894. #endif
  895. if (!mode_volume_) {
  896. mode_volume_ = true;
  897. if (SFX_vmbegin) {
  898. hybrid_font.PlayCommon(&SFX_vmbegin);
  899. } else {
  900. beeper.Beep(0.5, 3000);
  901. }
  902. STDOUT.println("Enter Volume Menu");
  903. } else {
  904. mode_volume_ = false;
  905. if (SFX_vmend) {
  906. hybrid_font.PlayCommon(&SFX_vmend);
  907. } else {
  908. beeper.Beep(0.5, 3000);
  909. }
  910. STDOUT.println("Exit Volume Menu");
  911. }
  912. return true;
  913.  
  914. // Battery level
  915. case EVENTID(BUTTON_POWER, EVENT_FOURTH_SAVED_CLICK_SHORT, MODE_OFF):
  916. #if NUM_BUTTONS == 2
  917. case EVENTID(BUTTON_AUX, EVENT_FIRST_CLICK_LONG, MODE_OFF):
  918. #endif
  919. talkie.SayDigit((int)floorf(battery_monitor.battery()));
  920. talkie.Say(spPOINT);
  921. talkie.SayDigit(((int)floorf(battery_monitor.battery() * 10)) % 10);
  922. talkie.SayDigit(((int)floorf(battery_monitor.battery() * 100)) % 10);
  923. talkie.Say(spVOLTS);
  924. SaberBase::DoEffect(EFFECT_BATTERY_LEVEL, 0);
  925. return true;
  926.  
  927. #ifdef BLADE_DETECT_PIN
  928. case EVENTID(BUTTON_BLADE_DETECT, EVENT_LATCH_ON, MODE_ANY_BUTTON | MODE_ON):
  929. case EVENTID(BUTTON_BLADE_DETECT, EVENT_LATCH_ON, MODE_ANY_BUTTON | MODE_OFF):
  930. // Might need to do something cleaner, but let's try this for now.
  931. blade_detected_ = true;
  932. FindBladeAgain();
  933. SaberBase::DoBladeDetect(true);
  934. return true;
  935.  
  936. case EVENTID(BUTTON_BLADE_DETECT, EVENT_LATCH_OFF, MODE_ANY_BUTTON | MODE_ON):
  937. case EVENTID(BUTTON_BLADE_DETECT, EVENT_LATCH_OFF, MODE_ANY_BUTTON | MODE_OFF):
  938. // Might need to do something cleaner, but let's try this for now.
  939. blade_detected_ = false;
  940. FindBladeAgain();
  941. SaberBase::DoBladeDetect(false);
  942. return true;
  943. #endif
  944.  
  945. // Events that needs to be handled regardless of what other buttons are pressed.
  946. case EVENTID(BUTTON_AUX2, EVENT_RELEASED, MODE_ANY_BUTTON | MODE_ON):
  947. if (SaberBase::Lockup()) {
  948. SaberBase::DoEndLockup();
  949. SaberBase::SetLockup(SaberBase::LOCKUP_NONE);
  950. return true;
  951. }
  952. }
  953. return false;
  954. }
  955.  
  956. #ifdef SABERSENSE_OS7_LEGACY_SUPPORT
  957. void SB_Effect(EffectType effect, float location) override { // Required for ProffieOS 7.x.
  958. #else
  959. void SB_Effect(EffectType effect, EffectLocation location) override { // Required for ProffieOS 8.x.
  960. #endif
  961. switch (effect) {
  962. case EFFECT_QUOTE: hybrid_font.PlayCommon(&SFX_quote); return;
  963. case EFFECT_POWERSAVE:
  964. if (SFX_dim) {
  965. hybrid_font.PlayCommon(&SFX_dim);
  966. } else {
  967. beeper.Beep(0.5, 3000);
  968. }
  969. return;
  970. case EFFECT_BATTERY_LEVEL:
  971. if (SFX_battery) {
  972. hybrid_font.PlayCommon(&SFX_battery);
  973. } else {
  974. beeper.Beep(0.5, 3000);
  975. }
  976. return;
  977. case EFFECT_FAST_ON:
  978. if (SFX_faston) {
  979. hybrid_font.PlayCommon(&SFX_faston);
  980. }
  981. return;
  982.  
  983. default: break; // avoids compiler warning
  984. }
  985. }
  986.  
  987. private:
  988. bool pointing_down_ = false;
  989. bool swing_blast_ = false;
  990. bool mode_volume_ = false;
  991. bool auto_lockup_on_ = false;
  992. bool auto_melt_on_ = false;
  993. bool max_vol_reached_ = false;
  994. bool min_vol_reached_ = false;
  995. uint32_t thrust_begin_millis_ = millis();
  996. uint32_t push_begin_millis_ = millis();
  997. uint32_t clash_impact_millis_ = millis();
  998. uint32_t last_twist_ = millis();
  999. uint32_t last_push_ = millis();
  1000. uint32_t saber_off_time_ = millis();
  1001. };
  1002.  
  1003. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement