diff --git a/README.md b/README.md index 5817a16..ec0edd9 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,9 @@ # QO-100-modem The purpose of this project is to transfer data (pictures...) via a 2,7kHz SSB channel on the narrow band transponder as fast as possible. +Now also including RTTY mode. # this is work in progress -Version 0.55 +Version 0.64 Windows 10 (should work on Win7, not tested) linux Desktop PC, Odroid SBC diff --git a/WinRelease/hsmodem.exe b/WinRelease/hsmodem.exe index 048d8a9..1fa2a45 100755 Binary files a/WinRelease/hsmodem.exe and b/WinRelease/hsmodem.exe differ diff --git a/WinRelease/hsmodem.iobj b/WinRelease/hsmodem.iobj deleted file mode 100755 index 2289cf4..0000000 Binary files a/WinRelease/hsmodem.iobj and /dev/null differ diff --git a/WinRelease/hsmodem.ipdb b/WinRelease/hsmodem.ipdb deleted file mode 100755 index da71cc2..0000000 Binary files a/WinRelease/hsmodem.ipdb and /dev/null differ diff --git a/WinRelease/hsmodem.pdb b/WinRelease/hsmodem.pdb deleted file mode 100755 index 29e3771..0000000 Binary files a/WinRelease/hsmodem.pdb and /dev/null differ diff --git a/WinRelease/oscardata.exe b/WinRelease/oscardata.exe index 28bc9e3..a83dfd7 100755 Binary files a/WinRelease/oscardata.exe and b/WinRelease/oscardata.exe differ diff --git a/WinRelease/sio_list_devices.exe b/WinRelease/sio_list_devices.exe deleted file mode 100755 index 0bc7bf8..0000000 Binary files a/WinRelease/sio_list_devices.exe and /dev/null differ diff --git a/WinRelease/sio_sine.exe b/WinRelease/sio_sine.exe deleted file mode 100755 index 785f254..0000000 Binary files a/WinRelease/sio_sine.exe and /dev/null differ diff --git a/hsmodem/announcement.cpp b/hsmodem/announcement.cpp index 15ffaf9..9669645 100755 --- a/hsmodem/announcement.cpp +++ b/hsmodem/announcement.cpp @@ -27,8 +27,6 @@ #include "hsmodem.h" -void close_a(); - const int h_len = 57; float h[h_len]; firfilt_crcf qfilt = NULL; diff --git a/hsmodem/baudot.h b/hsmodem/baudot.h new file mode 100755 index 0000000..2d17902 --- /dev/null +++ b/hsmodem/baudot.h @@ -0,0 +1,7 @@ +#pragma once + +typedef struct _BAUDOTTAB_ { + unsigned char baudot; + char letter; + char number; +} BAUDOTTAB; diff --git a/hsmodem/fft.cpp b/hsmodem/fft.cpp index ef1918b..c10fc8c 100755 --- a/hsmodem/fft.cpp +++ b/hsmodem/fft.cpp @@ -47,6 +47,24 @@ int rxlevel_deteced = 0; int rx_in_sync = 0; msresamp_crcf fftdecim = NULL; +float doublePeak(float *f_fftout, int e) +{ + // measure level at rtty freq + // -100..-70 and +70..+100 + float v = 0; + v += f_fftout[e - 7]; + v += f_fftout[e - 8]; + v += f_fftout[e - 9]; + v += f_fftout[e - 10]; + + v += f_fftout[e + 7]; + v += f_fftout[e + 8]; + v += f_fftout[e + 9]; + v += f_fftout[e + 10]; + + return v; +} + uint16_t *make_waterfall(float fre, int *retlen) { int fftrdy = 0; @@ -101,9 +119,27 @@ uint16_t *make_waterfall(float fre, int *retlen) // measure level at mid band float midlevel = 0; - for (int e = 100; e < 200; e++) - midlevel += f_fftout[e]; - midlevel /= 100; + if (speedmode == 10) + { + // RTTY + int mid = (rtty_frequency - 170 / 2) / 10; + int lowlow = mid - 5; + int lowhigh = mid + 5; + mid = (rtty_frequency + 170 / 2) / 10; + int highlow = mid - 5; + int highhigh = mid + 5; + for (int e = lowlow; e < lowhigh; e++) + midlevel += f_fftout[e]; + for (int e = highlow; e < highhigh; e++) + midlevel += f_fftout[e]; + midlevel /= ((lowhigh-lowlow) + (highhigh-highlow)); + } + else + { + for (int e = 100; e < 200; e++) + midlevel += f_fftout[e]; + midlevel /= 100; + } //calc difference in % int idiff = (int)((edgelevel * 100) / midlevel); @@ -118,10 +154,62 @@ uint16_t *make_waterfall(float fre, int *retlen) // check if signal detected or not if (idiff > 100) sig = 0; - if (idiff < 30) sig = 1; + if (idiff < 50) sig = 1; rxlevel_deteced = sig; + if (speedmode == 10 && rtty_autosync == 1) + { + // find an RTTY signal + // from 200 to 2800 Hz look for the beste double peak + float dp = 0; + int dpidx = 0; + + for (int e = 20; e < 280; e++) + { + float d = doublePeak(f_fftout, e); + if (d > dp) + { + dp = d; + dpidx = e; + } + } + + //printf("Signal at: %d Hz\n", (int)(dpidx * 10)); + + // accept if we get 3 equal values after each other + const static int simi = 3; + static int simiarr[simi]; + static int simiidx = 0; + simiarr[simiidx] = (int)(dpidx * 10); + if (++simiidx >= simi) simiidx = 0; + + int cp0 = simiarr[0]; + for (int i = 1; i < simi; i++) + if (simiarr[i] < (cp0-10) || simiarr[i] > (cp0 + 10)) cp0 = 0; + + if (cp0 > 0) + { + // mid value of last "arl" frequencies + const static int arl = 10; + static int fra[arl]; + static int fraidx = 0; + fra[fraidx] = cp0; + if (++fraidx >= arl) fraidx = 0; + int fm = 0; + for (int i = 0; i < arl; i++) + fm += fra[i]; + fm /= arl; + + static int lastfm = 0; + if (fm == lastfm) + { + rtty_modifyRXfreq(fm); + } + lastfm = fm; + } + } + // check if changed since last check if (sig != lastsig) { diff --git a/hsmodem/fifo.cpp b/hsmodem/fifo.cpp index 5d1584e..6083e63 100755 --- a/hsmodem/fifo.cpp +++ b/hsmodem/fifo.cpp @@ -27,6 +27,8 @@ #include "hsmodem.h" +void rtty_init_pipes(); + #ifdef _WIN32_ CRITICAL_SECTION io_cap_crit_sec; CRITICAL_SECTION io_pb_crit_sec; @@ -77,6 +79,7 @@ void io_init_pipes() #endif io_voice_init_pipes(); + rtty_init_pipes(); } // write one sample into the fifo @@ -190,19 +193,25 @@ int io_pb_fifo_freespace(int nolock) int io_pb_fifo_usedspace() { + IO_PB_LOCK; + int elemInFifo = (io_pb_wridx + AUDIO_PLAYBACK_BUFLEN - io_pb_rdidx) % AUDIO_PLAYBACK_BUFLEN; + IO_PB_UNLOCK(); + + return elemInFifo; + /* int anz = io_pb_fifo_freespace(0); - return AUDIO_PLAYBACK_BUFLEN - anz; + return AUDIO_PLAYBACK_BUFLEN - anz;*/ } // read num elements -// if num elems not avail, return 0 +// if num elems not avail, return all what fifo has stored int io_pb_read_fifo_num(float* data, int num) { IO_PB_LOCK; int elemInFifo = (io_pb_wridx + AUDIO_PLAYBACK_BUFLEN - io_pb_rdidx) % AUDIO_PLAYBACK_BUFLEN; - if (elemInFifo < num) + if (elemInFifo == 0) { // Fifo empty, no data available //printf("only %d elements available\n", elemInFifo); @@ -210,14 +219,17 @@ int io_pb_read_fifo_num(float* data, int num) return 0; } + if (num > elemInFifo) + num = elemInFifo; + for (int i = 0; i < num; i++) { *data++ = io_pb_buffer[io_pb_rdidx]; if (++io_pb_rdidx >= AUDIO_PLAYBACK_BUFLEN) io_pb_rdidx = 0; } IO_PB_UNLOCK(); - - return 1; + + return num; } void io_clear_audio_fifos() @@ -225,3 +237,152 @@ void io_clear_audio_fifos() io_pb_write_fifo_clear(); io_cap_write_fifo_clear(); } + +// ================== RTTY FIFO =================== + +void clear_rtty_fifos(); + +#ifdef _WIN32_ +CRITICAL_SECTION rtty_tx_crit_sec; +CRITICAL_SECTION rtty_rx_crit_sec; +#define RTTY_TX_LOCK EnterCriticalSection(&rtty_tx_crit_sec) +#define RTTY_RX_LOCK EnterCriticalSection(&rtty_rx_crit_sec) +void RTTY_TX_UNLOCK() +{ + if (&rtty_tx_crit_sec != NULL) + LeaveCriticalSection(&rtty_tx_crit_sec); +} +void RTTY_RX_UNLOCK() +{ + if (&rtty_rx_crit_sec != NULL) + LeaveCriticalSection(&rtty_rx_crit_sec); +} +#endif + +#ifdef _LINUX_ +pthread_mutex_t rtty_tx_crit_sec; +pthread_mutex_t rtty_rx_crit_sec; +#define RTTY_TX_LOCK pthread_mutex_lock(&rtty_tx_crit_sec) +void RTTY_TX_UNLOCK() { pthread_mutex_unlock(&rtty_tx_crit_sec); } +#define RTTY_RX_LOCK pthread_mutex_lock(&rtty_rx_crit_sec) +void RTTY_RX_UNLOCK() { pthread_mutex_unlock(&rtty_rx_crit_sec); } +#endif + +void rtty_init_pipes() +{ +#ifdef _WIN32_ + if (&rtty_tx_crit_sec != NULL) DeleteCriticalSection(&rtty_tx_crit_sec); + InitializeCriticalSection(&rtty_tx_crit_sec); + + if (&rtty_rx_crit_sec != NULL) DeleteCriticalSection(&rtty_rx_crit_sec); + InitializeCriticalSection(&rtty_rx_crit_sec); + +#endif + + clear_rtty_fifos(); +} + +#define RTTY_FIFOLEN 200 + +int rtty_tx_wridx = 0; +int rtty_tx_rdidx = 0; +char rtty_tx_buffer[RTTY_FIFOLEN]; + +int rtty_rx_wridx = 0; +int rtty_rx_rdidx = 0; +char rtty_rx_buffer[RTTY_FIFOLEN]; + +// TX char from GUI to RTTY TX thread + +void clear_rtty_fifos() +{ + rtty_tx_wridx = rtty_tx_rdidx = 0; + rtty_rx_wridx = rtty_rx_rdidx = 0; +} + +int rtty_tx_fifo_freespace() +{ + int elemInFifo = (rtty_tx_wridx + RTTY_FIFOLEN - rtty_tx_rdidx) % RTTY_FIFOLEN; + return RTTY_FIFOLEN - elemInFifo; +} + +void clear_rtty_txfifo() +{ + RTTY_TX_LOCK; + rtty_tx_wridx = rtty_tx_rdidx = 0; + RTTY_TX_UNLOCK(); +} + +void rtty_tx_write_fifo(char c) +{ + RTTY_TX_LOCK; + + // check if there is free space in fifo + if (rtty_tx_fifo_freespace() == 0) + { + RTTY_TX_UNLOCK(); + return; + } + + rtty_tx_buffer[rtty_tx_wridx] = c; + if (++rtty_tx_wridx >= RTTY_FIFOLEN) rtty_tx_wridx = 0; + RTTY_TX_UNLOCK(); +} + +int rtty_tx_read_fifo(char *pc) +{ + RTTY_TX_LOCK; + + if (rtty_tx_rdidx == rtty_tx_wridx) + { + // Fifo empty, no data available + RTTY_TX_UNLOCK(); + return 0; + } + + *pc = rtty_tx_buffer[rtty_tx_rdidx]; + if (++rtty_tx_rdidx >= RTTY_FIFOLEN) rtty_tx_rdidx = 0; + RTTY_TX_UNLOCK(); + + return 1; +} + +int rtty_rx_fifo_freespace() +{ + int elemInFifo = (rtty_rx_wridx + RTTY_FIFOLEN - rtty_rx_rdidx) % RTTY_FIFOLEN; + return RTTY_FIFOLEN - elemInFifo; +} + +void rtty_rx_write_fifo(char c) +{ + RTTY_RX_LOCK; + + // check if there is free space in fifo + if (rtty_rx_fifo_freespace() == 0) + { + RTTY_RX_UNLOCK(); + return; + } + + rtty_rx_buffer[rtty_rx_wridx] = c; + if (++rtty_rx_wridx >= RTTY_FIFOLEN) rtty_rx_wridx = 0; + RTTY_RX_UNLOCK(); +} + +int rtty_rx_read_fifo(char* pc) +{ + RTTY_RX_LOCK; + + if (rtty_rx_rdidx == rtty_rx_wridx) + { + // Fifo empty, no data available + RTTY_RX_UNLOCK(); + return 0; + } + + *pc = rtty_rx_buffer[rtty_rx_rdidx]; + if (++rtty_rx_rdidx >= RTTY_FIFOLEN) rtty_rx_rdidx = 0; + RTTY_RX_UNLOCK(); + + return 1; +} diff --git a/hsmodem/fm.cpp b/hsmodem/fm.cpp new file mode 100755 index 0000000..2266498 --- /dev/null +++ b/hsmodem/fm.cpp @@ -0,0 +1,222 @@ + +#include "hsmodem.h" + +void initfm(); +void runfm(); + +freqmod fmmod; +freqdem fdem = NULL; +nco_crcf fm_dnnco = NULL; +nco_crcf fm_upnco = NULL; + +firfilt_crcf fm_q = NULL; + +void fmtest() +{ + static int f = 1; + if (f) + { + f = 0; + initfm(); + } + + runfm(); +} + +#define CENTERF 1700.0f + +/* +* fmin = 1200 Hz +* fmax = 2300 Hz +* fcarrier = 1700 Hz +* +* kf = max.deviation / samplerate +* max deviation = 2300 - 1700 = 600 Hz +* kf = 600/48000 = 0.0125 +* +* this results in: +* -0.99 ... 1100 Hz +* +0.99 ... 2300 Hz +*/ +const int sstv_fsync = 1200; +const int sstv_fblack = 1500; +const int sstv_fwhite = 2300; + +const int sstv_maxbw = (sstv_fwhite - sstv_fsync); +const float sstv_kf = ((float)sstv_maxbw / 2.0f) / (float)caprate; +const float sstv_carrier = (sstv_maxbw / 2) + sstv_fsync; + +// frequency values per millisecond +#define COLLECT 5 +const float per_ms = (float)COLLECT * 1000.0f / 48000.0f; +int realsync = 0; +const int maxpixel = 5000; +const int maxlines = 300; +int pidx = 0; +int lidx = 0; +uint8_t fmap[maxlines][maxpixel*2]; + +void initfm() +{ + fmmod = freqmod_create(sstv_kf); // modulator + fdem = freqdem_create(sstv_kf); + + // create NCO for up-mixing to 1500 Hz + float fm_RX_RADIANS_PER_SAMPLE = 2.0f * (float)M_PI * sstv_carrier / (float)caprate; + fm_upnco = nco_crcf_create(LIQUID_NCO); + nco_crcf_set_phase(fm_upnco, 0.0f); + nco_crcf_set_frequency(fm_upnco, fm_RX_RADIANS_PER_SAMPLE); + + // create NCO for down-mixing from 1500 Hz + fm_dnnco = nco_crcf_create(LIQUID_NCO); + nco_crcf_set_phase(fm_dnnco, 0.0f); + nco_crcf_set_frequency(fm_dnnco, fm_RX_RADIANS_PER_SAMPLE); + + // RX Filter + unsigned int flt_h_len = 31; // filter length + // we filter at 48k samp rate + float flt_fc = (float)sstv_fwhite / 2.0f / 48000.0f; // cutoff frequency + float flt_As = 40.0f; // stop-band attenuation + + fm_q = firfilt_crcf_create_kaiser(flt_h_len, flt_fc, flt_As, 0.0f); + firfilt_crcf_set_scale(fm_q, 2.0f * flt_fc); +} + +void runfm() +{ + int synpulse = 0; + int syncanz = 0; + float f; + liquid_float_complex s; // modulated signal + liquid_float_complex sbase; + liquid_float_complex sbasef; + float syntim = 0; + float sigtim = 0; + + while (keeprunning) + { + int ret = io_cap_read_fifo(&f); + if (ret == 0) + { + sleep_ms(1); + continue; + } + + nco_crcf_step(fm_dnnco); + s.real = f; + s.imag = f; + nco_crcf_mix_down(fm_dnnco, s, &sbase); + + // sharp filter + firfilt_crcf_push(fm_q, sbase); // push input sample + firfilt_crcf_execute(fm_q, &sbasef); // compute output + + float y; // output/demodulated message + freqdem_demodulate(fdem, sbasef, &y); + + // y: -1..+1 (fsync..fwhite) + y += 1; // y: 0..2 (fsync..fwhite) + y *= (sstv_maxbw/2); // y: 0..maxbw (1100) + y += sstv_fsync; // y: fsync..fwhite + int freq = (int)y; + + printf("%d ", freq); + if (freq < 2000) printf("\n"); + + static int farr[COLLECT]; + static int fidx = 0; + + farr[fidx] = freq; + if (++fidx < COLLECT) continue; + fidx = 0; + + for (int i = 0; i < COLLECT; i++) + freq += farr[i]; + freq /= COLLECT; + + if (freq < sstv_fsync) freq = sstv_fsync; + if (freq > sstv_fwhite) freq = sstv_fwhite; + + //printf("%d ", freq); + //if (freq < 2000) printf("\n"); + + syntim += per_ms; + sigtim += per_ms; + + // detect start of sync pulse + if (synpulse == 0 && freq < 1480 && sigtim > 430.0f) + { + // syn pulse starts + if (sigtim < 431.0f) + { + printf("syn pulse missed, forced after %10.6f\n", sigtim); + realsync = 0; + syncanz = 0; + } + else + { + printf("syn pulse starts after %10.6f\n", sigtim); + realsync = 1; + if(syncanz < 4) syncanz++; + if (syncanz == 3) + { + printf("picture start\n"); + lidx = 0; + } + } + synpulse = 1; + syntim = 0; + if (lidx < maxlines) lidx++; + } + + // detect end of syn pulse + if (synpulse == 1 && freq > 1480) + { + // syn pulse ends + // check if valid length + if (syntim > 4.0f) + { + printf("syn pulse ends after %10.6f. In Sync:%d, written:%d to line:%d\n",syntim,realsync,pidx,lidx); + synpulse = 0; + sigtim = 0; + pidx = 0; + } + } + + if (synpulse == 0) + { + fmap[lidx][pidx * 2] = freq >> 8; + fmap[lidx][pidx * 2 + 1] = freq & 0xff; + if (pidx < maxpixel) pidx++; + + if (lidx == 260) + { + FILE* fp = fopen("sstv.img", "wb"); + if(fp) + { + for (int i = 0; i < 260; i++) + { + fwrite(fmap[i], 1, maxpixel*2, fp); + } + fclose(fp); + printf("file saved\n"); + sleep_ms(10000); + } + } + } + + + + + //printf("%10.6f %10.6f %d\n", f, y, freq); + + /* + // monitor + nco_crcf_step(fm_upnco); + nco_crcf_mix_up(fm_upnco, sbasef, &s); + float usbf = s.real + s.imag; + + io_pb_write_fifo(usbf * 0.2f); // reduce volume and send to soundcard + */ + } +} \ No newline at end of file diff --git a/hsmodem/hsmodem.cpp b/hsmodem/hsmodem.cpp index 806d484..2ffcf13 100755 --- a/hsmodem/hsmodem.cpp +++ b/hsmodem/hsmodem.cpp @@ -56,6 +56,7 @@ int UdpDataPort_ModemToApp = 40133; // op mode depending values // default mode if not set by the app int speedmode = 4; +int set_speedmode = 4; int bitsPerSymbol = 2; // QPSK=2, 8PSK=3 int constellationSize = 4; // QPSK=4, 8PSK=8 @@ -208,10 +209,11 @@ int main(int argc, char* argv[]) { if (restart_modems == 1) { + printf("restart modem requested\n"); startModem(); restart_modems = 0; } - + //doArraySend(); if (VoiceAudioMode == VOICEMODE_INTERNALLOOP) { @@ -255,24 +257,34 @@ int main(int argc, char* argv[]) do_tuning(tuning); } - // demodulate incoming audio data stream - static uint64_t old_tm = 0; - uint64_t tm = getms(); - if (tm >= (old_tm + 1000)) + if (speedmode == 10) { - // read Audio device list every 1s - io_readAudioDevices(); - old_tm = tm; + //testall(); + //fmtest(); + sleep_ms(10); // nothing to do here } - int dret = demodulator(); - if (dret == 0) + else { - // no new data in fifo + // demodulate incoming audio data stream + static uint64_t old_tm = 0; + uint64_t tm = getms(); + if (tm >= (old_tm + 1000)) + { + // read Audio device list every 1s + io_readAudioDevices(); + old_tm = tm; + } + int dret = demodulator(); + if (dret == 0) + { + // no new data in fifo #ifdef _LINUX_ // not important how long to sleep, 10ms is fine - sleep_ms(10); + sleep_ms(10); #endif + } } + } printf("stopped: %d\n", keeprunning); @@ -283,7 +295,6 @@ int main(int argc, char* argv[]) closesocket(BC_sock_AppToModem); #endif - return 0; } @@ -298,7 +309,7 @@ typedef struct { } SPEEDRATE; // AudioRate, TX-Resampler, RX-Resampler/4, bit/symbol, Codec-Rate -SPEEDRATE sr[10] = { +SPEEDRATE sr[11] = { // BPSK modes {48000, 40,10, 1, 1200, 800}, {48000, 20, 5, 1, 2400, 2000}, @@ -314,10 +325,19 @@ SPEEDRATE sr[10] = { {48000, 24, 6, 3, 6000, 4800}, {44100, 20, 5, 3, 6600, 5200}, {48000, 20, 5, 3, 7200, 6000}, + + // RTTY + {48000, 0, 0, 0, 0, 0}, }; void startModem() { + printf("startModem\n"); + close_dsp(); + close_rtty(); + io_close_audio(); + speedmode = set_speedmode; + bitsPerSymbol = sr[speedmode].bpsym; constellationSize = (1 << bitsPerSymbol); // QPSK=4, 8PSK=8 @@ -328,10 +348,27 @@ void startModem() opusbitrate = sr[speedmode].codecrate; // int TX audio and modulator - close_dsp(); init_audio_result = io_init_sound(playbackDeviceName, captureDeviceName); _init_fft(); - init_dsp(); + if (speedmode < 10) + { + init_dsp(); + } + if (speedmode == 10) + { + rtty_txoff = 1; + init_rtty(); + } +} + +// called from UDP callback ! DO NOT call any system functions +void setSpeedmode(int spm) +{ + printf("set speedmode:%d\n", spm); + + set_speedmode = spm; + restart_modems = 1; + transmissions = 1000; // announcement at next TX } void io_setAudioDevices(uint8_t pbvol, uint8_t capvol, uint8_t announce, uint8_t pbls, uint8_t pbmic, char *pbname, char*capname) @@ -374,7 +411,8 @@ void bc_rxdata(uint8_t* pdata, int len, struct sockaddr_in* rxsock) * 5 ... DV mic volume * 6 ... safe mode number * 7 ... send Intro - * 8..9 ... unused + * 8 ... rtty autosync + * 9 ... unused * 10 .. 109 ... PB device name * 110 .. 209 ... CAP device name */ @@ -429,6 +467,7 @@ void bc_rxdata(uint8_t* pdata, int len, struct sockaddr_in* rxsock) io_setAudioDevices(pdata[1], pdata[2], pdata[3], pdata[4], pdata[5], (char*)(pdata + 10), (char*)(pdata + 110)); safemode = pdata[6]; sendIntro = pdata[7]; + rtty_autosync = pdata[8]; lastms = actms; } @@ -440,19 +479,13 @@ void appdata_rxdata(uint8_t* pdata, int len, struct sockaddr_in* rxsock) uint8_t type = pdata[0]; uint8_t minfo = pdata[1]; + //printf("from GUI: %d %d\n", pdata[0], pdata[1]); + // type values: see oscardata config.cs: frame types if (type == 16) { - // Byte 1 contains the resampler ratio for TX and RX modem - if (pdata[1] >= 12) - { - printf("wrong speedmode %d, ignoring\n", pdata[1]); - return; - } - speedmode = pdata[1]; - printf("set speedmode to %d\n", speedmode); - restart_modems = 1; - transmissions = 1000; // announcement at next TX + // Byte 1 contains the speed mode index + setSpeedmode(pdata[1]); return; } @@ -544,7 +577,7 @@ void appdata_rxdata(uint8_t* pdata, int len, struct sockaddr_in* rxsock) VoiceAudioMode = pdata[1]; codec = pdata[2]; - printf("LS:<%s> MIC:<%s> Mode:%d codec:%d\n", lsDeviceName, micDeviceName, VoiceAudioMode, codec); + //printf("LS:<%s> MIC:<%s> Mode:%d codec:%d\n", lsDeviceName, micDeviceName, VoiceAudioMode, codec); // init voice audio if (VoiceAudioMode == VOICEMODE_OFF) @@ -585,14 +618,61 @@ void appdata_rxdata(uint8_t* pdata, int len, struct sockaddr_in* rxsock) return; } - if (type == 29) + if (speedmode == 10) { - int v = minfo; - if (v > 128) - v = v - 255; - modifyRXfreq(float(v)); - return; + // rtty commands + if (type == 29) + { + int16_t freq = pdata[1]; + freq <<= 8; + freq += pdata[2]; + printf("set freq:%d\n", freq); + + rtty_modifyRXfreq(freq); + return; + } + + if (type == 30) + { + // rtty key pressed + rtty_tx_write_fifo(minfo); + return; + } + + if (type == 31) + { + // rtty string + int len = pdata[1]; + len <<= 8; + len += pdata[2]; + len++; // the first toTX command + //printf("hsmodem.cpp rtty_tx_write_fifo: "); + for (int i = 0; i < len; i++) + { + //printf("%c", pdata[3 + i]); + rtty_tx_write_fifo(pdata[3 + i]); + } + //printf("\n"); + return; + } + + if (type == 32) + { + // TX on/off, but send buffer + rtty_txoff = minfo?0:1; + return; + } + + if (type == 33) + { + // stop TX immediately + rtty_txoff = 1; + clear_rtty_txfifo(); + } } + if (type >= 29 && type <= 32) return; + + if (speedmode == 10) return; // here we are with payload data to be sent via the modulator @@ -741,8 +821,11 @@ void GRdata_rxdata(uint8_t* pdata, int len, struct sockaddr_in* rxsock) // reset modem if more than 2 frames have not been received trigger_resetmodem = 0; rx_in_sync = 0; - printf("no signal detected, reset RX modem\n"); - resetModem(); + if (speedmode < 10) + { + printf("no signal detected, reset RX modem\n"); + resetModem(); + } lasttime = acttm; } } diff --git a/hsmodem/hsmodem.h b/hsmodem/hsmodem.h index 43744d6..e1232ba 100755 --- a/hsmodem/hsmodem.h +++ b/hsmodem/hsmodem.h @@ -64,6 +64,7 @@ #include "symboltracker.h" #include "codec2.h" #include "soundio.h" +#include "baudot.h" #define jpg_tempfilename "rxdata.jpg" @@ -191,14 +192,15 @@ void write_sample_s16ne(char* ptr, double sample); int io_ls_fifo_usedspace(); void write_sample_float32ne(char* ptr, double sample); -void km_symtrack_cccf_create(int _ftype, - unsigned int _k, - unsigned int _m, - float _beta, - int _ms); -void km_symtrack_cccf_reset(int mode); -void km_symtrack_cccf_set_bandwidth(float _bw); -void km_symtrack_execute(liquid_float_complex _x, liquid_float_complex* _y, unsigned int* _ny, unsigned int* psym_out); +SYMTRACK* km_symtrack_cccf_create( int _ftype, + unsigned int _k, + unsigned int _m, + float _beta, + int _ms); +void km_symtrack_cccf_reset(SYMTRACK*, int mode); +void km_symtrack_cccf_set_bandwidth(SYMTRACK* , float _bw); +void km_symtrack_execute(SYMTRACK* ,liquid_float_complex _x, liquid_float_complex* _y, unsigned int* _ny, unsigned int* psym_out); +void km_symtrack_cccf_destroy(SYMTRACK*); void io_saveStream(float f); void playIntro(); @@ -206,10 +208,24 @@ void io_clear_voice_fifos(); float do_tuning(int send); void init_tune(); float singleFrequency(); -void rtty_tx(); int rtty_rx(); -void modifyRXfreq(float fr); +void modifyRXfreq(float diff_Hz, int absolute); void showbytestring16(char* title, uint16_t* data, int anz); +void rtty_sendChar(int c); +void init_rtty(); +int do_rtty(); +void make_FFTdata(float f); +void getMax(float fv); +void close_rtty(); +void close_a(); +void rtty_modifyRXfreq(int); +void showbitstring(char* title, uint8_t* data, int totallen, int anz); +void rtty_tx_write_fifo(char c); +int rtty_tx_read_fifo(char* pc); +void rtty_rx_write_fifo(char c); +int rtty_rx_read_fifo(char* pc); +void clear_rtty_txfifo(); +void fmtest(); extern int speedmode; @@ -252,9 +268,13 @@ extern int sendIntro; extern int tuning; extern uint32_t tuning_runtime; extern int marker; +extern int rtty_txoff; +extern int rtty_txidx; +extern int rtty_frequency; +extern int rtty_autosync; + #ifdef _LINUX_ int isRunning(char* prgname); void install_signal_handler(); -int isRunning(char* prgname); #endif diff --git a/hsmodem/hsmodem.vcxproj b/hsmodem/hsmodem.vcxproj index ffff591..3007ea5 100755 --- a/hsmodem/hsmodem.vcxproj +++ b/hsmodem/hsmodem.vcxproj @@ -223,6 +223,7 @@ + diff --git a/hsmodem/hsmodem.vcxproj.filters b/hsmodem/hsmodem.vcxproj.filters index f1cf294..ce43efa 100755 --- a/hsmodem/hsmodem.vcxproj.filters +++ b/hsmodem/hsmodem.vcxproj.filters @@ -122,5 +122,8 @@ Header Files + + Header Files + \ No newline at end of file diff --git a/hsmodem/liquid_if.cpp b/hsmodem/liquid_if.cpp index a42c075..aa3f2d4 100755 --- a/hsmodem/liquid_if.cpp +++ b/hsmodem/liquid_if.cpp @@ -200,7 +200,7 @@ void modulator(uint8_t sym_in) // adapt speed to soundcard samplerate int fs; - while(1) + while(keeprunning) { fs = io_pb_fifo_freespace(0); // wait until there is space in fifo @@ -218,7 +218,6 @@ void modulator(uint8_t sym_in) // =========== DEMODULATOR ============================= nco_crcf dnnco = NULL; -symtrack_cccf symtrack = NULL; firdecim_crcf decim = NULL; msresamp_crcf adecim = NULL; msresamp_crcf lsresamp = NULL; @@ -243,14 +242,8 @@ uint8_t maxTXLevel = 0; // maximum TXlevel over the last x samples in % float radians_per_sample = ((2.0f * (float)M_PI * (float)FREQUENCY) / (float)caprate); float last_radians_per_sample = 0; -float actfrequency = (float)FREQUENCY; -void modifyRXfreq(float diff_Hz) -{ - actfrequency += diff_Hz; - printf("set:%f Hz\n", actfrequency); - radians_per_sample = ((2.0f * (float)M_PI * actfrequency) / (float)caprate); -} +SYMTRACK *km_symtrack = NULL; void init_demodulator() { @@ -275,8 +268,8 @@ void init_demodulator() lsresamp = msresamp_crcf_create((float)(48000.0/44100.0), As_adecim); // create symbol tracking synchronizer - km_symtrack_cccf_create(ftype_st, k_st, m_st, beta_st, getMod()); - km_symtrack_cccf_set_bandwidth(bandwidth_st); + km_symtrack = km_symtrack_cccf_create(ftype_st, k_st, m_st, beta_st, getMod()); + km_symtrack_cccf_set_bandwidth(km_symtrack, bandwidth_st); } void close_demodulator() @@ -287,16 +280,17 @@ void close_demodulator() adecim = NULL; if (lsresamp) msresamp_crcf_destroy(lsresamp); lsresamp = NULL; - if (symtrack != NULL) symtrack_cccf_destroy(symtrack); - symtrack = NULL; if (dnnco != NULL) nco_crcf_destroy(dnnco); dnnco = NULL; + if (km_symtrack != NULL) km_symtrack_cccf_destroy(km_symtrack); + km_symtrack = NULL; } void resetModem() { //printf("Reset Symtrack\n"); - km_symtrack_cccf_reset(0xff); + if (km_symtrack == NULL) return; + km_symtrack_cccf_reset(km_symtrack,0xff); } // called for Audio-Samples (FFT) @@ -307,33 +301,6 @@ void make_FFTdata(float f) uint16_t* fft = make_waterfall(f, &fftlen); if (fft != NULL) { - // fft data are in fft[] size: 0..fftlen - // 10 Hz per value - float fdiff = (float)FREQUENCY - actfrequency; - // shift spectrum if we are off 1500 Hz - int diff10Hz = (int)(fdiff / 10.0); - if (diff10Hz != 0) - { - //printf("%d %f %f %d\n", FREQUENCY, actfrequency, fdiff, diff10Hz); - if (diff10Hz < 0) - { - diff10Hz = -diff10Hz; - for (int i = 0; i < (fftlen-diff10Hz); i++) - fft[i] = fft[i + diff10Hz]; - - for (int i = (fftlen - diff10Hz); i < fftlen; i++) - fft[i] = 0; - } - else - { - for (int i = fftlen-1; i >= diff10Hz; i--) - fft[i] = fft[i - diff10Hz]; - - for (int i = 0; i < diff10Hz; i++) - fft[i] = 0; - } - } - uint8_t txpl[10000]; if (fftlen > (10000 * 2 + 1)) { @@ -344,10 +311,17 @@ void make_FFTdata(float f) int bidx = 0; txpl[bidx++] = 4; // type 4: FFT data follows - int us = io_pb_fifo_usedBlocks(); + int us = 0; + if(speedmode < 10) + us = io_pb_fifo_usedBlocks(); + if (speedmode == 10) + { + // RTTY + us = io_pb_fifo_usedspace(); + } + if (us > 255 || ann_running == 1) us = 255; txpl[bidx++] = us; // usage of TX fifo - us = io_cap_fifo_usedPercent(); if (us > 255) us = 255; txpl[bidx++] = us; // usage of TX fifo @@ -355,8 +329,11 @@ 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 % + txpl[bidx++] = maxLevel; // actual max level on sound capture in % + txpl[bidx++] = maxTXLevel; // actual max level on sound playback in % + + txpl[bidx++] = rtty_frequency >> 8; // rtty qrg by autosync + txpl[bidx++] = rtty_frequency & 0xff; for (int i = 0; i < fftlen; i++) { @@ -491,7 +468,7 @@ static int const_idx = 0; unsigned int num_symbols_sync; liquid_float_complex syms; unsigned int nsym_out; // demodulated output symbol - km_symtrack_execute(y, &syms, &num_symbols_sync, &nsym_out); + km_symtrack_execute(km_symtrack,y, &syms, &num_symbols_sync, &nsym_out); if (num_symbols_sync > 1) printf("symtrack_cccf_execute %d output symbols ???\n", num_symbols_sync); if (num_symbols_sync != 0) diff --git a/hsmodem/main_helper.cpp b/hsmodem/main_helper.cpp index 4ad0325..6929c4b 100755 --- a/hsmodem/main_helper.cpp +++ b/hsmodem/main_helper.cpp @@ -100,9 +100,17 @@ void closeAllandTerminate() exit(0); } +void showbitstring(char* title, uint8_t* data, int totallen, int anz) +{ + printf("%s. len %d: ", title, totallen); + for (int i = 0; i < anz; i++) + printf("%01X ", data[i]); + printf("\n"); +} + void showbytestring(char *title, uint8_t *data, int totallen, int anz) { - printf("%s. Len %d: ",title, totallen); + printf("%s. len %d: ",title, totallen); for(int i=0; i1...downcount for off +int synced = 0; +int run_rtty_threads = 0; -void init_rtty() +int rtty_frequency = rtty_CENTERFREQUENCY; + +unsigned int m = 1; // number of bits/symbol +#define k 264 // filter samples/symbol +float SNRdB = 0.0f; // signal-to-noise ratio [dB] +float bandwidth = 0.001894f; // frequency spacing +unsigned int nfft = 1200; // FFT size for compute spectrum + +liquid_float_complex buf_tx[k]; // transmit buffer +liquid_float_complex buf_rx[k]; // transmit buffer +unsigned int sym_out; +float nstd; + +fskmod modi = NULL; +fskdem dem = NULL; + +int rtty_autosync = 0; + + +void rtty_modifyRXfreq(int f_Hz) { - close_rtty(); + printf("set:%d Hz\n", f_Hz); + rtty_frequency = f_Hz; + rtty_RX_RADIANS_PER_SAMPLE = ((2.0f * (float)M_PI * (float)f_Hz) / (float)caprate); +} - rtty_mod = fskmod_create(rtty_m, rtty_k, rtty_bandwith); - rtty_dem = fskdem_create(rtty_m, rtty_k, rtty_bandwith); - // TX: Interpolator Filter - rtty_k_SampPerSymb = caprate / rtty_CENTERFREQUENCY; +void sendRttyToGUI(uint8_t b) +{ + uint8_t txpl[7]; + txpl[0] = 6; // RTTY RX Byte follows + txpl[1] = b; // RXed byte + txpl[2] = rtty_txoff?0:1; // TX on/off + txpl[3] = synced; + txpl[4] = 0; // unused + txpl[5] = 0; + txpl[6] = 0; + sendUDP(appIP, UdpDataPort_ModemToApp, txpl, sizeof(txpl)); +} - // compute delay - while (rtty_tau_FracSymbOffset < 0) rtty_tau_FracSymbOffset += 1.0f; // ensure positive tau - float g = rtty_k_SampPerSymb * rtty_tau_FracSymbOffset; // number of samples offset - int ds = (int)floorf(g); // additional symbol delay - float dt = (g - (float)ds); // fractional sample offset - // force dt to be in [0.5,0.5] - if (dt > 0.5f) +/* +* space=lower tone (Bitvalue=1) +* mark=higher tone (Bitvalue=0) +* +* start (space) +* bit 4 +* bit 3 +* bit 2 +* bit 1 +* bit 0 +* stop (mark) +* stop (mark) +* +* send space if nothing to transmit +*/ +BAUDOTTAB baudot[] = { + {0b00010111,'Q','1',}, + {0b00010011,'W','2',}, + {0b00000001,'E','3',}, + {0b00001010,'R','4',}, + {0b00010000,'T','5',}, + {0b00010101,'Y','6',}, + {0b00000111,'U','7',}, + {0b00000110,'I','8',}, + {0b00011000,'O','9',}, + {0b00010110,'P','0',}, + {0b00000011,'A','-',}, + {0b00000101,'S','\'',}, + {0b00001001,'D','|',}, + {0b00001101,'F','|',}, + {0b00011010,'G','|',}, + {0b00010100,'H','|',}, + {0b00001011,'J','|',}, + {0b00001111,'K','(',}, + {0b00010010,'L',')',}, + {0b00010001,'Z','+',}, + {0b00011101,'X','/',}, + {0b00001110,'C',':',}, + {0b00011110,'V','=',}, + {0b00011001,'B','?',}, + {0b00001100,'N',',',}, + {0b00011100,'M','.',}, + {0b00001000,'\r','\r',}, + {0b00000010,'\n','\n',}, + {0b00000100,' ',' ',}, + {0b00011011,'@','@',}, // switch to numbers + {0b00011111,'§','§',}, // switch to letters (if already letter, then backspace) + {0xff,' ',' '} // end of table +}; + +int isletters = 1; + +void baudot_encoder(char c, uint8_t bd[2], int* pnum) +{ + int anz = 0; + int letters = 0; + + //printf("ascii:%c letter:%d (%d)\n", c, letters,isletters); + + if (c == '#') { - dt -= 1.0f; - ds++; - } - - // calculate filter coeffs - unsigned int h_len_NumFilterCoeefs = 2 * rtty_k_SampPerSymb * rtty_m_filterDelay_Symbols + 1; - float h[4000]; - if (h_len_NumFilterCoeefs >= 4000) - { - printf("rtty h in h_len_NumFilterCoeefs too small, need %d\n", h_len_NumFilterCoeefs); + rtty_txoff = 0; + *pnum = 0; return; } - liquid_firdes_prototype(LIQUID_FIRFILT_RRC, - rtty_k_SampPerSymb, - rtty_m_filterDelay_Symbols, - rtty_beta_excessBW, - dt, - h); - // create the filter - rtty_TX_interpolator = firinterp_crcf_create(rtty_k_SampPerSymb, h, h_len_NumFilterCoeefs); - // create NCO for upmixing to 1500 Hz - float rtty_RADIANS_PER_SAMPLE = ((2.0f * (float)M_PI * (float)rtty_CENTERFREQUENCY) / (float)caprate); + if (c == '~') + { + rtty_txoff = 10; + *pnum = 0; + return; + } + + if (c == 0x08) + { + // backspace does not exist in RTTY + return; + } + + if (c == ' ') + { + bd[anz++] = 4; + *pnum = anz; + return; + } + + if (c == '\n') + { + bd[anz++] = getBaudot('\n', letters); + bd[anz++] = getBaudot('\r', letters); + *pnum = anz; + return; + } + + if (c >= 'A' && c <= 'Z') letters = 1; + + if (letters == 1 && isletters == 0) + { + bd[anz++] = getBaudot('§', letters); + isletters = 1; + } + + if (letters == 0 && isletters == 1) + { + bd[anz++] = getBaudot('@', letters); + isletters = 0; + } + +bd[anz++] = getBaudot(c, letters); + +*pnum = anz; +} + +uint8_t getBaudot(char c, int letters) +{ + uint8_t res = 0; + int idx = 0; + + while (baudot[idx].baudot != 0xff) + { + if (letters == 1 && c == baudot[idx].letter) + { + res = baudot[idx].baudot; + break; + } + + if (letters == 0 && c == baudot[idx].number) + { + res = baudot[idx].baudot; + break; + } + + idx++; + } + return res; +} + +char baudot_decoder(char c) +{ + static int letter = 1; + + if (c == 0x1b) + { + letter = 0; + return 0; + } + + if (c == 0x1f) + { + letter = 1; + return 0; + } + + int idx = 0; + while (baudot[idx].baudot != 0xff) + { + if (baudot[idx].baudot == c) + { + if (letter == 1) + return baudot[idx].letter; + else + return baudot[idx].number; + } + idx++; + } + return 0; +} + + +/* +// ====================================================================================== +// Testfunctions: sends 010101.. in rtty speed and shows RX +// 1. disable rtty_init() +// 2. call testall() from hsmodem if speedmode==10 + + +void ttest(); +int rtest(); +void itest(); + + +void testall() +{ + static int f = 1; + if (f) + { + itest(); + f = 0; + } + + while (keeprunning) + { + ttest(); + while(keeprunning && rtest()); + sleep_ms(1); + } +} + +void itest() +{ + M = 1 << m; + nstd = powf(10.0f, -SNRdB / 20.0f); + + // create modulator/demodulator pair + modi = fskmod_create(m, k, bandwidth); + dem = fskdem_create(m, k, bandwidth); + fskdem_print(dem); + + // create NCO for up-mixing to 1500 Hz + rtty_RADIANS_PER_SAMPLE = ((2.0f * (float)M_PI * (float)rtty_CENTERFREQUENCY) / (float)caprate); rtty_upnco = nco_crcf_create(LIQUID_NCO); nco_crcf_set_phase(rtty_upnco, 0.0f); nco_crcf_set_frequency(rtty_upnco, rtty_RADIANS_PER_SAMPLE); + // create NCO for down-mixing from 1500 Hz + float rtty_RX_RADIANS_PER_SAMPLE = 2.0f * (float)M_PI * (float)rtty_CENTERFREQUENCY / (float)caprate; rtty_dnnco = nco_crcf_create(LIQUID_NCO); nco_crcf_set_phase(rtty_dnnco, 0.0f); - nco_crcf_set_frequency(rtty_dnnco, rtty_RADIANS_PER_SAMPLE); + nco_crcf_set_frequency(rtty_dnnco, rtty_RX_RADIANS_PER_SAMPLE); - rtty_decim = firdecim_crcf_create_kaiser(rtty_k_SampPerSymb, rtty_m_predec, rtty_As_predec); - firdecim_crcf_set_scale(rtty_decim, 1.0f / (float)rtty_k_SampPerSymb); + // modulate, demodulate, count errors + unsigned int num_symbol_errors = 0; } -void close_rtty() +void ttest() { - if (rtty_mod != NULL) fskmod_destroy(rtty_mod); - rtty_mod = NULL; - if (rtty_TX_interpolator != NULL) firinterp_crcf_destroy(rtty_TX_interpolator); - rtty_TX_interpolator = NULL; - if (rtty_upnco != NULL) nco_crcf_destroy(rtty_upnco); - rtty_upnco = NULL; - if (rtty_dnnco != NULL) nco_crcf_destroy(rtty_dnnco); - rtty_dnnco = NULL; - if (rtty_decim != NULL) firdecim_crcf_destroy(rtty_decim); - rtty_decim = NULL; - if (rtty_dem != NULL) fskdem_destroy(rtty_dem); - rtty_dem = NULL; -} + int i, j; + static unsigned int sym_in=0; -char text[6] = {"ABCD\n"}; -int tidx = 0; -int bitidx = 1; + int fs = io_pb_fifo_freespace(0); + if (fs < 20000) return; -void rtty_tx() -{ - if (rtty_mod == NULL) - init_rtty(); - - unsigned int sym = (text[tidx] & bitidx) ? 1 : 0; - bitidx <<= 1; - if (bitidx == 0x0100) + static int scnt = 0; + if (++scnt == 8) { - bitidx = 1; - tidx++; - if (tidx == 6) tidx = 0; + scnt = 0; + sym_in = 1 - sym_in; } + //unsigned int sym_in = rand() % M; - liquid_float_complex rtty_txbuf[33+1]; + //measure_speed_bps(1); - // gets one symbol at a speed of 45.45 - fskmod_modulate(rtty_mod, sym, rtty_txbuf); - // here we have the complex RTTY signal in baseband - // one symbol was expanded to rtty_k periods: - // 45.454545 * 33 = 1500 periods - - for (unsigned int i = 0; i < rtty_k; i++) + //printf("modulate\n"); + fskmod_modulate(modi, sym_in, &(buf_tx[0])); + + // move sample to 1,5kHz carrier + for (j = 0; j < k; j++) { - // resample it to the soundcard rate caprate - // interpolate by k_SampPerSymb - liquid_float_complex y[40]; - if (rtty_k_SampPerSymb >= 40) - { - printf("y in k_SampPerSymb too small, need %d\n", rtty_k_SampPerSymb); - return; - } + nco_crcf_step(rtty_upnco); + nco_crcf_mix_up(rtty_upnco, buf_tx[j], &(buf_tx1500[j])); - firinterp_crcf_execute(rtty_TX_interpolator, rtty_txbuf[i], y); - // here we have rtty_k_SampPerSymb samples in y[] in the baseband at caprate - // speed - - for (unsigned int i = 0; i < rtty_k_SampPerSymb; i++) - { - // move sample to 1,5kHz carrier - nco_crcf_step(rtty_upnco); + usbf = (buf_tx1500[j]).real + (buf_tx1500[j]).imag; - liquid_float_complex c; - nco_crcf_mix_up(rtty_upnco, y[i], &c); - float usb = c.real + c.imag; + //measure_speed_bps(1); - // speed: 48000 - // adapt speed to soundcard samplerate - int fs; - while (1) - { - fs = io_pb_fifo_freespace(0); - // wait until there is space in fifo - if (fs > 20000) break; - sleep_ms(10); - } - - io_pb_write_fifo(usb * 0.2f); // reduce volume and send to soundcard - } + io_pb_write_fifo(usbf * 0.2f); // reduce volume and send to soundcard } } -// RTTY: sample rate HAS TO BE 48000 -int rtty_rx() +int rtest() { - static liquid_float_complex ccol[500]; - static unsigned int ccol_idx = 0; + static int bridx = 0; - if (rtty_dnnco == NULL) return 0; - - // get one received sample + int j; float f; int ret = io_cap_read_fifo(&f); if (ret == 0) return 0; - if (VoiceAudioMode == VOICEMODE_LISTENAUDIOIN) - io_ls_write_fifo(f); + // noise + //printf("%f\n", f); + //f = f + nstd * randnf() * M_SQRT1_2; - // input volume - f *= softwareCAPvolume; - - //getMax(f); - //make_FFTdata(f * 100); - - // downconvert 1,5kHz into baseband, still at soundcard sample rate + (buf_rx1500[bridx]).real = f; + (buf_rx1500[bridx]).imag = f; nco_crcf_step(rtty_dnnco); + nco_crcf_mix_down(rtty_dnnco, buf_rx1500[bridx], &(buf_rx[bridx])); + bridx++; - liquid_float_complex in; - in.real = f; - in.imag = f; - liquid_float_complex c; - nco_crcf_mix_down(rtty_dnnco, in, &c); - - // c is the actual sample, converted to complex and shifted to baseband - - // this is the first decimator. We need to collect rtty_k_SampPerSymb number of samples - // then call execute which will give us one decimated sample - ccol[ccol_idx++] = c; - if (ccol_idx < rtty_k_SampPerSymb) return 1; - ccol_idx = 0; - - // we have rtty_k_SampPerSymb samples in ccol - liquid_float_complex y; - firdecim_crcf_execute(rtty_decim, ccol, &y); - // the output of the pre decimator is exactly one sample in y - // ready for demodulation - // here we have 1500 samples/s - // collect rtty_k (33) samples then demodulate, 1500/33 = 45.45 - static unsigned int cs = 0; - static liquid_float_complex camps[rtty_k]; - camps[cs] = y; - if (++cs < rtty_k) return 1; - cs = 0; - - //measure_speed_bps(1); - - unsigned int sym_out = fskdem_demodulate(rtty_dem, camps); - - static int sym = 0; - static int symidx = 0; - sym |= sym_out << symidx; - symidx++; - if (symidx == 8) + if (bridx == k) { - symidx = 0; - printf("%d: %c\n", sym, sym); - sym = 0; + bridx = 0; + + sym_out = fskdem_demodulate(dem, buf_rx); + + static int nlixd = 0; + + //measure_speed_bps(1); + + printf("%01X ", sym_out); + if (++nlixd == 16) + { + nlixd = 0; + printf("\n"); + } } + return 1; } +*/ +// ========================================================================== + +#ifdef _LINUX_ +void* rtty_tx_function(void* param); +void* rtty_rx_function(void* param); +#endif + +#ifdef _WIN32_ +void rtty_tx_function(void* param); +void rtty_rx_function(void* param); +#endif + +void init_rtty() +{ + //printf("wegen FM test, kein Init RTTY\n"); + //return; + + close_rtty(); + + printf("Init RTTY\n"); + nstd = powf(10.0f, -SNRdB / 20.0f); // SNR Simulation referenced to -1..+1 + + // create modulator/demodulator pair + modi = fskmod_create(m, k, bandwidth); + dem = fskdem_create(m, k, bandwidth); + + // create NCO for up-mixing to 1500 Hz + rtty_RADIANS_PER_SAMPLE = ((2.0f * (float)M_PI * (float)rtty_CENTERFREQUENCY) / (float)caprate); + rtty_upnco = nco_crcf_create(LIQUID_NCO); + nco_crcf_set_phase(rtty_upnco, 0.0f); + nco_crcf_set_frequency(rtty_upnco, rtty_RADIANS_PER_SAMPLE); + + // create NCO for down-mixing from 1500 Hz + rtty_RX_RADIANS_PER_SAMPLE = 2.0f * (float)M_PI * (float)rtty_CENTERFREQUENCY / (float)caprate; + rtty_dnnco = nco_crcf_create(LIQUID_NCO); + nco_crcf_set_phase(rtty_dnnco, 0.0f); + nco_crcf_set_frequency(rtty_dnnco, rtty_RX_RADIANS_PER_SAMPLE); + + // RTTY RX Filter + rtty_q = firfilt_crcf_create_kaiser(flt_h_len, flt_fc, flt_As, 0.0f); + firfilt_crcf_set_scale(rtty_q, 2.0f * flt_fc); + + // create the rtty TX threads + static int f = 1; + if (f) + { + f = 0; + +#ifdef _LINUX_ + pthread_t rtty_txthread; + pthread_create(&rtty_txthread, NULL, rtty_tx_function, NULL); + pthread_t rtty_rxthread; + pthread_create(&rtty_rxthread, NULL, rtty_rx_function, NULL); +#endif +#ifdef _WIN32_ + _beginthread(rtty_tx_function, 0, NULL); + _beginthread(rtty_rx_function, 0, NULL); +#endif + } + + run_rtty_threads = 1; +} + +void close_rtty() +{ + printf("Close RTTY\n"); + + run_rtty_threads = 0; + sleep_ms(100); + + if (modi != NULL) fskmod_destroy(modi); + modi = NULL; + + if (dem != NULL) fskdem_destroy(dem); + dem = NULL; + + if (rtty_upnco != NULL) nco_crcf_destroy(rtty_upnco); + rtty_upnco = NULL; + + if (rtty_dnnco != NULL) nco_crcf_destroy(rtty_dnnco); + rtty_dnnco = NULL; + + if (rtty_q != NULL) firfilt_crcf_destroy(rtty_q); + rtty_q = NULL; +} + +// RTTY TX thread +#ifdef _LINUX_ +void* rtty_tx_function(void* param) +{ + pthread_detach(pthread_self()); +#endif +#ifdef _WIN32_ +void rtty_tx_function(void* param) +{ +#endif + + uint8_t bd[2]; + int anz = 0; + + while (keeprunning) + { + while (run_rtty_threads == 0) + { + sleep_ms(100); + if (keeprunning == 0) + { +#ifdef _LINUX_ + pthread_exit(NULL); // self terminate this thread + return NULL; +#endif +#ifdef _WIN32_ + return; +#endif + } + } + + /*static int last_txoff = -2; + if (last_txoff != 0 && rtty_txoff == 0) + { + // just switched TX on + //printf("force Bu/Zi switch: %d %d\n", rtty_txoff, last_txoff); + isletters = isletters ? 0 : 1; // force Bu/Zi command + } + last_txoff = rtty_txoff;*/ + + char csend; + if (rtty_tx_read_fifo(&csend)) + { + baudot_encoder(csend, bd, &anz); + //printf("read fifo: %d -> %02X\n", csend, bd[0]); + } + else + { + bd[0] = 0x1f; // idle + anz = 1; + + if (rtty_txoff == 1) + { + sleep_ms(10); + continue; + } + + if (rtty_txoff > 1) rtty_txoff--; + } + + //if(bd[0] != 0x1f) printf("send chars: %02X\n",bd[0]); + + for (int i = 0; i < anz; i++) + { + char c = bd[i]; + // c is the baudot code, fill into final byte cs + uint8_t cs = 0; + cs |= ((c & 1) ? 0x40 : 0); + cs |= ((c & 2) ? 0x20 : 0); + cs |= ((c & 4) ? 0x10 : 0); + cs |= ((c & 8) ? 0x08 : 0); + cs |= ((c & 16) ? 0x04 : 0); + cs &= ~0x80; // Start bit to 1 + cs |= 3; // 2 stop bits + + // send cs bit per bit + for (int bitidx = 7; bitidx >= 0; bitidx--) + { + if (run_rtty_threads == 0) break; + + //measure_speed_bps(1); + + unsigned int sym_in = (cs & (1 << bitidx)) ? 1 : 0; + + for (int twice = 0; twice < 4; twice++) + { + if (bitidx == 0 && twice == 2) break; //last bit only once + + fskmod_modulate(modi, sym_in, &(buf_tx[0])); + + // move sample to 1,5kHz carrier + for (int j = 0; j < k; j++) + { + nco_crcf_step(rtty_upnco); + liquid_float_complex outb; + nco_crcf_mix_up(rtty_upnco, buf_tx[j], &outb); + + float usbf = outb.real + outb.imag; + + // adapt to audio sample rate + int fs; + while (keeprunning && run_rtty_threads) + { + fs = io_pb_fifo_usedspace(); + //printf("%d\n", fs); + // attention: if this number is too low, the audio write callback will not process it + if (fs < 24000) break; + sleep_ms(1); + } + + io_pb_write_fifo(usbf * 0.05f); // reduce volume and send to soundcard + } + } + } + } + } +#ifdef _LINUX_ + pthread_exit(NULL); // self terminate this thread + return NULL; +#endif +} + +// RTTY RX thread +#ifdef _LINUX_ +void* rtty_rx_function(void* param) +{ +pthread_detach(pthread_self()); +#endif +#ifdef _WIN32_ +void rtty_rx_function(void* param) +{ +#endif + + while (keeprunning) + { + while (run_rtty_threads == 0) + { + sleep_ms(100); + if (keeprunning == 0) + { +#ifdef _LINUX_ + pthread_exit(NULL); // self terminate this thread + return NULL; +#endif +#ifdef _WIN32_ + return; +#endif + } + } + + static int bridx = 0; + float f; + int ret = io_cap_read_fifo(&f); + if (ret) + { + if (VoiceAudioMode == VOICEMODE_LISTENAUDIOIN) + io_ls_write_fifo(f); + + // input volume + f *= softwareCAPvolume; + + // TODO check Multithreading !!!!!!!!! + getMax(f); + make_FFTdata(f * 25); + + static float last_rs = 0; + if (rtty_RX_RADIANS_PER_SAMPLE != last_rs) + { + // tuning freq was changed, set NCO + nco_crcf_set_frequency(rtty_dnnco, rtty_RX_RADIANS_PER_SAMPLE); + last_rs = rtty_RX_RADIANS_PER_SAMPLE; + } + + liquid_float_complex rx1500; + rx1500.real = f; + rx1500.imag = f; + nco_crcf_step(rtty_dnnco); + liquid_float_complex dc_out; + nco_crcf_mix_down(rtty_dnnco, rx1500, &dc_out); + + // sharp filter + firfilt_crcf_push(rtty_q, dc_out); // push input sample + firfilt_crcf_execute(rtty_q, &(buf_rx[bridx])); // compute output + + bridx++; + + if (bridx == k) + { + bridx = 0; + + sym_out = fskdem_demodulate(dem, buf_rx); + + int db = evalSymbols(sym_out); + if (db != -1) + { + char lt = baudot_decoder((uint8_t)db); + //printf("rxbyte:%02X deoced:%02X\n", db, lt); + if (lt > 0) + sendRttyToGUI(lt); + } + } + } + else + sleep_ms(1); + } + +#ifdef _LINUX_ + pthread_exit(NULL); // self terminate this thread + return NULL; +#endif +} + + +// get the bit level, +// offs ... offset from beginning of the symbol buffer in bits, +// so offset 0 ist the beginning +// and offset 1 is the "overs" bit, i.e.: symbol[4] +// this eliminates the need of thinking in oversampled bits + +const int maxsym = 8; // stop-start-1-2-3-4-5-stop +const int overs = 4; // symbols per bit +uint8_t symbuf[maxsym * overs]; +int bitcnt = 0; + +uint8_t getBit(int offs) +{ + // we have overs symbols per bit + // the first or maybe last symbol may be wrong, so we don't use it + // looks like that ignoring the first sample is the best solution + // lets evaluate the value of three symbols + int pos = offs * overs; + uint8_t h = 0, l = 0; + for (int i = 0+1; i < overs - 1+1; i++) + { + if (symbuf[pos + i]) h++; + else l++; + } + + return (h > l) ? 1 : 0; +} + +uint8_t getDatebyte() +{ + uint8_t db = 0; + + db |= getBit(2) ? 0x01 : 0; + db |= getBit(3) ? 0x02 : 0; + db |= getBit(4) ? 0x04 : 0; + db |= getBit(5) ? 0x08 : 0; + db |= getBit(6) ? 0x10 : 0; + + return db; +} + +// check if there is a complete frame in the symbol buffer +int findStart() +{ + if ((synced == 0 || bitcnt > overs * 6) && symbuf[3] == 1 && symbuf[4] == 0) + { + if (getBit(0) == 1 && getBit(1) == 0 && getBit(7) == 1) + { + //printf("possible Frame Detection at index:%d\n", bitcnt); + bitcnt = 0; + synced = 1; + return getDatebyte(); + } + else + synced = 0; + } + bitcnt++; + + return -1; +} + +int evalSymbols(uint8_t sym) +{ + // feed smbol in buffer + memmove(symbuf, symbuf + 1, maxsym * overs - 1); + symbuf[maxsym * overs - 1] = sym; + + //showbitstring("rx: ", symbuf, sizeof(symbuf), sizeof(symbuf)); + + int db = findStart(); + if (db != -1) + { + //printf("Data_ %02X\n", db); + } + return db; +} diff --git a/hsmodem/soundio.cpp b/hsmodem/soundio.cpp index c3839a0..c44d5aa 100755 --- a/hsmodem/soundio.cpp +++ b/hsmodem/soundio.cpp @@ -36,7 +36,7 @@ struct SoundIoDevice* io_cap_device = NULL; struct SoundIoInStream* instream = NULL; struct SoundIoOutStream* outstream = NULL; -float latenz = 0.1f; +float latenz = 0.1f; // long (some seconds) delay can be caused by SDR console (not this program and not the VAC) typedef struct _AUDIODEV_ { @@ -83,6 +83,7 @@ static void get_channel_layout(const struct SoundIoChannelLayout* layout) int print_device(struct SoundIoDevice* device) { + if (soundio == NULL) return 0; if (!device->probe_error) { // ignore if exists @@ -119,6 +120,7 @@ int print_device(struct SoundIoDevice* device) static int scan_devices(struct SoundIo* soundio) { + if (soundio == NULL) return 0; audiodevidx = 0; for (int i = 0; i < soundio_input_device_count(soundio); i++) { @@ -224,14 +226,14 @@ int min_int(int a, int b) void read_callback(struct SoundIoInStream* instream, int frame_count_min, int frame_count_max) { int err; - if (instream == NULL) return; + if (instream == NULL || soundio == NULL) return; //printf("cap: %d %d\n", frame_count_min, frame_count_max); //int chans = instream->layout.channel_count; struct SoundIoChannelArea* areas; // samples are in areas.ptr int frames_left = frame_count_max; // take all - while (1) + while (keeprunning) { int frame_count = frames_left; if ((err = soundio_instream_begin_read(instream, &areas, &frame_count))) @@ -340,6 +342,7 @@ static double seconds_offset = 0.0; static void write_callback(struct SoundIoOutStream* outstream, int frame_count_min, int frame_count_max) { + if(outstream == NULL || soundio == NULL) return; //printf("pb: %d %d\n", frame_count_min, frame_count_max); #ifdef SINEWAVETEST double float_sample_rate = outstream->sample_rate; @@ -431,7 +434,7 @@ int io_init_sound(char *pbname, char *capname) init_audio_result = 0; printf("\n ==== IO INIT AUDIO devices ====\n"); - printf("requested\nTX:<%s>\nRX:<%s>\ncapture rate:%d\n\n",pbname,capname,caprate); + //printf("requested\nTX:<%s>\nRX:<%s>\ncapture rate:%d\n\n",pbname,capname,caprate); io_close_audio(); diff --git a/hsmodem/symboltracker.cpp b/hsmodem/symboltracker.cpp index 41bd425..8e0b375 100755 --- a/hsmodem/symboltracker.cpp +++ b/hsmodem/symboltracker.cpp @@ -1,7 +1,6 @@ #include "hsmodem.h" -SYMTRACK km_symtrack; -SYMTRACK* q = &km_symtrack; + // create km_symtrack object with basic parameters // _ftype : filter type (e.g. LIQUID_FIRFILT_RRC) @@ -9,7 +8,7 @@ SYMTRACK* q = &km_symtrack; // _m : filter delay (symbols) // _beta : filter excess bandwidth // _ms : modulation scheme (e.g. LIQUID_MODEM_QPSK) -void km_symtrack_cccf_create(int _ftype, +SYMTRACK* km_symtrack_cccf_create(int _ftype, unsigned int _k, unsigned int _m, float _beta, @@ -17,7 +16,7 @@ void km_symtrack_cccf_create(int _ftype, { // validate input if (_k < 2) - printf((char *)"symtrack_cccf_create(), filter samples/symbol must be at least 2\n"); + printf((char*)"symtrack_cccf_create(), filter samples/symbol must be at least 2\n"); if (_m == 0) printf((char*)"symtrack_cccf_create(), filter delay must be greater than zero\n"); if (_beta <= 0.0f || _beta > 1.0f) @@ -25,6 +24,9 @@ void km_symtrack_cccf_create(int _ftype, if (_ms == LIQUID_MODEM_UNKNOWN || _ms >= LIQUID_MODEM_NUM_SCHEMES) printf((char*)"symtrack_cccf_create(), invalid modulation scheme\n"); + // allocate memory for main object + SYMTRACK *q = (SYMTRACK *) malloc(sizeof(SYMTRACK)); + // set input parameters q->filter_type = _ftype; q->k = _k; @@ -54,14 +56,33 @@ void km_symtrack_cccf_create(int _ftype, q->demod = modem_create((modulation_scheme)q->mod_scheme); // set default bandwidth - km_symtrack_cccf_set_bandwidth(0.9f); + km_symtrack_cccf_set_bandwidth(q, 0.9f); // reset and return main object - km_symtrack_cccf_reset(0xff); + km_symtrack_cccf_reset(q, 0xff); + + return q; } -void km_symtrack_cccf_reset(int mode) +void km_symtrack_cccf_destroy(SYMTRACK *_q) { + if (_q == NULL) return; + + // destroy objects + agc_crcf_destroy(_q->agc); + symsync_crcf_destroy(_q->symsync); + eqlms_cccf_destroy(_q->eq); + nco_crcf_destroy(_q->nco); + modem_destroy(_q->demod); + + // free main object + free(_q); +} + +void km_symtrack_cccf_reset(SYMTRACK* q, int mode) +{ + if (q == NULL) return; + // reset objects if (mode & 1) agc_crcf_reset(q->agc); if (mode & 2) symsync_crcf_reset(q->symsync); @@ -74,7 +95,7 @@ void km_symtrack_cccf_reset(int mode) q->num_syms_rx = 0; } -void km_symtrack_cccf_set_bandwidth(float _bw) +void km_symtrack_cccf_set_bandwidth(SYMTRACK *q, float _bw) { // validate input if (_bw < 0) @@ -106,8 +127,10 @@ void km_symtrack_cccf_set_bandwidth(float _bw) // _x : input data sample // _y : output data array // _ny : number of samples written to output buffer -void km_symtrack_execute(liquid_float_complex _x, liquid_float_complex* _y, unsigned int* _ny, unsigned int *psym_out) +void km_symtrack_execute(SYMTRACK* q, liquid_float_complex _x, liquid_float_complex* _y, unsigned int* _ny, unsigned int *psym_out) { + if (q == NULL) return; + liquid_float_complex v; // output sample unsigned int i; unsigned int num_outputs = 0; diff --git a/hsmodem/tuning.cpp b/hsmodem/tuning.cpp index 5580d31..090b1a0 100755 --- a/hsmodem/tuning.cpp +++ b/hsmodem/tuning.cpp @@ -79,7 +79,7 @@ float do_tuning(int send) // adapt speed to soundcard samplerate int fs; - while (1) + while (keeprunning) { fs = io_pb_fifo_freespace(0); // wait until there is space in fifo diff --git a/hsmodem/voiceio.cpp b/hsmodem/voiceio.cpp index 268d388..f02f28a 100755 --- a/hsmodem/voiceio.cpp +++ b/hsmodem/voiceio.cpp @@ -46,7 +46,7 @@ void read_voicecallback(struct SoundIoInStream* instream, int frame_count_min, i struct SoundIoChannelArea* areas; // samples are in areas.ptr int frames_left = frame_count_max; // take all - while (1) + while (keeprunning) { int frame_count = frames_left; if ((err = soundio_instream_begin_read(instream, &areas, &frame_count))) diff --git a/hsmodem/voiceprocessor.cpp b/hsmodem/voiceprocessor.cpp index a0406c0..763df73 100755 --- a/hsmodem/voiceprocessor.cpp +++ b/hsmodem/voiceprocessor.cpp @@ -168,7 +168,7 @@ void sendCodecToModulator(uint8_t *pdata, int len) toGR_sendData(payload, 6, 1 ,0); // 6 ... voice data, 1 ... valid voice data } - while (1) + while (keeprunning) { // we have to check if the TX fifo has enough data. In case of an underrun the Q(8A)PSK signal will be distorted int us = io_pb_fifo_usedspace(); diff --git a/hsmodemLinux/audio/announcement.pcm b/hsmodemLinux/audio/announcement.pcm deleted file mode 100644 index 84d6293..0000000 Binary files a/hsmodemLinux/audio/announcement.pcm and /dev/null differ diff --git a/hsmodemLinux/hsmodem b/hsmodemLinux/hsmodem index c1ed2a1..30eddd7 100755 Binary files a/hsmodemLinux/hsmodem and b/hsmodemLinux/hsmodem differ diff --git a/hsmodemLinux/oscardata.exe b/hsmodemLinux/oscardata.exe index 2568aac..a83dfd7 100755 Binary files a/hsmodemLinux/oscardata.exe and b/hsmodemLinux/oscardata.exe differ diff --git a/oscardata/oscardata/Form1.Designer.cs b/oscardata/oscardata/Form1.Designer.cs index 3747193..d05166b 100755 --- a/oscardata/oscardata/Form1.Designer.cs +++ b/oscardata/oscardata/Form1.Designer.cs @@ -43,10 +43,10 @@ this.tabPage_ber = new System.Windows.Forms.TabPage(); this.bt_allf = new System.Windows.Forms.Button(); this.lb_tuningqrgs = new System.Windows.Forms.Label(); + this.rtb = new System.Windows.Forms.RichTextBox(); this.button_stopBERtest = new System.Windows.Forms.Button(); this.imageList1 = new System.Windows.Forms.ImageList(this.components); this.button_startBERtest = new System.Windows.Forms.Button(); - this.rtb = new System.Windows.Forms.RichTextBox(); this.tabPage_image = new System.Windows.Forms.TabPage(); this.groupBox1 = new System.Windows.Forms.Panel(); this.cb_loop = new System.Windows.Forms.CheckBox(); @@ -97,7 +97,46 @@ this.label10 = new System.Windows.Forms.Label(); this.cb_mic = new System.Windows.Forms.ComboBox(); this.label11 = new System.Windows.Forms.Label(); + this.tabPage_rtty = new System.Windows.Forms.TabPage(); + this.label4 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.tb_rtty_TX = new System.Windows.Forms.TextBox(); + this.tb_rtty_RX = new System.Windows.Forms.TextBox(); + this.panel1 = new System.Windows.Forms.Panel(); + this.rb_rtty_real = new System.Windows.Forms.RadioButton(); + this.bt_rtty_text6 = new System.Windows.Forms.Button(); + this.bt_rtty_text5 = new System.Windows.Forms.Button(); + this.bt_rtty_text4 = new System.Windows.Forms.Button(); + this.bt_rtty_text3 = new System.Windows.Forms.Button(); + this.bt_rtty_text2 = new System.Windows.Forms.Button(); + this.bt_rtty_text1 = new System.Windows.Forms.Button(); + this.button5 = new System.Windows.Forms.Button(); + this.bt_rtty_RY = new System.Windows.Forms.Button(); + this.textBox2 = new System.Windows.Forms.TextBox(); + this.button4 = new System.Windows.Forms.Button(); + this.bt_rtty_cq = new System.Windows.Forms.Button(); + this.bt_rxfont = new System.Windows.Forms.Button(); + this.bt_rtty_answerCQ = new System.Windows.Forms.Button(); + this.button3 = new System.Windows.Forms.Button(); + this.bt_rtty_start = new System.Windows.Forms.Button(); + this.button1 = new System.Windows.Forms.Button(); + this.bt_rtty_end = new System.Windows.Forms.Button(); + this.textBox5 = new System.Windows.Forms.TextBox(); + this.bt_rtty_endqso = new System.Windows.Forms.Button(); + this.rb_rtty_edit = new System.Windows.Forms.RadioButton(); + this.bt_rtty_myinfo = new System.Windows.Forms.Button(); + this.rb_rtty_normal = new System.Windows.Forms.RadioButton(); + this.bt_rtty_station = new System.Windows.Forms.Button(); + this.bt_rtty_default = new System.Windows.Forms.Button(); + this.bt_rtty_tx = new System.Windows.Forms.Button(); + this.label_urname = new System.Windows.Forms.Label(); + this.tb_rtty_deftext = new System.Windows.Forms.TextBox(); + this.tb_urname = new System.Windows.Forms.TextBox(); + this.tb_urcall = new System.Windows.Forms.TextBox(); + this.label_urcall = new System.Windows.Forms.Label(); this.tabPage_setup = new System.Windows.Forms.TabPage(); + this.label_cfgpath = new System.Windows.Forms.Label(); + this.label_cfgpath_tit = new System.Windows.Forms.Label(); this.groupBox4 = new System.Windows.Forms.GroupBox(); this.label13 = new System.Windows.Forms.Label(); this.label12 = new System.Windows.Forms.Label(); @@ -123,6 +162,12 @@ this.cb_audioPB = new System.Windows.Forms.ComboBox(); this.cb_audioCAP = new System.Windows.Forms.ComboBox(); this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.tb_myqthloc = new System.Windows.Forms.TextBox(); + this.label14 = new System.Windows.Forms.Label(); + this.tb_myqth = new System.Windows.Forms.TextBox(); + this.lb_qth = new System.Windows.Forms.Label(); + this.tb_myname = new System.Windows.Forms.TextBox(); + this.lb_myname = new System.Windows.Forms.Label(); this.lb_rec = new System.Windows.Forms.Label(); this.tb_recintro = new System.Windows.Forms.TextBox(); this.bt_astop = new System.Windows.Forms.Button(); @@ -144,14 +189,16 @@ this.label_speed = new System.Windows.Forms.Label(); this.timer_searchmodem = new System.Windows.Forms.Timer(this.components); this.label_fifo = new System.Windows.Forms.Label(); - this.bt_blockinfo = new System.Windows.Forms.Button(); this.label_capfifo = new System.Windows.Forms.Label(); this.lb_rxsignal = new System.Windows.Forms.Label(); this.lb_rxsync = new System.Windows.Forms.Label(); - this.pb_rxsync = new System.Windows.Forms.PictureBox(); + this.pn1 = new System.Windows.Forms.Panel(); this.pb_rxsignal = new System.Windows.Forms.PictureBox(); - this.progressBar_capfifo = new oscardata.KmProgressBar(); + this.pb_rxsync = new System.Windows.Forms.PictureBox(); + this.cb_rx_autosync = new System.Windows.Forms.CheckBox(); + this.textBox6 = new System.Windows.Forms.TextBox(); this.progressBar_fifo = new oscardata.KmProgressBar(); + this.progressBar_capfifo = new oscardata.KmProgressBar(); this.vu_cap = new oscardata.KmProgressBar(); this.vu_pb = new oscardata.KmProgressBar(); this.statusStrip1.SuspendLayout(); @@ -173,6 +220,8 @@ ((System.ComponentModel.ISupportInitialize)(this.pb_voicePBstatus)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.tb_mic)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.tb_loadspeaker)).BeginInit(); + this.tabPage_rtty.SuspendLayout(); + this.panel1.SuspendLayout(); this.tabPage_setup.SuspendLayout(); this.groupBox4.SuspendLayout(); this.groupBox3.SuspendLayout(); @@ -184,8 +233,9 @@ ((System.ComponentModel.ISupportInitialize)(this.tb_PBvol)).BeginInit(); this.groupBox2.SuspendLayout(); this.tabPage_about.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)(this.pb_rxsync)).BeginInit(); + this.pn1.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.pb_rxsignal)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.pb_rxsync)).BeginInit(); this.SuspendLayout(); // // timer_udpTX @@ -204,9 +254,9 @@ this.toolStripStatusLabel, this.ts_ip, this.RXstatus}); - this.statusStrip1.Location = new System.Drawing.Point(0, 669); + this.statusStrip1.Location = new System.Drawing.Point(0, 671); this.statusStrip1.Name = "statusStrip1"; - this.statusStrip1.Size = new System.Drawing.Size(1293, 22); + this.statusStrip1.Size = new System.Drawing.Size(1296, 22); this.statusStrip1.TabIndex = 4; this.statusStrip1.Text = "statusStrip1"; // @@ -259,15 +309,16 @@ this.panel_txspectrum.Size = new System.Drawing.Size(442, 76); this.panel_txspectrum.TabIndex = 6; this.panel_txspectrum.Paint += new System.Windows.Forms.PaintEventHandler(this.panel_txspectrum_Paint); + this.panel_txspectrum.DoubleClick += new System.EventHandler(this.panel_txspectrum_DoubleClick); // // tabPage_ber // this.tabPage_ber.BackColor = System.Drawing.Color.Transparent; this.tabPage_ber.Controls.Add(this.bt_allf); this.tabPage_ber.Controls.Add(this.lb_tuningqrgs); + this.tabPage_ber.Controls.Add(this.rtb); this.tabPage_ber.Controls.Add(this.button_stopBERtest); this.tabPage_ber.Controls.Add(this.button_startBERtest); - this.tabPage_ber.Controls.Add(this.rtb); this.tabPage_ber.ImageIndex = 4; this.tabPage_ber.Location = new System.Drawing.Point(4, 23); this.tabPage_ber.Name = "tabPage_ber"; @@ -296,6 +347,15 @@ this.lb_tuningqrgs.TabIndex = 21; this.lb_tuningqrgs.Text = "Frequency Test:"; // + // rtb + // + this.rtb.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.rtb.Location = new System.Drawing.Point(6, 51); + this.rtb.Name = "rtb"; + this.rtb.Size = new System.Drawing.Size(1266, 494); + this.rtb.TabIndex = 0; + this.rtb.Text = ""; + // // button_stopBERtest // this.button_stopBERtest.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); @@ -327,6 +387,16 @@ this.imageList1.Images.SetKeyName(10, "transmit.png"); this.imageList1.Images.SetKeyName(11, "voice.png"); this.imageList1.Images.SetKeyName(12, "about.png"); + this.imageList1.Images.SetKeyName(13, "rtty.png"); + this.imageList1.Images.SetKeyName(14, "home-icon.png"); + this.imageList1.Images.SetKeyName(15, "ryry-icon.png"); + this.imageList1.Images.SetKeyName(16, "voice-icon.png"); + this.imageList1.Images.SetKeyName(17, "user-icon.png"); + this.imageList1.Images.SetKeyName(18, "answer.png"); + this.imageList1.Images.SetKeyName(19, "stop-icon.png"); + this.imageList1.Images.SetKeyName(20, "start-icon.png"); + this.imageList1.Images.SetKeyName(21, "endqso-icon.png"); + this.imageList1.Images.SetKeyName(22, "text-icon.png"); // // button_startBERtest // @@ -342,15 +412,6 @@ this.button_startBERtest.UseVisualStyleBackColor = true; this.button_startBERtest.Click += new System.EventHandler(this.button_startBERtest_Click); // - // rtb - // - this.rtb.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.rtb.Location = new System.Drawing.Point(6, 51); - this.rtb.Name = "rtb"; - this.rtb.Size = new System.Drawing.Size(1266, 494); - this.rtb.TabIndex = 0; - this.rtb.Text = ""; - // // tabPage_image // this.tabPage_image.BackColor = System.Drawing.Color.Transparent; @@ -531,6 +592,7 @@ this.tabControl1.Controls.Add(this.tabPage_file); this.tabControl1.Controls.Add(this.tabPage_audio); this.tabControl1.Controls.Add(this.tabPage_ber); + this.tabControl1.Controls.Add(this.tabPage_rtty); this.tabControl1.Controls.Add(this.tabPage_setup); this.tabControl1.Controls.Add(this.tabPage_about); this.tabControl1.ImageList = this.imageList1; @@ -948,9 +1010,490 @@ this.label11.TabIndex = 10; this.label11.Text = "Microphone:"; // + // tabPage_rtty + // + this.tabPage_rtty.Controls.Add(this.label4); + this.tabPage_rtty.Controls.Add(this.label3); + this.tabPage_rtty.Controls.Add(this.tb_rtty_TX); + this.tabPage_rtty.Controls.Add(this.tb_rtty_RX); + this.tabPage_rtty.Controls.Add(this.panel1); + this.tabPage_rtty.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.tabPage_rtty.ImageIndex = 13; + this.tabPage_rtty.Location = new System.Drawing.Point(4, 23); + this.tabPage_rtty.Name = "tabPage_rtty"; + this.tabPage_rtty.Size = new System.Drawing.Size(1280, 552); + this.tabPage_rtty.TabIndex = 7; + this.tabPage_rtty.Text = "RTTY"; + this.tabPage_rtty.UseVisualStyleBackColor = true; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label4.Location = new System.Drawing.Point(13, 393); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(29, 20); + this.label4.TabIndex = 32; + this.label4.Text = "TX"; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label3.Location = new System.Drawing.Point(13, 13); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(32, 20); + this.label3.TabIndex = 26; + this.label3.Text = "RX"; + // + // tb_rtty_TX + // + this.tb_rtty_TX.BackColor = System.Drawing.Color.AliceBlue; + this.tb_rtty_TX.BorderStyle = System.Windows.Forms.BorderStyle.None; + this.tb_rtty_TX.CharacterCasing = System.Windows.Forms.CharacterCasing.Upper; + this.tb_rtty_TX.Font = new System.Drawing.Font("Courier New", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.tb_rtty_TX.Location = new System.Drawing.Point(9, 416); + this.tb_rtty_TX.Multiline = true; + this.tb_rtty_TX.Name = "tb_rtty_TX"; + this.tb_rtty_TX.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; + this.tb_rtty_TX.Size = new System.Drawing.Size(675, 103); + this.tb_rtty_TX.TabIndex = 1; + this.tb_rtty_TX.TextChanged += new System.EventHandler(this.tb_rtty_TX_TextChanged); + this.tb_rtty_TX.KeyDown += new System.Windows.Forms.KeyEventHandler(this.tb_rtty_TX_KeyDown); + // + // tb_rtty_RX + // + this.tb_rtty_RX.BackColor = System.Drawing.Color.Cornsilk; + this.tb_rtty_RX.BorderStyle = System.Windows.Forms.BorderStyle.None; + this.tb_rtty_RX.CharacterCasing = System.Windows.Forms.CharacterCasing.Upper; + this.tb_rtty_RX.Font = new System.Drawing.Font("Courier New", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.tb_rtty_RX.Location = new System.Drawing.Point(9, 35); + this.tb_rtty_RX.Multiline = true; + this.tb_rtty_RX.Name = "tb_rtty_RX"; + this.tb_rtty_RX.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; + this.tb_rtty_RX.Size = new System.Drawing.Size(675, 348); + this.tb_rtty_RX.TabIndex = 2; + this.tb_rtty_RX.MouseDown += new System.Windows.Forms.MouseEventHandler(this.tb_rtty_RX_MouseDown); + // + // panel1 + // + this.panel1.BackColor = System.Drawing.Color.Transparent; + this.panel1.Controls.Add(this.textBox6); + this.panel1.Controls.Add(this.cb_rx_autosync); + this.panel1.Controls.Add(this.rb_rtty_real); + this.panel1.Controls.Add(this.bt_rtty_text6); + this.panel1.Controls.Add(this.bt_rtty_text5); + this.panel1.Controls.Add(this.bt_rtty_text4); + this.panel1.Controls.Add(this.bt_rtty_text3); + this.panel1.Controls.Add(this.bt_rtty_text2); + this.panel1.Controls.Add(this.bt_rtty_text1); + this.panel1.Controls.Add(this.button5); + this.panel1.Controls.Add(this.bt_rtty_RY); + this.panel1.Controls.Add(this.textBox2); + this.panel1.Controls.Add(this.button4); + this.panel1.Controls.Add(this.bt_rtty_cq); + this.panel1.Controls.Add(this.bt_rxfont); + this.panel1.Controls.Add(this.bt_rtty_answerCQ); + this.panel1.Controls.Add(this.button3); + this.panel1.Controls.Add(this.bt_rtty_start); + this.panel1.Controls.Add(this.button1); + this.panel1.Controls.Add(this.bt_rtty_end); + this.panel1.Controls.Add(this.textBox5); + this.panel1.Controls.Add(this.bt_rtty_endqso); + this.panel1.Controls.Add(this.rb_rtty_edit); + this.panel1.Controls.Add(this.bt_rtty_myinfo); + this.panel1.Controls.Add(this.rb_rtty_normal); + this.panel1.Controls.Add(this.bt_rtty_station); + this.panel1.Controls.Add(this.bt_rtty_default); + this.panel1.Controls.Add(this.bt_rtty_tx); + this.panel1.Controls.Add(this.label_urname); + this.panel1.Controls.Add(this.tb_rtty_deftext); + this.panel1.Controls.Add(this.tb_urname); + this.panel1.Controls.Add(this.tb_urcall); + this.panel1.Controls.Add(this.label_urcall); + this.panel1.Location = new System.Drawing.Point(696, 8); + this.panel1.Name = "panel1"; + this.panel1.Size = new System.Drawing.Size(564, 514); + this.panel1.TabIndex = 31; + // + // rb_rtty_real + // + this.rb_rtty_real.AutoSize = true; + this.rb_rtty_real.Location = new System.Drawing.Point(373, 203); + this.rb_rtty_real.Name = "rb_rtty_real"; + this.rb_rtty_real.Size = new System.Drawing.Size(47, 17); + this.rb_rtty_real.TabIndex = 33; + this.rb_rtty_real.Text = "Real"; + this.rb_rtty_real.UseVisualStyleBackColor = true; + this.rb_rtty_real.CheckedChanged += new System.EventHandler(this.rb_rtty_real_CheckedChanged); + // + // bt_rtty_text6 + // + this.bt_rtty_text6.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; + this.bt_rtty_text6.ImageIndex = 22; + this.bt_rtty_text6.ImageList = this.imageList1; + this.bt_rtty_text6.Location = new System.Drawing.Point(432, 293); + this.bt_rtty_text6.Name = "bt_rtty_text6"; + this.bt_rtty_text6.Size = new System.Drawing.Size(107, 25); + this.bt_rtty_text6.TabIndex = 32; + this.bt_rtty_text6.Text = "TEXT 6"; + this.bt_rtty_text6.UseVisualStyleBackColor = true; + this.bt_rtty_text6.Click += new System.EventHandler(this.bt_rtty_text6_Click); + // + // bt_rtty_text5 + // + this.bt_rtty_text5.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; + this.bt_rtty_text5.ImageIndex = 22; + this.bt_rtty_text5.ImageList = this.imageList1; + this.bt_rtty_text5.Location = new System.Drawing.Point(432, 264); + this.bt_rtty_text5.Name = "bt_rtty_text5"; + this.bt_rtty_text5.Size = new System.Drawing.Size(107, 25); + this.bt_rtty_text5.TabIndex = 31; + this.bt_rtty_text5.Text = "TEXT 5"; + this.bt_rtty_text5.UseVisualStyleBackColor = true; + this.bt_rtty_text5.Click += new System.EventHandler(this.bt_rtty_text5_Click); + // + // bt_rtty_text4 + // + this.bt_rtty_text4.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; + this.bt_rtty_text4.ImageIndex = 22; + this.bt_rtty_text4.ImageList = this.imageList1; + this.bt_rtty_text4.Location = new System.Drawing.Point(432, 235); + this.bt_rtty_text4.Name = "bt_rtty_text4"; + this.bt_rtty_text4.Size = new System.Drawing.Size(107, 25); + this.bt_rtty_text4.TabIndex = 30; + this.bt_rtty_text4.Text = "TEXT 4"; + this.bt_rtty_text4.UseVisualStyleBackColor = true; + this.bt_rtty_text4.Click += new System.EventHandler(this.bt_rtty_text4_Click); + // + // bt_rtty_text3 + // + this.bt_rtty_text3.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; + this.bt_rtty_text3.ImageIndex = 22; + this.bt_rtty_text3.ImageList = this.imageList1; + this.bt_rtty_text3.Location = new System.Drawing.Point(319, 293); + this.bt_rtty_text3.Name = "bt_rtty_text3"; + this.bt_rtty_text3.Size = new System.Drawing.Size(107, 25); + this.bt_rtty_text3.TabIndex = 29; + this.bt_rtty_text3.Text = "TEXT 3"; + this.bt_rtty_text3.UseVisualStyleBackColor = true; + this.bt_rtty_text3.Click += new System.EventHandler(this.bt_rtty_text3_Click); + // + // bt_rtty_text2 + // + this.bt_rtty_text2.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; + this.bt_rtty_text2.ImageIndex = 22; + this.bt_rtty_text2.ImageList = this.imageList1; + this.bt_rtty_text2.Location = new System.Drawing.Point(319, 264); + this.bt_rtty_text2.Name = "bt_rtty_text2"; + this.bt_rtty_text2.Size = new System.Drawing.Size(107, 25); + this.bt_rtty_text2.TabIndex = 28; + this.bt_rtty_text2.Text = "TEXT 2"; + this.bt_rtty_text2.UseVisualStyleBackColor = true; + this.bt_rtty_text2.Click += new System.EventHandler(this.bt_rtty_text2_Click); + // + // bt_rtty_text1 + // + this.bt_rtty_text1.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; + this.bt_rtty_text1.ImageIndex = 22; + this.bt_rtty_text1.ImageList = this.imageList1; + this.bt_rtty_text1.Location = new System.Drawing.Point(319, 235); + this.bt_rtty_text1.Name = "bt_rtty_text1"; + this.bt_rtty_text1.Size = new System.Drawing.Size(107, 25); + this.bt_rtty_text1.TabIndex = 27; + this.bt_rtty_text1.Text = "TEXT 1"; + this.bt_rtty_text1.UseVisualStyleBackColor = true; + this.bt_rtty_text1.Click += new System.EventHandler(this.bt_rtty_text1_Click); + // + // button5 + // + this.button5.BackColor = System.Drawing.Color.Transparent; + this.button5.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom; + this.button5.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.button5.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; + this.button5.ImageIndex = 1; + this.button5.ImageList = this.imageList1; + this.button5.Location = new System.Drawing.Point(39, 123); + this.button5.Name = "button5"; + this.button5.Size = new System.Drawing.Size(114, 38); + this.button5.TabIndex = 26; + this.button5.Text = "Stop TX"; + this.button5.UseVisualStyleBackColor = false; + this.button5.Click += new System.EventHandler(this.button5_Click); + // + // bt_rtty_RY + // + this.bt_rtty_RY.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; + this.bt_rtty_RY.ImageIndex = 15; + this.bt_rtty_RY.ImageList = this.imageList1; + this.bt_rtty_RY.Location = new System.Drawing.Point(179, 293); + this.bt_rtty_RY.Name = "bt_rtty_RY"; + this.bt_rtty_RY.Size = new System.Drawing.Size(134, 25); + this.bt_rtty_RY.TabIndex = 25; + this.bt_rtty_RY.Text = "RYRYRY..."; + this.bt_rtty_RY.UseVisualStyleBackColor = true; + this.bt_rtty_RY.Click += new System.EventHandler(this.bt_rtty_RY_Click); + // + // textBox2 + // + this.textBox2.BackColor = System.Drawing.SystemColors.Control; + this.textBox2.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.textBox2.Enabled = false; + this.textBox2.Font = new System.Drawing.Font("Courier New", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.textBox2.Location = new System.Drawing.Point(305, 18); + this.textBox2.Multiline = true; + this.textBox2.Name = "textBox2"; + this.textBox2.ReadOnly = true; + this.textBox2.Size = new System.Drawing.Size(186, 143); + this.textBox2.TabIndex = 12; + this.textBox2.Text = "Special Markers:\r\n%m ... my call\r\n%c ... ur call\r\n%n ... ur name\r\n%r ... stop TX\r" + + "\n"; + // + // button4 + // + this.button4.BackgroundImage = global::oscardata.Properties.Resources.foht; + this.button4.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom; + this.button4.Location = new System.Drawing.Point(1, 429); + this.button4.Name = "button4"; + this.button4.Size = new System.Drawing.Size(24, 24); + this.button4.TabIndex = 24; + this.button4.UseVisualStyleBackColor = true; + this.button4.Click += new System.EventHandler(this.button4_Click); + // + // bt_rtty_cq + // + this.bt_rtty_cq.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; + this.bt_rtty_cq.ImageIndex = 16; + this.bt_rtty_cq.ImageList = this.imageList1; + this.bt_rtty_cq.Location = new System.Drawing.Point(39, 177); + this.bt_rtty_cq.Name = "bt_rtty_cq"; + this.bt_rtty_cq.Size = new System.Drawing.Size(134, 25); + this.bt_rtty_cq.TabIndex = 3; + this.bt_rtty_cq.Text = "Call CQ"; + this.bt_rtty_cq.UseVisualStyleBackColor = true; + this.bt_rtty_cq.Click += new System.EventHandler(this.bt_rtty_cq_Click); + // + // bt_rxfont + // + this.bt_rxfont.BackgroundImage = global::oscardata.Properties.Resources.foht; + this.bt_rxfont.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom; + this.bt_rxfont.Location = new System.Drawing.Point(1, 59); + this.bt_rxfont.Name = "bt_rxfont"; + this.bt_rxfont.Size = new System.Drawing.Size(24, 24); + this.bt_rxfont.TabIndex = 23; + this.bt_rxfont.UseVisualStyleBackColor = true; + this.bt_rxfont.Click += new System.EventHandler(this.bt_rxfont_Click); + // + // bt_rtty_answerCQ + // + this.bt_rtty_answerCQ.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; + this.bt_rtty_answerCQ.ImageIndex = 18; + this.bt_rtty_answerCQ.ImageList = this.imageList1; + this.bt_rtty_answerCQ.Location = new System.Drawing.Point(39, 206); + this.bt_rtty_answerCQ.Name = "bt_rtty_answerCQ"; + this.bt_rtty_answerCQ.Size = new System.Drawing.Size(134, 25); + this.bt_rtty_answerCQ.TabIndex = 4; + this.bt_rtty_answerCQ.Text = "Answer CQ Call"; + this.bt_rtty_answerCQ.UseVisualStyleBackColor = true; + this.bt_rtty_answerCQ.Click += new System.EventHandler(this.bt_rtty_answerCQ_Click); + // + // button3 + // + this.button3.BackgroundImage = global::oscardata.Properties.Resources.clearscreen; + this.button3.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom; + this.button3.Location = new System.Drawing.Point(1, 399); + this.button3.Name = "button3"; + this.button3.Size = new System.Drawing.Size(24, 24); + this.button3.TabIndex = 22; + this.button3.UseVisualStyleBackColor = true; + this.button3.Click += new System.EventHandler(this.button3_Click); + // + // bt_rtty_start + // + this.bt_rtty_start.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; + this.bt_rtty_start.ImageIndex = 20; + this.bt_rtty_start.ImageList = this.imageList1; + this.bt_rtty_start.Location = new System.Drawing.Point(39, 235); + this.bt_rtty_start.Name = "bt_rtty_start"; + this.bt_rtty_start.Size = new System.Drawing.Size(134, 25); + this.bt_rtty_start.TabIndex = 5; + this.bt_rtty_start.Text = "Start Transmission"; + this.bt_rtty_start.UseVisualStyleBackColor = true; + this.bt_rtty_start.Click += new System.EventHandler(this.bt_rtty_start_Click); + // + // button1 + // + this.button1.BackgroundImage = global::oscardata.Properties.Resources.clearscreen; + this.button1.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom; + this.button1.Location = new System.Drawing.Point(1, 29); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(24, 24); + this.button1.TabIndex = 21; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click_1); + // + // bt_rtty_end + // + this.bt_rtty_end.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; + this.bt_rtty_end.ImageIndex = 19; + this.bt_rtty_end.ImageList = this.imageList1; + this.bt_rtty_end.Location = new System.Drawing.Point(39, 264); + this.bt_rtty_end.Name = "bt_rtty_end"; + this.bt_rtty_end.Size = new System.Drawing.Size(134, 25); + this.bt_rtty_end.TabIndex = 6; + this.bt_rtty_end.Text = "End Transmission"; + this.bt_rtty_end.UseVisualStyleBackColor = true; + this.bt_rtty_end.Click += new System.EventHandler(this.bt_rtty_end_Click); + // + // textBox5 + // + this.textBox5.BackColor = System.Drawing.SystemColors.Control; + this.textBox5.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.textBox5.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F); + this.textBox5.Location = new System.Drawing.Point(171, 67); + this.textBox5.Multiline = true; + this.textBox5.Name = "textBox5"; + this.textBox5.ReadOnly = true; + this.textBox5.Size = new System.Drawing.Size(117, 50); + this.textBox5.TabIndex = 20; + this.textBox5.Text = "Click Callsign and Names in RX-Windows"; + // + // bt_rtty_endqso + // + this.bt_rtty_endqso.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; + this.bt_rtty_endqso.ImageIndex = 21; + this.bt_rtty_endqso.ImageList = this.imageList1; + this.bt_rtty_endqso.Location = new System.Drawing.Point(39, 293); + this.bt_rtty_endqso.Name = "bt_rtty_endqso"; + this.bt_rtty_endqso.Size = new System.Drawing.Size(134, 25); + this.bt_rtty_endqso.TabIndex = 7; + this.bt_rtty_endqso.Text = "End QSO"; + this.bt_rtty_endqso.UseVisualStyleBackColor = true; + this.bt_rtty_endqso.Click += new System.EventHandler(this.bt_rtty_endqso_Click); + // + // rb_rtty_edit + // + this.rb_rtty_edit.AutoSize = true; + this.rb_rtty_edit.Location = new System.Drawing.Point(436, 203); + this.rb_rtty_edit.Name = "rb_rtty_edit"; + this.rb_rtty_edit.Size = new System.Drawing.Size(43, 17); + this.rb_rtty_edit.TabIndex = 19; + this.rb_rtty_edit.Text = "Edit"; + this.rb_rtty_edit.UseVisualStyleBackColor = true; + this.rb_rtty_edit.CheckedChanged += new System.EventHandler(this.rb_rtty_edit_CheckedChanged); + // + // bt_rtty_myinfo + // + this.bt_rtty_myinfo.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; + this.bt_rtty_myinfo.ImageIndex = 17; + this.bt_rtty_myinfo.ImageList = this.imageList1; + this.bt_rtty_myinfo.Location = new System.Drawing.Point(179, 235); + this.bt_rtty_myinfo.Name = "bt_rtty_myinfo"; + this.bt_rtty_myinfo.Size = new System.Drawing.Size(134, 25); + this.bt_rtty_myinfo.TabIndex = 8; + this.bt_rtty_myinfo.Text = "My Info"; + this.bt_rtty_myinfo.UseVisualStyleBackColor = true; + this.bt_rtty_myinfo.Click += new System.EventHandler(this.bt_rtty_myinfo_Click); + // + // rb_rtty_normal + // + this.rb_rtty_normal.AutoSize = true; + this.rb_rtty_normal.Checked = true; + this.rb_rtty_normal.Location = new System.Drawing.Point(320, 203); + this.rb_rtty_normal.Name = "rb_rtty_normal"; + this.rb_rtty_normal.Size = new System.Drawing.Size(39, 17); + this.rb_rtty_normal.TabIndex = 18; + this.rb_rtty_normal.TabStop = true; + this.rb_rtty_normal.Text = "TX"; + this.rb_rtty_normal.UseVisualStyleBackColor = true; + this.rb_rtty_normal.CheckedChanged += new System.EventHandler(this.rb_rtty_normal_CheckedChanged); + // + // bt_rtty_station + // + this.bt_rtty_station.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; + this.bt_rtty_station.ImageIndex = 14; + this.bt_rtty_station.ImageList = this.imageList1; + this.bt_rtty_station.Location = new System.Drawing.Point(179, 264); + this.bt_rtty_station.Name = "bt_rtty_station"; + this.bt_rtty_station.Size = new System.Drawing.Size(134, 25); + this.bt_rtty_station.TabIndex = 9; + this.bt_rtty_station.Text = "My Station"; + this.bt_rtty_station.UseVisualStyleBackColor = true; + this.bt_rtty_station.Click += new System.EventHandler(this.bt_rtty_station_Click); + // + // bt_rtty_default + // + this.bt_rtty_default.Enabled = false; + this.bt_rtty_default.Location = new System.Drawing.Point(305, 167); + this.bt_rtty_default.Name = "bt_rtty_default"; + this.bt_rtty_default.Size = new System.Drawing.Size(186, 23); + this.bt_rtty_default.TabIndex = 17; + this.bt_rtty_default.Text = "set Default Text"; + this.bt_rtty_default.UseVisualStyleBackColor = true; + this.bt_rtty_default.Click += new System.EventHandler(this.bt_rtty_default_Click); + // + // bt_rtty_tx + // + this.bt_rtty_tx.BackColor = System.Drawing.Color.LightGreen; + this.bt_rtty_tx.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.bt_rtty_tx.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; + this.bt_rtty_tx.ImageIndex = 9; + this.bt_rtty_tx.ImageList = this.imageList1; + this.bt_rtty_tx.Location = new System.Drawing.Point(39, 79); + this.bt_rtty_tx.Name = "bt_rtty_tx"; + this.bt_rtty_tx.Size = new System.Drawing.Size(114, 38); + this.bt_rtty_tx.TabIndex = 10; + this.bt_rtty_tx.Text = "TX on/off"; + this.bt_rtty_tx.UseVisualStyleBackColor = false; + this.bt_rtty_tx.Click += new System.EventHandler(this.bt_rtty_tx_Click); + // + // label_urname + // + this.label_urname.AutoSize = true; + this.label_urname.Location = new System.Drawing.Point(74, 46); + this.label_urname.Name = "label_urname"; + this.label_urname.Size = new System.Drawing.Size(63, 13); + this.label_urname.TabIndex = 16; + this.label_urname.Text = "Your Name:"; + // + // tb_rtty_deftext + // + this.tb_rtty_deftext.Font = new System.Drawing.Font("Courier New", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.tb_rtty_deftext.Location = new System.Drawing.Point(39, 341); + this.tb_rtty_deftext.Multiline = true; + this.tb_rtty_deftext.Name = "tb_rtty_deftext"; + this.tb_rtty_deftext.Size = new System.Drawing.Size(522, 153); + this.tb_rtty_deftext.TabIndex = 11; + this.tb_rtty_deftext.TextChanged += new System.EventHandler(this.tb_rtty_deftext_TextChanged); + // + // tb_urname + // + this.tb_urname.Location = new System.Drawing.Point(171, 43); + this.tb_urname.Name = "tb_urname"; + this.tb_urname.Size = new System.Drawing.Size(117, 20); + this.tb_urname.TabIndex = 15; + // + // tb_urcall + // + this.tb_urcall.Location = new System.Drawing.Point(171, 17); + this.tb_urcall.Name = "tb_urcall"; + this.tb_urcall.Size = new System.Drawing.Size(117, 20); + this.tb_urcall.TabIndex = 13; + // + // label_urcall + // + this.label_urcall.AutoSize = true; + this.label_urcall.Location = new System.Drawing.Point(74, 20); + this.label_urcall.Name = "label_urcall"; + this.label_urcall.Size = new System.Drawing.Size(71, 13); + this.label_urcall.TabIndex = 14; + this.label_urcall.Text = "Your Callsign:"; + // // tabPage_setup // this.tabPage_setup.BackColor = System.Drawing.Color.Transparent; + this.tabPage_setup.Controls.Add(this.label_cfgpath); + this.tabPage_setup.Controls.Add(this.label_cfgpath_tit); this.tabPage_setup.Controls.Add(this.groupBox4); this.tabPage_setup.Controls.Add(this.groupBox3); this.tabPage_setup.Controls.Add(this.groupBox2); @@ -961,6 +1504,24 @@ this.tabPage_setup.TabIndex = 4; this.tabPage_setup.Text = "Setup"; // + // label_cfgpath + // + this.label_cfgpath.AutoSize = true; + this.label_cfgpath.Location = new System.Drawing.Point(162, 441); + this.label_cfgpath.Name = "label_cfgpath"; + this.label_cfgpath.Size = new System.Drawing.Size(16, 13); + this.label_cfgpath.TabIndex = 17; + this.label_cfgpath.Text = "..."; + // + // label_cfgpath_tit + // + this.label_cfgpath_tit.AutoSize = true; + this.label_cfgpath_tit.Location = new System.Drawing.Point(17, 441); + this.label_cfgpath_tit.Name = "label_cfgpath_tit"; + this.label_cfgpath_tit.Size = new System.Drawing.Size(115, 13); + this.label_cfgpath_tit.TabIndex = 16; + this.label_cfgpath_tit.Text = "Configuration stored in:"; + // // groupBox4 // this.groupBox4.Controls.Add(this.label13); @@ -1254,6 +1815,12 @@ // // groupBox2 // + this.groupBox2.Controls.Add(this.tb_myqthloc); + this.groupBox2.Controls.Add(this.label14); + this.groupBox2.Controls.Add(this.tb_myqth); + this.groupBox2.Controls.Add(this.lb_qth); + this.groupBox2.Controls.Add(this.tb_myname); + this.groupBox2.Controls.Add(this.lb_myname); this.groupBox2.Controls.Add(this.lb_rec); this.groupBox2.Controls.Add(this.tb_recintro); this.groupBox2.Controls.Add(this.bt_astop); @@ -1276,12 +1843,61 @@ this.groupBox2.TabStop = false; this.groupBox2.Text = "Personal Settings"; // + // tb_myqthloc + // + this.tb_myqthloc.CharacterCasing = System.Windows.Forms.CharacterCasing.Upper; + this.tb_myqthloc.Location = new System.Drawing.Point(71, 99); + this.tb_myqthloc.Name = "tb_myqthloc"; + this.tb_myqthloc.Size = new System.Drawing.Size(104, 20); + this.tb_myqthloc.TabIndex = 35; + // + // label14 + // + this.label14.AutoSize = true; + this.label14.Location = new System.Drawing.Point(14, 102); + this.label14.Name = "label14"; + this.label14.Size = new System.Drawing.Size(54, 13); + this.label14.TabIndex = 34; + this.label14.Text = "QTHLOC:"; + // + // tb_myqth + // + this.tb_myqth.Location = new System.Drawing.Point(71, 72); + this.tb_myqth.Name = "tb_myqth"; + this.tb_myqth.Size = new System.Drawing.Size(104, 20); + this.tb_myqth.TabIndex = 33; + // + // lb_qth + // + this.lb_qth.AutoSize = true; + this.lb_qth.Location = new System.Drawing.Point(14, 75); + this.lb_qth.Name = "lb_qth"; + this.lb_qth.Size = new System.Drawing.Size(33, 13); + this.lb_qth.TabIndex = 32; + this.lb_qth.Text = "QTH:"; + // + // tb_myname + // + this.tb_myname.Location = new System.Drawing.Point(71, 46); + this.tb_myname.Name = "tb_myname"; + this.tb_myname.Size = new System.Drawing.Size(104, 20); + this.tb_myname.TabIndex = 31; + // + // lb_myname + // + this.lb_myname.AutoSize = true; + this.lb_myname.Location = new System.Drawing.Point(14, 49); + this.lb_myname.Name = "lb_myname"; + this.lb_myname.Size = new System.Drawing.Size(38, 13); + this.lb_myname.TabIndex = 30; + this.lb_myname.Text = "Name:"; + // // lb_rec // this.lb_rec.AutoSize = true; this.lb_rec.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.lb_rec.ForeColor = System.Drawing.Color.Red; - this.lb_rec.Location = new System.Drawing.Point(576, 101); + this.lb_rec.Location = new System.Drawing.Point(712, 101); this.lb_rec.Name = "lb_rec"; this.lb_rec.Size = new System.Drawing.Size(23, 13); this.lb_rec.TabIndex = 29; @@ -1293,7 +1909,7 @@ this.tb_recintro.BorderStyle = System.Windows.Forms.BorderStyle.None; this.tb_recintro.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.tb_recintro.ForeColor = System.Drawing.Color.Black; - this.tb_recintro.Location = new System.Drawing.Point(334, 100); + this.tb_recintro.Location = new System.Drawing.Point(470, 100); this.tb_recintro.Multiline = true; this.tb_recintro.Name = "tb_recintro"; this.tb_recintro.Size = new System.Drawing.Size(121, 19); @@ -1306,7 +1922,7 @@ this.bt_astop.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center; this.bt_astop.FlatStyle = System.Windows.Forms.FlatStyle.Flat; this.bt_astop.ForeColor = System.Drawing.SystemColors.Control; - this.bt_astop.Location = new System.Drawing.Point(527, 89); + this.bt_astop.Location = new System.Drawing.Point(663, 89); this.bt_astop.Name = "bt_astop"; this.bt_astop.Size = new System.Drawing.Size(32, 36); this.bt_astop.TabIndex = 27; @@ -1319,7 +1935,7 @@ this.bt_aplay.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center; this.bt_aplay.FlatStyle = System.Windows.Forms.FlatStyle.Flat; this.bt_aplay.ForeColor = System.Drawing.SystemColors.Control; - this.bt_aplay.Location = new System.Drawing.Point(489, 89); + this.bt_aplay.Location = new System.Drawing.Point(625, 89); this.bt_aplay.Name = "bt_aplay"; this.bt_aplay.Size = new System.Drawing.Size(32, 36); this.bt_aplay.TabIndex = 26; @@ -1332,7 +1948,7 @@ this.bt_arecord.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center; this.bt_arecord.FlatStyle = System.Windows.Forms.FlatStyle.Flat; this.bt_arecord.ForeColor = System.Drawing.SystemColors.Control; - this.bt_arecord.Location = new System.Drawing.Point(451, 89); + this.bt_arecord.Location = new System.Drawing.Point(587, 89); this.bt_arecord.Name = "bt_arecord"; this.bt_arecord.Size = new System.Drawing.Size(32, 36); this.bt_arecord.TabIndex = 25; @@ -1344,7 +1960,7 @@ this.cb_sendIntro.AutoSize = true; this.cb_sendIntro.Checked = true; this.cb_sendIntro.CheckState = System.Windows.Forms.CheckState.Checked; - this.cb_sendIntro.Location = new System.Drawing.Point(71, 104); + this.cb_sendIntro.Location = new System.Drawing.Point(207, 104); this.cb_sendIntro.Name = "cb_sendIntro"; this.cb_sendIntro.Size = new System.Drawing.Size(105, 17); this.cb_sendIntro.TabIndex = 24; @@ -1356,7 +1972,7 @@ this.cb_stampinfo.AutoSize = true; this.cb_stampinfo.Checked = true; this.cb_stampinfo.CheckState = System.Windows.Forms.CheckState.Checked; - this.cb_stampinfo.Location = new System.Drawing.Point(71, 84); + this.cb_stampinfo.Location = new System.Drawing.Point(207, 84); this.cb_stampinfo.Name = "cb_stampinfo"; this.cb_stampinfo.Size = new System.Drawing.Size(128, 17); this.cb_stampinfo.TabIndex = 23; @@ -1367,7 +1983,7 @@ // this.tb_info.Location = new System.Drawing.Point(243, 28); this.tb_info.Name = "tb_info"; - this.tb_info.Size = new System.Drawing.Size(413, 20); + this.tb_info.Size = new System.Drawing.Size(492, 20); this.tb_info.TabIndex = 22; this.tb_info.Text = "tnx fer QSO, vy 73"; // @@ -1395,7 +2011,7 @@ "8", "9", "10"}); - this.cb_announcement.Location = new System.Drawing.Point(453, 60); + this.cb_announcement.Location = new System.Drawing.Point(589, 60); this.cb_announcement.Name = "cb_announcement"; this.cb_announcement.Size = new System.Drawing.Size(56, 21); this.cb_announcement.TabIndex = 19; @@ -1407,7 +2023,7 @@ this.textBox4.BorderStyle = System.Windows.Forms.BorderStyle.None; this.textBox4.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.textBox4.ForeColor = System.Drawing.Color.Black; - this.textBox4.Location = new System.Drawing.Point(518, 62); + this.textBox4.Location = new System.Drawing.Point(654, 62); this.textBox4.Multiline = true; this.textBox4.Name = "textBox4"; this.textBox4.Size = new System.Drawing.Size(75, 19); @@ -1420,7 +2036,7 @@ this.textBox1.BorderStyle = System.Windows.Forms.BorderStyle.None; this.textBox1.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.textBox1.ForeColor = System.Drawing.Color.Black; - this.textBox1.Location = new System.Drawing.Point(259, 64); + this.textBox1.Location = new System.Drawing.Point(395, 64); this.textBox1.Multiline = true; this.textBox1.Name = "textBox1"; this.textBox1.Size = new System.Drawing.Size(196, 19); @@ -1430,7 +2046,7 @@ // tb_callsign // this.tb_callsign.CharacterCasing = System.Windows.Forms.CharacterCasing.Upper; - this.tb_callsign.Location = new System.Drawing.Point(71, 28); + this.tb_callsign.Location = new System.Drawing.Point(71, 20); this.tb_callsign.Name = "tb_callsign"; this.tb_callsign.Size = new System.Drawing.Size(104, 20); this.tb_callsign.TabIndex = 1; @@ -1438,7 +2054,7 @@ // label1 // this.label1.AutoSize = true; - this.label1.Location = new System.Drawing.Point(14, 31); + this.label1.Location = new System.Drawing.Point(14, 23); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(46, 13); this.label1.TabIndex = 0; @@ -1449,7 +2065,7 @@ this.cb_stampcall.AutoSize = true; this.cb_stampcall.Checked = true; this.cb_stampcall.CheckState = System.Windows.Forms.CheckState.Checked; - this.cb_stampcall.Location = new System.Drawing.Point(71, 64); + this.cb_stampcall.Location = new System.Drawing.Point(207, 64); this.cb_stampcall.Name = "cb_stampcall"; this.cb_stampcall.Size = new System.Drawing.Size(146, 17); this.cb_stampcall.TabIndex = 2; @@ -1472,7 +2088,7 @@ this.richTextBox1.BorderStyle = System.Windows.Forms.BorderStyle.None; this.richTextBox1.Location = new System.Drawing.Point(17, 22); this.richTextBox1.Name = "richTextBox1"; - this.richTextBox1.Size = new System.Drawing.Size(855, 527); + this.richTextBox1.Size = new System.Drawing.Size(573, 527); this.richTextBox1.TabIndex = 0; this.richTextBox1.Text = resources.GetString("richTextBox1.Text"); // @@ -1489,8 +2105,9 @@ "5500 8APSK BW: 2300 Hz", "6000 8APSK BW: 2500 Hz (QO-100 Transceiver)", "6600 8APSK BW: 2600 Hz", - "7200 8APSK BW: 2700 Hz (QO-100 SDR)"}); - this.cb_speed.Location = new System.Drawing.Point(658, 591); + "7200 8APSK BW: 2700 Hz (QO-100 SDR)", + "45.45 Baud RTTY"}); + this.cb_speed.Location = new System.Drawing.Point(122, 2); this.cb_speed.Name = "cb_speed"; this.cb_speed.Size = new System.Drawing.Size(304, 21); this.cb_speed.TabIndex = 11; @@ -1500,7 +2117,7 @@ // label_speed // this.label_speed.AutoSize = true; - this.label_speed.Location = new System.Drawing.Point(567, 594); + this.label_speed.Location = new System.Drawing.Point(31, 5); this.label_speed.Name = "label_speed"; this.label_speed.Size = new System.Drawing.Size(71, 13); this.label_speed.TabIndex = 12; @@ -1514,26 +2131,16 @@ // label_fifo // this.label_fifo.AutoSize = true; - this.label_fifo.Location = new System.Drawing.Point(567, 620); + this.label_fifo.Location = new System.Drawing.Point(31, 31); this.label_fifo.Name = "label_fifo"; this.label_fifo.Size = new System.Drawing.Size(55, 13); this.label_fifo.TabIndex = 14; this.label_fifo.Text = "TX Buffer:"; // - // bt_blockinfo - // - this.bt_blockinfo.Location = new System.Drawing.Point(1213, 591); - this.bt_blockinfo.Name = "bt_blockinfo"; - this.bt_blockinfo.Size = new System.Drawing.Size(68, 23); - this.bt_blockinfo.TabIndex = 13; - this.bt_blockinfo.Text = "Block Info"; - this.bt_blockinfo.UseVisualStyleBackColor = true; - this.bt_blockinfo.Click += new System.EventHandler(this.bt_blockinfo_Click); - // // label_capfifo // this.label_capfifo.AutoSize = true; - this.label_capfifo.Location = new System.Drawing.Point(567, 643); + this.label_capfifo.Location = new System.Drawing.Point(31, 54); this.label_capfifo.Name = "label_capfifo"; this.label_capfifo.Size = new System.Drawing.Size(56, 13); this.label_capfifo.TabIndex = 16; @@ -1542,7 +2149,7 @@ // lb_rxsignal // this.lb_rxsignal.AutoSize = true; - this.lb_rxsignal.Location = new System.Drawing.Point(984, 643); + this.lb_rxsignal.Location = new System.Drawing.Point(448, 54); this.lb_rxsignal.Name = "lb_rxsignal"; this.lb_rxsignal.Size = new System.Drawing.Size(57, 13); this.lb_rxsignal.TabIndex = 18; @@ -1551,46 +2158,76 @@ // lb_rxsync // this.lb_rxsync.AutoSize = true; - this.lb_rxsync.Location = new System.Drawing.Point(984, 596); + this.lb_rxsync.Location = new System.Drawing.Point(448, 7); this.lb_rxsync.Name = "lb_rxsync"; this.lb_rxsync.Size = new System.Drawing.Size(52, 13); this.lb_rxsync.TabIndex = 20; this.lb_rxsync.Text = "RX Sync:"; // - // pb_rxsync + // pn1 // - this.pb_rxsync.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("pb_rxsync.BackgroundImage"))); - this.pb_rxsync.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom; - this.pb_rxsync.Location = new System.Drawing.Point(1047, 591); - this.pb_rxsync.Name = "pb_rxsync"; - this.pb_rxsync.Size = new System.Drawing.Size(24, 24); - this.pb_rxsync.TabIndex = 19; - this.pb_rxsync.TabStop = false; + this.pn1.Controls.Add(this.progressBar_fifo); + this.pn1.Controls.Add(this.label_capfifo); + this.pn1.Controls.Add(this.label_speed); + this.pn1.Controls.Add(this.pb_rxsignal); + this.pn1.Controls.Add(this.lb_rxsync); + this.pn1.Controls.Add(this.progressBar_capfifo); + this.pn1.Controls.Add(this.cb_speed); + this.pn1.Controls.Add(this.lb_rxsignal); + this.pn1.Controls.Add(this.pb_rxsync); + this.pn1.Controls.Add(this.label_fifo); + this.pn1.Location = new System.Drawing.Point(540, 588); + this.pn1.Name = "pn1"; + this.pn1.Size = new System.Drawing.Size(538, 74); + this.pn1.TabIndex = 30; // // pb_rxsignal // this.pb_rxsignal.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("pb_rxsignal.BackgroundImage"))); this.pb_rxsignal.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom; - this.pb_rxsignal.Location = new System.Drawing.Point(1047, 636); + this.pb_rxsignal.Location = new System.Drawing.Point(511, 47); this.pb_rxsignal.Name = "pb_rxsignal"; this.pb_rxsignal.Size = new System.Drawing.Size(24, 24); this.pb_rxsignal.TabIndex = 17; this.pb_rxsignal.TabStop = false; // - // progressBar_capfifo + // pb_rxsync // - this.progressBar_capfifo.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(192)))), ((int)(((byte)(128))))); - this.progressBar_capfifo.Location = new System.Drawing.Point(658, 642); - this.progressBar_capfifo.Name = "progressBar_capfifo"; - this.progressBar_capfifo.Size = new System.Drawing.Size(304, 18); - this.progressBar_capfifo.Step = 1; - this.progressBar_capfifo.Style = System.Windows.Forms.ProgressBarStyle.Continuous; - this.progressBar_capfifo.TabIndex = 15; + this.pb_rxsync.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("pb_rxsync.BackgroundImage"))); + this.pb_rxsync.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom; + this.pb_rxsync.Location = new System.Drawing.Point(511, 2); + this.pb_rxsync.Name = "pb_rxsync"; + this.pb_rxsync.Size = new System.Drawing.Size(24, 24); + this.pb_rxsync.TabIndex = 19; + this.pb_rxsync.TabStop = false; + // + // cb_rx_autosync + // + this.cb_rx_autosync.AutoSize = true; + this.cb_rx_autosync.Location = new System.Drawing.Point(195, 146); + this.cb_rx_autosync.Name = "cb_rx_autosync"; + this.cb_rx_autosync.Size = new System.Drawing.Size(93, 17); + this.cb_rx_autosync.TabIndex = 34; + this.cb_rx_autosync.Text = "RX Auto Sync"; + this.cb_rx_autosync.UseVisualStyleBackColor = true; + // + // textBox6 + // + this.textBox6.BackColor = System.Drawing.SystemColors.Control; + this.textBox6.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.textBox6.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F); + this.textBox6.Location = new System.Drawing.Point(195, 167); + this.textBox6.Multiline = true; + this.textBox6.Name = "textBox6"; + this.textBox6.ReadOnly = true; + this.textBox6.Size = new System.Drawing.Size(93, 35); + this.textBox6.TabIndex = 35; + this.textBox6.Text = "or double click in spectrum"; // // progressBar_fifo // this.progressBar_fifo.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(128)))), ((int)(((byte)(255)))), ((int)(((byte)(255))))); - this.progressBar_fifo.Location = new System.Drawing.Point(658, 618); + this.progressBar_fifo.Location = new System.Drawing.Point(122, 29); this.progressBar_fifo.Maximum = 20; this.progressBar_fifo.Name = "progressBar_fifo"; this.progressBar_fifo.Size = new System.Drawing.Size(304, 18); @@ -1598,6 +2235,16 @@ this.progressBar_fifo.Style = System.Windows.Forms.ProgressBarStyle.Continuous; this.progressBar_fifo.TabIndex = 13; // + // progressBar_capfifo + // + this.progressBar_capfifo.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(192)))), ((int)(((byte)(128))))); + this.progressBar_capfifo.Location = new System.Drawing.Point(122, 53); + this.progressBar_capfifo.Name = "progressBar_capfifo"; + this.progressBar_capfifo.Size = new System.Drawing.Size(304, 18); + this.progressBar_capfifo.Step = 1; + this.progressBar_capfifo.Style = System.Windows.Forms.ProgressBarStyle.Continuous; + this.progressBar_capfifo.TabIndex = 15; + // // vu_cap // this.vu_cap.Location = new System.Drawing.Point(479, 111); @@ -1617,18 +2264,8 @@ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.BackColor = System.Drawing.SystemColors.Control; - this.ClientSize = new System.Drawing.Size(1293, 691); - this.Controls.Add(this.lb_rxsync); - this.Controls.Add(this.pb_rxsync); - this.Controls.Add(this.lb_rxsignal); - this.Controls.Add(this.pb_rxsignal); - this.Controls.Add(this.label_capfifo); - this.Controls.Add(this.progressBar_capfifo); - this.Controls.Add(this.bt_blockinfo); - this.Controls.Add(this.label_fifo); - this.Controls.Add(this.progressBar_fifo); - this.Controls.Add(this.cb_speed); - this.Controls.Add(this.label_speed); + this.ClientSize = new System.Drawing.Size(1296, 693); + this.Controls.Add(this.pn1); this.Controls.Add(this.panel_txspectrum); this.Controls.Add(this.panel_constel); this.Controls.Add(this.statusStrip1); @@ -1636,7 +2273,7 @@ this.ForeColor = System.Drawing.SystemColors.ControlText; this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); this.Name = "Form1"; - this.Text = "AMSAT-DL Multimedia HS Modem V0.56 by DJ0ABR"; + this.Text = "AMSAT-DL Multimedia HS Modem V0.64 by DJ0ABR"; this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.Form1_FormClosing); this.statusStrip1.ResumeLayout(false); this.statusStrip1.PerformLayout(); @@ -1665,7 +2302,12 @@ ((System.ComponentModel.ISupportInitialize)(this.pb_voicePBstatus)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.tb_mic)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.tb_loadspeaker)).EndInit(); + this.tabPage_rtty.ResumeLayout(false); + this.tabPage_rtty.PerformLayout(); + this.panel1.ResumeLayout(false); + this.panel1.PerformLayout(); this.tabPage_setup.ResumeLayout(false); + this.tabPage_setup.PerformLayout(); this.groupBox4.ResumeLayout(false); this.groupBox4.PerformLayout(); this.groupBox3.ResumeLayout(false); @@ -1679,8 +2321,10 @@ this.groupBox2.ResumeLayout(false); this.groupBox2.PerformLayout(); this.tabPage_about.ResumeLayout(false); - ((System.ComponentModel.ISupportInitialize)(this.pb_rxsync)).EndInit(); + this.pn1.ResumeLayout(false); + this.pn1.PerformLayout(); ((System.ComponentModel.ISupportInitialize)(this.pb_rxsignal)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.pb_rxsync)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); @@ -1766,7 +2410,6 @@ private System.Windows.Forms.Label label10; private System.Windows.Forms.ComboBox cb_mic; private System.Windows.Forms.Label label11; - private System.Windows.Forms.Button bt_blockinfo; private System.Windows.Forms.CheckBox cb_switchtoLS; private System.Windows.Forms.GroupBox groupBox6; private System.Windows.Forms.CheckBox cb_voiceloop; @@ -1812,6 +2455,54 @@ private System.Windows.Forms.PictureBox pictureBox4; private System.Windows.Forms.Button bt_tune_minus; private System.Windows.Forms.Button bt_tune_plus; + private System.Windows.Forms.TabPage tabPage_rtty; + private System.Windows.Forms.TextBox tb_rtty_TX; + private System.Windows.Forms.Button bt_rtty_station; + private System.Windows.Forms.Button bt_rtty_myinfo; + private System.Windows.Forms.Button bt_rtty_endqso; + private System.Windows.Forms.Button bt_rtty_end; + private System.Windows.Forms.Button bt_rtty_start; + private System.Windows.Forms.Button bt_rtty_answerCQ; + private System.Windows.Forms.Button bt_rtty_cq; + private System.Windows.Forms.TextBox tb_rtty_deftext; + private System.Windows.Forms.Button bt_rtty_tx; + private System.Windows.Forms.TextBox textBox2; + private System.Windows.Forms.Label label_urname; + private System.Windows.Forms.TextBox tb_urname; + private System.Windows.Forms.Label label_urcall; + private System.Windows.Forms.TextBox tb_urcall; + private System.Windows.Forms.Button bt_rtty_default; + private System.Windows.Forms.RadioButton rb_rtty_edit; + private System.Windows.Forms.RadioButton rb_rtty_normal; + private System.Windows.Forms.TextBox tb_rtty_RX; + private System.Windows.Forms.TextBox textBox5; + private System.Windows.Forms.TextBox tb_myqthloc; + private System.Windows.Forms.Label label14; + private System.Windows.Forms.TextBox tb_myqth; + private System.Windows.Forms.Label lb_qth; + private System.Windows.Forms.TextBox tb_myname; + private System.Windows.Forms.Label lb_myname; + private System.Windows.Forms.Label label_cfgpath_tit; + private System.Windows.Forms.Label label_cfgpath; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.Button button3; + private System.Windows.Forms.Button bt_rxfont; + private System.Windows.Forms.Button button4; + private System.Windows.Forms.Button bt_rtty_RY; + private System.Windows.Forms.Panel pn1; + private System.Windows.Forms.Panel panel1; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Button button5; + private System.Windows.Forms.Button bt_rtty_text6; + private System.Windows.Forms.Button bt_rtty_text5; + private System.Windows.Forms.Button bt_rtty_text4; + private System.Windows.Forms.Button bt_rtty_text3; + private System.Windows.Forms.Button bt_rtty_text2; + private System.Windows.Forms.Button bt_rtty_text1; + private System.Windows.Forms.RadioButton rb_rtty_real; + private System.Windows.Forms.CheckBox cb_rx_autosync; + private System.Windows.Forms.TextBox textBox6; } } diff --git a/oscardata/oscardata/Form1.cs b/oscardata/oscardata/Form1.cs index ac2f82a..8ff712e 100755 --- a/oscardata/oscardata/Form1.cs +++ b/oscardata/oscardata/Form1.cs @@ -48,6 +48,8 @@ namespace oscardata int last_initVoiceStatus; int recordStatus = 0; int recPhase = 0; + const int Rtty_deftext_anz = 20; + String[] Rtty_deftext = new string[Rtty_deftext_anz]; public Form1() @@ -55,6 +57,8 @@ namespace oscardata // init GUI InitializeComponent(); + //showSSTV(); + // needed for ARM mono, which cannot load a picbox directly from file var bmp = new Bitmap(Resources.hintergrundxcf); pictureBox_rximage.BackgroundImage = bmp; @@ -122,6 +126,10 @@ namespace oscardata // TX timer private void timer1_Tick(object sender, EventArgs e) { + // cancel high speed TX in RTTY mode + if(statics.real_datarate == 45) + txcommand = statics.noTX; + // BER testdata if (txcommand == statics.BERtest) { @@ -596,7 +604,10 @@ namespace oscardata pb_rxsignal.BackgroundImage = Resources.redmarker; showType(-1); } - if (statics.RXinSync == 1) pb_rxsync.BackgroundImage = Resources.greenmarker; else pb_rxsync.BackgroundImage = Resources.redmarker; + if (statics.real_datarate == 45) + if (rtty_sync == 1 && statics.RXlevelDetected == 1) pb_rxsync.BackgroundImage = Resources.greenmarker; else pb_rxsync.BackgroundImage = Resources.redmarker; + else + if (statics.RXinSync == 1) pb_rxsync.BackgroundImage = Resources.greenmarker; else pb_rxsync.BackgroundImage = Resources.redmarker; // update rx,tx level progress bar int factor = 1; @@ -644,6 +655,72 @@ namespace oscardata bt_resetmodem_Click(null, null); statics.tuning_active = 0; } + + Byte[] ba = Udp.getRTTYrx(); + if (ba != null) + { + int rtty_val = ba[0]; + rtty_txon = ba[1]; + rtty_sync = ba[2]; + if (rtty_val != 0) + { + if (rtty_val == 0x08) + { + // backspace + tb_rtty_RX.Text = tb_rtty_RX.Text.Trim(new char[] { '\r', '\n' }); + if (tb_rtty_RX.Text.Length > 0) + tb_rtty_RX.Text = tb_rtty_RX.Text.Substring(0, tb_rtty_RX.Text.Length - 1); + } + else if (rtty_val != '\r') + { + String s = ""; + s += (char)rtty_val; + if (rtty_val == '\n') + s = "\r" + s; + if(statics.RXlevelDetected == 1) // do not print if no signal detected + tb_rtty_RX.AppendText(s); + } + } + } + if (rtty_txon == 1) + { + bt_rtty_tx.BackColor = Color.Red; + tb_rtty_TX.Enabled = true; + } + else + { + bt_rtty_tx.BackColor = Color.LightGreen; + tb_rtty_TX.Enabled = false; + } + } + + // click into RTTY RX Textbox + Point RTTYmousepos = new Point(0, 0); + private void tb_rtty_RX_MouseDown(object sender, MouseEventArgs e) + { + RTTYmousepos.X = e.X; + RTTYmousepos.Y = e.Y; + int cidx = tb_rtty_RX.GetCharIndexFromPosition(RTTYmousepos); + + // get the word under this position + // text after pos + String ls = tb_rtty_RX.Text.Substring(cidx); + ls = ls.Trim(new char[] { ' ', '\r', '\n' }); + int lidx = ls.IndexOfAny(new char[] {' ', '\r', '\n' }); + if (lidx != -1) + ls = tb_rtty_RX.Text.Substring(0, lidx + cidx); + else + ls = tb_rtty_RX.Text.Trim(new char[] { ' ', '\r', '\n' }); + int fidx = ls.LastIndexOf(' '); + if (fidx != -1) + ls = ls.Substring(fidx).Trim(); + + // ls is the word under the caret + // check if it is a name or callsign + if (ls.IndexOfAny(new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }) == -1) + tb_urname.Text = ls; + else + tb_urcall.Text = ls; } private void panel_constel_Paint(object sender, PaintEventArgs e) @@ -719,6 +796,11 @@ namespace oscardata AppendTextOnce(rtb, new Font("Courier New", (float)8), Color.Blue, Color.White, s); } + void printTextnoFont(RichTextBox rtb, String s) + { + AppendTextOnce(rtb, null, Color.Blue, Color.FromArgb(255, 255, 230), s); + } + void AppendTextOnce(RichTextBox rtb, Font selfont, Color color, Color bcolor, string text) { try @@ -746,7 +828,7 @@ namespace oscardata // Textbox may transform chars, so (end-start) != text.Length rtb.Select(start, end - start); rtb.SelectionColor = color; - rtb.SelectionFont = selfont; + if(selfont != null) rtb.SelectionFont = selfont; rtb.SelectionBackColor = bcolor; rtb.Select(end, 0); @@ -1075,24 +1157,19 @@ namespace oscardata 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 + 15,panel_txspectrum.Location.Y+10); - cb_speed.Location = new Point(label_speed.Location.X + label_speed.Size.Width + 10, label_speed.Location.Y-5); + pn1.Location = new Point(panel_txspectrum.Location.X + panel_txspectrum.Size.Width + 10, panel_txspectrum.Location.Y +0); - int y = 26; - label_fifo.Location = new Point(label_speed.Location.X, label_speed.Location.Y + y); - progressBar_fifo.Location = new Point(cb_speed.Location.X, cb_speed.Location.Y + y+5); - progressBar_fifo.Size = new Size(progressBar_fifo.Width, 18); + tb_rtty_RX.Location = new Point(9, 35); + tb_rtty_RX.Size = new Size(675, 348); - y = 20; - label_capfifo.Location = new Point(label_fifo.Location.X, label_fifo.Location.Y + y); - progressBar_capfifo.Location = new Point(progressBar_fifo.Location.X, progressBar_fifo.Location.Y + y); - progressBar_capfifo.Size = new Size(progressBar_capfifo.Width, 18); + tb_rtty_TX.Location = new Point(9, 416); + tb_rtty_TX.Size = new Size(675, 103); - lb_rxsignal.Location = new Point(progressBar_capfifo.Location.X + progressBar_capfifo.Size.Width + 15, label_fifo.Location.Y-15); - pb_rxsignal.Location = new Point(lb_rxsignal.Location.X + lb_rxsignal.Size.Width + 2, label_fifo.Location.Y-5-15); + label4.Location = new Point(13, 393); - lb_rxsync.Location = new Point(progressBar_capfifo.Location.X + progressBar_capfifo.Size.Width + 15, label_capfifo.Location.Y); - pb_rxsync.Location = new Point(lb_rxsignal.Location.X + lb_rxsignal.Size.Width + 2, label_capfifo.Location.Y-5); + panel1.Location = new Point(696,8); + + tb_rtty_deftext.Size = new Size(522, 160); } public String GetMyBroadcastIP() @@ -1157,7 +1234,7 @@ namespace oscardata txb[5] = (Byte)tb_mic.Value; txb[6] = safemode; txb[7] = (Byte)(cb_sendIntro.Checked?1:0); - txb[8] = (Byte)0; // unused + txb[8] = (Byte)(cb_rx_autosync.Checked ? 1 : 0); txb[9] = (Byte)0; // unused Byte[] bpb = statics.StringToByteArrayUtf8(cb_audioPB.Text); @@ -1243,12 +1320,45 @@ namespace oscardata } } + /*void removeTab(TabPage tb) + { + if (tabControl1.TabPages.IndexOf(tb) != -1) + tabControl1.TabPages.Remove(tb); + } + + void addTab(int idx, TabPage tb) + { + if (tabControl1.TabPages.IndexOf(tb) == -1) + tabControl1.TabPages.Insert(idx,tb); + }*/ + private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) { bool b = cb_switchtoLS.Checked; allVoiceModesOff(); cb_switchtoLS.Checked = b; + if (cb_speed.Text.Contains("45")) + { + txcommand = statics.noTX; + panel_constel.Visible = false; + statics.real_datarate = 45; + /*removeTab(tabPage_image); + removeTab(tabPage_file); + removeTab(tabPage_audio); + removeTab(tabPage_ber); + addTab(0,tabPage_rtty);*/ + } + else + { + panel_constel.Visible = true; + /*addTab(0,tabPage_image); + addTab(1,tabPage_file); + addTab(2,tabPage_audio); + addTab(3,tabPage_ber); + removeTab(tabPage_rtty);*/ + } + if (cb_speed.Text.Contains("3000")) statics.real_datarate = 3000; if (cb_speed.Text.Contains("4000")) statics.real_datarate = 4000; if (cb_speed.Text.Contains("4410")) statics.real_datarate = 4410; @@ -1366,7 +1476,9 @@ namespace oscardata { try { - using (StreamReader sr = new StreamReader(statics.getHomePath("", "od.cfg"))) + String fn = statics.getHomePath("", "od.cfg"); + label_cfgpath.Text = fn; + using (StreamReader sr = new StreamReader(fn)) { tb_callsign.Text = ReadString(sr); cb_speed.Text = ReadString(sr); @@ -1397,6 +1509,32 @@ namespace oscardata catch { } try { cb_language.Text = ReadString(sr); } catch { } try { s = ReadString(sr); cb_sendIntro.Checked = (s == "1"); } catch { } + for (int i = 0; i < Rtty_deftext_anz; i++) + { + String sx = ""; + try + { + sx = ReadString(sr).Trim(); + if(sx.Length == 0) + initRttyDefString(i); + else + Rtty_deftext[i] = ParagrToCRLF(sx); + } + catch + { + initRttyDefString(i); + break; + } + } + tb_myname.Text = ReadString(sr); + tb_myqth.Text = ReadString(sr); + tb_myqthloc.Text = ReadString(sr); + Font fnt1 = FontDeserialize(ReadString(sr)); + if (fnt1 != null) tb_rtty_RX.Font = fnt1; + fnt1 = FontDeserialize(ReadString(sr)); + if (fnt1 != null) tb_rtty_TX.Font = fnt1; + s = ReadString(sr); + cb_rx_autosync.Checked = (s == "1"); } } catch @@ -1441,11 +1579,110 @@ namespace oscardata sw.WriteLine(rb_opus.Checked ? "1" : "0"); sw.WriteLine(cb_language.Text); sw.WriteLine(cb_sendIntro.Checked ? "1" : "0"); + for(int i=0; i < Rtty_deftext_anz; i++) + { + if (Rtty_deftext[i] == null) + Rtty_deftext[i] = " "; + sw.WriteLine(CRLFtoParagr(Rtty_deftext[i])); + } + sw.WriteLine(tb_myname.Text.Trim()); + sw.WriteLine(tb_myqth.Text.Trim()); + sw.WriteLine(tb_myqthloc.Text.Trim()); + sw.WriteLine(FontSerialize(tb_rtty_RX.Font)); + sw.WriteLine(FontSerialize(tb_rtty_TX.Font)); + sw.WriteLine(cb_rx_autosync.Checked ? "1" : "0"); } } catch { } } + String FontSerialize(Font value) + { + String str; + + str = value.Name + "," + value.Size.ToString() + ","; + if (value.Style == FontStyle.Regular) + { + str += "R"; + } + else + { + if (value.Bold) str += "B"; + if (value.Italic) str += "I"; + if (value.Underline) str += "U"; + } + + return str; + } + + Font FontDeserialize(String s) + { + String[] sa = s.Split(','); + + FontStyle fs = FontStyle.Regular; + if (sa[2] == "B") fs = FontStyle.Bold; + if (sa[2] == "I") fs = FontStyle.Italic; + if (sa[2] == "U") fs = FontStyle.Underline; + + FontFamily ff = new FontFamily(sa[0]); + float size = (float)statics.MyToDouble(sa[1]); + + Font fnt = new Font(ff, size, fs); + + return fnt; + } + + String CRLFtoParagr(String s) + { + s = s.Replace('\n', '§'); + s = s.Replace("\r", String.Empty); + // make String 200 chars long, for exact storage position in cfg file + s = s.PadRight(210); + s = s.Substring(0, 200); + return s; + } + + String ParagrToCRLF(String s) + { + s = s.Replace("§", "\r\n").TrimEnd(new char[] {' '}); + return s; + } + + + void initRttyDefString(int i) + { + switch(i) + { + case 0: + Rtty_deftext[0] = "\r\n\r\nCQ CQ CQ de %m CQ CQ CQ de %m pse k k k\r\n%r"; // CQ call + break; + case 1: + Rtty_deftext[1] = "\r\n\r\n%c de %m pse k k k\r\n%r"; // answer CQ call + break; + case 2: + Rtty_deftext[2] = "\r\n\r\n%c de %m\r\n"; // start TX + break; + case 3: + Rtty_deftext[3] = "\r\nbtu dr %n %c de %m pse k k k\r\n%r"; // end TX + break; + case 4: + Rtty_deftext[4] = "\r\nmany thanks for the nice QSO dr %n.\r\nHpe to see you agn. gl es mny 73 %c de %m bye bye ar sk\r\n%r"; // end QSO + break; + case 5: + Rtty_deftext[5] = "\r\nName: %i\r\nQTH: %s\r\nQTHLOC: %q\r\n"; + break; + case 6: + Rtty_deftext[6] = "\r\n%m station:\r\n"; // my station + break; + case 7: + Rtty_deftext[7] = "RYRYRYRYRYRYRYRYRYRY"; + break; + default: + Rtty_deftext[i] = " "; + break; + } + } + private void bt_shutdown_Click(object sender, EventArgs e) { DialogResult dr = MessageBox.Show(statics.langstr[23], statics.langstr[22], MessageBoxButtons.YesNo); @@ -1494,27 +1731,6 @@ namespace oscardata setCAPvolume = tb_CAPvol.Value; } - private void bt_blockinfo_Click(object sender, EventArgs e) - { - String s; - int[] d = new int[2]; - recfile.oldblockinfo(d); - int failed = d[0] - d[1]; - - s = statics.langstr[25] + - "---------------\n" + - "total : " + d[0] + "\n" + - statics.langstr[26] + d[1] + "\n" + - statics.langstr[27] + failed + "\n"; - if(failed > 1) - { - s += statics.langstr[28]; - } - - Form2_showtext sf = new Form2_showtext("Block Info",s); - sf.ShowDialog(); - } - void setVoiceAudio(Byte opmode = 0) { /* @@ -1762,7 +1978,6 @@ namespace oscardata tabPage_about.Text = "About"; label_speed.Text = "Speed [bit/s]:"; label_fifo.Text = "TX Buffer:"; - bt_blockinfo.Text = "Block Info"; label_capfifo.Text = "RX Buffer:"; lb_rxsignal.Text = "RX Signal:"; lb_rxsync.Text = "RX Sync:"; @@ -1771,6 +1986,29 @@ namespace oscardata lb_tuningqrgs.Text = "Send Mid-Frequency:"; cb_marker.Text = "2.9kHz Tuning Marker"; label13.Text = "Data Security:"; + textBox5.Text = "Click on Callsign or Name in RX window"; + textBox2.Text = @"Special Markers: +%m... my call +%i... my name +%s... my city +%q... my qthloc +%c... ur call +%n... ur name +%r... switch to RX +"; + label_cfgpath_tit.Text = "Configuration stored in:"; + label_urcall.Text = "Your Callsign:"; + label_urname.Text = "Your Name:"; + bt_rtty_tx.Text = "TX On/Off"; + bt_rtty_default.Text = "set Default Text"; + bt_rtty_cq.Text = "Call CQ"; + bt_rtty_answerCQ.Text = "Answer CQ Call"; + bt_rtty_endqso.Text = "End QSO"; + bt_rtty_start.Text = "Start Transmission"; + bt_rtty_end.Text = "End Transmission"; + bt_rtty_myinfo.Text = "My Info"; + bt_rtty_station.Text = "My Station"; + textBox6.Text = "or double click in spectrum"; } if (language == 1) @@ -1828,6 +2066,29 @@ namespace oscardata lb_tuningqrgs.Text = "Sende Mittenfrequenz:"; cb_marker.Text = "2,9kHz Tuning Markierung"; label13.Text = "Datensicherheit:"; + textBox5.Text = "Klicke auf Rufzeichen und Namen im RX Fenster"; + textBox2.Text = @"Spezialzeichen: +%m... mein Rufzeichen +%i... mein Name +%s... mein Ort +%q... mein QTHLOC +%c... dein Rufzeichen +%n... dein Name +%r... schalte auf RX +"; + label_cfgpath_tit.Text = "Konfiguration gespeichert in:"; + label_urcall.Text = "Dein Rufzeichen:"; + label_urname.Text = "Dein Name:"; + bt_rtty_tx.Text = "TX ein/aus"; + bt_rtty_default.Text = "setze Standardtexte"; + bt_rtty_cq.Text = "Rufe CQ"; + bt_rtty_answerCQ.Text = "Beantworte CQ"; + bt_rtty_endqso.Text = "Beende QSO"; + bt_rtty_start.Text = "Start Durchgang"; + bt_rtty_end.Text = "Beende Durchgang"; + bt_rtty_myinfo.Text = "Meine Info"; + bt_rtty_station.Text = "Meine Station"; + textBox6.Text = "oder Doppelklick in Spektrum"; } } @@ -1873,6 +2134,8 @@ namespace oscardata " of ", //30 "Bad blocks, retransmission required", "Bad blocks", //32 + "Set RTTY predefinded text messages to default values. Are you sure ?", //33 + "Set Default Mesages", //34 }; String[] langstr_de = new String[]{ @@ -1909,6 +2172,8 @@ namespace oscardata " von ", //30 "defekte Blöcke, Datei muss nochmal empfangen werden", "defekte Blöcke", //32 + "Setze RTTY Nachrichten auf die Standardtexte zurück. Sind sie sicher?", //33 + "Setze Standardnachrichten", //34 }; private void cb_autostart_CheckedChanged(object sender, EventArgs e) @@ -1986,6 +2251,316 @@ namespace oscardata txdata[1] = 255 - 10; Udp.UdpSendCtrl(txdata); } - } + bool backspace = false; + private void tb_rtty_TX_TextChanged(object sender, EventArgs e) + { + if (backspace) + { + backspace = false; + return; + } + + if (tb_rtty_TX.Text.Length > 0) + { + char c = tb_rtty_TX.Text[tb_rtty_TX.Text.Length - 1]; + + c = char.ToUpper(c); + + // filter allowed characters + bool ok = false; + if (c >= 'A' && c <= 'Z') ok = true; + if (c >= '0' && c <= '9') ok = true; + if (c == '\\') ok = true; + if (c == '(') ok = true; + if (c == ')') ok = true; + if (c == '+') ok = true; + if (c == '/') ok = true; + if (c == '-') ok = true; + if (c == ':') ok = true; + if (c == '=') ok = true; + if (c == '?') ok = true; + if (c == ',') ok = true; + if (c == '.') ok = true; + if (c == ' ') ok = true; + if (c == '\n') ok = true; + + if (ok) + { + Byte[] txdata = new byte[2]; + txdata[0] = statics.rttykey; + txdata[1] = (Byte)c; + Udp.UdpSendCtrl(txdata); + } + } + } + + /* + %m ... my call + %i ... my name + %s ... my city + %q ... my qthloc + %c ... ur call + %n ... ur name + %r ... stop TX + */ + // convert short forms into text + String realRTTYtext(String s) + { + String sdec = s; + sdec = sdec.Replace("%m", tb_callsign.Text.Trim().ToUpper()); + sdec = sdec.Replace("%i", tb_myname.Text.Trim().ToUpper()); + sdec = sdec.Replace("%s", tb_myqth.Text.Trim().ToUpper()); + sdec = sdec.Replace("%q", tb_myqthloc.Text.Trim().ToUpper()); + sdec = sdec.Replace("%c", tb_urcall.Text.Trim().ToUpper()); + sdec = sdec.Replace("%n", tb_urname.Text.Trim().ToUpper()); + if(tb_urname.Text.Length == 0) + { + sdec = sdec.Replace(" dr ", " "); + } + sdec = sdec.Replace("%r", "[RX]"); + + return sdec.ToUpper(); + } + + int selected_rtty_deftext = 0; + + void ShowRTTYtext(int selnum, int nosend = 0) + { + if (selnum >= Rtty_deftext_anz) return; + + selected_rtty_deftext = selnum; + + if (rb_rtty_normal.Checked) + { + bt_rtty_default.Enabled = textBox2.Enabled = false; + tb_rtty_deftext.ReadOnly = true; + tb_rtty_deftext.Text = realRTTYtext(Rtty_deftext[selnum]); + + if (nosend == 0) + { + String sx = tb_rtty_deftext.Text; + sx = sx.Replace("[RX]", "~"); + + // print also in TX window + String sxtx = sx; + sxtx = sxtx.Replace('~', ' '); + tb_rtty_TX.AppendText(sxtx); + + Byte[] tarr = statics.StringToByteArray(sx); + + Byte[] txdata = new byte[4 + tarr.Length]; + txdata[0] = statics.rttystring; + int len = tarr.Length; + txdata[1] = (Byte)(len >> 8); + txdata[2] = (Byte)(len & 0xff); + txdata[3] = (Byte)'#'; // always switch TX on before transmitting + for (int i = 0; i < tarr.Length; i++) + txdata[i + 4] = tarr[i]; + Udp.UdpSendCtrl(txdata); + } + } + else if (rb_rtty_real.Checked) + { + bt_rtty_default.Enabled = textBox2.Enabled = false; + tb_rtty_deftext.ReadOnly = true; + tb_rtty_deftext.Text = realRTTYtext(Rtty_deftext[selnum]); + } + else + { + bt_rtty_default.Enabled = textBox2.Enabled = true; + tb_rtty_deftext.ReadOnly = false; + tb_rtty_deftext.Text = Rtty_deftext[selnum]; + } + } + + private void bt_rtty_cq_Click(object sender, EventArgs e) + { + ShowRTTYtext(0); + } + + private void bt_rtty_answerCQ_Click(object sender, EventArgs e) + { + ShowRTTYtext(1); + } + + private void bt_rtty_endqso_Click(object sender, EventArgs e) + { + ShowRTTYtext(4); + } + + private void bt_rtty_start_Click(object sender, EventArgs e) + { + ShowRTTYtext(2); + } + + private void bt_rtty_end_Click(object sender, EventArgs e) + { + ShowRTTYtext(3); + } + + private void bt_rtty_myinfo_Click(object sender, EventArgs e) + { + ShowRTTYtext(5); + } + + private void bt_rtty_station_Click(object sender, EventArgs e) + { + ShowRTTYtext(6); + } + + private void bt_rtty_RY_Click(object sender, EventArgs e) + { + ShowRTTYtext(7); + } + + private void tb_rtty_deftext_TextChanged(object sender, EventArgs e) + { + if (rb_rtty_edit.Checked) + { + try + { + Rtty_deftext[selected_rtty_deftext] = tb_rtty_deftext.Text; + } + catch + { + Rtty_deftext[selected_rtty_deftext] = ""; + } + } + } + + private void bt_rtty_default_Click(object sender, EventArgs e) + { + if (MessageBox.Show(statics.langstr[33], statics.langstr[34], MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + for (int i = 0; i < Rtty_deftext_anz; i++) + initRttyDefString(i); + + ShowRTTYtext(selected_rtty_deftext); + } + } + + private void rb_rtty_normal_CheckedChanged(object sender, EventArgs e) + { + if (rb_rtty_normal.Checked) + ShowRTTYtext(selected_rtty_deftext,1); + } + + private void rb_rtty_edit_CheckedChanged(object sender, EventArgs e) + { + if (rb_rtty_edit.Checked) + ShowRTTYtext(selected_rtty_deftext, 0); + } + + private void rb_rtty_real_CheckedChanged(object sender, EventArgs e) + { + if (rb_rtty_real.Checked) + ShowRTTYtext(selected_rtty_deftext, 0); + } + + int rtty_txon = 0; + int rtty_sync = 0; + private void bt_rtty_tx_Click(object sender, EventArgs e) + { + Byte[] txdata = new byte[2]; + txdata[0] = statics.txonoff; + txdata[1] = (Byte)((rtty_txon==1)?0:1); + Udp.UdpSendCtrl(txdata); + } + + private void tb_rtty_TX_KeyDown(object sender, KeyEventArgs e) + { + if(e.KeyValue == 8) + { + // back space + backspace = true; // do not process text change + Byte[] txdata = new byte[2]; + txdata[0] = statics.rttykey; + txdata[1] = 0x08; + Udp.UdpSendCtrl(txdata); + } + } + + private void button1_Click_1(object sender, EventArgs e) + { + tb_rtty_RX.Text = ""; + } + + private void button3_Click(object sender, EventArgs e) + { + tb_rtty_TX.Text = ""; + } + + private void bt_rxfont_Click(object sender, EventArgs e) + { + FontDialog fontDialog1 = new FontDialog(); + fontDialog1.Font = tb_rtty_RX.Font; + if (fontDialog1.ShowDialog() == DialogResult.OK) + { + tb_rtty_RX.Font = fontDialog1.Font; + } + } + + private void button4_Click(object sender, EventArgs e) + { + FontDialog fontDialog1 = new FontDialog(); + fontDialog1.Font = tb_rtty_TX.Font; + if (fontDialog1.ShowDialog() == DialogResult.OK) + { + tb_rtty_TX.Font = fontDialog1.Font; + } + } + + private void panel_txspectrum_DoubleClick(object sender, EventArgs e) + { + MouseEventArgs a = (MouseEventArgs)e; + Int16 freq = (Int16)(10 * (a.X - 16)); + + statics.tune_frequency = freq; + + Byte[] txdata = new byte[3]; + txdata[0] = statics.setfreq; + txdata[1] = (Byte)(freq >> 8); + txdata[2] = (Byte)(freq & 0xff); + Udp.UdpSendCtrl(txdata); + + } + + private void button5_Click(object sender, EventArgs e) + { + Byte[] txdata = new byte[1]; + txdata[0] = statics.rtty_stopTX; + Udp.UdpSendCtrl(txdata); + } + + private void bt_rtty_text1_Click(object sender, EventArgs e) + { + ShowRTTYtext(8); + } + + private void bt_rtty_text2_Click(object sender, EventArgs e) + { + ShowRTTYtext(9); + } + + private void bt_rtty_text3_Click(object sender, EventArgs e) + { + ShowRTTYtext(10); + } + + private void bt_rtty_text4_Click(object sender, EventArgs e) + { + ShowRTTYtext(11); + } + + private void bt_rtty_text5_Click(object sender, EventArgs e) + { + ShowRTTYtext(12); + } + + private void bt_rtty_text6_Click(object sender, EventArgs e) + { + ShowRTTYtext(13); + } + } } diff --git a/oscardata/oscardata/Form1.resx b/oscardata/oscardata/Form1.resx index ddd53e9..242b4af 100755 --- a/oscardata/oscardata/Form1.resx +++ b/oscardata/oscardata/Form1.resx @@ -136,9 +136,9 @@ AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 - ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAABw - FwAAAk1TRnQBSQFMAgEBDQEAAUABBgFAAQYBEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo - AwABQAMAAUADAAEBAQABCAYAARAYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA + ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAA+ + JQAAAk1TRnQBSQFMAgEBFwEAAYgBDAGIAQwBEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo + AwABQAMAAWADAAEBAQABCAYAARgYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5 AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA AWYDAAGZAwABzAIAATMDAAIzAgABMwFmAgABMwGZAgABMwHMAgABMwH/AgABZgMAAWYBMwIAAmYCAAFm @@ -165,79 +165,137 @@ AcwBAAH/AZkB/wEAAf8BzAIAAf8BzAEzAQAB/wHMAWYBAAH/AcwBmQEAAf8CzAEAAf8BzAH/AQAC/wEz AQABzAH/AWYBAAL/AZkBAAL/AcwBAAJmAf8BAAFmAf8BZgEAAWYC/wEAAf8CZgEAAf8BZgH/AQAC/wFm AQABIQEAAaUBAANfAQADdwEAA4YBAAOWAQADywEAA7IBAAPXAQAD3QEAA+MBAAPqAQAD8QEAA/gBAAHw - AfsB/wEAAaQCoAEAA4ADAAH/AgAB/wMAAv8BAAH/AwAB/wEAAf8BAAL/AgAD/wQAARoBmQEbAf8CAAH/ - AfQBGgGZAf81AAF0ATIBNwFLAfEB9AF0ATEBOAEyAfM1AAF5AzgCNwM4ATEB8zUAAZkEOAH7AzgBMQH0 - NQABmQg4ATEB9jUAAZkEegJZAjgBMQH0MwAB/wGZAVgIegFZAXkB/zIAARoBWQt6AVIB/zAAAfQBeQ16 - ARowAAHzAVIMegF5AZkxAAH2ARsBGgGZBnoBmQEaARsB9AH/NQABGwF6ApoBegF5Af85AAH/AXkCoAF6 - AfY7AAH2AXoBoAEaPQABGwGaAf93AAH/DPIB9AH/BwABBwHsAeoBbQHqAewBvBMABP8B9AHzAQcB7wHw - AfQF/wEAAZMDRQZGBEUB9AkAAW0BEwHsBgAC/wn2Af8FAAH0AfAB9wEUARECEAYAAf8BbwIfAUYGJQFG - ASQBHwFFAfIDAAH0BfMBbQFDAZIFAAH/AZkBUwkyAXUB/wEAAf8BBwHwAfEB9AH/AfMCBwHyAwAB/wIA - Af8BbwEfAW8B9AF0ASUCJgIlARsBkwEfAUUB8gMAAe0BEQFEAQEBRAIRAQ8BkgUAAf8CUwGaAVMBwwFZ - AcMBWQQyAfYBAAH/AfIB8AERAfQHAAHxAUMB8wEAAf8BbwEfAZMC8wF1AiwBTQHxAfMB8AFFASQB8gQA - Af8BRQEfAW4B/wHrAQ4B7QUAAf8BMgFTARoBWQH/AVkB/wFZBDIB9gEAAfQB7AETAQ8B8gcAAe8BEQEV - AfEB/wFvAR8BJAGTAfIB8QF1ASwBvAHxAbwBJAEfASQB8gUAAW8BIAGTAQABbQEAAe0FAAH/AzIBmgHD - AVkB/wE4BDIB9gEAAfQBDgHqARAB8gcAAe8BQwEVAZIB/wFvAh8BJAGTAfEB8AK8AQcBRgMfAfIFAAFv - ASABkwEAAW0BAAHtBQAB/wEyAVMBGgGaAVMBmgF6BTIB9gEAAfQB6gHrAUMB8gcAAe8BEwHqAQcB/wFv - AQEBHwEkAUYBHAHxAfABBwElAh8BAQEfAfIFAAFvASABkwEAAesBEAHtBQAB/wEsAjIBWQH2ARoBUwUy - AfYCAAEHAe0BFAHyBwAB7wFtAewB8AH/AW8BRQFGAUwBbwPxAfABkwFvAUYCRQHyBAAB/wFuASABkwEA - AesBDwGSAwAB8wEAAf8BUwF6AcMBGgGaAXoBWQJ6A1MB/wIAAfIBvAESAfMHAAEHAesB8AHzAf8EbwHx - AfIBvAEHAfEB8gGTA28B8gQAAfMBCwEfAZMBAAHrAREBkgMAARMBAAH/AVMDdQR6BHUB/wIAAfQBvAH/ - CQAB/wHvAf8BAAJvAZMC8wG8AZMBbwEHAfIB8wGTAm8B8wQAAfQBDwEBAZMBAAHrAUMBkgEAAf8BvAER - AQAB/wFTCnoBdQH/AgAB/wGSAfQJAAHyAe8B/wEAAm8BvAHzAfAEbwHvAvMBkwFvAfMEAAH/AREBEAFD - AW0BQwIVAW0BFAERARQBAAH/AVMKegF1Af8DAAH/AfIJAAHyAwADkwEHBpMB7wOTAfMB9AFvAgAB/wIS - AW0D7QFEAu0B7AGSAQAB/wF1CpoBegH/BAABvAHvAf8FAAH0AewB8QMADpMB8wH/AUUB/wIAARwB7QHv - AgAB8QFFBQAB/wEbAXoJdQEaAf8EAAH/AkMBvAL/AfQBBwEQAW0B/wMAAfMMkwEaAv8CbgLvAW4B9wHs - Ae8BkwJuBgAM/wYAAf8B7wETAw4BFAEHAf8TAAH/C28bAAH/AfMB/wYABP8C9AHvAewBkgHyAfQF/wMA - C/8CAAH/AfAB7wHyAf8HAAH/AfMBGgH/EwAB9AESAewE7wHsAfAFAAH/AfQK8gHzAf8BAAH/AQcB/wHv - AfIB/wUAAf8B8gFSATgBGgQAAfQBCAwAAfAC7ALwAv8B9AGSAfAB7QQAAf8B8gHxAQgCvAHwAQgEGwLz - Av8BBwG8AewB7QHyAf8DAAH/AfABUgI4AZkEAAHyAU8BlwH0CQAB/wHsAW0D/wL0Av8BBwHzAQcDAAH0 - AfMBcgEoAS4BLwF4AS8ENQEbAfIB/wEAAfQBBwEUAQ8B7QH0Af8BAAH/AfIBMQE4AVkBdAH/BAAB8gIt - AU8B/wgAAeoBbQH0AbwD9AHzAfQBBwH0AZIBBwMAAfQB8wFyAigCmAIvAzUBGwHyAf8BAAH/AfQB7wET - ARQB9wH0Af8B8wFSAlkBmQH/BQAB8gIzAS0BTwG8Af8FAAH/Ae0BvAT0AfMB8gT0AfEBBwIAAfQB8wFy - AigB/wEIBS8BCAHyAf8DAAH/AQcBEgFDAe8BvAExATgBWQGZAf8GAAHyAjMCLQECAZgB/wQAAfAB7AH0 - AfMC9AEHAfQBGgP0AfAB7QHsAgAB9AHzAXICKAH/AfQBUAEuAXgBUAEvAbwB8gH/BAAB/wEHAhIB7QFZ - ATIB8wH/BwAB8gIzAS0CAgEnAXIB9AMAAQcB7AL0AvMB9AEfAbwE9AHtAe8BDgEAAfQB8wFyAigB9AL/ - AbwB/wFQASgBvAHyAf8FAAH/Ae8B7AHwAfcBvAH/CAAB8gMtAgIBJwEhAUkB9AIAAbwBkgLzAfAC8wEH - Ae0E8wHtAe8B/wEAAfQB8wFyAigBUAH0A/8BUAEoAbwB8gH/BQAB/wIHAewB6wEHAfMC/wYAAfEGTwFJ - AZgB/wIAAf8BBwHxAfMB8gHzAZMC8wEHAvMB8QHwAQcCAAH0AfMBcgMoAZgD/wFQASgBvAHyAf8EAAH/ - AQcB8QHyAQcB7wHsAesB7AHvAfQB/wQAAfEGTwEIBQABBwHrAfMB7wHzARoD8wHwAfEB7AHzAf8CAAH0 - AfMBcgIoAVAECAFKASgBvAHyAf8DAAH0AQcBvAHyAv8B8AHsAe0B7wLtAfQEAAHxAU8EcgHxAf8FAAHz - AfEB7AHyAfAD8wHyAbwB7AHxAe8DAAH0AfMBcgkoAbwB8gH/AgAB/wEHAfIB8wMAAfIBvAEHAbwC7wHx - BAAB8QFyAZcBcgFJAfQIAAEHAfMB6wHvAfcBBwHvAe0BbQHwAe0B9wHtAf8BAAH0AfMBHAlyAfEB8gL/ - AfMB7wG8AfMB/wMAAfQBBwHyAQcB9AH/AfQEAAHxAnIB7wH/CgAC8wG8Ae0C7AEHAfMBBwHyAbwB9AEH - AQAB/wHwCvMB8gH0AQAB/wIHAfMFAAH/Ae8B9AHvAfMB/wUAAfEBTwEIAf8NAAHzAbwBBwG8AfICAAHy - AfQBAAG8AQAC/wr0Av8BAAH/AfEB8gH/BQAB/wHyAfAB8wEHAfQFAAH/AfMXAALxHAAB/wHzAf8cAAH/ - AfADmAH0IAAF/wH0Cv8B9A3yAZEB7xAAEP8QAAHxAvQC/wHvA/8B8gHxAfQBCAG7AfABkQQAAQEBHgQA - Af8BRQEBAwAB8wHwBfIC8QbyAfABAAG8ArQLtQH/AfIC9AL/Ae8D/wHyAfEBcgFxAZEBSQFyAwABAQH5 - AUcBCwIAAf8BHgH5ARcBAQIAAfIB8wP/AfMBuwK0AQkB9AT/AfABAAH3AUMBFQJKAUQBQwERA0MBFQFD - ARMB9AHyAvQC/wHvA/8B8gHxAUkC/wEHAXECAAGTAW8C+QFHAQsB/wELA/kBRQIAAfIB8wL/AfQBtAGz - AgkCtAHxA/8B8AEAAfcBEQFDAkoBFQMQAhEBQwERAWYB9AHyBAcB7AG8AvACvAFJAfMB9AHxAXIDAAJv - AiABRgEOAyABAQH/AgAB8gHzAv8CiwG0AgkBtAGLAa4D/wHwAQAB9wEQAUMCSgFEAREDEAMRARUB9AHy - BLwBkgHwAvEB8AG8AUkB7wHwAewB7wQAAW8BTAUgAQEB/wMAAfIB8wH/AQcBhgGtAbQBCQG6AbMBrQGG - AQcC/wHwAQAB9wIUAkoBFAERARABDwQOARUB9AHyAfQBBwEIAf8BBwH/AfIB/wHzAfEB8AFJAQ0B7QH/ - BQABbwFMAyABHwH/BAAB8gHzAf8BtQGGArQCswGtAosBrgL/AfEBAAHvAusBbQHqARIBFAEVAREBEAIP - ARABFQH0AfIC8wEHAfQBBwH/AbwB/wHzAfED/wHyAf8EAAH/AR8DRgFvAUYBHwQAAfIB8wH/AbUBhgG7 - AQkBtAGtAosBzwGuAv8B8QEAAQcBkwF0AXkCegJTAkwDKwFLAfQB8gHzAQcBvAH0AQcB/wHwAf8B8wHy - A/8B8wQAAf8BHwNGAXQCRgFvAR8DAAHyAfMB/wK1AgkBtAKLAYYBiwG1Av8B8QEAAQcBlAGaAqABegF1 - AlMETQFvAfQB8gG8AwcB9wG8BPAB8wH0Af8B8wMAAf8BHwNvAQEBbgF0Am8BFgEfAgAB8gHzAf8B8wG1 - AQcBCQG0Ac8CiwGuAfQC/wHxAQABBwKUA5oDdQLjAhcBbwH0BfMBBwP0AfMB8gP/AfMDAAEaAUwCFgEf - Af8BAAFvAxYBHwIAAfIB8wL/AfABtQEJAa4BtAGuAc8BvAP/AfEBAAEHBrcDlAOxAY4B9ALzAggB8wG8 - A/QB8wHyA/8B8wQAARoBTAEfAf8DAAFvARYBHwMAAvID8wG8ArUBrgG1AbwE8wHxAQABBwHPDLUB9ALz - AfIBBwHzAfAE8wHyA/QB8wUAARoB/wUAAZMEAAHyCfAC7wO1AfABAAG7A60DswK0BdUB9ALzAvAB8wHw - BfMD9AHzEQAB9Am8AQcBvAMHAfIBAAHyBQkE3QQZAv8G8gfzAf8xAAFCAU0BPgcAAT4DAAEoAwABQAMA - AUADAAEBAQABAQYAAQIWAAP/AQAB4QGDBgAB4AEDBgAB4AEDBgAB4AEDBgAB4AEDBgAB4AEDBgABgAEB - BgABgBcAAYAHAAH4AQ8GAAH4AR8GAAH8AT8GAAH+AT8GAAL/BgABgAEAAf4BAwL/AYABAAGAAQAB/wGP - AcABAwHgAT8CAAHgAQ8BgAEBAQABOwIAAeABDwGAAQEBBwHxAgAB8AEPAYABAQEHAfACAAH4AY8BgAEB - AQcB8AIAAfgBjwGAAQEBBwHwAgAB+AGPAYABAQGHAfACAAHwAY4BgAEBAYcB8AIAAfABjgGAAQEBjwH4 - AYABAAHwAYgBgAEBAY8B+AGAAQAB8AEAAYABAQHPAfsBgAEAATABAAGAAQEC4wGAAQABGAHPAYABAQHg - AQMBgAIAAQ8BwAEDAfABBwL/AQABDwL/Af4BPwIAAeABAwEHAfAC/wHgAQ8BgAEBAQMB4AHzAf8BwAEH - AYABAAEBAcAB8AH/AYABAwGAAQACgAHwAX8BgAEDAYABAAGAAQEB8AEfAQABAQGAAQAB4AEDAfABDwEA - AQEBgAEAAfABBwHwAQcCAAGAAQAB+AEPAfABAwIAAYABAAH4AQMB8AEDAQABAQGAAQAB8AEAAfABDwGA - AQEBgAEAAeABAAHwAQ8BgAEDAYABAAHDAYAB8AE/AcABAAGAAQABAwGAAfABfwHgAQABgAEBAQ8BgQHw - Af8B+AEyAYABAQEPAYEB8wL/AfkD/wHjA/8BwAT/BAAC/wIAAv8CAAHzAccCAAGAAwAB4QGDAgABgAMA - AcABAwIAAYADAAHgAQMCAAGAAwAB8AEHAgABgAMAAfgBDwIAAYADAAHwAQ8CAAGAAgABAQHgAQcCAAGA - AgABAQHAAQMCAAGAAgABAQHAAYMCAAGAAgABAQHhAccCAAGAAgABAQHzAe8CAAGAAgABAQL/AgABgAIA - AQEG/ws= + AfsB/wEAAaQCoAEAA4ADAAH/AgAB/wMAAv8BAAH/AwAB/wEAAf8BAAL/AgAD/wQAAf8B8gHvAesB6gES + AW0BkgHwAf8GAAH/AfIB7wHsAeoBEgFtAZIB8AH/CAAB9AXyAf8XAAHvARIBEwHrAe0BkgHsARIBEwFt + AfQFAAHvAhIB6wKSAewCEgFtAfQHAAH0AQcCDgFtAfMB/xUAAf8BkgESAewBBwHyAvMB8gHxAZIB6gHs + AfQCAAH/AfcB6gHsAbwB8gLzAfIB8QH3AeoB7AH0CAABbQEPAfIXAAEHARIB7QHxAfMB9AL/AvQB8gG8 + AeoBbQH/AQABBwHqAZIB8QHzAfQC/wL0AfIBvAJtAf8HAAHsAREB8xYAAf8BbQHrAfEB9AH/AesBBwP/ + AfQB8gH3ARIB8AH/AusB8QH0Av8BGgG9Av8B9AHyAfcB6gHwBwAB7AEVAfMWAAHwARIBvAHzAv8BEwEV + AewB9AL/AfQB8QESAZIB8AHqAbwB8wL/AWkCIAFGAfQB/wH0AfEB6gH3BwAB7QETAfMWAAHsAW0B8QH0 + Av8BQwIQAeoBBwL/AfIB7AHrAe0B6wHxAfQB/wEWBCABRgL/AfIC7AcAAZIB6gHzFgABbQHsAfIB9AL/ + ARECDgERARMBkgH/AfMB9wHqAesB7AHyAfQB/wEXASAC+QIgAb0B/wHzAfcBbQcAAfcB6wHzFgAB6wHs + AfEB9AL/AW0BEwEUARMB6wG8Af8B8gGSAW0C7AHxAfQB/wEWARcCRwFGASABGgH/AfIBkgFtBwAB7wHs + AfMWAAH3AW0B8QH0Av8B6wFtARIB7QL/AfQB8gLsAe8B6wHxAfQB/wG9ARcDRgFvAf8B9AHyAuwHAAHv + AewB8xYAAfMBbQHvAfQC/wLsAbwD/wHzAbwB6gHvAfMBbQHvAfQC/wG9ARYBbwGUAv8B8wG8AW0BBwcA + AfcB6wHzFwAB7QFtAfAB9AH/Ae8E/wH0AfEB7QFtAfIBAAGSAW0B8AH0Bv8B9AHxAe0B6wHyAgAB7wH/ + AwAB9wFtAfMDAAHxEwAB8gFtAewB8QHzBPQB8wHxAZIBbQEHAf8BAAHyAesB7AHxAfME9AHzAfEB9wHr + AQcB/wIAAe0B8wMAAZIB6gHzAwAB7xQAAfEB6wFtAe8B8QLyAfEBvAHsAesB7wQAAfEB7AFtAe8B8QLy + AfEBvAHsAesB7wQAAe0B7AH0Av8B7QETAfMC/wEHAW0VAAHyAZIB6wTsAesB7AG8Af8FAAHyAZIF7AHr + AewB8AH/BAABBwrsAfcXAAHzAe8C7AHvAfEB/wkAAfMB7wHtAewB7wHxAf80AAH/AfQC8wHyAvEB8ALx + AbwBuwG0AQkB9AH/EwAB/wHyAe8B6wHqARIBbQGSAfAB/wgAAf8B8wH/CAAB9ALxBvQBuwGsAbMB7wGt + AYoB9BMAAe8BEgETAesB7QGSAewBEgETAW0B9AQAAfEBswHzAfEB8wHyAfEB8gYAAf8B8QHyBvQBtAGK + AbQB8QGtAYoBuwUAAv8B9AHzAfQE/wMAAf8BkgESAewBBwHyAvMB8gHxAZIB6gHsAfQCAAH/ArMB7AHt + AQcB8wEAAfAHAAHyAfMG9AKLAbQB/wGtAYoBtAQAAf8B7wGLAWwCZgLqAWYBbAG8Af8BAAEHARIB7QHx + AfMB9AL/AvQB8gG8AeoBbQH/AQAB8gEZAbsCvAEHAfcB7QGSAbwB8gL/AQAB/wEAAfQB8gHzBPQB/wG0 + Aa0BswG7Aq0BuwMAAfABZgFDARADDwIOAQABvAIAAf8BbQHrAfEB9AHxBfAB8wHyAfcBEgHwAQAB8wEJ + AfAC8gHxAbwBBwH3AewB6wHqAewBvAG0AwAB9AHzAfIBmQEcAfEBuwGzAbQB/wG0AbMB8wIAAfQBEQEO + AQ8BEAENAhABDwIOAe8CAAHwARIBvAHzAf8B7AETAhQBEwHqAfAB9AHxARIBkgEAAv8B8gL0AfMB8gHx + AbwBBwH3AewBbQGKAfAFAAHzAZMBHAG8Af8B8gEJAbUBCQHzAf8BAAH/ARMBDgEQAg0CZQINARABDgEV + Af8BAAHsAW0B8QH0Af8B7AEVAREBEAFDARQB8AH/AfIB7AHrAwAB/wHyAfQB/wH0AfMB8gHwAbwB7wGR + AbMB/wUAAfECmgGTAf8HAAHzAQ4EDQNmAkMBEAEOAfMBAAFtAewB8gH0Af8B6wERAg4BEAEVAfAB/wHz + AfcB6gQAAf8B8gH0Af8C9AHzAfEBBwGzAfQGAAEaA5oB9AcAAfMBEAFDARUDZgNsARIBEwEUAfMBAAHr + AewB8QH0Af8B7QFtARMCFQETAfAB/wHyAZIBbQUAAfQB8gP/AfQB8gG0AQkGAAH0AZoDGgEbBwAB9AJm + AmwB6gFsBW0B6gH/AQAB9wFtAfEB9AH/AfcB6wFtAxIB8AH0AfIC7AYAAfQB8wP/AQkB2wH/BQAB/wGZ + BRoHAAH/AewDrgHrAa4C7AGuAuwB7wIAAfMBbQHvAfQB/wEHAfcB7QPsAfEB8wG8AeoB7wcAAfQB8wH/ + AfMB2wHzBgAB/wEcAhoBGwEaAZkIAAH/BOwE7QL3AfQDAAHtAW0B8AH0Bv8B9AHxAe0BbQHyBwAB/wH0 + AfICCQgAAXMBmgG8ApkBkwkAAfQB7wT3Au8BBwH0BAAB8gFtAewB8QHzBPQB8wHxAZIBbQEHAf8JAAHz + AdsB9AgAAbwCbgIcAbwLAAHzAQcC7wG8AfMB/wYAAfEB6wFtAe8B8QLyAfEBvAHsAesB7wsAAfQBGQH/ + CAAB/wEHAW4BHAEHAfQZAAHyAZIB6wTsAesB7AG8Af8YAAL/HQAB8wHvAuwB7wHxAf8HAAEaAZkBGwH/ + AgAB/wH0ARoBmQH/AwAC/wHyBrwB8AK8AfQC/wEAAf8B8wHyAfMH8gLzAv8BAAH/AfEBCQEZAf8BAAH/ + AfABCQHyAZgBAgEIBQABdAEyATcBSwHxAfQBdAExATgBMgHzBQAB7wHwBv8B8gGSAfMEAAETAW0G7AHt + AewB6wHqAwABCQGKAbMBsgHzAQABuwKzAbIBTwFVAZgFAAF5AzgCNwM4ATEB8wIAAf8C9AHvAewC8wP0 + AfMB7wFtAfIB9AH/AgABBwP0AUoBKQIDA/QB8QIAAf8BuwGzAdQBswG7AfMBtAGzAXEBSQFPAVUBcgGY + AQgDAAGZBDgB+wM4ATEB9AIAAf8CBwHsARQCBwK8AgcB7AESAgcB8QIAAQcBHAFzAZkBSwIrAUwB8AJz + AQcCAAEJAYoBiwLUA4oBkAFyA5gBlwFPAS4DAAGZCDgBMQH2AgAB9ALxAewIFQESAfABvAHyAgABBwHv + AQcBmQFLAisBTAEaA+8CAAGLAbMC1APaAtsBnQFyAZcBmAFyAZgBCAMAAZkEegJZAjgBMQH0AgAO9AHw + AfMCAAHvAZkBvAGZAUsBJAEqAUsBvAIHAe8CAAKzAtQD2gTbAZ0BCAFyAwAB/wGZAVgIegFZAXkB/wEA + AfQC8AH3Am0B6wPsAm0B6wLwAfICAAHvAZkBvAEHAUsBKgJLAfECmQEHAgAB9AEJArMB2wGzAbkBugGz + AbkB2wGdAZgBCAMAARoBWQt6AVIC/wHzAfQB7wgSAW0C9AHzAQAB8wH3A/MEGgPzAbwB8AH/AgAB8gGz + AdsBugG0AQABCQG0AdsBswGdAf8CAAH0AXkNegEaAf8BBwG8Ae8E6wHsA+sB7AG8AQcB8gEAAfIBEgEH + CPQB8wHrAQcB/wIAAf8BswLbAawB8wHyAbMC2wGzAfMB9AH/AfMBUgx6AXkBmQEAAu8D7AXtAewBEwHv + AZIB8gIAAfQBEgEHBvIB8AESAQcDAAH/AYoBkALcAbMCiwGzAtwBswGLAbIBGQEAAfYBGwEaAZkGegGZ + ARoBGwH0Af8BAAHzAfIBBwG8AfAB8QHyAvEB8AG8AewB8wHyAf8DAAHyAeoB7wTyAfACbQHzAwAB8gGz + C9wBuQG7BQABGwF6ApoBegF5Af8HAALxAfME9AHzAfEB7QcAAfQBEgHvArwBBwETAesBvAH0AwAB8wG6 + AhkC3AIJARkBCQLcAwkFAAH/AXkCoAF6AfYIAALzBv8B9AG8CAAB8gESAZIBBwFtAQcB7wEHAfQDAAH/ + ARkBugGzAhkBswK6AbMCCQGzAQkB9AYAAfYBegGgARoJAAH0CP8B8wkAAfQBEgEUAQcBAAH0AfMB/wUA + Af8BsgEJARkBugEAAf8BsgEJARkBugkAARsBmgH/CQAB9AjwAfMKAAHzAbwB/woAAgkBuQEJAQAB/wG7 + AQkBuQEJFQAK/xgAAfQB/wQAAfQB/wQAAf8M8gH0Af8HAAEHAewB6gFtAeoB7AG8EwAE/wH0AfMBBwHv + AfAB9AX/AQABkwNFBkYERQH0CQABbQETAewGAAL/CfYB/wUAAfQB8AH3ARQBEQIQBgAB/wFvAh8BRgYl + AUYBJAEfAUUB8gMAAfQF8wFtAUMBkgUAAf8BmQFTCTIBdQH/AQAB/wEHAfAB8QH0Af8B8wIHAfIDAAH/ + AgAB/wFvAR8BbwH0AXQBJQImAiUBGwGTAR8BRQHyAwAB7QERAUQBAQFEAhEBDwGSBQAB/wJTAZoBUwHD + AVkBwwFZBDIB9gEAAf8B8gHwAREB9AcAAfEBQwHzAQAB/wFvAR8BkwLzAXUCLAFNAfEB8wHwAUUBJAHy + BAAB/wFFAR8BbgH/AesBDgHtBQAB/wEyAVMBGgFZAf8BWQH/AVkEMgH2AQAB9AHsARMBDwHyBwAB7wER + ARUB8QH/AW8BHwEkAZMB8gHxAXUBLAG8AfEBvAEkAR8BJAHyBQABbwEgAZMBAAFtAQAB7QUAAf8DMgGa + AcMBWQH/ATgEMgH2AQAB9AEOAeoBEAHyBwAB7wFDARUBkgH/AW8CHwEkAZMB8QHwArwBBwFGAx8B8gUA + AW8BIAGTAQABbQEAAe0FAAH/ATIBUwEaAZoBUwGaAXoFMgH2AQAB9AHqAesBQwHyBwAB7wETAeoBBwH/ + AW8BAQEfASQBRgEcAfEB8AEHASUCHwEBAR8B8gUAAW8BIAGTAQAB6wEQAe0FAAH/ASwCMgFZAfYBGgFT + BTIB9gIAAQcB7QEUAfIHAAHvAW0B7AHwAf8BbwFFAUYBTAFvA/EB8AGTAW8BRgJFAfIEAAH/AW4BIAGT + AQAB6wEPAZIDAAHzAQAB/wFTAXoBwwEaAZoBegFZAnoDUwH/AgAB8gG8ARIB8wcAAQcB6wHwAfMB/wRv + AfEB8gG8AQcB8QHyAZMDbwHyBAAB8wELAR8BkwEAAesBEQGSAwABEwEAAf8BUwN1BHoEdQH/AgAB9AG8 + Af8JAAH/Ae8B/wEAAm8BkwLzAbwBkwFvAQcB8gHzAZMCbwHzBAAB9AEPAQEBkwEAAesBQwGSAQAB/wG8 + AREBAAH/AVMKegF1Af8CAAH/AZIB9AkAAfIB7wH/AQACbwG8AfMB8ARvAe8C8wGTAW8B8wQAAf8BEQEQ + AUMBbQFDAhUBbQEUAREBFAEAAf8BUwp6AXUB/wMAAf8B8gkAAfIDAAOTAQcGkwHvA5MB8wH0AW8CAAH/ + AhIBbQPtAUQC7QHsAZIBAAH/AXUKmgF6Af8EAAG8Ae8B/wUAAfQB7AHxAwAOkwHzAf8BRQH/AgABHAHt + Ae8CAAHxAUUFAAH/ARsBegl1ARoB/wQAAf8CQwG8Av8B9AEHARABbQH/AwAB8wyTARoC/wJuAu8BbgH3 + AewB7wGTAm4GAAz/BgAB/wHvARMDDgEUAQcB/xMAAf8LbxsAAf8B8wH/BgAE/wL0Ae8B7AGSAfIB9AX/ + AwAL/wIAAf8B8AHvAfIB/wcAAf8B8wEaAf8TAAH0ARIB7ATvAewB8AUAAf8B9AryAfMB/wEAAf8BBwH/ + Ae8B8gH/BQAB/wHyAVIBOAEaBAAB9AEIDAAB8ALsAvAC/wH0AZIB8AHtBAAB/wHyAfEBCAK8AfABCAQb + AvMC/wEHAbwB7AHtAfIB/wMAAf8B8AFSAjgBmQQAAfIBTwGXAfQJAAH/AewBbQP/AvQC/wEHAfMBBwMA + AfQB8wFyASgBLgEvAXgBLwQ1ARsB8gH/AQAB9AEHARQBDwHtAfQB/wEAAf8B8gExATgBWQF0Af8EAAHy + Ai0BTwH/CAAB6gFtAfQBvAP0AfMB9AEHAfQBkgEHAwAB9AHzAXICKAKYAi8DNQEbAfIB/wEAAf8B9AHv + ARMBFAH3AfQB/wHzAVICWQGZAf8FAAHyAjMBLQFPAbwB/wUAAf8B7QG8BPQB8wHyBPQB8QEHAgAB9AHz + AXICKAH/AQgFLwEIAfIB/wMAAf8BBwESAUMB7wG8ATEBOAFZAZkB/wYAAfICMwItAQIBmAH/BAAB8AHs + AfQB8wL0AQcB9AEaA/QB8AHtAewCAAH0AfMBcgIoAf8B9AFQAS4BeAFQAS8BvAHyAf8EAAH/AQcCEgHt + AVkBMgHzAf8HAAHyAjMBLQICAScBcgH0AwABBwHsAvQC8wH0AR8BvAT0Ae0B7wEOAQAB9AHzAXICKAH0 + Av8BvAH/AVABKAG8AfIB/wUAAf8B7wHsAfAB9wG8Af8IAAHyAy0CAgEnASEBSQH0AgABvAGSAvMB8ALz + AQcB7QTzAe0B7wH/AQAB9AHzAXICKAFQAfQD/wFQASgBvAHyAf8FAAH/AgcB7AHrAQcB8wL/BgAB8QZP + AUkBmAH/AgAB/wEHAfEB8wHyAfMBkwLzAQcC8wHxAfABBwIAAfQB8wFyAygBmAP/AVABKAG8AfIB/wQA + Af8BBwHxAfIBBwHvAewB6wHsAe8B9AH/BAAB8QZPAQgFAAEHAesB8wHvAfMBGgPzAfAB8QHsAfMB/wIA + AfQB8wFyAigBUAQIAUoBKAG8AfIB/wMAAfQBBwG8AfIC/wHwAewB7QHvAu0B9AQAAfEBTwRyAfEB/wUA + AfMB8QHsAfIB8APzAfIBvAHsAfEB7wMAAfQB8wFyCSgBvAHyAf8CAAH/AQcB8gHzAwAB8gG8AQcBvALv + AfEEAAHxAXIBlwFyAUkB9AgAAQcB8wHrAe8B9wEHAe8B7QFtAfAB7QH3Ae0B/wEAAfQB8wEcCXIB8QHy + Av8B8wHvAbwB8wH/AwAB9AEHAfIBBwH0Af8B9AQAAfECcgHvAf8KAALzAbwB7QLsAQcB8wEHAfIBvAH0 + AQcBAAH/AfAK8wHyAfQBAAH/AgcB8wUAAf8B7wH0Ae8B8wH/BQAB8QFPAQgB/w0AAfMBvAEHAbwB8gIA + AfIB9AEAAbwBAAL/CvQC/wEAAf8B8QHyAf8FAAH/AfIB8AHzAQcB9AUAAf8B8xcAAvEcAAH/AfMB/xwA + Af8B8AOYAfQgAAX/AfQK/wH0DfIBkQHvEAAQ/xAAAfEC9AL/Ae8D/wHyAfEB9AEIAbsB8AGRBAABAQEe + BAAB/wFFAQEDAAHzAfAF8gLxBvIB8AEAAbwCtAu1Af8B8gL0Av8B7wP/AfIB8QFyAXEBkQFJAXIDAAEB + AfkBRwELAgAB/wEeAfkBFwEBAgAB8gHzA/8B8wG7ArQBCQH0BP8B8AEAAfcBQwEVAkoBRAFDAREDQwEV + AUMBEwH0AfIC9AL/Ae8D/wHyAfEBSQL/AQcBcQIAAZMBbwL5AUcBCwH/AQsD+QFFAgAB8gHzAv8B9AG0 + AbMCCQK0AfED/wHwAQAB9wERAUMCSgEVAxACEQFDAREBZgH0AfIEBwHsAbwC8AK8AUkB8wH0AfEBcgMA + Am8CIAFGAQ4DIAEBAf8CAAHyAfMC/wKLAbQCCQG0AYsBrgP/AfABAAH3ARABQwJKAUQBEQMQAxEBFQH0 + AfIEvAGSAfAC8QHwAbwBSQHvAfAB7AHvBAABbwFMBSABAQH/AwAB8gHzAf8BBwGGAa0BtAEJAboBswGt + AYYBBwL/AfABAAH3AhQCSgEUAREBEAEPBA4BFQH0AfIB9AEHAQgB/wEHAf8B8gH/AfMB8QHwAUkBDQHt + Af8FAAFvAUwDIAEfAf8EAAHyAfMB/wG1AYYCtAKzAa0CiwGuAv8B8QEAAe8C6wFtAeoBEgEUARUBEQEQ + Ag8BEAEVAfQB8gLzAQcB9AEHAf8BvAH/AfMB8QP/AfIB/wQAAf8BHwNGAW8BRgEfBAAB8gHzAf8BtQGG + AbsBCQG0Aa0CiwHPAa4C/wHxAQABBwGTAXQBeQJ6AlMCTAMrAUsB9AHyAfMBBwG8AfQBBwH/AfAB/wHz + AfID/wHzBAAB/wEfA0YBdAJGAW8BHwMAAfIB8wH/ArUCCQG0AosBhgGLAbUC/wHxAQABBwGUAZoCoAF6 + AXUCUwRNAW8B9AHyAbwDBwH3AbwE8AHzAfQB/wHzAwAB/wEfA28BAQFuAXQCbwEWAR8CAAHyAfMB/wHz + AbUBBwEJAbQBzwKLAa4B9AL/AfEBAAEHApQDmgN1AuMCFwFvAfQF8wEHA/QB8wHyA/8B8wMAARoBTAIW + AR8B/wEAAW8DFgEfAgAB8gHzAv8B8AG1AQkBrgG0Aa4BzwG8A/8B8QEAAQcGtwOUA7EBjgH0AvMCCAHz + AbwD9AHzAfID/wHzBAABGgFMAR8B/wMAAW8BFgEfAwAC8gPzAbwCtQGuAbUBvATzAfEBAAEHAc8MtQH0 + AvMB8gEHAfMB8ATzAfID9AHzBQABGgH/BQABkwQAAfIJ8ALvA7UB8AEAAbsDrQOzArQF1QH0AvMC8AHz + AfAF8wP0AfMRAAH0CbwBBwG8AwcB8gEAAfIFCQTdBBkC/wbyB/MB/zEAAUIBTQE+BwABPgMAASgDAAFA + AwABYAMAAQEBAAEBBgABAxYAA/8BAAHgAQcB4AEHAfgBDwIAAeABAwHgAQMB+AEPAgABgAEBAYABAQH+ + AT8CAAGAAQABgAEAAf4BPwYAAf4BPwYAAf4BPwYAAf4BPwYAAf4BPwYAAf4BPwYAAf4BPwYAAf4BPwIA + AYABAAGAAQABzgE7AgABgAEAAYABAAHOATsCAAHAAQMBwAEDAcABAwIAAeABAwHgAQMBwAEDAgAB+AEP + AfgBDwL/AgAC/wIAAv8B4AEHAfgB/wIAAv8B4AEDAcABPwIAAfgBAwGAAQEBgAG/AYABAAHwAQABgAEA + AYABAgGAAQAB4AEDAgABgAEAAeABAAHAAQMCAAGAAQAB+AEAAYABAQIAAeABAAH4AT8BgAEBAgAB8AEB + AfgBPwGAAQECAAH4AQMB8AE/AYABAQIAAfwBAwHgAT8BgAEDAgAB/gEHAeABPwHAAQMBgAEAAf4BDwHw + AT8B4AEHAYABAAH/AY8B8AE/AfgBDwHAAQMB/wGPAfABPwL/AeABAwL/AfwD/wH4AQ8B4QGDAYABAAGA + AQABggEDAeABAwHgAQMBwAEDAYIBAwHgAQMCAAHAAQMCAAHgAQMCAAHAAQMCAAHgAQMCAAHAAQMCAAHg + AQMCAAHAAQMBAAEDAYABAQIAAcABAwEAAQMBgAMAAYABAAHBAQMEAAGAAQABwAMAAYABAAHAAQMBgAEA + AYABAAGAAQAB4AEDAYABAAH4AQ8B4AEHAfABAwGAAQAB+AEfAeABBwH4AQMBgAEAAfwBPwHgAQcB/AEj + AeABgwH+AT8B4AEHAf4BPwHwAYMC/wHgAQcC/wH5AecBgAEAAf4BAwL/AYABAAGAAQAB/wGPAcABAwHg + AT8CAAHgAQ8BgAEBAQABOwIAAeABDwGAAQEBBwHxAgAB8AEPAYABAQEHAfACAAH4AY8BgAEBAQcB8AIA + AfgBjwGAAQEBBwHwAgAB+AGPAYABAQGHAfACAAHwAY4BgAEBAYcB8AIAAfABjgGAAQEBjwH4AYABAAHw + AYgBgAEBAY8B+AGAAQAB8AEAAYABAQHPAfsBgAEAATABAAGAAQEC4wGAAQABGAHPAYABAQHgAQMBgAIA + AQ8BwAEDAfABBwL/AQABDwL/Af4BPwIAAeABAwEHAfAC/wHgAQ8BgAEBAQMB4AHzAf8BwAEHAYABAAEB + AcAB8AH/AYABAwGAAQACgAHwAX8BgAEDAYABAAGAAQEB8AEfAQABAQGAAQAB4AEDAfABDwEAAQEBgAEA + AfABBwHwAQcCAAGAAQAB+AEPAfABAwIAAYABAAH4AQMB8AEDAQABAQGAAQAB8AEAAfABDwGAAQEBgAEA + AeABAAHwAQ8BgAEDAYABAAHDAYAB8AE/AcABAAGAAQABAwGAAfABfwHgAQABgAEBAQ8BgQHwAf8B+AEy + AYABAQEPAYEB8wL/AfkD/wHjA/8BwAT/BAAC/wIAAv8CAAHzAccCAAGAAwAB4QGDAgABgAMAAcABAwIA + AYADAAHgAQMCAAGAAwAB8AEHAgABgAMAAfgBDwIAAYADAAHwAQ8CAAGAAgABAQHgAQcCAAGAAgABAQHA + AQMCAAGAAgABAQHAAYMCAAGAAgABAQHhAccCAAGAAgABAQHzAe8CAAGAAgABAQL/AgABgAIAAQEG/ws= @@ -4495,344 +4553,6 @@ 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 - wIg2Hr6dReMAAAAASUVORK5CYII= - - - - - iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAtxJREFUSEvt - 0m1Ik1EUB3C3yk193OPUJZovm69Zznwpw2BYkE6TNDdNbaXOt+l0Pr61FNNSFMs0bUUayoKIgpaYmNN0 - U1MxJCKiD2VFkBBRBNGnovKcDG6CGFHql8IfHC6c87/nfrkWa/4PTmVOXLVBrY3SRQlJa/Vw1VxLXh2v - Vz+jR6FO+IKlYbmT0cpRamqDY4PjzYp7FWB4awDdEx3Qp+hndDm9iUSWj5fDW+9c63ydMTPYNdMFnTOd - +KMaphtA0iG5TWJL+df4y5huZtz3uK8vaS1hl2u3zq3G7UqeUYWtD1qw5X4zNE+fwaapJhSfF3+xLbVN - JNHFeIW8+IhLks+Nk3WwvTX0lQvj4kVGC+wz7dmiKlFX9q0MqJ+sgbq71XBypBpqTScgpC34K1vFPkKi - iwk0guiws8GfKoYYrDQzcHSoAHc0hr50znde+BkOCgeWt9a7XXkjBapGi6HCxKB2kMGqwXKQ6MK/cVSc - TBJdyqfSx6juVoCmTwnMgBJKhpVQPJAOodXbnjtlbXTlK/gsz0LRubSr8VBmzoLiO0oo6leC1qgG6YU9 - c1Y5Viqy6teoDMrL85jrbKYhDnP75JA/KMcCUyIW9MsgqGzrU/ds9/ZUfSRoRpJAPSTHPKMcSgYyUNYR - PUdlURqy5vds0mz8/LTC15k9kaAciMRsUxTmjkVBbn8kpuolmD8egyUTiVA6mjz/cBwc7IgGOyVdRq7/ - GRuFzZaActGbtN6dmDwoxkPmQFCMilExGoDJw5tR2iOA3ddojDjtBfbp/Epy7e9QSVSguMjjXUKfC0Sb - aYgdn68JGvaNzZ/DfJC2+oBdKl1D4stDJVAhQRqP94en3ED2iI/yx3xMeuiA8Rf9gJbR9SS2Mtb7rcNC - Cz0+qGY8MG1WgCmX/ZGO5TVxpBwWiawcN4YbvosRfVQbgoEnpdo4ey1Xb/lPggO2YZ6pjgVULJdNWmv+ - GRYW3wHoVCJ7F4lIiQAAAABJRU5ErkJggg== - - - - - iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAtxJREFUSEvt - 0m1Ik1EUB3C3yk193OPUJZovm69Zznwpw2BYkE6TNDdNbaXOt+l0Pr61FNNSFMs0bUUayoKIgpaYmNN0 - U1MxJCKiD2VFkBBRBNGnovKcDG6CGFHql8IfHC6c87/nfrkWa/4PTmVOXLVBrY3SRQlJa/Vw1VxLXh2v - Vz+jR6FO+IKlYbmT0cpRamqDY4PjzYp7FWB4awDdEx3Qp+hndDm9iUSWj5fDW+9c63ydMTPYNdMFnTOd - +KMaphtA0iG5TWJL+df4y5huZtz3uK8vaS1hl2u3zq3G7UqeUYWtD1qw5X4zNE+fwaapJhSfF3+xLbVN - JNHFeIW8+IhLks+Nk3WwvTX0lQvj4kVGC+wz7dmiKlFX9q0MqJ+sgbq71XBypBpqTScgpC34K1vFPkKi - iwk0guiws8GfKoYYrDQzcHSoAHc0hr50znde+BkOCgeWt9a7XXkjBapGi6HCxKB2kMGqwXKQ6MK/cVSc - TBJdyqfSx6juVoCmTwnMgBJKhpVQPJAOodXbnjtlbXTlK/gsz0LRubSr8VBmzoLiO0oo6leC1qgG6YU9 - c1Y5Viqy6teoDMrL85jrbKYhDnP75JA/KMcCUyIW9MsgqGzrU/ds9/ZUfSRoRpJAPSTHPKMcSgYyUNYR - PUdlURqy5vds0mz8/LTC15k9kaAciMRsUxTmjkVBbn8kpuolmD8egyUTiVA6mjz/cBwc7IgGOyVdRq7/ - GRuFzZaActGbtN6dmDwoxkPmQFCMilExGoDJw5tR2iOA3ddojDjtBfbp/Epy7e9QSVSguMjjXUKfC0Sb - aYgdn68JGvaNzZ/DfJC2+oBdKl1D4stDJVAhQRqP94en3ED2iI/yx3xMeuiA8Rf9gJbR9SS2Mtb7rcNC - Cz0+qGY8MG1WgCmX/ZGO5TVxpBwWiawcN4YbvosRfVQbgoEnpdo4ey1Xb/lPggO2YZ6pjgVULJdNWmv+ - GRYW3wHoVCJ7F4lIiQAAAABJRU5ErkJggg== @@ -5212,6 +4932,344 @@ aYgdn68JGvaNzZ/DfJC2+oBdKl1D4stDJVAhQRqP94en3ED2iI/yx3xMeuiA8Rf9gJbR9SS2Mtb7rcNC Cz0+qGY8MG1WgCmX/ZGO5TVxpBwWiawcN4YbvosRfVQbgoEnpdo4ey1Xb/lPggO2YZ6pjgVULJdNWmv+ GRYW3wHoVCJ7F4lIiQAAAABJRU5ErkJggg== + + + + + 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 + wIg2Hr6dReMAAAAASUVORK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAtxJREFUSEvt + 0m1Ik1EUB3C3yk193OPUJZovm69Zznwpw2BYkE6TNDdNbaXOt+l0Pr61FNNSFMs0bUUayoKIgpaYmNN0 + U1MxJCKiD2VFkBBRBNGnovKcDG6CGFHql8IfHC6c87/nfrkWa/4PTmVOXLVBrY3SRQlJa/Vw1VxLXh2v + Vz+jR6FO+IKlYbmT0cpRamqDY4PjzYp7FWB4awDdEx3Qp+hndDm9iUSWj5fDW+9c63ydMTPYNdMFnTOd + +KMaphtA0iG5TWJL+df4y5huZtz3uK8vaS1hl2u3zq3G7UqeUYWtD1qw5X4zNE+fwaapJhSfF3+xLbVN + JNHFeIW8+IhLks+Nk3WwvTX0lQvj4kVGC+wz7dmiKlFX9q0MqJ+sgbq71XBypBpqTScgpC34K1vFPkKi + iwk0guiws8GfKoYYrDQzcHSoAHc0hr50znde+BkOCgeWt9a7XXkjBapGi6HCxKB2kMGqwXKQ6MK/cVSc + TBJdyqfSx6juVoCmTwnMgBJKhpVQPJAOodXbnjtlbXTlK/gsz0LRubSr8VBmzoLiO0oo6leC1qgG6YU9 + c1Y5Viqy6teoDMrL85jrbKYhDnP75JA/KMcCUyIW9MsgqGzrU/ds9/ZUfSRoRpJAPSTHPKMcSgYyUNYR + PUdlURqy5vds0mz8/LTC15k9kaAciMRsUxTmjkVBbn8kpuolmD8egyUTiVA6mjz/cBwc7IgGOyVdRq7/ + GRuFzZaActGbtN6dmDwoxkPmQFCMilExGoDJw5tR2iOA3ddojDjtBfbp/Epy7e9QSVSguMjjXUKfC0Sb + aYgdn68JGvaNzZ/DfJC2+oBdKl1D4stDJVAhQRqP94en3ED2iI/yx3xMeuiA8Rf9gJbR9SS2Mtb7rcNC + Cz0+qGY8MG1WgCmX/ZGO5TVxpBwWiawcN4YbvosRfVQbgoEnpdo4ey1Xb/lPggO2YZ6pjgVULJdNWmv+ + GRYW3wHoVCJ7F4lIiQAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAtxJREFUSEvt + 0m1Ik1EUB3C3yk193OPUJZovm69Zznwpw2BYkE6TNDdNbaXOt+l0Pr61FNNSFMs0bUUayoKIgpaYmNN0 + U1MxJCKiD2VFkBBRBNGnovKcDG6CGFHql8IfHC6c87/nfrkWa/4PTmVOXLVBrY3SRQlJa/Vw1VxLXh2v + Vz+jR6FO+IKlYbmT0cpRamqDY4PjzYp7FWB4awDdEx3Qp+hndDm9iUSWj5fDW+9c63ydMTPYNdMFnTOd + +KMaphtA0iG5TWJL+df4y5huZtz3uK8vaS1hl2u3zq3G7UqeUYWtD1qw5X4zNE+fwaapJhSfF3+xLbVN + JNHFeIW8+IhLks+Nk3WwvTX0lQvj4kVGC+wz7dmiKlFX9q0MqJ+sgbq71XBypBpqTScgpC34K1vFPkKi + iwk0guiws8GfKoYYrDQzcHSoAHc0hr50znde+BkOCgeWt9a7XXkjBapGi6HCxKB2kMGqwXKQ6MK/cVSc + TBJdyqfSx6juVoCmTwnMgBJKhpVQPJAOodXbnjtlbXTlK/gsz0LRubSr8VBmzoLiO0oo6leC1qgG6YU9 + c1Y5Viqy6teoDMrL85jrbKYhDnP75JA/KMcCUyIW9MsgqGzrU/ds9/ZUfSRoRpJAPSTHPKMcSgYyUNYR + PUdlURqy5vds0mz8/LTC15k9kaAciMRsUxTmjkVBbn8kpuolmD8egyUTiVA6mjz/cBwc7IgGOyVdRq7/ + GRuFzZaActGbtN6dmDwoxkPmQFCMilExGoDJw5tR2iOA3ddojDjtBfbp/Epy7e9QSVSguMjjXUKfC0Sb + aYgdn68JGvaNzZ/DfJC2+oBdKl1D4stDJVAhQRqP94en3ED2iI/yx3xMeuiA8Rf9gJbR9SS2Mtb7rcNC + Cz0+qGY8MG1WgCmX/ZGO5TVxpBwWiawcN4YbvosRfVQbgoEnpdo4ey1Xb/lPggO2YZ6pjgVULJdNWmv+ + GRYW3wHoVCJ7F4lIiQAAAABJRU5ErkJggg== @@ -5265,7 +5323,7 @@ VIP user: DP0GVN: https://www.awi.de/expedition/stationen/neumayer-station-iii.h 482, 17 - + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAL EwAACxMBAJqcGAAAA3xJREFUSEulVstL1FEYvfmYMR+LisJoU5QEiVipSLQQn6RjNMk4ig+wCJSpDCzU @@ -5286,7 +5344,7 @@ VIP user: DP0GVN: https://www.awi.de/expedition/stationen/neumayer-station-iii.h f/5tMeY3ET3ttnz8RoQAAAAASUVORK5CYII= - + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAL EwAACxMBAJqcGAAAA3xJREFUSEulVstL1FEYvfmYMR+LisJoU5QEiVipSLQQn6RjNMk4ig+wCJSpDCzU diff --git a/oscardata/oscardata/Properties/Actions-go-next-view-icon.png b/oscardata/oscardata/Properties/Actions-go-next-view-icon.png new file mode 100644 index 0000000..9857ab1 Binary files /dev/null and b/oscardata/oscardata/Properties/Actions-go-next-view-icon.png differ diff --git a/oscardata/oscardata/Properties/Fernschreiben für Funkamateure.pdf b/oscardata/oscardata/Properties/Fernschreiben für Funkamateure.pdf new file mode 100644 index 0000000..1930534 Binary files /dev/null and b/oscardata/oscardata/Properties/Fernschreiben für Funkamateure.pdf differ diff --git a/oscardata/oscardata/Properties/Lehrstuhlseminar_BenjaminKoch.pdf b/oscardata/oscardata/Properties/Lehrstuhlseminar_BenjaminKoch.pdf new file mode 100644 index 0000000..4a651be Binary files /dev/null and b/oscardata/oscardata/Properties/Lehrstuhlseminar_BenjaminKoch.pdf differ diff --git a/oscardata/oscardata/Properties/Resources.Designer.cs b/oscardata/oscardata/Properties/Resources.Designer.cs index aa88aeb..84e419f 100755 --- a/oscardata/oscardata/Properties/Resources.Designer.cs +++ b/oscardata/oscardata/Properties/Resources.Designer.cs @@ -60,6 +60,26 @@ namespace oscardata.Properties { } } + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap amsat_dl_logo { + get { + object obj = ResourceManager.GetObject("amsat_dl_logo", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap answer { + get { + object obj = ResourceManager.GetObject("answer", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. /// @@ -150,6 +170,16 @@ namespace oscardata.Properties { } } + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap clearscreen { + get { + object obj = ResourceManager.GetObject("clearscreen", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. /// @@ -160,6 +190,16 @@ namespace oscardata.Properties { } } + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap foht { + get { + object obj = ResourceManager.GetObject("foht", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. /// @@ -180,6 +220,16 @@ namespace oscardata.Properties { } } + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap home_icon { + get { + object obj = ResourceManager.GetObject("home_icon", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. /// @@ -300,6 +350,26 @@ namespace oscardata.Properties { } } + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap rtty { + get { + object obj = ResourceManager.GetObject("rtty", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap ryry_icon { + get { + object obj = ResourceManager.GetObject("ryry_icon", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. /// @@ -370,6 +440,16 @@ namespace oscardata.Properties { } } + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap start_icon { + get { + object obj = ResourceManager.GetObject("start_icon", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. /// @@ -380,6 +460,16 @@ namespace oscardata.Properties { } } + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap stop_icon { + get { + object obj = ResourceManager.GetObject("stop_icon", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. /// @@ -420,6 +510,16 @@ namespace oscardata.Properties { } } + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap user_icon { + get { + object obj = ResourceManager.GetObject("user_icon", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. /// @@ -439,5 +539,15 @@ namespace oscardata.Properties { return ((System.Drawing.Bitmap)(obj)); } } + + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap voice_icon { + get { + object obj = ResourceManager.GetObject("voice_icon", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } } } diff --git a/oscardata/oscardata/Properties/Resources.resx b/oscardata/oscardata/Properties/Resources.resx index a88624c..7a78a7c 100755 --- a/oscardata/oscardata/Properties/Resources.resx +++ b/oscardata/oscardata/Properties/Resources.resx @@ -232,4 +232,37 @@ playbackicon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + rtty.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + amsat_dl_logo.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + clearscreen.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + foht.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + home-icon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ryry-icon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + voice-icon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + answer.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + start-icon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + stop-icon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + user-icon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + \ No newline at end of file diff --git a/oscardata/oscardata/Properties/amsat_dl_logo.png b/oscardata/oscardata/Properties/amsat_dl_logo.png new file mode 100644 index 0000000..6e7ad5e Binary files /dev/null and b/oscardata/oscardata/Properties/amsat_dl_logo.png differ diff --git a/oscardata/oscardata/Properties/answer.png b/oscardata/oscardata/Properties/answer.png new file mode 100644 index 0000000..51ac561 Binary files /dev/null and b/oscardata/oscardata/Properties/answer.png differ diff --git a/oscardata/oscardata/Properties/clearscreen.png b/oscardata/oscardata/Properties/clearscreen.png new file mode 100644 index 0000000..820f4c1 Binary files /dev/null and b/oscardata/oscardata/Properties/clearscreen.png differ diff --git a/oscardata/oscardata/Properties/endqso-icon.png b/oscardata/oscardata/Properties/endqso-icon.png new file mode 100644 index 0000000..1075d70 Binary files /dev/null and b/oscardata/oscardata/Properties/endqso-icon.png differ diff --git a/oscardata/oscardata/Properties/foht.png b/oscardata/oscardata/Properties/foht.png new file mode 100644 index 0000000..f1d04b9 Binary files /dev/null and b/oscardata/oscardata/Properties/foht.png differ diff --git a/oscardata/oscardata/Properties/home-icon.png b/oscardata/oscardata/Properties/home-icon.png new file mode 100644 index 0000000..d49d6aa Binary files /dev/null and b/oscardata/oscardata/Properties/home-icon.png differ diff --git a/oscardata/oscardata/Properties/rtty.png b/oscardata/oscardata/Properties/rtty.png new file mode 100644 index 0000000..0e07ac9 Binary files /dev/null and b/oscardata/oscardata/Properties/rtty.png differ diff --git a/oscardata/oscardata/Properties/ryry-icon.png b/oscardata/oscardata/Properties/ryry-icon.png new file mode 100644 index 0000000..50571d1 Binary files /dev/null and b/oscardata/oscardata/Properties/ryry-icon.png differ diff --git a/oscardata/oscardata/Properties/start-icon.png b/oscardata/oscardata/Properties/start-icon.png new file mode 100644 index 0000000..1f778d8 Binary files /dev/null and b/oscardata/oscardata/Properties/start-icon.png differ diff --git a/oscardata/oscardata/Properties/stop-icon.png b/oscardata/oscardata/Properties/stop-icon.png new file mode 100644 index 0000000..ef5edcc Binary files /dev/null and b/oscardata/oscardata/Properties/stop-icon.png differ diff --git a/oscardata/oscardata/Properties/text-icon.png b/oscardata/oscardata/Properties/text-icon.png new file mode 100644 index 0000000..f1d04b9 Binary files /dev/null and b/oscardata/oscardata/Properties/text-icon.png differ diff --git a/oscardata/oscardata/Properties/uart_design_doc.pdf b/oscardata/oscardata/Properties/uart_design_doc.pdf new file mode 100644 index 0000000..4b03094 Binary files /dev/null and b/oscardata/oscardata/Properties/uart_design_doc.pdf differ diff --git a/oscardata/oscardata/Properties/user-icon.png b/oscardata/oscardata/Properties/user-icon.png new file mode 100644 index 0000000..317b8c5 Binary files /dev/null and b/oscardata/oscardata/Properties/user-icon.png differ diff --git a/oscardata/oscardata/Properties/voice-icon.png b/oscardata/oscardata/Properties/voice-icon.png new file mode 100644 index 0000000..f233f7a Binary files /dev/null and b/oscardata/oscardata/Properties/voice-icon.png differ diff --git a/oscardata/oscardata/bin/Release/oscardata.exe b/oscardata/oscardata/bin/Release/oscardata.exe index 28bc9e3..a83dfd7 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 275d8e0..d353501 100755 --- a/oscardata/oscardata/config.cs +++ b/oscardata/oscardata/config.cs @@ -39,6 +39,10 @@ namespace oscardata public static Byte tuning = 27; public static Byte marker = 28; public static Byte setfreq = 29; + public static Byte rttykey = 30; + public static Byte rttystring = 31; + public static Byte txonoff = 32; + public static Byte rtty_stopTX = 33; // frame sequence, modem needs that for i.e. sending a preamble public static Byte FirstFrame = 0; @@ -51,6 +55,7 @@ namespace oscardata public static Byte udp_bc = 3; public static Byte udp_fft = 4; public static Byte udp_iq = 5; + public static Byte udp_rtty_rx = 6; // global static variables public static bool running = true; @@ -85,6 +90,7 @@ namespace oscardata public static Color WindowBackColor; public static String[] langstr; public static int tuning_active = 0; + public static int tune_frequency = 1500; public static String[] getOwnIPs() { @@ -435,5 +441,24 @@ namespace oscardata } catch { } } + + // Culture invariant conversion + + public static double MyToDouble(String s) + + { + double r = 0; + + try + { + s = s.Replace(',', '.'); + r = Convert.ToDouble(s, System.Globalization.CultureInfo.InvariantCulture); + } + catch + { + } + return r; + + } } } diff --git a/oscardata/oscardata/oscardata.csproj b/oscardata/oscardata/oscardata.csproj index 2004078..ddd5021 100755 --- a/oscardata/oscardata/oscardata.csproj +++ b/oscardata/oscardata/oscardata.csproj @@ -64,12 +64,6 @@ Form1.cs - - Form - - - Form2_showtext.cs - Component @@ -82,9 +76,6 @@ Form1.cs - - Form2_showtext.cs - ResXFileCodeGenerator Resources.Designer.cs @@ -152,6 +143,17 @@ + + + + + + + + + + + diff --git a/oscardata/oscardata/udp.cs b/oscardata/oscardata/udp.cs index e1488f2..4c05374 100755 --- a/oscardata/oscardata/udp.cs +++ b/oscardata/oscardata/udp.cs @@ -31,6 +31,7 @@ namespace oscardata static UdpQueue uq_ctrl = new UdpQueue(); static UdpQueue uq_fft = new UdpQueue(); static UdpQueue uq_iq = new UdpQueue(); + static UdpQueue uq_rtty_rx = new UdpQueue(); public static int searchtimeout = 0; static String last_audiodevstring = ""; @@ -150,6 +151,10 @@ namespace oscardata statics.RXinSync = b[3]; statics.maxRXlevel = b[4]; statics.maxTXlevel = b[5]; + statics.tune_frequency = b[6]; + statics.tune_frequency <<= 8; + statics.tune_frequency += b[7]; + //Console.WriteLine("f:" + statics.tune_frequency); Byte[] b1 = new byte[b.Length - 6]; Array.Copy(b, 6, b1, 0, b1.Length); drawFftBitmap(b1); @@ -175,6 +180,11 @@ namespace oscardata } drawBitmap(re, im); } + + if (rxtype == statics.udp_rtty_rx) + { + uq_rtty_rx.Add(b); + } } } catch { } @@ -267,19 +277,22 @@ namespace oscardata static Font fnt = new Font("Verdana", 9.0f); static Font smallfnt = new Font("Verdana", 7.0f); static Pen penyl = new Pen(Brushes.Yellow, 1); + static Pen pengn = new Pen(Brushes.LightGreen, 3); static void drawFftBitmap(Byte[] b1) { - if(!bmf) + int yl = ffth - 20; + int yh = 20; + + if (!bmf) { // pre-draw background bmf = true; - int yl = ffth - 20; - int yh = 20; Pen pen = new Pen(Brushes.Navy, 1); Pen pensolid = new Pen(Brushes.Navy, 1); pen.DashPattern = new float[] { 1.0F, 2.0F, 1.0F, 2.0F }; Pen penred = new Pen(Brushes.Red, 1); + Pen penred2 = new Pen(Brushes.Red, 2); using (Graphics gr = Graphics.FromImage(bmskala)) { @@ -289,7 +302,7 @@ namespace oscardata for (int x = 10; x <= 390; x += 10) gr.DrawLine(pen, x, yl, x, yh); - gr.DrawLine(penred, 10, yl, 10, yh); + gr.DrawLine(penred2, 11, yl, 10, yh); gr.DrawLine(penred, 150, yl, 150, yh); gr.DrawLine(pensolid, 20, yl, 20, yh); gr.DrawLine(pensolid, 280, yl, 280, yh); @@ -322,6 +335,15 @@ namespace oscardata gr.FillRectangle(bgcol, 0, 0, bm.Width, bm.Height); // scala gr.DrawImage(bmskala,16,2); + + if(statics.real_datarate == 45) + { + // RTTY Markers + int low = (statics.tune_frequency - 170 / 2)/10; + int high = (statics.tune_frequency + 170 / 2)/10; + gr.DrawLine(pengn, low + 16, yl, low + 16, yh + 3); + gr.DrawLine(pengn, high + 16, yl, high + 16, yh + 3); + } /* // screws at the 4 corners Bitmap screw = new Bitmap(Properties.Resources.schraube); @@ -463,6 +485,12 @@ namespace oscardata if (uq_iq.Count() == 0) return false; return true; } + + public static Byte[] getRTTYrx() + { + if (uq_rtty_rx.Count() == 0) return null; + return uq_rtty_rx.Getarr(); + } } // this class is a thread safe queue wich is used