blob: 2596688bec870706a650cbab0f8872d352834e71 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001/*
2** Copyright (c) 2015-2017 by Silicon Laboratories
3**
4** $Id: demo_common.c 6365 2017-04-06 22:18:56Z nizajerk $
5**
6** Distributed by:
7** Silicon Laboratories, Inc
8**
9** This file contains proprietary information.
10** No dissemination allowed without prior written permission from
11** Silicon Laboratories, Inc.
12**
13** File Description:
14** Various utility functions that are common for the ProSLIC API demos...
15**
16**
17*/
18
19#include "demo_common.h"
20#include "user_intf.h"
21#include "si_voice_datatypes.h"
22#include "api_demo.h"
23
24
25////#include DEMO_INCLUDE
26
27/* If the header files are NOT defined, this is the fall back limit */
28#define SI_DEMO_MAX_ENUM_DEFAULT 32
29
30#ifdef FXS_CONSTANTS_HDR
31#include FXS_CONSTANTS_HDR /* See makefile for how this is determined... */
32#endif
33
34#ifdef DAA_CONSTANTS_HDR
35#include DAA_CONSTANTS_HDR /* See makefile for how this is determined... */
36#endif
37
38#ifdef SI3217X
39#include "si3217x.h"
40#include "vdaa.h"
41extern Si3217x_General_Cfg Si3217x_General_Configuration;
42#endif
43
44#ifdef SI3226X
45#include "si3226x.h"
46#endif
47
48#ifdef SI3218X
49#include "si3218x.h"
50#endif
51
52#ifdef SI3219X
53#include "si3219x.h"
54#endif
55
56#ifdef SI3228X
57#include "si3228x.h"
58#endif
59
60#ifdef VDAA_SUPPORT
61#include "vdaa.h"
62#endif
63
64#ifdef TSTIN_SUPPORT
65#include "proslic_tstin_limits.h"
66#endif
67
68/*****************************************************************************************************/
69#ifdef PERL
70
71#ifndef NOFXS_SUPPORT
72extern const char *Ring_preset_options[];
73extern const char *DcFeed_preset_options[];
74extern const char *Impedance_preset_options[];
75extern const char *FSK_preset_options[];
76extern const char *PulseMeter_preset_options[];
77extern const char *Tone_preset_options[];
78extern const char *PCM_preset_options[];
79#endif
80
81#ifdef VDAA_SUPPORT
82extern const char *Vdaa_country_preset_options[];
83extern const char *Vdaa_audioGain_preset_options[];
84extern const char *Vdaa_ringDetect_preset_options[];
85extern const char *Vdaa_PCM_preset_options[];
86extern const char *Vdaa_hybrid_preset_options[];
87#endif
88
89#endif /* PERL */
90
91extern int modem_is_wb, modem_is_master;
92/*****************************************************************************************************/
93#ifndef LOGPRINT_PREFIX
94#define LOGPRINT_PREFIX "ProSLIC_DEMO: "
95#endif
96
97/*****************************************************************************************************/
98/* This is a simple initialization - all ports have the same device type. For a more complex
99 * system, a customer could key off of port_id and depending on value, fill in the "correct" setting
100 * for their system. No memory allocation is done here.
101 */
102#ifndef SIVOICE_USE_CUSTOM_PORT_INFO
103void demo_init_port_info(demo_port_t *port, unsigned int port_id)
104{
105 SILABS_UNREFERENCED_PARAMETER(port_id);
106#ifdef SI3217X
107 port->deviceType = SI3217X_TYPE;
108 port->numberOfDevice = SI3217XB_NUMBER_OF_DEVICE;
109 port->numberOfChan = SI3217XB_NUMBER_OF_CHAN;
110 port->chanPerDevice = SI3217X_CHAN_PER_DEVICE;
111#endif
112
113#ifdef SI3226X
114 port->deviceType = SI3226X_TYPE;
115 port->numberOfDevice = SI3226X_NUMBER_OF_DEVICE;
116 port->numberOfChan = SI3226X_NUMBER_OF_CHAN;
117 port->chanPerDevice =SI3226X_CHAN_PER_DEVICE;
118#endif
119
120#ifdef SI3218X
121 port->deviceType = SI3218X_TYPE;
122 port->numberOfDevice = SI3218X_NUMBER_OF_DEVICE;
123 port->numberOfChan = SI3218X_NUMBER_OF_CHAN;
124 port->chanPerDevice = SI3218X_CHAN_PER_DEVICE;
125#endif
126
127#ifdef SI3219X
128 port->deviceType = SI3219X_TYPE;
129 port->numberOfDevice = SI3219X_NUMBER_OF_DEVICE;
130 port->numberOfChan = SI3219X_NUMBER_OF_CHAN;
131 port->chanPerDevice = SI3219X_CHAN_PER_DEVICE;
132#endif
133
134#ifdef SI3228X
135 port->deviceType = SI3228X_TYPE;
136 port->numberOfDevice = SI3228X_NUMBER_OF_DEVICE;
137 port->numberOfChan = SI3228X_NUMBER_OF_CHAN;
138 port->chanPerDevice = SI3228X_CHAN_PER_DEVICE;
139#endif
140
141#ifdef SI3050_CHIPSET
142 port->deviceType = SI3050_TYPE;
143 port->numberOfDevice = SI3050_NUMBER_OF_DEVICE;
144 port->numberOfChan = SI3050_NUMBER_OF_CHAN;
145 port->chanPerDevice = SI3050_CHAN_PER_DEVICE;
146#endif
147
148}
149#endif /* SIVOICE_USE_CUSTOM_PORT_INFO */
150
151/*****************************************************************************************************/
152
153int demo_alloc(demo_port_t *port, int *base_channel_index,
154 controlInterfaceType *proslic_api_hwIf)
155{
156 int i;
157
158 LOGPRINT("%sAllocating memory\n", LOGPRINT_PREFIX);
159
160 /* First allocate all the needed data structures for ProSLIC API */
161 if( SiVoice_createDevices(&(port->devices),
162 (uInt32)(port->numberOfDevice)) != RC_NONE )
163 {
164 return RC_NO_MEM;
165 }
166
167 if( SiVoice_createChannels(&(port->channels),
168 (uInt32)port->numberOfChan) != RC_NONE )
169 {
170 goto free_mem;
171 }
172
173 /* Demo specific code */
174 port->channelPtrs = SIVOICE_CALLOC(sizeof(SiVoiceChanType_ptr),
175 port->numberOfChan);
176
177 port->demo_info = SIVOICE_CALLOC(sizeof(demo_chan_info_t),
178 port->numberOfChan);
179
180 if( (port->channelPtrs == NULL) || (port->demo_info == NULL) )
181 {
182 goto free_mem;
183 }
184
185 /* Back to API init code */
186#ifdef TSTIN_SUPPORT
187 LOGPRINT("%sCreating Inward Test Objs...\n", LOGPRINT_PREFIX);
188 if( ProSLIC_createTestInObjs(&(port->pTstin),
189 (uInt32)(port->numberOfChan) != RC_NONE) )
190 {
191 goto free_mem;
192 }
193#endif
194
195 for(i = 0; i < port->numberOfChan; i++)
196 {
197 /* If supporting more than 1 SPI interface, a code change is needed here - channel count may not match
198 * and the pointer to the api_hwIf may change for the SPI object... */
199 if(SiVoice_SWInitChan(&(port->channels[i]),
200 (i + port->channelBaseIndex), port->deviceType,
201 &(port->devices[i/port->chanPerDevice]), proslic_api_hwIf ) != RC_NONE)
202 {
203 goto free_mem;
204 }
205 port->channelPtrs[i] = &(port->channels[i]); /* Demo specific */
206#ifdef TSTIN_SUPPORT
207 LOGPRINT("%sConfiguring Inward Tests...\n", LOGPRINT_PREFIX);
208 ProSLIC_testInPcmLpbkSetup(port->pTstin, &ProSLIC_testIn_PcmLpbk_Test);
209 ProSLIC_testInDcFeedSetup(port->pTstin, &ProSLIC_testIn_DcFeed_Test);
210 ProSLIC_testInRingingSetup(port->pTstin, &ProSLIC_testIn_Ringing_Test);
211 ProSLIC_testInBatterySetup(port->pTstin, &ProSLIC_testIn_Battery_Test);
212 ProSLIC_testInAudioSetup(port->pTstin, &ProSLIC_testIn_Audio_Test);
213#endif
214
215 SiVoice_setSWDebugMode(&(port->channels[i]),
216 TRUE); /* Enable debug mode for all channels */
217#ifdef ENABLE_INITIAL_LOGGING
218 SiVoice_setTraceMode(&(port->channels[i]),
219 TRUE); /* Enable trace mode for all channels */
220#endif
221 }
222
223 /* Demo specific code */
224 port->channelBaseIndex = *base_channel_index;
225 (*base_channel_index) += port->numberOfChan;
226
227 return RC_NONE;
228
229free_mem:
230 demo_free(port);
231 return RC_NO_MEM;
232}
233
234/*****************************************************************************************************/
235int demo_init_devices(demo_port_t *port)
236{
237 int rc=0;
238
239
240#ifndef NOFXS_SUPPORT
241 LOGPRINT("%sInitializing ProSLIC...\n", LOGPRINT_PREFIX);
242 if(ProSLIC_Init(port->channelPtrs, port->numberOfChan) != RC_NONE)
243 {
244 LOGPRINT("%s ERROR: ProSLIC_Init() failed\n", LOGPRINT_PREFIX);
245 return(-1);
246 }
247#endif
248#ifdef VDAA_SUPPORT
249 if( (port->deviceType == SI3050_TYPE)
250#if defined(SI3217X)
251 /* Si32178/9 Rev B only supports VDAA */
252 ||( (Si3217x_General_Configuration.daa_cntl != 0)
253 && (port->deviceType == SI3217X_TYPE)
254 && (port->channels->deviceId->chipRev == 1) )
255
256#endif /* 17x */
257 )
258 {
259 LOGPRINT("%sInitializing FXO...\n", LOGPRINT_PREFIX);
260 /* Initialize any DAA channels that are present */
261 if (Vdaa_Init(port->channelPtrs, port->numberOfChan))
262 {
263 LOGPRINT("\n%s ERROR : DAA Initialization Failed\n", LOGPRINT_PREFIX);
264 return(-1);
265 }
266 }
267#endif
268
269#ifndef SKIP_LBCAL
270 /*
271 ** Longitudinal Balance Calibration
272 **
273 */
274 LOGPRINT("%sStarting Longitudinal Balance Calibration...\n", LOGPRINT_PREFIX);
275 rc = ProSLIC_LBCal(port->channelPtrs, port->numberOfChan);
276 if(rc != RC_NONE)
277 {
278 LOGPRINT("\n%sLB CAL ERROR : %d\n", LOGPRINT_PREFIX, rc);
279 }
280#endif
281
282 return rc;
283}
284
285/*****************************************************************************************************/
286int demo_load_presets(demo_port_t *port)
287{
288 int i;
289 SiVoiceChanType_ptr chanPtr;
290
291 LOGPRINT("%sLoading presets...\n",LOGPRINT_PREFIX);
292 for(i = 0; i < port->numberOfChan; i++)
293 {
294 chanPtr = port->channelPtrs[i];
295#ifndef NOFXS_SUPPORT
296 /* We assume the 1st constants setting is the default one... */
297 ProSLIC_DCFeedSetup(chanPtr, 0);
298 ProSLIC_RingSetup(chanPtr, 0);
299 ProSLIC_ZsynthSetup(chanPtr, 0);
300
301 if (modem_is_wb)
302 ProSLIC_PCMSetup(chanPtr, PCM_16LIN_WB);
303 else
304 ProSLIC_PCMSetup(chanPtr, PCM_16LIN);
305
306 ProSLIC_PCMTimeSlotSetup(chanPtr, 1, 1); //1826 MSA use 1 bit offset for both Rx & Tx PCM data
307#endif
308
309#ifdef VDAA_SUPPORT
310 Vdaa_CountrySetup(chanPtr, 0);
311 Vdaa_HybridSetup(chanPtr, 0);
312 Vdaa_PCMSetup(chanPtr, 0);
313#endif
314 }
315 return 0;
316}
317
318/*****************************************************************************************************/
319int demo_set_chan_state(demo_port_t *port)
320{
321 int i;
322#ifndef NOFXS_SUPPORT
323 int j;
324#endif
325 SiVoiceChanType_ptr chanPtr;
326
327 for(i = 0; i < port->numberOfChan; i++)
328 {
329 chanPtr = port->channelPtrs[i];
330#ifndef NOFXS_SUPPORT
331 ProSLIC_SetLinefeedStatus(chanPtr, LF_FWD_ACTIVE);
332 ProSLIC_EnableInterrupts(chanPtr);
333
334 /* Cache IRQEN settings for the demo */
335 for(j = PROSLIC_REG_IRQEN1; j < PROSLIC_REG_IRQEN4; j++)
336 {
337 port->demo_info[i].irq_save[j-PROSLIC_REG_IRQEN1] =
338 SiVoice_ReadReg(chanPtr, j);
339 }
340#endif
341
342#ifdef VDAA_SUPPORT
343 Vdaa_SetHookStatus(chanPtr, VDAA_ONHOOK);
344#endif
345 }
346 return 0;
347}
348
349/*****************************************************************************************************/
350void demo_shutdown(demo_port_t *port)
351{
352#ifdef NOFXS_SUPPORT
353 SILABS_UNREFERENCED_PARAMETER(port);
354#else
355 int i;
356 SiVoiceChanType_ptr chanPtr;
357
358 for(i = 0; i < port->numberOfChan; i++)
359 {
360 chanPtr = port->channelPtrs[i];
361 ProSLIC_ShutdownChannel(chanPtr);
362 }
363#endif
364}
365
366/*****************************************************************************************************/
367void demo_free(demo_port_t *port)
368{
369#ifdef TSTIN_SUPPORT
370 ProSLIC_destroyTestInObjs(&(port->pTstin));
371#endif
372 if(port->demo_info != NULL)
373 {
374 SIVOICE_FREE(port->demo_info);
375 }
376
377 SiVoice_destroyChannels( &(port->channels) );
378 SiVoice_destroyDevices( &(port->devices) );
379
380 if(port->channelPtrs != NULL)
381 {
382 SIVOICE_FREE(port->channelPtrs);
383 }
384}
385
386/*****************************************************************************************************/
387int demo_get_preset(demo_preset_t preset_enum)
388{
389 int max_value, user_input;
390 const char *preset_string[] =
391 {
392 "Ringing",
393 "DC Feed",
394 "Zsynth",
395 "FSK",
396 "Pulse Metering",
397 "Tone Generation",
398 "PCM",
399 "Country",
400 "Audio Gain",
401 "Ring Validation",
402 "PCM",
403 "Hybrid"
404 };
405#ifdef PERL
406 const char **menu_items;
407#endif
408 switch(preset_enum)
409 {
410#ifndef NOFXS_SUPPORT
411 case DEMO_RING_PRESET:
412#ifdef FXS_CONSTANTS_HDR
413 max_value = RINGING_LAST_ENUM-1;
414#else
415 max_value = SI_DEMO_MAX_ENUM_DEFAULT;
416#endif
417#ifdef PERL
418 menu_items = Ring_preset_options;
419#endif
420 break;
421
422 case DEMO_DCFEED_PRESET:
423#ifdef FXS_CONSTANTS_HDR
424 max_value = DC_FEED_LAST_ENUM-1;
425#else
426 max_value = SI_DEMO_MAX_ENUM_DEFAULT;
427#endif
428
429#ifdef PERL
430 menu_items = DcFeed_preset_options;
431#endif
432 break;
433
434 case DEMO_IMPEDANCE_PRESET:
435#ifdef FXS_CONSTANTS_HDR
436 max_value = IMPEDANCE_LAST_ENUM-1;
437#else
438 max_value = SI_DEMO_MAX_ENUM_DEFAULT;
439#endif
440
441#ifdef PERL
442 menu_items = Impedance_preset_options;
443#endif
444 break;
445
446 case DEMO_FSK_PRESET:
447#ifdef FXS_CONSTANTS_HDR
448 max_value = FSK_LAST_ENUM-1;
449#else
450 max_value = SI_DEMO_MAX_ENUM_DEFAULT;
451#endif
452
453#ifdef PERL
454 menu_items = FSK_preset_options;
455#endif
456 break;
457
458 case DEMO_PM_PRESET:
459#ifdef FXS_CONSTANTS_HDR
460 max_value = PULSE_METERING_LAST_ENUM-1;
461#else
462 max_value = SI_DEMO_MAX_ENUM_DEFAULT;
463#endif
464
465#ifdef PERL
466 menu_items = PulseMeter_preset_options;
467#endif
468 break;
469
470 case DEMO_TONEGEN_PRESET:
471#ifdef FXS_CONSTANTS_HDR
472 max_value = TONE_LAST_ENUM-1;
473#else
474 max_value = SI_DEMO_MAX_ENUM_DEFAULT;
475#endif
476
477#ifdef PERL
478 menu_items = Tone_preset_options;
479#endif
480 break;
481
482 case DEMO_PCM_PRESET:
483#ifdef FXS_CONSTANTS_HDR
484 max_value = PCM_LAST_ENUM-1;
485#else
486 max_value = SI_DEMO_MAX_ENUM_DEFAULT;
487#endif
488
489#ifdef PERL
490 menu_items = PCM_preset_options;
491#endif
492 break;
493#endif /* FXS selection */
494
495#ifdef VDAA_SUPPORT
496 case DEMO_VDAA_COUNTRY_PRESET:
497#ifdef DAA_CONSTANTS_HDR
498 max_value = VDAA_COUNTRY_LAST_ENUM-1;
499#else
500 max_value = SI_DEMO_MAX_ENUM_DEFAULT;
501#endif
502
503#ifdef PERL
504 menu_items = Vdaa_country_preset_options;
505#endif
506 break;
507
508 case DEMO_VDAA_AUDIO_GAIN_PRESET:
509#ifdef DAA_CONSTANTS_HDR
510 max_value = VDAA_AUDIO_GAIN_LAST_ENUM-1;
511#else
512 max_value = SI_DEMO_MAX_ENUM_DEFAULT;
513#endif
514
515#ifdef PERL
516 menu_items = Vdaa_audioGain_preset_options;
517#endif
518 break;
519
520 case DEMO_VDAA_RING_VALIDATION_PRESET:
521#ifdef DAA_CONSTANTS_HDR
522 max_value = VDAA_RING_VALIDATION_LAST_ENUM-1;
523#else
524 max_value = SI_DEMO_MAX_ENUM_DEFAULT;
525#endif
526
527#ifdef PERL
528 menu_items = Vdaa_ringDetect_preset_options;
529#endif
530 break;
531
532 case DEMO_VDAA_PCM_PRESET:
533#ifdef DAA_CONSTANTS_HDR
534 max_value = VDAA_PCM_LAST_ENUM-1;
535#else
536 max_value = SI_DEMO_MAX_ENUM_DEFAULT;
537#endif
538
539#ifdef PERL
540 menu_items = Vdaa_PCM_preset_options;
541#endif
542 break;
543
544 case DEMO_VDAA_HYBRID_PRESET:
545#ifdef DAA_CONSTANTS_HDR
546 max_value = VDAA_HYBRID_LAST_ENUM-1;
547#else
548 max_value = SI_DEMO_MAX_ENUM_DEFAULT;
549#endif
550
551#ifdef PERL
552 menu_items = Vdaa_hybrid_preset_options;
553#endif
554 break;
555#endif /* VDAA */
556 default:
557 return -1; /* We shouldn't hit this line... but just in case... */
558 } /* switch(preset_enum) */
559
560#ifndef PERL
561 do
562 {
563 printf("Enter %s preset (0-%d) %s", preset_string[preset_enum], max_value,
564 PROSLIC_PROMPT);
565 user_input = get_int(0, max_value);
566 }
567 while( user_input >= max_value);
568#else
569 do
570 {
571 display_menu(preset_string[preset_enum], menu_items);
572 printf("Select Menu item (0-%d) %s ", max_value, PROSLIC_PROMPT);
573 user_input = get_int( 0, max_value) ;
574 }
575 while(user_input > max_value);
576#endif
577 return user_input;
578}
579
580/*****************************************************************************************************/
581SiVoiceChanType_ptr demo_get_cptr(demo_state_t *pState, int channel_number)
582{
583 int i;
584
585 if(channel_number >= pState->totalChannelCount)
586 {
587 return NULL;
588 }
589
590 /* Determine which port we're on */
591 for(i = 0; channel_number < pState->ports[i].channelBaseIndex; i++)
592 {
593 }
594 return pState->ports[i].channelPtrs[(channel_number - pState->ports[i].channelBaseIndex)];
595}
596
597/*****************************************************************************************************/
598void demo_save_slic_irqens(demo_state_t *pState)
599{
600 int portIndex = pState->currentChannel - pState->currentPort->channelBaseIndex;
601 int i;
602
603 for(i = PROSLIC_REG_IRQEN1; i < PROSLIC_REG_IRQEN4; i++)
604 {
605 pState->currentPort->demo_info[portIndex].irq_save[i-PROSLIC_REG_IRQEN1] =
606 SiVoice_ReadReg(pState->currentChanPtr, i);
607 }
608}
609
610/*****************************************************************************************************/
611void demo_restore_slic_irqens(demo_state_t *pState)
612{
613 int portIndex = pState->currentChannel - pState->currentPort->channelBaseIndex;
614 int i;
615
616 for(i = PROSLIC_REG_IRQEN1; i < PROSLIC_REG_IRQEN4; i++)
617 {
618 SiVoice_WriteReg(pState->currentChanPtr, i,
619 pState->currentPort->demo_info[portIndex].irq_save[i-PROSLIC_REG_IRQEN1] );
620 }
621}
622