/***************************************************************

   MicroEtherCore\FlashLEDS.c
   Zworld, 2001

   Rabbit 2200 Micro Core Module Demo board example program

   This program flashes the DS2 and DS3 LED's on the Rabbit 2200
   Micro Ethernet Core Module Prototyping board (PE1 and PE7 ports
   on the Rabbit Core Module).  The MASTER core controls the LEDs.

   It also demonstrates coding with assembly instructions,
   indexed cofunctions, and costatements.

****************************************************************/

/***************************************************************
  index predefines for the leds and switches
****************************************************************/
#define DS2 0
#define DS3 1

/***************************************************************
  initialize_ports();
  set up the parallel ports so PORTA are outputs, and PORTE bits
  1,7 are I/O (ie, not control signals) others unchanged.  It
  updates SPCRShadow, PEFRShadow, PEDDRShadow and PECRShadow .
****************************************************************/
void initialize_ports()
{
/*
 *  Use leading zero to force constant value, not memory address.
 *  The 1 shifted over 1 place and 7 places refer to bits 1 and 7
 *  in Port E.  This creates a mask of bits to affect.  The second
 *  line creates a mask of bits NOT to affect; good for turning off
 *  PE1 and PE7.
 */
#define  PE_IO_SETTINGS		0+(1<<1)|(1<<7)			;; Bits 7 and 1 turned on.
#define  PE_NOT_IO_SETTINGS   0+~PE_IO_SETTINGS    ;; 0x7D	; ~82

#asm

	ld		a,0x84				; port A all outputs
ioi ld	(SPCR),a
	ld		(SPCRShadow), a	; store value into shadow register

	ld		a, (PEFRShadow)	; get current settings
	and	a, PE_NOT_IO_SETTINGS	; port E bit 1,7 normal I/O
ioi ld	(PEFR),a
	ld		(PEFRShadow), a	; store shadow register

	ld		a,PE_IO_SETTINGS	; Bits 1,7 as output.
ioi ld	(PEDDR),a
	ld		(PEDDRShadow), a	; store shadow register

	xor	a  					; default transfer clocking
ioi ld	(PECR),a
	ld		(PECRShadow), a
#endasm
}

/***************************************************************
  ledon(int led)
  turn the specified led on.
****************************************************************/
void ledon(int led)
{
	/*  Map from index into bit map. ON requires logic 0, so invert.
	 *  The value will appear in reg-pair HL.
	 */
	(led == DS2) ? ~(1 << 1) : ~(1 << 7);

#asm
	ld		a,(PEDRShadow)
	and	l      					; reg L has bit value (computed above)
ioi ld	(PEDR),a
	ld		(PEDRShadow), a
#endasm
}

/***************************************************************
  ledoff(int led)
  turn the specified led off.
****************************************************************/
void ledoff(int led)
{
	/*  Map from index into bit map. OFF requires logic 1.
	 *  The value will appear in reg-pair HL.
	 */
	(led == DS2) ? (1 << 1) : (1 << 7);

#asm
	ld		a,(PEDRShadow)
	or		l      					; reg L has bit value (computed above)
ioi ld	(PEDR),a
	ld		(PEDRShadow), a
#endasm
}

/***************************************************************
  flashled[2](int,int,int)
  cofunction which flashes the "which" led on for ontime then
  off for offtime
****************************************************************/

cofunc flashled[2](int which, int ontime, int offtime)
{
	for(;;) {
		waitfor(DelayMs(ontime));
		ledoff(which);
		waitfor(DelayMs(offtime));
		ledon(which);
	}
}

main()
{
	initialize_ports();

	for(;;) {

		costate {
			wfd {
				flashled[0](DS2,500,1000);    // Flashes DS2  PA0
				flashled[1](DS3,1000,500);    // Flashes DS3  PA1
				}
		}
	}  /* for ever.. */
}
