209 lines
7.1 KiB
C#
Executable File
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"));
|
|
}
|
|
}
|
|
}
|