Re-organized even more the repo, separated broadcast and arq

This commit is contained in:
Rafael Diniz 2025-08-12 02:10:25 +01:00
parent 17f3a3f99b
commit e517b31ca7
21 changed files with 231 additions and 57 deletions

View file

@ -1,12 +1,16 @@
.PHONY: all modem/freedv datalink audioio common clean
.PHONY: all modem datalink_arq datalink_broadcast audioio common clean
all: modem/freedv datalink audioio common
all: datalink_arq
modem/freedv:
$(MAKE) -C modem/freedv
modem:
$(MAKE) -C modem
datalink: modem/freedv common audioio
$(MAKE) -C datalink
# main is temporarily here, will be moved to a separate directory later
datalink_arq: modem common audioio datalink_broadcast
$(MAKE) -C datalink_arq
datalink_broadcast: modem common audioio
$(MAKE) -C datalink_broadcast
audioio:
$(MAKE) -C audioio
@ -15,7 +19,8 @@ common:
$(MAKE) -C common
clean:
$(MAKE) -C modem/freedv clean
$(MAKE) -C datalink clean
$(MAKE) -C modem clean
$(MAKE) -C datalink_arq clean
$(MAKE) -C datalink_broadcast clean
$(MAKE) -C audioio clean
$(MAKE) -C common clean

View file

@ -19,7 +19,7 @@
#include "ring_buffer_posix.h"
#include "shm_posix.h"
#include "../datalink/defines.h"
#include "../common/defines_modem.h"
#include "os_interop.h"
#include "audioio.h"

View file

@ -1,6 +1,6 @@
#ifndef HAVE_DEFINES_H
#define HAVE_DEFINES_H
#ifndef HAVE_DEFINES_MODEM_H
#define HAVE_DEFINES_MODEM_H
#define MAX_PATH 255
@ -26,4 +26,4 @@
#endif
#endif // HAVE_DEFINES_H
#endif // HAVE_DEFINES_MODEM_H

View file

@ -40,16 +40,16 @@ endif
CC = gcc
CFLAGS = -Wall -O2 -std=gnu11 -pthread -D_GNU_SOURCE -I../modem/freedv -I.. -I../audioio/ffaudio -I../common
CFLAGS = -Wall -O2 -std=gnu11 -pthread -D_GNU_SOURCE -I../modem/freedv -I../modem -I../datalink_broadcast -I.. -I../audioio/ffaudio -I../common
LDFLAGS=$(FFAUDIO_LINKFLAGS) -lm
all: ../mercury
../mercury: main.o arq.o net.o fsm.o arith.o crc6.o modem.o broadcast.o ../modem/freedv/libfreedvdata.a ../audioio/audioio.a \
../mercury: main.o arq.o net.o fsm.o arith.o crc6.o ../datalink_broadcast/broadcast.o ../modem/modem.o ../modem/freedv/libfreedvdata.a ../audioio/audioio.a \
../common/os_interop.o ../common/ring_buffer_posix.o ../common/shm_posix.o
$(CC) -o ../mercury \
main.o arq.o net.o fsm.o arith.o crc6.o modem.o broadcast.o ../modem/freedv/libfreedvdata.a ../audioio/audioio.a \
main.o arq.o net.o fsm.o arith.o crc6.o ../datalink_broadcast/broadcast.o ../modem/modem.o ../modem/freedv/libfreedvdata.a ../audioio/audioio.a \
../common/os_interop.o ../common/ring_buffer_posix.o ../common/shm_posix.o $(LDFLAGS)
main.o: main.c
@ -70,11 +70,5 @@ arith.o: arith.c
crc6.o: crc6.c
$(CC) $(CFLAGS) -c crc6.c
modem.o: modem.c
$(CC) $(CFLAGS) -c modem.c
broadcast.o: broadcast.c
$(CC) $(CFLAGS) -c broadcast.c
clean:
rm -f *.o

View file

@ -25,7 +25,7 @@
#include "fsm.h"
#include "../audioio/audioio.h"
#include "net.h"
#include "defines.h"
#include "defines_modem.h"
extern cbuf_handle_t capture_buffer;
extern cbuf_handle_t playback_buffer;

View file

@ -36,7 +36,7 @@
#include "arq.h"
#include "modem.h"
#include "broadcast.h"
#include "defines.h"
#include "defines_modem.h"
#include "audioio/audioio.h"
extern cbuf_handle_t capture_buffer;
@ -318,14 +318,13 @@ int main(int argc, char *argv[])
return EXIT_SUCCESS;
}
struct freedv *freedv = NULL;
pthread_t radio_capture;
pthread_t radio_playback;
generic_modem_t g_modem;
pthread_t radio_capture, radio_playback;
if (audio_system == AUDIO_SUBSYSTEM_SHM)
{
printf("Initializing I/O from Shared Memory (SHM)\n");
init_modem(&freedv, mod_config, 1, &radio_capture, &radio_playback); // frames per burst is 1 for now
init_modem(&g_modem, mod_config, 1); // frames per burst is 1 for now
}
else
{
@ -337,11 +336,11 @@ int main(int argc, char *argv[])
// arq_init(base_tcp_port, mod_config);
// we block here
broadcast_run(freedv, broadcast_port);
broadcast_run(&g_modem, broadcast_port);
if (audio_system == AUDIO_SUBSYSTEM_SHM)
{
shutdown_modem(freedv, &radio_capture, &radio_playback);
shutdown_modem(&g_modem);
}
else
{

View file

@ -0,0 +1,13 @@
CC=gcc
CFLAGS=-Wall -O2 -std=gnu11 -pthread -D_GNU_SOURCE=1 -I../modem -I../modem/freedv -I../common -I../datalink_arq
all: broadcast.o kiss.o
kiss.o: kiss.c
$(CC) $(CFLAGS) -c kiss.c
broadcast.o: broadcast.c
$(CC) $(CFLAGS) -c broadcast.c
clean:
rm *.o

View file

@ -28,9 +28,10 @@
#include <arpa/inet.h>
#include "modem.h"
#include "defines.h"
#include "ring_buffer_posix.h"
#include "arq.h"
#include "defines_modem.h"
#include "ring_buffer_posix.h"
extern cbuf_handle_t data_tx_buffer;
extern cbuf_handle_t data_rx_buffer;
@ -39,9 +40,9 @@ extern bool shutdown_; // global shutdown flag
extern arq_info arq_conn; // ARQ connection info
// Function to handle TX logic
void *broadcast_tx_thread(void *freedv_ptr)
void *broadcast_tx_thread(void *g_modem)
{
struct freedv *freedv = (struct freedv *)freedv_ptr;
struct freedv *freedv = ((generic_modem_t *)g_modem)->freedv;
size_t bytes_per_modem_frame = freedv_get_bits_per_modem_frame(freedv) / 8;
uint8_t *data = (uint8_t *)malloc(bytes_per_modem_frame);
@ -65,7 +66,7 @@ void *broadcast_tx_thread(void *freedv_ptr)
read_buffer(data_tx_buffer, data, bytes_per_modem_frame);
// Transmit the data
send_modulated_data(freedv, data, 1);
send_modulated_data(g_modem, data, 1);
usleep(5000000); // 5s for now - TODO !!! some delay for transmission
}
}
@ -75,9 +76,9 @@ void *broadcast_tx_thread(void *freedv_ptr)
}
// Function to handle RX logic
void *broadcast_rx_thread(void *freedv_ptr)
void *broadcast_rx_thread(void *g_modem)
{
struct freedv *freedv = (struct freedv *)freedv_ptr;
struct freedv *freedv = ((generic_modem_t *)g_modem)->freedv;
size_t bytes_per_modem_frame = freedv_get_bits_per_modem_frame(freedv) / 8;
uint8_t *data = (uint8_t *)malloc(bytes_per_modem_frame);
size_t nbytes_out = 0;
@ -93,7 +94,7 @@ void *broadcast_rx_thread(void *freedv_ptr)
if (arq_conn.TRX == RX)
{
// Receive data
receive_modulated_data(freedv, data, &nbytes_out);
receive_modulated_data(g_modem, data, &nbytes_out);
if (nbytes_out > 0)
{
write_buffer(data_rx_buffer, data, nbytes_out);
@ -156,7 +157,7 @@ void *tcp_server_thread(void *port_ptr)
printf("Client connected.\n");
uint8_t *buffer = (uint8_t *)malloc(DATA_TX_BUFFER_SIZE);
uint8_t *buffer = (uint8_t *)malloc(DATA_TX_BUFFER_SIZE);;
if (!buffer)
{
fprintf(stderr, "Failed to allocate memory for TCP buffer.\n");
@ -211,15 +212,15 @@ void *tcp_server_thread(void *port_ptr)
}
// Main function to handle broadcast operations
void broadcast_run(struct freedv *freedv, int tcp_port)
void broadcast_run(generic_modem_t *g_modem, int tcp_port)
{
printf("Starting broadcast system...\n");
pthread_t tx_thread, rx_thread, server_thread;
// Create TX and RX threads
pthread_create(&tx_thread, NULL, broadcast_tx_thread, (void *)freedv);
pthread_create(&rx_thread, NULL, broadcast_rx_thread, (void *)freedv);
pthread_create(&tx_thread, NULL, broadcast_tx_thread, (void *)g_modem);
pthread_create(&rx_thread, NULL, broadcast_rx_thread, (void *)g_modem);
// Create TCP server thread
pthread_create(&server_thread, NULL, tcp_server_thread, (void *)&tcp_port);

View file

@ -23,7 +23,7 @@
#include <stdint.h>
#include <stdbool.h>
#include "freedv_api.h"
#include "modem.h"
/* Function declarations */
@ -33,7 +33,7 @@
* @param freedv Pointer to the FreeDV structure.
* @param tcp_port The TCP port to use for the server.
*/
void broadcast_run(struct freedv *freedv, int tcp_port);
void broadcast_run(generic_modem_t *g_modem, int tcp_port);
#endif // BROADCAST_H_

101
datalink_broadcast/kiss.c Normal file
View file

@ -0,0 +1,101 @@
/* KISS framer
*
* Copyright (C) 2020-2024 Rhizomatica
* Author: Rafael Diniz <rafael@rhizomatica.org>
*
* SPDX-License-Identifier: GPL-3.0-or-later
*
*/
#include <unistd.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include "kiss.h"
int frame_len;
bool IN_FRAME;
bool ESCAPE;
uint8_t kiss_command = CMD_UNKNOWN;
uint8_t frame_buffer[MAX_PAYLOAD];
uint8_t write_buffer[MAX_PAYLOAD*2+3];
void kiss_frame_received(int frame_len)
{
// do something here...
int written = write(1, frame_buffer, frame_len);
}
void kiss_read(uint8_t sbyte)
{
if (IN_FRAME && sbyte == FEND && kiss_command == CMD_DATA)
{
IN_FRAME = false;
kiss_frame_received(frame_len);
return;
}
if (sbyte == FEND)
{
IN_FRAME = true;
kiss_command = CMD_UNKNOWN;
frame_len = 0;
return;
}
if (IN_FRAME && frame_len < MAX_PAYLOAD)
{
// Have a look at the command byte first
if (frame_len == 0 && kiss_command == CMD_UNKNOWN)
{
// Strip of port nibble
kiss_command = sbyte & 0x0F;
return;
}
if (kiss_command == CMD_DATA)
{
if (sbyte == FESC)
{
ESCAPE = true;
return;
}
if (ESCAPE)
{
if (sbyte == TFEND) sbyte = FEND;
if (sbyte == TFESC) sbyte = FESC;
ESCAPE = false;
}
if (frame_len < MAX_PAYLOAD)
{
frame_buffer[frame_len++] = sbyte;
}
}
}
}
int kiss_write_frame(uint8_t* buffer, int frame_len)
{
int write_len = 0;
write_buffer[write_len++] = FEND;
write_buffer[write_len++] = CMD_DATA;
for (int i = 0; i < frame_len; i++)
{
uint8_t byte = buffer[i];
switch(byte)
{
case FEND:
write_buffer[write_len++] = FESC;
write_buffer[write_len++] = TFEND;
break;
case FESC:
write_buffer[write_len++] = FESC;
write_buffer[write_len++] = TFESC;
break;
default:
write_buffer[write_len++] = byte;
}
}
write_buffer[write_len++] = FEND;
// TODO: write the buffer somewhere...
return write(1, write_buffer, write_len);
}

38
datalink_broadcast/kiss.h Normal file
View file

@ -0,0 +1,38 @@
/* KISS framer
*
* Copyright (C) 2020-2024 Rhizomatica
* Author: Rafael Diniz <rafael@rhizomatica.org>
*
* SPDX-License-Identifier: GPL-3.0-or-later
*
*/
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#define FEND 0xC0
#define FESC 0xDB
#define TFEND 0xDC
#define TFESC 0xDD
#define CMD_UNKNOWN 0xFE
#define CMD_AX25 0x00 // AX25 Frame (standard) in VARA
#define CMD_AX25CALLSIGN 0x01 // AX25 Frame (7 chrs Call Signs) in VARA
#define CMD_DATA 0x02 // VARA / Mercury unformatted frame
#define CMD_RQ_CONFIG 0x03 // Mercury special fountain code configuration frame
#define CMD_RQ_PAYLOAD 0x04 // Fountain code payload
#define MAX_PAYLOAD 756 // ~ 18 frames at VARA Level 4
void kiss_read(uint8_t sbyte);
int kiss_write_frame(uint8_t* buffer, int frame_len);
#ifdef __cplusplus
};
#endif

16
modem/Makefile Normal file
View file

@ -0,0 +1,16 @@
CFLAGS=-D_GNU_SOURCE=1 -I. -I../common -I../modem -I../modem/freedv -I../datalink_arq -Wall -Wno-strict-overflow -std=gnu11 -fPIC -O2
CC=gcc
.PHONY: all freedv
all: freedv modem.o
freedv:
$(MAKE) -C freedv
modem.o: modem.c modem.h
$(CC) $(CFLAGS) -c modem.c
clean:
$(MAKE) -C freedv clean
rm -f *.o

View file

@ -34,7 +34,7 @@
#include "ldpc_codes.h"
#include "ofdm_internal.h"
#include "defines.h"
#include "defines_modem.h"
extern bool shutdown_; // global shutdown flag
@ -45,7 +45,7 @@ cbuf_handle_t data_tx_buffer;
cbuf_handle_t data_rx_buffer;
int init_modem(struct freedv **freedv, int mode, int frames_per_burst, pthread_t *radio_capture, pthread_t *radio_playback)
int init_modem(generic_modem_t *g_modem, int mode, int frames_per_burst)
{
// connect to shared memory buffers
try_shm_connect1:
@ -72,21 +72,21 @@ try_shm_connect2:
data_tx_buffer = circular_buf_init(buffer_tx, DATA_TX_BUFFER_SIZE);
data_rx_buffer = circular_buf_init(buffer_rx, DATA_RX_BUFFER_SIZE);
printf("Created data buffers for TX and RX.\n");
char codename[80] = "H_256_512_4";
struct freedv_advanced adv = {0, 2, 100, 8000, 1000, 200, codename};
if (mode == FREEDV_MODE_FSK_LDPC)
*freedv = freedv_open_advanced(mode, &adv);
g_modem->freedv = freedv_open_advanced(mode, &adv);
else
*freedv = freedv_open(mode);
g_modem->freedv = freedv_open(mode);
freedv_set_frames_per_burst(*freedv, frames_per_burst);
freedv_set_frames_per_burst(g_modem->freedv, frames_per_burst);
return 0;
}
int shutdown_modem(struct freedv *freedv, pthread_t *radio_capture, pthread_t *radio_playback)
int shutdown_modem(generic_modem_t *g_modem)
{
circular_buf_destroy_shm(capture_buffer, SIGNAL_BUFFER_SIZE, SIGNAL_INPUT);
circular_buf_destroy_shm(playback_buffer, SIGNAL_BUFFER_SIZE, SIGNAL_OUTPUT);
@ -98,13 +98,14 @@ int shutdown_modem(struct freedv *freedv, pthread_t *radio_capture, pthread_t *r
circular_buf_free(data_tx_buffer);
circular_buf_free(data_rx_buffer);
freedv_close(freedv);
freedv_close(g_modem->freedv);
return 0;
}
int send_modulated_data(struct freedv *freedv, uint8_t *bytes_in, int frames_per_burst)
int send_modulated_data(generic_modem_t *g_modem, uint8_t *bytes_in, int frames_per_burst)
{
struct freedv *freedv = g_modem->freedv;
size_t bytes_per_modem_frame = freedv_get_bits_per_modem_frame(freedv) / 8;
size_t payload_bytes_per_modem_frame = bytes_per_modem_frame - 2; /* 16 bits used for the CRC */
size_t n_mod_out = freedv_get_n_tx_modem_samples(freedv);
@ -155,8 +156,9 @@ int send_modulated_data(struct freedv *freedv, uint8_t *bytes_in, int frames_per
return 0;
}
int receive_modulated_data(struct freedv *freedv, uint8_t *bytes_out, size_t *nbytes_out)
int receive_modulated_data(generic_modem_t *g_modem, uint8_t *bytes_out, size_t *nbytes_out)
{
struct freedv *freedv = g_modem->freedv;
size_t bytes_per_modem_frame = freedv_get_bits_per_modem_frame(freedv) / 8;
size_t payload_bytes_per_modem_frame = bytes_per_modem_frame - 2; /* 16 bits used for the CRC */

View file

@ -27,14 +27,19 @@
#include "freedv_api.h"
int init_modem(struct freedv **freedv, int mode, int frames_per_burst, pthread_t *radio_capture, pthread_t *radio_playback);
typedef struct generic_modem {
struct freedv *freedv;
void *future_extension; // Placeholder for future extensions
} generic_modem_t;
int shutdown_modem(struct freedv *freedv, pthread_t *radio_capture, pthread_t *radio_playback);
int init_modem(generic_modem_t *g_modem, int mode, int frames_per_burst);
int shutdown_modem(generic_modem_t *g_modem);
// always send the frame size in bytes_in
int send_modulated_data(struct freedv *freedv, uint8_t *bytes_in, int frames_per_burst);
int send_modulated_data(generic_modem_t *g_modem, uint8_t *bytes_in, int frames_per_burst);
int receive_modulated_data(struct freedv *freedv, uint8_t *bytes_out, size_t *nbytes_out);
int receive_modulated_data(generic_modem_t *g_modem, uint8_t *bytes_out, size_t *nbytes_out);
#endif // MODEM_H