#include <mega128.h>
#include <stdio.h>
#include <delay.h>
#include <string.h>
#include <stdlib.h>
#include "def.h"
#include "coder.h"
//#include "LCD_3320.h"
#include "displ.h"
#include "LMX2306.h"
#include "menu.h"


#define menuT0L 4
#define menuT1L 10 
#define menuT2L 10 
#define menuT3L 2 
#define menuT4L 5
#define menuT5L 8 
#define menuT6L 2 
#define menuT7L 3 
#define menuChL 6 

__flash const char Name_table[] = {
' ','_','-','0','1','2','3','4','5','6','7','8','9','A','a','B','b','C','c','D',
'd','E','e','F','f','G','g','H','h','I','i','J','j','K','k','L','l','M','m','N',	
'n','O','o','P','p','Q','q','R','r','S','s','T','t','U','u','V','v','W','w','X',
'x','Y','y','Z','z'};

unsigned char pos[6];
unsigned char T[2];
bit f_edit_cur;
bit f_edit;
unsigned char mnu_keys;
bit f_clip;
bit  f_sound_en;
unsigned char BatCntr[3];
unsigned char gAntCntr;
unsigned int time;
bit f_timer_en;
unsigned char div_beep_batt;
unsigned char div_beep_antenna;
unsigned char g_rep;
signed int CalibrTemperature[2]; 
extern signed int gAddPropVal;
extern signed int gAddPropValOld;
extern bit gfca_start;
 
#define REP_FAST 5
#define REP_SLOW 10
//-------------------------------------------------------------
//------------------------------------------------------
//------------------------------------------------------
flash const BEEP_TRACK_DEF hello_sound[]={ {10,200}, {7,50},{3,50}, {10,200} };
flash const BEEP_TRACK_DEF error_sound[]={ {20,500}, {10,1000} };
flash const BEEP_TRACK_DEF error_starting[]={ {20,100}, {10,100}, {5,100} };
flash const BEEP_TRACK_DEF calibr_sound[]={ {10,50}, {20,50}, {10,50} };
flash const BEEP_TRACK_DEF key_sound[]={ {20, 20} };
flash const BEEP_TRACK_DEF EEP_sound[]={ {20, 20}, {10, 40} };
flash const BEEP_TRACK_DEF batt_sound[]={ {10,50}, {20,50} };
flash const BEEP_TRACK_DEF antenna_sound[]={ {5,20}, {10,20}, {5,20}  };
flash const BEEP_TRACK_DEF timer_sound[]={ {10,20}, {20,20} };
flash const BEEP_TRACK_DEF trimmer_sound[]={ {10,5} };
flash const BEEP_TRACK_DEF trimmer_c_sound[]={ {15,40} };

//------------------------------------------------------
void beep_work(void)
{
unsigned char i;

if(TCCR3B & 0x3) return; 
i=cur_Batt/5;
if(i<=BatCntr[1]) 
  { // Alarm
  if(div_beep_batt>(1000/20)) div_beep_batt=0;
  if(!div_beep_batt) { beep_start(batt_sound, 2, 4); div_beep_batt=(1000/20); }
  }
if(i<=BatCntr[0] && !div_beep_batt)  // Warm
  { beep_start(batt_sound, 2, 1); div_beep_batt=(5000/20); }
i=cur_Antenna/10;
if(i<gAntCntr && !div_beep_antenna)
  { beep_start(antenna_sound, 3, 0); div_beep_antenna=(5000/20); }
  if(f_beep_timer) { f_beep_timer=0; beep_start(timer_sound, 2, 25);  return; }
if(f_beep_EEP) { f_beep_EEP=0; if(f_sound_en) beep_start(EEP_sound, 2, 0); return; }
if(f_beep_key) { f_beep_key=0; if(f_sound_en) beep_start(key_sound, 1, 0); return; }
if(f_beep_trimmer_c) { f_beep_trimmer_c=0; if(f_sound_en) beep_start(trimmer_c_sound, 1, 0); return; }
if(f_beep_trimmer) { f_beep_trimmer=0; if(f_sound_en) beep_start(trimmer_sound, 1, 0); return; }
}
//------------------------------------------------------
//------------------------------------------------------
//------------------------------------------------------
#define F_UP    1
#define F_DOWN  2
#define F_LEFT  4
#define F_RIGHT 8
#define _UP (mnu_keys & F_UP)
#define _DOWN (mnu_keys & F_DOWN)
#define _LEFT (mnu_keys & F_LEFT)
#define _RIGHT (mnu_keys & F_RIGHT)
//-------------------------------------------------------------
void keys_driver(void)
{  // 20ms
unsigned char kf, n, m;
static unsigned char kf1;
static unsigned char cnt_rep;

kf=0;
if(!KEY_UP) kf|=F_UP;
if(!KEY_DOWN) kf|=F_DOWN;
if(!KEY_LEFT) kf|=F_LEFT;
if(!KEY_RIGHT) kf|=F_RIGHT;
for(m=1, n=0; m; m<<=1) if(kf & m) n++;
if(n>1) kf=0; 
if(kf!=kf1) { kf1=kf; mnu_keys=0; cnt_rep=0; return; }
if(kf==0) { mnu_keys=0; cnt_rep=0; return; }// all up
if(!cnt_rep) mnu_keys=kf;
cnt_rep++;
if( ((kf & F_UP) || (kf & F_DOWN)) && g_rep)
  {
  if(cnt_rep>g_rep+25) cnt_rep=25;
  if(cnt_rep==25) mnu_keys=kf;
  }  
}
//-------------------------------------------------------------
void TimerOn(void)
{// 50Hz (20ms)
#define TIME_DISPL_TEMPERATURE 50*10
#define WAIT_DISPL_TEMPERATURE 50*2
static unsigned char dev_clip=0;
static unsigned char dev_timer=0;
unsigned int i;

if(g_MainMenuMode==0 || dev_clip==0) 
  {
  cur_Batt=read_adc(ch_Batt);
  cur_Antenna=read_adc(ch_Antenna);
  }
i=read_adc(ch_Temperature);
if(i!=cur_Temperature)
  {
  if(++wd_Temperature>WAIT_DISPL_TEMPERATURE)
    {
    wd_Temperature=0;
    if(i>cur_Temperature) dir_Temperature=TIME_DISPL_TEMPERATURE;
    else if(i<cur_Temperature) dir_Temperature=-TIME_DISPL_TEMPERATURE;
    cur_Temperature=i;
    }
  }
else wd_Temperature=0;    
if(dir_Temperature>0) dir_Temperature--;
else if(dir_Temperature<0) dir_Temperature++; 
if(++dev_clip>=30)  { dev_clip=0; f_clip=!f_clip; }
if (f_timer_en)
  { // разрешен счет
  if (++dev_timer>=50)
    {
    dev_timer=0;
    if(cur_model.timer_mode!=1) 
      {
      time++;
      if(time && !(time%cur_model.timer_set)) f_beep_timer=1;
      }
    else
      {
      if(time) time--;
      if(time==0) { f_timer_en=0; f_beep_timer=1; }
      }  
    }
  }
if(div_beep_batt) div_beep_batt--;
if(div_beep_antenna) div_beep_antenna--; 
if(div_trimmer) { div_trimmer--;  if(div_trimmer==1) save_trimmer();  } 

keys_driver();
keys_menu();
beep_work();
}
//-------------------------------------------------------------
void save_trimmer(void)
{
unsigned char i;

if(div_trimmer==0) return;
div_trimmer=0;
BEEP1;
for(i=0; i<4; i++)
  {
  EEPR_models[cur_model_ind].modes[cur_mode_ind].trimmers[i]=
      cur_model.modes[cur_mode_ind].trimmers[i];
  }
SetCRC_EEPROM();
}  
//-------------------------------------------------------------
void MODEL_reset(unsigned char ind)
{
static signed char nod_val[CURVE_NODES+1]= { 0, -100, -66, -34, 0,  34, 66, 100 };
unsigned char i, j, n;
eeprom MODEL_SET *model;
eeprom DEF_MODE *cm;
eeprom CHANNEL *ch;
char tmp[12];


model=(EEPR_models+ind);
sprintf(tmp,"Model %-i ", ind+1);  
for (i=0; i<8; i++) model->name[i]=tmp[i];
model->type=0;  // plane.
model->modulation=0; // PPM
model->timer_mode=0;
model->timer_set=300;
model->num_ch=6;
model->num_freq=0;
for (i=0; i<MAX_MODES; i++)
  {
  cm=&model->modes[i];
  for(j=0; j<3; j++) 
    {
    cm->contr_ab[j].minRates=100;  cm->contr_ab[j].maxRates=100;
    cm->contr_ab[j].minDRates=120; cm->contr_ab[j].maxDRates=120;
    for(n=0; n<CURVE_NODES+1; n++) cm->contr_ab[j].cur_nodes[n]=nod_val[n];
    }
  cm->contr_tr.minRates=100;  cm->contr_tr.maxRates=100;
  cm->contr_tr.tcut=120;
  for(n=0; n<CURVE_NODES+1; n++) cm->contr_tr.cur_nodes[n]=nod_val[n];
  cm->contr_ap.minRates=100;  cm->contr_ap.maxRates=100;
  for(n=0; n<CURVE_NODES+1; n++) cm->contr_ap.cur_nodes[n]=nod_val[n];
  for(j=0; j<3; j++) 
    {
    cm->contr_d[j].minRates=100;  cm->contr_d[j].maxRates=100;
    cm->contr_d[j].delay=0; 
    }
  for(j=0; j<2; j++) 
    {
    cm->contr_v[j].minRates=100;  cm->contr_v[j].maxRates=100;
    cm->contr_v[j].from=j;
    for(n=0; n<CURVE_NODES+1; n++) cm->contr_v[j].cur_nodes[n]=nod_val[n];
    }
  for(j=0; j<MAX_CHANS; j++)
    for(n=0; n<MAX_CONTRS; n++)
      if(j==n) cm->mixer[j][n]=100; else cm->mixer[j][n]=0;
  for(j=0; j<4; j++) cm->trimmers[j]=0;    
  }
for (i=0; i<MAX_CHANS; i++)
  {
  ch=&model->channels[i];
  ch->subtrimmer=0; 
  ch->epa[0]=120; 
  ch->epa[1]=120;
  ch->reverse=1; 
  }
SetCRC_EEPROM();  
}
//-------------------------------------------------------------
void MODEL_init(unsigned char ind)
{
save_trimmer();
cur_model_ind=ind;
cur_model=EEPR_models[ind];
if (cur_model.modulation==0) TCCR1A=0x82;
if (cur_model.modulation==1) TCCR1A=0xC2;
if (cur_model.timer_mode!=1) time=0;
else time=cur_model.timer_set;
PLL_SetFreq(cur_model.num_freq);
}
//-------------------------------------------------------------
void MODEL_copy (unsigned char from, unsigned char to)
{
unsigned char i;
EEPR_models[to].type=EEPR_models[from].type;
EEPR_models[to].modulation=EEPR_models[from].modulation;
EEPR_models[to].timer_mode=EEPR_models[from].timer_mode;
EEPR_models[to].timer_set=EEPR_models[from].timer_set;
EEPR_models[to].num_ch=EEPR_models[from].num_ch;
EEPR_models[to].num_freq=EEPR_models[from].num_freq;
for(i=0; i<MAX_MODES; i++)
 EEPR_models[to].modes[i]=EEPR_models[from].modes[i];
for (i=0; i<MAX_CHANS; i++)
 EEPR_models[to].channels[i]=EEPR_models[from].channels[i];
SetCRC_EEPROM();  
}
//-------------------------------------------------------------
void NormalizeMixer(unsigned char ind)
{
signed char *mix;
signed int summ, v;
unsigned char i;

mix=cur_model.modes[cur_mode_ind].mixer[ind];
for(i=0, summ=0; i<MAX_CONTRS; i++) summ+=cabs(*(mix+i));
for(i=0; i<MAX_CONTRS; i++) { v=*(mix+i); v*=200; v/=summ; v++; *(mix+i)=(v/2); }
}
//-------------------------------------------------------------
void start_change_analog(void)
{
gfca_start=0;
gAddPropValOld=gAddPropVal;
}
//-------------------------------------------------------------
int change_analog(int val, int minv, int maxv)
{
int v;
signed long ln;

if(!gfca_start)
  {
  v=gAddPropVal-gAddPropValOld;
  if(v<0) v=-v;
  if(v>150) gfca_start=1; //10%
  } 
if(gfca_start)
  {
  ln=(maxv-minv); ln*=gAddPropVal; ln/=1500;
  return (minv+(int)ln);  
  }
return val;  
}
//-------------------------------------------------------------
unsigned char g_list_topitem=0;
unsigned char g_list_selitem=0;
unsigned char g_list_cnt=0;

//----------------
void list_ini (unsigned char cnt,unsigned char sel)
{
g_list_cnt=cnt; g_list_selitem=sel; g_list_topitem=0;
if(g_list_selitem>=(g_list_topitem+MAX_LIST_LINES)) 
  g_list_topitem=g_list_selitem-(MAX_LIST_LINES-1);
else if(g_list_selitem<g_list_topitem) g_list_topitem=g_list_selitem; 
}
//----------------
void list_scroll (void)
{
if(_DOWN && g_list_selitem<(g_list_cnt-1))
  { g_list_selitem++; BEEP;  }
else if(_UP && g_list_selitem>0)
  { g_list_selitem--; BEEP;  }
g_list_selitem=(unsigned char)change_analog(g_list_selitem, 0, g_list_cnt-1);
if(g_list_selitem>=(g_list_topitem+MAX_LIST_LINES)) 
    g_list_topitem=g_list_selitem-(MAX_LIST_LINES-1);
if(g_list_selitem<g_list_topitem) g_list_topitem=g_list_selitem;
}
//----------------
void list_scroll_roll(void)
{ 
if(g_list_selitem==g_list_cnt-1) { g_list_selitem=0; g_list_topitem=0; }
else
  {
  g_list_selitem++;
  if(g_list_selitem>=(g_list_topitem+MAX_LIST_LINES)) 
    g_list_topitem=g_list_selitem-(MAX_LIST_LINES-1);
  }  
BEEP;  
}
//-------------------------------------------------------------
int change_par(int val, int min, int max)
{
if(_UP && val<max) { val++; BEEP; }
else if(_DOWN && val>min) { val--; BEEP; }
val=change_analog(val, min, max);
return val;
}
//-------------------------------------------------------------
void change_paru(unsigned char *par, unsigned char max)
{
(*par)=(unsigned char)change_par(*par, 0, max);
}
//-------------------------------------------------------------
void change_pars(signed char *par, signed char min, signed char max)
{
(*par)=(signed char)change_par(*par, min, max);
}
//-------------------------------------------------------------
void change_parr(unsigned char *par, unsigned char max)
{
if(_UP) { if((*par)>0) (*par)--; else *par=max; BEEP; }
else if(_DOWN) { if((*par)<max) (*par)++; else *par=0; BEEP; }
(*par)=(unsigned char)change_analog(*par, 0, max);
}
//-------------------------------------------------------------
void change_name_ch(unsigned char *ch)
{
char i;

for(i=0; i<sizeof(Name_table); i++) if( *ch==Name_table[i]) break;
if(i==sizeof(Name_table)) i=0;
if(_UP) { if(i<sizeof(Name_table)-1) i++; else i=0; BEEP; }
else if(_DOWN) { if(i>0) i--; else i=sizeof(Name_table)-1;  BEEP;}
i=(char)change_analog(i, 0, sizeof(Name_table)-1);
*ch=Name_table[i];
}
//-------------------------------------------------------------
void change_curve(unsigned char ind, signed char *curve)
{
int v;

if(ind>0) 
  {
  *curve=127;
  change_pars(curve+ind, -100, 100);
  }  
else
  {
  if(*curve>100) *curve=0;
  change_pars(curve, -50, 50);
  v=*curve;
  curve[1]=-100; curve[4]=0; curve[7]=100;
  v=*curve; v*=(34-16); v/=35; 
  curve[5]=34+v;
  curve[3]=-curve[5];
  v=*curve; v*=(66-48); v/=35; 
  curve[6]=66+v;
  curve[2]=-curve[6]; 
  }  
}
//-------------------------------------------------------------
void keys_menu(void)
{
unsigned char ind, ch, v;
unsigned int i;
DEF_MODE *rm;
unsigned char *p1;
eeprom unsigned char *p2;

if(mnu_keys) start_change_analog();
switch(pos[0])
  {
  case 0: // Main screen
    if(_UP) 
     {
     if(cur_model.timer_mode!=2)
       {
       if(!f_timer_en)
         {
         if(cur_model.timer_mode==1 && time==0) time=cur_model.timer_set;
         f_timer_en=1;
         }
       else f_timer_en=0;
       BEEP;
       }
     }
   if(_DOWN)
     {
     if(cur_model.timer_mode!=2) f_timer_en=0;
     if(cur_model.timer_mode==1) time=cur_model.timer_set; else time=0; 
     BEEP;
     }       
   if(_RIGHT) { pos[0]=1; pos[1]=0; list_ini(menuT0L, 0); g_rep=REP_SLOW; BEEP;  }
   if(_LEFT) 
     {
     if(g_MainMenuMode<1) g_MainMenuMode++; else g_MainMenuMode=0; 
     BEEP; 
     } 
  break;
  case 1:
  switch(pos[1])
    {
    case 0: //Главное меню
    if(_LEFT) { pos[0]=0; g_rep=0; BEEP; break; }
    if(_RIGHT) 
      {
      pos[1]=g_list_selitem+1; pos[2]=0;
      switch(pos[1])
        {
        case 1: list_ini(MAX_MODELS, cur_model_ind); break;
        case 2: list_ini(menuT1L, 0); break;
        case 3: T[0]=cur_model_ind; T[1]=cur_model_ind+1; if(T[1]>=MAX_MODELS) T[1]=0; break;
        case 4: list_ini(menuT4L, 0); break;
        }
      BEEP; 
      break; 
      }
    list_scroll();
    break;
    case 1: // Select
      if(_LEFT) { list_ini(menuT0L, pos[1]-1); pos[1]=0; BEEP; break; } // Cancel
      if(_RIGHT) 
        { // OK
        BEEP1;
        MODEL_init(g_list_selitem);
        EEPR_start_model=g_list_selitem;
        SetCRC_EEPROM();
        pos[0]=0; g_rep=0;
        break; 
        }
      list_scroll();
    break;
    case 2: // Model
    switch(pos[2])
      {
      case 0:
        if(_LEFT) 
          {
          p1=(unsigned char *)&cur_model;
          p2=(eeprom unsigned char *)&EEPR_models[cur_model_ind];
          for(i=0, v=0; i<sizeof(MODEL_SET); i++) 
            if( (*(p1+i))!=(*(p2+i)) ) { v=1; break; }
          if(v) { list_ini(menuT7L, 0); pos[2]=11;  BEEP; break; }
          list_ini(menuT0L, pos[1]-1); pos[1]=0;
          BEEP;
          break;
          }
        if(_RIGHT) 
          {
          pos[2]=g_list_selitem+1; pos[3]=0; f_edit=0;
          switch(pos[2])
            {
            case 1: list_ini(menuT2L, 0); break;  
            case 2: list_ini(menuT5L, 0); break;
            case 8: list_ini(menuT3L, 0); break;
            case 9: T[0]=cur_mode_ind; T[1]=cur_mode_ind+1; if(T[1]>2) T[1]=0; break;
            }           
          BEEP; 
          break; 
          }
        list_scroll();
      break;
      case 1: // CONTROLS
        switch(pos[3])
          {
        case 0:
          if(_LEFT) { list_ini(menuT1L, pos[2]-1); pos[2]=0;  BEEP; }
          if(_RIGHT) 
            {
            pos[3]=g_list_selitem+1; pos[4]=0;
            f_edit=0; f_edit_cur=0;
            BEEP; 
            break; 
            }
          list_scroll();
        break;
        default:
          ch=pos[3]-1;
          rm=&cur_model.modes[cur_mode_ind];
          if(!f_edit_cur)
            {
            if(ch==0 || ch==1 || ch==3) v=4;
            else if(ch==2 || ch==8 || ch==9) v=3;
            else if(ch==7) v=2;
            else v=2;                
            if(_RIGHT) 
                {
                if(pos[4]==v && (ch<4 || ch>6))
                  { f_edit=0; f_edit_cur=1; pos[5]=0; g_rep=REP_SLOW; BEEP; break; }
                }
            if(!f_edit)
              {
              if(_LEFT) { list_ini(menuT2L, pos[3]-1); pos[3]=0; BEEP; break; }
              if(_RIGHT) { f_edit=1; g_rep=REP_FAST; BEEP; break; }
              change_parr(&pos[4], v);
              }
            else // edit
              { 
              if(_LEFT)  { f_edit=0; g_rep=REP_SLOW; BEEP; break; }
              if(_RIGHT)
                {
                if(pos[4]<v) pos[4]++; else pos[4]=0;
                BEEP; break;
                }
              if(ch<=3 && ch!=2) // Основные каналы и не газ
                { 
                ind=ch; if(ch>2) ind=2;
                switch(pos[4])
                  {
                  case 0: change_paru(&rm->contr_ab[ind].minRates, 150); break;
                  case 1: change_paru(&rm->contr_ab[ind].maxRates, 150); break;
                  case 2: change_paru(&rm->contr_ab[ind].minDRates, 150); break;
                  case 3: change_paru(&rm->contr_ab[ind].maxDRates, 150); break;
                  }
                }
              else if (ch==2) // Газ
                { 
                switch(pos[4])
                  {
                  case 0: change_paru(&rm->contr_tr.minRates, 150); break;
                  case 1: change_paru(&rm->contr_tr.maxRates, 150); break;
                  case 2: change_paru(&rm->contr_tr.tcut,  150); break;
                  }
                }  
              else if(ch>=4 && ch<=6) // дискретные каналы
                { 
                ind=ch-4;
                switch(pos[4])
                  {
                  case 0: change_paru(&rm->contr_d[ind].minRates, 150); break;
                  case 1: change_paru(&rm->contr_d[ind].maxRates, 150); break;
                  case 2: change_paru(&rm->contr_d[ind].delay, 100); break;
                  }
                }  
             else if (ch==7) // Дополнительный канал
                { 
                switch(pos[4])
                  {
                  case 0: change_paru(&rm->contr_ap.minRates, 150); break;
                  case 1: change_paru(&rm->contr_ap.maxRates, 150); break;
                  }
                }  
              else if(ch>=8)
                { // Виртуальные каналы
                ind=ch-8;
                switch(pos[4])
                  {
                  case 0: change_paru(&rm->contr_v[ind].minRates, 150); break;
                  case 1: change_paru(&rm->contr_v[ind].maxRates, 150); break;
                  case 2: change_paru(&rm->contr_v[ind].from, 7); break;
                  }
                }   
            }                
          }
          else // edit curve
            { 
            if(!f_edit)
              {
              if (_LEFT)  { f_edit_cur=0; BEEP; break; }
              if (_RIGHT) 
                {
                f_edit=1;
                g_rep=REP_FAST; BEEP; break; 
                } 
              change_paru(&pos[5], 7); 
              }
            else // edit
              {
              if (_LEFT)  { f_edit=0; g_rep=REP_SLOW; BEEP; break; }
              if (_RIGHT && pos[5]) { if(pos[5]<7) pos[5]++; else pos[5]=1; BEEP; break; } 
              if(ch<=3 && ch!=2)
                { // Основные каналы и не газ
                ind=ch; if(ch>2) ind=2;
                change_curve(pos[5], rm->contr_ab[ind].cur_nodes); 
                }
              else if (ch==2) //Газ
                change_curve(pos[5], rm->contr_tr.cur_nodes);
              else if (ch==7) // Дополнительный канал
                change_curve(pos[5], rm->contr_ap.cur_nodes);
              else if(ch>=8)
                { // Виртуальные каналы
                ind=ch-8;
                change_curve(pos[5], rm->contr_v[ind].cur_nodes);
                }
              }  
            }  
        break;
        }
      break;    
      case 2: // CHANNELS
      switch(pos[3])
        {
        case 0:
        if(_LEFT) { list_ini(menuT1L, pos[2]-1); pos[2]=0;  BEEP; break;}
        if(_RIGHT) 
          {
          pos[3]=g_list_selitem+1; pos[4]=0;
          list_ini(menuChL, 0);
          f_edit=0;
          BEEP; 
          break; 
          }
        list_scroll();
        break;
        default:
        if(pos[4]==0)
          {
          if(!f_edit)
            {
            if(_LEFT) { list_ini(menuT5L, pos[3]-1); pos[3]=0;  BEEP; break; } // Назад
            if(_RIGHT) 
              {
              if(g_list_selitem==0) { list_ini(menuT2L, 0); pos[4]=1; } // mixer
              else if(g_list_selitem==1) pos[4]=2; // Normalize
              else { f_edit=1; g_rep=REP_FAST; } // Вкл.редакт
              BEEP;
              break; 
              } 
            list_scroll();
            }
          else
            { // edit
            if (_LEFT)  { f_edit=0; g_rep=REP_SLOW; BEEP; break; }
            if (_RIGHT) 
              {
              list_scroll_roll();
              if(g_list_selitem==0) { f_edit=0; g_rep=REP_SLOW; } 
              break;
              } 
            ind=pos[3]-1; // ind channel
            switch(g_list_selitem)
              {
              case 2: change_pars(&cur_model.channels[ind].subtrimmer, -50, 50); break; 
              case 3: change_pars(&cur_model.channels[ind].epa[0], 0, 120); break; 
              case 4: change_pars(&cur_model.channels[ind].epa[1], 0, 120); break; 
              case 5:
               if(_UP || _DOWN) 
                 { if(cur_model.channels[ind].reverse==1) cur_model.channels[ind].reverse=-1; 
                 else cur_model.channels[ind].reverse=1; BEEP; }
              break;
              }     
            }
          }
        else if(pos[4]==1)
          { // mixer
          if(!f_edit)
            {
            if(_LEFT) { list_ini(menuChL, 0); pos[4]=0;  BEEP; break; } // Назад
            if(_RIGHT) { f_edit=1; g_rep=REP_FAST; BEEP; break; } // Вкл.редакт
            list_scroll();
            }
          else
            {
            ind=pos[3]-1; // ind channel
            if(_LEFT)  { f_edit=0; g_rep=REP_SLOW; BEEP; break; }
            if(_RIGHT) { list_scroll_roll(); break; }
            change_pars(&cur_model.modes[cur_mode_ind].mixer[ind][g_list_selitem], -100, 100);
            }
          break;            
          }
        else if(pos[4]==2)
          { // normalize
          if(_LEFT)  { list_ini(menuChL, 0); pos[4]=0;  BEEP; break; } // Назад
          if(_RIGHT)
            {
            ind=pos[3]-1; // ind channel
            NormalizeMixer(ind);
            list_ini(menuChL, 0); pos[4]=0;
            BEEP;
            break;
            }
          }  
        break;  
        }  
      break;
      case 3: //Ввод имени
        if(!f_edit)
          {
          if(_LEFT) {  list_ini(menuT1L, pos[2]-1); pos[2]=0; BEEP; break; }
          if(_RIGHT) { f_edit=1; g_rep=REP_FAST; BEEP; break; }
          change_paru(&pos[3], 7);
          break;
          }
        if(_LEFT)  { f_edit=0; g_rep=REP_SLOW; BEEP; break; } 
        if(_RIGHT) { if(pos[3]<7) pos[3]++; else pos[3]=0; BEEP; break; }  
        change_name_ch(&cur_model.name[pos[3]]); // Смена символа
      break;    
      case 4: //Выбор типа модели
        if(_LEFT)  { list_ini(menuT1L, pos[2]-1); pos[2]=0; BEEP; break; }
        if (_DOWN || _UP ) { cur_model.type=!cur_model.type; BEEP; } 
      break;
      case 5: // Частота
        if(_LEFT) {  list_ini(menuT1L, pos[2]-1); pos[2]=0; BEEP; break; }
        v=cur_model.num_freq;
        change_paru(&v, PLL_CountChannel);
        if(v!=cur_model.num_freq) 
          {
          cur_model.num_freq=v;
          PLL_SetFreq(cur_model.num_freq);
          BEEP;
          }
      break;      
      case 6:  //Выбор модуляции
        if(_LEFT) { list_ini(menuT1L, pos[2]-1); pos[2]=0; BEEP; break; }
        v=cur_model.modulation; change_parr(&v, 1);
        if(cur_model.modulation!=v)
          {
          cur_model.modulation=v;
          if (cur_model.modulation==0) TCCR1A=0x82;
          else if (cur_model.modulation==1) TCCR1A=0xC2;
          }  
      break;
      case 7: //количество каналов
        if(_LEFT) { list_ini(menuT1L, pos[2]-1); pos[2]=0; BEEP; break; }
        if (_UP && cur_model.num_ch<8) {  cur_model.num_ch++; BEEP; } 
        if (_DOWN && cur_model.num_ch>2) {  cur_model.num_ch--; BEEP; }  
      break;
      case 8: // TIMER
        switch(pos[3])
          {
          case 0:
          if(_LEFT) { list_ini(menuT1L, pos[2]-1); pos[2]=0; BEEP; }
          if(_RIGHT) 
            {
            pos[3]=g_list_selitem+1; pos[4]=0; 
            if(pos[3]==1) g_rep=REP_FAST;
            BEEP;
            break; 
            }
          list_scroll();
          break;
          case 1: //установка времени
          if(_LEFT) { list_ini(menuT3L, pos[3]-1); pos[3]=0; g_rep=REP_SLOW; BEEP; break; }
          i=cur_model.timer_set/10;
          i=change_par(i, 0, 359);
          cur_model.timer_set=i*10;
          break;
          case 2: //выбор режима
          if(_LEFT)  { list_ini(menuT3L, pos[3]-1); pos[3]=0; BEEP; break; }
          v=cur_model.timer_mode; change_paru(&v, 2); cur_model.timer_mode=v; 
          break;
          }
      break;  
      case 9:  //Копирование настроек режима
      if(!f_edit)
        {
        if(_LEFT) { list_ini(menuT1L, pos[2]-1); pos[2]=0; BEEP; break; }
        if(_RIGHT)
          {
          if(pos[3]<2) { f_edit=1; BEEP; break; }
          cur_model.modes[T[1]]=cur_model.modes[T[0]];
          list_ini(menuT1L, pos[2]-1); pos[2]=0; BEEP;  break;
          }
        change_parr(&pos[3], 2);  
        break;
        }
      if(_LEFT) { f_edit=0; BEEP; break; }
      if(_RIGHT) { if(pos[3]<1) pos[3]++; else pos[3]=0; BEEP; break; }
      if(pos[3]<2) { change_parr(&T[pos[3]], 2); break; }
      break;
      case 10: // Reset
        if(_LEFT) // Cancel 
          { list_ini(menuT1L, pos[2]-1); pos[2]=0; BEEP; break; }
        if(_RIGHT) 
          { // OK
          BEEP1;
          MODEL_reset(cur_model_ind);
          MODEL_init(cur_model_ind);
          list_ini(menuT1L, pos[2]-1); pos[2]=0;
          }
      break;
      case 11: // Save
        if(_RIGHT) 
         {
         switch(g_list_selitem)
           {
         case 0: // Save
           BEEP1; 
           EEPR_models[cur_model_ind]=cur_model;
           SetCRC_EEPROM();
         break; 
         case 1: BEEP; break; // Cancel
         case 2: // Restore
           BEEP;
           MODEL_init(cur_model_ind);
         break; 
           }
         pos[0]=0; g_rep=0;  
//         list_ini(menuT0L, pos[1]-1); pos[1]=0;
         break;  
         }
       list_scroll();
      break;
      }
    break;  
    case 3: //Копирование настроек модели
      if(!f_edit)
        {
        if(_LEFT) { list_ini(menuT0L, pos[1]-1); pos[1]=0; BEEP; break; }
        if(_RIGHT)
          {
          if(pos[2]<2) { f_edit=1; BEEP; break; }
          BEEP1;
          MODEL_copy(T[0],T[1]); 
          MODEL_init(cur_model_ind);
          list_ini(menuT0L, pos[1]-1); pos[1]=0;
          break;
          }
        change_parr(&pos[2], 2);  
        break;
        }
      if(_LEFT) { f_edit=0; BEEP; break; }
      if(_RIGHT) { if(pos[2]<1) pos[2]++; else pos[2]=0; BEEP; break; }
      if(pos[2]<2)
        {
        change_parr(&T[pos[2]], MAX_MODELS-1);
        break;
        }
    break;
    case 4: // OPTION
    switch(pos[2])
      {
      case 0:
        if(_LEFT) { list_ini(menuT0L, pos[1]-1); pos[1]=0;  BEEP; }
        if(_RIGHT) 
          {
          pos[2]=g_list_selitem+1; pos[3]=0;
          if(pos[2]==2) list_ini(menuT6L, 0);
          if(pos[2]==3) g_list_selitem=0;
          if(pos[2]==4) { EIMSK|=0x01; EIFR=0x01; }
          BEEP; break; 
          }
        list_scroll();
      break;
      case 1: // Sound
        if (_DOWN || _UP) { f_sound_en=!f_sound_en; BEEP; break;}
        if (_LEFT)
          {
          BEEP1;
          EEPR_f_sound_en=f_sound_en; 
          SetCRC_EEPROM();
          list_ini(menuT4L, pos[2]-1); pos[2]=0;
          break;
          }
      break;
      case 2: // Alarms
        switch(pos[3])
          {
        case 0:
          if(_LEFT) {  list_ini(menuT4L, pos[2]-1); pos[2]=0; BEEP; break;}
          if(_RIGHT) 
            {
            pos[3]=g_list_selitem+1; pos[4]=0; f_edit=0;
            if(pos[3]==2) g_rep=REP_FAST;
            BEEP; 
            break; 
            }
          list_scroll();
        break;
        case 1: // Battery
          if(!f_edit)
            {
            if(_LEFT) {  list_ini(menuT6L, pos[3]-1); pos[3]=0; BEEP; break;}
            if(_RIGHT) { f_edit=1; g_rep=REP_FAST; BEEP; break;}
            change_parr(&pos[4], 2);
            break;
            }
          if(_LEFT) 
            {
            f_edit=0; g_rep=REP_SLOW;
            BEEP1;
            EEPR_BatCntr[pos[4]]=BatCntr[pos[4]];
            SetCRC_EEPROM();
            break; 
            }
          if(_RIGHT)
            {  if(++pos[4]>2) pos[4]=0; BEEP; break; }
          change_paru( &BatCntr[pos[4]], 130);            
        break;
        case 2: // Antenna
          if(_LEFT) 
            {
            BEEP1;
            EEPR_AntCntr=gAntCntr; 
            SetCRC_EEPROM();
            list_ini(menuT6L, pos[3]-1); pos[3]=0; g_rep=REP_SLOW;
            break;
            }
          change_paru( &gAntCntr, 100);
        break;          
          }
      break;        
      case 3: // Monitor
        if(_LEFT) {  list_ini(menuT4L, pos[2]-1); pos[2]=0; BEEP; break; }
        if(_RIGHT) { pos[3]=!pos[3]; BEEP; break; }
        if (_DOWN &&  g_list_selitem<(cur_model.num_ch-MAX_LIST_LINES)) { g_list_selitem++; BEEP; break; }
        if (_UP && g_list_selitem) { g_list_selitem--; BEEP; break; }        
      break;
      case 4: // Tachometer
        if(_LEFT) {  EIMSK&=0xfe; list_ini(menuT4L, pos[2]-1); pos[2]=0; BEEP; break; }
      break;
      case 5: // Version
        if(_LEFT) {  list_ini(menuT4L, pos[2]-1); pos[2]=0; BEEP; break; }
      break;
      }
    break;
    }
  break;
  }
mnu_keys=0;
}
//-------------------------------------------------------------
void TX_init(void)
{
char i;

cur_model_ind=EEPR_start_model;
f_sound_en=EEPR_f_sound_en;
BatCntr[0]=EEPR_BatCntr[0];
BatCntr[1]=EEPR_BatCntr[1];
BatCntr[2]=EEPR_BatCntr[2];
gAntCntr=EEPR_AntCntr;
CalibrTemperature[0]=EPPR_CalibrTemperature[0];  
CalibrTemperature[1]=EPPR_CalibrTemperature[1];  
for (i=0; i<5; i++)
  {
  ADmin[i]=EEPR_ADmin[i];
  ADmid[i]=EEPR_ADmid[i];
  ADmax[i]=EEPR_ADmax[i];
  }
MODEL_init(cur_model_ind);
}
//---------------------------------------------------------------------------
#define SIZEOF_EEPROM 4*1024
#define POLINOM 33800   // (15-0)+(15-5)+(15-12)
unsigned int CalcCRC_EEPROM(void)
{
unsigned int i;
unsigned char m, pr, v;
union  { unsigned int r; unsigned char rb[2]; } rr;
eeprom unsigned char *p;

p=0;
rr.r=0;
for(i=0; i<SIZEOF_EEPROM; i++, p++)
  {
  v=*p;
  for(m=1; m; m<<=1)
    {
    pr=(rr.rb[0] & 1);
    rr.r>>=1;
    if(i<(SIZEOF_EEPROM-2) && (v & m ))  rr.rb[1]|=0x80;
    if(pr)  rr.r^=POLINOM;
    }
  }
return rr.r;
}
//---------------------------------------------------------------------------
void SetCRC_EEPROM(void)
{
unsigned int crc;
eeprom unsigned int *p;

crc=CalcCRC_EEPROM();
p=(eeprom unsigned int *)(SIZEOF_EEPROM-2);
*p=crc;
}
//---------------------------------------------------------------------------
unsigned char VerifyCRC_EEPROM(void)
{
unsigned int crc;
eeprom unsigned int *p;

p=(eeprom unsigned int *)(SIZEOF_EEPROM-2);
crc=CalcCRC_EEPROM();
if(crc!=*p) return 1;
return 0;
}
//---------------------------------------------------------------------------


