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:
		
							
								
								
									
										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()
 | 
				
			||||||
		Reference in New Issue
	
	Block a user