From ecdadfb0b10e4a587f9cad5218c608ba89676add Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Sat, 30 Sep 2023 15:13:04 +0800 Subject: [PATCH 01/14] Implement basic keyboard firmware Lights up capslock LED and when in USB suspend blinks it every 500ms. Signed-off-by: Daniel Schaefer --- .github/workflows/firmware.yml | 15 ++ .github/workflows/software.yml | 2 + .github/workflows/traditional-cargo.yml | 2 + Cargo.lock | 20 ++ Cargo.toml | 7 + fl16-inputmodules/Cargo.toml | 1 + fl16-inputmodules/src/keyboard_hal.rs | 97 ++++++++ fl16-inputmodules/src/lib.rs | 10 +- keyboard/Cargo.toml | 39 ++++ keyboard/Makefile.toml | 12 + keyboard/README.md | 4 + keyboard/src/main.rs | 281 ++++++++++++++++++++++++ 12 files changed, 489 insertions(+), 1 deletion(-) create mode 100644 fl16-inputmodules/src/keyboard_hal.rs create mode 100644 keyboard/Cargo.toml create mode 100644 keyboard/Makefile.toml create mode 100644 keyboard/README.md create mode 100644 keyboard/src/main.rs diff --git a/.github/workflows/firmware.yml b/.github/workflows/firmware.yml index 64603a4f..96e915d5 100644 --- a/.github/workflows/firmware.yml +++ b/.github/workflows/firmware.yml @@ -34,11 +34,13 @@ jobs: - run: cargo install flip-link - run: cargo make --cwd b1display - run: cargo make --cwd c1minimal + - run: cargo make --cwd keyboard - run: cargo make --cwd ledmatrix build-release - run: cargo make --cwd ledmatrix build-release-10k - run: cargo make --cwd ledmatrix build-release-evt - run: cargo make --cwd b1display build-release - run: cargo make --cwd c1minimal build-release + - run: cargo make --cwd keyboard build-release - name: Convert to UF2 format run: | @@ -46,6 +48,7 @@ jobs: sudo apt-get install -y libudev-dev cargo make --cwd b1display uf2 cargo make --cwd c1minimal uf2 + cargo make --cwd keyboard uf2 cargo make --cwd ledmatrix build-release-10k-uf2 cargo make --cwd ledmatrix build-release-evt-uf2 cargo make --cwd ledmatrix uf2 @@ -56,6 +59,7 @@ jobs: sudo apt-get install -y llvm cargo make --cwd b1display bin cargo make --cwd c1minimal bin + cargo make --cwd keyboard bin cargo make --cwd ledmatrix bin - name: Upload ledmatrix files @@ -87,6 +91,14 @@ jobs: target/thumbv6m-none-eabi/release/c1minimal.bin target/thumbv6m-none-eabi/release/c1minimal.uf2 + - name: Upload keyboard files + uses: actions/upload-artifact@v3 + with: + name: c1minimal_fw_${{github.sha}} + path: | + target/thumbv6m-none-eabi/release/keyboard.bin + target/thumbv6m-none-eabi/release/keyboard.uf2 + linting: name: Linting runs-on: ubuntu-latest @@ -103,6 +115,7 @@ jobs: sudo apt-get install -y libudev-dev cargo make clippy --cwd b1display cargo make clippy --cwd c1minimal + cargo make clippy --cwd keyboard cargo make clippy --cwd ledmatrix # fl16-inputmodules/src/serialnum.rs @@ -114,6 +127,7 @@ jobs: cargo pkgid -p fl16-inputmodules | cut -d "#" -f2 >> versions.tmp cargo pkgid -p b1display | cut -d "#" -f2 >> versions.tmp cargo pkgid -p c1minimal | cut -d "#" -f2 >> versions.tmp + cargo pkgid -p keyboard | cut -d "#" -f2 >> versions.tmp cargo pkgid -p ledmatrix | cut -d "#" -f2 >> versions.tmp uniq -c versions.tmp | [ $(wc -l) -eq 1 ] @@ -129,5 +143,6 @@ jobs: - run: | cargo fmt -p b1display -- --check cargo fmt -p c1minimal -- --check + cargo fmt -p keyboard -- --check cargo fmt -p ledmatrix -- --check cargo fmt -p fl16-inputmodules -- --check diff --git a/.github/workflows/software.yml b/.github/workflows/software.yml index d65c8aee..537b8dcc 100644 --- a/.github/workflows/software.yml +++ b/.github/workflows/software.yml @@ -8,6 +8,7 @@ on: paths-ignore: - 'b1display/**' - 'c1minimal/**' + - 'keyboard/**' - 'fl16-inputmodules/**' - 'ledmatrix/**' pull_request: @@ -16,6 +17,7 @@ on: paths-ignore: - 'b1display/**' - 'c1minimal/**' + - 'keyboard/**' - 'fl16-inputmodules/**' - 'ledmatrix/**' diff --git a/.github/workflows/traditional-cargo.yml b/.github/workflows/traditional-cargo.yml index fcd96c49..baa162d9 100644 --- a/.github/workflows/traditional-cargo.yml +++ b/.github/workflows/traditional-cargo.yml @@ -36,6 +36,7 @@ jobs: - run: cargo build -p ledmatrix --features evt - run: cargo build -p b1display - run: cargo build -p c1minimal + - run: cargo build -p keyboard linux-software: name: Build Linux @@ -92,6 +93,7 @@ jobs: run: | cargo clippy -p b1display -- --deny=warnings cargo clippy -p c1minimal -- --deny=warnings + cargo clippy -p keyboard -- --deny=warnings cargo clippy -p ledmatrix -- --deny=warnings cargo clippy -p fl16-inputmodules -- --deny=warnings diff --git a/Cargo.lock b/Cargo.lock index 00663417..1df49e0f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1089,6 +1089,26 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "keyboard" +version = "0.1.7" +dependencies = [ + "cortex-m", + "cortex-m-rt", + "defmt", + "defmt-rtt", + "embedded-hal", + "fl16-inputmodules", + "fugit", + "heapless", + "rp2040-boot2", + "rp2040-hal", + "rp2040-panic-usb-boot", + "usb-device", + "usbd-hid", + "usbd-serial", +] + [[package]] name = "lazy_static" version = "1.4.0" diff --git a/Cargo.toml b/Cargo.toml index e86f3e3b..40ac4df2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ resolver = "2" members = [ "b1display", "c1minimal", + "keyboard", "ledmatrix", "fl16-inputmodules", "inputmodule-control", @@ -57,6 +58,12 @@ incremental = true # To allow single-stepping through code use 0. Will cause timing issues, though opt-level = 3 +[profile.dev.package.keyboard] +codegen-units = 1 +incremental = true +# To allow single-stepping through code use 0. Will cause timing issues, though +opt-level = 3 + [profile.dev.package.b1display] codegen-units = 1 incremental = true diff --git a/fl16-inputmodules/Cargo.toml b/fl16-inputmodules/Cargo.toml index 9c28fd13..a91de0eb 100644 --- a/fl16-inputmodules/Cargo.toml +++ b/fl16-inputmodules/Cargo.toml @@ -47,3 +47,4 @@ default = [] ledmatrix = ["is31fl3741"] b1display = ["st7306", "embedded-graphics", "tinybmp"] c1minimal = ["smart-leds", "ws2812-pio"] +keyboard = [] diff --git a/fl16-inputmodules/src/keyboard_hal.rs b/fl16-inputmodules/src/keyboard_hal.rs new file mode 100644 index 00000000..beeb3ec1 --- /dev/null +++ b/fl16-inputmodules/src/keyboard_hal.rs @@ -0,0 +1,97 @@ +// Taken from rp_pico hal and adjusted + +pub extern crate rp2040_hal as hal; + +extern crate cortex_m_rt; +pub use hal::entry; + +/// 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. +#[link_section = ".boot2"] +#[no_mangle] +#[used] +pub static BOOT2_FIRMWARE: [u8; 256] = rp2040_boot2::BOOT_LOADER_W25Q080; + +pub use hal::pac; + +hal::bsp_pins!( + /// GPIO 0 is connected to the SLEEP# pin of the EC + Gpio0 { name: sleep }, + /// Mux selector A + Gpio1 { name: mux_a }, + /// Mux selector B + Gpio2 { name: mux_b }, + /// Mux selector C + Gpio3 { name: mux_c }, + /// Mux enable + Gpio4 { name: mux_enable }, + /// Pull low when firmware has started to turn off bootloader logic + Gpio5 { name: boot_done }, + /// Connected to KSI5 but unused, should use high-Z + Gpio6 { + name: ksi5_reserved + }, + /// Connected to KSI5 but unused, should use high-Z + Gpio7 { + name: ksi6_reserved + }, + /// Keyboard column drive + Gpio8 { name: kso0 }, + /// Keyboard column drive + Gpio9 { name: kso1 }, + /// Keyboard column drive + Gpio10 { name: kso2 }, + /// Keyboard column drive + Gpio11 { name: kso3 }, + /// Keyboard column drive + Gpio12 { name: kso4 }, + /// Keyboard column drive + Gpio13 { name: kso5 }, + /// Keyboard column drive + Gpio14 { name: kso6 }, + /// Keyboard column drive + Gpio15 { name: kso7 }, + /// Keyboard column drive + Gpio16 { name: kso13 }, + /// Keyboard column drive + Gpio17 { name: kso12 }, + /// Keyboard column drive + Gpio18 { name: kso11 }, + /// Keyboard column drive + Gpio19 { name: kso10 }, + /// Keyboard column drive + Gpio20 { name: kso9 }, + /// Keyboard column drive + Gpio21 { name: kso8 }, + /// Keyboard column drive + Gpio22 { name: kso15 }, + /// Keyboard column drive + Gpio23 { name: kso14 }, + /// Capslock LED + Gpio24 { name: caps_led }, + /// Single zone backlight (unused on RGB keyboard) + Gpio25 { name: backlight }, + /// GPIO 26 is connected to I2C SDA of the LED controller + Gpio26 { + name: gpio26, + aliases: { + /// I2C Function alias for pin [crate::Pins::gpio26]. + FunctionI2C: Gp26I2C1Sda + } + }, + /// GPIO 27 is connected to I2C SCL of the LED controller + Gpio27 { + name: gpio27, + aliases: { + /// I2C Function alias for pin [crate::Pins::gpio27]. + FunctionI2C: Gp27I2C1Scl + } + }, + /// Analog IN from mux + Gpio28 { name: analog_in }, + /// GPIO 29 is connected to the SDB pin of the LED controller + Gpio29 { name: sdb }, +); + +// External crystal frequency, same as Raspberry Pi Pico +pub const XOSC_CRYSTAL_FREQ: u32 = 12_000_000; diff --git a/fl16-inputmodules/src/lib.rs b/fl16-inputmodules/src/lib.rs index e7fa8370..bfb278ec 100644 --- a/fl16-inputmodules/src/lib.rs +++ b/fl16-inputmodules/src/lib.rs @@ -5,8 +5,13 @@ all(feature = "ledmatrix", feature = "b1display"), all(feature = "ledmatrix", feature = "c1minimal"), all(feature = "b1display", feature = "c1minimal"), + all(feature = "ledmatrix", feature = "keyboard"), + all(feature = "b1display", feature = "keyboard"), + all(feature = "c1minimal", feature = "keyboard"), ))] -compile_error!("Features \"ledmatrix\", \"b1display\", and \"c1minimal\" are mutually exclusive"); +compile_error!( + "Features \"ledmatrix\", \"b1display\", \"c1minimal\", and \"keyboard\" are mutually exclusive" +); #[cfg(feature = "ledmatrix")] pub mod fl16; @@ -30,5 +35,8 @@ pub mod lcd_hal; #[cfg(feature = "c1minimal")] pub mod minimal_hal; +#[cfg(feature = "keyboard")] +pub mod keyboard_hal; + pub mod control; pub mod serialnum; diff --git a/keyboard/Cargo.toml b/keyboard/Cargo.toml new file mode 100644 index 00000000..f16b1b94 --- /dev/null +++ b/keyboard/Cargo.toml @@ -0,0 +1,39 @@ +[package] +edition = "2021" +name = "keyboard" +version = "0.1.7" + +[features] +default = ["macropad"] +cli = [] +ansi = [] +iso = [] +jis = [] +numpad = [] +macropad = [] + +[dependencies] +cortex-m.workspace = true +cortex-m-rt.workspace = true +embedded-hal.workspace = true + +defmt.workspace = true +defmt-rtt.workspace = true + +#panic-probe.workspace = true +rp2040-panic-usb-boot.workspace = true + +# Not using an external BSP, we've got the Framework Laptop 16 BSPs locally in this crate +rp2040-hal.workspace = true +rp2040-boot2.workspace = true + +# USB Serial +usb-device.workspace = true +heapless.workspace = true +usbd-serial.workspace = true +usbd-hid.workspace = true +fugit.workspace = true + +[dependencies.fl16-inputmodules] +path = "../fl16-inputmodules" +features = ["keyboard"] diff --git a/keyboard/Makefile.toml b/keyboard/Makefile.toml new file mode 100644 index 00000000..ea7d5ecc --- /dev/null +++ b/keyboard/Makefile.toml @@ -0,0 +1,12 @@ +extend = "../Makefile.toml" + +[tasks.uf2] +command = "elf2uf2-rs" +args = ["../target/thumbv6m-none-eabi/release/b1display", "../target/thumbv6m-none-eabi/release/b1display.uf2"] +dependencies = ["build-release"] +install_crate = "elf2uf2-rs" + +[tasks.bin] +command = "llvm-objcopy" +args = ["-Obinary", "../target/thumbv6m-none-eabi/release/b1display", "../target/thumbv6m-none-eabi/release/b1display.bin"] +dependencies = ["build-release"] diff --git a/keyboard/README.md b/keyboard/README.md new file mode 100644 index 00000000..9beb06c0 --- /dev/null +++ b/keyboard/README.md @@ -0,0 +1,4 @@ +# Keyboard + +NOT THE OFFICIAL Keyboard firmware +Just experimental reference code for building keyboard firmare in Rust \ No newline at end of file diff --git a/keyboard/src/main.rs b/keyboard/src/main.rs new file mode 100644 index 00000000..8d2e3546 --- /dev/null +++ b/keyboard/src/main.rs @@ -0,0 +1,281 @@ +//! NOT THE OFFICIAL Keyboard firmware +//! Just experimental reference code for building keyboard firmare in Rust +#![no_std] +#![no_main] +#![allow(clippy::needless_range_loop)] + +//use cortex_m::delay::Delay; +//use defmt::*; +use defmt_rtt as _; +use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin}; + +use rp2040_hal::Timer; +//#[cfg(debug_assertions)] +//use panic_probe as _; +use rp2040_panic_usb_boot as _; + +/// List maximum current as 500mA in the USB descriptor +const MAX_CURRENT: usize = 500; + +// 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 bsp::entry; +use fl16_inputmodules::keyboard_hal as bsp; +//use rp_pico as bsp; +// use sparkfun_pro_micro_rp2040 as bsp; + +use bsp::hal::{ + clocks::{init_clocks_and_plls, Clock}, + pac, + sio::Sio, + usb, + watchdog::Watchdog, +}; + +// USB Device support +use usb_device::{class_prelude::*, prelude::*}; + +// USB Communications Class Device support +use usbd_serial::{SerialPort, USB_CLASS_CDC}; + +// Used to demonstrate writing formatted strings +use core::fmt::Write; +use heapless::String; + +use fl16_inputmodules::serialnum::device_release; + +#[entry] +fn main() -> ! { + 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 clocks = init_clocks_and_plls( + bsp::XOSC_CRYSTAL_FREQ, + pac.XOSC, + pac.CLOCKS, + pac.PLL_SYS, + pac.PLL_USB, + &mut pac.RESETS, + &mut watchdog, + ) + .ok() + .unwrap(); + + let rosc = rp2040_hal::rosc::RingOscillator::new(pac.ROSC); + let _rosc = rosc.initialize(); + + 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, + ); + + // Set up the USB driver + let usb_bus = UsbBusAllocator::new(usb::UsbBus::new( + pac.USBCTRL_REGS, + pac.USBCTRL_DPRAM, + clocks.usb_clock, + true, + &mut pac.RESETS, + )); + + // Set up the USB Communications Class Device driver + let mut serial = SerialPort::new(&usb_bus); + + #[cfg(feature = "macropad")] + let pid = 0x013; + #[cfg(feature = "ansi")] + let pid = 0x012; + #[cfg(feature = "numpad")] + let pid = 0x014; + #[cfg(feature = "iso")] + let pid = 0x018; + #[cfg(feature = "jis")] + let pid = 0x019; + + #[cfg(feature = "macropad")] + let product = "Rust Macropad"; + #[cfg(feature = "ansi")] + let product = "Rust ANSI Keyboard"; + #[cfg(feature = "numpad")] + let product = "Rust Numpad"; + #[cfg(feature = "iso")] + let product = "Rust ISO Keyboard"; + #[cfg(feature = "jis")] + let product = "Rust JIS Keyboard"; + + let mut usb_dev = UsbDeviceBuilder::new(&usb_bus, UsbVidPid(0x32ac, pid)) + .manufacturer("Framework Computer Inc") + .product(product) + //.supports_remote_wakeup(true) + .device_class(USB_CLASS_CDC) + .max_power(MAX_CURRENT) + .serial_number("testing") + .device_release(device_release()) + .build(); + + // Disable bootloader circuitry + let mut boot_done = pins.boot_done.into_push_pull_output(); + boot_done.set_high().unwrap(); + + // pins.gp26 // SDA + // pins.gp27 // SCL + // pins.analog_in + + let mut caps_led = pins.caps_led.into_push_pull_output(); + let mut _backlight = pins.backlight.into_push_pull_output(); + + // Pull low to enable mux + let mut mux_enable = pins.mux_enable.into_push_pull_output(); + mux_enable.set_low().unwrap(); + let mut _mux_a = pins.mux_a.into_push_pull_output(); + let mut _mux_b = pins.mux_b.into_push_pull_output(); + let mut _mux_c = pins.mux_c.into_push_pull_output(); + + // KS0 - KSO7 for Keyboard and Numpad + let mut _kso0 = pins.kso0.into_push_pull_output(); + let mut _kso1 = pins.kso1.into_push_pull_output(); + let mut _kso2 = pins.kso2.into_push_pull_output(); + let mut _kso3 = pins.kso3.into_push_pull_output(); + let mut _kso4 = pins.kso4.into_push_pull_output(); + let mut _kso5 = pins.kso5.into_push_pull_output(); + let mut _kso6 = pins.kso6.into_push_pull_output(); + let mut _kso7 = pins.kso7.into_push_pull_output(); + // KS08 - KS015 for Keyboard only + let mut _kso8 = pins.kso8.into_push_pull_output(); + let mut _kso9 = pins.kso9.into_push_pull_output(); + let mut _kso10 = pins.kso10.into_push_pull_output(); + let mut _kso11 = pins.kso11.into_push_pull_output(); + let mut _kso12 = pins.kso12.into_push_pull_output(); + let mut _kso13 = pins.kso13.into_push_pull_output(); + let mut _kso14 = pins.kso14.into_push_pull_output(); + let mut _kso15 = pins.kso15.into_push_pull_output(); + // Set unused pins to input to avoid interfering. They're hooked up to rows 5 and 6 + let _ = pins.ksi5_reserved.into_floating_input(); + let _ = pins.ksi6_reserved.into_floating_input(); + + let sleep = pins.sleep.into_floating_input(); + + // Enable LED controller + // SDB + let mut led_enable = pins.sdb.into_push_pull_output(); + led_enable.set_low().unwrap(); + // led_enable.set_high().unwrap(); + // + // let i2c = bsp::hal::I2C::i2c1( + // pac.I2C1, + // pins.gpio26.into_mode::(), + // pins.gpio27.into_mode::(), + // 1000.kHz(), + // &mut pac.RESETS, + // &clocks.peripheral_clock, + // ); + // + // let mut matrix = LedMatrix::new(i2c, DVT2_CALC_PIXEL); + // matrix + // .setup(&mut delay) + // .expect("failed to setup RGB controller"); + // + // matrix + // .set_scaling(MAX_BRIGHTNESS) + // .expect("failed to set scaling"); + // + // fill_grid_pixels(&state, &mut matrix); + + let timer = Timer::new(pac.TIMER, &mut pac.RESETS); + let mut animation_timer = timer.get_counter().ticks(); + caps_led.set_high().unwrap(); + + let mut usb_initialized; + let mut usb_suspended = false; + loop { + let _ = sleep.is_high(); + + // Turn back on when not suspended anymore + if !usb_suspended { + if caps_led.is_set_low().unwrap() { + caps_led.set_high().unwrap(); + } + } + + // Blink when in USB Suspend + // 500_000us = 500ms = 0.5s + if usb_suspended && timer.get_counter().ticks() > animation_timer + 500_000 { + if caps_led.is_set_high().unwrap() { + caps_led.set_low().unwrap(); + } else { + caps_led.set_high().unwrap(); + } + animation_timer = timer.get_counter().ticks(); + } + + // Check for new data + if usb_dev.poll(&mut [&mut serial]) { + match usb_dev.state() { + // Default: Device has just been created or reset + // Addressed: Device has received an address for the host + UsbDeviceState::Default | UsbDeviceState::Addressed => { + usb_initialized = false; + usb_suspended = false; + // Must not display anything or windows cannot enumerate properly + } + // Configured and is fully operational + UsbDeviceState::Configured => { + usb_initialized = true; + usb_suspended = false; + } + // Never occurs here. Only if poll() returns false + UsbDeviceState::Suspend => { + panic!("Never occurs here. Only if poll() returns false") + } + } + + // Ignore unused + let _ = usb_initialized; + let _ = usb_suspended; + + let mut buf = [0u8; 64]; + match serial.read(&mut buf) { + Err(_e) => { + // Do nothing + } + Ok(0) => { + // Do nothing + } + Ok(count) => { + let mut text: String<64> = String::new(); + write!( + &mut text, + "Hello World: Usb Suspended: {}. C: {}\r\n", + usb_suspended, count + ) + .unwrap(); + let _ = serial.write(text.as_bytes()); + } + } + } else { + match usb_dev.state() { + // No new data + UsbDeviceState::Default | UsbDeviceState::Addressed => { + usb_initialized = false; + usb_suspended = false; + } + UsbDeviceState::Configured => { + usb_initialized = true; + usb_suspended = false; + } + UsbDeviceState::Suspend => { + usb_suspended = true; + } + } + // Ignore unused + let _ = usb_initialized; + let _ = usb_suspended; + } + } +} From 931a00a98c39a1c6c437d6dd21a39ba739e5840b Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Sat, 30 Sep 2023 19:11:05 +0800 Subject: [PATCH 02/14] keyboard: Implement reading of arrow keys Prints to USB serial Signed-off-by: Daniel Schaefer --- Cargo.lock | 7 +- Cargo.toml | 3 + keyboard/src/main.rs | 263 ++++++++++++++++++++++++++++++++++++++----- 3 files changed, 237 insertions(+), 36 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1df49e0f..774e65d0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1864,8 +1864,7 @@ dependencies = [ [[package]] name = "rp2040-hal" version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1369bb84862d7f69391a96606b2f29a00bfce7f29a749e23d5f01fc3f607ada0" +source = "git+https://github.com/FrameworkComputer/rp-hal?branch=adc-pull-down-up#ef80ceba220f0dc0f50cabeee4ed8fc3c597cf43" dependencies = [ "cortex-m", "critical-section", @@ -1887,10 +1886,8 @@ dependencies = [ [[package]] name = "rp2040-hal-macros" version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86479063e497efe1ae81995ef9071f54fd1c7427e04d6c5b84cde545ff672a5e" +source = "git+https://github.com/FrameworkComputer/rp-hal?branch=adc-pull-down-up#ef80ceba220f0dc0f50cabeee4ed8fc3c597cf43" dependencies = [ - "cortex-m-rt", "proc-macro2", "quote", "syn 1.0.109", diff --git a/Cargo.toml b/Cargo.toml index 40ac4df2..09867579 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,9 @@ members = [ # target. But we set the default target to thumbv6m-none-eabi default-members = ["fl16-inputmodules"] +[patch.crates-io] +rp2040-hal = { git = "https://github.com/FrameworkComputer/rp-hal", branch = "adc-pull-down-up" } + [workspace.dependencies] cortex-m = "0.7" cortex-m-rt = "0.7.3" diff --git a/keyboard/src/main.rs b/keyboard/src/main.rs index 8d2e3546..306a8178 100644 --- a/keyboard/src/main.rs +++ b/keyboard/src/main.rs @@ -7,9 +7,24 @@ //use cortex_m::delay::Delay; //use defmt::*; use defmt_rtt as _; +use embedded_hal::adc::OneShot; use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin}; - -use rp2040_hal::Timer; +use rp2040_hal::gpio::bank0::Gpio28; +use rp2040_hal::gpio::{Input, PullUp}; + +use core::fmt::Display; +use core::fmt::{self, Formatter}; + +use rp2040_hal::{ + gpio::{ + bank0::{ + Gpio1, Gpio10, Gpio11, Gpio12, Gpio13, Gpio14, Gpio15, Gpio16, Gpio17, Gpio18, Gpio19, + Gpio2, Gpio20, Gpio21, Gpio22, Gpio23, Gpio3, Gpio8, Gpio9, + }, + Output, Pin, PinState, PushPull, + }, + Adc, Timer, +}; //#[cfg(debug_assertions)] //use panic_probe as _; use rp2040_panic_usb_boot as _; @@ -44,6 +59,151 @@ use heapless::String; use fl16_inputmodules::serialnum::device_release; +const MATRIX_COLS: usize = 16; +const MATRIX_ROWS: usize = 8; +const ADC_THRESHOLD: usize = 2900; + +struct Mux { + a: Pin>, + b: Pin>, + c: Pin>, + // TODO + // x: Pin>, +} +impl Mux { + pub fn select_row(&mut self, row: usize) { + let index = match row { + 0 => 2, + 1 => 0, + 2 => 1, + _ => row, + }; + self.a.set_state(PinState::from(index & 0x01 != 0)).unwrap(); + self.b.set_state(PinState::from(index & 0x02 != 0)).unwrap(); + self.c.set_state(PinState::from(index & 0x04 != 0)).unwrap(); + } +} + +#[derive(Debug, PartialEq, Eq, Clone, Default)] +pub struct Col(u8); +#[derive(Debug, PartialEq, Eq, Clone, Default)] +struct Matrix([Col; MATRIX_COLS]); + +impl Matrix { + pub fn set(&mut self, row: usize, col: usize, val: bool) { + let mask = 1 << row; + + self.0[col].0 = if val { + self.0[col].0 | mask + } else { + self.0[col].0 & !mask + }; + } +} + +impl Display for Col { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + for row in 0..MATRIX_ROWS { + let val = (self.0 & (1 << row)) >> row; + write!(f, "{:b}", val)? + } + Ok(()) + } +} + +type Kso = ( + Pin>, + Pin>, + Pin>, + Pin>, + Pin>, + Pin>, + Pin>, + Pin>, + Pin>, + Pin>, + Pin>, + Pin>, + Pin>, + Pin>, + Pin>, + Pin>, +); + +struct Scanner { + kso: Kso, + mux: Mux, + adc: (Adc, Pin>), +} +impl Scanner { + fn drive_col(&mut self, col: usize, state: PinState) { + match col { + 0 => self.kso.0.set_state(state).unwrap(), + 1 => self.kso.1.set_state(state).unwrap(), + 2 => self.kso.2.set_state(state).unwrap(), + 3 => self.kso.3.set_state(state).unwrap(), + 4 => self.kso.4.set_state(state).unwrap(), + 5 => self.kso.5.set_state(state).unwrap(), + 6 => self.kso.6.set_state(state).unwrap(), + 7 => self.kso.7.set_state(state).unwrap(), + 8 => self.kso.8.set_state(state).unwrap(), + 9 => self.kso.9.set_state(state).unwrap(), + 10 => self.kso.10.set_state(state).unwrap(), + 11 => self.kso.11.set_state(state).unwrap(), + 12 => self.kso.12.set_state(state).unwrap(), + 13 => self.kso.13.set_state(state).unwrap(), + 14 => self.kso.14.set_state(state).unwrap(), + 15 => self.kso.15.set_state(state).unwrap(), + _ => unreachable!(), + } + } + fn read_voltage(&mut self) -> usize { + let _adc_read: u16 = self.adc.0.read(&mut self.adc.1).unwrap(); + 33000 + } + pub fn measure_key(&mut self, row: usize, col: usize) -> (usize, usize) { + for col in 0..MATRIX_COLS { + self.drive_col(col, PinState::High); + } + self.drive_col(col, PinState::Low); + + self.mux.select_row(row); + cortex_m::asm::delay(2000); + let adc_read: u16 = self.adc.0.read(&mut self.adc.1).unwrap(); + + self.drive_col(col, PinState::High); + + let voltage_10k = ((adc_read as usize) * 3300) / 4096; + (voltage_10k / 1_000, voltage_10k % 1_000) + } + pub fn scan(&mut self) -> Matrix { + let mut matrix = Matrix::default(); + + // Initialize all cols as high + for col in 0..MATRIX_COLS { + self.drive_col(col, PinState::High); + } + + for col in 0..MATRIX_COLS { + self.drive_col(col, PinState::Low); + + for row in 0..MATRIX_ROWS { + self.mux.select_row(row); + + if self.read_voltage() < ADC_THRESHOLD { + matrix.set(row, col, true); + } + } + + self.drive_col(col, PinState::High); + } + + matrix.set(3, 4, true); + matrix.set(0, 4, true); + matrix + } +} + #[entry] fn main() -> ! { let mut pac = pac::Peripherals::take().unwrap(); @@ -121,7 +281,7 @@ fn main() -> ! { // Disable bootloader circuitry let mut boot_done = pins.boot_done.into_push_pull_output(); - boot_done.set_high().unwrap(); + boot_done.set_low().unwrap(); // pins.gp26 // SDA // pins.gp27 // SCL @@ -133,28 +293,28 @@ fn main() -> ! { // Pull low to enable mux let mut mux_enable = pins.mux_enable.into_push_pull_output(); mux_enable.set_low().unwrap(); - let mut _mux_a = pins.mux_a.into_push_pull_output(); - let mut _mux_b = pins.mux_b.into_push_pull_output(); - let mut _mux_c = pins.mux_c.into_push_pull_output(); + let mux_a = pins.mux_a.into_push_pull_output(); + let mux_b = pins.mux_b.into_push_pull_output(); + let mux_c = pins.mux_c.into_push_pull_output(); // KS0 - KSO7 for Keyboard and Numpad - let mut _kso0 = pins.kso0.into_push_pull_output(); - let mut _kso1 = pins.kso1.into_push_pull_output(); - let mut _kso2 = pins.kso2.into_push_pull_output(); - let mut _kso3 = pins.kso3.into_push_pull_output(); - let mut _kso4 = pins.kso4.into_push_pull_output(); - let mut _kso5 = pins.kso5.into_push_pull_output(); - let mut _kso6 = pins.kso6.into_push_pull_output(); - let mut _kso7 = pins.kso7.into_push_pull_output(); + let kso0 = pins.kso0.into_push_pull_output(); + let kso1 = pins.kso1.into_push_pull_output(); + let kso2 = pins.kso2.into_push_pull_output(); + let kso3 = pins.kso3.into_push_pull_output(); + let kso4 = pins.kso4.into_push_pull_output(); + let kso5 = pins.kso5.into_push_pull_output(); + let kso6 = pins.kso6.into_push_pull_output(); + let kso7 = pins.kso7.into_push_pull_output(); // KS08 - KS015 for Keyboard only - let mut _kso8 = pins.kso8.into_push_pull_output(); - let mut _kso9 = pins.kso9.into_push_pull_output(); - let mut _kso10 = pins.kso10.into_push_pull_output(); - let mut _kso11 = pins.kso11.into_push_pull_output(); - let mut _kso12 = pins.kso12.into_push_pull_output(); - let mut _kso13 = pins.kso13.into_push_pull_output(); - let mut _kso14 = pins.kso14.into_push_pull_output(); - let mut _kso15 = pins.kso15.into_push_pull_output(); + let kso8 = pins.kso8.into_push_pull_output(); + let kso9 = pins.kso9.into_push_pull_output(); + let kso10 = pins.kso10.into_push_pull_output(); + let kso11 = pins.kso11.into_push_pull_output(); + let kso12 = pins.kso12.into_push_pull_output(); + let kso13 = pins.kso13.into_push_pull_output(); + let kso14 = pins.kso14.into_push_pull_output(); + let kso15 = pins.kso15.into_push_pull_output(); // Set unused pins to input to avoid interfering. They're hooked up to rows 5 and 6 let _ = pins.ksi5_reserved.into_floating_input(); let _ = pins.ksi6_reserved.into_floating_input(); @@ -191,6 +351,22 @@ fn main() -> ! { let mut animation_timer = timer.get_counter().ticks(); caps_led.set_high().unwrap(); + let adc = Adc::new(pac.ADC, &mut pac.RESETS); + let adc_x = pins.analog_in.into_pull_up_input(); + + let mut scanner = Scanner { + kso: ( + kso0, kso1, kso2, kso3, kso4, kso5, kso6, kso7, kso8, kso9, kso10, kso11, kso12, kso13, + kso14, kso15, + ), + mux: Mux { + a: mux_a, + b: mux_b, + c: mux_c, + }, + adc: (adc, adc_x), + }; + let mut usb_initialized; let mut usb_suspended = false; loop { @@ -214,6 +390,23 @@ fn main() -> ! { animation_timer = timer.get_counter().ticks(); } + if timer.get_counter().ticks() > animation_timer + 500_000 { + let left = scanner.measure_key(6, 11); + let up = scanner.measure_key(1, 13); + let down = scanner.measure_key(1, 8); + let right = scanner.measure_key(2, 15); + let mut text: String<64> = String::new(); + write!( + &mut text, + "L:{}.{:0>4}V, R:{}.{:0>4}V, U:{}.{:0>4}V, D:{}.{:0>4}V\r\n", + left.0, left.1, right.0, right.1, up.0, up.1, down.0, down.1 + ) + .unwrap(); + let _ = serial.write(text.as_bytes()); + + animation_timer = timer.get_counter().ticks(); + } + // Check for new data if usb_dev.poll(&mut [&mut serial]) { match usb_dev.state() { @@ -239,6 +432,9 @@ fn main() -> ! { let _ = usb_initialized; let _ = usb_suspended; + let kb = Matrix::default(); + let kb = scanner.scan(); + let mut buf = [0u8; 64]; match serial.read(&mut buf) { Err(_e) => { @@ -247,15 +443,20 @@ fn main() -> ! { Ok(0) => { // Do nothing } - Ok(count) => { - let mut text: String<64> = String::new(); - write!( - &mut text, - "Hello World: Usb Suspended: {}. C: {}\r\n", - usb_suspended, count - ) - .unwrap(); - let _ = serial.write(text.as_bytes()); + Ok(_count) => { + match buf[0] { + b'r' => rp2040_hal::rom_data::reset_to_usb_boot(0, 0), + _ => (), + } + //let mut text: String<64> = String::new(); + //write!(&mut text, " 01234567\r\n").unwrap(); + //let _ = serial.write(text.as_bytes()); + + //for col in 0..MATRIX_COLS { + // let mut text: String<64> = String::new(); + // write!(&mut text, "{:2}: {}\r\n", col, kb.0[col]).unwrap(); + // let _ = serial.write(text.as_bytes()); + //} } } } else { From f1faa5b26a8dc65617da8d89d845738288796539 Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Sat, 30 Sep 2023 19:11:39 +0800 Subject: [PATCH 03/14] fixup! Implement basic keyboard firmware --- keyboard/Makefile.toml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/keyboard/Makefile.toml b/keyboard/Makefile.toml index ea7d5ecc..38bc921b 100644 --- a/keyboard/Makefile.toml +++ b/keyboard/Makefile.toml @@ -2,11 +2,18 @@ extend = "../Makefile.toml" [tasks.uf2] command = "elf2uf2-rs" -args = ["../target/thumbv6m-none-eabi/release/b1display", "../target/thumbv6m-none-eabi/release/b1display.uf2"] +args = [ + "../target/thumbv6m-none-eabi/release/keyboard", + "../target/thumbv6m-none-eabi/release/keyboard.uf2", +] dependencies = ["build-release"] install_crate = "elf2uf2-rs" [tasks.bin] command = "llvm-objcopy" -args = ["-Obinary", "../target/thumbv6m-none-eabi/release/b1display", "../target/thumbv6m-none-eabi/release/b1display.bin"] +args = [ + "-Obinary", + "../target/thumbv6m-none-eabi/release/keyboard", + "../target/thumbv6m-none-eabi/release/keyboard.bin", +] dependencies = ["build-release"] From 13d1cbd587961b1ebf1c6ae6958921c0ebb006b7 Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Sat, 30 Sep 2023 19:19:14 +0800 Subject: [PATCH 04/14] fixup! keyboard: Implement reading of arrow keys --- keyboard/src/main.rs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/keyboard/src/main.rs b/keyboard/src/main.rs index 306a8178..5c66ea0f 100644 --- a/keyboard/src/main.rs +++ b/keyboard/src/main.rs @@ -395,15 +395,30 @@ fn main() -> ! { let up = scanner.measure_key(1, 13); let down = scanner.measure_key(1, 8); let right = scanner.measure_key(2, 15); + let mut text: String<64> = String::new(); write!( &mut text, - "L:{}.{:0>4}V, R:{}.{:0>4}V, U:{}.{:0>4}V, D:{}.{:0>4}V\r\n", + "L:{}.{:0>3}V, R:{}.{:0>3}V, U:{}.{:0>3}V, D:{}.{:0>3}V\r\n", left.0, left.1, right.0, right.1, up.0, up.1, down.0, down.1 ) .unwrap(); let _ = serial.write(text.as_bytes()); + let left_p = left.0 < 2 || (left.0 == 2 && left.1 < 290); + let right_p = right.0 < 2 || (right.0 == 2 && right.1 < 290); + let up_p = up.0 < 2 || (up.0 == 2 && up.1 < 290); + let down_p = down.0 < 2 || (up.0 == 2 && down.1 < 290); + + let mut text: String<64> = String::new(); + write!( + &mut text, + "L:{:5}, R:{:5}, U:{:5}, D:{:5}\r\n", + left_p, right_p, up_p, down_p + ) + .unwrap(); + let _ = serial.write(text.as_bytes()); + animation_timer = timer.get_counter().ticks(); } From edbcb3069ef2336c80a33baea965d742ef622910 Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Sat, 30 Sep 2023 23:32:08 +0800 Subject: [PATCH 05/14] keyboard: Implement HID keyboard TODO: - [x] Basic keyscan - [x] Send UP/LEFT/RIGHT/CAPS HID reports, DOWN to go into bootloader - [x] Can go into D2 (tested on Linux) - [x] Can wake host (remote wakeup) - [ ] Both serial and HID keyboard as composite device - [ ] Key Debouncing - [ ] 1-Zone PWM backlight - [ ] RGB backlight (needs new/modified Rust driver) - [ ] Separate builds for different keyboard variants - [ ] Measure and optimize scan frequency - [ ] Implement full key matrix with all keys - [ ] Implement second layer for FN (including FN lock) - [ ] Persist brightness setting and FN lock through reset - [ ] Media keys Signed-off-by: Daniel Schaefer --- Cargo.lock | 134 ++++++++++++++++++++++++++++++++ keyboard/Cargo.toml | 2 + keyboard/src/main.rs | 180 +++++++++++++++++++++++++++++-------------- 3 files changed, 260 insertions(+), 56 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 774e65d0..a5b71157 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -280,6 +280,18 @@ version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "487f1e0fcbe47deb8b0574e646def1c903389d95241dd1bbcc6ce4a715dfc0c1" +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + [[package]] name = "bumpalo" version = "3.13.0" @@ -654,6 +666,17 @@ dependencies = [ "defmt", ] +[[package]] +name = "delegate" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d358e0ec5c59a5e1603b933def447096886121660fc680dc1e64a0753981fe3c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "either" version = "1.8.1" @@ -820,6 +843,45 @@ dependencies = [ "num-traits", ] +[[package]] +name = "frunk" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11a351b59e12f97b4176ee78497dff72e4276fb1ceb13e19056aca7fa0206287" +dependencies = [ + "frunk_core", + "frunk_derives", +] + +[[package]] +name = "frunk_core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af2469fab0bd07e64ccf0ad57a1438f63160c69b2e57f04a439653d68eb558d6" + +[[package]] +name = "frunk_derives" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fa992f1656e1707946bbba340ad244f0814009ef8c0118eb7b658395f19a2e" +dependencies = [ + "frunk_proc_macro_helpers", + "quote", + "syn 2.0.18", +] + +[[package]] +name = "frunk_proc_macro_helpers" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35b54add839292b743aeda6ebedbd8b11e93404f902c56223e51b9ec18a13d2c" +dependencies = [ + "frunk_core", + "proc-macro2", + "quote", + "syn 2.0.18", +] + [[package]] name = "fuchsia-cprng" version = "0.1.1" @@ -835,6 +897,12 @@ dependencies = [ "gcd", ] +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + [[package]] name = "gcd" version = "2.3.0" @@ -1106,6 +1174,7 @@ dependencies = [ "rp2040-panic-usb-boot", "usb-device", "usbd-hid", + "usbd-human-interface-device", "usbd-serial", ] @@ -1489,6 +1558,33 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +[[package]] +name = "option-block" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0f2c5d345596a14d7c8b032a68f437955f0059f2eb9a5972371c84f7eef3227" + +[[package]] +name = "packed_struct" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36b29691432cc9eff8b282278473b63df73bea49bc3ec5e67f31a3ae9c3ec190" +dependencies = [ + "bitvec", + "packed_struct_codegen", +] + +[[package]] +name = "packed_struct_codegen" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cd6706dfe50d53e0f6aa09e12c034c44faacd23e966ae5a209e8bdb8f179f98" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "parking_lot" version = "0.7.1" @@ -1644,6 +1740,12 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + [[package]] name = "rand" version = "0.6.5" @@ -2165,6 +2267,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + [[package]] name = "termcolor" version = "1.2.0" @@ -2334,6 +2442,23 @@ dependencies = [ "usbd-hid-descriptors", ] +[[package]] +name = "usbd-human-interface-device" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec9b21b68dbad6f411589e94b1b4e8792943959e8a99fdbc336f38cf4e5a3542" +dependencies = [ + "delegate", + "frunk", + "fugit", + "heapless", + "log", + "num_enum", + "option-block", + "packed_struct", + "usb-device", +] + [[package]] name = "usbd-serial" version = "0.1.1" @@ -2699,3 +2824,12 @@ dependencies = [ "rp2040-hal", "smart-leds-trait", ] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] diff --git a/keyboard/Cargo.toml b/keyboard/Cargo.toml index f16b1b94..7ee13d62 100644 --- a/keyboard/Cargo.toml +++ b/keyboard/Cargo.toml @@ -34,6 +34,8 @@ usbd-serial.workspace = true usbd-hid.workspace = true fugit.workspace = true +usbd-human-interface-device = "0.3.1" + [dependencies.fl16-inputmodules] path = "../fl16-inputmodules" features = ["keyboard"] diff --git a/keyboard/src/main.rs b/keyboard/src/main.rs index 5c66ea0f..81547fe2 100644 --- a/keyboard/src/main.rs +++ b/keyboard/src/main.rs @@ -4,6 +4,22 @@ #![no_main] #![allow(clippy::needless_range_loop)] +// TODO: +// - [x] Basic keyscan +// - [x] Send UP/LEFT/RIGHT/CAPS HID reports, DOWN to go into bootloader +// - [x] Can go into D2 (tested on Linux) +// - [x] Can wake host (remote wakeup) +// - [ ] Both serial and HID keyboard as composite device +// - [ ] Key Debouncing +// - [ ] 1-Zone PWM backlight +// - [ ] RGB backlight (needs new/modified Rust driver) +// - [ ] Separate builds for different keyboard variants +// - [ ] Measure and optimize scan frequency +// - [ ] Implement full key matrix with all keys +// - [ ] Implement second layer for FN (including FN lock) +// - [ ] Persist brightness setting and FN lock through reset +// - [ ] Media keys + //use cortex_m::delay::Delay; //use defmt::*; use defmt_rtt as _; @@ -11,6 +27,10 @@ use embedded_hal::adc::OneShot; use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin}; use rp2040_hal::gpio::bank0::Gpio28; use rp2040_hal::gpio::{Input, PullUp}; +use usbd_human_interface_device::device::keyboard::BootKeyboardInterface; +use usbd_human_interface_device::page::Keyboard; +use usbd_human_interface_device::prelude::UsbHidClassBuilder; +use usbd_human_interface_device::UsbHidError; use core::fmt::Display; use core::fmt::{self, Formatter}; @@ -168,6 +188,7 @@ impl Scanner { self.drive_col(col, PinState::Low); self.mux.select_row(row); + // Let column and mux settle a bit cortex_m::asm::delay(2000); let adc_read: u16 = self.adc.0.read(&mut self.adc.1).unwrap(); @@ -245,7 +266,10 @@ fn main() -> ! { )); // Set up the USB Communications Class Device driver - let mut serial = SerialPort::new(&usb_bus); + //let mut serial = SerialPort::new(&usb_bus); + let mut keyboard_hid = UsbHidClassBuilder::new() + .add_interface(BootKeyboardInterface::default_config()) + .build(&usb_bus); #[cfg(feature = "macropad")] let pid = 0x013; @@ -272,8 +296,10 @@ fn main() -> ! { let mut usb_dev = UsbDeviceBuilder::new(&usb_bus, UsbVidPid(0x32ac, pid)) .manufacturer("Framework Computer Inc") .product(product) - //.supports_remote_wakeup(true) - .device_class(USB_CLASS_CDC) + .supports_remote_wakeup(true) + .device_class(0) + .device_sub_class(0) + .device_protocol(0) .max_power(MAX_CURRENT) .serial_number("testing") .device_release(device_release()) @@ -285,7 +311,6 @@ fn main() -> ! { // pins.gp26 // SDA // pins.gp27 // SCL - // pins.analog_in let mut caps_led = pins.caps_led.into_push_pull_output(); let mut _backlight = pins.backlight.into_push_pull_output(); @@ -348,7 +373,8 @@ fn main() -> ! { // fill_grid_pixels(&state, &mut matrix); let timer = Timer::new(pac.TIMER, &mut pac.RESETS); - let mut animation_timer = timer.get_counter().ticks(); + let mut scan_timer = timer.get_counter().ticks(); + let mut capslock_timer = timer.get_counter().ticks(); caps_led.set_high().unwrap(); let adc = Adc::new(pac.ADC, &mut pac.RESETS); @@ -381,49 +407,89 @@ fn main() -> ! { // Blink when in USB Suspend // 500_000us = 500ms = 0.5s - if usb_suspended && timer.get_counter().ticks() > animation_timer + 500_000 { + if usb_suspended && timer.get_counter().ticks() > capslock_timer + 500_000 { if caps_led.is_set_high().unwrap() { caps_led.set_low().unwrap(); } else { caps_led.set_high().unwrap(); } - animation_timer = timer.get_counter().ticks(); + capslock_timer = timer.get_counter().ticks(); } - if timer.get_counter().ticks() > animation_timer + 500_000 { + let mut keycode: Option = None; + if timer.get_counter().ticks() > scan_timer + 250_000 { let left = scanner.measure_key(6, 11); let up = scanner.measure_key(1, 13); let down = scanner.measure_key(1, 8); let right = scanner.measure_key(2, 15); + let caps = scanner.measure_key(4, 4); - let mut text: String<64> = String::new(); - write!( - &mut text, - "L:{}.{:0>3}V, R:{}.{:0>3}V, U:{}.{:0>3}V, D:{}.{:0>3}V\r\n", - left.0, left.1, right.0, right.1, up.0, up.1, down.0, down.1 - ) - .unwrap(); - let _ = serial.write(text.as_bytes()); + // let mut text: String<64> = String::new(); + // write!( + // &mut text, + // "L:{}.{:0>3}V, R:{}.{:0>3}V, U:{}.{:0>3}V, D:{}.{:0>3}V\r\n", + // left.0, left.1, right.0, right.1, up.0, up.1, down.0, down.1 + // ) + // .unwrap(); + // let _ = serial.write(text.as_bytes()); let left_p = left.0 < 2 || (left.0 == 2 && left.1 < 290); let right_p = right.0 < 2 || (right.0 == 2 && right.1 < 290); let up_p = up.0 < 2 || (up.0 == 2 && up.1 < 290); - let down_p = down.0 < 2 || (up.0 == 2 && down.1 < 290); - - let mut text: String<64> = String::new(); - write!( - &mut text, - "L:{:5}, R:{:5}, U:{:5}, D:{:5}\r\n", - left_p, right_p, up_p, down_p - ) - .unwrap(); - let _ = serial.write(text.as_bytes()); - - animation_timer = timer.get_counter().ticks(); + let down_p = down.0 < 2 || (down.0 == 2 && down.1 < 290); + let caps_p = caps.0 < 2 || (caps.0 == 2 && caps.1 < 290); + + // let mut text: String<64> = String::new(); + // write!( + // &mut text, + // "L:{:5}, R:{:5}, U:{:5}, D:{:5}\r\n", + // left_p, right_p, up_p, down_p + // ) + // .unwrap(); + // let _ = serial.write(text.as_bytes()); + + if left_p { + keycode = Some(Keyboard::LeftArrow); + } else if right_p { + keycode = Some(Keyboard::RightArrow); + } else if up_p { + keycode = Some(Keyboard::UpArrow); + } else if down_p { + keycode = None; + rp2040_hal::rom_data::reset_to_usb_boot(0, 0); + } else if caps_p { + keycode = Some(Keyboard::CapsLock); + } else { + keycode = None; + } + + scan_timer = timer.get_counter().ticks(); + } + + let _ = keyboard_hid.interface().read_report(); + + // Setup the report for the control channel + let keycodes = if let Some(keycode) = keycode { + [keycode] + } else { + [Keyboard::NoEventIndicated] + }; + match keyboard_hid.interface().write_report(keycodes) { + Err(UsbHidError::WouldBlock) | Err(UsbHidError::Duplicate) | Ok(_) => {} + Err(e) => panic!("Failed to write keyboard report: {:?}", e), + } + match keyboard_hid.interface().tick() { + Err(UsbHidError::WouldBlock) | Ok(_) => {} + Err(e) => panic!("Failed to process keyboard tick: {:?}", e), + } + + // Wake the host. + if keycode.is_some() && usb_suspended && usb_dev.remote_wakeup_enabled() { + usb_dev.bus().remote_wakeup(); } // Check for new data - if usb_dev.poll(&mut [&mut serial]) { + if usb_dev.poll(&mut [&mut keyboard_hid]) { match usb_dev.state() { // Default: Device has just been created or reset // Addressed: Device has received an address for the host @@ -447,33 +513,35 @@ fn main() -> ! { let _ = usb_initialized; let _ = usb_suspended; - let kb = Matrix::default(); - let kb = scanner.scan(); - - let mut buf = [0u8; 64]; - match serial.read(&mut buf) { - Err(_e) => { - // Do nothing - } - Ok(0) => { - // Do nothing - } - Ok(_count) => { - match buf[0] { - b'r' => rp2040_hal::rom_data::reset_to_usb_boot(0, 0), - _ => (), - } - //let mut text: String<64> = String::new(); - //write!(&mut text, " 01234567\r\n").unwrap(); - //let _ = serial.write(text.as_bytes()); - - //for col in 0..MATRIX_COLS { - // let mut text: String<64> = String::new(); - // write!(&mut text, "{:2}: {}\r\n", col, kb.0[col]).unwrap(); - // let _ = serial.write(text.as_bytes()); - //} - } - } + //let kb = Matrix::default(); + //let kb = scanner.scan(); + + keyboard_hid.poll(); + + // let mut buf = [0u8; 64]; + // match serial.read(&mut buf) { + // Err(_e) => { + // // Do nothing + // } + // Ok(0) => { + // // Do nothing + // } + // Ok(_count) => { + // match buf[0] { + // b'r' => rp2040_hal::rom_data::reset_to_usb_boot(0, 0), + // _ => (), + // } + // //let mut text: String<64> = String::new(); + // //write!(&mut text, " 01234567\r\n").unwrap(); + // //let _ = serial.write(text.as_bytes()); + + // //for col in 0..MATRIX_COLS { + // // let mut text: String<64> = String::new(); + // // write!(&mut text, "{:2}: {}\r\n", col, kb.0[col]).unwrap(); + // // let _ = serial.write(text.as_bytes()); + // //} + // } + // } } else { match usb_dev.state() { // No new data From 8d9f343be20ab046f2a2dc28b8b3e850e477744b Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Sun, 1 Oct 2023 00:22:40 +0800 Subject: [PATCH 06/14] keyboard: Light up RGB backlight Just all white Signed-off-by: Daniel Schaefer --- Cargo.lock | 5 ++-- Cargo.toml | 2 +- keyboard/Cargo.toml | 1 + keyboard/src/main.rs | 61 +++++++++++++++++++++++++------------------- 4 files changed, 40 insertions(+), 29 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a5b71157..346f7829 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1089,8 +1089,8 @@ dependencies = [ [[package]] name = "is31fl3741" -version = "0.2.1" -source = "git+https://github.com/FrameworkComputer/is31fl3741-rs?branch=sw-enablement#fb88ad1baf28aa2a61bc85ff5db83c6e2b661ed5" +version = "0.2.2" +source = "git+https://github.com/FrameworkComputer/is31fl3741-rs?branch=is31fl3743a#1814f6a838560c7553cda34cdad4692dc5da2d5f" dependencies = [ "embedded-graphics-core", "embedded-hal", @@ -1169,6 +1169,7 @@ dependencies = [ "fl16-inputmodules", "fugit", "heapless", + "is31fl3741", "rp2040-boot2", "rp2040-hal", "rp2040-panic-usb-boot", diff --git a/Cargo.toml b/Cargo.toml index 09867579..bddff02a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,7 +40,7 @@ usbd-serial = "0.1.1" usbd-hid = "0.6.1" fugit = "0.3.7" # LED Matrix -is31fl3741 = { git = "https://github.com/FrameworkComputer/is31fl3741-rs", branch = "sw-enablement" } +is31fl3741 = { git = "https://github.com/FrameworkComputer/is31fl3741-rs", branch = "is31fl3743a" } # B1 Display st7306 = { git = "https://github.com/FrameworkComputer/st7306-rs", branch = "update-deps" } embedded-graphics = "0.8" diff --git a/keyboard/Cargo.toml b/keyboard/Cargo.toml index 7ee13d62..51fc93e5 100644 --- a/keyboard/Cargo.toml +++ b/keyboard/Cargo.toml @@ -35,6 +35,7 @@ usbd-hid.workspace = true fugit.workspace = true usbd-human-interface-device = "0.3.1" +is31fl3741.workspace = true [dependencies.fl16-inputmodules] path = "../fl16-inputmodules" diff --git a/keyboard/src/main.rs b/keyboard/src/main.rs index 81547fe2..edb9bf8b 100644 --- a/keyboard/src/main.rs +++ b/keyboard/src/main.rs @@ -12,7 +12,9 @@ // - [ ] Both serial and HID keyboard as composite device // - [ ] Key Debouncing // - [ ] 1-Zone PWM backlight -// - [ ] RGB backlight (needs new/modified Rust driver) +// - [x] RGB backlight (needs new/modified Rust driver) +// - [x] Working (all white) +// - [ ] Map all LEDs // - [ ] Separate builds for different keyboard variants // - [ ] Measure and optimize scan frequency // - [ ] Implement full key matrix with all keys @@ -22,16 +24,19 @@ //use cortex_m::delay::Delay; //use defmt::*; +use crate::rgb_matrix::{LedMatrix, DVT2_CALC_PIXEL}; use defmt_rtt as _; use embedded_hal::adc::OneShot; use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin}; use rp2040_hal::gpio::bank0::Gpio28; -use rp2040_hal::gpio::{Input, PullUp}; +use rp2040_hal::gpio::{self, Input, PullUp}; use usbd_human_interface_device::device::keyboard::BootKeyboardInterface; use usbd_human_interface_device::page::Keyboard; use usbd_human_interface_device::prelude::UsbHidClassBuilder; use usbd_human_interface_device::UsbHidError; +mod rgb_matrix; + use core::fmt::Display; use core::fmt::{self, Formatter}; @@ -66,6 +71,7 @@ use bsp::hal::{ usb, watchdog::Watchdog, }; +use fugit::RateExtU32; // USB Device support use usb_device::{class_prelude::*, prelude::*}; @@ -247,7 +253,7 @@ fn main() -> ! { let rosc = rp2040_hal::rosc::RingOscillator::new(pac.ROSC); let _rosc = rosc.initialize(); - let mut _delay = cortex_m::delay::Delay::new(core.SYST, clocks.system_clock.freq().to_Hz()); + let mut delay = cortex_m::delay::Delay::new(core.SYST, clocks.system_clock.freq().to_Hz()); let pins = bsp::Pins::new( pac.IO_BANK0, @@ -347,30 +353,33 @@ fn main() -> ! { let sleep = pins.sleep.into_floating_input(); // Enable LED controller - // SDB let mut led_enable = pins.sdb.into_push_pull_output(); - led_enable.set_low().unwrap(); - // led_enable.set_high().unwrap(); - // - // let i2c = bsp::hal::I2C::i2c1( - // pac.I2C1, - // pins.gpio26.into_mode::(), - // pins.gpio27.into_mode::(), - // 1000.kHz(), - // &mut pac.RESETS, - // &clocks.peripheral_clock, - // ); - // - // let mut matrix = LedMatrix::new(i2c, DVT2_CALC_PIXEL); - // matrix - // .setup(&mut delay) - // .expect("failed to setup RGB controller"); - // - // matrix - // .set_scaling(MAX_BRIGHTNESS) - // .expect("failed to set scaling"); - // - // fill_grid_pixels(&state, &mut matrix); + led_enable.set_high().unwrap(); + + let i2c = bsp::hal::I2C::i2c1( + pac.I2C1, + pins.gpio26.into_mode::(), + pins.gpio27.into_mode::(), + 1000.kHz(), + &mut pac.RESETS, + &clocks.peripheral_clock, + ); + + let mut matrix = LedMatrix::new(i2c, DVT2_CALC_PIXEL); + + matrix.set_address(0b0100000); + matrix + .setup(&mut delay) + .expect("failed to setup RGB controller"); + matrix.set_scaling(0xFF).expect("failed to set scaling"); + matrix.device.fill(0xFF); + + matrix.set_address(0b0100011); + matrix + .setup(&mut delay) + .expect("failed to setup RGB controller"); + matrix.set_scaling(0xFF).expect("failed to set scaling"); + matrix.device.fill(0xFF); let timer = Timer::new(pac.TIMER, &mut pac.RESETS); let mut scan_timer = timer.get_counter().ticks(); From ecab28b6896079fad6cdab7ef0e8e8de72231a37 Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Sun, 1 Oct 2023 13:13:31 +0800 Subject: [PATCH 07/14] keyboard: Avoid HID activity in USB suspend Signed-off-by: Daniel Schaefer --- keyboard/src/main.rs | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/keyboard/src/main.rs b/keyboard/src/main.rs index edb9bf8b..53826cfb 100644 --- a/keyboard/src/main.rs +++ b/keyboard/src/main.rs @@ -475,21 +475,23 @@ fn main() -> ! { scan_timer = timer.get_counter().ticks(); } - let _ = keyboard_hid.interface().read_report(); + if !usb_suspended { + let _ = keyboard_hid.interface().read_report(); - // Setup the report for the control channel - let keycodes = if let Some(keycode) = keycode { - [keycode] - } else { - [Keyboard::NoEventIndicated] - }; - match keyboard_hid.interface().write_report(keycodes) { - Err(UsbHidError::WouldBlock) | Err(UsbHidError::Duplicate) | Ok(_) => {} - Err(e) => panic!("Failed to write keyboard report: {:?}", e), - } - match keyboard_hid.interface().tick() { - Err(UsbHidError::WouldBlock) | Ok(_) => {} - Err(e) => panic!("Failed to process keyboard tick: {:?}", e), + // Setup the report for the control channel + let keycodes = if let Some(keycode) = keycode { + [keycode] + } else { + [Keyboard::NoEventIndicated] + }; + match keyboard_hid.interface().write_report(keycodes) { + Err(UsbHidError::WouldBlock) | Err(UsbHidError::Duplicate) | Ok(_) => {} + Err(e) => panic!("Failed to write keyboard report: {:?}", e), + } + match keyboard_hid.interface().tick() { + Err(UsbHidError::WouldBlock) | Ok(_) => {} + Err(e) => panic!("Failed to process keyboard tick: {:?}", e), + } } // Wake the host. From 246b8553db61e881d039b472d9b60eb6fa746f54 Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Sun, 1 Oct 2023 18:13:24 +0800 Subject: [PATCH 08/14] keyboard: Move HID code into USB poll Automatically handles not doing anything if in USB suspend. Signed-off-by: Daniel Schaefer --- keyboard/src/main.rs | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/keyboard/src/main.rs b/keyboard/src/main.rs index 53826cfb..c91709b7 100644 --- a/keyboard/src/main.rs +++ b/keyboard/src/main.rs @@ -475,25 +475,6 @@ fn main() -> ! { scan_timer = timer.get_counter().ticks(); } - if !usb_suspended { - let _ = keyboard_hid.interface().read_report(); - - // Setup the report for the control channel - let keycodes = if let Some(keycode) = keycode { - [keycode] - } else { - [Keyboard::NoEventIndicated] - }; - match keyboard_hid.interface().write_report(keycodes) { - Err(UsbHidError::WouldBlock) | Err(UsbHidError::Duplicate) | Ok(_) => {} - Err(e) => panic!("Failed to write keyboard report: {:?}", e), - } - match keyboard_hid.interface().tick() { - Err(UsbHidError::WouldBlock) | Ok(_) => {} - Err(e) => panic!("Failed to process keyboard tick: {:?}", e), - } - } - // Wake the host. if keycode.is_some() && usb_suspended && usb_dev.remote_wakeup_enabled() { usb_dev.bus().remote_wakeup(); @@ -527,7 +508,22 @@ fn main() -> ! { //let kb = Matrix::default(); //let kb = scanner.scan(); - keyboard_hid.poll(); + let _ = keyboard_hid.interface().read_report(); + + // Setup the report for the control channel + let keycodes = if let Some(keycode) = keycode { + [keycode] + } else { + [Keyboard::NoEventIndicated] + }; + match keyboard_hid.interface().write_report(keycodes) { + Err(UsbHidError::WouldBlock) | Err(UsbHidError::Duplicate) | Ok(_) => {} + Err(e) => panic!("Failed to write keyboard report: {:?}", e), + } + match keyboard_hid.interface().tick() { + Err(UsbHidError::WouldBlock) | Ok(_) => {} + Err(e) => panic!("Failed to process keyboard tick: {:?}", e), + } // let mut buf = [0u8; 64]; // match serial.read(&mut buf) { From 5dedf230100dd8eeae13a2650fdf2228c7a65682 Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Tue, 3 Oct 2023 11:46:51 +0800 Subject: [PATCH 09/14] Revert "keyboard: Move HID code into USB poll" This reverts commit 246b8553db61e881d039b472d9b60eb6fa746f54. --- keyboard/src/main.rs | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/keyboard/src/main.rs b/keyboard/src/main.rs index c91709b7..53826cfb 100644 --- a/keyboard/src/main.rs +++ b/keyboard/src/main.rs @@ -475,6 +475,25 @@ fn main() -> ! { scan_timer = timer.get_counter().ticks(); } + if !usb_suspended { + let _ = keyboard_hid.interface().read_report(); + + // Setup the report for the control channel + let keycodes = if let Some(keycode) = keycode { + [keycode] + } else { + [Keyboard::NoEventIndicated] + }; + match keyboard_hid.interface().write_report(keycodes) { + Err(UsbHidError::WouldBlock) | Err(UsbHidError::Duplicate) | Ok(_) => {} + Err(e) => panic!("Failed to write keyboard report: {:?}", e), + } + match keyboard_hid.interface().tick() { + Err(UsbHidError::WouldBlock) | Ok(_) => {} + Err(e) => panic!("Failed to process keyboard tick: {:?}", e), + } + } + // Wake the host. if keycode.is_some() && usb_suspended && usb_dev.remote_wakeup_enabled() { usb_dev.bus().remote_wakeup(); @@ -508,22 +527,7 @@ fn main() -> ! { //let kb = Matrix::default(); //let kb = scanner.scan(); - let _ = keyboard_hid.interface().read_report(); - - // Setup the report for the control channel - let keycodes = if let Some(keycode) = keycode { - [keycode] - } else { - [Keyboard::NoEventIndicated] - }; - match keyboard_hid.interface().write_report(keycodes) { - Err(UsbHidError::WouldBlock) | Err(UsbHidError::Duplicate) | Ok(_) => {} - Err(e) => panic!("Failed to write keyboard report: {:?}", e), - } - match keyboard_hid.interface().tick() { - Err(UsbHidError::WouldBlock) | Ok(_) => {} - Err(e) => panic!("Failed to process keyboard tick: {:?}", e), - } + keyboard_hid.poll(); // let mut buf = [0u8; 64]; // match serial.read(&mut buf) { From e2e7b32b74f533c3dfe05221dc323fe31f137e73 Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Tue, 24 Oct 2023 01:09:47 +0800 Subject: [PATCH 10/14] keyboard: Separate build per variant ``` > cargo run -p keyboard --features ansi > cargo run -p keyboard --features numpad > cargo run -p keyboard --features macropad ``` Signed-off-by: Daniel Schaefer --- Cargo.lock | 1 + keyboard/Cargo.toml | 2 + keyboard/src/main.rs | 132 +++++++++++++++++++++++++------------------ 3 files changed, 79 insertions(+), 56 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 346f7829..3807d72b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1161,6 +1161,7 @@ dependencies = [ name = "keyboard" version = "0.1.7" dependencies = [ + "cfg-if", "cortex-m", "cortex-m-rt", "defmt", diff --git a/keyboard/Cargo.toml b/keyboard/Cargo.toml index 51fc93e5..9ed709b2 100644 --- a/keyboard/Cargo.toml +++ b/keyboard/Cargo.toml @@ -37,6 +37,8 @@ fugit.workspace = true usbd-human-interface-device = "0.3.1" is31fl3741.workspace = true +cfg-if = "1.0.0" + [dependencies.fl16-inputmodules] path = "../fl16-inputmodules" features = ["keyboard"] diff --git a/keyboard/src/main.rs b/keyboard/src/main.rs index 53826cfb..e4b67611 100644 --- a/keyboard/src/main.rs +++ b/keyboard/src/main.rs @@ -367,19 +367,27 @@ fn main() -> ! { let mut matrix = LedMatrix::new(i2c, DVT2_CALC_PIXEL); - matrix.set_address(0b0100000); - matrix - .setup(&mut delay) - .expect("failed to setup RGB controller"); - matrix.set_scaling(0xFF).expect("failed to set scaling"); - matrix.device.fill(0xFF); - - matrix.set_address(0b0100011); - matrix - .setup(&mut delay) - .expect("failed to setup RGB controller"); - matrix.set_scaling(0xFF).expect("failed to set scaling"); - matrix.device.fill(0xFF); + cfg_if::cfg_if! { + if #[cfg(any(feature = "ansi", feature = "macropad"))] { + matrix.set_address(0b0100000); + matrix + .setup(&mut delay) + .expect("failed to setup RGB controller"); + matrix.set_scaling(0xFF).expect("failed to set scaling"); + matrix.device.fill(0xFF); + } + } + + cfg_if::cfg_if! { + if #[cfg(feature = "ansi")] { + matrix.set_address(0b0100011); + matrix + .setup(&mut delay) + .expect("failed to setup RGB controller"); + matrix.set_scaling(0xFF).expect("failed to set scaling"); + matrix.device.fill(0xFF); + } + } let timer = Timer::new(pac.TIMER, &mut pac.RESETS); let mut scan_timer = timer.get_counter().ticks(); @@ -427,49 +435,61 @@ fn main() -> ! { let mut keycode: Option = None; if timer.get_counter().ticks() > scan_timer + 250_000 { - let left = scanner.measure_key(6, 11); - let up = scanner.measure_key(1, 13); - let down = scanner.measure_key(1, 8); - let right = scanner.measure_key(2, 15); - let caps = scanner.measure_key(4, 4); - - // let mut text: String<64> = String::new(); - // write!( - // &mut text, - // "L:{}.{:0>3}V, R:{}.{:0>3}V, U:{}.{:0>3}V, D:{}.{:0>3}V\r\n", - // left.0, left.1, right.0, right.1, up.0, up.1, down.0, down.1 - // ) - // .unwrap(); - // let _ = serial.write(text.as_bytes()); - - let left_p = left.0 < 2 || (left.0 == 2 && left.1 < 290); - let right_p = right.0 < 2 || (right.0 == 2 && right.1 < 290); - let up_p = up.0 < 2 || (up.0 == 2 && up.1 < 290); - let down_p = down.0 < 2 || (down.0 == 2 && down.1 < 290); - let caps_p = caps.0 < 2 || (caps.0 == 2 && caps.1 < 290); - - // let mut text: String<64> = String::new(); - // write!( - // &mut text, - // "L:{:5}, R:{:5}, U:{:5}, D:{:5}\r\n", - // left_p, right_p, up_p, down_p - // ) - // .unwrap(); - // let _ = serial.write(text.as_bytes()); - - if left_p { - keycode = Some(Keyboard::LeftArrow); - } else if right_p { - keycode = Some(Keyboard::RightArrow); - } else if up_p { - keycode = Some(Keyboard::UpArrow); - } else if down_p { - keycode = None; - rp2040_hal::rom_data::reset_to_usb_boot(0, 0); - } else if caps_p { - keycode = Some(Keyboard::CapsLock); - } else { - keycode = None; + cfg_if::cfg_if! { + if #[cfg(any(feature = "ansi", feature = "iso", feature = "jis"))] { + let left = scanner.measure_key(6, 11); + let up = scanner.measure_key(1, 13); + let down = scanner.measure_key(1, 8); + let right = scanner.measure_key(2, 15); + let caps = scanner.measure_key(4, 4); + + let left_p = left.0 < 2 || (left.0 == 2 && left.1 < 290); + let right_p = right.0 < 2 || (right.0 == 2 && right.1 < 290); + let up_p = up.0 < 2 || (up.0 == 2 && up.1 < 290); + let down_p = down.0 < 2 || (down.0 == 2 && down.1 < 290); + let caps_p = caps.0 < 2 || (caps.0 == 2 && caps.1 < 290); + + if left_p { + keycode = Some(Keyboard::LeftArrow); + } else if right_p { + keycode = Some(Keyboard::RightArrow); + } else if up_p { + keycode = Some(Keyboard::UpArrow); + } else if down_p { + keycode = None; + rp2040_hal::rom_data::reset_to_usb_boot(0, 0); + } else if caps_p { + keycode = Some(Keyboard::CapsLock); + } else { + keycode = None; + } + } + } + + cfg_if::cfg_if! { + if #[cfg(any(feature = "numapd", feature = "macropad"))] { + let one = scanner.measure_key(0, 3); + let two = scanner.measure_key(0, 7); + let three = scanner.measure_key(1, 4); + let four = scanner.measure_key(2, 6); + + let one_p = one.0 < 2 || (one.0 == 2 && one.1 < 290); + let two_p = two.0 < 2 || (two.0 == 2 && two.1 < 290); + let three_p = three.0 < 2 || (three.0 == 2 && three.1 < 290); + let four_p = four.0 < 2 || (four.0 == 2 && four.1 < 290); + + if one_p { + keycode = Some(Keyboard::Keyboard1); + } else if two_p { + keycode = Some(Keyboard::Keyboard2); + } else if three_p { + keycode = Some(Keyboard::Keyboard3); + } else if four_p { + keycode = Some(Keyboard::Keyboard4); + } else { + keycode = None; + } + } } scan_timer = timer.get_counter().ticks(); From e822d1db01694c75ba185a7ca00ae8fee6e2d0cd Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Tue, 24 Oct 2023 01:11:14 +0800 Subject: [PATCH 11/14] fixup! keyboard: Light up RGB backlight --- keyboard/src/rgb_matrix.rs | 377 +++++++++++++++++++++++++++++++++++++ 1 file changed, 377 insertions(+) create mode 100644 keyboard/src/rgb_matrix.rs diff --git a/keyboard/src/rgb_matrix.rs b/keyboard/src/rgb_matrix.rs new file mode 100644 index 00000000..3b077022 --- /dev/null +++ b/keyboard/src/rgb_matrix.rs @@ -0,0 +1,377 @@ +// #[cfg_attr(docsrs, doc(cfg(feature = "adafruit_rgb_13x9")))] +#[allow(unused_imports)] +use core::convert::TryFrom; +#[allow(unused_imports)] +use embedded_hal::blocking::delay::DelayMs; +use embedded_hal::blocking::i2c::Read; +use embedded_hal::blocking::i2c::Write; +#[allow(unused_imports)] +use is31fl3741::{Error, IS31FL3743}; + +pub const DVT2_CALC_PIXEL: fn(x: u8, y: u8) -> (u8, u8) = |x: u8, y: u8| -> (u8, u8) { + // Generated by led-matrix.py + let lookup: [(u8, u8); 34 * 9] = [ + (0x00, 0), // x: 1, y: 1, sw: 1, cs: 1, id: 1 + (0x1e, 0), // x: 2, y: 1, sw: 2, cs: 1, id: 2 + (0x3c, 0), // x: 3, y: 1, sw: 3, cs: 1, id: 3 + (0x5a, 0), // x: 4, y: 1, sw: 4, cs: 1, id: 4 + (0x78, 0), // x: 5, y: 1, sw: 5, cs: 1, id: 5 + (0x96, 0), // x: 6, y: 1, sw: 6, cs: 1, id: 6 + (0x00, 1), // x: 7, y: 1, sw: 7, cs: 1, id: 7 + (0x1e, 1), // x: 8, y: 1, sw: 8, cs: 1, id: 8 + (0x5f, 1), // x: 9, y: 1, sw: 1, cs:36, id: 9 + (0x01, 0), // x: 1, y: 2, sw: 1, cs: 2, id: 10 + (0x1f, 0), // x: 2, y: 2, sw: 2, cs: 2, id: 11 + (0x3d, 0), // x: 3, y: 2, sw: 3, cs: 2, id: 12 + (0x5b, 0), // x: 4, y: 2, sw: 4, cs: 2, id: 13 + (0x79, 0), // x: 5, y: 2, sw: 5, cs: 2, id: 14 + (0x97, 0), // x: 6, y: 2, sw: 6, cs: 2, id: 15 + (0x01, 1), // x: 7, y: 2, sw: 7, cs: 2, id: 16 + (0x1f, 1), // x: 8, y: 2, sw: 8, cs: 2, id: 17 + (0x60, 1), // x: 9, y: 2, sw: 1, cs:37, id: 18 + (0x02, 0), // x: 1, y: 3, sw: 1, cs: 3, id: 19 + (0x20, 0), // x: 2, y: 3, sw: 2, cs: 3, id: 20 + (0x3e, 0), // x: 3, y: 3, sw: 3, cs: 3, id: 21 + (0x5c, 0), // x: 4, y: 3, sw: 4, cs: 3, id: 22 + (0x7a, 0), // x: 5, y: 3, sw: 5, cs: 3, id: 23 + (0x98, 0), // x: 6, y: 3, sw: 6, cs: 3, id: 24 + (0x02, 1), // x: 7, y: 3, sw: 7, cs: 3, id: 25 + (0x20, 1), // x: 8, y: 3, sw: 8, cs: 3, id: 26 + (0x61, 1), // x: 9, y: 3, sw: 1, cs:38, id: 27 + (0x03, 0), // x: 1, y: 4, sw: 1, cs: 4, id: 28 + (0x21, 0), // x: 2, y: 4, sw: 2, cs: 4, id: 29 + (0x3f, 0), // x: 3, y: 4, sw: 3, cs: 4, id: 30 + (0x5d, 0), // x: 4, y: 4, sw: 4, cs: 4, id: 31 + (0x7b, 0), // x: 5, y: 4, sw: 5, cs: 4, id: 32 + (0x99, 0), // x: 6, y: 4, sw: 6, cs: 4, id: 33 + (0x03, 1), // x: 7, y: 4, sw: 7, cs: 4, id: 34 + (0x21, 1), // x: 8, y: 4, sw: 8, cs: 4, id: 35 + (0x62, 1), // x: 9, y: 4, sw: 1, cs:39, id: 36 + (0x04, 0), // x: 1, y: 5, sw: 1, cs: 5, id: 37 + (0x22, 0), // x: 2, y: 5, sw: 2, cs: 5, id: 41 + (0x40, 0), // x: 3, y: 5, sw: 3, cs: 5, id: 45 + (0x5e, 0), // x: 4, y: 5, sw: 4, cs: 5, id: 49 + (0x7c, 0), // x: 5, y: 5, sw: 5, cs: 5, id: 53 + (0x9a, 0), // x: 6, y: 5, sw: 6, cs: 5, id: 57 + (0x04, 1), // x: 7, y: 5, sw: 7, cs: 5, id: 61 + (0x22, 1), // x: 8, y: 5, sw: 8, cs: 5, id: 65 + (0x5e, 1), // x: 9, y: 5, sw: 1, cs:35, id: 69 + (0x05, 0), // x: 1, y: 6, sw: 1, cs: 6, id: 38 + (0x23, 0), // x: 2, y: 6, sw: 2, cs: 6, id: 42 + (0x41, 0), // x: 3, y: 6, sw: 3, cs: 6, id: 46 + (0x5f, 0), // x: 4, y: 6, sw: 4, cs: 6, id: 50 + (0x7d, 0), // x: 5, y: 6, sw: 5, cs: 6, id: 54 + (0x9b, 0), // x: 6, y: 6, sw: 6, cs: 6, id: 58 + (0x05, 1), // x: 7, y: 6, sw: 7, cs: 6, id: 62 + (0x23, 1), // x: 8, y: 6, sw: 8, cs: 6, id: 66 + (0x68, 1), // x: 9, y: 6, sw: 2, cs:36, id: 70 + (0x06, 0), // x: 1, y: 7, sw: 1, cs: 7, id: 39 + (0x24, 0), // x: 2, y: 7, sw: 2, cs: 7, id: 43 + (0x42, 0), // x: 3, y: 7, sw: 3, cs: 7, id: 47 + (0x60, 0), // x: 4, y: 7, sw: 4, cs: 7, id: 51 + (0x7e, 0), // x: 5, y: 7, sw: 5, cs: 7, id: 55 + (0x9c, 0), // x: 6, y: 7, sw: 6, cs: 7, id: 59 + (0x06, 1), // x: 7, y: 7, sw: 7, cs: 7, id: 63 + (0x24, 1), // x: 8, y: 7, sw: 8, cs: 7, id: 67 + (0x69, 1), // x: 9, y: 7, sw: 2, cs:37, id: 71 + (0x07, 0), // x: 1, y: 8, sw: 1, cs: 8, id: 40 + (0x25, 0), // x: 2, y: 8, sw: 2, cs: 8, id: 44 + (0x43, 0), // x: 3, y: 8, sw: 3, cs: 8, id: 48 + (0x61, 0), // x: 4, y: 8, sw: 4, cs: 8, id: 52 + (0x7f, 0), // x: 5, y: 8, sw: 5, cs: 8, id: 56 + (0x9d, 0), // x: 6, y: 8, sw: 6, cs: 8, id: 60 + (0x07, 1), // x: 7, y: 8, sw: 7, cs: 8, id: 64 + (0x25, 1), // x: 8, y: 8, sw: 8, cs: 8, id: 68 + (0x6a, 1), // x: 9, y: 8, sw: 2, cs:38, id: 72 + (0x08, 0), // x: 1, y: 9, sw: 1, cs: 9, id: 73 + (0x26, 0), // x: 2, y: 9, sw: 2, cs: 9, id: 81 + (0x44, 0), // x: 3, y: 9, sw: 3, cs: 9, id: 89 + (0x62, 0), // x: 4, y: 9, sw: 4, cs: 9, id: 97 + (0x80, 0), // x: 5, y: 9, sw: 5, cs: 9, id:105 + (0x9e, 0), // x: 6, y: 9, sw: 6, cs: 9, id:113 + (0x08, 1), // x: 7, y: 9, sw: 7, cs: 9, id:121 + (0x26, 1), // x: 8, y: 9, sw: 8, cs: 9, id:129 + (0x6b, 1), // x: 9, y: 9, sw: 2, cs:39, id:137 + (0x09, 0), // x: 1, y:10, sw: 1, cs:10, id: 74 + (0x27, 0), // x: 2, y:10, sw: 2, cs:10, id: 82 + (0x45, 0), // x: 3, y:10, sw: 3, cs:10, id: 90 + (0x63, 0), // x: 4, y:10, sw: 4, cs:10, id: 98 + (0x81, 0), // x: 5, y:10, sw: 5, cs:10, id:106 + (0x9f, 0), // x: 6, y:10, sw: 6, cs:10, id:114 + (0x09, 1), // x: 7, y:10, sw: 7, cs:10, id:122 + (0x27, 1), // x: 8, y:10, sw: 8, cs:10, id:130 + (0x67, 1), // x: 9, y:10, sw: 2, cs:35, id:138 + (0x0a, 0), // x: 1, y:11, sw: 1, cs:11, id: 75 + (0x28, 0), // x: 2, y:11, sw: 2, cs:11, id: 83 + (0x46, 0), // x: 3, y:11, sw: 3, cs:11, id: 91 + (0x64, 0), // x: 4, y:11, sw: 4, cs:11, id: 99 + (0x82, 0), // x: 5, y:11, sw: 5, cs:11, id:107 + (0xa0, 0), // x: 6, y:11, sw: 6, cs:11, id:115 + (0x0a, 1), // x: 7, y:11, sw: 7, cs:11, id:123 + (0x28, 1), // x: 8, y:11, sw: 8, cs:11, id:131 + (0x71, 1), // x: 9, y:11, sw: 3, cs:36, id:139 + (0x0b, 0), // x: 1, y:12, sw: 1, cs:12, id: 76 + (0x29, 0), // x: 2, y:12, sw: 2, cs:12, id: 84 + (0x47, 0), // x: 3, y:12, sw: 3, cs:12, id: 92 + (0x65, 0), // x: 4, y:12, sw: 4, cs:12, id:100 + (0x83, 0), // x: 5, y:12, sw: 5, cs:12, id:108 + (0xa1, 0), // x: 6, y:12, sw: 6, cs:12, id:116 + (0x0b, 1), // x: 7, y:12, sw: 7, cs:12, id:124 + (0x29, 1), // x: 8, y:12, sw: 8, cs:12, id:132 + (0x72, 1), // x: 9, y:12, sw: 3, cs:37, id:140 + (0x0c, 0), // x: 1, y:13, sw: 1, cs:13, id: 77 + (0x2a, 0), // x: 2, y:13, sw: 2, cs:13, id: 85 + (0x48, 0), // x: 3, y:13, sw: 3, cs:13, id: 93 + (0x66, 0), // x: 4, y:13, sw: 4, cs:13, id:101 + (0x84, 0), // x: 5, y:13, sw: 5, cs:13, id:109 + (0xa2, 0), // x: 6, y:13, sw: 6, cs:13, id:117 + (0x0c, 1), // x: 7, y:13, sw: 7, cs:13, id:125 + (0x2a, 1), // x: 8, y:13, sw: 8, cs:13, id:133 + (0x73, 1), // x: 9, y:13, sw: 3, cs:38, id:141 + (0x0d, 0), // x: 1, y:14, sw: 1, cs:14, id: 78 + (0x2b, 0), // x: 2, y:14, sw: 2, cs:14, id: 86 + (0x49, 0), // x: 3, y:14, sw: 3, cs:14, id: 94 + (0x67, 0), // x: 4, y:14, sw: 4, cs:14, id:102 + (0x85, 0), // x: 5, y:14, sw: 5, cs:14, id:110 + (0xa3, 0), // x: 6, y:14, sw: 6, cs:14, id:118 + (0x0d, 1), // x: 7, y:14, sw: 7, cs:14, id:126 + (0x2b, 1), // x: 8, y:14, sw: 8, cs:14, id:134 + (0x70, 1), // x: 9, y:14, sw: 3, cs:35, id:142 + (0x0e, 0), // x: 1, y:15, sw: 1, cs:15, id: 79 + (0x2c, 0), // x: 2, y:15, sw: 2, cs:15, id: 87 + (0x4a, 0), // x: 3, y:15, sw: 3, cs:15, id: 95 + (0x68, 0), // x: 4, y:15, sw: 4, cs:15, id:103 + (0x86, 0), // x: 5, y:15, sw: 5, cs:15, id:111 + (0xa4, 0), // x: 6, y:15, sw: 6, cs:15, id:119 + (0x0e, 1), // x: 7, y:15, sw: 7, cs:15, id:127 + (0x2c, 1), // x: 8, y:15, sw: 8, cs:15, id:135 + (0x7a, 1), // x: 9, y:15, sw: 4, cs:36, id:143 + (0x0f, 0), // x: 1, y:16, sw: 1, cs:16, id: 80 + (0x2d, 0), // x: 2, y:16, sw: 2, cs:16, id: 88 + (0x4b, 0), // x: 3, y:16, sw: 3, cs:16, id: 96 + (0x69, 0), // x: 4, y:16, sw: 4, cs:16, id:104 + (0x87, 0), // x: 5, y:16, sw: 5, cs:16, id:112 + (0xa5, 0), // x: 6, y:16, sw: 6, cs:16, id:120 + (0x0f, 1), // x: 7, y:16, sw: 7, cs:16, id:128 + (0x2d, 1), // x: 8, y:16, sw: 8, cs:16, id:136 + (0x7b, 1), // x: 9, y:16, sw: 4, cs:37, id:144 + (0x10, 0), // x: 1, y:17, sw: 1, cs:17, id:145 + (0x2e, 0), // x: 2, y:17, sw: 2, cs:17, id:161 + (0x4c, 0), // x: 3, y:17, sw: 3, cs:17, id:177 + (0x6a, 0), // x: 4, y:17, sw: 4, cs:17, id:193 + (0x88, 0), // x: 5, y:17, sw: 5, cs:17, id:209 + (0xa6, 0), // x: 6, y:17, sw: 6, cs:17, id:225 + (0x10, 1), // x: 7, y:17, sw: 7, cs:17, id:241 + (0x2e, 1), // x: 8, y:17, sw: 8, cs:17, id:257 + (0x7c, 1), // x: 9, y:17, sw: 4, cs:38, id:273 + (0x11, 0), // x: 1, y:18, sw: 1, cs:18, id:146 + (0x2f, 0), // x: 2, y:18, sw: 2, cs:18, id:162 + (0x4d, 0), // x: 3, y:18, sw: 3, cs:18, id:178 + (0x6b, 0), // x: 4, y:18, sw: 4, cs:18, id:194 + (0x89, 0), // x: 5, y:18, sw: 5, cs:18, id:210 + (0xa7, 0), // x: 6, y:18, sw: 6, cs:18, id:226 + (0x11, 1), // x: 7, y:18, sw: 7, cs:18, id:242 + (0x2f, 1), // x: 8, y:18, sw: 8, cs:18, id:258 + (0x79, 1), // x: 9, y:18, sw: 4, cs:35, id:274 + (0x12, 0), // x: 1, y:19, sw: 1, cs:19, id:147 + (0x30, 0), // x: 2, y:19, sw: 2, cs:19, id:163 + (0x4e, 0), // x: 3, y:19, sw: 3, cs:19, id:179 + (0x6c, 0), // x: 4, y:19, sw: 4, cs:19, id:195 + (0x8a, 0), // x: 5, y:19, sw: 5, cs:19, id:211 + (0xa8, 0), // x: 6, y:19, sw: 6, cs:19, id:227 + (0x12, 1), // x: 7, y:19, sw: 7, cs:19, id:243 + (0x30, 1), // x: 8, y:19, sw: 8, cs:19, id:259 + (0x83, 1), // x: 9, y:19, sw: 5, cs:36, id:275 + (0x13, 0), // x: 1, y:20, sw: 1, cs:20, id:148 + (0x31, 0), // x: 2, y:20, sw: 2, cs:20, id:164 + (0x4f, 0), // x: 3, y:20, sw: 3, cs:20, id:180 + (0x6d, 0), // x: 4, y:20, sw: 4, cs:20, id:196 + (0x8b, 0), // x: 5, y:20, sw: 5, cs:20, id:212 + (0xa9, 0), // x: 6, y:20, sw: 6, cs:20, id:228 + (0x13, 1), // x: 7, y:20, sw: 7, cs:20, id:244 + (0x31, 1), // x: 8, y:20, sw: 8, cs:20, id:260 + (0x84, 1), // x: 9, y:20, sw: 5, cs:37, id:276 + (0x14, 0), // x: 1, y:21, sw: 1, cs:21, id:149 + (0x32, 0), // x: 2, y:21, sw: 2, cs:21, id:165 + (0x50, 0), // x: 3, y:21, sw: 3, cs:21, id:181 + (0x6e, 0), // x: 4, y:21, sw: 4, cs:21, id:197 + (0x8c, 0), // x: 5, y:21, sw: 5, cs:21, id:213 + (0xaa, 0), // x: 6, y:21, sw: 6, cs:21, id:229 + (0x14, 1), // x: 7, y:21, sw: 7, cs:21, id:245 + (0x32, 1), // x: 8, y:21, sw: 8, cs:21, id:261 + (0x85, 1), // x: 9, y:21, sw: 5, cs:38, id:277 + (0x15, 0), // x: 1, y:22, sw: 1, cs:22, id:150 + (0x33, 0), // x: 2, y:22, sw: 2, cs:22, id:166 + (0x51, 0), // x: 3, y:22, sw: 3, cs:22, id:182 + (0x6f, 0), // x: 4, y:22, sw: 4, cs:22, id:198 + (0x8d, 0), // x: 5, y:22, sw: 5, cs:22, id:214 + (0xab, 0), // x: 6, y:22, sw: 6, cs:22, id:230 + (0x15, 1), // x: 7, y:22, sw: 7, cs:22, id:246 + (0x33, 1), // x: 8, y:22, sw: 8, cs:22, id:262 + (0x82, 1), // x: 9, y:22, sw: 5, cs:35, id:278 + (0x16, 0), // x: 1, y:23, sw: 1, cs:23, id:151 + (0x34, 0), // x: 2, y:23, sw: 2, cs:23, id:167 + (0x52, 0), // x: 3, y:23, sw: 3, cs:23, id:183 + (0x70, 0), // x: 4, y:23, sw: 4, cs:23, id:199 + (0x8e, 0), // x: 5, y:23, sw: 5, cs:23, id:215 + (0xac, 0), // x: 6, y:23, sw: 6, cs:23, id:231 + (0x16, 1), // x: 7, y:23, sw: 7, cs:23, id:247 + (0x34, 1), // x: 8, y:23, sw: 8, cs:23, id:263 + (0x8c, 1), // x: 9, y:23, sw: 6, cs:36, id:279 + (0x17, 0), // x: 1, y:24, sw: 1, cs:24, id:152 + (0x35, 0), // x: 2, y:24, sw: 2, cs:24, id:168 + (0x53, 0), // x: 3, y:24, sw: 3, cs:24, id:184 + (0x71, 0), // x: 4, y:24, sw: 4, cs:24, id:200 + (0x8f, 0), // x: 5, y:24, sw: 5, cs:24, id:216 + (0xad, 0), // x: 6, y:24, sw: 6, cs:24, id:232 + (0x17, 1), // x: 7, y:24, sw: 7, cs:24, id:248 + (0x35, 1), // x: 8, y:24, sw: 8, cs:24, id:264 + (0x8d, 1), // x: 9, y:24, sw: 6, cs:37, id:280 + (0x18, 0), // x: 1, y:25, sw: 1, cs:25, id:153 + (0x36, 0), // x: 2, y:25, sw: 2, cs:25, id:169 + (0x54, 0), // x: 3, y:25, sw: 3, cs:25, id:185 + (0x72, 0), // x: 4, y:25, sw: 4, cs:25, id:201 + (0x90, 0), // x: 5, y:25, sw: 5, cs:25, id:217 + (0xae, 0), // x: 6, y:25, sw: 6, cs:25, id:233 + (0x18, 1), // x: 7, y:25, sw: 7, cs:25, id:249 + (0x36, 1), // x: 8, y:25, sw: 8, cs:25, id:265 + (0x8e, 1), // x: 9, y:25, sw: 6, cs:38, id:281 + (0x19, 0), // x: 1, y:26, sw: 1, cs:26, id:154 + (0x37, 0), // x: 2, y:26, sw: 2, cs:26, id:170 + (0x55, 0), // x: 3, y:26, sw: 3, cs:26, id:186 + (0x73, 0), // x: 4, y:26, sw: 4, cs:26, id:202 + (0x91, 0), // x: 5, y:26, sw: 5, cs:26, id:218 + (0xaf, 0), // x: 6, y:26, sw: 6, cs:26, id:234 + (0x19, 1), // x: 7, y:26, sw: 7, cs:26, id:250 + (0x37, 1), // x: 8, y:26, sw: 8, cs:26, id:266 + (0x8b, 1), // x: 9, y:26, sw: 6, cs:35, id:282 + (0x1a, 0), // x: 1, y:27, sw: 1, cs:27, id:155 + (0x38, 0), // x: 2, y:27, sw: 2, cs:27, id:171 + (0x56, 0), // x: 3, y:27, sw: 3, cs:27, id:187 + (0x74, 0), // x: 4, y:27, sw: 4, cs:27, id:203 + (0x92, 0), // x: 5, y:27, sw: 5, cs:27, id:219 + (0xb0, 0), // x: 6, y:27, sw: 6, cs:27, id:235 + (0x1a, 1), // x: 7, y:27, sw: 7, cs:27, id:251 + (0x38, 1), // x: 8, y:27, sw: 8, cs:27, id:267 + (0x95, 1), // x: 9, y:27, sw: 7, cs:36, id:283 + (0x1b, 0), // x: 1, y:28, sw: 1, cs:28, id:156 + (0x39, 0), // x: 2, y:28, sw: 2, cs:28, id:172 + (0x57, 0), // x: 3, y:28, sw: 3, cs:28, id:188 + (0x75, 0), // x: 4, y:28, sw: 4, cs:28, id:204 + (0x93, 0), // x: 5, y:28, sw: 5, cs:28, id:220 + (0xb1, 0), // x: 6, y:28, sw: 6, cs:28, id:236 + (0x1b, 1), // x: 7, y:28, sw: 7, cs:28, id:252 + (0x39, 1), // x: 8, y:28, sw: 8, cs:28, id:268 + (0x96, 1), // x: 9, y:28, sw: 7, cs:37, id:284 + (0x1c, 0), // x: 1, y:29, sw: 1, cs:29, id:157 + (0x3a, 0), // x: 2, y:29, sw: 2, cs:29, id:173 + (0x58, 0), // x: 3, y:29, sw: 3, cs:29, id:189 + (0x76, 0), // x: 4, y:29, sw: 4, cs:29, id:205 + (0x94, 0), // x: 5, y:29, sw: 5, cs:29, id:221 + (0xb2, 0), // x: 6, y:29, sw: 6, cs:29, id:237 + (0x1c, 1), // x: 7, y:29, sw: 7, cs:29, id:253 + (0x3a, 1), // x: 8, y:29, sw: 8, cs:29, id:269 + (0x97, 1), // x: 9, y:29, sw: 7, cs:38, id:285 + (0x1d, 0), // x: 1, y:30, sw: 1, cs:30, id:158 + (0x3b, 0), // x: 2, y:30, sw: 2, cs:30, id:174 + (0x59, 0), // x: 3, y:30, sw: 3, cs:30, id:190 + (0x77, 0), // x: 4, y:30, sw: 4, cs:30, id:206 + (0x95, 0), // x: 5, y:30, sw: 5, cs:30, id:222 + (0xb3, 0), // x: 6, y:30, sw: 6, cs:30, id:238 + (0x1d, 1), // x: 7, y:30, sw: 7, cs:30, id:254 + (0x3b, 1), // x: 8, y:30, sw: 8, cs:30, id:270 + (0x94, 1), // x: 9, y:30, sw: 7, cs:35, id:286 + (0x5a, 1), // x: 1, y:31, sw: 1, cs:31, id:159 + (0x63, 1), // x: 2, y:31, sw: 2, cs:31, id:175 + (0x6c, 1), // x: 3, y:31, sw: 3, cs:31, id:191 + (0x75, 1), // x: 4, y:31, sw: 4, cs:31, id:207 + (0x7e, 1), // x: 5, y:31, sw: 5, cs:31, id:223 + (0x87, 1), // x: 6, y:31, sw: 6, cs:31, id:239 + (0x90, 1), // x: 7, y:31, sw: 7, cs:31, id:255 + (0x99, 1), // x: 8, y:31, sw: 8, cs:31, id:271 + (0x9e, 1), // x: 9, y:31, sw: 8, cs:36, id:287 + (0x5b, 1), // x: 1, y:32, sw: 1, cs:32, id:160 + (0x64, 1), // x: 2, y:32, sw: 2, cs:32, id:176 + (0x6d, 1), // x: 3, y:32, sw: 3, cs:32, id:192 + (0x76, 1), // x: 4, y:32, sw: 4, cs:32, id:208 + (0x7f, 1), // x: 5, y:32, sw: 5, cs:32, id:224 + (0x88, 1), // x: 6, y:32, sw: 6, cs:32, id:240 + (0x91, 1), // x: 7, y:32, sw: 7, cs:32, id:256 + (0x9a, 1), // x: 8, y:32, sw: 8, cs:32, id:272 + (0x9f, 1), // x: 9, y:32, sw: 8, cs:37, id:288 + (0x5c, 1), // x: 1, y:33, sw: 1, cs:33, id:289 + (0x65, 1), // x: 2, y:33, sw: 2, cs:33, id:290 + (0x6e, 1), // x: 3, y:33, sw: 3, cs:33, id:291 + (0x77, 1), // x: 4, y:33, sw: 4, cs:33, id:292 + (0x80, 1), // x: 5, y:33, sw: 5, cs:33, id:293 + (0x89, 1), // x: 6, y:33, sw: 6, cs:33, id:294 + (0x92, 1), // x: 7, y:33, sw: 7, cs:33, id:295 + (0x9b, 1), // x: 8, y:33, sw: 8, cs:33, id:296 + (0xa0, 1), // x: 9, y:33, sw: 8, cs:38, id:297 + (0x5d, 1), // x: 1, y:34, sw: 1, cs:34, id:298 + (0x66, 1), // x: 2, y:34, sw: 2, cs:34, id:299 + (0x6f, 1), // x: 3, y:34, sw: 3, cs:34, id:300 + (0x78, 1), // x: 4, y:34, sw: 4, cs:34, id:301 + (0x81, 1), // x: 5, y:34, sw: 5, cs:34, id:302 + (0x8a, 1), // x: 6, y:34, sw: 6, cs:34, id:303 + (0x93, 1), // x: 7, y:34, sw: 7, cs:34, id:304 + (0x9c, 1), // x: 8, y:34, sw: 8, cs:34, id:305 + (0x9d, 1), // x: 9, y:34, sw: 8, cs:35, id:306 + ]; + let index: usize = (x as usize) + (y as usize) * 9; + if index < lookup.len() { + lookup[index] + } else { + (0x00, 0) + } +}; + +pub struct LedMatrix { + pub device: IS31FL3743, +} + +impl LedMatrix +where + I2C: Write, + I2C: Read, + I2cError: core::fmt::Debug, +{ + pub fn unwrap(self) -> I2C { + self.device.i2c + } + + // TODO: Maybe make this private and set it once in the constructor + pub fn set_scaling(&mut self, scale: u8) -> Result<(), I2cError> { + self.device.set_scaling(scale) + } + + pub fn set_address(&mut self, address: u8) { + self.device.address = address; + } + + pub fn new(i2c: I2C, calc_pixel: fn(x: u8, y: u8) -> (u8, u8)) -> LedMatrix { + LedMatrix { + device: IS31FL3743 { + i2c, + address: 0b0100000, + width: 9, + height: 34, + calc_pixel, + }, + } + } + + pub fn setup>(&mut self, delay: &mut DEL) -> Result<(), Error> { + self.device.setup(delay)?; + Ok(()) + } + + pub fn fill_brightness(&mut self, brightness: u8) -> Result<(), Error> { + for x in 0..self.device.width { + for y in 0..self.device.height { + self.device.pixel(x, y, brightness)?; + } + } + Ok(()) + } +} From 14a6026731ec680e22f6339f488d23ff0c6b666c Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Thu, 26 Oct 2023 16:15:15 +0800 Subject: [PATCH 12/14] keyboard: Use newly published is31fl3743a crate Signed-off-by: Daniel Schaefer --- Cargo.lock | 17 ++++++++++++++--- Cargo.toml | 3 ++- keyboard/Cargo.toml | 2 +- keyboard/src/main.rs | 2 +- keyboard/src/rgb_matrix.rs | 4 ++-- 5 files changed, 20 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3807d72b..24089a28 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1089,8 +1089,19 @@ dependencies = [ [[package]] name = "is31fl3741" -version = "0.2.2" -source = "git+https://github.com/FrameworkComputer/is31fl3741-rs?branch=is31fl3743a#1814f6a838560c7553cda34cdad4692dc5da2d5f" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66d02b7bcb58e9f5ef8562cec1914198f71a35aa8f90e23326b77d12502ab860" +dependencies = [ + "embedded-graphics-core", + "embedded-hal", +] + +[[package]] +name = "is31fl3743a" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "884ca84ba6f4c9a42cf7116611fda1c94f1c735555ae768fbfccad8ccc491235" dependencies = [ "embedded-graphics-core", "embedded-hal", @@ -1170,7 +1181,7 @@ dependencies = [ "fl16-inputmodules", "fugit", "heapless", - "is31fl3741", + "is31fl3743a", "rp2040-boot2", "rp2040-hal", "rp2040-panic-usb-boot", diff --git a/Cargo.toml b/Cargo.toml index bddff02a..06c3ebd6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,7 +40,8 @@ usbd-serial = "0.1.1" usbd-hid = "0.6.1" fugit = "0.3.7" # LED Matrix -is31fl3741 = { git = "https://github.com/FrameworkComputer/is31fl3741-rs", branch = "is31fl3743a" } +is31fl3741 = "0.3.0" +is31fl3743a = "0.1.0" # B1 Display st7306 = { git = "https://github.com/FrameworkComputer/st7306-rs", branch = "update-deps" } embedded-graphics = "0.8" diff --git a/keyboard/Cargo.toml b/keyboard/Cargo.toml index 9ed709b2..e15a57f4 100644 --- a/keyboard/Cargo.toml +++ b/keyboard/Cargo.toml @@ -35,7 +35,7 @@ usbd-hid.workspace = true fugit.workspace = true usbd-human-interface-device = "0.3.1" -is31fl3741.workspace = true +is31fl3743a.workspace = true cfg-if = "1.0.0" diff --git a/keyboard/src/main.rs b/keyboard/src/main.rs index e4b67611..eff78e86 100644 --- a/keyboard/src/main.rs +++ b/keyboard/src/main.rs @@ -365,7 +365,7 @@ fn main() -> ! { &clocks.peripheral_clock, ); - let mut matrix = LedMatrix::new(i2c, DVT2_CALC_PIXEL); + let mut matrix = LedMatrix::new(i2c, |_, _| 0x00); cfg_if::cfg_if! { if #[cfg(any(feature = "ansi", feature = "macropad"))] { diff --git a/keyboard/src/rgb_matrix.rs b/keyboard/src/rgb_matrix.rs index 3b077022..c750283a 100644 --- a/keyboard/src/rgb_matrix.rs +++ b/keyboard/src/rgb_matrix.rs @@ -6,7 +6,7 @@ use embedded_hal::blocking::delay::DelayMs; use embedded_hal::blocking::i2c::Read; use embedded_hal::blocking::i2c::Write; #[allow(unused_imports)] -use is31fl3741::{Error, IS31FL3743}; +use is31fl3743a::{Error, IS31FL3743}; pub const DVT2_CALC_PIXEL: fn(x: u8, y: u8) -> (u8, u8) = |x: u8, y: u8| -> (u8, u8) { // Generated by led-matrix.py @@ -349,7 +349,7 @@ where self.device.address = address; } - pub fn new(i2c: I2C, calc_pixel: fn(x: u8, y: u8) -> (u8, u8)) -> LedMatrix { + pub fn new(i2c: I2C, calc_pixel: fn(x: u8, y: u8) -> u8) -> LedMatrix { LedMatrix { device: IS31FL3743 { i2c, From 5a5cc03ab87aae5be440e430181abbccd778e23d Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Tue, 21 Nov 2023 13:30:35 +0800 Subject: [PATCH 13/14] keyboard: Also blink RGB backlight in suspend Signed-off-by: Daniel Schaefer --- keyboard/src/main.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/keyboard/src/main.rs b/keyboard/src/main.rs index eff78e86..2ca6cdbd 100644 --- a/keyboard/src/main.rs +++ b/keyboard/src/main.rs @@ -22,7 +22,7 @@ // - [ ] Persist brightness setting and FN lock through reset // - [ ] Media keys -//use cortex_m::delay::Delay; +use cortex_m::delay::Delay; //use defmt::*; use crate::rgb_matrix::{LedMatrix, DVT2_CALC_PIXEL}; use defmt_rtt as _; @@ -419,6 +419,8 @@ fn main() -> ! { if !usb_suspended { if caps_led.is_set_low().unwrap() { caps_led.set_high().unwrap(); + #[cfg(any(feature = "ansi", feature = "macropad"))] + matrix.device.fill(0xFF); } } @@ -426,9 +428,13 @@ fn main() -> ! { // 500_000us = 500ms = 0.5s if usb_suspended && timer.get_counter().ticks() > capslock_timer + 500_000 { if caps_led.is_set_high().unwrap() { + #[cfg(any(feature = "ansi", feature = "macropad"))] + matrix.device.fill(0x00); caps_led.set_low().unwrap(); } else { caps_led.set_high().unwrap(); + #[cfg(any(feature = "ansi", feature = "macropad"))] + matrix.device.fill(0xFF); } capslock_timer = timer.get_counter().ticks(); } @@ -467,7 +473,7 @@ fn main() -> ! { } cfg_if::cfg_if! { - if #[cfg(any(feature = "numapd", feature = "macropad"))] { + if #[cfg(any(feature = "numpad", feature = "macropad"))] { let one = scanner.measure_key(0, 3); let two = scanner.measure_key(0, 7); let three = scanner.measure_key(1, 4); From c8aaeaf97cb6e978eba7f211a3679488282dc833 Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Sun, 4 Feb 2024 18:30:23 +0800 Subject: [PATCH 14/14] keyboard: Update hid to 0.4.5 Signed-off-by: Daniel Schaefer --- Cargo.lock | 78 +++++++++++++++++++++++++++++--------------- keyboard/Cargo.toml | 2 +- keyboard/src/main.rs | 10 +++--- 3 files changed, 58 insertions(+), 32 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 24089a28..1396ee70 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -207,7 +207,7 @@ dependencies = [ "embedded-hal", "fl16-inputmodules", "fugit", - "heapless", + "heapless 0.7.16", "rp2040-boot2", "rp2040-hal", "rp2040-panic-usb-boot", @@ -327,7 +327,7 @@ dependencies = [ "embedded-hal", "fl16-inputmodules", "fugit", - "heapless", + "heapless 0.7.16", "rp2040-boot2", "rp2040-hal", "rp2040-panic-usb-boot", @@ -666,17 +666,6 @@ dependencies = [ "defmt", ] -[[package]] -name = "delegate" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d358e0ec5c59a5e1603b933def447096886121660fc680dc1e64a0753981fe3c" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "either" version = "1.8.1" @@ -807,7 +796,7 @@ dependencies = [ "embedded-graphics", "embedded-hal", "fugit", - "heapless", + "heapless 0.7.16", "is31fl3741", "num", "num-derive", @@ -951,6 +940,15 @@ dependencies = [ "byteorder", ] +[[package]] +name = "hash32" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" +dependencies = [ + "byteorder", +] + [[package]] name = "hashbrown" version = "0.12.3" @@ -964,12 +962,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db04bc24a18b9ea980628ecf00e6c0264f3c1426dac36c00cb49b6fbad8b0743" dependencies = [ "atomic-polyfill", - "hash32", + "hash32 0.2.1", "rustc_version 0.4.0", "spin", "stable_deref_trait", ] +[[package]] +name = "heapless" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" +dependencies = [ + "hash32 0.3.1", + "stable_deref_trait", +] + [[package]] name = "heck" version = "0.4.1" @@ -1180,7 +1188,7 @@ dependencies = [ "embedded-hal", "fl16-inputmodules", "fugit", - "heapless", + "heapless 0.7.16", "is31fl3743a", "rp2040-boot2", "rp2040-hal", @@ -1214,7 +1222,7 @@ dependencies = [ "embedded-hal", "fl16-inputmodules", "fugit", - "heapless", + "heapless 0.7.16", "is31fl3741", "rp2040-boot2", "rp2040-hal", @@ -1376,7 +1384,7 @@ dependencies = [ "bitflags 1.3.2", "jni-sys", "ndk-sys", - "num_enum", + "num_enum 0.5.11", "raw-window-handle", "thiserror", ] @@ -1509,7 +1517,16 @@ version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" dependencies = [ - "num_enum_derive", + "num_enum_derive 0.5.11", +] + +[[package]] +name = "num_enum" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" +dependencies = [ + "num_enum_derive 0.7.2", ] [[package]] @@ -1524,6 +1541,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "num_enum_derive" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.18", +] + [[package]] name = "object" version = "0.30.4" @@ -1663,7 +1691,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76e09694b50f89f302ed531c1f2a7569f0be5867aee4ab4f8f729bbeec0078e3" dependencies = [ "arrayvec", - "num_enum", + "num_enum 0.5.11", "paste", ] @@ -2457,16 +2485,14 @@ dependencies = [ [[package]] name = "usbd-human-interface-device" -version = "0.3.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec9b21b68dbad6f411589e94b1b4e8792943959e8a99fdbc336f38cf4e5a3542" +checksum = "d69710303c06f23a1259d086bfb241212ae1ccfb5d582ebd596bb042d662ed73" dependencies = [ - "delegate", "frunk", "fugit", - "heapless", - "log", - "num_enum", + "heapless 0.8.0", + "num_enum 0.7.2", "option-block", "packed_struct", "usb-device", diff --git a/keyboard/Cargo.toml b/keyboard/Cargo.toml index e15a57f4..6734e9b7 100644 --- a/keyboard/Cargo.toml +++ b/keyboard/Cargo.toml @@ -34,7 +34,7 @@ usbd-serial.workspace = true usbd-hid.workspace = true fugit.workspace = true -usbd-human-interface-device = "0.3.1" +usbd-human-interface-device = "0.4.5" is31fl3743a.workspace = true cfg-if = "1.0.0" diff --git a/keyboard/src/main.rs b/keyboard/src/main.rs index 2ca6cdbd..44c3d93a 100644 --- a/keyboard/src/main.rs +++ b/keyboard/src/main.rs @@ -30,9 +30,9 @@ use embedded_hal::adc::OneShot; use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin}; use rp2040_hal::gpio::bank0::Gpio28; use rp2040_hal::gpio::{self, Input, PullUp}; -use usbd_human_interface_device::device::keyboard::BootKeyboardInterface; use usbd_human_interface_device::page::Keyboard; use usbd_human_interface_device::prelude::UsbHidClassBuilder; +use usbd_human_interface_device::prelude::*; use usbd_human_interface_device::UsbHidError; mod rgb_matrix; @@ -274,7 +274,7 @@ fn main() -> ! { // Set up the USB Communications Class Device driver //let mut serial = SerialPort::new(&usb_bus); let mut keyboard_hid = UsbHidClassBuilder::new() - .add_interface(BootKeyboardInterface::default_config()) + .add_device(usbd_human_interface_device::device::keyboard::BootKeyboardConfig::default()) .build(&usb_bus); #[cfg(feature = "macropad")] @@ -502,7 +502,7 @@ fn main() -> ! { } if !usb_suspended { - let _ = keyboard_hid.interface().read_report(); + let _ = keyboard_hid.device().read_report(); // Setup the report for the control channel let keycodes = if let Some(keycode) = keycode { @@ -510,11 +510,11 @@ fn main() -> ! { } else { [Keyboard::NoEventIndicated] }; - match keyboard_hid.interface().write_report(keycodes) { + match keyboard_hid.device().write_report(keycodes) { Err(UsbHidError::WouldBlock) | Err(UsbHidError::Duplicate) | Ok(_) => {} Err(e) => panic!("Failed to write keyboard report: {:?}", e), } - match keyboard_hid.interface().tick() { + match keyboard_hid.tick() { Err(UsbHidError::WouldBlock) | Ok(_) => {} Err(e) => panic!("Failed to process keyboard tick: {:?}", e), }