summaryrefslogtreecommitdiff
path: root/src/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.c')
-rw-r--r--src/main.c297
1 files changed, 297 insertions, 0 deletions
diff --git a/src/main.c b/src/main.c
new file mode 100644
index 0000000..6d0cb0a
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,297 @@
+
+#include <global.h>
+#include <string.h>
+
+enum indicator_index {
+ IND_TLR, // 0
+ IND_TLY, // 1
+ IND_TLG, // 2
+ IND_B1, // 3
+ IND_B2, // 4
+ IND_S3, // 5
+ IND_S1, // 6
+ IND_S2, // 7
+ IND_R2, // 8
+ IND_S4, // 9
+ IND_R1, // 10
+};
+
+enum andon_index {
+ AND_G,
+ AND_B,
+ AND_Y,
+ AND_R,
+};
+
+uint32_t xorshift32()
+{
+ /* https://en.wikipedia.org/wiki/Xorshift */
+ static uint32_t x = 1;
+ x ^= x << 13;
+ x ^= x >> 17;
+ x ^= x << 5;
+ return x;
+}
+
+void set_indicators(int val) {
+ int tlr = !!(val & (1<<0));
+ int tly = !!(val & (1<<1));
+ int tlg = !!(val & (1<<2));
+ int b1 = !!(val & (1<<3));
+ int b2 = !!(val & (1<<4));
+ int r1 = !!(val & (1<<5));
+ int r2 = !!(val & (1<<6));
+ int s1 = !!(val & (1<<7));
+ int s2 = !!(val & (1<<8));
+ int s3 = !!(val & (1<<9));
+ int s4 = !!(val & (1<<10));
+
+ GPIOB->BRR =
+ (1 << 12) |
+ (1 << 13) |
+ (1 << 14) |
+ (1 << 15) |
+ (1 << 0) |
+ (1 << 1) |
+ (1 << 10) |
+ (1 << 11) |
+ (1 << 5) |
+ (1 << 6) |
+ (1 << 7);
+ GPIOB->BSRR =
+ (tlr << 12) |
+ (tly << 13) |
+ (tlg << 14) |
+ ( b1 << 15) |
+ ( b2 << 0) |
+ ( r1 << 1) |
+ ( r2 << 10) |
+ ( s1 << 11) |
+ ( s2 << 5) |
+ ( s3 << 6) |
+ ( s4 << 7);
+}
+
+void set_andon(int val) {
+ int a = !!(val & (1<<0));
+ int b = !!(val & (1<<1));
+ int c = !!(val & (1<<2));
+ int d = !!(val & (1<<3));
+
+ GPIOB->BRR = (1<<8) | (1<<9) | (1<<4) | (1<<3);
+ GPIOB->BSRR = (a<<3) | (b<<4) | (c<<8) | (d<<9);
+}
+
+void buzz(int val) {
+ GPIOA->BRR = 1;
+ GPIOA->BSRR = !!val;
+}
+
+ssize_t uart_pos = 0;
+ssize_t uart_nb = 0;
+struct ch9329_packet {
+ uint8_t header[2];
+ uint8_t addr;
+ uint8_t cmd;
+ uint8_t len;
+ uint8_t data[9];
+} uart_buf;
+uint8_t *uart_p = (uint8_t *)&uart_buf;
+
+void uart_tx(bool keyboard, bool press) {
+ if (uart_nb > 0) {
+ return;
+ }
+
+ memset(&uart_buf, 0, sizeof(uart_buf));
+ uart_buf.header[0] = 0x57;
+ uart_buf.header[1] = 0xab;
+ int dlen = sizeof(uart_buf);
+
+ if (keyboard) {
+ uart_buf.len = 8;
+ uart_buf.cmd = 2;
+ uart_buf.data[0] = 0;
+ uart_buf.data[1] = 0;
+ uart_buf.data[2] = press ? 0x28 : 0; /* Enter */
+ } else {
+ uart_buf.len = 7;
+ uart_buf.cmd = 4;
+ dlen -= 1;
+ uart_buf.data[0] = 2;
+ uart_buf.data[1] = press ? 1 : 0;
+ uart_buf.data[2] = 0;
+ }
+
+ int checksum = 0;
+ for (size_t i=0; i<dlen-1; i++) {
+ checksum += uart_p[i];
+ }
+ uart_buf.data[uart_buf.len] = checksum;
+
+ uart_nb = dlen;
+}
+
+int get_config_button() {
+ return !(GPIOA->IDR & (1<<6));
+}
+
+int get_trig_button() {
+ return !(GPIOA->IDR & (1<<7));
+}
+
+int main(void) {
+ RCC->CFGR = (0x7 << RCC_CFGR_PLLMULL_Pos);
+ RCC->CR |= RCC_CR_PLLON;
+ while (!(RCC->CR & RCC_CR_PLLRDY)) {
+ /* Do nothing. */
+ }
+
+ FLASH->ACR |= (1<<FLASH_ACR_LATENCY_Pos);
+
+ RCC->CFGR |= (2<<RCC_CFGR_SW_Pos);
+ while (((RCC->CFGR >> RCC_CFGR_SWS_Pos) & 0x3) != 2) {
+ /* Do nothing. */
+ }
+
+ /* Enable peripheral clocks */
+ RCC->APB2ENR |= RCC_APB2ENR_USART1EN | RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN | RCC_APB2ENR_AFIOEN;
+
+ /* Disable JTAG NJTRST pin to free up GPIOB4*/
+ AFIO->MAPR = (2<<AFIO_MAPR_SWJ_CFG_Pos);
+
+ /*
+ * 76543210 */
+ GPIOA->CRL = 0x88444443;
+ /* 111111
+ * 54321098 */
+ GPIOA->CRH = 0x444444b4;
+
+ GPIOA->BSRR = (1<<6) | (1<<7); /* Enable button pull-ups */
+
+ /*
+ * 76543210 */
+ GPIOB->CRL = 0x33333433;
+ /* 111111
+ * 54321098 */
+ GPIOB->CRH = 0x33333333;
+
+ /* 111111
+ * 54321098 */
+ GPIOC->CRH = 0x44344444;
+
+ USART1->CR1 = USART_CR1_UE | USART_CR1_TE;
+ USART1->BRR = 0xea6; /* 9600 Bd, matches default baud rate of CH9329 */
+
+ SystemCoreClockUpdate();
+
+ set_indicators(0xffff);
+ set_andon(0xf);
+
+ buzz(1);
+ for (int i=0; i<3000000; i++) {
+ asm volatile ("nop");
+ }
+ buzz(0);
+
+ int n = 0;
+ int tl = 0;
+ int spin = 0;
+ int andr = 0;
+ int blk = 0;
+ int uart_ct = 0;
+ while (23) {
+ if ((uart_nb > 0) && (USART1->SR & USART_SR_TXE)) {
+ USART1->DR = uart_p[uart_pos];
+ uart_pos += 1;
+ if (uart_pos == uart_nb) {
+ uart_pos = 0;
+ uart_nb = 0;
+ }
+ }
+
+ if (uart_ct == 0) {
+ uart_tx(get_config_button(), get_trig_button());
+ uart_ct = 1<<12;
+ } else {
+ uart_ct -= 1;
+ }
+
+ n++;
+ if (n&(1<<16)) {
+ tl = (tl+1)%3;
+ spin = (spin+1)%4;
+ int r = xorshift32();
+
+ int ind = 0;
+ ind |= (tl == 0 ? (1<<IND_TLR) : (tl == 1 ? (1<<IND_TLY) : (1<<IND_TLG)));
+ ind |= (spin == 0 ? (1<<IND_S1) : (spin == 1 ? (1<<IND_S2) : (spin == 2 ? (1<<IND_S3) : (1<<IND_S4))));
+ ind |= (r & 1) ? (1<<IND_B1) : 0;
+ ind |= (r & 2) ? (1<<IND_B2) : 0;
+ ind |= (r & 4) ? (1<<IND_R1) : (1<<IND_R2);
+ set_indicators(ind);
+
+ andr = (andr + 1) % 18;
+ blk = (blk + 1) % 32;
+ int and = 0;
+ and |= (andr > 12) ? (1<<AND_R) : 0;
+ and |= (blk > 16) ? (1<<AND_Y) : 0;
+ and |= (blk < 16) ? (1<<AND_G) : 0;
+ and |= (r & 8) ? (1<<AND_B) : 0;
+ set_andon(and);
+
+ n = 0;
+ GPIOC->ODR ^= 1<<13;
+ }
+ }
+}
+
+void HardFault_Handler() {
+ asm volatile ("bkpt");
+}
+
+void delay_us(int duration_us) {
+ while (duration_us--) {
+ for (int i=0; i<3; i++) {
+ asm volatile ("nop");
+ }
+ }
+}
+
+void *memcpy(void *restrict dest, const void *restrict src, size_t n)
+{
+ unsigned char *d = dest;
+ const unsigned char *s = src;
+
+ for (; n; n--) {
+ *d++ = *s++;
+ }
+ return dest;
+}
+
+void *memmove(void *dest, const void *src, size_t n)
+{
+ return memcpy(dest, src, n);
+}
+
+void *memset(void *dest, int c, size_t n)
+{
+ unsigned char *d = dest;
+ while (n--) {
+ *d++ = c;
+ }
+ return dest;
+}
+
+size_t strlen(const char *s)
+{
+ const char *start = s;
+ while (*s) {
+ s++;
+ }
+ return s - start;
+}
+
+void __libc_init_array (void) __attribute__((weak));
+void __libc_init_array () {
+}