#ifndef AD0X0_I2C_H
#define AD0X0_I2C_H

#include "main.h"


// ************************** I2C Configuration Variables **************************

/* definition of fast or default standard mode (bus speed up to 400 or 100 kHz) */
#define AD0X0_I2C_EXT_COUNT 32
//#define FAST_I2C_MODE
#define AD0X0_FIFO_COUNT 32
    
#define AD0X0_I2C_DBG
/* definition of 10-bit or default 7-bit slave address */
//#define TEN_BITS_ADDRESS

/* uncomment next line when stop request is required between device address sent and read data */
//#define NO_RESTART

#ifdef TEN_BITS_ADDRESS
#define SLAVE_ADDRESS  0x3F0
#else
#define SLAVE_ADDRESS  0x3C
#endif
/*
очередь - кольцевой бл. буфер с командами и данными для моего движка i2c на прер-ях
В общем теория с очердью такая: мы можем их разные делать для разной отрисовки, 
для чтения гироскопа... метить cbyte |=0x80 и подсовывать когда надо на обработку..
Можно так же перескоки с очереди на очередь предусмотреть, типа дочитал гироскоп, погнал рисовать 
на экране. С экраном вообще надо сделать чтобы коды символов передавались, а он их писАл пачками
за один старт-рестарт-данные стоп.
*/

//#undef AD0X0_I2C_DBG_CO
//2do переделать нахер под тайпдеф
//ADQ_ это замена ad0x0_queue_ - это б писанина излишняя
typedef enum{
	/*ADQ_START_ADDR           = (uint8_t)0x1,
	ADQ_STOP                 = (uint8_t)0x2,
	ADQ_TX                   = (uint8_t)0x0,
	ADQ_TX_STOP              = (uint8_t)0x4,
	ADQ_TX_LRB_STOP          = (uint8_t)0xA,
	ADQ_RX_STOP              = (uint8_t)0x5,
	ADQ_RX_PBUF_STOP_EXT     = (uint8_t)0xB, //прочитать в пбуф. кол-во cbyte
	ADQ_TX_PBUF_STOP_EXT		 = (uint8_t)0x8,*/
	ADQ_USE_EXT           = (uint8_t)0x6, //[15:8]
	ADQ_HAL_ADDR_TX_BUF_SEQ_FIRST_EXT       = (uint8_t)0xE, 
	ADQ_HAL_ADDR_RX_BUF_SEQ_FIRST_EXT       = (uint8_t)0xF, 
	//ADQ_HAL_ADDR_TX_BUF_SEQ_LAST_EXT       = (uint8_t)0x10, 
	ADQ_HAL_ADDR_RX_BUF_SEQ_LAST_EXT       = (uint8_t)0x11, 
	ADQ_HAL_ADDR_TX_BUF_STOP_EXT					 = (uint8_t)0x12, 	
	ADQ_DBG_XXX           = (uint8_t)0xD, //[7:0]
//	ADQ_LRB_MODIFY_APPLY_MASK    = (uint8_t)0xC, //прочитанный байт &= cbyte
//	ADQ_LRB_MODIFY_APPLY_OR      = (uint8_t)0x7, //прочитанный байт |= cbyte
	ADQ_DELAY_MS             = (uint8_t)0x9,
	ADQ_PROCESSED          = (uint8_t)0x40,//6й бит
	ADQ_EMPTY		          = (uint8_t)0x80 //7й бит
} ADQ_t;

/*#define AD_START_ADDR           0x1
#define AD_STOP                 0x2
#define AD_TX                   0x0
#define AD_TX_STOP              0x4
#define AD_TXLAST_STOP          0x8
#define AD_RX_STOP              0x5
#define AD_RX_PBUF_STOP         0xB //прочитать в пбуф. кол-во cbyte
#define AD_SET_PBUF_H           0xC //[15:8]
#define AD_SET_PBUF_L           0xD //[7:0]
#define AD_SET_PBUF_HH           0xE //[31:24] блин ну адреса 0x4000, 0x2000 в зависимости от типа памяти
#define AD_SET_PBUF_HL           0xF //[23:16] в общем пока делаю весь указатель (ad0x0 23082020)
#define AD_MODIFY_APPLY_MASK    0x6 //прочитанный байт &= cbyte
#define AD_MODIFY_APPLY_OR      0x7 //прочитанный байт |= cbyte
#define AD_DELAY_MS             0x9
#define AD_Q_PROCESSED          0x40//6й бит
#define AD_Q_EMPTY		          0x80//7й бит*/

//#define AD0X0_I2C2_DBG
#define AD_DBG_S1_Pin GPIO_PIN_1
#define AD_DBG_S1_GPIO_Port GPIOA
#ifdef AD0X0_I2C2_DBG
#define AD_I2C_INT_HIGH  AD_DBG_S1_GPIO_Port->ODR |= AD_DBG_S1_Pin;
#else
	#define AD_I2C_INT_HIGH ;
#endif
#ifdef AD0X0_I2C2_DBG
#define AD_I2C_INT_LOW  AD_DBG_S1_GPIO_Port->ODR &= ~AD_DBG_S1_Pin;
#else
	#define AD_I2C_INT_LOW ;
#endif
#ifdef AD0X0_I2C2_DBG
	#define ADDBG2_HIGH  AD_DBG_S2_GPIO_Port->ODR |= AD_DBG_S2_Pin;
#else
	#define ADDBG2_HIGH ;
#endif
#ifdef AD0X0_I2C2_DBG
	#define ADDBG2_LOW  AD_DBG_S2_GPIO_Port->ODR &= ~AD_DBG_S2_Pin;//*/
#else
	#define ADDBG2_LOW ;
#endif

/*void HAL_I2C_MasterRxCpltCallback (I2C_HandleTypeDef * hi2c){
	if(hi2c->Instance==hi2c1.Instance){
		ad0x0_i2c1_MasterRxCpltCallback();
	}else ad0x0_i2c2_MasterRxCpltCallback();
}
void HAL_I2C_MasterTxCpltCallback (I2C_HandleTypeDef * hi2c){
	if(hi2c->Instance==hi2c1.Instance){
		ad0x0_i2c1_MasterTxCpltCallback();
	}else ad0x0_i2c2_MasterTxCpltCallback();
}

void HAL_I2C_ErrorCallback (I2C_HandleTypeDef * hi2c){
	if(hi2c->Instance==hi2c1.Instance){
		ad0x0_i2c1_ErrorCallback();
	}else ad0x0_i2c2_ErrorCallback();
}

void HAL_I2C_AbortCpltCallback (I2C_HandleTypeDef * hi2c){
	if(hi2c->Instance==hi2c1.Instance){
		ad0x0_i2c1_AbortCpltCallback();
	}else ad0x0_i2c2_AbortCpltCallback();*/


// ************************* Function Declaration ***************************
struct ad0x0_i2c_cmd_s{	
  ADQ_t       ctype;//
	//u8 processed=ctypex & 0x40;//b 0100 0000
	//u8 dropped=ctypex & 0x80;//b 1000 0000
  uint8_t       cbyte;
  struct ad0x0_i2c_cmd_s *pnext;
#ifdef AD0X0_I2C_DBG_CO  
  uint8_t       co;
#endif  
};

typedef struct {	
/*	//u8 processed=ctypex & 0x40;//b 0100 0000
	//u8 dropped=ctypex & 0x80;//b 1000 0000*/
	I2C_TypeDef *i2cx;
	I2C_HandleTypeDef *phi2c;
	uint8_t addr_w,addr_r;
	uint8_t *rx_pbuf,*tx_pbuf;
	uint16_t pbuf_counter;//установочные
	volatile uint8_t *rx_pbuf_cur,*tx_pbuf_cur;//текущие
	uint16_t pbuf_counter_cur;
	uint8_t rx_last_byte;
	volatile void (*pfunc)(void);
	void (*perrfunc)(void);
	void (*pfunc_on_error)(void);
	void (*pfunc_on_i2c_restart)(void);
	uint8_t err_ovrflow;
	volatile uint8_t insint;
	volatile uint32_t last_hwi_process_tick;
	uint32_t last_hal_err;
	HAL_I2C_StateTypeDef last_hal_state;
	uint8_t is_i2c_restarting;
}ad0x0_i2c_desc_s;

#endif 
