diff --git a/src/bin/tcp.rs b/src/bin/tcp.rs index 39f5a85..d29a25f 100644 --- a/src/bin/tcp.rs +++ b/src/bin/tcp.rs @@ -19,10 +19,9 @@ use embassy_rp::gpio::{Level, Output}; use embassy_rp::peripherals::{PIO0, PIO1, USB}; use embassy_rp::pio::Pio; use embassy_rp::usb::Driver; -use embassy_time::{Duration, Timer}; -use itertools::Itertools; +use embassy_time::Duration; use pico_w_neopixel_server::ws2812::Ws2812; -use pico_w_neopixel_server::{logger_task, net_task, secret, wifi_task}; +use pico_w_neopixel_server::{frame, logger_task, net_task, secret, wifi_task}; use ringbuf::StaticRb; use static_cell::make_static; @@ -99,7 +98,6 @@ async fn main(spawner: Spawner) { let mut tx_buffer = [0; 1024]; let mut rb = StaticRb::::default(); let (mut prod, mut cons) = rb.split_ref(); - let mut num_bytes: Option = None; loop { let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); @@ -115,6 +113,10 @@ async fn main(spawner: Spawner) { cons.clear(); loop { + while let Some(frame_length) = frame::next_length(&cons) { + frame::display_frame(&mut cons, frame_length, &mut ws2812).await; + } + match socket .read_with(|x| { log::debug!("Received bytes: {:?}", x); @@ -133,28 +135,6 @@ async fn main(spawner: Spawner) { break; } } - - if cons.len() > 1 { - if num_bytes.is_none() { - num_bytes = Some(u16::from_le_bytes([cons.pop().unwrap(), cons.pop().unwrap()])); - } - let length = num_bytes.unwrap() as usize; - if cons.len() >= length { - // there might be the start of the next "frame" in the input buffer - let overflow = cons.len() - length; - if overflow > 0 { - log::warn!("overflow len: {:?}", overflow); - } - cons.pop_iter() - .take(length) - .tuples() - .for_each(|(r, g, b)| ws2812.write(r, g, b)); - - num_bytes = None; - // let the neopixels latch on - Timer::after_micros(60).await; - } - } } } } diff --git a/src/bin/udp.rs b/src/bin/udp.rs index 735676a..aa76532 100644 --- a/src/bin/udp.rs +++ b/src/bin/udp.rs @@ -19,10 +19,8 @@ use embassy_rp::gpio::{Level, Output}; use embassy_rp::peripherals::{PIO0, PIO1, USB}; use embassy_rp::pio::Pio; use embassy_rp::usb::Driver; -use embassy_time::Timer; -use itertools::Itertools; use pico_w_neopixel_server::ws2812::Ws2812; -use pico_w_neopixel_server::{logger_task, net_task, secret, wifi_task}; +use pico_w_neopixel_server::{frame, logger_task, net_task, secret, wifi_task}; use ringbuf::StaticRb; use static_cell::make_static; @@ -102,7 +100,6 @@ async fn main(spawner: Spawner) { let mut buf = [0; 4096]; let mut rb = StaticRb::::default(); let (mut prod, mut cons) = rb.split_ref(); - let mut num_bytes: Option = None; loop { let mut socket = UdpSocket::new(stack, &mut rx_meta, &mut rx_buffer, &mut tx_meta, &mut tx_buffer); @@ -113,6 +110,10 @@ async fn main(spawner: Spawner) { continue; } loop { + while let Some(frame_length) = frame::next_length(&cons) { + frame::display_frame(&mut cons, frame_length, &mut ws2812).await; + } + let count = match socket.recv_from(&mut buf[..cons.free_len()]).await { Ok((count, _)) => count, Err(e) => { @@ -122,28 +123,6 @@ async fn main(spawner: Spawner) { }; log::debug!("Received bytes: {:?}", &buf[0..count]); prod.push_slice(&buf[0..count]); - - if cons.len() > 1 { - if num_bytes.is_none() { - num_bytes = Some(u16::from_le_bytes([cons.pop().unwrap(), cons.pop().unwrap()])); - } - let length = num_bytes.unwrap() as usize; - if cons.len() >= length { - // there might be the start of the next "frame" in the input buffer - let overflow = cons.len() - length; - if overflow > 0 { - log::warn!("overflow len: {:?}", overflow); - } - cons.pop_iter() - .take(length) - .tuples() - .for_each(|(r, g, b)| ws2812.write(r, g, b)); - - num_bytes = None; - // let the neopixels latch on - Timer::after_micros(60).await; - } - } } } } diff --git a/src/frame.rs b/src/frame.rs new file mode 100644 index 0000000..ac791aa --- /dev/null +++ b/src/frame.rs @@ -0,0 +1,48 @@ +use embassy_rp::pio::Instance; +use embassy_time::Timer; +use itertools::Itertools; +use ringbuf::ring_buffer::{RbRead, RbRef}; +use ringbuf::Consumer; + +use crate::ws2812::Ws2812; + +fn peek(cons: &Consumer, index: usize) -> Option<&T> +where + R: RbRef, + R::Rb: RbRead, +{ + let (left, right) = cons.as_slices(); + if index < left.len() { + Some(&left[index]) + } else if index < left.len() + right.len() { + Some(&right[index - left.len()]) + } else { + None + } +} + +pub fn next_length(cons: &Consumer) -> Option +where + R: RbRef, + R::Rb: RbRead, +{ + peek(cons, 0) + .zip(peek(cons, 1)) + .map(|(l1, l2)| u16::from_le_bytes([*l1, *l2])) + .map(|l| l as usize) + .filter(|len| *len < cons.len()) +} + +pub async fn display_frame(cons: &mut Consumer, len: usize, ws2812: &mut Ws2812<'_, P, S>) +where + R: RbRef, + R::Rb: RbRead, + P: Instance, +{ + for (r, g, b) in cons.pop_iter().skip(2).take(len).tuples() { + ws2812.write(r, g, b); + } + + // let the neopixels latch on + Timer::after_micros(60).await; +} diff --git a/src/lib.rs b/src/lib.rs index 544e956..d148e85 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,6 +2,7 @@ #![feature(type_alias_impl_trait)] pub mod binary_info; +pub mod frame; pub mod panic; pub mod secret; pub mod ws2812;