//--------------------------------------
// Disco Light Driver For the PIC12C50x
//              Version 2
// Has facility For RS-232 Interfacing
//      Using HiTech - C Compiler
//
// Author: M.O.Pearce
//
// Started: 18 - December -1997
//--------------------------------------

//-- Pin assignments as follow --
//== OUTPUTS ==
// GP0 - Lamp Drive 0
// GP1 - Lamp Drive 1
// GP2 - Lamp Drive 2
// GP4 - Lamp Drive 3  **** Note it is GP4 cause GP3 is input only
//== INPUTS ==
// GP3 - Beat / RS-232 RxD
// GP5 - Pattern Select / Address Select


#include <pic.h>


#define MAXSEQ  15
#define MAXPOS  7
#define BITNUM(adr, bit)       ((unsigned)(&adr)*8+(bit))
#define BAUD    2400
#define BITTIME  ((unsigned char) (((1000000/BAUD)/8)-3))   

static bit  Beat    @ BITNUM(GPIO, 3);  //- Beat input pin
static bit  Select  @ BITNUM(GPIO, 5);  //- Sequ Select pin
static bit  Rxd     @ BITNUM(GPIO, 3);  //- RS-232 RXD pin


unsigned char const PATTERN[(MAXSEQ+1)*(MAXPOS+1)] =
{ 
  0x17,0x0,0x80,0x80,0x80,0x80,0x80,0x80,
  0x10,0x4,0x2,0x1,0x80,0x80,0x80,0x80,
  0x1,0x1,0x17,0x10,0x10,0x17,0x80,0x80,
  0x17,0x7,0x3,0x1,0x0,0x10,0x14,0x16, 
  0x7,0x13,0x15,0x16,0x80,0x80,0x80,0x80, 
  0x0,0x10,0x0,0x1,0x0,0x4,0x0,0x2, 
  0x0,0x0,0x1,0x0,0x0,0x2,0x0,0x0, 
  0x6,0x11,0x80,0x80,0x80,0x80,0x80,0x80, 
  0x14,0x3,0x80,0x80,0x80,0x80,0x80,0x80, 
  0x1,0x3,0x7,0x17,0x7,0x3,0x1,0x0, 
  0x14,0x6,0x3,0x80,0x80,0x80,0x80,0x80, 
  0x10,0x10,0x1,0x1,0x80,0x80,0x80,0x80, 
  0x4,0x4,0x2,0x2,0x80,0x80,0x80,0x80, 
  0x17,0x17,0x17,0x0,0x80,0x80,0x80,0x80, 
  0x2,0x6,0x7,0x17,0x16,0x6,0x4,0x80, 
  0x10,0x2,0x4,0x1,0x2,0x10,0x1,0x4
};

  unsigned char Sequ,Pos;    // Sequence # and Position
  unsigned char KeyCnt1,KeyCnt2; // For auto inc of stuff
//-----------------------------------------------------
void delay(unsigned char ms);
void Run232(void),RunAuto(void);
void CheckKeys(void);
unsigned char getch(void);
void Init232(void);
//-----------------------------------------------------
struct
{
	  unsigned int InRx   :1;
	  unsigned int NewDat :1;
	  unsigned int RxErr  :1;
	  unsigned int Init   :1;
} Flags;

//-----------------------------------------------------


//*****************************************************
//  Main - Start of the program
//*****************************************************
main (void)
{
 OPTION=0xDF;    //- T0CS has to be low so GP2 is output
 TRIS = 0x28;    //- GP0,1,2,4 = Out GP3,5 = In
 Flags.Init=0;
 if(Select==0)
 {
	  //-- if Select held low on reset  =  RS-232 mode
   Run232();
 }
 else
 {
	  RunAuto();
 }
}
//********** END OF main
//*****************************************************
// Run232 - Runs the RS-232 Routines
//*****************************************************
void Run232(void)
{
	while(1)
	{
	 GPIO=getch();    //-- read serial input and output to port
	}
//  RunAuto();  //- No RS-232 Routines yet
}
//********** END OF Run232

//*****************************************************
// RunAuto - Runs the Standalone auto routines
//*****************************************************
void RunAuto(void)
{
  unsigned char Data,error;
  Sequ=0,Pos=0,KeyCnt1=0,KeyCnt2=0;
  while(1) // Loop Forever
  {
	  error=10;
	  while((Data=PATTERN[(Sequ*(MAXPOS+1))+Pos]) >128 && error > 0)
	  {
		  //-- Check for end of pattern
		  Pos=0;
		  error--; //-- dec error until == 0
	  } 
	  GPIO=Data;           //-- Output the data to the port
	  CheckKeys();
 }
}
//********** END OF RunAuto
//*****************************************************
// CheckKeys - checks the keys + Auto repeats
//*****************************************************
void CheckKeys(void)
{
	//-- Check the Beat Key --
	if(KeyCnt1==0)
	{
	 if(Beat==0)                  //-- if previously released + now held
	 {
	  KeyCnt1++;                  //-- inc how long key pressed
	  if((Pos++)>MAXPOS) Pos=0;   //-- check position in data + reset if needed
	 }
	}
	else
	{
	 if(Beat==0)                 //-- if still held down ( not released yet)
	 {
	  KeyCnt1++;                 //-- inc time held down
	  if(KeyCnt1 > 250)          //-- if > 250 counts then go to next position
	  {
	   if((Pos++)>MAXPOS) Pos=0; //-- inc position + check for roll over
	   KeyCnt1=1;
	  }
	  delay(10);                 //-- short delay
	 }
	 else
	 {
		  KeyCnt1=0;             //-- if key not held any more then reset counter
	 }
	}
	//--- Check the Sequence Key --
	if(KeyCnt2==0)
	{
	 if(Select==0)                  //-- if key previously released + now held
	 {
	  KeyCnt2++;                    //-- inc holding time
	  if((Sequ++)>MAXSEQ) Sequ=0;   //-- check for roll over
	  Pos=0;               //-- move to the first position in new sequence  
  }
	}
	else
	{
	 if(Select==0)        //-- if still held down....
	 {
	  KeyCnt2++;          //-- inc count
	  if(KeyCnt2 > 250)   //-- if more than 250 counts then...
	  {
	   if((Sequ++)>MAXSEQ) Sequ=0;  //-- go to next sequence + check 4 roll
	   Pos=0;             //-- move to first position in new sequence
	   KeyCnt2=1;
	  }
	  delay(10);         //-- short delay
	 }
	 else
	 {
	  KeyCnt2=0;        //-- if key not held any more then reset counter
	 }
	}
}
//************* END OF CheckKeys
//*****************************************************
//Delay -  creates a short delay
//*****************************************************
void delay(unsigned char ms)
{
	unsigned char loop,waste;
	unsigned int dly;
 for(loop=0;loop < ms;loop++)
 {
	  for(dly=0;dly<1000;dly++)
	  {
		  waste=(unsigned char) dly + loop;
	  }
 }
}
//********** END OF delay
//*****************************************************
//getch - gets a character from RS-232
//*****************************************************
unsigned char getch(void)
{
	unsigned char InData=0,Count;
	if (Flags.Init==0) Init232();
	Flags.NewDat=0;
	while(Flags.NewDat==0)  //-- keep going until new data found
	{
		while(Rxd);      //-- Wait for start bit (hi to lo)
		TMR0=(255-(BITTIME/2));   //-- Start timer
		while(TMR0!=0);   //-- wait for timer to go to zero
		if(Rxd==0)
		{
			 //-- Valid start bit
	   TMR0=(255-(BITTIME));   //-- Start timer For next bit
 		 for(Count=0;Count++;Count<8)
			 {
			   while(TMR0 != 0);       //-- wait for timer to overflow
			   TMR0=(255-(BITTIME));   //-- Start timer again
 		   InData >> 1;            //-- Rotate right 1 bit
			   InData+=(Rxd*128);      //-- Store new Bit in top of data
			 }
			 while(TMR0 !=0);
			 if(Rxd)
			 {
	     Flags.RxErr=0;
	     Flags.NewDat=1;
			 }
			 else
			 {
				  Flags.RxErr=1;
			 }
		}
		else
		{
			 Flags.RxErr=1;
		}
	}
	return(InData);
}
//************* END OF getch
//*****************************************************
//Init232 - Initialises RS-232 Port
//*****************************************************
void Init232(void)
{
  //-- Setup the timer module
  //T0CS=0            xx0x xxxx
  //PSA=0             xxxx 0xxx
  //Prescaler = 8     xxxx x010
  OPTION= 0xD2;  //-- 1101 0010  
  Flags.Init=1;
}
//************* END OF Init232

