#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 F412

#define RA_CHANNEL 1
#define RV_CHANNEL 2
#define LV_CHANNEL 3

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

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

#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 2.0
#define MAX_TRES 10.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				500
#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				10
#define	MAX_ENERGY				100
//сколько шагов должно быть в терапии
#define	HV_STEP_NUM				1
//время в мс когда мы слепы
#define	HV_BLIND_TIME_MS		1500
// размер буффера редетекции
#define	REDET_BUF_LEN			8
// сколько нужно плохих периодов для продолжения терапии
#define	REDET_BAD_MAX			4

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

// минимальное и максимальное кол-во импульсов в пачке
#define	BURST_CNT_MIN			5
#define	BURST_CNT_MAX			50

// минимальное и максимальное напряжение стимуляции в burst режиме
#define	BURST_VOLTAGE_MIN		10
#define	BURST_VOLTAGE_MAX		80

// минимальный и максимальный период следования импульсов в burst режиме
#define	BURST_PERIOD_MIN		150
#define	BURST_PERIOD_MAX		500

#define	BURST_PERIOD_MIN_F		150.0
#define	BURST_PERIOD_MAX_F		500.0

#define CHARDE_TONE				120
#define READY_TONE				100
#define SHOCK_TONE				80
#define NO_TONE					0
typedef enum
{
    Monitor 	= 0,  // Тупо смотрим
    Normal 		= 1,  // поиск порогов и терапия
    Force 		= 2  // только терапия похуй на сигнал
}	main_mode;


typedef enum
{
    low 		= 0,  // активен нижний ключ
	high 		= 1,  // активен верхний ключ
    z_state 	= 2   // оба неактивны
}	half_br;


//режим поиска пиков 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;

//конфигурация высоковольтных электродов
typedef enum
{
    rv_neg_scv_poz 		= 0,  // Электрод RV отрицательный SCV положительный
	rv_neg_can_poz		= 1,  // Электрод RV отрицательный корпус прибора положительный
	rv_neg_scv_can_poz 	= 2,  // Электрод RV отрицательный SCV и корпус прибора положительный
}	hv_polarity;

//тип высоковольтной стимуляции
typedef enum
{
    hv_mode_fixed 		= 0,  // стимуляция идёт согласно заданному времени
	hv_mode_adaptive	= 1,  // стимуляция идёт согласно заданным процентам, но не более 2 длительностей фаз
	hv_mode_mixed		= 2,  // Электрод RV отрицательный SCV и корпус прибора положительный//fixme надо подумать
}	hv_mode;

//полярность низковольтной стимуляции
typedef enum
{
    lv_mono 	= 0,  // стимуляция идёт между выводами tip-can
	lv_bipolar	= 1  // стимуляция идёт между выводами tip-coil
}	lv_polarity;

//режим низковольтной стимуляции
typedef enum
{
    lv_mode_none 	= 0, //без стимуляции
	lv_mode_BURST 	= 1, //режим для вызова фибрилляции  после отработки пачки сбрасывается в lv_mode_none
	lv_mode_VOO		= 2, //стимуляция идёт независимо от активности сердца Желудочка
	lv_mode_VVI		= 3//, //стимуляция ингибируется при активности сердца Желудочка
//	lv_mode_VVT		= 4, //стимуляция активизируется при активности сердца Желудочка
//	lv_mode_VVIR	= 5, //как VVI, но порог чсс зависит отдвигательной активности Желудочка
//	lv_mode_AOO		= 6, //стимуляция идёт независимо от активности сердца Предсердия
//	lv_mode_AAI		= 7, //стимуляция ингибируется при активности сердца Предсердия
//	lv_mode_AAT		= 8, //стимуляция активизируется при активности сердца Предсердия
//	lv_mode_AAIR	= 9, //как VVI, но порог чсс зависит отдвигательной активности Предсердия
}	lv_mode;

//подрежим низковольтной стимуляции
typedef enum
{
	lv_sub_free 		= 0, //Свободный без всякого вмешательства tip и coil свободны разряда\заряда не происходит
	lv_sub_charge		= 1, //Заряд без всякого вмешательства tip и coil идёт заряд
	lv_sub_shock		= 2, //Разряд coil на землю притягиваем tip к конденсатору заряда нет
	lv_sub_relax 		= 3, //Релаксация tip и coil притянуты к земле
	lv_sub_discharge	= 4  //Разряд без всякого вмешательства tip и coil свободны идёт разряд(необязательный режим)
}	lv_sub_mode;


//тип для 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;

	//новое про низкое напряжение
	bool lv_start; //начало стимуляции
	////////////////////////////////////////////////////////////////////////////////////////////
	lv_polarity lv_polarity;//полярность низковольтной стимуляции
	lv_mode lv_mode;//режим низковольтной стимуляции

	uint8_t lv_shock_time;//время импульса низковольной стимуляции 1-20(0,1-2мс) одна единица 0,1мс шаг 0.1мс
	uint8_t lv_relax_time;//время стабилизации после удара низковольной стимуляции 0-20(0-20мс) одна единица 1мс шаг 1мс
	uint8_t lv_voltage;//какое напряжение у импульсов 10-80(1,0-8,0В) одна единица 0,1В шаг 0,1В

	//bool BURST_active;//параметр вводящий нас в режим burst посылка пачки импульсов для вызова фибрилляции
	uint8_t burst_cnt;//сколько импульсов в одной пачке 5-50 одна единица 1 импульс шаг 1 импульс
	uint8_t burst_voltage;//какое напряжение у импульсов 10-80(1,0-8,0В) одна единица 0,1В шаг 0,1В
	uint16_t burst_period;//период следования импульсов в мс 150-500мс одна единица 1мс шаг 10 мс на ползунке
	uint16_t burst_end_period;//конечный период следования импульсов в мс 150-500мс одна единица 1мс шаг 10 мс на ползунке

	//	Время в мс которое длится режим стимуляции низким напряжением
	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;// какой сейчас шаг?

	//новое про высокое напряжение
	//режимы стимуляции
	bool		hv_sound_accomp;//нужно ли звуковое сопровождение при заряде и ударе
	hv_polarity	hv_polarity;//полярность стимуляции
	hv_mode		hv_mode;//тип способа задания длительности импульса
	//время константы времени стимуляции
	uint8_t		hv_phase_1_duration;// время в десятых мс приходящееся на 1 фазу 30-120(3-12мс) одна единица 0,1мс
	uint8_t		hv_phase_2_duration;// время в десятых мс приходящееся на 2 фазу 20-100(2-10мс) одна единица 0,1мс
	uint8_t		hv_switch_duration;// время в десятых мс приходящееся на переключение между фазами 10-30(1-3мс) одна единица 0,1мс
	//процентные параметры стимуляции
	uint8_t		hv_switching_voltage;//процент напряжения при котором происходит завешение 1 фазы при адаптивном режиме (20-80) одна единица 1%
	uint8_t		hv_cutoff_voltage;//процент напряжения при котором происходит завешение 2 фазы при адаптивном режиме (5-50) одна единица 1%

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


	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);
bool quick_analyse(icd_str * icd_str);


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

void terapy_algorithm(icd_str * icd_str);
void hv_pwm(bool state);
void hv_sound(uint32_t presc);

//управление защитными реле
void relay_all_control(bool RV_safe,bool RA_safe,bool CAN_safe);
void relay_ra_control(bool RA_safe);
void relay_rv_control(bool RV_safe);
void relay_can_control(bool CAN_safe);
//управление ключами
void hv_ll_control(half_br state_RV, half_br state_SCV, half_br state_CAN);
void hv_power(bool state);
void hv_ll_rv_control(half_br state);
void hv_ll_scv_control(half_br state);
void hv_ll_can_control(half_br state);


void ll_h_off(void);
void ll_h_1_side(half_br state);
void ll_h_2_side(half_br state);
void ll_bi_dis(void);
void ll_bi_shock_param(icd_str * icd_str);

void ra_lv_control(icd_str * icd_str,lv_sub_mode mode);
void rv_lv_control(icd_str * icd_str,lv_sub_mode mode);

void one_stimul(icd_str *icd_str);
void burst(icd_str *icd_str);

void hv_en_control(bool en_RV, bool en_SCV, bool en_CAN);
void hv_en_rv(bool state);
void hv_en_scv(bool state);
void hv_en_can(bool state);

void delay_critical(uint8_t delay);
#endif
