WIP
This commit is contained in:
parent
c7b7e6b1d5
commit
c5d0320696
6 changed files with 139 additions and 39 deletions
|
|
@ -7,7 +7,11 @@ struct adc_state {
|
|||
uint8_t txbuf[12];
|
||||
uint8_t rxbuf[12];
|
||||
uint32_t dma_ccr3;
|
||||
int32_t data[2];
|
||||
uint32_t sampling_interval_us;
|
||||
uint32_t sample_count;
|
||||
int32_t samples[16][2];
|
||||
size_t sample_wr_idx;
|
||||
size_t sample_rd_idx;
|
||||
bool has_adc;
|
||||
bool overload[2];
|
||||
ErrorCode error;
|
||||
|
|
|
|||
|
|
@ -84,8 +84,10 @@ enum board_addr {
|
|||
};
|
||||
|
||||
void delay_us(int duration_us);
|
||||
uint64_t get_sync_time(void);
|
||||
|
||||
extern enum board_config board_config;
|
||||
extern uint64_t sys_time_us;
|
||||
extern uint64_t sync_time_us;
|
||||
|
||||
#endif /* __GLOBAL_H__ */
|
||||
|
|
|
|||
|
|
@ -40,6 +40,13 @@ struct proto_state {
|
|||
uint8_t rx_buttons;
|
||||
bool rx_lid_open;
|
||||
bool rx_estop;
|
||||
|
||||
uint32_t adc_samples[2][2][512];
|
||||
size_t adc_sp_wr_idx[2];
|
||||
size_t adc_sp_rd_idx[2];
|
||||
uint64_t adc_sample_timestamp[2];
|
||||
uint32_t adc_sampling_interval[2];
|
||||
uint32_t adc_sample_count[2];
|
||||
};
|
||||
|
||||
enum proto_led_format {
|
||||
|
|
@ -82,11 +89,19 @@ struct __attribute__((__packed__)) pkt_time_sync {
|
|||
uint64_t timestamp;
|
||||
};
|
||||
|
||||
struct __attribute__((__packed__)) pkt_adc_data {
|
||||
struct ll_pkt ll_pkt;
|
||||
uint64_t timestamp;
|
||||
uint32_t sampling_interval_us;
|
||||
uint32_t sample_count;
|
||||
uint8_t samples[16][2][3];
|
||||
};
|
||||
|
||||
|
||||
extern struct proto_state st_proto;
|
||||
|
||||
|
||||
void proto_init_host(void);
|
||||
void proto_loop_host(void);
|
||||
|
||||
void proto_init(void);
|
||||
void proto_loop(void);
|
||||
|
||||
#endif /* __PROTO_H__ */
|
||||
|
|
|
|||
|
|
@ -113,6 +113,7 @@ void adc_init() {
|
|||
adc_sync_write(ADC_REG_CLOCK, ADC_CLOCK_CH1_EN | ADC_CLOCK_CH2_EN | ADC_CLOCK_OSR_8192 | ADC_CLOCK_PWR_HIRES);
|
||||
adc_sync_write(ADC_REG_GAIN, ADC_GAIN1_PGAGAIN1_4 | ADC_GAIN1_PGAGAIN0_4);
|
||||
adc_sync_write(ADC_REG_MODE, (1<<ADC_MODE_WLENGTH_Pos) | ADC_MODE_TIMEOUT);
|
||||
st_adc.sampling_interval_us =
|
||||
|
||||
/* wait for ~DRDY to go high (inactive) */
|
||||
int i;
|
||||
|
|
@ -159,11 +160,12 @@ void adc_dma_interrupt(uint32_t channel, uint32_t flags) {
|
|||
|
||||
} else {
|
||||
/* measurements ready */
|
||||
size_t wr_idx = st_adc.sample_wr_idx;
|
||||
int32_t val = (st_adc.rxbuf[3] << 16) | (st_adc.rxbuf[4] << 8) | st_adc.rxbuf[5];
|
||||
if (val&0x00800000) {
|
||||
val |= 0xff000000;
|
||||
}
|
||||
st_adc.data[0] = val;
|
||||
st_adc.samples[wr_idx][0] = val;
|
||||
|
||||
if (val > ADC_FSR_POS || val < ADC_FSR_NEG) {
|
||||
st_adc.overload[0] = true;
|
||||
|
|
@ -175,7 +177,10 @@ void adc_dma_interrupt(uint32_t channel, uint32_t flags) {
|
|||
if (val&0x00800000) {
|
||||
val |= 0xff000000;
|
||||
}
|
||||
st_adc.data[1] = val;
|
||||
st_adc.samples[wr_idx][1] = val;
|
||||
st_adc.sample_rd_idx = wr_idx;
|
||||
st_adc.sample_wr_idx = (wr_idx+1) % COUNT_OF(st_adc.data);
|
||||
st_adc.sample_count++;
|
||||
|
||||
if (val > ADC_FSR_POS || val < ADC_FSR_NEG) {
|
||||
st_adc.overload[1] = true;
|
||||
|
|
|
|||
14
src/main.c
14
src/main.c
|
|
@ -34,6 +34,7 @@ static void loop_adc(void);
|
|||
|
||||
enum board_config board_config;
|
||||
uint64_t sys_time_us;
|
||||
uint64_t sync_time_us;
|
||||
|
||||
int bt_inputs() {
|
||||
bool bt0 = !!(GPIOB->IDR & (1<<2));
|
||||
|
|
@ -354,9 +355,11 @@ int main(void) {
|
|||
uart_st.addr = BADDR_MEAS_BASE + ((bt>>1) & 3);
|
||||
}
|
||||
}
|
||||
proto_init();
|
||||
usb_init();
|
||||
|
||||
sys_time_us = 0;
|
||||
sync_time_us = 0;
|
||||
SysTick->LOAD = SystemCoreClock / SYSTICK_INTERVAL_US; /* 1ms interrupt interval */
|
||||
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk;
|
||||
NVIC_EnableIRQ(SysTick_IRQn);
|
||||
|
|
@ -382,11 +385,13 @@ int main(void) {
|
|||
update_leds();
|
||||
}
|
||||
|
||||
proto_loop();
|
||||
|
||||
if (board_config == BCFG_DISPLAY) {
|
||||
loop_display();
|
||||
if (board_config == BCFG_MOTOR) {
|
||||
} else if (board_config == BCFG_MOTOR) {
|
||||
loop_motor();
|
||||
if (board_config == BCFG_MEAS) {
|
||||
} else if (board_config == BCFG_MEAS) {
|
||||
loop_adc();
|
||||
}
|
||||
}
|
||||
|
|
@ -499,6 +504,11 @@ void loop_adc() {
|
|||
|
||||
void SysTick_Handler() {
|
||||
sys_time_us += SYSTICK_INTERVAL_US;
|
||||
sync_time_us += SYSTICK_INTERVAL_US;
|
||||
}
|
||||
|
||||
uint64_t get_sync_time() {
|
||||
return sync_time_us + SysTick->VAL * SYSTICK_INTERVAL_US / SysTick->LOAD;
|
||||
}
|
||||
|
||||
void handle_usb_packet(void *packet, size_t len) {
|
||||
|
|
|
|||
126
src/proto.c
126
src/proto.c
|
|
@ -1,26 +1,32 @@
|
|||
|
||||
#include <proto.h>
|
||||
#include <adc.h>
|
||||
|
||||
static void tx_time_sync(void);
|
||||
static void tx_fetch_adc(int index);
|
||||
static void proto_handle(bool timeout);
|
||||
static ErrorCode tx_fetch_adc(int index);
|
||||
static void proto_handle_host(bool timeout);
|
||||
static void proto_update_lcd_strings(void);
|
||||
static void tx_update_display(void);
|
||||
static ErrorCode tx_update_display(void);
|
||||
static void tx_adc_data(void);
|
||||
|
||||
|
||||
struct proto_state st_proto;
|
||||
|
||||
|
||||
void proto_init_host() {
|
||||
void proto_init() {
|
||||
memset(&st_proto, 0, sizeof(st_proto));
|
||||
}
|
||||
|
||||
void proto_loop_host() {
|
||||
if (sys_time_us - st_proto.last_start > PROTO_UPDATE_INTERVAL_MS*1000 - st_proto.delta ) {
|
||||
st_proto.fsm = ST_START;
|
||||
} else if (st_proto.fsm > ST_START && st_proto.fsm < ST_WAITING) {
|
||||
if (sys_time_us - uart_st.last_transmission > PROTO_RESPONSE_TIMEOUT_MS*1000) {
|
||||
proto_handle(true);
|
||||
void proto_loop() {
|
||||
if (board_config == BCFG_MOTOR) { /* We are the protocol host */
|
||||
if (sys_time_us - st_proto.last_start > PROTO_UPDATE_INTERVAL_MS*1000 - st_proto.delta ) {
|
||||
st_proto.fsm = ST_START;
|
||||
proto_handle_host(false);
|
||||
|
||||
} else if (st_proto.fsm > ST_START && st_proto.fsm < ST_WAITING) {
|
||||
if (sys_time_us - uart_st.last_transmission > PROTO_RESPONSE_TIMEOUT_MS*1000) {
|
||||
proto_handle_host(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -32,12 +38,34 @@ void uart_handle_user_packet(struct ll_pkt *pkt, size_t len) {
|
|||
st_proto.rx_buttons = ((struct pkt_button_state *)pkt)->buttons;
|
||||
st_proto.rx_lid_open = st_proto.rx_buttons & PROTO_DSP_BT_LID;
|
||||
st_proto.rx_estop = st_proto.rx_buttons & PROTO_DSP_BT_ESTOP;
|
||||
|
||||
} else if (pkt->type == PK_TIME_SYNC) {
|
||||
sync_time_us = ((pkt_time_sync *)pkt)->timestamp;
|
||||
}
|
||||
|
||||
proto_handle(false);
|
||||
if (board_config == BCFG_MOTOR) { /* We are the protocol host */
|
||||
if (pkt->type == PK_FETCH_RESPONSE) {
|
||||
/* ... */
|
||||
|
||||
proto_handle_host(false);
|
||||
|
||||
} else {
|
||||
proto_handle_host(true);
|
||||
}
|
||||
|
||||
} else if (board_config == BCFG_DISPLAY) {
|
||||
if (pkt->type == PK_DISPLAY_UPDATE) {
|
||||
/* ... */
|
||||
}
|
||||
} else if (board_config == BCFG_MEAS) {
|
||||
if (pkt->type == PK_FETCH_ADC) {
|
||||
tx_adc_data();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void proto_handle(bool timeout) {
|
||||
void proto_handle_host(bool timeout) {
|
||||
ErrorCode rc = ERR_SUCCESS;
|
||||
switch (st_proto.fsm) {
|
||||
case ST_START:
|
||||
st_proto.delta += (sys_time_us - st_proto.last_start) - UPDATE_INTERVAL_MS*1000;
|
||||
|
|
@ -45,21 +73,21 @@ void proto_handle(bool timeout) {
|
|||
tx_time_sync();
|
||||
st_proto.fsm = ST_TIME_SYNC;
|
||||
/* immediately enqueue next command, since time syncs are a broadcast and do not require a response. */
|
||||
proto_handle(false);
|
||||
proto_handle_host(false);
|
||||
break;
|
||||
|
||||
case ST_TIME_SYNC:
|
||||
tx_fetch_adc(0);
|
||||
rc = tx_fetch_adc(0);
|
||||
st_proto.fsm = ST_FETCH_0;
|
||||
break;
|
||||
|
||||
case ST_FETCH_0:
|
||||
tx_fetch_adc(1);
|
||||
rc = tx_fetch_adc(1);
|
||||
st_proto.fsm = ST_FETCH_1;
|
||||
break;
|
||||
|
||||
case ST_FETCH_1:
|
||||
tx_update_display();
|
||||
rc = tx_update_display();
|
||||
st_proto.fsm = ST_UPDATE_DISPLAY;
|
||||
break;
|
||||
|
||||
|
|
@ -71,6 +99,53 @@ void proto_handle(bool timeout) {
|
|||
st_proto.fsm = ST_WAITING;
|
||||
break;
|
||||
}
|
||||
|
||||
if (rc) {
|
||||
st_proto.error = rc;
|
||||
st_proto.last_error = sys_time_us;
|
||||
/* If there was a transmission error, immediately enqueue next transmission. */
|
||||
proto_handle_host(true);
|
||||
}
|
||||
}
|
||||
|
||||
void tx_adc_data() {
|
||||
struct pkt_adc_data pk = {
|
||||
.ll_pkt = {
|
||||
.src = uart_st.addr,
|
||||
.dst = SER_ADDR_BROADCAST,
|
||||
.pid = 0,
|
||||
.type = PK_TIME_SYNC,
|
||||
},
|
||||
.timestamp = sync_time_us,
|
||||
.sampling_interval_us = st_adc.sampling_interval_us,
|
||||
.sample_count = st_adc.sample_count,
|
||||
};
|
||||
|
||||
/* Format samples stored in native 32 bit ints into 24 bit fields */
|
||||
ssize_t rd_idx = st_adc.sample_rd_idx;
|
||||
uint8_t *p = samples;
|
||||
for (size_t i=0; i<COUNT_OF(pk.samples)) {
|
||||
uint32_t sp = st_adc.samples[rd_idx][0];
|
||||
*p++ = sp&0xff;
|
||||
*p++ = (sp>>8)&0xff;
|
||||
*p++ = (sp>>16)&0xff;
|
||||
|
||||
sp = st_adc.samples[rd_idx][1];
|
||||
*p++ = sp&0xff;
|
||||
*p++ = (sp>>8)&0xff;
|
||||
*p++ = (sp>>16)&0xff;
|
||||
|
||||
rd_idx -= 1;
|
||||
if (rd_idx < 0) {
|
||||
rd_idx = COUNT_OF(st_adc.samples);
|
||||
}
|
||||
}
|
||||
|
||||
ErrorCode rc = uart_send_packet_nonblocking(&pk, sizeof(pk));
|
||||
if (rc) {
|
||||
st_proto.error = rc;
|
||||
st_proto.last_error = sys_time_us;
|
||||
}
|
||||
}
|
||||
|
||||
void tx_time_sync() {
|
||||
|
|
@ -88,11 +163,10 @@ void tx_time_sync() {
|
|||
if (rc) {
|
||||
st_proto.error = rc;
|
||||
st_proto.last_error = sys_time_us;
|
||||
proto_handle(true);
|
||||
}
|
||||
}
|
||||
|
||||
void tx_fetch_adc(int index) {
|
||||
ErrorCode tx_fetch_adc(int index) {
|
||||
struct ll_pkt pk = {
|
||||
.src = uart_st.addr,
|
||||
.dst = BADDR_MEAS_BASE + index,
|
||||
|
|
@ -100,12 +174,7 @@ void tx_fetch_adc(int index) {
|
|||
.type = PK_FETCH_ADC,
|
||||
};
|
||||
|
||||
ErrorCode rc = uart_send_packet_nonblocking(&pk, sizeof(pk));
|
||||
if (rc) {
|
||||
st_proto.error = rc;
|
||||
st_proto.last_error = sys_time_us;
|
||||
proto_handle(true);
|
||||
}
|
||||
return uart_send_packet_nonblocking(&pk, sizeof(pk));
|
||||
}
|
||||
|
||||
void proto_update_lcd_strings(void) {
|
||||
|
|
@ -119,7 +188,7 @@ void proto_update_lcd_strings(void) {
|
|||
}
|
||||
}
|
||||
|
||||
void tx_update_display() {
|
||||
ErrorCode tx_update_display() {
|
||||
struct pkt_update_display pk = {
|
||||
.ll_pkt = {
|
||||
.src = uart_st.addr,
|
||||
|
|
@ -148,11 +217,6 @@ void tx_update_display() {
|
|||
memcpy(pk.lcd[0], st_proto.status_msg, strlen(st_proto.status_msg));
|
||||
}
|
||||
|
||||
ErrorCode rc = uart_send_packet_nonblocking(&pk, sizeof(pk));
|
||||
if (rc) {
|
||||
st_proto.error = rc;
|
||||
st_proto.last_error = sys_time_us;
|
||||
proto_handle(true);
|
||||
}
|
||||
return uart_send_packet_nonblocking(&pk, sizeof(pk));
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue