📄 vblank.c
字号:
// if vblanking ISR still running (aquiring data) don't adjust
// offset2.
if(rgb_index)
return;
B_rgboff2[0] = gm_ReadRegByte(RED_OFFSET2);
B_rgboff2[1] = gm_ReadRegByte(GRN_OFFSET2);
B_rgboff2[2] = gm_ReadRegByte(BLU_OFFSET2);
// if new total is greater than the calibrated value, decrease the offset2,
// else increase it. rgb_tot[0] and red_cal haven't been divided by
// OFFSET2_ARRAY_SIZE to scale them back down, so instead ADC_THRESHOLD
// if multipied by OFFSET2_ARRAY_SIZE so we don't have to do the division
// (or shift)
for(color=0;color<3;color++)
{
// Round up! (add 0.5)
#if (OFFSET2_ARRAY_SIZE > 1)
rgb_tot[color] -= (OFFSET2_ARRAY_SIZE / 2);
#endif
// use a proportional control to speedup the calibration.
adj = abs(rgb_tot[color]) / ADC_THRESHOLD;
if(rgb_tot[color] < -(ADC_THRESHOLD))
{
B_rgboff2[color]-= adj;
// check we didn't wrap around.
if(B_rgboff2[color] > 0x7F)
B_rgboff2[color] = 0x00;
}
if(rgb_tot[color] > (ADC_THRESHOLD))
{
B_rgboff2[color]+= adj;
// check we didn't wrap around.
if(B_rgboff2[color] > 0x7F)
B_rgboff2[color] = 0x7F;
}
// reset rgb_tot
rgb_tot[color] = rgb_cal[color];
}
// restore offset2 and gain.
gm_WriteRegByte(RED_OFFSET2,B_rgboff2[0]);
gm_WriteRegByte(GRN_OFFSET2,B_rgboff2[1]);
gm_WriteRegByte(BLU_OFFSET2,B_rgboff2[2]);
gm_WriteRegByte(HOST_CONTROL, IPFORCE_UPDATE);
// re-enable the ISR
rgb_index = OFFSET2_ARRAY_SIZE;
// Clear status before enabling ISR to prevent ISR from occuring
// the moment we enable it causing a flicker of a few lines on the display.
//gm_WriteRegByte(IP_FLAGLINE, 0); // Louis 0810
gm_WriteRegByte(DISPLAY_STATUS, D_VBLANK);
gm_SetRegBitsByte(MISC_OCMMASK, D_VBLANK);
//gm_WriteRegByte(IP_FLAGLINE, 1); // Louis 0810
}
//******************************************************************
// FUNCTION : void ADCCalibrationISR
// USAGE : The main code for performing the ADC Offset2
// adjustments. It feeds in a DAC value, and compares
// the ADC values, if they are higher than the calibrated
// value, then OFFSET2 is decreased, if it's lower then
// OFFSET2 is increased.
//******************************************************************
void far ADCCalibrationISR(void)
{
BYTE i, B_Timeout, Fas2;
WORD B_Adc[3];
// set up DAC
gm_WriteRegWord(ADC_TESTDAC,(((WORD)ADC_TESTDAC_VALUE << 8) | RED_ST | GRN_ST | BLU_ST));
#ifdef ADC_B_PHASE
Fas2 = gm_ReadRegByte(ADC_B_PHASE);
gm_WriteRegByte(ADC_B_PHASE, 0x00); // Reduced the BW before calibration.
#else
Fas2 = gm_ReadRegByte(ADC_FAS2);
gm_WriteRegByte(ADC_FAS2, 0x00); // Reduced the BW before calibration.
#endif
B_Timeout = ADC_GLITCH_RETRY;
for(i = 0;i < ADC_READINGS_PER_INTERRUPT;i++)
{
do
{
B_Adc[0] = (WORD)gm_ReadRegByte(ADC_DATA_RED);
}while((abs(B_Adc[0] - (WORD)gm_ReadRegByte(ADC_DATA_RED)) > ADC_GLITCH_THRESHOLD) && B_Timeout--);
//
B_Timeout++;
do
{
B_Adc[1] = (WORD)gm_ReadRegByte(ADC_DATA_GRN);
}while((abs(B_Adc[1] - (WORD)gm_ReadRegByte(ADC_DATA_GRN)) > ADC_GLITCH_THRESHOLD) && B_Timeout--);
B_Timeout++;
do
{
B_Adc[2] = (WORD)gm_ReadRegByte(ADC_DATA_BLU);
}while((abs(B_Adc[2] - (WORD)gm_ReadRegByte(ADC_DATA_BLU)) > ADC_GLITCH_THRESHOLD) && B_Timeout--);
// if no timeout, then adjust the rgb_tot values.
if(B_Timeout)
{
rgb_tot[0] -= B_Adc[0];
rgb_tot[1] -= B_Adc[1];
rgb_tot[2] -= B_Adc[2];
rgb_index--;
if(rgb_index == 0x00)
{
gm_ClearRegBitsByte(MISC_OCMMASK, D_VBLANK);
break;
}
}
}
// restore DAC
gm_WriteRegWord(ADC_TESTDAC,0x00);
// Restore BW
#ifdef ADC_B_PHASE
gm_WriteRegByte(ADC_B_PHASE, Fas2);
#else
gm_WriteRegByte(ADC_FAS2, Fas2);
#endif
}
//******************************************************************
// FUNCTION : ext_VBlankISR
// DESCRIPTION : ext_VBlankISR is the interrupt we get on each
// IRQ4. When we enter this ISR we first determine
// whether it's a vertical blanking ISR, if so then
// check func_ptr, if it's NULL, then we should change
// the stack space and call the vertical blanking
// function. If func_ptr is not NULL, then we want
// to return from where we last left off. Change
// to the alternate stack space, pop off our registers
// and perform an IRET to get back to where we left off.
// The TimerISR() function below is the ISR which stops
// the execution of the vertical blanking function. It
// saves the registers on the alternate stack and returns
// from both interrupts (IRQ4 and the timer IRQ)
//******************************************************************
void far interrupt (*OldIRQ4)(void) = NULL_PTR;
WORD VBlankHoldOff = 0;
#if ADC_CALIBRATION_ISR_IN_RAM
void (*ptrADCCalbrationISR)(void) = NULL_PTR;
BYTE ADCCalibrationISRRAM[0xDB]; // 0xDB
BYTE VBlankISRRAM[0x48]; // 0x48
#else
BYTE VBlankISRRAM[0x54];
#endif // ADC_CALIBRATION_ISR_IN_RAM
void interrupt ext_VBlankISR(void)
{
// if you don't explicitely call ADCCalibration as 'far' compiler will
// make it a near call since this is the same module. The call must
// be 'far' because this routine is running from RAM.
#if ADC_CALIBRATION_ISR_IN_RAM
ptrADCCalbrationISR();
#else
asm{ call far ptr ADCCalibrationISR }
#endif // ADC_CALIBRATION_ISR_IN_RAM
WRITE_PCB_REG(EOI, INT5_VTYPE); //clear IRQ4 request.
gm_WriteRegByte(DISPLAY_STATUS, D_VBLANK);
}
//******************************************************************
// FUNCTION : ext_InitVBlankISR
// DESCRIPTION : ext_InitVBlankISR initializes the vertical blanking
// interrupt machine.
//******************************************************************
void InitADCCalibrationISR(BYTE integrity)
{
InitADCCalibration(integrity);
gm_DisableInterrupts();
_fmemcpy(VBlankISRRAM, (BYTE far *)ext_VBlankISR, sizeof(VBlankISRRAM));
#if ADC_CALIBRATION_ISR_IN_RAM
_fmemcpy(ADCCalibrationISRRAM, (BYTE far *)ADCCalibrationISR, sizeof(ADCCalibrationISRRAM));
ptrADCCalbrationISR = (void (*)(void)) ADCCalibrationISRRAM;
#endif // ADC_CALIBRATION_ISR_IN_RAM
// enable the VBlanking ISR.
gm_ClearRegBitsByte(MISC_OCMMASK, D_VBLANK);
#if 0
if((BYTE *)GET_VECTOR(INT5_VECTOR) != VBlankISRRAM)
{
OldIRQ4 = (void far interrupt (*)(void))GET_VECTOR(INT5_VECTOR);
// check to make sure we haven't already put our interrupt on the vector.
SET_VECTOR(INT5_VECTOR, VBlankISRRAM);
}
#endif
SET_VECTOR(INT5_VECTOR, VBlankISRRAM);
WRITE_PCB_REG(I5CON, LEVEL_ONE); // Raise priority of IRQ4
rgb_index = OFFSET2_ARRAY_SIZE;
CLEAR_PCB_REG_BITS(IMASK, I5); // unmask IRQ4
asm{ STI };
}
//******************************************************************
// FUNCTION : StartADCCalibrationISR
// DESCRIPTION : StartADCCalibrationISR will unmask the vertical
// blanking ISR which will start the process.
//******************************************************************
void VBLK_StartADCCalibrationISR(void)
{
// reset the calibration array index.
rgb_index = OFFSET2_ARRAY_SIZE;
rgb_tot[0] = rgb_cal[0];
rgb_tot[1] = rgb_cal[1];
rgb_tot[2] = rgb_cal[2];
// Clear status before enabling ISR to prevent ISR from occuring
// the moment we enable it causing a flicker of a few lines on the display.
gm_WriteRegByte(DISPLAY_STATUS, D_VBLANK);
gm_SetRegBitsByte(MISC_OCMMASK, D_VBLANK);
msg("StartVBlankingFunction",0);
}
//******************************************************************
// FUNCTION : StopADCCalibrationISR
// DESCRIPTION : StopADCCalibrationISR will mask the vertical
// blanking ISR, stopping the process. To stop the
// processs both the vertical blanking ISR and the timer
// ISR should be stopped. Then the alternate stack
// pointer should be reset and func_ptr set back to NULL,
// now when the vertical blanking ISR starts again, it will
// start fresh from the begining.
//******************************************************************
void VBLK_StopADCCalibrationISR(void)
{
// disable the VBlanking interrupt.
gm_ClearRegBitsByte(MISC_OCMMASK, D_VBLANK);
// a non-zero rgb_index tells ADCAdjustOffset2 not to run.
rgb_index = OFFSET2_ARRAY_SIZE;
msg("StopADCCalibrationISR",0);
}
typedef struct Offset1CalStruct
{
BYTE redOffset1;
BYTE grnOffset1;
BYTE bluOffset1;
BYTE red_cal;
BYTE grn_cal;
BYTE blu_cal;
}Offset1CalType;
//***************************************************************
// FUNCTION : LoadColorTemp
// USAGE : Read Color Temperature Data from NVRAM
// DESCRIPTION :
// INPUT : None
// OUTPUT : none
// GLOBALS : none
// USED_REGS : None
//***************************************************************
static gmt_RET_STAT LoadOffset1Cal(void)
{
#ifdef NVRAM_BLOCK_Offset1Cal_WB_Used
gmt_RET_STAT ret;
Offset1CalType cal;
BYTE B_temp[3], B_ArraySize;
ret = gm_ReadNVRAMBlock(Offset1Cal_ID, 0x00, (BYTE *)&cal, 0, sizeof(cal));
if((ret == gmd_OK))// && (cal.array_size == OFFSET2_ARRAY_SIZE))
{
msg("offset1cal found in nvram",0);
// Get Integer part.
rgb_cal[0] = cal.red_cal * OFFSET2_ARRAY_SIZE;
rgb_cal[1] = cal.grn_cal * OFFSET2_ARRAY_SIZE;
rgb_cal[2] = cal.blu_cal * OFFSET2_ARRAY_SIZE;
// Get Fractional part.
B_temp[0] = cal.redOffset1 & 0xc0;
B_temp[1] = cal.grnOffset1 & 0xc0;
B_temp[2] = cal.bluOffset1 & 0xc0;
// move MSB of fractional part back down from top 2 bits.
// The fractional part will be added back into the rgb_cal value.
B_ArraySize = OFFSET2_ARRAY_SIZE - 1;
while(!(B_ArraySize & 0x80))
{
B_ArraySize <<= 1;
B_temp[0] >>= 1;
B_temp[1] >>= 1;
B_temp[2] >>= 1;
}
msg("fractional:",0);
msg("r %x",(WORD)B_temp[0]);
msg("g %x",(WORD)B_temp[1]);
msg("b %x",(WORD)B_temp[2]);
// Add Fractional part back in.
rgb_cal[0] += B_temp[0];
rgb_cal[1] += B_temp[1];
rgb_cal[2] += B_temp[2];
gm_WriteRegByte(RED_OFFSET1,(cal.redOffset1 & 0x3f));
gm_WriteRegByte(GRN_OFFSET1,(cal.grnOffset1 & 0x3f));
gm_WriteRegByte(BLU_OFFSET1,(cal.bluOffset1 & 0x3f));
return gmd_OK;
}
msg("offset1cal not found in nvram",0);
return gmd_FAIL;
#else // NVRAM_BLOCK_Offset1Cal_WB_Used
return gmd_FAIL;
#endif // NVRAM_BLOCK_Offset1Cal_WB_Used
}
//***************************************************************
// FUNCTION : SaveColorTemp
// USAGE : Save Color Temperature Data in NVRAM
// DESCRIPTION :
// INPUT : None
// OUTPUT : none
// GLOBALS : none
// USED_REGS : None
//***************************************************************
static void SaveOffset1Cal(void)
{
#ifdef NVRAM_BLOCK_Offset1Cal_WB_Used
Offset1CalType cal;
BYTE B_ArraySize, B_temp[3];
// offset1 nvram value: rgb_cal[
cal.redOffset1 = gm_ReadRegByte(RED_OFFSET1) & 0x3f; // only need 6 bits
cal.grnOffset1 = gm_ReadRegByte(GRN_OFFSET1) & 0x3f;
cal.bluOffset1 = gm_ReadRegByte(BLU_OFFSET1) & 0x3f;
// Get Fractional part.
B_temp[0] = rgb_cal[0] % OFFSET2_ARRAY_SIZE;
B_temp[1] = rgb_cal[1] % OFFSET2_ARRAY_SIZE;
B_temp[2] = rgb_cal[2] % OFFSET2_ARRAY_SIZE;
// move MSB of fractional part into top 2 bits
// that will be masked into the extra 2 bits of cal.XXXOffset1
// example: OFFSET2_ARRAY_SIZE = 64 or 0x40, rgb_cal = 0x043F
// Integer part = 0x043F / 0x40 = 0x10
// Fractional part = 0x43F % 0x40 = 0x3F
// Shift fractional into top 2 bits of cal.XXXOffset1 Looking at 0x3F we
// know we need to shift left by 2 bits and 0x3F becomes 0xFC, mask off
// lower 6 bits and we have 0xC0. To figure out how many bits to shift
// is hard to explain, but if you take the array size (0x40) subtract 1 (0x3F)
// now shift that value left until you have the fist non zero value (2 shifts)
// and that's how many bits to shift.
msg("fractional:",0);
msg("r %x",(WORD)B_temp[0]);
msg("g %x",(WORD)B_temp[1]);
msg("b %x",(WORD)B_temp[2]);
B_ArraySize = OFFSET2_ARRAY_SIZE - 1;
while(!(B_ArraySize & 0x80))
{
B_ArraySize <<= 1;
B_temp[0] <<= 1;
B_temp[1] <<= 1;
B_temp[2] <<= 1;
}
cal.redOffset1 |= B_temp[0] & 0xc0;
cal.grnOffset1 |= B_temp[1] & 0xc0;
cal.bluOffset1 |= B_temp[2] & 0xc0;
// now put the Integer portion into it's own BYTE.
cal.red_cal = rgb_cal[0] / OFFSET2_ARRAY_SIZE;
cal.grn_cal = rgb_cal[1] / OFFSET2_ARRAY_SIZE;
cal.blu_cal = rgb_cal[2] / OFFSET2_ARRAY_SIZE;
gm_WriteNVRAMBlock(Offset1Cal_ID, 0x00, (BYTE *)&cal, 0, sizeof(cal));
#endif // NVRAM_BLOCK_Offset1Cal_WB_Used
}
// When DebugOn command is set, need to reset the INT4 Vector to the ISR code in ROM.
// This can prevent the ISP through DDc2Bi protocol failed at writing ISP driver into RAM.
// When DebugOff cpmmand is set, change back to normal mode which ADC Calibration ISR
// is executed in RAM.
void StartADCCalibrationISR(void)
{
gm_DisableInterrupts();
SET_VECTOR(INT5_VECTOR, VBlankISRRAM);
VBLK_StartADCCalibrationISR();
asm {STI};
}
void StopADCCalibrationISR(void)
{
gm_DisableInterrupts();
VBLK_StopADCCalibrationISR();
gm_WriteRegByte(DISPLAY_STATUS, D_VBLANK);
SET_VECTOR(INT5_VECTOR, ext_VBlankISR);
asm {STI};
}
#else
// need dummy stub for OSD to compile when not using ISR.
void StartADCCalibrationISR(void) { return;}
void StopADCCalibrationISR(void) { return;}
void InitCalValues(void){ return; }
// void SetInt4VectorToISRInRAM(void) {return;}
// void SetInt4VectorToISRInROM(void) {return;}
#endif// USE_ADC_CALIBRATION_ISR
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -