/**************************************************************************//**
 * @file     pan_otp.c
 * @version  V1.00
 * $Revision: 2 $
 * $Date: 19/10/28 16:08 $ 
 * @brief    Panchip series otp driver source file
 *
 * @note
 * Copyright (C) 2025 Panchip Technology Corp. All rights reserved.
 *****************************************************************************/ 
#include "pan271x.h"
#include "pan_otp.h"

void OTP_ReadInit(uint8_t Ptm, bool ecc_en)
{
	uint32_t tmpreg;

	OTP->READ_PROG_CTL = (OTP->READ_PROG_CTL & ~(0X1F << 4)) | (Ptm << 4);
	tmpreg = OTP->MODE_CTL;
	tmpreg = (tmpreg & ~WORK_MODE_IDLE) | WORK_MODE_READ;
	OTP->MODE_CTL = tmpreg;
	(ecc_en) ? (OTP->READ_PROG_CTL &= ~READ_PROG_CTL_ECC_DISABLE_Msk) : (OTP->READ_PROG_CTL |= READ_PROG_CTL_ECC_DISABLE_Msk);
}

void OTP_ReadWord(uint32_t Addr, uint8_t *buf)
{
	uint32_t read_value = 0;

	OTP->BYTE_ADDR = Addr;
	OTP->OPERATE_TRG |= 0X1;
	while(OTP->OPERATE_TRG) {}
	read_value = OTP->OPERATE_DATA_0;
	*buf = read_value & 0xff;
	buf++;
	*buf = (read_value & 0xff00) >> 8;
	buf++;
	*buf = (read_value & 0xff0000) >> 16;
	buf++;
	*buf = (read_value & 0xff000000) >> 24;
	buf++;
}

void OTP_WriteInit(uint8_t Ptm, bool ecc_en)
{
	OTP->READ_PROG_CTL = (OTP->READ_PROG_CTL & ~(0X1F << 4)) | (Ptm << 4);
	OTP->MODE_CTL = (OTP->MODE_CTL & ~WORK_MODE_IDLE) | WORK_MODE_WRITE;
	(ecc_en) ? (OTP->READ_PROG_CTL &= ~READ_PROG_CTL_ECC_DISABLE_Msk) : (OTP->READ_PROG_CTL |= READ_PROG_CTL_ECC_DISABLE_Msk);
}

void OTP_WriteWord(uint32_t Addr, uint8_t *buf)
{
	uint32_t w_data;

	OTP->BYTE_ADDR = Addr;
	w_data = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | (buf[0]);
	OTP->OPERATE_DATA_0 = w_data;
	OTP->OPERATE_TRG |= 0X1;
	while(OTP->OPERATE_TRG) {}
	buf+=4;
}

void OTP_ReadStream(uint32_t adr, uint32_t sz, uint8_t *buf) 
{
	uint32_t idx = 0;

	for(idx = 0; idx < sz; idx +=4) {
		OTP_ReadWord(adr+idx, buf+idx);
	}
}

int8_t OTP_WriteStream(uint32_t adr, uint32_t sz, uint8_t *buf) 
{
	uint32_t idx = 0;

//	((uint8_t*)(&adr))[3] = 0x02;

	for(idx = 0; idx < sz; idx +=4) 
	{
		OTP_WriteWord(adr+idx, buf+idx);
	}

	return 0;
}

uint32_t OTP_Verify(uint32_t adr, uint32_t sz, uint8_t *buf)
{
	uint32_t idx = 0;
	uint8_t count, read_value[4];

	for(idx = 0; idx < sz; idx +=4) 
	{
		OTP_ReadWord(adr+idx, read_value);
		if (idx+4 <= sz) {
			if(*((__I uint32_t*)read_value) != *((__I uint32_t*)(buf+idx))){
				return adr+idx+1;
			}
		} else {
			for(count = 0; count < sz - idx; count++) {
				if(read_value[count] != buf[idx+count]) {
					return adr+idx+count+1;
				}
			}
		}
	}
	return 0;
}
