diff --git a/firmware/Cargo.lock b/firmware/Cargo.lock index d76a922..e89ecb9 100644 --- a/firmware/Cargo.lock +++ b/firmware/Cargo.lock @@ -29,6 +29,18 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[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 = "bxcan" version = "0.7.0" @@ -41,6 +53,12 @@ dependencies = [ "vcell", ] +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + [[package]] name = "cortex-m" version = "0.7.7" @@ -70,7 +88,7 @@ checksum = "f0f6f3e36f203cfedbc78b357fb28730aa2c6dc1ab060ee5c2405e843988d3c7" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -114,9 +132,49 @@ dependencies = [ "ryu", "stm32f1xx-hal", "usb-device", + "usbd-human-interface-device", "usbd-serial", ] +[[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.53", +] + +[[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.53", +] + [[package]] name = "fugit" version = "0.3.7" @@ -136,12 +194,37 @@ dependencies = [ "nb 1.1.0", ] +[[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" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a" +[[package]] +name = "hash32" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" +dependencies = [ + "byteorder", +] + +[[package]] +name = "heapless" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" +dependencies = [ + "hash32", + "stable_deref_trait", +] + [[package]] name = "nb" version = "0.1.3" @@ -157,6 +240,53 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" +[[package]] +name = "num_enum" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" +dependencies = [ + "num_enum_derive", +] + +[[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.53", +] + +[[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 = "panic-halt" version = "0.2.0" @@ -191,6 +321,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 = "rustc_version" version = "0.2.3" @@ -281,6 +417,23 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn" +version = "2.0.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7383cd0e49fff4b6b90ca5670bfd3e9d6a733b3f90c686605aa7eec8c4996032" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + [[package]] name = "unicode-ident" version = "1.0.12" @@ -293,6 +446,21 @@ version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f6cc3adc849b5292b4075fc0d5fdcf2f24866e88e336dd27a8943090a520508" +[[package]] +name = "usbd-human-interface-device" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d69710303c06f23a1259d086bfb241212ae1ccfb5d582ebd596bb042d662ed73" +dependencies = [ + "frunk", + "fugit", + "heapless", + "num_enum", + "option-block", + "packed_struct", + "usb-device", +] + [[package]] name = "usbd-serial" version = "0.1.1" @@ -324,3 +492,12 @@ checksum = "de437e2a6208b014ab52972a27e59b33fa2920d3e00fe05026167a1c509d19cc" dependencies = [ "vcell", ] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] diff --git a/firmware/Cargo.toml b/firmware/Cargo.toml index 7ccf775..93241d5 100644 --- a/firmware/Cargo.toml +++ b/firmware/Cargo.toml @@ -17,6 +17,7 @@ usb-device = "0.2.9" usbd-serial = "0.1.1" ryu = "1.0.16" panic-semihosting = "0.6.0" +usbd-human-interface-device = "0.4.5" [dependencies.stm32f1xx-hal] version = "0.10.0" diff --git a/firmware/src/main.rs b/firmware/src/main.rs index d9ad218..68c95cb 100644 --- a/firmware/src/main.rs +++ b/firmware/src/main.rs @@ -4,17 +4,17 @@ use panic_halt as _; -use nb::block; +//use nb::block; use cortex_m_rt::entry; use cortex_m::asm::delay; -use stm32f1xx_hal::{adc, pac, prelude::*, timer::{Channel, Tim2NoRemap}}; +use stm32f1xx_hal::{adc, pac, prelude::*, timer::{Channel, Tim2NoRemap, Timer}, gpio::{Analog}}; use stm32f1xx_hal::usb::{Peripheral, UsbBus}; use usb_device::prelude::*; -use usbd_serial::{SerialPort, USB_CLASS_CDC}; - -use core::f32::RADIX; +use usbd_human_interface_device::device::consumer::MultipleConsumerReport; +use usbd_human_interface_device::prelude::*; +use usbd_human_interface_device::page::Consumer; #[entry] fn main() -> ! { @@ -49,21 +49,27 @@ fn main() -> ! { }; let usb_bus = UsbBus::new(usb); - let mut serial = SerialPort::new(&usb_bus); + let mut consumer = UsbHidClassBuilder::new() + .add_device(usbd_human_interface_device::device::consumer::ConsumerControlConfig::default()) + .build(&usb_bus); let mut usb_dev = UsbDeviceBuilder::new(&usb_bus, UsbVidPid(0x16c0, 0x27dd)) .manufacturer("FLC Meow") .product("Serial port") .serial_number("01189998819991197253") - .device_class(USB_CLASS_CDC) .build(); // ====================== ADC setup ================= // Setup ADC let mut adc1 = adc::Adc::adc1(p.ADC1, clocks); - // Configure pa1 as an analog input - let mut ch0 = gpioa.pa1.into_analog(&mut gpioa.crl); + // ====================== Pin setup ================= + let input_pins: [&dyn ErasedPin; 2] = [ + &gpioa.pa1.into_analog(&mut gpioa.crl), + &gpioa.pa2.into_analog(&mut gpioa.crl) + ]; + + let mut last = get_report(&input_pins); // ====================== PWM setup ================= let mut afio = p.AFIO.constrain(); @@ -72,54 +78,61 @@ fn main() -> ! { pwm.enable(Channel::C1); let pwm_max = pwm.get_max_duty() as u16; //48000 in our case - let mut pwm_debug = 0; - let mut isInit = false; + // ====================== Timer setup ================= + let timer = Timer::new(pwm, &mut clocks); + let mut input_count_down = timer.count_down(); + input_count_down.start(50.millis()); + loop { - // Poll USB - if !usb_dev.poll(&mut [&mut serial]) { - continue; - } - - // Read serial data and set PWM - let mut buf = [0u8; 64]; - - match serial.read(&mut buf) { - Ok(count) => { - isInit = true; - let tmpBuf = format!("{:?}", &buf); - let pwm_duty = tmpBuf.chars().map(|c| c.to_digit(RADIX).unwrap()).sum::(); - // TODO get value and set PWM - pwm.set_duty(Channel::C1, pwm_duty); - } - _ => { - if !isInit { - continue; - } - } - } - - // Get data from pots - let data: u16 = adc1.read(&mut ch0).unwrap(); - let mut pwm_val = data as f32 / 0xfff as f32; - - let mut outBuf = ryu::Buffer::new(); - let mut ret = outBuf.format(pwm_val).as_bytes(); - - // Write serial data - // NOTE: Make sure not to ever run in here before a successful read! - if isInit { - while !ret.is_empty() { - match serial.write(ret) { - Ok(count) => { - ret = &ret[count..]; + //Poll the every 10ms + if input_count_down.wait().is_ok() { + let report = get_report(&input_pins); + if report != last { + match consumer.device().write_report(&report) { + Err(UsbError::WouldBlock) => {} + Ok(_) => { + last = report; + } + Err(e) => { + core::panic!("Failed to write consumer report: {:?}", e) } - _ => {continue;}, } } - serial.write(b"\n"); } - // Sleep so we don't send that quickly - delay(clocks.sysclk().raw() / 10); + if usb_dev.poll(&mut [&mut consumer]) {} + + // TODO get value and set PWM + //pwm.set_duty(Channel::C1, pwm_duty); + +// // Get data from pots +// let data: u16 = adc1.read(&mut ch0).unwrap(); +// let mut pwm_val = data as f32 / 0xfff as f32; +// +// let mut outBuf = ryu::Buffer::new(); +// let mut ret = outBuf.format(pwm_val).as_bytes(); } } +fn get_report( + pins: &[&dyn InputPin; 2], +) -> MultipleConsumerReport { + #[rustfmt::skip] + let pins = [ +// pins[0].is_low().unwrap() { Consumer::PlayPause } else { Consumer::Unassigned }, +// pins[1].is_low().unwrap() { Consumer::ScanPreviousTrack } else { Consumer::Unassigned }, + ]; + + let mut report = MultipleConsumerReport { + codes: [Consumer::Unassigned; 4], + }; + + let mut it = pins.iter().filter(|&&c| c != Consumer::Unassigned); + for c in report.codes.iter_mut() { + if let Some(&code) = it.next() { + *c = code; + } else { + break; + } + } + report +}