diff --git a/Cargo.lock b/Cargo.lock index 68243038d..e4e3d8ff4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -302,6 +302,7 @@ dependencies = [ "log-server", "num-derive", "num-traits", + "rkyv 0.4.3", "susres", "ticktimer-server", "utralib", diff --git a/services/codec/Cargo.toml b/services/codec/Cargo.toml index 66a98723f..df0faf8b9 100644 --- a/services/codec/Cargo.toml +++ b/services/codec/Cargo.toml @@ -12,13 +12,15 @@ log-server = { path = "../log-server" } ticktimer-server = { path = "../ticktimer-server" } xous-names = { path = "../xous-names" } log = "0.4" -xous-ipc = {path="../../xous-ipc"} -num-derive = {version = "0.3", default-features = false} -num-traits = {version = "0.2", default-features = false} susres = {path = "../susres"} llio = {path = "../llio"} volatile = "0.4" +xous-ipc = {path="../../xous-ipc"} +num-derive = {version = "0.3", default-features = false} +num-traits = {version = "0.2", default-features = false} +rkyv = {version = "0.4.3", default-features = false, features = ["const_generics"]} + [target.'cfg(not(any(windows,unix)))'.dependencies] utralib = { path = "../../utralib"} diff --git a/services/codec/src/api.rs b/services/codec/src/api.rs index 049fd4506..cb872f66a 100644 --- a/services/codec/src/api.rs +++ b/services/codec/src/api.rs @@ -46,6 +46,13 @@ pub(crate) enum EventCallback { Drop, } +#[derive(Debug, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize, Copy, Clone)] +pub(crate) struct ScalarHook { + pub sid: (u32, u32, u32, u32), + pub id: u32, // ID of the scalar message to send through (e.g. the discriminant of the Enum on the caller's side API) + pub cid: xous::CID, // caller-side connection ID for the scalar message to route to. Created by the caller before hooking. +} + ////////////////////////////////////////////////////////////////////////////////////// pub(crate) const ZERO_PCM: u16 = 0x0; // assumes 2's compliment. 0x8000 otherwise. @@ -56,25 +63,38 @@ The format of samples appears to be u32: |31 right 16|15 left 0| */ -pub struct FrameRing { +/* +Implementation note: rkyv's derives are having trouble with specifying the +depth of the frame as a const generic, eg. +pub struct FrameRing:: {...} +because the derive macro is not putting the `const F` at the end. This problem +exists as of rkyv 0.6.2. Implement using fixed-size variants, with traits. + +We would ideally like to be able to specify various-sized frame rings for +more efficient memory usage and message passing, but for now, we will fix +the size at 16 frames. +*/ +const FRAMES: usize = 16; +#[derive(rkyv::Serialize, rkyv::Deserialize, Debug, rkyv::Archive, Copy, Clone)] +pub struct FrameRing { // a set of frames we will circulate through - buffer: [[u32; DEPTH]; FRAMES], + buffer: [[u32; FIFO_DEPTH]; FRAMES], // the current readable frame number rd_frame: usize, // the current writeable frame number wr_frame: usize, } -impl FrameRing { - pub fn new() -> FrameRing:: { +impl FrameRing { + pub fn new() -> FrameRing { FrameRing { - buffer: [[(ZERO_PCM as u32 | (ZERO_PCM as u32) << 16); DEPTH]; FRAMES], + buffer: [[(ZERO_PCM as u32 | (ZERO_PCM as u32) << 16); FIFO_DEPTH]; FRAMES], rd_frame: 0, wr_frame: 0, } } /* empty: rd_frame == wr_frame - full: wr_frame == (rd_frame - 1) || (rd_frame == 0) && (wr_frame == FRAMES-1) + full: wr_frame == (rd_frame - 1) || (rd_frame == 0) && (wr_frame == F-1) */ pub fn is_empty(&self) -> bool { self.rd_frame == self.wr_frame @@ -96,25 +116,26 @@ impl FrameRing { pub fn writeable_count(&self) -> usize { (FRAMES-1) - self.readable_count() } - pub fn nq_frame(&mut self, frame: [u32; DEPTH]) -> Result<(), [u32; DEPTH]> { + pub fn nq_frame(&mut self, frame: [u32; FIFO_DEPTH]) -> Result<(), [u32; FIFO_DEPTH]> { if self.is_full() { - Err(frame) + return Err(frame); } else { - for (src, &stereo_sample) in frame.iter().zip(self.buffer[self.wr_frame].iter_mut()) { + for (&src, stereo_sample) in frame.iter().zip(self.buffer[self.wr_frame].iter_mut()) { *stereo_sample = src; } } - self.wr_frame = ((self.wr_frame + 1) % FRAMES); + self.wr_frame = (self.wr_frame + 1) % FRAMES; + Ok(()) } - pub fn dq_frame(&mut self) -> Option<[u32; DEPTH]> { + pub fn dq_frame(&mut self) -> Option<[u32; FIFO_DEPTH]> { if self.is_empty() { None } else { - let playbuf = [u32; DEPTH]; - for (src, &dst) in self.buffer[self.rd_frame].iter().zip(playbuf.iter_mut()) { + let playbuf: [u32; FIFO_DEPTH]; + for (&src, dst) in self.buffer[self.rd_frame].iter().zip(playbuf.iter_mut()) { *dst = src; } - self.rd_frame = ((self.rd_frame + 1) % FRAMES); + self.rd_frame = (self.rd_frame + 1) % FRAMES; Some(playbuf) } } diff --git a/services/codec/src/lib.rs b/services/codec/src/lib.rs index 53092fe83..f302dae6e 100644 --- a/services/codec/src/lib.rs +++ b/services/codec/src/lib.rs @@ -1,8 +1,10 @@ #![cfg_attr(target_os = "none", no_std)] pub mod api; -use xous::{CID, send_message}; -use num_traits::ToPrimitive; +use xous::{CID, send_message, Message}; +use num_traits::{ToPrimitive, FromPrimitive}; +use xous_ipc::Buffer; +use api::*; pub struct Codec { conn: CID, @@ -40,7 +42,7 @@ impl Codec { ).map(|_| ()) } - pub fn free_frames(&mut self) -> Result<(play, rec), xous::Error> { + pub fn free_frames(&mut self) -> Result<(usize, usize), xous::Error> { let response = send_message(self.conn, Message::new_blocking_scalar(Opcode::FreeFrames.to_usize().unwrap(), 0, 0, 0, 0))?; if let xous::Result::Scalar2(play_free, rec_avail) = response { @@ -53,11 +55,11 @@ impl Codec { } } - pub fn swap_frames(&mut self, frames: &mut FrameRing::) -> Result<(), xous::Error> { + pub fn swap_frames(&mut self, frames: &mut FrameRing) -> Result<(), xous::Error> { let mut buf = Buffer::into_buf(*frames).or(Err(xous::Error::InternalError))?; buf.lend_mut(self.conn, Opcode::SwapFrames.to_u32().unwrap()).or(Err(xous::Error::InternalError))?; - frames = buf.to_original::, _>().unwrap(); + *frames = buf.to_original::().unwrap(); Ok(()) }