REM >JP REM REM Library of routines for John Parkinson. REM Designed to control Intasolve Touch Monitor system, using Arachnid. REM REM Revision history: REM Started on 7 July 99 by Rudolf Cardinal. REM Advanced handler system on 12 July 99. Untested. REM REM Things to think about: REM - resolution (software averaging, manual section 8.4) REM REM Modified for Yogi's IntaSolve system, 21 Aug 99. REM - System discriminates the two types with _tch_screentype%, just in case REM - Yogi's superlabels don't have CR appended, so my library now uses CR as an end-of- REM label flag. REM - With stylus status on, JP's manual says it should send REM "label 0 CR LF" or "label 1 CR LF" REM but Yogi's sends "label 0" or "label 1" REM Yogi's system now works. JP's system untested. ERROR 1,"JP: This file cannot be run. It is a library file." REM ======================================================================== DEF PROCjp_touchscreen_boxes REM ======================================================================== REM Only one box... frontlicker% = 0 houselight% = 1 frontjuice% = 2 hightone% = 3 backlicker% = 4 :REM ??? lowtone% = 5 backjuice% = 6 :REM ??? REM Take control of output lines; watch input lines PROCfree_switch(frontlicker%,E%) PROCfree_switch(backlicker%,E%) PROCgovn_switch(houselight%,E%) PROCgovn_switch(frontjuice%,E%) PROCgovn_switch(backjuice%,E%) PROCgovn_switch(hightone%,E%) PROCgovn_switch(lowtone%,E%) touchscreen_channel% = 0 max_touchscreens% = 0 :REM Arrays are indexed by channel number, so this must equal the greatest *channel number* used PROCgeneric_touchscreen_init(max_touchscreens%) ENDPROC REM ======================================================================== DEF PROCgeneric_touchscreen_init(max_touchscreens%) REM ======================================================================== LOCAL t% DIM _tch_superlabel_handler$(max_touchscreens%) :REM internal variable to hold name of user function; do not modify directly DIM _tch_coordinate_handler$(max_touchscreens%) :REM internal variable to hold name of user function; do not modify directly DIM _tch_stylus_status%(max_touchscreens%) :REM internal variable to keep track of stylus status bit; do not modify directly DIM _tch_input_buffer$(max_touchscreens%) :REM internal variable to store codes; do not modify DIM _tch_escape%(max_touchscreens%) DIM _tch_screentype%(max_touchscreens%) DIM _tch_awaiting_stylus%(max_touchscreens%) esc$ = CHR$(27) esc% = 27 cr% = 13 lf% = 10 jp_type%=0: yogi_type%=1 touch_debug%=0 FOR t%=0 TO max_touchscreens% _tch_screentype%(t%) = jp_type% PROCinit_touchscreen(t%) PROCdefine_origin_bottom_left(t%) ENDPROC ENDPROC REM ======================================================================== DEF PROCinit_touchscreen(channel%) REM ======================================================================== PROCsclr_rbuf(channel%, E%) :REM clear serial buffer PROCsroll_rbuf(channel%, E%):REM give permission to use receive buffer PROCsroll_tbuf(channel%, E%):REM give permission to use transmit buffer _tch_escape%(channel%) = 0 _tch_awaiting_stylus%(channel%) =0 _tch_input_buffer$(channel%) = "" PROCunregister_superlabel_handler(channel%) PROCunregister_coordinate_handler(channel%) PROCtouchscreen_software_reset(channel%) PROCdisable_stylus_status(channel%) PROCpipe_serial(touchscreen_channel%, 0, 0, "FNtouchscreen_handler(", touchscreen_channel%, E%) ENDPROC DEF PROCtouchscreen_software_reset(channel%) PROCsend_string(channel%, esc$ + "[%C") ENDPROC DEF PROCpoint_mode(channel%) REM A single coordinate pair is transmitted each time the touch active REM area is entered. No more data comes until you've taken your finger off. PROCsend_string(channel%, esc$ + "[%0O") :REM zero/oh ENDPROC DEF PROCcontinuous_mode(channel%) REM Transmits coords as long as a stylus is in the frame, continuously. PROCsend_string(channel%, esc$ + "[%1O") ENDPROC DEF PROCstream_mode(channel%) REM Transmits coords every time a styles *moves*. PROCsend_string(channel%, esc$ + "[%2O") ENDPROC DEF PROCinverse_stream_mode(channel%, detection_period%) REM Transmits coords whenever the styles has stopped for a pre-determined period. REM Period measured in scans and should be 0-255. IF detection_period%<0 OR detection_period%>255 THEN VDU7:PRINT"Invalid parameters to PROCinverse_stream_mode!" ENDPROC ENDIF PROCsend_string(channel%, esc$ + "[%5O") PROCsend_string(channel%, esc$ + "[%8;" + STR$(detection_period%) +"D") ENDPROC DEF PROCenable_superlabels(channel%) PROCsend_string(channel%, esc$ + "[%25H") ENDPROC DEF PROCdisable_superlabels(channel%) PROCsend_string(channel%, esc$ + "[%25L") ENDPROC DEF PROCenable_stylus_status(channel%) PROCsend_string(channel%, esc$ + "[%32H") _tch_stylus_status%(channel%) = 1 ENDPROC DEF PROCdisable_stylus_status(channel%) PROCsend_string(channel%, esc$ + "[%32L") _tch_stylus_status%(channel%) = 0 ENDPROC DEF PROCenable_coords_in_superlabels(channel%) PROCsput_tbuf(channel%, 27, E%) :REM Esc PROCsput_tbuf(channel%, ASC("["), E%) PROCsput_tbuf(channel%, ASC("%"), E%) PROCsput_tbuf(channel%, ASC("2"), E%) PROCsput_tbuf(channel%, ASC("6"), E%) PROCsput_tbuf(channel%, ASC("H"), E%) REM Could have been written PROCsend_string(channel%, esc$ + "[%26H") ENDPROC DEF PROCdisable_coords_in_superlabels(channel%) PROCsend_string(channel%, esc$ + "[%26L") ENDPROC DEF PROCdefine_origin_bottom_left(channel%) PROCsend_string(channel%, esc$ + "[%16H") ENDPROC DEF PROCsend_string(channel%, string$) LOCAL i% FOR i% = 1 TO LEN(string$) PROCsput_tbuf(channel%, ASC(MID$(string$,i%,1)), E%) NEXT ENDPROC DEF PROCdefine_superlabel(channel%, left%, right%, bottom%, top%, name$) REM Assumes bottom left origin REM Yogi's superlabels don't use CR at the end, but we want them to. *** Note this. IF _tch_screentype%(channel%)=yogi_type% THEN name$ = name$ + CHR$(cr%) PROCsend_string(channel%, esc$+"[%"+STR$(bottom%)+";"+STR$(left%)+";"+STR$(top%)+";"+STR$(right%)+"U") PROCsend_string(channel%, esc$+"[%\5"+name$+"~") ENDPROC DEF PROCclear_superlabels(channel%) PROCsend_string(channel%, esc$+"[%P") ENDPROC REM ======================================================================== DEF PROCregister_superlabel_handler(channel%, function$) REM ======================================================================== _tch_superlabel_handler$(channel%) = function$ REM user responsibility is to make sure that the handler function REM can be called like this: REM result% = FNuserfunction(..., superlabel$, on_off%) REM ^^^^^^^^^^^^^^^^^^^ REM This can go in function$ REM REM where "superlabel$" is the name of the label triggered REM REM If you have set the touchscreen STYLUS STATUS REPORT bit on, then REM on_off% will be 0 or 1 to indicated whether the stylus (finger) has just left or touched the screen. REM Otherwise, it will always be 1. REM Up to you whether you use this, and up to you to interpret the label. ENDPROC REM ======================================================================== DEF PROCregister_coordinate_handler(channel%, function$) REM ======================================================================== _tch_coordinate_handler$(channel%) = function$ REM similarly... REM result% = FNuserfunction(..., x_coord%, y_coord%, on_off%) REM ^^^^^^^^^^^^^^^^^^^ ENDPROC REM ======================================================================== DEF PROCunregister_superlabel_handler(channel%) REM ======================================================================== _tch_superlabel_handler$(channel%) = "" ENDPROC REM ======================================================================== DEF PROCunregister_coordinate_handler(channel%) REM ======================================================================== _tch_coordinate_handler$(channel%) = "" ENDPROC REM ======================================================================== DEF PROCtwo_regions_setup(channel%) REM ======================================================================== PROCdefine_origin_bottom_left(channel%) PROCpoint_mode(channel%) PROCenable_superlabels(channel%) PROCdisable_coords_in_superlabels(channel%) PROCdisable_stylus_status(channel%) :REM *** Experiment with turning this on REM Now two regions, "L" and "R" PROCdefine_superlabel(channel%, 10, 30, 26, 52, "L") PROCdefine_superlabel(channel%, 50, 70, 26, 52, "R") ENDPROC REM ======================================================================== DEF FNtouchscreen_handler(channel%, bogus%) REM ======================================================================== IF bogus%=0 =0 REM At this point, a character has arrived in the input buffer. REM (From PROCpipe_serial.) LOCAL c%, dummy%, on_off%, x%, y% c% = FNsget_rbuf(channel%, E%) IF touch_debug%=1 AND debug%=1 THEN REM Just print stuff IF c%=esc% THEN VDU 7 ELSE PRINT CHR$(c%); ENDIF ENDIF REM Principles of interpreting codes from the touchscreen: REM * If we've not had an escape code, accumulate any characters until we get CR/LF. Then send it to superlabel handler. REM and clear the accumulated characters. (In practice, chuck all LFs out and look for a CR. Don't send the CR itself.) REM * If we've had an escape code, accumulate characters *until* we get a letter. Then interpret the letter as a command. REM * If we get an escape code, clear the accumulated characters and start again. IF touch_debug%=1 THEN PRINT"touchscreen_handler (channel ";channel%;"): incoming character ";c%; IF c%>=32 THEN PRINT;" (";CHR$(c%);")" ELSE PRINT ENDIF IF c%=esc% THEN IF touch_debug%=1 THEN PRINT "touchscreen_handler (channel ";channel%;"): Esc" _tch_input_buffer$(channel%) = "" :REM not interested in storing the escape character itself. _tch_escape%(channel%) = 1 =0 ENDIF REM Now the current character is not an escape. IF _tch_escape%(channel%) = 1 THEN c% = FNtch_uppercase_ascii(c%) IF c%>=ASC"A" AND c%<=ASC"Z" THEN IF touch_debug%=1 THEN PRINT"touchscreen_handler (channel ";channel%;"): Command received: ";_tch_input_buffer$(channel%);CHR$(c%) REM Command received. CASE c% OF WHEN ASC"R", ASC"F": REM coordinate report, or report with beam fault IF _tch_coordinate_handler$(channel%)="" THEN ENDCASE IF LEFT$(_tch_input_buffer$(channel%),1) <> "[" THEN ENDCASE :REM hope that works IF INSTR(_tch_input_buffer$(channel%),";") = 0 THEN ENDCASE _tch_input_buffer$(channel%) = RIGHT$(_tch_input_buffer$(channel%),LEN(_tch_input_buffer$(channel%))-1) REM That chops off "[" y% = VAL(LEFT$(_tch_input_buffer$(channel%),INSTR(_tch_input_buffer$(channel%),";")-1)) _tch_input_buffer$(channel%) = RIGHT$(_tch_input_buffer$(channel%),LEN(_tch_input_buffer$(channel%))-INSTR(_tch_input_buffer$(channel%),";")) x% = VAL(_tch_input_buffer$(channel%)) :REM doesn't matter if there's extra data in this, VAL will sort it out on_off% = 1 IF _tch_stylus_status%(channel%)=1 THEN on_off% = VAL(RIGHT$(_tch_input_buffer$(channel%),LEN(_tch_input_buffer$(channel%))-INSTR(_tch_input_buffer$(channel%),";"))) ENDIF IF touch_debug%=1 THEN PRINT "touchscreen handler (channel ";channel%;") Have x=";x%;", y=";y%;", on_off%=";on_off% dummy% = EVAL(_tch_coordinate_handler$(channel%) + STR$(x%) + "," + STR$(y%) + "," + STR$(on_off%) + ")" ) OTHERWISE: REM Don't care. ENDCASE REM That's the end of the command, so clear the buffer. _tch_escape%(channel%) = 0 _tch_input_buffer$(channel%) = "" ELSE REM a number or punctuation mark; store it _tch_input_buffer$(channel%) += CHR$(c%) ENDIF ELSE REM We're in the Land of Superlabels. REM ***Note (21-Aug-99): Yogi's boxes do _not_ append CR/LF. The library appends it for you. CASE c% OF WHEN lf%: =0 WHEN cr%: IF LEN(_tch_input_buffer$(channel%))=0 THEN =0 :REM lone CR probably came from a coord report IF touch_debug%=1 THEN PRINT"touchscreen_handler (channel ";channel%;"): Superlabel CR terminator received" IF _tch_screentype%(channel%)=yogi_type% AND _tch_stylus_status%(channel%) THEN _tch_awaiting_stylus%(channel%) = 1 =0 ENDIF IF _tch_superlabel_handler$(channel%)<>"" THEN on_off% = 1 IF _tch_stylus_status%(channel%) = 1 THEN IF RIGHT$(_tch_input_buffer$(channel%),2) = " 0" THEN on_off% = 0 REM so default is on, just in case we've lost track of the stylus status bit ENDIF dummy% = EVAL(_tch_superlabel_handler$(channel%) + """" + _tch_input_buffer$(channel%) + """," + STR$(on_off%) + ")" ) ENDIF _tch_input_buffer$(channel%) = "" =0 OTHERWISE: IF _tch_awaiting_stylus%(channel%)=1 AND _tch_screentype%(channel%)=yogi_type% THEN _tch_awaiting_stylus%(channel%)=0 on_off%=VAL(CHR$(c%)) IF _tch_superlabel_handler$(channel%)<>"" THEN dummy% = EVAL(_tch_superlabel_handler$(channel%) + """" + _tch_input_buffer$(channel%) + """," + STR$(on_off%) + ")" ) ENDIF _tch_input_buffer$(channel%) = "" =0 ENDIF _tch_input_buffer$(channel%) += CHR$(c%) =0 ENDCASE ENDIF =0 DEF FNtch_uppercase_ascii(c%) IF c%>=ASC"a" AND c%<=ASC"z" THEN c%-=32 =c%