mirror of
https://github.com/saymrwulf/xous-core.git
synced 2026-11-08 04:56:43 +00:00
UX improvements for loader update interface
This commit is contained in:
parent
9c1186022f
commit
ed085f2c83
1 changed files with 70 additions and 123 deletions
|
|
@ -1,15 +1,22 @@
|
|||
use core::fmt::Display;
|
||||
|
||||
use cramium_hal::iox::{IoGpio, IoSetup, Iox, IoxPort, IoxValue};
|
||||
use cramium_hal::minigfx::{FrameBuffer, Point};
|
||||
use cramium_hal::sh1107::Mono;
|
||||
use cramium_hal::udma;
|
||||
use simple_fatfs::io::{IOBase, Read, Seek, SeekFrom, Write};
|
||||
use simple_fatfs::{IOError, IOErrorKind, PathBuf};
|
||||
use cramium_hal::usb::driver::UsbDeviceState;
|
||||
use simple_fatfs::PathBuf;
|
||||
use utralib::generated::*;
|
||||
|
||||
use crate::platform::cramium::gfx;
|
||||
use crate::platform::cramium::usb;
|
||||
use crate::platform::cramium::usb::SliceCursor;
|
||||
|
||||
// TODO:
|
||||
// - Port unicode font drawing into loader
|
||||
// - Support localization
|
||||
|
||||
// Empirically measured PORTSC when the port is unplugged. This might be a brittle way
|
||||
// to detect if the device is unplugged.
|
||||
const DISCONNECT_STATE: u32 = 0x40b;
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum KeyPress {
|
||||
|
|
@ -69,6 +76,7 @@ pub fn process_update(perclk: u32) {
|
|||
let mut iox = Iox::new(utra::iox::HW_IOX_BASE as *mut u32);
|
||||
let mut udma_global = udma::GlobalConfig::new(utra::udma_ctrl::HW_UDMA_CTRL_BASE as *mut u32);
|
||||
|
||||
let iox_kbd = iox.clone();
|
||||
let mut sh1107 = cramium_hal::sh1107::Oled128x128::new(perclk, &mut iox, &mut udma_global);
|
||||
|
||||
gfx::msg(&mut sh1107, " START to boot", Point::new(0, 16), Mono::White.into(), Mono::Black.into());
|
||||
|
|
@ -78,12 +86,12 @@ pub fn process_update(perclk: u32) {
|
|||
sh1107.draw();
|
||||
|
||||
// setup IO pins to check for update viability
|
||||
let (rows, cols) = cramium_hal::board::baosec::setup_kb_pins(&iox);
|
||||
let (rows, cols) = cramium_hal::board::baosec::setup_kb_pins(&iox_kbd);
|
||||
|
||||
let mut key_pressed = false;
|
||||
let mut do_update = false;
|
||||
while !key_pressed {
|
||||
let kps = scan_keyboard(&iox, &rows, &cols);
|
||||
let kps = scan_keyboard(&iox_kbd, &rows, &cols);
|
||||
for kp in kps {
|
||||
if kp != KeyPress::None {
|
||||
crate::println!("Got key: {:?}", kp);
|
||||
|
|
@ -94,7 +102,14 @@ pub fn process_update(perclk: u32) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
sh1107.clear();
|
||||
|
||||
if do_update {
|
||||
gfx::msg(&mut sh1107, "Connect to USB", Point::new(16, 64), Mono::White.into(), Mono::Black.into());
|
||||
sh1107.buffer_swap();
|
||||
sh1107.draw();
|
||||
|
||||
crate::platform::cramium::usb::init_usb();
|
||||
// it's all unsafe because USB is global mutable state
|
||||
unsafe {
|
||||
|
|
@ -117,16 +132,57 @@ pub fn process_update(perclk: u32) {
|
|||
usb.start();
|
||||
usb.update_current_speed();
|
||||
|
||||
crate::println!("hw started...");
|
||||
|
||||
let mut last_usb_state = usb.get_device_state();
|
||||
let mut portsc = usb.portsc_val();
|
||||
crate::println!("USB state: {:?}, {:x}", last_usb_state, portsc);
|
||||
loop {
|
||||
let kps = scan_keyboard(&iox, &rows, &cols);
|
||||
let kps = scan_keyboard(&iox_kbd, &rows, &cols);
|
||||
// only consider the first key returned in case of multi-key hit, for simplicity
|
||||
if kps[0] == KeyPress::Select {
|
||||
break;
|
||||
} else if kps[0] != KeyPress::None {
|
||||
crate::println!("Got key {:?}; ignoring", kps[0]);
|
||||
}
|
||||
let new_usb_state = usb.get_device_state();
|
||||
let new_portsc = usb.portsc_val();
|
||||
// alternately, break out of the loop when USB is disconnected
|
||||
if new_portsc != portsc {
|
||||
crate::println!("PP: {:x}", portsc);
|
||||
portsc = new_portsc;
|
||||
if portsc == DISCONNECT_STATE && new_usb_state == UsbDeviceState::Configured {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if new_usb_state != last_usb_state {
|
||||
crate::println!("USB state: {:?}", new_usb_state);
|
||||
if new_usb_state == UsbDeviceState::Configured {
|
||||
sh1107.clear();
|
||||
gfx::msg(
|
||||
&mut sh1107,
|
||||
"Copy files to device",
|
||||
Point::new(6, 64),
|
||||
Mono::White.into(),
|
||||
Mono::Black.into(),
|
||||
);
|
||||
gfx::msg(
|
||||
&mut sh1107,
|
||||
"Press SELECT",
|
||||
Point::new(22, 46),
|
||||
Mono::Black.into(),
|
||||
Mono::White.into(),
|
||||
);
|
||||
gfx::msg(
|
||||
&mut sh1107,
|
||||
"when finished!",
|
||||
Point::new(19, 32),
|
||||
Mono::Black.into(),
|
||||
Mono::White.into(),
|
||||
);
|
||||
sh1107.buffer_swap();
|
||||
sh1107.draw();
|
||||
last_usb_state = new_usb_state;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let disk = usb::conjure_disk();
|
||||
|
|
@ -149,118 +205,9 @@ pub fn process_update(perclk: u32) {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SliceCursor<'a> {
|
||||
slice: &'a mut [u8],
|
||||
pos: u64,
|
||||
}
|
||||
|
||||
impl<'a> SliceCursor<'a> {
|
||||
pub fn new(slice: &'a mut [u8]) -> Self { Self { slice, pos: 0 } }
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||
pub enum IOErrorFatfs {
|
||||
UnexpectedEof,
|
||||
Interrupted,
|
||||
InvalidData,
|
||||
Description,
|
||||
SeekUnderflow,
|
||||
SeekOverflow,
|
||||
SeekOutOfBounds,
|
||||
}
|
||||
|
||||
impl Display for IOErrorFatfs {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
match self {
|
||||
IOErrorFatfs::UnexpectedEof => write!(f, "Unexpected EOF"),
|
||||
IOErrorFatfs::Interrupted => write!(f, "Interrupted"),
|
||||
IOErrorFatfs::InvalidData => write!(f, "Invalid Data"),
|
||||
IOErrorFatfs::Description => write!(f, "Unsupported string description"),
|
||||
IOErrorFatfs::SeekOutOfBounds => write!(f, "Seek out of bounds"),
|
||||
IOErrorFatfs::SeekOverflow => write!(f, "Seek overflow"),
|
||||
IOErrorFatfs::SeekUnderflow => write!(f, "Seek underflow"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for IOErrorFatfs {
|
||||
fn from(_value: &str) -> Self { IOErrorFatfs::Description }
|
||||
}
|
||||
impl IOErrorKind for IOErrorFatfs {
|
||||
fn new_unexpected_eof() -> Self { Self::UnexpectedEof }
|
||||
|
||||
fn new_invalid_data() -> Self { Self::InvalidData }
|
||||
|
||||
fn new_interrupted() -> Self { Self::Interrupted }
|
||||
}
|
||||
impl IOError for IOErrorFatfs {
|
||||
type Kind = IOErrorFatfs;
|
||||
|
||||
fn new<M>(kind: Self::Kind, _msg: M) -> Self
|
||||
where
|
||||
M: core::fmt::Display,
|
||||
{
|
||||
kind
|
||||
}
|
||||
|
||||
fn kind(&self) -> Self::Kind { *self }
|
||||
}
|
||||
|
||||
impl simple_fatfs::Error for IOErrorFatfs {}
|
||||
|
||||
impl IOBase for SliceCursor<'_> {
|
||||
type Error = IOErrorFatfs;
|
||||
}
|
||||
|
||||
impl Seek for SliceCursor<'_> {
|
||||
fn seek(&mut self, seek_from: simple_fatfs::io::SeekFrom) -> Result<u64, Self::Error> {
|
||||
let new_pos = match seek_from {
|
||||
SeekFrom::Start(offset) => offset,
|
||||
SeekFrom::End(offset) => {
|
||||
let result = if offset < 0 {
|
||||
self.slice.len().checked_sub((-offset) as usize).ok_or(IOErrorFatfs::SeekUnderflow)?
|
||||
} else {
|
||||
self.slice.len().checked_add(offset as usize).ok_or(IOErrorFatfs::SeekOverflow)?
|
||||
};
|
||||
result as u64
|
||||
}
|
||||
SeekFrom::Current(offset) => {
|
||||
if offset < 0 {
|
||||
self.pos.checked_sub((-offset) as u64).ok_or(IOErrorFatfs::SeekUnderflow)?
|
||||
} else {
|
||||
self.pos.checked_add(offset as u64).ok_or(IOErrorFatfs::SeekUnderflow)?
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if new_pos > self.slice.len() as u64 {
|
||||
Err(IOErrorFatfs::SeekOutOfBounds)
|
||||
} else {
|
||||
self.pos = new_pos;
|
||||
Ok(self.pos)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Read for SliceCursor<'_> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
|
||||
let available = &self.slice[self.pos as usize..];
|
||||
let to_read = buf.len().min(available.len());
|
||||
buf[..to_read].copy_from_slice(&available[..to_read]);
|
||||
self.pos += to_read as u64;
|
||||
Ok(to_read)
|
||||
}
|
||||
}
|
||||
impl Write for SliceCursor<'_> {
|
||||
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
|
||||
let available = &mut self.slice[self.pos as usize..];
|
||||
let to_write = buf.len().min(available.len());
|
||||
available[..to_write].copy_from_slice(&buf[..to_write]);
|
||||
self.pos += to_write as u64;
|
||||
Ok(to_write)
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> Result<(), Self::Error> { Ok(()) }
|
||||
|
||||
gfx::msg(&mut sh1107, " Booting Xous...", Point::new(0, 64), Mono::White.into(), Mono::Black.into());
|
||||
sh1107.buffer_swap();
|
||||
sh1107.draw();
|
||||
sh1107.clear();
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue