⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vblank.c

📁 GM5621原代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	// 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 + -