const int N = 8;
const int MSB = 1 << N;
byte pins[] = {
2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17,
};
class Port {
byte length;
byte* pins;
byte level;
public:
Port(byte length, byte level)
: length(length), level(level){}
void Connect(byte* pins, byte mode){
this->pins = pins;
for(int i = 0; i < length; i++){
pinMode(pins[i], mode);
}
}
void Write(int value) {
if(level == 0) value = ~value;
for(int i = 0; i < length; i++){
digitalWrite(pins[i], value & (1 << i));
}
}
};
class Process {
protected:
int value;
public:
virtual int GetValue() const { return value; }
virtual void Init() = 0;
virtual void Next() = 0;
virtual bool EoP(int count) { return count == 0; }
};
class Led : public Port {
int count;
public:
Led(byte* pins) : Port(N, 1) {
Port::Connect(pins, OUTPUT);
count = N;
}
bool Run(Process* p) {
if (count == N) {
p->Init();
}
Port::Write(p->GetValue());
if (p->EoP(--count)) {
count = N;
return false;
}
p->Next();
return true;
}
};
class Single1 : public Process {
public:
void Init() override { value = 1; }
void Next() override { value <<= 1; }
};
class Single2 : public Process {
public:
void Init() override { value = MSB >> 1; }
void Next() override { value >>= 1; }
};
class Clear1 : public Single1 {
public:
void Init() override { value = MSB - 1; }
bool EoP(int count) override { return count == -2; }
};
class Clear2 : public Clear1 {
public:
void Next() override { value >>= 1; }
};
class Fill1 : public Single1 {
public:
void Next() override { Single1::Next(); value |= 1; }
};
class Fill2 : public Single2 {
public:
void Next() override { Single2::Next(); value |= (MSB >> 1); }
};
class Blink : public Process {
public:
void Init() override { value = 0x5555; }
void Next() override { value = ~value; }
};
Led le(pins);
Led ri(pins + N);
int index = 0;
Process* procs[] = {
new Fill1(), new Fill2(),
new Clear1(), new Clear2(),
new Fill2(), new Fill1(),
new Clear2(), new Clear1(),
new Blink(), new Blink(),
new Single1(), new Single1(),
new Single2(), new Single2(),
0,
};
void setup() {
// put your setup code here, to run once:
}
void loop() {
// put your main code here, to run repeatedly:
auto pl = procs[index];
if (pl == 0) {
index = 0;
pl = procs[index];
}
auto pr = procs[index + 1];
le.Run(pl);
if (!ri.Run(pr)) {
index += 2;
}
delay(100);
}