/* * 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. * */ using System; using System.Windows.Forms; using System.Drawing; using System.Text; using System.IO; using System.Drawing.Drawing2D; using System.Diagnostics; namespace oscardata { public partial class Form1 : Form { Imagehandler ih = new Imagehandler(); int txcommand = 0; // commands what to send int txframecounter = 0; Byte frameinfo = (Byte)statics.FirstFrame; String TXfilename; int rxbytecounter = 0; DateTime starttime; String old_tsip = ""; public Form1() { // init GUI InitializeComponent(); // test OS type OperatingSystem osversion = System.Environment.OSVersion; statics.OSversion = osversion.Platform.ToString(); if (osversion.VersionString.Contains("indow")) statics.ostype = 0; else statics.ostype = 1; // Linux // set temp paths statics.zip_TXtempfilename = statics.addTmpPath(statics.zip_TXtempfilename); statics.zip_RXtempfilename = statics.addTmpPath(statics.zip_RXtempfilename); statics.jpg_tempfilename = statics.addTmpPath(statics.jpg_tempfilename); load_Setup(); checkBox_small_CheckedChanged(null, null); // init speed comboBox1_SelectedIndexChanged(null,null); // create Udp Communication ports and init UDP system Udp.InitUdp(); search_modem(); ArraySend.ArraySendInit(); // enable processing timer_udpTX.Enabled = true; timer_udprx.Enabled = true; timer_searchmodem.Enabled = true; //pictureBox_rximage.BackgroundImage = Image.FromFile("/tmp/temp293.jpg"); } // TX timer int loopdelay = 0; private void timer1_Tick(object sender, EventArgs e) { // BER testdata if (txcommand == statics.BERtest) { if (Udp.GetBufferCount() > 3) return; Byte[] txdata = new byte[statics.PayloadLen+2]; txdata[0] = (Byte)statics.BERtest; // BER Test Marker txdata[1] = frameinfo; Byte tb = (Byte)'A'; for (int i = 2; i < txdata.Length; i++) { txdata[i] = tb; tb++; if (tb == 'z') tb = (Byte)'A'; } // and transmit it Udp.UdpSend(txdata); frameinfo = (Byte)statics.NextFrame; txframecounter++; } if (ArraySend.getSending()) { button_loadimage.Enabled = false; button_sendimage.Enabled = false; } else { button_loadimage.Enabled = true; if (TXimagefilename != "") button_sendimage.Enabled = true; else button_sendimage.Enabled = false; } if (TXfoldername == "" || lastFullName == "") cb_loop.Enabled = false; else cb_loop.Enabled = true; ShowTXstatus(); if (txcommand == statics.Image) { // if "loop" is selected send the next image in folder if (cb_loop.Checked) { // check if we are ready with any transmission if (ArraySend.getSending() == false) { // this timer runs with 10ms // after an image was finished, wait before starting the new one // this helps cleaning any buffer int spacetime = 20000; // ms label_nextimage.Text = "next image in " + ((spacetime / timer_udpTX.Interval - loopdelay) / 10).ToString() + " s"; if (++loopdelay > (spacetime / timer_udpTX.Interval)) { // start sending a new picture startNextImage(); } } else { loopdelay = 0; label_nextimage.Text = "transmitting"; } } else label_nextimage.Text = ""; } else label_nextimage.Text = ""; if (ts_ip.Text.Contains("?") || ts_ip.Text.Contains("1.2.3.4") || old_tsip != statics.ModemIP) { if (statics.ModemIP == "1.2.3.4") ts_ip.Text = "Modem-IP: ?"; else { ts_ip.Text = "Modem-IP: " + statics.ModemIP; old_tsip = statics.ModemIP; comboBox1_SelectedIndexChanged(null, null); // send speed to modem } } } private void Form1_FormClosing(object sender, FormClosingEventArgs e) { save_Setup(); // exit the threads statics.running = false; Udp.Close(); } // RX timer int rxstat = 0; int speed; int tmpnum = 0; int file_lostframes = 0; private void timer_udprx_Tick(object sender, EventArgs e) { while (true) { Byte[] rxd = Udp.UdpReceive(); if (rxd == null) break; // these status information are added by the unpack routine int rxtype = rxd[0]; int rxfrmnum = rxd[1]; rxfrmnum <<= 8; rxfrmnum += rxd[2]; int minfo = rxd[3]; rxstat = rxd[4]; speed = rxd[5]; speed <<= 8; speed += rxd[6]; int dummy3 = rxd[7]; int dummy4 = rxd[8]; int dummy5 = rxd[9]; if (rxstat == 4) { framelost++; file_lostframes++; } calcBer(rxfrmnum); if (minfo == statics.FirstFrame) file_lostframes = 0; Byte[] rxdata = new byte[rxd.Length - 10]; Array.Copy(rxd, 10, rxdata, 0, rxd.Length - 10); //Console.WriteLine("minfo:" + minfo + " data:" + rxdata[0].ToString("X2") + " " + rxdata[1].ToString("X2")); if (minfo == statics.FirstFrame) { rxbytecounter = rxdata.Length; starttime = DateTime.UtcNow; } else { rxbytecounter += rxdata.Length; } TimeSpan ts = DateTime.UtcNow - starttime; ts += new TimeSpan(0, 0, 0, 1); // ===== ASCII RX ================================================ if (rxtype == statics.AsciiFile) { // if this is the first frame of a file transfer // then read and remove the file info header if (minfo == statics.FirstFrame || minfo == statics.SingleFrame) { //Console.WriteLine("first, single"); rxdata = ArraySend.GetAndRemoveHeader(rxdata); if (rxdata == null) return; } // collect all received data into zip_RXtempfilename Byte[] ba = null; Byte[] nba; try { ba = File.ReadAllBytes(statics.zip_RXtempfilename); } catch { } if (ba != null) { //Console.WriteLine("write next"); nba = new Byte[ba.Length + rxdata.Length]; Array.Copy(ba, nba, ba.Length); Array.Copy(rxdata, 0, nba, ba.Length, rxdata.Length); } else { //Console.WriteLine("write first"); nba = new Byte[rxdata.Length]; Array.Copy(rxdata, nba, rxdata.Length); } File.WriteAllBytes(statics.zip_RXtempfilename, nba); long filesize = 0; // check if transmission is finished if (minfo == statics.LastFrame || minfo == statics.SingleFrame) { // statics.zip_RXtempfilename has the received data, but maybee too long (multiple of payload length) // reduce for the real file length Byte[] fc = File.ReadAllBytes(statics.zip_RXtempfilename); Byte[] fdst = new byte[ArraySend.FileSize]; Array.Copy(fc, 0, fdst, 0, ArraySend.FileSize); File.WriteAllBytes(statics.zip_RXtempfilename, fdst); //Console.WriteLine("size:"+ ArraySend.FileSize.ToString()); //Console.WriteLine("last"); // unzip received data and store result in file: unzipped_RXtempfilename rtb_RXfile.Text = ""; ZipStorer zs = new ZipStorer(); String fl = zs.unzipFile(statics.zip_RXtempfilename); if (fl != null) { // save file int idx = fl.LastIndexOf('/'); if (idx == -1) idx = fl.LastIndexOf('\\'); String fdest = fl.Substring(idx + 1); fdest = statics.getHomePath("", fdest); try { File.Delete(fdest); } catch { } File.Move(fl, fdest); filesize = statics.GetFileSize(fdest); String serg = File.ReadAllText(fdest); printText(rtb_RXfile, serg); } else printText(rtb_RXfile, "unzip failed"); File.Delete(statics.zip_RXtempfilename); } int rest = ArraySend.FileSize - rxbytecounter; if (rest < 0) rest = 0; if (rest > 0) label_rxfile.Text = "RX file: " + ArraySend.rxFilename + " " + rest.ToString() + " bytes"; else label_rxfile.Text = "RX file: " + ArraySend.rxFilename + " " + filesize + " bytes"; if (minfo == statics.LastFrame) ShowStatus((int)filesize, (int)ts.TotalSeconds); else ShowStatus(rxbytecounter, (int)ts.TotalSeconds); } // ===== HTML File RX ================================================ if (rxtype == statics.HTMLFile) { // if this is the first frame of a file transfer // then read and remove the file info header if (minfo == statics.FirstFrame) { rxdata = ArraySend.GetAndRemoveHeader(rxdata); if (rxdata == null) return; } Byte[] ba = null; Byte[] nba; try { ba = File.ReadAllBytes(statics.zip_RXtempfilename); } catch { } if (ba != null) { nba = new Byte[ba.Length + rxdata.Length]; Array.Copy(ba, nba, ba.Length); Array.Copy(rxdata, 0, nba, ba.Length, rxdata.Length); } else { nba = new Byte[rxdata.Length]; Array.Copy(rxdata, nba, rxdata.Length); } File.WriteAllBytes(statics.zip_RXtempfilename, nba); long filesize = 0; if (minfo == statics.LastFrame) { // unzip received data rtb_RXfile.Text = ""; ZipStorer zs = new ZipStorer(); // unzip returns filename+path of unzipped file String fl = zs.unzipFile(statics.zip_RXtempfilename); if (fl != null) { // save file int idx = fl.LastIndexOf('/'); if (idx == -1) idx = fl.LastIndexOf('\\'); String fdest = fl.Substring(idx + 1); fdest = statics.getHomePath("", fdest); try { File.Delete(fdest); } catch { } File.Move(fl, fdest); filesize = statics.GetFileSize(fdest); rxbytecounter = (int)statics.GetFileSize(fdest); String serg = File.ReadAllText(fdest); printText(rtb_RXfile, serg); try { OpenUrl(fdest); } catch (Exception ex) { Console.WriteLine(ex.ToString()); } } else printText(rtb_RXfile, "unzip failed"); } int rest = ArraySend.FileSize - rxbytecounter; if (rest < 0) rest = 0; if (rest > 0) label_rxfile.Text = "RX file: " + ArraySend.rxFilename + " " + rest.ToString() + " bytes"; else label_rxfile.Text = "RX file: " + ArraySend.rxFilename + " " + filesize + " bytes"; if (minfo == statics.LastFrame) ShowStatus(ArraySend.FileSize, (int)ts.TotalSeconds); else ShowStatus(rxbytecounter, (int)ts.TotalSeconds); } // ===== Binary File RX ================================================ if (rxtype == statics.BinaryFile) { // if this is the first frame of a file transfer // then read and remove the file info header if (minfo == statics.FirstFrame || minfo == statics.SingleFrame) { //Console.WriteLine("first, single"); rxdata = ArraySend.GetAndRemoveHeader(rxdata); if (rxdata == null) return; } // collect all received data into zip_RXtempfilename Byte[] ba = null; Byte[] nba; try { ba = File.ReadAllBytes(statics.zip_RXtempfilename); } catch { } if (ba != null) { //Console.WriteLine("write next"); nba = new Byte[ba.Length + rxdata.Length]; Array.Copy(ba, nba, ba.Length); Array.Copy(rxdata, 0, nba, ba.Length, rxdata.Length); } else { //Console.WriteLine("write first"); nba = new Byte[rxdata.Length]; Array.Copy(rxdata, nba, rxdata.Length); } File.WriteAllBytes(statics.zip_RXtempfilename, nba); long filesize = 0; // check if transmission is finished if (minfo == statics.LastFrame || minfo == statics.SingleFrame) { // statics.zip_RXtempfilename has the received data, but maybee too long (multiple of payload length) // reduce for the real file length Byte[] fc = File.ReadAllBytes(statics.zip_RXtempfilename); Byte[] fdst = new byte[ArraySend.FileSize]; Array.Copy(fc, 0, fdst, 0, ArraySend.FileSize); File.WriteAllBytes(statics.zip_RXtempfilename, fdst); //Console.WriteLine("last"); // unzip received data and store result in file: unzipped_RXtempfilename rtb_RXfile.Text = ""; ZipStorer zs = new ZipStorer(); String fl = zs.unzipFile(statics.zip_RXtempfilename); if (fl != null) { int idx = fl.LastIndexOf('/'); if(idx == -1) idx = fl.LastIndexOf('\\'); String fdest = fl.Substring(idx + 1); fdest = statics.getHomePath("", fdest); try { File.Delete(fdest); } catch { } File.Move(fl, fdest); filesize = statics.GetFileSize(fdest); //File.WriteAllBytes(fl, nba); printText(rtb_RXfile, "binary file received\r\n"); printText(rtb_RXfile, "--------------------\r\n\r\n"); printText(rtb_RXfile, "file size : " + filesize + " byte\r\n\r\n"); printText(rtb_RXfile, "stored in : " + fdest + "\r\n\r\n"); printText(rtb_RXfile, "transmission time : " + ((int)ts.TotalSeconds).ToString() + " seconds" + "\r\n\r\n"); printText(rtb_RXfile, "transmission speed: " + ((int)(filesize*8/ts.TotalSeconds)).ToString() + " bit/s" + "\r\n\r\n"); } else printText(rtb_RXfile, "unzip failed"); File.Delete(statics.zip_RXtempfilename); } int rest = ArraySend.FileSize - rxbytecounter; if (rest < 0) rest = 0; if (rest > 0) label_rxfile.Text = "RX file: " + ArraySend.rxFilename + " " + rest.ToString() + " bytes"; else label_rxfile.Text = "RX file: " + ArraySend.rxFilename + " " + filesize + " bytes"; if (minfo == statics.LastFrame) ShowStatus((int)filesize, (int)ts.TotalSeconds); else ShowStatus(rxbytecounter, (int)ts.TotalSeconds); } // ===== IMAGE RX ================================================ if (rxtype == statics.Image) { // if this is the first frame of a file transfer // then read and remove the file info header if (minfo == statics.FirstFrame) { rxdata = ArraySend.GetAndRemoveHeader(rxdata); if (rxdata == null) return; } ih.receive_image(rxdata, minfo); // show currect contents of rxtemp.jpg in RX picturebox try { String fn = statics.addTmpPath("temp" + tmpnum.ToString() + ".jpg"); try { File.Delete(fn); } catch { } tmpnum++; fn = statics.addTmpPath("temp" + tmpnum.ToString() + ".jpg"); File.Copy(statics.jpg_tempfilename, fn); try { if(statics.GetFileSize(fn) > 1200) pictureBox_rximage.BackgroundImage = Image.FromFile(fn); } catch { } if (minfo == statics.LastFrame) { // file is complete, save in RX storage // remove possible path from filename String fname = ArraySend.rxFilename; int idx = fname.IndexOfAny(new char[] {'\\','/' }); if (idx != -1) { try { fname = fname.Substring(idx + 1); } catch{ } } if (!cb_savegoodfiles.Checked || (file_lostframes == 0 && cb_savegoodfiles.Checked)) { // add home path and RXstorage path String fnx = statics.getHomePath(statics.RXimageStorage, fname); File.Copy(fn, fnx); } } } catch { } int rest = ArraySend.FileSize - rxbytecounter; if (rest < 0) rest = 0; if(rest > 0) label_rximage.Text = "RX image: " + ArraySend.rxFilename + " " + rest.ToString() + " bytes"; else label_rximage.Text = "RX image: " + ArraySend.rxFilename; ShowStatus(rxbytecounter, (int)ts.TotalSeconds); } // ===== BER Test ================================================ if (rxtype == statics.BERtest) { RXstatus.Text = "BER: " + ber.ToString("E3") + " " + rxframecounter.ToString() + " frames received OK"; BERcheck(rxdata); } } } private void OpenUrl(string url) { try { Process.Start(url); } catch { // hack because of this: https://github.com/dotnet/corefx/issues/10361 if (statics.ostype == 0) { url = url.Replace("&", "^&"); Process.Start(new ProcessStartInfo("cmd", $"/c start {url}") { CreateNoWindow = true }); } else { Process.Start("xdg-open", url); } } } private void timer_qpsk_Tick(object sender, EventArgs e) { panel_constel.Invalidate(); panel_txspectrum.Invalidate(); } private void panel_constel_Paint(object sender, PaintEventArgs e) { Pen pen = new Pen(Brushes.LightGray); e.Graphics.DrawEllipse(pen, 0, 0, panel_constel.Size.Width-1, panel_constel.Size.Height-1); e.Graphics.DrawLine(pen, panel_constel.Size.Width / 2, 0, panel_constel.Size.Width / 2, panel_constel.Size.Height); e.Graphics.DrawLine(pen, 0, panel_constel.Size.Height / 2, panel_constel.Size.Width, panel_constel.Size.Height/2); while (true) { qpskitem qi = Udp.UdpGetIQ(); if (qi == null) break; // re and im are in the range of +/- 2^24 (16777216) // scale it to +/- 128 double fre = qi.re; double fim = qi.im; fre = fre * panel_constel.Size.Width / 2 / 16777216.0; fim = fim * panel_constel.Size.Width / 2 / 16777216.0; // scale it to the picture int x = panel_constel.Size.Width / 2 + (int)fre - 2; int y = panel_constel.Size.Height / 2 + (int)fim - 2; e.Graphics.FillEllipse(Brushes.Blue, x, y, 2, 2); } } static Brush brred = new SolidBrush(Color.FromArgb(255, (byte)255, (byte)220, (byte)220)); static Brush brgreen = new SolidBrush(Color.FromArgb(255, (byte)240, (byte)255, (byte)240)); static Brush brgray = new SolidBrush(Color.FromArgb(255, (byte)220, (byte)220, (byte)220)); static Pen pen = new Pen(Brushes.Black); static Pen penblue = new Pen(Brushes.Blue, 2); static Pen pengrey = new Pen(brgray, 1); Font fnt = new Font("Verdana", 8.0f); Font smallfnt = new Font("Verdana", 6.0f); private void panel_txspectrum_Paint(object sender, PaintEventArgs e) { int miny = 200; int maxy = 2800; // horizontal level markers Point ps = GetFFTPos(0, 0); Point pe = GetFFTPos(maxxval, maxyval); int pw = pe.X - ps.X; int ph = ps.Y - pe.Y; e.Graphics.FillRectangle(brred, ps.X, pe.Y, pw, ph); ps = GetFFTPos(miny/10, 700); pe = GetFFTPos(maxy/10, 2300); pw = pe.X - ps.X; ph = ps.Y - pe.Y; e.Graphics.FillRectangle(brgreen, ps.X, pe.Y, pw, ph); // Coordinates e.Graphics.DrawLine(pen, GetFFTPos(0, 0), GetFFTPos(maxxval, 0)); e.Graphics.DrawLine(pen, GetFFTPos(0, 0), GetFFTPos(0, maxyval)); // vertical frequency markers for 2.7kHz for (int i = miny; i <= maxy; i+=100) { e.Graphics.DrawLine(pengrey, GetFFTPos(i / 10, 0), GetFFTPos(i / 10, maxyval)); } // Title e.Graphics.DrawString("Tuning Window", fnt, Brushes.Black, GetFFTPos(110, 3000)); e.Graphics.DrawString(miny.ToString() + " Hz", smallfnt, Brushes.Black, GetFFTPos(5, 2800)); e.Graphics.DrawString("1500 Hz", smallfnt, Brushes.Black, GetFFTPos(138, 680)); e.Graphics.DrawString(maxy.ToString() + " Hz", smallfnt, Brushes.Black, GetFFTPos(270, 2800)); e.Graphics.DrawString("min Level", smallfnt, Brushes.Black, GetFFTPos(290, 1000)); e.Graphics.DrawString("max", smallfnt, Brushes.Black, GetFFTPos(290, 2450)); while (true) { UInt16[] da = Udp.UdpGetFFT(); if (da == null) break; if (da.Length < maxxval) return; Fftmean(da); } // da are the FFT data // from 0 Hz to 4410 Hz with a resolution of 10 Hz // so we get 441 values // there may be 442, just ignore the last one GraphicsPath gp = new GraphicsPath(); // calculate mean value and calc mean value over all values UInt16[] su = new UInt16[maxxval+1]; for (int i = 0; i < maxxval; i++) { su[i] = 0; for(int j=0; j< meansize; j++) su[i] += dam[j, i]; su[i] /= (UInt16)meansize; } // scale and X-mean int lastu = 0; for (int i = 0; i < maxxval; i++) { UInt16 u = 0; if (i >= 1 && i < maxxval - 1) u = (UInt16)((su[i - 1] + su[i] + su[i + 1]) / 3); else u = su[i]; u *= 3; gp.AddLine(GetFFTPos(i, lastu), GetFFTPos(i + 1, u)); lastu = u; } e.Graphics.DrawPath(penblue, gp); } private UInt16[,] dam = new UInt16[meansize, maxxval]; private void Fftmean(UInt16[] v) { for (int sh = meansize - 1; sh > 0; sh--) for (int i = 0; i < maxxval; i++) dam[sh, i] = dam[sh - 1, i]; for (int i = 0; i < maxxval; i++) dam[0, i] = v[i]; } readonly static int meansize = 20; readonly static int maxxval = (statics.real_datarate / 10) * 6 / 10; readonly int maxyval = 3000; private Point GetFFTPos(int x, int y) { int leftMargin = 2; int rightMargin = 2; int topMargin = 2; int bottomMargin =2; int xsize = panel_txspectrum.Size.Width; int newx = (x * (xsize - leftMargin - rightMargin)) / maxxval; newx += leftMargin; int ysize = panel_txspectrum.Size.Height; int newy = (y * (ysize - topMargin - bottomMargin)) / maxyval; newy += bottomMargin; newy = ysize - newy; Point p = new Point(newx, newy); return p; } void printText(RichTextBox rtb, String s) { AppendTextOnce(rtb, new Font("Courier New", (float)8), Color.Blue, Color.White, s); } void AppendTextOnce(RichTextBox rtb, Font selfont, Color color, Color bcolor, string text) { try { if (text.Contains("\n")) { char[] ca = new char[] { '\n', '\r' }; text = text.Trim(ca); text += "\n"; } // max. xxx Zeilen, wenn mehr dann lösche älteste if (rtb.Lines.Length > 200) { rtb.SelectionStart = 0; rtb.SelectionLength = rtb.Text.IndexOf("\n", 0) + 1; rtb.SelectedText = ""; } int start = rtb.TextLength; rtb.AppendText(text); int end = rtb.TextLength; // Textbox may transform chars, so (end-start) != text.Length rtb.Select(start, end - start); rtb.SelectionColor = color; rtb.SelectionFont = selfont; rtb.SelectionBackColor = bcolor; rtb.Select(end, 0); rtb.ScrollToCaret(); } catch (Exception e) { Console.WriteLine(e.ToString()); } } String TXimagefilename = ""; String TXRealFilename = ""; long TXRealFileSize = 0; String TXfoldername = ""; String lastFullName = ""; // prepare an image file for transmission void prepareImage(String fullfn) { if (statics.checkImage(fullfn) == false) return; // all images are converted to jpg, make the new filename TXfoldername = statics.purePath(fullfn); TXRealFilename = statics.pureFilename(fullfn); TXRealFilename = statics.AddReplaceFileExtension(TXRealFilename,"jpg"); lastFullName = fullfn; // random filename for picturebox control (picturebox cannot reload image from actual filename) try { File.Delete(TXimagefilename); } catch { } Random randNum = new Random(); TXimagefilename = statics.addTmpPath("tempTX" + randNum.Next(0, 65000).ToString() + ".jpg"); // get the quality selected by the user String qual = comboBox_quality.Text; long max_size = 22500; if (qual.Contains("30s")) max_size = 12000; if (qual.Contains("2min")) max_size = 45000; if (qual.Contains("4min")) max_size = 90000; // resize image and save it according the quality settings Image img = new Bitmap(fullfn); String cs = tb_callsign.Text; if (cb_stampcall.Checked == false) cs = ""; if (!checkBox_big.Checked) { img = ih.ResizeImage(img, 320, 240, cs); // set quality by reducing the file size and save under default name ih.SaveJpgAtFileSize(img, TXimagefilename, max_size / 2); } else { img = ih.ResizeImage(img, 640, 480, cs); // set quality by reducing the file size and save under default name ih.SaveJpgAtFileSize(img, TXimagefilename, max_size); } pictureBox_tximage.Load(TXimagefilename); TXRealFileSize = statics.GetFileSize(TXimagefilename); ShowTXstatus(); txcommand = statics.Image; } void ShowTXstatus() { if(txcommand == statics.Image) label_tximage.Text = "TX image: " + TXRealFilename + ". Sent: " + (ArraySend.txpos / 1000).ToString() + " of " + (TXRealFileSize / 1000).ToString() + " kB"; else label_txfile.Text = "TX file: " + TXRealFilename + ". Sent: " + (ArraySend.txpos / 1000).ToString() + " of " + (TXRealFileSize / 1000).ToString() + " kB"; } // in loop mode only: send the next picture in current image folder void startNextImage() { if (TXfoldername == "" || lastFullName == "") return; // read all file from folder String[] files = Directory.GetFiles(TXfoldername); Array.Sort(files); int i; bool found = false; for(i=0; i= 1) rspeed = rxbytecounter * 8 / totalseconds; RXstatus.Text = "received " + rxbytecounter + " byte " + totalseconds + " s, " + rspeed + " bit/s"; } private void button_cancelimg_Click(object sender, EventArgs e) { //txcommand = statics.noTX; // finished label_rximage.ForeColor = Color.Black; pictureBox_rximage.Image = null; ArraySend.stopSending(); } private void checkBox_small_CheckedChanged(object sender, EventArgs e) { // scale all elements // this is required if a scaled screen resolution is used für large 4k monitor, important under mono // since mono fails in automatic scaling if the screen resolution is different from 1:1 label_rximage.Location = new Point(6, 7); label_rximage.Location = new Point(650, 7); pictureBox_tximage.Size = new Size(640,480); pictureBox_rximage.Size = new Size(640,480); int yPicBoxes = label_rximage.Location.Y + label_rximage.Size.Height + 3; pictureBox_tximage.Location = new Point(1, yPicBoxes); pictureBox_rximage.Location = new Point(642, yPicBoxes); int gb_yloc = pictureBox_tximage.Location.Y + pictureBox_tximage.Size.Height + 3; groupBox1.Location = new Point(3, gb_yloc); tabControl1.Size = new Size(pictureBox_tximage.Size.Width + pictureBox_rximage.Size.Width + 10, label_rximage.Size.Height + 3 + pictureBox_rximage.Size.Height + 3 + groupBox1.Size.Height + 3 + 20); int rxpan_yloc = tabControl1.Location.Y + tabControl1.Size.Height + 3; panel_constel.Location = new Point(11, rxpan_yloc); panel_constel.Size = new Size(75,75); panel_txspectrum.Location = new Point(92, rxpan_yloc); panel_txspectrum.Size = new Size(441,75); rtb.Size = new Size(tabControl1.Size.Width - 30, tabControl1.Size.Height - button_startBERtest.Location.Y - button_startBERtest.Size.Height - 44); this.Size = new Size(tabControl1.Size.Width + 23, rxpan_yloc + panel_constel.Size.Height + statusStrip1.Size.Height + 42); int xf = bt_file_ascii.Location.X + bt_file_ascii.Size.Width + 20; int yf = bt_file_ascii.Location.Y; rtb_TXfile.Location = new Point(xf, yf); int mw = tabControl1.Size.Width - bt_file_ascii.Size.Width - 80; mw /= 2; int mh = tabControl1.Size.Height - bt_file_ascii.Size.Height - 50; rtb_TXfile.Size = new Size(mw, mh); xf += mw + 5; rtb_RXfile.Location = new Point(xf, yf); rtb_RXfile.Size = new Size(mw, mh); int ly = rtb_TXfile.Location.Y / 4; label_txfile.Location = new Point(rtb_TXfile.Location.X, ly); label_rxfile.Location = new Point(rtb_RXfile.Location.X, ly); label_speed.Location = new Point(panel_txspectrum.Location.X + panel_txspectrum.Size.Width + 20,panel_txspectrum.Location.Y+10); cb_speed.Location = new Point(label_speed.Location.X + label_speed.Size.Width + 10, label_speed.Location.Y-5); } public String GetMyBroadcastIP() { String ip = "255.255.255.255"; String[] myips = statics.getOwnIPs(); //Console.WriteLine("BClen: " + myips.Length.ToString()); // nur wenn der PC eine IP hat // hat er mehr, dann wissen wir nicht in welchem Netz wird broadcasten sollen, nehmen also die 255.255.255.255 if (myips.Length == 1) { int idx = myips[0].LastIndexOf('.'); if (idx >= 0) { ip = myips[0].Substring(0, idx); ip += ".255"; //Console.WriteLine("BCip: " + ip); } } return ip; } /* * search for the modem IP: * send a search message (2 bytes) via UDP to port UdpBCport * if a modem receives this message, it returns with an * UDP message to UdpBCport containing a String with it's IP address */ private void search_modem() { Udp.UdpBCsend(new Byte[] { (Byte)0x3c }, GetMyBroadcastIP(), statics.UdpBCport_AppToModem); Udp.searchtimeout++; if (Udp.searchtimeout >= 3) statics.ModemIP = "1.2.3.4"; } private void bt_file_ascii_Click(object sender, EventArgs e) { OpenFileDialog open = new OpenFileDialog(); open.Filter = "Text Files(*.txt*; *.*)|*.txt; *.*"; if (open.ShowDialog() == DialogResult.OK) { TXfilename = open.FileName; TXRealFilename = open.SafeFileName; String text = File.ReadAllText(TXfilename); rtb_TXfile.Text = text; txcommand = statics.AsciiFile; // compress file ZipStorer zs = new ZipStorer(); zs.zipFile(statics.zip_TXtempfilename,open.SafeFileName,open.FileName); TXRealFileSize = statics.GetFileSize(statics.zip_TXtempfilename); ShowTXstatus(); } } private void bt_file_send_Click(object sender, EventArgs e) { rtb_RXfile.Text = ""; File.Delete(statics.zip_RXtempfilename); Byte[] textarr = File.ReadAllBytes(statics.zip_TXtempfilename); ArraySend.Send(textarr, (Byte)txcommand, TXfilename, TXRealFilename); } private void button2_Click(object sender, EventArgs e) { OpenFileDialog open = new OpenFileDialog(); open.Filter = "HTML Files(*.html; *.htm; *.*)|*.html; *.htm; *.*"; if (open.ShowDialog() == DialogResult.OK) { TXfilename = open.FileName; TXRealFilename = open.SafeFileName; String text = File.ReadAllText(TXfilename); rtb_TXfile.Text = text; txcommand = statics.HTMLFile; // compress file ZipStorer zs = new ZipStorer(); zs.zipFile(statics.zip_TXtempfilename, open.SafeFileName, open.FileName); TXRealFileSize = statics.GetFileSize(statics.zip_TXtempfilename); ShowTXstatus(); } } private void bt_sendBinaryFile_Click(object sender, EventArgs e) { OpenFileDialog open = new OpenFileDialog(); open.Filter = "All Files(*.*)|*.*"; if (open.ShowDialog() == DialogResult.OK) { TXfilename = open.FileName; TXRealFilename = open.SafeFileName; rtb_TXfile.Text = "Binary file " + TXfilename + " loaded"; txcommand = statics.BinaryFile; // compress file ZipStorer zs = new ZipStorer(); zs.zipFile(statics.zip_TXtempfilename, open.SafeFileName, open.FileName); TXRealFileSize = statics.GetFileSize(statics.zip_TXtempfilename); ShowTXstatus(); } } private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) { int idx = cb_speed.SelectedIndex; int real_rate=4000; switch (idx) { case 0: real_rate = 3000; break; case 1: real_rate = 3150; break; case 2: real_rate = 3675; break; case 3: real_rate = 4000; break; case 4: real_rate = 4410; break; case 5: real_rate = 4800; break; case 6: real_rate = 5525; break; case 7: real_rate = 6000; break; } statics.setDatarate(real_rate); Byte[] txdata = new byte[statics.PayloadLen + 2]; txdata[0] = (Byte)statics.ResamplingRate; // BER Test Marker txdata[1] = (Byte)idx; // and send info to modem Udp.UdpSend(txdata); //txcommand = statics.noTX; // stop any ongoing transmission button_cancelimg_Click(null, null); } private void timer_searchmodem_Tick(object sender, EventArgs e) { search_modem(); } private void bt_rximages_Click(object sender, EventArgs e) { if (statics.ostype == 0) { try { String s = "file://" + statics.getHomePath(statics.RXimageStorage, ""); Process.Start(s); } catch (Exception ex) { Console.WriteLine(ex.ToString()); } } else { try { Process.Start("xdg-open", statics.getHomePath(statics.RXimageStorage, "")); } catch (Exception ex) { Console.WriteLine(ex.ToString()); } } } /// // TEST ONLY: tell modem to send a file private void button1_Click(object sender, EventArgs e) { Byte[] txdata = new byte[statics.PayloadLen + 2]; txdata[0] = (Byte)statics.AutosendFile; // and transmit it Udp.UdpSend(txdata); } private void bt_openrxfile_Click(object sender, EventArgs e) { if (statics.ostype == 0) { try { String s = "file://" + statics.getHomePath("", ""); Process.Start(s); } catch (Exception ex) { Console.WriteLine(ex.ToString()); } } else { try { Process.Start("xdg-open", statics.getHomePath("", "")); } catch (Exception ex) { Console.WriteLine(ex.ToString()); } } } private String ReadString(StreamReader sr) { String s = sr.ReadLine(); if (s != null) { return s; } return " "; } private int ReadInt(StreamReader sr) { int v; try { String s = sr.ReadLine(); if (s != null) { v = Convert.ToInt32(s); return v; } } catch { } return 0; } void load_Setup() { try { using (StreamReader sr = new StreamReader(statics.getHomePath("", "od.cfg"))) { tb_callsign.Text = ReadString(sr); cb_speed.Text = ReadString(sr); String s = ReadString(sr); cb_stampcall.Checked = (s == "1"); s = ReadString(sr); cb_savegoodfiles.Checked = (s == "1"); } } catch { tb_callsign.Text = ""; cb_speed.Text = "4000 QPSK BW: 2400 Hz (default QO-100)"; } } void save_Setup() { try { using (StreamWriter sw = new StreamWriter(statics.getHomePath("", "od.cfg"))) { sw.WriteLine(tb_callsign.Text); sw.WriteLine(cb_speed.Text); sw.WriteLine(cb_stampcall.Checked?"1":"0"); sw.WriteLine(cb_savegoodfiles.Checked ? "1" : "0"); } } catch { } } private void bt_shutdown_Click(object sender, EventArgs e) { DialogResult dr = MessageBox.Show("Do you want to shut down the Modem-Computer ?", "Shut Down Modem", MessageBoxButtons.YesNo); if (dr == DialogResult.Yes) { Byte[] txdata = new byte[statics.PayloadLen + 2]; txdata[0] = (Byte)statics.Modem_shutdown; // and transmit it Udp.UdpSend(txdata); MessageBox.Show("Please wait abt. 1 minute before powering OFF the modem", "Shut Down Modem", MessageBoxButtons.OK); } } } }