mirror of
https://github.com/LegitCamper/picocalc-os-rs.git
synced 2025-12-28 16:25:33 +00:00
Compare commits
2 Commits
fix-fb
...
userland-a
| Author | SHA1 | Date | |
|---|---|---|---|
| 49b6a99ea8 | |||
| 718bcd6b5b |
212
Cargo.lock
generated
212
Cargo.lock
generated
@@ -18,7 +18,7 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"abi_sys",
|
"abi_sys",
|
||||||
"embassy-time 0.5.0",
|
"embassy-time 0.5.0",
|
||||||
"embedded-graphics 0.8.1",
|
"embedded-graphics",
|
||||||
"shared",
|
"shared",
|
||||||
"spin",
|
"spin",
|
||||||
"talc",
|
"talc",
|
||||||
@@ -28,7 +28,7 @@ dependencies = [
|
|||||||
name = "abi_sys"
|
name = "abi_sys"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"embedded-graphics 0.8.1",
|
"embedded-graphics",
|
||||||
"shared",
|
"shared",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -77,12 +77,6 @@ dependencies = [
|
|||||||
"term 1.1.0",
|
"term 1.1.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "assign-resources"
|
|
||||||
version = "0.5.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "840ad5d907de7448d88a3f22b4a7b5d326c6eb3deeb9f94cfaaec7354a80b305"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "atomic-polyfill"
|
name = "atomic-polyfill"
|
||||||
version = "1.0.3"
|
version = "1.0.3"
|
||||||
@@ -226,7 +220,7 @@ name = "calculator"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"abi",
|
"abi",
|
||||||
"embedded-graphics 0.8.1",
|
"embedded-graphics",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -502,7 +496,7 @@ checksum = "8578db196d74db92efdd5ebc546736dac1685499ee245b22eff92fa5e4b57945"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"embassy-futures",
|
"embassy-futures",
|
||||||
"embassy-hal-internal 0.3.0",
|
"embassy-hal-internal 0.3.0",
|
||||||
"embassy-sync 0.7.2",
|
"embassy-sync 0.7.0",
|
||||||
"embassy-time 0.4.0",
|
"embassy-time 0.4.0",
|
||||||
"embedded-hal 0.2.7",
|
"embedded-hal 0.2.7",
|
||||||
"embedded-hal 1.0.0",
|
"embedded-hal 1.0.0",
|
||||||
@@ -512,42 +506,24 @@ dependencies = [
|
|||||||
"nb 1.1.0",
|
"nb 1.1.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "embassy-embedded-hal"
|
|
||||||
version = "0.5.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "554e3e840696f54b4c9afcf28a0f24da431c927f4151040020416e7393d6d0d8"
|
|
||||||
dependencies = [
|
|
||||||
"embassy-futures",
|
|
||||||
"embassy-hal-internal 0.3.0",
|
|
||||||
"embassy-sync 0.7.2",
|
|
||||||
"embedded-hal 0.2.7",
|
|
||||||
"embedded-hal 1.0.0",
|
|
||||||
"embedded-hal-async",
|
|
||||||
"embedded-storage",
|
|
||||||
"embedded-storage-async",
|
|
||||||
"nb 1.1.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "embassy-executor"
|
name = "embassy-executor"
|
||||||
version = "0.9.1"
|
version = "0.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "06070468370195e0e86f241c8e5004356d696590a678d47d6676795b2e439c6b"
|
checksum = "90327bcc66333a507f89ecc4e2d911b265c45f5c9bc241f98eee076752d35ac6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cortex-m",
|
"cortex-m",
|
||||||
"critical-section",
|
"critical-section",
|
||||||
"defmt 1.0.1",
|
"defmt 0.3.100",
|
||||||
"document-features",
|
"document-features",
|
||||||
"embassy-executor-macros",
|
"embassy-executor-macros",
|
||||||
"embassy-executor-timer-queue",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "embassy-executor-macros"
|
name = "embassy-executor-macros"
|
||||||
version = "0.7.0"
|
version = "0.6.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dfdddc3a04226828316bf31393b6903ee162238576b1584ee2669af215d55472"
|
checksum = "3577b1e9446f61381179a330fc5324b01d511624c55f25e3c66c9e3c626dbecf"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"darling",
|
"darling",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
@@ -555,17 +531,11 @@ dependencies = [
|
|||||||
"syn 2.0.104",
|
"syn 2.0.104",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "embassy-executor-timer-queue"
|
|
||||||
version = "0.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2fc328bf943af66b80b98755db9106bf7e7471b0cf47dc8559cd9a6be504cc9c"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "embassy-futures"
|
name = "embassy-futures"
|
||||||
version = "0.1.2"
|
version = "0.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dc2d050bdc5c21e0862a89256ed8029ae6c290a93aecefc73084b3002cdebb01"
|
checksum = "1f878075b9794c1e4ac788c95b728f26aa6366d32eeb10c7051389f898f7d067"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "embassy-hal-internal"
|
name = "embassy-hal-internal"
|
||||||
@@ -575,6 +545,7 @@ checksum = "0ef3bac31ec146321248a169e9c7b5799f1e0b3829c7a9b324cb4600a7438f59"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"cortex-m",
|
"cortex-m",
|
||||||
"critical-section",
|
"critical-section",
|
||||||
|
"defmt 0.3.100",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -584,9 +555,6 @@ version = "0.3.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "95285007a91b619dc9f26ea8f55452aa6c60f7115a4edc05085cd2bd3127cd7a"
|
checksum = "95285007a91b619dc9f26ea8f55452aa6c60f7115a4edc05085cd2bd3127cd7a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cortex-m",
|
|
||||||
"critical-section",
|
|
||||||
"defmt 1.0.1",
|
|
||||||
"num-traits",
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -598,13 +566,13 @@ checksum = "524eb3c489760508f71360112bca70f6e53173e6fe48fc5f0efd0f5ab217751d"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "embassy-net-driver-channel"
|
name = "embassy-net-driver-channel"
|
||||||
version = "0.3.2"
|
version = "0.3.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b7b2739fbcf6cd206ae08779c7d709087b16577d255f2ea4a45bc4bbbf305b3f"
|
checksum = "25a567ab50319d866ad5e6c583ed665ba9b07865389644d3d82e45bf1497c934"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"embassy-futures",
|
"embassy-futures",
|
||||||
"embassy-net-driver",
|
"embassy-net-driver",
|
||||||
"embassy-sync 0.7.2",
|
"embassy-sync 0.7.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -619,12 +587,12 @@ dependencies = [
|
|||||||
"cortex-m-rt",
|
"cortex-m-rt",
|
||||||
"critical-section",
|
"critical-section",
|
||||||
"document-features",
|
"document-features",
|
||||||
"embassy-embedded-hal 0.3.1",
|
"embassy-embedded-hal",
|
||||||
"embassy-futures",
|
"embassy-futures",
|
||||||
"embassy-hal-internal 0.2.0",
|
"embassy-hal-internal 0.2.0",
|
||||||
"embassy-sync 0.6.2",
|
"embassy-sync 0.6.2",
|
||||||
"embassy-time 0.4.0",
|
"embassy-time 0.4.0",
|
||||||
"embassy-usb-driver 0.1.1",
|
"embassy-usb-driver",
|
||||||
"embedded-hal 0.2.7",
|
"embedded-hal 0.2.7",
|
||||||
"embedded-hal 1.0.0",
|
"embedded-hal 1.0.0",
|
||||||
"embedded-hal-async",
|
"embedded-hal-async",
|
||||||
@@ -637,7 +605,7 @@ dependencies = [
|
|||||||
"nb 1.1.0",
|
"nb 1.1.0",
|
||||||
"pio 0.2.1",
|
"pio 0.2.1",
|
||||||
"pio-proc 0.2.2",
|
"pio-proc 0.2.2",
|
||||||
"rand_core 0.6.4",
|
"rand_core",
|
||||||
"rp-pac",
|
"rp-pac",
|
||||||
"rp2040-boot2",
|
"rp2040-boot2",
|
||||||
"sha2-const-stable",
|
"sha2-const-stable",
|
||||||
@@ -646,25 +614,25 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "embassy-rp"
|
name = "embassy-rp"
|
||||||
version = "0.8.0"
|
version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1a284935af0a869de3fa14af74b5f932389dd66d7048012f1083b06f38d05399"
|
checksum = "d1a063d8baccdc5c7752840f4c7931f17bcd7de1ffe1efa2109e68113fe42612"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atomic-polyfill",
|
"atomic-polyfill",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"cortex-m",
|
"cortex-m",
|
||||||
"cortex-m-rt",
|
"cortex-m-rt",
|
||||||
"critical-section",
|
"critical-section",
|
||||||
"defmt 1.0.1",
|
"defmt 0.3.100",
|
||||||
"document-features",
|
"document-features",
|
||||||
"embassy-embedded-hal 0.5.0",
|
"embassy-embedded-hal",
|
||||||
"embassy-futures",
|
"embassy-futures",
|
||||||
"embassy-hal-internal 0.3.0",
|
"embassy-hal-internal 0.2.0",
|
||||||
"embassy-sync 0.7.2",
|
"embassy-sync 0.6.2",
|
||||||
"embassy-time 0.5.0",
|
"embassy-time 0.4.0",
|
||||||
"embassy-time-driver",
|
"embassy-time-driver",
|
||||||
"embassy-time-queue-utils",
|
"embassy-time-queue-utils",
|
||||||
"embassy-usb-driver 0.2.0",
|
"embassy-usb-driver",
|
||||||
"embedded-hal 0.2.7",
|
"embedded-hal 0.2.7",
|
||||||
"embedded-hal 1.0.0",
|
"embedded-hal 1.0.0",
|
||||||
"embedded-hal-async",
|
"embedded-hal-async",
|
||||||
@@ -676,8 +644,7 @@ dependencies = [
|
|||||||
"fixed",
|
"fixed",
|
||||||
"nb 1.1.0",
|
"nb 1.1.0",
|
||||||
"pio 0.3.0",
|
"pio 0.3.0",
|
||||||
"rand_core 0.6.4",
|
"rand_core",
|
||||||
"rand_core 0.9.3",
|
|
||||||
"rp-pac",
|
"rp-pac",
|
||||||
"rp2040-boot2",
|
"rp2040-boot2",
|
||||||
"sha2-const-stable",
|
"sha2-const-stable",
|
||||||
@@ -700,16 +667,16 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "embassy-sync"
|
name = "embassy-sync"
|
||||||
version = "0.7.2"
|
version = "0.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "73974a3edbd0bd286759b3d483540f0ebef705919a5f56f4fc7709066f71689b"
|
checksum = "cef1a8a1ea892f9b656de0295532ac5d8067e9830d49ec75076291fd6066b136"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"critical-section",
|
"critical-section",
|
||||||
"defmt 1.0.1",
|
"defmt 1.0.1",
|
||||||
"embedded-io-async",
|
"embedded-io-async",
|
||||||
"futures-core",
|
|
||||||
"futures-sink",
|
"futures-sink",
|
||||||
|
"futures-util",
|
||||||
"heapless",
|
"heapless",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -721,8 +688,10 @@ checksum = "f820157f198ada183ad62e0a66f554c610cdcd1a9f27d4b316358103ced7a1f8"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"critical-section",
|
"critical-section",
|
||||||
|
"defmt 0.3.100",
|
||||||
"document-features",
|
"document-features",
|
||||||
"embassy-time-driver",
|
"embassy-time-driver",
|
||||||
|
"embassy-time-queue-utils",
|
||||||
"embedded-hal 0.2.7",
|
"embedded-hal 0.2.7",
|
||||||
"embedded-hal 1.0.0",
|
"embedded-hal 1.0.0",
|
||||||
"embedded-hal-async",
|
"embedded-hal-async",
|
||||||
@@ -737,10 +706,8 @@ checksum = "f4fa65b9284d974dad7a23bb72835c4ec85c0b540d86af7fc4098c88cff51d65"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"critical-section",
|
"critical-section",
|
||||||
"defmt 1.0.1",
|
|
||||||
"document-features",
|
"document-features",
|
||||||
"embassy-time-driver",
|
"embassy-time-driver",
|
||||||
"embassy-time-queue-utils",
|
|
||||||
"embedded-hal 0.2.7",
|
"embedded-hal 0.2.7",
|
||||||
"embedded-hal 1.0.0",
|
"embedded-hal 1.0.0",
|
||||||
"embedded-hal-async",
|
"embedded-hal-async",
|
||||||
@@ -758,25 +725,24 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "embassy-time-queue-utils"
|
name = "embassy-time-queue-utils"
|
||||||
version = "0.3.0"
|
version = "0.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "80e2ee86063bd028a420a5fb5898c18c87a8898026da1d4c852af2c443d0a454"
|
checksum = "dc55c748d16908a65b166d09ce976575fb8852cf60ccd06174092b41064d8f83"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"embassy-executor-timer-queue",
|
"embassy-executor",
|
||||||
"heapless",
|
"heapless",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "embassy-usb"
|
name = "embassy-usb"
|
||||||
version = "0.5.1"
|
version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dc4462e48b19a4f401a11901bdd981aab80c6a826608016a0bdc73cbbab31954"
|
checksum = "6e651b9b7b47b514e6e6d1940a6e2e300891a2c33641917130643602a0cb6386"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"embassy-futures",
|
"embassy-futures",
|
||||||
"embassy-net-driver-channel",
|
"embassy-net-driver-channel",
|
||||||
"embassy-sync 0.7.2",
|
"embassy-sync 0.6.2",
|
||||||
"embassy-usb-driver 0.2.0",
|
"embassy-usb-driver",
|
||||||
"embedded-io-async",
|
|
||||||
"heapless",
|
"heapless",
|
||||||
"ssmarshal",
|
"ssmarshal",
|
||||||
"usbd-hid",
|
"usbd-hid",
|
||||||
@@ -787,33 +753,11 @@ name = "embassy-usb-driver"
|
|||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "340c5ce591ef58c6449e43f51d2c53efe1bf0bb6a40cbf80afa0d259c7d52c76"
|
checksum = "340c5ce591ef58c6449e43f51d2c53efe1bf0bb6a40cbf80afa0d259c7d52c76"
|
||||||
dependencies = [
|
|
||||||
"embedded-io-async",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "embassy-usb-driver"
|
|
||||||
version = "0.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "17119855ccc2d1f7470a39756b12068454ae27a3eabb037d940b5c03d9c77b7a"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"defmt 1.0.1",
|
"defmt 1.0.1",
|
||||||
"embedded-io-async",
|
"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]]
|
[[package]]
|
||||||
name = "embedded-graphics"
|
name = "embedded-graphics"
|
||||||
version = "0.8.1"
|
version = "0.8.1"
|
||||||
@@ -823,19 +767,9 @@ dependencies = [
|
|||||||
"az",
|
"az",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"defmt 0.3.100",
|
"defmt 0.3.100",
|
||||||
"embedded-graphics-core 0.4.0",
|
"embedded-graphics-core",
|
||||||
"float-cmp 0.9.0",
|
"float-cmp",
|
||||||
"micromath 2.1.0",
|
"micromath",
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "embedded-graphics-core"
|
|
||||||
version = "0.3.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b8b1239db5f3eeb7e33e35bd10bd014e7b2537b17e071f726a09351431337cfa"
|
|
||||||
dependencies = [
|
|
||||||
"az",
|
|
||||||
"byteorder",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -916,7 +850,7 @@ version = "0.4.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9a90553247f2b05c59ac7894ea13d830636c2b1203fa03bff400eddbd1fa9f52"
|
checksum = "9a90553247f2b05c59ac7894ea13d830636c2b1203fa03bff400eddbd1fa9f52"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"embedded-graphics 0.8.1",
|
"embedded-graphics",
|
||||||
"embedded-layout-macros",
|
"embedded-layout-macros",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -944,16 +878,6 @@ dependencies = [
|
|||||||
"heapless",
|
"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]]
|
[[package]]
|
||||||
name = "embedded-storage"
|
name = "embedded-storage"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
@@ -976,7 +900,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "005680edc0d075af5e02d5788ca291737bd9aba7fc404ae031cc9dfa715e5f7d"
|
checksum = "005680edc0d075af5e02d5788ca291737bd9aba7fc404ae031cc9dfa715e5f7d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"az",
|
"az",
|
||||||
"embedded-graphics 0.8.1",
|
"embedded-graphics",
|
||||||
"object-chain",
|
"object-chain",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1025,15 +949,6 @@ version = "0.5.7"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99"
|
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]]
|
[[package]]
|
||||||
name = "float-cmp"
|
name = "float-cmp"
|
||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
@@ -1288,7 +1203,6 @@ name = "kernel"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"abi_sys",
|
"abi_sys",
|
||||||
"assign-resources",
|
|
||||||
"bitflags 2.9.1",
|
"bitflags 2.9.1",
|
||||||
"bt-hci",
|
"bt-hci",
|
||||||
"cortex-m",
|
"cortex-m",
|
||||||
@@ -1297,16 +1211,15 @@ dependencies = [
|
|||||||
"cyw43-pio",
|
"cyw43-pio",
|
||||||
"defmt 0.3.100",
|
"defmt 0.3.100",
|
||||||
"defmt-rtt",
|
"defmt-rtt",
|
||||||
"embassy-embedded-hal 0.3.1",
|
"embassy-embedded-hal",
|
||||||
"embassy-executor",
|
"embassy-executor",
|
||||||
"embassy-futures",
|
"embassy-futures",
|
||||||
"embassy-rp 0.8.0",
|
"embassy-rp 0.4.0",
|
||||||
"embassy-sync 0.7.2",
|
"embassy-sync 0.7.0",
|
||||||
"embassy-time 0.5.0",
|
"embassy-time 0.4.0",
|
||||||
"embassy-usb",
|
"embassy-usb",
|
||||||
"embedded-graphics 0.8.1",
|
"embedded-graphics",
|
||||||
"embedded-hal 0.2.7",
|
"embedded-hal 0.2.7",
|
||||||
"embedded-hal 1.0.0",
|
|
||||||
"embedded-hal-async",
|
"embedded-hal-async",
|
||||||
"embedded-hal-bus",
|
"embedded-hal-bus",
|
||||||
"embedded-layout",
|
"embedded-layout",
|
||||||
@@ -1438,12 +1351,6 @@ version = "2.7.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
|
checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "micromath"
|
|
||||||
version = "1.1.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "bc4010833aea396656c2f91ee704d51a6f1329ec2ab56ffd00bfd56f7481ea94"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "micromath"
|
name = "micromath"
|
||||||
version = "2.1.0"
|
version = "2.1.0"
|
||||||
@@ -1804,12 +1711,6 @@ version = "0.6.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand_core"
|
|
||||||
version = "0.9.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_syscall"
|
name = "redox_syscall"
|
||||||
version = "0.5.13"
|
version = "0.5.13"
|
||||||
@@ -2018,16 +1919,6 @@ dependencies = [
|
|||||||
"rgb",
|
"rgb",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "snake"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"abi",
|
|
||||||
"embedded-graphics 0.8.1",
|
|
||||||
"embedded-snake",
|
|
||||||
"rand_core 0.6.4",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "spin"
|
name = "spin"
|
||||||
version = "0.10.0"
|
version = "0.10.0"
|
||||||
@@ -2050,10 +1941,9 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "st7365p-lcd"
|
name = "st7365p-lcd"
|
||||||
version = "0.11.0"
|
version = "0.11.0"
|
||||||
source = "git+https://github.com/legitcamper/st7365p-lcd-rs?rev=1d15123929fa7ef73d5d6aead7faf1bba50ce915#1d15123929fa7ef73d5d6aead7faf1bba50ce915"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitvec",
|
"bitvec",
|
||||||
"embedded-graphics-core 0.4.0",
|
"embedded-graphics-core",
|
||||||
"embedded-hal 1.0.0",
|
"embedded-hal 1.0.0",
|
||||||
"embedded-hal-async",
|
"embedded-hal-async",
|
||||||
"heapless",
|
"heapless",
|
||||||
@@ -2221,7 +2111,7 @@ dependencies = [
|
|||||||
"embedded-io",
|
"embedded-io",
|
||||||
"futures",
|
"futures",
|
||||||
"heapless",
|
"heapless",
|
||||||
"rand_core 0.6.4",
|
"rand_core",
|
||||||
"static_cell",
|
"static_cell",
|
||||||
"trouble-host-macros",
|
"trouble-host-macros",
|
||||||
"zerocopy",
|
"zerocopy",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
use abi_sys::draw_iter;
|
use abi_sys::draw_iter;
|
||||||
pub use abi_sys::{get_key, print, sleep};
|
pub use abi_sys::{get_key, print};
|
||||||
pub use embassy_time;
|
pub use embassy_time;
|
||||||
pub use shared::keyboard::{KeyCode, KeyEvent, KeyState, Modifiers};
|
pub use shared::keyboard::{KeyCode, KeyEvent, KeyState, Modifiers};
|
||||||
use talc::*;
|
use talc::*;
|
||||||
|
|||||||
@@ -21,13 +21,12 @@ pub static mut CALL_ABI_TABLE: [usize; CallAbiTable::COUNT] = [0; CallAbiTable::
|
|||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum CallAbiTable {
|
pub enum CallAbiTable {
|
||||||
Print = 0,
|
Print = 0,
|
||||||
Sleep = 1,
|
DrawIter = 1,
|
||||||
DrawIter = 2,
|
GetKey = 2,
|
||||||
GetKey = 3,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CallAbiTable {
|
impl CallAbiTable {
|
||||||
pub const COUNT: usize = 4;
|
pub const COUNT: usize = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type PrintAbi = extern "Rust" fn(msg: &str);
|
pub type PrintAbi = extern "Rust" fn(msg: &str);
|
||||||
@@ -40,16 +39,6 @@ pub fn print(msg: &str) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type SleepAbi = extern "Rust" fn(ms: u64);
|
|
||||||
|
|
||||||
pub fn sleep(ms: u64) {
|
|
||||||
unsafe {
|
|
||||||
let ptr = CALL_ABI_TABLE[CallAbiTable::Sleep as usize];
|
|
||||||
let f: SleepAbi = core::mem::transmute(ptr);
|
|
||||||
f(ms);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type DrawIterAbi = extern "Rust" fn(pixels: &[Pixel<Rgb565>]);
|
pub type DrawIterAbi = extern "Rust" fn(pixels: &[Pixel<Rgb565>]);
|
||||||
|
|
||||||
pub fn draw_iter(pixels: &[Pixel<Rgb565>]) {
|
pub fn draw_iter(pixels: &[Pixel<Rgb565>]) {
|
||||||
|
|||||||
@@ -31,20 +31,20 @@ defmt = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
embassy-executor = { version = "0.9", features = [
|
embassy-executor = { version = "0.7", features = [
|
||||||
"arch-cortex-m",
|
"arch-cortex-m",
|
||||||
"executor-interrupt",
|
"executor-interrupt",
|
||||||
"executor-thread",
|
"executor-thread",
|
||||||
"nightly",
|
"nightly",
|
||||||
] }
|
] }
|
||||||
embassy-rp = { version = "0.8.0", features = [
|
embassy-rp = { version = "0.4.0", features = [
|
||||||
"critical-section-impl",
|
"critical-section-impl",
|
||||||
"unstable-pac",
|
"unstable-pac",
|
||||||
"time-driver",
|
"time-driver",
|
||||||
] }
|
] }
|
||||||
embassy-usb = "0.5.1"
|
embassy-usb = "0.4.0"
|
||||||
embassy-futures = "0.1.2"
|
embassy-futures = "0.1.1"
|
||||||
embassy-time = { version = "0.5.0", features = ["generic-queue-8"] }
|
embassy-time = { version = "0.4.0", features = ["generic-queue-8"] }
|
||||||
embassy-embedded-hal = "0.3.1"
|
embassy-embedded-hal = "0.3.1"
|
||||||
embassy-sync = { version = "0.7" }
|
embassy-sync = { version = "0.7" }
|
||||||
trouble-host = { version = "0.1", features = [
|
trouble-host = { version = "0.1", features = [
|
||||||
@@ -60,19 +60,18 @@ cyw43-pio = { version = "0.3.0", optional = true }
|
|||||||
|
|
||||||
embedded-hal-bus = { version = "0.3.0", features = ["async"] }
|
embedded-hal-bus = { version = "0.3.0", features = ["async"] }
|
||||||
embedded-hal = "0.2.7"
|
embedded-hal = "0.2.7"
|
||||||
embedded-hal_2 = { package = "embedded-hal", version = "1.0.0" }
|
|
||||||
embedded-hal-async = "1.0.0"
|
embedded-hal-async = "1.0.0"
|
||||||
cortex-m = { version = "0.7.7" }
|
cortex-m = { version = "0.7.7" }
|
||||||
cortex-m-rt = "0.7.5"
|
cortex-m-rt = "0.7.5"
|
||||||
panic-probe = "0.3"
|
panic-probe = "0.3"
|
||||||
portable-atomic = { version = "1.11", features = ["critical-section"] }
|
portable-atomic = { version = "1.11", features = ["critical-section"] }
|
||||||
assign-resources = "0.5.0"
|
|
||||||
|
|
||||||
defmt = { version = "0.3", optional = true }
|
defmt = { version = "0.3", optional = true }
|
||||||
defmt-rtt = "0.4.2"
|
defmt-rtt = "0.4.2"
|
||||||
|
|
||||||
embedded-sdmmc = { version = "0.9", default-features = false }
|
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 = "87abf450404865dcb535292e9e1a6a2457fd4599" } # async branch
|
||||||
|
st7365p-lcd = { path = "../../ST7365P-lcd-rs" } # async branch
|
||||||
embedded-graphics = { version = "0.8.1" }
|
embedded-graphics = { version = "0.8.1" }
|
||||||
embedded-text = "0.7.2"
|
embedded-text = "0.7.2"
|
||||||
embedded-layout = "0.4.2"
|
embedded-layout = "0.4.2"
|
||||||
|
|||||||
@@ -1,11 +1,8 @@
|
|||||||
use core::{pin::Pin, time::Duration};
|
use core::pin::Pin;
|
||||||
|
|
||||||
use abi_sys::{DrawIterAbi, GetKeyAbi, Pixel, PrintAbi, SleepAbi};
|
use abi_sys::{DrawIterAbi, GetKeyAbi, Pixel, PrintAbi};
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
use defmt::info;
|
use defmt::info;
|
||||||
use embassy_futures::block_on;
|
|
||||||
use embassy_rp::clocks::clk_sys_freq;
|
|
||||||
use embassy_time::Timer;
|
|
||||||
use embedded_graphics::{
|
use embedded_graphics::{
|
||||||
Drawable,
|
Drawable,
|
||||||
draw_target::DrawTarget,
|
draw_target::DrawTarget,
|
||||||
@@ -15,11 +12,10 @@ use embedded_graphics::{
|
|||||||
};
|
};
|
||||||
use shared::keyboard::KeyEvent;
|
use shared::keyboard::KeyEvent;
|
||||||
|
|
||||||
use crate::{KEY_CACHE, display::FRAMEBUFFER};
|
use crate::{KEY_CACHE, display::framebuffer_mut};
|
||||||
|
|
||||||
// ensure the abi and the kernel fn signatures are the same
|
// ensure the abi and the kernel fn signatures are the same
|
||||||
const _: PrintAbi = print;
|
const _: PrintAbi = print;
|
||||||
const _: SleepAbi = sleep;
|
|
||||||
const _: DrawIterAbi = draw_iter;
|
const _: DrawIterAbi = draw_iter;
|
||||||
const _: GetKeyAbi = get_key;
|
const _: GetKeyAbi = get_key;
|
||||||
|
|
||||||
@@ -27,18 +23,10 @@ pub extern "Rust" fn print(msg: &str) {
|
|||||||
defmt::info!("{:?}", msg);
|
defmt::info!("{:?}", msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub extern "Rust" fn sleep(ms: u64) {
|
|
||||||
let cycles_per_ms = clk_sys_freq() / 1000;
|
|
||||||
for _ in 0..ms {
|
|
||||||
for _ in 0..cycles_per_ms {
|
|
||||||
cortex_m::asm::nop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: maybe return result
|
// TODO: maybe return result
|
||||||
pub extern "Rust" fn draw_iter(pixels: &[Pixel<Rgb565>]) {
|
pub extern "Rust" fn draw_iter(pixels: &[Pixel<Rgb565>]) {
|
||||||
unsafe { FRAMEBUFFER.draw_iter(pixels.iter().copied()).unwrap() }
|
let fb = framebuffer_mut();
|
||||||
|
fb.draw_iter(pixels.iter().copied()).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub extern "Rust" fn get_key() -> Option<KeyEvent> {
|
pub extern "Rust" fn get_key() -> Option<KeyEvent> {
|
||||||
|
|||||||
@@ -1,18 +1,13 @@
|
|||||||
use crate::framebuffer::AtomicFrameBuffer;
|
|
||||||
use embassy_rp::{
|
use embassy_rp::{
|
||||||
Peri,
|
|
||||||
gpio::{Level, Output},
|
gpio::{Level, Output},
|
||||||
peripherals::{PIN_13, PIN_14, PIN_15, SPI1},
|
peripherals::{PIN_13, PIN_14, PIN_15, SPI1},
|
||||||
spi::{Async, Spi},
|
spi::{Async, Spi},
|
||||||
};
|
};
|
||||||
|
use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, mutex::Mutex};
|
||||||
use embassy_time::{Delay, Timer};
|
use embassy_time::{Delay, Timer};
|
||||||
use embedded_graphics::{
|
|
||||||
draw_target::DrawTarget,
|
|
||||||
pixelcolor::{Rgb565, RgbColor},
|
|
||||||
prelude::Dimensions,
|
|
||||||
};
|
|
||||||
use embedded_hal_bus::spi::ExclusiveDevice;
|
use embedded_hal_bus::spi::ExclusiveDevice;
|
||||||
use st7365p_lcd::ST7365P;
|
use st7365p_lcd::{FrameBuffer, ST7365P};
|
||||||
|
use static_cell::StaticCell;
|
||||||
|
|
||||||
type DISPLAY = ST7365P<
|
type DISPLAY = ST7365P<
|
||||||
ExclusiveDevice<Spi<'static, SPI1, Async>, Output<'static>, Delay>,
|
ExclusiveDevice<Spi<'static, SPI1, Async>, Output<'static>, Delay>,
|
||||||
@@ -24,13 +19,18 @@ type DISPLAY = ST7365P<
|
|||||||
pub const SCREEN_WIDTH: usize = 320;
|
pub const SCREEN_WIDTH: usize = 320;
|
||||||
pub const SCREEN_HEIGHT: usize = 320;
|
pub const SCREEN_HEIGHT: usize = 320;
|
||||||
|
|
||||||
pub static mut FRAMEBUFFER: AtomicFrameBuffer = AtomicFrameBuffer::new();
|
type FB = FrameBuffer<SCREEN_WIDTH, SCREEN_HEIGHT, { SCREEN_WIDTH * SCREEN_HEIGHT }>;
|
||||||
|
static mut FRAMEBUFFER: Option<FB> = None;
|
||||||
|
|
||||||
|
pub fn framebuffer_mut() -> &'static mut FB {
|
||||||
|
unsafe { FRAMEBUFFER.as_mut().unwrap() }
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn init_display(
|
pub async fn init_display(
|
||||||
spi: Spi<'static, SPI1, Async>,
|
spi: Spi<'static, SPI1, Async>,
|
||||||
cs: Peri<'static, PIN_13>,
|
cs: PIN_13,
|
||||||
data: Peri<'static, PIN_14>,
|
data: PIN_14,
|
||||||
reset: Peri<'static, PIN_15>,
|
reset: PIN_15,
|
||||||
) -> DISPLAY {
|
) -> DISPLAY {
|
||||||
let spi_device = ExclusiveDevice::new(spi, Output::new(cs, Level::Low), Delay).unwrap();
|
let spi_device = ExclusiveDevice::new(spi, Output::new(cs, Level::Low), Delay).unwrap();
|
||||||
let mut display = ST7365P::new(
|
let mut display = ST7365P::new(
|
||||||
@@ -41,30 +41,20 @@ pub async fn init_display(
|
|||||||
true,
|
true,
|
||||||
Delay,
|
Delay,
|
||||||
);
|
);
|
||||||
|
|
||||||
display.init().await.unwrap();
|
display.init().await.unwrap();
|
||||||
display.set_custom_orientation(0x40).await.unwrap();
|
display.set_custom_orientation(0x40).await.unwrap();
|
||||||
unsafe { FRAMEBUFFER.draw(&mut display).await.unwrap() }
|
unsafe { FRAMEBUFFER.replace(FrameBuffer::new()) };
|
||||||
|
display.draw(framebuffer_mut()).await.unwrap();
|
||||||
display.set_on().await.unwrap();
|
display.set_on().await.unwrap();
|
||||||
|
|
||||||
display
|
display
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear_fb() {
|
|
||||||
let bounds = unsafe { FRAMEBUFFER.bounding_box() };
|
|
||||||
unsafe {
|
|
||||||
let _ = FRAMEBUFFER.fill_solid(&bounds, Rgb565::BLACK);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn display_handler(mut display: DISPLAY) {
|
pub async fn display_handler(mut display: DISPLAY) {
|
||||||
|
let fb = framebuffer_mut();
|
||||||
loop {
|
loop {
|
||||||
unsafe {
|
display.partial_draw_batched(fb).await.unwrap();
|
||||||
FRAMEBUFFER
|
embassy_time::Timer::after_millis(32).await; // 30 fps
|
||||||
.partial_draw_batched(&mut display)
|
|
||||||
.await
|
|
||||||
.unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
Timer::after_millis(32).await; // 30 fps
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,7 +53,6 @@ pub async unsafe fn load_binary(name: &ShortFileName) -> Result<EntryFn, &str> {
|
|||||||
// MUST MATCH ABI EXACTLY
|
// MUST MATCH ABI EXACTLY
|
||||||
let entries: &[(CallAbiTable, usize)] = &[
|
let entries: &[(CallAbiTable, usize)] = &[
|
||||||
(CallAbiTable::Print, abi::print as usize),
|
(CallAbiTable::Print, abi::print as usize),
|
||||||
(CallAbiTable::Sleep, abi::sleep as usize),
|
|
||||||
(CallAbiTable::DrawIter, abi::draw_iter as usize),
|
(CallAbiTable::DrawIter, abi::draw_iter as usize),
|
||||||
(CallAbiTable::GetKey, abi::get_key as usize),
|
(CallAbiTable::GetKey, abi::get_key as usize),
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -1,432 +0,0 @@
|
|||||||
use crate::display::{SCREEN_HEIGHT, SCREEN_WIDTH};
|
|
||||||
use core::sync::atomic::{AtomicBool, Ordering};
|
|
||||||
use embassy_sync::lazy_lock::LazyLock;
|
|
||||||
use embedded_graphics::{
|
|
||||||
draw_target::DrawTarget,
|
|
||||||
pixelcolor::{
|
|
||||||
Rgb565,
|
|
||||||
raw::{RawData, RawU16},
|
|
||||||
},
|
|
||||||
prelude::*,
|
|
||||||
primitives::Rectangle,
|
|
||||||
};
|
|
||||||
use embedded_hal_2::digital::OutputPin;
|
|
||||||
use embedded_hal_async::{delay::DelayNs, spi::SpiDevice};
|
|
||||||
use heapless::Vec;
|
|
||||||
use st7365p_lcd::{FrameBuffer, ST7365P};
|
|
||||||
|
|
||||||
pub const TILE_SIZE: usize = 16; // 16x16 tile
|
|
||||||
pub const TILE_COUNT: usize = (SCREEN_WIDTH / TILE_SIZE) * (SCREEN_HEIGHT / TILE_SIZE); // 400 tiles
|
|
||||||
|
|
||||||
// Group of tiles for batching
|
|
||||||
pub const MAX_META_TILES: usize = SCREEN_WIDTH / TILE_SIZE; // max number of meta tiles in buffer
|
|
||||||
type MetaTileVec = heapless::Vec<Rectangle, { TILE_COUNT / MAX_META_TILES }>;
|
|
||||||
|
|
||||||
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(|| {
|
|
||||||
let mut tiles = Vec::new();
|
|
||||||
for _ in 0..TILE_COUNT {
|
|
||||||
tiles.push(AtomicBool::new(true)).unwrap();
|
|
||||||
}
|
|
||||||
tiles
|
|
||||||
});
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub struct AtomicFrameBuffer;
|
|
||||||
|
|
||||||
impl AtomicFrameBuffer {
|
|
||||||
pub const fn new() -> Self {
|
|
||||||
Self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn mark_tiles_dirty(&mut self, rect: Rectangle) {
|
|
||||||
let tiles_x = (SCREEN_WIDTH + TILE_SIZE - 1) / 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;
|
|
||||||
let end_ty = ((rect.top_left.y + rect.size.height as i32 - 1) as usize) / TILE_SIZE;
|
|
||||||
|
|
||||||
for ty in start_ty..=end_ty {
|
|
||||||
for tx in start_tx..=end_tx {
|
|
||||||
let tile_idx = ty * tiles_x + tx;
|
|
||||||
unsafe { DIRTY_TILES.get_mut()[tile_idx].store(true, Ordering::Relaxed) };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_pixel(&mut self, x: u16, y: u16, color: u16) -> Result<(), ()> {
|
|
||||||
unsafe { BUFFER[(y as usize * SCREEN_WIDTH) + x as usize] = color };
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_pixels_buffered<P: IntoIterator<Item = u16>>(
|
|
||||||
&mut self,
|
|
||||||
sx: u16,
|
|
||||||
sy: u16,
|
|
||||||
ex: u16,
|
|
||||||
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
|
|
||||||
{
|
|
||||||
return Err(()); // Bounds check
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut color_iter = colors.into_iter();
|
|
||||||
|
|
||||||
for y in sy..=ey {
|
|
||||||
for x in sx..=ex {
|
|
||||||
if let Some(color) = color_iter.next() {
|
|
||||||
unsafe { BUFFER[(y as usize * SCREEN_WIDTH) + x as usize] = color };
|
|
||||||
} else {
|
|
||||||
return Err(()); // Not enough data
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Optional: check that we consumed *exactly* the right amount
|
|
||||||
if color_iter.next().is_some() {
|
|
||||||
return Err(()); // Too much data
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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();
|
|
||||||
|
|
||||||
for ty in 0..tiles_y {
|
|
||||||
let mut tx = 0;
|
|
||||||
while tx < tiles_x {
|
|
||||||
let idx = ty * tiles_x + tx;
|
|
||||||
if !unsafe { DIRTY_TILES.get()[idx].load(Ordering::Acquire) } {
|
|
||||||
tx += 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start meta-tile at this tile
|
|
||||||
let mut width_tiles = 1;
|
|
||||||
let height_tiles = 1;
|
|
||||||
|
|
||||||
// Grow horizontally, but keep under MAX_TILES_PER_METATILE
|
|
||||||
while tx + width_tiles < tiles_x
|
|
||||||
&& unsafe {
|
|
||||||
DIRTY_TILES.get()[ty * tiles_x + tx + width_tiles].load(Ordering::Relaxed)
|
|
||||||
}
|
|
||||||
&& (width_tiles + height_tiles) <= MAX_META_TILES
|
|
||||||
{
|
|
||||||
width_tiles += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: for simplicity, skipped vertical growth
|
|
||||||
|
|
||||||
for x_off in 0..width_tiles {
|
|
||||||
unsafe {
|
|
||||||
DIRTY_TILES.get()[ty * tiles_x + tx + x_off]
|
|
||||||
.store(false, Ordering::Release);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// new meta-tile pos
|
|
||||||
let rect = Rectangle::new(
|
|
||||||
Point::new((tx * TILE_SIZE) as i32, (ty * TILE_SIZE) as i32),
|
|
||||||
Size::new(
|
|
||||||
(width_tiles * TILE_SIZE) as u32,
|
|
||||||
(height_tiles * TILE_SIZE) as u32,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
if meta_tiles.push(rect).is_err() {
|
|
||||||
return meta_tiles;
|
|
||||||
};
|
|
||||||
|
|
||||||
tx += width_tiles;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
meta_tiles
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sends the entire framebuffer to the display
|
|
||||||
pub async fn draw<SPI, DC, RST, DELAY: DelayNs>(
|
|
||||||
&mut self,
|
|
||||||
display: &mut ST7365P<SPI, DC, RST, DELAY>,
|
|
||||||
) -> Result<(), ()>
|
|
||||||
where
|
|
||||||
SPI: SpiDevice,
|
|
||||||
DC: OutputPin,
|
|
||||||
RST: OutputPin,
|
|
||||||
{
|
|
||||||
display
|
|
||||||
.set_pixels_buffered(
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
self.size().width as u16 - 1,
|
|
||||||
self.size().height as u16 - 1,
|
|
||||||
unsafe { &BUFFER },
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
for tile in DIRTY_TILES.get_mut().iter() {
|
|
||||||
tile.store(false, Ordering::Release);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sends only dirty tiles (16x16px) individually to the display without batching
|
|
||||||
pub async fn partial_draw<SPI, DC, RST, DELAY: DelayNs>(
|
|
||||||
&mut self,
|
|
||||||
display: &mut ST7365P<SPI, DC, RST, DELAY>,
|
|
||||||
) -> Result<(), ()>
|
|
||||||
where
|
|
||||||
SPI: SpiDevice,
|
|
||||||
DC: OutputPin,
|
|
||||||
RST: OutputPin,
|
|
||||||
{
|
|
||||||
if unsafe { DIRTY_TILES.get().iter().any(|p| p.load(Ordering::Acquire)) } {
|
|
||||||
let tiles_x = (SCREEN_WIDTH + TILE_SIZE - 1) / TILE_SIZE;
|
|
||||||
let tiles_y = (SCREEN_HEIGHT + TILE_SIZE - 1) / TILE_SIZE;
|
|
||||||
|
|
||||||
let mut tile_buffer = [0u16; TILE_SIZE * TILE_SIZE];
|
|
||||||
|
|
||||||
for ty in 0..tiles_y {
|
|
||||||
for tx in 0..tiles_x {
|
|
||||||
if unsafe { !DIRTY_TILES.get()[ty * tiles_x + tx].load(Ordering::Acquire) } {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let x = tx * TILE_SIZE;
|
|
||||||
let y = ty * TILE_SIZE;
|
|
||||||
|
|
||||||
// Copy pixels for the tile into tile_buffer
|
|
||||||
for row in 0..TILE_SIZE {
|
|
||||||
for col in 0..TILE_SIZE {
|
|
||||||
let actual_x = x + col;
|
|
||||||
let actual_y = y + row;
|
|
||||||
|
|
||||||
if actual_x < SCREEN_WIDTH && actual_y < SCREEN_HEIGHT {
|
|
||||||
let idx = actual_y * SCREEN_WIDTH + actual_x;
|
|
||||||
tile_buffer[row * TILE_SIZE + col] = unsafe { BUFFER[idx] };
|
|
||||||
} else {
|
|
||||||
// Out of bounds, fill with zero (or background)
|
|
||||||
tile_buffer[row * TILE_SIZE + col] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send the tile's pixel data to the display
|
|
||||||
display
|
|
||||||
.set_pixels_buffered(
|
|
||||||
x as u16,
|
|
||||||
y as u16,
|
|
||||||
(x + TILE_SIZE - 1).min(SCREEN_WIDTH - 1) as u16,
|
|
||||||
(y + TILE_SIZE - 1).min(SCREEN_HEIGHT - 1) as u16,
|
|
||||||
&tile_buffer,
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
// Mark tile as clean
|
|
||||||
unsafe {
|
|
||||||
DIRTY_TILES.get_mut()[ty * tiles_x + tx].store(false, Ordering::Release)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sends only dirty tiles (16x16px) in batches to the display
|
|
||||||
pub async fn partial_draw_batched<SPI, DC, RST, DELAY>(
|
|
||||||
&mut self,
|
|
||||||
display: &mut ST7365P<SPI, DC, RST, DELAY>,
|
|
||||||
) -> Result<(), ()>
|
|
||||||
where
|
|
||||||
SPI: SpiDevice,
|
|
||||||
DC: OutputPin,
|
|
||||||
RST: OutputPin,
|
|
||||||
DELAY: DelayNs,
|
|
||||||
{
|
|
||||||
if unsafe { DIRTY_TILES.get().iter().any(|p| p.load(Ordering::Acquire)) } {
|
|
||||||
let tiles_x = (SCREEN_WIDTH + TILE_SIZE - 1) / TILE_SIZE;
|
|
||||||
let tiles_y = (SCREEN_HEIGHT + TILE_SIZE - 1) / TILE_SIZE;
|
|
||||||
|
|
||||||
let meta_tiles = self.find_meta_tiles(tiles_x, tiles_y);
|
|
||||||
|
|
||||||
// buffer for copying meta tiles before sending to display
|
|
||||||
let mut pixel_buffer: heapless::Vec<u16, { MAX_META_TILES * TILE_SIZE * TILE_SIZE }> =
|
|
||||||
Vec::new();
|
|
||||||
|
|
||||||
for rect in meta_tiles {
|
|
||||||
let rect_width = rect.size.width as usize;
|
|
||||||
let rect_height = rect.size.height as usize;
|
|
||||||
let rect_x = rect.top_left.x as usize;
|
|
||||||
let rect_y = rect.top_left.y as usize;
|
|
||||||
|
|
||||||
pixel_buffer.clear();
|
|
||||||
|
|
||||||
for row in 0..rect_height {
|
|
||||||
let y = rect_y + row;
|
|
||||||
let start = y * SCREEN_WIDTH + rect_x;
|
|
||||||
let end = start + rect_width;
|
|
||||||
|
|
||||||
// Safe: we guarantee buffer will not exceed MAX_META_TILE_PIXELS
|
|
||||||
pixel_buffer
|
|
||||||
.extend_from_slice(unsafe { &BUFFER[start..end] })
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
display
|
|
||||||
.set_pixels_buffered(
|
|
||||||
rect_x as u16,
|
|
||||||
rect_y as u16,
|
|
||||||
(rect_x + rect_width - 1) as u16,
|
|
||||||
(rect_y + rect_height - 1) as u16,
|
|
||||||
&pixel_buffer,
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
// walk the meta-tile and set as clean
|
|
||||||
let start_tx = rect_x / TILE_SIZE;
|
|
||||||
let start_ty = rect_y / TILE_SIZE;
|
|
||||||
let end_tx = (rect_x + rect_width - 1) / TILE_SIZE;
|
|
||||||
let end_ty = (rect_y + rect_height - 1) / TILE_SIZE;
|
|
||||||
|
|
||||||
for ty in start_ty..=end_ty {
|
|
||||||
for tx in start_tx..=end_tx {
|
|
||||||
let tile_idx = ty * tiles_x + tx;
|
|
||||||
unsafe { DIRTY_TILES.get_mut()[tile_idx].store(false, Ordering::Release) };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DrawTarget for AtomicFrameBuffer {
|
|
||||||
type Error = ();
|
|
||||||
type Color = Rgb565;
|
|
||||||
|
|
||||||
fn draw_iter<I>(&mut self, pixels: I) -> Result<(), Self::Error>
|
|
||||||
where
|
|
||||||
I: IntoIterator<Item = Pixel<Self::Color>>,
|
|
||||||
{
|
|
||||||
let mut dirty_rect: Option<Rectangle> = None;
|
|
||||||
|
|
||||||
for Pixel(coord, color) in pixels {
|
|
||||||
if coord.x >= 0 && coord.y >= 0 {
|
|
||||||
let x = coord.x as i32;
|
|
||||||
let y = coord.y as i32;
|
|
||||||
|
|
||||||
if (x as usize) < SCREEN_WIDTH && (y as usize) < SCREEN_HEIGHT {
|
|
||||||
unsafe {
|
|
||||||
BUFFER[(y as usize) * SCREEN_WIDTH + (x as usize)] =
|
|
||||||
RawU16::from(color).into_inner()
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(ref mut rect) = dirty_rect {
|
|
||||||
rect.top_left.x = rect.top_left.x.min(x);
|
|
||||||
rect.top_left.y = rect.top_left.y.min(y);
|
|
||||||
let max_x = (rect.top_left.x + rect.size.width as i32 - 1).max(x);
|
|
||||||
let max_y = (rect.top_left.y + rect.size.height as i32 - 1).max(y);
|
|
||||||
rect.size.width = (max_x - rect.top_left.x + 1) as u32;
|
|
||||||
rect.size.height = (max_y - rect.top_left.y + 1) as u32;
|
|
||||||
} else {
|
|
||||||
dirty_rect = Some(Rectangle::new(Point::new(x, y), Size::new(1, 1)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(rect) = dirty_rect {
|
|
||||||
self.mark_tiles_dirty(rect);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fill_contiguous<I>(&mut self, area: &Rectangle, colors: I) -> Result<(), Self::Error>
|
|
||||||
where
|
|
||||||
I: IntoIterator<Item = Self::Color>,
|
|
||||||
{
|
|
||||||
let drawable_area = area.intersection(&Rectangle::new(Point::zero(), self.size()));
|
|
||||||
|
|
||||||
if drawable_area.size != Size::zero() {
|
|
||||||
// We assume that `colors` iterator is in row-major order for the original `area`
|
|
||||||
// So we must skip rows/pixels that are clipped
|
|
||||||
let area_width = area.size.width;
|
|
||||||
let area_height = area.size.height;
|
|
||||||
let mut colors = colors.into_iter();
|
|
||||||
|
|
||||||
for y in 0..area_height {
|
|
||||||
for x in 0..area_width {
|
|
||||||
let p = area.top_left + Point::new(x as i32, y as i32);
|
|
||||||
|
|
||||||
if drawable_area.contains(p) {
|
|
||||||
if let Some(color) = colors.next() {
|
|
||||||
self.set_pixel(
|
|
||||||
p.x as u16,
|
|
||||||
p.y as u16,
|
|
||||||
RawU16::from(color).into_inner(),
|
|
||||||
)?;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Still need to consume the color even if not used!
|
|
||||||
let _ = colors.next();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.mark_tiles_dirty(*area);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
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),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn clear(&mut self, color: Self::Color) -> Result<(), Self::Error> {
|
|
||||||
self.set_pixels_buffered(
|
|
||||||
0,
|
|
||||||
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),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
for tile in DIRTY_TILES.get_mut().iter() {
|
|
||||||
tile.store(true, Ordering::Relaxed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl OriginDimensions for AtomicFrameBuffer {
|
|
||||||
fn size(&self) -> Size {
|
|
||||||
Size::new(SCREEN_WIDTH as u32, SCREEN_HEIGHT as u32)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -10,7 +10,6 @@ extern crate alloc;
|
|||||||
mod abi;
|
mod abi;
|
||||||
mod display;
|
mod display;
|
||||||
mod elf;
|
mod elf;
|
||||||
mod framebuffer;
|
|
||||||
mod peripherals;
|
mod peripherals;
|
||||||
mod scsi;
|
mod scsi;
|
||||||
mod storage;
|
mod storage;
|
||||||
@@ -19,8 +18,7 @@ mod usb;
|
|||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
display::{FRAMEBUFFER, clear_fb, display_handler, init_display},
|
display::{display_handler, framebuffer_mut, init_display},
|
||||||
elf::load_binary,
|
|
||||||
peripherals::{
|
peripherals::{
|
||||||
conf_peripherals,
|
conf_peripherals,
|
||||||
keyboard::{KeyCode, KeyState, read_keyboard_fifo},
|
keyboard::{KeyCode, KeyState, read_keyboard_fifo},
|
||||||
@@ -29,16 +27,11 @@ use crate::{
|
|||||||
ui::{SELECTIONS, ui_handler},
|
ui::{SELECTIONS, ui_handler},
|
||||||
usb::usb_handler,
|
usb::usb_handler,
|
||||||
};
|
};
|
||||||
use abi_sys::EntryFn;
|
use abi_sys::{EntryFn, Rgb565, RgbColor};
|
||||||
|
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
|
||||||
|
|
||||||
use assign_resources::assign_resources;
|
|
||||||
use defmt::unwrap;
|
use defmt::unwrap;
|
||||||
use embassy_executor::{Executor, Spawner};
|
use embassy_executor::{Executor, Spawner};
|
||||||
use embassy_futures::join::{join, join3, join4, join5};
|
use embassy_futures::join::{join, join3, join4, join5};
|
||||||
use embassy_rp::{
|
use embassy_rp::{
|
||||||
Peri,
|
|
||||||
gpio::{Input, Level, Output, Pull},
|
gpio::{Input, Level, Output, Pull},
|
||||||
i2c::{self, I2c},
|
i2c::{self, I2c},
|
||||||
multicore::{Stack, spawn_core1},
|
multicore::{Stack, spawn_core1},
|
||||||
@@ -53,12 +46,14 @@ use embassy_sync::{
|
|||||||
blocking_mutex::raw::CriticalSectionRawMutex, channel::Channel, mutex::Mutex, signal::Signal,
|
blocking_mutex::raw::CriticalSectionRawMutex, channel::Channel, mutex::Mutex, signal::Signal,
|
||||||
};
|
};
|
||||||
use embassy_time::{Delay, Timer};
|
use embassy_time::{Delay, Timer};
|
||||||
|
use embedded_graphics::draw_target::DrawTarget;
|
||||||
use embedded_hal_bus::spi::ExclusiveDevice;
|
use embedded_hal_bus::spi::ExclusiveDevice;
|
||||||
use embedded_sdmmc::SdCard as SdmmcSdCard;
|
use embedded_sdmmc::SdCard as SdmmcSdCard;
|
||||||
use heapless::spsc::Queue;
|
use heapless::spsc::Queue;
|
||||||
use shared::keyboard::KeyEvent;
|
use shared::keyboard::KeyEvent;
|
||||||
use static_cell::StaticCell;
|
use static_cell::StaticCell;
|
||||||
use talc::*;
|
use talc::*;
|
||||||
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
embassy_rp::bind_interrupts!(struct Irqs {
|
embassy_rp::bind_interrupts!(struct Irqs {
|
||||||
I2C1_IRQ => i2c::InterruptHandler<I2C1>;
|
I2C1_IRQ => i2c::InterruptHandler<I2C1>;
|
||||||
@@ -79,7 +74,7 @@ static ALLOCATOR: Talck<spin::Mutex<()>, ClaimOnOom> =
|
|||||||
static TASK_STATE: Mutex<CriticalSectionRawMutex, TaskState> = Mutex::new(TaskState::Ui);
|
static TASK_STATE: Mutex<CriticalSectionRawMutex, TaskState> = Mutex::new(TaskState::Ui);
|
||||||
static TASK_STATE_CHANGED: Signal<CriticalSectionRawMutex, ()> = Signal::new();
|
static TASK_STATE_CHANGED: Signal<CriticalSectionRawMutex, ()> = Signal::new();
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq)]
|
#[derive(Copy, Clone)]
|
||||||
enum TaskState {
|
enum TaskState {
|
||||||
Ui,
|
Ui,
|
||||||
Kernel,
|
Kernel,
|
||||||
@@ -135,54 +130,61 @@ async fn userland_task() {
|
|||||||
let recv = BINARY_CH.receiver();
|
let recv = BINARY_CH.receiver();
|
||||||
loop {
|
loop {
|
||||||
let entry = recv.receive().await;
|
let entry = recv.receive().await;
|
||||||
defmt::info!("Got Entry");
|
defmt::info!("got bin");
|
||||||
|
|
||||||
// disable kernel ui
|
// disable kernel ui
|
||||||
{
|
{
|
||||||
let mut state = TASK_STATE.lock().await;
|
let mut state = TASK_STATE.lock().await;
|
||||||
*state = TaskState::Kernel;
|
*state = TaskState::Kernel;
|
||||||
|
TASK_STATE_CHANGED.signal(());
|
||||||
}
|
}
|
||||||
|
|
||||||
// clear_fb();
|
{
|
||||||
|
let fb = framebuffer_mut();
|
||||||
|
fb.clear(Rgb565::BLACK).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
defmt::info!("Executing Binary");
|
defmt::info!("running entry");
|
||||||
entry().await;
|
entry().await;
|
||||||
|
|
||||||
// enable kernel ui
|
// enable kernel ui
|
||||||
{
|
{
|
||||||
let mut state = TASK_STATE.lock().await;
|
let mut state = TASK_STATE.lock().await;
|
||||||
*state = TaskState::Ui;
|
*state = TaskState::Ui;
|
||||||
|
TASK_STATE_CHANGED.signal(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Display {
|
struct Display {
|
||||||
spi: Peri<'static, SPI1>,
|
spi: SPI1,
|
||||||
clk: Peri<'static, PIN_10>,
|
clk: PIN_10,
|
||||||
mosi: Peri<'static, PIN_11>,
|
mosi: PIN_11,
|
||||||
miso: Peri<'static, PIN_12>,
|
miso: PIN_12,
|
||||||
dma1: Peri<'static, DMA_CH0>,
|
dma1: DMA_CH0,
|
||||||
dma2: Peri<'static, DMA_CH1>,
|
dma2: DMA_CH1,
|
||||||
cs: Peri<'static, PIN_13>,
|
cs: PIN_13,
|
||||||
data: Peri<'static, PIN_14>,
|
data: PIN_14,
|
||||||
reset: Peri<'static, PIN_15>,
|
reset: PIN_15,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Sd {
|
struct Sd {
|
||||||
spi: Peri<'static, SPI0>,
|
spi: SPI0,
|
||||||
clk: Peri<'static, PIN_18>,
|
clk: PIN_18,
|
||||||
mosi: Peri<'static, PIN_19>,
|
mosi: PIN_19,
|
||||||
miso: Peri<'static, PIN_16>,
|
miso: PIN_16,
|
||||||
cs: Peri<'static, PIN_17>,
|
cs: PIN_17,
|
||||||
det: Peri<'static, PIN_22>,
|
det: PIN_22,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Mcu {
|
struct Mcu {
|
||||||
i2c: Peri<'static, I2C1>,
|
i2c: I2C1,
|
||||||
clk: Peri<'static, PIN_7>,
|
clk: PIN_7,
|
||||||
data: Peri<'static, PIN_6>,
|
data: PIN_6,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[embassy_executor::task]
|
#[embassy_executor::task]
|
||||||
async fn kernel_task(display: Display, sd: Sd, mcu: Mcu, usb: Peri<'static, USB>) {
|
async fn kernel_task(display: Display, sd: Sd, mcu: Mcu, usb: USB) {
|
||||||
// MCU i2c bus for peripherals
|
// MCU i2c bus for peripherals
|
||||||
let mut config = i2c::Config::default();
|
let mut config = i2c::Config::default();
|
||||||
config.frequency = 400_000;
|
config.frequency = 400_000;
|
||||||
@@ -242,8 +244,8 @@ async fn kernel_task(display: Display, sd: Sd, mcu: Mcu, usb: Peri<'static, USB>
|
|||||||
SDCARD.get().lock().await.replace(SdCard::new(sdcard, det));
|
SDCARD.get().lock().await.replace(SdCard::new(sdcard, det));
|
||||||
};
|
};
|
||||||
|
|
||||||
let usb = embassy_rp_usb::Driver::new(usb, Irqs);
|
// let usb = embassy_rp_usb::Driver::new(usb, Irqs);
|
||||||
let usb_fut = usb_handler(usb);
|
// let usb_fut = usb_handler(usb);
|
||||||
|
|
||||||
let key_abi_fut = async {
|
let key_abi_fut = async {
|
||||||
loop {
|
loop {
|
||||||
@@ -252,17 +254,15 @@ async fn kernel_task(display: Display, sd: Sd, mcu: Mcu, usb: Peri<'static, USB>
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
join5(display_fut, ui_fut, usb_fut, binary_search_fut, key_abi_fut).await;
|
join4(display_fut, ui_fut, binary_search_fut, key_abi_fut).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
static mut KEY_CACHE: Queue<KeyEvent, 32> = Queue::new();
|
static mut KEY_CACHE: Queue<KeyEvent, 32> = Queue::new();
|
||||||
|
|
||||||
async fn get_keys() {
|
async fn get_keys() {
|
||||||
if let Some(event) = read_keyboard_fifo().await {
|
if let Some(event) = read_keyboard_fifo().await {
|
||||||
if let KeyState::Pressed = event.state {
|
unsafe {
|
||||||
unsafe {
|
let _ = KEY_CACHE.enqueue(event);
|
||||||
let _ = KEY_CACHE.enqueue(event);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,9 +5,7 @@ use embassy_rp::{
|
|||||||
i2c::{Async, I2c},
|
i2c::{Async, I2c},
|
||||||
peripherals::I2C1,
|
peripherals::I2C1,
|
||||||
};
|
};
|
||||||
use embassy_sync::{
|
use embassy_sync::{blocking_mutex::raw::NoopRawMutex, lazy_lock::LazyLock, mutex::Mutex};
|
||||||
blocking_mutex::raw::CriticalSectionRawMutex, lazy_lock::LazyLock, mutex::Mutex,
|
|
||||||
};
|
|
||||||
use embassy_time::Timer;
|
use embassy_time::Timer;
|
||||||
|
|
||||||
pub mod keyboard;
|
pub mod keyboard;
|
||||||
@@ -17,7 +15,7 @@ use crate::peripherals::keyboard::{configure_keyboard, read_keyboard_fifo};
|
|||||||
const MCU_ADDR: u8 = 0x1F;
|
const MCU_ADDR: u8 = 0x1F;
|
||||||
|
|
||||||
type I2CBUS = I2c<'static, I2C1, Async>;
|
type I2CBUS = I2c<'static, I2C1, Async>;
|
||||||
pub static PERIPHERAL_BUS: LazyLock<Mutex<CriticalSectionRawMutex, Option<I2CBUS>>> =
|
pub static PERIPHERAL_BUS: LazyLock<Mutex<NoopRawMutex, Option<I2CBUS>>> =
|
||||||
LazyLock::new(|| Mutex::new(None));
|
LazyLock::new(|| Mutex::new(None));
|
||||||
|
|
||||||
const REG_ID_VER: u8 = 0x01;
|
const REG_ID_VER: u8 = 0x01;
|
||||||
|
|||||||
@@ -8,25 +8,30 @@ use heapless::Vec;
|
|||||||
mod scsi_types;
|
mod scsi_types;
|
||||||
use scsi_types::*;
|
use scsi_types::*;
|
||||||
|
|
||||||
use crate::storage::{SDCARD, SdCard};
|
use crate::storage::SdCard;
|
||||||
|
|
||||||
const BULK_ENDPOINT_PACKET_SIZE: usize = 64;
|
const BULK_ENDPOINT_PACKET_SIZE: usize = 64;
|
||||||
|
|
||||||
pub struct MassStorageClass<'d, D: Driver<'d>> {
|
pub struct MassStorageClass<'d, 's, D: Driver<'d>> {
|
||||||
|
sdcard: &'s SdCard,
|
||||||
bulk_out: D::EndpointOut,
|
bulk_out: D::EndpointOut,
|
||||||
bulk_in: D::EndpointIn,
|
bulk_in: D::EndpointIn,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, 's, D: Driver<'d>> MassStorageClass<'d, D> {
|
impl<'d, 's, D: Driver<'d>> MassStorageClass<'d, 's, D> {
|
||||||
pub fn new(builder: &mut Builder<'d, D>) -> Self {
|
pub fn new(builder: &mut Builder<'d, D>, sdcard: &'s SdCard) -> Self {
|
||||||
let mut function = builder.function(0x08, SUBCLASS_SCSI, 0x50); // Mass Storage class
|
let mut function = builder.function(0x08, SUBCLASS_SCSI, 0x50); // Mass Storage class
|
||||||
let mut interface = function.interface();
|
let mut interface = function.interface();
|
||||||
let mut alt = interface.alt_setting(0x08, SUBCLASS_SCSI, 0x50, None);
|
let mut alt = interface.alt_setting(0x08, SUBCLASS_SCSI, 0x50, None);
|
||||||
|
|
||||||
let bulk_out = alt.endpoint_bulk_out(None, BULK_ENDPOINT_PACKET_SIZE as u16);
|
let bulk_out = alt.endpoint_bulk_out(BULK_ENDPOINT_PACKET_SIZE as u16);
|
||||||
let bulk_in = alt.endpoint_bulk_in(None, BULK_ENDPOINT_PACKET_SIZE as u16);
|
let bulk_in = alt.endpoint_bulk_in(BULK_ENDPOINT_PACKET_SIZE as u16);
|
||||||
|
|
||||||
Self { bulk_out, bulk_in }
|
Self {
|
||||||
|
bulk_out,
|
||||||
|
bulk_in,
|
||||||
|
sdcard,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn poll(&mut self) {
|
pub async fn poll(&mut self) {
|
||||||
@@ -134,9 +139,7 @@ impl<'d, 's, D: Driver<'d>> MassStorageClass<'d, D> {
|
|||||||
self.bulk_in.write(&response[..len]).await.map_err(|_| ())
|
self.bulk_in.write(&response[..len]).await.map_err(|_| ())
|
||||||
}
|
}
|
||||||
ScsiCommand::TestUnitReady => {
|
ScsiCommand::TestUnitReady => {
|
||||||
let guard = SDCARD.get().lock().await;
|
if self.sdcard.is_attached() {
|
||||||
let sdcard = guard.as_ref().unwrap();
|
|
||||||
if sdcard.is_attached() {
|
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(())
|
||||||
@@ -182,11 +185,8 @@ impl<'d, 's, D: Driver<'d>> MassStorageClass<'d, D> {
|
|||||||
self.bulk_in.write(&response[..len]).await.map_err(|_| ())
|
self.bulk_in.write(&response[..len]).await.map_err(|_| ())
|
||||||
}
|
}
|
||||||
ScsiCommand::ReadCapacity10 => {
|
ScsiCommand::ReadCapacity10 => {
|
||||||
let guard = SDCARD.get().lock().await;
|
|
||||||
let sdcard = guard.as_ref().unwrap();
|
|
||||||
|
|
||||||
let block_size = SdCard::BLOCK_SIZE as u64;
|
let block_size = SdCard::BLOCK_SIZE as u64;
|
||||||
let total_blocks = sdcard.size() / block_size;
|
let total_blocks = self.sdcard.size() / block_size;
|
||||||
|
|
||||||
let last_lba = total_blocks.checked_sub(1).unwrap_or(0);
|
let last_lba = total_blocks.checked_sub(1).unwrap_or(0);
|
||||||
|
|
||||||
@@ -196,11 +196,8 @@ impl<'d, 's, D: Driver<'d>> MassStorageClass<'d, D> {
|
|||||||
self.bulk_in.write(&response).await.map_err(|_| ())
|
self.bulk_in.write(&response).await.map_err(|_| ())
|
||||||
}
|
}
|
||||||
ScsiCommand::ReadCapacity16 { alloc_len } => {
|
ScsiCommand::ReadCapacity16 { alloc_len } => {
|
||||||
let guard = SDCARD.get().lock().await;
|
|
||||||
let sdcard = guard.as_ref().unwrap();
|
|
||||||
|
|
||||||
let block_size = SdCard::BLOCK_SIZE as u64;
|
let block_size = SdCard::BLOCK_SIZE as u64;
|
||||||
let total_blocks = sdcard.size() / block_size;
|
let total_blocks = self.sdcard.size() / block_size;
|
||||||
|
|
||||||
let last_lba = total_blocks.checked_sub(1).unwrap_or(0);
|
let last_lba = total_blocks.checked_sub(1).unwrap_or(0);
|
||||||
|
|
||||||
@@ -212,12 +209,9 @@ impl<'d, 's, D: Driver<'d>> MassStorageClass<'d, D> {
|
|||||||
self.bulk_in.write(&response[..len]).await.map_err(|_| ())
|
self.bulk_in.write(&response[..len]).await.map_err(|_| ())
|
||||||
}
|
}
|
||||||
ScsiCommand::Read { lba, len } => {
|
ScsiCommand::Read { lba, len } => {
|
||||||
let guard = SDCARD.get().lock().await;
|
|
||||||
let sdcard = guard.as_ref().unwrap();
|
|
||||||
|
|
||||||
for i in 0..len {
|
for i in 0..len {
|
||||||
let block_idx = BlockIdx(lba as u32 + i as u32);
|
let block_idx = BlockIdx(lba as u32 + i as u32);
|
||||||
sdcard.read_blocks(&mut block, block_idx)?;
|
self.sdcard.read_blocks(&mut block, block_idx)?;
|
||||||
for chunk in block[0].contents.chunks(BULK_ENDPOINT_PACKET_SIZE.into()) {
|
for chunk in block[0].contents.chunks(BULK_ENDPOINT_PACKET_SIZE.into()) {
|
||||||
self.bulk_in.write(chunk).await.map_err(|_| ())?;
|
self.bulk_in.write(chunk).await.map_err(|_| ())?;
|
||||||
}
|
}
|
||||||
@@ -225,9 +219,6 @@ impl<'d, 's, D: Driver<'d>> MassStorageClass<'d, D> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
ScsiCommand::Write { lba, len } => {
|
ScsiCommand::Write { lba, len } => {
|
||||||
let guard = SDCARD.get().lock().await;
|
|
||||||
let sdcard = guard.as_ref().unwrap();
|
|
||||||
|
|
||||||
for i in 0..len {
|
for i in 0..len {
|
||||||
let block_idx = BlockIdx(lba as u32 + i as u32);
|
let block_idx = BlockIdx(lba as u32 + i as u32);
|
||||||
for chunk in block[0]
|
for chunk in block[0]
|
||||||
@@ -236,16 +227,13 @@ impl<'d, 's, D: Driver<'d>> MassStorageClass<'d, D> {
|
|||||||
{
|
{
|
||||||
self.bulk_out.read(chunk).await.map_err(|_| ())?;
|
self.bulk_out.read(chunk).await.map_err(|_| ())?;
|
||||||
}
|
}
|
||||||
sdcard.write_blocks(&mut block, block_idx)?;
|
self.sdcard.write_blocks(&mut block, block_idx)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
ScsiCommand::ReadFormatCapacities { alloc_len } => {
|
ScsiCommand::ReadFormatCapacities { alloc_len } => {
|
||||||
let guard = SDCARD.get().lock().await;
|
|
||||||
let sdcard = guard.as_ref().unwrap();
|
|
||||||
|
|
||||||
let block_size = SdCard::BLOCK_SIZE as u32;
|
let block_size = SdCard::BLOCK_SIZE as u32;
|
||||||
let num_blocks = (sdcard.size() / block_size as u64) as u32;
|
let num_blocks = (self.sdcard.size() / block_size as u64) as u32;
|
||||||
|
|
||||||
let mut response = [0u8; 12];
|
let mut response = [0u8; 12];
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use core::str::FromStr;
|
|||||||
use embassy_rp::gpio::{Input, Output};
|
use embassy_rp::gpio::{Input, Output};
|
||||||
use embassy_rp::peripherals::SPI0;
|
use embassy_rp::peripherals::SPI0;
|
||||||
use embassy_rp::spi::{Blocking, Spi};
|
use embassy_rp::spi::{Blocking, Spi};
|
||||||
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
use embassy_sync::blocking_mutex::raw::NoopRawMutex;
|
||||||
use embassy_sync::lazy_lock::LazyLock;
|
use embassy_sync::lazy_lock::LazyLock;
|
||||||
use embassy_sync::mutex::Mutex;
|
use embassy_sync::mutex::Mutex;
|
||||||
use embassy_time::Delay;
|
use embassy_time::Delay;
|
||||||
@@ -25,7 +25,7 @@ type Vol<'a> = Volume<'a, SD, DummyTimeSource, MAX_DIRS, MAX_FILES, MAX_VOLUMES>
|
|||||||
type Dir<'a> = Directory<'a, SD, DummyTimeSource, MAX_DIRS, MAX_FILES, MAX_VOLUMES>;
|
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>;
|
pub type File<'a> = SdFile<'a, SD, DummyTimeSource, MAX_DIRS, MAX_FILES, MAX_VOLUMES>;
|
||||||
|
|
||||||
pub static SDCARD: LazyLock<Mutex<CriticalSectionRawMutex, Option<SdCard>>> =
|
pub static SDCARD: LazyLock<Mutex<NoopRawMutex, Option<SdCard>>> =
|
||||||
LazyLock::new(|| Mutex::new(None));
|
LazyLock::new(|| Mutex::new(None));
|
||||||
|
|
||||||
pub struct DummyTimeSource {}
|
pub struct DummyTimeSource {}
|
||||||
|
|||||||
@@ -1,25 +1,40 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
BINARY_CH, TASK_STATE, TaskState,
|
BINARY_CH, TASK_STATE, TaskState,
|
||||||
display::{FRAMEBUFFER, SCREEN_HEIGHT, SCREEN_WIDTH},
|
display::{SCREEN_HEIGHT, SCREEN_WIDTH, framebuffer_mut},
|
||||||
elf::load_binary,
|
elf::load_binary,
|
||||||
format,
|
format,
|
||||||
peripherals::keyboard,
|
peripherals::keyboard,
|
||||||
storage::FileName,
|
storage::FileName,
|
||||||
|
usb::RESTART_USB,
|
||||||
};
|
};
|
||||||
use alloc::{string::String, vec::Vec};
|
use alloc::{string::String, vec::Vec};
|
||||||
use core::{fmt::Debug, str::FromStr, sync::atomic::Ordering};
|
use core::{fmt::Debug, str::FromStr, sync::atomic::Ordering};
|
||||||
|
use defmt::info;
|
||||||
|
use embassy_rp::{
|
||||||
|
gpio::{Level, Output},
|
||||||
|
peripherals::{PIN_13, PIN_14, PIN_15, SPI1},
|
||||||
|
spi::{Async, Spi},
|
||||||
|
};
|
||||||
use embassy_sync::{
|
use embassy_sync::{
|
||||||
blocking_mutex::raw::{CriticalSectionRawMutex, ThreadModeRawMutex},
|
blocking_mutex::raw::{CriticalSectionRawMutex, ThreadModeRawMutex},
|
||||||
mutex::Mutex,
|
mutex::Mutex,
|
||||||
|
signal::Signal,
|
||||||
};
|
};
|
||||||
|
use embassy_time::{Delay, Timer};
|
||||||
use embedded_graphics::{
|
use embedded_graphics::{
|
||||||
Drawable,
|
Drawable,
|
||||||
mono_font::{MonoTextStyle, ascii::FONT_9X15},
|
draw_target::DrawTarget,
|
||||||
|
mono_font::{
|
||||||
|
MonoTextStyle,
|
||||||
|
ascii::{FONT_6X9, FONT_6X10, FONT_9X15, FONT_10X20},
|
||||||
|
},
|
||||||
pixelcolor::Rgb565,
|
pixelcolor::Rgb565,
|
||||||
prelude::{Dimensions, Point, RgbColor, Size},
|
prelude::{Dimensions, Point, Primitive, RgbColor, Size},
|
||||||
primitives::Rectangle,
|
primitives::{PrimitiveStyle, Rectangle, StyledDrawable},
|
||||||
text::Text,
|
text::Text,
|
||||||
};
|
};
|
||||||
|
use embedded_hal_async::spi::SpiDevice;
|
||||||
|
use embedded_hal_bus::spi::{ExclusiveDevice, NoDelay};
|
||||||
use embedded_layout::{
|
use embedded_layout::{
|
||||||
align::{horizontal, vertical},
|
align::{horizontal, vertical},
|
||||||
layout::linear::LinearLayout,
|
layout::linear::LinearLayout,
|
||||||
@@ -32,38 +47,51 @@ use shared::keyboard::{KeyCode, KeyState};
|
|||||||
pub static SELECTIONS: Mutex<CriticalSectionRawMutex, SelectionList> =
|
pub static SELECTIONS: Mutex<CriticalSectionRawMutex, SelectionList> =
|
||||||
Mutex::new(SelectionList::new());
|
Mutex::new(SelectionList::new());
|
||||||
|
|
||||||
|
pub async fn run_selected() {
|
||||||
|
info!("Getting selections lock");
|
||||||
|
let selections = SELECTIONS.lock().await;
|
||||||
|
info!("Got selections lock");
|
||||||
|
let selection = selections.selections[selections.current_selection as usize - 1].clone();
|
||||||
|
|
||||||
|
let entry = unsafe { load_binary(&selection.short_name).await.unwrap() };
|
||||||
|
info!("loaded binary");
|
||||||
|
BINARY_CH.send(entry).await;
|
||||||
|
info!("sent bin");
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn ui_handler() {
|
pub async fn ui_handler() {
|
||||||
loop {
|
loop {
|
||||||
if let TaskState::Ui = *TASK_STATE.lock().await {
|
let state = *TASK_STATE.lock().await;
|
||||||
|
if let TaskState::Ui = state {
|
||||||
|
let mut redraw = false;
|
||||||
|
|
||||||
if let Some(event) = keyboard::read_keyboard_fifo().await {
|
if let Some(event) = keyboard::read_keyboard_fifo().await {
|
||||||
if let KeyState::Pressed = event.state {
|
if event.state == KeyState::Pressed {
|
||||||
match event.key {
|
match event.key {
|
||||||
KeyCode::JoyUp => {
|
KeyCode::JoyUp => {
|
||||||
let mut selections = SELECTIONS.lock().await;
|
let mut selections = SELECTIONS.lock().await;
|
||||||
selections.up();
|
selections.up();
|
||||||
|
redraw = true;
|
||||||
}
|
}
|
||||||
KeyCode::JoyDown => {
|
KeyCode::JoyDown => {
|
||||||
let mut selections = SELECTIONS.lock().await;
|
let mut selections = SELECTIONS.lock().await;
|
||||||
selections.down();
|
selections.down();
|
||||||
|
redraw = true;
|
||||||
}
|
}
|
||||||
KeyCode::Enter | KeyCode::JoyRight => {
|
KeyCode::Enter | KeyCode::JoyRight => run_selected().await,
|
||||||
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 {
|
let mut selections = SELECTIONS.lock().await;
|
||||||
embassy_time::Timer::after_millis(50).await;
|
redraw |= selections.take_changed();
|
||||||
|
}
|
||||||
|
|
||||||
|
if redraw {
|
||||||
|
draw_selection().await;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -74,8 +102,9 @@ async fn draw_selection() {
|
|||||||
guard.selections.clone()
|
guard.selections.clone()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let fb = framebuffer_mut();
|
||||||
let text_style = MonoTextStyle::new(&FONT_9X15, Rgb565::WHITE);
|
let text_style = MonoTextStyle::new(&FONT_9X15, Rgb565::WHITE);
|
||||||
let display_area = unsafe { FRAMEBUFFER.bounding_box() };
|
let display_area = fb.bounding_box();
|
||||||
|
|
||||||
const NO_BINS: &str = "No Programs found on SD Card. Ensure programs end with '.bin', and are located in the root directory";
|
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 no_bins = String::from_str(NO_BINS).unwrap();
|
||||||
@@ -89,14 +118,13 @@ async fn draw_selection() {
|
|||||||
),
|
),
|
||||||
text_style,
|
text_style,
|
||||||
)
|
)
|
||||||
.draw(unsafe { &mut FRAMEBUFFER })
|
.draw(fb)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
} else {
|
} else {
|
||||||
let mut file_names = file_names.iter();
|
let mut file_names = file_names.iter();
|
||||||
let Some(first) = file_names.next() else {
|
let Some(first) = file_names.next() else {
|
||||||
Text::new(NO_BINS, Point::zero(), text_style)
|
Text::new("No Programs found on SD Card\nEnsure programs end with '.bin',\nand are located in the root directory",
|
||||||
.draw(unsafe { &mut FRAMEBUFFER })
|
Point::zero(), text_style).draw(fb).unwrap();
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
@@ -115,15 +143,16 @@ async fn draw_selection() {
|
|||||||
.with_alignment(horizontal::Center)
|
.with_alignment(horizontal::Center)
|
||||||
.arrange()
|
.arrange()
|
||||||
.align_to(&display_area, horizontal::Center, vertical::Center)
|
.align_to(&display_area, horizontal::Center, vertical::Center)
|
||||||
.draw(unsafe { &mut FRAMEBUFFER })
|
.draw(fb)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SelectionList {
|
pub struct SelectionList {
|
||||||
current_selection: u16,
|
current_selection: u16,
|
||||||
pub selections: Vec<FileName>,
|
pub selections: Vec<FileName>,
|
||||||
|
has_changed: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SelectionList {
|
impl SelectionList {
|
||||||
@@ -131,6 +160,7 @@ impl SelectionList {
|
|||||||
Self {
|
Self {
|
||||||
selections: Vec::new(),
|
selections: Vec::new(),
|
||||||
current_selection: 0,
|
current_selection: 0,
|
||||||
|
has_changed: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,4 +179,10 @@ impl SelectionList {
|
|||||||
self.current_selection -= 1
|
self.current_selection -= 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn take_changed(&mut self) -> bool {
|
||||||
|
let changed = self.has_changed;
|
||||||
|
self.has_changed = false;
|
||||||
|
changed
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,20 @@
|
|||||||
use crate::{TASK_STATE, TASK_STATE_CHANGED, TaskState, scsi::MassStorageClass};
|
use core::sync::atomic::Ordering;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
scsi::MassStorageClass,
|
||||||
|
storage::{SDCARD, SdCard},
|
||||||
|
};
|
||||||
use embassy_futures::{
|
use embassy_futures::{
|
||||||
join::join,
|
join::join,
|
||||||
select::{select, select3},
|
select::{select, select3},
|
||||||
};
|
};
|
||||||
use embassy_rp::{peripherals::USB, usb::Driver};
|
use embassy_rp::{peripherals::USB, usb::Driver};
|
||||||
|
use embassy_sync::{blocking_mutex::raw::ThreadModeRawMutex, signal::Signal};
|
||||||
use embassy_usb::{Builder, Config};
|
use embassy_usb::{Builder, Config};
|
||||||
|
use portable_atomic::AtomicBool;
|
||||||
|
|
||||||
|
pub static RESTART_USB: Signal<ThreadModeRawMutex, ()> = Signal::new();
|
||||||
|
pub static ENABLE_SCSI: AtomicBool = AtomicBool::new(false);
|
||||||
|
|
||||||
pub async fn usb_handler(driver: Driver<'static, USB>) {
|
pub async fn usb_handler(driver: Driver<'static, USB>) {
|
||||||
let mut config = Config::new(0xc0de, 0xbabe);
|
let mut config = Config::new(0xc0de, 0xbabe);
|
||||||
@@ -27,17 +37,27 @@ pub async fn usb_handler(driver: Driver<'static, USB>) {
|
|||||||
&mut control_buf,
|
&mut control_buf,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut scsi = MassStorageClass::new(&mut builder);
|
let lock = SDCARD.get().lock().await;
|
||||||
|
let sdcard = lock.as_ref().unwrap();
|
||||||
|
|
||||||
|
let mut scsi = MassStorageClass::new(&mut builder, &sdcard);
|
||||||
let mut usb = builder.build();
|
let mut usb = builder.build();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
defmt::info!("in: {}", *TASK_STATE.lock().await as u32);
|
select3(
|
||||||
if *TASK_STATE.lock().await == TaskState::Ui {
|
async {
|
||||||
defmt::info!("running scsi and usb");
|
loop {
|
||||||
select(join(usb.run(), scsi.poll()), TASK_STATE_CHANGED.wait()).await;
|
RESTART_USB.wait().await;
|
||||||
} else {
|
return;
|
||||||
defmt::info!("not in ui state");
|
}
|
||||||
TASK_STATE_CHANGED.wait().await;
|
},
|
||||||
}
|
usb.run(),
|
||||||
|
async {
|
||||||
|
if ENABLE_SCSI.load(Ordering::Acquire) {
|
||||||
|
scsi.poll().await
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
use abi::{KeyCode, display::Display, embassy_time, get_key, print, sleep};
|
use abi::{KeyCode, display::Display, embassy_time, get_key, print};
|
||||||
use alloc::{boxed::Box, string::String, vec};
|
use alloc::{boxed::Box, string::String, vec};
|
||||||
use core::{panic::PanicInfo, pin::Pin};
|
use core::{panic::PanicInfo, pin::Pin};
|
||||||
use embedded_graphics::{
|
use embedded_graphics::{
|
||||||
@@ -10,8 +10,7 @@ use embedded_graphics::{
|
|||||||
geometry::{Dimensions, Point},
|
geometry::{Dimensions, Point},
|
||||||
mono_font::{MonoTextStyle, ascii::FONT_6X10},
|
mono_font::{MonoTextStyle, ascii::FONT_6X10},
|
||||||
pixelcolor::Rgb565,
|
pixelcolor::Rgb565,
|
||||||
prelude::{Primitive, RgbColor, Size},
|
prelude::RgbColor,
|
||||||
primitives::{PrimitiveStyle, Rectangle},
|
|
||||||
text::{Alignment, Text},
|
text::{Alignment, Text},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -26,49 +25,31 @@ pub async fn main() {
|
|||||||
|
|
||||||
let character_style = MonoTextStyle::new(&FONT_6X10, Rgb565::RED);
|
let character_style = MonoTextStyle::new(&FONT_6X10, Rgb565::RED);
|
||||||
|
|
||||||
let mut text = vec!['T', 'y', 'p', 'e'];
|
let mut text = vec!['H', 'E', 'L', 'L', 'O'];
|
||||||
let mut dirty = true;
|
|
||||||
let mut last_bounds: Option<Rectangle> = None;
|
|
||||||
|
|
||||||
loop {
|
// loop {
|
||||||
if dirty {
|
Text::with_alignment(
|
||||||
if let Some(bounds) = last_bounds {
|
&text.iter().cloned().collect::<String>(),
|
||||||
Rectangle::new(bounds.top_left, bounds.size)
|
display.bounding_box().center() + Point::new(0, 15),
|
||||||
.into_styled(PrimitiveStyle::with_fill(Rgb565::BLACK))
|
character_style,
|
||||||
.draw(&mut display)
|
Alignment::Center,
|
||||||
.unwrap();
|
)
|
||||||
|
.draw(&mut display)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
if let Some(event) = get_key() {
|
||||||
|
print("User got event");
|
||||||
|
match event.key {
|
||||||
|
KeyCode::Char(ch) => {
|
||||||
|
text.push(ch);
|
||||||
}
|
}
|
||||||
|
KeyCode::Backspace => {
|
||||||
let text = text.iter().cloned().collect::<String>();
|
text.pop();
|
||||||
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();
|
|
||||||
dirty = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(event) = get_key() {
|
|
||||||
dirty = true;
|
|
||||||
match event.key {
|
|
||||||
KeyCode::Char(ch) => {
|
|
||||||
text.push(ch);
|
|
||||||
}
|
|
||||||
KeyCode::Del => {
|
|
||||||
text.clear();
|
|
||||||
}
|
|
||||||
KeyCode::Backspace => {
|
|
||||||
text.pop();
|
|
||||||
}
|
|
||||||
KeyCode::Esc => return,
|
|
||||||
_ => (),
|
|
||||||
}
|
}
|
||||||
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
|
|||||||
Reference in New Issue
Block a user