/*	clrll17.c -- Cirrus Logic RLL 1,7 encoder and decoder
 *
 *
 *			Code Tables
 *
 *			NRZ	RLL
 *			============
 *			00	010
 *			10	x01
 *			11	x00
 *			0100	010001
 *			0101	010000
 *			0110	x00001
 *			0111	x00000
 *
 *	In the table, the symbol 'x' means to complement the previous bit.
 *	All table entries are read left to right.
 */

typedef unsigned char byte;
int clrll17_encoder(byte *data,byte *code,int n)
{
	int tmp,lastbit,icount,ocount,flag,outcode;
	
/* check for valid array size */
	if (n < 4) return 1;
	lastbit = 0;
	icount=ocount=0;
	while (icount < n-4) {
		tmp = (data[icount] << 1) + data[icount+1];
		icount += 2;
		flag = 2;
		switch (tmp) {
			case 0: {
				outcode = 2;
				break;
			}
			case 2: {
				outcode = 1 + ((1-lastbit) << 2);
				break;
			}
			case 3: {
				outcode = ((1-lastbit) << 2);
				break;
			}
			case 1: {
				flag = 4;
				tmp = (data[icount] << 1) + data[icount+1];
				icount += 2;
				switch (tmp) {
					case 0: {
						outcode = 17;
						break;
					}
					case 1: {
						outcode = 16;
						break;
					}
					case 2: {
						outcode = 1 + ((1-lastbit) << 5);
						break;
					}
					case 3: {
						outcode = ((1-lastbit) << 5);
						break;
					}
				}
			}
		}
		if (flag == 4) {
			code[ocount++] = (outcode & 32) > 0;
			code[ocount++] = (outcode & 16) > 0;
			code[ocount++] = (outcode & 8) > 0;
			
		}
		code[ocount++] = (outcode & 4) > 0;
		code[ocount++] = (outcode & 2) > 0;
		code[ocount++] = (outcode & 1) > 0;
		lastbit = (outcode & 1);
	}	
	return 0;	
}

int clrll17_decoder(byte *code, byte *data, int n)
{
	int icount,ocount,flag,tmp,tmp2,outcode;
	
/* check for valid array size */
	if (n == 6) return 1;
	
	icount=ocount=0;
	while (icount < n-6) {
		tmp = (code[icount] << 2) + (code[icount+1] << 1) + code[icount+2];
		icount += 3;
		tmp2 = (code[icount] << 2) + (code[icount+1] << 1) + code[icount+2];
		flag = 3;
		switch (tmp) {
			case 2: {
				outcode = 0;
				if (tmp2 == 1) {
					outcode = 4;
					flag = 6;
				}
				if (tmp2 == 0) {
					outcode = 5;
					flag = 6;
				} 
				break;
			}
			case 1: {
				outcode = 2;
				break;
			}
			case 5: {
				outcode = 2;
				break;
			}
			case 0: {
				outcode = 3;
				if (tmp2 == 0) {
					outcode = 7;
					flag = 6;
				}
				if (tmp2 == 1) {
					outcode = 6;
					flag = 6;
				}
				break;
			}
			case 4: {
				outcode = 3;
				if (tmp2 == 0) {
					outcode = 7;
					flag = 6;
				}
				if (tmp2 == 1) {
					outcode = 6;
					flag = 6;
				}
				break;
			}
		}
		if (flag == 6) {
			data[ocount++] = 0;
			data[ocount++] = 1;
			icount += 3;
		}
		data[ocount++] = (outcode & 2) > 0;
		data[ocount++] = (outcode & 1) > 0;
	}
	return 0;
	
}

