/*
 * File:			SigmaStudioFW.h
 *
 * Description:  	SigmaStudio System Framwork macro definitions. These
 *				macros should be implemented for your system's software.
 *
 * This software is distributed in the hope that it will be useful,
 * but is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 * CONDITIONS OF ANY KIND, without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 * This software may only be used to program products purchased from
 * Analog Devices for incorporation by you into audio products that
 * are intended for resale to audio product end users. This software
 * may not be distributed whole or in any part to third parties.
 *
 * Copyright � 2008 Analog Devices, Inc. All rights reserved.
 */

#ifndef __SIGMASTUDIOFW_H__
#define __SIGMASTUDIOFW_H__

#include <stdint.h>
#include <inttypes.h>
#include "esp_log.h"
#include "driver/i2c.h"
#include "H2201_i2c.h"

/*
 * TODO: Update for your system's data type
 */
typedef unsigned short ADI_DATA_U16;
typedef unsigned char ADI_REG_TYPE;

#define Address_Length 2
void SIGMA_WRITE_REGISTER(uint8_t devAddress, uint16_t address, ADI_REG_TYPE data);
void SIGMA_WRITE_REGISTER_BLOCK(uint8_t devAddress, uint16_t address, int length, ADI_REG_TYPE *pData);
void SIGMA_WRITE_DELAY(int devAddress, int length, ADI_REG_TYPE *pData);

/*
 * Parameter data format
 */
#define SIGMASTUDIOTYPE_FIXPOINT 0
#define SIGMASTUDIOTYPE_INTEGER 1

/*
 * Write to a single Device register
 */
void SIGMA_WRITE_REGISTER(uint8_t devAddress, uint16_t address, ADI_REG_TYPE data)
{
	i2c_cmd_handle_t cmd = i2c_cmd_link_create();
	i2c_master_start(cmd);
	i2c_master_write_byte(cmd, devAddress, true); // write address 0x70
	i2c_master_write_byte(cmd, (address >> 8), true);
	i2c_master_write_byte(cmd, (address & 0xFF), true);

	i2c_master_write_byte(cmd, data, true);

	i2c_master_stop(cmd);
	esp_err_t err = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 10 / portTICK_PERIOD_MS);
	if (err != ESP_OK)
	{
		ESP_LOGE(H2201_I2C_TAG, "ADAU1761 block write failed. code: 0x%.2X", err);
	}

	i2c_cmd_link_delete(cmd);
}

/*
 * Write to multiple Device registers
 */
void SIGMA_WRITE_REGISTER_BLOCK(uint8_t devAddress, uint16_t address, int length, ADI_REG_TYPE *pData)
{
	// SIGMA_WRITE_REGISTER_BLOCK(DEVICE_ADDR_IC1, REG_SAMPLE_RATE_SETTING_IC1_ADDR, REG_SAMPLE_RATE_SETTING_IC1_BYTE, R0_SAMPLE_RATE_SETTING_IC1_Default);
	//									0x70         		0x40EB								1							0x7F

	i2c_cmd_handle_t cmd = i2c_cmd_link_create();
	i2c_master_start(cmd);
	i2c_master_write_byte(cmd, devAddress, true); // write address 0x70
	i2c_master_write_byte(cmd, (address >> 8), true);
	i2c_master_write_byte(cmd, (address & 0xFF), true);
	i2c_master_write(cmd, pData, length, true);
	i2c_master_stop(cmd);
	esp_err_t err = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 10 / portTICK_PERIOD_MS);
	if (err != ESP_OK)
	{
		ESP_LOGE(H2201_I2C_TAG, "ADAU1761 block write failed. code: 0x%.2X", err);
	}

	i2c_cmd_link_delete(cmd);
}

void SIGMA_WRITE_DELAY(int devAddress, int length, ADI_REG_TYPE *pData)
{
	if (length == 1)
	{
		const TickType_t xDelay = *pData / portTICK_PERIOD_MS;
		vTaskDelay(xDelay);
	}
	if (length == 2)
	{
		uint16_t delay = (pData[0] << 8) | (pData[1] << 0);
		const TickType_t xDelay = delay / portTICK_PERIOD_MS;
		vTaskDelay(xDelay);
	}

	// uint32_t delay;
	// for (size_t i = 0; i < length; i++)
	// {
	// 	/* code */
	// }

	// // Block for 500ms.
	// const TickType_t xDelay = 500 / portTICK_PERIOD_MS;
	// vTaskDelay(xDelay);

	//	int cnt=0;
	// int nCount = 0;
	// int data_length = length - Address_Length;
	//	ADI_REG_TYPE data[4]={0x05, 0xF5, 0xE1, 0x00};
	//	for(cnt=0; cnt<data_length; cnt++)
	//	{
	//		nCount &= pData[cnt] >> (8*cnt);
	//	}
	//	for(cnt=0; cnt<4; cnt++)
	//	{
	//		nCount +=  data[cnt];
	//		nCount = nCount<<(8);
	//
	//	}
	// nCount=0xFFFFFF;
	// nCount=0x15752A00;	 //5 secs approx
	// nCount=0x05F5E100;	 //5 secs approx
	// nCount = 0xFFFFF;
	// for (; nCount != 0; nCount--)
	//	;
}

/*
 * Read device registers
 */
#define SIGMA_READ_REGISTER(devAddress, address, length, pData) \
	{ /*TODO: implement macro or define as function*/           \
	}

/*
 * Set a register field's value
 */
#define SIGMA_SET_REGSITER_FIELD(regVal, fieldVal, fieldMask, fieldShift)                        \
	{                                                                                            \
		(regVal) = (((regVal) & (~(fieldMask))) | (((fieldVal) << (fieldShift)) && (fieldMask))) \
	}

/*
 * Get the value of a register field
 */
#define SIGMA_GET_REGSITER_FIELD(regVal, fieldMask, fieldShift) \
	{                                                           \
		((regVal) & (fieldMask)) >> (fieldShift)                \
	}

/*
 * Convert a floating-point value to SigmaDSP (5.23) fixed point format
 *    This optional macro is intended for systems having special implementation
 *    requirements (for example: limited memory size or endianness)
 */
#define SIGMASTUDIOTYPE_FIXPOINT_CONVERT(_value) \
	{ /*TODO: IMPLEMENT MACRO*/                  \
	}

/*
 * Convert integer data to system compatible format
 *    This optional macro is intended for systems having special implementation
 *    requirements (for example: limited memory size or endianness)
 */
#define SIGMASTUDIOTYPE_INTEGER_CONVERT(_value) \
	{ /*TODO: IMPLEMENT MACRO*/                 \
	}

#endif
