/********************************************************* * 
@file		:spi_common.c 
@brief  	:common interface source file,store some common interface functions 
@author 	:zhongfeng
@version	:v1.0 
@date 		:19/10/31
Copyright (C) 2019 Panchip Technology Corp. All rights reserved. 
***********************************************************/
#include "pan271x.h"
#include "otp_common.h"

void OTP_PrintReadSampleInfo(void)
{
    SYS_TEST("\n");
    SYS_TEST("+------------------------------------------------------------------+ \r\n");
    SYS_TEST("|                      PAN271 OTP Read Sample Code.                | \r\n");
    SYS_TEST("+------------------------------------------------------------------+ \r\n");
    SYS_TEST("|    press key to start test                                       | \r\n");
    SYS_TEST("|    Input'0'   OTP_ReadMainArea();                                | \r\n");
    SYS_TEST("|    Input'1'   OTP_ReadRowArea();                                 | \r\n");
    SYS_TEST("|    Input'2'   OTP_ReadColArea();                                 | \r\n");
    SYS_TEST("|    Input'3'   OTP_ReadByTrChanged();                             | \r\n");
    SYS_TEST("|    Input'4'   OTP_ReadAny();                                     | \r\n");
    SYS_TEST("|    Input'ECS' EXIT                                               | \r\n");
    SYS_TEST("+------------------------------------------------------------------+ \r\n");
}

static __ramfunc void TempFunc_ReadInit(uint8_t Ptm, bool ecc_en)
{
	uint32_t tmpreg;

	OTP->MODE_CTL = WORK_MODE_IDLE;
	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);
}

static __ramfunc void TempFunc_SwitchToOtpClk(uint8_t read2, uint8_t high_cycle, uint8_t low_cycle)
{
	uint32_t tmp_reg = PMU->SYS_CLK_CTRL;

	(read2) ? (tmp_reg &= ~SYS_CLK_CTRL_OTP_READ_MODE_SEL_Msk) : (tmp_reg |= SYS_CLK_CTRL_OTP_READ_MODE_SEL_Msk);
	tmp_reg &= ~(SYS_CLK_CTRL_OTP_CLK_HIGH_CYCLE_Msk | SYS_CLK_CTRL_OTP_CLK_LOW_CYCLE_Msk);
	tmp_reg |= ((high_cycle << SYS_CLK_CTRL_OTP_CLK_HIGH_CYCLE_Pos) | (low_cycle << SYS_CLK_CTRL_OTP_CLK_LOW_CYCLE_Pos));
	tmp_reg |= SYS_CLK_CTRL_OTP_SW_UP_CYCLE_EN_Msk;
	PMU->SYS_CLK_CTRL = tmp_reg;
}

void OTP_ReadByTrChanged(uint8_t *buf, uint32_t adr, uint32_t len)
{
	TempFunc_SetTrTrim(0x0 << 6);
	TempFunc_ReadInit(PTM_USER_MAIN_AREA_READ, DISABLE);
	OTP_ReadStream(adr, len, buf);
	data_printf(buf, len);

	TempFunc_SetTrTrim(0x1 << 6);
	TempFunc_ReadInit(PTM_USER_MAIN_AREA_READ, DISABLE);
	OTP_ReadStream(adr, len, buf);
	data_printf(buf, len);

	TempFunc_SetTrTrim(0x2 << 6);
	TempFunc_ReadInit(PTM_USER_MAIN_AREA_READ, DISABLE);
	OTP_ReadStream(adr, len, buf);
	data_printf(buf, len);
	
	TempFunc_SetTrTrim(0x3 << 6);
	TempFunc_ReadInit(PTM_USER_MAIN_AREA_READ, DISABLE);
	OTP_ReadStream(adr, len, buf);
	data_printf(buf, len);
}

__ramfunc void OTP_ReadAny(uint16_t tr_trim,
				uint8_t ptm,
				bool ecc_en,
				uint32_t adr,
				uint32_t sz,
				uint8_t *buf)
{
	uint32_t idx = 0;

	if ((ptm == PTM_USER_MAIN_AREA_READ2) || (ptm == PTM_TEST_MAIN_AREA_WEAK_READ2) || (ptm == PTM_TEST_MAIN_AREA_MARGAIN_READ2)
		|| (ptm == PTM_TEST_ROW_READ2) || (ptm == PTM_TEST_ROW_WEAK_READ2) || (ptm == PTM_TEST_ROW_MARGAIN_READ2)
		|| (ptm == PTM_TEST_COL_READ2) || (ptm == PTM_TEST_COL_WEAK_READ2) || (ptm == PTM_TEST_COL_MARGAIN_READ2)
	) {
		TempFunc_SwitchToOtpClk(1, 1, 1);
	}
	TempFunc_SetTrTrim(tr_trim);
	TempFunc_ReadInit(ptm, ecc_en);
//	OTP_ReadStream(adr, sz, buf);

	if ((ptm == 0x04) || (ptm == 0x05) || (ptm == 0x06)
		|| (ptm == 0x14) || (ptm == 0x15) || (ptm == 0x16))
	{
		for(idx = 0; idx < sz; idx++) {
			ReadColumn(adr+idx, buf+idx);
		}
	} else {
		for(idx = 0; idx < sz; idx +=4) {
			OTP_ReadWord(adr+idx, buf+idx);
		}
	}
	data_printf(buf, sz);
	TempFunc_SwitchToOtpClk(0, 0, 0);
}

void PrintReadCmd(void)
{
	SYS_TEST("MAIN_READ               (0X00)\n");
	SYS_TEST("MAIN_READ2              (0X10)\n");
	SYS_TEST("MAIN_WEAK_READ          (0X01)\n");
	SYS_TEST("MAIN_WEAK_READ2         (0X11)\n");
	SYS_TEST("MAIN_MARGAIN_READ       (0X02)\n");
	SYS_TEST("MAIN_MARGAIN_READ2      (0X12)\n");
	SYS_TEST("--------------------------------------------\n");
	SYS_TEST("ROW_READ                     (0X08)\n");
	SYS_TEST("ROW_READ2                    (0X18)\n");
	SYS_TEST("ROW_WEAK_READ                (0X09)\n");
	SYS_TEST("ROW_WEAK_READ2               (0X19)\n");
	SYS_TEST("ROW_MARGAIN_READ             (0X0A)\n");
	SYS_TEST("ROW_MARGAIN_READ2            (0X1A)\n");
	SYS_TEST("--------------------------------------------\n");
	SYS_TEST("COL_READ                     (0X04)\n");
	SYS_TEST("COL_READ2                    (0X14)\n");
	SYS_TEST("COL_WEAK_READ                (0X05)\n");
	SYS_TEST("COL_WEAK_READ2               (0X15)\n");
	SYS_TEST("COL_MARGAIN_READ             (0X06)\n");
	SYS_TEST("COL_MARGAIN_READ2            (0X16)\n");
}


uint32_t OTP_ReadTest(void)
{
	char s[6];
	uint8_t buf[32];
	uint16_t tr_trim;
	uint8_t ptm;
	bool ecc_en;
	uint32_t adr;

	memset(buf, 0, sizeof(buf));

	SYS_TEST("Input tr trim u want, value will change to hex\n");
	gets(s);
	tr_trim = strtol(s, NULL, 16);
	SYS_TEST("tr trim is %x\n", tr_trim);
	SYS_TEST("\r\nInput ptm u want\n");
	PrintReadCmd();
	gets(s);
	ptm = strtol(s, NULL, 16);
	SYS_TEST("ptm is %x\n", ptm);
	SYS_TEST("\r\nInput ecc_en u want\n");
	gets(s);
	ecc_en = (bool)strtol(s, NULL, 16);
	SYS_TEST("ecc is %x\n", ecc_en);
	SYS_TEST("\r\nInput adr u want\n");
	gets(s);
	adr = strtol(s, NULL, 16);
	SYS_TEST("adr is %x\n", adr);
	if (adr > 0x4000) {
		SYS_TEST("Input adr is too bigger \n");
	}
	OTP_ReadAny(tr_trim, ptm, ecc_en, adr, 32, buf);
    return 0;
}
