blink-led-uart.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. // SPDX-License-Identifier: MIT
  2. // SPDX-FileCopyrightText: 2022 Ivan Baidakou
  3. #include "board.h"
  4. #include "rotor-light.hpp"
  5. #include <string.h>
  6. namespace rl = rotor_light;
  7. namespace message {
  8. struct ChangeInterval : rl::Message {
  9. static constexpr auto type_id = __LINE__;
  10. ChangeInterval(rl::ActorId to, const rl::Duration &delta_)
  11. : Message{to}, delta{delta_} {}
  12. rl::Duration delta;
  13. };
  14. struct Notify : rl::Message {
  15. static constexpr auto type_id = __LINE__;
  16. Notify(rl::ActorId to, const char *data_) : Message(to), data{data_} {}
  17. const char *data;
  18. };
  19. } // namespace message
  20. struct Blinker : rl::Actor<2> {
  21. using Parent = Actor<2>;
  22. void initialize() override {
  23. next_event = 0;
  24. subscribe(&Blinker::on_change_interval);
  25. Parent::initialize();
  26. }
  27. void advance_start() override {
  28. Parent::advance_start();
  29. next_event = add_event<rl::ctx::thread>(
  30. delay, [](void *data) { static_cast<Blinker *>(data)->blink(); }, this);
  31. }
  32. void blink() {
  33. if (next_event) {
  34. supervisor->get_planner()->remove_event(next_event);
  35. }
  36. Board::toggle_led();
  37. send<rl::ctx::thread, message::Notify>(0, notifier_id, "blink\r\n");
  38. next_event = add_event<rl::ctx::thread>(
  39. delay, [](void *data) { static_cast<Blinker *>(data)->blink(); }, this);
  40. }
  41. void on_change_interval(message::ChangeInterval &msg) {
  42. if (delay > msg.delta) {
  43. send<rl::ctx::thread, message::Notify>(0, notifier_id, "dec\r\n");
  44. } else {
  45. send<rl::ctx::thread, message::Notify>(0, notifier_id, "inc\r\n");
  46. }
  47. delay = msg.delta;
  48. blink();
  49. }
  50. rl::ActorId notifier_id;
  51. rl::Duration delay;
  52. rl::TimePoint next_event;
  53. };
  54. struct Notifier : rl::Actor<2> {
  55. using Parent = Actor<2>;
  56. void initialize() override {
  57. ptr = end = nullptr;
  58. subscribe(&Notifier::on_notify);
  59. Parent::initialize();
  60. }
  61. void advance_start() override {
  62. Parent::advance_start();
  63. send<rl::ctx::thread, message::Notify>(0, id, "Ready\n");
  64. }
  65. void on_notify(message::Notify &message) {
  66. if (!ptr) { // prevent overloading
  67. ROTOR_LIGHT_DISABLE_INTERRUPTS();
  68. ptr = message.data;
  69. end = message.data + strlen(message.data);
  70. send_next();
  71. ROTOR_LIGHT_ENABLE_INTERRUPTS();
  72. }
  73. }
  74. void send_next() {
  75. if (end) {
  76. if (ptr == end) {
  77. ptr = nullptr;
  78. end = nullptr;
  79. } else {
  80. Board::send_uart(*ptr++);
  81. }
  82. }
  83. }
  84. volatile const char *ptr;
  85. const char *end;
  86. };
  87. static void app_hw_init();
  88. using Supervisor =
  89. rl::Supervisor<rl::SupervisorBase::min_handlers_amount, Blinker, Notifier>;
  90. using Storage =
  91. rl::traits::MessageStorage<rl::message::ChangeState,
  92. rl::message::ChangeStateAck,
  93. message::ChangeInterval, message::Notify>;
  94. using Queue = rl::Queue<Storage, 5>; /* upto 5 messages in 1 queue */
  95. using Planner = rl::Planner<2>; /* upto 2 time events */
  96. static void on_rx(char c);
  97. static void on_tx();
  98. Supervisor sup;
  99. int main(int, char **) {
  100. Board::init_start();
  101. Board::enable_timer();
  102. Board::enable_uart(&on_rx, &on_tx);
  103. ROTOR_LIGHT_ENABLE_INTERRUPTS();
  104. /* setup */
  105. Queue queue;
  106. Planner planner;
  107. rl::Context context{&queue, &planner, &Board::get_now};
  108. sup.bind(context);
  109. auto blinker = sup.get_child<0>();
  110. blinker->delay = rl::Duration{1000000};
  111. blinker->notifier_id = sup.get_child<1>()->get_id();
  112. /* let it polls timer */
  113. sup.start(true);
  114. /* main cycle */
  115. sup.process();
  116. return 0;
  117. }
  118. static void on_rx(char c) {
  119. auto blinker = sup.get_child<0>();
  120. const auto &value = blinker->delay;
  121. if (c == '+') {
  122. auto new_value = value + value / 10;
  123. blinker->send<rl::ctx::thread, message::ChangeInterval>(
  124. 0, blinker->get_id(), new_value);
  125. } else if (c == '-') {
  126. auto new_value = value - value / 10;
  127. blinker->send<rl::ctx::thread, message::ChangeInterval>(
  128. 0, blinker->get_id(), new_value);
  129. }
  130. }
  131. static void on_tx() {
  132. auto notifier = sup.get_child<1>();
  133. notifier->send_next();
  134. }