diff --git a/gemma_m0_lights/Cargo.toml b/gemma_m0_lights/Cargo.toml new file mode 100644 index 0000000..b0be849 --- /dev/null +++ b/gemma_m0_lights/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "gemma_m0_lights" +version = "0.1.0" +authors = ["Tangent 128 "] +edition = "2018" + +[dependencies] +cortex-m = { version = "0.5.8", features = ["inline-asm"] } +embedded-hal = "0.2.2" +gemma_m0 = "0.2.1" +lights = { path = "../lights" } +panic-halt = "0.2" diff --git a/gemma_m0_lights/src/lib.rs b/gemma_m0_lights/src/lib.rs new file mode 100644 index 0000000..981a13f --- /dev/null +++ b/gemma_m0_lights/src/lib.rs @@ -0,0 +1,84 @@ +#![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::{ + gamma::CorrectedRgb, + Lights +}; + +pub fn boot() -> impl Lights { + 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 { + out: T +} + +impl NeopixelLights { + #[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 Lights for NeopixelLights { + type Pixel = CorrectedRgb; + + #[inline] + fn render(&mut self, rgb: &CorrectedRgb) { + // GRB pixel order + self.byte(rgb.1); + self.byte(rgb.0); + self.byte(rgb.2); + } + fn latch(&mut self) { + delay(LATCH_CYCLES); + } +}