#include <stdio.h>
#include <string.h>
#include <at89x51.h>

#include "rll_cod.c"		/* RLL Tabellen einfuegen    */

/*-----------------------------------------------------------*/
/* Sendestatis definieren                                    */
/*-----------------------------------------------------------*/
#define SEND_IDLE	0	/* keine Sendung, kein Signal*/
#define SEND_RUN	1	/* Daten werden gesendet     */

/*-----------------------------------------------------------*/
/* Sendeleitung definieren                                   */
/*-----------------------------------------------------------*/
#define SEND_BIT	P3_0
#define SEND_ON		P1_7	/* Senderaktivierungsbit     */

bit next_bit=0;

unsigned char akt_byte;        /* Byte, das gesendet wird */
unsigned char akt_bit_pos;     /* aktuelle Bitposition    */

bit send_run=0;
bit do_flag=1;

unsigned char str[10];

long    as=0;			/* amperesekunden		*/
int	i_akt=0;
int	i_mittel=0;
int 	korrektur = 0;

/*-----------------------------------------------------------*/
/* Sendefifo behandlung                                      */
/*-----------------------------------------------------------*/
#define FIFO_MAX 32
unsigned char fifo[FIFO_MAX];
unsigned char fifo_read=0;
unsigned char fifo_write=0;
unsigned char fifo_count=0;

#include "ltc1298.c"


/*-----------------------------------------------------------*/
/* Fifo Zeichen schreiben                                    */
/*-----------------------------------------------------------*/
void write_fifo( unsigned char c)
{
while(fifo_count >= FIFO_MAX)
  ;		

fifo[fifo_write++] = c;
fifo_write &= 0x1F;
fifo_count ++;
}

/*-----------------------------------------------------------*/
/* Fifo string schreiben                                     */
/* in 3er Paeckchen im RLL Code                              */
/*-----------------------------------------------------------*/
void write_fifo_str( unsigned char *str, int count, int id)
{
char i;
unsigned char csum=0;
unsigned char csum1=0;

for(i=0;i<count;i++)
 {
  csum += str[i];
  csum1 ^= str[i];
 }
str[count++] = csum;
str[count++] = csum1;

write_fifo(rll_codes[ id ] );  		/* ID     wird direkt RLL codiert und gesendet */
write_fifo(rll_codes[ count -2 ] );	/* Anzahl wird direkt RLL codiert und gesendet */

for(i=0;i<count;i+=3)
 {
  write_fifo(rll_codes[  str[i  ]&0x3F] );
  write_fifo(rll_codes[((str[i  ]&0xC0) >> 6) | ((str[i+1]&0x0F) << 2) ] );
  write_fifo(rll_codes[((str[i+1]&0xF0) >> 4) | ((str[i+2]&0x03) << 4) ] );
  write_fifo(rll_codes[((str[i+2]&0xFC) >> 2)                          ] );
 }
}

/*-----------------------------------------------------------*/
/* Interrruptroutine fuer Timer 0 			     */
/*-----------------------------------------------------------*/
void timer0( void ) interrupt 1
{
  static char icount=0;

/*
  if(++icount < 4)
    return;
*/
  SEND_BIT = next_bit; 	/* so schnell wie moeglich           */
                    	/* Sender im Leerlauf und keine Daten vorhanden      */
  icount = 0;
  if(!send_run && fifo_count == 0)
  {
    next_bit = 0;/* !next_bit;*/  /* 1/0 Wechsel senden */
    return;     /* neu ! null in Ruhe senden		*/
  }
	/* Sender im Leerlauf, aber Zeichen vorhanden        */
  if(!send_run && fifo_count > 0)
  {	/* Aussendung Aktivieren                             */
    send_run = 1;
    akt_bit_pos=8;  /* outdated */
  }

  if(akt_bit_pos >= 8)  	/* naechstes Byte faellig ?  */
  {
    if(fifo_count > 0)
    {
      akt_byte = fifo[fifo_read++];
      fifo_read &=0x1F;
      fifo_count --;
      akt_bit_pos = 0;
    }
    else
    {
      send_run = 0;
      return;
    }
  }
  next_bit = (akt_byte & 0x01);
  akt_byte = akt_byte >> 1;
  akt_bit_pos++;
  return;
}


/*-----------------------------------------------------------*/
/* Interrruptroutine fuer Timer 1 			     */
/* 81,38 Hz -> 12.288 ms  				     */
/*-----------------------------------------------------------*/
void timer1( void ) interrupt 3
{		/* laeuft mit 81,38 Hz			     */
  static char tick=0;
  static long i_sammel=0;

  i_akt = (ad_get(3) - ad_get(2) + korrektur) * 10 / 18;
               /* Strom in 100 mA Schritten		     */
  i_sammel += i_akt;
  as= as + (long)i_akt*12288L/10000L;

  if(tick++ >= 30)
  {
    tick = 0;
    do_flag = 1;
    i_mittel = i_sammel / 30;
    i_sammel = 0;
  }
}

/*-----------------------------------------------------------*/
/* Hauptprogramm		 			     */
/*-----------------------------------------------------------*/

main()
{
  int i,j;

  SCON = 0x52;

  TMOD = 0x00 | 	/*Timer  1 auf 13 Bit   		*/ 
         0x02 ;         /* Timer 0 auf 8 Bit Reload       */


  TH1 = 0xFD;

  TH0 = -250;


  TR0 = 1;  /* Timer 0 Run Flag */

  TR1 = 1;  /* Timer 1 Run Flag */


  IE = 0x80 |    	/*gobal Int enable 		*/ 
       0x08 |		/* Timer 1 Interrupt enable */
       0x02 ;		/* Timer 0 Interrupt enable */

  IP = 0x02;		/* Timer 0 hat priotitaet (Datenausgabe)  */

  for(j=0;j<8;j++)     /* einschwingen lassen */
  {
    for(i=0;i<30000;i++);
    i = ad_get(3);
    korrektur = ad_get(2) - i;
  }

  while(1)
  {
      while(!do_flag)
        PCON |= 1;		/* set idle mode */
      do_flag = 0;

      SEND_ON = 1;

      {
        for(i=0;i<8;i++)
          write_fifo(0x55);                 /* Sync senden    */
        write_fifo(0x0F);       		  /* nutzdatenstart */

        str[1] = (i_mittel & 0xFF00) >> 8;
        str[2] = (i_mittel & 0xFF);

        i = as / 3600;  /* as in ah */

        str[3] = (i & 0xFF00) >> 8;
        str[4] = (i & 0xFF);

        str[0] = 0x03 | (P1 & 0xFC);
        write_fifo_str(str,5,1);
        write_fifo(0x55);
      }

      while(fifo_count);	/* erst fifo leerlaufen lassen  */
      while(send_run);		/* jetzt noch bits rauslaufen lassen */

      SEND_ON = 0;

      if(!P1_2) 		/* Nulltaste gedrueckt */
      {
        i = ad_get(3);
        korrektur = ad_get(2) - i;
        as = 0;
      }
  }
}


