{
return (CY_SYSCLK_BAD_PARAM);
}
if(outputDiv == NULL)
{
return (CY_SYSCLK_BAD_PARAM);
}
if ((targetOutFreq < lim->minFoutput) || (lim->maxFoutput < targetOutFreq))
{
return (CY_SYSCLK_BAD_PARAM);
}
/* REFERENCE_DIV selection */
for (uint32_t i_refDiv = lim->minRefDiv; i_refDiv <= lim->maxRefDiv; i_refDiv++)
{
uint32_t fpd_roundDown = inFreq / i_refDiv;
if (fpd_roundDown < lim->minFpd)
{
break;
}
uint32_t fpd_roundUp = CY_SYSCLK_DIV_ROUNDUP(inFreq, i_refDiv);
if (lim->maxFpd < fpd_roundUp)
{
continue;
}
/* OUTPUT_DIV selection */
for (uint32_t i_outDiv = lim->minOutputDiv; i_outDiv <= lim->maxOutputDiv; i_outDiv++)
{
uint64_t tempVco = i_outDiv * targetOutFreq;
if(tempVco < lim->minFvco)
{
continue;
}
else if(lim->maxFvco < tempVco)
{
break;
}
// (inFreq / refDiv) * feedBackDiv = Fvco
// feedBackDiv = Fvco * refDiv / inFreq
uint64_t tempFeedBackDivLeftShifted = ((tempVco << (uint64_t)fracBitNum) * (uint64_t)i_refDiv) /
(uint64_t)inFreq;
uint64_t error = abs(((uint64_t)targetOutFreq << (uint64_t)fracBitNum) - ((uint64_t)inFreq *
tempFeedBackDivLeftShifted / ((uint64_t)i_refDiv * (uint64_t)i_outDiv)));
if (error < errorMin)
{
*feedBackDiv = (uint32_t)(tempFeedBackDivLeftShifted >> (uint64_t)fracBitNum);
if(feedBackFracDiv != NULL)
{
if(fracBitNum == 0ul)
{
*feedBackFracDiv = 0ul;
}
else
{
*feedBackFracDiv = (uint32_t)(tempFeedBackDivLeftShifted & ((1ull << (uint64_t)fracBitNum) -
1ull));
}
}
*refDiv = i_refDiv;
*outputDiv = i_outDiv;
errorMin = error;
if(errorMin == 0ull){break;}
}
}
if(errorMin == 0ull){break;}
}
if(errorMin == 0xFFFFFFFFFFFFFFFFull)
{
return (CY_SYSCLK_BAD_PARAM);
}
else
{
return (CY_SYSCLK_SUCCESS);
}
}