working flash and gc controller
This commit is contained in:
parent
33234c6257
commit
6c7202bed2
5 changed files with 109 additions and 53 deletions
10
Cargo.lock
generated
10
Cargo.lock
generated
|
@ -269,6 +269,7 @@ dependencies = [
|
|||
"panic-halt",
|
||||
"panic-probe",
|
||||
"rp2040-boot2",
|
||||
"rp2040-flash",
|
||||
"rp2040-hal",
|
||||
"usb-device",
|
||||
"usbd-human-interface-device",
|
||||
|
@ -451,6 +452,15 @@ dependencies = [
|
|||
"crc-any",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rp2040-flash"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2007f9701924b88cbffc172cdf09e01b9c03ecd0b2f59bc6eea5283982855438"
|
||||
dependencies = [
|
||||
"rp2040-hal",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rp2040-hal"
|
||||
version = "0.9.2"
|
||||
|
|
|
@ -7,6 +7,7 @@ edition = "2021"
|
|||
|
||||
[dependencies]
|
||||
rp2040-hal = { version = "0.9.2", features = ["rt", "critical-section-impl"] }
|
||||
rp2040-flash = "0.4.0"
|
||||
usbd-human-interface-device = { version = "0.4.5", features = ["defmt"] }
|
||||
usb-device = "0.2"
|
||||
cortex-m = "0.7.7"
|
||||
|
|
36
src/flash_mem.rs
Normal file
36
src/flash_mem.rs
Normal file
|
@ -0,0 +1,36 @@
|
|||
use core::slice::from_raw_parts;
|
||||
|
||||
use defmt::info;
|
||||
use rp2040_flash::flash::{flash_range_erase, flash_range_program};
|
||||
|
||||
const XIP_BASE: u32 = 0x10000000;
|
||||
const FLASH_PAGE_SIZE: usize = 1usize << 8;
|
||||
const FLASH_SECTOR_SIZE: u32 = 1u32 << 12;
|
||||
const FLASH_BLOCK_SIZE: u32 = 1u32 << 16;
|
||||
const FLASH_BLOCK_ERASE_CMD: u8 = 0xd8;
|
||||
|
||||
const FLASH_TARGET_OFFSET: u32 = 256 * 1024;
|
||||
|
||||
pub fn read_from_flash() -> u8 {
|
||||
let flash_target_contents = (XIP_BASE + FLASH_TARGET_OFFSET) as *const u8;
|
||||
|
||||
let d = unsafe { from_raw_parts(flash_target_contents, FLASH_PAGE_SIZE) };
|
||||
|
||||
d[0]
|
||||
}
|
||||
|
||||
pub unsafe fn write_to_flash(b: u8) {
|
||||
let mut data = [0u8; FLASH_PAGE_SIZE];
|
||||
data[0] = b;
|
||||
info!("About to write with XIP_BASE: 0x{:x}", XIP_BASE);
|
||||
info!("FLASH_PAGE_SIZE is {}", FLASH_PAGE_SIZE);
|
||||
info!("FLASH_SECTOR_SIZE is {}", FLASH_SECTOR_SIZE);
|
||||
info!("FLASH_BLOCK_SIZE is {}", FLASH_BLOCK_SIZE);
|
||||
info!("FLASH_BLOCK_ERASE_CMD is 0x{:x}", FLASH_BLOCK_ERASE_CMD);
|
||||
info!("FLASH_TARGET_OFFSET is {}", FLASH_TARGET_OFFSET);
|
||||
|
||||
flash_range_erase(FLASH_TARGET_OFFSET, FLASH_SECTOR_SIZE, true);
|
||||
info!("Erased flash");
|
||||
flash_range_program(FLASH_TARGET_OFFSET, &data, true);
|
||||
info!("Wrote to flash");
|
||||
}
|
|
@ -7,7 +7,7 @@ use usbd_human_interface_device::{
|
|||
descriptor::InterfaceProtocol,
|
||||
device::DeviceClass,
|
||||
interface::{
|
||||
InBytes8, Interface, InterfaceBuilder, InterfaceConfig, OutNone, ReportSingle,
|
||||
InBytes64, InBytes8, Interface, InterfaceBuilder, InterfaceConfig, OutNone, ReportSingle,
|
||||
UsbAllocatable,
|
||||
},
|
||||
UsbHidError,
|
||||
|
@ -73,69 +73,69 @@ pub const GCC_REPORT_DESCRIPTOR: &[u8] = &[
|
|||
];
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default, PackedStruct)]
|
||||
#[packed_struct(endian = "msb", size_bytes = "1")]
|
||||
#[packed_struct(bit_numbering = "lsb0", size_bytes = "1")]
|
||||
pub struct Buttons1 {
|
||||
#[packed_field(size_bits = "1")]
|
||||
#[packed_field(bits = "0")]
|
||||
pub button_a: bool,
|
||||
#[packed_field(size_bits = "1")]
|
||||
#[packed_field(bits = "1")]
|
||||
pub button_b: bool,
|
||||
#[packed_field(size_bits = "1")]
|
||||
#[packed_field(bits = "2")]
|
||||
pub button_x: bool,
|
||||
#[packed_field(size_bits = "1")]
|
||||
#[packed_field(bits = "3")]
|
||||
pub button_y: bool,
|
||||
#[packed_field(size_bits = "1")]
|
||||
#[packed_field(bits = "4")]
|
||||
pub dpad_left: bool,
|
||||
#[packed_field(size_bits = "1")]
|
||||
#[packed_field(bits = "5")]
|
||||
pub dpad_right: bool,
|
||||
#[packed_field(size_bits = "1")]
|
||||
#[packed_field(bits = "6")]
|
||||
pub dpad_down: bool,
|
||||
#[packed_field(size_bits = "1")]
|
||||
#[packed_field(bits = "7")]
|
||||
pub dpad_up: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default, PackedStruct)]
|
||||
#[packed_struct(endian = "msb", size_bytes = "1")]
|
||||
#[packed_struct(bit_numbering = "lsb0", size_bytes = "1")]
|
||||
pub struct Buttons2 {
|
||||
#[packed_field(size_bits = "1")]
|
||||
#[packed_field(bits = "0")]
|
||||
pub button_start: bool,
|
||||
#[packed_field(size_bits = "1")]
|
||||
#[packed_field(bits = "1")]
|
||||
pub button_z: bool,
|
||||
#[packed_field(size_bits = "1")]
|
||||
#[packed_field(bits = "2")]
|
||||
pub button_r: bool,
|
||||
#[packed_field(size_bits = "1")]
|
||||
#[packed_field(bits = "3")]
|
||||
pub button_l: bool,
|
||||
#[packed_field(size_bits = "4")]
|
||||
#[packed_field(bits = "4..=7")]
|
||||
pub blank1: Integer<u8, packed_bits::Bits<4>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default, PackedStruct)]
|
||||
#[packed_struct(endian = "msb", size_bytes = "8")]
|
||||
#[packed_struct(bit_numbering = "msb0", size_bytes = "8")]
|
||||
pub struct GcReport {
|
||||
#[packed_field(size_bits = "8")]
|
||||
#[packed_field(bits = "0..=7")]
|
||||
pub buttons_1: Buttons1,
|
||||
#[packed_field(size_bits = "8")]
|
||||
#[packed_field(bits = "8..=15")]
|
||||
pub buttons_2: Buttons2,
|
||||
#[packed_field(size_bits = "8")]
|
||||
#[packed_field(bits = "16..=23")]
|
||||
pub stick_x: u8,
|
||||
#[packed_field(size_bits = "8")]
|
||||
#[packed_field(bits = "24..=31")]
|
||||
pub stick_y: u8,
|
||||
#[packed_field(size_bits = "8")]
|
||||
#[packed_field(bits = "32..=39")]
|
||||
pub cstick_x: u8,
|
||||
#[packed_field(size_bits = "8")]
|
||||
#[packed_field(bits = "40..=47")]
|
||||
pub cstick_y: u8,
|
||||
#[packed_field(size_bits = "8")]
|
||||
#[packed_field(bits = "48..=55")]
|
||||
pub trigger_l: u8,
|
||||
#[packed_field(size_bits = "8")]
|
||||
#[packed_field(bits = "56..=63")]
|
||||
pub trigger_r: u8,
|
||||
}
|
||||
|
||||
pub struct GcConfig<'a> {
|
||||
interface: InterfaceConfig<'a, InBytes8, OutNone, ReportSingle>,
|
||||
interface: InterfaceConfig<'a, InBytes64, OutNone, ReportSingle>,
|
||||
}
|
||||
|
||||
impl<'a> GcConfig<'a> {
|
||||
#[must_use]
|
||||
pub fn new(interface: InterfaceConfig<'a, InBytes8, OutNone, ReportSingle>) -> Self {
|
||||
pub fn new(interface: InterfaceConfig<'a, InBytes64, OutNone, ReportSingle>) -> Self {
|
||||
Self { interface }
|
||||
}
|
||||
}
|
||||
|
@ -146,7 +146,7 @@ impl<'a> Default for GcConfig<'a> {
|
|||
let i = unwrap!(unwrap!(InterfaceBuilder::new(GCC_REPORT_DESCRIPTOR))
|
||||
.boot_device(InterfaceProtocol::None)
|
||||
.description("NaxGCC")
|
||||
.in_endpoint(10.millis()));
|
||||
.in_endpoint(1.millis()));
|
||||
|
||||
Self::new(i.without_out_endpoint().build())
|
||||
}
|
||||
|
@ -163,27 +163,25 @@ impl<'a, B: UsbBus + 'a> UsbAllocatable<'a, B> for GcConfig<'a> {
|
|||
}
|
||||
|
||||
pub struct GcController<'a, B: UsbBus> {
|
||||
interface: Interface<'a, B, InBytes8, OutNone, ReportSingle>,
|
||||
interface: Interface<'a, B, InBytes64, OutNone, ReportSingle>,
|
||||
}
|
||||
|
||||
impl<'a, B: UsbBus> GcController<'a, B> {
|
||||
pub fn write_report(&mut self, report: &GcReport) -> Result<(), UsbHidError> {
|
||||
let report = get_gcinput_hid_report(report);
|
||||
// print report as binary
|
||||
|
||||
info!("Report: {:08b}", report);
|
||||
|
||||
self.interface
|
||||
.write_report(&report)
|
||||
.map(|_| ())
|
||||
.map_err(|e| {
|
||||
error!("Found an error: {:?}", e);
|
||||
UsbHidError::from(e)
|
||||
})
|
||||
.map_err(|e| UsbHidError::from(e))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, B: UsbBus> DeviceClass<'a> for GcController<'a, B> {
|
||||
type I = Interface<'a, B, InBytes8, OutNone, ReportSingle>;
|
||||
type I = Interface<'a, B, InBytes64, OutNone, ReportSingle>;
|
||||
|
||||
fn interface(&mut self) -> &mut Self::I {
|
||||
&mut self.interface
|
||||
|
@ -202,11 +200,10 @@ fn get_gcinput_hid_report(input_state: &GcReport) -> [u8; 37] {
|
|||
let mut buffer = [0u8; 37];
|
||||
|
||||
buffer[0] = 0x21;
|
||||
buffer[1] |= 0x14;
|
||||
|
||||
let data = input_state.pack().expect("Failed to pack GC input data");
|
||||
|
||||
info!("Packed data: {:08b}", data);
|
||||
|
||||
if unsafe { !GC_FIRST } {
|
||||
buffer[1] |= 0x04;
|
||||
buffer[10] |= 0x04;
|
||||
|
|
46
src/main.rs
46
src/main.rs
|
@ -8,6 +8,7 @@
|
|||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
mod flash_mem;
|
||||
mod gcc_hid;
|
||||
|
||||
use core::fmt::Write;
|
||||
|
@ -19,6 +20,7 @@ use fugit::ExtU32;
|
|||
// Ensure we halt the program on panic (if we don't mention this crate it won't
|
||||
// be linked)
|
||||
use defmt_rtt as _;
|
||||
use packed_struct::PackedStruct;
|
||||
use panic_halt as _;
|
||||
|
||||
// Alias for our HAL crate
|
||||
|
@ -33,14 +35,20 @@ use hal::{
|
|||
};
|
||||
|
||||
// Some traits we need
|
||||
use embedded_hal::{blocking::delay::DelayMs, digital::v2::OutputPin, timer::CountDown};
|
||||
use embedded_hal::{
|
||||
blocking::delay::DelayMs,
|
||||
digital::v2::{InputPin, OutputPin},
|
||||
timer::CountDown,
|
||||
};
|
||||
use rp2040_hal::Clock;
|
||||
use usb_device::{
|
||||
bus::UsbBusAllocator,
|
||||
device::{UsbDeviceBuilder, UsbVidPid},
|
||||
device::{UsbDeviceBuilder, UsbDeviceState, UsbVidPid},
|
||||
};
|
||||
use usbd_human_interface_device::{usb_class::UsbHidClassBuilder, UsbHidError};
|
||||
|
||||
use crate::flash_mem::{read_from_flash, write_to_flash};
|
||||
|
||||
/// The linker will place this boot block at the start of our program image. We
|
||||
/// need this to help the ROM bootloader get our code up and running.
|
||||
/// Note: This boot block is not necessary when using a rp-hal based BSP
|
||||
|
@ -84,7 +92,7 @@ fn main() -> ! {
|
|||
let mut timer = rp2040_hal::Timer::new(pac.TIMER, &mut pac.RESETS, &clocks);
|
||||
|
||||
let mut poll_timer = timer.count_down();
|
||||
poll_timer.start(10.millis());
|
||||
poll_timer.start(1.millis());
|
||||
|
||||
// The single-cycle I/O block controls our GPIO pins
|
||||
let sio = hal::Sio::new(pac.SIO);
|
||||
|
@ -124,23 +132,26 @@ fn main() -> ! {
|
|||
.max_packet_size_0(64)
|
||||
.build();
|
||||
|
||||
let mut uart = UartPeripheral::new(
|
||||
pac.UART0,
|
||||
(
|
||||
pins.gpio0.into_mode::<FunctionUart>(),
|
||||
pins.gpio1.into_mode(),
|
||||
),
|
||||
&mut pac.RESETS,
|
||||
)
|
||||
.enable(UartConfig::default(), clocks.peripheral_clock.freq())
|
||||
.unwrap();
|
||||
gcc_state.stick_x = 0;
|
||||
gcc_state.stick_y = 0;
|
||||
gcc_state.trigger_l = 21;
|
||||
gcc_state.cstick_x = 127;
|
||||
gcc_state.cstick_y = 127;
|
||||
|
||||
gcc_state.buttons_1.button_a = true;
|
||||
let btn_pin = pins.gpio15.into_pull_up_input();
|
||||
|
||||
unsafe {
|
||||
let some_byte: u8 = 0xAB;
|
||||
info!("Byte to be written is {:02X}", some_byte);
|
||||
write_to_flash(some_byte);
|
||||
let r = read_from_flash();
|
||||
info!("Byte read from flash is {:02X}", r);
|
||||
}
|
||||
|
||||
info!("Initialized");
|
||||
|
||||
// Configure GPIO25 as an output
|
||||
let mut led_pin = pins.gpio25.into_push_pull_output();
|
||||
info!("Bleg");
|
||||
let _ = uart.write_str("FLAR");
|
||||
loop {
|
||||
if poll_timer.wait().is_ok() {
|
||||
match gcc.device().write_report(&gcc_state) {
|
||||
|
@ -153,7 +164,8 @@ fn main() -> ! {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if usb_dev.poll(&mut [&mut gcc]) {}
|
||||
|
||||
gcc_state.buttons_2.button_start = btn_pin.is_low().unwrap();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue