mirror of https://github.com/wb2osz/direwolf.git
266 lines
7.8 KiB
Plaintext
266 lines
7.8 KiB
Plaintext
//
|
|
// 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
|
|
|
|
|