// ***********************************************************************************
// **** PROGRAM = TROPICIEL GPS (C) 2010 LUCIDSCIENCE.COM
// **** PLATFORMA = ATMEGA324P & FV-M8 GPS MODULE
// **** PRDKO ZEGARA = 14,7456 MHZ, KRYSZTA
// ***********************************************************************************
#include <mega324.h>
#include <delay.h>
// ***********************************************************************************
// **** ZMIENNE GLOBALNE NA DANE GPGGA 
// ***********************************************************************************
char gpgga[80];
char track[1440];
// ***********************************************************************************
// **** WYSYANIE DANYCH PRZEZ PORT USART0 Z PRDKOCI 38400 B/S
// ***********************************************************************************
void DATSEND(char dat) {
  while(!(UCSR0A & (1<<5)));
  UDR0 = dat;
}
// ***********************************************************************************
// **** ODCZYT DANYCH GPGGA Z PORTU USART1 Z PRDKOCI 38400 B/S I ZAPIS DO ACUCHA
// ***********************************************************************************
void GPSREAD() {
  unsigned char ctr;
  unsigned char data;
  // $GPGGA, 223611.000, 4821.9234,N, 08916.4091,W, 1, 8, 1.17, 190.1,M, -35.0,M, ,*6F
  // $GPGGA, CZAS UTC, SZER. GEOGR., D. GEOGR., STAN, SATELITY, PO. POZ., WYS., PO. PION., SUMA KONTR.
  // SKASOWANIE OSTATNICH DANYCH W CIGU ZNAKW
  for (ctr = 0; ctr < 80; ctr++) {
    gpgga[ctr] = 32;
  }
  // OCZEKIWANIE NA NAGWEK $GPGGA
  while (ctr != 6) {
    ctr = 0;
    while (!(UCSR1A & (1<<7)));
    data = UDR1;
    if (data == '$') ctr++;
    while (!(UCSR1A & (1<<7)));
    data = UDR1;
    if (data == 'G') ctr++;
    while (!(UCSR1A & (1<<7)));
    data = UDR1;
    if (data == 'P') ctr++;
    while (!(UCSR1A & (1<<7)));
    data = UDR1;
    if (data == 'G') ctr++;
    while (!(UCSR1A & (1<<7)));
    data = UDR1;
    if (data == 'G') ctr++;
    while (!(UCSR1A & (1<<7)));
    data = UDR1;
    if (data == 'A') ctr++;
  }
  while (data != ',') {
    while (!(UCSR1A & (1<<7)));
    data = UDR1;
  }
  // ODCZYT DANYCH GPGGA DO KOCA WIERSZA
  data = 0;
  ctr = 0;
  while (data != 10) {
    while (!(UCSR1A & (1<<7)));
    data = UDR1;
    gpgga[ctr] = data;
    ctr++;
  }
}
// ***********************************************************************************
// **** ZMIENNE PROGRAMU I KONFIGURACJA PORTU
// ***********************************************************************************
void main(void) {
  // GWNE ZMIENNE PROGRAMU
  unsigned char ctr;
  unsigned char mode;
  unsigned char skip;
  unsigned int trk;
  // USTAWIENIE PRDKOCI PORTU USART0 NA 38400,8,N,1
  UCSR0A=0x00;
  UCSR0B=0x08;
  UCSR0C=0x06;
  UBRR0H=0x00;
  UBRR0L=0x17;
  // USTAWIENIE PRDKOCI PORTU USART1 NA 38400,8,N,1
  UCSR1A=0x00;
  UCSR1B=0x10;
  UCSR1C=0x06;
  UBRR1H=0x00;
  UBRR1L=0x17;
  // PIN PRZYCISKU DO ZAPISU DANYCH
  DDRC.3 = 0;
  PORTC.3 = 1;
  // PIN PRZYCISKU DO ODTWARZANIA DANYCH
  DDRC.2 = 0;
  PORTC.2 = 1;
  // DIODA LED DO ZAPISU DANYCH
  DDRC.1 = 1;
  PORTC.1 = 0;
  // DIODA LED DO ODTWARZANIA DANYCH
  DDRC.0 = 1;
  PORTC.0 = 0;
  // ***********************************************************************************
  // **** INICJALIZACJA PROGRAMU
  // ***********************************************************************************
  // SKASOWANIE PAMICI NA DANE
  for (trk = 0; trk < 1440; trk++) {
    track[trk] = 0;
  }
  // RESET ZMIENNYCH
  mode = 0;
  skip = 0;
  // ***********************************************************************************
  // **** GWNA PTLA PROGRAMU
  // ***********************************************************************************
  while (1) {
    // ***********************************************************************************
    // **** PRZYCISKI ZMIANY TRYBU
    // ***********************************************************************************
    // TRYB ZAPISU = 1
    if (PINC.3 == 0) {
      trk = 0;
      mode = 1;
      PORTC.1 = 1;
      PORTC.0 = 0;
    }
    // TRYB ODTWARZANIA = 2
    if (PINC.2 == 0) {
      trk = 0;
      mode = 2;
      PORTC.1 = 0;
      PORTC.0 = 1;
    }
    // ***********************************************************************************
    // **** DIODY LED STANU
    // ***********************************************************************************
    // TRYB BEZCZYNNOCI
    if (mode == 0) {
      PORTC.1 = 0;
      PORTC.0 = 0;
    }
    // TRYB ZAPISU
    if (mode == 1) {
      PORTC.1 = 1;
      PORTC.0 = 0;
    }
    // TRYB ODTWARZANIA
    if (mode == 2) {
      PORTC.1 = 0;
      PORTC.0 = 1;
    }
    // ***********************************************************************************
    // **** TRYB 1 : ZAPIS (1440/80) = 18 PUNKTW DO PAMICI
    // ***********************************************************************************
    if (mode == 1) {
      // ODCZYT DANYCH GPGGA Z GPS
      GPSREAD();
      // ZAPIS DO 20. PUNKTU
      skip++;
      if (skip == 20){
        skip = 0;
        // WYSANIE BIECYCH DANYCH GPGGA NA PORT USART
        DATSEND('$');
        DATSEND('G');
        DATSEND('P');
        DATSEND('G');
        DATSEND('G');
        DATSEND('A');
        DATSEND(',');
        for (ctr = 0; ctr < 80; ctr++) {
          DATSEND(gpgga[ctr]);
        }
        DATSEND(13);
        // ZAPISANIE DANYCH GPGGA W PAMICI
        for (ctr = 0; ctr < 80; ctr++) {
          track[ctr+trk] = gpgga[ctr];
        }
        // ZWIKSZENIE WSKANIKA PAMICI
        trk = trk + 80;
        // ZATRZYMANIE REJESTROWANIA PO ZAPENIENIU PAMICI
        if (trk > 1440) mode = 0;
      }
    }
    // ***********************************************************************************
    // **** TRYB 2 : WYSANIE 18 PUNKTW PRZEZ PORT USART
    // ***********************************************************************************
    if (mode == 2) {
      // WYSANIE WSZYSTKICH 18 PUNKTW
      for (trk = 0; trk < 1440; trk = trk + 80) {
        // UTWORZENIE CIGU DANYCH GPGGA
        DATSEND('$');
        DATSEND('G');
        DATSEND('P');
        DATSEND('G');
        DATSEND('G');
        DATSEND('A');
        DATSEND(',');
        for (ctr = 0; ctr < 80; ctr++) {
          DATSEND(track[ctr+trk]);
        }
        DATSEND(13);
      }
      // KONIEC PAMICI
      mode = 0;
    }
    // KONIEC GWNEJ PTLI
  }
}
