123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- // SPDX-License-Identifier: MIT
- // SPDX-FileCopyrightText: 2022 Ivan Baidakou
- #include "common.h"
- #include <avr/interrupt.h>
- #include <avr/io.h>
- #include <avr/wdt.h>
- #include <rotor-light.hpp>
- #include <string.h>
- #define LED PB5
- void send_usart(const char *data);
- void send_usart(const char *data, size_t count);
- namespace rl = rotor_light;
- namespace message {
- struct Ping : rl::Message {
- using Message::Message;
- static constexpr auto type_id = __LINE__;
- rl::MessageTypeId get_type_id() const override { return type_id; }
- };
- struct Pong : rl::Message {
- using Message::Message;
- static constexpr auto type_id = __LINE__;
- rl::MessageTypeId get_type_id() const override { return type_id; }
- };
- } // namespace message
- struct Pinger : rl::Actor<2> {
- using Parent = Actor<2>;
- void initialize() override {
- subscribe(&Pinger::on_pong);
- Parent::initialize();
- }
- void advance_start() override {
- Parent::advance_start();
- ping();
- }
- void ping() {
- /* toggle led */
- PORTB ^= (1 << LED);
- send_usart("ping\r\n");
- send<message::Ping>(0, ponger_id);
- }
- void on_pong(message::Pong &) {
- add_event(
- 500000, [](void *data) { static_cast<Pinger *>(data)->ping(); }, this);
- }
- rl::ActorId ponger_id;
- };
- struct Ponger : rl::Actor<2> {
- using Parent = Actor<2>;
- void initialize() override {
- subscribe(&Ponger::on_ping);
- Parent::initialize();
- }
- void on_ping(message::Ping &) {
- send<message::Pong>(0, pinger_id);
- }
- rl::ActorId pinger_id;
- };
- using Supervisor =
- rl::Supervisor<rl::SupervisorBase::min_handlers_amount, Pinger, Ponger>;
- using Storage = rl::traits::MessageStorage<rl::message::ChangeState,
- rl::message::ChangeStateAck,
- message::Ping, message::Pong>;
- using Queue = rl::Queue<Storage, 5>; /* upto 5 messages in 1 queue */
- using Planner = rl::Planner<1>; /* upto 1 time event */
- static void app_hw_init();
- /* allocate */
- Queue queue;
- Planner planner;
- rl::Context context{&queue, &planner, &get_now};
- Supervisor sup;
- int main(int, char **) {
- app_hw_init();
- /* setup */
- sup.bind(context);
- auto pinger = sup.get_child<0>();
- auto ponger = sup.get_child<1>();
- pinger->ponger_id = ponger->get_id();
- ponger->pinger_id = pinger->get_id();
- /* let it polls timer */
- sup.start(true);
- send_usart("start\r\n");
- /* main cycle */
- sup.process();
- return 0;
- }
- static void app_hw_init() {
- // Initialize the application including WDT, PORTB.5 and TIMER0
- // We will now disable the watchdog.
- // Service the watchdog just to be sure to avoid pending timeout.
- wdt_reset();
- // Clear WDRF in MCUSR.
- MCUSR &= ~(1U << WDRF);
- // Write logical one to WDCE and WDE.
- // Keep the old prescaler setting to prevent unintentional time-out.
- WDTCSR |= (1U << WDCE) | (1U << WDE);
- // Turn off the WDT.
- WDTCSR = 0x00;
- // We will now initialize PORTB.5 to be used as an LED driver port.
- // Set PORTB.5 value to low.
- PORTB &= ~(1U << PORTB5);
- /* initializing PB5 which is connected to port 13 of uno as output*/
- DDRB |= (1 << LED);
- enable_timer();
- // USART
- #define BAUD 9600
- #include <util/setbaud.h>
- UBRR0H = UBRRH_VALUE;
- UBRR0L = UBRRL_VALUE;
- UCSR0B = (1 << RXEN0) | (1 << TXEN0);
- /* Set frame format: 8data, 2stop bit */
- UCSR0C = (1 << USBS0) | (3 << UCSZ00);
- // Enable all interrupts.
- sei();
- }
- void send_usart(const char *data) { send_usart(data, strlen(data)); }
- void send_usart(const char *data, size_t count) {
- auto end = data + count;
- while (data != end) {
- while (!(UCSR0A & (1 << UDRE0)))
- ;
- UDR0 = static_cast<uint8_t>(*data++);
- }
- }
|