mirror of
https://github.com/dj0abr/SSB_HighSpeed_Modem.git
synced 2025-02-03 09:44:05 -05:00
222 lines
4.5 KiB
C++
Executable File
222 lines
4.5 KiB
C++
Executable File
|
|
#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
|
|
*/
|
|
}
|
|
} |