WIP scsi
This commit is contained in:
126
Cargo.lock
generated
126
Cargo.lock
generated
@@ -17,8 +17,7 @@ name = "abi"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"abi_sys",
|
||||
"embassy-time 0.5.0",
|
||||
"embedded-graphics 0.8.1",
|
||||
"embedded-graphics",
|
||||
"shared",
|
||||
"spin",
|
||||
"talc",
|
||||
@@ -28,7 +27,7 @@ dependencies = [
|
||||
name = "abi_sys"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"embedded-graphics 0.8.1",
|
||||
"embedded-graphics",
|
||||
"shared",
|
||||
]
|
||||
|
||||
@@ -143,6 +142,12 @@ version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7"
|
||||
|
||||
[[package]]
|
||||
name = "bit_field"
|
||||
version = "0.10.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e4b40c7323adcfc0a41c4b88143ed58346ff65a288fc144329c5c45e05d70c6"
|
||||
|
||||
[[package]]
|
||||
name = "bitfield"
|
||||
version = "0.13.2"
|
||||
@@ -226,7 +231,8 @@ name = "calculator"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"abi",
|
||||
"embedded-graphics 0.8.1",
|
||||
"embedded-graphics",
|
||||
"kolibri-embedded-gui",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -801,19 +807,6 @@ dependencies = [
|
||||
"embedded-io-async",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "embedded-graphics"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "750082c65094fbcc4baf9ba31583ce9a8bb7f52cadfb96f6164b1bc7f922f32b"
|
||||
dependencies = [
|
||||
"az",
|
||||
"byteorder",
|
||||
"embedded-graphics-core 0.3.3",
|
||||
"float-cmp 0.8.0",
|
||||
"micromath 1.1.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "embedded-graphics"
|
||||
version = "0.8.1"
|
||||
@@ -823,19 +816,9 @@ dependencies = [
|
||||
"az",
|
||||
"byteorder",
|
||||
"defmt 0.3.100",
|
||||
"embedded-graphics-core 0.4.0",
|
||||
"float-cmp 0.9.0",
|
||||
"micromath 2.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "embedded-graphics-core"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8b1239db5f3eeb7e33e35bd10bd014e7b2537b17e071f726a09351431337cfa"
|
||||
dependencies = [
|
||||
"az",
|
||||
"byteorder",
|
||||
"embedded-graphics-core",
|
||||
"float-cmp",
|
||||
"micromath",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -895,6 +878,18 @@ dependencies = [
|
||||
"nb 1.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "embedded-iconoir"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c52b9899b636b56d4e66834f7a90766d0bc6600c0f067d91ed0711b11fa3f5c8"
|
||||
dependencies = [
|
||||
"bit_field",
|
||||
"embedded-graphics",
|
||||
"paste",
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "embedded-io"
|
||||
version = "0.6.1"
|
||||
@@ -916,7 +911,7 @@ version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a90553247f2b05c59ac7894ea13d830636c2b1203fa03bff400eddbd1fa9f52"
|
||||
dependencies = [
|
||||
"embedded-graphics 0.8.1",
|
||||
"embedded-graphics",
|
||||
"embedded-layout-macros",
|
||||
]
|
||||
|
||||
@@ -944,16 +939,6 @@ dependencies = [
|
||||
"heapless",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "embedded-snake"
|
||||
version = "0.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af598ad20b839c26b95be615a94619a069303ec776a58aef6dc0e86cf7eabbb8"
|
||||
dependencies = [
|
||||
"embedded-graphics 0.7.1",
|
||||
"rand_core 0.6.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "embedded-storage"
|
||||
version = "0.3.1"
|
||||
@@ -976,7 +961,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "005680edc0d075af5e02d5788ca291737bd9aba7fc404ae031cc9dfa715e5f7d"
|
||||
dependencies = [
|
||||
"az",
|
||||
"embedded-graphics 0.8.1",
|
||||
"embedded-graphics",
|
||||
"object-chain",
|
||||
]
|
||||
|
||||
@@ -1025,15 +1010,6 @@ version = "0.5.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99"
|
||||
|
||||
[[package]]
|
||||
name = "float-cmp"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1267f4ac4f343772758f7b1bdcbe767c218bbab93bb432acbf5162bbf85a6c4"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "float-cmp"
|
||||
version = "0.9.0"
|
||||
@@ -1049,6 +1025,12 @@ version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||
|
||||
[[package]]
|
||||
name = "foldhash"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
|
||||
|
||||
[[package]]
|
||||
name = "funty"
|
||||
version = "2.0.0"
|
||||
@@ -1210,6 +1192,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad"
|
||||
dependencies = [
|
||||
"hash32",
|
||||
"serde",
|
||||
"stable_deref_trait",
|
||||
]
|
||||
|
||||
@@ -1304,7 +1287,7 @@ dependencies = [
|
||||
"embassy-sync 0.7.2",
|
||||
"embassy-time 0.5.0",
|
||||
"embassy-usb",
|
||||
"embedded-graphics 0.8.1",
|
||||
"embedded-graphics",
|
||||
"embedded-hal 0.2.7",
|
||||
"embedded-hal 1.0.0",
|
||||
"embedded-hal-async",
|
||||
@@ -1314,6 +1297,7 @@ dependencies = [
|
||||
"embedded-text",
|
||||
"goblin",
|
||||
"heapless",
|
||||
"kolibri-embedded-gui",
|
||||
"num_enum 0.7.4",
|
||||
"panic-probe",
|
||||
"portable-atomic",
|
||||
@@ -1325,6 +1309,18 @@ dependencies = [
|
||||
"trouble-host",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kolibri-embedded-gui"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "011f8f415e8c2f03e4ad752afcf1bb156a18926250401b1fe29d8feda644c140"
|
||||
dependencies = [
|
||||
"embedded-graphics",
|
||||
"embedded-iconoir",
|
||||
"foldhash",
|
||||
"heapless",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lalrpop"
|
||||
version = "0.19.12"
|
||||
@@ -1438,12 +1434,6 @@ version = "2.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
|
||||
|
||||
[[package]]
|
||||
name = "micromath"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc4010833aea396656c2f91ee704d51a6f1329ec2ab56ffd00bfd56f7481ea94"
|
||||
|
||||
[[package]]
|
||||
name = "micromath"
|
||||
version = "2.1.0"
|
||||
@@ -2018,16 +2008,6 @@ dependencies = [
|
||||
"rgb",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "snake"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"abi",
|
||||
"embedded-graphics 0.8.1",
|
||||
"embedded-snake",
|
||||
"rand_core 0.6.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.10.0"
|
||||
@@ -2050,10 +2030,10 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "st7365p-lcd"
|
||||
version = "0.11.0"
|
||||
source = "git+https://github.com/legitcamper/st7365p-lcd-rs?rev=1d15123929fa7ef73d5d6aead7faf1bba50ce915#1d15123929fa7ef73d5d6aead7faf1bba50ce915"
|
||||
source = "git+https://github.com/legitcamper/st7365p-lcd-rs?rev=a784b9e6df0769371dfc522528e770cf8fc6403a#a784b9e6df0769371dfc522528e770cf8fc6403a"
|
||||
dependencies = [
|
||||
"bitvec",
|
||||
"embedded-graphics-core 0.4.0",
|
||||
"embedded-graphics-core",
|
||||
"embedded-hal 1.0.0",
|
||||
"embedded-hal-async",
|
||||
"heapless",
|
||||
@@ -2066,6 +2046,12 @@ version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
||||
|
||||
[[package]]
|
||||
name = "static_assertions"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||
|
||||
[[package]]
|
||||
name = "static_cell"
|
||||
version = "2.1.1"
|
||||
|
||||
@@ -9,4 +9,3 @@ shared = { path = "../shared" }
|
||||
abi_sys = { path = "../abi_sys" }
|
||||
talc = "4.4.3"
|
||||
spin = "0.10.0"
|
||||
embassy-time = "0.5.0"
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
use abi_sys::draw_iter;
|
||||
pub use abi_sys::{get_key, print, sleep};
|
||||
pub use embassy_time;
|
||||
pub use shared::keyboard::{KeyCode, KeyEvent, KeyState, Modifiers};
|
||||
use talc::*;
|
||||
|
||||
|
||||
@@ -72,10 +72,11 @@ defmt = { version = "0.3", optional = true }
|
||||
defmt-rtt = "0.4.2"
|
||||
|
||||
embedded-sdmmc = { version = "0.9", default-features = false }
|
||||
st7365p-lcd = { git = "https://github.com/legitcamper/st7365p-lcd-rs", rev = "1d15123929fa7ef73d5d6aead7faf1bba50ce915" } # async branch
|
||||
st7365p-lcd = { git = "https://github.com/legitcamper/st7365p-lcd-rs", rev = "a784b9e6df0769371dfc522528e770cf8fc6403a" } # async branch
|
||||
embedded-graphics = { version = "0.8.1" }
|
||||
embedded-text = "0.7.2"
|
||||
embedded-layout = "0.4.2"
|
||||
kolibri-embedded-gui = "0.1.0"
|
||||
|
||||
static_cell = "2.1.1"
|
||||
bitflags = "2.9.1"
|
||||
|
||||
@@ -50,12 +50,12 @@ pub async fn init_display(
|
||||
}
|
||||
|
||||
pub fn clear_fb() {
|
||||
let bounds = unsafe { FRAMEBUFFER.bounding_box() };
|
||||
unsafe {
|
||||
let _ = FRAMEBUFFER.fill_solid(&bounds, Rgb565::BLACK);
|
||||
FRAMEBUFFER.clear(Rgb565::WHITE).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[embassy_executor::task]
|
||||
pub async fn display_handler(mut display: DISPLAY) {
|
||||
loop {
|
||||
unsafe {
|
||||
|
||||
@@ -26,7 +26,7 @@ const SIZE: usize = SCREEN_HEIGHT * SCREEN_WIDTH;
|
||||
|
||||
static mut BUFFER: [u16; SIZE] = [0; SIZE];
|
||||
|
||||
static mut DIRTY_TILES: LazyLock<Vec<AtomicBool, TILE_COUNT>> = LazyLock::new(|| {
|
||||
static mut DIRTY_TILES: LazyLock<heapless::Vec<AtomicBool, TILE_COUNT>> = LazyLock::new(|| {
|
||||
let mut tiles = Vec::new();
|
||||
for _ in 0..TILE_COUNT {
|
||||
tiles.push(AtomicBool::new(true)).unwrap();
|
||||
@@ -71,10 +71,10 @@ impl AtomicFrameBuffer {
|
||||
ey: u16,
|
||||
colors: P,
|
||||
) -> Result<(), ()> {
|
||||
if sx >= self.size().width as u16 - 1
|
||||
|| ex >= self.size().width as u16 - 1
|
||||
|| sy >= self.size().height as u16 - 1
|
||||
|| ey >= self.size().height as u16 - 1
|
||||
if sx >= self.size().width as u16
|
||||
|| ex >= self.size().width as u16
|
||||
|| sy >= self.size().height as u16
|
||||
|| ey >= self.size().height as u16
|
||||
{
|
||||
return Err(()); // Bounds check
|
||||
}
|
||||
@@ -101,7 +101,7 @@ impl AtomicFrameBuffer {
|
||||
|
||||
// walk the dirty tiles and mark groups of tiles(meta-tiles) for batched updates
|
||||
fn find_meta_tiles(&mut self, tiles_x: usize, tiles_y: usize) -> MetaTileVec {
|
||||
let mut meta_tiles: MetaTileVec = Vec::new();
|
||||
let mut meta_tiles: MetaTileVec = heapless::Vec::new();
|
||||
|
||||
for ty in 0..tiles_y {
|
||||
let mut tx = 0;
|
||||
@@ -415,10 +415,8 @@ impl DrawTarget for AtomicFrameBuffer {
|
||||
.take((self.size().width * self.size().height) as usize),
|
||||
)?;
|
||||
|
||||
unsafe {
|
||||
for tile in DIRTY_TILES.get_mut().iter() {
|
||||
tile.store(true, Ordering::Relaxed);
|
||||
}
|
||||
for tile in unsafe { DIRTY_TILES.get_mut() }.iter() {
|
||||
tile.store(true, Ordering::Release);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -19,12 +19,12 @@ mod usb;
|
||||
mod utils;
|
||||
|
||||
use crate::{
|
||||
display::{FRAMEBUFFER, clear_fb, display_handler, init_display},
|
||||
elf::load_binary,
|
||||
display::{clear_fb, display_handler, init_display},
|
||||
peripherals::{
|
||||
conf_peripherals,
|
||||
keyboard::{KeyCode, KeyState, read_keyboard_fifo},
|
||||
keyboard::{KeyState, read_keyboard_fifo},
|
||||
},
|
||||
scsi::MSC_SHUTDOWN,
|
||||
storage::{SDCARD, SdCard},
|
||||
ui::{SELECTIONS, ui_handler},
|
||||
usb::usb_handler,
|
||||
@@ -33,10 +33,12 @@ use abi_sys::EntryFn;
|
||||
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
use assign_resources::assign_resources;
|
||||
use defmt::unwrap;
|
||||
use embassy_executor::{Executor, Spawner};
|
||||
use embassy_futures::join::{join, join3, join4, join5};
|
||||
use embassy_futures::{
|
||||
join::{join, join3, join5},
|
||||
yield_now,
|
||||
};
|
||||
use embassy_rp::{
|
||||
Peri,
|
||||
gpio::{Input, Level, Output, Pull},
|
||||
@@ -86,7 +88,7 @@ enum TaskState {
|
||||
}
|
||||
|
||||
#[embassy_executor::main]
|
||||
async fn main(_spawner: Spawner) {
|
||||
async fn main(spawner: Spawner) {
|
||||
let p = embassy_rp::init(Default::default());
|
||||
|
||||
spawn_core1(
|
||||
@@ -123,7 +125,7 @@ async fn main(_spawner: Spawner) {
|
||||
data: p.PIN_6,
|
||||
};
|
||||
let executor0 = EXECUTOR0.init(Executor::new());
|
||||
executor0.run(|spawner| unwrap!(spawner.spawn(kernel_task(display, sd, mcu, p.USB))));
|
||||
executor0.run(|spawner| unwrap!(spawner.spawn(kernel_task(spawner, display, sd, mcu, p.USB))));
|
||||
}
|
||||
|
||||
// One-slot channel to pass EntryFn from core1
|
||||
@@ -141,10 +143,11 @@ async fn userland_task() {
|
||||
{
|
||||
let mut state = TASK_STATE.lock().await;
|
||||
*state = TaskState::Kernel;
|
||||
TASK_STATE_CHANGED.signal(());
|
||||
// clear_fb();
|
||||
MSC_SHUTDOWN.signal(());
|
||||
}
|
||||
|
||||
// clear_fb();
|
||||
|
||||
defmt::info!("Executing Binary");
|
||||
entry().await;
|
||||
|
||||
@@ -152,6 +155,8 @@ async fn userland_task() {
|
||||
{
|
||||
let mut state = TASK_STATE.lock().await;
|
||||
*state = TaskState::Ui;
|
||||
TASK_STATE_CHANGED.signal(());
|
||||
// clear_fb();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -181,16 +186,15 @@ struct Mcu {
|
||||
data: Peri<'static, PIN_6>,
|
||||
}
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn kernel_task(display: Display, sd: Sd, mcu: Mcu, usb: Peri<'static, USB>) {
|
||||
// MCU i2c bus for peripherals
|
||||
async fn setup_mcu(mcu: Mcu) {
|
||||
// MCU i2c bus for peripherals( keyboard)
|
||||
let mut config = i2c::Config::default();
|
||||
config.frequency = 400_000;
|
||||
let i2c1 = I2c::new_async(mcu.i2c, mcu.clk, mcu.data, Irqs, config);
|
||||
conf_peripherals(i2c1).await;
|
||||
}
|
||||
|
||||
Timer::after_millis(250).await;
|
||||
|
||||
async fn setup_display(display: Display, spawner: Spawner) {
|
||||
let mut config = spi::Config::default();
|
||||
config.frequency = 16_000_000;
|
||||
let spi = Spi::new(
|
||||
@@ -203,66 +207,85 @@ async fn kernel_task(display: Display, sd: Sd, mcu: Mcu, usb: Peri<'static, USB>
|
||||
config,
|
||||
);
|
||||
let display = init_display(spi, display.cs, display.data, display.reset).await;
|
||||
spawner.spawn(display_handler(display)).unwrap();
|
||||
}
|
||||
|
||||
let display_fut = display_handler(display);
|
||||
async fn setup_sd(sd: Sd) {
|
||||
let mut config = spi::Config::default();
|
||||
config.frequency = 400_000;
|
||||
let spi = Spi::new_blocking(sd.spi, sd.clk, sd.mosi, sd.miso, config.clone());
|
||||
let cs = Output::new(sd.cs, Level::High);
|
||||
let det = Input::new(sd.det, Pull::None);
|
||||
|
||||
let ui_fut = ui_handler();
|
||||
let device = ExclusiveDevice::new(spi, cs, Delay).unwrap();
|
||||
let sdcard = SdmmcSdCard::new(device, Delay);
|
||||
|
||||
let binary_search_fut = async {
|
||||
loop {
|
||||
{
|
||||
let mut guard = SDCARD.get().lock().await;
|
||||
config.frequency = 32_000_000;
|
||||
sdcard.spi(|dev| dev.bus_mut().set_config(&config));
|
||||
SDCARD.get().lock().await.replace(SdCard::new(sdcard, det));
|
||||
}
|
||||
|
||||
if let Some(sd) = guard.as_mut() {
|
||||
let files = sd.list_files_by_extension(".bin").unwrap();
|
||||
let mut select = SELECTIONS.lock().await;
|
||||
|
||||
if select.selections != files {
|
||||
select.selections = files;
|
||||
select.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
Timer::after_secs(5).await;
|
||||
}
|
||||
};
|
||||
|
||||
{
|
||||
let mut config = spi::Config::default();
|
||||
config.frequency = 400_000;
|
||||
let spi = Spi::new_blocking(sd.spi, sd.clk, sd.mosi, sd.miso, config.clone());
|
||||
let cs = Output::new(sd.cs, Level::High);
|
||||
let det = Input::new(sd.det, Pull::None);
|
||||
|
||||
let device = ExclusiveDevice::new(spi, cs, Delay).unwrap();
|
||||
let sdcard = SdmmcSdCard::new(device, Delay);
|
||||
|
||||
config.frequency = 32_000_000;
|
||||
sdcard.spi(|dev| dev.bus_mut().set_config(&config));
|
||||
SDCARD.get().lock().await.replace(SdCard::new(sdcard, det));
|
||||
};
|
||||
#[embassy_executor::task]
|
||||
async fn kernel_task(
|
||||
spawner: Spawner,
|
||||
display: Display,
|
||||
sd: Sd,
|
||||
mcu: Mcu,
|
||||
usb: Peri<'static, USB>,
|
||||
) {
|
||||
setup_mcu(mcu).await;
|
||||
Timer::after_millis(250).await;
|
||||
setup_display(display, spawner).await;
|
||||
setup_sd(sd).await;
|
||||
|
||||
let usb = embassy_rp_usb::Driver::new(usb, Irqs);
|
||||
let usb_fut = usb_handler(usb);
|
||||
spawner.spawn(usb_handler(usb)).unwrap();
|
||||
|
||||
let key_abi_fut = async {
|
||||
loop {
|
||||
Timer::after_millis(100).await;
|
||||
get_keys().await
|
||||
spawner.spawn(key_handler()).unwrap();
|
||||
|
||||
loop {
|
||||
if let TaskState::Ui = *TASK_STATE.lock().await {
|
||||
let ui_fut = ui_handler();
|
||||
let binary_search_fut = prog_search_handler();
|
||||
|
||||
join(ui_fut, binary_search_fut).await;
|
||||
}
|
||||
};
|
||||
|
||||
join5(display_fut, ui_fut, usb_fut, binary_search_fut, key_abi_fut).await;
|
||||
yield_now().await;
|
||||
}
|
||||
}
|
||||
|
||||
async fn prog_search_handler() {
|
||||
loop {
|
||||
{
|
||||
let mut guard = SDCARD.get().lock().await;
|
||||
|
||||
if let Some(sd) = guard.as_mut() {
|
||||
let files = sd.list_files_by_extension(".bin").unwrap();
|
||||
let mut select = SELECTIONS.lock().await;
|
||||
|
||||
if select.selections != files {
|
||||
select.selections = files;
|
||||
select.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
Timer::after_secs(5).await;
|
||||
}
|
||||
}
|
||||
|
||||
static mut KEY_CACHE: Queue<KeyEvent, 32> = Queue::new();
|
||||
|
||||
async fn get_keys() {
|
||||
if let Some(event) = read_keyboard_fifo().await {
|
||||
if let KeyState::Pressed = event.state {
|
||||
unsafe {
|
||||
let _ = KEY_CACHE.enqueue(event);
|
||||
#[embassy_executor::task]
|
||||
async fn key_handler() {
|
||||
loop {
|
||||
if let Some(event) = read_keyboard_fifo().await {
|
||||
if let KeyState::Pressed = event.state {
|
||||
unsafe {
|
||||
let _ = KEY_CACHE.enqueue(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
Timer::after_millis(50).await;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::format;
|
||||
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
||||
use embassy_sync::signal::Signal;
|
||||
use embassy_usb::Builder;
|
||||
use embassy_usb::driver::{Driver, EndpointIn, EndpointOut};
|
||||
use embassy_usb::types::StringIndex;
|
||||
use embassy_usb::{Builder, Config};
|
||||
use embedded_sdmmc::{Block, BlockIdx};
|
||||
use heapless::Vec;
|
||||
|
||||
@@ -12,6 +12,8 @@ use crate::storage::{SDCARD, SdCard};
|
||||
|
||||
const BULK_ENDPOINT_PACKET_SIZE: usize = 64;
|
||||
|
||||
pub static MSC_SHUTDOWN: Signal<CriticalSectionRawMutex, ()> = Signal::new();
|
||||
|
||||
pub struct MassStorageClass<'d, D: Driver<'d>> {
|
||||
bulk_out: D::EndpointOut,
|
||||
bulk_in: D::EndpointIn,
|
||||
@@ -31,16 +33,24 @@ impl<'d, 's, D: Driver<'d>> MassStorageClass<'d, D> {
|
||||
|
||||
pub async fn poll(&mut self) {
|
||||
loop {
|
||||
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]) {
|
||||
// TODO: validate cbw
|
||||
if self.handle_command(&cbw.CBWCB).await.is_ok() {
|
||||
self.send_csw_success(cbw.dCBWTag).await
|
||||
} else {
|
||||
self.send_csw_fail(cbw.dCBWTag).await
|
||||
}
|
||||
embassy_futures::select::select(self.handle_cbw(), MSC_SHUTDOWN.wait()).await;
|
||||
|
||||
if MSC_SHUTDOWN.signaled() {
|
||||
defmt::info!("MSC shutting down");
|
||||
return; // or break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 self.handle_command(&cbw.CBWCB).await.is_ok() {
|
||||
self.send_csw_success(cbw.dCBWTag).await
|
||||
} else {
|
||||
self.send_csw_fail(cbw.dCBWTag).await
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
101
kernel/src/ui.rs
101
kernel/src/ui.rs
@@ -14,7 +14,10 @@ use embassy_sync::{
|
||||
};
|
||||
use embedded_graphics::{
|
||||
Drawable,
|
||||
mono_font::{MonoTextStyle, ascii::FONT_9X15},
|
||||
mono_font::{
|
||||
MonoTextStyle,
|
||||
ascii::{self, FONT_9X15},
|
||||
},
|
||||
pixelcolor::Rgb565,
|
||||
prelude::{Dimensions, Point, RgbColor, Size},
|
||||
primitives::Rectangle,
|
||||
@@ -27,6 +30,7 @@ use embedded_layout::{
|
||||
prelude::*,
|
||||
};
|
||||
use embedded_text::TextBox;
|
||||
use kolibri_embedded_gui::{label::Label, style::medsize_rgb565_style, ui::Ui};
|
||||
use shared::keyboard::{KeyCode, KeyState};
|
||||
|
||||
pub static SELECTIONS: Mutex<CriticalSectionRawMutex, SelectionList> =
|
||||
@@ -34,89 +38,50 @@ pub static SELECTIONS: Mutex<CriticalSectionRawMutex, SelectionList> =
|
||||
|
||||
pub async fn ui_handler() {
|
||||
loop {
|
||||
if let TaskState::Ui = *TASK_STATE.lock().await {
|
||||
if let Some(event) = keyboard::read_keyboard_fifo().await {
|
||||
if let KeyState::Pressed = event.state {
|
||||
match event.key {
|
||||
KeyCode::JoyUp => {
|
||||
let mut selections = SELECTIONS.lock().await;
|
||||
selections.up();
|
||||
}
|
||||
KeyCode::JoyDown => {
|
||||
let mut selections = SELECTIONS.lock().await;
|
||||
selections.down();
|
||||
}
|
||||
KeyCode::Enter | KeyCode::JoyRight => {
|
||||
let selections = SELECTIONS.lock().await;
|
||||
let selection = selections.selections
|
||||
[selections.current_selection as usize - 1]
|
||||
.clone();
|
||||
|
||||
let entry =
|
||||
unsafe { load_binary(&selection.short_name).await.unwrap() };
|
||||
BINARY_CH.send(entry).await;
|
||||
}
|
||||
_ => (),
|
||||
if let Some(event) = keyboard::read_keyboard_fifo().await {
|
||||
if let KeyState::Pressed = event.state {
|
||||
match event.key {
|
||||
KeyCode::JoyUp => {
|
||||
let mut selections = SELECTIONS.lock().await;
|
||||
selections.up();
|
||||
}
|
||||
KeyCode::JoyDown => {
|
||||
let mut selections = SELECTIONS.lock().await;
|
||||
selections.down();
|
||||
}
|
||||
KeyCode::Enter | KeyCode::JoyRight => {
|
||||
let selections = SELECTIONS.lock().await;
|
||||
let selection = selections.selections
|
||||
[selections.current_selection as usize - 1]
|
||||
.clone();
|
||||
|
||||
let entry = unsafe { load_binary(&selection.short_name).await.unwrap() };
|
||||
BINARY_CH.send(entry).await;
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
draw_selection().await;
|
||||
} else {
|
||||
embassy_time::Timer::after_millis(50).await;
|
||||
}
|
||||
|
||||
draw_selection().await;
|
||||
}
|
||||
}
|
||||
|
||||
async fn draw_selection() {
|
||||
const NO_BINS: &str = "No Programs found on SD Card. Ensure programs end with '.bin', and are located in the root directory";
|
||||
let file_names: Vec<FileName> = {
|
||||
let guard = SELECTIONS.lock().await;
|
||||
guard.selections.clone()
|
||||
};
|
||||
|
||||
let text_style = MonoTextStyle::new(&FONT_9X15, Rgb565::WHITE);
|
||||
let display_area = unsafe { FRAMEBUFFER.bounding_box() };
|
||||
|
||||
const NO_BINS: &str = "No Programs found on SD Card. Ensure programs end with '.bin', and are located in the root directory";
|
||||
let no_bins = String::from_str(NO_BINS).unwrap();
|
||||
let mut ui = Ui::new_fullscreen(unsafe { &mut FRAMEBUFFER }, medsize_rgb565_style());
|
||||
|
||||
if file_names.is_empty() {
|
||||
TextBox::new(
|
||||
&no_bins,
|
||||
Rectangle::new(
|
||||
Point::new(25, 25),
|
||||
Size::new(display_area.size.width - 50, display_area.size.width - 50),
|
||||
),
|
||||
text_style,
|
||||
)
|
||||
.draw(unsafe { &mut FRAMEBUFFER })
|
||||
.unwrap();
|
||||
ui.add(Label::new(NO_BINS).with_font(ascii::FONT_10X20));
|
||||
} else {
|
||||
let mut file_names = file_names.iter();
|
||||
let Some(first) = file_names.next() else {
|
||||
Text::new(NO_BINS, Point::zero(), text_style)
|
||||
.draw(unsafe { &mut FRAMEBUFFER })
|
||||
.unwrap();
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
let chain = Chain::new(Text::new(&first.long_name, Point::zero(), text_style));
|
||||
|
||||
// for _ in 0..file_names.len() {
|
||||
// let chain = chain.append(Text::new(
|
||||
// file_names.next().unwrap(),
|
||||
// Point::zero(),
|
||||
// text_style,
|
||||
// ));
|
||||
// }
|
||||
|
||||
LinearLayout::vertical(chain)
|
||||
.with_alignment(horizontal::Center)
|
||||
.arrange()
|
||||
.align_to(&display_area, horizontal::Center, vertical::Center)
|
||||
.draw(unsafe { &mut FRAMEBUFFER })
|
||||
.unwrap();
|
||||
for file in file_names {
|
||||
ui.add(Label::new(&file.long_name).with_font(ascii::FONT_10X20));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
use crate::{TASK_STATE, TASK_STATE_CHANGED, TaskState, scsi::MassStorageClass};
|
||||
use embassy_futures::{
|
||||
join::join,
|
||||
select::{select, select3},
|
||||
};
|
||||
use crate::scsi::MassStorageClass;
|
||||
use embassy_futures::join::join;
|
||||
use embassy_rp::{peripherals::USB, usb::Driver};
|
||||
use embassy_usb::{Builder, Config};
|
||||
|
||||
#[embassy_executor::task]
|
||||
pub async fn usb_handler(driver: Driver<'static, USB>) {
|
||||
let mut config = Config::new(0xc0de, 0xbabe);
|
||||
config.manufacturer = Some("LegitCamper");
|
||||
@@ -30,14 +28,5 @@ pub async fn usb_handler(driver: Driver<'static, USB>) {
|
||||
let mut scsi = MassStorageClass::new(&mut builder);
|
||||
let mut usb = builder.build();
|
||||
|
||||
loop {
|
||||
defmt::info!("in: {}", *TASK_STATE.lock().await as u32);
|
||||
if *TASK_STATE.lock().await == TaskState::Ui {
|
||||
defmt::info!("running scsi and usb");
|
||||
select(join(usb.run(), scsi.poll()), TASK_STATE_CHANGED.wait()).await;
|
||||
} else {
|
||||
defmt::info!("not in ui state");
|
||||
TASK_STATE_CHANGED.wait().await;
|
||||
}
|
||||
}
|
||||
join(usb.run(), scsi.poll()).await;
|
||||
}
|
||||
|
||||
@@ -6,3 +6,4 @@ edition = "2024"
|
||||
[dependencies]
|
||||
abi = { path = "../../abi" }
|
||||
embedded-graphics = "0.8.1"
|
||||
kolibri-embedded-gui = "0.1.0"
|
||||
|
||||
@@ -2,18 +2,22 @@
|
||||
#![no_main]
|
||||
|
||||
extern crate alloc;
|
||||
use abi::{KeyCode, display::Display, embassy_time, get_key, print, sleep};
|
||||
use abi::{KeyCode, display::Display, get_key, print, sleep};
|
||||
use alloc::{boxed::Box, string::String, vec};
|
||||
use core::{panic::PanicInfo, pin::Pin};
|
||||
use embedded_graphics::{
|
||||
Drawable,
|
||||
geometry::{Dimensions, Point},
|
||||
mono_font::{MonoTextStyle, ascii::FONT_6X10},
|
||||
mono_font::{
|
||||
MonoTextStyle,
|
||||
ascii::{self, FONT_6X10},
|
||||
},
|
||||
pixelcolor::Rgb565,
|
||||
prelude::{Primitive, RgbColor, Size},
|
||||
primitives::{PrimitiveStyle, Rectangle},
|
||||
text::{Alignment, Text},
|
||||
};
|
||||
use kolibri_embedded_gui::{label::Label, style::medsize_rgb565_style, ui::Ui};
|
||||
|
||||
#[panic_handler]
|
||||
fn panic(_info: &PanicInfo) -> ! {
|
||||
@@ -24,36 +28,20 @@ pub async fn main() {
|
||||
print("Starting Async Calculator app");
|
||||
let mut display = Display;
|
||||
|
||||
let character_style = MonoTextStyle::new(&FONT_6X10, Rgb565::RED);
|
||||
|
||||
let mut text = vec!['T', 'y', 'p', 'e'];
|
||||
let mut dirty = true;
|
||||
let mut last_bounds: Option<Rectangle> = None;
|
||||
|
||||
loop {
|
||||
if dirty {
|
||||
if let Some(bounds) = last_bounds {
|
||||
Rectangle::new(bounds.top_left, bounds.size)
|
||||
.into_styled(PrimitiveStyle::with_fill(Rgb565::BLACK))
|
||||
.draw(&mut display)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
let mut ui = Ui::new_fullscreen(&mut display, medsize_rgb565_style());
|
||||
let text = text.iter().cloned().collect::<String>();
|
||||
let aligned_text = Text::with_alignment(
|
||||
&text,
|
||||
display.bounding_box().center(),
|
||||
character_style,
|
||||
Alignment::Center,
|
||||
);
|
||||
last_bounds = Some(aligned_text.bounding_box());
|
||||
|
||||
aligned_text.draw(&mut display).unwrap();
|
||||
// ui.clear_background();
|
||||
ui.add(Label::new(&text).with_font(ascii::FONT_10X20));
|
||||
dirty = false;
|
||||
}
|
||||
|
||||
if let Some(event) = get_key() {
|
||||
dirty = true;
|
||||
match event.key {
|
||||
KeyCode::Char(ch) => {
|
||||
text.push(ch);
|
||||
@@ -67,6 +55,7 @@ pub async fn main() {
|
||||
KeyCode::Esc => return,
|
||||
_ => (),
|
||||
}
|
||||
dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user