1#![no_std]
19
20use core::ptr::{read_volatile, write_volatile};
21
22pub enum Pin {
23 P0,
24 P1,
25 P2,
26 P3,
27 P4,
28 P5,
29 P6,
30 P7,
31}
32
33impl Pin {
34 pub const fn index(self) -> u8 {
36 match self {
37 Pin::P0 => 0,
38 Pin::P1 => 1,
39 Pin::P2 => 2,
40 Pin::P3 => 3,
41 Pin::P4 => 4,
42 Pin::P5 => 5,
43 Pin::P6 => 6,
44 Pin::P7 => 7,
45 }
46 }
47
48 pub const fn from_u8(value: u8) -> Option<Self> {
49 match value {
50 0 => Some(Pin::P0),
51 1 => Some(Pin::P1),
52 2 => Some(Pin::P2),
53 3 => Some(Pin::P3),
54 4 => Some(Pin::P4),
55 5 => Some(Pin::P5),
56 6 => Some(Pin::P6),
57 7 => Some(Pin::P7),
58 _ => None,
59 }
60 }
61}
62
63pub struct Port {
64 ddr: *mut u8,
65 port: *mut u8,
66 pin: *const u8,
67}
68
69impl Port {
70 pub unsafe fn new(ddr_addr: u16, port_addr: u16, pin_addr: u16) -> Self {
76 Port {
77 ddr: ddr_addr as *mut u8,
78 port: port_addr as *mut u8,
79 pin: pin_addr as *const u8,
80 }
81 }
82
83 pub fn set_pin_mode(&mut self, pin: Pin, is_output: bool) {
88 unsafe {
89 let current = read_volatile(self.ddr);
90 let new = if is_output {
91 set_bit(current, pin)
92 } else {
93 clear_bit(current, pin)
94 };
95 write_volatile(self.ddr, new);
96 }
97 }
98
99 pub fn set_pin_state(&mut self, pin: Pin, is_high: bool) {
104 unsafe {
105 let current = read_volatile(self.port);
106 let new = if is_high {
107 set_bit(current, pin)
108 } else {
109 clear_bit(current, pin)
110 };
111 write_volatile(self.port, new);
112 }
113 }
114
115 pub fn read_pin(&self, pin: Pin) -> bool {
117 unsafe {
118 let value = read_volatile(self.pin);
119 read_bit(value, pin)
120 }
121 }
122
123 pub fn read_ddr(&self) -> u8 {
125 unsafe { read_volatile(self.ddr) }
126 }
127
128 pub fn read_port(&self) -> u8 {
130 unsafe { read_volatile(self.port) }
131 }
132
133 pub fn read_pin_reg(&self) -> u8 {
135 unsafe { read_volatile(self.pin) }
136 }
137}
138
139#[inline]
140fn set_bit(value: u8, pin: Pin) -> u8 {
141 value | (1 << pin.index())
142}
143
144#[inline]
145fn clear_bit(value: u8, pin: Pin) -> u8 {
146 value & !(1 << pin.index())
147}
148
149#[inline]
150fn read_bit(value: u8, pin: Pin) -> bool {
151 (value & (1 << pin.index())) != 0
152}
153
154pub mod portb {
155 use super::Port;
156
157 const DDRB: u16 = 0x24;
158 const PORTB: u16 = 0x25;
159 const PINB: u16 = 0x23;
160
161 pub fn init() -> Port {
162 unsafe { Port::new(DDRB, PORTB, PINB) }
163 }
164}
165
166pub mod portc {
167 use super::Port;
168
169 const DDRC: u16 = 0x27;
170 const PORTC: u16 = 0x28;
171 const PINC: u16 = 0x26;
172
173 pub fn init() -> Port {
174 unsafe { Port::new(DDRC, PORTC, PINC) }
175 }
176}
177
178pub mod portd {
179 use super::Port;
180
181 const DDRD: u16 = 0x2a;
182 const PORTD: u16 = 0x2b;
183 const PIND: u16 = 0x29;
184
185 pub fn init() -> Port {
186 unsafe { Port::new(DDRD, PORTD, PIND) }
187 }
188}