133 lines
No EOL
2.5 KiB
C
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;
|
|
} |