RUNSTIM Manual
RUNSTIM Version 4.1.3e

Table on Contents

General Description
Hardware and Software Requirements
Linux Port
Settings File
Stimulus Description File
Expressions
Constants
Operators
Functions
Special random sequence functions
Procedures
Defined functions
Variable Names
Built in variables
Arrays
Assignments
Flow Control Statements
Control Statements
Logging Data
Display Settings
Stimulus Control
Object descriptions
Saving images
Sound Support
Preloading Sounds
Record Sound
Calibration Menu
Sound Calibration
Video Calibration
Start Up Controls
Outputting data to LPT port
Interprocess Communication
Miscellaneous
Restrictions
System Lockups
Timing Accuracy
ISI Timing
Projection modes
Built in help
Installation
Other files
Example control file
Example Animation control file


General Description

RUNSTIM is program which can be used to program a variety of visual and auditory stimulus. The program reads a description file containing details of how the stimulus is to be presented, then executes the requested sequence.

Hardware and Software Requirements

DOS

The program will run on any IBM compatible PC with a VESA compliant video card that is at least at version 2. A version 3 card is required if you want to change the video timing.

For sound support, a SoundBlaster (Not Live), Ensoniq Soundscape, Windows Sound System chips or ESS AudioDrive. If your sound card uses a PCI slot (or is a PnP ISA), then you may have problems with MSDOS modes, since it cannot manage resource allocation correctly. Usually you get legacy drivers with the cards, but they may fail to work correctly with the sound library.

You can run the program in a MS_DOS Prompt window under Windoze 95/98/ME (yes I meant to spell it that way!), but it is strongly suggested that you run the experiment in MS-DOS mode (from the shutdown menu) for good timing accuracy.

If you run the program under normal Windoze, there is no guarantee that some utility or network activity will not stall your program and corrupt the timing. To demonstrate this, use the calibration mode under MS-DOS and Windoze and note the occasional flicker of the latter. For this reason, Windoze ME, 2000 and NT is not recommended since they don't support a real MS-DOS mode.

The program is normally installed in a directory called 'C:\RUNSTIM'. Optional calibration data, utility programs and extra text fonts and stored here also. (see installation).

You will need the DPMI memory handling package to run the program. This is provided by Win95/98, but in DOS mode you will need to install the handler. In addition (for DOS mode only) you may need to install mouse and sound card drivers. The recommended package is CWSDPMI version 5 (you may get lockups on earlier versions with newer processor cards).

Linux

  • Kernel 2.6.x (if you use 2.4.x you'll loose timing accuracy)
  • Kernel Preempt and Lock-Break patches (if 2.4.x)
  • XFree86 or Xorg
  • DGA2 Xserver extension
  • XNTP for clock corrections
  • A supported video card for DGA
  • A supported sound card

    Windows XP

  • Video card with DirectX support
  • Sound card with DirectX support
  • TVicPort package to allow direct access to the LPT port (if required)

    Macintosh OS X

    A port should not be hard, but has not been attempted.

    Settings File

    Before RUNSTIM reads the descriptions file, it checks for the existence of a settings file called 'RUNSTIM.SET'. It first looks in the default installation directory 'C:\RUNSTIM', and then in the current directory. If file exist in both, then it uses installation directory copy first, followed by the one in the current directory. Certain commands, such as
    no splash are only effective in settings files.

    Stimulus Description File

    The program must be provided with a description of how the stimulus is to be generated. The file format is flexible, allowing spaces or tabs between command parameters, empty lines and the hash symbol # to introduce comments. If there is a syntax error in a description file, then an error message with the line number is output. If possible, the offending line is also output with a carrot ^ symbol marking the position on the line where the error was encountered.

    In the descriptions that follow, items in braces {...} are optional, and items shown with a vertical bar {xx | yy} are a choice. Italics are used where you provide the information (such a a value for the display size)

    Expressions

    Expressions and variables are allowed in object descriptions. Because they are a late addition to the package, they must be enclosed in square brackets [ ... ]. Variables can be up to 16 characters long, must start with an alphabetic character, and in addition, can contain digits, underscore _ or the dollar symbol $. Internally, variables are can switch between integer and floating point, according to what operations are performed on them.

    In general, most of the operators in the C programming language are supported along with the same operator precedence.

    Constants

    Constants can be integers (decimal, octal or hexadecimal) or floating point. Assignments that only contain constants (or functions with constants) are marked as constant, and don't get reevaluated when the program runs. This can save a substantial amount of CPU time.
    	255		a decimal integer constant
    	0xff		a hexadecimal integer constant
    	0377		a octal integer constant
    	255.0		a floating point constant
    

    You can have single quoted characters where the ASCII code is returned as an integer. Control characters supported are backspace '\b', tab '\t', new line '\n' and carriage return '\r'.

    	'X'		returns 0130
    	'\b'		returns code for backspace
    

    Operators

    Unary-expressionnegate
    !expressionlogical negation
    ~expressionone's complement
    ++variableincrement variable by one before use
    --variabledecrement variable by one before use
    variable++increment variable by one after use
    variable--decrement variable by one after use
    Multiplicativeexpression * expressionmultiply
    expression / expressiondivide
    expression % expressionremainder
    Additiveexpression + expressionadd
    expression - expressionsubtract
    Logicalexpression & expressionbitwise AND
    expression | expressionbitwise OR
    expression ^ expressionbitwise XOR
    Shiftexpression >> expressionshift right
    expression << expressionshift left
    Relationalexpression == expressionequal to
    expression != expressionnot equal to
    expression < expressionless than
    expression > expressiongreater than
    expression <= expressionless than or equal to
    expression >= expressiongreater than or equal to
    expression && expressionlogical AND
    expression || expressionlogical OR

    Functions

    sin(expression)Compute sine value, expression in radians
    cos(expression)Compute cosine value, expression in radians
    asin(expression)Compute arc sine value, result in radians
    acos(expression)Compute arc cosine value, result in radians
    atan(expression)Compute arc tangent value, result in radians
    atan2(exp_y, exp_x)Compute arc tangent of y/x, result in radians
    log(expression)Compute natural logarithm (base e)
    log10(expression)Compute common logarithm (base 10)
    pow(exp_x, exp_y)Raise x to the power of y
    sqrt(expression)Compute square root
    cqrt(expression)Compute cube root
    abs(expression)Compute absolute value
    ceil(expression)Compute smallest integer greater than value
    floor(expression)Compute largest integer less than value
    int(expression)Convert to integer
    float(expression)Convert to floating point
    rand(expression)Generate random number in the range 0 to value
    sizeof(list)Return the number of elements in the list
    defined(identity)Return non-zero if identity exists
    date()Return the current date in seconds since 1/1/1970
    time()Return the time in milliseconds since the experiment started
    day(date)Given a value returned by date, return the current day
    month(date)Given a value returned by date, return the current month
    year(date)Given a value returned by date, return the current year
    hour(date)Given a value returned by date, return the current hour
    minute(date)Given a value returned by date, return the current minute
    second(date)Given a value returned by date, return the current second
    lptdata()Return the state of the current input bits from the LPT port

    Special random sequence functions

    There is a special class of functions that generate random number sequences. They return an array
    rather than just a number. There are two versions:-
    	array_name = randseq(n)
    
    Return an integer array of n elements, with a complete set of integers from 1-n, where each number is only used once, but the order is random.
    	array_name = crandseq(n, levels, behind, end)
    
    This routine will generate a random sequence of numbers (n in total), where the numbers will be in the range of '1 - levels'. The sequence will be constrained so that the cumulative count for each level will not deviate more than behind the total of any other, and finally, if the end sequence has a run of more that end numbers of the same value, then some will be exchanged with earlier values.

    For example, say you want an experiment that has 5 different stimulus conditions, and you want each stimulus to be used exactly 5 times (for a total of 25 trials). Also, you want the sequence to be constrained so that a single stimulus type is not presented more than 3 times is a row (which is possible if the numbers are truely random), then the following code will generate the required sequence, and leave the values in the array result, array indexes 0 - 24 (ie 0 to n - 1), values 1 - nlevels

    	result = crandseq(25, 5, 3, 3)
    
    Note that the n must be divisible levels without any remainder

    Procedures

    Procedures can be declared at the beginning of the stimulus control file. Each procedure can be called with up to four parameters, which can be accessed with using the dummy variables $1 to $4. The number of parameters that a procedure is called with is available in the local variable $?. You can specify when a procedure is declared an exact number of parameters.
    
    #	procedure must have exactly two parameters
    
    procedure sumate2(2)
    {
    	sum = $1 + $2
    }
    
    #	procedure with a variable number of parameters
    
    procedure sumate
    {
    	if $? == 1
    		sum = $1
    	elseif $? == 2
    		sum = $1 + $2
    	elseif $? == 3
    		sum = $1 + $2 + $3
    	else
    		sum = $1 + $2 + $3 + $4
    	endif
    }
    
    #	procedures must be declared before they are used.
    
    sumate(1,2)
    sumate(1,2,3)
    
    
    You can use up to four local variables named @1 to @4. These variables are local to the procedure and their value are nots affected by their use in other procedures or functions. See note on variable/procedure names below for restrictions

    The return statment can be used to exit a procedure at any point.

    Defined functions

    You can declare a procedure that returns a value. In all other ways it is identical to a procedure, but you must return a value.
    
    #	the recursive use of functions and procedures
    #	to print the value of an integer, one digit at
    #	a time
    
    #	return the quotient after dividing by 10
    
    function div10(1)
    {
    	return $1 / 10
    }
    
    #	return the remainder after dividing by ten
    
    function rem10(1)
    {
    	return $1 % 10
    }
    
    procedure printn(1)
    {
    	@1 = div10($1)
    	if @1
    		printn(@1)
    	endif
    	print "%c" rem10($1) + '0'
    }
    
    

    Variable Names

    Variable names can be up to 15 characters long, but must start with an alphabetic letter. Names may include digits, underline '_' or the dollar sign '$'.

    Note:- Variable or procedure names must not clash with names used by any of the RUNSTIM commands or inbuilt functions. The name 'save' would clash with the statement 'save bitmap' or 'save screen'. You will get an error if there is a name clash.

    Built in variables

    xsizeScreen dimension for x in pixels
    ysizeScreen dimension for y in pixels
    pi3.1415926535897932385...
    last_key_asciiLast valid keyboard code in ASCII
    last_key_scanLast valid keyboard code as scan code
    last_key_timeTime of last valid keyboard press
    last_key_countCount of keyboard event captured
    last_mouse_codeLast valid mouse button code
    last_mouse_timeTime of last valid mouse button press
    last_mouse_cntCount of mouse events captured (note spelling cnt)
    last_ext_changeLast external event change
    last_ext_timeTime of last external event change
    last_ext_countCount of external events captured
    last_stim_timeTime of the last stimulus onset
    last_xLast x coordinate used by an object (eg end of line)
    last_yLast y coordinate used by an object
    last_line_valThe value of the last numeric string resulting from a prompt or promptk.
    keyboard_bufferAn array of ASCII integers from the last prompt command.
    linuxDefined if operating system is Linux
    windowsDefined if operating system is Windoze
    msdosDefined if operating system is MESSYDOS
    macosxDefined if operating system is Macintosh OS X
    DEBUGDefined if command line debug mode is set
    NO_PAUSEDefined if command line 'no pause' mode is set

    The keyboard and mouse data are for presses that are waited for.

    Arrays

    Single dimensioned arrays are allowed, but must be declared first. Unlike other variables, the type (integer or floating point) is fixed. Array indices start are zero and extent to the size specified. So, declaring an array size of 10, results in 11 elements (0 - 10). You cannot use the same name for an array and an ordinary variable.
    array int ivals[32]
    array float ivals[size]
    

    Arrays may be initialised. The declaration my extend over more than one line.

    array int data[] = { 1,2,3,4}
    array float fdata[] = { 1.0
                            2.0 }
    

    Assignments

    Assignments are made using the = operator. If the expression only contains constants, then the result is marked constant and does not need to be reevaluated if used again. An assignment can be marked as constant to ensure that the value cannot be changed without errors. There is no need for square brackets [...] in assignment statements.

    Variables are stored either as integers or floating point, depending on the value. By default they are integer, but any operation that involves a floating point operation (eg a constant .22, or trigonometric function) will convert the result to floating point. Note, floating point calculations take longer than integers, so don't use them unless required.

    x = 22			# an assignment that will be marked as constant
    y = sin(pi / 2)		# the result is still a constant
    x = y + 10		# this is not constant, since y may change
    constant size = 640	# mark as a constant that cannot be changed
    z = 0.22		# this is a constant, and is stored as a floating point number
    

    Flow Control Statements

    if logical test

    The logical test is evaluated, and if the result is true (non-zero), then the following statements are executed. If false, a jump is made to the one of the following :-

    elseif logical test

    Apply an second logical test if the first one fails. These may be nested

    else

    If the logical test fails for an if statement (or all elseif's, then the following code is executed

    endif

    Mark the end of an if statement.
    if x == 1
    	...	# reached if x = 1
    elseif x == 2
    	... 	# reached if x = 2
    else
    	...	# reached for any other value
    endif
    

    block

    This statement is used to mark the beginning of a repeat or while block of commands. They can be nested (blocks within blocks)

    repeat expression

    This terminates a block statement, and will loop n times through the statements between block/repeat pairs.
    block
    	...
    	...
    	block
    		...	# this gets executed 10 times (5 x 2)
    	repeat 5
    repeat 2
    

    repeat sizeof list

    In RUNSTIM, there is the concept of
    lists, which may be a set of images, objects or sounds. The number of entries in the list is used as the repeat count.
    block
    	display stim.lst ...
    repeat sizeof stim.lst
    

    while logical test

    A while statement can also terminate a block loop. Note that one iteration will always be made.
    x = 1
    block
    	...
    	...
    	x = y
    while x < 10
    

    for variable = expression; logical test {; increment statement}

    This statement is used to control a program loop. The first statement is always executed, then the logical test is applied before each iteration, and the optional increment statement is applied after each iteration. Note that is possible for the logical test to not allow even one iteration.

    next

    Marks the final statement for a for loop.

    continue

    Allow a jump to the end of a for loop for then next iteration.
    for x = 0; x < 10; x++
    	...
    	...
    	if x == y
    		continue
    	endif
    	...
    	...
    next
    

    exit [ status_value ]

    Unconditionally terminate the program. An optional exit status is allowed (default 0) that can be tested in batch or shell scripts.

    goto label

    Unconditionally go to the first statement after label. Labels are lines that begin with a colon :, followed by a name that will be used to reference it.

    Control Statements

    isi nn.n

    Set the inter-stimulus interval to nn.n seconds. There is an implied ISI between every stimulus presentation. The time is measured in seconds. You must specify an ISI interval as there is no default value.
    isi	1.5		# set the ISI to 1.5 seconds
    

    isi xx.x - yy.y

    Generate a randomised inter-stimulus interval in the range from xx.x to yy.y. Each trial will have a different ISI interval within the specified range.
    isi	1.0 - 3.0 	# set the ISI to a random value
    

    initial isi nn.n

    Set the initial delay before the first trial to nn.n. The default value is 5 seconds, but it can be set to 0 if no delay is required.

    randomise

    Use this statement to truly randomise the experiment, so that for each subject, the random image selection and ISI times will be different for each run.

    Without this option, a pseudo-random sequence is generated, but the same sequence is calculated for each run, which can be handy for debugging the program.

    seed n

    Seed the random number generator with the value n. If you use the same seed, the same random sequence is generated.

    prompt {"Text of message"}

    This statement will pause and wait for the return key to be pressed. If there was no text message provided, the message is defaulted to Ready.
    prompt "Ready for Part 1"
    
    Any types response is stored in the array keyboard_buffer, and any initial numeric string is stored in last_line_val.

    prompt [xposition] [yposition] {"Text of message"}

    Normaly, prompt will position the string ast the bottom of the screen. You may specify the position of the text in the prompt string.

    promptk

    Normally, the prompt command will erase any text, and typed characters when it returns. the promptk version will keep any text generated.

    path directory path

    Use this statement to tell RUNSTIM to look in directory path to find image files, lists etc. This avoids cluttering up the directories with lots of files. path is remembered in the current context and may be changed between statements
    path stimulus_1
    display list1.lst ...
    path different_directory
    display list2.lst
    

    font font_name

    Set the current font to font_name. The font may be a GRX font file (.fnt) or a bitmap (.bmp or .pcx). The program will look in runstim default font list, or the file set by the font library directive. The special font name system will restore the default font. If the font is a .fnt or .pcx file, you can leave the extension off.

    To get a list of inbuilt fonts (and all command and object names) type :-

    runstim -h
    
    The font names are encoded as cw for constant width (courier) or r for proportionally spaced width (Roman Times), followed by the pixel width and then r for regular or b for bold. (see the file fontlib.txt provided with your software distribution for a list of fonts)

    font library file_path

    Set the name of the library file to find fonts in.

    Logging Data

    Data can optionally be recorded in a datafile. Each line is time stamped, the resolution of with is determined by the
    clock rate.

    datafile filename

    RUNSTIM can optionally record the onset of the stimulus, and responses from the the program. If the specified file exists, it will ask you if you want to append to the end of the file, replace it or silently do either (see open mode)

    datafile prompt

    Prompt on the keyboard for the name of a file to be used to log data.

    open mode [ask | replace | append]

    Set the action to be taken if the datafile specified already exists. By default, the program will prompt for an action on the screen. You can explicitly set the action (without prompting) to either replace the file (loosing the previous contents), or append to the end of the file.

    log mode verbose | concise

    The data log file can be quite verbose in the output it generates as various stimulus is outputed. If you elect to have concise mode, only text from log statement will be generated.

    key enable { up | down | both } nnn

    This statement will enable the keyboard for the next trial for nnn milliseconds after the onset of the stimulus, and record any key presses in the data file. For each statement that your want to record responses from, precede it with this statement.

    You can optionally specify that you want to record keys being released (up), pressed (down) or either (both). The default is down.

    block
    	display ...	# no response measured
    	key enable down 500
    	display ...	# collect responses for key presses
    	display		# no response measured
    repeat ...
    

    Note

    If you use preloaded screens, and then use display with a sleep 0 to generate an image sequence without ISI's, then the enable will extend over all the display statements until the specified time is up, or if isi was used, the whole interval.

    key enable { up | down | both } isi

    This is similar to the previous statement, but will collect data for the whole inter-stimulus interval.

    key enable { up | down | both }

    A key enable without a time period or isi will leave the keyboard permanently enabled so that all presses thoughout the experiment will be recorded.

    key disable

    This will disable the recording of subsequent key presses.

    mouse enable { up | down | both } nnn

    Similar to the key enable statement, but enables the mouse instead (you can enable both the keyboard and mouse if required)

    mouse enable { up | down | both } isi

    Similar to the key enable isi statement, but enables the mouse instead.

    mouse enable { up | down | both }

    A mouse enable without a time period or isi will leave the mouse permanently enabled so that all presses thoughout the experiment will be recorded.

    mouse disable

    This will disable the recording of subsequent mouse presses.

    external enable [+-=^] data ... nnn

    Similar to the key enable statement, but enables the input from the LPT port. The first character specifies when a change is detected, where + means rising edge, - means falling edge, = means exact match, ^ means XOR (or change) and data is used as a mask, and can be decimal, octal or hexadecimal according to the leading digit (0 is octal, 0x is hexadecimal, otherwise an integer).

    You can specify multiple combinations of change detection by using several operators. Only the last external enable will ever be active.

    external enable [+-=^] ... data isi

    Similar to above, but the time interval is the isi.
    	external enable + 0x80 isi	# look only at the rising edge of a single
    					# input bit
    	display image.gif 1000		# display image, collect data from LPT port
    
    	external enable + 0x80 - 0x40	# detect rising bit (0x80) or falling bit (0x40)
    	display image.gif 1000
    

    external enable [+-=^] ... data

    A external enable without a time period or isi will leave the external input permanently enabled so that all external changes selected will be recorded.

    external disable

    This will disable the recording of subsequent external data changes.

    log comment "comment text"

    This will log a date stamped comment to the output file.

    log data "format" { expressions }

    Log formatted data to the output file using the same parameters as the
    print statement.

    Display Settings

    vesa

    Normally, the program expects a VESA version 3 compliant video display card. If your card is only version 2, use this command to stop the program aborting. It is not possible to change the video refresh rate unless you have a version 3 card.

    local

    In local mode, the computer does all the timing for generating the stimulus. In remote mode, a second computer sends the timing commands for the stimulus generation. The timing accuracy is vastly reduced in remote mode. The default moded is local.

    remote

    As described in local mode, remote mode waits for commands from a remote computer before it initiates stimulus changes. This is legacy code for a research project at Westmead Hospital, do not expect this to work in any other environment. See
    waitexternal for the new method of handling external triggers.

    lpt n

    Set the parallel port number used for communicating with the remote computer. Only used in remote, waitexternal or strobe mode. The default port number is 1.
    lpt	2
    

    xsize nnn & ysize nnn

    Use this pair of commands to set the vertical and horizontal size of the display. The default is 640x480. Your video card MUST support any mode you select. Use the following command to discover the available combinations.
    runstim -m | more
    
    To set a higher resolution display :-
    xsize	1024
    ysize	768
    

    vrate nnn

    Set the vertical refresh rate to nnnHz. The rate you choose has be compatible with your display card and monitor. It is possible to permanently damage your display if your select a rate that is TOO high. A rate of 100 is handy, since each refresh takes 10ms. You must have a VESA version 3 display card to use this command.
    vrate	100
    

    depth 8 | 15 | 16 | 24 | 32

    You can set the colour depth of the display to any of the above values. Any depth other than 8 encodes the colours directly for each pixel. If you choose a depth of 8, a palette is required, and there are restrictions on the combinations of colours allowed for images (see restrictions). The amount of memory required for an image increases as the display depth increases. The default is 16.
    depth 16
    

    colour name r,g,b

    Add a new entry into the colour table, and associate the colour name with the values for red, green and blue in the range 0-255.
    colour orange 127, 63, 0
    

    background

    Revert to the background screen.

    background r,g,b

    Set the background for the ISI to the colour represented as red, green and blue values in the range 0-255.
    background 127,127,127		# a grey background
    

    background colour

    Set the background to a named colour. The colour must be inbuilt (black, white, grey, red, green, blue or yellow), or set using the
    colour command.
    background grey
    

    background image filename

    Load the image contained in the file and use it as the background.

    background sample filename

    Set the background colour from pixel 0,0 of the image contained in the file.

    fill colour colour | r,g,b

    Set the colour to fill the background of an image that is smaller than the screen size.

    sample colour x y

    Sample the colour at coordinate x,y and use it to fill the background of an image that is smaller than the screen size.

    foreground r,g,b

    Set the foreground for the ISI to the colour represented as red, green and blue values in the range 0-255.
    foreground 255,255,255		# a white foreground
    

    foreground colour

    Set the foreground text and object colour to the named colour. The colour must be inbuilt (black, white, grey, red, green or blue), or set using the
    colour command.
    foreground white
    

    image mask filename

    The image contained in filename will be applied as a mask over any image (or object) displayed, not including the background. Black areas in the mask when it is applied to the image will be left as the current background. White areas in the mask will allow the image to be seen.

    image mask object

    Generate an image mask using an object list
    image mask object
    circlefill 340 280 200	#apply a circular mask to all images
    end object
    

    image mask on

    Turn the image mask on (if it was off)

    image mask off

    Turn the image mask off (if it was on)

    Image Specifications

    There are several ways to specify an image. Images must be that same size or smaller than the selected screen size. If the image is smaller, it is centred, and the colour of the pixel at 0,0 in the image is used to fill in the background.

    The image specification consists of a filename, followed by either the presentation time in milliseconds or the key words waitkey, waitmouse, waitexternal or nowait which will keep the display image on until a waited event occurs, whereupon the program will move to the next command. waitkey and waitmouse will wait until a key or mouse button is pressed.

    waitexternal will wait for an external signal from the printer port. The syntax is:-

    waitexternal +|-|0|1|=|^ mask

    where + means rising edge, - means falling edge, 0 means all bits must be zero (or low) and 1 means all bits must be one (or high). The = means exact match ^ means XOR (or change) mask is used as a mask, and can be decimal, octal or hexadecimal according to the leading digit (0 is octal, 0x is hexadecimal, otherwise an integer). You can specify multiple combinations of detection patterns :-

    The display time keyword nowait will make display leave the image on the screen and immediately return, without restoring the background. When used in combination with bitmaps and objects, dynamic displays can be generated.

    Note that the system will wait for the beginning of the next video refresh before it will switch images. Therefore, when animating at full refresh rate, there is no need to interpose 'wait refresh' commands to stay synchronised.

    A optional offset can be specified. The offset must be followed by a comma separated x,y offset, or the keyword random which will use a randomly selected offset from a list. Finally, stimulus onset can be signaled to another computer by using the word strobe followed by a data value, which make be an expression enclosed in square brackets or a constant.

    The filename extension ('.' followed by the last three characters) is used to determine the type of file being read, either an image file, list or objects. The filename may be specified as follows:-

    filename.??? The name of a file in BMP, GIF, LBM, PCX or TGA format. (Filenames have the current path prepended to them before being read.)
    background Display the current background (used mainly for preload modes)

    filelist.lst A file containing a list of files to be randomly selected. The entry is cached, so if the list is mentioned more than once, the same list is used (and shared). Comments '#' and empty lines allowed. Since the file selection in random, an image may be selected more than once.
    filelist.lst once_only This is a variation of a list where an entry is randomly selected, but only ever used once. You will get a fatal error if you try to read more images than listed in the file. Use the sizeof option in the repeat command to avoid this problem.
    filelist.lst sequential This mode is mainly used for debugging the display. The list isn't randomised, and the images are displayed in the same order as in the list.

    filelist.lst [expression] Select an image using the value of the expression as an index into the list (starting at 1). If you mix this with once_only modes with the same list, the size and order of the list will change!

    objectlist.obj A file containing a list of objects, otherwise the same as filelist.lst.

    objectlist.obj once_only The same as filelist.lst once_only, but containing a list of objects instead of images.

    objectlist.lst sequential This mode is mainly used for debugging the display. The list isn't randomised, and the objects are generated in the same order as in the list.

    objectlist.lst [expression] Select an object using the value of the expression as an index into the list.

    strobe data_value This must be the last option in the specification. The data_value will be sent to the remote computer on the onset of the stimulus, and held until the stimulus offset. The value may be an expression enclosed in square brackets or a constant.

    inbuilt There are several inbuilt images used mainly for testing :- inbuilt.left_box, inbuilt.right_box, inbuilt.centre_box (inbuilt.center_box), inbuilt.border, inbuilt.foreground, inbuilt.background. The colours used are the current foreground and background values, which can be changed by the appropriate statements (see foreground, background). An '_inverse' can be added to invert colours, but it only makes sense for 'boxes', eg inbuild.left_box_inverse
    objectAn inline object, see objects. Inline objects must be terminated by an end object statement.

    In full :-

    
    	imagefile.ext time_in_milliseconds {offset {x,y | random} {strobe data_value}
    	imagefile.ext { waitkey | waitmouse | waitboth | waitexternal }
    	
    	listfile.lst {once_only | sequential} time_in_milliseconds {offset {x,y | random} {strobe data_value}
    	listfile.lst {once_only | sequential} waitmouse {offset {x,y | random} {strobe data_value}
    
    

    Examples :-

    	display file.pcx 30				# a single image for 30ms
    	display list.lst 100				# select a random image from a list
    	display list.lst once_only 100			# select a random image from a list
    							# but only once for each image
    	display object 100				# an inline object
    		circle ...
    		ellipse ...
    	end object
    	display object.obj 100				# select from a list of objects
    	
    	display calibrate.pcx waitkey			# display a calibration screen and 
    							# wait for a keypress to continue
    
    	display background waitexternal + 0200		# display the background until the Busy bit (bit 7)
    							# goes from 0 to 1 on the printer port
    	display background waitexternal + 0x80 - 0x40	# detect two different bits
    	display type1.pcx 100 strobe [sdata+0100]	# display and send data to remote computer
    	display list.lst [20] 100			# display image 20 from the list
    	flash type1.pcx 100 type2.pcx strobe 1		# flash and send data to remote computer
    							# only on the second of the two images
    

    The offset is introduced by the keyword offset, followed either by a x,y value (offset from the centre), or the keyword random, where the offset in randomly selected from a list built from offset statements

    	offset 100,100				# generate some offset table entries
    	offset 100,-100
    	offset -100,-100
    	offset -100,100
    
    	display file.pcx 30 offset -100, -100	# offset up and to the left
    	display file.pcx 30 offset 100, -100
    
    	display file.pcx offset random		# select a random offset
    						# from a list
    

    sleep nn.n

    Sleep for nn.n seconds. This time will replace the ISI for one trial. There is a special case of having a sleep value of zero between display commands (see
    special display timing)

    wait refresh expression

    The expression is evaluated and the number used to count how many display refreshes to wait before returning. Note that unlike using sleep or the ISI, wait refresh does not allow the next image to be loaded by waiting for the time to elapse.

    duplicate original.lst new.lst

    You can duplicate list of images or objects. This is handy if you want to use a once_only list in more than one place, and want to have all the items in the list available.

    Under normal circumstances, a once_only used more than once will only allow one use of each item.

    nop

    No Operation.... Do nothing. There will be an ISI delay.

    Stimulus Control

    preload screen{1-n} image_specification

    Preload an image during the ISI, and store it in one of the available screens (a minimum of three is usually available). A subsequent display screen{1-n} will display it.

    preload screen[expression] image_specification

    Load the screen specified by the expression.

    preload bitmap{1-10} object

    This loads an object (either a list or inline objects) into an internal bitmap, that can subsequently be loaded by a sprite or sprite rotated object command. This allows you to build a common image, and either rotate it or offset it on the screen in other object lists. The images are rendered on a transparent background so that they can be overlayed onto other images.

    preload background object

    Load into the background bitmap.

    preload bitmap[expression] object

    Load the bitmap specified by the expression, in the range 1-10

    display image_specification

    preload bitmap[expression] object

    Load the bitmap specified by the expression, in the range 1-10

    display image_specification

    Display an single image.
    	display image.pcx 100		# single image for 100 milliseconds
    

    display screen{1-n}

    Display the specified screen, using the settings previously provided by a preload command.
    	preload screen1 image.lst once_only 100
    	preload screen2 image.lst once_only 200
    	preload screen3 image.lst once_only 300
    
    	display screen1
    	sleep 0.1
    	display screen2
    	sleep 0.2
    	display screen3
    	sleep 0.3
    OR
    
    	display screen1		# animate a sequence without
    	sleep 0			# delays between images
    	display screen2		# and don't revert to background
    	sleep 0			# between images
    	display screen3
    	sleep 0
    	
    

    flash image_specification_1 image_specification_2

    Flash two images, one immediately after the other
    	flash image_1.pcx 100 image_2.pcx 10 # flash image 1 for 100 ms, 
    					     # followed by image 2 for 10ms
    

    movie listfile frame_time

    Play a list file (or objects) as a movie.
    	movie list.lst 20		# play list as movie, each frame for
    					# 20 milliseconds
    

    movie listfile frame_time repeat_count

    Play a list file (or objects) as a movie, and repeat the sequence repeat_count times.
    	movie list.lst 20 2		# play list as movie, each frame for
    					# 20 milliseconds, twice
    

    movie listfile {waitkey | waitmouse}

    Play a list file (or objects) continuously as a movie until a keyboard or mouse button is pressed.
    	movie list.lst 20 waitkey	# play list as movie, each frame for
    					# 20 milliseconds, until key is pressed
    

    movie screenx - screeny frame_time {repeat_count}

    Play a movie of preloaded screens, x to y inclusive. Each will be displayed for frame_time milliseconds, and the sequence can optionally be repeated repeat_count times.

    movie screen[expression] - screen[expression] frame_time {repeat_count}

    Play a movie of preloaded screens, using expressions for the start and end screen numbers.

    preload movie object_list.obj

    Preload a movie from an object list into memory. List can use a huge about of memory

    preload movie[number] object_list.obj

    Preload a movie into numbered memory cache (1-10). Movies can be overwritten, an change size.

    movie[number] frame_time {repeat_count}

    Play a previously cached movie
    If you have a complex object list to render, and you machine is not fast enough to get it done within the presentation time, then you can render it into a cache, which will happen in the ISI interval (which must be large enough).
    	preload movie[1] object_list_a.obj
    
    	movie[1] 10
    

    object background single object description

    Draw a single object on the background screen.
    	object background line 0 0 100 100 colour white
    

    object screen{1-n} single object description

    Draw a single object on the specified screen screen.

    object screen[expression] single object description

    Draw a single object on the specified screen screen.

    Object Descriptions

    Instead of loading image files, RUNSTIM can draw images using graphical primitives from a description. There can be several items in each image, and they can be either a separate description file ending in .obj which will always be treated as a list, or the object can be inline or embedded in other descriptions. In the latter case, it is always considered a single image.

    The object is drawn using the current foreground and background colours, but the foreground colour can be overridden by adding the keyword colour followed by a name or red, green, blue values. You can also specify the background colour (and foreground) by using the keywords fgcolour or bgcolour.

    Object lists are delineated by the keywords start object and end object (see examples below).

    For convenience, a x y pair may be replaced by the word centred, which will place the object in the middle of the screen (handy for overlaying and rotating sprites) . Runstim also keep track of the last position used in objects (like the end of a line). Use the word last to replace a x,y pair as the start position for an object. The values are also keep the the variables last_x and last_y.

    start object {"comment"}

    Mark the start of a new object in a list. The optional "comment" will be logged to the data file whenever that object is displayed.

    end object

    Mark the end of an object in a list.

    start mask

    You can build a image mask using standard object descriptions. This mask will be applied to the final object image before it is displayed.

    end mask

    Used to mark the end of a mask description.

    object name "name here"

    Name an inline object. The name will be logged in the data file whenever the object is displayed.

    no clear

    This stops the object bitmap being cleared back to the current background. If you want to animate a sequence, this allows you to retain a bitmap image (in conjunction with preload object) and change parts of the image without redrawing the entire bitmap.

    image filename

    Load an image or object list. If an image, all previously draw objects will disappear, and the image will be centred and the background filled.

    mask filename

    Read an image mask from a file (rather than inline with start/stop mask).

    units {global} pixels

    The units for coordinates and radii is pixels and changes with screen size (xsize and ysize). The optional global will make the units setting persist across all objects, not just within the current one. This is the default setting.

    units {global} relative

    The units for coordinates are relative to the centre (0,0), and scale to 1.0 independently of the screen size. The optional global will make the units setting persist across all objects, not just within the current one.

    scale {global} xscale, yscale

    Scale objects using xscale, yscale. The optional global will make the scaling persist across all objects, not just within the current one.

    offset {global} xoffset, yoffset

    Offset objects by xoffset, yoffset. The optional global will make the offset persist across all objects, not just within the current one. The offset is applied after any scaling.

    line x1 y1 x2 y2

    Draw a line from x1, y1 to x2, y2.

    rect x1 y1 x2 y2

    Draw a rectangle with corners at x1, y1 and x2, y2.

    rectfill x1 y1 x2 y2

    Draw a filled rectangle with corners at x1, y1 and x2, y2.

    reverse rect x1 y1 x2 y2

    Within the rectangle specified, reverse the colours. The reversal is based on the current foreground and background colours, not a logical reversal.

    circle x y radius

    Draw a circle centred at x, y of radius.

    circlefill x y radius

    Draw a filled circle centred at x, y of radius.

    reverse circle x y radius

    Within the circle specified, reverse the colours. The reversal is based on the current foreground and background colours, not a logical reversal.

    checkerboard rows columns {fgcolour colour} {bgcolour colour}

    Generate a checkerboard pattern on the entire screen.

    speckle x y radius {fgcolour colour} {bgcolour colour}

    Draw a speckle filled circle (default current foreground colour and black) centred at x, y of radius. Optionally, both the foreground and background colours can be specified.

    ellipse x y radius1 radius2

    Draw an ellipse centred at x, y of radius1 and radius2.

    ellipsefill x y radius1 radius2

    Draw a filled ellipse centred at x, y of radius1 and radius2.

    sprite x y filename|bitmap

    Draw an image over the current background, centred at x,y. If the image contains any transparent colours (index 0 for 8 bit modes, pink for other), the background will show through. The image may be of any size and is not filled.

    The sprite must be an image file or bitmap (built by preload), and not a list or object.

    sprite rotated x y angle filename|bitmap

    Same as sprite, but the image is rotated angle degrees (in the range -360 to 360).

    sprite vflip x y filename|bitmap

    Same as sprite, but the image is flipped about the vertical axis before it is rendered.

    sprite hflip x y filename|bitmap

    Same as sprite, but the image is flipped about the horizontal axis before it is rendered.

    compiled sprite x y filename|bitmap

    Same as sprite, but the image is compiled into a set of computer instructions that can render the image very quickly. This will use a large amount of memory. It is useful if you want to draw a common small shape frequently (remember that all images (and sprites) are cached, so once an image is named, only a single copy is kept by the program).

    floodfill x y

    Starting at x, y, fill the screen until a colour change is encountered.

    text x y "Enclosed text"

    Draw left justified text, starting at x, y.

    textright x y "Enclosed text"

    Draw right justified text, starting at x, y.

    textcentre x y "Enclosed text"

    Draw text centred at x, y.

    flow text left_margin right_margin vertical_spacing "Enclosed text"

    This will do rudimentary text formatting, by adding words from the last used object position (last_x, last_y) until the line would overflow, where upon a new line will be started with the specified margin. The vertical spacing is multiplied by the font height to establish the spacing between lines.

    There are three escapes allowed in flowed text strings, \n to for a new line, \u to turn on underlining and \r to turn off underlining.

    font font_name

    Set the font to be used for subsequent text objects. The font used for prompts is unaffected. You may have several font changes within the same object list.

    Example of object descriptions

    	line 100 100 200 200		# a line from 100,100 to 200,200
    	rect 100 100 200 200		# a rectangle, corners 100,100 and 200,200
    	rectfill 100 100 200 200	# a filled rectangle
    	circle 200 200 50		# a circle, radius 50, centre 200,200
    	circlefill centred 50		# a filled circle in the middle of the screen
    	ellipse 200 200	50 60 		# an ellipse, radius 50 and 60, centre 200,200
    	ellipsefill 200 200 50 60
    	floodfill 100 100 		# fill screen, staring at 100, 100
    	font char40			# use a large font
    	text 100 100 "A Message"	# a left justified message at 100,100
    	textcentre 100 100 "A Message"  # a centred image
    
    	rectfill 100 100 200 200 colour red	# a filled red rectangle
    	rectfill 100 100 200 200 colour 0,0,127	# a filled dark blue rectangle
    
    Using relative coordinates
    	units relative
    	rect -0.5 -0.5 0.5 0.5		# a square covering hals the screen
    	circle centred 1.0 1.0		# a centred circle filling the entire screen
    
    An example of an inline object
    	display object 100		# an inline object
    	name object "Stimulus type 1"	# record info in log file
    	line 100 100 200 200
    	rect 100 100 200 200
    	end object
    
    An example of an object file containing a list of objects
    	start object "Type 2"		# start of object, with name
    	offset 100,-100			# offset the image
    	scale  0.5,0.5			# halve the image size
    	line 100 100 200 200
    	rect 100 100 200 200
    	end object
    
    	start object
    	offset global 100,-100		# offset the image for all subsequent entries
    	line 200 200 300 300
    	rect 200 200 300 300
    	end object
    
    An example of speckles with different contrasts
    	colour	fg1	255,255,255		# bright while
    	colour	bg1	0,0,0			# black
    	colour	fg2	128,128,128		# grey
    	colour	bg2	63,63,63		# dark grey
    
    	start object "High contrast"
    	speckle 100 100 20 fgcolour fg1 bgcolour bg1
    	...
    	end object
    
    	start object "Low contrast"
    	speckle 100 100 20 fgcolour fg2 bgcolour bg2
    	...
    	end object
    
    An example of using bitmaps. It is best to draw them in the centre so that they in the middle of the sprite (use the centred control word).
    	preload bitmap1 object
    	rectfill 220 140 420 340		# render a filled rectangle
    	end object
    
    	preload bitmap2 object
    	circlefill 320 480 100			# render a filled circle
    	end object
    
    	display object 100			# build an image
    	sprite rotated centred 90 bitmap1	# with a rotated rectangle
    	sprite 100 100 bitmap2			# and offset circle
    	end object
    
    A more elaborate example that builds a symmetrical dot pattern, then rotates it.
    	preload bitmap1 object
    	circlefill 100 100 5			# some dots down the
    	circlefill 150 200 5			# left hand side of
    	circlefill 250 300 5			# the screen only
    	circlefill 310 360 5
    	end object
    
    	preload bitmap2 object
    	sprite centred bitmap1			# render the original image 
    	sprite hflip centred bitmap1		# and mirror about vertical axis
    	end object
    
    	display object 100
    	sprite rotated centred 15 bitmap2	# and put up image rotated 15 degrees
    	end object
    

    Saving images

    It is possible to save images generated by RUNSTIM. This is meant only as a debugging aid or saving images for other uses. You can save from a screen or bitmap. Remember that screen1 is the screen used by default by display, and screen1 and screen2 are used by the flash command. You can have a string and expression to generate automatic sequential filenames. The format of the saved image file is set by the file extension, being .bmp, .pcx or .tga.

    save screen{1-n} "filename"

    Save from a fixed screen to a fixed file

    save background "filename"

    Save the background screen to a fixed file

    save screen[expression] "filename%d.pcx" index

    Save from the screen specified by expression, and save it in a file whose name is formatted using another expression

    save background "filename"

    Save the current background.

    save bitmap{1-n} "filename"

    Save the contents of a bitmap. The bitmap must have been build first using preload bitmap

    save bitmap[expression] "filename"

    Save the contents of a bitmap specified by the expression.

    Note:- The palette used in 8 bit display modes can, in some circumstances, not be saved correctly. It is suggested that you use 16 bit or greater image modes

    The example below shows how to save sequentially into files using a procedure

    	file = 0
    	procedure img_save(1)
    	{
    		save screen[$1] "image%d.pcx" file
    		file = file + 1
    	}
    
    	block
    		display list.obj 100
    		image_save(1)
    	repeat sizeof list.obj
    

    Sound Support

    Sounds can be generated internally (tone, square wave, click, noise) or read from a sound file (.wav, .voc or .mid). In all cases, a volume is specified as a raw number (0-255), an absolute SPL measured in dB or a SPL relative to a baseline value. In the latter cases, a calibration file is checked and a matching entry is used to set the appropriate volume. This allows individual machines to be calibrated and use a common stimulus control file. To specify a calibrated SPL, append dB to the value, eg 80dB.

    By default RUNSTIM will allow you to use a dB value that is less than a calibrated value (provided other parameters match) as long as it is less than the calibration point and within 35dB. You can control turn on/off this feature using the command line -Jx or control file allow calculated dB x, where x in non-zero to enable extended ranges, or zero to allow only calibrated values.

    An onset and offset ramp may be applied to sounds so that there isn't a perceived click at the start and finish. The ramp that is applied is a quarter sine wave envelope and is measured in milliseconds. A 50 millisecond onset and offset is specified as onset 50 offset 50.

    The sound channel can also be specified, as left, right or both. Finally, strobe data can be specified to send data via the printer port.

    tone frequency left|right|both volume duration {onset milliseconds} {offset milliseconds} {strobe data} {nowait}

    Generate a pure sine wave tone of frequency (in Hz), with volume (eg 200 or 75dB), in the specified channel, with a duration (in milliseconds) and optionally onset and/or offset.

    Sound ramps are applied within the duration specified, and are sinusoidal.

    If the keyword nowait is present, then the program will not wait for the tone to complete or the ISI interval. This allows a tone (or square, noise or click) to have it's onset at the same time as a image presentation.

    square wave frequency left|right|both volume duration {onset milliseconds} {offset milliseconds} { nowait }

    Similar to tone, but a square wave.

    noise left|right|both volume duration {onset milliseconds} {offset milliseconds} {strobe data} { nowait }

    Generate a burst of white noise

    click left|right|both volume duration {onset milliseconds} {offset milliseconds} {strobe data} { nowait }

    Generate a click (single cycle square pulse).

    play filename left|right|both volume {strobe data}

    Play a sound file, either a .wav, .voc or MIDI file .mid

    calibration age days

    Specify the maximum allowable age for a calibration entry in days

    calibration file filename

    Change the name of the calibration file from the default sound.cal

    Example sound descriptions

    	tone 1000 both 80db 1000 onset 50 offset 50	# clickless 1KHz tone for 1 second
    	noise 1000 both 200				# uncalibrated noise burst
    	square wave 1000 left 75dB 100			# 1Hz square wave
    	play tada.wav both 128				# play a sound file
    	noise 1000 both 200 strobe 010			# uncalibrated noise burst with strobe data
    
    	sound threshold 40				# the sound threshold is 40dB
    	tone 1000 both +40dB				# output 1kHz tone at 80dB (40dB threshold + 40dB)
    

    Preloading Sounds

    The previous sound statements all use constants to specify the parameters for the sounds. This results in the efficient generation of the data before the experiment is run. It is possible to specify preload sounds that can have a variable or expression in any part of the specification (enclosed in brackets []). Since the data, and any calibration corrections has to be calculated during the interstimulus interval, it is possible that the ISI could be affected if short.

    The syntax is identical to the previous section, with preload sound before each statement :-

    	preload sound1 tone 1000 both 80db 1000 onset 50 offset 50
    	preload sound2 noise [duration] both [volume]dB 
    
    	sound 1
    	sound 2
    
    You can preload up to ten sounds and then use them at any time. Only the preload statement can affect timing if the ISI is short.

    You can also use the sound statement without a preload, but the time taken will be unpredictable (variable amounts of data has to be calculated).

    	sound noise [duration] both [volume]dB
    
    If all the values are constant, it is strongly recommended to use the original forms of sound specification :-
    	tone 1000 both 80db 1000 onset 50 offset 50
    
    	instead of
    
    	sound tone 1000 both 80db 1000 onset 50 offset 50
    

    Recording Sounds

    This is still in the development phase :-

    recorder frequency integer value

    Set the sample rate for recording sound

    recorder input [mic | line]

    Set the input source.

    recorder bits [8 | 16]

    Set the sampling resolution.

    recorder open mode [ask | append | replace]

    Select the mode for storing sampled sound data.

    Calibration Menu

    Starting RUNSTIM with a -c command line option will put the program into calibration mode. This will bring up a calibration menu :-

    Menu ItemDescription
    Sound LevelsCalibrate sound levels
    Video LuminanceCalibrate pseudo colours for luminance control
    Video DemosTest screen gamma, grey scales and refresh rate

    Note:-

    Calibration files are stamped with a serial number obtained from your license and machine identification. The purpose of this is to stop the accidental use of a calibration file on a different machine. If you want to transfer a calibration file to another machine, just edit the file and remove the licence number at the end. When you make any adjustments to calibration file, a new identification number will be added when the data is saved.

    Sound Calibration

    The program maintains a sound calibration file (normally called sound.cal), that is used to convert sound levels in dB into the internal values required to drive your sound source at the correct level. To prevent the calibration file from another computer being used by mistake, the program will record your license number in the calibration file. You can copy this file to other machines by removing the license code line.

    See the Sound Support section for details about calculated sound calibration values.

    It is strongly recommended that you leave the CPUID feature enabled in your computers BIOS to allow this calibration check.

    If you start the program with a -E on the command line, or invoke the program with the name caledit, you will enter a calibration mode that allows you to make entries in the calibration file. The program employs a simple graphical interface using the mouse and/or keyboard to make selections. The initial menu will have the current entries, and clickable boxes to make new entries, edit or delete old entries and saving the data. Each entry has a description, sound level and date stamp. If you have set a calibration age and an entry is too old, you will get an error message if it is used for an experiment.

    The New button will enter another menu that will allow you to select a sound type, frequency, calibration and volume. You can then Play the sound, and adjust the volume and pan levels until it matches the required sound level.

    Edit button will allow you to recalibrate an existing entry.

    Video Calibration

    It is possible to calibrate screen luminance and colour, based on using screen 'objects'. Upon entering the calibration mode, a menu is displayed with a list of current calibration colours, and menu buttons with the following functions :-

    Menu ItemDescription
    NewCreate a new entry
    Recal.Run the calibration sequence on the selected colour name
    DeleteDelete the selected entry
    UpdateUpdate the timestamp for the selected entry
    SaveSave any changed calibration settings

    When a new entry is made, the screen resolution, pixel depth and refresh rate is set, along with a name (equivalent to a named colour). The screen is then changed to the selected resolution, and then divided is to 16 regions (4 x 4 matrix). For each region, you can set the white level, or individually set each colour. When complete, the data is interpolated to generate a calibrated screen associated with the named colour. Any screen object using the named colour, will use data from the calibrated bitmap

    Please note that it is futile to use screen pixel depths of less that 24 bits, since this drastically limits the available range of intensities with which to apply corrections

    As and example, you may require a calibrated white, grey and black intensity to be correct, regardless of the position on the screen. Run three calibrations and give them colour names (such as cal_grey), and used the named colours to draw the stimulus. Currently, it is not possible to apply a calibration to an image file.

    Start Up Controls

    Depending on options in your license file, it is possible to control how RUNSTIM starts. The following commands cane be used :-

    no splash

    Disable the splash screen, which shows license and copyright details (you licence may not allow this!)

    no progress

    Disable the progress screen that show details of images and sounds loading

    no ready

    Display the Ready prompt that is normally issued when RUNSTIM is ready to start the task.

    Outputting data to LPT port

    RUNSTIM sends signals to the specified LPT port that is time locked to the stimulus. The strobe pin will always assert on the onset of stimulus and clear on the offset. Additional data can be output to the data pins using the strobe modifier. This data, by default, is also synchronised with the onset/offset of the stimulus. The data will be stable before the strobe pin is asserted.

    It is possible to hold data specified by a strobe command longer than the stimulus time, but using the following global command :-

    holdtime time_in_milliseconds

    The output data will be held for this amount of time.

    Note

    If the holdtime extends into another stimulus with different data, then the data will change with the onset of the new stimulus. The holdtime will also be reset to it's original value in this circumstance. The strobe data pin should accurately reflect the timing of the stimulus, and not be affected by the holdtime value.

    Interprocess communication

    There is a very basic interprocess communication for Unix versons of RUNSTIM. When RUNSTIM starts, it will create a file called /usr/local/runstim/runstim.pid which will contain the process ID for the controlling process (RUNSTIM will run as several threads) in ASCII. If you use the control statement wait signal, RUNSTIM will pause until it receives a SIGUSR1, where upon processing will continue. A count if kept of the number of signals received. If a wait signal is entered after an unprocessed SIGUSR1 is received, then RUNSTIM will continue without a pause.

    There is a more useful IPC mechanism in the planning stages that will use the unix socket mechanism to allow two-way communication.

    Miscellaneous

    print "format specification" { optional expressions }

    This statement formats text strings (see Unix 'printf') and outputs them to the screen. The following formats are accepted :-

    %dDecimal integer
    %oOctal integer
    %xHexadecimal integer
    %uUnsigned decimal integer
    %fFloating point number
    %gFloating point number
    %vAutomatic integer or floating point
    %cOutput integer as character
    %kSpecial. Output curent keyboard buffer
    %%Output %
    \tExpand as a tab
    \bOutput as backspace
    \nOutput a new line

    A number can be used to specify the width of the resulting output. A leading 0 will zero pad the number, while a leading - will left justify the number. eg :-

    print "Decimal %d, octal 0%0, hexadecimal 0x%x\n" x1, x2, x3
    print "Floating point %6.3f\n" value
    

    clock rate milliseconds_per_tick

    The clock used for internal timing can be set to the rate of milliseconds_per_tick. The default is 10.

    pause key value

    The program can be paused by hitting a special key. value my be one of:-
    offTo disable the feature.
    cA single character, eg p
    0101The octal value for the character.
    0x03The hexadecimal value for the character
    '^c'The control code for c.
    '\x'The unix style escape character.
    There is no default.

    quit key value

    Use this key to force the program do to an orderly exit. The options are the same as pause key. The default is the escape key (ESC).

    strobe data_value

    The data_value will be sent to the remote computer at the onset of the stimulus, and held until the stimulus offset. The value may be an expression enclosed in square brackets or an integer constant.

    defer images

    Normally images are loaded before the sequence in run. If you have a large number of images, you may run into memory problems. Using this mode will defer the loading of images until the ISI break before the image is required. This can affect timing if you have set a small ISI. It may be of benefit to avoid the use of 8 bit mode since the colour palette manipulations can take considerable time.

    lock image image_file

    Mark image_file to be kept after it is used. This will stop images being discarded after they are used in defer images mode.

    preallocate

    If you have a lot of images that are smaller than the screen size, memory can become fragmented as the images are loaded. Setting this option will preallocate memory for images. There is a slight speed penalty when the programs starts loading the images.

    log milliseconds

    The log file records the time is seconds. You can elect to have the time printed in milliseconds with this option.

    Restrictions

    System Lockups

    The program will occasionally lockup the computer necessitating a hardware reset. To date, this has only happened when running under Windoze (not recommended) and appears to be associated with the screen saver being activated.

    Timing Accuracy

    There are two sources of timing in this program. The displays are timed by counting the number of video screen refreshes. So image times (for display, flash and movie) must be a whole number of refreshes. You will get a warning message if the time you request will result in more than a 5 percent error. You may have to play with the vertical refresh rate to accommodate particular display times.

    The inter-stimulus interval is timed using the system clock, which is normally set to run at 1ms intervals. During the ISI, the program preloads images and outputs data that has been collected. This can result in slight variations in the ISI timing if the ISI is set to a small value. The times recorded in the data file will be accurate.

    Latter versions of RUNSTIM (version 4), keeps a wallclock estimate of what the time should be, and compares it with the actual time. This allows unexpected scheduling delays by the operating system to be corrected (rather than accumulate)

    ISI Timing

    Commands that generate stimulus will generate an ISI interval after them, specifically :-

    display, flash, movie, noise, tone, square, wave, click, play and sound.

    The special case of sleep after a display does not invoke an ISI. The commands sleep and wait refresh will invoke a different delay from the current ISI.

    All background commands generate a one frame delay to allow the change to happen.

    Movies

    Short movies can be stored in available video card memory, but longer ones must be loaded out of memory. If you are short of real memory, the system will page in the data off the disk, which may slow down updates. You can minimise the problem, either by using a small image size (320 x 240) or using 8 bit mode (see warning below).

    8 bit mode

    In 8 bit mode, the video card uses a palette to store colour information. The program tries to keep all it's colours in the one palette to avoid costly switching between images, which can result in a colour flash. Try to use the same palette for all images, and use less that 240 colours. There are programs available to force a constant palette on a set of images.

    Due to a bug in the graphics package, 15/16/24/32 bit image files cannot be converted into 8 bit images. Use an external program to convert the files before they are used.

    Memory

    If you are short of memory, the system will start paging from disk, which can affect timing if the ISI is set to a small value. You can use the defer images to save on memory usage, but the ISI has to be long enough to allow all the images for the next trial to be loaded.

    Preload's

    Be weary of mixing preload with display image_spec ... and flash statements, since they will interact. Preload is a low level routine to load an image into a video screen bitmap (1-48). Display and flash automatically use screens 1, and 1,2 respectively. Screen 3 is always available, and more screens are generally available depending on the amount of video memory your display card has, and the screen resolution that you are using. Use the -D debug mode to find the number of available screens (recorded in debug.log). The movie command can potentially use all the available screens.

    A complicated example of using low level preloads and displays is given below:-

    lock image fixation.pcx					# keep this image
    
    preload screen1 fixation.pcx 100			# keep in screen 1
    
    block
    	preload screen2 images1.lst once_only 100	# random image
    	preload screen3 background 100			# background
    	preload screen4 images2.lst once_only 100	# random image
    
    	display screen1					# display fixation
    	sleep 0						# no ISI
    	display screen2					# random image
    	sleep 0	
    	display screen3					# this is a background. Use display
    							# to maintain accurate timing
    	sleep 0	
    	display screen4					# random image
    repeat sizeof images1.lst
    

    Filenames

    You are stuck with the MS-DOS 8.3 format. In addition, beware of using filenames that match keywords such as object

    Objects

    Objects are drawn directly into the screen bitmap during the ISI. If you have a long list of objects and a short ISI, then you may run out of time. If you have a common list of objects, draw them into a bitmap using preload bitmap1 object at the start of your control file, and apply it latter using sprites.

    You cannot apply offset commands to objects using the display or flash directives. You can apply fixed offsets as part of the object description.

    Command line options

    -AOutput statistics
    -bDisable the dumping of object lists into debug or data files
    -cCalibrate the display (no control file is required)
    -CSkip pauses, prompts, waitanything
    -DDebug program
    -dDisplay loaded images
    -eSingle step through the stimulus list
    -EEnter the sound calibration mode
    -aUse VESA palette code
    -iIgnore VESA VBE version
    -Inn.nSet the first ISI interval to nn.n seconds
    -JnEnable (non-zero) or disable (zero) calculated sound dB levels
    -hOutput help list or all command line arguments and control file options.
    -lRun in local mode
    -LnSet LPT port to n
    -mGet VESA display modes and output the details
    -nDon't exit on quits
    -NNo video
    -PDon't merge palettes
    -rxxSet the clock rate to nn milliseconds per click
    -sUse vsync for timing
    -SnForce screen count to n
    -vnnnSet refresh rate to nnn Hz
    -VnnnSet explicit refresh rate to nnn Hz
    -wNo warnings
    -WLinux - run in window rather than full screen
    -XLabel images
    -xnnnDisplay X size to nnn
    -ynnnDisplay Y size to nnn
    -znnnDisplay depth to nnn

    Debugging Commands

    There are several commands that are useful when debugging the program. They can be in the control file, or a -?option on the command line.

    calibrate

    This is the screen calibration. It sets up the screen as 640x480, 16 bits deep and 100 Hz refresh rate (all parameters can be overridden). A border in drawn, then three squares. The left and right squares alternate with each refresh, while the centre is always present. The left a right should appear greyish with no flickering, and the centre bright white.

    debug

    A debugging file debug.log is produced containing information about stimulus data, image order ... Logging this data can affect the timing of the experiment, and should only be used to look at the internal sequences generated.

    statistics

    Output statistics about how much resources are used, eg the amount of memory in use, the number of images, lists ...

    vesa palette

    Use the VESA palette routines instead of graphics library (8 bit mode only).

    no merge

    Don't try to merge image palettes into the system palette (8 bit mode only).

    vsync clock

    Use the vertical retrace for timing instead of the system clock.

    label

    Label each image with it's filename.

    nowarn

    Disable some of the warnings. help clock rate

    no object dumps

    Disable the dumping of object lists. If you are generating complex displays, the debug log file can become rather large!

    nscreens n

    Override the auto-detected number of video bitmap screens. This can be used to force the movie command to use memory bitmaps instead of video card bitmaps (not a good idea).

    Projection modes

    Some of the newer data projectors (especially the compact ones) may not allow the image to be inverted or mirrored, which could be a problem in some experimental setups. RUNSTIM allows the global control of image orientation:-

    mirror images

    All images (and sprites) will be transposed left to right.

    invert images

    All images (and sprites) will be transposed top to bottom.

    mirror objects

    All objects will be transposed left to right.

    invert images

    All objects will be transposed top to bottom.

    mirror and invert may be selected at the same time, and the projection code will optimise how the images are manipulated.

    Note

    Any image or sprite used in a object, is initially loaded as an image so an invert images or mirror images will also result in them being changed when used in an object. Turning on the projection modes for both images and objects will result in objects and sprites being projected in their original orientations, but other objects (such as text and lines) will be affected.

    Built in help

    RUNSTIM has a very crude and brisk built in help utility. Type in :-
    runstim -h
    
    It will output the following :-
    • Version number of the software
    • All command line options
    • All control file commands
    • A list of object types
    • A list of builtin colours
    • A list of built in fonts

    Press the space bar to get another screen full, the return key will give one line at a time, and q will quit the program.

    Installation

    MDSOS

    The program suite is delivered as a compressed ZIP file called RUNSxxxx.ZIP, where xxxx is the version number (eg RUNS317E.ZTP is version 3.1.7e). You should create a directory named C:\RUNSTIM, and extract the ZIP files into it. The files extracted are :-

    CRASHDMP.EXEA program to save data if RUNSTIM crashes
    FONTLIB.DATAdditional text fonts
    FONTLIB.TXTA list of the contents of FONTLIB.DAT
    MANUAL.HTMThe manual for RUNSTIM
    PSN.EXEA program to generate a machine identification number
    RUNSTIM.EXEThe program itself

    To run the program, you need a valid license file generated at the University of Sydney, Department of Psychology.

    You will also need to let MSDOS and Windows where the program is. Edit both C:\Autoexec.dos and C:\Autoexec.bat so the the PATH command contains C:\RUNSTIM in addition to the other entries

    Linux

    The distribution file is in compressed TAR format. As 'root', do the following step:-
    mkdir /usr/local/runstim
    cd /usr/local/runstim
    tar zx location_of_distribution file
    ln -s  /usr/local/runstim/runstim /usr/local/bin
    

    Getting the video settings correct

    DGA (not RUNSTIM or the Allegro library) is very particular about having settings in /etc/X11/XF86Config for exact x, y, bit depth and refresh rate. There is an utility provided in the distribution called 'dga_modes' that will list all available combinations of screen size, depth and refresh rates. You will need to ensure that the video combinations you require are available (as identified by dga_modes), AND are in the X server configuration file /etc/X11/XF86Config (/etc/X11/xorg.conf for newer versions of XFree86) in the Screen section as a ModeLine. Use can use the standard X11 utility gtf to calculate a new ModeLine for a particulat screen resolution and refresh rate.

    Other Files

    There are several files used by RUNSTIM that are normally stored in C:\RUNSTIM. They are :-

    File NameDescription
    license.datLicense details, termination dates and options
    sound.calOptional sound calibration file
    video.calOptional video calibration files
    fontlib.datExtended font library for text


    Example control file

    Display a randomly (1) selected image from a list (2), each image is used only once(4), and is presented for for 100 milliseconds (3), the inter-stimulus interval is one second (5). The background colour is sampled from the image list (6). The program can be paused by pressing the 'p' key (7). Data in recorded from the mouse (8) and stored in a file, the name of which is prompted from the keyboard (9).
    #
    #	test sequence file
    #
    
    xsize	640
    ysize	480
    vrate	100
    depth	8
    vesa
    local
    randomise			# (1)
    pause key p			# (7)
    
    background sample small.lst	# (6)
    
    isi     1.0			# (5)
    
    datafile prompt			# (9)
    
    block
    mouse enable isi		# (8)
    display small.lst once_only 100
    #           (2)      (4)    (3)
    
    repeat sizeof small.lst
    

    Example Animation control file

    Listed below is an example of animation using objects and screen preloads. The program is designed to move a dot horizontally back and forth across the screen, the speed determined by a sine wave function. The features to note are :-
    • A table of positions is calculated to specify the screen positions for the dot at it moves.
    • Two screens are used. While one is being displayed, the other is changed for the next dot position
    • To speed up screen updates, the 'no clear' object mode is used. Instead of clearing the whole background for the next screen, the previous dot is erased, and a new one drawn. Note that a compiled sprites are used to set and clear dots, rather than 'circlefill'. If you have a fast processor, the latter would suffice.
    • Expressions that are constant are calculated outside the loop.

    #
    #	test moving object using sinewave increment steps
    #
    
    xsize 640
    ysize 480
    vrate 75
    
    path tests
    
    initial isi 0
    background black
    
    #
    #	set initial screens black
    #
    
    preload screen1 object nowait
    background colour black
    end object
    
    preload screen2 object nowait
    background colour black
    end object
    
    #
    #	set initial parameters
    #
    
    steps = 201		# steps per scan, should be odd
    width = 400		# width along screen
    
    #
    #	calculate constants
    #
    
    xc = xsize / 2.0	# centre of screen
    hw = width / 2.0	# half width
    hs = steps / 2.0	# half step 
    sc = (pi / 2.0) / hs	# increment for sine function
    y = ysize / 2		# middle of screen
    
    #
    #	calculate sine table for x position
    #
    
    array float xpos[steps]	# array to hold steps
    
    for x = 0; x < steps; x++
    	xpos[x] = xc + hw * sin(sc * (x - hs))
    next x
    
    #
    #	set initial array position 'x' and screen index
    #
    
    x = 1
    index = 1
    
    #
    #	fast lookup table for index
    #
    array int idx[3]
    
    idx[1] = 2
    idx[2] = 1
    
    #	render initial dot
    
    preload screen1 object nowait
    	sprite [xpos[1]] [y] dot.pcx
    end object
    
    #
    #	continuous loop
    #
    block
    
    #
    #	moving left to right
    #
    	block
    		display screen[index]
    #
    #	generate new index
    #
    		nindex = idx[index]
    #
    #	erase previous dot (two points ago) and render new one
    #
    		preload screen[nindex] object nowait
    			no clear
    			compiled sprite [xpos[x - 1]] [y] notdot.pcx
    			compiled sprite [xpos[x + 1]] [y] dot.pcx
    		end object
    
    		index = nindex
    #
    #	loop for width
    #
    	while ++x < steps - 1
    #
    #	moving right to left
    #	
    	block
    		display screen[index]
    
    		nindex = idx[index]
    
    		preload screen[nindex] object nowait
    			no clear
    			sprite [xpos[x + 1]] [y] notdot.pcx
    			sprite [xpos[x - 1]] [y] dot.pcx
    		end object
    
    		index = nindex
    	while --x > 1
    
    repeat for ever
    
    

    Email:- johnh@psych.usyd.edu.au

    Copyright © 2001 by John Holden