#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
** ===================================================================
*/
__declspec(register_abi) void Cpu_Delay100US(word us100:__D0)
{
  /* 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)   */

  asm {
    naked
    andi.l #0xFFFF,d0                  /* parameter is word - clear the rest of d0 register */
    tpf                                /* alignment */
loop:
    /* 100 us delay block begin */
    /*
     * Delay
     *   - requested                  : 100 us @ 56MHz,
     *   - possible                   : 5600 c, 100000 ns
     *   - without removable overhead : 5597 c, 99946.43 ns
     */
    move.l #0x0749,d1                  /* (1 c: 17.86 ns) number of iterations */
label0:
    subq.l #1,d1                       /* (1 c: 17.86 ns) decrement d1 */
    bne.b label0                       /* (2 c: 35.71 ns) repeat 1865x */
    tpf                                /* (1 c: 17.86 ns) wait for 1 c */
    /* 100 us delay block end */
    subq.l #1,d0                       /* parameter is passed via d0 register */
    bne.w loop                         /* next loop */
    rts                                /* return from subroutine */
  }
  /* Restore MISRA rule 55 checking - Non-case label used */
  /*lint +esym( 961, 55)   */
}
