/**************************************************************
        Schemat podłączeń programowanego układu
                       +----v----+
                 MCLR [| 1     28|] VDD
                      [| 2     27|] VSS
                      [| 3     26|] RP15 <- SCK1IN
                      [| 4     25|] RP14 <- SDI1
                      [| 5     24|] 
                      [| 6     23|] 
                      [| 7     22|] 
                  VSS [| 8     21|] 
       (8 MHz) / OSCI [| 9     20|] VCAP/VDDCORE
               \ OSCO [|10     19|] DISVREG
                      [|11     18|] RB9 -> D3
                      [|12     17|] RB8 -> D2
                  VDD [|13     16|] RB7 -> D1 
                      [|14     15|] 
                       +---------+
                     PIC24FJ64GB002
***************************************************************/
#include <p24Fxxxx.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)

unsigned char bufor;	//zmienna globalna dla danych wejściowych

//funkcja tworząca opóźnienie o wielokrotność mikrosekund
//dla taktowania 32 MHz
void Czekaj_us(unsigned long int ile)
{
	//jednokrotne wykonanie pętli zajmuje 16 cykli (1 us)
	while(ile>0) 
	{
		ile--;
		asm("nop");		
		asm("nop");		
		asm("nop");		
		asm("nop");		
		asm("nop");	
		asm("nop");
	}
}

void StartSPI()
{
	//1. wyczyszczenie bufora SPI1BUF
	SPI1BUF = 0;
	//2. konfiguracja przerwania
    IFS0bits.SPI1IF = 0;		//wyczyszczenie flagi przerwania
    IEC0bits.SPI1IE = 1;		//włączenie przerwania SPI1
	//3. konfiguracja SPI1CON1 i SPI1CON2
	SPI1CON1bits.MSTEN = 0;		//tryb Slave
	SPI1CON1bits.MODE16 = 0;	//dane 8-bitowe
	//2. ustawienie bitu SPIEN (włączenie modułu SPI1)
	SPI1STATbits.SPIEN = 1;	
}

void __attribute__((interrupt, no_auto_psv)) _SPI1Interrupt(void)
{
	bufor = SPI1BUF;			//pobierz dane
	IFS0bits.SPI1IF = 0;		//wyczyść flagę przerwania
}

int main()
{
	AD1PCFG = 0xFFFF;			//wszystkie linie cyfrowe
	//konfiguracja linii portu B
	TRISBbits.TRISB7 = 0;		//linia RB7 wyjściowa (D1)
	TRISBbits.TRISB8 = 0;		//linia RB8 wyjściowa (D2)
	TRISBbits.TRISB9 = 0;		//linia RB9 wyjściowa (D3)

	//remapowanie linii portów dla interfejsu SPI (linie wejściowe)
	//1. RP14 <- SDI1
	RPINR20bits.SDI1R = 14;
	//2. RP15 <- SCK1IN
	RPINR20bits.SCK1R = 15;

	bufor = 0;	
	StartSPI();					//uruchomienie modułu SPI

	for(;;)						//nieskończona pętla
	{	
		//czy w buforze są odebrane dane
		if(bufor == 1)
		{
			LATBbits.LATB8 = 0;
			LATBbits.LATB9 = 0;
			bufor = 0;
		}
		if(bufor == 2)
		{
			LATBbits.LATB8 = 1;
			LATBbits.LATB9 = 0;
			bufor = 0;
		}
		if(bufor == 3)
		{
			LATBbits.LATB8 = 0;
			LATBbits.LATB9 = 1;
			bufor = 0;
		}
		if(bufor == 4)
		{
			LATBbits.LATB8 = 1;
			LATBbits.LATB9 = 1;
			bufor = 0;
		}
		//oczekiwanie 125 ms
		Czekaj_us(125000);
		//mruganie diody kontrolnej D1
		LATBbits.LATB7 ^= 1;
	}
}
