#include #include #include #include #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