This commit is contained in:
Kurt Moraw 2021-01-03 00:34:35 +01:00
parent 573107a3d0
commit 429ec008a9
54 changed files with 3480 additions and 851 deletions

View File

@ -1,8 +1,9 @@
# QO-100-modem # 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. 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 # this is work in progress
Version 0.55 Version 0.64
Windows 10 (should work on Win7, not tested) Windows 10 (should work on Win7, not tested)
linux Desktop PC, linux Desktop PC,
Odroid SBC Odroid SBC

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -27,8 +27,6 @@
#include "hsmodem.h" #include "hsmodem.h"
void close_a();
const int h_len = 57; const int h_len = 57;
float h[h_len]; float h[h_len];
firfilt_crcf qfilt = NULL; firfilt_crcf qfilt = NULL;

7
hsmodem/baudot.h Executable file
View File

@ -0,0 +1,7 @@
#pragma once
typedef struct _BAUDOTTAB_ {
unsigned char baudot;
char letter;
char number;
} BAUDOTTAB;

View File

@ -47,6 +47,24 @@ int rxlevel_deteced = 0;
int rx_in_sync = 0; int rx_in_sync = 0;
msresamp_crcf fftdecim = NULL; 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) uint16_t *make_waterfall(float fre, int *retlen)
{ {
int fftrdy = 0; int fftrdy = 0;
@ -101,9 +119,27 @@ uint16_t *make_waterfall(float fre, int *retlen)
// measure level at mid band // measure level at mid band
float midlevel = 0; float midlevel = 0;
for (int e = 100; e < 200; e++) if (speedmode == 10)
midlevel += f_fftout[e]; {
midlevel /= 100; // 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 % //calc difference in %
int idiff = (int)((edgelevel * 100) / midlevel); int idiff = (int)((edgelevel * 100) / midlevel);
@ -118,10 +154,62 @@ uint16_t *make_waterfall(float fre, int *retlen)
// check if signal detected or not // check if signal detected or not
if (idiff > 100) sig = 0; if (idiff > 100) sig = 0;
if (idiff < 30) sig = 1; if (idiff < 50) sig = 1;
rxlevel_deteced = sig; 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 // check if changed since last check
if (sig != lastsig) if (sig != lastsig)
{ {

View File

@ -27,6 +27,8 @@
#include "hsmodem.h" #include "hsmodem.h"
void rtty_init_pipes();
#ifdef _WIN32_ #ifdef _WIN32_
CRITICAL_SECTION io_cap_crit_sec; CRITICAL_SECTION io_cap_crit_sec;
CRITICAL_SECTION io_pb_crit_sec; CRITICAL_SECTION io_pb_crit_sec;
@ -77,6 +79,7 @@ void io_init_pipes()
#endif #endif
io_voice_init_pipes(); io_voice_init_pipes();
rtty_init_pipes();
} }
// write one sample into the fifo // write one sample into the fifo
@ -190,19 +193,25 @@ int io_pb_fifo_freespace(int nolock)
int io_pb_fifo_usedspace() 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); int anz = io_pb_fifo_freespace(0);
return AUDIO_PLAYBACK_BUFLEN - anz; return AUDIO_PLAYBACK_BUFLEN - anz;*/
} }
// read num elements // 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) int io_pb_read_fifo_num(float* data, int num)
{ {
IO_PB_LOCK; IO_PB_LOCK;
int elemInFifo = (io_pb_wridx + AUDIO_PLAYBACK_BUFLEN - io_pb_rdidx) % AUDIO_PLAYBACK_BUFLEN; 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 // Fifo empty, no data available
//printf("only %d elements available\n", elemInFifo); //printf("only %d elements available\n", elemInFifo);
@ -210,14 +219,17 @@ int io_pb_read_fifo_num(float* data, int num)
return 0; return 0;
} }
if (num > elemInFifo)
num = elemInFifo;
for (int i = 0; i < num; i++) for (int i = 0; i < num; i++)
{ {
*data++ = io_pb_buffer[io_pb_rdidx]; *data++ = io_pb_buffer[io_pb_rdidx];
if (++io_pb_rdidx >= AUDIO_PLAYBACK_BUFLEN) io_pb_rdidx = 0; if (++io_pb_rdidx >= AUDIO_PLAYBACK_BUFLEN) io_pb_rdidx = 0;
} }
IO_PB_UNLOCK(); IO_PB_UNLOCK();
return 1; return num;
} }
void io_clear_audio_fifos() void io_clear_audio_fifos()
@ -225,3 +237,152 @@ void io_clear_audio_fifos()
io_pb_write_fifo_clear(); io_pb_write_fifo_clear();
io_cap_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;
}

222
hsmodem/fm.cpp Executable file
View File

@ -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
*/
}
}

View File

@ -56,6 +56,7 @@ int UdpDataPort_ModemToApp = 40133;
// op mode depending values // op mode depending values
// default mode if not set by the app // default mode if not set by the app
int speedmode = 4; int speedmode = 4;
int set_speedmode = 4;
int bitsPerSymbol = 2; // QPSK=2, 8PSK=3 int bitsPerSymbol = 2; // QPSK=2, 8PSK=3
int constellationSize = 4; // QPSK=4, 8PSK=8 int constellationSize = 4; // QPSK=4, 8PSK=8
@ -208,10 +209,11 @@ int main(int argc, char* argv[])
{ {
if (restart_modems == 1) if (restart_modems == 1)
{ {
printf("restart modem requested\n");
startModem(); startModem();
restart_modems = 0; restart_modems = 0;
} }
//doArraySend(); //doArraySend();
if (VoiceAudioMode == VOICEMODE_INTERNALLOOP) if (VoiceAudioMode == VOICEMODE_INTERNALLOOP)
{ {
@ -255,24 +257,34 @@ int main(int argc, char* argv[])
do_tuning(tuning); do_tuning(tuning);
} }
// demodulate incoming audio data stream if (speedmode == 10)
static uint64_t old_tm = 0;
uint64_t tm = getms();
if (tm >= (old_tm + 1000))
{ {
// read Audio device list every 1s //testall();
io_readAudioDevices(); //fmtest();
old_tm = tm; sleep_ms(10); // nothing to do here
} }
int dret = demodulator(); else
if (dret == 0)
{ {
// 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_ #ifdef _LINUX_
// not important how long to sleep, 10ms is fine // not important how long to sleep, 10ms is fine
sleep_ms(10); sleep_ms(10);
#endif #endif
}
} }
} }
printf("stopped: %d\n", keeprunning); printf("stopped: %d\n", keeprunning);
@ -283,7 +295,6 @@ int main(int argc, char* argv[])
closesocket(BC_sock_AppToModem); closesocket(BC_sock_AppToModem);
#endif #endif
return 0; return 0;
} }
@ -298,7 +309,7 @@ typedef struct {
} SPEEDRATE; } SPEEDRATE;
// AudioRate, TX-Resampler, RX-Resampler/4, bit/symbol, Codec-Rate // AudioRate, TX-Resampler, RX-Resampler/4, bit/symbol, Codec-Rate
SPEEDRATE sr[10] = { SPEEDRATE sr[11] = {
// BPSK modes // BPSK modes
{48000, 40,10, 1, 1200, 800}, {48000, 40,10, 1, 1200, 800},
{48000, 20, 5, 1, 2400, 2000}, {48000, 20, 5, 1, 2400, 2000},
@ -314,10 +325,19 @@ SPEEDRATE sr[10] = {
{48000, 24, 6, 3, 6000, 4800}, {48000, 24, 6, 3, 6000, 4800},
{44100, 20, 5, 3, 6600, 5200}, {44100, 20, 5, 3, 6600, 5200},
{48000, 20, 5, 3, 7200, 6000}, {48000, 20, 5, 3, 7200, 6000},
// RTTY
{48000, 0, 0, 0, 0, 0},
}; };
void startModem() void startModem()
{ {
printf("startModem\n");
close_dsp();
close_rtty();
io_close_audio();
speedmode = set_speedmode;
bitsPerSymbol = sr[speedmode].bpsym; bitsPerSymbol = sr[speedmode].bpsym;
constellationSize = (1 << bitsPerSymbol); // QPSK=4, 8PSK=8 constellationSize = (1 << bitsPerSymbol); // QPSK=4, 8PSK=8
@ -328,10 +348,27 @@ void startModem()
opusbitrate = sr[speedmode].codecrate; opusbitrate = sr[speedmode].codecrate;
// int TX audio and modulator // int TX audio and modulator
close_dsp();
init_audio_result = io_init_sound(playbackDeviceName, captureDeviceName); init_audio_result = io_init_sound(playbackDeviceName, captureDeviceName);
_init_fft(); _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) 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 * 5 ... DV mic volume
* 6 ... safe mode number * 6 ... safe mode number
* 7 ... send Intro * 7 ... send Intro
* 8..9 ... unused * 8 ... rtty autosync
* 9 ... unused
* 10 .. 109 ... PB device name * 10 .. 109 ... PB device name
* 110 .. 209 ... CAP 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)); io_setAudioDevices(pdata[1], pdata[2], pdata[3], pdata[4], pdata[5], (char*)(pdata + 10), (char*)(pdata + 110));
safemode = pdata[6]; safemode = pdata[6];
sendIntro = pdata[7]; sendIntro = pdata[7];
rtty_autosync = pdata[8];
lastms = actms; 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 type = pdata[0];
uint8_t minfo = pdata[1]; uint8_t minfo = pdata[1];
//printf("from GUI: %d %d\n", pdata[0], pdata[1]);
// type values: see oscardata config.cs: frame types // type values: see oscardata config.cs: frame types
if (type == 16) if (type == 16)
{ {
// Byte 1 contains the resampler ratio for TX and RX modem // Byte 1 contains the speed mode index
if (pdata[1] >= 12) setSpeedmode(pdata[1]);
{
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
return; return;
} }
@ -544,7 +577,7 @@ void appdata_rxdata(uint8_t* pdata, int len, struct sockaddr_in* rxsock)
VoiceAudioMode = pdata[1]; VoiceAudioMode = pdata[1];
codec = pdata[2]; 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 // init voice audio
if (VoiceAudioMode == VOICEMODE_OFF) if (VoiceAudioMode == VOICEMODE_OFF)
@ -585,14 +618,61 @@ void appdata_rxdata(uint8_t* pdata, int len, struct sockaddr_in* rxsock)
return; return;
} }
if (type == 29) if (speedmode == 10)
{ {
int v = minfo; // rtty commands
if (v > 128) if (type == 29)
v = v - 255; {
modifyRXfreq(float(v)); int16_t freq = pdata[1];
return; 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 // 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 // reset modem if more than 2 frames have not been received
trigger_resetmodem = 0; trigger_resetmodem = 0;
rx_in_sync = 0; rx_in_sync = 0;
printf("no signal detected, reset RX modem\n"); if (speedmode < 10)
resetModem(); {
printf("no signal detected, reset RX modem\n");
resetModem();
}
lasttime = acttm; lasttime = acttm;
} }
} }

View File

@ -64,6 +64,7 @@
#include "symboltracker.h" #include "symboltracker.h"
#include "codec2.h" #include "codec2.h"
#include "soundio.h" #include "soundio.h"
#include "baudot.h"
#define jpg_tempfilename "rxdata.jpg" #define jpg_tempfilename "rxdata.jpg"
@ -191,14 +192,15 @@ void write_sample_s16ne(char* ptr, double sample);
int io_ls_fifo_usedspace(); int io_ls_fifo_usedspace();
void write_sample_float32ne(char* ptr, double sample); void write_sample_float32ne(char* ptr, double sample);
void km_symtrack_cccf_create(int _ftype, SYMTRACK* km_symtrack_cccf_create( int _ftype,
unsigned int _k, unsigned int _k,
unsigned int _m, unsigned int _m,
float _beta, float _beta,
int _ms); int _ms);
void km_symtrack_cccf_reset(int mode); void km_symtrack_cccf_reset(SYMTRACK*, int mode);
void km_symtrack_cccf_set_bandwidth(float _bw); void km_symtrack_cccf_set_bandwidth(SYMTRACK* , float _bw);
void km_symtrack_execute(liquid_float_complex _x, liquid_float_complex* _y, unsigned int* _ny, unsigned int* psym_out); 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 io_saveStream(float f);
void playIntro(); void playIntro();
@ -206,10 +208,24 @@ void io_clear_voice_fifos();
float do_tuning(int send); float do_tuning(int send);
void init_tune(); void init_tune();
float singleFrequency(); float singleFrequency();
void rtty_tx();
int rtty_rx(); int rtty_rx();
void modifyRXfreq(float fr); void modifyRXfreq(float diff_Hz, int absolute);
void showbytestring16(char* title, uint16_t* data, int anz); 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; extern int speedmode;
@ -252,9 +268,13 @@ extern int sendIntro;
extern int tuning; extern int tuning;
extern uint32_t tuning_runtime; extern uint32_t tuning_runtime;
extern int marker; extern int marker;
extern int rtty_txoff;
extern int rtty_txidx;
extern int rtty_frequency;
extern int rtty_autosync;
#ifdef _LINUX_ #ifdef _LINUX_
int isRunning(char* prgname); int isRunning(char* prgname);
void install_signal_handler(); void install_signal_handler();
int isRunning(char* prgname);
#endif #endif

View File

@ -223,6 +223,7 @@
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="baudot.h" />
<ClInclude Include="codec2.h" /> <ClInclude Include="codec2.h" />
<ClInclude Include="endian.h" /> <ClInclude Include="endian.h" />
<ClInclude Include="fec.h" /> <ClInclude Include="fec.h" />

View File

@ -122,5 +122,8 @@
<ClInclude Include="endian.h"> <ClInclude Include="endian.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="baudot.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -200,7 +200,7 @@ void modulator(uint8_t sym_in)
// adapt speed to soundcard samplerate // adapt speed to soundcard samplerate
int fs; int fs;
while(1) while(keeprunning)
{ {
fs = io_pb_fifo_freespace(0); fs = io_pb_fifo_freespace(0);
// wait until there is space in fifo // wait until there is space in fifo
@ -218,7 +218,6 @@ void modulator(uint8_t sym_in)
// =========== DEMODULATOR ============================= // =========== DEMODULATOR =============================
nco_crcf dnnco = NULL; nco_crcf dnnco = NULL;
symtrack_cccf symtrack = NULL;
firdecim_crcf decim = NULL; firdecim_crcf decim = NULL;
msresamp_crcf adecim = NULL; msresamp_crcf adecim = NULL;
msresamp_crcf lsresamp = 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 radians_per_sample = ((2.0f * (float)M_PI * (float)FREQUENCY) / (float)caprate);
float last_radians_per_sample = 0; float last_radians_per_sample = 0;
float actfrequency = (float)FREQUENCY;
void modifyRXfreq(float diff_Hz) SYMTRACK *km_symtrack = NULL;
{
actfrequency += diff_Hz;
printf("set:%f Hz\n", actfrequency);
radians_per_sample = ((2.0f * (float)M_PI * actfrequency) / (float)caprate);
}
void init_demodulator() void init_demodulator()
{ {
@ -275,8 +268,8 @@ void init_demodulator()
lsresamp = msresamp_crcf_create((float)(48000.0/44100.0), As_adecim); lsresamp = msresamp_crcf_create((float)(48000.0/44100.0), As_adecim);
// create symbol tracking synchronizer // create symbol tracking synchronizer
km_symtrack_cccf_create(ftype_st, k_st, m_st, beta_st, getMod()); km_symtrack = km_symtrack_cccf_create(ftype_st, k_st, m_st, beta_st, getMod());
km_symtrack_cccf_set_bandwidth(bandwidth_st); km_symtrack_cccf_set_bandwidth(km_symtrack, bandwidth_st);
} }
void close_demodulator() void close_demodulator()
@ -287,16 +280,17 @@ void close_demodulator()
adecim = NULL; adecim = NULL;
if (lsresamp) msresamp_crcf_destroy(lsresamp); if (lsresamp) msresamp_crcf_destroy(lsresamp);
lsresamp = NULL; lsresamp = NULL;
if (symtrack != NULL) symtrack_cccf_destroy(symtrack);
symtrack = NULL;
if (dnnco != NULL) nco_crcf_destroy(dnnco); if (dnnco != NULL) nco_crcf_destroy(dnnco);
dnnco = NULL; dnnco = NULL;
if (km_symtrack != NULL) km_symtrack_cccf_destroy(km_symtrack);
km_symtrack = NULL;
} }
void resetModem() void resetModem()
{ {
//printf("Reset Symtrack\n"); //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) // called for Audio-Samples (FFT)
@ -307,33 +301,6 @@ void make_FFTdata(float f)
uint16_t* fft = make_waterfall(f, &fftlen); uint16_t* fft = make_waterfall(f, &fftlen);
if (fft != NULL) 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]; uint8_t txpl[10000];
if (fftlen > (10000 * 2 + 1)) if (fftlen > (10000 * 2 + 1))
{ {
@ -344,10 +311,17 @@ void make_FFTdata(float f)
int bidx = 0; int bidx = 0;
txpl[bidx++] = 4; // type 4: FFT data follows 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; if (us > 255 || ann_running == 1) us = 255;
txpl[bidx++] = us; // usage of TX fifo txpl[bidx++] = us; // usage of TX fifo
us = io_cap_fifo_usedPercent(); us = io_cap_fifo_usedPercent();
if (us > 255) us = 255; if (us > 255) us = 255;
txpl[bidx++] = us; // usage of TX fifo 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++] = rxlevel_deteced; // RX level present
txpl[bidx++] = rx_in_sync; txpl[bidx++] = rx_in_sync;
txpl[bidx++] = maxLevel; // actual max level on sound capture in % txpl[bidx++] = maxLevel; // actual max level on sound capture in %
txpl[bidx++] = maxTXLevel; // actual max level on sound playback 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++) for (int i = 0; i < fftlen; i++)
{ {
@ -491,7 +468,7 @@ static int const_idx = 0;
unsigned int num_symbols_sync; unsigned int num_symbols_sync;
liquid_float_complex syms; liquid_float_complex syms;
unsigned int nsym_out; // demodulated output symbol 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 > 1) printf("symtrack_cccf_execute %d output symbols ???\n", num_symbols_sync);
if (num_symbols_sync != 0) if (num_symbols_sync != 0)

View File

@ -100,9 +100,17 @@ void closeAllandTerminate()
exit(0); 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) 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; i<anz; i++) for(int i=0; i<anz; i++)
printf("%02X ",data[i]); printf("%02X ",data[i]);
printf("\n"); printf("\n");
@ -110,7 +118,7 @@ void showbytestring(char *title, uint8_t *data, int totallen, int anz)
void showbytestring16(char *title, uint16_t *data, int anz) void showbytestring16(char *title, uint16_t *data, int anz)
{ {
printf("%s. Len %d: ",title,anz); printf("%s. len %d: ",title,anz);
for(int i=0; i<anz; i++) for(int i=0; i<anz; i++)
printf("%04X ",data[i]); printf("%04X ",data[i]);
printf("\n"); printf("\n");
@ -118,7 +126,7 @@ void showbytestring16(char *title, uint16_t *data, int anz)
void showbytestringf(char* title, float* data, int totallen, int anz) void showbytestringf(char* title, float* data, int totallen, int anz)
{ {
printf("%s. Len %d: ", title, totallen); printf("%s. len %d: ", title, totallen);
for (int i = 0; i < anz; i++) for (int i = 0; i < anz; i++)
printf("%7.4f ", data[i]); printf("%7.4f ", data[i]);
printf("\n"); printf("\n");

View File

@ -32,231 +32,743 @@
#include "hsmodem.h" #include "hsmodem.h"
int evalSymbols(uint8_t sym);
void baudot_encoder(char c, uint8_t bd[2], int* pnum);
uint8_t getBaudot(char c, int letters);
char baudot_decoder(char c);
void sendRttyToGUI(uint8_t b);
#define rtty_CENTERFREQUENCY 1500 #define rtty_CENTERFREQUENCY 1500
fskmod rtty_mod = NULL; float rtty_RADIANS_PER_SAMPLE = 0;
fskdem rtty_dem = NULL; float rtty_RX_RADIANS_PER_SAMPLE = 0;
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_upnco = NULL;
nco_crcf rtty_dnnco = NULL; nco_crcf rtty_dnnco = NULL;
firdecim_crcf rtty_decim = NULL; // RX RTTY Filter
unsigned int rtty_m_predec = 8; // filter delay firfilt_crcf rtty_q;
float rtty_As_predec = 40.0f; // stop-band att unsigned int flt_h_len = 65; // filter length
// we filter at 48k samp rate, half BW=170/2, so lets filter at 80 Hz
float flt_fc = 80.0f/48000.0f; // cutoff frequency
float flt_As = 60.0f; // stop-band attenuation
void close_rtty(); int rtty_txoff = 1; // 1=off, 0=on , >1...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 void sendRttyToGUI(uint8_t b)
rtty_k_SampPerSymb = caprate / rtty_CENTERFREQUENCY; {
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 * space=lower tone (Bitvalue=1)
float g = rtty_k_SampPerSymb * rtty_tau_FracSymbOffset; // number of samples offset * mark=higher tone (Bitvalue=0)
int ds = (int)floorf(g); // additional symbol delay *
float dt = (g - (float)ds); // fractional sample offset * start (space)
// force dt to be in [0.5,0.5] * bit 4
if (dt > 0.5f) * 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; rtty_txoff = 0;
ds++; *pnum = 0;
}
// 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; 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 if (c == '~')
float rtty_RADIANS_PER_SAMPLE = ((2.0f * (float)M_PI * (float)rtty_CENTERFREQUENCY) / (float)caprate); {
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); rtty_upnco = nco_crcf_create(LIQUID_NCO);
nco_crcf_set_phase(rtty_upnco, 0.0f); nco_crcf_set_phase(rtty_upnco, 0.0f);
nco_crcf_set_frequency(rtty_upnco, rtty_RADIANS_PER_SAMPLE); 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); rtty_dnnco = nco_crcf_create(LIQUID_NCO);
nco_crcf_set_phase(rtty_dnnco, 0.0f); 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); // modulate, demodulate, count errors
firdecim_crcf_set_scale(rtty_decim, 1.0f / (float)rtty_k_SampPerSymb); unsigned int num_symbol_errors = 0;
} }
void close_rtty() void ttest()
{ {
if (rtty_mod != NULL) fskmod_destroy(rtty_mod); int i, j;
rtty_mod = NULL; static unsigned int sym_in=0;
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 fs = io_pb_fifo_freespace(0);
int tidx = 0; if (fs < 20000) return;
int bitidx = 1;
void rtty_tx() static int scnt = 0;
{ if (++scnt == 8)
if (rtty_mod == NULL)
init_rtty();
unsigned int sym = (text[tidx] & bitidx) ? 1 : 0;
bitidx <<= 1;
if (bitidx == 0x0100)
{ {
bitidx = 1; scnt = 0;
tidx++; sym_in = 1 - sym_in;
if (tidx == 6) tidx = 0;
} }
//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 //printf("modulate\n");
fskmod_modulate(rtty_mod, sym, rtty_txbuf); fskmod_modulate(modi, sym_in, &(buf_tx[0]));
// here we have the complex RTTY signal in baseband
// one symbol was expanded to rtty_k periods: // move sample to 1,5kHz carrier
// 45.454545 * 33 = 1500 periods for (j = 0; j < k; j++)
for (unsigned int i = 0; i < rtty_k; i++)
{ {
// resample it to the soundcard rate caprate nco_crcf_step(rtty_upnco);
// interpolate by k_SampPerSymb nco_crcf_mix_up(rtty_upnco, buf_tx[j], &(buf_tx1500[j]));
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); usbf = (buf_tx1500[j]).real + (buf_tx1500[j]).imag;
// 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; //measure_speed_bps(1);
nco_crcf_mix_up(rtty_upnco, y[i], &c);
float usb = c.real + c.imag;
// speed: 48000 io_pb_write_fifo(usbf * 0.2f); // reduce volume and send to soundcard
// 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 rtest()
int rtty_rx()
{ {
static liquid_float_complex ccol[500]; static int bridx = 0;
static unsigned int ccol_idx = 0;
if (rtty_dnnco == NULL) return 0; int j;
// get one received sample
float f; float f;
int ret = io_cap_read_fifo(&f); int ret = io_cap_read_fifo(&f);
if (ret == 0) return 0; if (ret == 0) return 0;
if (VoiceAudioMode == VOICEMODE_LISTENAUDIOIN) // noise
io_ls_write_fifo(f); //printf("%f\n", f);
//f = f + nstd * randnf() * M_SQRT1_2;
// input volume (buf_rx1500[bridx]).real = f;
f *= softwareCAPvolume; (buf_rx1500[bridx]).imag = f;
//getMax(f);
//make_FFTdata(f * 100);
// downconvert 1,5kHz into baseband, still at soundcard sample rate
nco_crcf_step(rtty_dnnco); nco_crcf_step(rtty_dnnco);
nco_crcf_mix_down(rtty_dnnco, buf_rx1500[bridx], &(buf_rx[bridx]));
bridx++;
liquid_float_complex in; if (bridx == k)
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; bridx = 0;
printf("%d: %c\n", sym, sym);
sym = 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; 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;
}

View File

@ -36,7 +36,7 @@ struct SoundIoDevice* io_cap_device = NULL;
struct SoundIoInStream* instream = NULL; struct SoundIoInStream* instream = NULL;
struct SoundIoOutStream* outstream = 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_ { typedef struct _AUDIODEV_ {
@ -83,6 +83,7 @@ static void get_channel_layout(const struct SoundIoChannelLayout* layout)
int print_device(struct SoundIoDevice* device) int print_device(struct SoundIoDevice* device)
{ {
if (soundio == NULL) return 0;
if (!device->probe_error) if (!device->probe_error)
{ {
// ignore if exists // ignore if exists
@ -119,6 +120,7 @@ int print_device(struct SoundIoDevice* device)
static int scan_devices(struct SoundIo* soundio) static int scan_devices(struct SoundIo* soundio)
{ {
if (soundio == NULL) return 0;
audiodevidx = 0; audiodevidx = 0;
for (int i = 0; i < soundio_input_device_count(soundio); i++) 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) void read_callback(struct SoundIoInStream* instream, int frame_count_min, int frame_count_max)
{ {
int err; int err;
if (instream == NULL) return; if (instream == NULL || soundio == NULL) return;
//printf("cap: %d %d\n", frame_count_min, frame_count_max); //printf("cap: %d %d\n", frame_count_min, frame_count_max);
//int chans = instream->layout.channel_count; //int chans = instream->layout.channel_count;
struct SoundIoChannelArea* areas; struct SoundIoChannelArea* areas;
// samples are in areas.ptr // samples are in areas.ptr
int frames_left = frame_count_max; // take all int frames_left = frame_count_max; // take all
while (1) while (keeprunning)
{ {
int frame_count = frames_left; int frame_count = frames_left;
if ((err = soundio_instream_begin_read(instream, &areas, &frame_count))) 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) 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); //printf("pb: %d %d\n", frame_count_min, frame_count_max);
#ifdef SINEWAVETEST #ifdef SINEWAVETEST
double float_sample_rate = outstream->sample_rate; double float_sample_rate = outstream->sample_rate;
@ -431,7 +434,7 @@ int io_init_sound(char *pbname, char *capname)
init_audio_result = 0; init_audio_result = 0;
printf("\n ==== IO INIT AUDIO devices ====\n"); 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(); io_close_audio();

View File

@ -1,7 +1,6 @@
#include "hsmodem.h" #include "hsmodem.h"
SYMTRACK km_symtrack;
SYMTRACK* q = &km_symtrack;
// create km_symtrack object with basic parameters // create km_symtrack object with basic parameters
// _ftype : filter type (e.g. LIQUID_FIRFILT_RRC) // _ftype : filter type (e.g. LIQUID_FIRFILT_RRC)
@ -9,7 +8,7 @@ SYMTRACK* q = &km_symtrack;
// _m : filter delay (symbols) // _m : filter delay (symbols)
// _beta : filter excess bandwidth // _beta : filter excess bandwidth
// _ms : modulation scheme (e.g. LIQUID_MODEM_QPSK) // _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 _k,
unsigned int _m, unsigned int _m,
float _beta, float _beta,
@ -17,7 +16,7 @@ void km_symtrack_cccf_create(int _ftype,
{ {
// validate input // validate input
if (_k < 2) 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) if (_m == 0)
printf((char*)"symtrack_cccf_create(), filter delay must be greater than zero\n"); printf((char*)"symtrack_cccf_create(), filter delay must be greater than zero\n");
if (_beta <= 0.0f || _beta > 1.0f) 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) if (_ms == LIQUID_MODEM_UNKNOWN || _ms >= LIQUID_MODEM_NUM_SCHEMES)
printf((char*)"symtrack_cccf_create(), invalid modulation scheme\n"); printf((char*)"symtrack_cccf_create(), invalid modulation scheme\n");
// allocate memory for main object
SYMTRACK *q = (SYMTRACK *) malloc(sizeof(SYMTRACK));
// set input parameters // set input parameters
q->filter_type = _ftype; q->filter_type = _ftype;
q->k = _k; q->k = _k;
@ -54,14 +56,33 @@ void km_symtrack_cccf_create(int _ftype,
q->demod = modem_create((modulation_scheme)q->mod_scheme); q->demod = modem_create((modulation_scheme)q->mod_scheme);
// set default bandwidth // set default bandwidth
km_symtrack_cccf_set_bandwidth(0.9f); km_symtrack_cccf_set_bandwidth(q, 0.9f);
// reset and return main object // 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 // reset objects
if (mode & 1) agc_crcf_reset(q->agc); if (mode & 1) agc_crcf_reset(q->agc);
if (mode & 2) symsync_crcf_reset(q->symsync); if (mode & 2) symsync_crcf_reset(q->symsync);
@ -74,7 +95,7 @@ void km_symtrack_cccf_reset(int mode)
q->num_syms_rx = 0; 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 // validate input
if (_bw < 0) if (_bw < 0)
@ -106,8 +127,10 @@ void km_symtrack_cccf_set_bandwidth(float _bw)
// _x : input data sample // _x : input data sample
// _y : output data array // _y : output data array
// _ny : number of samples written to output buffer // _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 liquid_float_complex v; // output sample
unsigned int i; unsigned int i;
unsigned int num_outputs = 0; unsigned int num_outputs = 0;

View File

@ -79,7 +79,7 @@ float do_tuning(int send)
// adapt speed to soundcard samplerate // adapt speed to soundcard samplerate
int fs; int fs;
while (1) while (keeprunning)
{ {
fs = io_pb_fifo_freespace(0); fs = io_pb_fifo_freespace(0);
// wait until there is space in fifo // wait until there is space in fifo

View File

@ -46,7 +46,7 @@ void read_voicecallback(struct SoundIoInStream* instream, int frame_count_min, i
struct SoundIoChannelArea* areas; struct SoundIoChannelArea* areas;
// samples are in areas.ptr // samples are in areas.ptr
int frames_left = frame_count_max; // take all int frames_left = frame_count_max; // take all
while (1) while (keeprunning)
{ {
int frame_count = frames_left; int frame_count = frames_left;
if ((err = soundio_instream_begin_read(instream, &areas, &frame_count))) if ((err = soundio_instream_begin_read(instream, &areas, &frame_count)))

View File

@ -168,7 +168,7 @@ void sendCodecToModulator(uint8_t *pdata, int len)
toGR_sendData(payload, 6, 1 ,0); // 6 ... voice data, 1 ... valid voice data 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 // 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(); int us = io_pb_fifo_usedspace();

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -48,6 +48,8 @@ namespace oscardata
int last_initVoiceStatus; int last_initVoiceStatus;
int recordStatus = 0; int recordStatus = 0;
int recPhase = 0; int recPhase = 0;
const int Rtty_deftext_anz = 20;
String[] Rtty_deftext = new string[Rtty_deftext_anz];
public Form1() public Form1()
@ -55,6 +57,8 @@ namespace oscardata
// init GUI // init GUI
InitializeComponent(); InitializeComponent();
//showSSTV();
// needed for ARM mono, which cannot load a picbox directly from file // needed for ARM mono, which cannot load a picbox directly from file
var bmp = new Bitmap(Resources.hintergrundxcf); var bmp = new Bitmap(Resources.hintergrundxcf);
pictureBox_rximage.BackgroundImage = bmp; pictureBox_rximage.BackgroundImage = bmp;
@ -122,6 +126,10 @@ namespace oscardata
// TX timer // TX timer
private void timer1_Tick(object sender, EventArgs e) 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 // BER testdata
if (txcommand == statics.BERtest) if (txcommand == statics.BERtest)
{ {
@ -596,7 +604,10 @@ namespace oscardata
pb_rxsignal.BackgroundImage = Resources.redmarker; pb_rxsignal.BackgroundImage = Resources.redmarker;
showType(-1); 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 // update rx,tx level progress bar
int factor = 1; int factor = 1;
@ -644,6 +655,72 @@ namespace oscardata
bt_resetmodem_Click(null, null); bt_resetmodem_Click(null, null);
statics.tuning_active = 0; 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) 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); 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) void AppendTextOnce(RichTextBox rtb, Font selfont, Color color, Color bcolor, string text)
{ {
try try
@ -746,7 +828,7 @@ namespace oscardata
// Textbox may transform chars, so (end-start) != text.Length // Textbox may transform chars, so (end-start) != text.Length
rtb.Select(start, end - start); rtb.Select(start, end - start);
rtb.SelectionColor = color; rtb.SelectionColor = color;
rtb.SelectionFont = selfont; if(selfont != null) rtb.SelectionFont = selfont;
rtb.SelectionBackColor = bcolor; rtb.SelectionBackColor = bcolor;
rtb.Select(end, 0); rtb.Select(end, 0);
@ -1075,24 +1157,19 @@ namespace oscardata
label_txfile.Location = new Point(rtb_TXfile.Location.X, ly); label_txfile.Location = new Point(rtb_TXfile.Location.X, ly);
label_rxfile.Location = new Point(rtb_RXfile.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); pn1.Location = new Point(panel_txspectrum.Location.X + panel_txspectrum.Size.Width + 10, panel_txspectrum.Location.Y +0);
cb_speed.Location = new Point(label_speed.Location.X + label_speed.Size.Width + 10, label_speed.Location.Y-5);
int y = 26; tb_rtty_RX.Location = new Point(9, 35);
label_fifo.Location = new Point(label_speed.Location.X, label_speed.Location.Y + y); tb_rtty_RX.Size = new Size(675, 348);
progressBar_fifo.Location = new Point(cb_speed.Location.X, cb_speed.Location.Y + y+5);
progressBar_fifo.Size = new Size(progressBar_fifo.Width, 18);
y = 20; tb_rtty_TX.Location = new Point(9, 416);
label_capfifo.Location = new Point(label_fifo.Location.X, label_fifo.Location.Y + y); tb_rtty_TX.Size = new Size(675, 103);
progressBar_capfifo.Location = new Point(progressBar_fifo.Location.X, progressBar_fifo.Location.Y + y);
progressBar_capfifo.Size = new Size(progressBar_capfifo.Width, 18);
lb_rxsignal.Location = new Point(progressBar_capfifo.Location.X + progressBar_capfifo.Size.Width + 15, label_fifo.Location.Y-15); label4.Location = new Point(13, 393);
pb_rxsignal.Location = new Point(lb_rxsignal.Location.X + lb_rxsignal.Size.Width + 2, label_fifo.Location.Y-5-15);
lb_rxsync.Location = new Point(progressBar_capfifo.Location.X + progressBar_capfifo.Size.Width + 15, label_capfifo.Location.Y); panel1.Location = new Point(696,8);
pb_rxsync.Location = new Point(lb_rxsignal.Location.X + lb_rxsignal.Size.Width + 2, label_capfifo.Location.Y-5);
tb_rtty_deftext.Size = new Size(522, 160);
} }
public String GetMyBroadcastIP() public String GetMyBroadcastIP()
@ -1157,7 +1234,7 @@ namespace oscardata
txb[5] = (Byte)tb_mic.Value; txb[5] = (Byte)tb_mic.Value;
txb[6] = safemode; txb[6] = safemode;
txb[7] = (Byte)(cb_sendIntro.Checked?1:0); 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 txb[9] = (Byte)0; // unused
Byte[] bpb = statics.StringToByteArrayUtf8(cb_audioPB.Text); 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) private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{ {
bool b = cb_switchtoLS.Checked; bool b = cb_switchtoLS.Checked;
allVoiceModesOff(); allVoiceModesOff();
cb_switchtoLS.Checked = b; 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("3000")) statics.real_datarate = 3000;
if (cb_speed.Text.Contains("4000")) statics.real_datarate = 4000; if (cb_speed.Text.Contains("4000")) statics.real_datarate = 4000;
if (cb_speed.Text.Contains("4410")) statics.real_datarate = 4410; if (cb_speed.Text.Contains("4410")) statics.real_datarate = 4410;
@ -1366,7 +1476,9 @@ namespace oscardata
{ {
try 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); tb_callsign.Text = ReadString(sr);
cb_speed.Text = ReadString(sr); cb_speed.Text = ReadString(sr);
@ -1397,6 +1509,32 @@ namespace oscardata
catch { } catch { }
try { cb_language.Text = ReadString(sr); } catch { } try { cb_language.Text = ReadString(sr); } catch { }
try { s = ReadString(sr); cb_sendIntro.Checked = (s == "1"); } 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 catch
@ -1441,11 +1579,110 @@ namespace oscardata
sw.WriteLine(rb_opus.Checked ? "1" : "0"); sw.WriteLine(rb_opus.Checked ? "1" : "0");
sw.WriteLine(cb_language.Text); sw.WriteLine(cb_language.Text);
sw.WriteLine(cb_sendIntro.Checked ? "1" : "0"); 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 { } 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) private void bt_shutdown_Click(object sender, EventArgs e)
{ {
DialogResult dr = MessageBox.Show(statics.langstr[23], statics.langstr[22], MessageBoxButtons.YesNo); DialogResult dr = MessageBox.Show(statics.langstr[23], statics.langstr[22], MessageBoxButtons.YesNo);
@ -1494,27 +1731,6 @@ namespace oscardata
setCAPvolume = tb_CAPvol.Value; 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) void setVoiceAudio(Byte opmode = 0)
{ {
/* /*
@ -1762,7 +1978,6 @@ namespace oscardata
tabPage_about.Text = "About"; tabPage_about.Text = "About";
label_speed.Text = "Speed [bit/s]:"; label_speed.Text = "Speed [bit/s]:";
label_fifo.Text = "TX Buffer:"; label_fifo.Text = "TX Buffer:";
bt_blockinfo.Text = "Block Info";
label_capfifo.Text = "RX Buffer:"; label_capfifo.Text = "RX Buffer:";
lb_rxsignal.Text = "RX Signal:"; lb_rxsignal.Text = "RX Signal:";
lb_rxsync.Text = "RX Sync:"; lb_rxsync.Text = "RX Sync:";
@ -1771,6 +1986,29 @@ namespace oscardata
lb_tuningqrgs.Text = "Send Mid-Frequency:"; lb_tuningqrgs.Text = "Send Mid-Frequency:";
cb_marker.Text = "2.9kHz Tuning Marker"; cb_marker.Text = "2.9kHz Tuning Marker";
label13.Text = "Data Security:"; 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) if (language == 1)
@ -1828,6 +2066,29 @@ namespace oscardata
lb_tuningqrgs.Text = "Sende Mittenfrequenz:"; lb_tuningqrgs.Text = "Sende Mittenfrequenz:";
cb_marker.Text = "2,9kHz Tuning Markierung"; cb_marker.Text = "2,9kHz Tuning Markierung";
label13.Text = "Datensicherheit:"; 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 " of ", //30
"Bad blocks, retransmission required", "Bad blocks, retransmission required",
"Bad blocks", //32 "Bad blocks", //32
"Set RTTY predefinded text messages to default values. Are you sure ?", //33
"Set Default Mesages", //34
}; };
String[] langstr_de = new String[]{ String[] langstr_de = new String[]{
@ -1909,6 +2172,8 @@ namespace oscardata
" von ", //30 " von ", //30
"defekte Blöcke, Datei muss nochmal empfangen werden", "defekte Blöcke, Datei muss nochmal empfangen werden",
"defekte Blöcke", //32 "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) private void cb_autostart_CheckedChanged(object sender, EventArgs e)
@ -1986,6 +2251,316 @@ namespace oscardata
txdata[1] = 255 - 10; txdata[1] = 255 - 10;
Udp.UdpSendCtrl(txdata); 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);
}
}
} }

View File

@ -136,9 +136,9 @@
<value> <value>
AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w
LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAABw ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAA+
FwAAAk1TRnQBSQFMAgEBDQEAAUABBgFAAQYBEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo JQAAAk1TRnQBSQFMAgEBFwEAAYgBDAGIAQwBEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo
AwABQAMAAUADAAEBAQABCAYAARAYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA AwABQAMAAWADAAEBAQABCAYAARgYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA
AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5 AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5
AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA
AWYDAAGZAwABzAIAATMDAAIzAgABMwFmAgABMwGZAgABMwHMAgABMwH/AgABZgMAAWYBMwIAAmYCAAFm AWYDAAGZAwABzAIAATMDAAIzAgABMwFmAgABMwGZAgABMwHMAgABMwH/AgABZgMAAWYBMwIAAmYCAAFm
@ -165,79 +165,137 @@
AcwBAAH/AZkB/wEAAf8BzAIAAf8BzAEzAQAB/wHMAWYBAAH/AcwBmQEAAf8CzAEAAf8BzAH/AQAC/wEz AcwBAAH/AZkB/wEAAf8BzAIAAf8BzAEzAQAB/wHMAWYBAAH/AcwBmQEAAf8CzAEAAf8BzAH/AQAC/wEz
AQABzAH/AWYBAAL/AZkBAAL/AcwBAAJmAf8BAAFmAf8BZgEAAWYC/wEAAf8CZgEAAf8BZgH/AQAC/wFm AQABzAH/AWYBAAL/AZkBAAL/AcwBAAJmAf8BAAFmAf8BZgEAAWYC/wEAAf8CZgEAAf8BZgH/AQAC/wFm
AQABIQEAAaUBAANfAQADdwEAA4YBAAOWAQADywEAA7IBAAPXAQAD3QEAA+MBAAPqAQAD8QEAA/gBAAHw AQABIQEAAaUBAANfAQADdwEAA4YBAAOWAQADywEAA7IBAAPXAQAD3QEAA+MBAAPqAQAD8QEAA/gBAAHw
AfsB/wEAAaQCoAEAA4ADAAH/AgAB/wMAAv8BAAH/AwAB/wEAAf8BAAL/AgAD/wQAARoBmQEbAf8CAAH/ AfsB/wEAAaQCoAEAA4ADAAH/AgAB/wMAAv8BAAH/AwAB/wEAAf8BAAL/AgAD/wQAAf8B8gHvAesB6gES
AfQBGgGZAf81AAF0ATIBNwFLAfEB9AF0ATEBOAEyAfM1AAF5AzgCNwM4ATEB8zUAAZkEOAH7AzgBMQH0 AW0BkgHwAf8GAAH/AfIB7wHsAeoBEgFtAZIB8AH/CAAB9AXyAf8XAAHvARIBEwHrAe0BkgHsARIBEwFt
NQABmQg4ATEB9jUAAZkEegJZAjgBMQH0MwAB/wGZAVgIegFZAXkB/zIAARoBWQt6AVIB/zAAAfQBeQ16 AfQFAAHvAhIB6wKSAewCEgFtAfQHAAH0AQcCDgFtAfMB/xUAAf8BkgESAewBBwHyAvMB8gHxAZIB6gHs
ARowAAHzAVIMegF5AZkxAAH2ARsBGgGZBnoBmQEaARsB9AH/NQABGwF6ApoBegF5Af85AAH/AXkCoAF6 AfQCAAH/AfcB6gHsAbwB8gLzAfIB8QH3AeoB7AH0CAABbQEPAfIXAAEHARIB7QHxAfMB9AL/AvQB8gG8
AfY7AAH2AXoBoAEaPQABGwGaAf93AAH/DPIB9AH/BwABBwHsAeoBbQHqAewBvBMABP8B9AHzAQcB7wHw AeoBbQH/AQABBwHqAZIB8QHzAfQC/wL0AfIBvAJtAf8HAAHsAREB8xYAAf8BbQHrAfEB9AH/AesBBwP/
AfQF/wEAAZMDRQZGBEUB9AkAAW0BEwHsBgAC/wn2Af8FAAH0AfAB9wEUARECEAYAAf8BbwIfAUYGJQFG AfQB8gH3ARIB8AH/AusB8QH0Av8BGgG9Av8B9AHyAfcB6gHwBwAB7AEVAfMWAAHwARIBvAHzAv8BEwEV
ASQBHwFFAfIDAAH0BfMBbQFDAZIFAAH/AZkBUwkyAXUB/wEAAf8BBwHwAfEB9AH/AfMCBwHyAwAB/wIA AewB9AL/AfQB8QESAZIB8AHqAbwB8wL/AWkCIAFGAfQB/wH0AfEB6gH3BwAB7QETAfMWAAHsAW0B8QH0
Af8BbwEfAW8B9AF0ASUCJgIlARsBkwEfAUUB8gMAAe0BEQFEAQEBRAIRAQ8BkgUAAf8CUwGaAVMBwwFZ Av8BQwIQAeoBBwL/AfIB7AHrAe0B6wHxAfQB/wEWBCABRgL/AfIC7AcAAZIB6gHzFgABbQHsAfIB9AL/
AcMBWQQyAfYBAAH/AfIB8AERAfQHAAHxAUMB8wEAAf8BbwEfAZMC8wF1AiwBTQHxAfMB8AFFASQB8gQA ARECDgERARMBkgH/AfMB9wHqAesB7AHyAfQB/wEXASAC+QIgAb0B/wHzAfcBbQcAAfcB6wHzFgAB6wHs
Af8BRQEfAW4B/wHrAQ4B7QUAAf8BMgFTARoBWQH/AVkB/wFZBDIB9gEAAfQB7AETAQ8B8gcAAe8BEQEV AfEB9AL/AW0BEwEUARMB6wG8Af8B8gGSAW0C7AHxAfQB/wEWARcCRwFGASABGgH/AfIBkgFtBwAB7wHs
AfEB/wFvAR8BJAGTAfIB8QF1ASwBvAHxAbwBJAEfASQB8gUAAW8BIAGTAQABbQEAAe0FAAH/AzIBmgHD AfMWAAH3AW0B8QH0Av8B6wFtARIB7QL/AfQB8gLsAe8B6wHxAfQB/wG9ARcDRgFvAf8B9AHyAuwHAAHv
AVkB/wE4BDIB9gEAAfQBDgHqARAB8gcAAe8BQwEVAZIB/wFvAh8BJAGTAfEB8AK8AQcBRgMfAfIFAAFv AewB8xYAAfMBbQHvAfQC/wLsAbwD/wHzAbwB6gHvAfMBbQHvAfQC/wG9ARYBbwGUAv8B8wG8AW0BBwcA
ASABkwEAAW0BAAHtBQAB/wEyAVMBGgGaAVMBmgF6BTIB9gEAAfQB6gHrAUMB8gcAAe8BEwHqAQcB/wFv AfcB6wHzFwAB7QFtAfAB9AH/Ae8E/wH0AfEB7QFtAfIBAAGSAW0B8AH0Bv8B9AHxAe0B6wHyAgAB7wH/
AQEBHwEkAUYBHAHxAfABBwElAh8BAQEfAfIFAAFvASABkwEAAesBEAHtBQAB/wEsAjIBWQH2ARoBUwUy AwAB9wFtAfMDAAHxEwAB8gFtAewB8QHzBPQB8wHxAZIBbQEHAf8BAAHyAesB7AHxAfME9AHzAfEB9wHr
AfYCAAEHAe0BFAHyBwAB7wFtAewB8AH/AW8BRQFGAUwBbwPxAfABkwFvAUYCRQHyBAAB/wFuASABkwEA AQcB/wIAAe0B8wMAAZIB6gHzAwAB7xQAAfEB6wFtAe8B8QLyAfEBvAHsAesB7wQAAfEB7AFtAe8B8QLy
AesBDwGSAwAB8wEAAf8BUwF6AcMBGgGaAXoBWQJ6A1MB/wIAAfIBvAESAfMHAAEHAesB8AHzAf8EbwHx AfEBvAHsAesB7wQAAe0B7AH0Av8B7QETAfMC/wEHAW0VAAHyAZIB6wTsAesB7AG8Af8FAAHyAZIF7AHr
AfIBvAEHAfEB8gGTA28B8gQAAfMBCwEfAZMBAAHrAREBkgMAARMBAAH/AVMDdQR6BHUB/wIAAfQBvAH/ AewB8AH/BAABBwrsAfcXAAHzAe8C7AHvAfEB/wkAAfMB7wHtAewB7wHxAf80AAH/AfQC8wHyAvEB8ALx
CQAB/wHvAf8BAAJvAZMC8wG8AZMBbwEHAfIB8wGTAm8B8wQAAfQBDwEBAZMBAAHrAUMBkgEAAf8BvAER AbwBuwG0AQkB9AH/EwAB/wHyAe8B6wHqARIBbQGSAfAB/wgAAf8B8wH/CAAB9ALxBvQBuwGsAbMB7wGt
AQAB/wFTCnoBdQH/AgAB/wGSAfQJAAHyAe8B/wEAAm8BvAHzAfAEbwHvAvMBkwFvAfMEAAH/AREBEAFD AYoB9BMAAe8BEgETAesB7QGSAewBEgETAW0B9AQAAfEBswHzAfEB8wHyAfEB8gYAAf8B8QHyBvQBtAGK
AW0BQwIVAW0BFAERARQBAAH/AVMKegF1Af8DAAH/AfIJAAHyAwADkwEHBpMB7wOTAfMB9AFvAgAB/wIS AbQB8QGtAYoBuwUAAv8B9AHzAfQE/wMAAf8BkgESAewBBwHyAvMB8gHxAZIB6gHsAfQCAAH/ArMB7AHt
AW0D7QFEAu0B7AGSAQAB/wF1CpoBegH/BAABvAHvAf8FAAH0AewB8QMADpMB8wH/AUUB/wIAARwB7QHv AQcB8wEAAfAHAAHyAfMG9AKLAbQB/wGtAYoBtAQAAf8B7wGLAWwCZgLqAWYBbAG8Af8BAAEHARIB7QHx
AgAB8QFFBQAB/wEbAXoJdQEaAf8EAAH/AkMBvAL/AfQBBwEQAW0B/wMAAfMMkwEaAv8CbgLvAW4B9wHs AfMB9AL/AvQB8gG8AeoBbQH/AQAB8gEZAbsCvAEHAfcB7QGSAbwB8gL/AQAB/wEAAfQB8gHzBPQB/wG0
Ae8BkwJuBgAM/wYAAf8B7wETAw4BFAEHAf8TAAH/C28bAAH/AfMB/wYABP8C9AHvAewBkgHyAfQF/wMA Aa0BswG7Aq0BuwMAAfABZgFDARADDwIOAQABvAIAAf8BbQHrAfEB9AHxBfAB8wHyAfcBEgHwAQAB8wEJ
C/8CAAH/AfAB7wHyAf8HAAH/AfMBGgH/EwAB9AESAewE7wHsAfAFAAH/AfQK8gHzAf8BAAH/AQcB/wHv AfAC8gHxAbwBBwH3AewB6wHqAewBvAG0AwAB9AHzAfIBmQEcAfEBuwGzAbQB/wG0AbMB8wIAAfQBEQEO
AfIB/wUAAf8B8gFSATgBGgQAAfQBCAwAAfAC7ALwAv8B9AGSAfAB7QQAAf8B8gHxAQgCvAHwAQgEGwLz AQ8BEAENAhABDwIOAe8CAAHwARIBvAHzAf8B7AETAhQBEwHqAfAB9AHxARIBkgEAAv8B8gL0AfMB8gHx
Av8BBwG8AewB7QHyAf8DAAH/AfABUgI4AZkEAAHyAU8BlwH0CQAB/wHsAW0D/wL0Av8BBwHzAQcDAAH0 AbwBBwH3AewBbQGKAfAFAAHzAZMBHAG8Af8B8gEJAbUBCQHzAf8BAAH/ARMBDgEQAg0CZQINARABDgEV
AfMBcgEoAS4BLwF4AS8ENQEbAfIB/wEAAfQBBwEUAQ8B7QH0Af8BAAH/AfIBMQE4AVkBdAH/BAAB8gIt Af8BAAHsAW0B8QH0Af8B7AEVAREBEAFDARQB8AH/AfIB7AHrAwAB/wHyAfQB/wH0AfMB8gHwAbwB7wGR
AU8B/wgAAeoBbQH0AbwD9AHzAfQBBwH0AZIBBwMAAfQB8wFyAigCmAIvAzUBGwHyAf8BAAH/AfQB7wET AbMB/wUAAfECmgGTAf8HAAHzAQ4EDQNmAkMBEAEOAfMBAAFtAewB8gH0Af8B6wERAg4BEAEVAfAB/wHz
ARQB9wH0Af8B8wFSAlkBmQH/BQAB8gIzAS0BTwG8Af8FAAH/Ae0BvAT0AfMB8gT0AfEBBwIAAfQB8wFy AfcB6gQAAf8B8gH0Af8C9AHzAfEBBwGzAfQGAAEaA5oB9AcAAfMBEAFDARUDZgNsARIBEwEUAfMBAAHr
AigB/wEIBS8BCAHyAf8DAAH/AQcBEgFDAe8BvAExATgBWQGZAf8GAAHyAjMCLQECAZgB/wQAAfAB7AH0 AewB8QH0Af8B7QFtARMCFQETAfAB/wHyAZIBbQUAAfQB8gP/AfQB8gG0AQkGAAH0AZoDGgEbBwAB9AJm
AfMC9AEHAfQBGgP0AfAB7QHsAgAB9AHzAXICKAH/AfQBUAEuAXgBUAEvAbwB8gH/BAAB/wEHAhIB7QFZ AmwB6gFsBW0B6gH/AQAB9wFtAfEB9AH/AfcB6wFtAxIB8AH0AfIC7AYAAfQB8wP/AQkB2wH/BQAB/wGZ
ATIB8wH/BwAB8gIzAS0CAgEnAXIB9AMAAQcB7AL0AvMB9AEfAbwE9AHtAe8BDgEAAfQB8wFyAigB9AL/ BRoHAAH/AewDrgHrAa4C7AGuAuwB7wIAAfMBbQHvAfQB/wEHAfcB7QPsAfEB8wG8AeoB7wcAAfQB8wH/
AbwB/wFQASgBvAHyAf8FAAH/Ae8B7AHwAfcBvAH/CAAB8gMtAgIBJwEhAUkB9AIAAbwBkgLzAfAC8wEH AfMB2wHzBgAB/wEcAhoBGwEaAZkIAAH/BOwE7QL3AfQDAAHtAW0B8AH0Bv8B9AHxAe0BbQHyBwAB/wH0
Ae0E8wHtAe8B/wEAAfQB8wFyAigBUAH0A/8BUAEoAbwB8gH/BQAB/wIHAewB6wEHAfMC/wYAAfEGTwFJ AfICCQgAAXMBmgG8ApkBkwkAAfQB7wT3Au8BBwH0BAAB8gFtAewB8QHzBPQB8wHxAZIBbQEHAf8JAAHz
AZgB/wIAAf8BBwHxAfMB8gHzAZMC8wEHAvMB8QHwAQcCAAH0AfMBcgMoAZgD/wFQASgBvAHyAf8EAAH/ AdsB9AgAAbwCbgIcAbwLAAHzAQcC7wG8AfMB/wYAAfEB6wFtAe8B8QLyAfEBvAHsAesB7wsAAfQBGQH/
AQcB8QHyAQcB7wHsAesB7AHvAfQB/wQAAfEGTwEIBQABBwHrAfMB7wHzARoD8wHwAfEB7AHzAf8CAAH0 CAAB/wEHAW4BHAEHAfQZAAHyAZIB6wTsAesB7AG8Af8YAAL/HQAB8wHvAuwB7wHxAf8HAAEaAZkBGwH/
AfMBcgIoAVAECAFKASgBvAHyAf8DAAH0AQcBvAHyAv8B8AHsAe0B7wLtAfQEAAHxAU8EcgHxAf8FAAHz AgAB/wH0ARoBmQH/AwAC/wHyBrwB8AK8AfQC/wEAAf8B8wHyAfMH8gLzAv8BAAH/AfEBCQEZAf8BAAH/
AfEB7AHyAfAD8wHyAbwB7AHxAe8DAAH0AfMBcgkoAbwB8gH/AgAB/wEHAfIB8wMAAfIBvAEHAbwC7wHx AfABCQHyAZgBAgEIBQABdAEyATcBSwHxAfQBdAExATgBMgHzBQAB7wHwBv8B8gGSAfMEAAETAW0G7AHt
BAAB8QFyAZcBcgFJAfQIAAEHAfMB6wHvAfcBBwHvAe0BbQHwAe0B9wHtAf8BAAH0AfMBHAlyAfEB8gL/ AewB6wHqAwABCQGKAbMBsgHzAQABuwKzAbIBTwFVAZgFAAF5AzgCNwM4ATEB8wIAAf8C9AHvAewC8wP0
AfMB7wG8AfMB/wMAAfQBBwHyAQcB9AH/AfQEAAHxAnIB7wH/CgAC8wG8Ae0C7AEHAfMBBwHyAbwB9AEH AfMB7wFtAfIB9AH/AgABBwP0AUoBKQIDA/QB8QIAAf8BuwGzAdQBswG7AfMBtAGzAXEBSQFPAVUBcgGY
AQAB/wHwCvMB8gH0AQAB/wIHAfMFAAH/Ae8B9AHvAfMB/wUAAfEBTwEIAf8NAAHzAbwBBwG8AfICAAHy AQgDAAGZBDgB+wM4ATEB9AIAAf8CBwHsARQCBwK8AgcB7AESAgcB8QIAAQcBHAFzAZkBSwIrAUwB8AJz
AfQBAAG8AQAC/wr0Av8BAAH/AfEB8gH/BQAB/wHyAfAB8wEHAfQFAAH/AfMXAALxHAAB/wHzAf8cAAH/ AQcCAAEJAYoBiwLUA4oBkAFyA5gBlwFPAS4DAAGZCDgBMQH2AgAB9ALxAewIFQESAfABvAHyAgABBwHv
AfADmAH0IAAF/wH0Cv8B9A3yAZEB7xAAEP8QAAHxAvQC/wHvA/8B8gHxAfQBCAG7AfABkQQAAQEBHgQA AQcBmQFLAisBTAEaA+8CAAGLAbMC1APaAtsBnQFyAZcBmAFyAZgBCAMAAZkEegJZAjgBMQH0AgAO9AHw
Af8BRQEBAwAB8wHwBfIC8QbyAfABAAG8ArQLtQH/AfIC9AL/Ae8D/wHyAfEBcgFxAZEBSQFyAwABAQH5 AfMCAAHvAZkBvAGZAUsBJAEqAUsBvAIHAe8CAAKzAtQD2gTbAZ0BCAFyAwAB/wGZAVgIegFZAXkB/wEA
AUcBCwIAAf8BHgH5ARcBAQIAAfIB8wP/AfMBuwK0AQkB9AT/AfABAAH3AUMBFQJKAUQBQwERA0MBFQFD AfQC8AH3Am0B6wPsAm0B6wLwAfICAAHvAZkBvAEHAUsBKgJLAfECmQEHAgAB9AEJArMB2wGzAbkBugGz
ARMB9AHyAvQC/wHvA/8B8gHxAUkC/wEHAXECAAGTAW8C+QFHAQsB/wELA/kBRQIAAfIB8wL/AfQBtAGz AbkB2wGdAZgBCAMAARoBWQt6AVIC/wHzAfQB7wgSAW0C9AHzAQAB8wH3A/MEGgPzAbwB8AH/AgAB8gGz
AgkCtAHxA/8B8AEAAfcBEQFDAkoBFQMQAhEBQwERAWYB9AHyBAcB7AG8AvACvAFJAfMB9AHxAXIDAAJv AdsBugG0AQABCQG0AdsBswGdAf8CAAH0AXkNegEaAf8BBwG8Ae8E6wHsA+sB7AG8AQcB8gEAAfIBEgEH
AiABRgEOAyABAQH/AgAB8gHzAv8CiwG0AgkBtAGLAa4D/wHwAQAB9wEQAUMCSgFEAREDEAMRARUB9AHy CPQB8wHrAQcB/wIAAf8BswLbAawB8wHyAbMC2wGzAfMB9AH/AfMBUgx6AXkBmQEAAu8D7AXtAewBEwHv
BLwBkgHwAvEB8AG8AUkB7wHwAewB7wQAAW8BTAUgAQEB/wMAAfIB8wH/AQcBhgGtAbQBCQG6AbMBrQGG AZIB8gIAAfQBEgEHBvIB8AESAQcDAAH/AYoBkALcAbMCiwGzAtwBswGLAbIBGQEAAfYBGwEaAZkGegGZ
AQcC/wHwAQAB9wIUAkoBFAERARABDwQOARUB9AHyAfQBBwEIAf8BBwH/AfIB/wHzAfEB8AFJAQ0B7QH/ ARoBGwH0Af8BAAHzAfIBBwG8AfAB8QHyAvEB8AG8AewB8wHyAf8DAAHyAeoB7wTyAfACbQHzAwAB8gGz
BQABbwFMAyABHwH/BAAB8gHzAf8BtQGGArQCswGtAosBrgL/AfEBAAHvAusBbQHqARIBFAEVAREBEAIP C9wBuQG7BQABGwF6ApoBegF5Af8HAALxAfME9AHzAfEB7QcAAfQBEgHvArwBBwETAesBvAH0AwAB8wG6
ARABFQH0AfIC8wEHAfQBBwH/AbwB/wHzAfED/wHyAf8EAAH/AR8DRgFvAUYBHwQAAfIB8wH/AbUBhgG7 AhkC3AIJARkBCQLcAwkFAAH/AXkCoAF6AfYIAALzBv8B9AG8CAAB8gESAZIBBwFtAQcB7wEHAfQDAAH/
AQkBtAGtAosBzwGuAv8B8QEAAQcBkwF0AXkCegJTAkwDKwFLAfQB8gHzAQcBvAH0AQcB/wHwAf8B8wHy ARkBugGzAhkBswK6AbMCCQGzAQkB9AYAAfYBegGgARoJAAH0CP8B8wkAAfQBEgEUAQcBAAH0AfMB/wUA
A/8B8wQAAf8BHwNGAXQCRgFvAR8DAAHyAfMB/wK1AgkBtAKLAYYBiwG1Av8B8QEAAQcBlAGaAqABegF1 Af8BsgEJARkBugEAAf8BsgEJARkBugkAARsBmgH/CQAB9AjwAfMKAAHzAbwB/woAAgkBuQEJAQAB/wG7
AlMETQFvAfQB8gG8AwcB9wG8BPAB8wH0Af8B8wMAAf8BHwNvAQEBbgF0Am8BFgEfAgAB8gHzAf8B8wG1 AQkBuQEJFQAK/xgAAfQB/wQAAfQB/wQAAf8M8gH0Af8HAAEHAewB6gFtAeoB7AG8EwAE/wH0AfMBBwHv
AQcBCQG0Ac8CiwGuAfQC/wHxAQABBwKUA5oDdQLjAhcBbwH0BfMBBwP0AfMB8gP/AfMDAAEaAUwCFgEf AfAB9AX/AQABkwNFBkYERQH0CQABbQETAewGAAL/CfYB/wUAAfQB8AH3ARQBEQIQBgAB/wFvAh8BRgYl
Af8BAAFvAxYBHwIAAfIB8wL/AfABtQEJAa4BtAGuAc8BvAP/AfEBAAEHBrcDlAOxAY4B9ALzAggB8wG8 AUYBJAEfAUUB8gMAAfQF8wFtAUMBkgUAAf8BmQFTCTIBdQH/AQAB/wEHAfAB8QH0Af8B8wIHAfIDAAH/
A/QB8wHyA/8B8wQAARoBTAEfAf8DAAFvARYBHwMAAvID8wG8ArUBrgG1AbwE8wHxAQABBwHPDLUB9ALz AgAB/wFvAR8BbwH0AXQBJQImAiUBGwGTAR8BRQHyAwAB7QERAUQBAQFEAhEBDwGSBQAB/wJTAZoBUwHD
AfIBBwHzAfAE8wHyA/QB8wUAARoB/wUAAZMEAAHyCfAC7wO1AfABAAG7A60DswK0BdUB9ALzAvAB8wHw AVkBwwFZBDIB9gEAAf8B8gHwAREB9AcAAfEBQwHzAQAB/wFvAR8BkwLzAXUCLAFNAfEB8wHwAUUBJAHy
BfMD9AHzEQAB9Am8AQcBvAMHAfIBAAHyBQkE3QQZAv8G8gfzAf8xAAFCAU0BPgcAAT4DAAEoAwABQAMA BAAB/wFFAR8BbgH/AesBDgHtBQAB/wEyAVMBGgFZAf8BWQH/AVkEMgH2AQAB9AHsARMBDwHyBwAB7wER
AUADAAEBAQABAQYAAQIWAAP/AQAB4QGDBgAB4AEDBgAB4AEDBgAB4AEDBgAB4AEDBgAB4AEDBgABgAEB ARUB8QH/AW8BHwEkAZMB8gHxAXUBLAG8AfEBvAEkAR8BJAHyBQABbwEgAZMBAAFtAQAB7QUAAf8DMgGa
BgABgBcAAYAHAAH4AQ8GAAH4AR8GAAH8AT8GAAH+AT8GAAL/BgABgAEAAf4BAwL/AYABAAGAAQAB/wGP AcMBWQH/ATgEMgH2AQAB9AEOAeoBEAHyBwAB7wFDARUBkgH/AW8CHwEkAZMB8QHwArwBBwFGAx8B8gUA
AcABAwHgAT8CAAHgAQ8BgAEBAQABOwIAAeABDwGAAQEBBwHxAgAB8AEPAYABAQEHAfACAAH4AY8BgAEB AW8BIAGTAQABbQEAAe0FAAH/ATIBUwEaAZoBUwGaAXoFMgH2AQAB9AHqAesBQwHyBwAB7wETAeoBBwH/
AQcB8AIAAfgBjwGAAQEBBwHwAgAB+AGPAYABAQGHAfACAAHwAY4BgAEBAYcB8AIAAfABjgGAAQEBjwH4 AW8BAQEfASQBRgEcAfEB8AEHASUCHwEBAR8B8gUAAW8BIAGTAQAB6wEQAe0FAAH/ASwCMgFZAfYBGgFT
AYABAAHwAYgBgAEBAY8B+AGAAQAB8AEAAYABAQHPAfsBgAEAATABAAGAAQEC4wGAAQABGAHPAYABAQHg BTIB9gIAAQcB7QEUAfIHAAHvAW0B7AHwAf8BbwFFAUYBTAFvA/EB8AGTAW8BRgJFAfIEAAH/AW4BIAGT
AQMBgAIAAQ8BwAEDAfABBwL/AQABDwL/Af4BPwIAAeABAwEHAfAC/wHgAQ8BgAEBAQMB4AHzAf8BwAEH AQAB6wEPAZIDAAHzAQAB/wFTAXoBwwEaAZoBegFZAnoDUwH/AgAB8gG8ARIB8wcAAQcB6wHwAfMB/wRv
AYABAAEBAcAB8AH/AYABAwGAAQACgAHwAX8BgAEDAYABAAGAAQEB8AEfAQABAQGAAQAB4AEDAfABDwEA AfEB8gG8AQcB8QHyAZMDbwHyBAAB8wELAR8BkwEAAesBEQGSAwABEwEAAf8BUwN1BHoEdQH/AgAB9AG8
AQEBgAEAAfABBwHwAQcCAAGAAQAB+AEPAfABAwIAAYABAAH4AQMB8AEDAQABAQGAAQAB8AEAAfABDwGA Af8JAAH/Ae8B/wEAAm8BkwLzAbwBkwFvAQcB8gHzAZMCbwHzBAAB9AEPAQEBkwEAAesBQwGSAQAB/wG8
AQEBgAEAAeABAAHwAQ8BgAEDAYABAAHDAYAB8AE/AcABAAGAAQABAwGAAfABfwHgAQABgAEBAQ8BgQHw AREBAAH/AVMKegF1Af8CAAH/AZIB9AkAAfIB7wH/AQACbwG8AfMB8ARvAe8C8wGTAW8B8wQAAf8BEQEQ
Af8B+AEyAYABAQEPAYEB8wL/AfkD/wHjA/8BwAT/BAAC/wIAAv8CAAHzAccCAAGAAwAB4QGDAgABgAMA AUMBbQFDAhUBbQEUAREBFAEAAf8BUwp6AXUB/wMAAf8B8gkAAfIDAAOTAQcGkwHvA5MB8wH0AW8CAAH/
AcABAwIAAYADAAHgAQMCAAGAAwAB8AEHAgABgAMAAfgBDwIAAYADAAHwAQ8CAAGAAgABAQHgAQcCAAGA AhIBbQPtAUQC7QHsAZIBAAH/AXUKmgF6Af8EAAG8Ae8B/wUAAfQB7AHxAwAOkwHzAf8BRQH/AgABHAHt
AgABAQHAAQMCAAGAAgABAQHAAYMCAAGAAgABAQHhAccCAAGAAgABAQHzAe8CAAGAAgABAQL/AgABgAIA Ae8CAAHxAUUFAAH/ARsBegl1ARoB/wQAAf8CQwG8Av8B9AEHARABbQH/AwAB8wyTARoC/wJuAu8BbgH3
AQEG/ws= 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=
</value> </value>
</data> </data>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
@ -4495,344 +4553,6 @@
bPHp06fm8+fPLb58+dJ8/fq1EsCKioqKioqK94mIvEWICJ0jInVgLKnLiV1O8MYQu5zcQeyc3IFv374p bPHp06fm8+fPLb58+dJ8/fq1EsCKioqKioqK94mIvEWICJ0jInVgLKnLiV1O8MYQu5zcQeyc3IFv374p
vn//3vzyyy8tfvz40fz8+bMSwIqKioqKioq3h4jIDWEMqcsJ3a6kbheLnZO7yGqXE7uS3EHsnNyBX3/9 vn//3vzyyy8tfvz40fz8+bMSwIqKioqKioq3h4jIDWEMqcsJ3a6kbheLnZO7yGqXE7uS3EHsnNyBX3/9
tfntt99a/P77782//vUvxR9//NH8f2wEO4ZCaXfjAAAAAElFTkSuQmCC tfntt99a/P77782//vUvxR9//NH8f2wEO4ZCaXfjAAAAAElFTkSuQmCC
</value>
</data>
<data name="pictureBox3.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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
wIg2Hr6dReMAAAAASUVORK5CYII=
</value>
</data>
<data name="pb_audioCAPstatus.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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==
</value>
</data>
<data name="pb_audioPBstatus.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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==
</value> </value>
</data> </data>
<data name="pictureBox1.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="pictureBox1.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
@ -5212,6 +4932,344 @@
aYgdn68JGvaNzZ/DfJC2+oBdKl1D4stDJVAhQRqP94en3ED2iI/yx3xMeuiA8Rf9gJbR9SS2Mtb7rcNC aYgdn68JGvaNzZ/DfJC2+oBdKl1D4stDJVAhQRqP94en3ED2iI/yx3xMeuiA8Rf9gJbR9SS2Mtb7rcNC
Cz0+qGY8MG1WgCmX/ZGO5TVxpBwWiawcN4YbvosRfVQbgoEnpdo4ey1Xb/lPggO2YZ6pjgVULJdNWmv+ Cz0+qGY8MG1WgCmX/ZGO5TVxpBwWiawcN4YbvosRfVQbgoEnpdo4ey1Xb/lPggO2YZ6pjgVULJdNWmv+
GRYW3wHoVCJ7F4lIiQAAAABJRU5ErkJggg== GRYW3wHoVCJ7F4lIiQAAAABJRU5ErkJggg==
</value>
</data>
<data name="pictureBox3.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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
wIg2Hr6dReMAAAAASUVORK5CYII=
</value>
</data>
<data name="pb_audioCAPstatus.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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==
</value>
</data>
<data name="pb_audioPBstatus.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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==
</value> </value>
</data> </data>
<data name="richTextBox1.Text" xml:space="preserve"> <data name="richTextBox1.Text" xml:space="preserve">
@ -5265,7 +5323,7 @@ VIP user: DP0GVN: https://www.awi.de/expedition/stationen/neumayer-station-iii.h
<metadata name="timer_searchmodem.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> <metadata name="timer_searchmodem.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>482, 17</value> <value>482, 17</value>
</metadata> </metadata>
<data name="pb_rxsync.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="pb_rxsignal.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAL iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAL
EwAACxMBAJqcGAAAA3xJREFUSEulVstL1FEYvfmYMR+LisJoU5QEiVipSLQQn6RjNMk4ig+wCJSpDCzU EwAACxMBAJqcGAAAA3xJREFUSEulVstL1FEYvfmYMR+LisJoU5QEiVipSLQQn6RjNMk4ig+wCJSpDCzU
@ -5286,7 +5344,7 @@ VIP user: DP0GVN: https://www.awi.de/expedition/stationen/neumayer-station-iii.h
f/5tMeY3ET3ttnz8RoQAAAAASUVORK5CYII= f/5tMeY3ET3ttnz8RoQAAAAASUVORK5CYII=
</value> </value>
</data> </data>
<data name="pb_rxsignal.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="pb_rxsync.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAL iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAL
EwAACxMBAJqcGAAAA3xJREFUSEulVstL1FEYvfmYMR+LisJoU5QEiVipSLQQn6RjNMk4ig+wCJSpDCzU EwAACxMBAJqcGAAAA3xJREFUSEulVstL1FEYvfmYMR+LisJoU5QEiVipSLQQn6RjNMk4ig+wCJSpDCzU

Binary file not shown.

After

Width:  |  Height:  |  Size: 954 B

View File

@ -60,6 +60,26 @@ namespace oscardata.Properties {
} }
} }
/// <summary>
/// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap amsat_dl_logo {
get {
object obj = ResourceManager.GetObject("amsat_dl_logo", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap answer {
get {
object obj = ResourceManager.GetObject("answer", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary> /// <summary>
/// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
/// </summary> /// </summary>
@ -150,6 +170,16 @@ namespace oscardata.Properties {
} }
} }
/// <summary>
/// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap clearscreen {
get {
object obj = ResourceManager.GetObject("clearscreen", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary> /// <summary>
/// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
/// </summary> /// </summary>
@ -160,6 +190,16 @@ namespace oscardata.Properties {
} }
} }
/// <summary>
/// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap foht {
get {
object obj = ResourceManager.GetObject("foht", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary> /// <summary>
/// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
/// </summary> /// </summary>
@ -180,6 +220,16 @@ namespace oscardata.Properties {
} }
} }
/// <summary>
/// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap home_icon {
get {
object obj = ResourceManager.GetObject("home_icon", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary> /// <summary>
/// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
/// </summary> /// </summary>
@ -300,6 +350,26 @@ namespace oscardata.Properties {
} }
} }
/// <summary>
/// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap rtty {
get {
object obj = ResourceManager.GetObject("rtty", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap ryry_icon {
get {
object obj = ResourceManager.GetObject("ryry_icon", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary> /// <summary>
/// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
/// </summary> /// </summary>
@ -370,6 +440,16 @@ namespace oscardata.Properties {
} }
} }
/// <summary>
/// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap start_icon {
get {
object obj = ResourceManager.GetObject("start_icon", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary> /// <summary>
/// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
/// </summary> /// </summary>
@ -380,6 +460,16 @@ namespace oscardata.Properties {
} }
} }
/// <summary>
/// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap stop_icon {
get {
object obj = ResourceManager.GetObject("stop_icon", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary> /// <summary>
/// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
/// </summary> /// </summary>
@ -420,6 +510,16 @@ namespace oscardata.Properties {
} }
} }
/// <summary>
/// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap user_icon {
get {
object obj = ResourceManager.GetObject("user_icon", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary> /// <summary>
/// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
/// </summary> /// </summary>
@ -439,5 +539,15 @@ namespace oscardata.Properties {
return ((System.Drawing.Bitmap)(obj)); return ((System.Drawing.Bitmap)(obj));
} }
} }
/// <summary>
/// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap voice_icon {
get {
object obj = ResourceManager.GetObject("voice_icon", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
} }
} }

View File

@ -232,4 +232,37 @@
<data name="playbackicon" type="System.Resources.ResXFileRef, System.Windows.Forms"> <data name="playbackicon" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>playbackicon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> <value>playbackicon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data> </data>
<data name="rtty" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>rtty.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="amsat_dl_logo" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>amsat_dl_logo.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="clearscreen" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>clearscreen.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="foht" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>foht.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="home_icon" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>home-icon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="ryry_icon" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>ryry-icon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="voice_icon" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>voice-icon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="answer" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>answer.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="start_icon" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>start-icon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="stop_icon" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>stop-icon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="user_icon" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>user-icon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root> </root>

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 554 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 554 B

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -39,6 +39,10 @@ namespace oscardata
public static Byte tuning = 27; public static Byte tuning = 27;
public static Byte marker = 28; public static Byte marker = 28;
public static Byte setfreq = 29; 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 // frame sequence, modem needs that for i.e. sending a preamble
public static Byte FirstFrame = 0; public static Byte FirstFrame = 0;
@ -51,6 +55,7 @@ namespace oscardata
public static Byte udp_bc = 3; public static Byte udp_bc = 3;
public static Byte udp_fft = 4; public static Byte udp_fft = 4;
public static Byte udp_iq = 5; public static Byte udp_iq = 5;
public static Byte udp_rtty_rx = 6;
// global static variables // global static variables
public static bool running = true; public static bool running = true;
@ -85,6 +90,7 @@ namespace oscardata
public static Color WindowBackColor; public static Color WindowBackColor;
public static String[] langstr; public static String[] langstr;
public static int tuning_active = 0; public static int tuning_active = 0;
public static int tune_frequency = 1500;
public static String[] getOwnIPs() public static String[] getOwnIPs()
{ {
@ -435,5 +441,24 @@ namespace oscardata
} }
catch { } 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;
}
} }
} }

View File

@ -64,12 +64,6 @@
<Compile Include="Form1.Designer.cs"> <Compile Include="Form1.Designer.cs">
<DependentUpon>Form1.cs</DependentUpon> <DependentUpon>Form1.cs</DependentUpon>
</Compile> </Compile>
<Compile Include="Form2_showtext.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Form2_showtext.Designer.cs">
<DependentUpon>Form2_showtext.cs</DependentUpon>
</Compile>
<Compile Include="imagehandler.cs" /> <Compile Include="imagehandler.cs" />
<Compile Include="KmProgressBar.cs"> <Compile Include="KmProgressBar.cs">
<SubType>Component</SubType> <SubType>Component</SubType>
@ -82,9 +76,6 @@
<EmbeddedResource Include="Form1.resx"> <EmbeddedResource Include="Form1.resx">
<DependentUpon>Form1.cs</DependentUpon> <DependentUpon>Form1.cs</DependentUpon>
</EmbeddedResource> </EmbeddedResource>
<EmbeddedResource Include="Form2_showtext.resx">
<DependentUpon>Form2_showtext.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx"> <EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator> <Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput> <LastGenOutput>Resources.Designer.cs</LastGenOutput>
@ -152,6 +143,17 @@
<None Include="Properties\playback.png" /> <None Include="Properties\playback.png" />
<None Include="Properties\playbackicon.png" /> <None Include="Properties\playbackicon.png" />
<None Include="Properties\captureicon.png" /> <None Include="Properties\captureicon.png" />
<None Include="Properties\rtty.png" />
<None Include="Properties\amsat_dl_logo.png" />
<None Include="Properties\clearscreen.png" />
<None Include="Properties\foht.png" />
<None Include="Properties\home-icon.png" />
<None Include="Properties\ryry-icon.png" />
<None Include="Properties\voice-icon.png" />
<None Include="Properties\user-icon.png" />
<None Include="Properties\answer.png" />
<None Include="Properties\stop-icon.png" />
<None Include="Properties\start-icon.png" />
<Content Include="Satellite-icon.ico" /> <Content Include="Satellite-icon.ico" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

View File

@ -31,6 +31,7 @@ namespace oscardata
static UdpQueue uq_ctrl = new UdpQueue(); static UdpQueue uq_ctrl = new UdpQueue();
static UdpQueue uq_fft = new UdpQueue(); static UdpQueue uq_fft = new UdpQueue();
static UdpQueue uq_iq = new UdpQueue(); static UdpQueue uq_iq = new UdpQueue();
static UdpQueue uq_rtty_rx = new UdpQueue();
public static int searchtimeout = 0; public static int searchtimeout = 0;
static String last_audiodevstring = ""; static String last_audiodevstring = "";
@ -150,6 +151,10 @@ namespace oscardata
statics.RXinSync = b[3]; statics.RXinSync = b[3];
statics.maxRXlevel = b[4]; statics.maxRXlevel = b[4];
statics.maxTXlevel = b[5]; 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]; Byte[] b1 = new byte[b.Length - 6];
Array.Copy(b, 6, b1, 0, b1.Length); Array.Copy(b, 6, b1, 0, b1.Length);
drawFftBitmap(b1); drawFftBitmap(b1);
@ -175,6 +180,11 @@ namespace oscardata
} }
drawBitmap(re, im); drawBitmap(re, im);
} }
if (rxtype == statics.udp_rtty_rx)
{
uq_rtty_rx.Add(b);
}
} }
} }
catch { } catch { }
@ -267,19 +277,22 @@ namespace oscardata
static Font fnt = new Font("Verdana", 9.0f); static Font fnt = new Font("Verdana", 9.0f);
static Font smallfnt = new Font("Verdana", 7.0f); static Font smallfnt = new Font("Verdana", 7.0f);
static Pen penyl = new Pen(Brushes.Yellow, 1); static Pen penyl = new Pen(Brushes.Yellow, 1);
static Pen pengn = new Pen(Brushes.LightGreen, 3);
static void drawFftBitmap(Byte[] b1) static void drawFftBitmap(Byte[] b1)
{ {
if(!bmf) int yl = ffth - 20;
int yh = 20;
if (!bmf)
{ {
// pre-draw background // pre-draw background
bmf = true; bmf = true;
int yl = ffth - 20;
int yh = 20;
Pen pen = new Pen(Brushes.Navy, 1); Pen pen = new Pen(Brushes.Navy, 1);
Pen pensolid = 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.DashPattern = new float[] { 1.0F, 2.0F, 1.0F, 2.0F };
Pen penred = new Pen(Brushes.Red, 1); Pen penred = new Pen(Brushes.Red, 1);
Pen penred2 = new Pen(Brushes.Red, 2);
using (Graphics gr = Graphics.FromImage(bmskala)) using (Graphics gr = Graphics.FromImage(bmskala))
{ {
@ -289,7 +302,7 @@ namespace oscardata
for (int x = 10; x <= 390; x += 10) for (int x = 10; x <= 390; x += 10)
gr.DrawLine(pen, x, yl, x, yh); 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(penred, 150, yl, 150, yh);
gr.DrawLine(pensolid, 20, yl, 20, yh); gr.DrawLine(pensolid, 20, yl, 20, yh);
gr.DrawLine(pensolid, 280, yl, 280, yh); gr.DrawLine(pensolid, 280, yl, 280, yh);
@ -322,6 +335,15 @@ namespace oscardata
gr.FillRectangle(bgcol, 0, 0, bm.Width, bm.Height); gr.FillRectangle(bgcol, 0, 0, bm.Width, bm.Height);
// scala // scala
gr.DrawImage(bmskala,16,2); 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 // screws at the 4 corners
Bitmap screw = new Bitmap(Properties.Resources.schraube); Bitmap screw = new Bitmap(Properties.Resources.schraube);
@ -463,6 +485,12 @@ namespace oscardata
if (uq_iq.Count() == 0) return false; if (uq_iq.Count() == 0) return false;
return true; 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 // this class is a thread safe queue wich is used