当前位置:网站首页>TEMPEST HDMI泄漏接收 2
TEMPEST HDMI泄漏接收 2
2022-06-25 06:38:00 【老邵的开源世界】
我后来找到了gr-tempest包,它基于gnuradio重置了tempestsdr,由于是gnuradio,比较方便我本地安装,因此我跑了一下,结果没跑出实际效果,可能因为它默认用usrp,我这用的是hackrf+重采样,硬件不太一样导致的。但是它里面还有个simulate的流图,可以导入图片再重新解出来。这个我玩成功了,通过调试,我发现在不同sample correction时,会出现类似第一篇文章的样子,也会出现比较像样的画面。所以我的信心大增。
后来我还是决定在我以前的c++/hackrf实现的模拟视频解调程序里试试。果然试成了,主要秘诀在于要去掉模拟视频解调里的各种同步,去掉隔行扫描,然后再耐心调整行宽,最后为了效果好一些,不乱跳,建议再人为限制刷新间隔。
下面就是我的代码:
#include <iostream>
#include <signal.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <libhackrf/hackrf.h>
#include <pthread.h>
#include <unistd.h>
#include <string>
#include <sstream>
using namespace std;
using namespace cv;
int decimate_rate = 1;
//#define original_width_x_height 65100
static volatile bool do_exit = false;
int result;
static hackrf_device* device = NULL;
double sample_rate_hz = 6e6/decimate_rate * 1.951047 ;
double baseband_filter_bw_hz = 1e6 ;
double freq_hz = 395.991*1000000;
Mat frame;
int x = 0;
int y = 0;
int correctX = 0;
int correctY = 0;
int autoCorrectX = 0;
int autoCorrectY = 0;
int width = 2081; //multiple of 347 like 2081 or 1387
int height = 800;
int original_width = width / decimate_rate;
int original_width_x_height = original_width * height;
int inverseVideo = 1;
double maxSignalLevel = 0;
double blackLevel = 0;
double coeff = 0;
double agcSignalLevel = 0;
int pixelCounter = 0;
double contrast = 40;
double bright = 40;
int delay_count = 0;
bool bufferIsFull = false;
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
//double grayScaleValues[original_width_x_height];
double grayScaleValues[2000000];
void sigint_callback_handler(int signum)
{
cout << "Caught signal" << endl;
do_exit = true;
}
void draw_pixel(double mag)
{
if (x >= original_width)
{
y += 1;
x = 0;
}
if (y >= height)
{
y = 0;
delay_count++;
if (delay_count > 3)
{
bufferIsFull = true;
delay_count = 0;
}
}
double num2 = (blackLevel - mag) * coeff * contrast;
num2 += bright;
if (num2 > 255)
{
num2 = 255;
}
if (num2 < 0)
{
num2 = 0;
}
int num = y % height * original_width + x % original_width;
grayScaleValues[num] = num2;
x = x + 1;
}
int rx_callback(hackrf_transfer* transfer)
{
double im, re, mag;
double num = 0;
double num2 = 0;
double compare_re;
for( uint32_t i = 0; i < transfer->valid_length; i += 2)
{
// int8_t(transfer->buffer[i]) -128~127
im = (int8_t(transfer->buffer[i]))/128.0;
re = (int8_t(transfer->buffer[i + 1]))/128.0;
compare_re = abs(int8_t(transfer->buffer[i+1])) ;
if (compare_re > num)
{
num = compare_re;
}
double mag = sqrt( im * im + re * re); //mag 0~1.414
if (mag > num2)
{
num2 = mag;
}
if (inverseVideo)
{
mag = maxSignalLevel - mag;
}
pthread_mutex_lock(&mtx);
draw_pixel(mag);
pthread_mutex_unlock(&mtx);
//grey of opencv is 0~255
//0 is black 255 is white
}
maxSignalLevel = maxSignalLevel * 0.9 + num2 * 0.1;
blackLevel = maxSignalLevel * 0.4;
coeff = 255 / blackLevel;
agcSignalLevel = num;
return 0;
}
void *receiving_function(void *arg)
{
while (do_exit == false)
{
sleep(1);
}
cout << "Thread Exiting..." << endl;
pthread_exit(NULL);
}
int main()
{
pthread_t recv_th;
signal(SIGINT, &sigint_callback_handler);
frame = Mat::zeros(height, width, CV_8UC1);
result = hackrf_init();
if( result != HACKRF_SUCCESS )
{
cout << "hackrf_init() failed" << endl;
return EXIT_FAILURE;
}
result = hackrf_open(&device);
if( result != HACKRF_SUCCESS )
{
cout << "hackrf_open() failed" << endl;
return EXIT_FAILURE;
}
result = hackrf_set_sample_rate(device, sample_rate_hz);
if( result != HACKRF_SUCCESS )
{
cout << "hackrf_set_sample_rate() failed" << endl;
return EXIT_FAILURE;
}
result = hackrf_set_baseband_filter_bandwidth(device, baseband_filter_bw_hz);
if( result != HACKRF_SUCCESS )
{
cout << "hackrf_baseband_filter_bandwidth_set() failed" << endl;
return EXIT_FAILURE;
}
result = hackrf_set_freq(device, freq_hz);
if( result != HACKRF_SUCCESS )
{
cout << "hackrf_set_freq() failed" << endl;
return EXIT_FAILURE;
}
result = hackrf_set_lna_gain(device, 40);
if( result != HACKRF_SUCCESS )
{
cout << "hackrf_set_lna_gain() failed" << endl;
return EXIT_FAILURE;
}
result = hackrf_set_vga_gain(device, 26);
if( result != HACKRF_SUCCESS )
{
cout << "hackrf_set_vga_gain() failed" << endl;
return EXIT_FAILURE;
}
int err = pthread_create(&recv_th, NULL, receiving_function, NULL);
if (err != 0)
{
cout << "Create thread failed" << endl;
}
result = hackrf_start_rx(device, rx_callback, NULL);
while( (hackrf_is_streaming(device) == HACKRF_TRUE) && (do_exit == false) )
{
if (bufferIsFull)
{
pthread_mutex_lock(&mtx);
for (int counter = 0; counter < original_width_x_height; counter++)
{
int new_x = counter % original_width;
int new_y = counter / original_width;
for (int c = 0; c < decimate_rate; c++)
{
frame.at<uchar>(new_y, new_x*decimate_rate + c) = grayScaleValues[counter];
}
grayScaleValues[counter] = 0;
}
bufferIsFull = false;
pthread_mutex_unlock(&mtx);
}
imshow("frame", frame);
if (waitKey(5) == 'q')
{
do_exit = true;
break;
}
}
if (do_exit)
{
cout << "Exiting..." << endl;
}
result = hackrf_close(device);
if(result != HACKRF_SUCCESS)
{
cout << "hackrf_close() failed" << endl;
}
else
{
cout << "hackrf_close() done" << endl;
}
hackrf_exit();
cout << "hackrf_exit() done" << endl;
pthread_join(recv_th,NULL);
return 0;
}
下面是编译用的命令:
g++ hackrf_tv_hdmi.cpp -o hackrf_tv_hdmi `pkg-config --cflags --libs opencv` -lhackrf -pthread
感兴趣的朋友可以试一下,我的显示器设置为1920x1080 60Hz。你的可能频点和我不一样。
目前这个c++版本代码肯定比tempestsdr简单好多,但是仍然不是最简化的,里面有不少我做模拟视频解调时的冗余代码。等我有时间再整理为python版本。
边栏推荐
- CTFHub-Web-信息泄露-目录遍历
- Several schemes of traffic exposure in kubernetes cluster
- How do I get red green blue (RGB) and alpha back from a UIColor object?
- 哇哦,好丰富呀。
- Three laws of go reflection
- Event registration Apache pulsar x kubesphere online meetup hot registration
- Is it possible to use Jasmine's toHaveBeenCalledWith matcher with a regular expression?
- Esp8266 & sg90 steering gear & Lighting Technology & Arduino
- 全局变量&局部变量
- [Shangshui Shuo series] day 4
猜你喜欢
Analysis on the trend of the number of national cinemas, film viewers and average ticket prices in 2021 [figure]
Error reported during vivado simulation common 17-39
Americo technology launches professional desktop video editing solution
One year's time and University experience sharing with CSDN
Modify the default log level
深入解析 Apache BookKeeper 系列:第三篇——读取原理
Kubernetes 集群中流量暴露的几种方案
[2022 dark horse programmer] SQL optimization
Simple and complete steps of vivado project
Kubernetes cluster dashboard & kuboard installation demo
随机推荐
alphassl通配符证书送一个月
基于 KubeSphere 的分级管理实践
Your local changes to the following files would be overwritten by merge: . vs/slnx. sqlite
Drawing shp files using OpenGL
[Yu Yue education] engineering testing technology reference of Wenhua University
SQL query, if value is null then return 1 - SQL query, if value is null then return 1
Is it possible to use Jasmine's toHaveBeenCalledWith matcher with a regular expression?
Three laws of go reflection
Using awk to process input from multiple files
joda. Time get date summary
Non-contact infrared temperature measurement system for human body based on single chip microcomputer
Event registration Apache pulsar x kubesphere online meetup hot registration
lotus v1.16.0-rc3 calibnet
Event registration | Apache pulsar x kubesphere online meetup is coming
破万,我用了六年!
从感知机到Transformer,一文概述深度学习简史
Make fertilizer Safi from crop residues locally to increase yield by 30% and improve soil
Rotation vector (rotation matrix) and Euler angle
Ctfhub web - divulgation d'informations - traversée du Répertoire
How to store the directory / hierarchy / tree structure in the database- How to store directory / hierarchy / tree structure in the database?