spdxl/src/frameio.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();
}