comparison src/cs/layer1/p_cfile/l1p_func.c @ 302:0740b5ff15f6

reconstructed L1_GPRS source imported from tcs211-l1-reconst
author Mychaela Falconia <falcon@freecalypso.org>
date Tue, 31 Oct 2017 03:42:35 +0000
parents
children
comparison
equal deleted inserted replaced
301:a963c5c35f8d 302:0740b5ff15f6
1 /************* Revision Controle System Header *************
2 * GSM Layer 1 software
3 * L1P_FUNC.C
4 *
5 * Filename l1p_func.c
6 * Copyright 2003 (C) Texas Instruments
7 *
8 ************* Revision Controle System Header *************/
9
10 #define L1P_FUNC_C
11
12 #include "l1_macro.h"
13 #include "l1_confg.h"
14
15 #if L1_GPRS
16
17 #if (CODE_VERSION == SIMULATION)
18 #include "stddef.h"
19 #endif
20
21 #include "l1_types.h"
22 #include "sys_types.h"
23 #include "l1_const.h"
24
25
26 #if TESTMODE
27 #include "l1tm_defty.h"
28 #endif
29 #if (AUDIO_TASK == 1)
30 #include "l1audio_const.h"
31 #include "l1audio_cust.h"
32 #include "l1audio_defty.h"
33 #endif
34 #if (L1_GTT == 1)
35 #include "l1gtt_const.h"
36 #include "l1gtt_defty.h"
37 #endif
38 #if (L1_MP3 == 1)
39 #include "l1mp3_defty.h"
40 #endif
41 #if (L1_MIDI == 1)
42 #include "l1midi_defty.h"
43 #endif
44 #include "l1_defty.h"
45 #include "l1_varex.h"
46
47 #include "cust_os.h"
48 #include "l1_msgty.h"
49 #include "l1_time.h"
50
51 #include "l1p_cons.h"
52 #include "l1p_msgt.h"
53 #include "l1p_deft.h"
54 #include "l1p_vare.h"
55 #include "l1p_sign.h"
56
57 #if(RF_FAM == 61)
58 #include "l1_rf61.h"
59 #include "tpudrv61.h"
60 #endif
61
62 #if (CODE_VERSION == SIMULATION)
63 #include "l1_rf2.h"
64 #endif
65
66 /*-------------------------------------------------------*/
67 /* Prototypes of external functions used in this file. */
68 /*-------------------------------------------------------*/
69
70 void l1pddsp_meas_ctrl (UWORD8 nbmeas, UWORD8 pm_pos);
71 void l1dtpu_meas (UWORD16 radio_freq,WORD8 agc,UWORD8 lna_off,
72 UWORD16 win_id,UWORD16 tpu_synchro, UWORD8 adc_active
73 #if (RF_FAM == 61)
74 ,UWORD8 afc_mode
75 ,UWORD8 if_ctl
76 #endif
77 );
78 WORD8 Cust_get_agc_from_IL (UWORD16 radio_freq, UWORD16 agc_index, UWORD8 table_id);
79 void l1ps_macs_init (void);
80
81 /*-------------------------------------------------------*/
82 /* initialize_l1pvar() */
83 /*-------------------------------------------------------*/
84 /* Parameters : */
85 /* ------------- */
86 /* Return : */
87 /* ------------- */
88 /* Description : */
89 /* ------------- */
90 /* This routine is used to initialize the l1pa, l1ps and */
91 /* l1pa_l1ps_com global structures. */
92 /*-------------------------------------------------------*/
93 void initialize_l1pvar(void)
94 {
95 UWORD8 i;
96
97 //++++++++++++++++++++++++++++++++++++++++++
98 // Reset "l1ps" structure.
99 //++++++++++++++++++++++++++++++++++++++++++
100
101 l1ps.last_PR_good = 0;
102 l1ps.ILmin_beacon = 255;
103 #if 0 /* FreeCalypso TCS211 reconstruction */
104 l1ps.read_param.assignment_id = 0xFF; /* do not return non initialized value to RLC */
105 #endif
106
107 for(i = 0; i < 8; i++)
108 l1ps.ILmin_others[i] = l1_config.params.il_min;
109
110 //++++++++++++++++++++++++++++++++++++++++++
111 // Reset "l1pa" structure.
112 //++++++++++++++++++++++++++++++++++++++++++
113
114 for(i=0;i<NBR_L1PA_PROCESSES;i++)
115 {
116 l1pa.state[i] = 0;
117 l1pa.l1pa_en_meas[i] = 0;
118 }
119
120 //++++++++++++++++++++++++++++++++++++++++++
121 // Reset "l1pa_l1ps_com" structure.
122 //++++++++++++++++++++++++++++++++++++++++++
123
124 // Initialize PC_MEAS_CHAN flag
125 l1ps.pc_meas_chan_ctrl = FALSE;
126
127 // Initialize active list used in Neighbour Measurement Transfer Process
128 l1pa_l1ps_com.cres_freq_list.alist = &(l1pa_l1ps_com.cres_freq_list.list[0]);
129
130 // Initialize parameters used in Neighbour Measurement Transfer Process
131 l1pa_l1ps_com.cres_freq_list.alist->nb_carrier = 0;
132 l1pa_l1ps_com.tcr_freq_list.new_list_present = FALSE;
133
134 l1pa_l1ps_com.transfer.semaphore = TRUE;
135 l1pa_l1ps_com.transfer.aset = &(l1pa_l1ps_com.transfer.set[0]);
136 l1pa_l1ps_com.transfer.fset[0] = &(l1pa_l1ps_com.transfer.set[1]);
137 l1pa_l1ps_com.transfer.fset[1] = &(l1pa_l1ps_com.transfer.set[2]);
138
139 // Initialize Downlink Power Control Struture. Set CRC to BAD, bcch_level
140 // and burst_level[] to INVALID.
141 l1pa_l1ps_com.transfer.dl_pwr_ctrl.crc_error = TRUE;
142 l1pa_l1ps_com.transfer.dl_pwr_ctrl.bcch_level = (WORD8)0x80;//omaps00090550
143
144 for(i = 0; i < 4; i++)
145 {
146 l1pa_l1ps_com.transfer.dl_pwr_ctrl.burst_level[i] = (WORD8)0x80;//omaps00090550
147 }
148
149 l1pa_l1ps_com.transfer.set[0].ul_tbf_alloc = &(l1pa_l1ps_com.transfer.ul_tbf_alloc[0]);
150 l1pa_l1ps_com.transfer.set[1].ul_tbf_alloc = &(l1pa_l1ps_com.transfer.ul_tbf_alloc[1]);
151 l1pa_l1ps_com.transfer.set[2].ul_tbf_alloc = &(l1pa_l1ps_com.transfer.ul_tbf_alloc[2]);
152
153 for(i=0;i<3;i++)
154 {
155 l1pa_l1ps_com.transfer.set[i].SignalCode = 0;
156 l1pa_l1ps_com.transfer.set[i].dl_tbf_synchro_timeslot = 0;
157 l1pa_l1ps_com.transfer.set[i].dl_tbf_synchro_timeslot = 0;
158 l1pa_l1ps_com.transfer.set[i].transfer_synchro_timeslot = 0;
159 l1pa_l1ps_com.transfer.set[i].allocated_tbf = NO_TBF;
160 l1pa_l1ps_com.transfer.set[i].assignment_command = NO_TBF;
161 l1pa_l1ps_com.transfer.set[i].multislot_class = 0;
162
163 l1pa_l1ps_com.transfer.set[i].packet_ta.ta = 255;
164 l1pa_l1ps_com.transfer.set[i].packet_ta.ta_index = 255;
165 l1pa_l1ps_com.transfer.set[i].packet_ta.ta_tn = 255;
166
167 l1pa_l1ps_com.transfer.set[i].tsc = 0;
168
169 l1pa_l1ps_com.transfer.set[i].freq_param.chan_sel.h = 0;
170 l1pa_l1ps_com.transfer.set[i].freq_param.chan_sel.
171 rf_channel.single_rf.radio_freq = 0;
172
173 l1pa_l1ps_com.transfer.set[i].tbf_sti.present = FALSE;
174
175 l1pa_l1ps_com.transfer.set[i].mac_mode = 0;
176
177 l1pa_l1ps_com.transfer.set[i].ul_tbf_alloc->tfi = 255;
178 l1pa_l1ps_com.transfer.set[i].dl_tbf_alloc.tfi = 255;
179
180 l1pa_l1ps_com.transfer.set[i].dl_pwr_ctl.p0 = 255;
181 l1pa_l1ps_com.transfer.set[i].dl_pwr_ctl.bts_pwr_ctl_mode = 0;
182 l1pa_l1ps_com.transfer.set[i].dl_pwr_ctl.pr_mode = 0;
183 }
184
185 //++++++++++++++++++++++++++++++++++++++++++
186 // Reset "l1pa_macs_com" structure.
187 //++++++++++++++++++++++++++++++++++++++++++
188
189 l1ps_macs_com.fix_alloc_exhaust_flag = FALSE;
190 l1ps_macs_com.rlc_downlink_call = FALSE;
191 #if FF_L1_IT_DSP_USF
192 l1ps_macs_com.usf_status = USF_AVAILABLE;
193 #endif
194 #if L1_EDA
195 l1ps_macs_com.fb_sb_task_enabled = FALSE;
196 l1ps_macs_com.fb_sb_task_detect = FALSE;
197 #endif
198
199 //++++++++++++++++++++++++++++++++++++++++++
200 // Reset MAC-S static structure.
201 //++++++++++++++++++++++++++++++++++++++++++
202 l1ps_macs_init();
203
204 //++++++++++++++++++++++++++++++++++++++++++
205 // Reset packet transfer mode commands.
206 //++++++++++++++++++++++++++++++++++++++++++
207
208 l1pa_l1ps_com.transfer.ptcch.ta_update_cmd = FALSE;
209 l1pa_l1ps_com.transfer.psi_param.psi_param_update_cmd = FALSE;
210 l1pa_l1ps_com.transfer.tbf_release_param.tbf_release_cmd = FALSE;
211 l1pa_l1ps_com.transfer.pdch_release_param.pdch_release_cmd = FALSE;
212 l1pa_l1ps_com.transfer.repeat_alloc.repeat_allocation = FALSE;
213 }
214
215 /*-------------------------------------------------------*/
216 /* l1ps_reset_db_mcu_to_dsp() */
217 /*-------------------------------------------------------*/
218 /* Parameters : */
219 /* Return : */
220 /* Functionality : */
221 /*-------------------------------------------------------*/
222 void l1ps_reset_db_mcu_to_dsp(T_DB_MCU_TO_DSP_GPRS *page_ptr)
223 {
224 API i;
225 API size = sizeof(T_DB_MCU_TO_DSP_GPRS) / sizeof(API);
226 API *ptr = (API *)page_ptr;
227
228 // Clear all locations.
229 for(i=0; i<size; i++) *ptr++ = 0;
230 }
231
232 /*-------------------------------------------------------*/
233 /* l1ps_reset_db_dsp_to_mcu() */
234 /*-------------------------------------------------------*/
235 /* Parameters : */
236 /* Return : */
237 /* Functionality : */
238 /*-------------------------------------------------------*/
239 void l1ps_reset_db_dsp_to_mcu(T_DB_DSP_TO_MCU *page_ptr)
240 {
241 API i;
242 API size = sizeof(T_DB_DSP_TO_MCU_GPRS) / sizeof(API);
243 API *ptr = (API *)page_ptr;
244
245 // Clear all locations.
246 for(i=0; i<size; i++) *ptr++ = 0;
247
248 // Set crc result as "SB not found".
249 page_ptr->a_sch[0] = (1<<B_SCH_CRC); // B_SCH_CRC =1, BLUD =0
250 }
251
252 /*-------------------------------------------------------*/
253 /* l1ps_swap_iq_dl() */
254 /*-------------------------------------------------------*/
255 /* Parameters : */
256 /* Return : */
257 /* Functionality : */
258 /*-------------------------------------------------------*/
259 BOOL l1ps_swap_iq_dl(UWORD16 radio_freq)
260 {
261 UWORD8 swap_iq;
262 BOOL swap_flag;
263
264 #if (L1_FF_MULTIBAND == 0)
265
266 if(((l1_config.std.id == DUAL) || (l1_config.std.id == DUALEXT) || (l1_config.std.id == DUAL_US)) &&
267 (radio_freq >= l1_config.std.first_radio_freq_band2))
268 {
269 swap_iq = l1_config.std.swap_iq_band2;
270 }
271 else
272 {
273 swap_iq = l1_config.std.swap_iq_band1;
274 }
275
276 #else // L1_FF_MULTIBAND = 1 below
277
278 UWORD16 physical_band_id;
279 physical_band_id =
280 l1_multiband_radio_freq_convert_into_physical_band_id(radio_freq);
281 swap_iq = rf_band[physical_band_id].swap_iq;
282
283 #endif // #if (L1_FF_MULTIBAND == 0) else
284
285
286 switch(swap_iq)
287 {
288 case 0: /* No swap at all. */
289 case 2: /* DL, no swap. */
290 swap_flag = FALSE;
291 break;
292 case 1: /* DL I/Q swap. */
293 case 3: /* DL I/Q swap. */
294 swap_flag = TRUE;
295 break;
296 }
297 return(swap_flag);
298 }
299
300 /*-------------------------------------------------------*/
301 /* l1ps_swap_iq_ul() */
302 /*-------------------------------------------------------*/
303 /* Parameters : */
304 /* Return : */
305 /* Functionality : */
306 /*-------------------------------------------------------*/
307 BOOL l1ps_swap_iq_ul(UWORD16 radio_freq)
308 {
309 UWORD8 swap_iq;
310 BOOL swap_flag;
311
312 #if (L1_FF_MULTIBAND == 0)
313
314 if(((l1_config.std.id == DUAL) || (l1_config.std.id == DUALEXT) || (l1_config.std.id == DUAL_US)) &&
315 (radio_freq >= l1_config.std.first_radio_freq_band2))
316 {
317 swap_iq = l1_config.std.swap_iq_band2;
318 }
319 else
320 {
321 swap_iq = l1_config.std.swap_iq_band1;
322 }
323
324 #else // L1_FF_MULTIBAND = 1 below
325
326 UWORD16 physical_band_id = 0;
327 physical_band_id =
328 l1_multiband_radio_freq_convert_into_physical_band_id(radio_freq);
329 swap_iq = rf_band[physical_band_id].swap_iq;
330
331 #endif // #if (L1_FF_MULTIBAND == 0) else
332
333 switch(swap_iq)
334 {
335 case 0: /* No swap at all. */
336 case 1: /* UL, no swap. */
337 swap_flag = FALSE;
338 break;
339 case 2: /* UL I/Q swap. */
340 case 3: /* UL I/Q swap. */
341 swap_flag = TRUE;
342 break;
343 }
344 return(swap_flag);
345 }
346
347 /*-------------------------------------------------------*/
348 /* l1ps_tcr_ctrl() */
349 /*-------------------------------------------------------*/
350 /* Parameters : */
351 /* Return : */
352 /* Functionality : */
353 /*-------------------------------------------------------*/
354 void l1ps_tcr_ctrl(UWORD8 pm_position)
355 {
356 UWORD16 radio_freq_ctrl;
357 UWORD8 lna_off;
358 WORD8 agc;
359
360 UWORD8 mode = PACKET_TRANSFER;
361 UWORD8 input_level;
362 #if (RF_FAM == 61)
363 UWORD16 dco_algo_ctl_pw = 0;
364 UWORD8 if_ctl = 0;
365 UWORD8 if_threshold = C_IF_ZERO_LOW_THRESHOLD_GSM;
366 #endif
367
368 radio_freq_ctrl = l1pa_l1ps_com.cres_freq_list.alist->freq_list[l1pa_l1ps_com.tcr_freq_list.tcr_next_to_ctrl];
369
370 // Get AGC according to the last known IL.
371
372 input_level = l1a_l1s_com.last_input_level[radio_freq_ctrl - l1_config.std.radio_freq_index_offset].input_level;
373 agc = Cust_get_agc_from_IL(radio_freq_ctrl, input_level >> 1, PWR_ID);
374 lna_off = l1a_l1s_com.last_input_level[radio_freq_ctrl - l1_config.std.radio_freq_index_offset].lna_off;
375
376 #if (RF_FAM == 61) // Locosto DCO
377 #if (PWMEAS_IF_MODE_FORCE == 0)
378 cust_get_if_dco_ctl_algo(&dco_algo_ctl_pw, &if_ctl, (UWORD8) L1_IL_VALID ,
379 input_level,
380 l1pa_l1ps_com.p_idle_param.radio_freq, if_threshold);
381 #else
382 if_ctl = IF_120KHZ_DSP;
383 dco_algo_ctl_pw = DCO_IF_0KHZ;
384 #endif
385
386
387 l1ddsp_load_dco_ctl_algo_pw(dco_algo_ctl_pw);
388 l1s.tcr_prog_done=1;
389 #endif
390
391 // Memorize the IL and LNA used for AGC setting.
392 l1pa_l1ps_com.tcr_freq_list.used_il_lna.il = l1a_l1s_com.last_input_level[radio_freq_ctrl - l1_config.std.radio_freq_index_offset].input_level;
393 l1pa_l1ps_com.tcr_freq_list.used_il_lna.lna = l1a_l1s_com.last_input_level[radio_freq_ctrl - l1_config.std.radio_freq_index_offset].lna_off;
394
395 // tpu pgm: 1 measurement only.
396 l1dtpu_meas(radio_freq_ctrl,
397 agc,
398 lna_off,
399 l1s.tpu_win,
400 l1s.tpu_offset,INACTIVE
401 #if(RF_FAM == 61)
402 ,L1_AFC_SCRIPT_MODE
403 ,if_ctl
404 #endif
405 );
406
407 // Increment tpu window identifier.
408 l1s.tpu_win += (l1_config.params.rx_synth_load_split + PWR_LOAD);
409
410 // increment carrier counter for next measurement...
411 if(++l1pa_l1ps_com.tcr_freq_list.tcr_next_to_ctrl >= l1pa_l1ps_com.cres_freq_list.alist->nb_carrier)
412 l1pa_l1ps_com.tcr_freq_list.tcr_next_to_ctrl = 0;
413
414 // Program DSP, in order to performed 1 measure.
415 // Second argument specifies PW position.
416 l1pddsp_meas_ctrl(1, pm_position);
417
418 #if (TRACE_TYPE!=0)
419 //trace_fct(CST_CTRL_TRANSFER_MEAS, radio_freq_ctrl);
420 #endif
421
422 // Update d_debug timer
423 l1s_dsp_com.dsp_db_w_ptr->d_debug = (l1s.debug_time + 2) ;
424
425
426 // Flag measurement control.
427 // **************************
428
429 // Set flag "ms_ctrl" to nb_meas_to_perform.
430 // It will be used as 2 tdma delayed to trigger Read phase.
431 l1pa_l1ps_com.tcr_freq_list.ms_ctrl = 1;
432
433 // Flag DSP and TPU programmation.
434 // ********************************
435
436 // Set "CTRL_MS" flag in the controle flag register.
437 l1s.tpu_ctrl_reg |= CTRL_MS;
438 l1s.dsp_ctrl_reg |= CTRL_MS;
439
440 }
441
442 /*-------------------------------------------------------*/
443 /* l1ps_bcch_meas_ctrl() */
444 /*-------------------------------------------------------*/
445 /* Parameters : */
446 /* Return : */
447 /* Functionality : */
448 /*-------------------------------------------------------*/
449 void l1ps_bcch_meas_ctrl(UWORD8 ts)
450 {
451 UWORD8 lna_off;
452 WORD8 agc;
453
454 UWORD8 mode = PACKET_TRANSFER;
455 UWORD8 input_level;
456 #if (RF_FAM == 61)
457 UWORD16 dco_algo_ctl_pw =0;
458 UWORD8 if_ctl=0;
459 UWORD8 if_threshold = C_IF_ZERO_LOW_THRESHOLD_GSM;
460 #endif
461
462
463 if ((l1s.dsp_ctrl_reg & CTRL_ABORT) == 0)
464 {
465 #define radio_freq_ctrl l1a_l1s_com.Scell_info.radio_freq
466
467 // Get AGC according to the last known IL.
468 input_level = l1a_l1s_com.last_input_level[radio_freq_ctrl - l1_config.std.radio_freq_index_offset].input_level;
469 agc = Cust_get_agc_from_IL(radio_freq_ctrl, input_level >> 1, PWR_ID);
470 lna_off = l1a_l1s_com.last_input_level[radio_freq_ctrl - l1_config.std.radio_freq_index_offset].lna_off;
471 // Memorize the IL and LNA used for AGC setting.
472 // Note: the same structure as for TCR meas is used for PC_MEAS_CHAN measurements
473 l1pa_l1ps_com.tcr_freq_list.used_il_lna.il = l1a_l1s_com.last_input_level[radio_freq_ctrl - l1_config.std.radio_freq_index_offset].input_level;
474 l1pa_l1ps_com.tcr_freq_list.used_il_lna.lna = l1a_l1s_com.last_input_level[radio_freq_ctrl - l1_config.std.radio_freq_index_offset].lna_off;
475
476
477 #if (RF_FAM == 61) // Locosto DCO
478 cust_get_if_dco_ctl_algo(&dco_algo_ctl_pw, &if_ctl, (UWORD8) L1_IL_VALID,
479 input_level,
480 radio_freq_ctrl,if_threshold);
481
482 l1ddsp_load_dco_ctl_algo_pw(dco_algo_ctl_pw);
483 #endif
484
485
486 // tpu pgm: 1 measurement only.
487 l1dtpu_meas(radio_freq_ctrl,
488 agc,
489 lna_off,
490 l1s.tpu_win,
491 l1s.tpu_offset,INACTIVE
492 #if(RF_FAM == 61)
493 ,L1_AFC_SCRIPT_MODE
494 ,if_ctl
495 #endif
496 );
497
498 // Increment tpu window identifier.
499 l1s.tpu_win += (l1_config.params.rx_synth_load_split + PWR_LOAD);
500
501 // Program DSP, in order to performed 1 measure.
502 // Second argument specifies PW position.
503 l1pddsp_meas_ctrl(1, (UWORD8)ts);
504
505 #if (TRACE_TYPE!=0) && (TRACE_TYPE!=5)
506 //trace_fct(CST_CTRL_SCELL_TRANSFER_MEAS, radio_freq_ctrl);
507 #endif
508
509 // Update d_debug timer
510 l1s_dsp_com.dsp_db_w_ptr->d_debug = (l1s.debug_time + 2) ;
511
512
513 // Flag measurement control.
514 // **************************
515
516 l1ps.pc_meas_chan_ctrl = TRUE;
517
518 // Flag DSP and TPU programmation.
519 // ********************************
520
521 // Set "CTRL_MS" flag in the controle flag register.
522 l1s.tpu_ctrl_reg |= CTRL_MS;
523 l1s.dsp_ctrl_reg |= CTRL_MS;
524 }
525 }
526
527 /*-------------------------------------------------------*/
528 /* l1ps_update_read_set_parameters() */
529 /*-------------------------------------------------------*/
530 /* Parameters : */
531 /* Return : */
532 /* Functionality : Updating of the "Read_param" structure*/
533 /* usefull in case the aset structure has been updated */
534 /* before the last read of the current block */
535 /*-------------------------------------------------------*/
536 void l1ps_update_read_set_parameters(void)
537 {
538 #define READ_PARAM l1ps.read_param
539 #define ASET l1pa_l1ps_com.transfer.aset
540
541 // Copy of the "aset" parameters in the "read_param" structure
542 #if 0 /* FreeCalypso TCS211 reconstruction */
543 READ_PARAM.dl_tn = l1a_l1s_com.dl_tn;
544 #endif
545 READ_PARAM.new_set = 0;
546 READ_PARAM.assignment_id = ASET->assignment_id;
547 READ_PARAM.allocated_tbf = ASET->allocated_tbf;
548 READ_PARAM.dl_tfi = ASET->dl_tbf_alloc.tfi;
549 READ_PARAM.ul_tfi = ASET->ul_tbf_alloc->tfi;
550 READ_PARAM.dl_pwr_ctl = ASET->dl_pwr_ctl;
551 READ_PARAM.pc_meas_chan = ASET->pc_meas_chan;
552
553 // We need to know on which frequency band we work for LNA state processing
554 if (!l1pa_l1ps_com.transfer.aset->freq_param.chan_sel.h)
555 {
556 // Single frequency
557 READ_PARAM.radio_freq_for_lna = l1pa_l1ps_com.transfer.aset->freq_param.chan_sel.rf_channel.single_rf.radio_freq;
558 }
559 else
560 {
561 // Frequency hopping: all frequencies of the frequency list are on the same band
562 // We take the first frequency of the list
563 READ_PARAM.radio_freq_for_lna = l1pa_l1ps_com.transfer.aset->freq_param.freq_list.rf_chan_no.A[0];
564 }
565 }
566 #endif