changeset 51:db39e8855f3d

ater: implement play-d144
author Mychaela Falconia <falcon@freecalypso.org>
date Wed, 25 Sep 2024 05:53:38 +0000
parents 6ba4de500532
children 626180a15857
files ater/globals.h ater/play_cmd.c ater/read_file.c ater/read_file.h ater/tx_func.c ater/user_cmd.c
diffstat 6 files changed, 138 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/ater/globals.h	Tue Sep 24 06:15:40 2024 +0000
+++ b/ater/globals.h	Wed Sep 25 05:53:38 2024 +0000
@@ -20,6 +20,7 @@
 void cmd_activate_csd(int argc, char **argv);
 void cmd_deact(int argc, char **argv);
 void cmd_play_file(int argc, char **argv);
+void cmd_play_d144(int argc, char **argv);
 void cmd_play_stop(int argc, char **argv);
 void cmd_set_dbits(int argc, char **argv);
 void cmd_set_edata(int argc, char **argv);
--- a/ater/play_cmd.c	Tue Sep 24 06:15:40 2024 +0000
+++ b/ater/play_cmd.c	Wed Sep 25 05:53:38 2024 +0000
@@ -47,6 +47,38 @@
 	at->play_wait_align = true;
 }
 
+void cmd_play_d144(int argc, char **argv)
+{
+	int nr, rc;
+	struct ater_subslot *at;
+
+	if (argc != 3) {
+usage:		fprintf(stderr, "usage: %s 0|1|2|3 play-file.bin\n", argv[0]);
+		return;
+	}
+	if (argv[1][0] < '0' || argv[1][0] > '3' || argv[1][1])
+		goto usage;
+	nr = argv[1][0] - '0';
+	at = &subslots[nr];
+	if (!at->is_active) {
+		fprintf(stderr, "error: subslot %d is not active\n", nr);
+		return;
+	}
+	if (!at->is_data_144) {
+		fprintf(stderr, "error: subslot %d is not in D144 mode\n", nr);
+		return;
+	}
+	if (at->play_buffer) {
+		fprintf(stderr, "error: file play already in progress\n");
+		return;
+	}
+	rc = read_binary_file_d144(argv[2], &at->play_buffer,
+				   &at->play_buf_total);
+	if (rc < 0)
+		return;		/* error msg already printed */
+	at->play_buf_ptr = 0;
+}
+
 void cmd_play_stop(int argc, char **argv)
 {
 	int nr;
--- a/ater/read_file.c	Tue Sep 24 06:15:40 2024 +0000
+++ b/ater/read_file.c	Wed Sep 25 05:53:38 2024 +0000
@@ -96,3 +96,68 @@
 	*size_ret = nframes;
 	return 0;
 }
+
+static int check_magic_d144(const uint8_t *buf, unsigned nframes)
+{
+	unsigned n;
+
+	for (n = 0; n < nframes; n++) {
+		if (*buf != 0xD4)
+			return -1;
+		buf += 38;
+	}
+	return 0;
+}
+
+int read_binary_file_d144(const char *filename, uint8_t **bufret,
+			  unsigned *size_ret)
+{
+	int fd, rc;
+	struct stat st;
+	uint8_t *buf;
+	unsigned nframes;
+
+	fd = open(filename, O_RDONLY);
+	if (fd < 0) {
+		perror(filename);
+		return -1;
+	}
+	fstat(fd, &st);
+	if (!S_ISREG(st.st_mode)) {
+		close(fd);
+		fprintf(stderr, "error: %s is not a regular file\n", filename);
+		return -1;
+	}
+	if (!st.st_size) {
+		close(fd);
+		fprintf(stderr, "error: %s is an empty file\n", filename);
+		return -1;
+	}
+	if (st.st_size % 38) {
+		close(fd);
+		fprintf(stderr,
+			"error: size of %s is not a multiple of 38 bytes\n",
+			filename);
+		return -1;
+	}
+	buf = malloc(st.st_size);
+	if (!buf) {
+		close(fd);
+		fprintf(stderr, "unable to malloc buffer for %s\n", filename);
+		return -1;
+	}
+	read(fd, buf, st.st_size);
+	close(fd);
+	nframes = st.st_size / 38;
+
+	rc = check_magic_d144(buf, nframes);
+	if (rc < 0) {
+		free(buf);
+		fprintf(stderr, "error: %s is not a valid D144 test file\n",
+			filename);
+		return -1;
+	}
+	*bufret = buf;
+	*size_ret = nframes;
+	return 0;
+}
--- a/ater/read_file.h	Tue Sep 24 06:15:40 2024 +0000
+++ b/ater/read_file.h	Wed Sep 25 05:53:38 2024 +0000
@@ -10,3 +10,6 @@
 
 int read_binary_file(const char *filename, bool is_efr, uint8_t **bufret,
 		     unsigned *size_ret);
+
+int read_binary_file_d144(const char *filename, uint8_t **bufret,
+			  unsigned *size_ret);
--- a/ater/tx_func.c	Tue Sep 24 06:15:40 2024 +0000
+++ b/ater/tx_func.c	Wed Sep 25 05:53:38 2024 +0000
@@ -9,6 +9,7 @@
 #include <string.h>
 #include <unistd.h>
 
+#include <osmocom/core/bits.h>
 #include <osmocom/core/msgb.h>
 #include <osmocom/core/select.h>
 #include <osmocom/isdn/i460_mux.h>
@@ -136,11 +137,46 @@
 	memset(fr->d_bits, 1, 63 * 4);
 }
 
+static void d144_play_frame(struct ater_subslot *at, const uint8_t *filerec)
+{
+	struct osmo_trau_frame *fr = &at->ul_frame;
+	struct msgb *msg;
+	int len;
+
+	msg = msgb_alloc_c(g_ctx, 320, "TRAU-UL-frame");
+	if (!msg)
+		return;
+	fr->type = OSMO_TRAU16_FT_EDATA;
+	fr->dir = OSMO_TRAU_DIR_UL;
+	fr->c_bits[5] = 0;
+	memset(fr->c_bits + 6, 1, 7);
+	fr->m_bits[0] = (filerec[1] & 2) >> 1;
+	fr->m_bits[1] = filerec[1] & 1;
+	osmo_pbit2ubit(fr->d_bits, filerec + 2, 288);
+	len = osmo_trau_frame_encode(msg->tail, msgb_tailroom(msg), fr);
+	if (len <= 0) {
+		msgb_free(msg);
+		return;
+	}
+	msgb_put(msg, len);
+	osmo_i460_mux_enqueue(at->schan, msg);
+}
+
 static void handle_d144(int nr)
 {
 	struct ater_subslot *at = &subslots[nr];
 	struct msgb *msg;
 
+	if (at->play_buffer) {
+		d144_play_frame(at, at->play_buffer + at->play_buf_ptr * 38);
+		at->play_buf_ptr++;
+		if (at->play_buf_ptr < at->play_buf_total)
+			return;
+		free(at->play_buffer);
+		at->play_buffer = NULL;
+		printf("file play finished\n");
+		return;
+	}
 	msg = msgb_alloc_c(g_ctx, 320, "TRAU-UL-frame");
 	if (!msg)
 		return;
--- a/ater/user_cmd.c	Tue Sep 24 06:15:40 2024 +0000
+++ b/ater/user_cmd.c	Wed Sep 25 05:53:38 2024 +0000
@@ -23,6 +23,7 @@
 	{"dset", cmd_set_dbits},
 	{"edata", cmd_set_edata},
 	{"play", cmd_play_file},
+	{"play-d144", cmd_play_d144},
 	{"play-stop", cmd_play_stop},
 	{"print-rx", cmd_print_rx},
 	{"record", cmd_record_start},