diff --git a/boards/pygamer/CHANGELOG.md b/boards/pygamer/CHANGELOG.md index a51d22fd0c04..f345a913c3c2 100644 --- a/boards/pygamer/CHANGELOG.md +++ b/boards/pygamer/CHANGELOG.md @@ -1,5 +1,7 @@ # Unreleased +- remove neopixel support and examples (currently unreliable) +- update HAL v0.14 -> v0.17 and other dependencies, fix examples - update path of Cargo config # v0.9.0 diff --git a/boards/pygamer/Cargo.toml b/boards/pygamer/Cargo.toml index 684f16b9748c..f0b40e81bc56 100644 --- a/boards/pygamer/Cargo.toml +++ b/boards/pygamer/Cargo.toml @@ -15,16 +15,15 @@ edition = "2021" exclude = ["assets"] [dependencies] -cortex-m = "0.7" +cortex-m = {version = "0.7", features = ["critical-section-single-core"]} st7735-lcd = "0.8.1" -ws2812-timer-delay = "0.3" [dependencies.cortex-m-rt] version = "0.7" optional = true [dependencies.atsamd-hal] -version = "0.14" +version = "0.17" default-features = false [dependencies.micromath] @@ -32,28 +31,28 @@ version = "0.5.1" optional = true [dependencies.embedded-sdmmc] -version = "0.3.0" +version = "0.8.0" optional = true [dependencies.usb-device] -version = "0.2" +version = "0.3.1" optional = true [dev-dependencies] -usbd-serial = "0.1" +usbd-serial = "0.2" panic-halt = "0.2" embedded-graphics = "0.7.1" +embedded-hal-02 = {package = "embedded-hal", version = "0.2", features = ["unproven"]} +embedded-hal-bus = "0.2.0" smart-leds = "0.3" -ws2812-spi = { version = "0.4.0", features = ["mosi_idle_high"] } lis3dh = "0.1.0" cortex-m-rtic = "1.0" tinybmp = "0.3.1" [features] # ask the HAL to enable atsamd51j support -default = ["rt", "atsamd-hal/samd51j", "unproven"] +default = ["rt", "atsamd-hal/samd51j"] rt = ["cortex-m-rt", "atsamd-hal/samd51j-rt"] -unproven = ["atsamd-hal/unproven"] usb = ["atsamd-hal/usb", "usb-device"] sd-card = ["embedded-sdmmc"] math = ["micromath"] @@ -73,10 +72,6 @@ opt-level = 's' [package.metadata] chip = "ATSAMD51J19A" -[[example]] -name = "usb_serial" -required-features = ["usb"] - [[example]] name = "usb_poll" required-features = ["usb"] @@ -85,10 +80,6 @@ required-features = ["usb"] name = "sd_card" required-features = ["sd-card"] -[[example]] -name = "neopixel_easing" -required-features = ["math"] - [[example]] name = "pwm_tc4" required-features = ["math"] diff --git a/boards/pygamer/examples/blinky_basic.rs b/boards/pygamer/examples/blinky_basic.rs index c5028ecc1ca0..d55ac9745b66 100644 --- a/boards/pygamer/examples/blinky_basic.rs +++ b/boards/pygamer/examples/blinky_basic.rs @@ -3,9 +3,10 @@ #![no_std] #![no_main] +use bsp::{entry, hal, pac, Pins, RedLed}; #[cfg(not(feature = "panic_led"))] use panic_halt as _; -use pygamer::{entry, hal, pac, Pins}; +use pygamer as bsp; use hal::clock::GenericClockController; use hal::delay::Delay; @@ -27,8 +28,8 @@ fn main() -> ! { let mut delay = Delay::new(core.SYST, &mut clocks); delay.delay_ms(400u16); - let mut pins = Pins::new(peripherals.PORT); - let mut red_led = pins.d13.into_open_drain_output(&mut pins.port); + let pins = Pins::new(peripherals.PORT); + let mut red_led: RedLed = pins.d13.into(); let mut wdt = Watchdog::new(peripherals.WDT); wdt.start(WatchdogTimeout::Cycles256 as u8); diff --git a/boards/pygamer/examples/button_rtic.rs b/boards/pygamer/examples/button_rtic.rs index ae8c314568d6..2dc860a166b8 100644 --- a/boards/pygamer/examples/button_rtic.rs +++ b/boards/pygamer/examples/button_rtic.rs @@ -1,23 +1,25 @@ #![no_std] #![no_main] -use bsp::{pins::ButtonReader, pins::Keys, Pins}; +use bsp::{hal, ButtonReader, Keys, Pins, RedLed}; #[cfg(not(feature = "panic_led"))] use panic_halt as _; use pygamer as bsp; -#[rtic::app(device = bsp::pac, peripherals = true)] -mod app { +use hal::clock::GenericClockController; +use hal::prelude::*; +use hal::time::Hertz; +use hal::timer::TimerCounter; +use rtic::app; +#[app(device = crate::hal::pac, peripherals = true)] +mod app { use super::*; - use bsp::clock::GenericClockController; - use bsp::gpio::{OpenDrain, Output, Pa23}; - use bsp::prelude::*; #[local] - struct Local { - red_led: Pa23>, - timer: bsp::timer::TimerCounter3, + struct Resources { + red_led: RedLed, + timer: hal::timer::TimerCounter3, buttons: ButtonReader, } @@ -30,7 +32,7 @@ mod app { /// period. #[task(binds = TC3, local = [timer, red_led, buttons])] fn tc3(c: tc3::Context) { - if c.local.timer.wait().is_ok() { + if InterruptDrivenTimer::wait(c.local.timer).is_ok() { for event in c.local.buttons.events() { match event { Keys::SelectDown => { @@ -46,7 +48,7 @@ mod app { } #[init] - fn init(c: init::Context) -> (Shared, Local, init::Monotonics) { + fn init(c: init::Context) -> (Shared, Resources, init::Monotonics) { let mut device = c.device; let mut clocks = GenericClockController::with_internal_32kosc( device.GCLK, @@ -56,21 +58,22 @@ mod app { &mut device.NVMCTRL, ); - let mut pins = Pins::new(device.PORT).split(); + let pins = Pins::new(device.PORT).split(); let gclk0 = clocks.gclk0(); let timer_clock = clocks.tc2_tc3(&gclk0).unwrap(); - let mut tc3 = bsp::timer::TimerCounter::tc3_(&timer_clock, device.TC3, &mut device.MCLK); + let mut tc3 = TimerCounter::tc3_(&timer_clock, device.TC3, &mut device.MCLK); + + InterruptDrivenTimer::start(&mut tc3, Hertz::Hz(200).into_duration()); - tc3.start(200.hz()); tc3.enable_interrupt(); ( Shared {}, - Local { - buttons: pins.buttons.init(&mut pins.port), - red_led: pins.led_pin.into_open_drain_output(&mut pins.port), + Resources { + buttons: pins.buttons.init(), + red_led: pins.led_pin.into(), timer: tc3, }, init::Monotonics(), diff --git a/boards/pygamer/examples/clock_out.rs b/boards/pygamer/examples/clock_out.rs index 18a7273e81f8..46e82e199fc5 100644 --- a/boards/pygamer/examples/clock_out.rs +++ b/boards/pygamer/examples/clock_out.rs @@ -3,13 +3,14 @@ #![no_std] #![no_main] +use bsp::{entry, hal, pac, GclkOut, Pins}; #[cfg(not(feature = "panic_led"))] use panic_halt as _; -use pygamer::{entry, hal, pac, Pins}; +use pygamer as bsp; use hal::clock::GenericClockController; -use pac::gclk::genctrl::SRC_A::DPLL0; -use pac::gclk::pchctrl::GEN_A::GCLK2; +use pac::gclk::genctrl::SRCSELECT_A::DPLL0; +use pac::gclk::pchctrl::GENSELECT_A::GCLK2; use pac::Peripherals; #[entry] @@ -22,12 +23,12 @@ fn main() -> ! { &mut peripherals.OSCCTRL, &mut peripherals.NVMCTRL, ); - let mut pins = Pins::new(peripherals.PORT); + let pins = Pins::new(peripherals.PORT); - //3mhz + // Output 3 MHz clock on pin d5 let _gclk2 = clocks .configure_gclk_divider_and_source(GCLK2, 40, DPLL0, false) .unwrap(); - pins.d5.into_function_m(&mut pins.port); + let _clock_out_pin: GclkOut = pins.d5.into(); loop {} } diff --git a/boards/pygamer/examples/ferris_img.rs b/boards/pygamer/examples/ferris_img.rs index d707e54671c1..6aeba04f2e77 100644 --- a/boards/pygamer/examples/ferris_img.rs +++ b/boards/pygamer/examples/ferris_img.rs @@ -8,9 +8,10 @@ #![no_std] #![no_main] +use bsp::{entry, hal, pac, Pins}; #[cfg(not(feature = "panic_led"))] use panic_halt as _; -use pygamer::{entry, hal, pac, Pins}; +use pygamer as bsp; use embedded_graphics::prelude::*; use embedded_graphics::primitives::{PrimitiveStyleBuilder, Rectangle}; @@ -30,7 +31,7 @@ fn main() -> ! { &mut peripherals.OSCCTRL, &mut peripherals.NVMCTRL, ); - let mut pins = Pins::new(peripherals.PORT).split(); + let pins = Pins::new(peripherals.PORT).split(); let mut delay = hal::delay::Delay::new(core.SYST, &mut clocks); let (mut display, _backlight) = pins @@ -41,7 +42,6 @@ fn main() -> ! { &mut peripherals.MCLK, peripherals.TC2, &mut delay, - &mut pins.port, ) .unwrap(); diff --git a/boards/pygamer/examples/neopixel_adc_battery.rs b/boards/pygamer/examples/neopixel_adc_battery.rs deleted file mode 100644 index 5612c7202135..000000000000 --- a/boards/pygamer/examples/neopixel_adc_battery.rs +++ /dev/null @@ -1,83 +0,0 @@ -//! Display battery percentage on the neopixels. -//! -//! Note leds may appear white during debug. Either build for release or add -//! opt-level = 2 to profile.dev in Cargo.toml - -#![no_std] -#![no_main] - -#[cfg(not(feature = "panic_led"))] -use panic_halt as _; -use pygamer::{entry, hal, pac, Pins}; - -use hal::adc::Adc; -use hal::pac::gclk::pchctrl::GEN_A::GCLK11; -use hal::prelude::*; -use hal::timer::SpinTimer; -use hal::{clock::GenericClockController, delay::Delay}; -use pac::{CorePeripherals, Peripherals}; -use smart_leds::{brightness, hsv::RGB8, SmartLedsWrite}; - -#[entry] -fn main() -> ! { - let mut peripherals = Peripherals::take().unwrap(); - let core = CorePeripherals::take().unwrap(); - let mut clocks = GenericClockController::with_internal_32kosc( - peripherals.GCLK, - &mut peripherals.MCLK, - &mut peripherals.OSC32KCTRL, - &mut peripherals.OSCCTRL, - &mut peripherals.NVMCTRL, - ); - let mut pins = Pins::new(peripherals.PORT).split(); - - let mut adc0 = Adc::adc0(peripherals.ADC0, &mut peripherals.MCLK, &mut clocks, GCLK11); - let mut battery = pins.battery.init(&mut pins.port); - - // neopixels - let timer = SpinTimer::new(4); - let mut neopixel = pins.neopixel.init(timer, &mut pins.port); - - let mut delay = Delay::new(core.SYST, &mut clocks); - - //todo put this on a .. 10minute, 30min, update timer - loop { - let battery_data = battery.read(&mut adc0); - - let mut colors = [ - RGB8::default(), - RGB8::default(), - RGB8::default(), - RGB8::default(), - RGB8::default(), - ]; - - if battery_data < 3.6 { - colors[0] = RGB8::from((255, 0, 0)); - } else if (battery_data >= 3.6) && (battery_data < 3.8) { - colors[0] = RGB8::from((255, 0, 0)); - colors[1] = RGB8::from((255, 0, 0)); - } else if (battery_data >= 3.8) && (battery_data < 3.9) { - colors[0] = RGB8::from((255, 255, 0)); - colors[1] = RGB8::from((255, 255, 0)); - colors[2] = RGB8::from((255, 255, 0)); - } else if (battery_data >= 3.9) && (battery_data < 4.0) { - colors[0] = RGB8::from((0, 255, 0)); - colors[1] = RGB8::from((0, 255, 0)); - colors[2] = RGB8::from((0, 255, 0)); - colors[3] = RGB8::from((0, 255, 0)); - } else { - colors[0] = RGB8::from((0, 255, 0)); - colors[1] = RGB8::from((0, 255, 0)); - colors[2] = RGB8::from((0, 255, 0)); - colors[3] = RGB8::from((0, 255, 0)); - colors[4] = RGB8::from((0, 255, 0)); - }; - - neopixel - .write(brightness(colors.iter().cloned(), 1)) - .unwrap(); - - delay.delay_ms(10u8); - } -} diff --git a/boards/pygamer/examples/neopixel_adc_light.rs b/boards/pygamer/examples/neopixel_adc_light.rs deleted file mode 100644 index 782fd25096a7..000000000000 --- a/boards/pygamer/examples/neopixel_adc_light.rs +++ /dev/null @@ -1,82 +0,0 @@ -//! Display light sensor reading on the neopixels. -//! -//! Note leds may appear white during debug. Either build for release or add -//! opt-level = 2 to profile.dev in Cargo.toml - -#![no_std] -#![no_main] - -#[cfg(not(feature = "panic_led"))] -use panic_halt as _; -use pygamer::{entry, hal, pac, Pins}; - -use hal::adc::Adc; -use hal::ehal::digital::v1_compat::OldOutputPin; -use hal::prelude::*; -use hal::timer::SpinTimer; -use hal::{clock::GenericClockController, delay::Delay}; -use pac::gclk::pchctrl::GEN_A::GCLK11; -use pac::{CorePeripherals, Peripherals}; -use smart_leds::hsv::{hsv2rgb, Hsv, RGB8}; -use smart_leds::SmartLedsWrite; -use ws2812_timer_delay as ws2812; - -#[entry] -fn main() -> ! { - let mut peripherals = Peripherals::take().unwrap(); - let core = CorePeripherals::take().unwrap(); - let mut clocks = GenericClockController::with_internal_32kosc( - peripherals.GCLK, - &mut peripherals.MCLK, - &mut peripherals.OSC32KCTRL, - &mut peripherals.OSCCTRL, - &mut peripherals.NVMCTRL, - ); - let mut pins = Pins::new(peripherals.PORT); - - let mut adc1 = Adc::adc1(peripherals.ADC1, &mut peripherals.MCLK, &mut clocks, GCLK11); - let mut light = pins.light.into_function_b(&mut pins.port); - - let timer = SpinTimer::new(4); - let neopixel_pin: OldOutputPin<_> = pins.neopixel.into_push_pull_output(&mut pins.port).into(); - let mut neopixel = ws2812::Ws2812::new(timer, neopixel_pin); - - let mut delay = Delay::new(core.SYST, &mut clocks); - - const NUM_LEDS: usize = 5; - let mut j: u8 = 0; - - loop { - let light_data: u16 = adc1.read(&mut light).unwrap(); - - let pos: usize = if light_data < 100 { - 0 - } else if (light_data >= 147) && (light_data < 1048) { - 1 - } else if (light_data >= 1048) && (light_data < 3048) { - 2 - } else if (light_data >= 3048) && (light_data < 3948) { - 3 - } else { - 4 - }; - - //finally paint the one led wherever the position is - let _ = neopixel.write((0..NUM_LEDS).map(|i| { - if i == pos { - hsv2rgb(Hsv { - hue: j, - sat: 255, - val: 32, - }) - } else { - RGB8::default() - } - })); - - //incremement the hue easing - j = j.wrapping_add(1); - - delay.delay_ms(10u8); - } -} diff --git a/boards/pygamer/examples/neopixel_button.rs b/boards/pygamer/examples/neopixel_button.rs deleted file mode 100644 index 52b08cc8b89f..000000000000 --- a/boards/pygamer/examples/neopixel_button.rs +++ /dev/null @@ -1,107 +0,0 @@ -//! Joystick y controls the color of a neopixel while Joystick x moves it -//! left and right around the center neopixel -//! Select and Start control a second neopixel left and right while it is -//! automatically rotating through the color wheel -//! When they overlap, joystick takes precedence -//! -//! Note leds may appear white during debug. Either build for release or add -//! opt-level = 2 to profile.dev in Cargo.toml - -#![no_std] -#![no_main] - -#[cfg(not(feature = "panic_led"))] -use panic_halt as _; -use pygamer::{self as hal, entry, pac, pins::Keys, Pins}; - -use hal::adc::Adc; -use hal::prelude::*; -use hal::timer::SpinTimer; -use hal::util::map_from; -use hal::{clock::GenericClockController, delay::Delay}; -use pac::gclk::pchctrl::GEN_A::GCLK11; -use pac::{CorePeripherals, Peripherals}; -use smart_leds::hsv::{hsv2rgb, Hsv, RGB8}; -use smart_leds::SmartLedsWrite; - -#[entry] -fn main() -> ! { - let mut peripherals = Peripherals::take().unwrap(); - let core_peripherals = CorePeripherals::take().unwrap(); - - let mut clocks = GenericClockController::with_internal_32kosc( - peripherals.GCLK, - &mut peripherals.MCLK, - &mut peripherals.OSC32KCTRL, - &mut peripherals.OSCCTRL, - &mut peripherals.NVMCTRL, - ); - - let mut delay = Delay::new(core_peripherals.SYST, &mut clocks); - let mut pins = Pins::new(peripherals.PORT).split(); - - let mut buttons = pins.buttons.init(&mut pins.port); - - let mut adc1 = Adc::adc1(peripherals.ADC1, &mut peripherals.MCLK, &mut clocks, GCLK11); - let mut joystick = pins.joystick.init(&mut pins.port); - - // neopixels - let timer = SpinTimer::new(4); - - let mut neopixel = pins.neopixel.init(timer, &mut pins.port); - - const NUM_LEDS: usize = 5; - let mut pos_button: usize = 2; - let mut color_button: u8 = 0; - loop { - let (x, y) = joystick.read(&mut adc1); - - // map up/down to control rainbow color 0-255 - let color_joy = map_from(y as i16, (0, 4095), (0, 255)) as u8; - - // map left/right to neopixel position 0-4 - // joystick is not quite linear, rests at second pixel - // shifting up by 500 seems to help - let pos_joy = map_from(x as i16 + 500, (0, 4595), (0, 4)) as usize; - - for event in buttons.events() { - match event { - Keys::SelectDown => { - if pos_button > 0 { - pos_button -= 1; - } - } - Keys::StartDown => { - if pos_button < 4 { - pos_button += 1; - } - } - _ => {} - } - } - - //finally paint the two leds at position, accel priority - let _ = neopixel.write((0..NUM_LEDS).map(|i| { - if i == pos_joy { - hsv2rgb(Hsv { - hue: color_joy, - sat: 255, - val: 32, - }) - } else if i == pos_button { - hsv2rgb(Hsv { - hue: color_button, - sat: 255, - val: 32, - }) - } else { - RGB8::default() - } - })); - - //incremement the hue easing - color_button = color_button.wrapping_add(1); - - delay.delay_ms(5u8); - } -} diff --git a/boards/pygamer/examples/neopixel_easing.rs b/boards/pygamer/examples/neopixel_easing.rs deleted file mode 100644 index f6f82a47548c..000000000000 --- a/boards/pygamer/examples/neopixel_easing.rs +++ /dev/null @@ -1,88 +0,0 @@ -//! Randomly choose and led and color to breath in and out -//! -//! Note leds may appear white during debug. Either build for release or add -//! opt-level = 2 to profile.dev in Cargo.toml - -#![no_std] -#![no_main] - -#[cfg(not(feature = "panic_led"))] -use panic_halt as _; -use pygamer::{entry, hal, pac, Pins}; - -use core::f32::consts::FRAC_PI_2; -use hal::clock::GenericClockController; -use hal::delay::Delay; -use hal::prelude::*; -use hal::timer::SpinTimer; -use hal::trng::Trng; -use micromath::F32Ext; -use pac::{CorePeripherals, Peripherals}; -use smart_leds::hsv::{hsv2rgb, Hsv, RGB8}; -use smart_leds::SmartLedsWrite; - -#[entry] -fn main() -> ! { - let mut peripherals = Peripherals::take().unwrap(); - let core = CorePeripherals::take().unwrap(); - let mut clocks = GenericClockController::with_internal_32kosc( - peripherals.GCLK, - &mut peripherals.MCLK, - &mut peripherals.OSC32KCTRL, - &mut peripherals.OSCCTRL, - &mut peripherals.NVMCTRL, - ); - - let mut pins = Pins::new(peripherals.PORT).split(); - let timer = SpinTimer::new(4); - - let mut neopixel = pins.neopixel.init(timer, &mut pins.port); - let mut delay = Delay::new(core.SYST, &mut clocks); - - let trng = Trng::new(&mut peripherals.MCLK, peripherals.TRNG); - - const NUM_LEDS: usize = 5; - - loop { - let rand = trng.random_u8(); - let pos: usize = rand.wrapping_rem(5) as usize; //random led - - //slowly enable led - for j in 0..255u8 { - let _ = neopixel.write((0..NUM_LEDS).map(|i| { - if i == pos { - hsv2rgb(Hsv { - hue: rand, - sat: 255, - val: sine_ease_in(j as f32, 0.0, 32.0, 255.0) as u8, - }) - } else { - RGB8::default() - } - })); - delay.delay_ms(5u8); - } - - //slowly disable led - note the reverse .rev() - for j in (0..255u8).rev() { - let _ = neopixel.write((0..NUM_LEDS).map(|i| { - if i == pos { - hsv2rgb(Hsv { - hue: rand, - sat: 255, - val: sine_ease_in(j as f32, 0.0, 32.0, 255.0) as u8, - }) - } else { - RGB8::default() - } - })); - delay.delay_ms(5u8); - } - } -} - -#[inline] -// current step, where oputput starts, where output ends, last step -fn sine_ease_in(t: f32, b: f32, c: f32, d: f32) -> f32 { - -c * (t / d * FRAC_PI_2).cos() + c + b -} diff --git a/boards/pygamer/examples/neopixel_rainbow_spi.rs b/boards/pygamer/examples/neopixel_rainbow_spi.rs deleted file mode 100644 index 69a6a1492820..000000000000 --- a/boards/pygamer/examples/neopixel_rainbow_spi.rs +++ /dev/null @@ -1,96 +0,0 @@ -//! Rotate all neopixel leds through a rainbow. Uses a luckily placed set of SPI -//! pins as a timer source. -//! -//! Note leds may appear white during debug. Either build for release or add -//! opt-level = 2 to profile.dev in Cargo.toml - -#![no_std] -#![no_main] - -#[cfg(not(feature = "panic_led"))] -use panic_halt as _; -use pygamer::{entry, hal, pac, Pins}; - -use hal::prelude::*; -use hal::sercom::PadPin; -use hal::time::MegaHertz; -use hal::{clock::GenericClockController, delay::Delay}; -use pac::{CorePeripherals, Peripherals}; -use smart_leds::hsv::{hsv2rgb, Hsv}; -use smart_leds::SmartLedsWrite; -use ws2812_spi as ws2812; - -#[entry] -fn main() -> ! { - let mut peripherals = Peripherals::take().unwrap(); - let core = CorePeripherals::take().unwrap(); - let mut clocks = GenericClockController::with_internal_32kosc( - peripherals.GCLK, - &mut peripherals.MCLK, - &mut peripherals.OSC32KCTRL, - &mut peripherals.OSCCTRL, - &mut peripherals.NVMCTRL, - ); - let mut pins = Pins::new(peripherals.PORT); - let gclk = clocks.gclk0(); - - let spi: hal::sercom::SPIMaster2< - hal::sercom::Sercom2Pad0>, - hal::sercom::Sercom2Pad3>, - hal::sercom::Sercom2Pad1>, - > = hal::sercom::SPIMaster2::new( - &clocks.sercom2_core(&gclk).unwrap(), - MegaHertz(3), - hal::ehal::spi::Mode { - phase: hal::ehal::spi::Phase::CaptureOnFirstTransition, - polarity: hal::ehal::spi::Polarity::IdleLow, - }, - peripherals.SERCOM2, - &mut peripherals.MCLK, - ( - pins.sda.into_pad(&mut pins.port), - pins.neopixel.into_pad(&mut pins.port), - pins.scl.into_pad(&mut pins.port), - ), - ); - - let mut neopixel = ws2812::Ws2812::new(spi); - let mut delay = Delay::new(core.SYST, &mut clocks); - - loop { - for j in 0..255u8 { - let colors = [ - // split the color changes across all 5 leds evenly, 255/5=51 - // and have them safely wrap over when they go above 255 - hsv2rgb(Hsv { - hue: j, - sat: 255, - val: 32, - }), - hsv2rgb(Hsv { - hue: j.wrapping_add(51), - sat: 255, - val: 32, - }), - hsv2rgb(Hsv { - hue: j.wrapping_add(102), - sat: 255, - val: 32, - }), - hsv2rgb(Hsv { - hue: j.wrapping_add(153), - sat: 255, - val: 32, - }), - hsv2rgb(Hsv { - hue: j.wrapping_add(204), - sat: 255, - val: 32, - }), - ]; - - neopixel.write(colors.iter().cloned()).unwrap(); - delay.delay_ms(5u8); - } - } -} diff --git a/boards/pygamer/examples/neopixel_rainbow_timer.rs b/boards/pygamer/examples/neopixel_rainbow_timer.rs deleted file mode 100644 index d1ae56fa291a..000000000000 --- a/boards/pygamer/examples/neopixel_rainbow_timer.rs +++ /dev/null @@ -1,78 +0,0 @@ -//! Rotate all neopixel leds through a rainbow. Uses a Timer as a timer source. -//! -//! Note leds may appear white during debug. Either build for release or add -//! opt-level = 2 to profile.dev in Cargo.toml -//! -//! Note: This is jittery these days and probably not a good choice until -//! debugged - -#![no_std] -#![no_main] - -#[cfg(not(feature = "panic_led"))] -use panic_halt as _; -use pygamer::{self as hal, entry, Pins}; - -use hal::pac::{CorePeripherals, Peripherals}; -use hal::prelude::*; -use hal::{clock::GenericClockController, delay::Delay, timer::TimerCounter}; -use smart_leds::hsv::{hsv2rgb, Hsv}; -use smart_leds::SmartLedsWrite; - -#[entry] -fn main() -> ! { - let mut peripherals = Peripherals::take().unwrap(); - let core = CorePeripherals::take().unwrap(); - let mut clocks = GenericClockController::with_internal_32kosc( - peripherals.GCLK, - &mut peripherals.MCLK, - &mut peripherals.OSC32KCTRL, - &mut peripherals.OSCCTRL, - &mut peripherals.NVMCTRL, - ); - let mut pins = Pins::new(peripherals.PORT).split(); - - let gclk0 = clocks.gclk0(); - let timer_clock = clocks.tc2_tc3(&gclk0).unwrap(); - let mut timer = TimerCounter::tc3_(&timer_clock, peripherals.TC3, &mut peripherals.MCLK); - timer.start(3.mhz()); - - let mut neopixel = pins.neopixel.init(timer, &mut pins.port); - let mut delay = Delay::new(core.SYST, &mut clocks); - - loop { - for j in 0..255u8 { - let colors = [ - // stagger the color changes across all 5 leds evenly, 255/5=51 - // and have them safely wrap over when they go above 255 - hsv2rgb(Hsv { - hue: j, - sat: 255, - val: 32, - }), - hsv2rgb(Hsv { - hue: j.wrapping_add(51), - sat: 255, - val: 32, - }), - hsv2rgb(Hsv { - hue: j.wrapping_add(102), - sat: 255, - val: 32, - }), - hsv2rgb(Hsv { - hue: j.wrapping_add(153), - sat: 255, - val: 32, - }), - hsv2rgb(Hsv { - hue: j.wrapping_add(204), - sat: 255, - val: 32, - }), - ]; - neopixel.write(colors.iter().cloned()).unwrap(); - delay.delay_ms(5u8); - } - } -} diff --git a/boards/pygamer/examples/neopixel_tilt.rs b/boards/pygamer/examples/neopixel_tilt.rs deleted file mode 100644 index d11fdbca8266..000000000000 --- a/boards/pygamer/examples/neopixel_tilt.rs +++ /dev/null @@ -1,132 +0,0 @@ -//! LIS3DH accelerometer example. Move the neopixel led by tilting left and -//! right. -//! -//! Note leds may appear white during debug. Either build for release or add -//! opt-level = 2 to profile.dev in Cargo.toml - -#![no_std] -#![no_main] - -#[cfg(not(feature = "panic_led"))] -use panic_halt as _; -use pygamer::{entry, hal, pac, Pins}; - -use hal::prelude::*; -use hal::time::KiloHertz; -use hal::timer::SpinTimer; -use hal::{clock::GenericClockController, delay::Delay}; -use lis3dh::{accelerometer::Accelerometer, Lis3dh}; -use pac::{CorePeripherals, Peripherals}; -use smart_leds::hsv::{hsv2rgb, Hsv, RGB8}; -use smart_leds::SmartLedsWrite; - -#[entry] -fn main() -> ! { - let mut peripherals = Peripherals::take().unwrap(); - let core_peripherals = CorePeripherals::take().unwrap(); - - let mut clocks = GenericClockController::with_internal_32kosc( - peripherals.GCLK, - &mut peripherals.MCLK, - &mut peripherals.OSC32KCTRL, - &mut peripherals.OSCCTRL, - &mut peripherals.NVMCTRL, - ); - - let mut delay = Delay::new(core_peripherals.SYST, &mut clocks); - let mut pins = Pins::new(peripherals.PORT).split(); - - // neopixels - let timer = SpinTimer::new(4); - let mut neopixel = pins.neopixel.init(timer, &mut pins.port); - - // i2c - let i2c = pins.i2c.init( - &mut clocks, - KiloHertz(400), - peripherals.SERCOM2, - &mut peripherals.MCLK, - &mut pins.port, - ); - - let mut lis3dh = Lis3dh::new(i2c, 0x19).unwrap(); - lis3dh.set_range(lis3dh::Range::G2).unwrap(); - lis3dh.set_datarate(lis3dh::DataRate::Hz_100).unwrap(); - - let mut state = TiltState::new(); - - loop { - let lis = lis3dh.acceleration().unwrap(); - - let (pos, j) = state.update(lis.x); - - // iterate through neopixels and paint the one led - let _ = neopixel.write((0..5).map(|i| { - if i == pos { - hsv2rgb(Hsv { - hue: j, - sat: 255, - val: 32, - }) - } else { - RGB8::default() - } - })); - - //don't update faster than the accell is reading - delay.delay_ms(10u8); - } -} - -pub struct TiltState { - pos: usize, - tilt: i16, - j: u8, -} - -impl TiltState { - // start at the middle pixel - const fn new() -> TiltState { - TiltState { - pos: 2, - tilt: 0, - j: 0, - } - } - - fn update(&mut self, value: i16) -> (usize, u8) { - //what about like.. momentum, more angle or longer its been at angle stops - // slower like.. steps larger so it gets easier. also on a bigger number - // tilt? - - // naive solution.. threshold tilt - // better.. delay filter? - - // actually 2 thresholds, first you have to be tilted enough (gt / lt 1000) to - // be counted - if value > 1000 { - self.tilt += 1; - } else if value < -1000 { - self.tilt -= 1; - } - - // then we need threshold amount of counted tilts to inc/dec position - if self.tilt.abs() > 20 { - //todo clamp is nightly - if self.tilt.is_negative() { - if self.pos > 0 { - self.pos -= 1; - } - } else { - if self.pos < 4 { - self.pos += 1; - } - } - self.tilt = 0; - } - - //incremement the hue easing - self.j = self.j.wrapping_add(1); - (self.pos, self.j) - } -} diff --git a/boards/pygamer/examples/pwm_tc4.rs b/boards/pygamer/examples/pwm_tc4.rs index 812ebf75ac29..e63f9001acde 100644 --- a/boards/pygamer/examples/pwm_tc4.rs +++ b/boards/pygamer/examples/pwm_tc4.rs @@ -3,9 +3,10 @@ #![no_std] #![no_main] +use bsp::{entry, hal, pac, Pins}; #[cfg(not(feature = "panic_led"))] use panic_halt as _; -use pygamer::{entry, hal, pac, Pins}; +use pygamer as bsp; use core::f32::consts::FRAC_PI_2; use hal::clock::GenericClockController; @@ -30,15 +31,15 @@ fn main() -> ! { let mut delay = Delay::new(core.SYST, &mut clocks); delay.delay_ms(400u16); - let mut pins = Pins::new(peripherals.PORT); + let pins = Pins::new(peripherals.PORT); let gclk = clocks.gclk0(); let mut pwm0 = Pwm4::new( &clocks.tc4_tc5(&gclk).unwrap(), - 1.khz(), + 1.kHz(), peripherals.TC4, - TC4Pinout::Pa23(pins.d13.into_function_e(&mut pins.port)), + TC4Pinout::Pa23(pins.d13), &mut peripherals.MCLK, ); let max_duty = pwm0.get_max_duty(); diff --git a/boards/pygamer/examples/pwm_tcc0.rs b/boards/pygamer/examples/pwm_tcc0.rs index b2c1d279bf5b..ffc50d96ada4 100644 --- a/boards/pygamer/examples/pwm_tcc0.rs +++ b/boards/pygamer/examples/pwm_tcc0.rs @@ -3,9 +3,10 @@ #![no_std] #![no_main] +use bsp::{entry, hal, pac, Pins, RedLedTcc0}; #[cfg(not(feature = "panic_led"))] use panic_halt as _; -use pygamer::{entry, hal, pac, Pins}; +use pygamer as bsp; use core::f32::consts::FRAC_PI_2; use hal::clock::GenericClockController; @@ -30,15 +31,17 @@ fn main() -> ! { let mut delay = Delay::new(core.SYST, &mut clocks); delay.delay_ms(400u16); - let mut pins = Pins::new(peripherals.PORT); + let pins = Pins::new(peripherals.PORT); let gclk = clocks.gclk0(); + let tcc0_pin: RedLedTcc0 = pins.d13.into(); + let mut pwm0 = Tcc0Pwm::new( &clocks.tcc0_tcc1(&gclk).unwrap(), - 1.khz(), + 1.kHz(), peripherals.TCC0, - TCC0Pinout::Pa23(pins.d13.into_function_g(&mut pins.port)), + TCC0Pinout::Pa23(tcc0_pin), &mut peripherals.MCLK, ); let max_duty = pwm0.get_max_duty(); diff --git a/boards/pygamer/examples/qspi.rs b/boards/pygamer/examples/qspi.rs index f62ccae378cd..c86d75cd6faf 100644 --- a/boards/pygamer/examples/qspi.rs +++ b/boards/pygamer/examples/qspi.rs @@ -22,9 +22,10 @@ #![no_std] #![no_main] +use bsp::{entry, hal, pac, Pins}; #[cfg(not(feature = "panic_led"))] use panic_halt as _; -use pygamer::{entry, hal, pac, Pins}; +use pygamer as bsp; use hal::clock::GenericClockController; use hal::delay::Delay; @@ -45,11 +46,9 @@ fn main() -> ! { ); let mut delay = Delay::new(core.SYST, &mut clocks); - let mut sets = Pins::new(peripherals.PORT).split(); + let sets = Pins::new(peripherals.PORT).split(); - let mut flash = sets - .flash - .init(&mut peripherals.MCLK, &mut sets.port, peripherals.QSPI); + let mut flash = sets.flash.init(&mut peripherals.MCLK, peripherals.QSPI); // Startup delay. Can't find documented but Adafruit use 5ms delay.delay_ms(5u8); diff --git a/boards/pygamer/examples/sd_card.rs b/boards/pygamer/examples/sd_card.rs index 2cfe1c595432..6db1659bacd6 100644 --- a/boards/pygamer/examples/sd_card.rs +++ b/boards/pygamer/examples/sd_card.rs @@ -1,29 +1,35 @@ -//! Place a bitmap image on the screen. Ferris pngs from https://rustacean.net/ -//! Convert png to .bmp bytes +//! Place a series of bitmap images on the screen +//! +//! Ferris pngs from , convert png to .bmp bytes: //! * Resize and export images directly from image editor by saving as .bmp and //! choosing 16bit R5 G6 B5 //! * OR Convert with imagemagick: convert rustacean-flat-noshadow.png -type //! truecolor -define bmp:subtype=RGB565 -depth 16 -strip -resize 86x64 //! ferris.bmp -//! -//! cp ferris*.bmp /Volumes/SDCARD/ +//! * SD card should have one (or at least, the first) primary partition of type +//! W95 FAT32, formatted eg `sudo mkfs.fat /dev/path/to/sdcardp1` +//! * Put assets/ferris*.bmp in the root directory of the sd card `cp +//! assets/ferris*.bmp /Volumes/SDCARD/` #![no_std] #![no_main] +use bsp::{entry, hal, pac, Pins, RedLed}; #[cfg(not(feature = "panic_led"))] use panic_halt as _; -use pygamer::{entry, hal, pac, Pins}; +use pygamer as bsp; use embedded_graphics::prelude::*; use embedded_graphics::primitives::{PrimitiveStyleBuilder, Rectangle}; use embedded_graphics::{image::Image, pixelcolor::Rgb565}; -use embedded_sdmmc::{TimeSource, Timestamp, VolumeIdx}; +use embedded_hal_bus::spi::ExclusiveDevice; +use embedded_sdmmc::{Mode, TimeSource, Timestamp, VolumeIdx, VolumeManager}; use hal::clock::GenericClockController; use hal::delay::Delay; -use hal::ehal::digital::v1_compat::OldOutputPin; +use hal::nb; use hal::prelude::*; -use hal::time::MegaHertz; +use hal::time::Hertz; +use hal::timer::TimerCounter; use pac::{CorePeripherals, Peripherals}; use tinybmp::Bmp; @@ -40,20 +46,9 @@ fn main() -> ! { ); let mut delay = Delay::new(core.SYST, &mut clocks); - let mut pins = Pins::new(peripherals.PORT).split(); - - let mut red_led = pins.led_pin.into_open_drain_output(&mut pins.port); + let pins = Pins::new(peripherals.PORT).split(); - let sdmmc_cs: OldOutputPin<_> = pins.sd_cs_pin.into_push_pull_output(&mut pins.port).into(); - let sdmmc_spi = pins.spi.init( - &mut clocks, - MegaHertz(3), - peripherals.SERCOM1, - &mut peripherals.MCLK, - &mut pins.port, - ); - let mut cont = - embedded_sdmmc::Controller::new(embedded_sdmmc::SdMmcSpi::new(sdmmc_spi, sdmmc_cs), Clock); + let mut red_led: RedLed = pins.led_pin.into(); let (mut display, _backlight) = pins .display @@ -63,7 +58,6 @@ fn main() -> ! { &mut peripherals.MCLK, peripherals.TC2, &mut delay, - &mut pins.port, ) .unwrap(); @@ -77,9 +71,30 @@ fn main() -> ! { .draw(&mut display) .unwrap(); - cont.device().init().unwrap(); - let mut volume = cont.get_volume(VolumeIdx(0)).unwrap(); - let dir = cont.open_root_dir(&volume).unwrap(); + let gclk0 = clocks.gclk0(); + let timer_clock = clocks.tc4_tc5(&gclk0).unwrap(); + let mut khz_timer = TimerCounter::tc4_(&timer_clock, peripherals.TC4, &mut peripherals.MCLK); + InterruptDrivenTimer::start(&mut khz_timer, Hertz::kHz(1).into_duration()); + + let sdmmc_cs = pins.sd_cs_pin.into_push_pull_output(); + let sdmmc_spi_bus = pins.spi.init( + &mut clocks, + 3.MHz(), + peripherals.SERCOM1, + &mut peripherals.MCLK, + ); + + let sdmmc_spi = + ExclusiveDevice::new_no_delay(sdmmc_spi_bus, sdmmc_cs).expect("Failed to create SpiDevice"); + + let card = embedded_sdmmc::SdCard::new(sdmmc_spi, delay); + + let mut volume_mgr = VolumeManager::new(card, Clock {}); + let mut volume = volume_mgr + .open_volume(VolumeIdx(0)) + .expect("Failed to open volume"); + + let mut dir = volume.open_root_dir().expect("Failed to open root dir"); let mut scratch = [0u8; 11008]; @@ -88,22 +103,22 @@ fn main() -> ! { loop { for image in images.iter() { - if let Ok(mut f) = - cont.open_file_in_dir(&mut volume, &dir, image, embedded_sdmmc::Mode::ReadOnly) - { - let _ = cont.read(&volume, &mut f, &mut scratch); - - let raw_image: Bmp = Bmp::from_slice(&scratch).unwrap(); - - let ferris = Image::new(&raw_image, Point::new(32, 32)); - - let _ = ferris.draw(&mut display); + match dir.open_file_in_dir(*image, Mode::ReadOnly) { + Ok(mut f) => { + let _ = f.read(&mut scratch); + let raw_image: Bmp = Bmp::from_slice(&scratch).unwrap(); + let ferris = Image::new(&raw_image, Point::new(32, 32)); + let _ = ferris.draw(&mut display); + let _ = f.close(); + } + Err(_err) => { + red_led.set_high().ok(); + } + } - cont.close_file(&volume, f).ok(); - } else { - let _ = red_led.set_high(); + for _ in 0..100 { + nb::block!(InterruptDrivenTimer::wait(&mut khz_timer)).unwrap(); } - delay.delay_ms(200u8); } } } diff --git a/boards/pygamer/examples/timer.rs b/boards/pygamer/examples/timer.rs index 30587a96d1ff..6b21d22d7566 100644 --- a/boards/pygamer/examples/timer.rs +++ b/boards/pygamer/examples/timer.rs @@ -4,13 +4,17 @@ #![no_std] #![no_main] +use bsp::{entry, hal, pac, Pins, RedLed}; #[cfg(not(feature = "panic_led"))] use panic_halt as _; -use pygamer::{entry, hal, pac, Pins}; +use pygamer as bsp; use hal::clock::GenericClockController; -use hal::prelude::*; +use hal::ehal::digital::OutputPin; +use hal::nb; +use hal::time::Hertz; use hal::timer::TimerCounter; +use hal::timer_traits::InterruptDrivenTimer; use pac::Peripherals; #[entry] @@ -23,19 +27,32 @@ fn main() -> ! { &mut peripherals.OSCCTRL, &mut peripherals.NVMCTRL, ); - let mut pins = Pins::new(peripherals.PORT); + let pins = Pins::new(peripherals.PORT); let gclk0 = clocks.gclk0(); let timer_clock = clocks.tc2_tc3(&gclk0).unwrap(); let mut timer = TimerCounter::tc3_(&timer_clock, peripherals.TC3, &mut peripherals.MCLK); - timer.start(250.khz()); - let mut d5 = pins.d5.into_push_pull_output(&mut pins.port); + timer.start(Hertz::kHz(250).into_duration()); + let mut d13: RedLed = pins.d13.into(); - //50% duty cycle, so 500khz period + // Cycle red LED through 50%, 100%, 0% loop { - let _ = d5.set_high(); - let _ = nb::block!(timer.wait()); - let _ = d5.set_low(); - let _ = nb::block!(timer.wait()); + for _ in 0..125000 { + //50% duty cycle, so 125khz period + let _ = d13.set_high(); + let _ = nb::block!(timer.wait()); + let _ = d13.set_low(); + let _ = nb::block!(timer.wait()); + } + let _ = d13.set_high(); + for _ in 0..125000 { + let _ = nb::block!(timer.wait()); + let _ = nb::block!(timer.wait()); + } + let _ = d13.set_low(); + for _ in 0..125000 { + let _ = nb::block!(timer.wait()); + let _ = nb::block!(timer.wait()); + } } } diff --git a/boards/pygamer/examples/usb_poll.rs b/boards/pygamer/examples/usb_poll.rs index 6c8d51a783c9..c4b1b9ac437b 100644 --- a/boards/pygamer/examples/usb_poll.rs +++ b/boards/pygamer/examples/usb_poll.rs @@ -4,9 +4,10 @@ #![no_std] #![no_main] +use bsp::{entry, hal, pac, Pins, RedLed}; #[cfg(not(feature = "panic_led"))] use panic_halt as _; -use pygamer::{entry, hal, pac, Pins}; +use pygamer as bsp; use hal::clock::GenericClockController; use hal::prelude::*; @@ -26,22 +27,27 @@ fn main() -> ! { &mut peripherals.NVMCTRL, ); - let mut pins = Pins::new(peripherals.PORT).split(); + let pins = Pins::new(peripherals.PORT).split(); let usb_bus = pins .usb .init(peripherals.USB, &mut clocks, &mut peripherals.MCLK); let mut serial = SerialPort::new(&usb_bus); - let mut led = pins.led_pin.into_open_drain_output(&mut pins.port); + let mut led: RedLed = pins.led_pin.into(); let mut usb_dev = UsbDeviceBuilder::new(&usb_bus, UsbVidPid(0x16c0, 0x27dd)) - .manufacturer("Fake company") - .product("Serial port") - .serial_number("TEST") + .strings(&[StringDescriptors::new(LangID::EN) + .manufacturer("Fake company") + .product("Serial port") + .serial_number("TEST")]) + .expect("Failed to set strings") .device_class(USB_CLASS_CDC) .build(); + let mut led_state = false; + let _ = led.set_low(); // Turn off + loop { if !usb_dev.poll(&mut [&mut serial]) { continue; @@ -51,10 +57,16 @@ fn main() -> ! { match serial.read(&mut buf) { Ok(count) if count > 0 => { - let _ = led.set_high(); // Turn on - // Echo back in upper case for c in buf[0..count].iter_mut() { + led_state = if led_state { + let _ = led.set_low(); // Turn off + false + } else { + let _ = led.set_high(); // Turn on + true + }; + if 0x61 <= *c && *c <= 0x7a { *c &= !0x20; } @@ -72,7 +84,5 @@ fn main() -> ! { } _ => {} } - - let _ = led.set_low(); // Turn off } } diff --git a/boards/pygamer/examples/usb_serial.rs b/boards/pygamer/examples/usb_serial.rs deleted file mode 100644 index bf6b6393da13..000000000000 --- a/boards/pygamer/examples/usb_serial.rs +++ /dev/null @@ -1,133 +0,0 @@ -//! Makes the pygamer appear as a USB serial port. The color of the -//! neopixel LED can be changed by sending bytes to the serial port. -//! -//! Sending the characters R, G, and O set the LED red, green, and off -//! respectively. For example: -//! $> sudo stty -F /dev/ttyACM0 115200 raw -echo -//! $> sudo bash -c "echo 'R' > /dev/ttyACM0" -//! $> sudo bash -c "echo 'G' > /dev/ttyACM0" -//! $> sudo bash -c "echo 'O' > /dev/ttyACM0" -//! -//! Note leds may appear white during debug. Either build for release or add -//! opt-level = 2 to profile.dev in Cargo.toml - -#![no_std] -#![no_main] - -#[cfg(not(feature = "panic_led"))] -use panic_halt as _; -use pygamer::{entry, hal, pac, Pins}; - -use cortex_m::interrupt::free as disable_interrupts; -use cortex_m::peripheral::NVIC; -use hal::clock::GenericClockController; -use hal::timer::SpinTimer; -use hal::usb::UsbBus; -use pac::{interrupt, CorePeripherals, Peripherals}; -use smart_leds::{colors, hsv::RGB8, SmartLedsWrite}; -use usb_device::bus::UsbBusAllocator; -use usb_device::prelude::*; -use usbd_serial::{SerialPort, USB_CLASS_CDC}; - -#[entry] -fn main() -> ! { - let mut peripherals = Peripherals::take().unwrap(); - let mut core = CorePeripherals::take().unwrap(); - let mut clocks = GenericClockController::with_internal_32kosc( - peripherals.GCLK, - &mut peripherals.MCLK, - &mut peripherals.OSC32KCTRL, - &mut peripherals.OSCCTRL, - &mut peripherals.NVMCTRL, - ); - let mut pins = Pins::new(peripherals.PORT).split(); - - let timer = SpinTimer::new(4); - let mut neopixel = pins.neopixel.init(timer, &mut pins.port); - - let _ = neopixel.write((0..5).map(|_| RGB8::default())); - - let bus_allocator = unsafe { - USB_ALLOCATOR = Some( - pins.usb - .init(peripherals.USB, &mut clocks, &mut peripherals.MCLK), - ); - USB_ALLOCATOR.as_ref().unwrap() - }; - - unsafe { - USB_SERIAL = Some(SerialPort::new(&bus_allocator)); - USB_BUS = Some( - UsbDeviceBuilder::new(&bus_allocator, UsbVidPid(0x16c0, 0x27dd)) - .manufacturer("Fake company") - .product("Serial port") - .serial_number("TEST") - .device_class(USB_CLASS_CDC) - .build(), - ); - } - - unsafe { - core.NVIC.set_priority(interrupt::USB_OTHER, 1); - core.NVIC.set_priority(interrupt::USB_TRCPT0, 1); - core.NVIC.set_priority(interrupt::USB_TRCPT1, 1); - NVIC::unmask(interrupt::USB_OTHER); - NVIC::unmask(interrupt::USB_TRCPT0); - NVIC::unmask(interrupt::USB_TRCPT1); - } - - loop { - let pending = disable_interrupts(|_| unsafe { - let pending = PENDING_COLOR; - PENDING_COLOR = None; - pending - }); - if let Some(color) = pending { - let _ = neopixel.write((0..5).map(|_| color)); - } - } -} - -static mut USB_ALLOCATOR: Option> = None; -static mut USB_BUS: Option> = None; -static mut USB_SERIAL: Option> = None; -static mut PENDING_COLOR: Option = None; - -fn poll_usb() { - unsafe { - USB_BUS.as_mut().map(|usb_dev| { - USB_SERIAL.as_mut().map(|serial| { - usb_dev.poll(&mut [serial]); - - let mut buf = [0u8; 64]; - - if let Ok(count) = serial.read(&mut buf) { - let last = buf[count - 1] as char; - let color = match last { - 'R' => colors::RED, - 'G' => colors::GREEN, - 'O' => colors::ORANGE, - _ => RGB8::default(), - }; - - PENDING_COLOR = Some(color); - }; - }); - }); - }; -} - -#[interrupt] -fn USB_OTHER() { - poll_usb(); -} - -#[interrupt] -fn USB_TRCPT0() { - poll_usb(); -} - -#[interrupt] -fn USB_TRCPT1() { - poll_usb(); -} diff --git a/boards/pygamer/src/buttons.rs b/boards/pygamer/src/buttons.rs index 39672f809c94..d714005dd234 100644 --- a/boards/pygamer/src/buttons.rs +++ b/boards/pygamer/src/buttons.rs @@ -1,10 +1,10 @@ use super::hal; use cortex_m::asm::delay as cycle_delay; -use gpio::{Floating, Input, Output, PushPull}; -use hal::gpio::{self, *}; use hal::prelude::*; +use super::pins::{ButtonClock, ButtonLatch, ButtonOut}; + #[derive(Debug, PartialEq)] pub enum Keys { SelectDown, @@ -100,11 +100,11 @@ impl Iterator for ButtonIter { pub struct ButtonReader { /// Button Latch - pub latch: Pb0>, + pub latch: ButtonLatch, /// Button Out - pub data_in: Pb30>, + pub data_in: ButtonOut, /// Button Clock - pub clock: Pb31>, + pub clock: ButtonClock, pub last: u8, } diff --git a/boards/pygamer/src/lib.rs b/boards/pygamer/src/lib.rs index c0a753af2afa..13f23cfc342c 100644 --- a/boards/pygamer/src/lib.rs +++ b/boards/pygamer/src/lib.rs @@ -1,20 +1,17 @@ #![no_std] #![recursion_limit = "1024"] -#[cfg(feature = "unproven")] -pub mod buttons; - -pub mod pins; -pub use atsamd_hal as hal; - #[cfg(feature = "rt")] pub use cortex_m_rt::entry; -pub use pins::Pins; - -pub use hal::common::*; +pub use atsamd_hal as hal; pub use hal::pac; -pub use hal::samd51::*; + +pub mod buttons; +pub mod pins; + +pub use buttons::*; +pub use pins::*; pub mod util { /// Analogous to Arduinos map function @@ -34,11 +31,11 @@ pub mod util { #[inline(never)] #[panic_handler] fn panic(_info: &core::panic::PanicInfo) -> ! { - use hal::ehal::digital::v2::OutputPin; + use hal::ehal::digital::OutputPin; let peripherals = unsafe { crate::pac::Peripherals::steal() }; - let mut pins = Pins::new(peripherals.PORT); - let _ = pins.d13.into_open_drain_output(&mut pins.port).set_high(); + let pins = Pins::new(peripherals.PORT); + pins.d13.into_push_pull_output().set_high().ok(); cortex_m::asm::udf() } diff --git a/boards/pygamer/src/pins.rs b/boards/pygamer/src/pins.rs index b6d3a79b3909..6054a6408c61 100644 --- a/boards/pygamer/src/pins.rs +++ b/boards/pygamer/src/pins.rs @@ -2,147 +2,421 @@ use super::{hal, pac}; -use gpio::{Floating, Input, Output, Port, PushPull}; -use hal::clock::GenericClockController; -use hal::define_pins; -use hal::ehal::{digital::v1_compat::OldOutputPin, timer::CountDown, timer::Periodic}; -use hal::gpio::{self, *}; -use hal::hal::spi; -use hal::prelude::*; -use hal::sercom::{I2CMaster2, PadPin, SPIMaster1, SPIMaster4, UART5}; -use hal::{qspi, time::Hertz}; use pac::{MCLK, QSPI}; + +use hal::prelude::*; + +use hal::clock::GenericClockController; +use hal::gpio::PA01; +use hal::pwm; +use hal::qspi; +use hal::sercom::uart::{self, BaudMode, Oversampling}; +use hal::sercom::{i2c, spi, IoSet1, Sercom1, Sercom4, UndocIoSet1}; +use hal::time::Hertz; +use hal::typelevel::NoneT; + use st7735_lcd::{Orientation, ST7735}; -use ws2812_timer_delay as ws2812; #[cfg(feature = "usb")] use hal::usb::usb_device::bus::UsbBusAllocator; #[cfg(feature = "usb")] pub use hal::usb::UsbBus; #[cfg(feature = "usb")] -use pac::gclk::{genctrl::SRC_A, pchctrl::GEN_A}; +use pac::gclk::{genctrl::SRCSELECT_A, pchctrl::GENSELECT_A}; + +hal::bsp_peripherals!( + SERCOM2 { I2cSercom } + SERCOM5 { UartSercom } +); -#[cfg(feature = "unproven")] pub use crate::buttons::ButtonReader; -#[cfg(feature = "unproven")] pub use crate::buttons::Keys; -#[cfg(feature = "unproven")] use hal::pwm::Pwm2; -#[cfg(feature = "unproven")] use pac::{ADC0, ADC1}; -define_pins!( - /// Maps the pins to their arduino names and - /// the numbers printed on the board. - struct Pins, - pac: pac, - - /// Analog pin 0. Can act as a true analog output - /// as it has a DAC (which is not currently supported - /// by this hal) as well as input. - pin speaker = a2, - /// enable speaker amplifier - pin speaker_enable = a27, - - /// Analog pin 1 - pin a1 = a5, - /// Analog pin 2 - pin a2 = b8, - /// Analog pin 3 - pin a3 = b9, - /// Analog pin 4 - pin a4 = a4, - /// Analog pin 5 - pin a5 = a6, - /// Battery Measure (also Analog pin 6) - pin battery = b1, - /// Light sensor (also Analog pin 7) - pin light = b4, - /// Digital pin 2 (also Analog pin 8) - pin d2 = b3, - /// Digital pin 3 (also Analog pin 9) - pin d3 = b2, - /// Digital pin 5 - pin d5 = a16, - /// Digital pin 6 - pin d6 = a18, - /// Accelerometer interrupt pin (also d7) - pin accel_irq = b14, - /// Neopixel data line (controls all 5 neopixels, also d8) - pin neopixel = a15, - /// Digital pin 9 - pin d9 = a19, - /// Digital pin 10 - pin d10 = a20, - /// Digital pin 11 - pin d11 = a21, - /// Digital pin 12 - pin d12 = a22, - /// D13 LED/JACDAC - pin d13 = a23, - - // TFT(Thin-film-transistor liquid-crystal display) control pins - /// TFT MOSI - pin tft_mosi = b15, - /// TFT SCK - pin tft_sck = b13, - /// TFT Reset - pin tft_reset = a0, - /// TFT DC - pin tft_dc = b5, - /// TFT CS - pin tft_cs = b12, - /// TFT Backlight (also Analog pin 7) - pin tft_backlight = a1, - - // UART - Universal Asynchronous Receiver/Transmitter - /// Pin TX (d1) - pin tx = b16, - /// Pin RX (d0) - pin rx = b17, - - // SPI - Serial Peripheral Interface (connected to sd card slot) - /// Pin MISO - pin miso = b22, - /// Pin MOSI - pin mosi = b23, - /// Pin SCK - pin sck = a17, - - // I2C (connected to LIS3DH accelerometer) - /// STEMMA SDA - pin sda = a12, - /// STEMMA SCL - pin scl = a13, - - /// USB D- pin - pin usb_dm = a24, - /// USB D+ pin - pin usb_dp = a25, - - /// SD card chip select (also d4) - pin sd_cs = a14, - - /// Joystick X - pin joy_x = b7, - /// Joystick Y - pin joy_y = b6, - - /// Button Latch - pin button_latch = b0, - /// Button Out - pin button_out = b30, - /// Button Clock - pin button_clock = b31, - - /// qspi flash - pin flash_sck = b10, - pin flash_cs = b11, - pin flash_d0 = a8, - pin flash_d1 = a9, - pin flash_d2 = a10, - pin flash_d3 = a11, -); +/// Pin constants and type aliases +pub use aliases::*; + +pub mod aliases { + use super::hal::bsp_pins; + + bsp_pins!( + + /// Analog pin 0. Can act as a true analog output + /// as it has a DAC (which is not currently supported + /// by this hal) as well as input. + PA02 { + name: speaker + aliases: { + Reset: SpeakerReset + } + }, + /// enable speaker amplifier + PA27 { + name: speaker_enable + aliases: { + Reset: SpeakerEnableReset + } + }, + + /// Analog pin 1 + PA05 { + name: a1 + aliases: { + Reset: A1Reset + } + }, + /// Analog pin 2 + PB08 { + name: a2 + aliases: { + Reset: A2Reset + } + }, + /// Analog pin 3 + PB09 { + name: a3 + aliases: { + Reset: A3Reset + } + }, + /// Analog pin 4 + PA04 { + name: a4 + aliases: { + Reset: A4Reset + } + }, + /// Analog pin 5 + PA06 { + name: a5 + aliases: { + Reset: A5Reset + } + }, + /// Battery Measure (also Analog pin 6) + PB01 { + name: battery + aliases: { + AlternateB: BatteryPin, + Reset: BatteryReset + } + }, + /// Light sensor (also Analog pin 7) + PB04 { + name: light + aliases: { + Reset: LightReset, + AlternateB: LightSensor + } + }, + /// Digital pin 2 (also Analog pin 8) + PB03 { + name: d2 + aliases: { + Reset: D2Reset + } + }, + /// Digital pin 3 (also Analog pin 9) + PB02 { + name: d3 + aliases: { + Reset: D3Reset + } + }, + /// Digital pin 5 + PA16 { + name: d5 + aliases: { + Reset: D5Reset, + AlternateM: GclkOut + } + }, + /// Digital pin 6 + PA18 { + name: d6 + aliases: { + Reset: D6Reset + } + }, + /// Accelerometer interrupt pin (also d7) + PB14 { + name: accel_irq + aliases: { + Reset: AccelIrqReset + } + }, + PA15 { + /// Neopixel data line (controls all 5 neopixels, also d8) + name: neopixel + aliases: { + PushPullOutput: NeopixelPin, + Reset: NeopixelReset + } + }, + /// Digital pin 9 + PA19 { + name: d9 + aliases: { + Reset: D9Reset + } + }, + /// Digital pin 10 + PA20 { + name: d10 + aliases: { + Reset: D10Reset + } + }, + /// Digital pin 11 + PA21 { + name: d11 + aliases: { + Reset: D11Reset + } + }, + /// Digital pin 12 + PA22 { + name: d12 + aliases: { + Reset: D12Reset + } + }, + /// D13 LED/JACDAC + PA23 { + name: d13 + aliases: { + PushPullOutput: RedLed, + Reset: D13Reset, + AlternateE: Tc4Pwm, + AlternateG: RedLedTcc0 + } + }, + + // TFT(Thin-film-transistor liquid-crystal display) control pins + PB15 { + /// TFT MOSI + name: tft_mosi, + aliases: { + AlternateC: TftMosi, + Reset: TftMosiReset + } + }, + PB13 { + /// TFT SCLK + name: tft_sclk + aliases: { + AlternateC: TftSclk, + Reset: TftSclkReset + } + }, + PA00 { + /// TFT Reset + name: tft_reset + aliases: { + PushPullOutput: TftReset, + Reset: TftResetReset + } + }, + PB05 { + /// TFT DC + name: tft_dc + aliases: { + PushPullOutput: TftDc, + Reset: TftDcReset + } + }, + PB12 { + /// TFT CS + name: tft_cs + aliases: { + PushPullOutput: TftCs, + Reset: TftCsReset + } + }, + PA01 { + /// TFT Backlight (also Analog pin 7) + name: tft_backlight + aliases: { + AlternateE: TftBacklight, + Reset: TftBacklightReset + } + }, + + // UART - Universal Asynchronous Receiver/Transmitter + PB16 { + /// Pin TX (d1) + name: tx + aliases: { + AlternateC: UartTx, + Reset: UartTxReset + } + }, + PB17 { + /// Pin RX (d0) + name: rx + aliases: { + AlternateC: UartRx, + Reset: UartRxReset + } + }, + + // SPI - Serial Peripheral Interface (connected to sd card slot) + PB22 { + /// Pin MISO + name: miso + aliases: { + AlternateC: SpiMiso, + Reset: SpiMisoReset + } + }, + PB23 { + /// Pin MOSI + name: mosi + aliases: { + AlternateC: SpiMosi, + Reset: SpiMosiReset + } + }, + PA17 { + /// Pin SCK + name: sclk + aliases: { + AlternateC: SpiSclk, + Reset: SpiSclkReset + } + }, + + // I2C (connected to LIS3DH accelerometer) + PA12 { + /// STEMMA SDA + name: sda + aliases: { + AlternateC: Sda, + Reset: SdaReset + } + }, + PA13 { + /// STEMMA SCL + name: scl + aliases: { + AlternateC: Scl, + Reset: SclReset + } + }, + + PA24 { + /// USB D- pin + name: usb_dm + aliases: { + AlternateH: UsbDm, + Reset: UsbDmReset + } + }, + PA25 { + /// USB D+ pin + name: usb_dp + aliases: { + AlternateH: UsbDp, + Reset: UsbDpReset + } + }, + + /// SD card chip select (also d4) + PA14 { + name: sd_cs + aliases: { + Reset: SdCsReset + } + }, + + PB07 { + /// Joystick X + name: joy_x + aliases: { + AlternateB: JoyX, + Reset: JoyXReset + } + }, + PB06 { + /// Joystick Y + name: joy_y + aliases: { + AlternateB: JoyY, + Reset: JoyYReset + } + }, + + PB00 { + /// Button Latch + name: button_latch + aliases: { + PushPullOutput: ButtonLatch, + Reset: ButtonLatchReset + } + }, + PB30 { + /// Button Out + name: button_out + aliases: { + FloatingInput: ButtonOut, + Reset: ButtonOutReset + } + }, + PB31 { + /// Button Clock + name: button_clock + aliases: { + PushPullOutput: ButtonClock, + Reset: ButtonClockReset + } + }, + + // qspi flash + PB10 { + name: flash_sclk + aliases: { + AlternateH: QspiSclk, + Reset: QspiSclkReset + } + }, + PB11 { + name: flash_cs + aliases: { + AlternateH: QspiCs, + Reset: QspiCsReset + } + }, + PA08 { + name: flash_d0 + aliases: { + AlternateH: QspiD0, + Reset: QspiD0Reset + } + }, + PA09 { + name: flash_d1 + aliases: { + AlternateH: QspiD1, + Reset: QspiD1Reset + } + }, + PA10 { + name: flash_d2 + aliases: { + AlternateH: QspiD2, + Reset: QspiD2Reset + } + }, + PA11 { + name: flash_d3 + aliases: { + AlternateH: QspiD3, + Reset: QspiD3Reset + } + }, + ); +} impl Pins { /// Split the device pins into subsets @@ -153,9 +427,8 @@ impl Pins { }; let display = Display { - accel_irq: self.accel_irq, tft_mosi: self.tft_mosi, - tft_sck: self.tft_sck, + tft_sclk: self.tft_sclk, tft_reset: self.tft_reset, tft_cs: self.tft_cs, tft_dc: self.tft_dc, @@ -182,7 +455,7 @@ impl Pins { }; let flash = QSPIFlash { - sck: self.flash_sck, + sclk: self.flash_sclk, cs: self.flash_cs, data0: self.flash_d0, data1: self.flash_d1, @@ -191,7 +464,7 @@ impl Pins { }; let spi = SPI { - sck: self.sck, + sclk: self.sclk, mosi: self.mosi, miso: self.miso, }; @@ -231,7 +504,6 @@ impl Pins { }; Sets { - port: self.port, display, led_pin: self.d13, neopixel, @@ -254,26 +526,23 @@ impl Pins { /// Sets of pins split apart by category pub struct Sets { - /// Port - pub port: Port, - /// LCD Display pub display: Display, /// Red Led - pub led_pin: Pa23>, + pub led_pin: D13Reset, /// Neopixel (RGB LED) pins pub neopixel: Neopixel, /// Analog Light Sensor - pub light_pin: Pb4>, + pub light_pin: LightReset, /// I2C (connected to LIS3DH accelerometer and "Stemma" port) pub i2c: I2C, /// SD Card CS pin - pub sd_cs_pin: Pa14>, + pub sd_cs_pin: SdCsReset, /// Battery Voltage pub battery: Battery, @@ -306,16 +575,17 @@ pub struct Sets { /// Display pins pub struct Display { - pub accel_irq: Pb14>, // TODO remove once we make miso optional - pub tft_mosi: Pb15>, - pub tft_sck: Pb13>, - pub tft_reset: Pa0>, - pub tft_cs: Pb12>, - pub tft_dc: Pb5>, - pub tft_backlight: Pa1>, + pub tft_mosi: TftMosiReset, + pub tft_sclk: TftSclkReset, + pub tft_reset: TftResetReset, + pub tft_cs: TftCsReset, + pub tft_dc: TftDcReset, + pub tft_backlight: TftBacklightReset, } -#[cfg(feature = "unproven")] +pub type TftPads = spi::Pads; +pub type TftSpi = spi::Spi, spi::Tx>; + impl Display { /// Convenience for setting up the on board display. pub fn init( @@ -325,164 +595,130 @@ impl Display { mclk: &mut pac::MCLK, timer2: pac::TC2, delay: &mut hal::delay::Delay, - port: &mut Port, - ) -> Result< - ( - ST7735< - SPIMaster4< - hal::sercom::Sercom4Pad2>, - hal::sercom::Sercom4Pad3>, - hal::sercom::Sercom4Pad1>, - >, - Pb5>, - Pa0>, - >, - Pwm2, - ), - (), - > { + ) -> Result<(ST7735, Pwm2), ()> { let gclk0 = clocks.gclk0(); - let tft_spi = SPIMaster4::new( - &clocks.sercom4_core(&gclk0).ok_or(())?, - 16.mhz(), - spi::Mode { - phase: spi::Phase::CaptureOnFirstTransition, - polarity: spi::Polarity::IdleLow, - }, - sercom4, - mclk, - ( - self.accel_irq.into_pad(port), - self.tft_mosi.into_pad(port), - self.tft_sck.into_pad(port), - ), + let clock = &clocks.sercom4_core(&gclk0).ok_or(())?; + let pads = spi::Pads::default() + .sclk(self.tft_sclk) + .data_out(self.tft_mosi); + let tft_spi = spi::Config::new(mclk, sercom4, pads, clock.freq()) + .spi_mode(spi::MODE_0) + .baud(16.MHz()) + .enable(); + let mut tft_cs: TftCs = self.tft_cs.into(); + tft_cs.set_low().ok(); + let mut display = st7735_lcd::ST7735::new( + tft_spi, + self.tft_dc.into(), + self.tft_reset.into(), + true, + false, + 160, + 128, ); - - let mut tft_cs = self.tft_cs.into_push_pull_output(port); - tft_cs.set_low()?; - - let tft_dc = self.tft_dc.into_push_pull_output(port); - let tft_reset = self.tft_reset.into_push_pull_output(port); - - let mut display = - st7735_lcd::ST7735::new(tft_spi, tft_dc, tft_reset, true, false, 160, 128); display.init(delay)?; display.set_orientation(&Orientation::LandscapeSwapped)?; - - let tft_backlight = self.tft_backlight.into_function_e(port); - let mut pwm2 = Pwm2::new( - &clocks.tc2_tc3(&gclk0).ok_or(())?, - 1.khz(), - timer2, - hal::pwm::TC2Pinout::Pa1(tft_backlight), - mclk, - ); - + let pwm_clock = &clocks.tc2_tc3(&gclk0).ok_or(())?; + let pwm_pinout = pwm::TC2Pinout::Pa1(self.tft_backlight); + let mut pwm2 = Pwm2::new(pwm_clock, 1.kHz(), timer2, pwm_pinout, mclk); pwm2.set_duty(pwm2.get_max_duty()); - Ok((display, pwm2)) } } /// Neopixel pins pub struct Neopixel { - pub neopixel: Pa15>, -} - -impl Neopixel { - /// Convenience for setting up the onboard neopixels using the provided - /// Timer preconfigured to 3mhz. - pub fn init( - self, - timer: T, - port: &mut Port, - ) -> ws2812::Ws2812>>> { - let neopixel_pin: OldOutputPin<_> = self.neopixel.into_push_pull_output(port).into(); - - ws2812::Ws2812::new(timer, neopixel_pin) - } + pub neopixel: NeopixelReset, } /// SPI pins pub struct SPI { - pub mosi: Pb23>, - pub miso: Pb22>, - pub sck: Pa17>, + pub mosi: SpiMosiReset, + pub miso: SpiMisoReset, + pub sclk: SpiSclkReset, } +/// Pads for the labelled SPI pins +/// +/// According to the datasheet, the combination of PA17, PB22 & PB23 shouldn't +/// work, even though it does. We have added an undocumented `UndocIoSet1` to +/// `Sercom1` for this combination. +pub type SpiPads = spi::Pads; + +/// SPI master for the labelled pins +pub type Spi = spi::Spi, spi::Duplex>; + impl SPI { /// Convenience for setting up the labelled pins to operate /// as an SPI master, running at the specified frequency. - pub fn init>( + pub fn init( self, clocks: &mut GenericClockController, - bus_speed: F, + baud: impl Into, sercom1: pac::SERCOM1, mclk: &mut MCLK, - port: &mut Port, - ) -> SPIMaster1< - hal::sercom::Sercom1Pad2>, - hal::sercom::Sercom1Pad3>, - hal::sercom::Sercom1Pad1>, - > { + ) -> Spi { let gclk0 = clocks.gclk0(); - SPIMaster1::new( - &clocks.sercom1_core(&gclk0).unwrap(), - bus_speed.into(), - spi::Mode { - phase: spi::Phase::CaptureOnFirstTransition, - polarity: spi::Polarity::IdleLow, - }, - sercom1, - mclk, - ( - self.miso.into_pad(port), - self.mosi.into_pad(port), - self.sck.into_pad(port), - ), - ) + let clock = &clocks.sercom1_core(&gclk0).unwrap(); + let pads = spi::Pads::default() + .data_in(self.miso) + .data_out(self.mosi) + .sclk(self.sclk); + spi::Config::new(mclk, sercom1, pads, clock.freq()) + .spi_mode(spi::MODE_0) + .baud(baud.into()) + .enable() } } /// I2C pins pub struct I2C { - pub sda: Pa12>, - pub scl: Pa13>, + pub sda: SdaReset, + pub scl: SclReset, } -impl I2C { - /// Convenience for setting up the labelled SDA, SCL pins to - /// operate as an I2C master running at the specified frequency. - pub fn init>( - self, - clocks: &mut GenericClockController, - bus_speed: F, - sercom2: pac::SERCOM2, - mclk: &mut MCLK, - port: &mut Port, - ) -> I2CMaster2>, hal::sercom::Sercom2Pad1>> { - let gclk0 = clocks.gclk0(); - I2CMaster2::new( - &clocks.sercom2_core(&gclk0).unwrap(), - bus_speed.into(), - sercom2, - mclk, - self.sda.into_pad(port), - self.scl.into_pad(port), - ) - } +/// I2C pads for the labelled I2C peripheral +/// +/// You can use these pads with other, user-defined [`i2c::Config`]urations. +pub type I2cPads = i2c::Pads; + +/// I2C master for the labelled I2C peripheral +/// +/// This type implements [`Read`](ehal::blocking::i2c::Read), +/// [`Write`](ehal::blocking::i2c::Write) and +/// [`WriteRead`](ehal::blocking::i2c::WriteRead). +pub type I2c = i2c::I2c>; + +/// Convenience for setting up the labelled SDA, SCL pins to +/// operate as an I2C master running at the specified frequency. +pub fn i2c_master( + clocks: &mut GenericClockController, + baud: impl Into, + sercom: I2cSercom, + mclk: &mut pac::MCLK, + sda: impl Into, + scl: impl Into, +) -> I2c { + let gclk0 = clocks.gclk0(); + let clock = &clocks.sercom2_core(&gclk0).unwrap(); + let freq = clock.freq(); + let baud = baud.into(); + let pads = i2c::Pads::new(sda.into(), scl.into()); + i2c::Config::new(mclk, sercom, pads, freq) + .baud(baud) + .enable() } /// Speaker pins pub struct Speaker { - pub speaker: Pa2>, - pub enable: Pa27>, + pub speaker: SpeakerReset, + pub enable: SpeakerEnableReset, } /// USB pins pub struct USB { - pub dm: Pa24>, - pub dp: Pa25>, + pub dm: UsbDmReset, + pub dp: UsbDpReset, } impl USB { @@ -495,81 +731,85 @@ impl USB { clocks: &mut GenericClockController, mclk: &mut MCLK, ) -> UsbBusAllocator { - clocks.configure_gclk_divider_and_source(GEN_A::GCLK2, 1, SRC_A::DFLL, false); - let usb_gclk = clocks.get_gclk(GEN_A::GCLK2).unwrap(); + clocks.configure_gclk_divider_and_source(GENSELECT_A::GCLK2, 1, SRCSELECT_A::DFLL, false); + let usb_gclk = clocks.get_gclk(GENSELECT_A::GCLK2).unwrap(); let usb_clock = &clocks.usb(&usb_gclk).unwrap(); - - UsbBusAllocator::new(UsbBus::new(usb_clock, mclk, self.dm, self.dp, usb)) + let (dm, dp): (UsbDm, UsbDp) = (self.dm.into(), self.dp.into()); + UsbBusAllocator::new(UsbBus::new(usb_clock, mclk, dm, dp, usb)) } } /// UART pins pub struct UART { - pub tx: Pb16>, - pub rx: Pb17>, + pub tx: UartTxReset, + pub rx: UartRxReset, } +/// UART Pads for the labelled UART peripheral +pub type UartPads = uart::Pads; + +/// UART device for the labelled RX & TX pins +pub type Uart = uart::Uart, uart::Duplex>; + impl UART { /// Convenience for setting up the labelled TX, RX pins /// to operate as a UART device at the specified baud rate. - pub fn init>( + pub fn init( self, clocks: &mut GenericClockController, - baud: F, - sercom5: pac::SERCOM5, + baud: impl Into, + sercom: UartSercom, mclk: &mut MCLK, - port: &mut Port, - ) -> UART5>, hal::sercom::Sercom5Pad0>, (), ()> - { + ) -> Uart { let gclk0 = clocks.gclk0(); - - UART5::new( - &clocks.sercom5_core(&gclk0).unwrap(), - baud.into(), - sercom5, - mclk, - (self.rx.into_pad(port), self.tx.into_pad(port)), - ) + let clock = &clocks.sercom5_core(&gclk0).unwrap(); + let baud = baud.into(); + let rx: UartRx = self.rx.into(); + let tx: UartTx = self.tx.into(); + let pads = uart::Pads::default().rx(rx).tx(tx); + uart::Config::new(mclk, sercom, pads, clock.freq()) + .baud(baud, BaudMode::Fractional(Oversampling::Bits16)) + .enable() } } /// Analog pins pub struct Analog { - pub a1: Pa5>, - pub a2: Pb8>, - pub a3: Pb9>, - pub a4: Pa4>, - pub a5: Pa6>, + pub a1: A1Reset, + pub a2: A2Reset, + pub a3: A3Reset, + pub a4: A4Reset, + pub a5: A5Reset, } /// Digital pins pub struct Digital { /// also usabe as A8 - pub d2: Pb3>, + pub d2: D2Reset, /// also usabe as A9 - pub d3: Pb2>, - pub d5: Pa16>, - pub d6: Pa18>, - pub d9: Pa19>, - pub d10: Pa20>, - pub d11: Pa21>, - pub d12: Pa22>, + pub d3: D3Reset, + pub d5: D5Reset, + pub d6: D6Reset, + pub d9: D9Reset, + pub d10: D10Reset, + pub d11: D11Reset, + pub d12: D12Reset, } /// QSPI flash pins pub struct QSPIFlash { - pub sck: Pb10>, - pub cs: Pb11>, - pub data0: Pa8>, - pub data1: Pa9>, - pub data2: Pa10>, - pub data3: Pa11>, + pub sclk: QspiSclkReset, + pub cs: QspiCsReset, + pub data0: QspiD0Reset, + pub data1: QspiD1Reset, + pub data2: QspiD2Reset, + pub data3: QspiD3Reset, } impl QSPIFlash { - pub fn init(self, mclk: &mut MCLK, _port: &mut Port, qspi: QSPI) -> qspi::Qspi { + pub fn init(self, mclk: &mut MCLK, qspi: QSPI) -> qspi::Qspi { qspi::Qspi::new( - mclk, qspi, self.sck, self.cs, self.data0, self.data1, self.data2, self.data3, + mclk, qspi, self.sclk, self.cs, self.data0, self.data1, self.data2, self.data3, ) } } @@ -577,29 +817,24 @@ impl QSPIFlash { /// Button pins pub struct Buttons { /// Button Latch - pub latch: Pb0>, + pub latch: ButtonLatchReset, /// Button Out - pub data_in: Pb30>, + pub data_in: ButtonOutReset, /// Button Clock - pub clock: Pb31>, + pub clock: ButtonClockReset, } -#[cfg(feature = "unproven")] impl Buttons { /// Convenience for setting up the button latch pins /// Returns ButtonReader iterator which can be polled for Key events - pub fn init(self, port: &mut Port) -> ButtonReader { - let mut latch = self.latch.into_push_pull_output(port); + pub fn init(self) -> ButtonReader { + let mut latch: ButtonLatch = self.latch.into(); latch.set_high().ok(); - - let data_in = self.data_in.into_floating_input(port); - - let mut clock = self.clock.into_push_pull_output(port); + let mut clock: ButtonClock = self.clock.into(); clock.set_high().ok(); - ButtonReader { latch, - data_in, + data_in: self.data_in.into(), clock, last: 0, } @@ -609,12 +844,11 @@ impl Buttons { /// Joystick pins pub struct JoystickReader { /// Joystick X - pub joy_x: Pb7, + pub joy_x: JoyX, /// Joystick Y - pub joy_y: Pb6, + pub joy_y: JoyY, } -#[cfg(feature = "unproven")] impl JoystickReader { /// returns a tuple (x,y) where values are 12 bit, between 0-4095 /// values are NOT centered, but could be by subtracting 2048 @@ -633,31 +867,28 @@ impl JoystickReader { /// Joystick pins pub struct Joystick { /// Joystick X - pub joy_x: Pb7>, + pub joy_x: JoyXReset, /// Joystick Y - pub joy_y: Pb6>, + pub joy_y: JoyYReset, } -#[cfg(feature = "unproven")] impl Joystick { /// Convenience for setting up the joystick. Returns JoystickReader instance /// which can be polled for joystick (x,y) tuple - pub fn init(self, port: &mut Port) -> JoystickReader { + pub fn init(self) -> JoystickReader { JoystickReader { - joy_x: self.joy_x.into_function_b(port), - joy_y: self.joy_y.into_function_b(port), + joy_x: self.joy_x.into(), + joy_y: self.joy_y.into(), } } } /// Battery Reader -#[cfg(feature = "unproven")] pub struct BatteryReader { /// Battery pin - pub battery: Pb1, + pub battery: BatteryPin, } -#[cfg(feature = "unproven")] impl BatteryReader { /// Returns a float for voltage of battery pub fn read(&mut self, adc: &mut hal::adc::Adc) -> f32 { @@ -669,16 +900,15 @@ impl BatteryReader { /// Battery pin pub struct Battery { - pub battery: Pb1>, + pub battery: BatteryReset, } -#[cfg(feature = "unproven")] impl Battery { /// Convenience for reading Battery Volage. Returns BatteryReader instance /// which can be polled for battery voltage - pub fn init(self, port: &mut Port) -> BatteryReader { + pub fn init(self) -> BatteryReader { BatteryReader { - battery: self.battery.into_function_b(port), + battery: self.battery.into(), } } }