//****************************************************************************
//
// LCD_ALPS.C - Routines to enable and draw on the Alps LRHDD101XA LCD panel
//              (at 320x240 resolution)
//
// Copyright (c) 1998-1999 Cirrus Logic, Inc.
//
//****************************************************************************
#include "ep7209.h"
#include "lib7209.h"

//****************************************************************************
//
// LCDEnable initializes the control logic for the LCD panel.
//
//****************************************************************************
void
LCDEnable(void)
{
    unsigned long * volatile pulPtr = (unsigned long *)HwBaseAddress;
    unsigned long ulLcdConfig, ulLineLength, ulVideoBufferSize;

    //
    // Determine the value to be programmed into the LCD controller in the
    // EP7209 to properly drive the ALPS LCD panel at 320x240, 4 bits per
    // pixel, at 60Hz.
    //
    ulVideoBufferSize = ((320 * 240* 4*3) / 128) - 1;
    ulLineLength = ((320*3) / 16) - 1;
    ulLcdConfig = HwLcdControlGreyEnable |
                  HwLcdControlGrey4Or2 |
                  (0x20 << HwLcdControlAcPrescaleShift) |
                  (1 << HwLcdControlPixelPrescaleShift) |
                  (ulLineLength << HwLcdControlLineLengthShift) |
                  (ulVideoBufferSize << HwLcdControlBufferSizeShift);

    //
    // Configure the palette to be a one-to-one mapping of the pixel values to
    // the available LCD pixel intensities.
    //
    pulPtr[HwPaletteLSW >> 2] = 0x76543210;
    pulPtr[HwPaletteMSW >> 2] = 0xFEDCBA98;

    //
    // Program the LCD controller with the previously determined configuration.
    //
    pulPtr[HwLcdControl >> 2] = ulLcdConfig;

    //
    // Set the LCD frame buffer start address.
    //
    pulPtr[HwLcdFrameBuffer >> 2] = HwLcdBaseAddress >> 28;
}

//****************************************************************************
//
// LCDOn turns on the LCD panel.
//
//****************************************************************************
void
LCDOn(void) 
{
    unsigned long * volatile pulPtr = (unsigned long *)HwBaseAddress;
    int iDelay;

    //
    // Power up the LCD controller.
    //
    pulPtr[HwControl >> 2] |= HwControlLcdEnable;

    //
    // Power up the LCD panel.
    //
    ((unsigned char *)pulPtr)[HwPortD] |= HwPortDLCDPower;

    //
    // Delay for a little while.
    //
    for(iDelay = 0; iDelay < 65536 * 4; iDelay++)
    {
    }

    //
    // Power up the LCD DC-DC converter.
    //
    ((unsigned char *)pulPtr)[HwPortD] |= HwPortDLCDDcDcPower;
}

//****************************************************************************
//
// LCDOff turns off the LCD panel.
//
//****************************************************************************
void
LCDOff(void)
{
    unsigned long * volatile pulPtr = (unsigned long *)HwBaseAddress;
    int iDelay;

    //
    // Power off the LCD DC-DC converter.
    //
    ((unsigned char *)pulPtr)[HwPortD] &= ~HwPortDLCDDcDcPower;

    //
    // Delay for a little while.
    //
    for(iDelay = 0; iDelay < 65536 * 4; iDelay++)
    {
    }

    //
    // Power off the LCD panel.
    //
    ((unsigned char *)pulPtr)[HwPortD] &= ~HwPortDLCDPower;

    //
    // Power off the LCD controller.
    //
    pulPtr[HwControl >> 2] &= ~HwControlLcdEnable;
}

//****************************************************************************
//
// LCDCls clears the LCD frame buffer.
//
//****************************************************************************
void
LCDCls(void)
{
    char *pcPtr = (char *)HwLcdBaseAddress;
    int iIdx;

    //
    // Fill the frame buffer with zeros.
    //
    for(iIdx = 0; iIdx < ((320 *3 *240) / 2); iIdx++)
    {
        *pcPtr++ = 0x0;
    }
}

//****************************************************************************
//
// LCDSetPixel changes the color of the specified pixel to the specified
// color.
//
//****************************************************************************
void
LCDSetPixel(long lX, long lY, USIGN16 cColor)
{
    long x;
    unsigned int RColor,BColor,GColor;	
    unsigned char * volatile pucPtr1;
    unsigned char * volatile pucPtr2;

    RColor = BColor = GColor = 0x00;
    if (cColor & 1)
 	BColor = 0xf;
    if (cColor & 2)
 	GColor = 0xf;
    if (cColor & 4)
 	RColor = 0xf;
    if (cColor & 8)
{
 	BColor = BColor & 0x2;
 	RColor = RColor & 0x2;
 	GColor = GColor & 0x2;
}
    if((lX < 0) || (lX >= 320) || (lY < 0) || (lY >= 240))
    {
        return;
    }

    pucPtr1 = (unsigned char *)(HwLcdBaseAddress + (lY *480)+((lX*3)>>1));
    x= ((lX*3)/2);

  if(lX & 4)
  {
    if  (lX & 2)
    {
       if(x & 1)
       {
	*(pucPtr1+2) = (*(pucPtr1+2) & 0xF0) | RColor;
	*(pucPtr1+2) = (*(pucPtr1+2) & 0x0F) |(GColor << 4);
	*(pucPtr1-1) = (*(pucPtr1-1) & 0xF0) | BColor;
       }
       else
       {
	*(pucPtr1-2) = (*(pucPtr1-2) & 0x0F) | (RColor << 4);
	*(pucPtr1-1) = (*(pucPtr1-1) & 0xF0) | GColor;
	*(pucPtr1-1) = (*(pucPtr1-1) & 0x0F) | (BColor << 4);
       }
    }
    else
    {
       if(x & 1)
       {
	*(pucPtr1-2) = (*(pucPtr1-2) & 0x0F) | (RColor << 4);
	*(pucPtr1+3) = (*(pucPtr1+3) & 0xF0) | GColor;
	*(pucPtr1+3) = (*(pucPtr1+3) & 0x0F) | (BColor << 4);
       }
       else
       {
	*(pucPtr1-2) = (*(pucPtr1-2) & 0xF0) | RColor;
	*(pucPtr1-2) = (*(pucPtr1-2) & 0x0F) | (GColor << 4);
	*(pucPtr1-1) = (*(pucPtr1-1) & 0xF0) | BColor;
       }
    }
  }
  else
  {
    if  (lX & 2)
    {
       if(x & 1)
       {
	*(pucPtr1-2) = (*(pucPtr1-2) & 0xF0) | RColor;
	*(pucPtr1-2) = (*(pucPtr1-2) & 0x0F) | (GColor << 4);
	*(pucPtr1+3) = (*(pucPtr1+3) & 0xF0) | BColor;
       }
       else
       {
	*(pucPtr1+2) = (*(pucPtr1+2) & 0x0F) | (RColor << 4);
	*(pucPtr1+3) = (*(pucPtr1+3) & 0xF0) | GColor;
	*(pucPtr1+3) = (*(pucPtr1+3) & 0x0F) | (BColor << 4);
       }
    }
    else
    {
       if(x & 1)
       {
	*(pucPtr1+2) = (*(pucPtr1+2) & 0x0F) | (RColor << 4);
	*(pucPtr1-1) = (*(pucPtr1-1) & 0xF0) | GColor;
	*(pucPtr1-1) = (*(pucPtr1-1) & 0x0F) | (BColor << 4);
       }
       else
       {
	*(pucPtr1+2) = (*(pucPtr1+2) & 0xF0) | RColor;
	*(pucPtr1+2) = (*(pucPtr1+2) & 0x0F) | (GColor << 4);
	*(pucPtr1+3) = (*(pucPtr1+3) & 0xF0) | BColor;
       }
    }

  }



}

//****************************************************************************
//
// LCDSetPixel changes the color of the specified pixel to the specified
// color.
//
//****************************************************************************
void
SetPixel(long lX, long lY, char RColor, char GColor, char BColor)
{
    long x;
    unsigned char * volatile pucPtr1;

    if((lX < 0) || (lX >= 320) || (lY < 0) || (lY >= 240))
    {
        return;
    }

    pucPtr1 = (unsigned char *)(HwLcdBaseAddress + (lY *480)+((lX*3)>>1));
    x= ((lX*3)/2);

  if(lX & 4)
  {
    if  (lX & 2)
    {
       if(x & 1)
       {
	*(pucPtr1+2) = (*(pucPtr1+2) & 0xF0) | RColor;
	*(pucPtr1+2) = (*(pucPtr1+2) & 0x0F) |(GColor << 4);
	*(pucPtr1-1) = (*(pucPtr1-1) & 0xF0) | BColor;
       }
       else
       {
	*(pucPtr1-2) = (*(pucPtr1-2) & 0x0F) | (RColor << 4);
	*(pucPtr1-1) = (*(pucPtr1-1) & 0xF0) | GColor;
	*(pucPtr1-1) = (*(pucPtr1-1) & 0x0F) | (BColor << 4);
       }
    }
    else
    {
       if(x & 1)
       {
	*(pucPtr1-2) = (*(pucPtr1-2) & 0x0F) | (RColor << 4);
	*(pucPtr1+3) = (*(pucPtr1+3) & 0xF0) | GColor;
	*(pucPtr1+3) = (*(pucPtr1+3) & 0x0F) | (BColor << 4);
       }
       else
       {
	*(pucPtr1-2) = (*(pucPtr1-2) & 0xF0) | RColor;
	*(pucPtr1-2) = (*(pucPtr1-2) & 0x0F) | (GColor << 4);
	*(pucPtr1-1) = (*(pucPtr1-1) & 0xF0) | BColor;
       }
    }
  }
  else
  {
    if  (lX & 2)
    {
       if(x & 1)
       {
	*(pucPtr1-2) = (*(pucPtr1-2) & 0xF0) | RColor;
	*(pucPtr1-2) = (*(pucPtr1-2) & 0x0F) | (GColor << 4);
	*(pucPtr1+3) = (*(pucPtr1+3) & 0xF0) | BColor;
       }
       else
       {
	*(pucPtr1+2) = (*(pucPtr1+2) & 0x0F) | (RColor << 4);
	*(pucPtr1+3) = (*(pucPtr1+3) & 0xF0) | GColor;
	*(pucPtr1+3) = (*(pucPtr1+3) & 0x0F) | (BColor << 4);
       }
    }
    else
    {
       if(x & 1)
       {
	*(pucPtr1+2) = (*(pucPtr1+2) & 0x0F) | (RColor << 4);
	*(pucPtr1-1) = (*(pucPtr1-1) & 0xF0) | GColor;
	*(pucPtr1-1) = (*(pucPtr1-1) & 0x0F) | (BColor << 4);
       }
       else
       {
	*(pucPtr1+2) = (*(pucPtr1+2) & 0xF0) | RColor;
	*(pucPtr1+2) = (*(pucPtr1+2) & 0x0F) | (GColor << 4);
	*(pucPtr1+3) = (*(pucPtr1+3) & 0xF0) | BColor;
       }
    }

  }



}


//****************************************************************************
//
// LCDGetPixel returns the color of the specified pixel.
//
//****************************************************************************
char
LCDGetPixel(long lX, long lY)
{
    unsigned char * volatile pucPtr;

    //
    // Make sure the specified pixel is valid.
    //
    if((lX < 0) || (lX >= 320) || (lY < 0) || (lY >= 240))
    {
        return(0);
    }

    //
    // Compute the address of the pixel.
    //
    pucPtr = (unsigned char *)(HwLcdBaseAddress + (lY*3 * 320)/2 + ((lX*3) >> 1));

    //
    // Return the appropriate pixel based on the value of lX.
    //
    if(lX & 1)
    {
        return((*pucPtr & 0xF0) >> 4);
    }
    else
    {
        return(*pucPtr & 0x0F);
    }
}

//****************************************************************************
//
// LCDBacklightOn turns on the backlighting on the LCD panel.
//
//****************************************************************************
void
LCDBacklightOn(void)
{
    unsigned char * volatile pucPtr = (unsigned char *)HwBaseAddress;

    //
    // The backlighting is controlled on the evaluation board by a bit in the
    // GPIO port D.
    //
    pucPtr[HwPortD] |= HwPortDLCDBacklightPower;
}

//****************************************************************************
//
// LCDBacklightOff turns off the backlighting on the LCD panel.
//
//****************************************************************************
void
LCDBacklightOff(void)
{
    unsigned char * volatile pucPtr = (unsigned char *)HwBaseAddress;

    //
    // The backlighting is controlled on the evaluation board by a bit in the
    // GPIO port D.
    //
    pucPtr[HwPortD] &= ~HwPortDLCDBacklightPower;
}
