blob: 65aaf9bde5f47b34d4be05b57b46792d14478b96 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001/*
2** Copyright (c) 2015-2017 by Silicon Laboratories
3**
4** $Id: si3218x_intf.c 6502 2017-05-05 02:35:39Z nizajerk $
5**
6** SI3218X ProSLIC interface implementation file
7**
8** Author(s):
9** cdp
10**
11** Distributed by:
12** Silicon Laboratories, Inc
13**
14** This file contains proprietary information.
15** No dissemination allowed without prior written permission from
16** Silicon Laboratories, Inc.
17**
18*/
19
20#include "si_voice_datatypes.h"
21#include "si_voice_ctrl.h"
22#include "si_voice_timer_intf.h"
23#include "proslic.h"
24#include "si3218x.h"
25#include "si3218x_intf.h"
26#include "si3218x_registers.h"
27#include "proslic_api_config.h"
28
29#define SI3218X_IRING_LIM_MAX 0xA00000L /* 103mA */
30#define SI3218X_REVA 2
31
32#define WriteReg pProslic->deviceId->ctrlInterface->WriteRegister_fptr
33#define ReadReg pProslic->deviceId->ctrlInterface->ReadRegister_fptr
34#define pProHW pProslic->deviceId->ctrlInterface->hCtrl
35#define Reset pProslic->deviceId->ctrlInterface->Reset_fptr
36#define Delay pProslic->deviceId->ctrlInterface->Delay_fptr
37#define pProTimer pProslic->deviceId->ctrlInterface->hTimer
38#define WriteRAM pProslic->deviceId->ctrlInterface->WriteRAM_fptr
39#define ReadRAM pProslic->deviceId->ctrlInterface->ReadRAM_fptr
40#define TimeElapsed pProslic->deviceId->ctrlInterface->timeElapsed_fptr
41#define getTime pProslic->deviceId->ctrlInterface->getTime_fptr
42
43#define WriteRegX deviceId->ctrlInterface->WriteRegister_fptr
44#define ReadRegX deviceId->ctrlInterface->ReadRegister_fptr
45#define pProHWX deviceId->ctrlInterface->hCtrl
46#define DelayX deviceId->ctrlInterface->Delay_fptr
47#define pProTimerX deviceId->ctrlInterface->hTimer
48#define ReadRAMX deviceId->ctrlInterface->ReadRAM_fptr
49#define WriteRAMX deviceId->ctrlInterface->WriteRAM_fptr
50
51#define DEVICE_KEY_MIN 0x6E
52#define DEVICE_KEY_MAX 0x77
53
54#ifdef ENABLE_DEBUG
55static const char LOGPRINT_PREFIX[] = "Si3218x: ";
56#endif
57
58/*
59** Externs
60*/
61
62/* General Configuration */
63extern Si3218x_General_Cfg Si3218x_General_Configuration;
64#ifdef SIVOICE_MULTI_BOM_SUPPORT
65extern const proslicPatch SI3218X_PATCH_A;
66extern Si3218x_General_Cfg Si3218x_General_Configuration_MultiBOM[];
67extern int si3218x_genconf_multi_max_preset;
68#else
69extern const proslicPatch SI3218X_PATCH_A_DEFAULT;
70#endif
71
72/* Ringing */
73#ifndef DISABLE_RING_SETUP
74extern Si3218x_Ring_Cfg Si3218x_Ring_Presets[];
75#endif
76
77/* Zsynth */
78#ifndef DISABLE_ZSYNTH_SETUP
79extern Si3218x_Impedance_Cfg Si3218x_Impedance_Presets [];
80#endif
81
82/* Audio Gain Scratch */
83extern Si3218x_audioGain_Cfg Si3218x_audioGain_Presets[];
84
85/* Pulse Metering */
86#ifndef DISABLE_PULSE_SETUP
87extern Si3218x_PulseMeter_Cfg Si3218x_PulseMeter_Presets [];
88#endif
89
90/* PCM */
91#ifndef DISABLE_PCM_SETUP
92extern Si3218x_PCM_Cfg Si3218x_PCM_Presets [];
93#endif
94
95#define SI3218X_RAM_DCDC_DCFF_ENABLE SI3218X_RAM_GENERIC_8
96#define GCONF Si3218x_General_Configuration
97
98/*
99** Constants
100*/
101#define BIT20LSB 1048576L
102#define OITHRESH_OFFS 900L
103#define OITHRESH_SCALE 100L
104#define OVTHRESH_OFFS 71000
105#define OVTHRESH_SCALE 3000L
106#define UVTHRESH_OFFS 4057L
107#define UVTHRESH_SCALE 187L
108#define UVHYST_OFFS 548L
109#define UVHYST_SCALE 47L
110
111/*
112** Local functions are defined first
113*/
114
115/*
116** Function: getChipType
117**
118** Description:
119** Decode ID register to identify chip type
120**
121** Input Parameters:
122** ID register value
123**
124** Return:
125** partNumberType
126*/
127static partNumberType getChipType(uInt8 data)
128{
129 /* For the parts that have a HV variant, we map to the lower voltage version,
130 the actual differences are handled in the constants file
131 */
132
133 const uInt8 partNums[8] =
134 {
135 UNSUPPORTED_PART_NUM, UNSUPPORTED_PART_NUM, UNSUPPORTED_PART_NUM, UNSUPPORTED_PART_NUM,
136 SI32184, SI32182, SI32185, SI32183
137 };
138
139 uInt8 partNum = (data & 0x38) >> 3; /* PART_NUM[2:0] = ID[5:3] */
140
141 return partNums[ partNum ];
142}
143
144int Si3218x_GetChipInfo(proslicChanType_ptr pProslic)
145{
146 uInt8 id;
147 id = ReadReg(pProHW, pProslic->channel, PROSLIC_REG_ID);
148
149 pProslic->deviceId->chipRev = id & 0x7;
150 pProslic->deviceId->chipType = getChipType(id);
151
152 if(pProslic->deviceId->chipType == UNSUPPORTED_PART_NUM)
153 {
154#ifdef ENABLE_DEBUG
155 LOGPRINT("%sregister 0 read = 0x%02X\n", LOGPRINT_PREFIX, id);
156#endif
157 return RC_SPI_FAIL;
158 }
159 else
160 {
161 return RC_NONE;
162 }
163}
164
165/*
166** Function: Si3218x_ConverterSetup
167**
168** Description:
169** Program revision specific settings before powering converter
170**
171** Specifically, from general parameters and knowledge that this
172** is Si32188x, setup dcff drive, gate drive polarity, and charge pump.
173**
174** Returns:
175** int (error)
176**
177*/
178int Si3218x_ConverterSetup(proslicChanType_ptr pProslic)
179{
180 ramData inv_off;
181
182 /* Option to add a per-channel inversion for maximum flexibility */
183 if(pProslic->dcdc_polarity_invert)
184 {
185 inv_off = 0x100000L;
186 }
187 else
188 {
189 inv_off = 0x0L;
190 }
191
192 switch(Si3218x_General_Configuration.bom_option)
193 {
194 case BO_DCDC_LCQC_5W:
195 case BO_DCDC_LCCB:
196 case BO_DCDC_LCCB110:
197 WriteRAM(pProHW, pProslic->channel,SI3218X_RAM_DCDC_LIFT_EN,
198 0x0L); /* dcff disabled */
199 WriteRAM(pProHW, pProslic->channel,SI3218X_RAM_DCDC_SWDRV_POL,
200 inv_off); /* non-inverted */
201 WriteRAM(pProHW, pProslic->channel,SI3218X_RAM_DCDC_CPUMP,
202 0x100000L); /* Charge pump on */
203 Delay(pProTimer,20); /* Cpump settle */
204 break;
205
206 case BO_DCDC_BUCK_BOOST:
207 /*
208 ** RevC buck-boost designs are identical to RevB - no gate drive,
209 ** dcff enabled, non-inverting (charge pump off)
210 */
211 WriteRAM(pProHW, pProslic->channel,SI3218X_RAM_DCDC_CPUMP,0x0L);
212 WriteRAM(pProHW, pProslic->channel,SI3218X_RAM_DCDC_SWDRV_POL,inv_off);
213 WriteRAM(pProHW, pProslic->channel,SI3218X_RAM_DCDC_LIFT_EN,
214 0x100000L); /* dcff enabled */
215 break;
216
217 default:
218 return RC_DCDC_SETUP_ERR;
219 }
220
221 return RC_NONE;
222}
223
224/*
225** Function: Si3218x_PowerUpConverter
226**
227** Description:
228** Powers all DC/DC converters sequentially with delay to minimize
229** peak power draw on VDC.
230**
231** Returns:
232** int (error)
233**
234*/
235
236int Si3218x_PowerUpConverter(proslicChanType_ptr pProslic)
237{
238 errorCodeType error = RC_DCDC_SETUP_ERR;
239 int32 vbath,vbat;
240 uInt8 reg = 0;
241 int timer = 0;
242
243
244 if(pProslic->channelType != PROSLIC)
245 {
246 return RC_CHANNEL_TYPE_ERR;
247 }
248
249 /*
250 ** - powerup digital dc/dc w/ OV clamping and shutdown
251 ** - delay
252 ** - verify no short circuits by looking for vbath/2
253 ** - clear dcdc status
254 ** - switch to analog converter with OV clamping only (no shutdown)
255 ** - select analog dcdc and disable pwrsave
256 ** - delay
257 */
258
259 WriteReg(pProHW,pProslic->channel,SI3218X_REG_LINEFEED,
260 LF_FWD_OHT); /* Force out of pwrsave mode if called in error */
261 WriteReg(pProHW,pProslic->channel,SI3218X_REG_LINEFEED,
262 LF_OPEN); /* Ensure open line before powering up converter */
263 reg = ReadReg(pProHW,pProslic->channel,SI3218X_REG_ENHANCE);
264 WriteReg(pProHW,pProslic->channel,SI3218X_REG_ENHANCE,
265 reg&0x07); /* Disable powersave mode */
266
267 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_PD_DCDC,
268 0x700000L); /* In case OV or UV previously occurred */
269
270 /*
271 ** Setup converter drive polarity and charge pump enable
272 ** based on bom
273 */
274
275 error = Si3218x_ConverterSetup(pProslic);
276
277 if(error != RC_NONE)
278 {
279 DEBUG_PRINT (pProslic, "%sChannel %d : DCDC initialization failed\n",
280 LOGPRINT_PREFIX, pProslic->channel);
281 return error;
282 }
283
284 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_PD_DCDC,0x600000L);
285 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_PD_BIAS,0x200000L);
286 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_PD_HVIC,0x200000L);
287 Delay(pProTimer,50);
288
289 vbath = ReadRAM(pProHW,pProslic->channel,SI3218X_RAM_VBATH_EXPECT);
290 vbat = ReadRAM(pProHW,pProslic->channel,SI3218X_RAM_MADC_VBAT);
291 if(vbat & 0x10000000L)
292 {
293 vbat |= 0xF0000000L;
294 }
295 if(vbat < (vbath / 2))
296 {
297 pProslic->channelEnable = 0;
298 error = RC_VBAT_UP_TIMEOUT;
299 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_PD_DCDC,
300 0x300000L); /* shutdown converter */
301 DEBUG_PRINT (pProslic,
302 "%sChannel %d : DCDC Short Circuit Failure - disabling channel\n%sVBAT = %d.%d\n",
303 LOGPRINT_PREFIX, pProslic->channel, LOGPRINT_PREFIX,
304 (int)((vbat/SCALE_V_MADC)/1000),
305 (int)(((vbat/SCALE_V_MADC) - (vbat/SCALE_V_MADC)/1000*1000)));
306 return error;
307 }
308 else /* Enable analog converter */
309 {
310 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_DCDC_STATUS,0L);
311 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_PD_DCDC,0x400000L);
312 WriteReg(pProHW,pProslic->channel,SI3218X_REG_ENHANCE,
313 reg); /* Restore ENHANCE */
314 Delay(pProTimer,50);
315 }
316
317 /*
318 ** - monitor vbat vs expected level (VBATH_EXPECT)
319 */
320 vbath = ReadRAM(pProHW,pProslic->channel,SI3218X_RAM_VBATH_EXPECT);
321 do
322 {
323 vbat = ReadRAM(pProHW,pProslic->channel,SI3218X_RAM_MADC_VBAT);
324 if(vbat & 0x10000000L)
325 {
326 vbat |= 0xF0000000L;
327 }
328 Delay(pProTimer,10);
329 }
330 while((vbat < (vbath - COMP_5V))
331 &&(timer++ < SI3218X_TIMEOUT_DCDC_UP)); /* 2 sec timeout */
332
333 DEBUG_PRINT (pProslic, "%sChannel %d : VBAT Up = %d.%d v\n",
334 LOGPRINT_PREFIX,
335 pProslic->channel,(int)((vbat/SCALE_V_MADC)/1000),
336 (int)(((vbat/SCALE_V_MADC) - (vbat/SCALE_V_MADC)/1000*1000)));
337 if(timer > SI3218X_TIMEOUT_DCDC_UP)
338 {
339 /* Error handling - shutdown converter, disable channel, set error tag */
340 pProslic->channelEnable = 0;
341 error = RC_VBAT_UP_TIMEOUT;
342 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_PD_DCDC,
343 0x900000L); /* shutdown converter */
344 DEBUG_PRINT (pProslic, "%sChannel %d : DCDC Power up timeout : Status=0x%08X\n",
345 LOGPRINT_PREFIX, pProslic->channel, ReadRAM(pProHW,pProslic->channel,
346 SI3218X_RAM_DCDC_STATUS));
347 }
348
349 return error;
350}
351
352/*
353**
354** PROSLIC INITIALIZATION FUNCTIONS
355**
356*/
357
358/*
359** Function: Si3218x_Init_MultiBOM
360**
361** Description:
362** - probe SPI to establish daisy chain length
363** - load patch
364** - initialize general parameters
365** - calibrate madc
366** - bring up DC/DC converters
367** - calibrate everything except madc & lb
368**
369** Input Parameters:
370** pProslic: pointer to PROSLIC object array
371** fault: error code
372**
373** Return:
374** error code
375*/
376
377#ifdef SIVOICE_MULTI_BOM_SUPPORT
378int Si3218x_Init_MultiBOM (proslicChanType_ptr *pProslic, int size, int preset)
379{
380
381 if(preset < si3218x_genconf_multi_max_preset)
382 {
383 /* Copy selected General Configuration parameters to Std structure */
384 Si3218x_General_Configuration = Si3218x_General_Configuration_MultiBOM[preset];
385 }
386 else
387 {
388 return RC_INVALID_PRESET;
389 }
390 return Si3218x_Init_with_Options(pProslic,size, INIT_NO_OPT);
391}
392#endif
393
394
395/*
396** Function: Si3218x_SelectPatch
397**
398** Select patch based on general parameters
399**
400** Input Parameters:
401** pProslic: pointer to PROSLIC object array
402** fault: error code
403** patch: Pointer to proslicPatch pointer
404**
405** Return:
406** error code
407*/
408int Si3218x_SelectPatch(proslicChanType_ptr pProslic,
409 const proslicPatch **patch)
410{
411
412#ifdef SIVOICE_MULTI_BOM_SUPPORT
413 if(Si3218x_General_Configuration.bom_option == BO_DCDC_LCQC_5W
414 || Si3218x_General_Configuration.bom_option == BO_DCDC_LCCB
415 || Si3218x_General_Configuration.bom_option == BO_DCDC_LCCB110
416 || Si3218x_General_Configuration.bom_option == BO_DCDC_BUCK_BOOST)
417 {
418 *patch = &(SI3218X_PATCH_A);
419 }
420 else
421 {
422 DEBUG_PRINT(pProslic, "%sChannel %d : Invalid Patch\n", LOGPRINT_PREFIX,
423 pProslic->channel);
424 pProslic->channelEnable = 0;
425 pProslic->error = RC_INVALID_PATCH;
426 return RC_INVALID_PATCH;
427 }
428#else
429 SILABS_UNREFERENCED_PARAMETER(pProslic);
430 *patch = &(SI3218X_PATCH_A_DEFAULT);
431#endif
432
433 return RC_NONE;
434}
435
436/*
437** Function: Si3218x_GenParamUpdate
438**
439** Update general parameters
440**
441** Input Parameters:
442** pProslic: pointer to PROSLIC object array
443** fault: error code
444**
445** Return:
446** error code
447*/
448
449int Si3218x_GenParamUpdate(proslicChanType_ptr pProslic,initSeqType seq)
450{
451 ramData ram_data;
452 uInt8 data;
453
454 switch(seq)
455 {
456 case INIT_SEQ_PRE_CAL:
457 /*
458 ** Force pwrsave off and disable AUTO-tracking - set to user configured state after cal
459 */
460 WriteReg(pProHW, pProslic->channel,SI3218X_REG_ENHANCE,0);
461 WriteReg(pProHW, pProslic->channel,SI3218X_REG_AUTO,0x2F);
462
463 /*
464 ** General Parameter Updates
465 */
466
467 WriteRAM(pProHW, pProslic->channel,SI3218X_RAM_P_TH_HVIC,
468 Si3218x_General_Configuration.p_th_hvic);
469 WriteRAM(pProHW, pProslic->channel,SI3218X_RAM_COEF_P_HVIC,
470 Si3218x_General_Configuration.coef_p_hvic);
471 WriteRAM(pProHW, pProslic->channel,SI3218X_RAM_BAT_HYST,
472 Si3218x_General_Configuration.bat_hyst);
473 WriteRAM(pProHW, pProslic->channel,SI3218X_RAM_VBATH_EXPECT,
474 Si3218x_General_Configuration.vbath_expect);
475 WriteRAM(pProHW, pProslic->channel,SI3218X_RAM_VBATR_EXPECT,
476 Si3218x_General_Configuration.vbatr_expect);
477
478 WriteRAM(pProHW, pProslic->channel,SI3218X_RAM_PWRSAVE_TIMER,
479 Si3218x_General_Configuration.pwrsave_timer);
480 WriteRAM(pProHW, pProslic->channel,SI3218X_RAM_OFFHOOK_THRESH,
481 Si3218x_General_Configuration.pwrsave_ofhk_thresh);
482 WriteRAM(pProHW, pProslic->channel,SI3218X_RAM_VBAT_TRACK_MIN,
483 Si3218x_General_Configuration.vbat_track_min);
484 WriteRAM(pProHW, pProslic->channel,SI3218X_RAM_VBAT_TRACK_MIN_RNG,
485 Si3218x_General_Configuration.vbat_track_min_rng);
486
487 WriteRAM(pProHW, pProslic->channel,SI3218X_RAM_THERM_DBI,
488 Si3218x_General_Configuration.therm_dbi);
489 WriteRAM(pProHW, pProslic->channel,SI3218X_RAM_VOV_DCDC_SLOPE,
490 Si3218x_General_Configuration.vov_dcdc_slope);
491 WriteRAM(pProHW, pProslic->channel,SI3218X_RAM_VOV_DCDC_OS,
492 Si3218x_General_Configuration.vov_dcdc_os);
493 WriteRAM(pProHW, pProslic->channel,SI3218X_RAM_VOV_RING_BAT_MAX,
494 Si3218x_General_Configuration.vov_ring_bat_max);
495 WriteRAM(pProHW, pProslic->channel,SI3218X_RAM_DCDC_VERR,
496 Si3218x_General_Configuration.dcdc_verr);
497 WriteRAM(pProHW, pProslic->channel,SI3218X_RAM_DCDC_VERR_HYST,
498 Si3218x_General_Configuration.dcdc_verr_hyst);
499
500 WriteRAM(pProHW, pProslic->channel,SI3218X_RAM_PD_UVLO,
501 Si3218x_General_Configuration.pd_uvlo);
502 WriteRAM(pProHW, pProslic->channel,SI3218X_RAM_PD_OVLO,
503 Si3218x_General_Configuration.pd_ovlo);
504 WriteRAM(pProHW, pProslic->channel,SI3218X_RAM_PD_OCLO,
505 Si3218x_General_Configuration.pd_oclo);
506 WriteRAM(pProHW, pProslic->channel,SI3218X_RAM_PD_SWDRV,
507 Si3218x_General_Configuration.pd_swdrv);
508
509 WriteRAM(pProHW, pProslic->channel,SI3218X_RAM_DCDC_UVPOL,
510 Si3218x_General_Configuration.dcdc_uvpol);
511
512 WriteRAM(pProHW, pProslic->channel,SI3218X_RAM_DCDC_RNGTYPE,
513 Si3218x_General_Configuration.dcdc_rngtype);
514
515 WriteRAM(pProHW, pProslic->channel,SI3218X_RAM_DCDC_ANA_TOFF,
516 Si3218x_General_Configuration.dcdc_ana_toff);
517 WriteRAM(pProHW, pProslic->channel,SI3218X_RAM_DCDC_ANA_TONMIN,
518 Si3218x_General_Configuration.dcdc_ana_tonmin);
519 WriteRAM(pProHW, pProslic->channel,SI3218X_RAM_DCDC_ANA_TONMAX,
520 Si3218x_General_Configuration.dcdc_ana_tonmax);
521
522
523 /*
524 ** Hardcoded RAM
525 */
526
527 WriteRAM(pProHW, pProslic->channel,SI3218X_RAM_DCDC_OITHRESH_LO,
528 GCONF.i_oithresh_lo);
529 WriteRAM(pProHW, pProslic->channel,SI3218X_RAM_DCDC_OITHRESH_HI,
530 GCONF.i_oithresh_hi);
531 WriteRAM(pProHW, pProslic->channel,SI3218X_RAM_DCDC_OVTHRESH,GCONF.v_ovthresh);
532
533 ram_data = (GCONF.v_uvthresh > UVTHRESH_OFFS)?(GCONF.v_uvthresh -
534 UVTHRESH_OFFS)/UVTHRESH_SCALE:0L;
535 ram_data *= BIT20LSB;
536 WriteRAM(pProHW, pProslic->channel,SI3218X_RAM_DCDC_UVTHRESH,ram_data);
537
538 ram_data = (GCONF.v_uvhyst > UVHYST_OFFS)?(GCONF.v_uvhyst -
539 UVHYST_OFFS)/UVHYST_SCALE:0L;
540 ram_data *= BIT20LSB;
541 WriteRAM(pProHW, pProslic->channel,SI3218X_RAM_DCDC_UVHYST,ram_data);
542
543 /* Set default audio gain based on PM bom */
544 if(Si3218x_General_Configuration.pm_bom == BO_PM_BOM)
545 {
546 WriteRAM(pProHW, pProslic->channel,SI3218X_RAM_SCALE_KAUDIO,BOM_KAUDIO_PM);
547 WriteRAM(pProHW, pProslic->channel,SI3218X_RAM_AC_ADC_GAIN,BOM_AC_ADC_GAIN_PM);
548 }
549 else
550 {
551 WriteRAM(pProHW, pProslic->channel,SI3218X_RAM_SCALE_KAUDIO,BOM_KAUDIO_NO_PM);
552 WriteRAM(pProHW, pProslic->channel,SI3218X_RAM_AC_ADC_GAIN,
553 BOM_AC_ADC_GAIN_NO_PM);
554 }
555
556 /*
557 ** Hardcoded changes to default settings
558 */
559 data = ReadReg(pProHW, pProslic->channel,SI3218X_REG_GPIO_CFG1);
560 data &= 0xF9; /* Clear DIR for GPIO 1&2 */
561 data |= 0x60; /* Set ANA mode for GPIO 1&2 */
562 WriteReg(pProHW,pProslic->channel,SI3218X_REG_GPIO_CFG1,
563 data); /* coarse sensors analog mode */
564 WriteReg(pProHW,pProslic->channel,SI3218X_REG_PDN,
565 0x80); /* madc powered in open state */
566 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACHPF_A1_1,
567 0x71EB851L); /* Fix HPF corner */
568 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_PD_REF_OSC,
569 0x200000L); /* PLL freerun workaround */
570 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_ILOOPLPF,
571 0x4EDDB9L); /* 20pps pulse dialing enhancement */
572 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_ILONGLPF,
573 0x806D6L); /* 20pps pulse dialing enhancement */
574 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_VDIFFLPF,
575 0x10038DL); /* 20pps pulse dialing enhancement */
576 WriteRAM(pProHW, pProslic->channel,SI3218X_RAM_DCDC_VREF_CTRL,0x0L);
577 WriteRAM(pProHW, pProslic->channel,SI3218X_RAM_VCM_TH,0x106240L);
578 WriteRAM(pProHW, pProslic->channel,SI3218X_RAM_VCMLPF,0x10059FL);
579 WriteRAM(pProHW, pProslic->channel,SI3218X_RAM_CM_SPEEDUP_TIMER,0x0F0000);
580 WriteRAM(pProHW, pProslic->channel,SI3218X_RAM_VCM_HYST,0x206280L);
581
582 /* Prevent Ref Osc from powering down in PLL Freerun mode (pd_ref_osc) */
583 ram_data = ReadRAM(pProHW, pProslic->channel,SI3218X_RAM_PWRSAVE_CTRL_LO);
584 WriteRAM(pProHW, pProslic->channel,SI3218X_RAM_PWRSAVE_CTRL_LO,
585 ram_data&0x07FFFFFFL); /* clear b27 */
586 break;
587
588
589 case INIT_SEQ_POST_CAL:
590 WriteReg(pProHW, pProslic->channel,SI3218X_REG_ENHANCE,
591 Si3218x_General_Configuration.enhance&0x1F);
592 WriteReg(pProHW, pProslic->channel,SI3218X_REG_AUTO,
593 Si3218x_General_Configuration.auto_reg);
594 if(Si3218x_General_Configuration.zcal_en)
595 {
596 WriteReg(pProHW,pProslic->channel, SI3218X_REG_ZCAL_EN, 0x04);
597 }
598 break;
599
600 default:
601 break;
602 }
603 return RC_NONE;
604}
605
606/*
607** Function: Si3218x_Init_with_Options
608**
609** Description:
610** - probe SPI to establish daisy chain length
611** - load patch
612** - initialize general parameters
613** - calibrate madc
614** - bring up DC/DC converters
615** - calibrate everything except madc & lb
616**
617** Input Parameters:
618** pProslic: pointer to PROSLIC object array
619** fault: error code
620**
621** Return:
622** error code
623*/
624
625int Si3218x_Init_with_Options (proslicChanType_ptr *pProslic, int size,
626 initOptionsType init_opt)
627{
628 /*
629 ** This function will initialize the chipRev and chipType members in pProslic
630 ** as well as load the initialization structures.
631 */
632
633 uInt8 data;
634 uInt8 calSetup[] = {0x00, 0x00, 0x01, 0x80}; /* CALR0-CALR3 */
635 int k, device_count;
636 const proslicPatch *patch;
637 uInt8 status;
638
639 LOGPRINT("%s(%d) size = %d init_opt = %d\n", __FUNCTION__, __LINE__, size,
640 init_opt);
641 /*
642 **
643 ** First qualify general parameters by identifying valid device key. This
644 ** will prevent inadvertent use of other device's preset files, which could
645 ** lead to improper initialization and high current states.
646 */
647
648 data = Si3218x_General_Configuration.device_key;
649
650 if((data < DEVICE_KEY_MIN)||(data > DEVICE_KEY_MAX))
651 {
652 pProslic[0]->error = RC_INVALID_GEN_PARAM;
653 return pProslic[0]->error;
654 }
655
656 /* reset error code */
657 for(k = 0; k < size; k++)
658 {
659 pProslic[k]->error = RC_NONE;
660 }
661
662 if( (init_opt == INIT_REINIT) || (init_opt == INIT_SOFTRESET) )
663 {
664 ProSLIC_ReInit_helper(pProslic, size, init_opt, SI3218X_CHAN_PER_DEVICE);
665
666 /* for single channel devices, we need do a full restore.. */
667 if(init_opt == INIT_REINIT)
668 {
669 init_opt = 0;
670 }
671}
672
673 if( init_opt != INIT_REINIT )
674 {
675 if( (SiVoice_IdentifyChannels(pProslic, size, &device_count, NULL) != RC_NONE)
676 ||(device_count == 0) )
677 {
678 DEBUG_PRINT(*pProslic, "%s: failed to detect any ProSLICs\n", LOGPRINT_PREFIX);
679 return RC_SPI_FAIL;
680 }
681
682 /*
683 ** Probe each channel and enable all channels that respond
684 */
685 for (k=0; k<size; k++)
686 {
687 if ((pProslic[k]->channelEnable)
688 &&(pProslic[k]->channelType == PROSLIC))
689 {
690 if ( (ProSLIC_VerifyMasterStat(pProslic[k]) != RC_NONE)
691 || (ProSLIC_VerifyControlInterface(pProslic[k]) != RC_NONE) )
692 {
693 pProslic[k]->channelEnable = 0;
694 pProslic[k]->error = RC_SPI_FAIL;
695 DEBUG_PRINT(*pProslic, "%s: SPI communications or PCLK/FS failure\n", LOGPRINT_PREFIX);
696 return pProslic[k]->error; /* Halt init if SPI fail */
697 }
698 }
699 }
700 } /* init_opt !REINIT */
701
702
703 if( (init_opt != INIT_NO_PATCH_LOAD ) && (init_opt != INIT_REINIT) )
704 {
705 /*
706 ** Load patch (load on every channel since single channel device)
707 */
708 for (k=0; k<size; k++)
709 {
710 if ((pProslic[k]->channelEnable)&&(pProslic[k]->channelType == PROSLIC))
711 {
712
713 /* Select Patch*/
714 if (pProslic[k]->deviceId->chipRev == SI3218X_REVA )
715 {
716 status = (uInt8) Si3218x_SelectPatch(pProslic[k],&patch);
717 }
718 else
719 {
720 DEBUG_PRINT(pProslic[k], "%sChannel %d : Unsupported Device Revision (%d)\n",
721 LOGPRINT_PREFIX, pProslic[k]->channel,pProslic[k]->deviceId->chipRev );
722 pProslic[k]->channelEnable = 0;
723 pProslic[k]->error = RC_UNSUPPORTED_DEVICE_REV;
724 return RC_UNSUPPORTED_DEVICE_REV;
725 }
726
727 data = 1; /* Use this as a flag to see if we need to load the patch */
728 /* If the patch doesn't match, we need to do a full init, change settings */
729 if(init_opt == INIT_SOFTRESET)
730 {
731 ramData patchData;
732 patchData = pProslic[k]->ReadRAMX(pProslic[k]->pProHWX, pProslic[k]->channel,
733 PROSLIC_RAM_PATCHID);
734
735 if( patchData == patch->patchSerial)
736 {
737 data = 0;
738 }
739 else
740 {
741 init_opt = INIT_NO_OPT;
742 }
743 } /* SOFTRESET */
744
745 /* Load Patch */
746 if(status == RC_NONE)
747 {
748 if(data == 1)
749 {
750 Si3218x_LoadPatch(pProslic[k],patch);
751#ifndef DISABLE_VERIFY_PATCH
752 /* Optional Patch Verification */
753 data = (uInt8)Si3218x_VerifyPatch(pProslic[k],patch);
754 if (data != RC_NONE)
755 {
756 DEBUG_PRINT(pProslic[k], "%sChannel %d : Patch verification failed (%d)\n",
757 LOGPRINT_PREFIX, k, data);
758 pProslic[k]->channelEnable=0;
759 pProslic[k]->error = RC_PATCH_ERR;
760 return data;
761 }
762#endif
763 }
764 }
765 else
766 {
767 return status;
768 }
769 } /* channel == PROSLIC */
770 } /* for all channles */
771 }/* init_opt - need to reload patch */
772
773 /*
774 ** Load general parameters - includes all BOM dependencies
775 */
776 if(init_opt != INIT_SOFTRESET)
777 {
778 for (k=0; k<size; k++)
779 {
780 if ((pProslic[k]->channelEnable)&&(pProslic[k]->channelType == PROSLIC))
781 {
782 Si3218x_GenParamUpdate(pProslic[k],INIT_SEQ_PRE_CAL);
783 }
784
785 pProslic[k]->WriteRAMX(pProslic[k]->pProHWX,pProslic[k]->channel,
786 SI3218X_RAM_IRING_LIM,SI3218X_IRING_LIM_MAX);
787 }
788 }
789
790 if((init_opt != INIT_NO_CAL)
791 && (init_opt != INIT_SOFTRESET)) /* Must recal on single channel devices */
792 {
793 /*
794 ** Calibrate (madc offset)
795 */
796 ProSLIC_Calibrate(pProslic,size,calSetup,TIMEOUT_MADC_CAL);
797 }/* init_opt */
798
799 /*
800 ** Bring up DC/DC converters sequentially to minimize
801 ** peak power demand on VDC
802 */
803 for (k=0; k<size; k++)
804 {
805 if ((pProslic[k]->channelEnable)&&(pProslic[k]->channelType == PROSLIC))
806 {
807 pProslic[k]->error = Si3218x_PowerUpConverter(pProslic[k]);
808 }
809 }
810
811 if((init_opt != INIT_NO_CAL) && (init_opt != INIT_SOFTRESET))
812 {
813 /*
814 ** Calibrate remaining cals (except madc, lb)
815 */
816 calSetup[1] = SI3218X_CAL_STD_CALR1;
817 calSetup[2] = SI3218X_CAL_STD_CALR2;
818
819 ProSLIC_Calibrate(pProslic,size,calSetup,TIMEOUT_GEN_CAL);
820 }
821
822 /*
823 ** Apply post calibration general parameters
824 */
825 if(init_opt != INIT_SOFTRESET)
826 {
827 for (k=0; k<size; k++)
828 {
829
830 if ((pProslic[k]->channelEnable)&&(pProslic[k]->channelType == PROSLIC))
831 {
832 Si3218x_GenParamUpdate(pProslic[k],INIT_SEQ_POST_CAL);
833 }
834 }
835 }
836
837 /* Restore linefeed state after initialization for REINIT/SOFTRESET */
838 if( (init_opt == INIT_REINIT) || (init_opt == INIT_SOFTRESET) )
839 {
840 for(k = 0; k < size; k++)
841 {
842 pProslic[k]->WriteRegX(pProslic[k]->pProHWX,pProslic[k]->channel,
843 SI3218X_REG_LINEFEED,pProslic[k]->scratch);
844 }
845 }
846
847 /*
848 ** If any channel incurred a non-fatal error, return
849 ** RC_NON_FATAL_INIT_ERR to trigger user to read each channel's
850 ** error status
851 */
852 for (k=0; k<size; k++)
853 {
854 if(pProslic[k]->error != RC_NONE)
855 {
856 return RC_NON_FATAL_INIT_ERR;
857 }
858 }
859
860 return RC_NONE;
861}
862
863/*
864** Function: Si3218x_EnableInterrupts
865**
866** Description:
867** Enables interrupts
868**
869** Input Parameters:
870** pProslic: pointer to PROSLIC channel obj
871**
872** Returns:
873** 0
874*/
875
876int Si3218x_EnableInterrupts (proslicChanType_ptr pProslic)
877{
878 uInt8 i;
879#ifdef GCI_MODE
880 uInt8 data;
881#endif
882 /* Clear pending interrupts first */
883 for(i = SI3218X_REG_IRQ1; i < SI3218X_REG_IRQ4; i++)
884 {
885#ifdef GCI_MODE
886 data = ReadReg(pProHW,pProslic->channel, i);
887 WriteReg(pProHW,pProslic->channel,i,data); /*clear interrupts (gci only)*/
888#else
889 (void)ReadReg(pProHW,pProslic->channel, i);
890#endif
891
892 }
893
894 WriteReg (pProHW,pProslic->channel,SI3218X_REG_IRQEN1,
895 Si3218x_General_Configuration.irqen1);
896 WriteReg (pProHW,pProslic->channel,SI3218X_REG_IRQEN2,
897 Si3218x_General_Configuration.irqen2);
898 WriteReg (pProHW,pProslic->channel,SI3218X_REG_IRQEN3,
899 Si3218x_General_Configuration.irqen3);
900 WriteReg (pProHW,pProslic->channel,SI3218X_REG_IRQEN4,
901 Si3218x_General_Configuration.irqen4);
902
903 return RC_NONE;
904}
905
906/*
907**
908** PROSLIC CONFIGURATION FUNCTIONS
909**
910*/
911
912/*
913** Function: Si3218x_RingSetup
914**
915** Description:
916** configure ringing
917**
918** Input Parameters:
919** pProslic: pointer to PROSLIC channel obj
920** preset: ring preset
921**
922** Returns:
923** 0
924*/
925
926#ifndef DISABLE_RING_SETUP
927int Si3218x_RingSetup (proslicChanType *pProslic, int preset)
928{
929
930 if(pProslic->channelType != PROSLIC)
931 {
932 return RC_CHANNEL_TYPE_ERR;
933 }
934
935 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RTPER,
936 Si3218x_Ring_Presets[preset].rtper);
937 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RINGFR,
938 Si3218x_Ring_Presets[preset].freq);
939 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RINGAMP,
940 Si3218x_Ring_Presets[preset].amp);
941 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RINGPHAS,
942 Si3218x_Ring_Presets[preset].phas);
943 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RINGOF,
944 Si3218x_Ring_Presets[preset].offset);
945 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_SLOPE_RING,
946 Si3218x_Ring_Presets[preset].slope_ring);
947
948 if(Si3218x_Ring_Presets[preset].iring_lim > SI3218X_IRING_LIM_MAX)
949 {
950 Si3218x_Ring_Presets[preset].iring_lim = SI3218X_IRING_LIM_MAX;
951 }
952
953 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_IRING_LIM,
954 Si3218x_Ring_Presets[preset].iring_lim);
955 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RTACTH,
956 Si3218x_Ring_Presets[preset].rtacth);
957 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RTDCTH,
958 Si3218x_Ring_Presets[preset].rtdcth);
959 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RTACDB,
960 Si3218x_Ring_Presets[preset].rtacdb);
961 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RTDCDB,
962 Si3218x_Ring_Presets[preset].rtdcdb);
963 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_VOV_RING_BAT,
964 Si3218x_Ring_Presets[preset].vov_ring_bat);
965 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_VOV_RING_GND,
966 Si3218x_Ring_Presets[preset].vov_ring_gnd);
967
968#ifndef NOCLAMP_VBATR
969 /* Always limit VBATR_EXPECT to the general configuration maximum */
970 if(Si3218x_Ring_Presets[preset].vbatr_expect >
971 Si3218x_General_Configuration.vbatr_expect)
972 {
973 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_VBATR_EXPECT,
974 Si3218x_General_Configuration.vbatr_expect);
975 DEBUG_PRINT(pProslic,
976 "%sRingSetup : VBATR_EXPECT : Clamped to Gen Conf Limit\n",LOGPRINT_PREFIX);
977 }
978 else
979 {
980 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_VBATR_EXPECT,
981 Si3218x_Ring_Presets[preset].vbatr_expect);
982 }
983
984#else
985 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_VBATR_EXPECT,
986 Si3218x_Ring_Presets[preset].vbatr_expect);
987#endif
988
989
990 WriteReg(pProHW,pProslic->channel,SI3218X_REG_RINGTALO,
991 Si3218x_Ring_Presets[preset].talo);
992 WriteReg(pProHW,pProslic->channel,SI3218X_REG_RINGTAHI,
993 Si3218x_Ring_Presets[preset].tahi);
994 WriteReg(pProHW,pProslic->channel,SI3218X_REG_RINGTILO,
995 Si3218x_Ring_Presets[preset].tilo);
996 WriteReg(pProHW,pProslic->channel,SI3218X_REG_RINGTIHI,
997 Si3218x_Ring_Presets[preset].tihi);
998
999 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_VBAT_TRACK_MIN_RNG,
1000 Si3218x_Ring_Presets[preset].dcdc_vref_min_rng);
1001
1002 /*
1003 ** LPR Handler
1004 **
1005 ** If USERSTAT == 0x01, adjust RINGCON and clear USERSTAT
1006 */
1007 if (Si3218x_Ring_Presets[preset].userstat == 0x01)
1008 {
1009 WriteReg(pProHW,pProslic->channel,SI3218X_REG_RINGCON,
1010 (0x80|Si3218x_Ring_Presets[preset].ringcon) & ~(0x40));
1011 WriteReg(pProHW,pProslic->channel,SI3218X_REG_USERSTAT,0x00);
1012 }
1013 else
1014 {
1015 WriteReg(pProHW,pProslic->channel,SI3218X_REG_RINGCON,
1016 Si3218x_Ring_Presets[preset].ringcon);
1017 WriteReg(pProHW,pProslic->channel,SI3218X_REG_USERSTAT,
1018 Si3218x_Ring_Presets[preset].userstat);
1019 }
1020
1021
1022 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_VCM_RING,
1023 Si3218x_Ring_Presets[preset].vcm_ring);
1024 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_VCM_RING_FIXED,
1025 Si3218x_Ring_Presets[preset].vcm_ring_fixed);
1026 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_DELTA_VCM,
1027 Si3218x_Ring_Presets[preset].delta_vcm);
1028
1029
1030 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_DCDC_RNGTYPE,
1031 Si3218x_Ring_Presets[preset].dcdc_rngtype);
1032
1033
1034 /*
1035 ** If multi bom supported **AND** a buck boost converter
1036 ** is being used, force dcdc_rngtype to be fixed.
1037 */
1038#ifdef SIVOICE_MULTI_BOM_SUPPORT
1039#define DCDC_RNGTYPE_BKBT 0L
1040 /* Automatically adjust DCDC_RNGTYPE */
1041 if(Si3218x_General_Configuration.bom_option == BO_DCDC_BUCK_BOOST)
1042 {
1043 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_DCDC_RNGTYPE,DCDC_RNGTYPE_BKBT);
1044 }
1045#endif
1046
1047
1048 return RC_NONE;
1049}
1050#endif
1051
1052/*
1053** Function: PROSLIC_ZsynthSetup
1054**
1055** Description:
1056** configure impedance synthesis
1057*/
1058
1059#ifndef DISABLE_ZSYNTH_SETUP
1060int Si3218x_ZsynthSetup (proslicChanType *pProslic, int preset)
1061{
1062 uInt8 lf;
1063 uInt8 cal_en = 0;
1064 uInt16 timer = 500;
1065
1066 if(pProslic->channelType != PROSLIC)
1067 {
1068 return RC_CHANNEL_TYPE_ERR;
1069 }
1070
1071 lf = ReadReg(pProHW,pProslic->channel,SI3218X_REG_LINEFEED);
1072 WriteReg(pProHW,pProslic->channel,SI3218X_REG_LINEFEED,0);
1073 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACEQ_C0,
1074 Si3218x_Impedance_Presets[preset].audioEQ.txaceq_c0);
1075 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACEQ_C1,
1076 Si3218x_Impedance_Presets[preset].audioEQ.txaceq_c1);
1077 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACEQ_C2,
1078 Si3218x_Impedance_Presets[preset].audioEQ.txaceq_c2);
1079 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACEQ_C3,
1080 Si3218x_Impedance_Presets[preset].audioEQ.txaceq_c3);
1081 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACEQ_C0,
1082 Si3218x_Impedance_Presets[preset].audioEQ.rxaceq_c0);
1083 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACEQ_C1,
1084 Si3218x_Impedance_Presets[preset].audioEQ.rxaceq_c1);
1085 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACEQ_C2,
1086 Si3218x_Impedance_Presets[preset].audioEQ.rxaceq_c2);
1087 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACEQ_C3,
1088 Si3218x_Impedance_Presets[preset].audioEQ.rxaceq_c3);
1089 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_ECFIR_C2,
1090 Si3218x_Impedance_Presets[preset].hybrid.ecfir_c2);
1091 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_ECFIR_C3,
1092 Si3218x_Impedance_Presets[preset].hybrid.ecfir_c3);
1093 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_ECFIR_C4,
1094 Si3218x_Impedance_Presets[preset].hybrid.ecfir_c4);
1095 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_ECFIR_C5,
1096 Si3218x_Impedance_Presets[preset].hybrid.ecfir_c5);
1097 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_ECFIR_C6,
1098 Si3218x_Impedance_Presets[preset].hybrid.ecfir_c6);
1099 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_ECFIR_C7,
1100 Si3218x_Impedance_Presets[preset].hybrid.ecfir_c7);
1101 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_ECFIR_C8,
1102 Si3218x_Impedance_Presets[preset].hybrid.ecfir_c8);
1103 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_ECFIR_C9,
1104 Si3218x_Impedance_Presets[preset].hybrid.ecfir_c9);
1105 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_ECIIR_B0,
1106 Si3218x_Impedance_Presets[preset].hybrid.ecfir_b0);
1107 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_ECIIR_B1,
1108 Si3218x_Impedance_Presets[preset].hybrid.ecfir_b1);
1109 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_ECIIR_A1,
1110 Si3218x_Impedance_Presets[preset].hybrid.ecfir_a1);
1111 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_ECIIR_A2,
1112 Si3218x_Impedance_Presets[preset].hybrid.ecfir_a2);
1113 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_ZSYNTH_A1,
1114 Si3218x_Impedance_Presets[preset].zsynth.zsynth_a1);
1115 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_ZSYNTH_A2,
1116 Si3218x_Impedance_Presets[preset].zsynth.zsynth_a2);
1117 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_ZSYNTH_B1,
1118 Si3218x_Impedance_Presets[preset].zsynth.zsynth_b1);
1119 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_ZSYNTH_B0,
1120 Si3218x_Impedance_Presets[preset].zsynth.zsynth_b0);
1121 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_ZSYNTH_B2,
1122 Si3218x_Impedance_Presets[preset].zsynth.zsynth_b2);
1123 WriteReg(pProHW,pProslic->channel,SI3218X_REG_RA,
1124 Si3218x_Impedance_Presets[preset].zsynth.ra);
1125 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACGAIN,
1126 Si3218x_Impedance_Presets[preset].txgain);
1127 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACGAIN_SAVE,
1128 Si3218x_Impedance_Presets[preset].rxgain);
1129 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACGAIN,
1130 Si3218x_Impedance_Presets[preset].rxgain);
1131 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACHPF_B0_1,
1132 Si3218x_Impedance_Presets[preset].rxachpf_b0_1);
1133 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACHPF_B1_1,
1134 Si3218x_Impedance_Presets[preset].rxachpf_b1_1);
1135 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACHPF_A1_1,
1136 Si3218x_Impedance_Presets[preset].rxachpf_a1_1);
1137
1138 /*
1139 ** Scale based on desired gain plan
1140 */
1141 Si3218x_dbgSetTXGain(pProslic,Si3218x_Impedance_Presets[preset].txgain_db,
1142 preset,TXACGAIN_SEL);
1143 Si3218x_dbgSetRXGain(pProslic,Si3218x_Impedance_Presets[preset].rxgain_db,
1144 preset,RXACGAIN_SEL);
1145 Si3218x_TXAudioGainSetup(pProslic,TXACGAIN_SEL);
1146 Si3218x_RXAudioGainSetup(pProslic,RXACGAIN_SEL);
1147
1148 /*
1149 ** Perform Zcal in case OHT used (eg. no offhook event to trigger auto Zcal)
1150 */
1151 WriteReg(pProHW,pProslic->channel,SI3218X_REG_CALR0,0x00);
1152 WriteReg(pProHW,pProslic->channel,SI3218X_REG_CALR1,0x40);
1153 WriteReg(pProHW,pProslic->channel,SI3218X_REG_CALR2,0x00);
1154 WriteReg(pProHW,pProslic->channel,SI3218X_REG_CALR3,0x80); /* start cal */
1155
1156 /* Wait for zcal to finish */
1157 do
1158 {
1159 cal_en = ReadReg(pProHW,pProslic->channel,SI3218X_REG_CALR3);
1160 Delay(pProTimer,1);
1161 timer--;
1162 }
1163 while((cal_en&0x80)&&(timer>0));
1164
1165 WriteReg(pProHW,pProslic->channel,SI3218X_REG_LINEFEED,lf);
1166
1167 if(timer > 0)
1168 {
1169 return RC_NONE;
1170 }
1171 else
1172 {
1173 return RC_CAL_TIMEOUT;
1174 }
1175}
1176#endif
1177
1178/*
1179** Function: PROSLIC_AudioGainSetup
1180**
1181** Description:
1182** configure audio gains
1183*/
1184int Si3218x_TXAudioGainSetup (proslicChanType *pProslic, int preset)
1185{
1186
1187 if(pProslic->channelType != PROSLIC)
1188 {
1189 return RC_CHANNEL_TYPE_ERR;
1190 }
1191
1192 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACGAIN,
1193 Si3218x_audioGain_Presets[preset].acgain);
1194 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACEQ_C0,
1195 Si3218x_audioGain_Presets[preset].aceq_c0);
1196 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACEQ_C1,
1197 Si3218x_audioGain_Presets[preset].aceq_c1);
1198 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACEQ_C2,
1199 Si3218x_audioGain_Presets[preset].aceq_c2);
1200 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACEQ_C3,
1201 Si3218x_audioGain_Presets[preset].aceq_c3);
1202
1203 return RC_NONE;
1204}
1205
1206/*
1207** Function: PROSLIC_AudioGainSetup
1208**
1209** Description:
1210** configure audio gains
1211*/
1212
1213int Si3218x_RXAudioGainSetup (proslicChanType *pProslic, int preset)
1214{
1215
1216 if(pProslic->channelType != PROSLIC)
1217 {
1218 return RC_CHANNEL_TYPE_ERR;
1219 }
1220 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACGAIN_SAVE,
1221 Si3218x_audioGain_Presets[preset].acgain);
1222 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACGAIN,
1223 Si3218x_audioGain_Presets[preset].acgain);
1224 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACEQ_C0,
1225 Si3218x_audioGain_Presets[preset].aceq_c0);
1226 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACEQ_C1,
1227 Si3218x_audioGain_Presets[preset].aceq_c1);
1228 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACEQ_C2,
1229 Si3218x_audioGain_Presets[preset].aceq_c2);
1230 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACEQ_C3,
1231 Si3218x_audioGain_Presets[preset].aceq_c3);
1232
1233 return RC_NONE;
1234}
1235
1236
1237/*
1238** Function: PROSLIC_AudioGainScale
1239**
1240** Description:
1241** Multiply path gain by passed value for PGA and EQ scale (no reference to dB,
1242** multiply by a scale factor)
1243*/
1244int Si3218x_AudioGainScale (proslicChanType *pProslic, int preset,
1245 uInt32 pga_scale, uInt32 eq_scale,int rx_tx_sel)
1246{
1247
1248 if(rx_tx_sel == TXACGAIN_SEL)
1249 {
1250 Si3218x_audioGain_Presets[TXACGAIN_SEL].acgain =
1251 (Si3218x_Impedance_Presets[preset].txgain/1000)*pga_scale;
1252 if (Si3218x_Impedance_Presets[preset].audioEQ.txaceq_c0 & 0x10000000L)
1253 {
1254 Si3218x_Impedance_Presets[preset].audioEQ.txaceq_c0 |= 0xf0000000L;
1255 }
1256 if (Si3218x_Impedance_Presets[preset].audioEQ.txaceq_c1 & 0x10000000L)
1257 {
1258 Si3218x_Impedance_Presets[preset].audioEQ.txaceq_c1 |= 0xf0000000L;
1259 }
1260 if (Si3218x_Impedance_Presets[preset].audioEQ.txaceq_c2 & 0x10000000L)
1261 {
1262 Si3218x_Impedance_Presets[preset].audioEQ.txaceq_c2 |= 0xf0000000L;
1263 }
1264 if (Si3218x_Impedance_Presets[preset].audioEQ.txaceq_c3 & 0x10000000L)
1265 {
1266 Si3218x_Impedance_Presets[preset].audioEQ.txaceq_c3 |= 0xf0000000L;
1267 }
1268 Si3218x_audioGain_Presets[TXACGAIN_SEL].aceq_c0 = ((int32)
1269 Si3218x_Impedance_Presets[preset].audioEQ.txaceq_c0/1000)*eq_scale;
1270 Si3218x_audioGain_Presets[TXACGAIN_SEL].aceq_c1 = ((int32)
1271 Si3218x_Impedance_Presets[preset].audioEQ.txaceq_c1/1000)*eq_scale;
1272 Si3218x_audioGain_Presets[TXACGAIN_SEL].aceq_c2 = ((int32)
1273 Si3218x_Impedance_Presets[preset].audioEQ.txaceq_c2/1000)*eq_scale;
1274 Si3218x_audioGain_Presets[TXACGAIN_SEL].aceq_c3 = ((int32)
1275 Si3218x_Impedance_Presets[preset].audioEQ.txaceq_c3/1000)*eq_scale;
1276
1277 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACGAIN,
1278 Si3218x_audioGain_Presets[TXACGAIN_SEL].acgain);
1279 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACEQ_C0,
1280 Si3218x_audioGain_Presets[TXACGAIN_SEL].aceq_c0);
1281 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACEQ_C1,
1282 Si3218x_audioGain_Presets[TXACGAIN_SEL].aceq_c1);
1283 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACEQ_C2,
1284 Si3218x_audioGain_Presets[TXACGAIN_SEL].aceq_c2);
1285 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACEQ_C3,
1286 Si3218x_audioGain_Presets[TXACGAIN_SEL].aceq_c3);
1287 }
1288 else
1289 {
1290 Si3218x_audioGain_Presets[RXACGAIN_SEL].acgain =
1291 (Si3218x_Impedance_Presets[preset].rxgain/1000)*pga_scale;
1292 if (Si3218x_Impedance_Presets[preset].audioEQ.rxaceq_c0 & 0x10000000L)
1293 {
1294 Si3218x_Impedance_Presets[preset].audioEQ.rxaceq_c0 |= 0xf0000000L;
1295 }
1296 if (Si3218x_Impedance_Presets[preset].audioEQ.rxaceq_c1 & 0x10000000L)
1297 {
1298 Si3218x_Impedance_Presets[preset].audioEQ.rxaceq_c1 |= 0xf0000000L;
1299 }
1300 if (Si3218x_Impedance_Presets[preset].audioEQ.rxaceq_c2 & 0x10000000L)
1301 {
1302 Si3218x_Impedance_Presets[preset].audioEQ.rxaceq_c2 |= 0xf0000000L;
1303 }
1304 if (Si3218x_Impedance_Presets[preset].audioEQ.rxaceq_c3 & 0x10000000L)
1305 {
1306 Si3218x_Impedance_Presets[preset].audioEQ.rxaceq_c3 |= 0xf0000000L;
1307 }
1308 Si3218x_audioGain_Presets[RXACGAIN_SEL].aceq_c0 = ((int32)
1309 Si3218x_Impedance_Presets[preset].audioEQ.rxaceq_c0/1000)*eq_scale;
1310 Si3218x_audioGain_Presets[RXACGAIN_SEL].aceq_c1 = ((int32)
1311 Si3218x_Impedance_Presets[preset].audioEQ.rxaceq_c1/1000)*eq_scale;
1312 Si3218x_audioGain_Presets[RXACGAIN_SEL].aceq_c2 = ((int32)
1313 Si3218x_Impedance_Presets[preset].audioEQ.rxaceq_c2/1000)*eq_scale;
1314 Si3218x_audioGain_Presets[RXACGAIN_SEL].aceq_c3 = ((int32)
1315 Si3218x_Impedance_Presets[preset].audioEQ.rxaceq_c3/1000)*eq_scale;
1316
1317 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACGAIN_SAVE,
1318 Si3218x_audioGain_Presets[RXACGAIN_SEL].acgain);
1319 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACGAIN,
1320 Si3218x_audioGain_Presets[RXACGAIN_SEL].acgain);
1321 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACEQ_C0,
1322 Si3218x_audioGain_Presets[RXACGAIN_SEL].aceq_c0);
1323 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACEQ_C1,
1324 Si3218x_audioGain_Presets[RXACGAIN_SEL].aceq_c1);
1325 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACEQ_C2,
1326 Si3218x_audioGain_Presets[RXACGAIN_SEL].aceq_c2);
1327 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACEQ_C3,
1328 Si3218x_audioGain_Presets[RXACGAIN_SEL].aceq_c3);
1329 }
1330 return 0;
1331}
1332int Si3218x_TXAudioGainScale (proslicChanType *pProslic, int preset,
1333 uInt32 pga_scale, uInt32 eq_scale)
1334{
1335 return Si3218x_AudioGainScale(pProslic,preset,pga_scale,eq_scale,TXACGAIN_SEL);
1336}
1337int Si3218x_RXAudioGainScale (proslicChanType *pProslic, int preset,
1338 uInt32 pga_scale, uInt32 eq_scale)
1339{
1340 return Si3218x_AudioGainScale(pProslic,preset,pga_scale,eq_scale,RXACGAIN_SEL);
1341}
1342
1343
1344/*
1345** Function: PROSLIC_DCFeedSetup
1346**
1347** Description:
1348** configure dc feed
1349*/
1350
1351#ifndef DISABLE_DCFEED_SETUP
1352int Si3218x_DCFeedSetupCfg (proslicChanType *pProslic, Si3218x_DCfeed_Cfg *cfg,
1353 int preset)
1354{
1355 uInt8 lf;
1356
1357 if(pProslic->channelType != PROSLIC)
1358 {
1359 return RC_CHANNEL_TYPE_ERR;
1360 }
1361 lf = ReadReg(pProHW,pProslic->channel,SI3218X_REG_LINEFEED);
1362 WriteReg(pProHW,pProslic->channel,SI3218X_REG_LINEFEED,0);
1363 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_SLOPE_VLIM,
1364 cfg[preset].slope_vlim);
1365 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_SLOPE_RFEED,
1366 cfg[preset].slope_rfeed);
1367 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_SLOPE_ILIM,
1368 cfg[preset].slope_ilim);
1369 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_SLOPE_DELTA1,cfg[preset].delta1);
1370 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_SLOPE_DELTA2,cfg[preset].delta2);
1371 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_V_VLIM,cfg[preset].v_vlim);
1372 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_V_RFEED,cfg[preset].v_rfeed);
1373 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_V_ILIM,cfg[preset].v_ilim);
1374 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_CONST_RFEED,
1375 cfg[preset].const_rfeed);
1376 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_CONST_ILIM,
1377 cfg[preset].const_ilim);
1378 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_I_VLIM,cfg[preset].i_vlim);
1379 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_LCRONHK,cfg[preset].lcronhk);
1380 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_LCROFFHK,cfg[preset].lcroffhk);
1381 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_LCRDBI,cfg[preset].lcrdbi);
1382 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_LONGHITH,cfg[preset].longhith);
1383 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_LONGLOTH,cfg[preset].longloth);
1384 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_LONGDBI,cfg[preset].longdbi);
1385 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_LCRMASK,cfg[preset].lcrmask);
1386 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_LCRMASK_POLREV,
1387 cfg[preset].lcrmask_polrev);
1388 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_LCRMASK_STATE,
1389 cfg[preset].lcrmask_state);
1390 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_LCRMASK_LINECAP,
1391 cfg[preset].lcrmask_linecap);
1392 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_VCM_OH,cfg[preset].vcm_oh);
1393 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_VOV_BAT,cfg[preset].vov_bat);
1394 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_VOV_GND,cfg[preset].vov_gnd);
1395 WriteReg(pProHW,pProslic->channel,SI3218X_REG_LINEFEED,lf);
1396
1397 return RC_NONE;
1398}
1399
1400#endif
1401
1402/*
1403** Function: PROSLIC_PulseMeterSetup
1404**
1405** Description:
1406** configure pulse metering
1407*/
1408
1409#ifndef DISABLE_PULSE_SETUP
1410int Si3218x_PulseMeterSetup (proslicChanType *pProslic, int preset)
1411{
1412 uInt8 reg;
1413
1414 if(pProslic->channelType != PROSLIC)
1415 {
1416 return RC_CHANNEL_TYPE_ERR;
1417 }
1418
1419 else
1420 {
1421 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_PM_AMP_THRESH,
1422 Si3218x_PulseMeter_Presets[preset].pm_amp_thresh);
1423 reg = (Si3218x_PulseMeter_Presets[preset].pmFreq<<1)|
1424 (Si3218x_PulseMeter_Presets[preset].pmAuto<<3);
1425 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_PM_ACTIVE,
1426 Si3218x_PulseMeter_Presets[preset].pmActive);
1427 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_PM_INACTIVE,
1428 Si3218x_PulseMeter_Presets[preset].pmInactive);
1429 WriteReg(pProHW,pProslic->channel,SI3218X_REG_PMCON,reg);
1430 return RC_NONE;
1431 }
1432
1433}
1434#endif
1435
1436/*
1437** Function: PROSLIC_PCMSetup
1438**
1439** Description:
1440** configure pcm
1441*/
1442
1443#ifndef DISABLE_PCM_SETUP
1444int Si3218x_PCMSetup(proslicChanType *pProslic, int preset)
1445{
1446 uInt8 regTemp;
1447 uInt8 pmEn;
1448
1449 if(pProslic->channelType != PROSLIC)
1450 {
1451 return RC_CHANNEL_TYPE_ERR;
1452 }
1453
1454 pmEn = ReadReg(pProHW,pProslic->channel,
1455 SI3218X_REG_PMCON) & 0x01; /* PM/wideband lockout */
1456 if (Si3218x_PCM_Presets[preset].widebandEn && pmEn)
1457 {
1458#ifdef ENABLE_DEBUG
1459 LOGPRINT ("%s Wideband Mode is not supported while Pulse Metering is enabled.\n",
1460 LOGPRINT_PREFIX);
1461#endif
1462 }
1463 else if (Si3218x_PCM_Presets[preset].widebandEn && !pmEn)
1464 {
1465 /* TXIIR settings */
1466 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACIIR_B0_1,0x3538E80L);
1467 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACIIR_B1_1,0x3538E80L);
1468 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACIIR_A1_1,0x1AA9100L);
1469 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACIIR_B0_2,0x216D100L);
1470 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACIIR_B1_2,0x2505400L);
1471 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACIIR_B2_2,0x216D100L);
1472 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACIIR_A1_2,0x2CB8100L);
1473 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACIIR_A2_2,0x1D7FA500L);
1474 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACIIR_B0_3,0x2CD9B00L);
1475 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACIIR_B1_3,0x1276D00L);
1476 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACIIR_B2_3,0x2CD9B00L);
1477 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACIIR_A1_3,0x2335300L);
1478 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACIIR_A2_3,0x19D5F700L);
1479 /* RXIIR settings */
1480 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACIIR_B0_1,0x6A71D00L);
1481 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACIIR_B1_1,0x6A71D00L);
1482 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACIIR_A1_1,0x1AA9100L);
1483 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACIIR_B0_2,0x216D100L);
1484 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACIIR_B1_2,0x2505400L);
1485 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACIIR_B2_2,0x216D100L);
1486 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACIIR_A1_2,0x2CB8100L);
1487 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACIIR_A2_2,0x1D7FA500L);
1488 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACIIR_B0_3,0x2CD9B00L);
1489 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACIIR_B1_3,0x1276D00L);
1490 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACIIR_B2_3,0x2CD9B00L);
1491 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACIIR_A1_3,0x2335300L);
1492 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACIIR_A2_3,0x19D5F700L);
1493 /*
1494 ** RXHPF
1495 ** Note: Calling ProSLIC_ZsynthSetup() will overwrite some
1496 ** of these values. ProSLIC_PCMSetup() should always
1497 ** be called after loading coefficients when using
1498 ** wideband mode
1499 */
1500 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACHPF_B0_1,0x7CFF900L);
1501 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACHPF_B1_1,0x18300700L);
1502 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACHPF_A1_1,0x79FF201L);
1503 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACHPF_B0_2,0x7CEDA1DL);
1504 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACHPF_B1_2,0x106320D4L);
1505 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACHPF_B2_2,0x7CEDA1DL);
1506 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACHPF_A1_2,0xF9A910FL);
1507 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACHPF_A2_2,0x185FFDA8L);
1508 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACHPF_GAIN,0x08000000L);
1509 /* TXHPF */
1510 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACHPF_B0_1,0x0C7FF4CEL);
1511 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACHPF_B1_1,0x13800B32L);
1512 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACHPF_A1_1,0x079FF201L);
1513 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACHPF_B0_2,0x030FDD10L);
1514 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACHPF_B1_2,0x19E0996CL);
1515 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACHPF_B2_2,0x030FDD10L);
1516 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACHPF_A1_2,0x0F9A910FL);
1517 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACHPF_A2_2,0x185FFDA8L);
1518 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACHPF_GAIN,0x0CD30000L);
1519
1520 regTemp = ReadReg(pProHW,pProslic->channel,SI3218X_REG_DIGCON);
1521#ifndef DISABLE_HPF_WIDEBAND
1522 WriteReg(pProHW,pProslic->channel,SI3218X_REG_DIGCON,
1523 regTemp&~(0xC)); /* Enable HPF */
1524#else
1525 WriteReg(pProHW,pProslic->channel,SI3218X_REG_DIGCON,
1526 regTemp|(0xC)); /* Disable HPF */
1527#endif
1528 regTemp = ReadReg(pProHW,pProslic->channel,SI3218X_REG_ENHANCE);
1529 WriteReg(pProHW,pProslic->channel,SI3218X_REG_ENHANCE,regTemp|1);
1530 }
1531 else
1532 {
1533 regTemp = ReadReg(pProHW,pProslic->channel,SI3218X_REG_DIGCON);
1534 WriteReg(pProHW,pProslic->channel,SI3218X_REG_DIGCON,regTemp&~(0xC));
1535 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACIIR_B0_1,0x3538E80L);
1536 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACIIR_B1_1,0x3538E80L);
1537 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACIIR_A1_1,0x1AA9100L);
1538 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACIIR_B0_2,0x216D100L);
1539 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACIIR_B1_2,0x2505400L);
1540 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACIIR_B2_2,0x216D100L);
1541 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACIIR_A1_2,0x2CB8100L);
1542 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACIIR_A2_2,0x1D7FA500L);
1543 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACIIR_B0_3,0x2CD9B00L);
1544 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACIIR_B1_3,0x1276D00L);
1545 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACIIR_B2_3,0x2CD9B00L);
1546 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACIIR_A1_3,0x2335300L);
1547 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_TXACIIR_A2_3,0x19D5F700L);
1548 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACIIR_B0_1,0x6A71D00L);
1549 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACIIR_B1_1,0x6A71D00L);
1550 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACIIR_A1_1,0x1AA9100L);
1551 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACIIR_B0_2,0x216D100L);
1552 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACIIR_B1_2,0x2505400L);
1553 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACIIR_B2_2,0x216D100L);
1554 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACIIR_A1_2,0x2CB8100L);
1555 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACIIR_A2_2,0x1D7FA500L);
1556 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACIIR_B0_3,0x2CD9B00L);
1557 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACIIR_B1_3,0x1276D00L);
1558 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACIIR_B2_3,0x2CD9B00L);
1559 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACIIR_A1_3,0x2335300L);
1560 WriteRAM(pProHW,pProslic->channel,SI3218X_RAM_RXACIIR_A2_3,0x19D5F700L);
1561 regTemp = ReadReg(pProHW,pProslic->channel,SI3218X_REG_ENHANCE);
1562 WriteReg(pProHW,pProslic->channel,SI3218X_REG_ENHANCE,regTemp&~(1));
1563 }
1564 regTemp = Si3218x_PCM_Presets[preset].pcmFormat;
1565 regTemp |= Si3218x_PCM_Presets[preset].pcm_tri << 5;
1566 regTemp |= Si3218x_PCM_Presets[preset].alaw_inv << 2;
1567 WriteReg(pProHW,pProslic->channel,SI3218X_REG_PCMMODE,regTemp);
1568 regTemp = ReadReg(pProHW,pProslic->channel,SI3218X_REG_PCMTXHI);
1569 regTemp &= 3;
1570 regTemp |= Si3218x_PCM_Presets[preset].tx_edge<<4;
1571 WriteReg(pProHW,pProslic->channel,SI3218X_REG_PCMTXHI,regTemp);
1572
1573 return RC_NONE;
1574}
1575#endif
1576
1577/*
1578**
1579** PROSLIC CONTROL FUNCTIONS
1580**
1581*/
1582
1583/*
1584
1585** Function: PROSLIC_dbgSetDCFeed
1586**
1587** Description:
1588** provisionally function for setting up
1589** dcfeed given desired open circuit voltage
1590** and loop current.
1591*/
1592
1593int Si3218x_dbgSetDCFeed (proslicChanType *pProslic, uInt32 v_vlim_val,
1594 uInt32 i_ilim_val, int32 preset)
1595{
1596#ifndef DISABLE_DCFEED_SETUP
1597 /* Note: * needs more descriptive return codes in the event of an out of range argument */
1598 uInt16 vslope = 160;
1599 uInt16 rslope = 720;
1600 uInt32 vscale1 = 1386;
1601 uInt32 vscale2 =
1602 1422; /* 1386x1422 = 1970892 broken down to minimize trunc err */
1603 uInt32 iscale1 = 913;
1604 uInt32 iscale2 = 334; /* 913x334 = 304942 */
1605 uInt32 i_rfeed_val, v_rfeed_val, const_rfeed_val, i_vlim_val, const_ilim_val,
1606 v_ilim_val;
1607 int32 signedVal;
1608 /* Set Linefeed to open state before modifying DC Feed */
1609
1610 /* Assumptions must be made to minimize computations. This limits the
1611 ** range of available settings, but should be more than adequate for
1612 ** short loop applications.
1613 **
1614 ** Assumtions:
1615 **
1616 ** SLOPE_VLIM => 160ohms
1617 ** SLOPE_RFEED => 720ohms
1618 ** I_RFEED => 3*I_ILIM/4
1619 **
1620 ** With these assumptions, the DC Feed parameters now become
1621 **
1622 ** Inputs: V_VLIM, I_ILIM
1623 ** Constants: SLOPE_VLIM, SLOPE_ILIM, SLOPE_RFEED, SLOPE_DELTA1, SLOPE_DELTA2
1624 ** Outputs: V_RFEED, V_ILIM, I_VLIM, CONST_RFEED, CONST_ILIM
1625 **
1626 */
1627
1628 if(pProslic->channelType != PROSLIC)
1629 {
1630 return RC_CHANNEL_TYPE_ERR;
1631 }
1632
1633 /* Validate arguments */
1634 if((i_ilim_val < 15)||(i_ilim_val > 45))
1635 {
1636 return 1; /* need error code */
1637 }
1638 if((v_vlim_val < 30)||(v_vlim_val > 52))
1639 {
1640 return 1; /* need error code */
1641 }
1642
1643 /* Calculate voltages in mV and currents in uA */
1644 v_vlim_val *= 1000;
1645 i_ilim_val *= 1000;
1646
1647 /* I_RFEED */
1648 i_rfeed_val = (3*i_ilim_val)/4;
1649
1650 /* V_RFEED */
1651 v_rfeed_val = v_vlim_val - (i_rfeed_val*vslope)/1000;
1652
1653 /* V_ILIM */
1654 v_ilim_val = v_rfeed_val - (rslope*(i_ilim_val - i_rfeed_val))/1000;
1655
1656 /* I_VLIM */
1657 i_vlim_val = (v_vlim_val*1000)/4903;
1658
1659 /* CONST_RFEED */
1660 signedVal = v_rfeed_val * (i_ilim_val - i_rfeed_val);
1661 signedVal /= (v_rfeed_val - v_ilim_val);
1662 signedVal = i_rfeed_val + signedVal;
1663
1664 /* signedVal in uA here */
1665 signedVal *= iscale1;
1666 signedVal /= 100;
1667 signedVal *= iscale2;
1668 signedVal /= 10;
1669
1670 if(signedVal < 0)
1671 {
1672 const_rfeed_val = (signedVal)+ (1L<<29);
1673 }
1674 else
1675 {
1676 const_rfeed_val = signedVal & 0x1FFFFFFF;
1677 }
1678
1679 /* CONST_ILIM */
1680 const_ilim_val = i_ilim_val;
1681
1682 /* compute RAM values */
1683 v_vlim_val *= vscale1;
1684 v_vlim_val /= 100;
1685 v_vlim_val *= vscale2;
1686 v_vlim_val /= 10;
1687
1688 v_rfeed_val *= vscale1;
1689 v_rfeed_val /= 100;
1690 v_rfeed_val *= vscale2;
1691 v_rfeed_val /= 10;
1692
1693 v_ilim_val *= vscale1;
1694 v_ilim_val /= 100;
1695 v_ilim_val *= vscale2;
1696 v_ilim_val /= 10;
1697
1698 const_ilim_val *= iscale1;
1699 const_ilim_val /= 100;
1700 const_ilim_val *= iscale2;
1701 const_ilim_val /= 10;
1702
1703 i_vlim_val *= iscale1;
1704 i_vlim_val /= 100;
1705 i_vlim_val *= iscale2;
1706 i_vlim_val /= 10;
1707
1708 Si3218x_DCfeed_Presets[preset].slope_vlim = 0x18842BD7L;
1709 Si3218x_DCfeed_Presets[preset].slope_rfeed = 0x1E8886DEL;
1710 Si3218x_DCfeed_Presets[preset].slope_ilim = 0x40A0E0L;
1711 Si3218x_DCfeed_Presets[preset].delta1 = 0x1EABA1BFL;
1712 Si3218x_DCfeed_Presets[preset].delta2 = 0x1EF744EAL;
1713 Si3218x_DCfeed_Presets[preset].v_vlim = v_vlim_val;
1714 Si3218x_DCfeed_Presets[preset].v_rfeed = v_rfeed_val;
1715 Si3218x_DCfeed_Presets[preset].v_ilim = v_ilim_val;
1716 Si3218x_DCfeed_Presets[preset].const_rfeed = const_rfeed_val;
1717 Si3218x_DCfeed_Presets[preset].const_ilim = const_ilim_val;
1718 Si3218x_DCfeed_Presets[preset].i_vlim = i_vlim_val;
1719
1720 return RC_NONE;
1721#else
1722 SILABS_UNREFERENCED_PARAMETER(pProslic);
1723 SILABS_UNREFERENCED_PARAMETER(preset);
1724 SILABS_UNREFERENCED_PARAMETER(v_vlim_val);
1725 SILABS_UNREFERENCED_PARAMETER(i_ilim_val);
1726 return RC_IGNORE;
1727#endif
1728}
1729
1730/*
1731** Function: PROSLIC_dbgSetDCFeedVopen
1732**
1733** Description:
1734** provisionally function for setting up
1735** dcfeed given desired open circuit voltage.
1736** Entry I_ILIM value will be used.
1737*/
1738int Si3218x_dbgSetDCFeedVopen (proslicChanType *pProslic, uInt32 v_vlim_val,
1739 int32 preset)
1740{
1741#ifndef DISABLE_DCFEED_SETUP
1742 uInt32 i_ilim_val;
1743 uInt32 iscale1 = 913;
1744 uInt32 iscale2 = 334; /* 913x334 = 304942 */
1745
1746
1747 if(pProslic->channelType != PROSLIC)
1748 {
1749 return RC_CHANNEL_TYPE_ERR;
1750 }
1751
1752 /* Read present CONST_ILIM value */
1753 i_ilim_val = Si3218x_DCfeed_Presets[preset].const_ilim;
1754
1755
1756 i_ilim_val /= iscale2;
1757 i_ilim_val /= iscale1;
1758
1759 return Si3218x_dbgSetDCFeed(pProslic,v_vlim_val,i_ilim_val,preset);
1760#else
1761 SILABS_UNREFERENCED_PARAMETER(pProslic);
1762 SILABS_UNREFERENCED_PARAMETER(preset);
1763 SILABS_UNREFERENCED_PARAMETER(v_vlim_val);
1764 return RC_IGNORE;
1765#endif
1766}
1767
1768/*
1769** Function: PROSLIC_dbgSetDCFeedIloop
1770**
1771** Description:
1772** provisionally function for setting up
1773** dcfeed given desired loop current.
1774** Entry V_VLIM value will be used.
1775*/
1776int Si3218x_dbgSetDCFeedIloop (proslicChanType *pProslic, uInt32 i_ilim_val,
1777 int32 preset)
1778{
1779#ifndef DISABLE_DCFEED_SETUP
1780
1781 uInt32 v_vlim_val;
1782 uInt32 vscale1 = 1386;
1783 uInt32 vscale2 =
1784 1422; /* 1386x1422 = 1970892 broken down to minimize trunc err */
1785
1786 if(pProslic->channelType != PROSLIC)
1787 {
1788 return RC_CHANNEL_TYPE_ERR;
1789 }
1790
1791 /* Read present V_VLIM value */
1792 v_vlim_val = Si3218x_DCfeed_Presets[preset].v_vlim;
1793
1794 v_vlim_val /= vscale2;
1795 v_vlim_val /= vscale1;
1796
1797 return Si3218x_dbgSetDCFeed(pProslic,v_vlim_val,i_ilim_val, preset);
1798#else
1799 SILABS_UNREFERENCED_PARAMETER(pProslic);
1800 SILABS_UNREFERENCED_PARAMETER(preset);
1801 SILABS_UNREFERENCED_PARAMETER(i_ilim_val);
1802 return RC_IGNORE;
1803#endif
1804}
1805
1806typedef struct
1807{
1808 uInt8 freq;
1809 ramData ringfr; /* trise scale for trap */
1810 uInt32 ampScale;
1811} ProSLIC_SineRingFreqLookup;
1812
1813typedef struct
1814{
1815 uInt8 freq;
1816 ramData rtacth;
1817 ramData rtper;
1818 ramData rtdb;
1819} ProSLIC_SineRingtripLookup;
1820
1821typedef struct
1822{
1823 uInt8 freq;
1824 uInt16 cfVal[6];
1825} ProSLIC_TrapRingFreqLookup;
1826
1827typedef struct
1828{
1829 uInt8 freq;
1830 ramData rtper;
1831 ramData rtdb;
1832 uInt32 rtacth[6];
1833} ProSLIC_TrapRingtripLookup;
1834
1835static const ProSLIC_SineRingFreqLookup sineRingFreqTable[] =
1836 /* Freq RINGFR, vScale */
1837 {
1838 {15, 0x7F6E930L, 18968L},
1839 {16, 0x7F5A8E0L, 20234L},
1840 {20, 0x7EFD9D5L, 25301L},
1841 {22, 0x7EC770AL, 27843L},
1842 {23, 0x7EAA6E2L, 29113L},
1843 {25, 0x7E6C925L, 31649L},
1844 {30, 0x7DBB96BL, 38014L},
1845 {34, 0x7D34155L, 42270L}, /* Actually 33.33Hz */
1846 {35, 0x7CEAD72L, 44397L},
1847 {40, 0x7BFA887L, 50802L},
1848 {45, 0x7AEAE74L, 57233L},
1849 {50, 0x79BC384L, 63693L},
1850 {0,0,0}
1851 }; /* terminator */
1852
1853static const ProSLIC_SineRingtripLookup sineRingtripTable[] =
1854 /* Freq rtacth */
1855 {
1856 {15, 11440000L, 0x6A000L, 0x4000L },
1857 {16, 10810000L, 0x64000L, 0x4000L },
1858 {20, 8690000L, 0x50000L, 0x8000L },
1859 {22, 7835000L, 0x48000L, 0x8000L },
1860 {23, 7622000L, 0x46000L, 0x8000L },
1861 {25, 6980000L, 0x40000L, 0xA000L },
1862 {30, 5900000L, 0x36000L, 0xA000L },
1863 {34, 10490000L, 0x60000L, 0x6000L }, /* Actually 33.33 */
1864 {35, 10060000L, 0x5C000L, 0x6000L },
1865 {40, 8750000L, 0x50000L, 0x8000L },
1866 {45, 7880000L, 0x48000L, 0x8000L },
1867 {50, 7010000L, 0x40000L, 0xA000L },
1868 {0,0L, 0L, 0L}
1869 }; /* terminator */
1870
1871static const ProSLIC_TrapRingFreqLookup trapRingFreqTable[] =
1872 /* Freq multCF11 multCF12 multCF13 multCF14 multCF15 multCF16*/
1873 {
1874 {15, {69,122, 163, 196, 222,244}},
1875 {16, {65,115, 153, 184, 208,229}},
1876 {20, {52,92, 122, 147, 167,183}},
1877 {22, {47,83, 111, 134, 152,166}},
1878 {23, {45,80, 107, 128, 145,159}},
1879 {25, {42,73, 98, 118, 133,146}},
1880 {30, {35,61, 82, 98, 111,122}},
1881 {34, {31,55, 73, 88, 100,110}},
1882 {35, {30,52, 70, 84, 95,104}},
1883 {40, {26,46, 61, 73, 83,91}},
1884 {45, {23,41, 54, 65, 74,81}},
1885 {50, {21,37, 49, 59, 67,73}},
1886 {0,{0L,0L,0L,0L}} /* terminator */
1887 };
1888
1889
1890static const ProSLIC_TrapRingtripLookup trapRingtripTable[] =
1891 /* Freq rtper rtdb rtacthCR11 rtacthCR12 rtacthCR13 rtacthCR14 rtacthCR15 rtacthCR16*/
1892 {
1893 {15, 0x6A000L, 0x4000L, {16214894L, 14369375L, 12933127L, 11793508L, 10874121L, 10121671L}},
1894 {16, 0x64000L, 0x4000L, {15201463L, 13471289L, 12124806L, 11056414L, 10194489L, 9489067L}},
1895 {20, 0x50000L, 0x6000L, {12161171L, 10777031L, 9699845L, 8845131L, 8155591L, 7591253L}},
1896 {22, 0x48000L, 0x6000L, {11055610L, 9797301L, 8818041L, 8041028L, 7414174L, 6901139L}},
1897 {23, 0x46000L, 0x6000L, {10574931L, 9371331L, 8434648L, 7691418L, 7091818L, 6601090L}},
1898 {25, 0x40000L, 0x8000L, {9728937L, 8621625L, 7759876L, 7076105L, 6524473L, 6073003L}},
1899 {30, 0x36000L, 0x8000L, {8107447L, 7184687L, 6466563L, 5896754L, 5437061L, 5060836L}},
1900 {34, 0x60000L, 0x6000L, {7297432L, 6466865L, 5820489L, 5307609L, 4893844L, 4555208L}},
1901 {35, 0x5C000L, 0x6000L, {6949240L, 6158303L, 5542769L, 5054361L, 4660338L, 4337859L}},
1902 {40, 0x50000L, 0x6000L, {6080585L, 5388516L, 4849923L, 4422565L, 4077796L, 3795627L}},
1903 {45, 0x48000L, 0x6000L, {5404965L, 4789792L, 4311042L, 3931169L, 3624707L, 3373890L}},
1904 {50, 0x40000L, 0x8000L, {4864468L, 4310812L, 3879938L, 3538052L, 3262236L, 3036501L}},
1905 {0,0x0L, 0x0L, {0L,0L,0L,0L}} /* terminator */
1906 };
1907
1908/*
1909** Function: PROSLIC_dbgRingingSetup
1910**
1911** Description:
1912** Provision function for setting up
1913** Ring type, frequency, amplitude and dc offset.
1914** Main use will be by peek/poke applications.
1915*/
1916int Si3218x_dbgSetRinging (proslicChanType *pProslic,
1917 ProSLIC_dbgRingCfg *ringCfg, int preset)
1918{
1919#ifndef DISABLE_RING_SETUP
1920 int errVal,i=0;
1921 uInt32 vScale = 1608872L; /* (2^28/170.25)*((100+4903)/4903) */
1922 ramData dcdcVminTmp;
1923
1924
1925 if(pProslic->channelType != PROSLIC)
1926 {
1927 return RC_CHANNEL_TYPE_ERR;
1928 }
1929
1930 errVal = RC_NONE;
1931
1932 switch(ringCfg->ringtype)
1933 {
1934 case ProSLIC_RING_SINE:
1935 i=0;
1936 do
1937 {
1938 if(sineRingFreqTable[i].freq >= ringCfg->freq)
1939 {
1940 break;
1941 }
1942 i++;
1943 }
1944 while (sineRingFreqTable[i].freq);
1945
1946 /* Set to maximum value if exceeding maximum value from table */
1947 if(sineRingFreqTable[i].freq == 0)
1948 {
1949 i--;
1950 errVal = RC_RING_V_LIMITED;
1951 }
1952
1953 /* Update RINGFR RINGAMP, RINGOFFSET, and RINGCON */
1954 Si3218x_Ring_Presets[preset].freq = sineRingFreqTable[i].ringfr;
1955 Si3218x_Ring_Presets[preset].amp = ringCfg->amp * sineRingFreqTable[i].ampScale;
1956 Si3218x_Ring_Presets[preset].offset = ringCfg->offset * vScale;
1957 Si3218x_Ring_Presets[preset].phas = 0L;
1958
1959 /* Don't alter anything in RINGCON other than clearing the TRAP bit */
1960 Si3218x_Ring_Presets[preset].ringcon &= 0xFE;
1961
1962 Si3218x_Ring_Presets[preset].rtper = sineRingtripTable[i].rtper;
1963 Si3218x_Ring_Presets[preset].rtacdb = sineRingtripTable[i].rtdb;
1964 Si3218x_Ring_Presets[preset].rtdcdb = sineRingtripTable[i].rtdb;
1965 Si3218x_Ring_Presets[preset].rtdcth = 0xFFFFFFFL;
1966 Si3218x_Ring_Presets[preset].rtacth = sineRingtripTable[i].rtacth;
1967 break;
1968
1969 case ProSLIC_RING_TRAP_CF11:
1970 case ProSLIC_RING_TRAP_CF12:
1971 case ProSLIC_RING_TRAP_CF13:
1972 case ProSLIC_RING_TRAP_CF14:
1973 case ProSLIC_RING_TRAP_CF15:
1974 case ProSLIC_RING_TRAP_CF16:
1975 i=0;
1976 do
1977 {
1978 if(trapRingFreqTable[i].freq >= ringCfg->freq)
1979 {
1980 break;
1981 }
1982 i++;
1983 }
1984 while (trapRingFreqTable[i].freq);
1985
1986 /* Set to maximum value if exceeding maximum value from table */
1987 if(trapRingFreqTable[i].freq == 0)
1988 {
1989 i--;
1990 errVal = RC_RING_V_LIMITED;
1991 }
1992
1993 /* Update RINGFR RINGAMP, RINGOFFSET, and RINGCON */
1994 Si3218x_Ring_Presets[preset].amp = ringCfg->amp * vScale;
1995 Si3218x_Ring_Presets[preset].freq =
1996 Si3218x_Ring_Presets[preset].amp/trapRingFreqTable[i].cfVal[ringCfg->ringtype];
1997 Si3218x_Ring_Presets[preset].offset = ringCfg->offset * vScale;
1998 Si3218x_Ring_Presets[preset].phas = 262144000L/trapRingFreqTable[i].freq;
1999
2000 /* Don't alter anything in RINGCON other than setting the TRAP bit */
2001 Si3218x_Ring_Presets[preset].ringcon |= 0x01;
2002
2003 /* RTPER and debouce timers */
2004 Si3218x_Ring_Presets[preset].rtper = trapRingtripTable[i].rtper;
2005 Si3218x_Ring_Presets[preset].rtacdb = trapRingtripTable[i].rtdb;
2006 Si3218x_Ring_Presets[preset].rtdcdb = trapRingtripTable[i].rtdb;
2007
2008
2009 Si3218x_Ring_Presets[preset].rtdcth = 0xFFFFFFFL;
2010 Si3218x_Ring_Presets[preset].rtacth =
2011 trapRingtripTable[i].rtacth[ringCfg->ringtype];
2012
2013
2014 break;
2015 }
2016
2017 /*
2018 ** DCDC tracking sluggish under light load at higher ring freq.
2019 ** Reduce tracking depth above 40Hz. This should have no effect
2020 ** if using the Buck-Boost architecture.
2021 */
2022 if((sineRingFreqTable[i].freq >= 40)
2023 ||(Si3218x_General_Configuration.bom_option == BO_DCDC_BUCK_BOOST))
2024 {
2025 dcdcVminTmp = ringCfg->amp + ringCfg->offset;
2026 dcdcVminTmp *= 1000;
2027 dcdcVminTmp *= SCALE_V_MADC;
2028 Si3218x_Ring_Presets[preset].dcdc_vref_min_rng = dcdcVminTmp;
2029 }
2030 else
2031 {
2032 Si3218x_Ring_Presets[preset].dcdc_vref_min_rng = 0x1800000L;
2033 }
2034
2035 return errVal;
2036#else
2037 SILABS_UNREFERENCED_PARAMETER(pProslic);
2038 SILABS_UNREFERENCED_PARAMETER(preset);
2039 SILABS_UNREFERENCED_PARAMETER(ringCfg);
2040 return RC_IGNORE;
2041#endif
2042}
2043
2044
2045typedef struct
2046{
2047 int32 gain;
2048 uInt32 scale;
2049} ProSLIC_GainScaleLookup;
2050
2051#ifndef ENABLE_HIRES_GAIN
2052static int Si3218x_dbgSetGain (proslicChanType *pProslic, int32 gain,
2053 int impedance_preset, int tx_rx_sel)
2054{
2055 int errVal = 0;
2056 int32 i;
2057 int32 gain_pga, gain_eq;
2058 const ProSLIC_GainScaleLookup gainScaleTable[]
2059 = /* gain, scale=10^(gain/20) */
2060 {
2061 {-30, 32},
2062 {-29, 35},
2063 {-28, 40},
2064 {-27, 45},
2065 {-26, 50},
2066 {-25, 56},
2067 {-24, 63},
2068 {-23, 71},
2069 {-22, 79},
2070 {-21, 89},
2071 {-20, 100},
2072 {-19, 112},
2073 {-18, 126},
2074 {-17, 141},
2075 {-16, 158},
2076 {-15, 178},
2077 {-14, 200},
2078 {-13, 224},
2079 {-12, 251},
2080 {-11, 282},
2081 {-10, 316},
2082 {-9, 355},
2083 {-8, 398},
2084 {-7, 447},
2085 {-6, 501},
2086 {-5, 562},
2087 {-4, 631},
2088 {-3, 708},
2089 {-2, 794},
2090 {-1, 891},
2091 {0, 1000},
2092 {1, 1122},
2093 {2, 1259},
2094 {3, 1413},
2095 {4, 1585},
2096 {5, 1778},
2097 {6, 1995},
2098 {0xff,0} /* terminator */
2099 };
2100
2101 SILABS_UNREFERENCED_PARAMETER(pProslic);
2102
2103 /* Test against max gain */
2104 if (gain > PROSLIC_EXTENDED_GAIN_MAX)
2105 {
2106 errVal = RC_GAIN_OUT_OF_RANGE;
2107 DEBUG_PRINT(pProslic, "%sdbgSetGain: Gain %d out of range\n", LOGPRINT_PREFIX,
2108 (int)gain);
2109 gain = PROSLIC_EXTENDED_GAIN_MAX; /* Clamp to maximum */
2110 }
2111
2112 /* Test against min gain */
2113 if (gain < PROSLIC_GAIN_MIN)
2114 {
2115 errVal = RC_GAIN_OUT_OF_RANGE;
2116 DEBUG_PRINT(pProslic, "%sdbgSetGain: Gain %d out of range\n", LOGPRINT_PREFIX,
2117 (int)gain);
2118 gain = PROSLIC_GAIN_MIN; /* Clamp to minimum */
2119 }
2120
2121 /* Distribute gain */
2122 if(gain == 0)
2123 {
2124 gain_pga = 0;
2125 gain_eq = 0;
2126 }
2127 else if(gain > PROSLIC_GAIN_MAX)
2128 {
2129 if(tx_rx_sel == TXACGAIN_SEL)
2130 {
2131 gain_pga = PROSLIC_GAIN_MAX;
2132 gain_eq = gain - PROSLIC_GAIN_MAX;
2133 }
2134 else
2135 {
2136 gain_pga = gain - PROSLIC_GAIN_MAX;
2137 gain_eq = PROSLIC_GAIN_MAX;
2138 }
2139 }
2140 else if(gain > 0)
2141 {
2142 if(tx_rx_sel == TXACGAIN_SEL)
2143 {
2144 gain_pga = gain;
2145 gain_eq = 0;
2146 }
2147 else
2148 {
2149 gain_pga = 0;
2150 gain_eq = gain;
2151 }
2152 }
2153 else
2154 {
2155 if(tx_rx_sel == TXACGAIN_SEL)
2156 {
2157 gain_pga = 0;
2158 gain_eq = gain;
2159 }
2160 else
2161 {
2162 gain_pga = gain;
2163 gain_eq = 0;
2164 }
2165
2166 }
2167
2168
2169 /*
2170 ** Lookup PGA Appropriate PGA Gain
2171 */
2172 i=0;
2173 do
2174 {
2175 if(gainScaleTable[i].gain >= gain_pga) /* was gain_1 */
2176 {
2177 break;
2178 }
2179 i++;
2180 }
2181 while (gainScaleTable[i].gain!=0xff);
2182
2183 /* Set to maximum value if exceeding maximum value from table */
2184 if(gainScaleTable[i].gain == 0xff)
2185 {
2186 i--;
2187 errVal = RC_GAIN_DELTA_TOO_LARGE;
2188 }
2189
2190 if(tx_rx_sel == TXACGAIN_SEL)
2191 {
2192 Si3218x_audioGain_Presets[0].acgain =
2193 (Si3218x_Impedance_Presets[impedance_preset].txgain/1000)
2194 *gainScaleTable[i].scale;
2195 }
2196 else
2197 {
2198 Si3218x_audioGain_Presets[1].acgain =
2199 (Si3218x_Impedance_Presets[impedance_preset].rxgain/1000)
2200 *gainScaleTable[i].scale;
2201 }
2202
2203
2204 /*
2205 ** Lookup EQ Gain
2206 */
2207 i=0;
2208 do
2209 {
2210 if(gainScaleTable[i].gain >= gain_eq) /* was gain_2 */
2211 {
2212 break;
2213 }
2214 i++;
2215 }
2216 while (gainScaleTable[i].gain!=0xff);
2217
2218 /* Set to maximum value if exceeding maximum value from table */
2219 if(gainScaleTable[i].gain == 0xff)
2220 {
2221 i--;
2222 errVal = RC_GAIN_DELTA_TOO_LARGE;
2223 }
2224
2225 if(tx_rx_sel == TXACGAIN_SEL)
2226 {
2227 /*sign extend negative numbers*/
2228 if (Si3218x_Impedance_Presets[impedance_preset].audioEQ.txaceq_c0 & 0x10000000L)
2229 {
2230 Si3218x_Impedance_Presets[impedance_preset].audioEQ.txaceq_c0 |= 0xf0000000L;
2231 }
2232 if (Si3218x_Impedance_Presets[impedance_preset].audioEQ.txaceq_c1 & 0x10000000L)
2233 {
2234 Si3218x_Impedance_Presets[impedance_preset].audioEQ.txaceq_c1 |= 0xf0000000L;
2235 }
2236 if (Si3218x_Impedance_Presets[impedance_preset].audioEQ.txaceq_c2 & 0x10000000L)
2237 {
2238 Si3218x_Impedance_Presets[impedance_preset].audioEQ.txaceq_c2 |= 0xf0000000L;
2239 }
2240 if (Si3218x_Impedance_Presets[impedance_preset].audioEQ.txaceq_c3 & 0x10000000L)
2241 {
2242 Si3218x_Impedance_Presets[impedance_preset].audioEQ.txaceq_c3 |= 0xf0000000L;
2243 }
2244
2245 Si3218x_audioGain_Presets[0].aceq_c0 = ((int32)
2246 Si3218x_Impedance_Presets[impedance_preset].audioEQ.txaceq_c0/1000)
2247 *gainScaleTable[i].scale;
2248 Si3218x_audioGain_Presets[0].aceq_c1 = ((int32)
2249 Si3218x_Impedance_Presets[impedance_preset].audioEQ.txaceq_c1/1000)
2250 *gainScaleTable[i].scale;
2251 Si3218x_audioGain_Presets[0].aceq_c2 = ((int32)
2252 Si3218x_Impedance_Presets[impedance_preset].audioEQ.txaceq_c2/1000)
2253 *gainScaleTable[i].scale;
2254 Si3218x_audioGain_Presets[0].aceq_c3 = ((int32)
2255 Si3218x_Impedance_Presets[impedance_preset].audioEQ.txaceq_c3/1000)
2256 *gainScaleTable[i].scale;
2257 }
2258 else
2259 {
2260 /*sign extend negative numbers*/
2261 if (Si3218x_Impedance_Presets[impedance_preset].audioEQ.rxaceq_c0 & 0x10000000L)
2262 {
2263 Si3218x_Impedance_Presets[impedance_preset].audioEQ.rxaceq_c0 |= 0xf0000000L;
2264 }
2265 if (Si3218x_Impedance_Presets[impedance_preset].audioEQ.rxaceq_c1 & 0x10000000L)
2266 {
2267 Si3218x_Impedance_Presets[impedance_preset].audioEQ.rxaceq_c1 |= 0xf0000000L;
2268 }
2269 if (Si3218x_Impedance_Presets[impedance_preset].audioEQ.rxaceq_c2 & 0x10000000L)
2270 {
2271 Si3218x_Impedance_Presets[impedance_preset].audioEQ.rxaceq_c2 |= 0xf0000000L;
2272 }
2273 if (Si3218x_Impedance_Presets[impedance_preset].audioEQ.rxaceq_c3 & 0x10000000L)
2274 {
2275 Si3218x_Impedance_Presets[impedance_preset].audioEQ.rxaceq_c3 |= 0xf0000000L;
2276 }
2277
2278 Si3218x_audioGain_Presets[1].aceq_c0 = ((int32)
2279 Si3218x_Impedance_Presets[impedance_preset].audioEQ.rxaceq_c0/1000)
2280 *gainScaleTable[i].scale;
2281 Si3218x_audioGain_Presets[1].aceq_c1 = ((int32)
2282 Si3218x_Impedance_Presets[impedance_preset].audioEQ.rxaceq_c1/1000)
2283 *gainScaleTable[i].scale;
2284 Si3218x_audioGain_Presets[1].aceq_c2 = ((int32)
2285 Si3218x_Impedance_Presets[impedance_preset].audioEQ.rxaceq_c2/1000)
2286 *gainScaleTable[i].scale;
2287 Si3218x_audioGain_Presets[1].aceq_c3 = ((int32)
2288 Si3218x_Impedance_Presets[impedance_preset].audioEQ.rxaceq_c3/1000)
2289 *gainScaleTable[i].scale;
2290 }
2291
2292
2293 return errVal;
2294}
2295#else /* ENABLE_HIRES_GAIN */
2296/*
2297** Function: Si3218x_dbgSetGainHiRes()
2298**
2299** Description:
2300** Provision function for setting up
2301** TX and RX gain with 0.1dB resolution instead
2302** of 1.0dB resolution
2303*/
2304static int Si3218x_dbgSetGainHiRes (proslicChanType *pProslic, int32 gain,
2305 int impedance_preset, int tx_rx_sel)
2306{
2307 int errVal = 0;
2308 int32 i;
2309 int32 coarseGainIndex, fineGainIndex;
2310 int32 gain_pga, gain_eq;
2311 int32 coarseGain, fineGain;
2312 int32 tmp;
2313 const ProSLIC_GainScaleLookup coarseGainScaleTable[]
2314 = /* gain, scale=10^(gain/20) */
2315 {
2316 {-30, 32},
2317 {-29, 35},
2318 {-28, 40},
2319 {-27, 45},
2320 {-26, 50},
2321 {-25, 56},
2322 {-24, 63},
2323 {-23, 71},
2324 {-22, 79},
2325 {-21, 89},
2326 {-20, 100},
2327 {-19, 112},
2328 {-18, 126},
2329 {-17, 141},
2330 {-16, 158},
2331 {-15, 178},
2332 {-14, 200},
2333 {-13, 224},
2334 {-12, 251},
2335 {-11, 282},
2336 {-10, 316},
2337 {-9, 355},
2338 {-8, 398},
2339 {-7, 447},
2340 {-6, 501},
2341 {-5, 562},
2342 {-4, 631},
2343 {-3, 708},
2344 {-2, 794},
2345 {-1, 891},
2346 {0, 1000},
2347 {1, 1122},
2348 {2, 1259},
2349 {3, 1413},
2350 {4, 1585},
2351 {5, 1778},
2352 {6, 1995},
2353 {0xff,0} /* terminator */
2354 };
2355
2356 const ProSLIC_GainScaleLookup fineGainScaleTable[]
2357 = /* gain, scale=10^(gain/20) */
2358 {
2359 {-9, 902},
2360 {-8, 912},
2361 {-7, 923},
2362 {-6, 933},
2363 {-5, 944},
2364 {-4, 955},
2365 {-3, 966},
2366 {-2, 977},
2367 {-1, 989},
2368 {0, 1000},
2369 {1, 1012},
2370 {2, 1023},
2371 {3, 1035},
2372 {4, 1047},
2373 {5, 1059},
2374 {6, 1072},
2375 {7, 1084},
2376 {8, 1096},
2377 {9, 1109},
2378 {0xff,0} /* terminator */
2379 };
2380
2381 SILABS_UNREFERENCED_PARAMETER(pProslic);
2382
2383 /* Test against max gain */
2384 if (gain > (PROSLIC_GAIN_MAX*10L))
2385 {
2386 errVal = RC_GAIN_OUT_OF_RANGE;
2387 DEBUG_PRINT(pProslic, "%sdbgSetGain: Gain %d dB*10 out of range\n",
2388 LOGPRINT_PREFIX, gain);
2389 gain = (PROSLIC_GAIN_MAX*10L); /* Clamp to maximum */
2390 }
2391
2392 /* Test against min gain */
2393 if (gain < (PROSLIC_GAIN_MIN*10L))
2394 {
2395 errVal = RC_GAIN_OUT_OF_RANGE;
2396 DEBUG_PRINT(pProslic, "%sdbgSetGain: Gain %d dB*10 out of range\n",
2397 LOGPRINT_PREFIX, gain);
2398 gain = (PROSLIC_GAIN_MIN*10); /* Clamp to minimum */
2399 }
2400
2401 /* Distribute gain */
2402 coarseGain = gain/10L;
2403 fineGain = gain - (coarseGain*10L);
2404
2405 /* Distribute coarseGain */
2406 if(coarseGain == 0)
2407 {
2408 gain_pga = 0;
2409 gain_eq = 0;
2410 }
2411 else if(coarseGain > 0)
2412 {
2413 if(tx_rx_sel == TXACGAIN_SEL)
2414 {
2415 gain_pga = coarseGain;
2416 gain_eq = 0;
2417 }
2418 else
2419 {
2420 gain_pga = 0;
2421 gain_eq = coarseGain;
2422 }
2423 }
2424 else
2425 {
2426 if(tx_rx_sel == TXACGAIN_SEL)
2427 {
2428 gain_pga = 0;
2429 gain_eq = coarseGain;
2430 }
2431 else
2432 {
2433 gain_pga = coarseGain;
2434 gain_eq = 0;
2435 }
2436 }
2437
2438 /*
2439 ** Lookup PGA Appopriate PGA Gain
2440 */
2441 i=0;
2442 do
2443 {
2444 if(coarseGainScaleTable[i].gain >= gain_pga)
2445 {
2446 break;
2447 }
2448 i++;
2449 }
2450 while (coarseGainScaleTable[i].gain!=0xff);
2451
2452 /* Set to maximum value if exceeding maximum value from table */
2453 if(coarseGainScaleTable[i].gain == 0xff)
2454 {
2455 i--;
2456 errVal = RC_GAIN_DELTA_TOO_LARGE;
2457 }
2458
2459 coarseGainIndex = i; /* Store coarse index */
2460
2461 /* Find fineGain */
2462 i = 0;
2463 do
2464 {
2465 if(fineGainScaleTable[i].gain >= fineGain)
2466 {
2467 break;
2468 }
2469 i++;
2470 }
2471 while (fineGainScaleTable[i].gain!=0xff);
2472
2473 /* Set to maximum value if exceeding maximum value from table */
2474 if(fineGainScaleTable[i].gain == 0xff)
2475 {
2476 i--;
2477 errVal = RC_GAIN_DELTA_TOO_LARGE;
2478 }
2479
2480 fineGainIndex = i;
2481
2482 if(tx_rx_sel == TXACGAIN_SEL)
2483 {
2484 Si3218x_audioGain_Presets[0].acgain = ((
2485 Si3218x_Impedance_Presets[impedance_preset].txgain/1000L)
2486 *coarseGainScaleTable[coarseGainIndex].scale);
2487 }
2488 else
2489 {
2490 Si3218x_audioGain_Presets[1].acgain = ((
2491 Si3218x_Impedance_Presets[impedance_preset].rxgain/1000L)
2492 * coarseGainScaleTable[coarseGainIndex].scale)/1000L
2493 * fineGainScaleTable[fineGainIndex].scale;
2494 }
2495
2496 /*
2497 ** Lookup EQ Gain
2498 */
2499 i=0;
2500 do
2501 {
2502 if(coarseGainScaleTable[i].gain >= gain_eq)
2503 {
2504 break;
2505 }
2506 i++;
2507 }
2508 while (coarseGainScaleTable[i].gain!=0xff);
2509
2510 /* Set to maximum value if exceeding maximum value from table */
2511 if(coarseGainScaleTable[i].gain == 0xff)
2512 {
2513 i--;
2514 errVal = RC_GAIN_DELTA_TOO_LARGE;
2515 }
2516
2517 coarseGainIndex = i; /* Store coarse index */
2518
2519 if(tx_rx_sel == TXACGAIN_SEL)
2520 {
2521 /*sign extend negative numbers*/
2522 if (Si3218x_Impedance_Presets[impedance_preset].audioEQ.txaceq_c0 & 0x10000000L)
2523 {
2524 Si3218x_Impedance_Presets[impedance_preset].audioEQ.txaceq_c0 |= 0xf0000000L;
2525 }
2526 if (Si3218x_Impedance_Presets[impedance_preset].audioEQ.txaceq_c1 & 0x10000000L)
2527 {
2528 Si3218x_Impedance_Presets[impedance_preset].audioEQ.txaceq_c1 |= 0xf0000000L;
2529 }
2530 if (Si3218x_Impedance_Presets[impedance_preset].audioEQ.txaceq_c2 & 0x10000000L)
2531 {
2532 Si3218x_Impedance_Presets[impedance_preset].audioEQ.txaceq_c2 |= 0xf0000000L;
2533 }
2534 if (Si3218x_Impedance_Presets[impedance_preset].audioEQ.txaceq_c3 & 0x10000000L)
2535 {
2536 Si3218x_Impedance_Presets[impedance_preset].audioEQ.txaceq_c3 |= 0xf0000000L;
2537 }
2538
2539 tmp = (((int32)
2540 Si3218x_Impedance_Presets[impedance_preset].audioEQ.txaceq_c0/1000L)
2541 *coarseGainScaleTable[coarseGainIndex].scale);
2542 tmp = tmp / (int32)1000L;
2543 tmp = tmp * (int32)fineGainScaleTable[fineGainIndex].scale;
2544 Si3218x_audioGain_Presets[0].aceq_c0 = tmp;
2545
2546 tmp = (((int32)
2547 Si3218x_Impedance_Presets[impedance_preset].audioEQ.txaceq_c1/1000L)
2548 *coarseGainScaleTable[coarseGainIndex].scale);
2549 tmp = tmp / (int32)1000L;
2550 tmp = tmp * (int32)fineGainScaleTable[fineGainIndex].scale;
2551 Si3218x_audioGain_Presets[0].aceq_c1 = tmp;
2552
2553 tmp = (((int32)
2554 Si3218x_Impedance_Presets[impedance_preset].audioEQ.txaceq_c2/1000L)
2555 *coarseGainScaleTable[coarseGainIndex].scale);
2556 tmp = tmp / (int32)1000L;
2557 tmp = tmp * (int32)fineGainScaleTable[fineGainIndex].scale;
2558 Si3218x_audioGain_Presets[0].aceq_c2 = tmp;
2559
2560 tmp = (((int32)
2561 Si3218x_Impedance_Presets[impedance_preset].audioEQ.txaceq_c3/1000L)
2562 *coarseGainScaleTable[coarseGainIndex].scale);
2563 tmp = tmp / (int32)1000L;
2564 tmp = tmp * (int32)fineGainScaleTable[fineGainIndex].scale;
2565 Si3218x_audioGain_Presets[0].aceq_c3 = tmp;
2566 }
2567 else
2568 {
2569 /*sign extend negative numbers*/
2570 if (Si3218x_Impedance_Presets[impedance_preset].audioEQ.rxaceq_c0 & 0x10000000L)
2571 {
2572 Si3218x_Impedance_Presets[impedance_preset].audioEQ.rxaceq_c0 |= 0xf0000000L;
2573 }
2574 if (Si3218x_Impedance_Presets[impedance_preset].audioEQ.rxaceq_c1 & 0x10000000L)
2575 {
2576 Si3218x_Impedance_Presets[impedance_preset].audioEQ.rxaceq_c1 |= 0xf0000000L;
2577 }
2578 if (Si3218x_Impedance_Presets[impedance_preset].audioEQ.rxaceq_c2 & 0x10000000L)
2579 {
2580 Si3218x_Impedance_Presets[impedance_preset].audioEQ.rxaceq_c2 |= 0xf0000000L;
2581 }
2582 if (Si3218x_Impedance_Presets[impedance_preset].audioEQ.rxaceq_c3 & 0x10000000L)
2583 {
2584 Si3218x_Impedance_Presets[impedance_preset].audioEQ.rxaceq_c3 |= 0xf0000000L;
2585 }
2586
2587 Si3218x_audioGain_Presets[1].aceq_c0 = ((int32)
2588 Si3218x_Impedance_Presets[impedance_preset].audioEQ.rxaceq_c0/1000)
2589 *coarseGainScaleTable[i].scale;
2590 Si3218x_audioGain_Presets[1].aceq_c1 = ((int32)
2591 Si3218x_Impedance_Presets[impedance_preset].audioEQ.rxaceq_c1/1000)
2592 * coarseGainScaleTable[i].scale;
2593 Si3218x_audioGain_Presets[1].aceq_c2 = ((int32)
2594 Si3218x_Impedance_Presets[impedance_preset].audioEQ.rxaceq_c2/1000)
2595 * coarseGainScaleTable[i].scale;
2596 Si3218x_audioGain_Presets[1].aceq_c3 = ((int32)
2597 Si3218x_Impedance_Presets[impedance_preset].audioEQ.rxaceq_c3/1000)
2598 * coarseGainScaleTable[i].scale;
2599 }
2600
2601 return errVal;
2602}
2603#endif /* ENABLE_HIRES_GAIN */
2604
2605/*
2606** Function: PROSLIC_dbgSetTXGain
2607**
2608** Description:
2609** Provision function for setting up
2610** TX gain
2611*/
2612
2613int Si3218x_dbgSetTXGain (proslicChanType *pProslic, int32 gain,
2614 int impedance_preset, int audio_gain_preset)
2615{
2616 SILABS_UNREFERENCED_PARAMETER(audio_gain_preset);
2617#ifdef ENABLE_HIRES_GAIN
2618 return Si3218x_dbgSetGainHiRes(pProslic,gain,impedance_preset,TXACGAIN_SEL);
2619#else
2620 return Si3218x_dbgSetGain(pProslic,gain,impedance_preset,TXACGAIN_SEL);
2621#endif
2622}
2623
2624/*
2625** Function: PROSLIC_dbgSetRXGain
2626**
2627** Description:
2628** Provision function for setting up
2629** RX gain
2630*/
2631int Si3218x_dbgSetRXGain (proslicChanType *pProslic, int32 gain,
2632 int impedance_preset, int audio_gain_preset)
2633{
2634 SILABS_UNREFERENCED_PARAMETER(audio_gain_preset);
2635#ifdef ENABLE_HIRES_GAIN
2636 return Si3218x_dbgSetGainHiRes(pProslic,gain,impedance_preset,RXACGAIN_SEL);
2637#else
2638 return Si3218x_dbgSetGain(pProslic,gain,impedance_preset,RXACGAIN_SEL);
2639#endif
2640}
2641
2642/*
2643** Function: Si3218x_GetRAMScale
2644**
2645** Description:
2646** Read scale factor for passed RAM location
2647**
2648** Return Value:
2649** int32 scale
2650*/
2651static int32 Si3218x_GetRAMScale(uInt16 addr)
2652{
2653 int32 scale;
2654
2655 switch(addr)
2656 {
2657 case SI3218X_RAM_MADC_ILOOP:
2658 case SI3218X_RAM_MADC_ITIP:
2659 case SI3218X_RAM_MADC_IRING:
2660 case SI3218X_RAM_MADC_ILONG:
2661 scale = SCALE_I_MADC;
2662 break;
2663
2664 case SI3218X_RAM_MADC_VTIPC:
2665 case SI3218X_RAM_MADC_VRINGC:
2666 case SI3218X_RAM_MADC_VBAT:
2667 case SI3218X_RAM_MADC_VDC:
2668 case SI3218X_RAM_MADC_VDC_OS:
2669 case SI3218X_RAM_MADC_VLONG:
2670 case SI3218X_RAM_VDIFF_SENSE:
2671 case SI3218X_RAM_VDIFF_FILT:
2672 case SI3218X_RAM_VDIFF_COARSE:
2673 case SI3218X_RAM_VTIP:
2674 case SI3218X_RAM_VRING:
2675 scale = SCALE_V_MADC;
2676 break;
2677
2678 default:
2679 scale = 1;
2680 break;
2681 }
2682
2683 return scale;
2684}
2685
2686/*
2687** Function: Si3218x_ReadMADCScaled
2688**
2689** Description:
2690** Read MADC (or other sensed voltages/currents) and
2691** return scaled value in int32 format.
2692**
2693** Return Value:
2694** int32 voltage in mV or
2695** int32 current in uA
2696*/
2697int32 Si3218x_ReadMADCScaled(proslicChanType_ptr pProslic,uInt16 addr,
2698 int32 scale)
2699{
2700 int32 data;
2701
2702 /*
2703 ** Read 29-bit RAM and sign extend to 32-bits
2704 */
2705 data = ReadRAM(pProHW,pProslic->channel,addr);
2706 if(data & 0x10000000L)
2707 {
2708 data |= 0xF0000000L;
2709 }
2710
2711 /*
2712 ** Scale to provided value, or use defaults if scale = 0
2713 */
2714 if(scale == 0)
2715 {
2716 scale = Si3218x_GetRAMScale(addr);
2717 }
2718
2719 data /= scale;
2720
2721 return data;
2722}
2723
2724/*
2725** Function: Si3218x_LineMonitor
2726**
2727** Description:
2728** Monitor line voltages and currents
2729*/
2730int Si3218x_LineMonitor(proslicChanType *pProslic, proslicMonitorType *monitor)
2731{
2732
2733 if(pProslic->channelType != PROSLIC)
2734 {
2735 return RC_CHANNEL_TYPE_ERR;
2736 }
2737
2738 if(pProslic->channelEnable)
2739 {
2740 monitor->vtr = ReadRAM(pProHW,pProslic->channel,SI3218X_RAM_VDIFF_FILT);
2741 if(monitor->vtr & 0x10000000L)
2742 {
2743 monitor->vtr |= 0xf0000000L;
2744 }
2745 monitor->vtr /= SCALE_V_MADC;
2746
2747 monitor->vtip = ReadRAM(pProHW,pProslic->channel,SI3218X_RAM_VTIP);
2748 if(monitor->vtip & 0x10000000L)
2749 {
2750 monitor->vtip |= 0xf0000000L;
2751 }
2752 monitor->vtip /= SCALE_V_MADC;
2753
2754 monitor->vring = ReadRAM(pProHW,pProslic->channel,SI3218X_RAM_VRING);
2755 if(monitor->vring & 0x10000000L)
2756 {
2757 monitor->vring |= 0xf0000000L;
2758 }
2759 monitor->vring /= SCALE_V_MADC;
2760
2761 monitor->vlong = ReadRAM(pProHW,pProslic->channel,SI3218X_RAM_MADC_VLONG);
2762 if(monitor->vlong & 0x10000000L)
2763 {
2764 monitor->vlong |= 0xf0000000L;
2765 }
2766 monitor->vlong /= SCALE_V_MADC;
2767
2768 monitor->vbat = ReadRAM(pProHW,pProslic->channel,SI3218X_RAM_MADC_VBAT);
2769 if(monitor->vbat & 0x10000000L)
2770 {
2771 monitor->vbat |= 0xf0000000L;
2772 }
2773 monitor->vbat /= SCALE_V_MADC;
2774
2775 monitor->vdc = 0; /* Si3218x has no SVDC */
2776
2777 monitor->itr = ReadRAM(pProHW,pProslic->channel,SI3218X_RAM_MADC_ILOOP);
2778 if(monitor->itr & 0x10000000L)
2779 {
2780 monitor->itr |= 0xf0000000L;
2781 }
2782 monitor->itr /= SCALE_I_MADC;
2783
2784 monitor->itip = ReadRAM(pProHW,pProslic->channel,SI3218X_RAM_MADC_ITIP);
2785 if(monitor->itip & 0x10000000L)
2786 {
2787 monitor->itip |= 0xf0000000L;
2788 }
2789 monitor->itip /= SCALE_I_MADC;
2790
2791 monitor->iring = ReadRAM(pProHW,pProslic->channel,SI3218X_RAM_MADC_IRING);
2792 if(monitor->iring & 0x10000000L)
2793 {
2794 monitor->iring |= 0xf0000000L;
2795 }
2796 monitor->iring /= SCALE_I_MADC;
2797
2798 monitor->ilong = ReadRAM(pProHW,pProslic->channel,SI3218X_RAM_MADC_ILONG);
2799 if(monitor->ilong & 0x10000000L)
2800 {
2801 monitor->ilong |= 0xf0000000L;
2802 }
2803 monitor->ilong /= SCALE_I_MADC;
2804
2805 monitor->p_hvic = ReadRAM(pProHW,pProslic->channel,
2806 SI3218X_RAM_P_Q1_D); /* P_HVIC_LPF */
2807 if(monitor->p_hvic & 0x10000000L)
2808 {
2809 monitor->p_hvic |= 0xf0000000L;
2810 }
2811 monitor->p_hvic /= SCALE_P_MADC;
2812 }
2813
2814 return RC_NONE;
2815}
2816
2817/*
2818** Function: Si3218x_PSTNCheck
2819**
2820** Description:
2821** Continuous monitoring of longitudinal current.
2822** If an average of N samples exceed avgThresh or a
2823** single sample exceeds singleThresh, the linefeed
2824** is forced into the open state.
2825**
2826** This protects the port from connecting to a live
2827** pstn line (faster than power alarm).
2828**
2829*/
2830int Si3218x_PSTNCheck (proslicChanType *pProslic,
2831 proslicPSTNCheckObjType *pPSTNCheck)
2832{
2833 uInt8 i;
2834
2835 if( (pProslic->channelType != PROSLIC)
2836 || (pPSTNCheck->samples == 0) )
2837 {
2838 return RC_NONE; /* Ignore DAA channels */
2839 }
2840
2841 /* Adjust buffer index */
2842 if(pPSTNCheck->count >= pPSTNCheck->samples)
2843 {
2844 pPSTNCheck->buffFull = TRUE;
2845 pPSTNCheck->count = 0; /* reset buffer ptr */
2846 }
2847
2848 /* Read next sample */
2849 pPSTNCheck->ilong[pPSTNCheck->count] = ReadRAM(pProHW,pProslic->channel,
2850 SI3218X_RAM_MADC_ILONG);
2851 if(pPSTNCheck->ilong[pPSTNCheck->count] & 0x10000000L)
2852 {
2853 pPSTNCheck->ilong[pPSTNCheck->count] |= 0xf0000000L;
2854 }
2855 pPSTNCheck->ilong[pPSTNCheck->count] /= SCALE_I_MADC;
2856
2857 /* Monitor magnitude only */
2858 if(pPSTNCheck->ilong[pPSTNCheck->count] < 0)
2859 {
2860 pPSTNCheck->ilong[pPSTNCheck->count] = -pPSTNCheck->ilong[pPSTNCheck->count];
2861 }
2862
2863 /* Quickly test for single measurement violation */
2864 if(pPSTNCheck->ilong[pPSTNCheck->count] > pPSTNCheck->singleThresh)
2865 {
2866 return RC_PSTN_CHECK_SINGLE_FAIL; /* fail */
2867 }
2868
2869 /* Average once buffer is full */
2870 if(pPSTNCheck->buffFull == TRUE)
2871 {
2872 pPSTNCheck->avgIlong = 0;
2873 for(i=0; i<pPSTNCheck->samples; i++)
2874 {
2875 pPSTNCheck->avgIlong += pPSTNCheck->ilong[i];
2876 }
2877 pPSTNCheck->avgIlong /= pPSTNCheck->samples;
2878
2879 if(pPSTNCheck->avgIlong > pPSTNCheck->avgThresh)
2880 {
2881 /* reinit obj and return fail */
2882 pPSTNCheck->count = 0;
2883 pPSTNCheck->buffFull = FALSE;
2884 return RC_PSTN_CHECK_AVG_FAIL;
2885 }
2886 else
2887 {
2888 pPSTNCheck->count++;
2889 return RC_NONE;
2890 }
2891 }
2892 else
2893 {
2894 pPSTNCheck->count++;
2895 return RC_NONE;
2896 }
2897}
2898
2899#ifdef PSTN_DET_ENABLE
2900/*
2901** Function: abs_int32
2902**
2903** Description:
2904** abs implementation for int32 type
2905*/
2906static int32 abs_int32(int32 a)
2907{
2908 if(a < 0)
2909 {
2910 return -1*a;
2911 }
2912 return a;
2913}
2914
2915/*
2916** Function: Si3218x_DiffPSTNCheck
2917**
2918** Description:
2919** Monitor for excessive longitudinal current, which
2920** would be present if a live pstn line was connected
2921** to the port.
2922**
2923** Returns:
2924** RC_NONE - test in progress
2925** RC_COMPLETE_NO_ERR - test complete, no alarms or errors
2926** RC_POWER_ALARM_HVIC - test interrupted by HVIC power alarm
2927** RC_
2928**
2929*/
2930
2931int Si3218x_DiffPSTNCheck (proslicChanType *pProslic,
2932 proslicDiffPSTNCheckObjType *pPSTNCheck)
2933{
2934 uInt8 loop_status;
2935 int i;
2936
2937 if(pProslic->channelType != PROSLIC)
2938 {
2939 return RC_CHANNEL_TYPE_ERR; /* Ignore DAA channels */
2940 }
2941
2942
2943 switch(pPSTNCheck->pState.stage)
2944 {
2945 case 0:
2946 /* Optional OPEN foreign voltage measurement - only execute if LCS = 0 */
2947 /* Disable low power mode */
2948 pPSTNCheck->enhanceRegSave = ReadReg(pProHW,pProslic->channel, PROSLIC_REG_ENHANCE);
2949 WriteReg(pProHW,pProslic->channel, PROSLIC_REG_ENHANCE,
2950 pPSTNCheck->enhanceRegSave&0x07); /* Disable powersave */
2951 pPSTNCheck->vdiff1_avg = 0;
2952 pPSTNCheck->vdiff2_avg = 0;
2953 pPSTNCheck->iloop1_avg = 0;
2954 pPSTNCheck->iloop2_avg = 0;
2955 pPSTNCheck->return_status = RC_COMPLETE_NO_ERR;
2956 /* Do OPEN state hazardous voltage measurement if enabled and ONHOOK */
2957 Si3218x_ReadHookStatus(pProslic,&loop_status);
2958 if((loop_status == PROSLIC_ONHOOK)&&(pPSTNCheck->femf_enable == 1))
2959 {
2960 pPSTNCheck->pState.stage++;
2961 }
2962 else
2963 {
2964 pPSTNCheck->pState.stage = 10;
2965 }
2966
2967 return RC_NONE;
2968
2969 case 1:
2970 /* Change linefeed to OPEN state for HAZV measurement, setup coarse sensors */
2971 pPSTNCheck->lfstate_entry = ReadReg(pProHW,pProslic->channel, PROSLIC_REG_LINEFEED);
2972 ProSLIC_SetLinefeedStatus(pProslic,LF_OPEN);
2973 pPSTNCheck->pState.stage++;
2974 return RC_NONE;
2975
2976 case 2:
2977 /* Settle */
2978 ProSLIC_PSTN_delay_poll(&(pPSTNCheck->pState), PSTN_DET_OPEN_FEMF_SETTLE);
2979 return RC_NONE;
2980
2981 case 3:
2982 /* Measure HAZV */
2983 pPSTNCheck->vdiff_open = Si3218x_ReadMADCScaled(pProslic,SI3218X_RAM_VDIFF_COARSE,0);
2984 DEBUG_PRINT(pProslic, "%sDiff PSTN : Vopen = %d mV\n", LOGPRINT_PREFIX,
2985 pPSTNCheck->vdiff_open);
2986
2987 /* Stop PSTN check if differential voltage > max_femf_vopen present */
2988 if(abs_int32(pPSTNCheck->vdiff_open) > pPSTNCheck->max_femf_vopen)
2989 {
2990 pPSTNCheck->pState.stage = 70;
2991 pPSTNCheck->return_status = RC_PSTN_OPEN_FEMF;
2992 }
2993 else
2994 {
2995 pPSTNCheck->pState.stage = 10;
2996 }
2997 return 0;
2998
2999 case 10:
3000 /* Load first DC feed preset */
3001 ProSLIC_DCFeedSetup(pProslic,pPSTNCheck->dcfPreset1);
3002 ProSLIC_SetLinefeedStatus(pProslic,LF_FWD_ACTIVE);
3003 pPSTNCheck->pState.stage++;
3004 return RC_NONE;
3005
3006 case 11:
3007 /* Settle */
3008 ProSLIC_PSTN_delay_poll(&(pPSTNCheck->pState), PSTN_DET_DIFF_IV1_SETTLE);
3009 return RC_NONE;
3010
3011 case 12:
3012 /* Measure VDIFF and ILOOP, switch to 2nd DCFEED setup */
3013 pPSTNCheck->vdiff1[pPSTNCheck->pState.sampleIterations] =
3014 Si3218x_ReadMADCScaled(pProslic,SI3218X_RAM_VDIFF_FILT,0);
3015 pPSTNCheck->iloop1[pPSTNCheck->pState.sampleIterations] =
3016 Si3218x_ReadMADCScaled(pProslic,SI3218X_RAM_MADC_ILOOP,0);
3017#ifdef ENABLE_DEBUG
3018 if ( DEBUG_ENABLED(pProslic) )
3019 {
3020 LOGPRINT("%sDiff PSTN: Vdiff1[%d] = %d mV\n", LOGPRINT_PREFIX,
3021 pPSTNCheck->pState.sampleIterations,
3022 pPSTNCheck->vdiff1[pPSTNCheck->pState.sampleIterations]);
3023 LOGPRINT("%sDiff PSTN: Iloop1[%d] = %d uA\n", LOGPRINT_PREFIX,
3024 pPSTNCheck->pState.sampleIterations,
3025 pPSTNCheck->iloop1[pPSTNCheck->pState.sampleIterations]);
3026 }
3027#endif
3028 pPSTNCheck->pState.sampleIterations++;
3029 if(pPSTNCheck->pState.sampleIterations >= pPSTNCheck->samples)
3030 {
3031 ProSLIC_DCFeedSetup(pProslic,pPSTNCheck->dcfPreset2);
3032 pPSTNCheck->pState.stage++;
3033 pPSTNCheck->pState.sampleIterations = 0;
3034 }
3035 return RC_NONE;
3036
3037 case 13:
3038 /* Settle feed 500ms */
3039 ProSLIC_PSTN_delay_poll(&(pPSTNCheck->pState), PSTN_DET_DIFF_IV2_SETTLE);
3040 return RC_NONE;
3041
3042 case 14:
3043 /* Measure VDIFF and ILOOP*/
3044 pPSTNCheck->vdiff2[pPSTNCheck->pState.sampleIterations] =
3045 Si3218x_ReadMADCScaled(pProslic,SI3218X_RAM_VDIFF_FILT,0);
3046 pPSTNCheck->iloop2[pPSTNCheck->pState.sampleIterations] =
3047 Si3218x_ReadMADCScaled(pProslic,SI3218X_RAM_MADC_ILOOP,0);
3048#ifdef ENABLE_DEBUG
3049 if ( DEBUG_ENABLED(pProslic) )
3050 {
3051 LOGPRINT("%sDiff PSTN: Vdiff2[%d] = %d mV\n", LOGPRINT_PREFIX,
3052 pPSTNCheck->pState.sampleIterations,
3053 pPSTNCheck->vdiff2[pPSTNCheck->pState.sampleIterations]);
3054 LOGPRINT("%sDiff PSTN: Iloop2[%d] = %d uA\n", LOGPRINT_PREFIX,
3055 pPSTNCheck->pState.sampleIterations,
3056 pPSTNCheck->iloop2[pPSTNCheck->pState.sampleIterations]);
3057 }
3058#endif
3059 pPSTNCheck->pState.sampleIterations++;
3060 if(pPSTNCheck->pState.sampleIterations >= pPSTNCheck->samples)
3061 {
3062 /* Compute averages */
3063 for (i=0; i<pPSTNCheck->samples; i++)
3064 {
3065 pPSTNCheck->vdiff1_avg += pPSTNCheck->vdiff1[i];
3066 pPSTNCheck->iloop1_avg += pPSTNCheck->iloop1[i];
3067 pPSTNCheck->vdiff2_avg += pPSTNCheck->vdiff2[i];
3068 pPSTNCheck->iloop2_avg += pPSTNCheck->iloop2[i];
3069 }
3070
3071 pPSTNCheck->vdiff1_avg /= pPSTNCheck->samples;
3072 pPSTNCheck->iloop1_avg /= pPSTNCheck->samples;
3073 pPSTNCheck->vdiff2_avg /= pPSTNCheck->samples;
3074 pPSTNCheck->iloop2_avg /= pPSTNCheck->samples;
3075
3076 /* Force small (probably offset) currents to minimum value */
3077 if(abs_int32(pPSTNCheck->iloop1_avg) < PSTN_DET_MIN_ILOOP)
3078 {
3079 pPSTNCheck->iloop1_avg = PSTN_DET_MIN_ILOOP;
3080 }
3081 if(abs_int32(pPSTNCheck->iloop2_avg) < PSTN_DET_MIN_ILOOP)
3082 {
3083 pPSTNCheck->iloop2_avg = PSTN_DET_MIN_ILOOP;
3084 }
3085
3086 /* Calculate measured loop impedance */
3087 pPSTNCheck->rl1 = abs_int32((
3088 pPSTNCheck->vdiff1_avg*1000L)/pPSTNCheck->iloop1_avg);
3089 pPSTNCheck->rl2 = abs_int32((
3090 pPSTNCheck->vdiff2_avg*1000L)/pPSTNCheck->iloop2_avg);
3091
3092 /* Force non-zero loop resistance */
3093 if(pPSTNCheck->rl1 == 0)
3094 {
3095 pPSTNCheck->rl1 = 1;
3096 }
3097 if(pPSTNCheck->rl2 == 0)
3098 {
3099 pPSTNCheck->rl2 = 1;
3100 }
3101
3102 /* Qualify loop impedances */
3103 pPSTNCheck->rl_ratio = (pPSTNCheck->rl1*1000L)/pPSTNCheck->rl2;
3104#ifdef ENABLE_DEBUG
3105 if ( DEBUG_ENABLED(pProslic) )
3106 {
3107 const char fmt_string[] = "%sDiffPSTN: %s = %d %s\n";
3108 LOGPRINT(fmt_string, LOGPRINT_PREFIX, "VDIFF1", pPSTNCheck->vdiff1_avg, "mV");
3109 LOGPRINT(fmt_string, LOGPRINT_PREFIX, "ILOOP1",pPSTNCheck->iloop1_avg, "uA");
3110 LOGPRINT(fmt_string, LOGPRINT_PREFIX, "VDIFF2",pPSTNCheck->vdiff2_avg, "mV");
3111 LOGPRINT(fmt_string, LOGPRINT_PREFIX, "ILOOP2",pPSTNCheck->iloop2_avg, "uA");
3112 LOGPRINT(fmt_string, LOGPRINT_PREFIX, "RL1",pPSTNCheck->rl1, "ohm");
3113 LOGPRINT(fmt_string, LOGPRINT_PREFIX, "RL2",pPSTNCheck->rl2, "ohm");
3114 LOGPRINT(fmt_string, LOGPRINT_PREFIX, "RL_Ratio",pPSTNCheck->rl_ratio, " ");
3115 }
3116#endif
3117
3118 /* Restore */
3119 pPSTNCheck->pState.sampleIterations = 0;
3120 pPSTNCheck->pState.stage = 70;
3121 }
3122 return RC_NONE;
3123
3124 case 70: /* Reset test state, restore entry conditions */
3125 ProSLIC_DCFeedSetup(pProslic,pPSTNCheck->entryDCFeedPreset);
3126 ProSLIC_SetLinefeedStatus(pProslic,pPSTNCheck->lfstate_entry);
3127 WriteReg(pProHW,pProslic->channel,PROSLIC_REG_ENHANCE, pPSTNCheck->enhanceRegSave);
3128 pPSTNCheck->pState.stage = 0;
3129 pPSTNCheck->pState.waitIterations = 0;
3130 pPSTNCheck->pState.sampleIterations = 0;
3131 return pPSTNCheck->return_status;
3132
3133 }
3134 return RC_NONE;
3135}
3136
3137#endif
3138