commit 1701f95fa3180a2559ad2e7e668efe253f18bac2 Author: kirbylife Date: Mon Oct 11 15:19:54 2021 -0500 Initial commit diff --git a/.cargo/config b/.cargo/config new file mode 100644 index 0000000..4faea99 --- /dev/null +++ b/.cargo/config @@ -0,0 +1,13 @@ +[target.'cfg(all(target_arch = "arm", target_os = "none"))'] + +rustflags = [ + "-C", "linker=flip-link", + "-C", "link-arg=--nmagic", + "-C", "link-arg=-Tlink.x", + + "-C", "inline-threshold=5", + "-C", "no-vectorize-loops", +] + +[build] +target = "thumbv6m-none-eabi" \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ada8be9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +# Generated by Cargo +# will have compiled files and executables +debug/ +target/ + +# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries +# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html +Cargo.lock + +# These are backup files generated by rustfmt +**/*.rs.bk + +# MSVC Windows builds of rustc generate these, which store debugging information +*.pdb \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..99469b5 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,33 @@ +[package] +name = "waveshare_rust_rp2040" +version = "0.1.0" +authors = ["kirbylife "] +edition = "2018" +resolver = "2" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +cortex-m = "0.7.3" +cortex-m-rt = "0.7.0" +embedded-hal = { version = "0.2.5", features=["unproven"] } +embedded-time = "0.12.0" +embedded-graphics = "0.6.1" + +panic-probe = { version = "0.2.0" } + +rp2040-hal = { git = "https://github.com/rp-rs/rp-hal", branch="main", features=["rt"] } +rp2040-boot2 = { git = "https://github.com/rp-rs/rp2040-boot2-rs", branch="main" } + +epd-waveshare = "0.4.0" +tinytga = { version = "0.3.2", features = [ "graphics" ] } + +# cargo build/run --release +[profile.release] +codegen-units = 1 +debug = 2 +debug-assertions = false +incremental = false +lto = 'fat' +opt-level = 3 +overflow-checks = false diff --git a/RustMX.tga b/RustMX.tga new file mode 100644 index 0000000..dd09db0 Binary files /dev/null and b/RustMX.tga differ diff --git a/binary.uf2 b/binary.uf2 new file mode 100644 index 0000000..cb67047 Binary files /dev/null and b/binary.uf2 differ diff --git a/memory.x b/memory.x new file mode 100644 index 0000000..46aab3a --- /dev/null +++ b/memory.x @@ -0,0 +1,14 @@ + +MEMORY { +BOOT2 : ORIGIN = 0x10000000, LENGTH = 0x100 +FLASH : ORIGIN = 0x10000100, LENGTH = 2048K - 0x100 +RAM : ORIGIN = 0x20000000, LENGTH = 256K +} + +SECTIONS { +/* ### Boot loader */ +.boot2 ORIGIN(BOOT2) : +{ +KEEP(*(.boot2)); +} > BOOT2 +} INSERT BEFORE .text; diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..ba5f8e5 --- /dev/null +++ b/readme.md @@ -0,0 +1,30 @@ +# Waveshare-Rust-RP2040 +### This is a template to use a waveshare e-ink screen with the rp-pico board andrp-pico HAT using Rust. + +## Prepare your system +- Install the toolchain + - `rustup target install thumbv6m-none-eabi` +- Install the linker (with [flip-link](https://github.com/knurling-rs/flip-link) you will have zero-cost stack overflow) + - `cargo install flip-link` +- Install elf2uf2-rs + - `cargo install elf2uf2-rs` +- Install the pico-sdk + - (search on the Internet, it's really boring and I don't remember how to do it lol) +- Install the gcc-arm corresponding to the board + - (The same as with pico-sdk... sorry) + +## Usage +1. Clone the repo + - `git clone https://gitlab.com/kirbylife/waveshare-rust-rp2040` +2. Build with --release + - `cargo build --release` +3. Convert to uf2 + - elf2uf2-rs target/thumbv6m-none-eabi/release/waveshare_rust_rp2040 binary.uf2 +4. Connect your rp-pico to the PC with in BOOTSEL mode +5. Grab your file `binary.uf2` and drop it inside of the RPI-RP2 volume +6. Enjoy :) (apply restrictions) + +## License +This template does not have any license but the [RustMX](https://t.me/RustMX) can have it. + +written in Rust the ran originally in the Raspberry Pi Pico with a Waveshare 7.5 inch e-ink screen. diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..bb8c716 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,162 @@ +#![no_std] +#![no_main] + +use cortex_m_rt::entry; +use embedded_graphics::{ + fonts::{Font24x32 as Font, Text}, + image::Image, + pixelcolor::BinaryColor, + prelude::*, + primitives::{Circle, Line, Triangle}, + style::{PrimitiveStyle, PrimitiveStyleBuilder, TextStyleBuilder}, +}; +use embedded_hal::digital::v2::OutputPin; +use embedded_time::fixed_point::FixedPoint; +use embedded_time::rate::Extensions; +use epd_waveshare::{ + color::*, epd7in5_v2::Display7in5 as EPDisplay, epd7in5_v2::EPD7in5 as EPD, epd7in5_v2::HEIGHT, + epd7in5_v2::WIDTH, graphics::DisplayRotation, prelude::*, +}; +use panic_probe as _; +use rp2040_hal as hal; +use tinytga::Tga; + +use hal::{ + clocks::{init_clocks_and_plls, Clock}, + pac, + sio::Sio, + watchdog::Watchdog, +}; + +// IMPORTANT!! first of all, you need to load the BOOT2 binary (rp-rs courtesy) +#[link_section = ".boot2"] +#[used] +pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER_W25Q080; + +#[entry] +fn main() -> ! { + // Start all the peripherals + let mut pac = pac::Peripherals::take().unwrap(); + let core = pac::CorePeripherals::take().unwrap(); + let mut watchdog = Watchdog::new(pac.WATCHDOG); + let sio = Sio::new(pac.SIO); + + let external_xtal_freq_hz = 12_000_000u32; + let clocks = init_clocks_and_plls( + external_xtal_freq_hz, + pac.XOSC, + pac.CLOCKS, + pac.PLL_SYS, + pac.PLL_USB, + &mut pac.RESETS, + &mut watchdog, + ) + .ok() + .unwrap(); + + let mut delay = cortex_m::delay::Delay::new(core.SYST, clocks.system_clock.freq().integer()); + + let pins = hal::gpio::Pins::new( + pac.IO_BANK0, + pac.PADS_BANK0, + sio.gpio_bank0, + &mut pac.RESETS, + ); + // End of Start the peripherals + + // SPI declaration + let _spi_sclk = pins.gpio10.into_mode::(); + let _spi_mosi = pins.gpio11.into_mode::(); + let spi = hal::spi::Spi::<_, _, 8>::new(pac.SPI1); + + let mut spi = spi.init( + &mut pac.RESETS, + clocks.peripheral_clock.freq(), + // you can put cookie (increase the speed) in it but I don't recommend it. + 4_000_000u32.Hz(), + &embedded_hal::spi::MODE_0, + ); + // End of SPI declaration + + // Start the rest of pins needed to communicate with the screen + let mut cs = pins.gpio9.into_push_pull_output(); // CS + cs.set_high().unwrap(); + let busy = pins.gpio13.into_pull_up_input(); // BUSY + let dc = pins.gpio8.into_push_pull_output(); // DC + let rst = pins.gpio12.into_push_pull_output(); // RST + + // Start the EPD struct + let mut epd = EPD::new( + &mut spi, // SPI + cs, // CS + busy, // BUSY + dc, // DC + rst, // RST + &mut delay, // DELAY + ) + .unwrap(); + // Start the display buffer + let mut display = EPDisplay::default(); + + epd.wake_up(&mut spi, &mut delay).unwrap(); + // epd.set_background_color(epd_waveshare::color::Color::Black); + // epd.clear_frame(&mut spi).unwrap(); + // epd.set_background_color(epd_waveshare::color::Color::White); + epd.clear_frame(&mut spi).unwrap(); + + display.clear_buffer(Color::Black); + + // Start the fun + let style_text = TextStyleBuilder::new(Font) + .text_color(BinaryColor::Off) + .background_color(BinaryColor::On) + .build(); + let style_forms = PrimitiveStyleBuilder::new() + .stroke_width(10) + .stroke_color(BinaryColor::Off) + .fill_color(BinaryColor::Off) + .build(); + + for i in 0..(WIDTH / 10) as i32 { + Line::new(Point::new(i * 10, 0), Point::new(i * 10, HEIGHT as i32)) + .into_styled(PrimitiveStyle::with_stroke(BinaryColor::Off, 1)) + .draw(&mut display) + .unwrap(); + } + for i in 0..(HEIGHT / 10) as i32 { + Line::new(Point::new(0, i * 10), Point::new(WIDTH as i32, i * 10)) + .into_styled(PrimitiveStyle::with_stroke(BinaryColor::Off, 1)) + .draw(&mut display) + .unwrap(); + } + + display.set_rotation(DisplayRotation::Rotate270); + + let tga = Tga::from_slice(include_bytes!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/RustMX.tga" + ))) + .unwrap(); + + let image: Image = Image::new(&tga, Point::new(50, 100)); + image.draw(&mut display).unwrap(); + + Text::new("RustMX", Point::new(50, 50)) + .into_styled(style_text) + .draw(&mut display) + .unwrap(); + + epd.update_frame(&mut spi, display.buffer()).unwrap(); + epd.display_frame(&mut spi).unwrap(); + delay.delay_ms(1000); + + let mut led_pin = pins.gpio25.into_push_pull_output(); + + // If the led blink, everything it's ok (big debug skills) + loop { + led_pin.set_high().unwrap(); + delay.delay_ms(500); + led_pin.set_low().unwrap(); + delay.delay_ms(500); + } +}