#include #include #include // 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); } }