1 /*
2  * Copyright 2018 Oticon A/S
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include "bs_types.h"
7 #include "bs_tracing.h"
8 #include "bs_oswrap.h"
9 #include "bs_utils.h"
10 #include "bs_rand_main.h"
11 #include "bs_pc_2G4.h"
12 #include "bs_pc_2G4_utils.h"
13 #include "modem_if.h"
14 #include "p2G4_pending_tx_rx_list.h"
15 #include "modem_BLE_simple.h"
16 #include "modem_BLE_simple_args.h"
17 #include <math.h>
18 
19 #define FreqRes 200e3
20 
21 //Rx filters "_power_ gain" (gain in natural units ^2) (the gain for the desired modulation should be 0dB)
22 static const double channel_filter_BLE[41] = {
23     1.0000e-06,   1.2589e-06,   1.5849e-06,   1.9953e-06,   2.5119e-06,
24     3.1623e-06,   5.0119e-06,   1.0000e-05,   3.1623e-05,   1.0000e-04,
25     3.1623e-04,   1.0000e-03,   3.1623e-03,   1.0000e-02,   3.9811e-02,
26     1.1398e-01,   2.6304e-01,   6.7212e-01,   7.9446e-01,   9.8531e-01,
27     1.1791e+00,   9.8531e-01,   7.9446e-01,   6.7212e-01,   2.6304e-01,
28     1.1398e-01,   3.9811e-02,   1.0000e-02,   3.1623e-03,   1.0000e-03,
29     3.1623e-04,   1.0000e-04,   3.1623e-05,   1.0000e-05,   5.0119e-06,
30     3.1623e-06,   2.5119e-06,   1.9953e-06,   1.5849e-06,   1.2589e-06,
31     1.0000e-06
32 };
33 static const uint channel_filter_BW_BLE = 20; //How many samples from the center frequency
34 
35 static const double channel_filter_Prop2[81] = {
36     1.0000e-06,   1.5849e-06,   2.5119e-06,   3.9811e-06,   6.3096e-06,
37     7.9433e-06,   1.0000e-05,   1.2589e-05,   1.5849e-05,   1.9953e-05,
38     2.5119e-05,   3.1623e-05,   3.9811e-05,   5.0119e-05,   6.3096e-05,
39     7.9433e-05,   1.0000e-04,   1.2589e-04,   1.5849e-04,   1.9953e-04,
40     2.5119e-04,   3.1623e-04,   3.9811e-04,   5.0119e-04,   6.3096e-04,
41     1.0000e-03,   1.5849e-03,   3.1623e-03,   6.3096e-03,   3.1565e-02,
42     5.2087e-02,   6.4973e-02,   1.3748e-01,   2.0369e-01,   4.3440e-01,
43     8.5992e-01,   1.0097e+00,   1.0097e+00,   1.0097e+00,   1.0097e+00,
44     1.0097e+00,   1.0097e+00,   1.0097e+00,   1.0097e+00,   1.0097e+00,
45     8.5992e-01,   4.3440e-01,   2.0369e-01,   1.3748e-01,   6.4973e-02,
46     5.2087e-02,   3.1565e-02,   6.3096e-03,   3.1623e-03,   1.5849e-03,
47     1.0000e-03,   6.3096e-04,   5.0119e-04,   3.9811e-04,   3.1623e-04,
48     2.5119e-04,   1.9953e-04,   1.5849e-04,   1.2589e-04,   1.0000e-04,
49     7.9433e-05,   6.3096e-05,   5.0119e-05,   3.9811e-05,   3.1623e-05,
50     2.5119e-05,   1.9953e-05,   1.5849e-05,   1.2589e-05,   1.0000e-05,
51     7.9433e-06,   6.3096e-06,   3.9811e-06,   2.5119e-06,   1.5849e-06,
52     1.0000e-06
53 };
54 static const uint channel_filter_BW_Prop2 = 40; //How many samples from the center frequency
55 
56 //_Power_ spectral density of each modulation (in natural units, power (sum must be 1.0))
57 static const double TxSpectrum_BLE[13] = {
58     4.1980e-05,   2.8516e-04,   4.8379e-04,   1.2872e-02,   9.1159e-02,
59     2.4433e-01,   3.0165e-01,   2.4433e-01,   9.1159e-02,   1.2872e-02,
60     4.8379e-04,   2.8516e-04,   4.1980e-05};
61 static const uint TxSpecBW_BLE = 6;
62 
63 static const double TxSpectrum_Prop2[25] =
64 { 1.4055e-05,   5.6012e-05,   1.5134e-04,   2.1890e-04,   1.2972e-04,
65     3.2762e-04,   3.3251e-03,   1.4459e-02,   4.1335e-02,   8.0105e-02,
66     1.1656e-01,   1.5506e-01,   1.7652e-01,   1.5506e-01,   1.1656e-01,
67     8.0105e-02,   4.1335e-02,   1.4459e-02,   3.3251e-03,   3.2762e-04,
68     1.2972e-04,   2.1890e-04,   1.5134e-04,   5.6012e-05,   1.4055e-05};
69 static const uint TxSpecBW_Prop2 = 12;
70 
71 static const double TxSpectrum_WLAN[123] = {
72     1.511874e-006 ,3.797656e-006 ,9.539280e-006 ,1.511874e-005 ,2.396159e-005 ,
73     3.797656e-005 ,6.753293e-005 ,9.539280e-005 ,1.347459e-004 ,1.903337e-004 ,
74     2.688534e-004 ,3.797656e-004 ,4.565786e-004 ,3.016585e-004 ,3.585218e-004 ,
75     5.617144e-004 ,7.071566e-004 ,8.501892e-004 ,7.577319e-004 ,1.200924e-003 ,
76     1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,
77     1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,
78     1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,
79     1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,
80     1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,
81     1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,
82     1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,
83     1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,
84     1.200924e-002 ,2.396159e-003 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,
85     1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,
86     1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,
87     1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,
88     1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,
89     1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,
90     1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,
91     1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,
92     1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-003 ,7.577319e-004 ,
93     8.501892e-004 ,7.071566e-004 ,5.617144e-004 ,3.585218e-004 ,3.016585e-004 ,
94     4.565786e-004 ,3.797656e-004 ,2.688534e-004 ,1.903337e-004 ,1.347459e-004 ,
95     9.539280e-005 ,6.753293e-005 ,3.797656e-005 ,2.396159e-005 ,1.511874e-005 ,
96     9.539280e-006 ,3.797656e-006 ,1.511874e-006
97 };
98 static const uint TxSpecBW_WLAN = 61;
99 
100 static const double TxSpectrum_CW[1]  = {1};
101 static const uint TxSpecBW_CW = 0;
102 static const double TxSpectrum_WN1MHz[5] = {
103     1.0/5 , 1.0/5.0, 1.0/5.0, 1.0/5.0, 1.0/5
104 };
105 static const uint TxSpecBW_WN1MHz = 2;
106 static const double TxSpectrum_WN2MHz[11] = {
107     1.0/20.0, 1.0/10.0, 1.0/10.0, 1.0/10.0, 1.0/10.0,
108     1.0/10.0, 1.0/10.0, 1.0/10.0, 1.0/10.0, 1.0/10.0,
109     1.0/20.0
110 };
111 static const uint TxSpecBW_WN2MHz = 5;
112 static const double TxSpectrum_WN4MHz[21] = {
113     1.0/40.0, 1.0/20.0, 1.0/20.0, 1.0/20.0, 1.0/20.0,
114     1.0/20.0, 1.0/20.0, 1.0/20.0, 1.0/20.0, 1.0/20.0,
115     1.0/20.0, 1.0/20.0, 1.0/20.0, 1.0/20.0, 1.0/20.0,
116     1.0/20.0, 1.0/20.0, 1.0/20.0, 1.0/20.0, 1.0/20.0,
117     1.0/40.0
118 };
119 static const uint TxSpecBW_WN4MHz = 10;
120 
121 static const double TxSpectrum_WN8MHz[41] = {
122     1.0/80.0, 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0,
123     1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0,
124     1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0,
125     1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0,
126     1.0/80.0
127 };
128 
129 static const uint   TxSpecBW_WN8MHz = 20;
130 
131 static const double TxSpectrum_WN16MHz[81] = {
132     1.0/160.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0,
133     1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0,
134     1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0,
135     1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0,
136     1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0,
137     1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0,
138     1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0,
139     1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0,
140     1.0/160.0
141 };
142 static const uint   TxSpecBW_WN16MHz = 40;
143 
144 static const double TxSpectrum_WN20MHz[101] = {
145     1.0/200.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, //1
146     1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, //2
147     1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, //3
148     1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, //4
149     1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, //5
150     1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, //6
151     1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, //7
152     1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, //8
153     1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, //9
154     1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, //10
155     1.0/200.0
156 };
157 
158 static const uint   TxSpecBW_WN20MHz = 50;
159 
160 static const double TxSpectrum_WN40MHz[201] = {
161     1.0/400.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, //1
162     1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, //2
163     1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, //3
164     1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, //4
165     1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, //5
166     1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, //6
167     1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, //7
168     1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, //8
169     1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, //9
170     1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, //10
171     1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, //11
172     1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, //12
173     1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, //13
174     1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, //14
175     1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, //15
176     1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, //16
177     1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, //17
178     1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, //18
179     1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, //19
180     1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, //20
181     1.0/400.0
182 };
183 static const uint   TxSpecBW_WN40MHz = 100;
184 
185 static const double TxSpectrum_WN80MHz[401] = {
186     1.0/800.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //1
187     1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //2
188     1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //3
189     1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //4
190     1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //5
191     1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //6
192     1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //7
193     1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //8
194     1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //9
195     1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //10
196     1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //11
197     1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //12
198     1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //13
199     1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //14
200     1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //15
201     1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //16
202     1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //17
203     1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //18
204     1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //19
205     1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //20
206     1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //21
207     1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //22
208     1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //23
209     1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //24
210     1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //25
211     1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //26
212     1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //27
213     1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //28
214     1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //29
215     1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //30
216     1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //31
217     1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //32
218     1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //33
219     1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //34
220     1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //35
221     1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //36
222     1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //37
223     1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //38
224     1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //39
225     1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //40
226     1.0/800.0
227 };
228 static const uint TxSpecBW_WN80MHz = 200;
229 
230 /**
231  * Return the Rx filter equivalent noise BW for a given Rx modulation configuration
232  *
233  * Note that these values do not need to necessarily match the real Rx filter noise BW.
234  * As they really are just a factor in the thermal noise calculation they may
235  * just include any other effect which would affect the resulting thermal noise component
236  * in the demodulator input for that given modulation.
237  */
noiseBW_from_modulation(uint modulation_type)238 static double noiseBW_from_modulation(uint modulation_type) {
239   switch (modulation_type) {
240     case P2G4_MOD_BLE:
241     case P2G4_MOD_154_250K_DSS: //Provisionally let's treat 15.4 like 1Mbps BLE
242       return 1.1e6;
243       break;
244     case P2G4_MOD_BLE2M:
245     case P2G4_MOD_PROP2M:
246       return 2.5e6;
247       break;
248     default:
249       bs_trace_error_line("modem BLE Simple does not support receiving "
250                           "configured with this modulation type (%i)\n",
251                           modulation_type);
252       break;
253   }
254   return 0;
255 }
256 
RxFilter_from_modulation(uint modulation_type,const double ** filter_attenuation,uint * filter_half_BW)257 static void RxFilter_from_modulation(uint modulation_type, const double ** filter_attenuation,
258                                      uint *filter_half_BW) {
259 
260   switch (modulation_type) {
261     case P2G4_MOD_BLE:
262     case P2G4_MOD_154_250K_DSS: //Provisionally let's treat 15.4 like 1Mbps BLE
263       *filter_attenuation = channel_filter_BLE;
264       *filter_half_BW     = channel_filter_BW_BLE;
265       break;
266     case P2G4_MOD_BLE2M:
267     case P2G4_MOD_PROP2M:
268       *filter_attenuation = channel_filter_Prop2;
269       *filter_half_BW     = channel_filter_BW_Prop2;
270       break;
271     default:
272       bs_trace_error_line("modem BLE Simple does not support receiving "
273                           "configured with this modulation type (%i)\n",
274                           modulation_type);
275       break;
276   }
277 }
278 
spectrum_from_modulation(uint modulation_type,const double ** tx_spectrum,uint * tx_spec_halfBW)279 static void spectrum_from_modulation(uint modulation_type, const double **tx_spectrum,
280                                      uint *tx_spec_halfBW) {
281 
282   switch (modulation_type) {
283     case P2G4_MOD_BLE :
284     case P2G4_MOD_154_250K_DSS: //Provisionally let's treat 15.4 like 1Mbps BLE
285       *tx_spectrum    = TxSpectrum_BLE;
286       *tx_spec_halfBW = TxSpecBW_BLE;
287       break;
288     case P2G4_MOD_BLE2M:
289     case P2G4_MOD_PROP2M:
290       *tx_spectrum    = TxSpectrum_Prop2;
291       *tx_spec_halfBW = TxSpecBW_Prop2;
292       break;
293     case P2G4_MOD_PROP4M :
294       *tx_spectrum    = TxSpectrum_WN4MHz;
295       *tx_spec_halfBW = TxSpecBW_WN4MHz;
296       break;
297     case P2G4_MOD_CWINTER :
298       *tx_spectrum    = TxSpectrum_CW;
299       *tx_spec_halfBW = TxSpecBW_CW;
300       break;
301     case P2G4_MOD_WHITENOISE1MHz :
302       *tx_spectrum    = TxSpectrum_WN1MHz;
303       *tx_spec_halfBW = TxSpecBW_WN1MHz;
304       break;
305     case P2G4_MOD_WHITENOISE2MHz :
306       *tx_spectrum    = TxSpectrum_WN2MHz;
307       *tx_spec_halfBW = TxSpecBW_WN2MHz;
308       break;
309     case P2G4_MOD_WHITENOISE4MHz :
310       *tx_spectrum    = TxSpectrum_WN4MHz;
311       *tx_spec_halfBW = TxSpecBW_WN4MHz;
312       break;
313     case P2G4_MOD_WHITENOISE8MHz :
314       *tx_spectrum    = TxSpectrum_WN8MHz;
315       *tx_spec_halfBW = TxSpecBW_WN8MHz;
316       break;
317     case P2G4_MOD_WHITENOISE16MHz :
318       *tx_spectrum    = TxSpectrum_WN16MHz;
319       *tx_spec_halfBW = TxSpecBW_WN16MHz;
320       break;
321     case P2G4_MOD_WHITENOISE20MHz :
322       *tx_spectrum    = TxSpectrum_WN20MHz;
323       *tx_spec_halfBW = TxSpecBW_WN20MHz;
324       break;
325     case P2G4_MOD_WHITENOISE40MHz :
326       *tx_spectrum    = TxSpectrum_WN40MHz;
327       *tx_spec_halfBW = TxSpecBW_WN40MHz;
328       break;
329     case P2G4_MOD_WHITENOISE80MHz :
330       *tx_spectrum    = TxSpectrum_WN80MHz;
331       *tx_spec_halfBW = TxSpecBW_WN80MHz;
332       break;
333     case P2G4_MOD_WLANINTER :
334       *tx_spectrum    = TxSpectrum_WLAN;
335       *tx_spec_halfBW = TxSpecBW_WLAN;
336       break;
337     default:
338       bs_trace_warning_line("modem BLE Simple does not support seeing this "
339                             "modulation type (%i) in the air, it will be "
340                             "treated as 1MHz white noise\n",modulation_type);
341       *tx_spectrum    = TxSpectrum_WN1MHz;
342       *tx_spec_halfBW = TxSpecBW_WN1MHz;
343       break;
344   }
345 }
346 
347 /**
348  * Q function:
349  *   Q(x) = P(X > x) , where X = N(0,1)
350  *   That is, Q(x) is the probability of a N(0,1) having a value > x
351  *   where N(0,1) is a Normal distribution with average 0, and standard deviation 1
352  */
Q_function(double x)353 static double Q_function(double x) {
354   return 1.0/2.0*erfc(x/sqrt(2.0));
355 }
356 
357 /************
358  * Modem IF *
359  ************/
360 
361 /**
362  * Initialize the modem internal status
363  *
364  * The input parameters are:
365  *   dev_nbr      : the device number this modem library corresponds to
366  *                  (note that this library may be reused in between several devices)
367  *   nbr_devices  : the total number of devices in the simulation (gives the length of vectors later)
368  *   char *argv[] : a set of arguments passed to the modem library (same convention as POSIX main() command line arguments)
369  *   int argc     : the number of arguments passed to the modem library
370  *
371  * It is up to the modem to define which arguments it can or shall receive to configure it
372  * The only argument all modems shall understand is :
373  *    [-h] [--h] [--help] [-?]  The modem shall print a list of arguments it supports with a descriptive message for each
374  *
375  * This function shall return a pointer to this modems status structure
376  * This same pointer will be passed back to consecutive function calls of the library (void *this)
377  *
378  * If the library does not require to keep any status it can just return NULL
379  */
modem_init(int argc,char * argv[],uint d,uint n_devs)380 void* modem_init(int argc, char *argv[], uint d, uint n_devs) {
381   m_simple_status_t* mo_st;
382 
383   mo_st = (m_simple_status_t *)bs_calloc(1,sizeof(m_simple_status_t));
384 
385   mo_st->nbr_devices = n_devs;
386 
387   modem_simple_argparse(argc, argv, d, &mo_st->args);
388 
389   mo_st->device_RSSI_offsetdB = bs_random_Gaus()*mo_st->args.RSSI_offsetdB_std;
390 
391   return (void*)mo_st;
392 }
393 
394 /**
395  * Calculate the SNR of the desired input signal at the digital modem input/analog output
396  * including all modem analog impairments
397  *
398  * inputs:
399  *  this               : Pointer to this modem object
400  *  rx_radioparams     : Radio parameters/configuration of this receiver for this Rx/RSSI measurement
401  *  rx_powers          : For each possible transmitter ([0..n_devices-1]) what is their power level at this device antenna connector in dBm
402  *  txl_c              : For each possible transmitter what are their Tx parameters
403  *  desired_tx_nbr     : which of the transmitters is the one we are trying to receive
404  *
405  * outputs:
406  *  OutputSNR               : SNR in the analog output / digital input of this modem (dB)
407  *  Output_RSSI_power_level : RSSI level (analog, dBm) sent to the modem digital
408  */
modem_analog_rx(void * this,p2G4_radioparams_t * rx_radioparams,double * OutputSNR,double * Output_RSSI_power_level,double * rx_powers,tx_l_c_t * txl_c,uint desired_tx_nbr)409 void modem_analog_rx(void *this, p2G4_radioparams_t *rx_radioparams, double *OutputSNR,
410                      double *Output_RSSI_power_level, double *rx_powers, tx_l_c_t *txl_c,
411                      uint desired_tx_nbr) {
412   m_simple_status_t *mo_st = (m_simple_status_t *)this;
413   uint i;
414 
415   double ThermalNoisemW = 0;
416   double TotalInterfmW  = 0;
417   double TotalPhaseReciprocalMixmW = 0; //If we were more precise, we would also calculate here the phase noise mixing
418   double TotalIntermmW  = 0; //Intermodulation noise. This can be very significant if there is any blocker present, but we don't include it in this model
419 
420   { //Thermal noise calculation
421     double NoiseFigure = mo_st->args.NFigure_ana; //dB
422     double EquivalentBW = noiseBW_from_modulation(rx_radioparams->modulation);
423     ThermalNoisemW = EquivalentBW * pow(10, (-174.0 + NoiseFigure )/10);
424   }
425 
426   { //Interference calculation (including adjacent channel)
427     const double *RxFilterAttenuation;
428     uint RxFilterHalfBW;
429 
430     RxFilter_from_modulation(rx_radioparams->modulation, &RxFilterAttenuation, &RxFilterHalfBW);
431     //The "Rx filter" shall include all effects which would increase
432     //the noise/interference power at a given frequency offset
433 
434     int CenterR = p2G4_freq_to_d(rx_radioparams->center_freq) / (FreqRes/1e6); //Center frequency (where 0 = 2400MHz)
435     int StartR  = CenterR - RxFilterHalfBW;
436     int EndR    = CenterR + RxFilterHalfBW;
437 
438     for ( i = 0; i < mo_st->nbr_devices ; i++ ) {
439       if ( txl_c->used[i] && ( i != desired_tx_nbr ) ){ //For each active transmitter
440         //Calculate how much power comes thru the Rx channel/IF filtering
441 
442         const double *TxSpectrum;
443         uint TxSpecHalfBW;
444 
445         spectrum_from_modulation(txl_c->tx_list[i].tx_s.radio_params.modulation, &TxSpectrum, &TxSpecHalfBW);
446 
447         int CenterI = p2G4_freq_to_d(txl_c->tx_list[i].tx_s.radio_params.center_freq) / (FreqRes/1e6); //Center frequency (where 0 = 2400MHz)
448         int StartI  = CenterI - TxSpecHalfBW;
449         int EndI    = CenterI + TxSpecHalfBW;
450 
451         int StartOverlap = BS_MAX(StartR,StartI);
452         int EndOverlap   = BS_MIN(EndR, EndI);
453 
454         double AccRatio = 0; //Calculate the overlap of the Rx filter with the tx modulation shape
455         for (int Freq = StartOverlap; Freq <= EndOverlap ; Freq++) {
456            int IndexR = (Freq - StartR);
457            int IndexI = (Freq - StartI);
458            AccRatio = AccRatio + TxSpectrum[IndexI] * RxFilterAttenuation[IndexR];
459         }
460 
461         TotalInterfmW = TotalInterfmW + AccRatio * pow(10.0, rx_powers[i]/10.0);
462 
463       }
464     }
465   } //End of Interference calc.
466 
467   { //Adding it all together
468     double DesiredPowerdBm;
469     double TotalNoisemW = ThermalNoisemW + TotalInterfmW + TotalPhaseReciprocalMixmW + TotalIntermmW;
470     double TotalSignalEtNoisemW;
471 
472     if ( desired_tx_nbr >= mo_st->nbr_devices ){
473       DesiredPowerdBm = -1000; //-1000dB == nothing
474     } else {
475       DesiredPowerdBm = rx_powers[desired_tx_nbr];
476     }
477 
478     TotalSignalEtNoisemW = TotalNoisemW + pow( 10.0, DesiredPowerdBm/10.0 );
479 
480     *OutputSNR = DesiredPowerdBm - 10.0*log10( TotalNoisemW );
481     *Output_RSSI_power_level = 10*log10(TotalSignalEtNoisemW);
482   }
483 }
484 
485 /**
486  * Return the bit error probability ([0.. RAND_PROB_1]) for a given SNR
487  *
488  * inputs:
489  *  this           : Pointer to this modem object
490  *  rx_radioparams : Radio parameters/configuration of this receiver for this Rx/RSSI measurement
491  *  SNR            : SNR level at the analog output as calculated by modem_analog_rx()
492  */
modem_digital_perf_ber(void * this,p2G4_radioparams_t * rx_radioparams,double SNR)493 uint32_t modem_digital_perf_ber(void *this, p2G4_radioparams_t *rx_radioparams, double SNR) {
494   m_simple_status_t *mo_st = (m_simple_status_t *)this;
495 
496   //Just the theoretical BER vs Eb/No | SNR:
497   // BER = Q(sqrt(Eb/No)) = 1/2*erfc(sqrt(Eb/(2*No)))
498 
499   /*SNR = SNR - NFigure;
500     N_u = 1./10.^((SNR)/10);
501     N_u_o = N_u + 10.^(NoiseFloor/10);
502     SNR_2 = 10*log10(1./N_u_o); */
503 
504   SNR = SNR - mo_st->args.NFigure_extra;
505   double N_u = 1.0/pow(10.0,SNR/10.0); //equivalent noise level level relative to the signal power
506   double N_u_o = N_u + pow(10.0, mo_st->args.NFloor_dig/10); //add the noise equivalent to the noise floor (relative to the singal power also)
507 
508   double SNR_nu = 1.0/N_u_o; //back to SNR (in natural units)
509   //SNR = 10.0*log10(1.0/N_u_o);
510 
511   double BER = Q_function(sqrt(SNR_nu)); //BER from [0..1.0]
512   //BER = Q_function(pow(10.0,SNR/20));
513 
514   return BER*RAND_PROB_1 + 0.5; //scaled to 32bits and rounded to nearest int.
515 }
516 
517 /**
518  * Return the probability of the packet sync'ing ([0.. RAND_PROB_1]) for a given SNR and
519  * transmission parameters
520  *
521  * (note that this should ONLY include excess packet error probability,
522  * as over the sync word and address normal bit errors will also be calculated)
523  *
524  * inputs:
525  *  this           : Pointer to this modem object
526  *  rx_radioparams : Radio parameters/configuration of this receiver for this Rx/RSSI measurement
527  *  SNR            : SNR level at the analog output as calculated by modem_analog_rx()
528  *  tx_s           : Parameters of the transmission we are receiving (in case the sync. probability depends on any of them)
529  */
modem_digital_perf_sync(void * this,p2G4_radioparams_t * rx_radioparams,double SNR,p2G4_txv2_t * tx_s)530 uint32_t modem_digital_perf_sync(void *this, p2G4_radioparams_t *rx_radioparams,
531                                  double SNR, p2G4_txv2_t* tx_s) {
532   m_simple_status_t *mo_st = (m_simple_status_t *)this;
533   mo_simple_args_t *args = &mo_st->args;
534 
535   return args->Sync_prob;
536 }
537 
538 /**
539  * Return the digital RSSI value the modem would have produced for this given
540  * RSSI_power_level in the digital input
541  *
542  * inputs:
543  *  this             : Pointer to this modem object
544  *  rx_radioparams   : Radio parameters/configuration of this receiver for this Rx/RSSI measurement
545  *  RSSI_power_level : Analog power level as measured by modem_analog_rx()
546  *
547  * outputs:
548  *  RSSI  : RSSI "digital" value returned by this modem, following the p2G4_rssi_power_t format (16.16 signed value)
549  */
modem_digital_RSSI(void * this,p2G4_radioparams_t * rx_radioparams,double RSSI_power_level,p2G4_rssi_power_t * RSSI)550 void modem_digital_RSSI(void *this, p2G4_radioparams_t *rx_radioparams,
551                         double RSSI_power_level, p2G4_rssi_power_t* RSSI) {
552 
553   m_simple_status_t *mo_st = (m_simple_status_t *)this;
554 
555   RSSI_power_level += mo_st->device_RSSI_offsetdB; //average measurement offset of this device relative to a perfect device
556   RSSI_power_level += bs_random_Gaus() * mo_st->args.RSSI_meas_noisedB_std; //measurement noise
557 
558   *RSSI = p2G4_RSSI_value_from_dBm(RSSI_power_level);
559 }
560 
561 /**
562  * Clean up: Free the memory the modem may have allocated
563  * close any file descriptors etc.
564  * (the simulation has ended)
565  */
modem_delete(void * this)566 void modem_delete(void *this) {
567   if (this != NULL) {
568     free(this);
569   }
570 }
571