ipc thing, and some more stuff i guess

This commit is contained in:
2026-07-11 13:37:41 +02:00
parent 564ea1c20e
commit 5bad2b8200
17 changed files with 271 additions and 264 deletions
+69
View File
@@ -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;
}
+11
View File
@@ -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
View File
@@ -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");
-51
View File
@@ -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;
}
-25
View File
@@ -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);
+3 -2
View File
@@ -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
View File
@@ -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];