/* INCLUSION OF FILES */

#include <AT892051.H>
#include <intrins.h>  /* for _nop_ */

/* GENERAL CONSTANTS */
#define FALSE          0x00
#define TRUE           0x01
#define ACTIVE         0x00
#define NOT_ACTIVE     0x01
#define pa_delay         50  
#define trx_delay        50
#define RUNNING           1
#define ELAPSED           0
#define NOT_STARTED       2 
#define TIMER0_COUNT   0xDBFF  
/* 0xDBFF (9216 cycles met 11.0592 MHz Xtal, timer0 16 bit) -> 10 ms interrupt */
/* reload value is 65535 - 9216 = 56319 = 0xDBFF */

/* bits used for the I/O ports */
sbit cw_out     = P3^2;
sbit trx_out    = P3^3;
sbit pa_out     = P3^4;
sbit relais_out = P3^5;
sbit tune_in    = P3^7;

sbit pttExt_in  = P1^4;
sbit cw_in      = P1^5;
sbit pttWinK_in = P1^6;
sbit spare      = P1^7;
sbit delay_in0  = P1^3;
sbit delay_in1  = P1^0;
sbit delay_in2  = P1^2;
sbit delay_in3  = P1^1;
                                       
/* Global variable declarations */
bit tune;
bit pttExt;
bit cw;
bit pttWinK;
bit goon;
unsigned int timer0_tick;
unsigned int timer0_count;
unsigned int vox_delay_array[] = {15,20,25,30,35,40,45,50,55,60,65,70}; /* 10 ms unit ! */
unsigned int vox_delay;

/* forward declarations */
void CheckInputs (void);
void delay_10us(void);
void delay_1ms (int nr);
void Go2Tx (void);
void Go2Rx (void);
unsigned int read_vox_delay (void);
void vox_delay_timer_start  (void);
unsigned char  vox_delay_timer_status (unsigned int vox_delay_timer);
void timer_10ms_start (void);


void delay_10us(void)
{
  _nop_(); 
}

void delay_1ms (int nr)  
{
 unsigned char s;
 int r;
 for (r = 0; r < nr; r++)
 {
    for (s = 0; s < 150; s++)   /* approx 1 ms using 11.0592 Xtal */
    {
      _nop_(); _nop_(); _nop_();
    }
  }  
}


void CheckInputs (void)
{
  char LoopCounter;
  char tuneCounter;
  char cwCounter;
  char pttExtCounter;
  char pttWinKCounter;
  
  tuneCounter     = 0;
  cwCounter       = 0;
  pttExtCounter   = 0;
  pttWinKCounter  = 0;
  tune            = FALSE;
  cw              = FALSE;
  pttExt          = FALSE;
  pttWinK         = FALSE;
  
  for (LoopCounter = 0; LoopCounter < 5 ; LoopCounter++)
  {
    if (tune_in == FALSE)
    {
      tuneCounter++;
    }
    if (cw_in == TRUE)
    {
      cwCounter++;
    }
    if (pttExt_in == TRUE)
    {
      pttExtCounter++; 
    }
    if (pttWinK_in == TRUE)
    {
      pttWinKCounter++; 
    }
  } 
  if (tuneCounter > 3) 
  { 
    tune = TRUE;
  }
  if (cwCounter > 3) 
  { 
    cw = TRUE;
  }
  if (pttExtCounter > 3) 
  { 
    pttExt = TRUE;
  }
  if (pttWinKCounter > 3) 
  { 
    pttWinK = TRUE;
  }
}  

void Go2Tx (void)
{
  relais_out = NOT_ACTIVE; /* RECEIVE = ACTIVE */
  delay_1ms(pa_delay);
  pa_out = ACTIVE;
  delay_1ms(trx_delay);
  trx_out = ACTIVE;  
}

void Go2Rx (void)
{
  trx_out = NOT_ACTIVE; 
  delay_1ms(trx_delay); 
  pa_out = NOT_ACTIVE;
  delay_1ms(pa_delay);
  relais_out = ACTIVE;   /* RECEIVE = ACTIVE */
}

/* Function read value on ports 1.0 t/m 1.3    */
/* Output: delay in 10ms units, using vox_delay_array      */
unsigned int read_vox_delay(void)     
{
  unsigned int vox_delay_10ms;
  unsigned char vox_delay_input;
  vox_delay_input = 0;                      /* read bits 0 t/m 3, add vox_delay_array value  */
  if (delay_in0 == 0) 
    vox_delay_input = vox_delay_input + 1;
  if (delay_in1 == 0) 
    vox_delay_input = vox_delay_input + 2;
  if (delay_in2 == 0) 
    vox_delay_input = vox_delay_input + 4;
  if (delay_in3 == 0) 
    vox_delay_input = vox_delay_input + 8;
  if (vox_delay_input > 11)                  /* check for value above 11 (12 position switch)  */
    vox_delay_input = 11;
  vox_delay_10ms = vox_delay_array[vox_delay_input]; /* select corresponding value from tabel */
  return(vox_delay_10ms);
}

/* Procedure start de vox_timer             */
void vox_delay_timer_start (void)
{
  EA = 0;  /* disable all interrupts */
  timer0_tick = 0;
  timer_10ms_start();
}
  
/*Procedure start de 10 ms timer */
void timer_10ms_start (void)
{
  EA = 0;  /* disable all interrupts */
  TR0 = 0 ;/* stop timer 0*/
  TMOD &= ~0x0F; /* clear timer 0 mode bits */
  TMOD |= 0x01; /* timer 0 in mode 1, 16 bits */
  TL0 = (TIMER0_COUNT & 0x00FF);
  TH0 = (TIMER0_COUNT >> 8);
  PT0 = 1; /*set high priority for timer 0*/
  ET0 = 1; /*enable timer 0*/
  TR0 = 1; /* start timer 0*/
  EA = 1; /*enable interrupts*/
}

/* functie provides status of vox_delay_timer */
/* Output: RUNNING or ELAPSED                               */
unsigned char vox_delay_timer_status (unsigned int vox_delay_timer)
{
  EA = 0;                                   /*disable interrupts */
  if (timer0_tick >= vox_delay_timer)
  {
    TR0 = 0 ;                               /* stop timer 0 */
    timer0_tick = vox_delay_timer;          /* force timer to end value */
    EA = 1;                                 /* enable other interrupts */
    return(ELAPSED);                        /* and return ELAPSED */
  }
  else
  {
    if (TR0 == 0)                           /* timer not started yet */
      return(NOT_STARTED);
    else
    {
      EA = 1; /* enable interrupts */
      return(RUNNING);  /* and return RUNNING */
    }
  }
}


void timer0_ISR (void) interrupt 1
{
  TR0 = 0; /* stop timer 0 */  
  TL0 = (TIMER0_COUNT & 0x00FF);
  TH0 = (TIMER0_COUNT >> 8);
  timer0_tick++;
  if (timer0_tick == 65535) /* make sure no overflow can occur */
     timer0_tick = 65534;
  TR0 = 1; /*start timer 0 */ 
}

void Main (void)
{
  trx_out = NOT_ACTIVE; 
  pa_out = NOT_ACTIVE;
  relais_out = ACTIVE; /* RECEIVE = ACTIVE */
  spare = FALSE;
  while (TRUE)
  {
    if (spare == FALSE)
     spare =  TRUE;
    else
     spare = FALSE;  /* used for test purposes: square wave on output pin SPARE */
    delay_10us();
    CheckInputs();
    if (tune == TRUE || pttWinK == TRUE || pttExt == TRUE || cw == TRUE )
    {
      vox_delay = read_vox_delay();   /* read vox delay from p1.0 t/m p1.3 and converted to ms*/
      if (cw == TRUE)
      {
        vox_delay_timer_start();    /* start voxdelay if CW input */
      }
      Go2Tx();
      goon = TRUE;
      while (goon)
      {
        CheckInputs();
        if (cw == TRUE)               /* read CW input */
        {
          cw_out = ACTIVE;            /* CW input is key down -> CW output becomes actief and */
          vox_delay_timer_start();    /* restart vox delay timer for first time t */
        } 
        else
        {
          if (tune == TRUE)           /* read tune input */
            cw_out = ACTIVE;          /* tune input is actief -> CW output becomes actief */
          else
          {
            cw_out = NOT_ACTIVE;      /*CW input is key_up -> CW output not actief and no restart of  vox_timer and will elapse*/      
            if (pttExt != TRUE)
              if (pttWinK !=TRUE)
                if  (vox_delay_timer_status(vox_delay) != RUNNING)
                  goon = FALSE; 
          }
        } 
      }
      Go2Rx();
    }    
  }  
}  

