d9b5d0c65d018d8124d29ecc0b79f1d10a95d102
[o-du/phy.git] / fhi_lib / app / src / common.c
1 /******************************************************************************
2 *
3 *   Copyright (c) 2019 Intel.
4 *
5 *   Licensed under the Apache License, Version 2.0 (the "License");
6 *   you may not use this file except in compliance with the License.
7 *   You may obtain a copy of the License at
8 *
9 *       http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *   Unless required by applicable law or agreed to in writing, software
12 *   distributed under the License is distributed on an "AS IS" BASIS,
13 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *   See the License for the specific language governing permissions and
15 *   limitations under the License.
16 *
17 *******************************************************************************/
18
19
20 #include <assert.h>
21 #include <err.h>
22 #include <arpa/inet.h>
23 #include <sys/time.h>
24 #include <time.h>
25
26 #include "common.h"
27 #include "xran_fh_o_du.h"
28 #include "xran_pkt.h"
29 #include "xran_pkt_up.h"
30 #include "xran_cp_api.h"
31 #include "xran_up_api.h"
32
33 #include "xran_mlog_lnx.h"
34
35 extern enum app_state state;
36
37 int iq_playback_buffer_size_dl = IQ_PLAYBACK_BUFFER_BYTES;
38 int iq_playback_buffer_size_ul = IQ_PLAYBACK_BUFFER_BYTES;
39
40 uint8_t numCCPorts = 1;
41 /* Number of antennas supported by front-end */
42
43 uint8_t num_eAxc = 4;
44 /* Number of CPRI ports supported by front-end */
45
46 int16_t *p_tx_play_buffer[MAX_ANT_CARRIER_SUPPORTED];
47 int32_t tx_play_buffer_size[MAX_ANT_CARRIER_SUPPORTED];
48 int32_t tx_play_buffer_position[MAX_ANT_CARRIER_SUPPORTED];
49
50 int16_t *p_tx_prach_play_buffer[MAX_ANT_CARRIER_SUPPORTED];
51 int32_t tx_prach_play_buffer_size[MAX_ANT_CARRIER_SUPPORTED];
52 int32_t tx_prach_play_buffer_position[MAX_ANT_CARRIER_SUPPORTED];
53
54 int16_t *p_rx_log_buffer[MAX_ANT_CARRIER_SUPPORTED];
55 int32_t rx_log_buffer_size[MAX_ANT_CARRIER_SUPPORTED];
56 int32_t rx_log_buffer_position[MAX_ANT_CARRIER_SUPPORTED];
57
58 int16_t *p_prach_log_buffer[MAX_ANT_CARRIER_SUPPORTED];
59 int32_t prach_log_buffer_size[MAX_ANT_CARRIER_SUPPORTED];
60 int32_t prach_log_buffer_position[MAX_ANT_CARRIER_SUPPORTED];
61
62 int16_t *p_tx_buffer[MAX_ANT_CARRIER_SUPPORTED];
63 int32_t tx_buffer_size[MAX_ANT_CARRIER_SUPPORTED];
64
65 int16_t *p_rx_buffer[MAX_ANT_CARRIER_SUPPORTED];
66 int32_t rx_buffer_size[MAX_ANT_CARRIER_SUPPORTED];
67
68
69 // F1 Tables 38.101-1 Table 5.3.2-1. Maximum transmission bandwidth configuration NRB
70 uint16_t nNumRbsPerSymF1[3][13] =
71 {
72     //  5MHz    10MHz   15MHz   20 MHz  25 MHz  30 MHz  40 MHz  50MHz   60 MHz  70 MHz  80 MHz   90 MHz  100 MHz
73         {25,    52,     79,     106,    133,    160,    216,    270,    0,         0,      0,      0,      0},         // Numerology 0 (15KHz)
74         {11,    24,     38,     51,     65,     78,     106,    133,    162,       0,    217,    245,    273},         // Numerology 1 (30KHz)
75         {0,     11,     18,     24,     31,     38,     51,     65,     79,        0,    107,    121,    135}          // Numerology 2 (60KHz)
76 };
77
78 // F2 Tables 38.101-2 Table 5.3.2-1. Maximum transmission bandwidth configuration NRB
79 uint16_t nNumRbsPerSymF2[2][4] =
80 {
81     //  50Mhz  100MHz  200MHz   400MHz
82         {66,    132,    264,     0},        // Numerology 2 (60KHz)
83         {32,    66,     132,     264}       // Numerology 3 (120KHz)
84 };
85
86 // 38.211 - Table 4.2.1
87 uint16_t nSubCarrierSpacing[5] =
88 {
89     15,     // mu = 0
90     30,     // mu = 1
91     60,     // mu = 2
92     120,    // mu = 3
93     240     // mu = 4
94 };
95
96 // TTI interval in us (slot duration)
97 uint16_t nTtiInterval[4] =
98 {
99     1000,     // mu = 0
100     500,     // mu = 1
101     250,     // mu = 2
102     125,     // mu = 3
103 };
104
105
106 // F1 Tables 38.101-1 Table F.5.3. Window length for normal CP
107 uint16_t nCpSizeF1[3][13][2] =
108 {
109     //    5MHz      10MHz      15MHz       20 MHz      25 MHz     30 MHz      40 MHz       50MHz       60 MHz      70 MHz     80 MHz     90 MHz     100 MHz
110         {{40, 36}, {80, 72}, {120, 108}, {160, 144}, {160, 144}, {240, 216}, {320, 288}, {320, 288},     {0, 0},     {0, 0},     {0, 0},     {0, 0},     {0, 0}},        // Numerology 0 (15KHz)
111         {{22, 18}, {44, 36},   {66, 54},   {88, 72},   {88, 72}, {132, 108}, {176, 144}, {176, 144}, {264, 216}, {264, 216}, {352, 288}, {352, 288}, {352, 288}},       // Numerology 1 (30KHz)
112         {  {0, 0}, {26, 18},   {39, 27},   {52, 36},   {52, 36},   {78, 54},  {104, 72},  {104, 72}, {156, 108}, {156, 108}, {208, 144}, {208, 144}, {208, 144}},       // Numerology 2 (60KHz)
113 };
114
115 // F2 Tables 38.101-2 Table F.5.3. Window length for normal CP
116 int16_t nCpSizeF2[2][4][2] =
117 {
118     //    50Mhz    100MHz      200MHz     400MHz
119         {  {0, 0}, {104, 72}, {208, 144}, {416, 288}}, // Numerology 2 (60KHz)
120         {{68, 36}, {136, 72}, {272, 144}, {544, 288}}, // Numerology 3 (120KHz)
121 };
122
123 uint32_t gMaxSlotNum;
124 uint32_t gNumDLCtx;
125 uint32_t gNumULCtx;
126 uint32_t gDLResetAdvance;
127 uint32_t gDLProcAdvance;
128 uint32_t gULProcAdvance;
129
130 static uint16_t g_NumSlotTDDLoop[XRAN_MAX_SECTOR_NR] = { XRAN_NUM_OF_SLOT_IN_TDD_LOOP };
131 static uint16_t g_NumDLSymSp[XRAN_MAX_SECTOR_NR][XRAN_NUM_OF_SLOT_IN_TDD_LOOP] = {0};
132 static uint16_t g_NumULSymSp[XRAN_MAX_SECTOR_NR][XRAN_NUM_OF_SLOT_IN_TDD_LOOP] = {0};
133 static uint8_t g_SlotType[XRAN_MAX_SECTOR_NR][XRAN_NUM_OF_SLOT_IN_TDD_LOOP] = {{XRAN_SLOT_TYPE_INVALID}};
134 float g_UlRate[XRAN_MAX_SECTOR_NR] = {0.0};
135 float g_DlRate[XRAN_MAX_SECTOR_NR] = {0.0};
136
137 uint32_t app_xran_get_tti_interval(uint8_t nMu)
138 {
139     if (nMu < 4)
140     {
141         return nTtiInterval[nMu];
142     }
143     else
144     {
145         printf("ERROR: %s Mu[%d] is not valid\n",__FUNCTION__, nMu);
146     }
147
148     return 0;
149 }
150
151 uint32_t app_xran_get_scs(uint8_t nMu)
152 {
153     if (nMu <= 3)
154     {
155         return nSubCarrierSpacing[nMu];
156     }
157     else
158     {
159         printf("ERROR: %s Mu[%d] is not valid\n",__FUNCTION__, nMu);
160     }
161
162     return 0;
163 }
164
165
166
167
168 //-------------------------------------------------------------------------------------------
169 /** @ingroup group_nr5g_source_phy_common
170  *
171  *  @param[in]   nNumerology - Numerology determine sub carrier spacing, Value: 0->4 0: 15khz,  1: 30khz,  2: 60khz 3: 120khz, 4: 240khz
172  *  @param[in]   nBandwidth - Carrier bandwidth for in MHz. Value: 5->400
173  *  @param[in]   nAbsFrePointA - Abs Freq Point A of the Carrier Center Frequency for in KHz Value: 450000->52600000
174  *
175  *  @return  Number of RBs in cell
176  *
177  *  @description
178  *  Returns number of RBs based on 38.101-1 and 38.101-2 for the cell
179  *
180 **/
181 //-------------------------------------------------------------------------------------------
182 uint16_t app_xran_get_num_rbs(uint32_t nNumerology, uint32_t nBandwidth, uint32_t nAbsFrePointA)
183 {
184     uint32_t error = 1;
185     uint16_t numRBs = 0;
186
187     if (nAbsFrePointA <= 6000000)
188     {
189         // F1 Tables 38.101-1 Table 5.3.2-1. Maximum transmission bandwidth configuration NRB
190         if (nNumerology < 3)
191         {
192             switch(nBandwidth)
193             {
194                 case PHY_BW_5_0_MHZ:
195                     numRBs = nNumRbsPerSymF1[nNumerology][0];
196                     error = 0;
197                 break;
198                 case PHY_BW_10_0_MHZ:
199                     numRBs = nNumRbsPerSymF1[nNumerology][1];
200                     error = 0;
201                 break;
202                 case PHY_BW_15_0_MHZ:
203                     numRBs = nNumRbsPerSymF1[nNumerology][2];
204                     error = 0;
205                 break;
206                 case PHY_BW_20_0_MHZ:
207                     numRBs = nNumRbsPerSymF1[nNumerology][3];
208                     error = 0;
209                 break;
210                 case PHY_BW_25_0_MHZ:
211                     numRBs = nNumRbsPerSymF1[nNumerology][4];
212                     error = 0;
213                 break;
214                 case PHY_BW_30_0_MHZ:
215                     numRBs = nNumRbsPerSymF1[nNumerology][5];
216                     error = 0;
217                 break;
218                 case PHY_BW_40_0_MHZ:
219                     numRBs = nNumRbsPerSymF1[nNumerology][6];
220                     error = 0;
221                 break;
222                 case PHY_BW_50_0_MHZ:
223                     numRBs = nNumRbsPerSymF1[nNumerology][7];
224                     error = 0;
225                 break;
226                 case PHY_BW_60_0_MHZ:
227                     numRBs = nNumRbsPerSymF1[nNumerology][8];
228                     error = 0;
229                 break;
230                 case PHY_BW_70_0_MHZ:
231                     numRBs = nNumRbsPerSymF1[nNumerology][9];
232                     error = 0;
233                 break;
234                 case PHY_BW_80_0_MHZ:
235                     numRBs = nNumRbsPerSymF1[nNumerology][10];
236                     error = 0;
237                 break;
238                 case PHY_BW_90_0_MHZ:
239                     numRBs = nNumRbsPerSymF1[nNumerology][11];
240                     error = 0;
241                 break;
242                 case PHY_BW_100_0_MHZ:
243                     numRBs = nNumRbsPerSymF1[nNumerology][12];
244                     error = 0;
245                 break;
246                 default:
247                     error = 1;
248                 break;
249             }
250         }
251     }
252     else
253     {
254         if ((nNumerology >= 2) && (nNumerology <= 3))
255         {
256             // F2 Tables 38.101-2 Table 5.3.2-1. Maximum transmission bandwidth configuration NRB
257             switch(nBandwidth)
258             {
259                 case PHY_BW_50_0_MHZ:
260                     numRBs = nNumRbsPerSymF2[nNumerology-2][0];
261                     error = 0;
262                 break;
263                 case PHY_BW_100_0_MHZ:
264                     numRBs = nNumRbsPerSymF2[nNumerology-2][1];
265                     error = 0;
266                 break;
267                 case PHY_BW_200_0_MHZ:
268                     numRBs = nNumRbsPerSymF2[nNumerology-2][2];
269                     error = 0;
270                 break;
271                 case PHY_BW_400_0_MHZ:
272                     numRBs = nNumRbsPerSymF2[nNumerology-2][3];
273                     error = 0;
274                 break;
275                 default:
276                     error = 1;
277                 break;
278             }
279         }
280     }
281
282
283     if (error)
284     {
285         printf("ERROR: %s: nNumerology[%d] nBandwidth[%d] nAbsFrePointA[%d]\n",__FUNCTION__, nNumerology, nBandwidth, nAbsFrePointA);
286     }
287     else
288     {
289         printf("%s: nNumerology[%d] nBandwidth[%d] nAbsFrePointA[%d] numRBs[%d]\n",__FUNCTION__, nNumerology, nBandwidth, nAbsFrePointA, numRBs);
290     }
291
292     return numRBs;
293 }
294
295 //-------------------------------------------------------------------------------------------
296 /** @ingroup phy_cal_nrarfcn
297  *
298  *  @param[in]   center frequency
299  *
300  *  @return  NR-ARFCN
301  *
302  *  @description
303  *  This calculates NR-ARFCN value according to center frequency
304  *
305 **/
306 //-------------------------------------------------------------------------------------------
307 uint32_t app_xran_cal_nrarfcn(uint32_t nCenterFreq)
308 {
309     uint32_t nDeltaFglobal,nFoffs,nNoffs;
310     uint32_t nNRARFCN = 0;
311
312     if(nCenterFreq > 0 && nCenterFreq < 3000*1000)
313     {
314         nDeltaFglobal = 5;
315         nFoffs = 0;
316         nNoffs = 0;
317     }
318     else if(nCenterFreq >= 3000*1000 && nCenterFreq < 24250*1000)
319     {
320         nDeltaFglobal = 15;
321         nFoffs = 3000*1000;
322         nNoffs = 600000;
323     }
324     else if(nCenterFreq >= 24250*1000 && nCenterFreq <= 100000*1000)
325     {
326         nDeltaFglobal = 60;
327         nFoffs = 24250080;
328         nNoffs = 2016667;
329     }
330     else
331     {
332          printf("@@@@ incorrect center frerquency %d\n",nCenterFreq);
333          return (0);
334     }
335
336     nNRARFCN = ((nCenterFreq - nFoffs)/nDeltaFglobal) + nNoffs;
337
338     printf("%s: nCenterFreq[%d] nDeltaFglobal[%d] nFoffs[%d] nNoffs[%d] nNRARFCN[%d]\n", __FUNCTION__, nCenterFreq, nDeltaFglobal, nFoffs, nNoffs, nNRARFCN);
339     return (nNRARFCN);
340 }
341
342 int32_t app_xran_slot_limit(int32_t nSfIdx)
343 {
344     while (nSfIdx < 0) {
345         nSfIdx += gMaxSlotNum;
346     }
347
348     while (nSfIdx >= gMaxSlotNum) {
349         nSfIdx -= gMaxSlotNum;
350     }
351
352     return nSfIdx;
353 }
354
355 void app_xran_clear_slot_type(uint32_t nPhyInstanceId)
356 {
357     g_UlRate[nPhyInstanceId] = 0.0;
358     g_DlRate[nPhyInstanceId] = 0.0;
359     g_NumSlotTDDLoop[nPhyInstanceId] = 1;
360 }
361
362 int32_t app_xran_set_slot_type(uint32_t nPhyInstanceId, uint32_t nFrameDuplexType, uint32_t nTddPeriod, struct xran_slot_config *psSlotConfig)
363 {
364     uint32_t nSlotNum, nSymNum, nVal, i;
365     uint32_t numDlSym, numUlSym, numGuardSym;
366     uint32_t numDlSlots = 0, numUlSlots = 0, numSpDlSlots = 0, numSpUlSlots = 0, numSpSlots = 0;
367     char sSlotPattern[XRAN_SLOT_TYPE_LAST][10] = {"IN\0", "DL\0", "UL\0", "SP\0", "FD\0"};
368
369     // nPhyInstanceId    Carrier ID
370     // nFrameDuplexType  0 = FDD 1 = TDD
371     // nTddPeriod        Tdd Periodicity
372     // psSlotConfig[80]  Slot Config Structure for nTddPeriod Slots
373
374     g_UlRate[nPhyInstanceId] = 0.0;
375     g_DlRate[nPhyInstanceId] = 0.0;
376     g_NumSlotTDDLoop[nPhyInstanceId] = nTddPeriod;
377
378     for (i = 0; i < XRAN_NUM_OF_SLOT_IN_TDD_LOOP; i++)
379     {
380         g_SlotType[nPhyInstanceId][i] = XRAN_SLOT_TYPE_INVALID;
381         g_NumDLSymSp[nPhyInstanceId][i] = 0;
382         g_NumULSymSp[nPhyInstanceId][i] = 0;
383     }
384
385     if (nFrameDuplexType == XRAN_FDD)
386     {
387         for (i = 0; i < XRAN_NUM_OF_SLOT_IN_TDD_LOOP; i++)
388         {
389             g_SlotType[nPhyInstanceId][i] = XRAN_SLOT_TYPE_FDD;
390         }
391         g_NumSlotTDDLoop[nPhyInstanceId] = 1;
392         g_DlRate[nPhyInstanceId] = 1.0;
393         g_UlRate[nPhyInstanceId] = 1.0;
394     }
395     else
396     {
397         for (nSlotNum = 0; nSlotNum < nTddPeriod; nSlotNum++)
398         {
399             numDlSym = 0;
400             numUlSym = 0;
401             numGuardSym = 0;
402             for (nSymNum = 0; nSymNum < XRAN_NUM_OF_SYMBOL_PER_SLOT; nSymNum++)
403             {
404                 switch(psSlotConfig[nSlotNum].nSymbolType[nSymNum])
405                 {
406                     case XRAN_SYMBOL_TYPE_DL:
407                         numDlSym++;
408                     break;
409                     case XRAN_SYMBOL_TYPE_GUARD:
410                         numGuardSym++;
411                     break;
412                     default:
413                         numUlSym++;
414                     break;
415                 }
416             }
417
418             // printf("nSlotNum[%d] : numDlSym[%d] numGuardSym[%d] numUlSym[%d]\n", nSlotNum, numDlSym, numGuardSym, numUlSym);
419
420             if ((numUlSym == 0) && (numGuardSym == 0))
421             {
422                 g_SlotType[nPhyInstanceId][nSlotNum] = XRAN_SLOT_TYPE_DL;
423                 numDlSlots++;
424             }
425             else if ((numDlSym == 0) && (numGuardSym == 0))
426             {
427                 g_SlotType[nPhyInstanceId][nSlotNum] = XRAN_SLOT_TYPE_UL;
428                 numUlSlots++;
429             }
430             else
431             {
432                 g_SlotType[nPhyInstanceId][nSlotNum] = XRAN_SLOT_TYPE_SP;
433                 numSpSlots++;
434
435                 if (numDlSym)
436                 {
437                     numSpDlSlots++;
438                     g_NumDLSymSp[nPhyInstanceId][nSlotNum] = numDlSym;
439                 }
440                 if (numUlSym)
441                 {
442                     numSpUlSlots++;
443                     g_NumULSymSp[nPhyInstanceId][nSlotNum] = numUlSym;
444                 }
445             }
446
447             // printf("            numDlSlots[%d] numUlSlots[%d] numSpSlots[%d] numSpDlSlots[%d] numSpUlSlots[%d]\n", numDlSlots, numUlSlots, numSpSlots, numSpDlSlots, numSpUlSlots);
448         }
449
450         g_DlRate[nPhyInstanceId] = (float)(numDlSlots + numSpDlSlots) / (float)nTddPeriod;
451         g_UlRate[nPhyInstanceId] = (float)(numUlSlots + numSpUlSlots) / (float)nTddPeriod;
452     }
453
454     printf("set_slot_type: nPhyInstanceId[%d] nFrameDuplexType[%d], nTddPeriod[%d]\n",
455         nPhyInstanceId, nFrameDuplexType, nTddPeriod);
456
457     printf("DLRate[%f] ULRate[%f]\n", g_DlRate[nPhyInstanceId], g_UlRate[nPhyInstanceId]);
458
459     nVal = (g_NumSlotTDDLoop[nPhyInstanceId] < 10) ? g_NumSlotTDDLoop[nPhyInstanceId] : 10;
460
461     printf("SlotPattern:\n");
462     printf("Slot:   ");
463     for (nSlotNum = 0; nSlotNum < nVal; nSlotNum++)
464     {
465         printf("%d    ", nSlotNum);
466     }
467     printf("\n");
468
469     printf("  %3d   ", 0);
470     for (nSlotNum = 0, i = 0; nSlotNum < g_NumSlotTDDLoop[nPhyInstanceId]; nSlotNum++)
471     {
472         printf("%s   ", sSlotPattern[g_SlotType[nPhyInstanceId][nSlotNum]]);
473         i++;
474         if ((i == 10) && ((nSlotNum+1) < g_NumSlotTDDLoop[nPhyInstanceId]))
475         {
476             printf("\n");
477             printf("  %3d   ", nSlotNum);
478             i = 0;
479         }
480     }
481     printf("\n\n");
482
483     return 0;
484 }
485
486 int32_t app_xran_get_slot_type(int32_t nCellIdx, int32_t nSlotdx, int32_t nType)
487 {
488     int32_t nSfIdxMod, nSfType, ret = 0;
489
490     nSfIdxMod = app_xran_slot_limit(nSlotdx) % ((g_NumSlotTDDLoop[nCellIdx] > 0) ? g_NumSlotTDDLoop[nCellIdx]: 1);
491     nSfType = g_SlotType[nCellIdx][nSfIdxMod];
492
493     if (nSfType == nType)
494     {
495         ret = 1;
496     }
497     else if (nSfType == XRAN_SLOT_TYPE_SP)
498     {
499         if ((nType == XRAN_SLOT_TYPE_DL) && g_NumDLSymSp[nCellIdx][nSfIdxMod])
500         {
501             ret = 1;
502         }
503
504         if ((nType == XRAN_SLOT_TYPE_UL) && g_NumULSymSp[nCellIdx][nSfIdxMod])
505         {
506             ret = 1;
507         }
508     }
509     else if (nSfType == XRAN_SLOT_TYPE_FDD)
510     {
511         ret = 1;
512     }
513
514     return ret;
515 }
516
517
518
519 void sys_save_buf_to_file(char *filename, char *bufname, unsigned char *pBuffer, unsigned int size, unsigned int buffers_num)
520 {
521     if (size)
522     {
523         if (filename && bufname)
524         {
525             FILE           *file;
526             printf("Storing %s to file %s: ", bufname, filename);
527             file = fopen(filename, "wb");
528             if (file == NULL)
529             {
530                 printf("can't open file %s!!!", filename);
531             }
532             else
533             {
534                 uint32_t             num;
535                 num = fwrite(pBuffer, buffers_num, size, file);
536                 fflush(file);
537                 fclose(file);
538                 printf("from addr (0x%lx) size (%d) bytes num (%d)", (uint64_t)pBuffer, size, num);
539             }
540             printf(" \n");
541         }
542         else
543         {
544             printf(" the file name, buffer name are not set!!!");
545         }
546     }
547     else
548     {
549         printf(" the %s is free: size = %d bytes!!!", bufname, size);
550     }
551 }
552
553 int sys_load_file_to_buff(char *filename, char *bufname, unsigned char *pBuffer, unsigned int size, unsigned int buffers_num)
554 {
555     unsigned int  file_size = 0;
556     int  num= 0;
557
558     if (size)
559     {
560         if (filename && bufname)
561         {
562             FILE           *file;
563             printf("Loading file %s to  %s: ", filename, bufname);
564             file = fopen(filename, "rb");
565
566
567             if (file == NULL)
568             {
569                 printf("can't open file %s!!!", filename);
570                 exit(-1);
571             }
572             else
573             {
574                 fseek(file, 0, SEEK_END);
575                 file_size = ftell(file);
576                 fseek(file, 0, SEEK_SET);
577
578                 if ((file_size > size) || (file_size == 0))
579                     file_size = size;
580
581                 printf("Reading IQ samples from file: File Size: %d [Buffer Size: %d]\n", file_size, size);
582
583                 num = fread(pBuffer, buffers_num, size, file);
584                 fflush(file);
585                 fclose(file);
586                 printf("from addr (0x%lx) size (%d) bytes num (%d)", (uint64_t)pBuffer, file_size, num);
587             }
588             printf(" \n");
589
590         }
591         else
592         {
593             printf(" the file name, buffer name are not set!!!");
594         }
595     }
596     else
597     {
598         printf(" the %s is free: size = %d bytes!!!", bufname, size);
599     }
600     return num;
601 }
602
603
604 void sys_save_buf_to_file_txt(char *filename, char *bufname, unsigned char *pBuffer, unsigned int size, unsigned int buffers_num)
605 {
606     unsigned int i;
607     int ret = 0;
608     if (pBuffer == NULL)
609         return;
610
611     if (size)
612     {
613         if (filename && bufname)
614         {
615             FILE           *file;
616             printf("Storing %s to file %s: ", bufname, filename);
617             file = fopen(filename, "w");
618             if (file == NULL)
619             {
620                 printf("can't open file %s!!!", filename);
621                 exit(-1);
622             }
623             else
624             {
625                 uint32_t num = 0;
626
627                 signed short *ptr = (signed short*)pBuffer;
628                 for (i = 0; i < (size/((unsigned int)sizeof(signed short) /** 2 * 2 * 2*/)); i = i + 2)
629                 {
630 #ifndef CSCOPE_DEBUG
631                     ret = fprintf(file,"%d %d\n", ptr[i], ptr[i + 1]);
632 #else
633                     ret = fprintf(file,"%d %d ", ptr[i], ptr[i + 1]);
634                     /*      I data => Ramp data, from 1 to 792.
635                             Q data => Contains time information of the current symbol:
636                             Bits [15:14] = Antenna-ID
637                             Bits [13:12] = \9300\94
638                             Bits [11:8]  = Subframe-ID
639                             Bits [7:4]   = Slot-ID
640                             Bits [3:0]   = Symbol-ID */
641                             fprintf(file, "0x%04x: ant %d Subframe-ID %d Slot-ID %d Symbol-ID %d\n",
642                                         ptr[i + 1], (ptr[i + 1]>>14) & 0x3,  (ptr[i + 1]>>8) & 0xF,  (ptr[i + 1]>>4) & 0xF, (ptr[i + 1]>>0) & 0xF);
643 #endif
644                     if (ret < 0)
645                     {
646                         printf("fprintf %d\n", ret);
647                         fclose(file);
648                         break;
649                     }
650                     num++;
651                 }
652                 fflush(file);
653                 fclose(file);
654                 printf("from addr (0x%lx) size (%d) IQ num (%d)", (uint64_t)pBuffer, size, num);
655             }
656             printf(" \n");
657         }
658         else
659         {
660             printf(" the file name, buffer name are not set!!!");
661         }
662     }
663     else
664     {
665         printf(" the %s is free: size = %d bytes!!!", bufname, size);
666     }
667 }
668