commit 5f6eda2f1c79509023cf6981076f9e42bb7c30d5 Author: nzasch <> Date: Mon Oct 24 19:13:54 2022 +0200 Initial import diff --git a/arphy.c b/arphy.c new file mode 100644 index 0000000..ba7b934 --- /dev/null +++ b/arphy.c @@ -0,0 +1,92 @@ +/* the arPhy physical layer */ + +#include +#include + +#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; +} \ No newline at end of file diff --git a/arphy.h b/arphy.h new file mode 100644 index 0000000..0ec45a1 --- /dev/null +++ b/arphy.h @@ -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 */ + diff --git a/arphy_cli.c b/arphy_cli.c new file mode 100644 index 0000000..0ba4778 --- /dev/null +++ b/arphy_cli.c @@ -0,0 +1,47 @@ +/* + * https://ciapini.wiki.esiliati.org/index.php/Armando47/ArPhyCLI + */ + +#include + +#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; +} + diff --git a/arphy_cli.h b/arphy_cli.h new file mode 100644 index 0000000..70fc088 --- /dev/null +++ b/arphy_cli.h @@ -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 */ + diff --git a/arphy_fec.c b/arphy_fec.c new file mode 100644 index 0000000..dcadbb5 --- /dev/null +++ b/arphy_fec.c @@ -0,0 +1,136 @@ +/* + * Title: FEC + */ + +#include +#include // 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; + } + } + } +} diff --git a/arphy_fec.h b/arphy_fec.h new file mode 100644 index 0000000..3690755 --- /dev/null +++ b/arphy_fec.h @@ -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 */ \ No newline at end of file diff --git a/arphy_interleaver.c b/arphy_interleaver.c new file mode 100644 index 0000000..d737ac5 --- /dev/null +++ b/arphy_interleaver.c @@ -0,0 +1,35 @@ +#include + +#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; +} \ No newline at end of file diff --git a/arphy_interleaver.h b/arphy_interleaver.h new file mode 100644 index 0000000..b01281c --- /dev/null +++ b/arphy_interleaver.h @@ -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 */ \ No newline at end of file