Skip to content

Commit

Permalink
Add rp-pico example
Browse files Browse the repository at this point in the history
  • Loading branch information
9names committed Apr 8, 2024
1 parent 7122188 commit 5aca3e9
Show file tree
Hide file tree
Showing 8 changed files with 264 additions and 0 deletions.
15 changes: 15 additions & 0 deletions examples/rp2040-hal-blocking/.cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
runner = "probe-rs run --chip RP2040 --protocol swd"
# runner = "elf2uf2-rs -d"

rustflags = [
"-C", "link-arg=--nmagic",
"-C", "link-arg=-Tlink.x",
"-C", "link-arg=-Tdefmt.x",
]

[build]
target = "thumbv6m-none-eabi"

[env]
DEFMT_LOG = "debug"
14 changes: 14 additions & 0 deletions examples/rp2040-hal-blocking/.gitignore
Original file line number Diff line number Diff line change
@@ -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
8 changes: 8 additions & 0 deletions examples/rp2040-hal-blocking/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"rust-analyzer.cargo.target": "thumbv6m-none-eabi",
"rust-analyzer.checkOnSave.allTargets": false,
"editor.formatOnSave": true,
"[toml]": {
"editor.formatOnSave": false,
}
}
25 changes: 25 additions & 0 deletions examples/rp2040-hal-blocking/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
[package]
authors = ["9names"]
edition = "2018"
readme = "README.md"
name = "wii-ext_blocking_demo"
version = "0.1.0"
resolver = "2"
publish = false

[dependencies]
cortex-m = "0.7.3"
cortex-m-rt = "0.7.0"
embedded-hal = { version = "0.2.7", features = ["unproven"] }
embedded-time = "0.12.0"
defmt = "0.3.0"
defmt-rtt = "0.4.0"
panic-probe = { version = "0.3.0", features = ["print-defmt"] }
fugit = "0.3.6"
usb-device = "0.2"
usbd-human-interface-device = "0.4.5"
wii-ext = { version = "0.3.0", features = ["defmt_print",], path = "../../wii-ext" }
rp-pico = "0.8.0"

[profile.release]
debug = 2
4 changes: 4 additions & 0 deletions examples/rp2040-hal-blocking/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Example project for wii-ext using Raspberry Pi Pico

Just a simple example of how to use wii-ext-rs.
Grab a pico, wire up a classic controller or nunchuk and test it out!
31 changes: 31 additions & 0 deletions examples/rp2040-hal-blocking/build.rs
Original file line number Diff line number Diff line change
@@ -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");
}
15 changes: 15 additions & 0 deletions examples/rp2040-hal-blocking/memory.x
Original file line number Diff line number Diff line change
@@ -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;
152 changes: 152 additions & 0 deletions examples/rp2040-hal-blocking/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
//! Interact with a Wii extension controller via the wii-ext crate on a Pico board
//!
//! It will enumerate as a USB joystick, which you can use to control a game
#![no_std]
#![no_main]

use defmt::*;
use defmt_rtt as _;
use panic_probe as _;

use rp_pico as bsp;
use bsp::hal::{
self,
entry,
clocks::{init_clocks_and_plls, Clock},
gpio::FunctionI2C,
pac,
sio::Sio,
watchdog::Watchdog,
};
use fugit::RateExtU32;
use wii_ext::{classic_sync::Classic, core::classic::ClassicReadingCalibrated};

use usb_device::class_prelude::*;
use usb_device::prelude::*;
use usbd_human_interface_device::device::joystick::JoystickReport;
use usbd_human_interface_device::prelude::*;

#[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 usb_bus = UsbBusAllocator::new(hal::usb::UsbBus::new(
pac.USBCTRL_REGS,
pac.USBCTRL_DPRAM,
clocks.usb_clock,
true,
&mut pac.RESETS,
));

let mut joy = UsbHidClassBuilder::new()
.add_device(usbd_human_interface_device::device::joystick::JoystickConfig::default())
.build(&usb_bus);

//https://pid.codes
let mut usb_dev = UsbDeviceBuilder::new(&usb_bus, UsbVidPid(0x1209, 0x0001))
.manufacturer("usbd-human-interface-device")
.product("Rusty joystick")
.serial_number("TEST")
.build();

let sda_pin = pins.gpio8.into_function::<FunctionI2C>();
let scl_pin = pins.gpio9.into_function::<FunctionI2C>();

let i2c = bsp::hal::I2C::i2c0(
pac.I2C0,
sda_pin,
scl_pin,
100.kHz(),
&mut pac.RESETS,
&clocks.peripheral_clock,
);

// Create, initialise and calibrate the controller
let mut controller = Classic::new(i2c, &mut delay).unwrap();

let hi_res = false;

// Enable hi-resolution mode. This also updates calibration
// Don't really need it for this single stick mode. Plus it might make recovery easier...
if hi_res {
controller.enable_hires(&mut delay).unwrap();
}

// If you have a Nunchuk controller, use this instead.
// let mut controller = Nunchuk::new(i2c, &mut delay).unwrap();
loop {
// Some controllers need a delay between reads or they become unhappy
// delay.delay_ms(10);

// Capture the current button and axis values
let input = controller.read_blocking(&mut delay);
if let Ok(input) = input {
match joy.device().write_report(&get_report(&input)) {
Err(UsbHidError::WouldBlock) => {}
Ok(_) => {}
Err(e) => {
core::panic!("Failed to write joystick report: {:?}", e)
}
}
// Print inputs from the controller
debug!("{:?}", input);
} else {
// re-init controller on failure
let _ = controller.init(&mut delay);
if hi_res {
let _ = controller.enable_hires(&mut delay);
}
}

if usb_dev.poll(&mut [&mut joy]) {}
}
}

fn get_report(input: &ClassicReadingCalibrated) -> JoystickReport {
// Read out buttons first
let mut buttons = 0;

buttons += input.button_b as u8;
buttons += (input.button_a as u8) << 1;
buttons += (input.button_y as u8) << 2;
buttons += (input.button_x as u8) << 3;
buttons += (input.button_trigger_l as u8) << 4;
buttons += (input.button_trigger_r as u8) << 5;
buttons += (input.button_minus as u8) << 6;
buttons += (input.button_plus as u8) << 7;

JoystickReport {
buttons,
x: input.joystick_left_x,
y: -input.joystick_left_y,
}
}

// End of file

0 comments on commit 5aca3e9

Please sign in to comment.