aboutsummaryrefslogtreecommitdiffstats
path: root/sw/eval-clock-cw-tx/src/usb.rs
blob: e803c91314fbb2e4fab4b9843bacfc52b17b9a21 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
use core::fmt::Write;
use stm32f1xx_hal::gpio;
use stm32f1xx_hal::pac;
use stm32f1xx_hal::pac::{interrupt, Interrupt};
use stm32f1xx_hal::usb::{Peripheral, UsbBus, UsbBusType};
use usb_device::{bus::UsbBusAllocator, prelude::*};
use usbd_serial::{SerialPort, USB_CLASS_CDC};

static mut USB_BUS: Option<UsbBusAllocator<UsbBusType>> = None;
static mut USB_SERIAL: Option<usbd_serial::SerialPort<UsbBusType>> = None;
static mut USB_DEVICE: Option<UsbDevice<UsbBusType>> = None;

pub struct USB {
}

impl USB {
    pub fn new(
        usb: stm32f1xx_hal::pac::USB,
        pin_dm: gpio::gpioa::PA11<gpio::Input<gpio::Floating>>,
        pin_dp: gpio::gpioa::PA12<gpio::Input<gpio::Floating>>) -> Self {

        let peripheral = Peripheral {
            usb,
            pin_dm,
            pin_dp,
        };

        unsafe {
            let bus = UsbBus::new(peripheral);

            USB_BUS = Some(bus);

            USB_SERIAL = Some(SerialPort::new(USB_BUS.as_ref().unwrap()));

            let usb_dev = UsbDeviceBuilder::new(USB_BUS.as_ref().unwrap(), UsbVidPid(0x1d50, 0x5120)) // Openmoko Neo1973 serial
                .manufacturer("HB9EGM")
                .product("Beep Machine")
                .serial_number("1")
                .device_class(USB_CLASS_CDC)
                .build();

            USB_DEVICE = Some(usb_dev);
        }

        USB{}
    }

    pub fn enable_interrupts(&self) {
        unsafe {
            pac::NVIC::unmask(Interrupt::USB_HP_CAN_TX);
            pac::NVIC::unmask(Interrupt::USB_LP_CAN_RX0);
        }
    }
}

#[allow(non_snake_case)]
#[interrupt]
fn USB_HP_CAN_TX() {
    usb_interrupt();
}

#[allow(non_snake_case)]
#[interrupt]
fn USB_LP_CAN_RX0() {
    usb_interrupt();
}

fn usb_interrupt() {
    let usb_dev = unsafe { USB_DEVICE.as_mut().unwrap() };
    let serial = unsafe { USB_SERIAL.as_mut().unwrap() };

    if !usb_dev.poll(&mut [serial]) {
        return;
    }

    let mut buf = [0u8; 8];
    let mut string = arrayvec::ArrayString::<[_; 16]>::new();

    match serial.read(&mut buf) {
        Ok(count) if count > 0 => {
            // Echo back in upper case
            for c in buf[0..count].iter_mut() {
                write!(string, "{:02x}", *c).ok();
            }
            serial.write(string.as_bytes()).ok();
            string.clear();
        }
        _ => {}
    }
}