Playing unique blade array audio idents on live array switching

Ah, sorry Brian - yes, there are two goals here - a manual array selector and a true bladeID selector.

The manual selector I have working - as you say it disregards any BladeID resistances and just cycles next array, next array (or previous array pointing down), and when it does, it plays the array1.wav for first array, array2.wav for second array etc. This means you can create individual wav idents for each array and keep them in your common folder - no more having to have multiple bladein.wavs in various prefont folders on your SD card.

That all works great. But I want to also have an option to use on-demand true BladeID, which you run as a button event, to run the scan and switch to the correct array. (You couldn’t use both at the same time - it’s other the above manual array selection or BladeID selection). The only difference between how I want it to run and how it runs by default is that I want it to again play the arrayX.wav files associated with each individual array.

You’d think it would be super-simple since it already works with my manual cycling, but I’m struggling. It may be that I’ve gone too far down the rabbit hole and I’m now lost in the dead roots of earlier schemes. I should probably leave it for a day or two and come back to it.

Back at workbench.
This does accomplish what you were saying.

  void TriggerBladeID() {
    size_t detected_best_config = FindBestConfig(false);
    current_config = blades + detected_best_config;
    FakeFindBladeAgain();
    SFX_array.Select(detected_best_config);
    hybrid_font.PlayCommon(&SFX_array);
  }

Then the button

  case EVENTID(BUTTON_POWER, EVENT_THIRD_SAVED_CLICK_SHORT, MODE_OFF):
    TriggerBladeID();
    return true;

Hmmm… I can’t seem to make that even compile.
Is there a whole nother section to it that I’m missing?

OK, following your help last night Brian (thanks again for that), I got this working today, but Interestingly it seems instead of switching arrays, it’s merging them, and running each array’s parallel preset all at once.

My array below highlights this, because the first array is a full, short test blade, and the second is no blade but with the presets designed to create a spinner effect in the Shtok connector, while the third is a longer blade (the fourth is charge mode which doesn’t light anything). The first three arrays all light the full length blade while simultaneously running the spinner effect at the base of it.

I know it’s not a config thing, because the config is tried and tested under normal BladeID.

I’ll keep working on figuring out why and will share any findings here…

BladeConfig blades[] = {
   { 71,
//  Main Blade:
 	WS281XBladePtr<68, bladePin, Color8::GRB, PowerPINS<bladePowerPin2, bladePowerPin3>>(),
//  Bluetooth Module:   
    SimpleBladePtr<Bluetooth, NoLED, NoLED, NoLED, bladePowerPin6, -1, -1, -1>(),   
   CONFIGARRAY(testblde), "save2"},

   { 76,
//  Main Blade:
 	WS281XBladePtr<8, bladePin, Color8::GRB, PowerPINS<bladePowerPin2, bladePowerPin3>>(),
//  Bluetooth Module:   
    SimpleBladePtr<Bluetooth, NoLED, NoLED, NoLED, bladePowerPin6, -1, -1, -1>(),   
   CONFIGARRAY(noblade), "save1"},

   { 64,
//  Main Blade:
 	WS281XBladePtr<114, bladePin, Color8::GRB, PowerPINS<bladePowerPin2, bladePowerPin3>>(),
//  Bluetooth Module:   
    SimpleBladePtr<Bluetooth, NoLED, NoLED, NoLED, bladePowerPin6, -1, -1, -1>(),   
   CONFIGARRAY(lgt), "save3"},

   { 52,
//  Main Blade:
 	WS281XBladePtr<10, bladePin, Color8::GRB, PowerPINS<bladePowerPin2, bladePowerPin3>>(),
//  Bluetooth Module:   
    SimpleBladePtr<Bluetooth, NoLED, NoLED, NoLED, bladePowerPin6, -1, -1, -1>(),   
   CONFIGARRAY(charging), "save4"},
};
#endif

OK, ignoring the manual array cycling for a moment, and just focusing on BladeID playing array ident sound effects, the below, with event handler TriggerBladeID(), seems to have solved the arrays merging thing,

  void TriggerBladeID() {
    size_t detected_best_config = FindBestConfig(false);
      FindBladeAgain();
      SFX_array.Select(detected_best_config);
      hybrid_font.PlayCommon(&SFX_array);
    }

However with the above under OS-8 (GitHub Master), although it always plays the correct arrayX.wav for the array that BladeID should be sending me to, the actual array itself doesn’t always switch. I find going from 2 to 1 or 3 to 1 works, but going from 1 to 2 doesn’t - it plays array2.wav but stays on array 1 blade config.

But if I remove the word ‘false’ from the second line and run it under 7.14, it’s flawless.

Testing continues… :slight_smile:

I can’t imagine what you are actually experiencing.
Merging is not a thing. There’s no way you can have multiple blade arrays active at the same time, nor “merged” preset arrays, so that all sounds very odd.

The parameter sent in FindBestConfig(false) simply sets a printout to print the “BLADE ID: NNNNNN” in serial monitor or not.
In 7.14, FindBestConfig() didn’t have that parameter for that option .

These are pretty straight forward functions, although i think TriggerID() could be even simpler. Just do the BladeID scan, then say which array was chosen.

  void TriggerBladeID() {
      FindBladeAgain();
      SFX_array.Select(current_config);
      hybrid_font.PlayCommon(&SFX_array);
    }

In the above array, array 1 had 68 pixels, array 2 only had 8 pixels. Array 1 had regular blade styles for a normal blade, array 2 is intended for the Shtok connector and had a colourcycle effect that started slow then sped up.

If you started with no blade, the colour cycle was fine, if you put the blade in, all you saw was the first 8 pixels colour cycling, which is obviously correct until you run the scan. But once the scan had run with the blade fitted, it would switch to the first array, but when you ignited the blade, pixels 9 to 68 would light as per the normal blade, but pixels 1 to 8 would still colour cycle, meaning they must have been looking at array 1’s blade style.

If I get time tonight I’ll try and get a video of it. I tried it in OS7 and OS8 but they were both the same.

OK, here’s the vid of everything running under GitHub Master:

Blade Array:

BladeConfig blades[] = {
   { 76,  
//  Main Blade:
 	WS281XBladePtr<8, bladePin, Color8::GRB, PowerPINS<bladePowerPin2, bladePowerPin3>>(),
//  Bluetooth Module:   
    SimpleBladePtr<Bluetooth, NoLED, NoLED, NoLED, bladePowerPin6, -1, -1, -1>(),   
   CONFIGARRAY(noblade), "save1"},

    { 71,
//  Main Blade:
 	WS281XBladePtr<68, bladePin, Color8::GRB, PowerPINS<bladePowerPin2, bladePowerPin3>>(),
//  Bluetooth Module:   
    SimpleBladePtr<Bluetooth, NoLED, NoLED, NoLED, bladePowerPin6, -1, -1, -1>(),   
   CONFIGARRAY(testblde), "save2"},

   { 64,
//  Main Blade:
 	WS281XBladePtr<114, bladePin, Color8::GRB, PowerPINS<bladePowerPin2, bladePowerPin3>>(),
//  Bluetooth Module:   
    SimpleBladePtr<Bluetooth, NoLED, NoLED, NoLED, bladePowerPin6, -1, -1, -1>(),   
   CONFIGARRAY(lgt), "save3"},
   
   { 52,
//  Main Blade:
 	WS281XBladePtr<10, bladePin, Color8::GRB, PowerPINS<bladePowerPin2, bladePowerPin3>>(),
//  Bluetooth Module:   
    SimpleBladePtr<Bluetooth, NoLED, NoLED, NoLED, bladePowerPin6, -1, -1, -1>(),   
   CONFIGARRAY(charging), "save4"}, 
};
#endif

Presets for comparison:

Preset noblade[] = {
   { "PreFont0;FontPrem/ANHGrfx1;Shared/Random;Shared/Function", "tracks/ANH_Track5.wav",
//  Main Blade:
StylePtr<Layers<Layers<ColorCycle<ColorSelect<Sum<Variation,IntArg<STYLE_OPTION_ARG,0>>,TrFade<50>,ColorChange<TrInstant,DeepSkyBlue>,Blue,Cyan,DodgerBlue,Green,Rgb<28,255,28>,Red,Magenta,Rgb<255,80,154>,Yellow,Orange,Azure>,0,1,ColorSelect<Sum<Variation,IntArg<STYLE_OPTION_ARG,0>>,TrFade<50>,ColorChange<TrInstant,DeepSkyBlue>,Blue,Cyan,DodgerBlue,Green,Rgb<28,255,28>,Red,Magenta,Rgb<255,80,154>,Yellow,Orange,Azure>,70,1000,4000>,TransitionEffectL<TrConcat<TrWipe<1000>,AlphaL<Mix<BatteryLevel,Red,Green>,SmoothStep<BatteryLevel,Int<-10>>>,TrDelay<2000>,AlphaL<Mix<BatteryLevel,Red,Green>,SmoothStep<BatteryLevel,Int<-10>>>,TrWipeIn<1000>>,EFFECT_BATTERY_LEVEL>>>>("~ ~ 0"),


Preset testblde[] = {
   { "PreFont1;FontPrem/ANHGrfx1;Shared/Luke;Shared/Function", "tracks/ANH_Track5.wav",
//  Main Blade:
StylePtr<Layers<Layers<ColorSelect<Sum<Variation,IntArg<STYLE_OPTION_ARG,0>>,TrFade<50>,ColorChange<TrInstant,DeepSkyBlue>,Blue,Cyan,DodgerBlue,Green,Rgb<28,255,28>,Red,Magenta,Rgb<255,80,154>,Yellow,Orange,Azure>,RandomL<ColorSelect<Sum<Variation,IntArg<STYLE_OPTION_ARG,0>>,TrFade<50>,ColorChange<TrInstant,Rgb<0,107,205>>,Rgb<0,0,205>,Rgb<0,205,205>,Rgb<0,60,205>,Rgb<0,205,0>,Rgb<22,205,22>,Rgb<205,0,0>,Rgb<205,0,205>,Rgb<205,62,115>,Rgb<205,205,0>,Rgb<205,79,0>,Rgb<178,205,205>>>,OriginalBlastL<ColorSelect<Sum<Variation,IntArg<STYLE_OPTION_ARG,0>>,TrFade<50>,ColorChange<TrInstant,Red>,Red,Red,Red,Red,Red,LightYellow,Blue,Blue,Red,Blue,Red>>,LockupL<Strobe<ColorSelect<Sum<Variation,IntArg<STYLE_OPTION_ARG,0>>,TrFade<50>,ColorChange<TrInstant,Rgb<200,255,255>>,Rgb<200,255,255>,Rgb<200,255,255>,Rgb<200,255,255>,White,Rgb<200,255,255>,Rgb<200,255,255>,Rgb<200,255,255>,Rgb<200,255,255>,Rgb<200,255,255>,Rgb<200,255,255>,Yellow>,Black,20,16>,Strobe<ColorSelect<Sum<Variation,IntArg<STYLE_OPTION_ARG,0>>,TrFade<50>,ColorChange<TrInstant,White>,White,White,White,White,White,White,White,White,White,White,Yellow>,Black,20,16>>,LockupTrL<AlphaL<Mix<TwistAngle<>,RandomFlicker<Red,Black>,RandomFlicker<Yellow,Red>>,SmoothStep<Int<28000>,Int<5000>>>,TrWipeIn<600>,TrFade<300>,SaberBase::LOCKUP_MELT>,SimpleClashL<Strobe<ColorSelect<Sum<Variation,IntArg<STYLE_OPTION_ARG,0>>,TrFade<50>,ColorChange<TrInstant,Yellow>,Yellow,Yellow,Yellow,White,Red,Yellow,Yellow,Yellow,White,White,Yellow>,Black,28,25>,260>,InOutTrL<TrWipe<500>,TrWipeInX<WavLen<EFFECT_RETRACTION>>>,TransitionEffectL<TrConcat<TrWipe<1000>,AlphaL<Mix<BatteryLevel,Red,Green>,SmoothStep<BatteryLevel,Int<-10>>>,TrDelay<2000>,AlphaL<Mix<BatteryLevel,Red,Green>,SmoothStep<BatteryLevel,Int<-10>>>,TrWipeIn<1000>>,EFFECT_BATTERY_LEVEL>>>>("~ ~ 0"),

Preset lgt[] = {
   { "PreFont2;FontPrem/ANHGrfx1;Shared/Luke;Shared/Function", "tracks/ANH_Track5.wav",
//  Main Blade:
StylePtr<Layers<Layers<ColorSelect<Sum<Variation,IntArg<STYLE_OPTION_ARG,0>>,TrFade<50>,ColorChange<TrInstant,DeepSkyBlue>,Blue,Cyan,DodgerBlue,Green,Rgb<28,255,28>,Red,Magenta,Rgb<255,80,154>,Yellow,Orange,Azure>,RandomL<ColorSelect<Sum<Variation,IntArg<STYLE_OPTION_ARG,0>>,TrFade<50>,ColorChange<TrInstant,Rgb<0,107,205>>,Rgb<0,0,205>,Rgb<0,205,205>,Rgb<0,60,205>,Rgb<0,205,0>,Rgb<22,205,22>,Rgb<205,0,0>,Rgb<205,0,205>,Rgb<205,62,115>,Rgb<205,205,0>,Rgb<205,79,0>,Rgb<178,205,205>>>,OriginalBlastL<ColorSelect<Sum<Variation,IntArg<STYLE_OPTION_ARG,0>>,TrFade<50>,ColorChange<TrInstant,Red>,Red,Red,Red,Red,Red,LightYellow,Blue,Blue,Red,Blue,Red>>,LockupL<Strobe<ColorSelect<Sum<Variation,IntArg<STYLE_OPTION_ARG,0>>,TrFade<50>,ColorChange<TrInstant,Rgb<200,255,255>>,Rgb<200,255,255>,Rgb<200,255,255>,Rgb<200,255,255>,White,Rgb<200,255,255>,Rgb<200,255,255>,Rgb<200,255,255>,Rgb<200,255,255>,Rgb<200,255,255>,Rgb<200,255,255>,Yellow>,Black,20,16>,Strobe<ColorSelect<Sum<Variation,IntArg<STYLE_OPTION_ARG,0>>,TrFade<50>,ColorChange<TrInstant,White>,White,White,White,White,White,White,White,White,White,White,Yellow>,Black,20,16>>,LockupTrL<AlphaL<Mix<TwistAngle<>,RandomFlicker<Red,Black>,RandomFlicker<Yellow,Red>>,SmoothStep<Int<28000>,Int<5000>>>,TrWipeIn<600>,TrFade<300>,SaberBase::LOCKUP_MELT>,SimpleClashL<Strobe<ColorSelect<Sum<Variation,IntArg<STYLE_OPTION_ARG,0>>,TrFade<50>,ColorChange<TrInstant,Yellow>,Yellow,Yellow,Yellow,White,Red,Yellow,Yellow,Yellow,White,White,Yellow>,Black,28,25>,260>,InOutTrL<TrWipe<500>,TrWipeInX<WavLen<EFFECT_RETRACTION>>>,TransitionEffectL<TrConcat<TrWipe<1000>,AlphaL<Mix<BatteryLevel,Red,Green>,SmoothStep<BatteryLevel,Int<-10>>>,TrDelay<2000>,AlphaL<Mix<BatteryLevel,Red,Green>,SmoothStep<BatteryLevel,Int<-10>>>,TrWipeIn<1000>>,EFFECT_BATTERY_LEVEL>>>>("~ ~ 0"),

Full config:

Full prop (untidy as it’s basically a building site at the moment):

I haven’t looked in earnest at the cycling side of things, but as mentioned, just using that very simple, cut down BladeID code to run BladeID but play arrayX.wav associated with each one seemed to work, albeit with a tiny bugette under OS-8, but flawless under OS7 if you remove the ‘false’:

  void TriggerBladeID() {
    size_t detected_best_config = FindBestConfig(false);
      FindBladeAgain();
      SFX_array.Select(detected_best_config);
      hybrid_font.PlayCommon(&SFX_array);
    }

what about the even more cut down version?

 void TriggerBladeID() {
      FindBladeAgain();
      SFX_array.Select(current_config);
      hybrid_font.PlayCommon(&SFX_array);
    }

Not sure why OS8 would sometimes make different (incorrect?) choices though. we should figure that out.

I know I tried that option as it seemed like the obvious way to go. But I tried an awful lot of other combos too today, and I can’t remember exactly what the issue was with that one, but I think it was that it didn’t play any audio file when it ran. But I’ll give it another go and get a definitive answer.

Agree. Again, I’ll try and get a video of it so you can see what I mean…

Sorry, no, it wasn’t missing audio - it was that it wouldn’t compile:

/Users/chrisandlindsey/Desktop/ProffieOS GitHub OS-8/ProffieOS/props/saber_sabersense_buttons_v73.h:424:24: error: invalid conversion from 'BladeConfig*' to 'int' [-fpermissive]
  424 |       SFX_array.Select(current_config);
      |                        ^~~~~~~~~~~~~~
      |                        |
      |                        BladeConfig*
In file included from /Users/chrisandlindsey/Desktop/ProffieOS GitHub OS-8/ProffieOS/sound/sound.h:25,
                 from /Users/chrisandlindsey/Desktop/ProffieOS GitHub OS-8/ProffieOS/ProffieOS.ino:446:
/Users/chrisandlindsey/Desktop/ProffieOS GitHub OS-8/ProffieOS/sound/effect.h:351:19: note:   initializing argument 1 of 'void Effect::Select(int)'
  351 |   void Select(int n) {
      |               ~~~~^
exit status 1
Error compiling for board Proffieboard V2.

Oh. Pointer arithmetic?
Try ‘SFX_array.Select(current_config - blades)’

1 Like

That’s much better! :+1: And switches reliably too! :smiley:

(Although I think OS-8 switching might have been a red herring - I just did some more tests and the previous code was unreliable in OS7 and 8 - but this new code seems much better).

I think you’ve cracked it Brian - BladeID unique array idents are go! :smiley:

2 Likes

I’m on the train headed home to a saber try and check the other function for someone else.
While you’re there tinkering, would you be willing to test this?

  void NextBladeArray() {
    current_config = blades + (current_config - blades + 1) % NELEM(blades);
    FakeFindBladeAgain();
    // option if no array.wavs used, play font.wav instead
    //  SaberBase::DoNewFont();
    SFX_array.Select(current_config - blades);
    hybrid_font.PlayCommon(&SFX_array);
  }

He’s getting freezing, which is weird because all it’s doing is adding 1 to the current array and activating it. Trying to determine if it’s just something else on his side. I’m leaning towards yes because I’m pretty sure I tested it, plus there’s not much there to mess up.

Just tried it using GitHub master - it doesn’t freeze, but it does do that weird merge array thing we were having earlier. I guess it’s possible that could freeze a different system…?

:man_shrugging:

Sounds like it’s not deactivating the blade right, or more like maybe not working with save files right.
If you don’t use SAVE_PRESET or an encompassing define, does the “merging” stop?
To test this, you might need to delete the save files in the folder named at the end of the balde array.

@profezzorn I’m stumped, so asking for help.
If you see above, we’ve made a couple of simple functions that can be called to manually trigger a change of the active blade array.
One called TriggerBladeID() simply calls FindBladeAgain() and then plays an “array ident” sound. This is super straight forward and I believe is working fine all around.

The other called NextBladeArray() simply increments the current_config by 1 and then does a FakeFindBladeAgain(), which is a conglomeration of the sequence of code flow for deactivating and activating the blade array, minus the FindBestConfig() part. Essentially this is just bypassing some prop_base logic to just cut to the chase and make the next blade array active.

NextBladeArray() works as standalone without any defines for Blade Detect or Blade ID. However this includes a requirement that BLADE_ID_SCAN_MILLIS is NOT defined. (more on that below)

Now while it works for me just fine as far as cycling to the next blade array and announcing an array.wav, Chris is noticing some “leftovers” from the previously active array (see above), and @hkwwinger has a combination of prop and config that I can’t get it to work on because it freezes the board.
I have ruled out SAVE_PRESET as the culprit, as well as NUM_BLADES, and even the fett1263 prop file (it behaves the same writing it into saber.h).

If there’s any light you could shed on why this NextBladeArray() kind of works but then seems like it doesn’t, it would be appreciated. I know this explanation is somewhat haphazzard.

Lastly, I have spent a few days now trying to get it to work while still using Blade ID constant monitoring, as that seems like the penultimate goal for me. Having it all work together.
I am very close and have everything working. Blade in, blade out, manual switch, blade back in… all works as expected. But once any manual switching is done, blade removal will freeze the board (insertion is OK). Which lead me to believe that it’s got something to do with NO_BLADE.
I am basically setting a boolean “manual_mode_” flag when the button EVENT happens. Then as long as in that mode, I am overriding FindBestConfig() and spoofing the manually selected current_config into best_config and returning that. This injects the manually chosen blade array instead of the measured resistance result and consequently prevents scans from changing it back to the measured amount (which may or may not be a different array)
Meanwhile, I’m monitoring id() for actual blade changes which will then reset the flag and resume normal detection .

Is this a wild goose chase that you suggest I stop staying up all night over, or maybe something workable?
Yes…Im having fun.

It might be a save file thing.

Separate save file directories is supposed to fix this, but it’s possible that when messing with the prop, that something gets confused, and the list of presets meant for one blade array gets saved into a directory meant for another.

The result would be that you get the font directories from one array, and the styles from the other, and it might crash if when it tries to access styles past the end of the array.

Thanks.
Yeah I thought save files too. Unfortunately, I tried without SAVE_PRESET defined and it didn’t make a difference.
Also, all 3 tested config files use specified save directories. I wish the one that it freezes with were the odd man out and used a common save location, but alas, it does not and seems it should be working the same.
I’ll continue to debug.

Without seeing the actual code, all I have is (pointy) questions.
FakeFindBladeAgain() deactivate and re-activate the blade drivers?
If yes, how does it know which ones to deactivates since current_config has changed?
If no, it would leave the wrong drivers active, which will likely cause a problem if FindBladeAgain() is called later.