660 lines
21 KiB
C
660 lines
21 KiB
C
/* V2MemTest - A CLI Tool to test & fix Voodoo² TMU System
|
|
* Copyright (C) 2026 ChaCha
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#define _BSD_SOURCE 1
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
#include <unistd.h>
|
|
#include <math.h>
|
|
|
|
#include "cvg.h"
|
|
#include <glide.h>
|
|
#include "sst1init.h"
|
|
#include "fxpci.h"
|
|
|
|
#include "FaultSources.h"
|
|
#include "Utils.h"
|
|
#include "Draw.h"
|
|
|
|
#include "Test_Common.h"
|
|
#include "Test_Data_Huge.h"
|
|
#include "Test_Data_NoMem.h"
|
|
|
|
extern const def_sTestPattern ar_sExpectedPattern_Test3[];
|
|
extern const unsigned int uNbPattern_Test3;
|
|
|
|
extern const def_sTestPattern ar_sExpectedPattern_Test3_Dither[];
|
|
extern const unsigned int uNbPattern_Test3_Dither;
|
|
|
|
extern const def_sFaultSourceLineMap ar_sFaultSourceLineMap[];
|
|
|
|
void DisplayPattern(const def_sTestPattern * const pREF)
|
|
{
|
|
printf("RGB: %04X %04X %04X %04X\n",
|
|
pREF->data.access.u16Pix[0][0],
|
|
pREF->data.access.u16Pix[0][1],
|
|
pREF->data.access.u16Pix[0][2],
|
|
pREF->data.access.u16Pix[0][3]);
|
|
printf("RGB: %04X %04X %04X %04X\n",
|
|
pREF->data.access.u16Pix[1][0],
|
|
pREF->data.access.u16Pix[1][1],
|
|
pREF->data.access.u16Pix[1][2],
|
|
pREF->data.access.u16Pix[1][3]);
|
|
printf("RGB: %04X %04X %04X %04X\n",
|
|
pREF->data.access.u16Pix[2][0],
|
|
pREF->data.access.u16Pix[2][1],
|
|
pREF->data.access.u16Pix[2][2],
|
|
pREF->data.access.u16Pix[2][3]);
|
|
printf("RGB: %04X %04X %04X %04X\n",
|
|
pREF->data.access.u16Pix[3][0],
|
|
pREF->data.access.u16Pix[3][1],
|
|
pREF->data.access.u16Pix[3][2],
|
|
pREF->data.access.u16Pix[3][3]);
|
|
|
|
printf("Alpha: %02X %02X %02X %02X\n",
|
|
pREF->data.access.u8APix[0][0],
|
|
pREF->data.access.u8APix[0][1],
|
|
pREF->data.access.u8APix[0][2],
|
|
pREF->data.access.u8APix[0][3]);
|
|
printf("Alpha: %02X %02X %02X %02X\n",
|
|
pREF->data.access.u8APix[1][0],
|
|
pREF->data.access.u8APix[1][1],
|
|
pREF->data.access.u8APix[1][2],
|
|
pREF->data.access.u8APix[1][3]);
|
|
printf("Alpha: %02X %02X %02X %02X\n",
|
|
pREF->data.access.u8APix[2][0],
|
|
pREF->data.access.u8APix[2][1],
|
|
pREF->data.access.u8APix[2][2],
|
|
pREF->data.access.u8APix[2][3]);
|
|
printf("Alpha: %02X %02X %02X %02X\n",
|
|
pREF->data.access.u8APix[3][0],
|
|
pREF->data.access.u8APix[3][1],
|
|
pREF->data.access.u8APix[3][2],
|
|
pREF->data.access.u8APix[3][3]);
|
|
}
|
|
|
|
// Returns the distance between A & B, normalized between 0 and 1.
|
|
// 0 means they are perfectly identicals.
|
|
// 1 means they are entirely diferents.
|
|
double ComputePatternDistance( const def_sTestPattern * const pA,
|
|
const def_sTestPattern * const pB)
|
|
{
|
|
double dDistance = 0;
|
|
logT("========================\n");
|
|
logT("Compare A|B:\n");
|
|
for (unsigned int i = 0; i <12; i=i+4)
|
|
{
|
|
logT("%08X\t%08X\n",pA->data.raw[i],pB->data.raw[i]);
|
|
logT("%08X\t%08X\n",pA->data.raw[i+1],pB->data.raw[i+1]);
|
|
logT("%08X\t%08X\n",pA->data.raw[i+2],pB->data.raw[i+2]);
|
|
logT("%08X\t%08X\n",pA->data.raw[i+3],pB->data.raw[i+3]);
|
|
dDistance += dComputeDistance32(pA->data.raw[i], pB->data.raw[i]);
|
|
dDistance += dComputeDistance32(pA->data.raw[i+1],pB->data.raw[i+1]);
|
|
dDistance += dComputeDistance32(pA->data.raw[i+2],pB->data.raw[i+2]);
|
|
dDistance += dComputeDistance32(pA->data.raw[i+3],pB->data.raw[i+3]);
|
|
}
|
|
dDistance /= 12*4*32;
|
|
logT("dDistance: %f\n",dDistance);
|
|
return dDistance;
|
|
}
|
|
|
|
typedef struct _def_sScoreSet{
|
|
double dScore;
|
|
const def_sTestPattern * pREF;
|
|
}def_sScoreSet;
|
|
|
|
int scoreSetCmp(const void * const first, const void * const second)
|
|
{
|
|
const double scoreFirst = ((def_sScoreSet*)first)->dScore;
|
|
const double scoreSecond = ((def_sScoreSet*)second)->dScore;
|
|
return scoreFirst > scoreSecond ? -1 :
|
|
(scoreFirst < scoreSecond ? 1 : 0);
|
|
}
|
|
|
|
double inline ScaleScore(const double dIn,const double dK)
|
|
{
|
|
return (1.0-exp(-dK*dIn))/(1.0-exp(-dK));
|
|
//return log(1.0+(dK*dIn))/log(1.0+dK);
|
|
}
|
|
|
|
/* returns a def_sScoreSet array, containing ordered reference to testPattern
|
|
* plus the corresponding score.
|
|
*/
|
|
void GetNearestIndexes( const def_sTestPattern * const pREF,
|
|
const def_sTestPattern * const pSet,
|
|
def_sScoreSet * const ScoreSet,
|
|
const unsigned int uNbPattern)
|
|
{
|
|
for (unsigned int i = 0; i < uNbPattern; i++)
|
|
{
|
|
ScoreSet[i].pREF = &pSet[i];
|
|
ScoreSet[i].dScore = (1 - ScaleScore(ComputePatternDistance(pREF,pSet+i),100));
|
|
logT("ScoreSet[%d].dScore = %f\n",i,ScoreSet[i].dScore);
|
|
}
|
|
|
|
qsort(ScoreSet,uNbPattern,sizeof(def_sScoreSet),scoreSetCmp);
|
|
|
|
double dFirstScore = -INFINITY;
|
|
|
|
for (unsigned int i = 0; i < uNbPattern; i++)
|
|
{
|
|
if(i==0)
|
|
dFirstScore = ScoreSet[i].dScore;
|
|
ScoreSet[i].dScore = (ScoreSet[i].dScore / dFirstScore) * 100;
|
|
}
|
|
}
|
|
|
|
unsigned char DistributeFaults( const def_sTestPattern * const pREF,
|
|
const def_sTestPattern * const pREFPatterns,
|
|
const unsigned int uNbREFPatterns,
|
|
const unsigned char ucNumTMU,
|
|
def_sFaultSourceScoreRec* const pFaultSrcCtx)
|
|
{
|
|
def_sScoreSet * const ScoreSet
|
|
= (def_sScoreSet*)malloc(uNbREFPatterns*sizeof(def_sScoreSet));
|
|
|
|
if(ScoreSet==NULL)
|
|
{
|
|
logE("Cannot allocate memory...");
|
|
return 1;
|
|
}
|
|
|
|
GetNearestIndexes(pREF,pREFPatterns,ScoreSet,uNbREFPatterns);
|
|
|
|
for( int i = 0 ; i < uNbREFPatterns ; i++)
|
|
{
|
|
if( ScoreSet[i].pREF->bReferenceSet && ScoreSet[i].dScore==100)
|
|
{
|
|
//logD("No Fault found\n");
|
|
free(ScoreSet);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
logD("==========================\n");
|
|
logD("Read:\n");
|
|
if( sOptions.eLogLevel >= E_LOGLEVEL__DEBUG)
|
|
DisplayPattern(pREF);
|
|
for( int i = 0 ; i < uNbREFPatterns ; i++)
|
|
{
|
|
logD("==========================\n");
|
|
if((!ScoreSet[i].pREF->bReferenceSet) && (ScoreSet[i].dScore>=80))
|
|
{
|
|
logD( "%d Score = %f\n",
|
|
ScoreSet[i].pREF->u8FaultLineIdx,ScoreSet[i].dScore);
|
|
FaultSource_addScore( pFaultSrcCtx,
|
|
ar_sFaultSourceLineMap
|
|
[ScoreSet[i].pREF->u8FaultLineIdx]
|
|
.eTMUFaultSource_TMU0_RES,
|
|
ScoreSet[i].dScore);
|
|
|
|
FaultSource_addScore( pFaultSrcCtx,
|
|
ar_sFaultSourceLineMap
|
|
[ScoreSet[i].pREF->u8FaultLineIdx]
|
|
.eTMUFaultSource_FBI,
|
|
ScoreSet[i].dScore);
|
|
|
|
FaultSource_addScore( pFaultSrcCtx,
|
|
ar_sFaultSourceLineMap
|
|
[ScoreSet[i].pREF->u8FaultLineIdx]
|
|
.eTMUFaultSource_TMU0_FBI,
|
|
ScoreSet[i].dScore);
|
|
if(ucNumTMU==1)
|
|
{
|
|
FaultSource_addScore( pFaultSrcCtx,
|
|
ar_sFaultSourceLineMap
|
|
[ScoreSet[i].pREF->u8FaultLineIdx]
|
|
.eTMUFaultSource_TMU0_TMU1,
|
|
ScoreSet[i].dScore);
|
|
|
|
FaultSource_addScore( pFaultSrcCtx,
|
|
ar_sFaultSourceLineMap
|
|
[ScoreSet[i].pREF->u8FaultLineIdx]
|
|
.eTMUFaultSource_TMU1,
|
|
ScoreSet[i].dScore);
|
|
}
|
|
}
|
|
}
|
|
|
|
free(ScoreSet);
|
|
|
|
return 1;
|
|
}
|
|
|
|
void TestStep_NoMem(FxU32 * const sst,
|
|
SstRegs * const sstregs,
|
|
const unsigned char ucNumTMU,
|
|
const uint8_t bEnableRGB,
|
|
const uint8_t bEnbleAlpha,
|
|
const uint8_t bEnableDitherValues,
|
|
def_sTestPattern * const psResultPattern)
|
|
{
|
|
|
|
ISET(SST_TREX(sstregs,ucNumTMU)->texBaseAddr, (0x000000>>3));
|
|
volatile const FxU32 * const pLFB1 = sst + (SST_LFB_ADDR>>2);
|
|
volatile const FxU32 * const pLFB2 = pLFB1 +((2048)>>2) ;
|
|
volatile const FxU32 * const pLFB3 = pLFB2 +((2048)>>2) ;
|
|
volatile const FxU32 * const pLFB4 = pLFB3 +((2048)>>2) ;
|
|
|
|
ISET( SST_TREX(sstregs,ucNumTMU)->textureMode,
|
|
SST_RGB565
|
|
| (bEnableRGB ? SST_TC_ONE : SST_TC_ZERO)
|
|
| (bEnbleAlpha ? SST_TCA_ONE :SST_TCA_ZERO));
|
|
|
|
if(bEnableDitherValues)
|
|
{
|
|
/* We are using dithering to detect lsb Faults.
|
|
* We need a non-zero original LFB value for dithering to happen.
|
|
* Drawing a triangle make detection easier.*/
|
|
clearScreen(sstregs,(1 << 11) | (0<<5) |(1),8,8);
|
|
drawTriangle(sstregs, ucNumTMU, 0, 0, 3, 4);
|
|
}
|
|
else
|
|
{
|
|
clearScreen(sstregs,0x00000000,8,8);
|
|
drawRect2(sstregs, ucNumTMU, 0, 0, 4, 4);
|
|
}
|
|
sst1InitIdle(sst);
|
|
|
|
mmio_fastread32((uint32_t*)psResultPattern->data.access.u16Pix[0], pLFB1, 2);
|
|
mmio_fastread32((uint32_t*)psResultPattern->data.access.u16Pix[1], pLFB2, 2);
|
|
mmio_fastread32((uint32_t*)psResultPattern->data.access.u16Pix[2], pLFB3, 2);
|
|
mmio_fastread32((uint32_t*)psResultPattern->data.access.u16Pix[3], pLFB4, 2);
|
|
|
|
const uint32_t OldlfbMode = IGET(sstregs->lfbMode);
|
|
ISET(sstregs->lfbMode, (OldlfbMode & ~SST_LFB_READFRONTBUFFER) //SST_LFB_READBACKBUFFER
|
|
| SST_LFB_READDEPTHABUFFER);
|
|
|
|
psResultPattern->data.access.u8APix[0][0] = pLFB1[0] & 0xFF;
|
|
psResultPattern->data.access.u8APix[0][1] = (pLFB1[0]>>16) & 0xFF;
|
|
psResultPattern->data.access.u8APix[0][2] = pLFB1[1] & 0xFF;
|
|
psResultPattern->data.access.u8APix[0][3] = (pLFB1[1]>>16) & 0xFF;
|
|
|
|
psResultPattern->data.access.u8APix[1][0] = pLFB2[0] & 0xFF;
|
|
psResultPattern->data.access.u8APix[1][1] = (pLFB2[0]>>16) & 0xFF;
|
|
psResultPattern->data.access.u8APix[1][2] = pLFB2[1] & 0xFF;
|
|
psResultPattern->data.access.u8APix[1][3] = (pLFB2[1]>>16) & 0xFF;
|
|
|
|
psResultPattern->data.access.u8APix[2][0] = pLFB3[0] & 0xFF;
|
|
psResultPattern->data.access.u8APix[2][1] = (pLFB3[0]>>16) & 0xFF;
|
|
psResultPattern->data.access.u8APix[2][2] = pLFB3[1] & 0xFF;
|
|
psResultPattern->data.access.u8APix[2][3] = (pLFB3[1]>>16) & 0xFF;
|
|
|
|
psResultPattern->data.access.u8APix[3][0] = pLFB4[0] & 0xFF;
|
|
psResultPattern->data.access.u8APix[3][1] = (pLFB4[0]>>16) & 0xFF;
|
|
psResultPattern->data.access.u8APix[3][2] = pLFB4[1] & 0xFF;
|
|
psResultPattern->data.access.u8APix[3][3] = (pLFB4[1]>>16) & 0xFF;
|
|
|
|
ISET(sstregs->lfbMode, OldlfbMode);
|
|
ISET( SST_TREX(sstregs,ucNumTMU)->textureMode,
|
|
SST_RGB565 | SST_TC_REPLACE | SST_TCA_REPLACE);
|
|
}
|
|
|
|
#define N_LOOP_TEST 100
|
|
unsigned long long
|
|
test_TMU_datalines_NoMem( sst1DeviceInfoStruct * const devInfo,
|
|
FxU32 * const sst,
|
|
SstRegs * const sstregs,
|
|
const unsigned char ucNumTMU,
|
|
def_sFaultSourceScoreRec* const pFaultSrcCtx)
|
|
{
|
|
unsigned long long ullNbErrorAll = 0;
|
|
|
|
static def_sTestPattern ar_ResultPattern[N_LOOP_TEST][8];
|
|
|
|
sst1InitIdle(sst);
|
|
|
|
const uint32_t OldlfbMode = IGET(sstregs->lfbMode);//SST_LFB_READBACKBUFFER
|
|
ISET(sstregs->lfbMode, SST_LFB_565 | SST_LFB_READFRONTBUFFER | SST_LFB_RGBALANES_ARGB);
|
|
|
|
const uint32_t OldfbzMode = IGET(sstregs->fbzMode);
|
|
ISET(sstregs->fbzMode,
|
|
// SST_DRAWBUFFER_BACK
|
|
SST_DRAWBUFFER_FRONT
|
|
| SST_RGBWRMASK
|
|
| SST_ZAWRMASK
|
|
| SST_ENALPHABUFFER // <-for NoMEM test ?? Not needed
|
|
| SST_ENALPHAMASK); // <-for NoMEM test; Needed
|
|
|
|
const uint32_t OldtrexInit0 = IGET(SST_TREX(sstregs,ucNumTMU)->trexInit0);
|
|
devInfo->tmuInit0[(int)ucNumTMU] = SST_TREXINIT0_DEFAULT ;
|
|
ISET(SST_TREX(sstregs,ucNumTMU)->trexInit0, devInfo->tmuInit0[(int)ucNumTMU]);
|
|
sst1InitIdle(sst);
|
|
|
|
/* set downstream TMUs to passthrough */
|
|
for (int i=0; i< ucNumTMU; i++)
|
|
{
|
|
ISET(SST_TREX(sstregs,i)->textureMode, SST_RGB565 | SST_TC_PASS | SST_TCA_PASS);
|
|
}
|
|
|
|
/* Testing several time to exclude instabilities */
|
|
for(unsigned int i = 0; i < N_LOOP_TEST ; i++)
|
|
{
|
|
/* this test is using the only feature I found that can
|
|
* control TMUs output without using TMU's RAM. Using
|
|
* textureMode we can force a TMU to output RGB value to
|
|
* 0xFFFFFF or 0x000000 (only), and A(lpha) to 0xFF or 0x00 (Only).
|
|
* So we will try these 4 pattern and check what we get on the LFB.
|
|
* Then eventually we can make "smart" Fault recognition...
|
|
*
|
|
* To make things harder, the physical data bus is 16Bit (DDR?).
|
|
* So [AR] and [GB] or superposed.
|
|
* */
|
|
|
|
/***************/
|
|
/* RGB: 0, A: 0*/
|
|
/***************/
|
|
/* Not implemented because the "all on" test should be enough for now
|
|
TestStep_NoMem( sst, sstregs, ucNumTMU, 0 ,0, 0,
|
|
&ar_ResultPattern[i][0]);*/
|
|
|
|
/***************/
|
|
/* RGB: 1, A: 0*/
|
|
/***************/
|
|
/* Not implemented because the "all on" test should be enough for now
|
|
TestStep_NoMem( sst, sstregs, ucNumTMU, 1, 0, 0,
|
|
&ar_ResultPattern[i][1]);*/
|
|
|
|
/***************/
|
|
/* RGB: 1, A: 1*/
|
|
/***************/
|
|
TestStep_NoMem( sst, sstregs, ucNumTMU, 1, 1 , 0,
|
|
&ar_ResultPattern[i][2]);
|
|
|
|
/***************/
|
|
/* RGB: 0, A: 1*/
|
|
/***************/
|
|
/* Not implemented because the "all on" test should be enough for now
|
|
TestStep_NoMem( sst, sstregs, ucNumTMU, 0, 1 , 0,
|
|
&ar_ResultPattern[i][3]);*/
|
|
}
|
|
|
|
/* Same test but with dithering enabled to get bit 0-1 values */
|
|
ISET(sstregs->fbzMode,
|
|
// SST_DRAWBUFFER_BACK
|
|
SST_DRAWBUFFER_FRONT
|
|
| SST_ENDITHER // <- enabling Dithering for this test
|
|
| SST_RGBWRMASK
|
|
| SST_ZAWRMASK
|
|
| SST_ENALPHABUFFER
|
|
| SST_ENALPHAMASK);
|
|
|
|
for(unsigned int i = 0; i < N_LOOP_TEST ; i++)
|
|
{
|
|
/* this test is using the only feature I found that can
|
|
* control TMUs output without using TMU's RAM. Using
|
|
* textureMode we can force a TMU to output RGB value to
|
|
* 0xFFFFFF or 0x000000 (only), and A(lpha) to 0xFF or 0x00 (Only).
|
|
* So we will try these 4 pattern and check what we get on the LFB.
|
|
* Then eventually we can make "smart" Fault recognition...
|
|
*
|
|
* To make things harder, the physical data bus is 16Bit (DDR?).
|
|
* So [AR] and [GB] or superposed.
|
|
* */
|
|
|
|
/***************/
|
|
/* RGB: 0, A: 0*/
|
|
/***************/
|
|
/* Not implemented because the "all on" test should be enough for now
|
|
TestStep_NoMem( sst, sstregs, ucNumTMU, 0 ,0, 1,
|
|
&ar_ResultPattern[i][4]);*/
|
|
|
|
/***************/
|
|
/* RGB: 1, A: 0*/
|
|
/***************/
|
|
/* Not implemented because the "all on" test should be enough for now
|
|
TestStep_NoMem( sst, sstregs, ucNumTMU, 1, 0, 1,
|
|
&ar_ResultPattern[i][5]);*/
|
|
|
|
/***************/
|
|
/* RGB: 1, A: 1*/
|
|
/***************/
|
|
TestStep_NoMem( sst, sstregs, ucNumTMU, 1, 1 , 1,
|
|
&ar_ResultPattern[i][6]);
|
|
|
|
/***************/
|
|
/* RGB: 0, A: 1*/
|
|
/***************/
|
|
/* Not implemented because the "all on" test should be enough for now
|
|
TestStep_NoMem( sst, sstregs, ucNumTMU, 0, 1 , 1,
|
|
&ar_ResultPattern[i][7]);*/
|
|
}
|
|
/* Post processing test results */
|
|
for(unsigned int i = 0; i < N_LOOP_TEST ; i++)
|
|
{ /* Not implemented because the "all on" test should be enough for now
|
|
ullNbErrorAll +=
|
|
DistributeFaults( &ar_ResultPattern[i][0],
|
|
ar_sExpectedPattern_Test1,
|
|
uNbPattern_Test1,
|
|
ucNumTMU,
|
|
pFaultSrcCtx);*/
|
|
|
|
/* Not implemented because the "all on" test should be enough for now
|
|
ullNbErrorAll +=
|
|
DistributeFaults( &ar_ResultPattern[i][1],
|
|
ar_sExpectedPattern_Test2,
|
|
uNbPattern_Test2,
|
|
ucNumTMU,
|
|
pFaultSrcCtx);*/
|
|
|
|
ullNbErrorAll +=
|
|
DistributeFaults( &ar_ResultPattern[i][2],
|
|
ar_sExpectedPattern_Test3,
|
|
uNbPattern_Test3,
|
|
ucNumTMU,
|
|
pFaultSrcCtx);
|
|
|
|
/* Not implemented because the "all on" test should be enough for now
|
|
ullNbErrorAll +=
|
|
DistributeFaults( &ar_ResultPattern[i][3],
|
|
ar_sExpectedPattern_Test4,
|
|
uNbPattern_Test4,
|
|
ucNumTMU,
|
|
pFaultSrcCtx);*/
|
|
|
|
/* Not implemented because the "all on" test should be enough for now
|
|
ullNbErrorAll +=
|
|
DistributeFaults( &ar_ResultPattern[i][4],
|
|
ar_sExpectedPattern_Test1_Dither,
|
|
uNbPattern_Test1_Dither,
|
|
ucNumTMU,
|
|
pFaultSrcCtx);*/
|
|
|
|
/* Not implemented because the "all on" test should be enough for now
|
|
ullNbErrorAll +=
|
|
DistributeFaults( &ar_ResultPattern[i][5],
|
|
ar_sExpectedPattern_Test2_Dither,
|
|
uNbPattern_Test2_Dither,
|
|
ucNumTMU,
|
|
pFaultSrcCtx);*/
|
|
|
|
ullNbErrorAll +=
|
|
DistributeFaults( &ar_ResultPattern[i][6],
|
|
ar_sExpectedPattern_Test3_Dither,
|
|
uNbPattern_Test3_Dither,
|
|
ucNumTMU,
|
|
pFaultSrcCtx);
|
|
|
|
/* Not implemented because the "all on" test should be enough for now
|
|
ullNbErrorAll +=
|
|
DistributeFaults( &ar_ResultPattern[i][7],
|
|
ar_sExpectedPattern_Test4_Dither,
|
|
uNbPattern_Test4_Dither,
|
|
ucNumTMU,
|
|
pFaultSrcCtx);*/
|
|
}
|
|
|
|
/* reset the Init0 register back to its previous value */
|
|
ISET(sstregs->lfbMode,OldlfbMode);
|
|
ISET(sstregs->fbzMode, OldfbzMode);
|
|
sst1InitIdle(sst);
|
|
devInfo->tmuInit0[(int)ucNumTMU] = OldtrexInit0;
|
|
ISET(SST_TREX(sstregs,ucNumTMU)->trexInit0, devInfo->tmuInit0[(int)ucNumTMU]);
|
|
sst1InitIdle(sst);
|
|
|
|
return ullNbErrorAll;
|
|
}
|
|
|
|
|
|
/* This is an attempt to simulate TMU->FBI->LFB values exchange and
|
|
* computation. It partially works for normal mode (no dithering, alpha buffer
|
|
* enabled), with two exception: Alpha bit XX seems to have a special behaviour
|
|
* that just zeros the output. And the colour mixing hasnt been reverse
|
|
* enginered. The dithering algorithm hasnt been reversed either.
|
|
* Then, because we are using pattern distance matching, this function is not
|
|
* used anymore. I let it here in case one day we want/need to implement a more
|
|
* accurate test
|
|
*
|
|
int simuFault_step( uint8_t bRGB,
|
|
uint8_t bA,
|
|
uint16_t u16CurrentPixel,
|
|
uint8_t u8CurrentAPixel,
|
|
uint16_t * const pu16RenderedPixel,
|
|
uint8_t * const pu8RenderedAPixel,
|
|
uint16_t u16BUSFaultMap )
|
|
{
|
|
// TMU Output force set
|
|
const uint8_t u8TMU_r8 = bRGB ? 0xFF : 0;
|
|
const uint8_t u8TMU_g8 = bRGB ? 0xFF : 0;
|
|
const uint8_t u8TMU_b8 = bRGB ? 0xFF : 0;
|
|
const uint8_t u8TMU_a8 = bA ? 0xFF : 0;
|
|
|
|
// TMU Output values packing (useless as its only all 0 or 1, but for brain model..)
|
|
const uint16_t u16Sent_W1 = (u8TMU_g8<<8) + u8TMU_b8;
|
|
const uint16_t u16Sent_W2 = (u8TMU_a8<<8) + u8TMU_r8;
|
|
|
|
// FBI receiving + Error aplication
|
|
const uint16_t u16received_W1 = u16Sent_W1 & ~u16BUSFaultMap;
|
|
const uint16_t u16received_W2 = u16Sent_W2 & ~u16BUSFaultMap;
|
|
|
|
// FBI received colours unpacking (!!! to be checked)
|
|
uint16_t u16FBI_Input_r8 = (u16received_W2 & 0xFF);
|
|
uint16_t u16FBI_Input_g8 = (u16received_W1 >> 8);
|
|
uint16_t u16FBI_Input_b8 = (u16received_W1 & 0xFF);
|
|
uint16_t u16FBI_Input_a8 = (u16received_W2 >> 8);
|
|
|
|
// FBI LFB current colours unpacking
|
|
const uint16_t u16FBI_Current_r8 = ((u16CurrentPixel>>11) & 0x1F) << 3;
|
|
const uint16_t u16FBI_Current_g8 = ((u16CurrentPixel>>5) & 0x3F) << 2;
|
|
const uint16_t u16FBI_Current_b8 = ((u16CurrentPixel>>0) & 0x1F) << 3;
|
|
const uint16_t u16FBI_Current_a8 = u8CurrentAPixel;
|
|
|
|
// Mixing current and new colours
|
|
//u16FBI_Input_r8 *= u16FBI_Input_a8;
|
|
// This does not work
|
|
//u16FBI_Input_r8 += u16FBI_Current_r8 * (255-u16FBI_Input_a8);
|
|
//u16FBI_Input_r8 >>=8;
|
|
|
|
//u16FBI_Input_g8 *= u16FBI_Input_a8;
|
|
//u16FBI_Input_g8 += u16FBI_Current_g8 * (255-u16FBI_Input_a8);
|
|
//u16FBI_Input_g8 >>=8;
|
|
|
|
//u16FBI_Input_b8 *= u16FBI_Input_a8;
|
|
//u16FBI_Input_b8 += u16FBI_Current_b8 * (255-u16FBI_Input_a8);
|
|
//u16FBI_Input_b8 >>=8;
|
|
|
|
//u16FBI_Input_a8 *= u16FBI_Input_a8;
|
|
//u16FBI_Input_a8 += u16FBI_Current_a8*(255-u16FBI_Input_a8);
|
|
//u16FBI_Input_a8 >>=8;
|
|
|
|
const uint16_t u16LFB_R5G6B5_r5 = (u16FBI_Input_r8>>3) & 0x1F;
|
|
const uint16_t u16LFB_R5G6B5_g6 = (u16FBI_Input_g8>>2) & 0x3F;
|
|
const uint16_t u16LFB_R5G6B5_b5 = (u16FBI_Input_b8>>3) & 0x1F;
|
|
const uint16_t u8LFB_R5G6B5_a8 = (u16FBI_Input_a8>>0) & 0xFF;
|
|
|
|
const uint16_t u16LBF_R5G6B5_Pixel = (u16LFB_R5G6B5_r5 <<11)
|
|
+ (u16LFB_R5G6B5_g6<<5)
|
|
+ (u16LFB_R5G6B5_b5);
|
|
const uint8_t u8LBF_R5G6B5_APixel = u8LFB_R5G6B5_a8;
|
|
|
|
*pu16RenderedPixel = u16LBF_R5G6B5_Pixel;
|
|
*pu8RenderedAPixel = u8LBF_R5G6B5_APixel;
|
|
|
|
return 0;
|
|
}
|
|
*/
|
|
|
|
/* In conjonction to the previous function, the idea here was to precompute all
|
|
* the possible fault pattern and use them as a comparison to find the actual
|
|
* one using real measurement. It is now deprecated in favor of the pattern
|
|
* distance matching.
|
|
*
|
|
void simuFault( uint8_t bRGB,
|
|
uint8_t bA )
|
|
{
|
|
uint16_t u16RenderedPixel;
|
|
uint8_t u8RenderedAPixel;
|
|
uint32_t u16PreviousPixel = 0;
|
|
uint16_t u8PreviousAPixel = 0;
|
|
//for(char bitPos1 = -1; bitPos1 <= 15 ; ++bitPos1)
|
|
//for(u8PreviousAPixel= 0; u8PreviousAPixel <= 0xFF ; ++u8PreviousAPixel)
|
|
{
|
|
//for(u16PreviousPixel= 0; u16PreviousPixel <= 0xFFFF ; ++u16PreviousPixel)
|
|
{
|
|
//u16PreviousPixel += (bitPos1 ==-1) ? 0 : (1u << bitPos1);
|
|
uint16_t Pattern_OK;
|
|
uint16_t APattern_OK;
|
|
for(char bitPos = -1; bitPos <= 15 ; ++bitPos)
|
|
{
|
|
const uint16_t u16FaultMap = (bitPos ==-1) ? 0 : (1u << bitPos);
|
|
simuFault_step( bRGB,
|
|
bA,
|
|
u16PreviousPixel,
|
|
u8PreviousAPixel,
|
|
&u16RenderedPixel,
|
|
&u8RenderedAPixel,
|
|
u16FaultMap);
|
|
|
|
//if(u16FaultMap==0)
|
|
//{
|
|
// Pattern_OK = u16RenderedPixel;
|
|
// APattern_OK = u8RenderedAPixel;
|
|
//}
|
|
//else if(u16FaultMap==0x100)
|
|
//{
|
|
// if((u16RenderedPixel!=Pattern_OK) && (u8RenderedAPixel!=APattern_OK))
|
|
// {
|
|
// printf("bRGB %d\n",bRGB);
|
|
// printf("bA, %d\n",bA);
|
|
// printf("u16PreviousPixel %04X\n",u16PreviousPixel);
|
|
// printf("u8PreviousAPixel %02X\n",u8PreviousAPixel);
|
|
// printf("SIMU: %04X\n",u16FaultMap);
|
|
// printf("\t0x%04X | 0x%02X %c\n",
|
|
// u16RenderedPixel,
|
|
// u8RenderedAPixel,
|
|
// (u16RenderedPixel==0xFFFF)
|
|
// && (u8RenderedAPixel==0xFF) ? '!' : ' ');
|
|
// }
|
|
//}
|
|
printf("bRGB %d\n",bRGB);
|
|
printf("bA, %d\n",bA);
|
|
printf("u16PreviousPixel %04X\n",u16PreviousPixel);
|
|
printf("u8PreviousAPixel %02X\n",u8PreviousAPixel);
|
|
printf("SIMU: %04X\n",u16FaultMap);
|
|
printf("\t0x%04X | 0x%02X %c\n",
|
|
u16RenderedPixel,
|
|
u8RenderedAPixel,
|
|
(u16RenderedPixel==0xFFFF)
|
|
&& (u8RenderedAPixel==0xFF) ? '!' : ' ');
|
|
}
|
|
}
|
|
}
|
|
}
|
|
*/
|