Measure mean signal level in the converters.
Rearrange the meaning of the measured power level to be consistent with the signal level.
This commit is contained in:
parent
8182dc9a8f
commit
cc47718a2d
99
convert.c
99
convert.c
|
@ -30,11 +30,13 @@ static void convert_uc8_nodc(void *iq_data,
|
||||||
uint16_t *mag_data,
|
uint16_t *mag_data,
|
||||||
unsigned nsamples,
|
unsigned nsamples,
|
||||||
struct converter_state *state,
|
struct converter_state *state,
|
||||||
double *out_power)
|
double *out_mean_level,
|
||||||
|
double *out_mean_power)
|
||||||
{
|
{
|
||||||
uint16_t *in = iq_data;
|
uint16_t *in = iq_data;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
uint64_t power = 0;
|
uint64_t sum_level = 0;
|
||||||
|
uint64_t sum_power = 0;
|
||||||
uint16_t mag;
|
uint16_t mag;
|
||||||
|
|
||||||
MODES_NOTUSED(state);
|
MODES_NOTUSED(state);
|
||||||
|
@ -43,45 +45,58 @@ static void convert_uc8_nodc(void *iq_data,
|
||||||
for (i = 0; i < (nsamples>>3); ++i) {
|
for (i = 0; i < (nsamples>>3); ++i) {
|
||||||
mag = Modes.maglut[*in++];
|
mag = Modes.maglut[*in++];
|
||||||
*mag_data++ = mag;
|
*mag_data++ = mag;
|
||||||
power += (uint32_t)mag * (uint32_t)mag;
|
sum_level += mag;
|
||||||
|
sum_power += (uint32_t)mag * (uint32_t)mag;
|
||||||
|
|
||||||
mag = Modes.maglut[*in++];
|
mag = Modes.maglut[*in++];
|
||||||
*mag_data++ = mag;
|
*mag_data++ = mag;
|
||||||
power += (uint32_t)mag * (uint32_t)mag;
|
sum_level += mag;
|
||||||
|
sum_power += (uint32_t)mag * (uint32_t)mag;
|
||||||
|
|
||||||
mag = Modes.maglut[*in++];
|
mag = Modes.maglut[*in++];
|
||||||
*mag_data++ = mag;
|
*mag_data++ = mag;
|
||||||
power += (uint32_t)mag * (uint32_t)mag;
|
sum_level += mag;
|
||||||
|
sum_power += (uint32_t)mag * (uint32_t)mag;
|
||||||
|
|
||||||
mag = Modes.maglut[*in++];
|
mag = Modes.maglut[*in++];
|
||||||
*mag_data++ = mag;
|
*mag_data++ = mag;
|
||||||
power += (uint32_t)mag * (uint32_t)mag;
|
sum_level += mag;
|
||||||
|
sum_power += (uint32_t)mag * (uint32_t)mag;
|
||||||
|
|
||||||
mag = Modes.maglut[*in++];
|
mag = Modes.maglut[*in++];
|
||||||
*mag_data++ = mag;
|
*mag_data++ = mag;
|
||||||
power += (uint32_t)mag * (uint32_t)mag;
|
sum_level += mag;
|
||||||
|
sum_power += (uint32_t)mag * (uint32_t)mag;
|
||||||
|
|
||||||
mag = Modes.maglut[*in++];
|
mag = Modes.maglut[*in++];
|
||||||
*mag_data++ = mag;
|
*mag_data++ = mag;
|
||||||
power += (uint32_t)mag * (uint32_t)mag;
|
sum_level += mag;
|
||||||
|
sum_power += (uint32_t)mag * (uint32_t)mag;
|
||||||
|
|
||||||
mag = Modes.maglut[*in++];
|
mag = Modes.maglut[*in++];
|
||||||
*mag_data++ = mag;
|
*mag_data++ = mag;
|
||||||
power += (uint32_t)mag * (uint32_t)mag;
|
sum_level += mag;
|
||||||
|
sum_power += (uint32_t)mag * (uint32_t)mag;
|
||||||
|
|
||||||
mag = Modes.maglut[*in++];
|
mag = Modes.maglut[*in++];
|
||||||
*mag_data++ = mag;
|
*mag_data++ = mag;
|
||||||
power += (uint32_t)mag * (uint32_t)mag;
|
sum_level += mag;
|
||||||
|
sum_power += (uint32_t)mag * (uint32_t)mag;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < (nsamples&7); ++i) {
|
for (i = 0; i < (nsamples&7); ++i) {
|
||||||
mag = Modes.maglut[*in++];
|
mag = Modes.maglut[*in++];
|
||||||
*mag_data++ = mag;
|
*mag_data++ = mag;
|
||||||
power += (uint32_t)mag * (uint32_t)mag;
|
sum_level += mag;
|
||||||
|
sum_power += (uint32_t)mag * (uint32_t)mag;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (out_power) {
|
if (out_mean_level) {
|
||||||
*out_power = power / 65535.0 / 65535.0;
|
*out_mean_level = sum_level / 65536.0 / nsamples;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (out_mean_power) {
|
||||||
|
*out_mean_power = sum_power / 65535.0 / 65535.0 / nsamples;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,10 +104,10 @@ static void convert_uc8_generic(void *iq_data,
|
||||||
uint16_t *mag_data,
|
uint16_t *mag_data,
|
||||||
unsigned nsamples,
|
unsigned nsamples,
|
||||||
struct converter_state *state,
|
struct converter_state *state,
|
||||||
double *out_power)
|
double *out_mean_level,
|
||||||
|
double *out_mean_power)
|
||||||
{
|
{
|
||||||
uint8_t *in = iq_data;
|
uint8_t *in = iq_data;
|
||||||
float power = 0.0;
|
|
||||||
float z1_I = state->z1_I;
|
float z1_I = state->z1_I;
|
||||||
float z1_Q = state->z1_Q;
|
float z1_Q = state->z1_Q;
|
||||||
const float dc_a = state->dc_a;
|
const float dc_a = state->dc_a;
|
||||||
|
@ -101,6 +116,7 @@ static void convert_uc8_generic(void *iq_data,
|
||||||
unsigned i;
|
unsigned i;
|
||||||
uint8_t I, Q;
|
uint8_t I, Q;
|
||||||
float fI, fQ, magsq;
|
float fI, fQ, magsq;
|
||||||
|
float sum_level = 0, sum_power = 0;
|
||||||
|
|
||||||
for (i = 0; i < nsamples; ++i) {
|
for (i = 0; i < nsamples; ++i) {
|
||||||
I = *in++;
|
I = *in++;
|
||||||
|
@ -118,25 +134,32 @@ static void convert_uc8_generic(void *iq_data,
|
||||||
if (magsq > 1)
|
if (magsq > 1)
|
||||||
magsq = 1;
|
magsq = 1;
|
||||||
|
|
||||||
power += magsq;
|
float mag = sqrtf(magsq);
|
||||||
*mag_data++ = (uint16_t)(sqrtf(magsq) * 65535.0 + 0.5);
|
sum_power += magsq;
|
||||||
|
sum_level += mag;
|
||||||
|
*mag_data++ = (uint16_t)(mag * 65535.0 + 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
state->z1_I = z1_I;
|
state->z1_I = z1_I;
|
||||||
state->z1_Q = z1_Q;
|
state->z1_Q = z1_Q;
|
||||||
|
|
||||||
if (out_power)
|
if (out_mean_level) {
|
||||||
*out_power = power;
|
*out_mean_level = sum_level / nsamples;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (out_mean_power) {
|
||||||
|
*out_mean_power = sum_power / nsamples;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void convert_sc16_generic(void *iq_data,
|
static void convert_sc16_generic(void *iq_data,
|
||||||
uint16_t *mag_data,
|
uint16_t *mag_data,
|
||||||
unsigned nsamples,
|
unsigned nsamples,
|
||||||
struct converter_state *state,
|
struct converter_state *state,
|
||||||
double *out_power)
|
double *out_mean_level,
|
||||||
|
double *out_mean_power)
|
||||||
{
|
{
|
||||||
uint16_t *in = iq_data;
|
uint16_t *in = iq_data;
|
||||||
float power = 0.0;
|
|
||||||
float z1_I = state->z1_I;
|
float z1_I = state->z1_I;
|
||||||
float z1_Q = state->z1_Q;
|
float z1_Q = state->z1_Q;
|
||||||
const float dc_a = state->dc_a;
|
const float dc_a = state->dc_a;
|
||||||
|
@ -145,6 +168,7 @@ static void convert_sc16_generic(void *iq_data,
|
||||||
unsigned i;
|
unsigned i;
|
||||||
int16_t I, Q;
|
int16_t I, Q;
|
||||||
float fI, fQ, magsq;
|
float fI, fQ, magsq;
|
||||||
|
float sum_level = 0, sum_power = 0;
|
||||||
|
|
||||||
for (i = 0; i < nsamples; ++i) {
|
for (i = 0; i < nsamples; ++i) {
|
||||||
I = (int16_t)le16toh(*in++);
|
I = (int16_t)le16toh(*in++);
|
||||||
|
@ -162,25 +186,32 @@ static void convert_sc16_generic(void *iq_data,
|
||||||
if (magsq > 1)
|
if (magsq > 1)
|
||||||
magsq = 1;
|
magsq = 1;
|
||||||
|
|
||||||
power += magsq;
|
float mag = sqrtf(magsq);
|
||||||
*mag_data++ = (uint16_t)(sqrtf(magsq) * 65535.0 + 0.5);
|
sum_power += magsq;
|
||||||
|
sum_level += mag;
|
||||||
|
*mag_data++ = (uint16_t)(mag * 65535.0 + 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
state->z1_I = z1_I;
|
state->z1_I = z1_I;
|
||||||
state->z1_Q = z1_Q;
|
state->z1_Q = z1_Q;
|
||||||
|
|
||||||
if (out_power)
|
if (out_mean_level) {
|
||||||
*out_power = power;
|
*out_mean_level = sum_level / nsamples;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (out_mean_power) {
|
||||||
|
*out_mean_power = sum_power / nsamples;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void convert_sc16q11_generic(void *iq_data,
|
static void convert_sc16q11_generic(void *iq_data,
|
||||||
uint16_t *mag_data,
|
uint16_t *mag_data,
|
||||||
unsigned nsamples,
|
unsigned nsamples,
|
||||||
struct converter_state *state,
|
struct converter_state *state,
|
||||||
double *out_power)
|
double *out_mean_level,
|
||||||
|
double *out_mean_power)
|
||||||
{
|
{
|
||||||
uint16_t *in = iq_data;
|
uint16_t *in = iq_data;
|
||||||
float power = 0.0;
|
|
||||||
float z1_I = state->z1_I;
|
float z1_I = state->z1_I;
|
||||||
float z1_Q = state->z1_Q;
|
float z1_Q = state->z1_Q;
|
||||||
const float dc_a = state->dc_a;
|
const float dc_a = state->dc_a;
|
||||||
|
@ -189,6 +220,7 @@ static void convert_sc16q11_generic(void *iq_data,
|
||||||
unsigned i;
|
unsigned i;
|
||||||
int16_t I, Q;
|
int16_t I, Q;
|
||||||
float fI, fQ, magsq;
|
float fI, fQ, magsq;
|
||||||
|
float sum_level = 0, sum_power = 0;
|
||||||
|
|
||||||
for (i = 0; i < nsamples; ++i) {
|
for (i = 0; i < nsamples; ++i) {
|
||||||
I = (int16_t)le16toh(*in++);
|
I = (int16_t)le16toh(*in++);
|
||||||
|
@ -206,15 +238,22 @@ static void convert_sc16q11_generic(void *iq_data,
|
||||||
if (magsq > 1)
|
if (magsq > 1)
|
||||||
magsq = 1;
|
magsq = 1;
|
||||||
|
|
||||||
power += magsq;
|
float mag = sqrtf(magsq);
|
||||||
|
sum_power += magsq;
|
||||||
|
sum_level += mag;
|
||||||
*mag_data++ = (uint16_t)(sqrtf(magsq) * 65535.0 + 0.5);
|
*mag_data++ = (uint16_t)(sqrtf(magsq) * 65535.0 + 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
state->z1_I = z1_I;
|
state->z1_I = z1_I;
|
||||||
state->z1_Q = z1_Q;
|
state->z1_Q = z1_Q;
|
||||||
|
|
||||||
if (out_power)
|
if (out_mean_level) {
|
||||||
*out_power = power;
|
*out_mean_level = sum_level / nsamples;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (out_mean_power) {
|
||||||
|
*out_mean_power = sum_power / nsamples;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
|
|
|
@ -27,7 +27,8 @@ typedef void (*iq_convert_fn)(void *iq_data,
|
||||||
uint16_t *mag_data,
|
uint16_t *mag_data,
|
||||||
unsigned nsamples,
|
unsigned nsamples,
|
||||||
struct converter_state *state,
|
struct converter_state *state,
|
||||||
double *out_power);
|
double *out_mean_level,
|
||||||
|
double *out_mean_power);
|
||||||
|
|
||||||
iq_convert_fn init_converter(input_format_t format,
|
iq_convert_fn init_converter(input_format_t format,
|
||||||
double sample_rate,
|
double sample_rate,
|
||||||
|
|
|
@ -360,7 +360,7 @@ void demodulate2400(struct mag_buf *mag)
|
||||||
/* update noise power */
|
/* update noise power */
|
||||||
{
|
{
|
||||||
double sum_signal_power = sum_scaled_signal_power / 65535.0 / 65535.0;
|
double sum_signal_power = sum_scaled_signal_power / 65535.0 / 65535.0;
|
||||||
Modes.stats_current.noise_power_sum += (mag->total_power - sum_signal_power);
|
Modes.stats_current.noise_power_sum += (mag->mean_power * mag->length - sum_signal_power);
|
||||||
Modes.stats_current.noise_power_count += mag->length;
|
Modes.stats_current.noise_power_count += mag->length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -246,9 +246,10 @@ void modesInit(void) {
|
||||||
static void convert_samples(void *iq,
|
static void convert_samples(void *iq,
|
||||||
uint16_t *mag,
|
uint16_t *mag,
|
||||||
unsigned nsamples,
|
unsigned nsamples,
|
||||||
double *power)
|
double *mean_level,
|
||||||
|
double *mean_power)
|
||||||
{
|
{
|
||||||
Modes.converter_function(iq, mag, nsamples, Modes.converter_state, power);
|
Modes.converter_function(iq, mag, nsamples, Modes.converter_state, mean_level, mean_power);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -445,7 +446,7 @@ void rtlsdrCallback(unsigned char *buf, uint32_t len, void *ctx) {
|
||||||
|
|
||||||
// Convert the new data
|
// Convert the new data
|
||||||
outbuf->length = slen;
|
outbuf->length = slen;
|
||||||
convert_samples(buf, &outbuf->data[Modes.trailing_samples], slen, &outbuf->total_power);
|
convert_samples(buf, &outbuf->data[Modes.trailing_samples], slen, &outbuf->mean_level, &outbuf->mean_power);
|
||||||
|
|
||||||
// Push the new data to the demodulation thread
|
// Push the new data to the demodulation thread
|
||||||
pthread_mutex_lock(&Modes.data_mutex);
|
pthread_mutex_lock(&Modes.data_mutex);
|
||||||
|
@ -538,7 +539,7 @@ void readDataFromFile(void) {
|
||||||
slen = outbuf->length = MODES_MAG_BUF_SAMPLES - toread/bytes_per_sample;
|
slen = outbuf->length = MODES_MAG_BUF_SAMPLES - toread/bytes_per_sample;
|
||||||
|
|
||||||
// Convert the new data
|
// Convert the new data
|
||||||
convert_samples(readbuf, &outbuf->data[Modes.trailing_samples], slen, &outbuf->total_power);
|
convert_samples(readbuf, &outbuf->data[Modes.trailing_samples], slen, &outbuf->mean_level, &outbuf->mean_power);
|
||||||
|
|
||||||
if (Modes.throttle) {
|
if (Modes.throttle) {
|
||||||
// Wait until we are allowed to release this buffer to the main thread
|
// Wait until we are allowed to release this buffer to the main thread
|
||||||
|
|
|
@ -255,7 +255,8 @@ struct mag_buf {
|
||||||
uint64_t sampleTimestamp; // Clock timestamp of the start of this block, 12MHz clock
|
uint64_t sampleTimestamp; // Clock timestamp of the start of this block, 12MHz clock
|
||||||
struct timespec sysTimestamp; // Estimated system time at start of block
|
struct timespec sysTimestamp; // Estimated system time at start of block
|
||||||
uint32_t dropped; // Number of dropped samples preceding this buffer
|
uint32_t dropped; // Number of dropped samples preceding this buffer
|
||||||
double total_power; // Sum of per-sample input power (in the range [0.0,1.0] per sample), or 0 if not measured
|
double mean_level; // Mean of normalized (0..1) signal level
|
||||||
|
double mean_power; // Mean of normalized (0..1) power level
|
||||||
};
|
};
|
||||||
|
|
||||||
// Program global state
|
// Program global state
|
||||||
|
|
Loading…
Reference in a new issue