From 0b1118937f3281af93507496c4bb0c97016d5709 Mon Sep 17 00:00:00 2001 From: D4VID Date: Sat, 21 Jun 2025 17:13:19 +0200 Subject: [PATCH] Play a song Bad Apple ofc --- bad-apple/.cargo/config.toml | 8 +++ bad-apple/.gitignore | 3 + bad-apple/.vscode/settings.json | 5 ++ bad-apple/Cargo.lock | 121 ++++++++++++++++++++++++++++++++ bad-apple/Cargo.toml | 20 ++++++ bad-apple/Makefile | 20 ++++++ bad-apple/build.rs | 14 ++++ bad-apple/media/bad-apple.bin | Bin 0 -> 14336 bytes bad-apple/memory.x | 14 ++++ bad-apple/src/main.rs | 47 +++++++++++++ lwcpu/src/lib.rs | 26 +++++++ 11 files changed, 278 insertions(+) create mode 100644 bad-apple/.cargo/config.toml create mode 100644 bad-apple/.gitignore create mode 100644 bad-apple/.vscode/settings.json create mode 100644 bad-apple/Cargo.lock create mode 100644 bad-apple/Cargo.toml create mode 100644 bad-apple/Makefile create mode 100644 bad-apple/build.rs create mode 100644 bad-apple/media/bad-apple.bin create mode 100644 bad-apple/memory.x create mode 100644 bad-apple/src/main.rs diff --git a/bad-apple/.cargo/config.toml b/bad-apple/.cargo/config.toml new file mode 100644 index 0000000..6dfb735 --- /dev/null +++ b/bad-apple/.cargo/config.toml @@ -0,0 +1,8 @@ +[build] +target = "riscv32i-unknown-none-elf" + +[target.riscv32i-unknown-none-elf] +rustflags = [ + "-C", "link-arg=-Tmemory.x", + "-C", "link-arg=-Tlink.x", +] diff --git a/bad-apple/.gitignore b/bad-apple/.gitignore new file mode 100644 index 0000000..5ad8f69 --- /dev/null +++ b/bad-apple/.gitignore @@ -0,0 +1,3 @@ +/target +text.bin +rodata.bin diff --git a/bad-apple/.vscode/settings.json b/bad-apple/.vscode/settings.json new file mode 100644 index 0000000..1f30ed8 --- /dev/null +++ b/bad-apple/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "rust-analyzer.check.allTargets": false, + "rust-analyzer.cargo.allTargets": false, + "rust-analyzer.cargo.target": "riscv32i-unknown-none-elf" +} diff --git a/bad-apple/Cargo.lock b/bad-apple/Cargo.lock new file mode 100644 index 0000000..c948292 --- /dev/null +++ b/bad-apple/Cargo.lock @@ -0,0 +1,121 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "bad-apple" +version = "0.1.0" +dependencies = [ + "lwcpu", + "riscv", + "riscv-rt", +] + +[[package]] +name = "critical-section" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" + +[[package]] +name = "embedded-hal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" + +[[package]] +name = "lwcpu" +version = "0.1.0" + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "proc-macro2" +version = "1.0.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "riscv" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ea8ff73d3720bdd0a97925f0bf79ad2744b6da8ff36be3840c48ac81191d7a7" +dependencies = [ + "critical-section", + "embedded-hal", + "paste", + "riscv-macros", + "riscv-pac", +] + +[[package]] +name = "riscv-macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f265be5d634272320a7de94cea15c22a3bfdd4eb42eb43edc528415f066a1f25" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "riscv-pac" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8188909339ccc0c68cfb5a04648313f09621e8b87dc03095454f1a11f6c5d436" + +[[package]] +name = "riscv-rt" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "753f1bd7eb4e0003cec5e2fb60ea8e253a71d0b041bc7d1ba0fffe22e3c0294d" +dependencies = [ + "riscv", + "riscv-pac", + "riscv-rt-macros", +] + +[[package]] +name = "riscv-rt-macros" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30f19a85fe107b65031e0ba8ec60c34c2494069fe910d6c297f5e7cb5a6f76d0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "syn" +version = "2.0.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c786062daee0d6db1132800e623df74274a0a87322d8e183338e01b3d98d058" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" diff --git a/bad-apple/Cargo.toml b/bad-apple/Cargo.toml new file mode 100644 index 0000000..1e9b0b9 --- /dev/null +++ b/bad-apple/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "bad-apple" +version = "0.1.0" +edition = "2021" + +[dependencies] +riscv = "0.12.1" +riscv-rt = { version = "0.13.0", features=["single-hart"] } +lwcpu = { path = "../lwcpu" } + +# https://docs.rust-embedded.org/book/unsorted/speed-vs-size.html +[profile.release] +# symbols are nice and they don't increase the size on Flash +debug = true +codegen-units = 1 +opt-level = "z" + +[profile.dev.package."*"] +codegen-units = 1 +opt-level = "z" diff --git a/bad-apple/Makefile b/bad-apple/Makefile new file mode 100644 index 0000000..ece420d --- /dev/null +++ b/bad-apple/Makefile @@ -0,0 +1,20 @@ +NAME=bad-apple + +default: extract + +build: + cargo build --release + +extract: build + riscv32-elf-objcopy -O binary --only-section=.text "target/riscv32i-unknown-none-elf/release/${NAME}" /tmp/text.bin + riscv32-elf-objcopy -O binary --only-section=.rodata "target/riscv32i-unknown-none-elf/release/${NAME}" /tmp/rodata.bin + +size: extract + cargo size --release -- -A + +disassemble: extract + riscv32-elf-objdump -Cd "target/riscv32i-unknown-none-elf/release/${NAME}" | less + +clean: + cargo clean + rm /tmp/text.bin /tmp/rodata.bin diff --git a/bad-apple/build.rs b/bad-apple/build.rs new file mode 100644 index 0000000..c941735 --- /dev/null +++ b/bad-apple/build.rs @@ -0,0 +1,14 @@ +// build.rs +use std::env; +use std::fs; +use std::path::PathBuf; + +fn main() { + let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); + + // Put the linker script somewhere the linker can find it. + fs::write(out_dir.join("memory.x"), include_bytes!("memory.x")).unwrap(); + println!("cargo:rustc-link-search={}", out_dir.display()); + println!("cargo:rerun-if-changed=memory.x"); + println!("cargo:rerun-if-changed=build.rs"); +} diff --git a/bad-apple/media/bad-apple.bin b/bad-apple/media/bad-apple.bin new file mode 100644 index 0000000000000000000000000000000000000000..69430eddbdcecdc661b194059f5e4356157e61ea GIT binary patch literal 14336 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 Pj$Ajz)3KGY`xgH<>eA39 literal 0 HcmV?d00001 diff --git a/bad-apple/memory.x b/bad-apple/memory.x new file mode 100644 index 0000000..1c24f2c --- /dev/null +++ b/bad-apple/memory.x @@ -0,0 +1,14 @@ +MEMORY +{ + INST : ORIGIN = 0x00000000, LENGTH = 256K + IO : ORIGIN = 0x10000000, LENGTH = 1K + CONST : ORIGIN = 0x20000000, LENGTH = 16K + RAM : ORIGIN = 0x40000000, LENGTH = 16K +} + +REGION_ALIAS("REGION_TEXT", INST); +REGION_ALIAS("REGION_RODATA", CONST); +REGION_ALIAS("REGION_DATA", RAM); +REGION_ALIAS("REGION_BSS", RAM); +REGION_ALIAS("REGION_HEAP", RAM); +REGION_ALIAS("REGION_STACK", RAM); diff --git a/bad-apple/src/main.rs b/bad-apple/src/main.rs new file mode 100644 index 0000000..8a642ea --- /dev/null +++ b/bad-apple/src/main.rs @@ -0,0 +1,47 @@ +#![no_std] +#![no_main] + +use core::fmt::Write; +use core::panic::PanicInfo; +use lwcpu::{Audio, CharDisplay, NumberDisplay, Screen, ScreenMode}; +use riscv_rt::entry; + +#[panic_handler] +fn panic_handler(_info: &PanicInfo) -> ! { + NumberDisplay::display_number(0xDEADC0DE); + let mut text = CharDisplay {}; + let _ = write!(text, "Panic: {}", _info.message()); + loop {} +} + +const DATA_RAW: &[u8] = include_bytes!("../media/bad-apple.bin"); +const LEN: usize = DATA_RAW.len() / 4; +const DATA: [u32; LEN] = to_u32_array(DATA_RAW); + +const fn to_u32_array(bytes: &[u8]) -> [u32; LEN] { + let mut result = [0u32; LEN]; + let mut i = 0; + while i < LEN { + let idx = i * 4; + result[i] = u32::from_le_bytes([ + bytes[idx + 0], + bytes[idx + 1], + bytes[idx + 2], + bytes[idx + 3], + ]); + i += 1; + } + return result; +} + +#[entry] +fn main() -> ! { + NumberDisplay::display_number(0); + Screen::init(ScreenMode::Buffered); + for index in (0..LEN).step_by(2) { + Audio::play_upper(DATA[index]); + Audio::play_lower(DATA[index + 1]); + } + Audio::stop(); + loop {} +} diff --git a/lwcpu/src/lib.rs b/lwcpu/src/lib.rs index 49bdacf..9a97b27 100644 --- a/lwcpu/src/lib.rs +++ b/lwcpu/src/lib.rs @@ -11,6 +11,7 @@ pub const KEYBOARD_OFFSET : u32 = 0x10; pub const CHAR_CONTROL_OFFSET : u32 = 0x20; pub const SCREEN_CONTROL_OFFSET : u32 = 0x22; pub const CHAR_DISPLAY_OFFSET : u32 = 0x24; +pub const AUDIO_MAIN_OFFSET : u32 = 0x30; pub const SCREEN_OFFSET : u32 = 0x80; pub const NUMBER_DISPLAY_POINTER : *mut u32 = (BASE_POINTER + NUMBER_DISPLAY_OFFSET) as *mut u32; @@ -20,6 +21,7 @@ pub const CHAR_DISPLAY_POINTER : *mut u8 = (BASE_POINTER + CHAR_DISPLAY_OFFSE pub const KEYBOARD_POINTER : *mut u32 = (BASE_POINTER + KEYBOARD_OFFSET) as *mut u32; pub const SCREEN_CONTROL_POINTER : *mut u16 = (BASE_POINTER + SCREEN_CONTROL_OFFSET) as *mut u16; pub const CHAR_CONTROL_POINTER : *mut u16 = (BASE_POINTER + CHAR_CONTROL_OFFSET) as *mut u16; +pub const AUDIO_MAIN_POINTER : *mut u32 = (BASE_POINTER + AUDIO_MAIN_OFFSET) as *mut u32; pub const SCREEN_POINTER : *mut u32 = (BASE_POINTER + SCREEN_OFFSET) as *mut u32; @@ -181,3 +183,27 @@ impl Buttons { return unsafe { read_volatile(BUTTONS_POINTER.byte_offset(3)) }; } } + +pub struct Audio {} +impl Audio { + #[inline] + pub fn play_upper(notes: u32) { + unsafe { + write_volatile(AUDIO_MAIN_POINTER, notes); + } + } + #[inline] + pub fn play_lower(notes: u32) { + unsafe { + write_volatile(AUDIO_MAIN_POINTER.offset(1), notes); + } + } + #[inline] + pub fn stop() { + unsafe { + write_volatile(AUDIO_MAIN_POINTER.offset(0), 0); + write_volatile(AUDIO_MAIN_POINTER.offset(1), 0); + } + } + +}