forked from NaxdyOrg/NaxGCC-FW
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-halt",
|
||||||
"panic-probe",
|
"panic-probe",
|
||||||
"rp2040-boot2",
|
"rp2040-boot2",
|
||||||
|
"rp2040-flash",
|
||||||
"rp2040-hal",
|
"rp2040-hal",
|
||||||
"usb-device",
|
"usb-device",
|
||||||
"usbd-human-interface-device",
|
"usbd-human-interface-device",
|
||||||
|
@ -451,6 +452,15 @@ dependencies = [
|
||||||
"crc-any",
|
"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]]
|
[[package]]
|
||||||
name = "rp2040-hal"
|
name = "rp2040-hal"
|
||||||
version = "0.9.2"
|
version = "0.9.2"
|
||||||
|
|
|
@ -7,6 +7,7 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rp2040-hal = { version = "0.9.2", features = ["rt", "critical-section-impl"] }
|
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"] }
|
usbd-human-interface-device = { version = "0.4.5", features = ["defmt"] }
|
||||||
usb-device = "0.2"
|
usb-device = "0.2"
|
||||||
cortex-m = "0.7.7"
|
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,
|
descriptor::InterfaceProtocol,
|
||||||
device::DeviceClass,
|
device::DeviceClass,
|
||||||
interface::{
|
interface::{
|
||||||
InBytes8, Interface, InterfaceBuilder, InterfaceConfig, OutNone, ReportSingle,
|
InBytes64, InBytes8, Interface, InterfaceBuilder, InterfaceConfig, OutNone, ReportSingle,
|
||||||
UsbAllocatable,
|
UsbAllocatable,
|
||||||
},
|
},
|
||||||
UsbHidError,
|
UsbHidError,
|
||||||
|
@ -73,69 +73,69 @@ pub const GCC_REPORT_DESCRIPTOR: &[u8] = &[
|
||||||
];
|
];
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default, PackedStruct)]
|
#[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 {
|
pub struct Buttons1 {
|
||||||
#[packed_field(size_bits = "1")]
|
#[packed_field(bits = "0")]
|
||||||
pub button_a: bool,
|
pub button_a: bool,
|
||||||
#[packed_field(size_bits = "1")]
|
#[packed_field(bits = "1")]
|
||||||
pub button_b: bool,
|
pub button_b: bool,
|
||||||
#[packed_field(size_bits = "1")]
|
#[packed_field(bits = "2")]
|
||||||
pub button_x: bool,
|
pub button_x: bool,
|
||||||
#[packed_field(size_bits = "1")]
|
#[packed_field(bits = "3")]
|
||||||
pub button_y: bool,
|
pub button_y: bool,
|
||||||
#[packed_field(size_bits = "1")]
|
#[packed_field(bits = "4")]
|
||||||
pub dpad_left: bool,
|
pub dpad_left: bool,
|
||||||
#[packed_field(size_bits = "1")]
|
#[packed_field(bits = "5")]
|
||||||
pub dpad_right: bool,
|
pub dpad_right: bool,
|
||||||
#[packed_field(size_bits = "1")]
|
#[packed_field(bits = "6")]
|
||||||
pub dpad_down: bool,
|
pub dpad_down: bool,
|
||||||
#[packed_field(size_bits = "1")]
|
#[packed_field(bits = "7")]
|
||||||
pub dpad_up: bool,
|
pub dpad_up: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default, PackedStruct)]
|
#[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 {
|
pub struct Buttons2 {
|
||||||
#[packed_field(size_bits = "1")]
|
#[packed_field(bits = "0")]
|
||||||
pub button_start: bool,
|
pub button_start: bool,
|
||||||
#[packed_field(size_bits = "1")]
|
#[packed_field(bits = "1")]
|
||||||
pub button_z: bool,
|
pub button_z: bool,
|
||||||
#[packed_field(size_bits = "1")]
|
#[packed_field(bits = "2")]
|
||||||
pub button_r: bool,
|
pub button_r: bool,
|
||||||
#[packed_field(size_bits = "1")]
|
#[packed_field(bits = "3")]
|
||||||
pub button_l: bool,
|
pub button_l: bool,
|
||||||
#[packed_field(size_bits = "4")]
|
#[packed_field(bits = "4..=7")]
|
||||||
pub blank1: Integer<u8, packed_bits::Bits<4>>,
|
pub blank1: Integer<u8, packed_bits::Bits<4>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default, PackedStruct)]
|
#[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 {
|
pub struct GcReport {
|
||||||
#[packed_field(size_bits = "8")]
|
#[packed_field(bits = "0..=7")]
|
||||||
pub buttons_1: Buttons1,
|
pub buttons_1: Buttons1,
|
||||||
#[packed_field(size_bits = "8")]
|
#[packed_field(bits = "8..=15")]
|
||||||
pub buttons_2: Buttons2,
|
pub buttons_2: Buttons2,
|
||||||
#[packed_field(size_bits = "8")]
|
#[packed_field(bits = "16..=23")]
|
||||||
pub stick_x: u8,
|
pub stick_x: u8,
|
||||||
#[packed_field(size_bits = "8")]
|
#[packed_field(bits = "24..=31")]
|
||||||
pub stick_y: u8,
|
pub stick_y: u8,
|
||||||
#[packed_field(size_bits = "8")]
|
#[packed_field(bits = "32..=39")]
|
||||||
pub cstick_x: u8,
|
pub cstick_x: u8,
|
||||||
#[packed_field(size_bits = "8")]
|
#[packed_field(bits = "40..=47")]
|
||||||
pub cstick_y: u8,
|
pub cstick_y: u8,
|
||||||
#[packed_field(size_bits = "8")]
|
#[packed_field(bits = "48..=55")]
|
||||||
pub trigger_l: u8,
|
pub trigger_l: u8,
|
||||||
#[packed_field(size_bits = "8")]
|
#[packed_field(bits = "56..=63")]
|
||||||
pub trigger_r: u8,
|
pub trigger_r: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct GcConfig<'a> {
|
pub struct GcConfig<'a> {
|
||||||
interface: InterfaceConfig<'a, InBytes8, OutNone, ReportSingle>,
|
interface: InterfaceConfig<'a, InBytes64, OutNone, ReportSingle>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> GcConfig<'a> {
|
impl<'a> GcConfig<'a> {
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new(interface: InterfaceConfig<'a, InBytes8, OutNone, ReportSingle>) -> Self {
|
pub fn new(interface: InterfaceConfig<'a, InBytes64, OutNone, ReportSingle>) -> Self {
|
||||||
Self { interface }
|
Self { interface }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -146,7 +146,7 @@ impl<'a> Default for GcConfig<'a> {
|
||||||
let i = unwrap!(unwrap!(InterfaceBuilder::new(GCC_REPORT_DESCRIPTOR))
|
let i = unwrap!(unwrap!(InterfaceBuilder::new(GCC_REPORT_DESCRIPTOR))
|
||||||
.boot_device(InterfaceProtocol::None)
|
.boot_device(InterfaceProtocol::None)
|
||||||
.description("NaxGCC")
|
.description("NaxGCC")
|
||||||
.in_endpoint(10.millis()));
|
.in_endpoint(1.millis()));
|
||||||
|
|
||||||
Self::new(i.without_out_endpoint().build())
|
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> {
|
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> {
|
impl<'a, B: UsbBus> GcController<'a, B> {
|
||||||
pub fn write_report(&mut self, report: &GcReport) -> Result<(), UsbHidError> {
|
pub fn write_report(&mut self, report: &GcReport) -> Result<(), UsbHidError> {
|
||||||
let report = get_gcinput_hid_report(report);
|
let report = get_gcinput_hid_report(report);
|
||||||
// print report as binary
|
// print report as binary
|
||||||
|
|
||||||
info!("Report: {:08b}", report);
|
info!("Report: {:08b}", report);
|
||||||
|
|
||||||
self.interface
|
self.interface
|
||||||
.write_report(&report)
|
.write_report(&report)
|
||||||
.map(|_| ())
|
.map(|_| ())
|
||||||
.map_err(|e| {
|
.map_err(|e| UsbHidError::from(e))
|
||||||
error!("Found an error: {:?}", e);
|
|
||||||
UsbHidError::from(e)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, B: UsbBus> DeviceClass<'a> for GcController<'a, B> {
|
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 {
|
fn interface(&mut self) -> &mut Self::I {
|
||||||
&mut self.interface
|
&mut self.interface
|
||||||
|
@ -202,11 +200,10 @@ fn get_gcinput_hid_report(input_state: &GcReport) -> [u8; 37] {
|
||||||
let mut buffer = [0u8; 37];
|
let mut buffer = [0u8; 37];
|
||||||
|
|
||||||
buffer[0] = 0x21;
|
buffer[0] = 0x21;
|
||||||
|
buffer[1] |= 0x14;
|
||||||
|
|
||||||
let data = input_state.pack().expect("Failed to pack GC input data");
|
let data = input_state.pack().expect("Failed to pack GC input data");
|
||||||
|
|
||||||
info!("Packed data: {:08b}", data);
|
|
||||||
|
|
||||||
if unsafe { !GC_FIRST } {
|
if unsafe { !GC_FIRST } {
|
||||||
buffer[1] |= 0x04;
|
buffer[1] |= 0x04;
|
||||||
buffer[10] |= 0x04;
|
buffer[10] |= 0x04;
|
||||||
|
|
46
src/main.rs
46
src/main.rs
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
mod flash_mem;
|
||||||
mod gcc_hid;
|
mod gcc_hid;
|
||||||
|
|
||||||
use core::fmt::Write;
|
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
|
// Ensure we halt the program on panic (if we don't mention this crate it won't
|
||||||
// be linked)
|
// be linked)
|
||||||
use defmt_rtt as _;
|
use defmt_rtt as _;
|
||||||
|
use packed_struct::PackedStruct;
|
||||||
use panic_halt as _;
|
use panic_halt as _;
|
||||||
|
|
||||||
// Alias for our HAL crate
|
// Alias for our HAL crate
|
||||||
|
@ -33,14 +35,20 @@ use hal::{
|
||||||
};
|
};
|
||||||
|
|
||||||
// Some traits we need
|
// 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 rp2040_hal::Clock;
|
||||||
use usb_device::{
|
use usb_device::{
|
||||||
bus::UsbBusAllocator,
|
bus::UsbBusAllocator,
|
||||||
device::{UsbDeviceBuilder, UsbVidPid},
|
device::{UsbDeviceBuilder, UsbDeviceState, UsbVidPid},
|
||||||
};
|
};
|
||||||
use usbd_human_interface_device::{usb_class::UsbHidClassBuilder, UsbHidError};
|
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
|
/// 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.
|
/// 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
|
/// 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 timer = rp2040_hal::Timer::new(pac.TIMER, &mut pac.RESETS, &clocks);
|
||||||
|
|
||||||
let mut poll_timer = timer.count_down();
|
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
|
// The single-cycle I/O block controls our GPIO pins
|
||||||
let sio = hal::Sio::new(pac.SIO);
|
let sio = hal::Sio::new(pac.SIO);
|
||||||
|
@ -124,23 +132,26 @@ fn main() -> ! {
|
||||||
.max_packet_size_0(64)
|
.max_packet_size_0(64)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let mut uart = UartPeripheral::new(
|
gcc_state.stick_x = 0;
|
||||||
pac.UART0,
|
gcc_state.stick_y = 0;
|
||||||
(
|
gcc_state.trigger_l = 21;
|
||||||
pins.gpio0.into_mode::<FunctionUart>(),
|
gcc_state.cstick_x = 127;
|
||||||
pins.gpio1.into_mode(),
|
gcc_state.cstick_y = 127;
|
||||||
),
|
|
||||||
&mut pac.RESETS,
|
|
||||||
)
|
|
||||||
.enable(UartConfig::default(), clocks.peripheral_clock.freq())
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
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
|
// Configure GPIO25 as an output
|
||||||
let mut led_pin = pins.gpio25.into_push_pull_output();
|
let mut led_pin = pins.gpio25.into_push_pull_output();
|
||||||
info!("Bleg");
|
|
||||||
let _ = uart.write_str("FLAR");
|
|
||||||
loop {
|
loop {
|
||||||
if poll_timer.wait().is_ok() {
|
if poll_timer.wait().is_ok() {
|
||||||
match gcc.device().write_report(&gcc_state) {
|
match gcc.device().write_report(&gcc_state) {
|
||||||
|
@ -153,7 +164,8 @@ fn main() -> ! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if usb_dev.poll(&mut [&mut gcc]) {}
|
if usb_dev.poll(&mut [&mut gcc]) {}
|
||||||
|
|
||||||
|
gcc_state.buttons_2.button_start = btn_pin.is_low().unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue