ch32_oled/gol/gol.c
2024-04-07 13:06:09 +02:00

133 lines
No EOL
2.5 KiB
C

#define SSD1306_128X32
#include "ch32v003fun.h"
#include <stdio.h>
#include "ssd1306_i2c.h"
#include "ssd1306.h"
#define PIN_LED PC4
#define PIN_BTN PC7
#define u8 uint8_t
#define u16 uint16_t
uint8_t gol_tmp[sizeof(ssd1306_buffer)];
uint32_t lfsr = 1; // PRNG state
u8 rand8();
u8 get_pixel(u8 x, u8 y);
void gol_step();
void r_pentomino();
void randomise();
int main()
{
SystemInit();
funGpioInitAll();
funPinMode(PIN_LED, GPIO_CFGLR_OUT_10Mhz_PP);
funPinMode(PIN_BTN, GPIO_CFGLR_IN_PUPD);
ssd1306_i2c_init();
ssd1306_init();
randomise();
while (1)
{
ssd1306_refresh();
gol_step();
memcpy(ssd1306_buffer, gol_tmp, sizeof(ssd1306_buffer));
if (funDigitalRead(PIN_BTN))
{
randomise();
ssd1306_refresh();
funDigitalWrite(PIN_LED, FUN_HIGH);
Delay_Ms(100);
funDigitalWrite(PIN_LED, FUN_LOW);
}
}
}
void r_pentomino()
{
ssd1306_setbuf(0);
ssd1306_drawPixel(20, 20, 1);
ssd1306_drawPixel(21, 20, 1);
ssd1306_drawPixel(21, 21, 1);
ssd1306_drawPixel(22, 21, 1);
ssd1306_drawPixel(21, 22, 1);
}
void randomise()
{
lfsr = SysTick->CNT;
for (u16 b = 0; b < sizeof(ssd1306_buffer); b++)
{
ssd1306_buffer[b] = rand8();
}
}
u8 get_pixel(u8 x, u8 y)
{
x = x & 127;
y = y & 31;
u8 slice = ssd1306_buffer[(y / 8) * 128 + x];
return (slice & (1 << (y & 7))) != 0;
}
void gol_step()
{
// slow pixel-by-pixel implementation
for (u8 x = 0; x < 128; x++)
{
for (u8 y = 0; y < 32; y++)
{
u8 this = get_pixel(x, y);
u8 sum = 0;
sum += get_pixel(x + 127, y + 31);
sum += get_pixel(x + 127, y);
sum += get_pixel(x + 127, y + 1);
sum += get_pixel(x, y + 31);
sum += get_pixel(x, y + 1);
sum += get_pixel(x + 1, y + 31);
sum += get_pixel(x + 1, y);
sum += get_pixel(x + 1, y + 1);
u8 new_state = (sum == 3) | ((sum == 2) & this);
u16 addr = x + (y / 8) * 128;
if (new_state)
gol_tmp[addr] |= (1 << (y & 7));
else
gol_tmp[addr] &= ~(1 << (y & 7));
}
}
}
/* White Noise Generator State */
#define NOISE_BITS 8
#define NOISE_MASK ((1 << NOISE_BITS) - 1)
#define NOISE_POLY_TAP0 31
#define NOISE_POLY_TAP1 21
#define NOISE_POLY_TAP2 1
#define NOISE_POLY_TAP3 0
/*
* random byte generator, taken from ch32v003fun examples
*/
uint8_t rand8(void)
{
uint8_t bit;
uint32_t new_data;
for (bit = 0; bit < NOISE_BITS; bit++)
{
new_data = ((lfsr >> NOISE_POLY_TAP0) ^
(lfsr >> NOISE_POLY_TAP1) ^
(lfsr >> NOISE_POLY_TAP2) ^
(lfsr >> NOISE_POLY_TAP3));
lfsr = (lfsr << 1) | (new_data & 1);
}
return lfsr & NOISE_MASK;
}