#ifndef _ICD
#define _ICD
#include "main.h"
#include <stdbool.h>
#include "cmsis_os.h"
#include "adc.h"
//Глобальные настройки, делаем их неизменными
#define F103 0
#define F412 1
#define MK_TYPE F103

#define LAMP true//увеличенное время разряда
#define SPI_MODE true//с фронт энда берём данные
#define ACTIVE_CH 1//с фронт энда берём данные
#define CAP_VOLT_CTRL true//нужен ли контроль реального напряжения на конденсаторе

#define CAPACITY 0.000470
#define FORCE_DELAY 100 //Задержка МС после зарядки конденсатора в принудительном режиме
#define DANGER_HV true //чтобы риту не ёбнуло если 1 значит по реальному заряжаем
#define FILTER true //нужен ли фнч может флаг?

#define RG 1000.0//сопротивление резистора в омах

#define VOLT_COEF 3300.0/(4096*(1 + 100000.0/RG))
#define VOLT_COEF_MAX30003 0.000005
//по даташиту  G = 1 + (100 kΩ / RG(1000 у нас)) G = 101
//перевод остч	тов в вольты 3.3/4096
// Х*3.3/(4096*(1 + 100000.0/RG))  это сколько вольт у нас
#define MOV_AV_COEF 0.02//коэффициет скользящего среднего

#define MIN_TRES 0.5
#define MAX_TRES 3.0

#define DATA_RATE 200
//время для стабилизации сигналов когда ничего не происходит
#define ALL_TIME_MS				1500
#define START_UP_TIME_MS		2000
#define SEARCH_BASE_TIME_MS		700
#define SEARCH_MAX_TIME_MS		125
#define SQUARE_TIME_MS			400
#define TRIANGLE_TIME_MS		300
#define TRIANGLE_STEP_TIME_MS	50
#define LV_TIME_MS				200
#define LV_START_TIME_MS		5
#define LV_STOP_TIME_MS			50

#define SQUARE_COEF				0.5
#define TRIANGLE_COEF			0.85

#define TERAPY_TRES				10//сколько нужно единичных фибриляций для терапии

// Период 0 - FIBR_PERIOD считаем фибриляцией
#define FIBR_PERIOD				250
#define FIBR_PERIOD_MIN			250
#define FIBR_PERIOD_MAX			350
// Период FIBR_PERIOD - TACHY_2_PERIOD считаем тахикардией глубокой
#define TACHY_2_PERIOD			350
#define TACHY_2_PERIOD_MIN		300
#define TACHY_2_PERIOD_MAX		400
// Период TACHY_2_PERIOD - TACHY_1_PERIOD считаем тахикардией неглубокой
#define TACHY_1_PERIOD			400
#define TACHY_1_PERIOD_MIN		350
#define TACHY_1_PERIOD_MAX		450

// в десятых джоуля
#define	MIN_ENERGY				50
#define	MAX_ENERGY				400
//сколько шагов должно быть в терапии
#define	HV_STEP_NUM				6
//время в мс когда мы слепы
#define	HV_BLIND_TIME_MS		1500
// размер буффера редетекции
#define	REDET_BUF_LEN			8
// сколько нужно плохих периодов для продолжения терапии
#define	REDET_BAD_MAX			4

#define	STANDBY_TIME_MS			10*1000//пусть будет 10 секунд

typedef enum
{
    Monitor 	= 0,  // Тупо смотрим
    Normal 		= 1,  // поиск порогов и терапия
    Force 		= 2  // только терапия похуй на сигнал
}	main_mode;


//режим поиска пиков 3 байта
typedef enum
{
    Mode_start_UP 			= 0,  // тупо накапливаем среднее секунды 3 чтоб никого случайно током не ударить
    Mode_search_BASE 		= 1,  // поиск по нижнему порогу из памяти
    Mode_search_SQUARE 		= 2,  // поиск 300-400 мс по прошлый порог*коэффициент
    Mode_search_TRIANGLE 	= 3,  // поиск в режиме треугольников
    Mode_search_MAX 		= 4,  // режим поиска максимума Vsense
    Mode_stimulation_LV 	= 5,  // нет пиков стимулируем низким напряжением и не анализируем заданное время в Mode_search_BASE?
	Mode_stimulation_HV 	= 6   // отключаем вход чтобы не улетела скользящее среднее
//    Mode_stimulation_HV 	= 6   // Обнаружили фибриляцию  начали заряжать конденсатор(возможно это над режим т.к. в нём мы тоже ищем пики)
}	search_mode;

//режимы терапии 2 байта
typedef enum
{
    Terapy_off 				= 0,  // активна при тупом поиске корзин
	Terapy_fibr 			= 1,  // терапия фибриляции
	Terapy_tachy_2 			= 2,  // терапия сильной тахикардии
	Terapy_tachy_1 			= 3   // терапия слабой тахикардии
}	terapy_mode;

//подрежимы терапии 3 байта
typedef enum
{
    sub_off	 				= 0,  // неактивный
	sub_cap_ch	 			= 1,  // зарядка конденсатора
	sub_redet 				= 2,  // редетекция
	sub_shock 				= 3,  // удар током + время слепоты
	sub_stim_fail 			= 4   // провели стимуляцию, но не помогло
}	terapy_sub_mode;


//тип для события, каким он может быть 2 байта
typedef enum
{
    Vsense 		= 0,  // нормальное сокращение
    Vpace		= 1,  // пришлось стимулировать сейчас не используем
    Vnoise 		= 2,  // шумы в QRS комплексе(пока не реализовали)
}	QRS_type;

//тип для события, каким он может быть 2 байта
typedef enum
{
    cap_poz 	= 0,  // позитивная полярность сигнала(только её пока можем)
	cap_neg		= 1,  // негативная полярность сигнала(на старом железе нельзя)
	cap_bi 		= 2,  // сначала позитивная потом негативная
}	cap_polarity;

//тип для RR интервала
typedef struct icd_str
{
	main_mode work_set_mode; //режим
	main_mode work_now_mode; //режим

	search_mode search_set_mode; //режим
	search_mode search_now_mode; //режим
	bool	filter_on;//фильтр активен
	uint8_t active_ch;//какой канал используем 0-3 0 это spi
	bool	sd_card;//используем ли мы SD карту?
	bool	dc_cut;//стираем ли мы постоянную составляющую

	bool	rr_now;//сейчас сокращение сердца
	//минимальный и максимальный пороги с плав. точкой и инт в десятых миливольта
	float min_tres;
	uint8_t min_tres_d;
	float max_tres;
	uint8_t max_tres_d;
	//	коэффициент на который умножается сигнал при переход в режим квадратов
	float square_coef;
	uint8_t square_coef_d;
	//	коэффициент на который умножается сигнал на каждой ступени в режиме треугольников
	float triangle_coef;
	uint8_t triangle_coef_d;

//	счётчик режимов чтобы не задерживаться слишком долго в одном режиме
	uint16_t mode_cnt;
//	время слепоты при включении
	uint16_t start_up_time;
//	время поиска в базовом режиме с минимальным порогом
	uint16_t base_time;
//	Время в мс которое алгоритм ищет максимум
	uint16_t max_search_time;

//	Время в мс нахождения в режиме поиска квадратов
	uint16_t square_time;

//	время на весь режим треугольников
	uint16_t triangle_time;
//	время каждой ступени в режиме треугольников
	uint16_t triangle_step_time;

//	Время в мс которое длится режим стимуляции низким напряжением
	uint16_t lv_mode_time;
//	это во моногом эрзац.
	uint16_t lv_start_time; //во сколько начали выдавать импульс
	uint16_t lv_stop_time; //во сколько закончили выдавать импульс

	uint16_t max_time; //сколько отведено на весь QRS комплекс

//	тип последнего определённого события
	QRS_type	last_QRS;
//	время между последним и предпоследним событием
	uint16_t	last_period;


	float last_RR_amp;// переменная в которой храним амплитуды начала QRS#
	int32_t last_RR_poz;//переменная в котором храним положение начала QRS#
	int16_t last_RR_poz_rel;//переменная в которой храним относительное положение начала QRS

//	Счётчики нужны для алгоритма терапии Михаила
	uint32_t	Vs_cnt;//счётчик собственных сокращений сердца
	uint32_t	Vn_cnt;//счётчик собственных сокращений которые в шуме(не детектируется пока fixme)
	uint32_t	Vp_cnt;//счётчик принудительных стимуляций сердца низким напряжением(низковольтная стимуляция)

	bool	LV_on;// реально стимулируем низковольтно
	bool	HV_on;// реально стимулируем высоковольтно

	int32_t		counter;
	float 	ecg_rv_filt;		//экг в миливольтах для врачей
	float 	ecg_rv_mov_av;	//скользящее среднее для вычитания постоянной составляющей из сигнала
	float 	ecg_rv_pos_sig;	//сигнал из которого вычтена постоянная сост. и взят модуль
	float 	ecg_rv_din_treshold;//динамический порог

	// тут уже корзины
	//порог периода фибриляции если период меньше, чем это число это фибриляция
	uint16_t 	fibr_tres;
	//порог периода Тахикардии 2 если период меньше, чем это число это Тахикардия 2
	uint16_t 	tachy_2_tres;
	//порог периода Тахикардии 1 если период меньше, чем это число это Тахикардия 1
	uint16_t 	tachy_1_tres;

	uint32_t	vs_cnt_last;//сбрасываемый счётчик Vs событий
	uint16_t	filt_period;//фильтрованный скользящим средним период
	uint8_t		fibr_cnt; //счётчик фибриляции при обнаружении короткого RR он растёт
	uint8_t 	tachy_2_cnt; //счётчик Тахикардии 2 при обнаружении короткого RR он растёт
	uint8_t 	tachy_1_cnt; //счётчик Тахикардии 1 при обнаружении короткого RR он растёт
	uint8_t 	norm_cnt; //счётчик событий c нормальным ЧСС при достижении 5 сбрасываем все корзины

	uint32_t	vp_cnt_last;//сбрасываемый счётчик Vs событий нужен при редетекции сергей сказал что Vp достаточно для выхода из режима
	uint8_t 	fibr_max_tres; //порог счётчика фибриляций при котором начинаем терапию

	/////////////////////////////////////////////////////
	/////				терапия						/////
	/////////////////////////////////////////////////////
	terapy_mode terapy_set;//заданный режим терапии
	terapy_mode terapy_now;//текущий режим терапии

	terapy_sub_mode	sub_mode;//подрежим для индикации

	uint8_t		hv_step_number;//сколько шагов ВВ терапии?
	uint8_t		hv_step_cnt;// какой сейчас шаг?

	uint16_t	hv_step_energy;//сколько джоулей в одном шаге считаем в зависимости от минимума и максимума.
	uint16_t	min_energy;
	uint16_t	now_energy;
	uint16_t	max_energy;
	cap_polarity	cap_pol;//поляроность конденсатора

	uint16_t	hv_blind_time;//время которое мы слепы после HV разряда

	uint8_t		redet_num;	//какой длинны мы заполныем буффер при редетекции
	uint8_t		redet_bad;	//сколько нам нужно плохих событий для запуска терапии
	uint8_t		redet_cnt;	//сколько всего событий в редетекции
	uint8_t		redet_bad_cnt;	//сколько реально плохих событий

	uint32_t	standby_timer;//сколько отдыхать после неудачного подавления фибриляции

	uint8_t		com_buf[20];

	uint8_t		spi_pot_set;//spi резистор для задания КУ
	uint8_t		spi_pot_now;//spi резистор для задания КУ
} icd_str;





float my_abs(float a);
void get_data(icd_str * icd_str,uint16_t input);
void get_data_max30003(icd_str * icd_str,int32_t input);

void init_icd(icd_str * icd_str);
bool mode_start(icd_str * icd_str);
bool check_mode_len(icd_str * icd_str,uint16_t base_time, search_mode mode_to_set);
bool check_tres(icd_str * icd_str);
void search_alg(icd_str * icd_str);
uint16_t moving_avarage(uint16_t data);
void basket_alg(icd_str * icd_str);

void hv_charge(icd_str * icd_str);
//функция плавного разряда Конденсатора
void hv_discharge(icd_str * icd_str);
//функция резкого разряда
void hv_shock(icd_str * icd_str);

void terapy_algorithm(icd_str * icd_str);
void hv_pwm(bool state);


#endif
