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