1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
use std::{cell::RefCell, thread::sleep, time::Duration};

use common_infrastructure::hals::{TrainHal,GenericHal};
use common_infrastructure::messages::{TrainMessage,MasterMessage};
use common_infrastructure::Position;
use anyhow::Result;
use esp_idf_svc::hal;
use esp_idf_svc::hal::task::watchdog::{WatchdogSubscription, TWDTDriver};
use hal::task::watchdog::TWDTConfig;
use enumset::enum_set;
use esp_idf_svc::wifi::{BlockingWifi, EspWifi};
use esp_idf_svc::eventloop::EspSystemEventLoop;
use esp_idf_svc::nvs::EspDefaultNvsPartition;
use hal::peripherals::Peripherals;


mod message_sender;
use message_sender::MessageSender;
mod message_receiver;
use message_receiver::MessageReceiver;
mod nfc_reader;
use nfc_reader::NfcReader;
mod speed_setter;
use speed_setter::MotorDriver;
mod wifi_configuration;
use wifi_configuration::WiFiManager;


struct EspController<'a>{
    nfc_reader: NfcReader<'a>,
    motor_driver: MotorDriver<'a>,
    message_sender: MessageSender,
    message_receiver: MessageReceiver<'a,TrainMessage>,
    #[allow(dead_code)]
    wifi_manager: WiFiManager,
    watchdog_driver: TWDTDriver<'a>,
}

impl EspController<'_> {    
    fn new() -> Result<Self> {    
        let peripherals = Peripherals::take()?;


        let config = TWDTConfig {
            duration: Duration::from_secs(1000000000),
            panic_on_trigger: true,
            subscribed_idle_tasks: enum_set!(hal::cpu::Core::Core0)
        };
        let mut watchdog_driver = hal::task::watchdog::TWDTDriver::new(
            peripherals.twdt,
            &config,
        )?;
    
        let sys_loop = EspSystemEventLoop::take()?;
        let nvs = EspDefaultNvsPartition::take()?;
        let wifi = BlockingWifi::wrap(
            EspWifi::new(peripherals.modem, sys_loop.clone(), Some(nvs))?,
            sys_loop,
        )?;
        let mut wifi_manager = WiFiManager::new(wifi);
        wifi_manager.connect_wifi_default()?;


        let spi = peripherals.spi2;
        let sclk = peripherals.pins.gpio15;
        let serial_in = peripherals.pins.gpio16;
        let serial_out = peripherals.pins.gpio17;
        let cs_1 = peripherals.pins.gpio18;
        let nfc_reader = NfcReader::new(spi, sclk, serial_in, serial_out, cs_1)?;


        let timer = peripherals.ledc.timer0;
        let pwm_pin = peripherals.pins.gpio25;
        let forward_pin = peripherals.pins.gpio26;
        let backward_pin = peripherals.pins.gpio27;
        let channel = peripherals.ledc.channel0;
        let motor_driver = MotorDriver::new(timer, pwm_pin, forward_pin, backward_pin, channel)?;


        let message_sender = MessageSender::new();


        let message_receiver = MessageReceiver::<TrainMessage>::new("/train_message")?;

        return Ok(Self{motor_driver,message_receiver,message_sender,nfc_reader,wifi_manager,watchdog_driver});
    }

}

pub struct EspTrainHal<'a>{
    controller: RefCell<EspController<'a>>
}


impl GenericHal for EspTrainHal<'_> {
    fn new() -> Result<Self> {
        Ok(Self{
          controller: EspController::new()?.into()
        })
    }
    fn sleep_for_ms(&self, ms: u32) {
        sleep(Duration::from_millis(ms as u64))
    }
}

impl TrainHal for EspTrainHal<'_> {
    fn get_message(&self) -> Result<Option<TrainMessage>> {
        self.controller.borrow_mut().message_receiver.get_message()
    }
    fn read_position(&self) -> Result<Option<common_infrastructure::Position>> {
        let tag = self.controller.borrow_mut().nfc_reader.try_get_tag();
        let tag = match tag{
            Some(t) => t,
            None => return Ok(None)
        };
        let tag = Position::from_id(tag)?;
        
        return Ok(Some(tag))
    }
    fn send_message_to_master(&self, message: MasterMessage) -> Result<()> {
        self.controller.borrow().message_sender.send_message(message)
    }
    fn set_speed(&self, speed: i8) -> Result<()> {
        self.controller.borrow_mut().motor_driver.set_speed(speed)
    }
}