first commit

This commit is contained in:
2024-11-08 00:11:06 +06:00
commit 1e0915ac08
9 changed files with 532 additions and 0 deletions

157
ch32ext.c Normal file
View File

@@ -0,0 +1,157 @@
#include <stdio.h>
#include "ch32v003fun.h"
#include "simple_eeprom.h"
#include "state_manager.h"
#define RS485_DIR (1 << 0) // RS485 direction control
#define SRCLR (1 << 1) // Shift register clear (active low)
#define SRCLK (1 << 2) // Shift register clock
#define RCLK (1 << 3) // Storage register clock
#define SER (1 << 4) // Serial data input
// "protocol" defines
#define BOARD_ADDRESS 0x01
#define CMD_SET_OUTPUTS 0x01
#define BROADCAST_ADDR 0xFF
// "protocol" states
enum rx_states {
STATE_ADDR,
STATE_IGNORE,
STATE_CMD,
STATE_DATA_HIGH,
STATE_DATA_LOW
};
void setup_uart(int uartBRR) {
RCC->APB2PCENR |= RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOC |
RCC_APB2Periph_USART1 | RCC_APB2Periph_AFIO;
// RS485_DIR as output, set recv mode
GPIOC->CFGLR &= ~(0xf << (4 * 0));
GPIOC->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP) << (4 * 0);
GPIOC->BCR = RS485_DIR;
// UART pins (PD5=TX, PD6=RX)
GPIOD->CFGLR &= ~(0xf << (4 * 5) | 0xf << (4 * 6));
GPIOD->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP_AF) << (4 * 5);
GPIOD->CFGLR |= GPIO_CNF_IN_FLOATING << (4 * 6);
// 115200 8N1
USART1->CTLR1 =
USART_WordLength_8b | USART_Parity_No | USART_Mode_Tx | USART_Mode_Rx;
USART1->CTLR2 = USART_StopBits_1;
USART1->CTLR3 = USART_HardwareFlowControl_None;
USART1->BRR = uartBRR;
USART1->CTLR1 |= CTLR1_UE_Set;
}
void setup_gpio(void) {
RCC->APB2PCENR |= RCC_APB2Periph_GPIOC;
// PC1-PC4 as out
for (int pin = 1; pin <= 4; pin++) {
GPIOC->CFGLR &= ~(0xf << (4 * pin));
GPIOC->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP) << (4 * pin);
}
GPIOC->BCR = SRCLR | SRCLK | RCLK | SER;
}
void shift_out(uint16_t data) {
GPIOC->BCR = RCLK;
// reorder
uint16_t ordered_data = ((data & 0xFF00) >> 8) | // 1st reg (Q0-Q7)
((data & 0x00FF) << 8); // 2nd reg (Q8-Q15)
// shift out 16 bits, MSB 1st
for (int8_t i = 15; i >= 0; i--) {
GPIOC->BCR = SRCLK;
if (ordered_data & (1 << i)) {
GPIOC->BSHR = SER;
} else {
GPIOC->BCR = SER;
}
GPIOC->BSHR = SRCLK;
}
// latch
GPIOC->BSHR = RCLK;
GPIOC->BCR = RCLK;
}
uint8_t uart_receive_byte(void) {
while (!(USART1->STATR & USART_FLAG_RXNE));
return USART1->DATAR & 0xFF;
}
int main(void) {
SystemInit();
setup_gpio();
setup_uart(UART_BRR);
// reset shift reg
GPIOC->BSHR = SRCLR;
GPIOC->BSHR = RCLK; // rising edge on RCLK
GPIOC->BCR = RCLK;
// load last state
uint16_t current_state = load_state();
printf("Loaded state: %04x\n", current_state);
shift_out(current_state);
uint8_t rx_state = STATE_ADDR;
uint8_t addr, cmd;
uint16_t data = 0;
uint8_t bytes_to_ignore = 0;
printf("SystemClk:%d\r\n", FUNCONF_SYSTEM_CORE_CLOCK);
printf("ChipID:%08lx\r\n", *(uint32_t *)0x1FFFF7C4);
while (1) {
uint8_t byte = uart_receive_byte();
switch (rx_state) {
case STATE_ADDR:
addr = byte;
if (addr == BOARD_ADDRESS || addr == BROADCAST_ADDR) {
rx_state = STATE_CMD;
} else {
// crc??))
bytes_to_ignore = 3; // skip cmd + data_high + data_low
rx_state = STATE_IGNORE;
}
break;
case STATE_IGNORE:
bytes_to_ignore--;
if (bytes_to_ignore == 0) {
rx_state = STATE_ADDR;
}
break;
case STATE_CMD:
cmd = byte;
rx_state = STATE_DATA_HIGH;
break;
case STATE_DATA_HIGH:
data = (uint16_t)byte << 8;
rx_state = STATE_DATA_LOW;
break;
case STATE_DATA_LOW:
data |= byte;
if (cmd == CMD_SET_OUTPUTS) {
printf("Set outputs: 0x%04X\n", data);
shift_out(data);
save_state(data);
dump_eeprom();
}
rx_state = STATE_ADDR;
break;
}
}
}