summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arcin/config.h15
-rw-r--r--arcin/configloader.h86
-rw-r--r--arcin/main.cpp373
-rw-r--r--arcin/report_desc.h197
-rw-r--r--arcin/usb_strings.h92
5 files changed, 395 insertions, 368 deletions
diff --git a/arcin/config.h b/arcin/config.h
new file mode 100644
index 0000000..a851e9c
--- /dev/null
+++ b/arcin/config.h
@@ -0,0 +1,15 @@
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#include <stdint.h>
+
+struct config_t {
+ uint8_t label[12];
+ uint32_t flags;
+ int8_t qe1_sens;
+ int8_t qe2_sens;
+ uint8_t ps2_mode;
+ uint8_t ws2812b_mode;
+};
+
+#endif
diff --git a/arcin/configloader.h b/arcin/configloader.h
new file mode 100644
index 0000000..0963a01
--- /dev/null
+++ b/arcin/configloader.h
@@ -0,0 +1,86 @@
+#ifndef CONFIGLOADER_H
+#define CONFIGLOADER_H
+
+#include <rcc/flash.h>
+#include <string.h>
+
+class Configloader {
+ private:
+ enum {
+ MAGIC = 0xc0ff600d,
+ };
+
+ struct header_t {
+ uint32_t magic;
+ uint32_t size;
+ };
+
+ uint32_t flash_addr;
+
+ public:
+ Configloader(uint32_t addr) : flash_addr(addr) {}
+
+ bool read(uint32_t size, void* data) {
+ header_t* header = (header_t*)flash_addr;
+
+ if(header->magic != MAGIC) {
+ return false;
+ }
+
+ if(header->size < size) {
+ size = header->size;
+ }
+
+ memcpy(data, (void*)(flash_addr + sizeof(header_t)), size);
+
+ return true;
+ }
+
+ bool write(uint32_t size, void* data) {
+ header_t header = {MAGIC, size};
+
+ // Unlock flash.
+ FLASH.KEYR = 0x45670123;
+ FLASH.KEYR = 0xCDEF89AB;
+
+ // Erase page.
+ FLASH.CR = 1 << 1; // PER
+ FLASH.AR = flash_addr;
+ FLASH.CR = (1 << 6) | (1 << 1); // STRT, PER
+
+ while(FLASH.SR & (1 << 0)); // BSY
+
+ FLASH.SR &= ~(1 << 5); // EOP
+ FLASH.CR = 0;
+
+ // Write header.
+ uint16_t* src = (uint16_t*)&header;
+ uint16_t* dest = (uint16_t*)flash_addr;
+
+ for(uint32_t n = 0; n < sizeof(header); n += 2) {
+ FLASH.CR = 1 << 0; // PG
+
+ *dest++ = *src++;
+
+ while(FLASH.SR & (1 << 0)); // BSY
+ }
+
+ // Write data.
+ src = (uint16_t*)data;
+
+ for(uint32_t n = 0; n < size; n += 2) {
+ FLASH.CR = 1 << 0; // PG
+
+ *dest++ = *src++;
+
+ while(FLASH.SR & (1 << 0)); // BSY
+ }
+
+ // Lock flash.
+ FLASH.CR = 1 << 7; // LOCK
+
+ return true;
+ }
+};
+
+#endif
diff --git a/arcin/main.cpp b/arcin/main.cpp
index 5294b29..8f6abc3 100644
--- a/arcin/main.cpp
+++ b/arcin/main.cpp
@@ -1,14 +1,15 @@
#include <rcc/rcc.h>
-#include <rcc/flash.h>
#include <gpio/gpio.h>
#include <interrupt/interrupt.h>
#include <timer/timer.h>
#include <os/time.h>
#include <usb/usb.h>
#include <usb/descriptor.h>
-#include <usb/hid.h>
-#include <string.h>
+#include "report_desc.h"
+#include "usb_strings.h"
+#include "configloader.h"
+#include "config.h"
static uint32_t& reset_reason = *(uint32_t*)0x10000000;
@@ -24,289 +25,10 @@ void reset_bootloader() {
reset();
}
-class Configloader {
- private:
- enum {
- MAGIC = 0xc0ff600d,
- };
-
- struct header_t {
- uint32_t magic;
- uint32_t size;
- };
-
- uint32_t flash_addr;
-
- public:
- Configloader(uint32_t addr) : flash_addr(addr) {}
-
- bool read(uint32_t size, void* data) {
- header_t* header = (header_t*)flash_addr;
-
- if(header->magic != MAGIC) {
- return false;
- }
-
- if(header->size < size) {
- size = header->size;
- }
-
- memcpy(data, (void*)(flash_addr + sizeof(header_t)), size);
-
- return true;
- }
-
- bool write(uint32_t size, void* data) {
- header_t header = {MAGIC, size};
-
- // Unlock flash.
- FLASH.KEYR = 0x45670123;
- FLASH.KEYR = 0xCDEF89AB;
-
- // Erase page.
- FLASH.CR = 1 << 1; // PER
- FLASH.AR = flash_addr;
- FLASH.CR = (1 << 6) | (1 << 1); // STRT, PER
-
- while(FLASH.SR & (1 << 0)); // BSY
-
- FLASH.SR &= ~(1 << 5); // EOP
- FLASH.CR = 0;
-
- // Write header.
- uint16_t* src = (uint16_t*)&header;
- uint16_t* dest = (uint16_t*)flash_addr;
-
- for(uint32_t n = 0; n < sizeof(header); n += 2) {
- FLASH.CR = 1 << 0; // PG
-
- *dest++ = *src++;
-
- while(FLASH.SR & (1 << 0)); // BSY
- }
-
- // Write data.
- src = (uint16_t*)data;
-
- for(uint32_t n = 0; n < size; n += 2) {
- FLASH.CR = 1 << 0; // PG
-
- *dest++ = *src++;
-
- while(FLASH.SR & (1 << 0)); // BSY
- }
-
- // Lock flash.
- FLASH.CR = 1 << 7; // LOCK
-
- return true;
- }
-};
-
Configloader configloader(0x801f800);
-struct config_t {
- uint8_t label[12];
- uint32_t flags;
- int8_t qe1_sens;
- int8_t qe2_sens;
- uint8_t ps2_mode;
- uint8_t ws2812b_mode;
-};
-
config_t config;
-auto report_desc = gamepad(
- // Inputs.
- report_id(1),
-
- buttons(15),
- padding_in(1),
-
- usage_page(UsagePage::Desktop),
- usage(DesktopUsage::X),
- logical_minimum(0),
- logical_maximum(255),
- report_count(1),
- report_size(8),
- input(0x02),
-
- usage_page(UsagePage::Desktop),
- usage(DesktopUsage::Y),
- logical_minimum(0),
- logical_maximum(255),
- report_count(1),
- report_size(8),
- input(0x02),
-
- // Outputs.
- report_id(2),
-
- usage_page(UsagePage::Ordinal),
- usage(1),
- collection(Collection::Logical,
- usage_page(UsagePage::LED),
- usage(0x4b),
- report_size(1),
- report_count(1),
- output(0x02)
- ),
-
- usage_page(UsagePage::Ordinal),
- usage(2),
- collection(Collection::Logical,
- usage_page(UsagePage::LED),
- usage(0x4b),
- report_size(1),
- report_count(1),
- output(0x02)
- ),
-
- usage_page(UsagePage::Ordinal),
- usage(3),
- collection(Collection::Logical,
- usage_page(UsagePage::LED),
- usage(0x4b),
- report_size(1),
- report_count(1),
- output(0x02)
- ),
-
- usage_page(UsagePage::Ordinal),
- usage(4),
- collection(Collection::Logical,
- usage_page(UsagePage::LED),
- usage(0x4b),
- report_size(1),
- report_count(1),
- output(0x02)
- ),
-
- usage_page(UsagePage::Ordinal),
- usage(5),
- collection(Collection::Logical,
- usage_page(UsagePage::LED),
- usage(0x4b),
- report_size(1),
- report_count(1),
- output(0x02)
- ),
-
- usage_page(UsagePage::Ordinal),
- usage(6),
- collection(Collection::Logical,
- usage_page(UsagePage::LED),
- usage(0x4b),
- report_size(1),
- report_count(1),
- output(0x02)
- ),
-
- usage_page(UsagePage::Ordinal),
- usage(7),
- collection(Collection::Logical,
- usage_page(UsagePage::LED),
- usage(0x4b),
- report_size(1),
- report_count(1),
- output(0x02)
- ),
-
- usage_page(UsagePage::Ordinal),
- usage(8),
- collection(Collection::Logical,
- usage_page(UsagePage::LED),
- usage(0x4b),
- report_size(1),
- report_count(1),
- output(0x02)
- ),
-
- usage_page(UsagePage::Ordinal),
- usage(9),
- collection(Collection::Logical,
- usage_page(UsagePage::LED),
- usage(0x4b),
- report_size(1),
- report_count(1),
- output(0x02)
- ),
-
- usage_page(UsagePage::Ordinal),
- usage(10),
- collection(Collection::Logical,
- usage_page(UsagePage::LED),
- usage(0x4b),
- report_size(1),
- report_count(1),
- output(0x02)
- ),
-
- usage_page(UsagePage::Ordinal),
- usage(11),
- collection(Collection::Logical,
- usage_page(UsagePage::LED),
- usage(0x4b),
- report_size(1),
- report_count(1),
- output(0x02)
- ),
-
- padding_out(5),
-
- // Bootloader
- report_id(0xb0),
-
- usage_page(0xff55),
- usage(0xb007),
- logical_minimum(0),
- logical_maximum(255),
- report_size(8),
- report_count(1),
-
- feature(0x02), // HID bootloader function
-
- // Configuration
- report_id(0xc0),
-
- usage(0xc000),
- feature(0x02), // Config segment
-
- usage(0xc001),
- feature(0x02), // Config segment size
-
- feature(0x01), // Padding
-
- usage(0xc0ff),
- report_count(60),
- feature(0x02) // Config data
-);
-
-struct input_report_t {
- uint8_t report_id;
- uint16_t buttons;
- uint8_t axis_x;
- uint8_t axis_y;
-} __attribute__((packed));
-
-struct output_report_t {
- uint8_t report_id;
- uint16_t leds;
-} __attribute__((packed));
-
-struct bootloader_report_t {
- uint8_t report_id;
- uint8_t func;
-} __attribute__((packed));
-
-struct config_report_t {
- uint8_t report_id;
- uint8_t segment;
- uint8_t size;
- uint8_t pad;
- uint8_t data[60];
-} __attribute__((packed));
-
auto dev_desc = device_desc(0x200, 0, 0, 0, 64, 0x1d50, 0x6080, 0x110, 1, 2, 3, 1);
auto conf_desc = configuration_desc(1, 1, 0, 0xc0, 0,
// HID interface.
@@ -429,92 +151,7 @@ class HID_arcin : public USB_HID {
HID_arcin usb_hid(usb, report_desc_p);
-uint32_t serial_num() {
- uint32_t* uid = (uint32_t*)0x1ffff7ac;
-
- return uid[0] * uid[1] * uid[2];
-}
-
-class USB_strings : public USB_class_driver {
- private:
- USB_generic& usb;
-
- public:
- USB_strings(USB_generic& usbd) : usb(usbd) {
- usb.register_driver(this);
- }
-
- protected:
- virtual SetupStatus handle_setup(uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, uint16_t wLength) {
- // Get string descriptor.
- if(bmRequestType == 0x80 && bRequest == 0x06 && (wValue & 0xff00) == 0x0300) {
- const void* desc = nullptr;
- uint16_t buf[64] = {0x300};
- uint32_t i = 1;
-
- switch(wValue & 0xff) {
- case 0:
- desc = u"\u0304\u0409";
- break;
-
- case 1:
- desc = u"\u0308zyp";
- break;
-
- case 2:
- for(const char* p = "arcin"; *p; p++) {
- buf[i++] = *p;
- }
-
- if(config.label[0]) {
- buf[i++] = ' ';
- buf[i++] = '(';
-
- for(uint8_t* p = config.label; *p; p++) {
- buf[i++] = *p;
- }
-
- buf[i++] = ')';
- }
-
- buf[0] |= i * 2;
-
- desc = buf;
- break;
-
- case 3:
- {
- buf[0] = 0x0312;
- uint32_t id = serial_num();
- for(int i = 8; i > 0; i--) {
- buf[i] = (id & 0xf) > 9 ? 'A' + (id & 0xf) - 0xa : '0' + (id & 0xf);
- id >>= 4;
- }
- desc = buf;
- }
- break;
- }
-
- if(!desc) {
- return SetupStatus::Unhandled;
- }
-
- uint8_t len = *(uint8_t*)desc;
-
- if(len > wLength) {
- len = wLength;
- }
-
- usb.write(0, (uint32_t*)desc, len);
-
- return SetupStatus::Ok;
- }
-
- return SetupStatus::Unhandled;
- }
-};
-
-USB_strings usb_strings(usb);
+USB_strings usb_strings(usb, config.label);
int main() {
rcc_init();
diff --git a/arcin/report_desc.h b/arcin/report_desc.h
new file mode 100644
index 0000000..b9602b7
--- /dev/null
+++ b/arcin/report_desc.h
@@ -0,0 +1,197 @@
+#ifndef REPORT_DESC_H
+#define REPORT_DESC_H
+
+#include <usb/hid.h>
+
+auto report_desc = gamepad(
+ // Inputs.
+ report_id(1),
+
+ buttons(15),
+ padding_in(1),
+
+ usage_page(UsagePage::Desktop),
+ usage(DesktopUsage::X),
+ logical_minimum(0),
+ logical_maximum(255),
+ report_count(1),
+ report_size(8),
+ input(0x02),
+
+ usage_page(UsagePage::Desktop),
+ usage(DesktopUsage::Y),
+ logical_minimum(0),
+ logical_maximum(255),
+ report_count(1),
+ report_size(8),
+ input(0x02),
+
+ // Outputs.
+ report_id(2),
+
+ usage_page(UsagePage::Ordinal),
+ usage(1),
+ collection(Collection::Logical,
+ usage_page(UsagePage::LED),
+ usage(0x4b),
+ report_size(1),
+ report_count(1),
+ output(0x02)
+ ),
+
+ usage_page(UsagePage::Ordinal),
+ usage(2),
+ collection(Collection::Logical,
+ usage_page(UsagePage::LED),
+ usage(0x4b),
+ report_size(1),
+ report_count(1),
+ output(0x02)
+ ),
+
+ usage_page(UsagePage::Ordinal),
+ usage(3),
+ collection(Collection::Logical,
+ usage_page(UsagePage::LED),
+ usage(0x4b),
+ report_size(1),
+ report_count(1),
+ output(0x02)
+ ),
+
+ usage_page(UsagePage::Ordinal),
+ usage(4),
+ collection(Collection::Logical,
+ usage_page(UsagePage::LED),
+ usage(0x4b),
+ report_size(1),
+ report_count(1),
+ output(0x02)
+ ),
+
+ usage_page(UsagePage::Ordinal),
+ usage(5),
+ collection(Collection::Logical,
+ usage_page(UsagePage::LED),
+ usage(0x4b),
+ report_size(1),
+ report_count(1),
+ output(0x02)
+ ),
+
+ usage_page(UsagePage::Ordinal),
+ usage(6),
+ collection(Collection::Logical,
+ usage_page(UsagePage::LED),
+ usage(0x4b),
+ report_size(1),
+ report_count(1),
+ output(0x02)
+ ),
+
+ usage_page(UsagePage::Ordinal),
+ usage(7),
+ collection(Collection::Logical,
+ usage_page(UsagePage::LED),
+ usage(0x4b),
+ report_size(1),
+ report_count(1),
+ output(0x02)
+ ),
+
+ usage_page(UsagePage::Ordinal),
+ usage(8),
+ collection(Collection::Logical,
+ usage_page(UsagePage::LED),
+ usage(0x4b),
+ report_size(1),
+ report_count(1),
+ output(0x02)
+ ),
+
+ usage_page(UsagePage::Ordinal),
+ usage(9),
+ collection(Collection::Logical,
+ usage_page(UsagePage::LED),
+ usage(0x4b),
+ report_size(1),
+ report_count(1),
+ output(0x02)
+ ),
+
+ usage_page(UsagePage::Ordinal),
+ usage(10),
+ collection(Collection::Logical,
+ usage_page(UsagePage::LED),
+ usage(0x4b),
+ report_size(1),
+ report_count(1),
+ output(0x02)
+ ),
+
+ usage_page(UsagePage::Ordinal),
+ usage(11),
+ collection(Collection::Logical,
+ usage_page(UsagePage::LED),
+ usage(0x4b),
+ report_size(1),
+ report_count(1),
+ output(0x02)
+ ),
+
+ padding_out(5),
+
+ // Bootloader
+ report_id(0xb0),
+
+ usage_page(0xff55),
+ usage(0xb007),
+ logical_minimum(0),
+ logical_maximum(255),
+ report_size(8),
+ report_count(1),
+
+ feature(0x02), // HID bootloader function
+
+ // Configuration
+ report_id(0xc0),
+
+ usage(0xc000),
+ feature(0x02), // Config segment
+
+ usage(0xc001),
+ feature(0x02), // Config segment size
+
+ feature(0x01), // Padding
+
+ usage(0xc0ff),
+ report_count(60),
+ feature(0x02) // Config data
+);
+
+struct input_report_t {
+ uint8_t report_id;
+ uint16_t buttons;
+ uint8_t axis_x;
+ uint8_t axis_y;
+} __attribute__((packed));
+
+struct output_report_t {
+ uint8_t report_id;
+ uint16_t leds;
+} __attribute__((packed));
+
+struct bootloader_report_t {
+ uint8_t report_id;
+ uint8_t func;
+} __attribute__((packed));
+
+struct config_report_t {
+ uint8_t report_id;
+ uint8_t segment;
+ uint8_t size;
+ uint8_t pad;
+ uint8_t data[60];
+} __attribute__((packed));
+
+#endif
diff --git a/arcin/usb_strings.h b/arcin/usb_strings.h
new file mode 100644
index 0000000..6463ba4
--- /dev/null
+++ b/arcin/usb_strings.h
@@ -0,0 +1,92 @@
+#ifndef USB_STRINGS_H
+#define USB_STRINGS_H
+
+#include <usb/usb.h>
+
+uint32_t serial_num() {
+ uint32_t* uid = (uint32_t*)0x1ffff7ac;
+
+ return uid[0] * uid[1] * uid[2];
+}
+
+class USB_strings : public USB_class_driver {
+ private:
+ USB_generic& usb;
+ const uint8_t* label;
+
+ public:
+ USB_strings(USB_generic& usbd, const uint8_t* l) : usb(usbd), label(l) {
+ usb.register_driver(this);
+ }
+
+ protected:
+ virtual SetupStatus handle_setup(uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, uint16_t wLength) {
+ // Get string descriptor.
+ if(bmRequestType == 0x80 && bRequest == 0x06 && (wValue & 0xff00) == 0x0300) {
+ const void* desc = nullptr;
+ uint16_t buf[64] = {0x300};
+ uint32_t i = 1;
+
+ switch(wValue & 0xff) {
+ case 0:
+ desc = u"\u0304\u0409";
+ break;
+
+ case 1:
+ desc = u"\u0308zyp";
+ break;
+
+ case 2:
+ for(const char* p = "arcin"; *p; p++) {
+ buf[i++] = *p;
+ }
+
+ if(label[0]) {
+ buf[i++] = ' ';
+ buf[i++] = '(';
+
+ for(const uint8_t* p = label; *p; p++) {
+ buf[i++] = *p;
+ }
+
+ buf[i++] = ')';
+ }
+
+ buf[0] |= i * 2;
+
+ desc = buf;
+ break;
+
+ case 3:
+ {
+ buf[0] = 0x0312;
+ uint32_t id = serial_num();
+ for(int i = 8; i > 0; i--) {
+ buf[i] = (id & 0xf) > 9 ? 'A' + (id & 0xf) - 0xa : '0' + (id & 0xf);
+ id >>= 4;
+ }
+ desc = buf;
+ }
+ break;
+ }
+
+ if(!desc) {
+ return SetupStatus::Unhandled;
+ }
+
+ uint8_t len = *(uint8_t*)desc;
+
+ if(len > wLength) {
+ len = wLength;
+ }
+
+ usb.write(0, (uint32_t*)desc, len);
+
+ return SetupStatus::Ok;
+ }
+
+ return SetupStatus::Unhandled;
+ }
+};
+
+#endif