/**************************************************************
        Schemat podłączeń programowanego układu
                       +----v----+
                 MCLR [| 1     28|] VDD
                  RA0 [| 2     27|] VSS
                  RA1 [| 3     26|] RB15 -> DB4        
           SDO <- RP0 [| 4     25|] RB14 -> DB5
           SCK <- RP1 [| 5     24|] RB13 -> DB6
            SS <- RP2 [| 6     23|] 
           SDI -> RP3 [| 7     22|] RB11 -> DB7
                  VSS [| 8     21|] RB10 -> RS
       (8 MHz) / OSCI [| 9     20|] VCAP/VDDCORE
               \ OSCO [|10     19|] DISVREG
                      [|11     18|] RB9 -> EN
                      [|12     17|] 
                  VDD [|13     16|] RP7 (U2RXR) <- GPS TX
            S1 -> RB5 [|14     15|] 
                       +---------+
                     PIC24FJ64GB002
***************************************************************/
#include <p24FJ64GB002.h>
//definiujemy szybkość oscylatora dla funkcji __delay_
#define FCY 16000000UL 
//biblioteka z funkcjami __delay_us i __delay_ms
#include <libpic30.h>
//biblioteka FAT16
#include "FSIO.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)
//////////////////////////////////////
#define TRIS_RS_LCD   TRISBbits.TRISB10
#define TRIS_EN_LCD   TRISBbits.TRISB9
#define TRIS_DB4_LCD  TRISBbits.TRISB15
#define TRIS_DB5_LCD  TRISBbits.TRISB14
#define TRIS_DB6_LCD  TRISBbits.TRISB13
#define TRIS_DB7_LCD  TRISBbits.TRISB11

#define RS_LCD   LATBbits.LATB10
#define EN_LCD   LATBbits.LATB9
#define DB4_LCD  LATBbits.LATB15
#define DB5_LCD  LATBbits.LATB14
#define DB6_LCD  LATBbits.LATB13
#define DB7_LCD  LATBbits.LATB11

#include "lcd.h"
//////////////////////////////////////
char tablica[128] = {13, 10};			//tablica danych

//tablice znakowe dla funkcji LCD
char napis0[] = "Szukam karty SD";		//15 znaków
char napis1[] = "Nie mam kontaktu";		//16 znaków
char napis2[] = "Mam kontakt z SD";		//16 znaków

char dane = 0, flaga = 0;				//zmienne modyfikowane w funkcji obsługi przerwania
int kursor;								//zmienna do obsługi tablicy

void __attribute__ ((interrupt, no_auto_psv)) _U2RXInterrupt(void) 
{
	dane = U2RXREG;						//odczytaj dane
	flaga = 1;							//ustaw flagę odebranego bajtu
	IFS1bits.U2RXIF = 0;				//czyść flagę przerwania
}

int main()
{
	FSFILE *plik;						//wskaźnik do pliku
	/////////////////////////////////////////////////////
	AD1PCFGL = 0xFFFF;					//wszystkie linie cyfrowe

	TRISBbits.TRISB5 = 1;				//linia RB5 wejściowa (S1)
	/////////////////////////////////////////////////////
	//uruchomienie wyświetlacza LCD//////////////////////
	WlaczLCD();							//inicjalizacja wyświetlacza LCD
	WyswietlLCD(napis0, 15);			//wyświetl napis "Szukam karty SD"

	/////////////////////////////////////////////////////
	// obsługa SPI1
	//remapowanie linii portów dla interfejsu SPI
	//linie wyjściowe
	//1. RP0 -> SDO1 (funkcja nr 7)
	RPOR0bits.RP0R = 7;
	//2. RP1 -> SCK1OUT (funkcja nr 8)
	RPOR0bits.RP1R = 8;
	//3. RP2 -> SS1OUT
	RPOR1bits.RP2R = 9;
	//linia wejściowa
	//4. RP3 <- SDI1 (linia nr 3)
	RPINR20bits.SDI1R = 3;

	/////////////////////////////////////////////////////
	// inicjalizacja karty SD i interfejsu SPI1
	while(!FSInit())
	{
		CzyscLCD();						//resetuj pamięć wyświetlacza
		WyswietlLCD(napis1, 16);		//wyświetl napis "Nie mam kontaktu"
		__delay_ms(1000);				//zaczekaj 1 s
	}
	/////////////////////////////////////////////////////
	//inicjalizacja SD i SPI przebiegła poprawnie
	CzyscLCD();							//resetuj pamięć wyświetlacza
	WyswietlLCD(napis2, 16);			//wyświetl napis "Mam kontakt z SD"

	/////////////////////////////////////////////////////
	// obsługa UART
	//remapowanie RP2 dla wejściowej linii U2RX modułu UART2
	//RP7 <- U2RX (linia nr 7)
	RPINR19bits.U2RXR = 7;
	//prędkość = 9600 (U2BRG = 16000000/16*9600 - 1)
	U2BRG = 103;
	//włącz obsługę przerwania U2RX
	IPC7bits.U2RXIP = 4;				//priorytet przerwania 4 (domyślny)
	IFS1bits.U2RXIF = 0;				//czyść flagę przerwania
	IEC1bits.U2RXIE = 1;				//włącz przerwanie
	//włącz moduł UART2
	U2MODEbits.UARTEN = 1;

	/////////////////////////////////////////////////////
	CzyscLCD();							//resetuj pamięć wyświetlacza
	/////////////////////////////////////////////////////
	//nieskończona pętla
	for(;;)						
	{
		//czy nadeszła nowa wiadomość
		if(flaga)
		{
			flaga = 0;					//zerowanie flagi
			if(dane == '$') kursor = 1;	//szukaj początku wiadomości
			if(kursor>0) 
			{
				kursor++;				//inkrementuj kursor
				tablica[kursor] = dane;	//ładuj dane do tablicy

				//czy odczytany został wystarczający fragment ramki
				if(kursor>64)
				{
					//zapisz dane do pliku, jeśli S1 jest włączony
					if(PORTBbits.RB5 == 0)
					{
						//otwórz plik w trybie dopisywania
						plik = FSfopen("TRASA.TXT", "a");
						//zapisz dane do pliku
						FSfwrite((void*)tablica, 65, 1, plik);
						FSfclose(plik);	//zamknij plik
					}
					kursor = 0;
				}
				if(tablica[20] == 'A')	//jeśli dane są poprawne
				{
					//wyświetl współrzędne długości
					if((kursor>21)&&(kursor<34))
					{
						UstawKursorLCD(1, kursor-21);
						Wyslij_do_LCD(tablica[kursor]);
					}
					//wyświetl współrzędne szerokości
					if((kursor>33)&&(kursor<47))
					{
						UstawKursorLCD(2, kursor-33);
						Wyslij_do_LCD(tablica[kursor]);
					}
					//wyświetl inf. o danych poprawnych
					if(kursor == 20)
					{
						UstawKursorLCD(1, 16);
						Wyslij_do_LCD('A');
					}
				}
				else
				//wyświetl inf. o danych niepoprawnych
				{
					if(kursor == 20)
					{
						UstawKursorLCD(1, 16);
						Wyslij_do_LCD('V');
					}
				}
				//szukamy ramki $GPRMC
				//tablica[2] = $, tablica[3] = G, tablica[4] = P
				//tablica[5] = R, tablica[6] = M, tablica[7] = C
				if((kursor == 5)&&(tablica[5]!='R')) kursor = 0;
				if((kursor == 6)&&(tablica[6]!='M')) kursor = 0;
				if((kursor == 7)&&(tablica[7]!='C')) kursor = 0;
			}
		}
	}

}
