diff --git a/src/audio.h b/src/audio.h index f69fc1d7..6eb682ac 100644 --- a/src/audio.h +++ b/src/audio.h @@ -208,6 +208,7 @@ struct audio_s { int il2p_max_fec; // 1 for max FEC length, 0 for automatic based on size. int il2p_invert_polarity; // 1 means invert on transmit. Receive handles either automatically. + enum il2p_use_crc_t { IL2P_NOCRC = 0, IL2P_USECRC } il2p_use_crc; enum v26_e { V26_UNSPECIFIED=0, V26_A, V26_B } v26_alternative; diff --git a/src/config.c b/src/config.c index 097c908f..18e4e25b 100644 --- a/src/config.c +++ b/src/config.c @@ -791,6 +791,7 @@ void config_init (char *fname, struct audio_s *p_audio_config, p_audio_config->achan[channel].layer2_xmit = LAYER2_AX25; p_audio_config->achan[channel].il2p_max_fec = 1; p_audio_config->achan[channel].il2p_invert_polarity = 0; + p_audio_config->achan[channel].il2p_use_crc = IL2P_USECRC; p_audio_config->achan[channel].fix_bits = DEFAULT_FIX_BITS; p_audio_config->achan[channel].sanity_test = SANITY_APRS; @@ -2625,13 +2626,15 @@ void config_init (char *fname, struct audio_s *p_audio_config, } /* - * IL2PTX [ + - ] [ 0 1 ] - Enable IL2P transmission. Default off. + * IL2PTX [ + - ] [ 0 1 ] [ C ] - Enable IL2P transmission. Default off. * "+" means normal polarity. Redundant since it is the default. * (command line -I for first channel) * "-" means inverted polarity. Do not use for 1200 bps. * (command line -i for first channel) * "0" means weak FEC. Not recommended. * "1" means stronger FEC. "Max FEC." Default if not specified. + * "C" means check CRC. Default is not to check CRC. + * Note, that it'll always generate CRC for the frame. */ else if (strcasecmp(t, "IL2PTX") == 0) { @@ -2644,6 +2647,7 @@ void config_init (char *fname, struct audio_s *p_audio_config, p_audio_config->achan[channel].layer2_xmit = LAYER2_IL2P; p_audio_config->achan[channel].il2p_max_fec = 1; p_audio_config->achan[channel].il2p_invert_polarity = 0; + p_audio_config->achan[channel].il2p_use_crc = IL2P_NOCRC; // Default is no CRC. while ((t = split(NULL,0)) != NULL) { for (char *c = t; *c != '\0'; c++) { @@ -2659,6 +2663,11 @@ void config_init (char *fname, struct audio_s *p_audio_config, break; case '1': p_audio_config->achan[channel].il2p_max_fec = 1; + break; + case 'C': + case 'c': + p_audio_config->achan[channel].il2p_use_crc = IL2P_USECRC; + dw_printf ("Line %d: IL2P transmission will use CRC.\n", line); break; default: text_color_set(DW_COLOR_ERROR); diff --git a/src/hdlc_rec.c b/src/hdlc_rec.c index cfae77a6..a6b90c04 100644 --- a/src/hdlc_rec.c +++ b/src/hdlc_rec.c @@ -504,7 +504,7 @@ void hdlc_rec_bit_new (int chan, int subchan, int slice, int raw, int is_scrambl if (g_audio_p->achan[chan].modem_type != MODEM_AIS) { fx25_rec_bit (chan, subchan, slice, dbit); - il2p_rec_bit (chan, subchan, slice, raw); // Note: skip NRZI. + il2p_rec_bit (chan, subchan, slice, raw, g_audio_p->achan[chan].il2p_use_crc); // Note: skip NRZI. } /* diff --git a/src/il2p.h b/src/il2p.h index d18e2d05..34c0c605 100644 --- a/src/il2p.h +++ b/src/il2p.h @@ -19,6 +19,7 @@ #define IL2P_MAX_PACKET_SIZE (IL2P_SYNC_WORD_SIZE + IL2P_HEADER_SIZE + IL2P_HEADER_PARITY + IL2P_MAX_ENCODED_PAYLOAD_SIZE) +#define IL2P_CODED_CRC_LENGTH 4 /////////////////////////////////////////////////////////////////////////////// // @@ -52,7 +53,7 @@ extern void il2p_set_debug(int debug); // Receives a bit stream from demodulator. -extern void il2p_rec_bit (int chan, int subchan, int slice, int dbit); +extern void il2p_rec_bit (int chan, int subchan, int slice, int dbit, int use_crc); @@ -81,9 +82,9 @@ int il2p_send_frame (int chan, packet_t pp, int max_fec, int polarity); 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_frame (unsigned char *irec, int use_crc); -packet_t il2p_decode_header_payload (unsigned char* uhdr, unsigned char *epayload, int *symbols_corrected); +packet_t il2p_decode_header_payload (unsigned char* uhdr, unsigned char *epayload, int *symbols_corrected, int use_crc); @@ -138,7 +139,7 @@ extern int il2p_payload_compute (il2p_payload_properties_t *p, int payload_size, 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_decode_payload (unsigned char *received, int payload_size, int max_fec, unsigned char *payload_out, int *symbols_corrected, unsigned char **next_hdr); extern int il2p_get_header_attributes (unsigned char *hdr, int *hdr_type, int *max_fec); diff --git a/src/il2p_codec.c b/src/il2p_codec.c index a20aed65..d9645165 100644 --- a/src/il2p_codec.c +++ b/src/il2p_codec.c @@ -28,6 +28,8 @@ #include "textcolor.h" #include "demod.h" +#include "fcs_calc.h" +#include "audio.h" /*------------------------------------------------------------- * @@ -38,6 +40,34 @@ *--------------------------------------------------------------*/ +static int il2p_check_crc(unsigned char *payload, int payload_length, unsigned char *coded_crc); +static int il2p_generate_crc(unsigned char *coded_crc, unsigned char *payload, int payload_length); + +#define IL2P_NIBLE_MASK 0x0f +#define IL2P_DECODE_MASK 0x7f + +// local variables + +static uint8_t encode_table[16] = { 0x0, 0x71, 0x62, 0x13, 0x54, 0x25, 0x36, 0x47, 0x38, 0x49, 0x5a, 0x2b, 0x6c, 0x1d, 0x0e, 0x7f }; + +static uint8_t decode_table[128] = { 0x0, 0x0, 0x0, 0x3, 0x0, 0x5, 0xe, 0x7, + 0x0, 0x9, 0xe, 0xb, 0xe, 0xd, 0xe, 0xe, + 0x0, 0x3, 0x3, 0x3, 0x4, 0xd, 0x6, 0x3, + 0x8, 0xd, 0xa, 0x3, 0xd, 0xd, 0xe, 0xd, + 0x0, 0x5, 0x2, 0xb, 0x5, 0x5, 0x6, 0x5, + 0x8, 0xb, 0xb, 0xb, 0xc, 0x5, 0xe, 0xb, + 0x8, 0x1, 0x6, 0x3, 0x6, 0x5, 0x6, 0x6, + 0x8, 0x8, 0x8, 0xb, 0x8, 0xd, 0x6, 0xf, + 0x0, 0x9, 0x2, 0x7, 0x4, 0x7, 0x7, 0x7, + 0x9, 0x9, 0xa, 0x9, 0xc, 0x9, 0xe, 0x7, + 0x4, 0x1, 0xa, 0x3, 0x4, 0x4, 0x4, 0x7, + 0xa, 0x9, 0xa, 0xa, 0x4, 0xd, 0xa, 0xf, + 0x2, 0x1, 0x2, 0x2, 0xc, 0x5, 0x2, 0x7, + 0xc, 0x9, 0x2, 0xb, 0xc, 0xc, 0xc, 0xf, + 0x1, 0x1, 0x2, 0x1, 0x4, 0x1, 0x6, 0xf, + 0x8, 0x1, 0xa, 0xf, 0xc, 0xf, 0xf, 0xf }; + + /*------------------------------------------------------------- * * Name: il2p_encode_frame @@ -50,6 +80,8 @@ * * max_fec - 1 to send maximum FEC size rather than automatic. * + * use_crc - 1 to use CRC for the payload. + * * Outputs: iout - Encoded result, excluding the 3 byte sync word. * Caller should provide IL2P_MAX_PACKET_SIZE bytes. * @@ -75,6 +107,15 @@ int il2p_encode_frame (packet_t pp, int max_fec, unsigned char *iout) unsigned char hdr[IL2P_HEADER_SIZE + IL2P_HEADER_PARITY]; int e; int out_len = 0; + unsigned char crc[IL2P_CODED_CRC_LENGTH]; + int crc_len; + unsigned char *frame_data; + int frame_len; + + + frame_len = ax25_get_frame_len(pp); + frame_data = ax25_get_frame_data_ptr(pp); + crc_len = il2p_generate_crc(crc, frame_data, frame_len); e = il2p_type_1_header (pp, max_fec, hdr); if (e >= 0) { @@ -84,6 +125,8 @@ int il2p_encode_frame (packet_t pp, int max_fec, unsigned char *iout) if (e == 0) { // Success. No info part. + memcpy(iout + out_len, crc, crc_len); + out_len += crc_len; return (out_len); } @@ -91,11 +134,13 @@ int il2p_encode_frame (packet_t pp, int max_fec, unsigned char *iout) 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. + memcpy(iout + out_len, crc, crc_len); + out_len += crc_len; return (out_len); } @@ -115,13 +160,15 @@ int il2p_encode_frame (packet_t pp, int max_fec, unsigned char *iout) 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. + crc_len = il2p_generate_crc(crc, frame_data_ptr, frame_len); + memcpy(iout + out_len, crc, crc_len); + out_len += crc_len; return (out_len); } // Something went wrong with the payload encoding. @@ -138,7 +185,7 @@ int il2p_encode_frame (packet_t pp, int max_fec, unsigned char *iout) } // AX.25 Information part is too large. - return (-1); + return (-1); } @@ -153,6 +200,7 @@ int il2p_encode_frame (packet_t pp, int max_fec, unsigned char *iout) * applied first so we would know how much to collect for the payload. * * Inputs: irec - Received IL2P frame excluding the 3 byte sync word. + * use_crc - 1 to chec CRC for the payload. * * Future Out: Number of symbols corrected. * @@ -160,14 +208,14 @@ 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_frame (unsigned char *irec, int use_crc) { unsigned char uhdr[IL2P_HEADER_SIZE]; // After FEC and descrambling. int e = il2p_clarify_header (irec, uhdr); // TODO?: 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)); + return (il2p_decode_header_payload(uhdr, irec + IL2P_HEADER_SIZE + IL2P_HEADER_PARITY, &e, use_crc)); } @@ -179,6 +227,7 @@ packet_t il2p_decode_frame (unsigned char *irec) * * Inputs: uhdr - Received header after FEC and descrambling. * epayload - Encoded payload. + * use_crc - 1 to check CRC for the payload. * * In/Out: symbols_corrected - Symbols (bytes) corrected in the header. * Should be 0 or 1 because it has 2 parity symbols. @@ -188,11 +237,15 @@ packet_t il2p_decode_frame (unsigned char *irec) * *--------------------------------------------------------------*/ -packet_t il2p_decode_header_payload (unsigned char* uhdr, unsigned char *epayload, int *symbols_corrected) +packet_t il2p_decode_header_payload (unsigned char* uhdr, unsigned char *epayload, int *symbols_corrected, int use_crc) { int hdr_type; int max_fec; int payload_len = il2p_get_header_attributes (uhdr, &hdr_type, &max_fec); + unsigned char *crc_hdr = epayload; // In case ther's no payload, this is where the CRC is stored. + int ret; + int frame_len; + unsigned char *frame_data; packet_t pp = NULL; @@ -210,7 +263,7 @@ packet_t il2p_decode_header_payload (unsigned char* uhdr, unsigned char *epayloa // 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); + int e = il2p_decode_payload (epayload, payload_len, max_fec, extracted, symbols_corrected, &crc_hdr); // It would be possible to have a good header but too many errors in the payload. @@ -219,14 +272,22 @@ packet_t il2p_decode_header_payload (unsigned char* uhdr, unsigned char *epayloa pp = NULL; return (pp); } - - if (e != payload_len) { + 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); } + // Check CRC if requested. + if (use_crc == IL2P_USECRC) { + frame_len = ax25_get_frame_len(pp); + frame_data = ax25_get_frame_data_ptr(pp); + ret = il2p_check_crc(frame_data, frame_len, crc_hdr); + if (ret < 0) { + ax25_delete (pp); + pp = NULL; + } + } return (pp); } else { @@ -234,12 +295,11 @@ packet_t il2p_decode_header_payload (unsigned char* uhdr, unsigned char *epayloa // 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); + int e = il2p_decode_payload (epayload, payload_len, max_fec, extracted, symbols_corrected, &crc_hdr); 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); @@ -253,11 +313,118 @@ packet_t il2p_decode_header_payload (unsigned char* uhdr, unsigned char *epayloa // this redundant. pp = ax25_from_frame (extracted, payload_len, alevel); + if (use_crc) { + frame_len = payload_len; + frame_data = extracted; + ret = il2p_check_crc(frame_data, frame_len, crc_hdr); + if (ret < 0) { + ax25_delete (pp); + pp = NULL; + } + } return (pp); } } // end il2p_decode_header_payload -// end il2p_codec.c +/*------------------------------------------------------------- + * + * Name: il2p_generate_crc + * + * Purpose: Generate IL2P encoded CRC + * + * Inputs: payload - Decoded payload. + * payload_length - payload length. + * + * In/Out: coded_crc - Coded CRC + * + * Returns: The length of the CRC, which is 4 bytes. + * + *--------------------------------------------------------------*/ +static int il2p_generate_crc(unsigned char *coded_crc, unsigned char *payload, int payload_length) +{ + int out_len = 0; + // Calculate CRC-16 for the payload. + unsigned short crc = fcs_calc (payload, payload_length); + uint8_t crc_nibles[IL2P_CODED_CRC_LENGTH]; + + if (il2p_get_debug() >= 1) { + dw_printf ("IL2P TX CRC data:\n"); + fx_hex_dump (payload, payload_length); + text_color_set (DW_COLOR_DEBUG); + dw_printf ("IL2P TX CRC: %04x.\n", crc); + } + + crc_nibles[0] = crc & IL2P_NIBLE_MASK; // low nibble + crc_nibles[1] = (crc >> 4) & IL2P_NIBLE_MASK; // next nibble + crc_nibles[2] = (crc >> 8) & IL2P_NIBLE_MASK; // next nibble + crc_nibles[3] = (crc >> 12) & IL2P_NIBLE_MASK; // high nibble + + for (int i = 0; i < IL2P_CODED_CRC_LENGTH; i++) { + *(coded_crc + i) = encode_table[crc_nibles[i]]; + out_len++; + } + return out_len; +} // end il2p_generate_crc + + +/*------------------------------------------------------------- + * + * Name: il2p_check_crc + * + * Purpose: Check IL2P CRC against decoded payload. + * + * Inputs: payload - Decoded payload. + * payload_length - payload length. + * + * In/Out: coded_crc - pointer to the coded CRC + * The length is assumed to be IL2P_CODED_CRC_LENGTH + * + * Returns: The result of the check. + * 0 for success, -1 for failure. + * + *--------------------------------------------------------------*/ + +static int il2p_check_crc(unsigned char *payload, int payload_length, unsigned char *coded_crc) +{ + + int ret; + ret = 0; + + uint8_t crc_nibles[IL2P_CODED_CRC_LENGTH]; + // Check the CRC-16 for the payload. + unsigned short crc = fcs_calc (payload, payload_length); + + if (il2p_get_debug() >= 1) { + dw_printf ("IL2P RX CRC data:\n"); + fx_hex_dump (payload, payload_length); + text_color_set (DW_COLOR_DEBUG); + dw_printf ("IL2P RX CRC: %04x.\n", crc); + } + + for (int i = 0; i < IL2P_CODED_CRC_LENGTH; i++) { + uint8_t coded_crc_byte = IL2P_DECODE_MASK & *(coded_crc+i); + crc_nibles[i] = decode_table[coded_crc_byte]; + } + + unsigned short decoded_crc = (crc_nibles[0] & IL2P_NIBLE_MASK) | + ((crc_nibles[1] & IL2P_NIBLE_MASK)<< 4) | + ((crc_nibles[2] & IL2P_NIBLE_MASK)<< 8) | + ((crc_nibles[3] & IL2P_NIBLE_MASK)<< 12); + if (decoded_crc != crc) { + if (il2p_get_debug() >= 1) { + text_color_set (DW_COLOR_ERROR); + dw_printf ("IL2P RX CRC error: expected %04x, got %04x.\n", crc, decoded_crc); + } + ret = -1; + } else if (il2p_get_debug() >= 1) { + text_color_set (DW_COLOR_DEBUG); + dw_printf ("IL2P RX CRC OK: %04x.\n", decoded_crc); + } + + return ret; +} // end il2p_check_crc + +// end il2p_codec.c diff --git a/src/il2p_payload.c b/src/il2p_payload.c index d5fb4887..61aab8c9 100644 --- a/src/il2p_payload.c +++ b/src/il2p_payload.c @@ -215,13 +215,14 @@ int il2p_encode_payload (unsigned char *payload, int payload_size, int max_fec, * *--------------------------------------------------------------------------------*/ -int il2p_decode_payload (unsigned char *received, int payload_size, int max_fec, unsigned char *payload_out, int *symbols_corrected) +int il2p_decode_payload (unsigned char *received, int payload_size, int max_fec, unsigned char *payload_out, int *symbols_corrected, unsigned char **next_hdr) { // Determine number of blocks and sizes. il2p_payload_properties_t ipp; int e; e = il2p_payload_compute (&ipp, payload_size, max_fec); + *next_hdr = NULL; if (e <= 0) { return (e); } @@ -290,6 +291,8 @@ int il2p_decode_payload (unsigned char *received, int payload_size, int max_fec, return (-3); } + *next_hdr = pin; // Point to the next header, if any. + return (decoded_length); } // end il2p_decode_payload diff --git a/src/il2p_rec.c b/src/il2p_rec.c index a1e27263..2d09d313 100644 --- a/src/il2p_rec.c +++ b/src/il2p_rec.c @@ -59,7 +59,7 @@ struct il2p_context_s { unsigned char uhdr[IL2P_HEADER_SIZE]; // Header after FEC and unscrambling. - int eplen; // Encoded payload length. This is not the nuumber from + int eplen; // Encoded payload length. This is not the number from // from the header but rather the number of encoded bytes to gather. unsigned char spayload[IL2P_MAX_ENCODED_PAYLOAD_SIZE]; @@ -94,7 +94,7 @@ static struct il2p_context_s *il2p_context[MAX_RADIO_CHANS][MAX_SUBCHANS][MAX_SL * ***********************************************************************************/ -void il2p_rec_bit (int chan, int subchan, int slice, int dbit) +void il2p_rec_bit (int chan, int subchan, int slice, int dbit, int use_crc) { // Allocate context blocks only as needed. @@ -167,7 +167,11 @@ void il2p_rec_bit (int chan, int subchan, int slice, int dbit) int hdr_type, max_fec; int len = il2p_get_header_attributes (F->uhdr, &hdr_type, &max_fec); - F->eplen = il2p_payload_compute (&plprop, len, max_fec); + if (use_crc == IL2P_USECRC) { + F->eplen = IL2P_CODED_CRC_LENGTH + il2p_payload_compute (&plprop, len, max_fec); + } else { + F->eplen = il2p_payload_compute (&plprop, len, max_fec); + } if (il2p_get_debug() >= 1) { text_color_set(DW_COLOR_DEBUG); @@ -200,8 +204,8 @@ void il2p_rec_bit (int chan, int subchan, int slice, int dbit) } // good header after FEC. else { F->state = IL2P_SEARCHING; // Header failed FEC check. - } - } // entire header has been collected. + } + } // entire header has been collected. } // full byte collected. break; @@ -235,7 +239,7 @@ void il2p_rec_bit (int chan, int subchan, int slice, int dbit) // TODO?: for symmetry, we might decode the payload here and later build the frame. { - packet_t pp = il2p_decode_header_payload (F->uhdr, F->spayload, &(F->corrected)); + packet_t pp = il2p_decode_header_payload (F->uhdr, F->spayload, &(F->corrected), use_crc); if (il2p_get_debug() >= 1) { if (pp != NULL) { diff --git a/src/il2p_send.c b/src/il2p_send.c index 28948766..e9b4c074 100644 --- a/src/il2p_send.c +++ b/src/il2p_send.c @@ -50,6 +50,8 @@ static void send_bit (int chan, int b, int polarity); * max_fec - 1 to force 16 parity symbols for each payload block. * 0 for automatic depending on block size. * + * use_crc - 1 to use CRC for the payload. + * * polarity - 0 for normal. 1 to invert signal. * 2 special case for testing - introduce some errors to test FEC. * diff --git a/src/il2p_test.c b/src/il2p_test.c index 17995259..602d4633 100644 --- a/src/il2p_test.c +++ b/src/il2p_test.c @@ -288,6 +288,7 @@ static void test_payload(void) for (int max_fec = 0; max_fec <= 1; max_fec++) { for (int payload_length = 1; payload_length <= IL2P_MAX_PAYLOAD_SIZE; payload_length++) { //dw_printf ("\n--------- max_fec = %d, payload_length = %d\n", max_fec, payload_length); + unsigned char *next = NULL; unsigned char encoded[IL2P_MAX_ENCODED_PAYLOAD_SIZE]; int k = il2p_encode_payload (original_payload, payload_length, max_fec, encoded); @@ -620,7 +621,7 @@ static void enc_dec_compare (packet_t pp1) assert (enc_len >= 0); packet_t pp2; - pp2 = il2p_decode_frame (encoded); + pp2 = il2p_decode_frame (encoded, 1); assert (pp2 != NULL); // Is it the same after encoding to IL2P and then decoding? @@ -851,7 +852,7 @@ static void decode_bitstream(void) while ( (ch = fgetc(fp)) != EOF) { if (ch == '0' || ch == '1') { - il2p_rec_bit (0, 0, 0, ch - '0'); + il2p_rec_bit (0, 0, 0, ch - '0', 1); } } fclose(fp); @@ -922,7 +923,7 @@ static void test_serdes (void) dw_printf ("%d bits sent.\n", num_bits_sent); // Need extra bit at end to flush out state machine. - il2p_rec_bit (0, 0, 0, 0); + il2p_rec_bit (0, 0, 0, 0, 1); } } ax25_delete(pp); @@ -938,7 +939,7 @@ static void test_serdes (void) void tone_gen_put_bit (int chan, int data) { - il2p_rec_bit (chan, 0, 0, data); + il2p_rec_bit (chan, 0, 0, data, 1); } // This is called when a complete frame has been deserialized.