#include	<p18F4550.h>
#include	"libro.h"
#include 	"spi.h"


#define WREN        0b00000110          // WREN command
#define WRDI        0b00000100          // WRDI command
#define WRITE       0b00000010          // WRITE command
#define READ        0b00000011          // READ command
#define WRSR        0b00000001          // WRSR command
#define RDSR        0b00000101          // RDSR command

#define CS          PORTAbits.RA3       // Chip select pin
#define SCK         PORTBbits.RB1       // Clock pin
#define SO          PORTCbits.RC7       // Serial output pin
#define SI          PORTBbits.RB0       // Serial input pin
#define SS			PORTAbits.RA5		// Slave Select

#define	size_dir	24					// La direccion de memoria es de 24 bits
#define size_data	8					// El dato temdrá en el proyecto final un valor de 24 (creo)

unsigned long direccion;
unsigned char mascara, charAlto, charMedio, charBajo, dato;


void separar_palabra(unsigned long palabra)
{
	unsigned char i;

	charAlto = 0;
	charMedio = 0;
	charBajo = 0;
	mascara = 0x01;
	
	for(i=0;i<8;i++)
	{
		if((palabra & mascara) != 0)	
		{
			charBajo = charBajo | mascara;
		}
		mascara = mascara << 1;
	}

	palabra = palabra >> 8;
	mascara = 0x01;

	for(i=0;i<8;i++)
	{
		if((palabra & mascara) != 0)	
		{
			charMedio = charMedio | mascara;
		}
		mascara = mascara << 1;
	}

	palabra = palabra >> 8;
	mascara = 0x01;

	for(i=0;i<8;i++)
	{
		if((palabra & mascara) != 0)	
		{
			charAlto = charAlto | mascara;
		}
		mascara = mascara << 1;
	}

}


// Secuencia de lectura
unsigned char leer_dato_PIC (unsigned long direccion)
{

	separar_palabra(direccion);

	CS	=	0;

// Enviamos la orden de lectura
//	SSPBUF	=	READ;
	WriteSPI(READ);
	while(!PIR1bits.SSPIF);   			// Esperamos que finalice la transmisión
	PIR1bits.SSPIF = 0;      			// Limpiamos la bandera
	ReadSPI();


// Enviamos la direccion
//	SSPBUF	=	charAlto;
	WriteSPI(charAlto);
	while(!PIR1bits.SSPIF);   			// Esperamos que finalice la transmisión
	PIR1bits.SSPIF = 0;      			// Limpiamos la bandera
	ReadSPI();

//	SSPBUF	=	charMedio;
	WriteSPI(charMedio);
	while(!PIR1bits.SSPIF);   			// Esperamos que finalice la transmisión
	PIR1bits.SSPIF = 0;      			// Limpiamos la bandera
	ReadSPI();

//	SSPBUF	=	charBajo;
	WriteSPI(charBajo);
	while(!PIR1bits.SSPIF);   			// Esperamos que finalice la transmisión
	PIR1bits.SSPIF = 0;      			// Limpiamos la bandera
	ReadSPI();

// Recibimos el dato
	while(!PIR1bits.SSPIF);   			// Esperamos que finalice la transmisión
	PIR1bits.SSPIF = 0;      			// Limpiamos la bandera
	ReadSPI();


	CS	=	1;

	dato = SSPBUF;
	return dato;

//	return SSPBUF;
}

// Secuencia de escritura
void escribir_dato_PIC (unsigned long direccion, unsigned char dato)
{
	separar_palabra(direccion);

	CS	=	0;

// Enviamos la orden de escritura
//	SSPBUF	=	WRITE;
	WriteSPI(WRITE);
	while(!PIR1bits.SSPIF);   			// Esperamos que finalice la transmisión
	PIR1bits.SSPIF = 0;      			// Limpiamos la bandera
	ReadSPI();

// Enviamos la direccion

//	SSPBUF	=	charAlto;
	WriteSPI(charAlto);
	while(!PIR1bits.SSPIF);   			// Esperamos que finalice la transmisión
	PIR1bits.SSPIF = 0;      			// Limpiamos la bandera
	ReadSPI();

//	SSPBUF	=	charMedio;
	WriteSPI(charMedio);
	while(!PIR1bits.SSPIF);   			// Esperamos que finalice la transmisión
	PIR1bits.SSPIF = 0;      			// Limpiamos la bandera
	ReadSPI();

//	SSPBUF	=	charBajo;
	WriteSPI(charBajo);
	while(!PIR1bits.SSPIF);   			// Esperamos que finalice la transmisión
	PIR1bits.SSPIF = 0;      			// Limpiamos la bandera
	ReadSPI();
	

// Enviamos el dato
//	SSPBUF	=	dato;
	WriteSPI(dato);
	while(!PIR1bits.SSPIF);   			// Esperamos que finalice la transmisión
	PIR1bits.SSPIF = 0;      			// Limpiamos la bandera
	ReadSPI();

	CS	=	1;

	delay_10ms();

}

void habilitar_escritura(void)
{
	CS	=	0;

//	SSPBUF	=	WREN;
	WriteSPI(WREN);
	while(!PIR1bits.SSPIF);   			// Esperamos que finalice la transmisión
	PIR1bits.SSPIF = 0;      			// Limpiamos la bandera
	ReadSPI();

	CS	=	1;
}

unsigned int leer_status(void)
{
	CS	=	0;

//	SSPBUF	=	RDSR;
	WriteSPI(RDSR);
	while(!PIR1bits.SSPIF);   			// Esperamos que finalice la transmisión
	PIR1bits.SSPIF = 0;      			// Limpiamos la bandera
	ReadSPI();

//	SSPBUF	=	0x02;
	WriteSPI(0x00);						// Mando palabra 0, para que responda la memoria ???????????????????
	while(!PIR1bits.SSPIF);   			// Esperamos que finalice la transmisión
	PIR1bits.SSPIF = 0;      			// Limpiamos la bandera
	ReadSPI();

	CS	=	1;

}


// Un retardo de 10ms aproximadamente (con el uC trabajando a 4 MHz)
void delay_10ms (void)
{
	unsigned int i;
	for (i = 0; i < 700 ; i++);
}

void main(void)
{

// Declaraciones
	unsigned char dato_recibido = 0;
	unsigned char i;

// Configuracion de los puertos
	TRISA	=	0x00;
	TRISAbits.TRISA5	=	1;			// No se porque, pero lo pone en el datasheet (pag. 199)
	TRISB	=	0x01;
	TRISC	=	0x00;
	PORTC 	=	0x00;

// Configuracion para la comunicacion SPI
	SSPSTATbits.SMP		=	1;			// Input data sampled at end of data output time
	SSPSTATbits.CKE		=	0;			// Transmit occurs on transition from active to Idle clock state

//	SSPCON1bits.WCOL	=	0;			// Limpiamos la bandera que detecta la colision en escritura
	SSPCON1bits.SSPEN	=	1;			// Enables serial port and configures SCK, SDO, SDI and SS as serial port pins
	SSPCON1bits.CKP		=	1;			// Idle state for clock is a high level
	SSPCON1bits.SSPM3	=	0;
	SSPCON1bits.SSPM2	=	0;
	SSPCON1bits.SSPM1	=	0;
	SSPCON1bits.SSPM0	=	1;			// SSPM3:SSPM0 = 0000 -> SPI Master mode, clock = FOSC/4

// Funcionamiento
	while(1)
	{
		delay_10ms();

		// Envio el comando de habilitar escritura
		habilitar_escritura();

		leer_status();

		escribir_dato_PIC(0xAAAAAA, 0x99);
//		PORTCbits.RC6	=	1;
		dato = leer_dato_PIC(0xAAAAAA);

		if(dato == 0x99) PORTCbits.RC6	=	1;
	}
}
