kopia lustrzana https://github.com/sp9skp/spdxl
409 wiersze
10 KiB
C
409 wiersze
10 KiB
C
/*
|
|
* dxlAPRS toolchain
|
|
*
|
|
* Copyright (C) Christian Rabler <oe5dxl@oevsv.at>
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0+
|
|
*/
|
|
/* "@(#)frameio.c May 10 23:20:08 2017" */
|
|
|
|
|
|
#define X2C_int32
|
|
#define X2C_index32
|
|
#ifndef frameio_H_
|
|
#include "frameio.h"
|
|
#endif
|
|
#define frameio_C_
|
|
#ifndef l2_H_
|
|
#include "l2.h"
|
|
#endif
|
|
#ifndef osi_H_
|
|
#include "osi.h"
|
|
#endif
|
|
#ifndef udp_H_
|
|
#include "udp.h"
|
|
#endif
|
|
#ifndef aprsstr_H_
|
|
#include "aprsstr.h"
|
|
#endif
|
|
|
|
|
|
|
|
char frameio_crcok;
|
|
struct frameio_UDPSOCK frameio_udpsocks0[15];
|
|
#define frameio_DCDRETRIES 500
|
|
|
|
static uint32_t size;
|
|
|
|
static uint32_t from;
|
|
|
|
static uint32_t udppos;
|
|
|
|
static char axv2;
|
|
|
|
static char udpbuf[1601];
|
|
|
|
|
|
struct _0 {
|
|
uint32_t lastBaud; /*insert flags if baud change*/
|
|
uint32_t oldi; /*last received frame index from hardware*/
|
|
uint32_t nextfrom; /*read next frame from hardware*/
|
|
uint32_t txakku; /*send next frame to hardware*/
|
|
char twoflags;
|
|
};
|
|
|
|
/*
|
|
VAR CRCL, CRCH:ARRAY[0..255] OF SET8;
|
|
|
|
PROCEDURE CRC(VAR frame:ARRAY OF CHAR; VAR crc:CARD16; size:CARDINAL);
|
|
VAR l,h:SET8;
|
|
b:CARD8;
|
|
i:INTEGER;
|
|
BEGIN
|
|
l:=CAST(SET8, crc);
|
|
h:=CAST(SET8, crc >> 8);
|
|
FOR i:=0 TO VAL(INTEGER, size)-1 DO
|
|
b:=CAST(CARD8, CAST(SET8, frame[i]) / l);
|
|
l:=CRCL[b] / h;
|
|
h:=CRCH[b];
|
|
END;
|
|
crc:=CAST(CARD16, l) + (CAST(CARD16, h) << 8);
|
|
END CRC;
|
|
|
|
|
|
|
|
PROCEDURE UDPCRC(frame-:ARRAY OF CHAR; size:INTEGER):CARDINAL;
|
|
VAR l,h:SET8;
|
|
b:CARD8;
|
|
i:INTEGER;
|
|
BEGIN
|
|
l:=SET8{};
|
|
h:=SET8{};
|
|
FOR i:=0 TO size-1 DO
|
|
b:=CAST(CARD8, CAST(SET8, frame[i]) / l);
|
|
l:=CRCL[b] / h;
|
|
h:=CRCH[b];
|
|
END;
|
|
RETURN ORD(CAST(CHAR, l))+256*ORD(CAST(CHAR, h))
|
|
END UDPCRC;
|
|
*/
|
|
/*
|
|
PROCEDURE opensock(num:CARDINAL; fromport, toport:UDPPORT):BOOLEAN;
|
|
BEGIN
|
|
WITH udpsocks[num] DO
|
|
fd:=openudp();
|
|
IF (CAST(INTEGER,fd)<0) OR (bindudp(fd,
|
|
fromport)<0) THEN RETURN FALSE END;
|
|
dport:=toport;
|
|
END;
|
|
RETURN TRUE
|
|
END opensock;
|
|
*/
|
|
|
|
static void rmnc(void)
|
|
{
|
|
uint32_t k;
|
|
uint32_t j;
|
|
char cmd;
|
|
l2_adress[14U] = l2_adress[7U];
|
|
l2_asize = 15U;
|
|
k = (uint32_t)(uint8_t)l2_adress[0U]*128UL+(uint32_t)(uint8_t)
|
|
l2_adress[1U]/2UL;
|
|
cmd = (char)(k&1);
|
|
k = k/2UL;
|
|
j = 12UL;
|
|
do {
|
|
l2_adress[j] = (char)((k%10UL+48UL)*2UL);
|
|
--j;
|
|
k = k/10UL;
|
|
} while (j!=6UL);
|
|
if (cmd) l2_adress[13U] = '`';
|
|
else l2_adress[13U] = '\340';
|
|
j = (uint32_t)(uint8_t)l2_adress[2U];
|
|
l2_adress[0U] = (char)((j/4UL)*2UL+64UL);
|
|
k = (uint32_t)(uint8_t)l2_adress[3U];
|
|
l2_adress[1U] = (char)(((j&3UL)*16UL+k/16UL+32UL)*2UL);
|
|
j = (uint32_t)(uint8_t)l2_adress[4U];
|
|
l2_adress[2U] = (char)(((k&15UL)*4UL+j/64UL+32UL)*2UL);
|
|
l2_adress[3U] = (char)(((j&63UL)+32UL)*2UL);
|
|
j = (uint32_t)(uint8_t)l2_adress[5U];
|
|
l2_adress[4U] = (char)((j/4UL)*2UL+64UL);
|
|
k = (uint32_t)(uint8_t)l2_adress[6U];
|
|
l2_adress[5U] = (char)(((j&3UL)*16UL+k/16UL+32UL)*2UL);
|
|
l2_adress[6U] = (char)(((k&15UL)+48UL)*2UL+(uint32_t)cmd*128UL);
|
|
} /* end rmnc() */
|
|
|
|
|
|
static char GetAField(uint32_t port)
|
|
{
|
|
uint32_t a;
|
|
uint32_t j;
|
|
uint32_t i;
|
|
char c;
|
|
uint32_t tmp;
|
|
if (size>=10UL) {
|
|
if (size>=70UL) a = 70UL;
|
|
else a = size;
|
|
udppos = 0UL;
|
|
tmp = a-1UL;
|
|
i = 0UL;
|
|
if (i<=tmp) for (;; i++) {
|
|
c = udpbuf[udppos];
|
|
++udppos;
|
|
l2_adress[i] = c;
|
|
if (((uint32_t)(uint8_t)c&1)) {
|
|
/*address end mark*/
|
|
if (i==1UL) {
|
|
for (j = 2UL; j<=6UL; j++) {
|
|
l2_adress[j] = udpbuf[udppos];
|
|
++udppos;
|
|
} /* end for */
|
|
l2_asize = 7U;
|
|
}
|
|
else l2_asize = (uint16_t)(i+1UL);
|
|
/*WrInt(asize, 4); WrStrLn("=as"); */
|
|
if ((l2_asize>=7U && l2_asize%7U==0U) && (uint32_t)
|
|
l2_asize<=size) {
|
|
l2_adress[l2_asize] = udpbuf[udppos]; /*command*/
|
|
++udppos;
|
|
++l2_asize;
|
|
size -= (uint32_t)l2_asize;
|
|
/*WrInt(size, 4); WrStrLn("=saf"); */
|
|
/*FOR j:=0 TO asize-1 DO WrInt(ORD(adress[j]), 4); END;
|
|
WrStrLn("=af"); */
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
if (i==tmp) break;
|
|
} /* end for */
|
|
}
|
|
return 0;
|
|
} /* end GetAField() */
|
|
|
|
|
|
static char GetDField(void)
|
|
{
|
|
int32_t i;
|
|
struct l2_DFIELD * anonym;
|
|
int32_t tmp;
|
|
if (size<=257UL) {
|
|
{ /* with */
|
|
struct l2_DFIELD * anonym = l2_dbuf;
|
|
anonym->len = (uint16_t)size;
|
|
/*WrInt(len, 4); WrStrLn("=ilen"); */
|
|
tmp = (int32_t)size-1L;
|
|
i = 0L;
|
|
if (i<=tmp) for (;; i++) {
|
|
anonym->info[i] = udpbuf[udppos];
|
|
++udppos;
|
|
if (i==tmp) break;
|
|
} /* end for */
|
|
/*
|
|
crc:=0;
|
|
CRC(adress,crc,asize);
|
|
IF len<>0 THEN CRC(info,crc,len) END;
|
|
crcok:=ORD(udpbuf[udppos]) + (ORD(udpbuf[udppos+1]) << 8)
|
|
= crc;
|
|
*/
|
|
frameio_crcok = 1;
|
|
if (l2_asize==8U) rmnc();
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
} /* end GetDField() */
|
|
|
|
|
|
static void getudp(uint32_t usock, char buf[], uint32_t buf_len,
|
|
int32_t * len)
|
|
{
|
|
uint32_t fromport;
|
|
uint32_t ipn;
|
|
char crc2;
|
|
char crc1;
|
|
*len = -1L;
|
|
if ((int32_t)frameio_udpsocks0[usock].fd<0L) return;
|
|
*len = udpreceive(frameio_udpsocks0[usock].fd, buf, (int32_t)(buf_len),
|
|
&fromport, &ipn);
|
|
if ((*len>2L && *len<(int32_t)(buf_len))
|
|
&& (!frameio_udpsocks0[usock]
|
|
.checkip || frameio_udpsocks0[usock].ipnum==ipn)) {
|
|
/*WrInt(udpsend(usock^.fd, buf, len, usock^.dport, usock^.ip), 1);
|
|
WrStrLn(" us"); */
|
|
*len -= 2L;
|
|
crc1 = buf[*len];
|
|
crc2 = buf[*len+1L];
|
|
aprsstr_AppCRC(buf, buf_len, *len);
|
|
if (crc1!=buf[*len] || crc2!=buf[*len+1L]) {
|
|
osi_WrStrLn(" axudp crc error", 17ul);
|
|
*len = -1L;
|
|
return;
|
|
}
|
|
if (buf[0UL]=='\001') {
|
|
aprsstr_extrudp2(buf, buf_len, l2_udp2buf, 100ul, len);
|
|
if (l2_udp2buf[1U]!='?') {
|
|
frameio_udpsocks0[usock].dcd = ((uint8_t)(uint8_t)
|
|
l2_udp2buf[1U]&0x2U)!=0U;
|
|
frameio_udpsocks0[usock].hastxdata = ((uint8_t)(uint8_t)
|
|
l2_udp2buf[1U]&0x4U)!=0U;
|
|
}
|
|
if (*len==0L) *len = -1L;
|
|
axv2 = 1;
|
|
}
|
|
else {
|
|
/*WrStr("<");WrStr(udp2buf); WrStrLn(">"); */
|
|
l2_udp2buf[0U] = 0;
|
|
frameio_udpsocks0[usock].dcd = 0;
|
|
frameio_udpsocks0[usock].hastxdata = 0;
|
|
axv2 = 0;
|
|
}
|
|
}
|
|
else *len = -1L;
|
|
} /* end getudp() */
|
|
|
|
|
|
extern char frameio_GetFrame(uint32_t port)
|
|
{
|
|
int32_t i;
|
|
if (port==0UL) return 0;
|
|
getudp(port-1UL, udpbuf, 1601ul, &i);
|
|
if (i<0L) return 0;
|
|
/*WrInt(i, 5); WrStrLn("=udpin"); */
|
|
size = (uint32_t)i;
|
|
from = 0UL;
|
|
if (GetAField(port) && GetDField()) return 1;
|
|
return 0;
|
|
} /* end GetFrame() */
|
|
|
|
|
|
extern void frameio_Modempoll(uint32_t tport)
|
|
{
|
|
char b[100];
|
|
int32_t ret;
|
|
/*WrStrLn("send ?"); */
|
|
struct frameio_UDPSOCK * anonym;
|
|
if (tport==0UL || tport>15UL) return;
|
|
b[0U] = '\001';
|
|
b[1U] = '?';
|
|
b[2U] = 0;
|
|
aprsstr_AppCRC(b, 100ul, 3L);
|
|
{ /* with */
|
|
struct frameio_UDPSOCK * anonym = &frameio_udpsocks0[tport-1UL];
|
|
ret = udpsend(anonym->fd, b, 5L, anonym->toport, anonym->ipnum);
|
|
}
|
|
} /* end Modempoll() */
|
|
|
|
|
|
extern char frameio_DCD(uint32_t port)
|
|
{
|
|
struct frameio_UDPSOCK * anonym;
|
|
if (port==0UL || port-1UL>14UL) return 0;
|
|
{ /* with */
|
|
struct frameio_UDPSOCK * anonym = &frameio_udpsocks0[port-1UL];
|
|
if (anonym->dcd) {
|
|
if (anonym->dcdretry>500UL) {
|
|
frameio_Modempoll(port);
|
|
anonym->dcdretry = 0UL;
|
|
}
|
|
else ++anonym->dcdretry;
|
|
}
|
|
else anonym->dcdretry = 0UL;
|
|
/*IF dcd THEN WrStrLn("dcd") END; */
|
|
return anonym->dcd;
|
|
}
|
|
} /* end DCD() */
|
|
|
|
|
|
extern char frameio_Sending(uint32_t port)
|
|
{
|
|
struct frameio_UDPSOCK * anonym;
|
|
if (port==0UL || port-1UL>14UL) return 0;
|
|
{ /* with */
|
|
struct frameio_UDPSOCK * anonym = &frameio_udpsocks0[port-1UL];
|
|
if (anonym->hastxdata) {
|
|
if (anonym->txbufretry>500UL) {
|
|
frameio_Modempoll(port);
|
|
anonym->txbufretry = 0UL;
|
|
}
|
|
else ++anonym->txbufretry;
|
|
}
|
|
else {
|
|
/*WrStr("txbufretry:");WrInt(txbufretry, 1);WrStrLn(""); */
|
|
anonym->txbufretry = 0UL;
|
|
}
|
|
/*IF hastxdata THEN WrStrLn("txing") END; */
|
|
return anonym->hastxdata;
|
|
}
|
|
} /* end Sending() */
|
|
|
|
|
|
extern void frameio_SendFrame(uint32_t tport, uint32_t Baud,
|
|
char Adress[], uint32_t Adress_len, uint32_t AdrLen,
|
|
l2_pDATA dp)
|
|
{
|
|
uint32_t j;
|
|
uint32_t i;
|
|
char b[351];
|
|
int32_t ret;
|
|
struct frameio_UDPSOCK * anonym;
|
|
uint32_t tmp;
|
|
if ((tport==0UL || tport>15UL) || AdrLen>=350UL) return;
|
|
--tport;
|
|
j = 0UL;
|
|
tmp = AdrLen-1UL;
|
|
i = 0UL;
|
|
if (i<=tmp) for (;; i++) {
|
|
b[j] = Adress[i];
|
|
++j;
|
|
if (i==tmp) break;
|
|
} /* end for */
|
|
if (dp) {
|
|
tmp = (uint32_t)(dp->len-1U);
|
|
i = 0UL;
|
|
if (i<=tmp) for (;; i++) {
|
|
b[j] = dp->info[i];
|
|
++j;
|
|
if (i==tmp) break;
|
|
} /* end for */
|
|
}
|
|
aprsstr_AppCRC(b, 351ul, (int32_t)j);
|
|
{ /* with */
|
|
struct frameio_UDPSOCK * anonym = &frameio_udpsocks0[tport];
|
|
ret = udpsend(anonym->fd, b, (int32_t)(j+2UL), anonym->toport,
|
|
anonym->ipnum);
|
|
anonym->hastxdata = axv2;
|
|
}
|
|
} /* end SendFrame() */
|
|
|
|
|
|
extern void frameio_Init(void)
|
|
{
|
|
axv2 = 0;
|
|
/* FILL(ADR(udpsocks), 0C, SIZE(udpsocks)); */
|
|
/* udpsocks[0].ip:=7F000001H; */
|
|
/* IF NOT opensock(0, 5603, 5602) THEN WrStrLn("socket open error");
|
|
HALT END; */
|
|
/* udpsocks[0].ip:=44<<24 + 143<<16 + 40<<8 + 90; */
|
|
/* IF NOT opensock(0, 10094, 10094) THEN WrStrLn("socket open error");
|
|
HALT END; */
|
|
/* udpsocks[0].ip:=192<<24 + 168<<16 + 1<<8 + 30; */
|
|
/* IF NOT opensock(0, 11000, 11001) THEN WrStrLn("socket open error");
|
|
HALT END; */
|
|
/* udpsocks[0].ip:=127<<24 + 0<<16 + 0<<8 + 1; */
|
|
/* IF NOT opensock(0, 2603, 2602) THEN WrStrLn("socket open error");
|
|
HALT END; */
|
|
} /* end Init() */
|
|
|
|
|
|
extern void frameio_BEGIN(void)
|
|
{
|
|
static int frameio_init = 0;
|
|
if (frameio_init) return;
|
|
frameio_init = 1;
|
|
l2_BEGIN();
|
|
aprsstr_BEGIN();
|
|
osi_BEGIN();
|
|
}
|
|
|