SP8EBC-ParaTNC/system/src/aprs/ax25.c

323 wiersze
7.8 KiB
C

#include "ax25.h"
#include <string.h> /* memset */
#include <ctype.h>
#include <stdio.h> /* printf */
#include <afsk.h>
#include <cfifo.h>
#include <crc.h>
#include "station_config.h"
#include "KissCommunication.h"
AX25Msg ax25_rxed_frame;
char ax25_new_msg_rx_flag;
/*********************************************************************************************************************/
static void ax25_decode(AX25Ctx *ctx) {
/*********************************************************************************************************************/
uint16_t i;
uint8_t *buf = ctx->buf;
//
for (i = 0; i < ctx->frm_len ;i++)
*(ax25_rxed_frame.raw_data + i) = *(ctx->buf + i);
*(ax25_rxed_frame.raw_data + i) = '\0';
//
ax25_rxed_frame.raw_msg_len = i;
for (i = 0; i < sizeof(ax25_rxed_frame.dst.call);i++)
{
uint8_t c = (*(buf)++ >> 1);
(ax25_rxed_frame.dst.call)[i] = (c == ' ') ? '\x0' : c;
}
ax25_rxed_frame.dst.ssid = (*buf++ >> 1) & 0x0F;
for (i = 0; i < sizeof(ax25_rxed_frame.src.call);i++)
{
uint8_t c = (*(buf)++ >> 1);
(ax25_rxed_frame.src.call)[i] = (c == ' ') ? '\x0' : c;
}
ax25_rxed_frame.src.ssid = (*buf >> 1) & 0x0F;
for (ax25_rxed_frame.rpt_cnt = 0; !(*buf++ & 0x01) && (ax25_rxed_frame.rpt_cnt < (sizeof(ax25_rxed_frame.rpt_lst) / sizeof(*(ax25_rxed_frame.rpt_lst)))); ax25_rxed_frame.rpt_cnt++)
{
for (i = 0; i < sizeof(ax25_rxed_frame.rpt_lst[ax25_rxed_frame.rpt_cnt].call);i++)
{
uint8_t c = (*(buf)++ >> 1);
(ax25_rxed_frame.rpt_lst[ax25_rxed_frame.rpt_cnt].call)[i] = (c == ' ') ? '\x0' : c;
}
ax25_rxed_frame.rpt_lst[ax25_rxed_frame.rpt_cnt].ssid = (*buf >> 1) & 0x0F;
if ((*buf & 0x80)) (&ax25_rxed_frame)->rpt_flags |= BV(ax25_rxed_frame.rpt_cnt);
else (&ax25_rxed_frame)->rpt_flags &= ~BV(ax25_rxed_frame.rpt_cnt);
}
ax25_rxed_frame.ctrl = *buf++;
if (ax25_rxed_frame.ctrl != AX25_CTRL_UI) return;
ax25_rxed_frame.pid = *buf++;
if (ax25_rxed_frame.pid != AX25_PID_NOLAYER3) return;
ax25_rxed_frame.len = ctx->frm_len - 2 - (buf - ctx->buf);
ax25_rxed_frame.info = buf;
if (ctx->hook) {
ax25_new_msg_rx_flag = 1;
// ctx->dcd = false;
ctx->hook(&ax25_rxed_frame);
}
/*
insert your code here
*/
/*
end
*/
}
/*********************************************************************************************************************/
void ax25_poll(AX25Ctx *ctx) {
/*********************************************************************************************************************/
int16_t c;
while ((c = fifo_getc(&ctx->afsk->rx_fifo)) != -1)
{
if (!ctx->escape && c == HDLC_FLAG)
{
if (ctx->frm_len >= AX25_MIN_FRAME_LEN)
{
if (ctx->crc_in == AX25_CRC_CORRECT)
{
if (ctx->raw)
{
if (ctx->hook)
{
ctx->hook(NULL);
}
}
else
{
ax25_decode(ctx);
}
}
}
ctx->sync = true;
ctx->crc_in = CRC_CCITT_INIT_VAL;
ctx->frm_len = 0;
ctx->dcd_state = 0;
ctx->dcd = false; ///// bylo false
continue;
}
if (!ctx->escape && c == HDLC_RESET)
{
ctx->sync = false;
ctx->dcd = false;
continue;
}
if (!ctx->escape && c == AX25_ESC)
{
ctx->escape = true;
continue;
}
if (ctx->sync)
{
if (ctx->frm_len < CONFIG_AX25_FRAME_BUF_LEN)
{
ctx->buf[ctx->frm_len++] = c;
ctx->crc_in = updcrc_ccitt(c, ctx->crc_in);
/* Begin of Destination-ADDR based DCD*/
if (ctx->buf[6] == 0x60 && ctx->buf[0] == 0x82) {
ctx->dcd = true;
}
/* End */
if (ctx->dcd_state == 1 && c == AX25_PID_NOLAYER3) {
ctx->dcd_state ++;
ctx->dcd = true;
}
if (ctx->dcd_state == 0 && c == AX25_CTRL_UI) {
ctx->dcd_state ++;
}
}
else
{
ctx->sync = false;
ctx->dcd = false;
}
}
ctx->escape = false;
}
}
/*********************************************************************************************************************/
void ax25_putchar(AX25Ctx *ctx, uint8_t c) {
/*********************************************************************************************************************/
if (c == HDLC_FLAG || c == HDLC_RESET || c == AX25_ESC)
{
fifo_putc(AX25_ESC, &ctx->afsk->tx_fifo);
}
ctx->crc_out = updcrc_ccitt(c, ctx->crc_out);
fifo_putc(c, &ctx->afsk->tx_fifo);
}
/*********************************************************************************************************************/
static void ax25_sendCall(AX25Ctx *ctx, const AX25Call *addr, bool last) {
/*********************************************************************************************************************/
//#ifdef _DBG_TRACE
// trace_printf("ax25_sendCall:call=%s\r\n", addr->call);
//#endif
uint16_t i;
uint8_t ssid;
uint16_t len = MIN(sizeof(addr->call), strlen(addr->call));
for (i = 0; i < len; i++)
{
uint8_t c = addr->call[i];
// c = toupper(c); /////////////////////////////////////////////
ax25_putchar(ctx, c << 1);
}
if (len < sizeof(addr->call))
{
for (i = 0; i < sizeof(addr->call) - len; i++)
{
ax25_putchar(ctx, ' ' << 1);
}
}
ssid = 0x60 | (addr->ssid << 1) | (last ? 0x01 : 0);
ax25_putchar(ctx, ssid);
}
/*********************************************************************************************************************/
void ax25_sendVia(AX25Ctx *ctx, const AX25Call *path, uint16_t path_len, const void *_buf, uint16_t len) {
/*********************************************************************************************************************/
uint16_t i;
uint8_t crcl,crch;
const uint8_t *buf = (const uint8_t *)_buf;
ctx->crc_out = CRC_CCITT_INIT_VAL;
fifo_putc(HDLC_FLAG, &ctx->afsk->tx_fifo);
for (i = 0; i < path_len; i++)
{
ax25_sendCall(ctx, &path[i], (i == path_len - 1));
}
ax25_putchar(ctx, AX25_CTRL_UI);
ax25_putchar(ctx, AX25_PID_NOLAYER3);
while (len--)
{
ax25_putchar(ctx, *buf++);
}
crcl = (ctx->crc_out & 0xff) ^ 0xff;
crch = (ctx->crc_out >> 8) ^ 0xff;
ax25_putchar(ctx, crcl);
ax25_putchar(ctx, crch);
fifo_putc(HDLC_FLAG, &ctx->afsk->tx_fifo);
}
uint16_t ax25_sendVia_toBuffer(const AX25Call *path, uint16_t path_len, const void *payload, uint16_t payload_len, uint8_t* output_buf, uint16_t output_size) {
uint16_t i;
uint8_t crcl,crch;
uint16_t crc = CRC_CCITT_INIT_VAL;
const uint8_t *buf = (const uint8_t *)payload;
uint16_t return_val = 0;
kiss_reset_buffer(output_buf, output_size, &return_val);
for (i = 0; i < path_len; i++)
{
kiss_put_call(&path[i], (i == path_len - 1), output_buf, output_size, &return_val, &crc);
}
kiss_put_char(AX25_CTRL_UI, output_buf, output_size, &return_val, &crc);
kiss_put_char(AX25_PID_NOLAYER3, output_buf, output_size, &return_val, &crc);
while (payload_len--)
{
kiss_put_char(*buf++, output_buf, output_size, &return_val, &crc);
}
kiss_finalize_buffer(output_buf, output_size, &return_val);
return return_val;
}
/*********************************************************************************************************************/
void ax25_sendRaw(AX25Ctx *ctx, const void *_buf, uint16_t len) {
/*********************************************************************************************************************/
const uint8_t *buf = (const uint8_t *)_buf;
uint8_t crcl,crch;
ctx->crc_out = CRC_CCITT_INIT_VAL;
fifo_putc(HDLC_FLAG, &ctx->afsk->tx_fifo);
while (len--) ax25_putchar(ctx, *buf++);
crcl = (ctx->crc_out & 0xff) ^ 0xff;
crch = (ctx->crc_out >> 8) ^ 0xff;
ax25_putchar(ctx, crcl);
ax25_putchar(ctx, crch);
fifo_putc(HDLC_FLAG, &ctx->afsk->tx_fifo);
}
/*********************************************************************************************************************/
void ax25_init(AX25Ctx *ctx, Afsk *afsk, bool raw, ax25_callback_t hook) {
/*********************************************************************************************************************/
memset(ctx, 0, sizeof(*ctx));
ctx->afsk = afsk;
ctx->raw = raw;
ctx->hook = hook;
ctx->crc_in = ctx->crc_out = CRC_CCITT_INIT_VAL;
}