#include #include "NeoPixel.h" #include "Timer.h" #include "DMA.h" #include "SPI.h" #include "ADC.h" static uint8_t pixel_buffer[NUM_PIXELS * 3]; // 3 bytes per pixel (G-R-B) static uint8_t dma_buffer[NUM_PIXELS * 3 * 3 + 90]; // each byte is expanded to 3 bytes + 90 bytes (zero) for latching static const uint32_t bit_expand[256]; // lookup table for bit expansion static Animation current_animation; static int frame; void NeoPixel_init(void) { /* initialize pixel buffer */ NeoPixel_clear_pixels(); /* initialize DMA buffer */ for (int i = 0 ; i < sizeof dma_buffer ; i++) dma_buffer[i] = 0x00; /* configure and enable DMA controller */ /* set up transfer descriptor */ DmacDescriptor descriptor; descriptor.DSTADDR.reg = (uint32_t)&SERCOM0->SPI.DATA; // destination address is SPI DATA register descriptor.SRCADDR.reg = (uint32_t)(dma_buffer + sizeof dma_buffer); // source address is the DMA buffer descriptor.DESCADDR.reg = 0; // only one transfer descriptor descriptor.BTCTRL.bit.BEATSIZE = DMAC_BTCTRL_BEATSIZE_BYTE_Val; // beat size is one byte descriptor.BTCTRL.bit.DSTINC = 0; // destination address increment disabled descriptor.BTCTRL.bit.SRCINC = 1; // source address increment enabled descriptor.BTCTRL.bit.STEPSEL = DMAC_BTCTRL_STEPSEL_SRC_Val; // flexible source address increment size descriptor.BTCTRL.bit.STEPSIZE = DMAC_BTCTRL_STEPSIZE_X1_Val; // source address increment is one byte descriptor.BTCTRL.bit.BLOCKACT = DMAC_BTCTRL_BLOCKACT_NOACT_Val; // request interrupt at end of block transfer descriptor.BTCNT.reg = sizeof dma_buffer; // beat count descriptor.BTCTRL.bit.VALID = 1; // descriptor is valid /* initialize DMA controller */ DMA_init(); /* add and enable SERCOM0 (SPI) channel */ DMA_add_channel(DMA_SOURCE_SERCOM0, &descriptor); /* enable DMA */ DMA_enable(); /* initialize timer */ Timer_init(); /* initialize SPI */ SPI_init(); } /* set pixel color (pixel are numbered from 0 to NUM_PIXELS - 1) */ void NeoPixel_set_pixel(int pixel, uint8_t red, uint8_t green, uint8_t blue) { if (pixel < 0 || pixel >= NUM_PIXELS) return; int n = pixel * 3; pixel_buffer[n] = green; pixel_buffer[n + 1] = red; pixel_buffer[n + 2] = blue; } /* all pixels off */ void NeoPixel_clear_pixels(void) { for (int i = 0 ; i < NUM_PIXELS * 3 ; i++) pixel_buffer[i] = 0; } /* update DMA buffer */ void NeoPixel_update(void) { for (int i = 0, j = 0 ; i < sizeof pixel_buffer ; i++, j += 3) { uint32_t expanded = bit_expand[pixel_buffer[i]]; dma_buffer[j] = expanded >> 16; dma_buffer[j + 1] = expanded >> 8; dma_buffer[j + 2] = expanded; } } void NeoPixel_update_animation(void) { static int v = 1; static int on = 0; int sound_value = 0; if (frame_time) // if all DMA transfers for a frame has occurred { frame_time = 0; // acknowledge/clear flag from timer /* update pixel buffer */ switch (current_animation) { case KITT: NeoPixel_clear_pixels(); NeoPixel_set_pixel(frame, 255, 0, 0); NeoPixel_set_pixel(frame - v, 255, 0, 0); NeoPixel_set_pixel(frame - 2*v, 200, 0, 0); NeoPixel_set_pixel(frame - 3*v, 100, 0, 0); NeoPixel_set_pixel(frame - 4*v, 50, 0, 0); if (frame == NUM_PIXELS - 1 || frame == 0) v = -v; frame += v; break; case BREATHING: for (int i = 0 ; i < NUM_PIXELS ; i++) NeoPixel_set_pixel(i, 0 , 0, frame*4); if (frame == 63 || frame == 0) v = -v; frame += v; break; case BLINK: if (!(frame++ % 20)) if (!on) { on = 1; for (int i = 0 ; i < NUM_PIXELS ; i++) NeoPixel_set_pixel(i, 0, 255, 0); } else { on = 0; NeoPixel_clear_pixels(); } break; case SOUND: #define THRESHOLD 200 if (adc_value < THRESHOLD) // threshold sound_value = 0; else sound_value = (adc_value - THRESHOLD) * ((255.0 - 0.0)/(400.0 - THRESHOLD)); // linear map: y = (x - x1) * (y2 - y1)/(x2 - x1) if (sound_value >= 255) sound_value = 255; for (int i = 0 ; i < NUM_PIXELS ; i++) NeoPixel_set_pixel(i, sound_value, sound_value, 0); break; default: break; } /* send frame to DMA buffer */ NeoPixel_update(); } } void NeoPixel_set_animation(Animation animation) { current_animation = animation; if (animation == SOUND) ADC_init(); else ADC_deinit(); frame = 1; NeoPixel_clear_pixels(); } /* bit expansion lookup table */ static const uint32_t bit_expand[256] = { 0b100100100100100100100100, 0b100100100100100100100110, 0b100100100100100100110100, 0b100100100100100100110110, 0b100100100100100110100100, 0b100100100100100110100110, 0b100100100100100110110100, 0b100100100100100110110110, 0b100100100100110100100100, 0b100100100100110100100110, 0b100100100100110100110100, 0b100100100100110100110110, 0b100100100100110110100100, 0b100100100100110110100110, 0b100100100100110110110100, 0b100100100100110110110110, 0b100100100110100100100100, 0b100100100110100100100110, 0b100100100110100100110100, 0b100100100110100100110110, 0b100100100110100110100100, 0b100100100110100110100110, 0b100100100110100110110100, 0b100100100110100110110110, 0b100100100110110100100100, 0b100100100110110100100110, 0b100100100110110100110100, 0b100100100110110100110110, 0b100100100110110110100100, 0b100100100110110110100110, 0b100100100110110110110100, 0b100100100110110110110110, 0b100100110100100100100100, 0b100100110100100100100110, 0b100100110100100100110100, 0b100100110100100100110110, 0b100100110100100110100100, 0b100100110100100110100110, 0b100100110100100110110100, 0b100100110100100110110110, 0b100100110100110100100100, 0b100100110100110100100110, 0b100100110100110100110100, 0b100100110100110100110110, 0b100100110100110110100100, 0b100100110100110110100110, 0b100100110100110110110100, 0b100100110100110110110110, 0b100100110110100100100100, 0b100100110110100100100110, 0b100100110110100100110100, 0b100100110110100100110110, 0b100100110110100110100100, 0b100100110110100110100110, 0b100100110110100110110100, 0b100100110110100110110110, 0b100100110110110100100100, 0b100100110110110100100110, 0b100100110110110100110100, 0b100100110110110100110110, 0b100100110110110110100100, 0b100100110110110110100110, 0b100100110110110110110100, 0b100100110110110110110110, 0b100110100100100100100100, 0b100110100100100100100110, 0b100110100100100100110100, 0b100110100100100100110110, 0b100110100100100110100100, 0b100110100100100110100110, 0b100110100100100110110100, 0b100110100100100110110110, 0b100110100100110100100100, 0b100110100100110100100110, 0b100110100100110100110100, 0b100110100100110100110110, 0b100110100100110110100100, 0b100110100100110110100110, 0b100110100100110110110100, 0b100110100100110110110110, 0b100110100110100100100100, 0b100110100110100100100110, 0b100110100110100100110100, 0b100110100110100100110110, 0b100110100110100110100100, 0b100110100110100110100110, 0b100110100110100110110100, 0b100110100110100110110110, 0b100110100110110100100100, 0b100110100110110100100110, 0b100110100110110100110100, 0b100110100110110100110110, 0b100110100110110110100100, 0b100110100110110110100110, 0b100110100110110110110100, 0b100110100110110110110110, 0b100110110100100100100100, 0b100110110100100100100110, 0b100110110100100100110100, 0b100110110100100100110110, 0b100110110100100110100100, 0b100110110100100110100110, 0b100110110100100110110100, 0b100110110100100110110110, 0b100110110100110100100100, 0b100110110100110100100110, 0b100110110100110100110100, 0b100110110100110100110110, 0b100110110100110110100100, 0b100110110100110110100110, 0b100110110100110110110100, 0b100110110100110110110110, 0b100110110110100100100100, 0b100110110110100100100110, 0b100110110110100100110100, 0b100110110110100100110110, 0b100110110110100110100100, 0b100110110110100110100110, 0b100110110110100110110100, 0b100110110110100110110110, 0b100110110110110100100100, 0b100110110110110100100110, 0b100110110110110100110100, 0b100110110110110100110110, 0b100110110110110110100100, 0b100110110110110110100110, 0b100110110110110110110100, 0b100110110110110110110110, 0b110100100100100100100100, 0b110100100100100100100110, 0b110100100100100100110100, 0b110100100100100100110110, 0b110100100100100110100100, 0b110100100100100110100110, 0b110100100100100110110100, 0b110100100100100110110110, 0b110100100100110100100100, 0b110100100100110100100110, 0b110100100100110100110100, 0b110100100100110100110110, 0b110100100100110110100100, 0b110100100100110110100110, 0b110100100100110110110100, 0b110100100100110110110110, 0b110100100110100100100100, 0b110100100110100100100110, 0b110100100110100100110100, 0b110100100110100100110110, 0b110100100110100110100100, 0b110100100110100110100110, 0b110100100110100110110100, 0b110100100110100110110110, 0b110100100110110100100100, 0b110100100110110100100110, 0b110100100110110100110100, 0b110100100110110100110110, 0b110100100110110110100100, 0b110100100110110110100110, 0b110100100110110110110100, 0b110100100110110110110110, 0b110100110100100100100100, 0b110100110100100100100110, 0b110100110100100100110100, 0b110100110100100100110110, 0b110100110100100110100100, 0b110100110100100110100110, 0b110100110100100110110100, 0b110100110100100110110110, 0b110100110100110100100100, 0b110100110100110100100110, 0b110100110100110100110100, 0b110100110100110100110110, 0b110100110100110110100100, 0b110100110100110110100110, 0b110100110100110110110100, 0b110100110100110110110110, 0b110100110110100100100100, 0b110100110110100100100110, 0b110100110110100100110100, 0b110100110110100100110110, 0b110100110110100110100100, 0b110100110110100110100110, 0b110100110110100110110100, 0b110100110110100110110110, 0b110100110110110100100100, 0b110100110110110100100110, 0b110100110110110100110100, 0b110100110110110100110110, 0b110100110110110110100100, 0b110100110110110110100110, 0b110100110110110110110100, 0b110100110110110110110110, 0b110110100100100100100100, 0b110110100100100100100110, 0b110110100100100100110100, 0b110110100100100100110110, 0b110110100100100110100100, 0b110110100100100110100110, 0b110110100100100110110100, 0b110110100100100110110110, 0b110110100100110100100100, 0b110110100100110100100110, 0b110110100100110100110100, 0b110110100100110100110110, 0b110110100100110110100100, 0b110110100100110110100110, 0b110110100100110110110100, 0b110110100100110110110110, 0b110110100110100100100100, 0b110110100110100100100110, 0b110110100110100100110100, 0b110110100110100100110110, 0b110110100110100110100100, 0b110110100110100110100110, 0b110110100110100110110100, 0b110110100110100110110110, 0b110110100110110100100100, 0b110110100110110100100110, 0b110110100110110100110100, 0b110110100110110100110110, 0b110110100110110110100100, 0b110110100110110110100110, 0b110110100110110110110100, 0b110110100110110110110110, 0b110110110100100100100100, 0b110110110100100100100110, 0b110110110100100100110100, 0b110110110100100100110110, 0b110110110100100110100100, 0b110110110100100110100110, 0b110110110100100110110100, 0b110110110100100110110110, 0b110110110100110100100100, 0b110110110100110100100110, 0b110110110100110100110100, 0b110110110100110100110110, 0b110110110100110110100100, 0b110110110100110110100110, 0b110110110100110110110100, 0b110110110100110110110110, 0b110110110110100100100100, 0b110110110110100100100110, 0b110110110110100100110100, 0b110110110110100100110110, 0b110110110110100110100100, 0b110110110110100110100110, 0b110110110110100110110100, 0b110110110110100110110110, 0b110110110110110100100100, 0b110110110110110100100110, 0b110110110110110100110100, 0b110110110110110100110110, 0b110110110110110110100100, 0b110110110110110110100110, 0b110110110110110110110100, 0b110110110110110110110110 };