Switching between many (more than 2) preset lists

I must say I’ve only been trying it with blade arrays and preset arrays switching together at the same time (if that makes sense) as that was kind of my intended purpose. I haven’t yet tried divorcing the two. That should be my next test.

Yes, with the same number of blade arrays and preset arrays, everything seemed to work fine. But as I say it’s early days so it would be good for someone else to try to see if they can find any pitfalls I’ve missed.

I just tried my code above with four blade arrays each pointing to a single preset array, and amazingly it seemed to work as far as I can tell. However I can’t imagine a scenario where you’d want it as the whole idea is to have different blade styles and/or sound fonts on different blade arrays, albeit possibly with some duplication or commonality. Although I dare say someone will come up with a valid use for it.

More testing is needed, but so far it seems like any which way you like it, it works. :smiley:

The next modification I’d like to make is to get it to play a unique sound file identing each array as you switch to it. I know I can make it work by using prefont folders on the SD card with each one having a unique bladein.wav file, but that’s kind of clunky in terms of SD file management. A better solution would be to have a load of array wav files (array1.wav, array2.wav, array3.wav etc.) all kept in the common folder, then have the system access the individual numbered wav that matches the array number as you switch to it.

But this is where I’m struggling as the whole of ProffieOS is geared towards the system randomly selecting which numbered wav file of a given filename to use when it’s asked to play it (clsh1, clsh2 etc.), whereas in this instance we want a particular numbered file to be fixed to a particular action (switching to Array 2 plays array2.wav, Array 3 plays array3.wav etc.).

Hope all this is all making sense to anyone who has hung in to read this far! LOL! As I say, work in progress… :slight_smile:

Actually cancel that last bit - the scenario above where the array selector is used as a means of shutting down a rotating motor is exactly the kind of thing where two blade arrays but one preset array would work perfectly, as you could specify the motor’s LED power pad to be an unused one in the OFF array, meaning the system would never power up the actual motor LED pad to set it spinning when on that blade array.

This just gets better! :smiley:

Sure but it would be more typical and fine to just have a different preset array selected and set the style to Black for the motor.
I was never suggesting divorcing the two, I was just thrown off by the use of id() in your code because that chooses a blade array, consequently choosing the desired preset array if you don’t have any duplication, they are in the same order, and they are one for one.

What I’m saying is although it may be working for you, it might just be happenstance the way you have it set up and maybe could benefit by making it a little more proper/concise/cleaner so it is actually doing what you think it is.
Again, on a train on my phone is not how to go about talking about this. I’ll wrap my head around it when I can sit down at a computer.
Meanwhile, maybe @profezzorn will have a chance to chime in.

1 Like

I think I see where you’re coming from, and yes, the whole thing is intended to be driven by the blade array pulling its associated preset array with it as it were.

The evolution of this was that I’d used Blade Detect on installs with removable chassis to switch between blade/preset arrays for exactly the reason above - i.e. to switch off motors and accent LEDs when they couldn’t be seen inside a hilt. Extending the functionality was driven by then wanting things like blade plug chargers to work by having their own array, so that you could skip to a single-preset charging array then skip straight back to the sound font/preset you were last using without having to find it again as you would if blade plug charging were just another preset.

Then it extended further when I did a Kestis install which had a load of sound fonts each with a light side version and a dark side version. Obviously alt-sound would have been one way to handle that, but it would have meant editing around 40 blade styles and/or also limiting the simplicity of colour changing as my understanding is that it uses the colour change system to work. Having two blade and preset arrays with their respective parallel light side and dark side font versions seemed much simpler both to implement and to operate.

So yes, the whole thing is driven by BladeID to switch blade array and pull the associated preset array with it by design. But of course if the code making it work can be streamlined without introducing additional complexity for the end-user, then all to the good. Making code changes on this scale is new territory for me, so it goes without saying I value any feedback on it. :slight_smile:

1 Like

OK, I’m revisiting this because although a couple of solutions have been found, it has been pointed out that they are a bit clunky in how they work.

So let me first recap the story so far. NoSloppy, Olivier, apologies if I get some of this wrong, or grasp a few sticks by the wrong end, but this is my understanding of where we’re at…

We started with this at the top of the prop outside the prop class which neatly toggled between two blade arrays:

#ifdef SABERSENSE_ARRAY_SELECTOR
//  Toggle switch between blade arrays manually.
//  This goes in the prop file, but not in the prop class.
struct SabersenseArraySelect {
   static int return_value;
   float id() { return return_value; }
   static void toggle() {
     return_value = NO_BLADE - return_value;
   }
};
int SabersenseArraySelect::return_value = 0;
#undef BLADE_ID_CLASS_INTERNAL
#define BLADE_ID_CLASS_INTERNAL SabersenseArraySelect
#undef BLADE_ID_CLASS
#define BLADE_ID_CLASS SabersenseArraySelect
#endif

With this as the event handler:

    // Manual Array Selector.
    // Cycles through blade arrays regardless of BladeID status.
#ifdef SABERSENSE_ARRAY_SELECTOR
    case EVENTID(BUTTON_POWER, EVENT_THIRD_SAVED_CLICK_SHORT, MODE_OFF):
      SabersenseArraySelector::toggle();
      FindBladeAgain();
      return true;
#endif

But we wanted to be able to cycle between multiple arrays. In trying to do this, it was thought that the code below (along with changing toggle to cycle in the event handler) would cycle to the next array in the list But unfortunately, although it compiles, it doesn’t actually work - pressing the button does nothing.

#ifdef SABERSENSE_ARRAY_SELECTOR
  struct SabersenseArraySelector {
    static int return_value; // Tracks the current array index.
    float id() { 
      return return_value; 
    }  // Return the current array index.
    static void cycle() {
      return_value = (return_value + 1) % NUM_BLADES;
    }
  };
  int SabersenseArraySelector::return_value = 0; // Start with the first array (index 0). 
  #undef BLADE_ID_CLASS_INTERNAL
  #define BLADE_ID_CLASS_INTERNAL SabersenseArraySelector
  #undef BLADE_ID_CLASS
  #define BLADE_ID_CLASS SabersenseArraySelector
#endif

I managed to build on the above to make it work, but in order to do so, I had to add a separate define in the config to tell the system how many arrays there were. This too was a bit clunky.

Then NoSloppy found a way to make it work by adding some code inside the class, but to do that, quite a big chunk of code had to be replicated from prop_base, which is also slightly clunky.

I should also add that a lot of water was muddied when I wanted to make the system play confirmation arrayx.wav files, but we (well, NoSloppy and the prof really) managed to finally solve that one separately.

Which leads us back to searching for an elegant solution to performing the actual array switch. It seems to me the key is somewhere around the
return_value = (return_value + 1) % NUM_BLADES;
line, in so far as we need to figure out how the system can keep track of which array it’s on and where it’s going (and ideally save it so it survives reboots), but I’ve spent the afternoon experiementing without much success.

So if anyone who can still see the wood for the trees in all this (I’m kinda too close to it to see anything clearly any more! LOL! I’ll revisit it after a good night’s sleep) and something leaps out as clearly wrong, feel free to share your thoughts. :slight_smile:

Thanks in advance as always.

Here is what I would recommend:

  1. Make SaberBase::id virtual.
  2. Override it like:
int next_id_;
bool use_next_id_;

int id(bool announce = false) override {
  if (use_next_id_) {
    use_next_id_ = false;
    return next_id_;
  }
  return SaberBase::id(announce);
}
  1. To select the next array element, do something like:
void NextArray() {
   int n = current_config - blades;
   n = (n + 1) % NELEM(blades);
   next_id_ = blades[n].id;
   use_next_id_ = true;
   FindBladeAgain();
}
1 Like

Would this enable blade support from hilts that were not wired to support blade-id or blade-detect?
I have a few factory installs that do not support blade-id because the emitter is in parallel or data 1 is going to accents–and I may never get around to rebuilding them… and this could be a solution for me.

BladeID requires a wiring mod to the blade, not the hilt, by adding a resistor between data and blade neg, unlike blade detect which does indeed require a wiring mod to the hilt and neopixel connector with a floating ground pin such as a Shtok 10 or 11 pin connector.

But to answer your question, yes, this would address your requirements exactly because you can run it one of two ways…

The first way is to have BladeID scanning on demand, for setups where you have those resistors inside your blades so the system can identify which blade is which. In this instance you would press the button, it would perform the scan and switch to the correct array for whichever blade you had fitted.

But if you only have blades without those resistors, the other way to run it would be manually where you press the button and it simply changes to the next array in the list. The system would play a custom sound effect to let you know which array you were on (a range of effects will soon be available to download from the Sabersense website, with idents for many different blade types and lengths) and you just cycle through them until you reach the array you want.

If he has an illuminated PCB with serial connection, there’s no way to get the ID from the blade. And if it is connected in parallel, you get very weird readings.

I’ve read many of your posts related to blade-id and you clearly understand how it works better than I do, but to be fair, the “mod to the blade, not the hilt” comment is not exactly correct. If the hilt is wired with data 1 to the main blade AND the hilt side pcb pixels (such as when using an ECO pcb) or to accent pixels, blade-id will not return the expected result. I have several blades with id resistors that require unique definitions… 2 and 4 independent strips, some zigzag and some in series that use subbladewithstride, and blades with different lengths–where length really matters. The hilts I’ve installed can detect any of my blades–but if I want to use my “fancy” blades in my factory installed hilts, I have to change the config and reflash the board. If you have a way to manually select which blade array is active, I will be able to use those special blades with the factory installs that do not correctly read the blade-id (without having to reflash the board every time).

Thanks Prof.
I’ve got it working, albeit not quite the way you described, but the same principle and much more streamlined that how it was before.

Next challenge is to try and make the system save the array, but I’m guessing that:
a) I need to edit prop_base.h to make that work;
b) It would need to be submitted as a new pull request.

I’ll have a play and see how I get on.
:slight_smile:

You could just create a new savefile and put the overridden ID in there.
I don’t think you need to do that in prop_base.h, but I would still recommend doing it a separate pull request.

1 Like

I’ve been doing some more work on saving the array, and I’ve got as far as making the system create the save file on the SD card. However I now need to tell the system to retrieve that number on bootup, but I don’t know the syntax. My guess is it’s something like:

void InitializeSaber() {
RestoreSabersenseState();

I guess Fredrik, you’re best placed to answer this one - do you know what the boot process is called for me to jump onto it like this, and am I right in saying that I can actually jump onto it from the prop file, or do I need to edit a different file? Or am I barking up a wrong tree here? (BTW SabersenseState won’t be the final filename - I’ll make sure it has fewer than eight characters once I’ve got it working).

Thanks as always.
:slight_smile:

I haven’t thought this all the way though, but there are basically two possibilities:

  1. Setup()
  2. FindBlade()

Both of these are called on boot to set things up. FindBlade() is also called by FindBladeAgain().

1 Like

Well this is turning into a good week - prop file accepted, had a small service charge victory, it hasn’t rained on me on my motorcycle commute, and now I’ve managed to get array saving to work! :smiley: :smiley: :smiley:

Pull request submitted.
:slight_smile:

1 Like

Sabersense prop file array saving now merged into ProffieOS Master, OS-8. :smiley:

For me, it’s going to be super useful, as all my installs can now come pre set for all the common blade lengths, and people can just select the blade they plan to use with it when they receive their saber, like this:

  • Array 1 - KR 36 inch - 132 pixels (default)
  • Array 2 - LGT 35 inch - 128 pixels
  • Array 3 - KR 33 inch - 122 pixels
  • Array 4 - LGT 32 inch - 114 pixels
  • Array 5 - KR Shoto - 108 pixels
  • Array 6 - Extra long custom - 144 pixels

Each blade array can look at the same preset array, which makes the array switch basically a blade length selector. And with the new save feature, people only need do it once unless they revert to factory defaults on the buttons (also built into the Sabersense prop :smiley: ).

Better still, the downloadable audio files from my website include a whole range of idents that people can just rename when they’re setting up their own array selection systems.

I’ll write up a full POD description soon and will make a video showing the various ways Array Selection can be implemented.

I realise for the heavyweight coders here, this is smallfry, but for someone relatively new to C++ like me, it’s a big deal. :smiley: Hope someone out there other than me finds it useful! LOL! :smiley:

2 Likes

It’s not smallfry. Nice work! cool feature.
Sharing, writeup, and video is bonus good stuff, great idea.

1 Like