diff --git a/WinRelease/hsmodem.exe b/WinRelease/hsmodem.exe index fc7486b..05ff01f 100755 Binary files a/WinRelease/hsmodem.exe and b/WinRelease/hsmodem.exe differ diff --git a/WinRelease/oscardata.exe b/WinRelease/oscardata.exe new file mode 100755 index 0000000..82bdca0 Binary files /dev/null and b/WinRelease/oscardata.exe differ diff --git a/hsmodem/frame_packer.cpp b/hsmodem/frame_packer.cpp index 6cb8866..8128d62 100755 --- a/hsmodem/frame_packer.cpp +++ b/hsmodem/frame_packer.cpp @@ -89,24 +89,28 @@ void init_packer() // the payload has a size of PAYLOADLEN // type ... inserted in the "frame type information" field // status ... specifies first/last frame of a data stream -uint8_t *Pack(uint8_t *payload, int type, int status, int *plen) +// repeat ... 0=normal frame, 1=repeated frame (do not increment frame counter) +uint8_t *Pack(uint8_t *payload, int type, int status, int *plen, int repeat) { FRAME frame; // raw frame without fec // polulate the raw frame // make the frame counter - if(status == 0) - framecounter = 0; // first block of a stream - else + if(repeat == 0 || type == 1) // 1=BER test framecounter++; - + + if (status == 0) + framecounter = 0; // start of file + // insert frame counter and status bits frame.counter_LSB = framecounter & 0xff; int framecnt_MSB = (framecounter >> 8) & 0x03; // Bit 8+9 of framecounter frame.status = framecnt_MSB << 6; frame.status += ((status & 0x03)<<4); frame.status += (type & 0x0f); + + //printf("type:%d stat:%d frmnum:%d fifo:%d\n", type, status, framecounter, io_pb_fifo_freespace(0)); // insert the payload memcpy(frame.payload, payload, PAYLOADLEN); @@ -344,8 +348,8 @@ uint8_t *getPayload(uint8_t *rxb) payload[4] = rx_status; // frame lost information payload[5] = speed >> 8; // measured line speed payload[6] = speed; - payload[7] = maxLevel; // actual max level on sound capture in % - payload[8] = 0; // free for later use + payload[7] = 0; // free for later use + payload[8] = 0; payload[9] = 0; //printf("Frame no.: %d, type:%d, minfo:%d\n",framenumrx,payload[0],payload[3]); diff --git a/hsmodem/hsmodem.cpp b/hsmodem/hsmodem.cpp index bd82c29..4cbf684 100755 --- a/hsmodem/hsmodem.cpp +++ b/hsmodem/hsmodem.cpp @@ -36,7 +36,6 @@ #include "hsmodem.h" -void toGR_sendData(uint8_t* data, int type, int status); void bc_rxdata(uint8_t* pdata, int len, struct sockaddr_in* rxsock); void appdata_rxdata(uint8_t* pdata, int len, struct sockaddr_in* rxsock); void startModem(); @@ -90,6 +89,8 @@ int codec = 1; // 0=opus, 1=codec2 int init_audio_result = 0; int init_voice_result = 0; +int safemode = 0; + int main(int argc, char* argv[]) { int opt = 0; @@ -300,7 +301,8 @@ void bc_rxdata(uint8_t* pdata, int len, struct sockaddr_in* rxsock) * 3 ... announcement on / off, duration * 4 ... DV loudspeaker volume * 5 ... DV mic volume - * 6..9 ... unused + * 6 ... safe mode number + * 7..9 ... unused * 10 .. 109 ... PB device name * 110 .. 209 ... CAP device name */ @@ -308,6 +310,8 @@ void bc_rxdata(uint8_t* pdata, int len, struct sockaddr_in* rxsock) //printf("%d %d %d %d %d %d %d \n",pdata[1], pdata[2], pdata[3], pdata[4], pdata[5], pdata[6], pdata[7]); io_setAudioDevices(pdata[1], pdata[2], pdata[3], pdata[4], pdata[5], (char *)(pdata + 10), (char *)(pdata + 110)); + safemode = pdata[6]; + char rxip[20]; strcpy(rxip, inet_ntoa(rxsock->sin_addr)); @@ -474,13 +478,14 @@ void appdata_rxdata(uint8_t* pdata, int len, struct sockaddr_in* rxsock) closeAllandTerminate(); } + // here we are with payload data to be sent via the modulator + if (len != (PAYLOADLEN + 2)) { printf("data from app: wrong length:%d (should be %d)\n", len - 2, PAYLOADLEN); return; } - //if (getSending() == 1) return; // already sending (Array sending) if (minfo == 0 || minfo == 3) @@ -493,9 +498,10 @@ void appdata_rxdata(uint8_t* pdata, int len, struct sockaddr_in* rxsock) // and bits: symbols * bitsPerSymbol // and bytes/second: bits/8 = (caprate/txinterpolfactor) * bitsPerSymbol / 8 // one frame has 258 bytes, so we need for 6s: 6* ((caprate/txinterpolfactor) * bitsPerSymbol / 8) /258 + 1 frames + toGR_sendData(pdata + 2, type, minfo,0); int numframespreamble = 6 * ((caprate / txinterpolfactor) * bitsPerSymbol / 8) / 258 + 1; for (int i = 0; i < numframespreamble; i++) - toGR_sendData(pdata + 2, type, minfo); + toGR_sendData(pdata + 2, type, minfo,1); } else if ((len - 2) < PAYLOADLEN) { @@ -503,18 +509,41 @@ void appdata_rxdata(uint8_t* pdata, int len, struct sockaddr_in* rxsock) uint8_t payload[PAYLOADLEN]; memset(payload, 0, PAYLOADLEN); memcpy(payload, pdata + 2, len - 2); - toGR_sendData(payload, type, minfo); + toGR_sendData(payload, type, minfo,0); + if (safemode > 0) + { + for (int sm = 0; sm < safemode; sm++) + toGR_sendData(payload, type, minfo, 1); + } + if (minfo == 2) + { + // repeat last frame + for (int rl = 0; rl < (10 - safemode); rl++) + toGR_sendData(payload, type, minfo, 1); + } } else { - toGR_sendData(pdata + 2, type, minfo); + toGR_sendData(pdata + 2, type, minfo,0); + + if (safemode > 0) + { + for(int sm=0; sm < safemode; sm++) + toGR_sendData(pdata + 2, type, minfo, 1); + } + if (minfo == 2) + { + // repeat last frame + for(int rl = 0; rl < (10-safemode); rl ++) + toGR_sendData(pdata + 2, type, minfo, 1); + } } } -void toGR_sendData(uint8_t* data, int type, int status) +void toGR_sendData(uint8_t* data, int type, int status, int repeat) { int len = 0; - uint8_t* txdata = Pack(data, type, status, &len); + uint8_t* txdata = Pack(data, type, status, &len, repeat); //showbytestring((char *)"BERtx: ", txdata, len); diff --git a/hsmodem/hsmodem.h b/hsmodem/hsmodem.h index 705696e..c9027be 100755 --- a/hsmodem/hsmodem.h +++ b/hsmodem/hsmodem.h @@ -88,7 +88,7 @@ enum _VOICEMODES_ { }; void init_packer(); -uint8_t* Pack(uint8_t* payload, int type, int status, int* plen); +uint8_t* Pack(uint8_t* payload, int type, int status, int* plen, int repeat); uint8_t* unpack_data(uint8_t* rxd, int len); void convertBytesToSyms_QPSK(uint8_t* bytes, uint8_t* syms, int bytenum); @@ -142,7 +142,7 @@ void sendAnnouncement(); void sleep_ms(int ms); int getus(); void GRdata_rxdata(uint8_t* pdata, int len, struct sockaddr_in* rxsock); -void toGR_sendData(uint8_t* data, int type, int status); +void toGR_sendData(uint8_t* data, int type, int status, int repeat); void modulator(uint8_t sym_in); int io_pb_fifo_usedBlocks(); @@ -213,6 +213,7 @@ extern int ann_running; extern int transmissions; extern int linespeed; extern uint8_t maxLevel; +extern uint8_t maxTXLevel; extern int VoiceAudioMode; extern int opusbitrate; extern int init_audio_result; @@ -227,6 +228,7 @@ extern float softwareMICvolume; extern float softwareLSvolume; extern int physcaprate; extern int restart_modems; +extern int safemode; #ifdef _LINUX_ int isRunning(char* prgname); diff --git a/hsmodem/liquid_if.cpp b/hsmodem/liquid_if.cpp index 4f872ee..8e15489 100755 --- a/hsmodem/liquid_if.cpp +++ b/hsmodem/liquid_if.cpp @@ -199,7 +199,7 @@ void modulator(uint8_t sym_in) { fs = io_pb_fifo_freespace(0); // wait until there is space in fifo - if(fs) break; + if(fs > 20000) break; sleep_ms(10); } @@ -229,7 +229,8 @@ unsigned int m_st = 7; // filter delay (symbols) float beta_st = beta_excessBW;//0.30f; // filter excess bandwidth factor float bandwidth_st = 0.9f; // loop filter bandwidth -uint8_t maxLevel = 0; // maximum level over the last x samples in % +uint8_t maxLevel = 0; // maximum RXlevel over the last x samples in % +uint8_t maxTXLevel = 0; // maximum TXlevel over the last x samples in % void init_demodulator() { @@ -282,7 +283,7 @@ void make_FFTdata(float f) uint8_t txpl[10000]; if (fftlen > (10000 * 2 + 1)) { - printf("GRdata_FFTdata: txpl too small !!!\n"); + printf("FFTdata: txpl too small !!!\n"); return; } @@ -300,6 +301,9 @@ void make_FFTdata(float f) txpl[bidx++] = rxlevel_deteced; // RX level present txpl[bidx++] = rx_in_sync; + txpl[bidx++] = maxLevel; // actual max level on sound capture in % + txpl[bidx++] = maxTXLevel; // actual max level on sound playback in % + for (int i = 0; i < fftlen; i++) { txpl[bidx++] = fft[i] >> 8; @@ -309,7 +313,7 @@ void make_FFTdata(float f) } } -#define MCHECK 1000 +#define MCHECK 48000 void getMax(float fv) { static float farr[MCHECK]; @@ -334,7 +338,7 @@ void getMax(float fv) if (farr[i] > max) max = farr[i]; } maxLevel = (uint8_t)(max*100); - //printf("max: %10.6f\n", max); + //printf("RX max: %10.6f\n", max); } } @@ -414,7 +418,7 @@ static int ccol_idx = 0; unsigned int sym_out; // output symbol sym_out = nsym_out; - //measure_speed_syms(1); + measure_speed_syms(1); // do NOT remove, used for speed display in GUI // try to extract a complete frame uint8_t symb = sym_out; diff --git a/hsmodem/soundio.cpp b/hsmodem/soundio.cpp index 746496c..9391cd3 100755 --- a/hsmodem/soundio.cpp +++ b/hsmodem/soundio.cpp @@ -276,7 +276,7 @@ void read_callback(struct SoundIoInStream* instream, int frame_count_min, int fr } } //printf("%d into fifo\n", frame_count); - // needs to sleep or it will not work correctly, no idea why + // needs to sleep or it will not work correctly on Windows, no idea why sleep_ms(1); //measure_speed_bps(frame_count); @@ -300,6 +300,35 @@ void overflow_callback(struct SoundIoInStream* instream) printf("overflow %d\n", ++count); } +#define MTXCHECK 48000 +void getTXMax(float fv) +{ + static float farr[MTXCHECK]; + static int idx = 0; + static int f = 1; + + if (f) + { + f = 0; + for (int i = 0; i < MTXCHECK; i++) + farr[i] = 1; + } + + farr[idx] = fv; + idx++; + if (idx == MTXCHECK) + { + idx = 0; + float max = 0; + for (int i = 0; i < MTXCHECK; i++) + { + if (farr[i] > max) max = farr[i]; + } + maxTXLevel = (uint8_t)(max * 100); + //printf("TX max: %10.6f\n", max); + } +} + // #define SINEWAVETEST #ifdef SINEWAVETEST @@ -354,6 +383,7 @@ static void write_callback(struct SoundIoOutStream* outstream, int frame_count_m for (int channel = 0; channel < layout->channel_count; channel += 1) { float ftx = f[frame] * softwarePBvolume; + getTXMax(ftx); if (pbrawdev == false) { #ifdef SINEWAVETEST diff --git a/hsmodem/speed.cpp b/hsmodem/speed.cpp index 188f30f..6d69a9b 100755 --- a/hsmodem/speed.cpp +++ b/hsmodem/speed.cpp @@ -132,8 +132,8 @@ void measure_speed_syms(int len) speed = meanval((int)dspd) * bitsPerSymbol; // here we have number of elements after 1s - printf("%d sym/s\n",speed); - + //printf("%d sym/s\n",speed); + // do NOT uncomment this function for RX, it is used to measure the speed for the GUI elems=0; lasttim = tim; } @@ -160,7 +160,7 @@ void measure_speed_bps(int len) speed = meanvalbps((int)dspd); // here we have number of elements after 1s - printf(" ======================= %d bit/s\n", speed); + //printf(" ======================= %d bit/s\n", speed); elems = 0; lasttim = tim; diff --git a/hsmodem/voiceprocessor.cpp b/hsmodem/voiceprocessor.cpp index 5163807..a0406c0 100755 --- a/hsmodem/voiceprocessor.cpp +++ b/hsmodem/voiceprocessor.cpp @@ -165,7 +165,7 @@ void sendCodecToModulator(uint8_t *pdata, int len) if (vdidx == PAYLOADLEN) { vdidx = 0; - toGR_sendData(payload, 6, 1); // 6 ... voice data, 1 ... valid voice data + toGR_sendData(payload, 6, 1 ,0); // 6 ... voice data, 1 ... valid voice data } while (1) @@ -179,7 +179,7 @@ void sendCodecToModulator(uint8_t *pdata, int len) // send a dummy frame, a frame with 0 voice data uint8_t dummy[PAYLOADLEN]; memset(dummy, 0, PAYLOADLEN); - toGR_sendData(dummy, 6, 0); + toGR_sendData(dummy, 6, 0, 0); } else break; diff --git a/oscardata/oscardata/App.config b/oscardata/oscardata/App.config index e743be0..a3f4642 100755 --- a/oscardata/oscardata/App.config +++ b/oscardata/oscardata/App.config @@ -2,5 +2,5 @@ - + diff --git a/oscardata/oscardata/ArraySend.cs b/oscardata/oscardata/ArraySend.cs index 494e286..0d98638 100755 --- a/oscardata/oscardata/ArraySend.cs +++ b/oscardata/oscardata/ArraySend.cs @@ -17,6 +17,7 @@ namespace oscardata 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() @@ -81,7 +82,7 @@ namespace oscardata // CRC16 over complete file contents is the file ID Crc c = new Crc(); - UInt16 fncrc = c.crc16_messagecalc(data, data.Length); + fncrc = c.crc16_messagecalc(data, data.Length); // create the file header // 50 bytes ... Filename (or first 50 chars of the filename) @@ -133,7 +134,7 @@ namespace oscardata return null; } - // runs every 10 ms + // runs every 10 ms to send a file static void TimerTick(object stateInfo) { // check if we need to send something @@ -157,7 +158,7 @@ namespace oscardata } else { - // additional frame follow + // 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); @@ -176,9 +177,9 @@ namespace oscardata { // 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 - for(int i=0; i<10; i++) - txudp(txarr, txtype, statics.LastFrame); + + // send the last frame a couple of times (see hsmodem.cpp) + txudp(txarr, txtype, statics.LastFrame); setSending(false); // transmission complete } else diff --git a/oscardata/oscardata/Form1.Designer.cs b/oscardata/oscardata/Form1.Designer.cs index a5b9fdb..f5a619b 100755 --- a/oscardata/oscardata/Form1.Designer.cs +++ b/oscardata/oscardata/Form1.Designer.cs @@ -97,6 +97,9 @@ this.label11 = new System.Windows.Forms.Label(); this.tabPage_setup = new System.Windows.Forms.TabPage(); this.groupBox4 = new System.Windows.Forms.GroupBox(); + this.label13 = new System.Windows.Forms.Label(); + this.label12 = new System.Windows.Forms.Label(); + this.cb_safemode = new System.Windows.Forms.ComboBox(); this.cb_language = new System.Windows.Forms.ComboBox(); this.cb_autostart = new System.Windows.Forms.CheckBox(); this.bt_shutdown = new System.Windows.Forms.Button(); @@ -104,6 +107,8 @@ this.bt_resetmodem = new System.Windows.Forms.Button(); this.textBox3 = new System.Windows.Forms.TextBox(); this.groupBox3 = new System.Windows.Forms.GroupBox(); + this.vu_cap = new KmProgressBar(); + this.vu_pb = new KmProgressBar(); this.pb_audioCAPstatus = new System.Windows.Forms.PictureBox(); this.pb_audioPBstatus = new System.Windows.Forms.PictureBox(); this.label6 = new System.Windows.Forms.Label(); @@ -130,10 +135,10 @@ this.cb_speed = new System.Windows.Forms.ComboBox(); this.label_speed = new System.Windows.Forms.Label(); this.timer_searchmodem = new System.Windows.Forms.Timer(this.components); - this.progressBar_fifo = new System.Windows.Forms.ProgressBar(); + this.progressBar_fifo = new KmProgressBar(); this.label_fifo = new System.Windows.Forms.Label(); this.bt_blockinfo = new System.Windows.Forms.Button(); - this.progressBar_capfifo = new System.Windows.Forms.ProgressBar(); + this.progressBar_capfifo = new KmProgressBar(); this.label_capfifo = new System.Windows.Forms.Label(); this.lb_rxsignal = new System.Windows.Forms.Label(); this.lb_rxsync = new System.Windows.Forms.Label(); @@ -223,7 +228,7 @@ // timer_qpsk // this.timer_qpsk.Enabled = true; - this.timer_qpsk.Interval = 500; + this.timer_qpsk.Interval = 200; this.timer_qpsk.Tick += new System.EventHandler(this.timer_qpsk_Tick); // // panel_txspectrum @@ -926,6 +931,9 @@ // // groupBox4 // + this.groupBox4.Controls.Add(this.label13); + this.groupBox4.Controls.Add(this.label12); + this.groupBox4.Controls.Add(this.cb_safemode); this.groupBox4.Controls.Add(this.cb_language); this.groupBox4.Controls.Add(this.cb_autostart); this.groupBox4.Controls.Add(this.bt_shutdown); @@ -939,13 +947,44 @@ this.groupBox4.TabStop = false; this.groupBox4.Text = "Maintenance"; // + // label13 + // + this.label13.AutoSize = true; + this.label13.Location = new System.Drawing.Point(240, 78); + this.label13.Name = "label13"; + this.label13.Size = new System.Drawing.Size(70, 13); + this.label13.TabIndex = 27; + this.label13.Text = "data security:"; + // + // label12 + // + this.label12.AutoSize = true; + this.label12.Location = new System.Drawing.Point(253, 23); + this.label12.Name = "label12"; + this.label12.Size = new System.Drawing.Size(54, 13); + this.label12.TabIndex = 26; + this.label12.Text = "language:"; + // + // cb_safemode + // + this.cb_safemode.FormattingEnabled = true; + this.cb_safemode.Items.AddRange(new object[] { + "off (fast)", + "medium", + "high (slow)"}); + this.cb_safemode.Location = new System.Drawing.Point(326, 75); + this.cb_safemode.Name = "cb_safemode"; + this.cb_safemode.Size = new System.Drawing.Size(110, 21); + this.cb_safemode.TabIndex = 25; + this.cb_safemode.Text = "off"; + // // cb_language // this.cb_language.FormattingEnabled = true; this.cb_language.Items.AddRange(new object[] { "English", "German/Deutsch"}); - this.cb_language.Location = new System.Drawing.Point(207, 19); + this.cb_language.Location = new System.Drawing.Point(326, 19); this.cb_language.Name = "cb_language"; this.cb_language.Size = new System.Drawing.Size(110, 21); this.cb_language.TabIndex = 24; @@ -989,7 +1028,7 @@ // // bt_resetmodem // - this.bt_resetmodem.Location = new System.Drawing.Point(356, 82); + this.bt_resetmodem.Location = new System.Drawing.Point(529, 92); this.bt_resetmodem.Name = "bt_resetmodem"; this.bt_resetmodem.Size = new System.Drawing.Size(117, 23); this.bt_resetmodem.TabIndex = 6; @@ -1012,6 +1051,8 @@ // // groupBox3 // + this.groupBox3.Controls.Add(this.vu_cap); + this.groupBox3.Controls.Add(this.vu_pb); this.groupBox3.Controls.Add(this.pb_audioCAPstatus); this.groupBox3.Controls.Add(this.pb_audioPBstatus); this.groupBox3.Controls.Add(this.label6); @@ -1029,11 +1070,25 @@ this.groupBox3.TabStop = false; this.groupBox3.Text = "Transceiver Audio"; // + // vu_cap + // + this.vu_cap.Location = new System.Drawing.Point(479, 87); + this.vu_cap.Name = "vu_cap"; + this.vu_cap.Size = new System.Drawing.Size(100, 10); + this.vu_cap.TabIndex = 20; + // + // vu_pb + // + this.vu_pb.Location = new System.Drawing.Point(479, 45); + this.vu_pb.Name = "vu_pb"; + this.vu_pb.Size = new System.Drawing.Size(100, 10); + this.vu_pb.TabIndex = 19; + // // pb_audioCAPstatus // this.pb_audioCAPstatus.BackgroundImage = global::oscardata.Properties.Resources.ok; this.pb_audioCAPstatus.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom; - this.pb_audioCAPstatus.Location = new System.Drawing.Point(375, 52); + this.pb_audioCAPstatus.Location = new System.Drawing.Point(375, 63); this.pb_audioCAPstatus.Name = "pb_audioCAPstatus"; this.pb_audioCAPstatus.Size = new System.Drawing.Size(21, 21); this.pb_audioCAPstatus.TabIndex = 18; @@ -1052,7 +1107,7 @@ // label6 // this.label6.AutoSize = true; - this.label6.Location = new System.Drawing.Point(428, 54); + this.label6.Location = new System.Drawing.Point(428, 65); this.label6.Name = "label6"; this.label6.Size = new System.Drawing.Size(45, 13); this.label6.TabIndex = 16; @@ -1070,9 +1125,10 @@ // tb_CAPvol // this.tb_CAPvol.Cursor = System.Windows.Forms.Cursors.SizeAll; - this.tb_CAPvol.Location = new System.Drawing.Point(479, 50); + this.tb_CAPvol.Location = new System.Drawing.Point(479, 61); this.tb_CAPvol.Maximum = 100; this.tb_CAPvol.MaximumSize = new System.Drawing.Size(0, 24); + this.tb_CAPvol.Minimum = 1; this.tb_CAPvol.MinimumSize = new System.Drawing.Size(100, 0); this.tb_CAPvol.Name = "tb_CAPvol"; this.tb_CAPvol.Size = new System.Drawing.Size(100, 24); @@ -1087,6 +1143,7 @@ this.tb_PBvol.Location = new System.Drawing.Point(479, 19); this.tb_PBvol.Maximum = 100; this.tb_PBvol.MaximumSize = new System.Drawing.Size(0, 24); + this.tb_PBvol.Minimum = 1; this.tb_PBvol.MinimumSize = new System.Drawing.Size(100, 0); this.tb_PBvol.Name = "tb_PBvol"; this.tb_PBvol.Size = new System.Drawing.Size(100, 24); @@ -1116,7 +1173,7 @@ // cb_audioCAP // this.cb_audioCAP.FormattingEnabled = true; - this.cb_audioCAP.Location = new System.Drawing.Point(138, 52); + this.cb_audioCAP.Location = new System.Drawing.Point(138, 63); this.cb_audioCAP.Name = "cb_audioCAP"; this.cb_audioCAP.Size = new System.Drawing.Size(230, 21); this.cb_audioCAP.TabIndex = 9; @@ -1125,7 +1182,7 @@ // label4 // this.label4.AutoSize = true; - this.label4.Location = new System.Drawing.Point(12, 56); + this.label4.Location = new System.Drawing.Point(12, 67); this.label4.Name = "label4"; this.label4.Size = new System.Drawing.Size(112, 13); this.label4.TabIndex = 10; @@ -1538,7 +1595,7 @@ private System.Windows.Forms.Label label6; private System.Windows.Forms.Label label5; private System.Windows.Forms.TrackBar tb_CAPvol; - private System.Windows.Forms.ProgressBar progressBar_fifo; + private KmProgressBar progressBar_fifo; private System.Windows.Forms.Label label_fifo; private System.Windows.Forms.CheckBox cb_autostart; private System.Windows.Forms.TextBox textBox5; @@ -1579,13 +1636,18 @@ private System.Windows.Forms.RadioButton rb_codec2; private System.Windows.Forms.CheckBox cb_digitalVoiceRXonly; private System.Windows.Forms.PictureBox pb_voice; - private System.Windows.Forms.ProgressBar progressBar_capfifo; + private KmProgressBar progressBar_capfifo; private System.Windows.Forms.Label label_capfifo; private System.Windows.Forms.PictureBox pb_rxsignal; private System.Windows.Forms.Label lb_rxsignal; private System.Windows.Forms.Label lb_rxsync; private System.Windows.Forms.PictureBox pb_rxsync; private System.Windows.Forms.ComboBox cb_language; + private System.Windows.Forms.Label label13; + private System.Windows.Forms.Label label12; + private System.Windows.Forms.ComboBox cb_safemode; + private KmProgressBar vu_cap; + private KmProgressBar vu_pb; } } diff --git a/oscardata/oscardata/Form1.cs b/oscardata/oscardata/Form1.cs index 7cf360a..987c837 100755 --- a/oscardata/oscardata/Form1.cs +++ b/oscardata/oscardata/Form1.cs @@ -400,7 +400,6 @@ namespace oscardata // RX timer int rxstat = 0; int speed; - int maxlevel = 0; private void timer_udprx_Tick(object sender, EventArgs e) { while (true) @@ -418,11 +417,11 @@ namespace oscardata speed = rxd[5]; speed <<= 8; speed += rxd[6]; - maxlevel = rxd[7]; + int dummy3 = rxd[7]; int dummy4 = rxd[8]; int dummy5 = rxd[9]; - rxbytecounter += statics.UdpBlocklen; + rxbytecounter = statics.UdpBlocklen * rxfrmnum; Byte[] rxdata = new byte[rxd.Length - 10]; Array.Copy(rxd, 10, rxdata, 0, rxd.Length - 10); @@ -581,6 +580,32 @@ namespace oscardata // Show RX Status LEDs if (statics.RXlevelDetected == 1) pb_rxsignal.BackgroundImage = Resources.greenmarker; else pb_rxsignal.BackgroundImage = Resources.redmarker; if (statics.RXinSync == 1 && statics.RXlevelDetected == 1) pb_rxsync.BackgroundImage = Resources.greenmarker; else pb_rxsync.BackgroundImage = Resources.redmarker; + + // update rx,tx level progress bar + int factor = 1; + int addf = 80; + double vl100 = (100 / addf) + Math.Log10(100 + factor); + double vl = ((double)statics.maxRXlevel / addf) + Math.Log10((double)statics.maxRXlevel + factor); + vl = vl * 100 / vl100; + if (vl > 99) vl = 99; + if (vl < 1) vl = 1; + vu_cap.Value = (int)vl; + if (vl < 20 || vl > 85) + vu_cap.ForeColor = Color.Red; + else + vu_cap.ForeColor = Color.Yellow; + + addf = 80; + vl = ((double)statics.maxTXlevel / addf) + Math.Log10((double)statics.maxTXlevel + factor); + vl100 = (100 / addf) + Math.Log10(100 + factor); + vl = vl * 100 / vl100; + if (vl > 99) vl = 99; + if (vl < 1) vl = 1; + vu_pb.Value = (int)vl; + if(vl <20 || vl > 85) + vu_pb.ForeColor = Color.Red; + else + vu_pb.ForeColor = Color.Yellow; } private void panel_constel_Paint(object sender, PaintEventArgs e) @@ -602,7 +627,7 @@ namespace oscardata 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 penblue = new Pen(Brushes.Blue, 1); static Pen pengrey = new Pen(brgray, 1); Font fnt = new Font("Verdana", 8.0f); Font smallfnt = new Font("Verdana", 6.0f); @@ -673,12 +698,14 @@ namespace oscardata 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); + if (i >= 2 && i < maxxval - 2) + u = (UInt16)((su[i - 2] + su[i - 1] + su[i] + su[i + 1] + su[i + 2]) / 5); else u = su[i]; - u *= 3; + if (i < 3) u = 0; + + u *= 10; gp.AddLine(GetFFTPos(i, lastu), GetFFTPos(i + 1, u)); lastu = u; } @@ -698,7 +725,7 @@ namespace oscardata dam[0, i] = v[i]; } - readonly static int meansize = 20; + readonly static int meansize = 6;//0; readonly static int maxxval = (statics.real_datarate / 10) * 6 / 10; readonly int maxyval = 3000; @@ -1154,7 +1181,8 @@ namespace oscardata * 3 ... announcement on/off, duration * 4 ... DV loudspeaker volume * 5 ... DV mic volume - * 6..9 ... unused + * 6 ... safe mode + * 7..9 ... unused * 10 .. 109 ... PB device name * 110 .. 209 ... CAP device name * @@ -1162,6 +1190,10 @@ namespace oscardata private void search_modem() { + Byte safemode = 0; //number of frame repeats + if (cb_safemode.Text.Contains("medium")) safemode = 2; + else if (cb_safemode.Text.Contains("high")) safemode = 4; + Byte[] txb = new byte[210]; txb[0] = 0x3c; // ID of this message txb[1] = (Byte)tb_PBvol.Value; @@ -1169,7 +1201,7 @@ namespace oscardata txb[3] = (Byte)cb_announcement.Items.IndexOf(cb_announcement.Text); txb[4] = (Byte)tb_loadspeaker.Value; txb[5] = (Byte)tb_mic.Value; - txb[6] = (Byte)0; // unused + txb[6] = safemode; txb[7] = (Byte)0; // unused txb[8] = (Byte)0; // unused txb[9] = (Byte)0; // unused diff --git a/oscardata/oscardata/Form1.resx b/oscardata/oscardata/Form1.resx index c1275b2..3dd9d7a 100755 --- a/oscardata/oscardata/Form1.resx +++ b/oscardata/oscardata/Form1.resx @@ -137,7 +137,7 @@ AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAABw - FwAAAk1TRnQBSQFMAgEBDQEAAUABAQFAAQEBEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo + FwAAAk1TRnQBSQFMAgEBDQEAAUABAgFAAQIBEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo AwABQAMAAUADAAEBAQABCAYAARAYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5 AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA diff --git a/oscardata/oscardata/KmProgressBar.cs b/oscardata/oscardata/KmProgressBar.cs new file mode 100755 index 0000000..4441b9a --- /dev/null +++ b/oscardata/oscardata/KmProgressBar.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace oscardata +{ + class KmProgressBar : ProgressBar + { + double myvalue = 0; + public KmProgressBar() + { + SetStyle(ControlStyles.UserPaint, true); + SetStyle(ControlStyles.OptimizedDoubleBuffer, true); + } + + protected override void OnPaintBackground(PaintEventArgs pevent) + { + // None... Helps control the flicker. + } + + protected override void OnPaint(PaintEventArgs e) + { + try + { + Rectangle rect = ClientRectangle; + Graphics g = e.Graphics; + Brush br = new SolidBrush(Color.FromArgb(255, ForeColor.R, ForeColor.G, ForeColor.B)); + + g.FillRectangle(Brushes.LightGray, rect); + rect.Inflate(-1, -1); + g.FillRectangle(Brushes.White, rect); + rect.Inflate(-1, -1); + + double diff = Math.Abs(Value - myvalue); + if (Value > myvalue) myvalue += diff/10; + if (Value < myvalue) myvalue -= diff / 10; + + //myvalue = Value; + + if (myvalue > 0) + { + // As we doing this ourselves we need to draw the chunks on the progress bar + Rectangle clip = new Rectangle(rect.X, rect.Y, (int)Math.Round(((double)myvalue / Maximum) * rect.Width), rect.Height); + g.FillRectangle(br,clip); + } + } + catch { } + } + } +} diff --git a/oscardata/oscardata/Properties/Settings.Designer.cs b/oscardata/oscardata/Properties/Settings.Designer.cs index 75b410f..6064552 100755 --- a/oscardata/oscardata/Properties/Settings.Designer.cs +++ b/oscardata/oscardata/Properties/Settings.Designer.cs @@ -12,7 +12,7 @@ namespace oscardata.Properties { [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.7.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.8.1.0")] internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); diff --git a/oscardata/oscardata/bin/Release/oscardata.exe b/oscardata/oscardata/bin/Release/oscardata.exe index a716c2c..82bdca0 100755 Binary files a/oscardata/oscardata/bin/Release/oscardata.exe and b/oscardata/oscardata/bin/Release/oscardata.exe differ diff --git a/oscardata/oscardata/config.cs b/oscardata/oscardata/config.cs index 0ea8f80..2d84044 100755 --- a/oscardata/oscardata/config.cs +++ b/oscardata/oscardata/config.cs @@ -76,6 +76,8 @@ namespace oscardata public static int initVoiceStatus; public static int RXlevelDetected = 0; public static int RXinSync = 0; + public static int maxRXlevel = 0; + public static int maxTXlevel = 0; public static String[] getOwnIPs() diff --git a/oscardata/oscardata/oscardata.csproj b/oscardata/oscardata/oscardata.csproj index febefe6..d86309d 100755 --- a/oscardata/oscardata/oscardata.csproj +++ b/oscardata/oscardata/oscardata.csproj @@ -8,7 +8,7 @@ WinExe oscardata oscardata - v4.5 + v4.5.2 512 true @@ -71,6 +71,9 @@ Form2_showtext.cs + + Component + diff --git a/oscardata/oscardata/receivefile.cs b/oscardata/oscardata/receivefile.cs index 8429080..f4babcd 100755 --- a/oscardata/oscardata/receivefile.cs +++ b/oscardata/oscardata/receivefile.cs @@ -24,11 +24,11 @@ * ========================= * 1) file header is received, get filename and file ID (which is the CRC16 over the complete file contents) * 2) is this file already existing ? yes-> 3) -* 3) this file does not exist -> 4) +* this file does not exist -> 4) * * 3) file with this name and ID exists is already, cancel reception, show file * -* 4) file dows not exist, receive the blocks +* 4) file doews not exist, receive the blocks * 5) a block is missing -> find a previous block-file with this name+ID. If exists, take the block from this file * 6) reception complete, the files is OK -> save the file, delete a block file * 7) reception complete, the files is incomplete -> save the block file for late use @@ -189,6 +189,8 @@ namespace oscardata if (!autoRXnum) blockidx = rxfrmnum; + Console.WriteLine("minfo:" + minfo + " framenum:" + rxfrmnum + " blockidx:" + blockidx); + Array.Copy(rxd, 10, rxdata, 0, rxd.Length - 10); return true; } @@ -269,7 +271,10 @@ namespace oscardata public bool blockstat(int[] result) { + // return if no blocks received if (blockidx == 0) return false; + + // count the number of good blocks int ok = 0; for (int i = 0; i <= blockidx; i++) { @@ -278,6 +283,7 @@ namespace oscardata result[0] = blockidx+1; // +1 because we start with block 0 result[1] = ok; + // store in lastblockvalid for later evaluation for status display on the screen Array.Copy(blockvalid, lastblockvalid, blockvalid.Length); lastblockidx = blockidx; @@ -385,10 +391,12 @@ namespace oscardata if (autoRXnum) { + // for compatibility with old implementation which did not send a block number blockidx++; Console.WriteLine("blockidx: do auto increment " + blockidx); } + // insert the received payload into the block buffer and set this block's status to "valid" for (int i = 0; i < rxdata.Length; i++) blockbuf[blockidx, i] = rxdata[i]; diff --git a/oscardata/oscardata/udp.cs b/oscardata/oscardata/udp.cs index d505c4e..474fa42 100755 --- a/oscardata/oscardata/udp.cs +++ b/oscardata/oscardata/udp.cs @@ -124,7 +124,9 @@ namespace oscardata statics.PBfifousage = b[0]; statics.CAPfifousage = b[1]; statics.RXlevelDetected = b[2]; - statics. RXinSync = b[3]; + statics.RXinSync = b[3]; + statics.maxRXlevel = b[4]; + statics.maxTXlevel = b[5]; Byte[] b1 = new byte[b.Length - 4]; Array.Copy(b, 4, b1, 0, b1.Length); uq_fft.Add(b1);