summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2004-04-18 01:35:53 +0000
committerLennart Poettering <lennart@poettering.net>2004-04-18 01:35:53 +0000
commit783b56d54788f177881d68ae2ec7a7cb4bb38ac4 (patch)
tree77555207fa13c137e0c8dab8726f2ed96538e075
parentf069d236c79a7cb89542eba5ddc454d03ead5394 (diff)
Initial commit
git-svn-id: file:///home/lennart/svn/public/vfax/trunk@3 541b366f-4dd8-0310-ae39-b2612fd50714
-rw-r--r--Makefile15
-rw-r--r--bitsplit.c104
-rw-r--r--bitsplit.h21
-rw-r--r--interpol.c139
-rw-r--r--interpol.h17
-rw-r--r--main.c87
-rw-r--r--resample.c147
-rw-r--r--resample.h12
-rw-r--r--util.c21
-rw-r--r--util.h8
-rw-r--r--v17dem.c102
-rw-r--r--v17mod.c206
-rw-r--r--v17mod.h22
-rw-r--r--v17tcm.c109
-rw-r--r--v17tcm.h15
15 files changed, 1025 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..45cc029
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,15 @@
+CFLAGS=-pipe -O0 -W -Wall -g -DTEST=7 -D_GNU_SOURCE
+CC=gcc
+LIBS=-lm
+
+all: main
+
+*.o: Makefile
+
+main: main.o v17tcm.o v17mod.o bitsplit.o util.o interpol.o resample.o
+ $(CC) -o $@ $^ $(LIBS)
+
+clean:
+ rm -f main *.o
+
+.PHONY: clean
diff --git a/bitsplit.c b/bitsplit.c
new file mode 100644
index 0000000..ee2074b
--- /dev/null
+++ b/bitsplit.c
@@ -0,0 +1,104 @@
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "bitsplit.h"
+#include "util.h"
+
+void bitsplit_init(struct bitsplit_state *s, int maxbits_in, int maxbits_out) {
+ assert(s && maxbits_in && maxbits_out);
+ assert(maxbits_in <= 8 && maxbits_out <= 8);
+
+ memset(s, 0, sizeof(struct bitsplit_state));
+ s->maxbits_in = maxbits_in;
+ s->maxbits_out = maxbits_out;
+}
+
+inline static int read_next_bit(struct bitsplit_state *s, uint8_t **src) {
+ assert(s);
+
+ if (!s->n_in) {
+ s->in = **src;
+ (*src)++;
+ s->n_in = s->maxbits_in;
+ }
+
+ return (s->in >> (-- (s->n_in))) & 1;
+}
+
+inline static void write_next_bit(struct bitsplit_state *s, uint8_t **dst, int bit) {
+ assert(s);
+
+ s->out = (s->out << 1) | (bit & 1);
+ s->n_out++;
+
+ if (s->n_out >= s->maxbits_out) {
+ **dst = s->out;
+ s->out = 0;
+ (*dst)++;
+ s->n_out = 0;
+ }
+}
+
+void bitsplit(struct bitsplit_state *s, uint8_t *src, size_t *src_l, uint8_t *dst, size_t *dst_l) {
+ uint8_t *save_dst = dst, *save_src = src;
+
+ assert(s && src && dst && src_l && dst_l);
+
+ while ((src < save_src+*src_l /*|| s->n_in*/) && (dst < save_dst+*dst_l /*|| s->n_out < s->maxbits_out*/)) {
+ int bit;
+
+ bit = read_next_bit(s, &src);
+ write_next_bit(s, &dst, bit);
+ }
+
+ *src_l = src - save_src;
+ *dst_l = dst - save_dst;
+}
+
+#if (TEST == 4)
+
+int main(int argc, char *argv[]) {
+ struct bitsplit_state s;
+
+ assert(argc >= 3);
+
+ bitsplit_init(&s, atoi(argv[1]), atoi(argv[2]));
+
+ for (;;) {
+ uint8_t in[1024];
+ uint8_t *i;
+
+ ssize_t r;
+
+ r = read(0, in, sizeof(in));
+ assert(r >= 0);
+
+ if (r == 0)
+ break;
+
+ i = in;
+
+ while (r) {
+ uint8_t out[1024];
+ size_t outl = sizeof(out);
+ size_t il = r;
+ ssize_t r2;
+
+ bitsplit(&s, i, &il, out, &outl);
+ i += il;
+ r -= il;
+
+ if (outl) {
+ r2 = loop_write(1, out, outl);
+ assert(r2 > 0);
+ }
+ }
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/bitsplit.h b/bitsplit.h
new file mode 100644
index 0000000..8a53f3e
--- /dev/null
+++ b/bitsplit.h
@@ -0,0 +1,21 @@
+#ifndef foobitsplithfoo
+#define foobitsplithfoo
+
+#include <inttypes.h>
+#include <sys/types.h>
+
+struct bitsplit_state {
+ uint8_t in;
+ int n_in;
+ int maxbits_in;
+
+ uint8_t out;
+ int n_out;
+ int maxbits_out;
+};
+
+
+void bitsplit_init(struct bitsplit_state *s, int maxbits_in, int maxbits_out);
+void bitsplit(struct bitsplit_state *s, uint8_t *src, size_t *src_l, uint8_t *dst, size_t *dst_l);
+
+#endif
diff --git a/interpol.c b/interpol.c
new file mode 100644
index 0000000..fb710c4
--- /dev/null
+++ b/interpol.c
@@ -0,0 +1,139 @@
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+#include <stdio.h>
+
+#include "interpol.h"
+#include "util.h"
+
+void interpol_init(struct interpol_state *s, int frac, int radius) {
+ int l;
+ assert(s && frac);
+
+ memset(s, 0, sizeof(struct interpol_state));
+
+ s->frac = frac;
+
+ s->radius = radius;
+ s->coeff = malloc((l = s->radius*frac)*sizeof(float));
+ s->coeff_valid = malloc(l*sizeof(int));
+
+ assert(s->coeff_valid && s->coeff);
+
+ memset(s->coeff_valid, 0, l*sizeof(int));
+}
+
+void interpol_done(struct interpol_state *s) {
+ assert(s);
+ free(s->coeff);
+ free(s->coeff_valid);
+}
+
+static float sinc(struct interpol_state *s, int x) {
+ assert(s);
+
+ if (x == 0)
+ return 1;
+
+ if (x < 0)
+ x = -x;
+
+ if (x >= s->frac * s->radius)
+ return 0;
+
+ if (!s->coeff_valid[x]) {
+ float fx = ((float) x)/s->frac;
+ float hanning = .5*(1+cos(M_PI * fx / s->radius));
+ float _sinc = sin(M_PI * fx) / M_PI / fx;
+
+ /*fprintf(stderr, "%2.10f %2.10f %2.10f\n", fx, hanning, _sinc);*/
+
+ assert(_sinc <= 1);
+ assert(_sinc >= -1);
+ assert(hanning >= 0);
+ assert(hanning <= 1);
+
+
+ s->coeff[x] = hanning * _sinc;
+ s->coeff_valid[x] = 1;
+ }
+
+ return s->coeff[x];
+}
+
+float interpol_get(struct interpol_state *s, float *p, int l, float x) {
+ int i, j, z, d, n;
+ float sum;
+
+ assert(s && p && l);
+
+ i = (int) roundf(x*s->frac); /* x in units of 1/fracs */
+ z = i/s->frac; /* index of sample left of x */
+ j = z*s->frac; /* index of sample left of x in units of 1/fracs */
+ d = i-j;
+
+ sum = 0;
+
+ for (n = -s->radius; n <= s->radius; n++) {
+ int k = z + n; /* sample of current sinc pulse */
+
+ if (k < 0 || k >= l)
+ fprintf(stderr, "interpol.c: index out of bound: %i not in 0...%i\n", k, l);
+ else {
+/*
+ char txt[2];
+ snprintf(txt, sizeof(txt), "%f", p[k]);
+ fprintf(stderr, "%i %i\r", k, l);
+*/
+ sum += p[k] * sinc(s, -n*s->frac + d);
+ }
+ }
+
+ return sum;
+}
+
+#if (TEST == 5)
+
+int main() {
+ struct interpol_state s;
+ int x;
+ int frac = 9;
+
+ interpol_init(&s, frac);
+
+ for (x = -10*frac; x <= 10*frac; x ++) {
+ fprintf(stderr, "%2.5f -> %2.5f\n", (float)x/frac, sinc(&s, x));
+ }
+
+ interpol_done(&s);
+
+ return 0;
+}
+
+#endif
+
+#if (TEST == 6)
+
+int main() {
+ struct interpol_state s;
+ float buf[1024], x;
+ int i, frac = 37;
+
+ interpol_init(&s, frac);
+
+ for (i = 0; i < 1024; i++)
+ buf[i] = 1;
+
+ for (x = 0; x < 1024; x += 0.1) {
+ float y = interpol_get(&s, buf, 1024, x);
+ //loop_write(1, &y, sizeof(float));
+ fprintf(stderr, "%2.10f => %2.10f\n", x, y);
+ }
+
+ interpol_done(&s);
+
+ return 0;
+}
+
+#endif
diff --git a/interpol.h b/interpol.h
new file mode 100644
index 0000000..e4ba740
--- /dev/null
+++ b/interpol.h
@@ -0,0 +1,17 @@
+#ifndef foointerpolhfoo
+#define foointerpolhfoo
+
+struct interpol_state {
+ int frac;
+ float *coeff;
+ int *coeff_valid;
+ int radius;
+};
+
+
+void interpol_init(struct interpol_state *s, int frac, int radius);
+void interpol_done(struct interpol_state *s);
+
+float interpol_get(struct interpol_state *s, float *p, int l, float x);
+
+#endif
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..5356f47
--- /dev/null
+++ b/main.c
@@ -0,0 +1,87 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <assert.h>
+
+#include "v17mod.h"
+#include "v17tcm.h"
+#include "util.h"
+
+int16_t *conv_float_16sle(float *p, int l) {
+ int i;
+ int16_t *r = (int16_t*) p, *target = (int16_t*) p;
+
+ assert(2*sizeof(int16_t) == sizeof(float));
+
+ for (i = 0; i < l; i++) {
+ int v = (int) (0x3FFF * *p);
+
+ if (v < -0x8000) {
+ v = -0x8000;
+ fprintf(stderr, "UNDERFLOW: %f\n", *p);
+ }
+
+ if (v > 0x7fff) {
+ v = 0x7fff;
+ fprintf(stderr, "OVERFLOW\n");
+ }
+
+
+ *(target++) = (int16_t) v;
+ *(target++) = (int16_t) v;
+
+ p++;
+ }
+
+ return r;
+}
+
+#ifndef TEST
+
+int main() {
+ struct v17mod_state mod;
+ struct v17tcm_state tcm;
+
+ v17mod_init(&mod);
+ v17tcm_init(&tcm);
+
+ for (;;) {
+ ssize_t l;
+ uint8_t buf[64];
+ int i, n;
+ float f[1024];
+
+ //fprintf(stderr, "ITERATE\n");
+
+ if ((l = read(0, buf, sizeof(buf))) <= 0) {
+ //if (l < 0)
+ fprintf(stderr, "read failure\n");
+
+
+ goto finish;
+ }
+
+ for (i = 0; i < l; i++)
+ buf[i] = v17tcm_encode(&tcm, buf[i] & 7);
+
+ v17mod_push(&mod, buf, l);
+
+ n = v17mod_pull(&mod, f, sizeof(f)/sizeof(float));
+
+
+
+ if (loop_write(1, conv_float_16sle(f, n), n*sizeof(int16_t)*2) < 0) {
+ fprintf(stderr, "write failure\n");
+ goto finish;
+ }
+ }
+
+
+finish:
+
+ v17mod_done(&mod);
+
+ return 0;
+}
+
+#endif
diff --git a/resample.c b/resample.c
new file mode 100644
index 0000000..ee9e540
--- /dev/null
+++ b/resample.c
@@ -0,0 +1,147 @@
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+#include <math.h>
+#include <inttypes.h>
+
+#include "resample.h"
+#include "interpol.h"
+
+#define SINC_RADIUS 10
+
+struct resample_state {
+ float delta;
+
+ int sfreq, dfreq;
+ struct interpol_state interpol;
+};
+
+
+static int lcd(int a, int b) {
+ assert(a >= 1 && b >= 1);
+
+ while (a != b) {
+ while (a > b) {
+ a = a-b;
+ }
+
+ while (b > a) {
+ b = b-a;
+ }
+ }
+
+ return a;
+}
+
+void resample_init(struct resample_state *s) {
+ assert(s);
+ memset(s, 0, sizeof(struct resample_state));
+ s->sfreq = s->dfreq = -1;
+}
+
+void resample_done(struct resample_state *s) {
+ assert(s);
+ interpol_done(&s->interpol);
+}
+
+void resample_get(struct resample_state *s, float* sp, int *sl, float *dp, int *dl, int sfreq, int dfreq) {
+ int di;
+ float x = 0;
+
+ assert(s && sp && dp && sfreq > 0 && dfreq > 0);
+ assert(*sl > 0);
+ assert(*dl > 0);
+
+ if (sfreq != s->sfreq || dfreq != s->dfreq) {
+ interpol_done(&s->interpol);
+ interpol_init(&s->interpol, dfreq/lcd(sfreq,dfreq), SINC_RADIUS);
+ s->sfreq = sfreq;
+ s->dfreq = dfreq;
+ }
+
+ di = 0;
+ while (di < *dl) {
+ x = (float) di*sfreq/dfreq + s->delta;
+
+ if (x + SINC_RADIUS + 1 > *sl)
+ break;
+
+ *(dp++) = interpol_get(&s->interpol, sp, *sl, x);
+ di++;
+ }
+
+ *dl = di;
+
+ if (x >= SINC_RADIUS) {
+ *sl = (int) (x - SINC_RADIUS);
+ s->delta = x - *sl;
+ } else
+ *sl = 0;
+}
+
+#if (TEST == 7)
+
+#define BUFSIZE (10*1024)
+
+void sinbuf(float *buf, int l) {
+ static int i = 0;
+
+ for (; l > 0; l--, i = (i+1 == 100) ? 0 : i+1)
+ *(buf++) = sin(i*2*M_PI/100);
+}
+
+void convbuf(float *buf, int l) {
+ int16_t *p = (int16_t*) buf;
+ for (; l > 0; l--, p+=2) {
+ float v = ((float) *p + (float) *(p+1))/0x7FFF;
+ *(buf++) = (v < -1) ? -1 : ((v > 1) ? 1 : v);
+ }
+
+}
+
+
+int main(int argc, char *argv[]) {
+ struct resample_state resample;
+ float inbuf[BUFSIZE];
+ int total_n_inbuf = 0;
+
+ if (argc > 1) {
+ stdin = fopen(argv[1], "r");
+ assert(stdin);
+ }
+
+ resample_init(&resample);
+
+ while (!feof(stdin)) {
+ float outbuf[BUFSIZE];
+ int n_outbuf = sizeof(outbuf) / sizeof(float);
+ int n_inbuf, c;
+
+ fprintf(stderr, "LOOP!\n");
+
+ c = fread(inbuf + total_n_inbuf, sizeof(float), sizeof(inbuf)/sizeof(float) - total_n_inbuf, stdin);
+ convbuf(inbuf + total_n_inbuf, c);
+ n_inbuf = (total_n_inbuf += c);
+
+
+
+/* sinbuf(inbuf + total_n_inbuf, sizeof(inbuf)/sizeof(float) - total_n_inbuf); */
+/* n_inbuf = total_n_inbuf = sizeof(inbuf)/sizeof(float); *\/ */
+
+
+ resample_get(&resample, inbuf, &n_inbuf, outbuf, &n_outbuf, 44100, 8000);
+
+ fwrite(outbuf, sizeof(float), n_outbuf, stdout);
+
+ if (n_inbuf) {
+ total_n_inbuf -= n_inbuf;
+ memmove(inbuf, inbuf + n_inbuf, total_n_inbuf*sizeof(float));
+ }
+ }
+
+ resample_done(&resample);
+
+ return 0;
+}
+
+#endif
diff --git a/resample.h b/resample.h
new file mode 100644
index 0000000..a2905b3
--- /dev/null
+++ b/resample.h
@@ -0,0 +1,12 @@
+#ifndef fooresamplehfoo
+#define fooresamplehfoo
+
+struct resample_state;
+
+void resample_init(struct resample_state *s);
+void resample_done(struct resample_state *s);
+void resample_get(struct resample_state *s, float* sp, int *sl, float *dp, int *dl, int sfreq, int dfreq);
+
+#endif
+
+
diff --git a/util.c b/util.c
new file mode 100644
index 0000000..3907dad
--- /dev/null
+++ b/util.c
@@ -0,0 +1,21 @@
+#include <unistd.h>
+
+#include "util.h"
+
+ssize_t loop_write(int fd, const void *b, size_t l) {
+ ssize_t t = 0;
+ while (l) {
+ ssize_t r;
+
+ if ((r = write(fd, b, l)) < 0)
+ return t == 0 ? r : t;
+ else if (r == 0)
+ return t;
+
+ b += r;
+ l -= r;
+ t += r;
+ }
+
+ return t;
+}
diff --git a/util.h b/util.h
new file mode 100644
index 0000000..96dd779
--- /dev/null
+++ b/util.h
@@ -0,0 +1,8 @@
+#ifndef fooutilhfoo
+#define fooutilhfoo
+
+#include <sys/types.h>
+
+ssize_t loop_write(int fd, const void *b, size_t l);
+
+#endif
diff --git a/v17dem.c b/v17dem.c
new file mode 100644
index 0000000..4fad8f3
--- /dev/null
+++ b/v17dem.c
@@ -0,0 +1,102 @@
+#include "v17dem.h"
+
+#define INITIAL_BAUD_RATE 2400
+#define INITIAL_CARRIER_FREQ 1800
+#define SAMPLE_RATE 8000
+#define SAMPLES_MAX (SAMPLES_RATE*5) /* -> 5s buffer */
+
+#define SINC_RADIUS 10
+
+struct v17dem_state {
+ float *samples;
+ int i_samples, n_samples;
+
+ int sample_index;
+
+ int baud_rate;
+ int carrier_freq;
+
+ struct interpol_state qam_interpol;
+ struct interpol_state am_interpol;
+
+ enum { COSINUS, SINUS } current;
+ float *xam, *yam;
+ int am_index;
+};
+
+
+void v17dem_init(struct v17dem_state *s) {
+ assert(s);
+
+ memset(s, 0, sizeof(struct v17dem_state));
+ s->baud_rate = INITIAL_BAUD_RATE;
+ s->carrier_freq = INITIAL_CARRIER_FREQ;
+ s->samples = malloc(sizeof(float) * SAMPLES_MAX * 2);
+
+ interpol_init(&s->qam_interpol, 9, SINC_RADIUS);
+}
+
+void v17dem_done(struct v17dem_state *s) {
+ assert(s);
+
+ free(s->samples);
+ inertpol_done(&s->qam_interpol);
+}
+
+static void move_to_front(struct v17dem_state *s) {
+ assert(s);
+
+ if (s->i_samples < SAMPLES_MAX)
+ return;
+
+ memmove(s->samples, s->samples + s->i_samples, s->n_samples*sizeof(float));
+ s->i_samples = 0;
+}
+
+void v17dem_push(struct v17dem_state *s, const float *p, int l){
+ assert(s && p && l);
+
+ assert(l <= SAMPLES_MAX-s->n_samples);
+
+ move_to_front(s);
+
+ memcpy(s->samples + s->i_samples + s->n_samples, p, l*sizeof(float));
+ s->n_samples += l;
+}
+
+int v17dem_pull(struct v17dem_state *s, uint8_t *p, int l){
+ int alt = 0;
+
+ assert(s && p && l);
+
+ for (;;) {
+ int n;
+
+ /* Position für AM-Abtastung im Sample-Puffer berechnen -- alle 90° */
+ float x = (SAMPLE_RATE/(4.0*s->carrier_freq) * s->am_index) - s->sample_index;
+ assert(x >= 0);
+
+ /* AM-Abtatsung druchführen */
+ if (s->current = COSINUS)
+ am = s->xam;
+ else
+ am = s->yam;
+
+ am[s->am_index] = interpol_get(s->qam_interpol, s->samples + s->i_samples, s->n_samples, x);
+
+ if (s->current == SINUS)
+ s->am_index++;
+
+ s->current = !s->current;
+
+ /* Überflüssige Sampledaten killen */
+
+ n = (int) (x - (float) SINC_RADIUS*SAMPLE_RATE/s->carrier_freq/4);
+
+ if (n > 0) {
+ s->n_samples -= n;
+ s->i_samples += n;
+ s->sample_index += n;
+ }
+ }
+}
diff --git a/v17mod.c b/v17mod.c
new file mode 100644
index 0000000..3c604ef
--- /dev/null
+++ b/v17mod.c
@@ -0,0 +1,206 @@
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include "v17mod.h"
+
+#define SAMPLE_RATE 8000
+#define CARRIER_FREQ 1800
+#define BAUD_RATE 2400
+#define SYMBOL_INTERVAL ((float) SAMPLE_RATE/BAUD_RATE)
+#define SINC_RADIUS 5
+#define SYMBOLS_MAX 1024
+
+static const float v17_7k2_x[] = {
+ 0.6, -0.2, 0.6, -0.6,
+ -0.6, 0.2, -0.6, 0.6,
+ -0.2, 0.6, -0.2, 0.2,
+ 0.2, -0.6, 0.2, -0.2
+};
+
+static const float v17_7k2_y[] = {
+ -0.6, 0.6, 0.2, -0.6,
+ 0.6, -0.6, -0.2, 0.6,
+ 0.2, -0.2, -0.6, 0.2,
+ -0.2, 0.2, 0.6, -0.2
+};
+
+void v17mod_init(struct v17mod_state *s) {
+ size_t l;
+ int i;
+
+ assert(s);
+ memset(s, 0, sizeof(*s));
+
+ s->xsymbols = malloc(l = (sizeof(float)*SYMBOLS_MAX));
+ s->ysymbols = malloc(l);
+
+ s->n_symbols = SINC_RADIUS*2;
+
+ for (i = 0; i < s->n_symbols; i++)
+ s->xsymbols[i] = s->ysymbols[i] = 0.0;
+}
+
+void v17mod_done(struct v17mod_state *s) {
+ assert(s);
+ free(s->xsymbols);
+ free(s->ysymbols);
+}
+
+static const float sinc_table[] = {
+ 0.0000, -0.0000, -0.0002, -0.0005, -0.0009,
+ -0.0014, -0.0018, -0.0020, -0.0019, -0.0013,
+ 0.0000, 0.0019, 0.0042, 0.0068, 0.0093,
+ 0.0113, 0.0124, 0.0120, 0.0098, 0.0058,
+ -0.0000, -0.0073, -0.0153, -0.0234, -0.0303,
+ -0.0350, -0.0365, -0.0340, -0.0270, -0.0155,
+ 0.0000, 0.0183, 0.0377, 0.0562, 0.0716,
+ 0.0815, 0.0838, 0.0771, 0.0605, 0.0344,
+ -0.0000, -0.0403, -0.0832, -0.1243, -0.1589,
+ -0.1821, -0.1893, -0.1767, -0.1415, -0.0824,
+ 0.0000, 0.1035, 0.2241, 0.3561, 0.4926,
+ 0.6261, 0.7488, 0.8533, 0.9330, 0.9830,
+ 1.0000, 0.9830, 0.9330, 0.8533, 0.7488,
+ 0.6261, 0.4926, 0.3561, 0.2241, 0.1035,
+ 0.0000, -0.0824, -0.1415, -0.1767, -0.1893,
+ -0.1821, -0.1589, -0.1243, -0.0832, -0.0403,
+ -0.0000, 0.0344, 0.0605, 0.0771, 0.0838,
+ 0.0815, 0.0716, 0.0562, 0.0377, 0.0183,
+ 0.0000, -0.0155, -0.0270, -0.0340, -0.0365,
+ -0.0350, -0.0303, -0.0234, -0.0153, -0.0073,
+ -0.0000, 0.0058, 0.0098, 0.0120, 0.0124,
+ 0.0113, 0.0093, 0.0068, 0.0042, 0.0019,
+ 0.0000, -0.0013, -0.0019, -0.0020, -0.0018,
+ -0.0014, -0.0009, -0.0005, -0.0002, -0.0000,
+ -0.0000
+};
+
+static float sinc(float x) {
+ int i;
+ assert(sizeof(sinc_table)/sizeof(float) == 121);
+
+ i = (int) (60+x*10+.5);
+
+ if (i < 0)
+ return 0;
+ if (i > 120)
+ return 0;
+
+ return sinc_table[i];
+}
+
+
+void v17mod_push(struct v17mod_state *s, const uint8_t *p, int l) {
+ int i, j;
+
+ assert(s && p && l);
+ assert(s->n_symbols+l <= SYMBOLS_MAX);
+
+ for (i = 0, j = (s->i_symbols+s->n_symbols) % SYMBOLS_MAX; i < l; i++, j = (j+1) % SYMBOLS_MAX) {
+ assert(p[i] < 16);
+ s->xsymbols[j] = v17_7k2_x[p[i]];
+ s->ysymbols[j] = v17_7k2_y[p[i]];
+ }
+
+ s->n_symbols += l;
+}
+
+inline static float symbol_at(struct v17mod_state *s, float *a, int i) {
+ int j = s->i_symbols+i;
+
+ assert(i >= 0);
+ assert(i < s->n_symbols);
+
+ while(j >= SYMBOLS_MAX)
+ j -= SYMBOLS_MAX;
+
+ assert(j>=0);
+ assert(j<SYMBOLS_MAX);
+
+ return a[j];
+}
+
+static float fsignal(struct v17mod_state *s, int i) {
+ float sum, d;
+ int n;
+ float *symbols;
+
+ assert(s && i >= 0 && i <= 1);
+
+ symbols = (i == 0) ? s->xsymbols : s->ysymbols;
+ sum = 0;
+ d = s->sample - s->symbol_index*SAMPLE_RATE/BAUD_RATE;
+
+ for (n = -SINC_RADIUS; n < SINC_RADIUS; n++) {
+ float a,b;
+ a = symbol_at(s, symbols, n+SINC_RADIUS);
+ b = sinc(-n + d*BAUD_RATE/SAMPLE_RATE);
+ sum += a*b;
+ }
+ assert(sum<=10);
+ assert(sum >=-10);
+
+ return sum;
+}
+
+int v17mod_pull(struct v17mod_state *s, float *p, int l) {
+ assert(s && p && l && p && l);
+
+ int n_samples = 0;
+
+ for (;;) {
+ float x;
+ int nsi;
+
+ if (s->sample % 800 == 0)
+ fprintf(stderr, "seconds: %i; samples: %i; symbols: %i \r", s->seconds, s->sample, s->symbol_index);
+
+ if (!l) {
+ fprintf(stderr, "v17_mod(): destination buffer too short\n");
+ return -1;
+ }
+
+ nsi = (int) ((float) s->sample*BAUD_RATE/SAMPLE_RATE);
+ if (nsi != s->symbol_index) {
+ s->i_symbols++;
+ s->n_symbols--;
+
+ while (s->i_symbols >= SYMBOLS_MAX)
+ s->i_symbols -= SYMBOLS_MAX;
+
+ s->symbol_index = nsi;
+ }
+
+ if (s->n_symbols < SINC_RADIUS*2)
+ return n_samples;
+
+ if (s->sample == SAMPLE_RATE) {
+ assert(s->symbol_index == BAUD_RATE);
+
+ s->symbol_index = s->sample = 0;
+ s->seconds++;
+ }
+
+
+ x = (s->sample % SAMPLE_RATE) * M_PI*2 * CARRIER_FREQ / SAMPLE_RATE;
+
+ *(p++) = fsignal(s, 0)*sin(x) + fsignal(s, 1)*cos(x);
+ l--;
+
+ s->sample++;
+ n_samples++;
+ }
+}
+
+
+#if (TEST == 3)
+
+int main() {
+ fprintf(stderr, "%f\n", sinc(1.0/3));
+
+ return 0;
+}
+
+#endif
diff --git a/v17mod.h b/v17mod.h
new file mode 100644
index 0000000..6417ca4
--- /dev/null
+++ b/v17mod.h
@@ -0,0 +1,22 @@
+#ifndef foov17modhfoo
+#define foov17modhfoo
+
+#include <inttypes.h>
+
+struct v17mod_state {
+ int sample;
+ int symbol_index;
+
+ int seconds;
+
+ float *xsymbols, *ysymbols;
+ int i_symbols, n_symbols;
+};
+
+void v17mod_init(struct v17mod_state *s);
+void v17mod_done(struct v17mod_state *s);
+
+void v17mod_push(struct v17mod_state *s, const uint8_t *p, int l);
+int v17mod_pull(struct v17mod_state *s, float *p, int l);
+
+#endif
diff --git a/v17tcm.c b/v17tcm.c
new file mode 100644
index 0000000..0edaefe
--- /dev/null
+++ b/v17tcm.c
@@ -0,0 +1,109 @@
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+#include <inttypes.h>
+
+#include "v17tcm.h"
+
+static const uint8_t v17tcm_table[] = {
+ 0, 1, 2, 3,
+ 1, 2, 3, 0,
+ 2, 3, 0, 1,
+ 3, 0, 1, 2
+};
+
+static const uint8_t v17tcm_table_reverse[] = {
+ 0, 1, 2, 3,
+ 3, 0, 1, 2,
+ 2, 3, 0, 1,
+ 1, 2, 3, 0
+};
+
+void v17tcm_init(struct v17tcm_state *s) {
+ assert(s);
+ memset(s, 0, sizeof(*s));
+}
+
+static uint8_t conv_encode(struct v17tcm_state* s, uint8_t y) {
+ uint8_t x, a, b, c, d, e;
+
+ /*
+ fprintf(stderr, "conv_encode(..., %u)\n", y);
+ */
+ a = (y&1) ^ (y>>1);
+ b = (a ^ s->c1);
+ d = s->c2 ^ (s->c2 ^ (y>>1));
+ c = b ^ (s->c3 & d);
+ e = d ^ ((y&1) & s->c3);
+
+ x = s->c3;
+
+ s->c1 = s->c3;
+ s->c2 = c;
+ s->c3 = e;
+
+ return x;
+}
+
+uint8_t v17tcm_encode(struct v17tcm_state* s, uint8_t input) {
+ uint8_t y, c;
+
+ y = s->y = v17tcm_table[((input & 3) << 2) | (s->y & 3)];
+
+ /*fprintf(stderr, "tcm = %u\n", y);*/
+
+ c = conv_encode(s, y);
+
+ /*fprintf(stderr, "c:%u von %u\n", c, y);*/
+
+ return c | ((y | (input & ~3)) << 1);
+}
+
+uint8_t v17tcm_decode(struct v17tcm_state *s, uint8_t input) {
+ uint8_t y, py;
+
+ if (conv_encode(s, (input >> 1) & 3) != (input & 1))
+ fprintf(stderr, "Invalid TCM code, ignoring\n");
+
+ y = v17tcm_table_reverse[((s->y&3) << 2) | (py = ((input >> 1) & 3))];
+
+ s->y = py;
+
+ return (input >> 3 << 2) | y;
+}
+
+#ifdef TEST1
+int main() {
+ uint8_t c;
+
+ for (c = 0; c <= 0xF; c++) {
+ if (v17tcm_table_reverse[v17tcm_table[c] | ((c&3) << 2)] != (c >> 2))
+ fprintf(stderr, "%u: FEHLER\n", c);
+ else
+ fprintf(stderr, "%u: OK\n", c);
+ }
+ return 0;
+}
+#endif
+
+#ifdef TEST2
+int main() {
+ struct v17tcm_state s1, s2;
+ int c, n;
+
+ v17tcm_init(&s1);
+ v17tcm_init(&s2);
+
+ n = 0;
+ while ((c = getchar()) >= 0) {
+ uint8_t b = ((uint8_t) c) & 63;
+ uint8_t u = v17tcm_encode(&s1, b);
+ uint8_t e = v17tcm_decode(&s2, u);
+
+ fprintf(stderr, "%i) %u %s %u (encoded: %u)\n", n++, b, b == e ? "==" : "!=", e, u);
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/v17tcm.h b/v17tcm.h
new file mode 100644
index 0000000..f126714
--- /dev/null
+++ b/v17tcm.h
@@ -0,0 +1,15 @@
+#ifndef foov17tcmhfoo
+#define foov17tcmhfoo
+
+#include <inttypes.h>
+
+struct v17tcm_state {
+ uint8_t y, c1, c2, c3;
+};
+
+void v17tcm_init(struct v17tcm_state *s);
+
+uint8_t v17tcm_encode(struct v17tcm_state* s, uint8_t input);
+uint8_t v17tcm_decode(struct v17tcm_state *s, uint8_t input);
+
+#endif