123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- // SPDX-License-Identifier: MIT
- // SPDX-FileCopyrightText: 2022 Ivan Baidakou
- #include "board.h"
- #include "rotor-light.hpp"
- #include <string.h>
- namespace rl = rotor_light;
- namespace message {
- struct ChangeInterval : rl::Message {
- static constexpr auto type_id = __LINE__;
- ChangeInterval(rl::ActorId to, const rl::Duration &delta_)
- : Message{to}, delta{delta_} {}
- rl::Duration delta;
- };
- struct Notify : rl::Message {
- static constexpr auto type_id = __LINE__;
- Notify(rl::ActorId to, const char *data_) : Message(to), data{data_} {}
- const char *data;
- };
- } // namespace message
- struct Blinker : rl::Actor<2> {
- using Parent = Actor<2>;
- void initialize() override {
- next_event = 0;
- subscribe(&Blinker::on_change_interval);
- Parent::initialize();
- }
- void advance_start() override {
- Parent::advance_start();
- next_event = add_event<rl::ctx::thread>(
- delay, [](void *data) { static_cast<Blinker *>(data)->blink(); }, this);
- }
- void blink() {
- if (next_event) {
- supervisor->get_planner()->remove_event(next_event);
- }
- Board::toggle_led();
- send<rl::ctx::thread, message::Notify>(0, notifier_id, "blink\r\n");
- next_event = add_event<rl::ctx::thread>(
- delay, [](void *data) { static_cast<Blinker *>(data)->blink(); }, this);
- }
- void on_change_interval(message::ChangeInterval &msg) {
- if (delay > msg.delta) {
- send<rl::ctx::thread, message::Notify>(0, notifier_id, "dec\r\n");
- } else {
- send<rl::ctx::thread, message::Notify>(0, notifier_id, "inc\r\n");
- }
- delay = msg.delta;
- blink();
- }
- rl::ActorId notifier_id;
- rl::Duration delay;
- rl::TimePoint next_event;
- };
- struct Notifier : rl::Actor<2> {
- using Parent = Actor<2>;
- void initialize() override {
- ptr = end = nullptr;
- subscribe(&Notifier::on_notify);
- Parent::initialize();
- }
- void advance_start() override {
- Parent::advance_start();
- send<rl::ctx::thread, message::Notify>(0, id, "Ready\n");
- }
- void on_notify(message::Notify &message) {
- if (!ptr) { // prevent overloading
- ROTOR_LIGHT_DISABLE_INTERRUPTS();
- ptr = message.data;
- end = message.data + strlen(message.data);
- send_next();
- ROTOR_LIGHT_ENABLE_INTERRUPTS();
- }
- }
- void send_next() {
- if (end) {
- if (ptr == end) {
- ptr = nullptr;
- end = nullptr;
- } else {
- Board::send_uart(*ptr++);
- }
- }
- }
- volatile const char *ptr;
- const char *end;
- };
- static void app_hw_init();
- using Supervisor =
- rl::Supervisor<rl::SupervisorBase::min_handlers_amount, Blinker, Notifier>;
- using Storage =
- rl::traits::MessageStorage<rl::message::ChangeState,
- rl::message::ChangeStateAck,
- message::ChangeInterval, message::Notify>;
- using Queue = rl::Queue<Storage, 5>; /* upto 5 messages in 1 queue */
- using Planner = rl::Planner<2>; /* upto 2 time events */
- static void on_rx(char c);
- static void on_tx();
- Supervisor sup;
- int main(int, char **) {
- Board::init_start();
- Board::enable_timer();
- Board::enable_uart(&on_rx, &on_tx);
- ROTOR_LIGHT_ENABLE_INTERRUPTS();
- /* setup */
- Queue queue;
- Planner planner;
- rl::Context context{&queue, &planner, &Board::get_now};
- sup.bind(context);
- auto blinker = sup.get_child<0>();
- blinker->delay = rl::Duration{1000000};
- blinker->notifier_id = sup.get_child<1>()->get_id();
- /* let it polls timer */
- sup.start(true);
- /* main cycle */
- sup.process();
- return 0;
- }
- static void on_rx(char c) {
- auto blinker = sup.get_child<0>();
- const auto &value = blinker->delay;
- if (c == '+') {
- auto new_value = value + value / 10;
- blinker->send<rl::ctx::thread, message::ChangeInterval>(
- 0, blinker->get_id(), new_value);
- } else if (c == '-') {
- auto new_value = value - value / 10;
- blinker->send<rl::ctx::thread, message::ChangeInterval>(
- 0, blinker->get_id(), new_value);
- }
- }
- static void on_tx() {
- auto notifier = sup.get_child<1>();
- notifier->send_next();
- }
|