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_BLE_CODED:
242     case P2G4_MOD_154_250K_DSS: //Provisionally let's treat 15.4 like 1Mbps BLE
243       return 1.1e6;
244       break;
245     case P2G4_MOD_BLE2M:
246     case P2G4_MOD_PROP2M:
247       return 2.5e6;
248       break;
249     default:
250       bs_trace_error_line("modem BLE Simple does not support receiving "
251                           "configured with this modulation type (%i)\n",
252                           modulation_type);
253       break;
254   }
255   return 0;
256 }
257 
RxFilter_from_modulation(uint modulation_type,const double ** filter_attenuation,uint * filter_half_BW)258 static void RxFilter_from_modulation(uint modulation_type, const double ** filter_attenuation,
259                                      uint *filter_half_BW) {
260 
261   switch (modulation_type) {
262     case P2G4_MOD_BLE:
263     case P2G4_MOD_BLE_CODED:
264     case P2G4_MOD_154_250K_DSS: //Provisionally let's treat 15.4 like 1Mbps BLE
265       *filter_attenuation = channel_filter_BLE;
266       *filter_half_BW     = channel_filter_BW_BLE;
267       break;
268     case P2G4_MOD_BLE2M:
269     case P2G4_MOD_PROP2M:
270       *filter_attenuation = channel_filter_Prop2;
271       *filter_half_BW     = channel_filter_BW_Prop2;
272       break;
273     default:
274       bs_trace_error_line("modem BLE Simple does not support receiving "
275                           "configured with this modulation type (%i)\n",
276                           modulation_type);
277       break;
278   }
279 }
280 
spectrum_from_modulation(uint modulation_type,const double ** tx_spectrum,uint * tx_spec_halfBW)281 static void spectrum_from_modulation(uint modulation_type, const double **tx_spectrum,
282                                      uint *tx_spec_halfBW) {
283 
284   switch (modulation_type) {
285     case P2G4_MOD_BLE :
286     case P2G4_MOD_BLE_CODED:
287     case P2G4_MOD_154_250K_DSS: //Provisionally let's treat 15.4 like 1Mbps BLE
288       *tx_spectrum    = TxSpectrum_BLE;
289       *tx_spec_halfBW = TxSpecBW_BLE;
290       break;
291     case P2G4_MOD_BLE2M:
292     case P2G4_MOD_PROP2M:
293       *tx_spectrum    = TxSpectrum_Prop2;
294       *tx_spec_halfBW = TxSpecBW_Prop2;
295       break;
296     case P2G4_MOD_PROP4M :
297       *tx_spectrum    = TxSpectrum_WN4MHz;
298       *tx_spec_halfBW = TxSpecBW_WN4MHz;
299       break;
300     case P2G4_MOD_CWINTER :
301       *tx_spectrum    = TxSpectrum_CW;
302       *tx_spec_halfBW = TxSpecBW_CW;
303       break;
304     case P2G4_MOD_WHITENOISE1MHz :
305       *tx_spectrum    = TxSpectrum_WN1MHz;
306       *tx_spec_halfBW = TxSpecBW_WN1MHz;
307       break;
308     case P2G4_MOD_WHITENOISE2MHz :
309       *tx_spectrum    = TxSpectrum_WN2MHz;
310       *tx_spec_halfBW = TxSpecBW_WN2MHz;
311       break;
312     case P2G4_MOD_WHITENOISE4MHz :
313       *tx_spectrum    = TxSpectrum_WN4MHz;
314       *tx_spec_halfBW = TxSpecBW_WN4MHz;
315       break;
316     case P2G4_MOD_WHITENOISE8MHz :
317       *tx_spectrum    = TxSpectrum_WN8MHz;
318       *tx_spec_halfBW = TxSpecBW_WN8MHz;
319       break;
320     case P2G4_MOD_WHITENOISE16MHz :
321       *tx_spectrum    = TxSpectrum_WN16MHz;
322       *tx_spec_halfBW = TxSpecBW_WN16MHz;
323       break;
324     case P2G4_MOD_WHITENOISE20MHz :
325       *tx_spectrum    = TxSpectrum_WN20MHz;
326       *tx_spec_halfBW = TxSpecBW_WN20MHz;
327       break;
328     case P2G4_MOD_WHITENOISE40MHz :
329       *tx_spectrum    = TxSpectrum_WN40MHz;
330       *tx_spec_halfBW = TxSpecBW_WN40MHz;
331       break;
332     case P2G4_MOD_WHITENOISE80MHz :
333       *tx_spectrum    = TxSpectrum_WN80MHz;
334       *tx_spec_halfBW = TxSpecBW_WN80MHz;
335       break;
336     case P2G4_MOD_WLANINTER :
337       *tx_spectrum    = TxSpectrum_WLAN;
338       *tx_spec_halfBW = TxSpecBW_WLAN;
339       break;
340     default:
341       bs_trace_warning_line("modem BLE Simple does not support seeing this "
342                             "modulation type (%i) in the air, it will be "
343                             "treated as 1MHz white noise\n",modulation_type);
344       *tx_spectrum    = TxSpectrum_WN1MHz;
345       *tx_spec_halfBW = TxSpecBW_WN1MHz;
346       break;
347   }
348 }
349 
350 /**
351  * Q function:
352  *   Q(x) = P(X > x) , where X = N(0,1)
353  *   That is, Q(x) is the probability of a N(0,1) having a value > x
354  *   where N(0,1) is a Normal distribution with average 0, and standard deviation 1
355  */
Q_function(double x)356 static double Q_function(double x) {
357   return 1.0/2.0*erfc(x/sqrt(2.0));
358 }
359 
360 /************
361  * Modem IF *
362  ************/
363 
364 /**
365  * Initialize the modem internal status
366  *
367  * The input parameters are:
368  *   dev_nbr      : the device number this modem library corresponds to
369  *                  (note that this library may be reused in between several devices)
370  *   nbr_devices  : the total number of devices in the simulation (gives the length of vectors later)
371  *   char *argv[] : a set of arguments passed to the modem library (same convention as POSIX main() command line arguments)
372  *   int argc     : the number of arguments passed to the modem library
373  *
374  * It is up to the modem to define which arguments it can or shall receive to configure it
375  * The only argument all modems shall understand is :
376  *    [-h] [--h] [--help] [-?]  The modem shall print a list of arguments it supports with a descriptive message for each
377  *
378  * This function shall return a pointer to this modems status structure
379  * This same pointer will be passed back to consecutive function calls of the library (void *this)
380  *
381  * If the library does not require to keep any status it can just return NULL
382  */
modem_init(int argc,char * argv[],uint d,uint n_devs)383 void* modem_init(int argc, char *argv[], uint d, uint n_devs) {
384   m_simple_status_t* mo_st;
385 
386   mo_st = (m_simple_status_t *)bs_calloc(1,sizeof(m_simple_status_t));
387 
388   mo_st->nbr_devices = n_devs;
389 
390   modem_simple_argparse(argc, argv, d, &mo_st->args);
391 
392   mo_st->device_RSSI_offsetdB = bs_random_Gaus()*mo_st->args.RSSI_offsetdB_std;
393 
394   return (void*)mo_st;
395 }
396 
397 /**
398  * Calculate the SNR of the desired input signal at the digital modem input/analog output
399  * including all modem analog impairments
400  *
401  * inputs:
402  *  this               : Pointer to this modem object
403  *  rx_radioparams     : Radio parameters/configuration of this receiver for this Rx/RSSI measurement
404  *  rx_powers          : For each possible transmitter ([0..n_devices-1]) what is their power level at this device antenna connector in dBm
405  *  txl_c              : For each possible transmitter what are their Tx parameters
406  *  desired_tx_nbr     : which of the transmitters is the one we are trying to receive
407  *
408  * outputs:
409  *  OutputSNR               : SNR in the analog output / digital input of this modem (dB)
410  *  Output_RSSI_power_level : RSSI level (analog, dBm) sent to the modem digital
411  */
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)412 void modem_analog_rx(void *this, p2G4_radioparams_t *rx_radioparams, double *OutputSNR,
413                      double *Output_RSSI_power_level, double *rx_powers, tx_l_c_t *txl_c,
414                      uint desired_tx_nbr) {
415   m_simple_status_t *mo_st = (m_simple_status_t *)this;
416   uint i;
417 
418   double ThermalNoisemW = 0;
419   double TotalInterfmW  = 0;
420   double TotalPhaseReciprocalMixmW = 0; //If we were more precise, we would also calculate here the phase noise mixing
421   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
422 
423   { //Thermal noise calculation
424     double NoiseFigure = mo_st->args.NFigure_ana; //dB
425     double EquivalentBW = noiseBW_from_modulation(rx_radioparams->modulation);
426     ThermalNoisemW = EquivalentBW * pow(10, (-174.0 + NoiseFigure )/10);
427   }
428 
429   { //Interference calculation (including adjacent channel)
430     const double *RxFilterAttenuation;
431     uint RxFilterHalfBW;
432 
433     RxFilter_from_modulation(rx_radioparams->modulation, &RxFilterAttenuation, &RxFilterHalfBW);
434     //The "Rx filter" shall include all effects which would increase
435     //the noise/interference power at a given frequency offset
436 
437     int CenterR = p2G4_freq_to_d(rx_radioparams->center_freq) / (FreqRes/1e6); //Center frequency (where 0 = 2400MHz)
438     int StartR  = CenterR - RxFilterHalfBW;
439     int EndR    = CenterR + RxFilterHalfBW;
440 
441     for ( i = 0; i < mo_st->nbr_devices ; i++ ) {
442       if ( txl_c->used[i] && ( i != desired_tx_nbr ) ){ //For each active transmitter
443         //Calculate how much power comes thru the Rx channel/IF filtering
444 
445         const double *TxSpectrum;
446         uint TxSpecHalfBW;
447 
448         spectrum_from_modulation(txl_c->tx_list[i].tx_s.radio_params.modulation, &TxSpectrum, &TxSpecHalfBW);
449 
450         int CenterI = p2G4_freq_to_d(txl_c->tx_list[i].tx_s.radio_params.center_freq) / (FreqRes/1e6); //Center frequency (where 0 = 2400MHz)
451         int StartI  = CenterI - TxSpecHalfBW;
452         int EndI    = CenterI + TxSpecHalfBW;
453 
454         int StartOverlap = BS_MAX(StartR,StartI);
455         int EndOverlap   = BS_MIN(EndR, EndI);
456 
457         double AccRatio = 0; //Calculate the overlap of the Rx filter with the tx modulation shape
458         for (int Freq = StartOverlap; Freq <= EndOverlap ; Freq++) {
459            int IndexR = (Freq - StartR);
460            int IndexI = (Freq - StartI);
461            AccRatio = AccRatio + TxSpectrum[IndexI] * RxFilterAttenuation[IndexR];
462         }
463 
464         TotalInterfmW = TotalInterfmW + AccRatio * pow(10.0, rx_powers[i]/10.0);
465 
466       }
467     }
468   } //End of Interference calc.
469 
470   { //Adding it all together
471     double DesiredPowerdBm;
472     double TotalNoisemW = ThermalNoisemW + TotalInterfmW + TotalPhaseReciprocalMixmW + TotalIntermmW;
473     double TotalSignalEtNoisemW;
474 
475     if ( desired_tx_nbr >= mo_st->nbr_devices ){
476       DesiredPowerdBm = -1000; //-1000dB == nothing
477     } else {
478       DesiredPowerdBm = rx_powers[desired_tx_nbr];
479     }
480 
481     TotalSignalEtNoisemW = TotalNoisemW + pow( 10.0, DesiredPowerdBm/10.0 );
482 
483     *OutputSNR = DesiredPowerdBm - 10.0*log10( TotalNoisemW );
484     *Output_RSSI_power_level = 10*log10(TotalSignalEtNoisemW);
485   }
486 }
487 
488 /**
489  * Return the bit error probability ([0.. RAND_PROB_1]) for a given SNR
490  *
491  * inputs:
492  *  this           : Pointer to this modem object
493  *  rx_radioparams : Radio parameters/configuration of this receiver for this Rx/RSSI measurement
494  *  SNR            : SNR level at the analog output as calculated by modem_analog_rx()
495  */
modem_digital_perf_ber(void * this,p2G4_modemdigparams_t * rx_modem_params,double SNR)496 uint32_t modem_digital_perf_ber(void *this, p2G4_modemdigparams_t *rx_modem_params, double SNR) {
497   m_simple_status_t *mo_st = (m_simple_status_t *)this;
498 
499   double coding_gain = 0;
500 
501   if (rx_modem_params->modulation == P2G4_MOD_BLE_CODED) {
502     //By now let's just offset the curve by 4 and 9dB respectively
503     //It is not too accurate, but much better than nothing
504     if (rx_modem_params->coding_rate == 2) { //S=2
505       coding_gain = 4;
506     } else { //S=8
507       coding_gain = 9;
508     }
509   }
510 
511   //Just the theoretical BER vs Eb/No | SNR
512   // BER = Q(sqrt(Eb/No)) = 1/2*erfc(sqrt(Eb/(2*No)))
513 
514   /*SNR = SNR - NFigure;
515     N_u = 1./10.^((SNR)/10);
516     N_u_o = N_u + 10.^(NoiseFloor/10);
517     SNR_2 = 10*log10(1./N_u_o); */
518 
519   SNR = SNR - mo_st->args.NFigure_extra + coding_gain;
520   double N_u = 1.0/pow(10.0,SNR/10.0); //equivalent noise level level relative to the signal power
521   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)
522 
523   double SNR_nu = 1.0/N_u_o; //back to SNR (in natural units)
524   //SNR = 10.0*log10(1.0/N_u_o);
525 
526   double BER = Q_function(sqrt(SNR_nu)); //BER from [0..1.0]
527   //BER = Q_function(pow(10.0,SNR/20));
528 
529   return BER*RAND_PROB_1 + 0.5; //scaled to 32bits and rounded to nearest int.
530 }
531 
532 /**
533  * Return the probability of the packet sync'ing ([0.. RAND_PROB_1]) for a given SNR and
534  * transmission parameters
535  *
536  * (note that this should ONLY include excess packet error probability,
537  * as over the sync word and address normal bit errors will also be calculated)
538  *
539  * inputs:
540  *  this           : Pointer to this modem object
541  *  rx_radioparams : Radio parameters/configuration of this receiver for this Rx/RSSI measurement
542  *  SNR            : SNR level at the analog output as calculated by modem_analog_rx()
543  *  tx_s           : Parameters of the transmission we are receiving (in case the sync. probability depends on any of them)
544  */
modem_digital_perf_sync(void * this,p2G4_modemdigparams_t * rx_modem_params,double SNR,p2G4_txv2_t * tx_s)545 uint32_t modem_digital_perf_sync(void *this, p2G4_modemdigparams_t *rx_modem_params,
546                                  double SNR, p2G4_txv2_t* tx_s) {
547   m_simple_status_t *mo_st = (m_simple_status_t *)this;
548   mo_simple_args_t *args = &mo_st->args;
549 
550   return args->Sync_prob;
551 }
552 
553 /**
554  * Return the digital RSSI value the modem would have produced for this given
555  * RSSI_power_level in the digital input
556  *
557  * inputs:
558  *  this             : Pointer to this modem object
559  *  rx_radioparams   : Radio parameters/configuration of this receiver for this Rx/RSSI measurement
560  *  RSSI_power_level : Analog power level as measured by modem_analog_rx()
561  *
562  * outputs:
563  *  RSSI  : RSSI "digital" value returned by this modem, following the p2G4_rssi_power_t format (16.16 signed value)
564  */
modem_digital_RSSI(void * this,p2G4_radioparams_t * rx_radioparams,double RSSI_power_level,p2G4_rssi_power_t * RSSI)565 void modem_digital_RSSI(void *this, p2G4_radioparams_t *rx_radioparams,
566                         double RSSI_power_level, p2G4_rssi_power_t* RSSI) {
567 
568   m_simple_status_t *mo_st = (m_simple_status_t *)this;
569 
570   RSSI_power_level += mo_st->device_RSSI_offsetdB; //average measurement offset of this device relative to a perfect device
571   RSSI_power_level += bs_random_Gaus() * mo_st->args.RSSI_meas_noisedB_std; //measurement noise
572 
573   *RSSI = p2G4_RSSI_value_from_dBm(RSSI_power_level);
574 }
575 
576 /**
577  * Clean up: Free the memory the modem may have allocated
578  * close any file descriptors etc.
579  * (the simulation has ended)
580  */
modem_delete(void * this)581 void modem_delete(void *this) {
582   if (this != NULL) {
583     free(this);
584   }
585 }
586