RadioLibSmol/src/protocols/AX25/AX25.h
2020-02-14 08:08:59 +01:00

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