use crate::delay::delay_ms;
use bit_field::BitField;
use core::ptr::write_volatile;
use core::{f64, u32, u8};
use volatile::Volatile;
use crate::atmega328p::hal::interrupts;
use crate::atmega328p::hal::port;
use crate::atmega328p::hal::power;
const USART0_XCK: u8 = 4;
const F_OSC: f64 = 1.0000;
const MULTIPLY: f64 = 1000000.00;
#[derive(Clone, Copy)]
pub enum UsartNum {
Usart0,
}
#[derive(Clone, Copy)]
pub enum UsartModes {
Normasync,
Douasync,
Mastersync,
Slavesync,
}
#[derive(Clone, Copy)]
pub enum UsartParity {
No,
Even,
Odd,
}
#[derive(Clone, Copy)]
pub enum UsartDataSize {
Five,
Six,
Seven,
Eight,
Nine,
}
#[derive(Clone, Copy)]
pub enum UsartStop {
One,
Two,
}
#[derive(Clone, Copy)]
pub enum UsartPolarity {
Outputrise,
Inputrise,
}
#[repr(C, packed)]
pub struct Usart {
pub ucsra: Volatile<u8>,
pub ucsrb: Volatile<u8>,
pub ucsrc: Volatile<u8>,
_pad: u8, pub ubrrl: Volatile<u8>,
pub ubrrh: Volatile<u8>,
pub udr: Volatile<u8>,
}
impl Usart {
pub unsafe fn new(num: UsartNum) -> &'static mut Usart {
match num {
UsartNum::Usart0 => &mut *(0xC0 as *mut Usart),
}
}
}
impl Usart {
fn disable(&mut self) {
unsafe {
interrupts::Interrupt::disable(&mut interrupts::Interrupt::new());
}
}
fn enable(&mut self) {
unsafe {
interrupts::Interrupt::enable(&mut interrupts::Interrupt::new());
}
}
fn get_num(&mut self) -> UsartNum {
let address = (self as *const Usart) as u8; match address {
0xC0 => UsartNum::Usart0,
_ => unreachable!(),
}
}
fn get_port_xck(&mut self) -> (&mut port::Port, u8) {
let num: UsartNum = self.get_num();
match num {
UsartNum::Usart0 => (port::Port::new(port::PortName::D), USART0_XCK),
}
}
fn get_mode(&mut self) -> bool {
let mut src = self.ucsrc.read();
src = src & (1 << 6);
if src == 0 {
return false;
} else {
return true;
}
}
pub fn set_polarity(&mut self, mode: UsartPolarity) {
if self.get_mode() == false {
self.ucsrc.update(|src| {
src.set_bit(0, false);
});
} else {
match mode {
UsartPolarity::Outputrise => {
self.ucsrc.update(|src| {
src.set_bit(0, false);
});
}
UsartPolarity::Inputrise => {
self.ucsrc.update(|src| {
src.set_bit(0, true);
});
}
}
}
}
pub fn mode_select(&mut self, mode: UsartModes) {
match mode {
UsartModes::Normasync | UsartModes::Douasync => {
self.ucsrc.update( |src| {
src.set_bit(6,false);
src.set_bit(7,false);
});
},
UsartModes::Mastersync
| UsartModes::Slavesync => { self.ucsrc.update( |src| {
src.set_bit(6,true);
src.set_bit(7,false);
});
self.ucsra.update( |sra| {
sra.set_bit(1,false);
});
},
}
match mode {
UsartModes::Normasync => {
self.ucsra.update(|sra| {
sra.set_bit(1, false);
});
}
UsartModes::Douasync => {
self.ucsra.update(|sra| {
sra.set_bit(1, true);
});
}
UsartModes::Mastersync => {
let (port, xck) = self.get_port_xck();
unsafe {
write_volatile(&mut port.ddr, port.ddr | 1 << xck);
}
}
UsartModes::Slavesync => {
let (port, xck) = self.get_port_xck();
unsafe {
write_volatile(&mut port.ddr, port.ddr & !(1 << xck));
}
}
}
}
pub fn set_power(&mut self, num: UsartNum) {
let pow: &mut power::Power;
pow = power::Power::new();
match num {
UsartNum::Usart0 => unsafe {
write_volatile(&mut pow.prr, pow.prr & !(1 << 1));
},
}
}
fn check_ongoing(&self) -> bool {
let ucsra = self.ucsra.read();
if ucsra.get_bit(6) == true && ucsra.get_bit(7) == false {
true
} else {
false
}
}
fn set_clock(&mut self, baud: i64, mode: UsartModes) {
let ubrr: u32;
match mode {
UsartModes::Normasync => {
ubrr = (((F_OSC * MULTIPLY) / (16.00 * baud as f64)) - 1.00) as u32;
}
UsartModes::Douasync => {
ubrr = (((F_OSC * MULTIPLY) / (8.00 * baud as f64)) - 1.00) as u32;
}
UsartModes::Mastersync => {
ubrr = (((F_OSC * MULTIPLY) / (2.00 * baud as f64)) - 1.00) as u32;
}
_ => unreachable!(),
}
self.ubrrl.update(|ubrrl| {
for i in 0..8 {
ubrrl.set_bit(i, ubrr.get_bit(i));
}
});
self.ubrrh.update(|ubrrh| {
for i in 0..4 {
ubrrh.set_bit(i, ubrr.get_bit(i + 8));
}
});
}
fn set_size(&mut self, size: UsartDataSize) {
match size {
UsartDataSize::Five
| UsartDataSize::Six
| UsartDataSize::Seven
| UsartDataSize::Eight => {
self.ucsrb.update(|srb| {
srb.set_bit(2, false);
});
}
UsartDataSize::Nine => {
self.ucsrb.update(|srb| {
srb.set_bit(2, true);
});
}
}
match size {
UsartDataSize::Five | UsartDataSize::Six => {
self.ucsrc.update(|src| {
src.set_bit(2, false);
});
}
UsartDataSize::Nine | UsartDataSize::Seven | UsartDataSize::Eight => {
self.ucsrc.update(|src| {
src.set_bit(2, true);
});
}
}
match size {
UsartDataSize::Five | UsartDataSize::Seven => {
self.ucsrc.update(|src| {
src.set_bit(1, false);
});
}
UsartDataSize::Nine | UsartDataSize::Six | UsartDataSize::Eight => {
self.ucsrc.update(|src| {
src.set_bit(1, true);
});
}
}
}
fn set_parity(&mut self, parity: UsartParity) {
match parity {
UsartParity::No => {
self.ucsrc.update(|src| {
src.set_bit(4, false);
src.set_bit(5, false);
});
}
UsartParity::Even => {
self.ucsrc.update(|src| {
src.set_bit(4, false);
src.set_bit(5, true);
});
}
UsartParity::Odd => {
self.ucsrc.update(|src| {
src.set_bit(4, true);
src.set_bit(5, true);
});
}
}
}
fn set_stop(&mut self, stop: UsartStop) {
match stop {
UsartStop::One => {
self.ucsrc.update(|src| {
src.set_bit(3, false);
});
}
UsartStop::Two => {
self.ucsrc.update(|src| {
src.set_bit(3, true);
});
}
}
}
fn set_frame(&mut self, stop: UsartStop, size: UsartDataSize, parity: UsartParity) {
self.set_size(size);
self.set_parity(parity);
self.set_stop(stop);
}
pub fn initialize(
&mut self,
mode: UsartModes,
baud: i64,
stop: UsartStop,
size: UsartDataSize,
parity: UsartParity,
) {
let mut i: i32 = 10;
while self.check_ongoing() == false {
if i != 0 {
delay_ms(1000);
i = i - 1;
} else {
unreachable!()
}
}
self.disable(); let num: UsartNum = self.get_num();
self.set_power(num);
self.mode_select(mode);
match mode {
UsartModes::Slavesync => {}
_ => {
self.set_clock(baud, mode);
}
}
self.set_frame(stop, size, parity);
self.enable(); }
}