arduino-tnc

git clone https://git.bradleygannon.com/arduino-tnc.git
Log | Files | Refs

main.rs (5551B)


      1 #![no_std]
      2 #![no_main]
      3 #![feature(abi_avr_interrupt)]
      4 
      5 mod kiss;
      6 mod rx;
      7 mod tx;
      8 
      9 use core::cell::RefCell;
     10 use core::hint::spin_loop;
     11 
     12 use arduino_hal::clock::MHz16;
     13 use arduino_hal::hal::usart::{Event, Usart0};
     14 use arduino_hal::{pac, Adc};
     15 use avr_device::generic::Periph;
     16 use avr_device::interrupt::{self, Mutex};
     17 use kiss::{KissAction, KissTncState};
     18 use panic_halt as _;
     19 use rx::Receiver;
     20 use tx::Transmitter;
     21 
     22 type TC0 = Periph<pac::tc0::RegisterBlock, 53>;
     23 type TC1 = Periph<pac::tc1::RegisterBlock, 54>;
     24 
     25 struct Tnc {
     26     state: TncState,
     27     serial: Option<Usart0<MHz16>>,
     28     receiver: Receiver,
     29     transmitter: Transmitter,
     30     kiss_state: KissTncState,
     31     sample_timer: Option<TC0>,
     32     symbol_timer: Option<TC1>,
     33 }
     34 
     35 impl Tnc {
     36     // 52 * 8 = 416 cycles; at 16 MHz this gives a period of 26 µs (about 38460 Hz)
     37     const SAMPLE_TIMER_COMPARE: u8 = 52;
     38     // this should theoretically be 13_333 cycles, but in practice we have to go a little faster to
     39     // account for overhead; this value seems to work well
     40     const SYMBOL_TIMER_COMPARE: u16 = 13_300;
     41 
     42     const fn default() -> Tnc {
     43         Tnc {
     44             state: TncState::Receiving,
     45             serial: None,
     46             receiver: Receiver::default(),
     47             transmitter: Transmitter::default(),
     48             kiss_state: KissTncState::Idle,
     49             sample_timer: None,
     50             symbol_timer: None,
     51         }
     52     }
     53     pub(crate) fn handle_usart_byte(&mut self, byte: u8) {
     54         if let Some(action) = self.kiss_state.update(byte) {
     55             match action {
     56                 KissAction::PushTx(b) => {
     57                     let _ = self.transmitter.push_message_byte(b);
     58                 }
     59                 KissAction::ClearTx => self.transmitter.clear_message(),
     60                 KissAction::SendTx => {
     61                     if self.transmitter.has_pending_bytes() {
     62                         self.state = TncState::Transmitting;
     63                         self.transmitter.start();
     64                     }
     65                 }
     66                 KissAction::_SetTxDelay { .. } => todo!(),
     67                 KissAction::_SetPersistence { .. } => todo!(),
     68                 KissAction::_SetSlotTime { .. } => todo!(),
     69                 KissAction::_SetTxTail { .. } => todo!(),
     70                 KissAction::_SetFullDuplex { .. } => todo!(),
     71                 KissAction::_SetHardware { .. } => todo!(),
     72                 KissAction::_Return => todo!(),
     73             }
     74         };
     75     }
     76 }
     77 
     78 enum TncState {
     79     Receiving,
     80     Transmitting,
     81 }
     82 
     83 static TNC: Mutex<RefCell<Tnc>> = Mutex::new(RefCell::new(Tnc::default()));
     84 
     85 #[avr_device::interrupt(atmega328p)]
     86 fn TIMER0_COMPA() {
     87     interrupt::free(|cs| {
     88         let mut tnc = TNC.borrow(cs).borrow_mut();
     89         match tnc.state {
     90             TncState::Receiving => {
     91                 if tnc.receiver.sample_update() {
     92                     if let Some(ref mut symbol_timer) = tnc.symbol_timer {
     93                         symbol_timer
     94                             .tcnt1()
     95                             .write(|w| w.set(Tnc::SYMBOL_TIMER_COMPARE / 2));
     96                     }
     97                 }
     98                 if let Some(byte) = tnc.receiver.get_output() {
     99                     if let Some(ref mut serial) = tnc.serial {
    100                         let _ = ufmt::uwriteln!(serial, "0x{:02x}", byte);
    101                     }
    102                 }
    103             }
    104             TncState::Transmitting => {
    105                 tnc.transmitter.sample_update();
    106                 if tnc.transmitter.is_done() {
    107                     tnc.state = TncState::Receiving;
    108                 }
    109             }
    110         }
    111     });
    112 }
    113 
    114 #[avr_device::interrupt(atmega328p)]
    115 fn TIMER1_COMPA() {
    116     interrupt::free(|cs| {
    117         let mut tnc = TNC.borrow(cs).borrow_mut();
    118         if let TncState::Transmitting = tnc.state {
    119             tnc.transmitter.symbol_update();
    120         }
    121     });
    122 }
    123 
    124 #[avr_device::interrupt(atmega328p)]
    125 fn USART_RX() {
    126     interrupt::free(|cs| {
    127         let mut tnc = TNC.borrow(cs).borrow_mut();
    128         if let Some(ref mut serial) = tnc.serial {
    129             let byte = serial.read_byte();
    130             tnc.handle_usart_byte(byte);
    131         }
    132     });
    133 }
    134 
    135 #[arduino_hal::entry]
    136 fn main() -> ! {
    137     let dp = arduino_hal::Peripherals::take().unwrap();
    138     let pins = arduino_hal::pins!(dp);
    139 
    140     let mut serial = arduino_hal::default_serial!(dp, pins, 115200);
    141     serial.listen(Event::RxComplete);
    142 
    143     let sample_timer = dp.TC0;
    144     sample_timer.tccr0a().write(|w| w.wgm0().ctc());
    145     sample_timer.tccr0b().write(|w| w.cs0().prescale_8());
    146     sample_timer
    147         .ocr0a()
    148         .write(|w| w.set(Tnc::SAMPLE_TIMER_COMPARE));
    149     sample_timer.timsk0().write(|w| w.ocie0a().set_bit());
    150 
    151     let symbol_timer = dp.TC1;
    152     symbol_timer
    153         .tccr1b()
    154         .write(|w| w.wgm1().set(0b01).cs1().direct());
    155     symbol_timer
    156         .ocr1a()
    157         .write(|w| w.set(Tnc::SYMBOL_TIMER_COMPARE));
    158     symbol_timer.timsk1().write(|w| w.ocie1a().set_bit());
    159 
    160     interrupt::free(|cs| {
    161         let mut tnc = TNC.borrow(cs).borrow_mut();
    162         tnc.serial = Some(serial);
    163         tnc.sample_timer = Some(sample_timer);
    164         tnc.symbol_timer = Some(symbol_timer);
    165         tnc.receiver
    166             .initialize(Adc::new(dp.ADC, Default::default()), pins.a0);
    167         tnc.transmitter.initialize(
    168             pins.d2.into_output(),
    169             pins.d3.into_output(),
    170             pins.d4.into_output(),
    171             pins.d5.into_output(),
    172             pins.d6.into_output(),
    173         );
    174     });
    175 
    176     unsafe { avr_device::interrupt::enable() };
    177 
    178     loop {
    179         spin_loop();
    180     }
    181 }