clock recovering for time2 method only if latter selected

pull/18/head
Xael South 2021-02-02 08:28:24 +00:00
rodzic 6d92d1b3f1
commit cec199312e
2 zmienionych plików z 57 dodań i 41 usunięć

Wyświetl plik

@ -43,7 +43,7 @@ static const uint32_t ACCESS_CODE = 0b0101010101010000111101u;
static const uint32_t ACCESS_CODE_BITMASK = 0x3FFFFFu;
static const unsigned ACCESS_CODE_ERRORS = 1u; // 0 if no errors allowed
/* deglitch_filter has been calculated by Python script as follows.
/* deglitch_filter has been calculated by a Python script as follows.
The filter is counting "1" among 7 bits and saying "1" if count("1") >= 3 else "0".
Notice here count("1") >= 3. (More intuitive in that case would be count("1") >= 3.5.)
That forces the filter to put more "1" than "0" on the output, because RTL-SDR streams
@ -83,6 +83,7 @@ static const uint8_t deglitch_filter[128] =
1,1,1,1,1,1,1,1
};
static float lp_1600kHz_56kHz(int sample, size_t i_or_q)
{
static float moving_average[2];
@ -334,6 +335,7 @@ struct runlength_algorithm
struct t1_c1_packet_decoder_work decoder;
};
static void runlength_algorithm_reset(struct runlength_algorithm *algo)
{
algo->run_length = 0;
@ -345,6 +347,7 @@ static void runlength_algorithm_reset(struct runlength_algorithm *algo)
reset_t1_c1_packet_decoder(&algo->decoder);
}
static void runlength_algorithm(unsigned raw_bit, unsigned rssi, struct runlength_algorithm *algo)
{
algo->raw_bitstream = (algo->raw_bitstream << 1) | raw_bit;
@ -406,7 +409,7 @@ static void runlength_algorithm(unsigned raw_bit, unsigned rssi, struct runlengt
#endif
// Some kind of PI controller is implemented below: u[n] = u[n-1] + Kp * e[n] + Ki * sum(e[0..n]).
// Kp and Ki were found by experiment; e[n] := algo->run_length
// Kp and Ki were found by experiment; e[n] := algo->run_length; u[[n] is the new bit length; u[n-1] is the last known bit length
algo->cum_run_length_error += algo->run_length; // sum(e[0..n])
#define PI_KP 32
#define PI_KI 16
@ -420,18 +423,21 @@ static void runlength_algorithm(unsigned raw_bit, unsigned rssi, struct runlengt
}
}
struct time2_algorithm
{
uint32_t bitstream;
struct t1_c1_packet_decoder_work decoder;
};
static void time2_algorithm_reset(struct time2_algorithm *algo)
{
algo->bitstream = 0;
reset_t1_c1_packet_decoder(&algo->decoder);
}
static void time2_algorithm(unsigned bit, unsigned rssi, struct time2_algorithm *algo)
{
algo->bitstream = (algo->bitstream << 1) | bit;
@ -444,10 +450,13 @@ static void time2_algorithm(unsigned bit, unsigned rssi, struct time2_algorithm
t1_c1_packet_decoder(bit, rssi, &algo->decoder, "t2a;");
}
static int opts_run_length_algorithm_enabled = 1;
static int opts_time2_algorithm_enabled = 1;
static unsigned decimation_rate = 2u;
int show_used_algorithm = 0;
static unsigned opts_decimation_rate = 2u;
int opts_show_used_algorithm = 0;
static const unsigned opts_CLOCK_LOCK_THRESHOLD = 2;
static void print_usage(const char *program_name)
{
@ -458,6 +467,7 @@ static void print_usage(const char *program_name)
fprintf(stdout, "\t-s show used algorithm in the output\n");
}
static void process_options(int argc, char *argv[])
{
int option;
@ -489,10 +499,10 @@ static void process_options(int argc, char *argv[])
}
break;
case 'd':
decimation_rate = strtoul(optarg, NULL, 10);
opts_decimation_rate = strtoul(optarg, NULL, 10);
break;
case 's':
show_used_algorithm = 1;
opts_show_used_algorithm = 1;
break;
default:
print_usage(argv[0]);
@ -505,14 +515,6 @@ int main(int argc, char *argv[])
{
process_options(argc, argv);
// --- parameter section begin ---
// The idea behind the variables in the section is to make parameters
// configurable via command line.
const unsigned CLOCK_LOCK_THRESHOLD = 2;
// --- parameter section end ---
__attribute__((__aligned__(16))) uint8_t samples[4096];
float i = 0, q = 0;
unsigned decimation_rate_index = 0;
@ -587,7 +589,7 @@ int main(int argc, char *argv[])
#endif
++decimation_rate_index;
if (decimation_rate_index < decimation_rate) continue;
if (decimation_rate_index < opts_decimation_rate) continue;
decimation_rate_index = 0;
// Demodulate.
@ -605,46 +607,60 @@ int main(int argc, char *argv[])
//int16_t u = bit ? (INT16_MAX-1) : 0;
//fwrite(&u, sizeof(u), 1, rawbits_out);
// --- rssi filtering section begin ---
// We are using one simple filter to rssi value in order to
// prevent unexpected "splashes" in signal power.
float rssi = sqrtf(i*i + q*q);
rssi = rssi_filter(rssi); // comment out, if rssi filtering is unwanted
#if defined(USE_MOVING_AVERAGE)
// If using moving average, we would have doubles of each of i- and q- signal components.
rssi /= decimation_rate;
// If using moving average, we would have multiples of I- and Q- signal components.
rssi /= opts_decimation_rate;
#endif
// --- rssi filtering section end ---
// --- runlength algorithm section begin ---
if (opts_run_length_algorithm_enabled) runlength_algorithm(bit, rssi, &rl_algo);
if (opts_run_length_algorithm_enabled)
{
runlength_algorithm(bit, rssi, &rl_algo);
}
// --- runlength algorithm section end ---
// --- clock recovery section begin ---
// The time-2 method is implemented: push squared signal through a bandpass
// tuned close to the symbol rate. Saturating band-pass output produces a
// rectangular pulses with the required timing information.
// Clock-Signal is crossing zero in half period.
const int16_t clock = (bp_iir_cheb1_800kHz_90kHz_98kHz_102kHz_110kHz(delta_phi * delta_phi) >= 0) ? INT16_MAX : INT16_MIN;
//fwrite(&clock, sizeof(clock), 1, clock_out);
if (clock > old_clock) // rising edge
// --- time2 algorithm section begin ---
if (opts_time2_algorithm_enabled)
{
clock_lock = 1;
}
else if (old_clock == clock && clock_lock < CLOCK_LOCK_THRESHOLD)
{
clock_lock++;
}
else if (clock_lock == CLOCK_LOCK_THRESHOLD) // sample data bit on CLOCK_LOCK_THRESHOLD after rose up
{
clock_lock++;
// --- clock recovery section begin ---
// The time-2 method is implemented: push squared signal through a bandpass
// tuned close to the symbol rate. Saturating band-pass output produces a
// rectangular pulses with the required timing information.
// Clock-Signal is crossing zero in half period.
const int16_t clock = (bp_iir_cheb1_800kHz_90kHz_98kHz_102kHz_110kHz(delta_phi * delta_phi) >= 0) ? INT16_MAX : INT16_MIN;
//fwrite(&clock, sizeof(clock), 1, clock_out);
//fwrite(&bit, sizeof(bit), 1, bits_out);
if (opts_time2_algorithm_enabled) time2_algorithm(bit, rssi, &t2_algo);
if (clock > old_clock)
{ // Clock signal rising edge detected.
clock_lock = 1;
}
else if (clock == INT16_MAX)
{ // Clock signal is still high.
if (clock_lock < opts_CLOCK_LOCK_THRESHOLD)
{ // Skip up to (opts_CLOCK_LOCK_THRESHOLD - 1) clock bits
// to get closer to the middle of the data bit.
clock_lock++;
}
else if (clock_lock == opts_CLOCK_LOCK_THRESHOLD)
{ // Sample data bit at CLOCK_LOCK_THRESHOLD clock bit position.
clock_lock++;
time2_algorithm(bit, rssi, &t2_algo);
//fwrite(&bit, sizeof(bit), 1, bits_out);
}
}
old_clock = clock;
// --- clock recovery section end ---
}
old_clock = clock;
// --- clock recovery section end ---
// --- time2 algorithm section end ---
#if defined(USE_MOVING_AVERAGE)
i = q = 0;

Wyświetl plik

@ -661,7 +661,7 @@ static inline uint32_t get_serial(const uint8_t *const packet)
return serial;
}
extern int show_used_algorithm;
extern int opts_show_used_algorithm;
static void t1_c1_packet_decoder(unsigned bit, unsigned rssi, struct t1_c1_packet_decoder_work *decoder, const char *algorithm)
{
@ -684,7 +684,7 @@ static void t1_c1_packet_decoder(unsigned bit, unsigned rssi, struct t1_c1_packe
decoder->crc_ok = check_calc_crc_wmbus(decoder->packet, decoder->L) ? 1 : 0;
}
if (!show_used_algorithm) algorithm = "";
if (!opts_show_used_algorithm) algorithm = "";
fprintf(stdout, "%s%s;%u;%u;%s;%u;%u;%08X;", algorithm, decoder->c1_packet ? "C1": "T1",
decoder->crc_ok,
decoder->err_3outof^1,