Subblade, SubBladeWithStride, and/or SubBladeZZ emitter PCB use case

I checked out the discussion of the Shadowfoil Hangman PCB where SubBladeZZ was implemented to aid in the complex setup, but this is a different Shadowfoil PCB, and I’ve stumbled upon whether the “with stride” logic can handle the layout. For context, here’s Sam’s data layout:

What I’m hoping to achieve is 3 concentric blades (12, 8, and 4px lengths), and the pixels numbers would be as follows:

outer: 0-11
mid: 12,14,15,17,18,20,21,23
inner: 13,16,19,22

So, the outer would be easily SubBlade(0, 11, NULL), and the inner would be SubBladeWithStride(13, 22, 3, NULL), but the weird intervals of 1, skip 1, 2, skip 1, 2, skip 1, 2, skip 1, 1 don’t seem applicable.

I can imagine a complex subblade setup, like @NoSloppy suggested before the zig-zag stride was created, but my styles would be limited (i wouldn’t be able to have a cylon bladestyle in the middle because) because I could only duplicate the exact same style on all the 1,2,2,2,1 strip and have them be time based (like a pulsing where they all start and stop at the same time).

Am I wrong, and am missing how to setup a blade array to take advantage of the placement? I don’t think ZZ would work, since it alternates left-right. As of late, I’ve only split the emitter into two concentric rings, and it’s obvious when scrolling styles move across the snaking pattern of the inner ring. Still looks cool, but my curiosity got me wondering if I fully understood the newest SubBlade options.

Any suggestions?

When I program these I have it as one blade, but the style is a gradient broken up into 24 “colors”. I got the idea from the Shtok off effects and just modified it for 24 pixels. Here are some of the effects I have made, starting with the list of modified Shtok effects. I know it’s not exactly what you were asking, but it’s an option to keep in mind.

I appreciate that, but that still doesn’t solve the odd number pattern. There wouldn’t be a way to subdivide the style into 3 rings with a bladestyle. So the colorcycle in your first few splits wouldn’t be able to work based on the pad layout in the attached photo from Sam.

This is definitely a nice work-around for less complex setups.

Edit: Looks like I lied. I tried to split up the gradient into discrete pixels and the colorcyle acts like one layer…at least in the style editor. I assumed each instance would start and stop independently, but because it’s all in the same bladestyle the motion appears continuous.

3 rings is a thing. Is it able to do exactly what you are after, I don’t know. But you can separate the rings.

Yeah, I edited my reply after playing around with one of the styles in the editor. It is inelegant, as some features aren’t easy to implement, but splitting it in a bladestyle is doable.

What features are you trying to implement?

Different on and off sequences, the ability to use some of my standard accent styles built off the fett263 library. I tried playing with Transition Loop Layers in the editor, but it was too much of a time suck. So I’m just going to split in two my old-fashioned way for now. When I get time to maybe make some new styles specific to this emitter PCB, at perhaps your suggestion, I may invest that time. It’s a trade-off of easy to define subblades and copy/paste previous styles, vs overhauling bladestyles to use the simpler gradient styles in your pastebin.

You’ve given me quite a bit to work with, actually. I would just have to add a Layers< start before an on style, an InOutTrL for an off style, and any other regular effects for clashes, blasters, etc. Thank you for the idea. Still will need to wait until the next commission to implement, but now I know it’s more doable.

There isn’t a way to do exactly what you want right now.
We could add a subblade variant which just takes a list of numbers, which could be used for these sort of odd things.

In the meantime, I would suggest using four blades using SubBladeWithStride:

  • 0-12
  • 12, 15, 18. 21
  • 14, 17, 20, 23
  • 13, 16, 19, 22

The two middle ones could have the same style to make them behave basically the same.

1 Like

Thanks, profezzor. I thought I might be able to overlap strides, but I thought I had accidentally done so in the past with unwanted results. Given this would be planned, I think you’re right that the matched styled subblades would behave in tandem. I’ll try it later today and report back.

I tested this and it actually works (added in sub_blade.h):


class SubBladeWrapperWithList : public SubBladeWrapper {
public:
  SubBladeWrapperWithList(const int* indices, int count)
      : indices_(indices), count_(count) {}

  void set(int led, Color16 c) override {
    if (led >= 0 && led < count_) {
      blade_->set(indices_[led], c);
    }
  }

  void set_overdrive(int led, Color16 c) override {
    if (led >= 0 && led < count_) {
      blade_->set_overdrive(indices_[led], c);
    }
  }

  int num_leds() const override { return count_; }

protected:
  const int* indices_;
  int count_;
};

// This function needs to read a declared list of LED indices from the config file.
BladeBase* SubBladeWithList(const int* indices, int count, BladeBase* blade) {
  // If 'blade' is not NULL, this sub-blade is primary; reset the chain.
  if (blade) {
    first_subblade_wrapper = last_subblade_wrapper = NULL;
  } else {
    // If 'blade' is NULL, chain onto the existing sub-blade base.
    if (!first_subblade_wrapper) return NULL;
    blade = first_subblade_wrapper->blade_;
  }

  SubBladeWrapperWithList* ret = new SubBladeWrapperWithList(indices, count);

  if (first_subblade_wrapper) {
    ret->SetNext(last_subblade_wrapper);
    first_subblade_wrapper->SetNext(ret);
    last_subblade_wrapper = ret;
  } else {
    ret->SetNext(ret);
    first_subblade_wrapper = last_subblade_wrapper = ret;
  }

  ret->SetupSubBlade(blade, 0, count);
  return ret;
}

The config just needs to set the pixels to be used.
So to make 3 rings on a PCB wired like this:

You would add:

static const int outer_ring[] = {1, 2, 5, 6, 9, 10, 12, 13, 16, 17, 20, 21, 24, 25, 27, 28};
static const int middle_ring[] = {3, 7, 11, 14, 18, 22, 26, 29};
static const int inner_ring[] = {0, 4, 8, 15, 19, 23};

And then the blade config would be

BladeConfig blades[] = {
  { 0,
    // Outer Ring
    SubBladeWithList(outer_ring, NELEM(outer_ring), WS281XBladePtr<30, bladePin, Color8::GRB, PowerPINS<bladePowerPin2, bladePowerPin3>>()),

    // Middle Ring (Secondary sub-blade, pass NULL to chain)
    SubBladeWithList(middle_ring, NELEM(middle_ring), NULL),

    // Inner Ring (Tertiary sub-blade)
    SubBladeWithList(inner_ring, NELEM(inner_ring), NULL),

    CONFIGARRAY(presets)
  }
};

Now I know that strays from the typical syntax and format of a blade definition, so it’s a little unique and confusing… but something to work towards?

1 Like

Hey hey, new functions! Whose new emitter PCB is that diagram from? I know Rick Ryo has a new 28px emitter PCB developed, but I don’t recognize the logo on that one in your example.

Not sure on the order here, but Rick’s (from a text thread with Jon Rossi

PR time???

Yes it’s Goth. And the reason I started working with this was due to a conversation with Jon looking for custom blade styles for it. If designers would literally make each ring wired that way, would certainly be a lot easier.

Interesting. The photos I got must be prototypes. Yours shows 30count. I have a few left of the Shadowfoil PCBs that prompted this post. And when I heard about the new ones Rick was going to be getting manufactured, I started giving it a thought. I’m stoked to give this new subblade option a try on the next install opportunity. Thanks for doing the heavy lifting. I’ll have to thank Jon too.

We could use a bit of templating so you could just write:

SubBladeWithList<3, 7, 11, 14, 18, 22, 26, 29>(NULL);

ok got it working so blade config can be formatted as such (main blade added ad normal subBlade here)

BladeConfig blades[] = {
  { 0,
    // Main
    SubBlade(31, 143, WS281XBladePtr<144, bladePin, Color8::GRB, PowerPINS<bladePowerPin2, bladePowerPin3>>()),

    // Middle
    SubBladeWithList<3, 7, 11, 14, 18, 22, 26, 29>(NULL),

    // Inner
    SubBladeWithList<0, 4, 8, 15, 19, 23>(NULL),

    // Outer
    SubBladeWithList<1, 2, 5, 6, 9, 10, 12, 13, 16, 17, 20, 21, 24, 25, 27, 28>(NULL),

    CONFIGARRAY(presets)
  }
};
5 Likes