fw: add working reed-solomon encoder/decoder
This commit is contained in:
parent
82c1302756
commit
9918eb5053
15 changed files with 253 additions and 462 deletions
3
.gitmodules
vendored
3
.gitmodules
vendored
|
|
@ -22,3 +22,6 @@
|
|||
[submodule "controller/fw/tinyprintf"]
|
||||
path = controller/fw/tinyprintf
|
||||
url = https://github.com/cjlano/tinyprintf
|
||||
[submodule "controller/fw/reed_solomon"]
|
||||
path = controller/fw/reed_solomon
|
||||
url = git@git.jaseg.net:bigdata/pub/reed_solomon_c.git
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ MSPDEBUG_DIR ?= mspdebug
|
|||
LIBSODIUM_DIR ?= libsodium
|
||||
TINYAES_DIR ?= tinyaes
|
||||
MUSL_DIR ?= musl
|
||||
RSLIB_DIR ?= reed_solomon
|
||||
|
||||
########################################################################################################################
|
||||
# Algorithm parameters
|
||||
|
|
@ -56,34 +57,38 @@ C_SOURCES += tinyprintf/tinyprintf.c
|
|||
|
||||
C_SOURCES += $(MSPDEBUG_DIR)/drivers/jtaglib.c
|
||||
|
||||
CMSIS_SOURCES += $(CMSIS_DIR)/CMSIS/DSP/Source/TransformFunctions/arm_rfft_fast_init_f32.c
|
||||
CMSIS_SOURCES += $(CMSIS_DIR)/CMSIS/DSP/Source/TransformFunctions/arm_rfft_fast_f32.c
|
||||
CMSIS_SOURCES += $(CMSIS_DIR)/CMSIS/DSP/Source/TransformFunctions/arm_cfft_init_f32.c
|
||||
CMSIS_SOURCES += $(CMSIS_DIR)/CMSIS/DSP/Source/TransformFunctions/arm_cfft_f32.c
|
||||
CMSIS_SOURCES += $(CMSIS_DIR)/CMSIS/DSP/Source/TransformFunctions/arm_cfft_radix8_f32.c
|
||||
CMSIS_SOURCES += $(CMSIS_DIR)/CMSIS/DSP/Source/CommonTables/arm_const_structs.c
|
||||
CMSIS_SOURCES += $(CMSIS_DIR)/CMSIS/DSP/Source/CommonTables/arm_common_tables.c
|
||||
CMSIS_SOURCES += $(CMSIS_DIR)/CMSIS/DSP/Source/TransformFunctions/arm_bitreversal.c
|
||||
CMSIS_SOURCES += $(CMSIS_DIR)/CMSIS/DSP/Source/TransformFunctions/arm_bitreversal2.c
|
||||
CMSIS_SOURCES += TransformFunctions/arm_rfft_fast_init_f32.c
|
||||
CMSIS_SOURCES += TransformFunctions/arm_rfft_fast_f32.c
|
||||
CMSIS_SOURCES += TransformFunctions/arm_cfft_init_f32.c
|
||||
CMSIS_SOURCES += TransformFunctions/arm_cfft_f32.c
|
||||
CMSIS_SOURCES += TransformFunctions/arm_cfft_radix8_f32.c
|
||||
CMSIS_SOURCES += CommonTables/arm_const_structs.c
|
||||
CMSIS_SOURCES += CommonTables/arm_common_tables.c
|
||||
CMSIS_SOURCES += TransformFunctions/arm_bitreversal.c
|
||||
CMSIS_SOURCES += TransformFunctions/arm_bitreversal2.c
|
||||
CMSIS_SOURCES := $(addprefix $(CMSIS_DIR)/CMSIS/DSP/Source/,$(CMSIS_SOURCES))
|
||||
|
||||
MUSL_SOURCES += $(MUSL_DIR)/src/math/tanhf.c $(MUSL_DIR)/src/math/atanhf.c
|
||||
MUSL_SOURCES += $(MUSL_DIR)/src/math/expm1f.c $(MUSL_DIR)/src/math/log1pf.c
|
||||
MUSL_SOURCES += $(MUSL_DIR)/src/math/expf.c $(MUSL_DIR)/src/math/exp2f_data.c
|
||||
MUSL_SOURCES += $(MUSL_DIR)/src/math/powf.c
|
||||
MUSL_SOURCES += $(MUSL_DIR)/src/math/sqrtf.c
|
||||
MUSL_SOURCES += $(MUSL_DIR)/src/math/fabsf.c
|
||||
MUSL_SOURCES += $(MUSL_DIR)/src/stdlib/abs.c
|
||||
MUSL_SOURCES += $(MUSL_DIR)/src/string/memset.c
|
||||
MUSL_SOURCES += $(MUSL_DIR)/src/string/memcpy.c
|
||||
MUSL_SOURCES += $(MUSL_DIR)/src/math/__math_oflowf.c
|
||||
MUSL_SOURCES += $(MUSL_DIR)/src/math/__math_uflowf.c
|
||||
MUSL_SOURCES += $(MUSL_DIR)/src/math/__math_xflowf.c
|
||||
MUSL_SOURCES += $(MUSL_DIR)/src/math/__math_invalidf.c
|
||||
MUSL_SOURCES += $(MUSL_DIR)/src/math/powf_data.c
|
||||
MUSL_SOURCES += math/tanhf.c math/atanhf.c
|
||||
MUSL_SOURCES += math/expm1f.c math/log1pf.c
|
||||
MUSL_SOURCES += math/expf.c math/exp2f_data.c
|
||||
MUSL_SOURCES += math/powf.c
|
||||
MUSL_SOURCES += math/sqrtf.c
|
||||
MUSL_SOURCES += math/fabsf.c
|
||||
MUSL_SOURCES += stdlib/abs.c
|
||||
MUSL_SOURCES += string/memset.c
|
||||
MUSL_SOURCES += string/memcpy.c
|
||||
MUSL_SOURCES += math/__math_oflowf.c
|
||||
MUSL_SOURCES += math/__math_uflowf.c
|
||||
MUSL_SOURCES += math/__math_xflowf.c
|
||||
MUSL_SOURCES += math/__math_invalidf.c
|
||||
MUSL_SOURCES += math/powf_data.c
|
||||
MUSL_SOURCES := $(addprefix $(MUSL_DIR)/src/,$(MUSL_SOURCES))
|
||||
|
||||
C_SOURCES += $(CMSIS_SOURCES) $(MUSL_SOURCES)
|
||||
RSLIB_SOURCES += $(addprefix $(RSLIB_DIR)/src/,rs.c ecc.c berlekamp.c galois.c)
|
||||
|
||||
CXX_SOURCES += src/ldpc_wrapper.cpp
|
||||
C_SOURCES += $(CMSIS_SOURCES) $(MUSL_SOURCES) $(RSLIB_SOURCES)
|
||||
|
||||
CXX_SOURCES +=
|
||||
|
||||
BUILDDIR ?= build
|
||||
BINARY := safetyreset.elf
|
||||
|
|
@ -299,8 +304,8 @@ $(BUILDDIR)/tinyaes/aes.o:
|
|||
# mkdir -p $(BUILDDIR)/musl
|
||||
# cd $(BUILDDIR)/musl && CFLAGS="$(SIM_CFLAGS) $(COMMON_CFLAGS)" CC=$(CC) LD=$(LD) AR=$(AR) $(MUSL_DIR_ABS)/configure && $(MAKE) TARGET=arm-linux-musleabihf GCC_CONFIG="-mcpu=cortex-m4 -mfloat-abi=soft" -j $(shell nproc)
|
||||
|
||||
build/ldpc_decoder_test.so: src/ldpc_decoder.c
|
||||
gcc -fPIC -shared -Wall -Wextra -Wpedantic -std=gnu11 -O0 -g -o $@ $^
|
||||
build/rslib.so: $(RSLIB_SOURCES) src/rslib.c
|
||||
gcc -fPIC -shared -Wall -Wextra -Wpedantic -std=gnu11 -O0 -g -o $@ -Isrc -I$(RSLIB_DIR)/src $^
|
||||
|
||||
clean:
|
||||
rm -rf $(BUILDDIR)/src
|
||||
|
|
|
|||
1
controller/fw/reed_solomon
Submodule
1
controller/fw/reed_solomon
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 63ff1482d42547422896418d5990a66a80e88d34
|
||||
46
controller/fw/src/gpio_helpers.c
Normal file
46
controller/fw/src/gpio_helpers.c
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
|
||||
#include "gpio_helpers.h"
|
||||
|
||||
void gpio_pin_mode(GPIO_TypeDef *gpio, int pin, int mode) {
|
||||
gpio->MODER &= ~(3 << (2*pin));
|
||||
gpio->MODER |= mode << (2*pin);
|
||||
}
|
||||
|
||||
void gpio_pin_setup(GPIO_TypeDef *gpio, int pin, int mode, int speed, int pullups, int afsel) {
|
||||
int gpio_idx = ((uint32_t)gpio>>10) & 0xf;
|
||||
RCC->AHB1ENR |= 1<<gpio_idx;
|
||||
|
||||
gpio->MODER &= ~(3 << (2*pin));
|
||||
gpio->MODER |= mode << (2*pin);
|
||||
gpio->OSPEEDR &= ~(3 << (2*pin));
|
||||
gpio->OSPEEDR |= speed << (2*pin);
|
||||
gpio->PUPDR &= ~(3 << (2*pin));
|
||||
gpio->PUPDR |= pullups << (2*pin);
|
||||
gpio->AFR[pin>>3] &= ~(0xf << (4*(pin&7)));
|
||||
gpio->AFR[pin>>3] |= afsel << (4*(pin&7));
|
||||
gpio->BSRR = 1<<pin<<16;
|
||||
}
|
||||
|
||||
void gpio_pin_output(GPIO_TypeDef *gpio, int pin, int speed) {
|
||||
gpio_pin_setup(gpio, pin, 1, speed, 0, 0);
|
||||
}
|
||||
|
||||
void gpio_pin_tristate(GPIO_TypeDef *gpio, int pin, int tristate) {
|
||||
if (tristate)
|
||||
gpio->MODER &= ~(3 << (2*pin));
|
||||
else
|
||||
gpio->MODER |= 1 << (2*pin);
|
||||
}
|
||||
|
||||
void gpio_pin_input(GPIO_TypeDef *gpio, int pin, int pullups) {
|
||||
gpio_pin_setup(gpio, pin, 0, 0, pullups, 0);
|
||||
}
|
||||
|
||||
void gpio_pin_af(GPIO_TypeDef *gpio, int pin, int speed, int pullups, int afsel) {
|
||||
gpio_pin_setup(gpio, pin, 2, speed, pullups, afsel);
|
||||
}
|
||||
|
||||
void gpio_pin_analog(GPIO_TypeDef *gpio, int pin) {
|
||||
gpio_pin_setup(gpio, pin, 3, 0, 0, 0);
|
||||
}
|
||||
|
||||
14
controller/fw/src/gpio_helpers.h
Normal file
14
controller/fw/src/gpio_helpers.h
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
#ifndef __GPIO_HELPERS_H__
|
||||
#define __GPIO_HELPERS_H__
|
||||
|
||||
#include <stm32f407xx.h>
|
||||
|
||||
void gpio_pin_mode(GPIO_TypeDef *gpio, int pin, int mode);
|
||||
void gpio_pin_setup(GPIO_TypeDef *gpio, int pin, int mode, int speed, int pullups, int afsel);
|
||||
void gpio_pin_output(GPIO_TypeDef *gpio, int pin, int speed);
|
||||
void gpio_pin_input(GPIO_TypeDef *gpio, int pin, int pullups);
|
||||
void gpio_pin_af(GPIO_TypeDef *gpio, int pin, int speed, int pullups, int afsel);
|
||||
void gpio_pin_analog(GPIO_TypeDef *gpio, int pin);
|
||||
void gpio_pin_tristate(GPIO_TypeDef *gpio, int pin, int tristate);
|
||||
|
||||
#endif /* __GPIO_HELPERS_H__ */
|
||||
|
|
@ -1,267 +0,0 @@
|
|||
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <stdbool.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
void gausselimination(size_t n, size_t k, int8_t *A, int8_t *b);
|
||||
|
||||
void inner_logbp(
|
||||
size_t m, size_t n,
|
||||
size_t bits_count, size_t nodes_count, const uint32_t bits_values[], const uint32_t nodes_values[],
|
||||
int8_t Lc[],
|
||||
float Lq[], float Lr[],
|
||||
unsigned int n_iter,
|
||||
float L_posteriori_out[]);
|
||||
|
||||
//decode(384, 6, 8, ...)
|
||||
int decode(size_t n, size_t nodes_count, size_t bits_count, uint32_t bits[], int8_t y[], int8_t out[], unsigned int maxiter) {
|
||||
const size_t m = n * nodes_count / bits_count;
|
||||
float Lq[m*n];
|
||||
float Lr[m*n];
|
||||
float L_posteriori[n];
|
||||
|
||||
/* Calculate column bit positions from row bit positions */
|
||||
int32_t bits_transposed[nodes_count * n];
|
||||
for (size_t i=0; i<nodes_count * n; i++)
|
||||
bits_transposed[i] = -1;
|
||||
|
||||
for (size_t i=0; i<m; i++) {
|
||||
for (size_t j=0; j<bits_count; j++) {
|
||||
int32_t *base = bits_transposed + bits[i*bits_count + j] * nodes_count;
|
||||
for (; *base != -1; base++)
|
||||
;
|
||||
*base = i;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
printf("Row positions: [");
|
||||
for (size_t i=0; i<m*bits_count; i++) {
|
||||
if (i)
|
||||
printf(", ");
|
||||
if (i%32 == 0)
|
||||
printf("\n ");
|
||||
printf("%4d", bits[i]);
|
||||
}
|
||||
printf("\n]\n");
|
||||
|
||||
printf("Column positions: [");
|
||||
for (size_t i=0; i<n*nodes_count; i++) {
|
||||
if (i)
|
||||
printf(", ");
|
||||
if (i%32 == 0)
|
||||
printf("\n ");
|
||||
printf("%4d", bits_transposed[i]);
|
||||
}
|
||||
printf("\n]\n");
|
||||
*/
|
||||
|
||||
/* Run iterative optimization algorithm */
|
||||
for (unsigned int n_iter=0; n_iter<maxiter; n_iter++) {
|
||||
inner_logbp(m, n, bits_count, nodes_count, bits, (uint32_t*)bits_transposed, y, Lq, Lr, n_iter, L_posteriori);
|
||||
|
||||
/*
|
||||
float *arrs[3] = {Lq, Lr, L_posteriori};
|
||||
const char *names[3] = {"Lq", "Lr", "L_posteriori"};
|
||||
size_t lens[3] = {m*n, m*n, n};
|
||||
const size_t head_tail = 10;
|
||||
for (int j=0; j<3; j++) {
|
||||
printf("%s=[", names[j]);
|
||||
bool ellipsis = false;
|
||||
const int w = 16;
|
||||
for (size_t i=0; i<lens[j]; i++) {
|
||||
if (lens[j] > 1000 && i/w > head_tail && i/w < m*n/w-head_tail) {
|
||||
if (!ellipsis) {
|
||||
ellipsis = true;
|
||||
printf("\n ...");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (i)
|
||||
printf(", ");
|
||||
if (i%w == 0)
|
||||
printf("\n ");
|
||||
float outf = arrs[j][i];
|
||||
char *s = outf < 0 ? "\033[91m" : (outf > 0 ? "\033[92m" : "\033[94m");
|
||||
printf("%s% 012.6g\033[38;5;240m", s, outf);
|
||||
}
|
||||
printf("\n]\n");
|
||||
}
|
||||
*/
|
||||
|
||||
for (size_t i=0; i<n; i++)
|
||||
out[i] = L_posteriori[i] <= 0.0f;
|
||||
|
||||
for (size_t i=0; i<m; i++) {
|
||||
bool sum = 0;
|
||||
for (size_t j=0; j<bits_count; j++)
|
||||
sum ^= out[bits[i*bits_count + j]];
|
||||
if (sum)
|
||||
continue;
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
return n_iter;
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Perform inner ext LogBP solver */
|
||||
void inner_logbp(
|
||||
size_t m, size_t n,
|
||||
size_t bits_count, size_t nodes_count, uint32_t const bits_values[], const uint32_t nodes_values[],
|
||||
int8_t Lc[],
|
||||
float Lq[], float Lr[],
|
||||
unsigned int n_iter,
|
||||
float L_posteriori_out[]) {
|
||||
|
||||
/*
|
||||
printf("Input data: [");
|
||||
for (size_t i=0; i<n; i++) {
|
||||
if (i)
|
||||
printf(", ");
|
||||
if (i%32 == 0)
|
||||
printf("\n ");
|
||||
printf("%4d", Lc[i]);
|
||||
}
|
||||
printf("\n]\n");
|
||||
*/
|
||||
|
||||
/* step 1 : Horizontal */
|
||||
unsigned int bits_counter = 0;
|
||||
for (size_t i=0; i<m; i++) {
|
||||
//printf("=== i=%zu\n", i);
|
||||
for (size_t p=bits_counter; p<bits_counter+bits_count; p++) {
|
||||
size_t j = bits_values[p];
|
||||
//printf("\033[38;5;240mj=%04zd ", j);
|
||||
|
||||
float x = 1;
|
||||
if (n_iter == 0) {
|
||||
for (size_t q=bits_counter; q<bits_counter+bits_count; q++) {
|
||||
if (bits_values[q] != j) {
|
||||
//int lcv = Lc[bits_values[q]];
|
||||
//char *s = lcv < 0 ? "\033[91m" : (lcv > 0 ? "\033[92m" : "\033[94m");
|
||||
//printf("nij=%04u Lc=%s%3d\033[38;5;240m ", bits_values[q], s, lcv);
|
||||
x *= tanhf(0.5f * Lc[bits_values[q]]);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
for (size_t q=bits_counter; q<bits_counter+bits_count; q++) {
|
||||
if (bits_values[q] != j)
|
||||
x *= tanhf(0.5f * Lq[i*n + bits_values[q]]);
|
||||
}
|
||||
}
|
||||
|
||||
//printf("\n==== i=%03zd p=%01zd x=%08f\n", i, p-bits_counter, x);
|
||||
|
||||
float num = 1 + x;
|
||||
float denom = 1 - x;
|
||||
if (num == 0)
|
||||
Lr[i*n + j] = -1.0f;
|
||||
else if (denom == 0)
|
||||
Lr[i*n + j] = 1.0f;
|
||||
else
|
||||
Lr[i*n + j] = logf(num/denom);
|
||||
}
|
||||
|
||||
bits_counter += bits_count;
|
||||
}
|
||||
|
||||
/* step 2 : Vertical */
|
||||
unsigned int nodes_counter = 0;
|
||||
for (size_t j=0; j<n; j++) {
|
||||
for (size_t p=bits_counter; p<nodes_counter+nodes_count; p++) {
|
||||
size_t i = nodes_values[p];
|
||||
|
||||
Lq[i*n + j] = Lc[j];
|
||||
|
||||
for (size_t q=bits_counter; q<nodes_counter+nodes_count; q++) {
|
||||
if (nodes_values[q] != i)
|
||||
Lq[i*n + j] += Lr[nodes_values[q]*n + j];
|
||||
}
|
||||
}
|
||||
|
||||
nodes_counter += nodes_count;
|
||||
}
|
||||
|
||||
/* LLR a posteriori */
|
||||
nodes_counter = 0;
|
||||
for (size_t j=0; j<n; j++) {
|
||||
float sum = 0;
|
||||
for (size_t k=bits_counter; k<nodes_counter+nodes_count; k++)
|
||||
sum += Lr[nodes_values[k]*n + j];
|
||||
nodes_counter += nodes_count;
|
||||
|
||||
L_posteriori_out[j] = Lc[j] + sum;
|
||||
}
|
||||
}
|
||||
|
||||
/* Compute the original (k) bit message from a (n) bit codeword x.
|
||||
*
|
||||
* tG: (n, k)-matrix
|
||||
* x: (n)-vector
|
||||
* out: (k)-vector
|
||||
*/
|
||||
void get_message(size_t n, size_t k, int8_t *tG, int8_t *x, int8_t *out) {
|
||||
|
||||
gausselimination(n, k, tG, x);
|
||||
|
||||
out[k - 1] = x[k - 1];
|
||||
for (ssize_t i=k-2; i>=0; i--) {
|
||||
out[i] = x[i];
|
||||
|
||||
uint8_t sum = 0;
|
||||
for (size_t j=i+1; j<k; j++)
|
||||
sum ^= tG[i*k + j] * out[j];
|
||||
|
||||
out[i] = !!(out[i] - sum);
|
||||
}
|
||||
}
|
||||
|
||||
/* Solve linear system in Z/2Z via Gauss Gauss elimination.
|
||||
*
|
||||
* A: (n, k)-matrix
|
||||
* b: (n)-vector
|
||||
*/
|
||||
void gausselimination(size_t n, size_t k, int8_t *A, int8_t *b) {
|
||||
ssize_t d = k<n ? k : n;
|
||||
for (ssize_t j=0; j<d; j++) {
|
||||
|
||||
ssize_t pivot = -1;
|
||||
for (size_t i=j; i<n; i++) {
|
||||
if (A[i*k + j]) {
|
||||
pivot = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (pivot == -1)
|
||||
continue;
|
||||
|
||||
if (pivot != j) {
|
||||
for (size_t i=0; i<k; i++) {
|
||||
int8_t tmp = A[j*k + i];
|
||||
A[j*k + i] = A[pivot*k + i];
|
||||
A[pivot*k + i] = tmp;
|
||||
}
|
||||
|
||||
int8_t tmp = b[j];
|
||||
b[j] = b[pivot];
|
||||
b[pivot] = tmp;
|
||||
}
|
||||
|
||||
for (size_t i=j+1; i<n; i++) {
|
||||
if (A[i*k + j]) {
|
||||
for (size_t p=0; p<k; p++)
|
||||
A[i*k + p] = !!(A[i*k + p] - A[j*k + p]);
|
||||
b[i] = !!(b[i] - b[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
|
||||
import pyldpc
|
||||
import scipy.sparse
|
||||
import numpy as np
|
||||
import test_decoder
|
||||
import os, sys
|
||||
import ctypes as C
|
||||
import argparse
|
||||
|
||||
if __name__ != '__main__':
|
||||
raise RuntimeError("Please don't import this module, this is a command-line program.")
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('-r', '--reference', action='store_true', default=False, help='Run reference decoder instead of C implemention')
|
||||
args = parser.parse_args()
|
||||
|
||||
lib = C.CDLL('./ldpc_decoder_test.so')
|
||||
|
||||
n = 5*19
|
||||
nodes, bits = 17, 19
|
||||
H, G = pyldpc.make_ldpc(n, nodes, bits, systematic=False, seed=0)
|
||||
_1, bits_pos, _2 = scipy.sparse.find(H)
|
||||
_, k = G.shape
|
||||
|
||||
st = np.random.RandomState(seed=0)
|
||||
test_data = st.randint(0, 2, k)
|
||||
d = np.dot(G, test_data) % 2
|
||||
x = (-1) ** d
|
||||
x[29:] = 0
|
||||
|
||||
bits_pos = bits_pos.astype(np.uint32)
|
||||
x = x.astype(np.int8)
|
||||
|
||||
lib.decode.argtypes = [C.c_size_t, C.c_size_t, C.c_size_t, C.POINTER(C.c_size_t), C.POINTER(C.c_int8), C.POINTER(C.c_int8), C.c_uint]
|
||||
lib.get_message.argtypes = [C.c_size_t, C.c_size_t, C.POINTER(C.c_int8), C.POINTER(C.c_int8), C.POINTER(C.c_int8)]
|
||||
|
||||
if args.reference:
|
||||
ref_out = test_decoder.decode(H, x, 3)
|
||||
print('decoder output:', ref_out, flush=True)
|
||||
print('msg reconstruction:', test_decoder.get_message(G, ref_out))
|
||||
print('reference decoder: ', np.all(np.equal(test_decoder.get_message(G, ref_out), test_data)), flush=True)
|
||||
np.set_printoptions(linewidth=220)
|
||||
print(test_data)
|
||||
print(test_decoder.get_message(G, ref_out))
|
||||
print(test_decoder.get_message(G, ref_out) ^ test_data)
|
||||
|
||||
else:
|
||||
out = np.zeros(n, dtype=np.uint8)
|
||||
# print('python data:', x, flush=True)
|
||||
print('decoder iterations:', lib.decode(n, nodes, bits,
|
||||
bits_pos.ctypes.data_as(C.POINTER(C.c_ulong)),
|
||||
x.ctypes.data_as(C.POINTER(C.c_int8)),
|
||||
out.ctypes.data_as(C.POINTER(C.c_int8)),
|
||||
25), flush=True)
|
||||
print('decoder output:', out)
|
||||
print('msg reconstruction:', test_decoder.get_message(G, out.astype(np.int64)))
|
||||
print('decoder under test:', np.all(np.equal(test_decoder.get_message(G, out.astype(np.int64)), test_data)))
|
||||
np.set_printoptions(linewidth=220)
|
||||
print(test_data)
|
||||
print(test_decoder.get_message(G, out.astype(np.int64)))
|
||||
G = G.astype(np.int8)
|
||||
msg = np.zeros(k, dtype=np.int8)
|
||||
lib.get_message(
|
||||
n, k,
|
||||
G.ctypes.data_as(C.POINTER(C.c_int8)),
|
||||
out.astype(np.int8).ctypes.data_as(C.POINTER(C.c_int8)),
|
||||
msg.ctypes.data_as(C.POINTER(C.c_int8)))
|
||||
print(msg)
|
||||
print(msg ^ test_data)
|
||||
|
||||
print('codeword length:', len(x))
|
||||
print('data length:', len(test_data))
|
||||
|
|
@ -1,84 +0,0 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <cmath>
|
||||
|
||||
#include "ldpc/generic.hh"
|
||||
#include "ldpc/layered_decoder.hh"
|
||||
|
||||
static const int DEFAULT_TRIALS = 25;
|
||||
|
||||
struct DVB_S2_TABLE_C9
|
||||
{
|
||||
static const int M = 360;
|
||||
static const int N = 16200;
|
||||
static const int K = 13320;
|
||||
static const int LINKS_MIN_CN = 15;
|
||||
static const int LINKS_MAX_CN = 19;
|
||||
static const int LINKS_TOTAL = 49319;
|
||||
static const int DEG_MAX = 13;
|
||||
static const int DEG[];
|
||||
static const int LEN[];
|
||||
static const int POS[];
|
||||
};
|
||||
|
||||
const int DVB_S2_TABLE_C9::DEG[] = {
|
||||
13, 3, 0
|
||||
};
|
||||
|
||||
const int DVB_S2_TABLE_C9::LEN[] = {
|
||||
1, 36, 0
|
||||
};
|
||||
|
||||
const int DVB_S2_TABLE_C9::POS[] = {
|
||||
3, 2409, 499, 1481, 908, 559, 716, 1270, 333, 2508, 2264, 1702, 2805,
|
||||
4, 2447, 1926,
|
||||
5, 414, 1224,
|
||||
6, 2114, 842,
|
||||
7, 212, 573,
|
||||
0, 2383, 2112,
|
||||
1, 2286, 2348,
|
||||
2, 545, 819,
|
||||
3, 1264, 143,
|
||||
4, 1701, 2258,
|
||||
5, 964, 166,
|
||||
6, 114, 2413,
|
||||
7, 2243, 81,
|
||||
0, 1245, 1581,
|
||||
1, 775, 169,
|
||||
2, 1696, 1104,
|
||||
3, 1914, 2831,
|
||||
4, 532, 1450,
|
||||
5, 91, 974,
|
||||
6, 497, 2228,
|
||||
7, 2326, 1579,
|
||||
0, 2482, 256,
|
||||
1, 1117, 1261,
|
||||
2, 1257, 1658,
|
||||
3, 1478, 1225,
|
||||
4, 2511, 980,
|
||||
5, 2320, 2675,
|
||||
6, 435, 1278,
|
||||
7, 228, 503,
|
||||
0, 1885, 2369,
|
||||
1, 57, 483,
|
||||
2, 838, 1050,
|
||||
3, 1231, 1990,
|
||||
4, 1738, 68,
|
||||
5, 2392, 951,
|
||||
6, 163, 645,
|
||||
7, 2644, 1704,
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
|
||||
int ldpc_decode(float *symbols, int trials) {
|
||||
if (trials < 0)
|
||||
trials = DEFAULT_TRIALS;
|
||||
|
||||
LDPCDecoder<float, SumProductAlgorithm<float, SelfCorrectedUpdate<float>>, LDPC<DVB_S2_TABLE_C9>> decoder;
|
||||
return decoder.run(symbols, symbols+decoder.K, trials, 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -190,9 +190,11 @@ static struct jtag_img_descriptor {
|
|||
.img_len = 0x004000,
|
||||
};
|
||||
|
||||
const char fw_dump[0x4000] = {
|
||||
char fw_dump[0x4000] = {
|
||||
#include "EasyMeter_Q3DA1002_V3.03_fw_dump_0xc000.h"
|
||||
};
|
||||
const int fw_dump_offx = 0xc000;
|
||||
const int row2_offx = 0xf438 - fw_dump_offx;
|
||||
|
||||
ssize_t jt_spi_flash_read_block(void *usr, int addr, size_t len, uint8_t *out) {
|
||||
/*
|
||||
|
|
@ -201,11 +203,25 @@ ssize_t jt_spi_flash_read_block(void *usr, int addr, size_t len, uint8_t *out) {
|
|||
*/
|
||||
|
||||
for (size_t i=0; i<len; i++)
|
||||
out[i] = fw_dump[addr - 0xc000 + i];
|
||||
out[i] = fw_dump[addr - fw_dump_offx + i];
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
void update_image_flash_counter(void) {
|
||||
static int flash_counter = 0;
|
||||
flash_counter ++;
|
||||
fw_dump[row2_offx + 0] = flash_counter/10000 + '0';
|
||||
flash_counter %= 10000;
|
||||
fw_dump[row2_offx + 1] = flash_counter/1000 + '0';
|
||||
flash_counter %= 1000;
|
||||
fw_dump[row2_offx + 2] = flash_counter/100 + '0';
|
||||
flash_counter %= 100;
|
||||
fw_dump[row2_offx + 3] = flash_counter/10 + '0';
|
||||
flash_counter %= 10;
|
||||
fw_dump[row2_offx + 4] = flash_counter + '0';
|
||||
}
|
||||
|
||||
static unsigned int measurement_errors = 0;
|
||||
static struct dsss_demod_state demod_state;
|
||||
static uint32_t freq_sample_ts = 0;
|
||||
|
|
@ -248,16 +264,18 @@ int main(void)
|
|||
dsss_demod_init(&demod_state);
|
||||
|
||||
con_printf("Booted.\r\n");
|
||||
int i=0;
|
||||
while (23) {
|
||||
con_printf("Attempting to flash meter...\r\n");
|
||||
int flash_tries = 0;
|
||||
while (flash_tries++ < 25) {
|
||||
mspd_jtag_init();
|
||||
int rv = mspd_jtag_flash_and_reset(jtag_img.devmem_img_start, jtag_img.img_len, jt_spi_flash_read_block, &jtag_img);
|
||||
con_printf("%d flash result: %d\r\n", i, rv);
|
||||
while (!rv) {}
|
||||
if (!mspd_jtag_flash_and_reset(jtag_img.devmem_img_start, jtag_img.img_len, jt_spi_flash_read_block, &jtag_img))
|
||||
break;
|
||||
for (int j=0; j<168*1000*5; j++)
|
||||
asm volatile ("nop");
|
||||
i++;
|
||||
}
|
||||
if (flash_tries == 25)
|
||||
con_printf("Giving up.\r\n");
|
||||
|
||||
while (23) {
|
||||
if (adc_fft_buf_ready_idx != -1) {
|
||||
for (int j=0; j<168*1000*2; j++)
|
||||
|
|
|
|||
|
|
@ -125,10 +125,7 @@ int mspd_jtag_flash_and_reset(size_t img_start, size_t img_len, ssize_t (*read_b
|
|||
return -EPIPE;
|
||||
}
|
||||
|
||||
/* Verify flash */
|
||||
/* FIXME
|
||||
word = jtag_read_mem(NULL, 16, addr+index );
|
||||
*/
|
||||
/* TODO: Verify flash here. */
|
||||
|
||||
/* Execute power on reset */
|
||||
jtag_execute_puc(&sr_jtdev);
|
||||
|
|
|
|||
|
|
@ -10,4 +10,6 @@ void handle_dsss_received(uint8_t data[static TRANSMISSION_SYMBOLS]) {
|
|||
con_printf("%3d ", x);
|
||||
}
|
||||
con_printf("\r\n");
|
||||
|
||||
update_image_flash_counter();
|
||||
}
|
||||
|
|
|
|||
9
controller/fw/src/rscode-config.h
Normal file
9
controller/fw/src/rscode-config.h
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
/* Config header for reed-solomon library */
|
||||
|
||||
#ifndef __RSCODE_CONFIG_H__
|
||||
#define __RSCODE_CONFIG_H__
|
||||
|
||||
#define NPAR 4
|
||||
#define NBITS 6
|
||||
|
||||
#endif /* __RSCODE_CONFIG_H__ */
|
||||
29
controller/fw/src/rslib.c
Normal file
29
controller/fw/src/rslib.c
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "rscode-config.h"
|
||||
#include <ecc.h>
|
||||
|
||||
#include "rslib.h"
|
||||
|
||||
void rslib_encode(int nbits, size_t msglen, char msg[static msglen], char out[msglen + NPAR]) {
|
||||
struct rscode_driver driver;
|
||||
rscode_init(&driver, nbits);
|
||||
rscode_encode(&driver, (unsigned char *)msg, msglen, (unsigned char *)out);
|
||||
}
|
||||
|
||||
int rslib_decode(int nbits, size_t msglen, char msg_inout[static msglen]) {
|
||||
struct rscode_driver driver;
|
||||
rscode_init(&driver, nbits);
|
||||
return rscode_decode(&driver, (unsigned char *)msg_inout, msglen);
|
||||
}
|
||||
|
||||
int rslib_gexp(int z, int nbits) {
|
||||
struct rscode_driver driver;
|
||||
rscode_init(&driver, nbits);
|
||||
return gexp(&driver, z);
|
||||
}
|
||||
|
||||
size_t rslib_npar() {
|
||||
return NPAR;
|
||||
}
|
||||
9
controller/fw/src/rslib.h
Normal file
9
controller/fw/src/rslib.h
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
#ifndef __RSLIB_H__
|
||||
#define __RSLIB_H__
|
||||
|
||||
void rslib_encode(int nbits, size_t msglen, char msg[static msglen], char out[msglen + NPAR]);
|
||||
int rslib_decode(int nbits, size_t msglen, char msg_inout[static msglen]);
|
||||
int rslib_gexp(int z, int nbits);
|
||||
size_t rslib_npar();
|
||||
|
||||
#endif /* __RSLIB_H__ */
|
||||
81
controller/fw/tools/reed_solomon.py
Normal file
81
controller/fw/tools/reed_solomon.py
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
import os, sys
|
||||
import ctypes as C
|
||||
import argparse
|
||||
import binascii
|
||||
import numpy as np
|
||||
import timeit
|
||||
import statistics
|
||||
|
||||
lib = C.CDLL('rslib.so')
|
||||
|
||||
lib.rslib_encode.argtypes = [C.c_int, C.c_size_t, C.POINTER(C.c_char), C.POINTER(C.c_char)]
|
||||
lib.rslib_decode.argtypes = [C.c_int, C.c_size_t, C.POINTER(C.c_char)]
|
||||
lib.rslib_gexp.argtypes = [C.c_int, C.c_int]
|
||||
lib.rslib_gexp.restype = C.c_int
|
||||
lib.rslib_decode.restype = C.c_int
|
||||
lib.rslib_npar.restype = C.c_size_t
|
||||
|
||||
def npar():
|
||||
return lib.rslib_npar()
|
||||
|
||||
def encode(data: bytes, nbits=8):
|
||||
out = C.create_string_buffer(len(data) + lib.rslib_npar())
|
||||
lib.rslib_encode(nbits, len(data), data, out)
|
||||
return out.raw
|
||||
|
||||
def decode(data: bytes, nbits=8):
|
||||
inout = C.create_string_buffer(data)
|
||||
lib.rslib_decode(nbits, len(data), inout)
|
||||
return inout.raw[:-lib.rslib_npar() - 1]
|
||||
|
||||
def cmdline_func_test(args, print=lambda *args, **kwargs: None, benchmark=False):
|
||||
st = np.random.RandomState(seed=args.seed)
|
||||
|
||||
lfsr = [lib.rslib_gexp(i, args.bits) for i in range(2**args.bits - 1)]
|
||||
print('LFSR', len(set(lfsr)), lfsr)
|
||||
assert all(0 < x < 2**args.bits for x in lfsr)
|
||||
assert len(set(lfsr)) == 2**args.bits - 1
|
||||
|
||||
print('Seed', args.seed)
|
||||
for i in range(args.repeat):
|
||||
print(f'Run {i}')
|
||||
test_data = bytes(st.randint(2**args.bits, size=args.message_length, dtype=np.uint8))
|
||||
print(' Raw:', binascii.hexlify(test_data).decode())
|
||||
encoded = encode(test_data, nbits=args.bits)
|
||||
print(' Encoded:', binascii.hexlify(encoded).decode())
|
||||
|
||||
indices = st.permutation(len(encoded))
|
||||
encoded = list(encoded)
|
||||
for pos in indices[:args.errors]:
|
||||
encoded[pos] = st.randint(2**args.bits)
|
||||
encoded = bytes(encoded)
|
||||
print(' Modified:', ''.join(f'\033[91m{b:02x}\033[0m' if pos in indices[:args.errors] else f'{b:02x}' for pos, b in enumerate(encoded)))
|
||||
|
||||
if benchmark:
|
||||
rpt = 10000
|
||||
delta = timeit.timeit('decode(encoded, nbits=args.bits)',
|
||||
globals={'args': args, 'decode': decode, 'encoded': encoded},
|
||||
number=rpt)/rpt
|
||||
print(f'Decoding runtime: {delta*1e6:.3f}μs')
|
||||
decoded = decode(encoded, nbits=args.bits)
|
||||
print(' Decoded:', binascii.hexlify(decoded).decode())
|
||||
print(' Delta:', binascii.hexlify(
|
||||
bytes(x^y for x, y in zip(test_data, decoded))
|
||||
).decode().replace('0', '.'))
|
||||
assert test_data == decoded
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser()
|
||||
cmd_parser = parser.add_subparsers(required=True)
|
||||
test_parser = cmd_parser.add_parser('test', help='Test reed-solomon implementation')
|
||||
test_parser.add_argument('-m', '--message-length', type=int, default=6, help='Test message (plaintext) length in bytes')
|
||||
test_parser.add_argument('-e', '--errors', type=int, default=2, help='Number of byte errors to insert into simulation')
|
||||
test_parser.add_argument('-r', '--repeat', type=int, default=1000, help='Repeat experiment -r times')
|
||||
test_parser.add_argument('-b', '--bits', type=int, default=8, help='Symbol bit size')
|
||||
test_parser.add_argument('-s', '--seed', type=int, default=0, help='Random seed')
|
||||
test_parser.set_defaults(func=cmdline_func_test)
|
||||
enc_parser = cmd_parser.add_parser('encode', help='RS-Encode given hex string')
|
||||
enc_parser.add_argument('hex_str')
|
||||
args = parser.parse_args()
|
||||
args.func(args, print=print)
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue