/* 		AVR studio 4.18 Build 684
		Nixie Tube Clock MINI For IW-9
		Программа для ламп ИВ-9.

Created by: Daemon Fox
Date: 27.06.2020
Date: 05.07.2021
HW: v2.0 by 05.2020 mod 05.07.21
SW: v1.2 by 05.07.21

SW: v1.0 by 27.06.2020 
SW: v1.1 by 13.09.2020


Fuses:
H-Fuse 1101 1001
L-Fuse 1110 0100

0 - unprogram
1 - program

Внутренний RC резонатор - 8MHz

*/



#include <avr/io.h> //библиотека ввода/вывода
#include <util/delay.h> //библиотека задержки (паузы)
#include <avr/interrupt.h> //библиотека прерываний
#include "i2c.h"		// Библиотека для работы с i2c "" - пользовательские <> - системные. 
//изменить строчку #define I2C_DELAY	_delay_us(1);	 // по умолчанию задержки 10 микросекунд

#define b0 	0
#define b1	1
#define b2  2
#define b3  3
#define b4  4
#define b5  5
#define b6	6
#define b7	7

#define READ_DS32	0xD1	//Адрес для чтения DS3231
#define WRITE_DS32	0xD0	//Адрес для записи DS3231

//#define StopT0	TIMSK &= ~(1 << TOIE0); //макрос для старта таймера
//#define StartT0	TIMSK |= (1 << TOIE0);	//макрос стоп таймера


// Переменные: 



//volatile uint8_t	test = 0x00;// Тестовые переменные.
//volatile uint8_t	test_v = 1;
//volatile uint8_t	test_i = 1;
//volatile uint8_t	test_t2 = 0x00; // тест таймера 2

volatile uint8_t ADC_DATA = 0; // Данные преобразованные из АЦП.
volatile uint8_t ADC_DATA_t = 0; // Временные данные для ADC.
//volatile uint8_t ADC_DATA_us = 10;// Для задержки измерений в ХХмсек.
//volatile uint8_t ADC_DATA_us_t;// Для задержки измерений в ХХмсек.

volatile uint8_t OCR0_t = 5;  // 0-255 Значение ШИМ для высоковольтного генератора 180v. | min = 50 ; max = 200 | 127 = 50%.

volatile uint8_t d_1ms = 0x00;  // Переменная 0-31 для отсчёта 1мсек. 1/31250 = 0.000032сек * 32 = 0,001024сек.
volatile uint8_t d_15ms = 0x00;
volatile uint8_t dp_on = 0x00;  // Переменная для включения точки. 1 - точка на 1й лампе, 2 - точка на 2й лампе, 3 - точка на 3й лампе, 4 - точка на 4й лампе. 
//volatile uint8_t d_300us = 0x00;  // Переменная 0-9 для отсчёта 0.3мсек. 1/31250 = 0.000032сек * 10 = 0,00032сек.
volatile uint8_t c_25ms = 0x00; // Переменная 0-25 для отсчёта 25мсек.
volatile uint8_t c_25ms_t = 0x00; // Переменная 5*25 для отсчёта 125мсек. Для быстрого листания цифр при постоянно нажатой клавише.
volatile uint8_t p_125ms = 0x00;
//volatile int i = 0x00;

volatile uint8_t	H10 = 0x01;		// Регистр десяток часов.
volatile uint8_t	H01 = 0x02;		// Регистр единиц минут.
volatile uint8_t	M10 = 0x00;		// Регистр десяток часов.
volatile uint8_t	M01 = 0x00;		// Регистр единиц минут.
volatile uint8_t	H10_t = 0x01;	// Регистр десяток часов. Хранение переменной.
volatile uint8_t	H01_t = 0x02;	// Регистр единиц минут. Хранение переменной.
volatile uint8_t	M10_t = 0x00;	// Регистр десяток часов. Хранение переменной.
volatile uint8_t	M01_t = 0x00;	// Регистр единиц минут. Хранение переменной.
volatile uint8_t	S01 = 0x00;	 	// Регистр секунды и будильника.
volatile uint8_t	M01_c = 0x00; 	// Цикл 40 проходов для защиты индикатора от ... (длительное горение одного сегмента, выгорание сегмента)
volatile uint8_t	M01_c_t = 0x00; 	// Задержка в 15 мсек для цикла защиты.



volatile uint8_t 	keys = 0x00; 	// Регистр клавиш: 
// 0 - отображение часов; 1 - настройка H10; 2 - настройка H01; 3 - настройка M10; 4 - настройка M01; 5 - настройка NE; 6 - сохранить; 7 - OCR min; 8 - OCR max;
volatile uint8_t 	sec = 0x00;		// Регистр отсчёта секунд. 0 - Отсчёт остановлен. 40*25us = 1000us; 120*25us = 3000us; 200*25 = 5000us.

volatile uint8_t 	keys_stop = 0x00; // Ожидание когда отпустят кнопку при входе в сервисное меню, для дальнейшего изменения параметра.



volatile uint8_t 	H = 0; // Байт часов. Упакованный BCD Формат.
volatile uint8_t 	M = 0; // Байт минут. Упакованный BCD Формат.
volatile uint8_t 	S = 40; // Байт секунд. Вспомогательная переменная. = 40, т.к. 40*25мс == 1сек
volatile uint8_t 	S_t = 0x00; // Байт секунд. 0xFF - секундная лампа горит, 0x00 секундная лампа выключена.


volatile uint8_t 	DG1 = 0x0F; // Регистр индикатора № 1.
volatile uint8_t 	DG2 = 0x0F; // Регистр индикатора № 2.
volatile uint8_t 	DG3 = 0x0F; // Регистр индикатора № 3.
volatile uint8_t 	DG4 = 0x0F; // Регистр индикатора № 4.

//volatile uint8_t U04 = 0x00;// Регистры микросхем сдвиговых регистров 74hc595
//volatile uint8_t U05 = 0x00;
//volatile uint8_t U06 = 0x00;
//volatile uint8_t U07 = 0x00;
//volatile uint8_t U08 = 0x00;
//volatile uint8_t U09 = 0x00;
//volatile uint8_t U10 = 0x00;
//volatile uint8_t U11 = 0x00;

//volatile uint8_t flag_INT = 0xFF; // Флаг прерываний INT1 INT0 от дребезга контактов. b1 = INT1, b0 = INT0. 1 - изменение разрешено.

volatile uint8_t service_menu_c = 84; // Счётчик входа в сервисное меню. с = 0 вход в меню. 5000мс / 30мс = 166 циклов.
volatile uint8_t service_menu_c_t = 84; //  service_menu_c_t = service_menu_c;
volatile uint8_t service_menu_i = 0;// Пункт сервисного меню. 0 - АЦП, 1 - ШИМ HV (OCR0_t). 2 - 12:00. 12 - выход.
volatile uint8_t menu_i = 0x00; // Пункт обычного меню. 0 - выход, 1 - настройка звуков, 2 - настройка будильника, 3 - настройка часов, 4 - настройка подсветки.
volatile uint8_t menu_s = 0; // меню селект: 0 - ничего не выбрано, 1 - настройка часов, 2 - настройка минут.
volatile uint8_t d_i = 1; // Текущий индикатор 1 - DG1, 2 - DG2, 3 - DG3, 4 - DG4, 5 - секундная NE. 

//volatile uint8_t ii = 0; 

//volatile uint8_t d_i_t = 0; 


// Функции:



void Read_DS();  // Чтение часов и минут из DS3231 с конвертацией их в H10 H01 M10 M01.
void Write_DS(); // Запись часов и минут в DS3231 с конвертацией их в H10 H01 M10 M01.
void DS3231_ini(); // Настройка часов.
void ADC_read(); // Функция преобразования АЦП.


//bin2bcd(); !!!
// В стандартном avr-gcc нет 24-хбитных типов, что вызывает у меня печальку.
volatile uint8_t bin2bcd0001 = 0x00;// Регистры вывода функции двоично десятичного преобразования.
volatile uint8_t bin2bcd0010 = 0x00;
volatile uint8_t bin2bcd0100 = 0x00;
//void BIN2BCD3shift(volatile uint8_t digHEX); // Двоично-десятичное преобразование.

void DIG(volatile uint8_t d); // Функция индикации.

// Функции инициализации:



void Timer_ini(){ // Инициализация таймера_0. 32-35кГц.	
//  TCNT0 - счетный регистр , OCR0 - регистр сравнения , TCCR0 - конфигурационный регистр. 
	OCR0 = OCR0_t; //Скважность импульсов. 
	TCNT0 = 0x00; //Регистр сравнения. TCNT0 - Регистр счётчика. сброс счётного регистра. Изменять только при остановленном таймере.

	// WGM01 WGM00 Режимы:
	//   0     0    Normal
	//   0     1    PWM, Phase Correct
	//   1     0    CTC
	//   1     1    Fast PWM
	TCCR0 |= (1<<WGM01)|(1<<WGM00);  // Режим таймера FastPWM.
	TIMSK |= (1<<OCIE0)|(1<<TOIE0);  // Разрешить прерывание по совпадению и по переполнению.

	// CS02 CS01 CS00  Пуск таймера + предделитель:
    //   0    0    0   No clock source (Timer/Counter stopped).
	//   0    0    1   clk (No prescaling).
    //   0    1    0   clk/8 (From prescaler).
	//   0    1    1   clk/64 (From prescaler).
	//   1    0    0   clk/256 (From prescaler).
	//   1    0    1   clk/1024 (From prescaler).
	TCCR0 |= (1<<CS00);//Частота 31,25кГц. (clk/N*256) 8000'000Гц/1*256 = 31250 Гц. N = 1, CS02 - CS00 = 001.
//  TCCR2 |= (1<<CS20);  // || (1<<CS21); Частота 31,25кГц. (clk/N*256) 8000'000Гц/2048 = 3 906,25Гц. N = 8, CS02 - CS00 = 010.
} 

void ADC_ini(){ // Инициализация АЦП.
//	ADMUX |= (1<<REFS1)|(1<<REFS0)|(1<<ADLAR); // REFS1 - REFS0 = 11, ИОН = внутр на 2.56в | ADLAR = 1, левое выравнивание.
//	ADMUX &= ~((1<<MUX4)|(1<<MUX3)|(1<<MUX2)|(1<<MUX1)|(1<<MUX0)); // АЦП = PA5 00101
	ADMUX = 0xE5;  // PA5, ИОН = внутр на 2.56в, левое выравнивание.
	// N = 64; 8'000'000 / 64 = 125'000. 1 / 125'000 = 0,000'008 такт, преобразование в среднем 13-25 тактов, 
	// преобразование примерно займёт 0,0002сек, с запасом возьмём 0,0003 сек, для АЦП доступно 37тактов.
	ADCSRA |= (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1); //|(1<<ADPS0) ADEN - разрешить АЦП | ADIE - разрешить прерывание | ADPS2-0 - делитель частоты на N
	//  Частота работы АЦП не больше 200 кГц, иначе теряем точность. Fclk / N.
	//N =  ADPS2-0; 2 = 000, 4 = 010,8 = 011, 16 = 100,32 = 101, 64 = 110, 128 = 111.
}



// Прерывания:



//PB0 - I/O. IRF740_PNP Step-Up HV. default = 1; 0 = вкл.
//PB1 - I/O. IRF740_NPN Step-Up HV. default = 1; 1 = вкл.

ISR (TIMER0_COMP_vect){ // Прерывание: совпадение счётчика и OCR0.
//	PORTB |= (1<<PB0); // PB0 = 1, PNP - OFF
//	PORTB |= (1<<PB1); // PB1 = 1, NPN - ON

//	PORTB ^= (1<<PB0); // PB0 = инверсия, PNP - OFF
//	PORTB ^= (1<<PB1); // PB1 = инверсия, NPN - ON
} 
ISR (TIMER0_OVF_vect){ // Прерывание: переполнение счётчика.
	OCR0 = OCR0_t;
//	PORTB &= ~(1<<PB0); // PB0 = 0, PNP - ON
//	PORTB &= ~(1<<PB1); // PB1 = 0, NPN - OFF
	d_1ms++;
//	d_300us++;
} 



int main (void){



// Инициализация портов:
	// = 0x00; Настройка порта как вход.
	// = 0xFF; Настройка порта как выход.

	DDRA = 0xFF;  // Настройка порта как выход.
	DDRA &= ~(1<<PA5); // PA5 вход, АЦП.
	DDRB = 0xFF;  // Настройка порта как выход.
	DDRB &= ~((1<<PB1)|(1<<PB0));// PD2 = 0, PD3 = 0,  как вход.
	DDRC = 0xFF;  // Настройка порта как выход.
	DDRD = 0xFF;  // Настройка порта как выход.
	DDRD &= ~((1<<PD2)|(1<<PD3));// PD2 = 0, PD3 = 0,  как вход.

	PORTA = 0x00;
	PORTB = 0b00000000;//0b00000011
	PORTC = 0b00000011;
	PORTD = 0b00001100;

	H10 = 1;
	H01 = 2;
	M10 = 0;
	M01 = 0;
	
	//S01 |= (1<<b1);

	Timer_ini(); // Инициализация таймера 0.
	//Timer2_ini(); // Инициализация таймера 2.


	i2c_init (); // Инициализация шины I2C.
	DS3231_ini();
//	ADC_ini(); // Инициализация АЦП.

	sei();  // Разрешить прерывания.

//	sei(); //глобальное разрешение прерываний 
 //cli; Запретить прерывания


/*

PORTA - Выход.

PA0 - I/O. Анодное питание NE1. default = 0; 1 = вкл.
PA1 - I/O. Анодное питание V4.  default = 0; 1 = вкл.
PA2 - I/O. Анодное питание V3.  default = 0; 1 = вкл.
PA3 - I/O. Анодное питание V2.  default = 0; 1 = вкл.
PA4 - I/O. Анодное питание V1 . default = 0; 1 = вкл.
PA5 -  ADC. Стабилизация напряжения 10.8в.
PA6 - NC.
PA7 - NC.

PORTB - Выход.

PB0 - I/O. IRF740_PNP Step-Up HV. default = 1; 0 = вкл.
PB1 - I/O. IRF740_NPN Step-Up HV. default = 1; 1 = вкл.
PB2 - NC.
PB3 - NC.
PB4 - NC.
PB5 - MOSI. ASP Программатор.
PB6 - MISO. ASP Программатор.
PB7 - SCK. ASP Программатор.

PORTC - Выход.

PC0 - SCL. DS3231.
PC1 - SDA. DS3231.
PC2 - I/O. Катод ламп "9"(HV GND). default = 0; 1 = вкл.
PC3 - I/O. Катод ламп "0"(HV GND). default = 0; 1 = вкл.
PC4 - I/O. Катод ламп "1"(HV GND). default = 0; 1 = вкл.
PC5 - I/O. Катод ламп "2"(HV GND). default = 0; 1 = вкл.
PC6 - I/O. Катод ламп "3"(HV GND). default = 0; 1 = вкл.
PC7 - I/O. Катод ламп "4"(HV GND). default = 0; 1 = вкл.

PORTD - Выход, PD2-3 Вход.

PD0 - NC. 
PD1 - NC.
PD2 - INT. Кнопка "SEL". Внутр. резистр 50К. default = 1; 0 = кн. нажата.
PD3 - INT. Кнопка "UP". Внутр. резистр 50К. default = 1; 0 = кн. нажата.
PD4 - I/O. Катод ламп "5"(HV GND). default = 0; 1 = вкл.
PD5 - I/O. Катод ламп "6"(HV GND). default = 0; 1 = вкл.
PD6 - I/O. Катод ламп "7"(HV GND). default = 0; 1 = вкл.
PD7 - I/O. Катод ламп "8"(HV GND). default = 0; 1 = вкл.


*/

// Программа:
Read_DS();	// Единожды в начале + каждую секунду по прерыванию.
H10_t = H10;
H01_t = H01;
M10_t = M10;
M01_t = M01;
//S_t = S;


// <--- Вход в сервисное меню:
if (!(PIND&(1<<PD2))){	// key1 "SEL" = 0; Кнопка нажата. "-".
	// Нажата кнопка "-"
	keys = 8;// OCR_t max
	keys_stop = 0xFF;
}else{
	if (!(PIND&(1<<PD3))){	// key2 "UP" = 0; Кнопка нажата. "+".
		// Нажата кнопка "+"
		keys = 7;// OCR_t min
		keys_stop = 0xFF;
	}else{
		if (M01_t == 0){ // При включении пролистать цифры("обновить экран"). 
			M01_t = 9;
		}else{ 
			M01_t--; 
		}
	}
}
// ---> Конец. Вход в сервисное меню. 





while(1){

/*
// <--- Стабилизация напряжения.
	if(d_300us > 10){
// 	Каждые 0,0003сек запускать преобразование АЦП:
		ADC_read();// Стабилизация 10,8 вольт.
		if (ADC_DATA < 105){
			//if(OCR0_t < 250){
			//	OCR0_t = OCR0_t + 1;
			//}
		}
		if (ADC_DATA > 107){ // Петля гистерезиса для плавности изменений напряжения. 
			//if(OCR0_t > 50){
			//	OCR0_t = OCR0_t - 1;
		//	}
		
		}
	PORTA ^= (1<<PA0); // PA0 = инверсия,
	d_300us = 0;
	}
// --->Конец. "Стабилизация напряжения".
*/

//	_delay_ms(1);
	if(d_1ms > 31){ // 0-31 = 32; 0.000032сек *32 = задержка в 0,001024сек.

// <--- "Каждую минуту". 

if(d_15ms == 0){
if ((M01_c == 0)){// Если цикл остановлен
	if (!(M01 == M01_t)&&(keys == 0)){// и минута сменилась - Запуск цикла.
		M01_c = 40;// Запуск цикла
		M01_t = M01;// Восстановление значения минуты.
	}
}else{
	// Цикл 40.
	if(M01_c_t == 0){
		M01_c_t = 75;
		M01_c--;
		
		if (H10 < 9){
			H10++;
		}else{ H10 = 0; }

		if(M01_c > 9){
			if (H01 < 9){
				H01++;
			}else{ H01 = 0; }
		}
		if(M01_c > 19){
			if (M10 < 9){
				M10++;
			}else{ M10 = 0; }
		}
		if(M01_c > 29){
			if (M01 < 9){
				M01++;
			}else{ M01 = 0; }
		}
//	_delay_ms(15);
	}else{M01_c_t--;}
}

d_15ms = 2;
}

// ---> Конец. "Каждую минуту".

// <--- "Каждую секунду":
	if(S == 0){
		//S_t = ~S_t; зажигать или тушить секундную лампу, неиспользовать, т.к. скачет напряжение и меняют яркость другие лампы...
		if((M01_c == 0)&&(keys == 0)){ // Если цикл остановлен. 
			i2c_init (); // Инициализация шины I2C.
			Read_DS();	// Единожды в начале + каждую секунду.
/*
			if(H10 < 9){
				H10++;
			}else{
				H10 = 0;
			}
*/
		}
		//if(ii == 9){
		//	ii=0;
		//}else{
	//		ii++;
		//}
		
		//PORTA |= (1<<PA4); 	
	//	DIG(3);
	// сверка часов и минут.
		S = 40;//Сброс счета мсек.
	}
// ---> Конец. "Каждую секунду".

// <--- "Опрос кнопок":			

//7 - nc; 6 - Энкодер2 (0 = "--", 1 = "++"); 5 - Энкодер2 (1 = ON); 4 - Энкодер1 (0 = "--", 1 = "++"); 3 - Энкодер1 (1 = ON);  2 - кнопка2 (1 = ON); 1 - кнопка1 (1 = ON); 0 - nc.

	if ((p_125ms == 0)&&(M01_c == 0)){ // Если не включена пауза 125мсек и нет перебора (защита от выгорания),		
		if(keys_stop == 0){//если кнопки не заблокированы, опрашиваем кнопки:
				
			// KEY SEL / "-" || 0 - NC, 1 - DG1, 2 - DG2, 3 - DG3, 4 - DG4, 5 - NE, 6 - save, 7-8 - сервисное меню.
			if (!(PIND&(1<<PD2))){	// key1 "SEL" = 0; Кнопка нажата. "-".
				keys_stop = 0xFF;
				p_125ms = 200;//125	

				switch (keys){
					case 0: keys++;
							break;
					case 1:	keys++;
							break;
					case 2:	keys++;
							//if(H10 == 2){
							//	if(H01 > 3){H01 = 0;}
						//	}
							break;
					case 3:	keys++;
							break;
				//	case 4:	keys++;
				//			break;
					case 4:	keys = 0; //	case 5:
							i2c_init (); // Инициализация шины I2C.
							Write_DS();// сохранить время.
							if (M01_t == 0){ // Пролистать цифры("Защита от выгорания"). 
								M01_t = 9;
							}else{ 
								M01_t--; 
							}
							break;
					case 6:	
							break;

				}	

			}// Конец KEY SEL / "-".


			// KEY UP / "+"
			if (!(PIND&(1<<PD3))){	// key2 "UP" = 0; Кнопка нажата. "+".
				p_125ms = 255;//200 125
				switch (keys){
					case 0: // NOP
							//OCR0_t = OCR0_t + 1; //OCR0_t = OCR0_t - 1;
							break;
					case 1:	if(H10 == 2){
								H10 = 0;					
							}else{
								H10++;
							}
							break;
					case 2:	if(H10 == 2){
								if(H01 > 2){
									H01 = 0;
								}else{
									H01++;
								}				
							}else{
								if(H01 == 9){
									H01 = 0;
								}else{
									H01++;
								}
							}
							break;
					case 3:	if(M10 == 5){
								M10 = 0;					
							}else{
								M10++;
							}
							break;
					case 4:	if(M01 == 9){
								M01 = 0;					
							}else{
								M01++;
							}

							break;
					case 5:	keys = 6;//S_t = ~S_t; //Зажечь / Потушить секундную лампу.
										//Сохранить в EEPROM.
							break;
					case 6:	// NOP
							break;

				}

			}// Конец KEY UP / "+".
				

				
		}else{
			if ((PIND&(1<<PD2))&&(PIND&(1<<PD3))){// KEY UP & KEY SEL Отпущены.
				keys_stop = 0x00;
			}
			p_125ms = 125;
			
		}
	}else{
		p_125ms--; // !!~! А что если пауза == 0 но сейчас идет перебор(защита от выгорания), кнопки заблокируются до тех пор пока не отсчитает 255?
	}
// ---> Конец. "Опрос кнопок". 

// <--- "Отображение и меню".
/*	switch (menu_i){
		case 0: DG1 = H10;// Отображение времени.
				DG2 = H01;
				DG3 = M10;
				DG4 = M01;
				break;
		case 1: ; // Защита индакаторов от выгорания.
				BIN2BCD3shift(OCR0_t);	//ADC_DATA Отображение АЦП. Высокое напряжение.	
				DG1 = 3;
				DG2 = bin2bcd0100;
				DG3 = bin2bcd0010;
				DG4 = bin2bcd0001;
			break;
		case 3: DG1 = 1;// Отображение времени.
				DG2 = 2;
				DG3 = 3;
				DG4 = 5;
				break;
	}
*/
// ---> Конец. "Отображение и меню".

// <--- "Задержка 1 мсек".
  
	//if (d_i_t == 0){
		//d_i = 1;
		switch (d_i){
			case 1:	//PORTA &= ~((1<<PA1)|(1<<PA0));
					PORTA &= ~((1<<PA4)|(1<<PA3)|(1<<PA2)|(1<<PA1)|(1<<PA0));
					PORTA |= (1<<PA4); 	
					DIG(H10);
					if(keys == d_i){
						PORTC |= (1<<PC7);
					}
					d_i = 2;
					break;

			case 2:	PORTA &= ~(1<<PA4);
					PORTA |= (1<<PA3); 	
					DIG(H01);
					if(keys == d_i){
						PORTC |= (1<<PC7);
					}
					d_i = 3; 
					break;
			case 3:	PORTA &= ~(1<<PA3);
					PORTA |= (1<<PA2); 	
					DIG(M10);
					if(keys == d_i){
						PORTC |= (1<<PC7);
					}
					d_i = 4;
					break;
			case 4:	PORTA &= ~(1<<PA2);
					PORTA |= (1<<PA1); 	
					DIG(M01);
					if(keys == d_i){
						PORTC |= (1<<PC7);
					}
					d_i = 1;
				/*	if(S_t){
						d_i = 5;	
					}else{
						d_i = 1;
						 switch (keys){ 
							case 0:	d_i = 1;				
									break;
							case 1:	d_i = 11;				
									break;
							case 2:	d_i = 12;				
									break;
							case 3:	d_i = 13;				
									break;
							case 4:	d_i = 14;				
									break;
							case 5:	d_i = 15;				
									break;
							default: d_i = 1;
									break;
						 } 
					}*/
					break;
			case 5:	PORTA &= ~(1<<PA1);
					PORTA |= (1<<PA0);
					DIG(8);
						/* switch (keys){ 
							case 0:	d_i = 1;				
									break;
							case 1:	d_i = 11;				
									break;
							case 2:	d_i = 12;				
									break;
							case 3:	d_i = 13;				
									break;
							case 4:	d_i = 14;				
									break;
							case 5:	d_i = 15;				
									break;
							default: d_i = 1;
									break;
						 } */
					d_i = 1;
					break;
			case 6: //Динамическое отображение отключено, светится только одна лампа. 
					OCR0_t = 190;// ШИМ при статической индикации одной лампы.
					break;
			case 11: PORTA &= ~((1<<PA1)|(1<<PA0));
					PORTA |= (1<<PA4); 	
					DIG(H10);
					 d_i = 1;
					break;
			case 12: PORTA &= ~((1<<PA1)|(1<<PA0));
					PORTA |= (1<<PA3); 	
					DIG(H01);
					 d_i = 1;
					break;
			case 13: PORTA &= ~((1<<PA1)|(1<<PA0));
					 PORTA |= (1<<PA2);
					 DIG(M10);
					 d_i = 1;
					break;

			case 14: PORTA &= ~((1<<PA1)|(1<<PA0));
					PORTA |= (1<<PA1); 	
					DIG(M01);
					 	d_i = 1;
					break;
			case 15: PORTA &= ~((1<<PA1)|(1<<PA0));
					PORTA |= (1<<PA0);
					DIG(8);
					 d_i = 1;
					break;

		}

	//	d_i_t = 1;
	//}else{
	//d_i_t = 0;
	//}	
	
//	d_i_t++;
//	if (d_i_t == 3){d_i_t = 0;}

		if (c_25ms == 0){
			c_25ms = 25;
			S--;
		}else{
			c_25ms--;	
		}
	d_15ms--;
	d_1ms = 0;
	}
// ---> Конец. "Задержка 1 мсек".

}// END WHILE LOOP
}//END MAIN



// ====== Функции: ======



void ADC_read(){ // Функция преобразования АЦП.
	// Калибровка нуля.
	// ADMUX |= ((1<<MUX4)|(1<<MUX3)|(1<<MUX2)|(1<<MUX1)|(1<<MUX0)); // АЦП = GND
	// ADCSRA |= (1<<ADSC);// Запуск преобразования.
	// while((ADCSRA & (1<<ADSC))){};// Ждём окончания преобразования.
	// ADC_DATA_t = ADCH;// GND.
	// MUX4-0 
	// 00000 PA0
	// 00001 PA1
	// 00010 PA2
	// 00011 PA3
	// 00100 PA4
	// 00101 PA5
	// 00110 PA6
	// 00111 PA7
	// 11111 GND	
	
//	ADMUX &= ~((1<<MUX4)|(1<<MUX3)|(1<<MUX2)|(1<<MUX1)|(1<<MUX0)); // АЦП = PA5 00101
	ADCSRA |= (1<<ADSC);// Запуск преобразования.

	while((ADCSRA & (1<<ADSC))){};  // Ждём окончания преобразования.
	ADC_DATA = ADCH;  // - ADC_DATA_t Порт  PA5.
}

void DIG(volatile uint8_t d){ // Функция индикации.
	switch (d){
		case 0: PORTC = 0b01001011;
				PORTD = 0b11111100;
				break;

		case 1: PORTC = 0b00001011;
				PORTD = 0b01001100;
				break;

		case 2: PORTC = 0b01101011;
				PORTD = 0b10011100;
				break;

		case 3: PORTC = 0b00101011;
				PORTD = 0b11011100;
				break;

		case 4: PORTC = 0b00101011;
				PORTD = 0b01101100;
				break;

		case 5: PORTC = 0b00100011;
				PORTD = 0b11111100;
				break;

		case 6: PORTC = 0b01100011;
				PORTD = 0b11111100;
				break;

		case 7: PORTC = 0b00001011;
				PORTD = 0b01011100;
				break;

		case 8: PORTC = 0b01101011;
				PORTD = 0b11111100;
				break;

		case 9: PORTC = 0b00101011;
				PORTD = 0b11111100;
				break;
		case 10: PORTC = 0b00000011;
				 PORTD = 0b11111100;
				break;
		case 11: PORTC = 0b00001011;
				PORTD = 0b00001100;
				break;
		case 12: PORTC = 0b00000011;
				PORTD = 0b01001100;
				break;

		case 0xFF: PORTC = 0b00000011;
				PORTD = 0b00001100;
				break;
				/*
PORTC - Выход. 7654 3210

PC0 - SCL. DS3231.
PC1 - SDA. DS3231.
PC2 - I/O. Катод ламп "9"(HV GND). default = 0; 1 = вкл.
PC3 - I/O. Катод ламп "0"(HV GND). default = 0; 1 = вкл.
PC4 - I/O. Катод ламп "1"(HV GND). default = 0; 1 = вкл.
PC5 - I/O. Катод ламп "2"(HV GND). default = 0; 1 = вкл.
PC6 - I/O. Катод ламп "3"(HV GND). default = 0; 1 = вкл.
PC7 - I/O. Катод ламп "4"(HV GND). default = 0; 1 = вкл.

PORTD - Выход, PD2-3 Вход.

PD0 - NC. 
PD1 - NC.
PD2 - INT. Кнопка "SEL". Внутр. резистр 50К. default = 1; 0 = кн. нажата.
PD3 - INT. Кнопка "UP". Внутр. резистр 50К. default = 1; 0 = кн. нажата.
PD4 - I/O. Катод ламп "5"(HV GND). default = 0; 1 = вкл.
PD5 - I/O. Катод ламп "6"(HV GND). default = 0; 1 = вкл.
PD6 - I/O. Катод ламп "7"(HV GND). default = 0; 1 = вкл.
PD7 - I/O. Катод ламп "8"(HV GND). default = 0; 1 = вкл.
*/

	}
}

void Read_DS(){ // Чтение часов и минут из DS3231 с конвертацией их в H10 H01 M10 M01.
	i2c_restart_cond();
	i2c_send_byte (WRITE_DS32);  // адрес записи.
	i2c_send_byte (0x01);		// адрес секунд и десятков секунд (при дальнейшем чтении, адрес инкрементируется автоматически).

	i2c_restart_cond();			// повторный старт.
	i2c_send_byte(READ_DS32);	// адрес чтения.

//	S = i2c_get_byte(0); // 0 - Подтверждение, ACK, будем считывать ещё один байт.
	M = i2c_get_byte(0); //
	H = i2c_get_byte(1); // 1 - NACK, это последний считанный байт.

	i2c_stop_cond();

	H01 = (H&0x0F);
	H10 = ((H&0x30)>>4); // BIT6-7 Не интерисует. 
	
	M01 = (M&0x0F);
	M10 = ((M&0xF0)>>4);
}
void Write_DS(){ // Запись часов и минут в DS3231 с конвертацией их в H10 H01 M10 M01.
	M = (M10<<4);
	M = (M|M01);
	H = (H10<<4);
	H = (H|H01);
	//S = 0x00;// Добавить сброс секунд.

	i2c_restart_cond();
	i2c_send_byte (WRITE_DS32);	// адрес записи
 
	i2c_send_byte (0x01);		// адрес минут //заменить на ?0x00? - адрес секунд
	//i2c_send_byte (S);
	i2c_send_byte (M);
	i2c_send_byte (H);
	i2c_stop_cond();
}

void DS3231_ini(){//  Настройка часов.

	i2c_restart_cond();
	i2c_send_byte (WRITE_DS32);	// адрес записи
	i2c_send_byte (0x0E);		// адрес регистра управления
	i2c_send_byte (0x00);// Регистр 0x0E, RS2 RS1 == 1Гц, включить меандр с частотой 1 герц.
	i2c_stop_cond();

}

/*
// !!! bin2bcd 3 знака Алгоритм «Плюс 3 и сдвиг»
void BIN2BCD3shift(volatile uint8_t digHEX){ // Двоично-десятичное преобразование.

	bin2bcd0001 = 0x00;//2 0-255
	bin2bcd0010 = 0x00;//5
	bin2bcd0100 = 0x00;//5

	int ii = 8;
	while (ii > 0){
		// 1) Корректировка (+3). 
		bin2bcd0001 &= 0x0F; //Выделение из байта младшей декады
		if (bin2bcd0001 > 4) //если декада больше 4
			bin2bcd0001 += 3;//то к ней прибавляется 3

		bin2bcd0010 &= 0x0F; //Выделение из байта младшей декады
		if (bin2bcd0010 > 4) //если декада больше 4
			bin2bcd0010 += 3;//то к ней прибавляется 3

		bin2bcd0100 &= 0x0F; //Выделение из байта младшей декады
		if (bin2bcd0100 > 4) //если декада больше 4
			bin2bcd0100 += 3;//то к ней прибавляется 3

		// 2) сдвиг 
		bin2bcd0100	<<= 1;
		
		// 3) копирование

		if (bin2bcd0010 & (1<<b3) )   // if XX_3 ==  1 старший разряд в младший разряд XX'_0
			bin2bcd0100 |= (1<<b0);
		
		bin2bcd0010	<<= 1;

		if (bin2bcd0001 & (1<<b3) )   // if XX_7 ==  1 старший разряд в младший разряд XX'_0
			bin2bcd0010 |= (1<<b0);
		
		bin2bcd0001	<<= 1;

		if (digHEX & (1<<b7) )   // if XX_7 ==  1 старший разряд в младший разряд XX'_0
			bin2bcd0001 |= (1<<b0);

		// 4)сдвиг параметра
		digHEX <<= 1;
		ii--;
	}
	bin2bcd0001 &= 0x0F; //Выделение из байта младшей декады
	bin2bcd0010 &= 0x0F; //Выделение из байта младшей декады
	bin2bcd0100 &= 0x0F; //Выделение из байта младшей декады
}// Несколько заметок о BCD-преобразованиях.pdf — Яндекс: нашлось 13 млн результатов https://megaobuchalka.ru/8/24109.html https://vgsemenov.wordpress.com/2011/11/08/%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B-%D0%B4%D0%B2%D0%BE%D0%B8%D1%87%D0%BD%D0%BE-%D0%B4%D0%B5%D1%81%D1%8F%D1%82%D0%B8%D1%87%D0%BD%D0%BE%D0%B3%D0%BE-%D0%BF%D1%80%D0%B5%D0%BE%D0%B1/
*/
