; WEDGEF64 ; ; Programma per Proteus ; ; (C) 2004 Simone Zanella Productions ; ; Riceve da un dispositivo seriale i dati inviati nel formato Datalogic® wedge protocol (utilizzato da F64/F67) ; e li inserisce in emulazione di tastiera. ; Questo programma può essere installato come script associato al servizio Proteus. ; ; I parametri di comunicazione si trovano all'inizio del programma e sono: ; - COMPORT = porta di comunicazione ("COM1", "COM2", ecc.) ; - COMSPEED = velocità di comunicazione (1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200) ; - COMPARITY = "N" (nessuna), "E" (pari), "O" (dispari), "M" (marca), "S" (spazio) ; - COMDATA = 7 o 8 (bit di dati) ; - COMSTOP = 1 o 2 (bit di stop) ; - COMFLOW = "R" (RTS/CTS detto anche hardware), "X" (XON/XOFF detto anche software), "E" (entrambi), "N" (nessuno) ; - POSTFIX = terminatore (di solito: "{ENTER}") ; ; E' poi possibile specificare: ; - PACE: ritardo dopo l'invio in emulazione di tastiera di ciascuna riga (in secondi); ; - POLLINTERVAL: periodicità (in secondi) con la quale il programma verifica la presenza di dati disponibili ; (default: 0.64); ; - TIMEOUT: timeout (in millisecondi) per la ricezione di un pacchetto dal terminale. ; ; Modificare la funzione ProcessRecord per scegliere quale parte del record inviare. ; ; Il codice commentato più sotto permette anche in alternativa di: ; - selezionare una specifica finestra (applicativo Ultra-Edit) ed inviare il dato verbatim, seguito da Invio; ; - lanciare il blocco note (se non aperto), introdurre il dato verbatim (seguito da Invio) e tornare alla finestra ; iniziale. #!proteus -z -j !include "win32.prt" ; Parametri di comunicazione ; -------------------------- ; Porta seriale COMPORT = "COM1" ; Baud rate COMSPEED = 9600 ; Parità (None, Odd, Even, Mark, Space: solo iniziale) COMPARITY = "E" ; Bit di dati COMDATA = 7 ; Bit di stop COMSTOP = 1 ; Controllo di flusso (Rts/cts, Xon/xoff, Entrambi, Nessuno: solo iniziale) COMFLOW = "N" ; Ritardo interlinea PACE = 0.02 ; Intervallo di polling POLLINTERVAL = 0.64 ; Timeout (in millisecondi) per la ricezione di un pacchetto dal terminale TIMEOUT = 500 ; Terminatore (default = "{ENTER}") POSTFIX = "{ENTER}" ; --------------------------- HCOM = OpenCom(COMPORT, COMSPEED, COMPARITY, COMDATA, COMSTOP, COMFLOW) ACK = CHR(6) NAK = CHR(21) NULL = CHR(0) ESC = CHR(0x1B) CR = CHR(0x0D) LF = CHR(0x0A) ETB = CHR(0x17) EOT = CHR(0x04) PACKETENQ = MKPacket(NULL ESC "5$" ESC CR) WHILE 1 ; Attende per l'intervallo specificato SLEEP(POLLINTERVAL) ; Se non è un servizio e l'utente ha premuto ESC, esce !ifndef SERVICE IF KBDHIT() IF EQ(GETCH(), 27) BREAK FI FI !endif ; Invia la richiesta dati W32WRITEFILE(HCOM, PACKETENQ) NCHAR = W32WAITRXCHAR(HCOM, TIMEOUT) IF NCHAR ; Ricevuti dei caratteri RXWedgeProtocol() FI LOOP W32CLOSEHANDLE(HCOM) ABORT 0 FUNCTION RXWedgeProtocol() lastblock = 0 rxabort = 0 nakcount = 0 _Q = QUEUENEW() lastpacketsent = _PACKETENQ status = 0 WHILE 1 s = W32READCOM(_HCOM, 0) WHILE NOT(STRSTR(s, _LF)) n = W32WAITRXCHAR(_HCOM, _TIMEOUT) IF n s = s W32READCOM(_HCOM, 0) nakcount = 0 ELSE ; In caso di timeout, invia NAK e riprova 2 volte CONSOLELN "s: " s CONSOLELN "TIMEOUT" INC(@nakcount) IF LT(nakcount, 2) s = "" W32READCOM(_HCOM, 0) W32WRITEFILE(_HCOM, lastpacketsent) CONSOLELN "RIPROVO" CONTINUE ELSE ; Troppi NAK: ricezione interrotta (scarta tutti i record ricevuti) rxabort = 1 FI BREAK FI LOOP IF rxabort BREAK FI p = STRSTR(s, _LF) s = LEFT(s, p) record = "" result = CheckFrame(s, @record, @lastblock) consoleln "record: " record W32READCOM(_HCOM, 0) IF result SWITCH status ON 0 ; Verifica se ha ricevuto [xx]<RUN> IF STREQ(RIGHT(record, 5), "<RUN>") W32WRITEFILE(_HCOM, _ACK) ; Resetta il puntatore all'inizio della lista record lastpacketsent = MKPacket(_NULL _ESC "0#" _ESC _CR) W32WRITEFILE(_HCOM, lastpacketsent) INC(@status) consoleln "RUN OK, INVIATO 0#" ELSE ; Record valido: lo accodo lastpacketsent = _NAK W32WRITEFILE(_HCOM, _ACK) status = 2 IF NOT(lastblock) ENQUEUE(_Q, record) FI ; W32WRITEFILE(_HCOM, _NAK) FI ON 1 IF STREQ(LEFT(record, 5), "<ACK>") W32WRITEFILE(_HCOM, _ACK) ; Chiede i primi 100 record lastpacketsent = MKPacket(_NULL _ESC "0#100" _ESC _CR) W32WRITEFILE(_HCOM, lastpacketsent) INC(@status) consoleln "ACK OK, INVIATO 0#100" ELSE ; Record valido: lo accodo lastpacketsent = _NAK W32WRITEFILE(_HCOM, _ACK) INC(@status) IF NOT(lastblock) ENQUEUE(_Q, record) FI ;W32WRITEFILE(_HCOM, _NAK) FI ON 2 ; Record valido: lo accodo lastpacketsent = _NAK W32WRITEFILE(_HCOM, _ACK) IF NOT(lastblock) ENQUEUE(_Q, record) FI OFF ELSE ; Record non valido W32WRITEFILE(_HCOM, _NAK) FI IF lastblock IF EQ(lastblock, 1) ; Ricevuto ETB, attendo EOT lastblock = 0 ; Chiedo altri 100 record (se ci sono) lastpacketsent = MKPacket(_NULL _ESC "0#100" _ESC _CR) W32WRITEFILE(_HCOM, lastpacketsent) status = 2 ELSE BREAK FI FI LOOP IF NOT(rxabort) EmulateKeyboard(_Q) FI QUEUEFREE(_Q) RETURN FUNCTION MKPacket(s) RETURN s CalcLRC(s) _LF FUNCTION CheckFrame(s, record, lastblock) ; L'inizio del frame è invalido? IF STRNEQ(LEFT(s, 2), _NULL _NULL) IF STRNEQ(LEFT(s, 1), _NULL) RETURN 0 ELSE s = _NULL s FI FI ; Verifica la fine del blocco IF STRNEQ(RIGHT(s, 1), _LF) RETURN 0 FI ; Elimina la fine del blocco s = LEFT(s, -1) ; Isola l'LRC lrc = RIGHT(s, 1) ; Elimina l'LRC s = LEFT(s, -1) IF STRNEQ(RIGHT(s, 1), _CR) RETURN 0 FI ; Verifica l'LRC IF NOT(VerifyLRC(lrc, s)) RETURN 0 FI ; Elimina i NULL iniziali s = RESTFROM(s, 3) ; Elimina il CR finale s = LEFT(s, -1) ; Verifica se è l'ultimo blocco e aggiorna i parametri SWITCH LEFT(s, 1) STREQ ON _EOT lastblock = 1 ON _ETB lastblock = 2 OTHER lastblock = 0 OFF ; Memorizza il record record = s RETURN 1 FUNCTION CalcLRC(s) acc = 0 l = STRLEN(s) ; XOR di tutti i caratteri in s FOR x = 1 to l NXOR(@acc, ASC(SUBSTR(s, x, 1))) NEXT RETURN CHR(acc) FUNCTION VerifyLRC(lrc, s) RETURN STREQ(lrc, CalcLRC(s)) FUNCTION EmulateKeyboard(q) ; Variante con salvataggio/ripristino finestra corrente e selezione blocco notes ; ; Preleva la finestra corrente ; hOld = W32GETFOCUS() ; ; ; Cerca il blocco notes ; hNotepad = W32FINDWINDOW("*Blocco note*") ; IF EQ(hNotepad, 0) ; ; Non trovato - lo lancia ; W32SHELL("NOTEPAD.EXE") ; ; Attende un secondo che si renda disponibile ; SLEEP(1) ; ; Cerca la sua finestra nuovamente ; hNotepad = W32FINDWINDOW("*Notepad*") ; FI ; ; Se trovato, seleziona la sua finestra ed invia i dati ; IF EQ(hNotepad, 0) ; W32SETFOCUS(hOld) ; RETURN ; FI ; W32SETFOCUS(hNotepad) WHILE QUEUELEN(q) W32SENDKEYS(KTrans(DEQUEUE(q)) _POSTFIX) SLEEP(_PACE) LOOP ; Variante - ripristina la vecchia finestra ; W32SETFOCUS(hOld) RETURN FUNCTION KTrans(s) l = STRLEN(s) r = "" FOR x = 1 TO l c = SUBSTR(s, x, 1) ; Mappatura dei caratteri speciali: caratteri che non si trovano ; sulla tastiera potrebbero richiedere l'introduzione della sequenza ; con ALT + numero SWITCH c STREQ ON "~" r = r "{ALT DOWN}{NUMPAD1}{NUMPAD2}{NUMPAD6}{ALT UP}" ON "{" r = r "{ALT DOWN}{NUMPAD1}{NUMPAD2}{NUMPAD3}{ALT UP}" ON "}" r = r "{ALT DOWN}{NUMPAD1}{NUMPAD2}{NUMPAD5}{ALT UP}" ON "+", "^", "%", "(", ")", "[", "]" r = r "{" c "}" OTHER r = r c OFF NEXT RETURN r FUNCTION OpenCom(comport, comspeed, comparity, comdata, comstop, comflow) ; Apre la porta seriale con i parametri specificati hcom = W32CREATEFILE(comport, NOR(_W32_GENERIC_WRITE, _W32_GENERIC_READ), 0, \ _W32_OPEN_EXISTING, 0) IF EQ(hcom, -1) !ifndef SERVICE CONSOLELN "Impossibile aprire " comport "." !endif ABORT 2 FI compar = VECNEW(13) v = W32GETCOMSTATE(hcom, compar) VECSET(compar, 2, comspeed) v = NOR(_W32_COM_BINARY, _W32_COM_PARITY_ON) SWITCH LEFT(comflow, 1) STRIEQ ON "R" NOR(@v, _W32_COM_RTS_HANDSHAKE, _W32_COM_CTSFLOW_ON) ON "X" NOR(@v, _W32_COM_XONXOFF_OUT, _W32_COM_XONXOFF_IN, _W32_COM_XOFF_CONTINUE) ON "E" NOR(@v, _W32_COM_RTS_HANDSHAKE, _W32_COM_CTSFLOW_ON, \ _W32_COM_XONXOFF_OUT, _W32_COM_XONXOFF_IN, _W32_COM_XOFF_CONTINUE) ON "N" OFF VECSET(compar, 3, v) VECSET(compar, 7, comdata) SWITCH LEFT(comparity, 1) STRIEQ ON "N" v = _W32_COM_PARITY_NONE ON "E" v = _W32_COM_PARITY_EVEN ON "O" v = _W32_COM_PARITY_ODD ON "M" v = _W32_COM_PARITY_MARK ON "S" v = _W32_COM_PARITY_SPACE OFF VECSET(compar, 8, v) SWITCH comstop ON 1 VECSET(compar, 9, 0) ON 2 VECSET(compar, 9, 2) OFF v = W32SETCOMSTATE(hcom, compar) VECFREE(compar) IF v !ifndef SERVICE CONSOLELN "Errore nell'impostazione della porta (" W32GETLASTERROR() ")." !endif W32CLOSEHANDLE(hcom) ABORT 3 FI tout = VECNEW(5) VECSET(tout, 1, 0) VECSET(tout, 2, 0) VECSET(tout, 3, 0) VECSET(tout, 4, 0) VECSET(tout, 5, 0) W32SETCOMTIMEOUTS(hcom, tout) VECFREE(tout) RETURN hcom