@@ 1,11 1,14 @@
#![no_std]
#![no_main]
+mod strip;
use embedded_hal::serial::{Read, Write};
use esp_backtrace as _;
use hal::{clock::ClockControl, pulse_control::{ClockSource}, peripherals::Peripherals, prelude::*, timer::{TimerGroup, Timer, Timer0}, Rtc, IO, Delay, interrupt, PulseControl, Uart};
use hal::uart::config::{Config, DataBits, Parity, StopBits};
use nb::Error::{WouldBlock, Other};
+use smart_leds::{RGB8, SmartLedsWrite};
+use crate::strip::StripTiming;
const LEDS_COUNT: usize = 72;
const COMMAND_BUFFER: usize = 200;
@@ 34,6 37,27 @@ fn main() -> ! {
wdt0.disable();
wdt1.disable();
+ let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
+
+ let mut delay = Delay::new(&clocks);
+
+ let pulse = PulseControl::new(
+ peripherals.RMT,
+ &mut system.peripheral_clock_control,
+ ).unwrap();
+
+ let mut strip = strip::Strip::<_, { LEDS_COUNT * 24 + 1 }>::new(
+ pulse.channel0,
+ io.pins.gpio25,
+ StripTiming::new(
+ 800u32.nanos(),
+ 450u32.nanos(),
+ 400u32.nanos(),
+ 850u32.nanos(),
+ ),
+ );
+
+ let mut rgb_data: [RGB8; 72] = [RGB8 { r: 0, g: 0, b: 0 }; 72];
loop {
}
@@ 0,0 1,97 @@
+use core::slice::IterMut;
+use hal::gpio::{OutputPin};
+use hal::peripheral::Peripheral;
+use hal::pulse_control::{OutputChannel, ConfiguredChannel, PulseCode, RepeatMode, TransmissionError, ClockSource};
+use smart_leds::{RGB8, SmartLedsWrite};
+use fugit::{Duration, NanosDuration};
+
+pub struct Strip<CHANNEL, const COUNT: usize> {
+ channel: CHANNEL,
+ timing: StripTiming
+}
+
+pub struct StripTiming {
+ one_high_duration: Duration::<u32, 1, 1_000_000_000>,
+ one_low_duration: Duration::<u32, 1, 1_000_000_000>,
+ zero_high_duration: Duration::<u32, 1, 1_000_000_000>,
+ zero_low_duration: Duration::<u32, 1, 1_000_000_000>,
+}
+
+impl StripTiming {
+ pub fn new(one_high_duration: Duration::<u32, 1, 1_000_000_000>,
+ one_low_duration: Duration::<u32, 1, 1_000_000_000>,
+ zero_high_duration: Duration::<u32, 1, 1_000_000_000>,
+ zero_low_duration: Duration::<u32, 1, 1_000_000_000>) -> Self {
+ StripTiming {
+ one_high_duration,
+ one_low_duration,
+ zero_high_duration,
+ zero_low_duration,
+ }
+ }
+}
+
+impl<'d, CHANNEL, const COUNT: usize> Strip<CHANNEL, COUNT>
+ where CHANNEL: ConfiguredChannel
+{
+ pub fn new<P: OutputPin + 'd, UnconfiguredChannel>(mut channel: UnconfiguredChannel, pin: impl Peripheral<P=P> + 'd, timing: StripTiming) -> Self
+ where UnconfiguredChannel: OutputChannel<ConfiguredChannel<'d, P> = CHANNEL>
+ {
+ channel
+ .set_channel_divider(4) // 1 tick = 50 ns = 0.05 us
+ .set_carrier_modulation(false)
+ .set_idle_output(true)
+ .set_idle_output_level(false)
+ .set_clock_source(ClockSource::APB);
+
+ let channel = channel.assign_pin(pin);
+
+ Strip::<CHANNEL, COUNT> {
+ channel,
+ timing
+ }
+ }
+
+ fn byte_to_pulse_code(&self, byte: u8, data: &mut IterMut<u32>) -> () {
+ for i in 0..8u8 {
+ let bit = if (byte & (1 << (7 - i))) > 0 { true } else { false };
+ *data.next().unwrap() = self.bit_to_pulse_code(bit);
+ }
+ }
+
+ fn bit_to_pulse_code(&self, bit: bool) -> u32 {
+ let length1 = if bit { self.timing.one_high_duration } else { self.timing.zero_high_duration };
+ let length2 = if bit { self.timing.one_low_duration } else { self.timing.zero_low_duration };
+
+ let length1 = NanosDuration::<u32>::from_ticks(length1.ticks() / 50);
+ let length2 = NanosDuration::<u32>::from_ticks(length2.ticks() / 50);
+
+ PulseCode {
+ level1: true,
+ length1,
+ level2: false,
+ length2,
+ }.into()
+ }
+}
+
+impl<CHANNEL, const COUNT: usize> SmartLedsWrite for Strip<CHANNEL, COUNT>
+ where CHANNEL: ConfiguredChannel
+{
+ type Error = TransmissionError;
+ type Color = RGB8;
+
+ fn write<T, I>(&mut self, iterator: T) -> Result<(), Self::Error> where T: Iterator<Item=I>, I: Into<Self::Color> {
+ let mut buffer: [u32; COUNT] = [0; COUNT];
+ let mut iter_mut = buffer.iter_mut();
+ for item in iterator {
+ let rgb = item.into();
+ self.byte_to_pulse_code(rgb.g, &mut iter_mut);
+ self.byte_to_pulse_code(rgb.r, &mut iter_mut);
+ self.byte_to_pulse_code(rgb.b, &mut iter_mut);
+ }
+ *iter_mut.next().unwrap() = 0;
+
+ self.channel.send_pulse_sequence_raw(RepeatMode::SingleShot, &buffer)
+ }
+}<
\ No newline at end of file