attenuation-control: Add scripts to control the attenuation
Xmlrpc client/server application to control the digital attenuators installed in the lava testbed. Implements AR_VUL-64. Signed-off-by: Thomas Klaehn <thomas.klaehn@u-blox.com>
This commit is contained in:
parent
3757cb3efd
commit
b1e66c2af1
4
.gitignore
vendored
4
.gitignore
vendored
@ -1 +1,5 @@
|
|||||||
.vscode/
|
.vscode/
|
||||||
|
.coverage
|
||||||
|
coverage.xml
|
||||||
|
__pycache__/
|
||||||
|
build/
|
||||||
|
4
attenuation-control-client
Normal file
4
attenuation-control-client
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
python3 -m attenuation_control_client $@
|
||||||
|
|
10
attenuation-control.service
Normal file
10
attenuation-control.service
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Attenuation control service.
|
||||||
|
After=multi-user.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=idle
|
||||||
|
ExecStart=/usr/bin/python3 -m attenuation_control_srv 192.168.1.16:8231
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
22
mock/IOPi/__init__.py
Normal file
22
mock/IOPi/__init__.py
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
class IOPi(object):
|
||||||
|
address = None
|
||||||
|
used_pins = [0 for i in range(17)]
|
||||||
|
pin_directions = [0 for i in range(17)]
|
||||||
|
pin_values = [0 for i in range(17)]
|
||||||
|
|
||||||
|
def __init__(self, address):
|
||||||
|
self.address = address
|
||||||
|
|
||||||
|
def set_pin_direction(self, pin, direction):
|
||||||
|
self.used_pins[pin] = 1
|
||||||
|
self.pin_directions[pin] = direction
|
||||||
|
|
||||||
|
def write_pin(self, pin, value):
|
||||||
|
self.used_pins[pin] = 1
|
||||||
|
self.pin_values[pin] = value
|
||||||
|
|
||||||
|
def read_pin(self, pin):
|
||||||
|
if self.used_pins[pin] == 1:
|
||||||
|
return self.pin_values[pin]
|
||||||
|
else:
|
||||||
|
return None
|
0
mock/__init__.py
Normal file
0
mock/__init__.py
Normal file
35
setup.py
Executable file
35
setup.py
Executable file
@ -0,0 +1,35 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
'''
|
||||||
|
@author: Thomas Klaehn <thomas.klaehn@u-blox.com>
|
||||||
|
'''
|
||||||
|
from distutils.core import setup
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import stat
|
||||||
|
import sys
|
||||||
|
|
||||||
|
NAME = 'attenuation-control'
|
||||||
|
VERSION = '1.0.0'
|
||||||
|
AUTHOR = 'Thomas Klaehn'
|
||||||
|
EMAIL = 'thomas.klaehn@u-blox.com'
|
||||||
|
SYSTEMD_SCRIPTS = ['attenuation-control.service']
|
||||||
|
EXEC_SCRIPTS = ['attenuation-control-client']
|
||||||
|
PACKAGES = ['attenuator', 'attenuation_control_srv', 'attenuation_control_client']
|
||||||
|
PACKAGE_DIRS = {
|
||||||
|
'attenuator':'source/attenuator',
|
||||||
|
'attenuation_control_srv':'source/attenuation_control_srv',
|
||||||
|
'attenuation_control_client':'source/attenuation_control_client'
|
||||||
|
}
|
||||||
|
|
||||||
|
SYSTEMD_PATH = '/lib/systemd/system/'
|
||||||
|
SRC_FILE = 'attenuation-control.service'
|
||||||
|
DST_FILE = SYSTEMD_PATH + SRC_FILE
|
||||||
|
|
||||||
|
if sys.argv[1] == 'install':
|
||||||
|
shutil.copyfile(SRC_FILE, DST_FILE)
|
||||||
|
os.chmod(DST_FILE, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH)
|
||||||
|
setup(name=NAME, version=VERSION, author=AUTHOR, author_email=EMAIL, package_dir=PACKAGE_DIRS, packages=PACKAGES,
|
||||||
|
scripts=EXEC_SCRIPTS)
|
||||||
|
elif sys.argv[1] == 'sdist':
|
||||||
|
setup(name=NAME, version=VERSION, author=AUTHOR, author_email=EMAIL, package_dir=PACKAGE_DIRS, packages=PACKAGES,
|
||||||
|
scripts=SYSTEMD_SCRIPTS)
|
0
source/__init__.py
Normal file
0
source/__init__.py
Normal file
0
source/attenuation_control_client/__init__.py
Normal file
0
source/attenuation_control_client/__init__.py
Normal file
65
source/attenuation_control_client/__main__.py
Normal file
65
source/attenuation_control_client/__main__.py
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import logging
|
||||||
|
import sys
|
||||||
|
from xmlrpc.client import ServerProxy
|
||||||
|
|
||||||
|
DEFAULT_PORT = "8231"
|
||||||
|
|
||||||
|
logging.basicConfig(level=logging.INFO, format='%(levelname)s %(message)s')
|
||||||
|
LOG = logging.getLogger("att_ctrl_client")
|
||||||
|
|
||||||
|
def parse_args():
|
||||||
|
"""Command line argument parser"""
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument("host", help="Hostname or ip address the server is \
|
||||||
|
serving on. (e.g. 'attctrl:8231 or 192.168.1.16'")
|
||||||
|
parser.add_argument('attenuator', help="Attenuator to be set [0..7]")
|
||||||
|
parser.add_argument('attenuation', help="Attenuation to be set [0.0 .. 31.5]")
|
||||||
|
|
||||||
|
return parser.parse_args()
|
||||||
|
|
||||||
|
def host_port(data):
|
||||||
|
'''Determine hostname/address and port.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
data (str): Hostname/address with optional port (e.g. 'localhost:1234'
|
||||||
|
or '192.168.0.1').
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: Hostname/address
|
||||||
|
str: Port
|
||||||
|
'''
|
||||||
|
tmp = data.split(":")
|
||||||
|
port = DEFAULT_PORT
|
||||||
|
host = tmp[0]
|
||||||
|
|
||||||
|
if len(tmp) > 1:
|
||||||
|
port = tmp[1]
|
||||||
|
return host, port
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
args = parse_args()
|
||||||
|
host, port = host_port(args.host)
|
||||||
|
client = ServerProxy('http://{}:{}'.format(host, port))
|
||||||
|
|
||||||
|
try:
|
||||||
|
dev = int(args.attenuator)
|
||||||
|
except ValueError:
|
||||||
|
LOG.error("attenuator needs to be convertible into int.")
|
||||||
|
return 1
|
||||||
|
try:
|
||||||
|
val = float(args.attenuation)
|
||||||
|
except ValueError:
|
||||||
|
LOG.error("attenuation needs to be convertible into float.")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
ret = client.set_attenuation(dev, val)
|
||||||
|
|
||||||
|
LOG.info("xmlrpcclient: set_attenuation result: {}.".format(ret))
|
||||||
|
return ret
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(main())
|
0
source/attenuation_control_srv/__init__.py
Normal file
0
source/attenuation_control_srv/__init__.py
Normal file
145
source/attenuation_control_srv/__main__.py
Normal file
145
source/attenuation_control_srv/__main__.py
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import logging
|
||||||
|
import sys
|
||||||
|
from xmlrpc.server import SimpleXMLRPCServer
|
||||||
|
import attenuator
|
||||||
|
|
||||||
|
DEFAULT_PORT = "8231"
|
||||||
|
|
||||||
|
logging.basicConfig(level=logging.INFO, format='%(levelname)s %(message)s')
|
||||||
|
LOG = logging.getLogger("att_ctrl_srv")
|
||||||
|
|
||||||
|
# Array of attenuator devices and their i2c bus and gpio pin numbers.
|
||||||
|
attenuators = [
|
||||||
|
attenuator.Attenuator(
|
||||||
|
attenuator.Pin(0x20, 1),
|
||||||
|
attenuator.Pin(0x20, 2),
|
||||||
|
attenuator.Pin(0x20, 3),
|
||||||
|
attenuator.Pin(0x20, 4),
|
||||||
|
attenuator.Pin(0x20, 5),
|
||||||
|
attenuator.Pin(0x20, 6)
|
||||||
|
),
|
||||||
|
attenuator.Attenuator(
|
||||||
|
attenuator.Pin(0x20, 7),
|
||||||
|
attenuator.Pin(0x20, 8),
|
||||||
|
attenuator.Pin(0x20, 9),
|
||||||
|
attenuator.Pin(0x20, 10),
|
||||||
|
attenuator.Pin(0x20, 11),
|
||||||
|
attenuator.Pin(0x20, 12)
|
||||||
|
),
|
||||||
|
attenuator.Attenuator(
|
||||||
|
attenuator.Pin(0x20, 13),
|
||||||
|
attenuator.Pin(0x20, 14),
|
||||||
|
attenuator.Pin(0x20, 15),
|
||||||
|
attenuator.Pin(0x20, 16),
|
||||||
|
attenuator.Pin(0x21, 1),
|
||||||
|
attenuator.Pin(0x21, 2)
|
||||||
|
),
|
||||||
|
attenuator.Attenuator(
|
||||||
|
attenuator.Pin(0x21, 3),
|
||||||
|
attenuator.Pin(0x21, 4),
|
||||||
|
attenuator.Pin(0x21, 5),
|
||||||
|
attenuator.Pin(0x21, 6),
|
||||||
|
attenuator.Pin(0x21, 7),
|
||||||
|
attenuator.Pin(0x21, 8)
|
||||||
|
),
|
||||||
|
attenuator.Attenuator(
|
||||||
|
attenuator.Pin(0x21, 9),
|
||||||
|
attenuator.Pin(0x21, 10),
|
||||||
|
attenuator.Pin(0x21, 11),
|
||||||
|
attenuator.Pin(0x21, 12),
|
||||||
|
attenuator.Pin(0x21, 13),
|
||||||
|
attenuator.Pin(0x21, 14)
|
||||||
|
),
|
||||||
|
attenuator.Attenuator(
|
||||||
|
attenuator.Pin(0x21, 15),
|
||||||
|
attenuator.Pin(0x21, 16),
|
||||||
|
attenuator.Pin(0x22, 1),
|
||||||
|
attenuator.Pin(0x22, 2),
|
||||||
|
attenuator.Pin(0x22, 3),
|
||||||
|
attenuator.Pin(0x22, 4)
|
||||||
|
),
|
||||||
|
attenuator.Attenuator(
|
||||||
|
attenuator.Pin(0x22, 5),
|
||||||
|
attenuator.Pin(0x22, 6),
|
||||||
|
attenuator.Pin(0x22, 7),
|
||||||
|
attenuator.Pin(0x22, 8),
|
||||||
|
attenuator.Pin(0x22, 9),
|
||||||
|
attenuator.Pin(0x22, 10)
|
||||||
|
),
|
||||||
|
attenuator.Attenuator(
|
||||||
|
attenuator.Pin(0x22, 11),
|
||||||
|
attenuator.Pin(0x22, 12),
|
||||||
|
attenuator.Pin(0x22, 13),
|
||||||
|
attenuator.Pin(0x22, 14),
|
||||||
|
attenuator.Pin(0x22, 15),
|
||||||
|
attenuator.Pin(0x22, 16)
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
def parse_args():
|
||||||
|
"""Command line argument parser"""
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument("host", help="Hostname or ip address the server is \
|
||||||
|
serving on. (e.g. 'attctrl:8231 or 192.168.1.16'")
|
||||||
|
|
||||||
|
return parser.parse_args()
|
||||||
|
|
||||||
|
def host_port(data):
|
||||||
|
'''Determine hostname/address and port.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
data (str): Hostname/address with optional port (e.g. 'localhost:1234'
|
||||||
|
or '192.168.0.1').
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: Hostname/address
|
||||||
|
str: Port
|
||||||
|
'''
|
||||||
|
tmp = data.split(":")
|
||||||
|
port = DEFAULT_PORT
|
||||||
|
host = tmp[0]
|
||||||
|
|
||||||
|
if len(tmp) > 1:
|
||||||
|
port = tmp[1]
|
||||||
|
return host, port
|
||||||
|
|
||||||
|
def set_attenuation(attenuator, attenuation):
|
||||||
|
"""Set the attenuation of the choosen attenuator
|
||||||
|
|
||||||
|
Args:
|
||||||
|
attenuator (int): Index of the attenuator device [0..8]
|
||||||
|
attenuation (float): Value of attenuation to be set [0.0..31.5]
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
dev = int(attenuator)
|
||||||
|
except ValueError:
|
||||||
|
LOG.error("attenuator needs to be convertible into int.")
|
||||||
|
return 1
|
||||||
|
try:
|
||||||
|
val = float(attenuation)
|
||||||
|
except ValueError:
|
||||||
|
LOG.error("attenuation needs to be convertible into float.")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
attenuators[dev].set_attenuation(val)
|
||||||
|
LOG.info("xmlrpcserver: set attenuation of attenuator {} to {}".format(attenuator, attenuation))
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def main():
|
||||||
|
args = parse_args()
|
||||||
|
host, port = host_port(args.host)
|
||||||
|
server = SimpleXMLRPCServer((host, int(port)))
|
||||||
|
server.register_function(set_attenuation)
|
||||||
|
LOG.info("xmlrpcserver: registering 'set_attenuation'.")
|
||||||
|
try:
|
||||||
|
LOG.info("xmlrpcserver: start serving on %s:%s.", str(host), str(port))
|
||||||
|
server.serve_forever()
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
LOG.info("xmlrpcserver: Keyboard interrupt catched - shutting down.")
|
||||||
|
return 0
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(main())
|
115
source/attenuator/__init__.py
Normal file
115
source/attenuator/__init__.py
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
try:
|
||||||
|
from IOPi import IOPi
|
||||||
|
except ImportError:
|
||||||
|
sys.path.append('mock')
|
||||||
|
try:
|
||||||
|
from IOPi import IOPi
|
||||||
|
except ImportError:
|
||||||
|
raise ImportError("IOPi not found")
|
||||||
|
|
||||||
|
class Pin(object):
|
||||||
|
"""Abstraction of pin object. Every pin object contains a gpio number and a i2c bus address."""
|
||||||
|
bus_address = None
|
||||||
|
pin_number = None
|
||||||
|
bus = None
|
||||||
|
|
||||||
|
def __init__(self, bus_address, pin_number):
|
||||||
|
"""Constructor.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
bus_address (int): i2c bus address [0x20..0x23].
|
||||||
|
pin_number (int): Gpio pin number.
|
||||||
|
"""
|
||||||
|
self.bus_address = bus_address
|
||||||
|
self.pin_number = pin_number
|
||||||
|
|
||||||
|
class Attenuator(object):
|
||||||
|
"""Abstraction of ANALOG DEVICES HMC425A digital attenuator"""
|
||||||
|
pin = None
|
||||||
|
|
||||||
|
def __init__(self,pin_0_5db, pin_1_0db, pin_2_0db, pin_4_0db, pin_8_0db, pin_16_0db):
|
||||||
|
"""Constructor.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
pin_0_5db (Pin): Pin object to control the 0.5 db gpio
|
||||||
|
pin_1_0db (Pin): Pin object to control the 1.0 db gpio
|
||||||
|
pin_2_0db (Pin): Pin object to control the 2.0 db gpio
|
||||||
|
pin_4_0db (Pin): Pin object to control the 4.0 db gpio
|
||||||
|
pin_8_0db (Pin): Pin object to control the 8.0 db gpio
|
||||||
|
pin_16_0db (Pin): Pin object to control the 16.0 db gpio
|
||||||
|
"""
|
||||||
|
if type(pin_0_5db) is not Pin:
|
||||||
|
raise TypeError("Wrong type for pin_0_5db")
|
||||||
|
if type(pin_1_0db) is not Pin:
|
||||||
|
raise TypeError("Wrong type for pin_1_0db")
|
||||||
|
if type(pin_2_0db) is not Pin:
|
||||||
|
raise TypeError("Wrong type for pin_2_0db")
|
||||||
|
if type(pin_4_0db) is not Pin:
|
||||||
|
raise TypeError("Wrong type for pin_4_0db")
|
||||||
|
if type(pin_8_0db) is not Pin:
|
||||||
|
raise TypeError("Wrong type for pin_8_0db")
|
||||||
|
if type(pin_16_0db) is not Pin:
|
||||||
|
raise TypeError("Wrong type for pin_16_0db")
|
||||||
|
|
||||||
|
if pin_0_5db.bus_address not in range(0x20, 0x24):
|
||||||
|
raise IndexError('pin_0_0db i2c bus address index out of range')
|
||||||
|
if pin_1_0db.bus_address not in range(0x20, 0x24):
|
||||||
|
raise IndexError('pin_1_0db i2c bus address index out of range')
|
||||||
|
if pin_2_0db.bus_address not in range(0x20, 0x24):
|
||||||
|
raise IndexError('pin_2_0db i2c bus address index out of range')
|
||||||
|
if pin_4_0db.bus_address not in range(0x20, 0x24):
|
||||||
|
raise IndexError('pin_4_0db i2c bus address index out of range')
|
||||||
|
if pin_8_0db.bus_address not in range(0x20, 0x24):
|
||||||
|
raise IndexError('pin_8_0db i2c bus address index out of range')
|
||||||
|
if pin_16_0db.bus_address not in range(0x20, 0x24):
|
||||||
|
raise IndexError('pin_16_0db i2c bus address index out of range')
|
||||||
|
|
||||||
|
if pin_0_5db.pin_number not in range(1, 17):
|
||||||
|
raise IndexError('pin_0_5db pin number index out of range')
|
||||||
|
if pin_1_0db.pin_number not in range(1, 17):
|
||||||
|
raise IndexError('pin_1_0db pin number index out of range')
|
||||||
|
if pin_2_0db.pin_number not in range(1, 17):
|
||||||
|
raise IndexError('pin_2_0db pin number index out of range')
|
||||||
|
if pin_4_0db.pin_number not in range(1, 17):
|
||||||
|
raise IndexError('pin_4_0db pin number index out of range')
|
||||||
|
if pin_8_0db.pin_number not in range(1, 17):
|
||||||
|
raise IndexError('pin_8_0db pin number index out of range')
|
||||||
|
if pin_16_0db.pin_number not in range(1, 17):
|
||||||
|
raise IndexError('pin_16_0db pin number index out of range')
|
||||||
|
|
||||||
|
self.pin = [pin_0_5db, pin_1_0db, pin_2_0db, pin_4_0db, pin_8_0db, pin_16_0db]
|
||||||
|
|
||||||
|
for pin in self.pin:
|
||||||
|
pin.bus = IOPi(pin.bus_address)
|
||||||
|
pin.bus.set_pin_direction(pin.pin_number, 0)
|
||||||
|
pin.bus.write_pin(pin.pin_number, 0)
|
||||||
|
|
||||||
|
def set_attenuation(self, attenuation):
|
||||||
|
"""Set attenuation.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
attenuation (float): Value of attenuation to be set [0..31.5]
|
||||||
|
"""
|
||||||
|
if attenuation < 0:
|
||||||
|
attenuation = 0
|
||||||
|
elif attenuation > 31.5:
|
||||||
|
attenuation = 31.5
|
||||||
|
|
||||||
|
max_single_value = 16 * 2
|
||||||
|
attenuation *= 2
|
||||||
|
switch_pin = [1 for i in range(6)]
|
||||||
|
index = 5
|
||||||
|
|
||||||
|
while index >= 0:
|
||||||
|
if attenuation - max_single_value >= 0:
|
||||||
|
attenuation -= max_single_value
|
||||||
|
switch_pin[index] = 0
|
||||||
|
max_single_value /= 2
|
||||||
|
index -= 1
|
||||||
|
|
||||||
|
for i in range(0, len(switch_pin)):
|
||||||
|
bus = IOPi(self.pin[i].bus_address)
|
||||||
|
bus.write_pin(self.pin[i].pin_number, switch_pin[i])
|
238
tests/test_attenuator.py
Normal file
238
tests/test_attenuator.py
Normal file
@ -0,0 +1,238 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
sys.path.append(os.getcwd())
|
||||||
|
import attenuator
|
||||||
|
|
||||||
|
class TestSetAttenuation(unittest.TestCase):
|
||||||
|
# assign attenuation value to expected gpio pin settings
|
||||||
|
att_pins = {
|
||||||
|
0.0: [1,1,1,1,1,1],
|
||||||
|
0.5: [0,1,1,1,1,1],
|
||||||
|
1.0: [1,0,1,1,1,1],
|
||||||
|
1.5: [0,0,1,1,1,1],
|
||||||
|
2.0: [1,1,0,1,1,1],
|
||||||
|
2.5: [0,1,0,1,1,1],
|
||||||
|
3.0: [1,0,0,1,1,1],
|
||||||
|
3.5: [0,0,0,1,1,1],
|
||||||
|
4.0: [1,1,1,0,1,1],
|
||||||
|
4.5: [0,1,1,0,1,1],
|
||||||
|
5.0: [1,0,1,0,1,1],
|
||||||
|
5.5: [0,0,1,0,1,1],
|
||||||
|
6.0: [1,1,0,0,1,1],
|
||||||
|
6.5: [0,1,0,0,1,1],
|
||||||
|
7.0: [1,0,0,0,1,1],
|
||||||
|
7.5: [0,0,0,0,1,1],
|
||||||
|
8.0: [1,1,1,1,0,1],
|
||||||
|
8.5: [0,1,1,1,0,1],
|
||||||
|
9.0: [1,0,1,1,0,1],
|
||||||
|
9.5: [0,0,1,1,0,1],
|
||||||
|
10.0: [1,1,0,1,0,1],
|
||||||
|
10.5: [0,1,0,1,0,1],
|
||||||
|
11.0: [1,0,0,1,0,1],
|
||||||
|
11.5: [0,0,0,1,0,1],
|
||||||
|
12.0: [1,1,1,0,0,1],
|
||||||
|
12.5: [0,1,1,0,0,1],
|
||||||
|
13.0: [1,0,1,0,0,1],
|
||||||
|
13.5: [0,0,1,0,0,1],
|
||||||
|
14.0: [1,1,0,0,0,1],
|
||||||
|
14.5: [0,1,0,0,0,1],
|
||||||
|
15.0: [1,0,0,0,0,1],
|
||||||
|
15.5: [0,0,0,0,0,1],
|
||||||
|
16.0: [1,1,1,1,1,0],
|
||||||
|
16.5: [0,1,1,1,1,0],
|
||||||
|
17.0: [1,0,1,1,1,0],
|
||||||
|
17.5: [0,0,1,1,1,0],
|
||||||
|
18.0: [1,1,0,1,1,0],
|
||||||
|
18.5: [0,1,0,1,1,0],
|
||||||
|
19.0: [1,0,0,1,1,0],
|
||||||
|
19.5: [0,0,0,1,1,0],
|
||||||
|
20.0: [1,1,1,0,1,0],
|
||||||
|
20.5: [0,1,1,0,1,0],
|
||||||
|
21.0: [1,0,1,0,1,0],
|
||||||
|
21.5: [0,0,1,0,1,0],
|
||||||
|
22.0: [1,1,0,0,1,0],
|
||||||
|
22.5: [0,1,0,0,1,0],
|
||||||
|
23.0: [1,0,0,0,1,0],
|
||||||
|
23.5: [0,0,0,0,1,0],
|
||||||
|
24.0: [1,1,1,1,0,0],
|
||||||
|
24.5: [0,1,1,1,0,0],
|
||||||
|
25.0: [1,0,1,1,0,0],
|
||||||
|
25.5: [0,0,1,1,0,0],
|
||||||
|
26.0: [1,1,0,1,0,0],
|
||||||
|
26.5: [0,1,0,1,0,0],
|
||||||
|
27.0: [1,0,0,1,0,0],
|
||||||
|
27.5: [0,0,0,1,0,0],
|
||||||
|
28.0: [1,1,1,0,0,0],
|
||||||
|
28.5: [0,1,1,0,0,0],
|
||||||
|
29.0: [1,0,1,0,0,0],
|
||||||
|
29.5: [0,0,1,0,0,0],
|
||||||
|
30.0: [1,1,0,0,0,0],
|
||||||
|
30.5: [0,1,0,0,0,0],
|
||||||
|
31.0: [1,0,0,0,0,0],
|
||||||
|
31.5: [0,0,0,0,0,0],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_type_error(self):
|
||||||
|
pin = attenuator.Pin(0x20, 1)
|
||||||
|
with self.assertRaises(TypeError):
|
||||||
|
attenuator.Attenuator(pin, pin, pin, pin, pin, 1)
|
||||||
|
with self.assertRaises(TypeError):
|
||||||
|
attenuator.Attenuator(pin, pin, pin, pin, 1, 1)
|
||||||
|
with self.assertRaises(TypeError):
|
||||||
|
attenuator.Attenuator(pin, pin, pin, 1, 1, 1)
|
||||||
|
with self.assertRaises(TypeError):
|
||||||
|
attenuator.Attenuator(pin, pin, 1, 1, 1, 1)
|
||||||
|
with self.assertRaises(TypeError):
|
||||||
|
attenuator.Attenuator(pin, 1, 1, 1, 1, 1)
|
||||||
|
with self.assertRaises(TypeError):
|
||||||
|
attenuator.Attenuator( 1, 1, 1, 1, 1, 1)
|
||||||
|
|
||||||
|
|
||||||
|
def test_bus_addr_config_matching(self):
|
||||||
|
"""Check for correct i2s bus address"""
|
||||||
|
dummy = 1
|
||||||
|
bus_addr = 0x20
|
||||||
|
pin = attenuator.Pin(bus_addr, dummy)
|
||||||
|
dut = attenuator.Attenuator(pin, pin, pin, pin, pin, pin)
|
||||||
|
for i in range(0, 6):
|
||||||
|
self.assertEqual(bus_addr, dut.pin[i].bus_address)
|
||||||
|
|
||||||
|
|
||||||
|
def test_bus_addr_out_of_range(self):
|
||||||
|
"""Check behaviour in case of out of range i2s bus address"""
|
||||||
|
pin_addr_wrong = attenuator.Pin(0x1F, 1)
|
||||||
|
pin_addr_correct = attenuator.Pin(0x20, 1)
|
||||||
|
|
||||||
|
with self.assertRaises(IndexError):
|
||||||
|
attenuator.Attenuator(pin_addr_correct, pin_addr_correct, pin_addr_correct, pin_addr_correct, pin_addr_correct, pin_addr_wrong)
|
||||||
|
with self.assertRaises(IndexError):
|
||||||
|
attenuator.Attenuator(pin_addr_correct, pin_addr_correct, pin_addr_correct, pin_addr_correct, pin_addr_wrong, pin_addr_wrong)
|
||||||
|
with self.assertRaises(IndexError):
|
||||||
|
attenuator.Attenuator(pin_addr_correct, pin_addr_correct, pin_addr_correct, pin_addr_wrong, pin_addr_wrong, pin_addr_wrong)
|
||||||
|
with self.assertRaises(IndexError):
|
||||||
|
attenuator.Attenuator(pin_addr_correct, pin_addr_correct, pin_addr_wrong, pin_addr_wrong, pin_addr_wrong, pin_addr_wrong)
|
||||||
|
with self.assertRaises(IndexError):
|
||||||
|
attenuator.Attenuator(pin_addr_correct, pin_addr_wrong, pin_addr_wrong, pin_addr_wrong, pin_addr_wrong, pin_addr_wrong)
|
||||||
|
with self.assertRaises(IndexError):
|
||||||
|
attenuator.Attenuator(pin_addr_wrong, pin_addr_wrong, pin_addr_wrong, pin_addr_wrong, pin_addr_wrong, pin_addr_wrong)
|
||||||
|
|
||||||
|
pin_addr_wrong = attenuator.Pin(0x24, 1)
|
||||||
|
|
||||||
|
with self.assertRaises(IndexError):
|
||||||
|
attenuator.Attenuator(pin_addr_correct, pin_addr_correct, pin_addr_correct, pin_addr_correct, pin_addr_correct, pin_addr_wrong)
|
||||||
|
with self.assertRaises(IndexError):
|
||||||
|
attenuator.Attenuator(pin_addr_correct, pin_addr_correct, pin_addr_correct, pin_addr_correct, pin_addr_wrong, pin_addr_wrong)
|
||||||
|
with self.assertRaises(IndexError):
|
||||||
|
attenuator.Attenuator(pin_addr_correct, pin_addr_correct, pin_addr_correct, pin_addr_wrong, pin_addr_wrong, pin_addr_wrong)
|
||||||
|
with self.assertRaises(IndexError):
|
||||||
|
attenuator.Attenuator(pin_addr_correct, pin_addr_correct, pin_addr_wrong, pin_addr_wrong, pin_addr_wrong, pin_addr_wrong)
|
||||||
|
with self.assertRaises(IndexError):
|
||||||
|
attenuator.Attenuator(pin_addr_correct, pin_addr_wrong, pin_addr_wrong, pin_addr_wrong, pin_addr_wrong, pin_addr_wrong)
|
||||||
|
with self.assertRaises(IndexError):
|
||||||
|
attenuator.Attenuator(pin_addr_wrong, pin_addr_wrong, pin_addr_wrong, pin_addr_wrong, pin_addr_wrong, pin_addr_wrong)
|
||||||
|
|
||||||
|
|
||||||
|
def test_gpio_config_matching(self):
|
||||||
|
"""Check if gpio numbers are set correctly"""
|
||||||
|
gpio_0_5db = attenuator.Pin(0x20, 1)
|
||||||
|
gpio_1_0db = attenuator.Pin(0x20, 2)
|
||||||
|
gpio_2_0db = attenuator.Pin(0x20, 3)
|
||||||
|
gpio_4_0db = attenuator.Pin(0x20, 4)
|
||||||
|
gpio_8_0db = attenuator.Pin(0x20, 5)
|
||||||
|
gpio_16_0db = attenuator.Pin(0x20, 6)
|
||||||
|
dut = attenuator.Attenuator(gpio_0_5db, gpio_1_0db, gpio_2_0db, gpio_4_0db, gpio_8_0db, gpio_16_0db)
|
||||||
|
expected_gpios = [gpio_0_5db.pin_number, gpio_1_0db.pin_number, gpio_2_0db.pin_number, gpio_4_0db.pin_number, gpio_8_0db.pin_number, gpio_16_0db.pin_number]
|
||||||
|
result_gpios = list()
|
||||||
|
for i in range(0, 6):
|
||||||
|
result_gpios.append(dut.pin[i].pin_number)
|
||||||
|
self.assertSequenceEqual(result_gpios, expected_gpios)
|
||||||
|
|
||||||
|
|
||||||
|
def test_gpio_out_of_range(self):
|
||||||
|
"""Check if IndexError is raised if gpio config is out of range"""
|
||||||
|
pin_valid = attenuator.Pin(0x20, 1)
|
||||||
|
pin_invalid_low = attenuator.Pin(0x20, 0)
|
||||||
|
pin_invalid_high = attenuator.Pin(0x20, 0)
|
||||||
|
|
||||||
|
with self.assertRaises(IndexError):
|
||||||
|
attenuator.Attenuator(pin_invalid_low, pin_invalid_low, pin_invalid_low, pin_invalid_low, pin_invalid_low, pin_invalid_low)
|
||||||
|
with self.assertRaises(IndexError):
|
||||||
|
attenuator.Attenuator(pin_valid, pin_invalid_low, pin_invalid_low, pin_invalid_low, pin_invalid_low, pin_invalid_low)
|
||||||
|
with self.assertRaises(IndexError):
|
||||||
|
attenuator.Attenuator(pin_valid, pin_valid, pin_invalid_low, pin_invalid_low, pin_invalid_low, pin_invalid_low)
|
||||||
|
with self.assertRaises(IndexError):
|
||||||
|
attenuator.Attenuator(pin_valid, pin_valid, pin_valid, pin_invalid_low, pin_invalid_low, pin_invalid_low)
|
||||||
|
with self.assertRaises(IndexError):
|
||||||
|
attenuator.Attenuator(pin_valid, pin_valid, pin_valid, pin_valid, pin_invalid_low, pin_invalid_low)
|
||||||
|
with self.assertRaises(IndexError):
|
||||||
|
attenuator.Attenuator(pin_valid, pin_valid, pin_valid, pin_valid, pin_valid, pin_invalid_low)
|
||||||
|
|
||||||
|
with self.assertRaises(IndexError):
|
||||||
|
attenuator.Attenuator(pin_invalid_high, pin_invalid_high, pin_invalid_high, pin_invalid_high, pin_invalid_high, pin_invalid_high)
|
||||||
|
with self.assertRaises(IndexError):
|
||||||
|
attenuator.Attenuator(pin_valid, pin_invalid_high, pin_invalid_high, pin_invalid_high, pin_invalid_high, pin_invalid_high)
|
||||||
|
with self.assertRaises(IndexError):
|
||||||
|
attenuator.Attenuator(pin_valid, pin_valid, pin_invalid_high, pin_invalid_high, pin_invalid_high, pin_invalid_high)
|
||||||
|
with self.assertRaises(IndexError):
|
||||||
|
attenuator.Attenuator(pin_valid, pin_valid, pin_valid, pin_invalid_high, pin_invalid_high, pin_invalid_high)
|
||||||
|
with self.assertRaises(IndexError):
|
||||||
|
attenuator.Attenuator(pin_valid, pin_valid, pin_valid, pin_valid, pin_invalid_high, pin_invalid_high)
|
||||||
|
with self.assertRaises(IndexError):
|
||||||
|
attenuator.Attenuator(pin_valid, pin_valid, pin_valid, pin_valid, pin_valid, pin_invalid_high)
|
||||||
|
|
||||||
|
|
||||||
|
def test_attenuation(self):
|
||||||
|
"""Test setting an attenuation."""
|
||||||
|
dut = attenuator.Attenuator(
|
||||||
|
attenuator.Pin(0X20, 1),
|
||||||
|
attenuator.Pin(0X20, 2),
|
||||||
|
attenuator.Pin(0X20, 3),
|
||||||
|
attenuator.Pin(0X20, 4),
|
||||||
|
attenuator.Pin(0X20, 5),
|
||||||
|
attenuator.Pin(0X20, 6))
|
||||||
|
|
||||||
|
for att in self.att_pins:
|
||||||
|
dut.set_attenuation(att)
|
||||||
|
result_pins = list()
|
||||||
|
for i in range(0, 6):
|
||||||
|
result_pins.append(dut.pin[i].bus.read_pin(dut.pin[i].pin_number))
|
||||||
|
self.assertSequenceEqual(result_pins, self.att_pins[att])
|
||||||
|
|
||||||
|
|
||||||
|
def test_attennuation_too_big(self):
|
||||||
|
dut = attenuator.Attenuator(
|
||||||
|
attenuator.Pin(0X20, 1),
|
||||||
|
attenuator.Pin(0X20, 2),
|
||||||
|
attenuator.Pin(0X20, 3),
|
||||||
|
attenuator.Pin(0X20, 4),
|
||||||
|
attenuator.Pin(0X20, 5),
|
||||||
|
attenuator.Pin(0X20, 6))
|
||||||
|
dut.set_attenuation(31.6)
|
||||||
|
result_pins = list()
|
||||||
|
for i in range(0, 6):
|
||||||
|
result_pins.append(dut.pin[i].bus.read_pin(dut.pin[i].pin_number))
|
||||||
|
self.assertSequenceEqual(result_pins, self.att_pins[31.5])
|
||||||
|
|
||||||
|
|
||||||
|
def test_attennuation_negative(self):
|
||||||
|
dut = attenuator.Attenuator(
|
||||||
|
attenuator.Pin(0X20, 1),
|
||||||
|
attenuator.Pin(0X20, 2),
|
||||||
|
attenuator.Pin(0X20, 3),
|
||||||
|
attenuator.Pin(0X20, 4),
|
||||||
|
attenuator.Pin(0X20, 5),
|
||||||
|
attenuator.Pin(0X20, 6))
|
||||||
|
dut.set_attenuation(-0.5)
|
||||||
|
result_pins = list()
|
||||||
|
for i in range(0, 6):
|
||||||
|
result_pins.append(dut.pin[i].bus.read_pin(dut.pin[i].pin_number))
|
||||||
|
self.assertSequenceEqual(result_pins, self.att_pins[0])
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
Loading…
x
Reference in New Issue
Block a user