sharp LM085YB01T01 kijelző vezérlése.

Hogyha sikeresen O/PLED illetve hagyományos alfanumerikus - esetleg tán grafikus kijelzővel gyűlik meg a baja valakinek:)
Bearnie74
DrótVégénSzéndarab
Hozzászólások: 34
Csatlakozott: 2016. november 25. péntek, 7:10

sharp LM085YB01T01 kijelző vezérlése.

Hozzászólás Szerző: Bearnie74 »

Sziasztok!

Már itt ott kérdeztem, de most jutottam olyan adatok birtokába, hogy össze kellene szedni a tudásunkat hozzá, hátha érdemleges eszköz lesz belőle.

A problémám:

A fenti cimben megnevezett kijelző vezérlése hogyan oldhtó meg arduinoval, akár plusz elektronikával is.

Amit konkrétan tudok már róla egy dataset. Ami képként van elmente, és ide szertném beszúrni.
Screenshot_2016-12-04-15-30-02.png
Ezek alapján mit hogyan kell kötni programozni?
Nincs meg a kellő jogosultságod a hozzászóláshoz csatolt állományok megtekintéséhez.
A microkontroler sok mindenre alkalmas. a Pc bármire amire meg tudod tanítani.
Avatar
winnerbt
Elektronbűvölő
Hozzászólások: 907
Csatlakozott: 2007. március 25. vasárnap, 6:00

Re: sharp LM085YB01T01 kijelző vezérlése.

Hozzászólás Szerző: winnerbt »

Nézd meg a SED1330/35 és T6963 LCD vezérlők pdf-jét. Az IC-nek lesznek ilyen lábai, oda kell kötni (tehát normális, 4-bites üzemmódban működik).
Lehet, hogy más vezérlőt kell majd választanod, amelyik tudja (főleg a vízszintes) megfelelő felbontást. Igazából, így belegondolva, amelyik uC (ARM) tudja a 4-bites SPI-t kezelni mondjuk DMA-val, azzal elég könnyen megoldható lenne programból is. AVR-el ne reménykedj, nincs rá ideje (vagy csak erre).
SED esetében ha már látsz futkosó vonalakat (bekapcsoláskor auto-refress módba áll), akkor már csak a kb 1000 oldalas doksit kell átbányászni a megfelelő beállításokhoz.
Bearnie74
DrótVégénSzéndarab
Hozzászólások: 34
Csatlakozott: 2016. november 25. péntek, 7:10

Re: sharp LM085YB01T01 kijelző vezérlése.

Hozzászólás Szerző: Bearnie74 »

Nem hangzik valami bizalomgerjesztően elsőre. De hosszas munkával ezek szerint lehet még belőle display.

A tapi padját az életre tudtam kelteni, vagyis odáig eljutottam vele, hogy az uno kiirja a port monitorra az érintési poziciót.

Mostmár csak a nyomkodni való képet kellene alá varázsolnom. :-(
A microkontroler sok mindenre alkalmas. a Pc bármire amire meg tudod tanítani.
Avatar
winnerbt
Elektronbűvölő
Hozzászólások: 907
Csatlakozott: 2007. március 25. vasárnap, 6:00

Re: sharp LM085YB01T01 kijelző vezérlése.

Hozzászólás Szerző: winnerbt »

Nem olyan vészes, logikus a felépítése a vezérlőknek, a T6963 egyszerűbb, a SED kicsit macerásabb, mert tud layer-eket kezelni meg grafikus/karakteres dolgokat egyszerre. Viszont be kellene szerezned egy IC-s kispanelt (valaki gyártott SED1335-os kispaneleket, de nem találom) vagy törött kijelzőt, arról beköthető. Magában csak igen rövid ideig kapcsold be (és tapizd meg a csatlékokat, akkor beszalad valami adat), mert beég (-het), szóval pár másodperc. A vezérlőkhöz mindenképp kell külső SRAM (videoram), kivéve pl. SED13700. HE forumon valaki PICcel hajtott 512x64-es, ilyen buta kijelzőt, szerintem segít Neked. A touch-pad szerintem hétköznapi, azzal nem lesz gondod.
Bearnie74
DrótVégénSzéndarab
Hozzászólások: 34
Csatlakozott: 2016. november 25. péntek, 7:10

Re: sharp LM085YB01T01 kijelző vezérlése.

Hozzászólás Szerző: Bearnie74 »

Mitől éghet be a kijelző?

Ez egy fénymáxolóban volt. Ott elég sokat ment bekapcsolt állapotban uhyanazzal a képpel. De béégve nincs.

Vagy ezeknél mit jelent a beégés?
A microkontroler sok mindenre alkalmas. a Pc bármire amire meg tudod tanítani.
Avatar
Robert
Elektronbűvölő
Hozzászólások: 10191
Csatlakozott: 2005. december 9. péntek, 7:00

Re: sharp LM085YB01T01 kijelző vezérlése.

Hozzászólás Szerző: Robert »

Az LCD maga (azaz a folyadékkristály). Ezt nem 50-50% jellel hajtva a folyadékkristály bomlani kezd.
http://www.tavir.hu - a gazda :)
Avatar
winnerbt
Elektronbűvölő
Hozzászólások: 907
Csatlakozott: 2007. március 25. vasárnap, 6:00

Re: sharp LM085YB01T01 kijelző vezérlése.

Hozzászólás Szerző: winnerbt »

Keress rá a SED1180 pdf-re, kb 10 oldalon van egy általános kijelző felépítéséről rajz. Tehát van X meg Y meghajtó (blokkok), ezek végül is hosszú shiftregiszterek, ezek vezérlése megtalálható a leírásban. A rajzon van egy soktagú feszültségosztó, ennek feszültségeit kapcsolgatja a FRAME-jellel szinkronban magára a folyadékkristályra, tehát AC meghajtást igényel. A vezérlők ezért állnak be egy auto-refress módba mindenféle inicializálás nélkül, így egy aránylag lassú pásztázást lehet látni a kijelzőn, hogy ezek az AC görbék létrejöjjenek, ne károsodjon a DC-től az anyag. Szenvedések közben kb 10 másodperces DC (tehát egy csík beszalad és ott áll) kb 6 órán keresztül látszott még, szerencsére lassan helyrerázódik (ha szerencsénk van, ha nincs, akkor örökre ott marad). Alap dolog az LCD-nél, hogy a kristály meghajtása DC összetevőt nem tartalmazhat. (ami végül is téged nem annyira érdekel, mert a vezérlő majd megoldja, ha egyszer beindul) Sokaknak sikerült túlhajtott AVR-el meghajtani ilyen kijelzőket, keress rá "Driving controller-less graphical LCD" -re.
Bearnie74
DrótVégénSzéndarab
Hozzászólások: 34
Csatlakozott: 2016. november 25. péntek, 7:10

Re: sharp LM085YB01T01 kijelző vezérlése.

Hozzászólás Szerző: Bearnie74 »

Gondolkodtam rajta, hogy magából a fénymásolóból kivarázsolom a meghajtását is.

Elképzelésem szerint, magát a gombok képeit alap és benyomott állapot is egy memóriában tárolhatja. Meg gondolom azon a meghajtó ic is rajta kell legyen.

De mikor kibontottam magát az elektronikát, hát van rajta ki meg bemenő kanóc rendesen. Meg pár ic is. Igy szerintem nehézkes lesz kiszűrni melyik lehet a vezérlő ic je.

Itt a kép róla: vagyis csak lett volna, mert igy túl nagy. Majd otthon gépről felteszem, mert ott le tudom venni a méretét.
A microkontroler sok mindenre alkalmas. a Pc bármire amire meg tudod tanítani.
Bearnie74
DrótVégénSzéndarab
Hozzászólások: 34
Csatlakozott: 2016. november 25. péntek, 7:10

Re: sharp LM085YB01T01 kijelző vezérlése.

Hozzászólás Szerző: Bearnie74 »

Itt vannak a képek a vezérlőjéről.

Maga az lcd még nincs feltölthető formában.
Nincs meg a kellő jogosultságod a hozzászóláshoz csatolt állományok megtekintéséhez.
A microkontroler sok mindenre alkalmas. a Pc bármire amire meg tudod tanítani.
Bearnie74
DrótVégénSzéndarab
Hozzászólások: 34
Csatlakozott: 2016. november 25. péntek, 7:10

Re: sharp LM085YB01T01 kijelző vezérlése.

Hozzászólás Szerző: Bearnie74 »

Maga a vezárlő panel egyszer 24v ot meg 5 v ot kap a fénymásolótol egy szalagkábelen, amin még jön rá pár érzékelő jele, de az most nálunk nem számit.

Tapija lejön külön. Próbáltam életre kelteni, de még az se nagyon sikerűlt. A 4 vezetéket valószinű rosszul kötöm be. Vagy passz.
A microkontroler sok mindenre alkalmas. a Pc bármire amire meg tudod tanítani.
Avatar
kapu48
Elektronbűvölő
Hozzászólások: 3375
Csatlakozott: 2008. augusztus 29. péntek, 6:00

Re: sharp LM085YB01T01 kijelző vezérlése.

Hozzászólás Szerző: kapu48 »

A vezérlő megtartása jó ötletnek tűnik.

Olyan képek kellenének, amin látunk is valamit, ez nagyon csillog!
Nem olvasható, a középen lévő nagyobb IC típus száma?
Ha ahhoz találsz adatlapot? Még boldogulhatsz vele.

Egy ehhez hasonló házilagos megépítésén ne is álmodozzál!
vargham
Chipgyilok
Hozzászólások: 308
Csatlakozott: 2014. január 8. szerda, 8:32

Re: sharp LM085YB01T01 kijelző vezérlése.

Hozzászólás Szerző: vargham »

NYÁK-ot úgy érdemes fotózni, hogy kikapcsolod a vakut, és leteszel mellé egy zseblámpát, ami oldalról világítja meg (súrlófény). Ha megtalálod a jó irányt, akkor az IC típusjelzése szinte kiugrik a képből.
Bearnie74
DrótVégénSzéndarab
Hozzászólások: 34
Csatlakozott: 2016. november 25. péntek, 7:10

Re: sharp LM085YB01T01 kijelző vezérlése.

Hozzászólás Szerző: Bearnie74 »

Nos van már újabb fejlemény a sharp kijelzővel kapcsolatban.

Találtam egy oldalt, ahol a következők voltak leírva. Sajnos csak lengyelűl. (http://www.elektroda.pl/rtvforum/topic2686696.html)

Kód: Egész kijelölése

Atmega1284p podłaczenie do LCD: 
PB0..PB3: Data bits 0..3 
PD2: YSCL 
PD3: M (AC) 
PD4: LCD Enable 
PD5: HSYNC 
PD6: VSYNC 
PD7: DOTCLOCK 
PC1: ECL 

PINOUTY: 
1 – DSP_OFF10 – VDD5 
2 – VSYNC11 – VDD4 
3 – HSYNC12 – VDD3 
4 – SFIC_K13 – VDD2 
5 – +5VS14 – VDD1 
6 – GND15 – VDD0 
7 – N.C16 – VEE 
8 – VDD717 – VLCD 
9 – VDD618 – N.C 



Meg 3 program kód is van, melyet próbálok az időhiányos szabadidőmben megfejteni.

1.:

// 640 x 1 x 200
// 4-bit parallel data interface.

#include <avr/io.h>
#include <stdlib.h>
#include <string.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <util/delay.h>

#include "./config.h"
#include "./clkisr.h"
#include "./util.h"

#define NIBBLEALIGN(px) if (1) {px = (px + 3) & 0xfffc;}	//align on next 4 bit boundary

// Clock Image Data
#include "./SharpClock.inc"

extern prog_uint8_t Font8x8[][8];
// SplashScreen 320 x 240 
extern prog_uint8_t SplashScreen[];
//
#define max(a,b) ((a > b) ? a : b)
#define min(a,b) ((a < b) ? a : b)
//
#define COLORON		0b00000001
#define COLOROFF	0b00000000
//
// a cluster is the lowest common denominator of
// pixels and memory units (bytes/nibbles)
// 
#if BITSPERPIXEL == 1
#define nClustersPerLine (nHorPixels / DATABITS)
#elif BITSPERPIXEL == 3
#define nClustersPerLine (nHorPixels / 8)
#endif

#define nLinesPerBar 20
#define CLOCKOFFSET 20			// such that the 200 x 200 Clock and the 80 x 60 picture are centered in the right side window

uint8 FrameBuffer[PHYS_LINES*BYTES_PER_LINE];
uint8 pwrup_state;
uint8 RefreshLine;
uint8 PDATA;
uint8 BDATA;
uint8 Vx, Vy, Vb;			//nibble address, row address, byte address
uint  Vpix;					//pixel address
uint8 ParseState, PrevParseCommand;
uint8 GlobalFault;
uint8 CommandTimeout;
uint  NoActivityTimeout;
uint8 SecsCountdown;
volatile uint8 SecsToAdd;
uint8 TimeSecs, TimeMins, TimeHrs;
uint8 fShowClock, fStartClock, fAutoClock;
uint  XStart, XEnd, XSize;			//current window limits
uint8 YStart, YEnd, YSize;
uint MaxPictureBytes;
// for Line Command
uint8 SavedArgs[9];
uint8 SavedIdx;
unsigned int BMByteCount;
#if EXTDEBUG
uint8 *pSTData;
unsigned long InCnt;
#endif

void LCDDemo(uint8 val);
void Serial_In (uint8 data);
void DrawTable(prog_uint8_t *Table, uint8 erase);

extern void InitMem(void);
#if DEBUG
uint8 ReadNibble(uint8 x, uint8 y)   __attribute__ ((noinline));
void WriteNibble(uint8 val, uint8 x, uint8 y)   __attribute__ ((noinline));
#else
uint8 ReadNibble(uint8 x, uint8 y);
void WriteNibble(uint8 val, uint8 x, uint8 y);
#endif
void SetPixel(uint8 color, uint x, uint8 y);
void PutChar(uint8 ch);

#if DEBUG
void MemoryScanNonZero(uint8 y);
#endif

void Parse(uint8 inByte);

void __attribute__ ((naked, section (".init1")))	// called before .do_copy_data_start
SetMem_init (void) 
{
	InitMem();
}

// __heap_start is defined in the linker script
extern uint8_t __heap_start;

#if DEBUG
//		 Check for 0xcc (in DEBUG mode) as set by SetMem();
uint16_t
GetMemUnused (void)
{
	uint16_t unused = 0;
    
    // Get end of static allocated RAM space (.data, .bss, .noinit, ...)
	uint8_t *p = &__heap_start;
	
	do
	{
        // Value written in InitMem() still intact?
		if (*p++ != 0xcc)
			break;
			
		unused++;
	} while (p <= (uint8_t *) RAMEND);

	return unused;
}
#endif

void foo(void)
{
	do {
		asm volatile (
			"nop	\n\t"
		);
	} while (1);
}
//
// Enable debug led
//
void InitDebug(void)
{
#if USE_LED
	LED_OFF;
	sbi(LED_DDR,LED_BIT);			//output
#endif
	LED2_OFF;
	sbi(LED2_DDR,LED2_BIT);			//output
}

const char DiagStr0[] PROGMEM = "DebugL0 ";
const char DiagStr1[] PROGMEM = "\n\rDebugL1: 0x";
const char DiagStr2[] PROGMEM = "DebugL2\n\r";
const char DiagStr3[] PROGMEM = "DebugL3\n\r";
const char DiagStr4[] PROGMEM = "DebugL4\n\r";
const char DiagStr5[] PROGMEM = "DebugL5\n\r";

void DebugL0(uint8 err)  __attribute__ ((noinline));
void DebugL0(uint8 err)
{
	UARTPrintfProgStr_I((prog_char*)DiagStr0);
	Printfuint8(err);
	PrintfEndOfLine();
	FlashLed(5, 1);
}

void DebugL1(void)
{
	UARTPrintfProgStr_I((prog_char*)DiagStr1);
#if 0
	// Move this to ClkIsr.c
	uint8 *ptr;
	Printfu16((int)TailPtr);
	UARTSendByte(' ', FALSE);
	FlashLed(10, 1);
	//
	// now print last 32 bytes from input queue
	//
	for (int i = 32; i >= 1; --i) {
		ptr = (uint8 *)(TailPtr - i);
		if (ptr < &RxBuffer[0]) ptr += RXSIZE;
		Printfuint8(*ptr);
		UARTSendByte(' ', FALSE);
	}
#endif
	PrintfEndOfLine();
}

void DebugL2(void)
{
	UARTPrintfProgStr_I((prog_char*)DiagStr2);
	FlashLed(10, 2);
}

void DebugL3(void)
{
	UARTPrintfProgStr_I((prog_char*)DiagStr3);
	FlashLed(10, 3);
}

void DebugL4(void)
{
	UARTPrintfProgStr_I((prog_char*)DiagStr4);
	FlashLed(10, 4);
}

void DebugL5(void)
{
	UARTPrintfProgStr_I((prog_char*)DiagStr5);
	FlashLed(10, 5);
}
//
// TC0 is used to do the LCD Screen Refresh
//
// Initialize TC0
// Set prescaler to clkio/64. At 20 Mhz, this is 3.2 uSec
// Using a Timer0CountUp value of 52 yields an match every 166.4 uSec.
// resulting in a refresh rate of 60 (60 x 100 = 6,000 Hz -> 166.66 uSec)
// 60Hz refresh rate shows no visible flicker, a little flicker on video.
//
// Processing time per line: 89 uSec (1/3/2011),
// meaning the LCD refresh load is 53%. At this load, the AVR has no
// trouble processing a 115,200 bps serial stream (plus there is flow control)
//
// The refresh rate can be reduced to 50 Hz and there still is no visible flicker.
//
#if F_CPU==20000000UL
#define Timer0CountUp 52		//62 for 50 Hz.
#else
error: F_CPU undefined
#endif

void InitTC0(void)
{
	TCCR0A = _BV(WGM01);			// run timer in CTC mode
	TCCR0B = (0<<CS02)|_BV(CS01)|_BV(CS00);
	OCR0A = Timer0CountUp;
}

void EnableTC0(void)
{
	TIFR0 = _BV(OCF0A);				//clear pending match
	TIMSK0 = _BV(OCIE0A);			//Enable TC0.match
}

//
// Timer1 is setup in util.c but calls the application
// specific function "AppTimer1Stuff"
//
void AppTimer1Stuff(void)
{
	if (--SecsCountdown == 0) {
		SecsCountdown = 10;
		++SecsToAdd;
	}
	if (CommandTimeout != 0) {
		if (--CommandTimeout == 0) {
			// Command Time out. Reset State Machine
			ParseState = STANDBY;
		}
	}
	if (NoActivityTimeout != 0) {
		if (--NoActivityTimeout == 0) {
			// No Activity Timeout. Start Clock
			// Ought to save current image, then clrscreen first
			fStartClock = TRUE;
			fAutoClock = TRUE;
		}
	}
}

void InitDebug(void);

void InitCtrl(void)
{
//
// I/O PORTS INITIALIZATION
//
 	SRAMDATA_DDR = SRAMDATA_MASK;	//data port defaults to output


	cbi(LCD_YSCL, YSCL_BIT);		//active High
	cbi(LCD_ENABLE, ENABLE_BIT);	//disable LCD
	cbi(LCD_HSYNC, HSYNC_BIT);		//active High
	cbi(LCD_VSYNC, VSYNC_BIT);		//active High
	cbi(DOTCLK, DOTCLK_BIT);		//active on falling edge
	cbi(LCD_ECL, ECL_BIT);			//active High

	sbi(YSCL_DDR, YSCL_BIT);
	sbi(LCDM_DDR, M_BIT);
	sbi(ENABLE_DDR, ENABLE_BIT);
	sbi(HSYNC_DDR, HSYNC_BIT);
	sbi(VSYNC_DDR, VSYNC_BIT);
	sbi(DOTCLK_DDR, DOTCLK_BIT);
	sbi(ECL_DDR, ECL_BIT);

#if DEBUG
	cbi(MCU_TEST, MCU_TEST_BIT);
	sbi(MCU_TEST_DDR, MCU_TEST_BIT);
#endif
//
// Disable unused parts of the AVR to reduce power consumption
//
// unused TWI, ADC, TIM2, SPI
//
// Reserve TIM1 for inByte timeout
//
	PRR0 = _BV(PRTWI) | _BV(PRADC) | _BV(PRTIM2) | _BV(PRSPI);

	InitTC0();					//LCD refresh timer
	InitTC1();					//Timeout/Led
	InitDebug();
//
// VARIABLES INITIALIZATION
//
	XStart = 0;
	XEnd = nHorPixels - 1;
	XSize = XEnd - XStart + 1;
	YStart = 0;
	YEnd = nLines - 1;
	YSize = YEnd - YStart + 1;
	MaxPictureBytes  = (YSize * (XSize / 8));

	RefreshLine = 0;			//LCD Line being displayed
	pwrup_state = 0;
	ParseState = 0;				//GrState = STANDBY
	PrevParseCommand = 0;			//nothing
	PDATA = COLORON;
	BDATA = COLOROFF;
	Vpix = Vx = Vy = 0;
	GlobalFault = 0;
	SecsCountdown = 10;
	SecsToAdd = 0;
	CommandTimeout = 0;
	NoActivityTimeout = NOACTIVITY;
#if EXTDEBUG
	pSTData = FrameBuffer;
	InCnt = 0;
#endif
}
//
// WriteNibble:	write a nibble to SRam.
//
// IN:	r24:nibble	r22 x-address	r20 y-address
//
void WriteNibble(uint8 nibble, uint8 x, uint8 y)
{
	uint8 b, *p;
	uint x0 = x;
	ASSERT(x < LOG_NIBBLES_PER_LINE);
	if (x >= LOG_NIBBLES_PER_LINE) {
		x = LOG_NIBBLES_PER_LINE - 1;
	}
	ASSERT(y < LOG_MAX_LINES);
	if (y >= LOG_MAX_LINES) {
		y = LOG_MAX_LINES - 1;
	}
	if (y >= PHYS_LINES) {
		y -= PHYS_LINES;
		x0 += LOG_NIBBLES_PER_LINE;
	}
	p = &FrameBuffer[(y * BYTES_PER_LINE) + (x0 >> 1)];
	b = *p;
	if (x & 1) {
		b = (nibble & 0x0f) | (b & 0xf0);
	} else {
		b = (nibble << 4) | (b & 0x0f);
	}
	*p = b;
}

//
// WriteByte:	write a byte to SRam.
//
// IN:	r24:byte	r22 x-address (in bytes)	r20 y-address
//
void WriteByte(uint8 b, uint8 x, uint8 y)
{
	ASSERT(x < LOG_NIBBLES_PER_LINE / 2);
	if (x >= (LOG_NIBBLES_PER_LINE /2)) {
		x = (LOG_NIBBLES_PER_LINE / 2) - 1;
	}
	ASSERT(y < LOG_MAX_LINES);
	if (y >= LOG_MAX_LINES) {
		y = LOG_MAX_LINES - 1;
	}
	if (y >= PHYS_LINES) {
		y -= PHYS_LINES;
		x += (LOG_NIBBLES_PER_LINE / 2);
	}
	FrameBuffer[(y * BYTES_PER_LINE) + x] = b;
}

uint8 ReadNibble(uint8 x, uint8 y)
{
	uint8 b;
	uint x0 = x;
	ASSERT(x < LOG_NIBBLES_PER_LINE);
	if (x >= LOG_NIBBLES_PER_LINE) {
		x = LOG_NIBBLES_PER_LINE - 1;
	}
	ASSERT(y < LOG_MAX_LINES);
	if (y >= LOG_MAX_LINES) {
		y = LOG_MAX_LINES - 1;
	}
	if (y >= PHYS_LINES) {
		y -= PHYS_LINES;
		x0 += LOG_NIBBLES_PER_LINE;
	}
	b = FrameBuffer[(y * BYTES_PER_LINE) + (x0 >> 1)];
	if (x & 1) {
		return (b & 0x0f);
	} else {
		return (b >> 4);
	}
}
//
// Write a character at the current pixel location.
// May not wrap Vpix and Vy properly.
// SED
//
void PutChar(uint8 ch)
{
	uint8	i,FontLine,px;
	prog_uint8_t *pCode;
	NIBBLEALIGN(Vpix);
	if ((Vpix + 8) > nHorPixels) {			// char won't fit on current line
		Vpix = 0;
		Vy += 8;							// Line overflow check next
	}
	if ((Vy + 8) > nLines) {				// char won't fit on screen
		Vy = 0;
	}
	if (((uint8)Vpix & 0x07) != 0) {		// not byte aligned
		px = (Vpix >> 2);					// Convert to nibble
		//
		// write One Line at a time
		for (i = 0; i < 8; i++) {
			pCode = &(Font8x8[ch][i]);
			FontLine = __LPM(pCode);
			WriteNibble(FontLine >> 4, px, Vy+i);
			WriteNibble(FontLine & 0x0f, px+1, Vy+i);
		}
	} else {								// Vpix is byte aligned
		px = (Vpix >> 3);					// Convert to byte
		//
		// write One Line at a time
		for (i = 0; i < 8; i++) {
			pCode = &(Font8x8[ch][i]);
			FontLine = __LPM(pCode);
			WriteByte(FontLine, px, Vy+i);
		}
	}
	Vpix += 8;
}

byte MaskTbl[4] PROGMEM = {
	8, 4, 2, 1
};

//
// Set Pixel at location x, y to color
// TODO use 4 byte table to compute bitmask
//
void SetPixel(uint8 color, uint x, uint8 y)
{
	uint8 v, offset, bitmask, px;
	x = min(x, nHorPixels - 1);
	y = min(y, nLines - 1);
	px = (x >> 2);				//enclosing nibble
	v = ReadNibble(px, y);
	offset = x & 0x03;
	bitmask = __LPM(&MaskTbl[offset]);
	v &= ~bitmask;		//clear pixel
	if (color) {
		v |= bitmask;
	}
	WriteNibble(v, px, y);
}
//
// Bresenham line drawing
//
void DrawLine(uint x0, uint y0, uint x1, uint y1)
{
	uint steep, tmp;
	u32 x, y;
	s16 ystep;
	int deltax, deltay, error;

#if DEBUG
	if ((x0 >= nHorPixels) || (x1 >= nHorPixels) || (y0 >= nLines) || (y1 >= nLines)) return;
#endif

	steep = (abs(y1 - y0) > abs (x1 - x0));
	if (steep) {
		tmp = x0; x0 = y0; y0 = tmp;		//  swap(x0, y0)
		tmp = x1; x1 = y1; y1 = tmp;        //  swap(x1, y1)
	}
    if (x0 > x1) {
		tmp = x0; x0 = x1; x1 = tmp;		// swap(x0, x1)
		tmp = y0; y0 = y1; y1 = tmp;		// swap(y0, y1)
	}
	deltax = x1 - x0;
	deltay = abs(y1 - y0);
	error = 0;
	y = y0;
	if (y0 < y1) ystep = 1;
	else ystep = -1;
	for (x = x0; x <= x1; x++) {
		if (steep) SetPixel(PDATA, y, x);
		else SetPixel(PDATA, x, y);
		error += deltay;
		if ((error * 2) >= deltax) {
			y += ystep;
			error -= deltax;
		}
	}
}

//
// Bresenham circle drawing
//
void DrawCircle(unsigned int cx, unsigned int cy ,unsigned int radius)
{
	int x, y, xchange, ychange, radiusError;
	x = radius;
	y = 0;
	xchange = 1 - 2 * radius;
	ychange = 1;
	radiusError = 0;
	while(x >= y) {
	  SetPixel(PDATA, cx+x, cy+y ); 
	  SetPixel(PDATA, cx-x, cy+y ); 
	  SetPixel(PDATA, cx-x, cy-y );
	  SetPixel(PDATA, cx+x, cy-y ); 
	  SetPixel(PDATA, cx+y, cy+x ); 
	  SetPixel(PDATA, cx-y, cy+x ); 
	  SetPixel(PDATA, cx-y, cy-x ); 
	  SetPixel(PDATA, cx+y, cy-x ); 
	  y++;
	  radiusError += ychange;
	  ychange += 2;
	  if ( 2*radiusError + xchange > 0 ) {
	    x--;
		radiusError += xchange;
		xchange += 2;
		}
	}
}

void DrawTable(prog_uint8_t *Table, uint8 erase)
{
	prog_uint8_t *pCode = Table;
	uint8 x0,y0,x1,y1;
	uint8 SavedColor = PDATA;

	if (erase) {
		PDATA = BDATA;
	}

	do {
		while ((x0 = __LPM(pCode)) == 0) {		//skip leading 0 bytes
			++pCode;
		}
		++pCode;
		ASSERT (x0 != 0);
		y0 = min(lastLine, __LPM(pCode));
		y0 = lastLine-y0;						//invert Y
		++pCode;
		do {
			x1 = __LPM(pCode);
			++pCode;
			if (0 == x1) break;				//move to next coordinate pair
			if (0xff == x1) {				//end of coordinate pairs
				if (erase) {
					BDATA = PDATA;
					PDATA = SavedColor;
				}
				return;
			}
			y1 = min(lastLine, __LPM(pCode));
			y1 = lastLine-y1;						//invert Y
			++pCode;
			DrawLine(x0 + CLOCKOFFSET, y0, x1 + CLOCKOFFSET, y1);
			x0 = x1;
			y0 = y1;
		} while (1);
	} while (1);

	if (erase) {
		BDATA = PDATA;
		PDATA = SavedColor;
	}
}

void DrawSecsHand(uint8 sec, uint8 erase)
{
	if (sec >= 60)
		return;

	DrawTable(&SecPtrData[sec * 5], erase);
}

void DrawMinsHand(uint8 min, uint8 erase)
{
	if (min >= 60)
		return;

	DrawTable(&MinPtrData[min * 9], erase);
}

void DrawHrsHand(uint8 hr, uint8 erase)
{
	if (hr >= 12)
		return;

	DrawTable(&HrPtrData[hr * 45], erase);
}

void UpdateTime(void)
{
	while (SecsToAdd > 0) {
		--SecsToAdd;
		if (fShowClock) {
			DrawSecsHand(TimeSecs, TRUE);			//erase current seconds hand
		}
		++TimeSecs;
		if (TimeSecs >= 60) {
			if (fShowClock) {
				DrawMinsHand(TimeMins, TRUE);		//erase current minutes hand
			}
			TimeSecs = 0;
			++TimeMins;
			if (TimeMins >= 60) {
				if (fShowClock) {
					DrawHrsHand(TimeHrs, TRUE);		//erase current hours hand
				}
				TimeMins = 0;
				++TimeHrs;
				if (TimeHrs >= 12) {
					TimeHrs = 0;
				}
			}
		}
		if (fShowClock) {
			DrawTable(DialDigits12, FALSE);
			DrawSecsHand(TimeSecs, FALSE);
			DrawMinsHand(TimeMins, FALSE);
			DrawHrsHand(TimeHrs, FALSE);
		}
	}
}

void StartClock(void)
{
	fStartClock = FALSE;
	fShowClock = TRUE;
	DrawTable(DialData, FALSE);
	DrawTable(DialDigits12, FALSE);
	DrawSecsHand(TimeSecs, FALSE);
	DrawMinsHand(TimeMins, FALSE);
	DrawHrsHand(TimeHrs, FALSE);
}

void StopClock(void)
{
	DrawTable(DialData, TRUE);
	DrawTable(DialDigits12, TRUE);
	DrawSecsHand(TimeSecs, TRUE);
	DrawMinsHand(TimeMins, TRUE);
	DrawHrsHand(TimeHrs, TRUE);
	fShowClock = FALSE;
	fAutoClock = FALSE;
}

uint8 PrepareNibble(uint8 color)
{
#if DEBUG
	color &= 0x01;
#endif
	return (color) ? 0b00001111 : 0;
}
//
// set screen area to color. Set BDATA, Vx, Vy, Vpix
//
void SetScreenX(uint8 color, uint x0, uint8 y0, uint x1, uint8 y1)
{
	uint8 nibble, x, y;
//
// convert pixel address X0 to nibble boundary
// align starting pixel to next nibble boundary
// align ending pixel to previous nibble boundary
//
	NIBBLEALIGN(x0);
	x1 = (x1 + 0) & 0xfffc;

	nibble = PrepareNibble(color);
	for (y = y0; y <= y1; ++y) {		// Top to Bottom
		for (x = (x0 >> 2) ; x <= (x1 >> 2); ++x) {
			WriteNibble(nibble, x, y);
		}
	}
	BDATA = color;						//set color as background color
	Vy = y0;
	Vx = (x0 >> 2);
	Vpix = (Vx << 2);
}

//
// set screen to color. Set BDATA, Vx, Vy, Vpix
//
// Optimization: could to a memset on the FrameBuffer!
//
void SetScreen(uint8 color)
{
	uint8 v, x, y;
#if DEBUG
	color &= 0x01;
#endif
	v = (color) ? 0b11111111 : 0;
	for (y = 0; y < nLines; ++y) {		// Top to Bottom
		for (x = 0 ; x < (LOG_NIBBLES_PER_LINE / 2); ++x) {
			WriteByte(v, x, y);
		}
	}
	BDATA = color;						//set color as background color
	Vy = Vx = Vpix = 0;
}

#if DEBUG
//
// Draw a line using argument color. Starting at current Vy
// Use WriteNibble()
//
void HorizontalLine(uint8 color)
{
	uint8 x, nibble;
	nibble = PrepareNibble(color);
	for (x = 0; x < nColumnsPerLine; ++x) {
		WriteNibble(nibble, x, Vy);
	}
}

//
// Draw a line using argument color. Starting at current Vy.
// Use SetPixel
//
void HorizontalPixelLine(uint8 color)
{
	PDATA = color;
	uint px;
	for (px = 0; px < (nHorPixels/16); ++px) {
		SetPixel(color, px, Vy);
	}
}
#endif

//
// Draw a bar using argument color. Starting at current Vy
//
void HorizontalBar(uint8 color)
{
	uint8 i, x, nibble;
	i = nLinesPerBar;			//number of lines
	nibble = PrepareNibble(color);
	do {
		for (x = 0; x < nColumnsPerLine; ++x) {
			WriteNibble(nibble, x, Vy);
		}
		++Vy;
	} while (--i);
	Vx = 0;
}
//	
// horizontal test bars.
//
void HorizontalTest(void)
{
	uint8 i;
	Vy = 0;
	for (i = 0; i < (nLines/(2 * nLinesPerBar)); ++i) {		//as many as will fit
		HorizontalBar(COLORON);
		HorizontalBar(COLOROFF);
	}
#if DEBUG
	if (Vy != nLines) {
		DebugL0(LCDERROR0);
	}
#endif
	Vx = Vy = 0;
}
//
//  compare data with PDATA
//
void VerifyNibble(uint8 data)
{
	// bit 0: D0 .. bit 3: D0
	if ((data & 0x01) != PDATA) DebugL0(LCDERROR0);
	data >>= 1;
	if ((data & 0x01) != PDATA) DebugL0(LCDERROR0);
	data >>= 1;
	if ((data & 0x01) != PDATA) DebugL0(LCDERROR0);
	data >>= 1;
	if ((data & 0x01) != PDATA) DebugL0(LCDERROR0);
}

void VerifyHorizontalLine(void)
{
	uint8 nibble, i = nClustersPerLine;
	Vx = 0;
	do {
		nibble = ReadNibble(Vx, Vy);
		++Vx;
		VerifyNibble(nibble);		//compare with PDATA
	} while (--i);
}
//
// argument: expected color 
//
void VerifyHorizontalBar(uint8 color)
{
	uint8 i = nLinesPerBar;
	PDATA = color;			//save
	do {
		VerifyHorizontalLine();
		++Vy;
	} while (--i);
}

void VerifyHorizontalTest()
{
	Vy = 0;
	for (uint8 i = 0; i < (nLines/(2 * nLinesPerBar)); ++i) {		//as many as will fit
		VerifyHorizontalBar(COLORON);
		VerifyHorizontalBar(COLOROFF);
	}
	Vx = Vy = 0;				//reset
	Vpix = 0;
}
//
// VerticalTest: draw vertical bars
//
void VerticalTest()
{
	uint8 color, i, nibble, x, y;
	for (y = 0; y < nLines; ++y) {
		x = 0;
		color = COLOROFF;		//color
		for (i = 0; i < (nColumnsPerLine >> 1); ++i) {
			if (++color > COLORON) {	//next color
				color = COLOROFF;
			}
			nibble = PrepareNibble(color);	//set from PDATA
			WriteNibble(nibble, x, y);
			WriteNibble(nibble, x+1, y);
			x += 2;
		}
	}
	Vx = Vy = 0;				//reset
	Vpix = 0;
}

//
// HorVertTest: draw clusters
//
void HorVertTest()
{
	uint8 i, j, color0, color, nibble, x, y;
	color0 = COLOROFF;				//start color
	for (y = 0; y < nLines;) {
		if (++color0 > COLORON) {	//next color
			color0 = COLOROFF;
		}
		color = color0;
		for (j = 0; j < 8; ++j) {		//nr of lines per block
			x = 0;
			for (i = 0; i < (nColumnsPerLine >> 1); ++i) {
				nibble = PrepareNibble(color);	//set  from PDATA
				WriteNibble(nibble, x, y);
				WriteNibble(nibble, x+1, y);
				x += 2;
				if (++color > COLORON) {	//next color
					color = COLOROFF;
				}
			}
			++y;
		}
	}
	Vx = Vy = 0;			//reset
	Vpix = 0;
}
//
// Draw horizontal bars slowly.
//
void SlowHorizontalBars(void)
{
	uint8 i;
	Vy = 0;
	for (i = 0; i < (nLines/(2 * nLinesPerBar)); ++i) {		//as many as will fit
		HorizontalBar(COLORON);
		HorizontalBar(COLOROFF);
		delayOneSecond();
	}
	Vx = 0;
	Vy = 0;
}
//
// Select a demo. All delays done by sender
//
void LCDDemo(uint8 val)
{
	if (val == 1) {
		HorizontalTest();
		VerifyHorizontalTest();
	} else if (val == 2) {
		VerticalTest();
	} else if (val == 3) {
		HorVertTest();
	} else if (val == 4) {
		SlowHorizontalBars();		//takes a while
	}
}

void Parse(uint8 inByte)
{
	uint8 v;
	//
	// Setting CommandTimeout to 50 gives us 5 second
	// before the ParseState is set to STANDBY
	// Timeout will never occur while inside Parse() - that's the intent
	//
	CommandTimeout = 50;
	if (ParseState == STANDBY) {
		//
		//Decode inByte
		//
  		if ((inByte & SINGLEBYTEMASK) != SINGLEBYTECMD) {
			//
			//MultiByteCommand
			//
			PrevParseCommand = inByte;
			ParseState = inByte & MULTIBYTEMASK;
		}
		else {
			//
			// SingleByteCommand
			//
			if (LCD_DUMMY == inByte) {
			} else if (CLEAR_SCR == inByte) {
				SetScreen(COLOROFF);		// sets BDATA
				PDATA = COLORON;
			} else if (CLOCK_ON == inByte) {
				StartClock();
			} else if (CLOCK_OFF == inByte) {
				StopClock();
			}
			//
			// done with unparameterized single byte commands.
			// Must be <PSET>, <X++>, <Y++>, <X-->, <Y-->, <X++,PSET>, <Y++,PSET>, <X--,PSET> or, <Y--,PSET>
			// Also UNSET (Clr pixel)
			else if ((inByte & PSETINCDECMASK) == PSETINCDECCMD) {	//Increment, Decrement, PSET
				if ((inByte & PSETPIXMASK) == PSETPIXMASK) {		// unused
				} else if (inByte & PSETPIXON) {
					SetPixel(PDATA, Vpix, Vy);			// Set Pixel
				} else if (inByte & PSETPIXOFF) {
					SetPixel(BDATA, Vpix, Vy);			//Clear Pixel
				}
				//
				// Now check for X/Y increment or decrement
				//
				v = (inByte & PSETXYMASK);				//X, Y or nothing
				if (v == PSETXYMASK) {					//unused
				} else if (v == PSETX) {
					if (inByte & PSETDEC) {				//Decrement
						if (--Vpix == 0xffff) Vpix = lastHorPixel;
					} else {							//Increment
						if (++Vpix == nHorPixels) Vpix = 0;
					}
				} else if (v == PSETY) {
					if (inByte & PSETDEC) {				//Decrement
						if (--Vy == 0xff) Vy = lastLine;
					} else {							//Increment
						if (++Vy == nLines) Vy = 0;
					}
				} else {								//No X or Y action.
				}
			} //PSETINCDECCMD
			else { // UNKNOWN or UNIMPLEMENTED
			//ignore since it's single byte
			}
		} // SingleByteCommand
	} //ParseState == STANDBY
#if EXTDEBUG
	else if (ParseState == SERIALTEST) {
  		if ((PrevParseCommand & MULTIBYTEMASK) == SERIALTEST) {
			//First time through.
			SavedIdx = 0;
			PrevParseCommand &= ~MULTIBYTEMASK;
		}
		// 1 byte argument: #of test bytes
		SavedArgs[SavedIdx++] = inByte;
		if (SavedIdx >= 1) {
			ParseState = SERIALTEST_DATA;
			PrevParseCommand = SERIALTEST;
		}
	}
	else if (ParseState == SERIALTEST_DATA) {
		if (PrevParseCommand != SERIALTEST) {
			// inconsistency
				DebugL1();
		}
		*pSTData++ = inByte;		//store test bytes
		if (pSTData >= &FrameBuffer[PHYS_LINES*BYTES_PER_LINE]) {
			pSTData = FrameBuffer;
		}
		if (--SavedArgs[0] == 0) {
			ParseState = STANDBY;
		}
	}
#endif
	else if (ParseState == PICTURE) {
		//
		// TODO. sb pixel argument for x. If x0 or x1 not aligned
		// on nibble boundary, discard the data.
		// first 4 byte arguments (x0, y0, x1, y1. Nibble addresses
		// then data: (((x1 - x0 + 1) * (y1 - y0 + 1)) / 2) bytes
  		if ((PrevParseCommand & MULTIBYTEMASK) == PICTURE) {
			//First time through.
			SavedIdx = 0;
			PrevParseCommand &= ~MULTIBYTEMASK;
		}
		// 4 bytes argument: X0,Y0,X1,Y1 (nibble addresses)
		SavedArgs[SavedIdx++] = inByte;
		if (SavedIdx >= 4) {	// collected all args
			BMByteCount = ((SavedArgs[2] - SavedArgs[0] + 1) * (SavedArgs[3] - SavedArgs[1] + 1) / 2);
			if (BMByteCount > MaxPictureBytes) {
				// TODO. Compute excess and ignore those bytes
				DebugL1();
			}
			// TODO: expect Pixel Argument? Cluster Argument. Use X window limits
			if (SavedArgs[0] >= nClustersPerLine) SavedArgs[0] = 0;		//TODO
			Vx = SavedArgs[0];
//			if (SavedArgs[1] < YStart) SavedArgs[1] = YStart;
			if (SavedArgs[3] > YEnd) SavedArgs[3] = YEnd;
			Vy = SavedArgs[3];
			ParseState = PICTURE_DATA;
#if DEBUG
			PrevParseCommand = PICTURE;
#endif
		}
	}	// PICTURE
	else if (ParseState == PICTURE_DATA) {
		ASSERT(PrevParseCommand == PICTURE);
		// 2 nibbles packed per byte, packed Upper nibble, then Lower nibble
		// works as long as "x1 - x0 + 1" is even
		// Data come in bottom of area lines first
		if (((uint8)Vx & 0x01) != 0) {		// not byte aligned
			WriteNibble((inByte >> 4), Vx, Vy);
			WriteNibble((inByte & 0x0f), Vx+1, Vy);
		} else {
			WriteByte(inByte, Vx >> 1, Vy);
		}
		Vx += 2;
		if ((Vx - 1) == SavedArgs[2]) {
			Vx = SavedArgs[0];
			Vpix = (Vx << 2);
			if (--Vy == SavedArgs[1] - 1) {
				Vy = SavedArgs[1];
			}
		}
		if (--BMByteCount == 0) {
			ParseState = STANDBY;
		}

	} //PICTURE_DATA
	else if ((ParseState & MULTIBYTEMASK) == COLOR) {
		PDATA = (PrevParseCommand & 0x07);
		BDATA = PDATA ? 0 : 1;
		// ignore current byte in inByte
		ParseState = STANDBY;
	}
	else if (ParseState == SET) {
  		if ((PrevParseCommand & MULTIBYTEMASK) == SET) {
			//First time through.
			SavedIdx = 0;
			PrevParseCommand &= ~MULTIBYTEMASK;
		}
		// 2 bytes argument: X or Y
		SavedArgs[SavedIdx++] = inByte;
		if (SavedIdx >= 2) {	// collected all args
			if (PrevParseCommand & SETX) Vpix = SavedArgs[0] | (SavedArgs[1] << 8);
			else Vy = (uint8)(SavedArgs[0] | (SavedArgs[1] << 8));
			if (PrevParseCommand & SETPIXON) {
				SetPixel(PDATA, Vpix, Vy);
			} else if (PrevParseCommand & SETPIXOFF) {
				SetPixel(BDATA, Vpix, Vy);
			}
			ParseState = STANDBY;
		}
	}
	else if (ParseState == PRINT_STRING) {
		//
		// Print String State. Check if NULL
		//
		if (inByte != 0) {
			PutChar(inByte);
		}
		else {
			ParseState = STANDBY;	// End of String
		}
	}
	else if (ParseState == PUT_CHAR) {
		PutChar(inByte);
		ParseState = STANDBY;
	}
	else if (ParseState == DRAW_LINE) {
  		if ((PrevParseCommand & MULTIBYTEMASK) == DRAW_LINE) {
			//First time through.
			SavedIdx = 0;
			PrevParseCommand &= ~MULTIBYTEMASK;
		}
		// 8 bytes argument: X0,Y0,X1,Y1
		// X0, X1, Y0 and Y1 are 2 bytes each (low, high)
		SavedArgs[SavedIdx++] = inByte;
		if (SavedIdx >= 8) {	// collected all args
			DrawLine(SavedArgs[0] | (SavedArgs[1] << 8),
					 SavedArgs[2] | (SavedArgs[3] << 8),
					 SavedArgs[4] | (SavedArgs[5] << 8),
					 SavedArgs[6] | (SavedArgs[7] << 8));
			//
			// Set current coordinate to last pixel drawn
			//
			Vpix = SavedArgs[4] | (SavedArgs[5] << 8);
			Vy = SavedArgs[6] | (SavedArgs[7] << 8);
			ParseState = STANDBY;
		}
	}
	else if (ParseState == DRAW_CIRCLE) {
  		if ((PrevParseCommand & MULTIBYTEMASK) == DRAW_CIRCLE) {
			//First time through.
			SavedIdx = 0;
			PrevParseCommand &= ~MULTIBYTEMASK;
		}
		// 6 bytes argument: X,Y,Radius
		// X, Y and Radius are 2 bytes each (low, high)
		SavedArgs[SavedIdx++] = inByte;
		if (SavedIdx >= 6) {	// collected all args
			DrawCircle(SavedArgs[0] | (SavedArgs[1] << 8),
					   SavedArgs[2] | (SavedArgs[3] << 8),
					   SavedArgs[4] | (SavedArgs[5] << 8));
			//
			// Set current coordinate to center of circle
			//
			Vpix = SavedArgs[0] | (SavedArgs[1] << 8);
			Vy = SavedArgs[2] | (SavedArgs[3] << 8);
			ParseState = STANDBY;
		}
	}
	else if (ParseState == SET_SCREEN) {
  		if ((PrevParseCommand & MULTIBYTEMASK) == SET_SCREEN) {
			//First time through.
			SavedIdx = 0;
			PrevParseCommand &= ~MULTIBYTEMASK;
		}
		// 9 bytes argument: color, X0,Y0,X1,Y1
		// color is 1 byte. X0, X1, Y0 and Y1 are 2 bytes each (low, high)
		SavedArgs[SavedIdx++] = inByte;
		if (SavedIdx >= 9) {	// collected all args
			SetScreenX(	SavedArgs[0],
						SavedArgs[1] | (SavedArgs[2] << 8),				//x0
						(uint8)(SavedArgs[3] | (SavedArgs[4] << 8)),	//y0
						SavedArgs[5] | (SavedArgs[6] << 8),				//x1
						(uint8)(SavedArgs[7] | (SavedArgs[8] << 8)));	//y1
			ParseState = STANDBY;
		}
	}
	else if (ParseState == LCDDEMO) {
		LCDDemo(inByte);		//select Demo
		ParseState = STANDBY;
	}
	else {
		DebugL1();
		ParseState = STANDBY;
	}
#if 0&DEBUG
	if (STANDBY == ParseState) {
		UARTSendByte('.', FALSE);
	}
#endif
}

const char StartStr1[] PROGMEM = "\r\nEpson P3000 LCD Controller V1.2\r\n";
//
// TODO: replace columnOffset with SetWindow()
void SetSplashScreen(uint8 columnOffset)
{
//
// should compress image before enabling this feature
//
// Bitmap is for QVGA (320 x 240) screen.
// Skip first and last 20 lines (6400 pixels, 800 bytes)
//
	prog_uint8_t *pCode = SplashScreen;
	uint8 x, v;
	int y;			//needed for for loop
	pCode += 800;
	for (y = YEnd; y >= YStart; --y) {
		//OK to use WriteByte since horizontal offset X is always even.
		for (x = 0; x < (nColumnsPerLine / 2); x += 2) {
				v = __LPM(pCode++);
				WriteByte(v, (x / 2) + (columnOffset / 2), y);
		}
	}
	fStartClock = TRUE;	//TEST TODO
}

void Preset(void)
{
	Serial_In(CLEAR_SCR);		//clear Screen
	Serial_In(PRINT_STRING);	//String
  	Serial_In('R');
	Serial_In('e');
	Serial_In('a');
	Serial_In('d');
	Serial_In('y');
	Serial_In(0);
}

int main(void)
{
	unsigned long i = 0;
	uint8 inByte;
	MCUSR = 0;
	GPIOR0 = 0;
	InitCtrl();
	if (0 == UARTInit(BAUD_115200)) {
		FlashLed(10, 100);
	}

	fShowClock = FALSE;
	fStartClock = FALSE;
	fAutoClock = FALSE;
	TimeSecs = 0;
	TimeMins = 0;
	TimeHrs = 1;
	SetScreen(COLOROFF);		// sets BDATA
	PDATA = COLORON;
#if SPLASHSCREEN
	SetSplashScreen(0);
	SetSplashScreen(80);
#else
	Preset();		// text to lines 0..7 through SerialIn()
#endif
//
//	Enable Timer0 & Timer1 in Interrupt Mask
//
	EnableTC0();
	EnableTC1();
	sei();							//start interrupts -> screen refresh, serial in
	BlinkFast();
	UARTPrintfProgStr((prog_char*)StartStr1);

#if 0
	SetScreen(COLOROFF);		// sets BDATA
	PDATA = COLORON;
	DrawTable(DialData, FALSE);
	DrawTable(DialDigits12, FALSE);
	DrawSecsHand(TimeMins, FALSE);
	DrawMinsHand(TimeSecs, FALSE);
	DrawHrsHand(TimeHrs, FALSE);
#endif

	do {
		//
		// process queued graphic commands from SerialIn
		//
		while (UARTRXAvailable()) {
			inByte = UARTReceiveByte();
			if (fAutoClock) {
				StopClock();
			}
			Parse(inByte);
			NoActivityTimeout = NOACTIVITY;		// 1 minute
		}

		if (GlobalFault) {
			DebugL0(GlobalFault);
		}
		//
		// Signal when buffer is empty.
		if (++i == 0x4ffff) {
			FlashLed(1, 5);
			i = 0;
			ASSERT(GetMemUnused() > 25);
		}

		if (fStartClock &!fShowClock) {
			SetScreen(COLOROFF);		// sets BDATA
			PDATA = COLORON;
			SetSplashScreen(80);
			StartClock();
		}
		fStartClock = FALSE;

		if (SecsToAdd > 0) {
			UpdateTime();
		}
	} while (TRUE);
}


2.:



byte DialData[] PROGMEM = {
                0x64,0xc7,0x64,0xbe,0x00,0x6e,0xc7,0x6d,0xc2,0x00,0x78,0xc5,0x77,0xc0,0x00,0x82,0xc3,0x81,0xbe,0x00,
                0x8c,0xbf,0x8a,0xba,0x00,0x95,0xba,0x92,0xb4,0x00,0x9e,0xb5,0x9b,0xb1,0x00,0xa6,0xae,0xa2,0xaa,0x00,
                0xad,0xa7,0xa9,0xa3,0x00,0xb4,0x9f,0xb0,0x9c,0x00,0xb9,0x96,0xb3,0x92,0x00,0xbe,0x8d,0xb9,0x8b,0x00,
                0xc2,0x83,0xbd,0x82,0x00,0xc4,0x79,0xbf,0x78,0x00,0xc6,0x6f,0xc1,0x6e,0x00,0xc6,0x64,0xbd,0x64,0x00,
                0xc6,0x5a,0xc1,0x5b,0x00,0xc4,0x50,0xbf,0x51,0x00,0xc2,0x46,0xbd,0x47,0x00,0xbe,0x3c,0xb9,0x3e,0x00,
                0xb9,0x33,0xb3,0x36,0x00,0xb4,0x2a,0xb0,0x2d,0x00,0xad,0x22,0xa9,0x26,0x00,0xa6,0x1b,0xa2,0x1f,0x00,
                0x9e,0x14,0x9b,0x18,0x00,0x95,0x0f,0x92,0x15,0x00,0x8c,0x0a,0x8a,0x0f,0x00,0x82,0x06,0x81,0x0b,0x00,
                0x78,0x04,0x77,0x09,0x00,0x6e,0x02,0x6d,0x07,0x00,0x63,0x02,0x63,0x0b,0x00,0x59,0x02,0x5a,0x07,0x00,
                0x4f,0x04,0x50,0x09,0x00,0x45,0x06,0x46,0x0b,0x00,0x3b,0x0a,0x3d,0x0f,0x00,0x32,0x0f,0x36,0x15,0x00,
                0x29,0x14,0x2c,0x18,0x00,0x21,0x1b,0x25,0x1f,0x00,0x1a,0x22,0x1e,0x26,0x00,0x13,0x2a,0x17,0x2d,0x00,
                0x0e,0x33,0x14,0x37,0x00,0x09,0x3c,0x0e,0x3e,0x00,0x05,0x46,0x0a,0x47,0x00,0x03,0x50,0x08,0x51,0x00,
                0x01,0x5a,0x06,0x5b,0x00,0x01,0x65,0x0a,0x65,0x00,0x01,0x6f,0x06,0x6e,0x00,0x03,0x79,0x08,0x78,0x00,
                0x05,0x83,0x0a,0x82,0x00,0x09,0x8d,0x0e,0x8b,0x00,0x0e,0x96,0x14,0x92,0x00,0x13,0x9f,0x17,0x9c,0x00,
                0x1a,0xa7,0x1e,0xa3,0x00,0x21,0xae,0x25,0xaa,0x00,0x29,0xb5,0x2c,0xb1,0x00,0x32,0xba,0x35,0xb4,0x00,
                0x3b,0xbf,0x3d,0xba,0x00,0x45,0xc3,0x46,0xbe,0x00,0x4f,0xc5,0x50,0xc0,0x00,0x59,0xc7,0x5a,0xc2,0xff
};


byte DialDigits12[] PROGMEM = {
                0x5c,0xb9,0x5d,0xba,0x60,0xbc,0x60,0xab,0x00,0x64,0xb8,0x64,0xb9,0x65,0xba,0x66,0xbb,0x67,0xbc,0x6b,0xbc,0x6c,0xbb,0x6d,0xba,0x6e,0xb9,0x6e,0xb7,0x6d,0xb5,0x6b,0xb3,0x63,0xab,0x6f,0xab,0x00,
                0x88,0xae,0x89,0xaf,0x8c,0xb1,0x8c,0xa0,0x00,0x00,
                0xa5,0x95,0xa5,0x96,0xa6,0x97,0xa7,0x98,0xa8,0x99,0xac,0x99,0xad,0x98,0xae,0x97,0xaf,0x96,0xaf,0x94,0xae,0x92,0xac,0x90,0xa4,0x88,0xb0,0x88,0x00,0x00,
                0xb1,0x6e,0xba,0x6e,0xb5,0x67,0xb7,0x67,0xb9,0x67,0xba,0x66,0xbb,0x63,0xbb,0x62,0xba,0x5f,0xb8,0x5d,0xb6,0x5d,0xb3,0x5d,0xb1,0x5d,0xb0,0x5e,0xaf,0x60,0x00,0xac,0x46,0xa4,0x3a,0xb1,0x3a,0x00,0xac,0x46,0xac,0x35,0x00,0x00,
                0x90,0x28,0x88,0x28,0x87,0x21,0x88,0x21,0x8a,0x22,0x8d,0x22,0x8f,0x21,0x91,0x20,0x92,0x1d,0x92,0x1c,0x91,0x19,0x8f,0x17,0x8d,0x17,0x8a,0x17,0x88,0x17,0x87,0x18,0x86,0x1a,0x00,0x00,
                0x68,0x1d,0x67,0x1e,0x65,0x1f,0x63,0x1f,0x60,0x1e,0x5f,0x1c,0x5e,0x18,0x5e,0x13,0x5f,0x10,0x60,0x0e,0x63,0x0e,0x64,0x0e,0x66,0x0e,0x68,0x10,0x69,0x13,0x69,0x13,0x68,0x16,0x66,0x18,0x64,0x18,0x63,0x18,0x60,0x18,0x5f,0x16,0x5e,0x13,0x00,0x42,0x28,0x39,0x17,0x00,0x36,0x28,0x42,0x28,0x00,0x00,
                0x1b,0x46,0x19,0x45,0x18,0x44,0x18,0x42,0x19,0x40,0x1a,0x3f,0x1e,0x3f,0x20,0x3e,0x22,0x3c,0x23,0x3a,0x23,0x38,0x22,0x36,0x21,0x35,0x1f,0x35,0x1b,0x35,0x19,0x35,0x18,0x36,0x17,0x38,0x17,0x3a,0x18,0x3c,0x1a,0x3e,0x1c,0x3f,0x1f,0x3f,0x21,0x40,0x22,0x42,0x22,0x44,0x21,0x45,0x1f,0x46,0x1b,0x46,0x00,0x00,
                0x18,0x69,0x17,0x67,0x15,0x65,0x13,0x64,0x12,0x64,0x10,0x65,0x0e,0x67,0x0d,0x69,0x0d,0x6a,0x0e,0x6d,0x10,0x6e,0x12,0x6f,0x13,0x6f,0x15,0x6e,0x17,0x6d,0x18,0x69,0x18,0x65,0x17,0x61,0x15,0x5e,0x13,0x5e,0x11,0x5e,0x0f,0x5e,0x0e,0x60,0x00,0x00,
                0x19,0x96,0x1a,0x97,0x1d,0x99,0x1d,0x88,0x00,0x00,
                0x25,0x99,0x23,0x98,0x21,0x96,0x20,0x92,0x20,0x8f,0x21,0x8b,0x23,0x88,0x25,0x88,0x27,0x88,0x29,0x88,0x2b,0x8b,0x2c,0x8f,0x2c,0x92,0x2b,0x96,0x29,0x98,0x27,0x99,0x25,0x99,0x00,0x00,
                0x34,0xae,0x35,0xaf,0x38,0xb1,0x38,0xa0,0x00,0x00,
                0x3e,0xae,0x3f,0xaf,0x42,0xb1,0x42,0xa0,0xff,0x00
};

byte SecPtrData[] PROGMEM = {
                0x64,0xbe,0x64,0x64,0xff,0x6d,0xbe,0x64,0x64,0xff,0x76,0xbd,0x64,0x64,0xff,0x7f,0xba,0x64,0x64,0xff,
                0x88,0xb7,0x64,0x64,0xff,0x91,0xb2,0x64,0x64,0xff,0x98,0xad,0x64,0x64,0xff,0xa0,0xa7,0x64,0x64,0xff,
                0xa6,0xa1,0x64,0x64,0xff,0xac,0x99,0x64,0x64,0xff,0xb1,0x91,0x64,0x64,0xff,0xb6,0x89,0x64,0x64,0xff,
                0xb9,0x80,0x64,0x64,0xff,0xbc,0x77,0x64,0x64,0xff,0xbd,0x6e,0x64,0x64,0xff,0xbd,0x64,0x64,0x64,0xff,
                0xbd,0x5b,0x64,0x64,0xff,0xbc,0x52,0x64,0x64,0xff,0xb9,0x49,0x64,0x64,0xff,0xb6,0x40,0x64,0x64,0xff,
                0xb1,0x37,0x64,0x64,0xff,0xac,0x30,0x64,0x64,0xff,0xa6,0x28,0x64,0x64,0xff,0xa0,0x22,0x64,0x64,0xff,
                0x98,0x1c,0x64,0x64,0xff,0x91,0x17,0x64,0x64,0xff,0x88,0x12,0x64,0x64,0xff,0x7f,0x0f,0x64,0x64,0xff,
                0x76,0x0c,0x64,0x64,0xff,0x6d,0x0b,0x64,0x64,0xff,0x64,0x0b,0x64,0x64,0xff,0x5a,0x0b,0x64,0x64,0xff,
                0x51,0x0c,0x64,0x64,0xff,0x48,0x0f,0x64,0x64,0xff,0x3f,0x12,0x64,0x64,0xff,0x37,0x17,0x64,0x64,0xff,
                0x2f,0x1c,0x64,0x64,0xff,0x27,0x22,0x64,0x64,0xff,0x21,0x28,0x64,0x64,0xff,0x1b,0x30,0x64,0x64,0xff,
                0x16,0x38,0x64,0x64,0xff,0x11,0x40,0x64,0x64,0xff,0x0e,0x49,0x64,0x64,0xff,0x0b,0x52,0x64,0x64,0xff,
                0x0a,0x5b,0x64,0x64,0xff,0x0a,0x64,0x64,0x64,0xff,0x0a,0x6e,0x64,0x64,0xff,0x0b,0x77,0x64,0x64,0xff,
                0x0e,0x80,0x64,0x64,0xff,0x11,0x89,0x64,0x64,0xff,0x16,0x91,0x64,0x64,0xff,0x1b,0x99,0x64,0x64,0xff,
                0x21,0xa1,0x64,0x64,0xff,0x27,0xa7,0x64,0x64,0xff,0x2f,0xad,0x64,0x64,0xff,0x36,0xb2,0x64,0x64,0xff,
                0x3f,0xb7,0x64,0x64,0xff,0x48,0xba,0x64,0x64,0xff,0x51,0xbd,0x64,0x64,0xff,0x5a,0xbe,0x64,0x64,0xff

};
byte MinPtrData[] PROGMEM = {
                0x66,0x64,0x64,0xb4,0x62,0x64,0x66,0x64,0xff,0x65,0x64,0x6c,0xb4,0x62,0x65,0x65,0x64,0xff,
                0x65,0x64,0x74,0xb3,0x62,0x65,0x65,0x64,0xff,0x65,0x64,0x7c,0xb1,0x62,0x65,0x65,0x64,0xff,
                0x65,0x64,0x84,0xae,0x62,0x65,0x65,0x64,0xff,0x65,0x63,0x8c,0xaa,0x62,0x66,0x65,0x63,0xff,
                0x65,0x63,0x93,0xa5,0x62,0x66,0x65,0x63,0xff,0x65,0x63,0x99,0xa0,0x62,0x66,0x65,0x63,0xff,
                0x65,0x63,0x9f,0x9a,0x62,0x66,0x65,0x63,0xff,0x65,0x63,0xa4,0x94,0x62,0x66,0x65,0x63,0xff,
                0x64,0x63,0xa9,0x8c,0x63,0x66,0x64,0x63,0xff,0x64,0x63,0xad,0x85,0x63,0x66,0x64,0x63,0xff,
                0x64,0x63,0xb0,0x7d,0x63,0x66,0x64,0x63,0xff,0x64,0x63,0xb2,0x75,0x63,0x66,0x64,0x63,0xff,
                0x64,0x63,0xb3,0x6d,0x63,0x66,0x64,0x63,0xff,0x63,0x62,0xb3,0x64,0x64,0x66,0x63,0x62,0xff,
                0x63,0x63,0xb3,0x5c,0x64,0x66,0x63,0x63,0xff,0x63,0x63,0xb2,0x54,0x64,0x66,0x63,0x63,0xff,
                0x63,0x63,0xb0,0x4c,0x64,0x66,0x63,0x63,0xff,0x63,0x63,0xad,0x44,0x64,0x66,0x63,0x63,0xff,
                0x62,0x63,0xa9,0x3c,0x65,0x66,0x62,0x63,0xff,0x62,0x63,0xa4,0x35,0x65,0x66,0x62,0x63,0xff,
                0x62,0x63,0x9f,0x2f,0x65,0x66,0x62,0x63,0xff,0x62,0x63,0x99,0x29,0x65,0x66,0x62,0x63,0xff,
                0x62,0x63,0x93,0x24,0x65,0x66,0x62,0x63,0xff,0x62,0x63,0x8c,0x1f,0x65,0x66,0x62,0x63,0xff,
                0x62,0x64,0x84,0x1b,0x65,0x65,0x62,0x64,0xff,0x62,0x64,0x7c,0x18,0x65,0x65,0x62,0x64,0xff,
                0x62,0x64,0x74,0x16,0x65,0x65,0x62,0x64,0xff,0x62,0x64,0x6c,0x15,0x65,0x65,0x62,0x64,0xff,
                0x62,0x65,0x63,0x15,0x65,0x64,0x62,0x65,0xff,0x62,0x65,0x5b,0x15,0x65,0x64,0x62,0x65,0xff,
                0x62,0x65,0x53,0x16,0x65,0x64,0x62,0x65,0xff,0x62,0x65,0x4b,0x18,0x65,0x64,0x62,0x65,0xff,
                0x62,0x65,0x43,0x1b,0x65,0x64,0x62,0x65,0xff,0x62,0x65,0x3c,0x1f,0x65,0x64,0x62,0x65,0xff,
                0x62,0x66,0x34,0x24,0x65,0x63,0x62,0x66,0xff,0x62,0x66,0x2e,0x29,0x65,0x63,0x62,0x66,0xff,
                0x62,0x66,0x28,0x2f,0x65,0x63,0x62,0x66,0xff,0x62,0x66,0x23,0x35,0x65,0x63,0x62,0x66,0xff,
                0x63,0x66,0x1e,0x3d,0x64,0x63,0x63,0x66,0xff,0x63,0x66,0x1a,0x44,0x64,0x63,0x63,0x66,0xff,
                0x63,0x66,0x17,0x4c,0x64,0x63,0x63,0x66,0xff,0x63,0x66,0x15,0x54,0x64,0x63,0x63,0x66,0xff,
                0x63,0x66,0x14,0x5c,0x64,0x63,0x63,0x66,0xff,0x64,0x66,0x14,0x65,0x63,0x62,0x64,0x66,0xff,
                0x64,0x66,0x14,0x6d,0x63,0x63,0x64,0x66,0xff,0x64,0x66,0x15,0x75,0x63,0x63,0x64,0x66,0xff,
                0x64,0x66,0x17,0x7d,0x63,0x63,0x64,0x66,0xff,0x64,0x66,0x1a,0x85,0x63,0x63,0x64,0x66,0xff,
                0x64,0x66,0x1e,0x8c,0x63,0x63,0x64,0x66,0xff,0x65,0x66,0x23,0x94,0x62,0x63,0x65,0x66,0xff,
                0x65,0x66,0x28,0x9a,0x62,0x63,0x65,0x66,0xff,0x65,0x66,0x2e,0xa0,0x62,0x63,0x65,0x66,0xff,
                0x65,0x66,0x34,0xa5,0x62,0x63,0x65,0x66,0xff,0x65,0x66,0x3b,0xaa,0x62,0x63,0x65,0x66,0xff,
                0x65,0x65,0x43,0xae,0x62,0x64,0x65,0x65,0xff,0x65,0x65,0x4b,0xb1,0x62,0x64,0x65,0x65,0xff,
                0x65,0x65,0x53,0xb3,0x62,0x64,0x65,0x65,0xff,0x65,0x65,0x5b,0xb4,0x62,0x64,0x65,0x65,0xff

};
byte HrPtrData[] PROGMEM = {
                0x66,0x64,0x64,0x9b,0x62,0x64,0x66,0x64,0xff,0x65,0x64,0x69,0x9b,0x62,0x65,0x65,0x64,0xff,
                0x65,0x64,0x6f,0x9a,0x62,0x65,0x65,0x64,0xff,0x65,0x64,0x74,0x99,0x62,0x65,0x65,0x64,0xff,
                0x65,0x64,0x7a,0x97,0x62,0x65,0x65,0x64,0xff,0x65,0x63,0x7f,0x94,0x62,0x66,0x65,0x63,0xff,
                0x65,0x63,0x84,0x91,0x62,0x66,0x65,0x63,0xff,0x65,0x63,0x88,0x8d,0x62,0x66,0x65,0x63,0xff,
                0x65,0x63,0x8c,0x89,0x62,0x66,0x65,0x63,0xff,0x65,0x63,0x90,0x85,0x62,0x66,0x65,0x63,0xff,
                0x64,0x63,0x93,0x80,0x63,0x66,0x64,0x63,0xff,0x64,0x63,0x96,0x7b,0x63,0x66,0x64,0x63,0xff,
                0x64,0x63,0x98,0x75,0x63,0x66,0x64,0x63,0xff,0x64,0x63,0x99,0x70,0x63,0x66,0x64,0x63,0xff,
                0x64,0x63,0x9a,0x6a,0x63,0x66,0x64,0x63,0xff,0x63,0x62,0x9a,0x64,0x64,0x66,0x63,0x62,0xff,
                0x63,0x63,0x9a,0x5f,0x64,0x66,0x63,0x63,0xff,0x63,0x63,0x99,0x59,0x64,0x66,0x63,0x63,0xff,
                0x63,0x63,0x98,0x54,0x64,0x66,0x63,0x63,0xff,0x63,0x63,0x96,0x4e,0x64,0x66,0x63,0x63,0xff,
                0x62,0x63,0x93,0x49,0x65,0x66,0x62,0x63,0xff,0x62,0x63,0x90,0x44,0x65,0x66,0x62,0x63,0xff,
                0x62,0x63,0x8c,0x40,0x65,0x66,0x62,0x63,0xff,0x62,0x63,0x88,0x3c,0x65,0x66,0x62,0x63,0xff,
                0x62,0x63,0x84,0x38,0x65,0x66,0x62,0x63,0xff,0x62,0x63,0x7f,0x35,0x65,0x66,0x62,0x63,0xff,
                0x62,0x64,0x7a,0x32,0x65,0x65,0x62,0x64,0xff,0x62,0x64,0x74,0x30,0x65,0x65,0x62,0x64,0xff,
                0x62,0x64,0x6f,0x2f,0x65,0x65,0x62,0x64,0xff,0x62,0x64,0x69,0x2e,0x65,0x65,0x62,0x64,0xff,
                0x62,0x65,0x63,0x2e,0x65,0x64,0x62,0x65,0xff,0x62,0x65,0x5e,0x2e,0x65,0x64,0x62,0x65,0xff,
                0x62,0x65,0x58,0x2f,0x65,0x64,0x62,0x65,0xff,0x62,0x65,0x53,0x30,0x65,0x64,0x62,0x65,0xff,
                0x62,0x65,0x4d,0x32,0x65,0x64,0x62,0x65,0xff,0x62,0x65,0x48,0x35,0x65,0x64,0x62,0x65,0xff,
                0x62,0x66,0x43,0x38,0x65,0x63,0x62,0x66,0xff,0x62,0x66,0x3f,0x3c,0x65,0x63,0x62,0x66,0xff,
                0x62,0x66,0x3b,0x40,0x65,0x63,0x62,0x66,0xff,0x62,0x66,0x37,0x44,0x65,0x63,0x62,0x66,0xff,
                0x63,0x66,0x34,0x49,0x64,0x63,0x63,0x66,0xff,0x63,0x66,0x31,0x4e,0x64,0x63,0x63,0x66,0xff,
                0x63,0x66,0x2f,0x54,0x64,0x63,0x63,0x66,0xff,0x63,0x66,0x2e,0x59,0x64,0x63,0x63,0x66,0xff,
                0x63,0x66,0x2d,0x5f,0x64,0x63,0x63,0x66,0xff,0x64,0x66,0x2d,0x65,0x63,0x62,0x64,0x66,0xff,
                0x64,0x66,0x2d,0x6a,0x63,0x63,0x64,0x66,0xff,0x64,0x66,0x2e,0x70,0x63,0x63,0x64,0x66,0xff,
                0x64,0x66,0x2f,0x75,0x63,0x63,0x64,0x66,0xff,0x64,0x66,0x31,0x7b,0x63,0x63,0x64,0x66,0xff,
                0x64,0x66,0x34,0x80,0x63,0x63,0x64,0x66,0xff,0x65,0x66,0x37,0x85,0x62,0x63,0x65,0x66,0xff,
                0x65,0x66,0x3b,0x89,0x62,0x63,0x65,0x66,0xff,0x65,0x66,0x3f,0x8d,0x62,0x63,0x65,0x66,0xff,
                0x65,0x66,0x43,0x91,0x62,0x63,0x65,0x66,0xff,0x65,0x66,0x48,0x94,0x62,0x63,0x65,0x66,0xff,
                0x65,0x65,0x4d,0x97,0x62,0x64,0x65,0x65,0xff,0x65,0x65,0x53,0x99,0x62,0x64,0x65,0x65,0xff,
                0x65,0x65,0x58,0x9a,0x62,0x64,0x65,0x65,0xff,0x65,0x65,0x5e,0x9b,0x62,0x64,0x65,0x65,0xff

};


3.:


#include "./avr.inc"
#include <avr/io.h>
#include <avr/portpins.h>

#include "Configuracja.h"  

	.extern TextPage
	.extern Font8x8

//-- map the IO register back into the IO address space
#define PA_DDR		(_SFR_IO_ADDR(PORTA) - 1)
#define PB_DDR		(_SFR_IO_ADDR(PORTB) - 1)
#define PC_DDR		(_SFR_IO_ADDR(PORTC) - 1)
#define PD_DDR		(_SFR_IO_ADDR(PORTD) - 1)
#define PA_OUT		_SFR_IO_ADDR(PORTA)
#define PB_OUT		_SFR_IO_ADDR(PORTB)
#define PC_OUT		_SFR_IO_ADDR(PORTC)
#define PD_OUT		_SFR_IO_ADDR(PORTD)
#define PA_IN		(_SFR_IO_ADDR(PORTA) - 2)
#define PB_IN		(_SFR_IO_ADDR(PORTB) - 2)
#define PC_IN		(_SFR_IO_ADDR(PORTC) - 2)
#define PD_IN		(_SFR_IO_ADDR(PORTD) - 2)

//
// GENERAL DEFINITIONS
//
// Vx is a memory nibble address, not a pixel address
// Vy is line number (pixel and memory values are identical)
//
// PB0..PD3 connected to D0..D3 (nibble data)
//
#define	SRAMDATAI	PB_IN
#define	SRAMDATAO	PB_OUT
#define	SRAMDATA_DDR PB_DDR
//
// PD2 connected to YSCL
//
#define	LCD_YSCL	PD_OUT,YSCL_BIT
#define	YSCL_DDR	PD_DDR,YSCL_BIT
//
// PD3 connected to M (AC) Line
//
#define	M_DDR		PD_DDR,3
#define	LCD_MTOGGLE	PD_IN,M_BIT
//
// PD4 connected to LCD Enable
//
#define	LCD_ENABLE	PD_OUT,ENABLE_BIT
#define	ENABLE_DDR	PD_DDR,ENABLE_BIT
//
// PD5 connected to LCD HSYNC (LP)
//
#define	LCD_HSYNC	PD_OUT,HSYNC_BIT
#define	HSYNC_DDR	PD_DDR,HSYNC_BIT
//
// PD6 connected to LCD VSYNC (SF)
//
#define	LCD_VSYNC	PD_OUT,VSYNC_BIT
#define	VSYNC_DDR	PD_DDR,VSYNC_BIT
//
// PD7 connected to software DOTCLOCK (XSCL)
//
#define	DOTCLK		PD_OUT,DOTCLK_BIT
#define	DOTCLK_PORT	PD_OUT
#define	DOTCLK_DDR	PD_DDR,DOTCLK_BIT
//
// PC0 connected to MCU_TEST bit
//
#define MCU_TEST	PC_OUT,MCU_TEST_BIT
#define MCU_TEST_DDR	DDRC,MCU_TEST_BIT
//
// PC1 connected to LCD ECL
//
#define	LCD_ECL		PC_OUT,ECL_BIT
#define	ECLDDR		PC_DDR,ECL_BIT
//
// PA0 connected to LED
//
#define	LEDI		PA_IN,0
#define	LEDO		PA_OUT,0
#define	LED_DDR		PA_DDR,0
//
// PA1 connected to LED2
//
#define	LED2I		PA_IN,1
#define	LED2O		PA_OUT,1
#define	LED2_DDR	PA_DDR,1

#define COLORWHITE	0b00000001
#define COLORBLACK	0b00000000

#define BITSPERPIXEL	1
#define DATABITS		4

.section	.text

#define	PORTDCLKOFF		r21
#define	PORTDCLKON		r20

        .global TIMER0_COMPA_vect
//
// Assume non-data pins in PORTB are input
//
	.macro	UpdateColumns
	ld		r16,Z+
	swap	r16				;ldata >> 4
	out		DOTCLK_PORT,PORTDCLKON			; sbi	DOTCLK
	out		SRAMDATAO,r16
	out		DOTCLK_PORT,PORTDCLKOFF			; cbi	DOTCLK
	swap	r16				;ldata << 4
	out		DOTCLK_PORT,PORTDCLKON			; sbi	DOTCLK
	out		SRAMDATAO,r16
	out		DOTCLK_PORT,PORTDCLKOFF			; cbi	DOTCLK
	.endm
//

//
// Executed every 198.4 uSec (5,000 Hz).
//
// Refreshes one display line.
// 100 lines -> 50 Screen refreshes / second
//
TIMER0_COMPA_vect:
	push	r16
	in		r16, _SFR_IO_ADDR(SREG)
	push	r16
#if 0
Not needed when running in CTC mode
	clr		r16
	sts		TCNT0,r16
#endif
	push	ZL
	push	ZH
	push	r18
	push	r19
	push	PORTDCLKOFF
	push	PORTDCLKON
	push	r0
	push	r1
#if DEBUG
	sbi		MCU_TEST
#endif
//
// get the line we're refreshing. Compute data ptr.
// todo: times 160 => times 128 + times 32
//
	lds		r19,RefreshLine			// Y
	ldi		r16,160					//160 bytes per line
	mul		r19,r16
	movw	ZL,r0
	eor		r1,r1
	subi	ZL,lo8(-(FrameBuffer))
	sbci	ZH,hi8(-(FrameBuffer))
//
//	Allow interrupts again (process Serial In while doing refresh)
//
	sei
//
	ldi		r18,20						//1180 count
#if 1
	tst		r19							//RefreshLine
	brne	1f
	sbi		LCD_VSYNC					//start VSYNC 
1:
#endif
//
// preload the clock toggle registers
//
	in		PORTDCLKOFF,DOTCLK_PORT
	mov		PORTDCLKON,PORTDCLKOFF
	sbr		PORTDCLKON,_BV(DOTCLK_BIT)	//DotClk On
SED1180Loop:
	UpdateColumns
	UpdateColumns
	UpdateColumns
	UpdateColumns
	UpdateColumns
	UpdateColumns
	UpdateColumns
	UpdateColumns
//
// Transfer the 1180 to the next 1180
//
	sbi	LCD_ECL
	cbi	LCD_ECL	
//
// Loop until all 20 1180s had their turn
//
	dec		r18
	breq	1f
	rjmp	SED1180Loop
1:
//
// Horizontal Sync.
//
	sbi		LCD_ECL				//needed!!
	sbi		LCD_YSCL
	sbi		LCD_HSYNC
	cbi		LCD_ECL				//PORTC!
#if 0
	tst		r19					//RefreshLine
	brne	1f
	sbi		LCD_VSYNC			//start VSYNC 
1:
#endif
	cbi		LCD_YSCL			//exact sequence is essential
	cbi		LCD_HSYNC
	cbi		LCD_VSYNC			//stop VSYNC

//
// Update Line Address
//
	inc		r19
	cpi		r19,PHYS_LINES
;	brsh	DoLCD_LastLine
;	rjmp	RefreshExit			//done
	brlo	RefreshExit

DoLCD_LastLine:
//
//toggle AC line
//
	sbi		LCD_MTOGGLE
//
// start new frame
//
	clr		r19
//
// Enable display after 3 frames
//
	lds		r16,pwrup_state
	cpi		r16,3
	brsh	Turn_On_LCDX
	inc 	r16
	sts		pwrup_state,r16
	rjmp	RefreshExit
Turn_On_LCDX:
	sbi		LCD_ENABLE
RefreshExit:
	sts		RefreshLine,r19
#if DEBUG
	cbi		MCU_TEST
#endif
	pop		r1
	pop		r0
	pop		PORTDCLKON
	pop		PORTDCLKOFF
	pop		r19
	pop		r18
	pop		ZH
	pop		ZL
Tdone:
	pop		r16
	out		_SFR_IO_ADDR(SREG),r16
	pop		r16
	reti

#undef	PORTDCLKOFF
#undef	PORTDCLKON

	.global	InitMem

#define	RAMSTART 0x0100

InitMem:
	push	r18
	push	r20
	push	r21
	push	ZL
	push	ZH
	in		r20,_SFR_IO_ADDR(SPL)					;top
	in		r21,_SFR_IO_ADDR(SPH)
	
	ldi		r18,0xcc
;	ldiw	Z,RAMSTART			;Preset RAM
	ldiw	Z,__heap_start
1:
	st		Z+,r18
	cp		ZL,r20
	cpc		ZH,r21
	brne	1b
	pop		ZH
	pop		ZL
	pop		r21
	pop		r20
	pop		r18
	ret



//## -------------------  FONTS & BITMAPS   
	.global	Font8x8
	.global	Font8x8End

#include ".\Font8x8.inc"

Font8x8End:
	.align

#if 0
	.global	DialData
	.global DialDigits
	.global SecPtrData
	.global MinPtrData
	.global HrPtrData

#include "./EpsonClk.inc"
#endif
	.align

#if SPLASHSCREEN
#include ".\RoseBM.inc"

	.global	SplashScreen
#endif

	.align
Igy esetleg lehet vele valamit kezdeni?
lcd sharp_1.jpg

Admin: a következő 4 oldalas kódbeszúrásért CODE gomb nélkül fenékbebillentés jár!
Nincs meg a kellő jogosultságod a hozzászóláshoz csatolt állományok megtekintéséhez.
A microkontroler sok mindenre alkalmas. a Pc bármire amire meg tudod tanítani.
Avatar
Robert
Elektronbűvölő
Hozzászólások: 10191
Csatlakozott: 2005. december 9. péntek, 7:00

Re: sharp LM085YB01T01 kijelző vezérlése.

Hozzászólás Szerző: Robert »

Ha van üres 10....30 órád, nyugodtan.
- A kód ATMega1284re készült (Nem Arduino támogatott chip)
- C nyelven (Nem Arduino)

Amúgy a Nextion Touch kijelzője 800x480 (5") felbontás, touch támogatásal: ~60$ -> 18 eFt.
Ha a kijelződ tudna minimum ennyit, akkor a Nextion árat oszd le 30 órára: 600 Ft órabér. És van egy olyan kijelződ amibe minimum 100 órát még bele kellene tolnod és ha meghibásodik, nem pótolható.
Gazdaságilag NEM éri meg.
Én inkább tanulnék valami rentábilisabbat:) .
http://www.tavir.hu - a gazda :)
Bearnie74
DrótVégénSzéndarab
Hozzászólások: 34
Csatlakozott: 2016. november 25. péntek, 7:10

Re: sharp LM085YB01T01 kijelző vezérlése.

Hozzászólás Szerző: Bearnie74 »

Ezt a kijelzőt 10.000 ért vesztegetik újonnan, és a céljaimnak tökéletesen megfelel, főleg hogy a hozzá való tapi sem több 1500 Ft nál.
A microkontroler sok mindenre alkalmas. a Pc bármire amire meg tudod tanítani.
Válasz küldése