diff --git a/README.md b/README.md index 1897f740..054ddb05 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,7 @@ Usage: = Tuner options = [-D] Print debug info on event (repeat for more info) [-q] Quiet mode, suppress non-data messages [-W] Overwrite mode, disable checks to prevent files from being overwritten + [-y ] Verify decoding of raw data (e.g. "{25}fb2dd58") with enabled devices = File I/O options = [-t] Test signal auto save. Use it together with analyze mode (-a -t). Creates one file per signal Note: Saves raw I/Q samples (uint8 pcm, 2 channel). Preferred mode for generating test files diff --git a/include/pulse_demod.h b/include/pulse_demod.h index 15e489ae..06f3615a 100755 --- a/include/pulse_demod.h +++ b/include/pulse_demod.h @@ -138,4 +138,14 @@ int pulse_demod_clock_bits(const pulse_data_t *pulses, struct protocol_state *de int pulse_demod_osv1(const pulse_data_t *pulses, struct protocol_state *device); + +/// Simulate demodulation using a given signal code string +/// +/// The (optionally "0x" prefixed) hex code is processed into a bitbuffer_t. +/// Each row is optionally prefixed with a length enclosed in braces "{}" or +/// separated with a slash "/" character. Whitespace is ignored. +/// Device params are disregarded. +/// @return number of events processed +int pulse_demod_string(const char *code, struct protocol_state *device); + #endif /* INCLUDE_PULSE_DEMOD_H_ */ diff --git a/src/pulse_demod.c b/src/pulse_demod.c index 8216c609..ecba6260 100755 --- a/src/pulse_demod.c +++ b/src/pulse_demod.c @@ -401,3 +401,68 @@ int pulse_demod_osv1(const pulse_data_t *pulses, struct protocol_state *device) } return events; } + + +int pulse_demod_string(const char *code, struct protocol_state *device) +{ + int events = 0; + bitbuffer_t bits = {0}; + const char *c; + int data = 0; + int width = -1; + + for(c = code; *c; ++c) { + + if (*c == ' ') { + continue; + + } else if (*c == '0' && (*(c+1) == 'x' || *(c+1) == 'X')) { + ++c; + continue; + + } else if (*c == '{') { + if (bits.num_rows > 0) { + if (width >= 0) { + bits.bits_per_row[bits.num_rows - 1] = width; + } + bitbuffer_add_row(&bits); + } + + width = strtol(c+1, (char **)&c, 0); + continue; + + } else if (*c == '/') { + bitbuffer_add_row(&bits); + if (width >= 0) { + bits.bits_per_row[bits.num_rows - 2] = width; + width = -1; + } + continue; + + } else if (*c >= '0' && *c <= '9') { + data = *c - '0'; + } else if (*c >= 'A' && *c <= 'F') { + data = *c - 'A' + 10; + } else if (*c >= 'a' && *c <= 'f') { + data = *c - 'a' + 10; + } + bitbuffer_add_bit(&bits, data >> 3 & 0x01); + bitbuffer_add_bit(&bits, data >> 2 & 0x01); + bitbuffer_add_bit(&bits, data >> 1 & 0x01); + bitbuffer_add_bit(&bits, data >> 0 & 0x01); + } + if (width >= 0 && bits.num_rows > 0) { + bits.bits_per_row[bits.num_rows - 1] = width; + } + + if (device->callback) { + events += device->callback(&bits); + } + // Debug printout + if(!device->callback || (debug_output && events > 0)) { + fprintf(stderr, "pulse_demod_pcm(): %s \n", device->name); + bitbuffer_print(&bits); + } + + return events; +} diff --git a/src/rtl_433.c b/src/rtl_433.c index 0e2bbcf2..3c45251a 100755 --- a/src/rtl_433.c +++ b/src/rtl_433.c @@ -101,7 +101,7 @@ void usage(r_device *devices) { "\t[-d ] (default: 0)\n" "\t[-g ] (default: 0 for auto)\n" "\t[-f ] [-f...] Receive frequency(s) (default: %i Hz)\n" - "\t[-H ] Hop interval for polling of multiple frequencies (default: %i seconds)\n" + "\t[-H ] Hop interval for polling of multiple frequencies (default: %i seconds)\n" "\t[-p ] Set sample rate (default: %i Hz)\n" "\t[-S] Force sync output (default: async)\n" @@ -119,6 +119,7 @@ void usage(r_device *devices) { "\t[-D] Print debug info on event (repeat for more info)\n" "\t[-q] Quiet mode, suppress non-data messages\n" "\t[-W] Overwrite mode, disable checks to prevent files from being overwritten\n" + "\t[-y ] Verify decoding of demodulated test data (e.g. \"{25}fb2dd58\") with enabled devices\n" "\t= File I/O options =\n" "\t[-t] Test signal auto save. Use it together with analyze mode (-a -t). Creates one file per signal\n" "\t\t Note: Saves raw I/Q samples (uint8 pcm, 2 channel). Preferred mode for generating test files\n" @@ -865,6 +866,7 @@ int main(int argc, char **argv) { #ifndef _WIN32 struct sigaction sigact; #endif + char *test_data = NULL; char *out_filename = NULL; char *in_filename = NULL; FILE *in_file; @@ -902,7 +904,7 @@ int main(int argc, char **argv) { demod->level_limit = DEFAULT_LEVEL_LIMIT; demod->hop_time = DEFAULT_HOP_TIME; - while ((opt = getopt(argc, argv, "x:z:p:DtaAI:qm:r:l:d:f:H:g:s:b:n:SR:F:C:T:UWG")) != -1) { + while ((opt = getopt(argc, argv, "x:z:p:DtaAI:qm:r:l:d:f:H:g:s:b:n:SR:F:C:T:UWGy:")) != -1) { switch (opt) { case 'd': dev_index = atoi(optarg); @@ -1026,6 +1028,9 @@ int main(int argc, char **argv) { stop_time += duration; } break; + case 'y': + test_data = optarg; + break; default: usage(devices); break; @@ -1066,6 +1071,16 @@ int main(int argc, char **argv) { out_block_size = DEFAULT_BUF_LENGTH; } + if (test_data) { + r = 0; + for (i = 0; i < demod->r_dev_num; i++) { + if (!quiet_mode) + fprintf(stderr, "Verifing test data with device %s.\n", demod->r_devs[i]->name); + r += pulse_demod_string(test_data, demod->r_devs[i]); + } + exit(!r); + } + if (!in_filename) { device_count = rtlsdr_get_device_count(); if (!device_count) {