diff --git a/include/list.h b/include/list.h index 0e4342a5..6e40744a 100644 --- a/include/list.h +++ b/include/list.h @@ -9,6 +9,9 @@ (at your option) any later version. */ +#ifndef INCLUDE_LIST_H_ +#define INCLUDE_LIST_H_ + #include <stddef.h> /// Dynamically growing list, elems is always NULL terminated, call list_ensure_size() to alloc elems. @@ -37,3 +40,5 @@ void list_clear(list_t *list, list_elem_free_fn elem_free); /// Clear the list, free backing, does not free list itself. void list_free_elems(list_t *list, list_elem_free_fn elem_free); + +#endif /* INCLUDE_LIST_H_ */ diff --git a/include/r_api.h b/include/r_api.h new file mode 100644 index 00000000..0def613a --- /dev/null +++ b/include/r_api.h @@ -0,0 +1,29 @@ +/** @file + Generic RF data receiver and decoder for ISM band devices using RTL-SDR and SoapySDR. + + Copyright (C) 2019 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_R_API_H_ +#define INCLUDE_R_API_H_ + +#include <stdint.h> + +struct r_cfg; + +/* general */ + +char const *version_string(void); + +struct r_cfg *r_create_cfg(void); + +void r_init_cfg(struct r_cfg *cfg); + +void r_free_cfg(struct r_cfg *cfg); + +#endif /* INCLUDE_R_API_H_ */ diff --git a/include/r_private.h b/include/r_private.h new file mode 100644 index 00000000..60720532 --- /dev/null +++ b/include/r_private.h @@ -0,0 +1,52 @@ +/** @file + Definition of r_private state structure. +*/ + +#ifndef INCLUDE_R_PRIVATE_H_ +#define INCLUDE_R_PRIVATE_H_ + +#include <stdint.h> +#include <time.h> +#include "list.h" +#include "baseband.h" +#include "pulse_detect.h" +#include "fileformat.h" +#include "samp_grab.h" +#include "am_analyze.h" +#include "rtl_433.h" + +struct dm_state { + int32_t level_limit; + int16_t am_buf[MAXIMAL_BUF_LENGTH]; // AM demodulated signal (for OOK decoding) + union { + // These buffers aren't used at the same time, so let's use a union to save some memory + int16_t fm[MAXIMAL_BUF_LENGTH]; // FM demodulated signal (for FSK decoding) + uint16_t temp[MAXIMAL_BUF_LENGTH]; // Temporary buffer (to be optimized out..) + } buf; + uint8_t u8_buf[MAXIMAL_BUF_LENGTH]; // format conversion buffer + float f32_buf[MAXIMAL_BUF_LENGTH]; // format conversion buffer + int sample_size; // CU8: 1, CS16: 2 + pulse_detect_t *pulse_detect; + filter_state_t lowpass_filter_state; + demodfm_state_t demod_FM_state; + int enable_FM_demod; + samp_grab_t *samp_grab; + am_analyze_t *am_analyze; + int analyze_pulses; + file_info_t load_info; + list_t dumper; + int hop_time; + + /* Protocol states */ + list_t r_devs; + + pulse_data_t pulse_data; + pulse_data_t fsk_pulse_data; + unsigned frame_event_count; + unsigned frame_start_ago; + unsigned frame_end_ago; + struct timeval now; + float sample_file_pos; +}; + +#endif /* INCLUDE_R_PRIVATE_H_ */ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c1abf747..7d0f882d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -18,6 +18,7 @@ add_executable(rtl_433 output_mqtt.c pulse_demod.c pulse_detect.c + r_api.c r_util.c rtl_433.c samp_grab.c diff --git a/src/Makefile.am b/src/Makefile.am index 1c65e526..ab64ce9e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -19,6 +19,7 @@ rtl_433_SOURCES = abuf.c \ output_mqtt.c \ pulse_demod.c \ pulse_detect.c \ + r_api.c \ r_util.c \ rtl_433.c \ samp_grab.c \ diff --git a/src/r_api.c b/src/r_api.c new file mode 100644 index 00000000..2398a587 --- /dev/null +++ b/src/r_api.c @@ -0,0 +1,128 @@ +/** @file + Generic RF data receiver and decoder for ISM band devices using RTL-SDR and SoapySDR. + + Copyright (C) 2019 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 <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <stdbool.h> +#include <string.h> + +#include "r_api.h" +#include "rtl_433.h" +#include "r_private.h" +#include "sdr.h" +#include "data.h" + +#ifdef _WIN32 +#include <io.h> +#include <fcntl.h> +#ifdef _MSC_VER +#define F_OK 0 +#endif +#endif +#ifndef _MSC_VER +#include <unistd.h> +#endif + +#ifndef _MSC_VER +#include <getopt.h> +#else +#include "getopt/getopt.h" +#endif + +char const *version_string(void) +{ + return "rtl_433" +#ifdef GIT_VERSION +#define STR_VALUE(arg) #arg +#define STR_EXPAND(s) STR_VALUE(s) + " version " STR_EXPAND(GIT_VERSION) + " branch " STR_EXPAND(GIT_BRANCH) + " at " STR_EXPAND(GIT_TIMESTAMP) +#undef STR_VALUE +#undef STR_EXPAND +#else + " version unknown" +#endif + " inputs file rtl_tcp" +#ifdef RTLSDR + " RTL-SDR" +#endif +#ifdef SOAPYSDR + " SoapySDR" +#endif + ; +} + +void r_init_cfg(r_cfg_t *cfg) +{ + cfg->out_block_size = DEFAULT_BUF_LENGTH; + cfg->samp_rate = DEFAULT_SAMPLE_RATE; + cfg->conversion_mode = CONVERT_NATIVE; + + list_ensure_size(&cfg->in_files, 100); + list_ensure_size(&cfg->output_handler, 16); + + cfg->demod = calloc(1, sizeof(*cfg->demod)); + if (!cfg->demod) { + fprintf(stderr, "Could not create demod!\n"); + exit(1); + } + + cfg->demod->level_limit = DEFAULT_LEVEL_LIMIT; + cfg->demod->hop_time = DEFAULT_HOP_TIME; + + list_ensure_size(&cfg->demod->r_devs, 100); + list_ensure_size(&cfg->demod->dumper, 32); +} + +r_cfg_t *r_create_cfg(void) +{ + r_cfg_t *cfg = calloc(1, sizeof(*cfg)); + if (!cfg) { + fprintf(stderr, "Could not create cfg!\n"); + exit(1); + } + + r_init_cfg(cfg); + + return cfg; +} + +void r_free_cfg(r_cfg_t *cfg) +{ + if (cfg->dev) + sdr_deactivate(cfg->dev); + if (cfg->dev) + sdr_close(cfg->dev); + + for (void **iter = cfg->demod->dumper.elems; iter && *iter; ++iter) { + file_info_t const *dumper = *iter; + if (dumper->file && (dumper->file != stdout)) + fclose(dumper->file); + } + list_free_elems(&cfg->demod->dumper, free); + + list_free_elems(&cfg->demod->r_devs, free); + + if (cfg->demod->am_analyze) + am_analyze_free(cfg->demod->am_analyze); + + pulse_detect_free(cfg->demod->pulse_detect); + + free(cfg->demod); + + list_free_elems(&cfg->output_handler, (list_elem_free_fn)data_output_free); + + list_free_elems(&cfg->in_files, NULL); + + //free(cfg); +} diff --git a/src/rtl_433.c b/src/rtl_433.c index e451fff2..b34ee2cf 100644 --- a/src/rtl_433.c +++ b/src/rtl_433.c @@ -30,8 +30,10 @@ #include <signal.h> #include "rtl_433.h" +#include "r_private.h" #include "r_device.h" #include "rtl_433_devices.h" +#include "r_api.h" #include "sdr.h" #include "baseband.h" #include "pulse_detect.h" @@ -65,68 +67,10 @@ #include "getopt/getopt.h" #endif -char const *version_string(void) -{ - return "rtl_433" -#ifdef GIT_VERSION -#define STR_VALUE(arg) #arg -#define STR_EXPAND(s) STR_VALUE(s) - " version " STR_EXPAND(GIT_VERSION) - " branch " STR_EXPAND(GIT_BRANCH) - " at " STR_EXPAND(GIT_TIMESTAMP) -#undef STR_VALUE -#undef STR_EXPAND -#else - " version unknown" -#endif - " inputs file rtl_tcp" -#ifdef RTLSDR - " RTL-SDR" -#endif -#ifdef SOAPYSDR - " SoapySDR" -#endif - ; -} - r_device *flex_create_device(char *spec); // maybe put this in some header file? void data_acquired_handler(r_device *r_dev, data_t *data); -struct dm_state { - int32_t level_limit; - int16_t am_buf[MAXIMAL_BUF_LENGTH]; // AM demodulated signal (for OOK decoding) - union { - // These buffers aren't used at the same time, so let's use a union to save some memory - int16_t fm[MAXIMAL_BUF_LENGTH]; // FM demodulated signal (for FSK decoding) - uint16_t temp[MAXIMAL_BUF_LENGTH]; // Temporary buffer (to be optimized out..) - } buf; - uint8_t u8_buf[MAXIMAL_BUF_LENGTH]; // format conversion buffer - float f32_buf[MAXIMAL_BUF_LENGTH]; // format conversion buffer - int sample_size; // CU8: 1, CS16: 2 - pulse_detect_t *pulse_detect; - filter_state_t lowpass_filter_state; - demodfm_state_t demod_FM_state; - int enable_FM_demod; - samp_grab_t *samp_grab; - am_analyze_t *am_analyze; - int analyze_pulses; - file_info_t load_info; - list_t dumper; - int hop_time; - - /* Protocol states */ - list_t r_devs; - - pulse_data_t pulse_data; - pulse_data_t fsk_pulse_data; - unsigned frame_event_count; - unsigned frame_start_ago; - unsigned frame_end_ago; - struct timeval now; - float sample_file_pos; -}; - static void print_version(void) { fprintf(stderr, "%s\n", version_string()); @@ -1669,71 +1613,6 @@ static void parse_conf_option(r_cfg_t *cfg, int opt, char *arg) } } -void r_init_cfg(r_cfg_t *cfg) -{ - cfg->out_block_size = DEFAULT_BUF_LENGTH; - cfg->samp_rate = DEFAULT_SAMPLE_RATE; - cfg->conversion_mode = CONVERT_NATIVE; - - list_ensure_size(&cfg->in_files, 100); - list_ensure_size(&cfg->output_handler, 16); - - cfg->demod = calloc(1, sizeof(*cfg->demod)); - if (!cfg->demod) { - fprintf(stderr, "Could not create demod!\n"); - exit(1); - } - - cfg->demod->level_limit = DEFAULT_LEVEL_LIMIT; - cfg->demod->hop_time = DEFAULT_HOP_TIME; - - list_ensure_size(&cfg->demod->r_devs, 100); - list_ensure_size(&cfg->demod->dumper, 32); -} - -r_cfg_t *r_create_cfg(void) -{ - r_cfg_t *cfg = calloc(1, sizeof(*cfg)); - if (!cfg) { - fprintf(stderr, "Could not create cfg!\n"); - exit(1); - } - - r_init_cfg(cfg); - - return cfg; -} - -void r_free_cfg(r_cfg_t *cfg) -{ - if (cfg->dev) - sdr_deactivate(cfg->dev); - if (cfg->dev) - sdr_close(cfg->dev); - - for (void **iter = cfg->demod->dumper.elems; iter && *iter; ++iter) { - file_info_t const *dumper = *iter; - if (dumper->file && (dumper->file != stdout)) - fclose(dumper->file); - } - list_free_elems(&cfg->demod->dumper, free); - - list_free_elems(&cfg->demod->r_devs, free); - - if (cfg->demod->am_analyze) - am_analyze_free(cfg->demod->am_analyze); - - pulse_detect_free(cfg->demod->pulse_detect); - - free(cfg->demod); - - list_free_elems(&cfg->output_handler, (list_elem_free_fn)data_output_free); - - list_free_elems(&cfg->in_files, NULL); - - //free(cfg); -} - // well-known fields "time", "msg" and "codes" are used to output general decoder messages // well-known field "bits" is only used when verbose bits (-M bits) is requested // well-known field "tag" is only used when output tagging is requested diff --git a/vs15/rtl_433.vcxproj b/vs15/rtl_433.vcxproj index 3fb365ca..084fb909 100644 --- a/vs15/rtl_433.vcxproj +++ b/vs15/rtl_433.vcxproj @@ -102,6 +102,8 @@ <ClInclude Include="..\include\output_mqtt.h" /> <ClInclude Include="..\include\pulse_demod.h" /> <ClInclude Include="..\include\pulse_detect.h" /> + <ClInclude Include="..\include\r_api.h" /> + <ClInclude Include="..\include\r_private.h" /> <ClInclude Include="..\include\r_device.h" /> <ClInclude Include="..\include\r_util.h" /> <ClInclude Include="..\include\rtl_433.h" /> @@ -129,6 +131,7 @@ <ClCompile Include="..\src\output_mqtt.c" /> <ClCompile Include="..\src\pulse_demod.c" /> <ClCompile Include="..\src\pulse_detect.c" /> + <ClCompile Include="..\src\r_api.c" /> <ClCompile Include="..\src\r_util.c" /> <ClCompile Include="..\src\rtl_433.c" /> <ClCompile Include="..\src\samp_grab.c" /> diff --git a/vs15/rtl_433.vcxproj.filters b/vs15/rtl_433.vcxproj.filters index ef86ce4e..3b84c849 100644 --- a/vs15/rtl_433.vcxproj.filters +++ b/vs15/rtl_433.vcxproj.filters @@ -68,6 +68,12 @@ <ClInclude Include="..\include\pulse_detect.h"> <Filter>Header Files</Filter> </ClInclude> + <ClInclude Include="..\include\r_api.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\include\r_private.h"> + <Filter>Header Files</Filter> + </ClInclude> <ClInclude Include="..\include\r_device.h"> <Filter>Header Files</Filter> </ClInclude> @@ -145,6 +151,9 @@ <ClCompile Include="..\src\pulse_detect.c"> <Filter>Source Files</Filter> </ClCompile> + <ClCompile Include="..\src\r_api.c"> + <Filter>Source Files</Filter> + </ClCompile> <ClCompile Include="..\src\r_util.c"> <Filter>Source Files</Filter> </ClCompile>