├── .gitignore ├── README.md ├── include ├── compat_paths.h ├── configure.h ├── confparse.h ├── logwrap.h ├── optparse.h ├── rxlist_entry.h ├── txlist_entry.h ├── wnd_main.h ├── wnd_main_log.h ├── wnd_main_rx.h ├── wnd_main_rxdetails.h ├── wnd_main_rxlist.h ├── wnd_main_rxscope.h ├── wnd_main_tx.h ├── wnd_main_txlist.h ├── wnd_rxopt_dev.h ├── wnd_rxopt_exp.h ├── wnd_rxopt_flex.h ├── wnd_rxopt_freq.h ├── wnd_rxopt_out.h ├── wnd_rxopt_prot.h ├── wnd_rxopt_siggrab.h ├── wnd_rxopt_strgrab.h ├── wnd_textreader.h ├── wnd_txopt_dev.h ├── wnd_txopt_exp.h ├── wnd_txopt_freq.h ├── wnd_txwarn.h └── wndelements.h ├── manual_rx.md ├── manual_tx.md ├── pics ├── example1_sdrsharp_rx.png ├── example2_rx.png ├── example3_queue.png ├── example4_tx.png ├── example5_sdrsharp_tx.png ├── rx_01_launch.png ├── rx_02_dev.png ├── rx_03_dev.png ├── rx_04_freq.png ├── rx_05_freq.png ├── rx_06_start.png ├── rx_07_pulses.png ├── rx_08_options.png ├── rx_09_protocols.png ├── tx_01_launch.png ├── tx_02_dev.png ├── tx_03_dev.png ├── tx_04_freq.png ├── tx_05_freq.png ├── tx_06_start.png ├── tx_07_send.png ├── zadig_devsel.png ├── zadig_fl2k.png ├── zadig_fl2k_check.png └── zadig_rtl.png ├── res ├── gui_win_icon.ico ├── gui_win_resources.h └── gui_win_resources.rc ├── src ├── compat_paths.cpp ├── configure.cpp ├── confparse.cpp ├── logwrap.cpp ├── optparse.cpp ├── rtl_fl2k_433.cpp ├── rxlist_entry.cpp ├── txlist_entry.cpp ├── wnd_main.cpp ├── wnd_main_log.cpp ├── wnd_main_rx.cpp ├── wnd_main_rxdetails.cpp ├── wnd_main_rxlist.cpp ├── wnd_main_rxscope.cpp ├── wnd_main_tx.cpp ├── wnd_main_txlist.cpp ├── wnd_rxopt_dev.cpp ├── wnd_rxopt_exp.cpp ├── wnd_rxopt_flex.cpp ├── wnd_rxopt_freq.cpp ├── wnd_rxopt_out.cpp ├── wnd_rxopt_prot.cpp ├── wnd_rxopt_siggrab.cpp ├── wnd_rxopt_strgrab.cpp ├── wnd_textreader.cpp ├── wnd_txopt_dev.cpp ├── wnd_txopt_exp.cpp ├── wnd_txopt_freq.cpp ├── wnd_txwarn.cpp └── wndelements.cpp └── vs15 ├── rtl_fl2k_433.sln ├── rtl_fl2k_433_dynamic.vcxproj ├── rtl_fl2k_433_dynamic.vcxproj.filters ├── rtl_fl2k_433_static.vcxproj └── rtl_fl2k_433_static.vcxproj.filters /.gitignore: -------------------------------------------------------------------------------- 1 | *.res 2 | *.idb 3 | *.lastbuildstate 4 | *.tlog 5 | *.ipdb 6 | *.iobj 7 | *.db 8 | *.sdf 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | rtl_fl2k_433 - a generic data receiver and transmitter 2 | =========== 3 | 4 | ## Introduction of rtl_fl2k_433 5 | rtl_fl2k_433 is a multi-purpose SDR tool which enables you to use cheap and widely available PC hardware to build a generic data receiver and transmitter working at arbitrary radio frequencies (like the commonly used bands around 315 MHz, 433.92 MHz, 868 MHz, and 915 MHz). It was designed as a quick and handy tool for purposes like prototyping or security analysis. 6 | 7 | ### RX part: hardware and software support 8 | To receive radio signals you need an RTL-SDR compatible USB stick (based on Realteks chipset RTL2832U for DVB-T receivers). The RX logic of rtl_fl2k_433 builds upon librtl_433, which is a custom lib-style modification of the well-known rtl_433 project. 9 | 10 | However, if you don't have such a device at hand to receive RX transmission physically, you can still load RX signals into rtl_fl2k_433 from files containing pre-recorded samples. 11 | ### TX part: hardware and software support 12 | To transmit radio signals on your own you need a USB3 to VGA adapter based on the Chipset FL2000 by Fresco Logic. The TX logic of rtl_fl2k_433 builds upon a custom library named libfl2k_433, which is an extension to the OSMO-FL2K library released in April 2018. 13 | 14 | However, if you don't have such a device at hand, you can let rtl_fl2k_433 save prepared TX signals to your disk which can be sent later using the fl2k_file application (from the OSMO-FL2K software package). 15 | 16 | ## Usage example 17 | 18 | You have a device that transmits at 433.92 MHz. In the waterfall plot of the SDR program of your choice (here: SDR#) its signals might look like this: 19 | 20 | ![example_sdrsharp_rx](pics/example1_sdrsharp_rx.png) 21 | 22 | In rtl_fl2k_433 you start the reception with an attached RTL-SDR device. Here, a captured message will show up in the reception list. If it uses a known protocol, the decoded data will be listed below. 23 | 24 | ![example_rx](pics/example2_rx.png) 25 | 26 | You can queue any received signal (or the entire pulse sequence which can contain multiple signals) for re-transmission. 27 | 28 | ![example_queuetx](pics/example3_queue.png) 29 | 30 | Once you start the TX module, the queued signals will be forwarded to your FL2K adapter. 31 | 32 | ![example_tx](pics/example4_tx.png) 33 | 34 | Now other systems within your setup should be able to spot these self-generated signals. In the waterfall plot of the SDR program of your choice (here: SDR#) it might look like this: 35 | 36 | ![example_sdrsharp_tx](pics/example5_sdrsharp_tx.png) 37 | 38 | ## Manual 39 | For detailed instructions refer to 40 | 41 | [Detailed manual on RX parts](manual_rx.md) 42 | 43 | [Detailed manual on TX parts](manual_tx.md) 44 | 45 | ## Scope and limitations 46 | As written above, rtl_fl2k_433 is mainly developed for purposes like prototyping or security analysis. It is explicitly not designed for productive use. If you intend to implement a productive use case, you better have a look on the following links 47 | * For productive RX applications consider using the original, command-line based version of rtl_433. Since it does not perform any GUI handling, it also runs well on cost-efficient and energy-saving hardware like the Raspberry Pi. 48 | * For productive TX applications consider using transmitters tailored for your intended frequency and modulation. There are cost-efficient solutions, also for small embedded boards like the Raspberry Pi and can be handled easily without requiring you to take special measures against unwanted RF harmonics (as present with FL2K or RpiTX). 49 | 50 | Current restrictions of rtl_fl2k_433 are: 51 | * Initially, rtl_fl2k_433 only features Win64 builds. However, the only Windows-specific component is the current GUI, which is based on the Windows API. Since the underlying libraries are not system-dependent, GUIs compatible with further systems should be possible to create without any expected problems. So builds for Linux might follow in future. 52 | * Currently, you cannot edit the message contents (i.e. its payloads) between reception and transmission - i.e. rtl_fl2k_433 currently cannot be considered as much more than a replay-tool. This would require to add re-modulation logic ontop of librtl_433 which is simply not there, yet. Might follow at some time in future. Currently, you have to record all types of signals first, if you want to be able to reproduce them. 53 | * TX signals dumped are intended to be used by the fl2k_file tool (see above), Currently, these files cannot be loaded back into rtl_fl2k_433 (this might be added in future) 54 | * Integration of further SDRs: Currently, only RTL-SDR and FL2K are supported on the RX and TX side, respectively. Especially on the RX side there are no big obstacles to extend this, since rtl_433 meanwhile also supports a bunch of other SDRs via SoapySDR. 55 | 56 | ## Cautionary advice 57 | Please carefully respect the following advice directly taken from the OSMO-FL2K project. Also rtl_fl2k_433 will show you a reminder prior each first start of its TX module. 58 | 59 | If you are operating a radio transmitter of any sort, particularly a DIY solution or a SDR transmitter, it is assumed that you are familiar with both the legal aspects of radio transmissions, as well as the technical aspects of it. Do not operate a radio transmitter unless you are clear of the legal and regulatory requirements. In most jurisdictions the operation of homebrew / DYI transmitters requires at the very least an amateur radio license. 60 | 61 | The raw, unfiltered DAC output contains lots of harmonics at multiples of the base frequency. This is what is creatively (ab)used if you use osmo-fl2k to generate a signal much higher than what you could normally achieve with a ~ 165MHz DAC without upconversion. However, this means that the frequency spectrum will contain not only the one desired harmonic, but all the lower harmonics as well as the base frequency. 62 | 63 | Before transmitting any signals with an FL2000 device, it is strongly suggested that you check the resulting spectrum with a spectrum analyzer, and apply proper filtering to suppress any but the desired transmit frequency. 64 | 65 | Operating a transmitter with the unfiltered FL2000 DAC output attached to an antenna outside a RF shielding chamber is dangerous. Don't do it! 66 | You have the following alternatives to broadcasting over the air: 67 | * add proper output band pass filtering for your desired TX frequency, or 68 | * operate transmitter + receiver in a shielded RF box / chamber, or 69 | * connect transmitter + receiver over coaxial cable (with proper attenuators) 70 | -------------------------------------------------------------------------------- /include/compat_paths.h: -------------------------------------------------------------------------------- 1 | /** @file 2 | compat_paths addresses compatibility with default OS path names. 3 | topic: default search paths for config file 4 | issue: Linux and Windows use different common paths for config files 5 | solution: provide specific default paths for each system 6 | */ 7 | 8 | #ifndef INCLUDE_COMPAT_PATHS_H_ 9 | #define INCLUDE_COMPAT_PATHS_H_ 10 | 11 | /// Get default search paths for rtl_433 config file. 12 | char **compat_get_default_conf_paths(void); 13 | 14 | #endif /* INCLUDE_COMPAT_PATHS_H_ */ -------------------------------------------------------------------------------- /include/configure.h: -------------------------------------------------------------------------------- 1 | #ifndef CONFIGURE_INCLUDED 2 | #define CONFIGURE_INCLUDED 3 | 4 | #include "librtl_433.h" 5 | 6 | typedef enum { 7 | CFG_EXITCODE_MINUS1 = -1, 8 | CFG_EXITCODE_NULL = 0, 9 | CFG_EXITCODE_ONE = 1, 10 | CFG_SUCCESS_GO_ON = 2 11 | } CfgResult; 12 | 13 | CfgResult configure_librtl433(r_cfg_t *cfg, int argc, char **argv, int allow_default_cfgfile); 14 | void add_infile(r_cfg_t *cfg, char *in_file); 15 | void clear_infiles(r_cfg_t *cfg); 16 | 17 | #endif // CONFIGURE_INCLUDED -------------------------------------------------------------------------------- /include/confparse.h: -------------------------------------------------------------------------------- 1 | /** @file 2 | Light-weight (i.e. dumb) config-file parser. 3 | Copyright (C) 2018 Christian W. Zuckschwerdt 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | */ 9 | 10 | #ifndef INCLUDE_CONFPARSE_H_ 11 | #define INCLUDE_CONFPARSE_H_ 12 | 13 | struct conf_keywords { 14 | char const *keyword; 15 | int key; 16 | }; 17 | 18 | /** Check if a file exists and can be read. 19 | @param path input file name 20 | @return 1 if the file exists and is readable, 0 otherwise 21 | */ 22 | int hasconf(char const *path); 23 | 24 | /** Open a config file, read contents to memory. 25 | @param path input file name 26 | @return allocated memory containing the config file 27 | */ 28 | char *readconf(char const *path); 29 | 30 | /** Return the next keyword token and set the optional argument. 31 | @param conf current position in conf 32 | @param keywords list of possible keywords 33 | @param arg optional out pointer to a argument string 34 | @return the next keyword token, -1 otherwise. 35 | */ 36 | int getconf(char **conf, struct conf_keywords const keywords[], char **arg); 37 | 38 | #endif /* INCLUDE_CONFPARSE_H_ */ 39 | -------------------------------------------------------------------------------- /include/logwrap.h: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * Interfacing of (3rd party) libraries used by rtl_fl2k_433 * 3 | * * 4 | * coded in 2018/19 by winterrace (github.com/winterrace) * 5 | * (github.com/winterrace2) * 6 | * * 7 | * This program is free software; you can redistribute it and/or * 8 | * modify it under the terms of the GNU General Public License as * 9 | * published by the Free Software Foundation; either version 2 of * 10 | * the License, or (at your option) any later version. * 11 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 12 | 13 | #ifndef LOGWRAP_INCLUDED 14 | #define LOGWRAP_INCLUDED 15 | 16 | int initLogRedirects(); 17 | 18 | #ifdef __cplusplus 19 | extern "C" { 20 | #endif 21 | int Gui_fprintf(FILE *stream, const char* aFormat, ...); 22 | #ifdef __cplusplus 23 | } 24 | #endif 25 | 26 | #endif // LOGWRAP_INCLUDED 27 | -------------------------------------------------------------------------------- /include/optparse.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Option parsing functions to complement getopt. 3 | * 4 | * Copyright (C) 2017 Christian Zuckschwerdt 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | */ 11 | 12 | #ifndef INCLUDE_OPTPARSE_H_ 13 | #define INCLUDE_OPTPARSE_H_ 14 | 15 | #include 16 | 17 | // makes strcasecmp() and strncasecmp() available when including optparse.h 18 | #ifdef _MSC_VER 19 | #include 20 | #define strcasecmp(s1,s2) _stricmp(s1,s2) 21 | #define strncasecmp(s1,s2,n) _strnicmp(s1,s2,n) 22 | #else 23 | #include 24 | #endif 25 | 26 | /// Convert string to int with fallback default. 27 | int atoiv(char *arg, int def); 28 | 29 | /// Convert string to bool with fallback default. 30 | /// Parses "true", "yes", "on", "enable" (not case-sensitive) to 1, atoi() otherwise. 31 | int atobv(char *arg, int def); 32 | 33 | /// Get the next colon or comma separated arg, NULL otherwise. 34 | /// Returns string including comma if a comma is found first, 35 | /// otherwise string after colon if found, NULL otherwise. 36 | char *arg_param(char *arg); 37 | 38 | /// Parse param string to host and port. 39 | /// E.g. ":514", "localhost", "[::1]", "127.0.0.1:514", "[::1]:514", 40 | /// also "//localhost", "//localhost:514", "//:514". 41 | /// Host or port are terminated at a comma, if found. 42 | /// @return the remaining options (might be "") or NULL on parsing error 43 | char *hostport_param(char *param, char **host, char **port); 44 | 45 | /// Convert a string to an unsigned integer, uses strtod() and accepts 46 | /// metric suffixes of 'k', 'M', and 'G' (also 'K', 'm', and 'g'). 47 | /// 48 | /// Parse errors will Gui_fprintf(stderr, ...) and exit(1). 49 | /// 50 | /// @param str: character string to parse 51 | /// @param error_hint: prepended to error output 52 | /// @return parsed number value 53 | uint32_t atouint32_metric(const char *str, const char *error_hint); 54 | 55 | /// Convert a string to an integer, uses strtod() and accepts 56 | /// time suffixes of 's', 'm', and 'h' (also 'S', 'M', and 'H'). 57 | /// 58 | /// Parse errors will Gui_fprintf(stderr, ...) and exit(1). 59 | /// 60 | /// @param str: character string to parse 61 | /// @param error_hint: prepended to error output 62 | /// @return parsed number value 63 | int atoi_time(const char *str, const char *error_hint); 64 | 65 | /// Trim left and right whitespace in string. 66 | /// 67 | /// @param[in,out] str 68 | /// @return the trimmed value of str 69 | char *trim_ws(char *str); 70 | 71 | /// Remove all whitespace from string. 72 | /// 73 | /// @param[in,out] str 74 | /// @return the stripped value of str 75 | char *remove_ws(char *str); 76 | 77 | #endif /* INCLUDE_OPTPARSE_H_ */ 78 | -------------------------------------------------------------------------------- /include/rxlist_entry.h: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * Definition of entries in the RX list * 3 | * * 4 | * coded in 2018/19 by winterrace (github.com/winterrace) * 5 | * (github.com/winterrace2) * 6 | * * 7 | * This program is free software; you can redistribute it and/or * 8 | * modify it under the terms of the GNU General Public License as * 9 | * published by the Free Software Foundation; either version 2 of * 10 | * the License, or (at your option) any later version. * 11 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 12 | 13 | #ifndef RXLIST_ENTRY_INCLUDED 14 | #define RXLIST_ENTRY_INCLUDED 15 | 16 | #include "librtl_433.h" 17 | #include "pulse_detect.h" 18 | 19 | // Relevant modulation types 20 | typedef enum { 21 | SIGNAL_MODULATION_UNK = 0, 22 | SIGNAL_MODULATION_OOK = 1, 23 | SIGNAL_MODULATION_FSK = 2 24 | } sigmod; 25 | 26 | typedef struct _PulseDatCompact { 27 | //uint64_t offset; ///< Offset to first pulse in number of samples from start of stream. 28 | uint32_t sample_rate; ///< Sample rate the pulses are recorded with. 29 | //unsigned start_ago; ///< Start of first pulse in number of samples ago. 30 | //unsigned end_ago; ///< End of last pulse in number of samples ago. 31 | unsigned int num_pulses; 32 | int *pulse; ///< Width of pulses (high) in number of samples. 33 | int *gap; ///< Width of gaps between pulses (low) in number of samples. 34 | //int ook_low_estimate; ///< Estimate for the OOK low level (base noise level) at beginning of package. 35 | //int ook_high_estimate; ///< Estimate for the OOK high level at end of package. 36 | //int fsk_f1_est; ///< Estimate for the F1 frequency for FSK. 37 | //int fsk_f2_est; ///< Estimate for the F2 frequency for FSK. 38 | float freq1_hz; 39 | float freq2_hz; 40 | float rssi_db; 41 | float snr_db; 42 | float noise_db; 43 | unsigned int segment_startidx; 44 | unsigned int segment_len; 45 | unsigned int num_samples; 46 | } PulseDatCompact, *pPulseDatCompact; 47 | 48 | class rx_entry { 49 | private: 50 | int devid; 51 | char time[32]; 52 | char type[32]; 53 | char model[64]; 54 | PulseDatCompact pdat; 55 | sigmod mod; 56 | data_t *data; 57 | 58 | public: 59 | rx_entry(); 60 | ~rx_entry(); 61 | void setTime(char *time); 62 | void setType(char *time); 63 | void setModel(char *time); 64 | void setDevId(int id); 65 | void setModulation(sigmod sm); 66 | char *getTime(); 67 | char *getType(); 68 | char *getModel(); 69 | sigmod getModulation(); 70 | int getDevId(); 71 | int copyData(data_t *data); 72 | data_t *getData(void); 73 | int copyPulses(const pulse_data_t *pulses, unsigned pulseexc_startidx, unsigned pulseexc_len); 74 | pPulseDatCompact getPulses(); 75 | }; 76 | 77 | #endif // RXLIST_ENTRY_INCLUDED 78 | -------------------------------------------------------------------------------- /include/txlist_entry.h: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * Definition of entries in the TX list * 3 | * * 4 | * coded in 2018/19 by winterrace (github.com/winterrace) * 5 | * (github.com/winterrace2) * 6 | * * 7 | * This program is free software; you can redistribute it and/or * 8 | * modify it under the terms of the GNU General Public License as * 9 | * published by the Free Software Foundation; either version 2 of * 10 | * the License, or (at your option) any later version. * 11 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 12 | 13 | #ifndef TXLIST_ENTRY_INCLUDED 14 | #define TXLIST_ENTRY_INCLUDED 15 | 16 | #include "libfl2k_433.h" 17 | 18 | class tx_entry { 19 | private: 20 | TxMsg msg; 21 | char description[200]; 22 | char time_sent[20]; 23 | 24 | public: 25 | tx_entry(char *description, mod_type mod, char *buf, uint32_t len, uint32_t samp_rate); 26 | ~tx_entry(); 27 | 28 | void setSentTime(char *timestr); 29 | char *getSentTime(); 30 | char *getDescription(); 31 | TxMsg *getMessage(); 32 | }; 33 | 34 | #endif // RXLIST_ENTRY_INCLUDED 35 | -------------------------------------------------------------------------------- /include/wnd_main.h: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * rtl_fl2k_433 main window (core part) * 3 | * * 4 | * coded in 2018/19 by winterrace (github.com/winterrace) * 5 | * (github.com/winterrace2) * 6 | * * 7 | * This program is free software; you can redistribute it and/or * 8 | * modify it under the terms of the GNU General Public License as * 9 | * published by the Free Software Foundation; either version 2 of * 10 | * the License, or (at your option) any later version. * 11 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 12 | 13 | #ifndef WND_MAIN_INCLUDED 14 | #define WND_MAIN_INCLUDED 15 | 16 | extern char copybuf[4096]; // todo: move to more appropriate place? 17 | 18 | int GuiMain(); 19 | BOOL CopyToClipboard(LPSTR txt); // todo: move to more appropriate place? 20 | 21 | #endif // WND_MAIN_INCLUDED 22 | -------------------------------------------------------------------------------- /include/wnd_main_log.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winterrace2/rtl_fl2k_433/8955374f9ecd9d71ef421f9f9dcdd869d91fb6b1/include/wnd_main_log.h -------------------------------------------------------------------------------- /include/wnd_main_rx.h: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * rtl_fl2k_433 main window (RX part) * 3 | * * 4 | * coded in 2018/19 by winterrace (github.com/winterrace) * 5 | * (github.com/winterrace2) * 6 | * * 7 | * This program is free software; you can redistribute it and/or * 8 | * modify it under the terms of the GNU General Public License as * 9 | * published by the Free Software Foundation; either version 2 of * 10 | * the License, or (at your option) any later version. * 11 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 12 | 13 | #ifndef WND_MAINRX_INCLUDED 14 | #define WND_MAINRX_INCLUDED 15 | 16 | #include "librtl_433.h" 17 | 18 | #define SCOPE_ZOOM_MIN 100 // Minimal Zoom is 1.00 19 | #define SCOPE_ZOOM_MAX 2000 // Maximal Zoom is 20.00 20 | 21 | #define SCOPE_OFFSET_MIN 0 // Minimal Offset is 0.000 22 | #define SCOPE_OFFSET_MAX 1000 // Maximal Offset is 1.000 23 | 24 | BOOL RxGui_prepare(); 25 | VOID RxGui_onInit(HWND hMainWnd, HMENU hMainMenu, HMENU poprx, HMENU popdet, HMENU popfreq, HMENU popflex, HMENU popprot); 26 | VOID RxGui_cleanup(); 27 | BOOL RxGui_onCommand(WPARAM wParam, LPARAM lParam); 28 | BOOL RxGui_onChangedItem(LPNMLISTVIEW ctx); 29 | BOOL RxGui_onKey(LPNMLVKEYDOWN ctx); 30 | BOOL RxGui_onRightClick(LPNMHDR ctx_in); 31 | BOOL RxGui_onDoubleClick(LPNMHDR ctx_in); 32 | VOID RxGui_onSizeChange(int add_w, int add_h, double fac_w, double fac_h, BOOL redraw); 33 | VOID RxGui_onHorScroll(HWND hElem); 34 | BOOL RxGui_shutdownRequest(); 35 | VOID RxGui_shutdownConfirm(); 36 | BOOL RxGui_isActive(); 37 | BOOL RxGui_passFile(LPSTR path); 38 | 39 | #endif // WND_MAINRX_INCLUDED 40 | -------------------------------------------------------------------------------- /include/wnd_main_rxdetails.h: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * Implementation of the ListView listing RX signal details * 3 | * * 4 | * coded in 2018/19 by winterrace (github.com/winterrace) * 5 | * (github.com/winterrace2) * 6 | * * 7 | * This program is free software; you can redistribute it and/or * 8 | * modify it under the terms of the GNU General Public License as * 9 | * published by the Free Software Foundation; either version 2 of * 10 | * the License, or (at your option) any later version. * 11 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 12 | 13 | #ifndef WND_MAIN_RXDETAILS_INCLUDED 14 | #define WND_MAIN_RXDETAILS_INCLUDED 15 | 16 | #define RX_COLUMN_KEY 140 17 | #define RX_COLUMN_VALUE 220 18 | 19 | class rxdetails { 20 | public: 21 | rxdetails(HWND hLogWnd, HWND hParent, HMENU popup_menu); 22 | ~rxdetails(); 23 | 24 | VOID DisplayData(data_t *data); 25 | HWND getWndHandle(); 26 | DWORD getRightClickCommand(LPNMITEMACTIVATE dat, INT *selidx); 27 | VOID toString(INT id, CHAR *buf, INT cap); 28 | 29 | private: 30 | HWND hList; // Handle of log window 31 | HWND hParWnd; 32 | HMENU hPopup; 33 | }; 34 | 35 | #endif // WND_MAIN_RXDETAILS_INCLUDED -------------------------------------------------------------------------------- /include/wnd_main_rxlist.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winterrace2/rtl_fl2k_433/8955374f9ecd9d71ef421f9f9dcdd869d91fb6b1/include/wnd_main_rxlist.h -------------------------------------------------------------------------------- /include/wnd_main_rxscope.h: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * Main window element: Scope to visualize message pulse data * 3 | * * 4 | * coded in 2018/19 by winterrace (github.com/winterrace) * 5 | * (github.com/winterrace2) * 6 | * * 7 | * This program is free software; you can redistribute it and/or * 8 | * modify it under the terms of the GNU General Public License as * 9 | * published by the Free Software Foundation; either version 2 of * 10 | * the License, or (at your option) any later version. * 11 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 12 | 13 | #ifndef WND_MAIN_RX_SCOPE_INCLUDED 14 | #define WND_MAIN_RX_SCOPE_INCLUDED 15 | #include "rxlist_entry.h" 16 | 17 | typedef enum { 18 | STATE_LOW_OUTSIDE = 0, 19 | STATE_LOW_INSIDE = 1, 20 | STATE_HIGH_INSIDE = 2, 21 | STATE_HIGH_OUTSIDE = 3 22 | } pulse_state; 23 | 24 | class ScopeWnd { 25 | public: 26 | ScopeWnd(HWND hBox); // specify handle of the picture element 27 | ~ScopeWnd(); 28 | 29 | void refreshBox(); // trigger redrawing 30 | void resizeBox(int redraw); // adjust to current dimensions and repaint 31 | void setSource(pPulseDatCompact pdat); // change the data source and redraw 32 | int isSourceSet(); // returns > 0 if a source is currently set 33 | void setZoom(double z); // change the current zoom (z >= 1.0) 34 | void setOffset(double o); // change the current offset (0.0 <= o <= 1.0) 35 | double getZoom(); // get the current zoom 36 | double getOffset(); // get the current offset 37 | LRESULT CALLBACK WndProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); 38 | 39 | private: 40 | HWND hGfxOut; // handle of the picture element 41 | pPulseDatCompact src; // data source 42 | double zoom; // current zoom (zoom >= 1.0) 43 | double offset; // current offset (0.0 <= offset <= 1.0) 44 | RECT boxpos; // Position der Gfx-Box 45 | WNDPROC OldGfxWndProc; // Address of original WNDPROC 46 | pulse_state getSrcStateAt(double relpos); // Gets value of signal at position relpos (0.0 <= relpos <= 1.0) 47 | }; 48 | 49 | #endif // WND_MAIN_RX_SCOPE_INCLUDED 50 | -------------------------------------------------------------------------------- /include/wnd_main_tx.h: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * rtl_fl2k_433 main window (TX part) * 3 | * * 4 | * coded in 2018/19 by winterrace (github.com/winterrace) * 5 | * (github.com/winterrace2) * 6 | * * 7 | * This program is free software; you can redistribute it and/or * 8 | * modify it under the terms of the GNU General Public License as * 9 | * published by the Free Software Foundation; either version 2 of * 10 | * the License, or (at your option) any later version. * 11 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 12 | 13 | #ifndef WND_MAINTX_INCLUDED 14 | #define WND_MAINTX_INCLUDED 15 | 16 | #include "librtl_433.h" 17 | #include "rxlist_entry.h" 18 | 19 | BOOL TxGui_prepare(); 20 | VOID TxGui_onInit(HWND hMainWnd, HMENU poptx); 21 | VOID TxGui_cleanup(); 22 | BOOL TxGui_onCommand(WPARAM wParam, LPARAM lParam); 23 | BOOL TxGui_onChangedItem(LPNMLISTVIEW ctx); 24 | BOOL TxGui_onKey(LPNMLVKEYDOWN ctx); 25 | BOOL TxGui_onRightClick(LPNMHDR ctx_in); 26 | BOOL TxGui_onDoubleClick(LPNMHDR ctx_in); 27 | VOID TxGui_onSizeChange(int add_w, int add_h, double fac_w, double fac_h, BOOL redraw); 28 | BOOL TxGui_shutdownRequest(); 29 | VOID TxGui_shutdownConfirm(); 30 | BOOL TxGui_isActive(); 31 | VOID QueueRxPulseToTx(rx_entry *entry, BOOL entirepulse = FALSE); 32 | 33 | #endif // WND_MAINTX_INCLUDED 34 | -------------------------------------------------------------------------------- /include/wnd_main_txlist.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winterrace2/rtl_fl2k_433/8955374f9ecd9d71ef421f9f9dcdd869d91fb6b1/include/wnd_main_txlist.h -------------------------------------------------------------------------------- /include/wnd_rxopt_dev.h: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * Option sub-dialog for RTL-SDR device selection * 3 | * * 4 | * coded in 2018/19 by winterrace (github.com/winterrace) * 5 | * (github.com/winterrace2) * 6 | * * 7 | * Basic actions performed by a call to ShowDeviceDialog(): * 8 | * - updates cfg-> * 9 | * - can provide a pointer to the device name (param trgdev_name) * 10 | * If the dialog is cancelled, no changes are made * 11 | * * 12 | * This program is free software; you can redistribute it and/or * 13 | * modify it under the terms of the GNU General Public License as * 14 | * published by the Free Software Foundation; either version 2 of * 15 | * the License, or (at your option) any later version. * 16 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 17 | 18 | #ifndef WND_RXOPT_DEV_INCLUDED 19 | #define WND_RXOPT_DEV_INCLUDED 20 | 21 | #include "librtl_433.h" 22 | 23 | int ShowDeviceRxDialog(rtl_433_t *rl, HWND hParent, char **trgdev_name); 24 | 25 | #endif // WND_RXOPT_DEV_INCLUDED 26 | -------------------------------------------------------------------------------- /include/wnd_rxopt_exp.h: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * Option sub-dialog for expert settings regarding RX * 3 | * * 4 | * coded in 2018/19 by winterrace (github.com/winterrace) * 5 | * (github.com/winterrace2) * 6 | * * 7 | * If the dialog is cancelled, no changes are made * 8 | * * 9 | * This program is free software; you can redistribute it and/or * 10 | * modify it under the terms of the GNU General Public License as * 11 | * published by the Free Software Foundation; either version 2 of * 12 | * the License, or (at your option) any later version. * 13 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 14 | 15 | #ifndef WND_RXOPT_EXP_INCLUDED 16 | #define WND_RXOPT_EXP_INCLUDED 17 | 18 | #include "librtl_433.h" 19 | 20 | int ShowExpertDialog(rtl_433_t *rl, HWND hParent); 21 | 22 | #endif // WND_RXOPT_EXP_INCLUDED 23 | -------------------------------------------------------------------------------- /include/wnd_rxopt_flex.h: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * Option sub-dialog for flex protocol configuration * 3 | * * 4 | * coded in 2018/19 by winterrace (github.com/winterrace) * 5 | * (github.com/winterrace2) * 6 | * * 7 | * Basic actions performed by a call to ShowFlexDialog(): * 8 | * - updates cfg->flex_specs * 9 | * If the dialog is cancelled, no changes are made * 10 | * * 11 | * This program is free software; you can redistribute it and/or * 12 | * modify it under the terms of the GNU General Public License as * 13 | * published by the Free Software Foundation; either version 2 of * 14 | * the License, or (at your option) any later version. * 15 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 16 | 17 | #ifndef WND_RXOPT_FLEX_INCLUDED 18 | #define WND_RXOPT_FLEX_INCLUDED 19 | 20 | #include "librtl_433.h" 21 | 22 | #define OPT_FLEX_SPEC_WIDTH 400 23 | 24 | int ShowFlexDialog(rtl_433_t *rl, HWND hParent, HMENU hPopupMenu); 25 | 26 | #endif // WND_RXOPT_FLEX_INCLUDED 27 | -------------------------------------------------------------------------------- /include/wnd_rxopt_freq.h: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * Option sub-dialog for RX frequency configuration * 3 | * * 4 | * coded in 2018/19 by winterrace (github.com/winterrace) * 5 | * (github.com/winterrace2) * 6 | * * 7 | * Basic actions performed by a call to ShowFrequencyRxDialog(): * 8 | * - updates cfg-> * 9 | * If the dialog is cancelled, no changes are made * 10 | * * 11 | * This program is free software; you can redistribute it and/or * 12 | * modify it under the terms of the GNU General Public License as * 13 | * published by the Free Software Foundation; either version 2 of * 14 | * the License, or (at your option) any later version. * 15 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 16 | 17 | #ifndef WND_RXOPT_FREQ_INCLUDED 18 | #define WND_RXOPT_FREQ_INCLUDED 19 | 20 | #include "librtl_433.h" 21 | 22 | #define OPT_FREQ_COLWIDTH 200 23 | 24 | int ShowFrequencyRxDialog(rtl_433_t *rl, HWND hParent, HMENU hPopupMenu); 25 | 26 | #endif // WND_RXOPT_FREQ_INCLUDED 27 | -------------------------------------------------------------------------------- /include/wnd_rxopt_out.h: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * Option sub-dialog for RX output * 3 | * * 4 | * coded in 2018/19 by winterrace (github.com/winterrace) * 5 | * (github.com/winterrace2) * 6 | * * 7 | * If the dialog is cancelled, no changes are made * 8 | * * 9 | * This program is free software; you can redistribute it and/or * 10 | * modify it under the terms of the GNU General Public License as * 11 | * published by the Free Software Foundation; either version 2 of * 12 | * the License, or (at your option) any later version. * 13 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 14 | 15 | #ifndef WND_RXOPT_OUT_INCLUDED 16 | #define WND_RXOPT_OUT_INCLUDED 17 | 18 | #include "librtl_433.h" 19 | 20 | int ShowOutputDialog(rtl_433_t *rl, HWND hParent); 21 | 22 | #endif // WND_RXOPT_OUT_INCLUDED 23 | -------------------------------------------------------------------------------- /include/wnd_rxopt_prot.h: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * Option sub-dialog for radio protocol selection * 3 | * * 4 | * coded in 2018/19 by winterrace (github.com/winterrace) * 5 | * (github.com/winterrace2) * 6 | * * 7 | * Basic actions performed by a call to ShowProtocolDialog(): * 8 | * - updates cfg->active_prots * 9 | * * 10 | * If the dialog is cancelled, no changes are made * 11 | * * 12 | * This program is free software; you can redistribute it and/or * 13 | * modify it under the terms of the GNU General Public License as * 14 | * published by the Free Software Foundation; either version 2 of * 15 | * the License, or (at your option) any later version. * 16 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 17 | 18 | #ifndef WND_RXOPT_PROT_INCLUDED 19 | #define WND_RXOPT_PROT_INCLUDED 20 | 21 | #include "librtl_433.h" 22 | 23 | #define OPT_PROT_NAMECOL_WIDTH 300 24 | #define OPT_PROT_PARAM_WIDTH 100 25 | #define OPT_PROT_STATECOL_WIDTH 80 26 | 27 | int ShowProtocolDialog(rtl_433_t *rl, HWND hParent, HMENU hPopupMenu); 28 | 29 | #endif // WND_RXOPT_PROT_INCLUDED 30 | -------------------------------------------------------------------------------- /include/wnd_rxopt_siggrab.h: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * Sub-dialog to configure dumping of signals * 3 | * * 4 | * coded in 2018/19 by winterrace (github.com/winterrace) * 5 | * (github.com/winterrace2) * 6 | * * 7 | * If the dialog is cancelled, no changes are made * 8 | * * 9 | * This program is free software; you can redistribute it and/or * 10 | * modify it under the terms of the GNU General Public License as * 11 | * published by the Free Software Foundation; either version 2 of * 12 | * the License, or (at your option) any later version. * 13 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 14 | 15 | #ifndef WND_RXOPT_SIGGRAB_INCLUDED 16 | #define WND_RXOPT_SIGGRAB_INCLUDED 17 | 18 | #include "librtl_433.h" 19 | 20 | int ShowSignalGrabberDialog(rtl_433_t *rl, HWND hParent); 21 | 22 | #endif // WND_RXOPT_SIGGRAB_INCLUDED 23 | -------------------------------------------------------------------------------- /include/wnd_rxopt_strgrab.h: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * Sub-dialog to configure dumping of sample stream * 3 | * * 4 | * coded in 2018/19 by winterrace (github.com/winterrace) * 5 | * (github.com/winterrace2) * 6 | * * 7 | * If the dialog is cancelled, no changes are made * 8 | * * 9 | * This program is free software; you can redistribute it and/or * 10 | * modify it under the terms of the GNU General Public License as * 11 | * published by the Free Software Foundation; either version 2 of * 12 | * the License, or (at your option) any later version. * 13 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 14 | 15 | #ifndef WND_RXOPT_STRGRAB_INCLUDED 16 | #define WND_RXOPT_STRGRAB_INCLUDED 17 | 18 | #include "librtl_433.h" 19 | 20 | int ShowStreamGrabberDialog(rtl_433_t *rl, HWND hParent); 21 | 22 | #endif // WND_RXOPT_STRGRAB_INCLUDED 23 | -------------------------------------------------------------------------------- /include/wnd_textreader.h: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * Sub-dialog to let the user enter some text * 3 | * * 4 | * coded in 2018/19 by winterrace (github.com/winterrace) * 5 | * (github.com/winterrace2) * 6 | * * 7 | * If the user entered some text, the dialog returns a pointer * 8 | * If the user cancelled, a NULL pointer is returned * 9 | * * 10 | * The calling code has to ensure an instant evaluatation or copy * 11 | * the resulting string before the next call to this dialog since * 12 | * it uses a local buffer which can be changed or re-allocated * 13 | * during the next call of this dialog * 14 | * * 15 | * This program is free software; you can redistribute it and/or * 16 | * modify it under the terms of the GNU General Public License as * 17 | * published by the Free Software Foundation; either version 2 of * 18 | * the License, or (at your option) any later version. * 19 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 20 | 21 | #ifndef WND_TEXTREADER_INCLUDED 22 | #define WND_TEXTREADER_INCLUDED 23 | 24 | LPSTR ShowTextReaderDialog(HWND hParent, LPSTR caption, LPSTR preset, DWORD maxbuf); 25 | 26 | #endif // WND_TEXTREADER_INCLUDED 27 | -------------------------------------------------------------------------------- /include/wnd_txopt_dev.h: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * Option sub-dialog for FL2K device selection * 3 | * * 4 | * coded in 2018/19 by winterrace (github.com/winterrace) * 5 | * (github.com/winterrace2) * 6 | * * 7 | * Basic actions performed by a call to ShowDeviceTxDialog(): * 8 | * - updates fl2k->cfg.dev_index * 9 | * If the dialog is cancelled, no changes are made * 10 | * * 11 | * This program is free software; you can redistribute it and/or * 12 | * modify it under the terms of the GNU General Public License as * 13 | * published by the Free Software Foundation; either version 2 of * 14 | * the License, or (at your option) any later version. * 15 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 16 | 17 | #ifndef WND_TXOPT_DEV_INCLUDED 18 | #define WND_TXOPT_DEV_INCLUDED 19 | 20 | #include "libfl2k_433.h" 21 | int ShowDeviceTxDialog(fl2k_433_t *fl, HWND hParent, char **trgdev_name); 22 | 23 | #endif // WND_TXOPT_DEV_INCLUDED 24 | -------------------------------------------------------------------------------- /include/wnd_txopt_exp.h: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * Option sub-dialog for expert settings regarding TX * 3 | * * 4 | * coded in 2018/19 by winterrace (github.com/winterrace) * 5 | * (github.com/winterrace2) * 6 | * * 7 | * If the dialog is cancelled, no changes are made * 8 | * * 9 | * This program is free software; you can redistribute it and/or * 10 | * modify it under the terms of the GNU General Public License as * 11 | * published by the Free Software Foundation; either version 2 of * 12 | * the License, or (at your option) any later version. * 13 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 14 | 15 | #ifndef WND_TXOPT_EXP_INCLUDED 16 | #define WND_TXOPT_EXP_INCLUDED 17 | 18 | #include "libfl2k_433.h" 19 | 20 | int ShowExpertDialog(fl2k_433_t *fl, HWND hParent); 21 | 22 | #endif // WND_TXOPT_EXP_INCLUDED 23 | -------------------------------------------------------------------------------- /include/wnd_txopt_freq.h: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * Option sub-dialog for TX frequency configuration * 3 | * * 4 | * coded in 2018/19 by winterrace (github.com/winterrace) * 5 | * (github.com/winterrace2) * 6 | * * 7 | * Basic actions performed by a call to ShowFrequencyTxDialog(): * 8 | * - updates fl2k->cfg. * 9 | * If the dialog is cancelled, no changes are made * 10 | * * 11 | * This program is free software; you can redistribute it and/or * 12 | * modify it under the terms of the GNU General Public License as * 13 | * published by the Free Software Foundation; either version 2 of * 14 | * the License, or (at your option) any later version. * 15 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 16 | 17 | #ifndef WND_TXOPT_FREQ_INCLUDED 18 | #define WND_TXOPT_FREQ_INCLUDED 19 | 20 | #include "libfl2k_433.h" 21 | 22 | #define FL2K_MULT_MIN 3 23 | #define FL2K_MULT_MAX 6 24 | 25 | #define FL2K_DIV_MIN 2 26 | #define FL2K_DIV_MAX 63 27 | 28 | #define FL2K_FRAC_MIN 1 29 | #define FL2K_FRAC_MAX 15 30 | 31 | #define MAX_DSP_HARMONIC 20 32 | 33 | #define FL2K_DEFAULT_MULT 6 34 | #define FL2K_DEFAULT_DIV 2 35 | #define FL2K_DEFAULT_FRAC 1 36 | 37 | #define FL2K_PRESET1_SRATE 85555554 38 | #define FL2K_PRESET1_CARRIER1 6183693 39 | #define FL2K_PRESET1_CARRIER2 0 40 | 41 | #define FL2K_PRESET2_SRATE 42777770 42 | #define FL2K_PRESET2_CARRIER1 6183693 43 | #define FL2K_PRESET2_CARRIER2 0 44 | 45 | #define FL2K_PRESET3_SRATE 21388878 46 | #define FL2K_PRESET3_CARRIER1 6183693 47 | #define FL2K_PRESET3_CARRIER2 0 48 | 49 | #define FL2K_PRESET4_SRATE 85555554 50 | #define FL2K_PRESET4_CARRIER1 6153693 51 | #define FL2K_PRESET4_CARRIER2 6213693 52 | 53 | #define FL2K_PRESET5_SRATE 85555554 54 | #define FL2K_PRESET5_CARRIER1 6213693 55 | #define FL2K_PRESET5_CARRIER2 6153693 56 | 57 | #define CARRIER_RESOLUTION 10000 // Initialize Slider with 10kHz steps 58 | 59 | int ShowFrequencyTxDialog(fl2k_433_t *fl2k, HWND hParent); 60 | 61 | #endif // WND_TXOPT_FREQ_INCLUDED 62 | -------------------------------------------------------------------------------- /include/wnd_txwarn.h: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * sub-dialog for TX warning * 3 | * * 4 | * coded in 2018/19 by winterrace (github.com/winterrace) * 5 | * (github.com/winterrace2) * 6 | * * 7 | * Basic actions performed by a call to ShowDeviceTxDialog(): * 8 | * - displays warning message and returns TRUE if user accepted * 9 | * * 10 | * This program is free software; you can redistribute it and/or * 11 | * modify it under the terms of the GNU General Public License as * 12 | * published by the Free Software Foundation; either version 2 of * 13 | * the License, or (at your option) any later version. * 14 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 15 | 16 | #ifndef WND_TXWARN_INCLUDED 17 | #define WND_TXWARN_INCLUDED 18 | 19 | BOOL ShowWarningDialog(HWND hParent); 20 | 21 | #endif // WND_TXWARN_INCLUDED 22 | -------------------------------------------------------------------------------- /include/wndelements.h: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * A class to manage window elements (to better handle resizing) * 3 | * * 4 | * coded in 2018/19 by winterrace (github.com/winterrace) * 5 | * (github.com/winterrace2) * 6 | * * 7 | * This program is free software; you can redistribute it and/or * 8 | * modify it under the terms of the GNU General Public License as * 9 | * published by the Free Software Foundation; either version 2 of * 10 | * the License, or (at your option) any later version. * 11 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 12 | 13 | #ifndef INCLUDE_WNDELEMENTS 14 | #define INCLUDE_WNDELEMENTS 15 | 16 | class WndElem { 17 | public: 18 | DWORD ctlid; 19 | HWND hWnd; 20 | RECT initrect; 21 | WndElem *next; 22 | 23 | WndElem(DWORD i, HWND w, LPRECT r); 24 | ~WndElem(); 25 | VOID add(WndElem *e); 26 | WndElem *get(DWORD ctlid); 27 | }; 28 | 29 | class WndElems { 30 | private: 31 | HWND hParent; 32 | 33 | public: 34 | WndElem *elems; 35 | 36 | WndElems(HWND hPar); 37 | ~WndElems(); 38 | HWND add(DWORD ctlid); 39 | WndElem *get(DWORD ctlid); 40 | BOOL show(DWORD ctlid, INT nShow); 41 | LRESULT sendMsg(DWORD ctlid, UINT Msg, WPARAM wParam, LPARAM lParam); 42 | BOOL enable(DWORD ctlid, BOOL bEnable); 43 | HWND getHandle(DWORD ctlid); 44 | }; 45 | 46 | #endif -------------------------------------------------------------------------------- /manual_rx.md: -------------------------------------------------------------------------------- 1 | Manual about the RX parts of rtl_fl2k_433 2 | =========== 3 | 4 | Installing libusb for your RTL-SDR device 5 | ---------------------- 6 | As for any other SDR-SDR application: Before you can use an RTL2832U-based DVB-T stick (i.e.: an RTL-SDR) in rtl_fl2k_433, you first need to install the libusb driver for it. 7 | An easy way to accomplish this is to use the tool Zadig (https://zadig.akeo.ie/) 8 | 9 | In the following example, the WinUSB driver is installed for an RTL-SDR compatible device: 10 | 11 | ![zadig rtl-sdr](pics/zadig_rtl.png) 12 | 13 | Note that you might have to repeat this step if you attach your RTL-SDR device on a different USB port of your PC. 14 | 15 | Selecting the RTL-SDR device in rtl_fl2k_433 16 | ---------------------- 17 | 18 | If you start rtl_fl2k_433 with (exactly) one RTL-SDR attached, you will find this device pre-selected in the upper left: 19 | 20 | ![program launch](pics/rx_01_launch.png) 21 | 22 | You can select a(nother) device at any time by pushing the "configure" button: 23 | 24 | ![configure rx device](pics/rx_02_dev.png) 25 | 26 | A device selection dialog will open that lets you select between all RTL-SDR devices currently detected: 27 | 28 | ![configure rx device](pics/rx_03_dev.png) 29 | 30 | Selecting the RX target frequency 31 | ---------------------- 32 | If your target device uses another frequency as the default of 433.92 MHz, you have to configure the target frequency by pushing the "configure" button next to the frequency listing: 33 | 34 | ![rx frequency presets](pics/rx_04_freq.png) 35 | 36 | This will open the dialog for the configuration of the RX frequencies: 37 | 38 | ![rx frequency settings](pics/rx_05_freq.png) 39 | 40 | Note that you can specify multiple target frequencies here that will be iterated through in an configurable hopping interval. 41 | 42 | Starting RX 43 | ---------------------- 44 | 45 | Once you start reception by pushing the "start rtl_433" button, the background of the RX list view will turn to green. Arriving messages will be added to that list. Clicking an entry will provide you with detailed information about the received message. 46 | 47 | ![rx start stop](pics/rx_06_start.png) 48 | 49 | Pulse visualization 50 | ---------------------- 51 | For the currently selected RX list entry, rtl_fl2k_433 will visualize its underlying pulses in the scope above the system log: 52 | 53 | ![rx pulses](pics/rx_07_pulses.png) 54 | 55 | Note that the librtl_433 engine might detect several signals within a single pulse sequence. Therefore, the parts of the current pulse sequence belonging to the currently selected signal are highlighted in green color. 56 | 57 | Reading and saving from/to files 58 | ---------------------- 59 | 60 | As an alternative to the SDR reception, you can open pre-recorded files using the main menu: File -> Open (feed to RX). 61 | The rtl_433 engine accepts different file types: 62 | * Raw samples (e.g. 8 bit unsigned / *.cu8) 63 | 64 | but also text-based representations like 65 | * OOK/FSK pulse data (*.ook) 66 | * VCD logic (*.vcd) 67 | 68 | Note that rtl_fl2k_433 allows you to save each signal from the RX list view in a *.ook or *.vcd text representation. Just right-click it, select "Save to file" and choose between saving the entire pulse sequence or only the parts belonging to the current signal (see above). 69 | The format of the file to be saved can be chosen in the following file selection dialog. 70 | 71 | Configuration 72 | ---------------------- 73 | Several configuration options for the rtl_433 engine can be found in the main menu in the RX (librtl_433) section: 74 | 75 | ![rx start stop](pics/rx_08_options.png) 76 | * "Protocols" 77 | Here you can enable/disable the protocols supported by librtl_433. Also you can set parameters for protocols supporting this (see screenshot below). 78 | * "Flex Protocols" 79 | Here you load text-based specifications for adding "flex" protocols to the librtl_433 engine. 80 | * "Analyzer output (in system log)" 81 | This allows you to activate some analysis features of librtl_433 (will show up in the system log during operation). 82 | * "Dump samples" 83 | Configure dumping facilities of librtl_433. 84 | * "Signal display details" 85 | Lets you enable some additional display details like high-resolution time stamps. 86 | * "Additional output" 87 | Lets you enable additional modules for decoded output (e.g. CSV files) 88 | * "Expert/special settings" 89 | Here you can change some special settings like verbosity level (affects log granularity of librtl_433) 90 | 91 | ![rx protocols](pics/rx_09_protocols.png) 92 | -------------------------------------------------------------------------------- /manual_tx.md: -------------------------------------------------------------------------------- 1 | Manual about the TX parts of rtl_fl2k_433 2 | =========== 3 | 4 | Installing libusb for your FL2K device 5 | ---------------------- 6 | Before you can use an Fl2000-based USB3 to VGA adapter in rtl_fl2k_433, you first need to install the libusb driver for it. 7 | An easy way to accomplish this is to use the tool Zadig (https://zadig.akeo.ie/) 8 | 9 | Just install the libusb-win32 driver for your FL2K device. On all FL2K adapters I've seen so far, the USB ID was "1D5C 2000". 10 | 11 | ![zadig](pics/zadig_fl2k.png) 12 | 13 | Note that the FL2000 chipset is a composite device which can present two child devices to the host computer: the VGA adapter and an (optional) flash drive containing the VGA drivers. Take care to install the libusb driver for the composite parent. You might have to (un)set these checkmarks to let Zadig show it: 14 | 15 | ![zadig_checkmarks](pics/zadig_fl2k_check.png) 16 | 17 | You can determine the right selection by the "Composite Parent" annotation or by the missing suffix of the USB id: 18 | 19 | ![zadig_device_selection](pics/zadig_devsel.png) 20 | 21 | Note that you might have to repeat this step if you attach your FL2K device on a different USB3 port of your PC. 22 | 23 | Selecting the FL2K device in rtl_fl2k_433 24 | ---------------------- 25 | 26 | If you start rtl_fl2k_433 with (exactly) one FL2K adapter attached, you will find this device pre-selected in the upper right: 27 | 28 | ![program launch](pics/tx_01_launch.png) 29 | 30 | You can select a(nother) device at any time by pushing the "configure" button: 31 | 32 | ![configure tx device](pics/tx_02_dev.png) 33 | 34 | A device selection dialog will open that lets you select between all FL2K devices currently detected: 35 | 36 | ![configure tx device](pics/tx_03_dev.png) 37 | 38 | Selecting the TX target frequency 39 | ---------------------- 40 | Ensure you have a correct setting loaded for the target frequency of your application. 41 | 42 | In rtl_fl2k_433 you can either select from some presets: 43 | 44 | ![tx frequency presets](pics/tx_04_freq.png) 45 | 46 | (more presets might follow in future) 47 | 48 | Or you select the first entry for a custom configuration and use the "configure" button to adjust the frequency settings: 49 | 50 | ![tx frequency settings](pics/tx_05_freq.png) 51 | 52 | This dialog lets you basically select a combination of the FL2K sample rate (in samples per second) and the frequency of the carrier wave (in MHz) which is used for on-off-keying transmission. 53 | 54 | When outputting the carrier wave, the FL2K adapter will produce harmonics on (n\*samplerate) +/- carrier frequency. 55 | 56 | For example: If you run your FL2K device at a sample rate of 85,555,554 samples/second and output a sine wave with a frequency of 6,180,000 Hz you will observe signals on the 5th harmonic at (5\*85,555,554) - 6,180,000 = 421,597,770 Hz and (5\*85,555,554) + 6,180,000 = 433,957,770 Hz 57 | 58 | On the right side you see a list of the expected harmonics given your current configuration. 59 | 60 | Keep in mind that the signal gets weaker with every additional harmonic: 61 | 62 | ![tx frequency settings](https://www.rtl-sdr.com/wp-content/uploads/2018/04/fl2k_harmonics.png) 63 | 64 | (image taken from https://www.rtl-sdr.com/setting-up-and-testing-osmo-fl2k/) 65 | 66 | Starting TX 67 | ---------------------- 68 | 69 | rtl_fl2k_433 provides two options to start transmission of queued signals: 70 | 71 | ![tx start stop](pics/tx_06_start.png) 72 | 73 | * "start fl2k_433" 74 | 75 | Pushing this button will initialize FL2K and starting to output a null (0 Hz) signal. It will keep running and ready to pick up each TX message you queue. This will last until you manually stop the FL2K device by pushing the button (which was renamed meanwhile in "stop fl2k_433") again. 76 | 77 | * auto start/stop 78 | 79 | Pushing this button will cause TX to start and stop automatically after new TX messages were queued and, respectively, processed. This means, the FL2K device will be deactivated while the TX queue does not contain any unsent messages. 80 | 81 | 82 | Both modes have their advantages and shortcomings. 83 | 84 | * The main advantage of the manual start/stop mode is that newly added TX messages will be sent with a very low latency since the FL2K device is already initialized. 85 | The auto start/stop mode will take some time (< 1 sec) until a newly added TX message is physically sent, if the FL2K device was previously stopped. 86 | 87 | * However, FL2K transmissions seem to be prone to breakdowns of their output signal which might not be detected by the controlling program. Therefore, the auto start/stop mode is the recommended mode, because it reduces the usage of the FL2K device and maximizes the chance that the signals will effectively be transmitted. 88 | 89 | 90 | While TX is active, the background of the TX queue will turn to red: 91 | 92 | ![tx active](pics/tx_07_send.png) 93 | -------------------------------------------------------------------------------- /pics/example1_sdrsharp_rx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winterrace2/rtl_fl2k_433/8955374f9ecd9d71ef421f9f9dcdd869d91fb6b1/pics/example1_sdrsharp_rx.png -------------------------------------------------------------------------------- /pics/example2_rx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winterrace2/rtl_fl2k_433/8955374f9ecd9d71ef421f9f9dcdd869d91fb6b1/pics/example2_rx.png -------------------------------------------------------------------------------- /pics/example3_queue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winterrace2/rtl_fl2k_433/8955374f9ecd9d71ef421f9f9dcdd869d91fb6b1/pics/example3_queue.png -------------------------------------------------------------------------------- /pics/example4_tx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winterrace2/rtl_fl2k_433/8955374f9ecd9d71ef421f9f9dcdd869d91fb6b1/pics/example4_tx.png -------------------------------------------------------------------------------- /pics/example5_sdrsharp_tx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winterrace2/rtl_fl2k_433/8955374f9ecd9d71ef421f9f9dcdd869d91fb6b1/pics/example5_sdrsharp_tx.png -------------------------------------------------------------------------------- /pics/rx_01_launch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winterrace2/rtl_fl2k_433/8955374f9ecd9d71ef421f9f9dcdd869d91fb6b1/pics/rx_01_launch.png -------------------------------------------------------------------------------- /pics/rx_02_dev.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winterrace2/rtl_fl2k_433/8955374f9ecd9d71ef421f9f9dcdd869d91fb6b1/pics/rx_02_dev.png -------------------------------------------------------------------------------- /pics/rx_03_dev.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winterrace2/rtl_fl2k_433/8955374f9ecd9d71ef421f9f9dcdd869d91fb6b1/pics/rx_03_dev.png -------------------------------------------------------------------------------- /pics/rx_04_freq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winterrace2/rtl_fl2k_433/8955374f9ecd9d71ef421f9f9dcdd869d91fb6b1/pics/rx_04_freq.png -------------------------------------------------------------------------------- /pics/rx_05_freq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winterrace2/rtl_fl2k_433/8955374f9ecd9d71ef421f9f9dcdd869d91fb6b1/pics/rx_05_freq.png -------------------------------------------------------------------------------- /pics/rx_06_start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winterrace2/rtl_fl2k_433/8955374f9ecd9d71ef421f9f9dcdd869d91fb6b1/pics/rx_06_start.png -------------------------------------------------------------------------------- /pics/rx_07_pulses.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winterrace2/rtl_fl2k_433/8955374f9ecd9d71ef421f9f9dcdd869d91fb6b1/pics/rx_07_pulses.png -------------------------------------------------------------------------------- /pics/rx_08_options.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winterrace2/rtl_fl2k_433/8955374f9ecd9d71ef421f9f9dcdd869d91fb6b1/pics/rx_08_options.png -------------------------------------------------------------------------------- /pics/rx_09_protocols.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winterrace2/rtl_fl2k_433/8955374f9ecd9d71ef421f9f9dcdd869d91fb6b1/pics/rx_09_protocols.png -------------------------------------------------------------------------------- /pics/tx_01_launch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winterrace2/rtl_fl2k_433/8955374f9ecd9d71ef421f9f9dcdd869d91fb6b1/pics/tx_01_launch.png -------------------------------------------------------------------------------- /pics/tx_02_dev.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winterrace2/rtl_fl2k_433/8955374f9ecd9d71ef421f9f9dcdd869d91fb6b1/pics/tx_02_dev.png -------------------------------------------------------------------------------- /pics/tx_03_dev.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winterrace2/rtl_fl2k_433/8955374f9ecd9d71ef421f9f9dcdd869d91fb6b1/pics/tx_03_dev.png -------------------------------------------------------------------------------- /pics/tx_04_freq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winterrace2/rtl_fl2k_433/8955374f9ecd9d71ef421f9f9dcdd869d91fb6b1/pics/tx_04_freq.png -------------------------------------------------------------------------------- /pics/tx_05_freq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winterrace2/rtl_fl2k_433/8955374f9ecd9d71ef421f9f9dcdd869d91fb6b1/pics/tx_05_freq.png -------------------------------------------------------------------------------- /pics/tx_06_start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winterrace2/rtl_fl2k_433/8955374f9ecd9d71ef421f9f9dcdd869d91fb6b1/pics/tx_06_start.png -------------------------------------------------------------------------------- /pics/tx_07_send.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winterrace2/rtl_fl2k_433/8955374f9ecd9d71ef421f9f9dcdd869d91fb6b1/pics/tx_07_send.png -------------------------------------------------------------------------------- /pics/zadig_devsel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winterrace2/rtl_fl2k_433/8955374f9ecd9d71ef421f9f9dcdd869d91fb6b1/pics/zadig_devsel.png -------------------------------------------------------------------------------- /pics/zadig_fl2k.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winterrace2/rtl_fl2k_433/8955374f9ecd9d71ef421f9f9dcdd869d91fb6b1/pics/zadig_fl2k.png -------------------------------------------------------------------------------- /pics/zadig_fl2k_check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winterrace2/rtl_fl2k_433/8955374f9ecd9d71ef421f9f9dcdd869d91fb6b1/pics/zadig_fl2k_check.png -------------------------------------------------------------------------------- /pics/zadig_rtl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winterrace2/rtl_fl2k_433/8955374f9ecd9d71ef421f9f9dcdd869d91fb6b1/pics/zadig_rtl.png -------------------------------------------------------------------------------- /res/gui_win_icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winterrace2/rtl_fl2k_433/8955374f9ecd9d71ef421f9f9dcdd869d91fb6b1/res/gui_win_icon.ico -------------------------------------------------------------------------------- /res/gui_win_resources.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Von Microsoft Visual C++ generierte Includedatei. 3 | // Verwendet durch gui_win_resources.rc 4 | // 5 | #define IDD_MAINDLG 100 6 | #define IDD_RX_DEV 110 7 | #define IDD_RX_FREQ 120 8 | #define IDD_RX_PROT 130 9 | #define IDD_RX_OUTPUT 140 10 | #define IDD_RX_EXPERT 150 11 | #define IDD_RX_SIGGRAB 160 12 | #define IDD_RX_STRGRAB 170 13 | #define IDD_RX_FLEX 180 14 | #define IDD_TX_DEV 200 15 | #define IDD_TX_FREQ 210 16 | #define IDD_TX_EXPERT 220 17 | #define IDD_TX_WARN 230 18 | #define IDD_TEXTREADER 300 19 | #define IDR_MENU1 501 20 | #define IDI_ICON1 502 21 | #define IDR_POPUPMENUS 503 22 | #define IDC_MAIN_RX_SDR_DSP 1001 23 | #define IDC_MAIN_RX_SDR_BTN 1002 24 | #define IDC_MAIN_RX_FREQ_LBL 1003 25 | #define IDC_MAIN_RX_FREQ_DSP 1004 26 | #define IDC_MAIN_RX_FREQ_BTN 1005 27 | #define IDC_MAIN_RX_STARTSTOP 1006 28 | #define IDC_MAIN_RX_COUNTER 1007 29 | #define IDC_MAIN_RX_CHKUNK 1008 30 | #define IDC_MAIN_RX_LIST 1009 31 | #define IDC_MAIN_RX_DETLIST 1010 32 | #define IDC_MAIN_RX_SCOPE 1011 33 | #define IDC_MAIN_RX_SCOPE_LBLZ 1012 34 | #define IDC_MAIN_RX_SCOPE_LBLP 1013 35 | #define IDC_MAIN_RX_SCOPE_ZOOM 1014 36 | #define IDC_MAIN_RX_SCOPE_OFFSET 1015 37 | #define IDC_MAIN_RX_STAT01 1016 38 | #define IDC_MAIN_RX_STAT02 1017 39 | #define IDC_MAIN_RX_STAT03 1018 40 | #define IDC_MAIN_TX_MODE 1019 41 | #define IDC_MAIN_TX_FILE_DSP 1020 42 | #define IDC_MAIN_TX_FILE_BTN 1021 43 | #define IDC_MAIN_TX_SDR_DSP 1022 44 | #define IDC_MAIN_TX_SDR_BTN 1023 45 | #define IDC_MAIN_TX_FREQ_LBL 1024 46 | #define IDC_MAIN_TX_FREQ_BTN 1025 47 | #define IDC_MAIN_TX_FREQ_CMB 1026 48 | #define IDC_MAIN_TX_STARTSTOP 1027 49 | #define IDC_MAIN_TX_AUTOSTART 1028 50 | #define IDC_MAIN_TX_COUNTER_Q 1029 51 | #define IDC_MAIN_TX_COUNTER_S 1030 52 | #define IDC_MAIN_TX_LIST 1031 53 | #define IDC_MAIN_TX_DETAILS 1032 54 | #define IDC_MAIN_TX_STAT01 1033 55 | #define IDC_MAIN_TX_STAT02 1034 56 | #define IDC_MAIN_TX_STAT03 1035 57 | #define IDC_MAIN_LOG 1036 58 | #define IDC_RX_DEV_LIST 1101 59 | #define IDC_RX_DEV_REFRESH 1102 60 | #define IDC_RX_DEV_SRATE 1103 61 | #define IDC_RX_DEV_RAD_GAINAUTO 1104 62 | #define IDC_RX_DEV_RAD_GAINMAN 1105 63 | #define IDC_RX_DEV_GAIN_DSP 1106 64 | #define IDC_RX_DEV_GAIN_SLIDER 1107 65 | #define IDC_RX_DEV_PPM_EDT 1108 66 | #define IDC_RX_DEV_OK 1109 67 | #define IDC_RX_DEV_CANCEL 1110 68 | #define IDC_RX_FREQ_CAPTION 1201 69 | #define IDC_RX_FREQ_LIST 1202 70 | #define IDC_RX_FREQ_ADD 1203 71 | #define IDC_RX_FREQ_EDIT 1204 72 | #define IDC_RX_FREQ_CLEAR 1205 73 | #define IDC_RX_FREQ_HOPCAP 1206 74 | #define IDC_RX_FREQ_HOPEDT 1207 75 | #define IDC_RX_FREQ_HOPBTN 1208 76 | #define IDC_RX_FREQ_OK 1209 77 | #define IDC_RX_FREQ_CANCEL 1211 78 | #define IDC_RX_PROT_CAPTION 1301 79 | #define IDC_RX_PROT_SELALL 1302 80 | #define IDC_RX_PROT_SELNONE 1303 81 | #define IDC_RX_PROT_DEFAULTS 1304 82 | #define IDC_RX_PROT_LIST 1305 83 | #define IDC_RX_PROT_OK 1306 84 | #define IDC_RX_PROT_CANCEL 1307 85 | #define IDC_RX_OUT_CHK_KV 1401 86 | #define IDC_RX_OUT_PATH_KV 1402 87 | #define IDC_RX_OUT_BTN_KV 1403 88 | #define IDC_RX_OUT_STDO_KV 1404 89 | #define IDC_RX_OUT_OVR_KV 1405 90 | #define IDC_RX_OUT_CHK_CSV 1406 91 | #define IDC_RX_OUT_PATH_CSV 1407 92 | #define IDC_RX_OUT_BTN_CSV 1408 93 | #define IDC_RX_OUT_STDO_CSV 1409 94 | #define IDC_RX_OUT_OVR_CSV 1410 95 | #define IDC_RX_OUT_CHK_JSON 1411 96 | #define IDC_RX_OUT_PATH_JSON 1412 97 | #define IDC_RX_OUT_BTN_JSON 1413 98 | #define IDC_RX_OUT_STDO_JSON 1414 99 | #define IDC_RX_OUT_OVR_JSON 1415 100 | #define IDC_RX_OUT_CHK_UDP 1416 101 | #define IDC_RX_OUT_UDP_HOST 1417 102 | #define IDC_RX_OUT_UDP_PORT 1418 103 | #define IDC_RX_OUT_BTN_OK 1419 104 | #define IDC_RX_OUT_BTN_CANCEL 1420 105 | #define IDC_RX_EXP_DUR 1501 106 | #define IDC_RX_EXP_DUR_EDT 1502 107 | #define IDC_RX_EXP_BYTEAMT 1503 108 | #define IDC_RX_EXP_BYTEAMT_EDT 1504 109 | #define IDC_RX_EXP_AUTOSTOP 1505 110 | #define IDC_RX_EXP_CONVMD 1506 111 | #define IDC_RX_EXP_DBGLVL 1507 112 | #define IDC_RX_EXP_BSIZE_EDT 1510 113 | #define IDC_RX_EXP_BSIZE_DSP 1511 114 | #define IDC_RX_EXP_BLEV_OVR 1512 115 | #define IDC_RX_EXP_BLEV_EDT 1513 116 | #define IDC_RX_EXP_SVAL_OVR 1514 117 | #define IDC_RX_EXP_SVAL_EDT 1515 118 | #define IDC_RX_EXP_LVAL_OVR 1516 119 | #define IDC_RX_EXP_LVAL_EDT 1517 120 | #define IDC_RX_EXP_BTN_OK 1518 121 | #define IDC_RX_EXP_BTN_CANCEL 1519 122 | #define IDC_RX_SIGGRAB_CHK 1601 123 | #define IDC_RX_SIGGRAB_PATH_LBL 1602 124 | #define IDC_RX_SIGGRAB_PATH 1603 125 | #define IDC_RX_SIGGRAB_PATH_BWS 1604 126 | #define IDC_RX_SIGGRAB_PATH_CLEAR 1605 127 | #define IDC_RX_SIGGRAB_OVR 1606 128 | #define IDC_RX_SIGGRAB_OK 1607 129 | #define IDC_RX_SIGGRAB_CANCEL 1608 130 | #define IDC_RX_STRGRAB_CHK 1701 131 | #define IDC_RX_STRGRAB_FILE_LBL 1702 132 | #define IDC_RX_STRGRAB_FILE 1703 133 | #define IDC_RX_STRGRAB_FILE_BWS 1704 134 | #define IDC_RX_STRGRAB_STDOUT 1705 135 | #define IDC_RX_STRGRAB_OVR 1706 136 | #define IDC_RX_STRGRAB_OK 1707 137 | #define IDC_RX_STRGRAB_CANCEL 1708 138 | #define IDC_RX_FLEX_CAPTION 1801 139 | #define IDC_RX_FLEX_ADD 1802 140 | #define IDC_RX_FLEX_CLEAR 1803 141 | #define IDC_RX_FLEX_LIST 1804 142 | #define IDC_RX_FLEX_OK 1805 143 | #define IDC_RX_FLEX_CANCEL 1806 144 | #define IDC_TX_DEV_LIST 2001 145 | #define IDC_TX_DEV_REFRESH 2002 146 | #define IDC_TX_DEV_OK 2003 147 | #define IDC_TX_DEV_CANCEL 2004 148 | #define IDC_TX_FREQ_SAMPRATE 2101 149 | #define IDC_TX_FREQ_SRATEDSP 2102 150 | #define IDC_TX_FREQ_WARNING 2103 151 | #define IDC_TX_FREQ_RADAUTO 2104 152 | #define IDC_TX_FREQ_SRATE_SL 2105 153 | #define IDC_TX_FREQ_RADMAN 2106 154 | #define IDC_TX_FREQ_MULT_DSP 2107 155 | #define IDC_TX_FREQ_MULT_SL 2108 156 | #define IDC_TX_FREQ_DIV_DSP 2109 157 | #define IDC_TX_FREQ_DIV_SL 2110 158 | #define IDC_TX_FREQ_FRAC_DSP 2111 159 | #define IDC_TX_FREQ_FRAC_SL 2112 160 | #define IDC_TX_FREQ_CARR1_DSP 2113 161 | #define IDC_TX_FREQ_CARR1_SL 2114 162 | #define IDC_TX_FREQ_CARR1_STAT 2115 163 | #define IDC_TX_FREQ_CARR2_DSP 2116 164 | #define IDC_TX_FREQ_CARR2_SL 2117 165 | #define IDC_TX_FREQ_CARR2_STAT 2118 166 | #define IDC_TX_FREQ_HARM 2119 167 | #define IDC_TX_FREQ_OK 2120 168 | #define IDC_TX_FREQ_CANCEL 2121 169 | #define IDC_TX_EXP_DBGLVL_EDT 2201 170 | #define IDC_TX_EXP_INITIME_EDT 2202 171 | #define IDC_TX_EXP_BTN_OK 2203 172 | #define IDC_TX_EXP_BTN_CANCEL 2204 173 | #define IDC_TX_WARN_TXT 2301 174 | #define IDC_TX_WARN_CHK 2302 175 | #define IDC_TX_WARN_OK 2303 176 | #define IDC_TEXTREADER_EDIT 3001 177 | #define IDC_TEXTREADER_OK 3002 178 | #define IDC_TEXTREADER_CANCEL 3003 179 | #define ID_RX_FILE 9001 180 | #define ID_RX_FILE_HIST0 9002 181 | #define ID_RX_FILE_HIST1 9003 182 | #define ID_RX_FILE_HIST2 9004 183 | #define ID_RX_FILE_HIST3 9005 184 | #define ID_RX_FILE_HIST4 9006 185 | #define ID_RX_FILE_HIST5 9007 186 | #define ID_RX_FILE_HIST6 9008 187 | #define ID_RX_FILE_HIST7 9009 188 | #define ID_RX_FILE_HIST8 9010 189 | #define ID_RX_FILE_HIST9 9011 190 | #define ID_PROG_CLOSE 9012 191 | #define ID_RX_PROT 9020 192 | #define ID_RX_FLEXPROT 9021 193 | #define ID_RX_MODE_ANALYZE 9022 194 | #define ID_RX_MODE_PLSANLZ 9023 195 | #define ID_RX_DUMP_STREAM 9024 196 | #define ID_RX_DUMP_SIGS 9025 197 | #define ID_RX_DSP_UNKNOWN 9026 198 | #define ID_RX_DSP_HIRES 9027 199 | #define ID_RX_DSP_META 9028 200 | #define ID_RX_DSP_BITS 9029 201 | #define ID_RX_OUT 9030 202 | #define ID_RX_EXP 9031 203 | #define ID_TX_DEV 9040 204 | #define ID_TX_FREQ 9041 205 | #define ID_TX_EXP 9042 206 | #define ID_RXLIST_ADDTOTXQUEUE 9049 207 | #define ID_HELP_ABOUT 9050 208 | #define ID_RXLIST_SIGTX 9060 209 | #define ID_RXLIST_PLSTX 9061 210 | #define ID_RXLIST_SAVESIG 9062 211 | #define ID_RXLIST_SAVEPLS 9063 212 | #define ID_RXLIST_DEL 9064 213 | #define ID_RXLIST_DELALL 9065 214 | #define ID_RDLIST_COPY 9066 215 | #define ID_RDLIST_COPYALL 9067 216 | #define ID_RDLIST_SAVEALL 9068 217 | #define ID_FRQLIST_DELSEL 9070 218 | #define ID_FRQLIST_DELALL 9071 219 | #define ID_FLXLIST_EDIT 9080 220 | #define ID_FLXLIST_DELSEL 9081 221 | #define ID_FLXLIST_DELALL 9082 222 | #define ID_PRTLIST_TOGGLE 9090 223 | #define ID_PRTLIST_ENABLE 9091 224 | #define ID_PRTLIST_DISABLE 9092 225 | #define ID_TXLIST_RESEND 9100 226 | #define ID_TXLIST_DEL 9101 227 | #define ID_TXLIST_DELALL 9102 228 | #define ID_LOG_COPY 9110 229 | #define ID_LOG_SAVE 9111 230 | #define ID_LOG_CLEAR 9112 231 | #define ID_PROTLIST_EDITPARAMETER 9120 232 | #define ID_PROTLIST_PAREDT 9121 233 | #define ID_PRTLIST_PAREDT 9122 234 | #define IDC_STATIC -1 235 | 236 | // Next default values for new objects 237 | // 238 | #ifdef APSTUDIO_INVOKED 239 | #ifndef APSTUDIO_READONLY_SYMBOLS 240 | #define _APS_NEXT_RESOURCE_VALUE 204 241 | #define _APS_NEXT_COMMAND_VALUE 9050 242 | #define _APS_NEXT_CONTROL_VALUE 2021 243 | #define _APS_NEXT_SYMED_VALUE 504 244 | #endif 245 | #endif 246 | -------------------------------------------------------------------------------- /src/compat_paths.cpp: -------------------------------------------------------------------------------- 1 | // compat_paths addresses following compatibility issue: 2 | // topic: default search paths for config file 3 | // issue: Linux and Windows use different common paths for config files 4 | // solution: provide specific default paths for each system 5 | 6 | #ifndef _WIN32 7 | // Linux variant 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "compat_paths.h" 15 | 16 | char **compat_get_default_conf_paths() 17 | { 18 | static char *paths[5] = { NULL }; 19 | static char buf[256] = ""; 20 | char *env_config_home = getenv("XDG_CONFIG_HOME"); 21 | if (!paths[0]) { 22 | paths[0] = "rtl_433.conf"; 23 | if (env_config_home && *env_config_home) 24 | snprintf(buf, sizeof(buf), "%s%s", env_config_home, "/rtl_433/rtl_433.conf"); 25 | else 26 | snprintf(buf, sizeof(buf), "%s%s", getenv("HOME"), "/.config/rtl_433/rtl_433.conf"); 27 | paths[1] = buf; 28 | paths[2] = "/usr/local/etc/rtl_433/rtl_433.conf"; 29 | paths[3] = "/etc/rtl_433/rtl_433.conf"; 30 | paths[4] = NULL; 31 | }; 32 | return paths; 33 | } 34 | 35 | #else 36 | // Windows variant 37 | 38 | #include 39 | #include 40 | #include 41 | 42 | #include "compat_paths.h" 43 | 44 | char **compat_get_default_conf_paths() 45 | { 46 | static char bufs[3][256]; 47 | static char *paths[4] = { NULL }; 48 | if (paths[0]) return paths; 49 | // Working directory, i.e. where the binary is located 50 | if (GetModuleFileName(NULL, bufs[0], sizeof(bufs[0]))) { 51 | char *last_backslash = strrchr(bufs[0], '\\'); 52 | if (last_backslash) 53 | *last_backslash = '\0'; 54 | strcat_s(bufs[0], sizeof(bufs[0]), "\\rtl_433.conf"); 55 | paths[0] = bufs[0]; 56 | } 57 | else { 58 | paths[0] = NULL; 59 | } 60 | // Local per user configuration files (e.g. Win7: C:\Users\myusername\AppData\Local\rtl_433\rtl_433.conf) 61 | if (SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, bufs[1]) == S_OK) { 62 | strcat_s(bufs[1], sizeof(bufs[1]), "\\rtl_433\\rtl_433.conf"); 63 | paths[1] = bufs[1]; 64 | } 65 | else { 66 | paths[1] = NULL; 67 | } 68 | // Per machine configuration data (e.g. Win7: C:\ProgramData\rtl_433\rtl_433.conf) 69 | if (SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL, 0, bufs[2]) == S_OK) { 70 | strcat_s(bufs[2], sizeof(bufs[2]), "\\rtl_433\\rtl_433.conf"); 71 | paths[2] = bufs[2]; 72 | } 73 | else { 74 | paths[2] = NULL; 75 | } 76 | paths[3] = NULL; 77 | return paths; 78 | } 79 | #endif // _WIN32 / !_WIN32 80 | -------------------------------------------------------------------------------- /src/configure.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winterrace2/rtl_fl2k_433/8955374f9ecd9d71ef421f9f9dcdd869d91fb6b1/src/configure.cpp -------------------------------------------------------------------------------- /src/confparse.cpp: -------------------------------------------------------------------------------- 1 | /** @file 2 | Light-weight (i.e. dumb) config-file parser. 3 | 4 | - a valid config line is a keyword followed by an argument to the end of line 5 | - whitespace around the keyword is ignored 6 | - comments start with a hash sign, no inline comments, empty lines are ok. 7 | - whitespace is space and tab 8 | 9 | Copyright (C) 2018 Christian W. Zuckschwerdt 10 | 11 | This program is free software; you can redistribute it and/or modify 12 | it under the terms of the GNU General Public License as published by 13 | the Free Software Foundation; either version 2 of the License, or 14 | (at your option) any later version. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include "confparse.h" 23 | #include "logwrap.h" 24 | 25 | #ifdef _WIN32 26 | #include 27 | #include 28 | #ifdef _MSC_VER 29 | #define F_OK 0 30 | #define R_OK (1<<2) 31 | #endif 32 | #endif 33 | #ifndef _MSC_VER 34 | #include 35 | #endif 36 | 37 | static off_t fsize(const char *path) 38 | { 39 | struct stat st; 40 | if (stat(path, &st) == 0) 41 | return st.st_size; 42 | 43 | return -1; 44 | } 45 | 46 | int hasconf(char const *path) 47 | { 48 | return !_access(path, R_OK); 49 | } 50 | 51 | char *readconf(char const *path) 52 | { 53 | FILE *fp; 54 | char *conf; 55 | off_t file_size = fsize(path); 56 | 57 | fp = fopen(path, "rb"); 58 | if (fp == NULL) { 59 | Gui_fprintf(stderr, "Failed to open \"%s\"\n", path); 60 | return NULL; 61 | } 62 | 63 | conf = (char *)malloc(file_size + 1); 64 | if (conf == NULL) { 65 | Gui_fprintf(stderr, "Failed to allocate memory for \"%s\"\n", path); 66 | fclose(fp); 67 | return NULL; 68 | } 69 | 70 | off_t n_read = (off_t) fread(conf, sizeof(char), file_size, fp); 71 | fclose(fp); 72 | if (n_read != file_size) { 73 | Gui_fprintf(stderr, "Failed to read \"%s\"\n", path); 74 | free(conf); 75 | return NULL; 76 | } 77 | conf[file_size] = '\0'; 78 | 79 | return conf; 80 | } 81 | 82 | int getconf(char **conf, struct conf_keywords const keywords[], char **arg) 83 | { 84 | // abort if no conf or EOF 85 | if (!conf || !*conf || !**conf) 86 | return -1; 87 | 88 | char *p = *conf; 89 | 90 | // skip whitespace and comments 91 | while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n' || *p == '#') 92 | if (*p++ == '#') { 93 | while (*p && *p != '\r' && *p != '\n') p++; 94 | } 95 | 96 | // abort if EOF 97 | if (!*p) 98 | return -1; 99 | 100 | // parse keyword 101 | char *kw = p; 102 | while (*p && *p != ' ' && *p != '\t' && *p != '\r' && *p != '\n') 103 | p++; 104 | if (*p) 105 | *p++ = '\0'; 106 | 107 | // parse arg 108 | while (*p == ' ' || *p == '\t') 109 | p++; 110 | char *ka = p; 111 | if (*p == '{') { // quoted 112 | ka = ++p; 113 | while (*p) { // skip to end-quote 114 | while (*p && *p != '}') 115 | p++; 116 | char *e = p; // possible end-quote 117 | if (*p) 118 | p++; 119 | // skip ws 120 | while (*p == ' ' || *p == '\t') 121 | p++; 122 | // check if proper end-quote 123 | if (!*p || *p == '\r' || *p == '\n' || *p == '#') { 124 | *e = '\0'; 125 | break; 126 | } 127 | } 128 | 129 | } else { // not quoted 130 | while (*p && *p != '\r' && *p != '\n') 131 | p++; 132 | if (*p) 133 | *p++ = '\0'; 134 | } 135 | 136 | // set OUT vars 137 | if (arg) 138 | *arg = ka; 139 | *conf = p; 140 | 141 | // decode keyword 142 | for (; keywords->keyword; keywords++) { 143 | if (!strcmp(keywords->keyword, kw)) { 144 | return keywords->key; 145 | } 146 | } 147 | 148 | Gui_fprintf(stderr, "Unknown keyword \"%s\"\n", kw); 149 | return '?'; 150 | } 151 | -------------------------------------------------------------------------------- /src/logwrap.cpp: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * Interfacing of (3rd party) libraries used by rtl_fl2k_433 * 3 | * * 4 | * coded in 2018/19 by winterrace (github.com/winterrace) * 5 | * (github.com/winterrace2) * 6 | * * 7 | * This program is free software; you can redistribute it and/or * 8 | * modify it under the terms of the GNU General Public License as * 9 | * published by the Free Software Foundation; either version 2 of * 10 | * the License, or (at your option) any later version. * 11 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include "logwrap.h" 18 | #include "librtl_433.h" 19 | #include "rtl-sdr.h" 20 | #include "osmo-fl2k.h" 21 | #include "libfl2k_433.h" 22 | #include "wnd_main_log.h" 23 | #include "wnd_main.h" 24 | 25 | extern loglist *lv_log; 26 | 27 | #define MAX_PRINT_LEN 5000 // maximum length of single print call is for rtl_433 usage instructions 28 | static char gui_printbuf[MAX_PRINT_LEN]; 29 | 30 | int Gui_fprintf(FILE *stream, const char* aFormat, ...) { 31 | va_list argptr; 32 | int rv = 0; 33 | 34 | va_start(argptr, aFormat); 35 | 36 | static char printbuf[512]; // local default buffer (stack). Sufficient size for most use cases. 37 | char *buf = printbuf; // we use the local buffer if possible 38 | rv = vsnprintf(NULL, 0, aFormat, argptr) + 1; // test how much space we really need 39 | int needed_cap = rv; 40 | if (needed_cap >= 0) { 41 | int need_more_mem = (needed_cap > sizeof(printbuf) ? 1 : 0); // if we need more space, we... 42 | if (need_more_mem) buf = (char*) calloc(1, needed_cap + 10); // ...allocate our buffer dynamically on the heap 43 | rv = vsprintf(buf, aFormat, argptr); 44 | // call the callback function 45 | if (rv >= 0) lv_log->AddLogEntry("rtl_fl2k_433", (stream == stderr ? LOG_TRG_STDERR : LOG_TRG_STDOUT), buf); 46 | // free the dynamic buffer (if used) 47 | if (need_more_mem) free(buf); 48 | } 49 | va_end(argptr); 50 | 51 | if (rv < 0) rv = -1; 52 | return rv; 53 | } 54 | 55 | static void wrapPrint_rtl433(char target, char *text, void *ctx) { 56 | if (lv_log) lv_log->AddLogEntry("librtl_433", target, text); 57 | } 58 | 59 | static void wrapPrint_librtlsdr(char target, char *text, void *ctx) { 60 | if (lv_log) lv_log->AddLogEntry("librtlsdr", target, text); 61 | } 62 | 63 | static void wrapPrint_libosmofl2k(char target, char *text, void *ctx) { 64 | if (lv_log) lv_log->AddLogEntry("libosmo-fl2k", target, text); 65 | } 66 | 67 | static void wrapPrint_libfl2k_433(char target, char *text, void *ctx) { 68 | if (lv_log) lv_log->AddLogEntry("libfl2k_433", target, text); 69 | } 70 | 71 | static void wrapPrint_getopt(char target, char *text, void *ctx) { 72 | if (lv_log) lv_log->AddLogEntry("getopt_win", target, text); 73 | } 74 | 75 | int initLogRedirects() { 76 | void (WINAPI *redirfn_p)(std_print_wrapper, void*); 77 | int r = 1; 78 | int r_tmp; 79 | 80 | // interfacing librtl_433 81 | #ifdef librtl_433_STATIC 82 | rtl433_print_redirection(wrapPrint_rtl433, NULL); 83 | #else 84 | r_tmp = 1; 85 | HMODULE hDllRtl433 = GetModuleHandle("librtl_433.dll"); 86 | if (hDllRtl433 != NULL) { 87 | redirfn_p = (void (WINAPI*)(std_print_wrapper, void*)) GetProcAddress(hDllRtl433, "rtl433_print_redirection"); 88 | if (redirfn_p) redirfn_p(wrapPrint_rtl433, NULL); 89 | else r_tmp = 0; 90 | } 91 | else r_tmp = 0; 92 | if (!r_tmp) { 93 | Gui_fprintf(stderr, "Print wrapper could not be registered for librtl_433, so no output messages from that library will be visible in this log."); 94 | r = 0; 95 | } 96 | 97 | #endif 98 | 99 | // interfacing librtlsdr 100 | #ifdef rtlsdr_STATIC 101 | rtlsdr_print_redirection(wrapPrint_librtlsdr, NULL); 102 | #else 103 | r_tmp = 1; 104 | HMODULE hDllRtl = GetModuleHandle("rtlsdr.dll"); 105 | if (hDllRtl != NULL) { 106 | redirfn_p = (void (WINAPI*)(std_print_wrapper, void*)) GetProcAddress(hDllRtl, "rtlsdr_print_redirection"); 107 | if (redirfn_p) redirfn_p(wrapPrint_librtlsdr, NULL); 108 | else r_tmp = 0; 109 | } 110 | else r_tmp = 0; 111 | if (!r_tmp) { 112 | Gui_fprintf(stderr, "Print wrapper could not be registered for rtlsdr, so no output messages from that library will be visible in this log."); 113 | r = 0; 114 | } 115 | #endif 116 | 117 | // interfacing getopt 118 | #ifdef STATIC_GETOPT 119 | getopt_print_redirection(wrapPrint_getopt, NULL); 120 | #else 121 | r_tmp = 1; 122 | HMODULE hDllGetopt = GetModuleHandle("getopt.dll"); 123 | if (!hDllGetopt) hDllGetopt = GetModuleHandle("getoptd.dll"); 124 | if (hDllGetopt != NULL) { 125 | redirfn_p = (void (WINAPI*)(std_print_wrapper, void*)) GetProcAddress(hDllGetopt, "getopt_print_redirection"); 126 | if (redirfn_p) redirfn_p(wrapPrint_getopt, NULL); 127 | else r_tmp = 0; 128 | } 129 | else r_tmp = 0; 130 | if (!r_tmp) { 131 | Gui_fprintf(stderr, "Print wrapper could not be registered for getopt, so no output messages from that library will be visible in this log."); 132 | r = 0; 133 | } 134 | #endif 135 | 136 | // interfacing osmo-fl2k 137 | #ifdef libosmofl2k_STATIC 138 | fl2k_print_redirection(wrapPrint_libosmofl2k, NULL); 139 | #else 140 | r_tmp = 1; 141 | HMODULE hDllFl2k = GetModuleHandle("osmo-fl2k.dll"); 142 | if (hDllFl2k != NULL) { 143 | redirfn_p = (void (WINAPI*)(std_print_wrapper, void*)) GetProcAddress(hDllFl2k, "fl2k_print_redirection"); 144 | if (redirfn_p) redirfn_p(wrapPrint_libosmofl2k, NULL); 145 | else r_tmp = 0; 146 | } 147 | else r_tmp = 0; 148 | if (!r_tmp) { 149 | Gui_fprintf(stderr, "Print wrapper could not be registered for osmo-fl2k, so no output messages from that library will be visible in this log."); 150 | r = 0; 151 | } 152 | #endif 153 | 154 | // interfacing libfl2k_433. 155 | #ifdef libfl2k_433_STATIC 156 | fl2k433_print_redirection(wrapPrint_libfl2k_433, NULL); 157 | #else 158 | r_tmp = 1; 159 | HMODULE hDllFl2k433 = GetModuleHandle("libfl2k_433.dll"); 160 | if (hDllFl2k433 != NULL) { 161 | redirfn_p = (void (WINAPI*)(std_print_wrapper, void*)) GetProcAddress(hDllFl2k433, "fl2k433_print_redirection"); 162 | if (redirfn_p) redirfn_p(wrapPrint_libfl2k_433, NULL); 163 | else r_tmp = 0; 164 | } 165 | else r_tmp = 0; 166 | if (!r_tmp) { 167 | Gui_fprintf(stderr, "Print wrapper could not be registered for libfl2k_433, so no output messages from that library will be visible in this log."); 168 | r = 0; 169 | } 170 | #endif 171 | 172 | return r; 173 | } 174 | 175 | -------------------------------------------------------------------------------- /src/optparse.cpp: -------------------------------------------------------------------------------- 1 | /** @file 2 | Option parsing functions to complement getopt. 3 | 4 | Copyright (C) 2017 Christian Zuckschwerdt 5 | 6 | This program is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | */ 11 | 12 | #include "optparse.h" 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include "logwrap.h" 18 | 19 | int atobv(char *arg, int def) 20 | { 21 | if (!arg) 22 | return def; 23 | if (!strcasecmp(arg, "true") || !strcasecmp(arg, "yes") || !strcasecmp(arg, "on") || !strcasecmp(arg, "enable")) 24 | return 1; 25 | return atoi(arg); 26 | } 27 | 28 | int atoiv(char *arg, int def) 29 | { 30 | if (!arg) 31 | return def; 32 | char *endptr; 33 | int val = strtol(arg, &endptr, 10); 34 | if (arg == endptr) 35 | return def; 36 | return val; 37 | } 38 | 39 | char *arg_param(char *arg) 40 | { 41 | if (!arg) 42 | return NULL; 43 | char *p = strchr(arg, ':'); 44 | char *c = strchr(arg, ','); 45 | if (p && (!c || p < c)) 46 | return ++p; 47 | else if (c) 48 | return c; 49 | else 50 | return p; 51 | } 52 | 53 | char *hostport_param(char *param, char **host, char **port) 54 | { 55 | if (param && *param) { 56 | if (param[0] == '/' && param[1] == '/') { 57 | param += 2; 58 | } 59 | if (*param != ':' && *param != ',') { 60 | *host = param; 61 | if (*param == '[') { 62 | (*host)++; 63 | param = strchr(param, ']'); 64 | if (param) { 65 | *param++ = '\0'; 66 | } 67 | else return NULL; // exit(1); // handled at caller 68 | } 69 | } 70 | char *colon = strchr(param, ':'); 71 | char *comma = strchr(param, ','); 72 | if (colon && (!comma || colon < comma)) { 73 | *colon++ = '\0'; 74 | *port = colon; 75 | } 76 | if (comma) { 77 | *comma++ = '\0'; 78 | return comma; 79 | } 80 | } 81 | return ""; 82 | } 83 | 84 | uint32_t atouint32_metric(const char *str, const char *error_hint) 85 | { 86 | if (!str) { 87 | Gui_fprintf(stderr, "%smissing number argument\n", error_hint); 88 | exit(1); 89 | } 90 | 91 | if (!*str) { 92 | Gui_fprintf(stderr, "%sempty number argument\n", error_hint); 93 | exit(1); 94 | } 95 | 96 | char *endptr; 97 | double val = strtod(str, &endptr); 98 | 99 | if (str == endptr) { 100 | Gui_fprintf(stderr, "%sinvalid number argument (%s)\n", error_hint, str); 101 | exit(1); 102 | } 103 | 104 | if (val < 0.0) { 105 | Gui_fprintf(stderr, "%snon-negative number argument expected (%f)\n", error_hint, val); 106 | exit(1); 107 | } 108 | 109 | // allow whitespace before suffix 110 | while (*endptr == ' ' || *endptr == '\t') 111 | ++endptr; 112 | 113 | switch (*endptr) { 114 | case '\0': 115 | break; 116 | case 'k': 117 | case 'K': 118 | val *= 1e3; 119 | break; 120 | case 'M': 121 | case 'm': 122 | val *= 1e6; 123 | break; 124 | case 'G': 125 | case 'g': 126 | val *= 1e9; 127 | break; 128 | default: 129 | Gui_fprintf(stderr, "%sunknown number suffix (%s)\n", error_hint, endptr); 130 | exit(1); 131 | } 132 | 133 | if (val > UINT32_MAX) { 134 | Gui_fprintf(stderr, "%snumber argument too big (%f)\n", error_hint, val); 135 | exit(1); 136 | } 137 | 138 | if ((uint32_t)((val - (uint32_t)val) * 1e6) != 0) { 139 | Gui_fprintf(stderr, "%sdecimal fraction (%f) did you forget k, M, or G suffix?\n", error_hint, val - (uint32_t)val); 140 | } 141 | 142 | return (uint32_t)val; 143 | } 144 | 145 | int atoi_time(const char *str, const char *error_hint) 146 | { 147 | if (!str) { 148 | Gui_fprintf(stderr, "%smissing time argument\n", error_hint); 149 | exit(1); 150 | } 151 | 152 | if (!*str) { 153 | Gui_fprintf(stderr, "%sempty time argument\n", error_hint); 154 | exit(1); 155 | } 156 | 157 | char *endptr; 158 | double val = strtod(str, &endptr); 159 | 160 | if (str == endptr) { 161 | Gui_fprintf(stderr, "%sinvalid time argument (%s)\n", error_hint, str); 162 | exit(1); 163 | } 164 | 165 | // allow whitespace before suffix 166 | while (*endptr == ' ' || *endptr == '\t') 167 | ++endptr; 168 | 169 | switch (*endptr) { 170 | case '\0': 171 | break; 172 | case 's': 173 | case 'S': 174 | break; 175 | case 'm': 176 | case 'M': 177 | val *= 60; 178 | break; 179 | case 'h': 180 | case 'H': 181 | val *= 60 * 60; 182 | break; 183 | default: 184 | Gui_fprintf(stderr, "%sunknown time suffix (%s)\n", error_hint, endptr); 185 | exit(1); 186 | } 187 | 188 | if (val > INT_MAX || val < INT_MIN) { 189 | Gui_fprintf(stderr, "%stime argument too big (%f)\n", error_hint, val); 190 | exit(1); 191 | } 192 | 193 | if ((uint32_t)((val - (uint32_t)val) * 1e6) != 0) { 194 | Gui_fprintf(stderr, "%sdecimal fraction (%f) did you forget m, or h suffix?\n", error_hint, val - (uint32_t)val); 195 | } 196 | 197 | return (int)val; 198 | } 199 | 200 | char *trim_ws(char *str) 201 | { 202 | if (!str || !*str) 203 | return str; 204 | while (*str == ' ' || *str == '\t' || *str == '\r' || *str == '\n') 205 | ++str; 206 | char *e = str; // end pointer (last non ws) 207 | char *p = str; // scanning pointer 208 | while (*p) { 209 | while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') 210 | ++p; 211 | if (*p) 212 | e = p++; 213 | } 214 | *++e = '\0'; 215 | return str; 216 | } 217 | 218 | char *remove_ws(char *str) 219 | { 220 | if (!str) 221 | return str; 222 | char *d = str; // dst pointer 223 | char *s = str; // src pointer 224 | while (*s) { 225 | while (*s == ' ' || *s == '\t' || *s == '\r' || *s == '\n') 226 | ++s; 227 | if (*s) 228 | *d++ = *s++; 229 | } 230 | *d++ = '\0'; 231 | return str; 232 | } 233 | 234 | // Unit testing 235 | #ifdef _TEST 236 | #define ASSERT_EQUALS(a,b) if ((a) == (b)) { ++passed; } else { ++failed; Gui_fprintf(stderr, "FAIL: %d <> %d\n", (a), (b)); } 237 | int main(int argc, char **argv) 238 | { 239 | unsigned passed = 0; 240 | unsigned failed = 0; 241 | 242 | Gui_fprintf(stderr, "optparse:: atouint32_metric\n"); 243 | ASSERT_EQUALS(atouint32_metric("0", ""), 0); 244 | ASSERT_EQUALS(atouint32_metric("1", ""), 1); 245 | ASSERT_EQUALS(atouint32_metric("0.0", ""), 0); 246 | ASSERT_EQUALS(atouint32_metric("1.0", ""), 1); 247 | ASSERT_EQUALS(atouint32_metric("1.024k", ""), 1024); 248 | ASSERT_EQUALS(atouint32_metric("433.92MHz", ""), 433920000); 249 | ASSERT_EQUALS(atouint32_metric(" +1 G ", ""), 1000000000); 250 | 251 | Gui_fprintf(stderr, "optparse:: atoi_time\n"); 252 | ASSERT_EQUALS(atoi_time("0", ""), 0); 253 | ASSERT_EQUALS(atoi_time("1", ""), 1); 254 | ASSERT_EQUALS(atoi_time("0.0", ""), 0); 255 | ASSERT_EQUALS(atoi_time("1.0", ""), 1); 256 | ASSERT_EQUALS(atoi_time("1s", ""), 1); 257 | ASSERT_EQUALS(atoi_time("2h", ""), 2*60*60); 258 | ASSERT_EQUALS(atoi_time(" -1 M ", ""), -60); 259 | 260 | Gui_fprintf(stderr, "optparse:: test (%u/%u) passed, (%u) failed.\n", passed, passed + failed, failed); 261 | 262 | return failed; 263 | } 264 | #endif /* _TEST */ 265 | -------------------------------------------------------------------------------- /src/rtl_fl2k_433.cpp: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * rtl_fl2k_433 * 3 | * * 4 | * a generic data receiver and transmitter * 5 | * * 6 | * coded in 2018/19 by winterrace (github.com/winterrace) * 7 | * (github.com/winterrace2) * 8 | * * 9 | * This program is free software; you can redistribute it and/or * 10 | * modify it under the terms of the GNU General Public License as * 11 | * published by the Free Software Foundation; either version 2 of * 12 | * the License, or (at your option) any later version. * 13 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 14 | 15 | #include 16 | #include "wnd_main.h" 17 | 18 | int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){ 19 | return GuiMain(); 20 | } 21 | -------------------------------------------------------------------------------- /src/rxlist_entry.cpp: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * Definition of entries in the RX list * 3 | * * 4 | * coded in 2018/19 by winterrace (github.com/winterrace) * 5 | * (github.com/winterrace2) * 6 | * * 7 | * This program is free software; you can redistribute it and/or * 8 | * modify it under the terms of the GNU General Public License as * 9 | * published by the Free Software Foundation; either version 2 of * 10 | * the License, or (at your option) any later version. * 11 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | 20 | #include "rxlist_entry.h" 21 | 22 | rx_entry::rx_entry() { 23 | this->devid = -1; 24 | memset(this->time, 0, sizeof(this->time)); 25 | memset(this->type, 0, sizeof(this->type)); 26 | memset(this->model, 0, sizeof(this->model)); 27 | this->pdat.sample_rate = 0; 28 | this->pdat.num_pulses = 0; 29 | this->pdat.pulse = NULL; 30 | this->pdat.gap = NULL; 31 | this->pdat.freq1_hz = 0; 32 | this->pdat.freq2_hz = 0; 33 | this->pdat.rssi_db = 0; 34 | this->pdat.snr_db = 0; 35 | this->pdat.noise_db = 0; 36 | this->pdat.segment_startidx = 0; 37 | this->pdat.segment_len = 0; 38 | this->pdat.num_samples = 0; 39 | this->mod = SIGNAL_MODULATION_UNK; // todo: move to pdat level? 40 | this->data = NULL; 41 | } 42 | 43 | rx_entry::~rx_entry() { 44 | if (this->pdat.pulse) free(this->pdat.pulse); 45 | // if (this->pdat.gap) free(this->pdat.gap); gap is freed with the previous line (it's just a pointer into the region alloced for pulse ) 46 | if (this->data) data_free(this->data); // frees the list (effectively, it decrements the usage counter and only actually frees the memory if it becomes 0 again) 47 | } 48 | 49 | int rx_entry::copyData(data_t *dat) { 50 | if (this->data) 51 | return 0; 52 | 53 | this->data = data_retain(dat); // Copies list by just saving the pointer and increasing the usage pointer 54 | return 1; 55 | } 56 | 57 | data_t *rx_entry::getData() { 58 | return this->data; 59 | } 60 | 61 | int rx_entry::copyPulses(const pulse_data_t *pulses, unsigned segment_start, unsigned segment_l) { 62 | if (!pulses) return 0; 63 | // check if pulses are already taken (currently calling this function is allowed once per instance. might be changed if necessary...) 64 | if (this->pdat.num_pulses || this->pdat.num_samples || this->pdat.sample_rate) return 0; 65 | // check pulse indices 66 | if ((segment_start + segment_l) > pulses->num_pulses) return 0; 67 | // alloc memory for pulses 68 | this->pdat.pulse = (int*) malloc(2* pulses->num_pulses * sizeof(int)); 69 | if (!this->pdat.pulse) return 0; 70 | this->pdat.gap = &this->pdat.pulse[pulses->num_pulses]; // gap is a pointer to the start of the second half of the same array 71 | // copy pulses 72 | this->pdat.sample_rate = pulses->sample_rate; 73 | this->pdat.num_pulses = pulses->num_pulses; 74 | this->pdat.freq1_hz = pulses->freq1_hz; 75 | this->pdat.freq2_hz = pulses->freq2_hz; 76 | this->pdat.rssi_db = pulses->rssi_db; 77 | this->pdat.snr_db = pulses->snr_db; 78 | this->pdat.noise_db = pulses->noise_db; 79 | this->pdat.segment_startidx = segment_start; 80 | this->pdat.segment_len = segment_l; 81 | memcpy(this->pdat.pulse, pulses->pulse, pulses->num_pulses * sizeof(int)); 82 | memcpy(this->pdat.gap, pulses->gap, pulses->num_pulses * sizeof(int)); 83 | // pre-calculate the total number of samples 84 | for (uint32_t a = 0; a < (pulses->num_pulses -1); a++) { // for all except the last pair: add up pulse and gap samples 85 | this->pdat.num_samples += this->pdat.pulse[a]; 86 | this->pdat.num_samples += this->pdat.gap[a]; 87 | } 88 | this->pdat.num_samples += this->pdat.pulse[pulses->num_pulses - 1]; // last pair: add up all pulse samples 89 | int last_gap_maxdsp = (this->pdat.num_samples / 100)+1; // don't display too much of the last gap. 1% of total signal length +1 should be enough to draw the falling edge. 90 | this->pdat.num_samples += min(this->pdat.gap[pulses->num_pulses - 1], last_gap_maxdsp); // (the reduced num_samples only affects the visualisation since only the last gap is shortened) 91 | return 1; 92 | } 93 | 94 | pPulseDatCompact rx_entry::getPulses() { 95 | return &this->pdat; 96 | } 97 | 98 | int rx_entry::getDevId() { 99 | return this->devid; 100 | } 101 | 102 | char *rx_entry::getTime() { 103 | return this->time; 104 | } 105 | 106 | char *rx_entry::getType() { 107 | return this->type; 108 | } 109 | 110 | char *rx_entry::getModel() { 111 | return this->model; 112 | } 113 | 114 | void rx_entry::setDevId(int v) { 115 | this->devid = v; 116 | } 117 | 118 | void rx_entry::setModulation(sigmod sm) { 119 | this->mod = sm; 120 | } 121 | 122 | sigmod rx_entry::getModulation() { 123 | return this->mod; 124 | } 125 | 126 | void rx_entry::setTime(char *str) { 127 | strncpy_s(this->time, sizeof(this->time), str, sizeof(this->time)); 128 | this->time[sizeof(this->time) - 1] = 0; 129 | } 130 | 131 | void rx_entry::setType(char *str) { 132 | strncpy_s(this->type, str, sizeof(this->type)); 133 | this->type[sizeof(this->type) - 1] = 0; 134 | } 135 | 136 | void rx_entry::setModel(char *str) { 137 | strncpy_s(this->model, sizeof(this->model), str, sizeof(this->model)); 138 | this->model[sizeof(this->model) - 1] = 0; 139 | } 140 | -------------------------------------------------------------------------------- /src/txlist_entry.cpp: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * Definition of entries in the TX list * 3 | * * 4 | * coded in 2018/19 by winterrace (github.com/winterrace) * 5 | * (github.com/winterrace2) * 6 | * * 7 | * This program is free software; you can redistribute it and/or * 8 | * modify it under the terms of the GNU General Public License as * 9 | * published by the Free Software Foundation; either version 2 of * 10 | * the License, or (at your option) any later version. * 11 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | 20 | #include "txlist_entry.h" 21 | 22 | // this will copy msg and description. 23 | // take care that msg->buf must not be freed by the caller, it will be freed by the tx_entry desctructor 24 | 25 | tx_entry::tx_entry(char *description, mod_type mod, char *buf, uint32_t len, uint32_t samp_rate) { 26 | strcpy_s(this->description, sizeof(this->description), description); 27 | this->msg.mod = mod; 28 | this->msg.buf = buf; 29 | this->msg.len = len; 30 | this->msg.samp_rate = samp_rate; 31 | this->msg.next = NULL; 32 | memset(this->time_sent, 0, sizeof(this->time_sent)); 33 | } 34 | 35 | tx_entry::~tx_entry() { 36 | if (this->msg.buf) free(this->msg.buf); 37 | } 38 | 39 | void tx_entry::setSentTime(char *timestr) { 40 | strcpy_s(this->time_sent, sizeof(this->time_sent), timestr ? timestr : ""); 41 | } 42 | 43 | char *tx_entry::getSentTime() { 44 | return (this->time_sent[0] ? this->time_sent : NULL); 45 | } 46 | 47 | char *tx_entry::getDescription() { 48 | return this->description; 49 | } 50 | 51 | TxMsg *tx_entry::getMessage() { 52 | return &this->msg; 53 | } 54 | -------------------------------------------------------------------------------- /src/wnd_main_log.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winterrace2/rtl_fl2k_433/8955374f9ecd9d71ef421f9f9dcdd869d91fb6b1/src/wnd_main_log.cpp -------------------------------------------------------------------------------- /src/wnd_main_rx.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winterrace2/rtl_fl2k_433/8955374f9ecd9d71ef421f9f9dcdd869d91fb6b1/src/wnd_main_rx.cpp -------------------------------------------------------------------------------- /src/wnd_main_rxdetails.cpp: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * Implementation of the ListView listing RX signal details * 3 | * * 4 | * coded in 2018/19 by winterrace (github.com/winterrace) * 5 | * (github.com/winterrace2) * 6 | * * 7 | * This program is free software; you can redistribute it and/or * 8 | * modify it under the terms of the GNU General Public License as * 9 | * published by the Free Software Foundation; either version 2 of * 10 | * the License, or (at your option) any later version. * 11 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include "logwrap.h" 18 | #include "rxlist_entry.h" 19 | #include "wnd_main_rxdetails.h" 20 | #include "gui_win_resources.h" 21 | 22 | /* data helper functions */ 23 | 24 | int print_value(char *trg, int cap, data_type_t type, void *value, char *format); 25 | 26 | typedef struct { 27 | int array_element_size; /* what is the element size when put inside an array? */ 28 | bool array_is_boxed; /* is the element boxed (ie. behind a pointer) when inside an array? */ 29 | } data_meta_type_t2; 30 | 31 | static data_meta_type_t2 dmt[DATA_COUNT] = { 32 | {sizeof(data_t*),true}, // DATA_DATA 33 | {sizeof(int), false}, // DATA_INT 34 | {sizeof(double), false}, // DATA_DOUBLE 35 | {sizeof(char*), true}, // DATA_STRING 36 | {sizeof(data_array_t*), true}, // DATA_ARRAY 37 | }; 38 | 39 | static int print_array_value(char *trg, int cap, data_array_t *array, char *format, int idx) 40 | { 41 | int element_size = dmt[array->type].array_element_size; 42 | char *buffer = (char*) malloc(element_size); 43 | if (!buffer) { 44 | Gui_fprintf(stderr, "print_array_value: Out of memory.\n"); 45 | return 0; 46 | } 47 | int len = 0; 48 | 49 | if (!dmt[array->type].array_is_boxed) { 50 | memcpy(buffer, (void **)((char *)array->values + element_size * idx), element_size); 51 | len = print_value(trg, cap, array->type, buffer, format); 52 | } 53 | else { 54 | len = print_value(trg, cap, array->type, *(void **)((char *)array->values + element_size * idx), format); 55 | } 56 | 57 | free(buffer); 58 | return len; 59 | } 60 | 61 | static int data_convert_array(char *trg, int cap, data_array_t *array, char *format) { 62 | int len = 0; 63 | 64 | len += max(0, sprintf_s(&trg[len], cap-len, "[")); 65 | 66 | for (int c = 0; c < array->num_values; ++c) { 67 | if (c) len += max(0, sprintf_s(&trg[len], cap-len, ", ")); 68 | len += print_array_value(&trg[len], cap-len, array, format, c); 69 | } 70 | len += max(0, sprintf_s(&trg[len], cap-len, "]")); 71 | 72 | return len; 73 | } 74 | 75 | int print_value(char *trg, int cap, data_type_t type, void *value, char *format) 76 | { 77 | if (!trg || cap <= 0) { 78 | Gui_fprintf(stderr, "print_value: Unexpected parameters (internal error).\n"); 79 | return 0; 80 | } 81 | trg[0] = 0; 82 | 83 | switch (type) { 84 | case DATA_FORMAT: 85 | case DATA_COUNT: 86 | case DATA_DATA: 87 | Gui_fprintf(stderr, "print_value: unexpected data type.\n"); 88 | return 0; 89 | case DATA_INT: 90 | return sprintf_s(trg, cap, format ? format : "%d", *(int *)value); 91 | case DATA_DOUBLE: 92 | return sprintf_s(trg, cap, format ? format : "%.3f", *(double *)value); 93 | case DATA_STRING: 94 | return sprintf_s(trg, cap, format ? format : "%s", (const char*)value); 95 | case DATA_ARRAY: 96 | return data_convert_array(trg, cap, (data_array_t *)value, format); 97 | default: 98 | Gui_fprintf(stderr, "print_value: unknown type (internal error).\n"); 99 | return 0; 100 | } 101 | } 102 | 103 | static INT ListView_GetSelectedItem(HWND hList) { 104 | if (ListView_GetSelectedCount(hList) != 1) return -2; 105 | int total_items = ListView_GetItemCount(hList); 106 | for (int a = 0; a < total_items; a++) { 107 | if (ListView_GetItemState(hList, a, LVIS_SELECTED) == LVIS_SELECTED) return a; 108 | } 109 | return -1; 110 | } 111 | 112 | 113 | rxdetails::rxdetails(HWND hWnd, HWND hParent, HMENU popup_menu){ 114 | this->hList = hWnd; 115 | this->hParWnd = hParent; 116 | this->hPopup = popup_menu; 117 | 118 | // initialize columns 119 | LVCOLUMN tmp_lvcolumn; 120 | tmp_lvcolumn.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH; 121 | tmp_lvcolumn.pszText = "key"; 122 | tmp_lvcolumn.fmt = LVCFMT_LEFT; 123 | tmp_lvcolumn.cx = RX_COLUMN_KEY; 124 | ListView_InsertColumn(this->hList, 0, &tmp_lvcolumn); 125 | tmp_lvcolumn.fmt = LVCFMT_LEFT; 126 | tmp_lvcolumn.pszText = "value"; 127 | tmp_lvcolumn.cx = RX_COLUMN_VALUE; 128 | ListView_InsertColumn(this->hList, 1, &tmp_lvcolumn); 129 | } 130 | 131 | rxdetails::~rxdetails(){ 132 | ListView_DeleteAllItems(this->hList); 133 | // no need to free any data items here since these are not kept by rxdetails (only by rxlist) 134 | } 135 | 136 | HWND rxdetails::getWndHandle() { 137 | return this->hList; 138 | } 139 | 140 | static char tmpstr[400]; 141 | VOID rxdetails::DisplayData(data_t *data){ 142 | ListView_DeleteAllItems(this->hList); 143 | data_t *d = data; 144 | while(d){ 145 | // Add line 146 | int idx = ListView_GetItemCount(this->hList); 147 | LVITEM tmp_lvitem; 148 | tmp_lvitem.iSubItem = 0; 149 | tmp_lvitem.iItem = idx; 150 | tmp_lvitem.pszText = (d->pretty_key && d->pretty_key[0] ? d->pretty_key : d->key); 151 | tmp_lvitem.mask = LVIF_TEXT; 152 | ListView_InsertItem(this->hList, &tmp_lvitem); 153 | print_value(tmpstr, sizeof(tmpstr), d->type, d->value, d->format); 154 | ListView_SetItemText(this->hList, idx, 1, tmpstr); 155 | d = d->next; 156 | } 157 | } 158 | 159 | DWORD rxdetails::getRightClickCommand(LPNMITEMACTIVATE dat, INT *selidx) { 160 | DWORD cmd = 0; 161 | if (dat && selidx) { 162 | *selidx = dat->iItem; 163 | POINT pt = dat->ptAction; 164 | INT num_entries = ListView_GetItemCount(this->hList); 165 | BOOL objsel = (*selidx >= 0 && *selidx < num_entries); 166 | EnableMenuItem(this->hPopup, ID_RDLIST_COPY, MF_BYCOMMAND | (objsel ? MF_ENABLED : MF_GRAYED)); 167 | EnableMenuItem(this->hPopup, ID_RDLIST_COPYALL, MF_BYCOMMAND | (num_entries ? MF_ENABLED : MF_GRAYED)); 168 | EnableMenuItem(this->hPopup, ID_RDLIST_SAVEALL, MF_BYCOMMAND | (num_entries ? MF_ENABLED : MF_GRAYED)); 169 | 170 | RECT list_pos; 171 | GetWindowRect(this->hList, &list_pos); 172 | cmd = TrackPopupMenu(this->hPopup, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_NONOTIFY | TPM_RETURNCMD | TPM_LEFTBUTTON, list_pos.left + pt.x, list_pos.top + pt.y, 0, this->hParWnd, 0); 173 | } 174 | return cmd; 175 | } 176 | 177 | VOID rxdetails::toString(INT id, CHAR *buf, INT cap) { 178 | buf[0] = 0; 179 | int buf_l = 0; 180 | int buf_c = cap - 1; 181 | 182 | INT start_entry = (id >= 0 ? id : 0); 183 | INT num_entries = (id >= 0 ? 1 : ListView_GetItemCount(this->hList)); 184 | 185 | for (int idx = start_entry; idx < (start_entry + num_entries) && ((buf_c - buf_l)>3); idx++) { 186 | LVITEM tmp_lvitem; 187 | tmp_lvitem.iSubItem = 0; 188 | tmp_lvitem.iItem = idx; 189 | tmp_lvitem.pszText = &buf[buf_l]; 190 | tmp_lvitem.cchTextMax = buf_c - buf_l; 191 | tmp_lvitem.mask = LVIF_TEXT; 192 | INT read = (INT)SendMessage(this->hList, LVM_GETITEMTEXT, idx, (LPARAM)&tmp_lvitem); 193 | buf_l += read; 194 | if ((buf_c - buf_l) >= 2) 195 | buf_l += sprintf_s(&buf[buf_l], buf_c - buf_l, "\t"); 196 | tmp_lvitem.iSubItem = 1; 197 | tmp_lvitem.pszText = &buf[buf_l]; 198 | tmp_lvitem.cchTextMax = buf_c - buf_l; 199 | read = (INT)SendMessage(this->hList, LVM_GETITEMTEXT, idx, (LPARAM)&tmp_lvitem); 200 | buf_l += read; 201 | if ((buf_c - buf_l) >= 3) 202 | buf_l += sprintf_s(&buf[buf_l], buf_c - buf_l, "\r\n"); 203 | } 204 | } 205 | -------------------------------------------------------------------------------- /src/wnd_main_rxlist.cpp: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * Main window element: ListView for incoming (RX) messages * 3 | * * 4 | * coded in 2018/19 by winterrace (github.com/winterrace) * 5 | * (github.com/winterrace2) * 6 | * * 7 | * This program is free software; you can redistribute it and/or * 8 | * modify it under the terms of the GNU General Public License as * 9 | * published by the Free Software Foundation; either version 2 of * 10 | * the License, or (at your option) any later version. * 11 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include "wnd_main_rxlist.h" 18 | #include "gui_win_resources.h" 19 | 20 | static INT ListView_GetSelectedItem(HWND hList) { 21 | if (ListView_GetSelectedCount(hList) != 1) return -2; 22 | int total_items = ListView_GetItemCount(hList); 23 | for (int a = 0; a < total_items; a++) { 24 | if (ListView_GetItemState(hList, a, LVIS_SELECTED) == LVIS_SELECTED) return a; 25 | } 26 | return -1; 27 | } 28 | 29 | rxlist::rxlist(HWND hLogWnd, HWND hParent, HMENU popup_menu){ 30 | this->hList = hLogWnd; 31 | this->hParWnd = hParent; 32 | this->hPopup = popup_menu; 33 | 34 | // Spalten initialisieren: 35 | LVCOLUMN tmp_lvcolumn; 36 | tmp_lvcolumn.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH; 37 | tmp_lvcolumn.pszText = "time received"; 38 | tmp_lvcolumn.fmt = LVCFMT_LEFT; 39 | tmp_lvcolumn.cx = RX_COLUMN_TIME_WIDTH; 40 | ListView_InsertColumn(this->hList, 0, &tmp_lvcolumn); 41 | tmp_lvcolumn.fmt = LVCFMT_LEFT; 42 | tmp_lvcolumn.pszText = "mod"; 43 | tmp_lvcolumn.cx = RX_COLUMN_MOD_WIDTH; 44 | ListView_InsertColumn(this->hList, 1, &tmp_lvcolumn); 45 | tmp_lvcolumn.fmt = LVCFMT_LEFT; 46 | tmp_lvcolumn.pszText = "RX message"; 47 | tmp_lvcolumn.cx = RX_COLUMN_TEXT_WIDTH; 48 | ListView_InsertColumn(this->hList, 2, &tmp_lvcolumn); 49 | Clear(); 50 | } 51 | 52 | rxlist::~rxlist(){ 53 | Clear(); 54 | } 55 | 56 | static COLORREF green = RGB(160, 255, 160); 57 | static COLORREF white = RGB(255, 255, 255); 58 | 59 | VOID rxlist::setActiveStyle(BOOL active) { 60 | ListView_SetBkColor(this->hList, (active ? green : white)); 61 | ListView_SetTextBkColor(this->hList, (active ? green : white)); 62 | RedrawWindow(this->hList, NULL, NULL, RDW_FRAME | RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW); 63 | } 64 | 65 | VOID rxlist::Clear(){ 66 | int cnt = this->GetRxEntryCount(); 67 | while (cnt > 0) { 68 | this->RemoveRxEntry(cnt-1); 69 | cnt--; 70 | } 71 | } 72 | 73 | HWND rxlist::getWndHandle() { 74 | return this->hList; 75 | } 76 | 77 | pPulseDatCompact rxlist::getPulses(int obj_idx) { 78 | rx_entry *entry = this->GetRxEntry(obj_idx); 79 | if (entry) { 80 | return entry->getPulses(); 81 | } 82 | return NULL; 83 | } 84 | 85 | data_t *rxlist::getData(int obj_idx) { 86 | rx_entry *entry = this->GetRxEntry(obj_idx); 87 | if (entry) { 88 | return entry->getData(); 89 | } 90 | return NULL; 91 | } 92 | 93 | VOID rxlist::AddRxEntry(rx_entry *entry){ 94 | char crntline[100]; 95 | 96 | if (entry) { 97 | char *time = entry->getTime(); 98 | if (time) { 99 | 100 | char *tp = entry->getType(); 101 | char *md = entry->getModel(); 102 | int id = entry->getDevId(); 103 | 104 | if (tp && *tp && md && *md) sprintf_s(crntline, "[%03lu] %s: %s", id, tp, md); 105 | else if (md && *md) sprintf_s(crntline, "[%03lu] %s", id, md); 106 | else if (tp && *tp) sprintf_s(crntline, "[%03lu] %s", id, tp); 107 | else if(id) sprintf_s(crntline, "[%03lu]", id); 108 | else sprintf_s(crntline, "[n/a]"); 109 | 110 | // Add line 111 | int idx = this->GetRxEntryCount(); 112 | BOOL autoscroll = ListView_IsItemVisible(this->hList, idx-1); // if the last item was visible before, we activate autoscrolling 113 | LVITEM tmp_lvitem; 114 | tmp_lvitem.iSubItem = 0; 115 | tmp_lvitem.iItem = idx; 116 | tmp_lvitem.pszText = time; 117 | tmp_lvitem.mask = LVIF_TEXT | LVIF_PARAM; 118 | tmp_lvitem.lParam = (LPARAM) entry; 119 | ListView_InsertItem(this->hList, &tmp_lvitem); 120 | 121 | sigmod sm = entry->getModulation(); 122 | ListView_SetItemText(this->hList, idx, 1, (sm == SIGNAL_MODULATION_OOK ? "OOK":(sm==SIGNAL_MODULATION_FSK?"FSK":"n/a"))); 123 | ListView_SetItemText(this->hList, idx, 2, crntline); 124 | 125 | if (autoscroll) ListView_EnsureVisible(this->hList, idx, FALSE); // conditional autoscrolling (ensure line is visible) 126 | } 127 | } 128 | } 129 | 130 | INT rxlist::GetRxEntryCount() { 131 | return ListView_GetItemCount(this->hList); 132 | } 133 | 134 | INT rxlist::GetSelectedItem() { 135 | return ListView_GetSelectedItem(this->hList); 136 | } 137 | 138 | rx_entry *rxlist::GetRxEntry(int obj_idx) { 139 | rx_entry *result = NULL; 140 | if (obj_idx >= 0) { 141 | int cnt = this->GetRxEntryCount(); 142 | if (obj_idx < cnt) { 143 | LVITEM tmp_lvitem; 144 | tmp_lvitem.iSubItem = 0; 145 | tmp_lvitem.iItem = obj_idx; 146 | tmp_lvitem.mask = LVIF_PARAM; 147 | tmp_lvitem.lParam = NULL; 148 | ListView_GetItem(this->hList, &tmp_lvitem); 149 | if (tmp_lvitem.lParam) { 150 | result = (rx_entry*)tmp_lvitem.lParam; 151 | } 152 | } 153 | } 154 | return result; 155 | } 156 | 157 | INT rxlist::RemoveRxEntry(int obj_idx) { 158 | rx_entry *entry = this->GetRxEntry(obj_idx); 159 | if (entry) { 160 | delete entry; 161 | ListView_DeleteItem(this->hList, obj_idx); 162 | return 1; 163 | } 164 | return 0; 165 | } 166 | 167 | DWORD rxlist::getRightClickCommand(LPNMITEMACTIVATE dat, INT *selidx) { 168 | DWORD cmd = 0; 169 | if (dat && selidx) { 170 | *selidx = dat->iItem; 171 | POINT pt = dat->ptAction; 172 | INT cnt = this->GetRxEntryCount(); 173 | BOOL objsel = (*selidx >= 0 && *selidx < cnt); 174 | EnableMenuItem(this->hPopup, 0, MF_BYPOSITION | (objsel ? MF_ENABLED : MF_DISABLED)); // popup including ID_RXLIST_SIGTX and ID_RXLIST_PLSTX 175 | EnableMenuItem(this->hPopup, 1, MF_BYPOSITION | (objsel ? MF_ENABLED : MF_DISABLED)); // popup including ID_RXLIST_SAVESIG and ID_RXLIST_SAVEPLS 176 | EnableMenuItem(this->hPopup, ID_RXLIST_DEL, MF_BYCOMMAND | (objsel ? MF_ENABLED : MF_GRAYED)); 177 | EnableMenuItem(this->hPopup, ID_RXLIST_DELALL, MF_BYCOMMAND | (cnt ? MF_ENABLED : MF_GRAYED)); 178 | 179 | RECT list_pos; 180 | GetWindowRect(this->hList, &list_pos); 181 | cmd = TrackPopupMenu(this->hPopup, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_NONOTIFY | TPM_RETURNCMD | TPM_LEFTBUTTON, list_pos.left + pt.x, list_pos.top + pt.y, 0, this->hParWnd, 0); 182 | } 183 | return cmd; 184 | } 185 | 186 | -------------------------------------------------------------------------------- /src/wnd_main_tx.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winterrace2/rtl_fl2k_433/8955374f9ecd9d71ef421f9f9dcdd869d91fb6b1/src/wnd_main_tx.cpp -------------------------------------------------------------------------------- /src/wnd_main_txlist.cpp: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * Main window element: ListView for outgoing (TX) messages * 3 | * * 4 | * coded in 2018/19 by winterrace (github.com/winterrace) * 5 | * (github.com/winterrace2) * 6 | * * 7 | * This program is free software; you can redistribute it and/or * 8 | * modify it under the terms of the GNU General Public License as * 9 | * published by the Free Software Foundation; either version 2 of * 10 | * the License, or (at your option) any later version. * 11 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include "wnd_main_txlist.h" 18 | #include "gui_win_resources.h" 19 | 20 | static INT ListView_GetSelectedItem(HWND hList) { 21 | if (ListView_GetSelectedCount(hList) != 1) return -2; 22 | int total_items = ListView_GetItemCount(hList); 23 | for (int a = 0; a < total_items; a++) { 24 | if (ListView_GetItemState(hList, a, LVIS_SELECTED) == LVIS_SELECTED) return a; 25 | } 26 | return -1; 27 | } 28 | 29 | txlist::txlist(HWND hLogWnd, HWND hParent, HMENU popup_menu){ 30 | this->hList = hLogWnd; 31 | this->hParWnd = hParent; 32 | this->hPopup = popup_menu; 33 | 34 | // Spalten initialisieren: 35 | LVCOLUMN tmp_lvcolumn; 36 | tmp_lvcolumn.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH; 37 | tmp_lvcolumn.pszText = "description"; 38 | tmp_lvcolumn.fmt = LVCFMT_LEFT; 39 | tmp_lvcolumn.cx = TX_COLUMN_DSCR_WIDTH; 40 | ListView_InsertColumn(this->hList, 0, &tmp_lvcolumn); 41 | tmp_lvcolumn.fmt = LVCFMT_LEFT; 42 | tmp_lvcolumn.pszText = "mod"; 43 | tmp_lvcolumn.cx = TX_COLUMN_MOD_WIDTH; 44 | ListView_InsertColumn(this->hList, 1, &tmp_lvcolumn); 45 | tmp_lvcolumn.fmt = LVCFMT_LEFT; 46 | tmp_lvcolumn.pszText = "time sent"; 47 | tmp_lvcolumn.cx = TX_COLUMN_SENT_WIDTH; 48 | ListView_InsertColumn(this->hList, 2, &tmp_lvcolumn); 49 | Clear(); 50 | } 51 | 52 | txlist::~txlist(){ 53 | Clear(); 54 | } 55 | 56 | static COLORREF red = RGB(255, 160, 160); 57 | static COLORREF white = RGB(255, 255, 255); 58 | 59 | VOID txlist::setActiveStyle(BOOL active) { 60 | ListView_SetBkColor(this->hList, (active ? red : white)); 61 | ListView_SetTextBkColor(this->hList, (active ? red : white)); 62 | RedrawWindow(this->hList, NULL, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_ALLCHILDREN); 63 | } 64 | 65 | VOID txlist::Clear(){ 66 | int cnt = this->CountAllEntries(); 67 | while (cnt > 0) { 68 | this->RemoveTxEntry(cnt-1); 69 | cnt--; 70 | } 71 | } 72 | 73 | HWND txlist::getWndHandle() { 74 | return this->hList; 75 | } 76 | 77 | LPSTR PrintSampleNumber(uint32_t size, char *trg, int cap) { 78 | if (size < 1024) { 79 | sprintf_s(trg, cap, "%lu samples", size); 80 | return trg; 81 | } 82 | else if (size < (1024 * 1024)) { 83 | sprintf_s(trg, cap, "%.3f kS", (double)size/1024.0); 84 | return trg; 85 | } 86 | else{ 87 | sprintf_s(trg, cap, "%.3f MS", (double)size / (1024.0 * 1024.0)); 88 | return trg; 89 | } 90 | } 91 | 92 | VOID txlist::AddTxEntry(tx_entry *entry){ 93 | if (entry) { 94 | // Add line 95 | int idx = this->CountAllEntries(); 96 | BOOL autoscroll = ListView_IsItemVisible(this->hList, idx - 1); // if the last item was visible before, we activate autoscrolling 97 | LVITEM tmp_lvitem; 98 | tmp_lvitem.iSubItem = 0; 99 | tmp_lvitem.iItem = idx; 100 | tmp_lvitem.mask = LVIF_PARAM; 101 | tmp_lvitem.lParam = (LPARAM) entry; 102 | ListView_InsertItem(this->hList, &tmp_lvitem); 103 | refreshLine(idx, entry); // sets text elements 104 | if (autoscroll) ListView_EnsureVisible(this->hList, idx, FALSE); // conditional autoscrolling (ensure line is visible) 105 | } 106 | } 107 | 108 | VOID txlist::refreshLine(int idx, tx_entry *entry) { 109 | if (entry) { 110 | ListView_SetItemText(this->hList, idx, 0, entry->getDescription()); 111 | 112 | mod_type sm = entry->getMessage()->mod; 113 | LPSTR modstr = "n/a"; 114 | if (sm == MODULATION_TYPE_OOK) modstr = "OOK"; 115 | else if (sm == MODULATION_TYPE_FSK) modstr = "FSK"; 116 | else if (sm == MODULATION_TYPE_SINE) modstr = "Sine"; 117 | ListView_SetItemText(this->hList, idx, 1, modstr); 118 | 119 | LPSTR time = entry->getSentTime(); 120 | ListView_SetItemText(this->hList, idx, 2, (time ? time : "not yet")); 121 | } 122 | } 123 | 124 | VOID txlist::refreshLine(int idx){ 125 | tx_entry *entry = this->GetTxEntry(idx); 126 | if (entry) refreshLine(idx, entry); 127 | } 128 | 129 | char *txlist::getStrView(int obj_idx, char *buf, int cap) { 130 | tx_entry *e = this->GetTxEntry(obj_idx); 131 | if (!e) return ""; 132 | 133 | TxMsg *msg = e->getMessage(); 134 | if (msg) { 135 | char tmp1[20]; 136 | mod_type sm = msg->mod; 137 | LPSTR dscr = e->getDescription(); 138 | LPSTR mod = (sm == MODULATION_TYPE_OOK ? "OOK" : (sm == MODULATION_TYPE_FSK ? "FSK" : (sm == MODULATION_TYPE_SINE ? "sine" : "n / a"))); 139 | LPSTR len = PrintSampleNumber(msg->len, tmp1, sizeof(tmp1)); 140 | double ms = (double) msg->len * 1000.0 / (double) msg->samp_rate; 141 | LPSTR time = e->getSentTime(); 142 | sprintf_s(buf, cap, "%s\r\nModulation: %s\r\nLength: %s @ %lu S/s (=> %.02f ms)\r\nSent: %s", dscr, mod, len, msg->samp_rate, ms, (time ? time : "not yet")); 143 | } 144 | else { 145 | sprintf_s(buf, cap, "Internal error (TX msg pointer is NULL) "); 146 | } 147 | 148 | return buf; 149 | } 150 | 151 | INT txlist::CountAllEntries() { 152 | return ListView_GetItemCount(this->hList); 153 | } 154 | 155 | INT txlist::CountUnsentEntries() { 156 | INT total = this->CountAllEntries(); 157 | INT unsent = 0; 158 | for (int a = 0; a < total; a++) { 159 | if (!this->hasEntryBeenSent(a)) unsent++; 160 | } 161 | return unsent; 162 | } 163 | 164 | tx_entry *txlist::GetFirstUnsentEntry(INT *obj_idx) { 165 | INT total = this->CountAllEntries(); 166 | for (int a = 0; a < total; a++) { 167 | if (!this->hasEntryBeenSent(a)) { 168 | if (obj_idx) *obj_idx = a; 169 | return this->GetTxEntry(a); 170 | } 171 | } 172 | return NULL; 173 | } 174 | 175 | INT txlist::GetSelectedItem() { 176 | return ListView_GetSelectedItem(this->hList); 177 | } 178 | 179 | tx_entry *txlist::GetTxEntry(INT obj_idx) { 180 | tx_entry *result = NULL; 181 | if (obj_idx >= 0) { 182 | int cnt = this->CountAllEntries(); 183 | if (obj_idx < cnt) { 184 | LVITEM tmp_lvitem; 185 | tmp_lvitem.iSubItem = 0; 186 | tmp_lvitem.iItem = obj_idx; 187 | tmp_lvitem.mask = LVIF_PARAM; 188 | tmp_lvitem.lParam = NULL; 189 | ListView_GetItem(this->hList, &tmp_lvitem); 190 | if (tmp_lvitem.lParam) { 191 | result = (tx_entry*)tmp_lvitem.lParam; 192 | } 193 | } 194 | } 195 | return result; 196 | } 197 | 198 | INT txlist::RemoveTxEntry(int obj_idx) { 199 | tx_entry *entry = this->GetTxEntry(obj_idx); 200 | if (entry) { 201 | delete entry; 202 | ListView_DeleteItem(this->hList, obj_idx); 203 | return 1; 204 | } 205 | return 0; 206 | } 207 | 208 | BOOL txlist::hasEntryBeenSent(int obj_idx) { 209 | tx_entry *etr = this->GetTxEntry(obj_idx); 210 | return (etr && etr->getSentTime() ? TRUE : FALSE); 211 | } 212 | 213 | DWORD txlist::getRightClickCommand(LPNMITEMACTIVATE dat, INT *selidx) { 214 | DWORD cmd = 0; 215 | if (dat && selidx) { 216 | *selidx = dat->iItem; 217 | POINT pt = dat->ptAction; 218 | INT cnt = this->CountAllEntries(); 219 | BOOL objsel = (*selidx >= 0 && *selidx < cnt); 220 | EnableMenuItem(this->hPopup, ID_TXLIST_DEL, MF_BYCOMMAND | (objsel ? MF_ENABLED : MF_GRAYED)); 221 | EnableMenuItem(this->hPopup, ID_TXLIST_RESEND, MF_BYCOMMAND | ((objsel && this->hasEntryBeenSent(*selidx)) ? MF_ENABLED : MF_GRAYED)); 222 | EnableMenuItem(this->hPopup, ID_TXLIST_DELALL, MF_BYCOMMAND | (cnt ? MF_ENABLED : MF_GRAYED)); 223 | 224 | RECT list_pos; 225 | GetWindowRect(this->hList, &list_pos); 226 | cmd = TrackPopupMenu(this->hPopup, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_NONOTIFY | TPM_RETURNCMD | TPM_LEFTBUTTON, list_pos.left + pt.x, list_pos.top + pt.y, 0, this->hParWnd, 0); 227 | } 228 | return cmd; 229 | } 230 | -------------------------------------------------------------------------------- /src/wnd_rxopt_exp.cpp: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * Option sub-dialog for expert settings regarding RX * 3 | * * 4 | * coded in 2018/19 by winterrace (github.com/winterrace) * 5 | * (github.com/winterrace2) * 6 | * * 7 | * If the dialog is cancelled, no changes are made * 8 | * * 9 | * This program is free software; you can redistribute it and/or * 10 | * modify it under the terms of the GNU General Public License as * 11 | * published by the Free Software Foundation; either version 2 of * 12 | * the License, or (at your option) any later version. * 13 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 14 | 15 | #include 16 | 17 | #include "librtl_433.h" 18 | #include "wnd_rxopt_exp.h" 19 | 20 | #include "../res/gui_win_resources.h" 21 | 22 | static rtl_433_t *rtl = NULL; 23 | 24 | static HWND hDlg; 25 | static HWND hEdtSydu, hEdtBamt, hEdtBlev, hEdtDlev, hEdtSVal, hEdtLVal, hBtnOk, hCmbConv, hVerbCmb; 26 | 27 | static int tmp_override_short; // -1 = no valid value configured, 0 = auto 28 | static int tmp_override_long; // -1 = no valid value configured, 0 = auto 29 | static int tmp_verbosity; 30 | static int tmp_duration; // -1 = no valid value configured 31 | static int tmp_byteamt; // -1 = no valid value configured 32 | static uint32_t tmp_out_block_size_d512; // 0 = no valid value configured 33 | static int32_t tmp_level_limit; // -1 = no valid value configured, 0 = auto 34 | static char tmp_conversion_mode; // 0...2 = valid, -1 = invalid 35 | static BOOL tmp_chkdur, tmp_chkbam, tmp_chkblev, tmp_chksval, tmp_chklval, tmp_chkstop; 36 | 37 | static void RefreshWndElements() { 38 | 39 | CheckDlgButton(hDlg, IDC_RX_EXP_DUR, (tmp_chkdur ? BST_CHECKED : BST_UNCHECKED)); 40 | CheckDlgButton(hDlg, IDC_RX_EXP_BYTEAMT, (tmp_chkbam ? BST_CHECKED : BST_UNCHECKED)); 41 | CheckDlgButton(hDlg, IDC_RX_EXP_BLEV_OVR, (tmp_chkblev ? BST_CHECKED : BST_UNCHECKED)); 42 | CheckDlgButton(hDlg, IDC_RX_EXP_SVAL_OVR, (tmp_chksval ? BST_CHECKED : BST_UNCHECKED)); 43 | CheckDlgButton(hDlg, IDC_RX_EXP_LVAL_OVR, (tmp_chklval ? BST_CHECKED : BST_UNCHECKED)); 44 | CheckDlgButton(hDlg, IDC_RX_EXP_AUTOSTOP, (tmp_chkstop ? BST_CHECKED : BST_UNCHECKED)); 45 | 46 | char tmpstr[100] = ""; 47 | sprintf_s(tmpstr, sizeof(tmpstr), "* 512 = %d", (512 * tmp_out_block_size_d512)); 48 | SetDlgItemText(hDlg, IDC_RX_EXP_BSIZE_DSP, tmpstr); 49 | 50 | EnableWindow(hEdtSydu, tmp_chkdur); 51 | EnableWindow(hEdtBamt, tmp_chkbam); 52 | EnableWindow(hEdtBlev, tmp_chkblev); 53 | EnableWindow(hEdtSVal, tmp_chksval); 54 | EnableWindow(hEdtLVal, tmp_chklval); 55 | EnableWindow(hBtnOk, (!tmp_chkdur || tmp_duration > 0) && (!tmp_chkbam || tmp_byteamt > 0) && (tmp_out_block_size_d512 > 0) && (!tmp_chkblev || tmp_level_limit > 0) && (!tmp_chksval || tmp_override_short > 0) && (!tmp_chklval || tmp_override_long > 0) && (tmp_conversion_mode >= CONVERT_NATIVE && tmp_conversion_mode <= CONVERT_CUSTOMARY)); 56 | } 57 | 58 | static BOOL onCommand(WPARAM wParam, LPARAM lParam) { 59 | switch (LOWORD(wParam)) { 60 | 61 | case IDC_RX_EXP_DUR: 62 | tmp_chkdur = !tmp_chkdur; 63 | RefreshWndElements(); 64 | break; 65 | 66 | case IDC_RX_EXP_DUR_EDT: { 67 | BOOL trans = FALSE; 68 | int tmp_dur = GetDlgItemInt(hDlg, IDC_RX_EXP_DUR_EDT, &trans, FALSE); 69 | tmp_duration = (trans ? tmp_dur : -1); 70 | RefreshWndElements(); 71 | break; 72 | } 73 | case IDC_RX_EXP_BYTEAMT: 74 | tmp_chkbam = !tmp_chkbam; 75 | RefreshWndElements(); 76 | break; 77 | 78 | case IDC_RX_EXP_BYTEAMT_EDT: { 79 | BOOL trans = FALSE; 80 | int tmp_bam = GetDlgItemInt(hDlg, IDC_RX_EXP_BYTEAMT_EDT, &trans, FALSE); 81 | tmp_byteamt = (trans ? tmp_bam : -1); 82 | RefreshWndElements(); 83 | break; 84 | } 85 | case IDC_RX_EXP_BSIZE_EDT: { 86 | BOOL trans = FALSE; 87 | int tmp_bsize = GetDlgItemInt(hDlg, IDC_RX_EXP_BSIZE_EDT, &trans, FALSE); 88 | tmp_out_block_size_d512 = (trans ? tmp_bsize : 0); 89 | RefreshWndElements(); 90 | break; 91 | } 92 | case IDC_RX_EXP_CONVMD: { 93 | int sel = (int)SendMessage(hCmbConv, CB_GETCURSEL, 0, 0); 94 | if (sel != tmp_conversion_mode) { 95 | tmp_conversion_mode = sel; 96 | RefreshWndElements(); 97 | } 98 | break; 99 | } 100 | case IDC_RX_EXP_AUTOSTOP: 101 | tmp_chkstop = !tmp_chkstop; 102 | RefreshWndElements(); 103 | break; 104 | 105 | case IDC_RX_EXP_DBGLVL: 106 | tmp_verbosity = (INT)SendMessage(hVerbCmb, CB_GETCURSEL, 0, 0); 107 | break; 108 | 109 | case IDC_RX_EXP_BLEV_OVR: 110 | tmp_chkblev = !tmp_chkblev; 111 | RefreshWndElements(); 112 | break; 113 | 114 | case IDC_RX_EXP_BLEV_EDT: { 115 | BOOL trans = FALSE; 116 | int tmp_lim = GetDlgItemInt(hDlg, IDC_RX_EXP_BLEV_EDT, &trans, FALSE); 117 | tmp_level_limit = (trans ? tmp_lim : -1); 118 | RefreshWndElements(); 119 | break; 120 | } 121 | 122 | case IDC_RX_EXP_SVAL_OVR: 123 | tmp_chksval = !tmp_chksval; 124 | RefreshWndElements(); 125 | break; 126 | 127 | case IDC_RX_EXP_SVAL_EDT: { 128 | BOOL trans = FALSE; 129 | int tmp_sval = GetDlgItemInt(hDlg, IDC_RX_EXP_SVAL_EDT, &trans, FALSE); 130 | tmp_override_short = (trans ? tmp_sval : -1); 131 | RefreshWndElements(); 132 | break; 133 | } 134 | 135 | case IDC_RX_EXP_LVAL_OVR: 136 | tmp_chklval = !tmp_chklval; 137 | RefreshWndElements(); 138 | break; 139 | 140 | case IDC_RX_EXP_LVAL_EDT: { 141 | BOOL trans = FALSE; 142 | int tmp_lval = GetDlgItemInt(hDlg, IDC_RX_EXP_LVAL_EDT, &trans, FALSE); 143 | tmp_override_long = (trans ? tmp_lval : -1); 144 | RefreshWndElements(); 145 | break; 146 | } 147 | 148 | case IDC_RX_EXP_BTN_OK: { 149 | rtl->cfg->duration = (tmp_chkdur && tmp_duration > 0 ? tmp_duration : 0); 150 | rtl->cfg->bytes_to_read = (tmp_chkbam && tmp_byteamt > 0 ? tmp_byteamt : 0); 151 | rtl->cfg->level_limit = (tmp_chkblev && tmp_level_limit > 0 ? tmp_level_limit : 0); 152 | rtl->cfg->override_short = (tmp_chksval && tmp_override_short > 0 ? tmp_override_short : 0); 153 | rtl->cfg->override_long = (tmp_chklval && tmp_override_long > 0 ? tmp_override_long : 0); 154 | rtl->cfg->verbosity = tmp_verbosity; 155 | rtl->cfg->out_block_size = (tmp_out_block_size_d512 > 0 ? 512 * tmp_out_block_size_d512 : 0); 156 | rtl->cfg->stop_after_successful_events_flag = (tmp_chkstop ? 1 : 0); 157 | rtl->cfg->conversion_mode = ((tmp_conversion_mode >= CONVERT_NATIVE && tmp_conversion_mode <= CONVERT_CUSTOMARY) ? (conversion_mode_t)tmp_conversion_mode : CONVERT_NATIVE); 158 | EndDialog(hDlg, TRUE); 159 | break; 160 | } 161 | 162 | case IDC_RX_EXP_BTN_CANCEL: 163 | EndDialog(hDlg, TRUE); 164 | break; 165 | 166 | default: 167 | return FALSE; 168 | } 169 | 170 | return TRUE; 171 | } 172 | 173 | static VOID onInit(HWND hwndDlg) { 174 | hDlg = hwndDlg; 175 | HICON hIcon = LoadIcon(GetModuleHandle(0), (const char *)IDI_ICON1); 176 | SendMessage(hDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcon); 177 | SendMessage(hDlg, WM_SETICON, ICON_SMALL, (LPARAM)hIcon); 178 | 179 | hEdtSydu = GetDlgItem(hDlg, IDC_RX_EXP_DUR_EDT); 180 | hEdtBamt = GetDlgItem(hDlg, IDC_RX_EXP_BYTEAMT_EDT); 181 | hEdtBlev = GetDlgItem(hDlg, IDC_RX_EXP_BLEV_EDT); 182 | hEdtSVal = GetDlgItem(hDlg, IDC_RX_EXP_SVAL_EDT); 183 | hEdtLVal = GetDlgItem(hDlg, IDC_RX_EXP_LVAL_EDT); 184 | hBtnOk = GetDlgItem(hDlg, IDC_RX_EXP_BTN_OK); 185 | hCmbConv = GetDlgItem(hDlg, IDC_RX_EXP_CONVMD); 186 | hVerbCmb = GetDlgItem(hDlg, IDC_RX_EXP_DBGLVL); 187 | 188 | SendMessage(hCmbConv, CB_ADDSTRING, 0, (LPARAM)"Native"); 189 | SendMessage(hCmbConv, CB_ADDSTRING, 0, (LPARAM)"SI"); 190 | SendMessage(hCmbConv, CB_ADDSTRING, 0, (LPARAM)"Customary"); 191 | SendMessage(hCmbConv, CB_SETCURSEL, tmp_conversion_mode, 0); 192 | 193 | SendMessage(hVerbCmb, CB_ADDSTRING, 0, (LPARAM)"0 (normal)"); 194 | SendMessage(hVerbCmb, CB_ADDSTRING, 0, (LPARAM)"1 (verbose)"); 195 | SendMessage(hVerbCmb, CB_ADDSTRING, 0, (LPARAM)"2 (verbose decoders)"); 196 | SendMessage(hVerbCmb, CB_ADDSTRING, 0, (LPARAM)"3 (debug decoders)"); 197 | SendMessage(hVerbCmb, CB_ADDSTRING, 0, (LPARAM)"4 (trace decoding)"); 198 | SendMessage(hVerbCmb, CB_SETCURSEL, tmp_verbosity, 0); 199 | 200 | if (tmp_out_block_size_d512 > 0) SetDlgItemInt(hDlg, IDC_RX_EXP_BSIZE_EDT, tmp_out_block_size_d512, FALSE); 201 | if (tmp_duration > 0) SetDlgItemInt(hDlg, IDC_RX_EXP_DUR_EDT, tmp_duration, FALSE); 202 | if (tmp_byteamt > 0) SetDlgItemInt(hDlg, IDC_RX_EXP_BYTEAMT_EDT, tmp_byteamt, FALSE); 203 | if (tmp_level_limit > 0) SetDlgItemInt(hDlg, IDC_RX_EXP_BLEV_EDT, tmp_level_limit, FALSE); 204 | if (tmp_override_short > 0) SetDlgItemInt(hDlg, IDC_RX_EXP_SVAL_EDT, tmp_override_short, FALSE); 205 | if (tmp_override_long > 0) SetDlgItemInt(hDlg, IDC_RX_EXP_LVAL_EDT, tmp_override_long, FALSE); 206 | 207 | RefreshWndElements(); 208 | } 209 | 210 | static INT_PTR CALLBACK DialogHandler(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { 211 | switch (uMsg) { 212 | 213 | case WM_COMMAND: 214 | onCommand(wParam, lParam); 215 | break; 216 | 217 | case WM_INITDIALOG: 218 | onInit(hwndDlg); 219 | break; 220 | 221 | case WM_CLOSE: 222 | EndDialog(hDlg, TRUE); 223 | break; 224 | 225 | default: 226 | return false; 227 | } 228 | return true; 229 | } 230 | 231 | int ShowExpertDialog(rtl_433_t *rtl_obj, HWND hParent) { 232 | int r = -1; 233 | if (rtl_obj) { 234 | rtl = rtl_obj; 235 | 236 | tmp_chkdur = (rtl->cfg->duration > 0); 237 | tmp_duration = (rtl->cfg->duration > 0 ? rtl->cfg->duration : -1); 238 | tmp_chkbam = (rtl->cfg->bytes_to_read > 0); 239 | tmp_byteamt = (rtl->cfg->bytes_to_read > 0 ? rtl->cfg->bytes_to_read: -1); 240 | tmp_chkblev = (rtl->cfg->level_limit > 0); 241 | tmp_level_limit = (rtl->cfg->level_limit > 0 ? rtl->cfg->level_limit : -1); 242 | tmp_chksval = (rtl->cfg->override_short > 0); 243 | tmp_override_short = (rtl->cfg->override_short > 0 ? rtl->cfg->override_short : -1); 244 | tmp_chklval = (rtl->cfg->override_long > 0); 245 | tmp_override_long = (rtl->cfg->override_long > 0 ? rtl->cfg->override_long : -1); 246 | tmp_verbosity = (rtl->cfg->verbosity < 0 ||rtl->cfg->verbosity > 4 ? 4: rtl->cfg->verbosity); 247 | tmp_out_block_size_d512 = (rtl->cfg->out_block_size > 0 && rtl->cfg->out_block_size % 512 == 0 ? rtl->cfg->out_block_size / 512 : 0); 248 | tmp_chkstop = (rtl->cfg->stop_after_successful_events_flag > 0); 249 | tmp_conversion_mode = ((rtl->cfg->conversion_mode >= CONVERT_NATIVE && rtl->cfg->conversion_mode <= CONVERT_CUSTOMARY) ? rtl->cfg->conversion_mode: -1); 250 | 251 | r = (int) DialogBox(GetModuleHandle(0), MAKEINTRESOURCE(IDD_RX_EXPERT), hParent, (DLGPROC)DialogHandler); 252 | } 253 | return r; 254 | } 255 | -------------------------------------------------------------------------------- /src/wnd_rxopt_flex.cpp: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * Option sub-dialog for flex protocol configuration * 3 | * * 4 | * coded in 2018/19 by winterrace (github.com/winterrace) * 5 | * (github.com/winterrace2) * 6 | * * 7 | * Basic actions performed by a call to ShowFlexDialog(): * 8 | * - updates cfg->flex_specs * 9 | * If the dialog is cancelled, no changes are made * 10 | * * 11 | * This program is free software; you can redistribute it and/or * 12 | * modify it under the terms of the GNU General Public License as * 13 | * published by the Free Software Foundation; either version 2 of * 14 | * the License, or (at your option) any later version. * 15 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | #include "librtl_433.h" 22 | #include "wnd_rxopt_flex.h" 23 | #include "wnd_textreader.h" 24 | 25 | #include "../res/gui_win_resources.h" 26 | 27 | 28 | static rtl_433_t *rtl = NULL; 29 | static HWND hDlg, hFlexList; 30 | static HMENU hPopup; 31 | 32 | static void flexList_addElement(LPSTR spec_src) { 33 | if (spec_src) { 34 | char *spec = strdup(spec_src); 35 | LVITEM tmp_lvitem; 36 | tmp_lvitem.iItem = ListView_GetItemCount(hFlexList); 37 | tmp_lvitem.iSubItem = 0; 38 | tmp_lvitem.pszText = spec; 39 | tmp_lvitem.lParam = (LPARAM)spec; 40 | tmp_lvitem.mask = LVIF_TEXT | LVIF_PARAM; 41 | ListView_InsertItem(hFlexList, &tmp_lvitem); 42 | } 43 | } 44 | 45 | static void flexList_init() { 46 | // create columns 47 | LVCOLUMN tmp_lvcolumn; 48 | tmp_lvcolumn.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH; 49 | tmp_lvcolumn.pszText = "Flex spec"; 50 | tmp_lvcolumn.fmt = LVCFMT_LEFT; 51 | tmp_lvcolumn.cx = OPT_FLEX_SPEC_WIDTH; 52 | ListView_InsertColumn(hFlexList, 0, &tmp_lvcolumn); 53 | 54 | //fill from config 55 | for (int a = 0; a < rtl->cfg->flex_specs.len; a++) { 56 | flexList_addElement((char*)rtl->cfg->flex_specs.elems[a]); 57 | } 58 | 59 | } 60 | static char *flexList_getSpec(int a) { 61 | int n_list_entries = ListView_GetItemCount(hFlexList); 62 | if (a < 0 || a >= n_list_entries) return NULL; 63 | 64 | LVITEM tmp_lvitem; 65 | tmp_lvitem.iItem = a; 66 | tmp_lvitem.iSubItem = 0; 67 | tmp_lvitem.lParam = NULL; 68 | tmp_lvitem.mask = LVIF_PARAM; 69 | ListView_GetItem(hFlexList, &tmp_lvitem); 70 | 71 | return (char*)tmp_lvitem.lParam; 72 | } 73 | 74 | static int flexList_editSpec(int a, char *newspec) { 75 | int n_list_entries = ListView_GetItemCount(hFlexList); 76 | if (a < 0 || a >= n_list_entries) return 0; 77 | 78 | LPSTR spec = strdup(newspec); 79 | LPSTR oldspec = flexList_getSpec(a); 80 | 81 | LVITEM tmp_lvitem; 82 | tmp_lvitem.iItem = a; 83 | tmp_lvitem.iSubItem = 0; 84 | tmp_lvitem.pszText = spec; 85 | tmp_lvitem.lParam = (LPARAM)spec; 86 | tmp_lvitem.mask = LVIF_TEXT | LVIF_PARAM; 87 | ListView_SetItem(hFlexList, &tmp_lvitem); 88 | 89 | if (oldspec) free(oldspec); 90 | return 1; 91 | } 92 | 93 | static int flexList_clear(int a) { 94 | int n_list_entries = ListView_GetItemCount(hFlexList); 95 | if (a < 0 || a >= n_list_entries) return 0; 96 | LPSTR spec = flexList_getSpec(a); 97 | ListView_DeleteItem(hFlexList, a); 98 | if (spec) free(spec); 99 | return 1; 100 | } 101 | 102 | static void flexList_clear() { 103 | int n_list_entries = ListView_GetItemCount(hFlexList); 104 | for (int a = n_list_entries - 1; a >= 0; a--) { 105 | flexList_clear(a); 106 | } 107 | } 108 | 109 | #define SEL_ALLOC_STEP 20 110 | static int *selected_indices = NULL; // array to temporarily hold the selection state of the list view entries 111 | static int selected_indices_cap = 0; 112 | 113 | static BOOL flexList_getSelectedEntries(int **sel_ents, int *n_sel, int *n_tot) { 114 | *n_tot = ListView_GetItemCount(hFlexList); 115 | if (!selected_indices_cap || *n_tot > selected_indices_cap) { 116 | selected_indices_cap = SEL_ALLOC_STEP * ((*n_tot / SEL_ALLOC_STEP) + 1); 117 | selected_indices = (int*)realloc(selected_indices, (selected_indices_cap * sizeof(int))); 118 | } 119 | if (!selected_indices) return FALSE; 120 | 121 | INT n_stored = 0; 122 | for (int a = 0; a < *n_tot; a++) { 123 | if (ListView_GetItemState(hFlexList, a, LVIS_SELECTED) == LVIS_SELECTED) { 124 | selected_indices[n_stored++] = a; 125 | } 126 | } 127 | 128 | *n_sel = n_stored; 129 | *sel_ents = selected_indices; 130 | return TRUE; 131 | } 132 | 133 | static void updateFlexGuiElements() { 134 | int n_list_entries = ListView_GetItemCount(hFlexList); 135 | 136 | char caption[40]; 137 | sprintf_s(caption, sizeof(caption), "Active flex protocols (%lu):", n_list_entries); 138 | SetDlgItemText(hDlg, IDC_RX_FLEX_CAPTION, caption); 139 | } 140 | 141 | static VOID EditFlexEntry(int idx) { 142 | LPSTR spec = flexList_getSpec(idx); 143 | LPSTR edited = ShowTextReaderDialog(hDlg, "Flex protocol specification", spec, 2000); 144 | if (edited) { 145 | if (strlen(edited) > 0) flexList_editSpec(idx, edited); 146 | else { 147 | if (MessageBox(hDlg, "Clearing the spec means deleting it. Are you sure?", "Attention:", MB_OKCANCEL | MB_ICONINFORMATION) == IDOK) { 148 | flexList_clear(idx); 149 | updateFlexGuiElements(); 150 | } 151 | } 152 | } 153 | } 154 | 155 | static BOOL onKey(LPNMLVKEYDOWN ctx) { 156 | if (!ctx) return FALSE; 157 | if (ctx->hdr.hwndFrom == hFlexList) { 158 | if (ctx->wVKey == VK_DELETE) { 159 | int *sel_ents = NULL; 160 | int n_sel; 161 | int n_tot; 162 | if (flexList_getSelectedEntries(&sel_ents, &n_sel, &n_tot)) { 163 | for (int a = n_sel - 1; a >= 0; a--) { 164 | flexList_clear(sel_ents[a]); 165 | } 166 | updateFlexGuiElements(); 167 | } 168 | return TRUE; 169 | } 170 | else if (ctx->wVKey == VK_SPACE) { 171 | int *sel_ents = NULL; 172 | int n_sel; 173 | int n_tot; 174 | if (flexList_getSelectedEntries(&sel_ents, &n_sel, &n_tot)) { 175 | if (n_sel == 1) EditFlexEntry(sel_ents[0]); 176 | } 177 | return TRUE; 178 | } 179 | } 180 | return FALSE; 181 | } 182 | 183 | static BOOL onRightClick(LPNMHDR ctx_in) { 184 | if (!ctx_in) return FALSE; 185 | if (ctx_in->hwndFrom == hFlexList) { 186 | LPNMITEMACTIVATE ctx = (LPNMITEMACTIVATE)ctx_in; 187 | 188 | int *sel_ents = NULL; 189 | int n_sel; 190 | int n_tot; 191 | if (flexList_getSelectedEntries(&sel_ents, &n_sel, &n_tot)) { 192 | EnableMenuItem(hPopup, ID_FLXLIST_EDIT, MF_BYCOMMAND | (n_sel == 1 ? MF_ENABLED : MF_GRAYED)); 193 | EnableMenuItem(hPopup, ID_FLXLIST_DELSEL, MF_BYCOMMAND | (n_sel > 0 ? MF_ENABLED : MF_GRAYED)); 194 | EnableMenuItem(hPopup, ID_FLXLIST_DELALL, MF_BYCOMMAND | (n_tot > 0 ? MF_ENABLED : MF_GRAYED)); 195 | 196 | POINT pt = ctx->ptAction; 197 | RECT list_pos; 198 | GetWindowRect(hFlexList, &list_pos); 199 | DWORD cmd = TrackPopupMenu(hPopup, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_NONOTIFY | TPM_RETURNCMD | TPM_LEFTBUTTON, list_pos.left + pt.x, list_pos.top + pt.y, 0, hDlg, 0); 200 | if (cmd == ID_FLXLIST_EDIT) { 201 | EditFlexEntry(sel_ents[0]); 202 | } 203 | else if (cmd == ID_FLXLIST_DELSEL) { 204 | for (int a = n_sel - 1; a >= 0; a--) { 205 | flexList_clear(sel_ents[a]); 206 | } 207 | updateFlexGuiElements(); 208 | } 209 | else if (cmd == ID_FLXLIST_DELALL) { 210 | flexList_clear(); 211 | updateFlexGuiElements(); 212 | } 213 | } 214 | return TRUE; 215 | } 216 | return FALSE; 217 | } 218 | 219 | static BOOL onDoubleClick(LPNMHDR ctx_in) { 220 | if (!ctx_in) return FALSE; 221 | if (ctx_in->hwndFrom == hFlexList) { 222 | LPNMITEMACTIVATE ctx = (LPNMITEMACTIVATE)ctx_in; 223 | 224 | 225 | int idx_clicked = ctx->iItem; 226 | int *sel_ents = NULL; 227 | int n_sel; 228 | int n_tot; 229 | if (flexList_getSelectedEntries(&sel_ents, &n_sel, &n_tot)) { 230 | if (n_sel == 1 && sel_ents[0] == idx_clicked) { 231 | EditFlexEntry(sel_ents[0]); 232 | } 233 | } 234 | return TRUE; 235 | } 236 | return FALSE; 237 | } 238 | 239 | static BOOL onCommand(WPARAM wParam, LPARAM lParam) { 240 | switch (LOWORD(wParam)) { 241 | 242 | case IDC_RX_FLEX_ADD: { 243 | LPSTR spec = ShowTextReaderDialog(hDlg, "Flex protocol specification", NULL, 2000); 244 | if (spec) flexList_addElement(spec); 245 | updateFlexGuiElements(); 246 | break; 247 | } 248 | 249 | case IDC_RX_FLEX_CLEAR: 250 | flexList_clear(); 251 | updateFlexGuiElements(); 252 | break; 253 | 254 | case IDC_RX_FLEX_OK: { 255 | int n_list_entries = ListView_GetItemCount(hFlexList); // current number of list entries 256 | list_clear(&rtl->cfg->flex_specs, free); 257 | list_ensure_size(&rtl->cfg->flex_specs, n_list_entries); 258 | for (int a = 0; a < n_list_entries; a++) { 259 | char *spec = flexList_getSpec(a); 260 | list_push(&rtl->cfg->flex_specs, strdup(spec)); 261 | } 262 | EndDialog(hDlg, TRUE); 263 | break; 264 | } 265 | 266 | case IDC_RX_FLEX_CANCEL: 267 | EndDialog(hDlg, TRUE); 268 | break; 269 | 270 | default: 271 | return FALSE; 272 | } 273 | return TRUE; 274 | } 275 | 276 | static VOID onInit(HWND hwndDlg) { 277 | hDlg = hwndDlg; 278 | HICON hIcon = LoadIcon(GetModuleHandle(0), (const char *)IDI_ICON1); 279 | SendMessage(hDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcon); 280 | SendMessage(hDlg, WM_SETICON, ICON_SMALL, (LPARAM)hIcon); 281 | 282 | hFlexList = GetDlgItem(hDlg, IDC_RX_FLEX_LIST); 283 | flexList_init(); 284 | updateFlexGuiElements(); 285 | } 286 | 287 | static INT_PTR CALLBACK DialogHandler(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { 288 | switch (uMsg) { 289 | 290 | case WM_NOTIFY: { 291 | switch (((LPNMHDR)lParam)->code) { 292 | 293 | case LVN_KEYDOWN: 294 | onKey((LPNMLVKEYDOWN) lParam); 295 | break; 296 | 297 | case NM_RCLICK: 298 | onRightClick((LPNMHDR) lParam); 299 | break; 300 | 301 | case NM_DBLCLK: 302 | onDoubleClick((LPNMHDR)lParam); 303 | break; 304 | 305 | default: 306 | break; 307 | } 308 | break; 309 | } 310 | 311 | case WM_COMMAND: 312 | onCommand(wParam, lParam); 313 | break; 314 | 315 | case WM_INITDIALOG: 316 | onInit(hwndDlg); 317 | break; 318 | 319 | case WM_CLOSE: 320 | EndDialog(hDlg, TRUE); 321 | break; 322 | 323 | default: 324 | return false; 325 | } 326 | return true; 327 | } 328 | 329 | int ShowFlexDialog(rtl_433_t *rtl_obj, HWND hParent, HMENU hPopupMenu) { 330 | hPopup = hPopupMenu; 331 | int r = -1; 332 | if (rtl_obj) { 333 | rtl = rtl_obj; 334 | r = (int)DialogBox(GetModuleHandle(0), MAKEINTRESOURCE(IDD_RX_FLEX), hParent, (DLGPROC)DialogHandler); 335 | } 336 | return r; 337 | } 338 | -------------------------------------------------------------------------------- /src/wnd_rxopt_freq.cpp: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * Option sub-dialog for RX frequency configuration * 3 | * * 4 | * coded in 2018/19 by winterrace (github.com/winterrace) * 5 | * (github.com/winterrace2) * 6 | * * 7 | * Basic actions performed by a call to ShowFrequencyRxDialog(): * 8 | * - updates cfg-> * 9 | * If the dialog is cancelled, no changes are made * 10 | * * 11 | * This program is free software; you can redistribute it and/or * 12 | * modify it under the terms of the GNU General Public License as * 13 | * published by the Free Software Foundation; either version 2 of * 14 | * the License, or (at your option) any later version. * 15 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 16 | 17 | #include 18 | #include 19 | 20 | #include "librtl_433.h" 21 | #include "wnd_rxopt_freq.h" 22 | 23 | #include "../res/gui_win_resources.h" 24 | 25 | static rtl_433_t *rtl = NULL; 26 | static int tmp_hoptime; 27 | 28 | static HMENU hPopup; 29 | static HWND hDlg, hFreqList, hHopCap, hHopEdt, hHopBtn; 30 | 31 | static void freqList_init() { 32 | LVCOLUMN tmp_lvcolumn; 33 | tmp_lvcolumn.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH; 34 | tmp_lvcolumn.pszText = "Frequency"; 35 | tmp_lvcolumn.fmt = LVCFMT_LEFT; 36 | tmp_lvcolumn.cx = OPT_FREQ_COLWIDTH; 37 | ListView_InsertColumn(hFreqList, 0, &tmp_lvcolumn); 38 | } 39 | 40 | static void RefreshWndElements() { 41 | int num_entries = ListView_GetItemCount(hFreqList); 42 | 43 | // caption: 44 | char caption[40]; 45 | sprintf_s(caption, sizeof(caption), "Selected frequencies (%lu):", num_entries); 46 | SetDlgItemText(hDlg, IDC_RX_FREQ_CAPTION, caption); 47 | 48 | sprintf_s(caption, sizeof(caption), "Hopping interval: %lus.", tmp_hoptime); 49 | SetDlgItemText(hDlg, IDC_RX_FREQ_HOPCAP, caption); 50 | 51 | // Hopping settings 52 | EnableWindow(hHopCap, num_entries > 1); 53 | EnableWindow(hHopEdt, num_entries > 1); 54 | EnableWindow(hHopBtn, num_entries > 1); 55 | } 56 | 57 | static void freqList_insertFreq(unsigned long freq) { 58 | int num_entries = ListView_GetItemCount(hFreqList); 59 | int trg_idx = 0; 60 | 61 | for (; trg_idx < num_entries; trg_idx++) { 62 | LVITEM tmp_lvitem; 63 | tmp_lvitem.iItem = trg_idx; 64 | tmp_lvitem.iSubItem = 0; 65 | tmp_lvitem.lParam = 0; 66 | tmp_lvitem.mask = LVIF_PARAM; 67 | ListView_GetItem(hFreqList, &tmp_lvitem); 68 | if (freq == tmp_lvitem.lParam) return; 69 | if (freq < tmp_lvitem.lParam) break; 70 | } 71 | 72 | char nice_freq[20]; 73 | if (freq >= 1E9) snprintf(nice_freq, sizeof(nice_freq), "%.3fGHz", (double)freq / 1E9); 74 | else if (freq >= 1E6) snprintf(nice_freq, sizeof(nice_freq), "%.3fMHz", (double)freq / 1E6); 75 | else if (freq >= 1E3) snprintf(nice_freq, sizeof(nice_freq), "%.3fkHz", (double)freq / 1E3); 76 | else snprintf(nice_freq, sizeof(nice_freq), "%f", (double)freq); 77 | char freqstr[150]; 78 | sprintf_s(freqstr, sizeof(freqstr), "%lu (%s)", freq, nice_freq); 79 | 80 | LVITEM tmp_lvitem; 81 | tmp_lvitem.iItem = trg_idx; 82 | tmp_lvitem.iSubItem = 0; 83 | tmp_lvitem.pszText = freqstr; 84 | tmp_lvitem.mask = LVIF_TEXT | LVIF_PARAM; 85 | tmp_lvitem.lParam = freq; 86 | ListView_InsertItem(hFreqList, &tmp_lvitem); 87 | } 88 | 89 | static void saveToCfg() { 90 | int num_entries = min(ListView_GetItemCount(hFreqList), MAX_FREQS); 91 | 92 | for (int a = 0; a < num_entries; a++) { 93 | LVITEM tmp_lvitem; 94 | tmp_lvitem.iItem = a; 95 | tmp_lvitem.iSubItem = 0; 96 | tmp_lvitem.lParam = 0; 97 | tmp_lvitem.mask = LVIF_PARAM; 98 | ListView_GetItem(hFreqList, &tmp_lvitem); 99 | rtl->cfg->frequency[a] = (unsigned long) tmp_lvitem.lParam; 100 | } 101 | rtl->cfg->frequencies = num_entries; 102 | rtl->cfg->hop_time = tmp_hoptime; 103 | } 104 | 105 | static int freqList_clear(int a) { 106 | int n_list_entries = ListView_GetItemCount(hFreqList); 107 | if (a < 0 || a >= n_list_entries) return 0; 108 | ListView_DeleteItem(hFreqList, a); 109 | return 1; 110 | } 111 | 112 | static void freqList_clear() { 113 | ListView_DeleteAllItems(hFreqList); 114 | //int n_list_entries = ListView_GetItemCount(hFreqList); 115 | //for (int a = n_list_entries - 1; a >= 0; a--) { 116 | // freqList_clear(a); 117 | //} 118 | } 119 | 120 | #define SEL_ALLOC_STEP 20 121 | static int *selected_indices = NULL; // array to temporarily hold the selection state of the list view entries 122 | static int selected_indices_cap = 0; 123 | 124 | static BOOL freqList_getSelectedEntries(int **sel_ents, int *n_sel, int *n_tot) { 125 | *n_tot = ListView_GetItemCount(hFreqList); 126 | if (!selected_indices_cap || *n_tot > selected_indices_cap) { 127 | selected_indices_cap = SEL_ALLOC_STEP * ((*n_tot / SEL_ALLOC_STEP) + 1); 128 | selected_indices = (int*)realloc(selected_indices, (selected_indices_cap * sizeof(int))); 129 | } 130 | if (!selected_indices) return FALSE; 131 | 132 | INT n_stored = 0; 133 | for (int a = 0; a < *n_tot; a++) { 134 | if (ListView_GetItemState(hFreqList, a, LVIS_SELECTED) == LVIS_SELECTED) { 135 | selected_indices[n_stored++] = a; 136 | } 137 | } 138 | 139 | *n_sel = n_stored; 140 | *sel_ents = selected_indices; 141 | return TRUE; 142 | } 143 | 144 | static BOOL onKey(LPNMLVKEYDOWN ctx) { 145 | if (!ctx) return FALSE; 146 | if (ctx->hdr.hwndFrom == hFreqList) { 147 | if (ctx->wVKey == VK_DELETE) { 148 | int *sel_ents = NULL; 149 | int n_sel; 150 | int n_tot; 151 | if (freqList_getSelectedEntries(&sel_ents, &n_sel, &n_tot)) { 152 | for (int a = n_sel - 1; a >= 0; a--) { 153 | freqList_clear(sel_ents[a]); 154 | } 155 | RefreshWndElements(); 156 | } 157 | return TRUE; 158 | } 159 | } 160 | return FALSE; 161 | } 162 | 163 | static BOOL onRightClick(LPNMHDR ctx_in) { 164 | if (!ctx_in) return FALSE; 165 | if (ctx_in->hwndFrom == hFreqList) { 166 | LPNMITEMACTIVATE ctx = (LPNMITEMACTIVATE)ctx_in; 167 | 168 | int *sel_ents = NULL; 169 | int n_sel; 170 | int n_tot; 171 | if (freqList_getSelectedEntries(&sel_ents, &n_sel, &n_tot)) { 172 | //INT clkidx = ctx->iItem; 173 | EnableMenuItem(hPopup, ID_FRQLIST_DELSEL, MF_BYCOMMAND | (n_sel > 0 ? MF_ENABLED : MF_GRAYED)); 174 | EnableMenuItem(hPopup, ID_FRQLIST_DELALL, MF_BYCOMMAND | (n_tot > 0 ? MF_ENABLED : MF_GRAYED)); 175 | 176 | POINT pt = ctx->ptAction; 177 | RECT list_pos; 178 | GetWindowRect(hFreqList, &list_pos); 179 | DWORD cmd = TrackPopupMenu(hPopup, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_NONOTIFY | TPM_RETURNCMD | TPM_LEFTBUTTON, list_pos.left + pt.x, list_pos.top + pt.y, 0, hDlg, 0); 180 | if (cmd == ID_FRQLIST_DELSEL) { 181 | for (int a = n_sel - 1; a >= 0; a--) { 182 | freqList_clear(sel_ents[a]); 183 | } 184 | RefreshWndElements(); 185 | } 186 | else if (cmd == ID_FRQLIST_DELALL) { 187 | freqList_clear(); 188 | RefreshWndElements(); 189 | } 190 | 191 | } 192 | return TRUE; 193 | } 194 | return FALSE; 195 | } 196 | 197 | static BOOL onCommand(WPARAM wParam, LPARAM lParam) { 198 | switch (LOWORD(wParam)) { 199 | 200 | case IDC_RX_FREQ_ADD: { 201 | BOOL trans = FALSE; 202 | unsigned long freq = GetDlgItemInt(hDlg, IDC_RX_FREQ_EDIT, &trans, FALSE); 203 | if (trans) { 204 | freqList_insertFreq(freq); 205 | RefreshWndElements(); 206 | } 207 | break; 208 | } 209 | 210 | case IDC_RX_FREQ_CLEAR: 211 | freqList_clear(); 212 | RefreshWndElements(); 213 | break; 214 | 215 | case IDC_RX_FREQ_HOPBTN: { 216 | BOOL trans = FALSE; 217 | unsigned long ht = GetDlgItemInt(hDlg, IDC_RX_FREQ_HOPEDT, &trans, FALSE); 218 | if (trans && ht) tmp_hoptime = ht; 219 | RefreshWndElements(); 220 | break; 221 | } 222 | 223 | case IDC_RX_FREQ_OK: 224 | saveToCfg(); 225 | EndDialog(hDlg, TRUE); 226 | break; 227 | 228 | case IDC_RX_FREQ_CANCEL: 229 | EndDialog(hDlg, TRUE); 230 | break; 231 | 232 | default: 233 | return FALSE; 234 | } 235 | return TRUE; 236 | } 237 | 238 | static VOID onInit(HWND hwndDlg) { 239 | hDlg = hwndDlg; 240 | HICON hIcon = LoadIcon(GetModuleHandle(0), (const char *)IDI_ICON1); 241 | SendMessage(hDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcon); 242 | SendMessage(hDlg, WM_SETICON, ICON_SMALL, (LPARAM)hIcon); 243 | 244 | hFreqList = GetDlgItem(hDlg, IDC_RX_FREQ_LIST); 245 | 246 | hHopCap = GetDlgItem(hDlg, IDC_RX_FREQ_HOPCAP); 247 | hHopEdt = GetDlgItem(hDlg, IDC_RX_FREQ_HOPEDT); 248 | hHopBtn = GetDlgItem(hDlg, IDC_RX_FREQ_HOPBTN); 249 | 250 | freqList_init(); 251 | for (int a = 0; a cfg->frequencies; a++) { 252 | freqList_insertFreq(rtl->cfg->frequency[a]); 253 | } 254 | 255 | RefreshWndElements(); 256 | } 257 | 258 | static INT_PTR CALLBACK DialogHandler(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { 259 | switch (uMsg) { 260 | 261 | case WM_NOTIFY: { 262 | switch (((LPNMHDR)lParam)->code) { 263 | 264 | case LVN_KEYDOWN: 265 | onKey((LPNMLVKEYDOWN) lParam); 266 | break; 267 | 268 | case NM_RCLICK: 269 | onRightClick((LPNMHDR) lParam); 270 | break; 271 | 272 | default: 273 | break; 274 | } 275 | break; 276 | } 277 | 278 | case WM_COMMAND: 279 | onCommand(wParam, lParam); 280 | break; 281 | 282 | case WM_INITDIALOG: 283 | onInit(hwndDlg); 284 | break; 285 | 286 | case WM_CLOSE: 287 | EndDialog(hDlg, TRUE); 288 | break; 289 | 290 | default: 291 | return false; 292 | } 293 | return true; 294 | } 295 | 296 | int ShowFrequencyRxDialog(rtl_433_t *rtl_obj,HWND hParent, HMENU hPopupMenu) { 297 | hPopup = hPopupMenu; 298 | int r = -1; 299 | if (rtl_obj) { 300 | rtl = rtl_obj; 301 | if (!rtl->cfg->frequencies) { 302 | rtl->cfg->frequencies = 1; 303 | rtl->cfg->frequency[0] = DEFAULT_FREQUENCY; 304 | } 305 | tmp_hoptime = rtl->cfg->hop_time; 306 | if (!tmp_hoptime) tmp_hoptime = DEFAULT_HOP_TIME; 307 | r = (int) DialogBox(GetModuleHandle(0), MAKEINTRESOURCE(IDD_RX_FREQ), hParent, (DLGPROC)DialogHandler); 308 | } 309 | return r; 310 | } 311 | -------------------------------------------------------------------------------- /src/wnd_rxopt_siggrab.cpp: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * Sub-dialog to configure dumping of signals * 3 | * * 4 | * coded in 2018/19 by winterrace (github.com/winterrace) * 5 | * (github.com/winterrace2) * 6 | * * 7 | * If the dialog is cancelled, no changes are made * 8 | * * 9 | * This program is free software; you can redistribute it and/or * 10 | * modify it under the terms of the GNU General Public License as * 11 | * published by the Free Software Foundation; either version 2 of * 12 | * the License, or (at your option) any later version. * 13 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 14 | 15 | #include 16 | #include 17 | #include // Contains SHBrowseForFolder 18 | 19 | #include "librtl_433.h" 20 | #include "wnd_rxopt_siggrab.h" 21 | 22 | #include "../res/gui_win_resources.h" 23 | 24 | static rtl_433_t *rtl = NULL; 25 | 26 | static char tmp_siggrab_path[MAX_PATHLEN]; // path or "" for working dir 27 | static BOOL tmp_siggrab_configured; 28 | static unsigned char tmp_ovrflags_configured; 29 | 30 | static HWND hDlg, hPathLbl, hPathDsp, hPathBtnSet, hPathBtnCls, hOutOverwrite; 31 | 32 | static void RefreshWndElements() { 33 | SetDlgItemText(hDlg, IDC_RX_SIGGRAB_PATH, (!tmp_siggrab_path[0] ? "" : tmp_siggrab_path)); 34 | CheckDlgButton(hDlg, IDC_RX_SIGGRAB_CHK, (tmp_siggrab_configured ? BST_CHECKED : BST_UNCHECKED)); 35 | CheckDlgButton(hDlg, IDC_RX_SIGGRAB_OVR, (tmp_ovrflags_configured & OVR_SUBJ_SIGNALS ? BST_CHECKED : BST_UNCHECKED)); 36 | EnableWindow(hPathLbl, tmp_siggrab_configured); 37 | EnableWindow(hPathDsp, tmp_siggrab_configured); 38 | EnableWindow(hPathBtnSet, tmp_siggrab_configured); 39 | EnableWindow(hPathBtnCls, tmp_siggrab_configured); 40 | } 41 | 42 | static BOOL GetSaveFolder(LPSTR buf, INT cap, LPSTR title) { 43 | char fpath[MAX_PATH]; 44 | BROWSEINFO BrwsInf = { hDlg,0,0,title, BIF_RETURNONLYFSDIRS,0,0,0 }; 45 | PIDLIST_ABSOLUTE FldId = SHBrowseForFolder(&BrwsInf); 46 | if (!FldId || !SHGetPathFromIDList(FldId, fpath)) return FALSE; 47 | strcpy_s(buf, cap, fpath); 48 | return TRUE; 49 | } 50 | 51 | static BOOL onCommand(WPARAM wParam, LPARAM lParam) { 52 | switch (LOWORD(wParam)) { 53 | 54 | case IDC_RX_SIGGRAB_CHK: 55 | tmp_siggrab_configured = !tmp_siggrab_configured; 56 | RefreshWndElements(); 57 | break; 58 | 59 | case IDC_RX_SIGGRAB_PATH_BWS: 60 | if (tmp_siggrab_configured && GetSaveFolder(tmp_siggrab_path, sizeof(tmp_siggrab_path), "Select target dir (if cancelled, working dir will be used)")) { 61 | RefreshWndElements(); 62 | } 63 | break; 64 | 65 | case IDC_RX_SIGGRAB_PATH_CLEAR: 66 | if (tmp_siggrab_configured) { 67 | tmp_siggrab_path[0] = 0; 68 | RefreshWndElements(); 69 | } 70 | break; 71 | 72 | case IDC_RX_SIGGRAB_OVR: 73 | if (tmp_siggrab_configured) { 74 | tmp_ovrflags_configured ^= OVR_SUBJ_SIGNALS; 75 | RefreshWndElements(); 76 | } 77 | break; 78 | 79 | 80 | case IDC_RX_SIGGRAB_OK: { 81 | rtl->cfg->grab_mode = (tmp_siggrab_configured ? GRAB_ALL_DEVICES : GRAB_DISABLED); 82 | strcpy_s(rtl->cfg->output_path_sigdmp, sizeof(rtl->cfg->output_path_sigdmp), tmp_siggrab_path); 83 | rtl->cfg->overwrite_modes = tmp_ovrflags_configured; 84 | EndDialog(hDlg, TRUE); 85 | break; 86 | } 87 | 88 | case IDC_RX_SIGGRAB_CANCEL: 89 | EndDialog(hDlg, FALSE); 90 | break; 91 | 92 | default: 93 | return FALSE; 94 | } 95 | 96 | return TRUE; 97 | } 98 | 99 | static VOID onInit(HWND hwndDlg) { 100 | hDlg = hwndDlg; 101 | HICON hIcon = LoadIcon(GetModuleHandle(0), (const char *)IDI_ICON1); 102 | SendMessage(hDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcon); 103 | SendMessage(hDlg, WM_SETICON, ICON_SMALL, (LPARAM)hIcon); 104 | 105 | hPathLbl = GetDlgItem(hDlg, IDC_RX_SIGGRAB_PATH_LBL); 106 | hPathDsp = GetDlgItem(hDlg, IDC_RX_SIGGRAB_PATH); 107 | hPathBtnSet = GetDlgItem(hDlg, IDC_RX_SIGGRAB_PATH_BWS); 108 | hPathBtnCls = GetDlgItem(hDlg, IDC_RX_SIGGRAB_PATH_CLEAR); 109 | hOutOverwrite = GetDlgItem(hDlg, IDC_RX_STRGRAB_OVR); 110 | EnableWindow(hOutOverwrite, tmp_siggrab_configured); 111 | 112 | RefreshWndElements(); 113 | } 114 | 115 | static INT_PTR CALLBACK DialogHandler(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { 116 | switch (uMsg) { 117 | 118 | case WM_COMMAND: 119 | onCommand(wParam, lParam); 120 | break; 121 | 122 | case WM_INITDIALOG: 123 | onInit(hwndDlg); 124 | break; 125 | 126 | case WM_CLOSE: 127 | EndDialog(hDlg, FALSE); 128 | break; 129 | 130 | default: 131 | return false; 132 | } 133 | return true; 134 | } 135 | 136 | int ShowSignalGrabberDialog(rtl_433_t *rtl_obj, HWND hParent) { 137 | int r = -1; 138 | if (rtl_obj) { 139 | rtl = rtl_obj; 140 | tmp_siggrab_configured = (rtl->cfg->grab_mode != GRAB_DISABLED); 141 | strcpy_s(tmp_siggrab_path, sizeof(tmp_siggrab_path), rtl->cfg->output_path_sigdmp); 142 | tmp_ovrflags_configured = rtl->cfg->overwrite_modes; 143 | r = (int) DialogBox(GetModuleHandle(0), MAKEINTRESOURCE(IDD_RX_SIGGRAB), hParent, (DLGPROC)DialogHandler); 144 | } 145 | return r; 146 | } 147 | -------------------------------------------------------------------------------- /src/wnd_rxopt_strgrab.cpp: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * Sub-dialog to configure dumping of sample stream * 3 | * * 4 | * coded in 2018/19 by winterrace (github.com/winterrace) * 5 | * (github.com/winterrace2) * 6 | * * 7 | * If the dialog is cancelled, no changes are made * 8 | * * 9 | * This program is free software; you can redistribute it and/or * 10 | * modify it under the terms of the GNU General Public License as * 11 | * published by the Free Software Foundation; either version 2 of * 12 | * the License, or (at your option) any later version. * 13 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 14 | 15 | #include 16 | #include 17 | 18 | #include "librtl_433.h" 19 | #include "wnd_rxopt_siggrab.h" 20 | 21 | #include "../res/gui_win_resources.h" 22 | 23 | static rtl_433_t *rtl = NULL; 24 | 25 | static char tmp_strgrab_file[MAX_PATHLEN]; // file or "-" for working stdout 26 | static BOOL tmp_strgrab_configured; 27 | static unsigned char tmp_ovrflags_configured; 28 | 29 | static HWND hDlg, hFileLbl, hFileDsp, hFileBtnSet, hFileBtnSout, hOutOverwrite, hOkBtn; 30 | 31 | static void RefreshWndElements() { 32 | SetDlgItemText(hDlg, IDC_RX_STRGRAB_FILE, (tmp_strgrab_file[0]=='-' ? "" : tmp_strgrab_file)); 33 | CheckDlgButton(hDlg, IDC_RX_STRGRAB_CHK, (tmp_strgrab_configured ? BST_CHECKED : BST_UNCHECKED)); 34 | CheckDlgButton(hDlg, IDC_RX_STRGRAB_STDOUT, (tmp_strgrab_file[0] == '-' ? BST_CHECKED : BST_UNCHECKED)); 35 | CheckDlgButton(hDlg, IDC_RX_STRGRAB_OVR, (tmp_ovrflags_configured & OVR_SUBJ_SAMPLES ? BST_CHECKED : BST_UNCHECKED)); 36 | EnableWindow(hFileLbl, tmp_strgrab_configured); 37 | EnableWindow(hFileDsp, tmp_strgrab_configured); 38 | EnableWindow(hFileBtnSet, tmp_strgrab_configured); 39 | EnableWindow(hFileBtnSout, tmp_strgrab_configured); 40 | EnableWindow(hOutOverwrite, tmp_strgrab_configured); 41 | EnableWindow(hOkBtn, !tmp_strgrab_configured || tmp_strgrab_file[0]); 42 | } 43 | 44 | static BOOL GetSaveFilePath(LPSTR buf, INT cap, LPSTR filter, LPSTR title, LPSTR defext) { 45 | char fpath[MAX_PATH] = ""; 46 | OPENFILENAME ofntemp = { sizeof(OPENFILENAME), hDlg, 0, filter, 0, 0, 0, fpath, sizeof(fpath), 0,0,0, title, OFN_EXPLORER | OFN_OVERWRITEPROMPT | OFN_READONLY | OFN_HIDEREADONLY, 0, 0, defext, 0, 0, 0 }; 47 | if (!GetSaveFileName(&ofntemp)) return FALSE; 48 | strcpy_s(buf, cap, fpath); 49 | return TRUE; 50 | } 51 | 52 | static BOOL onCommand(WPARAM wParam, LPARAM lParam) { 53 | switch (LOWORD(wParam)) { 54 | 55 | case IDC_RX_STRGRAB_CHK: 56 | tmp_strgrab_configured = !tmp_strgrab_configured; 57 | RefreshWndElements(); 58 | break; 59 | 60 | case IDC_RX_STRGRAB_FILE_BWS: 61 | if (tmp_strgrab_configured) { 62 | if (GetSaveFilePath(tmp_strgrab_file, sizeof(tmp_strgrab_file), "Dump files (*.dump)\0*.dump\0\0", "Select target sample file:", "dump")) { 63 | RefreshWndElements(); 64 | } 65 | } 66 | break; 67 | 68 | case IDC_RX_STRGRAB_STDOUT: 69 | if (tmp_strgrab_configured) { 70 | if (tmp_strgrab_file[0] != '-') { 71 | strcpy_s(tmp_strgrab_file, sizeof(tmp_strgrab_file), "-"); 72 | } 73 | else { 74 | tmp_strgrab_file[0] = 0; 75 | } 76 | RefreshWndElements(); 77 | } 78 | break; 79 | 80 | case IDC_RX_STRGRAB_OVR: 81 | if (tmp_strgrab_configured) { 82 | tmp_ovrflags_configured ^= OVR_SUBJ_SAMPLES; 83 | RefreshWndElements(); 84 | } 85 | break; 86 | 87 | 88 | case IDC_RX_STRGRAB_OK: { 89 | strcpy_s(rtl->cfg->out_filename, sizeof(rtl->cfg->out_filename), (tmp_strgrab_configured ? tmp_strgrab_file : "")); 90 | rtl->cfg->overwrite_modes = tmp_ovrflags_configured; 91 | EndDialog(hDlg, TRUE); 92 | break; 93 | } 94 | 95 | case IDC_RX_STRGRAB_CANCEL: 96 | EndDialog(hDlg, FALSE); 97 | break; 98 | 99 | default: 100 | return FALSE; 101 | } 102 | return TRUE; 103 | } 104 | 105 | static VOID onInit(HWND hwndDlg) { 106 | hDlg = hwndDlg; 107 | HICON hIcon = LoadIcon(GetModuleHandle(0), (const char *)IDI_ICON1); 108 | SendMessage(hDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcon); 109 | SendMessage(hDlg, WM_SETICON, ICON_SMALL, (LPARAM)hIcon); 110 | 111 | hFileLbl = GetDlgItem(hDlg, IDC_RX_STRGRAB_FILE_LBL); 112 | hFileDsp = GetDlgItem(hDlg, IDC_RX_STRGRAB_FILE); 113 | hFileBtnSet = GetDlgItem(hDlg, IDC_RX_STRGRAB_FILE_BWS); 114 | hFileBtnSout = GetDlgItem(hDlg, IDC_RX_STRGRAB_STDOUT); 115 | hOutOverwrite = GetDlgItem(hDlg, IDC_RX_STRGRAB_OVR); 116 | hOkBtn = GetDlgItem(hDlg, IDC_RX_STRGRAB_OK); 117 | 118 | RefreshWndElements(); 119 | } 120 | 121 | static INT_PTR CALLBACK DialogHandler(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { 122 | switch (uMsg) { 123 | 124 | case WM_COMMAND: 125 | onCommand(wParam, lParam); 126 | break; 127 | 128 | case WM_INITDIALOG: 129 | onInit(hwndDlg); 130 | break; 131 | 132 | case WM_CLOSE: 133 | EndDialog(hDlg, FALSE); 134 | break; 135 | 136 | default: 137 | return false; 138 | } 139 | return true; 140 | } 141 | 142 | int ShowStreamGrabberDialog(rtl_433_t *rtl_obj, HWND hParent) { 143 | int r = -1; 144 | if (rtl_obj) { 145 | rtl = rtl_obj; 146 | tmp_strgrab_configured = (rtl->cfg->out_filename[0] != 0); 147 | strcpy_s(tmp_strgrab_file, sizeof(tmp_strgrab_file), rtl->cfg->out_filename); 148 | tmp_ovrflags_configured = rtl->cfg->overwrite_modes; 149 | r = (int)DialogBox(GetModuleHandle(0), MAKEINTRESOURCE(IDD_RX_STRGRAB), hParent, (DLGPROC)DialogHandler); 150 | } 151 | return r; 152 | } 153 | -------------------------------------------------------------------------------- /src/wnd_textreader.cpp: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * Sub-dialog to let the user enter some text * 3 | * * 4 | * coded in 2018/19 by winterrace (github.com/winterrace) * 5 | * (github.com/winterrace2) * 6 | * * 7 | * If the user entered some text, the dialog returns a pointer * 8 | * If the user cancelled, a NULL pointer is returned * 9 | * * 10 | * The calling code has to ensure an instant evaluatation or copy * 11 | * the resulting string before the next call to this dialog since * 12 | * it uses a local buffer which can be changed or re-allocated * 13 | * during the next call of this dialog * 14 | * * 15 | * This program is free software; you can redistribute it and/or * 16 | * modify it under the terms of the GNU General Public License as * 17 | * published by the Free Software Foundation; either version 2 of * 18 | * the License, or (at your option) any later version. * 19 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 20 | 21 | #include 22 | #include 23 | 24 | #include "wnd_textreader.h" 25 | 26 | #include "../res/gui_win_resources.h" 27 | 28 | static HWND hDlg; 29 | static char *buf_ptr = NULL; 30 | static DWORD buf_cap = 0; 31 | static LPSTR wnd_caption = NULL; 32 | 33 | static INT_PTR CALLBACK EditDialogHandler(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { 34 | switch (uMsg) { 35 | 36 | case WM_COMMAND: 37 | switch (LOWORD(wParam)) { 38 | 39 | case IDC_TEXTREADER_OK: { 40 | GetDlgItemText(hDlg, IDC_TEXTREADER_EDIT, buf_ptr, buf_cap - 1); 41 | EndDialog(hDlg, TRUE); 42 | break; 43 | } 44 | 45 | case IDC_TEXTREADER_CANCEL: 46 | EndDialog(hDlg, TRUE); 47 | break; 48 | } 49 | break; 50 | 51 | case WM_INITDIALOG: { 52 | hDlg = hwndDlg; 53 | HICON hIcon = LoadIcon(GetModuleHandle(0), (const char *)IDI_ICON1); 54 | SendMessage(hDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcon); 55 | SendMessage(hDlg, WM_SETICON, ICON_SMALL, (LPARAM)hIcon); 56 | if (wnd_caption) SetWindowText(hDlg, wnd_caption); 57 | SetDlgItemText(hDlg, IDC_TEXTREADER_EDIT, buf_ptr); 58 | break; 59 | } 60 | 61 | case WM_CLOSE: 62 | EndDialog(hDlg, TRUE); 63 | break; 64 | 65 | default: 66 | return FALSE; 67 | } 68 | return TRUE; 69 | } 70 | 71 | LPSTR ShowTextReaderDialog(HWND hParent, LPSTR caption, LPSTR preset, DWORD maxbuf) { 72 | if (!buf_ptr || buf_cap < maxbuf) { 73 | buf_ptr = (char*) realloc(buf_ptr, maxbuf); 74 | buf_cap = maxbuf; 75 | } 76 | LPSTR result = NULL; 77 | if (buf_ptr) { 78 | strcpy_s(buf_ptr, buf_cap, (preset ? preset : "")); 79 | wnd_caption = caption; 80 | int confirmed = (int)DialogBox(GetModuleHandle(0), MAKEINTRESOURCE(IDD_TEXTREADER), hParent, (DLGPROC)EditDialogHandler); 81 | if(confirmed) result = buf_ptr; 82 | } 83 | return result; 84 | } 85 | -------------------------------------------------------------------------------- /src/wnd_txopt_dev.cpp: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * Option sub-dialog for FL2K device selection * 3 | * * 4 | * coded in 2018/19 by winterrace (github.com/winterrace) * 5 | * (github.com/winterrace2) * 6 | * * 7 | * Basic actions performed by a call to ShowDeviceTxDialog(): * 8 | * - updates fl2k->cfg.dev_index * 9 | * If the dialog is cancelled, no changes are made * 10 | * * 11 | * This program is free software; you can redistribute it and/or * 12 | * modify it under the terms of the GNU General Public License as * 13 | * published by the Free Software Foundation; either version 2 of * 14 | * the License, or (at your option) any later version. * 15 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | #include "libfl2k_433.h" 22 | #include "osmo-fl2k.h" 23 | #include "wnd_txopt_dev.h" 24 | 25 | #include "../res/gui_win_resources.h" 26 | 27 | #define MAX_FL2K_DEVICES 10 28 | 29 | typedef struct _RtlDevState { 30 | char name[3*256]; 31 | //int crnt_ppm; 32 | } RtlDevState, *pRtlDevState; 33 | 34 | 35 | static RtlDevState devs[MAX_FL2K_DEVICES]; 36 | static int num_devs; // number of recognized devices 37 | static int crnt_dev; // Device index, starting from 1 (0, if no device is selected) 38 | 39 | static fl2k_433_t *fl2k = 0; 40 | 41 | static HWND hDlg, hComboTxDevs; 42 | 43 | static void DevInfo_Refresh() { 44 | num_devs = 0; 45 | crnt_dev = 0; 46 | 47 | uint16_t device_count = fl2k_get_device_count(); 48 | for (int a = 0; a < device_count && num_devs < MAX_FL2K_DEVICES; a++) { 49 | const char *product = fl2k_get_device_name(a); 50 | if (product && *product) { 51 | sprintf_s(devs[num_devs].name, "%s", (product ? product : "n/a")); 52 | num_devs++; 53 | } 54 | } 55 | } 56 | 57 | static void Gui_RebuildDevlist() { 58 | // Update Combo Box: 59 | char caption[40]; 60 | sprintf_s(caption, sizeof(caption), "%s%lu device%s found%s", (num_devs > 1 ? "Select from " : ""), num_devs, (num_devs != 1 ? "s" : ""), (num_devs > 0 ? ":" : ".")); 61 | SendMessage(hComboTxDevs, CB_RESETCONTENT, 0, 0); 62 | SendMessage(hComboTxDevs, CB_ADDSTRING, 0, (LPARAM)caption); 63 | for (int a = 0; a < num_devs; a++) { 64 | SendMessage(hComboTxDevs, CB_ADDSTRING, 0, (LPARAM)devs[a].name); 65 | } 66 | crnt_dev = (num_devs == 1 ? 1 : 0); 67 | SendMessage(hComboTxDevs, CB_SETCURSEL, crnt_dev, 0); // 1 device: preselect this. >1 devices: No preselection 68 | } 69 | 70 | static void RefreshDev_Fl2k() { 71 | DevInfo_Refresh(); // Refresh structure with FL2K device infos (name) 72 | Gui_RebuildDevlist(); // Refresh combo box (device list), preselect if there's exactly 1 device. 73 | } 74 | 75 | static BOOL onCommand(WPARAM wParam, LPARAM lParam) { 76 | switch (LOWORD(wParam)) { 77 | 78 | case IDC_TX_DEV_LIST: { 79 | int sel = (int)SendMessage(hComboTxDevs, CB_GETCURSEL, 0, 0); 80 | if (sel != crnt_dev && sel <= num_devs) { 81 | crnt_dev = sel; 82 | } 83 | break; 84 | } 85 | 86 | case IDC_TX_DEV_REFRESH: 87 | RefreshDev_Fl2k(); 88 | break; 89 | 90 | case IDC_TX_DEV_OK: { 91 | if (crnt_dev > 0 && crnt_dev <= num_devs) { 92 | fl2k->cfg.dev_index = crnt_dev; 93 | } 94 | else { 95 | fl2k->cfg.dev_index = 0; 96 | } 97 | 98 | EndDialog(hDlg, 1); 99 | break; 100 | } 101 | 102 | case IDC_TX_DEV_CANCEL: 103 | EndDialog(hDlg, 0); 104 | break; 105 | 106 | default: 107 | return FALSE; 108 | } 109 | return TRUE; 110 | } 111 | 112 | static VOID onInit(HWND hwndDlg) { 113 | hDlg = hwndDlg; 114 | HICON hIcon = LoadIcon(GetModuleHandle(0), (const char *)IDI_ICON1); 115 | SendMessage(hDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcon); 116 | SendMessage(hDlg, WM_SETICON, ICON_SMALL, (LPARAM)hIcon); 117 | 118 | hComboTxDevs = GetDlgItem(hDlg, IDC_TX_DEV_LIST); 119 | RefreshDev_Fl2k(); 120 | } 121 | 122 | static INT_PTR CALLBACK DialogHandler(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { 123 | switch (uMsg) { 124 | 125 | case WM_COMMAND: 126 | onCommand(wParam, lParam); 127 | break; 128 | 129 | case WM_INITDIALOG: 130 | onInit(hwndDlg); 131 | break; 132 | 133 | case WM_CLOSE: 134 | EndDialog(hDlg, 0); 135 | break; 136 | 137 | default: 138 | return false; 139 | } 140 | return true; 141 | } 142 | 143 | int ShowDeviceTxDialog(fl2k_433_t *fl2k_obj, HWND hParent, char **trgdev_name) { 144 | num_devs = 0; 145 | crnt_dev = 0; 146 | 147 | int r = -1; 148 | if (fl2k_obj) { 149 | fl2k = fl2k_obj; 150 | r = (int) DialogBox(GetModuleHandle(0), MAKEINTRESOURCE(IDD_TX_DEV), hParent, (DLGPROC)DialogHandler); 151 | if(trgdev_name) *trgdev_name = (r>0 && crnt_dev > 0 && crnt_dev <= num_devs ? devs[crnt_dev-1].name : NULL); 152 | } 153 | return r; 154 | } 155 | -------------------------------------------------------------------------------- /src/wnd_txopt_exp.cpp: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * Option sub-dialog for expert settings regarding TX * 3 | * * 4 | * coded in 2018/19 by winterrace (github.com/winterrace) * 5 | * (github.com/winterrace2) * 6 | * * 7 | * If the dialog is cancelled, no changes are made * 8 | * * 9 | * This program is free software; you can redistribute it and/or * 10 | * modify it under the terms of the GNU General Public License as * 11 | * published by the Free Software Foundation; either version 2 of * 12 | * the License, or (at your option) any later version. * 13 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 14 | 15 | #include 16 | 17 | #include "libfl2k_433.h" 18 | #include "wnd_txopt_exp.h" 19 | 20 | #include "../res/gui_win_resources.h" 21 | 22 | static fl2k_433_t *fl2k= NULL; 23 | 24 | static HWND hDlg; 25 | 26 | static int tmp_verbose; // -1 = edit control currently carries no valid value 27 | static int tmp_initime; // -1 = edit control currently carries no valid value 28 | 29 | static BOOL onCommand(WPARAM wParam, LPARAM lParam) { 30 | switch (LOWORD(wParam)) { 31 | 32 | case IDC_TX_EXP_DBGLVL_EDT: { 33 | BOOL trans = FALSE; 34 | int tmp_dlev = GetDlgItemInt(hDlg, IDC_TX_EXP_DBGLVL_EDT, &trans, FALSE); 35 | tmp_verbose = (trans ? tmp_dlev : -1); 36 | break; 37 | } 38 | 39 | case IDC_TX_EXP_INITIME_EDT: { 40 | BOOL trans = FALSE; 41 | int tmp_ini = GetDlgItemInt(hDlg, IDC_TX_EXP_INITIME_EDT, &trans, FALSE); 42 | tmp_initime = (trans ? tmp_ini : -1); 43 | break; 44 | } 45 | 46 | case IDC_TX_EXP_BTN_OK: { 47 | fl2k->cfg.verbose = (tmp_verbose >= 0 ? tmp_verbose : FL2K_433_DEFAULT_VERBOSITY); 48 | fl2k->cfg.inittime_ms = (tmp_initime >= 0 ? tmp_initime : FL2K_433_DEFAULT_INIT_TIME); 49 | EndDialog(hDlg, TRUE); 50 | break; 51 | } 52 | 53 | case IDC_TX_EXP_BTN_CANCEL: 54 | EndDialog(hDlg, TRUE); 55 | break; 56 | 57 | default: 58 | return FALSE; 59 | } 60 | return TRUE; 61 | } 62 | 63 | static VOID onInit(HWND hwndDlg) { 64 | hDlg = hwndDlg; 65 | HICON hIcon = LoadIcon(GetModuleHandle(0), (const char *)IDI_ICON1); 66 | SendMessage(hDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcon); 67 | SendMessage(hDlg, WM_SETICON, ICON_SMALL, (LPARAM)hIcon); 68 | 69 | SetDlgItemInt(hDlg, IDC_TX_EXP_DBGLVL_EDT, tmp_verbose, TRUE); 70 | SetDlgItemInt(hDlg, IDC_TX_EXP_INITIME_EDT, tmp_initime, TRUE); 71 | } 72 | 73 | static INT_PTR CALLBACK DialogHandler(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { 74 | switch (uMsg) { 75 | 76 | case WM_COMMAND: 77 | onCommand(wParam, lParam); 78 | break; 79 | 80 | case WM_INITDIALOG: 81 | onInit(hwndDlg); 82 | break; 83 | 84 | case WM_CLOSE: 85 | EndDialog(hDlg, TRUE); 86 | break; 87 | 88 | default: 89 | return false; 90 | } 91 | return true; 92 | } 93 | 94 | int ShowExpertDialog(fl2k_433_t *fl2k_obj, HWND hParent) { 95 | int r = -1; 96 | if (fl2k_obj) { 97 | fl2k = fl2k_obj; 98 | tmp_verbose = (fl2k->cfg.verbose >= 0 ? fl2k->cfg.verbose : FL2K_433_DEFAULT_VERBOSITY); 99 | tmp_initime = (fl2k->cfg.inittime_ms >= 0 ? fl2k->cfg.inittime_ms : FL2K_433_DEFAULT_INIT_TIME); 100 | r = (int) DialogBox(GetModuleHandle(0), MAKEINTRESOURCE(IDD_TX_EXPERT), hParent, (DLGPROC)DialogHandler); 101 | } 102 | return r; 103 | } 104 | -------------------------------------------------------------------------------- /src/wnd_txwarn.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winterrace2/rtl_fl2k_433/8955374f9ecd9d71ef421f9f9dcdd869d91fb6b1/src/wnd_txwarn.cpp -------------------------------------------------------------------------------- /src/wndelements.cpp: -------------------------------------------------------------------------------- 1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | * A class to manage window elements (to better handle resizing) * 3 | * * 4 | * coded in 2018/19 by winterrace (github.com/winterrace) * 5 | * (github.com/winterrace2) * 6 | * * 7 | * This program is free software; you can redistribute it and/or * 8 | * modify it under the terms of the GNU General Public License as * 9 | * published by the Free Software Foundation; either version 2 of * 10 | * the License, or (at your option) any later version. * 11 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 12 | 13 | #include 14 | #include "wndelements.h" 15 | 16 | static VOID GetChildPos(HWND hChild, HWND hParent, RECT *r) { 17 | POINT p0 = { 0,0 }; 18 | 19 | GetWindowRect(hChild, r); 20 | ClientToScreen(hParent, &p0); 21 | r->left -= p0.x; 22 | r->top -= p0.y; 23 | r->right -= p0.x; 24 | r->bottom -= p0.y; 25 | } 26 | 27 | WndElem::WndElem(DWORD i, HWND w, LPRECT r) { 28 | this->ctlid = i; 29 | this->hWnd = w; 30 | this->initrect = *r; 31 | this->next = NULL; 32 | } 33 | 34 | WndElem::~WndElem() { 35 | if (this->next) delete this->next; 36 | } 37 | 38 | VOID WndElem::add(WndElem *e) { 39 | if (this->next) this->next->add(e); 40 | else this->next = e; 41 | } 42 | 43 | WndElem *WndElem::get(DWORD cid) { 44 | if (this->ctlid == cid) { 45 | return this; 46 | } 47 | else if(this->next){ 48 | return next->get(cid); 49 | } 50 | else return NULL; 51 | } 52 | 53 | WndElems::WndElems(HWND hPar) { 54 | this->hParent = hPar; 55 | this->elems = NULL; 56 | } 57 | 58 | HWND WndElems::add(DWORD ctlid) { 59 | HWND h = GetDlgItem(this->hParent, ctlid); 60 | RECT r; 61 | GetChildPos(h, this->hParent, &r); 62 | WndElem *e = new WndElem(ctlid, h, &r); 63 | if (this->elems) this->elems->add(e); 64 | else this->elems = e; 65 | 66 | return h; 67 | } 68 | 69 | WndElem *WndElems::get(DWORD ctlid) { 70 | if (this->elems) return elems->get(ctlid); 71 | else return NULL; 72 | } 73 | 74 | WndElems::~WndElems() { 75 | if (this->elems) delete this->elems; 76 | } 77 | 78 | BOOL WndElems::show(DWORD ctlid, int nShow) { 79 | WndElem *e = this->get(ctlid); 80 | if (e) { 81 | return ShowWindow(e->hWnd, nShow); 82 | } 83 | return FALSE; 84 | } 85 | 86 | LRESULT WndElems::sendMsg(DWORD ctlid, UINT Msg, WPARAM wParam, LPARAM lParam) { 87 | WndElem *e = this->get(ctlid); 88 | if (e) { 89 | return SendMessage(e->hWnd, Msg, wParam, lParam); 90 | } 91 | return NULL; 92 | } 93 | 94 | BOOL WndElems::enable(DWORD ctlid, BOOL bEnable) { 95 | WndElem *e = this->get(ctlid); 96 | if (e) { 97 | return EnableWindow(e->hWnd, bEnable); 98 | } 99 | return NULL; 100 | } 101 | 102 | HWND WndElems::getHandle(DWORD ctlid) { 103 | WndElem *e = this->get(ctlid); 104 | if (e) return e->hWnd; 105 | else return NULL; 106 | } 107 | -------------------------------------------------------------------------------- /vs15/rtl_fl2k_433.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rtl_fl2k_433", "rtl_fl2k_433_static.vcxproj", "{7EB4B17A-2185-47A5-8170-ACDC7EA30515}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rtl_fl2k_433", "rtl_fl2k_433_dynamic.vcxproj", "{7CCCC3AE-D6C7-40DA-A9CD-30F9E66DF7DC}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|x64 = Debug|x64 13 | Release|x64 = Release|x64 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {7EB4B17A-2185-47A5-8170-ACDC7EA30515}.Debug|x64.ActiveCfg = Debug|x64 17 | {7EB4B17A-2185-47A5-8170-ACDC7EA30515}.Debug|x64.Build.0 = Debug|x64 18 | {7EB4B17A-2185-47A5-8170-ACDC7EA30515}.Release|x64.ActiveCfg = Release|x64 19 | {7EB4B17A-2185-47A5-8170-ACDC7EA30515}.Release|x64.Build.0 = Release|x64 20 | {7CCCC3AE-D6C7-40DA-A9CD-30F9E66DF7DC}.Debug|x64.ActiveCfg = Debug|x64 21 | {7CCCC3AE-D6C7-40DA-A9CD-30F9E66DF7DC}.Debug|x64.Build.0 = Debug|x64 22 | {7CCCC3AE-D6C7-40DA-A9CD-30F9E66DF7DC}.Release|x64.ActiveCfg = Release|x64 23 | {7CCCC3AE-D6C7-40DA-A9CD-30F9E66DF7DC}.Release|x64.Build.0 = Release|x64 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /vs15/rtl_fl2k_433_dynamic.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | Release 10 | x64 11 | 12 | 13 | 14 | {7CCCC3AE-D6C7-40DA-A9CD-30F9E66DF7DC} 15 | Win32Proj 16 | rtl_fl2k_433 17 | 10.0.10586.0 18 | rtl_fl2k_433 19 | 20 | 21 | 22 | Application 23 | true 24 | v140 25 | NotSet 26 | 27 | 28 | Application 29 | false 30 | v140 31 | true 32 | NotSet 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | true 48 | $(SolutionDir)tmp\dynamic\$(Platform)\$(Configuration)\ 49 | $(SolutionDir)builds\dynamic\$(Platform)\$(Configuration)\ 50 | 51 | 52 | false 53 | $(SolutionDir)tmp\dynamic\$(Platform)\$(Configuration)\ 54 | $(SolutionDir)builds\dynamic\$(Platform)\$(Configuration)\ 55 | 56 | 57 | 58 | NotUsing 59 | Level3 60 | Disabled 61 | TX_ENABLED;_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) 62 | ..\include\;..\res\;..\..\librtl_433\include\;..\..\getopt_win\getopt_win_dll\;..\..\librtlsdr\include\;..\..\libfl2k_433\include\;..\..\libosmo-fl2k\include\; 63 | 4996 64 | 65 | 66 | Windows 67 | true 68 | ..\..\x64\Debug;..\..\getopt_win\x64\Debug Dll;..\..\librtlsdr\vs15\x64\Debug\;..\..\librtl_433\vs15\builds\x64\Debug\;..\..\libfl2k_433\vs15\builds\x64\Debug;..\..\libosmo-fl2k\vs15\builds\x64\Debug\; 69 | librtl_433.lib;getoptd.lib;rtlsdr.lib;libfl2k_433.lib;osmo-fl2k.lib;ws2_32.lib;comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 70 | 71 | 72 | 73 | 74 | Level3 75 | NotUsing 76 | MaxSpeed 77 | true 78 | true 79 | TX_ENABLED;WIN32_LEAN_AND_MEAN;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) 80 | ..\include\;..\res\;..\..\librtl_433\include\;..\..\getopt_win\getopt_win_dll\;..\..\librtlsdr\include\;..\..\libfl2k_433\include\;..\..\libosmo-fl2k\include\; 81 | 82 | 83 | Windows 84 | true 85 | true 86 | true 87 | ..\..\getopt_win\x64\Release Dll;..\..\librtlsdr\vs15\x64\Release\;..\..\librtl_433\vs15\builds\x64\Release\;..\..\libfl2k_433\vs15\builds\x64\Release;..\..\libosmo-fl2k\vs15\builds\x64\Release; 88 | librtl_433.lib;getopt.lib;rtlsdr.lib;libfl2k_433.lib;osmo-fl2k.lib;ws2_32.lib;comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | -------------------------------------------------------------------------------- /vs15/rtl_fl2k_433_dynamic.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header files 20 | 21 | 22 | Resource files 23 | 24 | 25 | Header files 26 | 27 | 28 | Header files 29 | 30 | 31 | Header files 32 | 33 | 34 | Header files 35 | 36 | 37 | Header files 38 | 39 | 40 | Header files 41 | 42 | 43 | Header files 44 | 45 | 46 | Header files 47 | 48 | 49 | Header files 50 | 51 | 52 | Header files 53 | 54 | 55 | Header files 56 | 57 | 58 | Header files 59 | 60 | 61 | Header files 62 | 63 | 64 | Header files 65 | 66 | 67 | Header files 68 | 69 | 70 | Header files 71 | 72 | 73 | Header files 74 | 75 | 76 | Header files 77 | 78 | 79 | Header files 80 | 81 | 82 | Header files 83 | 84 | 85 | Header files 86 | 87 | 88 | Header files 89 | 90 | 91 | Header files 92 | 93 | 94 | Header files 95 | 96 | 97 | Header files 98 | 99 | 100 | Header files 101 | 102 | 103 | Header files 104 | 105 | 106 | Header files 107 | 108 | 109 | 110 | 111 | Source files 112 | 113 | 114 | Source files 115 | 116 | 117 | Source files 118 | 119 | 120 | Source files 121 | 122 | 123 | Source files 124 | 125 | 126 | Source files 127 | 128 | 129 | Source files 130 | 131 | 132 | Source files 133 | 134 | 135 | Source files 136 | 137 | 138 | Source files 139 | 140 | 141 | Source files 142 | 143 | 144 | Source files 145 | 146 | 147 | Source files 148 | 149 | 150 | Source files 151 | 152 | 153 | Source files 154 | 155 | 156 | Source files 157 | 158 | 159 | Source files 160 | 161 | 162 | Source files 163 | 164 | 165 | Source files 166 | 167 | 168 | Source files 169 | 170 | 171 | Source files 172 | 173 | 174 | Source files 175 | 176 | 177 | Source files 178 | 179 | 180 | Source files 181 | 182 | 183 | Source files 184 | 185 | 186 | Source files 187 | 188 | 189 | Source files 190 | 191 | 192 | Source files 193 | 194 | 195 | Source files 196 | 197 | 198 | Source files 199 | 200 | 201 | 202 | 203 | Resource files 204 | 205 | 206 | 207 | 208 | Resource files 209 | 210 | 211 | -------------------------------------------------------------------------------- /vs15/rtl_fl2k_433_static.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | Release 10 | x64 11 | 12 | 13 | 14 | {7EB4B17A-2185-47A5-8170-ACDC7EA30515} 15 | Win32Proj 16 | rtl_fl2k_433 17 | 10.0.10586.0 18 | rtl_fl2k_433 19 | 20 | 21 | 22 | Application 23 | true 24 | v140 25 | NotSet 26 | 27 | 28 | Application 29 | false 30 | v140 31 | true 32 | NotSet 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | true 48 | $(SolutionDir)tmp\static\$(Platform)\$(Configuration)\ 49 | $(SolutionDir)builds\static\$(Platform)\$(Configuration)\ 50 | 51 | 52 | false 53 | $(SolutionDir)tmp\static\$(Platform)\$(Configuration)\ 54 | $(SolutionDir)builds\static\$(Platform)\$(Configuration)\ 55 | 56 | 57 | 58 | NotUsing 59 | Level3 60 | Disabled 61 | TX_ENABLED;rtlsdr_STATIC;librtl_433_STATIC;libfl2k_433_STATIC;libosmofl2k_STATIC;_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) 62 | ..\include\;..\res\;..\..\librtl_433\include\;..\..\getopt_win\getopt_win_dll\;..\..\librtlsdr\include\;..\..\libfl2k_433\include\;..\..\libosmo-fl2k\include\; 63 | 4996 64 | 65 | 66 | Windows 67 | true 68 | ..\..\x64\Debug;..\..\getopt_win\x64\Debug Dll;..\..\librtlsdr\vs15\x64\Debug\;..\..\librtl_433\vs15\builds\x64\Debug\;..\..\libfl2k_433\vs15\builds\x64\Debug;..\..\libosmo-fl2k\vs15\builds\x64\Debug\;..\..\libusb\x64\Debug\dll;..\..\pthread\lib\x64; 69 | libusb-1.0.lib;pthreadVC2.lib;librtl_433_static.lib;getoptd.lib;rtlsdr_static.lib;libfl2k_433_static.lib;osmo-fl2k_static.lib;ws2_32.lib;comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 70 | 71 | 72 | 73 | 74 | Level3 75 | NotUsing 76 | MaxSpeed 77 | true 78 | true 79 | TX_ENABLED;rtlsdr_STATIC;librtl_433_STATIC;libfl2k_433_STATIC;libosmofl2k_STATIC;WIN32_LEAN_AND_MEAN;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) 80 | ..\include\;..\res\;..\..\librtl_433\include\;..\..\getopt_win\getopt_win_dll\;..\..\librtlsdr\include\;..\..\libfl2k_433\include\;..\..\libosmo-fl2k\include\; 81 | 82 | 83 | Windows 84 | true 85 | true 86 | true 87 | ..\..\getopt_win\x64\Release Dll;..\..\librtlsdr\vs15\x64\Release\;..\..\librtl_433\vs15\builds\x64\Release\;..\..\libfl2k_433\vs15\builds\x64\Release;..\..\libosmo-fl2k\vs15\builds\x64\Release;..\..\libusb\x64\Release\dll;..\..\pthread\lib\x64; 88 | libusb-1.0.lib;pthreadVC2.lib;librtl_433_static.lib;getopt.lib;rtlsdr_static.lib;libfl2k_433_static.lib;osmo-fl2k_static.lib;ws2_32.lib;comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | -------------------------------------------------------------------------------- /vs15/rtl_fl2k_433_static.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header files 20 | 21 | 22 | Resource files 23 | 24 | 25 | Header files 26 | 27 | 28 | Header files 29 | 30 | 31 | Header files 32 | 33 | 34 | Header files 35 | 36 | 37 | Header files 38 | 39 | 40 | Header files 41 | 42 | 43 | Header files 44 | 45 | 46 | Header files 47 | 48 | 49 | Header files 50 | 51 | 52 | Header files 53 | 54 | 55 | Header files 56 | 57 | 58 | Header files 59 | 60 | 61 | Header files 62 | 63 | 64 | Header files 65 | 66 | 67 | Header files 68 | 69 | 70 | Header files 71 | 72 | 73 | Header files 74 | 75 | 76 | Header files 77 | 78 | 79 | Header files 80 | 81 | 82 | Header files 83 | 84 | 85 | Header files 86 | 87 | 88 | Header files 89 | 90 | 91 | Header files 92 | 93 | 94 | Header files 95 | 96 | 97 | Header files 98 | 99 | 100 | Header files 101 | 102 | 103 | Header files 104 | 105 | 106 | Header files 107 | 108 | 109 | 110 | 111 | Source files 112 | 113 | 114 | Source files 115 | 116 | 117 | Source files 118 | 119 | 120 | Source files 121 | 122 | 123 | Source files 124 | 125 | 126 | Source files 127 | 128 | 129 | Source files 130 | 131 | 132 | Source files 133 | 134 | 135 | Source files 136 | 137 | 138 | Source files 139 | 140 | 141 | Source files 142 | 143 | 144 | Source files 145 | 146 | 147 | Source files 148 | 149 | 150 | Source files 151 | 152 | 153 | Source files 154 | 155 | 156 | Source files 157 | 158 | 159 | Source files 160 | 161 | 162 | Source files 163 | 164 | 165 | Source files 166 | 167 | 168 | Source files 169 | 170 | 171 | Source files 172 | 173 | 174 | Source files 175 | 176 | 177 | Source files 178 | 179 | 180 | Source files 181 | 182 | 183 | Source files 184 | 185 | 186 | Source files 187 | 188 | 189 | Source files 190 | 191 | 192 | Source files 193 | 194 | 195 | Source files 196 | 197 | 198 | Source files 199 | 200 | 201 | 202 | 203 | Resource files 204 | 205 | 206 | 207 | 208 | Resource files 209 | 210 | 211 | --------------------------------------------------------------------------------