79 if (!
isMode(mode))
return false;
86 }
else if (tolower(mode[0]) ==
'f') {
95 static bool isMode(
const char* mode) {
96 if (mode ==
nullptr)
return false;
97 for (
const char* name :
98 {
"ax25",
"aprs",
"fx25",
"fx25-16",
"fx25-32",
"fx25-64",
"il2p"})
106 LOGE(
"AX25: invalid baud rate or frequencies");
110 if (max_freq >= sample_rate / 2.0f) {
111 LOGE(
"AX25: frequencies must be below %.1f Hz",
112 (
double)(sample_rate / 2.0f));
116 LOGE(
"AX25: at least 4 samples per bit are needed");
121 LOGE(
"AX25: fx25_check_bytes must be 16, 32 or 64");
130 if (tolower(*a++) != tolower(*b++))
return false;
151 static uint16_t
fcs(
const uint8_t* data,
size_t len) {
152 uint16_t crc = 0xFFFF;
153 for (
size_t i = 0; i < len; i++) {
155 for (
int b = 0; b < 8; b++)
156 crc = (crc & 1) ? (crc >> 1) ^ 0x8408 : (crc >> 1);
163 static int fromText(
const char* text,
size_t len, uint8_t* frame) {
164 const char* end = text + len;
165 const char* gt = (
const char*)memchr(text,
'>', len);
166 const char* colon = (
const char*)memchr(text,
':', len);
167 if (gt ==
nullptr || colon ==
nullptr || colon < gt)
return 0;
170 const char* dest = gt + 1;
171 const char* dest_end = dest;
172 while (dest_end < colon && *dest_end !=
',') dest_end++;
173 if (!
encodeAddress(dest, dest_end, frame + n,
true,
false))
return 0;
175 if (!
encodeAddress(text, gt, frame + n,
false,
false))
return 0;
177 const char* digi = dest_end;
178 while (digi < colon) {
180 const char* digi_end = digi;
181 while (digi_end < colon && *digi_end !=
',') digi_end++;
182 if (n + 7 > 7 * 10)
return 0;
183 if (!
encodeAddress(digi, digi_end, frame + n,
false,
true))
return 0;
187 frame[n - 1] |= 0x01;
190 size_t info_len = end - (colon + 1);
192 memcpy(frame + n, colon + 1, info_len);
198 static int toText(
const uint8_t* frame,
size_t len,
char* text,
202 while (naddr < 10 && (naddr + 1) * 7 <= len) {
204 if (frame[naddr * 7 - 1] & 0x01)
break;
206 if (naddr < 2 || !(frame[naddr * 7 - 1] & 0x01))
return 0;
207 size_t pos = naddr * 7;
208 if (pos >= len)
return 0;
211 auto append = [&](
const char* str,
size_t str_len) {
212 if (n + str_len < text_size) {
213 memcpy(text + n, str, str_len);
218 append(call, strlen(call));
221 append(call, strlen(call));
223 int last_repeated = -1;
224 for (
size_t j = 2; j < naddr; j++)
225 if (frame[j * 7 + 6] & 0x80) last_repeated = j;
226 for (
size_t j = 2; j < naddr; j++) {
229 append(call, strlen(call));
230 if ((
int)j == last_repeated) append(
"*", 1);
234 uint8_t control = frame[pos++];
235 if ((control & 0xEF) == 0x03 && pos < len) pos++;
236 append((
const char*)frame + pos, len - pos);
242 static size_t writeKiss(Print& out,
const uint8_t* frame,
size_t len) {
244 n += out.write((uint8_t)0x00);
245 for (
size_t j = 0; j < len; j++) {
253 n += out.write(frame[j]);
262 bool command,
bool digipeater) {
263 bool repeated =
false;
264 if (end > start && end[-1] ==
'*') {
268 const char* dash = start;
269 while (dash < end && *dash !=
'-') dash++;
270 int call_len = dash - start;
271 if (call_len < 1 || call_len > 6)
return false;
272 for (
int j = 0; j < 6; j++) {
273 char ch = j < call_len ? toupper(start[j]) :
' ';
274 if (!isalnum((
unsigned char)ch) && ch !=
' ')
return false;
279 ssid = atoi(dash + 1);
280 if (ssid < 0 || ssid > 15)
return false;
282 uint8_t flags = 0x60;
283 if (command || (digipeater && repeated)) flags |= 0x80;
284 out[6] = flags | (ssid << 1);
290 for (
int j = 0; j < 6; j++) {
291 char ch = (in[j] >> 1) & 0x7F;
292 if (ch !=
' ') call[n++] = ch;
294 int ssid = (in[6] >> 1) & 0x0F;
295 if (ssid > 0) n += sprintf(call + n,
"-%d", ssid);
Conversion between AX.25 frames and the monitor text format (SRC>DEST,DIGI1,DIGI2*:info) and the KISS...
Definition AX25.h:141
static constexpr uint8_t KISS_FESC
Definition AX25.h:146
static size_t writeKiss(Print &out, const uint8_t *frame, size_t len)
Writes the frame as KISS data frame for port 0.
Definition AX25.h:242
static bool encodeAddress(const char *start, const char *end, uint8_t *out, bool command, bool digipeater)
Definition AX25.h:261
static int toText(const uint8_t *frame, size_t len, char *text, size_t text_size)
Definition AX25.h:198
static uint16_t fcs(const uint8_t *data, size_t len)
AX.25 frame check sequence: CRC-16-CCITT with reflected bits.
Definition AX25.h:151
static constexpr uint8_t KISS_TFEND
Definition AX25.h:147
static constexpr uint8_t KISS_FEND
Definition AX25.h:145
static constexpr uint8_t KISS_TFESC
Definition AX25.h:148
static void decodeAddress(const uint8_t *in, char *call)
Definition AX25.h:288
static int fromText(const char *text, size_t len, uint8_t *frame)
Definition AX25.h:163
static constexpr int MAX_FRAME
Definition AX25.h:143
static constexpr int MIN_FRAME
Definition AX25.h:144
FX.25: AX.25 frames with Reed-Solomon forward error correction (as implemented by direwolf)....
Definition AX25FEC.h:20
IL2P (Improved Layer 2 Protocol, as implemented by direwolf): an AX.25 frame is sent as a scrambled h...
Definition AX25FEC.h:214
TinyModem: software audio modems and packets with error correction.
Definition AX25.h:11
AX25Format
Definition AX25.h:15
@ TEXT
one frame per line in the monitor format: SRC>DEST,DIGI1,DIGI2:info
Definition AX25.h:17
@ KISS
Definition AX25.h:20
AX25Layer2
Definition AX25.h:25
@ IL2P
IL2P: Improved Layer 2 Protocol with Reed-Solomon FEC.
Definition AX25.h:31
@ AX25
HDLC framing (standard AX.25).
Definition AX25.h:27
@ FX25
FX.25: HDLC frame with Reed-Solomon FEC (compatible with AX.25).
Definition AX25.h:29
float volume
transmit amplitude (0.0 - 1.0)
Definition AX25.h:58
AX25Format format
format of the written and decoded data
Definition AX25.h:64
float baud_rate
bits per second
Definition AX25.h:52
float space_freq
space frequency in Hz
Definition AX25.h:56
bool setMode(const char *mode)
Definition AX25.h:78
static bool isMode(const char *mode)
Definition AX25.h:95
bool il2p_max_fec
transmitter: IL2P with 16 parity bytes per block (otherwise 2 - 8)
Definition AX25.h:70
static bool equalsIgnoreCase(const char *a, const char *b)
Definition AX25.h:128
AX25Layer2 layer2
transmitter: frame format (AX.25, FX.25 or IL2P)
Definition AX25.h:66
uint8_t channel
receiver: input channel which is used for the decoding
Definition AX25.h:72
float mark_freq
mark frequency (1 = no tone change) in Hz
Definition AX25.h:54
int tx_tail_ms
transmitter: flags which are sent after the last frame (in ms)
Definition AX25.h:62
float rx_noise
receiver: (testing only) amplitude of added uniform noise
Definition AX25.h:74
bool isValid() const
Checks the configuration: returns false (and logs the reason) if invalid.
Definition AX25.h:104
int fx25_check_bytes
transmitter: FX.25 check bytes (16, 32 or 64)
Definition AX25.h:68
int tx_delay_ms
transmitter: flags which are sent before the first frame (in ms)
Definition AX25.h:60
AX25Config()
Definition AX25.h:45