Initial commit
This commit is contained in:
BIN
firmware/inputs/.FlaschenTaschen.cpp.swp
Normal file
BIN
firmware/inputs/.FlaschenTaschen.cpp.swp
Normal file
Binary file not shown.
82
firmware/inputs/Buttons.h
Normal file
82
firmware/inputs/Buttons.h
Normal file
@ -0,0 +1,82 @@
|
||||
#pragma once
|
||||
|
||||
class Bounce {
|
||||
public:
|
||||
void attach(int pin, PinMode buttonPinMode) {
|
||||
m_pin = pin;
|
||||
pinMode(m_pin, buttonPinMode);
|
||||
Log.info("Attaching a button to %d", pin);
|
||||
}
|
||||
|
||||
void update() {
|
||||
int readResult = digitalRead(m_pin);
|
||||
if (m_state == Ready) {
|
||||
if (readResult == HIGH) {
|
||||
m_state = Started;
|
||||
m_downStart = millis();
|
||||
Log.info("Button %d is started!", m_pin);
|
||||
}
|
||||
} else if (m_state == Started && millis() - m_downStart >= m_interval) {
|
||||
if (readResult == HIGH) {
|
||||
m_state = Confirmed;
|
||||
Log.info("Button %d is CONFIRMED!", m_pin);
|
||||
} else {
|
||||
m_state = Ready;
|
||||
Log.info("Button %d bounced back to ready!", m_pin);
|
||||
}
|
||||
} else if (m_state == Confirmed || m_state == Held) {
|
||||
if (readResult == LOW) {
|
||||
m_state = Ready;
|
||||
Log.info("Button %d is released and back to ready!", m_pin);
|
||||
} else if (m_state == Confirmed) {
|
||||
m_state = Held;
|
||||
Log.info("Button %d is being held down!", m_pin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void interval(uint8_t v) {
|
||||
m_interval = v;
|
||||
}
|
||||
|
||||
bool fell() const {
|
||||
return m_state == Confirmed;
|
||||
}
|
||||
|
||||
private:
|
||||
enum State {
|
||||
Ready,
|
||||
Started,
|
||||
Confirmed,
|
||||
Held
|
||||
};
|
||||
|
||||
State m_state = Ready;
|
||||
unsigned int m_pin = 0;
|
||||
unsigned int m_downStart = 0;
|
||||
unsigned int m_interval = 10;
|
||||
};
|
||||
|
||||
class Buttons: public InputSource {
|
||||
public:
|
||||
void onStart() override {
|
||||
for(int i = 0; i < 3; i++) {
|
||||
m_buttons[i].attach(2 + i, INPUT_PULLDOWN);
|
||||
m_buttons[i].interval(15);
|
||||
}
|
||||
}
|
||||
|
||||
InputEvent read() override {
|
||||
for(int i = 0; i < 3; i++) {
|
||||
m_buttons[i].update();
|
||||
if (m_buttons[i].fell()) {
|
||||
return InputEvent{m_buttonMap[i]};
|
||||
}
|
||||
}
|
||||
return InputEvent{};
|
||||
}
|
||||
|
||||
private:
|
||||
Bounce m_buttons[3];
|
||||
InputEvent::Intent m_buttonMap[3] = {InputEvent::PowerToggle, InputEvent::NextPattern, InputEvent::UserInput};
|
||||
};
|
25
firmware/inputs/CloudStatus.cpp
Normal file
25
firmware/inputs/CloudStatus.cpp
Normal file
@ -0,0 +1,25 @@
|
||||
#include "CloudStatus.h"
|
||||
#include "../Static.h"
|
||||
|
||||
void
|
||||
CloudStatus::onStart()
|
||||
{
|
||||
SINGLE_THREADED_BLOCK() {
|
||||
if (Particle.connected()) {
|
||||
initNetwork(0, cloud_status_connected);
|
||||
} else {
|
||||
System.on(cloud_status, &CloudStatus::initNetwork);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CloudStatus::initNetwork(system_event_t event, int param) {
|
||||
if (param == cloud_status_connected) {
|
||||
Log.info("Connected to T H E C L O U D");
|
||||
MainLoop::instance()->dispatch(InputEvent{InputEvent::NetworkStatus, true});
|
||||
}
|
||||
}
|
||||
|
||||
STATIC_ALLOC(CloudStatus);
|
11
firmware/inputs/CloudStatus.h
Normal file
11
firmware/inputs/CloudStatus.h
Normal file
@ -0,0 +1,11 @@
|
||||
#include "../Figments/Figments.h"
|
||||
|
||||
class CloudStatus: public Task {
|
||||
public:
|
||||
CloudStatus() : Task("Cloud") {}
|
||||
void loop() override {}
|
||||
void onStart() override;
|
||||
|
||||
private:
|
||||
static void initNetwork(system_event_t event, int param);
|
||||
};
|
0
firmware/inputs/ColorCycle.cpp
Normal file
0
firmware/inputs/ColorCycle.cpp
Normal file
20
firmware/inputs/ColorCycle.h
Normal file
20
firmware/inputs/ColorCycle.h
Normal file
@ -0,0 +1,20 @@
|
||||
#include "../Figments/Figments.h"
|
||||
|
||||
template<int Period>
|
||||
class ColorSequenceInput: public InputSource {
|
||||
public:
|
||||
ColorSequenceInput(const std::vector<NSFastLED::CRGB> &colors, const char* name, Task::State initialState)
|
||||
: InputSource(name, initialState), m_colors(colors) {}
|
||||
|
||||
InputEvent read() override {
|
||||
EVERY_N_SECONDS(Period) {
|
||||
m_idx %= m_colors.size();
|
||||
return InputEvent{InputEvent::SetColor, m_colors[m_idx++]};
|
||||
}
|
||||
return InputEvent{};
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<NSFastLED::CRGB> m_colors;
|
||||
int m_idx = 0;
|
||||
};
|
79
firmware/inputs/DMX.cpp
Normal file
79
firmware/inputs/DMX.cpp
Normal file
@ -0,0 +1,79 @@
|
||||
#if 0
|
||||
#include "Particle.h"
|
||||
#include "../Input.h"
|
||||
#include "../colors.h"
|
||||
#include "../Static.h"
|
||||
|
||||
volatile uint8_t DmxRxField[8];
|
||||
volatile uint16_t DmxAddress;
|
||||
enum { IDLE, BREAK, STARTB, STARTADR };
|
||||
|
||||
volatile uint8_t gDmxState;
|
||||
|
||||
class DMXInput: public InputSource {
|
||||
public:
|
||||
void init() {
|
||||
UCSR1B = (1<<RXEN1) | (1<<RXCE1);
|
||||
Serial1.begin(250000, SERIAL_8N2);
|
||||
}
|
||||
|
||||
static void handleInterrupt() {
|
||||
static uint16_t DmxCount;
|
||||
uint8_t USARTstate = UCSR1A;
|
||||
uint8_t DmxByte = UDR1;
|
||||
uint8_t DmxState = gDmxState;
|
||||
|
||||
if (USARTstate &(1<<FE1)) {
|
||||
DmxCount = DmxAddress;
|
||||
gDmxState = BREAK;
|
||||
} else if (DmxState == BREAK) {
|
||||
if (DmxByte == 0) {
|
||||
gDmxState = STARTB;
|
||||
} else {
|
||||
gDmxState = IDLE;
|
||||
}
|
||||
} else if (DmxState == STARTB) {
|
||||
if (--DmxCount == 0) {
|
||||
DmxCount = 1;
|
||||
DmxRxField[0] = DmxByte;
|
||||
gDmxState = STARTADR;
|
||||
}
|
||||
} else if (DmxState == STARTADR) {
|
||||
DmxRxField[DmxCount++] = DmxByte;
|
||||
if (DmxCount >= sizeof(DmxRxField)) {
|
||||
gDmxState = IDLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void update() override {
|
||||
bool hasUpdate = false;
|
||||
if (gDmxState == IDLE) {
|
||||
for(int i = 0; i < 8; i++) {
|
||||
if (m_lastReadFields[i] != DmxRxField[i]) {
|
||||
hasUpdate = true;
|
||||
m_lastReadFields[i] = DmxRxField[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hasUpdate) {
|
||||
m_lastReadEvent = InputEvent(InputEvent::SetColor, {m_lastReadFields[0], m_lastReadFields[1], m_lastReadFields[2]});
|
||||
}
|
||||
m_lastEvent = m_lastReadEvent;
|
||||
m_lastReadEvent = InputEvent();
|
||||
}
|
||||
|
||||
virtual InputEvent read() const override {
|
||||
return m_lastEvent;
|
||||
}
|
||||
|
||||
private:
|
||||
InputEvent m_lastEvent;
|
||||
InputEvent m_lastReadEvent;
|
||||
uint8_t m_lastReadFields[8];
|
||||
};
|
||||
|
||||
ISR(USART1_RX_vect) {
|
||||
DMXInput::handleInterrupt();
|
||||
}
|
||||
#endif
|
0
firmware/inputs/MPU6050.cpp
Normal file
0
firmware/inputs/MPU6050.cpp
Normal file
94
firmware/inputs/MPU6050.h
Normal file
94
firmware/inputs/MPU6050.h
Normal file
@ -0,0 +1,94 @@
|
||||
class MPU5060: public InputSource {
|
||||
const int ACCEL_XOUT_HIGH = 0x3B;
|
||||
const int ACCEL_XOUT_LOW = 0x3C;
|
||||
const int ACCEL_YOUT_HIGH = 0x3D;
|
||||
const int ACCEL_YOUT_LOW = 0x3E;
|
||||
const int ACCEL_ZOUT_HIGH = 0x3F;
|
||||
const int ACCEL_ZOUT_LOW = 0x40;
|
||||
|
||||
const int I2C_ADDRESS = 0x68;
|
||||
|
||||
const int PWR_MGMT_1 = 0x6B;
|
||||
const int CONFIG_REG = 0x1A;
|
||||
const int ACCEL_CONFIG_REG = 0x1C;
|
||||
|
||||
public:
|
||||
void onStart() override {
|
||||
Wire.begin();
|
||||
|
||||
// Turn on the sensor
|
||||
Wire.beginTransmission(I2C_ADDRESS);
|
||||
Wire.write(PWR_MGMT_1);
|
||||
Wire.write(0);
|
||||
Wire.endTransmission(true);
|
||||
|
||||
// Configure the filter
|
||||
Wire.beginTransmission(I2C_ADDRESS);
|
||||
Wire.write(CONFIG_REG);
|
||||
Wire.write(3);
|
||||
Wire.endTransmission(true);
|
||||
|
||||
// Configure the accel range
|
||||
Wire.beginTransmission(I2C_ADDRESS);
|
||||
Wire.write(ACCEL_CONFIG_REG);
|
||||
// 4G
|
||||
Wire.write(2 << 3);
|
||||
Wire.endTransmission(true);
|
||||
}
|
||||
|
||||
void onStop() override {
|
||||
Wire.beginTransmission(I2C_ADDRESS);
|
||||
// Turn off the sensor
|
||||
Wire.write(PWR_MGMT_1);
|
||||
Wire.write(1);
|
||||
Wire.endTransmission(true);
|
||||
Wire.end();
|
||||
}
|
||||
|
||||
InputEvent read() override {
|
||||
EVERY_N_MILLISECONDS(5) {
|
||||
Wire.beginTransmission(I2C_ADDRESS);
|
||||
Wire.write(ACCEL_XOUT_HIGH);
|
||||
Wire.endTransmission(false);
|
||||
Wire.requestFrom(I2C_ADDRESS, 6);
|
||||
const int16_t accelX = Wire.read() << 8 | Wire.read();
|
||||
const int16_t accelY = Wire.read() << 8 | Wire.read();
|
||||
const int16_t accelZ = Wire.read() << 8 | Wire.read();
|
||||
const uint16_t accelSum = abs(accelX) + abs(accelY) + abs(accelZ);
|
||||
const uint16_t delta = abs(m_value.value() - accelSum);
|
||||
m_value.add(accelSum);
|
||||
if (delta > 32) {
|
||||
return InputEvent{InputEvent::Acceleration, delta};
|
||||
}
|
||||
}
|
||||
return InputEvent{};
|
||||
}
|
||||
|
||||
template<typename T, uint8_t Size = 8>
|
||||
struct Averager {
|
||||
std::array<T, Size> buf;
|
||||
unsigned int idx = 0;
|
||||
unsigned int count = 0;
|
||||
|
||||
void add(const T &value) {
|
||||
buf[idx] = value;
|
||||
idx = (idx + 1) % Size;
|
||||
if (count < Size) {
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
T value() const {
|
||||
if (count == 0) {
|
||||
return T{};
|
||||
}
|
||||
long long int sum = 0;
|
||||
for(unsigned int i = 0; i < count; i++) {
|
||||
sum += buf[i];
|
||||
}
|
||||
return sum / count;
|
||||
}
|
||||
};
|
||||
|
||||
Averager<int16_t, 32> m_value;
|
||||
};
|
138
firmware/inputs/Photon.cpp
Normal file
138
firmware/inputs/Photon.cpp
Normal file
@ -0,0 +1,138 @@
|
||||
#include "Particle.h"
|
||||
#include "../Figments/Figments.h"
|
||||
#include "../colors.h"
|
||||
#include "../Static.h"
|
||||
#include "./Photon.h"
|
||||
|
||||
void
|
||||
PhotonInput::onConnected()
|
||||
{
|
||||
Log.info("Connecting photon input...");
|
||||
Particle.function("power", &PhotonInput::setPower, this);
|
||||
Particle.function("next", &PhotonInput::nextPattern, this);
|
||||
Particle.function("input", &PhotonInput::input, this);
|
||||
Particle.function("previous", &PhotonInput::previousPattern, this);
|
||||
Particle.function("pattern", &PhotonInput::setPattern, this);
|
||||
Particle.function("setHue", &PhotonInput::setHue, this);
|
||||
Particle.function("brightness", &PhotonInput::setBrightness, this);
|
||||
Particle.function("reboot", &PhotonInput::reboot, this);
|
||||
Particle.function("start", &PhotonInput::startThing, this);
|
||||
Particle.function("stop", &PhotonInput::stopThing, this);
|
||||
}
|
||||
|
||||
int
|
||||
PhotonInput::startThing(String command)
|
||||
{
|
||||
command.toCharArray(m_commandBuf, sizeof(m_commandBuf));
|
||||
setEvent(InputEvent(InputEvent::StartThing, m_commandBuf));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
PhotonInput::stopThing(String command)
|
||||
{
|
||||
command.toCharArray(m_commandBuf, sizeof(m_commandBuf));
|
||||
setEvent(InputEvent(InputEvent::StopThing, m_commandBuf));
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
PhotonInput::onStart()
|
||||
{
|
||||
System.on(firmware_update, &PhotonInput::onFirmwareUpdate);
|
||||
System.on(button_click, &PhotonInput::onButtonClick);
|
||||
System.on(reset, &PhotonInput::onReset);
|
||||
}
|
||||
|
||||
void
|
||||
PhotonInput::handleEvent(const InputEvent &evt)
|
||||
{
|
||||
if (evt.intent == InputEvent::NetworkStatus) {
|
||||
onConnected();
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
PhotonInput::reboot(String command)
|
||||
{
|
||||
System.reset();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
PhotonInput::onReset(system_event_t event, int param)
|
||||
{
|
||||
NSFastLED::FastLED.clear();
|
||||
}
|
||||
|
||||
void
|
||||
PhotonInput::onButtonClick(system_event_t event, int param)
|
||||
{
|
||||
Static<PhotonInput>::instance()->setEvent(InputEvent{InputEvent::NextPattern, param});
|
||||
}
|
||||
|
||||
void
|
||||
PhotonInput::onFirmwareUpdate(system_event_t event, int param)
|
||||
{
|
||||
Static<PhotonInput>::instance()->setEvent(InputEvent{InputEvent::FirmwareUpdate, param});
|
||||
}
|
||||
|
||||
int
|
||||
PhotonInput::input(String command)
|
||||
{
|
||||
command.toCharArray(m_commandBuf, sizeof(m_commandBuf));
|
||||
setEvent(InputEvent(InputEvent::UserInput, m_commandBuf));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
PhotonInput::setPattern(String command)
|
||||
{
|
||||
command.toCharArray(m_commandBuf, sizeof(m_commandBuf));
|
||||
setEvent(InputEvent(InputEvent::SetPattern, m_commandBuf));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
PhotonInput::setHue(String colorName)
|
||||
{
|
||||
ColorInfo nextColor = colorForName(colorName);
|
||||
setEvent(InputEvent(InputEvent::SetColor, nextColor.rgb));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
PhotonInput::nextPattern(String command)
|
||||
{
|
||||
setEvent(InputEvent(InputEvent::NextPattern));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
PhotonInput::previousPattern(String command)
|
||||
{
|
||||
setEvent(InputEvent(InputEvent::PreviousPattern));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
PhotonInput::setPower(String command)
|
||||
{
|
||||
if (command == "off") {
|
||||
setEvent(InputEvent(InputEvent::SetPower, 0));
|
||||
} else if (command == "on") {
|
||||
setEvent(InputEvent(InputEvent::SetPower, 1));
|
||||
} else {
|
||||
setEvent(InputEvent(InputEvent::PowerToggle));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
PhotonInput::setBrightness(String command)
|
||||
{
|
||||
setEvent(InputEvent(InputEvent::SetBrightness, command.toInt()));
|
||||
return 0;
|
||||
}
|
||||
|
||||
STATIC_ALLOC(PhotonInput);
|
29
firmware/inputs/Photon.h
Normal file
29
firmware/inputs/Photon.h
Normal file
@ -0,0 +1,29 @@
|
||||
#include "Particle.h"
|
||||
#include "../Figments/Figments.h"
|
||||
|
||||
class PhotonInput: public BufferedInputSource {
|
||||
public:
|
||||
PhotonInput() : BufferedInputSource("PhotonInput") {}
|
||||
void onStart() override;
|
||||
void handleEvent(const InputEvent &evt) override;
|
||||
|
||||
private:
|
||||
char m_commandBuf[16];
|
||||
|
||||
void onConnected();
|
||||
int reboot(String command);
|
||||
int input(String command);
|
||||
int setPattern(String command);
|
||||
int setHue(String colorName);
|
||||
int nextPattern(String command);
|
||||
int previousPattern(String command);
|
||||
int setPower(String command);
|
||||
int setBrightness(String command);
|
||||
|
||||
int startThing(String command);
|
||||
int stopThing(String command);
|
||||
|
||||
static void onReset(system_event_t event, int param);
|
||||
static void onButtonClick(system_event_t event, int param);
|
||||
static void onFirmwareUpdate(system_event_t event, int param);
|
||||
};
|
12
firmware/inputs/Serial.h
Normal file
12
firmware/inputs/Serial.h
Normal file
@ -0,0 +1,12 @@
|
||||
#include "Particle.h"
|
||||
#include "../Figments/Figments.h"
|
||||
|
||||
class SerialInput: public InputSource {
|
||||
public:
|
||||
void onAttach() override {
|
||||
//Serial.begin();
|
||||
}
|
||||
|
||||
InputEvent read() {
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user