intermediate checkin, taking a break

This commit is contained in:
bunnie 2021-05-04 19:08:56 +08:00
parent 61611caddd
commit 7a7e77d346
4 changed files with 48 additions and 22 deletions

1
Cargo.lock generated
View file

@ -302,6 +302,7 @@ dependencies = [
"log-server",
"num-derive",
"num-traits",
"rkyv 0.4.3",
"susres",
"ticktimer-server",
"utralib",

View file

@ -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"}

View file

@ -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<const DEPTH: usize, const FRAMES: usize> {
/*
Implementation note: rkyv's derives are having trouble with specifying the
depth of the frame as a const generic, eg.
pub struct FrameRing::<const F: usize> {...}
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<const DEPTH: usize, const FRAMES: usize> FrameRing<DEPTH, FRAMES> {
pub fn new() -> FrameRing::<DEPTH, FRAMES> {
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<const DEPTH: usize, const FRAMES: usize> FrameRing<DEPTH, FRAMES> {
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)
}
}

View file

@ -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::<FIFO_DEPTH, 4>) -> 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::<FrameRing::<FIFO_DEPTH, 4>, _>().unwrap();
*frames = buf.to_original::<FrameRing, _>().unwrap();
Ok(())
}