/************************************************************
DLP_2_FLASH.C 

Z-World, 2001

	This program is provided as a Sample ONLY. It is intended for
	use on Rabbit based boards with 2 flash chips in conjunction
	with the sample program DLM_SERIAL_2_FLASH.C. 
	
   It is just a small test program to use as a downloaded program,
   and is set up to send a character continuously over serial port B
   at 57600 baud.

   To use serial port C instead of B, uncomment the 
   USE_SERIAL_PORT_C    macro definition

   and comment out the 
   USE_SERIAL_PORT_B    macro definition

	Directions:

	1) In the Compile | Options dialog box in Dynamic C 7.05 or later,
	   click on the "Defines" button, add COMPILE_SECONDARY_PROG
	   to the list of macros, and make sure COMPILE_PRIMARY_PROG is
	   NOT on the list. Compile this program to a BIN file, (include
	   the BIOS). A HEX file will be automatically generated.

   2) Follow the instructions in DLM_SERIAL_2_FLASH.C to download
      the file DLP_2_FLASH.HEX.

	3)	Compile the program DLM_SERIAL_2_FLASH.C to the Rabbit target.
	   See the instructions in DLM_SERIAL_2_FLASH.C.

Note:  the macro  USE_2NDFLASH_CODE is not related to putting
       a secondary program in the second flash, and should be
       commented out when compiling this program.
****************************************************************/

#define MY_CHARACTER 'Z'

//*** uncomment one only! ***
#define USE_SERIAL_PORT_B
//#define USE_SERIAL_PORT_C

#ifdef  COMPILE_PRIMARY_PROG
#error "Cannot compile as primary program."
#error "Remove COMPILE_PRIMARY_PROG macro in Compiler | #defines options"
#error "Must Recompile BIOS also. Hit Ctrl-Y then recompile"
#endif

#ifndef  COMPILE_SECONDARY_PROG
#error "Must compile as secondary program."
#error "Put COMPILE_SECONDARY_PROG macro in Compiler | #defines options"
#error "Must Recompile BIOS also. Hit Ctrl-Y then recompile"
#endif

#ifdef USE_SERIAL_PORT_B
#define BINBUFSIZE  15
#define BOUTBUFSIZE 15
#else
#ifdef USE_SERIAL_PORT_C
#define CINBUFSIZE  15
#define COUTBUFSIZE 15
#endif
#endif

#define _232BAUD 57600ul

#define RESTARTSIGNAL "\xaa\xbb\xcc\xbb\xaa" 
#define RESTARTSIGNAL_TIMEOUT 10000 

char  Chip_SW_Func [30];
void  CopyChipSWtoRAM();
void  SwitchChip(int CSOEWE);
void ProcessRestartCommand(char ch);

void RestartDLM();
int vwd;

root main()
{
	int cIn;

#ifdef USE_SERIAL_PORT_B
	serBopen(_232BAUD);
#else
#ifdef USE_SERIAL_PORT_C
	serCopen(_232BAUD);
#else
#error "Must #define a port"
#endif
#endif

	vwd  = VdGetFreeWd(10); // get a virtual watchdog
			
	while (1)
	{
      // Listen for restart command
#ifdef USE_SERIAL_PORT_B
		cIn = serBgetc();
#else
#ifdef USE_SERIAL_PORT_C
		cIn = serCgetc();
#endif
#endif

		VdHitWd(vwd);    // hit vwd

		if((cIn&0xff80)==0x0080)
		{
		    ProcessRestartCommand(cIn);
		}

		// Send a char
		costate
		{
			waitfor(DelayMs(10));
#ifdef USE_SERIAL_PORT_B
			waitfor(serBwrFree());
			serBputc(MY_CHARACTER);
#else
#ifdef USE_SERIAL_PORT_C
			waitfor(serCwrFree());
			serCputc(MY_CHARACTER);
#endif
#endif
		}
	}
}

nodebug
void ProcessRestartCommand(char ch)
{
	static unsigned long timelimit;
	static char restart[sizeof(RESTARTSIGNAL)]; 
	static int indx;
#GLOBAL_INIT{ indx = 0;memset(restart,0,sizeof(RESTARTSIGNAL)-1);}

	if(!indx)
	{
		timelimit = SEC_TIMER+RESTARTSIGNAL_TIMEOUT;
	}
	else
	{
		if((long)(SEC_TIMER - timelimit)>=0)
		{
			indx = 0;
			memset(restart,0,sizeof(RESTARTSIGNAL)-1);		
			return;
		} 
	}
	restart[indx] = ch;
	indx++;
	if(indx==sizeof(RESTARTSIGNAL))
	{
		memset(restart,0,sizeof(RESTARTSIGNAL)-1);		
		indx = 0;
	}
   else if(!memcmp(restart,RESTARTSIGNAL,sizeof(RESTARTSIGNAL)-1))
	{
		RestartDLM();
	}
}

nodebug
void RestartDLM()
{
#ifdef USE_SERIAL_PORT_B
	serBclose();
#else
#ifdef USE_SERIAL_PORT_C
	serCclose();
#endif
#endif

	// Put flash switching function in RAM 
	CopyChipSWtoRAM();

	// ...and call it
	SwitchChip(0|0);  // CS0/OE0/WE0
}

#asm nodebug
_SwitchFlashChip::
	ipset 3							  // turn off interrupts
	ld   a,0x51
	ioi  ld (WDTTR),a
	ld   a,0x54
	ioi  ld (WDTTR),a

	ld   a,(MB0CRShadow)         // get shadow reg
   and  0xf0                    // mask out CS/WE/OE bits
   or   l                       // set to new CS,WE,OE 
   ioi  ld (MB0CR),a            // load MMU reg
	ld   hl,0
	jp   (hl)
_EndSwitchFlash::
#endasm

nodebug
void SwitchChip(int CSOEWE)
{
#asm
	call Chip_SW_Func
#endasm
}

nodebug
void  CopyChipSWtoRAM()
{
	// put flash switching function in RAM
	memcpy(	Chip_SW_Func	,
			 	_SwitchFlashChip,
			 	((int)((unsigned)_EndSwitchFlash - (unsigned)_SwitchFlashChip)+1)
   );
}