/* Allekirjoittanut ei sitten ota allaolevasta koodista minkäänmoisia kommenttaja vastaan. Lukija katsoo koodia täysin omalla 
vastuullaan sokeutumisen ja välittömän pahoinvoinnin uhalla.

ps. Fontit on noukittu vga näytönohjaimen biossista ja tuo oma_delay funktio tuskin toimii oikein kuin ainoastaan juuri 
yhdenlaisessa koneessa joten sille kannattaa tehdä jotain: liian pitkä viive ei juuri haittaa 
toimintaa mutta liian lyhyt kyllä aiheuttaa yhtä sun toista mielenkiintoista.

pps. kääntäjänä tais olla joku borlandin C ja jos homma ei ala toimia niin kannattee tarkistaa että nuo LCD_ENABLE, LCD_CS1 
jne vakiot vastaavat skemaa, kun en nyt muista oliko just tämä koodi se mitä käytin 8-)

Ugh. Ilkka Jauho on puhunut.

*/

#include <stdio.h>
#include <string.h>
#include <conio.h>
#include <io.h>
#include <dos.h>
#include "font.h"
#include <assert.h>

#define DISPLAY_ON         0x3f
#define DISPLAY_OFF        0x3e
#define DISPLAY_STARTLINE  0xc0
#define DISPLAY_PAGE_SET   0xb8
#define DISPLAY_COLUMN_SET 0x40

#define DATAREG 0x3BC
#define CONTROL 0x3BE

#define LCD_ENABLE      1        /* Inverted PIN !!! */
#define LCD_CS1         0	 /* Inverted PIN !!! */
#define LCD_CS2         2        /* connected to LCD_CS1 with inverter */
#define LCD_DATA        4
#define LCD_BACKLIGHT   8        

typedef unsigned char byte;

unsigned char DisplayData[8*128+1];
unsigned char CharacterTbl[256*32+1];

unsigned char CurrentColumn;
unsigned char CurrentLight = 0;

 void OmaDelay(void)
 {
	long a,b;
	for(a=0;a < 300 ;a++)
		b=a/3;
 }

void output(unsigned short port, unsigned char value)
{
   _asm mov al, value
   _asm mov dx, port
   _asm out dx, al
}
void SendLCDCommand(byte value, byte CS)
{
	output(CONTROL, CS | CurrentLight);
	OmaDelay();
	output(DATAREG, value);
	OmaDelay();
	output(CONTROL, LCD_ENABLE | CS | CurrentLight);
}

void SendLCDData(const unsigned char values[], unsigned int amount)
{
    byte cs;
    int counter;
    for (counter=0; counter < amount;counter++)
	{
		cs = CurrentColumn>63?LCD_CS2:LCD_CS1; 
		output(CONTROL, LCD_DATA | cs | CurrentLight);
		OmaDelay();
		output(DATAREG, values[counter]);		
		OmaDelay();
		output(CONTROL, LCD_DATA | LCD_ENABLE | cs | CurrentLight);
		CurrentColumn++;
		if (CurrentColumn > 127) 
			return;
	}	
}

void SetColumn(unsigned char y)
{

    assert(y < 128);
    CurrentColumn = y;
    if (y < 64)
	{		
		SendLCDCommand(DISPLAY_COLUMN_SET | (y&63), LCD_CS1);
		SendLCDCommand(DISPLAY_COLUMN_SET | 0, LCD_CS2);
    } else
	{
   	        SendLCDCommand(DISPLAY_COLUMN_SET | 63, LCD_CS1);
		SendLCDCommand(DISPLAY_COLUMN_SET | ((y-64)&63), LCD_CS2);
    }
}

void SetPage(unsigned char x)
{
    assert( x < 8);
	SendLCDCommand(DISPLAY_PAGE_SET | x, LCD_CS1);
	SendLCDCommand(DISPLAY_PAGE_SET | x, LCD_CS2);
}

void SetStartLine(unsigned char line)
{
	SendLCDCommand(DISPLAY_STARTLINE | (line & 63), LCD_CS1);
	SendLCDCommand(DISPLAY_STARTLINE | (line & 63), LCD_CS2);
}

void LightON(void)
{
	OmaDelay();
    CurrentLight = LCD_BACKLIGHT;
    output(CONTROL, LCD_ENABLE | LCD_CS1 |LCD_BACKLIGHT);
    OmaDelay();
}

void LightOFF(void)
{
	OmaDelay();
    CurrentLight = 0;
    output(CONTROL, LCD_ENABLE | LCD_CS1);
    OmaDelay();
}

 	

void putpixel(unsigned int x, unsigned int y, unsigned char toggle)
{
	DisplayData[(x&127)+(((y&63) >> 3) << 7)] |= 1 << (y & 7);
}

void LCDprintf(unsigned char y, unsigned char page, char *Str,...)
{
	unsigned char n;

    SetColumn(y);
	SetPage(page);
    SetColumn(y);

	for (n = 0;n < strlen(Str);n++)
	{
		  SendLCDData(&Character8x8[*(Str+n)*8], 8);
	}
}

void tauko(void)
{
    unsigned int a;
	a = 5000;
	while(a--) OmaDelay();
}

void main(void)
{
     unsigned char x, value, a;
     int b;
     
	 value = 0x0;
     
	 SendLCDCommand(DISPLAY_ON, LCD_CS1);
	 SendLCDCommand(DISPLAY_ON, LCD_CS2);

     SetStartLine(0);

     for (x=0;x < 8;x++)
     {
	     SetPage(x);SetColumn(0);
	     for (a = 0 ;a < 128; a++) 
			 SendLCDData(&value, 1);
     }

	 SetStartLine(0);
	
	 LightON();
     LCDprintf(0,0,"================");
     LCDprintf(0,1,"    128 x 64    ");
     LCDprintf(0,2," dot matrix LCD ");
     LCDprintf(0,3,"================");

     getch();

     LCDprintf(0,5,"    HW&SW by    ");
	 LCDprintf(4,6,"  Ilkka Jauho  ");
	 

     getch();

	 LCDprintf(0,5," Press any key ");
	 LCDprintf(0,6," to switch off ");

     getch();

     LightOFF();

     LCDprintf(0,5," Press any key ");
	 LCDprintf(0,6," to switch ON! ");
     
     getch();

     LightON();

     LCDprintf(0,5,"   SCROLLING... ");
	 LCDprintf(0,6,"   *********    ");
	 
      a = 0;
     while (!kbhit())
	 {
	   SetStartLine(a++);
	   b = 1000;
   	   while (b--) OmaDelay();
	 }
     LightOFF();

}



