#![no_std] #![no_main] #![allow(deprecated)] use core::convert::Infallible; use core::marker::PhantomData; use core::ptr; use bsp::hal; use bsp::hal::eic::pin::Sense; use bsp::hal::eic::EIC; use bsp::hal::gpio::v2::{DynPinId, PA06, PA10}; use bsp::hal::gpio::{Output, PushPull}; use bsp::hal::time::Hertz; use bsp::hal::timer::TimerCounter3; use panic_halt as _; use trinket_m0 as bsp; use bsp::entry; use hal::clock::GenericClockController; use hal::pac::{interrupt, CorePeripherals, Peripherals}; use hal::prelude::*; use cortex_m::peripheral::NVIC; use infrared::protocol::Nec; use infrared::Receiver; use embedded_hal::digital::v2::InputPin; use hal::gpio::v2::Pin; use hal::gpio::v2::PinId; struct IrRemotePin

where P: PinId { regs: *const bsp::hal::pac::port::RegisterBlock, id: PhantomData

} impl

IrRemotePin

where P: PinId { pub unsafe fn new(regs: *const bsp::hal::pac::port::RegisterBlock) -> Self { Self { regs, id: PhantomData } } fn id(&self) -> DynPinId { P::DYN } } impl

InputPin for IrRemotePin

where P: PinId { type Error = Infallible; fn is_high(&self) -> Result { let r = unsafe { &*self.regs }; Ok((r.in0.read().bits() & (1 << self.id().num)) != 0) } fn is_low(&self) -> Result { let r = unsafe { &*self.regs }; Ok((r.in0.read().bits() & (1 << self.id().num)) == 0) } } const TIMER_FREQ: Hertz = Hertz(40000); static mut RECEIVER: Option>> = None; static mut RED_LED: Option>> = None; #[entry] fn main() -> ! { let mut peripherals = Peripherals::take().unwrap(); let mut core = CorePeripherals::take().unwrap(); let mut clocks = GenericClockController::with_internal_32kosc( peripherals.GCLK, &mut peripherals.PM, &mut peripherals.SYSCTRL, &mut peripherals.NVMCTRL, ); let mut pins = bsp::Pins::new(peripherals.PORT); let gclk = clocks.gclk0(); let timer_clk = clocks.tcc2_tc3(&gclk).unwrap(); let mut timer = TimerCounter3::tc3_(&timer_clk, peripherals.TC3, &mut peripherals.PM); timer.start(TIMER_FREQ); timer.enable_interrupt(); let eic_clock = clocks.eic(&gclk).unwrap(); let mut eic = EIC::init(&mut peripherals.PM, eic_clock, peripherals.EIC); let mut inp = pins.d4.into_floating_ei(&mut pins.port); inp.sense(&mut eic, Sense::BOTH); inp.enable_interrupt(&mut eic); drop(inp); // SAFETY: The Pin that we're trying to reconjure should be out of scope. let ir_pin = unsafe { IrRemotePin::::new(bsp::pac::PORT::ptr()) }; let receiver = Receiver::::with_pin(TIMER_FREQ.0, ir_pin); let red_led = pins.d13.into_open_drain_output(&mut pins.port).into(); // SAFETY: These are mimicking Sends of types that impl Send. unsafe { *ptr::addr_of_mut!(RED_LED) = Some(red_led); *ptr::addr_of_mut!(RECEIVER) = Some(receiver); } // SAFETY: No interrupts were enabled before this point. unsafe { core.NVIC.set_priority(interrupt::EIC, 2); NVIC::unmask(interrupt::EIC); } loop { } } #[interrupt] fn EIC() { // Accessing registers from interrupts context is safe let eic = unsafe { &*bsp::pac::EIC::ptr() }; // check INTFLAG to validate interrupt source if more than one is in use if eic.intflag.read().extint6().bit_is_set() { // toggle LED unsafe { RED_LED.as_mut().map(|l| l.toggle()) }; // The interrupt request remains active until the interrupt flag is cleared, // the interrupt is disabled or the peripheral is reset. An interrupt flag is // cleared by writing a one to the corresponding bit in the INTFLAG register. // read more: SAM-D21DA1-Family-Data-Sheet-DS40001882G.pdf # 16.6.5 Interrupts eic.intflag.modify(|_, w| w.extint6().set_bit()); } }