Initial import

This commit is contained in:
nzasch
2022-10-24 19:13:54 +02:00
commit 5f6eda2f1c
8 changed files with 418 additions and 0 deletions

92
arphy.c Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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 */