/*
** lcd.h
**
** LCD 3310 driver
** Target: ATMEGA :: AVR-GCC
**
** Written by Tony Myatt - 2007
** Quantum Torque - www.quantumtorque.com
*/
#ifndef _LCD_GFX_H_
#define _LCD_GFX_H_

//
// C++ compatibility
//
#ifdef __cplusplus
extern "C" {
#endif

#include "common.h"

#if defined (__AVR_ATxmega128A1U__)

#include <util/delay.h>
#include "module/ff.h"
#include "module/diskio.h"
#include "xmega/spi_driver.h"

#include <avr/io.h>
#include "module/Font.h"
#include <stdio.h>

#include "fonts/ft10x20.h"
//#include "fonts/ft14x25.h"
//#include "fonts/ft18x34.h"
//#include "fonts/f20x19.h"
//#include "fonts/fn21x55.h"
//#include "fonts/fn31x45.h"
#define FONT_SELECTED ft10x20

/* _____PUBLIC VARIABLE_____________________________________________________ */

uint8_t madctl;
extern uint8_t  volatile data_ready;

#define LCD_CS	0
#define LCD_RS	1
#define LCD_RST 2
#define LCD_BL	3
#define LCD_SDA	5
#define LCD_SCL 7

//Control RS input of LCD
#define LCD_DRAM()				PORTK.OUTSET |= (1<<LCD_RS)
#define LCD_CMD()				PORTK.OUTCLR = (1<<LCD_RS)

//Control reset input of LCD
#define LCD_RESET_OFF()			PORTK.OUTSET |= (1<<LCD_RST)
#define LCD_RESET_ON()			PORTK.OUTCLR = (1<<LCD_RST)
#define LCD_RESET()				LCD_RESET_ON();  _delay_ms(100); LCD_RESET_OFF()

//Control CS input of LCD
#define LCD_SELECT()			PORTK.OUTCLR = (1<<LCD_CS)
#define LCD_UNSELECT()			PORTK.OUTSET |= (1<<LCD_CS)

#define swap(a, b) { uint16_t t = a; a = b; b = t; }

#define ST7735_NOP		0x0
#define ST7735_SWRESET	0x01
#define ST7735_RDDID	0x04
#define ST7735_RDDST	0x09

#define ST7735_SLPIN	0x10
#define ST7735_SLPOUT	0x11
#define ST7735_PTLON	0x12
#define ST7735_NORON	0x13

#define ST7735_INVOFF	0x20
#define ST7735_INVON	0x21
#define ST7735_DISPOFF	0x28
#define ST7735_DISPON	0x29
#define ST7735_CASET	0x2A
#define ST7735_RASET	0x2B
#define ST7735_RAMWR	0x2C
#define ST7735_RAMRD	0x2E

#define ST7735_COLMOD	0x3A
#define ST7735_MADCTL	0x36

#define ST7735_FRMCTR1	0xB1
#define ST7735_FRMCTR2	0xB2
#define ST7735_FRMCTR3	0xB3
#define ST7735_INVCTR	0xB4
#define ST7735_DISSET5	0xB6

#define ST7735_PWCTR1	0xC0
#define ST7735_PWCTR2	0xC1
#define ST7735_PWCTR3	0xC2
#define ST7735_PWCTR4	0xC3
#define ST7735_PWCTR5	0xC4
#define ST7735_VMCTR1	0xC5

#define ST7735_RDID1	0xDA
#define ST7735_RDID2	0xDB
#define ST7735_RDID3	0xDC
#define ST7735_RDID4	0xDD

#define ST7735_PWCTR6	0xFC

#define ST7735_GMCTRP1	0xE0
#define ST7735_GMCTRN1	0xE1

// color
#define BLACK           RGB(0x00, 0x00, 0x00)
#define WHITE           RGB(0xFF, 0xFF, 0xFF)
#define RED             RGB(0xFF, 0x00, 0x00)
#define GREEN           RGB(0x00, 0xFF, 0x00)
#define BLUE            RGB(0x00, 0x00, 0xFF)
#define YELLOW          RGB(0xFF, 0xFF, 0x00)
#define MAGENTA         RGB(0xFF, 0x00, 0xFF)
#define CYAN            RGB(0x00, 0xFF, 0xFF)
#define GRAY            RGB(0x80, 0x80, 0x40)
#define SILVER          RGB(0xA0, 0xA0, 0x80)
#define GOLD            RGB(0xA0, 0xA0, 0x40)

#define MAX_X				128
#define MAX_Y				160

// Horizontal and vertical screen size
#define SCREEN_HOR_SIZE    128UL
#define SCREEN_VER_SIZE    160UL

#define GetMaxX() 		((unsigned int)SCREEN_HOR_SIZE-1)
#define GetMaxY() 		((unsigned int)SCREEN_VER_SIZE-1)

#define RGB(red, green, blue)	((unsigned int)( (( blue >> 3 ) << 11 ) | \
                                 (( green >> 2 ) << 5  ) | \
                                 ( red  >> 3 )))
// Pass 8-bit (each) R,G,B, get back 16-bit packed color
inline uint16_t Color565(uint8_t b, uint8_t g, uint8_t r);
inline uint16_t Color565(uint8_t b, uint8_t g, uint8_t r)
{
    return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
}

void spi_write(uint8_t);
void lcd_gfx_init(void);
void lcd_gfx_write_string(char *c);
void lcd_gfx_write_char(char c);
void lcd_gfx_clear();
void lcd_gfx_drawPixel(uint8_t x, uint8_t y);
void lcd_gfx_drawPixel_h(uint8_t x, uint8_t y);
void lcd_gfx_drawLine(int16_t x, int16_t y, int16_t x1, int16_t y1, uint16_t color);
void lcd_gfx_fillScreen(uint16_t color);
void lcd_gfx_drawVerticalLine(uint8_t x0, uint8_t y0, uint8_t length, uint16_t color);
void lcd_gfx_drawHorizontalLine(uint8_t x0, uint8_t y0,uint8_t length, uint16_t color);
void lcd_gfx_drawFastLine(uint8_t x0, uint8_t y0, uint8_t l, uint16_t color, uint8_t flag);
void lcd_gfx_drawRect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint16_t color);
void lcd_gfx_fillRect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint16_t color);
void lcd_gfx_drawCircle(uint8_t x0, uint8_t y0, uint8_t r, uint16_t color);
void lcd_gfx_fillCircle(uint8_t x0, uint8_t y0, uint8_t r, uint16_t color);
void lcd_gfx_backlight(uint8_t state);

#define lcd_gfx_goto_char_xy(x,y) 	{cursorX = x*6; cursorY = y*12;}

static const uint8_t width = 128;
static const uint8_t height = 160;

void setAddrWindow(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1);
void setRotation(uint8_t m);
uint8_t getRotation(void);

void writecommand(uint8_t c);
void writedata(uint8_t c);
void get_cursor_xy (uint8_t x, uint8_t y);

void lcd_gfx_drawSymbol(unsigned int x, unsigned int y, unsigned int w, unsigned int h, unsigned char t, const unsigned char *pImage);
void lcd_gfx_drawImage(unsigned int x, unsigned int y, const TCHAR* filename);

void pushColor(uint16_t color);
uint16_t read16();
uint32_t read32();

#else
/*
** LCD 3310 driver
** Target: ATMEGA :: AVR-GCC
**
** Written by Tony Myatt - 2007
** Quantum Torque - www.quantumtorque.com
*/

/* Lcd screen size */
#define LCD_GFX_X_RES 84
#define LCD_GFX_Y_RES 48
#define LCD_GFX_CACHE_SIZE ((LCD_GFX_X_RES * LCD_GFX_Y_RES) / 8)

/* Pinout for LCD */
#define LCD_GFX_CLK_PIN 	(1<<PA4)
#define LCD_GFX_DATA_PIN 	(1<<PA3)
#define LCD_GFX_DC_PIN 		(1<<PA2)
#define LCD_GFX_CE_PIN 		(1<<PA0)
#define LCD_GFX_RST_PIN 	(1<<PA1)
#define LCD_GFX_EN_PIN 	    (1<<PA5)
#define LCD_GFX_PORT		PORTA
#define LCD_GFX_DDR			DDRA

/* Special Chars */
#define ARROW_RIGHT	ICON(0)
#define ARROW_LEFT 	ICON(1)
#define ARROW_UP 	ICON(2)
#define ARROW_DOWN 	ICON(3)
#define STOP 		ICON(4)
#define PLAY	 	ICON(5)

/* Function for my special characters */
#define	ICON(x)		'z'+1+x

void lcd_gfx_init(void);
void lcd_gfx_backlight(bool set);
void lcd_gfx_contrast(unsigned char contrast);
void lcd_gfx_clear(void);
void lcd_gfx_clear_line(unsigned char line);
void lcd_gfx_goto_char_xy(unsigned char x, unsigned char y);
void lcd_gfx_write_char(char c);
void lcd_gfx_write_string(char* s);

#endif //AVR select

//
// C++ compatibility
//
#ifdef __cplusplus
}
#endif

#endif //LCD_GFX_H