/*******
DCF kódolás

1-16 ---
17-19 - 0
20      1 Perc kezdet
21-27   perc (BCD) 21:1, 22:2, 23:4, 24:8, 25:10, 26:20, 27:40    
28      páros paritásbit a 21-27-re.
29-34   óra (BCD) 29:1, 30:2, 31:4, 32:8, 33:10, 34:20 
35      Páros paritásbit a 29-34-re.
36-41   a hónap napja (BCD) 36:1, 37:2, 38:4, 39:8, 40:10, 41:20
42-44   a hét napja (BCD) 42:1, 43:2, 44:4
45-49   melyik hónap (BCD) 45:1, 46:2, 47:4, 48:8, 49:10
50-57   év utolsó két számjegye (BCD) 50:1, 51:2, 52:4, 53:8, 54:10, 55:20, 56:40, 57:80
58      páros paritás a 36-57-re
59      NINCS JEL, perc szinkron


kimenet:
18 * 0 bit  
a maradék 40 bit (5 byte) időadat 1996.09.16 9:16 ... az eepromból
96.09.16 09:16
            PERC                ÓRA                NAP            HétNa  HÓNAP      ÉV
          1 2 4 8 10 20 40      1 2 4 8 10 20      1 2 4 8 10 20  1 2 4  1 2 4 8 10 1 2 4 8 10 20 40 80
bit   20                   28                 35                 42     45         50                   58 
16  0  1  0 1 1 0  1  0  0  1   1 0 0 1  0  0  0   0 1 1 0  1  0  1 0 0  1 0 0 1  0 0 1 1 0  1  0  0  1  0
17  0  1  1 1 1 0  1  0  0  0   1 0 0 1  0  0  0   0 1 1 0  1  0  1 0 0  1 0 0 1  0 0 1 1 0  1  0  0  1  0  
18  0  1  0 0 0 1  1  0  0  0   1 0 0 1  0  0  0   0 1 1 0  1  0  1 0 0  1 0 0 1  0 0 1 1 0  1  0  0  1  0
19  0  1  1 0 0 1  1  0  0  1   1 0 0 1  0  0  0   0 1 1 0  1  0  1 0 0  1 0 0 1  0 0 1 1 0  1  0  0  1  0
20  0  1  0 0 0 0  0  1  0  0   1 0 0 1  0  0  0   0 1 1 0  1  0  1 0 0  1 0 0 1  0 0 1 1 0  1  0  0  1  0 <- PERC PARITÁS HIBÁS
21  0  1  1 0 0 0  0  1  0  0   1 0 0 1  0  0  0   0 1 1 0  1  0  1 0 0  1 0 0 1  0 0 1 1 0  1  0  0  1  0
22  0  0  0 1 0 0  0  1  0  0   1 0 0 1  0  0  0   0 1 1 0  1  0  1 0 0  1 0 0 1  0 0 1 1 0  1  0  0  1  0 <- START BIT HIÁNYZIK
23  0  1  1 1 0 0  0  1  0  1   1 0 0 1  0  0  0   0 1 1 0  1  0  1 0 0  1 0 0 1  0 0 1 1 0  1  0  0  1  0
24  0  1  0 0 1 0  0  1  0  0   1 0 0 1  0  0  1   0 1 1 0  1  0  1 0 0  1 0 0 1  0 0 1 1 0  1  0  0  1  0 <- ORA PARITÁS HIBÁS
25  0  1  1 0 1 0  0  1  0  1   1 0 0 1  0  0  0   0 1 1 0  1  0  1 0 0  1 0 0 1  0 0 1 1 0  1  0  0  1  0
26  0  1  0 1 1 0  0  1  0  1   1 0 0 1  0  0  0   0 1 1 0  1  0  1 0 0  1 0 0 1  0 0 1 1 0  1  0  0  1  0
27  0  1  1 1 1 0  0  1  0  0   1 0 0 1  0  0  0   0 1 1 0  1  0  1 0 0  1 0 0 1  0 0 1 1 0  1  0  0  1  1 <- DÁTUM PARITÁS HIBÁS
28  0  1  0 0 0 1  0  1  0  0   1 0 0 1  0  0  0   0 1 1 0  1  0  1 0 0  1 0 0 1  0 0 1 1 0  1  0  0  1  0
29  0  1  1 0 0 1  0  1  0  1   1 0 0 1  0  0  0   0 1 1 0  1  0  1 0 0  1 0 0 1  0 0 1 1 0  1  0  0  1  0
30  0  1  0 0 0 0  1  1  0  0   1 0 0 1  0  0  0   0 1 1 0  1  0  1 0 0  1 0 0 1  0 0 1 1 0  1  0  0  1  0

16  01011010 01100100 00110101 00100100 11010010   -  5A, 64, 35, 24, D2
17  01111010 00100100 00110101 00100100 11010010   -  7A, 24, 35, 24, D2
18  01000110 00100100 00110101 00100100 11010010   -  46, 24, 35, 24, D2
19  01100110 01100100 00110101 00100100 11010010   -  66, 64, 35, 24, D2
20  01000001 00100100 00110101 00100100 11010010   -  41, 24, 35, 24, D2
21  01100001 00100100 00110101 00100100 11010010   -  61, 24, 35, 24, D2
22  00010001 00100100 00110101 00100100 11010010   -  11, 24, 35, 24, D2
23  01110001 01100100 00110101 00100100 11010010   -  71, 64, 35, 24, D2
24  01001001 00100100 10110101 00100100 11010010   -  49, 24, B5, 24, D2
25  01101001 01100100 00110101 00100100 11010010   -  69, 64, 35, 24, D2
26  01011001 01100100 00110101 00100100 11010010   -  59, 64, 35, 24, D2
27  01111001 00100100 00110101 00100100 11010011   -  79, 24, 35, 24, D3
28  01000101 00100100 00110101 00100100 11010010   -  45, 24, 35, 24, D2
29  01100101 01100100 00110101 00100100 11010010   -  65, 64, 35, 24, D2
30  01000011 00100100 00110101 00100100 11010010   -  43, 24, 35, 24, D2   
*/

#include <12F629.h>

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES HS                       //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOCPD                    //No EE protection
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NOMCLR                   //Master Clear pin used for I/O
#FUSES PUT                      //Power Up Timer
#FUSES BROWNOUT                 //Reset when brownout detected
#FUSES RESERVED                 //Used to set the reserved FUSE bits

#use delay(clock=20000000)


#define DCF_LED         PIN_A0
#define DCF_INV_LED     PIN_A1

#define XTAL_FREQUENCY  20000000
#define TIMER1_FREQUENCY (XTAL_FREQUENCY / 4)      // clock

#define ROM_ADDRESS  getenv("EEPROM_ADDRESS")

// eeprom tartalom
#rom ROM_ADDRESS      = { 0x5A, 0x64, 0x35, 0x24, 0xD2 }       // 16
#rom ROM_ADDRESS + 5  = { 0x7A, 0x24, 0x35, 0x24, 0xD2 }       // 17
#rom ROM_ADDRESS + 10 = { 0x46, 0x24, 0x35, 0x24, 0xD2 }       // 18
#rom ROM_ADDRESS + 15 = { 0x66, 0x64, 0x35, 0x24, 0xD2 }       // 19
#rom ROM_ADDRESS + 20 = { 0x41, 0x24, 0x35, 0x24, 0xD2 }       // 20 <- PERC CRC
#rom ROM_ADDRESS + 25 = { 0x61, 0x24, 0x35, 0x24, 0xD2 }       // 21
#rom ROM_ADDRESS + 30 = { 0x11, 0x24, 0x35, 0x24, 0xD2 }       // 22 <- START BIT
#rom ROM_ADDRESS + 35 = { 0x71, 0x64, 0x35, 0x24, 0xD2 }       // 23
#rom ROM_ADDRESS + 40 = { 0x49, 0x24, 0xB5, 0x24, 0xD2 }       // 24 <- ORA CRC
#rom ROM_ADDRESS + 45 = { 0x69, 0x64, 0x35, 0x24, 0xD2 }       // 25
#rom ROM_ADDRESS + 50 = { 0x59, 0x64, 0x35, 0x24, 0xD2 }       // 26
#rom ROM_ADDRESS + 55 = { 0x79, 0x24, 0x35, 0x24, 0xD3 }       // 27 <- DATE CRC
#rom ROM_ADDRESS + 60 = { 0x45, 0x24, 0x35, 0x24, 0xD2 }       // 28
#rom ROM_ADDRESS + 65 = { 0x65, 0x64, 0x35, 0x24, 0xD2 }       // 29
#rom ROM_ADDRESS + 70 = { 0x43, 0x24, 0x35, 0x24, 0xD2, 0x0 }  // 30

#ZERO_RAM

int32 Ticker = 1000;

int8  bit_pos = 8;
int16 eeprom_pos = 0;
int   sec_count = 0;
int8  send_data = 0; 


/***************
* pontos 1mp-es időzítés 
***************/
#int_TIMER1
void  TIMER1_isr(void) 
{
   Ticker -= 65535;
   if ( Ticker < 65536 ) {
      Ticker += TIMER1_FREQUENCY;
      send_data = 1;                         // adatot kell küldeni
   }
}

/***************
* DCF jel a kimenetekre
***************/
void DCFSignal( int1 Value )
{
   int wait_ms;
   // kimenő impulzus indítása
   output_high( DCF_LED );
   output_low(DCF_INV_LED);
   wait_ms = ( Value == 1 ? 200 : 100 );     // impulzus szélesség beéllítása
   delay_ms( wait_ms );                      // 0 - 100ms,  1 - 200ms
   // vissza az alapállapotba
   output_low( DCF_LED );
   output_high(DCF_INV_LED);
}


/***************
* a főprogram
***************/
void main()
{
   int8 dcf_data;
   
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_comparator(NC_NC);

   // kimenetek alaphelyzetbe
   output_low( DCF_LED );
   output_high(DCF_INV_LED);

   // "kicsit" várok, hogy az óra biztosan el tudjon indulni
   // ha az óráról kapja a tápot
   delay_ms( 3000 ); 

   Ticker = TIMER1_FREQUENCY;
   setup_timer_1( T1_INTERNAL | T1_DIV_BY_1 );
   enable_interrupts( INT_TIMER1 );


   while (true) {
      bit_pos = 8;         // az aktuálisan küldendő bit 
      eeprom_pos = 0;      // az aktuális eeprom adat offsetje
      sec_count = 0;       // másodperc számláló
      send_data = 0;       // itt az idő impulzus küldésre (a timer1 állítja be)
      // az első perc első adatbyte-ja
      dcf_data = read_eeprom( eeprom_pos );
  
      enable_interrupts( GLOBAL );
      
      while( dcf_data > 0 ) {                // az eeprom utolsó dcf adatbyte után 0x00 van
         if (send_data == 1) {               // adatot kell küldeni
            send_data = 0;                   // feldolgozás folyamatban
            if ( sec_count < 59 ) {          // az utolsó másodperc 59. a perc szinkron, ott nincs dolga   
               // az első 18 bit a tesztelés szempontjából nem tartalmaz érdemi információt, 0
               if ( sec_count < 19 ) {       // 18 * 0 bit, ezekkel most nem foglalkozunk
                  DCFSignal( 0 );
               } else {                      // a 19. bit-től kezdődően vannak az adatok az eepromban
                  // DCF impulzus küldése
                  DCFSignal( bit_test( dcf_data, --bit_pos ) );
                  if (bit_pos == 0 ) {       // ha már minden bit kiment
                     bit_pos = 8;            // a következő byte beolvasása az eepromból
                     dcf_data = read_eeprom( ++eeprom_pos );
                  }
               }
               sec_count++;                  // másodperc számláló léptetése
            } else {
               sec_count = 0;                // innen nincs dolgunk, a következő már az új perc lesz
            }
         }
      }

      // kicsit várunk mielőtt újraindul az egész,
      // addig ne ketyegjen
      disable_interrupts( GLOBAL );
      // kimenetek alaphelyzetbe (elvileg úgy is vannak, de itt nagyon ráér....
      output_low( DCF_LED );
      output_high(DCF_INV_LED);
      delay_ms( 20000 );                     // 20 mp várakozás, és kezdődik előlről
   }   
}
