#A = &CH1 + arcsin ( &CH2 * ln &CH3 )
exp ::= "-" exp
exp ::= "(" exp ")"
exp ::= exp op exp
op ::= "+" | "-" | "*" | "/" | "^" | and | or | xor
#A = &CH1 ^ -( &Ch2 / 10 )
#B = #A and 0x07 // bit 0-2 of #A
exp ::= unop exp
unop ::= arccos | arcsin | arctan | cos | cosh
| ln | log | sin | sinh | sqr
| tan | tanh
#A = sqr &CH1
condition ::= exp comp exp
condition ::= bit comp bit
condition ::= "(" condition ")"
condition ::= condition { comb_op condition }
comp ::= "<" | <= | "=" | >= | ">" | <>
bit ::= bitreg | bitvalue
bitvalue ::= on | off | true | false
comb_op ::= and | or
if #A >= &CH1 - #offset then
write " too high "
endif
if |CAPTURE_PIN = off and |RECEIVE_READY = true then
gosub read_serial_data
endif
if (&DISPLAY and 0x00000001) = 0 then
// display value is even
endif
dim A[] = [ "Hello ", \
"World" ]
write A[0] : append A[1]
// if the line contains only the comment
rem the comment markers don't differ
write "Hello " // but when preceded with other commands
append "World" : rem REM needs a separator
#A = -100
let %FloatValue_1 = 100.0
&CH1 = #A
mem &USER_MEMORY_1 = 0
// preset setpoint 1-3
mem &SETPOINT1[] = [ 1000, 2000, 3000 ]
reg &WaterTemperature = &CH1
bit |Phase_1 = |LED1
bitreg &CODE2 = [ ,,,,,, |FREQ_50HZ, |FAST_MODE ]
const ButtonTimeout = 40
const DefaultScaleFactor = 0.125
dim A[] = [ "0 Butane", "1 Oxygen", "2 Hydrogen", "3 Nitrogen" ]
dim B[] = [ 100, 101, 104, 109, 116, 125, 136, 149, 164, 181, 200 ]
...
write A[0] // this is equivalent to: write "0 Butane"
if_statement ::= if condition then statement_sequenceThe IF statement can have any number of ELSIF branches but only one ELSE. Please note that the ENDIF command is mandatory.
{ elsif condition then statement_sequence }
[ else statement_sequence ]
endif
if |SP1 = on then
&DATA_SOURCE_TOTAL1 = addr(&CH1)
elsif |SP2 = on then
&DATA_SOURCE_TOTAL1 = addr(&CH2)
else
&DATA_SOURCE_TOTAL1 = 0
endsel
select_statement ::= select var_regThe SELECT statement allows you to test a register for fixed values. The register can be either integer or floating point and might even be an array index. It needs at least one CASE branch with at least one immediate value as well as the ENDSEL at the end. The optional final DEFAULT case matches any value
case immediate { "," immediate } ":" statement_sequence
{ case immediate { "," immediate } ":" statement_sequence }
[ default: statement_sequence ]
endsel
var_reg ::= var | var "[" exp "]"
select &PumpState[#curPump]
case pOFF:
// do nothing
case pLOW, pMEDIUM:
write "Pump" + #curPump
case pHIGH:
write "Alarm"
endsel
error:
|Pump1 = off
|Pump2 = off
#state = sERROR
write "ALARM"
end
...
select #state
case pHIGH:
if &Temperature = FATAL then
goto error
endif
endsel
RESET_MACRO:
&TOTAL1 = 0
reset_cycle:
#counter = 0
#cycle = CYCLE_INIT
end
MAIN_MACRO:
if |CAPTURE_PIN = on then
gosub reset_cycle
endif
...
RESET_MACRO:
&TOTAL1 = 0
// last thing to do, so we don't have to get back
goto reset_cycle
end
reset_cycle:
#counter = 0
#cycle = CYCLE_INIT
return
MAIN_MACRO:
if |CAPTURE_PIN = on then
gosub reset_cycle
endif
...
for_loop ::= for var "=" exp to exp [ step exp ] statement_sequence next varThe FOR loop uses a counter variable which is initialized (start value) and then increased with every NEXT command by the STEP value (default is 1). When the counter reached the TO (end) value the loop is terminated and the execution continues after the NEXT statement. As long as the counter is between the start and the end value the command sequence between FOR and NEXT will be executed.
for #counter = 0 to 31
&TABLE1_OUTPUT1[#counter] = &USER_MEMORY_1[#counter]
next #counter
repeat_loop ::= repeat statement_sequence until conditionThe REPEAT command leads to a so called non-rejecting loop as it executes the command sequence within at least once before checking the condition. If the condition is false the loop back to the repeat command and execute the sequence again.
#digits = MAX_VALUE
print "&CH1 ="
repeat
print " "
#digits = #digits / 10
until #digits < &CH1
print &CH1
include "C:\BasicLibrary\SerialProtocol.bas"
if &TIMER1 > LOG_TIMEOUT then
&TIMER1 = 0
FORCE_LOG
endif
abs_function ::= abs "(" exp ")"
#diff = abs(&CH1 - &CH2)
addr_function ::= addr "(" var ")"
// show the value of #diff on the display
&DATA_SOURCE_DISPLAY1 = addr(#diff)
asc_function ::= asc "(" """ char """ ")"
chr_function ::= chr "(" ASCII_int ")"
mem &TEXT_CHARACTER_CH1 = asc("T")
print "Hello, World!" + CHR(CR) + CHR(LF)
scale_function ::= scale "(" exp "," table_num ")"
table_num ::= "1" | "2" | "3" | "4"
// apply lintable 2 to the sum of CH1, CH2, and CH3
#lin_out = scale(&CH1+&CH2+&CH3, 2)
append_statement ::= append text_string
write_statement ::= write text_string
write_port_statement ::= write const_int text_string
text_string ::= dim_array_name "[" const_int "]"
text_string ::= const_reg | sub_string { "+" sub_string }
sub_string ::= quoted_text | var | chr_function
const_reg ::= var | var "[" const_int "]"
dim space[] = [ " ___", "___ " ]
const LEADING = 0
const TRAILING = 1
write "" // interrupt previous message
write space[LEADING]
append "Setpoint 1 = " + &SETPOINT1
append space[TRAILING]
write 1 "Hello " // top display
write 2 "World!" // bottom/default display
edit_statement ::= edit constant | edit var_reg
edit_numeric_statement ::= edit_numeric
edit_text_statement ::= edit_text dim_array_name []
exit_edit_statement ::= exit_edit [ var_reg ]
var_reg ::= var | var "[" exp "]"
dim ExitEnter[] = [ " Exit", " Enter" ]
const mEXIT = 0
const mENTER = 1
...
MAIN_MACRO:
if |CAPTURE_PIN = on and &STATE = 0 and &EDIT_STATE = 0 then
edit mEXIT
&EDIT_MIN = mEXIT
&EDIT_MAX = mENTER
edit_text ExitEnter[]
&STATE = eENTER_SETUP
endif
end
EDIT_MACRO:
select &STATE
case eENTER_SETUP:
exit_edit #temp
if #temp = mEXIT then
&STATE = 0
else
// continue with next value
endif
...
endsel
end
print_statement ::= print text_string
print_statement ::= print const_reg print_format
print_port_statement ::= print const_int text_string
print_port_statement ::= print const_int const_reg print_format
text_string ::= reg_string | sub_string { "+" sub_string }
sub_string ::= quoted_text | reg | chr_function
const_reg ::= var | var "[" const_int "]"
print_format ::= "," const_int [ "," ASCII_int ]
print "" // flush the buffer
print "Channel 1 = " + &CH1 + chr(CR) + chr(LF)
print 2 "Hello, World!" // print to second port
// print CH1 left aligned, 8 chars wide, use '-' to fill up the trailing spaces
print &CH1, -8, asc("-")
serial_condition ::= serial_input [ const_int ] str_op comp_string [ "+" comp_string ]
str_op ::= "=" | <>
comp_string ::= quoted_string | chr_function
if SERIAL_INPUT 2 = "SR" then
// string in serial buffer 2 starts with 'SR'
endif
parse_func ::= num_func "(" serial_pointer [ const_int ] ["," const_int ] ")"
num_func ::= float | hex | integer
// read integer from index 8 to index 13 of buffer 2
&SERIAL_POINTER2 = 8
#data = int(serial_pointer 2, 6)
// read float variable from current position in default buffer (port 1)
%scale = float(serial_pointer)
mb_read ::= modbus_read "(" const_int "," const_int "," var [ "," mb_flag ]")"
mb_write ::= modbus_write "(" const_int "," var "," const_int [ "," mb_flag ]")"
mb_flag ::= MB_BYTE | MB_SHORT | MB_24 | MB_24_SWAPPED | MB_LONG | MB_LONG_SWAPPED | MB_FLOAT | MB_FLOAT_SWAPPED
const TIGER320_RESULT = 40513
MODBUS_MASTER_MACRO:
|LED1 = off : |LED2 = off
if #modbus = mbREAD then
// read CH3 from other Tiger 380
modbus_read 2 (5, addr(&CH3), &RESULT)
|LED1 = on
elsif #modbus = mbWRITE then
// write to a Tiger 320
modbus_write 2 (7, &RESULT, TIGER320_RESULT)
|LED2 = on
endif
end