diff --git a/.vscode/.server-controller-port.log b/.vscode/.server-controller-port.log index 273ba2c..556b036 100644 --- a/.vscode/.server-controller-port.log +++ b/.vscode/.server-controller-port.log @@ -1,5 +1,5 @@ { "port": 13452, - "time": 1728395259887, + "time": 1741628226423, "version": "0.0.3" } \ No newline at end of file diff --git a/README.md b/README.md deleted file mode 100644 index ee8ca42..0000000 --- a/README.md +++ /dev/null @@ -1,125 +0,0 @@ -# MiniRDS - -This program is designed for generating a realtime RDS signal. It is capable of RDS2 using up to 3 additional subcarriers. - -This is based on the RDS encoder from [Mpxgen](https://github.com/Anthony96922/mpxgen), which is currently not maintained. - -Note that some missing groups were added from [librds](https://flerken.zapto.org:1115/kuba/librds), [my](https://flerken.zapto.org:1115/kuba) other project - -#### Features -- Low resource requirements -- Support for basic RDS data fields: PS, RT, PTY and AF -- RDS items can be updated through control pipe -- RT+ support -- RDS2 support (including station logo transmission) - -#### To do -- Threading - -#### Planned features -- UECP -- Configuration file - -## What are the changes from normal MiniRDS? -- CMake -- better arguments -- Option to disable ODA -- Better Group Sequence (original had 0A 2A but here it is 0A 0A 0A 0A 2A 2A 2A 2A (2A) so PS appear instantly and RT is fast) -- Added LIC and PIN -- Most commands are compatible with the ASCII format that pira.cz uses -- Custom groups (use `G=BBBBCCCCDDDD` or `CG AAAA BBBB CCCC DDDD`) -- Mono! mono? Mono! Not stereo! why? because the 2 channels were exactly the same in the first place so there was no point in having a 2nd one - -## Build -For Debian-like distros: `sudo apt-get install libao-dev libsamplerate0-dev` to install deps. - -Note that MiniRDS requires CMake to compile (install with `sudo apt install cmake`) - -Once those are installed, run -```sh -git clone https://flerken.zapto.org:1115/kuba/minirds -cd minirds/src -mkdir build -cd build -cmake .. -make -sudo make install -``` - -## How to use -Simply run: -``` -minirds -``` -to confirm proper operation. - -Please see `-h` for more options. - -### Stereo Tool integration -The following setup allows MiniRDS to be used alongside Stereo Tool audio processor. -``` -.-------------. -| Stereo Tool |--(FM MPX w/o RDS)-----. -'-------------' | - v - .-----------------------. - | ALSA dmixer | - | slave: MPX sound card |--------(to sound card)--------> - | 192 kHz | - '-----------------------' - ^ -.---------. | -| MiniRDS |--(RDS output)-------------' -'---------' -``` - -First, add the following contents to ~/.asoundrc: -``` -# ST MPX output -pcm.mpxmix { - type dmix - ipc_key 1001 - slave { - pcm "digital-out" # change to your actual sound card - rate 192000 - } -} -``` - -Next, add the collowing contents to ~/.ao: -``` -dev=mpxmix -``` - -Then set the Stereo Tool MPX output to use the ALSA "mpxmix" output. Finally run minirds. *Adjust volumes accordingly.* - -Note that this setup is not optimal. Hans plans to add RDS2 passthough to the ST external RDS input. [Stereo Tool forum post](https://forums.stereotool.com/viewtopic.php?f=14&t=33793&start=150) - -If you need to you also can run MiniRDS on a ST transmitter modulated as mono audio, which does work however on some TXs the RDS signal may not be great due to harmonics of ST Pilot Tone - -### Changing PS, RT, TA and PTY at run-time -You can control PS, RT, TA (Traffic Announcement flag), PTY (Program Type) and many other items at run-time using a named pipe (FIFO). For this run MiniRDS with the `--ctl` argument. - -Scripts can be written to obtain and send "now playing" text data to MiniRDS for dynamic RDS. - -See the [command list](doc/command_list.md) for a complete list of valid commands. - -### RDS2 -MiniRDS has a working implementation of the RFT protocol in RDS2. Please edit the Makefile accordingly and rebuild for RDS2 capabilities. You may use your own image by using the provided "make-station-logo.sh" script. Valid formats are PNG or JPG and should be about 3kB or less. Larger images take considerably longer to receive. - -## References -- [EN 50067, Specification of the radio data system (RDS) for VHF/FM sound broadcasting in the frequency range 87.5 to 108.0 MHz](http://www.interactive-radio-system.com/docs/EN50067_RDS_Standard.pdf) -- [IEC 62106-2, Radio data system (RDS) – Part 2: Message format: coding and definitions of RDS features](http://downloads.dxing.si/download.php?file=ISO%20Stamdards/RDS/latest%20(includes%20RDS2)/iec-62106-2-2021.pdf) -- [IEC 62106-3, Radio data system (RDS) – Part 3: Usage and registration of Open Data Applications (ODAs)](http://downloads.dxing.si/download.php?file=ISO%20Stamdards/RDS/latest%20(includes%20RDS2)/iec-62106-3-2018.pdf) -- [IEC 62106-4, Radio data system (RDS) – Part 4: Registered code tables](http://downloads.dxing.si/download.php?file=ISO%20Stamdards/RDS/latest%20(includes%20RDS2)/iec-62106-4-2018.pdf) -- [IEC 62106-6, Radio data system (RDS) – Part 6: Compilation of technical specifications for Open Data Applications in the -public domain](http://downloads.dxing.si/download.php?file=ISO%20Stamdards/RDS/latest%20(includes%20RDS2)/iec-62106-6-2018.pdf) -- [P232 RDS Encoder -Technical Manual](https://pira.cz/rds/p232man.pdf) -- [PIRA32 RDS Encoder -Technical Manual](https://pira.cz/rds/manual.pdf) - -## Credits -Note that this is a fork of [Anthony96922](https://github.com/Anthony96922)'s [MiniRDS](https://github.com/Anthony96922/MiniRDS) - -The RDS waveform generator was adapted from [PiFmRds](https://github.com/ChristopheJacquet/PiFmRds) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 97383c1..910e295 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -8,14 +8,8 @@ project(minirds VERSION 1.0) # Define options option(ODA_RTP "Enable ODA (RT+)" ON) -option(RDS2 "Enable RDS2 capabilities" OFF) -option(RDS2_QUADRATURE_CARRIER "Shift RDS2 stream carriers by 90, 180, and 270 degrees" ON) -option(RDS2_SYMBOL_SHIFTING "Enable RDS2 symbol shifting" ON) -option(RDS2_DEBUG "Enable RDS2 debugging" OFF) - option(STATIC_LIBSAMPLERATE "Use a static libsamplerate library (.a)" OFF) - set(LIBSAMPLERATE_DIR "./libsamplerate" CACHE STRING "Directory for static libsamplerate") # Set compiler and flags @@ -28,22 +22,6 @@ set(SOURCES rds.c ) -# Handle RDS2 options -if(RDS2) - add_definitions(-DRDS2) - set(SOURCES ${SOURCES} rds2.c) - if(RDS2_QUADRATURE_CARRIER) - add_definitions(-DRDS2_QUADRATURE_CARRIER) - endif() - if(RDS2_SYMBOL_SHIFTING) - add_definitions(-DRDS2_SYMBOL_SHIFTING) - endif() -endif() - -if(RDS2_DEBUG) - add_definitions(-DRDS2_DEBUG) -endif() - if(ODA_RTP) add_definitions(-DODA) add_definitions(-DODA_RTP) diff --git a/src/ascii_cmd.c b/src/ascii_cmd.c index 8813d34..11da238 100644 --- a/src/ascii_cmd.c +++ b/src/ascii_cmd.c @@ -56,18 +56,6 @@ void process_ascii_cmd(unsigned char *str) { arg = str + 4; if (CMD_MATCHES("MPX")) { -#ifdef RDS2 - float gains[5]; - if (sscanf((char *)arg, "%f,%f,%f,%f,%f", - &gains[0], &gains[1], &gains[2], &gains[3], - &gains[4]) == 5) { - set_carrier_volume(0, gains[0]); - set_carrier_volume(1, gains[1]); - set_carrier_volume(2, gains[2]); - set_carrier_volume(3, gains[3]); - set_carrier_volume(4, gains[4]); - } -#else float gains[2]; if (sscanf((char *)arg, "%f,%f", &gains[0], &gains[1]) == 2) @@ -75,7 +63,6 @@ void process_ascii_cmd(unsigned char *str) { set_carrier_volume(0, gains[0]); set_carrier_volume(1, gains[1]); } -#endif return; } if (CMD_MATCHES("VOL")) { @@ -297,10 +284,7 @@ void process_ascii_cmd(unsigned char *str) { arg = str + 2; if (CMD_MATCHES("G")) { uint16_t blocks[4]; - if(cmd_len == 18){ - /* RDS2 Group*/ - /* do a ifdef rds2 here when implementing*/ - } else if(cmd_len == 14) { + if(cmd_len == 14) { /* RDS1 Group*/ blocks[0] = get_rds_pi(); int count = sscanf((char *)arg, "%4hx%4hx%4hx", &blocks[1], &blocks[2], &blocks[3]); @@ -336,12 +320,7 @@ void process_ascii_cmd(unsigned char *str) { uint8_t val = strtoul((char *)arg, NULL, 10); val /= 255; val *= 15; /* max value*/ - #ifdef RDS2 set_carrier_volume(1, val); - set_carrier_volume(2, val); - #else - set_carrier_volume(1, val); - #endif return; } } @@ -378,12 +357,7 @@ void process_ascii_cmd(unsigned char *str) { uint8_t val = strtoul((char *)arg, NULL, 10); val /= 255; val *= 15; /* max value*/ - #ifdef RDS2 set_carrier_volume(1, val); - set_carrier_volume(2, val); - #else - set_carrier_volume(1, val); - #endif return; } diff --git a/src/fm_mpx.c b/src/fm_mpx.c index 9395efb..011c720 100644 --- a/src/fm_mpx.c +++ b/src/fm_mpx.c @@ -19,24 +19,9 @@ #include "common.h" #include "rds.h" -#ifdef RDS2 -#include "rds2.h" -#endif #include "fm_mpx.h" #include "osc.h" -/* - * Local oscillator objects - * this is where the MPX waveforms are stored - * - */ -static struct osc_t osc_57k; -#ifdef RDS2 -static struct osc_t osc_67k; -static struct osc_t osc_71k; -static struct osc_t osc_76k; -#endif - static float mpx_vol; static uint8_t rdsgen; @@ -47,46 +32,19 @@ void set_output_volume(float vol) { } void set_rdsgen(uint8_t gen) { - #ifdef RDS2 - if (gen > 2) gen = 2; - #else if (gen > 1) gen = 1; - #endif rdsgen = gen; } -/* subcarrier volumes */ -static float volumes[MPX_SUBCARRIER_END] = { - 0.0f, /* pilot tone: 0% */ - 1.0f, /* RDS: 7.5% modulation */ -#ifdef RDS2 - /* RDS2 */ - 0.05f, //66.5 khz 5% - 0.05f, //71.25 khz 5% - 0.0f //76 khz 0% -#endif -}; - void set_carrier_volume(uint8_t carrier, float new_volume) { /* check for valid index */ if (carrier >= MPX_SUBCARRIER_END) return; - /* don't allow levels over 15% */ - if (new_volume >= 15.0f) new_volume = 15.0f; - volumes[carrier] = new_volume / 100.0f; } void fm_mpx_init(uint32_t sample_rate) { - /* initialize the subcarrier oscillators */ - osc_init(&osc_57k, sample_rate, 57000.0f); rdsgen = 1; -#ifdef RDS2 - osc_init(&osc_67k, sample_rate, 66500.0f); - osc_init(&osc_71k, sample_rate, 71250.0f); - osc_init(&osc_76k, sample_rate, 76000.0f); - rdsgen = 2; -#endif } void fm_rds_get_frames(float *outbuf, size_t num_frames) { @@ -96,68 +54,10 @@ void fm_rds_get_frames(float *outbuf, size_t num_frames) { for (size_t i = 0; i < num_frames; i++) { out = 0.0f; - #ifdef RDS2 - out += osc_get_cos(&osc_57k) - * get_rds_sample(0, 0) - * volumes[MPX_SUBCARRIER_RDS_STREAM_0]; - #else out += get_rds_sample(0) * volumes[MPX_SUBCARRIER_RDS_STREAM_0]; - #endif -#ifdef RDS2 -#ifdef RDS2_QUADRATURE_CARRIER - /* RDS2 is quadrature phase */ - /* 90 degree shift */ - if(rdsgen == 2 && volumes[MPX_SUBCARRIER_RDS2_STREAM_1] != 0) { - out += osc_get_sin(&osc_67k) - * get_rds_sample(1, 0) - * volumes[MPX_SUBCARRIER_RDS2_STREAM_1]; - } - - /* 180 degree shift */ - if(rdsgen == 2 && volumes[MPX_SUBCARRIER_RDS2_STREAM_2] != 0) { - out += -osc_get_cos(&osc_71k) - * get_rds_sample(2, 0) - * volumes[MPX_SUBCARRIER_RDS2_STREAM_2]; - } - - /* 270 degree shift */ - if(rdsgen == 2 && volumes[MPX_SUBCARRIER_RDS2_STREAM_3] != 0) { - out += -osc_get_sin(&osc_76k) - * get_rds_sample(3, 0) - * volumes[MPX_SUBCARRIER_RDS2_STREAM_3]; - } -#else - if(rdsgen == 2 && volumes[MPX_SUBCARRIER_RDS2_STREAM_1] != 0) { - out += osc_get_cos(&osc_67k) - * get_rds_sample(1, 0) - * volumes[MPX_SUBCARRIER_RDS2_STREAM_1]; - } - - if(rdsgen == 2 && volumes[MPX_SUBCARRIER_RDS2_STREAM_1] != 0) { - out += osc_get_cos(&osc_71k) - * get_rds_sample(2, 0) - * volumes[MPX_SUBCARRIER_RDS2_STREAM_2]; - } - - if(rdsgen == 2 && volumes[MPX_SUBCARRIER_RDS2_STREAM_3] != 0) { - out += osc_get_cos(&osc_76k) - * get_rds_sample(3, 0) - * volumes[MPX_SUBCARRIER_RDS2_STREAM_3]; - } -#endif -#endif - - /* update oscillator */ - osc_update_pos(&osc_57k); -#ifdef RDS2 - osc_update_pos(&osc_67k); - osc_update_pos(&osc_71k); - osc_update_pos(&osc_76k); -#endif - - /* declipper */ + /* clipper */ out = fminf(+1.0f, out); out = fmaxf(-1.0f, out); @@ -169,10 +69,5 @@ void fm_rds_get_frames(float *outbuf, size_t num_frames) { } void fm_mpx_exit() { - osc_exit(&osc_57k); -#ifdef RDS2 - osc_exit(&osc_67k); - osc_exit(&osc_71k); - osc_exit(&osc_76k); -#endif + return; } diff --git a/src/fm_mpx.h b/src/fm_mpx.h index 2b6225c..7f53ec6 100644 --- a/src/fm_mpx.h +++ b/src/fm_mpx.h @@ -26,17 +26,6 @@ #define OUTPUT_SAMPLE_RATE 192000 -enum mpx_subcarriers { - MPX_SUBCARRIER_ST_PILOT, - MPX_SUBCARRIER_RDS_STREAM_0, -#ifdef RDS2 - MPX_SUBCARRIER_RDS2_STREAM_1, - MPX_SUBCARRIER_RDS2_STREAM_2, - MPX_SUBCARRIER_RDS2_STREAM_3, -#endif - MPX_SUBCARRIER_END -}; - extern void fm_mpx_init(uint32_t sample_rate); extern void fm_rds_get_frames(float *outbuf, size_t num_frames); extern void fm_mpx_exit(); diff --git a/src/lib.c b/src/lib.c index d50722e..966af57 100644 --- a/src/lib.c +++ b/src/lib.c @@ -21,7 +21,7 @@ #include /* - * Stuff common for both RDS and RDS2 + * Stuff for RDS * */ @@ -175,44 +175,16 @@ uint16_t crc16(uint8_t *data, size_t len) { } /* Calculate the checkword for each block and emit the bits */ -#ifdef RDS2 -void add_checkwords(uint16_t *blocks, uint8_t *bits, bool rds2) -#else void add_checkwords(uint16_t *blocks, uint8_t *bits) -#endif { size_t i, j; uint8_t bit, msb; uint16_t block, block_crc, check, offset_word; bool group_type_b = false; -#ifdef RDS2 - bool tunneling_type_b = false; -#endif - - /* if b11 is 1, then type B */ -#ifdef RDS2 - if (!rds2 && IS_TYPE_B(blocks)) -#else if (IS_TYPE_B(blocks)) -#endif group_type_b = true; -#ifdef RDS2 - /* for when version B groups are coded in RDS2 */ - if (rds2 && IS_TUNNELING(blocks) && IS_TYPE_B(blocks)) - tunneling_type_b = true; -#endif - for (i = 0; i < GROUP_LENGTH; i++) { -#ifdef RDS2 - /* - * If tunneling type B groups use offset - * word C' for block 3 - */ - if (rds2 && i == 2 && tunneling_type_b) { - offset_word = offset_words[4]; - } else -#endif /* Group version B needs C' for block 3 */ if (i == 2 && group_type_b) { offset_word = offset_words[4]; diff --git a/src/lib.h b/src/lib.h index dcc882e..cafbba4 100644 --- a/src/lib.h +++ b/src/lib.h @@ -23,11 +23,7 @@ extern int ustrcmp(const unsigned char *s1, const unsigned char *s2); extern uint8_t get_rtp_tag_id(char *rtp_tag_name); extern char *get_rtp_tag_name(uint8_t rtp_tag); -#ifdef RDS2 -extern void add_checkwords(uint16_t *blocks, uint8_t *bits, bool rds2); -#else extern void add_checkwords(uint16_t *blocks, uint8_t *bits); -#endif extern uint8_t add_rds_af(struct rds_af_t *af_list, float freq); extern char *show_af_list(struct rds_af_t af_list); extern uint16_t crc16(uint8_t *data, size_t len); diff --git a/src/make-station-logo.sh b/src/make-station-logo.sh deleted file mode 100755 index e808a39..0000000 --- a/src/make-station-logo.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash - -# Create station logo data to build into the mpxgen executable for RDS2 - -if [ -z "$1" ]; then - echo "Usage: $0 " - exit -fi - -if [ -f "$1" ]; then - echo 'static const unsigned char station_logo[] = {' > rds2_image_data.c - xxd -i < "$1" >> rds2_image_data.c - echo '};' >> rds2_image_data.c - echo 'static const unsigned int station_logo_len = sizeof(station_logo);' >> rds2_image_data.c -fi diff --git a/src/minirds.c b/src/minirds.c index a58512c..9b1fd28 100644 --- a/src/minirds.c +++ b/src/minirds.c @@ -68,7 +68,7 @@ static void show_help(char *name) { "Usage: %s [options]\n" "\n" " -i,--pi Program Identification code\n" - " [default: 3073]\n" + " [default: 305F]\n" " -s,--ps Program Service name\n" " [default: \"radio95\"]\n" " -r,--rt1 Radio Text 1\n" @@ -84,9 +84,6 @@ static void show_help(char *name) { " -e,--ecc ECC code\n" " -d,--di DI code\n" " -C,--ctl FIFO control pipe\n" - #ifdef RDS2 - " -I,--img RDS2 Logo path\n" - #endif " -h,--help Show this help text and exit\n" " -v,--version Show version and exit\n" "\n", @@ -134,9 +131,6 @@ int main(int argc, char **argv) { pthread_cond_t control_pipe_cond; const char *short_opt = "R:i:s:r:p:T:A:P:l:e:L:d:C:" - #ifdef RDS2 - "I:" - #endif "hv"; struct option long_opt[] = @@ -154,9 +148,6 @@ int main(int argc, char **argv) { {"lic", required_argument, NULL, 'L'}, {"di", required_argument, NULL, 'd'}, {"ctl", required_argument, NULL, 'C'}, - #ifdef RDS2 - {"img", required_argument, NULL, 'I'}, - #endif {"help", no_argument, NULL, 'h'}, {"version", no_argument, NULL, 'v'}, @@ -215,12 +206,6 @@ keep_parsing_opts: memcpy(control_pipe, optarg, 50); break; - #ifdef RDS2 - case 'I': /* img */ - memcpy(rds_params.rds2_image_path, optarg, 50); - break; - #endif - case 'v': /* version */ show_version(); return 0; diff --git a/src/modulator.c b/src/modulator.c index e34d3ad..2c30b06 100644 --- a/src/modulator.c +++ b/src/modulator.c @@ -18,9 +18,6 @@ #include "common.h" #include "rds.h" -#ifdef RDS2 -#include "rds2.h" -#endif #include "fm_mpx.h" #include "waveforms.h" #include "modulator.h" @@ -33,56 +30,13 @@ static float **waveform; * */ void init_rds_objects() { - rds_ctx = malloc(NUM_STREAMS * sizeof(struct rds_t)); + rds_ctx = malloc(sizeof(struct rds_t)); - for (uint8_t i = 0; i < NUM_STREAMS; i++) { - rds_ctx[i] = malloc(sizeof(struct rds_t)); - rds_ctx[i]->bit_buffer = malloc(BITS_PER_GROUP); - rds_ctx[i]->sample_buffer = - malloc(SAMPLE_BUFFER_SIZE * sizeof(float)); - -#ifdef RDS2_SYMBOL_SHIFTING - /* - * symbol shifting to reduce total power of aggregate carriers - * - * see: - * https://ietresearch.onlinelibrary.wiley.com/doi/pdf/10.1049/el.2019.0292 - * for more information - */ - switch (i) { - case 1: - /* time offset of 1/2 */ - rds_ctx[i]->symbol_shift = SAMPLES_PER_BIT / 2; - rds_ctx[i]->symbol_shift_buf = malloc( - rds_ctx[i]->symbol_shift * sizeof(float)); - memset(rds_ctx[i]->symbol_shift_buf, 0, - rds_ctx[i]->symbol_shift * sizeof(float)); - break; - case 2: - /* time offset of 1/4 */ - rds_ctx[i]->symbol_shift = SAMPLES_PER_BIT / 4; - rds_ctx[i]->symbol_shift_buf = malloc( - rds_ctx[i]->symbol_shift * sizeof(float)); - memset(rds_ctx[i]->symbol_shift_buf, 0, - rds_ctx[i]->symbol_shift * sizeof(float)); - break; - case 3: - /* time offset of 3/4 */ - rds_ctx[i]->symbol_shift = (SAMPLES_PER_BIT / 4) * 3; - rds_ctx[i]->symbol_shift_buf = malloc( - rds_ctx[i]->symbol_shift * sizeof(float)); - memset(rds_ctx[i]->symbol_shift_buf, 0, - rds_ctx[i]->symbol_shift * sizeof(float)); - break; - default: /* stream 0 */ - /* no time offset */ - rds_ctx[i]->symbol_shift = 0; - break; - } -#endif - rds_ctx[i]->symbol_shift_buf_idx = 0; - - } + rds_ctx[0] = malloc(sizeof(struct rds_t)); + rds_ctx[0]->bit_buffer = malloc(BITS_PER_GROUP); + rds_ctx[0]->sample_buffer = + malloc(SAMPLE_BUFFER_SIZE * sizeof(float)); + rds_ctx[0]->symbol_shift_buf_idx = 0; waveform = malloc(2 * sizeof(float)); @@ -96,15 +50,13 @@ void init_rds_objects() { } void exit_rds_objects() { - for (uint8_t i = 0; i < NUM_STREAMS; i++) { - int has_symbol_shift = rds_ctx[i]->symbol_shift; - if (has_symbol_shift) { - free(rds_ctx[i]->symbol_shift_buf); - } - free(rds_ctx[i]->sample_buffer); - free(rds_ctx[i]->bit_buffer); - free(rds_ctx[i]); - } + int has_symbol_shift = rds_ctx[i]->symbol_shift; + if (has_symbol_shift) { + free(rds_ctx[i]->symbol_shift_buf); + } + free(rds_ctx[i]->sample_buffer); + free(rds_ctx[i]->bit_buffer); + free(rds_ctx[i]); free(rds_ctx); for (uint8_t i = 0; i < 2; i++) { @@ -117,11 +69,7 @@ void exit_rds_objects() { /* Get an RDS sample. This generates the envelope of the waveform using * pre-generated elementary waveform samples. */ -#ifdef RDS2 -float get_rds_sample(uint8_t stream_num, uint8_t rds2tunneling) { -#else float get_rds_sample(uint8_t stream_num) { -#endif struct rds_t *rds; uint16_t idx; float *cur_waveform; @@ -132,19 +80,7 @@ float get_rds_sample(uint8_t stream_num) { if (rds->sample_count == SAMPLES_PER_BIT) { if (rds->bit_pos == BITS_PER_GROUP) { -#ifdef RDS2 - if(!rds2tunneling) { - if (stream_num > 0) { - get_rds2_bits(stream_num, rds->bit_buffer); - } else { - get_rds_bits(rds->bit_buffer); - } - } else { - get_rds_bits(rds->bit_buffer); - } -#else get_rds_bits(rds->bit_buffer); -#endif rds->bit_pos = 0; } diff --git a/src/modulator.h b/src/modulator.h index 0ed8816..db34124 100644 --- a/src/modulator.h +++ b/src/modulator.h @@ -16,12 +16,6 @@ * along with this program. If not, see . */ -#ifdef RDS2 -#define NUM_STREAMS 4 -#else -#define NUM_STREAMS 1 -#endif - /* RDS signal context */ typedef struct rds_t { uint8_t *bit_buffer; /* BITS_PER_GROUP */ diff --git a/src/osc.c b/src/osc.c deleted file mode 100644 index 647fd4a..0000000 --- a/src/osc.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * mpxgen - FM multiplex encoder with Stereo and RDS - * Copyright (C) 2019 Anthony96922 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "common.h" -#include "osc.h" - -/* - * Code for MPX oscillator - * - * This uses lookup tables to speed up the waveform generation - * - */ - -/* - * DDS function generator - * - * Create wave constants for a given frequency - */ -static void create_wave(uint32_t rate, float freq, - float *sin_wave, float *cos_wave, uint16_t *max_phase) { - double sin_sample, cos_sample; - /* used to determine if we have completed a cycle */ - uint16_t periods = round((double)rate/freq); - const double w = M_2PI * freq / rate; - - /* First value of a sine wave is always 0 */ - *sin_wave++ = 0.0f; - *cos_wave++ = 1.0f; - - for(uint16_t i = 1; i < periods; i++) { - sin_sample = sin(w * i); - cos_sample = cos(w * i); - *sin_wave++ = (float)sin_sample; - *cos_wave++ = (float)cos_sample; - } - - *max_phase = periods; -} - -/* - * Oscillator object initialization - * - */ -void osc_init(struct osc_t *osc, uint32_t sample_rate, float freq) { - - /* sample rate for the objects */ - osc->sample_rate = sample_rate; - - /* waveform tables */ - osc->sin_wave = malloc(osc->sample_rate * sizeof(float)); - osc->cos_wave = malloc(osc->sample_rate * sizeof(float)); - - /* set current position to 0 */ - osc->cur = 0; - - /* create waveform data and load into lookup tables */ - create_wave(osc->sample_rate, freq, - osc->sin_wave, osc->cos_wave, - &osc->max); -} - -/* - * Get a single waveform sample - * - * Cosine is needed for SSB generation - * - */ -float osc_get_cos(struct osc_t *osc) { - return osc->cos_wave[osc->cur]; -} - -float osc_get_sin(struct osc_t *osc) { - return osc->sin_wave[osc->cur]; -} - -/* - * Shift the oscillator to the next position - * - */ -void osc_update_pos(struct osc_t *osc) { - if (++osc->cur == osc->max) osc->cur = 0; -} - -/* - * Unload waveform tables - * - */ -void osc_exit(struct osc_t *osc) { - free(osc->sin_wave); - free(osc->cos_wave); - osc->cur = 0; - osc->max = 0; -} diff --git a/src/osc.h b/src/osc.h deleted file mode 100644 index f68565c..0000000 --- a/src/osc.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * mpxgen - FM multiplex encoder with Stereo and RDS - * Copyright (C) 2019 Anthony96922 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* context for MPX oscillator */ -typedef struct osc_t { - /* the sample rate at which the oscillator operates */ - uint32_t sample_rate; - - /* - * frequency for this instance - * - */ - float freq; - - /* - * Arrays of carrier wave constants - * - */ - float *sin_wave_out_of_phase; - float *sin_wave; - float *cos_wave; - - /* - * Wave phase - * - */ - uint16_t cur; - uint16_t max; -} osc_t; - -extern void osc_init(struct osc_t *osc, uint32_t sample_rate, const float freq); -extern float osc_get_sin(struct osc_t *osc); -extern float osc_get_cos(struct osc_t *osc); -extern void osc_update_pos(struct osc_t *osc); -extern void osc_exit(struct osc_t *osc); diff --git a/src/rds.c b/src/rds.c index 94c8f6d..a031c9d 100644 --- a/src/rds.c +++ b/src/rds.c @@ -19,9 +19,6 @@ #include "common.h" #include "rds.h" #include "modulator.h" -#ifdef RDS2 -#include "rds2.h" -#endif #include "lib.h" #include @@ -529,11 +526,7 @@ group_coded: void get_rds_bits(uint8_t *bits) { static uint16_t out_blocks[GROUP_LENGTH]; get_rds_group(out_blocks); -#ifdef RDS2 - add_checkwords(out_blocks, bits, false); -#else add_checkwords(out_blocks, bits); -#endif } void init_rds_encoder(struct rds_params_t rds_params) { @@ -570,16 +563,10 @@ void init_rds_encoder(struct rds_params_t rds_params) { /* initialize modulator objects */ init_rds_objects(); -#ifdef RDS2 - init_rds2_encoder(rds_params.rds2_image_path); -#endif } void exit_rds_encoder() { exit_rds_objects(); -#ifdef RDS2 - exit_rds2_encoder(); -#endif } void set_rds_pi(uint16_t pi_code) { diff --git a/src/rds.h b/src/rds.h index 937450d..306f823 100644 --- a/src/rds.h +++ b/src/rds.h @@ -93,11 +93,6 @@ typedef struct rds_params_t { uint8_t pin_day; uint8_t pin_hour; uint8_t pin_minute; - - #ifdef RDS2 - /* RDS2 image path*/ - char rds2_image_path[51]; - #endif } rds_params_t; /* Here, the first member of the struct must be a scalar to avoid a warning on -Wmissing-braces with GCC < 4.8.3 @@ -259,14 +254,7 @@ typedef struct rds_params_t { #define INT16_14 0x4000 #define INT16_15 0x8000 -/* 18 bit (for RDS2) */ -#define INT18_U2 0x30000 -#define INT18_L4 0x0000f - #define IS_TYPE_B(a) (a[1] & INT16_11) -#ifdef RDS2 -#define IS_TUNNELING(a) (a[0] == 0x0000) -#endif #ifdef ODA /* @@ -291,9 +279,6 @@ typedef struct rds_oda_t { */ #define ODA_AID_RTPLUS 0x4bd7 #endif -/* RDS2 */ -#define ODA_AID_RFT 0xff7f -#define ODA_AID_RFTPLUS 0xff80 extern void init_rds_encoder(struct rds_params_t rds_params); extern void exit_rds_encoder(); @@ -325,11 +310,7 @@ extern void set_rds_tp(uint8_t tp); extern void set_rds_ms(uint8_t ms); extern void set_rds_ct(uint8_t ct); extern void set_rds_di(uint8_t di); -#ifdef RDS2 -extern float get_rds_sample(uint8_t stream_num, uint8_t rds2tunneling); -#else extern float get_rds_sample(uint8_t stream_num); -#endif extern uint16_t get_rds_pi(); extern void set_rds_cg(uint16_t* blocks); diff --git a/src/rds2.c b/src/rds2.c deleted file mode 100644 index 8d4b6a5..0000000 --- a/src/rds2.c +++ /dev/null @@ -1,452 +0,0 @@ -/* - * mpxgen - FM multiplex encoder with Stereo and RDS - * Copyright (C) 2019-2020 Anthony96922 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "common.h" -#include "rds.h" -#include "rds2.h" -#include "lib.h" - -/* - * RDS2-specific stuff - */ - - -/* RFT */ - -/* fallback station logo */ -#include "rds2_image_data.c" - -/* station logo */ -static struct rft_t station_logo_stream; - -static void init_rft(struct rft_t *rft, uint8_t file_id, - bool usecrc, uint8_t crc_mode, char *file_path) { - uint32_t seg_counter = 0; - uint32_t crc_chunk_counter = 0; - uint16_t crc_chunk_size = 0; - FILE *image_file_hdlr; - - rft->file_path = malloc(MAX_FILE_NAME_LEN + 1); - rft->file_path[MAX_FILE_NAME_LEN] = 0; - rft->file_data = malloc(MAX_IMAGE_LEN); - rft->crcs = malloc(MAX_CRC_CHUNK_ADDR * sizeof(uint16_t)); - - /* unused data must be padded with zeroes */ - memset(rft->file_data, 0, MAX_IMAGE_LEN); - - strncpy(rft->file_path, file_path, MAX_FILE_NAME_LEN); - - /* open file in binary mode */ - image_file_hdlr = fopen(file_path, "rb"); - if (image_file_hdlr != NULL) { - fseek(image_file_hdlr, 0, SEEK_END); - rft->file_len = ftell(image_file_hdlr); - rewind(image_file_hdlr); - - /* image cannot be larger than 163840 bytes */ - if (rft->file_len > MAX_IMAGE_LEN) { -#ifdef RDS2_DEBUG - fprintf(stderr, "W: Image too large!\n"); -#endif - rft->file_len = MAX_IMAGE_LEN; - } - - /* copy image data to local buffer */ - fread(rft->file_data, rft->file_len, 1, image_file_hdlr); - - fclose(image_file_hdlr); - } else { /* fallback in case file can't be read at startup */ - rft->file_len = station_logo_len; - - if (rft->file_len > MAX_IMAGE_LEN) { - rft->file_len = MAX_IMAGE_LEN; - } - - memcpy(rft->file_data, station_logo, rft->file_len); - } - - /* keep track of file lengths so we know when to toggle */ - rft->prev_file_len = rft->file_len; - rft->channel = 0; - rft->file_id = file_id; - rft->toggle = 0; - rft->num_segs = 0; - - /* determine how many segments we need */ - while (seg_counter < rft->file_len) { - seg_counter += 5; - rft->num_segs++; - } - - rft->use_crc = usecrc; - - /* if CRC is disabled exit early */ - if (!rft->use_crc) { - rft->crc_mode = 0; - rft->num_crc_chunks = 1; /* only 1 */ - rft->crcs[0] = 0x0000; - return; - } - - rft->crc_mode = crc_mode & 7; - - switch (rft->crc_mode) { - case RFT_CRC_MODE_ENTIRE_FILE: - /* no-op */ - break; - - case RFT_CRC_MODE_16_GROUPS: - crc_chunk_size = 16; - break; - - case RFT_CRC_MODE_32_GROUPS: - crc_chunk_size = 32; - break; - - case RFT_CRC_MODE_64_GROUPS: - crc_chunk_size = 64; - break; - - case RFT_CRC_MODE_128_GROUPS: - crc_chunk_size = 128; - break; - - case RFT_CRC_MODE_256_GROUPS: - crc_chunk_size = 256; - break; - - case RFT_CRC_MODE_RFU: /* reserved - use auto mode */ - case RFT_CRC_MODE_AUTO: - if (rft->file_len >= 81920) { - crc_chunk_size = 64; - rft->crc_mode = RFT_CRC_MODE_64_GROUPS; - } else if (rft->file_len > 40960) { - crc_chunk_size = 32; - rft->crc_mode = RFT_CRC_MODE_32_GROUPS; - } else { - crc_chunk_size = 16; - rft->crc_mode = RFT_CRC_MODE_16_GROUPS; - } - break; - } - - if (rft->crc_mode) { /* chunked modes */ - /* RFT packet size = chunk size * 5 data bytes per group */ - rft->pkt_size = crc_chunk_size * 5; - - /* the remainder (if file size is not a multiple of pkt_size) */ - rft->pkt_size_rem = rft->file_len % rft->pkt_size; - - /* calculate number of CRC chunks */ - while (crc_chunk_counter <= rft->file_len) { - crc_chunk_counter += rft->pkt_size; - rft->num_crc_chunks++; - } - - rft->crc_chunks = malloc(rft->pkt_size); - - /* calculate CRC's for chunks */ - for (uint16_t i = 0; i < rft->num_crc_chunks; i++) { - memset(rft->crc_chunks, 0, rft->pkt_size); - memcpy(rft->crc_chunks, - rft->file_data + i * rft->pkt_size, rft->pkt_size); - if ((i == rft->num_crc_chunks - 1) && rft->pkt_size_rem) { - /* last chunk may have less bytes */ - rft->crcs[i] = crc16(rft->crc_chunks, rft->pkt_size_rem); - } else { - rft->crcs[i] = crc16(rft->crc_chunks, rft->pkt_size); - } - } - - free(rft->crc_chunks); - } else { /* CRC of entire file */ - rft->num_crc_chunks = 1; /* only 1 */ - rft->crcs[0] = crc16(rft->file_data, rft->file_len); - } -} - -static void update_rft(struct rft_t *rft) { - uint32_t seg_counter = 0; - FILE *image_file_hdlr; - - /* open file in binary mode */ - image_file_hdlr = fopen(rft->file_path, "rb"); - if (image_file_hdlr == NULL) { - return; - } - - rft->prev_file_len = rft->file_len; - - /* update size field */ - fseek(image_file_hdlr, 0, SEEK_END); - rft->file_len = ftell(image_file_hdlr); - rewind(image_file_hdlr); - - /* file didn't change so return early */ - if (rft->file_len == rft->prev_file_len) { - fclose(image_file_hdlr); - return; - } - - /* image cannot be larger than 163840 bytes */ - if (rft->file_len > MAX_IMAGE_LEN) { -#ifdef RDS2_DEBUG - fprintf(stderr, "W: Image too large!\n"); -#endif - rft->file_len = MAX_IMAGE_LEN; - } - - /* copy image data to local buffer */ - fread(rft->file_data, rft->file_len, 1, image_file_hdlr); - - fclose(image_file_hdlr); - - rft->num_segs = 0; - - /* recalculate # of needed segments */ - while (seg_counter < rft->file_len) { - seg_counter += 5; - rft->num_segs++; - } - - if (rft->crc_mode) { - /* recalculate CRC's for chunks */ - for (uint16_t i = 0; i < rft->num_crc_chunks; i++) { - memset(rft->crc_chunks, 0, rft->pkt_size); - memcpy(rft->crc_chunks, - rft->file_data + i * rft->pkt_size, rft->pkt_size); - if ((i == rft->num_crc_chunks - 1) && rft->pkt_size_rem) { - /* last chunk may have less bytes */ - rft->crcs[i] = crc16(rft->crc_chunks, rft->pkt_size_rem); - } else { - rft->crcs[i] = crc16(rft->crc_chunks, rft->pkt_size); - } - } - - free(rft->crc_chunks); - } else { /* CRC of entire file */ - rft->num_crc_chunks = 1; /* only 1 */ - rft->crcs[0] = crc16(rft->file_data, rft->file_len); - } - - if (++rft->file_version == 8) { - rft->file_version = 0; - } -} - -static void exit_rft(struct rft_t *rft) { - free(rft->file_data); - free(rft->file_path); - free(rft->crcs); -} - -/* - * RFT variant 0 (file metadata) - * - * Carries: - * - Function Header - * - Pipe Number - * - ODA ID - * - Variant code (0) - * - CRC-16 Flag - * - File ID - * - File size (18 bits) - */ -static void get_rft_var_0_data_group(struct rft_t *rft, uint16_t *blocks) { - /* function header */ - blocks[0] = 1 << 15; - blocks[0] |= (rft->channel & INT8_L4); /* pipe number */ - - /* ODA ID */ - blocks[1] = ODA_AID_RFT; - - blocks[2] = (0 & INT18_L4) << 12; /* variant code */ - blocks[2] |= ((rft->use_crc ? 1 : 0) & INT8_L1) << 11; /* CRC */ - blocks[2] |= (rft->file_version & INT8_L3) << 8; /* file version */ - blocks[2] |= (rft->file_id & INT8_L6) << 2; /* file ID */ - blocks[2] |= (rft->file_len & INT18_U2) >> 16; - - blocks[3] = rft->file_len & INT16_ALL; -} - -/* - * RFT variant 1 (chunk to CRC mappings) - * - * Carries: - * - Function Header - * - Pipe Number - * - ODA ID - * - Variant Code (1) - * - CRC Mode - * - Chunk Address (9 bits) - * - CRC - */ -static void get_rft_var_1_data_group(struct rft_t *rft, uint16_t *blocks) { - /* function header */ - blocks[0] = 1 << 15; - blocks[0] |= (rft->channel & INT8_L4); /* pipe number */ - - /* ODA ID */ - blocks[1] = ODA_AID_RFT; - - blocks[2] = (1 & INT8_L4) << 12; /* variant code */ - blocks[2] |= (rft->crc_mode & INT8_L3) << 9; /* CRC mode */ - /* chunk address */ - blocks[2] |= rft->crc_chunk_addr & INT16_L9; - - /* CRC */ - blocks[3] = rft->crcs[rft->crc_chunk_addr]; - - if (++rft->crc_chunk_addr > rft->num_crc_chunks) { -#ifdef RDS2_DEBUG - fprintf(stderr, "File CRC sending complete\n"); -#endif - rft->crc_chunk_addr = 0; - } -} - -/* - * RFT variants 2-15 (custom variants) - * - * Carries: - * - Function Header - * - Pipe Number - * - Variant code - * - Variant data: - * - 2-7 carries file-related data - * - 8-15 ODA data that is not related - */ -#if 0 -static void get_rft_var_2_15_data_group(struct rft_t *rft, uint16_t *blocks) { - /* function header */ - blocks[0] = (2 << 6) << 8; - blocks[0] |= (rft->channel & INT8_L4); /* pipe number */ - - /* ODA ID */ - blocks[1] = ODA_AID_RFT; - - blocks[2] = (8 & INT8_L4) << 12; /* variant code */ - blocks[2] |= 0 & INT16_L12; - blocks[3] = 0 & INT16_ALL; -} -#endif - -/* - * RFT data group (for file data TXing) - * - * Carries: - * - Function Header - * - Pipe Number - * - Toggle Bit - * - Segment address (15 bits) - * - File data (5 bytes per group) - */ -static void get_rft_file_data_group(struct rft_t *rft, uint16_t *blocks) { - /* function header */ - blocks[0] = 2 << 12; - blocks[0] |= (rft->channel & INT8_L4) << 8; /* pipe number */ - - /* toggle bit */ - blocks[0] |= (rft->toggle & INT16_L1) << 7; - - /* segment address */ - blocks[0] |= ((rft->seg_addr_img & INT16_U8) >> 8) & INT16_L7; - blocks[1] = (rft->seg_addr_img & INT16_L8) << 8; - - /* image data */ - blocks[1] |= rft->file_data[rft->seg_addr_img * 5 + 0]; - blocks[2] = rft->file_data[rft->seg_addr_img * 5 + 1] << 8; - blocks[2] |= rft->file_data[rft->seg_addr_img * 5 + 2]; - blocks[3] = rft->file_data[rft->seg_addr_img * 5 + 3] << 8; - blocks[3] |= rft->file_data[rft->seg_addr_img * 5 + 4]; - - if (++rft->seg_addr_img > rft->num_segs) { -#ifdef RDS2_DEBUG - fprintf(stderr, "File sending complete\n"); -#endif - rft->seg_addr_img = 0; - rft->toggle ^= 1; - update_rft(rft); - } -} - -static void get_rft_stream(uint16_t *blocks) { - static uint8_t rft_state; - - switch (rft_state) { - case 0: - get_rft_var_0_data_group(&station_logo_stream, blocks); - break; - case 1: - get_rft_var_1_data_group(&station_logo_stream, blocks); - break; - case 2: - get_rft_var_0_data_group(&station_logo_stream, blocks); - break; - case 3: - get_rft_var_1_data_group(&station_logo_stream, blocks); - break; - - default: - get_rft_file_data_group(&station_logo_stream, blocks); - break; - } - - rft_state++; - if (rft_state == 50) rft_state = 0; -} - -/* - * RDS 2 group sequence - */ -static void get_rds2_group(uint8_t stream_num, uint16_t *blocks) { - - switch (stream_num) { - case 1: - case 2: - case 3: - default: - get_rft_stream(blocks); - break; - } - -#ifdef RDS2_DEBUG - fprintf(stderr, "Stream %u: %04x %04x %04x %04x\n", - stream_num, blocks[0], blocks[1], blocks[2], blocks[3]); -#endif -} - -void get_rds2_bits(uint8_t stream, uint8_t *bits) { - static uint16_t out_blocks[GROUP_LENGTH]; - get_rds2_group(stream, out_blocks); - add_checkwords(out_blocks, bits, true); -} - -void init_rds2_encoder(char *station_logo_path) { - /* create a new stream for the station logo */ - init_rft(&station_logo_stream, - 0 /* file ID */, - false /* don't use crc */, - RFT_CRC_MODE_AUTO, - station_logo_path - ); -} - -void exit_rds2_encoder() { - exit_rft(&station_logo_stream); -} diff --git a/src/rds2.h b/src/rds2.h deleted file mode 100644 index 17fdb1b..0000000 --- a/src/rds2.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * mpxgen - FM multiplex encoder with Stereo and RDS - * Copyright (C) 2019-2020 Anthony96922 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -typedef struct rds2_oda_t { - uint16_t aid; - uint8_t channel; -} rds2_oda_t; - -#define GET_RDS2_ODA_CHANNEL(x) (x & INT8_L5) - -#define MAX_FILE_NAME_LEN 64 /* does not include terminating null char */ -#define MAX_IMAGE_LEN 163840 -#define MAX_CRC_CHUNK_ADDR 511 - -/* RFT CRC mode */ -enum rft_crc_mode { - RFT_CRC_MODE_ENTIRE_FILE, /* over entire file (universal) */ - RFT_CRC_MODE_16_GROUPS, /* chunks of 16 groups (size <= 40,960) */ - RFT_CRC_MODE_32_GROUPS, /* chunks of 32 groups (40,960 < size <= 81,920) */ - RFT_CRC_MODE_64_GROUPS, /* chunks of 64 groups (size > 81,960) */ - RFT_CRC_MODE_128_GROUPS, /* chunks of 128 groups (size > 81,960) */ - RFT_CRC_MODE_256_GROUPS, /* chunks of 256 groups (size > 81,960) */ - RFT_CRC_MODE_RFU, /* reserved */ - RFT_CRC_MODE_AUTO /* automatic between 1-3 based on size */ -}; - -/* RDS2 File Transfer */ -typedef struct rft_t { - uint8_t channel; - - char *file_path; - unsigned char *file_data; - size_t file_len; - size_t prev_file_len; - uint8_t file_version; - uint8_t file_id; - uint8_t variant_code; - uint8_t toggle; - - uint16_t pkt_size; - uint16_t pkt_size_rem; - uint16_t seg_addr_img; - uint16_t num_segs; - - /* CRC chunk map */ - bool use_crc; - uint8_t crc_mode; - uint16_t crc_chunk_addr; - uint16_t num_crc_chunks; - uint8_t *crc_chunks; - uint16_t *crcs; -} rft_t; - -extern void get_rds2_bits(uint8_t stream_num, uint8_t *bits); -extern void init_rds2_encoder(char *station_logo_path); -extern void exit_rds2_encoder(); diff --git a/src/rds2_image_data.c b/src/rds2_image_data.c deleted file mode 100644 index 40b72c8..0000000 --- a/src/rds2_image_data.c +++ /dev/null @@ -1,181 +0,0 @@ -static const unsigned char station_logo[] = { - 0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01, - 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0xff, 0xe2, 0x01, 0xd8, - 0x49, 0x43, 0x43, 0x5f, 0x50, 0x52, 0x4f, 0x46, 0x49, 0x4c, 0x45, 0x00, - 0x01, 0x01, 0x00, 0x00, 0x01, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x04, 0x30, - 0x00, 0x00, 0x6d, 0x6e, 0x74, 0x72, 0x52, 0x47, 0x42, 0x20, 0x58, 0x59, - 0x5a, 0x20, 0x07, 0xe0, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x61, 0x63, 0x73, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, - 0xf6, 0xd6, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x09, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, - 0x00, 0x24, 0x72, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, - 0x00, 0x14, 0x67, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x01, 0x28, 0x00, 0x00, - 0x00, 0x14, 0x62, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x01, 0x3c, 0x00, 0x00, - 0x00, 0x14, 0x77, 0x74, 0x70, 0x74, 0x00, 0x00, 0x01, 0x50, 0x00, 0x00, - 0x00, 0x14, 0x72, 0x54, 0x52, 0x43, 0x00, 0x00, 0x01, 0x64, 0x00, 0x00, - 0x00, 0x28, 0x67, 0x54, 0x52, 0x43, 0x00, 0x00, 0x01, 0x64, 0x00, 0x00, - 0x00, 0x28, 0x62, 0x54, 0x52, 0x43, 0x00, 0x00, 0x01, 0x64, 0x00, 0x00, - 0x00, 0x28, 0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x01, 0x8c, 0x00, 0x00, - 0x00, 0x3c, 0x6d, 0x6c, 0x75, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x65, 0x6e, 0x55, 0x53, 0x00, 0x00, - 0x00, 0x08, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x73, 0x00, 0x52, 0x00, 0x47, - 0x00, 0x42, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x6f, 0xa2, 0x00, 0x00, 0x38, 0xf5, 0x00, 0x00, 0x03, 0x90, 0x58, 0x59, - 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x99, 0x00, 0x00, - 0xb7, 0x85, 0x00, 0x00, 0x18, 0xda, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x24, 0xa0, 0x00, 0x00, 0x0f, 0x84, 0x00, 0x00, - 0xb6, 0xcf, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xf6, 0xd6, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d, 0x70, 0x61, - 0x72, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, - 0x66, 0x66, 0x00, 0x00, 0xf2, 0xa7, 0x00, 0x00, 0x0d, 0x59, 0x00, 0x00, - 0x13, 0xd0, 0x00, 0x00, 0x0a, 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x6d, 0x6c, 0x75, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x65, 0x6e, 0x55, 0x53, 0x00, 0x00, - 0x00, 0x20, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x47, 0x00, 0x6f, 0x00, 0x6f, - 0x00, 0x67, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6e, - 0x00, 0x63, 0x00, 0x2e, 0x00, 0x20, 0x00, 0x32, 0x00, 0x30, 0x00, 0x31, - 0x00, 0x36, 0xff, 0xdb, 0x00, 0x43, 0x00, 0x1b, 0x12, 0x14, 0x17, 0x14, - 0x11, 0x1b, 0x17, 0x16, 0x17, 0x1e, 0x1c, 0x1b, 0x20, 0x28, 0x42, 0x2b, - 0x28, 0x25, 0x25, 0x28, 0x51, 0x3a, 0x3d, 0x30, 0x42, 0x60, 0x55, 0x65, - 0x64, 0x5f, 0x55, 0x5d, 0x5b, 0x6a, 0x78, 0x99, 0x81, 0x6a, 0x71, 0x90, - 0x73, 0x5b, 0x5d, 0x85, 0xb5, 0x86, 0x90, 0x9e, 0xa3, 0xab, 0xad, 0xab, - 0x67, 0x80, 0xbc, 0xc9, 0xba, 0xa6, 0xc7, 0x99, 0xa8, 0xab, 0xa4, 0xff, - 0xdb, 0x00, 0x43, 0x01, 0x1c, 0x1e, 0x1e, 0x28, 0x23, 0x28, 0x4e, 0x2b, - 0x2b, 0x4e, 0xa4, 0x6e, 0x5d, 0x6e, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, - 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, - 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, - 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, - 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xff, 0xc0, 0x00, 0x11, - 0x08, 0x00, 0xcd, 0x00, 0xcd, 0x03, 0x01, 0x22, 0x00, 0x02, 0x11, 0x01, - 0x03, 0x11, 0x01, 0xff, 0xc4, 0x00, 0x1a, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x05, 0x04, 0x06, 0x02, 0x03, 0x01, 0xff, 0xc4, 0x00, 0x3c, 0x10, - 0x00, 0x01, 0x03, 0x03, 0x02, 0x02, 0x05, 0x09, 0x05, 0x08, 0x03, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x11, 0x12, - 0x21, 0x06, 0x31, 0x13, 0x22, 0x41, 0x91, 0xa1, 0x14, 0x32, 0x51, 0x61, - 0x71, 0x73, 0x81, 0xb1, 0xd1, 0x34, 0x36, 0x52, 0xc2, 0xe1, 0x16, 0x24, - 0x33, 0x35, 0x42, 0x44, 0x82, 0xc1, 0x54, 0xb2, 0xf0, 0xff, 0xc4, 0x00, - 0x14, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc4, 0x00, 0x14, 0x11, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, - 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00, 0xe6, 0x40, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x56, - 0xc7, 0x68, 0x65, 0xd1, 0x26, 0x57, 0xcc, 0xe8, 0xfa, 0x3d, 0x3c, 0x93, - 0x39, 0xce, 0x7e, 0x85, 0x2a, 0x7e, 0x14, 0x6a, 0xac, 0x8b, 0x51, 0x3b, - 0x91, 0x35, 0x2a, 0x31, 0x18, 0x89, 0x9c, 0x76, 0x2a, 0xfd, 0x00, 0xe6, - 0x01, 0x42, 0x9e, 0xd8, 0xda, 0xab, 0xa3, 0xa8, 0xa0, 0xaa, 0x8d, 0xcd, - 0x6a, 0xff, 0x00, 0x15, 0x76, 0xd4, 0x89, 0xcf, 0x09, 0xdb, 0xdb, 0xdc, - 0x5b, 0x4e, 0x13, 0xa7, 0xe8, 0xb0, 0xb5, 0x32, 0xf4, 0x9f, 0x8b, 0x09, - 0x8e, 0xef, 0xd4, 0x0e, 0x50, 0x1b, 0x6e, 0xb6, 0xc9, 0x6d, 0x93, 0xa4, - 0x72, 0x2a, 0x3d, 0x8e, 0x4c, 0xb1, 0xe8, 0x98, 0xcf, 0xea, 0x6d, 0xb2, - 0xd8, 0x16, 0xe1, 0x0f, 0x94, 0x4d, 0x22, 0xc7, 0x12, 0xae, 0x1a, 0x8d, - 0x4d, 0xdd, 0xe9, 0x5f, 0x56, 0xe0, 0x67, 0xb1, 0xdb, 0xa3, 0xb9, 0xd4, - 0xbe, 0x29, 0x1e, 0xe6, 0x23, 0x59, 0xab, 0x2d, 0xf6, 0xa1, 0xf9, 0x55, - 0x6f, 0x8e, 0x1b, 0xe3, 0x68, 0x1a, 0xf7, 0x2b, 0x16, 0x46, 0x33, 0x52, - 0xf3, 0xeb, 0x63, 0xea, 0x74, 0x76, 0xab, 0x2a, 0xdb, 0x2e, 0x2f, 0x92, - 0x39, 0x3a, 0x48, 0x5f, 0x1a, 0xa2, 0x2a, 0xf3, 0x6a, 0xe5, 0x36, 0x5f, - 0x49, 0x12, 0xee, 0xc5, 0x97, 0x8a, 0x56, 0x36, 0xbd, 0x58, 0xaf, 0x92, - 0x36, 0xa3, 0x9b, 0xcd, 0xb9, 0x46, 0xee, 0x80, 0x78, 0xbf, 0x5a, 0x62, - 0xb5, 0xf4, 0x1d, 0x14, 0x8f, 0x7f, 0x49, 0xab, 0x3a, 0xb1, 0xb6, 0x31, - 0xf5, 0x24, 0x96, 0xb8, 0x8a, 0x86, 0x5a, 0x3f, 0x27, 0xe9, 0x2b, 0x26, - 0xa9, 0xd7, 0xab, 0x1d, 0x22, 0xaa, 0xe9, 0xc6, 0x39, 0x6f, 0xeb, 0x3f, - 0x6d, 0x1c, 0x3d, 0x25, 0x74, 0x29, 0x51, 0x3c, 0x8b, 0x14, 0x4e, 0x5e, - 0xaa, 0x22, 0x65, 0xce, 0x4f, 0x4f, 0xa8, 0x08, 0x87, 0xa8, 0xa3, 0x7c, - 0xd2, 0xb2, 0x28, 0xd3, 0x53, 0xde, 0xa8, 0xd6, 0xa7, 0xa5, 0x54, 0xe9, - 0x6a, 0xb8, 0x4d, 0xbd, 0x1a, 0xad, 0x25, 0x43, 0xb5, 0xa2, 0x79, 0xb2, - 0x22, 0x6f, 0xf1, 0x4e, 0x44, 0xbb, 0x03, 0x7a, 0x2b, 0xf4, 0x0c, 0x95, - 0x34, 0xb9, 0xae, 0x73, 0x55, 0x1d, 0xd8, 0xba, 0x57, 0x6e, 0xf0, 0x2b, - 0xd3, 0x70, 0x9c, 0x29, 0x1f, 0xef, 0x35, 0x12, 0x39, 0xeb, 0xd9, 0x1e, - 0x11, 0x13, 0xbd, 0x17, 0x3e, 0x04, 0xbb, 0xcd, 0x8e, 0x4b, 0x6b, 0x52, - 0x68, 0xde, 0xb2, 0xc0, 0xab, 0x85, 0x5c, 0x61, 0x5a, 0xbe, 0xbf, 0xa9, - 0x53, 0x8a, 0x22, 0xaf, 0x92, 0x68, 0x3c, 0x99, 0xb2, 0xbe, 0x14, 0x4c, - 0xe2, 0x24, 0x55, 0xc3, 0xb3, 0xcd, 0x71, 0xf0, 0xc7, 0xc4, 0xd5, 0x77, - 0x47, 0xb7, 0x86, 0x5c, 0x95, 0x19, 0x59, 0x12, 0x38, 0xd1, 0xfb, 0xe5, - 0x75, 0x65, 0x3f, 0xd8, 0x11, 0x6c, 0x76, 0x58, 0x6e, 0x74, 0xf2, 0x49, - 0x24, 0xaf, 0x62, 0xb5, 0xfa, 0x51, 0x1b, 0x8f, 0x41, 0x4b, 0xf6, 0x4e, - 0x97, 0xfe, 0x44, 0xde, 0x07, 0xef, 0x07, 0x7d, 0x86, 0x7f, 0x7b, 0xfe, - 0x90, 0xf3, 0x51, 0x64, 0xb9, 0x4b, 0x2c, 0xf2, 0xb2, 0xe0, 0xac, 0xd4, - 0xf7, 0x39, 0x8c, 0xd6, 0xec, 0x22, 0x2a, 0xed, 0xbf, 0x67, 0x70, 0x10, - 0xef, 0x54, 0x0c, 0xb7, 0x56, 0x24, 0x11, 0xbd, 0xcf, 0x45, 0x62, 0x3b, - 0x2e, 0xe7, 0xda, 0x60, 0x3e, 0xf5, 0xac, 0xa8, 0x8a, 0xa5, 0xf1, 0xd5, - 0xab, 0xd6, 0x56, 0x6c, 0xba, 0x9d, 0x93, 0xe0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x07, 0x4f, 0xc1, 0x9e, 0x6d, 0x5f, 0xb5, 0x9f, - 0x98, 0x97, 0x7a, 0xad, 0xa9, 0x75, 0xda, 0xa3, 0x13, 0x48, 0xd4, 0x63, - 0x95, 0x8d, 0x46, 0xb9, 0x51, 0x11, 0x39, 0x78, 0x95, 0x38, 0x33, 0xcd, - 0xab, 0xf6, 0xb3, 0xf3, 0x10, 0xee, 0xff, 0x00, 0xcd, 0x6a, 0xfd, 0xeb, - 0xbe, 0x60, 0x7d, 0x2d, 0x16, 0xea, 0x8b, 0x85, 0x4e, 0x20, 0x7f, 0x47, - 0xd1, 0xe1, 0xce, 0x93, 0xf0, 0xef, 0xb6, 0x3d, 0x7f, 0x42, 0xe3, 0x38, - 0x6a, 0x76, 0xd4, 0xa5, 0x42, 0x5c, 0xde, 0xb3, 0x22, 0xe7, 0x5a, 0xc7, - 0x95, 0xff, 0x00, 0xb1, 0x97, 0x84, 0x2a, 0x62, 0x8a, 0x6a, 0x88, 0x64, - 0x7a, 0x35, 0xf2, 0xa3, 0x74, 0x65, 0x71, 0x9c, 0x67, 0x6f, 0x6e, 0xe6, - 0x9a, 0xae, 0x1e, 0xa5, 0x8e, 0xa2, 0x4a, 0xba, 0x9a, 0xd7, 0x36, 0x15, - 0x72, 0xbd, 0xc8, 0xa9, 0xbe, 0xfb, 0xe3, 0x3f, 0xa0, 0x0e, 0x31, 0x6a, - 0x79, 0x35, 0x3b, 0xb1, 0xba, 0x3d, 0x53, 0x3f, 0x0f, 0xd0, 0xd8, 0xd7, - 0x2d, 0x3f, 0x0b, 0xb5, 0xd1, 0x75, 0x1c, 0x94, 0xc8, 0xa8, 0xa9, 0xb6, - 0x15, 0x53, 0x9f, 0x89, 0x97, 0x8c, 0x7e, 0xc7, 0x07, 0xbc, 0x5f, 0x91, - 0xf6, 0xb0, 0xd5, 0xc1, 0x5f, 0x6a, 0x4a, 0x39, 0x5c, 0x8b, 0x23, 0x18, - 0xb1, 0xbd, 0x8b, 0xb2, 0xab, 0x79, 0x22, 0xa7, 0xc3, 0x00, 0x4f, 0xe0, - 0xf9, 0xa4, 0x5a, 0xa9, 0xe2, 0x57, 0xaa, 0xb1, 0x59, 0xaf, 0x0a, 0xbd, - 0xb9, 0x4d, 0xfc, 0x4f, 0x8d, 0xc7, 0xef, 0x7b, 0x3d, 0xf4, 0x5f, 0x26, - 0x97, 0x6d, 0x96, 0xea, 0x2b, 0x6d, 0x53, 0xe2, 0x82, 0x47, 0x3e, 0x67, - 0xb3, 0x2a, 0x8f, 0x54, 0x55, 0x6b, 0x51, 0x7d, 0x49, 0xb7, 0x3f, 0x02, - 0x15, 0xc7, 0xef, 0x7b, 0x3d, 0xf4, 0x5f, 0x26, 0x81, 0xab, 0x8c, 0xff, - 0x00, 0xb3, 0xff, 0x00, 0x3f, 0xca, 0x6f, 0xb8, 0x48, 0xfa, 0x5e, 0x19, - 0x47, 0x40, 0xf5, 0x63, 0x9b, 0x14, 0x68, 0x8e, 0x45, 0xdd, 0x39, 0x27, - 0xc8, 0xc1, 0xc6, 0x7f, 0xd9, 0xff, 0x00, 0x9f, 0xe5, 0x36, 0x5a, 0xea, - 0xa9, 0x2e, 0xd6, 0x96, 0xd1, 0x4c, 0xa9, 0xad, 0x18, 0x8c, 0x7b, 0x35, - 0x61, 0x57, 0x1c, 0x95, 0x3b, 0x91, 0x40, 0xc5, 0xc2, 0x35, 0x53, 0x3e, - 0x79, 0xe1, 0x7c, 0x8e, 0x7b, 0x34, 0x23, 0x91, 0x1c, 0xaa, 0xb8, 0x5c, - 0xf6, 0x77, 0x93, 0x6f, 0xeb, 0xd0, 0xdf, 0xa7, 0x74, 0x5d, 0x47, 0x35, - 0xcd, 0x72, 0x2a, 0x6d, 0x85, 0xd2, 0x8b, 0x9e, 0xf3, 0xa6, 0xa5, 0xa3, - 0xa0, 0xb1, 0x43, 0x24, 0x8b, 0x2a, 0xb5, 0x1d, 0xcd, 0xf2, 0xb9, 0x32, - 0xb8, 0xec, 0x43, 0x8f, 0xb8, 0xd5, 0x2d, 0x6d, 0x74, 0xd5, 0x18, 0xc2, - 0x3d, 0xdb, 0x22, 0xf6, 0x27, 0x24, 0xf0, 0xc0, 0x1d, 0x1d, 0xa3, 0x88, - 0x27, 0xad, 0xa8, 0x8a, 0x95, 0xd4, 0xad, 0x73, 0xd7, 0xce, 0x91, 0x1d, - 0x84, 0x44, 0x4e, 0xdc, 0x63, 0xff, 0x00, 0x29, 0xe3, 0x8b, 0xeb, 0x34, - 0xc5, 0x15, 0x1b, 0x57, 0x77, 0x2f, 0x48, 0xff, 0x00, 0x67, 0x24, 0xf1, - 0xcf, 0x71, 0xeb, 0x84, 0xa8, 0xd2, 0x2a, 0x69, 0x2b, 0x5f, 0xb2, 0xc9, - 0xd5, 0x6a, 0xaf, 0x63, 0x53, 0x9a, 0xf7, 0xfc, 0x8e, 0x7a, 0xe7, 0x56, - 0xb5, 0xd5, 0xf3, 0x54, 0x7f, 0x4b, 0x9d, 0xd5, 0x4f, 0x43, 0x53, 0x64, - 0xf0, 0x03, 0x6d, 0x9a, 0xf0, 0xfb, 0x6c, 0x0f, 0x8d, 0xb4, 0xab, 0x32, - 0x39, 0xda, 0xb3, 0xab, 0x18, 0xdb, 0xd8, 0x6c, 0xb3, 0x5e, 0xab, 0x6a, - 0xef, 0x2c, 0x8e, 0x59, 0x11, 0x62, 0x97, 0x57, 0x53, 0x09, 0x86, 0xec, - 0xaa, 0x98, 0x3c, 0xf0, 0xad, 0xce, 0x1a, 0x74, 0x92, 0x92, 0x77, 0xb6, - 0x34, 0x7b, 0xb5, 0xb1, 0xce, 0xd9, 0x33, 0x8d, 0xd1, 0x57, 0xe0, 0x85, - 0x88, 0x6d, 0x14, 0x14, 0x55, 0x6f, 0xae, 0x6a, 0xab, 0x15, 0x32, 0xbd, - 0x67, 0x22, 0x31, 0x99, 0xe6, 0xa8, 0x04, 0x4e, 0x30, 0x6e, 0x2e, 0x31, - 0x3b, 0xd3, 0x12, 0x27, 0x8a, 0x90, 0x4a, 0x7c, 0x43, 0x5d, 0x1d, 0x7d, - 0xc5, 0x5f, 0x0e, 0xf1, 0xc6, 0xd4, 0x62, 0x3b, 0xf1, 0x73, 0x5c, 0xf8, - 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd9 -}; -static const unsigned int station_logo_len = sizeof(station_logo); diff --git a/src/station_logo.jpg b/src/station_logo.jpg deleted file mode 100644 index 43d72e2..0000000 Binary files a/src/station_logo.jpg and /dev/null differ