//Distributed under the GPL v 2.0 or later
//by fenn 12/19/06
//demonstration for the wd-c2401p lcd module from various surplus stores
//see http://www.serialwombat.com/parts/lcd111.htm

#include <avr/io.h>

#define SETBIT(PORT, BIT)  PORT |= (1<<BIT)
#define CLRBIT(PORT, BIT)  PORT &= ~(1<<BIT)

#define ISSET(PORT, BIT)  (PORT & (1<<BIT)) != 0
//if (ISSET(PIND, 2)) ...
#define ISNSET(PORT, BIT)  (PORT & ~(1<<BIT)) != 0

#define LED PB0

//lcd pinout
//i wish i knew how to include the port name in the macro definition
#define RST PB3 //reset
#define RS PB2 //register select, hi == data, low == command
#define RW GND //not used yet
#define ENA PB0 //this acts sorta like a clock
#define LCD_DATA PORTA
#define LCD_CTRL PORTB

//for a delay of 1 second, n = about 23000
void delay(long n) 
{
	long a;
	for(a=0;a<n;a++)
	{
		
	}
}

void lcd_send(char byte)
{
	SETBIT(LCD_CTRL, ENA);
	delay(2);
	LCD_DATA=byte; //the bits on the bus go round and round
	delay(2);
	CLRBIT(LCD_CTRL, ENA);
	delay(23); //"at least a millisecond between bytes"
}
/*
RS Pin  Value  Function
  Low  0x1C  Turn on the lcd driver power
  Low  0x14  Turn on the character display
  Low  0x28  Set two display lines (The hd66717 considers 12 characters to be a line. Our 24 character 
display is actually two 12-character lines right next to each other).
  Low  0x4F  Set to darkest contrast
  Low  0xE0  Set the data address to the first character
*/
void lcd_init(void)
{
	CLRBIT(LCD_CTRL, ENA);
	CLRBIT(LCD_CTRL, RS); //command mode
	delay(230);
	lcd_send(0x1C); //turn on LCD
	lcd_send(0x14); //turn on "character display"
	lcd_send(0x28); //set two display lines
	lcd_send(0x4F); //darkest contrast
}

void lcd_write(char* string)
{	
	CLRBIT(LCD_CTRL, RS); //command mode
	delay(23);
	lcd_send(0xE0); //cursor to first character
	SETBIT(LCD_CTRL, RS); //data mode
	int i;
	for(i=0; i<23; i++)
	{
		lcd_send(string[i]);
	}		
}

int main(void)
{    
	DDRB=(0xFF && ~(1<<PB3)  //set port B to output except RST
		&& ~(1<<PB4)
		&& ~(1<<PB5)
		&& ~(1<<PB6));
	DDRA=0xFF; //set port A to output
	lcd_init();

	while(1)
	{
//		SETBIT(PORTB, LED); //turn the led on
		//lcd_init();
		lcd_write("'sup fuckers");
		delay(230);
//		CLRBIT(PORTB, LED); //turn the led off
		delay(230);
	}
}

