use crate::atmega2560p::hal::pin::{AnalogPin, DigitalPin};
use crate::__nop;
use crate::atmega2560p::hal::power::Power;
use bit_field::BitField;
use volatile::Volatile;
#[derive(Clone, Copy)]
pub enum RefType {
DEFAULT,
INTERNAL1V1,
INTERNAL2V56,
EXTERNAL,
}
#[derive(Clone, Copy)]
pub enum TimerNo8 {
Timer0,
Timer2,
}
#[derive(Clone, Copy)]
pub enum TimerNo16 {
Timer1,
Timer3,
Timer4,
Timer5,
}
#[repr(C, packed)]
pub struct AnalogComparator {
acsr: Volatile<u8>,
}
#[repr(C, packed)]
pub struct Analog {
adcl: Volatile<u8>,
adch: Volatile<u8>,
adcsra: Volatile<u8>,
adcsrb: Volatile<u8>,
admux: Volatile<u8>,
didr2: Volatile<u8>,
didr0: Volatile<u8>,
didr1: Volatile<u8>,
}
#[repr(C, packed)]
pub struct Timer8 {
tccra: Volatile<u8>,
tccrb: Volatile<u8>,
_tcnt: Volatile<u8>,
ocra: Volatile<u8>,
ocrb: Volatile<u8>,
}
#[repr(C, packed)]
pub struct Timer16 {
tccra: Volatile<u8>,
tccrb: Volatile<u8>,
_tccrc: Volatile<u8>,
_pad0: u8,
_tcntl: Volatile<u8>,
_tcnth: Volatile<u8>,
_icrl: Volatile<u8>,
_icrh: Volatile<u8>,
ocral: Volatile<u8>,
_ocrah: Volatile<u8>,
ocrbl: Volatile<u8>,
_ocrbh: Volatile<u8>,
ocrcl: Volatile<u8>,
_ocrch: Volatile<u8>,
}
impl Timer8 {
pub fn new(timer: TimerNo8) -> &'static mut Timer8 {
match timer {
TimerNo8::Timer0 => unsafe { &mut *(0x44 as *mut Timer8) },
TimerNo8::Timer2 => unsafe { &mut *(0xB0 as *mut Timer8) },
}
}
}
impl Timer16 {
pub fn new(timer: TimerNo16) -> &'static mut Timer16 {
match timer {
TimerNo16::Timer1 => unsafe { &mut *(0x80 as *mut Timer16) },
TimerNo16::Timer3 => unsafe { &mut *(0x90 as *mut Timer16) },
TimerNo16::Timer4 => unsafe { &mut *(0xA0 as *mut Timer16) },
TimerNo16::Timer5 => unsafe { &mut *(0x120 as *mut Timer16) },
}
}
}
impl AnalogComparator {
pub unsafe fn new() -> &'static mut AnalogComparator {
&mut *(0x50 as *mut AnalogComparator)
}
}
impl AnalogPin {
pub fn read(&mut self) -> u32 {
self.pin.set_input();
let pin = self.pinno;
unsafe {
let analog = Analog::new();
analog.power_adc_disable();
analog.adc_enable();
analog.analog_prescaler(2);
analog.adc_auto_trig();
match pin {
0 => {
analog.admux.update(|admux| {
admux.set_bits(0..3, 0b000);
});
analog.didr0.update(|didr0| {
didr0.set_bit(0, true);
});
analog.adcsrb.update(|mux| {
mux.set_bit(3, false);
});
}
1 => {
analog.admux.update(|admux| {
admux.set_bits(0..3, 0b001);
});
analog.didr0.update(|didr0| {
didr0.set_bit(1, true);
});
analog.adcsrb.update(|mux| {
mux.set_bit(3, false);
});
}
2 => {
analog.admux.update(|admux| {
admux.set_bits(0..3, 0b010);
});
analog.didr0.update(|didr0| {
didr0.set_bit(2, true);
});
analog.adcsrb.update(|mux| {
mux.set_bit(3, false);
});
}
3 => {
analog.admux.update(|admux| {
admux.set_bits(0..3, 0b011);
});
analog.didr0.update(|didr0| {
didr0.set_bit(3, true);
});
analog.adcsrb.update(|mux| {
mux.set_bit(3, false);
});
}
4 => {
analog.admux.update(|admux| {
admux.set_bits(0..3, 0b100);
});
analog.didr0.update(|didr0| {
didr0.set_bit(4, true);
});
analog.adcsrb.update(|mux| {
mux.set_bit(3, false);
});
}
5 => {
analog.admux.update(|admux| {
admux.set_bits(0..3, 0b101);
});
analog.didr0.update(|didr0| {
didr0.set_bit(5, true);
});
analog.adcsrb.update(|mux| {
mux.set_bit(3, false);
});
}
6 => {
analog.admux.update(|admux| {
admux.set_bits(0..3, 0b110);
});
analog.didr0.update(|didr0| {
didr0.set_bit(6, true);
});
analog.adcsrb.update(|mux| {
mux.set_bit(3, false);
});
}
7 => {
analog.admux.update(|admux| {
admux.set_bits(0..3, 0b111);
});
analog.didr0.update(|didr0| {
didr0.set_bit(7, true);
});
analog.adcsrb.update(|mux| {
mux.set_bit(3, false);
});
}
8 => {
analog.admux.update(|admux| {
admux.set_bits(0..3, 0b000);
});
analog.didr2.update(|didr2| {
didr2.set_bit(0, true);
});
analog.adcsrb.update(|mux| {
mux.set_bit(3, true);
});
}
9 => {
analog.admux.update(|admux| {
admux.set_bits(0..3, 0b001);
});
analog.didr2.update(|didr2| {
didr2.set_bit(1, true);
});
analog.adcsrb.update(|mux| {
mux.set_bit(3, true);
});
}
10 => {
analog.admux.update(|admux| {
admux.set_bits(0..3, 0b010);
});
analog.didr2.update(|didr2| {
didr2.set_bit(2, true);
});
analog.adcsrb.update(|mux| {
mux.set_bit(3, true);
});
}
11 => {
analog.admux.update(|admux| {
admux.set_bits(0..3, 0b011);
});
analog.didr2.update(|didr2| {
didr2.set_bit(4, true);
});
analog.adcsrb.update(|mux| {
mux.set_bit(3, true);
});
}
12 => {
analog.admux.update(|admux| {
admux.set_bits(0..3, 0b100);
});
analog.didr2.update(|didr2| {
didr2.set_bit(4, true);
});
analog.adcsrb.update(|mux| {
mux.set_bit(3, true);
});
}
13 => {
analog.admux.update(|admux| {
admux.set_bits(0..3, 0b101);
});
analog.didr2.update(|didr2| {
didr2.set_bit(5, true);
});
analog.adcsrb.update(|mux| {
mux.set_bit(3, true);
});
}
14 => {
analog.admux.update(|admux| {
admux.set_bits(0..3, 0b110);
});
analog.didr2.update(|didr2| {
didr2.set_bit(6, true);
});
analog.adcsrb.update(|mux| {
mux.set_bit(3, true);
});
}
15 => {
analog.admux.update(|admux| {
admux.set_bits(0..3, 0b111);
});
analog.didr2.update(|didr2| {
didr2.set_bit(7, true);
});
analog.adcsrb.update(|mux| {
mux.set_bit(3, true);
});
}
_ => unreachable!(),
}
analog.adc_con_start();
let mut i: i32 = 25;
let adcsra = analog.adcsra.read();
while adcsra.get_bit(4) == true {
if i != 0 {
i = i - 1;
__nop();
__nop(); } else {
unreachable!()
}
}
let mut a: u32 = 0;
a.set_bits(0..8, analog.adcl.read() as u32);
a.set_bits(8..10, analog.adch.read() as u32);
analog.adc_disable();
a
}
}
}
impl DigitalPin {
pub fn write(&mut self, value1: u8) {
self.pin.set_output();
let pin1 = self.pinno;
match pin1 {
4 | 13 => {
let pow = unsafe { Power::new() };
pow.prr0.set_bit(5, false);
let timer = Timer8::new(TimerNo8::Timer0);
timer.tccra.update(|ctrl| {
ctrl.set_bits(0..2, 0b11);
});
timer.tccrb.update(|ctrl| {
ctrl.set_bits(0..4, 0b0011);
});
if pin1 == 4 {
timer.tccra.update(|ctrl| {
ctrl.set_bits(4..8, 0b0010);
});
timer.ocrb.write(value1);
} else {
timer.tccra.update(|ctrl| {
ctrl.set_bits(4..8, 0b1000);
});
timer.ocra.write(value1);
}
}
9 | 10 => {
let pow = unsafe { Power::new() };
pow.prr0.set_bit(6, false);
let timer = Timer8::new(TimerNo8::Timer2);
timer.tccra.update(|ctrl| {
ctrl.set_bits(0..2, 0b11);
});
timer.tccrb.update(|ctrl| {
ctrl.set_bits(0..4, 0b0101);
});
if pin1 == 9 {
timer.tccra.update(|ctrl| {
ctrl.set_bits(4..8, 0b0010);
});
timer.ocrb.write(value1);
} else {
timer.tccra.update(|ctrl| {
ctrl.set_bits(4..8, 0b1000);
});
timer.ocra.write(value1);
}
}
11 | 12 => {
let pow = unsafe { Power::new() };
pow.prr0.set_bit(3, false);
let timer = Timer16::new(TimerNo16::Timer1);
timer.tccra.update(|ctrl| {
ctrl.set_bits(0..2, 0b01);
});
timer.tccrb.update(|ctrl| {
ctrl.set_bits(0..5, 0b00011);
});
if pin1 == 12 {
timer.tccra.update(|ctrl| {
ctrl.set_bits(2..8, 0b001000);
});
timer.ocrbl.write(value1);
} else {
timer.tccra.update(|ctrl| {
ctrl.set_bits(2..8, 0b100000);
});
timer.ocral.write(value1);
}
}
2 | 3 | 5 => {
let pow = unsafe { Power::new() };
pow.prr1.set_bit(3, false);
let timer = Timer16::new(TimerNo16::Timer3);
timer.tccra.update(|ctrl| {
ctrl.set_bits(0..2, 0b01);
});
timer.tccrb.update(|ctrl| {
ctrl.set_bits(0..5, 0b00011);
});
if pin1 == 2 {
timer.tccra.update(|ctrl| {
ctrl.set_bits(2..8, 0b001000);
});
timer.ocrbl.write(value1);
} else if pin1 == 5 {
timer.tccra.update(|ctrl| {
ctrl.set_bits(2..8, 0b100000);
});
timer.ocral.write(value1);
} else {
timer.tccra.update(|ctrl| {
ctrl.set_bits(2..8, 0b000010);
});
timer.ocrcl.write(value1);
}
}
6 | 7 | 8 => {
let timer = Timer16::new(TimerNo16::Timer4);
let pow = unsafe { Power::new() };
pow.prr1.set_bit(4, false);
timer.tccra.update(|ctrl| {
ctrl.set_bits(0..2, 0b01);
});
timer.tccrb.update(|ctrl| {
ctrl.set_bits(0..5, 0b00011);
});
if pin1 == 7 {
timer.tccra.update(|ctrl| {
ctrl.set_bits(2..8, 0b001000);
});
timer.ocrbl.write(value1);
} else if pin1 == 6 {
timer.tccra.update(|ctrl| {
ctrl.set_bits(2..8, 0b100000);
});
timer.ocral.write(value1);
} else {
timer.tccra.update(|ctrl| {
ctrl.set_bits(2..8, 0b000010);
});
timer.ocrcl.write(value1);
}
}
44 | 45 | 46 => {
let pow = unsafe { Power::new() };
pow.prr1.set_bit(5, false);
let timer = Timer16::new(TimerNo16::Timer5);
timer.tccra.update(|ctrl| {
ctrl.set_bits(0..2, 0b01);
});
timer.tccrb.update(|ctrl| {
ctrl.set_bits(0..5, 0b00011);
});
if pin1 == 45 {
timer.tccra.update(|ctrl| {
ctrl.set_bits(2..8, 0b001000);
});
timer.ocrbl.write(value1);
} else if pin1 == 46 {
timer.tccra.update(|ctrl| {
ctrl.set_bits(2..8, 0b100000);
});
timer.ocral.write(value1);
} else {
timer.tccra.update(|ctrl| {
ctrl.set_bits(2..8, 0b000010);
});
timer.ocrcl.write(value1);
}
}
_ => unreachable!(),
}
}
}
impl Analog {
pub unsafe fn new() -> &'static mut Analog {
&mut *(0x78 as *mut Analog)
}
pub fn adc_enable(&mut self) {
self.adcsra.update(|aden| {
aden.set_bit(7, true);
});
}
pub fn adc_con_start(&mut self) {
self.adcsra.update(|aden| {
aden.set_bit(6, true);
});
}
pub fn adc_auto_trig(&mut self) {
self.adcsra.update(|aden| {
aden.set_bit(5, false);
});
}
pub fn adc_disable(&mut self) {
self.adcsra.update(|aden| {
aden.set_bit(7, false);
});
}
pub fn power_adc_enable(&mut self) {
{
let pow = unsafe { Power::new() };
pow.prr0.set_bit(0, true);
}
}
pub fn power_adc_disable(&mut self) {
{
let pow = unsafe { Power::new() };
pow.prr0.set_bit(0, false);
}
}
pub fn analog_prescaler(&mut self, factor: u8) {
match factor {
2 => {
self.adcsra.update(|adcsra| {
adcsra.set_bits(0..3, 0b000);
});
}
4 => {
self.adcsra.update(|adcsra| {
adcsra.set_bits(0..3, 0b010);
});
}
8 => {
self.adcsra.update(|adcsra| {
adcsra.set_bits(0..3, 0b011);
});
}
16 => {
self.adcsra.update(|adcsra| {
adcsra.set_bits(0..3, 0b100);
});
}
32 => {
self.adcsra.update(|adcsra| {
adcsra.set_bits(0..3, 0b101);
});
}
64 => {
self.adcsra.update(|adcsra| {
adcsra.set_bits(0..3, 0b110);
});
}
128 => {
self.adcsra.update(|adcsra| {
adcsra.set_bits(0..3, 0b111);
});
}
_ => unreachable!(),
}
}
}
pub fn analog_reference(reftype: RefType) {
let analog = unsafe { Analog::new() };
match reftype {
RefType::DEFAULT => {
analog.admux.update(|admux| {
admux.set_bits(6..8, 0b01);
});
}
RefType::INTERNAL1V1 => {
analog.admux.update(|admux| {
admux.set_bits(6..8, 0b10);
});
}
RefType::INTERNAL2V56 => {
analog.admux.update(|admux| {
admux.set_bits(6..8, 0b11);
});
}
RefType::EXTERNAL => {
analog.admux.update(|admux| {
admux.set_bits(6..8, 0b00);
});
}
}
}