Split receiver into logical parts

This commit is contained in:
jaseg 2019-01-12 12:31:59 +09:00
parent c6547c6e6f
commit 43f64f0e1f
8 changed files with 172 additions and 148 deletions

View file

@ -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)

View file

@ -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
View file

@ -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;
}

View file

@ -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__*/

View file

@ -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
View 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
View 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