#include "stdio.h"
#include <mbed.h>
#include <rtos.h>
#include "display.h"


Display::Display(int Hz, PinName mosi, PinName miso, PinName sclk, PinName CS, PinName reset, PinName DC,
				 const char* name)
		: SSD1322(Hz, mosi, miso, sclk, CS, reset, DC, name)
{
	must_refresh = 0;
}

Display::~Display()
{
}

void Display::show_splashscreen()
{
	locate(30, 10);
	set_font((unsigned char*)Mono19x27);
	this->printf("HP34970A");
	set_font((unsigned char*)Terminal6x8);
	locate(90, 40);
	this->printf("David Douard");
	locate(0, 52);
	this->printf("Clock = %ld ", SystemCoreClock);

	RCC_OscInitTypeDef cfg;
	HAL_RCC_GetOscConfig(&cfg);
	if (cfg.HSEState == RCC_HSE_BYPASS)
		this->printf("HSE:EXT ");
	else if (cfg.HSEState == RCC_HSE_ON)
		this->printf("HSE:XTAL ");
	else
		this->printf("HSE:OFF ");

	if (cfg.HSIState == RCC_HSI_ON)
		this->printf("HSI:ON ");
	else
		this->printf("HSI:OFF ");

	copy_to_lcd();
}


void Display::show(uint8_t cmd, const char *intxt, uint8_t nchar=0)
{
	uint8_t i;
	// uint8_t len;
	uint16_t bgcolor, fgcolor;
	char *oldv;
	// char *txt;
	char *txtp;
	static char txt[256];


	if (cmd == 0xFF) // cls
	{
		clrbuff();
	}
	else
	{
		//txt = (char *)malloc(strlen(intxt)+1);
		strcpy(txt, intxt);
		txtp = txt;

		for (i=0; i<sizeof(table)/sizeof(table[0]); ++i) {
			if (table[i].cmd == cmd) {
				bgcolor = table[i].bgcolor;
				fgcolor = table[i].color;
				background(bgcolor);
				foreground(fgcolor);
				set_font((unsigned char*) table[i].font);
				oldv = table[i].buffer;

				locate(table[i].x0, table[i].y0);

				if (table[i].fmt & 0x01)  // ASCII text
				{
					if (strncmp(oldv, txt, table[i].maxsize) != 0)
					{
						if (table[i].width > 0)
							fillrect(table[i].x0,
														table[i].y0,
														table[i].x0 + table[i].width,
														table[i].y0 + table[i].font[2],
														bgcolor);
						for (uint8_t k=0; ;k++)
						{
							if (txtp[k] == 0x00)
							{
								this->printf(txtp);
								break;
							}
							if (txtp[k] == 0x09)
							{ // \t is a special char for 'unselected' display value
								txtp[k] = 0x00;
								this->printf(txtp);

								if (fgcolor == table[i].color)
									fgcolor /= 2;
								else
									fgcolor = table[i].color;
								foreground(fgcolor);
								txtp = &(txtp[k+1]);
								k = 0;
							}
						}
						if (cmd == 0x00) // main area
							must_refresh |= 0x01;
						if (cmd == 0x0C) // channels area
							must_refresh |= 0x04;
					}
				}
				/*
					if (table[i].fmt & 0x02 ) {
					// hex
					for (uint8_t j=0;; j++) {
					if (txt[j] == 0x00)
					break;
					this->printf("%02X ", txt[j]);
					}
					for (uint8_t j=3*strlen(txt); j<table[i].maxsize; j++)
					this->printf(" ");
					}
				*/
				if (table[i].fmt & 0x08 )  // flag indicators
				{
					// flags
					for (uint8_t j=0; j<max(nchar, table[i].maxsize) ; j++)
					{
						for (uint8_t k=0; k<8; k++)
						{
							if (1)
							{ //(txt[j] & (1 << k) ) != (oldv[j] & (1 << k))) {
								for (uint8_t l=0;
										 l<(sizeof(flags)/sizeof(flags[0])); ++l)
								{
									if (flags[l].flag == ((j<<4) + k)) {
										if (txtp[j] & (1 << k))
										{
											foreground(flags[l].reverse ? bgcolor : fgcolor);
											background(flags[l].reverse ? fgcolor : bgcolor);
										}
										else
										{
											foreground(bgcolor);
											background(bgcolor);
										}
										if (flags[l].msg != NULL)
										{ // a string
											locate(flags[l].x, flags[l].y);
											this->printf(flags[l].msg);}
										else
										{ // an icon
											Bitmap_s pic = {9, 10, 2, (char*) flags[l].icon};
											Bitmap_BW(pic, flags[l].x, flags[l].y);
										}
										must_refresh = 1; //|= zones[m].flag;
										break;
									}
								}
							}
						}
					}

					// draw frames (Alarm and Channel)
					for (uint8_t l=0;
							 l<(sizeof(frames)/sizeof(frames[0])); ++l)
					{
						uint16_t color;
						if (frames[l].flag & txt[0]) // frame flags are on the 1st byte only
							color = fgcolor/6;
						else
							color = bgcolor;
						hline(frames[l].x0+1, frames[l].x0+3, frames[l].y0, color);
						hline(frames[l].x1-3, frames[l].x1-1, frames[l].y0, color);
						hline(frames[l].x0+1, frames[l].x1-1, frames[l].y1, color);

						vline(frames[l].x0, frames[l].y0+1, frames[l].y1-1, color);
						vline(frames[l].x1, frames[l].y0+1, frames[l].y1-1, color);
					}
				}

				for(uint8_t j=0; j<table[i].maxsize; j++)
					oldv[j] = txt[j];
				break;
			}
		}
		//free(txt);
		//this->copy_to_lcd();
	}
}


void Display::test_dsp()
{
	const FRAME *z;
	printf("TEST DSP\r\n");
	cls();
	printf("TEST DSP #2\r\n");
	show(0x00, "8g8g8g8g8g8g8", 13); // main dsp
	show(0x0C, "888", 3); // channel dsp
	show(0x0A, "\xFF\xFF\xFF\xFF", 4); // all flags
	copy_to_lcd();
	ThisThread::sleep_for(3ms);
	cls();
	printf("TEST DSP #3\r\n");

	for (uint8_t i=0; i<(sizeof(zones)/sizeof(zones[0])); i++)
	{
		z = &zones[i];
		fillrect(z->x0, z->y0, z->x1, z->y1, 4+i);
		locate(z->x0+1, z->y0+1);
		this->printf("%d", i);
	}

	/*
		for (uint8_t i=0; i<(sizeof(zones)/sizeof(zones[0])); i++)
		{
		z = &zones[i];
		printf("Zone %d [%x]: %d, %d, %d, %d\n", i, z->flag,
		z->x0, z->y0, z->x1, z->y1);
		must_refresh = z->flag;
		wait(1);
		}
		printf("Done\n");
		wait(2);
		printf("Copy ALL\n");
		copy_to_lcd();
	*/
	ThisThread::sleep_for(2ms);
	cls();
	printf("TEST DSP DONE\r\n");
}
