holiday_lights/gemma_m0_lights/src/lib.rs

85 lines
2.1 KiB
Rust

#![no_std]
extern crate cortex_m;
extern crate embedded_hal;
extern crate gemma_m0 as hal;
extern crate panic_halt;
pub use cortex_m::asm::delay;
pub use hal::entry;
use core::u8;
use embedded_hal::digital::OutputPin;
use hal::{
clock::GenericClockController,
Peripherals
};
use lights::{
HardwareRgb,
Lights
};
pub fn boot() -> impl Lights<Pixel = HardwareRgb> {
let mut peripherals = Peripherals::take().unwrap();
let _clock = GenericClockController::with_internal_32kosc(
peripherals.GCLK,
&mut peripherals.PM,
&mut peripherals.SYSCTRL,
&mut peripherals.NVMCTRL
);
let mut pins = hal::Pins::new(peripherals.PORT);
NeopixelLights {
out: pins.d1.into_push_pull_output(&mut pins.port)
}
}
// approx. 20ns per clock cycle;
const ZERO_HIGH_CYCLES: u32 = 11; // smidge above 200ns
const ONE_HIGH_CYCLES: u32 = 35; // about 700ns
const DATA_LOW_CYCLES: u32 = 25; // about 500ns
const LATCH_CYCLES: u32 = 300; // about 6000ns
//const FRAME_DELAY_CYCLES: u32 = 1_000_000; // about 20ms, but doesn't count the time for the other operations
pub struct NeopixelLights<T: OutputPin> {
out: T
}
impl<T: OutputPin> NeopixelLights<T> {
#[inline]
fn write(&mut self, bit: bool) {
self.out.set_high();
delay(if bit { ONE_HIGH_CYCLES } else { ZERO_HIGH_CYCLES });
self.out.set_low();
delay(DATA_LOW_CYCLES);
}
#[inline]
fn byte(&mut self, byte: u8) {
self.write(byte & 0x80 != 0);
self.write(byte & 0x40 != 0);
self.write(byte & 0x20 != 0);
self.write(byte & 0x10 != 0);
self.write(byte & 0x08 != 0);
self.write(byte & 0x04 != 0);
self.write(byte & 0x02 != 0);
self.write(byte & 0x01 != 0);
}
}
impl<T: OutputPin> Lights for NeopixelLights<T> {
type Pixel = HardwareRgb;
#[inline]
fn render(&mut self, rgb: &HardwareRgb) {
// GRB pixel order
self.byte(rgb.1);
self.byte(rgb.0);
self.byte(rgb.2);
}
fn latch(&mut self) {
delay(LATCH_CYCLES);
}
}