forked from Rahix/avr-hal
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathusart_spi.rs
More file actions
95 lines (80 loc) · 4.21 KB
/
Copy pathusart_spi.rs
File metadata and controls
95 lines (80 loc) · 4.21 KB
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
//! MSPIM Implimentation
use crate::spi;
// This module just impliments a macro for SpiOps, since underlyingly, the Spi type can still be used since it just needs SpiOps
pub type UsartSpi<H, USART, SCLKPIN, MOSIPIN, MISOPIN, CSPIN> =
spi::Spi<H, USART, SCLKPIN, MOSIPIN, MISOPIN, CSPIN>;
// Impliment SpiOps trait for USART
#[macro_export]
macro_rules! add_usart_spi {
(
hal: $HAL:ty,
peripheral: $USART_SPI:ty,
register_suffix: $n:expr,
sclk: $sclkpin:ty,
mosi: $mosipin:ty,
miso: $misopin:ty,
cs: $cspin:ty,
) => {
$crate::paste::paste! {
// This is quite a messy way to get the doc string working properly... but it works!
#[doc = concat!("**Clock:** `", stringify!($sclkpin), "`<br>**MOSI:** `", stringify!($mosipin), "`<br> **MISO:** `", stringify!($misopin), "`<br> **CS:** `", stringify!($cspin), "`")]
pub type [<Usart $n Spi>] = avr_hal_generic::usart_spi::UsartSpi<$HAL, $USART_SPI, $sclkpin, $mosipin, $misopin, $cspin>;
impl $crate::spi::SpiOps<$HAL, $sclkpin, $mosipin, $misopin, $cspin> for $USART_SPI {
fn raw_setup(&mut self, settings: &crate::spi::Settings) {
use $crate::hal::spi;
// Setup control registers
// We start by setting the UBBRn to 0
self.[<ubrr $n>].write(|w| unsafe {w.bits(0)});
// We have to translate the character size register into the 2 bits which are the MSB/LSB and the phase
// 5 Bit Char = MSB and 1st
// 6 Bit Char = MSB and 2nd
// 7 Bit Char = LSB and 1st
// 8 Bit Char = LSB and 2nd
self.[<ucsr $n c>].write(|w| {
w.[<umsel $n>]().spi_master();
match settings.data_order {
crate::spi::DataOrder::MostSignificantFirst => match settings.mode.phase {
spi::Phase::CaptureOnFirstTransition => w.[<ucsz $n>]().chr5(),
spi::Phase::CaptureOnSecondTransition => w.[<ucsz $n>]().chr6(),
},
crate::spi::DataOrder::LeastSignificantFirst => match settings.mode.phase {
spi::Phase::CaptureOnFirstTransition => w.[<ucsz $n>]().chr7(),
spi::Phase::CaptureOnSecondTransition => w.[<ucsz $n>]().chr8(),
},
};
match settings.mode.polarity {
spi::Polarity::IdleLow => w.[<ucpol $n>]().clear_bit(),
spi::Polarity::IdleHigh => w.[<ucpol $n>]().set_bit(),
}
});
// Enable receiver and transmitter, and also the rec interrupt.
self.[<ucsr $n b>].write(|w| w
.[<txen $n>]().set_bit()
.[<rxen $n>]().set_bit()
.[<rxcie $n>]().set_bit()
);
// Set the baudrate of the UBRRn, idk what it should be set to, so for now, it'll be set to 0
self.[<ubrr $n>].write(|w| unsafe{w.bits(0)});
}
fn raw_release(&mut self) {
// Probably a better way to "release" the SPI interface, but from the datasheet, this is what they suggest, so ig it works
self.[<ucsr $n c>].write(|w| w.[<umsel $n>]().usart_async());
}
fn raw_check_iflag(&self) -> bool {
self.[<ucsr $n a>].read().[<rxc $n>]().bit_is_set()
}
fn raw_read(&self) -> u8 {
self.[<udr $n>].read().bits()
}
fn raw_write(&mut self, byte: u8) {
self.[<udr $n>].write(|w| unsafe { w.bits(byte) });
}
fn raw_transaction(&mut self, byte: u8) -> u8 {
self.raw_write(byte);
while !self.raw_check_iflag() {}
self.raw_read()
}
}
}
};
}