summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVegard Storheil Eriksen <zyp@jvnv.net>2015-04-09 01:36:51 +0200
committerVegard Storheil Eriksen <zyp@jvnv.net>2015-04-11 05:01:07 +0200
commit1cb55ca06ecbc3666d3bf66a583a768f69bf9278 (patch)
tree664388b7fe1cad3b1b50ed41acc7d5ae8cd0785b
parentcd8a8277bc31148673f9094cd0c64fd75778d989 (diff)
Add WS2812B output support.
-rw-r--r--arcin/main.cpp92
-rw-r--r--arcin/report_desc.h59
m---------laks0
3 files changed, 151 insertions, 0 deletions
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 <gpio/gpio.h>
#include <interrupt/interrupt.h>
#include <timer/timer.h>
+#include <dma/dma.h>
#include <adc/adc_f3.h>
#include <os/time.h>
#include <usb/usb.h>
@@ -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<Interrupt::DMA1_Channel7>() {
+ 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
-Subproject ebddcef73dbe544718ea5d607072fad36e1809d
+Subproject e520cc2d4b856658d338a5fcb8ecd65699b41c3