Skip to content

Commit

Permalink
Merge branch 'main' into pddb-feat-down
Browse files Browse the repository at this point in the history
  • Loading branch information
bunnie authored Mar 5, 2025
2 parents 56890c3 + b7f29c8 commit d1860fe
Show file tree
Hide file tree
Showing 28 changed files with 598 additions and 96 deletions.
9 changes: 4 additions & 5 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

34 changes: 34 additions & 0 deletions libs/cramium-hal/src/axp2101.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use cramium_api::*;
pub const AXP2101_DEV: u8 = 0x34;

const REG_DCDC_ENA: usize = 0x80;
const REG_DCDC_PWM: usize = 0x81;
const REG_DCDC1_V: usize = 0x82;
const REG_DCDC2_V: usize = 0x83;
const REG_DCDC3_V: usize = 0x84;
Expand Down Expand Up @@ -281,6 +282,39 @@ impl Axp2101 {
let data = VBUS_INSERT_MASK | VBUS_REMOVE_MASK;
i2c.i2c_write(AXP2101_DEV, REG_IRQ_STATUS1, &[data]).map(|_| ())
}

pub fn set_pwm_mode(
&mut self,
i2c: &mut dyn I2cApi,
which: WhichDcDc,
always: bool,
) -> Result<(), xous::Error> {
match which {
WhichDcDc::Dcdc5 => Err(xous::Error::BadAddress),
_ => {
let mut buf = [0u8];
i2c.i2c_read(AXP2101_DEV, REG_DCDC_PWM as u8, &mut buf, false).map(|_| ())?;
if always {
buf[0] |= 4u8 << (which as usize as u8);
} else {
buf[0] &= !(4u8 << (which as usize as u8));
}
i2c.i2c_write(AXP2101_DEV, REG_DCDC_PWM as u8, &buf).map(|_| ())
}
}
}

pub fn debug(&mut self, i2c: &mut dyn I2cApi) {
let mut buf = [0u8, 0u8];
i2c.i2c_read(AXP2101_DEV, REG_DCDC_ENA as u8, &mut buf, false).unwrap();
crate::println!("ena|pwm bef: {:x?}", buf);
// force CCM mode
i2c.i2c_write(AXP2101_DEV, REG_DCDC_ENA as u8, &[buf[0] | 0b0100_0000]).unwrap();
// disable spreading, force PWM on DCDC2
i2c.i2c_write(AXP2101_DEV, REG_DCDC_PWM as u8, &[(buf[1] & 0b0011_1111) | 0b0000_1000]).unwrap();
i2c.i2c_read(AXP2101_DEV, REG_DCDC_ENA as u8, &mut buf, false).unwrap();
crate::println!("ena|pwm aft: {:x?}", buf);
}
}

pub fn parse_dcdc_ena(d: u8) -> ([bool; 4], bool, bool) {
Expand Down
2 changes: 1 addition & 1 deletion libs/ux-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ pub mod cursor;
mod fontmap;
pub mod minigfx;
pub mod platform;
#[cfg(all(feature = "std", any(feature = "cramium-soc", feature = "hosted-baosec")))]
#[cfg(all(feature = "std", any(feature = "board-baosec", feature = "hosted-baosec")))]
pub mod widgets;
#[cfg(feature = "std")]
pub mod wordwrap;
Expand Down
32 changes: 32 additions & 0 deletions libs/ux-api/src/minigfx/clip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,35 @@ impl ClipObjectList {
}
}
}

#[cfg_attr(feature = "derive-rkyv", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize))]
#[derive(Debug, Clone)]
/// This API relies on an upgraded version of rkyv that was not available when the ClipObjectList
/// API was defined: we can now just use a `Vec` to do the trick.
#[cfg(feature = "std")]
pub struct ObjectList {
pub list: Vec<ClipObjectType>,
}
#[cfg(feature = "std")]
impl ObjectList {
pub fn new() -> Self { Self { list: Vec::new() } }

/// The intent was for the push() to be infalliable, but in practice, draw lists could get
/// arbitrarily large and some back-pressure is needed to keep the memory allocation within
/// bounds that the system can handle. Thus, this method can fail returning the pushed object,
/// at which point one should send the draw list to the graphics engine, and retry the push.
pub fn push(&mut self, item: ClipObjectType) -> Result<(), ClipObjectType> {
// TODO: export the capacity limit of a buffer. The origin of the capacity limit is equal to
// the size of a page of memory, plus 256 bytes for "scratch" area for rkyv to work in. I did
// try to use the .replace() method with an allocation of a large enough buffer to hold the whole
// Vec, but it seems to fail. I think it could be that the scratch space hard-coded into the IPC
// library is not big enough...
if self.list.capacity() * size_of::<ClipObjectType>() + size_of::<Vec<ClipObjectType>>() < 4096 - 256
{
self.list.push(item);
Ok(())
} else {
Err(item)
}
}
}
35 changes: 34 additions & 1 deletion libs/ux-api/src/minigfx/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,34 @@ pub fn draw_clip_object_list<T: FrameBuffer>(display: &mut T, msg: &mut xous::en
}
}

pub fn draw_object_list<T: FrameBuffer>(display: &mut T, msg: &mut xous::envelope::Envelope) {
let buffer = unsafe { Buffer::from_memory_message(msg.body.memory_message().unwrap()) };
let list_ipc = buffer.to_original::<ObjectList, _>().unwrap();
for &item in list_ipc.list.iter() {
match item {
ClipObjectType::Line(line) => {
op::line(display, line, None, false);
}
ClipObjectType::XorLine(line) => {
op::line(display, line, None, true);
}
ClipObjectType::Circ(circ) => {
op::circle(display, circ, None);
}
ClipObjectType::Rect(rect) => {
op::rectangle(display, rect, None, false);
}
ClipObjectType::RoundRect(rr) => {
op::rounded_rectangle(display, rr, None);
}
#[cfg(feature = "ditherpunk")]
_ => {
unimplemented!("Object type not yet implemented");
}
}
}
}

pub fn line<T: FrameBuffer>(
display: &mut T,
screen_clip: Option<Rectangle>,
Expand Down Expand Up @@ -166,7 +194,12 @@ pub fn draw_text_view<T: FrameBuffer>(display: &mut T, msg: &mut xous::envelope:
let mut tv = buffer.to_original::<TextView, _>().unwrap();

if tv.clip_rect.is_none() {
return;
if cfg!(feature = "hosted-baosec") || cfg!(feature = "cramium-soc") || cfg!(feature = "board-baosec")
{
tv.clip_rect = Some(Rectangle::new(Point::new(0, 0), display.dimensions()));
} else {
return;
}
} // if no clipping rectangle is specified, nothing to draw

// this is the clipping rectangle of the canvas in screen coordinates
Expand Down
8 changes: 8 additions & 0 deletions libs/ux-api/src/service/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ impl Gid {
pub fn new(id: [u32; 4]) -> Self { Gid { gid: id } }

pub fn gid(&self) -> [u32; 4] { self.gid }

pub fn dummy() -> Self { Gid { gid: [0xdead, 0xbeef, 0xdead, 0xbeef] } }
}
impl Hash for Gid {
fn hash<H>(&self, state: &mut H)
Expand Down Expand Up @@ -89,6 +91,12 @@ pub enum GfxOpcode {
/// Handle Camera IRQs
CamIrq,

/// V2 API for claiming ownership of screen for modal operation
AcquireModal,
ReleaseModal,
/// V2 API for fast drawing of multiple objects
UnclippedObjectList,

/// Gutter for invalid calls
InvalidCall,

Expand Down
52 changes: 52 additions & 0 deletions libs/ux-api/src/service/gfx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,31 @@ impl Gfx {
Ok(())
}

/// Bounds computation does no checks on security since it's a non-drawing operation. While normal drawing
/// always takes the bounds from the canvas, the caller can specify a clip_rect in this tv, instead of
/// drawing the clip_rect from the Canvas associated with the tv.
pub fn bounds_compute_textview(&self, tv: &mut TextView) -> Result<(), xous::Error> {
let mut tv_query = tv.clone();
tv_query.set_dry_run(true);
let mut buf = Buffer::into_buf(tv_query).or(Err(xous::Error::InternalError))?;
buf.lend_mut(self.conn, GfxOpcode::DrawTextView.to_u32().unwrap())
.or(Err(xous::Error::InternalError))?;
let tvr = buf.to_original::<TextView, _>().unwrap();

tv.cursor = tvr.cursor;
tv.bounds_computed = tvr.bounds_computed;
tv.overflow = tvr.overflow;
// don't update the animation state when just computing the textview bounds
// tv.busy_animation_state = tvr.busy_animation_state;
Ok(())
}

/// Clear the screen in a device-optimized fashion. The exact background color depends on the device.
pub fn clear(&self) -> Result<(), xous::Error> {
send_message(self.conn, Message::new_scalar(GfxOpcode::Clear.to_usize().unwrap(), 0, 0, 0, 0))
.map(|_| ())
}

/// Draws a line with clipping.
///
/// This function sends a message to the graphics server to draw the specified `Line` within the specified
Expand Down Expand Up @@ -665,6 +690,33 @@ impl Gfx {
.expect("couldn't pop");
}
}

/// This will cause the caller to block until it is granted a lock on the modal state.
///
/// This is a v2-only API. Calling it on a v1 system will cause a panic.
pub fn acquire_modal(&self) -> Result<xous::Result, xous::Error> {
send_message(
self.conn,
Message::new_blocking_scalar(GfxOpcode::AcquireModal.to_usize().unwrap(), 0, 0, 0, 0),
)
}

/// This is a v2-only API. Calling it on a v1 system will cause a panic.
pub fn release_modal(&self) -> Result<xous::Result, xous::Error> {
send_message(self.conn, Message::new_scalar(GfxOpcode::ReleaseModal.to_usize().unwrap(), 0, 0, 0, 0))
}

/// V2-only API
pub fn draw_object_list(&self, list: ObjectList) -> Result<(), xous::Error> {
let buf = match Buffer::into_buf(list) {
Ok(b) => b,
Err(e) => {
log::error!("err: {:?}", e);
panic!("error")
}
};
buf.lend(self.conn, GfxOpcode::UnclippedObjectList.to_u32().unwrap()).map(|_| ())
}
}

use core::sync::atomic::{AtomicU32, Ordering};
Expand Down
6 changes: 4 additions & 2 deletions libs/ux-api/src/widgets/action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@ pub enum ActionType {

#[enum_dispatch]
pub trait ActionApi {
fn height(&self, glyph_height: i16, margin: i16, _modal: &Modal) -> i16 { glyph_height + margin * 2 }
fn redraw(&self, _at_height: i16, _modal: &Modal) { unimplemented!() }
fn height(&self, glyph_height: isize, margin: isize, _modal: &Modal) -> isize {
glyph_height + margin * 2
}
fn redraw(&self, _at_height: isize, _modal: &Modal) { unimplemented!() }
fn close(&mut self) {}
fn is_password(&self) -> bool { false }
/// navigation is one of '∴' | '←' | '→' | '↑' | '↓'
Expand Down
Loading

0 comments on commit d1860fe

Please sign in to comment.