avr-oxide 0.0.1

An extremely simply Rusty operating system for AVR microcontrollers
/* ports.rs
 *
 * Developed by Tim Walls <tim.walls@snowgoons.com>
 * Copyright (c) All Rights Reserved, Tim Walls
 */
//! Generic I/O ports provided by the AVR microcontroller.

// Imports ===================================================================


// Declarations ==============================================================
#[derive(Clone,Copy,PartialEq,Eq)]
pub enum PinMode {
  Output,
  InputPullup,
  InputFloating
}

pub trait Pin {
  fn set_mode(&self, mode: PinMode);

  fn toggle(&self);

  fn set_on(&self);

  fn set_off(&self);
}

pub trait Port
{
}

// Code ======================================================================
pub mod base {
  pub trait AtmelPortControl {
    fn set_as_output(&self,p: u8);
    fn set_as_input(&self, p: u8);
    fn set_high(&self, p: u8);
    fn set_low(&self, p: u8);
    fn toggle(&self, p: u8);
  }

  #[macro_export]
  macro_rules! atmel_port_tpl {
    ($hw_type:ty, $ref:expr, $ddr_set:ident, $ddr_clr:ident, $port_set:ident, $port_clr:ident, $port_tgl:ident) => {
      extern crate avr_device_snowgoons as avr_device;

      use crate::hal::generic::port::{PinMode,Pin,Port};
      use crate::hal::generic::port::base::AtmelPortControl;

      pub type PortImpl = $hw_type;
      pub type PinImpl<const N: u8> = AtmelPin<N>;

      pub struct AtmelPin<const N: u8> {
      }

      impl<const N: u8> Pin for AtmelPin<N> {
        #[inline(always)]
        fn set_mode(&self, mode: PinMode) {
          unsafe {
            match mode {
              PinMode::Output => {
                (*$ref).$ddr_set.write(|w| w.bits(0x01 << N));
              },
              PinMode::InputPullup => {
                (*$ref).$ddr_clr.write(|w| w.bits(0x01 << N));
                todo!("Set pullup on");
              },
              PinMode::InputFloating => {
                (*$ref).$ddr_clr.write(|w| w.bits(0x01 << N));
                todo!("Set floating on");
              }
            }
          }
        }
        #[inline(always)]
        fn toggle(&self) {
          unsafe {
            (*$ref).$port_tgl.write(|w| w.bits(0x01 << N));
          }
        }
        #[inline(always)]
        fn set_on(&self) {
          unsafe {
            (*$ref).$port_set.write(|w| w.bits(0x01 << N));
          }
        }
        #[inline(always)]
        fn set_off(&self) {
          unsafe {
            (*$ref).$port_clr.write(|w| w.bits(0x01 << N));
          }
        }
      }

      pub fn instance() -> &'static PortImpl  {
        unsafe {
          &(*$ref)
        }
      }

      impl Port for $hw_type {
      }

      impl<const N: u8> AtmelPin<N> {
        pub fn instance() -> AtmelPin<N>  {
          AtmelPin::<N> { }
        }
      }

      pub fn pin_instance<const N: u8>() -> AtmelPin<N> {
        AtmelPin::<N> { }
      }

      impl AtmelPortControl for $hw_type {
        #[inline(always)]
        fn set_as_output(&self, p: u8) {
          self.$ddr_set.write(|w| unsafe { w.bits(0x01 << p) });
        }
        #[inline(always)]
        fn set_as_input(&self, p: u8) {
          self.$ddr_clr.write(|w| unsafe { w.bits(0x01 << p) });
          todo!()
        }
        #[inline(always)]
        fn set_high(&self, p: u8) {
          self.$port_set.write(|w| unsafe { w.bits(0x01 << p) });
        }
        #[inline(always)]
        fn set_low(&self, p: u8) {
          self.$port_clr.write(|w| unsafe { w.bits(0x01 << p) });
        }
        #[inline(always)]
        fn toggle(&self, p: u8) {
          self.$port_tgl.write(|w| unsafe { w.bits(0x01 << p) });
        }
      }
    }
  }
}