Initial import
This commit is contained in:
92
arphy.c
Normal file
92
arphy.c
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
/* the arPhy physical layer */
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "../../net/net.h" // necessario? vedi net_generate_block
|
||||||
|
|
||||||
|
#include "../phy.h"
|
||||||
|
#include "arphy.h"
|
||||||
|
|
||||||
|
#include "../../modem/modem_types.h"
|
||||||
|
|
||||||
|
|
||||||
|
// encoda un po di data in un buffer di simboli, torna il numero di simboli encodati
|
||||||
|
|
||||||
|
uint8_t arphy_data2symbol(uint8_t *InData, uint8_t *ModulationSymbolsBuffer) {
|
||||||
|
uint8_t FEC_index = 0, data_chunk = 0;
|
||||||
|
uint8_t i;
|
||||||
|
uint16_t bit_index;
|
||||||
|
|
||||||
|
// pulisci buffer simboli - necessario
|
||||||
|
memset(ModulationSymbolsBuffer, 0, interleaver.size);
|
||||||
|
|
||||||
|
// cicla i fec contenuti in un blocco di interleave
|
||||||
|
for (FEC_index = 0; FEC_index < interleaver.fec_blocks_size; FEC_index++) {
|
||||||
|
// spezza dati in pezzi grandi come il netto di un FEC
|
||||||
|
data_chunk = phy_data_to_chunk(InData, FEC_index, fec.in_bit_size, 0);
|
||||||
|
|
||||||
|
// pulisci buffer matrice di hadamard
|
||||||
|
memset(tx_FHT_Buffer, 0, MAX_FEC_OUTPUT_SIZE);
|
||||||
|
|
||||||
|
// encoda chunk in matrice FEC
|
||||||
|
arphy_FEC_encode(data_chunk, fec.in_bit_size, tx_FHT_Buffer);
|
||||||
|
|
||||||
|
// dispone matrice FEC nella costellazione
|
||||||
|
for (i = 0; i < fec.out_bit_size; i++) {
|
||||||
|
bit_index = (FEC_index * fec.out_bit_size) + i;
|
||||||
|
|
||||||
|
// rimappa
|
||||||
|
if (interleaver.type == ARPHY_INTERLEAVER_TYPE_HELIX) {
|
||||||
|
bit_index = arphy_index_interleave(bit_index, mod.bits_per_symbol, interleaver.symbols_size);
|
||||||
|
} else if (interleaver.type == ARPHY_INTERLEAVER_TYPE_NONE) {
|
||||||
|
// nulla
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
phy_bit_to_constellation(tx_FHT_Buffer[i], bit_index, ModulationSymbolsBuffer, mod.bits_per_symbol, interleaver.symbols_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return interleaver.symbols_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
// torna bytes dati encodati
|
||||||
|
|
||||||
|
uint8_t arphy_symbol2data(uint8_t *OutData, uint8_t *ModulationSymbolsBuffer) {
|
||||||
|
uint8_t FECIndex = 0, Chunk = 0;
|
||||||
|
uint8_t i;
|
||||||
|
uint16_t bit_index;
|
||||||
|
for (FECIndex = 0; FECIndex < interleaver.fec_blocks_size; FECIndex++) {
|
||||||
|
// pulisci buffer matrice
|
||||||
|
memset(rx_FHT_Buffer, 0, MAX_FEC_OUTPUT_SIZE);
|
||||||
|
|
||||||
|
// estrae il binario dalla costellazione e lo mette in matrice
|
||||||
|
for (i = 0; i < fec.out_bit_size; i++) {
|
||||||
|
bit_index = (FECIndex * fec.out_bit_size) + i;
|
||||||
|
// interfoglia!
|
||||||
|
if (interleaver.type == ARPHY_INTERLEAVER_TYPE_HELIX) {
|
||||||
|
bit_index = arphy_index_deinterleave(bit_index, mod.bits_per_symbol, interleaver.symbols_size);
|
||||||
|
} else if (interleaver.type == ARPHY_INTERLEAVER_TYPE_NONE) {
|
||||||
|
// nulla
|
||||||
|
}
|
||||||
|
|
||||||
|
rx_FHT_Buffer[i] = phy_constellation_to_bit(bit_index, ModulationSymbolsBuffer, mod.bits_per_symbol, interleaver.symbols_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// decodifica il FEC in-place e torna i dati puliti
|
||||||
|
Chunk = arphy_FEC_decode(rx_FHT_Buffer);
|
||||||
|
|
||||||
|
// aggrega i chunk su OutData
|
||||||
|
phy_chunk_to_data(OutData, FECIndex, fec.in_bit_size, 0, Chunk);
|
||||||
|
}
|
||||||
|
return interleaver.net_bit_size / 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t arphy_generate_symbol_buffer(uint8_t *SymbolBuffer) {
|
||||||
|
uint8_t out_symbols = 0;
|
||||||
|
uint8_t BlockBuffer[4];
|
||||||
|
net_generate_block(BlockBuffer, phy_block_buffer_size);
|
||||||
|
out_symbols = arphy_data2symbol(BlockBuffer, SymbolBuffer);
|
||||||
|
|
||||||
|
return out_symbols;
|
||||||
|
}
|
||||||
19
arphy.h
Normal file
19
arphy.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
/** @file
|
||||||
|
* @brief armando, protocollo arphy
|
||||||
|
*
|
||||||
|
* https://ciapini.wiki.esiliati.org/index.php/ArPhy
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ARPHY_H
|
||||||
|
#define ARPHY_H
|
||||||
|
|
||||||
|
#include "arphy_fec.h"
|
||||||
|
#include "arphy_interleaver.h"
|
||||||
|
|
||||||
|
uint8_t arphy_data2symbol(uint8_t *InData, uint8_t *ModulationSymbolsBuffer);
|
||||||
|
uint8_t arphy_symbol2data(uint8_t *OutData, uint8_t *ModulationSymbolsBuffer);
|
||||||
|
uint8_t arphy_generate_symbol_buffer(uint8_t *SymbolBuffer);
|
||||||
|
|
||||||
|
#endif /* ARPHY_H */
|
||||||
|
|
||||||
47
arphy_cli.c
Normal file
47
arphy_cli.c
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* https://ciapini.wiki.esiliati.org/index.php/Armando47/ArPhyCLI
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "../../mini-printf.h"
|
||||||
|
|
||||||
|
#include "../phy.h"
|
||||||
|
#include "arphy.h"
|
||||||
|
#include "arphy_cli.h"
|
||||||
|
#include "arphy_fec.h"
|
||||||
|
#include "arphy_interleaver.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
uint8_t arphy_cli_print_frame(net_packet net_pck, arnet_packet arnet_pck, uint8_t *Buffer) {
|
||||||
|
uint8_t q = 0;
|
||||||
|
return q;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
uint8_t arphy_cli_print_state(uint8_t *Buffer) {
|
||||||
|
uint8_t q = 0;
|
||||||
|
q += mini_snprintf((char*) (&Buffer[q]), 24, "%c%c%u%c%c%c%u", ARPHY_CLI_FEC_TYPE, ARPHY_CLI_KV_SEPARATOR, fec.type, ARPHY_CLI_ELEMENT_SEPARATOR, ARPHY_CLI_INTERLEAVER_TYPE, ARPHY_CLI_KV_SEPARATOR, interleaver.type);
|
||||||
|
return q;
|
||||||
|
}
|
||||||
|
|
||||||
|
// assegna
|
||||||
|
|
||||||
|
uint8_t arphy_cli_exec(uint8_t name, uint32_t value) {
|
||||||
|
uint8_t err = ARPHY_CLI_ERR_OK;
|
||||||
|
if (name == ARPHY_CLI_FEC_TYPE) {
|
||||||
|
if (value <= ARPHY_FEC_TYPE_MAX) fec.type = value;
|
||||||
|
else {
|
||||||
|
err = ARPHY_CLI_ERR_INVALID_VALUE;
|
||||||
|
}
|
||||||
|
} else if (name == ARPHY_CLI_INTERLEAVER_TYPE) {
|
||||||
|
if (value <= ARPHY_INTERLEAVER_TYPE_MAX) interleaver.type = value;
|
||||||
|
else {
|
||||||
|
err = ARPHY_CLI_ERR_INVALID_VALUE;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err = ARPHY_CLI_ERR_INVALID_NAME;
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
26
arphy_cli.h
Normal file
26
arphy_cli.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
/**
|
||||||
|
* https://ciapini.wiki.esiliati.org/index.php/Armando47/ArPhyCLI
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ARPHY_CLI_H
|
||||||
|
#define ARPHY_CLI_H
|
||||||
|
|
||||||
|
#define ARPHY_CLI_ELEMENT_SEPARATOR ','
|
||||||
|
#define ARPHY_CLI_KV_SEPARATOR '='
|
||||||
|
|
||||||
|
// registri
|
||||||
|
#define ARPHY_CLI_FEC_TYPE 'F'
|
||||||
|
#define ARPHY_CLI_INTERLEAVER_TYPE 'I'
|
||||||
|
|
||||||
|
// errori
|
||||||
|
#define ARPHY_CLI_ERR 'E'
|
||||||
|
#define ARPHY_CLI_ERR_OK 0
|
||||||
|
#define ARPHY_CLI_ERR_INVALID_NAME 1
|
||||||
|
#define ARPHY_CLI_ERR_INVALID_VALUE 2
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t arphy_cli_exec(uint8_t name, uint32_t value);
|
||||||
|
uint8_t arphy_cli_print_state(uint8_t *Buffer);
|
||||||
|
|
||||||
|
#endif /* ARPHY_CLI_H */
|
||||||
|
|
||||||
136
arphy_fec.c
Normal file
136
arphy_fec.c
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
/*
|
||||||
|
* Title: FEC
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h> // serve ad abs()
|
||||||
|
|
||||||
|
#include "arphy.h"
|
||||||
|
#include "arphy_fec.h"
|
||||||
|
#include "arphy_interleaver.h"
|
||||||
|
|
||||||
|
#include "../../modem/modem_types.h"
|
||||||
|
|
||||||
|
// buffer per FEC // perche 16bit ?
|
||||||
|
int16_t tx_FHT_Buffer[MAX_FEC_OUTPUT_SIZE], rx_FHT_Buffer[MAX_FEC_OUTPUT_SIZE];
|
||||||
|
|
||||||
|
block_code fec;
|
||||||
|
|
||||||
|
/// Calculate FEC parameters
|
||||||
|
|
||||||
|
void arphy_set_up_FEC(block_code* fec_params) {
|
||||||
|
if (fec_params->type == ARPHY_FEC_TYPE_NONE) {
|
||||||
|
fec_params->in_bit_size = 8;
|
||||||
|
fec_params->out_bit_size = fec_params->in_bit_size;
|
||||||
|
} else if (fec_params->type == ARPHY_FEC_TYPE_HADAMARD) {
|
||||||
|
fec_params->in_bit_size = 4; // dimensione singolo dato in ingresso
|
||||||
|
fec_params->out_bit_size = 1 << (fec_params->in_bit_size - 1); // dimensione del singolo codice hadamard in uscita 2^(n-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fec_params->out_symbols_size = (fec_params->out_bit_size / mod.bits_per_symbol);
|
||||||
|
}
|
||||||
|
|
||||||
|
void arphy_FEC_encode(uint8_t Chunk, uint8_t ChunkSize, int16_t *DataBuffer) {
|
||||||
|
if (fec.type == ARPHY_FEC_TYPE_NONE) {
|
||||||
|
uint8_t i;
|
||||||
|
for (i = 0; i < ChunkSize; i++) {
|
||||||
|
DataBuffer[i] |= (Chunk >> i) & 1;
|
||||||
|
}
|
||||||
|
} else if (fec.type == ARPHY_FEC_TYPE_HADAMARD) {
|
||||||
|
// il valore massimo del dato e' 2 * size(matrice)
|
||||||
|
// inserimento chunk nella matrice, alti negativi, bassi positivi
|
||||||
|
if (Chunk < (fec.out_bit_size * 2)) {
|
||||||
|
if (Chunk < fec.out_bit_size) DataBuffer[Chunk] = 1;
|
||||||
|
else DataBuffer[Chunk - fec.out_bit_size] = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// trasformata inversa di hadamard
|
||||||
|
InverseFastHadamardTransform(DataBuffer, fec.out_bit_size);
|
||||||
|
|
||||||
|
// riduci a binario
|
||||||
|
uint8_t MatrixIndex;
|
||||||
|
for (MatrixIndex = 0; MatrixIndex < fec.out_bit_size; MatrixIndex++) {
|
||||||
|
if (DataBuffer[MatrixIndex] < 0) DataBuffer[MatrixIndex] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t arphy_FEC_decode(int16_t *DataMatrix) {
|
||||||
|
uint8_t DataChunk = 0;
|
||||||
|
uint16_t TimeBit;
|
||||||
|
if (fec.type == ARPHY_FEC_TYPE_NONE) {
|
||||||
|
for (TimeBit = 0; TimeBit < fec.out_bit_size; TimeBit++) {
|
||||||
|
DataChunk |= ((DataMatrix[TimeBit] & 1) << TimeBit);
|
||||||
|
}
|
||||||
|
} else if (fec.type == ARPHY_FEC_TYPE_HADAMARD) {
|
||||||
|
// converti 0 in -1
|
||||||
|
for (TimeBit = 0; TimeBit < fec.out_bit_size; TimeBit++) {
|
||||||
|
if (DataMatrix[TimeBit] == 0) DataMatrix[TimeBit] = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// decodifica
|
||||||
|
FastHadamardTransform(DataMatrix, fec.out_bit_size);
|
||||||
|
// estrae dalla matrice
|
||||||
|
int16_t Peak = 0;
|
||||||
|
uint8_t PeakPos = 0;
|
||||||
|
fec.sqrsum = 0;
|
||||||
|
|
||||||
|
for (TimeBit = 0; TimeBit < fec.out_bit_size; TimeBit++) {
|
||||||
|
int16_t Signal = DataMatrix[TimeBit];
|
||||||
|
fec.sqrsum += Signal * Signal;
|
||||||
|
if (abs(Signal) > abs(Peak)) {
|
||||||
|
Peak = Signal;
|
||||||
|
PeakPos = TimeBit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// info
|
||||||
|
DataChunk = PeakPos;
|
||||||
|
if (Peak < 0) DataChunk += fec.out_bit_size;
|
||||||
|
fec.sqrsum -= Peak * Peak;
|
||||||
|
|
||||||
|
}
|
||||||
|
return DataChunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Forward Fast Hadamard Transform
|
||||||
|
|
||||||
|
void FastHadamardTransform(int16_t *Data, uint8_t fec_size) {
|
||||||
|
int16_t Bit1, Bit2, NewBit1, NewBit2 = 0;
|
||||||
|
uint16_t Step, Ptr, Ptr2;
|
||||||
|
for (Step = 1; Step < fec_size; Step <<= 1) {
|
||||||
|
for (Ptr = 0; Ptr < fec_size; Ptr += (Step << 1)) {
|
||||||
|
for (Ptr2 = Ptr; Ptr2 - Ptr < Step; ++Ptr2) {
|
||||||
|
Bit1 = Data[Ptr2];
|
||||||
|
Bit2 = Data[Ptr2 + Step];
|
||||||
|
NewBit1 = Bit2;
|
||||||
|
NewBit1 += Bit1;
|
||||||
|
NewBit2 = Bit2;
|
||||||
|
NewBit2 -= Bit1;
|
||||||
|
Data[Ptr2] = NewBit1;
|
||||||
|
Data[Ptr2 + Step] = NewBit2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inverse Fast Hadamard Transform
|
||||||
|
|
||||||
|
void InverseFastHadamardTransform(int16_t *Data, uint8_t fec_size) {
|
||||||
|
int16_t Bit1, Bit2, NewBit1, NewBit2 = 0;
|
||||||
|
uint16_t Step, Ptr, Ptr2;
|
||||||
|
for (Step = (fec_size >> 1); Step; Step >>= 1) {
|
||||||
|
for (Ptr = 0; Ptr < fec_size; Ptr += (Step << 1)) {
|
||||||
|
for (Ptr2 = Ptr; Ptr2 - Ptr < Step; ++Ptr2) {
|
||||||
|
Bit1 = Data[Ptr2];
|
||||||
|
Bit2 = Data[Ptr2 + Step];
|
||||||
|
NewBit1 = Bit1;
|
||||||
|
NewBit1 -= Bit2;
|
||||||
|
NewBit2 = Bit1;
|
||||||
|
NewBit2 += Bit2;
|
||||||
|
Data[Ptr2] = NewBit1;
|
||||||
|
Data[Ptr2 + Step] = NewBit2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
37
arphy_fec.h
Normal file
37
arphy_fec.h
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
#ifndef HADAMARD_H
|
||||||
|
#define HADAMARD_H
|
||||||
|
|
||||||
|
// FEC
|
||||||
|
#define MAX_FEC_INPUT_SIZE 8U
|
||||||
|
#define MAX_FEC_OUTPUT_SIZE 128U // (2^(MAX_FEC_INPUT_SIZE-1)) non fa
|
||||||
|
#define MAX_FEC_PER_BLOCK 4U
|
||||||
|
|
||||||
|
#define ARPHY_FEC_TYPE_NONE 0
|
||||||
|
#define ARPHY_FEC_TYPE_HADAMARD 1
|
||||||
|
#define ARPHY_FEC_TYPE_MAX 1
|
||||||
|
|
||||||
|
#define ARPHY_FEC_INPUT_SIZE_NIBBLE 0
|
||||||
|
#define ARPHY_FEC_INPUT_SIZE_BYTE 1
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t type; ///< algoritmo di FEC
|
||||||
|
uint8_t in_bit_size; ///< net data size in bits
|
||||||
|
uint8_t out_bit_size; ///< code size in bits
|
||||||
|
uint8_t out_symbols_size; ///< code size in symbols
|
||||||
|
uint8_t hamming_distance; ///<
|
||||||
|
uint8_t sqrsum; // fattore qualita
|
||||||
|
} block_code;
|
||||||
|
|
||||||
|
extern block_code fec;
|
||||||
|
|
||||||
|
// buffer per FEC
|
||||||
|
extern int16_t tx_FHT_Buffer[MAX_FEC_OUTPUT_SIZE], rx_FHT_Buffer[MAX_FEC_OUTPUT_SIZE];
|
||||||
|
|
||||||
|
void arphy_set_up_FEC(block_code* fec_params);
|
||||||
|
void arphy_FEC_encode(uint8_t Chunk, uint8_t ChunkSize, int16_t *DataBuffer);
|
||||||
|
uint8_t arphy_FEC_decode(int16_t *DataMatrix);
|
||||||
|
void FastHadamardTransform(int16_t *Data, uint8_t fec_size);
|
||||||
|
void InverseFastHadamardTransform(int16_t *Data, uint8_t fec_size);
|
||||||
|
|
||||||
|
#endif /* HADAMARD_H */
|
||||||
35
arphy_interleaver.c
Normal file
35
arphy_interleaver.c
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "../../modem/modem.h"
|
||||||
|
|
||||||
|
#include "../phy.h"
|
||||||
|
#include "arphy.h"
|
||||||
|
|
||||||
|
interleaver_params interleaver;
|
||||||
|
|
||||||
|
void arphy_set_up_interleaver(interleaver_params* interleaver_parameters) {
|
||||||
|
interleaver_parameters->net_bit_size = PHY_MAX_BLOCK_SIZE * 8; // interlaccia sempre su una pdu
|
||||||
|
interleaver_parameters->fec_blocks_size = interleaver_parameters->net_bit_size / fec.in_bit_size;
|
||||||
|
interleaver_parameters->symbols_size = fec.out_symbols_size * interleaver_parameters->fec_blocks_size;
|
||||||
|
interleaver_parameters->size = (interleaver_parameters->fec_blocks_size * fec.out_bit_size); // dimensione del blocco di interleaving
|
||||||
|
}
|
||||||
|
|
||||||
|
// interleaving degli indici
|
||||||
|
|
||||||
|
// torna indice mappato
|
||||||
|
|
||||||
|
uint16_t arphy_index_interleave(uint16_t in, uint8_t x, uint16_t y) {
|
||||||
|
uint16_t out;
|
||||||
|
out = in * (x + 1);
|
||||||
|
out = out % (x * y);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
// torna indice de-mappato
|
||||||
|
|
||||||
|
uint16_t arphy_index_deinterleave(uint16_t in, uint8_t x, uint16_t y) {
|
||||||
|
uint16_t out;
|
||||||
|
out = in + (in * x);
|
||||||
|
out = out % (x * y);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
26
arphy_interleaver.h
Normal file
26
arphy_interleaver.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* File: interleaver.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INTERLEAVER_H
|
||||||
|
#define INTERLEAVER_H
|
||||||
|
|
||||||
|
#define ARPHY_INTERLEAVER_TYPE_NONE 0
|
||||||
|
#define ARPHY_INTERLEAVER_TYPE_HELIX 1
|
||||||
|
#define ARPHY_INTERLEAVER_TYPE_MAX 1
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t type;
|
||||||
|
uint8_t net_bit_size; // dati contenuti in un blocco di interleaver al netto del FEC
|
||||||
|
uint8_t fec_blocks_size; // blocchi FEC contenuti in un blocco di interleaver
|
||||||
|
uint16_t symbols_size; // simboli contenuti in un blocco di interleaver
|
||||||
|
uint16_t size; // dimensione del blocco di interleaving
|
||||||
|
} interleaver_params;
|
||||||
|
|
||||||
|
extern interleaver_params interleaver;
|
||||||
|
|
||||||
|
void arphy_set_up_interleaver(interleaver_params* interleaver_parameters);
|
||||||
|
uint16_t arphy_index_interleave(uint16_t in, uint8_t x, uint16_t y);
|
||||||
|
uint16_t arphy_index_deinterleave(uint16_t in, uint8_t x, uint16_t y);
|
||||||
|
|
||||||
|
#endif /* INTERLEAVER_H */
|
||||||
Reference in New Issue
Block a user