Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add ComboBlade and associated wrappers #668

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ProffieOS.ino
Original file line number Diff line number Diff line change
Expand Up @@ -628,6 +628,7 @@ class NoLED;
#include "blades/simple_blade.h"
#include "blades/saviblade.h"
#include "blades/sub_blade.h"
#include "blades/combo_blade.h"
#include "blades/dim_blade.h"
#include "blades/blade_id.h"
#include "common/preset.h"
Expand Down
162 changes: 162 additions & 0 deletions blades/combo_blade.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
#ifndef BLADES_COMBO_BLADE_H
#define BLADES_COMBO_BLADE_H

/*
Usage: ComboBlade(blade1, blade2)
This allows multiple blades to be combined into a single linear blade even if
they use different data lines for control.

The resulting blade will have a length of the number of LEDs in the first and
second blade combined. When the style is running, the second blade's LEDs will
be controlled as though they were in line and after the first blade's LEDs

For a simple example, if you have a saber with 2 crystal LEDs running on different
data lines rather than in line with one another, you might often do the following.

{ 0,
WS281XBladePtr<128, bladePin, Color8::GRB, PowerPINS<bladePowerPin2, bladePowerPin3> >(),
WS281XBladePtr<1, blade4Pin, Color8::GRB, PowerPINS<bladePowerPin2, bladePowerPin3> >(),
WS281XBladePtr<1, blade3Pin, Color8::GRB, PowerPINS<bladePowerPin2, bladePowerPin3> >(),
}

The above way allows us to assign either the same style or different styles to
both LEDs

However, if we assign the same style the LEDs will do the same thing since they
are both seen as the first LED in a 1 LED longht blade. To avoid this, we can
use ComboBlade, which will result in the style being run against an intermediate
blade with a length of 2, rainbow and stripe styles to move between the two

{ 0,
WS281XBladePtr<128, bladePin, Color8::GRB, PowerPINS<bladePowerPin2, bladePowerPin3> >(),
ComboBlade(WS281XBladePtr<1, blade4Pin, Color8::GRB, PowerPINS<bladePowerPin2, bladePowerPin3> >(),
WS281XBladePtr<1, blade3Pin, Color8::GRB, PowerPINS<bladePowerPin2, bladePowerPin3>>()),

In the above example we must reduce the NUM_BLADES by 1 since the ComboBlade itself
is the only thing that counts as an entry in the blade array.

*/

class ComboBladeWrapper : public BladeWrapper, BladeStyle {
public:
ComboBladeWrapper(BladeBase* blade1, BladeBase* blade2):
blade1_num_leds_(blade1->num_leds()),
blade2_num_leds_(blade2->num_leds()),
blade2_(blade2),
real_style_(nullptr),
blade2_cache_(new OverDriveColor[blade2_num_leds_])
{
blade_ = blade1;
}

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs a destructor that deletes the blade2_cache_

// BladeStyle implementation
virtual void activate() override {
real_style_->activate();
}
virtual void deactivate() override {
real_style_->deactivate();
}
virtual void run(BladeBase* blade) override {
if (blade == blade_) {
real_style_->run(this);
} else {
// On blade2_ we just apply cached values from when blade_ was run
for (int i = 0; i < blade2_num_leds_; i++){
if (blade2_cache_[i].overdrive) {
blade2_->set_overdrive(i, blade2_cache_[i].c);
} else {
blade2_->set(i, blade2_cache_[i].c);
}
}
}
}

bool NoOnOff() override {
return real_style_->NoOnOff();
}

profezzorn marked this conversation as resolved.
Show resolved Hide resolved
virtual bool Charging() { return real_style_->Charging(); }

bool IsHandled(HandledFeature effect) override {
return real_style_->IsHandled(effect);
}

OverDriveColor getColor(int i) override { return real_style_->getColor(i); }

int get_max_arg(int arg) override { return real_style_->get_max_arg(arg); }

// BladeBase implementation
int num_leds() const override {
return blade1_num_leds_ + blade2_num_leds_;
}
void set(int led, Color16 c) override {
if (led < blade1_num_leds_) {
return blade_->set(led, c);
profezzorn marked this conversation as resolved.
Show resolved Hide resolved
} else {
blade2_cache_[led - blade1_num_leds_].c = c;
blade2_cache_[led - blade1_num_leds_].overdrive = false;
}
}

void set_overdrive(int led, Color16 c) override {
if (led < blade1_num_leds_) {
return blade_->set_overdrive(led, c);
} else {
blade2_cache_[led - blade1_num_leds_].c = c;
blade2_cache_[led - blade1_num_leds_].overdrive = true;
}
}

void allow_disable() override {
blade_->allow_disable();
blade2_->allow_disable();
}

void clear() override {
blade_->clear();
blade2_->clear();
}

void Activate(int blade_number) override {
blade_->Activate(blade_number);
blade2_->Activate(blade_number);
}

void Deactivate() override {
blade_->Deactivate();
blade2_->Deactivate();
}

void SetStyle(BladeStyle* style) override {
real_style_ = style;
blade_->SetStyle(this);
blade2_->SetStyle(this);
}

BladeStyle* UnSetStyle() override {
BladeStyle* ret = real_style_;
if (ret) {
ret->deactivate();
}
real_style_ = nullptr;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should also call blade_ / blade2_ -> UnSetStyle() here.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure why, but it actually seems like I get a crash due to a null pointer somewhere when I tried this, willing to explore more if you think this idea is still worth pursuing

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you have a config file that crashes (and instructions for how to make it crash if needed) I can run it with a debugger to see exactly where the crash occurs.

return ret;
}

BladeStyle* current_style() const override {
return real_style_;
}

private:
int blade1_num_leds_;
int blade2_num_leds_;
BladeBase* blade2_;
BladeStyle* real_style_;
OverDriveColor *blade2_cache_;
};

BladeBase* ComboBlade(BladeBase* blade1, BladeBase* blade2)
{
return new ComboBladeWrapper(blade1, blade2);
}

#endif