/******************
*****Heniek*****
Sterownik DDS do trx by: 
SP9MRN - idea i core
SQ9NJE - struktury i indeksowanie VFO - bez tego projekt leżał i płakał.... 
SP9NJ - koncepcja i debugowanie CAT oraz dedykowany logger
Copyleft dla zastosowań amatorskich
For ham radio non commertial use - Copyleft
R2DHG выкинул лишнее и адаптировал под ST7735 :)
******libraries**************************/
#include "Adafruit_GFX.h"
#include "Adafruit_ST7735.h"
#include "rotary.h"
#include "si5351.h"
#include <SPI.h>
#include <EEPROM.h>

//пины
//3,2 - encoder (in)
//4   - ATT (out)
//5   - PTT (in) 
//6   - TUN (1 КГц меандр)
//7   - TX  OUT
//8   - TFT DC
//10  - TFT CS
//11  - TFT & DDS SPI MOSI
//12  - TFT RST
//9   - BPF band3 on
//A0  - P METER ADC
//A1  - S METER ADC    
//A2  - BPF band1 on
//A3  - BPF band2 on
//A6  - Voltmeter ADC

//цвет в формате 565 можно подобрать тут http://www.barth-dev.de/online/rgb565-color-picker/

#define IFFreq         50000        // Расчетная промежуточная частота. Обратите внимание на разрядность ! 498800 = 498.800 КГц
#define IFFreqCLK2LSB  50000        // Опора при LSB
#define IFFreqCLK2USB  50370        // Опора при USB
#define BAND_MAX       2            // от 0 до 3 - 4 диапазона
#define PIN_MEANDR     6
#define PIN_PTT        5
#define PIN_ATT        4
#define PIN_TX         7
#define PIN_PMETER     A0
#define PIN_SMETER     A1
#define PIN_VMETER     A6
#define PIN_KEYPAD     A7

#define TFT_CS         10
#define TFT_RST        12            // you can also connect this to the Arduino reset
                                     // in which case, set this #define pin to 0!
#define TFT_DC         8

#define SI5351_CRYSTAL_FREQ 25001035
#define SERIAL_SPEED        19200
#define REVERSE_TXRX        1        // 1 - CLK1 = VFO, CLK0 = BFO when TX

/*
#define DDS_FQUP       9
#define DDS_CLK        13
#define DDS_DATA       11
#define DDS_OSC_FREQ   125000000     // частота генератора модуля DDS, обычно 125000000 для 9850 и 180000000 для 9851, можно подкрутить под свой экземпляр
#define DDS_END_BYTE   0             // завершающий байт последовательности установки частоты, 0 для модуля AD9850 и 1 для модуля AD9851 (включает умножение частоты генератора на 6)
#define pulseHigh(pin) { digitalWrite(pin, HIGH); digitalWrite(pin, LOW); }
*/

#define BPF_BAND_1     A2
#define BPF_BAND_2     A3
#define BPF_BAND_3     9
#define BPF_BAND_4     A5

#define MEMSTORETOEEPROM   3000        //14.10.16 таймер запись частоты в EEPROM
#define DDSCORRECTION      20000       //можно использовать для коррекции частоты DDS в небольших пределах

// Этот define должен быть раскомментарен для настройки уровней кнопок через терминал (смотрите через монитор com-порта)
 #define Keypad_ADC_Check

// Значения уровня с АЦП для кнопок на делителе _1 нижнее _2 верхнее
// Должны идти по убыванию - это важно !
// Функции кнопок можно поменять в loop()
// 1я кнопка
#define  BUTTON1_1  600
#define  BUTTON1_2  700
// 2я кнопка
#define  BUTTON2_1  400
#define  BUTTON2_2  500
// 3я кнопка
#define  BUTTON3_1  100
#define  BUTTON3_2  200
// 4я кнопка
#define  BUTTON4_1  0
#define  BUTTON4_2  50
// 5я кнопка
//#define  BUTTON5_1  90
//#define  BUTTON5_2  110
// 6я кнопка
//#define  BUTTON6_1  0
//#define  BUTTON6_2  10

//настройки уровней S/P метра
#define  SMETER_1      1
#define  SMETER_2      4
#define  SMETER_3      8
#define  SMETER_4      12
#define  SMETER_5      16
#define  SMETER_6      20
#define  SMETER_7      24
#define  SMETER_8      40
#define  SMETER_9      60
#define  SMETER_9_10   100
#define  SMETER_9_20   200
#define  SMETER_9_30   300
#define  SMETER_9_40   400

#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  PMETER_13     580

//настройки графического интерфейса

#define SEP_DIGIT       46             // код символа-разделителя разрядов (точка .) 

#define BG_COLOR        ST7735_BLACK
#define COLOR           ST7735_WHITE
#define OUTLINE_COLOR   0xC618         //обрамление графических элементов, серый 565

#define MAIN_COLOR      ST7735_CYAN
#define MAIN_BG_COLOR   ST7735_BLACK
#define MAIN_X_BASE     0
#define MAIN_Y_BASE     0
#define MAIN_TEXTSIZE1  4            //основные разряды 
#define MAIN_TEXTSIZE2  2            //два последних разряда
#define MAIN_TEXTPIXX   6            //базовый размер шрифта по X в пикселях

#define TX_COLOR        ST7735_BLACK
#define TX_BG_COLOR     ST7735_RED
#define TX_X_BASE       5
#define TX_Y_BASE       46
#define TX_TEXTSIZE     2 
#define TX_BGSIZE_W     30            //ширина плашки цвета фона 
#define TX_BGSIZE_H     20            //высота плашки цвета фона 
#define TX_TEXTPIXX     6             //базовый размер шрифта по X в пикселях

#define RX_COLOR        ST7735_BLACK
#define RX_BG_COLOR     ST7735_GREEN
#define RX_X_BASE       5
#define RX_Y_BASE       46
#define RX_TEXTSIZE     2 
#define RX_BGSIZE_W     30            //ширина плашки цвета фона 
#define RX_BGSIZE_H     20            //высота плашки цвета фона 
#define RX_TEXTPIXX     6             //базовый размер шрифта по X в пикселях

#define AT_COLOR        ST7735_BLACK
#define AT_BG_COLOR     ST7735_GREEN
#define AT_X_BASE       5
#define AT_Y_BASE       71
#define AT_TEXTSIZE     2 
#define AT_BGSIZE_W     30            //ширина плашки цвета фона 
#define AT_BGSIZE_H     20            //высота плашки цвета фона 
#define AT_TEXTPIXX     6             //базовый размер шрифта по X в пикселях

#define USB_COLOR       ST7735_BLACK
#define USB_BG_COLOR    ST7735_GREEN
#define USB_X_BASE      45
#define USB_Y_BASE      46
#define USB_TEXTSIZE    2 
#define USB_BGSIZE_W    41            //ширина плашки цвета фона 
#define USB_BGSIZE_H    20            //высота плашки цвета фона 
#define USB_TEXTPIXX    6             //базовый размер шрифта по X в пикселях

#define LSB_COLOR       ST7735_BLACK
#define LSB_BG_COLOR    ST7735_GREEN
#define LSB_X_BASE      45
#define LSB_Y_BASE      46
#define LSB_TEXTSIZE    2 
#define LSB_BGSIZE_W    41            //ширина плашки цвета фона 
#define LSB_BGSIZE_H    20            //высота плашки цвета фона 
#define LSB_TEXTPIXX    6             //базовый размер шрифта по X в пикселях

#define TUN_COLOR       ST7735_BLACK
#define TUN_BG_COLOR    ST7735_YELLOW
#define TUN_X_BASE      45
#define TUN_Y_BASE      46
#define TUN_TEXTSIZE    2 
#define TUN_BGSIZE_W    41            //ширина плашки цвета фона 
#define TUN_BGSIZE_H    20            //высота плашки цвета фона 
#define TUN_TEXTPIXX    6             //базовый размер шрифта по X в пикселях

// вольтметр, значение ADC сразу делится на 4 и получаем Vref = 255 с внешним делителем 1/4, т.е. около 176 при 13.8 вольт
#define VIN_COLOR       ST7735_BLACK
#define VIN_BG_COLOR    ST7735_GREEN
#define VIN_BG_COLORA   ST7735_RED    //если напряжение отличается от нормы на 10%
#define VIN_DELTA_MIN   108           //максимальное напряжение * 10 - норма
#define VIN_DELTA_MAX   144           //минимальное напряжение  * 10 - норма
#define VIN_BG_MEASPER  500           //период измерения, мсек
#define VIN_X_BASE      95
#define VIN_Y_BASE      46
#define VIN_TEXTSIZE    2 
#define VIN_BGSIZE_W    55            //ширина плашки цвета фона 
#define VIN_BGSIZE_H    20            //высота плашки цвета фона 
#define VIN_TEXTPIXX    6             //базовый размер шрифта по X в пикселях

#define SUB_BG_COLOR    ST7735_BLACK
#define SUB_COLOR       ST7735_GREEN
#define SUB_X_BASE      10
#define SUB_Y_BASE      44

#define METER_BG_COLOR  ST7735_BLACK
#define METER_COLOR     ST7735_WHITE
#define METER_COLOR_P   ST7735_RED
#define METER_COLOR_PW  ST7735_YELLOW
#define METER_LABEL_C   ST7735_YELLOW //подпись под S метром 
#define METER_LABEL_S   1             //размер шрифта подписи под S метром 
#define METER_X_BASE    0
#define METER_Y_BASE    110

//********Parametry TRX *******Hardware definition********************
// частоты поделены на 10
const int  homodyna=0;         //dla homodyny=1, dla trx z pcz=0
const long IF=IFFreq;          // промежуточная частота
const int  IFoffset=0;         // отступ в ГЦ для режимов, кроме CW (1.5 КГц)
const int  DirectCW=0;         // прямой вывод CW с синтезатора
const int  CWoffset=700;         // отступ в ГЦ для CW (700 Гц)
long  DDSfreq;

//LSB: DDS = RF + IF + IFoffset   ---> RF на дисплей, DDS на синтезатор
//USB: DDS = RF + IF - IFoffset
//CW : DDS = RF + IF - CWoffset   ---> для CW 
//*********************************************************************

Rotary r = Rotary(3, 2);
Si5351 si5351; // Синтезатор
Adafruit_ST7735 display = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);

//***************Deklaracje CAT***************
int  buffget[11] ;                             // the receive buffer
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;
// 14.10.16 <
unsigned long timepassed = millis();
boolean       memstatus = 0;
//Десятичные разряды представления частоты (для EEPROM)
byte ones,tens,hundreds,thousands,tenthousands,hundredthousands,millions;
String freq;
// 14.10.16 >
//***********koniec deklaracji CAT***************/

typedef struct {
  long lower_limit;
  long upper_limit;
  long mid;
} band_t;

typedef struct {
  byte band;
  long freq[9];
  byte mode[9];
  boolean att[9];
} vfo_t;

band_t bands[9] = {
  {100000, 250000, 185000},
  {250000, 600000, 370000},
  {600000, 800000, 710000},
  {1010000, 1015000, 1010000},
  {1400000, 1435000, 1425000},
  {1806800, 1816800, 1816000},
  {2100000, 2145000, 2125000},
  {2489000, 2499000, 2494000},
  {2800000, 2970000, 2850000}};

byte modes[9]={0, 0, 0, 1, 1, 1, 1, 1, 1};
byte att[9]  ={0, 0, 0, 0, 0, 0, 0, 0, 0};

int  smeterlevels[14]={SMETER_1, SMETER_2, SMETER_3, SMETER_4, SMETER_5, SMETER_6, SMETER_6, SMETER_7, SMETER_8, SMETER_9, SMETER_9_10, SMETER_9_20, SMETER_9_30, SMETER_9_40};
int  pmeterlevels[14]={PMETER_1, PMETER_2, PMETER_3, PMETER_4, PMETER_5, PMETER_6, PMETER_7, PMETER_8, PMETER_9, PMETER_10, PMETER_11, PMETER_12, PMETER_13};
 
vfo_t vfo[2];
byte active_vfo = 1;

boolean  rownaj=0;
boolean  split=0;
boolean  ptt, ex_ptt=0;
boolean  swap=0;
int      mod=0;
boolean  cm=0;           // change mode
int      mode1=0;        // текущий режим
int      ex_mode1=10;    // предыдущий режим
long     stepA=100;
long     ex_stepA=0;
int      cb=0;           // change band
unsigned int vin=0;      // текущее напряжение
unsigned int ex_vin=0;   // предыдущее напряжение
unsigned long vin_time=0;// таймер периода измерения напряжения

//boolean buttonState           = 0;     // current state of the button
//boolean lastButtonState_step  = 0;     // previous state of the button
//boolean lastButtonState_band  = 0;     // previous state of the button
boolean PTTState                = 0;     
boolean lastPTTState            = 1;      
boolean firstRunSMeter          = 1;     
boolean TuneState               = 0;
boolean CATTXState              = 0;
boolean xCATTXState             = 1;
boolean AttState                = 0;
boolean xAttState               = 1;

int     smeterLevel           = 0;
int     smeterlastLevel       = 9999;
int     smeterlastLevel_cub   = 9999;

byte    setATT=0; //wartosc ATT 0=nic 1=6db 2=12db 3=wzmacniacz
byte    cATT=0; //czy zmieniac att

byte    PCFband=1;
byte    PCFmode=16;

byte    g_keypressed  = 0;
byte    g_xkeypressed = 0;

//текстовые строки с частотой до изменения
char ex_buffer_main[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
char ex_buffer_sub[10]  = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};

void printMain(){
  char buffer[10];    //буфер строки преобразования частоты в текст
  char c, s;
  uint16_t l_color;
  int i, j, x, y;
  long stepAcheck, l_stepA;
  noInterrupts();
  //переводим значение частоты в строку
  //это позволит использовать разделить групп разрядов,
  //зафиксировать длину строки и сравнивать старое и новое
  //значение поразрадно простым и быстрым способом
  utoa_fast_div(vfo[active_vfo].freq[vfo[active_vfo].band], buffer, sizeof(buffer), 1);
  //в первом цикле печатаем изменившиеся старые символы строки цветом фона,
  //остальные не трогаем, во втором печатаем изменившиеся новые
  for(j=0;j<2;j++) {
  stepAcheck = 1000000;  
  display.setCursor(MAIN_X_BASE+0,MAIN_Y_BASE+0);
  if (j==0) {
    l_color = MAIN_BG_COLOR;
    l_stepA = ex_stepA;
  } else {
    l_color = MAIN_COLOR;    
    l_stepA = stepA;    
  };  
  display.setTextColor(l_color);  
  for(i=0;i<9;i++) {
    if (i<6) display.setTextSize(MAIN_TEXTSIZE1); else display.setTextSize(MAIN_TEXTSIZE2);
      if (j==0) {
        c = ex_buffer_main[i]; 
        s = buffer[i];
      } else {
        c = buffer[i];
        s = ex_buffer_main[i];         
      };
      if (i<6) {
        //мегагерцы, килогерцы
        if (c==SEP_DIGIT) {
          //коррекция положения курсора если попалась точка (делаем точку узкой)          
          display.setCursor(display.getCursorX()-8,display.getCursorY());
          //тут можно нарисовать свою точку по координатам или напечатать стандартную
          //текущим цветом l_color
          if (c!=s) display.write(c); else display.write(' ');
          display.setCursor(display.getCursorX()-4,display.getCursorY());          
        } else {
          //если это разряд, изменяемый валкодером - рисуем подчеркивание
          if ((stepAcheck == l_stepA)&&(stepA != ex_stepA)) {
            //сохраняем координаты
            x = display.getCursorX();
            y = display.getCursorY();
            //сдвигаем курсор ниже на 8 пикселей
            display.setCursor(x, y+8);   
            //печатаем подчеркивание, 
            //можно по текущим координатам нарисовать свое что нибудь
            //текущим цветом l_color
            display.setTextSize(MAIN_TEXTSIZE1);
            display.write(95);
            //восстанавливаем координаты
            display.setCursor(x, y);
          };
          //обычные символы
          display.setTextSize(MAIN_TEXTSIZE1);
          if (c!=s) display.write(c); else display.write(' ');
          stepAcheck = stepAcheck / 10;
        };
      //герцы  
      } else {
        // после мГц и кГц печатаем все, кроме точки
        if (c!=SEP_DIGIT) {
          //если это разряд, изменяемый валкодером - рисуем подчеркивание
          if ((stepAcheck == l_stepA)&&(stepA != ex_stepA)) {
            //сохраняем координаты
            x = display.getCursorX();
            y = display.getCursorY();
            //сдвигаем курсор ниже на 5 пикселей
            display.setCursor(x, y+5);   
            //печатаем подчеркивание, 
            //можно по текущим координатам нарисовать свое что нибудь
            //текущим цветом l_color
            display.setTextSize(MAIN_TEXTSIZE2);
            display.write(95);
            //восстанавливаем координаты
            display.setCursor(x, y);
          };
          display.setTextSize(MAIN_TEXTSIZE2);
          if (c!=s) display.write(c); else display.write(' ');
          stepAcheck = stepAcheck / 10;          
        };
      };
  };
  };
  //старое значение частоты в строке = текущему
  for(i=0;i<sizeof(buffer);i++) { ex_buffer_main[i] = buffer[i]; }
  //старое значение шага = текущему
  ex_stepA = stepA;
  interrupts();
}

void printSub() {
//  пока выкинул вообще
//  char buffer[10];    //буфер строки преобразования частоты в текст
//  int i;
}

void printModes(){
uint16_t l_rx_bg_color, l_rx_color;
uint16_t l_tx_bg_color, l_tx_color;
//если tx и rx в одном месте - важна последовательность отрисовки
if (ptt != ex_ptt) {
  if (ptt) {
    display.fillRoundRect(TX_X_BASE, TX_Y_BASE, TX_BGSIZE_W, TX_BGSIZE_H, min(TX_BGSIZE_W, TX_BGSIZE_H)/4, TX_BG_COLOR);
    display.drawRoundRect(TX_X_BASE, TX_Y_BASE, TX_BGSIZE_W, TX_BGSIZE_H, min(TX_BGSIZE_W, TX_BGSIZE_H)/4, OUTLINE_COLOR);
    display.setCursor(TX_X_BASE+3, TX_Y_BASE+3);
    display.setTextColor(TX_COLOR);
    display.setTextSize(TX_TEXTSIZE);    
    display.print("TX");
  } else {
    display.fillRoundRect(RX_X_BASE, RX_Y_BASE, RX_BGSIZE_W, RX_BGSIZE_H, min(RX_BGSIZE_W, RX_BGSIZE_H)/4, RX_BG_COLOR);
    display.drawRoundRect(RX_X_BASE, RX_Y_BASE, RX_BGSIZE_W, RX_BGSIZE_H, min(RX_BGSIZE_W, RX_BGSIZE_H)/4, OUTLINE_COLOR);
    display.setCursor(RX_X_BASE+3, RX_Y_BASE+3);
    display.setTextColor(RX_COLOR);
    display.setTextSize(RX_TEXTSIZE);
    display.print("RX");
    
    /*
    l_tx_bg_color  = TX_BG_COLOR;
    l_tx_color     = TX_COLOR;    
    l_rx_bg_color  = BG_COLOR;
    l_rx_color     = BG_COLOR;
    if ((TX_X_BASE != RX_X_BASE)||(TX_Y_BASE != RX_Y_BASE)) {    
      display.fillRoundRect(RX_X_BASE, RX_Y_BASE, RX_BGSIZE_W, RX_BGSIZE_H, min(RX_BGSIZE_W, RX_BGSIZE_H)/4, l_rx_bg_color);
      display.drawRoundRect(RX_X_BASE, RX_Y_BASE, RX_BGSIZE_W, RX_BGSIZE_H, min(RX_BGSIZE_W, RX_BGSIZE_H)/4, OUTLINE_COLOR);
      display.setCursor(RX_X_BASE+3, RX_Y_BASE+3);
      display.setTextColor(l_rx_color);
      display.setTextSize(RX_TEXTSIZE);
      display.print("RX");
    }  
    display.fillRoundRect(TX_X_BASE, TX_Y_BASE, TX_BGSIZE_W, TX_BGSIZE_H, min(TX_BGSIZE_W, TX_BGSIZE_H)/4, l_tx_bg_color);
    display.drawRoundRect(TX_X_BASE, TX_Y_BASE, TX_BGSIZE_W, TX_BGSIZE_H, min(TX_BGSIZE_W, TX_BGSIZE_H)/4, OUTLINE_COLOR);
    display.setCursor(TX_X_BASE+3, TX_Y_BASE+3);
    display.setTextColor(l_tx_color);
    display.setTextSize(TX_TEXTSIZE);    
    display.print("TX");
  } else {
    l_rx_bg_color  = RX_BG_COLOR;
    l_rx_color     = RX_COLOR;    
    l_tx_bg_color  = BG_COLOR;
    l_tx_color     = BG_COLOR;    
    if ((TX_X_BASE != RX_X_BASE)||(TX_Y_BASE != RX_Y_BASE)) {
      display.fillRoundRect(TX_X_BASE, TX_Y_BASE, TX_BGSIZE_W, TX_BGSIZE_H, min(TX_BGSIZE_W, TX_BGSIZE_H)/4, l_tx_bg_color);
      display.drawRoundRect(TX_X_BASE, TX_Y_BASE, TX_BGSIZE_W, TX_BGSIZE_H, min(TX_BGSIZE_W, TX_BGSIZE_H)/4, OUTLINE_COLOR);
      display.setCursor(TX_X_BASE+3, TX_Y_BASE+3);
      display.setTextColor(l_tx_color);
      display.setTextSize(TX_TEXTSIZE);      
      display.print("TX");
    }
    display.fillRoundRect(RX_X_BASE, RX_Y_BASE, RX_BGSIZE_W, RX_BGSIZE_H, min(RX_BGSIZE_W, RX_BGSIZE_H)/4, l_rx_bg_color);
    display.drawRoundRect(RX_X_BASE, RX_Y_BASE, RX_BGSIZE_W, RX_BGSIZE_H, min(RX_BGSIZE_W, RX_BGSIZE_H)/4, OUTLINE_COLOR);
    display.setCursor(RX_X_BASE+3, RX_Y_BASE+3);
    display.setTextColor(l_rx_color);
    display.setTextSize(RX_TEXTSIZE);
    display.print("RX");
  */  
  };
  printSmeter();
  ex_ptt = ptt;
  };
 
//Tune 
if (TuneState) {
    display.fillRoundRect(TUN_X_BASE, TUN_Y_BASE, TUN_BGSIZE_W, TUN_BGSIZE_H, min(TUN_BGSIZE_W, TUN_BGSIZE_H)/4, TUN_BG_COLOR);
    display.drawRoundRect(TUN_X_BASE, TUN_Y_BASE, TUN_BGSIZE_W, TUN_BGSIZE_H, min(TUN_BGSIZE_W, TUN_BGSIZE_H)/4, OUTLINE_COLOR);
    display.setCursor(TUN_X_BASE+3, TUN_Y_BASE+3);
    display.setTextColor(TUN_COLOR);
    display.setTextSize(TUN_TEXTSIZE);    
    display.print("TUN");
}

//Att
if (vfo[active_vfo].att[vfo[active_vfo].band] != xAttState) {
  if (vfo[active_vfo].att[vfo[active_vfo].band]) {
    display.fillRoundRect(AT_X_BASE, AT_Y_BASE, AT_BGSIZE_W, AT_BGSIZE_H, min(AT_BGSIZE_W, AT_BGSIZE_H)/4, AT_BG_COLOR);
    display.drawRoundRect(AT_X_BASE, AT_Y_BASE, AT_BGSIZE_W, AT_BGSIZE_H, min(AT_BGSIZE_W, AT_BGSIZE_H)/4, OUTLINE_COLOR);
    display.setCursor(AT_X_BASE+3, AT_Y_BASE+3);
    display.setTextColor(AT_COLOR);
    display.setTextSize(AT_TEXTSIZE);    
    display.print("CW");
  } else {
    display.fillRoundRect(AT_X_BASE, AT_Y_BASE, AT_BGSIZE_W, AT_BGSIZE_H, min(AT_BGSIZE_W, AT_BGSIZE_H)/4, BG_COLOR);
    display.drawRoundRect(AT_X_BASE, AT_Y_BASE, AT_BGSIZE_W, AT_BGSIZE_H, min(AT_BGSIZE_W, AT_BGSIZE_H)/4, BG_COLOR);
  }    
  xAttState = vfo[active_vfo].att[vfo[active_vfo].band];
}
 
//если usb и lsb в одном месте - важна последовательность отрисовки
if ((mode1 != ex_mode1)and(!TuneState)) {
  if (mode1 == 0) {
    display.fillRoundRect(LSB_X_BASE, LSB_Y_BASE, LSB_BGSIZE_W, LSB_BGSIZE_H, min(LSB_BGSIZE_W, LSB_BGSIZE_H)/4, LSB_BG_COLOR);
    display.drawRoundRect(LSB_X_BASE, LSB_Y_BASE, LSB_BGSIZE_W, LSB_BGSIZE_H, min(LSB_BGSIZE_W, LSB_BGSIZE_H)/4, OUTLINE_COLOR);
    display.setCursor(LSB_X_BASE+3, LSB_Y_BASE+3);
    display.setTextColor(LSB_COLOR);
    display.setTextSize(LSB_TEXTSIZE);    
    display.print("LSB");
  } else {
    display.fillRoundRect(USB_X_BASE, USB_Y_BASE, USB_BGSIZE_W, USB_BGSIZE_H, min(USB_BGSIZE_W, USB_BGSIZE_H)/4, USB_BG_COLOR);
    display.drawRoundRect(USB_X_BASE, USB_Y_BASE, USB_BGSIZE_W, USB_BGSIZE_H, min(USB_BGSIZE_W, USB_BGSIZE_H)/4, OUTLINE_COLOR);
    display.setCursor(USB_X_BASE+3, USB_Y_BASE+3);
    display.setTextColor(USB_COLOR);
    display.setTextSize(USB_TEXTSIZE);
    display.print("USB");
    
    /*
    l_tx_bg_color  = LSB_BG_COLOR;
    l_tx_color     = LSB_COLOR;    
    l_rx_bg_color  = BG_COLOR;
    l_rx_color     = BG_COLOR;
    if ((LSB_X_BASE != USB_X_BASE)||(LSB_Y_BASE != USB_Y_BASE)) {    
      display.fillRoundRect(USB_X_BASE, USB_Y_BASE, USB_BGSIZE_W, USB_BGSIZE_H, min(USB_BGSIZE_W, USB_BGSIZE_H)/4, l_rx_bg_color);
      display.drawRoundRect(USB_X_BASE, USB_Y_BASE, USB_BGSIZE_W, USB_BGSIZE_H, min(USB_BGSIZE_W, USB_BGSIZE_H)/4, OUTLINE_COLOR);
      display.setCursor(USB_X_BASE+3, USB_Y_BASE+3);
      display.setTextColor(l_rx_color);
      display.setTextSize(USB_TEXTSIZE);
      display.print("USB");
    }  
    display.fillRoundRect(LSB_X_BASE, LSB_Y_BASE, LSB_BGSIZE_W, LSB_BGSIZE_H, min(LSB_BGSIZE_W, LSB_BGSIZE_H)/4, l_tx_bg_color);
    display.drawRoundRect(LSB_X_BASE, LSB_Y_BASE, LSB_BGSIZE_W, LSB_BGSIZE_H, min(LSB_BGSIZE_W, LSB_BGSIZE_H)/4, OUTLINE_COLOR);
    display.setCursor(LSB_X_BASE+3, LSB_Y_BASE+3);
    display.setTextColor(l_tx_color);
    display.setTextSize(LSB_TEXTSIZE);    
    display.print("LSB");
  } else {
    l_rx_bg_color  = USB_BG_COLOR;
    l_rx_color     = USB_COLOR;    
    l_tx_bg_color  = BG_COLOR;
    l_tx_color     = BG_COLOR;    
    if ((LSB_X_BASE != USB_X_BASE)||(LSB_Y_BASE != USB_Y_BASE)) {
      display.fillRoundRect(LSB_X_BASE, LSB_Y_BASE, LSB_BGSIZE_W, LSB_BGSIZE_H, min(LSB_BGSIZE_W, LSB_BGSIZE_H)/4, l_tx_bg_color);
      display.drawRoundRect(LSB_X_BASE, LSB_Y_BASE, LSB_BGSIZE_W, LSB_BGSIZE_H, min(LSB_BGSIZE_W, LSB_BGSIZE_H)/4, OUTLINE_COLOR);
      display.setCursor(LSB_X_BASE+3, LSB_Y_BASE+3);
      display.setTextColor(l_tx_color);
      display.setTextSize(LSB_TEXTSIZE);      
      display.print("LSB");
    }
    display.fillRoundRect(USB_X_BASE, USB_Y_BASE, USB_BGSIZE_W, USB_BGSIZE_H, min(USB_BGSIZE_W, USB_BGSIZE_H)/4, l_rx_bg_color);
    display.drawRoundRect(USB_X_BASE, USB_Y_BASE, USB_BGSIZE_W, USB_BGSIZE_H, min(USB_BGSIZE_W, USB_BGSIZE_H)/4, OUTLINE_COLOR);
    display.setCursor(USB_X_BASE+3, USB_Y_BASE+3);
    display.setTextColor(l_rx_color);
    display.setTextSize(USB_TEXTSIZE);
    display.print("USB");
    */
  };
  ex_mode1 = mode1;
  };

}

void printVoltmeter() {
char buffer[5];  
// если время измерения еще не подошло - игнорим
if ((vin_time == 0)||(vin_time < millis())) {
  vin = ((analogRead(PIN_VMETER)>>2)*50)>>6;
  utoa_fast_div( vin, buffer, sizeof(buffer), 0 );
  //buffer[sizeof(buffer)-1] = 0x00;
  if (vin != ex_vin) {
    noInterrupts();
    // напряжение изменилось
    if ((vin <= VIN_DELTA_MIN)||(vin >= VIN_DELTA_MAX)) {
      display.fillRoundRect(VIN_X_BASE, VIN_Y_BASE, VIN_BGSIZE_W, VIN_BGSIZE_H, min(VIN_BGSIZE_W, VIN_BGSIZE_H)/4, VIN_BG_COLORA);
    } else {
      display.fillRoundRect(VIN_X_BASE, VIN_Y_BASE, VIN_BGSIZE_W, VIN_BGSIZE_H, min(VIN_BGSIZE_W, VIN_BGSIZE_H)/4, VIN_BG_COLOR);      
    };
    display.drawRoundRect(VIN_X_BASE, VIN_Y_BASE, VIN_BGSIZE_W, VIN_BGSIZE_H, min(VIN_BGSIZE_W, VIN_BGSIZE_H)/4, OUTLINE_COLOR);
    display.setCursor(VIN_X_BASE+3, VIN_Y_BASE+3);
    display.setTextColor(VIN_COLOR);
    display.setTextSize(VIN_TEXTSIZE);
//    display.print( ((vin * 50) >> 6) );
//    display.print( vin );
    display.print( buffer );
    ex_vin = vin;
    interrupts();
    };  
  // заряжаем следующий таймер для измерения
  vin_time = millis() + VIN_BG_MEASPER;  
  };
}

void printSmeter(){
  int i,x,h,w,l;
  uint16_t c,l_METER_COLOR,l_METER_COLOR_P;
  
  if (firstRunSMeter) {
    display.drawFastHLine(METER_X_BASE+0, METER_Y_BASE+0, 160, METER_COLOR);      
    display.drawFastHLine(METER_X_BASE+0, METER_Y_BASE+1, 160, METER_COLOR);   
    for ( int i=0;i<14;i++) {         
      if (i<11) { x = METER_X_BASE+i*12; } else { x = METER_X_BASE + 120 + ((i-10)*13); };
      display.drawFastVLine(x, METER_Y_BASE+0, 4, METER_COLOR);    
      display.drawFastVLine(x+1, METER_Y_BASE+0, 4, METER_COLOR);        
    }
  };
  
  //если меняется rx/tx - меняем подпись под S метром
  if (ptt != ex_ptt) {
    display.setCursor(METER_X_BASE+4, METER_Y_BASE+10);
    display.setTextSize(METER_LABEL_S);
    if (ptt) {
      display.setTextColor(BG_COLOR);      
      display.print("1   3   5   7   9 + + + +");
      display.setCursor(METER_X_BASE+4, METER_Y_BASE+10);      
      display.setTextColor(METER_LABEL_C);      
      display.print(" 10%  30%  50%  70%  100%");
    } else {
      display.setTextColor(BG_COLOR);      
      display.print(" 10%  30%  50%  70%  100%");      
      display.setCursor(METER_X_BASE+4, METER_Y_BASE+10);      
      display.setTextColor(METER_LABEL_C);      
      display.print("1   3   5   7   9 + + + +");
    };
    if (!firstRunSMeter) {
      smeterlastLevel = 9999;
      smeterlastLevel_cub = 0;
    };
  };    
  if (smeterlastLevel != smeterLevel) {
    noInterrupts();
    //преобразуем уровень в число кубиков
    if (ptt) {
      for ( l=0;  ((l<13)&&(smeterLevel > pmeterlevels[l]));    l++ ); 
      l_METER_COLOR   = METER_COLOR_PW;
      l_METER_COLOR_P = METER_COLOR_PW;      
    } else {
      for ( l=0;  ((l<13)&&(smeterLevel > smeterlevels[l]));    l++ );
      l_METER_COLOR   = METER_COLOR;
      l_METER_COLOR_P = METER_COLOR_P;      
    }
    for ( i=0;i<14;i++ ) {
      if (i<9) { 
        x = METER_X_BASE+i*12; 
        h = i*2 + 8;
        c = l_METER_COLOR;
        w = 10;
      } else { 
        h = i*2 + 8;
        x = METER_X_BASE + 121 + ((i-10)*13); 
        c = l_METER_COLOR_P;
        w = 11;
      };
      if (i < l) {
        if (smeterlastLevel_cub <= i) {
          display.fillRoundRect(x+2, METER_Y_BASE - h, w, h-1, min(w, h-1)/4, c);
          display.drawRoundRect(x+2, METER_Y_BASE - h, w, h-1, min(w, h-1)/4, OUTLINE_COLOR);
        };  
      } else {
        if (smeterlastLevel_cub > i) {        
          display.fillRoundRect(x+2, METER_Y_BASE - h, w, h-1, min(w, h-1)/4, BG_COLOR);
          display.drawRoundRect(x+2, METER_Y_BASE - h, w, h-1, min(w, h-1)/4, OUTLINE_COLOR);
        };
      };  
    };
  smeterlastLevel = smeterLevel;
  smeterlastLevel_cub = l;
  interrupts();
  };  
  if (firstRunSMeter) firstRunSMeter = 0;
}

void setup()   {
  pinMode(PIN_TX,     OUTPUT);        //1=TX_on
  pinMode(PIN_PTT,    INPUT_PULLUP);
  pinMode(PIN_MEANDR, OUTPUT);  
  pinMode(PIN_ATT,    OUTPUT);  
  //pinMode(DDS_FQUP,   OUTPUT);
  //digitalWrite(DDS_FQUP, LOW);
  //pulseHigh(DDS_FQUP);  
  
  pinMode(BPF_BAND_1, OUTPUT);
  pinMode(BPF_BAND_2, OUTPUT);  
  pinMode(BPF_BAND_3, OUTPUT);  
  //pinMode(BPF_BAND_4, OUTPUT);  
  
  digitalWrite(PIN_KEYPAD, HIGH);

//  SPI.begin();
//  SPI.setClockDivider(2);
//  SPI.setBitOrder(LSBFIRST);
//  SPI.setDataMode(SPI_MODE0);

  Serial.begin(SERIAL_SPEED);
  vfo[0].band = 1;  
  vfo[1].band = 1;
    
  for(byte i=0; i<9;i++)
  {
    vfo[0].freq[i] = bands[i].mid;
    vfo[1].freq[i] = bands[i].mid;
    vfo[0].mode[i] = modes[i];
    vfo[1].mode[i] = modes[i];
    vfo[0].att[i]  = att[i];
    vfo[1].att[i]  = att[i];
  }
  //***************** прерывание для энкодера ******************
  PCICR |= (1 << PCIE2);
  PCMSK2 |= (1 << PCINT18) | (1 << PCINT19);
  sei();
  //************************************************************

  display.initR(INITR_BLACKTAB);   // инициализация ST7735S с черной меткой
  display.setRotation(3);
  display.fillScreen(BG_COLOR);
  display.setTextColor(COLOR);
  
  si5351.set_correction(DDSCORRECTION); 
  si5351.init(SI5351_CRYSTAL_LOAD_8PF, SI5351_CRYSTAL_FREQ);
  si5351.set_pll(SI5351_PLL_FIXED, SI5351_PLLA);
  si5351.set_pll(SI5351_PLL_FIXED, SI5351_PLLB);
  si5351.set_ms_source(SI5351_CLK0, SI5351_PLLA);
  si5351.set_ms_source(SI5351_CLK1, SI5351_PLLB); 
  si5351.pll_reset(SI5351_PLLA);
  si5351.output_enable(SI5351_CLK0, 1);
  si5351.output_enable(SI5351_CLK1, 0);
  si5351.output_enable(SI5351_CLK2, 0);
  si5351.drive_strength(SI5351_CLK0, SI5351_DRIVE_4MA); // 2MA ~ 7dbm, 8MA ~ 14dbm
  
  #ifdef IFFreqCLK2LSB
   si5351.drive_strength(SI5351_CLK1, SI5351_DRIVE_4MA);
   si5351.output_enable(SI5351_CLK1, 1);
  #else
   si5351.output_enable(SI5351_CLK1, 0);   
  #endif
  
  ex_ptt = !ptt;
  restoreMem(); //14.10.16



  DDSfreq=((vfo[active_vfo].freq[vfo[active_vfo].band])+IF+IFoffset)*10;
  DDSsetFrequency(DDSfreq);
  digitalWrite(PIN_ATT, vfo[active_vfo].att[vfo[active_vfo].band]);
  DDSsetFrequency(DDSfreq); // <-- эту добавляем
  xAttState = !vfo[active_vfo].att[vfo[active_vfo].band];
  printMain();
  //printSub();
  bpfUpdate();
  printSmeter(); 
  printModes(); 
}

void loop() {
 if (Serial.available() > 0){
   catread();
 }

  if (CATTXState != xCATTXState) {
  if (CATTXState&&(!ptt)) {
    ptt = HIGH;
    printModes();
  } else if (!CATTXState && (ptt)) {
    ptt = LOW;
    printModes();
  }
    xCATTXState = CATTXState;
  }
  
  //проверяем изменения на PTT только если выключен Tune
  if ((TuneState == 0)&&(CATTXState == 0)) {
  if (digitalRead(PIN_PTT) != ptt) {
    delay(20);
    if (digitalRead(PIN_PTT) != ptt) {
      //if (CATTXState && (!ptt)) CATTXState = 0;
      ptt=digitalRead(PIN_PTT); 
      DDSsetFrequency(DDSfreq);
      printModes();
    }
  }
  }
  
  //Проверяем не нажата ли кнопка кейпада
  g_keypressed = keypooler();

  //Функции кнопок если это первое нажатие
  if ((g_keypressed > 0)&&(g_xkeypressed == 0)) {
  switch (g_keypressed) {
    case 0:
      break;
    case 1:
      setstep();   
      break;
    case 2:
      cb=1;   
      setband();
      break;
    case 3:
      //setTune();
      if (TuneState) { TuneState = 0; } else { TuneState = 1; }
      if (TuneState && (ptt == 0)) {
        ptt=1;
        analogWrite(PIN_MEANDR, 127);
      } else {
          if ((ptt != 0) && (TuneState == 0)) {
            //TX on, но Tune выключили
            //нужно просканить ногу PTT
            if (digitalRead(PIN_PTT) != ptt) {
              delay(20);
              if (digitalRead(PIN_PTT) != ptt) {
                ptt=digitalRead(PIN_PTT); 
              }
            }            
          }
      }
      DDSsetFrequency(DDSfreq);
      if (!TuneState) {
        analogWrite(PIN_MEANDR, 0);        
        ex_mode1 = 10; //Обновить режим на экране
      }
      printModes();
      break;
    case 4:
        Serial.println(vfo[active_vfo].att[vfo[active_vfo].band]);
        vfo[active_vfo].att[vfo[active_vfo].band] = !vfo[active_vfo].att[vfo[active_vfo].band];
        Serial.println(vfo[active_vfo].att[vfo[active_vfo].band]);
        Serial.println("");
        digitalWrite(PIN_ATT, vfo[active_vfo].att[vfo[active_vfo].band]);
        printModes();
      break;  
    default:  
      break;
  }
  g_xkeypressed = g_keypressed;   
  } else {
    if ((g_keypressed == 0)&&(g_xkeypressed > 0)) g_xkeypressed = 0;
  }
  
  if (ptt==0){ 
    digitalWrite(PIN_TX,LOW);
    PTTState=0;
    smeterLevel = analogRead(PIN_SMETER);
  }
  
 /* в связи с введением Tune тут надо разбираться со сплитом
 if (split==1){  //jezeli split jest wlaczony to: 
   if(ptt==1 && PTTState==0){  // sprawdz czy jest PTT i jezeli tak to wykonaj
   splity();
  }
 if(ptt==0 && lastPTTState==0){ //reset split
    splity();
 }
 }
 */

 if (ptt==1) {
   digitalWrite (PIN_TX,HIGH);
   smeterLevel = analogRead(PIN_PMETER);
 }
 
 if (smeterlastLevel != smeterLevel) printSmeter();
 printVoltmeter();

// Записываем частоту в постоянную память если она не изменнялась последние 3 секунды
if  ((memstatus != 0) && (timepassed < millis())) {
  storeMem(); 
}  
}

//обработка прерываний от энкодера
ISR(PCINT2_vect) {
  unsigned char result = r.process();
 if (result == DIR_NONE) {mod=0;}
  else if (result == DIR_CW) {mod=1; countfreq();}
  else if (result == DIR_CCW) {mod=-1; countfreq();}
}

//***********************Rozmowy z Katem****************
void catread(){
     incoming = Serial.read(); delay(3);
     //Serial.println("echo");
     //Serial.println(incoming);
     //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);       
 }
   }
   // display.print(CTi); display.display();

  switch (CTi){
  case 4:
    CATpoll_in();
    break;
  case 5:
    CATsetmode();
    break;
  case 6:
    CATsetmode();
    break;
  case 9:
    CATsetfreq();
    break;
  default:
    FA();
    break;  
  }
   //Serial.print("cti-=");
   //Serial.println(CTi,HEX);
   //display.setCursor(64,20);
   //display.print(CTi);
   //display.display();
}  //Koniec CAT

//********** переключение шага частоты *******************
void setstep(){
  switch (stepA){ 
    case 1:
      stepA=10000;
      break;
    case 10:
      stepA=1;
      break;
    case 100:
      stepA=10;
      break;
    case 1000:
      stepA=100;
      break;
    case 10000:
      stepA=1000;
      break;
  }
  printMain();
  // 14.10.16 <
  timepassed = millis() + MEMSTORETOEEPROM;
  memstatus = 1; // Сигнализируем об изменении частоты и потенциальной необходимости ее записи в постоянную память
  // 14.10.16 >   
}

//********** переключение аттенюатора ********************
//to jeszcze nie jest wyprowaszone na złącza
void set_ATT(){
  if (cATT==1){
  switch (setATT){ 
    case 0:
      setATT=1;
      break;
    case 1:
      setATT=2;
      break;
    case 2:
      setATT=3;
      break;
      case 3:
      setATT=1;
      break;
   }
  }
 cATT=0; 
  printModes(); 
}

//******** перестройка частоты ******************************
void countfreq(){
  vfo[active_vfo].freq[vfo[active_vfo].band] += stepA * mod;
  
  if(vfo[active_vfo].freq[vfo[active_vfo].band] < bands[vfo[active_vfo].band].lower_limit)
    vfo[active_vfo].freq[vfo[active_vfo].band] = bands[vfo[active_vfo].band].lower_limit;
    
  if(vfo[active_vfo].freq[vfo[active_vfo].band] > bands[vfo[active_vfo].band].upper_limit)
    vfo[active_vfo].freq[vfo[active_vfo].band] = bands[vfo[active_vfo].band].upper_limit; 
    
 // Serial.println(vfo[active_vfo].freq[vfo[active_vfo].band]);
 
 // определяем частоту для DDS в зависимости от режима 0=cw, 1=lsb, 3=usb
 switch(mode1){
      case 0:
            DDSfreq=((vfo[active_vfo].freq[vfo[active_vfo].band])+IF)*10;
            break;
      case 1:
            DDSfreq=((vfo[active_vfo].freq[vfo[active_vfo].band])-IF)*10;
            break;
      case 3:
            DDSfreq=((vfo[active_vfo].freq[vfo[active_vfo].band])+IF-CWoffset)*10;
            break;
 }
 DDSsetFrequency(DDSfreq); // отправляем частоту в DDS
 printMain();              // перерисовываем частоту на экране
 timepassed = millis() + MEMSTORETOEEPROM;
 memstatus = 1; // Сигнализируем об изменении частоты и потенциальной необходимости ее записи в постоянную память
}

//********** переключение диапазонов ***************
void setband(){
  if ((cb==1)&&(vfo[active_vfo].band==BAND_MAX)) 
  {
    vfo[active_vfo].band=0; 
    cb=0;
  }
  if ((cb==1)&&(vfo[active_vfo].band <BAND_MAX)) 
  {
    vfo[active_vfo].band++; 
    cb=0;
  } 
  if ((cb==-1)&&(vfo[active_vfo].band==0)) 
  {
    vfo[active_vfo].band=BAND_MAX; 
    cb=0;
  }
  if ((cb==-1)&&(vfo[active_vfo].band >0)) 
  {
    vfo[active_vfo].band--; 
    cb=0;
  }
  setmode();  // поскольку на каждом диапазоне по умолчанию может быть разный режим - апдейтим режим
}

//********** переключаем режим ***************
void setmode(){
 /****************Serial.println("*********************CM=");
Serial.print("CM=");
Serial.println(cm); 
Serial.println("*********************CM=");
  ******************************/
  if (cm==1)
 {   
     if(vfo[active_vfo].mode[vfo[active_vfo].band]==0) {vfo[active_vfo].mode[vfo[active_vfo].band]++;} 
     else if(vfo[active_vfo].mode[vfo[active_vfo].band]==1) {vfo[active_vfo].mode[vfo[active_vfo].band]+=2;}
     else if (vfo[active_vfo].mode[vfo[active_vfo].band]==3) {(vfo[active_vfo].mode[vfo[active_vfo].band])=0;}
     //mode+1 = (0,1,2)
     //else {vfo[active_vfo].mode[vfo[active_vfo].band]=0;}
  //Serial.println(vfo[active_vfo].mode[vfo[active_vfo].band]);
 cm=0;
  }
  mode1= vfo[active_vfo].mode[vfo[active_vfo].band];
 
  switch(mode1){
          case 0:
            DDSfreq=((vfo[active_vfo].freq[vfo[active_vfo].band])+IF)*10;
            PCFmode=16;
                      break;
            case 1:
            DDSfreq=((vfo[active_vfo].freq[vfo[active_vfo].band])-IF)*10;
            PCFmode=32;
            
            break;
            case 3:
            DDSfreq=((vfo[active_vfo].freq[vfo[active_vfo].band])+IF-CWoffset)*10;
            PCFmode=64;
            
            break;
 }
  bpfUpdate();
  DDSsetFrequency(DDSfreq);
  printMain();
  //printSub();
  printModes();
  timepassed = millis() + MEMSTORETOEEPROM;
  memstatus = 1; // Сигнализируем об изменении частоты и потенциальной необходимости ее записи в постоянную память
}

//**************** переключение VfoA / VfoB
/*
void swapy(){
  if (rownaj==1){
    vfo[1-active_vfo].band = vfo[active_vfo].band;
    vfo[1-active_vfo].freq[vfo[1-active_vfo].band] = vfo[active_vfo].freq[vfo[active_vfo].band];
    vfo[1-active_vfo].mode[vfo[1-active_vfo].band] = vfo[active_vfo].mode[vfo[active_vfo].band];
  }
  else 
    active_vfo = 1 - active_vfo;
  setmode(); 
}
*/

/*
//**************** обработка SPLIT
void splity(){
   if(ptt==1){
   PTTState=1;
   lastPTTState=0;
 }
else {lastPTTState=1;}
  swapy(); // сплит в режиме TX меняет VFO_A и VFO_B местами
} 
*/

//обновление регистра управления ДПФ
void bpfUpdate() {
  digitalWrite(BPF_BAND_1, LOW);
  digitalWrite(BPF_BAND_2, LOW);
  digitalWrite(BPF_BAND_3, LOW);
  //digitalWrite(BPF_BAND_4, LOW);  
  switch (vfo[active_vfo].band) {
  case 0:
          digitalWrite(BPF_BAND_1, HIGH);
          break;
  case 1:
          digitalWrite(BPF_BAND_2, HIGH);  
          break;
  case 2:
          digitalWrite(BPF_BAND_3, HIGH);  
          break;
//  case 3:
//          digitalWrite(BPF_BAND_4, HIGH);  
//          break;
  }
}

// ********************** поддержка DDS SI5351 **********************
void DDSsetFrequency(double frequency) {
  if (!ptt && vfo[active_vfo].att[vfo[active_vfo].band]) frequency += CWoffset; // <-- эту добавляем, += на -= если не в ту сторону
  /*
  // Вычисление частоты из даташита, стр. 8 = <sys clock> * <frequency tuning word>/2^32  
  int32_t freq = frequency * DDSCORRECTION/DDS_OSC_FREQ;
  SPI.setBitOrder(LSBFIRST);                        // включаем режим порядка битов SPI для AD985x
  for (int b=0; b<4; b++, freq>>=8) {
    byte response = SPI.transfer(freq & 0xFF);
  } 
  byte response = SPI.transfer(DDS_END_BYTE);
  pulseHigh(DDS_FQUP);                               
  SPI.setBitOrder(MSBFIRST);                        // включаем режим порядка битов SPI для дисплея  
  */
  #ifdef IFFreqCLK2LSB
    if (ptt && (REVERSE_TXRX==1)) {
      si5351.set_freq( frequency * SI5351_FREQ_MULT, SI5351_PLL_FIXED, SI5351_CLK1 );      
      if (vfo[active_vfo].mode[vfo[active_vfo].band] == 0) { 
        si5351.set_freq(IFFreqCLK2LSB * 10 * SI5351_FREQ_MULT, SI5351_PLL_FIXED, SI5351_CLK0); 
        } else {
          if (vfo[active_vfo].mode[vfo[active_vfo].band] == 1) { 
            si5351.set_freq(IFFreqCLK2USB * 10 * SI5351_FREQ_MULT, SI5351_PLL_FIXED, SI5351_CLK0);       
          };
        };
    } else {
      si5351.set_freq( frequency * SI5351_FREQ_MULT, SI5351_PLL_FIXED, SI5351_CLK0 );      
      if (vfo[active_vfo].mode[vfo[active_vfo].band] == 0) { 
        si5351.set_freq(IFFreqCLK2LSB * 10 * SI5351_FREQ_MULT, SI5351_PLL_FIXED, SI5351_CLK1); 
        } else {
          if (vfo[active_vfo].mode[vfo[active_vfo].band] == 1) { 
            si5351.set_freq(IFFreqCLK2USB * 10 * SI5351_FREQ_MULT, SI5351_PLL_FIXED, SI5351_CLK1);       
          };
        };
    };  
  #else
    si5351.set_freq( frequency * SI5351_FREQ_MULT, SI5351_PLL_FIXED, SI5351_CLK0 );
  #endif
}
// ********************** поддержка кейпада **********************
int keypooler() {
  int adc;
  int xkeypressed = 0;
  int keypressed  = g_xkeypressed;
  adc = analogRead(PIN_KEYPAD); // Считываем значение АЦП кейпада
  
  #ifdef Keypad_ADC_Check
   Serial.println();  
   Serial.println(adc);
  #endif
  
  if (adc > BUTTON1_2) 
  {
    //кнопка отпущена, но была нажата
    if (g_xkeypressed != 0) 
    {
	 //была нажатая кнопка, делаем паузу на дребезг и проверяем еще раз
	 delay(10);
	 adc  = analogRead(PIN_KEYPAD); //считываем значение АЦП кейпада
	 if (adc > BUTTON1_2) keypressed = 0; //кнопка действительно отпущена
    }
  } else {
      //кнопка была отпущена и обработана, но теперь что то нажали
      if (g_xkeypressed == 0) {
        //первый замер
        if ((adc >= BUTTON1_1)&&(adc <= BUTTON1_2)) { xkeypressed = 1; } else
          if ((adc >= BUTTON2_1)&&(adc <= BUTTON2_2)) { xkeypressed = 2; } else
            if ((adc >= BUTTON3_1)&&(adc <= BUTTON3_2)) { xkeypressed = 3; } else
              if ((adc >= BUTTON4_1)&&(adc <= BUTTON4_2)) { xkeypressed = 4; };
        //после паузы считываем еще раз
        delay(10);
        //второй замер
        adc  = analogRead(PIN_KEYPAD); // Считываем значение АЦП кейпада        
        if ((adc >= BUTTON1_1)&&(adc <= BUTTON1_2)) { keypressed = 1; } else
          if ((adc >= BUTTON2_1)&&(adc <= BUTTON2_2)) { keypressed = 2; } else
            if ((adc >= BUTTON3_1)&&(adc <= BUTTON3_2)) { keypressed = 3; } else          
              if ((adc >= BUTTON4_1)&&(adc <= BUTTON4_2)) { keypressed = 4; };
        //если замеры совпали - кнопка нажата
      }
  }
  return(keypressed);
}

// ********************** поддержка EEPROM **********************
void storeMem(){
//Записываем текущую частоту в постоянную память (EEPROM) поразрядно
  long stepC;
  int i;
  stepC = stepA;
  for(i=1;((i<5)&&(stepC>1));i++) stepC = stepC / 10;
  splitRx(vfo[active_vfo].freq[vfo[active_vfo].band]);
  EEPROM.write(0,millions);
  EEPROM.write(1,hundredthousands);
  EEPROM.write(2,tenthousands);
  EEPROM.write(3,thousands);
  EEPROM.write(4,hundreds);
  EEPROM.write(5,tens);
  EEPROM.write(6,ones);
  EEPROM.write(7,i);  
  //Serial.println(i);
  EEPROM.write(8,vfo[active_vfo].band);
  EEPROM.write(9,vfo[active_vfo].mode[vfo[active_vfo].band]);
  EEPROM.write(10,vfo[active_vfo].att[vfo[active_vfo].band]);
// Сигнализируем программе, что последние изменения частоты записаны в постоянную память (EEPROM)
  memstatus = 0;
};

void restoreMem() {
  long stepC;
  int i,j;
  stepC = 1;
  j = EEPROM.read(7);
  if ((j > 0)&&(j < 6)) for(i=1;(i<j);i++) stepC = stepC * 10;
  stepA = stepC;
  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));
  //Serial.println(stepA);
  vfo[active_vfo].band = EEPROM.read(8);
  vfo[active_vfo].mode[vfo[active_vfo].band] = EEPROM.read(9);
  vfo[active_vfo].att[vfo[active_vfo].band]  = EEPROM.read(10);
  vfo[active_vfo].freq[vfo[active_vfo].band] = freq.toInt();
  //если считали фигню - устанавливаем по умолчанию
  if ((vfo[active_vfo].freq[vfo[active_vfo].band] >= 3000000)||(vfo[active_vfo].freq[vfo[active_vfo].band] <= 10000)||
     (vfo[active_vfo].mode[vfo[active_vfo].band] < 0)||(vfo[active_vfo].mode[vfo[active_vfo].band] > BAND_MAX))
     {
       vfo[active_vfo].band = 1;
       vfo[active_vfo].mode[vfo[active_vfo].band] = 0;
       vfo[active_vfo].freq[vfo[active_vfo].band] = 370000;
       vfo[active_vfo].freq[vfo[active_vfo].band] = 0;
     }
}

void splitRx(long 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);
}
 
// ********************** поддержка CAT (ICOM) **********************
void CATpoll_in(){
  if (buffget[2]==3){freq_to_send();} //o czestotliwosc - wysylam odpowiedz
  if (buffget[2]==4){mode_to_send();} //o mode - - wysylam odpowiedz
}

void CATsetmode() //ustaw mode zgodnie z loggerem
{
  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;
      Serial.write (0xFE);
      Serial.write (0xFE);
      Serial.write (0x50);
      Serial.write (0xE0);
      Serial.write (buffget[2]);
      Serial.write (0xFD);
      Serial.flush();
    } else {
      FA();
    }
  }
}

void CATsetfreq() //ustaw freq zgodnie z loggerem
{
  if ((buffget[2]==5)||(buffget[2]==0))
  poll_in_frequency();
} 

void CAT_komunikat(){
  // tylko do testów CAT
  //display.print("odebrano polling");
  //display.display();
}

void poll_in_mode() //przyszło mode z loggera
{
  vfo[active_vfo].mode[vfo[active_vfo].band]=buffget[3];
  setmode();
}

void poll_in_frequency(){    
  DMHZ = (buffget[6]);  // Dziesiątki MHz ;-)
  DMHZ = DMHZ - (((DMHZ/16) * 6));
  MHZ = buffget[5];
  MHZ = MHZ - (((MHZ/16) * 6));              // Transform bytes ICOM CAT 
  KHZ = buffget[4]; 
  KHZ = KHZ - (((KHZ/16) * 6));              // Transform bytes ICOM CAT 
  HZ = buffget[3]; 
  HZ = HZ - (((HZ/16) * 6));                 // Transform bytes ICOM CAT 
  QRG = (((long(DMHZ)*1000000)+(long(MHZ) * 10000) + (long(KHZ) * 100) + (long(HZ) * 1)))/10; // QRG variable stores frequency in MMkkkH  format

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();
  vfo[active_vfo].band=bandCAT; //ustawiam pasmo Heńka
  (vfo[active_vfo].freq[vfo[active_vfo].band])=QRG; // i częstotliwość
  setband();
} else {
  FA();
}
}

void freq_to_send()  //policzenie czestotliwości i wyslanie do loggera
{
 // buffget[2]=0;
sendDMHz=(vfo[active_vfo].freq[vfo[active_vfo].band])/100000;
sendDMHz = sendDMHz + (((sendDMHz/10) * 6));
sendMHz= ((vfo[active_vfo].freq[vfo[active_vfo].band]) % 100000)/1000;
sendMHz = sendMHz + (((sendMHz/10) * 6));
sendkHz= ((vfo[active_vfo].freq[vfo[active_vfo].band]) % 1000)/10;
sendkHz = sendkHz + (((sendkHz/10) * 6));
sendHz= (((vfo[active_vfo].freq[vfo[active_vfo].band]) % 10))*10;
sendHz = sendHz + (((sendHz/10) * 6));
/*
Serial.write (0xFE);
Serial.write (0xFE);
Serial.write (0x50);
Serial.write (0xE0);
Serial.write (0x03);
Serial.write (0xFD);
Serial.flush();
*/
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 (0x50);
Serial.write (0xE0);
Serial.write (0x04);
Serial.write (0xFD);
Serial.flush();
*/
Serial.write (0xFE);
Serial.write (0xFE);
Serial.write (0xE0);
Serial.write (0x50);
Serial.write (0x04);
Serial.write (mode1);
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();
}

//совсем служебные функции

// быстрое деление для преобразования числа в строку
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++;
    }
}

// быстрое преобразования числа в строку с разделителем разрядов
// и фиксированной длиной sizeof(buffer)
//   char buffer[12];
//   utoa_fast_div(number, buffer, sizeof(buffer), );
//   lcd.print(buffer);  
char * utoa_fast_div(uint32_t value, char *buffer, uint8_t tcnt, uint8_t lgrp) {
    uint8_t  dcnt = 0;
    uint32_t quot;
    uint8_t  rem;
    uint8_t  grp;    
    buffer += tcnt;
    *--buffer = 0;
    grp = lgrp;
    do
    {
        divmodu10(value, quot, rem);
        *--buffer = rem + '0';
	dcnt++;
	tcnt--;
        if (dcnt > grp) { 
          *--buffer = SEP_DIGIT; dcnt = 0; tcnt--;
          if (grp < 2) grp = 2;
        }
        value = quot;
    }
    while (value != 0);
    tcnt--;
    while (tcnt > 0) {
    	tcnt--;
    	*--buffer = ' ';
    };
    return buffer;
}
