def write_mem (self, start_addr, type, data): """ Uploads data to a target SpiNNaker node at a specific memory location. :param int start_addr: base address for the uploaded data :param int type: one of ``TYPE_BYTE``, ``TYPE_HALF``, or ``TYPE_WORD`` to indicate element type :param str data: string of data to upload :raises: SCPError """ msg = SCPMessage (cmd_rc=scamp.CMD_WRITE, arg3=type) # confirm the data length is aligned to the appropriate boundary self._check_size_alignment(type, len (data)) # upload the data in maximum-sized chunks addr = start_addr for chunk in self.gen_slice(data, scamp.SDP_DATA_SIZE): # build up the packet as follows: # arg1 = start address # arg2 = chunk length # arg3 = element size msg.arg1 = addr msg.arg2 = len (chunk) msg.payload = chunk self.transceiver.conn.send_scp_msg(msg) # increment the address pointer addr += len (chunk)
def exec_app_start(self, start_addr, cpu_mask): """ Simultaneously executes APLX images on several processors in the target SpiNNaker node. :param int start_addr: memory address of the APLX image :param int cpu_mask: bit-mask of processors on which to execute the image :raises: SCPError ``cpu_mask`` is an integer *mask* where each bit corresponds to a processor on the target SpiNNaker node, i.e. bit N implies that the program should be executed on processor N. .. warning:: The monitor processor **is** included in the ``cpu_mask`` which can lead to errors if the APLX image was not designed to run on the monitor pacman. """ # simple packet: # arg1 = address of program in memory # arg2 = cpu mask - each bit corresponds to a pacman in the chip # arg3 = unused msg = SCPMessage() msg.cmd_rc = scamp.CMD_AS msg.arg1 = start_addr msg.arg2 = cpu_mask self.transceiver.conn.send_scp_msg(msg)
def nnp(self, key, data, sfr): msg = SCPMessage(cmd_rc=scamp.CMD_NNP) #initlise values msg._arg1 = key msg._arg2 = data msg._arg3 = sfr self.transceiver.conn.send_scp_msg(msg)
def init_p2p_tables(self, cx, cy): """ Configure the P2P tables on the remote SpiNNaker using the Manchester algorithm which superimposes a 2D co-ordinate space on the SpiNNaker fabric. :param int cx: width of the P2P space :param int cy: height of the P2P space """ msg = SCPMessage (cmd_rc=scamp.CMD_P2PC) # generate a new sequence number seq = self.next_seq_num() # the following lines have been taken almost verbatim from ybug. # the comments state the following organisation but this is clearly no # longer the case: # arg1 = 00 : 00 : 00 : seq num # arg2 = cx : cy : addr x : addr y # arg3 = 00 : 00 : fwd : retry msg.arg1 = (0x003e << 16) | seq msg.arg2 = (cx << 24) | (cy << 16) msg.arg3 = 0x3ff8 # send the command to SpiNNaker self.send_scp_msg (msg)
def get_iptag (self, index): """ Retrieve an IP-tag from the target SpiNNaker machine. :param int index: index in the IP-tag table. :returns: IP tag data in a :py:class:`IPTag` :raises: SCPError """ # build up the request as follows: # arg1 = 0 : command : 0 : tag # arg2 = 0 : 0 : 0 : count # arg3 = 0 : 0 : 0 : 0 msg = SCPMessage () msg.cmd_rc = scamp.CMD_IPTAG msg.arg1 = scamp.IPTAG_GET << 16 | index msg.arg2 = 1 msg.arg3 = 0 resp_msg = self.send_scp_msg (msg) # deconstruct the returned data if len (resp_msg.data) != 16: raise ValueError ("insufficient data received in response.") (ip, mac, port, timeout, flags) = struct.unpack ('<4s6s3H', resp_msg.data) # format the IP and MAC addresses correctly ip = '.'.join (['%d' % ord (c) for c in ip]) mac = ':'.join (['%02X' % ord (c) for c in mac]) # return the data as a struct return IPTag(ip=ip, mac=mac, port=port, timeout=timeout/100.0, flags=flags, index=index)
def get_iptag_table_info (self): """ Retrieve the number of fixed and transient tags available as well as the default timeout for all transient tags. :returns: fixed record count, transient record count, default timeout :raises: SCPError """ # build up the request according to the following formula: # arg1 = 0 : command : 0 : 0 # arg2 = 0 : 0 : 0 : timeout # arg3 = 0 : 0 : 0 : 0 msg = SCPMessage () msg.cmd_rc = scamp.CMD_IPTAG msg.arg1 = scamp.IPTAG_TTO << 16 msg.arg2 = 255 # must be 16 or greater to be ignored msg.arg3 = 0 resp_msg = self.send_scp_msg (msg) # decode the response data (32bits) structured as follows: # 31:24 - max. number of fixed tags # 23:16 - max. number of transient tags # 15: 8 - reserved (0) # 7: 0 - transient timeout exponent if len (resp_msg.data) != 4: raise ValueError ("insufficient data received in response.") (ttoE, trans, fixed) = struct.unpack ('Bx2B', resp_msg.data) # convert the timeout into seconds using the equation: # timeout = 10ms * 2^(ttoE - 1) timeout = (1 << (ttoE - 1)) * 0.01 return (fixed, trans, timeout)
def set_leds(self, led1=scamp.LED_NO_CHANGE, led2=scamp.LED_NO_CHANGE, led3=scamp.LED_NO_CHANGE, led4=scamp.LED_NO_CHANGE): """ Changes the state of the LEDs of the target SpiNNaker node. :param int led1: action for LED 1 :param int led2: action for LED 2 :param int led3: action for LED 3 :param int led4: action for LED 4 :raises: SCPError Each ``ledN`` parameter may be given one of four values from the SC&MP definitions: ``LED_NO_CHANGE``, ``LED_INVERT``, ``LED_OFF``, or ``LED_ON``. """ # LED control signals exist only in the lowest byte of arg1 msg = SCPMessage() msg.cmd_rc = scamp.CMD_LED msg.arg1 = (led4 << 6) | (led3 << 4) | (led2 << 2) | led1 self.send_scp_msg(msg)
def init_p2p_tables(self, cx, cy): """ Configure the P2P tables on the remote SpiNNaker using the Manchester algorithm which superimposes a 2D co-ordinate space on the SpiNNaker fabric. :param int cx: width of the P2P space :param int cy: height of the P2P space """ msg = SCPMessage(cmd_rc=scamp.CMD_P2PC) # generate a new sequence number seq = self.next_seq_num() # the following lines have been taken almost verbatim from ybug. # the comments state the following organisation but this is clearly no # longer the case: # arg1 = 00 : 00 : 00 : seq num # arg2 = cx : cy : addr x : addr y # arg3 = 00 : 00 : fwd : retry msg.arg1 = (0x003e << 16) | seq msg.arg2 = (cx << 24) | (cy << 16) msg.arg3 = 0x3ff8 # send the command to SpiNNaker self.send_scp_msg(msg)
def flood_fill(self, buf, region, mask, app_id, app_flags, base=0x67800000): num_bytes = len(buf) blocks = int(num_bytes / BLOCK_SIZE) if (num_bytes % BLOCK_SIZE) != 0: blocks += 1 logger.debug("Bytes %u blocks %u" % (num_bytes, blocks)) sfwd, srty = 0x3f, 0x18# Forward, retry parameters ff_id = self.next_id() fr = (sfwd << 8) + srty# Pack up fwd, rty sfr = (1 << 31) + fr# Bit 31 says allocate ID on Spin key = (NN_CMD_FFS << 24) + (ff_id << 16) + (blocks << 8) + 0 data = region self.nnp(key, data, sfr) #send FFD data ptr = 0 for block in range(blocks): end = ptr + BLOCK_SIZE data = buf[ptr:end] word_size = (len(data) / 4) - 1 #convert to word size (why -1?) arg1 = (sfwd << 24) + (srty << 16) + (0 << 8) + ff_id #?? arg2 = (0 << 24) + (block << 16) + (word_size << 8) + 0 #?? msg = SCPMessage(cmd_rc=scamp.CMD_FFD) #initlise values msg.arg1 = arg1 msg.arg2 = arg2 msg.arg3 = base msg.payload = data self.transceiver.conn.send_scp_msg(msg) #update pointer to next block base += BLOCK_SIZE ptr += BLOCK_SIZE # send FFE packet key = (NN_CMD_FFE << 24) + (0 << 16) + (0 << 8) + ff_id # const data = (app_id << 24) + (app_flags << 18) + (mask & 0x3ffff) self.nnp(key, data, fr)
def exec_aplx(self, start_addr): """ Executes an APLX image on the target SpiNNaker node. :param int start_addr: memory address of the APLX image :raises: SCPError """ # simple packet: # arg1 = address of "table" (i.e. program start in SDRAM) # arg2 = unused parameter - must be 0 # arg3 = unused msg = SCPMessage() msg.cmd_rc = scamp.CMD_APLX msg.arg1 = start_addr self.transceiver.conn.send_scp_msg(msg)
def exec_aplx (self, start_addr): """ Executes an APLX image on the target SpiNNaker node. :param int start_addr: memory address of the APLX image :raises: SCPError """ # simple packet: # arg1 = address of "table" (i.e. program start in SDRAM) # arg2 = unused parameter - must be 0 # arg3 = unused msg = SCPMessage () msg.cmd_rc = scamp.CMD_APLX msg.arg1 = start_addr self.transceiver.conn.send_scp_msg (msg)
def clear_iptag (self, index): """ Removes an IP-tag from the remote SpiNNaker. :param int index: index to remove from the table :raises: SCPError """ # build up the request as follows: # arg1 = 0 : command : 0 : tag # arg2 = 0 : 0 : 0 : 0 # arg3 = 0 : 0 : 0 : 0 msg = SCPMessage () msg.cmd_rc = scamp.CMD_IPTAG msg.arg1 = (scamp.IPTAG_CLR << 16) | index # fire off the command self.send_scp_msg (msg)
def clear_iptag(self, index): """ Removes an IP-tag from the remote SpiNNaker. :param int index: index to remove from the table :raises: SCPError """ # build up the request as follows: # arg1 = 0 : command : 0 : tag # arg2 = 0 : 0 : 0 : 0 # arg3 = 0 : 0 : 0 : 0 msg = SCPMessage() msg.cmd_rc = scamp.CMD_IPTAG msg.arg1 = (scamp.IPTAG_CLR << 16) | index # fire off the command self.send_scp_msg(msg)
def read_mem (self, start_addr, type, size): """ Reads an amount of data from the target SpiNNaker node starting at address ``start_addr``. :param int start_addr: address to start reading from :param int type: one of ``TYPE_BYTE``, ``TYPE_HALF``, or ``TYPE_WORD`` to indicate element type :param int size: number of bytes to read :returns: string containing the data read :raises: SCPError """ msg = SCPMessage (cmd_rc=scamp.CMD_READ) # confirm the data size is aligned to the appropriate boundary self._check_size_alignment (type, size) # initialise tracker variables addr = start_addr buf = '' read_size = size # read all the data while (addr - start_addr) < size: # build up the packet as follows: # arg1 = start address # arg2 = chunk length # arg3 = element size msg.arg1 = addr msg.arg2 = min (read_size, scamp.SDP_DATA_SIZE) msg.arg3 = type resp = self.transceiver.conn.send_scp_msg (msg) # add the data to the buffer and update the tracker variables buf += resp.data addr += len (resp.data) read_size -= len (resp.data) # return the (hopefully valid) data buffer return buf
def set_iptag (self, index, host, port): """ Set an IP-tag record at the required index. :param int index: index in the IP-tag table :param str host: hostname or IP address of destination :param int port: port to use on destination :param int timeout: specific timeout to use, or 0 for default :returns: record index in the IP-tag table :raises: SCPError """ # clamp the port and timeout to their appropriate ranges port &= 0xFFFF # ensure that the given hostname is always an IP if host.lower () in ("localhost", "127.0.0.1", "."): host = self._sock.getsockname()[0] ip = socket.gethostbyname (host) # decompose the IP address into the component numbers and store in an # integer in REVERSE order so that it's correct after packing ip, segs = 0, ip.split ('.') if len (segs) != 4: raise ValueError ("IP address format is incorrect") for n, seg in enumerate (segs): ip |= (int (seg) << (8*n)) msg = SCPMessage (cmd_rc=scamp.CMD_IPTAG) msg.arg1 = scamp.IPTAG_SET << 16 | (index & 0xFF) # the rest of the arguments follow the order: # arg2 = port # arg3 = IP msg.arg2 = port msg.arg3 = ip # fire off the packet self.send_scp_msg (msg)
def set_iptag(self, index, host, port): """ Set an IP-tag record at the required index. :param int index: index in the IP-tag table :param str host: hostname or IP address of destination :param int port: port to use on destination :param int timeout: specific timeout to use, or 0 for default :returns: record index in the IP-tag table :raises: SCPError """ # clamp the port and timeout to their appropriate ranges port &= 0xFFFF # ensure that the given hostname is always an IP if host.lower() in ("localhost", "127.0.0.1", "."): host = self._sock.getsockname()[0] ip = socket.gethostbyname(host) # decompose the IP address into the component numbers and store in an # integer in REVERSE order so that it's correct after packing ip, segs = 0, ip.split('.') if len(segs) != 4: raise ValueError("IP address format is incorrect") for n, seg in enumerate(segs): ip |= (int(seg) << (8 * n)) msg = SCPMessage(cmd_rc=scamp.CMD_IPTAG) msg.arg1 = scamp.IPTAG_SET << 16 | (index & 0xFF) # the rest of the arguments follow the order: # arg2 = port # arg3 = IP msg.arg2 = port msg.arg3 = ip # fire off the packet self.send_scp_msg(msg)
def get_iptag_table_info(self): """ Retrieve the number of fixed and transient tags available as well as the default timeout for all transient tags. :returns: fixed record count, transient record count, default timeout :raises: SCPError """ # build up the request according to the following formula: # arg1 = 0 : command : 0 : 0 # arg2 = 0 : 0 : 0 : timeout # arg3 = 0 : 0 : 0 : 0 msg = SCPMessage() msg.cmd_rc = scamp.CMD_IPTAG msg.arg1 = scamp.IPTAG_TTO << 16 msg.arg2 = 255 # must be 16 or greater to be ignored msg.arg3 = 0 resp_msg = self.send_scp_msg(msg) # decode the response data (32bits) structured as follows: # 31:24 - max. number of fixed tags # 23:16 - max. number of transient tags # 15: 8 - reserved (0) # 7: 0 - transient timeout exponent if len(resp_msg.data) != 4: raise ValueError("insufficient data received in response.") (ttoE, trans, fixed) = struct.unpack('Bx2B', resp_msg.data) # convert the timeout into seconds using the equation: # timeout = 10ms * 2^(ttoE - 1) timeout = (1 << (ttoE - 1)) * 0.01 return (fixed, trans, timeout)
def reset(hostname): """ Establishes a SCP connection to the board-management processor specified by ``hostname`` and sends a reset command. :param hostname: hostname of the board-management processor of the target SpiNNaker .. warning:: This function is only applicable to SpiNN-4 (or greater) boards that have board-management processors on the PCB. """ # simple packet: # arg1 = 2 (denotes pulse reset) conn = SCPConnection(hostname) msg = SCPMessage() msg.cmd_rc = scamp.CMD_RESET msg.arg1 = 2 conn.send_scp_msg(msg)
def read_link_word(start_addr, linkid, conn): """ Reads data from a neighbouring chip over that link :param int start_addr: address to start reading from (type is always a 32-bit word!) :param int linkid: which link to use, i.e. 0:E, 1: NE, 2:N, 3:W, 4:SW, 5:S :returns: string containing the data read :raises: SCPError """ msg = SCPMessage(cmd_rc=scamp.CMD_LINK_READ) # confirm the data size is aligned to the appropriate boundary #self._check_size_alignment (type, size) # initialise tracker variables addr = start_addr buf = '' read_size = 4 # read all the data while (addr - start_addr) < read_size: # build up the packet as follows: # arg1 = start address # arg2 = chunk length # arg3 = element size msg.arg1 = addr msg.arg2 = min(read_size, scamp.SDP_DATA_SIZE) msg.arg3 = linkid resp = conn.conn.send_scp_msg(msg) # add the data to the buffer and update the tracker variables buf += resp.data addr += len(resp.data) read_size -= len(resp.data) # return the (hopefully valid) data buffer requested return buf
def set_leds (self, led1=scamp.LED_NO_CHANGE, led2=scamp.LED_NO_CHANGE, led3=scamp.LED_NO_CHANGE, led4=scamp.LED_NO_CHANGE): """ Changes the state of the LEDs of the target SpiNNaker node. :param int led1: action for LED 1 :param int led2: action for LED 2 :param int led3: action for LED 3 :param int led4: action for LED 4 :raises: SCPError Each ``ledN`` parameter may be given one of four values from the SC&MP definitions: ``LED_NO_CHANGE``, ``LED_INVERT``, ``LED_OFF``, or ``LED_ON``. """ # LED control signals exist only in the lowest byte of arg1 msg = SCPMessage () msg.cmd_rc = scamp.CMD_LED msg.arg1 = (led4 << 6) | (led3 << 4) | (led2 << 2) | led1 self.send_scp_msg (msg)
def version(self, retries=10): """ Retreives the version information about the host operating system. :returns: version of OS in a class :raises: SCPError """ cmd_msg = SCPMessage(cmd_rc=scamp.CMD_VER) ver_msg = self.send_scp_msg(cmd_msg, retries=retries) # decode the payload into a usable struct return VersionInfo(ver_msg)
def set_transient_iptag_timeout (self, timeout): """ Sets the timeout for all transient IP-tags on the target machine. :param float: timeout in *seconds* :raises: SCPError .. note:: On the SpiNNaker node, all timeouts are stored in an exponential representation that limits the number of valid timeout durations to a small set. Timeouts are calculated (from the node's perspective) as follows:: timeout = 10ms * 2^(tto - 1) Hence timeout values passed into this function will be decomposed into ``tto`` in the above equation. """ # convert the timeout into the exponent as explained above tto = int (math.ceil (math.log ((timeout / 0.01), 2))) + 1 if tto >= 16: raise ValueError ("specific timeout is too large.") # set the new transient timeout # arg1 = 0 : command : 0 : 0 # arg2 = 0 : 0 : 0 : timeout # arg3 = 0 : 0 : 0 : 0 msg = SCPMessage () msg.cmd_rc = scamp.CMD_IPTAG msg.arg1 = scamp.IPTAG_TTO << 16 msg.arg2 = tto msg.arg3 = 0 self.send_scp_msg (msg)
def flood_fill(self, buf, region, mask, app_id, app_flags, base=0x67800000): num_bytes = len(buf) blocks = int(num_bytes / BLOCK_SIZE) if (num_bytes % BLOCK_SIZE) != 0: blocks += 1 logger.debug("Bytes %u blocks %u" % (num_bytes, blocks)) sfwd, srty = 0x3f, 0x18 # Forward, retry parameters ff_id = self.next_id() fr = (sfwd << 8) + srty # Pack up fwd, rty sfr = (1 << 31) + fr # Bit 31 says allocate ID on Spin key = (NN_CMD_FFS << 24) + (ff_id << 16) + (blocks << 8) + 0 data = region self.nnp(key, data, sfr) #send FFD data ptr = 0 for block in range(blocks): end = ptr + BLOCK_SIZE data = buf[ptr:end] word_size = (len(data) / 4) - 1 #convert to word size (why -1?) arg1 = (sfwd << 24) + (srty << 16) + (0 << 8) + ff_id #?? arg2 = (0 << 24) + (block << 16) + (word_size << 8) + 0 #?? msg = SCPMessage(cmd_rc=scamp.CMD_FFD) #initlise values msg.arg1 = arg1 msg.arg2 = arg2 msg.arg3 = base msg.payload = data self.transceiver.conn.send_scp_msg(msg) #update pointer to next block base += BLOCK_SIZE ptr += BLOCK_SIZE # send FFE packet key = (NN_CMD_FFE << 24) + (0 << 16) + (0 << 8) + ff_id # const data = (app_id << 24) + (app_flags << 18) + (mask & 0x3ffff) self.nnp(key, data, fr)
def get_iptag(self, index): """ Retrieve an IP-tag from the target SpiNNaker machine. :param int index: index in the IP-tag table. :returns: IP tag data in a :py:class:`IPTag` :raises: SCPError """ # build up the request as follows: # arg1 = 0 : command : 0 : tag # arg2 = 0 : 0 : 0 : count # arg3 = 0 : 0 : 0 : 0 msg = SCPMessage() msg.cmd_rc = scamp.CMD_IPTAG msg.arg1 = scamp.IPTAG_GET << 16 | index msg.arg2 = 1 msg.arg3 = 0 resp_msg = self.send_scp_msg(msg) # deconstruct the returned data if len(resp_msg.data) != 16: raise ValueError("insufficient data received in response.") (ip, mac, port, timeout, flags) = struct.unpack('<4s6s3H', resp_msg.data) # format the IP and MAC addresses correctly ip = '.'.join(['%d' % ord(c) for c in ip]) mac = ':'.join(['%02X' % ord(c) for c in mac]) # return the data as a struct return IPTag(ip=ip, mac=mac, port=port, timeout=timeout / 100.0, flags=flags, index=index)
def set_transient_iptag_timeout(self, timeout): """ Sets the timeout for all transient IP-tags on the target machine. :param float: timeout in *seconds* :raises: SCPError .. note:: On the SpiNNaker node, all timeouts are stored in an exponential representation that limits the number of valid timeout durations to a small set. Timeouts are calculated (from the node's perspective) as follows:: timeout = 10ms * 2^(tto - 1) Hence timeout values passed into this function will be decomposed into ``tto`` in the above equation. """ # convert the timeout into the exponent as explained above tto = int(math.ceil(math.log((timeout / 0.01), 2))) + 1 if tto >= 16: raise ValueError("specific timeout is too large.") # set the new transient timeout # arg1 = 0 : command : 0 : 0 # arg2 = 0 : 0 : 0 : timeout # arg3 = 0 : 0 : 0 : 0 msg = SCPMessage() msg.cmd_rc = scamp.CMD_IPTAG msg.arg1 = scamp.IPTAG_TTO << 16 msg.arg2 = tto msg.arg3 = 0 self.send_scp_msg(msg)
def app_signal(self, app_id, signal_id, state_id=None, x=None, y=None, range=None): ''' method that allows signals to be polled and sent to areas of a board ''' #define the region region = "" if(x is None and y is None): region = "all" if signal_id not in self.signal_states: raise exceptions.SpinnManException("signal definition does not " "exist for {}. List is {}" .format(signal_id, self.signal_states)) region = self.spinnaker_utility.parse_region(region, x, y) #locate signal name id signal = self.signal_states[signal_id] #locate state id state = None if signal_id >= 16: if state_id is not None: if state_id in self.states: state = self.states[state_id] else: raise exceptions.SpinnManException("No state with that id") else: raise exceptions.SpinnManException("state was defined as None " "when using a and/or/count " "signal") #locate type of signal signal_type = self.sig_type[signal] #parse the apps for a app mask app_mask = self.spinnaker_utility.parse_apps(app_id, range) mask = int(region) & 0xffff data = (app_mask << 8) + app_id #if signal type is 1 if signal_type == 1: level = (region >> 16) & 3 op, mode = 2, 2 #if signal is a and/or/count if signal_id >= 16: op = 1 mode = signal_id - 16 data += (level << 26) + (op << 22) + (mode << 20) if op == 1: data += state_id << 16 if op != 1: data += signal_id << 16 # logger.debug("Level {} op {} mode {}".format(level, op, mode)) else: data += signal_id << 16 # logger.debug("Type {} data {} mask {}".format(signal_type, data, mask)) # logger.debug("Region {} signal {} state {}".format(region, signal, state)) #send scp message and catch the return data msg = SCPMessage(cmd_rc=scamp.CMD_SIG) msg._arg1 = signal_type msg._arg2 = data msg._arg3 = mask return_data = self.transceiver.conn.send_scp_msg(msg).data # if the signal requires a repsonse, output resposne and return it if signal_type == 1: r = struct.unpack("<I", return_data)[0] if signal_id == 18: #count #logger.debug("count {}".format(r)) return r # else: #logger.debug("mask {}".format(r)) return 0
def app_signal(self, app_id, signal_id, state_id=None, x=None, y=None, range=None): ''' method that allows signals to be polled and sent to areas of a board ''' #define the region region = "" if (x is None and y is None): region = "all" if signal_id not in self.signal_states: raise exceptions.SpinnManException( "signal definition does not " "exist for {}. List is {}".format(signal_id, self.signal_states)) region = self.spinnaker_utility.parse_region(region, x, y) #locate signal name id signal = self.signal_states[signal_id] #locate state id state = None if signal_id >= 16: if state_id is not None: if state_id in self.states: state = self.states[state_id] else: raise exceptions.SpinnManException("No state with that id") else: raise exceptions.SpinnManException("state was defined as None " "when using a and/or/count " "signal") #locate type of signal signal_type = self.sig_type[signal] #parse the apps for a app mask app_mask = self.spinnaker_utility.parse_apps(app_id, range) mask = int(region) & 0xffff data = (app_mask << 8) + app_id #if signal type is 1 if signal_type == 1: level = (region >> 16) & 3 op, mode = 2, 2 #if signal is a and/or/count if signal_id >= 16: op = 1 mode = signal_id - 16 data += (level << 26) + (op << 22) + (mode << 20) if op == 1: data += state_id << 16 if op != 1: data += signal_id << 16 # logger.debug("Level {} op {} mode {}".format(level, op, mode)) else: data += signal_id << 16 # logger.debug("Type {} data {} mask {}".format(signal_type, data, mask)) # logger.debug("Region {} signal {} state {}".format(region, signal, state)) #send scp message and catch the return data msg = SCPMessage(cmd_rc=scamp.CMD_SIG) msg._arg1 = signal_type msg._arg2 = data msg._arg3 = mask return_data = self.transceiver.conn.send_scp_msg(msg).data # if the signal requires a repsonse, output resposne and return it if signal_type == 1: r = struct.unpack("<I", return_data)[0] if signal_id == 18: #count #logger.debug("count {}".format(r)) return r # else: #logger.debug("mask {}".format(r)) return 0