///////////////////////////////////////////////////////////////////////
////                          propklok.C
//// Version: 0.99
//// pic: 16F628
////
//// Date: 3-1-2002
////
////
///////////////////////////////////////////////////////////////////////


#include <16F628.H>
#fuses HS, NOPROTECT, PUT, NOWDT, NOBROWNOUT, NOLVP,NOMCLR


#use delay(clock=16000000)
#use rs232( baud=9600, xmit=PIN_A2, rcv=PIN_A3)
#use i2c(master,sda=PIN_A1,scl=PIN_A4)

#define dcf_data pin_A5
#define hal pin_A0

#include <input.c>

CONST unsigned int dt[12][5]={
{0x3E,0x41,0x41,0x41,0x3E}, // 0
{0x00,0x21,0x7F,0x01,0x00}, // 1
{0x21,0x43,0x45,0x49,0x31}, // 2
{0x42,0x41,0x51,0x69,0x46}, // 3
{0x0C,0x14,0x24,0x7F,0x04}, // 4
{0x72,0x51,0x51,0x51,0x4E}, // 5
{0x1E,0x29,0x49,0x49,0x06}, // 6
{0x40,0x47,0x48,0x50,0x60}, // 7
{0x36,0x49,0x49,0x49,0x36}, // 8
{0x30,0x49,0x49,0x4A,0x3C}, // 9
{0x00,0x00,0x36,0x00,0x00}, // :
{0x00,0x00,0x16,0x00,0x00}}; // .


int led6 [7];
int const bcd[7] = {1,2,4,8,10,20,40}; // bcd code
int const steptab[8] = {0,1,6,2,3,6,4,5}; // hh:mm:ss


int1 running;
int dcf_ms,
    dcf_timeline,
	 dcf_hour,
	 dcf_min,
	 dcf_bit,
	 chget,
	 s,m,h,   // I2c time
	 y,x,hour,minute;


/*****************************************************************************
 *  byte  decD2hexD( byte value);
 *
 *  Description : Converts the given value Decimal Digits to Hexidecimal
 *                digits (bcd format, for example: 99D => 99H).
 *  Arguments   : value   - to be converted
 *  Returns     : byte    - converted value.
 */
byte decD2hexD( byte value)
{
  return ( value%10 + 16 * (value/10));
}

/****************************************************************************
 *  byte  hexD2decD( byte value);
 *
 *  Description : Converts the given value Hexadecimal Digits to Decimal
 *                digits (bcd format, for example: 99H => 99D).
 *  Arguments   : value   - to be converted
 *  Returns     : byte    - converted value.
 */
byte hexD2decD( byte value)
{
  return ( value%16 + 10 * (value/16));
}

void Gettime ()
  {
    Byte Wm, Yd;
    i2c_start();                         //   generate start
    i2c_write(0xA0);                     //   write addres of PCF8583
    i2c_write(0x2);                      //   select second register
    i2c_start();                         //   generate repeated start
    i2c_write(0xA1);                     //   write address for reading info
    S =  i2c_read();                     //   read seconds
    M =  i2c_read();                     //   read minuts
    H =  i2c_read();                     //   read hours
    Yd =  i2c_read();                     //   read year and days
    Wm = i2c_read(0);                    //   read weekday and month
    i2c_stop();                          //   generate stop
  }

void Settime(byte s,byte M,byte H,byte D, byte Month)
  {
    i2c_start();                         //  generate start
    i2c_write(0xA0);                     //  write address
    i2c_write(0x0);                      //  select control register
    i2c_write(0x8);                      //  set year and day bit for masking
    i2c_stop();                          //  generate stop

    i2c_start();                         //  generate start
    i2c_write(0xA0);                     //  write mode
    i2c_write(0x2);                      //  select seconds Register
    i2c_write(S);                        //  write seconds
    i2c_write(M);                        //  write minuts
    i2c_write(H);                        //  write hours
    i2c_write(D);                        //  write days
    i2c_write(Month);                    //  write months
    i2c_stop();
 }


#int_TIMER1												//------------irq----------------------
TIMER1_isr() {				// routine elke 0.25uS *8 (ffff-F893=1900) = 3.8mS
  if (kbhit()) {
    chget = getc();
    Gettime ();
    output_b(0);										// led's uit
    Printf("Time: %x:%x:%x 'c' to change time\n\r" ,h,m,s); // door hex notitie te gebruiken gaat BCD code goed
    if (chget == 'c') {
      printf("\r\nHour: ");
      hour = gethex();
      printf("\r\nMinute: ");
      minute = gethex();
      Settime (0,minute,hour,0,0);
    }
  }
  set_timer1(0xFFF0);    // rtc waarde 0.25uS*8*256*1900* =0.9728 sec
}


#int_TIMER2												//------------irq----------------------
TIMER2_isr() {								// routine elke 0.25uS *div16 *91*16= = 5.8mS  }
  if (++dcf_ms == 0x00) {						// deel door 256 is 1.49S
    if (dcf_timeline == 60 ){						// received 61 char code is valid.
     Settime (0,decD2hexD(dcf_min),decD2hexD(dcf_hour),0,0);
    }
    dcf_bit = dcf_hour = dcf_min = dcf_timeline = 0; 			// overflow; dus einde timeline
  }
}



main() {
   int16 save_t1,del,over;
   int rnd,save_t2;
   int1 bitstart;
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);   // T1= Fosc/4
   setup_timer_2(T2_DIV_BY_16,0x5B,16);
   enable_interrupts(INT_TIMER1);
   enable_interrupts(INT_TIMER2);
   enable_interrupts(global);

   Printf( "Propellor Klok 2.00 DCF support\n\r" );
   dcf_timeline = dcf_bit =0;
   del= 2100;
   bitstart = false;
   output_b(0);


   do {
	  if (!input(hal)) {
	    save_t1 = get_timer1(); 			// counter: 0.25uS*8= 2uS per tel
		 set_timer1(0x00);
	    save_t2 = get_timer2();			// Save counter
		 disable_interrupts(global);
       for (y=0; y<8; y++) {  				// 8 karakters breed hh:mm:ss
    	   for (x=0; x<5; x++) {			// breedte 5 teller
	        output_b(dt[led6[steptab[y]]][x] );     // schrijf led's
	        delay_us(del);
		     }
			if (y==3) led6[6] = 10;			// dubble punt terugzetten
			output_b(0);
		   delay_us(del);				// 200tussen de karakters
	    }
	    set_timer2(save_t2);				// Restore counter
		 enable_interrupts(global);
	    if (++rnd%16==0) del = ((save_t1-2000) / 180);	// counter: 0.25uS*8= 2uS per tel
																		// een maal in de x ronde wordt nieuwe delay berekend
       Gettime ();
	    led6[0] = hexD2decD(h)/10;
	    led6[1] = hexD2decD(h)%10;
	    led6[2] = hexD2decD(m)/10;
	    led6[3] = hexD2decD(m)%10;
	    led6[4] = hexD2decD(s)/10;
	    led6[5] = hexD2decD(s)%10;
	    if (input(dcf_data)) led6[6] = 11; // is de :
         else led6[6] = 10;

 	 }
    if (dcf_timeline == 30) dcf_bit = 0;     // counter for the hours
	 if (input(dcf_data)){								// rising bit start timer dcf_ms
	   if (!bitstart) dcf_ms = 0;
 	   bitstart = true;
	 }
 	 if (dcf_ms == 42) bitstart = false;		// bit cannot exeed 42 (42*5.6mS= 244mS)
	 if (dcf_ms == 25){								// sample the bit at 145mS
		if (++dcf_timeline == (23+dcf_bit)) {  // postion 23--29 minutes
  	     if (input(dcf_data))
		    dcf_min = dcf_min + bcd[dcf_bit];  // increase with BCD array
  		  if (dcf_bit < 6) dcf_bit++;
		}
		if (dcf_timeline == (31+dcf_bit)) {    // postion 31--36 hours
  	     if (input(dcf_data))
		    dcf_hour = dcf_hour + bcd[dcf_bit];
 		  if (dcf_bit < 5) dcf_bit++;
      }
		dcf_ms++;
	 }
  } while (TRUE);
}