Skip to content

Commit

Permalink
clean up code (#2)
Browse files Browse the repository at this point in the history
  • Loading branch information
ahdinosaur authored May 24, 2021
1 parent dc049da commit 3dd87a4
Show file tree
Hide file tree
Showing 16 changed files with 326 additions and 204 deletions.
10 changes: 9 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,14 @@
"cinttypes": "cpp",
"typeinfo": "cpp",
"variant": "cpp",
"iostream": "cpp"
"iostream": "cpp",
"bitset": "cpp",
"chrono": "cpp",
"condition_variable": "cpp",
"cstring": "cpp",
"ctime": "cpp",
"ratio": "cpp",
"regex": "cpp",
"shared_mutex": "cpp"
}
}
4 changes: 4 additions & 0 deletions include/overload.hpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
// https://github.com/mpark/variant/issues/44#issuecomment-377333877

#pragma once

template <class... Fs>
struct OverLoaded;

Expand Down
6 changes: 4 additions & 2 deletions include/store.hpp → include/redux.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ SOFTWARE.
See also:
*/

#pragma once

#include <functional>
#include <vector>

Expand All @@ -42,7 +44,7 @@ class Store {
Store(Reducer, STATE_T);
void subscribe(Subscriber);
void dispatch(ACTION_T);
STATE_T getState();
STATE_T get_state();

private:
Reducer reducer;
Expand Down Expand Up @@ -71,6 +73,6 @@ void Store<STATE_T, ACTION_T>::dispatch(ACTION_T action) {
}

template <typename STATE_T, typename ACTION_T>
STATE_T Store<STATE_T, ACTION_T>::getState() {
STATE_T Store<STATE_T, ACTION_T>::get_state() {
return state;
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"description": "",
"scripts": {
"build": "node tools/cdata.js",
"dev": "nodemon -e js,html,htm,css,png,jpg,gif,ico,js -w tools/ -w wled00/data/ -x node tools/cdata.js"
"dev": "nodemon -e js,html,htm,css,png,jpg,gif,ico,js -w tools/ -w src/ui/ -x node tools/cdata.js"
},
"repository": {
"type": "git",
Expand Down
10 changes: 10 additions & 0 deletions src/effects/bot.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#pragma once

#include <effects/context.hpp>
#include <effects/leds.hpp>

namespace BotEffects {
void setup(BotContext *context) {
LedsEffects::setup(context);
}
}
9 changes: 9 additions & 0 deletions src/effects/context.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#pragma once

#include <store.hpp>
#include <timer.hpp>

struct BotContext {
BotStore *store;
BotTimer *timer;
};
26 changes: 26 additions & 0 deletions src/effects/leds.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#pragma once

#include <Arduino.h>
#include <STM32_ISR_Timer.h>

#include <effects/context.hpp>

namespace LedsEffects {
void output(void *params) {
BotContext *context = (BotContext*) params;
auto store = context->store;
auto state = store->get_state();
digitalWrite(LED_GREEN, state.leds.green);
digitalWrite(LED_BLUE, state.leds.blue);
digitalWrite(LED_RED, state.leds.red);
}

void setup(BotContext *context) {
pinMode(LED_GREEN, OUTPUT);
pinMode(LED_BLUE, OUTPUT);
pinMode(LED_RED, OUTPUT);

auto timer = context->timer;
timer->set_interval(10L, output, context);
}
}
201 changes: 24 additions & 177 deletions src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
#include <Arduino.h>
#include <LwIP.h>
#include <STM32Ethernet.h>
#include <AsyncWebServer_STM32.h>
#include <STM32TimerInterrupt.h>
#include <STM32_ISR_Timer.h>

#include <mpark/variant.hpp>
#include <overload.hpp>
#include <store.hpp>

#include <ui/index.h>
#include <timer.hpp>
#include <server.hpp>
#include <effects/bot.hpp>

#if !( defined(STM32F0) || defined(STM32F1) || defined(STM32F2) || defined(STM32F3) ||defined(STM32F4) || defined(STM32F7) || \
defined(STM32L0) || defined(STM32L1) || defined(STM32L4) || defined(STM32H7) ||defined(STM32G0) || defined(STM32G4) || \
Expand All @@ -20,121 +16,14 @@
// pins
// - https://github.com/stm32duino/Arduino_Core_STM32/blob/master/variants/STM32F7xx/F765Z(G-I)T_F767Z(G-I)T_F777ZIT/variant_NUCLEO_F767ZI.h

#define TIMER_INTERVAL_MS 100
#define HW_TIMER_INTERVAL_MS 50

// F767ZI can select Timer from TIM1-TIM14
STM32Timer ITimer(TIM1);

STM32_ISR_Timer ISR_Timer;

struct StateLeds {
bool green = true;
bool blue = true;
bool red = true;
BotTimer timer;
BotServer server;
BotStore store;
BotContext context = {
&store,
&timer
};

enum class LED_ID { GREEN, RED, BLUE };
struct ActionLedToggle {
LED_ID led_id;
};
using ActionLeds = mpark::variant<ActionLedToggle>;

StateLeds reducer_leds(StateLeds state, ActionLeds action) {
mpark::visit(overload(
[&state](const ActionLedToggle action) {
switch (action.led_id) {
case LED_ID::GREEN:
state.green = !state.green;
break;
case LED_ID::BLUE:
state.blue = !state.blue;
break;
case LED_ID::RED:
state.red = !state.red;
break;
}
}
), action);

return state;
}

struct ActionClockTick {};
using ActionClock = mpark::variant<ActionClockTick>;

struct StateClock {
uint16_t ticks = 0;
};

StateClock reducer_clock(StateClock state, ActionClock action) {
mpark::visit(overload(
[&state](const ActionClockTick) {
state.ticks++;
}
), action);

return state;
}

struct StateBot {
StateLeds leds = StateLeds {};
StateClock clock = StateClock {};
};

using ActionBot = mpark::variant<ActionLeds, ActionClock>;

StateBot reducer_bot(StateBot state, ActionBot action) {
noInterrupts();

mpark::visit(overload(
[&state](const ActionLeds a) {
state.leds = reducer_leds(state.leds, a);
},
[&state](const ActionClock a) {
state.clock = reducer_clock(state.clock, a);
}
), action);

interrupts();

return state;
}

Store<StateBot, ActionBot> store(reducer_bot, StateBot {});

IPAddress ip(10, 0, 0, 2);
AsyncWebServer server(80);
// uint8_t mac[] = { MAC_ADDR0, MAC_ADDR1, MAC_ADDR2, MAC_ADDR3, MAC_ADDR4, MAC_ADDR5 };
uint8_t mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x01 };
AsyncEventSource events("/events");

void handleNotFound(AsyncWebServerRequest *request)
{
String message = "File Not Found\n\n";

message += "URI: ";
//message += server.uri();
message += request->url();
message += "\nMethod: ";
message += (request->method() == HTTP_GET) ? "GET" : "POST";
message += "\nArguments: ";
message += request->args();
message += "\n";

for (uint8_t i = 0; i < request->args(); i++)
{
message += " " + request->argName(i) + ": " + request->arg(i) + "\n";
}

request->send(404, "text/plain", message);
}

void TimerHandler()
{
ISR_Timer.run();
}

volatile bool has_state_changed;

void setup()
Expand All @@ -143,87 +32,45 @@ void setup()
while (!Serial);

delay(1000);

Serial.print(F("\nStarting TimerInterrupt on ")); Serial.println(BOARD_NAME);
Serial.println(STM32_TIMER_INTERRUPT_VERSION);
Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz"));

// Interval in microsecs
if (ITimer.attachInterruptInterval(HW_TIMER_INTERVAL_MS * 1000, TimerHandler))
{
Serial.print(F("Starting ITimer OK, millis() = ")); Serial.println(millis());
}
else {
Serial.println(F("Can't set ITimer. Select another freq. or timer"));
}

Serial.println("\nStart AsyncWebServer on " + String(BOARD_NAME));
Ethernet.begin(mac, ip);

server.on("/", HTTP_GET, [](AsyncWebServerRequest * request)
{
AsyncWebServerResponse *response = request->beginResponse(200, "text/html", PAGE_INDEX);
request->send(response);
});

events.onConnect([](AsyncEventSourceClient * client)
{
client->send("hello!", NULL);
});

has_state_changed = false;
store.subscribe([](StateBot state){
has_state_changed = true;
});

server.addHandler(&events);
server.onNotFound(handleNotFound);
timer.setup();
server.begin();
BotEffects::setup(&context);

Serial.print(F("HTTP EthernetWebServer is @ IP : "));
Serial.println(Ethernet.localIP());

pinMode(LED_GREEN, OUTPUT);
pinMode(LED_BLUE, OUTPUT);
pinMode(LED_RED, OUTPUT);

ISR_Timer.setInterval(10L, [](){
StateBot state = store.getState();
digitalWrite(LED_GREEN, state.leds.green);
digitalWrite(LED_BLUE, state.leds.blue);
digitalWrite(LED_RED, state.leds.red);
store.subscribe([](BotModel::State state) {
has_state_changed = true;
});

ISR_Timer.setInterval(1000L, [](){
store.dispatch(ActionLedToggle {
led_id: LED_ID::GREEN
timer.set_interval(1000L, [](){
store.dispatch(LedsModel::ActionToggle {
led_id: LedsModel::LED_ID::GREEN
});
});

ISR_Timer.setInterval(2000L, [](){
store.dispatch(ActionLedToggle {
led_id: LED_ID::BLUE
timer.set_interval(2000L, [](){
store.dispatch(LedsModel::ActionToggle {
led_id: LedsModel::LED_ID::BLUE
});
});

ISR_Timer.setInterval(4000L, [](){
store.dispatch(ActionLedToggle {
led_id: LED_ID::RED
timer.set_interval(4000L, [](){
store.dispatch(LedsModel::ActionToggle {
led_id: LedsModel::LED_ID::RED
});
});
}

void loop()
{
if (has_state_changed) {
StateBot state = store.getState();
BotModel::State state = store.get_state();

String status = "";
if (state.leds.green) status += ":green";
if (state.leds.blue) status += ":blue";
if (state.leds.red) status += ":red";

events.send(status.c_str(), "status", millis());
server.events.send(status.c_str(), "status", millis());
has_state_changed = false;
}
}
Loading

0 comments on commit 3dd87a4

Please sign in to comment.