SSB_HighSpeed_Modem/oscardata/oscardata/ArraySend.cs

209 lines
7.1 KiB
C#
Executable File

using System;
using System.Threading;
// Input: Byte Array
// Action: sends this byte array to the modem
namespace oscardata
{
public static class ArraySend
{
static Timer TTimer;
static Byte[] txdata;
static int txlen;
public static int txpos;
static Byte txtype;
static bool sending = false;
public static Byte filestat = statics.noTX;
static private readonly object busyLock = new object();
static int timeout_period_ms = 10;
static UInt16 fncrc;
// start a timer which is used to send a file from txdata
public static void ArraySendInit()
{
TTimer = new Timer(new TimerCallback(TimerTick), 0, 0, timeout_period_ms);
}
static void setSending(bool v)
{
lock(busyLock)
{
sending = v;
if (v == false)
filestat = statics.LastFrame;
}
}
public static bool getSending()
{
bool v;
lock (busyLock)
{
v = sending;
}
return v;
}
/*
* start sending a file
* data ... contents of the file in a Byte array
* type ... type of the file (see statics)
* filename ... description of the file or its name (payload length max)
*/
public static bool Send(Byte[] data, Byte type, String filename, String RealFileName)
{
// check if already sending
if (getSending()) return false;
txtype = type;
txpos = 0;
filestat = statics.FirstFrame;
// add a file header and copy to txdata for transmission
AddHeader(data,filename, RealFileName);
// marker, we are sending
txlen = txdata.Length;
setSending(true);
return true;
}
public static void stopSending()
{
setSending(false);
}
static void AddHeader(Byte[] data, String filename, String realname)
{
long filesize = data.Length;// statics.GetFileSize(filename);
Byte[] fnarr = statics.StringToByteArray(realname);
// CRC16 over complete file contents is the file ID
Crc c = new Crc();
fncrc = c.crc16_messagecalc(data, data.Length);
// 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
Byte[] header = new Byte[55];
int len = fnarr.Length;
if (len > 50) len = 50;
Array.Copy(fnarr, header, len);
header[50] = (Byte)((fncrc >> 8)&0xff);
header[51] = (Byte)(fncrc&0xff);
header[52] = (Byte)((filesize >> 16) & 0xff);
header[53] = (Byte)((filesize >> 8) & 0xff);
header[54] = (Byte)(filesize & 0xff);
txdata = new Byte[data.Length + header.Length];
Array.Copy(header, txdata, header.Length);
Array.Copy(data, 0, txdata, header.Length, data.Length);
}
public static String rxFilename;
public static int FileID;
public static int FileSize;
public static Byte[] GetAndRemoveHeader(Byte[] data)
{
try
{
Byte[] fnarr = new byte[50];
Array.Copy(data, fnarr, 50);
rxFilename = statics.ByteArrayToString(fnarr);
FileID = data[50];
FileID <<= 8;
FileID += data[51];
FileSize = data[52];
FileSize <<= 8;
FileSize += data[53];
FileSize <<= 8;
FileSize += data[54];
Byte[] f = new byte[data.Length - 55];
Array.Copy(data, 55, f, 0, data.Length - 55);
return f;
}
catch { }
return null;
}
// runs every 10 ms to send a file
static void TimerTick(object stateInfo)
{
// check if we need to send something
if (getSending() == false) return; // nothing to send
// check the TX buffer, do not feed more data into
// the buffer if it has already more than 10 entries
if (Udp.GetBufferCount() > 3) return;
Byte[] txarr = new byte[statics.PayloadLen];
// check if txdata is smaller or equal one payload
if (filestat == statics.FirstFrame)
{
// send the first frame
if (txlen <= statics.PayloadLen)
{
// we just need to send one frame
txudp(txdata, txtype, statics.SingleFrame);
setSending(false); // transmission complete
}
else
{
// additional frame follows
// from txdata send one chunk of length statics.PayloadLen
// frame is repeated for preamble by hsmodem.cpp
Array.Copy(txdata, 0, txarr, 0, statics.PayloadLen);
txudp(txarr, txtype, statics.FirstFrame);
txpos = statics.PayloadLen;
filestat = statics.NextFrame;
}
return;
}
if (filestat == statics.NextFrame)
{
// check if this is the last frame
int restlen = txlen - txpos;
if(restlen <= statics.PayloadLen)
{
// send as the last frame
Array.Copy(txdata, txpos, txarr, 0, restlen); // unused byte will be 0
// send the last frame a couple of times (see hsmodem.cpp)
txudp(txarr, txtype, statics.LastFrame);
setSending(false); // transmission complete
}
else
{
// additional frame follows
// from txdata send one chunk of length statics.PayloadLen
Array.Copy(txdata, txpos, txarr, 0, statics.PayloadLen);
txudp(txarr, txtype, statics.NextFrame);
txpos += statics.PayloadLen;
}
return;
}
}
static void txudp(Byte[] txdata, Byte txtype, Byte filestat)
{
// add the txtype and filestatus at the beginning
Byte[] darr = new byte[statics.PayloadLen + 2];
darr[0] = txtype;
darr[1] = filestat;
Array.Copy(txdata, 0, darr, 2, statics.PayloadLen);
Udp.UdpSendData(darr);
// Console.WriteLine("TX filestat: " + filestat+ " data:" + darr[2].ToString("X2") + " " + darr[3].ToString("X2"));
}
}
}