/**************************************************************
        Schemat podłączeń programowanego układu
                       +----v----+
                 MCLR [| 1     28|] VDD
            D1 <- RA0 [| 2     27|] VSS
            D2 <- RA1 [| 3     26|] RP15 -> SCK1OUT	(SCK)
            D3 <- RB0 [| 4     25|] RP14 -> SDO1	(SI)
            D4 <- RB1 [| 5     24|] RP13 -> SDI1	(SO)
            D5 <- RB2 [| 6     23|] 
            D6 <- RB3 [| 7     22|] RP11 -> SS1		(CS)
                  VSS [| 8     21|] 
       (8 MHz) / OSCI [| 9     20|] VCAP/VDDCORE
               \ OSCO [|10     19|] DISVREG
                      [|11     18|] RB9 <- S2
                      [|12     17|] RB8 <- S1
                  VDD [|13     16|] RB7 -> D8 
            D7 <- RB5 [|14     15|] 
                       +---------+
                     PIC24FJ64GB002
***************************************************************/
#include <p24Fxxxx.h>
//definiujemy szybkość oscylatora dla funkcji __delay_
#define FCY 16000000UL 
//biblioteka z funkcjami __delay_us i __delay_ms
#include <libpic30.h>

//ustawienia bitów konfiguracyjnych
//1. 
//FWDTEN_OFF - Watchdog wyłączony
//JTAGEN_OFF - JTAG wyłączony
_CONFIG1(FWDTEN_OFF & JTAGEN_OFF)
//2.
//FNOSC_PRIPLL - układ taktowany zewnętrznym oscylatorem z pętlą PLL
//POSCMOD_XT - częstotliwość taktowania oscylatora 8 MHz
//PLLDIV_DIV2 - konieczność podzielenia przez 2 dla modułu USB PLL
_CONFIG2(FNOSC_PRIPLL & POSCMOD_XT & PLLDIV_DIV2)

void StartSPI()
{
	//1. konfiguracja SPI1CON1 i SPI1CON2
	SPI1CON1bits.MSTEN = 1;		//tryb Master
	SPI1CON1bits.MODE16 = 0;	//dane 8-bitowe
	//2. ustawienie bitu SPIEN (włączenie modułu SPI1)
	SPI1STATbits.SPIEN = 1;	
}

unsigned char TransferSPI1(unsigned char dane)
{
    SPI1BUF = dane;				//załaduj dane do bufora
    while(!SPI1STATbits.SPIRBF);//zaczekaj na zakończenie operacji
    return SPI1BUF;    			//odczytaj dane
}

void Diody(unsigned char x)
{
	//zgaś diody				
	LATAbits.LATA0 = 0;		//(D1)
	LATAbits.LATA1 = 0;		//(D2)
	LATBbits.LATB0 = 0;		//(D3)
	LATBbits.LATB1 = 0;		//(D4)
	LATBbits.LATB2 = 0;		//(D5)
	LATBbits.LATB3 = 0;		//(D6)
	LATBbits.LATB5 = 0;		//(D7)
	LATBbits.LATB7 = 0;		//(D8)

	//zaświeć diody
	if(x&0x01)	LATAbits.LATA0 = 1;
	if(x&0x02)	LATAbits.LATA1 = 1;
	if(x&0x04)	LATBbits.LATB0 = 1;
	if(x&0x08)	LATBbits.LATB1 = 1;
	if(x&0x10)	LATBbits.LATB2 = 1;
	if(x&0x20)	LATBbits.LATB3 = 1;
	if(x&0x40)	LATBbits.LATB5 = 1;
	if(x&0x80)	LATBbits.LATB7 = 1;
}

int main()
{
	unsigned char k, adres, bajt;

	AD1PCFG = 0xFFFF;			//wszystkie linie cyfrowe
	/////////////////////////////////////////////////////
	// konfiguracja linii portów A i B
	TRISAbits.TRISA0 = 0;		//linia RA0 wyjściowa (D1)
	TRISAbits.TRISA1 = 0;		//linia RA1 wyjściowa (D2)
	TRISBbits.TRISB0 = 0;		//linia RB0 wyjściowa (D3)
	TRISBbits.TRISB1 = 0;		//linia RB1 wyjściowa (D4)
	TRISBbits.TRISB2 = 0;		//linia RB2 wyjściowa (D5)
	TRISBbits.TRISB3 = 0;		//linia RB3 wyjściowa (D6)
	TRISBbits.TRISB5 = 0;		//linia RB5 wyjściowa (D7)
	TRISBbits.TRISB7 = 0;		//linia RB7 wyjściowa (D8)

	TRISBbits.TRISB8 = 1;		//linia RB8 wejściowa (S1)
	TRISBbits.TRISB9 = 1;		//linia RB9 wejściowa (S2)

	/////////////////////////////////////////////////////
	// obsługa SPI1
	//remapowanie linii portów dla interfejsu SPI
	//linie wyjściowe
	//1. RP14 -> SDO1 (funkcja nr 7)
	RPOR7bits.RP14R = 7;
	//2. RP15 -> SCK1OUT (funkcja nr 8)
	RPOR7bits.RP15R = 8;
	//linia wejściowa
	//3. RP13 <- SDI1 (linia nr 13)
	RPINR20bits.SDI1R = 13;
	//linię SS1 będziemy zerować samodzielnie
	TRISBbits.TRISB11 = 0;		//linia RB11 wyjściowa (SS1)
	LATBbits.LATB11 = 1;		//stan wysoki na linii
	
	StartSPI();					//uruchomienie modułu SPI

	/////////////////////////////////////////////////////
	//zapisz dane do pamięci SRAM (23K256)
	for(k=0; k<250; k++)
	{
		LATBbits.LATB11 = 0;//SS1 w stanie niskim
		TransferSPI1(2);	//rozkaz zapisu
		TransferSPI1(0);	//pierwsza część 16-bitowego adresu
		TransferSPI1(k);	//druga część 16-bitowego adresu
		TransferSPI1(k);	//bajt do zapisania
		LATBbits.LATB11 = 1;//SS1 w stanie wysokim
	}
	adres = 0;
	/////////////////////////////////////////////////////
	for(;;)						//nieskończona pętla
	{
		//odczytaj dane z pamięci SRAM
		for(k=0; k<250; k++)
		{
			LATBbits.LATB11 = 0;	//SS1 w stanie niskim
			TransferSPI1(3);		//rozkaz odczytu
			TransferSPI1(adres);	//pierwsza część 16-bitowego adresu
			TransferSPI1(k);		//druga część 16-bitowego adresu
			bajt = TransferSPI1(0);	//odczytaj bajt
			LATBbits.LATB11 = 1;	//SS1 w stanie wysokim

			Diody(bajt);			//zaświeć diody zgodnie z odczytanym bajtem
			__delay_ms(125);		//oczekiwanie 125 ms
			//sprawdź stan klawiszy
			if(PORTBbits.RB8 == 0) adres = 0;
			if(PORTBbits.RB9 == 0) adres = 0xA;
		}
	}
}
