#pragma once

#include "FreeRTOS.h"
#include "event_groups.h"
#include "avr/io.h"
#include "avr/interrupt.h"
#include "stdlib.h"
#include "stdint.h"
#include "string.h"
#include "stdbool.h"
#include "stdio.h"

#ifdef __cplusplus
extern "C"
{
#endif

	typedef enum
	{
		AVR_FAIL = -1,
		AVR_OK,
		AVR_ERR_NO_MEM,
		AVR_ERR_INVALID_ARG,
		AVR_ERR_INVALID_STATE,
		AVR_ERR_INVALID_SIZE,
		AVR_ERR_NOT_FOUND,
		AVR_ERR_NOT_SUPPORTED,
		AVR_ERR_TIMEOUT,
		AVR_ERR_INVALID_RESPONSE,
		AVR_ERR_INVALID_CRC,
		AVR_ERR_INVALID_VERSION,
		AVR_ERR_NOT_FINISHED,
		AVR_ERR_NOT_ALLOWED
	} avr_err_t;

	avr_err_t zh_avr_i2c_master_init(const bool pullup);
	avr_err_t zh_avr_i2c_master_probe(const uint8_t addr, TickType_t xTicksToWait);
	avr_err_t zh_avr_i2c_master_transmit(const uint8_t addr, uint8_t *data, uint8_t size, size_t delay);
	avr_err_t zh_avr_i2c_master_receive(const uint8_t addr, uint8_t *data, uint8_t size, size_t delay);
	avr_err_t zh_avr_i2c_master_transmit_receive(const uint8_t addr, uint8_t *write_data, uint8_t write_size, uint8_t *read_data, uint8_t read_size, size_t delay);

#ifdef __cplusplus
}
#endif

#ifndef IICULTIMATE_H
#define IICULTIMATE_H


// #include <avrlibtypes.h>
// #include <avrlibdefs.h>

#define i2c_PORT PORTC // Порт где сидит нога TWI
#define i2c_DDR DDRC
#define i2c_SCL 0 // Биты соответствующих выводов
#define i2c_SDA 1

#define i2c_MasterAddress 0x32 // Адрес на который будем отзываться
#define i2c_i_am_slave 1	   // Если мы еще и слейвом работаем то 1. А то не услышит!

#define i2c_MasterBytesRX 1 // Величина принимающего буфера режима Slave, т.е. сколько байт жрем.
#define i2c_MasterBytesTX 1 // Величина Передающего буфера режима Slave , т.е. сколько байт отдаем за сессию.

#define i2c_MaxBuffer 3		  // Величина буфера Master режима RX-TX. Зависит от того какой длины строки мы будем гонять
#define i2c_MaxPageAddrLgth 2 // Максимальная величина адреса страницы. Обычно адрес страницы это один или два байта.
							  // Зависит от типа ЕЕПРОМ или другой микросхемы.

#define i2c_type_msk 0b00001100 // Маска режима
#define i2c_sarp 0b00000000		// Start-Addr_R-Read-Stop  							Это режим простого чтения. Например из слейва или из епрома с текущего адреса
#define i2c_sawp 0b00000100		// Start-Addr_W-Write-Stop 							Это режим простой записи. В том числе и запись с адресом страницы.
#define i2c_sawsarp 0b00001000	// Start-Addr_W-WrPageAdr-rStart-Addr_R-Read-Stop 	Это режим с предварительной записью текущего адреса страницы

#define i2c_Err_msk 0b00110011 // Маска кода ошибок
#define i2c_Err_NO 0b00000000  // All Right! 						-- Все окей, передача успешна.
#define i2c_ERR_NA 0b00010000  // Device No Answer 				-- Слейв не отвечает. Т.к. либо занят, либо его нет на линии.
#define i2c_ERR_LP 0b00100000  // Low Priority 					-- нас перехватили собственным адресом, либо мы проиграли арбитраж
#define i2c_ERR_NK 0b00000010  // Received NACK. End Transmittion. -- Был получен NACK. Бывает и так.
#define i2c_ERR_BF 0b00000001  // BUS FAIL 						-- Автобус сломался. И этим все сказано. Можно попробовать сделать переинициализацию шины

#define i2c_Interrupted 0b10000000	 // Transmiting Interrupted		Битмаска установки флага занятости
#define i2c_NoInterrupted 0b01111111 // Transmiting No Interrupted	Битмаска снятия флага занятости

#define i2c_Busy 0b01000000 // Trans is Busy				Битмаска флага "Передатчик занят, руками не трогать".
#define i2c_Free 0b10111111 // Trans is Free				Битмаска снятия флага занятости.

#define MACRO_i2c_WhatDo_MasterOut (MasterOutFunc)(); // Макросы для режимо выхода. Пока тут функция, но может быть что угодно
#define MACRO_i2c_WhatDo_SlaveOut (SlaveOutFunc)();
#define MACRO_i2c_WhatDo_ErrorOut (ErrorOutFunc)();

typedef void (*IIC_F)(void); // Тип указателя на функцию

extern IIC_F MasterOutFunc; // Подрбрости в сишнике.
extern IIC_F SlaveOutFunc;
extern IIC_F ErrorOutFunc;

extern uint8_t i2c_Do;
extern uint8_t i2c_InBuff[i2c_MasterBytesRX];
extern uint8_t i2c_OutBuff[i2c_MasterBytesTX];

extern uint8_t i2c_SlaveIndex;

extern uint8_t i2c_Buffer[i2c_MaxBuffer];
extern uint8_t i2c_index;
extern uint8_t i2c_ByteCount;

extern uint8_t i2c_SlaveAddress;
extern uint8_t i2c_PageAddress[i2c_MaxPageAddrLgth];

extern uint8_t i2c_PageAddrIndex;
extern uint8_t i2c_PageAddrCount;

void Init_i2c(void);
void Init_Slave_i2c(IIC_F Addr);

extern uint8_t WorkLog[100];
extern uint8_t WorkIndex;

#endif