#include <Wire.h>
#include <LiquidCrystal.h>
#include "Rotary.h"
#include <si5351.h>
#include <EEPROM.h>

// Регистры управления 595
//#define BPF_CLK		13
//#define BPF_DATA		11
//#define BPF_LATCH		10

// Подключение модуля синтезатора
//#define W_CLK			13
//#define FQ_UD			12
//#define DATA			11

// Раскомментарить для настройки кейпада
//#define Keypad_ADC

// Раскомментарить для включения CAT
#define CAT_SPEED   19200

//Раскомментировать если требуется сброс EEPROM
#define INIT_EEPROM

// Подключение дешифратора диапазонов К561ИД1 ( CD4028 )
#define BPF_D0			A2
#define BPF_D1			A1
#define BPF_D2			A0
#define BPF_D3			13

//Управление ATT / Preamp
#define ATT			11
#define PRE			12

// Коррекция расчета частоты si5351 для записи в EEPROM при инициализации
#define SI5351_INITIAL_CORR 0
// Подберите емкость из 0PF 6PF 8PF при коррекции = 0 для получения 
// частоты синтезатора равной или чуть больше, чем на экране.
// Затем коррекцией подгоните до нужной (при увеличении коррекции уменьшается частота на выходе)
#define SI5351_CRYSTAL_LOAD0 SI5351_CRYSTAL_LOAD_6PF
// Здесь введите частоту вашего кварца на si5351
#define SI5351_CRYSTAL_FREQ 27000000
// Ток выходов si5351
//   основной 
#define SI5351_DRIVE_CLK0 SI5351_DRIVE_8MA
//   опорник 1й ПЧ
#define SI5351_DRIVE_CLK2 SI5351_DRIVE_2MA
// Показание на ЖКИ плюс(минус) на значение ПЧ (базовая при инициализации)
#define IFFreq			10700000
// Вторая ПЧ (оставить 0 если не нужна, определяет вместе с IFFreq частоту опорника 1й ПЧ, можно - и +)
#define IFFreq2     455000
// Вкл/выкл генерации опорного гетеродина 1й ПЧ на втором выходе si5351 (закомментарить если не нужено)
#define IFFreqSIOut 
// Общая частота изменения преобразования вверх/вниз (внутри диапазонов индивидуальные настройки)
// Логика работы с ПЧ описана в функции sendFrequency()
#define IFUpDn	 	 13880000

// Блокировка выхода за границы диапазонов, не работает вроде :)
//#define LockInBand

// Управление TX/RX (активный LOW - TX)
#define TXRX		  	4

// Клавиатура, S- метр, P- метр.
#define KEYPAD			A3
#define SMETER			A6
#define PMETER			A7

#define MAXFREQ			1590000000
#define MINFREQ			1000000
#define MAXIFFREQ   11000000
#define MINIFFREQ   8000000

#define TIME_DISPLAY_RATE	1500

#define  SMETER_1      80
#define  SMETER_2      120
#define  SMETER_3      160
#define  SMETER_4      200
#define  SMETER_5      240
#define  SMETER_6      280
#define  SMETER_7      320
#define  SMETER_8      360
#define  SMETER_9      400
#define  SMETER_9_10   440
#define  SMETER_9_20   480
#define  SMETER_9_30   520

#define  PMETER_1      80
#define  PMETER_2      120
#define  PMETER_3      160
#define  PMETER_4      200
#define  PMETER_5      240
#define  PMETER_6      280
#define  PMETER_7      320
#define  PMETER_8      360
#define  PMETER_9      400
#define  PMETER_10     440
#define  PMETER_11     480
#define  PMETER_12     520

#define  BAND_MAX      9            //Число диапазонов для обработки
// Границы диапазонов 
// 160-метровый (1,81 - 2 МГц)
#define  BAND_01_LOW   144000000      //Нижняя граница диапазона
#define  BAND_01_HIGH  145000000      //Верхняя граница диапазона
#define  BAND_01_NUM   1            //Номер диапазона (для вычисления ячеек EEPROM)
#define  BAND_01_EN    true         //Диапазон включен (если false - будет игнорироваться)
#define  BAND_01_DSSB  0            //Верхняя / нижняя боковая по умолчанию (пока не используется)
#define  BAND_01_INV   -1            //-1 (онимает ПЧ) 1 (прибавляет)Инверсия боковой (пока не используется)
#define  BAND_01_NAME  "2 m"        //Название диапазона
// 80-метровый (3,5 - 3,8 МГц)
#define  BAND_02_LOW   145000001
#define  BAND_02_HIGH  146000000
#define  BAND_02_NUM   2
#define  BAND_02_EN    true
#define  BAND_02_DSSB  0
#define  BAND_02_INV   -1
#define  BAND_02_NAME  "2 m"        //Название диапазона
// 40-метровый (7 - 7,2 МГц)
#define  BAND_03_LOW   146005000
#define  BAND_03_HIGH  147000000
#define  BAND_03_NUM   3
#define  BAND_03_EN    true
#define  BAND_03_DSSB  0
#define  BAND_03_INV   -1
#define  BAND_03_NAME  "2 m"        //Название диапазона
// 30-метровый (только телеграф 10,1 - 10,15 МГц)
#define  BAND_04_LOW   147005000
#define  BAND_04_HIGH  148000000
#define  BAND_04_NUM   4
#define  BAND_04_EN    true
#define  BAND_04_DSSB  0
#define  BAND_04_INV   -1
#define  BAND_04_NAME  "2 m"        //Название диапазона
// 20-метровый (14 - 14,35 МГц)
#define  BAND_05_LOW   148005000
#define  BAND_05_HIGH  148050000
#define  BAND_05_NUM   5
#define  BAND_05_EN    true
#define  BAND_05_DSSB  0
#define  BAND_05_INV   -1
#define  BAND_05_NAME  "MVD"        //Название диапазона
// 16-метровый (18,068 - 18,168 МГц)
#define  BAND_06_LOW   148051000
#define  BAND_06_HIGH  148175000
#define  BAND_06_NUM   6
#define  BAND_06_EN    true
#define  BAND_06_DSSB  0
#define  BAND_06_INV   -1
#define  BAND_06_NAME  "MVD"        //Название диапазона
// 15-метровый (21 - 21,45 МГц)
#define  BAND_07_LOW   148185000
#define  BAND_07_HIGH  148375000
#define  BAND_07_NUM   7
#define  BAND_07_EN    true
#define  BAND_07_DSSB  0
#define  BAND_07_INV   -1
#define  BAND_07_NAME  "ITK"        //Название диапазона
// 12-метровый (24,89 - 25,14 МГц)
#define  BAND_08_LOW   148376000
#define  BAND_08_HIGH  148875000
#define  BAND_08_NUM   8
#define  BAND_08_EN    true
#define  BAND_08_DSSB  0
#define  BAND_08_INV   -1
#define  BAND_08_NAME  "MCS"        //Название диапазона
// 10-метровый (28 - 29,7 МГц)
#define  BAND_09_LOW   148876000
#define  BAND_09_HIGH  174000000
#define  BAND_09_NUM   9
#define  BAND_09_EN    true
#define  BAND_09_DSSB  0
#define  BAND_09_INV   -1
#define  BAND_09_NAME  "RZD"        //Название диапазона

// Границы диапазонов для коммутации ДПФ 
#define  BAND_BPF_01_LOW   144000000      //Нижняя граница диапазона
#define  BAND_BPF_01_HIGH  145000000       //Верхняя граница диапазона
#define  BAND_BPF_01_CODE  0b000000000  //Код для управления ДПФ

#define  BAND_BPF_02_LOW   145000001 
#define  BAND_BPF_02_HIGH  146000000 
#define  BAND_BPF_02_CODE  0b00001000

#define  BAND_BPF_03_LOW   146000001 
#define  BAND_BPF_03_HIGH  148000000 
#define  BAND_BPF_03_CODE  0b00000100

#define  BAND_BPF_04_LOW   148000001 
#define  BAND_BPF_04_HIGH  151000000 
#define  BAND_BPF_04_CODE  0b000001100

#define  BAND_BPF_05_LOW   151000001
#define  BAND_BPF_05_HIGH  155000000
#define  BAND_BPF_05_CODE  0b000000010

#define  BAND_BPF_06_LOW   155000001
#define  BAND_BPF_06_HIGH  164000000
#define  BAND_BPF_06_CODE  0b000001010

#define  BAND_BPF_07_LOW   164000001
#define  BAND_BPF_07_HIGH  170000000
#define  BAND_BPF_07_CODE  0b000000110

#define  BAND_BPF_08_LOW   170000001
#define  BAND_BPF_08_HIGH  171000000
#define  BAND_BPF_08_CODE  0b000001110

#define  BAND_BPF_09_LOW   171000001
#define  BAND_BPF_09_HIGH  174000000
#define  BAND_BPF_09_CODE  0b000000001

// Значения уровня с АЦП для кнопок на делителе _1 нижнее _2 верхнее
// 1я кнопка
#define  BUTTON1_1  700
#define  BUTTON1_2  950
// 2я кнопка
#define  BUTTON2_1  500
#define  BUTTON2_2  690
// 3я кнопка
#define  BUTTON3_1  310
#define  BUTTON3_2  490
// 4я кнопка
#define  BUTTON4_1  160
#define  BUTTON4_2  240
// 5я кнопка
#define  BUTTON5_1  80
#define  BUTTON5_2  140
// 6я кнопка
#define  BUTTON6_1  0
#define  BUTTON6_2  30

#define pulseHigh(pin) { digitalWrite(pin, HIGH); delay(1); digitalWrite(pin, LOW); delay(1); }

struct Band {
  int_fast8_t	  num;
  int_fast8_t	  xnum;  
  int_fast8_t	  dssb;
  int_fast8_t	  inv;
  int_fast8_t	  nd;  
  int_fast8_t   ld;    
  int_fast16_t	bpf;  
  int_fast16_t	xbpf;    
  int_fast32_t	fhigh;
  int_fast32_t	flow;
  char          bname[4];
};

Band band = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "   "};

struct Mode {
//  int_fast8_t mode;
//  int_fast8_t cw_dir_freq;
//  int_fast8_t inv;
  unsigned int code;  
  String modename;
};

//Биты управления режимами через внешний регистр
Mode mode_m[4] = {0xFF, "", 0b0000000000000000, "USB", 0b1000000000000000, "LSB", 0xFF, ""};

Rotary r = Rotary(2,3); // sets the pins the rotary encoder uses. Must be interrupt pins.
//Подключаем энкодер к 2 и 3 ножкам
LiquidCrystal lcd(5, 6, 7, 8, 9, 10); // I used an odd pin combination because I need pin 2 and 3 for the interrupts.
//Подключаем 1602 дисплей к соответствующим пинам, указываем номера портов в порядке RS, E, DB4, DB5, DB6, DB7
int_fast32_t rx           = 10000000; // Base (starting) frequency of VFO. This only loads once. To force load again see ForceFreq variable below.
int_fast32_t si5351_corr  = SI5351_INITIAL_CORR;  // Base correction for si5351 chip.
int_fast32_t xsi5351_corr = 1;
int_fast32_t rx2          = 1; // variable to hold the updated frequency
// Переменная для хранения новой частоты
int_fast32_t increment    = 1000; // starting VFO update increment in HZ.
// Установка шага на один щелчек энкодера при запуске.
int_fast32_t iffreq       = IFFreq; // variable to hold the updated frequency
int_fast32_t xiffreq      = 1;

int_fast16_t buttonstate  = 0;  // Значение АЦП кейпада
int_fast16_t obuttonstate = 0;  // Предыдущее значение АЦП кейпада
int_fast16_t smeter       = 0;  // Значение АЦП S-метра
int_fast16_t pmeter       = 0;  // Значение АЦП P-метра

int_fast16_t xbuttonstate[7] = { 0,0,0,0,0,0,0 }; //Массив предыдущих стостояний кнопок

int_fast8_t  mode         = 1;  // Текущий режим 
int_fast8_t  xmode        = 0;  // Предыдущий режим

int_fast8_t  tx_mode      = 0;  // Текущий режим TX/RX
int_fast8_t  xtx_mode     = 0;  // Предыдущий режим TX/RX

int_fast8_t  att_preamp   = 0;  // Att / Preamp побитно

int_fast8_t  com_mode     = 0;  // Общий режим работы устройства
                                // 0 - управление основной частотой
                                // 1 - управление ПЧ
                                // 2 - управление коррекцией si5351

//int_fast16_t GoIF          = 1;  // Состояние вычета ПЧ
//int_fast16_t xGoIF         = 0;  // Старое состояние вычета ПЧ

String hertz = "100 Hz"; //Нужно для установки шага энкодера, при необходимости раскомментировать.
int hertzPosition = 5;

byte ones,tens,hundreds,thousands,tenthousands,hundredthousands,millions ; //Десятичные разряды представления частоты (для EEPROM)

String freq; // string to hold the frequency
//Строка для хранения частоты
String smtr; // string to hold the s-meter value
//Строка для хранения значения S-метра
String xsmtr; // string to hold the s-meter old value 
//Строка для хранения предыдущего значения S-метра
unsigned long timepassed = millis(); // int to hold the arduino miilis since startup
// Для хранения числа миллисекунд, прошедших с момента запуска
unsigned long rate_timepassed = millis(); // Для хранения числа миллисекунд идникации шага частоты
int memstatus = 0; // value to notify if memory is current or old. 0=old, 1=current.
// Смотрим, в памяти значение старое или новое. 0 - Старое 1 -Новое

Si5351 si5351; // Синтезатор

byte lcd_sym_01[8] = { 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b11111, 0b11111 };
byte lcd_sym_02[8] = { 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b11111, 0b11111, 0b11111 };
byte lcd_sym_03[8] = { 0b00000, 0b00000, 0b00000, 0b00000, 0b11111, 0b11111, 0b11111, 0b11111 };
byte lcd_sym_04[8] = { 0b00000, 0b00000, 0b00000, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111 };
byte lcd_sym_05[8] = { 0b00000, 0b00000, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111 };
byte lcd_sym_06[8] = { 0b00000, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111 };
byte lcd_sym_07[8] = { 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111 };

// Для CAT
boolean CATTXState=0;
boolean xCATTXState=1;
#ifdef CAT_SPEED
int  buffget[11];
int  incoming;
byte sendDMHz=0;
byte sendMHz=0;
byte sendkHz=0;
byte sendHz=0;
int  DMHZ = 0;
int  MHZ = 0;
int  KHZ = 0;
int  HZ = 0;
//int  slowo=0;
int  CTi=0;
int  bandCAT=0;
long QRG;
#endif

// быстрое деление для преобразования числа в строку
void divmodu10(uint32_t n, uint32_t &quot, uint8_t &rem) {
    quot = n >> 1;
    quot += quot >> 1;
    quot += quot >> 4;
    quot += quot >> 8;
    quot += quot >> 16;
    uint32_t qq = quot;
    quot >>= 3;
    rem = uint8_t(n - ((quot << 1) + (qq & ~7ul)));
    if(rem > 9)
    {
        rem -= 10;
        quot++;
    }
}

// быстрое преобразования числа в строку с разделителем разрядов
// , uint8_t tcnt
char * utoa_fast_div(uint32_t value, char *buffer, uint8_t tcnt) {
    uint8_t  dcnt = 0;
    uint32_t quot;
    uint8_t  rem;
    uint8_t  ocnt = tcnt;
    buffer[--tcnt] = 0;
    if (com_mode < 2) {
      buffer[--tcnt] = 'z';
      buffer[--tcnt] = 'H';
      buffer[--tcnt] = 'k';
      buffer[--tcnt] = ' ';
      divmodu10(value, quot, rem);
      value = quot;      
    } else {
      buffer[--tcnt] = ' ';
      buffer[--tcnt] = ' ';
      buffer[--tcnt] = ' ';
      buffer[--tcnt] = ' ';
    }  
    do
    {
      divmodu10(value, quot, rem);
      buffer[--tcnt] = rem + '0';
      if ((tcnt == (ocnt - 7)) && (com_mode < 2)) buffer[--tcnt] = '.';
      value = quot;
    }
    while ((value != 0) && (tcnt > 1));
    while (tcnt > 0) {
      buffer[--tcnt] = ' ';
    };

    tcnt = ocnt - 9;
    while (tcnt > 0) {
      buffer[tcnt + 3] = buffer[tcnt];
      buffer[tcnt] = ' ';
      tcnt--;
    }

    return buffer;
}

void setup() {

//Для I2C LCD
//lcd.init();
//lcd.backlight();

lcd.begin(16, 2); //Указываем сколько у нас символов и строк на дисплее.

// Спецсимволы для S/P метра
lcd.createChar(1, lcd_sym_01);
lcd.createChar(2, lcd_sym_02);
lcd.createChar(3, lcd_sym_03);
lcd.createChar(4, lcd_sym_04);
lcd.createChar(5, lcd_sym_05);
lcd.createChar(6, lcd_sym_06);
lcd.createChar(7, lcd_sym_07);

PCICR  |= (1 << PCIE2);
PCMSK2 |= (1 << PCINT18) | (1 << PCINT19);
sei();

//pinMode(FQ_UD, OUTPUT); //Выставляем вывод как цифровой выход
//pinMode(W_CLK, OUTPUT); //Выставляем вывод как цифровой выход
//pinMode(DATA,  OUTPUT); //Выставляем вывод как цифровой выход

//pinMode(BPF_CLK,   OUTPUT); 
//pinMode(BPF_DATA,  OUTPUT); 
//pinMode(BPF_LATCH, OUTPUT); 

pinMode(BPF_D0, OUTPUT); 
pinMode(BPF_D1, OUTPUT); 
pinMode(BPF_D2, OUTPUT); 
pinMode(BPF_D3, OUTPUT); 

pinMode(ATT, OUTPUT); 
pinMode(PRE, OUTPUT); 

pinMode(TXRX, INPUT); 
digitalWrite(TXRX, HIGH);

Wire.begin();
// **mine. There is a calibration sketch in File/Examples/si5351Arduino
// where you can determine the correction by using the serial monitor.
// ввести калибровочное знечение в строчке si5351.set_correction(хххххххх).
// Нужно вычислить запустив "si5351calibration" в папке с примерами библиотеки si5351.
// initialize the Si5351
si5351.init(SI5351_CRYSTAL_LOAD0, SI5351_CRYSTAL_FREQ, 0); 
// If you're using a 27Mhz crystal, put in 27000000 instead of 0
// 0 is the default crystal frequency of 25Mhz.

si5351.output_enable(SI5351_CLK0, 1);
si5351.output_enable(SI5351_CLK1, 0);
si5351.output_enable(SI5351_CLK2, 0);
// 2MA ~ 7dbm, 8MA ~ 14dbm
si5351.drive_strength(SI5351_CLK0, SI5351_DRIVE_CLK0);

#ifdef INIT_EEPROM
  initMem();
#endif

// Load the stored frequency
//Загружаем сохраненную частоту
if (keypooler() == 6) {
  initMem();
} else {
  restoreMem();
  decodeband(rx);
};
memstatus = 1;

si5351.set_correction(si5351_corr, SI5351_PLL_INPUT_XO); 
xsi5351_corr = si5351_corr;
si5351.set_pll(SI5351_PLL_FIXED, SI5351_PLLA);

#ifdef IFFreqSIOut
   si5351.drive_strength(SI5351_CLK2, SI5351_DRIVE_CLK2);
   si5351.output_enable(SI5351_CLK2, 1);
   //si5351.set_freq((iffreq + IFFreq2) * SI5351_FREQ_MULT, SI5351_PLL_FIXED, SI5351_CLK2);
   si5351.set_freq((iffreq + ((mode_m[mode].modename=='LSB')?-1:1)*IFFreq2) * SI5351_FREQ_MULT, SI5351_PLL_FIXED, SI5351_CLK2);
   xiffreq = iffreq;
#endif

#ifdef CAT_SPEED
   Serial.begin(CAT_SPEED);
#endif

//pinMode(RESET, OUTPUT); //Выставляем вывод как цифровой выход
//pulseHigh(RESET);

//pulseHigh(W_CLK);
//pulseHigh(FQ_UD); // this pulse enables serial mode on the AD9850 - Datasheet page 12.

// Этот импульс необходим для последовательной шины, Datasheet страница 12.
//pinMode(KEYPAD,INPUT);   // Конфигурируем порт кейпада
//pinMode(SMETER,INPUT);   // Конфигурируем порт S-метра

//pinMode(PINGOIF,INPUT);     // Конфигурируем вход вычета ПЧ
//digitalWrite(PINGOIF,HIGH); // Подтягиваем вход вычета ПЧ к плюсу питания 

//Serial.begin(115200);
//lcd.setCursor(hertzPosition,1);
//lcd.print(hertz);        // Начало настроек для выбора кнопки переключения шага энкодера----------------
};

void loop() {
int keypressed;  

#ifdef LockInBand
// Если используется блокировка выхода за пределы диапазонов
   if ((rx != rx2) && ((rx < band.flow) || (rx > band.fhigh)) && (band.nd == 0)) rx = rx2;
#endif

#ifdef CAT_SPEED
 if (Serial.available() > 0){
   catread();
 }
#endif

// Обновляем информацию на дисплее и частоту синтезатора если она (частота) изменилась
if ((rx != rx2)||(iffreq != xiffreq)||(si5351_corr != xsi5351_corr))  {
  if (si5351_corr != xsi5351_corr) {
    si5351.set_correction(si5351_corr, SI5351_PLL_INPUT_XO); 
    si5351.set_pll(SI5351_PLL_FIXED, SI5351_PLLA);
    #ifdef IFFreqSIOut  
    //si5351.set_freq((iffreq + IFFreq2) * SI5351_FREQ_MULT, SI5351_PLL_FIXED, SI5351_CLK2);
    si5351.set_freq((iffreq + ((mode_m[mode].modename=='LSB')?-1:1) * IFFreq2) * SI5351_FREQ_MULT, SI5351_CLK2);
    #endif  
    sendFrequency(rx);    
  }
  //mode_m[mode].modename
  #ifdef IFFreqSIOut  
  if (iffreq != xiffreq) {
   //si5351.set_freq(iffreq + IFFreq2 * SI5351_FREQ_MULT, SI5351_PLL_FIXED, SI5351_CLK2);
   si5351.set_freq(iffreq + ((mode_m[mode].modename=='LSB')?-1:1) * IFFreq2 * SI5351_FREQ_MULT, SI5351_CLK2);
   sendFrequency(rx);
  }
  #endif  
  if (rx != rx2) {
    decodeband(rx);
    if (band.bpf != band.xbpf) {
      sendReg(mode_m[mode].code + band.bpf);  
      band.xbpf = band.bpf;
      if (band.num != band.xnum) { band.xnum = band.num; }
    }
    if (band.num != band.xnum) {
      sendReg(mode_m[mode].code + band.bpf);
      band.xnum = band.num;
    }
    sendFrequency(rx);  
  }
  if (com_mode == 0) { showFrequency(rx); }
  if (com_mode == 1) { showFrequency(iffreq); }
  if (com_mode == 2) { showFrequency(si5351_corr); }
  if ((rx2 != 1)&&(xiffreq != 1)&&(xsi5351_corr != 1)) {
    memstatus = 0;
    timepassed = millis() + 5000;    
  }
  rx2 = rx;
  xiffreq = iffreq;
  xsi5351_corr = si5351_corr;
};

if (mode != xmode) { 
  sendReg(mode_m[mode].code + band.bpf);
  showMode(mode); 
}

#ifdef CAT_SPEED
if (CATTXState != xCATTXState) {
//   lcd.setCursor(1,1);
//   lcd.print(" TM1            ");
//   lcd.setCursor(6,1);
//   lcd.print(tx_mode, DEC);  //28
//   delay(1000);  
if ((CATTXState == 1)&&(xCATTXState == 0)) {
  tx_mode = HIGH;
  showOptions();
}
//   lcd.setCursor(1,1);
//   lcd.print(" TM2            ");
//   lcd.setCursor(6,1);
//   lcd.print(tx_mode, DEC);  //28
//   delay(1000);  
if ((CATTXState == 0)&&(xCATTXState == 1)&(xtx_mode == LOW)) {
  tx_mode = LOW;
  showOptions();
}
xCATTXState = CATTXState;
} else if ((CATTXState == 0)&&(xCATTXState == 0)) {
  // Считываем TX / RX
  // На всякий случай антидребезг
  tx_mode = !digitalRead(TXRX);
  if (tx_mode != xtx_mode) {
   delay(10);
   tx_mode   = !digitalRead(TXRX);
   if (tx_mode != xtx_mode) {
      xtx_mode  = tx_mode; 
      showOptions();
   } else {
      tx_mode = xtx_mode;
   }   
}
}
#else
if (tx_mode != xtx_mode) {
   delay(10);
   tx_mode   = !digitalRead(TXRX);
   if (tx_mode != xtx_mode) {
      xtx_mode  = tx_mode; 
      showOptions();
   } else {
      tx_mode = xtx_mode;
   }   
}
#endif

#ifdef Keypad_ADC
   buttonstate  = analogRead(KEYPAD);
   lcd.setCursor(0,1);
   lcd.print("                ");
   lcd.setCursor(5,1);
   lcd.print(buttonstate);
   delay(1000);   
#endif
   
//Проверяем не нажата ли кнопка кейпада
keypressed = keypooler();

//  Функции кнопок
switch (keypressed) {
    case 0:
      break;
    case 1:
      setAttPre();    
      break;
    case 2:
      setBand(-1);
      break;
    case 3:
      setBand(1);
      break;
    case 4:
      setMode();
      break;
    case 5:
      setComMode();
      break;
    case 6:
      setIncrement(); 
      break;
    default:  
      break;
  }

//Преобразуем значение уровня S-метра в строку
smtr = " ";
if (tx_mode) {
      pmeter = analogRead(PMETER); // Считываем значение АЦП P-метра
   } else {
      smeter = analogRead(SMETER); // Считываем значение АЦП S-метра 
   }

if (!tx_mode) {
if  (smeter > SMETER_9_30)
    {  smtr += "\02\02\03\03\04\04\05\06\07+30";  } else
    if  (smeter > SMETER_9_20)
    {  smtr += "\02\02\03\03\04\04\05\06\07+20";  } else
    if  (smeter > SMETER_9_10)
    {  smtr += "\02\02\03\03\04\04\05\06\07+10";  } else
    if  (smeter > SMETER_9)
    {  smtr += "\02\02\03\03\04\04\05\06\07   ";  } else
    if  (smeter > SMETER_8)
    {  smtr += "\02\02\03\03\04\04\05\06    ";  } else
    if  (smeter > SMETER_7)
    {  smtr += "\02\02\03\03\04\04\05     ";  } else
    if  (smeter > SMETER_6)
    {  smtr += "\02\02\03\03\04\04      ";  } else
    if  (smeter > SMETER_5)
    {  smtr += "\02\02\03\03\04       ";  } else
    if  (smeter > SMETER_4)
    {  smtr += "\02\02\03\03        ";  } else
    if  (smeter > SMETER_3)
    {  smtr += "\02\02\03         ";  } else
    if  (smeter > SMETER_2)
    {  smtr += "\02\02          ";  } else
    if  (smeter > SMETER_1)
    {  smtr += "\02           ";  } else
    {                };
} else {
if  (pmeter > PMETER_12)
    {  smtr += "\02\02\03\03\04\04\05\05\06\06\07\07";  } else
    if  (pmeter > PMETER_11)
    {  smtr += "\02\02\03\03\04\04\05\05\06\06\07 ";  } else
    if  (pmeter > PMETER_10)
    {  smtr += "\02\02\03\03\04\04\05\05\06\06  ";  } else
    if  (pmeter > PMETER_9)
    {  smtr += "\02\02\03\03\04\04\05\05\06   ";  } else
    if  (pmeter > PMETER_8)
    {  smtr += "\02\02\03\03\04\04\05\05    ";  } else
    if  (pmeter > PMETER_7)
    {  smtr += "\02\02\03\03\04\04\05     ";  } else
    if  (pmeter > PMETER_6)
    {  smtr += "\02\02\03\03\04\04      ";  } else
    if  (pmeter > PMETER_5)
    {  smtr += "\02\02\03\03\04       ";  } else
    if  (pmeter > PMETER_4)
    {  smtr += "\02\02\03\03        ";  } else
    if  (pmeter > PMETER_3)
    {  smtr += "\02\02\03         ";  } else
    if  (pmeter > PMETER_2)
    {  smtr += "\02\02          ";  } else
    if  (pmeter > PMETER_1)
    {  smtr += "\02          ";  } else
    {                };
}    
while (smtr.length() < 16)  {  smtr += " ";  };

// Показываем S/P-метр если время индикации шага перестройки вышло
if ((millis() > rate_timepassed) && (xsmtr != smtr)) { showSmeter(); };

// Записываем частоту и другие параметры в постоянную память если они не изменялись поседние 2-3 секунды
if  ((memstatus == 0) && ( timepassed < millis() )) { 
  if (band.nd == 0) { storeMemBand(band.num); }
  storeMem(); 
  };
}

// ********************** поддержка CAT (IC 756) ********************** <
#ifdef CAT_SPEED
void catread(){
   incoming = Serial.read(); delay(3);
   //lcd.setCursor(1,1);
   //lcd.print("CAT             ");
   //lcd.setCursor(5,1);
   //lcd.print(incoming, DEC);  
   //delay(1000);
   //display.print (incoming); display.display();
   if (incoming == 254) {
     Serial.write(incoming);
     Serial.flush();
     incoming=Serial.read(); //delay(3);
     if (incoming == 254){
       Serial.write(incoming);   
       Serial.flush();    
       //display.print(incoming); display.display();
       //delay(3);
       buffget[0] = 0;
       CTi=0;
       do{
         incoming=Serial.read();
         //delay(3);
         Serial.write(incoming);  
         Serial.flush();   
         buffget[CTi]=incoming;
         //display.print (buffget[CTi]); display.print(" "); 
         CTi++;
       } while(incoming!=253); //dopóki nie przyjdzie FD
       Serial.flush();
       delay (1);       
     }
   }
   switch (CTi){
   case 4:
     CATpoll_in();
     break;
   case 5:
     CATsetmode();
     break;
   case 6:
     CATsetmode();
     break;
   case 9:
     CATsetfreq();
     break;
   default:
     FA();
     break;  
   }
}

void CATpoll_in(){
  if (buffget[2]==3){freq_to_send();} 
  if (buffget[2]==4){mode_to_send();} 
}

void CATsetmode() 
{
  if (buffget[2]==6) poll_in_mode(); else
  {
    if (buffget[2]==0x1C) {
      if ((CTi=6)&&(buffget[4]==0x01)) CATTXState = 1;
      if ((CTi=6)&&(buffget[4]==0x00)) CATTXState = 0;
      if ((CTi=5)&&(buffget[3]==0x01)) CATTXState = 1;
      if ((CTi=5)&&(buffget[3]==0x00)) CATTXState = 0;
      if ((CTi=5)&&(buffget[3]==0x00)&&(buffget[4]==0x01)) CATTXState = 1;
      if ((CTi=5)&&(buffget[3]==0x00)&&(buffget[4]==0x00)) CATTXState = 0;
      Serial.write (0xFE);
      Serial.write (0xFE);
      Serial.write (0x50);
      Serial.write (0xE0);
      Serial.write (buffget[2]);
      Serial.write (0xFD);
      Serial.flush();
    } else {
      FA();
    }
  }
//   lcd.setCursor(1,1);
//   lcd.print("CAT             ");
//   lcd.setCursor(6,1);
//   lcd.print(CATTXState, DEC);  //28
//   delay(1000);  
//   lcd.setCursor(1,1);
//   lcd.print("CAT1            ");
//   lcd.setCursor(6,1);
//   lcd.print(buffget[2], DEC);  //28
//   delay(1000);  
//   lcd.setCursor(1,1);
//   lcd.print("CAT2            ");
//   lcd.setCursor(6,1);
//   lcd.print(CTi, DEC);  //5
//   delay(1000); 
//   lcd.setCursor(1,1);
//   lcd.print("CAT3            ");
//   lcd.setCursor(6,1);
//   lcd.print(buffget[3], DEC);  //0
//   delay(1000);  
//   lcd.setCursor(1,1);
//   lcd.print("CAT4            ");
//   lcd.setCursor(6,1);
//   lcd.print(buffget[4], DEC);  //
//   delay(1000);  
//   lcd.setCursor(1,1);
//   lcd.print("                ");
}

void CATsetfreq()
{
  // Установка частоты с компа
  if ((buffget[2]==5)||(buffget[2]==0))
  poll_in_frequency();
} 

void poll_in_mode() 
{
  // Установка режима с компа, пока нет
}

void poll_in_frequency(){    
  // Формируем частоту для установки с компа
  DMHZ = (buffget[6]);                       // Десятки МГц
  DMHZ = DMHZ - (((DMHZ/16) * 6));
  MHZ  = buffget[5];                         // МГц
  MHZ  = MHZ - (((MHZ/16) * 6));             // Трансформируем в формат ICOM CAT 
  KHZ  = buffget[4]; 
  KHZ  = KHZ - (((KHZ/16) * 6));             // Трансформируем в формат ICOM CAT 
  HZ   = buffget[3]; 
  HZ   = HZ - (((HZ/16) * 6));               // Трансформируем в формат ICOM CAT 
  QRG  = (((long(DMHZ)*1000000)+(long(MHZ) * 10000) + (long(KHZ) * 100) + (long(HZ) * 1))); // Собираем частоту из формата MMkkkH

  bandCAT=99;
  if ((DMHZ >= 1)&&(DMHZ < 3))   bandCAT=0;
  if ((DMHZ >= 3)&&(DMHZ < 7))   bandCAT=1;
  if ((DMHZ >= 7)&&(DMHZ < 10))  bandCAT=2;
  if ((DMHZ >= 10)&&(DMHZ < 14)) bandCAT=2;
  if ((DMHZ >= 14)&&(DMHZ < 18)) bandCAT=3;
  if ((DMHZ >= 18)&&(DMHZ < 21)) bandCAT=3;
  if ((DMHZ >= 21)&&(DMHZ < 24)) bandCAT=3;
  if ((DMHZ >= 24)&&(DMHZ < 27)) bandCAT=3;
  if ((DMHZ >= 27)&&(DMHZ < 30)) bandCAT=3;

  if (bandCAT!=99) {
    Serial.write (0xFE);
    Serial.write (0xFE);
    Serial.write (0x50);
    Serial.write (0xE0);
    Serial.write (buffget[2]);
    Serial.write (0xFD);  
    Serial.flush();
    rx=QRG; 
  } else {
    FA();
  }
}

void freq_to_send()  
{
  int_fast32_t lrx = rx / 10;
  // Формируем частоту для отправки в комп
  sendDMHz = lrx/100000;
  sendDMHz = sendDMHz + (((sendDMHz/10) * 6));
  sendMHz  = (lrx % 100000)/1000;
  sendMHz  = sendMHz + (((sendMHz/10) * 6));
  sendkHz  = (lrx % 1000)/10;
  sendkHz  = sendkHz + (((sendkHz/10) * 6));
  sendHz   = (lrx % 10)*10;
  sendHz   = sendHz + (((sendHz/10) * 6));
  Serial.write (0xFE);
  Serial.write (0xFE);
  Serial.write (0xE0);
  Serial.write (0x50);
  Serial.write (0x03);
  Serial.write (sendHz);
  Serial.write (sendkHz);
  Serial.write (sendMHz);
  Serial.write (sendDMHz);
  Serial.write (0x0);
  Serial.write (0xFD);
  Serial.flush();
}

void mode_to_send(){
  Serial.write (0xFE);
  Serial.write (0xFE);
  Serial.write (0xE0);
  Serial.write (0x50);
  Serial.write (0x04);
  // 0 - LSB, 1 - USB, 2 - CW ?
  // Декодируем режим просто по частоте
  if (IFUpDn < rx) {
    // пусть будет USB
    Serial.write (0x01);
    } else {
    // пусть будет LSB  
    Serial.write (0x00);
    }
  Serial.write (0x02);
  Serial.write (0xFD);
  Serial.flush();
}

void FA(){
Serial.write (0xFE);
Serial.write (0xFE);
Serial.write (0xE0);
Serial.write (0x50);
Serial.write (0xFA);
Serial.write (0xFD);
Serial.flush();
}
#endif
// ********************** поддержка CAT (IC 756) ********************** >

int keypooler() {
   int xbtnstate = buttonstate;
   int keypressed = 0;
   buttonstate  = analogRead(KEYPAD); // Считываем значение АЦП кейпада
   if (buttonstate > BUTTON1_2) {
      //все кнопки отпущены, но были нажаты
      if ((xbuttonstate[1] + xbuttonstate[2] + xbuttonstate[3] + xbuttonstate[4] + xbuttonstate[5] + xbuttonstate[6]) != 0) {
	 //на предыдущем шаге была нажатая кнопка, делаем паузу на дребезг и проверяем еще раз
	 delay(10);
	 buttonstate  = analogRead(KEYPAD); // Считываем значение АЦП кейпада
	 if (buttonstate > BUTTON1_2) {
	    //кнопки действительно отпущены
	    for (int i=1;i<7;i++) xbuttonstate[i] = 0;
	 }
      }
   } else {
      //кнопки были отпущены, но теперь что то нажали
      if ((xbuttonstate[1] + xbuttonstate[2] + xbuttonstate[3] + xbuttonstate[4] + xbuttonstate[5] + xbuttonstate[6]) == 0) {
	 //после паузы считываем еще раз
	 xbtnstate = buttonstate;
	 delay(10);
	 buttonstate  = analogRead(KEYPAD); // Считываем значение АЦП кейпада
	 if ((buttonstate > (xbtnstate - 5 - (buttonstate/10))) && (buttonstate < (xbtnstate + 5 + (buttonstate/10)))) {
	 //определенно что то нажато
	    if ((buttonstate >= BUTTON1_1)&&(buttonstate <= BUTTON1_2)) { keypressed = 1; } else
	       if ((buttonstate >= BUTTON2_1)&&(buttonstate <= BUTTON2_2)) { keypressed = 2; } else
		  if ((buttonstate >= BUTTON3_1)&&(buttonstate <= BUTTON3_2)) { keypressed = 3; } else
		     if ((buttonstate >= BUTTON4_1)&&(buttonstate <= BUTTON4_2)) { keypressed = 4; } else
			if ((buttonstate >= BUTTON5_1)&&(buttonstate <= BUTTON5_2)) { keypressed = 5; } else
			   if ((buttonstate >= BUTTON6_1)&&(buttonstate <= BUTTON6_2)) { keypressed = 6; };
	 }
	 xbuttonstate[keypressed] = 1;
      }
   }
   return(keypressed);
}

void setAttPre() {
   att_preamp += 1;
   if (att_preamp > 2) att_preamp = 0;
   digitalWrite(ATT, att_preamp & 0B01);
   digitalWrite(PRE, att_preamp & 0B10);
   showOptions();
}

//Вывод частоты в верхнюю строку LCD
void showFrequency(int_fast32_t lrx)  { 
   char buffer[15];
   utoa_fast_div(lrx, buffer, sizeof(buffer));
   lcd.setCursor(2,0);  
   lcd.print(buffer);
   // добавить
   lcd.setCursor(0,1);
   if (com_mode == 0) {
//    if (IFUpDn < rx) {
      // частота выше границы,гетеродин ниже частоты
   band.bname[3] = 0;   
   lcd.print(band.bname);
      //} else {
      //lcd.print("LSB");
      //}
   }
   if (com_mode == 1) { lcd.print("IF "); }
   if (com_mode == 2) { lcd.print("COR"); }
};

//Выводим вкл/выкл ATT / Preamp
void showOptions() { 
   lcd.setCursor(0,0);
   if (tx_mode == 0) {
      if (att_preamp & 0B01) lcd.print("ATT");
	 else 
	    if (att_preamp & 0B10) lcd.print("PRE");
	       else lcd.print("   ");
   } else {
   lcd.print("TX ");
   }   
}

//Выводим значение S/P-метра на LCD
void showSmeter() { 
 if (xsmtr != smtr) {
   lcd.setCursor(3,1);
   lcd.print(smtr);
   xsmtr = smtr;
 }
}

//Выводим режим
void showMode(int_fast8_t mode) { 
 //if (xmode != mode) {
   //lcd.setCursor(0,1);
   //lcd.print(mode_m[mode].modename);
   //xmode = mode;
 //}
}

void decodeband(int_fast32_t rx) {
//Декодируем диапазон и заполняем band
  band.nd = 0;
  band.num = 0;
  //lcd.setCursor(1,1);
  //lcd.print(" IN             ");
  //lcd.setCursor(5,1);
  //lcd.print(rx);  
  //delay(2000);
  if      ((rx >= BAND_01_LOW)&&(rx <= BAND_01_HIGH)&&(BAND_01_EN)) { band.num = BAND_01_NUM; band.dssb = BAND_01_DSSB; band.inv = BAND_01_INV; band.fhigh = BAND_01_HIGH; band.flow = BAND_01_LOW; strcpy(band.bname, BAND_01_NAME); }
  else if ((rx >= BAND_02_LOW)&&(rx <= BAND_02_HIGH)&&(BAND_02_EN)) { band.num = BAND_02_NUM; band.dssb = BAND_02_DSSB; band.inv = BAND_02_INV; band.fhigh = BAND_02_HIGH; band.flow = BAND_02_LOW; strcpy(band.bname, BAND_02_NAME); }
  else if ((rx >= BAND_03_LOW)&&(rx <= BAND_03_HIGH)&&(BAND_03_EN)) { band.num = BAND_03_NUM; band.dssb = BAND_03_DSSB; band.inv = BAND_03_INV; band.fhigh = BAND_03_HIGH; band.flow = BAND_03_LOW; strcpy(band.bname, BAND_03_NAME); }
  else if ((rx >= BAND_04_LOW)&&(rx <= BAND_04_HIGH)&&(BAND_04_EN)) { band.num = BAND_04_NUM; band.dssb = BAND_04_DSSB; band.inv = BAND_04_INV; band.fhigh = BAND_04_HIGH; band.flow = BAND_04_LOW; strcpy(band.bname, BAND_04_NAME); }
  else if ((rx >= BAND_05_LOW)&&(rx <= BAND_05_HIGH)&&(BAND_05_EN)) { band.num = BAND_05_NUM; band.dssb = BAND_05_DSSB; band.inv = BAND_05_INV; band.fhigh = BAND_05_HIGH; band.flow = BAND_05_LOW; strcpy(band.bname, BAND_05_NAME); }
  else if ((rx >= BAND_06_LOW)&&(rx <= BAND_06_HIGH)&&(BAND_06_EN)) { band.num = BAND_06_NUM; band.dssb = BAND_06_DSSB; band.inv = BAND_06_INV; band.fhigh = BAND_06_HIGH; band.flow = BAND_06_LOW; strcpy(band.bname, BAND_06_NAME); }
  else if ((rx >= BAND_07_LOW)&&(rx <= BAND_07_HIGH)&&(BAND_07_EN)) { band.num = BAND_07_NUM; band.dssb = BAND_07_DSSB; band.inv = BAND_07_INV; band.fhigh = BAND_07_HIGH; band.flow = BAND_07_LOW; strcpy(band.bname, BAND_07_NAME); }
  else if ((rx >= BAND_08_LOW)&&(rx <= BAND_08_HIGH)&&(BAND_08_EN)) { band.num = BAND_08_NUM; band.dssb = BAND_08_DSSB; band.inv = BAND_08_INV; band.fhigh = BAND_08_HIGH; band.flow = BAND_08_LOW; strcpy(band.bname, BAND_08_NAME); }
  else if ((rx >= BAND_09_LOW)&&(rx <= BAND_09_HIGH)&&(BAND_09_EN)) { band.num = BAND_09_NUM; band.dssb = BAND_09_DSSB; band.inv = BAND_09_INV; band.fhigh = BAND_09_HIGH; band.flow = BAND_09_LOW; strcpy(band.bname, BAND_09_NAME); }
  else { band.nd = 1; };
  if (band.num != 0) band.ld = band.num;
    
  if      ((rx >= BAND_BPF_01_LOW)&&(rx <= BAND_BPF_01_HIGH)) { band.bpf  = BAND_BPF_01_CODE; }
  else if ((rx >= BAND_BPF_02_LOW)&&(rx <= BAND_BPF_02_HIGH)) { band.bpf  = BAND_BPF_02_CODE; }  
  else if ((rx >= BAND_BPF_03_LOW)&&(rx <= BAND_BPF_03_HIGH)) { band.bpf  = BAND_BPF_03_CODE; }  
  else if ((rx >= BAND_BPF_04_LOW)&&(rx <= BAND_BPF_04_HIGH)) { band.bpf  = BAND_BPF_04_CODE; }  
  else if ((rx >= BAND_BPF_05_LOW)&&(rx <= BAND_BPF_05_HIGH)) { band.bpf  = BAND_BPF_05_CODE; }  
  else if ((rx >= BAND_BPF_06_LOW)&&(rx <= BAND_BPF_06_HIGH)) { band.bpf  = BAND_BPF_06_CODE; }  
  else if ((rx >= BAND_BPF_07_LOW)&&(rx <= BAND_BPF_07_HIGH)) { band.bpf  = BAND_BPF_07_CODE; }  
  else if ((rx >= BAND_BPF_08_LOW)&&(rx <= BAND_BPF_08_HIGH)) { band.bpf  = BAND_BPF_08_CODE; }  
  else if ((rx >= BAND_BPF_09_LOW)&&(rx <= BAND_BPF_09_HIGH)) { band.bpf  = BAND_BPF_09_CODE; }  
  else { band.bpf  = 0; }
}

void setIncrement() { 
//Здесь закомментированы шаги переключения энкодера, необходимое раскомментировать
//if(increment == 10){increment = 50; hertz = "50 Hz"; hertzPosition=5;}
//else if (increment == 50){increment = 100; hertz = "100 Hz"; hertzPosition=4;}
//else if (increment == 100){increment = 500; hertz="500 Hz"; hertzPosition=4;}
//else if (increment == 500){increment = 1000; hertz="1 KHz"; hertzPosition=6;}
//else if (increment == 1000){increment = 2500; hertz="2.5 KHz"; hertzPosition=4;}
//else if (increment == 2500){increment = 5000; hertz="5 KHz"; hertzPosition=6;}
//else if (increment == 5000){increment = 10000; hertz="10 KHz"; hertzPosition=5;}
//else if (increment == 10000){increment = 100000; hertz="100 KHz"; hertzPosition=4;}
//else if (increment == 100000){increment = 1000000; hertz="1 MHz"; hertzPosition=6;}
//else{increment = 10; hertz = "10 Hz"; hertzPosition=5;};

//Другой вариант шага переключения частоты
//if(increment == 10){increment = 100; hertz = "100 Hz"; hertzPosition=4;}
//else if (increment == 100){increment = 1000; hertz = "1 KHz"; hertzPosition=6;}
//else if (increment == 1000){increment = 10000; hertz="10 KHz"; hertzPosition=5;}
//else if (increment == 10000){increment = 100000; hertz="100 KHz"; hertzPosition=4;}
//else {increment = 10; hertz = "10 Hz"; hertzPosition=5;};

//Другой вариант шага переключения частоты
//if(increment == 100){increment = 1000;         hertz = "  1 kHz"; hertzPosition=5;}
 if (increment == 100){increment = 5000;   hertz=" 5 kHz"; hertzPosition=6;}
else if (increment == 5000){increment = 25000; hertz="25 KHz"; hertzPosition=5;}
//else if (increment == 25000){increment = 100000; hertz="100 kHz"; hertzPosition=5;}
else if (increment == 25000){increment = 1000000; hertz="1 MHz"; hertzPosition=6;}
else {increment = 100;                         hertz = "100  Hz"; hertzPosition=5;};

lcd.setCursor(3,1);
lcd.print("             ");
lcd.setCursor(hertzPosition,1);
lcd.print(hertz);
xsmtr = "";
rate_timepassed = millis() + TIME_DISPLAY_RATE; // До этого времени S-метр не будет отображаться
}
//---------------------------------------------Окончание участка кода для управления шагом щелчка энкодером.

// Процедура прерывания по событию изменение состояния энкодера
ISR(PCINT2_vect) {
unsigned char result = r.process();
if (result) {
  if (com_mode == 0) {
    if (result == DIR_CW)  {  rx=rx+increment;  }
      else {  rx=rx-increment;  };
    if (rx >=MAXFREQ)  {rx=rx2;}; // Верхний предел частоты
    if (rx <=MINFREQ)   {rx=rx2;}; // Нижний предел частоты
  }
  if (com_mode == 1) {
    if (result == DIR_CW)  {  iffreq=iffreq+increment/10;  }
      else {  iffreq=iffreq-increment/10;  };
    if (iffreq >=MAXIFFREQ)  {iffreq=xiffreq;}; // Верхний предел ПЧ
    if (iffreq <=MINIFFREQ)  {iffreq=xiffreq;}; // Нижний предел ПЧ
  }
  if (com_mode == 2) {
    if (result == DIR_CW)  {  si5351_corr=si5351_corr+increment;  }
      else {  si5351_corr=si5351_corr-increment;  };
    if (si5351_corr >=MAXIFFREQ)  {si5351_corr=xsi5351_corr;}; // Верхний предел коррекции
    if (si5351_corr <=0)          {si5351_corr=xsi5351_corr;}; // Нижний предел коррекции
  }
};
}

void sendReg(int_fast16_t bpf) {
//  Отправляем код диапазона и/или режим работы на дешифратор или сдвиговые регистры

//  HC595
//  digitalWrite(BPF_LATCH, LOW);
//  delay(1);
//  tfr_byte(dpf & 0xFF);
//  tfr_byte((dpf >> 8) & 0xFF); 
//  digitalWrite(BPF_LATCH, HIGH); 

//  Дешифратор
   digitalWrite(BPF_D0, bpf & 0B0001);
   digitalWrite(BPF_D1, bpf & 0B0010);
   digitalWrite(BPF_D2, bpf & 0B0100);
   digitalWrite(BPF_D3, bpf & 0B1000);
}

// Расчитываем и отправляем новую частоту в синтезатор
void sendFrequency(double frequency) {
// Si5351
double l_frequency_to_synth = frequency;

// Логика расчета частоты для синтезатора
#ifdef IFFreq
// Если используем ПЧ
  if (band.nd == 1) { 
   // Частота вне заданных диапазонов
   if (IFUpDn < rx) {
   // Частота выше границы, гетеродин ниже частоты
      l_frequency_to_synth = rx - iffreq;
   } else {
   // Частота ниже границы, гетеродин выше частоты
      l_frequency_to_synth = rx + iffreq;
   }
  } else { 
   // Частота в одном из диапазонов, делаем как в настройке диапазона
   l_frequency_to_synth = (rx + (iffreq * band.inv));
  }
#endif  

// Отправляем частоту в si5351
//si5351.set_freq( l_frequency_to_synth * SI5351_FREQ_MULT, SI5351_PLL_FIXED, SI5351_CLK0 );
si5351.set_freq( l_frequency_to_synth * SI5351_FREQ_MULT, SI5351_CLK0 );
//timepassed = millis() + 5000;
//memstatus = 0; // Сигнализируем об изменении частоты и потенциальной необходимости ее записи в постоянную память
}

void setBand(int dir) {
  if (band.num == 0) band.num = band.ld;
  band.num += dir;
  if (band.num < 1) { band.num = BAND_MAX; }
    else if (band.num > BAND_MAX) { band.num = 1; }
  if (dir > 0) {
    if  ((!BAND_01_EN) && (band.num == 1)) { band.num++; }  
    if  ((!BAND_02_EN) && (band.num == 2)) { band.num++; }      
    if  ((!BAND_03_EN) && (band.num == 3)) { band.num++; }  
    if  ((!BAND_04_EN) && (band.num == 4)) { band.num++; }  
    if  ((!BAND_05_EN) && (band.num == 5)) { band.num++; }  
    if  ((!BAND_06_EN) && (band.num == 6)) { band.num++; }  
    if  ((!BAND_07_EN) && (band.num == 7)) { band.num++; }  
    if  ((!BAND_08_EN) && (band.num == 8)) { band.num++; }      
  } else if (dir < 0) {
    if  ((!BAND_09_EN) && (band.num == 9)) { band.num--; }  
    if  ((!BAND_08_EN) && (band.num == 8)) { band.num--; }      
    if  ((!BAND_07_EN) && (band.num == 7)) { band.num--; }  
    if  ((!BAND_06_EN) && (band.num == 6)) { band.num--; }  
    if  ((!BAND_05_EN) && (band.num == 5)) { band.num--; }  
    if  ((!BAND_04_EN) && (band.num == 4)) { band.num--; }  
    if  ((!BAND_03_EN) && (band.num == 3)) { band.num--; }  
    if  ((!BAND_02_EN) && (band.num == 2)) { band.num--; }      
  }
  if (band.num != band.xnum) {
    storeMemBand(band.xnum);
    restoreMemBand(band.num);
  }
}

void setMode() {
   mode++;
   if ((mode < 0) || (mode_m[mode].code == 0xFF)) { mode = 1; }
   timepassed = millis() + 5000;
   memstatus = 0; // Сигнализируем об изменении режима и потенциальной необходимости его записи в постоянную память
}

void setComMode() {
  com_mode++;
  if (com_mode > 2)   { com_mode      = 0; }
  if (com_mode == 0)  { rx2           = 1; }
  if (com_mode == 1)  { xiffreq       = 1; }  
  if (com_mode == 2)  { xsi5351_corr  = 1; }    
}

void restoreMem() {
  mode        = EEPROM.read(9);
  xmode       = 0;
  freq        = String(EEPROM.read(0))+String(EEPROM.read(1))+String(EEPROM.read(2))+String(EEPROM.read(3))+String(EEPROM.read(4))+String(EEPROM.read(5))+String(EEPROM.read(6));
  rx          = freq.toInt();
  rx2         = 1;
  freq        = String(EEPROM.read(110))+String(EEPROM.read(111))+String(EEPROM.read(112))+String(EEPROM.read(113))+String(EEPROM.read(114))+String(EEPROM.read(115))+String(EEPROM.read(116));
  iffreq      = freq.toInt();
  xiffreq     = 1;
  freq        = String(EEPROM.read(120))+String(EEPROM.read(121))+String(EEPROM.read(122))+String(EEPROM.read(123))+String(EEPROM.read(124))+String(EEPROM.read(125))+String(EEPROM.read(126));  
  si5351_corr = freq.toInt();
  xsi5351_corr= 1;
  if (rx >= MAXFREQ)  {  rx  =  MAXFREQ; }; // Верхний предел частоты
  if (rx <= MINFREQ)  {  rx  =  MINFREQ; }; // Нижний предел частоты    
  if ((mode < 0) || (mode_m[mode].code == 0xFF)) { mode = 1; } // Если считали кривой режим
}

void restoreMemBand(int num) {
  freq = String(EEPROM.read(0 + (num * 10)))+String(EEPROM.read(1 + (num * 10)))+String(EEPROM.read(2 + (num * 10)))+String(EEPROM.read(3 + (num * 10)))+String(EEPROM.read(4 + (num * 10)))+String(EEPROM.read(5 + (num * 10)))+String(EEPROM.read(6 + (num * 10)));
  mode = EEPROM.read(9 + (num * 10));
  xmode = 0;
  rx2 = rx;
  rx = freq.toInt();
  if (rx >= MAXFREQ)  {  rx  =  rx2; }; // Верхний предел частоты
  if (rx <= MINFREQ)  {  rx  =  rx2; }; // Нижний предел частоты    
  if ((mode < 0) || (mode_m[mode].code == 0xFF)) { mode = 1; } // Если считали кривой режим
}

void initMem() {
  lcd.setCursor(0,0);
  lcd.print("  INITIALIZING  ");
  lcd.setCursor(0,1);
  lcd.print("     EEPROM     ");
  delay(1000);  
  memstatus = 0;
  mode = 1;
  iffreq = IFFreq;
  si5351_corr = 12345;
  rx = BAND_01_LOW; decodeband(rx); storeMemBand(1);
  if  (BAND_01_EN && (memstatus == 0)) { storeMem(); }
  rx = BAND_02_LOW; decodeband(rx); storeMemBand(2);
  if  (BAND_02_EN && (memstatus == 0)) { storeMem(); }  
  rx = BAND_03_LOW; decodeband(rx); storeMemBand(3);
  if  (BAND_03_EN && (memstatus == 0)) { storeMem(); }  
  rx = BAND_04_LOW; decodeband(rx); storeMemBand(4);
  if  (BAND_04_EN && (memstatus == 0)) { storeMem(); }  
  rx = BAND_05_LOW; decodeband(rx); storeMemBand(5);
  if  (BAND_05_EN && (memstatus == 0)) { storeMem(); }  
  rx = BAND_06_LOW; decodeband(rx); storeMemBand(6);
  if  (BAND_06_EN && (memstatus == 0)) { storeMem(); }  
  rx = BAND_07_LOW; decodeband(rx); storeMemBand(7);
  if  (BAND_07_EN && (memstatus == 0)) { storeMem(); }  
  rx = BAND_08_LOW; decodeband(rx); storeMemBand(8);  
  if  (BAND_08_EN && (memstatus == 0)) { storeMem(); }  
  rx = BAND_09_LOW; decodeband(rx); storeMemBand(9);    
   if  (BAND_09_EN && (memstatus == 0)) { storeMem(); }
 
  lcd.setCursor(0,0);
  lcd.print("                ");
  lcd.setCursor(0,1);
  lcd.print("                ");
}

void splitRx(int_fast32_t rx) {
  millions         = byte(rx/1000000); 
  hundredthousands = byte((rx/100000)%10);
  tenthousands     = byte((rx/10000)%10);
  thousands        = byte((rx/1000)%10);
  hundreds         = byte((rx/100)%10);
  tens             = byte((rx/10)%10);
  ones             = byte((rx/1)%10);
}

void storeMemBand(int num){
//Записываем частоту текущего диапазона в постоянную память (EEPROM) поразрядно
//Но только если попадает в границы диапазона
if ((num > 0)&&(rx >= band.flow)&&(rx <= band.fhigh)) {
  splitRx(rx);
  EEPROM.update(0 + (num * 10),millions);
  EEPROM.update(1 + (num * 10),hundredthousands);
  EEPROM.update(2 + (num * 10),tenthousands);
  EEPROM.update(3 + (num * 10),thousands);
  EEPROM.update(4 + (num * 10),hundreds);
  EEPROM.update(5 + (num * 10),tens);
  EEPROM.update(6 + (num * 10),ones);
  EEPROM.update(9 + (num * 10),mode);  
}
};

void storeMem(){
//Записываем текущую частоту в постоянную память (EEPROM) поразрядно
  //lcd.setCursor(4,1);
  //lcd.print("-=STORING=- ");
  splitRx(rx);
  EEPROM.update(0,millions);
  EEPROM.update(1,hundredthousands);
  EEPROM.update(2,tenthousands);
  EEPROM.update(3,thousands);
  EEPROM.update(4,hundreds);
  EEPROM.update(5,tens);
  EEPROM.update(6,ones);
  EEPROM.update(9,mode);

  splitRx(iffreq);
  EEPROM.update(110,millions);
  EEPROM.update(111,hundredthousands);
  EEPROM.update(112,tenthousands);
  EEPROM.update(113,thousands);
  EEPROM.update(114,hundreds);
  EEPROM.update(115,tens);
  EEPROM.update(116,ones);

  splitRx(si5351_corr);
  EEPROM.update(120,millions);
  EEPROM.update(121,hundredthousands);
  EEPROM.update(122,tenthousands);
  EEPROM.update(123,thousands);
  EEPROM.update(124,hundreds);
  EEPROM.update(125,tens);
  EEPROM.update(126,ones);
  memstatus = 1; // Сигнализируем программе, что последние изменения частоты записаны в постоянную память (EEPROM)
  //delay(100);
  //lcd.setCursor(4,1);
  //lcd.print("            ");
  //xsmtr = "";
};