// Библиотека предназначена для работы с димплеем от телефона
// SIEMENS S65 типа LS020XXXX.
// Содержит основные функции для инициализации и вывода информации на дисплей
// Для работы библиотеки в основном теле программы необходимо
// определить следующие переменные:
//
// 		#define F_CPU 16000000UL 		   // рабочая частота процессора (16 MHz)
//      #define S65_PORT         PORTB 	   // порт, на который вешается LCD (пины указанного порта будут сконфигурированы на "выход")
//		#define S65_DDR 		 DDRB 	   // регистр управления портом S65_PORT
//      #define SPI_APPARAT	     1		   // если переменная определена - будет использоваться аппаратный SPI, иначе - программный
//      #define INCDIRECTION     XDIR	   // направление приращения координат (по XDIR, YDIR)
//
//      #define S65_CLK_PIN      PB5       // если указан аппаратный SPI переменная S65_CLK_PIN должна указывать на ногу "SCK" процессора, иначе любая из ног S65_PORT
//      #define S65_DAT_PIN      PB3       // если указан аппаратный SPI переменная S65_DAT_PIN должна указывать на ногу "MOSI" процессора, иначе любая из ног S65_PORT
//      #define S65_CS_PIN       PB2       // любая из ног S65_PORT
//      #define S65_RS_PIN       PB0	   // любая из ног S65_PORT
//      #define S65_RESET_PIN	 PB1       // любая из ног S65_PORT
//      #define S65_LED_PIN      PB4       // любая из ног S65_PORT
//
//
// В инициализации код $7f3f заменяем на $7f1f ,
// получаем 256 цветов. Передача команд таже , 
// дата не 16 бит один пиксель , а 16 бит два пикселя. 
//
// Нашел решение проблемы переключения дисплея в 8ми битный 
// режим. необходимо было поставить задержку в процедуре 
// инициализации после слова 0x4306 около 50 мс (примерно).
// в моем случае это помогло. 
//
//
// Ориентация 
// -вертикальная XDIR:
//   *y---+
//   x    |
//   |    |
//   |    |
//   |    |
//   +----+
//
// -горизонтальная YDIR:
//   *y------+
//   x       |
//   |       |
//   +-------+
//
// * - начало координат



#include <util/delay.h>
#include <avr/pgmspace.h>
#include "proc.h"

//команды включения
uint8_t init_1[24] PROGMEM =
{0xFD, 0xFD, 0xFD, 0xFD, 0xEF, 0x00, 0xEE, 0x04, 0x1B, 0x04, 0xFE, 0xFE,
 0xFE, 0xFE, 0xEF, 0x90, 0x4A, 0x04, 0x7F, 0x3F, 0xEE, 0x04, 0x43, 0x06};

uint8_t init_2[46] PROGMEM =
{0xEF, 0x90, 0x09, 0x83, 0x08, 0x00, 0x0B, 0xAF,
 0x0A, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 
 0xEF, 0x00, 0xEE, 0x0C, 0xEF, 0x90, 0x00, 0x80, 
 0xEF, 0xB0, 0x49, 0x02, 0xEF, 0x00, 0x7F, 0x01,
 0xE1, 0x81, 0xE2, 0x02, 0xE2, 0x76, 0xE1, 0x83,
 0x80, 0x01, 0xEF, 0x90, 0x00, 0x00};

//команды выключения дисплея
uint8_t Off_1[8] PROGMEM={0xEF,0x00,0x7E,0x04,0xEF,0xB0,0x5A,0x48};  
uint8_t Off_2[8] PROGMEM={0xEF,0x00,0x7F,0x01,0xEF,0xB0,0x64,0xFF};
uint8_t Off_3[2] PROGMEM={0x65,0x00};
uint8_t Off_4[12] PROGMEM ={0xEF,0x00,0x7F,0x01,0xE2,0x62,0xE2,0x02,0xEF,0xB0,0xBC,0x02};
uint8_t Off_5[10] PROGMEM ={0xEF,0x00,0x7F,0x01,0xE2,0x00,0x80,0x00,0xE2,0x04};
uint8_t Off_6[8] PROGMEM ={0xE2,0x00,0xE1,0x00,0xEF,0xB0,0xBC,0x00}; 
uint8_t Off_7[4] PROGMEM ={0xEF,0x00,0x7F,0x01};

// приращение по X при выводе точки
#define XDIR	0x04	
// приращение по X при выводе точки
#define YDIR    0x00
// включить подсветку дисплея
#define ls020_led_on()        LS020_PORT |= (1<<LS020_LED_PIN)
// выключить подсветку дисплея
#define ls020_led_off()       LS020_PORT &= ~(1<<LS020_LED_PIN)
// установить флаги - послать команду
#define ls020_cmd_mode() 	  LS020_PORT |= (1<<LS020_RS_PIN);LS020_PORT &= ~(1<<LS020_CS_PIN)
// установить флаги - послать данные
#define ls020_data_mode() 	  LS020_PORT &= ~(1<<LS020_RS_PIN); LS020_PORT &= ~(1<<LS020_CS_PIN)
// отключться от lcd
#define ls020_deselect()	  LS020_PORT |= (1<<LS020_CS_PIN)

// в зависимости от ориентации устанавливаем размер экрана
#if (INCDIRECTION==XDIR)		
	#define cSCWidth	132
	#define cSCHeight	176
#endif

// в зависимости от ориентации устанавливаем размер экрана
#if (INCDIRECTION==YDIR)
	#define cSCWidth	176
	#define cSCHeight	132
#endif


#define clBlack 	0		// черный
#define clBlue 		0x127		// голубой
#define clWhite 	255		// бклый





/*
// ----------------------------------
// передача 8-и битов на LCD
// (эмуляция SPI протокола. ASM-версия)
// ----------------------------------
void spi_send_prog_asm(uint8_t send)
{
uint8_t count;
asm volatile (
					"LDI    %[count],0x08"  					"\n\t" // Загрузили в счетчик 8 (8 бит)
"_loop%=:"			"SBRS   %[send],7"  						"\n\t" // броверяем 7 бит данного на отсылку
					"RJMP	_setzero%="  						"\n\t" // бит равен 0 - переход
					"SBI    %[ls020_port],%[ls020_dat_pin]"  		"\n\t" // бит равен 1 - установить s65_dat_pin=1
					"RJMP	_clk%="  							"\n\t" // переход на сигнал CKL
"_setzero%=:"		"CBI    %[ls020_port],%[ls020_dat_pin]"  		"\n\t" // бит равен 1 - установить s65_dat_pin=1
"_clk%=:"			"SBI    %[ls020_port],%[ls020_clk_pin]"  		"\n\t" // установить s65_clk_pin=1
					"LSL 	%[send]"  							"\n\t" // сдвиг данного
					"CBI    %[ls020_port],%[ls020_clk_pin]"  		"\n\t" // установить s65_clk_pin=0
					"DEC 	%[count]" 							"\n\t" // уменьшить счетчик
					"BRNE   _loop%=" 						    "\n\t" // переход если не 0		
:
	[count] 		"=&r" (count)
:
	[ls020_port] 		"I" (_SFR_IO_ADDR(LS020_PORT)),
	[ls020_dat_pin] 	"I" (LS020_DAT_PIN), 
	[ls020_clk_pin] 	"I" (LS020_CLK_PIN),
	[send] 				"r" (send)
);

}

// ----------------------------------
// передача 8-и битов на LCD
// (эмуляция SPI протокола. C-версия)
// ----------------------------------
void spi_send_prog(uint8_t send)
{
uint8_t count=8;
while (count!=0) 
{
	if bit_is_set(send,7) {SETBIT(LS020_PORT,LS020_DAT_PIN);} else {CLEARBIT(LS020_PORT,LS020_DAT_PIN);}
	SETBIT(LS020_PORT,LS020_CLK_PIN);
	send=send<<1;
	CLEARBIT(LS020_PORT,LS020_CLK_PIN);
	count--;
}
}

*/






// отослать 8-и битную команду
void ls020_wrcmd8(uint8_t cmd)
{
  ls020_cmd_mode();
  SPCR = (1<<MSTR)|(1<<SPE);
  SPDR = cmd;
  while ( !(SPSR & (1 << SPIF)));
  ls020_deselect();
}

// отослать 8-и битные данные
void ls020_wrdata8(uint8_t data)
{
  ls020_data_mode();
  SPCR = (1<<MSTR)|(1<<SPE);
  SPDR = data;
  while ( !(SPSR & (1 << SPIF)));
  ls020_deselect(); // deselect LCD  
}

// отослать 16-и битную команду
void ls020_wrcmd16(uint16_t cmd16)
{
  ls020_wrcmd8((cmd16 >> 8) & 0xFF);
  ls020_wrcmd8(cmd16 & 0xFF);
}

// установить 8-и битный режим
void ls020_8bit_mode(uint8_t BGR) // BGR=0 - disabled, BGR=1 - enabled.
{
  ls020_wrcmd16(0xE800+(BGR&0x01)*0x40);
}

// установить 16-и битный режим
void ls020_16bit_mode(void)
{
  ls020_wrcmd16(0xE80F);
}

// инициализировать LCD
void ls020_init_lcd(void)
{
  LS020_DDR=LS020_DDR|
		((1<<LS020_RS_PIN)| 
		 (1<<LS020_RST_PIN)|
		 (1<<LS020_CS_PIN)|
		 (1<<LS020_CLK_PIN)|
		 (1<<LS020_DAT_PIN)|
		 (1<<LS020_LED_PIN));
  LS020_PORT=LS020_PORT|
		((1<<LS020_RS_PIN)| 
		 (1<<LS020_RST_PIN)|
		 (1<<LS020_CS_PIN)|
		 (1<<LS020_CLK_PIN)|
		 (1<<LS020_DAT_PIN)|
		 (1<<LS020_LED_PIN));
  LS020_PORT &= ~(1<<LS020_RST_PIN); // Pull RST pin down
  _delay_ms(50);
  LS020_PORT |= (1<<LS020_RST_PIN); // Release RST pin
  SPCR = (1<<MSTR)|(1<<SPE); // SPI config
  SPSR=(1<<SPI2X); // double speed
  for (uint8_t i=0; i<24; i++)
  {
    ls020_wrcmd8(pgm_read_byte(init_1+i));
  _delay_ms(50);
  }
  _delay_ms(50);
  for (uint8_t i=0; i<46; i++)
    ls020_wrcmd8(pgm_read_byte(init_2+i));
}


// Назначить регион вывода
void ls020_set_window(uint8_t x1, uint8_t y1, uint8_t x2,uint8_t y2)
{
//  ls020_wrcmd16((0x05<<8)+INCDIRECTION); // Set Direction
#if (INCDIRECTION==XDIR)
  ls020_wrcmd16((0x05<<8)+XDIR); // Set Direction
  ls020_wrcmd16(0x0A00+x1);
  ls020_wrcmd16(0x0B00+x2);
  ls020_wrcmd16(0x0800+y1);
  ls020_wrcmd16(0x0900+y2);
#endif

#if (INCDIRECTION==YDIR)
  ls020_wrcmd16((0x05<<8)+XDIR); // Set Direction
  ls020_wrcmd16(0x0A00+cSCWidth-y2);
  ls020_wrcmd16(0x0B00+cSCWidth-y1);
  ls020_wrcmd16(0x0800+x1);
  ls020_wrcmd16(0x0900+x1+x2);
#endif
}



// Выключить LCD
void ls020_off_lcd(void)
{
uint8_t i;
for (i=0;i<8;i++) ls020_wrcmd8(pgm_read_byte(Off_1+i));
_delay_ms(50);
for (i=0;i<8;i++) ls020_wrcmd8(pgm_read_byte(Off_2+i));
_delay_ms(50);
for (i=0;i<2;i++) ls020_wrcmd8(pgm_read_byte(Off_3+i));
_delay_ms(50);
for (i=0;i<12;i++) ls020_wrcmd8(pgm_read_byte(Off_4+i));
_delay_ms(50);
for (i=0;i<10;i++) ls020_wrcmd8(pgm_read_byte(Off_5+i));
_delay_ms(50);
for (i=0;i<8;i++) ls020_wrcmd8(pgm_read_byte(Off_6+i));
_delay_ms(50);
for (i=0;i<4;i++) ls020_wrcmd8(pgm_read_byte(Off_7+i));
ls020_led_off();
}















































