80 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			80 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #include <stdlib.h>
 | |
| #include <stdint.h>
 | |
| #include <unistd.h>
 | |
| 
 | |
| // Here I use a lcg RNG with a specificaly crafted period to enumerate all pixels
 | |
| // and color them by cycling a colormap in a randomish order
 | |
| // Same approch as in DOOM (1993)
 | |
| // see: Knuth - The Art of Computer Programming, Volume 2: Seminumerical Algorithms
 | |
| 
 | |
| uint32_t hash32(uint32_t d) {
 | |
|     // DJB Hash
 | |
|     uint32_t h = 0x811c9dc5;
 | |
|     h = (h * 16777619) ^ ((d >>  0) & 0xff);
 | |
|     h = (h * 16777619) ^ ((d >>  8) & 0xff);
 | |
|     h = (h * 16777619) ^ ((d >> 16) & 0xff);
 | |
|     h = (h * 16777619) ^ ((d >> 24) & 0xff);
 | |
|     return h;
 | |
| }
 | |
| 
 | |
| // must be the next prime after NUM_TOTAL_LEDS
 | |
| #define IDLE_PRIME 3203 
 | |
| // must be a primitive element of the prime residue field |N/IDLE_PRIM
 | |
| #define IDLE_PRIM_ELEM 777
 | |
| 
 | |
| int IDLE_rand(int *seed){
 | |
|     return *seed = (*seed * IDLE_PRIM_ELEM ) % IDLE_PRIME;
 | |
| }
 | |
| 
 | |
| int IDLE_last_pixel   = 34;
 | |
| int IDLE_color_offset = 2;
 | |
| 
 | |
| uint32_t IDLE_colors[5] ={
 | |
|     0xd31719,
 | |
|     0x0f6851,
 | |
|     0xd4772e,
 | |
|     0xd84b23,
 | |
|     0x3d89a7
 | |
| };
 | |
| 
 | |
| 
 | |
| int Nx, Ny;
 | |
| uint8_t *buf;
 | |
| 
 | |
| void SetPixel(int x, int y, uint8_t r, uint8_t g, uint8_t b){
 | |
|     buf[3*(x+Nx*y)+0] = r;
 | |
|     buf[3*(x+Nx*y)+1] = g;
 | |
|     buf[3*(x+Nx*y)+2] = b;
 | |
| }
 | |
| 
 | |
| void IDLE_set_pixel(){
 | |
|     int i = IDLE_rand(&IDLE_last_pixel)-1;
 | |
|     int x = i%Nx;
 | |
|     int y = i/Nx;
 | |
|     if (i == IDLE_color_offset){
 | |
|         IDLE_color_offset++;
 | |
|         if (IDLE_color_offset > 100)
 | |
|             IDLE_color_offset=2;
 | |
|     } 
 | |
|     if (i >= Nx*Ny) return;
 | |
|     int color_count = sizeof(IDLE_colors)/sizeof(IDLE_colors[0]);
 | |
| 
 | |
|     int color = IDLE_colors[hash32(i+IDLE_color_offset)%color_count];
 | |
|     SetPixel(x, y, (color>>16)&0xff, (color>>8)&0xff, (color>>0)&0xff);
 | |
| }
 | |
| 
 | |
| int main(int argc, char **argv) {
 | |
|     Nx = atoi(argv[1]);
 | |
|     Ny = atoi(argv[2]);
 | |
|     buf = malloc(Nx*Ny*3);
 | |
|     int sleepms = atoi(argv[3]);
 | |
|     if (sleepms == 0) sleepms = 30;
 | |
| 
 | |
|     while(1) {
 | |
|         IDLE_set_pixel();
 | |
|         write(1, buf, Nx*Ny*3);
 | |
|         usleep(1000*sleepms);
 | |
| 
 | |
|     }
 | |
| }
 | 
