📄 int_proc.h
字号:
/************************************************************************
* C-EMERALD code for ACCORDO ( 15 - 05 - 2003 )
* Ver: ver0.2
*
* File: int_proc.c (interrupt procedures)
*
* Author: A. Di Carlo
************************************************************************/
/*******************************************************************************
* - MR041215 Optimized TTM controller
* - Increased controller bandwidth, CLV 1X 17Hz/35Hz
* (inside/outside).
* - Added hold functionality, ST7 can force the TTM
* controller to hold its state and output.
* - During a defect (DEFOK) and during a short jump the state
* of the controller is held (implemented in the DSP).
* - MR20050106 Problem: Turntable motor often came to a halt or rotated
* backwards after a jump from track 1 to the last track or vice
* versa. The fixes are described in the following points: a, b
* and c.
* - MR20050106a Changed the thresholds that determine whether or not the
* correct TTM velocity has been reached in CLV mode. Especially
* the value for the phase was too high.
* - MR20050106b Introduced a timer which makes sure that the TTM velocity is
* within the defined range for at certain period of time before
* the DSP notifies the ST7 that the correct speed has been
* reached.
* - MR20050106c When the TTM controller switches to hold mode (either by the
* ST7, during a short jump or a defect) it will not be allowed
* to brake the TTM. If the TTM controller output is negative
* during the hold mode then its output is set to zero.
* - MR20050523a Fixed FG-period error calculation in TTM controller.
* - MR20050523b Added high frequency FG pulse detection. High frequency FG
* pulses are assummed to be caused by a stopped TTM. In order
* to recover from this situation, the I-action is loaded with
* a value that results in the maximum allowed value at the
* controller output to restart the TTM and the ST7 is notified
* about this situation. Normally the TTM restarts without pro-
* blems when the focus and radial loops are open. Opening these
* loops should be done in the ST7.
* - MR20050523c Changed limit on TTM controller output from one +/- level to
* a maximum and a minimum level.
* - MR20051115c Generate the speed_ok signal on the CLV buffer level only
* - MR20051115d Modified the handling of sledge controller. such that sledge not moved
* during defects
* - MR20051115e In tracking controller, shift gain is removed and compensated
* by changing the value of other coefficients
* - MR20060201a Interpolate fe during defect, also during short jumps.
* - MR20060201b Optimized noiseshaping (less instructions, i.e. faster).
* - MR20060201c Error fond in the previous optimized version of the deadzone.
* Implementation has been rewritten, works correcly now and
* uses one instruction less. Note the difference in the use of
* nlc_delta.
* - MR20060201d Optimized the "shift-out prevention" in the TTM controller.
* - FD060929a Fixed detection of very short focus ramping
*******************************************************************************/
#ifndef QAC_CHECK
#define MACRO # ## macro
#else
#define MACRO void
#endif
MACRO interrupt_decimation2_handle()
{
#if (1 == SAMPLERATE_TESTING)
/* Cycle start put gpio to 1 for monitoring */
GPIO_RW = 0x0f;
if (count16 == 0) {
GPIO_RW = 0x00; /* Mark count16 == 0 using a double pulse */
GPIO_RW = 0x0f;
}
#endif
#if (1 == DSP_PROC_ENABLE)
if (proc_enable) {
#endif
err_gen(); /* Generate error signals + defect detection */
focus(); /* Execute focus controller */
if (int_mode == TRK_MODE) goto CASE_TRK; /* Assume adjust-mode when tracking controller is switched off */
adjust(); /* Execute adjustment procedures before focus and tracking controller can be switched on */
/* goto END_SWITCH;*/
CASE_TRK:
track(); /* Execute radial tracking controller, including the nonlinear control */
END_SWITCH:
#if (1 == DEBUG_DSP || 2 == DEBUG_DSP)
test_out(); /* Output signals through the test_pdm DACs, for debuging only */
#endif
misc(); /* Other things suchs as TTM controller, AGC and generation hfok, teok and fok. */
#if (1 == DSP_PROC_ENABLE)
}
#endif
dsp_arm_communication(); /* Reports ARM the new DSP state when this has changed and calls read/write x/y memory routine. */
#if (1 == SAMPLERATE_TESTING)
/* cycle end put gpio to 0 for monitoring*/
GPIO_RW = 0x00;
#endif
}
#endm
MACRO err_gen()
{
fraction * delay; /* TO DO: LOCAL VARIABLE NOT ALLOWED IN INTERRUPT ROUTINE */
memoryY CONST * c; /* TO DO: LOCAL VARIABLE NOT ALLOWED IN INTERRUPT ROUTINE */
register fraction accu0 at(acc[0]);
register fraction accu1 at(acc[1]);
register fraction dx0 at(dx[0]);
register fraction dx1 at(dx[1]);
register fraction dy0 at(dy[0]);
register fraction dy1 at(dy[1]);
c = coeff_error;
delay = delay_error;
/* The radial tracking error (te) is generated by the RATE block. */
#if (1 == WORKAROUND_SPIKE_BUG)
/* When the DSP processing time takes longer than the sampling period, set by the */
/* decimation filters, the decimation registers are not read immediately after a */
/* decimation interrupt but some undefined period of time after this. If there are */
/* multiple processing cycles in a row that take longer than the sampling period */
/* then the time between the decimation interrupt and the reading of the decimation */
/* registers increases until a sample is lost. A sample is lost when two consecutive */
/* interrupts occur in one processing cycle, in that case the sample corresponding */
/* to the first interrupt is lost. Another problem that may occur in this case when */
/* the decimation registers are not immediately read after an interrupt is that the */
/* register is read by the DSP the moment an new value is written in to the registers */
/* by the decimation filters. If this is the case then the values read by the DSP are */
/* are corrupted. A work-around for the last problem is reading the decimation */
/* register twice and comparing both read values, if they are the same then the value */
/* is a valid if not then a third read of the decimation register will give a valid */
/* value. */
dx0 = E_IN;
dy0 = E_IN;
if (dx0 != dy0) { /* Check if read value is valid. */
dx0 = E_IN; /* If not: the third read will produce a valid value, see above. */
}
#else
dx0 = E_IN;
#endif
accu1 = dx0 * c[3];
te = (accu1 << 1);
#if (0 != DEBUG_DSP)
e_in = dx0;
#if (1 == WORKAROUND_SPIKE_BUG)
dx0 = F_IN;
dy0 = F_IN;
if (dx0 != dy0) { /* Check if read value is valid. */
dx0 = F_IN; /* If not: the third read will produce a valid value, see above. */
}
#else
dx0 = F_IN;
#endif
f_in = dx0;
#endif
/* Read AC detector signal. */
#if (1 == WORKAROUND_SPIKE_BUG)
dx0 = AC_IN;
dy0 = AC_IN;
if (dx0 != dy0) { /* Check if read value is valid. */
dx0 = AC_IN; /* If not: the third read will produce a valid value, see above. */
}
accu0 = dx0;
#else
dx0 = AC_IN;
accu0 = dx0;
#endif
#if (0 != DEBUG_DSP)
ac_in = dx0;
#endif
/* Read BD detector signal. */
#if (1 == WORKAROUND_SPIKE_BUG)
dx1 = BD_IN;
dy1 = BD_IN;
if (dx1 != dy1) { /* Check if read value is valid. */
dx1 = BD_IN; /* If not: the third read will produce a valid value, see above. */
}
#else
dx1 = BD_IN;
#endif
#if (0 != DEBUG_DSP)
bd_in = dx1;
#endif
/* Calculation of the focus tracking error (fe) from AC and BD. */
accu1 = dx0 * c[0] - dx1 * c[1] - c[2];
fe = (accu1 << 1);
/* Generation of the low frequent center aperture signal (hfl) from AC and BD. */
accu0 += dx1;
#if (0 != DEBUG_DSP)
hf_deb = accu0 >> 1;
#endif
/* Scale and translate the hfl signal such that it is always positive. */
accu0 -= c[4];
accu0 -= c[4];
accu0 = accu0 >> 2;
hfl = accu0;
/* Fast filter, operating on the scaled and translated hfl signal. */
accu1 = accu0 * c[5] + c[6] * delay[0];
delay[0] = accu1;
/* Slow filter, filtering the output of the fast filter. */
accu0 = delay[0] * c[7] + c[8] * delay[1];
delay[1] = accu0;
/* Detect black dot if slow filter is larger than fast filter by */
/* a certain amount. Results in 0x0001 if detect detected, otherwise 0x0000. */
accu1 = ((int)((c[9] * delay[1] - accu1) >> 15) + 0x0001);
bd_defect = (int)accu1 | DEFFOK;
accu0 = ((int)((c[10] * delay[0] - hfdc) >> 15) + 0x0001);
wd_defect = (int)accu0;
accu1 = (bd_defect << 1) - 1; /* 1 if bd_defect active otherwise -1. */
accu1 = ((int)accu1 + bd_cnt); /* Increase/decreas counter. */
accu0 = ((int)accu1 >> 15); /* Make counter zero when it */
accu1 = (int)accu1 & (int)accu0; /* becomes negative. */
bd_cnt = (int)accu1;
/* Increase white dot counter during defect, decrease outside defect. */
accu1 = (wd_defect << 1) - 1; /* 1 if wd_defect active otherwise -1. */
accu1 = ((int)accu1 + wd_cnt); /* Increase/decreas counter. */
accu0 = ((int)accu1 >> 15);
accu1 = (int)accu1 & (int)accu0;
wd_cnt = (int)accu1;
if (((int)accu1 - wd_cnt_max) >> 15)
{
bd_cnt = accu1;
}
/* Mask the generation of a black dot defect */
/* during and shortly after a white dot. */
/* Result: defect detected -> 0x0001 otherwise -> 0x0000. */
bd_defect_m = (bd_defect & ((-wd_cnt) >> 15)) | DEFFOK;
/* Mask the generation of a white dot defect */
/* during and shortly after a black dot. */
/* Result: defect detected -> 0x0001 otherwise -> 0x0000. */
wd_defect_m = wd_defect & ((-bd_cnt) >> 15);
/* Generate defect signal for focus loop. */
/* Result: defect detected -> 0x0001 otherwise -> 0x0000. */
fcs_defect = bd_defect_m & def_ena;
/* Generate defect signal for focus loop. */
/* Result: defect detected -> 0x0001 otherwise -> 0x0000. */
/* trk_defect = (wd_defect_m | bd_defect_m) & def_ena; */
trk_defect = bd_defect_m & def_ena;
}
#endm
MACRO init_focus()
{
#if (1 == OPTIMIZED_INIT)
/* Nothing to be done, everything is already reset to zero. */
#else
fraction * k;
integer i;
k = delay_focus;
fcs_off = 0;
fosc = 0;
fcrint = 0;
for (i = 0; i < MAX_DIM_DELAY_FOCUS; i++)
{
k[i] = 0;
}
#endif
}
#endm
/************************************************************************/
MACRO focus()
{
fraction * delay;
memoryY CONST * c;
register fraction pacc at(p);
register fraction accu0 at(acc[0]);
register fraction accu1 at(acc[1]);
register int int_accu1 at(acc[1]);
register fraction dx0 at(dx[0]);
register fraction dy0 at(dy[0]);
c = coeff_focus;
delay = delay_focus;
/* PID controller for the focus loop. */
accu0 = FCR_ON_INT & fcrint & fok;
fcrint = accu0;
if (accu0 != 0) /* Focus loop closed. */
{
dsp_state = get_set_focus_closed(dsp_state);
/* Slope filter that generates the interpolated fe-signal value */
/* during a defect. */
dx0 = delay[0];
accu1 = fe;
#if FE_INTERP_DURING_JUMPS_AND_DEFECTS
if (fcs_defect) /* Interpolate fe during a defect, also during short jumps MR060201a. */
#else
if (fcs_defect & (~jump_mode)) /* Interpolate fe during a defect. */
#endif
{
accu1 = dx0;
}
else /* Update slope filter when no is defect present. */
{
dy0 = c[0];
if (accu1 > dx0)
{
accu0 = dx0 + dy0;
}
else
{
accu0 = dx0 - dy0;
}
delay[0] = accu0;
}
fe = accu1;
/*-------------- I part of PID (with decimation) */
delay[1] += (accu1 >> 4); /* Decimation using an accumulate-and-drop filter. */
if (count16 == 5)
{
accu0 = delay[1] * c[1] + delay[2] * c[2];
if (!fcs_defect) /* Hold integrator during a defect. */
{
delay[2] = accu0;
}
delay[1] = 0; /* The "drop" part of the accumulate-and-drop filter. */
}
/*-------------- PD part of PID ----------------*/
accu1 = accu1 * c[3];
accu0 = accu1 + c[4] * delay[3] + c[5] * delay[4];
delay[3] = accu1;
delay[4] = accu0;
accu0 = accu0 + c[6] * delay[5];
dy0 = c[7];
delay[5] = accu0;
accu1 = accu0 << (int)dy0; /* Result of PD part in accu1. */
/*-------------- Combine I and PD parts, result is accu0 ----------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -