diff --git a/WinRelease/hsmodem.exe b/WinRelease/hsmodem.exe
index c2f5a1f..048d8a9 100755
Binary files a/WinRelease/hsmodem.exe and b/WinRelease/hsmodem.exe differ
diff --git a/WinRelease/hsmodem.iobj b/WinRelease/hsmodem.iobj
index 1fbcac8..2289cf4 100755
Binary files a/WinRelease/hsmodem.iobj and b/WinRelease/hsmodem.iobj differ
diff --git a/WinRelease/hsmodem.ipdb b/WinRelease/hsmodem.ipdb
index 2346a5b..da71cc2 100755
Binary files a/WinRelease/hsmodem.ipdb and b/WinRelease/hsmodem.ipdb differ
diff --git a/WinRelease/hsmodem.pdb b/WinRelease/hsmodem.pdb
index 69478ee..29e3771 100755
Binary files a/WinRelease/hsmodem.pdb and b/WinRelease/hsmodem.pdb differ
diff --git a/WinRelease/oscardata.exe b/WinRelease/oscardata.exe
index 82afc41..28bc9e3 100755
Binary files a/WinRelease/oscardata.exe and b/WinRelease/oscardata.exe differ
diff --git a/hsmodem/Makefile b/hsmodem/Makefile
index 656ae2a..a5a2525 100755
--- a/hsmodem/Makefile
+++ b/hsmodem/Makefile
@@ -9,7 +9,7 @@
CXXFLAGS = -Wall -O3 -std=c++0x -Wno-write-strings -Wno-narrowing
LDFLAGS = -lpthread -lrt -lsndfile -lasound -lm -lopus -lfftw3 -lfftw3_threads -lliquid -lcodec2 -lsoundio
-OBJ = hsmodem.o constellation.o crc16.o frame_packer.o main_helper.o scrambler.o speed.o fec.o udp.o fft.o liquid_if.o symboltracker.o voiceprocessor.o codec2.o soundio.o fifo.o announcement.o fifo_voice.o voiceio.o tuning.o
+OBJ = hsmodem.o constellation.o crc16.o frame_packer.o main_helper.o scrambler.o speed.o fec.o udp.o fft.o liquid_if.o symboltracker.o voiceprocessor.o codec2.o soundio.o fifo.o announcement.o fifo_voice.o voiceio.o tuning.o rtty.o
default: $(OBJ)
mkdir -p ../hsmodemLinux
diff --git a/hsmodem/Release/announcement.obj b/hsmodem/Release/announcement.obj
deleted file mode 100755
index 3bdde8d..0000000
Binary files a/hsmodem/Release/announcement.obj and /dev/null differ
diff --git a/hsmodem/Release/codec2.obj b/hsmodem/Release/codec2.obj
deleted file mode 100755
index e9d13cb..0000000
Binary files a/hsmodem/Release/codec2.obj and /dev/null differ
diff --git a/hsmodem/Release/constellation.obj b/hsmodem/Release/constellation.obj
deleted file mode 100755
index ff547b8..0000000
Binary files a/hsmodem/Release/constellation.obj and /dev/null differ
diff --git a/hsmodem/Release/crc16.obj b/hsmodem/Release/crc16.obj
deleted file mode 100755
index 12bc6f7..0000000
Binary files a/hsmodem/Release/crc16.obj and /dev/null differ
diff --git a/hsmodem/Release/fec.obj b/hsmodem/Release/fec.obj
deleted file mode 100755
index 895d19e..0000000
Binary files a/hsmodem/Release/fec.obj and /dev/null differ
diff --git a/hsmodem/Release/fft.obj b/hsmodem/Release/fft.obj
deleted file mode 100755
index 42f29c9..0000000
Binary files a/hsmodem/Release/fft.obj and /dev/null differ
diff --git a/hsmodem/Release/fifo.obj b/hsmodem/Release/fifo.obj
deleted file mode 100755
index 4348d34..0000000
Binary files a/hsmodem/Release/fifo.obj and /dev/null differ
diff --git a/hsmodem/Release/fifo_voice.obj b/hsmodem/Release/fifo_voice.obj
deleted file mode 100755
index b32ff78..0000000
Binary files a/hsmodem/Release/fifo_voice.obj and /dev/null differ
diff --git a/hsmodem/Release/frame_packer.obj b/hsmodem/Release/frame_packer.obj
deleted file mode 100755
index 88275ff..0000000
Binary files a/hsmodem/Release/frame_packer.obj and /dev/null differ
diff --git a/hsmodem/Release/hsmodem.Build.CppClean.log b/hsmodem/Release/hsmodem.Build.CppClean.log
deleted file mode 100755
index 7e8dd76..0000000
--- a/hsmodem/Release/hsmodem.Build.CppClean.log
+++ /dev/null
@@ -1,32 +0,0 @@
-e:\funk\hsmodem\hsmodem\release\vc140.pdb
-e:\funk\hsmodem\hsmodem\release\tuning.obj
-e:\funk\hsmodem\hsmodem\release\liquid_if.obj
-e:\funk\hsmodem\hsmodem\release\fft.obj
-e:\funk\hsmodem\hsmodem\release\voiceprocessor.obj
-e:\funk\hsmodem\hsmodem\release\voiceio.obj
-e:\funk\hsmodem\hsmodem\release\udp.obj
-e:\funk\hsmodem\hsmodem\release\symboltracker.obj
-e:\funk\hsmodem\hsmodem\release\speed.obj
-e:\funk\hsmodem\hsmodem\release\soundio.obj
-e:\funk\hsmodem\hsmodem\release\scrambler.obj
-e:\funk\hsmodem\hsmodem\release\main_helper.obj
-e:\funk\hsmodem\hsmodem\release\hsmodem.obj
-e:\funk\hsmodem\hsmodem\release\frame_packer.obj
-e:\funk\hsmodem\hsmodem\release\fifo_voice.obj
-e:\funk\hsmodem\hsmodem\release\fifo.obj
-e:\funk\hsmodem\hsmodem\release\fec.obj
-e:\funk\hsmodem\hsmodem\release\crc16.obj
-e:\funk\hsmodem\hsmodem\release\constellation.obj
-e:\funk\hsmodem\hsmodem\release\codec2.obj
-e:\funk\hsmodem\hsmodem\release\announcement.obj
-e:\funk\hsmodem\winrelease\hsmodem.exe
-e:\funk\hsmodem\winrelease\hsmodem.ipdb
-e:\funk\hsmodem\winrelease\hsmodem.iobj
-e:\funk\hsmodem\winrelease\hsmodem.pdb
-e:\funk\hsmodem\hsmodem\..\winrelease\hsmodem.exe
-e:\funk\hsmodem\hsmodem\release\hsmodem.tlog\cl.command.1.tlog
-e:\funk\hsmodem\hsmodem\release\hsmodem.tlog\cl.read.1.tlog
-e:\funk\hsmodem\hsmodem\release\hsmodem.tlog\cl.write.1.tlog
-e:\funk\hsmodem\hsmodem\release\hsmodem.tlog\link.command.1.tlog
-e:\funk\hsmodem\hsmodem\release\hsmodem.tlog\link.read.1.tlog
-e:\funk\hsmodem\hsmodem\release\hsmodem.tlog\link.write.1.tlog
diff --git a/hsmodem/Release/hsmodem.log b/hsmodem/Release/hsmodem.log
deleted file mode 100755
index 6a30007..0000000
--- a/hsmodem/Release/hsmodem.log
+++ /dev/null
@@ -1,24 +0,0 @@
- announcement.cpp
- codec2.cpp
- constellation.cpp
- crc16.cpp
- fec.cpp
- fft.cpp
- fifo.cpp
- fifo_voice.cpp
- frame_packer.cpp
- hsmodem.cpp
- liquid_if.cpp
- main_helper.cpp
- scrambler.cpp
- soundio.cpp
- speed.cpp
- symboltracker.cpp
- tuning.cpp
- udp.cpp
- voiceio.cpp
- voiceprocessor.cpp
- Code wird generiert.
- All 602 functions were compiled because no usable IPDB/IOBJ from previous compilation was found.
- Codegenerierung ist abgeschlossen.
- hsmodem.vcxproj -> E:\funk\hsmodem\hsmodem\..\WinRelease\hsmodem.exe
diff --git a/hsmodem/Release/hsmodem.obj b/hsmodem/Release/hsmodem.obj
deleted file mode 100755
index 8fd2ecf..0000000
Binary files a/hsmodem/Release/hsmodem.obj and /dev/null differ
diff --git a/hsmodem/Release/hsmodem.tlog/CL.command.1.tlog b/hsmodem/Release/hsmodem.tlog/CL.command.1.tlog
deleted file mode 100755
index 70e5322..0000000
Binary files a/hsmodem/Release/hsmodem.tlog/CL.command.1.tlog and /dev/null differ
diff --git a/hsmodem/Release/hsmodem.tlog/CL.read.1.tlog b/hsmodem/Release/hsmodem.tlog/CL.read.1.tlog
deleted file mode 100755
index ef9120e..0000000
Binary files a/hsmodem/Release/hsmodem.tlog/CL.read.1.tlog and /dev/null differ
diff --git a/hsmodem/Release/hsmodem.tlog/CL.write.1.tlog b/hsmodem/Release/hsmodem.tlog/CL.write.1.tlog
deleted file mode 100755
index 6b01914..0000000
Binary files a/hsmodem/Release/hsmodem.tlog/CL.write.1.tlog and /dev/null differ
diff --git a/hsmodem/Release/hsmodem.tlog/hsmodem.lastbuildstate b/hsmodem/Release/hsmodem.tlog/hsmodem.lastbuildstate
deleted file mode 100755
index d1d5971..0000000
--- a/hsmodem/Release/hsmodem.tlog/hsmodem.lastbuildstate
+++ /dev/null
@@ -1,2 +0,0 @@
-#TargetFrameworkVersion=v4.0:PlatformToolSet=v140_xp:EnableManagedIncrementalBuild=false:VCToolArchitecture=Native32Bit:WindowsTargetPlatformVersion=8.1
-Release|Win32|E:\funk\hsmodem\|
diff --git a/hsmodem/Release/hsmodem.tlog/link.command.1.tlog b/hsmodem/Release/hsmodem.tlog/link.command.1.tlog
deleted file mode 100755
index bc14a2c..0000000
Binary files a/hsmodem/Release/hsmodem.tlog/link.command.1.tlog and /dev/null differ
diff --git a/hsmodem/Release/hsmodem.tlog/link.read.1.tlog b/hsmodem/Release/hsmodem.tlog/link.read.1.tlog
deleted file mode 100755
index 0513737..0000000
Binary files a/hsmodem/Release/hsmodem.tlog/link.read.1.tlog and /dev/null differ
diff --git a/hsmodem/Release/hsmodem.tlog/link.write.1.tlog b/hsmodem/Release/hsmodem.tlog/link.write.1.tlog
deleted file mode 100755
index 02829da..0000000
Binary files a/hsmodem/Release/hsmodem.tlog/link.write.1.tlog and /dev/null differ
diff --git a/hsmodem/Release/hsmodem.vcxproj.FileListAbsolute.txt b/hsmodem/Release/hsmodem.vcxproj.FileListAbsolute.txt
deleted file mode 100755
index e69de29..0000000
diff --git a/hsmodem/Release/liquid_if.obj b/hsmodem/Release/liquid_if.obj
deleted file mode 100755
index 24c40b9..0000000
Binary files a/hsmodem/Release/liquid_if.obj and /dev/null differ
diff --git a/hsmodem/Release/main_helper.obj b/hsmodem/Release/main_helper.obj
deleted file mode 100755
index abdc194..0000000
Binary files a/hsmodem/Release/main_helper.obj and /dev/null differ
diff --git a/hsmodem/Release/scrambler.obj b/hsmodem/Release/scrambler.obj
deleted file mode 100755
index 9454855..0000000
Binary files a/hsmodem/Release/scrambler.obj and /dev/null differ
diff --git a/hsmodem/Release/soundio.obj b/hsmodem/Release/soundio.obj
deleted file mode 100755
index 5fe8b4f..0000000
Binary files a/hsmodem/Release/soundio.obj and /dev/null differ
diff --git a/hsmodem/Release/speed.obj b/hsmodem/Release/speed.obj
deleted file mode 100755
index dce1202..0000000
Binary files a/hsmodem/Release/speed.obj and /dev/null differ
diff --git a/hsmodem/Release/symboltracker.obj b/hsmodem/Release/symboltracker.obj
deleted file mode 100755
index 0cf525a..0000000
Binary files a/hsmodem/Release/symboltracker.obj and /dev/null differ
diff --git a/hsmodem/Release/tuning.obj b/hsmodem/Release/tuning.obj
deleted file mode 100755
index 222443d..0000000
Binary files a/hsmodem/Release/tuning.obj and /dev/null differ
diff --git a/hsmodem/Release/udp.obj b/hsmodem/Release/udp.obj
deleted file mode 100755
index 3994531..0000000
Binary files a/hsmodem/Release/udp.obj and /dev/null differ
diff --git a/hsmodem/Release/vc140.pdb b/hsmodem/Release/vc140.pdb
deleted file mode 100755
index a3e3c8d..0000000
Binary files a/hsmodem/Release/vc140.pdb and /dev/null differ
diff --git a/hsmodem/Release/voiceio.obj b/hsmodem/Release/voiceio.obj
deleted file mode 100755
index 27326cb..0000000
Binary files a/hsmodem/Release/voiceio.obj and /dev/null differ
diff --git a/hsmodem/Release/voiceprocessor.obj b/hsmodem/Release/voiceprocessor.obj
deleted file mode 100755
index df245ce..0000000
Binary files a/hsmodem/Release/voiceprocessor.obj and /dev/null differ
diff --git a/hsmodem/fft.cpp b/hsmodem/fft.cpp
index d53aefa..ef1918b 100755
--- a/hsmodem/fft.cpp
+++ b/hsmodem/fft.cpp
@@ -153,8 +153,8 @@ uint16_t *make_waterfall(float fre, int *retlen)
}
// smooth fft output
-const int smoothX = 6; // must be an even number !
-const int smoothY = 3;
+const int smoothX = 2; // must be an even number !
+const int smoothY = 10;
int yidx = 0;
uint16_t* mean(uint16_t* f)
@@ -164,7 +164,7 @@ uint16_t* mean(uint16_t* f)
if (tuning)
return f;
-
+
// first smooth X values
for (int x = 0; x < smoothX / 2; x++)
fa[x] = f[x];
@@ -179,8 +179,9 @@ uint16_t* mean(uint16_t* f)
for (int x = fftcount - smoothX / 2; x < fftcount; x++)
fa[x] = f[x];
-
+
// smooth Y values
+
static uint16_t yarr[smoothY][FFT_AUDIOSAMPLERATE / 2 + 1];
for (int i = 0; i < fftcount; i++)
yarr[yidx][i] = fa[i];
@@ -194,10 +195,6 @@ uint16_t* mean(uint16_t* f)
fa[i] /= smoothY;
}
- // do not smooth 2950 to 3050 Hz
- for (int i = 295; i < 305; i++)
- fa[i] = f[i];
-
return fa;
}
@@ -216,7 +213,7 @@ void _init_fft()
// decimate 44.1k or 48k down to 8000Hz
// the FFT rate is 800, but we feed it with 8000 Samplerate
// this results in a new fft every 100ms with a resolution of 10 Hz
- float ratio = 10.0f * (float)FFT_AUDIOSAMPLERATE / (float)physcaprate;
+ float ratio = 10.0f * (float)FFT_AUDIOSAMPLERATE / (float)physRXcaprate;
fftdecim = msresamp_crcf_create(ratio, 40.0f);
}
diff --git a/hsmodem/hsmodem.cpp b/hsmodem/hsmodem.cpp
index e084475..806d484 100755
--- a/hsmodem/hsmodem.cpp
+++ b/hsmodem/hsmodem.cpp
@@ -68,7 +68,7 @@ int trigger_resetmodem = 0;
char homepath[1000] = { 0 };
int caprate = 44100;
-int physcaprate = 44100;
+int physRXcaprate = 44100;
int txinterpolfactor = 20;
int rxPreInterpolfactor = 5;
int linespeed = 4410;
@@ -87,7 +87,7 @@ int announcement = 0;
int VoiceAudioMode = VOICEMODE_OFF;
int codec = 1; // 0=opus, 1=codec2
int tuning = 0;
-int marker = 0;
+int marker = 1;
int init_audio_result = 0;
int init_voice_result = 0;
@@ -382,6 +382,8 @@ void bc_rxdata(uint8_t* pdata, int len, struct sockaddr_in* rxsock)
char rxip[20];
strcpy(rxip, inet_ntoa(rxsock->sin_addr));
+ //printf("GUI search received:%s\n",rxip);
+
if (fixappIP == 0)
{
if (strcmp(appIP, rxip))
@@ -391,13 +393,14 @@ void bc_rxdata(uint8_t* pdata, int len, struct sockaddr_in* rxsock)
// there was an appIP already
// before accepting this new one, wait 3 seconds
int ts = (int)(actms - lastms);
- printf("new app IP: %s since %d, restarting modems\n", rxip,ts);
+ //printf("new app IP: %s since %d, restarting modems\n", rxip,ts);
if (ts < 3000)
return;
}
- printf("first app IP: %s, restarting modems\n", rxip);
+ //printf("first app IP: %s, restarting modems\n", rxip);
restart_modems = 1;
}
+
strcpy(appIP, rxip);
//printf("app (%s) is searching modem. Sending modem IP to the app\n",appIP);
// App searches for the modem IP, mirror the received messages
@@ -569,8 +572,7 @@ void appdata_rxdata(uint8_t* pdata, int len, struct sockaddr_in* rxsock)
if (type == 27)
{
// send Tuning tones
- printf("Tuning mode active\n");
- VoiceAudioMode = VOICEMODE_OFF;
+ printf("Tuning mode active:%d\n",minfo);
tuning_runtime = 0;
tuning = minfo;
return;
@@ -583,6 +585,15 @@ void appdata_rxdata(uint8_t* pdata, int len, struct sockaddr_in* rxsock)
return;
}
+ if (type == 29)
+ {
+ int v = minfo;
+ if (v > 128)
+ v = v - 255;
+ modifyRXfreq(float(v));
+ return;
+ }
+
// here we are with payload data to be sent via the modulator
if (len != (PAYLOADLEN + 2))
diff --git a/hsmodem/hsmodem.h b/hsmodem/hsmodem.h
index eaf03e9..43744d6 100755
--- a/hsmodem/hsmodem.h
+++ b/hsmodem/hsmodem.h
@@ -206,6 +206,10 @@ 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 showbytestring16(char* title, uint16_t* data, int anz);
extern int speedmode;
@@ -240,7 +244,7 @@ extern int rxlevel_deteced;
extern int rx_in_sync;
extern float softwareMICvolume;
extern float softwareLSvolume;
-extern int physcaprate;
+extern int physRXcaprate;
extern int restart_modems;
extern int safemode;
extern char homepath[];
diff --git a/hsmodem/hsmodem.vcxproj b/hsmodem/hsmodem.vcxproj
index 8c992c6..ffff591 100755
--- a/hsmodem/hsmodem.vcxproj
+++ b/hsmodem/hsmodem.vcxproj
@@ -251,6 +251,7 @@
+
diff --git a/hsmodem/hsmodem.vcxproj.filters b/hsmodem/hsmodem.vcxproj.filters
index c4015bf..f1cf294 100755
--- a/hsmodem/hsmodem.vcxproj.filters
+++ b/hsmodem/hsmodem.vcxproj.filters
@@ -75,6 +75,9 @@
Source Files
+
+ Source Files
+
diff --git a/hsmodem/liquid_if.cpp b/hsmodem/liquid_if.cpp
index 3c0356d..a42c075 100755
--- a/hsmodem/liquid_if.cpp
+++ b/hsmodem/liquid_if.cpp
@@ -209,7 +209,7 @@ void modulator(uint8_t sym_in)
}
if(marker)
- usb += singleFrequency() / 10.0f;
+ usb += singleFrequency() / 4.0f;
io_pb_write_fifo(usb * 0.2f); // reduce volume and send to soundcard
}
@@ -221,6 +221,7 @@ nco_crcf dnnco = NULL;
symtrack_cccf symtrack = NULL;
firdecim_crcf decim = NULL;
msresamp_crcf adecim = NULL;
+msresamp_crcf lsresamp = NULL;
// decimator parameters
unsigned int m_predec = 8; // filter delay
@@ -240,16 +241,27 @@ float bandwidth_st = 0.9f; // loop filter bandwidth
uint8_t maxLevel = 0; // maximum RXlevel over the last x samples in %
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);
+}
+
void init_demodulator()
{
printf("init RX demodulator\n");
// downmixer oscillator
- float RADIANS_PER_SAMPLE = ((2.0f*(float)M_PI*(float)FREQUENCY)/(float)caprate);
+ radians_per_sample = ((2.0f*(float)M_PI*(float)FREQUENCY)/(float)caprate);
dnnco = nco_crcf_create(LIQUID_NCO);
nco_crcf_set_phase(dnnco, 0.0f);
- nco_crcf_set_frequency(dnnco, RADIANS_PER_SAMPLE);
+ nco_crcf_set_frequency(dnnco, radians_per_sample);
// create pre-decimator
decim = firdecim_crcf_create_kaiser(rxPreInterpolfactor, m_predec, As_predec);
@@ -259,6 +271,8 @@ void init_demodulator()
// if Audio SR is 48000 but caprate is 44100
r_OutDivInRatio = (float)((float)caprate / 48000.0);
adecim = msresamp_crcf_create(r_OutDivInRatio, As_adecim);
+
+ 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());
@@ -268,10 +282,15 @@ void init_demodulator()
void close_demodulator()
{
if(decim != NULL) firdecim_crcf_destroy(decim);
- if(adecim) msresamp_crcf_destroy(adecim);
- symtrack = NULL;
decim = NULL;
+ if(adecim) msresamp_crcf_destroy(adecim);
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;
}
void resetModem()
@@ -288,6 +307,33 @@ 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))
{
@@ -367,7 +413,29 @@ static int const_idx = 0;
if(ret == 0) return 0;
if (VoiceAudioMode == VOICEMODE_LISTENAUDIOIN)
- io_ls_write_fifo(f);
+ {
+ if (physRXcaprate == 44100)
+ {
+ // Loudspeaker Audio "ls" works only with 48k
+ // so we have to resample 44k1 to 48k
+ unsigned int num_written = 0;
+ liquid_float_complex in;
+ liquid_float_complex out[100];
+ in.real = f;
+ in.imag = 0;
+ msresamp_crcf_execute(lsresamp, &in, 1, out, &num_written);
+ if (num_written != 0)
+ {
+ for (unsigned int i = 0; i < num_written; i++)
+ {
+ float fout = out[i].real;
+ io_ls_write_fifo(fout);
+ }
+ }
+ }
+ else
+ io_ls_write_fifo(f);
+ }
// input volume
f *= softwareCAPvolume;
@@ -375,7 +443,7 @@ static int const_idx = 0;
getMax(f);
make_FFTdata(f * 100);
- if (caprate == 44100 && physcaprate == 48000)
+ if (caprate == 44100 && physRXcaprate == 48000)
{
// the sound card capture for a VAC always works with 48000 because
// a VAC cannot be set to a specific cap rate in shared mode
@@ -389,7 +457,15 @@ static int const_idx = 0;
if (num_written == 0) return 1;
f = out.real;
}
-
+
+ // if user changed frequency
+ if (radians_per_sample != last_radians_per_sample)
+ {
+ //printf("new QRG. Rad:%f\n", radians_per_sample);
+ nco_crcf_set_frequency(dnnco, radians_per_sample);
+ last_radians_per_sample = radians_per_sample;
+ }
+
// downconvert 1,5kHz into baseband, still at soundcard sample rate
nco_crcf_step(dnnco);
diff --git a/hsmodem/rtty.cpp b/hsmodem/rtty.cpp
new file mode 100755
index 0000000..8f5f443
--- /dev/null
+++ b/hsmodem/rtty.cpp
@@ -0,0 +1,262 @@
+/*
+* High Speed modem to transfer data in a 2,7kHz SSB channel
+* =========================================================
+* Author: DJ0ABR
+*
+* (c) DJ0ABR
+* www.dj0abr.de
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*
+* RTTY:
+* =====
+* bit/symbol: 1
+* BW: 170 Hz
+* carrier: 1500 Hz
+* speed: 45.45 bits/s
+* samples/symbol: 33
+*/
+
+#include "hsmodem.h"
+
+#define rtty_CENTERFREQUENCY 1500
+
+fskmod rtty_mod = NULL;
+fskdem rtty_dem = NULL;
+
+unsigned int rtty_m = 1; // bits/symbol
+const unsigned int rtty_k = 33; // samples/symbol (periods of the 1500 Hz Carrier in one symbol)
+float rtty_bandwith = (170.0f/2)/ (float)rtty_CENTERFREQUENCY; // 170 Hz spacing normalized to 1500 Hz
+
+firinterp_crcf rtty_TX_interpolator = NULL;
+unsigned int rtty_k_SampPerSymb = 20; // 44100 / (4410/2)
+unsigned int rtty_m_filterDelay_Symbols = 15; // not too short for good filter
+float rtty_beta_excessBW = 0.2f; // filter excess bandwidth factor
+float rtty_tau_FracSymbOffset = -0.2f; // fractional symbol offset
+
+nco_crcf rtty_upnco = NULL;
+nco_crcf rtty_dnnco = NULL;
+
+firdecim_crcf rtty_decim = NULL;
+unsigned int rtty_m_predec = 8; // filter delay
+float rtty_As_predec = 40.0f; // stop-band att
+
+void close_rtty();
+
+void init_rtty()
+{
+ close_rtty();
+
+ 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;
+
+ // 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)
+ {
+ 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);
+ 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);
+ 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);
+
+ 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);
+
+ 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);
+}
+
+void close_rtty()
+{
+ 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;
+}
+
+char text[6] = {"ABCD\n"};
+int tidx = 0;
+int bitidx = 1;
+
+void rtty_tx()
+{
+ if (rtty_mod == NULL)
+ init_rtty();
+
+ unsigned int sym = (text[tidx] & bitidx) ? 1 : 0;
+ bitidx <<= 1;
+ if (bitidx == 0x0100)
+ {
+ bitidx = 1;
+ tidx++;
+ if (tidx == 6) tidx = 0;
+ }
+
+ liquid_float_complex rtty_txbuf[33+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++)
+ {
+ // 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;
+ }
+
+ 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);
+
+ liquid_float_complex c;
+ nco_crcf_mix_up(rtty_upnco, y[i], &c);
+ float usb = c.real + c.imag;
+
+ // 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
+ }
+ }
+}
+
+// RTTY: sample rate HAS TO BE 48000
+int rtty_rx()
+{
+ static liquid_float_complex ccol[500];
+ static unsigned int ccol_idx = 0;
+
+ if (rtty_dnnco == NULL) return 0;
+
+ // get one received sample
+ float f;
+ int ret = io_cap_read_fifo(&f);
+ if (ret == 0) return 0;
+
+ if (VoiceAudioMode == VOICEMODE_LISTENAUDIOIN)
+ io_ls_write_fifo(f);
+
+ // input volume
+ f *= softwareCAPvolume;
+
+ //getMax(f);
+ //make_FFTdata(f * 100);
+
+ // downconvert 1,5kHz into baseband, still at soundcard sample rate
+ nco_crcf_step(rtty_dnnco);
+
+ 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)
+ {
+ symidx = 0;
+ printf("%d: %c\n", sym, sym);
+ sym = 0;
+ }
+
+ return 1;
+}
diff --git a/hsmodem/soundio.cpp b/hsmodem/soundio.cpp
index 0df6f2e..c3839a0 100755
--- a/hsmodem/soundio.cpp
+++ b/hsmodem/soundio.cpp
@@ -522,14 +522,14 @@ int io_init_sound(char *pbname, char *capname)
{
instream->format = SoundIoFormatS16NE;
instream->sample_rate = caprate;
- physcaprate = caprate;
+ physRXcaprate = caprate;
}
else
{
// a VAC needs these settings or it will not work with 44100
instream->format = SoundIoFormatFloat32NE;
instream->sample_rate = AUDIO_SAMPRATE;
- physcaprate = AUDIO_SAMPRATE;
+ physRXcaprate = AUDIO_SAMPRATE;
}
instream->software_latency = latenz;
instream->read_callback = read_callback;
@@ -548,7 +548,7 @@ int io_init_sound(char *pbname, char *capname)
init_audio_result |= 2;
printf("selected CAPTURE device:\nname:%s\nid :%s\n", capname, capdevid);
- printf("physical capture rate:%d, logical capture rate:%d\n", physcaprate, caprate);
+ printf("physical capture rate:%d, logical capture rate:%d\n", physRXcaprate, caprate);
printf("format: %s\n\n", soundio_format_string(instream->format));
// the CAP callback is running now
diff --git a/hsmodem/speed.cpp b/hsmodem/speed.cpp
index 3bf40f6..94bd0a0 100755
--- a/hsmodem/speed.cpp
+++ b/hsmodem/speed.cpp
@@ -157,13 +157,12 @@ void measure_speed_bps(int len)
return;
}
-
elems += len;
if (timespan < 1000) return;
double dspd = elems;
dspd = dspd * 1e3 / timespan;
- speed = meanvalbps((int)dspd);
+ speed = (int)dspd;
// here we have number of elements after 1s
printf(" ======================= %d bit/s\n", speed);
diff --git a/hsmodem/symboltracker.cpp b/hsmodem/symboltracker.cpp
index 93d6d1c..41bd425 100755
--- a/hsmodem/symboltracker.cpp
+++ b/hsmodem/symboltracker.cpp
@@ -166,8 +166,7 @@ void km_symtrack_execute(liquid_float_complex _x, liquid_float_complex* _y, unsi
/*float fr = nco_crcf_get_frequency(q->nco);
float ph = nco_crcf_get_phase(q->nco);
-
- printf("%10.6f %10.6f %10.6f %10.6f\n", fr, ph, _x.real, _x.imag);*/
+ printf("f:%10.6f ph:%10.6f\n", fr, ph);*/
* _ny = num_outputs;
}
diff --git a/hsmodem/tuning.cpp b/hsmodem/tuning.cpp
index 9d48137..5580d31 100755
--- a/hsmodem/tuning.cpp
+++ b/hsmodem/tuning.cpp
@@ -26,11 +26,8 @@
#include "hsmodem.h"
-
-
-
-#define NUMFREQ 12
-int tunefreq[NUMFREQ] = { 150,420,690,960,1230,1500,1770,2040,2310,2580,2850,3000 };
+#define NUMFREQ 13
+int tunefreq[NUMFREQ] = { 150,420,690,960,1230,1500,1770,2040,2310,2580,2850,2890,100 };
nco_crcf tunenco[NUMFREQ];
uint32_t tuning_runtime = 0;
@@ -49,7 +46,6 @@ void init_tune()
if (tunenco[i] != NULL) nco_crcf_destroy(tunenco[i]);
// create NCO for frequency
- printf("tuning: physcaprate:%d\n", physcaprate);
float rad_per_sample = ((2.0f * (float)M_PI * (float)tunefreq[i]) / (float)caprate);
tunenco[i] = nco_crcf_create(LIQUID_NCO);
nco_crcf_set_phase(tunenco[i], 0.0f);
@@ -62,7 +58,7 @@ void init_tune()
float do_tuning(int send)
{
if (tunenco == NULL) return 0.0f;
- if (send < 0 || send > 4) return 0.0f;
+ if (send < 0 || send > 11) return 0.0f;
float f = 0;
if (send == 1)
@@ -77,8 +73,8 @@ float do_tuning(int send)
}
else
{
- nco_crcf_step(tunenco[send-2]);
- f = nco_crcf_sin(tunenco[send-2]);
+ nco_crcf_step(tunenco[send]);
+ f = nco_crcf_sin(tunenco[send]);
}
// adapt speed to soundcard samplerate
@@ -104,10 +100,15 @@ float do_tuning(int send)
float singleFrequency()
{
- int i = 11; // 3000 Hz
-
+ int /*i = 11; // 2900 Hz
if (tunenco[i] == NULL) return 0.0f;
-
nco_crcf_step(tunenco[i]);
- return nco_crcf_sin(tunenco[i]);
+ float f = nco_crcf_sin(tunenco[i]);*/
+
+ i = 12; // 2930 Hz
+ if (tunenco[i] == NULL) return 0.0f;
+ nco_crcf_step(tunenco[i]);
+ float f = nco_crcf_sin(tunenco[i]);
+
+ return f;
}
diff --git a/hsmodemLinux/hsmodem b/hsmodemLinux/hsmodem
index 1bb6492..c1ed2a1 100755
Binary files a/hsmodemLinux/hsmodem and b/hsmodemLinux/hsmodem differ
diff --git a/hsmodemLinux/oscardata.exe b/hsmodemLinux/oscardata.exe
index 706dd5f..2568aac 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 ad688c5..3747193 100755
--- a/oscardata/oscardata/Form1.Designer.cs
+++ b/oscardata/oscardata/Form1.Designer.cs
@@ -109,6 +109,11 @@
this.bt_resetmodem = new System.Windows.Forms.Button();
this.textBox3 = new System.Windows.Forms.TextBox();
this.groupBox3 = new System.Windows.Forms.GroupBox();
+ this.pictureBox4 = new System.Windows.Forms.PictureBox();
+ this.pictureBox3 = new System.Windows.Forms.PictureBox();
+ this.bt_tune_plus = new System.Windows.Forms.Button();
+ this.bt_tune_minus = new System.Windows.Forms.Button();
+ this.cb_marker = new System.Windows.Forms.CheckBox();
this.pb_audioCAPstatus = new System.Windows.Forms.PictureBox();
this.pb_audioPBstatus = new System.Windows.Forms.PictureBox();
this.label6 = new System.Windows.Forms.Label();
@@ -116,9 +121,7 @@
this.tb_CAPvol = new System.Windows.Forms.TrackBar();
this.tb_PBvol = new System.Windows.Forms.TrackBar();
this.cb_audioPB = new System.Windows.Forms.ComboBox();
- this.label3 = new System.Windows.Forms.Label();
this.cb_audioCAP = new System.Windows.Forms.ComboBox();
- this.label4 = new System.Windows.Forms.Label();
this.groupBox2 = new System.Windows.Forms.GroupBox();
this.lb_rec = new System.Windows.Forms.Label();
this.tb_recintro = new System.Windows.Forms.TextBox();
@@ -151,7 +154,6 @@
this.progressBar_fifo = new oscardata.KmProgressBar();
this.vu_cap = new oscardata.KmProgressBar();
this.vu_pb = new oscardata.KmProgressBar();
- this.cb_marker = new System.Windows.Forms.CheckBox();
this.statusStrip1.SuspendLayout();
this.tabPage_ber.SuspendLayout();
this.tabPage_image.SuspendLayout();
@@ -174,6 +176,8 @@
this.tabPage_setup.SuspendLayout();
this.groupBox4.SuspendLayout();
this.groupBox3.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.pictureBox4)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.pictureBox3)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.pb_audioCAPstatus)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.pb_audioPBstatus)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.tb_CAPvol)).BeginInit();
@@ -274,11 +278,11 @@
//
// bt_allf
//
- this.bt_allf.Location = new System.Drawing.Point(537, 18);
+ this.bt_allf.Location = new System.Drawing.Point(561, 18);
this.bt_allf.Name = "bt_allf";
- this.bt_allf.Size = new System.Drawing.Size(95, 23);
+ this.bt_allf.Size = new System.Drawing.Size(71, 23);
this.bt_allf.TabIndex = 25;
- this.bt_allf.Text = "150..2850 Hz";
+ this.bt_allf.Text = "1500 Hz";
this.bt_allf.UseVisualStyleBackColor = true;
this.bt_allf.Click += new System.EventHandler(this.bt_allf_Click);
//
@@ -987,11 +991,11 @@
// label12
//
this.label12.AutoSize = true;
- this.label12.Location = new System.Drawing.Point(253, 23);
+ this.label12.Location = new System.Drawing.Point(221, 23);
this.label12.Name = "label12";
- this.label12.Size = new System.Drawing.Size(54, 13);
+ this.label12.Size = new System.Drawing.Size(103, 13);
this.label12.TabIndex = 26;
- this.label12.Text = "language:";
+ this.label12.Text = "Language/Sprache:";
//
// cb_safemode
//
@@ -1081,6 +1085,10 @@
//
// groupBox3
//
+ this.groupBox3.Controls.Add(this.pictureBox4);
+ this.groupBox3.Controls.Add(this.pictureBox3);
+ this.groupBox3.Controls.Add(this.bt_tune_plus);
+ this.groupBox3.Controls.Add(this.bt_tune_minus);
this.groupBox3.Controls.Add(this.cb_marker);
this.groupBox3.Controls.Add(this.vu_cap);
this.groupBox3.Controls.Add(this.vu_pb);
@@ -1091,9 +1099,7 @@
this.groupBox3.Controls.Add(this.tb_CAPvol);
this.groupBox3.Controls.Add(this.tb_PBvol);
this.groupBox3.Controls.Add(this.cb_audioPB);
- this.groupBox3.Controls.Add(this.label3);
this.groupBox3.Controls.Add(this.cb_audioCAP);
- this.groupBox3.Controls.Add(this.label4);
this.groupBox3.Location = new System.Drawing.Point(12, 144);
this.groupBox3.Name = "groupBox3";
this.groupBox3.Size = new System.Drawing.Size(743, 163);
@@ -1101,11 +1107,70 @@
this.groupBox3.TabStop = false;
this.groupBox3.Text = "Transceiver Audio";
//
+ // pictureBox4
+ //
+ this.pictureBox4.BackgroundImage = global::oscardata.Properties.Resources.captureicon;
+ this.pictureBox4.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom;
+ this.pictureBox4.Location = new System.Drawing.Point(0, 61);
+ this.pictureBox4.Name = "pictureBox4";
+ this.pictureBox4.Size = new System.Drawing.Size(132, 87);
+ this.pictureBox4.TabIndex = 16;
+ this.pictureBox4.TabStop = false;
+ //
+ // pictureBox3
+ //
+ this.pictureBox3.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("pictureBox3.BackgroundImage")));
+ this.pictureBox3.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom;
+ this.pictureBox3.Location = new System.Drawing.Point(5, -7);
+ this.pictureBox3.Name = "pictureBox3";
+ this.pictureBox3.Size = new System.Drawing.Size(127, 85);
+ this.pictureBox3.TabIndex = 16;
+ this.pictureBox3.TabStop = false;
+ //
+ // bt_tune_plus
+ //
+ this.bt_tune_plus.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.bt_tune_plus.Location = new System.Drawing.Point(602, 79);
+ this.bt_tune_plus.Name = "bt_tune_plus";
+ this.bt_tune_plus.Size = new System.Drawing.Size(24, 23);
+ this.bt_tune_plus.TabIndex = 22;
+ this.bt_tune_plus.Text = "+";
+ this.bt_tune_plus.UseVisualStyleBackColor = true;
+ this.bt_tune_plus.Visible = false;
+ this.bt_tune_plus.Click += new System.EventHandler(this.bt_tune_plus_Click);
+ //
+ // bt_tune_minus
+ //
+ this.bt_tune_minus.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.bt_tune_minus.Location = new System.Drawing.Point(602, 55);
+ this.bt_tune_minus.Name = "bt_tune_minus";
+ this.bt_tune_minus.Size = new System.Drawing.Size(24, 23);
+ this.bt_tune_minus.TabIndex = 21;
+ this.bt_tune_minus.Text = "-";
+ this.bt_tune_minus.UseVisualStyleBackColor = true;
+ this.bt_tune_minus.Visible = false;
+ this.bt_tune_minus.Click += new System.EventHandler(this.bt_tune_minus_Click);
+ //
+ // cb_marker
+ //
+ this.cb_marker.AutoSize = true;
+ this.cb_marker.Checked = true;
+ this.cb_marker.CheckState = System.Windows.Forms.CheckState.Checked;
+ this.cb_marker.Location = new System.Drawing.Point(605, 23);
+ this.cb_marker.Name = "cb_marker";
+ this.cb_marker.RightToLeft = System.Windows.Forms.RightToLeft.No;
+ this.cb_marker.Size = new System.Drawing.Size(129, 17);
+ this.cb_marker.TabIndex = 27;
+ this.cb_marker.Text = "100Hz Tuning Marker";
+ this.cb_marker.UseVisualStyleBackColor = true;
+ this.cb_marker.Visible = false;
+ this.cb_marker.CheckedChanged += new System.EventHandler(this.cb_marker_CheckedChanged);
+ //
// pb_audioCAPstatus
//
this.pb_audioCAPstatus.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("pb_audioCAPstatus.BackgroundImage")));
this.pb_audioCAPstatus.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom;
- this.pb_audioCAPstatus.Location = new System.Drawing.Point(375, 63);
+ this.pb_audioCAPstatus.Location = new System.Drawing.Point(375, 87);
this.pb_audioCAPstatus.Name = "pb_audioCAPstatus";
this.pb_audioCAPstatus.Size = new System.Drawing.Size(21, 21);
this.pb_audioCAPstatus.TabIndex = 18;
@@ -1115,7 +1180,7 @@
//
this.pb_audioPBstatus.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("pb_audioPBstatus.BackgroundImage")));
this.pb_audioPBstatus.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom;
- this.pb_audioPBstatus.Location = new System.Drawing.Point(375, 19);
+ this.pb_audioPBstatus.Location = new System.Drawing.Point(375, 21);
this.pb_audioPBstatus.Name = "pb_audioPBstatus";
this.pb_audioPBstatus.Size = new System.Drawing.Size(21, 21);
this.pb_audioPBstatus.TabIndex = 17;
@@ -1124,7 +1189,7 @@
// label6
//
this.label6.AutoSize = true;
- this.label6.Location = new System.Drawing.Point(428, 65);
+ this.label6.Location = new System.Drawing.Point(428, 89);
this.label6.Name = "label6";
this.label6.Size = new System.Drawing.Size(45, 13);
this.label6.TabIndex = 16;
@@ -1133,7 +1198,7 @@
// label5
//
this.label5.AutoSize = true;
- this.label5.Location = new System.Drawing.Point(428, 23);
+ this.label5.Location = new System.Drawing.Point(428, 25);
this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(45, 13);
this.label5.TabIndex = 15;
@@ -1142,7 +1207,7 @@
// tb_CAPvol
//
this.tb_CAPvol.Cursor = System.Windows.Forms.Cursors.SizeAll;
- this.tb_CAPvol.Location = new System.Drawing.Point(479, 61);
+ this.tb_CAPvol.Location = new System.Drawing.Point(479, 85);
this.tb_CAPvol.Maximum = 100;
this.tb_CAPvol.MaximumSize = new System.Drawing.Size(0, 24);
this.tb_CAPvol.Minimum = 1;
@@ -1157,7 +1222,7 @@
// tb_PBvol
//
this.tb_PBvol.Cursor = System.Windows.Forms.Cursors.SizeAll;
- this.tb_PBvol.Location = new System.Drawing.Point(479, 19);
+ this.tb_PBvol.Location = new System.Drawing.Point(479, 21);
this.tb_PBvol.Maximum = 100;
this.tb_PBvol.MaximumSize = new System.Drawing.Size(0, 24);
this.tb_PBvol.Minimum = 1;
@@ -1172,39 +1237,21 @@
// cb_audioPB
//
this.cb_audioPB.FormattingEnabled = true;
- this.cb_audioPB.Location = new System.Drawing.Point(138, 19);
+ this.cb_audioPB.Location = new System.Drawing.Point(138, 21);
this.cb_audioPB.Name = "cb_audioPB";
this.cb_audioPB.Size = new System.Drawing.Size(230, 21);
this.cb_audioPB.TabIndex = 7;
this.cb_audioPB.Text = "Default";
//
- // label3
- //
- this.label3.AutoSize = true;
- this.label3.Location = new System.Drawing.Point(12, 23);
- this.label3.Name = "label3";
- this.label3.Size = new System.Drawing.Size(121, 13);
- this.label3.TabIndex = 8;
- this.label3.Text = "Audio Playback Device:";
- //
// cb_audioCAP
//
this.cb_audioCAP.FormattingEnabled = true;
- this.cb_audioCAP.Location = new System.Drawing.Point(138, 63);
+ this.cb_audioCAP.Location = new System.Drawing.Point(138, 87);
this.cb_audioCAP.Name = "cb_audioCAP";
this.cb_audioCAP.Size = new System.Drawing.Size(230, 21);
this.cb_audioCAP.TabIndex = 9;
this.cb_audioCAP.Text = "Default";
//
- // label4
- //
- this.label4.AutoSize = true;
- this.label4.Location = new System.Drawing.Point(12, 67);
- this.label4.Name = "label4";
- this.label4.Size = new System.Drawing.Size(112, 13);
- this.label4.TabIndex = 10;
- this.label4.Text = "Audio Record Device:";
- //
// groupBox2
//
this.groupBox2.Controls.Add(this.lb_rec);
@@ -1224,7 +1271,7 @@
this.groupBox2.Controls.Add(this.cb_stampcall);
this.groupBox2.Location = new System.Drawing.Point(12, 13);
this.groupBox2.Name = "groupBox2";
- this.groupBox2.Size = new System.Drawing.Size(734, 127);
+ this.groupBox2.Size = new System.Drawing.Size(743, 127);
this.groupBox2.TabIndex = 13;
this.groupBox2.TabStop = false;
this.groupBox2.Text = "Personal Settings";
@@ -1234,7 +1281,7 @@
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(498, 101);
+ this.lb_rec.Location = new System.Drawing.Point(576, 101);
this.lb_rec.Name = "lb_rec";
this.lb_rec.Size = new System.Drawing.Size(23, 13);
this.lb_rec.TabIndex = 29;
@@ -1246,7 +1293,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(256, 100);
+ this.tb_recintro.Location = new System.Drawing.Point(334, 100);
this.tb_recintro.Multiline = true;
this.tb_recintro.Name = "tb_recintro";
this.tb_recintro.Size = new System.Drawing.Size(121, 19);
@@ -1259,7 +1306,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(449, 89);
+ this.bt_astop.Location = new System.Drawing.Point(527, 89);
this.bt_astop.Name = "bt_astop";
this.bt_astop.Size = new System.Drawing.Size(32, 36);
this.bt_astop.TabIndex = 27;
@@ -1272,7 +1319,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(411, 89);
+ this.bt_aplay.Location = new System.Drawing.Point(489, 89);
this.bt_aplay.Name = "bt_aplay";
this.bt_aplay.Size = new System.Drawing.Size(32, 36);
this.bt_aplay.TabIndex = 26;
@@ -1285,7 +1332,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(373, 89);
+ this.bt_arecord.Location = new System.Drawing.Point(451, 89);
this.bt_arecord.Name = "bt_arecord";
this.bt_arecord.Size = new System.Drawing.Size(32, 36);
this.bt_arecord.TabIndex = 25;
@@ -1504,7 +1551,7 @@
// lb_rxsync
//
this.lb_rxsync.AutoSize = true;
- this.lb_rxsync.Location = new System.Drawing.Point(1094, 643);
+ this.lb_rxsync.Location = new System.Drawing.Point(984, 596);
this.lb_rxsync.Name = "lb_rxsync";
this.lb_rxsync.Size = new System.Drawing.Size(52, 13);
this.lb_rxsync.TabIndex = 20;
@@ -1514,7 +1561,7 @@
//
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(1155, 636);
+ 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;
@@ -1553,30 +1600,18 @@
//
// vu_cap
//
- this.vu_cap.Location = new System.Drawing.Point(479, 87);
+ this.vu_cap.Location = new System.Drawing.Point(479, 111);
this.vu_cap.Name = "vu_cap";
this.vu_cap.Size = new System.Drawing.Size(100, 10);
this.vu_cap.TabIndex = 20;
//
// vu_pb
//
- this.vu_pb.Location = new System.Drawing.Point(479, 45);
+ this.vu_pb.Location = new System.Drawing.Point(479, 47);
this.vu_pb.Name = "vu_pb";
this.vu_pb.Size = new System.Drawing.Size(100, 10);
this.vu_pb.TabIndex = 19;
//
- // cb_marker
- //
- this.cb_marker.AutoSize = true;
- this.cb_marker.Location = new System.Drawing.Point(605, 21);
- this.cb_marker.Name = "cb_marker";
- this.cb_marker.RightToLeft = System.Windows.Forms.RightToLeft.No;
- this.cb_marker.Size = new System.Drawing.Size(123, 17);
- this.cb_marker.TabIndex = 27;
- this.cb_marker.Text = "3kHz Tuning Marker";
- this.cb_marker.UseVisualStyleBackColor = true;
- this.cb_marker.CheckedChanged += new System.EventHandler(this.cb_marker_CheckedChanged);
- //
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@@ -1601,7 +1636,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.55 by DJ0ABR";
+ this.Text = "AMSAT-DL Multimedia HS Modem V0.56 by DJ0ABR";
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.Form1_FormClosing);
this.statusStrip1.ResumeLayout(false);
this.statusStrip1.PerformLayout();
@@ -1635,6 +1670,8 @@
this.groupBox4.PerformLayout();
this.groupBox3.ResumeLayout(false);
this.groupBox3.PerformLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.pictureBox4)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.pictureBox3)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.pb_audioCAPstatus)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.pb_audioPBstatus)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.tb_CAPvol)).EndInit();
@@ -1700,9 +1737,7 @@
private System.Windows.Forms.TextBox tb_shutdown;
private System.Windows.Forms.Button bt_shutdown;
private System.Windows.Forms.Button bt_resetmodem;
- private System.Windows.Forms.Label label4;
private System.Windows.Forms.ComboBox cb_audioCAP;
- private System.Windows.Forms.Label label3;
private System.Windows.Forms.ComboBox cb_audioPB;
private System.Windows.Forms.GroupBox groupBox4;
private System.Windows.Forms.GroupBox groupBox3;
@@ -1773,6 +1808,10 @@
private System.Windows.Forms.Label lb_tuningqrgs;
private System.Windows.Forms.Button bt_allf;
private System.Windows.Forms.CheckBox cb_marker;
+ private System.Windows.Forms.PictureBox pictureBox3;
+ private System.Windows.Forms.PictureBox pictureBox4;
+ private System.Windows.Forms.Button bt_tune_minus;
+ private System.Windows.Forms.Button bt_tune_plus;
}
}
diff --git a/oscardata/oscardata/Form1.cs b/oscardata/oscardata/Form1.cs
index 651318a..ac2f82a 100755
--- a/oscardata/oscardata/Form1.cs
+++ b/oscardata/oscardata/Form1.cs
@@ -1100,10 +1100,15 @@ namespace oscardata
String ip = "255.255.255.255";
String[] myips = statics.getOwnIPs();
//Console.WriteLine("BClen: " + myips.Length.ToString());
- // nur wenn der PC eine IP hat
- // hat er mehr, dann wissen wir nicht in welchem Netz wird broadcasten sollen, nehmen also die 255.255.255.255
- if (myips.Length == 1)
+ // if PC has multiple IPs then use 255.255.255.255
+ /*for (int i = 0; i < myips.Length; i++)
{
+ Console.WriteLine("ip:" + myips[i]);
+ }*/
+ if (myips.Length >= 1)
+ {
+ statics.MyIP = myips[0];
+ // PC has one IP, make it to a broadcast IP by adding 255
int idx = myips[0].LastIndexOf('.');
if (idx >= 0)
{
@@ -1173,11 +1178,22 @@ namespace oscardata
txb[i + 110] = bcap[i];
}
- Udp.UdpBCsend(txb, GetMyBroadcastIP(), statics.UdpBCport_AppToModem);
+ if (statics.ModemIP == "1.2.3.4")
+ {
+ // still searching a modem
+ //Console.WriteLine("1: send BCsearch to: " + GetMyBroadcastIP());
+ Udp.UdpBCsend(txb, GetMyBroadcastIP(), statics.UdpBCport_AppToModem);
+ }
+ else
+ {
+ // modem IP is known, send to it directly, no broadcast
+ //Console.WriteLine("2: send BCsearch to: " + statics.ModemIP);
+ Udp.UdpBCsend(txb, statics.ModemIP, statics.UdpBCport_AppToModem);
+ }
Udp.searchtimeout++;
if (Udp.searchtimeout >= 3)
- statics.ModemIP = "1.2.3.4";
+ statics.ModemIP = "1.2.3.4"; // which means: no IP known
}
private void bt_file_send_Click(object sender, EventArgs e)
@@ -1229,7 +1245,9 @@ namespace oscardata
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
+ bool b = cb_switchtoLS.Checked;
allVoiceModesOff();
+ cb_switchtoLS.Checked = b;
if (cb_speed.Text.Contains("3000")) statics.real_datarate = 3000;
if (cb_speed.Text.Contains("4000")) statics.real_datarate = 4000;
@@ -1388,6 +1406,14 @@ namespace oscardata
if (cb_audioPB.Text.Length <= 1) cb_audioPB.Text = "Default";
if (cb_audioCAP.Text.Length <= 1) cb_audioCAP.Text = "Default";
+
+ if (tb_callsign.Text == "DJ0ABR")
+ {
+ bt_resetmodem.Visible = true;
+ bt_tune_minus.Visible = true;
+ bt_tune_plus.Visible = true;
+ cb_marker.Visible = true;
+ }
}
void save_Setup()
@@ -1727,8 +1753,6 @@ namespace oscardata
groupBox3.Text = "Transceiver Audio";
label6.Text = "Volume:";
label5.Text = "Volume:";
- label3.Text = "Audio Playback Device:";
- label4.Text = "Audio Record Device:";
groupBox2.Text = "Personal Settings";
cb_stampinfo.Text = "Insert Info into picture";
textBox4.Text = "transmissions";
@@ -1742,10 +1766,11 @@ namespace oscardata
label_capfifo.Text = "RX Buffer:";
lb_rxsignal.Text = "RX Signal:";
lb_rxsync.Text = "RX Sync:";
- cb_sendIntro.Text = "send introduction";
+ cb_sendIntro.Text = "send introduction before TX";
tb_recintro.Text = "record introduction";
- lb_tuningqrgs.Text = "Frequency Test";
- cb_marker.Text = "3kHz Tuning Marker";
+ lb_tuningqrgs.Text = "Send Mid-Frequency:";
+ cb_marker.Text = "2.9kHz Tuning Marker";
+ label13.Text = "Data Security:";
}
if (language == 1)
@@ -1793,17 +1818,16 @@ namespace oscardata
cb_stampinfo.Text = "Füge Infotext ins Bild ein";
textBox1.Text = "sende Ansagetext vor TX, alle";
textBox4.Text = "Aussendungen";
- label3.Text = "Audio Wiedergabe";
- label4.Text = "Audio Eingang";
label5.Text = "Lautst.:";
label6.Text = "Lautst.:";
groupBox4.Text = "Wartung";
textBox3.Text = "Ausschalten wenn hsmodem auf separatem PC läuft";
tb_shutdown.Text = "Vor dem Ausschalten eines SBC diesen hier herunterfahren";
- cb_sendIntro.Text = "sende Vorstellung";
+ cb_sendIntro.Text = "sende Vorstellung vor TX";
tb_recintro.Text = "Vorstellung aufnehmen";
- lb_tuningqrgs.Text = "Frequenz Test:";
- cb_marker.Text = "3kHz Tuning Markierung";
+ lb_tuningqrgs.Text = "Sende Mittenfrequenz:";
+ cb_marker.Text = "2,9kHz Tuning Markierung";
+ label13.Text = "Datensicherheit:";
}
}
@@ -1936,7 +1960,7 @@ namespace oscardata
private void bt_allf_Click(object sender, EventArgs e)
{
- bt_tuning(1);
+ bt_tuning(5);
}
private void cb_marker_CheckedChanged(object sender, EventArgs e)
@@ -1946,6 +1970,22 @@ namespace oscardata
txdata[1] = (Byte)(cb_marker.Checked ? 1 : 0);
Udp.UdpSendCtrl(txdata);
}
+
+ private void bt_tune_minus_Click(object sender, EventArgs e)
+ {
+ Byte[] txdata = new byte[2];
+ txdata[0] = statics.setfreq;
+ txdata[1] = 10;
+ Udp.UdpSendCtrl(txdata);
+ }
+
+ private void bt_tune_plus_Click(object sender, EventArgs e)
+ {
+ Byte[] txdata = new byte[2];
+ txdata[0] = statics.setfreq;
+ txdata[1] = 255 - 10;
+ Udp.UdpSendCtrl(txdata);
+ }
}
}
diff --git a/oscardata/oscardata/Form1.resx b/oscardata/oscardata/Form1.resx
index 43c08c7..ddd53e9 100755
--- a/oscardata/oscardata/Form1.resx
+++ b/oscardata/oscardata/Form1.resx
@@ -137,7 +137,7 @@
AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w
LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAABw
- FwAAAk1TRnQBSQFMAgEBDQEAAQgBBQEIAQUBEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo
+ FwAAAk1TRnQBSQFMAgEBDQEAAUABBgFAAQYBEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo
AwABQAMAAUADAAEBAQABCAYAARAYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA
AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5
AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA
@@ -4495,6 +4495,344 @@
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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==
@@ -4874,42 +5212,6 @@
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==
-
-
-
-
- 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==
diff --git a/oscardata/oscardata/Properties/Resources.Designer.cs b/oscardata/oscardata/Properties/Resources.Designer.cs
index c5dd736..aa88aeb 100755
--- a/oscardata/oscardata/Properties/Resources.Designer.cs
+++ b/oscardata/oscardata/Properties/Resources.Designer.cs
@@ -80,6 +80,16 @@ namespace oscardata.Properties {
}
}
+ ///
+ /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap captureicon {
+ get {
+ object obj = ResourceManager.GetObject("captureicon", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
///
/// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
///
@@ -250,6 +260,16 @@ namespace oscardata.Properties {
}
}
+ ///
+ /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap playbackicon {
+ get {
+ object obj = ResourceManager.GetObject("playbackicon", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
///
/// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
///
diff --git a/oscardata/oscardata/Properties/Resources.resx b/oscardata/oscardata/Properties/Resources.resx
index 8d6411a..a88624c 100755
--- a/oscardata/oscardata/Properties/Resources.resx
+++ b/oscardata/oscardata/Properties/Resources.resx
@@ -226,4 +226,10 @@
stopplay.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+ captureicon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ playbackicon.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/captureicon.png b/oscardata/oscardata/Properties/captureicon.png
new file mode 100644
index 0000000..ed3d1c7
Binary files /dev/null and b/oscardata/oscardata/Properties/captureicon.png differ
diff --git a/oscardata/oscardata/Properties/playbackicon.png b/oscardata/oscardata/Properties/playbackicon.png
new file mode 100644
index 0000000..5079aa1
Binary files /dev/null and b/oscardata/oscardata/Properties/playbackicon.png differ
diff --git a/oscardata/oscardata/bin/Release/oscardata.exe b/oscardata/oscardata/bin/Release/oscardata.exe
index 82afc41..28bc9e3 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 7cf7d05..275d8e0 100755
--- a/oscardata/oscardata/config.cs
+++ b/oscardata/oscardata/config.cs
@@ -38,6 +38,7 @@ namespace oscardata
public static Byte terminate = 26;
public static Byte tuning = 27;
public static Byte marker = 28;
+ public static Byte setfreq = 29;
// frame sequence, modem needs that for i.e. sending a preamble
public static Byte FirstFrame = 0;
@@ -54,6 +55,7 @@ namespace oscardata
// global static variables
public static bool running = true;
public static String ModemIP = "1.2.3.4";
+ public static String MyIP = "1.2.3.4";
public static int UdpBCport_AppToModem = 40131; // broadcast port for modem search
public static int UdpTXport = 40132; // to modem
public static int UdpRXport = 40133; // from modem
diff --git a/oscardata/oscardata/oscardata.csproj b/oscardata/oscardata/oscardata.csproj
index bbb6d61..2004078 100755
--- a/oscardata/oscardata/oscardata.csproj
+++ b/oscardata/oscardata/oscardata.csproj
@@ -150,6 +150,8 @@
+
+
diff --git a/oscardata/oscardata/udp.cs b/oscardata/oscardata/udp.cs
index 2004f34..e1488f2 100755
--- a/oscardata/oscardata/udp.cs
+++ b/oscardata/oscardata/udp.cs
@@ -61,8 +61,11 @@ namespace oscardata
}
// Udp RX Loop runs in its own thread
+
static void Udprxloop()
{
+ int extIPcnt = 0;
+
// define UDP port
UdpClient udpc = new UdpClient(statics.UdpRXport);
udpc.Client.ReceiveTimeout = 100;
@@ -95,7 +98,27 @@ namespace oscardata
// Broadcast response
if (rxtype == statics.udp_bc)
{
- statics.ModemIP = RemoteEndpoint.Address.ToString();
+ String ModIP = RemoteEndpoint.Address.ToString();
+ if (ModIP != statics.MyIP)
+ {
+ // this is not the local IP
+ // wait for 3 Receptions before accepting it
+ if (extIPcnt < 3)
+ {
+ //Console.WriteLine("myIP:"+statics.MyIP+" modem is ext IP:"+ModIP+", waiting:" + extIPcnt);
+ if (extIPcnt < 4) extIPcnt++;
+ if (extIPcnt < 3)
+ continue;
+ }
+ //Console.WriteLine("modem is ext IP, accepted");
+ }
+ else
+ {
+ //Console.WriteLine("modem is local IP");
+ extIPcnt = 0;
+ }
+
+ statics.ModemIP = ModIP;
searchtimeout = 0;
// message b contains audio devices and init status
statics.initAudioStatus = b[0];
@@ -266,10 +289,10 @@ 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(penred, 150, yl, 150, yh);
gr.DrawLine(pensolid, 20, yl, 20, yh);
gr.DrawLine(pensolid, 280, yl, 280, yh);
- gr.DrawLine(penred, 300, yl, 300, yh);
gr.DrawLine(pensolid, 360, yl, 360, yh);
gr.DrawRectangle(penred, 15, yh, 270, yl-yh);