Add RfRaw format input support
This commit is contained in:
parent
0f5241cda8
commit
96308f6468
8 changed files with 242 additions and 2 deletions
24
include/rfraw.h
Normal file
24
include/rfraw.h
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
/** @file
|
||||||
|
RfRaw format functions.
|
||||||
|
|
||||||
|
Copyright (C) 2020 Christian W. Zuckschwerdt <zany@triq.net>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDE_RFRAW_H_
|
||||||
|
#define INCLUDE_RFRAW_H_
|
||||||
|
|
||||||
|
#include "pulse_detect.h"
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
/// Check if a given string is in RfRaw format.
|
||||||
|
bool rfraw_check(char const *p);
|
||||||
|
|
||||||
|
/// Decode RfRaw string to pulse data.
|
||||||
|
bool rfraw_parse(pulse_data_t *data, char const *p);
|
||||||
|
|
||||||
|
#endif /* INCLUDE_RFRAW_H_ */
|
|
@ -26,6 +26,7 @@ add_library(r_433 STATIC
|
||||||
pulse_detect_fsk.c
|
pulse_detect_fsk.c
|
||||||
r_api.c
|
r_api.c
|
||||||
r_util.c
|
r_util.c
|
||||||
|
rfraw.c
|
||||||
samp_grab.c
|
samp_grab.c
|
||||||
sdr.c
|
sdr.c
|
||||||
term_ctl.c
|
term_ctl.c
|
||||||
|
|
|
@ -24,6 +24,7 @@ rtl_433_SOURCES = abuf.c \
|
||||||
pulse_detect_fsk.c \
|
pulse_detect_fsk.c \
|
||||||
r_api.c \
|
r_api.c \
|
||||||
r_util.c \
|
r_util.c \
|
||||||
|
rfraw.c \
|
||||||
rtl_433.c \
|
rtl_433.c \
|
||||||
samp_grab.c \
|
samp_grab.c \
|
||||||
sdr.c \
|
sdr.c \
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "pulse_detect.h"
|
#include "pulse_detect.h"
|
||||||
|
#include "rfraw.h"
|
||||||
#include "pulse_demod.h"
|
#include "pulse_demod.h"
|
||||||
#include "pulse_detect_fsk.h"
|
#include "pulse_detect_fsk.h"
|
||||||
#include "baseband.h"
|
#include "baseband.h"
|
||||||
|
@ -112,9 +113,9 @@ void pulse_data_print_vcd(FILE *file, pulse_data_t const *data, int ch_id)
|
||||||
|
|
||||||
void pulse_data_load(FILE *file, pulse_data_t *data, uint32_t sample_rate)
|
void pulse_data_load(FILE *file, pulse_data_t *data, uint32_t sample_rate)
|
||||||
{
|
{
|
||||||
char s[256];
|
char s[1024];
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int size = sizeof(data->pulse) / sizeof(int);
|
int size = sizeof(data->pulse) / sizeof(*data->pulse);
|
||||||
|
|
||||||
pulse_data_clear(data);
|
pulse_data_clear(data);
|
||||||
data->sample_rate = sample_rate;
|
data->sample_rate = sample_rate;
|
||||||
|
@ -136,6 +137,11 @@ void pulse_data_load(FILE *file, pulse_data_t *data, uint32_t sample_rate)
|
||||||
continue; // still reading a header
|
continue; // still reading a header
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (rfraw_check(s)) {
|
||||||
|
rfraw_parse(data, s);
|
||||||
|
i = data->num_pulses;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
// parse two ints.
|
// parse two ints.
|
||||||
char *p = s;
|
char *p = s;
|
||||||
char *endptr;
|
char *endptr;
|
||||||
|
|
175
src/rfraw.c
Normal file
175
src/rfraw.c
Normal file
|
@ -0,0 +1,175 @@
|
||||||
|
/** @file
|
||||||
|
RfRaw format functions.
|
||||||
|
|
||||||
|
Copyright (C) 2020 Christian W. Zuckschwerdt <zany@triq.net>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "rfraw.h"
|
||||||
|
#include "fatal.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static int hexstr_get_nibble(char const **p)
|
||||||
|
{
|
||||||
|
if (!p || !*p || !**p) return -1;
|
||||||
|
while (**p == ' ' || **p == '\t' || **p == '-' || **p == ':') ++*p;
|
||||||
|
|
||||||
|
int c = **p;
|
||||||
|
if (c >= '0' && c <= '9') {
|
||||||
|
++*p;
|
||||||
|
return c - '0';
|
||||||
|
}
|
||||||
|
if (c >= 'A' && c <= 'F') {
|
||||||
|
++*p;
|
||||||
|
return c - 'A' + 10;
|
||||||
|
}
|
||||||
|
if (c >= 'a' && c <= 'f') {
|
||||||
|
++*p;
|
||||||
|
return c - 'a' + 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hexstr_get_byte(char const **p)
|
||||||
|
{
|
||||||
|
int h = hexstr_get_nibble(p);
|
||||||
|
int l = hexstr_get_nibble(p);
|
||||||
|
if (h >= 0 && l >= 0)
|
||||||
|
return (h << 4) | l;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hexstr_get_word(char const **p)
|
||||||
|
{
|
||||||
|
int h = hexstr_get_byte(p);
|
||||||
|
int l = hexstr_get_byte(p);
|
||||||
|
if (h >= 0 && l >= 0)
|
||||||
|
return (h << 8) | l;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hexstr_peek_byte(char const *p)
|
||||||
|
{
|
||||||
|
int h = hexstr_get_nibble(&p);
|
||||||
|
int l = hexstr_get_nibble(&p);
|
||||||
|
if (h >= 0 && l >= 0)
|
||||||
|
return (h << 4) | l;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool rfraw_check(char const *p)
|
||||||
|
{
|
||||||
|
// require 0xaa 0xb0 or 0xaa 0xb1
|
||||||
|
return hexstr_get_nibble(&p) == 0xa
|
||||||
|
&& hexstr_get_nibble(&p) == 0xa
|
||||||
|
&& hexstr_get_nibble(&p) == 0xb
|
||||||
|
&& (hexstr_get_nibble(&p) | 1) == 0x1;
|
||||||
|
/*
|
||||||
|
if (!p || !*p) return false;
|
||||||
|
while (*p == ' ' || *p == '\t' || *p == '-' || *p == ':') ++p;
|
||||||
|
if (*p != 'A' && *p != 'a') return false;
|
||||||
|
p++;
|
||||||
|
while (*p == ' ' || *p == '\t' || *p == '-' || *p == ':') ++p;
|
||||||
|
if (*p != 'A' && *p != 'a') return false;
|
||||||
|
p++;
|
||||||
|
while (*p == ' ' || *p == '\t' || *p == '-' || *p == ':') ++p;
|
||||||
|
if (*p != 'B' && *p != 'b') return false;
|
||||||
|
p++;
|
||||||
|
while (*p == ' ' || *p == '\t' || *p == '-' || *p == ':') ++p;
|
||||||
|
if (*p != '0' && *p != '1') return false;
|
||||||
|
p++;
|
||||||
|
while (*p == ' ' || *p == '\t' || *p == '-' || *p == ':') ++p;
|
||||||
|
if (*p != '0') return false;
|
||||||
|
return true;
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool parse_rfraw(pulse_data_t *data, char const **p)
|
||||||
|
{
|
||||||
|
if (!p || !*p || !**p) return false;
|
||||||
|
|
||||||
|
int hdr = hexstr_get_byte(p);
|
||||||
|
if (hdr !=0xaa) return false;
|
||||||
|
|
||||||
|
int fmt = hexstr_get_byte(p);
|
||||||
|
if (fmt != 0xb0 && fmt != 0xb1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (fmt == 0xb0) {
|
||||||
|
hexstr_get_byte(p); // ignore len
|
||||||
|
}
|
||||||
|
|
||||||
|
int bins_len = hexstr_get_byte(p);
|
||||||
|
if (bins_len > 8) return false;
|
||||||
|
|
||||||
|
int repeats = 1;
|
||||||
|
if (fmt == 0xb0) {
|
||||||
|
repeats = hexstr_get_byte(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
int bins[8] = {0};
|
||||||
|
for (int i = 0; i < bins_len; ++i) {
|
||||||
|
bins[i] = hexstr_get_word(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned prev_pulses = data->num_pulses;
|
||||||
|
bool pulse_needed = true;
|
||||||
|
while (*p) {
|
||||||
|
if (hexstr_peek_byte(*p) == 0x55) {
|
||||||
|
hexstr_get_byte(p); // consume 0x55
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int w = hexstr_get_nibble(p);
|
||||||
|
if (w < 0) return false;
|
||||||
|
if (w >= 8) { // pulse
|
||||||
|
if (!pulse_needed) {
|
||||||
|
data->gap[data->num_pulses] = 0;
|
||||||
|
data->num_pulses++;
|
||||||
|
}
|
||||||
|
data->pulse[data->num_pulses] = bins[w & 7];
|
||||||
|
pulse_needed = false;
|
||||||
|
}
|
||||||
|
else { // gap
|
||||||
|
if (pulse_needed) {
|
||||||
|
data->pulse[data->num_pulses] = 0;
|
||||||
|
}
|
||||||
|
data->gap[data->num_pulses] = bins[w];
|
||||||
|
data->num_pulses++;
|
||||||
|
pulse_needed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//data->gap[data->num_pulses - 1] = 3000; // TODO: extend last gap?
|
||||||
|
|
||||||
|
unsigned pkt_pulses = data->num_pulses - prev_pulses;
|
||||||
|
for (int i = 1; i < repeats && data->num_pulses + pkt_pulses <= PD_MAX_PULSES; ++i) {
|
||||||
|
memcpy(&data->pulse[data->num_pulses], &data->pulse[prev_pulses], pkt_pulses * sizeof (*data->pulse));
|
||||||
|
memcpy(&data->gap[data->num_pulses], &data->gap[prev_pulses], pkt_pulses * sizeof (*data->pulse));
|
||||||
|
data->num_pulses += pkt_pulses;
|
||||||
|
}
|
||||||
|
//pulse_data_print(data);
|
||||||
|
|
||||||
|
data->sample_rate = 1000000; // us
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool rfraw_parse(pulse_data_t *data, char const *p)
|
||||||
|
{
|
||||||
|
if (!p || !*p)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// don't reset pulse data
|
||||||
|
// pulse_data_clear(data);
|
||||||
|
|
||||||
|
while (*p) {
|
||||||
|
if (!parse_rfraw(data, &p))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//pulse_data_print(data);
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -39,6 +39,7 @@
|
||||||
#include "pulse_detect.h"
|
#include "pulse_detect.h"
|
||||||
#include "pulse_detect_fsk.h"
|
#include "pulse_detect_fsk.h"
|
||||||
#include "pulse_demod.h"
|
#include "pulse_demod.h"
|
||||||
|
#include "rfraw.h"
|
||||||
#include "data.h"
|
#include "data.h"
|
||||||
#include "r_util.h"
|
#include "r_util.h"
|
||||||
#include "optparse.h"
|
#include "optparse.h"
|
||||||
|
@ -1349,10 +1350,29 @@ int main(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
if (cfg->verbosity)
|
if (cfg->verbosity)
|
||||||
fprintf(stderr, "Verifying test data with device %s.\n", r_dev->name);
|
fprintf(stderr, "Verifying test data with device %s.\n", r_dev->name);
|
||||||
|
if (rfraw_check(e)) {
|
||||||
|
pulse_data_t pulse_data = {0};
|
||||||
|
rfraw_parse(&pulse_data, e);
|
||||||
|
list_t single_dev = {0};
|
||||||
|
list_push(&single_dev, r_dev);
|
||||||
|
if (!pulse_data.fsk_f2_est)
|
||||||
|
r += run_ook_demods(&single_dev, &pulse_data);
|
||||||
|
else
|
||||||
|
r += run_fsk_demods(&single_dev, &pulse_data);
|
||||||
|
list_free_elems(&single_dev, NULL);
|
||||||
|
} else
|
||||||
r += pulse_demod_string(e, r_dev);
|
r += pulse_demod_string(e, r_dev);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// otherwise test all decoders
|
// otherwise test all decoders
|
||||||
|
if (rfraw_check(line)) {
|
||||||
|
pulse_data_t pulse_data = {0};
|
||||||
|
rfraw_parse(&pulse_data, line);
|
||||||
|
if (!pulse_data.fsk_f2_est)
|
||||||
|
r += run_ook_demods(&demod->r_devs, &pulse_data);
|
||||||
|
else
|
||||||
|
r += run_fsk_demods(&demod->r_devs, &pulse_data);
|
||||||
|
} else
|
||||||
for (void **iter = demod->r_devs.elems; iter && *iter; ++iter) {
|
for (void **iter = demod->r_devs.elems; iter && *iter; ++iter) {
|
||||||
r_device *r_dev = *iter;
|
r_device *r_dev = *iter;
|
||||||
if (cfg->verbosity)
|
if (cfg->verbosity)
|
||||||
|
@ -1371,6 +1391,14 @@ int main(int argc, char **argv) {
|
||||||
// Special case for string test data
|
// Special case for string test data
|
||||||
if (cfg->test_data) {
|
if (cfg->test_data) {
|
||||||
r = 0;
|
r = 0;
|
||||||
|
if (rfraw_check(cfg->test_data)) {
|
||||||
|
pulse_data_t pulse_data = {0};
|
||||||
|
rfraw_parse(&pulse_data, cfg->test_data);
|
||||||
|
if (!pulse_data.fsk_f2_est)
|
||||||
|
r += run_ook_demods(&demod->r_devs, &pulse_data);
|
||||||
|
else
|
||||||
|
r += run_fsk_demods(&demod->r_devs, &pulse_data);
|
||||||
|
} else
|
||||||
for (void **iter = demod->r_devs.elems; iter && *iter; ++iter) {
|
for (void **iter = demod->r_devs.elems; iter && *iter; ++iter) {
|
||||||
r_device *r_dev = *iter;
|
r_device *r_dev = *iter;
|
||||||
if (cfg->verbosity)
|
if (cfg->verbosity)
|
||||||
|
|
|
@ -118,6 +118,7 @@ COPY ..\..\libusb\MS64\dll\libusb*.dll $(TargetDir)</Command>
|
||||||
<ClInclude Include="..\include\r_device.h" />
|
<ClInclude Include="..\include\r_device.h" />
|
||||||
<ClInclude Include="..\include\r_private.h" />
|
<ClInclude Include="..\include\r_private.h" />
|
||||||
<ClInclude Include="..\include\r_util.h" />
|
<ClInclude Include="..\include\r_util.h" />
|
||||||
|
<ClInclude Include="..\include\rfraw.h" />
|
||||||
<ClInclude Include="..\include\rtl_433.h" />
|
<ClInclude Include="..\include\rtl_433.h" />
|
||||||
<ClInclude Include="..\include\rtl_433_devices.h" />
|
<ClInclude Include="..\include\rtl_433_devices.h" />
|
||||||
<ClInclude Include="..\include\samp_grab.h" />
|
<ClInclude Include="..\include\samp_grab.h" />
|
||||||
|
@ -149,6 +150,7 @@ COPY ..\..\libusb\MS64\dll\libusb*.dll $(TargetDir)</Command>
|
||||||
<ClCompile Include="..\src\pulse_detect_fsk.c" />
|
<ClCompile Include="..\src\pulse_detect_fsk.c" />
|
||||||
<ClCompile Include="..\src\r_api.c" />
|
<ClCompile Include="..\src\r_api.c" />
|
||||||
<ClCompile Include="..\src\r_util.c" />
|
<ClCompile Include="..\src\r_util.c" />
|
||||||
|
<ClCompile Include="..\src\rfraw.c" />
|
||||||
<ClCompile Include="..\src\rtl_433.c" />
|
<ClCompile Include="..\src\rtl_433.c" />
|
||||||
<ClCompile Include="..\src\samp_grab.c" />
|
<ClCompile Include="..\src\samp_grab.c" />
|
||||||
<ClCompile Include="..\src\sdr.c" />
|
<ClCompile Include="..\src\sdr.c" />
|
||||||
|
|
|
@ -178,6 +178,9 @@
|
||||||
<ClCompile Include="..\src\r_util.c">
|
<ClCompile Include="..\src\r_util.c">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\src\rfraw.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="..\src\rtl_433.c">
|
<ClCompile Include="..\src\rtl_433.c">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|
Loading…
Add table
Reference in a new issue