avr-oxide 0.4.1

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 ATmega4809

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

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

// 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),

  ProxyPin::for_port_and_pin(3, 0),
  ProxyPin::for_port_and_pin(3, 1),
  ProxyPin::for_port_and_pin(3, 2),
  ProxyPin::for_port_and_pin(3, 3),
  ProxyPin::for_port_and_pin(3, 4),
  ProxyPin::for_port_and_pin(3, 5),
  ProxyPin::for_port_and_pin(3, 6),
  ProxyPin::for_port_and_pin(3, 7),

  ProxyPin::for_port_and_pin(4, 0),
  ProxyPin::for_port_and_pin(4, 1),
  ProxyPin::for_port_and_pin(4, 2),
  ProxyPin::for_port_and_pin(4, 3),
  ProxyPin::for_port_and_pin(4, 4),
  ProxyPin::for_port_and_pin(4, 5),
  ProxyPin::for_port_and_pin(4, 6),
  ProxyPin::for_port_and_pin(4, 7),

  ProxyPin::for_port_and_pin(5, 0),
  ProxyPin::for_port_and_pin(5, 1),
  ProxyPin::for_port_and_pin(5, 2),
  ProxyPin::for_port_and_pin(5, 3),
  ProxyPin::for_port_and_pin(5, 4),
  ProxyPin::for_port_and_pin(5, 5),
  ProxyPin::for_port_and_pin(5, 6),
  ProxyPin::for_port_and_pin(5, 7),
];
impl PinToPort for ProxyPin {
  fn get_port(&self) -> &'static mut dyn AtmelPortControl {
    match self.port_number() {
      0 => porta::instance(),
      1 => portb::instance(),
      2 => portc::instance(),
      3 => portd::instance(),
      4 => porte::instance(),
      5 => portf::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::PortA(self.pin_number()),
      1 => PinIdentity::PortB(self.pin_number()),
      2 => PinIdentity::PortC(self.pin_number()),
      3 => PinIdentity::PortD(self.pin_number()),
      4 => PinIdentity::PortE(self.pin_number()),
      5 => PinIdentity::PortF(self.pin_number()),
      _ => avr_oxide::oserror::halt(avr_oxide::oserror::OsError::InternalError)
    }
  }
}

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

  atmel_port_tpl!(super::super::ADDR_PORTA,
    avr_oxide::hal::generic::port::base::zeroseries::PortRegisterBlock,
    0, super::PIN_PROXIES, "porta_port");
}
pub mod portb {
  use avr_oxide::{atmel_port_tpl};

  atmel_port_tpl!(super::super::ADDR_PORTB,
    avr_oxide::hal::generic::port::base::zeroseries::PortRegisterBlock,
    1, super::PIN_PROXIES, "portb_port");
}
pub mod portc {
  use avr_oxide::{atmel_port_tpl};

  atmel_port_tpl!(super::super::ADDR_PORTC,
    avr_oxide::hal::generic::port::base::zeroseries::PortRegisterBlock,
    2, super::PIN_PROXIES, "portc_port");
}
pub mod portd {
  use avr_oxide::{atmel_port_tpl};

  atmel_port_tpl!(super::super::ADDR_PORTD,
    avr_oxide::hal::generic::port::base::zeroseries::PortRegisterBlock,
    3, super::PIN_PROXIES, "portd_port");
}
pub mod porte {
  use avr_oxide::{atmel_port_tpl};

  atmel_port_tpl!(super::super::ADDR_PORTE,
    avr_oxide::hal::generic::port::base::zeroseries::PortRegisterBlock,
    4, super::PIN_PROXIES, "porte_port");
}
pub mod portf {
  use avr_oxide::{atmel_port_tpl};

  atmel_port_tpl!(super::super::ADDR_PORTF,
    avr_oxide::hal::generic::port::base::zeroseries::PortRegisterBlock,
    5, super::PIN_PROXIES, "portf_port");
}