/*********************************************
+		Külső fájlok beemelése
**********************************************/
#include <p18F4550.h>			//PIC beálltása
#include <stdio.h>
#include <delays.h>				//Késleltetések
#include <stdlib.h>
#include "header.h"				//Álltalános header beállítások
#include "p18f4550_pindef.h"	//P18F4550 saját definicióim
#include "lcd.c"				//LDC meghajtás függvényei

/*********************************************
+		Definciciók deklarálása
**********************************************/
//-------------------------- Definciciók ----------------------------//
//PIC18F4550 SPI lábkiosztása
//7. (RA5)[SS - SPI másodlagos input választó]
//33.(RBO)[SDI - SPI adat bemenet]
//34.(RB1)[SCK - szinkron óra be/ki SPI módban]
//26.(RC7)[SDO - SPI adat kimenet]
#define SPI_CS_TRIS		TRIS_A5		//A5 chip választás
#define SPI_CS			LAT_A5		//A5 chip választás
#define SPI_SO_TRIS		TRIS_B0		//B0-ás bit
#define SPI_SCK_TRIS	TRIS_B1		//B1-es bit órajel
#define SPI_SI			TRIS_C7		//C7 adat ki
//-- A 25LC640 EEPROM által elfogadott parancsok
#define CMD_WRSR  		0x01		//Státuszregiszter írása
#define CMD_WRITE 		0x02		//Írás a megadott címtől kezdődően
#define CMD_READ  		0x03		//Olvasás a megadott címtől kezdődően
#define CMD_WRDI  		0x04		//Letiltja az írást
#define CMD_RDSR  		0x05		//Státuszregiszter olvasása
#define CMD_WREN  		0x06		//Engedélyezi az írást
#define PMEMBLOCK		32
/*********************************************
+		Union deklarálása
**********************************************/
/*- 16bit-es UNION - (SPI memória címzéshez és 2 bájtos (16bit-es) adatok tárolásához kell)*/
typedef union _union16 { 
  unsigned int value;
  struct {
    unsigned char low;
	unsigned char high;
  };
} union16;

/*********************************************
+		Prototípusok
**********************************************/
void main(void);								//Main()
unsigned char spi_io(unsigned char adat);		//SPI írás olvasás
void waitFor25LC640(void);						//Várakozás a SPI memóriára
void memWrite25LC640(union16 MemCim, unsigned char *pbuf);	//Memória írása
void memRead25LC640(union16 MemCim, unsigned char *pbuf);	//Meria olvasása

void main(void){
	
	/*********************************************
	+		Változók deklarálása
	**********************************************/	
	union16 MemCim, ReadCim, AlsoFutes;
	unsigned char Membuffer[PMEMBLOCK+1] = {0};
	unsigned char x=0, i=0, z=0;
		
	/*********************************************
	+		LCD inicializálás
	**********************************************/
	TRISD = 0;
    lcd_init();             // Az LCD modulinicializálása 
    stdout = _H_USER;       // Az LCD legyen a standard kimenetnt
    /****************************LCD*************************************/
	
	/*********************************************
	+		SPI init
	**********************************************/
	SPI_CS_TRIS = 0;		//A5-es láb kimenet
	SPI_CS = 1;				//A5 láb magas szinten
	SPI_SO_TRIS = 1;		//B0 láb SDI bemenet
	SPI_SCK_TRIS = 0;		//B1 láb SCK kimenet
	SPI_SI = 0;				//C7 láb SI kimenet
	SSPSTATbits.SMP = 0;	//Mintavételezés időzítése Master mód esetén 1: mintavételezés a kimeneti idő végén, 0: mintavételezés a kimeneti idő közepén). Slave módban kötelezően nullába kell állítani.
	SSPSTATbits.CKE = 0;	//Órajel fázisának beállítása (1: az adatkimenet beállítása akkor történik,amikor az órajel aktív állapotból tétlenre vált, 0: az adatkimenet beállítása akkor történik, amikor az órajel tétlen állapotból aktív szintre vált)
	SSPSTATbits.BF = 0;		//A buffer foglaltságát jelző állapotbit  (1: az adatátvitel lezajlott, SSPBUF kiolvasható, 0: az adatbuffer üres)
	SSPCON1bits.WCOL = 	0;	//Ütközés detektálás írásnál (1: írást/adatküldést kíséreltünk meg, amikor nem lehetett, 0: nincs ütközés)
	SSPCON1bits.SSPOV = 0;	//Vételi túlcsordulás-jelző (1: újabb bájt érkezett, de SSPBUF meg nincs kiolvasva, 0: nincs túlfolyás)
	SSPCON1bits.SSPEN = 1;	//Master Szinkron Soros Port engedélyezése (1: engedélyezve, 0: letiltva)
	SSPCON1bits.CKP = 	0;	//Órajel polaritása (1: aktív állapotban alacsony szint, 0: aktív állapotban magas szint)
	SSPCON1bits.SSPM0 = 0;
	SSPCON1bits.SSPM1 = 1;
	SSPCON1bits.SSPM2 = 0;
	SSPCON1bits.SSPM3 = 0;
	
	//Beíárás után ki kell kommentelni-------------------------------------
	/*Membuffer[0] = '#';
	Membuffer[1] = 'D';
	Membuffer[2] = 'P';
	Membuffer[3] = 'T';
	Membuffer[4] = 'P';
	Membuffer[5] = ' ';
	Membuffer[6] = ' ';
	Membuffer[7] = ' ';
	Membuffer[8] = ' ';
	Membuffer[9] = ' ';
	Membuffer[10] = ' ';
	Membuffer[11] = ' ';
	Membuffer[12] = ' ';
	Membuffer[13] = ' ';
	Membuffer[14] = ' ';
	Membuffer[15] = ' ';
	Membuffer[16] = ' ';
	Membuffer[17] = ' ';
	Membuffer[18] = 60;
	Membuffer[19] = 61;
	Membuffer[20] = 120;
	Membuffer[21] = 62;
	Membuffer[22] = 160;
	Membuffer[23] = 63;
	Membuffer[24] = 200;
	Membuffer[25] = 64;
	Membuffer[26] = 220;
	Membuffer[27] = 65;
	Membuffer[28] = 250;
	Membuffer[29] = 66;
	AlsoFutes.value = 500;
	Membuffer[30] = AlsoFutes.low;
	Membuffer[31] = AlsoFutes.high;
	Membuffer[32] = '\0';

	//2 memória blokk feltöltése
	MemCim.value = 0;
	memWrite25LC640(MemCim, Membuffer);
	
	//MemCim.value += PMEMBLOCK;	//32
	//memWrite25LC640(MemCim, Membuffer);
	
	memset(Membuffer, 0, sizeof(Membuffer));	//Nullázzuk Membuffer-t
	//Beíárás után ki kell kommentelni------------------------------------
	*/
	//Kiolvassuk a memória tartamát
	MemCim.value = 0;
	do{ 
		memRead25LC640(ReadCim, Membuffer);
		ReadCim.value += PMEMBLOCK;
		for(i=0; i<PMEMBLOCK; i++){
			if(Membuffer[i]=='#'){ z++; }
			printf("%i - %02i - 0x%x    ", x, ReadCim.value-PMEMBLOCK, ReadCim.value-PMEMBLOCK);
			lcd_write(0xC0,0,1,1);
			printf("Talalat(#): %i      ", z);
			lcd_write(0x94,0,1,1);
			printf("H:%i - L:%i         ", ReadCim.high, ReadCim.low);
			lcd_write(0xD4,0,1,1);
			printf("%i~%c               ", i,  Membuffer[i]);
			lcd_write(0x80,0,1,1); 
			Delay10KTCYx(10);
		}
		memset(Membuffer, 0, sizeof(Membuffer));
	x++;
	}while(x<15);	//Amennyi lapot akarunk, annyit olvasunk ki
	Delay10KTCYx(100);
	
	while(1);

}//main
 
/*********************************************
+		SPI 25LC640 memória
**********************************************/
	unsigned char spi_io(unsigned char adat){
		unsigned char tmp;  
		SSPSTATbits.BF = 0;			// törli foglaltság jelző álapotát a státusz regiszterben
		SSPCON1bits.WCOL = 0;		// törli az esetleges írás ütközés hibajelzőt
		tmp = SSPBUF;				// törli a BF jelzőbitet
		SSPBUF = adat;				// kirakja a kimenő adatot az SSPBUF regiszterbe
		while(!SSPSTATbits.BF);		// megvárjuk a busz ciklus végét 
		return (SSPBUF);			// a vett bájttal térünk vissza
	}

	void waitFor25LC640(void) {
	  unsigned int flag;
	  do {
		SPI_CS = 0;                      	    //kiadjuk a Chip Enable jelet
		spi_io(CMD_RDSR);                       //Státuszregiszter olvasása parancs
		flag = spi_io(0x00);                    //Olvasunk, de valamit akkor is küldeni kell!
		SPI_CS = 1;                   		    //megszüntetjük a Chip Enable jelet
	  } while (flag & 0x01); 
	}

	void memWrite25LC640(union16 MemCim, unsigned char *pbuf) {
		unsigned char i,flag;
		waitFor25LC640();                         //Várunk, ha az EEPROM elfoglalt
		SPI_CS = 0;
		WriteSPI(CMD_WREN);                       //Írás újraengedélyezése
		SPI_CS = 1;
		Delay10KTCYx(1);
		SPI_CS = 0;
		spi_io(CMD_WRITE);                        //Adatblokk írása
		spi_io(MemCim.low);
		spi_io(MemCim.high);
		for (i=0; i < PMEMBLOCK; i++) {
			spi_io(*pbuf++);                      //Az adatbuffer kiírása
		}
		SPI_CS = 1;
	}

	void memRead25LC640(union16 MemCim, unsigned char *pbuf) {
	  unsigned char i;
	  waitFor25LC640();                         //Várunk, ha az EEPROM elfoglalt
	  SPI_CS = 0;
	  spi_io(CMD_READ);                         //Adatblokk olvasása
	  spi_io(MemCim.low);
	  spi_io(MemCim.high);
	  for (i=0; i < PMEMBLOCK; i++) {
		*pbuf++=spi_io(0x00);                   //Olvasunk, de valamit akkor is küldeni kell!
	  }
	  SPI_CS = 1;
	}
