#![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());
}
}