mirror of https://github.com/wb2osz/direwolf.git
Clean up
This commit is contained in:
parent
42314b7219
commit
366e0ab6e0
150
src/il2p.h-bak16
150
src/il2p.h-bak16
|
@ -1,150 +0,0 @@
|
|||
|
||||
|
||||
#ifndef IL2P_H
|
||||
#define IL2P_H 1
|
||||
|
||||
|
||||
#define IL2P_PREAMBLE 0x55
|
||||
|
||||
#define IL2P_SYNC_WORD 0xF15E48
|
||||
|
||||
#define IL2P_SYNC_WORD_SIZE 3
|
||||
#define IL2P_HEADER_SIZE 13 // Does not include 2 parity.
|
||||
#define IL2P_HEADER_PARITY 2
|
||||
|
||||
#define IL2P_MAX_PAYLOAD_SIZE 1023
|
||||
#define IL2P_MAX_PAYLOAD_BLOCKS 5
|
||||
#define IL2P_MAX_PARITY_SYMBOLS 16 // For payload only.
|
||||
#define IL2P_MAX_ENCODED_SIZE (IL2P_MAX_PAYLOAD_SIZE + IL2P_MAX_PAYLOAD_BLOCKS * IL2P_MAX_PARITY_SYMBOLS)
|
||||
// FIXME: above & below IL2P_MAX_ENCODED_PAYLOAD_SIZE
|
||||
|
||||
#define IL2P_MAX_PACKET_SIZE (IL2P_SYNC_WORD_SIZE + IL2P_HEADER_SIZE + IL2P_HEADER_PARITY + IL2P_MAX_ENCODED_SIZE)
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// il2p_init.c
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
// Init must be called at start of application.
|
||||
|
||||
extern void il2p_init (int debug);
|
||||
|
||||
#include "fx25.h" // For Reed Solomon stuff. e.g. struct rs
|
||||
// Maybe rearrange someday because RS now used another place.
|
||||
|
||||
extern struct rs *il2p_find_rs(int nparity); // Internal later?
|
||||
|
||||
extern void il2p_encode_rs (unsigned char *tx_data, int data_size, int num_parity, unsigned char *parity_out);
|
||||
|
||||
extern int il2p_decode_rs (unsigned char *rec_block, int data_size, int num_parity, unsigned char *out);
|
||||
|
||||
extern int il2p_get_debug(void);
|
||||
extern void il2p_set_debug(int debug);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// il2p_rec.c
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Receives a bit stream from demodulator.
|
||||
|
||||
extern void il2p_rec_bit (int chan, int subchan, int slice, int dbit);
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// il2p_send.c
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "ax25_pad.h" // For packet object.
|
||||
|
||||
// Send bit stream to modulator.
|
||||
|
||||
int il2p_send_frame (int chan, packet_t pp, int max_fec, int polarity);
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// il2p_codec.c
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "ax25_pad.h"
|
||||
|
||||
extern int il2p_encode_frame (packet_t pp, int max_fec, unsigned char *iout);
|
||||
|
||||
packet_t il2p_decode_frame (unsigned char *irec);
|
||||
|
||||
packet_t il2p_decode_header_payload (unsigned char* uhdr, unsigned char *epayload, int *symbols_corrected);
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// il2p_header.c
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
extern int il2p_type_1_header (packet_t pp, int max_fec, unsigned char *hdr);
|
||||
|
||||
extern packet_t il2p_decode_header_type_1 (unsigned char *hdr, int num_sym_changed);
|
||||
|
||||
|
||||
extern int il2p_type_0_header (packet_t pp, int max_fec, unsigned char *hdr);
|
||||
|
||||
extern int il2p_clarify_header(unsigned char *rec_hdr, unsigned char *corrected_unscrambled_hdr);
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// il2p_scramble.c
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
extern void il2p_scramble_reset (int *lsfr_state);
|
||||
|
||||
extern void il2p_scramble_block (unsigned char *in, unsigned char *out, int len, int *lsfr_state);
|
||||
|
||||
extern void il2p_descramble_reset (int *lsfr_state);
|
||||
|
||||
extern void il2p_descramble_block (unsigned char *in, unsigned char *out, int len, int *lsfr_state);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// il2p_payload.c
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
typedef struct {
|
||||
int payload_byte_count; // Total size, 0 thru 1023
|
||||
int payload_block_count;
|
||||
int small_block_size;
|
||||
int large_block_size;
|
||||
int large_block_count;
|
||||
int small_block_count;
|
||||
int parity_symbols_per_block; // 2, 4, 6, 8, 16
|
||||
} il2p_payload_properties_t;
|
||||
|
||||
extern int il2p_payload_compute (il2p_payload_properties_t *p, int payload_size, int max_fec);
|
||||
|
||||
extern int il2p_encode_payload (unsigned char *payload, int payload_size, int max_fec, unsigned char *enc);
|
||||
|
||||
extern int il2p_decode_payload (unsigned char *received, int payload_size, int max_fec, unsigned char *payload_out, int *symbols_corrected);
|
||||
|
||||
extern int il2p_get_header_attributes (unsigned char *hdr, int *hdr_type, int *max_fec);
|
||||
|
||||
#endif
|
|
@ -1,265 +0,0 @@
|
|||
//
|
||||
// This file is part of Dire Wolf, an amateur radio packet TNC.
|
||||
//
|
||||
// Copyright (C) 2021 John Langner, WB2OSZ
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
#include "direwolf.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "il2p.h"
|
||||
#include "textcolor.h"
|
||||
#include "demod.h"
|
||||
|
||||
|
||||
/*-------------------------------------------------------------
|
||||
*
|
||||
* File: il2p_codec.c
|
||||
*
|
||||
* Purpose: Convert IL2P encoded format from and to direwolf internal packet format.
|
||||
*
|
||||
*--------------------------------------------------------------*/
|
||||
|
||||
|
||||
/*-------------------------------------------------------------
|
||||
*
|
||||
* Name: il2p_encode_frame
|
||||
*
|
||||
* Purpose: Convert AX.25 frame to IL2P encoding.
|
||||
*
|
||||
* Inputs: chan - Audio channel number, 0 = first.
|
||||
*
|
||||
* pp - Packet object pointer.
|
||||
*
|
||||
* max_fec - 1 to send maximum FEC size rather than automatic.
|
||||
*
|
||||
* Outputs: iout - Encoded result, excluding the 3 byte sync word.
|
||||
* Caller should provide IL2P_MAX_PACKET_SIZE bytes.
|
||||
*
|
||||
* Returns: Number of bytes for transmission.
|
||||
* -1 is returned for failure.
|
||||
*
|
||||
* Description: Encode into IL2P format.
|
||||
*
|
||||
* Errors: If something goes wrong, return -1.
|
||||
*
|
||||
* Most likely reason is that the frame is too large.
|
||||
* IL2P has a max payload size of 1023 bytes.
|
||||
* For a type 1 header, this is the maximum AX.25 Information part size.
|
||||
* For a type 0 header, this is the entire AX.25 frame.
|
||||
*
|
||||
*--------------------------------------------------------------*/
|
||||
|
||||
int il2p_encode_frame (packet_t pp, int max_fec, unsigned char *iout)
|
||||
{
|
||||
|
||||
// Can a type 1 header be used?
|
||||
|
||||
unsigned char hdr[IL2P_HEADER_SIZE + IL2P_HEADER_PARITY];
|
||||
int e;
|
||||
int tx_lfsr_state;
|
||||
il2p_scramble_reset(&tx_lfsr_state);
|
||||
int out_len = 0;
|
||||
|
||||
e = il2p_type_1_header (pp, max_fec, hdr);
|
||||
if (e >= 0) {
|
||||
il2p_scramble_block (hdr, iout, IL2P_HEADER_SIZE, &tx_lfsr_state);
|
||||
il2p_encode_rs (iout, IL2P_HEADER_SIZE, IL2P_HEADER_PARITY, iout+IL2P_HEADER_SIZE);
|
||||
out_len = IL2P_HEADER_SIZE + IL2P_HEADER_PARITY;
|
||||
|
||||
if (e == 0) {
|
||||
// Sucess. No info part.
|
||||
return (out_len);
|
||||
}
|
||||
|
||||
// Payload is AX.25 info part.
|
||||
unsigned char *pinfo;
|
||||
int info_len;
|
||||
info_len = ax25_get_info (pp, &pinfo);
|
||||
|
||||
int k = il2p_encode_payload (pinfo, info_len, max_fec, iout+out_len);
|
||||
if (k > 0) {
|
||||
out_len += k;
|
||||
// Success. Info part was <= 1023 bytes.
|
||||
return (out_len);
|
||||
}
|
||||
|
||||
// Something went wrong with the payload encoding.
|
||||
return (-1);
|
||||
}
|
||||
else if (e == -1) {
|
||||
|
||||
// Could not use type 1 header for some reason.
|
||||
// e.g. More than 2 addresses, extended (mod 128) sequence numbers, etc.
|
||||
|
||||
e = il2p_type_0_header (pp, max_fec, hdr);
|
||||
if (e > 0) {
|
||||
|
||||
il2p_scramble_block (hdr, iout, IL2P_HEADER_SIZE, &tx_lfsr_state);
|
||||
il2p_encode_rs (iout, IL2P_HEADER_SIZE, IL2P_HEADER_PARITY, iout+IL2P_HEADER_SIZE);
|
||||
out_len = IL2P_HEADER_SIZE + IL2P_HEADER_PARITY;
|
||||
|
||||
// Payload is entire AX.25 frame.
|
||||
|
||||
unsigned char *frame_data_ptr = ax25_get_frame_data_ptr (pp);
|
||||
int frame_len = ax25_get_frame_len (pp);
|
||||
int k = il2p_encode_payload (frame_data_ptr, frame_len, max_fec, iout+out_len);
|
||||
if (k > 0) {
|
||||
out_len += k;
|
||||
// Success. Entire AX.25 frame <= 1023 bytes.
|
||||
return (out_len);
|
||||
}
|
||||
// Something went wrong with the payload encoding.
|
||||
return (-1);
|
||||
}
|
||||
else if (e == 0) {
|
||||
// Impossible condition. Type 0 header must have payload.
|
||||
return (-1);
|
||||
}
|
||||
else {
|
||||
// AX.25 frame is too large.
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
// AX.25 Information part is too large.
|
||||
return (-1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-------------------------------------------------------------
|
||||
*
|
||||
* Name: il2p_decode_frame
|
||||
*
|
||||
* Purpose: Convert IL2P encoding to AX.25 frame.
|
||||
* This is only used during testing, with a whole encoded frame.
|
||||
* During reception, the header would have FEC and descrambling
|
||||
* applied first so we would know how much to collect for the payload.
|
||||
*
|
||||
* Inputs: irec - Received IL2P frame excluding the 3 byte sync word.
|
||||
*
|
||||
* Future Out: Number of symbols corrected.
|
||||
*
|
||||
* Returns: Packet pointer or NULL for error.
|
||||
*
|
||||
*--------------------------------------------------------------*/
|
||||
|
||||
packet_t il2p_decode_frame (unsigned char *irec)
|
||||
{
|
||||
unsigned char uhdr[IL2P_HEADER_SIZE]; // After FEC and descrambling.
|
||||
int e = il2p_clarify_header (irec, uhdr);
|
||||
|
||||
// FIXME: for symmetry we might want to clarify the payload before combining.
|
||||
|
||||
return (il2p_decode_header_payload(uhdr, irec + IL2P_HEADER_SIZE + IL2P_HEADER_PARITY, &e));
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------
|
||||
*
|
||||
* Name: il2p_decode_header_payload
|
||||
*
|
||||
* Purpose: Convert IL2P encoding to AX.25 frame
|
||||
*
|
||||
* Inputs: uhdr - Received header after FEC and descrambling.
|
||||
* epayload - Encoded payload.
|
||||
*
|
||||
* In/Out: symbols_corrected - Symbols (bytes) corrected in the header.
|
||||
* Should be 0 or 1 because it has 2 parity symbols.
|
||||
* Here we add number of corrections for the payload.
|
||||
*
|
||||
* Returns: Packet pointer or NULL for error.
|
||||
*
|
||||
*--------------------------------------------------------------*/
|
||||
|
||||
packet_t il2p_decode_header_payload (unsigned char* uhdr, unsigned char *epayload, int *symbols_corrected)
|
||||
{
|
||||
int hdr_type;
|
||||
int max_fec;
|
||||
int payload_len = il2p_get_header_attributes (uhdr, &hdr_type, &max_fec);
|
||||
|
||||
packet_t pp = NULL;
|
||||
|
||||
if (hdr_type == 1) {
|
||||
|
||||
// Header type 1. Any payload is the AX.25 Information part.
|
||||
|
||||
pp = il2p_decode_header_type_1 (uhdr, *symbols_corrected);
|
||||
if (pp == NULL) {
|
||||
// Failed for some reason.
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (payload_len > 0) {
|
||||
// This is the AX.25 Information part.
|
||||
|
||||
unsigned char extracted[IL2P_MAX_PAYLOAD_SIZE];
|
||||
int e = il2p_decode_payload (epayload, payload_len, max_fec, extracted, symbols_corrected);
|
||||
|
||||
// It would be possible to have a good header but too many errors in the payload.
|
||||
|
||||
if (e <= 0) {
|
||||
ax25_delete (pp);
|
||||
pp = NULL;
|
||||
return (pp);
|
||||
}
|
||||
|
||||
if (e != payload_len) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("IL2P Internal Error: %s(): hdr_type=%d, max_fec=%d, payload_len=%d, e=%d.\n", __func__, hdr_type, max_fec, payload_len, e);
|
||||
}
|
||||
|
||||
ax25_set_info (pp, extracted, payload_len);
|
||||
}
|
||||
return (pp);
|
||||
}
|
||||
else {
|
||||
|
||||
// Header type 0. The payload is the entire AX.25 frame.
|
||||
|
||||
unsigned char extracted[IL2P_MAX_PAYLOAD_SIZE];
|
||||
int e = il2p_decode_payload (epayload, payload_len, max_fec, extracted, symbols_corrected);
|
||||
|
||||
if (e <= 0) { // Payload was not received correctly.
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (e != payload_len) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("IL2P Internal Error: %s(): hdr_type=%d, e=%d, payload_len=%d\n", __func__, hdr_type, e, payload_len);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
alevel_t alevel;
|
||||
memset (&alevel, 0, sizeof(alevel));
|
||||
//alevel = demod_get_audio_level (chan, subchan); // What TODO? We don't know channel here.
|
||||
// I think alevel gets filled in somewhere later making
|
||||
// this redundant.
|
||||
|
||||
pp = ax25_from_frame (extracted, payload_len, alevel);
|
||||
return (pp);
|
||||
}
|
||||
|
||||
} // end il2p_decode_header_payload
|
||||
|
||||
// end il2p_codec.c
|
||||
|
||||
|
|
@ -1,317 +0,0 @@
|
|||
//
|
||||
// This file is part of Dire Wolf, an amateur radio packet TNC.
|
||||
//
|
||||
// Copyright (C) 2021 John Langner, WB2OSZ
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
#include "direwolf.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "textcolor.h"
|
||||
#include "il2p.h"
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
*
|
||||
* File: il2p_payload.c
|
||||
*
|
||||
* Purpose: Functions dealing with the payload.
|
||||
*
|
||||
*--------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
*
|
||||
* Function: il2p_payload_compute
|
||||
*
|
||||
* Purpose: Compute number and sizes of data blocks based on total size.
|
||||
*
|
||||
* Inputs: payload_size 0 to 1023. (IL2P_MAX_PAYLOAD_SIZE)
|
||||
* max_fec true for 16 parity symbols, false for automatic.
|
||||
*
|
||||
* Outputs: *p Payload block sizes and counts.
|
||||
* Number of parity symbols per block.
|
||||
*
|
||||
* Returns: Number of bytes in the encoded format.
|
||||
* Could be 0 for no payload blocks.
|
||||
* -1 for error (i.e. invalid unencoded size: <0 or >1023)
|
||||
*
|
||||
*--------------------------------------------------------------------------------*/
|
||||
|
||||
int il2p_payload_compute (il2p_payload_properties_t *p, int payload_size, int max_fec)
|
||||
{
|
||||
memset (p, 0, sizeof(il2p_payload_properties_t));
|
||||
|
||||
if (payload_size < 0 || payload_size > IL2P_MAX_PAYLOAD_SIZE) {
|
||||
return (-1);
|
||||
}
|
||||
if (payload_size == 0) {
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (max_fec) {
|
||||
p->payload_byte_count = payload_size;
|
||||
p->payload_block_count = (p->payload_byte_count + 238) / 239;
|
||||
p->small_block_size = p->payload_byte_count / p->payload_block_count;
|
||||
p->large_block_size = p->small_block_size + 1;
|
||||
p->large_block_count = p->payload_byte_count - (p->payload_block_count * p->small_block_size);
|
||||
p->small_block_count = p->payload_block_count - p->large_block_count;
|
||||
p->parity_symbols_per_block = 16;
|
||||
}
|
||||
else {
|
||||
p->payload_byte_count = payload_size;
|
||||
p->payload_block_count = (p->payload_byte_count + 246) / 247;
|
||||
p->small_block_size = p->payload_byte_count / p->payload_block_count;
|
||||
p->large_block_size = p->small_block_size + 1;
|
||||
p->large_block_count = p->payload_byte_count - (p->payload_block_count * p->small_block_size);
|
||||
p->small_block_count = p->payload_block_count - p->large_block_count;
|
||||
//p->parity_symbols_per_block = (p->small_block_size / 32) + 2; // Looks like error in documentation
|
||||
|
||||
// It would work if the number of parity symbols was based on large block size.
|
||||
|
||||
if (p->small_block_size <= 61) p->parity_symbols_per_block = 2;
|
||||
else if (p->small_block_size <= 123) p->parity_symbols_per_block = 4;
|
||||
else if (p->small_block_size <= 185) p->parity_symbols_per_block = 6;
|
||||
else if (p->small_block_size <= 247) p->parity_symbols_per_block = 8;
|
||||
else {
|
||||
// Should not happen. But just in case...
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("IL2P parity symbol per payload block error. small_block_size = %d\n", p->small_block_size);
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
// Return the total size for the encoded format.
|
||||
|
||||
return (p->small_block_count * (p->small_block_size + p->parity_symbols_per_block) +
|
||||
p->large_block_count * (p->large_block_size + p->parity_symbols_per_block));
|
||||
|
||||
} // end il2p_payload_compute
|
||||
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
*
|
||||
* Function: il2p_encode_payload
|
||||
*
|
||||
* Purpose: Split payload into multiple blocks such that each set
|
||||
* of data and parity symbols fit into a 255 byte RS block.
|
||||
*
|
||||
* Inputs: *payload Array of bytes.
|
||||
* payload_size 0 to 1023. (IL2P_MAX_PAYLOAD_SIZE)
|
||||
* max_fec true for 16 parity symbols, false for automatic.
|
||||
*
|
||||
* Outputs: *enc Encoded payload for transmission.
|
||||
* Up to IL2P_MAX_ENCODED_SIZE bytes.
|
||||
*
|
||||
* Returns: -1 for error (i.e. invalid size)
|
||||
* 0 for no blocks. (i.e. size zero)
|
||||
* Number of bytes generated. Maximum IL2P_MAX_ENCODED_SIZE.
|
||||
*
|
||||
* Note: I interpretted the protocol spec as saying the LFSR state is retained
|
||||
* between data blocks. During interoperability testing, I found that
|
||||
* was not the case. It is reset for each data block.
|
||||
*
|
||||
*--------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
int il2p_encode_payload (unsigned char *payload, int payload_size, int max_fec, unsigned char *enc)
|
||||
{
|
||||
if (payload_size > IL2P_MAX_PAYLOAD_SIZE) return (-1);
|
||||
if (payload_size == 0) return (0);
|
||||
|
||||
int tx_lsfr_state;
|
||||
il2p_scramble_reset(&tx_lsfr_state);
|
||||
|
||||
// Determine number of blocks and sizes.
|
||||
|
||||
il2p_payload_properties_t ipp;
|
||||
int e;
|
||||
e = il2p_payload_compute (&ipp, payload_size, max_fec);
|
||||
if (e <= 0) {
|
||||
return (e);
|
||||
}
|
||||
|
||||
unsigned char *pin = payload;
|
||||
unsigned char *pout = enc;
|
||||
int encoded_length = 0;
|
||||
unsigned char scram[256];
|
||||
unsigned char parity[IL2P_MAX_PARITY_SYMBOLS];
|
||||
|
||||
// First the large blocks.
|
||||
|
||||
for (int b = 0; b < ipp.large_block_count; b++) {
|
||||
|
||||
|
||||
// FIXME experiment
|
||||
il2p_scramble_reset(&tx_lsfr_state);
|
||||
|
||||
il2p_scramble_block (pin, scram, ipp.large_block_size, &tx_lsfr_state);
|
||||
memcpy (pout, scram, ipp.large_block_size);
|
||||
pin += ipp.large_block_size;
|
||||
pout += ipp.large_block_size;
|
||||
encoded_length += ipp.large_block_size;
|
||||
il2p_encode_rs (scram, ipp.large_block_size, ipp.parity_symbols_per_block, parity);
|
||||
memcpy (pout, parity, ipp.parity_symbols_per_block);
|
||||
pout += ipp.parity_symbols_per_block;
|
||||
encoded_length += ipp.parity_symbols_per_block;
|
||||
}
|
||||
|
||||
// Then the small blocks.
|
||||
|
||||
for (int b = 0; b < ipp.small_block_count; b++) {
|
||||
|
||||
// FIXME experiment -- works - no need to pass lfsr state in and out of scramble block.
|
||||
il2p_scramble_reset(&tx_lsfr_state);
|
||||
|
||||
il2p_scramble_block (pin, scram, ipp.small_block_size, &tx_lsfr_state);
|
||||
memcpy (pout, scram, ipp.small_block_size);
|
||||
pin += ipp.small_block_size;
|
||||
pout += ipp.small_block_size;
|
||||
encoded_length += ipp.small_block_size;
|
||||
il2p_encode_rs (scram, ipp.small_block_size, ipp.parity_symbols_per_block, parity);
|
||||
memcpy (pout, parity, ipp.parity_symbols_per_block);
|
||||
pout += ipp.parity_symbols_per_block;
|
||||
encoded_length += ipp.parity_symbols_per_block;
|
||||
}
|
||||
|
||||
return (encoded_length);
|
||||
|
||||
} // end il2p_encode_payload
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
*
|
||||
* Function: il2p_decode_payload
|
||||
*
|
||||
* Purpose: Extract original data from encoded payload.
|
||||
*
|
||||
* Inputs: received Array of bytes. Size is unknown but in practice it
|
||||
* must not exceeed IL2P_MAX_ENCODED_SIZE.
|
||||
* payload_size 0 to 1023. (IL2P_MAX_PAYLOAD_SIZE)
|
||||
* Expected result size based on header.
|
||||
* max_fec true for 16 parity symbols, false for automatic.
|
||||
*
|
||||
* Outputs: payload_out Recovered payload.
|
||||
*
|
||||
* In/Out: symbols_corrected Number of symbols corrected.
|
||||
*
|
||||
*
|
||||
* Returns: Number of bytes extracted. Should be same as payload_size going in.
|
||||
* -3 for unexpected internal inconsistency.
|
||||
* -2 for unable to recover from signal corruption.
|
||||
* -1 for invalid size.
|
||||
* 0 for no blocks. (i.e. size zero)
|
||||
*
|
||||
* Description: Each block is scrambled separately but the LSFR state is carried
|
||||
* from the first payload block to the next.
|
||||
*
|
||||
*--------------------------------------------------------------------------------*/
|
||||
|
||||
int il2p_decode_payload (unsigned char *received, int payload_size, int max_fec, unsigned char *payload_out, int *symbols_corrected)
|
||||
{
|
||||
// Determine number of blocks and sizes.
|
||||
|
||||
il2p_payload_properties_t ipp;
|
||||
int e;
|
||||
e = il2p_payload_compute (&ipp, payload_size, max_fec);
|
||||
if (e <= 0) {
|
||||
return (e);
|
||||
}
|
||||
|
||||
unsigned char *pin = received;
|
||||
unsigned char *pout = payload_out;
|
||||
int decoded_length = 0;
|
||||
int failed = 0;
|
||||
int rx_lfsr_state;
|
||||
il2p_descramble_reset(&rx_lfsr_state);
|
||||
|
||||
|
||||
// First the large blocks.
|
||||
|
||||
for (int b = 0; b < ipp.large_block_count; b++) {
|
||||
unsigned char corrected_block[255];
|
||||
int e = il2p_decode_rs (pin, ipp.large_block_size, ipp.parity_symbols_per_block, corrected_block);
|
||||
|
||||
// dw_printf ("%s:%d: large block decode_rs returned status = %d\n", __FILE__, __LINE__, e);
|
||||
|
||||
if (e < 0) failed = 1;
|
||||
*symbols_corrected += e;
|
||||
|
||||
// FIXME - simplify
|
||||
il2p_descramble_reset(&rx_lfsr_state);
|
||||
|
||||
il2p_descramble_block (corrected_block, pout, ipp.large_block_size, &rx_lfsr_state);
|
||||
|
||||
if (il2p_get_debug() >= 2) {
|
||||
text_color_set(DW_COLOR_DEBUG);
|
||||
dw_printf ("Descrambled large payload block, %d bytes:\n", ipp.large_block_size);
|
||||
fx_hex_dump(pout, ipp.large_block_size);
|
||||
}
|
||||
|
||||
pin += ipp.large_block_size + ipp.parity_symbols_per_block;
|
||||
pout += ipp.large_block_size;
|
||||
decoded_length += ipp.large_block_size;
|
||||
}
|
||||
|
||||
// Then the small blocks.
|
||||
|
||||
for (int b = 0; b < ipp.small_block_count; b++) {
|
||||
unsigned char corrected_block[255];
|
||||
int e = il2p_decode_rs (pin, ipp.small_block_size, ipp.parity_symbols_per_block, corrected_block);
|
||||
|
||||
// dw_printf ("%s:%d: small block decode_rs returned status = %d\n", __FILE__, __LINE__, e);
|
||||
|
||||
if (e < 0) failed = 1;
|
||||
*symbols_corrected += e;
|
||||
|
||||
// FIXME - just reset in descramble block - no need to pass around as argument.
|
||||
il2p_descramble_reset(&rx_lfsr_state);
|
||||
|
||||
il2p_descramble_block (corrected_block, pout, ipp.small_block_size, &rx_lfsr_state);
|
||||
|
||||
if (il2p_get_debug() >= 2) {
|
||||
text_color_set(DW_COLOR_DEBUG);
|
||||
dw_printf ("Descrambled small payload block, %d bytes:\n", ipp.small_block_size);
|
||||
fx_hex_dump(pout, ipp.small_block_size);
|
||||
}
|
||||
|
||||
pin += ipp.small_block_size + ipp.parity_symbols_per_block;
|
||||
pout += ipp.small_block_size;
|
||||
decoded_length += ipp.small_block_size;
|
||||
}
|
||||
|
||||
if (failed) {
|
||||
//dw_printf ("%s:%d: failed = %0x\n", __FILE__, __LINE__, failed);
|
||||
return (-2);
|
||||
}
|
||||
|
||||
if (decoded_length != payload_size) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("IL2P Internal error: decoded_length = %d, payload_size = %d\n", decoded_length, payload_size);
|
||||
return (-3);
|
||||
}
|
||||
|
||||
return (decoded_length);
|
||||
|
||||
} // end il2p_decode_payload
|
||||
|
||||
// end il2p_payload.c
|
||||
|
|
@ -1,194 +0,0 @@
|
|||
//
|
||||
// This file is part of Dire Wolf, an amateur radio packet TNC.
|
||||
//
|
||||
// Copyright (C) 2021 John Langner, WB2OSZ
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
// FIXME: be consistent about descramble or descramble. not unscramble.
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
*
|
||||
* File: il2p_scramble.c
|
||||
*
|
||||
* Purpose: Scramble / descramble data as specified in the IL2P protocol specification.
|
||||
*
|
||||
*--------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#include "direwolf.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "il2p.h"
|
||||
|
||||
|
||||
// Scramble bits for il2p transmit.
|
||||
|
||||
// Note that there is a delay of 5 until the first bit comes out.
|
||||
// So we need to need to ignore the first 5 out and stick in
|
||||
// an extra 5 filler bits to flush at the end.
|
||||
|
||||
#define INIT_TX_LSFR 0x00f
|
||||
|
||||
static inline int scramble_bit (int in, int *state)
|
||||
{
|
||||
int out = ((*state >> 4) ^ *state) & 1;
|
||||
*state = ( (((in ^ *state) & 1) << 9) | (*state ^ ((*state & 1) << 4)) ) >> 1;
|
||||
return (out);
|
||||
}
|
||||
|
||||
|
||||
// Undo data scrambling for il2p receive.
|
||||
|
||||
#define INIT_RX_LSFR 0x1f0
|
||||
|
||||
static inline int descramble_bit (int in, int *state)
|
||||
{
|
||||
int out = (in ^ *state) & 1;
|
||||
*state = ((*state >> 1) | ((in & 1) << 8)) ^ ((in & 1) << 3);
|
||||
return (out);
|
||||
}
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
*
|
||||
* Function: il2p_scramble_reset
|
||||
*
|
||||
* Purpose: Reset the TX LFSR register at the beginning of a packet or payload.
|
||||
*
|
||||
* Outputs: lfsr_state Current state of transmit LFSR.
|
||||
* This is reset at the start of the packet and is
|
||||
* cummulative across the header and data blocks.
|
||||
*
|
||||
*--------------------------------------------------------------------------------*/
|
||||
|
||||
void il2p_scramble_reset (int *lfsr_state)
|
||||
{
|
||||
*lfsr_state = INIT_TX_LSFR;
|
||||
}
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
*
|
||||
* Function: il2p_scramble_block
|
||||
*
|
||||
* Purpose: Scramble a block before adding RS parity.
|
||||
*
|
||||
* Inputs: in Array of bytes.
|
||||
* len Number of bytes both in and out.
|
||||
*
|
||||
* Outputs: out Array of bytes.
|
||||
*
|
||||
* In/Out: lfsr_state Current state of transmit LFSR. ---- FIXME --- remove this
|
||||
*
|
||||
*--------------------------------------------------------------------------------*/
|
||||
|
||||
void il2p_scramble_block (unsigned char *in, unsigned char *out, int len, int *lfsr_state)
|
||||
{
|
||||
il2p_scramble_reset (lfsr_state);
|
||||
|
||||
memset (out, 0, len);
|
||||
|
||||
int skipping = 1; // Discard the first 5 out.
|
||||
int ob = 0; // Index to output byte.
|
||||
int om = 0x80; // Output bit mask;
|
||||
for (int ib = 0; ib < len; ib++) {
|
||||
for (int im = 0x80; im != 0; im >>= 1) {
|
||||
int s = scramble_bit((in[ib] & im) != 0, lfsr_state);
|
||||
if (ib == 0 && im == 0x04) skipping = 0;
|
||||
if ( ! skipping) {
|
||||
if (s) {
|
||||
out[ob] |= om;
|
||||
}
|
||||
om >>= 1;
|
||||
if (om == 0) {
|
||||
om = 0x80;
|
||||
ob++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Flush it.
|
||||
|
||||
// Preserve the LSFR state from before flushing.
|
||||
// This might be needed as the initial state for later payload blocks.
|
||||
int x = *lfsr_state;
|
||||
for (int n = 0; n < 5; n++) {
|
||||
int s = scramble_bit(0, &x);
|
||||
if (s) {
|
||||
out[ob] |= om;
|
||||
}
|
||||
om >>=1;
|
||||
if (om == 0) {
|
||||
om = 0x80;
|
||||
ob++;
|
||||
}
|
||||
}
|
||||
|
||||
} // end il2p_scramble_block
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
*
|
||||
* Function: il2p_descramble_reset
|
||||
*
|
||||
* Purpose: Reset the RX LFSR register at the beginning of a packet or payload.
|
||||
*
|
||||
* Outputs: lfsr_state Current state of transmit LFSR.
|
||||
* This is cummulative across the payload data blocks.
|
||||
*
|
||||
*--------------------------------------------------------------------------------*/
|
||||
|
||||
void il2p_descramble_reset (int *lfsr_state)
|
||||
{
|
||||
*lfsr_state = INIT_RX_LSFR;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
*
|
||||
* Function: il2p_descramble_block
|
||||
*
|
||||
* Purpose: Unscramble a block after removing RS parity.
|
||||
*
|
||||
* Inputs: in Array of bytes.
|
||||
* len Number of bytes both in and out.
|
||||
*
|
||||
* Outputs: out Array of bytes.
|
||||
*
|
||||
* In/Out: lfsr_state Current state of receive LSFR. --- FIXME - remove this.
|
||||
*
|
||||
*--------------------------------------------------------------------------------*/
|
||||
|
||||
void il2p_descramble_block (unsigned char *in, unsigned char *out, int len, int *lfsr_state)
|
||||
{
|
||||
memset (out, 0, len);
|
||||
|
||||
for (int b = 0; b < len; b++) {
|
||||
for (int m = 0x80; m != 0; m >>= 1) {
|
||||
int d = descramble_bit((in[b] & m) != 0, lfsr_state);
|
||||
if (d) {
|
||||
out[b] |= m;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// end il2p_scramble.c
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue