1#!/usr/bin/env python3
2#
3#   Copyright 2018 - The Android Open Source Project
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
17import ntpath
18
19import time
20from acts.controllers.anritsu_lib.band_constants import GSM_BAND_DCS1800
21from acts.controllers.anritsu_lib.band_constants import GSM_BAND_EGSM900
22from acts.controllers.anritsu_lib.band_constants import GSM_BAND_GSM850
23from acts.controllers.anritsu_lib.band_constants import GSM_BAND_RGSM900
24from acts.controllers.anritsu_lib.md8475a import BtsGprsMode
25from acts.controllers.anritsu_lib.md8475a import BtsNumber
26from acts.controllers.anritsu_lib import md8475_cellular_simulator as anritsusim
27from acts.controllers.cellular_lib import BaseCellularDut
28from acts.controllers.cellular_lib.BaseSimulation import BaseSimulation
29from acts.controllers.cellular_lib.BaseCellConfig import BaseCellConfig
30
31
32class GsmSimulation(BaseSimulation):
33    """ Single base station GSM. """
34
35    # Simulation config files in the callbox computer.
36    # These should be replaced in the future by setting up
37    # the same configuration manually.
38
39    GSM_BASIC_SIM_FILE = 'SIM_default_GSM.wnssp'
40
41    GSM_CELL_FILE = 'CELL_GSM_config.wnscp'
42
43    # Configuration dictionary keys
44    PARAM_BAND = "band"
45    PARAM_GPRS = "gprs"
46    PARAM_EGPRS = "edge"
47    PARAM_NO_GPRS = "nogprs"
48    PARAM_SLOTS = "slots"
49
50    bands_parameter_mapping = {
51        '850': GSM_BAND_GSM850,
52        '900': GSM_BAND_EGSM900,
53        '1800': GSM_BAND_DCS1800,
54        '1900': GSM_BAND_RGSM900
55    }
56
57    def __init__(self, simulator, log, dut, test_config, calibration_table):
58        """ Initializes the simulator for a single-carrier GSM simulation.
59
60        Loads a simple LTE simulation environment with 1 basestation. It also
61        creates the BTS handle so we can change the parameters as desired.
62
63        Args:
64            simulator: a cellular simulator controller
65            log: a logger handle
66            dut: a device handler implementing BaseCellularDut
67            test_config: test configuration obtained from the config file
68            calibration_table: a dictionary containing path losses for
69                different bands.
70
71        """
72        # The GSM simulation relies on the cellular simulator to be a MD8475
73        if not isinstance(self.simulator, anritsusim.MD8475CellularSimulator):
74            raise ValueError('The GSM simulation relies on the simulator to '
75                             'be an Anritsu MD8475 A/B instrument.')
76
77        # The Anritsu controller needs to be unwrapped before calling
78        # super().__init__ because setup_simulator() requires self.anritsu and
79        # will be called during the parent class initialization.
80        self.anritsu = self.simulator.anritsu
81        self.bts1 = self.anritsu.get_BTS(BtsNumber.BTS1)
82
83        super().__init__(simulator, log, dut, test_config, calibration_table)
84
85        self.dut.set_preferred_network_type(
86            BaseCellularDut.PreferredNetworkType.GSM_ONLY)
87
88    def setup_simulator(self):
89        """ Do initial configuration in the simulator. """
90
91        # Load callbox config files
92        callbox_config_path = self.CALLBOX_PATH_FORMAT_STR.format(
93            self.anritsu._md8475_version)
94
95        self.anritsu.load_simulation_paramfile(
96            ntpath.join(callbox_config_path, self.GSM_BASIC_SIM_FILE))
97        self.anritsu.load_cell_paramfile(
98            ntpath.join(callbox_config_path, self.GSM_CELL_FILE))
99
100        # Start simulation if it wasn't started
101        self.anritsu.start_simulation()
102
103    def configure(self, parameters):
104        """ Configures simulation using a dictionary of parameters.
105
106        Processes GSM configuration parameters.
107
108        Args:
109            parameters: a configuration dictionary
110        """
111        # Don't call super() because Gsm doesn't control Tx power.
112
113        # Setup band
114        if self.PARAM_BAND not in parameters:
115            raise ValueError(
116                "The configuration dictionary must include key '{}' with the "
117                "required band number.".format(self.PARAM_BAND))
118
119        self.set_band(self.bts1, parameters[self.PARAM_BAND])
120        self.load_pathloss_if_required()
121
122        # Setup GPRS mode
123
124        if self.PARAM_GPRS in parameters:
125            self.bts1.gsm_gprs_mode = BtsGprsMode.GPRS
126        elif self.PARAM_EGPRS in parameters:
127            self.bts1.gsm_gprs_mode = BtsGprsMode.EGPRS
128        elif self.PARAM_NO_GPRS in parameters:
129            self.bts1.gsm_gprs_mode = BtsGprsMode.NO_GPRS
130        else:
131            raise ValueError(
132                "GPRS mode needs to be indicated in the config dictionary by "
133                "including either {}, {} or {} as a key.".format(
134                    self.PARAM_GPRS, self.PARAM_EGPRS, self.PARAM_NO_GPRS))
135
136        # Setup slot allocation
137        if self.PARAM_SLOTS not in parameters or len(
138                parameters[self.PARAM_SLOTS]) != 2:
139            raise ValueError(
140                "The config dictionary must include key {} with a list of two "
141                "int values indicating DL and UL slots.".format(
142                    self.PARAM_SLOTS))
143        values = parameters[self.PARAM_SLOTS]
144        self.bts1.gsm_slots = (int(values[0]), int(values[1]))
145
146    def set_band(self, bts, band):
147        """ Sets the band used for communication.
148
149        Args:
150            bts: basestation handle
151            band: desired band
152        """
153
154        bts.band = band
155        time.sleep(5)  # It takes some time to propagate the new band
156