summaryrefslogtreecommitdiffstats
path: root/v17tcm.c
blob: 0edaefe7401929668639db037b7affc78d76e614 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
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