RadioLibSmol/src/protocols/AX25/AX25.h

385 lines
14 KiB
C++

#if !defined(_RADIOLIB_RADIOLIB_AX25_H)
#define _RADIOLIB_RADIOLIB_AX25_H
#include "../../TypeDef.h"
#if !defined(RADIOLIB_EXCLUDE_AX25)
#include "../PhysicalLayer/PhysicalLayer.h"
#include "../AFSK/AFSK.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 RADIOLIB_AX25_MAX_CALLSIGN_LEN 6
// flag field MSB LSB DESCRIPTION
#define RADIOLIB_AX25_FLAG 0b01111110 // 7 0 AX.25 frame start/end flag
// address field
#define RADIOLIB_AX25_SSID_COMMAND_DEST 0b10000000 // 7 7 frame type: command (set in destination SSID)
#define RADIOLIB_AX25_SSID_COMMAND_SOURCE 0b00000000 // 7 7 command (set in source SSID)
#define RADIOLIB_AX25_SSID_RESPONSE_DEST 0b00000000 // 7 7 response (set in destination SSID)
#define RADIOLIB_AX25_SSID_RESPONSE_SOURCE 0b10000000 // 7 7 response (set in source SSID)
#define RADIOLIB_AX25_SSID_HAS_NOT_BEEN_REPEATED 0b00000000 // 7 7 not repeated yet (set in repeater SSID)
#define RADIOLIB_AX25_SSID_HAS_BEEN_REPEATED 0b10000000 // 7 7 repeated (set in repeater SSID)
#define RADIOLIB_AX25_SSID_RESERVED_BITS 0b01100000 // 6 5 reserved bits in SSID
#define RADIOLIB_AX25_SSID_HDLC_EXTENSION_CONTINUE 0b00000000 // 0 0 HDLC extension bit: next octet contains more address information
#define RADIOLIB_AX25_SSID_HDLC_EXTENSION_END 0b00000001 // 0 0 address field end
// control field
#define RADIOLIB_AX25_CONTROL_U_SET_ASYNC_BAL_MODE 0b01101100 // 7 2 U frame type: set asynchronous balanced mode (connect request)
#define RADIOLIB_AX25_CONTROL_U_SET_ASYNC_BAL_MODE_EXT 0b00101100 // 7 2 set asynchronous balanced mode extended (connect request with module 128)
#define RADIOLIB_AX25_CONTROL_U_DISCONNECT 0b01000000 // 7 2 disconnect request
#define RADIOLIB_AX25_CONTROL_U_DISCONNECT_MODE 0b00001100 // 7 2 disconnect mode (system busy or disconnected)
#define RADIOLIB_AX25_CONTROL_U_UNNUMBERED_ACK 0b01100000 // 7 2 unnumbered acknowledge
#define RADIOLIB_AX25_CONTROL_U_FRAME_REJECT 0b10000100 // 7 2 frame reject
#define RADIOLIB_AX25_CONTROL_U_UNNUMBERED_INFORMATION 0b00000000 // 7 2 unnumbered information
#define RADIOLIB_AX25_CONTROL_U_EXHANGE_IDENTIFICATION 0b10101100 // 7 2 exchange ID
#define RADIOLIB_AX25_CONTROL_U_TEST 0b11100000 // 7 2 test
#define RADIOLIB_AX25_CONTROL_POLL_FINAL_ENABLED 0b00010000 // 4 4 control field poll/final bit: enabled
#define RADIOLIB_AX25_CONTROL_POLL_FINAL_DISABLED 0b00000000 // 4 4 disabled
#define RADIOLIB_AX25_CONTROL_S_RECEIVE_READY 0b00000000 // 3 2 S frame type: receive ready (system ready to receive)
#define RADIOLIB_AX25_CONTROL_S_RECEIVE_NOT_READY 0b00000100 // 3 2 receive not ready (TNC buffer full)
#define RADIOLIB_AX25_CONTROL_S_REJECT 0b00001000 // 3 2 reject (out of sequence or duplicate)
#define RADIOLIB_AX25_CONTROL_S_SELECTIVE_REJECT 0b00001100 // 3 2 selective reject (single frame repeat request)
#define RADIOLIB_AX25_CONTROL_INFORMATION_FRAME 0b00000000 // 0 0 frame type: information (I frame)
#define RADIOLIB_AX25_CONTROL_SUPERVISORY_FRAME 0b00000001 // 1 0 supervisory (S frame)
#define RADIOLIB_AX25_CONTROL_UNNUMBERED_FRAME 0b00000011 // 1 0 unnumbered (U frame)
// protocol identifier field
#define RADIOLIB_AX25_PID_ISO_8208 0x01
#define RADIOLIB_AX25_PID_TCP_IP_COMPRESSED 0x06
#define RADIOLIB_AX25_PID_TCP_IP_UNCOMPRESSED 0x07
#define RADIOLIB_AX25_PID_SEGMENTATION_FRAGMENT 0x08
#define RADIOLIB_AX25_PID_TEXNET_DATAGRAM_PROTOCOL 0xC3
#define RADIOLIB_AX25_PID_LINK_QUALITY_PROTOCOL 0xC4
#define RADIOLIB_AX25_PID_APPLETALK 0xCA
#define RADIOLIB_AX25_PID_APPLETALK_ARP 0xCB
#define RADIOLIB_AX25_PID_ARPA_INTERNET_PROTOCOL 0xCC
#define RADIOLIB_AX25_PID_ARPA_ADDRESS_RESOLUTION 0xCD
#define RADIOLIB_AX25_PID_FLEXNET 0xCE
#define RADIOLIB_AX25_PID_NET_ROM 0xCF
#define RADIOLIB_AX25_PID_NO_LAYER_3 0xF0
#define RADIOLIB_AX25_PID_ESCAPE_CHARACTER 0xFF
// AFSK tones in Hz
#define RADIOLIB_AX25_AFSK_MARK 1200
#define RADIOLIB_AX25_AFSK_SPACE 2200
// tone duration in us (for 1200 baud AFSK)
#define RADIOLIB_AX25_AFSK_TONE_DURATION 833
/*!
\class AX25Frame
\brief Abstraction of AX.25 frame format.
*/
class AX25Frame {
public:
/*!
\brief Callsign of the destination station.
*/
char destCallsign[RADIOLIB_AX25_MAX_CALLSIGN_LEN + 1];
/*!
\brief SSID of the destination station.
*/
uint8_t destSSID;
/*!
\brief Callsign of the source station.
*/
char srcCallsign[RADIOLIB_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;
#if !defined(RADIOLIB_STATIC_ONLY)
/*!
\brief The info field.
*/
uint8_t* info;
/*!
\brief Array of repeater callsigns.
*/
char** repeaterCallsigns;
/*!
\brief Array of repeater SSIDs.
*/
uint8_t* repeaterSSIDs;
#else
/*!
\brief The info field.
*/
uint8_t info[RADIOLIB_STATIC_ARRAY_SIZE];
/*!
\brief Array of repeater callsigns.
*/
char repeaterCallsigns[8][RADIOLIB_AX25_MAX_CALLSIGN_LEN + 1];
/*!
\brief Array of repeater SSIDs.
*/
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 Copy constructor.
\param frame AX25Frame instance to copy.
*/
AX25Frame(const AX25Frame& frame);
/*!
\brief Default destructor.
*/
~AX25Frame();
/*!
\brief Overload for assignment operator.
\param frame rvalue AX25Frame.
*/
AX25Frame& operator=(const AX25Frame& frame);
/*!
\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 Constructor for 2-FSK mode.
\param phy Pointer to the wireless module providing PhysicalLayer communication.
*/
explicit AX25Client(PhysicalLayer* phy);
#if !defined(RADIOLIB_EXCLUDE_AFSK)
/*!
\brief Constructor for AFSK mode.
\param audio Pointer to the AFSK instance providing audio.
*/
explicit AX25Client(AFSKClient* audio);
/*!
\brief Set AFSK tone correction offset. On some platforms, this is required to get the audio produced by the setup to match the expected 1200/2200 Hz tones.
\param mark Positive or negative correction offset for mark audio frequency in Hz.
\param space Positive or negative correction offset for space audio frequency in Hz.
\param length Audio tone length modifier, defaults to 1.0.
\returns \ref status_codes
*/
int16_t setCorrection(int16_t mark, int16_t space, float length = 1.0f);
#endif
// 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 (RADIOLIB_AX25_FLAG) sent ahead of the actual AX.25 frame. Does not include the first RADIOLIB_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 as Arduino String.
\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(String& str, const char* destCallsign, uint8_t destSSID = 0x00);
/*!
\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);
#if !defined(RADIOLIB_GODMODE)
private:
#endif
friend class APRSClient;
PhysicalLayer* _phy;
#if !defined(RADIOLIB_EXCLUDE_AFSK)
AFSKClient* _audio;
uint32_t _afskMark;
uint32_t _afskSpace;
uint32_t _afskLen;
#endif
char _srcCallsign[RADIOLIB_AX25_MAX_CALLSIGN_LEN + 1] = {0, 0, 0, 0, 0, 0, 0};
uint8_t _srcSSID = 0;
uint16_t _preambleLen = 0;
static uint16_t getFrameCheckSequence(uint8_t* buff, size_t len);
void getCallsign(char* buff);
uint8_t getSSID();
};
#endif
#endif