From 1cb55ca06ecbc3666d3bf66a583a768f69bf9278 Mon Sep 17 00:00:00 2001 From: Vegard Storheil Eriksen Date: Thu, 9 Apr 2015 01:36:51 +0200 Subject: Add WS2812B output support. --- arcin/main.cpp | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++ arcin/report_desc.h | 59 ++++++++++++++++++++++++++++++++++ laks | 2 +- 3 files changed, 152 insertions(+), 1 deletion(-) diff --git a/arcin/main.cpp b/arcin/main.cpp index 538b6c1..cfb6598 100644 --- a/arcin/main.cpp +++ b/arcin/main.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -60,6 +61,92 @@ static Pin led2 = GPIOA[9]; USB_f1 usb(USB, dev_desc_p, conf_desc_p); +class WS2812B { + private: + uint8_t dmabuf[25]; + volatile uint32_t cnt; + volatile bool busy; + + void schedule_dma() { + cnt--; + + DMA1.reg.C[6].NDTR = 25; + DMA1.reg.C[6].MAR = (uint32_t)&dmabuf; + DMA1.reg.C[6].PAR = (uint32_t)&TIM4.CCR3; + DMA1.reg.C[6].CR = (0 << 10) | (1 << 8) | (1 << 7) | (0 << 6) | (1 << 4) | (1 << 1) | (1 << 0); + } + + void set_color(uint8_t r, uint8_t g, uint8_t b) { + uint32_t n = 0; + + for(uint32_t i = 8; i-- > 0; n++) { + dmabuf[n] = g & (1 << i) ? 58 : 29; + } + + for(uint32_t i = 8; i-- > 0; n++) { + dmabuf[n] = r & (1 << i) ? 58 : 29; + } + + for(uint32_t i = 8; i-- > 0; n++) { + dmabuf[n] = b & (1 << i) ? 58 : 29; + } + + dmabuf[n] = 0; + } + + public: + void init() { + RCC.enable(RCC.TIM4); + RCC.enable(RCC.DMA1); + + Interrupt::enable(Interrupt::DMA1_Channel7); + + TIM4.ARR = (72000000 / 800000) - 1; // period = 90, 0 = 29, 1 = 58 + TIM4.CCR3 = 0; + + TIM4.CCMR2 = (6 << 4) | (1 << 3); + TIM4.CCER = 1 << 8; + TIM4.DIER = 1 << 8; + + GPIOB[8].set_af(2); + GPIOB[8].set_mode(Pin::AF); + GPIOB[8].set_pull(Pin::PullNone); + + TIM4.CR1 = 1 << 0; + + Time::sleep(1); + + update(0, 0, 0); + } + + void update(uint8_t r, uint8_t g, uint8_t b) { + set_color(r, g, b); + + cnt = 15; + busy = true; + + schedule_dma(); + } + + void irq() { + DMA1.reg.C[6].CR = 0; + DMA1.reg.IFCR = 1 << 24; + + if(cnt) { + schedule_dma(); + } else { + busy = false; + } + } +}; + +WS2812B ws2812b; + +template <> +void interrupt() { + ws2812b.irq(); +} + uint32_t last_led_time; class HID_arcin : public USB_HID { @@ -115,6 +202,9 @@ class HID_arcin : public USB_HID { last_led_time = Time::time(); button_leds.set(report->leds); + + ws2812b.update(report->r, report->b, report->g); + return true; } @@ -313,6 +403,8 @@ int main() { axis_2 = &axis_qe2; } + ws2812b.init(); + uint8_t last_x = 0; uint8_t last_y = 0; diff --git a/arcin/report_desc.h b/arcin/report_desc.h index b9602b7..7acd314 100644 --- a/arcin/report_desc.h +++ b/arcin/report_desc.h @@ -28,6 +28,8 @@ auto report_desc = gamepad( // Outputs. report_id(2), + logical_minimum(0), + logical_maximum(1), usage_page(UsagePage::Ordinal), usage(1), @@ -141,6 +143,58 @@ auto report_desc = gamepad( padding_out(5), + logical_maximum(255), + + usage_page(UsagePage::Ordinal), + usage(12), + collection(Collection::Logical, + usage_page(UsagePage::LED), + usage(0x4b), + report_size(8), + report_count(1), + output(0x02) + ), + + usage_page(UsagePage::Ordinal), + usage(13), + collection(Collection::Logical, + usage_page(UsagePage::LED), + usage(0x4b), + report_size(8), + report_count(1), + output(0x02) + ), + + usage_page(UsagePage::Ordinal), + usage(14), + collection(Collection::Logical, + usage_page(UsagePage::LED), + usage(0x4b), + report_size(8), + report_count(1), + output(0x02) + ), + + usage_page(UsagePage::Ordinal), + usage(15), + collection(Collection::Logical, + usage_page(UsagePage::LED), + usage(0x4b), + report_size(8), + report_count(1), + output(0x02) + ), + + usage_page(UsagePage::Ordinal), + usage(16), + collection(Collection::Logical, + usage_page(UsagePage::LED), + usage(0x4b), + report_size(8), + report_count(1), + output(0x02) + ), + // Bootloader report_id(0xb0), @@ -179,6 +233,11 @@ struct input_report_t { struct output_report_t { uint8_t report_id; uint16_t leds; + uint8_t led1; + uint8_t led2; + uint8_t r; + uint8_t g; + uint8_t b; } __attribute__((packed)); struct bootloader_report_t { diff --git a/laks b/laks index ebddcef..e520cc2 160000 --- a/laks +++ b/laks @@ -1 +1 @@ -Subproject commit ebddcef73dbe544718ea5d607072fad36e1809d4 +Subproject commit e520cc2d4b856658d338a5fcb8ecd65699b41c38 -- cgit v1.2.3