//**********************************************************************
//            program pro rizeni TRXu
//**********************************************************************
// (c) OK1XGL 2005
// verze 1.0.0 - uvodni verze
// verze 1.0.1 - prechod 16F877 a usazeni sibnalu na porty
// verze 1.0.2 = odladeni zakladnich funkci - muzeme delat tistak
// verze 1.0.3 - definitivni usazeni signalu - hotovy DPS
// verze 1.0.4 - prvni pouzitelna verze
// verze 1.1.0 - SIGNAL ATN1 PRESUNUT NA RE0 A SIGNAL ATN2 PRESUNUT NA RC0 !!!!!
// verze 1.2.0 - doprobramovan jednopakovy klic
// verze 1.3.0 - elbug zmenen na dvoupakovy a cely presunut do preruseni
// verze 1.4.0 - po zapnuti se RX naladi na QRP kmitocet na danem pasmu
//             - PSV se povazuje za platne jen kdyz je skutecne zaklicovano
// verze 1.5.0 - upraven zpusob cteni dat z AD prevodniku
//             - pwm rozsirena na 157 kroku
//             - doplneno ALC pro vykon a nastaveni vykonu v 0.5W jednotkach
// verze 1.6.0 - provedena kalibrace S-metru


// Poznamky:
// zobrazeni kmitoctu na LCD trva 30ms !!!
// pri rychlosti klicovani 200zn/s je sirka impulzu (tecka) cca 30ms
// timer2 vyhrazen na generovani tonu a ma nastaven kmitocet 800Hz, ton se generuje PWM, rizeni vykonu tez PWM 800Hz je baze
// timer 1 vyhrazen pro elbug


//DODELAT: - pri BK provozu je treba, aby se pri prepnuti na prjem mezi elementy znacky nezobrazoval S-metr, protoze
//           se to tak rychle nestiha zobrazovat a je lepsi,aby se zobrazovalo stale psv a vykon. Nyni je toho dosazeno tak,
//           ze pokud je aktivni elbug, tak se zobrazeni nedela ovsem toto reseni nebude fungovat pri externim elbugu
//           spravne reseni je timerem, ktery bude vykryvat cas mezi znackami
//         - projit kod a nektere veci ucesat



#include "vfo.h"
#include <lcd.c>


//#define  ADC_LCD             // misto obvyklych udaju zobrazuje hodnoty AD prevodniku
//#define  NO_FILTER_CONTROL     // vyrazuje prubeznou kontrolu pritomnosti filtru pro prislusne pasmo


/////////// FUNKCE PRO ZOBRAZOVANI NA LCD /////////

// podpora zobrazeni RIT
// POZOR: pred pouzitim je nutno vynulovat promennou lcd_pos !!!
void rit_lcd_putc(int8 c)
{
 lcd_pos++;
 if(lcd_pos==2) lcd_putc('.');  // prida tecku za KHZ
 lcd_putc(c);
} // rit_lcd_putc



// podpora zobrazeni kmitoctu VFO
// POZOR: pred pouzitim je nutno vynulovat promennou lcd_pos !!!
void vfo_lcd_putc(int8 c)
{
  lcd_pos++;
  // za MHz dopln pismenko VFO
  if(lcd_pos==3)
   if(vfo_index)
     if(bit_test(_SPLIT)) lcd_putc('\21');   // vyplnene  b
     else lcd_putc('b');
   else if(bit_test(_SPLIT)) lcd_putc('\22'); // vyplnene a
        else lcd_putc('a');
   // za KHz dopln tecku
   if(lcd_pos==6)
      if(step_index) lcd_putc(':');            // hrube ladeni
      else lcd_putc('.');                      // jemne ladeni
  lcd_putc(c);
} //vfo_lcd_putc


// podpora zobrazeni vykonu a psv
// POZOR: pred pouzitim je nutno vynulovat promennou lcd_pos !!!
void pwr_lcd_putc(int8 c)
{
  lcd_pos++;
  if(lcd_pos==2) lcd_putc('.');
  lcd_putc(c);
} // pwr_lcd_putc



// podpora zobrazeni napeti baterie
// POZOR: pred pouzitim je nutno vynulovat promennou lcd_pos !!!
void batt_lcd_putc(int8 c)
{
  lcd_pos++;
  if(lcd_pos==3) lcd_putc('.');
  lcd_putc(c);
} // batt_lcd_putc




/////////// FUNKCE PRO PRACI S DDS /////////

// odesle 16 bitovy zaznam do DDS
//
void dds_send(int16 record)
{
 int8 i;
#use fast_io(A)
#use fast_io(B)
#use fast_io(C)
#use fast_io(D)

  output_low(DDS_FSYNC);               // zacatek komunikace s DDS
  i=16;
  do
  {
   if(bit_test(record,15)) output_high(DDS_SDATA); // vystav datovy bit, zaciname MSB
    else output_low(DDS_SDATA);
   output_low(DDS_SCK);                // hodinovy impulz
   output_high(DDS_SCK);
   record=record<<1;                   // na dalsi bit
  } while(--i);

  output_high(DDS_FSYNC);              // konec komunikace s DDS
#use standard_io(A)
#use standard_io(B)
#use standard_io(C)
#use standard_io(D)
} // dds_send




// naplni registr0  pro kmitocet v DDS (28 bitu)
//
void dds_freq0(int32 freq)
{
  int16 record;

  // posli ridici slovo
  dds_send(CTRL_FREQ0);

  // zapis pozadovane frekvence
  // zapis LSB
  record=(int16)freq;
  bit_set(record,14);             // zapis do frekvencniho registru 0
  bit_clear(record,15);
  dds_send(record);
  // zapis MSB
  record=(int16)((freq<<2)>>16);  // divny zapis, ale >> 14 dava hrozny vysledek
  bit_set(record,14);             // zapis do frekvencniho registru 0
  bit_clear(record,15);
  dds_send(record);
} // dds_freq0



/////////// FUNKCE PRO RIZENI PRIPOSLECHU /////////

// vypne generovani tonu priposlechu
//
#inline
void tone_off()
{
 int8 a;
  a=input(TONE);
} // tone_off()



// zapne generovani tonu priposlechu
//
#inline
void tone_on()
{
  output_low(TONE);
} // tone_on




/////////////////////////////////
//   Prerusovaci rutiny
/////////////////////////////////
// rezie preruseni je cca 30+30 cyklu

// preruseni od zmeny polohy kroutitka
#int_EXT
void Encoder_handler()
{
#use fast_io(a)
#use fast_io(b)
#use fast_io(c)
#use fast_io(d)


 int1 dir;

 dir=input(ENCODER_DIR);             // zapamatuj si smer krouceni
 bit_set(_ENC_CHNG);                 // oznam zmenu polohy kroutitka
 if(dir) enc_delta++;                // pridej
 else enc_delta--;                   // uber

#use standard_io(a)
#use standard_io(b)
#use standard_io(c)
#use standard_io(d)
} // Encoder_handler



// periodicke tiky, granularita TICK_TIME
// citace/ casovace se granularitou TICK_TIME
#INT_TIMER0
void Tick_handler()
{
#use fast_io(a)
#use fast_io(b)
#use fast_io(c)
#use fast_io(d)

  set_timer0(TICK_TIME);          // znovu natahni timer

  // mereni napeti z prevodniku
  if(bit_test(_ADC_START))
  {
    read_adc(ADC_START_ONLY);     // spust prevod
    bit_clear(_ADC_START);        // priste budeme cist vysledek
  } else
    {
      adc_val=read_adc(ADC_READ_ONLY);       // vyzvedni vysledek

      if(bit_test(_KEYING))       // hodnoty vykonu aktualizuj jen pokud je zaklicovano
      {
        if(adc_ch==1) fwd_val=adc_val;
        if(adc_ch==0) rev_val=adc_val;
      }
      if(adc_ch==2) batt_val=adc_val;
      else if(adc_ch==3) smtr_val=adc_val;
      else if(adc_ch==4) bnd_val=adc_val;
      if(adc_ch>=4) adc_ch=0;     // mame 5 kanalu
       else adc_ch++;
      set_adc_channel(adc_ch);    // priste nasledujici kanal
      bit_set(_ADC_START);        // priste budeme spoustet prevod
    }

  // klicovani
  if(bit_test(_TXDELAY))          // jen pokud tx_delay vyprsel
  {
    if(!bit_test(_ELBUG_ON))
      keyer=(~input_b()) & 0b10000000;  // pokud neni zapnut elbug, zavzorkuj stav klice

    if((keyer!=0 && !bit_test(_ELBUG_ON)) ||            // pri vypnutem elbugu rizeno stavem pak
       (bit_test(_ELBUG_OUT) && bit_test(_ELBUG_ON)))   // pri zapnutem elbugu rizeno stavem _ELBUG_ON
     {
       // zaklicuj
       output_high(KEYING);
       tone_on();
       bit_clear(_RUN_VOX);
       bit_set(_KEYING);
       adc_ch=0;                   // zacneme merit dopredny vykon
       set_adc_channel(adc_ch);
       bit_set(_ADC_START);        // priste spustime prevod ADC
     } else
       {
         // prestan klicovat
         output_low(KEYING);
         vox_timer=vox_time;        // natahni vox_timer
         bit_set(_RUN_VOX);
         tone_off();
         bit_clear(_KEYING);
       }
    bit_clear(_TXDELAY);
  }


  // periodicky timer na aktualizaci kde ceho
  if(update_timer==0xFF) update_timer=UPDATE_TIME;
  else update_timer--;

  // vox timer
  if(bit_test(_RUN_VOX))
   if(vox_timer!=0) vox_timer--;
   else
   {
     // vox vyprsel
     bit_clear(_RUN_VOX);
     output_low(RXTX);          // prepni zpet na prijem
     bit_clear(_TRANSMIT);
     bit_set(_DDS_UPDATE);
   }

  // timer pro zjisteni dlouheho stisku tlacitek
  if(key_timer!=0) key_timer--;


  // periodicke cteni tlacitek
  #use fast_io(C)
  keys_work=(~input_c()) & KEY_MASK;               // precti stav tlacitek
  #use standard_io(C)
  if(keys_work!=keys_old) keys_old=keys_work;      // neshoda zapamatuj si novy stav
  else
  {
    // shoda
    if(keys_work!=0)
    {
      // tlacitko je STISKNUTO
      if(keys==0)
      {
        // akceptujeme jen pokud bylo zpracovano vse predchozi
        keys=keys_work;                // zapamatuj si nove tlacitko
        key_timer=KEY_LONG;            // natahni casovac pro zjisteni dlouheho stisku
      } else
        {
          // neco je jeste ke zpracovani
          if(key_timer==0 && !bit_test(_KEYS_RELEASE))
          {
            // jde o dlouhy stisk tlacitka
            bit_set(_KEYS_LONG);
            bit_set(_KEYS_VALID);
          }
        }
    } else
      {
         // tlacitko je UVOLNENO
         if(key_timer!=0)
         {
           // jde o kratky stisk tlacitka
           bit_set(_KEYS_VALID);
           key_timer=0;
         } else if(bit_test(_KEYS_RELEASE))
                {
                  keys_flags=0;  // jde o klidovy stav - tlacitka zpracovana
                  keys=0;
                }
      }
  }

#use standard_io(a)
#use standard_io(b)
#use standard_io(c)
#use standard_io(d)
} // Tick_handler




// periodicke tiky kazdych 5ms
// vyuzito pro rizeli LCD_LED
//
#INT_TIMER2
void led_handler()
{
#use fast_io(a)
#use fast_io(b)
#use fast_io(c)
#use fast_io(d)


 flash_timer++;

   // rizeni LED
   // pri prijmu bez attenuatoru sviti zelena
   // pri prijmu s attenuatorem sviti zluta
   // pri vysilani sviti cervena
   // pri vybite baterii pri prijmu led blika


   if(bit_test(_TRANSMIT))
   {
     // vysilani - rozsvid cervenou LED
     if(bit_test(_LED_UPDATE)) output_high(LCD_LED1);
     else output_low(LCD_LED1);
     output_low(LCD_LED2);
   } else
     {
       if(bit_test(_BATT_LOW) && bit_test(flash_timer,7))
       {
         // zhasni led
         output_low(LCD_LED1);
         output_low(LCD_LED2);
       } else
         {
          // prijem - rozsvid zelenou nebo zlutou led
          if(bit_test(_LED_UPDATE))
          {
            output_high(LCD_LED2);
            output_low(LCD_LED1);
          } else
            {
             output_low(LCD_LED2);
             if(bit_test(_ATTN)) output_high(LCD_LED1);
             else output_low(LCD_LED1);
            }
         }
     }

   if(bit_test(_LED_UPDATE)) bit_clear(_LED_UPDATE);
   else bit_set(_LED_UPDATE);

#use standard_io(a)
#use standard_io(b)
#use standard_io(c)
#use standard_io(d)
} // led_handler




//  cteni pak, klice
#INT_RB
void paddle_handler()
{
#use fast_io(a)
#use fast_io(b)
#use fast_io(c)
#use fast_io(d)

  keyerb=(~input_b());                     // precti stav pak
  if(bit_test(_ELBUG_ON)) keyerb=keyerb & 0b11000000;    // platne jsou obe paky
  else keyerb=keyerb & 0b10000000;         // platna je paka tecek

  if(!bit_test(_TXDELAY))                  // reagujeme jen kdyz nebezi TXDELAY
  {
    if(!bit_test(_ELBUG_ON))
    {
      // RUCNI KLICOVANI
      set_timer0(TICK_TIME);               // txdelay je dano jednim zakladnim tikem, natahni tik
      _T0IF=0;
      bit_set(_TXDELAY);                   // spustime TXDELAY
    } else
      {
        // ELBUG
        // nastav priznaky pak
        if(bit_test(_ELBUG_REV))
        {
          if(bit_test(keyerb,6)) bit_set(_ELBUG_DOT);
          if(bit_test(keyerb,7)) bit_set(_ELBUG_DASH);
        } else
          {
            if(bit_test(keyerb,7)) bit_set(_ELBUG_DOT);
            if(bit_test(keyerb,6)) bit_set(_ELBUG_DASH);
          }
        if(!bit_test(_ELBUG_BSY))
        {
          // spusteni elbugu
          setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);      // spust casovac
          _TMR1IF=1;
        }
      }
    if(!bit_test(_TRANSMIT) && keyerb!=0)  // pri stisku pak prejdeme na vysilani pokud tomu jiz tak neni
    {
      bit_set(_TRANSMIT);                  // priznak stavu vysilani
      output_high(RXTX);                   // prepni TRX na vysilani
      bit_set(_DDS_UPDATE);                // nastav vysilaci kmitocet
    }
  }

#use standard_io(a)
#use standard_io(b)
#use standard_io(c)
#use standard_io(d)
} // paddle_handler



// elbug
//
#int_timer1
void elbug_handler()
{
#use fast_io(a)
#use fast_io(b)
#use fast_io(c)
#use fast_io(d)


   if(bit_test(_ELBUG_SP))
   {
     // odvysilali jsem tecku nebo carku - musime dovysilat mezeru
     bit_clear(_ELBUG_SP);               // priste budeme vysilat podle stavu pak
     bit_clear(_ELBUG_OUT);
     set_timer1(elbug_dot_sp);           // natahni casovac na mezeru
     set_timer0(TICK_TIME);              // txdelay je dano jednim zakladnim tikem, natahni tik
     _T0IF=0;
     bit_set(_TXDELAY);                  // spustime TXDELAY
     return;
   }

   if(bit_test(_ELBUG_BSY))
   {
     // odvysilali jsme posloupnost tecka-mezera nebo carka-mezera
     // nuluj priznak prave dovysilaneho elementu
     if(bit_test(_ELBUG_LAST)) bit_clear(_ELBUG_DASH);
     else bit_clear(_ELBUG_DOT);
     // dale se rozhodujeme podle stavu pak
     keyer=(~input_b()) & 0b11000000;             // precti stav pak

     // nastav priznak pak podle stisknute paky
     if(bit_test(_ELBUG_REV))
     {
       if(bit_test(keyer,6)) bit_set(_ELBUG_DOT);
       if(bit_test(keyer,7)) bit_set(_ELBUG_DASH);
     } else
       {
         if(bit_test(keyer,7)) bit_set(_ELBUG_DOT);
         if(bit_test(keyer,6)) bit_set(_ELBUG_DASH);
       }

     if(bit_test(_ELBUG_REAL) && keyer==0)        // nestisknuto nic
     {
       // pri realnem klicovani po uvolneni pak se uz dal nic nevysila
       bit_clear(_ELBUG_DOT);
       bit_clear(_ELBUG_DASH);
     }
   }

   // prepnuti na vysilani pokud tomu uz tak neni
   if(!bit_test(_TRANSMIT) &&
   (bit_test(_ELBUG_DOT) || bit_test(_ELBUG_DASH)))
   {
     bit_set(_TRANSMIT);                        // priznak stavu vysilani
     output_high(RXTX);                         // prepni TRX na vysilani
     bit_set(_DDS_UPDATE);                      // nastav vysilaci kmitocet
   }

   // nastav hodnotu casovace podle stisknute paky
   if(bit_test(_ELBUG_DOT))
   {
     if(bit_test(_ELBUG_DASH))
     {
       // stisknuty obe paky - vysilej opak priznaku LAST
       if(bit_test(_ELBUG_LAST))
       {
         bit_clear(_ELBUG_LAST);
         set_timer1(elbug_dot_sp);      // natahni casovac na tecku
       }  else
          {
            bit_set(_ELBUG_LAST);
            set_timer1(elbug_dash);     // natahni casovac na carku
          }
     } else
       {
         bit_clear(_ELBUG_LAST);
         set_timer1(elbug_dot_sp);      // natahni casovac na tecku
       }
   } else if(bit_test(_ELBUG_DASH))
          {
            bit_set(_ELBUG_LAST);
            set_timer1(elbug_dash);     // natahni casovac na carku
          } else
            {
              // NENI CO VYSILAT -KONCIME
              bit_clear(_ELBUG_BSY);
              setup_timer_1(T1_DISABLED); // zastav casovac
              return;
            }

   bit_set(_ELBUG_BSY);                // elbug bezi
   bit_set(_ELBUG_SP);                 // priste musime vysilat mezeru
   bit_set(_ELBUG_OUT);
   set_timer0(TICK_TIME);              // txdelay je dano jednim zakladnim tikem, natahni tik
   _T0IF=0;
   bit_set(_TXDELAY);                  // spustime TXDELAY

#use standard_io(a)
#use standard_io(b)
#use standard_io(c)
#use standard_io(d)
} // elbug_handler



/////////// FUNKCE PRO OVLADANI UTLUMU /////////

// natavi utlum
//
void Attn_0dB()
{
   output_low(ATN1);
   output_low(ATN2);
   output_high(ATNC);
   delay_ms(RELE_PULSE);
   input(ATNC);             // prepni ANTC zpet do tretiho stavu (vstup)
   delay_ms(RELE_PULSE);
   input(ATN1);
   input(ATN2);
}


// natavi utlum
//
void Attn_6dB()
{
   output_high(ATN1);
   output_low(ATNC);
   delay_ms(RELE_PULSE);
   input(ATNC);             // prepni ANTC zpet do tretiho stavu (vstup)
   output_low(ATN2);
   output_high(ATNC);
   delay_ms(RELE_PULSE);
   input(ATNC);             // prepni ANTC zpet do tretiho stavu (vstup)
   delay_ms(RELE_PULSE);
   input(ATN1);
   input(ATN2);
}


// natavi utlum
//
void Attn_12dB()
{
   output_low(ATN1);
   output_high(ATNC);
   delay_ms(RELE_PULSE);
   input(ATNC);             // prepni ANTC zpet do tretiho stavu (vstup)
   output_high(ATN2);
   output_low(ATNC);
   delay_ms(RELE_PULSE);
   input(ATNC);             // prepni ANTC zpet do tretiho stavu (vstup)
   delay_ms(RELE_PULSE);
   input(ATN1);
   input(ATN2);
}


// natavi utlum
//
void Attn_18dB()
{
   output_high(ATN1);
   output_high(ATN2);
   output_low(ATNC);
   delay_ms(RELE_PULSE);
   input(ATNC);             // prepni ANTC zpet do tretiho stavu (vstup)
   delay_ms(RELE_PULSE);
   input(ATN1);
   input(ATN2);
}



/*
// precte z prevodnihu hornich 8 bitu
//
int8 adc()
{
    return(read_adc()>>8) ;
} // adc
*/


/////////// FUNKCE PRO PRACI S EEPROM /////////

// aktualizuje kontrolni soucet
//
void update_eeprom()
{
  int8 i;
  int8 crc;
  crc=0;
  for(i=0;i<EE_ADR_CRC;i++) crc+=read_eeprom(i);
  crc=0-crc;
  write_eeprom(EE_ADR_CRC,crc);
} // update_eeprom



// zkontroluje obsah pameti eeprom a pokud je poskozen, nAstavi defaultni parametry
//
void check_eeprom()
{
  int8 i;
  int8 crc;

  crc=0;
  for(i=0;i<=EE_ADR_CRC;i++) crc=crc+read_eeprom(i);

  if(crc!=0)
  {
    i=EE_ADR_POWER;
    while(i<BAND_NUM) write_eeprom(i++,PAR_LIMIT[PAR_POWER][0]);   // minimalni vykon na vsech pasmech
    write_eeprom(EE_ADR_KEYER,20);                                 // nastaveno 20 WPM
    write_eeprom(EE_ADR_VOX,6);                                    // vox 300ms
    write_eeprom(EE_ADR_BATT,0);                                   // konstantni hodntota,dale se nemeni
    write_eeprom(EE_ADR_KEYER_REV,0);                              // nereverzuj paky
    write_eeprom(EE_ADR_KEYER_MODE,0);                             // doplnkove klicovani
    write_eeprom(EE_ADR_ATTN,PAR_LIMIT[PAR_VOX][0]);               // utlum vypnut
    update_eeprom();                                               // aktualizuj kontorlni soucet
  }

} // check_eeprom





/////////////////////////////////////
// VYKONNE FUNKCE HLAVNI SMYCKY
/////////////////////////////////////


// zpracovani zmeny polohy kroutitka
// trva max 600cyklu (600us)
//
// CHELO BY TO UCESAT POMOCI KONSTRUKCE IF - RETURN
#inline
void enc_chng()
{
  int32 freq_dds;
  signed int32 delta_freq;
  signed int16 delta_rit;

  if(bit_test(_MNU) || bit_test(_MNU2))
  {
    // NASTAVUJEME PARAMETRY
    if(enc_delta<ENC_HISTEREZE && enc_delta>-ENC_HISTEREZE) return;           // zmeny pod minimum si nevsimej

    if(enc_delta>0)
    {
      // nastala zmena +1
      if(bit_test(_MNU2))
      {
        if(par_index<PAR_NUM-3)
        {
          par_index++;                        // zmena typu parametru pokud projde kontrola horni meze
          bit_set(_LCD2_UPDATE);
        }
      } else if(par[par_index]<PAR_LIMIT[par_index][1])     // zmena hodnoty parametru pokud projde kontrola horni meze
             {
               par[par_index]++;
               bit_set(_PAR_UPDATE);                        // pozadavek aktualizace parametru
             }
    } else
       {
        // nastala zmena -1
        if(bit_test(_MNU2))
        {
          if(par_index>0)
          {
            par_index--; // zmena typu parametru pokud projde kontrola dolni meze
            bit_set(_LCD2_UPDATE);
          }
        } else if(par[par_index]>PAR_LIMIT[par_index][0])    // zmena hodnoty parametru pokud projde kontrola dolni meze
               {
                 par[par_index]--;
                 bit_set(_PAR_UPDATE);                       // pozadavek aktualizace parametru
               }
       }
    enc_delta=0;                                          // zmena provedena
  } else
    {
      // LADIME KMITOCET
      if(bit_test(_RIT))
      {
        // ladime RIT
        delta_rit=enc_delta*RIT_STEP;
        enc_delta=0;
        if(freq_rit+delta_rit <=RIT_LIMIT[1] &&
           freq_rit+delta_rit >=RIT_LIMIT[0]) freq_rit+=delta_rit;
      } else
        {
          // ladime VFO
          delta_freq=enc_delta*FREQ_STEP[step_index];
          enc_delta=0;
          freq_dds=freq_vfo[vfo_index]+delta_freq;
          if(freq_dds <=BAND_LIMIT[band_index][1] &&
             freq_dds >=BAND_LIMIT[band_index][0]) freq_vfo[vfo_index]+=delta_freq;
        }
      bit_set(_DDS_UPDATE);   // pozadujeme zmenu kmitoctu v DDS
    }
  bit_clear(_ENC_CHNG);   // zmena polohy kroutitka zpracovana
} // enc_chng





// aktualizuje parametry
//
#inline
void par_update()
{

// int16 power;

  bit_clear(_PAR_UPDATE);

  switch(par_index)
  {
    case PAR_ATTN:
                   bit_set(_ATTN);                         // pri utlumu bude misto zelene led svitit zluta
                   switch(par[PAR_ATTN])
                   {
                     case 1: Attn_6dB();
                             break;
                     case 2: Attn_12dB();
                             break;
                     case 3: Attn_18dB();
                             break;
                     default:Attn_0dB();
                             bit_clear(_ATTN);            // zadny utlum, zpet zelena led
                             break;
                   }
                   break;
    case PAR_POWER:
//                    set_pwm2_duty(par[PAR_POWER]);
//                    power=par[PAR_POWER];
//                    set_pwm2_duty(power<<1);
//!!!!!
                     power=par[PAR_POWER]*5;       // vykon je v nasobcich 0.5W
                    break;
    case PAR_KEYER:
                    if(par[PAR_KEYER]<=PAR_LIMIT[PAR_KEYER][0])  bit_clear(_ELBUG_ON); ///elbug_flags=0;    // vypni elbug
                      else
                      {
                        // zapni elbug a nastav rychlost
                        bit_set(_ELBUG_ON);
                        elbug_dot_sp=~(ELBUG_CONST/par[PAR_KEYER]);     // preved na hodnotu citace TMR1
                        elbug_dot_sp++;
                        elbug_dash=(elbug_dot_sp<<1)+elbug_dot_sp;      // *3, ale rychleji
                      }

                    break;
    case PAR_VOX:
                    vox_time=par[PAR_VOX];
                    if(vox_time!=0) vox_time=vox_time*10;        // cas je ve 50ms jednotkach
                     else vox_time=1;     // minimalni vox je 5ms
                    break;
   case PAR_KEYER_REV:
                    if(par[PAR_KEYER_REV]) bit_set(_ELBUG_REV);                  //
                    else bit_clear(_ELBUG_REV);
                    break;
   case PAR_KEYER_MODE:
//                    if(par[PAR_KEYER_MODE]) bit_set(_ELBUG_REAL);                 //
//                    else bit_clear(_ELBUG_REAL);
                    break;
  }
 bit_set(_LCD2_UPDATE);                                    // pozadujeme update 2. radku dispeje
} // par_update()




// aktualizuje kmitocet v dds
// trva max. cca 2500cyklu (2.5ms)
//
#inline
void dds_update()
{
  int32 freq_dds;
  signed int32 delta_freq;
  signed int32 freq_rit2;


  if(!bit_test(_TRANSMIT))
  {
    // PRIJEM
    if(band_index>=SUB_IF_INDEX) freq_dds=freq_vfo[vfo_index]-FREQ_IF;  // pri prijmu na 14MHz se odecita kmitocet mezifrekvence
    else freq_dds=freq_vfo[vfo_index]+FREQ_IF;                          // pri prijmu pod 14MHz se pricita kmitocet mezifrekvence

    if(bit_test(_RIT))
    {
       freq_rit2=freq_rit;           // prevod na signed int32, chyba v C, neumi int32 + signed int16
       freq_dds=freq_dds+freq_rit2;  // je-li zapnut RIT, udelej korekci kmitoctu
    }
    bit_set(_LCD1_UPDATE);           // pozadujeme zmenit kmitocet na lcd
  } else
    {
      // VYSILANI
      if(bit_test(_SPLIT))           // pri split se pouzije opacne vfo
      freq_dds=freq_vfo[(~vfo_index)];
      else freq_dds=freq_vfo[vfo_index];
    }

  dds_freq0((int32)((float)freq_dds*CONVERT_CONST)); // odesli jej do DDS trva to cca 2050 cylklu (2.05ms)
  bit_clear(_DDS_UPDATE);                            // kmitocet v dds zmenen
//    bit_set(_LCD1_UPDATE);                           // pozadujeme zmenit kmitocet na lcd
} // dds_update




// aktualizuje zobrazeni na lcd - 1.radek
// trva max. 3000cyklu (30ms)  !!!!!!
//
//#inline
#separate
int8 lcd1_update()
{
  int16  rit_val;

  lcd_gotoxy(1,1);
  bit_clear(_LCD1_UPDATE);

  if(bit_test(_MNU2)) printf(lcd_putc,"PARAM:   ");    // zobraz ze vybirame typ parametru
  else if(bit_test(_MNU))
       {
         // zobraz nazev parametru
         switch(par_index)
         {
           case PAR_ATTN:  printf(lcd_putc,"ATTN:   ");
                           break;
           case PAR_POWER: printf(lcd_putc,"POWER:  ");
                           break;
           case PAR_KEYER: printf(lcd_putc,"KEYER:  ");
                           break;
           case PAR_VOX:   printf(lcd_putc,"DELAY:  ");
                           break;
           case INF_BATT:  printf(lcd_putc,"BATTERY:");
                           break;
           case PAR_KEYER_MODE: printf(lcd_putc,"MODE:   ");
                           break;
           case PAR_KEYER_REV: printf(lcd_putc,"REVERSE:");
                           break;

         }
       } else if(bit_test(_RIT))
              {
                // POZN: fce printf spatne zachazi se znaminkovimi cisly, proto je znamenko
                // zobrazeno samostatne a rit je preveden na neznamenkove cislo
                printf(lcd_putc,"RIT:");
                if(freq_rit<0) lcd_putc('+');
                else lcd_putc('-');
                rit_val=abs(freq_rit);
                lcd_pos=0;
                printf(rit_lcd_putc,"%04LU",rit_val);                   // zobraz RIT na LCD
              } else
                {
                  lcd_pos=0;
                  printf(vfo_lcd_putc,"%8LD",freq_vfo[vfo_index]);   // zobraz kmitocet na LCD
                }
} // lcd1_update



// pomocna funkce pro zobrazeni vykonu a psv na lcd
//
#separate
void lcd_pwr_psv()
{
#ifdef ADC_LCD
  printf(lcd_putc,"F%2X R%2X",pwr_val,psv_val);
#else

  // vysilani - zobrazujeme vykon a psv
  if(pwr_val>99) printf(lcd_putc,">10");
  else
  {
     lcd_pos=0;
     printf(pwr_lcd_putc,"%02U",pwr_val);
  }
  printf(lcd_putc,"W ");
  if(psv_val>99) printf(lcd_putc,">10");
    else
    {
      lcd_pos=0;
      printf(pwr_lcd_putc,"%02U",psv_val);
    }
#endif
} // lcd_pwr_psv



// aktualizuje zobrazeni na lcd - 2.radek
// trva max 2000 cyklu (2ms)
//
//#inline
#separate
void lcd2_update()
{
  int8 i;
  int16 vox;
  int16 batt;

  bit_clear(_LCD2_UPDATE);
  lcd_gotoxy(1,2);

  if(bit_test(_MNU2))
  {
     // zobraz vybrany parametr
     switch(par_index)
     {
        case PAR_POWER: printf(lcd_putc,"POWER   ");
                        break;
        case PAR_VOX:   printf(lcd_putc,"DELAY   ");
                        break;
        case INF_BATT:  printf(lcd_putc,"BATTERY ");
                        break;
        case PAR_KEYER_MODE: printf(lcd_putc,"MODE    ");
                        break;
        case PAR_KEYER_REV: printf(lcd_putc,"REVERSE ");
                        break;

     }
  } else if(bit_test(_MNU))
         {
           // zobraz hodnotu parametru
           switch(par_index)
           {
             case PAR_ATTN:  printf(lcd_putc,"-%2U dB  ",par[PAR_ATTN]*6); // krok je po 6dB
                             break;
             case PAR_POWER: if(!bit_test(_TRANSMIT))
                             {
                               lcd_pos=0;
                               printf(pwr_lcd_putc,"%02UW PTT",power);     // prijem - zobraz pozadovany vykon a vyzvu k vysilani
                             } else lcd_pwr_psv();                         // vysilani - zobraz vykon a psv
                             break;
             case PAR_KEYER: if( par[PAR_KEYER]<=PAR_LIMIT[PAR_KEYER][0]) printf(lcd_putc,"OFF     ");
                             else printf(lcd_putc,"%2U      ",par[PAR_KEYER]);
                             break;
             case PAR_VOX:
                             vox=par[PAR_VOX];
                             vox=vox*50;                 // ve 50ms jednotkach
                             printf(lcd_putc,"%4LU ms  ",vox);
                             break;
             case INF_BATT:
#ifdef ADC_LCD
                             printf(lcd_putc,"%3X V   ",batt_val);
#else
                             // zobraz napeti baterie na desetiny voltu
                             batt=batt_val;
                             batt=(batt*10)/16;
                             lcd_pos=0;
                             printf(batt_lcd_putc,"%03UV    ",(int8)batt);

#endif
                             break;
             case PAR_KEYER_MODE:
                            if(par[PAR_KEYER_MODE]) printf(lcd_putc,"B       ");
                            else printf(lcd_putc,"A       ");
                            break;
             case PAR_KEYER_REV:
                            if(par[PAR_KEYER_REV]) printf(lcd_putc,"YES     ");
                            else printf(lcd_putc,"NO      ");
                            break;

           }
         } else if(bit_test(_TRANSMIT)) lcd_pwr_psv();   //  vysilani - zobraz vykon a psv
                else if(!bit_test(_ELBUG_BSY))           // v mezerach mezi znackami elbugu S-metr nezobrazuj
                     {
                       // prijem - zobrazujeme S-metr
#ifdef ADC_LCD
                       printf(lcd_putc,"SMTR:%2X ",smtr_val);
#else
                       if(smtr_val<=S_METER[0]) lcd_putc('2');
                       else lcd_putc(' ');
                       if(smtr_val<=S_METER[1]) lcd_putc('3');
                       else lcd_putc(' ');
                       if(smtr_val<=S_METER[2]) lcd_putc('4');
                       else lcd_putc(' ');
                       if(smtr_val<=S_METER[3]) lcd_putc('5');
                       else lcd_putc(' ');
                       if(smtr_val<=S_METER[4]) lcd_putc('6');
                       else lcd_putc(' ');
                       if(smtr_val<=S_METER[5]) lcd_putc('7');
                       else lcd_putc(' ');
                       if(smtr_val<=S_METER[6]) lcd_putc('8');
                       else lcd_putc(' ');
                       if(smtr_val<=S_METER[8]) lcd_putc('\23');
                       else if(smtr_val<=S_METER[7]) lcd_putc('9');
                            else lcd_putc(' ');
#endif
                      }
} // lcd2_update()




// nastavi pasmo podle pripojeneho filtru
//
//#inline
void set_band()
{
//  int8  adc_band;

  set_adc_channel (BND_CH);                          // prepni ADC na vstup signalu BAND
  delay_ms(20);

  // opakuj dokud neni pripojen vhodny filtr
  for(;;)
  {
    bnd_val=read_adc() & BAND_ADC_MASK;
    // prohlidni tabulku moznych filtru
    band_index=BAND_NUM;
    while(band_index--)
    {
      if(bnd_val==BAND_ADC[band_index]) return;           // platny filtr pritomen
    }
    printf(lcd_putc,"\rCONNECT\n");
    printf(lcd_putc," FILTER");
    delay_ms(500);
  }
} // set_band




// mereni analogovych vstupu
//
// doba trvani max 3000 cyklu  (3ms)
#separate
void analog_inputs()
{
  static int8  count;
  int16  k;
  int32  pom32,pom32_2; // pro vypocet dopredneho vykonu
  int16  pom16,pom16_2; // pro vypocet PSV
  signed int8   delta;


#ifndef NO_FILTER_CONTROL     // vyrazuje prubeznou kontrolu pritomnosti filtru pro prislusne pasmo
  if((bnd_val & BAND_ADC_MASK)!=BAND_ADC[band_index]) reset_cpu();    // fittr byl odpojen
#endif

  // mereni napeti baterie
  if(batt_val+5<=BATT_MIN) bit_set(_BATT_LOW);         // baterie je vybita

  // vypocti aktualni vykon a psv a reguluj vykon
  if(bit_test(_TRANSMIT))
  {
#ifdef ADC_LCD          // vypina zpracovani - zobrazuje prime hodnoty z prevodniku
      pwr_val=fwd_val;
      psv_val=rev_val;
#else
      // vypocti vykon na desetiny watu
      pom32=fwd_val;
      pom32=pom32*pom32;  // vykon je umerny kvadratu napeti
      // vynasobime *10 - vykon bude  100mW jednotkach
      // realizuje *10, je vyrazne casove kratsi ( o cca 500cyklu)
      pom32_2=pom32<<3;
      pom32_2=pom32_2+pom32;
      pom32_2=pom32_2+pom32;
      pwr_val=pom32_2/PWR_FWD_CONST; // vydelime kalibracni konstantou pro dopredny vykon

      // vypocti PSV na desetinu
      if(fwd_val>=0 && rev_val==0) psv_val=10; // psv je 1.0 pokud je  odrazeny vykon nulovy
      else
       {
         pom16=fwd_val;
         pom16=pom16<<4;             // vynasobime *16 pro vetsi presnost
         k=pom16/rev_val;            // pomer odpovidajici ciniteli odrazu
         if(k<=16) psv_val=250;      // PSV se blizi nekonecnu
         else if(k>337) psv_val=10;  // psv je lepsi jak 1.1 tedy ho povazujeme za 1.0
              else
              {
                // toto realizuje vyraz (k+16)*10
                pom16=k+16;
                pom16_2=pom16<<3;
                pom16_2=pom16_2+pom16;
                pom16_2=pom16_2+pom16;
                // vypocet psv
                psv_val=pom16_2/(k-16);
               }
       }

      // rizeni vykonu (ALC)
      if(psv_val>BAD_PSV) delta=PWR_LIM-pwr_val;    // pri spatnem PSV omez vykon
      else delta=power-pwr_val;
      if(delta<-PWR_HIST_HI && pwm_val>PWM_MIN)
      {
        if(delta<-10) pwm_val=pwm_val-4;
        else pwm_val--;
        pom16=pwm_val;
        set_pwm2_duty(pom16<<1);
      } else if(delta>PWR_HIST_LO && pwm_val<PWM_MAX)
             {
               if(delta>10) pwm_val=pwm_val+4;
               else pwm_val++;
               pom16=pwm_val;
               set_pwm2_duty(pom16<<1);
             }
#endif
    }

    // zobrazeni na LCD delame mene casto
    if(count>4)
    {
      bit_set(_LCD2_UPDATE);
      count=0;
    } else count++;
}// analog_inputs


/*
void pwr_control()
{
  int16 aaa;
  signed int8   delta;

  if(bit_test(_TRANSMIT))
  {
      delta=power-pwr_val;
      if(delta<-1 && pwm_val>27)
      {
        if(delta<-10) pwm_val=pwm_val-4;
        else
        pwm_val--;
        aaa=pwm_val;
        set_pwm2_duty(aaa<<1);
      } else if(delta>2 && pwm_val<157)
             {
               if(delta>10) pwm_val=pwm_val+4;
               else
               pwm_val++;
               aaa=pwm_val;
               set_pwm2_duty(aaa<<1);
             }
  }
} // pwr_control
*/




/////////////////////////////////
/////   HLAVNI FUNKCE       /////
/////////////////////////////////
void main()
{
  int8 ee_adr;

  int8 a;
  int8 b;
  signed int8 c;



  // inicializace LCD
  lcd_init();
  // definice specialnich znaku
  lcd_define_char(2,LCD_CHAR_a_FILL);
  lcd_define_char(1,LCD_CHAR_b_FILL);
  lcd_define_char(3,LCD_CHAR_9_FILL);

  // nastaveni smeru signalu a jejich klidovych stavu
  port_b_pullups(TRUE);
  output_high(DDS_FSYNC);          // zapis_so DDS neaktivni
  output_low(DDS_SDATA);           // data do 0
  output_high(DDS_SCK);            // hodiny do neaktivniho stavu
  output_low(RXTX);                // prepni na prijem
  output_low(KEYING);              // neklicuj
  output_low(LCD_LED2);            // zhasni led
  output_low(LCD_LED1);            // zhasni led
  input(TONE);                     // vypni priposlech
  output_low(PWR_CTRL);            // nulovy vykon

  output_low(ATN1);
  output_low(ATN2);
  output_low(ATNC);

  // inicializace DDS
  dds_send(CTRL_RESET);            // pozadujeme reset
  dds_send(CLR_PHASE0);
  dds_send(CLR_PHASE1);


  // zakladni nastaveni ridicich promennych programu
  update_timer=UPDATE_TIME;        // natahni periodicky timer pro LCD
  flags=0;                         // nuluj priznaky ridici program
  elbug_flags=0;                   // nuluj priznaky pro elbug
  keys_flags=0;
  adc_flags=0;
  adc_ch=0;
  pwm_val=PWM_MIN;
  enc_delta=0;                     // zadna zmena od kroutitka
  keys=0;                          // zadna tlacitka nejsou stisknuta
  freq_rit=0;                      // nuluj RIT

  // uvodni hlaseni programu
  lcd_gotoxy(1,1);
  printf(lcd_putc,NAME);
  lcd_gotoxy(1,2);
  printf(lcd_putc,VERSION);
  delay_ms(1000);

  // nastaveni AD prevodniku
  setup_adc(ADC_CLOCK_DIV_8);
  setup_adc_ports(AN0_AN1_AN2_AN3_AN4); // povoleny  porty AN0-AN4

  set_band();                      // nastav pasmo podle pripojeneho filtru nebo cekej na jeho pripojeni

  check_eeprom();                  // kontrola platnosti obsahu eeprom, pri poruse nastav defaultni parametry

  // obnoveni a nastaveni parametru programu
  par[PAR_POWER]=read_eeprom(EE_ADR_POWER+band_index);         // vyzvedni nastaveny vykon pro dane pasmo
  power=par[PAR_POWER]*5;

  par[PAR_KEYER]=read_eeprom(EE_ADR_KEYER);                    // vyzvedni rychlost klice
  if(par[PAR_KEYER]<=PAR_LIMIT[PAR_KEYER][0]) elbug_flags=0;   // vypni elbug
  else
  {
    // zapni elbug a nastav rychlost
    bit_set(_ELBUG_ON);
    elbug_dot_sp=~(ELBUG_CONST/par[PAR_KEYER]);                // preved na hodnotu citace TMR1
    elbug_dot_sp++;
    elbug_dash=(elbug_dot_sp<<1)+elbug_dot_sp;                 // *3, ale rychleji
  }

  par[PAR_VOX]=read_eeprom(EE_ADR_VOX);                        // vyzvedni vox
  vox_time=par[PAR_VOX];
  if(vox_time!=0) vox_time=vox_time*20;                        // cas je ve 100ms jednotkach
  else vox_time=2;

  par[PAR_KEYER_REV]=read_eeprom(EE_ADR_KEYER_REV);            // vyzvedni chapani pak
  if(par[PAR_KEYER_REV]) bit_set(_ELBUG_REV);                  //
  else bit_clear(_ELBUG_REV);


  par[PAR_KEYER_REV]=read_eeprom(EE_ADR_KEYER_REV);            // vyzvedni mod elbugu
//  if(par[PAR_KEYER_REV]) bit_set(_ELBUG_REAL);                 //
//  else bit_clear(_ELBUG_REAL);
  bit_clear(_ELBUG_REAL);                                      // mod elbugu je zatim vzdy doplnkovy

  par[PAR_ATTN]=PAR_LIMIT[PAR_ATTN][0];                        // attenuator vzdy vypnut
  Attn_0dB();
  freq_vfo[0]=START_FREQ[band_index];                          // QRP volaci kmitocet BAND_LIMIT[band_index][0] ;                      // po zapnuti ma VFO nejmensi kmitocet pasma
  freq_vfo[1]=START_FREQ[band_index];                          // QRP volaci kmitocet BAND_LIMIT[band_index][0] ;                      // po zapnuti ma VFO nejmensi kmitocet pasma
  bit_set(_DDS_UPDATE);                                        // pozadujeme nastavit kmitocet v dds
  step_index=0;                                                // defaultne jemny krok ladeni
  vfo_index=0;                                                 // defaultne vfoA



  // nastaveni zakladniho tiku
  setup_timer_0(RTCC_INTERNAL|RTCC_DIV_128);
  set_timer0(TICK_TIME);

  // nastaveni pro generovani priposlechu, rizeni LCD_LED a PWM pro rizeni vykonu
  setup_timer_2(T2_DIV_BY_16,TONE_SET,4);       // zajisti pro PWM rozliseni 8.28 bitu
  setup_ccp1(CCP_PWM);                          // pro generovani tonu
  set_pwm1_duty((TONE_SET+1)/2);                // strida cca 1:1
  tone_off();                                   // priposlech vypnut
  setup_ccp2(CCP_PWM);                          // pro rizeni vykonu
  set_pwm2_duty((int16)27);                     //
  setup_timer_1(T1_DISABLED);                   // elbug je v klidu


  #use fast_io(b)
     keyer=(~input_b()) & 0b11000000;             // precti stav pak
  #use standard_io(b)

  if(bit_test(keyer,6)) bit_clear(_ELBUG_ON);   // pokud je ori zapnuti stisknuta paka carek, je pripojen rucni klic


  // povoleni preruseni
  enable_interrupts(INT_EXT);         // preruseni od zmeny polohy kroutitka
  enable_interrupts(INT_TIMER0);      // zakadni tik
  enable_interrupts(INT_TIMER2);      // preruseni pro rizeni vykonu, LED a generovani priposlechu
  enable_interrupts(INT_TIMER1);      // preruseni pro elbug
  enable_interrupts(INT_RB);          // preruseni od stavu pak klice
  enable_interrupts(GLOBAL);





//#define  TEST
#ifdef TEST

bit_set(_TRANSMIT);
//bit_set(_MNU);

fwd_val=150;
rev_val=10;
smtr_val=150;
bnd_val=0x20;

a=50;
b=5;


// testovaci smycka pro zjistovani doby behu testovane funkce
setup_timer_1(T1_INTERNAL|RTCC_DIV_1);
set_timer1(0);

//Analog_inputs();

c=b-a;

setup_timer_1(T1_DISABLED);
lcd_gotoxy(1,1);
printf(lcd_putc,"T:%LU",get_timer1());
lcd_gotoxy(1,2);
printf(lcd_putc,"%D",c);

for(;;);

#else



  // HLAVNI SMYCKA
  for(;;)
  {

/////////////////
    // pozadavek na zmenu kmitoctu (max. 2,5ms)
    if(bit_test(_DDS_UPDATE)) dds_update();

////////////////
    // nastala zmena polohy kroutitka
    if(bit_test(_ENC_CHNG))  enc_chng();

/////////////////
    // zmena parametru
    if(bit_test(_PAR_UPDATE)) par_update();

/////////////////
    // pozadavek zmeny kmitoctu na lcd - 1.radek (zabere 30ms !!!!!)
    // PODMINKU NUTNO UPRAVIT
    if(bit_test(_LCD1_UPDATE) && update_timer==0 && !bit_test(_ELBUG_BSY)) lcd1_update();


/////////////////
   // pozadavek na zmenu informaci na lcd - 2.radek (max 2ms)
   if(bit_test(_LCD2_UPDATE) && update_timer==0)
   {
     lcd2_update();
     update_timer=0xFF;    // ukonci okno,kdy je timer vyprseny
   }


/////////////////
   // periodicka mereni (max 3ms)
   if(update_timer==0)
   {
     analog_inputs();
     update_timer=0xFF;    // ukonci okno,kdy je timer vyprseny
   }


/////////////////
   // stisknuta tlacitka

   if(bit_test(_KEYS_VALID))           // stisknuto nejake tlacitko
   {
     // kratky stisk libovolneho tlacitka ukonci nastavovani
     if(bit_test(_MNU) && !bit_test(_KEYS_LONG))
     {
       bit_clear(_MNU);                                        //  vypni nastavovani
       enc_delta=0;                                            // zahod nacitane zbyle impulzy korutitka
       if(bit_test(_ELBUG_ON_TMP)) bit_set(_ELBUG_ON);         // obnov zapnuti elbugu pokud byl zapnut

       if(par_index!=PAR_ATTN)        // stav attenuatoru se neuklada do eeprom
       {
         ee_adr=EE_ADDR[par_index];
         if(par_index==PAR_POWER) ee_adr=ee_adr+band_index;   // pro parametr vykonu urci adresu eeprom pro dane pasmo
         if(read_eeprom(ee_adr)!=par[par_index])              // pokud doslo ke zmene parametru, aktualizuj ho v eeprom
         {
           write_eeprom(ee_adr,par[par_index]);
           update_eeprom();
         }
       }
       bit_set(_LCD1_UPDATE);
       bit_set(_LCD2_UPDATE);
     } else
       {
         // ktere tlacitko je stisknuto?
         if(keys==KEY_SPLIT)                      // SPLIT/MNU
         {
           if(bit_test(_KEYS_LONG))
           {
             // dlouhy stisk - vstup do MENU
             bit_set(_MNU2);                     // prvni stisk - vyber parametr
             par_index=PAR_POWER;
             bit_set(_LCD1_UPDATE);
             bit_set(_LCD2_UPDATE);
           } else
             {
               // kratky stisk - pokracovani v MENU
               if(bit_test(_MNU2))
               {
                 if(par_index==PAR_POWER)
                 {
                   // zapamatuj si , zda je elbug zapnut nebo vypnut
                   if(bit_test(_ELBUG_ON)) bit_set(_ELBUG_ON_TMP);
                   else bit_clear(_ELBUG_ON_TMP);
                   bit_clear(_ELBUG_ON);        // pri nastavovani vykonu je elbug vypnut
                 }
                 bit_clear(_MNU2);              // druhy stisk - prejdi do vybraneho parametru
                 bit_set(_MNU);
               } else
                 {
                   // kratky stisk - funkce SPLIT
                   if(bit_test(_SPLIT)) bit_clear(_SPLIT);
                   else bit_set(_SPLIT);
                 }
               bit_set(_LCD1_UPDATE);
             }
         } // KEY_SPLIT

         // ostani tlacitka jsou aktivni jen kdyz nejsme ve vyberu parametru
         if(!bit_test(_MNU2))
         {
           if(keys==KEY_RIT)                   // RIT/STEP
           {
             if(bit_test(_KEYS_LONG))
             {
               // dlouhy stisk - funkce STEP
               if(step_index) step_index=0;
               else step_index=1;
               bit_set(_LCD1_UPDATE);
             } else
               {
                 // kratky stisk - funkce RIT
                 if(bit_test(_RIT))
                 {
                   bit_clear(_RIT);
                   freq_rit=0;                 // pri vypnuti RIT vynuluj
                 } else bit_set(_RIT);
                 bit_set(_DDS_UPDATE);
               }
           }   // KEY_RIT

           if(keys==KEY_CHNGVFO)               // prepni VFO/srovnej VFO
           {
             if(bit_test(_KEYS_LONG))
             {
               // dlouhy stisk - funkce srovnej VFO
               if(vfo_index) freq_vfo[0]=freq_vfo[1];
               else freq_vfo[1]=freq_vfo[0];
             } else
               {
                 // kratky stisk - funkce prepni VFO
                 if(vfo_index) vfo_index=0;
                 else vfo_index=1;
                 bit_set(_DDS_UPDATE);
               }
            } // KEY_CHNGVFO

           if(keys==KEY_ATTN)                // ATTN/ELBUG
           {
             if(bit_test(_KEYS_LONG))
             {
               // dlouhy stisk - funkce ELBUG
               par_index=PAR_KEYER;
               bit_set(_MNU);
               bit_set(_LCD1_UPDATE);
               bit_set(_LCD2_UPDATE);
             } else
               {
                 // kratky stisk - funkce ATTN - mozne jen pokud se nevysila
                 par_index=PAR_ATTN;
                 bit_set(_MNU);
                 bit_set(_LCD1_UPDATE);
                 bit_set(_LCD2_UPDATE);
               }
           } // KEY_ATTN
         }
       }
     bit_clear(_KEYS_VALID);     // tlacitko zpracovano
     bit_set(_KEYS_RELEASE);     //  budeme cekat na uvolneni tlacitek
   }

  }  // hlavni smycka
#endif
}
// End of File