Update deps, implement own BSP

This commit is contained in:
Aode (Lion) 2022-02-05 23:01:44 -06:00
parent 90c91e74c3
commit 0f6b49950a
7 changed files with 171 additions and 55 deletions

View file

@ -7,15 +7,17 @@ version = "0.1.0"
build = "src/build.rs"
[dependencies]
atsamd-hal = "0.12"
cortex-m = "0.6.0"
cortex-m-rt = "0.6.10"
apa102-spi = "0.3.2"
atsamd-hal = "0.14"
bitbang-hal = "0.3.2"
cortex-m = "0.7.4"
cortex-m-rt = "0.7.1"
cortex-m-semihosting = "0.3.3"
embedded-hal = "0.2"
once_cell = { version = "1.7.2", default-features = false }
panic-halt = "0.2.0"
smart-leds = "0.3"
trinket_m0 = { version = "0.9.0", features = ["unproven", "usb"] }
trinket_m0 = { version = "0.11.0", features = ["unproven", "usb"] }
usb-device = "0.2"
usbd-serial = "0.1"
streamdeck-common = { version = "0.1.0", path = "./streamdeck-common" }
@ -32,10 +34,8 @@ bench = false
[profile.release]
codegen-units = 1 # better optimizations
debug = true # symbols are nice and they don't increase the size on Flash
lto = true # better optimizations
debug = true # symbols are nice and they don't increase the size on Flash
lto = true # better optimizations
[workspace]
members = [
"./streamdeck-common",
]
members = ["./streamdeck-common"]

110
src/bsp.rs Normal file
View file

@ -0,0 +1,110 @@
use atsamd_hal::gpio::v2::{
Disabled, Floating, Input, Output, Pin, PullUp, PushPull, PA00, PA01, PA14,
};
use atsamd_hal::prelude::_embedded_hal_timer_CountDown as CountDown;
use embedded_hal::timer::Periodic;
pub struct Dotstar {
pub ci: Pin<PA01, Disabled<Floating>>,
pub di: Pin<PA00, Disabled<Floating>>,
pub nc: Pin<PA14, Disabled<Floating>>,
}
pub type Spi<C> = bitbang_hal::spi::SPI<
Pin<PA14, Input<PullUp>>,
Pin<PA00, Output<PushPull>>,
Pin<PA01, Output<PushPull>>,
C,
>;
impl Dotstar {
pub fn init<C: CountDown + Periodic>(self, timer: C) -> apa102_spi::Apa102<Spi<C>> {
let spi = bitbang_hal::spi::SPI::new(
apa102_spi::MODE,
self.nc.into(),
self.di.into(),
self.ci.into(),
timer,
);
apa102_spi::Apa102::new(spi)
}
}
atsamd_hal::bsp_pins! (
PA08 {
name: d0
aliases: {
AlternateC: Sda
}
}
PA02 {
name: d1
aliases: {
AlternateC: Scl
}
}
PA09 {
name: d2
}
PA07 {
name: d3
aliases: {
AlternateC: UartTx
}
}
PA06 {
name: d4
aliases: {
AlternateC: UartRx
}
}
PA10 {
name: d13
aliases: {
PushPullOutput: RedLed
}
}
PA01 {
name: dotstar_ci
aliases: {
AlternateD: Sclk
}
}
PA00 {
name: dotstar_di
aliases: {
AlternateD: Mosi
}
}
PA14 {
name: dotstar_nc
aliases: {
AlternateD: Miso
}
}
PA31 {
name: swdio
}
PA30 {
name: swdclk
}
PA28 {
name: usb_host_enable
}
PA23 {
name: usb_sof
}
PA24 {
name: usb_dm
aliases: {
AlternateG: UsbDm
}
}
PA25 {
name: usb_dp
aliases: {
AlternateG: UsbDp
}
}
);

View file

@ -1,6 +1,7 @@
#![no_std]
#![no_main]
use atsamd_hal::clock::{ClockGenId, ClockSource};
use panic_halt as _; // you can put a breakpoint on `rust_begin_unwind` to catch panics
use trinket_m0 as hal;
@ -15,9 +16,7 @@ use hal::{
entry,
pac::{interrupt, CorePeripherals, Peripherals},
prelude::_atsamd_hal_embedded_hal_digital_v2_OutputPin,
timer::SpinTimer,
usb::UsbBus,
Dotstar,
};
use once_cell::unsync::OnceCell;
use smart_leds::{SmartLedsWrite, RGB8};
@ -25,8 +24,10 @@ use streamdeck_common::{handle_input, Handshake, UnsafeSync};
use usb_device::{bus::UsbBusAllocator, prelude::*};
use usbd_serial::{SerialPort, USB_CLASS_CDC};
mod bsp;
mod trinket_buttons;
use bsp::{Dotstar, Pins};
use trinket_buttons::Buttons;
static USB_ALLOCATOR: UnsafeSync<OnceCell<UsbBusAllocator<UsbBus>>> =
@ -46,9 +47,9 @@ fn main() -> ! {
&mut peripherals.SYSCTRL,
&mut peripherals.NVMCTRL,
);
let mut pins = hal::Pins::new(peripherals.PORT);
let pins = Pins::new(peripherals.PORT);
let mut red_led = pins.d13.into_open_drain_output(&mut pins.port);
let mut red_led = pins.d13.into_push_pull_output();
red_led.set_low().unwrap();
let usb_allocator = hal::usb_allocator(
@ -57,9 +58,15 @@ fn main() -> ! {
&mut peripherals.PM,
pins.usb_dm,
pins.usb_dp,
&mut pins.port,
);
let timer_clock = clocks
.configure_gclk_divider_and_source(ClockGenId::GCLK1, 1, ClockSource::OSC32K, false)
.unwrap();
clocks.configure_standby(ClockGenId::GCLK1, true);
let tc45 = &clocks.tc4_tc5(&timer_clock).unwrap();
let timer = atsamd_hal::timer::TimerCounter::tc4_(tc45, peripherals.TC4, &mut peripherals.PM);
// SAFETY: No interrupt will access USB_ALLOCATOR before this point, since it is only
// referenced from inside the USB_SERIAL mutex and the USB_BUS mutex, which have not been set
// yet.
@ -101,14 +108,14 @@ fn main() -> ! {
d3: pins.d3,
d4: pins.d4,
}
.init(&mut pins.port);
.init();
let mut rgb = Dotstar {
ci: pins.dotstar_ci,
di: pins.dotstar_di,
nc: pins.dotstar_nc,
}
.init(SpinTimer::new(12), &mut pins.port);
.init(timer);
let off = RGB8 { r: 0, g: 0, b: 0 };
rgb.write([off].iter().cloned()).unwrap();
@ -168,10 +175,8 @@ fn poll_usb(handshake: &mut Handshake) -> Option<()> {
let current_time = SYST::get_current();
if count == 32 {
if handshake.perform(&input, current_time, &mut Device)? {
return Some(());
}
if count == 32 && handshake.perform(&input, current_time, &mut Device)? {
return Some(());
}
let is_complete = handshake.is_complete();
@ -182,13 +187,15 @@ fn poll_usb(handshake: &mut Handshake) -> Option<()> {
handle_input(&mut Device, &input, count)
}
fn with_op_lock_spin(cs: &cortex_m::interrupt::CriticalSection) -> bool {
let mut operation_lock = OPERATION_LOCK.borrow(cs).borrow_mut();
let prev = *operation_lock;
*operation_lock = true;
prev
}
fn with_op_lock(mut f: impl FnMut()) {
while cortex_m::interrupt::free(|cs| {
let mut operation_lock = OPERATION_LOCK.borrow(cs).borrow_mut();
let prev = *operation_lock;
*operation_lock = true;
prev
}) {
while cortex_m::interrupt::free(with_op_lock_spin) {
cycle_delay(1024);
}
@ -214,7 +221,7 @@ impl streamdeck_common::Device<16, 1> for Device {
let mut id = [0u8; 16];
for i in 0..4 {
id[i * 4 + 0] = unsafe { (*generator[i])[3] };
id[i * 4] = unsafe { (*generator[i])[3] };
id[i * 4 + 1] = unsafe { (*generator[i])[2] };
id[i * 4 + 2] = unsafe { (*generator[i])[1] };
id[i * 4 + 3] = unsafe { (*generator[i])[0] };

View file

@ -1,19 +1,16 @@
use atsamd_hal::common::gpio::{
v2::{
pin::{PA02, PA06, PA07, PA08, PA09},
Floating, Input, PullUp,
},
Pin, Port,
use atsamd_hal::common::gpio::v2::{
Disabled, Floating, Input, Pin, PullUp, PA02, PA06, PA07, PA08, PA09,
};
use core::convert::Infallible;
use embedded_hal::digital::v2::InputPin;
use streamdeck_common::{ButtonPins, ButtonState};
pub(crate) struct Buttons {
pub(crate) d0: Pin<PA08, Input<Floating>>,
pub(crate) d1: Pin<PA02, Input<Floating>>,
pub(crate) d2: Pin<PA09, Input<Floating>>,
pub(crate) d3: Pin<PA07, Input<Floating>>,
pub(crate) d4: Pin<PA06, Input<Floating>>,
pub(crate) d0: Pin<PA08, Disabled<Floating>>,
pub(crate) d1: Pin<PA02, Disabled<Floating>>,
pub(crate) d2: Pin<PA09, Disabled<Floating>>,
pub(crate) d3: Pin<PA07, Disabled<Floating>>,
pub(crate) d4: Pin<PA06, Disabled<Floating>>,
}
pub(crate) struct Pins {
@ -25,19 +22,19 @@ pub(crate) struct Pins {
}
impl<'a> ButtonPins<'a, 5> for Pins {
fn to_array(&'a self) -> [&'a dyn InputPin<Error = ()>; 5] {
fn to_array(&'a self) -> [&'a dyn InputPin<Error = Infallible>; 5] {
[&self.d0, &self.d1, &self.d2, &self.d3, &self.d4]
}
}
impl Buttons {
pub(crate) fn init(self, port: &mut Port) -> ButtonState<Pins, 5> {
pub(crate) fn init(self) -> ButtonState<Pins, 5> {
ButtonState::from_pins(Pins {
d0: self.d0.into_pull_up_input(port),
d1: self.d1.into_pull_up_input(port),
d2: self.d2.into_pull_up_input(port),
d3: self.d3.into_pull_up_input(port),
d4: self.d4.into_pull_up_input(port),
d0: self.d0.into(),
d1: self.d1.into(),
d2: self.d2.into(),
d3: self.d3.into(),
d4: self.d4.into(),
})
}
}

View file

@ -1,9 +1,10 @@
use core::convert::Infallible;
use embedded_hal::digital::v2::InputPin;
const DEBOUNCE_TIMEOUT: u32 = 100;
pub trait ButtonPins<'a, const N: usize> {
fn to_array(&'a self) -> [&'a dyn InputPin<Error = ()>; N];
fn to_array(&'a self) -> [&'a dyn InputPin<Error = Infallible>; N];
}
pub struct ButtonState<T, const N: usize> {
@ -56,13 +57,11 @@ where
*debounce_time = current_time;
}
if *debounce_time + DEBOUNCE_TIMEOUT < current_time {
if *current_state != *last_state {
*current_state = *last_state;
if *debounce_time + DEBOUNCE_TIMEOUT < current_time && *current_state != *last_state {
*current_state = *last_state;
if *current_state {
needs_update |= true;
}
if *current_state {
needs_update |= true;
}
}
}

View file

@ -5,6 +5,9 @@ impl<T> UnsafeSync<T> {
UnsafeSync(item)
}
/// # Safety
///
/// uhh...
pub unsafe fn get(&self) -> &T {
&self.0
}

View file

@ -1,8 +1,8 @@
use crate::device::Device;
static NAME: &'static [u8] = b"Streamdeck";
static AUTHOR: &'static [u8] = b"asonix";
static REPO: &'static [u8] = b"https://git.asonix.dog/asonix/trinket-streamdeck";
static NAME: &[u8] = b"Streamdeck";
static AUTHOR: &[u8] = b"asonix";
static REPO: &[u8] = b"https://git.asonix.dog/asonix/trinket-streamdeck";
pub fn handle_input<D, const SN_LEN: usize, const EXTRAS_LEN: usize>(
device: &mut D,