#include #include #include #include #include #include #include #include #include auto dev_desc = device_desc(0x200, 0, 0, 0, 64, 0x1d50, 0x60f8, 0, 0, 0, 0, 1); auto conf_desc = configuration_desc(1, 1, 0, 0xc0, 0, interface_desc(1, 0, 1, 0xff, 0x00, 0x00, 0, endpoint_desc(0x81, 0x02, 64, 0) ) ); desc_t dev_desc_p = {sizeof(dev_desc), (void*)&dev_desc}; desc_t conf_desc_p = {sizeof(conf_desc), (void*)&conf_desc}; USB_l0 usb(USB, dev_desc_p, conf_desc_p); Pin nfc_sck = GPIOB[3]; Pin nfc_miso = GPIOB[4]; Pin nfc_mosi = GPIOB[5]; Pin nfc_ss = GPIOB[6]; Pin nfc_irq_out = GPIOB[7]; Pin nfc_irq_in = GPIOC[13]; Pin button = GPIOA[3]; Pin led = GPIOA[4]; class CR95HF { private: SPI_t& spi; Pin& ss; public: CR95HF(SPI_t& spi_bus, Pin& p) : spi(spi_bus), ss(p) {} void send_cmd(uint8_t cmd, uint32_t len, uint8_t* buf) { ss.off(); spi.transfer_byte(0); spi.transfer_byte(cmd); spi.transfer_byte(len); while(len--) { spi.transfer_byte(*buf++); } ss.on(); } uint32_t get_response(uint32_t maxlen, uint8_t* buf) { uint32_t len = 0; while(nfc_irq_out.get()); ss.off(); spi.transfer_byte(2); *buf++ = spi.transfer_byte(); len++; uint32_t datalen = spi.transfer_byte(); *buf++ = datalen; len++; while(len < datalen + 2) { *buf++ = spi.transfer_byte(); len++; } ss.on(); return len; } }; CR95HF cr95hf(SPI1, nfc_ss); class USB_NFC : public USB_class_driver { private: USB_generic& usb; public: USB_NFC(USB_generic& usbd) : usb(usbd) { usb.register_driver(this); } protected: virtual void handle_set_configuration(uint8_t configuration) { if(configuration) { usb.hw_conf_ep(0x81, EPType::Bulk, 64); } } }; USB_NFC usb_nfc(usb); int main() { rcc_init(); // Initialize system timer. STK.LOAD = 32000000 / 8 / 1000; // 1000 Hz. STK.VAL = 0; STK.CTRL = 0x03; // Enable CRS. RCC.enable(RCC.CRS); CRS.enable(); RCC.enable(RCC.GPIOA); RCC.enable(RCC.GPIOB); RCC.enable(RCC.GPIOC); led.set_mode(Pin::Output); RCC.enable(RCC.USB); usb.init(); Time::sleep(10); USB.reg.BCDR |= 1 << 15; RCC.enable(RCC.SPI1); nfc_irq_out.set_mode(Pin::Input); nfc_irq_in.on(); nfc_irq_in.set_mode(Pin::Output); nfc_ss.on(); nfc_ss.set_mode(Pin::Output); nfc_sck.set_speed(Pin::High); nfc_sck.set_mode(Pin::AF); nfc_miso.set_mode(Pin::AF); nfc_mosi.set_mode(Pin::AF); SPI1.reg.CR1 = (1 << 9) | (1 << 8) | (1 << 6) | (4 << 3) | (1 << 2) | (0 << 1) | (0 << 0); // SSM, SSI, SPE, 36/32MHz, MSTR, CPOL=0, CPHA=0 SPI1.reg.CR2 = (1 << 12) | (7 << 8); // FRXTH, DS = 8bit Time::sleep(1); nfc_irq_in.off(); Time::sleep(1); nfc_irq_in.on(); Time::sleep(1); uint8_t buf[64]; bool cmd_sent = false; uint32_t nfc_delay_until = 0; uint8_t bulk_buf[8]; Time::sleep(1000); cr95hf.send_cmd(0x02, 2, (uint8_t*)"\x01\x05"); // Select ISO 15693 cr95hf.get_response(64, buf); while(1) { if(Time::time() < nfc_delay_until) { // Just do nothing. } else if(!cmd_sent) { led.off(); cr95hf.send_cmd(0x04, 3, (uint8_t*)"\x26\x01\x00"); // INVENTORY cmd_sent = true; } else if(!nfc_irq_out.get()) { cr95hf.get_response(64, buf); cmd_sent = false; if(buf[0] == 128 && buf[14] == 0) { led.on(); uint8_t* id_raw = &buf[11]; uint8_t* id_buf = bulk_buf; for(uint32_t i = 0; i < 8; i++) { *id_buf++ = *id_raw--; } if(usb.ep_ready(1)) { usb.write(1, (uint32_t*)bulk_buf, sizeof(bulk_buf)); } nfc_delay_until = Time::time() + 5000; // Valid for five seconds. } else { nfc_delay_until = Time::time() + 100; // Retry in 100ms. } } usb.process(); } }