1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/* 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");
}