/led-test.c
#include <stdint.h>

#define CKCU_BASE 0x40088000
#define AHBCCR 0x24
#define GPIOB_BASE 0x400b2000
#define DIRCR 0x000 // Port A Data Direction Control Register
#define INER  0x004 // Port A Input Function Enable Control Register
#define PUR   0x008 // Port A Pull-Up Selection Register
#define PDR   0x00C // Port A Pull-Down Selection Register
#define ODR   0x010 // Port A Open Drain Selection Register
#define DRVR  0x014 // Port A Drive Current Selection Register
#define LOCKR 0x018 // Port A Lock Register
#define DINR  0x01C // Port A Data Input Register
#define DOUTR 0x020 // Port A Data Output Register
#define SRR   0x024 // Port A Output Set and Reset Control Register
#define RR    0x028 // Port A Output Reset Control Register

#define LED_D_OFF (*(uint32_t*)(GPIOB_BASE + SRR) = 1)
#define LED_D_ON  (*(uint32_t*)(GPIOB_BASE + SRR) = 1 << 16)

void sendword(uint32_t w);

void delay(int n) {
	n <<= 4;
	for (int i = 0; i < n; i++) {
		__asm__("nop");
	}
}

void reset() {
	LED_D_OFF;
	delay(100);
}

// a * (c / 255) + b * ((255 - c) / 255)
uint32_t lerp(uint32_t a, uint32_t b, uint8_t c) {
	uint8_t* aa = (uint8_t*)&a;
	uint8_t* bb = (uint8_t*)&b;
	uint32_t r;
	uint8_t* rr = (uint8_t*)&r;
	
	for (int i = 0; i < 3; i++) {
		uint32_t ac = ((uint32_t)aa[i] * c) / 255;
		uint32_t bc = ((uint64_t)bb[i] * (255 - c)) / 255;
		rr[i] = (uint8_t)ac + bc;
	}
	return r;
}

void main() {
	// Enable GPIOB peripheral
	*(uint32_t*)(CKCU_BASE + AHBCCR) |= 0x00020000;
	// Enable output direction on B0
	*(uint32_t*)(GPIOB_BASE + DIRCR) = 1;

	uint8_t j = 0;
	uint32_t values[15];
	while (1) {
		for (int i = 0; i < 15; i++) {
			//values[i] = lerp(0x002020, 0x400000, (j + i * 10) % 255);
			values[i] = (i % 2) ^ (j < 128) ? (j < 128 ? 0x000f0f : 0x1e0000) : 0x000000;
		}
		for (int i = 0; i < 15; i++) {
			sendword(values[i]);
		}
		delay(1000);
		j += 5;
	}
}