mirror of
https://github.com/zint/zint
synced 2024-11-16 20:57:25 +13:00
1318 lines
46 KiB
C
1318 lines
46 KiB
C
/* dmatrix.c - Handles Data Matrix 2-D symbology */
|
|
|
|
/*
|
|
libzint - the open source barcode library
|
|
Copyright (C) 2008 Robin Stuart <robin@zint.org.uk>
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License along
|
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*/
|
|
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#ifdef _MSC_VER
|
|
#include <malloc.h>
|
|
#endif
|
|
#include "dmatrix.h"
|
|
#include "common.h"
|
|
#ifdef _MSC_VER
|
|
#include "dm200.h"
|
|
#else
|
|
extern int data_matrix_200(struct zint_symbol *symbol, unsigned char source[]);
|
|
#endif
|
|
|
|
#define B11SET " 0123456789"
|
|
#define B27SET " ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
#define B37SET " ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
|
#define B41SET " ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,-/"
|
|
|
|
void crc_machine(char data_prefix_bitstream[], int scheme, unsigned char source[])
|
|
{
|
|
int input_length, i;
|
|
input_length = ustrlen(source);
|
|
char xor_register[17];
|
|
#ifndef _MSC_VER
|
|
char precrc_bitstream[(input_length * 8) + 18];
|
|
char precrc_bitstream_reversed[(input_length * 8) + 18];
|
|
#else
|
|
char* precrc_bitstream = (char*)_alloca((input_length * 8) + 18);
|
|
char* precrc_bitstream_reversed = (char*)_alloca((input_length * 8) + 18);
|
|
#endif
|
|
int machine_cycles;
|
|
char input_bit, out1, out2, out3;
|
|
|
|
switch(scheme) {
|
|
case 11: strcpy(precrc_bitstream, "0000000100000000"); break;
|
|
case 27: strcpy(precrc_bitstream, "0000001000000000"); break;
|
|
case 41: strcpy(precrc_bitstream, "0000001100000000"); break;
|
|
case 37: strcpy(precrc_bitstream, "0000010000000000"); break;
|
|
default: strcpy(precrc_bitstream, "0000010100000000"); break;
|
|
}
|
|
|
|
for(i = 0; i < input_length; i++) {
|
|
if(source[i] & 0x80) { concat(precrc_bitstream, "1"); } else { concat(precrc_bitstream, "0"); }
|
|
if(source[i] & 0x40) { concat(precrc_bitstream, "1"); } else { concat(precrc_bitstream, "0"); }
|
|
if(source[i] & 0x20) { concat(precrc_bitstream, "1"); } else { concat(precrc_bitstream, "0"); }
|
|
if(source[i] & 0x10) { concat(precrc_bitstream, "1"); } else { concat(precrc_bitstream, "0"); }
|
|
if(source[i] & 0x08) { concat(precrc_bitstream, "1"); } else { concat(precrc_bitstream, "0"); }
|
|
if(source[i] & 0x04) { concat(precrc_bitstream, "1"); } else { concat(precrc_bitstream, "0"); }
|
|
if(source[i] & 0x02) { concat(precrc_bitstream, "1"); } else { concat(precrc_bitstream, "0"); }
|
|
if(source[i] & 0x01) { concat(precrc_bitstream, "1"); } else { concat(precrc_bitstream, "0"); }
|
|
}
|
|
|
|
/* pre-CRC bit stream byte reversal */
|
|
for(i = 0; i < (input_length + 2); i++) {
|
|
precrc_bitstream_reversed[0 + (i * 8)] = precrc_bitstream[7 + (i * 8)];
|
|
precrc_bitstream_reversed[1 + (i * 8)] = precrc_bitstream[6 + (i * 8)];
|
|
precrc_bitstream_reversed[2 + (i * 8)] = precrc_bitstream[5 + (i * 8)];
|
|
precrc_bitstream_reversed[3 + (i * 8)] = precrc_bitstream[4 + (i * 8)];
|
|
precrc_bitstream_reversed[4 + (i * 8)] = precrc_bitstream[3 + (i * 8)];
|
|
precrc_bitstream_reversed[5 + (i * 8)] = precrc_bitstream[2 + (i * 8)];
|
|
precrc_bitstream_reversed[6 + (i * 8)] = precrc_bitstream[1 + (i * 8)];
|
|
precrc_bitstream_reversed[7 + (i * 8)] = precrc_bitstream[0 + (i * 8)];
|
|
}
|
|
precrc_bitstream_reversed[strlen(precrc_bitstream)] = '\0';
|
|
machine_cycles = strlen(precrc_bitstream_reversed);
|
|
|
|
/* Start up the machine */
|
|
for(i = 0; i < 16; i++) {
|
|
xor_register[i] = '0';
|
|
}
|
|
input_bit = precrc_bitstream_reversed[0];
|
|
if(input_bit != xor_register[15]) { out1 = '1'; } else { out1 = '0'; }
|
|
if(input_bit != xor_register[11]) { out2 = '1'; } else { out2 = '0'; }
|
|
if(input_bit != xor_register[4]) { out3 = '1'; } else { out3 = '0'; }
|
|
|
|
for(i = 0; i < machine_cycles; i++) {
|
|
xor_register[15] = xor_register[14];
|
|
xor_register[14] = xor_register[13];
|
|
xor_register[13] = xor_register[12];
|
|
xor_register[12] = out2;
|
|
xor_register[11] = xor_register[10];
|
|
xor_register[10] = xor_register[9];
|
|
xor_register[9] = xor_register[8];
|
|
xor_register[8] = xor_register[7];
|
|
xor_register[7] = xor_register[6];
|
|
xor_register[6] = xor_register[5];
|
|
xor_register[5] = out3;
|
|
xor_register[4] = xor_register[3];
|
|
xor_register[3] = xor_register[2];
|
|
xor_register[2] = xor_register[1];
|
|
xor_register[1] = xor_register[0];
|
|
xor_register[0] = out1;
|
|
input_bit = precrc_bitstream_reversed[(i + 1)];
|
|
if(input_bit != xor_register[15]) { out1 = '1'; } else { out1 = '0'; }
|
|
if(out1 != xor_register[11]) { out2 = '1'; } else { out2 = '0'; }
|
|
if(out1 != xor_register[4]) { out3 = '1'; } else { out3 = '0'; }
|
|
}
|
|
|
|
for(i = 0; i < 16; i++) {
|
|
data_prefix_bitstream[i + 5] = xor_register[15 - i];
|
|
}
|
|
data_prefix_bitstream[16 + 5] = '\0';
|
|
|
|
return;
|
|
}
|
|
|
|
void i1_base11(char binary_string[], unsigned char source[])
|
|
{
|
|
int input_length, blocks, remainder, i, j;
|
|
char block_binary[22];
|
|
int block_value, c[6], weight[6];
|
|
int binary_posn;
|
|
|
|
input_length = ustrlen(source);
|
|
binary_posn = strlen(binary_string);
|
|
blocks = input_length / 6;
|
|
remainder = input_length % 6;
|
|
|
|
weight[0] = 1;
|
|
weight[1] = 11;
|
|
weight[2] = 121;
|
|
weight[3] = 1331;
|
|
weight[4] = 14641;
|
|
weight[5] = 161051;
|
|
|
|
for(i = 0; i < blocks; i++) {
|
|
strcpy(block_binary, "");
|
|
block_value = 0;
|
|
binary_posn = strlen(binary_string);
|
|
for(j = 0; j < 6; j++) {
|
|
c[j] = posn(B11SET, source[(i * 6) + j]);
|
|
c[j] *= weight[j];
|
|
block_value += c[j];
|
|
}
|
|
|
|
if(block_value & 0x100000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x80000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x40000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x20000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x10000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x8000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x4000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x2000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x1000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x800) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x400) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x200) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x100) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x80) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x40) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x20) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x10) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x08) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x04) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x02) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x01) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
|
|
for(j = 0; j < strlen(block_binary); j++) {
|
|
binary_string[strlen(block_binary) + binary_posn - j - 1] = block_binary[j];
|
|
}
|
|
binary_string[strlen(block_binary) + binary_posn] = '\0';
|
|
binary_posn = strlen(binary_string);
|
|
}
|
|
|
|
strcpy(block_binary, "");
|
|
block_value = 0;
|
|
binary_posn = strlen(binary_string);
|
|
for(j = 0; j < remainder; j++) {
|
|
c[j] = posn(B11SET, source[(i * 6) + j]);
|
|
c[j] *= weight[j];
|
|
block_value += c[j];
|
|
}
|
|
|
|
switch(remainder) {
|
|
case 5:
|
|
if(block_value & 0x20000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x10000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x8000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x4000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
case 4:
|
|
if(block_value & 0x2000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x1000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x800) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
case 3:
|
|
if(block_value & 0x400) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x200) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x100) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x80) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
case 2:
|
|
if(block_value & 0x40) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x20) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x10) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
case 1:
|
|
if(block_value & 0x08) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x04) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x02) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x01) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
default:
|
|
break;
|
|
}
|
|
|
|
for(j = 0; j < strlen(block_binary); j++) {
|
|
binary_string[strlen(block_binary) + binary_posn - j - 1] = block_binary[j];
|
|
}
|
|
binary_string[strlen(block_binary) + binary_posn] = '\0';
|
|
binary_posn = strlen(binary_string);
|
|
|
|
return;
|
|
}
|
|
|
|
void i2_base27(char binary_string[], unsigned char source[])
|
|
{
|
|
int input_length, blocks, remainder, i, j;
|
|
char block_binary[25];
|
|
int block_value, c[5], weight[5];
|
|
int binary_posn;
|
|
|
|
input_length = ustrlen(source);
|
|
blocks = input_length / 5;
|
|
remainder = input_length % 5;
|
|
binary_posn = strlen(binary_string);
|
|
|
|
weight[0] = 1;
|
|
weight[1] = 27;
|
|
weight[2] = 729;
|
|
weight[3] = 19683;
|
|
weight[4] = 531441;
|
|
|
|
for(i = 0; i < blocks; i++) {
|
|
strcpy(block_binary, "");
|
|
block_value = 0;
|
|
for(j = 0; j < 5; j++) {
|
|
c[j] = posn(B27SET, source[(i * 5) + j]);
|
|
c[j] *= weight[j];
|
|
block_value += c[j];
|
|
}
|
|
|
|
if(block_value & 0x800000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x400000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x200000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x100000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x80000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x40000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x20000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x10000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x8000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x4000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x2000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x1000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x800) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x400) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x200) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x100) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x80) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x40) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x20) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x10) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x08) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x04) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x02) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x01) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
|
|
for(j = 0; j < strlen(block_binary); j++) {
|
|
binary_string[strlen(block_binary) + binary_posn - j - 1] = block_binary[j];
|
|
}
|
|
binary_string[strlen(block_binary) + binary_posn] = '\0';
|
|
binary_posn = strlen(binary_string);
|
|
}
|
|
|
|
strcpy(block_binary, "");
|
|
block_value = 0;
|
|
for(j = 0; j < remainder; j++) {
|
|
c[j] = posn(B27SET, source[(i * 5) + j]);
|
|
c[j] *= weight[j];
|
|
block_value += c[j];
|
|
}
|
|
|
|
switch(remainder) {
|
|
case 4:
|
|
if(block_value & 0x80000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x40000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x20000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x10000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x8000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
case 3:
|
|
if(block_value & 0x4000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x2000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x1000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x800) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x400) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
case 2:
|
|
if(block_value & 0x200) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x100) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x80) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x40) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x20) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
case 1:
|
|
if(block_value & 0x10) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x08) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x04) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x02) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x01) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
default:
|
|
break;
|
|
}
|
|
|
|
for(j = 0; j < strlen(block_binary); j++) {
|
|
binary_string[strlen(block_binary) + binary_posn - j - 1] = block_binary[j];
|
|
}
|
|
binary_string[strlen(block_binary) + binary_posn] = '\0';
|
|
binary_posn = strlen(binary_string);
|
|
|
|
return;
|
|
}
|
|
|
|
void i3_base37(char binary_string[], unsigned char source[])
|
|
{
|
|
int input_length, blocks, remainder, i, j;
|
|
char block_binary[22];
|
|
int block_value, c[6], weight[6];
|
|
int binary_posn;
|
|
|
|
input_length = ustrlen(source);
|
|
blocks = input_length / 4;
|
|
remainder = input_length % 4;
|
|
binary_posn = strlen(binary_string);
|
|
|
|
weight[0] = 1;
|
|
weight[1] = 37;
|
|
weight[2] = 1369;
|
|
weight[3] = 50653;
|
|
|
|
for(i = 0; i < blocks; i++) {
|
|
strcpy(block_binary, "");
|
|
block_value = 0;
|
|
for(j = 0; j < 4; j++) {
|
|
c[j] = posn(B37SET, source[(i * 4) + j]);
|
|
c[j] *= weight[j];
|
|
block_value += c[j];
|
|
}
|
|
|
|
if(block_value & 0x100000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x80000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x40000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x20000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x10000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x8000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x4000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x2000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x1000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x800) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x400) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x200) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x100) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x80) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x40) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x20) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x10) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x08) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x04) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x02) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x01) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
|
|
for(j = 0; j < strlen(block_binary); j++) {
|
|
binary_string[strlen(block_binary) + binary_posn - j - 1] = block_binary[j];
|
|
}
|
|
binary_string[strlen(block_binary) + binary_posn] = '\0';
|
|
binary_posn = strlen(binary_string);
|
|
}
|
|
|
|
strcpy(block_binary, "");
|
|
block_value = 0;
|
|
for(j = 0; j < remainder; j++) {
|
|
c[j] = posn(B37SET, source[(i * 4) + j]);
|
|
c[j] *= weight[j];
|
|
block_value += c[j];
|
|
}
|
|
|
|
switch(remainder) {
|
|
case 3:
|
|
if(block_value & 0x8000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x4000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x2000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x1000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x800) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
case 2:
|
|
if(block_value & 0x400) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x200) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x100) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x80) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x40) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
case 1:
|
|
if(block_value & 0x20) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x10) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x08) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x04) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x02) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x01) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
default:
|
|
break;
|
|
}
|
|
|
|
for(j = 0; j < strlen(block_binary); j++) {
|
|
binary_string[strlen(block_binary) + binary_posn - j - 1] = block_binary[j];
|
|
}
|
|
binary_string[strlen(block_binary) + binary_posn] = '\0';
|
|
binary_posn = strlen(binary_string);
|
|
|
|
return;
|
|
}
|
|
|
|
void i4_base41(char binary_string[], unsigned char source[])
|
|
{
|
|
int input_length, blocks, remainder, i, j;
|
|
char block_binary[23];
|
|
int block_value, c[6], weight[6];
|
|
int binary_posn;
|
|
|
|
input_length = ustrlen(source);
|
|
blocks = input_length / 4;
|
|
remainder = input_length % 4;
|
|
binary_posn = strlen(binary_string);
|
|
|
|
weight[0] = 1;
|
|
weight[1] = 41;
|
|
weight[2] = 1681;
|
|
weight[3] = 68921;
|
|
|
|
for(i = 0; i < blocks; i++) {
|
|
strcpy(block_binary, "");
|
|
block_value = 0;
|
|
for(j = 0; j < 4; j++) {
|
|
c[j] = posn(B41SET, source[(i * 4) + j]);
|
|
c[j] *= weight[j];
|
|
block_value += c[j];
|
|
}
|
|
|
|
if(block_value & 0x200000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x100000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x80000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x40000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x20000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x10000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x8000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x4000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x2000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x1000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x800) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x400) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x200) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x100) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x80) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x40) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x20) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x10) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x08) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x04) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x02) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x01) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
|
|
for(j = 0; j < strlen(block_binary); j++) {
|
|
binary_string[strlen(block_binary) + binary_posn - j - 1] = block_binary[j];
|
|
}
|
|
binary_string[strlen(block_binary) + binary_posn] = '\0';
|
|
binary_posn = strlen(binary_string);
|
|
}
|
|
|
|
strcpy(block_binary, "");
|
|
block_value = 0;
|
|
for(j = 0; j < remainder; j++) {
|
|
c[j] = posn(B41SET, source[(i * 4) + j]);
|
|
c[j] *= weight[j];
|
|
block_value += c[j];
|
|
}
|
|
|
|
switch(remainder) {
|
|
case 3:
|
|
if(block_value & 0x10000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x8000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x4000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x2000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x1000) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x800) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
case 2:
|
|
if(block_value & 0x400) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x200) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x100) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x80) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x40) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
case 1:
|
|
if(block_value & 0x20) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x10) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x08) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x04) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x02) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(block_value & 0x01) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
default:
|
|
break;
|
|
}
|
|
|
|
for(j = 0; j < strlen(block_binary); j++) {
|
|
binary_string[strlen(block_binary) + binary_posn - j - 1] = block_binary[j];
|
|
}
|
|
binary_string[strlen(block_binary) + binary_posn] = '\0';
|
|
binary_posn = strlen(binary_string);
|
|
|
|
return;
|
|
}
|
|
|
|
void base128(char binary_string[], unsigned char source[])
|
|
{
|
|
int i, j, input_length;
|
|
char block_binary[9];
|
|
int binary_posn;
|
|
|
|
input_length = ustrlen(source);
|
|
binary_posn = strlen(binary_string);
|
|
|
|
for(i = 0; i < input_length; i++) {
|
|
strcpy(block_binary, "");
|
|
|
|
if(source[i] & 0x40) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(source[i] & 0x20) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(source[i] & 0x10) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(source[i] & 0x08) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(source[i] & 0x04) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(source[i] & 0x02) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
if(source[i] & 0x01) { concat(block_binary, "1"); } else { concat(block_binary, "0"); }
|
|
|
|
for(j = 0; j < strlen(block_binary); j++) {
|
|
binary_string[strlen(block_binary) + binary_posn - j - 1] = block_binary[j];
|
|
}
|
|
binary_string[strlen(block_binary) + binary_posn] = '\0';
|
|
binary_posn = strlen(binary_string);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void protect_ecc000(char protected_stream[], char unprotected_stream[])
|
|
{
|
|
/* ECC 000 - No processing needed */
|
|
|
|
strcpy(protected_stream, unprotected_stream);
|
|
}
|
|
|
|
void protect_ecc050(char protected_stream[], char unprotected_stream[])
|
|
{
|
|
/* ECC 050 - 4-3-3 convolutional code */
|
|
/* State machine illustrated in figure K1 */
|
|
char top_reg[4];
|
|
char mid_reg[4];
|
|
char low_reg[4];
|
|
char u1, u2, u3;
|
|
char output[6];
|
|
char gate_input[8];
|
|
int i, blocks, j, count;
|
|
|
|
strcpy(protected_stream, "");
|
|
|
|
for(i = 0; i < 3; i++) {
|
|
top_reg[i] = '0';
|
|
mid_reg[i] = '0';
|
|
low_reg[i] = '0';
|
|
}
|
|
|
|
for(i = 0; i < (strlen(unprotected_stream) % 3); i++){
|
|
concat(unprotected_stream, "0");
|
|
}
|
|
blocks = strlen(unprotected_stream) / 3;
|
|
blocks += 3;
|
|
for(i = 0; i < blocks; i++) {
|
|
if(i < (blocks - 3)) {
|
|
u1 = unprotected_stream[3 * i];
|
|
u2 = unprotected_stream[(3 * i) + 1];
|
|
u3 = unprotected_stream[(3 * i) + 2];
|
|
} else {
|
|
u1 = '0';
|
|
u2 = '0';
|
|
u3 = '0';
|
|
}
|
|
|
|
/* Gate 1 */
|
|
for(j = 0; j < 8; j++) {
|
|
gate_input[j] = '0';
|
|
}
|
|
|
|
gate_input[0] = u1;
|
|
gate_input[1] = mid_reg[2];
|
|
gate_input[2] = low_reg[0];
|
|
gate_input[3] = low_reg[1];
|
|
gate_input[4] = low_reg[2];
|
|
|
|
count = 0;
|
|
for(j = 0; j < 5; j++) {
|
|
if(gate_input[j] == '1') {
|
|
count++;
|
|
}
|
|
}
|
|
if((count & 0x01) == 0x01) { output[0] = '1'; } else { output[0] = '0'; }
|
|
|
|
/* Gate 2 */
|
|
for(j = 0; j < 8; j++) {
|
|
gate_input[j] = '0';
|
|
}
|
|
|
|
gate_input[0] = top_reg[1];
|
|
gate_input[1] = top_reg[2];
|
|
gate_input[2] = u2;
|
|
gate_input[3] = mid_reg[0];
|
|
gate_input[4] = mid_reg[2];
|
|
|
|
count = 0;
|
|
for(j = 0; j < 5; j++) {
|
|
if(gate_input[j] == '1') {
|
|
count++;
|
|
}
|
|
}
|
|
if((count & 0x01) == 0x01) { output[1] = '1'; } else { output[1] = '0'; }
|
|
|
|
/* Gate 3 */
|
|
for(j = 0; j < 8; j++) {
|
|
gate_input[j] = '0';
|
|
}
|
|
|
|
gate_input[0] = top_reg[0];
|
|
gate_input[1] = top_reg[1];
|
|
gate_input[2] = top_reg[2];
|
|
gate_input[3] = mid_reg[0];
|
|
gate_input[4] = u3;
|
|
gate_input[5] = low_reg[0];
|
|
|
|
count = 0;
|
|
for(j = 0; j < 6; j++) {
|
|
if(gate_input[j] == '1') {
|
|
count++;
|
|
}
|
|
}
|
|
if((count & 0x01) == 0x01) { output[2] = '1'; } else { output[2] = '0'; }
|
|
|
|
/* Gate 4 */
|
|
for(j = 0; j < 8; j++) {
|
|
gate_input[j] = '0';
|
|
}
|
|
|
|
gate_input[0] = u1;
|
|
gate_input[1] = top_reg[0];
|
|
gate_input[2] = u2;
|
|
gate_input[3] = mid_reg[0];
|
|
gate_input[4] = mid_reg[1];
|
|
gate_input[5] = u3;
|
|
gate_input[6] = low_reg[0];
|
|
gate_input[7] = low_reg[2];
|
|
|
|
count = 0;
|
|
for(j = 0; j < 8; j++) {
|
|
if(gate_input[j] == '1') {
|
|
count++;
|
|
}
|
|
}
|
|
if((count & 0x01) == 0x01) { output[3] = '1'; } else { output[3] = '0'; }
|
|
|
|
output[4] = '\0';
|
|
|
|
concat(protected_stream, output);
|
|
|
|
/* Shift registers right */
|
|
top_reg[2] = top_reg[1];
|
|
top_reg[1] = top_reg[0];
|
|
top_reg[0] = u1;
|
|
mid_reg[2] = mid_reg[1];
|
|
mid_reg[1] = mid_reg[0];
|
|
mid_reg[0] = u2;
|
|
low_reg[2] = low_reg[1];
|
|
low_reg[1] = low_reg[0];
|
|
low_reg[0] = u3;
|
|
}
|
|
}
|
|
|
|
void protect_ecc080(char protected_stream[], char unprotected_stream[])
|
|
{
|
|
/* ECC 080 - 3-2-11 convolutional code */
|
|
/* State machine illustrated in figure K2 */
|
|
/* NOTE: Figure K.2 of ISO/IEC 16022:2006 has an error in that input 2 of gate 1 and input 1 of gate 2 are
|
|
both connected to module 2 _and_ module 3 of the top register. This is obviously not correct so I have
|
|
made a guess at the correct interpretation and made a comment where a correction may be needed if this
|
|
guess is not correct */
|
|
char top_reg[12];
|
|
char low_reg[12];
|
|
char u1, u2;
|
|
char output[4];
|
|
char gate_input[12];
|
|
int i, j, count, blocks;
|
|
|
|
strcpy(protected_stream, "");
|
|
|
|
for(i = 0; i < 12; i++) {
|
|
top_reg[i] = '0';
|
|
low_reg[i] = '0';
|
|
}
|
|
|
|
for(i = 0; i < (strlen(unprotected_stream) % 2); i++){
|
|
concat(unprotected_stream, "0");
|
|
}
|
|
blocks = strlen(unprotected_stream) / 2;
|
|
blocks += 11;
|
|
for(i = 0; i < blocks; i++) {
|
|
if(i < (blocks - 11)) {
|
|
u1 = unprotected_stream[2 * i];
|
|
u2 = unprotected_stream[(2 * i) + 1];
|
|
} else {
|
|
u1 = '0';
|
|
u2 = '0';
|
|
}
|
|
|
|
/* Gate 1 */
|
|
for(j = 0; j < 12; j++) {
|
|
gate_input[j] = '0';
|
|
}
|
|
|
|
gate_input[0] = u1;
|
|
gate_input[1] = top_reg[0];
|
|
gate_input[2] = top_reg[3]; /* ? top_reg[2] ? */
|
|
gate_input[3] = top_reg[4];
|
|
gate_input[4] = top_reg[5];
|
|
gate_input[5] = top_reg[6];
|
|
gate_input[6] = top_reg[9];
|
|
gate_input[7] = low_reg[2];
|
|
gate_input[8] = low_reg[6];
|
|
gate_input[9] = low_reg[7];
|
|
gate_input[10] = low_reg[10];
|
|
|
|
count = 0;
|
|
for(j = 0; j < 11; j++) {
|
|
if(gate_input[j] == '1') {
|
|
count++;
|
|
}
|
|
}
|
|
if((count & 0x01) == 0x01) { output[0] = '1'; } else { output[0] = '0'; }
|
|
|
|
/* Gate 2 */
|
|
for(j = 0; j < 12; j++) {
|
|
gate_input[j] = '0';
|
|
}
|
|
|
|
gate_input[0] = top_reg[0];
|
|
gate_input[1] = top_reg[2]; /* ? top_reg[3] ? */
|
|
gate_input[2] = top_reg[4];
|
|
gate_input[3] = top_reg[7];
|
|
gate_input[4] = top_reg[8];
|
|
gate_input[5] = top_reg[9];
|
|
gate_input[6] = u2;
|
|
gate_input[7] = low_reg[2];
|
|
gate_input[8] = low_reg[5];
|
|
gate_input[9] = low_reg[7];
|
|
gate_input[10] = low_reg[8];
|
|
|
|
count = 0;
|
|
for(j = 0; j < 11; j++) {
|
|
if(gate_input[j] == '1') {
|
|
count++;
|
|
}
|
|
}
|
|
if((count & 0x01) == 0x01) { output[1] = '1'; } else { output[1] = '0'; }
|
|
|
|
/* Gate 3 */
|
|
for(j = 0; j < 12; j++) {
|
|
gate_input[j] = '0';
|
|
}
|
|
|
|
gate_input[0] = u1;
|
|
gate_input[1] = top_reg[4];
|
|
gate_input[2] = top_reg[5];
|
|
gate_input[3] = top_reg[6];
|
|
gate_input[4] = u2;
|
|
gate_input[5] = low_reg[0];
|
|
gate_input[6] = low_reg[1];
|
|
gate_input[7] = low_reg[3];
|
|
gate_input[8] = low_reg[6];
|
|
gate_input[9] = low_reg[8];
|
|
gate_input[10] = low_reg[10];
|
|
|
|
count = 0;
|
|
for(j = 0; j < 11; j++) {
|
|
if(gate_input[j] == '1') {
|
|
count++;
|
|
}
|
|
}
|
|
if((count & 0x01) == 0x01) { output[2] = '1'; } else { output[2] = '0'; }
|
|
|
|
output[3] = '\0';
|
|
|
|
concat(protected_stream, output);
|
|
|
|
/* Shift registers right */
|
|
top_reg[9] = top_reg[8];
|
|
top_reg[8] = top_reg[7];
|
|
top_reg[7] = top_reg[6];
|
|
top_reg[6] = top_reg[5];
|
|
top_reg[5] = top_reg[4];
|
|
top_reg[4] = top_reg[3];
|
|
top_reg[3] = top_reg[2];
|
|
top_reg[2] = top_reg[1];
|
|
top_reg[1] = top_reg[0];
|
|
top_reg[0] = u1;
|
|
low_reg[10] = low_reg[9];
|
|
low_reg[9] = low_reg[8];
|
|
low_reg[8] = low_reg[7];
|
|
low_reg[7] = low_reg[6];
|
|
low_reg[6] = low_reg[5];
|
|
low_reg[5] = low_reg[4];
|
|
low_reg[4] = low_reg[3];
|
|
low_reg[3] = low_reg[2];
|
|
low_reg[2] = low_reg[1];
|
|
low_reg[1] = low_reg[0];
|
|
low_reg[0] = u2;
|
|
|
|
}
|
|
}
|
|
|
|
void protect_ecc100(char protected_stream[], char unprotected_stream[])
|
|
{
|
|
/* ECC 100 - 2-1-15 convolutional code */
|
|
/* State machine illustrated in figure k3 */
|
|
char reg[16];
|
|
char u;
|
|
char output[3];
|
|
char gate_input[10];
|
|
int i, j, count, blocks;
|
|
|
|
strcpy(protected_stream, "");
|
|
|
|
for(i = 0; i < 16; i++) {
|
|
reg[i] = '0';
|
|
}
|
|
|
|
blocks = strlen(unprotected_stream);
|
|
blocks += 15;
|
|
for(i = 0; i < blocks; i++) {
|
|
if(i < (blocks - 15)) {
|
|
u = unprotected_stream[i];
|
|
} else {
|
|
u = '0';
|
|
}
|
|
|
|
/* Gate 1 */
|
|
for(j = 0; j < 10; j++) {
|
|
gate_input[j] = '0';
|
|
}
|
|
|
|
gate_input[0] = u;
|
|
gate_input[1] = reg[1];
|
|
gate_input[2] = reg[4];
|
|
gate_input[3] = reg[5];
|
|
gate_input[4] = reg[6];
|
|
gate_input[5] = reg[7];
|
|
gate_input[6] = reg[8];
|
|
gate_input[7] = reg[9];
|
|
gate_input[8] = reg[14];
|
|
|
|
count = 0;
|
|
for(j = 0; j < 9; j++) {
|
|
if(gate_input[j] == '1') {
|
|
count++;
|
|
}
|
|
}
|
|
if((count & 0x01) == 0x01) { output[0] = '1'; } else { output[0] = '0'; }
|
|
|
|
/* Gate 2 */
|
|
for(j = 0; j < 10; j++) {
|
|
gate_input[j] = '0';
|
|
}
|
|
|
|
gate_input[0] = u;
|
|
gate_input[1] = reg[0];
|
|
gate_input[2] = reg[2];
|
|
gate_input[3] = reg[3];
|
|
gate_input[4] = reg[5];
|
|
gate_input[5] = reg[10];
|
|
gate_input[6] = reg[12];
|
|
gate_input[7] = reg[13];
|
|
gate_input[8] = reg[14];
|
|
|
|
count = 0;
|
|
for(j = 0; j < 9; j++) {
|
|
if(gate_input[j] == '1') {
|
|
count++;
|
|
}
|
|
}
|
|
if((count & 0x01) == 0x01) { output[1] = '1'; } else { output[1] = '0'; }
|
|
|
|
output[2] = '\0';
|
|
|
|
concat(protected_stream, output);
|
|
|
|
/* Shift register right */
|
|
reg[14] = reg[13];
|
|
reg[13] = reg[12];
|
|
reg[12] = reg[11];
|
|
reg[11] = reg[10];
|
|
reg[10] = reg[9];
|
|
reg[9] = reg[8];
|
|
reg[8] = reg[7];
|
|
reg[7] = reg[6];
|
|
reg[6] = reg[5];
|
|
reg[5] = reg[4];
|
|
reg[4] = reg[3];
|
|
reg[3] = reg[2];
|
|
reg[2] = reg[1];
|
|
reg[1] = reg[0];
|
|
reg[0] = u;
|
|
}
|
|
}
|
|
|
|
void protect_ecc140(char protected_stream[], char unprotected_stream[])
|
|
{
|
|
/* ECC 140 - 4-1-13 convolutional coding */
|
|
/* State machine illustrated in figure k3 */
|
|
char reg[13];
|
|
char u;
|
|
char output[5];
|
|
char gate_input[12];
|
|
int i, j, count, blocks;
|
|
|
|
strcpy(protected_stream, "");
|
|
|
|
for(i = 0; i < 13; i++) {
|
|
reg[i] = '0';
|
|
}
|
|
|
|
blocks = strlen(unprotected_stream);
|
|
blocks += 13;
|
|
for(i = 0; i < blocks; i++) {
|
|
if(i < (blocks - 13)) {
|
|
u = unprotected_stream[i];
|
|
} else {
|
|
u = '0';
|
|
}
|
|
|
|
/* Gate 1 */
|
|
for(j = 0; j < 12; j++) {
|
|
gate_input[j] = '0';
|
|
}
|
|
|
|
gate_input[0] = u;
|
|
gate_input[1] = reg[3];
|
|
gate_input[2] = reg[6];
|
|
gate_input[3] = reg[9];
|
|
gate_input[4] = reg[11];
|
|
gate_input[5] = reg[12];
|
|
|
|
count = 0;
|
|
for(j = 0; j < 6; j++) {
|
|
if(gate_input[j] == '1') {
|
|
count++;
|
|
}
|
|
}
|
|
if((count & 0x01) == 0x01) { output[0] = '1'; } else { output[0] = '0'; }
|
|
|
|
/* Gate 2 */
|
|
for(j = 0; j < 12; j++) {
|
|
gate_input[j] = '0';
|
|
}
|
|
|
|
gate_input[0] = u;
|
|
gate_input[1] = reg[2];
|
|
gate_input[2] = reg[3];
|
|
gate_input[3] = reg[6];
|
|
gate_input[4] = reg[7];
|
|
gate_input[5] = reg[8];
|
|
gate_input[6] = reg[9];
|
|
gate_input[7] = reg[10];
|
|
gate_input[8] = reg[12];
|
|
|
|
count = 0;
|
|
for(j = 0; j < 9; j++) {
|
|
if(gate_input[j] == '1') {
|
|
count++;
|
|
}
|
|
}
|
|
if((count & 0x01) == 0x01) { output[1] = '1'; } else { output[1] = '0'; }
|
|
|
|
/* Gate 3 */
|
|
for(j = 0; j < 12; j++) {
|
|
gate_input[j] = '0';
|
|
}
|
|
|
|
gate_input[0] = u;
|
|
gate_input[1] = reg[0];
|
|
gate_input[2] = reg[1];
|
|
gate_input[3] = reg[3];
|
|
gate_input[4] = reg[4];
|
|
gate_input[5] = reg[6];
|
|
gate_input[6] = reg[8];
|
|
gate_input[7] = reg[10];
|
|
gate_input[8] = reg[11];
|
|
gate_input[9] = reg[12];
|
|
|
|
count = 0;
|
|
for(j = 0; j < 10; j++) {
|
|
if(gate_input[j] == '1') {
|
|
count++;
|
|
}
|
|
}
|
|
if((count & 0x01) == 0x01) { output[2] = '1'; } else { output[2] = '0'; }
|
|
|
|
/* Gate 4 */
|
|
for(j = 0; j < 12; j++) {
|
|
gate_input[j] = '0';
|
|
}
|
|
|
|
gate_input[0] = u;
|
|
gate_input[1] = reg[0];
|
|
gate_input[2] = reg[1];
|
|
gate_input[3] = reg[3];
|
|
gate_input[4] = reg[4];
|
|
gate_input[5] = reg[6];
|
|
gate_input[6] = reg[8];
|
|
gate_input[7] = reg[9];
|
|
gate_input[8] = reg[10];
|
|
gate_input[9] = reg[11];
|
|
gate_input[10] = reg[12];
|
|
|
|
count = 0;
|
|
for(j = 0; j < 11; j++) {
|
|
if(gate_input[j] == '1') {
|
|
count++;
|
|
}
|
|
}
|
|
if((count & 0x01) == 0x01) { output[3] = '1'; } else { output[3] = '0'; }
|
|
|
|
output[4] = '\0';
|
|
|
|
concat(protected_stream, output);
|
|
|
|
/* Shift register right */
|
|
reg[12] = reg[11];
|
|
reg[11] = reg[10];
|
|
reg[10] = reg[9];
|
|
reg[9] = reg[8];
|
|
reg[8] = reg[7];
|
|
reg[7] = reg[6];
|
|
reg[6] = reg[5];
|
|
reg[5] = reg[4];
|
|
reg[4] = reg[3];
|
|
reg[3] = reg[2];
|
|
reg[2] = reg[1];
|
|
reg[1] = reg[0];
|
|
reg[0] = u;
|
|
}
|
|
|
|
}
|
|
|
|
int matrix89(struct zint_symbol *symbol, unsigned char source[])
|
|
{
|
|
int i, j, input_length, scheme;
|
|
input_length = ustrlen(source);
|
|
char unprotected_stream[2210];
|
|
char data_prefix_bitstream[31];
|
|
char protected_stream[6630];
|
|
char unrandomized_stream[2210];
|
|
char master_random_stream[2214];
|
|
char randomized_stream[2210];
|
|
char header[20];
|
|
int symbol_size, hex_segment, width;
|
|
int error_number;
|
|
|
|
error_number = 0;
|
|
|
|
symbol_size = 0;
|
|
for(i = 0; i < input_length; i++) {
|
|
if(source[i] > 127) {
|
|
strcpy(symbol->errtxt, "Data Matrix ECC 000 - 140 doesn't support extended ASCII");
|
|
return ERROR_INVALID_DATA;
|
|
}
|
|
}
|
|
|
|
/* Decide which encoding scheme to use */
|
|
scheme = 128;
|
|
if(!(is_sane(B41SET, source))) { scheme = 41; }
|
|
if(!(is_sane(B37SET, source))) { scheme = 37; }
|
|
if(!(is_sane(B27SET, source))) { scheme = 27; }
|
|
if(!(is_sane(B11SET, source))) { scheme = 11; }
|
|
|
|
/* Data Prefix Bit Stream = Format ID + CRC + Data Length */
|
|
|
|
/* Format ID (5 bits) */
|
|
switch(scheme) {
|
|
case 11: strcpy(data_prefix_bitstream, "00000"); break;
|
|
case 27: strcpy(data_prefix_bitstream, "00001"); break;
|
|
case 37: strcpy(data_prefix_bitstream, "00011"); break;
|
|
case 41: strcpy(data_prefix_bitstream, "00010"); break;
|
|
default: strcpy(data_prefix_bitstream, "00100"); break;
|
|
}
|
|
|
|
/* CRC Value (16 bit) */
|
|
crc_machine(data_prefix_bitstream, scheme, source);
|
|
|
|
/* Data length (9 bit) */
|
|
if(input_length & 0x01) { concat(data_prefix_bitstream, "1"); } else { concat(data_prefix_bitstream, "0"); }
|
|
if(input_length & 0x02) { concat(data_prefix_bitstream, "1"); } else { concat(data_prefix_bitstream, "0"); }
|
|
if(input_length & 0x04) { concat(data_prefix_bitstream, "1"); } else { concat(data_prefix_bitstream, "0"); }
|
|
if(input_length & 0x08) { concat(data_prefix_bitstream, "1"); } else { concat(data_prefix_bitstream, "0"); }
|
|
if(input_length & 0x10) { concat(data_prefix_bitstream, "1"); } else { concat(data_prefix_bitstream, "0"); }
|
|
if(input_length & 0x20) { concat(data_prefix_bitstream, "1"); } else { concat(data_prefix_bitstream, "0"); }
|
|
if(input_length & 0x40) { concat(data_prefix_bitstream, "1"); } else { concat(data_prefix_bitstream, "0"); }
|
|
if(input_length & 0x80) { concat(data_prefix_bitstream, "1"); } else { concat(data_prefix_bitstream, "0"); }
|
|
if(input_length & 0x100) { concat(data_prefix_bitstream, "1"); } else { concat(data_prefix_bitstream, "0"); }
|
|
|
|
/* Unprotected Bit Stream = Data Prefix Bitstream + Encoded Data */
|
|
|
|
strcpy(unprotected_stream, data_prefix_bitstream);
|
|
|
|
switch(scheme) {
|
|
case 11:
|
|
if(input_length >= 618) {
|
|
strcpy(symbol->errtxt, "Input data too long"); return ERROR_TOO_LONG;
|
|
}
|
|
break;
|
|
case 27:
|
|
if(input_length >= 450) {
|
|
strcpy(symbol->errtxt, "Input data too long"); return ERROR_TOO_LONG;
|
|
}
|
|
break;
|
|
case 37:
|
|
if(input_length >= 412) {
|
|
strcpy(symbol->errtxt, "Input data too long"); return ERROR_TOO_LONG;
|
|
}
|
|
break;
|
|
case 41:
|
|
if(input_length >= 396) {
|
|
strcpy(symbol->errtxt, "Input data too long"); return ERROR_TOO_LONG;
|
|
}
|
|
break;
|
|
case 128:
|
|
if(input_length >= 311) {
|
|
strcpy(symbol->errtxt, "Input data too long"); return ERROR_TOO_LONG;
|
|
}
|
|
break;
|
|
}
|
|
|
|
switch(scheme) {
|
|
case 11: i1_base11(unprotected_stream, source); break;
|
|
case 27: i2_base27(unprotected_stream, source); break;
|
|
case 37: i3_base37(unprotected_stream, source); break;
|
|
case 41: i4_base41(unprotected_stream, source); break;
|
|
default: base128(unprotected_stream, source); break;
|
|
}
|
|
|
|
/* Header (ECC Bit field) LSB first */
|
|
switch(symbol->option_1) {
|
|
case 2: strcpy(header, "0111111"); break; /* ECC 000 */
|
|
case 3: strcpy(header, "0111000000000111000"); break; /* ECC 050 */
|
|
case 4: strcpy(header, "0111000000111000111"); break; /* ECC 080 */
|
|
case 5: strcpy(header, "0111000000111111111"); break; /* ECC 100 */
|
|
case 6: strcpy(header, "0111000111000111111"); break; /* ECC 140 */
|
|
}
|
|
|
|
/* Generate Protected Bit Stream */
|
|
switch(symbol->option_1) {
|
|
case 2: protect_ecc000(protected_stream, unprotected_stream); break;
|
|
case 3: protect_ecc050(protected_stream, unprotected_stream); break;
|
|
case 4: protect_ecc080(protected_stream, unprotected_stream); break;
|
|
case 5: protect_ecc100(protected_stream, unprotected_stream); break;
|
|
case 6: protect_ecc140(protected_stream, unprotected_stream); break;
|
|
}
|
|
|
|
if((strlen(protected_stream) + strlen(header)) > 2209) {
|
|
strcpy(symbol->errtxt, "Input data too long");
|
|
return ERROR_TOO_LONG;
|
|
}
|
|
|
|
/* Construct Unrandomized Bit Stream */
|
|
strcpy(unrandomized_stream, header);
|
|
concat(unrandomized_stream, protected_stream);
|
|
|
|
/* Determine Symbol Size */
|
|
for(i = 20; i >= 0; i--) {
|
|
if(MatrixMaxCapacities[i] > strlen(unrandomized_stream)) {
|
|
symbol_size = i;
|
|
}
|
|
}
|
|
|
|
if((symbol->option_2 < 0) || (symbol->option_2 > 21)) {
|
|
strcpy(symbol->errtxt, "Invalid symbol size");
|
|
error_number = WARN_INVALID_OPTION;
|
|
symbol->option_2 = 0;
|
|
}
|
|
|
|
if((symbol->option_2 - 1) > symbol_size) {
|
|
symbol_size = (symbol->option_2 - 1);
|
|
}
|
|
|
|
if(((symbol->option_2 - 1) < symbol_size) && (symbol->option_2 != 0)) {
|
|
strcpy(symbol->errtxt, "Unable to fit data in specified symbol size");
|
|
error_number = WARN_INVALID_OPTION;
|
|
}
|
|
|
|
/* Add trailer (pad bits) */
|
|
input_length = strlen(unrandomized_stream);
|
|
for(i = input_length; i < MatrixMaxCapacities[symbol_size]; i++) {
|
|
concat(unrandomized_stream, "0");
|
|
}
|
|
|
|
/* Load master random stream */
|
|
strcpy(master_random_stream, "");
|
|
for(i = 0; i < 276; i++) {
|
|
hex_segment = MasterRandomStream[i];
|
|
if(hex_segment & 0x80) { concat(master_random_stream, "1"); } else { concat(master_random_stream, "0"); }
|
|
if(hex_segment & 0x40) { concat(master_random_stream, "1"); } else { concat(master_random_stream, "0"); }
|
|
if(hex_segment & 0x20) { concat(master_random_stream, "1"); } else { concat(master_random_stream, "0"); }
|
|
if(hex_segment & 0x10) { concat(master_random_stream, "1"); } else { concat(master_random_stream, "0"); }
|
|
if(hex_segment & 0x08) { concat(master_random_stream, "1"); } else { concat(master_random_stream, "0"); }
|
|
if(hex_segment & 0x04) { concat(master_random_stream, "1"); } else { concat(master_random_stream, "0"); }
|
|
if(hex_segment & 0x02) { concat(master_random_stream, "1"); } else { concat(master_random_stream, "0"); }
|
|
if(hex_segment & 0x01) { concat(master_random_stream, "1"); } else { concat(master_random_stream, "0"); }
|
|
}
|
|
|
|
/* Randomizing Algorithm */
|
|
|
|
strcpy(randomized_stream, "");
|
|
for(i = 0; i < strlen(unrandomized_stream); i++) {
|
|
if(unrandomized_stream[i] != master_random_stream[i]) {
|
|
concat(randomized_stream, "1");
|
|
} else {
|
|
concat(randomized_stream, "0");
|
|
}
|
|
}
|
|
|
|
/* Placement Algorithm */
|
|
width = (symbol_size * 2) + 7;
|
|
|
|
symbol->row_height[0] = 1;
|
|
/* Fill corners */
|
|
set_module(symbol, 0, 0);
|
|
set_module(symbol, 0, width + 1);
|
|
set_module(symbol, width + 1, 0);
|
|
set_module(symbol, width + 1, width + 1);
|
|
for(i = 0; i < width; i++) {
|
|
/* Fill sides */
|
|
set_module(symbol, i + 1, 0);
|
|
set_module(symbol, width + 1, i + 1);
|
|
if((i % 2) == 0) {
|
|
set_module(symbol, i, width + 1);
|
|
set_module(symbol, 0, i);
|
|
}
|
|
for(j = 0; j < width; j++) {
|
|
|
|
switch(symbol_size) {
|
|
case 0: if(randomized_stream[tableh1[(i * width) + j]] == '1') { set_module(symbol, i + 1, j + 1); } break;
|
|
case 1: if(randomized_stream[tableh2[(i * width) + j]] == '1') { set_module(symbol, i + 1, j + 1); } break;
|
|
case 2: if(randomized_stream[tableh3[(i * width) + j]] == '1') { set_module(symbol, i + 1, j + 1); } break;
|
|
case 3: if(randomized_stream[tableh4[(i * width) + j]] == '1') { set_module(symbol, i + 1, j + 1); } break;
|
|
case 4: if(randomized_stream[tableh5[(i * width) + j]] == '1') { set_module(symbol, i + 1, j + 1); } break;
|
|
case 5: if(randomized_stream[tableh6[(i * width) + j]] == '1') { set_module(symbol, i + 1, j + 1); } break;
|
|
case 6: if(randomized_stream[tableh7[(i * width) + j]] == '1') { set_module(symbol, i + 1, j + 1); } break;
|
|
case 7: if(randomized_stream[tableh8[(i * width) + j]] == '1') { set_module(symbol, i + 1, j + 1); } break;
|
|
case 8: if(randomized_stream[tableh9[(i * width) + j]] == '1') { set_module(symbol, i + 1, j + 1); } break;
|
|
case 9: if(randomized_stream[tableh10[(i * width) + j]] == '1') { set_module(symbol, i + 1, j + 1); } break;
|
|
case 10: if(randomized_stream[tableh11[(i * width) + j]] == '1') { set_module(symbol, i + 1, j + 1); } break;
|
|
case 11: if(randomized_stream[tableh12[(i * width) + j]] == '1') { set_module(symbol, i + 1, j + 1); } break;
|
|
case 12: if(randomized_stream[tableh13[(i * width) + j]] == '1') { set_module(symbol, i + 1, j + 1); } break;
|
|
case 13: if(randomized_stream[tableh14[(i * width) + j]] == '1') { set_module(symbol, i + 1, j + 1); } break;
|
|
case 14: if(randomized_stream[tableh15[(i * width) + j]] == '1') { set_module(symbol, i + 1, j + 1); } break;
|
|
case 15: if(randomized_stream[tableh16[(i * width) + j]] == '1') { set_module(symbol, i + 1, j + 1); } break;
|
|
case 16: if(randomized_stream[tableh17[(i * width) + j]] == '1') { set_module(symbol, i + 1, j + 1); } break;
|
|
case 17: if(randomized_stream[tableh18[(i * width) + j]] == '1') { set_module(symbol, i + 1, j + 1); } break;
|
|
case 18: if(randomized_stream[tableh19[(i * width) + j]] == '1') { set_module(symbol, i + 1, j + 1); } break;
|
|
case 19: if(randomized_stream[tableh20[(i * width) + j]] == '1') { set_module(symbol, i + 1, j + 1); } break;
|
|
case 20: if(randomized_stream[tableh21[(i * width) + j]] == '1') { set_module(symbol, i + 1, j + 1); } break;
|
|
}
|
|
}
|
|
symbol->row_height[i + 1] = 1;
|
|
}
|
|
|
|
symbol->row_height[width + 1] = 1;
|
|
symbol->rows = width + 2;
|
|
symbol->width = width + 2;
|
|
|
|
return error_number;
|
|
}
|
|
|
|
int dmatrix(struct zint_symbol *symbol, unsigned char source[])
|
|
{
|
|
int error_number;
|
|
|
|
if(symbol->option_1 <= 1) {
|
|
/* ECC 200 */
|
|
error_number = data_matrix_200(symbol, source);
|
|
} else {
|
|
/* ECC 000 - 140 */
|
|
error_number = matrix89(symbol, source);
|
|
}
|
|
|
|
return error_number;
|
|
}
|