using System; using System.Runtime.InteropServices; 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; // 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); Crc c = new Crc(); UInt16 fncrc = c.crc16_messagecalc(fnarr, fnarr.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 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.LastFrame); setSending(false); // transmission complete } else { // additional frame follow // from txdata send one chunk of length statics.PayloadLen 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 txudp(txarr, txtype, statics.LastFrame); 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 tytype 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.UdpSend(darr); // Console.WriteLine("TX filestat: " + filestat+ " data:" + darr[2].ToString("X2") + " " + darr[3].ToString("X2")); } } }