extern crate proc_macro;
extern crate quote;
extern crate syn;
use proc_macro::TokenStream;
use quote::{format_ident, quote};
use syn::parse_macro_input;
#[proc_macro]
pub fn fgpio(item: TokenStream) -> TokenStream {
let name = parse_macro_input!(item as syn::Ident).to_string();
let name_uc = name.to_uppercase();
let fgpio = format_ident!("fgpio{}", name);
let fgpio_uc = format_ident!("FGPIO{}", name_uc);
let port = format_ident!("PORT{}", name_uc);
let pin_fields = (0..32 as usize).map(|i| {
let pxi = format_ident!("p{}{}", name, i);
let pxi_uc = format_ident!("P{}{}", name_uc, i);
quote! { pub #pxi: #pxi_uc<IN> }
});
let pin_init = (0..32 as usize).map(|i| {
let pxi = format_ident!("p{}{}", name, i);
let pxi_uc = format_ident!("P{}{}", name_uc, i);
quote! { #pxi: #pxi_uc::<IN>{_mode: PhantomData} }
});
let pin = (0..32 as usize).map(|i| {
let pxi_uc = format_ident!("P{}{}", name_uc, i);
let pcr = format_ident!("pcr{}", i);
quote! {
pub struct #pxi_uc<MODE> {
_mode: PhantomData<MODE>
}
impl<MODE> #pxi_uc<MODE> {
pub fn enable(&self) {
unsafe { &(*#port::ptr()) }.#pcr.write(|w| w.mux()._001());
}
pub fn into_input(self) -> #pxi_uc<IN> {
self.regblock().pddr.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << #i)) });
#pxi_uc{_mode: PhantomData}
}
pub fn into_output(self) -> #pxi_uc<OUT> {
self.regblock().pddr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << #i)) });
#pxi_uc{_mode: PhantomData}
}
fn regblock(&self) -> &#fgpio::RegisterBlock {
unsafe { &(*#fgpio_uc::ptr()) }
}
fn value(&self) -> u32 {
self.regblock().pdir.read().pdi().bits() & (1 << #i)
}
}
impl InputPin for #pxi_uc<IN> {
type Error = Void;
fn is_high(&self) -> Result<bool, Self::Error> {
Ok(self.value() != 0)
}
fn is_low(&self) -> Result<bool, Self::Error> {
Ok(self.value() == 0)
}
}
impl OutputPin for #pxi_uc<OUT> {
type Error = Void;
fn set_low(&mut self) -> Result<(), Self::Error> {
self.regblock().pcor.write(|w| unsafe { w.bits(1<<#i) });
Ok(())
}
fn set_high(&mut self) -> Result<(), Self::Error> {
self.regblock().psor.write(|w| unsafe { w.bits(1<<#i) });
Ok(())
}
}
impl #pxi_uc<OUT> {
pub fn toggle(&mut self) {
self.regblock().ptor.write(|w| unsafe { w.bits(1<<#i) });
}
}
}
});
let result = quote! {
pub mod #fgpio {
use core::marker::PhantomData;
use embedded_hal::digital::v2::{InputPin, OutputPin};
use void::Void;
use crate::dev::{#fgpio_uc, #port, #fgpio};
use super::{FgpioExt, IN, OUT};
pub struct Parts {
pub #fgpio: #fgpio_uc,
#(#pin_fields,)*
}
impl Parts {
pub fn into_fgpio(self) -> #fgpio_uc {
self.#fgpio
}
}
impl FgpioExt for #fgpio_uc {
type Parts = Parts;
fn split(self) -> Parts {
Parts {
#fgpio: self,
#(#pin_init,)*
}
}
}
#(#pin)*
}
};
TokenStream::from(result)
}