setup basic file structure

This commit is contained in:
2025-07-19 23:15:27 -06:00
parent 2d31e62d82
commit 0f4b4f8ffc
15 changed files with 362 additions and 275 deletions

25
Cargo.lock generated
View File

@@ -12,6 +12,13 @@ dependencies = [
"regex", "regex",
] ]
[[package]]
name = "abi"
version = "0.1.0"
dependencies = [
"shared",
]
[[package]] [[package]]
name = "aho-corasick" name = "aho-corasick"
version = "1.1.3" version = "1.1.3"
@@ -192,6 +199,10 @@ version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "calculator"
version = "0.1.0"
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
version = "1.0.1" version = "1.0.1"
@@ -1159,9 +1170,9 @@ checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776"
[[package]] [[package]]
name = "libredox" name = "libredox"
version = "0.1.4" version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1580801010e535496706ba011c15f8532df6b42297d2e471fec38ceadd8c0638" checksum = "4488594b9328dee448adb906d8b126d9b7deb7cf5c22161ee591610bb1be83c0"
dependencies = [ dependencies = [
"bitflags 2.9.1", "bitflags 2.9.1",
"libc", "libc",
@@ -1356,6 +1367,7 @@ checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315"
name = "picocalc-os-rs" name = "picocalc-os-rs"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"abi",
"bitflags 2.9.1", "bitflags 2.9.1",
"bt-hci", "bt-hci",
"cortex-m", "cortex-m",
@@ -1378,6 +1390,7 @@ dependencies = [
"heapless", "heapless",
"panic-probe", "panic-probe",
"portable-atomic", "portable-atomic",
"shared",
"spin", "spin",
"st7365p-lcd", "st7365p-lcd",
"static_cell", "static_cell",
@@ -1726,6 +1739,14 @@ dependencies = [
"keccak", "keccak",
] ]
[[package]]
name = "shared"
version = "0.1.0"
dependencies = [
"bitflags 2.9.1",
"defmt 1.0.1",
]
[[package]] [[package]]
name = "siphasher" name = "siphasher"
version = "1.0.1" version = "1.0.1"

View File

@@ -1,7 +1,6 @@
[package] [workspace]
name = "picocalc-os-rs" resolver = "3"
version = "0.1.0" members = ["kernel", "abi", "shared", "user-apps/calculator"]
edition = "2024"
[profile.release] [profile.release]
debug = 2 debug = 2
@@ -9,72 +8,3 @@ debug = 2
[profile.dev] [profile.dev]
lto = true lto = true
opt-level = "z" opt-level = "z"
[features]
default = ["rp235x", "defmt"]
rp2040 = ["embassy-rp/rp2040"]
rp235x = ["embassy-rp/rp235xb"]
trouble = ["dep:bt-hci", "dep:cyw43", "dep:cyw43-pio", "dep:trouble-host"]
defmt = [
"dep:defmt",
"panic-probe/print-defmt",
"embassy-executor/defmt",
"embassy-time/defmt",
"embassy-time/defmt-timestamp-uptime",
"embassy-rp/defmt",
"embassy-sync/defmt",
"embedded-graphics/defmt",
"embedded-sdmmc/defmt-log",
# "bt-hci/defmt",
# "cyw43/defmt",
# "cyw43-pio/defmt",
]
[dependencies]
embassy-executor = { version = "0.7", features = [
"arch-cortex-m",
"executor-interrupt",
"executor-thread",
"nightly",
] }
embassy-rp = { version = "0.4.0", features = [
"critical-section-impl",
"unstable-pac",
"time-driver",
"binary-info",
] }
embassy-futures = "0.1.1"
embassy-time = "0.4.0"
embassy-embedded-hal = "0.3.0"
embassy-sync = { version = "0.7" }
trouble-host = { version = "0.1", features = [
"derive",
"scan",
], optional = true }
bt-hci = { version = "0.2", default-features = false, optional = true }
cyw43 = { version = "0.3.0", features = [
"firmware-logs",
"bluetooth",
], optional = true }
cyw43-pio = { version = "0.3.0", optional = true }
embedded-hal-bus = { version = "0.3.0", features = ["async"] }
embedded-hal = "0.2.7"
embedded-hal-async = "1.0.0"
cortex-m = { version = "0.7.7" }
cortex-m-rt = "0.7.5"
panic-probe = "0.3"
portable-atomic = { version = "1.11", features = ["critical-section"] }
defmt = { version = "0.3", optional = true }
defmt-rtt = "0.4.2"
embedded-graphics = { version = "0.8.1" }
embedded-sdmmc = { git = "https://github.com/Be-ing/embedded-sdmmc-rs", branch = "bisync", default-features = false }
st7365p-lcd = { git = "https://github.com/legitcamper/st7365p-lcd-rs", branch = "async" }
static_cell = "2.1.1"
bitflags = "2.9.1"
talc = "4.4.3"
spin = "0.10.0"
heapless = "0.8.0"

7
abi/Cargo.toml Normal file
View File

@@ -0,0 +1,7 @@
[package]
name = "abi"
version = "0.1.0"
edition = "2024"
[dependencies]
shared = { path = "../shared" }

9
abi/src/lib.rs Normal file
View File

@@ -0,0 +1,9 @@
#![no_std]
use core::ffi::c_void;
use shared::keyboard::{KeyCode, KeyEvent, KeyState, Modifiers};
#[repr(C)]
pub enum Syscall {
DrawPixels { x: u32, y: u32, color: u32 },
}

83
kernel/Cargo.toml Normal file
View File

@@ -0,0 +1,83 @@
[package]
name = "picocalc-os-rs"
version = "0.1.0"
edition = "2024"
[[bin]]
name = "picocalc-os-rs"
path = "src/main.rs"
test = false
doctest = false
bench = false
[features]
default = ["rp235x", "defmt"]
rp2040 = ["embassy-rp/rp2040"]
rp235x = ["embassy-rp/rp235xb"]
trouble = ["dep:bt-hci", "dep:cyw43", "dep:cyw43-pio", "dep:trouble-host"]
defmt = [
"dep:defmt",
"panic-probe/print-defmt",
"embassy-executor/defmt",
"embassy-time/defmt",
"embassy-time/defmt-timestamp-uptime",
"embassy-rp/defmt",
"embassy-sync/defmt",
"embedded-graphics/defmt",
"embedded-sdmmc/defmt-log",
# "bt-hci/defmt",
# "cyw43/defmt",
# "cyw43-pio/defmt",
]
[dependencies]
embassy-executor = { version = "0.7", features = [
"arch-cortex-m",
"executor-interrupt",
"executor-thread",
"nightly",
] }
embassy-rp = { version = "0.4.0", features = [
"critical-section-impl",
"unstable-pac",
"time-driver",
"binary-info",
] }
embassy-futures = "0.1.1"
embassy-time = "0.4.0"
embassy-embedded-hal = "0.3.0"
embassy-sync = { version = "0.7" }
trouble-host = { version = "0.1", features = [
"derive",
"scan",
], optional = true }
bt-hci = { version = "0.2", default-features = false, optional = true }
cyw43 = { version = "0.3.0", features = [
"firmware-logs",
"bluetooth",
], optional = true }
cyw43-pio = { version = "0.3.0", optional = true }
embedded-hal-bus = { version = "0.3.0", features = ["async"] }
embedded-hal = "0.2.7"
embedded-hal-async = "1.0.0"
cortex-m = { version = "0.7.7" }
cortex-m-rt = "0.7.5"
panic-probe = "0.3"
portable-atomic = { version = "1.11", features = ["critical-section"] }
defmt = { version = "0.3", optional = true }
defmt-rtt = "0.4.2"
embedded-graphics = { version = "0.8.1" }
embedded-sdmmc = { git = "https://github.com/Be-ing/embedded-sdmmc-rs", branch = "bisync", default-features = false }
st7365p-lcd = { git = "https://github.com/legitcamper/st7365p-lcd-rs", branch = "async" }
shared = { path = "../shared" }
abi = { path = "../abi" }
static_cell = "2.1.1"
bitflags = "2.9.1"
talc = "4.4.3"
spin = "0.10.0"
heapless = "0.8.0"

View File

@@ -19,7 +19,7 @@ fn main() {
let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
File::create(out.join("memory.x")) File::create(out.join("memory.x"))
.unwrap() .unwrap()
.write_all(include_bytes!("memory.x")) .write_all(include_bytes!("../memory.x"))
.unwrap(); .unwrap();
println!("cargo:rustc-link-search={}", out.display()); println!("cargo:rustc-link-search={}", out.display());

View File

@@ -1,7 +1,7 @@
#![feature(impl_trait_in_assoc_type)] #![feature(impl_trait_in_assoc_type)]
#![feature(ascii_char)] #![feature(ascii_char)]
#![no_std] #![cfg_attr(not(test), no_std)]
#![no_main] #![cfg_attr(not(test), no_main)]
use crate::{ use crate::{
display::DISPLAY_SIGNAL, display::DISPLAY_SIGNAL,
@@ -80,3 +80,16 @@ async fn main(_spawner: Spawner) {
) )
.await; .await;
} }
use abi::Syscall;
#[no_mangle]
pub extern "C" fn syscall_dispatch(call: *const Syscall) -> usize {
let call = unsafe { &*call };
match call {
Syscall::DrawPixel { x, y, color } => {
draw_pixel(*x, *y, *color);
0
}
}
}

View File

@@ -0,0 +1,59 @@
use crate::peripherals::PERIPHERAL_BUS;
pub use shared::keyboard::{KeyCode, KeyEvent, KeyState, Modifiers};
const REG_ID_KEY: u8 = 0x04;
const REG_ID_FIF: u8 = 0x09;
const KEY_CAPSLOCK: u8 = 1 << 5;
const KEY_NUMLOCK: u8 = 1 << 6;
const KEY_COUNT_MASK: u8 = 0x1F; // 0x1F == 31
pub async fn read_keyboard_fifo() -> Option<KeyEvent> {
let mut i2c = PERIPHERAL_BUS.get().lock().await;
let i2c = i2c.as_mut().unwrap();
let mut key_status = [0_u8; 1];
if i2c
.write_read_async(super::MCU_ADDR, [REG_ID_KEY], &mut key_status)
.await
.is_ok()
{
let _caps = key_status[0] & KEY_CAPSLOCK == KEY_CAPSLOCK;
let _num = key_status[0] & KEY_NUMLOCK == KEY_NUMLOCK;
let fifo_count = key_status[0] & KEY_COUNT_MASK;
if fifo_count >= 1 {
let mut event = [0_u8; 2];
if i2c
.write_read_async(super::MCU_ADDR, [REG_ID_FIF], &mut event)
.await
.is_ok()
{
return Some(KeyEvent {
state: KeyState::from(event[0]),
key: KeyCode::from(event[1]),
mods: Modifiers::NONE,
});
}
}
}
None
}
const REG_ID_DEB: u8 = 0x06;
const REG_ID_FRQ: u8 = 0x07;
pub async fn configure_keyboard(debounce: u8, poll_freq: u8) {
let mut i2c = PERIPHERAL_BUS.get().lock().await;
let i2c = i2c.as_mut().unwrap();
let _ = i2c
.write_read_async(super::MCU_ADDR, [REG_ID_DEB], &mut [debounce])
.await;
let _ = i2c
.write_read_async(super::MCU_ADDR, [REG_ID_FRQ], &mut [poll_freq])
.await;
}

11
shared/Cargo.toml Normal file
View File

@@ -0,0 +1,11 @@
[package]
name = "shared"
version = "0.1.0"
edition = "2024"
[features]
defmt = ["dep:defmt"]
[dependencies]
bitflags = "2.9.1"
defmt = { version = "1.0.1", optional = true }

142
shared/src/lib.rs Normal file
View File

@@ -0,0 +1,142 @@
#![no_std]
pub mod keyboard {
bitflags::bitflags! {
#[derive(Default, Debug, PartialEq, Eq, Clone, Copy)]
pub struct Modifiers: u8 {
const NONE = 0;
const CTRL = 1;
const ALT = 2;
const LSHIFT = 4;
const RSHIFT = 8;
const SYM = 16;
}
}
#[derive(Debug)]
pub struct KeyEvent {
pub key: KeyCode,
pub state: KeyState,
pub mods: Modifiers,
}
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum KeyState {
Idle = 0,
Pressed = 1,
Hold = 2,
Released = 3,
}
impl From<u8> for KeyState {
fn from(value: u8) -> Self {
match value {
1 => KeyState::Pressed,
2 => KeyState::Hold,
3 => KeyState::Released,
0 | _ => KeyState::Idle,
}
}
}
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(C)]
#[repr(u8)]
pub enum KeyCode {
JoyUp = 0x01,
JoyDown = 0x02,
JoyLeft = 0x03,
JoyRight = 0x04,
JoyCenter = 0x05,
BtnLeft1 = 0x06,
BtnRight1 = 0x07,
BtnLeft2 = 0x11,
BtnRight2 = 0x12,
Backspace = 0x08,
Tab = 0x09,
Enter = 0x0A,
ModAlt = 0xA1,
ModShiftLeft = 0xA2,
ModShiftRight = 0xA3,
ModSym = 0xA4,
ModCtrl = 0xA5,
Esc = 0xB1,
Left = 0xB4,
Up = 0xB5,
Down = 0xB6,
Right = 0xB7,
Break = 0xD0,
Insert = 0xD1,
Home = 0xD2,
Del = 0xD4,
End = 0xD5,
PageUp = 0xD6,
PageDown = 0xD7,
CapsLock = 0xC1,
F1 = 0x81,
F2 = 0x82,
F3 = 0x83,
F4 = 0x84,
F5 = 0x85,
F6 = 0x86,
F7 = 0x87,
F8 = 0x88,
F9 = 0x89,
F10 = 0x90,
Char(char),
Unknown(u8),
}
impl From<u8> for KeyCode {
fn from(value: u8) -> Self {
match value {
0x01 => Self::JoyUp,
0x02 => Self::JoyDown,
0x03 => Self::JoyLeft,
0x04 => Self::JoyRight,
0x05 => Self::JoyCenter,
0x06 => Self::BtnLeft1,
0x07 => Self::BtnRight1,
0x08 => Self::Backspace,
0x09 => Self::Tab,
0x0A => Self::Enter,
0x11 => Self::BtnLeft2,
0x12 => Self::BtnRight2,
0xA1 => Self::ModAlt,
0xA2 => Self::ModShiftLeft,
0xA3 => Self::ModShiftRight,
0xA4 => Self::ModSym,
0xA5 => Self::ModCtrl,
0xB1 => Self::Esc,
0xB4 => Self::Left,
0xB5 => Self::Up,
0xB6 => Self::Down,
0xB7 => Self::Right,
0xC1 => Self::CapsLock,
0xD0 => Self::Break,
0xD1 => Self::Insert,
0xD2 => Self::Home,
0xD4 => Self::Del,
0xD5 => Self::End,
0xD6 => Self::PageUp,
0xD7 => Self::PageDown,
0x81 => Self::F1,
0x82 => Self::F2,
0x83 => Self::F3,
0x84 => Self::F4,
0x85 => Self::F5,
0x86 => Self::F6,
0x87 => Self::F7,
0x88 => Self::F8,
0x89 => Self::F9,
0x90 => Self::F10,
_ => match char::from_u32(value as u32) {
Some(c) => Self::Char(c),
None => Self::Unknown(value),
},
}
}
}
}

View File

@@ -1,197 +0,0 @@
use crate::peripherals::PERIPHERAL_BUS;
const REG_ID_KEY: u8 = 0x04;
const REG_ID_FIF: u8 = 0x09;
const KEY_CAPSLOCK: u8 = 1 << 5;
const KEY_NUMLOCK: u8 = 1 << 6;
const KEY_COUNT_MASK: u8 = 0x1F; // 0x1F == 31
pub async fn read_keyboard_fifo() -> Option<KeyEvent> {
let mut i2c = PERIPHERAL_BUS.get().lock().await;
let i2c = i2c.as_mut().unwrap();
let mut key_status = [0_u8; 1];
if i2c
.write_read_async(super::MCU_ADDR, [REG_ID_KEY], &mut key_status)
.await
.is_ok()
{
let _caps = key_status[0] & KEY_CAPSLOCK == KEY_CAPSLOCK;
let _num = key_status[0] & KEY_NUMLOCK == KEY_NUMLOCK;
let fifo_count = key_status[0] & KEY_COUNT_MASK;
if fifo_count >= 1 {
let mut event = [0_u8; 2];
if i2c
.write_read_async(super::MCU_ADDR, [REG_ID_FIF], &mut event)
.await
.is_ok()
{
return Some(KeyEvent {
state: KeyState::from(event[0]),
key: KeyCode::from(event[1]),
mods: Modifiers::NONE,
});
}
}
}
None
}
const REG_ID_DEB: u8 = 0x06;
const REG_ID_FRQ: u8 = 0x07;
pub async fn configure_keyboard(debounce: u8, poll_freq: u8) {
let mut i2c = PERIPHERAL_BUS.get().lock().await;
let i2c = i2c.as_mut().unwrap();
let _ = i2c
.write_read_async(super::MCU_ADDR, [REG_ID_DEB], &mut [debounce])
.await;
let _ = i2c
.write_read_async(super::MCU_ADDR, [REG_ID_FRQ], &mut [poll_freq])
.await;
}
bitflags::bitflags! {
#[derive(Default, Debug, PartialEq, Eq, Clone, Copy)]
pub struct Modifiers: u8 {
const NONE = 0;
const CTRL = 1;
const ALT = 2;
const LSHIFT = 4;
const RSHIFT = 8;
const SYM = 16;
}
}
#[derive(Debug)]
pub struct KeyEvent {
pub key: KeyCode,
pub state: KeyState,
pub mods: Modifiers,
}
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum KeyState {
Idle = 0,
Pressed = 1,
Hold = 2,
Released = 3,
}
impl From<u8> for KeyState {
fn from(value: u8) -> Self {
match value {
1 => KeyState::Pressed,
2 => KeyState::Hold,
3 => KeyState::Released,
0 | _ => KeyState::Idle,
}
}
}
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum KeyCode {
JoyUp = 0x01,
JoyDown = 0x02,
JoyLeft = 0x03,
JoyRight = 0x04,
JoyCenter = 0x05,
BtnLeft1 = 0x06,
BtnRight1 = 0x07,
BtnLeft2 = 0x11,
BtnRight2 = 0x12,
Backspace = 0x08,
Tab = 0x09,
Enter = 0x0A,
ModAlt = 0xA1,
ModShiftLeft = 0xA2,
ModShiftRight = 0xA3,
ModSym = 0xA4,
ModCtrl = 0xA5,
Esc = 0xB1,
Left = 0xB4,
Up = 0xB5,
Down = 0xB6,
Right = 0xB7,
Break = 0xD0,
Insert = 0xD1,
Home = 0xD2,
Del = 0xD4,
End = 0xD5,
PageUp = 0xD6,
PageDown = 0xD7,
CapsLock = 0xC1,
F1 = 0x81,
F2 = 0x82,
F3 = 0x83,
F4 = 0x84,
F5 = 0x85,
F6 = 0x86,
F7 = 0x87,
F8 = 0x88,
F9 = 0x89,
F10 = 0x90,
Char(char),
Unknown(u8),
}
impl From<u8> for KeyCode {
fn from(value: u8) -> Self {
match value {
0x01 => Self::JoyUp,
0x02 => Self::JoyDown,
0x03 => Self::JoyLeft,
0x04 => Self::JoyRight,
0x05 => Self::JoyCenter,
0x06 => Self::BtnLeft1,
0x07 => Self::BtnRight1,
0x08 => Self::Backspace,
0x09 => Self::Tab,
0x0A => Self::Enter,
0x11 => Self::BtnLeft2,
0x12 => Self::BtnRight2,
0xA1 => Self::ModAlt,
0xA2 => Self::ModShiftLeft,
0xA3 => Self::ModShiftRight,
0xA4 => Self::ModSym,
0xA5 => Self::ModCtrl,
0xB1 => Self::Esc,
0xB4 => Self::Left,
0xB5 => Self::Up,
0xB6 => Self::Down,
0xB7 => Self::Right,
0xC1 => Self::CapsLock,
0xD0 => Self::Break,
0xD1 => Self::Insert,
0xD2 => Self::Home,
0xD4 => Self::Del,
0xD5 => Self::End,
0xD6 => Self::PageUp,
0xD7 => Self::PageDown,
0x81 => Self::F1,
0x82 => Self::F2,
0x83 => Self::F3,
0x84 => Self::F4,
0x85 => Self::F5,
0x86 => Self::F6,
0x87 => Self::F7,
0x88 => Self::F8,
0x89 => Self::F9,
0x90 => Self::F10,
_ => match char::from_u32(value as u32) {
Some(c) => Self::Char(c),
None => Self::Unknown(value),
},
}
}
}

View File

@@ -0,0 +1,6 @@
[package]
name = "calculator"
version = "0.1.0"
edition = "2024"
[dependencies]

View File

@@ -0,0 +1,3 @@
fn main() {
println!("Hello, world!");
}