diff options
author | Vegard Storheil Eriksen <zyp@jvnv.net> | 2015-04-09 01:36:51 +0200 |
---|---|---|
committer | Vegard Storheil Eriksen <zyp@jvnv.net> | 2015-04-11 05:01:07 +0200 |
commit | 1cb55ca06ecbc3666d3bf66a583a768f69bf9278 (patch) | |
tree | 664388b7fe1cad3b1b50ed41acc7d5ae8cd0785b /arcin/main.cpp | |
parent | cd8a8277bc31148673f9094cd0c64fd75778d989 (diff) |
Add WS2812B output support.
Diffstat (limited to 'arcin/main.cpp')
-rw-r--r-- | arcin/main.cpp | 92 |
1 files changed, 92 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; |