├── .gitignore ├── EXTREMELY_IMPORTANT_WARNINGS.txt ├── Makefile ├── README.md ├── demo.c ├── ws2812-RPi.c └── ws2812-RPi.h /.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | -------------------------------------------------------------------------------- /EXTREMELY_IMPORTANT_WARNINGS.txt: -------------------------------------------------------------------------------- 1 | You are using this at your OWN RISK. I believe this software is reasonably safe to use (aside 2 | from the intrinsic risk to those who are photosensitive - see below), although I can't be certain 3 | that it won't trash your hardware or cause property damage. 4 | 5 | Speaking of risk, WS2812 pixels are bright enough to cause eye pain and (for all I know) possibly 6 | retina damage when run at full strength. It's a good idea to set the brightness at 0.2 or so for 7 | direct viewing (whether you're looking directly at the pixels or not), or to put some diffuse 8 | material between you and the LEDs. 9 | 10 | PHOTOSENSITIVITY WARNING: 11 | Patterns of light and darkness (stationary or moving), flashing lights, patterns and backgrounds 12 | on screens, and the like, may cause epilleptic seizures in some people. This is a danger EVEN IF 13 | THE PERSON (WHICH MAY BE *YOU*) HAS NEVER KNOWINGLY HAD A PHOTOSENSITIVE EPISODE BEFORE. It's up 14 | to you to learn the warning signs, but symptoms may include dizziness, nausea, vision changes, 15 | convlusions, disorientation, involuntary movements, and eye twitching. (This list is not 16 | necessarily exhaustive.) 17 | 18 | BEST PRACTICES: https://learn.adafruit.com/adafruit-neopixel-uberguide/best-practices 19 | It's a good idea to read these. They include advice for how to protect your NeoPixels against 20 | shorting out, and how to use a capacitor to ensure smooth power delivery. 21 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS=-g -O0 -Wall -Wformat 2 | LDFLAGS=-lm 3 | 4 | all: bin/ws2812-RPi 5 | 6 | 7 | bin/ws2812-RPi: ws2812-RPi.c ws2812-RPi.h demo.c 8 | mkdir -p bin 9 | gcc ${CFLAGS} ${LDFLAGS} $+ -o $@ 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | RaspberryPi-NeoPixel-WS2812 2 | =========================== 3 | 4 | Library for driving WS2812 pixels (also known as "NeoPixels" when sold by Adafruit) from a Raspberry Pi. Unlike other solutions, this DOES NOT require an Arduino or other external controller. The Raspberry Pi has a DMA controller that is perfectly capable of doing the job. All you need is a resistor and a capacitor, and you're done! 5 | 6 | Wishlist: 7 | * Modify DMA code so it can use more than one 4K page, enabling >450 pixels (some people have thousands!) 8 | * Turn this into a FIFO daemon, like ServoBlaster 9 | * There are a few stupid magic numbers left that I haven't changed to DEFINEs yet 10 | * Make it immediately return after initiating DMA transfer, so we can begin building the next frame (for higher framerate on huge lengths of pixels) 11 | 12 | Done: 13 | * Add whatever functions are present in the Adafruit Arduino library, but not implemented here 14 | * Change calculated delay after DMA transfer start to reflect number of pixel commands sent (plus one word, to ensure low latch signal is sent) rather than the length of the entire buffer 15 | * Fix high CPU usage 16 | -------------------------------------------------------------------------------- /demo.c: -------------------------------------------------------------------------------- 1 | // Set tabs to 4 spaces. 2 | 3 | // ================================================================================================= 4 | // 5 | // __ __ _________________ ______ ____________ ____________________.__ 6 | // / \ / \/ _____/\_____ \ / __ \/_ \_____ \ \______ \______ \__| 7 | // \ \/\/ /\_____ \ / ____/ > < | |/ ____/ | _/| ___/ | 8 | // \ / / \/ \/ -- \| / \ | | \| | | | 9 | // \__/\ / /_______ /\_______ \______ /|___\_______ \ |____|_ /|____| |__| 10 | // \/ \/ \/ \/ \/ \/ 11 | // 12 | // WS2812 NeoPixel driver 13 | // Based on code by Richard G. Hirst and others 14 | // Adapted for the WS2812 by 626Pilot, April/May 2014 15 | // Huge ASCII art section labels are from http://patorjk.com/software/taag/ 16 | // 17 | // License: GPL 18 | // 19 | // You are using this at your OWN RISK. I believe this software is reasonably safe to use (aside 20 | // from the intrinsic risk to those who are photosensitive - see below), although I can't be certain 21 | // that it won't trash your hardware or cause property damage. 22 | // 23 | // Speaking of risk, WS2812 pixels are bright enough to cause eye pain and (for all I know) possibly 24 | // retina damage when run at full strength. It's a good idea to set the brightness at 0.2 or so for 25 | // direct viewing (whether you're looking directly at the pixels or not), or to put some diffuse 26 | // material between you and the LEDs. 27 | // 28 | // PHOTOSENSITIVITY WARNING: 29 | // Patterns of light and darkness (stationary or moving), flashing lights, patterns and backgrounds 30 | // on screens, and the like, may cause epilleptic seizures in some people. This is a danger EVEN IF 31 | // THE PERSON (WHICH MAY BE *YOU*) HAS NEVER KNOWINGLY HAD A PHOTOSENSITIVE EPISODE BEFORE. It's up 32 | // to you to learn the warning signs, but symptoms may include dizziness, nausea, vision changes, 33 | // convlusions, disorientation, involuntary movements, and eye twitching. (This list is not 34 | // necessarily exhaustive.) 35 | // 36 | // NEOPIXEL BEST PRACTICES: https://learn.adafruit.com/adafruit-neopixel-uberguide/best-practices 37 | // 38 | // Connections: 39 | // Positive to Raspberry Pi's 3.3v 40 | // Negative to Raspberry Pi's ground 41 | // Data to GPIO18 (Pin 12) (through a resistor, which you should know from the Best 42 | // Practices guide!) 43 | // 44 | // GitHub (source, support, etc.): https://github.com/626Pilot/RaspberryPi-NeoPixel-WS2812 45 | // Buy WS2812-based stuff from: http://adafruit.com 46 | // Compile with: make 47 | // Test with: sudo ./bin/ws2812-RPi 48 | // (it needs to be root so it can map the peripherals' registers) 49 | // 50 | // ================================================================================================= 51 | 52 | // This is for the WS2812 LEDs. It won't work with the older WS2811s, although it could be modified 53 | // for that without too much trouble. Preliminary driver used Frank Buss' servo driver, but I moved 54 | // to Richard Hirst's memory mapping/access model because his code already works with DMA, and has 55 | // what I think is a slightly cleaner way of accessing the registers: register[name] rather than 56 | // *(register + name). 57 | 58 | // At the time of writing, there's a lot of confusing "PWM DMA" code revolving around simulating 59 | // an FM signal. Usually this is done without properly initializing certain registers, which is 60 | // OK for their purpose, but I needed to be able to transfer actual coherent data and have it wind 61 | // up in a proper state once it was transferred. This has proven to be a somewhat painful task. 62 | // The PWM controller likes to ignore the RPTL1 bit when the data is in a regular, repeating 63 | // pattern. I'M NOT MAKING IT UP! It really does that. It's bizarre. There are lots of other 64 | // strange irregularities as well, which had to be figured out through trial and error. It doesn't 65 | // help that the BCM2835 ARM Peripherals manual contains outright errors and omissions! 66 | 67 | // Many examples of this kind of code have magic numbers in them. If you don't know, a magic number 68 | // is one that either lacks an obvious structure (e.g. 0x2020C000) or purpose. Please don't use 69 | // that stuff in any code you release! All magic numbers found in reference code have been changed 70 | // to DEFINEs. That way, instead of seeing some inscrutable number, you see (e.g.) PWM_CTL. 71 | 72 | // References - BCM2835 ARM Peripherals: 73 | // http://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-Peripherals.pdf 74 | // 75 | // Raspberry Pi low-level peripherals: 76 | // http://elinux.org/RPi_Low-level_peripherals 77 | // 78 | // Richard Hirst's nice, clean code: 79 | // https://github.com/richardghirst/PiBits/blob/master/PiFmDma/PiFmDma.c 80 | // 81 | // PWM clock register: 82 | // http://www.raspberrypi.org/forums/viewtopic.php?t=8467&p=124620 83 | // 84 | // Simple (because it's in assembly) PWM+DMA setup: 85 | // https://github.com/mikedurso/rpi-projects/blob/master/asm-nyancat/rpi-nyancat.s 86 | // 87 | // Adafruit's NeoPixel driver: 88 | // https://github.com/adafruit/Adafruit_NeoPixel/blob/master/Adafruit_NeoPixel.cpp 89 | 90 | 91 | /* 92 | // ================================================================================================= 93 | // .___ .__ .___ 94 | // | | ____ ____ | | __ __ __| _/____ ______ 95 | // | |/ \_/ ___\| | | | \/ __ |/ __ \ / ___/ 96 | // | | | \ \___| |_| | / /_/ \ ___/ \___ \ 97 | // |___|___| /\___ >____/____/\____ |\___ >____ > 98 | // \/ \/ \/ \/ \/ 99 | // ================================================================================================= 100 | */ 101 | 102 | #include 103 | #include 104 | #include 105 | #include 106 | #include 107 | #include 108 | #include 109 | #include 110 | #include 111 | #include 112 | #include 113 | #include 114 | #include 115 | #include 116 | #include 117 | #include 118 | 119 | #include 120 | #include 121 | #include "ws2812-RPi.h" 122 | #include 123 | 124 | /* 125 | // ================================================================================================= 126 | // _____ .__ 127 | // / \ _____ |__| ____ 128 | // / \ / \\__ \ | |/ \ 129 | // / Y \/ __ \| | | \ 130 | // \____|__ (____ /__|___| / 131 | // \/ \/ \/ 132 | // ================================================================================================= 133 | */ 134 | 135 | float cfg_brightness=DEFAULT_BRIGHTNESS; 136 | 137 | void effectsDemo() { 138 | 139 | int i, j; 140 | // int ptr; 141 | float k; 142 | 143 | 144 | 145 | // Default effects from the Arduino lib 146 | colorWipe(Color(255, 0, 0), 50); // Red 147 | colorWipe(Color(0, 255, 0), 50); // Green 148 | colorWipe(Color(0, 0, 255), 50); // Blue 149 | theaterChase(Color(127, 127, 127), 50); // White 150 | theaterChase(Color(127, 0, 0), 50); // Red 151 | theaterChase(Color( 0, 0, 127), 50); // Blue 152 | rainbow(5); 153 | rainbowCycle(5); 154 | theaterChaseRainbow(50); 155 | 156 | // Watermelon fade :) 157 | for(k=0; k<0.5; k+=.01) { 158 | // ptr=0; 159 | setBrightness(k); 160 | for(i=0; i=0; k-=.01) { 166 | // ptr=0; 167 | setBrightness(k); 168 | for(i=0; itm_min & 1; 231 | sec_mills++; 232 | if(result->tm_sec != last_sec) { 233 | sec_mills=0; 234 | last_sec=result->tm_sec; 235 | } 236 | float f_sec=result->tm_sec + sec_mills*0.1; 237 | int i; 238 | // printf("min: %d h:%d s:%d\n", result->tm_min, result->tm_sec, result->tm_hour); 239 | // printf(" (%d, %d, %d);\n", (int) floor(result->tm_min/2.5), (int) floor(result->tm_sec/2.5), (result->tm_hour % 12)*2); 240 | for(i=0; i < 24; i++) { 241 | // printf("%d\n",i); 242 | uint8_t sec; 243 | if(i < floor(f_sec/2.5)) { 244 | sec=0xff; 245 | } else if(i <= floor(f_sec/2.5)) { 246 | sec=0xff * fmod(f_sec/2.5, 1.0) ; 247 | // printf("sec=%d sec_mills=%d\n",sec,sec_mills); 248 | } else { 249 | sec=0; 250 | } 251 | if(invert) { 252 | sec=0xff-sec; 253 | } 254 | setPixelColor(i, floor(result->tm_min/2.5) == i ? 0xff : 0, sec, (result->tm_hour*2 % 24) == i ? 0xff : 0 ); 255 | } 256 | show(); 257 | usleep(100000); 258 | } 259 | } 260 | 261 | int main(int argc, char **argv) 262 | { 263 | int set=false; 264 | int clock=false; 265 | 266 | while (1) { 267 | int option_index = 0; 268 | static struct option long_options[] = { 269 | {"help", 0, NULL, 'h'}, 270 | {"debug", 0, NULL, 'd'}, 271 | {"version", 0, NULL, 'v'}, 272 | {"brightness", 1, NULL, 'b'}, 273 | {"clock", 0, NULL, 'c'}, 274 | {"set", 0, NULL, 's'} 275 | }; 276 | int c = getopt_long(argc, argv, "hduvs:p:x", long_options, &option_index); 277 | if (c == -1) 278 | break; 279 | switch (c) { 280 | case 'h': 281 | printf( 282 | " --help\n" 283 | " --debug\n" 284 | " --version\n" 285 | " --brightness\n" 286 | " --set RRGGBB RRGGBB\n" 287 | " disables demo mode, sets X leds\n" 288 | ); 289 | exit(0); 290 | case 'd': 291 | //FIXME 292 | break; 293 | case 'v': 294 | printf("%s 0.123\n",argv[0]); 295 | exit(0); 296 | case 'b': 297 | cfg_brightness=atof(optarg); 298 | break; 299 | case 'c': 300 | clock=true; 301 | break; 302 | case 's': 303 | set=true; 304 | break; 305 | } 306 | } 307 | 308 | // Check "Single Instance" 309 | int pid_file = open("/var/run/whatever.pid", O_CREAT | O_RDWR, 0666); 310 | int rc = flock(pid_file, LOCK_EX | LOCK_NB); 311 | if(rc) { 312 | if(EWOULDBLOCK == errno) 313 | { 314 | // another instance is running 315 | printf("Instance already running\n"); 316 | exit(EXIT_FAILURE); 317 | } 318 | } 319 | 320 | // Catch all signals possible - it's vital we kill the DMA engine on process exit! 321 | int i; 322 | for (i = 0; i < 64; i++) { 323 | struct sigaction sa; 324 | memset(&sa, 0, sizeof(sa)); 325 | sa.sa_handler = terminate; 326 | sigaction(i, &sa, NULL); 327 | } 328 | 329 | // Don't buffer console output 330 | setvbuf(stdout, NULL, _IONBF, 0); 331 | 332 | // How many LEDs? 333 | numLEDs = 24; 334 | 335 | // How bright? (Recommend 0.2 for direct viewing @ 3.3V) 336 | setBrightness(cfg_brightness); 337 | 338 | // Init PWM generator and clear LED buffer 339 | initHardware(); 340 | clearLEDBuffer(); 341 | 342 | if(set) { 343 | for(i=optind; i < argc; i++) { 344 | const char *elem=argv[i]; 345 | char *endp=NULL; 346 | long l=strtol(elem, &endp, 16); 347 | if(endp && endp[0] == '\0') { 348 | // printf("argv[%d]=%s\n", i, elem); 349 | setPixelColor(i-optind, (l >> 16) & 0xff, (l >> 8) & 0xff , l & 0xff); 350 | } 351 | } 352 | show(); 353 | } else if(clock) { 354 | showClock(); 355 | } else { 356 | // Show some effects 357 | while(true) { 358 | effectsDemo(); 359 | } 360 | } 361 | 362 | // Exit cleanly, freeing memory and stopping the DMA & PWM engines 363 | // We trap all signals (including Ctrl+C), so even if you don't get here, it terminates correctly 364 | terminate(0); 365 | 366 | return 0; 367 | } 368 | -------------------------------------------------------------------------------- /ws2812-RPi.c: -------------------------------------------------------------------------------- 1 | // Set tabs to 4 spaces. 2 | 3 | // ================================================================================================= 4 | // 5 | // __ __ _________________ ______ ____________ ____________________.__ 6 | // / \ / \/ _____/\_____ \ / __ \/_ \_____ \ \______ \______ \__| 7 | // \ \/\/ /\_____ \ / ____/ > < | |/ ____/ | _/| ___/ | 8 | // \ / / \/ \/ -- \| / \ | | \| | | | 9 | // \__/\ / /_______ /\_______ \______ /|___\_______ \ |____|_ /|____| |__| 10 | // \/ \/ \/ \/ \/ \/ 11 | // 12 | // WS2812 NeoPixel driver 13 | // Based on code by Richard G. Hirst and others 14 | // Adapted for the WS2812 by 626Pilot, April/May 2014 15 | // Huge ASCII art section labels are from http://patorjk.com/software/taag/ 16 | // 17 | // License: GPL 18 | // 19 | // You are using this at your OWN RISK. I believe this software is reasonably safe to use (aside 20 | // from the intrinsic risk to those who are photosensitive - see below), although I can't be certain 21 | // that it won't trash your hardware or cause property damage. 22 | // 23 | // Speaking of risk, WS2812 pixels are bright enough to cause eye pain and (for all I know) possibly 24 | // retina damage when run at full strength. It's a good idea to set the brightness at 0.2 or so for 25 | // direct viewing (whether you're looking directly at the pixels or not), or to put some diffuse 26 | // material between you and the LEDs. 27 | // 28 | // PHOTOSENSITIVITY WARNING: 29 | // Patterns of light and darkness (stationary or moving), flashing lights, patterns and backgrounds 30 | // on screens, and the like, may cause epilleptic seizures in some people. This is a danger EVEN IF 31 | // THE PERSON (WHICH MAY BE *YOU*) HAS NEVER KNOWINGLY HAD A PHOTOSENSITIVE EPISODE BEFORE. It's up 32 | // to you to learn the warning signs, but symptoms may include dizziness, nausea, vision changes, 33 | // convlusions, disorientation, involuntary movements, and eye twitching. (This list is not 34 | // necessarily exhaustive.) 35 | // 36 | // NEOPIXEL BEST PRACTICES: https://learn.adafruit.com/adafruit-neopixel-uberguide/best-practices 37 | // 38 | // Connections: 39 | // Positive to Raspberry Pi's 3.3v 40 | // Negative to Raspberry Pi's ground 41 | // Data to GPIO18 (Pin 12) (through a resistor, which you should know from the Best 42 | // Practices guide!) 43 | // 44 | // GitHub (source, support, etc.): https://github.com/626Pilot/RaspberryPi-NeoPixel-WS2812 45 | // Buy WS2812-based stuff from: http://adafruit.com 46 | // Compile with: gcc ws2812-RPi.c -o ws2812-RPi 47 | // Test with: sudo ./ws2812-RPi 48 | // (it needs to be root so it can map the peripherals' registers) 49 | // 50 | // ================================================================================================= 51 | 52 | // This is for the WS2812 LEDs. It won't work with the older WS2811s, although it could be modified 53 | // for that without too much trouble. Preliminary driver used Frank Buss' servo driver, but I moved 54 | // to Richard Hirst's memory mapping/access model because his code already works with DMA, and has 55 | // what I think is a slightly cleaner way of accessing the registers: register[name] rather than 56 | // *(register + name). 57 | 58 | // At the time of writing, there's a lot of confusing "PWM DMA" code revolving around simulating 59 | // an FM signal. Usually this is done without properly initializing certain registers, which is 60 | // OK for their purpose, but I needed to be able to transfer actual coherent data and have it wind 61 | // up in a proper state once it was transferred. This has proven to be a somewhat painful task. 62 | // The PWM controller likes to ignore the RPTL1 bit when the data is in a regular, repeating 63 | // pattern. I'M NOT MAKING IT UP! It really does that. It's bizarre. There are lots of other 64 | // strange irregularities as well, which had to be figured out through trial and error. It doesn't 65 | // help that the BCM2835 ARM Peripherals manual contains outright errors and omissions! 66 | 67 | // Many examples of this kind of code have magic numbers in them. If you don't know, a magic number 68 | // is one that either lacks an obvious structure (e.g. 0x2020C000) or purpose. Please don't use 69 | // that stuff in any code you release! All magic numbers found in reference code have been changed 70 | // to DEFINEs. That way, instead of seeing some inscrutable number, you see (e.g.) PWM_CTL. 71 | 72 | // References - BCM2835 ARM Peripherals: 73 | // http://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-Peripherals.pdf 74 | // 75 | // Raspberry Pi low-level peripherals: 76 | // http://elinux.org/RPi_Low-level_peripherals 77 | // 78 | // Richard Hirst's nice, clean code: 79 | // https://github.com/richardghirst/PiBits/blob/master/PiFmDma/PiFmDma.c 80 | // 81 | // PWM clock register: 82 | // http://www.raspberrypi.org/forums/viewtopic.php?t=8467&p=124620 83 | // 84 | // Simple (because it's in assembly) PWM+DMA setup: 85 | // https://github.com/mikedurso/rpi-projects/blob/master/asm-nyancat/rpi-nyancat.s 86 | // 87 | // Adafruit's NeoPixel driver: 88 | // https://github.com/adafruit/Adafruit_NeoPixel/blob/master/Adafruit_NeoPixel.cpp 89 | 90 | 91 | /* 92 | // ================================================================================================= 93 | // .___ .__ .___ 94 | // | | ____ ____ | | __ __ __| _/____ ______ 95 | // | |/ \_/ ___\| | | | \/ __ |/ __ \ / ___/ 96 | // | | | \ \___| |_| | / /_/ \ ___/ \___ \ 97 | // |___|___| /\___ >____/____/\____ |\___ >____ > 98 | // \/ \/ \/ \/ \/ 99 | // ================================================================================================= 100 | */ 101 | 102 | #include 103 | #include 104 | #include 105 | #include 106 | #include 107 | #include 108 | #include 109 | #include 110 | #include 111 | #include 112 | #include 113 | #include 114 | #include 115 | #include 116 | #include 117 | #include 118 | #include 119 | #include // Used for single instance check 120 | 121 | 122 | 123 | /* 124 | // ================================================================================================= 125 | // ________ _____.__ ____ ____ ____ 126 | // \______ \ _____/ ____\__| ____ ____ ______ / _ \ \ \ / /____ _______ ______ 127 | // | | \_/ __ \ __\| |/ \_/ __ \ / ___/ > _ __| |__|___| /\___ >____ > \_____\ \ \___/ (____ /__| /____ > 130 | // \/ \/ \/ \/ \/ \/ \/ \/ 131 | // ================================================================================================= 132 | */ 133 | 134 | // Base addresses for GPIO, PWM, PWM clock, and DMA controllers (physical, not bus!) 135 | // These will be "memory mapped" into virtual RAM so that they can be written and read directly. 136 | // ------------------------------------------------------------------------------------------------- 137 | #define DMA_BASE 0x20007000 138 | #define DMA_LEN 0x24 139 | #define PWM_BASE 0x2020C000 140 | #define PWM_LEN 0x28 141 | #define CLK_BASE 0x20101000 142 | #define CLK_LEN 0xA8 143 | #define GPIO_BASE 0x20200000 144 | #define GPIO_LEN 0xB4 145 | 146 | // GPIO 147 | // ------------------------------------------------------------------------------------------------- 148 | #define GPFSEL0 0x20200000 // GPIO function select, pins 0-9 (bits 30-31 reserved) 149 | #define GPFSEL1 0x20200004 // Pins 10-19 150 | #define GPFSEL2 0x20200008 // Pins 20-29 151 | #define GPFSEL3 0x2020000C // Pins 30-39 152 | #define GPFSEL4 0x20200010 // Pins 40-49 153 | #define GPFSEL5 0x20200014 // Pins 50-53 154 | #define GPSET0 0x2020001C // Set (turn on) pin 155 | #define GPCLR0 0x20200028 // Clear (turn off) pin 156 | #define GPPUD 0x20200094 // Internal pullup/pulldown resistor control 157 | #define GPPUDCLK0 0x20200098 // PUD clock for pins 0-31 158 | #define GPPUDCLK1 0x2020009C // PUD clock for pins 32-53 159 | 160 | // Memory offsets for the PWM clock register, which is undocumented! Please fix that, Broadcom! 161 | // ------------------------------------------------------------------------------------------------- 162 | #define PWM_CLK_CNTL 40 // Control (on/off) 163 | #define PWM_CLK_DIV 41 // Divisor (bits 11:0 are *quantized* floating part, 31:12 integer part) 164 | 165 | // PWM Register Addresses (page 141) 166 | // These are divided by 4 because the register offsets in the guide are in bytes (8 bits) but 167 | // the pointers we use in this program are in words (32 bits). Buss' original defines are in 168 | // word offsets, e.g. PWM_RNG1 was 4 and PWM_DAT1 was 5. This is functionally the same, but it 169 | // matches the numbers supplied in the guide. 170 | // ------------------------------------------------------------------------------------------------- 171 | #define PWM_CTL 0x00 // Control Register 172 | #define PWM_STA (0x04 / 4) // Status Register 173 | #define PWM_DMAC (0x08 / 4) // DMA Control Register 174 | #define PWM_RNG1 (0x10 / 4) // Channel 1 Range 175 | #define PWM_DAT1 (0x14 / 4) // Channel 1 Data 176 | #define PWM_FIF1 (0x18 / 4) // FIFO (for both channels - bytes are interleaved if both active) 177 | #define PWM_RNG2 (0x20 / 4) // Channel 2 Range 178 | #define PWM_DAT2 (0x24 / 4) // Channel 2 Data 179 | 180 | // PWM_CTL register bit offsets 181 | // Note: Don't use MSEN1/2 for this purpose. It will screw things up. 182 | // ------------------------------------------------------------------------------------------------- 183 | #define PWM_CTL_MSEN2 15 // Channel 2 - 0: Use PWM algorithm. 1: Use M/S (serial) algorithm. 184 | #define PWM_CTL_USEF2 13 // Channel 2 - 0: Use PWM_DAT2. 1: Use FIFO. 185 | #define PWM_CTL_POLA2 12 // Channel 2 - Invert output polarity (if set, 0=high and 1=low) 186 | #define PWM_CTL_SBIT2 11 // Channel 2 - Silence bit (default line state when not transmitting) 187 | #define PWM_CTL_RPTL2 10 // Channel 2 - Repeat last data in FIFO 188 | #define PWM_CTL_MODE2 9 // Channel 2 - Mode. 0=PWM, 1=Serializer 189 | #define PWM_CTL_PWEN2 8 // Channel 2 - Enable PWM 190 | #define PWM_CTL_CLRF1 6 // Clear FIFO 191 | #define PWM_CTL_MSEN1 7 // Channel 1 - 0: Use PWM algorithm. 1: Use M/S (serial) algorithm. 192 | #define PWM_CTL_USEF1 5 // Channel 1 - 0: Use PWM_DAT1. 1: Use FIFO. 193 | #define PWM_CTL_POLA1 4 // Channel 1 - Invert output polarity (if set, 0=high and 1=low) 194 | #define PWM_CTL_SBIT1 3 // Channel 1 - Silence bit (default line state when not transmitting) 195 | #define PWM_CTL_RPTL1 2 // Channel 1 - Repeat last data in FIFO 196 | #define PWM_CTL_MODE1 1 // Channel 1 - Mode. 0=PWM, 1=Serializer 197 | #define PWM_CTL_PWEN1 0 // Channel 1 - Enable PWM 198 | 199 | // PWM_STA register bit offsets 200 | // ------------------------------------------------------------------------------------------------- 201 | #define PWM_STA_STA4 12 // Channel 4 State 202 | #define PWM_STA_STA3 11 // Channel 3 State 203 | #define PWM_STA_STA2 10 // Channel 2 State 204 | #define PWM_STA_STA1 9 // Channel 1 State 205 | #define PWM_STA_BERR 8 // Bus Error 206 | #define PWM_STA_GAPO4 7 // Gap Occurred on Channel 4 207 | #define PWM_STA_GAPO3 6 // Gap Occurred on Channel 3 208 | #define PWM_STA_GAPO2 5 // Gap Occurred on Channel 2 209 | #define PWM_STA_GAPO1 4 // Gap Occurred on Channel 1 210 | #define PWM_STA_RERR1 3 // FIFO Read Error 211 | #define PWM_STA_WERR1 2 // FIFO Write Error 212 | #define PWM_STA_EMPT1 1 // FIFO Empty 213 | #define PWM_STA_FULL1 0 // FIFO Full 214 | 215 | // PWM_DMAC bit offsets 216 | // ------------------------------------------------------------------------------------------------- 217 | #define PWM_DMAC_ENAB 31 // 0: DMA Disabled. 1: DMA Enabled. 218 | #define PWM_DMAC_PANIC 8 // Bits 15:8. Threshold for PANIC signal. Default 7. 219 | #define PWM_DMAC_DREQ 0 // Bits 7:0. Threshold for DREQ signal. Default 7. 220 | 221 | // PWM_RNG1, PWM_RNG2 222 | // -------------------------------------------------------------------------------------------------- 223 | // Defines the transmission range. In PWM mode, evenly spaced pulses are sent within a period 224 | // of length defined in these registers. In serial mode, serialized data is sent within the 225 | // same period. The value is normally 32. If less, data will be truncated. If more, data will 226 | // be padded with zeros. 227 | 228 | // DAT1, DAT2 229 | // -------------------------------------------------------------------------------------------------- 230 | // NOTE: These registers are not useful for our purposes - we will use the FIFO instead! 231 | // Stores 32 bits of data to be sent when USEF1/USEF2 is 0. In PWM mode, defines how many 232 | // pulses will be sent within the period specified in PWM_RNG1/PWM_RNG2. In serializer mode, 233 | // defines a 32-bit word to be transmitted. 234 | 235 | // FIF1 236 | // -------------------------------------------------------------------------------------------------- 237 | // 32-bit-wide register used to "stuff" the FIFO, which has 16 32-bit words. (So, if you write 238 | // it 16 times, it will fill the FIFO.) 239 | // See also: PWM_STA_EMPT1 (FIFO empty) 240 | // PWM_STA_FULL1 (FIFO full) 241 | // PWM_CTL_CLRF1 (Clear FIFO) 242 | 243 | // DMA 244 | // -------------------------------------------------------------------------------------------------- 245 | // DMA registers (divided by four to convert form word to byte offsets, as with the PWM registers) 246 | #define DMA_CS (0x00 / 4) // Control & Status register 247 | #define DMA_CONBLK_AD (0x04 / 4) // Address of Control Block (must be 256-BYTE ALIGNED!!!) 248 | #define DMA_TI (0x08 / 4) // Transfer Information (populated from CB) 249 | #define DMA_SOURCE_AD (0x0C / 4) // Source address, populated from CB. Physical address. 250 | #define DMA_DEST_AD (0x10 / 4) // Destination address, populated from CB. Bus address. 251 | #define DMA_TXFR_LEN (0x14 / 4) // Transfer length, populated from CB 252 | #define DMA_STRIDE (0x18 / 4) // Stride, populated from CB 253 | #define DMA_NEXTCONBK (0x1C / 4) // Next control block address, populated from CB 254 | #define DMA_DEBUG (0x20 / 4) // Debug settings 255 | 256 | // DMA Control & Status register bit offsets 257 | #define DMA_CS_RESET 31 // Reset the controller for this channel 258 | #define DMA_CS_ABORT 30 // Set to abort transfer 259 | #define DMA_CS_DISDEBUG 29 // Disable debug pause signal 260 | #define DMA_CS_WAIT_FOR 28 // Wait for outstanding writes 261 | #define DMA_CS_PANIC_PRI 20 // Panic priority (bits 23:20), default 7 262 | #define DMA_CS_PRIORITY 16 // AXI priority level (bits 19:16), default 7 263 | #define DMA_CS_ERROR 8 // Set when there's been an error 264 | #define DMA_CS_WAITING_FOR 6 // Set when the channel's waiting for a write to be accepted 265 | #define DMA_CS_DREQ_STOPS_DMA 5 // Set when the DMA is paused because DREQ is inactive 266 | #define DMA_CS_PAUSED 4 // Set when the DMA is paused (active bit cleared, etc.) 267 | #define DMA_CS_DREQ 3 // Set when DREQ line is high 268 | #define DMA_CS_INT 2 // If INTEN is set, this will be set on CB transfer end 269 | #define DMA_CS_END 1 // Set when the current control block is finished 270 | #define DMA_CS_ACTIVE 0 // Enable DMA (CB_ADDR must not be 0) 271 | // Default CS word 272 | #define DMA_CS_CONFIGWORD (8 << DMA_CS_PANIC_PRI) | \ 273 | (8 << DMA_CS_PRIORITY) | \ 274 | (1 << DMA_CS_WAIT_FOR) 275 | 276 | // DREQ lines (page 61, most DREQs omitted) 277 | #define DMA_DREQ_ALWAYS 0 278 | #define DMA_DREQ_PCM_TX 2 279 | #define DMA_DREQ_PCM_RX 3 280 | #define DMA_DREQ_PWM 5 281 | #define DMA_DREQ_SPI_TX 6 282 | #define DMA_DREQ_SPI_RX 7 283 | #define DMA_DREQ_BSC_TX 8 284 | #define DMA_DREQ_BSC_RX 9 285 | 286 | // DMA Transfer Information register bit offsets 287 | // We don't write DMA_TI directly. It's populated from the TI field in a control block. 288 | #define DMA_TI_NO_WIDE_BURSTS 26 // Don't do wide writes in 2-beat bursts 289 | #define DMA_TI_WAITS 21 // Wait this many cycles after end of each read/write 290 | #define DMA_TI_PERMAP 16 // Peripheral # whose ready signal controls xfer rate (pwm=5) 291 | #define DMA_TI_BURST_LENGTH 12 // Length of burst in words (bits 15:12) 292 | #define DMA_TI_SRC_IGNORE 11 // Don't perform source reads (for fast cache fill) 293 | #define DMA_TI_SRC_DREQ 10 // Peripheral in PERMAP gates source reads 294 | #define DMA_TI_SRC_WIDTH 9 // Source transfer width - 0=32 bits, 1=128 bits 295 | #define DMA_TI_SRC_INC 8 // Source address += SRC_WITH after each read 296 | #define DMA_TI_DEST_IGNORE 7 // Don't perform destination writes 297 | #define DMA_TI_DEST_DREQ 6 // Peripheral in PERMAP gates destination writes 298 | #define DMA_TI_DEST_WIDTH 5 // Destination transfer width - 0=32 bits, 1=128 bits 299 | #define DMA_TI_DEST_INC 4 // Dest address += DEST_WIDTH after each read 300 | #define DMA_TI_WAIT_RESP 3 // Wait for write response 301 | #define DMA_TI_TDMODE 1 // 2D striding mode 302 | #define DMA_TI_INTEN 0 // Interrupt enable 303 | // Default TI word 304 | #define DMA_TI_CONFIGWORD (1 << DMA_TI_NO_WIDE_BURSTS) | \ 305 | (1 << DMA_TI_SRC_INC) | \ 306 | (1 << DMA_TI_DEST_DREQ) | \ 307 | (1 << DMA_TI_WAIT_RESP) | \ 308 | (1 << DMA_TI_INTEN) | \ 309 | (DMA_DREQ_PWM << DMA_TI_PERMAP) 310 | 311 | // DMA Debug register bit offsets 312 | #define DMA_DEBUG_LITE 28 // Whether the controller is "Lite" 313 | #define DMA_DEBUG_VERSION 25 // DMA Version (bits 27:25) 314 | #define DMA_DEBUG_DMA_STATE 16 // DMA State (bits 24:16) 315 | #define DMA_DEBUG_DMA_ID 8 // DMA controller's AXI bus ID (bits 15:8) 316 | #define DMA_DEBUG_OUTSTANDING_WRITES 4 // Outstanding writes (bits 7:4) 317 | #define DMA_DEBUG_READ_ERROR 2 // Slave read response error (clear by setting) 318 | #define DMA_DEBUG_FIFO_ERROR 1 // Operational read FIFO error (clear by setting) 319 | #define DMA_DEBUG_READ_LAST_NOT_SET 0 // AXI bus read last signal not set (clear by setting) 320 | 321 | // Control Block (CB) - this tells the DMA controller what to do. 322 | typedef struct { 323 | unsigned int 324 | info, // Transfer Information (TI) 325 | src, // Source address (physical) 326 | dst, // Destination address (bus) 327 | length, // Length in bytes (not words!) 328 | stride, // We don't care about this 329 | next, // Pointer to next control block 330 | pad[2]; // These are "reserved" (unused) 331 | } dma_cb_t; 332 | 333 | // The page map contains pointers to memory that we will allocate below. It uses two pointers 334 | // per address. This is because the software (this program) deals only in virtual addresses, 335 | // whereas the DMA controller can only access RAM via physical address. (If that's not confusing 336 | // enough, it writes to peripherals by their bus addresses.) 337 | typedef struct { 338 | uint8_t *virtaddr; 339 | uint32_t physaddr; 340 | } page_map_t; 341 | 342 | page_map_t *page_map; // This will hold the page map, which we'll allocate below 343 | static uint8_t *virtbase; // Pointer to some virtual memory that will be allocated 344 | 345 | static volatile unsigned int *pwm_reg; // PWM controller register set 346 | static volatile unsigned int *clk_reg; // PWM clock manager register set 347 | static volatile unsigned int *dma_reg; // DMA controller register set 348 | static volatile unsigned int *gpio_reg; // GPIO pin controller register set 349 | 350 | // Contains arrays of control blocks and their related samples. 351 | // One pixel needs 72 bits (24 bits for the color * 3 to represent them on the wire). 352 | // 768 words = 341.3 pixels 353 | // 1024 words = 455.1 pixels 354 | // The highest I can make this number is 1016. Any higher, and it will start copying garbage to the 355 | // PWM controller. I think it might be because of the virtual->physical memory mapping not being 356 | // contiguous, so *pointer+1016 isn't "next door" to *pointer+1017 for some weird reason. 357 | // However, that's still enough for 451.5 color instructions! If someone has more pixels than that 358 | // to control, they can figure it out. I tried Hirst's message of having one CB per word, which 359 | // seems like it might fix that, but I couldn't figure it out. 360 | #define NUM_DATA_WORDS 1016 361 | struct control_data_s { 362 | dma_cb_t cb[1]; 363 | uint32_t sample[NUM_DATA_WORDS]; 364 | }; 365 | 366 | static struct control_data_s *ctl; 367 | 368 | #define PAGE_SIZE 4096 // Size of a RAM page to be allocated 369 | #define PAGE_SHIFT 12 // This is used for address translation 370 | #define NUM_PAGES ((sizeof(struct control_data_s) + PAGE_SIZE - 1) >> PAGE_SHIFT) 371 | 372 | #define SETBIT(word, bit) word |= 1<___| /\___ >__| (____ /____/ 392 | // \/ \/ \/ \/ \/ 393 | // ================================================================================================= 394 | 395 | // Convenience functions 396 | // -------------------------------------------------------------------------------------------------- 397 | // Print some bits of a binary number (2nd arg is how many bits) 398 | void printBinary(unsigned int i, unsigned int bits) { 399 | int x; 400 | for(x=bits-1; x>=0; x--) { 401 | printf("%d", (i & (1 << x)) ? 1 : 0); 402 | if(x % 16 == 0 && x > 0) { 403 | printf(" "); 404 | } else if(x % 4 == 0 && x > 0) { 405 | printf(":"); 406 | } 407 | } 408 | } 409 | 410 | // Reverse the bits in a word 411 | unsigned int reverseWord(unsigned int word) { 412 | unsigned int output = 0; 413 | // unsigned char bit; 414 | int i; 415 | for(i=0; i<32; i++) { 416 | // bit = word & (1 << i) ? 1 : 0; 417 | output |= word & (1 << i) ? 1 : 0; 418 | if(i<31) { 419 | output <<= 1; 420 | } 421 | } 422 | return output; 423 | } 424 | 425 | // Not sure how this is better than usleep...? 426 | /* 427 | static void udelay(int us) { 428 | struct timespec ts = { 0, us * 1000 }; 429 | nanosleep(&ts, NULL); 430 | } 431 | */ 432 | 433 | 434 | // Shutdown functions 435 | // -------------------------------------------------------------------------------------------------- 436 | void terminate(int dummy) { 437 | // Shut down the DMA controller 438 | if(dma_reg) { 439 | CLRBIT(dma_reg[DMA_CS], DMA_CS_ACTIVE); 440 | usleep(100); 441 | SETBIT(dma_reg[DMA_CS], DMA_CS_RESET); 442 | usleep(100); 443 | } 444 | 445 | // Shut down PWM 446 | if(pwm_reg) { 447 | CLRBIT(pwm_reg[PWM_CTL], PWM_CTL_PWEN1); 448 | usleep(100); 449 | pwm_reg[PWM_CTL] = (1 << PWM_CTL_CLRF1); 450 | } 451 | 452 | // Free the allocated memory 453 | if(page_map != 0) { 454 | free(page_map); 455 | } 456 | 457 | exit(1); 458 | } 459 | 460 | static void fatal(char *fmt, ...) { 461 | va_list ap; 462 | va_start(ap, fmt); 463 | vfprintf(stderr, fmt, ap); 464 | va_end(ap); 465 | terminate(0); 466 | } 467 | 468 | 469 | // Memory management 470 | // -------------------------------------------------------------------------------------------------- 471 | // Translate from virtual address to physical 472 | unsigned int mem_virt_to_phys(void *virt) { 473 | unsigned int offset = (uint8_t *)virt - virtbase; 474 | return page_map[offset >> PAGE_SHIFT].physaddr + (offset % PAGE_SIZE); 475 | } 476 | 477 | // Translate from physical address to virtual 478 | unsigned int mem_phys_to_virt(uint32_t phys) { 479 | unsigned int pg_offset = phys & (PAGE_SIZE - 1); 480 | unsigned int pg_addr = phys - pg_offset; 481 | int i; 482 | 483 | for (i = 0; i < NUM_PAGES; i++) { 484 | if (page_map[i].physaddr == pg_addr) { 485 | return (uint32_t)virtbase + i * PAGE_SIZE + pg_offset; 486 | } 487 | } 488 | fatal("Failed to reverse map phys addr %08x\n", phys); 489 | 490 | return 0; 491 | } 492 | 493 | // Map a peripheral's IO memory into our virtual memory, so we can read/write it directly 494 | static void * map_peripheral(uint32_t base, uint32_t len) { 495 | int fd = open("/dev/mem", O_RDWR); 496 | void * vaddr; 497 | 498 | if (fd < 0) 499 | fatal("Failed to open /dev/mem: %m\n"); 500 | vaddr = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, base); 501 | if (vaddr == MAP_FAILED) 502 | fatal("Failed to map peripheral at 0x%08x: %m\n", base); 503 | close(fd); 504 | 505 | return vaddr; 506 | } 507 | 508 | 509 | /* 510 | // ================================================================================================= 511 | // .____ ___________________ _________ __ _____ _____ 512 | // | | \_ _____/\______ \ / _____// |_ __ ___/ ____\/ ____\ 513 | // | | | __)_ | | \ \_____ \\ __\ | \ __\\ __\ 514 | // | |___ | \ | ` \ / \| | | | /| | | | 515 | // |_______ \/_______ //_______ / /_______ /|__| |____/ |__| |__| 516 | // \/ \/ \/ \/ 517 | // ================================================================================================= 518 | */ 519 | 520 | // Brightness - I recommend 0.2 for direct viewing at 3.3v. 521 | #define DEFAULT_BRIGHTNESS 1.0 522 | float brightness = DEFAULT_BRIGHTNESS; 523 | 524 | // LED buffer (this will be translated into pulses in PWMWaveform[]) 525 | typedef struct { 526 | unsigned char r; 527 | unsigned char g; 528 | unsigned char b; 529 | } Color_t; 530 | 531 | unsigned int numLEDs; // How many LEDs there are on the chain 532 | 533 | #define LED_BUFFER_LENGTH 24 534 | Color_t LEDBuffer[LED_BUFFER_LENGTH]; 535 | 536 | // PWM waveform buffer (in words), 16 32-bit words are enough to hold 170 wire bits. 537 | // That's OK if we only transmit from the FIFO, but for DMA, we will use a much larger size. 538 | // 1024 (4096 bytes) should be enough for over 400 elements. It can be bumped up if you need more! 539 | unsigned int PWMWaveform[NUM_DATA_WORDS]; 540 | 541 | // Set brightness 542 | unsigned char setBrightness(float b) { 543 | if(b < 0) { 544 | printf("Brightness can't be set below 0.\n"); 545 | return false; 546 | } 547 | if(b > 1) { 548 | printf("Brightness can't be set above 1.\n"); 549 | return false; 550 | } 551 | brightness = b; 552 | return true; 553 | } 554 | 555 | // Zero out the PWM waveform buffer 556 | void clearPWMBuffer() { 557 | memset(PWMWaveform, 0, NUM_DATA_WORDS * 4); // Times four because memset deals in bytes. 558 | } 559 | 560 | // Zero out the LED buffer 561 | void clearLEDBuffer() { 562 | int i; 563 | for(i=0; i LED_BUFFER_LENGTH - 1) { 589 | printf("Unable to set pixel %d (LED buffer is %d pixels long)\n", pixel, LED_BUFFER_LENGTH); 590 | return false; 591 | } 592 | LEDBuffer[pixel] = RGB2Color(r, g, b); 593 | return true; 594 | } 595 | 596 | // Set pixel color, by a direct Color_t 597 | unsigned char setPixelColorT(unsigned int pixel, Color_t c) { 598 | if(pixel < 0) { 599 | printf("Unable to set pixel %d (less than zero?)\n", pixel); 600 | return false; 601 | } 602 | if(pixel > LED_BUFFER_LENGTH - 1) { 603 | printf("Unable to set pixel %d (LED buffer is %d pixels long)\n", pixel, LED_BUFFER_LENGTH); 604 | return false; 605 | } 606 | LEDBuffer[pixel] = c; 607 | return true; 608 | } 609 | 610 | // Get pixel color 611 | Color_t getPixelColor(unsigned int pixel) { 612 | if(pixel < 0) { 613 | printf("Unable to get pixel %d (less than zero?)\n", pixel); 614 | return RGB2Color(0, 0, 0); 615 | } 616 | if(pixel > LED_BUFFER_LENGTH - 1) { 617 | printf("Unable to get pixel %d (LED buffer is %d pixels long)\n", pixel, LED_BUFFER_LENGTH); 618 | return RGB2Color(0, 0, 0); 619 | } 620 | return LEDBuffer[pixel]; 621 | } 622 | 623 | // Return # of pixels 624 | unsigned int numPixels() { 625 | return numLEDs; 626 | } 627 | 628 | // Return pointer to pixels (FIXME: dunno if this works!) 629 | Color_t* getPixels() { 630 | return LEDBuffer; 631 | } 632 | 633 | // Set an individual bit in the PWM output array, accounting for word boundaries 634 | // The (31 - bitIdx) is so that we write the data backwards, correcting its endianness 635 | // This means getPWMBit will return something other than what was written, so it would be nice 636 | // if the logic that calls this function would figure it out instead. (However, that's trickier) 637 | void setPWMBit(unsigned int bitPos, unsigned char bit) { 638 | 639 | // Fetch word the bit is in 640 | unsigned int wordOffset = (int)(bitPos / 32); 641 | unsigned int bitIdx = bitPos - (wordOffset * 32); 642 | 643 | // printf("bitPos=%d wordOffset=%d bitIdx=%d value=%d\n", bitPos, wordOffset, bitIdx, bit); 644 | 645 | switch(bit) { 646 | case 1: 647 | PWMWaveform[wordOffset] |= (1 << (31 - bitIdx)); 648 | // PWMWaveform[wordOffset] |= (1 << bitIdx); 649 | break; 650 | case 0: 651 | PWMWaveform[wordOffset] &= ~(1 << (31 - bitIdx)); 652 | // PWMWaveform[wordOffset] &= ~(1 << bitIdx); 653 | break; 654 | } 655 | } 656 | 657 | // Get an individual bit from the PWM output array, accounting for word boundaries 658 | unsigned char getPWMBit(unsigned int bitPos) { 659 | 660 | // Fetch word the bit is in 661 | unsigned int wordOffset = (int)(bitPos / 32); 662 | unsigned int bitIdx = bitPos - (wordOffset * 32); 663 | 664 | if(PWMWaveform[wordOffset] & (1 << bitIdx)) { 665 | return true; 666 | } else { 667 | return false; 668 | } 669 | } 670 | 671 | 672 | 673 | /* 674 | // ================================================================================================= 675 | // ________ ___. 676 | // \______ \ ____\_ |__ __ __ ____ 677 | // | | \_/ __ \| __ \| | \/ ___\ 678 | // | ` \ ___/| \_\ \ | / /_/ > 679 | // /_______ /\___ >___ /____/\___ / 680 | // \/ \/ \/ /_____/ 681 | // ================================================================================================= 682 | */ 683 | 684 | // Dump contents of LED buffer 685 | void dumpLEDBuffer() { 686 | int i; 687 | printf("Dumping LED buffer:\n"); 688 | for(i=0; i> PWM_DMAC_PANIC) & 0b11111111); 747 | printf(" DREQ: %d\n", (pwm_reg[PWM_DMAC] >> PWM_DMAC_DREQ) & 0b11111111); 748 | printf("\n"); 749 | } 750 | 751 | // Display all PWM registers 752 | void dumpPWM() { 753 | dumpPWMStatus(); 754 | dumpPWMControl(pwm_reg[PWM_CTL]); 755 | dumpPWMDMAC(); 756 | } 757 | 758 | // Display all PWM control registers 759 | void dumpDMARegs() { 760 | printf("DMA Registers\n"); 761 | printf(" CONBLK_AD: 0x%x (", dma_reg[DMA_CONBLK_AD]); 762 | printBinary(dma_reg[DMA_CONBLK_AD], 32); 763 | printf(")\n"); 764 | printf(" SOURCE_AD: 0x%x\n", dma_reg[DMA_SOURCE_AD]); 765 | printf(" DEST_AD: 0x%x\n", dma_reg[DMA_DEST_AD]); 766 | printf(" TXFR_LEN: 0x%x\n", dma_reg[DMA_TXFR_LEN]); 767 | printf(" NEXTCONBK: 0x%x\n", dma_reg[DMA_NEXTCONBK]); 768 | printf(" STRIDE: 0x%x\n", dma_reg[DMA_STRIDE]); 769 | printf(" TI: 0x%x\n", dma_reg[DMA_TI]); 770 | printf(" CS: 0x%x\n", dma_reg[DMA_CS]); 771 | printf(" DEBUG: 0x%x\n", dma_reg[DMA_DEBUG]); 772 | printf("\n"); 773 | } 774 | 775 | // Display the contents of a Control Block 776 | void dumpControlBlock(dma_cb_t *c) { 777 | printf("Control Block\n"); 778 | printf(" TI: 0x%x\n", c->info); 779 | printf(" SOURCE_AD: 0x%x\n", c->src); 780 | printf(" DEST_AD: 0x%x\n", c->dst); 781 | printf(" TXFR_LEN: 0x%x\n", c->length); 782 | printf(" STRIDE: 0x%x\n", c->stride); 783 | printf(" NEXTCONBK: 0x%x\n", c->next); 784 | printf(" RES1: 0x%x\n", c->pad[0]); 785 | printf(" RES2: 0x%x\n", c->pad[1]); 786 | printf("\n"); 787 | } 788 | 789 | // Display the contents of a Transfer Information word 790 | void dumpTransferInformation(unsigned int TI) { 791 | printf("Transfer Information (0x%x, ", TI); 792 | printBinary(TI, 32); 793 | printf(")\n"); 794 | printf(" NO_WIDE_BURSTS: %d\n", GETBIT(TI, DMA_TI_NO_WIDE_BURSTS)); 795 | printf(" WAITS: %d\n", (TI >> DMA_TI_WAITS) & 0b11111); // WAITS is bits 25:21 796 | printf(" PERMAP: %d\n", (TI >> DMA_TI_PERMAP) & 0b11111); // PERMAP is bits 20:16 797 | printf(" BURST_LENGTH: %d\n", (TI >> DMA_TI_BURST_LENGTH) & 0b1111); // BURST_LENGTH is bits 15:12 798 | printf(" SRC_IGNORE: %d\n", GETBIT(TI, DMA_TI_SRC_IGNORE)); 799 | printf(" SRC_DREQ: %d\n", GETBIT(TI, DMA_TI_SRC_DREQ)); 800 | printf(" SRC_WIDTH: %d\n", GETBIT(TI, DMA_TI_SRC_WIDTH)); 801 | printf(" SRC_INC: %d\n", GETBIT(TI, DMA_TI_SRC_INC)); 802 | printf(" DEST_IGNORE: %d\n", GETBIT(TI, DMA_TI_DEST_IGNORE)); 803 | printf(" DEST_DREQ: %d\n", GETBIT(TI, DMA_TI_DEST_DREQ)); 804 | printf(" DEST_WIDTH: %d\n", GETBIT(TI, DMA_TI_DEST_WIDTH)); 805 | printf(" DEST_INC: %d\n", GETBIT(TI, DMA_TI_DEST_INC)); 806 | printf(" WAIT_RESP: %d\n", GETBIT(TI, DMA_TI_WAIT_RESP)); 807 | printf(" TDMODE: %d\n", GETBIT(TI, DMA_TI_TDMODE)); 808 | printf(" INTEN: %d\n", GETBIT(TI, DMA_TI_INTEN)); 809 | printf("\n"); 810 | } 811 | 812 | // Display the readable DMA registers 813 | void dumpDMA() { 814 | 815 | dumpDMARegs(); 816 | 817 | printf("DMA Control & Status Register: "); 818 | printBinary(dma_reg[DMA_CS], 32); 819 | printf("\n"); 820 | printf(" RESET: %d\n", GETBIT(dma_reg[DMA_CS], DMA_CS_RESET)); 821 | printf(" ABORT: %d\n", GETBIT(dma_reg[DMA_CS], DMA_CS_ABORT)); 822 | printf(" DISDEBUG: %d\n", GETBIT(dma_reg[DMA_CS], DMA_CS_DISDEBUG)); 823 | printf(" PANIC_PRI: %d\n", (dma_reg[DMA_CS] >> DMA_CS_PANIC_PRI) & 0b1111); 824 | printf(" PRIORITY: %d\n", (dma_reg[DMA_CS] >> DMA_CS_PRIORITY) & 0b1111); 825 | printf(" ERROR: %d\n", GETBIT(dma_reg[DMA_CS], DMA_CS_ERROR)); 826 | printf(" WAITING_FOR: %d\n", GETBIT(dma_reg[DMA_CS], DMA_CS_WAITING_FOR)); 827 | printf(" DREQ_STOPS_DMA: %d\n", GETBIT(dma_reg[DMA_CS], DMA_CS_DREQ_STOPS_DMA)); 828 | printf(" PAUSED: %d\n", GETBIT(dma_reg[DMA_CS], DMA_CS_PAUSED)); 829 | printf(" DREQ: %d\n", GETBIT(dma_reg[DMA_CS], DMA_CS_DREQ)); 830 | printf(" INT: %d\n", GETBIT(dma_reg[DMA_CS], DMA_CS_INT)); 831 | printf(" END: %d\n", GETBIT(dma_reg[DMA_CS], DMA_CS_END)); 832 | printf(" ACTIVE: %d\n", GETBIT(dma_reg[DMA_CS], DMA_CS_ACTIVE)); 833 | printf("\n"); 834 | 835 | dumpTransferInformation(dma_reg[DMA_TI]); 836 | 837 | printf("DMA Debug Register: "); 838 | printBinary(dma_reg[DMA_DEBUG], 32); 839 | printf("\n"); 840 | printf(" LITE: %d\n", GETBIT(dma_reg[DMA_DEBUG], DMA_DEBUG_LITE)); 841 | printf(" VERSION: %d\n", (dma_reg[DMA_DEBUG] >> DMA_DEBUG_VERSION) & 0b1111); 842 | printf(" DMA_STATE: %d\n", (dma_reg[DMA_DEBUG] >> DMA_DEBUG_DMA_STATE) & 0b111111111); 843 | printf(" DMA_ID: %d\n", (dma_reg[DMA_DEBUG] >> DMA_DEBUG_DMA_ID) & 0b11111111); 844 | printf(" OUTSTANDING W: %d\n", (dma_reg[DMA_DEBUG] >> DMA_DEBUG_OUTSTANDING_WRITES) & 0b1111); 845 | printf(" READ_ERROR: %d\n", GETBIT(dma_reg[DMA_DEBUG], DMA_DEBUG_READ_ERROR)); 846 | printf(" FIFO_ERROR: %d\n", GETBIT(dma_reg[DMA_DEBUG], DMA_DEBUG_FIFO_ERROR)); 847 | printf(" READ_LAST_NS: %d\n", GETBIT(dma_reg[DMA_DEBUG], DMA_DEBUG_READ_LAST_NOT_SET)); 848 | printf("\n"); 849 | 850 | } 851 | 852 | 853 | 854 | /* 855 | // ================================================================================================= 856 | // .___ .__ __ ___ ___ .___ 857 | // | | ____ |__|/ |_ / | \_____ _______ __| _/_ _ _______ _______ ____ 858 | // | |/ \| \ __\ / ~ \__ \\_ __ \/ __ |\ \/ \/ /\__ \\_ __ \_/ __ \ 859 | // | | | \ || | \ Y // __ \| | \/ /_/ | \ / / __ \| | \/\ ___/ 860 | // |___|___| /__||__| \___|_ /(____ /__| \____ | \/\_/ (____ /__| \___ > 861 | // \/ \/ \/ \/ \/ \/ 862 | // ================================================================================================= 863 | */ 864 | 865 | void initHardware() { 866 | 867 | int i = 0; 868 | int pid; 869 | int fd; 870 | char pagemap_fn[64]; 871 | 872 | // Clear the PWM buffer 873 | // --------------------------------------------------------------- 874 | clearPWMBuffer(); 875 | 876 | // Set up peripheral access 877 | // --------------------------------------------------------------- 878 | dma_reg = map_peripheral(DMA_BASE, DMA_LEN); 879 | dma_reg += 0x000; 880 | pwm_reg = map_peripheral(PWM_BASE, PWM_LEN); 881 | clk_reg = map_peripheral(CLK_BASE, CLK_LEN); 882 | gpio_reg = map_peripheral(GPIO_BASE, GPIO_LEN); 883 | 884 | 885 | // Set PWM alternate function for GPIO18 886 | // --------------------------------------------------------------- 887 | //gpio_reg[1] &= ~(7 << 24); 888 | //usleep(100); 889 | //gpio_reg[1] |= (2 << 24); 890 | //usleep(100); 891 | SET_GPIO_ALT(18, 5); 892 | 893 | 894 | // Allocate memory for the DMA control block & data to be sent 895 | // --------------------------------------------------------------- 896 | virtbase = mmap( 897 | NULL, // Address 898 | NUM_PAGES * PAGE_SIZE, // Length 899 | PROT_READ | PROT_WRITE, // Protection 900 | MAP_SHARED | // Shared 901 | MAP_ANONYMOUS | // Not file-based, init contents to 0 902 | MAP_NORESERVE | // Don't reserve swap space 903 | MAP_LOCKED, // Lock in RAM (don't swap) 904 | -1, // File descriptor 905 | 0); // Offset 906 | 907 | if (virtbase == MAP_FAILED) { 908 | fatal("Failed to mmap physical pages: %m\n"); 909 | } 910 | 911 | if ((unsigned long)virtbase & (PAGE_SIZE-1)) { 912 | fatal("Virtual address is not page aligned\n"); 913 | } 914 | 915 | //printf("virtbase mapped 0x%x bytes at 0x%x\n", NUM_PAGES * PAGE_SIZE, virtbase); 916 | 917 | // Allocate page map (pointers to the control block(s) and data for each CB 918 | page_map = malloc(NUM_PAGES * sizeof(*page_map)); 919 | if (page_map == 0) { 920 | fatal("Failed to malloc page_map: %m\n"); 921 | } else { 922 | //printf("Allocated 0x%x bytes for page_map at 0x%x\n", NUM_PAGES * sizeof(*page_map), page_map); 923 | } 924 | 925 | // Use /proc/self/pagemap to figure out the mapping between virtual and physical addresses 926 | pid = getpid(); 927 | sprintf(pagemap_fn, "/proc/%d/pagemap", pid); 928 | fd = open(pagemap_fn, O_RDONLY); 929 | 930 | if (fd < 0) { 931 | fatal("Failed to open %s: %m\n", pagemap_fn); 932 | } 933 | 934 | if (lseek(fd, (unsigned long)virtbase >> 9, SEEK_SET) != (unsigned long)virtbase >> 9) { 935 | fatal("Failed to seek on %s: %m\n", pagemap_fn); 936 | } 937 | 938 | //printf("Page map: %d pages\n", NUM_PAGES); 939 | for (i = 0; i < NUM_PAGES; i++) { 940 | uint64_t pfn; 941 | page_map[i].virtaddr = virtbase + i * PAGE_SIZE; 942 | 943 | // Following line forces page to be allocated 944 | // (Note: Copied directly from Hirst's code... page_map[i].virtaddr[0] was just set...?) 945 | page_map[i].virtaddr[0] = 0; 946 | 947 | if (read(fd, &pfn, sizeof(pfn)) != sizeof(pfn)) { 948 | fatal("Failed to read %s: %m\n", pagemap_fn); 949 | } 950 | 951 | if (((pfn >> 55)&0xfbf) != 0x10c) { // pagemap bits: https://www.kernel.org/doc/Documentation/vm/pagemap.txt 952 | fatal("Page %d not present (pfn 0x%016llx)\n", i, pfn); 953 | } 954 | 955 | page_map[i].physaddr = (unsigned int)pfn << PAGE_SHIFT | 0x40000000; 956 | //printf("Page map #%2d: virtual %8p ==> physical 0x%08x [0x%016llx]\n", i, page_map[i].virtaddr, page_map[i].physaddr, pfn); 957 | } 958 | 959 | 960 | // Set up control block 961 | // --------------------------------------------------------------- 962 | ctl = (struct control_data_s *)virtbase; 963 | dma_cb_t *cbp = ctl->cb; 964 | // FIXME: Change this to use DEFINEs 965 | unsigned int phys_pwm_fifo_addr = 0x7e20c000 + 0x18; 966 | 967 | // No wide bursts, source increment, dest DREQ on line 5, wait for response, enable interrupt 968 | cbp->info = DMA_TI_CONFIGWORD; 969 | 970 | // Source is our allocated memory 971 | cbp->src = mem_virt_to_phys(ctl->sample); 972 | 973 | // Destination is the PWM controller 974 | cbp->dst = phys_pwm_fifo_addr; 975 | 976 | // 72 bits per pixel / 32 bits per word = 2.25 words per pixel 977 | // Add 1 to make sure the PWM FIFO gets the message: "we're sending zeroes" 978 | // Times 4 because DMA works in bytes, not words 979 | cbp->length = ((numLEDs * 2.25) + 1) * 4; 980 | if(cbp->length > NUM_DATA_WORDS * 4) { 981 | cbp->length = NUM_DATA_WORDS * 4; 982 | } 983 | 984 | // We don't use striding 985 | cbp->stride = 0; 986 | 987 | // These are reserved 988 | cbp->pad[0] = 0; 989 | cbp->pad[1] = 0; 990 | 991 | // Pointer to next block - 0 shuts down the DMA channel when transfer is complete 992 | cbp->next = 0; 993 | 994 | // Testing 995 | /* 996 | ctl = (struct control_data_s *)virtbase; 997 | ctl->sample[0] = 0x00000000; 998 | ctl->sample[1] = 0x000000FA; 999 | ctl->sample[2] = 0x0000FFFF; 1000 | ctl->sample[3] = 0xAAAAAAAA; 1001 | ctl->sample[4] = 0xF0F0F0F0; 1002 | ctl->sample[5] = 0x0A0A0A0A; 1003 | ctl->sample[6] = 0xF00F0000; 1004 | */ 1005 | 1006 | 1007 | // Stop any existing DMA transfers 1008 | // --------------------------------------------------------------- 1009 | dma_reg[DMA_CS] |= (1 << DMA_CS_ABORT); 1010 | usleep(100); 1011 | dma_reg[DMA_CS] = (1 << DMA_CS_RESET); 1012 | usleep(100); 1013 | 1014 | 1015 | // PWM Clock 1016 | // --------------------------------------------------------------- 1017 | // Kill the clock 1018 | // FIXME: Change this to use a DEFINE 1019 | clk_reg[PWM_CLK_CNTL] = 0x5A000000 | (1 << 5); 1020 | usleep(100); 1021 | 1022 | // Disable DMA requests 1023 | CLRBIT(pwm_reg[PWM_DMAC], PWM_DMAC_ENAB); 1024 | usleep(100); 1025 | 1026 | // The fractional part is quantized to a range of 0-1024, so multiply the decimal part by 1024. 1027 | // E.g., 0.25 * 1024 = 256. 1028 | // So, if you want a divisor of 400.5, set idiv to 400 and fdiv to 512. 1029 | unsigned int idiv = 400; 1030 | unsigned short fdiv = 0; // Should be 16 bits, but the value must be <= 1024 1031 | clk_reg[PWM_CLK_DIV] = 0x5A000000 | (idiv << 12) | fdiv; // Set clock multiplier 1032 | usleep(100); 1033 | 1034 | // Enable the clock. Next-to-last digit means "enable clock". Last digit is 1 (oscillator), 1035 | // 4 (PLLA), 5 (PLLC), or 6 (PLLD) (according to the docs) although PLLA doesn't seem to work. 1036 | // FIXME: Change this to use a DEFINE 1037 | clk_reg[PWM_CLK_CNTL] = 0x5A000015; 1038 | usleep(100); 1039 | 1040 | 1041 | // PWM 1042 | // --------------------------------------------------------------- 1043 | // Clear any preexisting crap from the control & status register 1044 | pwm_reg[PWM_CTL] = 0; 1045 | 1046 | // Set transmission range (32 bytes, or 1 word) 1047 | // <32: Truncate. >32: Pad with SBIT1. As it happens, 32 is perfect. 1048 | pwm_reg[PWM_RNG1] = 32; 1049 | usleep(100); 1050 | 1051 | // Send DMA requests to fill the FIFO 1052 | pwm_reg[PWM_DMAC] = 1053 | (1 << PWM_DMAC_ENAB) | 1054 | (8 << PWM_DMAC_PANIC) | 1055 | (8 << PWM_DMAC_DREQ); 1056 | usleep(1000); 1057 | 1058 | // Clear the FIFO 1059 | SETBIT(pwm_reg[PWM_CTL], PWM_CTL_CLRF1); 1060 | usleep(100); 1061 | 1062 | // Don't repeat last FIFO contents if it runs dry 1063 | CLRBIT(pwm_reg[PWM_CTL], PWM_CTL_RPTL1); 1064 | usleep(100); 1065 | 1066 | // Silence (default) bit is 0 1067 | CLRBIT(pwm_reg[PWM_CTL], PWM_CTL_SBIT1); 1068 | usleep(100); 1069 | 1070 | // Polarity = default (low = 0, high = 1) 1071 | CLRBIT(pwm_reg[PWM_CTL], PWM_CTL_POLA1); 1072 | usleep(100); 1073 | 1074 | // Enable serializer mode 1075 | SETBIT(pwm_reg[PWM_CTL], PWM_CTL_MODE1); 1076 | usleep(100); 1077 | 1078 | // Use FIFO rather than DAT1 1079 | SETBIT(pwm_reg[PWM_CTL], PWM_CTL_USEF1); 1080 | usleep(100); 1081 | 1082 | // Disable MSEN1 1083 | CLRBIT(pwm_reg[PWM_CTL], PWM_CTL_MSEN1); 1084 | usleep(100); 1085 | 1086 | 1087 | // DMA 1088 | // --------------------------------------------------------------- 1089 | // Raise an interrupt when transfer is complete, which will set the INT flag in the CS register 1090 | SETBIT(dma_reg[DMA_CS], DMA_CS_INT); 1091 | usleep(100); 1092 | 1093 | // Clear the END flag (by setting it - this is a "write 1 to clear", or W1C, bit) 1094 | SETBIT(dma_reg[DMA_CS], DMA_CS_END); 1095 | usleep(100); 1096 | 1097 | // Send the physical address of the control block into the DMA controller 1098 | dma_reg[DMA_CONBLK_AD] = mem_virt_to_phys(ctl->cb); 1099 | usleep(100); 1100 | 1101 | // Clear error flags, if any (these are also W1C bits) 1102 | // FIXME: Use a define instead of this 1103 | dma_reg[DMA_DEBUG] = 7; 1104 | usleep(100); 1105 | } 1106 | 1107 | // Begin the transfer 1108 | void startTransfer() { 1109 | // Enable DMA 1110 | dma_reg[DMA_CONBLK_AD] = mem_virt_to_phys(ctl->cb); 1111 | dma_reg[DMA_CS] = DMA_CS_CONFIGWORD | (1 << DMA_CS_ACTIVE); 1112 | usleep(100); 1113 | 1114 | // Enable PWM 1115 | SETBIT(pwm_reg[PWM_CTL], PWM_CTL_PWEN1); 1116 | 1117 | // dumpPWM(); 1118 | // dumpDMA(); 1119 | } 1120 | 1121 | 1122 | 1123 | /* 1124 | // ================================================================================================= 1125 | // ____ ___ .___ __ .____ ___________________ 1126 | // | | \______ __| _/____ _/ |_ ____ | | \_ _____/\______ \ ______ 1127 | // | | /\____ \ / __ |\__ \\ __\/ __ \ | | | __)_ | | \ / ___/ 1128 | // | | / | |_> > /_/ | / __ \| | \ ___/ | |___ | \ | ` \\___ \ 1129 | // |______/ | __/\____ |(____ /__| \___ > |_______ \/_______ //_______ /____ > 1130 | // |__| \/ \/ \/ \/ \/ \/ \/ 1131 | // ================================================================================================= 1132 | */ 1133 | 1134 | void show() { 1135 | 1136 | // Clear out the PWM buffer 1137 | // Disabled, because we will overwrite the buffer anyway. 1138 | 1139 | // Read data from LEDBuffer[], translate it into wire format, and write to PWMWaveform 1140 | int i, j; 1141 | // unsigned int LEDBuffeWordPos = 0; 1142 | // unsigned int PWMWaveformBitPos = 0; 1143 | unsigned int colorBits = 0; // Holds the GRB color before conversion to wire bit pattern 1144 | unsigned char colorBit = 0; // Holds current bit out of colorBits to be processed 1145 | unsigned int wireBit = 0; // Holds the current bit we will set in PWMWaveform 1146 | 1147 | for(i=0; i=0; j--) { 1159 | colorBit = (colorBits & (1 << j)) ? 1 : 0; 1160 | switch(colorBit) { 1161 | case 1: 1162 | //wireBits = 0b110; // High, High, Low 1163 | setPWMBit(wireBit++, 1); 1164 | setPWMBit(wireBit++, 1); 1165 | setPWMBit(wireBit++, 0); 1166 | break; 1167 | case 0: 1168 | //wireBits = 0b100; // High, Low, Low 1169 | setPWMBit(wireBit++, 1); 1170 | setPWMBit(wireBit++, 0); 1171 | setPWMBit(wireBit++, 0); 1172 | break; 1173 | } 1174 | } 1175 | } 1176 | 1177 | // Copy PWM waveform to DMA's data buffer 1178 | //printf("Copying %d words to DMA data buffer\n", NUM_DATA_WORDS); 1179 | ctl = (struct control_data_s *)virtbase; 1180 | dma_cb_t *cbp = ctl->cb; 1181 | 1182 | // This block is a major CPU hog when there are lots of pixels to be transmitted. 1183 | // It would go quicker with DMA. 1184 | for(i = 0; i < (cbp->length / 4); i++) { 1185 | ctl->sample[i] = PWMWaveform[i]; 1186 | } 1187 | 1188 | 1189 | // Enable DMA and PWM engines, which should now send the data 1190 | startTransfer(); 1191 | 1192 | // Wait long enough for the DMA transfer to finish 1193 | // 3 RAM bits per wire bit, so 72 bits to send one color command. 1194 | float bitTimeUSec = (float)(NUM_DATA_WORDS * 32) * 0.4; // Bits sent * time to transmit one bit, which is 0.4μSec 1195 | //printf("Delay for %d μSec\n", (int)bitTimeUSec); 1196 | usleep((int)bitTimeUSec); 1197 | /* 1198 | 1199 | This is the old FIFO-filling code. 1200 | The FIFO only has enough words for about 7 LEDs, which is why we use DMA instead! 1201 | 1202 | for(i=0; i\___ >__| /____ > 1224 | // \/ \/ \/ \/ 1225 | // ================================================================================================= 1226 | // The effects in this section are adapted from the Adafruit NeoPixel library at: 1227 | // https://github.com/adafruit/Adafruit_NeoPixel/blob/master/examples/strandtest/strandtest.ino 1228 | */ 1229 | 1230 | // Input a value 0 to 255 to get a color value. 1231 | // The colours are a transition r - g - b - back to r. 1232 | Color_t Wheel(uint8_t WheelPos) { 1233 | if(WheelPos < 85) { 1234 | return Color(WheelPos * 3, 255 - WheelPos * 3, 0); 1235 | } else if(WheelPos < 170) { 1236 | WheelPos -= 85; 1237 | return Color(255 - WheelPos * 3, 0, WheelPos * 3); 1238 | } else { 1239 | WheelPos -= 170; 1240 | return Color(0, WheelPos * 3, 255 - WheelPos * 3); 1241 | } 1242 | } 1243 | 1244 | 1245 | // Fill the dots one after the other with a color 1246 | void colorWipe(Color_t c, uint8_t wait) { 1247 | uint16_t i; 1248 | for(i=0; i < | |/ ____/ | _/| ___/ | 8 | // \ / / \/ \/ -- \| / \ | | \| | | | 9 | // \__/\ / /_______ /\_______ \______ /|___\_______ \ |____|_ /|____| |__| 10 | // \/ \/ \/ \/ \/ \/ 11 | // 12 | // WS2812 NeoPixel driver 13 | // Based on code by Richard G. Hirst and others 14 | // Adapted for the WS2812 by 626Pilot, April/May 2014 15 | // Huge ASCII art section labels are from http://patorjk.com/software/taag/ 16 | // 17 | // License: GPL 18 | // 19 | 20 | /* 21 | // ================================================================================================= 22 | // .___ .__ .___ 23 | // | | ____ ____ | | __ __ __| _/____ ______ 24 | // | |/ \_/ ___\| | | | \/ __ |/ __ \ / ___/ 25 | // | | | \ \___| |_| | / /_/ \ ___/ \___ \ 26 | // |___|___| /\___ >____/____/\____ |\___ >____ > 27 | // \/ \/ \/ \/ \/ 28 | // ================================================================================================= 29 | */ 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include // Used for single instance check 49 | 50 | 51 | 52 | /* 53 | // ================================================================================================= 54 | // ________ _____.__ ____ ____ ____ 55 | // \______ \ _____/ ____\__| ____ ____ ______ / _ \ \ \ / /____ _______ ______ 56 | // | | \_/ __ \ __\| |/ \_/ __ \ / ___/ > _ __| |__|___| /\___ >____ > \_____\ \ \___/ (____ /__| /____ > 59 | // \/ \/ \/ \/ \/ \/ \/ \/ 60 | // ================================================================================================= 61 | */ 62 | 63 | // Base addresses for GPIO, PWM, PWM clock, and DMA controllers (physical, not bus!) 64 | // These will be "memory mapped" into virtual RAM so that they can be written and read directly. 65 | // ------------------------------------------------------------------------------------------------- 66 | #define DMA_BASE 0x20007000 67 | #define DMA_LEN 0x24 68 | #define PWM_BASE 0x2020C000 69 | #define PWM_LEN 0x28 70 | #define CLK_BASE 0x20101000 71 | #define CLK_LEN 0xA8 72 | #define GPIO_BASE 0x20200000 73 | #define GPIO_LEN 0xB4 74 | 75 | // GPIO 76 | // ------------------------------------------------------------------------------------------------- 77 | #define GPFSEL0 0x20200000 // GPIO function select, pins 0-9 (bits 30-31 reserved) 78 | #define GPFSEL1 0x20200004 // Pins 10-19 79 | #define GPFSEL2 0x20200008 // Pins 20-29 80 | #define GPFSEL3 0x2020000C // Pins 30-39 81 | #define GPFSEL4 0x20200010 // Pins 40-49 82 | #define GPFSEL5 0x20200014 // Pins 50-53 83 | #define GPSET0 0x2020001C // Set (turn on) pin 84 | #define GPCLR0 0x20200028 // Clear (turn off) pin 85 | #define GPPUD 0x20200094 // Internal pullup/pulldown resistor control 86 | #define GPPUDCLK0 0x20200098 // PUD clock for pins 0-31 87 | #define GPPUDCLK1 0x2020009C // PUD clock for pins 32-53 88 | 89 | // Memory offsets for the PWM clock register, which is undocumented! Please fix that, Broadcom! 90 | // ------------------------------------------------------------------------------------------------- 91 | #define PWM_CLK_CNTL 40 // Control (on/off) 92 | #define PWM_CLK_DIV 41 // Divisor (bits 11:0 are *quantized* floating part, 31:12 integer part) 93 | 94 | // PWM Register Addresses (page 141) 95 | // These are divided by 4 because the register offsets in the guide are in bytes (8 bits) but 96 | // the pointers we use in this program are in words (32 bits). Buss' original defines are in 97 | // word offsets, e.g. PWM_RNG1 was 4 and PWM_DAT1 was 5. This is functionally the same, but it 98 | // matches the numbers supplied in the guide. 99 | // ------------------------------------------------------------------------------------------------- 100 | #define PWM_CTL 0x00 // Control Register 101 | #define PWM_STA (0x04 / 4) // Status Register 102 | #define PWM_DMAC (0x08 / 4) // DMA Control Register 103 | #define PWM_RNG1 (0x10 / 4) // Channel 1 Range 104 | #define PWM_DAT1 (0x14 / 4) // Channel 1 Data 105 | #define PWM_FIF1 (0x18 / 4) // FIFO (for both channels - bytes are interleaved if both active) 106 | #define PWM_RNG2 (0x20 / 4) // Channel 2 Range 107 | #define PWM_DAT2 (0x24 / 4) // Channel 2 Data 108 | 109 | // PWM_CTL register bit offsets 110 | // Note: Don't use MSEN1/2 for this purpose. It will screw things up. 111 | // ------------------------------------------------------------------------------------------------- 112 | #define PWM_CTL_MSEN2 15 // Channel 2 - 0: Use PWM algorithm. 1: Use M/S (serial) algorithm. 113 | #define PWM_CTL_USEF2 13 // Channel 2 - 0: Use PWM_DAT2. 1: Use FIFO. 114 | #define PWM_CTL_POLA2 12 // Channel 2 - Invert output polarity (if set, 0=high and 1=low) 115 | #define PWM_CTL_SBIT2 11 // Channel 2 - Silence bit (default line state when not transmitting) 116 | #define PWM_CTL_RPTL2 10 // Channel 2 - Repeat last data in FIFO 117 | #define PWM_CTL_MODE2 9 // Channel 2 - Mode. 0=PWM, 1=Serializer 118 | #define PWM_CTL_PWEN2 8 // Channel 2 - Enable PWM 119 | #define PWM_CTL_CLRF1 6 // Clear FIFO 120 | #define PWM_CTL_MSEN1 7 // Channel 1 - 0: Use PWM algorithm. 1: Use M/S (serial) algorithm. 121 | #define PWM_CTL_USEF1 5 // Channel 1 - 0: Use PWM_DAT1. 1: Use FIFO. 122 | #define PWM_CTL_POLA1 4 // Channel 1 - Invert output polarity (if set, 0=high and 1=low) 123 | #define PWM_CTL_SBIT1 3 // Channel 1 - Silence bit (default line state when not transmitting) 124 | #define PWM_CTL_RPTL1 2 // Channel 1 - Repeat last data in FIFO 125 | #define PWM_CTL_MODE1 1 // Channel 1 - Mode. 0=PWM, 1=Serializer 126 | #define PWM_CTL_PWEN1 0 // Channel 1 - Enable PWM 127 | 128 | // PWM_STA register bit offsets 129 | // ------------------------------------------------------------------------------------------------- 130 | #define PWM_STA_STA4 12 // Channel 4 State 131 | #define PWM_STA_STA3 11 // Channel 3 State 132 | #define PWM_STA_STA2 10 // Channel 2 State 133 | #define PWM_STA_STA1 9 // Channel 1 State 134 | #define PWM_STA_BERR 8 // Bus Error 135 | #define PWM_STA_GAPO4 7 // Gap Occurred on Channel 4 136 | #define PWM_STA_GAPO3 6 // Gap Occurred on Channel 3 137 | #define PWM_STA_GAPO2 5 // Gap Occurred on Channel 2 138 | #define PWM_STA_GAPO1 4 // Gap Occurred on Channel 1 139 | #define PWM_STA_RERR1 3 // FIFO Read Error 140 | #define PWM_STA_WERR1 2 // FIFO Write Error 141 | #define PWM_STA_EMPT1 1 // FIFO Empty 142 | #define PWM_STA_FULL1 0 // FIFO Full 143 | 144 | // PWM_DMAC bit offsets 145 | // ------------------------------------------------------------------------------------------------- 146 | #define PWM_DMAC_ENAB 31 // 0: DMA Disabled. 1: DMA Enabled. 147 | #define PWM_DMAC_PANIC 8 // Bits 15:8. Threshold for PANIC signal. Default 7. 148 | #define PWM_DMAC_DREQ 0 // Bits 7:0. Threshold for DREQ signal. Default 7. 149 | 150 | // PWM_RNG1, PWM_RNG2 151 | // -------------------------------------------------------------------------------------------------- 152 | // Defines the transmission range. In PWM mode, evenly spaced pulses are sent within a period 153 | // of length defined in these registers. In serial mode, serialized data is sent within the 154 | // same period. The value is normally 32. If less, data will be truncated. If more, data will 155 | // be padded with zeros. 156 | 157 | // DAT1, DAT2 158 | // -------------------------------------------------------------------------------------------------- 159 | // NOTE: These registers are not useful for our purposes - we will use the FIFO instead! 160 | // Stores 32 bits of data to be sent when USEF1/USEF2 is 0. In PWM mode, defines how many 161 | // pulses will be sent within the period specified in PWM_RNG1/PWM_RNG2. In serializer mode, 162 | // defines a 32-bit word to be transmitted. 163 | 164 | // FIF1 165 | // -------------------------------------------------------------------------------------------------- 166 | // 32-bit-wide register used to "stuff" the FIFO, which has 16 32-bit words. (So, if you write 167 | // it 16 times, it will fill the FIFO.) 168 | // See also: PWM_STA_EMPT1 (FIFO empty) 169 | // PWM_STA_FULL1 (FIFO full) 170 | // PWM_CTL_CLRF1 (Clear FIFO) 171 | 172 | // DMA 173 | // -------------------------------------------------------------------------------------------------- 174 | // DMA registers (divided by four to convert form word to byte offsets, as with the PWM registers) 175 | #define DMA_CS (0x00 / 4) // Control & Status register 176 | #define DMA_CONBLK_AD (0x04 / 4) // Address of Control Block (must be 256-BYTE ALIGNED!!!) 177 | #define DMA_TI (0x08 / 4) // Transfer Information (populated from CB) 178 | #define DMA_SOURCE_AD (0x0C / 4) // Source address, populated from CB. Physical address. 179 | #define DMA_DEST_AD (0x10 / 4) // Destination address, populated from CB. Bus address. 180 | #define DMA_TXFR_LEN (0x14 / 4) // Transfer length, populated from CB 181 | #define DMA_STRIDE (0x18 / 4) // Stride, populated from CB 182 | #define DMA_NEXTCONBK (0x1C / 4) // Next control block address, populated from CB 183 | #define DMA_DEBUG (0x20 / 4) // Debug settings 184 | 185 | // DMA Control & Status register bit offsets 186 | #define DMA_CS_RESET 31 // Reset the controller for this channel 187 | #define DMA_CS_ABORT 30 // Set to abort transfer 188 | #define DMA_CS_DISDEBUG 29 // Disable debug pause signal 189 | #define DMA_CS_WAIT_FOR 28 // Wait for outstanding writes 190 | #define DMA_CS_PANIC_PRI 20 // Panic priority (bits 23:20), default 7 191 | #define DMA_CS_PRIORITY 16 // AXI priority level (bits 19:16), default 7 192 | #define DMA_CS_ERROR 8 // Set when there's been an error 193 | #define DMA_CS_WAITING_FOR 6 // Set when the channel's waiting for a write to be accepted 194 | #define DMA_CS_DREQ_STOPS_DMA 5 // Set when the DMA is paused because DREQ is inactive 195 | #define DMA_CS_PAUSED 4 // Set when the DMA is paused (active bit cleared, etc.) 196 | #define DMA_CS_DREQ 3 // Set when DREQ line is high 197 | #define DMA_CS_INT 2 // If INTEN is set, this will be set on CB transfer end 198 | #define DMA_CS_END 1 // Set when the current control block is finished 199 | #define DMA_CS_ACTIVE 0 // Enable DMA (CB_ADDR must not be 0) 200 | // Default CS word 201 | #define DMA_CS_CONFIGWORD (8 << DMA_CS_PANIC_PRI) | \ 202 | (8 << DMA_CS_PRIORITY) | \ 203 | (1 << DMA_CS_WAIT_FOR) 204 | 205 | // DREQ lines (page 61, most DREQs omitted) 206 | #define DMA_DREQ_ALWAYS 0 207 | #define DMA_DREQ_PCM_TX 2 208 | #define DMA_DREQ_PCM_RX 3 209 | #define DMA_DREQ_PWM 5 210 | #define DMA_DREQ_SPI_TX 6 211 | #define DMA_DREQ_SPI_RX 7 212 | #define DMA_DREQ_BSC_TX 8 213 | #define DMA_DREQ_BSC_RX 9 214 | 215 | // DMA Transfer Information register bit offsets 216 | // We don't write DMA_TI directly. It's populated from the TI field in a control block. 217 | #define DMA_TI_NO_WIDE_BURSTS 26 // Don't do wide writes in 2-beat bursts 218 | #define DMA_TI_WAITS 21 // Wait this many cycles after end of each read/write 219 | #define DMA_TI_PERMAP 16 // Peripheral # whose ready signal controls xfer rate (pwm=5) 220 | #define DMA_TI_BURST_LENGTH 12 // Length of burst in words (bits 15:12) 221 | #define DMA_TI_SRC_IGNORE 11 // Don't perform source reads (for fast cache fill) 222 | #define DMA_TI_SRC_DREQ 10 // Peripheral in PERMAP gates source reads 223 | #define DMA_TI_SRC_WIDTH 9 // Source transfer width - 0=32 bits, 1=128 bits 224 | #define DMA_TI_SRC_INC 8 // Source address += SRC_WITH after each read 225 | #define DMA_TI_DEST_IGNORE 7 // Don't perform destination writes 226 | #define DMA_TI_DEST_DREQ 6 // Peripheral in PERMAP gates destination writes 227 | #define DMA_TI_DEST_WIDTH 5 // Destination transfer width - 0=32 bits, 1=128 bits 228 | #define DMA_TI_DEST_INC 4 // Dest address += DEST_WIDTH after each read 229 | #define DMA_TI_WAIT_RESP 3 // Wait for write response 230 | #define DMA_TI_TDMODE 1 // 2D striding mode 231 | #define DMA_TI_INTEN 0 // Interrupt enable 232 | // Default TI word 233 | #define DMA_TI_CONFIGWORD (1 << DMA_TI_NO_WIDE_BURSTS) | \ 234 | (1 << DMA_TI_SRC_INC) | \ 235 | (1 << DMA_TI_DEST_DREQ) | \ 236 | (1 << DMA_TI_WAIT_RESP) | \ 237 | (1 << DMA_TI_INTEN) | \ 238 | (DMA_DREQ_PWM << DMA_TI_PERMAP) 239 | 240 | // DMA Debug register bit offsets 241 | #define DMA_DEBUG_LITE 28 // Whether the controller is "Lite" 242 | #define DMA_DEBUG_VERSION 25 // DMA Version (bits 27:25) 243 | #define DMA_DEBUG_DMA_STATE 16 // DMA State (bits 24:16) 244 | #define DMA_DEBUG_DMA_ID 8 // DMA controller's AXI bus ID (bits 15:8) 245 | #define DMA_DEBUG_OUTSTANDING_WRITES 4 // Outstanding writes (bits 7:4) 246 | #define DMA_DEBUG_READ_ERROR 2 // Slave read response error (clear by setting) 247 | #define DMA_DEBUG_FIFO_ERROR 1 // Operational read FIFO error (clear by setting) 248 | #define DMA_DEBUG_READ_LAST_NOT_SET 0 // AXI bus read last signal not set (clear by setting) 249 | 250 | // Control Block (CB) - this tells the DMA controller what to do. 251 | typedef struct { 252 | unsigned int 253 | info, // Transfer Information (TI) 254 | src, // Source address (physical) 255 | dst, // Destination address (bus) 256 | length, // Length in bytes (not words!) 257 | stride, // We don't care about this 258 | next, // Pointer to next control block 259 | pad[2]; // These are "reserved" (unused) 260 | } dma_cb_t; 261 | 262 | // The page map contains pointers to memory that we will allocate below. It uses two pointers 263 | // per address. This is because the software (this program) deals only in virtual addresses, 264 | // whereas the DMA controller can only access RAM via physical address. (If that's not confusing 265 | // enough, it writes to peripherals by their bus addresses.) 266 | typedef struct { 267 | uint8_t *virtaddr; 268 | uint32_t physaddr; 269 | } page_map_t; 270 | 271 | 272 | // Contains arrays of control blocks and their related samples. 273 | // One pixel needs 72 bits (24 bits for the color * 3 to represent them on the wire). 274 | // 768 words = 341.3 pixels 275 | // 1024 words = 455.1 pixels 276 | // The highest I can make this number is 1016. Any higher, and it will start copying garbage to the 277 | // PWM controller. I think it might be because of the virtual->physical memory mapping not being 278 | // contiguous, so *pointer+1016 isn't "next door" to *pointer+1017 for some weird reason. 279 | // However, that's still enough for 451.5 color instructions! If someone has more pixels than that 280 | // to control, they can figure it out. I tried Hirst's message of having one CB per word, which 281 | // seems like it might fix that, but I couldn't figure it out. 282 | #define NUM_DATA_WORDS 1016 283 | struct control_data_s { 284 | dma_cb_t cb[1]; 285 | uint32_t sample[NUM_DATA_WORDS]; 286 | }; 287 | 288 | 289 | #define PAGE_SIZE 4096 // Size of a RAM page to be allocated 290 | #define PAGE_SHIFT 12 // This is used for address translation 291 | #define NUM_PAGES ((sizeof(struct control_data_s) + PAGE_SIZE - 1) >> PAGE_SHIFT) 292 | 293 | #define SETBIT(word, bit) word |= 1<___| /\___ >__| (____ /____/ 313 | // \/ \/ \/ \/ \/ 314 | // ================================================================================================= 315 | 316 | void printBinary(unsigned int i, unsigned int bits); 317 | unsigned int reverseWord(unsigned int word); 318 | 319 | void terminate(int dummy); 320 | 321 | void fatal(char *fmt, ...); 322 | 323 | // Memory management 324 | // -------------------------------------------------------------------------------------------------- 325 | unsigned int mem_virt_to_phys(void *virt); 326 | unsigned int mem_phys_to_virt(uint32_t phys); 327 | void * map_peripheral(uint32_t base, uint32_t len); 328 | 329 | 330 | /* 331 | // ================================================================================================= 332 | // .____ ___________________ _________ __ _____ _____ 333 | // | | \_ _____/\______ \ / _____// |_ __ ___/ ____\/ ____\ 334 | // | | | __)_ | | \ \_____ \\ __\ | \ __\\ __\ 335 | // | |___ | \ | ` \ / \| | | | /| | | | 336 | // |_______ \/_______ //_______ / /_______ /|__| |____/ |__| |__| 337 | // \/ \/ \/ \/ 338 | // ================================================================================================= 339 | */ 340 | 341 | // Brightness - I recommend 0.2 for direct viewing at 3.3v. 342 | #define DEFAULT_BRIGHTNESS 1.0 343 | extern float brightness; 344 | 345 | // LED buffer (this will be translated into pulses in PWMWaveform[]) 346 | typedef struct { 347 | unsigned char r; 348 | unsigned char g; 349 | unsigned char b; 350 | } Color_t; 351 | 352 | unsigned int numLEDs; // How many LEDs there are on the chain 353 | 354 | #define LED_BUFFER_LENGTH 24 355 | Color_t LEDBuffer[LED_BUFFER_LENGTH]; 356 | 357 | // PWM waveform buffer (in words), 16 32-bit words are enough to hold 170 wire bits. 358 | // That's OK if we only transmit from the FIFO, but for DMA, we will use a much larger size. 359 | // 1024 (4096 bytes) should be enough for over 400 elements. It can be bumped up if you need more! 360 | unsigned int PWMWaveform[NUM_DATA_WORDS]; 361 | 362 | // Set brightness 363 | unsigned char setBrightness(float b); 364 | 365 | // Zero out the PWM waveform buffer 366 | void clearPWMBuffer(); 367 | 368 | // Zero out the LED buffer 369 | void clearLEDBuffer(); 370 | 371 | // Turn r, g, and b into a Color_t struct 372 | Color_t RGB2Color(unsigned char r, unsigned char g, unsigned char b); 373 | 374 | // Alias for the above 375 | Color_t Color(unsigned char r, unsigned char g, unsigned char b); 376 | 377 | // Set pixel color (24-bit color) 378 | unsigned char setPixelColor(unsigned int pixel, unsigned char r, unsigned char g, unsigned char b); 379 | 380 | // Set pixel color, by a direct Color_t 381 | unsigned char setPixelColorT(unsigned int pixel, Color_t c); 382 | 383 | // Get pixel color 384 | Color_t getPixelColor(unsigned int pixel); 385 | 386 | // Return # of pixels 387 | unsigned int numPixels(); 388 | 389 | // Return pointer to pixels (FIXME: dunno if this works!) 390 | Color_t* getPixels(); 391 | 392 | // Set an individual bit in the PWM output array, accounting for word boundaries 393 | // The (31 - bitIdx) is so that we write the data backwards, correcting its endianness 394 | // This means getPWMBit will return something other than what was written, so it would be nice 395 | // if the logic that calls this function would figure it out instead. (However, that's trickier) 396 | void setPWMBit(unsigned int bitPos, unsigned char bit); 397 | 398 | // Get an individual bit from the PWM output array, accounting for word boundaries 399 | unsigned char getPWMBit(unsigned int bitPos); 400 | 401 | 402 | /* 403 | // ================================================================================================= 404 | // ________ ___. 405 | // \______ \ ____\_ |__ __ __ ____ 406 | // | | \_/ __ \| __ \| | \/ ___\ 407 | // | ` \ ___/| \_\ \ | / /_/ > 408 | // /_______ /\___ >___ /____/\___ / 409 | // \/ \/ \/ /_____/ 410 | // ================================================================================================= 411 | */ 412 | 413 | // Dump contents of LED buffer 414 | void dumpLEDBuffer(); 415 | 416 | // Dump contents of PWM waveform 417 | // The last number dumped may not have a multiple of 3 digits (our basic unit of data is 3 bits, 418 | // whereas the RAM comprising the buffer has to be a multiple of 2 bits in size) 419 | void dumpPWMBuffer(); 420 | 421 | // Display the status of the PWM's control register 422 | void dumpPWMStatus(); 423 | 424 | // Display the settings in a PWM control word 425 | // If you want to dump the register directly, use this: dumpPWMControl(*(pwm + PWM_CTL)); 426 | void dumpPWMControl(unsigned int word); 427 | 428 | // Display the settings in the PWM DMAC word 429 | void dumpPWMDMAC(); 430 | 431 | // Display all PWM registers 432 | void dumpPWM(); 433 | 434 | // Display all PWM control registers 435 | void dumpDMARegs(); 436 | 437 | // Display the contents of a Control Block 438 | void dumpControlBlock(dma_cb_t *c); 439 | 440 | // Display the contents of a Transfer Information word 441 | void dumpTransferInformation(unsigned int TI); 442 | 443 | // Display the readable DMA registers 444 | void dumpDMA(); 445 | 446 | 447 | /* 448 | // ================================================================================================= 449 | // .___ .__ __ ___ ___ .___ 450 | // | | ____ |__|/ |_ / | \_____ _______ __| _/_ _ _______ _______ ____ 451 | // | |/ \| \ __\ / ~ \__ \\_ __ \/ __ |\ \/ \/ /\__ \\_ __ \_/ __ \ 452 | // | | | \ || | \ Y // __ \| | \/ /_/ | \ / / __ \| | \/\ ___/ 453 | // |___|___| /__||__| \___|_ /(____ /__| \____ | \/\_/ (____ /__| \___ > 454 | // \/ \/ \/ \/ \/ \/ 455 | // ================================================================================================= 456 | */ 457 | 458 | void initHardware(); 459 | 460 | // Begin the transfer 461 | void startTransfer(); 462 | 463 | 464 | 465 | /* 466 | // ================================================================================================= 467 | // ____ ___ .___ __ .____ ___________________ 468 | // | | \______ __| _/____ _/ |_ ____ | | \_ _____/\______ \ ______ 469 | // | | /\____ \ / __ |\__ \\ __\/ __ \ | | | __)_ | | \ / ___/ 470 | // | | / | |_> > /_/ | / __ \| | \ ___/ | |___ | \ | ` \\___ \ 471 | // |______/ | __/\____ |(____ /__| \___ > |_______ \/_______ //_______ /____ > 472 | // |__| \/ \/ \/ \/ \/ \/ \/ 473 | // ================================================================================================= 474 | */ 475 | 476 | void show(); 477 | 478 | /* 479 | // ================================================================================================= 480 | // ___________ _____ _____ __ 481 | // \_ _____// ____\/ ____\____ _____/ |_ ______ 482 | // | __)_\ __\\ __\/ __ \_/ ___\ __\/ ___/ 483 | // | \| | | | \ ___/\ \___| | \___ \ 484 | // /_______ /|__| |__| \___ >\___ >__| /____ > 485 | // \/ \/ \/ \/ 486 | // ================================================================================================= 487 | // The effects in this section are adapted from the Adafruit NeoPixel library at: 488 | // https://github.com/adafruit/Adafruit_NeoPixel/blob/master/examples/strandtest/strandtest.ino 489 | */ 490 | 491 | // Input a value 0 to 255 to get a color value. 492 | // The colours are a transition r - g - b - back to r. 493 | Color_t Wheel(uint8_t WheelPos); 494 | 495 | // Fill the dots one after the other with a color 496 | void colorWipe(Color_t c, uint8_t wait); 497 | 498 | // Rainbow 499 | void rainbow(uint8_t wait); 500 | 501 | // Slightly different, this makes the rainbow equally distributed throughout 502 | void rainbowCycle(uint8_t wait); 503 | 504 | //Theatre-style crawling lights. 505 | void theaterChase(Color_t c, uint8_t wait); 506 | 507 | //Theatre-style crawling lights with rainbow effect 508 | void theaterChaseRainbow(uint8_t wait); 509 | 510 | --------------------------------------------------------------------------------