mirror of
https://github.com/radio95-rnt/rds95.git
synced 2026-07-30 00:39:15 +02:00
ipc thing, and some more stuff i guess
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
#include "ipc_client.h"
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int ipc_connect(IPC_Client *client, const char *socket_path) {
|
||||
client->fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (client->fd < 0) { perror("fm95 ipc: socket"); return -1; }
|
||||
|
||||
struct sockaddr_un addr = { .sun_family = AF_UNIX };
|
||||
strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path) - 1);
|
||||
|
||||
if (connect(client->fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||
perror("fm95 ipc: connect");
|
||||
close(client->fd);
|
||||
client->fd = -1;
|
||||
return -1;
|
||||
}
|
||||
memset(client->prev_output, 0, sizeof(client->prev_output));
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ipc_close(IPC_Client *client) {
|
||||
if (client->fd >= 0) close(client->fd);
|
||||
client->fd = -1;
|
||||
}
|
||||
|
||||
// Pulls one group's worth of bits (BITS_PER_GROUP), differentially encodes,
|
||||
// packs 8-to-a-byte, sends as opcode 112 with the stream index.
|
||||
int ipc_send_bits(IPC_Client *client, RDSEncoder *enc, uint8_t stream) {
|
||||
if (client->fd < 0) return -1;
|
||||
|
||||
uint8_t raw_bits[BITS_PER_GROUP];
|
||||
get_rds_bits(enc, raw_bits, stream);
|
||||
|
||||
uint8_t packed[(BITS_PER_GROUP + 7) / 8];
|
||||
memset(packed, 0, sizeof(packed));
|
||||
|
||||
uint8_t prev = client->prev_output[stream];
|
||||
for (int i = 0; i < BITS_PER_GROUP; i++) {
|
||||
uint8_t cur = prev ^ raw_bits[i]; // the differential step, moved here
|
||||
prev = cur;
|
||||
if (cur) packed[i / 8] |= (0x80 >> (i % 8));
|
||||
}
|
||||
client->prev_output[stream] = prev;
|
||||
|
||||
uint8_t msg[2 + sizeof(packed)];
|
||||
msg[0] = 112;
|
||||
msg[1] = stream;
|
||||
memcpy(msg + 2, packed, sizeof(packed));
|
||||
|
||||
ssize_t sent = send(client->fd, msg, sizeof(msg), 0);
|
||||
if (sent != (ssize_t)sizeof(msg)) {
|
||||
fprintf(stderr, "fm95 ipc: short/failed send\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t reply;
|
||||
if (recv(client->fd, &reply, 1, 0) <= 0) {
|
||||
fprintf(stderr, "fm95 ipc: no reply / disconnected\n");
|
||||
return -1;
|
||||
}
|
||||
if (reply == 2) fprintf(stderr, "fm95 reported bitring overrun on stream %d\n", stream);
|
||||
else if (reply == 1) fprintf(stderr, "fm95 rejected message (unknown opcode?)\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
#include <stdint.h>
|
||||
#include "rds.h" // for RDSEncoder, get_rds_bits, BITS_PER_GROUP
|
||||
|
||||
typedef struct {
|
||||
int fd;
|
||||
uint8_t prev_output[4]; // per-stream differential state
|
||||
} IPC_Client;
|
||||
|
||||
int ipc_connect(IPC_Client *client, const char *socket_path);
|
||||
void ipc_close(IPC_Client *client);
|
||||
int ipc_send_bits(IPC_Client *client, RDSEncoder *enc, uint8_t stream);
|
||||
+2
-6
@@ -118,18 +118,14 @@ uint8_t init_lua(RDSEncoder* _enc) {
|
||||
lua_newtable(globalL);
|
||||
lua_setfield(globalL, -2, "ps_transmission");
|
||||
lua_newtable(globalL);
|
||||
lua_setfield(globalL, -2, "pre_tx");
|
||||
lua_newtable(globalL);
|
||||
lua_setfield(globalL, -2, "group");
|
||||
lua_pushvalue(globalL, -1);
|
||||
hooks_ref = luaL_ref(globalL, LUA_REGISTRYINDEX);
|
||||
lua_setglobal(globalL, "hooks");
|
||||
|
||||
lua_newtable(globalL);
|
||||
lua_setglobal(globalL, "ext");
|
||||
|
||||
lua_newtable(globalL);
|
||||
|
||||
lua_newtable(globalL);
|
||||
lua_setfield(globalL, -2, "ext");
|
||||
|
||||
lua_pushinteger(globalL, EONs);
|
||||
lua_setfield(globalL, -2, "eon_count");
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
#include "modulator.h"
|
||||
#include "fs.h"
|
||||
|
||||
void init_rds_modulator(RDSModulator* rdsMod, RDSEncoder* enc, uint8_t num_streams) {
|
||||
memset(rdsMod, 0, sizeof(RDSModulator));
|
||||
rdsMod->num_streams = num_streams;
|
||||
|
||||
memset(enc, 0, sizeof(RDSEncoder));
|
||||
rdsMod->enc = enc;
|
||||
|
||||
rdsMod->data = (RDSModulatorModulationData*)calloc(num_streams, sizeof(RDSModulatorModulationData));
|
||||
if (rdsMod->data == NULL) {
|
||||
fprintf(stderr, "Error: Could not allocate memory for RDS modulation data\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < num_streams; i++) {
|
||||
rdsMod->data[i].symbol_shift = i * M_PI / 2.0f;
|
||||
rdsMod->data[i].bit_pos = BITS_PER_GROUP;
|
||||
}
|
||||
}
|
||||
|
||||
void cleanup_rds_modulator(RDSModulator* rdsMod) {
|
||||
if (rdsMod->data) {
|
||||
free(rdsMod->data);
|
||||
rdsMod->data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
float get_rds_sample(RDSModulator* rdsMod, uint8_t stream) {
|
||||
if(stream >= rdsMod->num_streams) return 0.0f;
|
||||
|
||||
rdsMod->data[stream].phase += 1187.5 / RDS_SAMPLE_RATE;
|
||||
|
||||
if (rdsMod->data[stream].phase >= 1.0f) {
|
||||
rdsMod->data[stream].phase -= 1.0f;
|
||||
if (rdsMod->data[stream].bit_pos == BITS_PER_GROUP) {
|
||||
get_rds_bits(rdsMod->enc, rdsMod->data[stream].bit_buffer, stream);
|
||||
rdsMod->data[stream].bit_pos = 0;
|
||||
}
|
||||
|
||||
rdsMod->data[stream].cur_bit = rdsMod->data[stream].bit_buffer[rdsMod->data[stream].bit_pos++];
|
||||
rdsMod->data[stream].prev_output = rdsMod->data[stream].cur_output;
|
||||
rdsMod->data[stream].cur_output = rdsMod->data[stream].prev_output ^ rdsMod->data[stream].cur_bit; // Something with differential encoding? Instead of encoding the data, encode if the bit of data changes
|
||||
}
|
||||
|
||||
float sample = sinf(M_2PI * rdsMod->data[stream].phase + rdsMod->data[stream].symbol_shift);
|
||||
if(rdsMod->data[stream].cur_output == 0) sample = -sample; // do bpsk, if you comment this part out, nothing will be decoded
|
||||
|
||||
return sample;
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
#pragma once
|
||||
#include "common.h"
|
||||
#include "lib.h"
|
||||
#include "rds.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t bit_buffer[BITS_PER_GROUP];
|
||||
uint8_t bit_pos : 7;
|
||||
uint8_t prev_output : 1;
|
||||
uint8_t cur_output : 1;
|
||||
uint8_t cur_bit : 1;
|
||||
float symbol_shift;
|
||||
float phase;
|
||||
} RDSModulatorModulationData;
|
||||
|
||||
typedef struct {
|
||||
RDSModulatorModulationData *data;
|
||||
RDSEncoder* enc;
|
||||
uint8_t num_streams;
|
||||
} RDSModulator;
|
||||
|
||||
void init_rds_modulator(RDSModulator* rdsMod, RDSEncoder* enc, uint8_t num_streams);
|
||||
void cleanup_rds_modulator(RDSModulator* rdsMod);
|
||||
float get_rds_sample(RDSModulator* rdsMod, uint8_t stream);
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "rds.h"
|
||||
#include "fs.h"
|
||||
#include "modulator.h"
|
||||
#include "lib.h"
|
||||
#include "lua_rds.h"
|
||||
#include <time.h>
|
||||
@@ -97,7 +96,7 @@ void get_rds_group(RDSEncoder* enc, RDSGroup *group, uint8_t stream) {
|
||||
time(&now);
|
||||
utc = gmtime(&now);
|
||||
|
||||
if(utc->tm_sec != enc->state[enc->program].last_second && stream == 0) {
|
||||
if(utc->tm_sec != enc->state[enc->program].last_second) {
|
||||
enc->state[enc->program].last_second = utc->tm_sec;
|
||||
lua_call_tfunction("tick");
|
||||
}
|
||||
@@ -112,6 +111,8 @@ void get_rds_group(RDSEncoder* enc, RDSGroup *group, uint8_t stream) {
|
||||
}
|
||||
}
|
||||
|
||||
lua_call_tfunction("pre_tx");
|
||||
|
||||
uint8_t good_group = 0;
|
||||
uint8_t grp_sqc_idx = 0;
|
||||
char grp;
|
||||
|
||||
+10
-24
@@ -2,13 +2,11 @@
|
||||
#include <signal.h>
|
||||
#include <getopt.h>
|
||||
#include <pthread.h>
|
||||
#include <pulse/simple.h>
|
||||
#include <pulse/error.h>
|
||||
#include "../inih/ini.h"
|
||||
|
||||
#include "rds.h"
|
||||
#include "ipc_client.h"
|
||||
#include "fs.h"
|
||||
#include "modulator.h"
|
||||
#include "udp_server.h"
|
||||
#include "tcp_server.h"
|
||||
#include "lib.h"
|
||||
@@ -49,8 +47,7 @@ static inline void show_help(char *name) {
|
||||
);
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
typedef struct {
|
||||
uint16_t udp_port;
|
||||
uint16_t tcp_port;
|
||||
char rds_device_name[48];
|
||||
@@ -201,28 +198,17 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
|
||||
if(config.asciig == 0) {
|
||||
int pulse_error;
|
||||
IPC_Client client;
|
||||
if (ipc_connect(&client, "/etc/fm95/ctl.socket") < 0) goto exit;
|
||||
|
||||
float *rds_buffer = (float*)malloc(NUM_MPX_FRAMES * config.num_streams * sizeof(float));
|
||||
if (rds_buffer == NULL) {
|
||||
fprintf(stderr, "Error: Could not allocate memory for RDS buffer\n");
|
||||
goto exit;
|
||||
while (!stop_rds) {
|
||||
for (uint8_t s = 0; s < config.num_streams; s++) {
|
||||
ipc_send_bits(&client, &rdsEncoder, s);
|
||||
}
|
||||
msleep((int)(1000.0 * BITS_PER_GROUP / 1187.5));
|
||||
}
|
||||
|
||||
while(!stop_rds) {
|
||||
for (uint16_t i = 0; i < NUM_MPX_FRAMES * config.num_streams; i++) {
|
||||
uint8_t stream = i % config.num_streams;
|
||||
if((rdsEncoder.enabled_streams > stream ? 1 : 0) == 0) rds_buffer[i] = 0.0f;
|
||||
rds_buffer[i] = get_rds_sample(&rdsModulator, stream);
|
||||
}
|
||||
|
||||
if (pa_simple_write(rds_device, rds_buffer, NUM_MPX_FRAMES * config.num_streams * sizeof(float), &pulse_error) != 0) {
|
||||
fprintf(stderr, "Error: could not play audio. (%s : %d)\n", pa_strerror(pulse_error), pulse_error);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free(rds_buffer);
|
||||
ipc_close(&client);
|
||||
} else {
|
||||
RDSGroup group;
|
||||
char output_buffer[1024];
|
||||
|
||||
Reference in New Issue
Block a user