ping-pong-poll.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. // SPDX-License-Identifier: MIT
  2. // SPDX-FileCopyrightText: 2022 Ivan Baidakou
  3. #include "common.h"
  4. #include <avr/interrupt.h>
  5. #include <avr/io.h>
  6. #include <avr/wdt.h>
  7. #include <rotor-light.hpp>
  8. #include <string.h>
  9. #define LED PB5
  10. void send_usart(const char *data);
  11. void send_usart(const char *data, size_t count);
  12. namespace rl = rotor_light;
  13. namespace message {
  14. struct Ping : rl::Message {
  15. using Message::Message;
  16. static constexpr auto type_id = __LINE__;
  17. rl::MessageTypeId get_type_id() const override { return type_id; }
  18. };
  19. struct Pong : rl::Message {
  20. using Message::Message;
  21. static constexpr auto type_id = __LINE__;
  22. rl::MessageTypeId get_type_id() const override { return type_id; }
  23. };
  24. } // namespace message
  25. struct Pinger : rl::Actor<2> {
  26. using Parent = Actor<2>;
  27. void initialize() override {
  28. subscribe(&Pinger::on_pong);
  29. Parent::initialize();
  30. }
  31. void advance_start() override {
  32. Parent::advance_start();
  33. ping();
  34. }
  35. void ping() {
  36. /* toggle led */
  37. PORTB ^= (1 << LED);
  38. send_usart("ping\r\n");
  39. send<message::Ping>(0, ponger_id);
  40. }
  41. void on_pong(message::Pong &) {
  42. add_event(
  43. 500000, [](void *data) { static_cast<Pinger *>(data)->ping(); }, this);
  44. }
  45. rl::ActorId ponger_id;
  46. };
  47. struct Ponger : rl::Actor<2> {
  48. using Parent = Actor<2>;
  49. void initialize() override {
  50. subscribe(&Ponger::on_ping);
  51. Parent::initialize();
  52. }
  53. void on_ping(message::Ping &) {
  54. send<message::Pong>(0, pinger_id);
  55. }
  56. rl::ActorId pinger_id;
  57. };
  58. using Supervisor =
  59. rl::Supervisor<rl::SupervisorBase::min_handlers_amount, Pinger, Ponger>;
  60. using Storage = rl::traits::MessageStorage<rl::message::ChangeState,
  61. rl::message::ChangeStateAck,
  62. message::Ping, message::Pong>;
  63. using Queue = rl::Queue<Storage, 5>; /* upto 5 messages in 1 queue */
  64. using Planner = rl::Planner<1>; /* upto 1 time event */
  65. static void app_hw_init();
  66. /* allocate */
  67. Queue queue;
  68. Planner planner;
  69. rl::Context context{&queue, &planner, &get_now};
  70. Supervisor sup;
  71. int main(int, char **) {
  72. app_hw_init();
  73. /* setup */
  74. sup.bind(context);
  75. auto pinger = sup.get_child<0>();
  76. auto ponger = sup.get_child<1>();
  77. pinger->ponger_id = ponger->get_id();
  78. ponger->pinger_id = pinger->get_id();
  79. /* let it polls timer */
  80. sup.start(true);
  81. send_usart("start\r\n");
  82. /* main cycle */
  83. sup.process();
  84. return 0;
  85. }
  86. static void app_hw_init() {
  87. // Initialize the application including WDT, PORTB.5 and TIMER0
  88. // We will now disable the watchdog.
  89. // Service the watchdog just to be sure to avoid pending timeout.
  90. wdt_reset();
  91. // Clear WDRF in MCUSR.
  92. MCUSR &= ~(1U << WDRF);
  93. // Write logical one to WDCE and WDE.
  94. // Keep the old prescaler setting to prevent unintentional time-out.
  95. WDTCSR |= (1U << WDCE) | (1U << WDE);
  96. // Turn off the WDT.
  97. WDTCSR = 0x00;
  98. // We will now initialize PORTB.5 to be used as an LED driver port.
  99. // Set PORTB.5 value to low.
  100. PORTB &= ~(1U << PORTB5);
  101. /* initializing PB5 which is connected to port 13 of uno as output*/
  102. DDRB |= (1 << LED);
  103. enable_timer();
  104. // USART
  105. #define BAUD 9600
  106. #include <util/setbaud.h>
  107. UBRR0H = UBRRH_VALUE;
  108. UBRR0L = UBRRL_VALUE;
  109. UCSR0B = (1 << RXEN0) | (1 << TXEN0);
  110. /* Set frame format: 8data, 2stop bit */
  111. UCSR0C = (1 << USBS0) | (3 << UCSZ00);
  112. // Enable all interrupts.
  113. sei();
  114. }
  115. void send_usart(const char *data) { send_usart(data, strlen(data)); }
  116. void send_usart(const char *data, size_t count) {
  117. auto end = data + count;
  118. while (data != end) {
  119. while (!(UCSR0A & (1 << UDRE0)))
  120. ;
  121. UDR0 = static_cast<uint8_t>(*data++);
  122. }
  123. }