📄 xp_osi_clk.c
字号:
} if(pGlobal->ClkInfo.XpClkNpcrs <= PCRS_HIGH_GAIN) { /* Still in the high gain */ pGlobal->ClkInfo.XpClkNpcrs++; } /*------------------------------------------------------------------------+ | Normalize the STC and PCR | This drops the upper 10 bits of both the PCR and the STC | This also detects if either the PCR or STC has wrapped | and other has not. In either case the software algorithm | doesn't run. +------------------------------------------------------------------------*/ stc = (((stc_high & 0x003FFFFF) * 2) + ((stc_low & 0x200) >> 9)) * 300; stc = stc + (stc_low & 0x1FF); pcr = (((pcr_high & 0x003FFFFF) * 2) + ((pcr_low & 0x200) >> 9)) * 300; pcr = pcr + (pcr_low & 0x1FF); /*------------------------------------------------------------------------+ | Check if the upper 10 bits are the same. | The software clock recovery algorithm is not used if | soft_overflow occurs. | Also check if hardware overflow has occured and treat | like a software overflow - pag 7/16/99 +------------------------------------------------------------------------*/ if(overflow || (stc_high & 0xFFC00000) != (pcr_high & 0xFFC00000)) { stc = stc_high & 0xFFC00000; pcr = pcr_high & 0xFFC00000; soft_overflow = 1; pGlobal->ClkInfo.XpClkErrs++; /* Increment the global error count */ /*--------------------------------------------------------------------+ | if there were two consecutive errors, force a PCR reload +--------------------------------------------------------------------*/ if(pGlobal->ClkInfo.wXpClkPrevErr == 1) { flag = os_enter_critical_section(); xp_osi_clk_set_pid(pGlobal,xp_atom_dcr_read(pGlobal->uDeviceIndex,XP_DCR_ADDR_PCRPID)); os_leave_critical_section(flag); pGlobal->ClkInfo.wXpClkPrevErr = 0; } else { pGlobal->ClkInfo.wXpClkPrevErr = 1; } } else { soft_overflow = 0; pGlobal->ClkInfo.wXpClkPrevErr = 0; } /*------------------------------------------------------------------------+ | Run the software algorithm if there are no errors | Adjust auto PWM if the delta is large +------------------------------------------------------------------------*/ if(soft_overflow == 0) { delta_pcr = pcr - pGlobal->ClkInfo.XpClkPrevPcr; delta_stc = stc - pGlobal->ClkInfo.XpClkPrevStc; temp1 = delta_pcr - delta_stc; temp2 = 27000000 / delta_pcr; rate_adjust = (temp1 * temp2) >> RATE_GAIN;//lingh changed it value_adjust = (pcr - stc) >> DELTA_GAIN; pwm_adjust = rate_adjust + value_adjust; /*--------------------------------------------------------------------+ | Once the delta is small enough increase the threshold | and use only autopwm until this function is called | again, then increase the threshold. +--------------------------------------------------------------------*/ if((delta < LOW_THRESHOLD) && (pGlobal->ClkInfo.lXpClkPrevDelta < LOW_THRESHOLD)) { pGlobal->ClkInfo.uwXpClkThreshold = HIGH_THRESHOLD; flag = os_enter_critical_section(); xp_atom_dcr_write(pGlobal->uDeviceIndex,XP_DCR_ADDR_PCRSTCT, pGlobal->ClkInfo.uwXpClkThreshold); os_leave_critical_section(flag); } else if(pGlobal->ClkInfo.uwXpClkThreshold != 0) { pGlobal->ClkInfo.uwXpClkThreshold = 0; flag = os_enter_critical_section(); xp_atom_dcr_write(pGlobal->uDeviceIndex,XP_DCR_ADDR_PCRSTCT, pGlobal->ClkInfo.uwXpClkThreshold); os_leave_critical_section(flag); } pGlobal->ClkInfo.XpClkPrevStc = stc; pGlobal->ClkInfo.XpClkPrevPcr = pcr; pGlobal->ClkInfo.lXpClkPrevDelta = delta; /*--------------------------------------------------------------------+ | Restrict the rate of change of the PWM value. | For the first few PCRs received after the STC is | loaded the clamp value is larger so that the local | clock moves closer to the multiplexor clock quickly. | After that reduce use a smaller clamp value. +--------------------------------------------------------------------*/ if (pGlobal->ClkInfo.XpClkNpcrs <= PCRS_HIGH_GAIN) { /* clamp adjustment */ if(pwm_adjust > STC_LOAD_PWM_CLAMP) { pwm_adjust = STC_LOAD_PWM_CLAMP; } else if(pwm_adjust < -STC_LOAD_PWM_CLAMP) { pwm_adjust = -STC_LOAD_PWM_CLAMP; } } else { if(pwm_adjust > PWM_CLAMP) { pwm_adjust = PWM_CLAMP; } else if(pwm_adjust < -PWM_CLAMP) { pwm_adjust = -PWM_CLAMP; } } flag = os_enter_critical_section(); pwm = xp_atom_dcr_read(pGlobal->uDeviceIndex,XP_DCR_ADDR_PWM); os_leave_critical_section(flag); new_pwm = pwm + pwm_adjust; /*--------------------------------------------------------------------+ | PWM range is actually a signed 12 bit number | whose range is 0x800 - 0x7ff. So after calculating | the new pwm, make sure we don't exceed the above bounds +--------------------------------------------------------------------*/ if((pwm <= 0x07ff) && (new_pwm > 0x07ff) && (pwm_adjust > 0)) { new_pwm = 0x07ff; } else if((pwm >= 0x0800) && (new_pwm < 0x0800) && (pwm_adjust < 0)) { new_pwm = 0x0800; } flag = os_enter_critical_section(); xp_atom_dcr_write(pGlobal->uDeviceIndex,XP_DCR_ADDR_PWM, new_pwm); /* Update the PWM register */ os_leave_critical_section(flag); }}/*----------------------------------------------------------------------------+| XXXXXXX XXX XXX XXXXXX XXXXXXX XXXXXX XX XX XX XXXX| XX X XX XX X XX X XX X XX XX XXX XX XXXX XX| XX X XXX XX XX X XX XX XXXX XX XX XX XX| XXXX X XX XXXX XXXXX XX XXXX XX XX XX| XX X XXX XX XX X XX XX XX XXX XXXXXX XX| XX X XX XX XX XX X XX XX XX XX XX XX XX XX| XXXXXXX XXX XXX XXXX XXXXXXX XXX XX XX XX XX XX XXXXXXX+----------------------------------------------------------------------------*//*----------------------------------------------------------------------------+| xp0_clk_get_stc_high+-----------------------------------------------------------------------------+|| DESCRIPTION: allocates a channel for the requested type|| PROTOTYPE : short xp0_clk_get_stc_high(| unsigned long *p_stc_high)|| ARGUMENTS : p_stc_high - the upper 32 bits of the stc, returned|| RETURNS : zero if the stc is valid, or non-zero if invalid|| ERRORS : XP_ERROR_INVALID_STC|| COMMENTS : The stc value is determined if it is valid if a recent| PCR value was loaded. Note: During a channel change,| there is an interval between the time the new PCR pid is| written, and the arrival of the first PCR where the STC,| could be considered either valid or invalid. This| function assumes the STC is valid for this duration.|+----------------------------------------------------------------------------*/SHORT xp_osi_clk_get_stc_high(GLOBAL_RESOURCES *pGlobal,ULONG *pStcHigh){ short rc; short i; unsigned long stc_high=0; unsigned long lstc_high=0; unsigned long lstc_high2=0; unsigned long diff; UINT32 flag; /*------------------------------------------------------------------------+ | Do not use xp0_os_semaphore_wait() since called from an interrupt +------------------------------------------------------------------------*/ /*------------------------------------------------------------------------+ | Get STC and Latched STC values. Since the hardware could | receive a PCR at any time, we re-read the STC Latched Register | twice to make sure the value is still the same. +------------------------------------------------------------------------*/ flag = os_enter_critical_section(); for(i=0; i<2; i++) { lstc_high = xp_atom_dcr_read(pGlobal->uDeviceIndex,XP_DCR_ADDR_LSTCHI); stc_high = xp_atom_dcr_read(pGlobal->uDeviceIndex,XP_DCR_ADDR_STCHI); lstc_high2 = xp_atom_dcr_read(pGlobal->uDeviceIndex,XP_DCR_ADDR_LSTCHI); if(lstc_high == lstc_high2) { break; } } os_leave_critical_section(flag); /*------------------------------------------------------------------------+ | Compare the Two Latched STC Values Read, A PCR must have been | Received if their Different +------------------------------------------------------------------------*/ rc = (lstc_high != lstc_high2) ? XP_ERROR_INVALID_STC : 0; /*------------------------------------------------------------------------+ | The STC is considered valid if a recent PCR has been received. | Each PCR received is loaded into the STC Latched register. So, we | compare the values of the STC Latched and the STC registers whose | difference should be within the expected arrival rate of PCR's. | | The calculation is as follows: | STC clock is 27 MHZ, PCR arrival rate=100ms | The upper 32 bits of the STC are modulo 600 | | difference = 2.7E6 / 600 | = 4500 | | Add a 1% margin so we don't hit the edge condition exactly | and are somewhat tolerant of non-compliant streams. | | 4500 x 1.01 = 4545 | | STC is valid if | STC - STCHOLD | < 4545 | | Note: We have to account for the STC wrapping. +------------------------------------------------------------------------*/ /*------------------------------------------------------------------------+ | Since these are both unsigned, there is not a Wrapping Issue +------------------------------------------------------------------------*/ if (rc == 0) { diff = stc_high - lstc_high; if (diff > 4545) { rc = XP_ERROR_INVALID_STC; } } if (rc == 0 && pGlobal->ClkInfo.XpClkNpcrs == 0) { rc = XP_ERROR_INVALID_STC; } *pStcHigh = stc_high; return(rc);}/*----------------------------------------------------------------------------+| xp0_clk_init+----------------------------------------------------------------------------*/SHORT xp_osi_clk_init(GLOBAL_RESOURCES *pGlobal){ pGlobal->ClkInfo.XpClkInstalled = 0; return(0);}/*----------------------------------------------------------------------------+| XX XXXXXX XXXXXX XXXXX
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -