Skip to content

Instantly share code, notes, and snippets.

@objarni
Created June 22, 2016 06:13
Show Gist options
  • Save objarni/99efb1955591233694e06f5ac7f6fc5a to your computer and use it in GitHub Desktop.
Save objarni/99efb1955591233694e06f5ac7f6fc5a to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <assert.h>
#include <vector>
#include <functional>
// Scenario: a button is connected to an input pin,
// and it toggles an output pin, connect to an output
// pin on and off. So when button is pressed, lamp
// goes on. Then the button is released, and the lamp
// stays on. Not until we press button again, does
// the lamp turn off. When the button is released,
// we are back in initial state (no button pressed,
// lamp off).
// This behaviour is nicely captured by two devices:
// One for the button (states released and pressed),
// One for the lamp (state on and off).
// They communicate via a signal "toggleButton",
// which is published when the button is pressed
// (but not released)
struct Signals {
enum {
PIN0_HIGH,
PIN0_LOW,
PIN1_HIGH,
PIN1_LOW,
TOGGLE
};
};
typedef std::function<void(int)> PublishCallback;
struct Button {
enum {
RELEASED,
PUSHED
};
int state;
Button(PublishCallback publish) {
state = RELEASED;
_publish = publish;
}
void handleSignal(int signal) {
switch(state) {
case RELEASED:
switch(signal) {
case Signals::PIN0_HIGH:
_publish(Signals::TOGGLE);
state = PUSHED;
break;
default:
break;
}
break;
case PUSHED:
switch(signal) {
case Signals::PIN0_LOW:
state = RELEASED;
break;
default:
break;
}
break;
}
}
private:
PublishCallback _publish;
};
void testButton() {
// Apart from changing it's own state, each
// device needs to be able to publish signals.
// It does that by calling publish(signal),
// a callback it gets in its constructor.
// In this test, we fake it.
std::vector<int> published_signals;
PublishCallback fakePublish = (PublishCallback)([&](int signal) { published_signals.push_back(signal); });
// Test button behaviour
Button button(fakePublish);
// It starts in released state
assert(button.state == Button::RELEASED);
// When pin 0 is high, it means button has
// been pushed as pin 0s circuit is shortcut
button.handleSignal(Signals::PIN0_HIGH);
// When the button goes down, the toggle signal
// is emitted
assert(published_signals.at(0) == Signals::TOGGLE);
// .. and we check that the button switches
// state appropriately
assert(button.state == Button::PUSHED);
// Just check that it does not react to
// wrong pin
button.handleSignal(Signals::PIN1_LOW);
assert(button.state == Button::PUSHED);
// Verify that button goes back to initial released
// state when pin goes low again
button.handleSignal(Signals::PIN0_LOW);
assert(button.state == Button::RELEASED);
// .. and that no more signal has been emitted
assert(published_signals.size() == 1);
}
int main()
{
testButton();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment