292 lines
11 KiB
C++
292 lines
11 KiB
C++
#ifndef _RADIOLIB_AX25_H
|
|
#define _RADIOLIB_AX25_H
|
|
|
|
#include "../../TypeDef.h"
|
|
#include "../PhysicalLayer/PhysicalLayer.h"
|
|
|
|
// macros to access bits in byte array, from http://www.mathcs.emory.edu/~cheung/Courses/255/Syllabus/1-C-intro/bit-array.html
|
|
#define SET_BIT_IN_ARRAY(A, k) ( A[(k/8)] |= (1 << (k%8)) )
|
|
#define CLEAR_BIT_IN_ARRAY(A, k) ( A[(k/8)] &= ~(1 << (k%8)) )
|
|
#define TEST_BIT_IN_ARRAY(A, k) ( A[(k/8)] & (1 << (k%8)) )
|
|
#define GET_BIT_IN_ARRAY(A, k) ( (A[(k/8)] & (1 << (k%8))) ? 1 : 0 )
|
|
|
|
// CRC-CCITT calculation macros
|
|
#define XOR(A, B) ( ((A) || (B)) && !((A) && (B)) )
|
|
#define CRC_CCITT_POLY 0x1021 // generator polynomial
|
|
#define CRC_CCITT_POLY_REVERSED 0x8408 // CRC_CCITT_POLY in reversed bit order
|
|
#define CRC_CCITT_INIT 0xFFFF // initial value
|
|
|
|
// maximum callsign length in bytes
|
|
#define AX25_MAX_CALLSIGN_LEN 6
|
|
|
|
// flag field MSB LSB DESCRIPTION
|
|
#define AX25_FLAG 0b01111110 // 7 0 AX.25 frame start/end flag
|
|
|
|
// address field
|
|
#define AX25_SSID_COMMAND_DEST 0b10000000 // 7 7 frame type: command (set in destination SSID)
|
|
#define AX25_SSID_COMMAND_SOURCE 0b00000000 // 7 7 command (set in source SSID)
|
|
#define AX25_SSID_RESPONSE_DEST 0b00000000 // 7 7 response (set in destination SSID)
|
|
#define AX25_SSID_RESPONSE_SOURCE 0b10000000 // 7 7 response (set in source SSID)
|
|
#define AX25_SSID_HAS_NOT_BEEN_REPEATED 0b00000000 // 7 7 not repeated yet (set in repeater SSID)
|
|
#define AX25_SSID_HAS_BEEN_REPEATED 0b10000000 // 7 7 repeated (set in repeater SSID)
|
|
#define AX25_SSID_RESERVED_BITS 0b01100000 // 6 5 reserved bits in SSID
|
|
#define AX25_SSID_HDLC_EXTENSION_CONTINUE 0b00000000 // 0 0 HDLC extension bit: next octet contains more address information
|
|
#define AX25_SSID_HDLC_EXTENSION_END 0b00000001 // 0 0 address field end
|
|
|
|
// control field
|
|
#define AX25_CONTROL_U_SET_ASYNC_BAL_MODE 0b01101100 // 7 2 U frame type: set asynchronous balanced mode (connect request)
|
|
#define AX25_CONTROL_U_SET_ASYNC_BAL_MODE_EXT 0b00101100 // 7 2 set asynchronous balanced mode extended (connect request with module 128)
|
|
#define AX25_CONTROL_U_DISCONNECT 0b01000000 // 7 2 disconnect request
|
|
#define AX25_CONTROL_U_DISCONNECT_MODE 0b00001100 // 7 2 disconnect mode (system busy or disconnected)
|
|
#define AX25_CONTROL_U_UNNUMBERED_ACK 0b01100000 // 7 2 unnumbered acknowledge
|
|
#define AX25_CONTROL_U_FRAME_REJECT 0b10000100 // 7 2 frame reject
|
|
#define AX25_CONTROL_U_UNNUMBERED_INFORMATION 0b00000000 // 7 2 unnumbered information
|
|
#define AX25_CONTROL_U_EXHANGE_IDENTIFICATION 0b10101100 // 7 2 exchange ID
|
|
#define AX25_CONTROL_U_TEST 0b11100000 // 7 2 test
|
|
#define AX25_CONTROL_POLL_FINAL_ENABLED 0b00010000 // 4 4 control field poll/final bit: enabled
|
|
#define AX25_CONTROL_POLL_FINAL_DISABLED 0b00000000 // 4 4 disabled
|
|
#define AX25_CONTROL_S_RECEIVE_READY 0b00000000 // 3 2 S frame type: receive ready (system ready to receive)
|
|
#define AX25_CONTROL_S_RECEIVE_NOT_READY 0b00000100 // 3 2 receive not ready (TNC buffer full)
|
|
#define AX25_CONTROL_S_REJECT 0b00001000 // 3 2 reject (out of sequence or duplicate)
|
|
#define AX25_CONTROL_S_SELECTIVE_REJECT 0b00001100 // 3 2 selective reject (single frame repeat request)
|
|
#define AX25_CONTROL_INFORMATION_FRAME 0b00000000 // 0 0 frame type: information (I frame)
|
|
#define AX25_CONTROL_SUPERVISORY_FRAME 0b00000001 // 1 0 supervisory (S frame)
|
|
#define AX25_CONTROL_UNNUMBERED_FRAME 0b00000011 // 1 0 unnumbered (U frame)
|
|
|
|
// protocol identifier field
|
|
#define AX25_PID_ISO_8208 0x01
|
|
#define AX25_PID_TCP_IP_COMPRESSED 0x06
|
|
#define AX25_PID_TCP_IP_UNCOMPRESSED 0x07
|
|
#define AX25_PID_SEGMENTATION_FRAGMENT 0x08
|
|
#define AX25_PID_TEXNET_DATAGRAM_PROTOCOL 0xC3
|
|
#define AX25_PID_LINK_QUALITY_PROTOCOL 0xC4
|
|
#define AX25_PID_APPLETALK 0xCA
|
|
#define AX25_PID_APPLETALK_ARP 0xCB
|
|
#define AX25_PID_ARPA_INTERNET_PROTOCOL 0xCC
|
|
#define AX25_PID_ARPA_ADDRESS_RESOLUTION 0xCD
|
|
#define AX25_PID_FLEXNET 0xCE
|
|
#define AX25_PID_NET_ROM 0xCF
|
|
#define AX25_PID_NO_LAYER_3 0xF0
|
|
#define AX25_PID_ESCAPE_CHARACTER 0xFF
|
|
|
|
/*!
|
|
\class AX25Frame
|
|
|
|
\brief Abstraction of AX.25 frame format.
|
|
*/
|
|
class AX25Frame {
|
|
public:
|
|
/*!
|
|
\brief Callsign of the destination station.
|
|
*/
|
|
char destCallsign[AX25_MAX_CALLSIGN_LEN + 1];
|
|
|
|
/*!
|
|
\brief SSID of the destination station.
|
|
*/
|
|
uint8_t destSSID;
|
|
|
|
/*!
|
|
\brief Callsign of the source station.
|
|
*/
|
|
char srcCallsign[AX25_MAX_CALLSIGN_LEN + 1];
|
|
|
|
/*!
|
|
\brief SSID of the source station.
|
|
*/
|
|
uint8_t srcSSID;
|
|
|
|
/*!
|
|
\brief Number of repeaters to be used.
|
|
*/
|
|
uint8_t numRepeaters;
|
|
|
|
/*!
|
|
\brief The control field.
|
|
*/
|
|
uint8_t control;
|
|
|
|
/*!
|
|
\brief The protocol identifier (PID) field.
|
|
*/
|
|
uint8_t protocolID;
|
|
|
|
/*!
|
|
\brief Number of bytes in the information field.
|
|
*/
|
|
uint16_t infoLen;
|
|
|
|
/*!
|
|
\brief Receive sequence number.
|
|
*/
|
|
uint8_t rcvSeqNumber;
|
|
|
|
/*!
|
|
\brief Send sequence number.
|
|
*/
|
|
uint16_t sendSeqNumber;
|
|
|
|
#ifndef RADIOLIB_STATIC_ONLY
|
|
uint8_t* info;
|
|
char** repeaterCallsigns;
|
|
uint8_t* repeaterSSIDs;
|
|
#else
|
|
uint8_t info[RADIOLIB_STATIC_ARRAY_SIZE];
|
|
char repeaterCallsigns[8][AX25_MAX_CALLSIGN_LEN + 1];
|
|
uint8_t repeaterSSIDs[8];
|
|
#endif
|
|
|
|
/*!
|
|
\brief Overloaded constructor, for frames without info field.
|
|
|
|
\param destCallsign Callsign of the destination station.
|
|
|
|
\param destSSID SSID of the destination station.
|
|
|
|
\param srcCallsign Callsign of the source station.
|
|
|
|
\param srcSSID SSID of the source station.
|
|
|
|
\param control The control field.
|
|
*/
|
|
AX25Frame(const char* destCallsign, uint8_t destSSID, const char* srcCallsign, uint8_t srcSSID, uint8_t control);
|
|
|
|
/*!
|
|
\brief Overloaded constructor, for frames with C-string info field.
|
|
|
|
\param destCallsign Callsign of the destination station.
|
|
|
|
\param destSSID SSID of the destination station.
|
|
|
|
\param srcCallsign Callsign of the source station.
|
|
|
|
\param srcSSID SSID of the source station.
|
|
|
|
\param control The control field.
|
|
|
|
\param protocolID The protocol identifier (PID) field. Set to zero if the frame doesn't have this field.
|
|
|
|
\param info Information field, in the form of null-terminated C-string.
|
|
*/
|
|
AX25Frame(const char* destCallsign, uint8_t destSSID, const char* srcCallsign, uint8_t srcSSID, uint8_t control, uint8_t protocolID, const char* info);
|
|
|
|
/*!
|
|
\brief Default constructor.
|
|
|
|
\param destCallsign Callsign of the destination station.
|
|
|
|
\param destSSID SSID of the destination station.
|
|
|
|
\param srcCallsign Callsign of the source station.
|
|
|
|
\param srcSSID SSID of the source station.
|
|
|
|
\param control The control field.
|
|
|
|
\param protocolID The protocol identifier (PID) field. Set to zero if the frame doesn't have this field.
|
|
|
|
\param info Information field, in the form of arbitrary binary buffer.
|
|
|
|
\param infoLen Number of bytes in the information field.
|
|
*/
|
|
AX25Frame(const char* destCallsign, uint8_t destSSID, const char* srcCallsign, uint8_t srcSSID, uint8_t control, uint8_t protocolID, uint8_t* info, uint16_t infoLen);
|
|
|
|
/*!
|
|
\brief Default destructor.
|
|
*/
|
|
~AX25Frame();
|
|
|
|
/*!
|
|
\brief Method to set the repeater callsigns and SSIDs.
|
|
|
|
\param repeaterCallsigns Array of repeater callsigns in the form of null-terminated C-strings.
|
|
|
|
\param repeaterSSIDs Array of repeater SSIDs.
|
|
|
|
\param numRepeaters Number of repeaters, maximum is 8.
|
|
|
|
\returns \ref status_codes
|
|
*/
|
|
int16_t setRepeaters(char** repeaterCallsigns, uint8_t* repeaterSSIDs, uint8_t numRepeaters);
|
|
|
|
/*!
|
|
\brief Method to set receive sequence number.
|
|
|
|
\param seqNumber Sequence number to set, 0 to 7.
|
|
*/
|
|
void setRecvSequence(uint8_t seqNumber);
|
|
|
|
/*!
|
|
\brief Method to set send sequence number.
|
|
|
|
\param seqNumber Sequence number to set, 0 to 7.
|
|
*/
|
|
void setSendSequence(uint8_t seqNumber);
|
|
};
|
|
|
|
/*!
|
|
\class AX25Client
|
|
|
|
\brief Client for AX25 communication.
|
|
*/
|
|
class AX25Client {
|
|
public:
|
|
/*!
|
|
\brief Default constructor.
|
|
|
|
\param phy Pointer to the wireless module providing PhysicalLayer communication.
|
|
*/
|
|
AX25Client(PhysicalLayer* phy);
|
|
|
|
// basic methods
|
|
|
|
/*!
|
|
\brief Initialization method.
|
|
|
|
\param srcCallsign Callsign of the source station.
|
|
|
|
\param srcSSID 4-bit SSID of the source station (in case there are more stations with the same callsign). Defaults to 0.
|
|
|
|
\param preambleLen Number of "preamble" bytes (AX25_FLAG) sent ahead of the actual AX.25 frame. Does not include the first AX25_FLAG byte, which is considered part of the frame. Defaults to 8.
|
|
|
|
\returns \ref status_codes
|
|
*/
|
|
int16_t begin(const char* srcCallsign, uint8_t srcSSID = 0x00, uint8_t preambleLen = 8);
|
|
|
|
/*!
|
|
\brief Transmit unnumbered information (UI) frame.
|
|
|
|
\param str Data to be sent.
|
|
|
|
\param destCallsign Callsign of the destination station.
|
|
|
|
\param destSSID 4-bit SSID of the destination station (in case there are more stations with the same callsign). Defaults to 0.
|
|
|
|
\returns \ref status_codes
|
|
*/
|
|
int16_t transmit(const char* str, const char* destCallsign, uint8_t destSSID = 0x00);
|
|
|
|
/*!
|
|
\brief Transmit arbitrary AX.25 frame.
|
|
|
|
\param frame Frame to be sent.
|
|
|
|
\returns \ref status_codes
|
|
*/
|
|
int16_t sendFrame(AX25Frame* frame);
|
|
|
|
#ifndef RADIOLIB_GODMODE
|
|
private:
|
|
#endif
|
|
PhysicalLayer* _phy;
|
|
|
|
char _srcCallsign[AX25_MAX_CALLSIGN_LEN + 1];
|
|
uint8_t _srcSSID;
|
|
uint16_t _preambleLen;
|
|
|
|
uint16_t getFrameCheckSequence(uint8_t* buff, size_t len);
|
|
uint8_t flipBits(uint8_t b);
|
|
uint16_t flipBits16(uint16_t i);
|
|
};
|
|
|
|
#endif
|