diff options
Diffstat (limited to 'src/main.c')
-rw-r--r-- | src/main.c | 297 |
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 () { +} |