bug fixes in the REPL demo

This commit is contained in:
bunnie 2022-01-25 01:57:16 +08:00
parent 0557caf9be
commit 617fc3b8f6
9 changed files with 97 additions and 56 deletions

View file

@ -81,7 +81,6 @@ fn xmain() -> ! {
}),
Some(AppOp::FocusChange) => xous::msg_scalar_unpack!(msg, new_state_code, _, _, _, {
let new_state = gam::FocusState::convert_focus_change(new_state_code);
log::info!("got focus change with new state: {:?}", new_state);
match new_state {
gam::FocusState::Background => {
allow_redraw = false; // this instantly terminates future updates, even if Pump messages are in our input queue

View file

@ -1,4 +1,14 @@
{
"replapp.greeting": {
"en": "Welcome to the simple REPL demo.",
"zh": "简单的 repl 演示活动",
"en-audio": "Welcome to the simple REPL demo."
},
"replapp.beep.start": {
"en": "beep started...",
"zh": "哔声开始...",
"en-audio": "beep started..."
},
"replapp.beep.help": {
"en": "beep [tone [freq [duration]]]",
"zh": "beep [tone [音频 [时长]]]",

View file

@ -89,6 +89,7 @@ pub struct CmdEnv {
impl CmdEnv {
pub fn new(xns: &xous_names::XousNames) -> CmdEnv {
let ticktimer = ticktimer_server::Ticktimer::new().expect("Couldn't connect to Ticktimer");
log::info!("creating CommonEnv");
let common = CommonEnv {
llio: llio::Llio::new(&xns),
com: com::Com::new(&xns).expect("could't connect to COM"),
@ -99,7 +100,7 @@ impl CmdEnv {
trng: Trng::new(&xns).unwrap(),
xns: xous_names::XousNames::new().unwrap(),
};
log::info!("done creating CommonEnv");
CmdEnv {
common_env: common,
lastverb: String::<256>::new(),

View file

@ -15,8 +15,9 @@ pub struct Beep {
}
impl Beep {
pub fn new(xns: &xous_names::XousNames) -> Self {
log::info!("initializing beep");
let callback_conn = xns.request_connection_blocking(crate::SERVER_NAME_REPL).unwrap();
log::info!("beep init returning");
Beep {
callback_id: None,
callback_conn,
@ -27,6 +28,7 @@ impl Beep {
}
}
const STOP_ID: usize = 1;
const SAMPLE_RATE_HZ: f32 = 8000.0;
// note to self: A4 = 440.0, E4 = 329.63, C4 = 261.63
@ -75,17 +77,18 @@ impl<'a> ShellCmdApi<'a> for Beep {
env.codec.resume().unwrap();
env.ticktimer.sleep_ms((duration * 1000.0) as usize).unwrap();
env.codec.pause().unwrap(); // this should stop callbacks from occurring too.
write!(ret, "{} {} {}.",
t!("replapp.beep.completion_a", xous::LANG),
self.framecount,
t!("replapp.beep.completion_b", xous::LANG),
).unwrap();
self.framecount = 0;
self.play_sample = 0.0;
env.codec.power_off().unwrap();
// kick off a thread that stops the playback, after the designated delay
std::thread::spawn({
let cb_id = self.callback_id.unwrap().clone();
let conn = self.callback_conn.clone();
let duration = duration.clone();
move || {
let ticktimer = ticktimer_server::Ticktimer::new().unwrap();
ticktimer.sleep_ms((duration * 1000.0) as usize).unwrap();
xous::send_message(conn, Message::new_scalar(cb_id as usize, 0, 0, 0, STOP_ID)).unwrap();
}
});
write!(ret, "{}", t!("replapp.beep.start", xous::LANG)).unwrap();
}
_ => {
write!(ret, "{}", helpstring).unwrap();
@ -100,32 +103,46 @@ impl<'a> ShellCmdApi<'a> for Beep {
const AMPLITUDE: f32 = 0.8;
match &msg.body {
Message::Scalar(xous::ScalarMessage{id: _, arg1: free_play, arg2: _avail_rec, arg3: _, arg4: _}) => {
let mut frames: FrameRing = FrameRing::new();
let frames_to_push = if frames.writeable_count() < *free_play {
frames.writeable_count()
} else {
*free_play
};
self.framecount += frames_to_push as u32;
Message::Scalar(xous::ScalarMessage{id: _, arg1: free_play, arg2: _avail_rec, arg3: _, arg4: routing_id}) => {
if *routing_id == codec::AUDIO_CB_ROUTING_ID {
let mut frames: FrameRing = FrameRing::new();
let frames_to_push = if frames.writeable_count() < *free_play {
frames.writeable_count()
} else {
*free_play
};
self.framecount += frames_to_push as u32;
log::debug!("f{} p{}", self.framecount, frames_to_push);
for _ in 0..frames_to_push {
let mut frame: [u32; codec::FIFO_DEPTH] = [ZERO_PCM as u32 | (ZERO_PCM as u32) << 16; codec::FIFO_DEPTH];
// put the "expensive" f32 comparison outside the cosine wave table computation loop
let omega = self.freq * 2.0 * std::f32::consts::PI / SAMPLE_RATE_HZ;
for sample in frame.iter_mut() {
let raw_sine: i16 = (AMPLITUDE * f32::cos( self.play_sample * omega ) * i16::MAX as f32) as i16;
let left = raw_sine as u16;
let right = raw_sine as u16;
*sample = right as u32 | (left as u32) << 16;
self.play_sample += 1.0;
}
frames.nq_frame(frame).unwrap();
log::debug!("f{} p{}", self.framecount, frames_to_push);
for _ in 0..frames_to_push {
let mut frame: [u32; codec::FIFO_DEPTH] = [ZERO_PCM as u32 | (ZERO_PCM as u32) << 16; codec::FIFO_DEPTH];
// put the "expensive" f32 comparison outside the cosine wave table computation loop
let omega = self.freq * 2.0 * std::f32::consts::PI / SAMPLE_RATE_HZ;
for sample in frame.iter_mut() {
let raw_sine: i16 = (AMPLITUDE * f32::cos( self.play_sample * omega ) * i16::MAX as f32) as i16;
let left = raw_sine as u16;
let right = raw_sine as u16;
*sample = right as u32 | (left as u32) << 16;
self.play_sample += 1.0;
}
frames.nq_frame(frame).unwrap();
env.codec.swap_frames(&mut frames).unwrap();
} else if *routing_id == STOP_ID {
let mut ret = String::<1024>::new();
env.codec.pause().unwrap(); // this should stop callbacks from occurring too.
write!(ret, "{} {} {}.",
t!("replapp.beep.completion_a", xous::LANG),
self.framecount,
t!("replapp.beep.completion_b", xous::LANG),
).unwrap();
self.framecount = 0;
self.play_sample = 0.0;
env.codec.power_off().unwrap();
return Ok(Some(ret));
}
env.codec.swap_frames(&mut frames).unwrap();
},
Message::Move(_mm) => {
log::error!("received memory message when not expected")

View file

@ -14,6 +14,8 @@ pub(crate) enum ReplOp {
Line = 0, // make sure we occupy opcodes with discriminants < 1000, as the rest are used for callbacks
/// redraw our UI
Redraw,
/// change focus
ChangeFocus,
/// exit the application
Quit,
}
@ -29,12 +31,13 @@ fn xmain() -> ! {
let xns = xous_names::XousNames::new().unwrap();
// unlimited connections allowed, this is a user app and it's up to the app to decide its policy
let sid = xns.register_name(SERVER_NAME_REPL, None).expect("can't register server");
//log::trace!("registered with NS -- {:?}", sid);
log::trace!("registered with NS -- {:?}", sid);
let mut repl = Repl::new(&xns, sid);
let mut update_repl = false;
let mut update_repl = true;
let mut was_callback = false;
let mut allow_redraw = false;
log::trace!("entering main loop");
loop {
let msg = xous::receive_message(sid).unwrap();
log::debug!("got message {:?}", msg);
@ -48,9 +51,22 @@ fn xmain() -> ! {
was_callback = false;
}
Some(ReplOp::Redraw) => {
log::trace!("got Redraw");
repl.redraw().expect("REPL couldn't redraw");
if allow_redraw {
repl.redraw().expect("REPL couldn't redraw");
}
}
Some(ReplOp::ChangeFocus) => xous::msg_scalar_unpack!(msg, new_state_code, _, _, _, {
let new_state = gam::FocusState::convert_focus_change(new_state_code);
match new_state {
gam::FocusState::Background => {
allow_redraw = false;
}
gam::FocusState::Foreground => {
allow_redraw = true;
update_repl = true;
}
}
}),
Some(ReplOp::Quit) => {
log::error!("got Quit");
break;

View file

@ -4,6 +4,7 @@ use graphics_server::{Gid, Point, Rectangle, TextBounds, TextView, DrawStyle, Pi
use graphics_server::api::GlyphStyle;
use xous::MessageEnvelope;
use core::fmt::Write;
use locales::t;
#[derive(Debug)]
struct History {
@ -54,7 +55,7 @@ impl Repl{
gotinput_id: Some(ReplOp::Line.to_u32().unwrap()),
audioframe_id: None,
rawkeys_id: None,
focuschange_id: None, // repl will keep running in the background even if it has lost focus
focuschange_id: Some(ReplOp::Redraw.to_u32().unwrap()),
}).expect("couldn't register Ux context for repl");
let content = gam.request_content_canvas(token.unwrap()).expect("couldn't get content canvas");
@ -62,7 +63,7 @@ impl Repl{
Repl {
input: None,
msg: None,
history: Vec::new(),
history: vec![History{text: String::from(t!("replapp.greeting", xous::LANG)), is_input: false}],
history_len: 10,
content,
gam,
@ -208,7 +209,6 @@ impl Repl{
}
}
self.gam.redraw().expect("couldn't redraw screen");
// self.gam.request_ime_redraw().expect("couldn't redraw the IME area");
Ok(())
}
}

View file

@ -6,6 +6,8 @@ use num_traits::{ToPrimitive, FromPrimitive};
use xous_ipc::Buffer;
pub use api::*;
/// This is a keyword reserved for the "arg4" slot of a scalar callback, where args are numbered 1-4.
pub const AUDIO_CB_ROUTING_ID: usize = 0;
#[derive(Debug)]
pub struct Codec {
conn: CID,
@ -145,7 +147,7 @@ fn frame_cb_server(sid0: usize, sid1: usize, sid2: usize, sid3: usize) {
Some(EventCallback::Event) => xous::msg_scalar_unpack!(msg, cid, id, free_play, avail_rec, {
// directly pass the scalar message onto the CID with the ID memorized in the original hook
send_message(cid as u32,
Message::new_scalar(id, free_play, avail_rec, 0, 0)
Message::new_scalar(id, free_play, avail_rec, 0, AUDIO_CB_ROUTING_ID)
).unwrap();
}),
Some(EventCallback::Drop) => {

View file

@ -323,6 +323,7 @@ impl ContextManager {
None
};
let maybe_new_focus = self.get_context_by_token_mut(token);
log::trace!("resolving visibility rules");
if let Some(context) = maybe_new_focus {
if let Some(leaving_focused_context) = maybe_leaving_focused_context {
if token != leaving_focused_context.app_token {
@ -355,6 +356,7 @@ impl ContextManager {
}
}
}
log::trace!("hiding old context");
{
// let all the previous operations go out of scope, so we can "check out" the old copy and modify it
if self.focused_context.is_some() {
@ -367,6 +369,7 @@ impl ContextManager {
}
}
}
log::trace!("rewiring IMEF and recomputing canvases");
{
// now re-check-out the new context and finalize things
let maybe_new_focus = self.get_context_by_token(token);
@ -404,6 +407,7 @@ impl ContextManager {
*canvases = recompute_canvases(canvases, Rectangle::new(Point::new(0, 0), screensize));
}
}
log::trace!("foregrounding new context");
{
// now re-check-out the new context and finalize things
let maybe_new_focus = self.get_context_by_token(token);
@ -427,6 +431,7 @@ impl ContextManager {
self.last_context = self.focused_context;
self.focused_context = Some(last_token);
}
log::trace!("defacing old canvases prior to redraw");
// run the defacement before we redraw all the canvases
deface(gfx, &self.trng, canvases);
log::trace!("activate redraw");

View file

@ -38,7 +38,7 @@ fn imef_cb(s: String::<4000>) {
#[xous::xous_main]
fn xmain() -> ! {
log_server::init_wait().unwrap();
log::set_max_level(log::LevelFilter::Trace);
log::set_max_level(log::LevelFilter::Info);
info!("my PID is {}", xous::process::id());
let xns = xous_names::XousNames::new().unwrap();
@ -484,15 +484,6 @@ fn xmain() -> ! {
Some(Opcode::RevertFocusNb) => {
context_mgr.revert_focus(&gfx, &mut canvases);
},
/*
Some(Opcode::RequestFocus) => msg_blocking_scalar_unpack!(msg, t0, t1, t2, t3, {
// TODO: add some limitations around who can request focus
// for now, it's the boot set so we just trust the requestor
context_mgr.activate(&gfx, &mut canvases, [t0 as u32, t1 as u32, t2 as u32, t3 as u32], true);
// this is a blocking scalar, so return /something/ so we know to move on
xous::return_scalar(msg.sender, 1).expect("couldn't confirm focus activation");
}), */
Some(Opcode::QueryGlyphProps) => msg_blocking_scalar_unpack!(msg, style, _, _, _, {
let height = gfx.glyph_height_hint(GlyphStyle::from(style)).expect("couldn't query glyph height from gfx");
xous::return_scalar(msg.sender, height).expect("could not return QueryGlyphProps request");