/*****************************************************
This program was produced by the
CodeWizardAVR V2.03.8a Evaluation
Automatic Program Generator
© Copyright 1998-2008 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com

Project : 
Version : 
Date    : 05.11.2008
Author  : Freeware, for evaluation and non-commercial use only
Company : 
Comments: 


Chip type           : ATmega32
Program type        : Application
Clock frequency     : 16,000000 MHz
Memory model        : Small
External RAM size   : 0
Data Stack size     : 256
*****************************************************/

#include <mega32.h>
#include <spi.h>
#include <delay.h>
#include <stdio.h>
#include <mem.h>
#include <math.h>
//#include <stdlib.h>

#define RES PORTB.1 // вывод нокиевского экрана - ресет - очень нужный
#define DC  PORTB.0  // вывод "Команда-Данные" инверсный - тож очень нужный

// 1 Wire Bus functions
#asm
.equ __w1_port=0x18 ;PORTB
   .equ __w1_bit=3
#endasm

// DS1820 Temperature Sensor functions
//#include <ds18b20.h> // это включать вместо следущей если хочется супер точность(пробывал - в эмуле не работает)
#include <1wire.h>
#include <ds18b20.h>

struct ds_scratch_pad_struct
       {
       unsigned char temp_lsb,temp_msb,
                temp_high,temp_low,
                conf_register,
                res1,
                res2,
                res3,
                crc;
       } ds_scratch_pad;


#include <USART.c>

unsigned char x1;
unsigned char y1;
float ds_temp; // если даччик тупенький и float если высокоточный

//bit below;  // идентификатор отрицательности
bit InvPrint = 0;
bit ExtRep; // идентификатор необходимости скидывать скретчпады в ком порт
//bit TimOwf = 0;
bit DispBusy = 0;
bit PrnTemps = 1; // идентификатор вывода граф температур на экран
unsigned char GraphicTimeout = 0; // Время в прерываниях 2-го таймера, на протяжении которого не обновлялся графически экран
#define MaxGraphTimeout 10  

// maximum number of DS1820 devices
// connected to the 1 Wire bus
#define MAX_DS1820 5
// number of DS1820 devices
// connected to the 1 Wire bus
unsigned char devices; //Это кол-во даччиков температуры 

// DS1820 devices ROM code storage area,
// 9 bytes are used for each device
// (see the w1_search function description in the help)
unsigned char rom_codes[MAX_DS1820][9];
int motor_step = 0;      // состояние шагового мотора

eeprom char mem_contr=90; // контрастность экранчика
eeprom unsigned char mem_WaitDS = 100; // сколько десятков миллисекунд ждать окончания преобразования ДСками(чем больше тем дольше :)
unsigned char WaitDS = 100;

void LCD_Menu(void);

void lcd_clear(void);

/*
//табличка расчета CRC
flash unsigned char CRCTable[256] = {
        0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65,
        157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220,
        35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98,
        190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255,
        70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102, 229, 187, 89, 7,
        219, 133, 103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 196, 154,
        101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36,
        248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185,
        140, 210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113, 147,205,
        17, 79, 173, 243, 112, 46, 204, 146, 211, 141, 111, 49, 178, 236, 14, 80,
        175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82, 176, 238,
        50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115,
        202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139,
        87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22,
        233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168,
        116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53};
*/

#define LcdBufSize 25

unsigned int temp=0;                // просто временная переменная для всех случаев
unsigned int i=1;                   // переменная для циклов
unsigned long int Sec = 0;          // переменная для обозначения секунд в тиках второго таймера
unsigned int mSec = 0;
#define SecondTick 15626

// переменные и шаблоны для TPIC и системы контроля температуры
#define TPIC_Write PORTC.3
unsigned char ExtPort = 0b00000000;                 // буффер записи в tpic
eeprom char TargTemp = 25;                          // еепром значение температуры поддержания
char CurrTargTemp = 0;                              // кэш еепрома для ускорения
eeprom unsigned char TargSensorCRC = 92;            // последний байт адреса сенсора
unsigned char CurrTargSensorCRC = 0;                // кешированный последний байт адреса сенсора
bit H1 = 0;                                         // флаг включения спирали 1
bit H2 = 0;                                         // флаг включения спирали 2
bit CurrH = 0;                                      // флаг для поочередного врубания одной спиирали
bit L1 = 0;                                         // флаг 1 лампочки
bit L2 = 0;                                         // флаг 2 лампочки
#define LAMP1 L1
#define LAMP2 L2


//шаблоны для подключенных лампочек и пинов ШИМки
#define BLANK PORTC.5
//#define BLANK2 DDRC.5
#define XLAT  PORTC.2

// подключение тсопа
#define tsop PINB.2

unsigned char l_min = 130;                     //диапазон для "длинного" (long) интервала в посылке, в "тиках" таймера, 1,28..2,176мс 
unsigned char l_max = 150;
unsigned char s_min = 60;                     //диапазон для "короткого" (short) интервала в посылке, в "тиках" таймера, 0,704..1,088мс
unsigned char s_max = 80;
unsigned int st_min = 800;                     //диапазон для "старт" интервала в посылке, в "тиках" таймера, 0,704..1,088мс
unsigned int st_max = 900;
unsigned int rp_min = 500;                     //диапазон для "Повтор" интервала в посылке, в "тиках" таймера, 0,704..1,088мс
unsigned int rp_max = 700;

unsigned char LastCMD = 0;      //переменная последней команды

unsigned int tick = 0;          //счетчик тиков таймера
unsigned char b_cnt = 0;        //счетчик принятых бит
unsigned int TimerH = 0;        //Старший разряд таймера
bit start_cond = 0;             //флаг стартового условия
bit repeat_cond = 0;            //флаг повтора
bit ShowTiming = 0;             //флаг показывания на экране таблички таймингов
bit Cmpl_Rcv    = 0;            //Флаг завершения приёма

unsigned char addr_1 = 0;       //прямой байт адреса
unsigned char addr_0 = 0;       //инверсный байт адреса
unsigned char cmd_1 = 0;        //прямой байт команды
unsigned char cmd_0 = 0;        //инверсный байт команды
unsigned char addr = 0;         //байт адреса
unsigned char cmd = 0;          //байт команды
// конец переменных пультика 

     
// Declare your global variables here
void ComInterface(void);
 
char x = 1;
char y = 1;

unsigned char CurrTemp = 0;

eeprom unsigned char Eep_PrnTemp = 1;
bit ThermoStabiliser = 1;               // Флаг включения термостабилизатора для спиралей нагревателя
bit PrnStatBar       = 1;               // Флаг включения вывода статус бара с состояниями выходов TPIC

typedef struct
{
    unsigned char En;
    unsigned long int Sec;
    unsigned int mSec;
    } nt;
    
    nt n1;  // Время след запуска процедуры начала преобразования
    nt n2;  // Время след запуска процедуры вывода результата преобразования
//    nt n3;  // Время след запуска процедуры обработки комманд пультика

//    unsigned long int   n1Sec  = 0;
//    unsigned int        n1mSec = 0;
//    bit                 n1En   = 1;
//    
//    unsigned long int   n2Sec  = 0;
//    unsigned int        n2mSec = 0;
//    bit                 n2En   = 1;

// переменные для PWM таймеров и зарядки вообще
unsigned char ChargeState[4]        = {0,0,0,0};    // флаг состояния зарядки

unsigned char input_index           = 0;            // простая переменная текущего канала измерения АЦП

/*
#define PWM_PIN_CHG1 PORTC.0                         // Ножка для PWM зарядки 1 канала     
#define PWM_PIN_CHG2 PORTC.2                         // Ножка для PWM зарядки 2 канала
#define PWM_PIN_CHG3 PORTC.4                         // Ножка для PWM зарядки 3 канала
#define PWM_PIN_CHG4 PORTC.6                         // Ножка для PWM зарядки 4 канала

#define PWM_PIN_DisCHG1 PORTC.1                      // Ножка для PWM разрядки 1 канала
#define PWM_PIN_DisCHG2 PORTC.3                      // Ножка для PWM разрядки 2 канала
#define PWM_PIN_DisCHG3 PORTC.5                      // Ножка для PWM разрядки 3 канала
#define PWM_PIN_DisCHG4 PORTC.7                      // Ножка для PWM разрядки 4 канала
*/

#define TimPWM_Start 03
#define TimPWM_Stop 00 

#define ADC_START 0xCC
#define ADC_STOP  0x8C

void PWM();
void TPIC();                                          // прототипы функций

unsigned int PWM_Oth[8]            = {0,0,0,0,0,0,0,0}; // Переменные для остальных 8-ми каналов PWM

unsigned int PWM_Chg[4]            = {0,0,0,0};       // переменная для задания уровня PWM зарядного канала
unsigned int PWM_DisChg[4]         = {0,0,0,0};       // переменная для задания уровня PWM разрядного канала
//unsigned char CurrentPWM            = 0;            // переменная текущего шага PWM

unsigned int Measured_Voltage[4]    = {0,0,0,0};    // текущие начения напряжений с аккумулятора
                                                                                                         
unsigned int Measured_BatCurr[4]    = {0,0,0,0};    // текущий замеренный ток через батарею
unsigned int Target_BatCurr[4]      = {0,0,0,0};    // требуемый для поддержания ток батареи

nt VProbe[4] = {{0,0,0},{0,0,0},{0,0,0},{0,0,0}};   // время следующего запуска замера напряжения(при низком токе разряда)
                                                    // и последующим принятием решения по шагу зарядки
                                                    
nt Charge[4] = {{0,0,0},{0,0,0},{0,0,0},{0,0,0}};   // время следующего запуска зарядки

nt DispState = {0,0,0};                             // Время запуска вывода на экран состояния зарядки 
     
#define FIRST_ADC_INPUT 0
#define LAST_ADC_INPUT 7
unsigned int adc_data[LAST_ADC_INPUT-FIRST_ADC_INPUT+1];
#define ADC_VREF_TYPE 0xC0

                                             
void port(void)
{        
#asm("cli");
// Declare your local variables here
// Input/Output Ports initialization
// Port A initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T 
PORTA=0x00;
DDRA=0x00;

// Port B initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=In Func1=Out Func0=Out 
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=P State1=0 State0=0 
PORTB=0x04;
DDRB=0xFB;

// Port C initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out 
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0 
PORTC=0x00;
DDRC=0xFF;


// Port D initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
// State7=T State6=P State5=P State4=P State3=P State2=T State1=T State0=T 
PORTD=0x78;
DDRD=0x00;


// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 62,500 kHz
// Mode: Normal top=FFh
// OC0 output: Disconnected
TCCR0=0x00;
TCNT0=0x00;
OCR0=0x00;


// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 16000,000 kHz
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: On
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x01;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x10;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 16000,000 kHz
// Mode: CTC top=OCR1A
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: On
// Compare B Match Interrupt: On
TCCR1A=0x00;
TCCR1B=0x09;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x3E;
OCR1AL=0x80;
OCR1BH=0x10;
OCR1BL=0x00;


// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;


// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// INT2: On
// INT2 Mode: Falling Edge
GICR|=0x20;
MCUCR=0x00;
MCUCSR=0x80;
GIFR=0x20;


// External Interrupt(s) initialization
// INT0: On
// INT0 Mode: Rising Edge
// INT1: Off
// INT2: On
// INT2 Mode: Falling Edge
GICR|=0x60;
MCUCR=0x03;
MCUCSR=0x80;
GIFR=0x60;

/*
// External Interrupt(s) initialization
// INT0: On
// INT0 Mode: Low level
// INT1: Off
// INT2: On
// INT2 Mode: Falling Edge
GICR|=0x60;
MCUCR=0x00;
MCUCSR=0x00;
GIFR=0x60;
*/

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x81;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x91;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x19;

/*
// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud Rate: 9600
UCSRA=0x00;
UCSRB=0x98;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0x67;
*/

// USART initialization
// Communication Parameters: 8 Data, 2 Stop, No Parity
// USART Receiver: On
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud Rate: 19200
UCSRA=0x00;
UCSRB=0x98;
UCSRC=0x8E;
UBRRH=0x00;
UBRRL=0x08;


// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;

/*
// Analog Comparator initialization
// Analog Comparator: On
// Interrupt on Falling Output Edge
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x0A;
SFIOR=0x00;
*/
/*
// ADC initialization
// ADC Clock frequency: 1000,000 kHz
// ADC Voltage Reference: Int., cap. on AREF
// ADC Auto Trigger Source: Free Running
ADMUX=FIRST_ADC_INPUT | (ADC_VREF_TYPE & 0xff);
ADCSRA=0xEC;
SFIOR&=0x1F;
*/

// ADC initialization
// ADC Clock frequency: 1000,000 kHz
// ADC Voltage Reference: AREF pin
// ADC Auto Trigger Source: None
ADMUX=FIRST_ADC_INPUT | (ADC_VREF_TYPE & 0xff);
ADCSRA=0x8C;

// SPI initialization
// SPI Type: Master
// SPI Clock Rate: 2*4000,000 kHz
// SPI Clock Phase: Cycle Half
// SPI Clock Polarity: Low
// SPI Data Order: MSB First
SPCR=0x50;
SPSR=0x00;

WaitDS = mem_WaitDS;

#asm("sei");

}

#include <lcd_3110.c>

void ComInterface()
{
  // COM портовая менюшка
      
  while(rx_counter){
    temp = getchar();
    //putchar(temp);
    //putsf("\n\r");
    if((temp=='p')||(temp=='P'))
    {
        // запрошена печать букв в дисплей - очень срочно - буфера может не хватить
        // первая после р цифра - номер строки
        DispBusy = 1;
        //TCCR2=0x00; // тормозим таймер чтоб не мешал
        lcd_gotoxy(0, getchar()-48);
             
        /*   
        for(x=0;x<LcdBufSize;x++)
        {
            a2[x] = ' ';
        }
        */
        
        temp=getchar();
        x = 0;
        while(temp<125)        
        {
            a2[x] = temp;
            x++;
            temp = getchar();
            if(x>=LcdBufSize)
                temp = 255;
        }
        //x = temp;
        
        // выводим накопленное
        for(temp=0;temp<x;temp++)
        {
            lcd_putchar(a2[temp]);
        }
        DispBusy = 0;
        //TCCR2=0x07; // стартуем таймер
        continue;
    } 
    else if((temp=='t')||(temp=='t'))
    {
        // Time request
        printf("Time: %u-Min, %u-mSec", Sec, mSec);
        continue;
    }
    else if((temp=='l')||(temp=='L'))
    {
        temp = getchar();
        if((temp=='o')||(temp=='O'))
            PrnTemps = 0;
    }        
    else if((temp=='g')||(temp=='G'))
    {
        // g - идентификатор посылки графики за ней идёт 2 числa:
        // 0 - стартовая строка
        // 1 - конечная строка 
        GraphicTimeout=0;
        DispBusy = 1;
        //TCCR2=0x00; // тормозим таймер чтоб не мешал
        x1 = getchar()-48;           // - номер стартовой строки
        y1 = getchar()-48;           // - номер последней строки
        for(i=x1;i<y1;i++) 
        {        
            lcd_gotoxy(0, i); // поставили курсор в текущее положение
            temp = 0;            // обнуляем счетчик выведенных черточек
            while(temp<84)
            {
                // пока черточек наклацало меньше заданного
                writedata(getchar());
                temp++;
            }
        }
        // закончили с черточками - прерываем обработку
        DispBusy = 0;
        continue;
    }
    else if((temp=='r')||(temp=='R'))
    {
        // ввод свободных комманд 
        switch(getchar()){
           case '1':
                // комманда 1 - изменить состояние первой лампы
                LAMP1 = !LAMP1;
                break;
           case '2':
                // комманда 2 - изменить состояние второй лампы
                LAMP2 = !LAMP2;
                break;
           case '3':
                // комманда 3 - изменить состояние первой лампы в выключенное
                LAMP1 = 0;
                break;
           case '4':
                // комманда 4 - изменить состояние второй лампы в выключенное
                LAMP2 = 0;
                break;                
        } 
        continue;                      
    }
    else if((temp=='x')||(temp=='X'))
    {
        // Это очистка строки, номер которой уже в буфере - следующий
        DispBusy = 1; 
        lcd_clear_row(getchar()-48);
        DispBusy = 0;
        continue;
    }
    else if((temp=='c')||(temp=='C'))
    {
        // ввели С - типа идентификатор конфигурирования
        putsf("Configure mode\n\r");
        putsf("1----Setting contrast\n\r");
        putsf("2----Setting bias\n\r");
        putsf("3----ReSetting LCD\n\r");
        putsf("4----ReScan 1Wire\n\r");
        
        if(ExtRep)
            putsf("5----Turn off ExtRep\n\r");
        else
            putsf("5----Turn on ExtRep\n\r");
        putsf("6----Setting WaitDS\n\r");
        
        /*
        putsf("7----Setting l_min\n\r");
        putsf("8----Setting l_max\n\r");
        putsf("9----Setting s_min\n\r");
        putsf("0----Setting s_max\n\r");  
        putsf("q----Setting st_min\n\r");
        putsf("w----Setting st_max\n\r");
        putsf("a----Setting rp_min\n\r");
        putsf("s----Setting rp_max\n\r");
        */
        
        if(ShowTiming)
            putsf("d----Turn off ShowTiming\n\r");
        else
            putsf("d----Turn on ShowTiming\n\r");
            
        if(PrnTemps)
            putsf("t----Turn off Temp disp\n\r");
        else
            putsf("t----Turn on Temp disp\n\r");                        
                                                 
        putsf("*----Clear LCD\n\r"); 
           
        switch(getchar()){
           case '*':
                do{
                lcd_clear();
                x=1;
                y=1;
                ShowTiming = 1;
                temp = getchar();
                }while((temp=='*')||(temp=='+'));
                break;
                
           case 'd':
                if(ShowTiming)
                    ShowTiming = 0;
                else
                    ShowTiming = 1;
                break;
                
           case 't':
                if(PrnTemps)
                {
                    PrnTemps = 0;
                    Eep_PrnTemp = 0;
                    }
                else
                {
                    PrnTemps = 1;
                    Eep_PrnTemp = 1;
                    }
                break;
                
           case '1':
                putsf("\n\r -- Setting the contrast \n\r");
               //1 - Настройка кинтраста
               // будем получать 0 или 1 побитово 
               i = mem_contr;
               temp = getchar();
               while((temp=='+')||(temp=='-')){
                    if(temp=='+')
                    {
                        i=i+1;
                    }
                    if(temp=='-')
                    {
                        i=i-1;
                    }
                    if(i<=0) i=1;
                    if(i>0b01111111) i=0b01001000;
                    sprintf(a2, "contrast = %i \n\r",i);
                    while(DispBusy == 1);
                    DispBusy = 1;
                    writecomm(0x21); // LCD Extended Commands.
                    writecomm(0b10000000|i); // Вставляем нашу контрастность
                    writecomm(0x20);                     
                    puts(a2);
                    DispBusy = 0;
                    temp = getchar();                        
               }  
               // сохраняем контраст в еепром
               mem_contr = i;                         
               break;
           case '2':
               //PORTC = 0b10010000;
               break;
           case '3':
               lcd_init();
               break;
           case '4':
               devices=w1_search(0xf0,rom_codes);                 
               break;
           case '5':
                if(ExtRep)
                    ExtRep = 0;
                else
                    ExtRep = 1;
                break;
           case '6':
                putsf("\n\r -- Setting the timeout for Temperature conversion of the DS18B20 -- \n\r");
               //1 - Настройка задержки
               // будем получать 0 или 1 побитово 
               i = mem_WaitDS;
               temp = getchar();
               while((temp=='+')||(temp=='-')){
                    if(temp=='+')
                    {
                        i++;
                    }
                    if(temp=='-')
                    {
                        i--;
                    }
                    if(i<=0) i=1;
                    if(i>1000) i=1000;
                    sprintf(a2, "Wait in millisec = %i x 10ms \n\r",i); 
                    puts(a2);
                    temp = getchar();                        
               }  
               // сохраняем WaitDS в еепром
               mem_WaitDS = i;
               WaitDS = i;                         
               break;
           /*    
               // настройки ир
           case '7':
                putsf("\n\r -- Setting the l_min -- \n\r");
               //1 - Настройка задержки
               // будем получать 0 или 1 побитово 
               i = l_min;
               temp = getchar();
               while((temp=='+')||(temp=='-')){
                    if(temp=='+')
                    {
                        i=i+1;
                    }
                    if(temp=='-')
                    {
                        i=i-1;
                    }
                    if(i<=0) i=0;
                    if(i>0b11111111) i=0b11111111;
                    sprintf(a2, "Wait in timer ticks = %i \n\r",i); 
                    puts(a2);
                    temp = getchar();                        
               }  
               // сохраняем WaitDS в еепром
               l_min = i;                         
               break;
           case '8':
                putsf("\n\r -- Setting the timeout l_max -- \n\r");
               //1 - Настройка задержки
               // будем получать 0 или 1 побитово 
               i = l_max;
               temp = getchar();
               while((temp=='+')||(temp=='-')){
                    if(temp=='+')
                    {
                        i=i+1;
                    }
                    if(temp=='-')
                    {
                        i=i-1;
                    }
                    if(i<=0) i=0;
                    if(i>0b11111111) i=0b11111111;
                    sprintf(a2, "Wait in timer ticks = %i \n\r",i); 
                    puts(a2);
                    temp = getchar();                        
               }  
               // сохраняем WaitDS в еепром
               l_max = i;                         
               break;
           case '9':
                putsf("\n\r -- Setting the timeout s_min -- \n\r");
               //1 - Настройка задержки
               // будем получать 0 или 1 побитово 
               i = s_min;
               temp = getchar();
               while((temp=='+')||(temp=='-')){
                    if(temp=='+')
                    {
                        i=i+1;
                    }
                    if(temp=='-')
                    {
                        i=i-1;
                    }
                    if(i<=0) i=0;
                    if(i>0b11111111) i=0b11111111;
                    sprintf(a2, "Wait in timer ticks = %i \n\r",i); 
                    puts(a2);
                    temp = getchar();                        
               }  
               // сохраняем WaitDS в еепром
               s_min = i;                         
               break;
           case '0':
                putsf("\n\r -- Setting the timeout s_max -- \n\r");
               //1 - Настройка задержки
               // будем получать 0 или 1 побитово 
               i = s_max;
               temp = getchar();
               while((temp=='+')||(temp=='-')){
                    if(temp=='+')
                    {
                        i=i+1;
                    }
                    if(temp=='-')
                    {
                        i=i-1;
                    }
                    if(i<=0) i=0;
                    if(i>0b11111111) i=0b11111111;
                    sprintf(a2, "Wait in timer ticks = %i \n\r",i); 
                    puts(a2);
                    temp = getchar();                        
               }  
               // сохраняем WaitDS в еепром
               s_max = i;                         
               break;
               
           case 'q':
                putsf("\n\r -- Setting the timeout st_min -- \n\r");
               //1 - Настройка задержки
               // будем получать 0 или 1 побитово 
               i = st_min;
               temp = getchar();
               while((temp=='+')||(temp=='-')){
                    if(temp=='+')
                    {
                        i=i+1;
                    }
                    if(temp=='-')
                    {
                        i=i-1;
                    }
                    if(i<=0) i=0;
                    if(i>65534) i=65534;
                    sprintf(a2, "Wait in timer ticks = %i \n\r",i); 
                    puts(a2);
                    temp = getchar();                        
               }  
               // сохраняем WaitDS в еепром
               st_min = i;                         
               break;
           case 'w':
                putsf("\n\r -- Setting the timeout st_max -- \n\r");
               //1 - Настройка задержки
               // будем получать 0 или 1 побитово 
               i = st_max;
               temp = getchar();
               while((temp=='+')||(temp=='-')){
                    if(temp=='+')
                    {
                        i=i+1;
                    }
                    if(temp=='-')
                    {
                        i=i-1;
                    }
                    if(i<=0) i=0;
                    if(i>65534) i=65534;
                    sprintf(a2, "Wait in timer ticks = %i \n\r",i); 
                    puts(a2);
                    temp = getchar();                        
               }  
               // сохраняем WaitDS в еепром
               st_max = i;                         
               break;
               
               
           case 'a':
                putsf("\n\r -- Setting the timeout rp_min -- \n\r");
               //1 - Настройка задержки
               // будем получать 0 или 1 побитово 
               i = rp_min;
               temp = getchar();
               while((temp=='+')||(temp=='-')){
                    if(temp=='+')
                    {
                        i=i+1;
                    }
                    if(temp=='-')
                    {
                        i=i-1;
                    }
                    if(i<=0) i=0;
                    if(i>65534) i=65534;
                    sprintf(a2, "Wait in timer ticks = %i \n\r",i); 
                    puts(a2);
                    temp = getchar();                        
               }  
               // сохраняем WaitDS в еепром
               rp_min = i;                         
               break;
           case 's':
                putsf("\n\r -- Setting the timeout rp_max -- \n\r");
               //1 - Настройка задержки
               // будем получать 0 или 1 побитово 
               i = rp_max;
               temp = getchar();
               while((temp=='+')||(temp=='-')){
                    if(temp=='+')
                    {
                        i=i+1;
                    }
                    if(temp=='-')
                    {
                        i=i-1;
                    }
                    if(i<=0) i=0;
                    if(i>65534) i=65534;
                    sprintf(a2, "Wait in timer ticks = %i \n\r",i); 
                    puts(a2);
                    temp = getchar();                        
               }  
               // сохраняем WaitDS в еепром
               rp_max = i;                         
               break;
           */
           }
           
           
        putsf("\n\r Continuing normal cycle\n\r");
    }      
    else if((temp=='w')||(temp=='W'))
    {
        putsf("PWM control mode\n\r");
        temp = '+';
        while((temp=='+')||(temp=='-'))
        {
            lcd_clear_row(1);
            lcd_gotoxy(1,1);
            sprintf(a2, "PWM = %u\n\r", PWM_Oth[3]);
            puts(a2);
            //putsf("");
            lcd_putstr(a2);
            PWM();
            temp = getchar();
            if(temp == '+')
                PWM_Oth[3]+=1;
            if(temp == '-')
                PWM_Oth[3]-=1;
        }
    }
    else if((temp=='d')||(temp=='D'))
    {
        putsf("Termal control mode\n\r");
        //temp = '+';
        CurrTargTemp = TargTemp;
        do
        {
            lcd_clear_row(1);
            lcd_clear_row(2);
            lcd_gotoxy(1,1);
            sprintf(a2, " Dest Temp\n\r");
            puts(a2);
            //putsf("/n/r");
            lcd_putstr(a2);
            lcd_gotoxy(1,1);
            sprintf(a2, "%u\n\r", CurrTargTemp);
            puts(a2);
            //putsf("/n/r");
            lcd_putstr(a2);

            
            //PWM();
            temp = getchar();
            if(temp == '+')
                CurrTargTemp+=1;
            if(temp == '-')
                CurrTargTemp-=1;
        }while((temp=='+')||(temp=='-'));
        TargTemp = CurrTargTemp;
        lcd_clear_row(1);
        lcd_clear_row(2);        
    }
    else if((temp=='k')||(temp=='K'))
    {
        // использование LCD менюшки через COM порт
        LCD_Menu();
    }
  }
}

#define b1 PIND.3
#define b2 PIND.4
#define b3 PIND.5
#define b4 PIND.6

char Button(char z)
{
unsigned char BP = 0;
    do{
        if(rx_counter)
        {
            temp=getchar();
            if(temp == '4')
                BP = 1;
            else if(temp=='8')
                BP=2;
            else if(temp=='2')
                BP=3;
            else if(temp=='6')
                BP=4;  
        }
        else if(Cmpl_Rcv)
        {
            //printf("TSOP button %i \n\r", cmd);
            Cmpl_Rcv = 0;
                if(cmd == 0)
                    BP = 1;
                else if(cmd==16)
                    BP=2;
                else if(cmd==32)
                    BP=3;
                else if(cmd==48)
                    BP=4;            
        }
        else if(z+1-b1+1-b2+1-b3+1-b4!=0)
        {
            delay_ms(100);
            if(z+1-b1+1-b2+1-b3+1-b4!=0)
            {
                if(!b1)
                    BP = 1;
                else if(!b2)
                    BP=2;
                else if(!b3)
                    BP=3;
                else if(!b4)
                    BP=4;
            }
            Cmpl_Rcv = 0;                
        }    
    }
    while(BP+z==0);
    return BP;
}

flash struct Menuitems{
    unsigned char Item[5][15];
    unsigned char NextMenuItem;
    } mi[7] =                     {
    
                                   {"-=MAIN  MENU=-",
                                    "-Lamp control-", 
                                    "- Termo ctrl -",
                                    "-Charge  ctrl-",
                                    "-  SETTINGS  -",255},
                                    
                                   {"*  SETTINGS  *",
                                    "-Set  WAIT_DS-", 
                                    "-Set Thermos -",
                                    "-Set PrnTemps-",
                                    "-Set Contrast-",255},
                                    
                                    
                                   {"*LAMP CONTROL*",
                                    "-POW lamp ON -", 
                                    "-POW lamp OFF-",
                                    "-Desktop  ON -",
                                    "-Desktop  OFF-",255},
 
                                   {"*HEATER CONTR*",
                                    "-t Stabil ON -", 
                                    "-t Stabil OFF-",
                                    "-Coil control-",
                                    "-Set t stabil-",255},

                                   {"*H COIL CONTR*",
                                    "-Coil HI  ON -", 
                                    "-Coil LO  ON -",
                                    "-Coil HI  OFF-",
                                    "-Coil LO  OFF-",255},

                                   {"*STAB  METHOD*",
                                    "-Simple relay-", 
                                    "-P I D Stabil-",
                                    "-P I D Set-gs-",
                                    "-Proportional-",255},
                                    
                                   {"*P I D Params*",
                                    "-Set KP index-", 
                                    "-Set KI index-",
                                    "-Set KD index-",
                                    "-View current-",255}, 
                                    
                                   };
void PrintMI(unsigned char Imi, char Sl)
{
    unsigned char tm = 0;
    lcd_clear();
    for(tm=0;tm<=4;tm++)
    {
        lcd_gotoxy(0,tm);
        sprintf(a2, mi[Imi].Item[tm]);
        if(Sl==tm)
            InvPrint=1;
        else
            InvPrint=0;
                    
        lcd_putstr(a2);
        if(InvPrint)
           putsf(">");
        puts(a2);
        if(InvPrint)
           putsf("<\n\r");
        else
            putsf("\n\r");
        
        
    }
    InvPrint = 0;
}


void Menu_PIDSet()
{
    char tm=0;
    bit cont=1;
    // процедурка первой менюшки для лсд
    //while(DispBusy);
    //DispBusy = 1;
    tm=1;
    do{
        PrintMI(4, tm);
        
        //while(Button()!=0);
        // обработка кнопочек - 
        // 1 "ентер"
        // 2 "вверх"
        // 3 "вниз"
        // 4 "назад"
        delay_ms(100); 
        while(Button(1)!=0)
        {
            delay_ms(10);
        }
        
//                                   {"*H COIL CONTR*",
//                                    "-Coil HI  ON -", 
//                                    "-Coil LO  ON -",
//                                    "-Coil HI  OFF-",
//                                    "-Coil LO  OFF-",255},

        
        switch(Button(0))
        {
            case 1 :    if(tm==1)
                        {
                            ThermoStabiliser = 0;
                            H1 = 1;
                        }
                        if(tm==2)
                        {
                            ThermoStabiliser = 0;
                            H2 = 1;
                        }
                        if(tm==3)
                        {
                            ThermoStabiliser = 0;
                            H1 = 0;
                        }
                        if(tm==4)
                        {
                            ThermoStabiliser = 0;
                            H2 = 0;
                        }
                        TPIC();
                        delay_ms(500);
                        break;
            case 2 :    tm-=1;
                        break;
            case 3 :    tm+=1;
                        break;
            case 4 :    cont=0;
                        break;
        }
        if(tm<1)
            tm = 1;
        if(tm>4)
            if(mi[0].NextMenuItem==255)
                tm = 4;
            else
                tm = 1;
                
    }while(cont);

}


void Menu_StabMethod()
{
    char tm=0;
    bit cont=1;
    // процедурка первой менюшки для лсд
    //while(DispBusy);
    //DispBusy = 1;
    tm=1;
    do{
        PrintMI(5, tm);
        
        //while(Button()!=0);
        // обработка кнопочек - 
        // 1 "ентер"
        // 2 "вверх"
        // 3 "вниз"
        // 4 "назад"
        delay_ms(100); 
        while(Button(1)!=0)
        {
            delay_ms(10);
        }
        
//                                   {"*STAB  METHOD*",
//                                    "-Simple relay-", 
//                                    "-P I D Stabil-",
//                                    "-P I D Set-gs-",
//                                    "-Proportional-",255},

        
        switch(Button(0))
        {
            case 1 :    if(tm==1)
                        {
                            ThermoStabiliser = 1;
                            //H1 = 1;
                        }
                        if(tm==2)
                        {
                            ThermoStabiliser = 2;
                            //H2 = 1;
                        }
                        if(tm==3)
                        {
                            Menu_PIDSet();
                            tm=0;
                        }
                        if(tm==4)
                        {
                            ThermoStabiliser = 3;
                            //H2 = 0;
                        }
                        TPIC();
                        delay_ms(500);
                        break;
            case 2 :    tm-=1;
                        break;
            case 3 :    tm+=1;
                        break;
            case 4 :    cont=0;
                        break;
        }
        if(tm<1)
            tm = 1;
        if(tm>4)
            if(mi[0].NextMenuItem==255)
                tm = 4;
            else
                tm = 1;
                
    }while(cont);

}

void Menu_Coil()
{
    char tm=0;
    bit cont=1;
    // процедурка первой менюшки для лсд
    //while(DispBusy);
    //DispBusy = 1;
    tm=1;
    do{
        PrintMI(4, tm);
        
        //while(Button()!=0);
        // обработка кнопочек - 
        // 1 "ентер"
        // 2 "вверх"
        // 3 "вниз"
        // 4 "назад"
        delay_ms(100); 
        while(Button(1)!=0)
        {
            delay_ms(10);
        }
        
//                                   {"*H COIL CONTR*",
//                                    "-Coil HI  ON -", 
//                                    "-Coil LO  ON -",
//                                    "-Coil HI  OFF-",
//                                    "-Coil LO  OFF-",255},

        
        switch(Button(0))
        {
            case 1 :    if(tm==1)
                        {
                            ThermoStabiliser = 0;
                            H1 = 1;
                        }
                        if(tm==2)
                        {
                            ThermoStabiliser = 0;
                            H2 = 1;
                        }
                        if(tm==3)
                        {
                            ThermoStabiliser = 0;
                            H1 = 0;
                        }
                        if(tm==4)
                        {
                            ThermoStabiliser = 0;
                            H2 = 0;
                        }
                        TPIC();
                        delay_ms(500);
                        break;
            case 2 :    tm-=1;
                        break;
            case 3 :    tm+=1;
                        break;
            case 4 :    cont=0;
                        break;
        }
        if(tm<1)
            tm = 1;
        if(tm>4)
            if(mi[0].NextMenuItem==255)
                tm = 4;
            else
                tm = 1;
                
    }while(cont);

}

void Menu_Heater()
{
    char tm=0;
    bit cont=1;
    // процедурка первой менюшки для лсд
    //while(DispBusy);
    //DispBusy = 1;
    tm=1;
    do{
        PrintMI(3, tm);
        
        //while(Button()!=0);
        // обработка кнопочек - 
        // 1 "ентер"
        // 2 "вверх"
        // 3 "вниз"
        // 4 "назад"
        delay_ms(100); 
        while(Button(1)!=0)
        {
            delay_ms(10);
        }
//        
//                                   {"*HEATER CONTR*",
//                                    "-Stabil t ON -", 
//                                    "-Stabil t OFF-",
//                                    "-Coil control-",
//                                    "-Set t stabil-",255},

        
        switch(Button(0))
        {
            case 1 :    if(tm==1)
                        {
                            //ThermoStabiliser = 1;
                            Menu_StabMethod();
                            tm=1;                            
                        }
                        if(tm==2)
                        {
                            ThermoStabiliser = 0;                            
                        }
                        if(tm==3)
                        {
                            Menu_Coil();
                            tm=1;
                        }
                        if(tm==4)
                        {
                            // установка температуры стабилизации
                        }
                        TPIC();
                        delay_ms(500);
                        break;
            case 2 :    tm-=1;
                        break;
            case 3 :    tm+=1;
                        break;
            case 4 :    cont=0;
                        break;
        }
        if(tm<1)
            tm = 1;
        if(tm>4)
            if(mi[0].NextMenuItem==255)
                tm = 4;
            else
                tm = 1;
                
    }while(cont);

}

void Menu_Light()
{
    char tm=0;
    bit cont=1;
    // процедурка первой менюшки для лсд
    //while(DispBusy);
    //DispBusy = 1;
    tm=1;
    do{
        PrintMI(2, tm);
        
        //while(Button()!=0);
        // обработка кнопочек - 
        // 1 "ентер"
        // 2 "вверх"
        // 3 "вниз"
        // 4 "назад"
        delay_ms(100); 
        while(Button(1)!=0)
        {
            delay_ms(10);
        }
        
//                                    {"*LAMP CONTROL*",
//                                    "-POW lamp ON -", 
//                                    "-POW lamp OFF-",
//                                    "-Desktop  ON -",
//                                    "-Desktop  OFF-",255},
// 

        
        switch(Button(0))
        {
            case 1 :    if(tm==1)
                        {   
                            // включаем мощную лампу
                            L1 = 1;
                        }
                        if(tm==2)
                        {
                            // выключаем мощную лампу
                            L1 = 0;
                        }
                        if(tm==3)
                        {
                            L2 = 1;
                        }
                        if(tm==4)
                        {
                            L2 = 0;
                        }
                        TPIC();
                        delay_ms(500);
                        break;
            case 2 :    tm-=1;
                        break;
            case 3 :    tm+=1;
                        break;
            case 4 :    cont=0;
                        break;
        }
        if(tm<1)
            tm = 1;
        if(tm>4)
            if(mi[0].NextMenuItem==255)
                tm = 4;
            else
                tm = 1;
                
    }while(cont);

}

void Menu_Setting()
{
    char tm=0;
    bit cont=1;
    // процедурка первой менюшки для лсд
    //while(DispBusy);
    //DispBusy = 1;
    tm=1;
    do{
        PrintMI(1, tm);
        
        //while(Button()!=0);
        // обработка кнопочек - 
        // 1 "ентер"
        // 2 "вверх"
        // 3 "вниз"
        // 4 "назад"
        delay_ms(100); 
        while(Button(1)!=0)
        {
            delay_ms(10);
        }
//        
//                                   {"*  SETTINGS  *",
//                                    "-Set  WAIT_DS-", 
//                                    "-Set Thermos -",
//                                    "-Set PrnTemps-",
//                                    "-Set Contrast-",255},

        
        switch(Button(0))
        {
            case 1 :    if(tm==1)
                        {
                            // настройка WAIT_ds
                        }
                        if(tm==2)
                        {
                            // Настройка температуры термостабилизации
                        }
                        if(tm==3)
                        {
                            // Настроить отображение только собственных данных
                        }
                        if(tm==4)
                        {
                            // Настройка значения контрастности
                        }
                        break;
            case 2 :    tm-=1;
                        break;
            case 3 :    tm+=1;
                        break;
            case 4 :    cont=0;
                        break;
        }
        if(tm<1)
            tm = 1;
        if(tm>4)
            if(mi[0].NextMenuItem==255)
                tm = 4;
            else
                tm = 1;
                
    }while(cont);

}
        
void LCD_Menu()
{
    char tm=0;
    bit cont=1;
    // процедурка первой менюшки для лсд
    while(DispBusy);
    DispBusy = 1;
    tm=1;
    do{
        PrintMI(0, tm);
        
        //while(Button()!=0);
        // обработка кнопочек - 
        // 1 "ентер"
        // 2 "вверх"
        // 3 "вниз"
        // 4 "назад" 
        if(Button(1)!=0)
        {
            delay_ms(100);
        }
        
//                                 {{"-=MAIN  MENU=-",
//                                    "-Lamp control-", 
//                                    "- Termo ctrl -",
//                                    "-Charge  ctrl-",
//                                    "-  SETTINGS  -",255},
        
        switch(Button(0))
        {
            case 1 :    if(tm==1)
                        {
                            Menu_Light();
                            tm=1;
                        }
                        if(tm==2)
                        {
                            Menu_Heater();
                            tm = 1;
                        }
                        if(tm==3)
                        {
                            lcd_clear();
                            lcd_gotoxy(0,0);
                            sprintf(a2, "BiGg");
                            lcd_putstrDS(a2);
                            delay_ms(5000);
                            while(!Button(1));
                            //L2 = 1;
                        }
                        if(tm==4)
                        {
                            // менюшка настроек
                            Menu_Setting();
                            tm=1;
                        }
                        break;
            case 2 :    tm-=1;
                        break;
            case 3 :    tm+=1;
                        break;
            case 4 :    cont=0;
                        break;
        }
        if(tm<1)
            tm = 1;
        if(tm>4)
            if(mi[0].NextMenuItem==255)
                tm = 4;
            else
                tm = 1;
                
    }while(cont);
    
    lcd_clear();
    DispBusy = 0;    
}

#pragma optsize-

/*
// External Interrupt 0 service routine для ШИМки - примерно 8 килогерц
interrupt [EXT_INT0] void ext_int0_isr(void)
{
// Place your code here
//delay_us(1);
   BLANK = 1;
   //delay_us(1);
   BLANK = 0;
}

*/

// External Interrupt 2 service routine - отработка тсопа
interrupt [EXT_INT2] void ext_int2_isr(void)
    {
    TCCR0=0x04;
        
    tick = TimerH + TCNT0;
    if(tick==0)
        return;
    
    TimerH  = 0;
    TCNT0   = 0; //обнулили тики
    
    /*
    // типа вывод таймингов
    if(ShowTiming)
    {
        DispBusy = 1;
        lcd_gotoxy(x, y-1);
        sprintf(a2, "%i",tick);
        lcd_putstr(a2);
        x+=21;
        if(x>=84)
        {
            y+=1;
            x=1;
        }
        if(y>6)
        {
            y=1;
            x=1;
            ShowTiming = 0;
        }
        DispBusy = 0;
        
    } 
    */         
        if (tick > st_min && tick < st_max)                                    //если случилось от 139 до 150 тиков
                {
                Cmpl_Rcv = 0;
                start_cond  = 1;                                                //фиксируем стартовое условие
                repeat_cond = 0;                                                //обнуляем флаг повтора
                addr_1 = addr_0 = cmd_1 = cmd_0 = 0;                            //и ранее полученную команду и адрес
                return;
                }
        if (tick > rp_min && tick < rp_max)                                    //если случилось от 116 до 138 тиков
                {
                Cmpl_Rcv = 1;
                repeat_cond = 1;                                                //фиксируем флаг повтора
                start_cond  = 0;                                                //обнуляем флаг стартового условия
                TCNT0       = 0x00;
                TimerH      = 0;
                TCCR0       = 0;
                return;
                }
                
        if(!start_cond)
        {
            return;
            }
            
        if (tick > l_min && tick < l_max && start_cond)                             //если случилось от 22 до 115 тиков
                {
                ++b_cnt;                                                        //приняли "1" и увеличили счетчик битов
                if (b_cnt < 9) addr_1 = (addr_1 << 1) + 1;                      //первый байт - прямой адрес
                if (b_cnt >= 9 && b_cnt < 17) addr_0 = (addr_0 << 1) + 1;       //второй байт - инверсный адрес
                if (b_cnt >= 16 && b_cnt < 25) cmd_1 = (cmd_1 << 1) + 1;        //третий байт - прямая команда
                if (b_cnt >= 24) cmd_0 = (cmd_0 << 1) + 1;                      //четвертый байт - инверсная команда
                }
        if (tick > s_min && tick < s_max && start_cond)                              //если случилось от 10 до 21 тика
                {
                ++b_cnt;                                                        //приняли "0" и увеличили счетчик битов
                if (b_cnt < 9) addr_1 = (addr_1 << 1);                          //далее - аналогично по байтам
                if (b_cnt >= 9 && b_cnt < 17) addr_0 = (addr_0 << 1);
                if (b_cnt >= 16 && b_cnt < 25) cmd_1 = (cmd_1 << 1);
                if (b_cnt >= 24) cmd_0 = (cmd_0 << 1);
                }
        
        if (b_cnt == 32)                                                        //если приняли уже 4 байта
                {
                addr     = 0;
                cmd      = 0;
                Cmpl_Rcv = 1;
                
                if ((addr_1+addr_0) == 0xFF) addr = addr_1;                     //закомментировано, потому как в пульте First
                        else Cmpl_Rcv = 0;                                      //16-bit адрес 0x6120, т.о. проверка адреса не проходит
                if ((cmd_1 + cmd_0) == 0xFF) cmd = cmd_1;                       //проверили правильность приема команды
                        else Cmpl_Rcv = 0;        
                b_cnt = 0;                                                      //обнулили счетчик битов
                start_cond = 0;                                                 //сбросили стартовое условие
                repeat_cond = 0;
                TCCR0=0x00;                                                     //остановили таймер
                TCNT0=0x00;
                TimerH  = 0;
                LastCMD = 0;
               }                                                               
    }

// Timer 0 overflow interrupt service routine  вспомогательная отработка тсопа
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{       
        TCNT0=0x00;     //обнуляем счетчик
        TimerH+=255;    //прибавляем к переменной счета значение
        
        //если буффер приёма КОМ порта переполнен и вывод на экран разрешен - надо срочно его отработать
        //if(rx_buffer_overflow&!DispBusy)
        //    ComInterface();                          

        if(TimerH>=65500)
        {
            //переполнение таймера - сбрасываем значения и останавливаем таймер
            TimerH = 0;
            TCCR0 = 0; 
        }        
}

// Timer 1 output compare A interrupt service routine
interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{
// Place your code here
    //BLANK = 1;
    //BLANK = 0;
    if(++mSec>=60000)
    {
        mSec = 0;
        ++Sec;
    }
    //OCR1BH=0x10;
    OCR1B-=0x3E80;
    //TCNT1 = 0x0000;
    //TCCNT1l = 0x00;
}

// Timer 1 output compare B interrupt service routine
interrupt [TIM1_COMPB] void timer1_compb_isr(void)
{
// Place your code here
    //BLANK = 0;
    BLANK = 1;
    BLANK = 0;
    //if(OCR1BH=0xF0
    OCR1B+=0x1000;
    //TCNT1H=0x00;
    //TCNT1L=0x00;
    //TCNT1 = 0x0000;
    //TCCNT1l = 0x00;
}

// Timer 2 output compare interrupt service routine  моргание лапами
interrupt [TIM2_COMP] void timer2_comp_isr(void)
{
// Place your code here
    TCNT2=0x00; // обнуляем счет таймеру
    //если буффер приёма КОМ порта переполнен и вывод на экран разрешен - надо срочно его отработать
    
    //if(rx_buffer_overflow&!DispBusy)
    //   ComInterface();               
}

// ADC interrupt service routine
// with auto input scanning
interrupt [ADC_INT] void adc_isr(void)
{
    //static unsigned char input_index=0;
    
    // Read the AD conversion result
    //adc_data[input_index]=ADCW;
    
    if (input_index<=3)
    {
        // если индекс входа меньше 4 - это входы 1 2 3 4 канала тока
        // пока просто запишем эти значения - хз как ево конвертировать
    }
    else
    {
        // а иначе это входы напряжения аккумулятора 
        // а напряжение - тупо - опора 2,54 вольта = 1023, 0 вольт = 0;
        Measured_Voltage[input_index-4] = ((unsigned long int)(ADCW*2540))>>10;
        
    }
    
    // Select next ADC input
    if (++input_index > (LAST_ADC_INPUT-FIRST_ADC_INPUT))
       input_index=0;
       
    // запускаем новое преобразование
    ADMUX=(FIRST_ADC_INPUT | (ADC_VREF_TYPE & 0xff))+input_index;
    
    // Delay needed for the stabilization of the ADC input voltage
    delay_us(10);
    
    // Start the AD conversion
    //ADCSRA|=0x40;
    ADCSRA=ADC_STOP;
}

// ПЕРЕМЕННЫЕ И ПРОЦЕДУРКИ ДЛЯ ПИД РЕГУЛЯТОРА   ------------------------------------------------------

// ПИД ядро
char pwm_val = 50; 
/* это начальная величина ШИМ 50%*/

//unsigned int TOFCOUNT; /* declare variables */  

#define CMNDVX 1.5  // требуемое знчение регулируемой величины

float ADRCX;        // текущее значение регулируемой величины
float ADRCXM1;      // предыдущее значение регулируемой величины   

float ERRX;         // текущее значение ошибки

float ERRM1X;       // предыдущее значение ошибки
float ERRM2X;       // пре-предыдущее значение ошибки
float ERRM3X;       // пре-пре-предыдущее значение ошибки 

#define PERDT 0.01  // для 100 вычислений в секунду - период 10 мС.  
float NEWDTY;       // новое вычисленое управляющее воздействие
float OLDDTY;       // предыдущее управляющее воздействие

float KP;
float KI;
float KD;

void PID_Temperature(float Temper)
{
    /* преобразуем результат АЦП к диапазону 1.0 - 2.023 
    поддерживаться регулятором будет значение CMNDVX = 1.5
    */ 
    ADRCX = 1.5/CurrTargTemp*Temper;
    
    if(ADRCX<1)
        ADRCX=1.0;
    if(ADRCX>2.02)
        ADRCX=2.02;    
     
    /* вычислить требуемое управляющее воздействие NEWDTY */         
          
       /* вычисление текущего знчения ошибки */
    ERRX = (CMNDVX - ADRCX); /* calculate current error */

    /* ======  вычисление управляющего воздействия ====== */
    NEWDTY =    OLDDTY                                  // к прошлому значению управл. возд. добавить
              + KP*(ERRX)                               // значение пропорциональное текущей ошибке 
              + KI*PERDT*(CMNDVX - (ADRCX + ADRCXM1)/2)
              + (KD/(6*PERDT))*((ERRX - ERRM3X) 
              + 3*(ERRM1X - ERRM2X));  

    printf("PIDcontrol: KP=&i, KI=&i, KD=&I, ERRX=&i, OLDDTY=&i, NEWDTY=&i, ", KP, KI, KD, ERRX, OLDDTY, NEWDTY);
    //puts(a2);

    if (NEWDTY > 1.99609) /* test for result being in usable */
            {
                NEWDTY = 1.99609; /* limits and set PWM duty cycle if */
            }
    else if (NEWDTY < 1.0) /* beyond saturation */
            {
                NEWDTY = 1.0;
            }

    ADRCXM1 = ADRCX; /* update A/D result for next cycle */


    ERRM3X = ERRM2X; /* update error pipeline */
    ERRM2X = ERRM1X;
    ERRM1X = ERRX;

    OLDDTY = NEWDTY; 
    /* update old duty cycle for next
    calculation period */


    /* Вычисление ШИМ из расчитаного NEWDTY */ 
    pwm_val = ((int)(NEWDTY * 100.0)) - 100;     
    printf("pwm_val=&i, \n\r", pwm_val);
}     

// Ядро исполнительного устройства для пид ядра - Алгоритм беспомехового регулирования брезенхема!

/*
// Асмовая аналога!!!
.def U_in = r17 ; Регистр входного значения
.def D_INT= r18 ; Регистр значения интегратора DA1
.equ I_ur = 100 ; Задаем значение тока уравновешивания I_ur
.equ REF_comp = 125 ; Задаем уровень сравнения компаратора D_comp
.equ DT = PortB ; Задаем порт выполняющий назначение триггера DT 
.equ Q = 0 ; Задаем бит выполняющий назначение выхода Q триггера DT
;************************************************************************************
; С частотой равной или кратной частоте задающего генератора входим в программу 
; дельта-модулятора в момент нулевого сетевого напряжения 
delta :
add D_INT, U_in ; Увеличиваем значение интегратора D_int на величину входного значения 
cpi D_INT , REF_comp ; Имитация компаратора D_comp
brpl DT_1 ; Если больше триггер DT переключим в "1"
DT_0 :
cbi DT , Q ; Установим выход Q триггера DT в "0"
reti ; Выйдем из подпрограммы
DT_1 :
subi D_INT , I_ur ; Подадим ток уравновешивания 
sbi DT, Q ; Установим выход Q триггера DT в "1"
reti ; Выйдем из подпрограммы
*/
unsigned char U_in;           // Задающий вход Сигма-дельта
unsigned char D_INT=0;        // временная переменная интегратора
#define I_ur 100              // значение тока уравновешивания I_ur
#define REF_comp 125          // Задаем уровень сравнения компаратора D_comp
//bit DT;                       // Задаём результат-выход

// по идее эту процедуру надо запускать каждый раз при переходе сети через 0 по прерыванию компаратора
// Но компаратор-то занят ноги не свободные потому работать будем по прерыванию 0 (16 ножка) Low Level
// Analog Comparator interrupt service routine
//interrupt [ANA_COMP] void ana_comp_isr(void)
interrupt [EXT_INT0] void ext_int0_isr(void)
{
// Place your code here
// процедурка сигма-дельта АЦП!
    if(pwm_val<50)
    {
        // одна спираль выключена всегда вторая включается по брезенхему от 0 до 100
        // номера спиралей меняются каждый раз при очередной 1це CurrH инвертируется
        U_in = pwm_val<<1; // Умножаем входной процент на 2
        D_INT+=U_in;       // Увеличиваем значение интегратора D_int на величину входного значения
        if(D_INT>REF_comp) // Имитация компаратора D_comp
        {
                            // Если больше триггер DT переключим в "1"
            D_INT-=I_ur;    // Подадим ток уравновешивания
                            // Установим выход Q триггера DT в "1"
            H1 = CurrH;
            CurrH = !CurrH;
            H2 = CurrH;
        }
        else
        {
                           // Если меньше триггер DT переключим в "0"
           H1 = 0;
           H2 = 0;           
        }
        
    }
    else if(pwm_val>50)
    {
        // одна спираль включена всегда вторая включается по брезенхему от 0 до 100
        // номера спиралей меняются каждый раз при очередной 1це CurrH инвертируется
        U_in = (pwm_val-50)<<1; // Уменьшаем на 50 и умножаем входной процент на 2
        D_INT+=U_in;       // Увеличиваем значение интегратора D_int на величину входного значения
        if(D_INT>REF_comp) // Имитация компаратора D_comp
        {
                            // Если больше триггер DT переключим в "1"
            D_INT-=I_ur;    // Подадим ток уравновешивания
                            // Установим выход Q триггера DT в "1"
            H1 = 1;
            H2 = 1;
        }
        else
        {
                           // Если меньше триггер DT переключим в "0"
            H1 = CurrH;
            CurrH = !CurrH;
            H2 = CurrH;           
        }

    }
    else
    {
        // если ровно 50 - то не бум считать - просто поморгаем грелками по очереди
        H1 = CurrH;
        CurrH = !CurrH;
        H2 = CurrH;
    }

}


//--------------------------------------------------------------------------------------------------------
void PWM()
{
            // тестувый кусок - попробуем манипулировать моей ШИМкой
            //BLANK = 1;
            //BLANK = 0;            
            //temp = mSec%4096;
            /*
            unsigned int PWM_Chg[4]            = {0,0,0,0};       // переменная для задания уровня PWM зарядного канала
            unsigned int PWM_DisChg[4]         = {0,0,0,0};       // переменная для задания уровня PWM разрядного канала
            */
            //PWM_Oth[3] = mSec&0x0FFF;
            
            // присвоение 12-тибитных переменных зарядки каждому каналу
            a2[0] = PWM_Chg[3]>>4;                                  // начало 15-го канала
            a2[1] = ((PWM_Chg[3]&0x0F)<<4)+(PWM_Chg[2]>>8);         // конец 15-го начало 14-го
            a2[2] = PWM_Chg[2];                                     // конец 14-го канала
            
            a2[3] = PWM_Chg[1]>>4;                                  // начало 13-го канала
            a2[4] = ((PWM_Chg[1]&0x0F)<<4)+(PWM_Chg[0]>>8);         // конец 13-го начало 12-го
            a2[5] = PWM_Chg[0];                                     // конец 12-го канала

            // каналы разрядки
            a2[6] = PWM_DisChg[3]>>4;                               // начало 11-го канала
            a2[7] = ((PWM_DisChg[3]&0x0F)<<4)+(PWM_DisChg[2]>>8);   // конец 11-го начало 10-го
            a2[8] = PWM_DisChg[2];                                  // конец 10-го канала
            
            a2[9] = PWM_DisChg[1]>>4;                               // начало  9-го канала
            a2[10] = ((PWM_DisChg[1]&0x0F)<<4)+(PWM_DisChg[0]>>8);  // конец  9-го начало  8-го
            a2[11] = PWM_DisChg[0];                                 // конец  8-го канала

            // растановка остальных каналов PWM
            a2[12] = PWM_Oth[7]>>4;                                 // начало  7-го канала
            a2[13] = ((PWM_Oth[7]&0x0F)<<4)+(PWM_Oth[6]>>8);        // конец  7-го начало  6-го
            a2[14] = PWM_Oth[6];                                    // конец  6-го канала

            a2[15] = PWM_Oth[5]>>4;                                 // начало  5-го канала
            a2[16] = ((PWM_Oth[5]&0x0F)<<4)+(PWM_Oth[4]>>8);        // конец  5-го начало  4-го
            a2[17] = PWM_Oth[4];                                    // конец  4-го канала

            a2[18] = PWM_Oth[3]>>4;                                 // начало  3-го канала
            a2[19] = ((PWM_Oth[3]&0x0F)<<4)+(PWM_Oth[2]>>8);        // конец  3-го начало  2-го
            a2[20] = PWM_Oth[2];                                    // конец  2-го канала
            
            a2[21] = PWM_Oth[1]>>4;                                 // начало  1-го канала
            a2[22] = ((PWM_Oth[1]&0x0F)<<4)+(PWM_Oth[0]>>8);        // конец  1-го начало  0-го
            a2[23] = PWM_Oth[0];                                    // конец  0-го канала

            // отключаем моник 3310
            PORTB.4 = 1;
            SPCR=0x50;
            SPSR=0x01;            
  
            // грузим значения GSCALE
            spi(a2[0]);
            spi(a2[1]);
            spi(a2[2]);
            spi(a2[3]);
            spi(a2[4]);
            spi(a2[5]);
            spi(a2[6]);
            spi(a2[7]);
            spi(a2[8]);
            spi(a2[9]);
            spi(a2[10]);
            spi(a2[11]);
            spi(a2[12]);
            spi(a2[13]);
            spi(a2[14]);
            spi(a2[15]);
            spi(a2[16]);
            spi(a2[17]);
            spi(a2[18]);
            spi(a2[19]);
            spi(a2[20]);
            spi(a2[21]);
            spi(a2[22]);
            spi(a2[23]);

            
            
            //клацаем триггер загрузки на выход
            XLAT = 1;
            delay_us(15);
            XLAT = 0;
            
            // вырубаем двойную скорость
            SPCR=0x50;
            SPSR=0x00;
            
            // врубаем моник
            PORTB.4 = 0;
}

void TPIC()
{
    // ПРОЦЕДУРКА ОБНОВЛЕНИЯ ЗНАЧЕНИЙ В Выходном буффере
    ExtPort = L1 | (L2<<1) | (H1<<2) | (H2<<3) | (1<<4);
    
    /*
    sprintf(a2, " %c %c  %c                ",(char)('z'+2+1&ExtPort), 
                                    (char)('z'+4+1&(ExtPort>>1)), 
                                    (char)('z'+6+3&(ExtPort>>2)));
    */
    if(PrnStatBar)
    {
        lcd_clear_row(5);
        lcd_gotoxy(2, 5);
        //lcd_putstr(a2);
        lcd_putchar(124+!(1&ExtPort));
        lcd_gotoxy(15, 5);
        lcd_putchar(126+!(1&(ExtPort>>1)));
        lcd_gotoxy(30, 5);
        lcd_putchar(128+(3&(ExtPort>>2)));
    }    
    
    //SPCR=0x57;
    //SPSR=0x00;
    // передаем
    PORTB.4 = 1;
    spi(ExtPort);
    PORTC.3 = 1;
    delay_us(1);
    PORTC.3 = 0;
    PORTB.4 = 0;
    //SPCR=0x50;
    //SPSR=0x00;
}
#pragma optsize+

void SecOrdInterrupt_STOP()
{
    //тут тормозим прерывания второстепенного характера
    ADCSRA = ADC_STOP;
    //TCCR1B = TimPWM_Stop;
}

void SecOrdInterrupt_START()
{
    // а тут снова запускаем второстепенные прерывания
    ADCSRA = ADC_START;
    //TCCR1B = TimPWM_Start;   
}

void main(void)
{
    // Declare your local variables here
    n1.En       = 1;
    n1.Sec      = 0;
    n1.mSec     = 0;
    
    n2.Sec      = 0;
    n2.mSec     = 0;
    n2.En       = 0;
    
    //n3.Sec    = 0;
    //n3.mSec   = 0;
    //n3.En     = 1;
    
    n1.Sec      = 0;
    n1.mSec     = 0;
    
    WaitDS      = mem_WaitDS;
    PrnTemps    = Eep_PrnTemp;
    
    CurrTargTemp        = TargTemp;
    CurrTargSensorCRC   = TargSensorCRC;
    
    port();       // настраиваем порты

    PWM();
    // ds1820_init();// инициализируем термометры
    //devices=w1_search(DS18B20_SEARCH_ROM_CMD,rom_codes); // это включать при необх повышенной точности
    lcd_init();   // инициируем нокиевый экран
    lcd_clear();  // чистим его
    lcd_gotoxy(1,3);
    sprintf(a2, "Initialising..");
    lcd_putstr(a2);
    puts(a2);
    putsf("\n\r");
    
    SecOrdInterrupt_STOP();
        
    do{
        devices=w1_search(0xf0,rom_codes);
        lcd_gotoxy(1,5);
        sprintf(a2, "%i DEV(S)DET.",devices);
        
        while(DispBusy);
        
        lcd_putstr(a2);
        lcd_gotoxy(1,6);
        sprintf(a2, "Still search..",devices);
        
        while(DispBusy);
        
        lcd_putstr(a2);
    }while(devices==0);
    
    lcd_clear_row(6); 

    for(i=0;i<devices;i++)
    {     
        if(!ds18b20_init(&rom_codes[i][0],25,35,DS18B20_12BIT_RES))
        {
            lcd_clear();
            lcd_gotoxy(5,0);
            sprintf(a2, "Er.init DS %i", &rom_codes[i][0]);
            lcd_putstr(a2);
            //delay_ms(1000);        
        }          
    }
    lcd_clear();
    while(DispBusy);
    DispBusy = 1;
    sprintf(a2, "N3310 MonitoR");
    lcd_gotoxy(0,0);  
    lcd_putstr(a2);
    puts(a2);
    putsf("\n\r");
    lcd_gotoxy(0,1); 
    sprintf(a2, "LeXX LTD & Co.");
    lcd_putstr(a2);
    puts(a2);
    putsf("\n\r");
    printf("DS`s devices find = %i\n\r", devices);
    DispBusy = 0;
    
    TCCR2 = 0x04;
    
    TPIC();
    
    SecOrdInterrupt_START();

    //LCD_Menu();
    
    while (1)
    {         
        if(n1.En==1)
        {
            // Пришло время запустить первое преобразование и задать время вывода
            //unsigned long int mins = (unsigned int)WaitDS*10;
            n1.En = 0;
            n2.En = 1;
            n2.Sec  = Sec;
            //mins+= mSec;
            n2.mSec = mSec;
            n2.mSec += (unsigned int)WaitDS*10;
            while(n2.mSec>=60000)
            {
                n2.mSec = n2.mSec - 60000;
                n2.Sec+=1;
            }
            //n2.mSec = mins;
            //printf("n2.Sec = %i, n2.mSec = %i", n2.Sec, n2.mSec);
            // теперь собственно сама обработка
            SecOrdInterrupt_STOP();
            w1_init();
            w1_write(0b11001100); // SkipRom
            w1_write(0b01000100); // Convert T
            SecOrdInterrupt_START();
                              
            if((++GraphicTimeout >= MaxGraphTimeout)&&(PrnTemps==0))
            {
                lcd_clear();
                PrnTemps=1;   
            }   
                     
            // теперь сильная подтяжка
            PORTB|=0b00100000;
            DDRB|=0b00100000;
            ComStateOn();
            
            PWM();                                              
        }
                  
        if(n2.En==1)
        if((n2.Sec<=Sec)&(n2.mSec<=mSec))
        {
          // Пришло время запустить первое преобразование и задать время вывода
          n1.En = 1;
          n2.En = 0;
          n1.Sec  = Sec;
          n1.mSec = mSec;
          //printf("n1Sec = %i, n1mSec = %i", n1Sec, n1mSec);
          // теперь собственно сама обработка
          ComStateOff();
          for (i=0;i<devices;i++)
          {
              /*
              if (PrnTemps==1)
              {
                  while(DispBusy);
                  DispBusy = 1;
                  lcd_gotoxy(75,2+i);
                  sprintf(a2, "<");
                  lcd_putstr(a2);
                  DispBusy = 0;
              }
              */
              SecOrdInterrupt_STOP();                
              ds18b20_read_spd(&rom_codes[i][0]);
              SecOrdInterrupt_START();
                                      
              // копируем полученные результаты в нашу струткуру ds_scratch_pad (адрес 0269)
              for(temp = 0;temp<=8;temp++)
              {
                    pokeb(temp+0x0269, peekb(temp+0x0260));
              }              
                                      
              if(ExtRep)
              {
                  // кидаем строчки в com порт 
                  puts(&rom_codes[i][0]);
                  puts(&rom_codes[i][1]);
                  puts(&rom_codes[i][2]);
                  puts(&rom_codes[i][3]);
                  puts(&rom_codes[i][4]);
                  puts(&rom_codes[i][5]);
                  puts(&rom_codes[i][6]);
                  puts(&rom_codes[i][7]);
                  puts(&rom_codes[i][8]);
                  putsf("\n\r");
                                                            
                  printf("temp_lsb = %i \n\r" ,ds_scratch_pad.temp_lsb); 
                  //puts(a2);
                  printf("temp_msb = %i \n\r" ,ds_scratch_pad.temp_msb); 
                  //puts(a2);
                  printf("temp_high = %i \n\r" ,ds_scratch_pad.temp_high); 
                  //puts(a2);
                  printf("temp_low = %i \n\r" ,ds_scratch_pad.temp_low); 
                  //puts(a2);
                  printf("conf_register = %i \n\r" ,ds_scratch_pad.conf_register); 
                  //puts(a2);
                  printf("res1 = %i \n\r" ,ds_scratch_pad.res1); 
                  //puts(a2);
                  printf("res2 = %i \n\r" ,ds_scratch_pad.res2); 
                  //puts(a2);
                  printf("res3 = %i \n\r" ,ds_scratch_pad.res3); 
                  //puts(a2);
                  printf("crc = %i \n\r" ,ds_scratch_pad.crc); 
                  //puts(a2);
              }
                                      
              // сравниваем CRC и если не совпадает - результат - лажа
              if(w1_dow_crc8(&ds_scratch_pad, 8)==ds_scratch_pad.crc)
              {
                                          
                  temp = *(signed int*)&ds_scratch_pad.temp_lsb;
                  ds_temp = temp/16.0;
                  if(ds_temp>256)
                    ds_temp-=4096;                                      
                                        
                  // выводим на экранчик
                  if(PrnTemps==1)
                  {
                      while(DispBusy);
                      DispBusy = 1;
                      sprintf(a2, "t%u=%+.4f\xf8C\n\r",i+1, ds_temp);
                      //TCCR2=0x00;                                                               
                      lcd_clear_row(1+i);
                      lcd_gotoxy(1,1+i);
                      lcd_putstr(a2); // выводим на экранчик
                      //TCCR2=0x04;
                      DispBusy = 0;
                  }
                                          
                  // строчка для com порта
                  printf("t%u(%u)= %f \n\r",i+1, rom_codes[i], ds_temp); 
                  //puts(a2);
                  
                  // регулятор температур
                  /*
                  sprintf(a2, "%u",rom_codes[i][7]);                                      
                  //lcd_clear_row(4);
                  lcd_gotoxy(0+(i*23),4);
                  lcd_putstr(a2);
                  */
                  
                  // ThermoStabiliser - режим термостабилизации
                  // 1 - релейный
                  // 2 - PID
                  // 3 - пропорциональный
                  if(ThermoStabiliser==1)
                  {
                      if(rom_codes[i][7] == 92)
                      {
                        if(CurrTargTemp>ds_temp)
                        {
                            ds_temp = CurrTargTemp-ds_temp;
                            //printf("%i-%f=%i\n\r",CurrTargTemp, ds_temp, a2);
                            //putsf("\n\r"); 
                            if((ds_temp>0)&&(ds_temp<=0.5))
                            {
                                H1 = CurrH;
                                CurrH=!CurrH;
                                H2 = CurrH;
                                TPIC();
                            }
                            else if(ds_temp>0.5)
                            {
                                if((H1!=1)||(H2!=1))
                                {
                                    H1 = 1;
                                    H2 = 1;
                                    TPIC();
                                }
                            }
                            
                        }
                        else
                            {
                                if(H1||H2)
                                {
                                    H1 = 0;
                                    H2 = 0;
                                    TPIC();
                                }
                            }
                      }
                  }                                         
              }
              else
              {
                  if (PrnTemps == 1)
                  {
                      while(DispBusy);
                      DispBusy = 1;
                      sprintf(a2, "t%u= ERROR !\n\r",i+1, ds_temp);                                                               
                      lcd_clear_row(1+i);
                      lcd_gotoxy(1,1+i);
                      lcd_putstr(a2); // выводим на экранчик
                      DispBusy = 0;
                  }
                                          
                  // строчка для com порта
                  printf("t%u(%i)= ERROR \n\r",i+1, rom_codes[i], ds_temp);
                  
                  
                  } 
              }
              
              /*                        
              if(PrnTemps == 1)
              {
                  while(DispBusy);
                  DispBusy = 1;
                  lcd_gotoxy(75,2+i);
                  sprintf(a2, "-");
                  lcd_putstr(a2);
                  DispBusy = 0;
              }
              */ 
          
          // выводим на экранчик локальное время и состояния выходов
          if (PrnTemps == 1)
          {
              while(DispBusy);
              DispBusy = 1;
              sprintf(a2, "[%+5u][%+5u]",Sec, mSec);                                      
              lcd_clear_row(0);
              lcd_gotoxy(1,0);
              lcd_putstr(a2); // выводим на экранчик
              DispBusy = 0;
          }          
        }
             
        if(Cmpl_Rcv)
        {
            // есть чтото принятое с ТСОПа - посмотрим что это
            if(repeat_cond)
                printf("addr=%u(%u/%u).cmd=%u(%u/%u)_REPEAT_\n\r" , addr, addr_1, addr_0, cmd, cmd_1, cmd_0);
            else
                printf("addr=%u(%u/%u).cmd=%u(%u/%u)\n\r" , addr, addr_1, addr_0, cmd, cmd_1, cmd_0);            
                            
            //Если Поседняя команда была 1 или адрес 0 и команда 128 - клацнули @Timer@ на пульте нагревателя
                            
            //if((LastCMD==1)|((cmd_1==128)&(addr_1==0)))  // с моргалкой(когда держишь)
            if((repeat_cond==0)&(cmd==128)&(addr==0))                   // без моргалки - для лампочек критично
            {
                // переключим лампочку 1
                LAMP1 = !LAMP1;
                LastCMD = 1;
                }

            //Если Последняя команда была 2 или адрес 0 и команда 0 - клацнули @SWING@ на пульте нагревателя
            if((repeat_cond==0)&(cmd==0)&(addr==0))
            {
                // переключим лампочку 2
                LAMP2 = !LAMP2;
                LastCMD = 2;
                }   
             
            if((repeat_cond==0)&(cmd==48)&(addr==0))
            {
                // красная кнопочка
                Cmpl_Rcv = 0;
                putsf("MAIN MENU \n\r");
                if(rx_counter)
                    ComInterface();
                delay_ms(100);
                LCD_Menu();
                putsf("MENU CLOSED\n\r");
            }
                           
            Cmpl_Rcv = 0;
            TPIC();
            
   
            
        }                            
      if(!b4)
        LCD_Menu();    
        
      ComInterface();
      PWM();

    };
}
