#![no_std] #![no_main] mod serial; use panic_probe as _; #[rtic::app(device = rp_pico::hal::pac, peripherals = true)] mod app { // Provide an alias for our BSP so we can switch targets quickly. // Uncomment the BSP you included in Cargo.toml, the rest of the code does not need to change. use rp_pico as bsp; use bsp::hal::{ clocks::{init_clocks_and_plls, Clock}, gpio::{bank0::Gpio26, Floating, Input, Pin}, rom_data::reset_to_usb_boot, sio::Sio, timer::{Alarm, Alarm0}, usb::UsbBus, watchdog::Watchdog, Adc, Timer, }; use fugit::MicrosDurationU32; use embedded_hal::{adc::OneShot, digital::v2::OutputPin}; use usb_device::{class_prelude::*, prelude::*}; use crate::serial::{Commands, Serial}; const SCAN_TIME_US: MicrosDurationU32 = MicrosDurationU32::secs(1); struct Data { i: usize, usb_bus: UsbBusAllocator, usb_dev: UsbDevice<'static, UsbBus>, serial: Serial<'static>, adc: Adc, adc_pin_0: Pin>, } #[shared] struct Shared { timer: Timer, alarm: Alarm0, data: Data, } #[local] struct Local {} #[init] fn init(c: init::Context) -> (Shared, Local, init::Monotonics) { // Soft-reset does not release the hardware spinlocks // Release them now to avoid a deadlock after debug or watchdog reset unsafe { bsp::hal::sio::spinlock_reset(); } let mut resets = c.device.RESETS; let mut watchdog = Watchdog::new(c.device.WATCHDOG); let external_xtal_freq_hz = 12_000_000u32; let clocks = init_clocks_and_plls( external_xtal_freq_hz, c.device.XOSC, c.device.CLOCKS, c.device.PLL_SYS, c.device.PLL_USB, &mut resets, &mut watchdog, ) .ok() .unwrap(); let sio = Sio::new(c.device.SIO); let pins = rp_pico::Pins::new( c.device.IO_BANK0, c.device.PADS_BANK0, sio.gpio_bank0, &mut resets, ); let mut timer = Timer::new(c.device.TIMER, &mut resets); let mut alarm = timer.alarm_0().unwrap(); let _ = alarm.schedule(SCAN_TIME_US); alarm.enable_interrupt(); let mut led_pin = pins.led.into_push_pull_output(); led_pin.set_low().unwrap(); // Set up the USB driver let usb_bus = UsbBusAllocator::new(UsbBus::new( c.device.USBCTRL_REGS, c.device.USBCTRL_DPRAM, clocks.usb_clock, true, &mut resets, )); let serial = Serial::new(&usb_bus); // Create a USB device with a fake VID and PID let usb_dev = UsbDeviceBuilder::new(&usb_bus, UsbVidPid(0x16c0, 0x27dd)) .manufacturer("Fake company") .product("Serial port") .serial_number("TEST") .device_class(2) // from: https://www.usb.org/defined-class-codes .build(); let adc = Adc::new(c.device.ADC, &mut resets); let adc_pin_0 = pins.gpio26.into_floating_input(); // let mut adc_pin_1 = pins.gpio27.into_floating_input(); // let mut adc_pin_2 = pins.gpio28.into_floating_input(); let data = Data { i: 0, usb_bus, usb_dev, serial, adc, adc_pin_0, }; (Shared { timer, alarm, data }, Local {}, init::Monotonics()) } #[task( binds = TIMER_IRQ_0, priority = 1, shared = [timer, alarm, data], local = [tog: bool = true], )] fn timer_irq(mut c: timer_irq::Context) { c.shared.data.lock(|data| { data.i += 1; if data.i == 100 { data.i = 0; let adc_0_value: u16 = data.adc.read(&mut data.adc_pin_0).unwrap(); // let adc_1_value: u16 = adc.read(&mut adc_pin_1).unwrap(); // let adc_2_value: u16 = adc.read(&mut adc_pin_2).unwrap(); data.serial.send(adc_0_value); } if data.usb_dev.poll(&mut [&mut data.serial]) { if let Some(command) = data.serial.read() { match command { Commands::Reset => reset_to_usb_boot(0, 0), } } } }); let mut alarm = c.shared.alarm; (alarm).lock(|a| { a.clear_interrupt(); let _ = a.schedule(SCAN_TIME_US); }); } }