#include "LCD.H"
/*
 ** ===================================================================
 **     Method      :  E_PutVal (component BitIO)
 **
 **     Description :
 **         This method writes the new output value.
 **     Parameters  :
 **         NAME       - DESCRIPTION
 **         Val             - Output value. Possible values:
 **                           FALSE - logical "0" (Low level)
 **                           TRUE - logical "1" (High level)
 **     Returns     : Nothing
 ** ===================================================================
 */
void E_PutVal(bool Val) {
	if (Val) {
		setReg8(SETAN, 0x20); /* SETAN5=0x01 */
	} else { /* !Val */
		setReg8(CLRAN, 0xDF); /* CLRAN5=0x00 */
	} /* !Val */
}

/*
 ** ===================================================================
 **     Method      :  RS_PutVal (component BitIO)
 **
 **     Description :
 **         This method writes the new output value.
 **     Parameters  :
 **         NAME       - DESCRIPTION
 **         Val             - Output value. Possible values:
 **                           FALSE - logical "0" (Low level)
 **                           TRUE - logical "1" (High level)
 **     Returns     : Nothing
 ** ===================================================================
 */
void RS_PutVal(bool Val) {
	if (Val) {
		setReg8(SETAN, 0x80); /* SETAN7=0x01 */
	} else { /* !Val */
		setReg8(CLRAN, 0x7F); /* CLRAN7=0x00 */
	} /* !Val */
}
/*
 ** ===================================================================
 **     Method      :  RW_PutVal (component BitIO)
 **
 **     Description :
 **         This method writes the new output value.
 **     Parameters  :
 **         NAME       - DESCRIPTION
 **         Val             - Output value. Possible values:
 **                           FALSE - logical "0" (Low level)
 **                           TRUE - logical "1" (High level)
 **     Returns     : Nothing
 ** ===================================================================
 */
void RW_PutVal(bool Val) {
	if (Val) {
		setReg8(SETAN, 0x40); /* SETAN6=0x01 */
	} else { /* !Val */
		setReg8(CLRAN, 0xBF); /* CLRAN6=0x00 */
	} /* !Val */
}

/*
 ** ===================================================================
 **     Method      :  LCD_DATA_GetMsk (component BitsIO)
 **
 **     Description :
 **         The method returns a bit mask which corresponds to the
 **         required bit position.
 **         This method is internal. It is used by Processor Expert only.
 ** ===================================================================
 */
static const byte LCD_DATA_Table[4] = { /* Table of mask constants */
0x01, 0x02, 0x04, 0x08 };

static byte LCD_DATA_GetMsk(byte PinIndex) {
	return (byte) (PinIndex < 4 ? LCD_DATA_Table[PinIndex] : 0); /* Check range and return appropriate bit mask */
}

/*
 ** ===================================================================
 **     Method      :  LCD_DATA_GetVal (component BitsIO)
 **
 **     Description :
 **         This method returns an input value.
 **           a) direction = Input  : reads the input value from the
 **                                   pins and returns it
 **           b) direction = Output : returns the last written value
 **     Parameters  : None
 **     Returns     :
 **         ---        - Input value (0 to 15)
 ** ===================================================================
 */
byte LCD_DATA_GetVal(void) {
	if ((getReg8(DDRAN) & 0x01)) {
		return (byte) (getReg8(PORTAN) & 0x0F); /* Return port output data */
	} else { /* !(getReg8(DDRAN) & 0x01) */
		return (byte) (getReg8(SETAN) & 0x0F); /* Return port input data */
	} /* !(getReg8(DDRAN) & 0x01) */
}

/*
 ** ===================================================================
 **     Method      :  LCD_DATA_PutVal (component BitsIO)
 **
 **     Description :
 **         This method writes the new output value.
 **         Note: If direction is set to input the method code may not
 **               work properly.
 **     Parameters  :
 **         NAME       - DESCRIPTION
 **         Val        - Output value (0 to 15)
 **     Returns     : Nothing
 ** ===================================================================
 */
void LCD_DATA_PutVal(byte Val) {
	Val &= 0x0F; /* Mask output value */
	setReg8(PORTAN, (getReg8(PORTAN) & (~0x0F)) | Val); /* Put masked value on port */
}

/*
 ** ===================================================================
 **     Method      :  LCD_DATA_GetBit (component BitsIO)
 **
 **     Description :
 **         This method returns the specified bit of the input value.
 **           a) direction = Input  : reads the input value from pins
 **                                   and returns the specified bit
 **           b) direction = Output : returns the specified bit
 **                                   of the last written value
 **     Parameters  :
 **         NAME       - DESCRIPTION
 **         Bit        - Number of the bit to read (0 to 3)
 **     Returns     :
 **         ---        - Value of the specified bit (FALSE or TRUE)
 **                      FALSE = "0" or "Low", TRUE = "1" or "High"
 ** ===================================================================
 */
bool LCD_DATA_GetBit(byte Bit) {
	byte const Mask = LCD_DATA_GetMsk(Bit); /* Temporary variable - bit mask to test */
	if ((getReg8(DDRAN) & 0x01)) {
		return (bool) ((getReg8(PORTAN) & Mask) == Mask); /* Test if specified bit of port register is set */
	} else { /* !(getReg8(DDRAN) & 0x01) */
		return (bool) ((getReg8(SETAN) & Mask) == Mask); /* Test if specified bit of port register is set */
	} /* !(getReg8(DDRAN) & 0x01) */
}

/*
 ** ===================================================================
 **     Method      :  LCD_DATA_PutBit (component BitsIO)
 **
 **     Description :
 **         This method writes the new value to the specified bit
 **         of the output value.
 **         Note: If direction is set to input the method code may not
 **               work properly.
 **     Parameters  :
 **         NAME       - DESCRIPTION
 **         Bit        - Number of the bit (0 to 3)
 **         Val        - New value of the bit (FALSE or TRUE)
 **                      FALSE = "0" or "Low", TRUE = "1" or "High"
 **     Returns     : Nothing
 ** ===================================================================
 */
void LCD_DATA_PutBit(byte Bit, bool Val) {
	byte const Mask = LCD_DATA_GetMsk(Bit); /* Temporary variable - put bit mask */
	if (Val) {
		setReg8(SETAN, Mask); /* [bit (Bit)]=0x01 */
	} else { /* !Val */
		setReg8(CLRAN, 0xFF ^ Mask); /* [bit (Bit)]=0x00 */
	} /* !Val */
}

/*
 ** ===================================================================
 **     Method      :  LCD_DATA_ClrBit (component BitsIO)
 **
 **     Description :
 **         This method clears (sets to zero) the specified bit
 **         of the output value.
 **         [ It is the same as "PutBit(Bit,FALSE);" ]
 **         Note: If direction is set to input the method code may not
 **               work properly.
 **     Parameters  :
 **         NAME       - DESCRIPTION
 **         Bit        - Number of the bit to clear (0 to 3)
 **     Returns     : Nothing
 ** ===================================================================
 */
void LCD_DATA_ClrBit(byte Bit) {
	byte const Mask = LCD_DATA_GetMsk(Bit); /* Temporary variable - set bit mask */
	setReg8(CLRAN, 0xFF ^ Mask); /* [bit (Bit)]=0x00 */
}

/*
 ** ===================================================================
 **     Method      :  LCD_DATA_SetBit (component BitsIO)
 **
 **     Description :
 **         This method sets (sets to one) the specified bit of the
 **         output value.
 **         [ It is the same as "PutBit(Bit,TRUE);" ]
 **         Note: If direction is set to input the method code may not
 **               work properly.
 **     Parameters  :
 **         NAME       - DESCRIPTION
 **         Bit        - Number of the bit to set (0 to 3)
 **     Returns     : Nothing
 ** ===================================================================
 */
void LCD_DATA_SetBit(byte Bit) {
	byte const Mask = LCD_DATA_GetMsk(Bit); /* Temporary variable - set bit mask */
	setReg8(SETAN, Mask); /* [bit (Bit)]=0x01 */
}

/*
 ** ===================================================================
 **     Method      :  LCD_DATA_NegBit (component BitsIO)
 **
 **     Description :
 **         This method negates (inverts) the specified bit of the
 **         output value.
 **         Note: If direction is set to input the method code may
 **               not work properly.
 **     Parameters  :
 **         NAME       - DESCRIPTION
 **         Bit        - Number of the bit to invert (0 to 31)
 **     Returns     : Nothing
 ** ===================================================================
 */
void LCD_DATA_NegBit(byte Bit) {
	byte const Mask = LCD_DATA_GetMsk(Bit); /* Temporary variable - set bit mask */
	invertReg8Bits(PORTAN, Mask); /* [bit (Bit)]=invert */
}

/*
 ** ===================================================================
 **     Method      :  LCD_DATA_GetDir (component BitsIO)
 **
 **     Description :
 **         This method returns direction of the component.
 **     Parameters  : None
 **     Returns     :
 **         ---        - Direction of the component (FALSE or TRUE)
 **                      FALSE = Input, TRUE = Output
 ** ===================================================================
 */
/*
 bool LCD_DATA_GetDir(void)

 **  This method is implemented as a macro. See LCD_DATA.h file.  **
 */

/*
 ** ===================================================================
 **     Method      :  LCD_DATA_SetDir (component BitsIO)
 **
 **     Description :
 **         This method sets direction of the component.
 **     Parameters  :
 **         NAME       - DESCRIPTION
 **         Dir        - Direction to set (FALSE or TRUE)
 **                      FALSE = Input, TRUE = Output
 **     Returns     : Nothing
 ** ===================================================================
 */
void LCD_DATA_SetDir(bool Dir) {
	if (Dir) {
		/* DDRAN: DDRAN3=1,DDRAN2=1,DDRAN1=1,DDRAN0=1 */
		setReg8Bits(DDRAN, 0x0F);
	} else { /* !Dir */
		/* DDRAN: DDRAN3=0,DDRAN2=0,DDRAN1=0,DDRAN0=0 */
		clrReg8Bits(DDRAN, 0x0F);
	} /* !Dir */
}
/*
 ** ===================================================================
 **     Method      :  Cpu_Delay100US (component MCF52233_80_LQFP)
 **
 **     Description :
 **         This method realizes software delay. The length of delay is
 **         at least 100 microsecond multiply input parameter [us100].
 **         As the delay implementation is not based on real clock, the
 **         delay time may be increased by interrupt service routines
 **         processed during the delay. The method is independent on
 **         selected speed mode.
 **     Parameters  :
 **         NAME            - DESCRIPTION
 **         us100           - Number of 100 us delay repetitions.
 **     Returns     : Nothing
 ** ===================================================================
 */
void Cpu_Delay100US(word us100 ) {
	/* irremovable one time overhead (ignored): 11 cycles */
	/* move: 1 cycle overhead (load parameter into register) */
	/* jsr:  3 cycles overhead (jump to subroutine) */
	/* andi: 1 cycle overhead (clear upper word of d0) */
	/* tpf: 1 cycle overhead (alignment) */
	/* rts:  5 cycles overhead (return from subroutine) */

	/* aproximate irremovable overhead for each 100us cycle (counted) : 3 cycles */
	/* subq.l 1 cycles overhead  */
	/* bne.b  2 cycles overhead  */

	/* Disable MISRA rule 55 checking - Non-case label used */
	/*lint -esym( 961, 55)   */
	//register word *p1 asm ("d0") = us100;

	asm volatile(
			"	move.l #0x100,%d0	\n\t"
			"	andi.l #0xFFFF,%d0  \n\t"
			"	tpf 				\n\t"
			"loop: 					\n\t"
			"	move.l #0x0749,%d1	\n\t"
			"label0:	 			\n\t"
			"	subq.l #1,%d1 		\n\t"
			"	bne.b label0		\n\t"
			"	tpf					\n\t"
			"	subq.l #1,%d0		\n\t"
			"	bne.w loop			\n\t"
			"	rts					\n\t"
);

}
