#include "C:\PIC\16f819-1\C LCD\LCD Driver.h"
   #include <math.h>
  #include <stdio.h>
  #include <stddef.h>
  #include <stdlib.h>
  #include <string.h>

#use delay (clock=8000000)
#fuses PUT,NOWDT,NOBROWNOUT,NOPROTECT,NOMCLR,INTRC_IO

char Track_1[80];
char string[32];
int T1_Offset;

void Clock_LCD()
{
   output_bit(PIN_A1, 1);
   delay_us(275);
   output_bit(PIN_A1, 0);
}

void LCD_cmd()
{
   output_bit(PIN_A0, 0);
   Clock_LCD();
}

void Clear_LCD()
{
   output_b(0x01);
   LCD_cmd();
   delay_ms(200);
}

void Enable_LCD()
{
   output_b(0x0e);
   LCD_cmd();
}

void LCD_char_out(char character)
{
   output_bit(PIN_A0, 1);
   output_b(character);
   Clock_LCD();
}

void Print_LCD(char *str_ptr)
{
   char *ptr;
   
   ptr = str_ptr;
   while(*ptr != 0)
   {
      LCD_char_out(*ptr);
      ptr++;
   }
}

void Position_LCD(int line, int offset)
{
   int _offset;
   
   switch(line)
   {
   case 0 : _offset = 0;
            break;
   case 1 : _offset = 0x40;
            break;
   case 2 : _offset = 0x14;
            break;
   case 3 : _offset = 0x54;
            break;
   }
   _offset += offset;
   _offset |= 0x80;
   output_b(_offset);
   LCD_cmd();
}

void Set_8bit_LCD()
{
   output_b(0x38);
   LCD_cmd();
}

void init_LCD()
{
   delay_ms(15);
   Set_8bit_LCD();
   delay_ms(5);
   Set_8bit_LCD();
   delay_us(100);
   Enable_LCD();
   Clear_LCD();
   strcpy(string, " LCD Driver Ver 1.0");
   Position_LCD(1,0);
   Print_LCD(string);
   strcpy(string, " Copyright (C) 2007");
   Position_LCD(2,0);
   Print_LCD(string);
   strcpy(string, "    CyberDefense");
   Position_LCD(3,0);
   Print_LCD(string);
   delay_ms(3000);
   Clear_LCD();
}

void Strobe_Reader()
{
   output_bit(PIN_A2, 1);
   delay_us(10);
   output_bit(PIN_A2, 0);
   delay_us(10);
}

int Card_Present()
{
   int bit;
   bit = input(PIN_A3); // Double read - seems to hold last value before re-TRIS
   bit = input(PIN_A3);
   bit ^= 0x01;
   return(bit);
}

int Read_Bit()
{
	int abit;
	Strobe_Reader();
	abit = input(PIN_A3);
	abit ^= 0x01;
	return(abit);
}

char Read_7_Byte()
{
   char retval;

	retval = 0;
	retval += (Read_Bit() * 64);
	retval += (Read_Bit() * 32);
	retval += (Read_Bit() * 16);
	retval += (Read_Bit() * 8);
	retval += (Read_Bit() * 4);
	retval += (Read_Bit() * 2);
	retval += (Read_Bit() * 1);
	retval = retval & 0x3f;
	retval += 32;
   return(retval);
}

char Read_5_Byte()
{
   char character[1];
   char retval;
   int bit;

	character[0] = 0;
	shift_left(character,1,Read_Bit());
	shift_left(character,1,Read_Bit());
	shift_left(character,1,Read_Bit());
	shift_left(character,1,Read_Bit());
	shift_left(character,1,Read_Bit());
	character[0] &= 0x0f;
	retval = character[0] + 48; // Shift to ASCII
   return(retval);
}
   
int Find_Start_Track_1()
{
	int piggy;
	int16 i, j;
	piggy = 0;

	for(i = 0; i != 80; i++)
	{
		piggy = Read_7_Byte();
		if(piggy == '?')  // % is start, ? is end... We're reading backwards.
		{ 
			for(j = 0; j != 79; j++)
			{
				piggy = Read_7_Byte();
				Track_1[78-j] = piggy;
				if(piggy == '%') { Track_1[j] = 0; return (78-j); }
			}
			return(0); 
		}

	}
}

void Find_Start_Track_2()
{
	int piggy[1];
	int16 i;
	piggy[0] = 0;
	
	for(i = 0; i != 4500; i++)
	{
		shift_left(piggy, 1, Read_Bit());
		if((piggy[0] & 0x1f) == 0x0b) { return; }
	}
	return;
}
   
void init_Card_Reader()
{
   set_tris_a(0x0c); // 00001100
   output_bit(PIN_A3, 1);
   delay_us(5);
   output_bit(PIN_A2, 1);
   delay_us(10);
   output_bit(PIN_A3, 0);
   Strobe_Reader();
   Strobe_Reader();
   set_tris_a(0x04); // 00001000
   Strobe_Reader();
   Strobe_Reader();
}

void main()
{
   int character;
   int16 i;

   setup_adc_ports(NO_ANALOGS);

   setup_adc(ADC_OFF);
   setup_spi(FALSE);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
   setup_timer_2(T2_DISABLED,0,1);
   setup_oscillator(OSC_8MHZ);
#use fast_io(A)
#use fast_io(B)
   set_tris_a(0x04); // 00001000
   set_tris_b(0);
   enable_interrupts(INT_TIMER1);
   enable_interrupts(GLOBAL);
   setup_oscillator(OSC_8MHZ);

	T1_Offset = 3;
   // TODO: USER CODE!!
   init_LCD();
   while(1)
   {
      Clear_LCD();
      strcpy(string, "Resetting reader");
      Position_LCD(0,0);
      Print_LCD(string);
      init_Card_Reader();
      sprintf(string, "Reader Armed:    ");
      Position_LCD(0,0);
      Print_LCD(string);
      while(! Card_Present()) { ; }
      strcpy(string, "Card Present ");
      Position_LCD(0,0);
      Print_LCD(string);
      Strobe_Reader();
      strcpy(string, "Awaiting Buffer ");
      Position_LCD(1,0);
      Print_LCD(string);
      while(input(PIN_A3)) { ; }
      Clear_LCD();
		for(i=0;i!=T1_Offset;i++) { Read_Bit(); }
		i = Find_Start_Track_1();
		{
      		Clear_LCD();
			Position_LCD(0,0);
			Print_LCD(Track_1+i);
			delay_ms(15000);
		}
	Clear_LCD();
   }
}

