mirror of
https://github.com/LegitCamper/picocalc-os-rs.git
synced 2025-12-26 23:35:53 +00:00
clippy
This commit is contained in:
@@ -11,7 +11,7 @@ doctest = false
|
||||
bench = false
|
||||
|
||||
[features]
|
||||
default = ["rp235x", "defmt"]
|
||||
default = ["rp235x"]
|
||||
pimoroni2w = ["rp235x", "psram"]
|
||||
# rp2040 = ["embassy-rp/rp2040"] # unsupported, ram too small for fb
|
||||
rp235x = ["embassy-rp/rp235xb"]
|
||||
|
||||
@@ -14,7 +14,7 @@ use std::io::Write;
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[cfg(all(feature = "rp235x", not(feature = "pimoroni2w")))]
|
||||
const MEMORY: &'static [u8] = include_bytes!("rp2350.x");
|
||||
const MEMORY: &[u8] = include_bytes!("rp2350.x");
|
||||
#[cfg(feature = "pimoroni2w")]
|
||||
const MEMORY: &'static [u8] = include_bytes!("rp2350.x");
|
||||
|
||||
|
||||
@@ -120,8 +120,10 @@ impl<'d, PIO: Instance, const SM: usize> PioPwmAudio<'d, PIO, SM> {
|
||||
let mut cfg = Config::default();
|
||||
cfg.set_set_pins(&[&pin]);
|
||||
cfg.fifo_join = FifoJoin::TxOnly;
|
||||
let mut shift_cfg = ShiftConfig::default();
|
||||
shift_cfg.auto_fill = true;
|
||||
let shift_cfg = ShiftConfig {
|
||||
auto_fill: true,
|
||||
..Default::default()
|
||||
};
|
||||
cfg.shift_out = shift_cfg;
|
||||
cfg.use_program(&prg.0, &[]);
|
||||
sm.set_config(&cfg);
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
use crate::framebuffer::{self, AtomicFrameBuffer, FB_PAUSED};
|
||||
use core::alloc::{GlobalAlloc, Layout};
|
||||
use core::sync::atomic::Ordering;
|
||||
use embassy_futures::yield_now;
|
||||
use embassy_rp::{
|
||||
@@ -9,17 +8,20 @@ use embassy_rp::{
|
||||
spi::{Async, Spi},
|
||||
};
|
||||
use embassy_time::Delay;
|
||||
use embedded_graphics::{draw_target::DrawTarget, pixelcolor::Rgb565, prelude::RgbColor};
|
||||
use embedded_hal_bus::spi::ExclusiveDevice;
|
||||
use st7365p_lcd::ST7365P;
|
||||
|
||||
#[cfg(feature = "psram")]
|
||||
use crate::heap::HEAP;
|
||||
#[cfg(feature = "psram")]
|
||||
use core::alloc::{GlobalAlloc, Layout};
|
||||
#[cfg(feature = "psram")]
|
||||
use embedded_graphics::{draw_target::DrawTarget, pixelcolor::Rgb565, prelude::RgbColor};
|
||||
|
||||
#[cfg(feature = "fps")]
|
||||
pub use framebuffer::fps::{FPS_CANVAS, FPS_COUNTER};
|
||||
|
||||
type DISPLAY = ST7365P<
|
||||
type Display = ST7365P<
|
||||
ExclusiveDevice<Spi<'static, SPI1, Async>, Output<'static>, Delay>,
|
||||
Output<'static>,
|
||||
Output<'static>,
|
||||
@@ -56,7 +58,7 @@ pub async fn init_display(
|
||||
cs: Peri<'static, PIN_13>,
|
||||
data: Peri<'static, PIN_14>,
|
||||
reset: Peri<'static, PIN_15>,
|
||||
) -> DISPLAY {
|
||||
) -> Display {
|
||||
init_fb();
|
||||
|
||||
let spi_device = ExclusiveDevice::new(spi, Output::new(cs, Level::Low), Delay).unwrap();
|
||||
@@ -84,7 +86,7 @@ pub async fn init_display(
|
||||
}
|
||||
|
||||
#[embassy_executor::task]
|
||||
pub async fn display_handler(mut display: DISPLAY) {
|
||||
pub async fn display_handler(mut display: Display) {
|
||||
use embassy_time::{Instant, Timer};
|
||||
|
||||
// Target ~60 Hz refresh (≈16.67 ms per frame)
|
||||
@@ -111,7 +113,7 @@ pub async fn display_handler(mut display: DISPLAY) {
|
||||
}
|
||||
}
|
||||
|
||||
let elapsed = start.elapsed().as_millis() as u64;
|
||||
let elapsed = start.elapsed().as_millis();
|
||||
if elapsed < FRAME_TIME_MS {
|
||||
Timer::after_millis(FRAME_TIME_MS - elapsed).await;
|
||||
} else {
|
||||
|
||||
@@ -39,7 +39,7 @@ pub async unsafe fn load_binary(name: &ShortFileName) -> Option<(EntryFn, Bump)>
|
||||
let mut ph_buf = vec![0_u8; elf_header.e_phentsize as usize];
|
||||
|
||||
let (total_size, min_vaddr, _max_vaddr) =
|
||||
total_loadable_size(&mut file, &elf_header, &mut ph_buf);
|
||||
total_loadable_size(&mut file, elf_header, &mut ph_buf);
|
||||
|
||||
let bump = Bump::with_capacity(total_size);
|
||||
let base = bump.alloc_slice_fill_default::<u8>(total_size);
|
||||
@@ -52,25 +52,22 @@ pub async unsafe fn load_binary(name: &ShortFileName) -> Option<(EntryFn, Bump)>
|
||||
let ph = cast_phdr(&ph_buf);
|
||||
|
||||
let seg_offset = (ph.p_vaddr - min_vaddr) as usize;
|
||||
let mut segment = &mut base[seg_offset..seg_offset + ph.p_memsz as usize];
|
||||
let segment = &mut base[seg_offset..seg_offset + ph.p_memsz as usize];
|
||||
|
||||
if ph.p_type == PT_LOAD {
|
||||
load_segment(&mut file, &ph, &mut segment).unwrap();
|
||||
load_segment(&mut file, &ph, segment).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
for i in 0..elf_header.e_shnum {
|
||||
let sh = read_section(&mut file, elf_header, i.into());
|
||||
|
||||
match sh.sh_type {
|
||||
SHT_REL => {
|
||||
if sh.sh_type == SHT_REL {
|
||||
apply_relocations(&sh, min_vaddr, base.as_mut_ptr(), &mut file).unwrap();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
patch_syscalls(&elf_header, base.as_mut_ptr(), min_vaddr, &mut file).unwrap();
|
||||
patch_syscalls(elf_header, base.as_mut_ptr(), min_vaddr, &mut file).unwrap();
|
||||
|
||||
// entry pointer is base_ptr + (entry - min_vaddr)
|
||||
let entry_ptr: EntryFn = unsafe {
|
||||
@@ -157,7 +154,7 @@ fn patch_syscalls(
|
||||
file: &mut File,
|
||||
) -> Result<(), ()> {
|
||||
for i in 1..=elf_header.e_shnum {
|
||||
let sh = read_section(file, &elf_header, i.into());
|
||||
let sh = read_section(file, elf_header, i.into());
|
||||
|
||||
// find the symbol table
|
||||
if sh.sh_type == SHT_SYMTAB {
|
||||
@@ -172,7 +169,7 @@ fn patch_syscalls(
|
||||
&symtab_buf[i * sh.sh_entsize as usize..(i + 1) * sh.sh_entsize as usize];
|
||||
let sym = cast_sym(sym_bytes);
|
||||
|
||||
let str_sh = read_section(file, &elf_header, sh.sh_link);
|
||||
let str_sh = read_section(file, elf_header, sh.sh_link);
|
||||
|
||||
let mut name = Vec::new();
|
||||
file.seek_from_start(str_sh.sh_offset + sym.st_name)
|
||||
@@ -211,7 +208,7 @@ fn patch_syscalls(
|
||||
SyscallTable::SendAudioBuffer => syscalls::send_audio_buffer as usize,
|
||||
};
|
||||
unsafe {
|
||||
table_base.add(idx as usize).write(ptr);
|
||||
table_base.add(idx).write(ptr);
|
||||
}
|
||||
}
|
||||
return Ok(());
|
||||
@@ -233,7 +230,7 @@ fn total_loadable_size(
|
||||
file.seek_from_start(elf_header.e_phoff + (elf_header.e_phentsize * i) as u32)
|
||||
.unwrap();
|
||||
file.read(ph_buf).unwrap();
|
||||
let ph = cast_phdr(&ph_buf);
|
||||
let ph = cast_phdr(ph_buf);
|
||||
|
||||
if ph.p_type == PT_LOAD {
|
||||
if ph.p_vaddr < min_vaddr {
|
||||
|
||||
@@ -46,7 +46,7 @@ impl<'a> AtomicFrameBuffer<'a> {
|
||||
}
|
||||
|
||||
fn mark_tiles_dirty(&mut self, rect: Rectangle) {
|
||||
let tiles_x = (SCREEN_WIDTH + TILE_SIZE - 1) / TILE_SIZE;
|
||||
let tiles_x = SCREEN_WIDTH.div_ceil(TILE_SIZE);
|
||||
let start_tx = (rect.top_left.x as usize) / TILE_SIZE;
|
||||
let end_tx = ((rect.top_left.x + rect.size.width as i32 - 1) as usize) / TILE_SIZE;
|
||||
let start_ty = (rect.top_left.y as usize) / TILE_SIZE;
|
||||
@@ -346,11 +346,10 @@ impl<'a> DrawTarget for AtomicFrameBuffer<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
if changed {
|
||||
if let Some(rect) = dirty_rect {
|
||||
if changed
|
||||
&& let Some(rect) = dirty_rect {
|
||||
self.mark_tiles_dirty(rect);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -402,7 +401,7 @@ impl<'a> DrawTarget for AtomicFrameBuffer<'a> {
|
||||
fn fill_solid(&mut self, area: &Rectangle, color: Self::Color) -> Result<(), Self::Error> {
|
||||
self.fill_contiguous(
|
||||
area,
|
||||
core::iter::repeat(color).take((self.size().width * self.size().height) as usize),
|
||||
core::iter::repeat_n(color, (self.size().width * self.size().height) as usize),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -412,8 +411,7 @@ impl<'a> DrawTarget for AtomicFrameBuffer<'a> {
|
||||
0,
|
||||
self.size().width as u16 - 1,
|
||||
self.size().height as u16 - 1,
|
||||
core::iter::repeat(RawU16::from(color).into_inner())
|
||||
.take((self.size().width * self.size().height) as usize),
|
||||
core::iter::repeat_n(RawU16::from(color).into_inner(), (self.size().width * self.size().height) as usize),
|
||||
)?;
|
||||
|
||||
for tile in self.dirty_tiles.iter() {
|
||||
|
||||
@@ -12,11 +12,15 @@ mod audio;
|
||||
mod display;
|
||||
mod elf;
|
||||
mod framebuffer;
|
||||
// TODO: NEED TO UPDATE MCU TO TEST BATTERY READS
|
||||
#[allow(unused)]
|
||||
mod peripherals;
|
||||
#[allow(unused)]
|
||||
mod scsi;
|
||||
mod storage;
|
||||
mod syscalls;
|
||||
mod ui;
|
||||
#[allow(unused)]
|
||||
mod usb;
|
||||
mod utils;
|
||||
|
||||
@@ -28,7 +32,7 @@ mod heap;
|
||||
mod psram;
|
||||
|
||||
#[cfg(feature = "psram")]
|
||||
use crate::{heap::HEAP, heap::init_qmi_psram_heap, psram::init_psram, psram::init_psram_qmi};
|
||||
use crate::{heap::init_qmi_psram_heap, psram::init_psram_qmi};
|
||||
|
||||
use crate::{
|
||||
audio::audio_handler,
|
||||
@@ -102,7 +106,7 @@ async fn watchdog_task(mut watchdog: Watchdog) {
|
||||
ResetReason::Forced => "forced",
|
||||
ResetReason::TimedOut => "timed out",
|
||||
};
|
||||
#[cfg(feature = "debug")]
|
||||
#[cfg(feature = "defmt")]
|
||||
defmt::error!("Watchdog reset reason: {}", _reason);
|
||||
}
|
||||
|
||||
@@ -321,7 +325,7 @@ async fn setup_display(display: Display, spawner: Spawner) {
|
||||
async fn setup_qmi_psram() {
|
||||
Timer::after_millis(250).await;
|
||||
let psram_qmi_size = init_psram_qmi(&embassy_rp::pac::QMI, &embassy_rp::pac::XIP_CTRL);
|
||||
#[cfg(feature = "debug")]
|
||||
#[cfg(feature = "defmt")]
|
||||
defmt::info!("size: {}", psram_qmi_size);
|
||||
Timer::after_millis(100).await;
|
||||
|
||||
@@ -363,7 +367,7 @@ async fn kernel_task(
|
||||
.spawn(watchdog_task(Watchdog::new(watchdog)))
|
||||
.unwrap();
|
||||
|
||||
#[cfg(feature = "debug")]
|
||||
#[cfg(feature = "defmt")]
|
||||
defmt::info!("Clock: {}", embassy_rp::clocks::clk_sys_freq());
|
||||
|
||||
setup_mcu(mcu).await;
|
||||
|
||||
@@ -526,7 +526,7 @@ pub fn init_psram_qmi(
|
||||
let psram_size = detect_psram_qmi(qmi);
|
||||
|
||||
if psram_size == 0 {
|
||||
#[cfg(feature = "debug")]
|
||||
#[cfg(feature = "defmt")]
|
||||
defmt::error!("qmi psram size 0");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ pub struct MassStorageClass<'d, D: Driver<'d>> {
|
||||
bulk_in: D::EndpointIn,
|
||||
}
|
||||
|
||||
impl<'d, 's, D: Driver<'d>> MassStorageClass<'d, D> {
|
||||
impl<'d, D: Driver<'d>> MassStorageClass<'d, D> {
|
||||
pub fn new(builder: &mut Builder<'d, D>, temp_sd: Option<SdCard>) -> Self {
|
||||
let mut function = builder.function(0x08, SUBCLASS_SCSI, 0x50); // Mass Storage class
|
||||
let mut interface = function.interface();
|
||||
@@ -72,9 +72,10 @@ impl<'d, 's, D: Driver<'d>> MassStorageClass<'d, D> {
|
||||
|
||||
async fn handle_cbw(&mut self) {
|
||||
let mut cbw_buf = [0u8; 31];
|
||||
if let Ok(n) = self.bulk_out.read(&mut cbw_buf).await {
|
||||
if n == 31 {
|
||||
if let Some(cbw) = CommandBlockWrapper::parse(&cbw_buf[..n]) {
|
||||
if let Ok(n) = self.bulk_out.read(&mut cbw_buf).await
|
||||
&& n == 31
|
||||
&& let Some(cbw) = CommandBlockWrapper::parse(&cbw_buf[..n])
|
||||
{
|
||||
// Take sdcard to increase speed
|
||||
if self.temp_sd.is_none() {
|
||||
let mut guard = SDCARD.get().lock().await;
|
||||
@@ -94,15 +95,13 @@ impl<'d, 's, D: Driver<'d>> MassStorageClass<'d, D> {
|
||||
self.send_csw_fail(cbw.dCBWTag).await
|
||||
}
|
||||
|
||||
if self.pending_eject {
|
||||
if let ScsiCommand::Write { lba: _, len: _ } = command {
|
||||
if self.pending_eject
|
||||
&& let ScsiCommand::Write { lba: _, len: _ } = command
|
||||
{
|
||||
MSC_SHUTDOWN.signal(());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn handle_command(&mut self, command: ScsiCommand) -> Result<(), ()> {
|
||||
let mut response: Vec<u8, BULK_ENDPOINT_PACKET_SIZE> = Vec::new();
|
||||
@@ -238,7 +237,7 @@ impl<'d, 's, D: Driver<'d>> MassStorageClass<'d, D> {
|
||||
let block_size = SdCard::BLOCK_SIZE as u64;
|
||||
let total_blocks = self.temp_sd.as_ref().unwrap().size() / block_size;
|
||||
|
||||
let last_lba = total_blocks.checked_sub(1).unwrap_or(0);
|
||||
let last_lba = total_blocks.saturating_sub(1);
|
||||
|
||||
response.extend_from_slice(&(last_lba as u32).to_be_bytes())?;
|
||||
response.extend_from_slice(&(block_size as u32).to_be_bytes())?;
|
||||
@@ -249,7 +248,7 @@ impl<'d, 's, D: Driver<'d>> MassStorageClass<'d, D> {
|
||||
let block_size = SdCard::BLOCK_SIZE as u64;
|
||||
let total_blocks = self.temp_sd.as_ref().unwrap().size() / block_size;
|
||||
|
||||
let last_lba = total_blocks.checked_sub(1).unwrap_or(0);
|
||||
let last_lba = total_blocks.saturating_sub(1);
|
||||
|
||||
response.extend_from_slice(&last_lba.to_be_bytes())?; // 8 bytes last LBA
|
||||
response.extend_from_slice(&(block_size as u32).to_be_bytes())?; // 4 bytes block length
|
||||
@@ -269,7 +268,7 @@ impl<'d, 's, D: Driver<'d>> MassStorageClass<'d, D> {
|
||||
sdcard.read_blocks(block_buf, BlockIdx(idx as u32))?;
|
||||
|
||||
for block in &mut *block_buf {
|
||||
for chunk in block.contents.chunks(BULK_ENDPOINT_PACKET_SIZE.into()) {
|
||||
for chunk in block.contents.chunks(BULK_ENDPOINT_PACKET_SIZE) {
|
||||
self.bulk_in.write(chunk).await.map_err(|_| ())?;
|
||||
}
|
||||
}
|
||||
@@ -281,7 +280,7 @@ impl<'d, 's, D: Driver<'d>> MassStorageClass<'d, D> {
|
||||
.read_blocks(&mut block_buf[..blocks as usize], BlockIdx(idx as u32))?;
|
||||
|
||||
for block in &block_buf[..blocks as usize] {
|
||||
for chunk in block.contents.chunks(BULK_ENDPOINT_PACKET_SIZE.into()) {
|
||||
for chunk in block.contents.chunks(BULK_ENDPOINT_PACKET_SIZE) {
|
||||
self.bulk_in.write(chunk).await.map_err(|_| ())?;
|
||||
}
|
||||
}
|
||||
@@ -301,8 +300,7 @@ impl<'d, 's, D: Driver<'d>> MassStorageClass<'d, D> {
|
||||
while blocks > 0 {
|
||||
if blocks >= block_buf.len() as u64 {
|
||||
for block in block_buf.as_mut() {
|
||||
for chunk in block.contents.chunks_mut(BULK_ENDPOINT_PACKET_SIZE.into())
|
||||
{
|
||||
for chunk in block.contents.chunks_mut(BULK_ENDPOINT_PACKET_SIZE) {
|
||||
self.bulk_out.read(chunk).await.map_err(|_| ())?;
|
||||
}
|
||||
}
|
||||
@@ -313,8 +311,7 @@ impl<'d, 's, D: Driver<'d>> MassStorageClass<'d, D> {
|
||||
idx += block_buf.len() as u64;
|
||||
} else {
|
||||
for block in block_buf[..blocks as usize].as_mut() {
|
||||
for chunk in block.contents.chunks_mut(BULK_ENDPOINT_PACKET_SIZE.into())
|
||||
{
|
||||
for chunk in block.contents.chunks_mut(BULK_ENDPOINT_PACKET_SIZE) {
|
||||
self.bulk_out.read(chunk).await.map_err(|_| ())?;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use num_enum::TryFromPrimitive;
|
||||
|
||||
/// THE CODE BELOW ORIGINATES FROM: https://github.com/apohrebniak/usbd-storage/blob/master/usbd-storage/src/subclass/scsi.rs
|
||||
|
||||
///
|
||||
/// SCSI device subclass code
|
||||
pub const SUBCLASS_SCSI: u8 = 0x06; // SCSI Transparent command set
|
||||
|
||||
@@ -91,6 +91,7 @@ pub enum ScsiCommand {
|
||||
},
|
||||
}
|
||||
|
||||
#[allow(clippy::enum_variant_names)]
|
||||
#[repr(u8)]
|
||||
#[derive(Copy, Clone, Debug, TryFromPrimitive)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
|
||||
@@ -9,8 +9,8 @@ use embassy_sync::mutex::Mutex;
|
||||
use embassy_time::Delay;
|
||||
use embedded_hal_bus::spi::ExclusiveDevice;
|
||||
use embedded_sdmmc::{
|
||||
Block, BlockCount, BlockDevice, BlockIdx, Directory, SdCard as SdmmcSdCard, TimeSource,
|
||||
Timestamp, Volume, VolumeIdx, VolumeManager, sdcard::Error,
|
||||
Block, BlockDevice, BlockIdx, Directory, SdCard as SdmmcSdCard, TimeSource, Timestamp,
|
||||
VolumeIdx, VolumeManager, sdcard::Error,
|
||||
};
|
||||
use embedded_sdmmc::{File as SdFile, LfnBuffer, Mode, ShortFileName};
|
||||
|
||||
@@ -21,7 +21,6 @@ pub const MAX_VOLUMES: usize = 1;
|
||||
type Device = ExclusiveDevice<Spi<'static, SPI0, Blocking>, Output<'static>, embassy_time::Delay>;
|
||||
type SD = SdmmcSdCard<Device, Delay>;
|
||||
type VolMgr = VolumeManager<SD, DummyTimeSource, MAX_DIRS, MAX_FILES, MAX_VOLUMES>;
|
||||
type Vol<'a> = Volume<'a, SD, DummyTimeSource, MAX_DIRS, MAX_FILES, MAX_VOLUMES>;
|
||||
pub type Dir<'a> = Directory<'a, SD, DummyTimeSource, MAX_DIRS, MAX_FILES, MAX_VOLUMES>;
|
||||
pub type File<'a> = SdFile<'a, SD, DummyTimeSource, MAX_DIRS, MAX_FILES, MAX_VOLUMES>;
|
||||
|
||||
@@ -43,7 +42,7 @@ pub struct FileName {
|
||||
|
||||
impl PartialOrd for FileName {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
|
||||
Some(self.long_name.cmp(&other.long_name))
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,10 +66,7 @@ impl SdCard {
|
||||
DummyTimeSource {},
|
||||
5000,
|
||||
);
|
||||
Self {
|
||||
det: det,
|
||||
volume_mgr,
|
||||
}
|
||||
Self { det, volume_mgr }
|
||||
}
|
||||
|
||||
/// Returns true if an SD card is inserted.
|
||||
@@ -90,17 +86,6 @@ impl SdCard {
|
||||
result
|
||||
}
|
||||
|
||||
pub fn num_blocks(&self) -> u32 {
|
||||
let mut result = 0;
|
||||
|
||||
self.volume_mgr.device(|sd| {
|
||||
result = sd.num_blocks().unwrap_or(BlockCount(0)).0;
|
||||
DummyTimeSource {}
|
||||
});
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
pub fn read_blocks(&self, blocks: &mut [Block], start_block_idx: BlockIdx) -> Result<(), ()> {
|
||||
let mut res: Result<(), Error> = Ok(());
|
||||
self.volume_mgr.device(|sd| {
|
||||
|
||||
@@ -35,7 +35,7 @@ pub extern "C" fn alloc(layout: CLayout) -> *mut u8 {
|
||||
|
||||
#[cfg(not(feature = "psram"))]
|
||||
{
|
||||
return alloc::alloc::alloc(layout.into());
|
||||
alloc::alloc::alloc(layout.into())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -134,7 +134,7 @@ unsafe fn copy_entry_to_user_buf(name: &[u8], dest: *mut c_char, max_str_len: us
|
||||
if !dest.is_null() {
|
||||
let len = name.len().min(max_str_len - 1);
|
||||
unsafe {
|
||||
ptr::copy_nonoverlapping(name.as_ptr(), dest as *mut u8, len);
|
||||
ptr::copy_nonoverlapping(name.as_ptr(), dest, len);
|
||||
*dest.add(len) = 0; // nul terminator
|
||||
}
|
||||
}
|
||||
@@ -191,7 +191,7 @@ pub extern "C" fn list_dir(
|
||||
|
||||
let mut wrote = 0;
|
||||
sd.access_root_dir(|root| {
|
||||
if dirs[0] == "" && dirs.len() >= 2 {
|
||||
if dirs[0].is_empty() && dirs.len() >= 2 {
|
||||
unsafe {
|
||||
if dir == "/" {
|
||||
wrote = get_dir_entries(&root, files, max_entry_str_len);
|
||||
@@ -214,11 +214,11 @@ fn recurse_file<T>(
|
||||
let mut buf = LfnBuffer::new(&mut b);
|
||||
let mut short_name = None;
|
||||
dir.iterate_dir_lfn(&mut buf, |entry, name| {
|
||||
if let Some(name) = name {
|
||||
if name == dirs[0] || entry.name.to_string().as_str() == dirs[0] {
|
||||
if let Some(name) = name
|
||||
&& (name == dirs[0] || entry.name.to_string().as_str() == dirs[0])
|
||||
{
|
||||
short_name = Some(entry.name.clone());
|
||||
}
|
||||
}
|
||||
})
|
||||
.expect("Failed to iterate dir");
|
||||
|
||||
@@ -257,7 +257,7 @@ pub extern "C" fn read_file(
|
||||
}
|
||||
|
||||
// SAFETY: caller guarantees `ptr` is valid for `len` bytes
|
||||
let mut buf = unsafe { core::slice::from_raw_parts_mut(buf, buf_len) };
|
||||
let buf = unsafe { core::slice::from_raw_parts_mut(buf, buf_len) };
|
||||
|
||||
let mut read = 0;
|
||||
|
||||
@@ -267,7 +267,7 @@ pub extern "C" fn read_file(
|
||||
sd.access_root_dir(|root| {
|
||||
if let Ok(result) = recurse_file(&root, &components[1..count], |file| {
|
||||
file.seek_from_start(start_from as u32).unwrap_or(());
|
||||
file.read(&mut buf).unwrap()
|
||||
file.read(buf).unwrap()
|
||||
}) {
|
||||
read = result
|
||||
};
|
||||
@@ -306,7 +306,7 @@ pub extern "C" fn write_file(
|
||||
sd.access_root_dir(|root| {
|
||||
recurse_file(&root, &components[1..count], |file| {
|
||||
file.seek_from_start(start_from as u32).unwrap();
|
||||
file.write(&buf).unwrap()
|
||||
file.write(buf).unwrap()
|
||||
})
|
||||
.unwrap_or(())
|
||||
});
|
||||
@@ -343,7 +343,9 @@ pub extern "C" fn send_audio_buffer(ptr: *const u8, len: usize) {
|
||||
// SAFETY: caller guarantees `ptr` is valid for `len` bytes
|
||||
let buf = unsafe { core::slice::from_raw_parts(ptr, len) };
|
||||
|
||||
while !AUDIO_BUFFER_READY.load(Ordering::Acquire) {}
|
||||
while !AUDIO_BUFFER_READY.load(Ordering::Acquire) {
|
||||
core::hint::spin_loop();
|
||||
}
|
||||
|
||||
if buf.len() == AUDIO_BUFFER_SAMPLES * 2 {
|
||||
AUDIO_BUFFER_READY.store(false, Ordering::Release);
|
||||
|
||||
@@ -2,7 +2,6 @@ use crate::{
|
||||
BINARY_CH, display::FRAMEBUFFER, elf::load_binary, framebuffer::FB_PAUSED,
|
||||
peripherals::keyboard, storage::FileName,
|
||||
};
|
||||
use userlib_sys::keyboard::{KeyCode, KeyState};
|
||||
use alloc::{str::FromStr, string::String, vec::Vec};
|
||||
use core::sync::atomic::Ordering;
|
||||
use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, mutex::Mutex};
|
||||
@@ -20,14 +19,16 @@ use embedded_layout::{
|
||||
prelude::*,
|
||||
};
|
||||
use embedded_text::TextBox;
|
||||
use userlib_sys::keyboard::{KeyCode, KeyState};
|
||||
|
||||
pub static SELECTIONS: Mutex<CriticalSectionRawMutex, SelectionList> =
|
||||
Mutex::new(SelectionList::new());
|
||||
|
||||
pub async fn ui_handler() {
|
||||
loop {
|
||||
if let Some(event) = keyboard::read_keyboard_fifo().await {
|
||||
if let KeyState::Pressed = event.state {
|
||||
if let Some(event) = keyboard::read_keyboard_fifo().await
|
||||
&& let KeyState::Pressed = event.state
|
||||
{
|
||||
match event.key {
|
||||
KeyCode::Up => {
|
||||
let mut selections = SELECTIONS.lock().await;
|
||||
@@ -52,7 +53,6 @@ pub async fn ui_handler() {
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let changed = SELECTIONS.lock().await.changed;
|
||||
if changed {
|
||||
|
||||
@@ -51,16 +51,15 @@ impl<'a> SelectionUi<'a> {
|
||||
let selection;
|
||||
loop {
|
||||
let key = get_key();
|
||||
if key.state == KeyState::Pressed {
|
||||
if let Some(s) = self.update(display, key.key)? {
|
||||
if key.state == KeyState::Pressed
|
||||
&& let Some(s) = self.update(display, key.key)? {
|
||||
selection = Some(s);
|
||||
display
|
||||
.clear(Rgb565::BLACK)
|
||||
.map_err(|e| SelectionUiError::DisplayError(e))?;
|
||||
.map_err(SelectionUiError::DisplayError)?;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(selection)
|
||||
}
|
||||
|
||||
@@ -100,7 +99,7 @@ impl<'a> SelectionUi<'a> {
|
||||
Rectangle::new(bounds.top_left, bounds.size)
|
||||
.into_styled(PrimitiveStyle::with_fill(Rgb565::BLACK))
|
||||
.draw(display)
|
||||
.map_err(|e| SelectionUiError::DisplayError(e))?;
|
||||
.map_err(SelectionUiError::DisplayError)?;
|
||||
}
|
||||
|
||||
let mut views: Vec<Text<MonoTextStyle<Rgb565>>> = Vec::new();
|
||||
@@ -119,7 +118,7 @@ impl<'a> SelectionUi<'a> {
|
||||
|
||||
layout
|
||||
.draw(display)
|
||||
.map_err(|e| SelectionUiError::DisplayError(e))?;
|
||||
.map_err(SelectionUiError::DisplayError)?;
|
||||
|
||||
// draw selected box
|
||||
if let Some(selected_bounds) = layout.inner().get(self.selection) {
|
||||
@@ -127,7 +126,7 @@ impl<'a> SelectionUi<'a> {
|
||||
Rectangle::new(selected_bounds.top_left, selected_bounds.size)
|
||||
.into_styled(PrimitiveStyle::with_stroke(Rgb565::WHITE, 1))
|
||||
.draw(display)
|
||||
.map_err(|e| SelectionUiError::DisplayError(e))?;
|
||||
.map_err(SelectionUiError::DisplayError)?;
|
||||
|
||||
self.last_bounds = Some(selected_bounds);
|
||||
}
|
||||
@@ -136,9 +135,9 @@ impl<'a> SelectionUi<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw_text_center<'a, S>(
|
||||
pub fn draw_text_center<S>(
|
||||
display: &mut Display,
|
||||
text: &'a str,
|
||||
text: &str,
|
||||
style: S,
|
||||
) -> Result<Point, <Display as DrawTarget>::Error>
|
||||
where
|
||||
|
||||
@@ -83,7 +83,7 @@ pub fn main() {
|
||||
.align_to(&display.bounding_box(), horizontal::Left, vertical::Center);
|
||||
|
||||
let result = if let Ok(result) = evaluate(&input[input_min..]) {
|
||||
&format!(" = {}", result)
|
||||
&format!(" = {result}")
|
||||
} else {
|
||||
" = Error"
|
||||
};
|
||||
|
||||
@@ -51,9 +51,9 @@ pub fn main() {
|
||||
|
||||
println!("file: {}", file);
|
||||
if file.extension().unwrap_or("") == "bmp" || file.extension().unwrap_or("") == "BMP" {
|
||||
let file_path = format!("/images/{}", file);
|
||||
let file_path = format!("/images/{file}");
|
||||
|
||||
let read = read_file(&file_path, 0, &mut &mut bmp_buf[..]);
|
||||
let read = read_file(&file_path, 0, &mut bmp_buf[..]);
|
||||
if read > 0 {
|
||||
let bmp = Bmp::from_slice(&bmp_buf).expect("failed to parse bmp");
|
||||
|
||||
@@ -74,7 +74,7 @@ pub fn main() {
|
||||
|
||||
let text_style = MonoTextStyle::new(&FONT_6X10, Rgb565::WHITE);
|
||||
let text_y = y + bmp_h + 2; // 2px gap under image
|
||||
Text::new(&file.base(), Point::new(cell_x + 2, text_y), text_style)
|
||||
Text::new(file.base(), Point::new(cell_x + 2, text_y), text_style)
|
||||
.draw(&mut display)
|
||||
.unwrap();
|
||||
|
||||
@@ -85,11 +85,8 @@ pub fn main() {
|
||||
|
||||
loop {
|
||||
let event = get_key();
|
||||
if event.state != KeyState::Idle {
|
||||
match event.key {
|
||||
KeyCode::Esc => return,
|
||||
_ => (),
|
||||
}
|
||||
};
|
||||
if event.state != KeyState::Idle && event.key == KeyCode::Esc {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,16 +6,16 @@ use alloc::{format, vec, vec::Vec};
|
||||
use core::panic::PanicInfo;
|
||||
use embedded_graphics::{
|
||||
image::ImageDrawable,
|
||||
mono_font::{ascii::FONT_6X10, MonoTextStyle},
|
||||
mono_font::{MonoTextStyle, ascii::FONT_6X10},
|
||||
pixelcolor::Rgb565,
|
||||
prelude::{Point, RgbColor},
|
||||
transform::Transform,
|
||||
};
|
||||
use selection_ui::{draw_text_center, SelectionUi, SelectionUiError};
|
||||
use selection_ui::{SelectionUi, SelectionUiError, draw_text_center};
|
||||
use tinygif::Gif;
|
||||
use userlib::{
|
||||
display::{Display, SCREEN_HEIGHT, SCREEN_WIDTH},
|
||||
fs::{file_len, list_dir, read_file, Entries},
|
||||
fs::{Entries, file_len, list_dir, read_file},
|
||||
get_key, get_ms,
|
||||
keyboard::{KeyCode, KeyState},
|
||||
println, sleep,
|
||||
@@ -44,7 +44,7 @@ pub fn main() {
|
||||
let mut gifs = files.iter().map(|e| e.full_name()).collect::<Vec<&str>>();
|
||||
gifs.sort();
|
||||
|
||||
let mut selection_ui = SelectionUi::new(&mut gifs);
|
||||
let mut selection_ui = SelectionUi::new(&gifs);
|
||||
let selection = match selection_ui.run_selection_ui(&mut display) {
|
||||
Ok(maybe_sel) => maybe_sel,
|
||||
Err(e) => match e {
|
||||
@@ -87,14 +87,9 @@ pub fn main() {
|
||||
|
||||
if frame_num % 5 == 0 {
|
||||
let event = get_key();
|
||||
if event.state != KeyState::Idle {
|
||||
match event.key {
|
||||
KeyCode::Esc => {
|
||||
if event.state != KeyState::Idle && event.key == KeyCode::Esc {
|
||||
drop(buf);
|
||||
return;
|
||||
}
|
||||
_ => (),
|
||||
};
|
||||
};
|
||||
}
|
||||
sleep(((frame.delay_centis as u64) * 10).saturating_sub(start));
|
||||
|
||||
@@ -4,18 +4,18 @@
|
||||
extern crate alloc;
|
||||
use alloc::{string::String, vec::Vec};
|
||||
use core::panic::PanicInfo;
|
||||
use embedded_audio::{wav::Wav, AudioFile, PlatformFile, PlatformFileError};
|
||||
use embedded_audio::{AudioFile, PlatformFile, PlatformFileError, wav::Wav};
|
||||
use embedded_graphics::{
|
||||
mono_font::{ascii::FONT_6X10, MonoTextStyle},
|
||||
mono_font::{MonoTextStyle, ascii::FONT_6X10},
|
||||
pixelcolor::Rgb565,
|
||||
prelude::RgbColor,
|
||||
};
|
||||
use selection_ui::{draw_text_center, SelectionUi, SelectionUiError};
|
||||
use selection_ui::{SelectionUi, SelectionUiError, draw_text_center};
|
||||
use userlib::{
|
||||
audio::{audio_buffer_ready, send_audio_buffer, AUDIO_BUFFER_LEN},
|
||||
audio::{AUDIO_BUFFER_LEN, audio_buffer_ready, send_audio_buffer},
|
||||
display::Display,
|
||||
format,
|
||||
fs::{file_len, list_dir, read_file, Entries},
|
||||
fs::{Entries, file_len, list_dir, read_file},
|
||||
get_key,
|
||||
keyboard::{KeyCode, KeyState},
|
||||
println,
|
||||
@@ -45,7 +45,7 @@ pub fn main() {
|
||||
let mut wavs = files.iter().map(|e| e.full_name()).collect::<Vec<&str>>();
|
||||
wavs.sort();
|
||||
|
||||
let mut selection_ui = SelectionUi::new(&mut wavs);
|
||||
let mut selection_ui = SelectionUi::new(&wavs);
|
||||
let selection = match selection_ui.run_selection_ui(&mut display) {
|
||||
Ok(maybe_sel) => maybe_sel,
|
||||
Err(e) => match e {
|
||||
@@ -72,7 +72,7 @@ pub fn main() {
|
||||
.expect("Display Error");
|
||||
|
||||
let file_name = format!("/music/{}", wavs[selection.unwrap()]);
|
||||
let file = File::new(String::from(file_name));
|
||||
let file = File::new(file_name);
|
||||
let mut wav = Wav::new(file).unwrap();
|
||||
println!("sample rate: {}", wav.sample_rate());
|
||||
println!("channels: {:?}", wav.channels() as u8);
|
||||
@@ -90,11 +90,8 @@ pub fn main() {
|
||||
}
|
||||
|
||||
let event = get_key();
|
||||
if event.state == KeyState::Released {
|
||||
match event.key {
|
||||
KeyCode::Esc => return,
|
||||
_ => (),
|
||||
}
|
||||
if event.state == KeyState::Released && event.key == KeyCode::Esc {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,6 +228,12 @@ pub mod fs {
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Entries([[u8; MAX_ENTRY_NAME_LEN]; MAX_ENTRIES]);
|
||||
|
||||
impl Default for Entries {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl Entries {
|
||||
pub fn new() -> Self {
|
||||
Self([[0; MAX_ENTRY_NAME_LEN]; MAX_ENTRIES])
|
||||
|
||||
@@ -46,9 +46,9 @@ pub struct CLayout {
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl Into<Layout> for CLayout {
|
||||
fn into(self) -> Layout {
|
||||
unsafe { Layout::from_size_align_unchecked(self.size, self.alignment) }
|
||||
impl From<CLayout> for Layout {
|
||||
fn from(val: CLayout) -> Self {
|
||||
unsafe { Layout::from_size_align_unchecked(val.size, val.alignment) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ pub extern "C" fn get_ms() -> u64 {
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Default, Copy, Clone)]
|
||||
pub struct CPixel {
|
||||
pub x: i32,
|
||||
pub y: i32,
|
||||
@@ -123,19 +123,22 @@ impl CPixel {
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<CPixel> for Pixel<Rgb565> {
|
||||
fn into(self) -> CPixel {
|
||||
CPixel {
|
||||
x: self.0.x,
|
||||
y: self.0.y,
|
||||
color: self.1.into_storage(),
|
||||
}
|
||||
impl From<CPixel> for Pixel<Rgb565> {
|
||||
fn from(value: CPixel) -> Self {
|
||||
Pixel(
|
||||
Point::new(value.x, value.y),
|
||||
RawU16::new(value.color).into(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<Pixel<Rgb565>> for CPixel {
|
||||
fn into(self) -> Pixel<Rgb565> {
|
||||
Pixel(Point::new(self.x, self.y), RawU16::new(self.color).into())
|
||||
impl From<Pixel<Rgb565>> for CPixel {
|
||||
fn from(value: Pixel<Rgb565>) -> Self {
|
||||
CPixel {
|
||||
x: value.0.x,
|
||||
y: value.0.y,
|
||||
color: value.1.into_storage(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,12 +174,12 @@ pub mod keyboard {
|
||||
pub mods: Modifiers,
|
||||
}
|
||||
|
||||
impl Into<KeyEvent> for KeyEventC {
|
||||
fn into(self) -> KeyEvent {
|
||||
impl From<KeyEventC> for KeyEvent {
|
||||
fn from(val: KeyEventC) -> Self {
|
||||
KeyEvent {
|
||||
key: self.key.into(),
|
||||
state: self.state,
|
||||
mods: self.mods,
|
||||
key: val.key.into(),
|
||||
state: val.state,
|
||||
mods: val.mods,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -188,12 +191,12 @@ pub mod keyboard {
|
||||
pub mods: Modifiers,
|
||||
}
|
||||
|
||||
impl Into<KeyEventC> for KeyEvent {
|
||||
fn into(self) -> KeyEventC {
|
||||
impl From<KeyEvent> for KeyEventC {
|
||||
fn from(val: KeyEvent) -> Self {
|
||||
KeyEventC {
|
||||
key: self.key.into(),
|
||||
state: self.state,
|
||||
mods: self.mods,
|
||||
key: val.key.into(),
|
||||
state: val.state,
|
||||
mods: val.mods,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -267,9 +270,9 @@ pub mod keyboard {
|
||||
Unknown(u8),
|
||||
}
|
||||
|
||||
impl Into<u8> for KeyCode {
|
||||
fn into(self) -> u8 {
|
||||
match self {
|
||||
impl From<KeyCode> for u8 {
|
||||
fn from(val: KeyCode) -> Self {
|
||||
match val {
|
||||
KeyCode::JoyUp => 0x01,
|
||||
KeyCode::JoyDown => 0x02,
|
||||
KeyCode::JoyLeft => 0x03,
|
||||
|
||||
Reference in New Issue
Block a user