mirror of
https://github.com/dj0abr/SSB_HighSpeed_Modem.git
synced 2024-11-25 21:58:41 -05:00
231 lines
6.3 KiB
C
231 lines
6.3 KiB
C
/*
|
|
* High Speed modem to transfer data in a 2,7kHz SSB channel
|
|
* =========================================================
|
|
* Author: DJ0ABR
|
|
*
|
|
* (c) DJ0ABR
|
|
* www.dj0abr.de
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*
|
|
*/
|
|
|
|
#include "qo100modem.h"
|
|
|
|
int AddHeader(uint8_t *data, int len, char *filename);
|
|
uint8_t *zipArray(uint8_t *data, int length, int *ziplen);
|
|
|
|
#define ZIPPED
|
|
#define TXMAXSIZE 200000
|
|
uint8_t TXarray[TXMAXSIZE];
|
|
int txlen; // total length of TXarray
|
|
int txpos; // current position in TXarray
|
|
uint8_t txtype = 0; // file type (from GUI)
|
|
uint8_t filestat = 0; // 0=first frame, 1=next frame, 2=last frame
|
|
|
|
/*
|
|
* start sending a named byte array
|
|
* data ... contents of the Byte array
|
|
* length ... length of the Byte array
|
|
* type ... type of the file (see statics)
|
|
* filename ... description of the file or its name which is send with the data
|
|
*/
|
|
|
|
|
|
int arraySend(uint8_t *data, int length, uint8_t type, char *filename)
|
|
{
|
|
if((length+55) >= TXMAXSIZE)
|
|
{
|
|
printf("file TOO long. Max is %d byte\n",TXMAXSIZE);
|
|
return 0;
|
|
}
|
|
|
|
txtype = type;
|
|
txpos = 0;
|
|
filestat = 0;
|
|
|
|
// if it is an ASCII, HTML or binary file, zip it
|
|
if(type == 3 || type == 4 || type == 5)
|
|
{
|
|
#ifdef ZIPPED
|
|
int ziplen = 0;
|
|
printf("orig len:%d\n",length);
|
|
uint8_t *zipdata = zipArray(data,length,&ziplen);
|
|
if(zipdata==NULL) return 0;
|
|
printf("zipped len:%d\n",ziplen);
|
|
// add a file header and copy to txdata for transmission
|
|
txlen = AddHeader(zipdata,ziplen,filename);
|
|
#else
|
|
txlen = AddHeader(data,length,filename);
|
|
#endif
|
|
printf("txlen:%d\n",txlen);
|
|
}
|
|
else
|
|
{
|
|
// add a file header and copy to txdata for transmission
|
|
txlen = AddHeader(data,length,filename);
|
|
}
|
|
|
|
// marker, we are sending
|
|
setSending(1);
|
|
return 1;
|
|
}
|
|
|
|
int AddHeader(uint8_t *data, int len, char *filename)
|
|
{
|
|
// make a unique ID number for this file
|
|
// we simply calc the CRC16 of the filename
|
|
uint16_t fncrc = Crc16_messagecalc(CRC16FILE, (uint8_t *)filename,strlen(filename));
|
|
|
|
// create the file header
|
|
// 50 bytes ... Filename (or first 50 chars of the filename)
|
|
// 2 bytes .... CRC16 od the filename, this is used as a file ID
|
|
// 3 bytes .... size of file
|
|
|
|
int flen = strlen(filename);
|
|
if (flen > 50) flen = 50;
|
|
memcpy(TXarray,filename,flen);
|
|
|
|
TXarray[50] = (uint8_t)((fncrc >> 8)&0xff);
|
|
TXarray[51] = (uint8_t)(fncrc&0xff);
|
|
|
|
TXarray[52] = len >> 16;
|
|
TXarray[53] = len >> 8;
|
|
TXarray[54] = len;
|
|
|
|
memcpy(TXarray+55,data,len);
|
|
|
|
return len+55;
|
|
}
|
|
|
|
// called from main() in a loop
|
|
// sends an array if specified by arraySend(..)
|
|
void doArraySend()
|
|
{
|
|
if(getSending() == 0) return;
|
|
|
|
if(filestat == 0)
|
|
{
|
|
// send first frame
|
|
printf("Start Array Send %d\n",getSending());
|
|
|
|
// preamble
|
|
int numframespreamble = 3* ((caprate/txinterpolfactor) * bitsPerSymbol / 8) /258 + 1;
|
|
for(int i=0; i<numframespreamble; i++)
|
|
toGR_sendData(TXarray, txtype, filestat);
|
|
|
|
if(txlen <= PAYLOADLEN)
|
|
{
|
|
// we just need to send one frame
|
|
printf("send last frame only\n");
|
|
toGR_sendData(TXarray, txtype, 3);
|
|
toGR_sendData(TXarray, txtype, 3);
|
|
setSending(0);
|
|
}
|
|
else
|
|
{
|
|
printf("send first frame\n");
|
|
// data is longer than one PAYLOAD
|
|
toGR_sendData(TXarray, txtype, filestat);
|
|
txpos += PAYLOADLEN;
|
|
filestat = 1;
|
|
}
|
|
return;
|
|
}
|
|
|
|
if(filestat == 1)
|
|
{
|
|
// check if this is the last frame
|
|
int restlen = txlen - txpos;
|
|
if(restlen <= PAYLOADLEN)
|
|
{
|
|
// send as the last frame
|
|
printf("send last frame\n");
|
|
toGR_sendData(TXarray+txpos, txtype, 2);
|
|
toGR_sendData(TXarray+txpos, txtype, 2);
|
|
setSending(0); // transmission complete
|
|
}
|
|
else
|
|
{
|
|
// additional frame follows
|
|
printf("send next frame\n");
|
|
// from txdata send one chunk of length PAYLOADLEN
|
|
toGR_sendData(TXarray+txpos, txtype, filestat);
|
|
txpos += PAYLOADLEN;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
// make _arraySending flag thread safe
|
|
// it is called from main() and from udp-RX
|
|
pthread_mutex_t as_crit_sec;
|
|
#define AS_LOCK pthread_mutex_lock(&as_crit_sec)
|
|
#define AS_UNLOCK pthread_mutex_unlock(&as_crit_sec)
|
|
|
|
int __arraySending = 0; // 1 ... Array transmission in progress
|
|
|
|
void setSending(uint8_t onoff)
|
|
{
|
|
AS_LOCK;
|
|
__arraySending = onoff;
|
|
AS_UNLOCK;
|
|
}
|
|
|
|
int getSending()
|
|
{
|
|
int as;
|
|
AS_LOCK;
|
|
if(__arraySending != 0)
|
|
printf("__arraySending: %d\n",__arraySending);
|
|
as = __arraySending;
|
|
AS_UNLOCK;
|
|
return as;
|
|
}
|
|
|
|
#define defaultTXzipFN "tmp.zip"
|
|
|
|
uint8_t *zipArray(uint8_t *data, int length, int *ziplen)
|
|
{
|
|
int err = 0;
|
|
unlink(defaultTXzipFN); // delete existing zip file
|
|
struct zip *zp = zip_open(defaultTXzipFN, ZIP_CREATE, &err);
|
|
|
|
zip_source_t *s;
|
|
if ((s=zip_source_buffer(zp, data, length, 0)) == NULL ||
|
|
zip_file_add(zp, "my2databuffer", s, ZIP_FL_ENC_UTF_8) < 0)
|
|
{
|
|
zip_source_free(s);
|
|
printf("error adding file: %s\n", zip_strerror(zp));
|
|
return NULL;
|
|
}
|
|
|
|
zip_close(zp);
|
|
|
|
// zip file is done
|
|
// now read the file and return the buffer
|
|
#define TXMAXSIZE 200000
|
|
static uint8_t ZIPdata[TXMAXSIZE];
|
|
FILE *fp=fopen(defaultTXzipFN,"rb");
|
|
if(fp)
|
|
{
|
|
*ziplen = fread(ZIPdata,1,TXMAXSIZE,fp);
|
|
fclose(fp);
|
|
return ZIPdata;
|
|
}
|
|
|
|
return NULL;
|
|
}
|