_REMOTE CONNECTIVITY FOR PORTABLE TERMINALS: PART I_ by Dan Troy [LISTING ONE] void process_VT100_input(char *z) { char data; TERMINALP t = (TERMINALP)z; /* default VT100 parameters */ if(!eof()) /* if character exists in */ { /* serial buffer */ read(&data); /* then read it */ active = TRUE; /* set global activity flag */ write_screen(t, data); /* process VT100 character */ } } [LISTING TWO] typedef struct { char addlf; /* line feed/new line */ char keymode; /* cursor/application */ char insert; /* replace/insert */ char autowrap; /* off/on */ char keypad; /* numeric/alternate */ char origin; /* absolute/relative */ char kblock; /* keyboard unlock/lock */ }TERMINAL, *TERMINALP; [LISTING THREE] init_emulation_mode: clr ea ;shut off interrupts mov dptr,#emul_processor_address ;get c function address mov a,r3 ;get low byte of function ;from C call movx @dptr,a ;save at storage address inc dptr ;inc processor address ptr mov a,r2 ;get high byte of function movx @dptr,a ;save at storage address setb ea ;turn back on interrupts lcall get_and_decr_stack_pointer ;get data stack ptr ;parameter data struct movx a,@dptr ;get low byte of setup ;parameter data struct xch a,b ;save in b reg lcall get_and_decr_stack_pointer ;adjust data stack ptr movx a,@dptr ;get high byte of setup ;parameter data struct push acc ;save on program stack mov dptr,#data_struct ;get storage address xch a,b movx @dptr,a ;save low byte of setup inc dptr pop acc movx @dptr,a ;save high byte of setup ret [LISTING FOUR] init_emulation_mode(process_VT100_input, (char *) t); [LISTING FIVE] typedef void(*PTF) (); /* a pointer to a function */ extern void init_emulation_mode(PTF, char *); And the VT100 driver can be installed as follows: /* initialize VT100 default parameters */ cursor.row = cursor.col = 1; t->origin = t->addlf = t->keymode = RESET; t->kblock = t->insert = t->autowrap = RESET; t->keypad = NUMERIC; clr_display(); /* clear LINKS display */ init_emulation_mode(process_VT100_input, (char *) t); [LISTING SIX] BEFORE timer0: . . . reti AFTER timer0: . . . jnb in_emul_processor,process_emul ;if the emulation driver reti ;is already running, then ;return from interrupt process_emul: ;else call the driver clr ea ;shut off interrupts while the setb in_emul_processor ;recursion prevention semaphore setb ea ;is set push dph ;protect all registers that the C code driver push dpl ;could possibly use (includes all of bank 3 push psw ;registers) push acc push b push 18h push 19h push 1ah push 1bh push 1ch push 1dh push 1eh push 1fh mov dptr,#return_from_emul_processor ;put return from push dpl ;emulation driver push dph ;on stack mov dptr,#emul_processor_address ;put emulation processor movx a,@dptr ;driver address on stack push acc inc dptr movx a,@dptr push acc mov dptr,#data_struct ;get the pointer to any movx a,@dptr ;data to be passed to mov r2,a ;the C language driver. inc dptr ;pointer address is movx a,@dptr ;stored in r2 and r3 mov r3,a reti ;calls generic emulation driver ;(last address on program stack) [LISTING SEVEN] return_from_emul_processor: pop 1fh ; restore stack prior to call to VT100 driver pop 1eh pop 1dh pop 1ch pop 1bh pop 1ah pop 19h pop 18h pop b pop acc pop psw pop dpl pop dph clr ea ;reset recursion prevention semaphore clr in_emul_processor ;while interrupts are off setb ea . . ret ; gets address of next instruction to execute ; in the routine that had been interrupted by ; timer 0. ; address taken off the 8051 stack and the stack ; pointer is updated [LISTING EIGHT] char *read_VT100_image(char row, char col, char *string, char number_to_read) { short i; char *ptr; if(row <= VT100_MAX_ROWS && col <= VT100_MAX_COLS) { /* calculate number of characters to read on row */ if((number_to_read + col) > (VT100_MAX_COLS+1)) number_to_read = (VT100_MAX_COLS+1) - col; /* get string start address from global screen array */ ptr = &screen[row - 1][col - 1]; /* transfer string to return string array */ for(i = 0; i < number_to_read; i++;) string[i] = *ptr++; str[i] = 0; /* terminate string */ } return(string); } [LISTING NINE] void get_cursor_position(TERMINALP t, char *row, char *col) { /* if cursor origin is relative, then calc row position based on scrolling start position, else use global row position */ if(t->origin == SET)*row = cursor.row - begin.scroll + 1; else *row = cursor.row; *col = cursor.col; } [LISTING TEN] static char screen[24][80]; /* VT100 virtual screen image */ /* put a space character in each virtual image position */ static void clr_display() { short i,j; for(j = 0;j < VT100_MAX_ROWS; j++) for(i = 0;i < VT100_MAX_COLS; i++) screen[j][i]=' '; } [LISTING ELEVEN] static char screen[24][80]; /* VT100 virtual screen image */ char *current, *next, *last; /* put a space character in each virtual image position */ static void clr_display() { current = &screen[0][0]; last = &screen[24 - 1][80 - 1]; do{ *current++ = ' '; *current++ = ' '; *current++ = ' '; *current++ = ' '; *current++ = ' '; *current++ = ' '; *current++ = ' '; *current++ = ' '; *current++ = ' '; *current++ = ' '; }while(current < last); } [LISTING TWELVE] static char screen[24][80]; /* VT100 virtual screen image */ static short begin_scroll_row, end_scroll_row; /* Scroll screen up one row. Last row is blank. */ static void scroll_up() { short i,j; for(j = (begin_scroll_row-1; j<(end_scroll_row-1); i++) for(i = 0;i < VT100_MAX_COLS; i++) screen[j][i]=screen[j+1][i]; for(i = 0;i < VT100_MAX_COLS; screen[j][i] = ' ', i++); } [LISTING THIRTEEN] static char screen[24][80]; /* VT100 virtual screen image */ static char *current, *next, *last; static short begin_scroll_row, end_scroll_row; /* Scroll screen up one row. Last row is blank. */ static void scroll_up() { current = &screen[begin_scroll_row - 1][0]; next = current + 80; last = &screen[end_scroll_row - 1][0]; do{ *current++ = *next++; *current++ = *next++; *current++ = *next++; *current++ = *next++; *current++ = *next++; *current++ = *next++; *current++ = *next++; *current++ = *next++; *current++ = *next++; *current++ = *next++; }while(current < last); last += 80; do{ *current++ = ' '; *current++ = ' '; *current++ = ' '; *current++ = ' '; *current++ = ' '; *current++ = ' '; *current++ = ' '; *current++ = ' '; *current++ = ' '; *current++ = ' '; }while(current < last); } [LISTING FOURTEEN] #include "speedc.h" #include "vt100.h" #include "string.h" void exception_handler(char code); void main() { TERMINAL t; /* define VT100 setup parameters */ char string[21]; char display_string[23]; cursor.row = cursor.col = 1; /* globals defined in vt100.h */ t->origin = t->addlf = t->keymode = 0; t->kblock = t->insert = t-> autowrap = 0; t->keypad = NUMERIC; init_emulation_mode(process_VT100_input, (char *)t); /* prototype in vt100.h */ /* initialize the first 3 lines on the LINKS terminal display by using the special LINKS x function. This function allows the user to define distinct display regions on the terminal. The nomenclature is as follows: D means define a display region which is touch sensitive. 1,2, or 3 means that the touch sensitive area defined will generate transmit that particular ASCII character in the key buffer when that touch sensitive area is pressed on the LINKS screen. This is also referred to as its name. A18; means the touch sensitive display area in row A (first row on the LINKS), columns 1-8 (touch display areas have 8 distinct areas per row). The semicolon means the end of the touch display definition, and what follows is the message to be displayed in that display area. B18; means row B (second row), columns 1-8. C18; means row C (third row), columns 1-8. */ x("D1 A18; "); x("D2 B18; "); x("D3 C18; "); open("98N1",1); /* open LINKS RS232 port with special LINKS operating system function */ /* continuously update LINKS terminal display with the current VT100 virtual image found in rows 1-3, columns 1-20) using read_VT100_scr whose prototype is in vt100.h. */ do{ read_VT100_scr(1, 1, string, 20); /* read row 1, cols 1-20 */ strcpy(display_string, "P1"); /* prefix string with special */ strcat(display_string, string); /* links P cmd (print to touch */ x(display_string); /* display area named '1') */ read_VT100_scr(2, 1, string, 20); /* read row 2, cols 1-20 */ strcpy(display_string, "P2"); /* prefix string with special */ strcat(display_string, string); /* links P cmd (print to touch */ x(display_string); /* display area named '2') */ read_VT100_scr(3, 1, string, 20); /* read row 3, cols 1-20 */ strcpy(display_string, "P3"); /* prefix string with special */ strcat(display_string, string); /* links P cmd (print to touch */ x(display_string); /* display area named '3') */ }while(-1); } /* The exception handler is needed for all LINKS applications to handle special LINKS control functions. */ void exception_handler(char code) { if (code == 4)turn_off(); /* detects ON/OFF button pressed, and turns LINKS off via LINKS turn_off */ }