commit f9f6808d65eb50782a644b7cc2e87a0552118bbc Author: Sebastian Date: Tue Sep 27 21:36:29 2022 +0200 First somewhat working version diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..1e16cfb --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,29 @@ +[target.'cfg(all(target_arch = "arm", target_os = "none"))'] +# Choose a default "cargo run" tool: +# - probe-run provides flashing and defmt via a hardware debugger +# - cargo embed offers flashing, rtt, defmt and a gdb server via a hardware debugger +# it is configured via the Embed.toml in the root of this project +# - elf2uf2-rs loads firmware over USB when the rp2040 is in boot mode +# runner = "probe-run --chip RP2040" +# runner = "cargo embed" +runner = "elf2uf2-rs -d" + +rustflags = [ + "-C", "linker=flip-link", + "-C", "link-arg=--nmagic", + "-C", "link-arg=-Tlink.x", + "-C", "link-arg=-Tdefmt.x", + + # Code-size optimizations. + # trap unreachable can save a lot of space, but requires nightly compiler. + # uncomment the next line if you wish to enable it + # "-Z", "trap-unreachable=no", + "-C", "inline-threshold=5", + "-C", "no-vectorize-loops", +] + +[build] +target = "thumbv6m-none-eabi" + +[env] +DEFMT_LOG = "debug" diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3a0e903 --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +**/*.rs.bk +.#* +.gdb_history +Cargo.lock +target/ + +# editor files +.vscode/* +!.vscode/*.md +!.vscode/*.svd +!.vscode/launch.json +!.vscode/tasks.json +!.vscode/extensions.json +!.vscode/settings.json \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..a3358ab --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,75 @@ +[package] +edition = "2021" +name = "pico-flipdot" +version = "0.1.0" + +[dependencies] +cortex-m = "0.7" +cortex-m-rt = "0.7" +embedded-hal = { version = "0.2.5", features = ["unproven"] } + +defmt = "0.3" +defmt-rtt = "0.3" +panic-probe = { version = "0.3", features = ["print-defmt"] } + +# We're using a Pico by default on this template +rp-pico = "0.5" + +# but you can use any BSP. Uncomment this to use the pro_micro_rp2040 BSP instead +# sparkfun-pro-micro-rp2040 = "0.3" + +# If you're not going to use a Board Support Package you'll need these: +# rp2040-hal = { version="0.6", features=["rt"] } +# rp2040-boot2 = "0.2" + +# cargo build/run +[profile.dev] +codegen-units = 1 +debug = 2 +debug-assertions = true +incremental = false +opt-level = 3 +overflow-checks = true + +# cargo build/run --release +[profile.release] +codegen-units = 1 +debug = 2 +debug-assertions = false +incremental = false +lto = 'fat' +opt-level = 3 +overflow-checks = false + +# do not optimize proc-macro crates = faster builds from scratch +[profile.dev.build-override] +codegen-units = 8 +debug = false +debug-assertions = false +opt-level = 0 +overflow-checks = false + +[profile.release.build-override] +codegen-units = 8 +debug = false +debug-assertions = false +opt-level = 0 +overflow-checks = false + +# cargo test +[profile.test] +codegen-units = 1 +debug = 2 +debug-assertions = true +incremental = false +opt-level = 3 +overflow-checks = true + +# cargo test --release +[profile.bench] +codegen-units = 1 +debug = 2 +debug-assertions = false +incremental = false +lto = 'fat' +opt-level = 3 diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..d534cc3 --- /dev/null +++ b/build.rs @@ -0,0 +1,31 @@ +//! This build script copies the `memory.x` file from the crate root into +//! a directory where the linker can always find it at build time. +//! For many projects this is optional, as the linker always searches the +//! project root directory -- wherever `Cargo.toml` is. However, if you +//! are using a workspace or have a more complicated build setup, this +//! build script becomes required. Additionally, by requesting that +//! Cargo re-run the build script whenever `memory.x` is changed, +//! updating `memory.x` ensures a rebuild of the application with the +//! new memory settings. + +use std::env; +use std::fs::File; +use std::io::Write; +use std::path::PathBuf; + +fn main() { + // Put `memory.x` in our output directory and ensure it's + // on the linker search path. + let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); + File::create(out.join("memory.x")) + .unwrap() + .write_all(include_bytes!("memory.x")) + .unwrap(); + println!("cargo:rustc-link-search={}", out.display()); + + // By default, Cargo will re-run a build script whenever + // any file in the project changes. By specifying `memory.x` + // here, we ensure the build script is only re-run when + // `memory.x` is changed. + println!("cargo:rerun-if-changed=memory.x"); +} diff --git a/memory.x b/memory.x new file mode 100644 index 0000000..070eac7 --- /dev/null +++ b/memory.x @@ -0,0 +1,15 @@ +MEMORY { + BOOT2 : ORIGIN = 0x10000000, LENGTH = 0x100 + FLASH : ORIGIN = 0x10000100, LENGTH = 2048K - 0x100 + RAM : ORIGIN = 0x20000000, LENGTH = 256K +} + +EXTERN(BOOT2_FIRMWARE) + +SECTIONS { + /* ### Boot loader */ + .boot2 ORIGIN(BOOT2) : + { + KEEP(*(.boot2)); + } > BOOT2 +} INSERT BEFORE .text; \ No newline at end of file diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..78a1a7a --- /dev/null +++ b/src/main.rs @@ -0,0 +1,153 @@ +//! Blinks the LED on a Pico board +//! +//! This will blink an LED attached to GP25, which is the pin the Pico uses for the on-board LED. +#![no_std] +#![no_main] + +use bsp::entry; +use defmt::*; +use defmt_rtt as _; +use embedded_hal::digital::v2::OutputPin; +use panic_probe as _; + +// Provide an alias for our BSP so we can switch targets quickly. +// Uncomment the BSP you included in Cargo.toml, the rest of the code does not need to change. +use rp_pico as bsp; +// use sparkfun_pro_micro_rp2040 as bsp; + +use bsp::hal::{ + clocks::{init_clocks_and_plls, Clock}, + pac, + sio::Sio, + watchdog::Watchdog, +}; + +fn toggle_clock(clock_pin: &mut PIN, delay: &mut cortex_m::delay::Delay) +where + PIN: OutputPin, +{ + clock_pin.set_high(); + delay.delay_ms(1); + clock_pin.set_low(); + delay.delay_ms(1); +} + +fn shift_out_bits( + data: u32, + len: u8, + clock_pin: &mut CLK_PIN, + data_pin: &mut DATA_PIN, + delay: &mut cortex_m::delay::Delay, +) where + CLK_PIN: OutputPin, + DATA_PIN: OutputPin, +{ + for i in 0..len { + if data & (1 << (len - i - 1) as u32) != 0 { + data_pin.set_high(); + } else { + data_pin.set_low(); + } + toggle_clock(clock_pin, delay); + } +} + +#[entry] +fn main() -> ! { + info!("Program start"); + 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); + + // External high-speed crystal on the pico board is 12Mhz + 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().to_Hz()); + + let pins = bsp::Pins::new( + pac.IO_BANK0, + pac.PADS_BANK0, + sio.gpio_bank0, + &mut pac.RESETS, + ); + + let mut led_pin = pins.led.into_push_pull_output(); + + let mut row_data_pin = pins.gpio2.into_push_pull_output(); + let mut row_clock_pin = pins.gpio3.into_push_pull_output(); + + let mut col_data_pin = pins.gpio4.into_push_pull_output(); + let mut col_clock_pin = pins.gpio5.into_push_pull_output(); + + let mut white_pin = pins.gpio6.into_push_pull_output(); + let mut black_pin = pins.gpio7.into_push_pull_output(); + let mut strobe_pin = pins.gpio8.into_push_pull_output(); + + loop { + for x in 0..24 { + for y in 0..16 { + shift_out_bits( + 1 << y, + 16, + &mut row_clock_pin, + &mut row_data_pin, + &mut delay, + ); + + shift_out_bits( + 1 << x, + 24, + &mut col_clock_pin, + &mut col_data_pin, + &mut delay, + ); + + black_pin.set_high(); + strobe_pin.set_high(); + delay.delay_ms(20); + strobe_pin.set_low(); + black_pin.set_low(); + + delay.delay_ms(10); + } + } + + led_pin.set_high().unwrap(); + + for y in 0..24 { + shift_out_bits(0, 16, &mut row_clock_pin, &mut row_data_pin, &mut delay); + + shift_out_bits( + 1 << y, + 24, + &mut col_clock_pin, + &mut col_data_pin, + &mut delay, + ); + + white_pin.set_high(); + strobe_pin.set_high(); + delay.delay_ms(20); + strobe_pin.set_low(); + white_pin.set_low(); + + delay.delay_ms(10); + } + + led_pin.set_low().unwrap(); + } +} + +// End of file