/* * pixelhub.c * * DMX to neopixel interface * * Copyright © 2023 Thomas White * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with This program. If not, see . * */ #include #include #include const int dmx_rx_pin = 16; struct pixel_strip { int pin; int num_pixels; PIO pio; uint pio_sm; uint offset; uint32_t pixelbuf[256]; int rgbw; uint dma_chan; }; static inline void put_pixel(struct pixel_strip *p, uint32_t pixel_grb) { pio_sm_put_blocking(p->pio, p->pio_sm, pixel_grb); } static inline uint32_t urgb_u32(uint8_t r, uint8_t g, uint8_t b) { return ((uint32_t)(g)<<24) | ((uint32_t)(r)<<16) | ((uint32_t)(b)<<8); } static inline uint32_t wrgb_u32(uint8_t r, uint8_t g, uint8_t b, uint8_t w) { return ((uint32_t)(g)<<24) | ((uint32_t)(r)<<16) | ((uint32_t)(b)<<8) | (uint32_t)(w); } uint dma_chan; dma_channel_config dma_conf; struct pixel_strip pxs[8]; int n_pxs; int cur_strip = 0; static void set_dma() { channel_config_set_dreq(&dma_conf, pio_get_dreq(pxs[cur_strip].pio, pxs[cur_strip].pio_sm, true)); dma_channel_configure(dma_chan, &dma_conf, &pxs[cur_strip].pio->txf[pxs[cur_strip].pio_sm], pxs[cur_strip].pixelbuf, pxs[cur_strip].num_pixels, true); } static int64_t next_strip(alarm_id_t id, void *vp) { cur_strip++; if ( cur_strip >= n_pxs ) cur_strip = 0; set_dma(); return 0; } static void dma_complete() { if ( dma_hw->ints0 & 1<ints0 = 1<num_pixels; i++ ) { p->pixelbuf[i] = 0; } p->pio = pio; p->pio_sm = sm; p->offset = pio_add_program(p->pio, &ws2812_program); ws2812_program_init(p->pio, p->pio_sm, p->offset, p->pin, 800000, p->rgbw); pio_sm_set_enabled(pio, sm, false); pio_sm_clear_fifos(pio, sm); pio_sm_restart(pio, sm); pio_sm_set_enabled(pio, sm, true); } int main() { DmxInput dmx_in; uint8_t dmxbuf[512]; int i; int blink = 1; /* Initialise DMX */ dmx_in.begin(dmx_rx_pin, 1, 512); pxs[0].pin = 2; pxs[0].num_pixels = 8; pxs[0].rgbw = false; pxs[1].pin = 3; pxs[1].num_pixels = 1; pxs[1].rgbw = true; n_pxs = 2; /* Initialise Neopixels */ init_pixel_strip(&pxs[0], pio0, 0); init_pixel_strip(&pxs[1], pio0, 1); /* Start DMA */ dma_chan = dma_claim_unused_channel(true); dma_conf = dma_channel_get_default_config(dma_chan); channel_config_set_read_increment(&dma_conf, true); channel_config_set_write_increment(&dma_conf, false); irq_set_exclusive_handler(DMA_IRQ_0, dma_complete); dma_channel_set_irq0_enabled(dma_chan, true); irq_set_enabled(DMA_IRQ_0, true); set_dma(); /* Status LED */ gpio_init(PICO_DEFAULT_LED_PIN); gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT); int loop = 0; while (1) { //dmx_in.read(dmxbuf); //int dmxpos = 1; /* Numbering starts at 1 */ for ( i=0; i 1000000 ) { loop = 0; blink = 1 - blink; } } }