Flexibility: Beyond Standard Inputs¶
The true power of the EVA concept and the SK part of the eva-core-sk library lies in its flexibility. Because Switch and Button are built on templates and decorators, they can work with any source of numerical data—not just physical pins. This section shows how you can adapt the library to unconventional input sources.
Example 1: Differential Joystick with Custom Zone Detection¶
Some precision joysticks use differential readings to cancel noise and improve accuracy. Here's how to combine a differential reader with custom zone mapping to create a 3-position virtual switch:
#include <evaSwitch.h>
#include <evaTac.h>
#include <evaHandler.h>
using namespace eva;
// Step 1: Create a differential reader (A0 - A1)
template <int IN1, int IN2>
class DifferentialReader
{
public:
signed short getValue()
{
return analogRead(IN1) - analogRead(IN2);
}
};
// Step 2: Map raw differences to meaningful codes
template <class READER>
class ZoneMapper : public READER
{
public:
signed short getValue()
{
signed short diff = READER::getValue();
if (diff < -100)
return 1; // Left zone
if (diff < 100)
return 0; // Center zone (nothing happening)
return 2; // Right zone
}
};
// Step 3: Assemble into a Button
using DifferentialSwitch = Switch<
DebounceDecor<
ZoneMapper<
DifferentialReader<A0, A1>
>
>
>;
class App {
private:
DifferentialSwitch joystickZone;
void onZoneEvent(void* sender, CallbackInfo cbInfo) {
unsigned short zone = cbInfo.eventArg; // 1 or 2
if (cbInfo.eventType & ON_PRESS) {
Serial.print("Entered zone ");
Serial.println(zone);
}
if (cbInfo.eventType & ON_RELEASE) {
Serial.println("Returned to center");
}
}
public:
App() {
joystickZone.setListener(
new Handler<App>(this, &App::onZoneEvent),
ON_PRESS | ON_RELEASE
);
}
};
What's happening
-
DifferentialReaderreads the difference between two analog pins, canceling common-mode noise -
ZoneMappertranslates the continuous difference into three discrete states: left (1), center (0), right (2) -
Buttonprovides press/release semantics for zone entry/exit
Example 2: Virtual Button from External Events¶
The same pattern works when values come from outside the normal polling loop—like interrupts, callbacks, or message decoders:
// A reader that stores the last known state
class ExternalStateReader {
private:
static signed short lastValue;
public:
// Called from interrupt or callback
static void update(signed short value) {
lastValue = value;
}
signed short getValue() {
return lastValue;
}
};
signed short ExternalStateReader::lastValue = 0;
// Use it with standard Button
using VirtualButton = Button<DebounceDecor<ExternalStateReader>>;
// Now any external code can inject button events:
// ExternalStateReader::update(1); // Press
// ExternalStateReader::update(0); // Release
What's happening
The Button class then handles all timing and generates appropriate press/release/click events automatically.
The Big Picture¶
The library doesn't care where the values come from. Whether it's: physical pins through standard readers, differential calculations like the joystick example, external signals injected by callbacks, any other source that can provide numerical codes