decoder seems to be working, but encoder looks a bit borked.
This commit is contained in:
parent
85e6e19af9
commit
ee1d1bd0c2
3 changed files with 326 additions and 148 deletions
File diff suppressed because one or more lines are too long
|
|
@ -16,10 +16,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
|
#include "8b10b.h"
|
||||||
|
|
||||||
uint16_t adc_data[192*2];
|
static uint16_t adc_data[64*2];
|
||||||
|
static volatile struct state_8b10b_dec st_8b10b_dec;
|
||||||
const int nominal_period = 125*16*32/2;
|
|
||||||
|
|
||||||
static void quicksort(uint16_t *head, uint16_t *tail);
|
static void quicksort(uint16_t *head, uint16_t *tail);
|
||||||
|
|
||||||
|
|
@ -64,11 +64,13 @@ int main(void) {
|
||||||
NVIC_SetPriority(TIM1_CC_IRQn, 0);
|
NVIC_SetPriority(TIM1_CC_IRQn, 0);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
xfr_8b10b_reset((struct state_8b10b_dec *)&st_8b10b_dec);
|
||||||
|
|
||||||
TIM3->CR1 = TIM_CR1_ARPE;
|
TIM3->CR1 = TIM_CR1_ARPE;
|
||||||
TIM3->CR2 = (2<<TIM_CR2_MMS_Pos); /* Update event on TRGO */
|
TIM3->CR2 = (2<<TIM_CR2_MMS_Pos); /* Update event on TRGO */
|
||||||
TIM3->PSC = 0;
|
TIM3->PSC = 0;
|
||||||
/* We sample 32 times per 1 kHz AC cycle, and use 32 times oversampling. */
|
/* We sample 32 times per 1 kHz AC cycle, and use 32 times oversampling. */
|
||||||
TIM3->ARR = 125*32; /* Output 64 MHz / 125 = 512 kHz signal */
|
TIM3->ARR = 125*16; /* Output 64 MHz / 125 = 512 kHz signal */
|
||||||
TIM3->CR1 |= TIM_CR1_CEN;
|
TIM3->CR1 |= TIM_CR1_CEN;
|
||||||
|
|
||||||
DMAMUX1[0].CCR = 5; /* ADC */
|
DMAMUX1[0].CCR = 5; /* ADC */
|
||||||
|
|
@ -121,131 +123,58 @@ void TIM1_CC_IRQHandler(void) {
|
||||||
TIM1->SR &= ~TIM_SR_CC1IF;
|
TIM1->SR &= ~TIM_SR_CC1IF;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
static size_t received_symbols = 0;
|
||||||
|
static int symbol_buf[32];
|
||||||
|
static size_t received_bits = 0;
|
||||||
|
static int16_t bit_buf[256];
|
||||||
|
size_t adc_reduced_pos = 0;
|
||||||
|
static uint8_t adc_reduced[4096];
|
||||||
|
|
||||||
void DMA1_Channel1_IRQHandler(void) {
|
void DMA1_Channel1_IRQHandler(void) {
|
||||||
static int32_t bottom = -1;
|
static int sampling_phase = 0;
|
||||||
static int32_t top = -1;
|
static int last_sample = 0;
|
||||||
|
|
||||||
|
uint16_t *buf = (DMA1->ISR & DMA_ISR_HTIF1) ? &adc_data[0] : &adc_data[COUNT_OF(adc_data)/2];
|
||||||
DMA1->IFCR = DMA_IFCR_CGIF1;
|
DMA1->IFCR = DMA_IFCR_CGIF1;
|
||||||
int phase_correction = 0;
|
|
||||||
GPIOB->BSRR = (1<<7);
|
GPIOB->BSRR = (1<<7);
|
||||||
uint16_t *data = DMA1->ISR & DMA_ISR_HTIF1 ? &adc_data[0] : &adc_data[192];
|
|
||||||
|
|
||||||
if (bottom >= 0) {
|
const int threshold_adc_counts = 28500;
|
||||||
uint32_t amplitude = top - bottom;
|
const int sample_per_baud = 16;
|
||||||
uint32_t middle = bottom + amplitude / 2;
|
|
||||||
|
|
||||||
const uint32_t lower_thr = bottom + amplitude / 4;
|
for (size_t i=0; i<COUNT_OF(adc_data)/2; i++) {
|
||||||
const uint32_t upper_thr = top - amplitude / 4;
|
int sample = buf[i];
|
||||||
const uint32_t adc_clockdiv = 125 * 32;
|
|
||||||
|
|
||||||
int num_edges = 0;
|
adc_reduced[adc_reduced_pos] = (sample & 0xffff)>>9;
|
||||||
int edge_indices[24];
|
if (adc_reduced_pos == 0) {
|
||||||
|
asm volatile ("bkpt");
|
||||||
int state = 0;
|
|
||||||
ssize_t run_start = -1;
|
|
||||||
int last_v = -1;
|
|
||||||
for (ssize_t i=0; i<192-1; i++) {
|
|
||||||
uint32_t a = data[i], b = data[i+1];
|
|
||||||
|
|
||||||
if (state == 0) {
|
|
||||||
if (a < lower_thr && b > lower_thr) {
|
|
||||||
state = 1;
|
|
||||||
run_start = i+1;
|
|
||||||
} else if (a > upper_thr && b < upper_thr) {
|
|
||||||
state = -1;
|
|
||||||
run_start = i+1;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (state == 1) {
|
|
||||||
if (b < a) {
|
|
||||||
state = 0;
|
|
||||||
} else if (a < upper_thr && b > upper_thr) {
|
|
||||||
/* run from run_start (incl.) to i (incl.) */
|
|
||||||
uint32_t v0 = data[run_start];
|
|
||||||
int d = a - v0;
|
|
||||||
int c = i - run_start;
|
|
||||||
size_t intercept = run_start * adc_clockdiv + (middle - v0) * adc_clockdiv * c / d;
|
|
||||||
if (num_edges < COUNT_OF(edge_indices)) {
|
|
||||||
edge_indices[num_edges] = intercept;
|
|
||||||
num_edges++;
|
|
||||||
}
|
|
||||||
state = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (state == -1) {
|
|
||||||
if (b > a) {
|
|
||||||
state = 0;
|
|
||||||
} else if (a > lower_thr && b < lower_thr) {
|
|
||||||
uint32_t v0 = data[run_start];
|
|
||||||
int d = a - v0;
|
|
||||||
int c = i - run_start;
|
|
||||||
size_t intercept = run_start * adc_clockdiv + (middle - v0) * adc_clockdiv * c / d;
|
|
||||||
if (num_edges < COUNT_OF(edge_indices)) {
|
|
||||||
edge_indices[num_edges] = intercept;
|
|
||||||
num_edges++;
|
|
||||||
}
|
|
||||||
state = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (num_edges > 1) {
|
if ((last_sample <= threshold_adc_counts && sample >= threshold_adc_counts) ||
|
||||||
const int approx_cycle = 32*16*125/2;
|
(last_sample >= threshold_adc_counts && sample <= threshold_adc_counts)){
|
||||||
int delta_avg = 0;
|
sampling_phase = sample_per_baud / 4; /* /2 for half baud sampling point, /2 for sinusoidal edge shape */
|
||||||
for (size_t i=0; i<num_edges-1; i++) {
|
|
||||||
int delta = edge_indices[i+1] - edge_indices[i];
|
|
||||||
if (delta > approx_cycle/2 * 50) {
|
|
||||||
asm volatile ("bkpt");
|
|
||||||
}
|
|
||||||
while (delta > approx_cycle/2) {
|
|
||||||
delta -= approx_cycle;
|
|
||||||
}
|
|
||||||
delta_avg += delta;
|
|
||||||
}
|
|
||||||
delta_avg /= num_edges-1;
|
|
||||||
|
|
||||||
int cycle = approx_cycle + delta_avg;
|
} else if (sampling_phase == 0) {
|
||||||
int offset = 0;
|
int bit = sample < threshold_adc_counts;
|
||||||
int phase_avg = 0;
|
adc_reduced[adc_reduced_pos] |= 0x80;
|
||||||
for (size_t i=0; i<num_edges; i++) {
|
|
||||||
int remainder = edge_indices[i] - offset;
|
|
||||||
while (remainder > cycle/2) {
|
|
||||||
remainder -= cycle;
|
|
||||||
offset += cycle;
|
|
||||||
}
|
|
||||||
phase_avg += remainder;
|
|
||||||
}
|
|
||||||
phase_avg /= num_edges;
|
|
||||||
phase_correction = phase_avg >= 0 ? cycle/2 - phase_avg : cycle/2 + phase_avg;
|
|
||||||
phase_correction /= 125 * 4;
|
|
||||||
|
|
||||||
const int deadzone = 3;
|
bit_buf[received_bits] = bit;
|
||||||
const int max_correction = 40;
|
received_bits = (received_bits+1) % COUNT_OF(bit_buf);
|
||||||
if (phase_correction < -deadzone || phase_correction > deadzone) {
|
|
||||||
if (phase_correction < -max_correction) {
|
int rc = xfr_8b10b_feed_bit((struct state_8b10b_dec *)&st_8b10b_dec, bit);
|
||||||
phase_correction = -max_correction;
|
if (rc > -K_CODES_LAST) {
|
||||||
} else if (phase_correction > max_correction) {
|
symbol_buf[received_symbols] = rc;
|
||||||
phase_correction = max_correction;
|
received_symbols = (received_symbols+1) % COUNT_OF(symbol_buf);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
sampling_phase = sample_per_baud;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
sampling_phase--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
adc_reduced_pos = (adc_reduced_pos+1) % COUNT_OF(adc_reduced);
|
||||||
|
last_sample = sample;
|
||||||
}
|
}
|
||||||
|
|
||||||
const int discard = 5;
|
|
||||||
const int keep = 32;
|
|
||||||
|
|
||||||
bottom = 0;
|
|
||||||
top = 0;
|
|
||||||
quicksort(data, &data[192-1]);
|
|
||||||
for (size_t i=0; i<keep; i++) {
|
|
||||||
bottom += data[discard + i];
|
|
||||||
top += data[COUNT_OF(data)/2 - 1 - discard - i];
|
|
||||||
}
|
|
||||||
|
|
||||||
bottom /= keep;
|
|
||||||
top /= keep;
|
|
||||||
|
|
||||||
TIM3->ARR = 125*32 + phase_correction;
|
|
||||||
GPIOB->BRR = (1<<7);
|
GPIOB->BRR = (1<<7);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ static int tx_datagram[33] = {
|
||||||
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
|
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
|
||||||
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa};
|
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa};
|
||||||
*/
|
*/
|
||||||
-K28_0,
|
-K28_1,
|
||||||
0x00, 0xff, 0xAA, 0x55, 0xfe, 0x18, 0xcc, 0x10,
|
0x00, 0xff, 0xAA, 0x55, 0xfe, 0x18, 0xcc, 0x10,
|
||||||
0x00, 0xff, 0xAA, 0x55, 0xfe, 0x18, 0xcc, 0x10,
|
0x00, 0xff, 0xAA, 0x55, 0xfe, 0x18, 0xcc, 0x10,
|
||||||
0x00, 0xff, 0xAA, 0x55, 0xfe, 0x18, 0xcc, 0x10,
|
0x00, 0xff, 0xAA, 0x55, 0xfe, 0x18, 0xcc, 0x10,
|
||||||
|
|
@ -195,8 +195,8 @@ void dma_tx_constant(size_t table_size, uint16_t constant) {
|
||||||
tx_constant[0] = constant;
|
tx_constant[0] = constant;
|
||||||
tx_constant[1] = constant;
|
tx_constant[1] = constant;
|
||||||
|
|
||||||
abhängig von $n$ DMA1_Channel1->CCR = 0; DMA1_Channel1->CCR = (1<<DMA_CCR_MSIZE_Pos) | (1<<DMA_CCR_PSIZE_Pos) |
|
DMA1_Channel1->CCR = 0;
|
||||||
DMA_CCR_DIR | DMA_CCR_TCIE;
|
DMA1_Channel1->CCR = (1<<DMA_CCR_MSIZE_Pos) | (1<<DMA_CCR_PSIZE_Pos) | DMA_CCR_DIR | DMA_CCR_TCIE;
|
||||||
DMA1_Channel1->CNDTR = table_size;
|
DMA1_Channel1->CNDTR = table_size;
|
||||||
DMA1_Channel1->CMAR = (uint32_t)&tx_constant;
|
DMA1_Channel1->CMAR = (uint32_t)&tx_constant;
|
||||||
DMA1_Channel1->CCR |= DMA_CCR_EN;
|
DMA1_Channel1->CCR |= DMA_CCR_EN;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue