avr-oxide 0.3.0

An extremely simple Rusty operating system for AVR microcontrollers
/* port.rs
 *
 * Developed by Tim Walls <tim.walls@snowgoons.com>
 * Copyright (c) All Rights Reserved, Tim Walls
 */
//! Implementation of the ports available on the ATmega328P

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


// Declarations ==============================================================


use avr_oxide::hal::generic::port::{PinIdentity, ProxyPin, PinToPort};
use avr_oxide::hal::generic::port::base::AtmelPortControl;

// Code ======================================================================
/**
 * We need 'something' to be able to pass around as a reference to a pin
 * (why not pass by copy?  Because we need sized types for dynamic resolution.)
 * So this array serves as a proxy 'device' for each pin attached to the
 * CPU.
 *
 * It uses a small amount of RAM (1 byte per pin), but I deem this an
 * acceptable use of RAM to allow us to reduce *code* size by using dynamic
 * references instead of lots of static (re)implementations.
 */
static PIN_PROXIES: [ProxyPin; avr_oxide::deviceconsts::oxide::PIN_ARRAY_SIZE] = [
  ProxyPin::for_port_and_pin(0, 0),
  ProxyPin::for_port_and_pin(0, 1),
  ProxyPin::for_port_and_pin(0, 2),
  ProxyPin::for_port_and_pin(0, 3),
  ProxyPin::for_port_and_pin(0, 4),
  ProxyPin::for_port_and_pin(0, 5),
  ProxyPin::for_port_and_pin(0, 6),
  ProxyPin::for_port_and_pin(0, 7),
  ProxyPin::for_port_and_pin(1, 0),
  ProxyPin::for_port_and_pin(1, 1),
  ProxyPin::for_port_and_pin(1, 2),
  ProxyPin::for_port_and_pin(1, 3),
  ProxyPin::for_port_and_pin(1, 4),
  ProxyPin::for_port_and_pin(1, 5),
  ProxyPin::for_port_and_pin(1, 6),
  ProxyPin::for_port_and_pin(1, 7),
  ProxyPin::for_port_and_pin(2, 0),
  ProxyPin::for_port_and_pin(2, 1),
  ProxyPin::for_port_and_pin(2, 2),
  ProxyPin::for_port_and_pin(2, 3),
  ProxyPin::for_port_and_pin(2, 4),
  ProxyPin::for_port_and_pin(2, 5),
  ProxyPin::for_port_and_pin(2, 6),
  ProxyPin::for_port_and_pin(2, 7),
];
impl PinToPort for ProxyPin {
  fn get_port(&self) -> &'static mut dyn AtmelPortControl {
    match self.port_number() {
      0 => portb::instance(),
      1 => portc::instance(),
      2 => portd::instance(),
      _ => avr_oxide::oserror::halt(avr_oxide::oserror::OsError::BadParams)
    }
  }
}
impl Into<PinIdentity> for ProxyPin {
  fn into(self) -> PinIdentity {
    match self.port_number() {
      0 => PinIdentity::PortB(self.pin_number()),
      1 => PinIdentity::PortC(self.pin_number()),
      2 => PinIdentity::PortD(self.pin_number()),
      _ => avr_oxide::oserror::halt(avr_oxide::oserror::OsError::InternalError)
    }
  }
}

pub mod portb {
  use avr_oxide::{atmel_port_tpl};

  use super::super::{ADDR_PORTB, ADDR_PCMSK0, ADDR_PCICR, ADDR_PCIFR};

  atmel_port_tpl!(ADDR_PORTB,
    avr_oxide::hal::generic::port::base::simple::AvrPortRegisterBlock<ADDR_PORTB,ADDR_PCMSK0,ADDR_PCICR,ADDR_PCIFR,0>,
      0, super::PIN_PROXIES, "pcint0");
}
pub mod portc {
  use avr_oxide::{atmel_port_tpl};

  use super::super::{ADDR_PORTC, ADDR_PCMSK1, ADDR_PCICR, ADDR_PCIFR};

  atmel_port_tpl!(ADDR_PORTC,
    avr_oxide::hal::generic::port::base::simple::AvrPortRegisterBlock<ADDR_PORTC,ADDR_PCMSK1,ADDR_PCICR,ADDR_PCIFR,1>,
      1, super::PIN_PROXIES, "pcint1");
}
pub mod portd {
  use avr_oxide::{atmel_port_tpl};

  use super::super::{ADDR_PORTD, ADDR_PCMSK2, ADDR_PCICR, ADDR_PCIFR};

  atmel_port_tpl!(ADDR_PORTD,
    avr_oxide::hal::generic::port::base::simple::AvrPortRegisterBlock<ADDR_PORTD,ADDR_PCMSK2,ADDR_PCICR,ADDR_PCIFR,2>,
      2, super::PIN_PROXIES, "pcint2");
}