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
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).
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.
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'.
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
'X' returns 0130
'\b' returns code for backspace
Operators
| Unary | -expression | negate |
| !expression | logical negation | |
| ~expression | one's complement | |
| ++variable | increment variable by one before use | |
| --variable | decrement variable by one before use | |
| variable++ | increment variable by one after use | |
| variable-- | decrement variable by one after use | |
| Multiplicative | expression * expression | multiply |
| expression / expression | divide | |
| expression % expression | remainder | |
| Additive | expression + expression | add |
| expression - expression | subtract | |
| Logical | expression & expression | bitwise AND |
| expression | expression | bitwise OR | |
| expression ^ expression | bitwise XOR | |
| Shift | expression >> expression | shift right |
| expression << expression | shift left | |
| Relational | expression == expression | equal to |
| expression != expression | not equal to | |
| expression < expression | less than | |
| expression > expression | greater than | |
| expression <= expression | less than or equal to | |
| expression >= expression | greater than or equal to | |
| expression && expression | logical AND | |
| expression || expression | logical OR |
| 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 |
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
# 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.
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.
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 '$'.
Built in variables
| xsize | Screen dimension for x in pixels |
| ysize | Screen dimension for y in pixels |
| pi | 3.1415926535897932385... |
| last_key_ascii | Last valid keyboard code in ASCII |
| last_key_scan | Last valid keyboard code as scan code |
| last_key_time | Time of last valid keyboard press |
| last_key_count | Count of keyboard event captured |
| last_mouse_code | Last valid mouse button code |
| last_mouse_time | Time of last valid mouse button press |
| last_mouse_cnt | Count of mouse events captured (note spelling cnt) |
| last_ext_change | Last external event change |
| last_ext_time | Time of last external event change |
| last_ext_count | Count of external events captured |
| last_stim_time | Time of the last stimulus onset |
| last_x | Last x coordinate used by an object (eg end of line) |
| last_y | Last y coordinate used by an object |
| last_line_val | The value of the last numeric string resulting from a prompt or promptk. |
| keyboard_buffer | An array of ASCII integers from the last prompt command. |
| linux | Defined if operating system is Linux |
| windows | Defined if operating system is Windoze |
| msdos | Defined if operating system is MESSYDOS |
| macosx | Defined if operating system is Macintosh OS X |
| DEBUG | Defined if command line debug mode is set |
| NO_PAUSE | Defined if command line 'no pause' mode is set |
The keyboard and mouse data are for presses that are waited
for.
Arrays may be initialised. The declaration my extend over more than one line.
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.
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]
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.
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
x = 1 block ... ... x = y while x < 10
for x = 0; x < 10; x++ ... ... if x == y continue endif ... ... next
isi 1.5 # set the ISI to 1.5 seconds
isi 1.0 - 3.0 # set the ISI to a random value
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.
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.
path stimulus_1 display list1.lst ... path different_directory display list2.lst
To get a list of inbuilt fonts (and all command and object names) type :-
runstim -hThe 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)
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 ...
You can specify multiple combinations of change detection by using several operators. Only the last external enable will ever be active.
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
lpt 2
runstim -m | moreTo set a higher resolution display :-
xsize 1024 ysize 768
vrate 100
depth 16
colour orange 127, 63, 0
background 127,127,127 # a grey background
background grey
foreground 255,255,255 # a white foreground
foreground white
image mask object circlefill 340 280 200 #apply a circular mask to all images end object
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.
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
Under normal circumstances, a once_only used more than once will only allow one use of each item.
display image.pcx 100 # single image for 100 milliseconds
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_1.pcx 100 image_2.pcx 10 # flash image 1 for 100 ms, # followed by image 2 for 10ms
movie list.lst 20 # play list as movie, each frame for # 20 milliseconds
movie list.lst 20 2 # play list as movie, each frame for # 20 milliseconds, twice
movie list.lst 20 waitkey # play list as movie, each frame for # 20 milliseconds, until key is pressed
preload movie[1] object_list_a.obj movie[1] 10
object background line 0 0 100 100 colour white
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.
The sprite must be an image file or bitmap (built by preload), and not a list or object.
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.
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 rectangleUsing 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 screenAn 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 objectAn 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 objectAn 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 objectAn 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 objectA 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
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
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.
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.
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)
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 2You 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]dBIf 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
| Menu Item | Description |
|---|---|
| Sound Levels | Calibrate sound levels |
| Video Luminance | Calibrate pseudo colours for luminance control |
| Video Demos | Test 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.
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.
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.
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 Item | Description |
|---|---|
| New | Create a new entry |
| Recal. | Run the calibration sequence on the selected colour name |
| Delete | Delete the selected entry |
| Update | Update the timestamp for the selected entry |
| Save | Save 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.
It is possible to hold data specified by a strobe command longer
than the stimulus time, but using the following global command :-
There is a more useful IPC mechanism in the planning stages that will use
the unix socket mechanism to allow two-way communication.
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.
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.
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 :-
| %d | Decimal integer |
| %o | Octal integer |
| %x | Hexadecimal integer |
| %u | Unsigned decimal integer |
| %f | Floating point number |
| %g | Floating point number |
| %v | Automatic integer or floating point |
| %c | Output integer as character |
| %k | Special. Output curent keyboard buffer |
| %% | Output % |
| \t | Expand as a tab |
| \b | Output as backspace |
| \n | Output 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
| off | To disable the feature. |
| c | A single character, eg p |
| 0101 | The octal value for the character. |
| 0x03 | The hexadecimal value for the character |
| '^c' | The control code for c. |
| '\x' | The unix style escape character. |
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.
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.
| -A | Output statistics |
| -b | Disable the dumping of object lists into debug or data files |
| -c | Calibrate the display (no control file is required) |
| -C | Skip pauses, prompts, waitanything |
| -D | Debug program |
| -d | Display loaded images |
| -e | Single step through the stimulus list |
| -E | Enter the sound calibration mode |
| -a | Use VESA palette code |
| -i | Ignore VESA VBE version |
| -Inn.n | Set the first ISI interval to nn.n seconds |
| -Jn | Enable (non-zero) or disable (zero) calculated sound dB levels |
| -h | Output help list or all command line arguments and control file options. |
| -l | Run in local mode |
| -Ln | Set LPT port to n |
| -m | Get VESA display modes and output the details |
| -n | Don't exit on quits |
| -N | No video |
| -P | Don't merge palettes |
| -rxx | Set the clock rate to nn milliseconds per click |
| -s | Use vsync for timing |
| -Sn | Force screen count to n |
| -vnnn | Set refresh rate to nnn Hz |
| -Vnnn | Set explicit refresh rate to nnn Hz |
| -w | No warnings |
| -W | Linux - run in window rather than full screen |
| -X | Label images |
| -xnnn | Display X size to nnn |
| -ynnn | Display Y size to nnn |
| -znnn | Display depth to nnn |
mirror and invert may be selected at the same time, and the projection code will optimise how the images are manipulated.
runstim -hIt will output the following :-
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.EXE | A program to save data if RUNSTIM crashes |
| FONTLIB.DAT | Additional text fonts |
| FONTLIB.TXT | A list of the contents of FONTLIB.DAT |
| MANUAL.HTM | The manual for RUNSTIM |
| PSN.EXE | A program to generate a machine identification number |
| RUNSTIM.EXE | The 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
| File Name | Description |
|---|---|
| license.dat | License details, termination dates and options |
| sound.cal | Optional sound calibration file |
| video.cal | Optional video calibration files |
| fontlib.dat | Extended font library for text |
# # 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
# # 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