#![no_std] #![no_main] //extern crate panic_semihosting; mod cirque; mod log; use cirque::Cirque; use cortex_m::{ asm::{bkpt, wfi}, interrupt, }; use cortex_m_rt::entry; use embedded_hal::spi; use stm32f1xx_hal::{ pac, prelude::*, serial::{Config, Serial, StopBits, WordLength}, spi::Spi, usb::{self, UsbBus}, }; use usb_device::prelude::*; use usbd_serial::{SerialPort, USB_CLASS_CDC}; #[entry] fn main() -> ! { let dp = pac::Peripherals::take().unwrap(); let mut flash = dp.FLASH.constrain(); let rcc = dp.RCC.constrain(); let clocks = rcc .cfgr .use_hse(8.MHz()) .sysclk(72.MHz()) // TODO: gd32 can get up to 120MHz // .pclk1(24.MHz()) // TODO: causes issues with gd32 usb (dropped packets) and garbled usart1 output .freeze(&mut flash.acr); assert!(clocks.usbclk_valid()); let mut gpiob = dp.GPIOB.split(); let mut led = gpiob.pb2.into_push_pull_output(&mut gpiob.crl); led.set_low(); let mut afio = dp.AFIO.constrain(); let mut gpioa = dp.GPIOA.split(); let tx_pin = gpioa.pa9.into_alternate_push_pull(&mut gpioa.crh); let rx_pin = gpioa.pa10; let serial = Serial::usart1( dp.USART1, (tx_pin, rx_pin), &mut afio.mapr, Config::default() .baudrate(115200.bps()) .wordlength(WordLength::Bits8) .parity_none() .stopbits(StopBits::STOP1), clocks, ); let (tx, _) = serial.split(); log::init(tx); logln!("luchie starting…"); // cirque spi connections to spi1: // // pb0 - dr // pa4 - ss1 // pa5 - clk1 // pa6 - miso1 // pa7 - mosi1 logln!("init trackpad"); // TODO: hook an interrupt up to the dr pin to trigger a poll. //let dr_pin = gpiob.pb1.into_pull_down_input(&mut gpiob.crl); let sck_pin = gpioa.pa5.into_alternate_push_pull(&mut gpioa.crl); let miso_pin = gpioa.pa6; let mosi_pin = gpioa.pa7.into_alternate_push_pull(&mut gpioa.crl); let cs_pin = gpioa.pa4.into_push_pull_output(&mut gpioa.crl); let mut spi = Spi::spi1( dp.SPI1, (sck_pin, miso_pin, mosi_pin), &mut afio.mapr, spi::MODE_1, 1_000_000.Hz(), // pinnacle supports up to 13mhz clocks, ); let mut cirque = match Cirque::new(cs_pin, &mut spi, clocks) { Ok(c) => c, Err(e) => { logln!("err: {:?}", e); panic!(); } }; logln!("init usb"); // BluePill board has a pull-up resistor on the D+ line. // Pull the D+ pin down to send a RESET condition to the USB bus. // This forced reset is needed only for development, without it host // will not reset your device when you upload new firmware. let mut usb_dp = gpioa.pa12.into_push_pull_output(&mut gpioa.crh); usb_dp.set_low(); // let mut delay = dp.TIM2.delay_us(&clocks); // delay.delay_ms(10u8); cortex_m::asm::delay(clocks.sysclk().raw() / 100); let usb = usb::Peripheral { usb: dp.USB, pin_dm: gpioa.pa11, pin_dp: usb_dp.into_floating_input(&mut gpioa.crh), }; let usb_bus = UsbBus::new(usb); let mut serial = SerialPort::new(&usb_bus); let mut usb_dev = UsbDeviceBuilder::new(&usb_bus, UsbVidPid(0xdead, 0xbeef)) .manufacturer("Fake company") .product("Serial port") .serial_number("TEST") .device_class(USB_CLASS_CDC) .build(); logln!("luchie started!"); loop { // logln!("."); if let Ok(mut td) = cirque.poll(&mut spi) { td.scale_to(1920, 1080); logln!("td: {:?}", td); } if !usb_dev.poll(&mut [&mut serial]) { continue; } let mut buf = [0u8; 64]; match serial.read(&mut buf) { Ok(count) if count > 0 => { led.set_high(); // Echo back in upper case for c in buf[0..count].iter_mut() { if 0x61 <= *c && *c <= 0x7a { *c &= !0x20; } } let mut write_offset = 0; while write_offset < count { match serial.write(&buf[write_offset..count]) { Ok(len) if len > 0 => { write_offset += len; } _ => {} } } led.set_low(); } _ => {} } } } #[panic_handler] fn panic(info: &core::panic::PanicInfo) -> ! { interrupt::free(|_cs| { log!("!!! panic "); if let Some(loc) = info.location() { log!("in {}:{} ", loc.file(), loc.line()); } if let Some(msg) = info.payload().downcast_ref::<&str>() { log!("⇒ {} ", msg); } logln!("!!!"); }); spin(); } fn spin() -> ! { bkpt(); loop { wfi(); } }