Nimbin[12]?Embedded / snake_compiler / snake_SDL/src/matrix.c

snake_compiler git · main

Snake compiled to a bare-metal RISC-V microcontroller

riscv embedded bare-metal c snake · first commit 2026-01-18 · last commit 2026-01-18 (8 months ago) · synced 3 days ago · upstream: git.ide3.de/hsnr/compilerbau/snake_compiler

C 95.2% Markdown 3.3%
git clone https://git.christianimmanuel.de/embedded/snake_compiler.gitwget https://git.christianimmanuel.de/embedded/snake_compiler/archive/snake_compiler.tar.gz
snake_SDL/src/matrix.c 5.4 KB · 209 lines raw
#include "matrix.h"




static uint8_t pixels_buffer[NUM_PIXELS * 3];

GameMode game_mode;

Button*    button_1;
Button*    button_2;
Button*    button_3;
Button*    button_4;
LEDMatrix* matrix;




// Generate a pseudo-random number in [0, max)
int random_Int(int max) {
    uint64_t t = uptime_us();        // get current microseconds
    t ^= t >> 33;                    // mix bits
    t *= 0xff51afd7ed558ccdULL;      // arbitrary constant
    t ^= t >> 33;
    t *= 0xc4ceb9fe1a85ec53ULL;      // arbitrary constant
    t ^= t >> 33;
    return (int)t % max;           // limit to range
}



void
matrix_Init(Color color) {
    for (int y = 0; y < MATRIX_HEIGHT; y++) {
        for (int x = 0; x < MATRIX_WIDTH; x++) {
            matrix->pixels[y][x].color = color;
            matrix->pixels[y][x].type  = NONE;
        }
    }
}

void
matrix_SetPixelColor(int x, int y, Color c) {
    if (x < 0 || x >= MATRIX_WIDTH || y < 0 || y >= MATRIX_HEIGHT) return;
    matrix->pixels[y][x].color = c;
}


void
matrix_ToMdkBuffer() {
    for (int y = 0, yy = MATRIX_HEIGHT-1; y < MATRIX_HEIGHT; y++, yy--) {
        int xx = 0;
        bool is_un = (y+1)%2;
        for (int x = is_un ? 0 : MATRIX_WIDTH-1;
             is_un ? (x < MATRIX_WIDTH)
                 : (x >= 0) ;
             xx++,
             is_un ? x++
                 : x--) {
            int idx = (y * MATRIX_WIDTH + xx) * 3;
            pixels_buffer[idx + 0] = matrix->pixels[yy][x].color.g;
            pixels_buffer[idx + 1] = matrix->pixels[yy][x].color.r;
            pixels_buffer[idx + 2] = matrix->pixels[yy][x].color.b;
        }
    }
    /*
    for (int y = 0; y < MATRIX_HEIGHT; y++) {
        for (int x = 0; x < MATRIX_WIDTH; x++) {
            int idx = (y * MATRIX_WIDTH + x) * 3;
            pixels_buffer[idx + 0] = matrix->pixels[y][x].color.g;
            pixels_buffer[idx + 1] = matrix->pixels[y][x].color.r;
            pixels_buffer[idx + 2] = matrix->pixels[y][x].color.b;
        }
    }
    */
}

void
matrix_WriteLed() {
    matrix_ToMdkBuffer();
    ws2812_show(WS2812_PIN, pixels_buffer, NUM_PIXELS * 3);
}

void
matrix_ClearAll(Color color) {
    matrix_Init(color);
    matrix_WriteLed();
}



void
matrix_Blink(int count, unsigned long delay_millis) {
    Color green = {0, MAX_BRIGHTNESS, 0};
    Color black = {0, 0, 0};

    for (int i = 0; i < count; i++) {
        // Set all pixels to green
        for (int y = 0; y < MATRIX_HEIGHT; y++) {
            for (int x = 0; x < MATRIX_WIDTH; x++) {
                matrix_SetPixelColor(x, y, green);
            }
        }
        matrix_WriteLed();
        delay_ms(delay_millis);

        // Set all pixels to black
        for (int y = 0; y < MATRIX_HEIGHT; y++) {
            for (int x = 0; x < MATRIX_WIDTH; x++) {
                matrix_SetPixelColor(x, y, black);
            }
        }
        matrix_WriteLed();
        delay_ms(delay_millis);
    }
}





static inline Color
hsv_to_rgb_u8(uint8_t h, uint8_t s, uint8_t v) {
    uint8_t region = h / 43;
    uint8_t rem = (h - region * 43) * 6;

    uint8_t p = (uint8_t)(v * (255 - s)) >> 8;
    uint8_t q = (uint8_t)(v * (255 - ((s * rem) >> 8))) >> 8;
    uint8_t t = (uint8_t)(v * (255 - ((s * (255 - rem)) >> 8))) >> 8;

    switch (region) {
        case 0: return (Color){ v, t, p };
        case 1: return (Color){ q, v, p };
        case 2: return (Color){ p, v, t };
        case 3: return (Color){ p, q, v };
        case 4: return (Color){ t, p, v };
        default:return (Color){ v, p, q };
    }
}



void matrix_Print() {
    printf("## START MATRIX\n", MATRIX_HEIGHT);
    for (int y = 0; y < MATRIX_HEIGHT; y++) {
        for (int x = 0; x < MATRIX_WIDTH; x++)
            printf("%u|%u|%u ",
                    matrix->pixels[y][x].color.r,
                    matrix->pixels[y][x].color.g,
                    matrix->pixels[y][x].color.b);
            //printf("%3d ", (matrix->pixels[y][x].color.r+matrix->pixels[y][x].color.g+matrix->pixels[y][x].color.b));
            //printf("%d ", matrix->pixels[y][x].type);
        printf("\n\n", MATRIX_HEIGHT);
    }
    printf("\n", MATRIX_HEIGHT);
}



void matrix_Update() {
    static uint64_t last = 0;
    static uint64_t now  = 0;
    static int counter    = 0;

    if (last == 0) {
        last = uptime_us();
        now  = last;
    }

    now = uptime_us();
    uint64_t interval = 50000;

    if (now - last > interval) {
        last = now;
        counter++;
    }

    for (int y = 0; y < MATRIX_HEIGHT; y++) {
        for (int x = 0; x < MATRIX_WIDTH; x++) {

            Color c = matrix->pixels[y][x].color;

            if (game_mode == FANCY) {
                if (matrix->pixels[y][x].type == NONE) {
                    int cx = MATRIX_WIDTH  / 2;
                    int cy = MATRIX_HEIGHT / 2;

                    int dx = (uint16_t)(x - cx);
                    int dy = (uint16_t)(y - cy);

                    uint16_t dist = (uint16_t)(dx*dx + dy*dy);
                    uint16_t maxd = (uint16_t)(cx*cx + cy*cy);

                    uint8_t hue = (uint8_t)((dist * 255) / maxd);

                    c = hsv_to_rgb_u8(hue, 255, 255);

                    /* downscale to MAX_BRIGHTNESS */
                    c.r = (uint8_t)(c.r + counter) % MAX_BRIGHTNESS;
                    c.g = (uint8_t)(c.g + counter) % MAX_BRIGHTNESS;
                    c.b = (uint8_t)(c.b + counter) % MAX_BRIGHTNESS;
                }
            }

            matrix_SetPixelColor(x, y, c);
        }
    }
}