use core::mem; use arduino_hal::{ hal::port::{PB4, PB5, PC4, PC5, PD2}, pac::{ adc::adc::ADC_SPEC, tc1::{ocr1a::OCR1A_SPEC, ocr1b::OCR1B_SPEC}, }, pins, port::{ mode::{Input, Output, PullUp}, Pin, }, Peripherals, }; use avr_device::generic::Reg; pub struct Setup<'a> { pub led: Pin, pub footswitch: Pin, PB4>, pub toggle: Pin, PD2>, pub push_button_1: Pin, PC5>, pub push_button_2: Pin, PC4>, ocr1a: &'a Reg, ocr1b: &'a Reg, adc: &'a Reg, } impl<'a> Setup<'a> { //defining the output PWM parameters // pwm frequency - 31.3KHz const PWM_FREQ: u16 = 0x00FF; // Fast (1) or Phase Correct (0) const PWM_MODE: u8 = 0; // 2 PWMs in parallel const PWM_QTY: u8 = 2; pub fn write_output(&self, output: u16) { let high_byte = ((output + 0x8000) >> 8) & 0x00FF; let low_byte = output & 0x00FF; self.ocr1a.write(|w| unsafe { w.bits(high_byte) }); self.ocr1b.write(|w| unsafe { w.bits(low_byte) }); } pub fn get_input(&self) -> u16 { self.adc.read().bits() } } impl<'a> Default for Setup<'a> { fn default() -> Self { let dp = Peripherals::take().unwrap(); // turn on outputs dp.PORTB.ddrb.write(|w| unsafe { w.bits(0x02) }); let pins = pins!(dp); // defining harware resources let led = pins.d13.into_output(); let footswitch = pins.d12.into_pull_up_input(); let toggle = pins.d2.into_pull_up_input(); let push_button_1 = pins.a5.into_pull_up_input(); let push_button_2 = pins.a4.into_pull_up_input(); // setup ADC // left adjust, adc0, internal vcc dp.ADC.admux.write(|w| unsafe { w.bits(0x60) }); // turn on adc, ck/32, auto trigger dp.ADC.adcsra.write(|w| unsafe { w.bits(0xe5) }); // t1 capture for trigger dp.ADC.adcsrb.write(|w| unsafe { w.bits(0x07) }); // turn off digital inputs for adc0 dp.ADC.didr0.write(|w| unsafe { w.bits(0x01) }); // setup PWM dp.TC1.tccr1a.write(|w| unsafe { w.bits(((Self::PWM_QTY - 1) << 5) | 0x80 | (Self::PWM_MODE << 1)) }); // ck/1 dp.TC1 .tccr1b .write(|w| unsafe { w.bits((Self::PWM_MODE << 3) | 0x11) }); // interrupt on capture interrupt dp.TC1.timsk1.write(|w| unsafe { w.bits(0x20) }); dp.TC1.icr1.write(|w| unsafe { w.bits(Self::PWM_FREQ) }); let ocr1a = &dp.TC1.ocr1a; let ocr1b = &dp.TC1.ocr1b; let adc = &dp.ADC.adc; unsafe { avr_device::interrupt::enable() }; Self { led, footswitch, toggle, push_button_1, push_button_2, ocr1a: unsafe { mem::transmute(ocr1a as *const _) }, ocr1b: unsafe { mem::transmute(ocr1b as *const _) }, adc: unsafe { mem::transmute(adc as *const _) }, } } }