/*********************************************************************
 *                 Flowcode LCD Display Component Code
 *
 * File: AVR_LCD.c
 *
 * (c) 2009 Matrix Multimedia Ltd.
 * http://www.matrixmultimedia.com
 *
 * Software License Agreement
 *
 * The software supplied herewith by Matrix Multimedia Ltd (the
 * “Company”) for its Flowcode graphical programming language is
 * intended and supplied to you, the Company’s customer, for use
 * solely and exclusively on the Company's products. The software
 * is owned by the Company, and is protected under applicable
 * copyright laws. All rights are reserved. Any use in violation
 * of the foregoing restrictions may subject the user to criminal
 * sanctions under applicable laws, as well as to civil liability
 * for the breach of the terms and conditions of this licence.
 *
 * THIS SOFTWARE IS PROVIDED IN AN “AS IS” CONDITION. NO WARRANTIES,
 * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
 * TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
 * IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
 * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
 *
 * Changelog:
 *
 *  date  | by | description
 * -------+----+-----------------------------------------------------
 * 300307 | ST | Created
 * 150807 | ST | Added a missing delay to <RawSend> function
 * 100608 | BR | Modified <Cursor> addressing on 4-line displays
 * 170209 | BR | Modified <Cursor> addressing on 16/20 char 4 line displays
 * 250209 | BR | Modified <Start> to allow for a more reliable startup
 * 120309 | BR | Added ClearLine and ScrollDisplay functions.
 * 180309 | BR | Changed delays to be WDT compatible
 * 130509 | BR | Added % definitions to DefinesCode section
 * 170809 | SK | Converted to AVR from PIC_LCD.c
 * 290610 | SK | %s_Delay defined using delay_10us(). delay_us() fails below 4MHz.
 *
 ********************************************************************/

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

 Return & parameter types:
   void
   char
   short
   char*

 Pin directions:
   0 = OUTPUT
   2 = INPUT
   3 = BIDIRECTIONAL

**********************************************************************

[Settings]
CLSID={02A7087C-4D0C-4AA4-9522-82A47E88BDC8}
IsAnalogue=0
MultipleAllowed=1
Description=Alphanumeric LCD Flowcode Component

**********************************************************************

[Port]
DesiredPort=1
PortMandatory=1
SamePortAsID=-1

[Pins]
Count=0
DesiredPin=0
BitMandatory=1

[PinPort]
# PORTA = 0
# PORTB = 1
# PORTC = 2
# PORTD = 3
# PORTE = 4

[PinDesiredBit]

[PinDirection]
# DIR_INPUT = 2
# DIR_OUTPUT = 0
# DIR_BIDIRECTIONAL = 3

[PinMustUsePort]
# boolean

[SamePortAsPinX]
# -1 = any pin
# otherwise, the pin number

[PinMustUsePin]
# boolean

[PinValue]
# boolean (0 = off, 1 = on)

**********************************************************************

[MacroNames]
Count=11
1=RawSend
2=Start
3=Clear
4=PrintASCII
5=Command
6=Cursor
7=PrintNumber
8=PrintString
9=ScrollDisplay
10=ClearLine
11=RAM_Write

[MacroReturns]
1=void
2=void
3=void
4=void
5=void
6=void
7=void
8=void
9=void
10=void
11=void

[MacroIsPrivate]
1=1
2=0
3=0
4=0
5=0
6=0
7=0
8=0
9=0
10=0
11=0

[MacroParameters_RawSend]
Count=2
1=in
2=mask

[MacroParamTypes_RawSend]
1=char
2=char

[MacroParameters_Start]
Count=0

[MacroParamTypes_Start]


[MacroParameters_Clear]
Count=0

[MacroParamTypes_Clear]


[MacroParameters_PrintASCII]
Count=1
1=Character

[MacroParamTypes_PrintASCII]
1=char


[MacroParameters_Command]
Count=1
1=in

[MacroParamTypes_Command]
1=char


[MacroParameters_Cursor]
Count=2
1=x
2=y

[MacroParamTypes_Cursor]
1=char
2=char


[MacroParameters_PrintNumber]
Count=1
1=Number

[MacroParamTypes_PrintNumber]
1=short


[MacroParameters_PrintString]
Count=1
1=String

[MacroParamTypes_PrintString]
1=char*


[MacroParameters_ScrollDisplay]
Count=2
1=Direction
2=Num_Positions

[MacroParamTypes_ScrollDisplay]
1=char
2=char


[MacroParameters_ClearLine]
Count=1
1=Line

[MacroParamTypes_ClearLine]
1=char

[MacroParameters_RAM_Write]
Count=9
1=nIdx
2=d0
3=d1
4=d2
5=d3
6=d4
7=d5
8=d6
9=d7

[MacroParamTypes_RAM_Write]
1=char
2=char
3=char
4=char
5=char
6=char
7=char
8=char
9=char

/********************************************************************
 * ADDITIONAL CODE
 ********************************************************************/

/*DefinesCode_Start*/

/**** Macro Substitutions ****
%a = D1 Port
%b = D1 Data Direction
%c = D2 Port
%d = D2 Data Direction
%e = D3 Port
%f = D3 Data Direction
%g = D4 Port
%h = D4 Data Direction
%i = RS Port
%j = RS Data Direction
%k = E Port
%l = E Data Direction
%m = Data 1_Pin
%n = Data 2 Pin
%o = Data 3 Pin
%p = Data 4 Pin
%q = RS Pin
%r = Enable Pin
%s = Unique Component Reference Number
%t = Row Count
%u = Column Count
******************************/

	//component connections
	#define %s_PORT0    %a
	#define %s_DDR0    %b
	#define %s_PORT1    %c
	#define %s_DDR1    %d
	#define %s_PORT2    %e
	#define %s_DDR2    %f
	#define %s_PORT3    %g
	#define %s_DDR3    %h
	#define %s_PORT4    %i
	#define %s_DDR4    %j
	#define %s_PORT5    %k
	#define %s_DDR5    %l
	#define %s_BIT0    	%m
	#define %s_BIT1    	%n
	#define %s_BIT2    	%o
	#define %s_BIT3    	%p
	#define %s_RS      	%q
	#define %s_E       	%r
	#define %s_ROWCNT	%t
	#define %s_COLCNT	%u

    #define %s_DELAY   delay_10us(10)

/*DefinesCode_End*/

/*InitialisationCode_Start*/
/*InitialisationCode_End*/

/*InterruptCode_Start*/
/*InterruptCode_End*/

/********************************************************************
 * FUNCTIONS
 ********************************************************************/

void RawSend(char in, char mask)
{
/*Macro_RawSend_Start*/
	unsigned char pt;

	clear_bit(%s_PORT0, %s_BIT0);
	clear_bit(%s_PORT1, %s_BIT1);
	clear_bit(%s_PORT2, %s_BIT2);
	clear_bit(%s_PORT3, %s_BIT3);
	clear_bit(%s_PORT4, %s_RS);
	clear_bit(%s_PORT5, %s_E);
	pt = ((in >> 4) & 0x0f);
	if (pt & 0x01)
	    set_bit(%s_PORT0, %s_BIT0);
	if (pt & 0x02)
	    set_bit(%s_PORT1, %s_BIT1);
	if (pt & 0x04)
	    set_bit(%s_PORT2, %s_BIT2);
	if (pt & 0x08)
	    set_bit(%s_PORT3, %s_BIT3);
	if (mask)
	    set_bit(%s_PORT4, %s_RS);
	%s_DELAY;
	set_bit (%s_PORT5, %s_E);
	%s_DELAY;
	clear_bit (%s_PORT5, %s_E);
	pt = (in & 0x0f);
	%s_DELAY;
	clear_bit(%s_PORT0, %s_BIT0);
	clear_bit(%s_PORT1, %s_BIT1);
	clear_bit(%s_PORT2, %s_BIT2);
	clear_bit(%s_PORT3, %s_BIT3);
	clear_bit(%s_PORT4, %s_RS);
	clear_bit(%s_PORT5, %s_E);
	if (pt & 0x01)
	    set_bit(%s_PORT0, %s_BIT0);
	if (pt & 0x02)
	    set_bit(%s_PORT1, %s_BIT1);
	if (pt & 0x04)
	    set_bit(%s_PORT2, %s_BIT2);
	if (pt & 0x08)
	    set_bit(%s_PORT3, %s_BIT3);
	if (mask)
	    set_bit(%s_PORT4, %s_RS);
	%s_DELAY;
	set_bit (%s_PORT5, %s_E);
	%s_DELAY;
	clear_bit (%s_PORT5, %s_E);
	%s_DELAY;
/*Macro_RawSend_End*/
}


void Start()
{
/*Macro_Start_Start*/

	set_bit(%s_DDR0, %s_BIT0);
	set_bit(%s_DDR1, %s_BIT1);
	set_bit(%s_DDR2, %s_BIT2);
	set_bit(%s_DDR3, %s_BIT3);
	set_bit(%s_DDR4, %s_RS);
	set_bit(%s_DDR5, %s_E);

	Wdt_Delay_Ms(12);

	RawSend(0x33, 0);
	Wdt_Delay_Ms(2);
	RawSend(0x33, 0);
	Wdt_Delay_Ms(2);
	RawSend(0x32, 0);
	Wdt_Delay_Ms(2);
	RawSend(0x2c, 0);
	Wdt_Delay_Ms(2);
	RawSend(0x06, 0);
	Wdt_Delay_Ms(2);
	RawSend(0x0c, 0);
	Wdt_Delay_Ms(2);

	//clear the display
	RawSend(0x01, 0);
	Wdt_Delay_Ms(2);
	RawSend(0x02, 0);
	Wdt_Delay_Ms(2);

/*Macro_Start_End*/
}



void Clear()
{
/*Macro_Clear_Start*/

	RawSend(0x01, 0);
	Wdt_Delay_Ms(2);
	RawSend(0x02, 0);
	Wdt_Delay_Ms(2);

/*Macro_Clear_End*/
}



void PrintASCII(char Character)
{
/*Macro_PrintASCII_Start*/

	RawSend(Character, 0x10);

/*Macro_PrintASCII_End*/
}



void Command(char in)
{
/*Macro_Command_Start*/

	RawSend(in, 0);
	Wdt_Delay_Ms(2);

/*Macro_Command_End*/
}



void Cursor(char x, char y)
{
/*Macro_Cursor_Start*/

  #if (%s_ROWCNT == 1)
    y=0x80;
  #endif

  #if (%s_ROWCNT == 2)
	if (y==0)
		y=0x80;
	else
		y=0xc0;
  #endif

  #if (%s_ROWCNT == 4)
	if (y==0)
		y=0x80;
	else if (y==1)
		y=0xc0;

	#if (%s_COLCNT == 16)
		else if (y==2)
			y=0x90;
		else
			y=0xd0;
	#endif

	#if (%s_COLCNT == 20)
		else if (y==2)
			y=0x94;
		else
			y=0xd4;
	#endif
  #endif

	RawSend(y+x, 0);
	Wdt_Delay_Ms(2);

/*Macro_Cursor_End*/
}


void PrintNumber(short Number)
{
/*Macro_PrintNumber_Start*/

	short tmp_int;
	char tmp_byte;
	if (Number < 0)
	{
		RawSend('-', 0x10);
		Number = 0 - Number;
	}

	tmp_int = Number;
	if (Number >= 10000)
	{
		tmp_byte = tmp_int / 10000;
		RawSend('0' + tmp_byte, 0x10);

		while (tmp_byte > 0)
		{
			tmp_int = tmp_int - 10000;
			tmp_byte--;
		}
	}
	if (Number >= 1000)
	{
		tmp_byte = tmp_int / 1000;
		RawSend('0' + tmp_byte, 0x10);

		while (tmp_byte > 0)
		{
			tmp_int = tmp_int - 1000;
			tmp_byte--;
		}
	}
	if (Number >= 100)
	{
		tmp_byte = tmp_int / 100;
		RawSend('0' + tmp_byte, 0x10);

		while (tmp_byte > 0)
		{
			tmp_int = tmp_int - 100;
			tmp_byte--;
		}
	}
	if (Number >= 10)
	{
		tmp_byte = tmp_int / 10;
		RawSend('0' + tmp_byte, 0x10);

		while (tmp_byte > 0)
		{
			tmp_int = tmp_int - 10;
			tmp_byte--;
		}
	}
	RawSend('0' + tmp_int, 0x10);

/*Macro_PrintNumber_End*/
}


void PrintString(char* String, char MSZ_String)
{
/*Macro_PrintString_Start*/

	char idx;
	for (idx=0; idx<MSZ_String; idx++)
	{
		if (String[idx]==0)
		{
			break;
		}
		RawSend(String[idx], 0x10);
	}

/*Macro_PrintString_End*/
}


void ScrollDisplay(char Direction, char Num_Positions)
{
/*Macro_ScrollDisplay_Start*/

	char cmd = 0;
	char count;

	//Choose the direction
	switch (Direction)
	{
		case 0:
		case 'l':
		case 'L':

			cmd = 0x18;
			break;

		case 1:
		case 'r':
		case 'R':

			cmd = 0x1C;
			break;

		default:
			break;
	}

	//If direction accepted then scroll the specified amount
	if (cmd)
	{
		for (count = 0; count < Num_Positions; count++)
			Command(cmd);
	}

/*Macro_ScrollDisplay_End*/
}


void ClearLine(char Line)
{
/*Macro_ClearLine_Start*/

	char count;
	char rowcount;

	//Define number of columns per line
	#if (%s_ROWCNT == 1)
		rowcount=80;
	#endif

	#if (%s_ROWCNT == 2)
		rowcount=40;
	#endif

	#if (%s_ROWCNT == 4)
		#if (%s_COLCNT == 16)
			rowcount=16;
		#endif
		#if (%s_COLCNT == 20)
			rowcount=20;
		#endif
	#endif

	//Start at beginning of the line
	Cursor (0, Line);

	//Send out spaces to clear line
	for (count = 0; count < rowcount; count++)
		RawSend(' ', 0x10);

	//Move back to the beginning of the line.
	Cursor (0, Line);

/*Macro_ClearLine_End*/
}


void RAM_Write(char nIdx, char d0,  char d1,  char d2,  char d3,  char d4,  char d5,  char d6,  char d7)
{
/*Macro_RAM_Write_Start*/
   //set CGRAM address
   RawSend(64 + (nIdx << 3), 0);
   delay_ms(2);

   //write CGRAM data
   RawSend(d0, 0x10);
   RawSend(d1, 0x10);
   RawSend(d2, 0x10);
   RawSend(d3, 0x10);
   RawSend(d4, 0x10);
   RawSend(d5, 0x10);
   RawSend(d6, 0x10);
   RawSend(d7, 0x10);

   //Clear the display
   RawSend(0x01, 0);
   delay_ms(2);
   RawSend(0x02, 0);
   delay_ms(2);
/*Macro_RAM_Write_End*/
}


