Split receiver into logical parts
This commit is contained in:
parent
c6547c6e6f
commit
43f64f0e1f
8 changed files with 172 additions and 148 deletions
|
|
@ -109,7 +109,7 @@ unsigned char random() {
|
|||
txpos = -1;
|
||||
|
||||
i++;
|
||||
if (i == 2) {
|
||||
if (i == 5) {
|
||||
//txbuf[2] = random();
|
||||
//txbuf[2] <<= 1;
|
||||
//if (!txbuf[2] & 0xff)
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ sources.tar.xz.zip: sources.tar.xz
|
|||
sources.c: sources.tar.xz.zip
|
||||
xxd -i $< | head -n -1 | sed 's/=/__attribute__((section(".source_tarball"))) =/' > $@
|
||||
|
||||
main.elf: main.o startup_stm32f030x6.o system_stm32f0xx.o $(HAL_PATH)/Src/stm32f0xx_ll_utils.o base.o cmsis_exports.o ../common/8b10b.o adc.o
|
||||
main.elf: main.o startup_stm32f030x6.o system_stm32f0xx.o $(HAL_PATH)/Src/stm32f0xx_ll_utils.o base.o cmsis_exports.o ../common/8b10b.o adc.o protocol.o
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)
|
||||
$(OBJCOPY) -O ihex $@ $(@:.elf=.hex)
|
||||
$(OBJCOPY) -O binary $@ $(@:.elf=.bin)
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
144
fw/adc.c
144
fw/adc.c
|
|
@ -31,6 +31,7 @@ static void adc_dma_init(int burstlen, bool enable_interrupt);
|
|||
static void adc_timer_init(int psc, int ivl);
|
||||
|
||||
|
||||
/* Mode that can be used for debugging */
|
||||
void adc_configure_scope_mode(uint8_t channel_mask, int sampling_interval_ns) {
|
||||
/* The constant SAMPLE_FAST (0) when passed in as sampling_interval_ns is handled specially in that we turn the ADC
|
||||
to continuous mode to get the highest possible sampling rate. */
|
||||
|
|
@ -76,7 +77,8 @@ void adc_configure_scope_mode(uint8_t channel_mask, int sampling_interval_ns) {
|
|||
adc_timer_init(12/*250ns/tick*/, cycles);
|
||||
}
|
||||
|
||||
void adc_configure_monitor_mode(int oversampling, int ivl_us, int mean_aggregate_len) {
|
||||
/* Regular operation receiver mode */
|
||||
void adc_configure_monitor_mode(struct command_if_def *cmd_if, int ivl_us) {
|
||||
/* First, disable trigger timer, DMA and ADC in case we're reconfiguring on the fly. */
|
||||
TIM1->CR1 &= ~TIM_CR1_CEN;
|
||||
ADC1->CR &= ~ADC_CR_ADSTART;
|
||||
|
|
@ -85,25 +87,21 @@ void adc_configure_monitor_mode(int oversampling, int ivl_us, int mean_aggregate
|
|||
/* keep track of current mode in global variable */
|
||||
st.adc_mode = ADC_MONITOR;
|
||||
|
||||
//st.adc_oversampling = oversampling;
|
||||
//st.ovs_count = 0;
|
||||
for (int i=0; i<NCH; i++)
|
||||
st.adc_aggregate[i] = 0;
|
||||
st.mean_aggregator[0] = st.mean_aggregator[1] = st.mean_aggregator[2] = 0;
|
||||
st.mean_aggregate_ctr = 0;
|
||||
|
||||
st.detector.hysteresis_mv = 6000;
|
||||
st.detector.debounce_cycles = 0;
|
||||
st.detector.base_interval_cycles = 10;
|
||||
st.det_st.hysteresis_mv = 6000;
|
||||
st.det_st.base_interval_cycles = 10;
|
||||
|
||||
st.detector.sync = 0;
|
||||
st.receiver.rxpos = -1;
|
||||
st.receiver.address = 5; /* FIXME debug code */
|
||||
st.receiver.global_brightness = 0xff;
|
||||
st.detector.bit = 0;
|
||||
st.detector.committed_len_ctr = st.detector.len_ctr = 0;
|
||||
st.detector.debounce_ctr = 0;
|
||||
xfr_8b10b_reset((struct state_8b10b_dec *)&st.detector.rx8b10b);
|
||||
st.det_st.sync = 0;
|
||||
st.det_st.rx_st.rxpos = -1;
|
||||
st.det_st.rx_st.address = 5; /* FIXME debug code */
|
||||
st.det_st.last_bit = 0;
|
||||
st.det_st.committed_len_ctr = st.det_st.len_ctr = 0;
|
||||
st.det_st.rx_st.cmd_if = cmd_if;
|
||||
xfr_8b10b_reset((struct state_8b10b_dec *)&st.det_st.rx8b10b);
|
||||
|
||||
adc_dma_init(NCH, true);
|
||||
|
||||
|
|
@ -172,84 +170,23 @@ static void adc_timer_init(int psc, int ivl) {
|
|||
static void gdb_dump(void) {
|
||||
}
|
||||
|
||||
int payload_len[PKT_TYPE_MAX] = {
|
||||
[PKT_TYPE_RESERVED] = 0,
|
||||
[PKT_TYPE_SET_OUTPUTS_BINARY] = 1,
|
||||
[PKT_TYPE_SET_GLOBAL_BRIGHTNESS] = 1,
|
||||
[PKT_TYPE_SET_OUTPUTS] = 8 };
|
||||
|
||||
void handle_command(int command, uint8_t *args) {
|
||||
switch (command) {
|
||||
case PKT_TYPE_SET_OUTPUTS_BINARY:
|
||||
set_outputs_binary(args[0], st.receiver.global_brightness);
|
||||
break;
|
||||
|
||||
case PKT_TYPE_SET_GLOBAL_BRIGHTNESS:
|
||||
st.receiver.global_brightness = args[0];
|
||||
break;
|
||||
|
||||
case PKT_TYPE_SET_OUTPUTS:
|
||||
set_outputs(args);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void receive_symbol(int symbol) {
|
||||
if (symbol == -K28_1) { /* Comma/frame delimiter */
|
||||
st.receiver.rxpos = 0;
|
||||
/* Fall through and return and just ignore incomplete packets */
|
||||
|
||||
} else if (symbol == -DECODING_ERROR) {
|
||||
st.receiver.rxpos = -1;
|
||||
|
||||
} else if (symbol < 0) { /* Unknown comma symbol or error */
|
||||
st.receiver.rxpos = -1;
|
||||
|
||||
} else if (st.receiver.rxpos == -1) {
|
||||
return;
|
||||
|
||||
} else if (st.receiver.rxpos == 0) { /* First data symbol, and not an error or comma symbol */
|
||||
st.receiver.packet_type = symbol & ~PKT_TYPE_BULK_FLAG;
|
||||
if (st.receiver.packet_type >= PKT_TYPE_MAX) {
|
||||
st.receiver.rxpos = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
st.receiver.is_bulk = symbol & PKT_TYPE_BULK_FLAG;
|
||||
st.receiver.offset = (st.receiver.is_bulk) ? st.receiver.address*payload_len[st.receiver.packet_type]+1 : 2;
|
||||
st.receiver.rxpos++;
|
||||
|
||||
} else if (!st.receiver.is_bulk && st.receiver.rxpos == 1) {
|
||||
st.receiver.rxpos = (symbol == st.receiver.address) ? 2 : -1;
|
||||
|
||||
} else {
|
||||
st.receiver.argbuf[st.receiver.rxpos - st.receiver.offset] = symbol;
|
||||
st.receiver.rxpos++;
|
||||
|
||||
if (st.receiver.rxpos - st.receiver.offset == payload_len[st.receiver.packet_type]) {
|
||||
handle_command(st.receiver.packet_type, (uint8_t *)st.receiver.argbuf);
|
||||
st.receiver.rxpos = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void receive_bit(int bit) {
|
||||
int symbol = xfr_8b10b_feed_bit((struct state_8b10b_dec *)&st.detector.rx8b10b, bit);
|
||||
void receive_bit(struct bit_detector_st *st, int bit) {
|
||||
int symbol = xfr_8b10b_feed_bit((struct state_8b10b_dec *)&st->rx8b10b, bit);
|
||||
if (symbol == -K28_1)
|
||||
st.detector.sync = 1;
|
||||
st->sync = 1;
|
||||
|
||||
if (symbol == -DECODING_IN_PROGRESS)
|
||||
return;
|
||||
|
||||
if (symbol == -DECODING_ERROR)
|
||||
st.detector.sync = 0;
|
||||
st->sync = 0;
|
||||
/* Fall through so we also pass the error to receive_symbol */
|
||||
|
||||
receive_symbol(symbol);
|
||||
receive_symbol(&st->rx_st, symbol);
|
||||
|
||||
/* Debug scope logic */
|
||||
static int debug_buf_pos = 0;
|
||||
if (st.detector.sync && symbol != -DECODING_IN_PROGRESS) {
|
||||
if (st->sync) {
|
||||
if (debug_buf_pos < NCH) {
|
||||
debug_buf_pos = NCH;
|
||||
} else {
|
||||
|
|
@ -257,7 +194,7 @@ void receive_bit(int bit) {
|
|||
|
||||
if (debug_buf_pos >= sizeof(adc_buf)/sizeof(adc_buf[0])) {
|
||||
debug_buf_pos = 0;
|
||||
st.detector.sync = 0;
|
||||
st->sync = 0;
|
||||
gdb_dump();
|
||||
for (int i=0; i<sizeof(adc_buf)/sizeof(adc_buf[0]); i++)
|
||||
adc_buf[i] = -255;
|
||||
|
|
@ -266,7 +203,28 @@ void receive_bit(int bit) {
|
|||
}
|
||||
}
|
||||
|
||||
void bit_detector(struct bit_detector_st *st, int a) {
|
||||
int new_bit = st->last_bit;
|
||||
int diff = a-5500;
|
||||
if (diff < - st->hysteresis_mv/2)
|
||||
new_bit = 0;
|
||||
else if (diff > st->hysteresis_mv/2)
|
||||
new_bit = 1;
|
||||
|
||||
st->len_ctr++;
|
||||
if (new_bit != st->last_bit) {
|
||||
st->last_bit = new_bit;
|
||||
st->len_ctr = 0;
|
||||
st->committed_len_ctr = st->base_interval_cycles>>1;
|
||||
|
||||
} else if (st->len_ctr >= st->committed_len_ctr) {
|
||||
st->committed_len_ctr += st->base_interval_cycles;
|
||||
receive_bit(&st->rx_st, st->last_bit);
|
||||
}
|
||||
}
|
||||
|
||||
void DMA1_Channel1_IRQHandler(void) {
|
||||
/* ISR timing measurement for debugging */
|
||||
int start = SysTick->VAL;
|
||||
|
||||
/* Clear the interrupt flag */
|
||||
|
|
@ -293,31 +251,13 @@ void DMA1_Channel1_IRQHandler(void) {
|
|||
const long vmeas_r_total = VMEAS_R_HIGH + VMEAS_R_LOW;
|
||||
//int a = adc_data.adc_vmeas_a_mv = (st.adc_aggregate[VMEAS_A]*(vmeas_r_total * vcc / VMEAS_R_LOW)) >> 12;
|
||||
int a = adc_data.adc_vmeas_a_mv = (adc_buf[VMEAS_A]*13300) >> 12;
|
||||
|
||||
int new_bit = st.detector.bit;
|
||||
int diff = a-5500;
|
||||
if (diff < - st.detector.hysteresis_mv/2)
|
||||
new_bit = 0;
|
||||
else if (diff > st.detector.hysteresis_mv/2)
|
||||
new_bit = 1;
|
||||
|
||||
if (new_bit != st.detector.bit) {
|
||||
st.detector.bit = new_bit;
|
||||
st.detector.len_ctr = 0;
|
||||
st.detector.committed_len_ctr = st.detector.base_interval_cycles>>1;
|
||||
|
||||
} else if (st.detector.len_ctr >= st.detector.committed_len_ctr) {
|
||||
st.detector.committed_len_ctr += st.detector.base_interval_cycles;
|
||||
receive_bit(st.detector.bit);
|
||||
}
|
||||
|
||||
st.detector.len_ctr++;
|
||||
bit_detector(&st.det_st, a);
|
||||
|
||||
/* ISR timing measurement for debugging */
|
||||
int end = SysTick->VAL;
|
||||
int tdiff = start - end;
|
||||
if (tdiff < 0)
|
||||
tdiff += SysTick->LOAD;
|
||||
st.detector.dma_isr_duration = tdiff;
|
||||
st.dma_isr_duration = tdiff;
|
||||
}
|
||||
|
||||
|
|
|
|||
52
fw/adc.h
52
fw/adc.h
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include "global.h"
|
||||
#include "8b10b.h"
|
||||
#include "protocol.h"
|
||||
|
||||
struct adc_measurements {
|
||||
int16_t adc_vcc_mv;
|
||||
|
|
@ -56,44 +57,23 @@ enum adc_channels {
|
|||
NCH
|
||||
};
|
||||
|
||||
enum packet_type {
|
||||
PKT_TYPE_RESERVED = 0,
|
||||
PKT_TYPE_SET_OUTPUTS_BINARY = 1,
|
||||
PKT_TYPE_SET_GLOBAL_BRIGHTNESS = 2,
|
||||
PKT_TYPE_SET_OUTPUTS = 3,
|
||||
PKT_TYPE_MAX,
|
||||
PKT_TYPE_BULK_FLAG = 0x80
|
||||
struct bit_detector_st {
|
||||
int hysteresis_mv;
|
||||
int sync;
|
||||
int base_interval_cycles;
|
||||
struct proto_rx_st rx_st;
|
||||
/* private stuff */
|
||||
int last_bit;
|
||||
int len_ctr;
|
||||
int committed_len_ctr;
|
||||
struct state_8b10b_dec rx8b10b;
|
||||
};
|
||||
|
||||
struct adc_state {
|
||||
enum adc_mode adc_mode;
|
||||
int adc_oversampling;
|
||||
int mean_aggregate_len;
|
||||
struct {
|
||||
int hysteresis_mv;
|
||||
int debounce_cycles;
|
||||
int sync;
|
||||
int base_interval_cycles;
|
||||
/* private stuff */
|
||||
int bit;
|
||||
int len_ctr;
|
||||
int committed_len_ctr;
|
||||
int debounce_ctr;
|
||||
struct state_8b10b_dec rx8b10b;
|
||||
int dma_isr_duration;
|
||||
} detector;
|
||||
struct {
|
||||
int packet_type;
|
||||
int is_bulk;
|
||||
int rxpos;
|
||||
int global_brightness;
|
||||
int address;
|
||||
uint8_t argbuf[8];
|
||||
int offset;
|
||||
} receiver;
|
||||
|
||||
int dma_isr_duration;
|
||||
struct bit_detector_st det_st;
|
||||
/* private stuff */
|
||||
int ovs_count; /* oversampling accumulator sample count */
|
||||
uint32_t adc_aggregate[NCH]; /* oversampling accumulator */
|
||||
uint32_t mean_aggregate_ctr;
|
||||
uint32_t mean_aggregator[3];
|
||||
|
|
@ -105,9 +85,9 @@ extern volatile struct adc_measurements adc_data;
|
|||
|
||||
void adc_init(void);
|
||||
void adc_configure_scope_mode(uint8_t channel_mask, int sampling_interval_ns);
|
||||
void adc_configure_monitor_mode(int oversampling, int ivl_us, int mean_aggregate_len);
|
||||
void adc_configure_monitor_mode(struct command_if_def *cmd_if, int ivl_us);
|
||||
|
||||
void set_outputs(uint8_t val[8]);
|
||||
void set_outputs_binary(int mask, int global_brightness);
|
||||
void bit_detector(struct bit_detector_st *st, int a);
|
||||
void receive_bit(struct bit_detector_st *st, int bit);
|
||||
|
||||
#endif/*__ADC_H__*/
|
||||
|
|
|
|||
45
fw/main.c
45
fw/main.c
|
|
@ -26,6 +26,24 @@ void TIM1_BRK_UP_TRG_COM_Handler() {
|
|||
TIM1->SR &= ~TIM_SR_UIF_Msk;
|
||||
}
|
||||
|
||||
enum packet_type {
|
||||
PKT_TYPE_RESERVED = 0,
|
||||
PKT_TYPE_SET_OUTPUTS_BINARY = 1,
|
||||
PKT_TYPE_SET_GLOBAL_BRIGHTNESS = 2,
|
||||
PKT_TYPE_SET_OUTPUTS = 3,
|
||||
PKT_TYPE_MAX
|
||||
};
|
||||
|
||||
struct {
|
||||
struct command_if_def cmd_if;
|
||||
int payload_len[PKT_TYPE_MAX];
|
||||
} cmd_if = {{PKT_TYPE_MAX}, {
|
||||
[PKT_TYPE_RESERVED] = 0,
|
||||
[PKT_TYPE_SET_OUTPUTS_BINARY] = 1,
|
||||
[PKT_TYPE_SET_GLOBAL_BRIGHTNESS] = 1,
|
||||
[PKT_TYPE_SET_OUTPUTS] = 8 }
|
||||
};
|
||||
|
||||
uint8_t out_state = 0x01;
|
||||
void set_outputs(uint8_t val[8]) {
|
||||
/* TODO implement BCM for digital brightness control */
|
||||
|
|
@ -43,6 +61,23 @@ void set_outputs_binary(int mask, int global_brightness) {
|
|||
set_outputs(val);
|
||||
}
|
||||
|
||||
void handle_command(int command, uint8_t *args) {
|
||||
static int global_brightness = 0xff;
|
||||
switch (command) {
|
||||
case PKT_TYPE_SET_OUTPUTS_BINARY:
|
||||
set_outputs_binary(args[0], global_brightness);
|
||||
break;
|
||||
|
||||
case PKT_TYPE_SET_GLOBAL_BRIGHTNESS:
|
||||
global_brightness = args[0];
|
||||
break;
|
||||
|
||||
case PKT_TYPE_SET_OUTPUTS:
|
||||
set_outputs(args);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
RCC->CR |= RCC_CR_HSEON;
|
||||
while (!(RCC->CR&RCC_CR_HSERDY));
|
||||
|
|
@ -60,8 +95,8 @@ int main(void) {
|
|||
RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
|
||||
|
||||
GPIOA->MODER |=
|
||||
(3<<GPIO_MODER_MODER0_Pos) /* PA0 - Vmeas_A to ADC */
|
||||
| (3<<GPIO_MODER_MODER1_Pos) /* PA1 - Vmeas_B to ADC */
|
||||
(0<<GPIO_MODER_MODER0_Pos) /* PA0 - Vmeas_A to ADC */
|
||||
| (0<<GPIO_MODER_MODER1_Pos) /* PA1 - Vmeas_B to ADC */
|
||||
| (1<<GPIO_MODER_MODER2_Pos) /* PA2 - LOAD */
|
||||
| (1<<GPIO_MODER_MODER3_Pos) /* PA3 - CH0 */
|
||||
| (1<<GPIO_MODER_MODER4_Pos) /* PA4 - CH3 */
|
||||
|
|
@ -86,9 +121,7 @@ int main(void) {
|
|||
}
|
||||
set_drv_gpios(0);
|
||||
|
||||
adc_configure_monitor_mode(0 /*no oversampling*/, 50 /*us*/, 10000/20 /*mean window size*/);
|
||||
/* FIXME DEBUG */
|
||||
//adc_configure_scope_mode(MASK_VMEAS_A, 50000);
|
||||
adc_configure_monitor_mode(&cmd_if.cmd_if, 50 /*us*/);
|
||||
|
||||
int debounce_ctr = 0;
|
||||
int val_last = 0;
|
||||
|
|
@ -99,7 +132,7 @@ int main(void) {
|
|||
else
|
||||
set_drv_gpios(0);
|
||||
|
||||
int val = adc_state.detector.bit;
|
||||
int val = adc_state.det_st.last_bit;
|
||||
if (val != val_last) {
|
||||
if (val)
|
||||
set_drv_gpios(out_state & 0xf);
|
||||
|
|
|
|||
43
fw/protocol.c
Normal file
43
fw/protocol.c
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
|
||||
#include "protocol.h"
|
||||
#include "8b10b.h"
|
||||
|
||||
void receive_symbol(struct proto_rx_st *st, int symbol) {
|
||||
if (symbol == -K28_1) { /* Comma/frame delimiter */
|
||||
st->rxpos = 0;
|
||||
/* Fall through and return and just ignore incomplete packets */
|
||||
|
||||
} else if (symbol == -DECODING_ERROR) {
|
||||
st->rxpos = -1;
|
||||
|
||||
} else if (symbol < 0) { /* Unknown comma symbol or error */
|
||||
st->rxpos = -1;
|
||||
|
||||
} else if (st->rxpos == -1) {
|
||||
return;
|
||||
|
||||
} else if (st->rxpos == 0) { /* First data symbol, and not an error or comma symbol */
|
||||
st->packet_type = symbol & ~PKT_TYPE_BULK_FLAG;
|
||||
if (st->packet_type >= st->cmd_if->packet_type_max) {
|
||||
st->rxpos = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
st->is_bulk = symbol & PKT_TYPE_BULK_FLAG;
|
||||
st->offset = (st->is_bulk) ? st->address*st->cmd_if->payload_len[st->packet_type]+1 : 2;
|
||||
st->rxpos++;
|
||||
|
||||
} else if (!st->is_bulk && st->rxpos == 1) {
|
||||
st->rxpos = (symbol == st->address) ? 2 : -1;
|
||||
|
||||
} else {
|
||||
st->argbuf[st->rxpos - st->offset] = symbol;
|
||||
st->rxpos++;
|
||||
|
||||
if (st->rxpos - st->offset == st->cmd_if->payload_len[st->packet_type]) {
|
||||
handle_command(st->packet_type, (uint8_t *)st->argbuf);
|
||||
st->rxpos = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
28
fw/protocol.h
Normal file
28
fw/protocol.h
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
#ifndef __PROTOCOL_H__
|
||||
#define __PROTOCOL_H__
|
||||
|
||||
#include "global.h"
|
||||
|
||||
#define PKT_TYPE_BULK_FLAG 0x80
|
||||
|
||||
struct proto_rx_st {
|
||||
int packet_type;
|
||||
int is_bulk;
|
||||
int rxpos;
|
||||
int address;
|
||||
uint8_t argbuf[8];
|
||||
int offset;
|
||||
struct command_if_def *cmd_if;
|
||||
};
|
||||
|
||||
struct command_if_def {
|
||||
int packet_type_max;
|
||||
int payload_len[0];
|
||||
};
|
||||
|
||||
/* Callback */
|
||||
void handle_command(int command, uint8_t *args);
|
||||
|
||||
void receive_symbol(struct proto_rx_st *st, int symbol);
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue