/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "math.h"
#include "bmp180_for_stm32_hal.h"
#include "stdio.h"
#include "disp.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define DS3231_ADDR 0xD0
#define BMP_ADDR 0xEE

#define PREAMBLE 3792
#define DELTA 350
#define ONE 2990

#define BUT_MODE GPIO_PIN_8
#define BUT_LEFT GPIO_PIN_9
#define BUT_RIGHT GPIO_PIN_10
#define BUT_UP GPIO_PIN_11
#define BUT_DOWN GPIO_PIN_12
#define BUT_OK GPIO_PIN_15

#define PRESS_ARCH_LEN 125


#define _DHT_LOW GPIOB->BSRR = (uint32_t)GPIO_PIN_4<<16u;
#define _DHT_HIGH GPIOB->BSRR = GPIO_PIN_4;


/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
ADC_HandleTypeDef hadc1;

I2C_HandleTypeDef hi2c1;

SPI_HandleTypeDef hspi1;

TIM_HandleTypeDef htim2;
TIM_HandleTypeDef htim3;

/* USER CODE BEGIN PV */
extern uint8_t rem_rdy;
extern uint16_t rx_filt[50];
double press_arc[PRESS_ARCH_LEN] = {0};

int32_t Press = 0;
uint8_t start_meas=0;
uint8_t cntr=0;
uint8_t cur_col = 0;


uint8_t p_1 = 0;
uint8_t p_2 =0;
double p_hg = 0;
double p_hg_med = 0;
int16_t temp_ext = 32700;
uint16_t ext_cnt = 0;
uint8_t mins_stmp = 0;
double p_hg_stmp = 0;
double p_hg_diff = 0;
uint8_t dht_cntr=0;
int16_t temp_dht = 0;
uint16_t humi = 0;
uint16_t humi_med = 0;
uint16_t dht_data[44] = {0};
uint16_t dht_proc[5] = {0};
uint16_t button_state = 0;


uint8_t hrs = 0;
uint8_t mins = 0;
uint8_t secs = 0;
uint8_t day = 0;
uint8_t month = 0;
uint8_t year = 0;
uint8_t daywk = 0;


char timedate[15];
uint8_t mode = 0;
int8_t corr_pos = 0;
int8_t batt_low=0;
uint16_t adc_val = 0;

double p_max=0.0;
double p_min=5000.0;


/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_I2C1_Init(void);
static void MX_SPI1_Init(void);
static void MX_TIM2_Init(void);
static void MX_TIM3_Init(void);
static void MX_ADC1_Init(void);
/* USER CODE BEGIN PFP */
void print_time0(void);
void print_date0(void);


void ReadFromDS3231(void);  //чтение из DS3231

void Clr_Arch(void);


/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */
  
  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_I2C1_Init();
  MX_SPI1_Init();
  MX_TIM2_Init();
  MX_TIM3_Init();
  MX_ADC1_Init();
  /* USER CODE BEGIN 2 */
	
  _DHT_HIGH
	HAL_I2C_Mem_Write(&hi2c1, DS3231_ADDR, 0x0E, 1, 0x00, 1, 1000); //включить выход 1 Гц
	BMP180_Init(&hi2c1);
	BMP180_SetOversampling(BMP180_ULTRA);
	BMP180_UpdateCalibrationData();
	HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_2);
	HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_2);
	
	ili9225_sw_reset();
	HAL_Delay(50);
	ili9225_init();
	ili9225_fill(0x0000);
	
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
		if (start_meas==1 && batt_low==0) {
			
			start_meas=0;
			if (ext_cnt<=1800 && temp_ext<=32701) ext_cnt++;
			if (ext_cnt>=1800) {
				 if (temp_ext<32700) {
					 sprintf(timedate, "> 30m");
				   print_lasttime(114,138,timedate, 0x9D96, ILI9225_LCD_WIDTH);
				 }
				 temp_ext=32700;
				 
			}
			
			dht_cntr++;

	
	if (mode==0) {
	ReadFromDS3231();
		
	}
			
	    ////////Ввод температуры и влажности от DHT22
			if (dht_cntr==2) {  //Запускаем измерение температуры DHT22
				dht_cntr=0;
				cntr=0;
				_DHT_LOW
				HAL_Delay(7);
				_DHT_HIGH
				HAL_Delay(10);
				
				//Разбираем по битам
				if (dht_data[2]>=PREAMBLE-DELTA && dht_data[2]<=PREAMBLE+DELTA) { //Получили "стартовый" бит
				dht_proc[0]=0;
				dht_proc[1]=0;
				dht_proc[2]=0;
				dht_proc[3]=0;
				dht_proc[4]=0;
				for (uint8_t u=3; u<43; u++) {
					if (dht_data[u]>=ONE-DELTA && dht_data[u]<=ONE+DELTA) { 
						dht_proc[(u-3)/8]|=(0x01<<(7-(u-3-((u-3)/8)*8)));
					}
				}
				
				if (dht_proc[2]&0x80) { //Значение температуры
				temp_dht = -((((int16_t)(dht_proc[2]&0x7F))<<8)+dht_proc[3]);
				} else {
					temp_dht = (((int16_t)(dht_proc[2]&0x7F))<<8)+dht_proc[3];
				}
			  
				
			  //Значение влажности
				humi = (((uint16_t)dht_proc[0])<<8) + dht_proc[1];
				if (humi_med==0) {
					humi_med=humi;
				} else {
					humi_med=(humi_med*4 + humi)/5;
				}
				
			}
				
			}
			
			////Получение и работа со значением давления от датчика BMP180
		  Press = BMP180_GetPressure();
			p_1 = Press/1000;
			p_2 = (Press-p_1*1000)/10;
			p_hg = (double)Press*7.5006/1000.0;
			if (p_hg_med==0.0) {p_hg_med=p_hg;} else {p_hg_med = (p_hg_med*9.0+p_hg)/10.0;}; //Делаем колебания более инерционными, добавляя текущее значение к среднему*9 и снова получая среднее
			if (p_hg_stmp==0.0) {p_hg_stmp=p_hg_med; mins_stmp = mins;};  //Если это первый замер давления, то засечем момент его взятия
			if (mins>=mins_stmp) {
				if (mins-mins_stmp>=15) { //Следующая точка - через 15 минут
				p_hg_diff = p_hg_med-p_hg_stmp; p_hg_stmp = p_hg_med; mins_stmp=mins;
				for(uint8_t l1=0; l1<PRESS_ARCH_LEN-1; l1++) press_arc[l1]=press_arc[l1+1];
				if (hrs==0 && mins<=15) {
				press_arc[PRESS_ARCH_LEN-1]=p_hg_med+2000.0;  //Начало замеров новых суток обозначим добавкой в 2000 мм. рт. ст.
				} else {
				press_arc[PRESS_ARCH_LEN-1]=p_hg_med;	
				}
				p_max=0.0;   ///Ищем минимум и максимум замеров давления
				p_min=5000.0;
				for(uint8_t l1=0; l1<PRESS_ARCH_LEN; l1++) {
					if (press_arc[l1]>0) {
						if (press_arc[l1]>2000) {
							if (press_arc[l1]-2000.0<p_min) p_min=press_arc[l1]-2000.0;
							if (press_arc[l1]-2000.0>p_max) p_max=press_arc[l1]-2000.0;
						} else {
							if (press_arc[l1]<p_min) p_min=press_arc[l1];
							if (press_arc[l1]>p_max) p_max=press_arc[l1];
						}
					}
				}
			if (press_arc[PRESS_ARCH_LEN-2]>0) {  //Если замеров 2 или больше, то можно отрисовывать график
			FillRect(31,188,PRESS_ARCH_LEN+2,32, 0x0000);
			while (p_max-p_min<2.5) {p_max+=0.1; p_min-=0.1;}; //Если минимум и максимум слишком близко, расширим шкалу
			sprintf(timedate, "%5.2f", p_max);
			print_small(0,188,timedate,0x3686,32);
			sprintf(timedate, "%5.2f", p_min);
			print_small(0,214,timedate,0x3686,32);
			double k1=(218.0-188.0)/(p_max-p_min); //Коэффициент перевода мм.рт.ст. в пиксели
			for (uint8_t k2=0; k2<PRESS_ARCH_LEN; k2++) {
				if (press_arc[k2]>0) {
					 if (press_arc[k2]>2000.0) {
						 drawdotbig(32+k2,218-(uint8_t)((press_arc[k2]-2000.0-p_min)*k1),0xF000); //Точка начала суток
					 } else {
						 drawdot(32+k2,218-(uint8_t)((press_arc[k2]-p_min)*k1),0x3686); //Обычная точка
						 
					 }
				 }
			}
			
			}
				
				};
			} else {
				if ((60-mins_stmp)+mins>=15) {
				p_hg_diff = p_hg_med-p_hg_stmp; p_hg_stmp = p_hg_med; mins_stmp=mins;
				for(uint8_t l1=0; l1<PRESS_ARCH_LEN-1; l1++) press_arc[l1]=press_arc[l1+1];
				if (hrs==0 && mins<=15) {
				press_arc[PRESS_ARCH_LEN-1]=p_hg_med+2000.0;
				} else {
				press_arc[PRESS_ARCH_LEN-1]=p_hg_med;	
				}
				p_max=0.0;
				p_min=5000.0;
				for(uint8_t l1=0; l1<PRESS_ARCH_LEN; l1++) {
					if (press_arc[l1]>0) {
						if (press_arc[l1]>2000) {
							if (press_arc[l1]-2000.0<p_min) p_min=press_arc[l1]-2000.0;
							if (press_arc[l1]-2000.0>p_max) p_max=press_arc[l1]-2000.0;
						} else {
							if (press_arc[l1]<p_min) p_min=press_arc[l1];
							if (press_arc[l1]>p_max) p_max=press_arc[l1];
						}
					}
				}
				if (press_arc[PRESS_ARCH_LEN-2]>0) {
				
				FillRect(31,188,PRESS_ARCH_LEN+2,31, 0x0000);
				
				while (p_max-p_min<2.5) {p_max+=0.1; p_min-=0.1;};
				sprintf(timedate, "%5.2f", p_max);
			  print_small(0,188,timedate,0x3686,32);
				sprintf(timedate, "%5.2f", p_min);
			  print_small(0,214,timedate,0x3686,32);
					double k1=(218.0-188.0)/(p_max-p_min);
					for (uint8_t k2=0; k2<PRESS_ARCH_LEN; k2++) {
				if (press_arc[k2]>0) {
					 if (press_arc[k2]>2000.0) {
						 drawdotbig(32+k2,218-(uint8_t)((press_arc[k2]-2000.0-p_min)*k1),0xF000);
					 } else {
						 drawdot(32+k2,218-(uint8_t)((press_arc[k2]-p_min)*k1),0x3686);
						 
					 }
				 }
			}
					
				}
				};
			}	
			
				
			
      //////Ежесекундный вывод времени и даты
			print_time0();
			print_date0();
				
					
				
			sprintf(timedate, "%4.1f@C %3.1f$", (double)temp_dht/10.0, (double)humi_med/10.0);  //Вывод температуры и влажности от DHT22
			print_date(0,94,timedate, 0x9F06, ILI9225_LCD_WIDTH);
			
			
			//////Вывод температуры от беспроводного датчика
			if (temp_ext==32700) { //Если температура не менялась с момента включения, то 
				sprintf(timedate, "-.-@C"); //Выведем прочерки
				print_mmhg(100,162,0x3686); //Напечатаем "mmHg" - в момент включения в эту ветку программа попадет, а после приема температуры от беспроводного датчика - только через полчаса радиомолчания
				print_last(115, 128, 0x9D96); //Напечатаем слово "посл.:" - также включено сюда для однократной печати
				print_date(0,128,timedate, 0x9D96, 114);
				temp_ext++; //увеличим на 1, чтобы в эту ветку код больше не попал
			}
			if (temp_ext<32700) {  //Вывод времени с момента последнего приема данных от беспроводного датчика температуры
			uint16_t p1 = ext_cnt/60;
			if (ext_cnt<=1800) {  //Если прошло менее 30 минут, то печатаем время полностью
			sprintf(timedate, "%dm %02ds", p1, ext_cnt-(p1*60)); 
			} else {
			sprintf(timedate, ">30m");	 //Если больше 30 минут, то просто указываем ">30м"
			}
			print_lasttime(114,138,timedate, 0x9D96, ILI9225_LCD_WIDTH);
			} 
			
			sprintf(timedate, "%5.2f", (double)p_hg_med);  //Вывод текущего давления с учетом усреднения
			print_date(0,162,timedate, 0x3686, 99);
			
			if (batt_low==1) ili9225_fill(0x0000);
			
		}
		
		if (batt_low==0) {
		///////// Обработка кнопок
		if ((GPIOA->IDR & BUT_MODE)>0) { //Нажатие MODE
					while (GPIOA->IDR & BUT_MODE) {HAL_Delay(10);};
					if (mode==0) {
						corr_pos=0;
						mode=1;
						print_time0();
					} else {
						mode=0;
						print_time0();
					}
				}
				if ((GPIOA->IDR & BUT_LEFT)>0) { //Нажатие LEFT
					while (GPIOA->IDR & BUT_LEFT) {HAL_Delay(10);};
					if (mode==1) {
						if (corr_pos>=1) {
						corr_pos--;
						} else {corr_pos=6; };
						print_time0(); print_date0();
					}
				}
				if ((GPIOA->IDR & BUT_RIGHT)>0) { //Нажатие RIGHT
					while (GPIOA->IDR & BUT_RIGHT) {HAL_Delay(10);};
					if (mode==1) {
						if (corr_pos<6) {
						corr_pos++;				
						} else {corr_pos=0; };
						print_time0(); print_date0();
					}
				}
				if ((GPIOA->IDR & BUT_UP)>0) { //Нажатие UP
					while (GPIOA->IDR & BUT_UP) {HAL_Delay(10);};
					if (mode==1) {
						switch(corr_pos) {
							case 0: {if (hrs<23) {hrs++;} else {hrs=0;};} break;
							case 1: {if (mins<59) {mins++;} else {mins=0;};} break;
							case 2: {if (secs<59) {secs++;} else {secs=0;};} break;
							
							case 3: {
								switch (month) {
									case 1:
                  case 3:
                  case 5:
                  case 7:
                  case 8:
                  case 10:
                  case 12:  {if (day<31) {day++;} else {day=1;}; }; break;

                  case 4:
                  case 6:
								  case 9:
                  case 11: 	{if (day<30) {day++;} else {day=1;}; break;	
                  
                  case 2: {
                     if (year%4==0) { if (day<29) {day++;} else {day=1;}; } else {if (day<28) {day++;} else {day=1;};};
									} 										
									
								}
								
							
							
							default: break;
						}
						
					}; break;
							
									case 4: if (month<12) {month++;} else {month=1;}; break;
									
									case 5: if (year<99) {year++;} else {year=0;}; break;
									
									case 6: if (daywk<7) {daywk++;} else {daywk=1;}; break;
									
							
									default: break;
									}
					if (corr_pos>=0 && corr_pos<=2) {print_time0();} else {print_date0();};
				}
					
			}
				if ((GPIOA->IDR & BUT_DOWN)>0) { //Нажатие DOWN
					while (GPIOA->IDR & BUT_DOWN) {HAL_Delay(10);};
					
					if (mode==1) {
						switch(corr_pos) {
							case 0: {if (hrs>0) {hrs--;} else {hrs=23;};} break;
							case 1: {if (mins>0) {mins--;} else {mins=59;};} break;
							case 2: {if (secs>0) {secs--;} else {secs=59;};} break;
							
							case 3: {
								switch (month) {
									case 1:
                  case 3:
                  case 5:
                  case 7:
                  case 8:
                  case 10:
                  case 12:  {if (day>1) {day--;} else {day=31;}; }; break;

                  case 4:
                  case 6:
								  case 9:
                  case 11: 	{if (day>1) {day--;} else {day=30;}; break;	
                  
                  case 2: {
                     if (year%4==0) { if (day>1) {day--;} else {day=29;}; } else {if (day>1) {day--;} else {day=28;};};
									} 										
									
								}
								
							
							
							default: break;
						}
						
					}; break;
							
					        case 4: if (month>1) {month--;} else {month=12;}; break;
									
									case 5: if (year>0) {year--;} else {year=99;}; break;
									
									case 6: if (daywk>1) {daywk--;} else {daywk=7;}; break;
							
									default: break;
									}
					if (corr_pos>=0 && corr_pos<=2) {print_time0();} else {print_date0();};
				}
					
					
				}
				if ((GPIOA->IDR & BUT_OK)>0) { //Нажатие OK
					while (GPIOA->IDR & BUT_OK) {HAL_Delay(10);};
					if (mode==1) {
						uint8_t tmp2 = 0;
						switch (corr_pos) {
							case 0: {tmp2=hrs/10; tmp2=tmp2<<4; tmp2|=(hrs%10);  HAL_I2C_Mem_Write(&hi2c1, DS3231_ADDR, 0x02, 1, &tmp2, 1, 1000); corr_pos++; if (corr_pos>6) corr_pos=0; Clr_Arch();} break;
							case 1: {tmp2=mins/10; tmp2=tmp2<<4; tmp2|=(mins%10);  HAL_I2C_Mem_Write(&hi2c1, DS3231_ADDR, 0x01, 1, &tmp2, 1, 1000); corr_pos++; if (corr_pos>6) corr_pos=0; Clr_Arch();} break;
							case 2: {tmp2=secs/10; tmp2=tmp2<<4; tmp2|=(secs%10);  HAL_I2C_Mem_Write(&hi2c1, DS3231_ADDR, 0x00, 1, &tmp2, 1, 1000); corr_pos++; if (corr_pos>6) corr_pos=0; Clr_Arch();} break;
								
							case 3: {tmp2=day/10; tmp2=tmp2<<4; tmp2|=(day%10);  HAL_I2C_Mem_Write(&hi2c1, DS3231_ADDR, 0x04, 1, &tmp2, 1, 1000); corr_pos++; if (corr_pos>6) corr_pos=0;} break;
							case 4: {
								if (day>28) {
									if (month==4 || month==6 || month==9 || month==11) {
										if (day==31) {day=30; tmp2=day/10; tmp2=tmp2<<4; tmp2|=(day%10);  HAL_I2C_Mem_Write(&hi2c1, DS3231_ADDR, 0x04, 1, &tmp2, 1, 1000);};
									}
									if (month==2) {
										if (year%4==0) {if (day>29) {day=29; tmp2=day/10; tmp2=tmp2<<4; tmp2|=(day%10);  HAL_I2C_Mem_Write(&hi2c1, DS3231_ADDR, 0x04, 1, &tmp2, 1, 1000);};}
											 else {if (day>28) {day=28; tmp2=day/10; tmp2=tmp2<<4; tmp2|=(day%10);  HAL_I2C_Mem_Write(&hi2c1, DS3231_ADDR, 0x04, 1, &tmp2, 1, 1000);};}
									}
								}
								{tmp2=month/10; tmp2=tmp2<<4; tmp2|=(month%10);  HAL_I2C_Mem_Write(&hi2c1, DS3231_ADDR, 0x05, 1, &tmp2, 1, 1000); corr_pos++; if (corr_pos>6) corr_pos=0;} 
								
							}; break;
							
							case 5: {
								if (day>28) {
								
									if (month==2) {
										if (year%4==0) {if (day>29) {day=29; tmp2=day/10; tmp2=tmp2<<4; tmp2|=(day%10);  HAL_I2C_Mem_Write(&hi2c1, DS3231_ADDR, 0x04, 1, &tmp2, 1, 1000);};}
											 else {if (day>28) {day=28; tmp2=day/10; tmp2=tmp2<<4; tmp2|=(day%10);  HAL_I2C_Mem_Write(&hi2c1, DS3231_ADDR, 0x04, 1, &tmp2, 1, 1000);};}
									}
								}
								{tmp2=year/10; tmp2=tmp2<<4; tmp2|=(year%10);  HAL_I2C_Mem_Write(&hi2c1, DS3231_ADDR, 0x06, 1, &tmp2, 1, 1000); corr_pos++; if (corr_pos>6) corr_pos=0;} 
								
							}; break;
							
							case 6: HAL_I2C_Mem_Write(&hi2c1, DS3231_ADDR, 0x03, 1, &daywk, 1, 1000); mode=0; break;
							
							default: break;
						}
						
						
					}
					
				}
				
			}
		if (batt_low==0) {
		if (rem_rdy==1) {  //Данные от беспроводного датчика температуры получены
				for (short j=0; j<49; j++) {
					if (rx_filt[j]>=28800 && rx_filt[j]<=29600 && rx_filt[j+1]>=28800 && rx_filt[j+1]<=29600) { //Найдем начало байта температуры (два "длинных" бита)
						 if (j<8) {
							 temp_ext = 0;
							 for(short k=j+4; k<j+4+12; k++) {
								 if (rx_filt[k]>=17800 && rx_filt[k]<=18600) {temp_ext|= ((uint16_t)1<<(11-(k-j-4)));} //Температура передается в инверсных кодах, т.е. единицы - это "короткие" биты
							 };
							 temp_ext-=400;  //Температура в десятых долях градуса и смещена на 40 градусов (код 0000000... - это -40С)
						 }
						break;
					}
					
				}
			sprintf(timedate, "%4.1f@C", (double)temp_ext/10.0); //вывод температуры
			print_date(0,128,timedate, 0x9D96, 114);	
			ext_cnt=0;	
			rem_rdy=0;	
				
				
			}
		}
		
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC;
  PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief ADC1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_ADC1_Init(void)
{

  /* USER CODE BEGIN ADC1_Init 0 */

  /* USER CODE END ADC1_Init 0 */

  ADC_ChannelConfTypeDef sConfig = {0};

  /* USER CODE BEGIN ADC1_Init 1 */

  /* USER CODE END ADC1_Init 1 */
  /** Common config
  */
  hadc1.Instance = ADC1;
  hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
  hadc1.Init.ContinuousConvMode = DISABLE;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.NbrOfConversion = 1;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_9;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN ADC1_Init 2 */

  /* USER CODE END ADC1_Init 2 */

}

/**
  * @brief I2C1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_I2C1_Init(void)
{

  /* USER CODE BEGIN I2C1_Init 0 */

  /* USER CODE END I2C1_Init 0 */

  /* USER CODE BEGIN I2C1_Init 1 */

  /* USER CODE END I2C1_Init 1 */
  hi2c1.Instance = I2C1;
  hi2c1.Init.ClockSpeed = 400000;
  hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
  hi2c1.Init.OwnAddress1 = 0;
  hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c1.Init.OwnAddress2 = 0;
  hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
  if (HAL_I2C_Init(&hi2c1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN I2C1_Init 2 */

  /* USER CODE END I2C1_Init 2 */

}

/**
  * @brief SPI1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_SPI1_Init(void)
{

  /* USER CODE BEGIN SPI1_Init 0 */

  /* USER CODE END SPI1_Init 0 */

  /* USER CODE BEGIN SPI1_Init 1 */

  /* USER CODE END SPI1_Init 1 */
  /* SPI1 parameter configuration*/
  hspi1.Instance = SPI1;
  hspi1.Init.Mode = SPI_MODE_MASTER;
  hspi1.Init.Direction = SPI_DIRECTION_2LINES;
  hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi1.Init.NSS = SPI_NSS_SOFT;
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi1.Init.CRCPolynomial = 10;
  if (HAL_SPI_Init(&hspi1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN SPI1_Init 2 */

  /* USER CODE END SPI1_Init 2 */

}

/**
  * @brief TIM2 Initialization Function
  * @param None
  * @retval None
  */
static void MX_TIM2_Init(void)
{

  /* USER CODE BEGIN TIM2_Init 0 */

  /* USER CODE END TIM2_Init 0 */

  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};
  TIM_IC_InitTypeDef sConfigIC = {0};

  /* USER CODE BEGIN TIM2_Init 1 */

  /* USER CODE END TIM2_Init 1 */
  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 5;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 65535;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_IC_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_FALLING;
  sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
  sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
  sConfigIC.ICFilter = 0;
  if (HAL_TIM_IC_ConfigChannel(&htim2, &sConfigIC, TIM_CHANNEL_2) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM2_Init 2 */

  /* USER CODE END TIM2_Init 2 */

}

/**
  * @brief TIM3 Initialization Function
  * @param None
  * @retval None
  */
static void MX_TIM3_Init(void)
{

  /* USER CODE BEGIN TIM3_Init 0 */

  /* USER CODE END TIM3_Init 0 */

  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};
  TIM_IC_InitTypeDef sConfigIC = {0};

  /* USER CODE BEGIN TIM3_Init 1 */

  /* USER CODE END TIM3_Init 1 */
  htim3.Instance = TIM3;
  htim3.Init.Prescaler = 2;
  htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim3.Init.Period = 65535;
  htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
  if (HAL_TIM_Base_Init(&htim3) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_IC_Init(&htim3) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_FALLING;
  sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
  sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
  sConfigIC.ICFilter = 0;
  if (HAL_TIM_IC_ConfigChannel(&htim3, &sConfigIC, TIM_CHANNEL_2) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM3_Init 2 */

  /* USER CODE END TIM3_Init 2 */

}

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOD_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0|GPIO_PIN_4, GPIO_PIN_RESET);

  /*Configure GPIO pin : PA6 */
  GPIO_InitStruct.Pin = GPIO_PIN_6;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /*Configure GPIO pin : PB0 */
  GPIO_InitStruct.Pin = GPIO_PIN_0;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /*Configure GPIO pin : PB2 */
  GPIO_InitStruct.Pin = GPIO_PIN_2;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /*Configure GPIO pins : PA8 PA9 PA10 PA11
                           PA12 PA15 */
  GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11
                          |GPIO_PIN_12|GPIO_PIN_15;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLDOWN;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /*Configure GPIO pin : PB4 */
  GPIO_InitStruct.Pin = GPIO_PIN_4;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /* EXTI interrupt init*/
  HAL_NVIC_SetPriority(EXTI2_IRQn, 2, 0);
  HAL_NVIC_EnableIRQ(EXTI2_IRQn);

}

/* USER CODE BEGIN 4 */



void ReadFromDS3231(void) {  ///Процедура чтения данных из DS3231
  uint8_t tmp;
  HAL_I2C_Mem_Read(&hi2c1, DS3231_ADDR, 0x00, 1, &tmp, 1, 1000);
	secs = (tmp>>4)*10+(tmp&0x0F);
	HAL_I2C_Mem_Read(&hi2c1, DS3231_ADDR, 0x01, 1, &tmp, 1, 1000);
	mins = (tmp>>4)*10+(tmp&0x0F);
	HAL_I2C_Mem_Read(&hi2c1, DS3231_ADDR, 0x02, 1, &tmp, 1, 1000);
	tmp&=0x3F;
	hrs = (tmp>>4)*10+(tmp&0x0F);
	
	HAL_I2C_Mem_Read(&hi2c1, DS3231_ADDR, 0x03, 1, &tmp, 1, 1000);
	daywk = (tmp>>4)*10+(tmp&0x0F);
	HAL_I2C_Mem_Read(&hi2c1, DS3231_ADDR, 0x04, 1, &tmp, 1, 1000);
	day = (tmp>>4)*10+(tmp&0x0F);
	HAL_I2C_Mem_Read(&hi2c1, DS3231_ADDR, 0x05, 1, &tmp, 1, 1000);
	tmp&=0x1F;
	month = (tmp>>4)*10+(tmp&0x0F);
	HAL_I2C_Mem_Read(&hi2c1, DS3231_ADDR, 0x06, 1, &tmp, 1, 1000);
	year = (tmp>>4)*10+(tmp&0x0F);	
	
}

void Clr_Arch(void) {  ///Процедура очистки архива показаний датчика давления
	for(uint8_t u=0; u<PRESS_ARCH_LEN; u++) {
		press_arc[u]=0;
	};
	FillRect(0,188,PRESS_ARCH_LEN+33,31, 0x0000);  //Очистим область с отображением показаний
	mins_stmp=mins; //Начнем отсчет показаний заново
	
}

void print_time0(void) { //Процедура вывода на экран времени
	
	if (mode==0) {
		  sprintf(timedate, "%02d:%02d:%02d", hrs,mins,secs); //Вне режима редактирования печатаем время целиком
      print_time(0,0,timedate, 0xAF50, ILI9225_LCD_WIDTH);
			
		} else {
			 sprintf(timedate, "%02d", hrs);  //В режиме редактирования печатаем по одной цифре с заливкой в зависимости от положения "курсора"
			if (mode==1 && corr_pos==0) {
				print_time(0,0,timedate, 0xF000, 0);
			} else {
				print_time(0,0,timedate, 0xAF50, 0);
			}
			sprintf(timedate, ":");
      print_time(cur_col,0,timedate, 0xAF50, 0);
			
			sprintf(timedate, "%02d", mins);
			if (mode==1 && corr_pos==1) {
      print_time(cur_col,0,timedate, 0xF000, 0);
			} else {
			print_time(cur_col,0,timedate, 0xAF50, 0);
			}
			
			sprintf(timedate, ":");
      print_time(cur_col,0,timedate, 0xAF50, 0);
			
			sprintf(timedate, "%02d", secs);
			if (mode==1 && corr_pos==2) {
      print_time(cur_col,0,timedate, 0xF000, ILI9225_LCD_WIDTH);
			} else {
			print_time(cur_col,0,timedate, 0xAF50, ILI9225_LCD_WIDTH);	
			}
		}
	
}

void print_date0(void) {  //Процедура вывода на экран даты
	
	if (mode==0) {
	sprintf(timedate, "%02d-%02d-%02d", day,month,year); //Вне режима редактирования печатаем дату целиком
  print_date(0,53,timedate, 0xB290, 125);
  print_daywk(125,53,daywk, 0xB290); //День недели выводится отдельно, под него заведена своя таблица символов
		
	} else {  //В режиме редактирования печатаем по одной цифре с заливкой в зависимости от положения "курсора"
		sprintf(timedate, "%02d", day);
		if (mode==1 && corr_pos==3) {
				print_date(0,53,timedate, 0xF000, 0);
			} else {
				print_date(0,53,timedate, 0xB290, 0);
			}
			
		sprintf(timedate, "-");
		print_date(cur_col,53,timedate, 0xB290, 0);
			
		sprintf(timedate, "%02d", month);
		if (mode==1 && corr_pos==4) {
				print_date(cur_col,53,timedate, 0xF000, 0);
			} else {
				print_date(cur_col,53,timedate, 0xB290, 0);
			}
		sprintf(timedate, "-");
		print_date(cur_col,53,timedate, 0xB290, 0);
			
		sprintf(timedate, "%02d", year);
		if (mode==1 && corr_pos==5) {
				print_date(cur_col,53,timedate, 0xF000, 125);
			} else {
				print_date(cur_col,53,timedate, 0xB290, 125);
			}
		
		if (mode==1 && corr_pos==6) {
				print_daywk(125,53,daywk, 0xF000);
			} else {
				print_daywk(125,53,daywk, 0xB290);
			}
	}
	
}


/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */

  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
