Portapack应用开发教程(十二) SSTV接收机 D

    科技2022-08-07  106

     接下来我又想用alsa声卡实现接收,这样可以在电脑上播放wav文件,然后接收声波并解调解码。

    我发现这样比直接解调wav更难,连续1300Hz以下只能收到3个点,不能像之前那样收到29个。

    所以我把对1300Hz的行同步信号检测功能也去掉了。直接根据频率来画亮度就行。

    另外这个程序还把频率也打印出来了,可以直接用正弦波信号源进行测试。

    我在gnuradio里画了一个流图用一个可变频率的cosine signal source接到audio sink上就能发出我要的频率的声波,但是gnuradio有时候会有bug发出的声音频点不纯净。

    decode_draw_realtime.cpp

    #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <string.h> #include <math.h> #include <complex.h> #include <time.h> #include <iostream> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <sys/stat.h> #include <fcntl.h> #include <sys/mman.h> #include "alsa.h" using namespace cv; using namespace std; struct pcm *pcm; Mat frame = Mat::zeros(67, 519, CV_8UC1); int SAMPLERATE = 8000; double round(double r) { return (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5); } double FIRLPCoeffs[51] = { +0.0001082461, +0.0034041195, +0.0063570207, +0.0078081648, +0.0060550614, -0.0002142384, -0.0104500335, -0.0211855480, -0.0264527776, -0.0201269304, +0.0004419626, +0.0312014771, +0.0606261038, +0.0727491887, +0.0537028370, -0.0004362161, -0.0779387981, -0.1511168919, -0.1829049634, -0.1390189257, -0.0017097774, +0.2201896764, +0.4894395006, +0.7485289338, +0.9357596142, +1.0040320616, +0.9357596142, +0.7485289338, +0.4894395006, +0.2201896764, -0.0017097774, -0.1390189257, -0.1829049634, -0.1511168919, -0.0779387981, -0.0004362161, +0.0537028370, +0.0727491887, +0.0606261038, +0.0312014771, +0.0004419626, -0.0201269304, -0.0264527776, -0.0211855480, -0.0104500335, -0.0002142384, +0.0060550614, +0.0078081648, +0.0063570207, +0.0034041195, +0.0001082461, }; double xvFIRLP1[51]; double FIRLowPass1(double sampleIn) { for (int i = 0; i < 50; i++) xvFIRLP1[i] = xvFIRLP1[i+1]; xvFIRLP1[50] = sampleIn / 5.013665674; double sum = 0; for (int i = 0; i <= 50; i++) sum += (FIRLPCoeffs[i] * xvFIRLP1[i]); return sum; } double xvFIRLP2[51]; double FIRLowPass2(double sampleIn) { for (int i = 0; i < 50; i++) xvFIRLP2[i] = xvFIRLP2[i+1]; xvFIRLP2[50] = sampleIn / 5.013665674; double sum = 0; for (int i = 0; i <= 50; i++) sum += (FIRLPCoeffs[i] * xvFIRLP2[i]); return sum; } // moving average double xvMA1[9]; double yvMA1prev = 0; double noiseReductionFilter1(double sampleIn) { for (int i = 0; i < 8; i++) xvMA1[i] = xvMA1[i+1]; xvMA1[8] = sampleIn; yvMA1prev = yvMA1prev+xvMA1[8]-xvMA1[0]; return yvMA1prev; } double xvMA2[9]; double yvMA2prev = 0; double noiseReductionFilter2(double sampleIn) { for (int i = 0; i < 8; i++) xvMA2[i] = xvMA2[i+1]; xvMA2[8] = sampleIn; yvMA2prev = yvMA2prev+xvMA2[8]-xvMA2[0]; return yvMA2prev; } double oscPhase = 0; double realPartPrev = 0; double imaginaryPartPrev = 0; int fmDemodulateLuminance(double sample) { oscPhase += (2 * M_PI * 2000) / SAMPLERATE; double realPart = cos(oscPhase) * sample; double imaginaryPart = sin(oscPhase) * sample; if (oscPhase >= 2 * M_PI) oscPhase -= 2 * M_PI; realPart = FIRLowPass1(realPart); imaginaryPart = FIRLowPass2(imaginaryPart); realPart = noiseReductionFilter1(realPart); imaginaryPart = noiseReductionFilter2(imaginaryPart); sample = (imaginaryPart*realPartPrev-realPart*imaginaryPartPrev)/(realPart*realPart+imaginaryPart*imaginaryPart); realPartPrev = realPart; imaginaryPartPrev = imaginaryPart; sample = sample - 0.2335 - 0.694; int luminance = (int)round((sample/0.617)*800); luminance = 800-luminance; return luminance; } int main(int argc, char **argv) { char *pcm_name; int nframes = 61282; int lineCount = 0; int sampleBuffer = 0; int lineIndex = 0; pcm_name = "default"; if (!open_alsa_read(&pcm, pcm_name)) return 1; double frequency_multiply; int i = 0; while (true) { static short *pcm_buff; pcm_buff = (short *)malloc(sizeof(short) * 1); if (!read_alsa(pcm, pcm_buff, 1)) { free(pcm_buff); return 0; } frequency_multiply = fmDemodulateLuminance(((double)pcm_buff[0]) / 32768.0); cout << "i: " << i << " freq: " << frequency_multiply << endl; int pixel; if (frequency_multiply < 1500) { pixel = 0; } else if (frequency_multiply > 2300) { pixel = 255; } else { pixel = int(((frequency_multiply - 1500.0)/800.0)*255.0); } frame.at<uchar>(lineCount, lineIndex) = pixel; cout << "pixel: " << pixel << endl; lineIndex = lineIndex + 1; if (lineIndex == 490+29) { lineCount = lineCount + 1; lineIndex = 0; imshow("frame", frame); if (waitKey(5) == 'q') { } } if (lineCount == 67) { lineCount = 0; } i = i + 1; if (i > nframes- 1470) i = 0; } return 0; }

    alsa.cpp

    #include <stdio.h> #include <stdlib.h> #include <alsa/asoundlib.h> #include "alsa.h" struct alsa { struct pcm base; snd_pcm_t *pcm; int index; int frames; int r; int c; }; int read_alsa(struct pcm *pcm, short *buff, int frames) { struct alsa *alsa = (struct alsa *)(pcm->data); int got = 0; while (0 < frames) { while ((got = snd_pcm_readi(alsa->pcm, buff, frames)) < 0) if (snd_pcm_prepare(alsa->pcm) < 0) return 0; buff += got * alsa->c; frames -= got; } return 1; } int open_alsa_read(struct pcm **p, char *name) { snd_pcm_t *pcm; if (snd_pcm_open(&pcm, name, SND_PCM_STREAM_CAPTURE, 0) < 0) { fprintf(stderr, "Error opening PCM device %s\n", name); return 0; } snd_pcm_hw_params_t *params; snd_pcm_hw_params_alloca(¶ms); if (snd_pcm_hw_params_any(pcm, params) < 0) { fprintf(stderr, "Can not configure this PCM device.\n"); snd_pcm_close(pcm); return 0; } if (snd_pcm_hw_params_set_access(pcm, params, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) { fprintf(stderr, "Error setting access.\n"); snd_pcm_close(pcm); return 0; } if (snd_pcm_hw_params_set_format(pcm, params, SND_PCM_FORMAT_S16_LE) < 0) { fprintf(stderr, "Error setting S16_LE format.\n"); snd_pcm_close(pcm); return 0; } if (snd_pcm_hw_params_set_rate_resample(pcm, params, 0) < 0) { fprintf(stderr, "Error disabling resampling.\n"); snd_pcm_close(pcm); return 0; } unsigned rate_min = 8000; int dir_min = 0; if (snd_pcm_hw_params_set_rate_min(pcm, params, &rate_min, &dir_min) < 0 || rate_min < 8000) { fprintf(stderr, "Error setting min rate.\n"); snd_pcm_close(pcm); return 0; } if (snd_pcm_hw_params(pcm, params) < 0) { fprintf(stderr, "Error setting HW params.\n"); snd_pcm_close(pcm); return 0; } unsigned int rate = 0; if (snd_pcm_hw_params_get_rate(params, &rate, 0) < 0) { fprintf(stderr, "Error getting rate.\n"); snd_pcm_close(pcm); return 0; } unsigned int channels = 0; if (snd_pcm_hw_params_get_channels(params, &channels) < 0) { fprintf(stderr, "Error getting channels.\n"); snd_pcm_close(pcm); return 0; } struct alsa *alsa = (struct alsa *)malloc(sizeof(struct alsa)); alsa->base.rw = read_alsa; alsa->base.data = (void *)alsa; alsa->pcm = pcm; alsa->r = rate; alsa->c = channels; alsa->frames = 0; *p = &(alsa->base); return 1; }

    alsa.h

    struct pcm { int (*rw)(struct pcm *, short *, int); void *data; }; int read_alsa(struct pcm *pcm, short *buff, int frames); int open_alsa_read(struct pcm **, char *);

     

    g++ decode_draw_realtime.cpp alsa.cpp -o decode -lm -lasound `pkg-config --cflags --libs opencv`

    上面程序的演示视频:

    https://www.bilibili.com/video/bv1y54y1y7BF

     

    声波发射和接收搞定后就是时候考虑无线电收发了。

    我先用stdout stdin的方式。把hackrf_fm程序和这个alsa解调程序(要改为stdin输入)连了起来。这时候信号发射部分必须要用portapack不能用gnuradio+hackrf了,不然有问题。portapack没有robot8的发射功能,但是可以用其它sstv制式发射,也能看到点东西,另外可以用signal generator来发射单音信号,并且在terminal上看解出来的频率是否相符。

    decode_hackrf.cpp

    #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <string.h> #include <math.h> #include <complex.h> #include <time.h> #include <iostream> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <sys/stat.h> #include <fcntl.h> #include <sys/mman.h> #include "alsa.h" using namespace cv; using namespace std; struct pcm *pcm; Mat frame = Mat::zeros(67, 519, CV_8UC1); int SAMPLERATE = 8000; double round(double r) { return (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5); } double FIRLPCoeffs[51] = { +0.0001082461, +0.0034041195, +0.0063570207, +0.0078081648, +0.0060550614, -0.0002142384, -0.0104500335, -0.0211855480, -0.0264527776, -0.0201269304, +0.0004419626, +0.0312014771, +0.0606261038, +0.0727491887, +0.0537028370, -0.0004362161, -0.0779387981, -0.1511168919, -0.1829049634, -0.1390189257, -0.0017097774, +0.2201896764, +0.4894395006, +0.7485289338, +0.9357596142, +1.0040320616, +0.9357596142, +0.7485289338, +0.4894395006, +0.2201896764, -0.0017097774, -0.1390189257, -0.1829049634, -0.1511168919, -0.0779387981, -0.0004362161, +0.0537028370, +0.0727491887, +0.0606261038, +0.0312014771, +0.0004419626, -0.0201269304, -0.0264527776, -0.0211855480, -0.0104500335, -0.0002142384, +0.0060550614, +0.0078081648, +0.0063570207, +0.0034041195, +0.0001082461, }; double xvFIRLP1[51]; double FIRLowPass1(double sampleIn) { for (int i = 0; i < 50; i++) xvFIRLP1[i] = xvFIRLP1[i+1]; xvFIRLP1[50] = sampleIn / 5.013665674; double sum = 0; for (int i = 0; i <= 50; i++) sum += (FIRLPCoeffs[i] * xvFIRLP1[i]); return sum; } double xvFIRLP2[51]; double FIRLowPass2(double sampleIn) { for (int i = 0; i < 50; i++) xvFIRLP2[i] = xvFIRLP2[i+1]; xvFIRLP2[50] = sampleIn / 5.013665674; double sum = 0; for (int i = 0; i <= 50; i++) sum += (FIRLPCoeffs[i] * xvFIRLP2[i]); return sum; } // moving average double xvMA1[9]; double yvMA1prev = 0; double noiseReductionFilter1(double sampleIn) { for (int i = 0; i < 8; i++) xvMA1[i] = xvMA1[i+1]; xvMA1[8] = sampleIn; yvMA1prev = yvMA1prev+xvMA1[8]-xvMA1[0]; return yvMA1prev; } double xvMA2[9]; double yvMA2prev = 0; double noiseReductionFilter2(double sampleIn) { for (int i = 0; i < 8; i++) xvMA2[i] = xvMA2[i+1]; xvMA2[8] = sampleIn; yvMA2prev = yvMA2prev+xvMA2[8]-xvMA2[0]; return yvMA2prev; } double oscPhase = 0; double realPartPrev = 0; double imaginaryPartPrev = 0; int fmDemodulateLuminance(double sample) { oscPhase += (2 * M_PI * 2000) / SAMPLERATE; double realPart = cos(oscPhase) * sample; double imaginaryPart = sin(oscPhase) * sample; if (oscPhase >= 2 * M_PI) oscPhase -= 2 * M_PI; realPart = FIRLowPass1(realPart); imaginaryPart = FIRLowPass2(imaginaryPart); realPart = noiseReductionFilter1(realPart); imaginaryPart = noiseReductionFilter2(imaginaryPart); sample = (imaginaryPart*realPartPrev-realPart*imaginaryPartPrev)/(realPart*realPart+imaginaryPart*imaginaryPart); realPartPrev = realPart; imaginaryPartPrev = imaginaryPart; sample = sample - 0.2335 - 0.694; int luminance = (int)round((sample/0.617)*800); luminance = 800-luminance; return luminance; } int main(int argc, char **argv) { int nframes = 61282; int lineCount = 0; int sampleBuffer = 0; int lineIndex = 0; double frequency_multiply; int i = 0; while (true) { static short *pcm_buff; pcm_buff = (short *)malloc(sizeof(short) * 1); fread(pcm_buff, sizeof(int16_t), 1, stdin); frequency_multiply = fmDemodulateLuminance(((double)pcm_buff[0]) / 32768.0); cout << "i: " << i << " freq: " << frequency_multiply << endl; int pixel; if (frequency_multiply < 1500) { pixel = 0; } else if (frequency_multiply > 2300) { pixel = 255; } else { pixel = int(((frequency_multiply - 1500.0)/800.0)*255.0); } frame.at<uchar>(lineCount, lineIndex) = pixel; cout << "pixel: " << pixel << endl; lineIndex = lineIndex + 1; if (lineIndex == 490+29) { lineCount = lineCount + 1; lineIndex = 0; imshow("frame", frame); if (waitKey(5) == 'q') { } } if (lineCount == 67) { lineCount = 0; } i = i + 1; if (i > nframes- 1470) i = 0; } return 0; } g++ decode_hackrf.cpp -o decode_hackrf -lm `pkg-config --cflags --libs opencv` ./hackrf_fm | ./decode_hackrf

    下面是把hackrf解调和decode解码合并为一个程序的代码

    combine.cpp

    #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <string.h> #include <math.h> #include <complex.h> #include <time.h> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <signal.h> #include <unistd.h> #include <pthread.h> #include <libhackrf/hackrf.h> #include <iostream> using namespace cv; using namespace std; struct pcm *pcm; Mat frame = Mat::zeros(67, 519, CV_8UC1); int lineCount = 0; int lineIndex = 0; int SAMPLERATE = 8000; #define MAXIMUM_BUF_LENGTH (16 * 16384) static volatile bool do_exit = false; hackrf_device *device; uint32_t freq; uint32_t hardware_sample_rate; uint16_t buf16[MAXIMUM_BUF_LENGTH]; int16_t lowpassed[MAXIMUM_BUF_LENGTH]; int lp_len; int rate_in; int rate_out; int rate_out2; int16_t result_demod[MAXIMUM_BUF_LENGTH]; int result_demod_len; int now_r, now_j; int pre_r, pre_j; int prev_index; int now_lpr; int prev_lpr_index; FILE *file; int downsample; double round(double r) { return (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5); } double FIRLPCoeffs[51] = { +0.0001082461, +0.0034041195, +0.0063570207, +0.0078081648, +0.0060550614, -0.0002142384, -0.0104500335, -0.0211855480, -0.0264527776, -0.0201269304, +0.0004419626, +0.0312014771, +0.0606261038, +0.0727491887, +0.0537028370, -0.0004362161, -0.0779387981, -0.1511168919, -0.1829049634, -0.1390189257, -0.0017097774, +0.2201896764, +0.4894395006, +0.7485289338, +0.9357596142, +1.0040320616, +0.9357596142, +0.7485289338, +0.4894395006, +0.2201896764, -0.0017097774, -0.1390189257, -0.1829049634, -0.1511168919, -0.0779387981, -0.0004362161, +0.0537028370, +0.0727491887, +0.0606261038, +0.0312014771, +0.0004419626, -0.0201269304, -0.0264527776, -0.0211855480, -0.0104500335, -0.0002142384, +0.0060550614, +0.0078081648, +0.0063570207, +0.0034041195, +0.0001082461, }; double xvFIRLP1[51]; double FIRLowPass1(double sampleIn) { for (int i = 0; i < 50; i++) xvFIRLP1[i] = xvFIRLP1[i+1]; xvFIRLP1[50] = sampleIn / 5.013665674; double sum = 0; for (int i = 0; i <= 50; i++) sum += (FIRLPCoeffs[i] * xvFIRLP1[i]); return sum; } double xvFIRLP2[51]; double FIRLowPass2(double sampleIn) { for (int i = 0; i < 50; i++) xvFIRLP2[i] = xvFIRLP2[i+1]; xvFIRLP2[50] = sampleIn / 5.013665674; double sum = 0; for (int i = 0; i <= 50; i++) sum += (FIRLPCoeffs[i] * xvFIRLP2[i]); return sum; } // moving average double xvMA1[9]; double yvMA1prev = 0; double noiseReductionFilter1(double sampleIn) { for (int i = 0; i < 8; i++) xvMA1[i] = xvMA1[i+1]; xvMA1[8] = sampleIn; yvMA1prev = yvMA1prev+xvMA1[8]-xvMA1[0]; return yvMA1prev; } double xvMA2[9]; double yvMA2prev = 0; double noiseReductionFilter2(double sampleIn) { for (int i = 0; i < 8; i++) xvMA2[i] = xvMA2[i+1]; xvMA2[8] = sampleIn; yvMA2prev = yvMA2prev+xvMA2[8]-xvMA2[0]; return yvMA2prev; } double oscPhase = 0; double realPartPrev = 0; double imaginaryPartPrev = 0; int fmDemodulateLuminance(double sample) { oscPhase += (2 * M_PI * 2000) / SAMPLERATE; double realPart = cos(oscPhase) * sample; double imaginaryPart = sin(oscPhase) * sample; if (oscPhase >= 2 * M_PI) oscPhase -= 2 * M_PI; realPart = FIRLowPass1(realPart); imaginaryPart = FIRLowPass2(imaginaryPart); realPart = noiseReductionFilter1(realPart); imaginaryPart = noiseReductionFilter2(imaginaryPart); sample = (imaginaryPart*realPartPrev-realPart*imaginaryPartPrev)/(realPart*realPart+imaginaryPart*imaginaryPart); realPartPrev = realPart; imaginaryPartPrev = imaginaryPart; sample = sample - 0.2335 - 0.694; int luminance = (int)round((sample/0.617)*800); luminance = 800-luminance; return luminance; } void sigint_callback_handler(int signum) { cout << "Caught signal" << endl; do_exit = true; } void multiply(int ar, int aj, int br, int bj, int *cr, int *cj) { *cr = ar*br - aj*bj; *cj = aj*br + ar*bj; } int polar_discriminant(int ar, int aj, int br, int bj) { int cr, cj; double angle; multiply(ar, aj, br, -bj, &cr, &cj); angle = atan2((double)cj, (double)cr); return (int)(angle / 3.14159 * (1<<14)); } int rx_callback(hackrf_transfer* transfer) { for (int i = 0; i < transfer->valid_length; i++) { double sample = (int8_t)(transfer->buffer[i]) + 1; buf16[i] = (int16_t)sample; //s->buf16[i] = (int16_t)buf[i] - 127; s->buf16[i] -127~128 uint16_t, unsigned for negative? } memcpy(lowpassed, buf16, 2*transfer->valid_length); lp_len = transfer->valid_length; //low pass //rate = hardware_sample_rate = 6*2M int i=0, i2=0; while (i < lp_len) { now_r += lowpassed[i]; now_j += lowpassed[i+1]; i += 2; prev_index++; if (prev_index < downsample) { continue; } lowpassed[i2] = now_r; lowpassed[i2+1] = now_j; prev_index = 0; now_r = 0; now_j = 0; i2 += 2; } lp_len = i2; //fm demod //rate = rate_in = 2M int i3, pcm; pcm = polar_discriminant(lowpassed[0], lowpassed[1], pre_r, pre_j); result_demod[0] = (int16_t)pcm; for (i3 = 2; i3 < (lp_len-1); i3 += 2) { pcm = polar_discriminant(lowpassed[i3], lowpassed[i3+1], lowpassed[i3-2], lowpassed[i3-1]); result_demod[i3/2] = (int16_t)pcm; } pre_r = lowpassed[lp_len - 2]; pre_j = lowpassed[lp_len - 1]; result_demod_len = lp_len/2; // low pass real //rate = rate_out = 2M int i4=0, i5=0; int fast = rate_out; int slow = rate_out2; while (i4 < result_demod_len) { now_lpr += result_demod[i4]; i4++; prev_lpr_index += slow; if (prev_lpr_index < fast) { continue; } result_demod[i5] = (int16_t)(now_lpr / (fast/slow)); prev_lpr_index -= fast; now_lpr = 0; i5 += 1; } result_demod_len = i5; //rate = rate_out2 = 8k fprintf(stderr, "result_demod_len: %d\n", result_demod_len); double frequency_multiply; for (int s = 0; s < result_demod_len; s++) { frequency_multiply = fmDemodulateLuminance(((double)result_demod[s]) / 32768.0); cout << "s: " << s << " freq: " << frequency_multiply << endl; int pixel; if (frequency_multiply < 1500) { pixel = 0; } else if (frequency_multiply > 2300) { pixel = 255; } else { pixel = int(((frequency_multiply - 1500.0)/800.0)*255.0); } cout << "pixel: " << pixel << endl; frame.at<uchar>(lineCount, lineIndex) = pixel; lineIndex = lineIndex + 1; if (lineIndex == 490+29) { lineCount = lineCount + 1; lineIndex = 0; imshow("frame", frame); if (waitKey(5) == 'q') { } } if (lineCount == 67) { lineCount = 0; } } return 0; } int main(int argc, char **argv) { char *pcm_name; signal(SIGINT, &sigint_callback_handler); int res; freq = 434e6; rate_in = 200000; rate_out = 200000; rate_out2 = 8000; file = stdout; downsample = 6; hardware_sample_rate = (uint32_t)(downsample * rate_in); res = hackrf_init(); if( res != HACKRF_SUCCESS ) { cout << "hackrf_init() failed" << endl; return EXIT_FAILURE; } res = hackrf_open(&device); if( res != HACKRF_SUCCESS ) { cout << "hackrf_open() failed" << endl; return EXIT_FAILURE; } res = hackrf_set_lna_gain(device, 40); if( res != HACKRF_SUCCESS ) { cout << "hackrf_set_lna_gain() failed" << endl; return EXIT_FAILURE; } res = hackrf_set_vga_gain(device, 26); if( res != HACKRF_SUCCESS ) { cout << "hackrf_set_vga_gain() failed" << endl; return EXIT_FAILURE; } /* Set the frequency */ res = hackrf_set_freq(device, freq); if( res != HACKRF_SUCCESS ) { cout << "hackrf_set_freq() failed" << endl; return EXIT_FAILURE; } fprintf(stderr, "Oversampling input by: %ix.\n", downsample); /* Set the sample rate */ res = hackrf_set_sample_rate(device, hardware_sample_rate); if( res != HACKRF_SUCCESS ) { cout << "hackrf_set_sample_rate() failed" << endl; return EXIT_FAILURE; } res = hackrf_set_baseband_filter_bandwidth(device, hardware_sample_rate); if( res != HACKRF_SUCCESS ) { cout << "hackrf_baseband_filter_bandwidth_set() failed" << endl; return EXIT_FAILURE; } fprintf(stderr, "Output at %u Hz.\n", rate_in); usleep(100000); res = hackrf_start_rx(device, rx_callback, NULL); while ((hackrf_is_streaming(device) == HACKRF_TRUE) && (do_exit == false)) { usleep(100000); } if (do_exit) { fprintf(stderr, "\nUser cancel, exiting...\n"); } else { fprintf(stderr, "\nLibrary error, exiting...\n"); } res = hackrf_close(device); if(res != HACKRF_SUCCESS) { cout << "hackrf_close() failed" << endl; } else { cout << "hackrf_close() done" << endl; } hackrf_exit(); cout << "hackrf_exit() done" << endl; return 0; } g++ combine.cpp -o combine -lhackrf -pthread -lm `pkg-config --cflags --libs opencv`

    下面是合并到一个函数里的代码

    single_function.cpp

    #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <string.h> #include <math.h> #include <complex.h> #include <time.h> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <signal.h> #include <unistd.h> #include <pthread.h> #include <libhackrf/hackrf.h> #include <iostream> using namespace cv; using namespace std; struct pcm *pcm; Mat frame = Mat::zeros(67, 519, CV_8UC1); int lineCount = 0; int lineIndex = 0; int SAMPLERATE = 8000; #define MAXIMUM_BUF_LENGTH (16 * 16384) static volatile bool do_exit = false; hackrf_device *device; uint32_t freq; uint32_t hardware_sample_rate; uint16_t buf16[MAXIMUM_BUF_LENGTH]; int16_t lowpassed[MAXIMUM_BUF_LENGTH]; int lp_len; int rate_in; int rate_out; int rate_out2; int16_t result_demod[MAXIMUM_BUF_LENGTH]; int result_demod_len; int now_r, now_j; int pre_r, pre_j; int prev_index; int now_lpr; int prev_lpr_index; int downsample; double round(double r) { return (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5); } double FIRLPCoeffs[51] = { +0.0001082461, +0.0034041195, +0.0063570207, +0.0078081648, +0.0060550614, -0.0002142384, -0.0104500335, -0.0211855480, -0.0264527776, -0.0201269304, +0.0004419626, +0.0312014771, +0.0606261038, +0.0727491887, +0.0537028370, -0.0004362161, -0.0779387981, -0.1511168919, -0.1829049634, -0.1390189257, -0.0017097774, +0.2201896764, +0.4894395006, +0.7485289338, +0.9357596142, +1.0040320616, +0.9357596142, +0.7485289338, +0.4894395006, +0.2201896764, -0.0017097774, -0.1390189257, -0.1829049634, -0.1511168919, -0.0779387981, -0.0004362161, +0.0537028370, +0.0727491887, +0.0606261038, +0.0312014771, +0.0004419626, -0.0201269304, -0.0264527776, -0.0211855480, -0.0104500335, -0.0002142384, +0.0060550614, +0.0078081648, +0.0063570207, +0.0034041195, +0.0001082461, }; double xvFIRLP1[51]; double xvFIRLP2[51]; double xvMA1[9]; double yvMA1prev = 0; double xvMA2[9]; double yvMA2prev = 0; double oscPhase = 0; double realPartPrev = 0; double imaginaryPartPrev = 0; void sigint_callback_handler(int signum) { cout << "Caught signal" << endl; do_exit = true; } void multiply(int ar, int aj, int br, int bj, int *cr, int *cj) { *cr = ar*br - aj*bj; *cj = aj*br + ar*bj; } int polar_discriminant(int ar, int aj, int br, int bj) { int cr, cj; double angle; multiply(ar, aj, br, -bj, &cr, &cj); angle = atan2((double)cj, (double)cr); return (int)(angle / 3.14159 * (1<<14)); } int rx_callback(hackrf_transfer* transfer) { for (int i = 0; i < transfer->valid_length; i++) { double sample = (int8_t)(transfer->buffer[i]) + 1; buf16[i] = (int16_t)sample; //s->buf16[i] = (int16_t)buf[i] - 127; s->buf16[i] -127~128 uint16_t, unsigned for negative? } memcpy(lowpassed, buf16, 2*transfer->valid_length); lp_len = transfer->valid_length; //low pass //rate = hardware_sample_rate = 6*2M int i=0, i2=0; while (i < lp_len) { now_r += lowpassed[i]; now_j += lowpassed[i+1]; i += 2; prev_index++; if (prev_index < downsample) { continue; } lowpassed[i2] = now_r; lowpassed[i2+1] = now_j; prev_index = 0; now_r = 0; now_j = 0; i2 += 2; } lp_len = i2; //fm demod //rate = rate_in = 2M int i3, pcm; pcm = polar_discriminant(lowpassed[0], lowpassed[1], pre_r, pre_j); result_demod[0] = (int16_t)pcm; for (i3 = 2; i3 < (lp_len-1); i3 += 2) { pcm = polar_discriminant(lowpassed[i3], lowpassed[i3+1], lowpassed[i3-2], lowpassed[i3-1]); result_demod[i3/2] = (int16_t)pcm; } pre_r = lowpassed[lp_len - 2]; pre_j = lowpassed[lp_len - 1]; result_demod_len = lp_len/2; // low pass real //rate = rate_out = 2M int i4=0, i5=0; int fast = rate_out; int slow = rate_out2; while (i4 < result_demod_len) { now_lpr += result_demod[i4]; i4++; prev_lpr_index += slow; if (prev_lpr_index < fast) { continue; } result_demod[i5] = (int16_t)(now_lpr / (fast/slow)); prev_lpr_index -= fast; now_lpr = 0; i5 += 1; } result_demod_len = i5; //rate = rate_out2 = 8k double frequency_multiply; for (int s = 0; s < result_demod_len; s++) { double sample_result; oscPhase += (2 * M_PI * 2000) / SAMPLERATE; double realPart = cos(oscPhase) * (((double)result_demod[s]) / 32768.0); double imaginaryPart = sin(oscPhase) * (((double)result_demod[s]) / 32768.0); if (oscPhase >= 2 * M_PI) oscPhase -= 2 * M_PI; for (int i = 0; i < 50; i++) xvFIRLP1[i] = xvFIRLP1[i+1]; xvFIRLP1[50] = realPart / 5.013665674; double realPart_lp = 0; for (int i = 0; i <= 50; i++) realPart_lp += (FIRLPCoeffs[i] * xvFIRLP1[i]); for (int i = 0; i < 50; i++) xvFIRLP2[i] = xvFIRLP2[i+1]; xvFIRLP2[50] = imaginaryPart / 5.013665674; double imaginaryPart_lp = 0; for (int i = 0; i <= 50; i++) imaginaryPart_lp += (FIRLPCoeffs[i] * xvFIRLP2[i]); for (int i = 0; i < 8; i++) xvMA1[i] = xvMA1[i+1]; xvMA1[8] = realPart_lp; yvMA1prev = yvMA1prev+xvMA1[8]-xvMA1[0]; double realPart_nr = yvMA1prev; for (int i = 0; i < 8; i++) xvMA2[i] = xvMA2[i+1]; xvMA2[8] = imaginaryPart_lp; yvMA2prev = yvMA2prev+xvMA2[8]-xvMA2[0]; double imaginaryPart_nr = yvMA2prev; sample_result = (imaginaryPart_nr*realPartPrev-realPart_nr*imaginaryPartPrev)/(realPart_nr*realPart_nr+imaginaryPart_nr*imaginaryPart_nr); realPartPrev = realPart_nr; imaginaryPartPrev = imaginaryPart_nr; sample_result = sample_result - 0.2335 - 0.694; int luminance = (int)round((sample_result/0.617)*800); luminance = 800-luminance; frequency_multiply = luminance; cout << "s: " << s << " freq: " << frequency_multiply << endl; int pixel; if (frequency_multiply < 1500) { pixel = 0; } else if (frequency_multiply > 2300) { pixel = 255; } else { pixel = int(((frequency_multiply - 1500.0)/800.0)*255.0); } cout << "pixel: " << pixel << endl; frame.at<uchar>(lineCount, lineIndex) = pixel; lineIndex = lineIndex + 1; if (lineIndex == 490+29) { lineCount = lineCount + 1; lineIndex = 0; imshow("frame", frame); if (waitKey(5) == 'q') { } } if (lineCount == 67) { lineCount = 0; } } return 0; } int main(int argc, char **argv) { signal(SIGINT, &sigint_callback_handler); int res; freq = 434e6; rate_in = 200000; rate_out = 200000; rate_out2 = 8000; downsample = 6; hardware_sample_rate = (uint32_t)(downsample * rate_in); res = hackrf_init(); if( res != HACKRF_SUCCESS ) { cout << "hackrf_init() failed" << endl; return EXIT_FAILURE; } res = hackrf_open(&device); if( res != HACKRF_SUCCESS ) { cout << "hackrf_open() failed" << endl; return EXIT_FAILURE; } res = hackrf_set_lna_gain(device, 40); if( res != HACKRF_SUCCESS ) { cout << "hackrf_set_lna_gain() failed" << endl; return EXIT_FAILURE; } res = hackrf_set_vga_gain(device, 26); if( res != HACKRF_SUCCESS ) { cout << "hackrf_set_vga_gain() failed" << endl; return EXIT_FAILURE; } /* Set the frequency */ res = hackrf_set_freq(device, freq); if( res != HACKRF_SUCCESS ) { cout << "hackrf_set_freq() failed" << endl; return EXIT_FAILURE; } fprintf(stderr, "Oversampling input by: %ix.\n", downsample); /* Set the sample rate */ res = hackrf_set_sample_rate(device, hardware_sample_rate); if( res != HACKRF_SUCCESS ) { cout << "hackrf_set_sample_rate() failed" << endl; return EXIT_FAILURE; } res = hackrf_set_baseband_filter_bandwidth(device, hardware_sample_rate); if( res != HACKRF_SUCCESS ) { cout << "hackrf_baseband_filter_bandwidth_set() failed" << endl; return EXIT_FAILURE; } fprintf(stderr, "Output at %u Hz.\n", rate_in); usleep(100000); res = hackrf_start_rx(device, rx_callback, NULL); while ((hackrf_is_streaming(device) == HACKRF_TRUE) && (do_exit == false)) { usleep(100000); } if (do_exit) { fprintf(stderr, "\nUser cancel, exiting...\n"); } else { fprintf(stderr, "\nLibrary error, exiting...\n"); } res = hackrf_close(device); if(res != HACKRF_SUCCESS) { cout << "hackrf_close() failed" << endl; } else { cout << "hackrf_close() done" << endl; } hackrf_exit(); cout << "hackrf_exit() done" << endl; return 0; }

    上面3个程序的功能和效果都差不多。

    我的测试方法是用portpack的signal generator当作信号源,发射sin波。

    用另一个hackrf接在电脑上,然后跑这个程序。终端会有频率输出(完全符合portapack上发射的信号),并且图像的亮度根据频率高低会有变化。我还尝试portapack发了martin m1和scottie s1的sstv信号,虽然制式不对,但是确实会看到点不像是噪声的图案。接下来就要改到portapack里去了。

    我打算先用portapack的wfm解调程序听一下sstv信号或者是频率可变的单音信号(单音要经过fm调制),然后portapack再把fm解调以后的信号的频率算出来,最后再考虑画图。

    频率可变的单音信号可以用这个流图生成(但是因为是gnuradio生成的,实际发出的频点可能是飘忽不定的,我用single_function程序接收并且对比过,不如portapack发的那么准)

    我最近手头有足够的portapack可以一个发射另一个接收了。

    我试过了前段时间想要做的实验了。

    现象是这样的:

    1.发射端portapack上用信号源发射1500~2000Hz的单音信号, 接收端portapack可以用wfm或nfm听到声音,但是无线电瀑布图上看不清fm的波形(wfm的音频频谱上能看到尖峰移动)。

    2.发射端portapack用sstv发射scottie 2的信号,接收端portapack用wfm或nfm都能听到正常的声音。

    2.发射端portapack上用信号源发射1Hz~10Hz的单音信号,接收端portapack瀑布图上能看到理想中的fm波形,但是听声音是不正常的。

     

    总结一下就是,直接用portapack的nfm解调来收sstv肯定是没问题的,要不然听sstv发射的声音或者1500~2000Hz的单音肯定不正常了。我现在要做的是实现计算nfm解调出的声音的频率的问题。我尝试了把前面的电脑上计算声音频率的代码搬入Portapack,但是计算结果并不正常。有一点很奇怪的是瀑布图只能看清低频声音信号,高频信号看不清,这样对我的分析增加了难度,但是可能是因为portapack瀑布图本来采样率就不够高的原因。

    整个sstv接收分三步:无线电fm解调、音频fm解调(频率数字显示)、频率转换为图像。

    在portapack上,第一步我现在确定没问题,第三步我认为应该可以比较简单的实现,主要是第二步还要再优化一下,频率数字显示我也已经搞定了,用了原ctcss的显示方法,只剩频率计算问题了,这个频率计算我已经在电脑上搞定了,无论是直接用声卡来算声波频率,还是hackrf收无线电波然后fm解调出声音后再算声音中的频率都可以了,就是搬去portapack后出现的问题,期待解决。

    decode_draw_realtime_remove_cos.cpp

    #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <string.h> #include <complex.h> #include <time.h> #include <iostream> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <sys/stat.h> #include <fcntl.h> #include <sys/mman.h> #include "alsa.h" using namespace cv; using namespace std; struct pcm *pcm; Mat frame = Mat::zeros(67, 519, CV_8UC1); int SAMPLERATE = 8000; double round(double r) { return (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5); } double FIRLPCoeffs[51] = { +0.0001082461, +0.0034041195, +0.0063570207, +0.0078081648, +0.0060550614, -0.0002142384, -0.0104500335, -0.0211855480, -0.0264527776, -0.0201269304, +0.0004419626, +0.0312014771, +0.0606261038, +0.0727491887, +0.0537028370, -0.0004362161, -0.0779387981, -0.1511168919, -0.1829049634, -0.1390189257, -0.0017097774, +0.2201896764, +0.4894395006, +0.7485289338, +0.9357596142, +1.0040320616, +0.9357596142, +0.7485289338, +0.4894395006, +0.2201896764, -0.0017097774, -0.1390189257, -0.1829049634, -0.1511168919, -0.0779387981, -0.0004362161, +0.0537028370, +0.0727491887, +0.0606261038, +0.0312014771, +0.0004419626, -0.0201269304, -0.0264527776, -0.0211855480, -0.0104500335, -0.0002142384, +0.0060550614, +0.0078081648, +0.0063570207, +0.0034041195, +0.0001082461, }; double xvFIRLP1[51]; double FIRLowPass1(double sampleIn) { for (int i = 0; i < 50; i++) xvFIRLP1[i] = xvFIRLP1[i+1]; xvFIRLP1[50] = sampleIn / 5.013665674; double sum = 0; for (int i = 0; i <= 50; i++) sum += (FIRLPCoeffs[i] * xvFIRLP1[i]); return sum; } double xvFIRLP2[51]; double FIRLowPass2(double sampleIn) { for (int i = 0; i < 50; i++) xvFIRLP2[i] = xvFIRLP2[i+1]; xvFIRLP2[50] = sampleIn / 5.013665674; double sum = 0; for (int i = 0; i <= 50; i++) sum += (FIRLPCoeffs[i] * xvFIRLP2[i]); return sum; } // moving average double xvMA1[9]; double yvMA1prev = 0; double noiseReductionFilter1(double sampleIn) { for (int i = 0; i < 8; i++) xvMA1[i] = xvMA1[i+1]; xvMA1[8] = sampleIn; yvMA1prev = yvMA1prev+xvMA1[8]-xvMA1[0]; return yvMA1prev; } double xvMA2[9]; double yvMA2prev = 0; double noiseReductionFilter2(double sampleIn) { for (int i = 0; i < 8; i++) xvMA2[i] = xvMA2[i+1]; xvMA2[8] = sampleIn; yvMA2prev = yvMA2prev+xvMA2[8]-xvMA2[0]; return yvMA2prev; } double oscPhase = 0; double realPartPrev = 0; double imaginaryPartPrev = 0; int cosine = 0; int sine = 0; int fmDemodulateLuminance(double sample) { oscPhase = oscPhase + 1; if (oscPhase == 0) { cosine = 1; sine = 0; } else if (oscPhase == 1) { cosine = 0; sine = 1; } else if (oscPhase == 2) { cosine = -1; sine = 0; } else if (oscPhase == 3) { cosine = 0; sine = -1; } else if (oscPhase == 4) { cosine = 1; sine = 0; oscPhase = 0; } double realPart = cosine * sample; double imaginaryPart = sine * sample; realPart = FIRLowPass1(realPart); imaginaryPart = FIRLowPass2(imaginaryPart); //realPart = noiseReductionFilter1(realPart); //imaginaryPart = noiseReductionFilter2(imaginaryPart); sample = (imaginaryPart*realPartPrev-realPart*imaginaryPartPrev)/(realPart*realPart+imaginaryPart*imaginaryPart); realPartPrev = realPart; imaginaryPartPrev = imaginaryPart; sample = sample - 0.2335 - 0.694; int luminance = (int)round((sample/0.617)*800); luminance = 800-luminance; return luminance; } int main(int argc, char **argv) { char *pcm_name; int nframes = 61282; int lineCount = 0; int sampleBuffer = 0; int lineIndex = 0; pcm_name = "default"; if (!open_alsa_read(&pcm, pcm_name)) return 1; double frequency_multiply; int i = 0; while (true) { static short *pcm_buff; pcm_buff = (short *)malloc(sizeof(short) * 1); if (!read_alsa(pcm, pcm_buff, 1)) { free(pcm_buff); return 0; } frequency_multiply = fmDemodulateLuminance(((double)pcm_buff[0]) / 32768.0); cout << "i: " << i << " freq: " << frequency_multiply << endl; int pixel; if (frequency_multiply < 1500) { pixel = 0; } else if (frequency_multiply > 2300) { pixel = 255; } else { pixel = int(((frequency_multiply - 1500.0)/800.0)*255.0); } frame.at<uchar>(lineCount, lineIndex) = pixel; cout << "pixel: " << pixel << endl; lineIndex = lineIndex + 1; if (lineIndex == 490+29) { lineCount = lineCount + 1; lineIndex = 0; imshow("frame", frame); if (waitKey(5) == 'q') { } } if (lineCount == 67) { lineCount = 0; } i = i + 1; if (i > nframes- 1470) i = 0; } return 0; }

    上面是我重写过的从声波中测量频率并画图的代码,我把math.h的库删除掉了,这样就不能用cosine和sine函数了,它们由-1,0,1,0替换,类似LUT。我发现noiseReductionFilter不是必须的,但是FIRLowPass1和FIRLowPass2是必须要做的,否则频率计算会出错。

    portapack代码里还没加FIRLowPass,可能这就是为啥频率算出来不对。

    下面这是hackrf解码sstv和频率计算程序,我把noise_reduction滤波器去掉了,math.h也去掉了,只留了低通滤波器。

     

    #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <string.h> #include <math.h> #include <complex.h> #include <time.h> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <signal.h> #include <unistd.h> #include <pthread.h> #include <libhackrf/hackrf.h> #include <iostream> using namespace cv; using namespace std; struct pcm *pcm; Mat frame = Mat::zeros(67, 519, CV_8UC1); int lineCount = 0; int lineIndex = 0; int SAMPLERATE = 8000; #define MAXIMUM_BUF_LENGTH (16 * 16384) static volatile bool do_exit = false; hackrf_device *device; uint32_t freq; uint32_t hardware_sample_rate; uint16_t buf16[MAXIMUM_BUF_LENGTH]; int16_t lowpassed[MAXIMUM_BUF_LENGTH]; int lp_len; int rate_in; int rate_out; int rate_out2; int16_t result_demod[MAXIMUM_BUF_LENGTH]; int result_demod_len; int now_r, now_j; int pre_r, pre_j; int prev_index; int now_lpr; int prev_lpr_index; int downsample; double round(double r) { return (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5); } double FIRLPCoeffs[51] = { +0.0001082461, +0.0034041195, +0.0063570207, +0.0078081648, +0.0060550614, -0.0002142384, -0.0104500335, -0.0211855480, -0.0264527776, -0.0201269304, +0.0004419626, +0.0312014771, +0.0606261038, +0.0727491887, +0.0537028370, -0.0004362161, -0.0779387981, -0.1511168919, -0.1829049634, -0.1390189257, -0.0017097774, +0.2201896764, +0.4894395006, +0.7485289338, +0.9357596142, +1.0040320616, +0.9357596142, +0.7485289338, +0.4894395006, +0.2201896764, -0.0017097774, -0.1390189257, -0.1829049634, -0.1511168919, -0.0779387981, -0.0004362161, +0.0537028370, +0.0727491887, +0.0606261038, +0.0312014771, +0.0004419626, -0.0201269304, -0.0264527776, -0.0211855480, -0.0104500335, -0.0002142384, +0.0060550614, +0.0078081648, +0.0063570207, +0.0034041195, +0.0001082461, }; double xvFIRLP1[51]; double xvFIRLP2[51]; double oscPhase = 0; double realPartPrev = 0; double imaginaryPartPrev = 0; int cosine = 0; int sine = 0; void sigint_callback_handler(int signum) { cout << "Caught signal" << endl; do_exit = true; } void multiply(int ar, int aj, int br, int bj, int *cr, int *cj) { *cr = ar*br - aj*bj; *cj = aj*br + ar*bj; } int polar_discriminant(int ar, int aj, int br, int bj) { int cr, cj; double angle; multiply(ar, aj, br, -bj, &cr, &cj); angle = atan2((double)cj, (double)cr); return (int)(angle / 3.14159 * (1<<14)); } int rx_callback(hackrf_transfer* transfer) { for (int i = 0; i < transfer->valid_length; i++) { double sample = (int8_t)(transfer->buffer[i]) + 1; buf16[i] = (int16_t)sample; //s->buf16[i] = (int16_t)buf[i] - 127; s->buf16[i] -127~128 uint16_t, unsigned for negative? } memcpy(lowpassed, buf16, 2*transfer->valid_length); lp_len = transfer->valid_length; //low pass //rate = hardware_sample_rate = 6*2M int i=0, i2=0; while (i < lp_len) { now_r += lowpassed[i]; now_j += lowpassed[i+1]; i += 2; prev_index++; if (prev_index < downsample) { continue; } lowpassed[i2] = now_r; lowpassed[i2+1] = now_j; prev_index = 0; now_r = 0; now_j = 0; i2 += 2; } lp_len = i2; //fm demod //rate = rate_in = 2M int i3, pcm; pcm = polar_discriminant(lowpassed[0], lowpassed[1], pre_r, pre_j); result_demod[0] = (int16_t)pcm; for (i3 = 2; i3 < (lp_len-1); i3 += 2) { pcm = polar_discriminant(lowpassed[i3], lowpassed[i3+1], lowpassed[i3-2], lowpassed[i3-1]); result_demod[i3/2] = (int16_t)pcm; } pre_r = lowpassed[lp_len - 2]; pre_j = lowpassed[lp_len - 1]; result_demod_len = lp_len/2; // low pass real //rate = rate_out = 2M int i4=0, i5=0; int fast = rate_out; int slow = rate_out2; while (i4 < result_demod_len) { now_lpr += result_demod[i4]; i4++; prev_lpr_index += slow; if (prev_lpr_index < fast) { continue; } result_demod[i5] = (int16_t)(now_lpr / (fast/slow)); prev_lpr_index -= fast; now_lpr = 0; i5 += 1; } result_demod_len = i5; //rate = rate_out2 = 8k double frequency_multiply; for (int s = 0; s < result_demod_len; s++) { double sample_result; oscPhase = oscPhase + 1; if (oscPhase == 0) { cosine = 1; sine = 0; } else if (oscPhase == 1) { cosine = 0; sine = 1; } else if (oscPhase == 2) { cosine = -1; sine = 0; } else if (oscPhase == 3) { cosine = 0; sine = -1; } else if (oscPhase == 4) { cosine = 1; sine = 0; oscPhase = 0; } //result_demod[s] is -16384~16384 float k = 16384; float ki = 1/k; double sample = (((double)result_demod[s]) * ki); //sample is -1~1 double realPart = cosine * sample; double imaginaryPart = sine * sample; for (int i = 0; i < 50; i++) xvFIRLP1[i] = xvFIRLP1[i+1]; xvFIRLP1[50] = realPart / 5.013665674; double realPart_lp = 0; for (int i = 0; i <= 50; i++) realPart_lp += (FIRLPCoeffs[i] * xvFIRLP1[i]); for (int i = 0; i < 50; i++) xvFIRLP2[i] = xvFIRLP2[i+1]; xvFIRLP2[50] = imaginaryPart / 5.013665674; double imaginaryPart_lp = 0; for (int i = 0; i <= 50; i++) imaginaryPart_lp += (FIRLPCoeffs[i] * xvFIRLP2[i]); sample_result = (imaginaryPart_lp*realPartPrev-realPart_lp*imaginaryPartPrev)/(realPart_lp*realPart_lp+imaginaryPart_lp*imaginaryPart_lp); realPartPrev = realPart_lp; imaginaryPartPrev = imaginaryPart_lp; /* sample_result = (imaginaryPart*realPartPrev-realPart*imaginaryPartPrev)/(realPart*realPart+imaginaryPart*imaginaryPart); realPartPrev = realPart; imaginaryPartPrev = imaginaryPart; */ int luminance = (int)round(((sample_result - 0.9275)/0.617)*800); luminance = 800-luminance; frequency_multiply = luminance; //cout << "s: " << s << " freq: " << frequency_multiply << endl; cout << "s: " << s << " freq: " << 800 - (int)round(((sample_result - 0.9275)/0.617)*800) <<"|" << (int)(1300*realPart) <<endl; int pixel; if (frequency_multiply < 1500) { pixel = 0; } else if (frequency_multiply > 2300) { pixel = 255; } else { pixel = int(((frequency_multiply - 1500.0)/800.0)*255.0); } cout << "pixel: " << pixel << endl; frame.at<uchar>(lineCount, lineIndex) = pixel; lineIndex = lineIndex + 1; if (lineIndex == 490+29) { lineCount = lineCount + 1; lineIndex = 0; imshow("frame", frame); if (waitKey(5) == 'q') { } } if (lineCount == 67) { lineCount = 0; } } return 0; } int main(int argc, char **argv) { signal(SIGINT, &sigint_callback_handler); int res; freq = 434e6; rate_in = 200000; rate_out = 200000; rate_out2 = 8000; downsample = 6; hardware_sample_rate = (uint32_t)(downsample * rate_in); res = hackrf_init(); if( res != HACKRF_SUCCESS ) { cout << "hackrf_init() failed" << endl; return EXIT_FAILURE; } res = hackrf_open(&device); if( res != HACKRF_SUCCESS ) { cout << "hackrf_open() failed" << endl; return EXIT_FAILURE; } res = hackrf_set_lna_gain(device, 40); if( res != HACKRF_SUCCESS ) { cout << "hackrf_set_lna_gain() failed" << endl; return EXIT_FAILURE; } res = hackrf_set_vga_gain(device, 26); if( res != HACKRF_SUCCESS ) { cout << "hackrf_set_vga_gain() failed" << endl; return EXIT_FAILURE; } /* Set the frequency */ res = hackrf_set_freq(device, freq); if( res != HACKRF_SUCCESS ) { cout << "hackrf_set_freq() failed" << endl; return EXIT_FAILURE; } fprintf(stderr, "Oversampling input by: %ix.\n", downsample); /* Set the sample rate */ res = hackrf_set_sample_rate(device, hardware_sample_rate); if( res != HACKRF_SUCCESS ) { cout << "hackrf_set_sample_rate() failed" << endl; return EXIT_FAILURE; } res = hackrf_set_baseband_filter_bandwidth(device, hardware_sample_rate); if( res != HACKRF_SUCCESS ) { cout << "hackrf_baseband_filter_bandwidth_set() failed" << endl; return EXIT_FAILURE; } fprintf(stderr, "Output at %u Hz.\n", rate_in); usleep(100000); res = hackrf_start_rx(device, rx_callback, NULL); while ((hackrf_is_streaming(device) == HACKRF_TRUE) && (do_exit == false)) { usleep(100000); } if (do_exit) { fprintf(stderr, "\nUser cancel, exiting...\n"); } else { fprintf(stderr, "\nLibrary error, exiting...\n"); } res = hackrf_close(device); if(res != HACKRF_SUCCESS) { cout << "hackrf_close() failed" << endl; } else { cout << "hackrf_close() done" << endl; } hackrf_exit(); cout << "hackrf_exit() done" << endl; return 0; }

     

    Processed: 0.011, SQL: 8