kopia lustrzana https://github.com/cariboulabs/cariboulite
dump1090 bug fixes, working
rodzic
adca66f611
commit
6a60ecbc31
Plik binarny nie jest wyświetlany.
|
@ -33,7 +33,7 @@ static void printBanner(void)
|
|||
/***********************************************************************
|
||||
* Find devices and print args
|
||||
**********************************************************************/
|
||||
static int findDevices(const std::string &argStr, const bool sparse)
|
||||
static int findDevices(const std::string &argStr)
|
||||
{
|
||||
const auto results = SoapySDR::Device::enumerate(argStr);
|
||||
std::cout << "Found " << results.size() << " devices" << std::endl;
|
||||
|
@ -64,7 +64,41 @@ static void sigIntHandler(const int)
|
|||
|
||||
void onModeSMessage(mode_s_t *self, struct mode_s_msg *mm)
|
||||
{
|
||||
printf("Got message from flight %s at altitude %d\n", mm->flight, mm->altitude);
|
||||
printf("Got message from flight %s\n", mm->flight);
|
||||
|
||||
printf(" HEADER: #Bits: %d, Type: %d, CRCOK: %d, ECC: %d, ICAO_ADDR:%02X%02X%02X, PHC: %d, CAP: %08X\n",
|
||||
mm->msgbits, // Number of bits in message
|
||||
mm->msgtype, // Downlink format #
|
||||
mm->crcok, // True if CRC was valid
|
||||
mm->errorbit, // Bit corrected. -1 if no bit corrected.
|
||||
mm->aa1, mm->aa2, mm->aa3, // ICAO Address bytes 1 2 and 3
|
||||
mm->phase_corrected, // True if phase correction was applied.
|
||||
mm->ca); // Responder capabilities.
|
||||
|
||||
|
||||
printf(" DATA1: MsgTp: %d, MsgSTp: %d, HdVld: %d, Hd: %d, AirCftTp:%d, FFlg: %d, UtcSync: %d, Lat: %d, Lon: %d, Dir W/S: %d/%d\n"
|
||||
" DATA2: Vel (W/S): %d/%d, Vel: %d, VertRt (Src/Sgn/Rt): %d/%d/%d, Alt: %d, Stat: %d, Id: %08X, Unt: %d\n\n",
|
||||
mm->metype, // Extended squitter message type.
|
||||
mm->mesub, // Extended squitter message subtype.
|
||||
mm->heading_is_valid, // heading_is_valid
|
||||
mm->heading, // heading
|
||||
mm->aircraft_type, // aircraft_type
|
||||
mm->fflag, // 1 = Odd, 0 = Even CPR message.
|
||||
mm->tflag, // UTC synchronized?
|
||||
mm->raw_latitude, // Non decoded latitude
|
||||
mm->raw_longitude, // Non decoded raw_longitude
|
||||
mm->ew_dir, // 0 = East, 1 = West.
|
||||
mm->ns_dir, // 0 = North, 1 = South.
|
||||
mm->ew_velocity, // E/W velocity.
|
||||
mm->ns_velocity, // N/S velocity.
|
||||
mm->velocity,
|
||||
mm->vert_rate_source, // Vertical rate source.
|
||||
mm->vert_rate_sign, // Vertical rate sign.
|
||||
mm->vert_rate, // // Vertical rate.
|
||||
mm->altitude,
|
||||
mm->fs, // Flight status for DF4,5,20,21
|
||||
mm->identity, // 13 bits identity (Squawk).
|
||||
mm->unit);
|
||||
}
|
||||
|
||||
#define FILT_ORDER 6
|
||||
|
@ -77,20 +111,18 @@ void makeFilter(double fs, double cutoff)
|
|||
}
|
||||
|
||||
// Turn I/Q samples pointed by `data` into the magnitude vector pointed by `mag`
|
||||
void MagnitudeVector(short *data, uint16_t *mag, uint32_t size)
|
||||
void MagnitudeVectorDownSample(short *data, uint16_t *mag, uint32_t size)
|
||||
{
|
||||
uint32_t k;
|
||||
float ii, qq, i, q;
|
||||
float i, q;
|
||||
int t = 0;
|
||||
for (k=0; k<size; k+=2, t++)
|
||||
{
|
||||
float i = data[k];
|
||||
float q = data[k+1];
|
||||
float i = (float)data[k];
|
||||
float q = (float)data[k+1];
|
||||
|
||||
//ii = filt.filter(i);
|
||||
//qq = filt.filter(q);
|
||||
|
||||
mag[t]=(uint16_t)sqrt(ii*ii + qq*qq);
|
||||
if (t & 0x1)
|
||||
mag[t >> 1]=(uint16_t)sqrt(i*i + q*q);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -139,15 +171,10 @@ void runSoapyProcess(
|
|||
}
|
||||
|
||||
// compute the magnitude of the signal
|
||||
MagnitudeVector(buff, mag, ret);
|
||||
|
||||
for (int jjj = 0; jjj < numElems; jjj++)
|
||||
{
|
||||
printf("%d, ", buff[jjj*2]);
|
||||
}
|
||||
MagnitudeVectorDownSample(buff, mag, ret);
|
||||
|
||||
// detect Mode S messages in the signal and call on_msg with each message
|
||||
mode_s_detect(&state, mag, ret, onModeSMessage);
|
||||
mode_s_detect(&state, mag, ret/2, onModeSMessage);
|
||||
|
||||
}
|
||||
device->deactivateStream(stream);
|
||||
|
@ -159,29 +186,27 @@ void runSoapyProcess(
|
|||
**********************************************************************/
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
SoapySDR::ModuleManager mm(false);
|
||||
SoapySDR::ModuleManager mm(false);
|
||||
|
||||
SoapySDR::Device *device(nullptr);
|
||||
std::vector<size_t> channels;
|
||||
std::string argStr;
|
||||
std::string argStr = "driver=Cariboulite,channel=HiF";
|
||||
double fullScale = 0.0;
|
||||
double freq = 1090.0e6;
|
||||
//double freq = 1090e6;
|
||||
|
||||
printBanner();
|
||||
//findDevices(argStr, false);
|
||||
|
||||
try
|
||||
{
|
||||
device = SoapySDR::Device::make(argStr);
|
||||
|
||||
// push the 6GHZ channel into the channel list
|
||||
channels.push_back(1);
|
||||
channels.push_back(0);
|
||||
|
||||
// set the sample rate
|
||||
device->setSampleRate(SOAPY_SDR_RX, channels[0], 4e6);
|
||||
device->setBandwidth(SOAPY_SDR_RX, channels[0], 2.5e6);
|
||||
device->setBandwidth(SOAPY_SDR_RX, channels[0], 2500e5);
|
||||
device->setGainMode(SOAPY_SDR_RX, channels[0], false);
|
||||
device->setGain(SOAPY_SDR_RX, channels[0], 60);
|
||||
device->setGain(SOAPY_SDR_RX, channels[0], 50);
|
||||
device->setFrequency(SOAPY_SDR_RX, channels[0], freq);
|
||||
|
||||
//create the stream, use the native format
|
||||
|
|
|
@ -101,13 +101,16 @@ uint32_t mode_s_checksum(unsigned char *msg, int bits) {
|
|||
|
||||
// Given the Downlink Format (DF) of the message, return the message length in
|
||||
// bits.
|
||||
int mode_s_msg_len_by_type(int type) {
|
||||
if (type == 16 || type == 17 ||
|
||||
type == 19 || type == 20 ||
|
||||
type == 21)
|
||||
return MODE_S_LONG_MSG_BITS;
|
||||
else
|
||||
return MODE_S_SHORT_MSG_BITS;
|
||||
int mode_s_msg_len_by_type(int type)
|
||||
{
|
||||
if (type == 16 || type == 17 ||
|
||||
type == 19 || type == 20 ||
|
||||
type == 21)
|
||||
{
|
||||
return MODE_S_LONG_MSG_BITS;
|
||||
}
|
||||
|
||||
return MODE_S_SHORT_MSG_BITS;
|
||||
}
|
||||
|
||||
// Try to fix single bit errors using the checksum. On success modifies the
|
||||
|
@ -550,36 +553,39 @@ void apply_phase_correction(uint16_t *mag) {
|
|||
// Detect a Mode S messages inside the magnitude buffer pointed by 'mag' and of
|
||||
// size 'maglen' bytes. Every detected Mode S message is convert it into a
|
||||
// stream of bits and passed to the function to display it.
|
||||
void mode_s_detect(mode_s_t *self, uint16_t *mag, uint32_t maglen, mode_s_callback_t cb) {
|
||||
unsigned char bits[MODE_S_LONG_MSG_BITS];
|
||||
unsigned char msg[MODE_S_LONG_MSG_BITS/2];
|
||||
uint16_t aux[MODE_S_LONG_MSG_BITS*2];
|
||||
uint32_t j;
|
||||
int use_correction = 0;
|
||||
void mode_s_detect(mode_s_t *self, uint16_t *mag, uint32_t maglen, mode_s_callback_t cb)
|
||||
{
|
||||
unsigned char bits[MODE_S_LONG_MSG_BITS];
|
||||
unsigned char msg[MODE_S_LONG_MSG_BITS/2];
|
||||
uint16_t aux[MODE_S_LONG_MSG_BITS*2];
|
||||
uint32_t j;
|
||||
int use_correction = 0;
|
||||
|
||||
// The Mode S preamble is made of impulses of 0.5 microseconds at the
|
||||
// following time offsets:
|
||||
//
|
||||
// 0 - 0.5 usec: first impulse.
|
||||
// 1.0 - 1.5 usec: second impulse.
|
||||
// 3.5 - 4 usec: third impulse.
|
||||
// 4.5 - 5 usec: last impulse.
|
||||
//
|
||||
// Since we are sampling at 2 Mhz every sample in our magnitude vector is
|
||||
// 0.5 usec, so the preamble will look like this, assuming there is an
|
||||
// impulse at offset 0 in the array:
|
||||
//
|
||||
// 0 -----------------
|
||||
// 1 -
|
||||
// 2 ------------------
|
||||
// 3 --
|
||||
// 4 -
|
||||
// 5 --
|
||||
// 6 -
|
||||
// 7 ------------------
|
||||
// 8 --
|
||||
// 9 -------------------
|
||||
for (j = 0; j < maglen - MODE_S_FULL_LEN*2; j++) {
|
||||
// The Mode S preamble is made of impulses of 0.5 microseconds at the
|
||||
// following time offsets:
|
||||
//
|
||||
// 0 - 0.5 usec: first impulse.
|
||||
// 1.0 - 1.5 usec: second impulse.
|
||||
// 3.5 - 4 usec: third impulse.
|
||||
// 4.5 - 5 usec: last impulse.
|
||||
//
|
||||
// Since we are sampling at 2 Mhz every sample in our magnitude vector is
|
||||
// 0.5 usec, so the preamble will look like this, assuming there is an
|
||||
// impulse at offset 0 in the array:
|
||||
//
|
||||
// 0 -----------------
|
||||
// 1 -
|
||||
// 2 ------------------
|
||||
// 3 --
|
||||
// 4 -
|
||||
// 5 --
|
||||
// 6 -
|
||||
// 7 ------------------
|
||||
// 8 --
|
||||
// 9 -------------------
|
||||
|
||||
for (j = 0; j < maglen - MODE_S_FULL_LEN*2; j++)
|
||||
{
|
||||
int low, high, delta, i, errors;
|
||||
int good_message = 0;
|
||||
|
||||
|
@ -660,72 +666,83 @@ good_preamble:
|
|||
}
|
||||
}
|
||||
|
||||
// Restore the original message if we used magnitude correction.
|
||||
if (use_correction)
|
||||
memcpy(mag+j+MODE_S_PREAMBLE_US*2, aux, sizeof(aux));
|
||||
// Restore the original message if we used magnitude correction.
|
||||
if (use_correction)
|
||||
{
|
||||
memcpy(mag+j+MODE_S_PREAMBLE_US*2, aux, sizeof(aux));
|
||||
}
|
||||
|
||||
// Pack bits into bytes
|
||||
for (i = 0; i < MODE_S_LONG_MSG_BITS; i += 8) {
|
||||
msg[i/8] =
|
||||
bits[i]<<7 |
|
||||
bits[i+1]<<6 |
|
||||
bits[i+2]<<5 |
|
||||
bits[i+3]<<4 |
|
||||
bits[i+4]<<3 |
|
||||
bits[i+5]<<2 |
|
||||
bits[i+6]<<1 |
|
||||
bits[i+7];
|
||||
}
|
||||
// Pack bits into bytes
|
||||
for (i = 0; i < MODE_S_LONG_MSG_BITS; i += 8)
|
||||
{
|
||||
msg[i/8] =
|
||||
bits[i]<<7 |
|
||||
bits[i+1]<<6 |
|
||||
bits[i+2]<<5 |
|
||||
bits[i+3]<<4 |
|
||||
bits[i+4]<<3 |
|
||||
bits[i+5]<<2 |
|
||||
bits[i+6]<<1 |
|
||||
bits[i+7];
|
||||
}
|
||||
|
||||
int msgtype = msg[0]>>3;
|
||||
int msglen = mode_s_msg_len_by_type(msgtype)/8;
|
||||
int msgtype = msg[0]>>3;
|
||||
int msglen = mode_s_msg_len_by_type(msgtype)/8;
|
||||
|
||||
// Last check, high and low bits are different enough in magnitude to
|
||||
// mark this as real message and not just noise?
|
||||
delta = 0;
|
||||
for (i = 0; i < msglen*8*2; i += 2) {
|
||||
delta += abs(mag[j+i+MODE_S_PREAMBLE_US*2]-
|
||||
mag[j+i+MODE_S_PREAMBLE_US*2+1]);
|
||||
}
|
||||
delta /= msglen*4;
|
||||
// Last check, high and low bits are different enough in magnitude to
|
||||
// mark this as real message and not just noise?
|
||||
delta = 0;
|
||||
for (i = 0; i < msglen*8*2; i += 2)
|
||||
{
|
||||
delta += abs(mag[j+i+MODE_S_PREAMBLE_US*2]-
|
||||
mag[j+i+MODE_S_PREAMBLE_US*2+1]);
|
||||
}
|
||||
delta /= msglen*4;
|
||||
|
||||
// Filter for an average delta of three is small enough to let almost
|
||||
// every kind of message to pass, but high enough to filter some random
|
||||
// noise.
|
||||
if (delta < 10*255) {
|
||||
use_correction = 0;
|
||||
continue;
|
||||
}
|
||||
// Filter for an average delta of three is small enough to let almost
|
||||
// every kind of message to pass, but high enough to filter some random
|
||||
// noise.
|
||||
if (delta < 10*255)
|
||||
{
|
||||
use_correction = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
// If we reached this point, and error is zero, we are very likely with
|
||||
// a Mode S message in our hands, but it may still be broken and CRC
|
||||
// may not be correct. This is handled by the next layer.
|
||||
if (errors == 0 || (self->aggressive && errors < 3)) {
|
||||
struct mode_s_msg mm;
|
||||
// If we reached this point, and error is zero, we are very likely with
|
||||
// a Mode S message in our hands, but it may still be broken and CRC
|
||||
// may not be correct. This is handled by the next layer.
|
||||
if (errors == 0 || (self->aggressive && errors < 3))
|
||||
{
|
||||
struct mode_s_msg mm;
|
||||
|
||||
// Decode the received message
|
||||
mode_s_decode(self, &mm, msg);
|
||||
// Decode the received message
|
||||
mode_s_decode(self, &mm, msg);
|
||||
|
||||
// Skip this message if we are sure it's fine.
|
||||
if (mm.crcok) {
|
||||
j += (MODE_S_PREAMBLE_US+(msglen*8))*2;
|
||||
good_message = 1;
|
||||
if (use_correction)
|
||||
mm.phase_corrected = 1;
|
||||
}
|
||||
// Skip this message if we are sure it's fine.
|
||||
if (mm.crcok)
|
||||
{
|
||||
j += (MODE_S_PREAMBLE_US+(msglen*8))*2;
|
||||
good_message = 1;
|
||||
if (use_correction)
|
||||
mm.phase_corrected = 1;
|
||||
}
|
||||
|
||||
// Pass data to the next layer
|
||||
if (self->check_crc == 0 || mm.crcok) {
|
||||
cb(self, &mm);
|
||||
}
|
||||
}
|
||||
// Pass data to the next layer
|
||||
if (self->check_crc == 0 || mm.crcok)
|
||||
{
|
||||
cb(self, &mm);
|
||||
}
|
||||
}
|
||||
|
||||
// Retry with phase correction if possible.
|
||||
if (!good_message && !use_correction) {
|
||||
j--;
|
||||
use_correction = 1;
|
||||
} else {
|
||||
use_correction = 0;
|
||||
}
|
||||
}
|
||||
// Retry with phase correction if possible.
|
||||
if (!good_message && !use_correction)
|
||||
{
|
||||
j--;
|
||||
use_correction = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
use_correction = 0;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -24,59 +24,61 @@ extern "C" {
|
|||
#define MODE_S_UNIT_METERS 1
|
||||
|
||||
// Program state
|
||||
typedef struct {
|
||||
// Internal state
|
||||
uint32_t icao_cache[sizeof(uint32_t)*MODE_S_ICAO_CACHE_LEN*2]; // Recently seen ICAO addresses cache
|
||||
typedef struct
|
||||
{
|
||||
// Internal state
|
||||
uint32_t icao_cache[sizeof(uint32_t)*MODE_S_ICAO_CACHE_LEN*2]; // Recently seen ICAO addresses cache
|
||||
|
||||
// Configuration
|
||||
int fix_errors; // Single bit error correction if true
|
||||
int aggressive; // Aggressive detection algorithm
|
||||
int check_crc; // Only display messages with good CRC
|
||||
// Configuration
|
||||
int fix_errors; // Single bit error correction if true
|
||||
int aggressive; // Aggressive detection algorithm
|
||||
int check_crc; // Only display messages with good CRC
|
||||
} mode_s_t;
|
||||
|
||||
// The struct we use to store information about a decoded message
|
||||
struct mode_s_msg {
|
||||
// Generic fields
|
||||
unsigned char msg[MODE_S_LONG_MSG_BYTES]; // Binary message
|
||||
int msgbits; // Number of bits in message
|
||||
int msgtype; // Downlink format #
|
||||
int crcok; // True if CRC was valid
|
||||
uint32_t crc; // Message CRC
|
||||
int errorbit; // Bit corrected. -1 if no bit corrected.
|
||||
int aa1, aa2, aa3; // ICAO Address bytes 1 2 and 3
|
||||
int phase_corrected; // True if phase correction was applied.
|
||||
struct mode_s_msg
|
||||
{
|
||||
// Generic fields
|
||||
unsigned char msg[MODE_S_LONG_MSG_BYTES]; // Binary message
|
||||
int msgbits; // Number of bits in message
|
||||
int msgtype; // Downlink format #
|
||||
int crcok; // True if CRC was valid
|
||||
uint32_t crc; // Message CRC
|
||||
int errorbit; // Bit corrected. -1 if no bit corrected.
|
||||
int aa1, aa2, aa3; // ICAO Address bytes 1 2 and 3
|
||||
int phase_corrected; // True if phase correction was applied.
|
||||
|
||||
// DF 11
|
||||
int ca; // Responder capabilities.
|
||||
// DF 11
|
||||
int ca; // Responder capabilities.
|
||||
|
||||
// DF 17
|
||||
int metype; // Extended squitter message type.
|
||||
int mesub; // Extended squitter message subtype.
|
||||
int heading_is_valid;
|
||||
int heading;
|
||||
int aircraft_type;
|
||||
int fflag; // 1 = Odd, 0 = Even CPR message.
|
||||
int tflag; // UTC synchronized?
|
||||
int raw_latitude; // Non decoded latitude
|
||||
int raw_longitude; // Non decoded longitude
|
||||
char flight[9]; // 8 chars flight number.
|
||||
int ew_dir; // 0 = East, 1 = West.
|
||||
int ew_velocity; // E/W velocity.
|
||||
int ns_dir; // 0 = North, 1 = South.
|
||||
int ns_velocity; // N/S velocity.
|
||||
int vert_rate_source; // Vertical rate source.
|
||||
int vert_rate_sign; // Vertical rate sign.
|
||||
int vert_rate; // Vertical rate.
|
||||
int velocity; // Computed from EW and NS velocity.
|
||||
// DF 17
|
||||
int metype; // Extended squitter message type.
|
||||
int mesub; // Extended squitter message subtype.
|
||||
int heading_is_valid;
|
||||
int heading;
|
||||
int aircraft_type;
|
||||
int fflag; // 1 = Odd, 0 = Even CPR message.
|
||||
int tflag; // UTC synchronized?
|
||||
int raw_latitude; // Non decoded latitude
|
||||
int raw_longitude; // Non decoded longitude
|
||||
char flight[9]; // 8 chars flight number.
|
||||
int ew_dir; // 0 = East, 1 = West.
|
||||
int ew_velocity; // E/W velocity.
|
||||
int ns_dir; // 0 = North, 1 = South.
|
||||
int ns_velocity; // N/S velocity.
|
||||
int vert_rate_source; // Vertical rate source.
|
||||
int vert_rate_sign; // Vertical rate sign.
|
||||
int vert_rate; // Vertical rate.
|
||||
int velocity; // Computed from EW and NS velocity.
|
||||
|
||||
// DF4, DF5, DF20, DF21
|
||||
int fs; // Flight status for DF4,5,20,21
|
||||
int dr; // Request extraction of downlink request.
|
||||
int um; // Request extraction of downlink request.
|
||||
int identity; // 13 bits identity (Squawk).
|
||||
// DF4, DF5, DF20, DF21
|
||||
int fs; // Flight status for DF4,5,20,21
|
||||
int dr; // Request extraction of downlink request.
|
||||
int um; // Request extraction of downlink request.
|
||||
int identity; // 13 bits identity (Squawk).
|
||||
|
||||
// Fields used by multiple message types.
|
||||
int altitude, unit;
|
||||
// Fields used by multiple message types.
|
||||
int altitude, unit;
|
||||
};
|
||||
|
||||
typedef void (*mode_s_callback_t)(mode_s_t *self, struct mode_s_msg *mm);
|
||||
|
|
|
@ -16,15 +16,15 @@ import SoapySDR
|
|||
from SoapySDR import SOAPY_SDR_RX, SOAPY_SDR_TX, SOAPY_SDR_CS16
|
||||
|
||||
|
||||
def setup_receiver(sdr, channel, freq_hz):
|
||||
use_agc = False # Use or don't use the AGC
|
||||
# The wide channel parameters
|
||||
sdr.setGainMode(SOAPY_SDR_RX, channel, use_agc) # Set the gain mode
|
||||
sdr.setGain(SOAPY_SDR_RX, channel, 0) # Set the gain
|
||||
sdr.setFrequency(SOAPY_SDR_RX, channel, freq_hz) # Tune the LO
|
||||
sdr.setBandwidth(SOAPY_SDR_RX, channel, 2500e5)
|
||||
rx_stream = sdr.setupStream(SOAPY_SDR_RX, SOAPY_SDR_CS16, [channel]) # Setup data stream
|
||||
return rx_stream
|
||||
def setup_receiver(sdr, freq_hz):
|
||||
use_agc = False
|
||||
sdr.setGainMode(SOAPY_SDR_RX, 0, use_agc)
|
||||
sdr.setGain(SOAPY_SDR_RX, 0, 50)
|
||||
sdr.setBandwidth(SOAPY_SDR_RX, 0, 2500e5)
|
||||
sdr.setFrequency(SOAPY_SDR_RX, 0, freq_hz)
|
||||
rx_stream = sdr.setupStream(SOAPY_SDR_RX, SOAPY_SDR_CS16, [0])
|
||||
return rx_stream
|
||||
|
||||
|
||||
def update_receiver_freq(sdr, stream, channel, freq_hz):
|
||||
sdr.setFrequency(SOAPY_SDR_RX, channel, freq_hz)
|
||||
|
@ -35,14 +35,14 @@ def update_receiver_freq(sdr, stream, channel, freq_hz):
|
|||
##
|
||||
|
||||
# Data and Source Configuration
|
||||
rx_chan = 0 # 6G = 1
|
||||
N = 16384 # Number of complex samples per transfer
|
||||
Fs = 4e6
|
||||
N = int(Fs/4) # Number of complex samples per transfer
|
||||
rx_buff = np.empty(2 * N, np.int16) # Create memory buffer for data stream
|
||||
freq = 915e6
|
||||
freq = 1090e6
|
||||
|
||||
# Initialize CaribouLite Soapy
|
||||
sdr = SoapySDR.Device(dict(driver="Cariboulite")) # Create Cariboulite
|
||||
rx_stream = setup_receiver(sdr, rx_chan, freq)
|
||||
sdr = SoapySDR.Device({"driver": "Cariboulite", "device_id": "1"})
|
||||
rx_stream = setup_receiver(sdr, freq)
|
||||
sdr.activateStream(rx_stream)
|
||||
|
||||
sr = sdr.readStream(rx_stream, [rx_buff], N, timeoutUs=int(5e6))
|
||||
|
@ -52,29 +52,33 @@ if (rc != N):
|
|||
print("Error Reading Samples from Device (error code = %d)!" % rc)
|
||||
exit
|
||||
|
||||
s_real = rx_buff[::2].astype(np.float32)
|
||||
s_imag = -rx_buff[1::2].astype(np.float32)
|
||||
s_real = rx_buff[::2].astype(np.float32) / 4096.0
|
||||
s_imag = rx_buff[1::2].astype(np.float32) / 4096.0
|
||||
x = s_real + 1j*s_imag
|
||||
|
||||
## PSD
|
||||
Fs = 4e6
|
||||
|
||||
#N = 2048
|
||||
#x = x[0:N] # we will only take the FFT of the first 1024 samples, see text below
|
||||
x = x * np.hamming(len(x)) # apply a Hamming window
|
||||
#x = x * np.hamming(len(x)) # apply a Hamming window
|
||||
|
||||
PSD = (np.abs(np.fft.fft(x))/N)**2
|
||||
PSD_log = 10.0*np.log10(PSD)
|
||||
PSD_shifted = np.fft.fftshift(PSD_log)
|
||||
#PSD = (np.abs(np.fft.fft(x))/N)**2
|
||||
#PSD_log = 10.0*np.log10(PSD)
|
||||
#PSD_shifted = np.fft.fftshift(PSD_log)
|
||||
|
||||
center_freq = freq
|
||||
f = np.arange(Fs/-2.0, Fs/2.0, Fs/N) # start, stop, step. centered around 0 Hz
|
||||
#center_freq = freq
|
||||
#f = np.arange(Fs/-2.0, Fs/2.0, Fs/N) # start, stop, step. centered around 0 Hz
|
||||
#f += center_freq # now add center frequency
|
||||
|
||||
fig = plt.figure()
|
||||
plt.plot(f, PSD_shifted)
|
||||
plt.show()
|
||||
window_size = 2048
|
||||
overlap = window_size - 64
|
||||
|
||||
fig = plt.figure()
|
||||
plt.plot(s_real)
|
||||
plt.plot(s_imag)
|
||||
plt.show()
|
||||
#plt.plot(f, PSD_shifted)
|
||||
plt.specgram(x, NFFT=window_size, Fs=Fs, noverlap=overlap, mode='psd')
|
||||
plt.show()
|
||||
|
||||
#fig = plt.figure()
|
||||
#plt.plot(s_real)
|
||||
#plt.plot(s_imag)
|
||||
#plt.show()
|
|
@ -68,7 +68,10 @@ SoapySDR::KwargsList findCariboulite(const SoapySDR::Kwargs &args)
|
|||
}
|
||||
|
||||
// no filterring specified, return all results
|
||||
if (args.count("serial") == 0 && args.count("label") == 0 && args.count("device_id") == 0) return results;
|
||||
if (args.count("serial") == 0 &&
|
||||
args.count("label") == 0 &&
|
||||
args.count("device_id") == 0 &&
|
||||
args.count("channel") == 0) return results;
|
||||
|
||||
// filter the return according to the "serial" or "label" or "device_id"
|
||||
std::vector<SoapySDR::Kwargs> filteredResults;
|
||||
|
@ -77,6 +80,7 @@ SoapySDR::KwargsList findCariboulite(const SoapySDR::Kwargs &args)
|
|||
int req_dev_num = args.count("device_id") == 0 ? -1 : atoi(args.at("device_id").c_str());
|
||||
std::string req_serial = args.count("serial") == 0 ? "" : args.at("serial");
|
||||
std::string req_label = args.count("label") == 0 ? "" : args.at("label");
|
||||
std::string req_channel = args.count("channel") == 0 ? "" : args.at("channel");
|
||||
|
||||
// search for the requested devNum within the un-filterred results
|
||||
for (size_t i = 0; i < results.size(); i++)
|
||||
|
@ -85,10 +89,12 @@ SoapySDR::KwargsList findCariboulite(const SoapySDR::Kwargs &args)
|
|||
int curDevNum = atoi(curArgs.at("device_id").c_str());
|
||||
std::string curSerial = curArgs.at("serial");
|
||||
std::string curLabel = curArgs.at("label");
|
||||
std::string curChannel = curArgs.at("channel");
|
||||
|
||||
if (curDevNum == req_dev_num ||
|
||||
!curSerial.compare(req_serial) ||
|
||||
!curLabel.compare(req_label))
|
||||
!curLabel.compare(req_label) ||
|
||||
!curChannel.compare(req_channel))
|
||||
{
|
||||
filteredResults.push_back(curArgs);
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue