IO::HyCon - Perl interface to the Analog Paradigm hybrid controller.


This document refers to version 1.0 of HyCon


    use strict;
    use warnings;

    use File::Basename;
    use HyCon;

    (my $config_filename = basename($0)) =~ s/\.pl$//;
    print "Create object...\n";
    my $ac = HyCon->new("$config_filename.yml");

    $ac->set_ic_time(500);  # Set IC-time to 500 ms
    $ac->set_op_time(1000); # Set OP-Time to 1000 ms
    $ac->single_run();      # Perform a single computation run

    # Read a value from a specific computing element:
    my $element_name = 'SUM8-0';
    my $value = $ac->read_element($element_name);


This module implements a simple object oriented interface to the Arduino\textregistered~ based Analog Paradigm hybrid controller which interfaces an analog computer to a digital computer and thus allows true hybrid computation.

Functions and methods


This function generates a HyCon-object. Currently there is only one hybrid controller supported, so this is, in fact, a singleton and every subsequent invocation will cause a fatal error. If no configuration file path is supplied as parameter, new() tries to open a YAML-file with the name of the currently running program but with the extension '.yml' instead of '.pl'. This file is assumed to have the following structure (this example configures a van der Pol oscillator):

serial: port: /dev/cu.usbserial-DN050L1O bits: 8 baud: 115200 parity: none stopbits: 1 poll_interval: 10 poll_attempts: 20000 types: 0: PS 1: SUM8 2: INT4 3: PT8 4: CU 5: MLT8 6: MDS2 7: CMP4 8: HC elements: INT0-: 0160 INT0+: 0123 INT0a: 0060/0 INT0b: 0060/1 INT0ic: 0080/0

    INT1-: 0161
    INT1+: 0126
    INT1a: 0060/2
    INT1b: 0060/3
    INT1ic: 0080/1

    INT2-: 0162
    INT2a: 0060/4
    INT2b: 0060/5
    INT2ic: 0080/2

    MLT0+: 0100
    MLT0-: 0127
    MLT0a: 0060/6
    MLT0b: 0060/7

    MLT1+: 0101
    MLT1a: 0060/8
    MLT1b: 0060/9

    SUM0-: 0120
    SUM0+: 0124
    SUM0a: 0060/a
    SUM0b: 0060/b

    SUM1-: 0121
    SUM1+: 0125
    SUM1a: 0060/c
    SUM1b: 0060/d

    SUM2-: 0122
    SUM2a: 0060/e
    SUM2b: 0060/f

    XBAR16: 0040
        - +1
        - -1
        - SUM2-
        - SUM1+
        - SUM1-
        - SUM0+
        - SUM0-
        - MLT1+
        - MLT0+
        - MLT0-
        - INT2-
        - INT1+
        - INT1-
        - INT0+
        - INT0-
        - INT0a
        - INT0b
        - INT1a
        - INT1b
        - INT2a
        - INT2b
        - MLT0a
        - MLT0b
        - MLT1a
        - MLT1b
        - SUM0a
        - SUM0b
        - SUM1a
        - SUM1b
        - SUM2a
        - SUM2b
        INT1ic: +.1 # Must start with + or -!
        ic: 20
        op: 400
        INT1a: .25
        INT2a: .2
        MLT0a: 1
        MLT0b: 1
        MLT1a: 1
        MLT1b: 1
        SUM0a: .02
        SUM0b: .08
        SUM1a: .1
        SUM1b: .25
        INT1a: INT2-
        INT2a: SUM0-
        MLT0a: INT1-
        MLT0b: INT1-
        MLT1a: INT2-
        MLT1b: SUM1-
        SUM0a: INT1-
        SUM0b: MLT1+
        SUM1a: MLT0+
        SUM1b: -1

The setup shown above will not fit your particular analog computer configuration; it just serves as an example. The remaining parameters nevertheless apply in general and are mostly self-explanatory. 'poll_interval' and 'poll_attempts' control how often this interface will poll the hybrid controller to get a response to a command issued before. The values shown above are overly pessimistic but this won't matter during normal operation.

If the number of values specified in the array 'values' does not match the number of configured potentiometers, the function will abort.

The 'types' section contains the mapping of the devices types as returned by the analog computer's readout system to their module names. This should not be changed but will be expanded when new analog computer modules will be developed.

The 'elements' section contains a list of computing elements defined by an arbitrary name and their respective address in the computer system. Calling read_all_elements() will switch the computer into HALT-mode, read the values of all elements in this list and return a reference to a hash containing all values and IDs of the elements read. (If jitter during readout is to be minimized, a readout-group should be defined instead, see below.)

Ideally, all manual potentiometers are listed under 'manual_potentiometers' which is used for automatic readout of the settings of these potentiometers by calling read_mpts(). This is useful, if a simulation has been parameterized manually and these parameters are required for documentation purposes or the like. Caution: All potentiometers to be read out by read_mpts() must be defined in the elements-section.

The new() function will clear the communication buffer of the hybrid controller by reading and discarding and data until a timeout will be reached. This currently equals the product of 'poll_interval' and 'poll_attempts' and may take a few seconds during startup.


In some cases, e.g. external HALT conditions, it is necessary to query the hybrid controller for any messages which may have occured since the last command. This can be done with this method - it will poll the controller for a period of 'poll_interval' times 'poll_attemps' microseconds. If this timeout value is not suitable, a different value (in milliseconds) can be supplied as first argument of this method. If this argument is zero or negative, get_response will wait indefinitely for a response from the hybrid controller.


This method switches the analog computer to IC (initial condition) mode during which the integrators are (re)set to their respective initial value. Since this involves charging a capacitor to a given value, this mode should be activated for the a minimum duration as required by the time scale factors involved.

ic() and the two following methods should not be used when timing is critical. Instead, IC- and OP-times should be setup explicitly (see below) and then a single-run should be initiated which will be under control of the hybrid controller. This avoids latencies involved with the communication to and from the hybrid controller and allows sub-millisecond resolution.


This method switches the analog computer to operating-mode.


Calling this method causes the analog computer to switch to HALT-mode. In this mode the integrators are halted and store their last value. After calling halt() it is possible to return to OP-mode by calling op() again. Depending on the analog computer being controlled, there will be a more or less substantial drift of the integrators in HALT-mode, so it is advisable to keep the HALT-periods as short as possible to minimize errors.

A typical operation cycle may look like this: IC-OP-HALT-OP-HALT-OP-HALT. This would start a single computation with the possibility of reading values from the analog computer during the HALT-intervals.

Another typical cycle is called 'repetitive operation' and looks like this: IC-OP-IC-OP-IC-OP... This is normally used with the integrators set to time-constants of 100 or 1000 and allows to display a solution as a more or less flicker free curve on an oscilloscope for example.


During a normal computation on an analog computation there should be no overloads of summers or integrators. Such overload conditions are typically the result of an erroneous computer setup (normally caused by wrong scaling of the underlying equations). To catch such problems it is usually a good idea to switch the analog computer automatically to HALT-mode when an overload occurs. The computing element(s) causing the overload condition can the easily identified on the analog computer's console and the variables of the computation run can be read out to identify the cause of the problem.


Calling this method will disable the automatic halt-on-overload functionality of the hybrid controller.


Sometimes it is necessary to halt a computation when some condition is satisfied (some value reached etc.). This is normally detected by a comparator used in the analog computer setup. The hybrid controller features an EXT-HALT input jack that can be connected to such a comparator. After calling this method, the hybrid controller will switch the analog computer from OP-mode to HALT as soon as the input signal patched to this input jack goes high.


This method disables the HALT-on-overflow feature of the hybrid controller.


Calling this method will initiate a so-called 'single-run' on the analog computer which automatically performs the sequence IC-OP-HALT. The times spent in IC- and OP-mode are specified with the methods set_ic_time() and set_op_time() (see below).

It should be noted that the hybrid controller will not be blocked during such a single-run - it is still possible to issue other commands to read or set ports etc.


This function behaves quite like single_run() but waits for the termination of the single run, thus blocking any further program execution. This method returns true, if the single-run mode was terminated by an external halt condition. undef is returned otherwise.


This initiates repetitive operation, i.e. the analog computer is commanded to perform an IC-OP-IC-OP-... sequence. The hybrid controller will not block during this sequence. To terminate a repetitive run either ic() or halt() may be called. Note that these methods act immediately and will interrupt any ongoing IC- or OP-period of the analog computer.


This function switches the analog computer to POTSET-mode, i.e. the integrators are set implicitly to HALT while all (manual) potentiometers are connected to +1 on their respective input side. This mode can be used to read the current settings of the potentiometers.


It is normally advisable to let the hybrid controller take care of the overall timing of OP and IC operations since the communication with the digital host introduces quite some jitter. This method sets the time the analog computer will spend in IC-mode during a single- or repetitive run. The time is specified in milliseconds and must be positive and can not exceed 999999 milliseconds due to limitations of the hybrid controller firmware.


This method specifies the duration of the OP-cycle(s) during a single- or repetitive analog computer run. The same limitations hold with respect to the value specified as for the set_ic_time() method.


This function expects the name of a computing element specified in the configuation YML-file and applies the corresponding 16 bit value $address to the address lines of the analog computer's bus system, asserts the active-low /READ-line, reads one value from the READOUT-line, and de-asserts /READ again. read_element(...) returns a reference to a hash containing the keys 'value' and 'id'.


This function expects the 16 bit address of a computing element as parameter and returns a data structure identically to that returned by read_element. This routine should not be used in general as computing elements are better addressed by their name. It is mainly provided for completeness.


get_data() reads data from the internal logging facility of the hybrid controller. When a readout group has been defined and a single_run is executed, the hybrid controller will gather data from the readout-group automatically. There are 1024 memory cells for 16 bit data in the hybrid controller. The sample rate is automatically determined.


The routine read_all_elements() reads the current values from all elements listed in the 'elements' section of the configuration file. It returns a reference to a hash containing all elements read with their associated values and IDs. It may be advisable to switch the analog computer to HALT mode before calling read_all_elements() to minimize the effect of jitter. After calling this routine the computer has to be switched back to OP mode again. A better way to readout groups of elements is by means of a readout-group (see below).


This function defines a readout group, i.e. a group of computing elements specified by their respective names as defined in the configuration file. All elements of such a readout group can be read by issuing a single call to read_ro_group(), thus reducing the communications overhead between the HC and digital computer substantially. A typical call would look like this (provided the names are defined in the configuration file):

    $ac->set_ro_group('INT0_1', 'SUM2_3');


read_ro_group() reads all elements defined in a readout group. This minimizes the communications overhead between digital and analog computer and reduces the effect of jitter during readout as well as the risk of a serial line buffer overflow on the side of the hybrid controller. The function returns a reference to a hash containing the names of the elements forming the readout group with their associated values.


In addition to these analog readout capabilities, the hybrid controller also features eight digital inputs which can be used to read the state of comparators or other logic elements of the analog computer being controlled. This method returns an array-reference containing values of 0 or 1 for each of the digital input ports.

digital_output($port, $value)

The hybrid controller also features eight digital outputs which can be used to control the electronic switches which are part of the comparator unit. Calling digital_output(0, 1) will set the first (0) digital output to 1 etc.


set_xbar creates and sends a configuration bitstream to an XBAR-module specified by its name in the elements section of the configuration file. The routine is called like this:

    xbar(name, config-string);

where name is the name of the XBAR-module to be configured and config-string is a string describing the mapping of output lines to input lines at the XBAR. This string consists of 16 single hex digits or '-'. Each digit/'-' denotes one output of the XBAR-module, starting with output 0. An output denoted by '-' is disabled.

To connect output 0 to input B and output 2 to input E while all other outputs are disabled, the following call would be issued:

xbar(name, 'B-E-------------');


Calling read_mpts() returns a reference to a hash containing the current settings of all manual potentiometers listed in the 'manual_potentiometers' section in the configuration file. To accomplish this, the analog computer is switched to POTSET-mode (implying HALT for the integrators). In this mode, all inputs of potentiometers are connected to the positive machine unit +1, so that their current setting can be read out. ("Free" potentiometers will behave erroneously unless their second input is connected to ground, refer to the analog computer manual for more information on that topic.)

set_pt($name, $value)

To set a digital potentiometer, set_pt() is called. The first argument is the name of the the digital potentiometer to be set as specified in the elements section in the configuration YML-file (an entry like 'DPT24-2: 0060/2'). The second argument is a floating point value 0 <= v <= 1. If the potentiometer to be set can not be found in the configuration data or if the value is out of bounds, the function will die.


Read the current setting of all digital potentiometers. Caution: This does not query the actual potentiometers as there is not readout capability on the modules containing DPTs, instead this function will query the hybrid controller to return the values it has stored when DPTs were set.


Calling get_status() yields a reference to a hash containing all current status information of the hybrid controller. A typical hash structure returned may look like this:

    $VAR1 = {
          'IC-time' => '500',
          'MODE' => 'HALT',
          'OP-time' => '1000',
          'STATE' => 'NORM',
          'OVLH' => 'DIS',
          'EXTH' => 'DIS',
          'RO_GROUP' => [..., ..., ...],
          'DPTADDR' => [60 => 9, 80 => 8, ], # hex address and module id

In this case the IC-time has been set to 500 ms while the OP-time is set to one second. The analog computer is currently in HALT-mode and the hybrid controller is in its normal state, i.e. it is not currently performing a single- or repetitive-run. HALT on overload and external HALT are both disabled. A readout-group has been defined, too.


In some applications it is useful to be able to determine how long the analog computer has been in OP-mode. As time as such is the only free variable of integration in an analog-electronic analog computer, it is a central parameter to know. Imagine that some integration is being performed by the analog computer and the time which it took to reach some threshold value is of interest. In this case, the hybrid controller would be configured so that external-HALT is enabled. Then the analog computer would be placed to IC-mode and then to OP-mode. After an external HALT has been triggered by some comparator of the analog commputer, the hybrid controller will switch the analog computer to HALT-mode immediately. Afterwards, the time the analog computer spent in OP-mode can be determined by calling this method. The time will be returned in microseconds (the resolution is about +/- 3 to 4 microseconds).


The reset() method resets the hybrid controller to its initial setup. This will also reset all digital potentiometer settings including their number! During normal operations it should not be necessary to call this method which was included primarily to aid debugging.

store_data() stores data gathered from an analog computer run into a file. If no arguments are supplied, the data is read from the current object where it has to have been stored by previously invoking get_data().

If external data and/or an external filename should be used these are expected as optional named parameters as in this example:

store_data(data => [...], filename => 'scratch.dat');

plot() uses gnuplot (which must be installed and be found in PATH) to plot data gathered by get_data(). If no argument is given, it uses the data stored in the ac-object. Otherwise, data can be given as an optional named parameter which consists of a reference to an array which either contains data values or arrays of data tuples in case multiple variables were logged during an analog computer run:

plot(data => [...]);

If the data set to be plotted contains two element tuples, a phase space plot can be created by specifying the named parameter type:

plot(type => phase);

Alternatively, a 3D-plot can be created by specifying

plot(type => 3d);

This is useful when partial differential equations are solved with a discretized space.

setup() prepares a problem based on the information contained in the problem section of the configuration YAML-file.


The following example initates a repetitive run of the analog computer with 20 ms of operating time and 10 ms IC time:

    use strict;
    use warnings;

    use File::Basename;
    use HyCon;

    my $ac = HyCon->new();




Dr. Bernd Ulmann,