1#!/usr/bin/env python3
2#
3#   Copyright 2016 - Google
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 time
18import math
19from acts.test_utils.tel.tel_defines import ATTEN_MAX_VALUE
20from acts.test_utils.tel.tel_defines import ATTEN_MIN_VALUE
21from acts.test_utils.tel.tel_defines import MAX_RSSI_RESERVED_VALUE
22from acts.test_utils.tel.tel_defines import MIN_RSSI_RESERVED_VALUE
23
24
25def get_atten(log, atten_obj):
26    """Get attenuator current attenuation value.
27
28    Args:
29        log: log object.
30        atten_obj: attenuator object.
31    Returns:
32        Current attenuation value.
33    """
34    return atten_obj.get_atten()
35
36
37def set_atten(log, atten_obj, target_atten, step_size=0, time_per_step=0):
38    """Set attenuator attenuation value.
39
40    Args:
41        log: log object.
42        atten_obj: attenuator object.
43        target_atten: target attenuation value.
44        step_size: step size (in unit of dBm) for 'attenuation value setting'.
45            This is optional. Default value is 0. If step_size is 0, it means
46            the setting will be done in only one step.
47        time_per_step: delay time (in unit of second) per step when setting
48            the attenuation value.
49            This is optional. Default value is 0.
50    Returns:
51        True is no error happened. Otherwise false.
52    """
53    try:
54        print_name = atten_obj.path
55    except AttributeError:
56        print_name = str(atten_obj)
57
58    current_atten = get_atten(log, atten_obj)
59    info = "set_atten {} from {} to {}".format(print_name, current_atten,
60                                               target_atten)
61    if step_size > 0:
62        info += ", step size {}, time per step {}s.".format(step_size,
63                                                            time_per_step)
64    log.info(info)
65    try:
66        delta = target_atten - current_atten
67        if step_size > 0:
68            number_of_steps = int(abs(delta) / step_size)
69            while number_of_steps > 0:
70                number_of_steps -= 1
71                current_atten += math.copysign(step_size,
72                                               (target_atten - current_atten))
73                atten_obj.set_atten(current_atten)
74                time.sleep(time_per_step)
75        atten_obj.set_atten(target_atten)
76    except Exception as e:
77        log.error("set_atten error happened: {}".format(e))
78        return False
79    return True
80
81
82def set_rssi(log,
83             atten_obj,
84             calibration_rssi,
85             target_rssi,
86             step_size=0,
87             time_per_step=0):
88    """Set RSSI value by changing attenuation.
89
90    Args:
91        log: log object.
92        atten_obj: attenuator object.
93        calibration_rssi: RSSI calibration information.
94        target_rssi: target RSSI value.
95        step_size: step size (in unit of dBm) for 'RSSI value setting'.
96            This is optional. Default value is 0. If step_size is 0, it means
97            the setting will be done in only one step.
98        time_per_step: delay time (in unit of second) per step when setting
99            the attenuation value.
100            This is optional. Default value is 0.
101    Returns:
102        True is no error happened. Otherwise false.
103    """
104    try:
105        print_name = atten_obj.path
106    except AttributeError:
107        print_name = str(atten_obj)
108
109    if target_rssi == MAX_RSSI_RESERVED_VALUE:
110        target_atten = ATTEN_MIN_VALUE
111    elif target_rssi == MIN_RSSI_RESERVED_VALUE:
112        target_atten = ATTEN_MAX_VALUE
113    else:
114        log.info("set_rssi {} to {}.".format(print_name, target_rssi))
115        target_atten = calibration_rssi - target_rssi
116
117    if target_atten < 0:
118        log.info("set_rssi: WARNING - you are setting an unreachable RSSI.")
119        log.info(
120            "max RSSI value on {} is {}. Setting attenuation to 0.".format(
121                print_name, calibration_rssi))
122        target_atten = 0
123    if not set_atten(log, atten_obj, target_atten, step_size, time_per_step):
124        log.error("set_rssi to {}failed".format(target_rssi))
125        return False
126    return True
127