/* rll17.c -- encoder/decoder for rll17 (as defined by Jacoby and Kost)
 *  (C) 2001, C. Bond. All rights reserved.
 *
 * 		Code Tables
 *
 *	Primary code table (read sequence from left to right)
 *
 *	source bits		code bits
 *	   00			  101
 *     01             100
 *	   10			  001
 *	   11			  010
 *
 *  Auxiliary table (to avoid invalid concatenation)
 *
 *	source bits		code bits
 *	  00.00			 101.000
 *	  00.01			 100.000
 *	  10.00			 001.000
 *	  10.01			 010.000
 *
 *  To interpret the above encoding rules, examine the Primary code table
 *  to determine the three output code bits corresponding to the various
 *  combinations of two source bits. Since the requirements of an RLL 1,7
 *  code prohibit adjacent ones, some means must be imposed to prevent
 *  code groups beginning with '1' from immediately following code groups
 *  ending with '1'. For example, if a pair of zeros '00' appears in the
 *  source stream and a '101' sequence is output, another pair of source
 *  zeros '00', must encode from the Auxiliary table '000'. Note that the
 *  source combination '00 01 10' outputs '100 000 001' which contains the
 *  longest possible run of zeros.
 */

int rll17_encoder(unsigned char *raw, unsigned char *code, int n)
/* 'raw' is a vector of ones and zeros with 1 bit per unsigned char (byte).
 *
 * 'n' is the number of bits in the source array, but note that this
 * is a 2/3 rate code so the destination (code) array must be 50% longer
 * than the source.
 *
 * The input array must be padded at the end by 4 bits to assure that all
 * desired bits are properly encoded. 
 *
 * NOTE: it is assumed by the following that each vector element is either
 * a one or a zero. No checking is done to test whether other numbers are
 * present. 
 */
{
	int i,icount,ocount,flag;
	unsigned char temp,otemp,lookahead;

/* check for invalid input parameter */
	if (n < 6) return 1;

	icount=ocount = 0;
	
	temp = raw[1]+(raw[0] << 1);
	lookahead = raw[3]+(raw[2] << 1);
	while (icount < n-4) {
		flag = 0;
		switch (temp) {
			case 0: {
				if (lookahead > 1) otemp = 5;
				else {
					flag = 1;
					if (lookahead == 0) otemp = 5;
					else otemp = 1;
				}
				break;
			}
			case 1: {
				otemp = 1;
				break;
			}
			case 2: {
				if (lookahead > 1) otemp = 4;
				else {
					flag = 1;
					if (lookahead == 0) otemp = 4;
					else otemp = 2;
				} 
				break;
			}
			case 3: {
				otemp = 2;
				break;
			}
		}
		icount += 2;
		if (flag != 0) icount += 2;
		temp = raw[icount+1]+(raw[icount] << 1);
		lookahead = raw[icount+3]+(raw[icount+2] << 1);
		for (i = 0; i < 3*(1+flag);i++)
			code[ocount++] = (otemp >> i) & 1;
	}
	return 0;
}	

int rll17_decoder(unsigned char *code,unsigned char *data, int n)
{
	int i,icount,ocount,flag;
	unsigned char temp,otemp1,otemp2,lookahead;	

	if (n < 6) return 1;
	icount = ocount = 0;
	temp = (code[0] << 2) + (code[1] << 1) + code[2];
	lookahead = (code[3] << 2) + (code[4] << 1) + code[5];
	while (icount < n-6) {
		flag = 0;	
		switch (temp) {
			case 1: {
				if (lookahead == 0) {
					flag = 1;
					otemp1 = 1;
					otemp2 = 0;
				}
				else otemp1 = 1;
				break;
			}
			case 2: {
				if (lookahead == 0) {
					flag = 1;
					otemp1 = 1;
					otemp2 = 2;
				}
				else otemp1 = 3;
				break;
			}
			case 4: {
				if (lookahead == 0) {
					flag = 1;
					otemp1 = 0;
					otemp2 = 2;
				}
				else otemp1 = 2;
				break;
			}
			case 5: {
				otemp1 = 0;
				break;
			}
		}
		icount += 3;
		if (flag != 0) icount += 3;
		temp = (code[icount] << 2) + (code[icount+1] << 1) 
			+ code[icount+2];
		lookahead = (code[icount+3] << 2) + (code[icount+4] << 1)
			 + code[icount+5];
		for (i = 0; i < 2; i++) 
			data[ocount++] = (otemp1 >> i) & 1;
		if (flag != 0) {
			for (i = 0;i < 2; i++)
				data[ocount++] = (otemp2 >> i) & 1;
		}
	}
	return 0;
}

	

