diff options
author | Lennart Poettering <lennart@poettering.net> | 2004-04-18 01:35:53 +0000 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2004-04-18 01:35:53 +0000 |
commit | 783b56d54788f177881d68ae2ec7a7cb4bb38ac4 (patch) | |
tree | 77555207fa13c137e0c8dab8726f2ed96538e075 | |
parent | f069d236c79a7cb89542eba5ddc454d03ead5394 (diff) |
Initial commit
git-svn-id: file:///home/lennart/svn/public/vfax/trunk@3 541b366f-4dd8-0310-ae39-b2612fd50714
-rw-r--r-- | Makefile | 15 | ||||
-rw-r--r-- | bitsplit.c | 104 | ||||
-rw-r--r-- | bitsplit.h | 21 | ||||
-rw-r--r-- | interpol.c | 139 | ||||
-rw-r--r-- | interpol.h | 17 | ||||
-rw-r--r-- | main.c | 87 | ||||
-rw-r--r-- | resample.c | 147 | ||||
-rw-r--r-- | resample.h | 12 | ||||
-rw-r--r-- | util.c | 21 | ||||
-rw-r--r-- | util.h | 8 | ||||
-rw-r--r-- | v17dem.c | 102 | ||||
-rw-r--r-- | v17mod.c | 206 | ||||
-rw-r--r-- | v17mod.h | 22 | ||||
-rw-r--r-- | v17tcm.c | 109 | ||||
-rw-r--r-- | v17tcm.h | 15 |
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 @@ -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 + + @@ -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; +} @@ -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 |