/***************************************************************************/ /* */ /* 730DR232.C - Demonstration package containing the 730D RS232 */ /* Communication routines. */ /* */ /* V1.00 01/10/96 */ /* V1.01 06/01/96 added frequency, TTL I/O, dac, ref, etc.. */ /* */ /***************************************************************************/ #include "disp.h" #include "stdio.h" #include "stdlib.h" void Setup_RS232(int); int out_message(int); int tttimer(struct INT_DATA *pd); void reset_buffer(void); int send_command(char address, char *command); int receive_command(char address, char *command, int flag); void setuptimer(void); int send_and_wait(char *buff, unsigned timetowait); void position_and_print(int y, int x, char *buff); char CheckSum (char *buff); char CheckCheckSum (char *buff); int receive_binary_data(char *, int, int); void UploadBufferedData(char *buff); // These functions will handle the BUFFER and STRING manipulations for // incoming and outgoing DATA to the SERIAL PORT #define B0 0x01 #define B1 0x02 #define B2 0x04 #define B3 0x08 #define B4 0x10 #define B5 0x20 #define B6 0x40 #define B7 0x80 #define MAXFILES 6 #define MAX_BUFFER 255 /* Circular buffer size */ struct mess_packet { char mess[MAX_BUFFER + 1], retry, /* set to 5 when built */ addressout; /* address to send the character to */ }; /* some useful definitions */ #define TRUE 1 #define FALSE !TRUE #define ON 1 #define OFF 0 /* Definitions for communications */ #define HOST_ADDRESS (0) #define APP_ADDRESS (1) #define ACK (char) 0x06 #define EOT (char) 0xFF #define ETX (char) 0x03 #define NAK (char) 0x15 #define STX (char) 0x02 /* * RS232 equates */ #define COM2 (11) #define COM1 (12) /* * parity equates */ #define NONE (0x00) #define EVEN (0x03) #define ODD (0x01) /* * register equates */ int ioport; #define C1 (0x3f8) #define C2 (0x2f8) #define THR (ioport+0) /* data in register / LOW baud register */ #define RBR (ioport+0) /* data out register */ #define IER (ioport+1) /* High baud register LCR B7 high*/ #define IIR (ioport+2) /* Interrupt identification register */ #define LCR (ioport+3) /* line control register */ #define MCR (ioport+4) /* Modem control resgister */ #define LSR (ioport+5) /* line status register */ #define BRGCLOCK (1843200l) /* BRG clock speed */ #define RTCCLOCK (1192737.0l) /* BRG clock speed */ union { struct { unsigned sent_eot : 1; unsigned sent_address : 1; unsigned go : 1; unsigned end_message : 1; unsigned received_eot : 1; unsigned receive_data : 1; unsigned receive_binary_data : 1; unsigned sent_ack_nak : 1; unsigned transmit_data : 1; unsigned transmit_done : 1; unsigned device_to_send : 1; unsigned device_to_send_binary : 1; unsigned transaction_done : 1; unsigned RNAK : 1; unsigned sent_nak : 1; unsigned dummy : 1; } b; unsigned word; } f; // // Special variables for binary transfer of large data blocks // char *binary_buffer = NULL; /* dynamically allocated on the fly when necessary */ int BinaryMessageAvailable; /*trigger to indicate the end of the transfer */ int BinaryByteCount; long baud = 9600; /* rates: 110, 300, 1200, 2400, 4800, 9600 */ int numbits = 8, /* number of data bits: 7 or 8 */ parity = NONE, /* parity choices: NONE, EVEN or ODD */ stopbits = 1; /* number of stop bits: 1 or 2 */ int MessageAvailable = 0; /* Holds # of messages in buffer */ int iir, iis; /* what mode are you in */ int data_to_send = 0, top_out = 0, bottom_out = 0, top_in = 0, bottom_in = 0; int restart_transfer; /* used to indicate polling only */ char addressout, lch; char inbuff[6][260]; struct mess_packet outbuff[6]; unsigned tttticker, ticker1, ticker3; int sending_z_command = 0; /* flag the z command so user can't abort an abort */ char *menustring = "\ \n\n =====Optronic Laboratories, Inc, 1996 ===== RS-232\n\n\ 1) Reset 730D Communications G) Select Reference\n\ 2) Read Luminance H) Set Notch Filters\n\ 3) Read Detector Current or Voltage I) Select DAC Outputs\n\ 4) Zero Dark Current or Voltage J) Select Update Rate\n\ 5) Select Units (0-3) K) Set Dynamic Reserve\n\ 6) Set Gain Range (>0=auto) L) Read Tristimulus\n\ 7) Normalize Reading M) Download from File\n\ 8) Set PMT Voltage (-200 - -1100) N) Upload to File\n\ 9) Select Detector (1-25) O) Set number of Points to buffer\n\ A) Set Resp. Time(0--10)(0.0033-4096) P) Trigger the photometer\n\ B) Select Input (0-6) R) Arm External Trigger\n\ C) Read Memory Hold Location (1-99) S) Upload Binary Buffer\n\ D) Remote Enter Key T) Set TTL I/O\n\ E) Read Frequency Q) Quit\n\ F) Set Frequency\n\ \n\nEnter your choice < >\b\b\ "; void main(int argv, char **argc) { FILE *fptr; double tempf1; int tempi1,tempi2,tempi3, port; char tempc1,tempc2,tempc3,ch,i; char buff[300], detbuff[40], c; int done = 0; int old_8259 = inp(0x21); disp_open(); disp_usebios(); disp_move(0,0); disp_eeop(); port = COM1; if(argv > 1) { port = (atoi(argc[1]) < 2) ? COM1 : COM2; } Setup_RS232(port); reset_buffer(); setuptimer(); /* build menu screen here */ disp_printf(menustring); while(!done) { c = getch(); switch(toupper(c)) { case '1': // reset 730d communications send_z_command(); break; case '2': // get luminance sprintf(buff, "l ",tempf1); if(send_and_wait(buff, 100)) { position_and_print(23, 0, buff); } break; case '3': // get current sprintf(buff, "c ",tempf1); if(send_and_wait(buff, 100)) { position_and_print(23, 0, buff); } break; case '4': // zero dark current sprintf(buff, "D "); if(send_and_wait(buff, 100)) { position_and_print(23, 0, buff); CheckCheckSum(buff); } break; case '5': // select units position_and_print(21,0,"Enter the units value: "); scanf("%d", &tempi1); position_and_print(21,0, ""); sprintf(buff, "U %d", tempi1); if(send_and_wait(buff, 100)) { position_and_print(23, 0, buff); } break; case '6': // set gain range position_and_print(21,0,"Enter the gain range value: "); scanf("%d", &tempi1); position_and_print(21,0, ""); sprintf(buff, "G %d", tempi1); if(send_and_wait(buff, 100)) { position_and_print(23, 0, buff); } break; case '7': // Normalize the reading sprintf(buff, "N "); if(send_and_wait(buff, 100)) { position_and_print(23, 0, buff); } break; case '8': // set PMT voltage position_and_print(21,0,"Enter the PMT voltage: "); scanf("%d", &tempi1); position_and_print(21,0, ""); sprintf(buff, "V %d", tempi1); if(send_and_wait(buff, 100)) { position_and_print(23, 0, buff); } break; case '9': // select detector position_and_print(21,0,"Enter the detector number (1 - 25): "); scanf("%d", &tempi1); position_and_print(21,0, ""); sprintf(buff, "S %d", tempi1); if(send_and_wait(buff, 100)) { position_and_print(23, 0, buff); } break; case 'A': // set Response time position_and_print(21,0,"Enter the range + response time: "); scanf("%d %lf", &tempi1,&tempf1); position_and_print(21,0, ""); sprintf(buff, "R %d %lf", tempi1, tempf1); if(send_and_wait(buff, 100)) { position_and_print(23, 0, buff); } break; case 'B': // select Input position_and_print(21,0,"Enter the input source number: "); scanf("%d", &tempi1); position_and_print(21,0, ""); sprintf(buff, "I %d", tempi1); if(send_and_wait(buff, 100)) { position_and_print(23, 0, buff); } break; case 'C': // recall memory position_and_print(21,0,"Enter the location number: "); scanf("%d", &tempi1); position_and_print(21,0, ""); sprintf(buff, "M %d ", tempi1); if(send_and_wait(buff, 100)) { position_and_print(23, 0, buff); } break; case 'D': // Remote Enter Key sprintf(buff, "E "); if(send_and_wait(buff, 100)) { position_and_print(23, 0, buff); } break; case 'E': // Read Frequency sprintf(buff, "f "); if(send_and_wait(buff, 100)) { position_and_print(23, 0, buff); } break; case 'F': // Set Frequency position_and_print(21,0,"Enter the frequency: "); scanf("%lf", &tempf1); position_and_print(21,0, ""); sprintf(buff, "F %lf", tempf1); if(send_and_wait(buff, 100)) { position_and_print(23, 0, buff); } break; case 'G': // select the reference source position_and_print(21,0,"Select Reference (0=CHOPPER, 1=INT, 2=EXT) "); scanf("%d", &tempi1); position_and_print(21,0, ""); sprintf(buff, "H %d ", tempi1); if(send_and_wait(buff, 100)) { position_and_print(23, 0, buff); } break; case 'H': // setup the notch filters position_and_print(21,0,"Enable 50/60Hz notch (0=NO, 1=YES): "); scanf("%d", &tempi1); position_and_print(21,0, ""); position_and_print(21,0,"Enable 100/120Hz notch (0=NO, 1=YES): "); scanf("%d", &tempi2); position_and_print(21,0, ""); tempi2<<=1; tempi1|=tempi2; sprintf(buff, "Q %d ", tempi1); if(send_and_wait(buff, 100)) { position_and_print(23, 0, buff); } break; case 'I': // select dac outputs position_and_print(21,0,"Enter DAC output (1 or 2): "); scanf("%d", &tempi1); position_and_print(21,0, ""); position_and_print(21,0,"Enter Selection (0-8): "); scanf("%d", &tempi2); position_and_print(21,0, ""); sprintf(buff, "O %d %d", tempi1,tempi2); if(send_and_wait(buff, 100)) { position_and_print(23, 0, buff); } break; case 'J': // select the update rate position_and_print(21,0,"Select Update Rate (0=300Hz,1=60Hz,2=50Hz,3=10Hz,4=2Hz) "); scanf("%d", &tempi1); position_and_print(21,0, ""); sprintf(buff, "W %d ", tempi1); if(send_and_wait(buff, 100)) { position_and_print(23, 0, buff); } break; case 'K': // Set Dynamic Reserve position_and_print(21,0,"Enter the dynamic reserve (0,20,40,60,80): "); scanf("%d", &tempi1); position_and_print(21,0, ""); sprintf(buff, "K %d", tempi1); if(send_and_wait(buff, 100)) { position_and_print(23, 0, buff); } break; case 'L': // Read Tristimulus sprintf(buff, "@ "); if(send_and_wait(buff, 100)) { position_and_print(23, 0, buff); } break; case 'M': // download a detector file // fptr=fopen("730d.txt","r"); tempi1=0; i=1; ch=0; position_and_print(21,0,"Enter the filename: "); scanf("%s", &buff); if((fptr=fopen(buff,"r"))==NULL) { position_and_print(21,0,"Can't open file !"); break; } printf("%c",'\n'); // look for a new detector record while(i) { ch=getc(fptr); switch(ch) { case EOF: i=0; break; case'\n': ch=getc(fptr); while(ch=='\r' || ch=='\n') { if(ch=='\n') i=1; ch=getc(fptr); } if(ch=='|') i++; break; } while((i>1)&&(i!=9)) // a detector record was found { if(i==2) // look for top line of description { fscanf(fptr,"%d",&tempi1); if(tempi1>=1 && tempi1<=25) { ch=getc(fptr); tempi2=0; // download line 1 of description while(((ch=getc(fptr))!='|') && tempi2<17) { sprintf(buff, "X %2d %2d ", tempi1, tempi2); buff[8]=ch; tempi2++; if(send_and_wait(buff, 100)) position_and_print(23, 0, buff); } i++; } else i=0; } // download cal factor while(i==3) { ch=getc(fptr); if(ch=='|') { tempi2=70; tempi3=8; sprintf(buff, "X %2d %2d ", tempi1, tempi2); ch=getc(fptr); while(ch=='E'||ch=='e'||ch==' '||ch=='.'||ch=='+'||ch=='-'||(ch>='0'&&ch<='9')) { buff[tempi3]=ch; tempi3++; ch=getc(fptr); } if(tempi3==8) sprintf(&buff[8],"+0.0E+00"); else buff[tempi3]=0; if(send_and_wait(buff, 100)) position_and_print(23, 0, buff); i=5; } else if(ch!=' ') i=0; } // download input type if(i==5) { ch=getc(fptr); while((ch!='|') && i) { if(ch==EOF || ch=='\n') i=0; ch=getc(fptr); } } while(i==5) { while(ch==' '||ch=='\t') ch=getc(fptr); if(ch>='0' || ch<='9') { sprintf(buff, "X %2d 61 ", tempi1); buff[8]=ch; if(send_and_wait(buff, 100)) position_and_print(23, 0, buff); i=7; } else if(ch==EOF) i=0; else // default to dc current /dc coupling { sprintf(buff, "X %2d 61 2 ", tempi1); if(send_and_wait(buff, 100)) position_and_print(23, 0, buff); if(ch=='\n') // default to hv off { sprintf(buff, "X %2d 60 0 ", tempi1); if(send_and_wait(buff, 100)) position_and_print(23, 0, buff); i=10; } else i+=2; // skip muxaddress ungetc(ch,fptr); } } // download hv level if(i==7) { ch=getc(fptr); while(ch==' '||ch=='\t') ch=getc(fptr); tempi2=8; sprintf(buff, "X %2d 60 ", tempi1); while((ch>='0' && ch <='9')||ch=='+'||ch=='-') { buff[tempi2]=ch; tempi2++; ch=getc(fptr); } if(tempi2>8) { buff[tempi2]=0x00; i++; } else { buff[tempi2]='0'; i=10; ungetc(ch,fptr); } if(send_and_wait(buff, 100)) position_and_print(23, 0, buff); } // download flux limit if(i==8) { while(ch==' '||ch=='\t') ch=getc(fptr); tempi2=8; sprintf(buff, "X %2d 80 ", tempi1); while((ch>='0' && ch <='9')||ch=='+'||ch=='-'||ch=='.') { buff[tempi2]=ch; tempi2++; ch=getc(fptr); } if(tempi2>8) buff[tempi2]=0x00; else { buff[tempi2]='1'; tempi2++; buff[tempi2]=0x00; } if(send_and_wait(buff, 100)) position_and_print(23, 0, buff); i=10; ungetc(ch,fptr); } // download line 2 of description if(i==10) { while(ch!='|') ch=getc(fptr); tempi2=17; while(((ch=getc(fptr))!='|') && tempi2<37) { sprintf(buff, "X %2d %2d ", tempi1, tempi2); buff[8]=ch; tempi2++; if(send_and_wait(buff, 100)) position_and_print(23, 0, buff); } i++; ch=getc(fptr); } // download units while(i==11) { ch=getc(fptr); if(ch=='|') { tempi2=40; while(((ch=getc(fptr))!='|') && tempi2<60) { sprintf(buff, "X %2d %2d ", tempi1, tempi2); buff[8]=ch; tempi2++; if(send_and_wait(buff, 100)) position_and_print(23, 0, buff); } i=1; } else if(ch==EOF||ch=='\n') i=0; } } } fclose(fptr); break; case 'N': // upload a detector file // fptr=fopen("730d.txt","w"); position_and_print(21,0,"Enter the filename: "); scanf("%s", &buff); if((fptr=fopen(buff,"w"))==NULL) { position_and_print(21,0,"Can't open file !"); break; } fputs(" CAL FACTOR AND DET PMT PMT\n",fptr); fputs(" DETECTOR DESCRIPTION UNITS DESCRIPTION INPUT VOLTS LIMIT(uA)\n",fptr); fputs("-------------------------------------------------------------------\n",fptr); tempi1=0; while(tempi1<26) { buff[9]=0x7f; while((buff[9]==0x7f||buff[9]==1) && tempi1<25) { tempi1++; sprintf(buff, "Y %2d 0 ", tempi1); if(send_and_wait(buff, 100)) position_and_print(23, 0, buff); } if(tempi1>25 || buff[9]==0x7f || buff[9]==1) break; tempi2=0; fprintf(fptr,"%c|%2d:",'\n',tempi1); // upload the 1st line of description while(tempi2<17) { sprintf(buff, "Y %2d %2d", tempi1,tempi2); if(send_and_wait(buff, 100)) position_and_print(23, 0, buff); putc(buff[9],fptr); tempi2++; } fputs("| | ",fptr); // upload the cal factor sprintf(buff, "Y %2d 70", tempi1); if(send_and_wait(buff, 100)) position_and_print(23, 0, buff); tempi2=9; while(tempi2<20 && buff[tempi2]!=0) { putc(buff[tempi2],fptr); tempi2++; } // upload the input type sprintf(buff, "Y %2d 61", tempi1); if(send_and_wait(buff, 100)) position_and_print(23, 0, buff); if(buff[9]=='0'||buff[9]=='1'||buff[9]=='2') fputs(" amps/ | ",fptr); else if(buff[9]=='3'||buff[9]=='4'||buff[9]=='5') fputs(" volts/ | ",fptr); else if(buff[9]=='6') fputs(" counts/| ",fptr); fputc(buff[9],fptr); //print the input type code // upload the hv level, limit sprintf(buff, "Y %2d 60", tempi1); if(send_and_wait(buff, 100)) position_and_print(23, 0, buff); buff[14]=0; sscanf(&buff[9],"%d",&tempi2); if(tempi2!=0) { tempi2=9; while(tempi2<15) { putc(buff[tempi2],fptr); tempi2++; } fputs(" ",fptr); sprintf(buff, "Y %2d 80", tempi1); if(send_and_wait(buff, 100)) position_and_print(23, 0, buff); tempi2=9; while(tempi2<15) { putc(buff[tempi2],fptr); tempi2++; } } fputs("\n|",fptr); // upload the 2nd line of description tempi2=17; while(tempi2<37) { sprintf(buff, "Y %2d %2d", tempi1,tempi2); if(send_and_wait(buff, 100)) position_and_print(23, 0, buff); putc(buff[9],fptr); tempi2++; } fputs("| |",fptr); // upload the units description tempi2=40; while(tempi2<60) { sprintf(buff, "Y %2d %2d", tempi1,tempi2); if(send_and_wait(buff, 100)) position_and_print(23, 0, buff); putc(buff[9],fptr); tempi2++; } fputs("|\n",fptr); } fclose(fptr); break; case 'O': // Set the number of points to read position_and_print(21,0,"Enter the number of points to read (1 to 2000): "); scanf("%d", &tempi1); position_and_print(21,0, ""); // // guard the range // if(tempi1<1) tempi1 = 1; else if(tempi1 > 2000) tempi1 = 2000; sprintf(buff, "P %d", tempi1); if(send_and_wait(buff, 100)) { position_and_print(23, 0, buff); } break; case 'P': // Trigger the photometer and take a reading sprintf(buff, "J "); if(send_and_wait(buff, 100)) { UploadBufferedData(buff); } break; case 'R': // setup the external trigger mode position_and_print(21,0,"Enter Trigger Pin (1 or 2): "); scanf("%d", &tempi1); position_and_print(21,0, ""); position_and_print(21,0,"Enter Trigger Mode (0 - Off, 1 - FE, 2 - RE, 3 - RE|FE): "); scanf("%d", &tempi2); // // guard the pin // if(tempi1<1) tempi1 = 1; else if(tempi1 > 2) tempi1 = 2; // // guard the mode if(tempi2<0) tempi2 = 0; else if(tempi2 > 3) tempi2 = 3; sprintf(buff, "A%d %d", tempi1,tempi2); if(send_and_wait(buff, 100)) { position_and_print(23, 0, buff); } break; case 'S': // upload the buffer memory from the 730D sprintf(buff, "B "); if(send_and_wait(buff, 100)) { UploadBufferedData(buff); } break; case 'T': // Set the TTL outputs, Read the trigger states position_and_print(21,0,"Enter the TTL outputs in binary form: "); scanf("%b", &tempi1); position_and_print(21,0, ""); sprintf(buff, "T %2X", tempi1); if(send_and_wait(buff, 100)) { position_and_print(23, 0, buff); } break; case 'Q': done=1; break; } } /* restore the interrupt vectors */ int_restore(8); int_restore(port); outp(0x21, old_8259); } //------------------------------------------------------------------------- // This routine will be used to upload the buffered data from the 730D // controller. // // Command 'B' - Says enter binary buffer transfer mode // // The instrument will respond with an ASCII string that identifies the // number of elements, the type of data and the exponent of the data. // // "B # T E" Where, // B is the command. // # is the number of elements to be received. // T is the type of data i.e. 0 for Fixed float point (2 bytes per point) // 1 for floating point (4 bytes per point // E is the exponent of he data. // void UploadBufferedData (char *buff) { int elements, type, exponent, numbytes, i; void *retbuf; float *darray; int *iarray; FILE *fp; // pick off the elements, the data type and the exponents sscanf(buff, "%*c%*c%d%d%d", &exponent, &type, &elements); numbytes = elements * ((type == 0) ? sizeof(short int) : sizeof(float)); sprintf(buff, "Entering binary transfer mode: Reading %d bytes. Please Wait", numbytes); position_and_print(23, 0, buff); retbuf = malloc(numbytes + 20); // // be sure memory could be allocated // if(retbuf == NULL ) { position_and_print(23, 0, "Memory Allocation Error. Function aborted"); return; } // Go receive the binary data from the device if(receive_binary_data(retbuf, APP_ADDRESS, numbytes)) { position_and_print(23, 0, "Binary Data received, conversion in process..."); // // Need to convert from fixed floating point to floating point if(type == 0) { darray = malloc(elements * sizeof(float)); iarray = retbuf; for(i=0; i BinaryByteCount) { f.b.receive_binary_data = 0; if((chk_sum & 0x7f)== (lch & 0x7f)) { lch = ACK; BinaryMessageAvailable = 1; f.b.sent_nak = 0; } else { lch = NAK; f.b.sent_nak = 1; } f.b.sent_ack_nak = 1; f.b.go = 0; chk_sum = 0; outp(THR,lch); } chk_sum += lch; } else if(lch == EOT) /* I am a device being awakened */ { outp(MCR, inp(MCR) & 0x0d); f.b.received_eot = 1; } else if(f.b.received_eot) // device reading address { f.b.received_eot = 0; if((lch & 0x7f) == HOST_ADDRESS) { outp(MCR, (inp(MCR) | B1)); if(lch & B7) { if(data_to_send) { i = 0; f.b.transmit_data = f.b.go = 1; outp(THR, ACK); } else { f.b.go = 0; outp(THR, NAK); } } else { if(MessageAvailable < 6) { f.b.go = f.b.receive_data = 1; i = chk_sum = 0; outp(THR, ACK); } else { f.b.go = f.b.receive_data = 0; outp(THR, NAK); } } } else { f.b.go = 0; f.b.transaction_done = 1; } } else if(f.b.receive_data) // host or device receiving data { inbuff[top_in][i] = lch; if(i && (inbuff[top_in][i-1] == ETX)) // when i > 0 look for end { inbuff[top_in][i+1] = '\000'; f.b.receive_data = 0; if((chk_sum & 0x7f)== lch) { lch = ACK; MessageAvailable++; if(++top_in > 5) top_in = 0; f.b.sent_nak = 0; } else { lch = NAK; f.b.sent_nak = 1; } f.b.sent_ack_nak = 1; f.b.go = 0; chk_sum = 0; outp(THR,lch); } else { chk_sum+= lch; i++; } } else if(f.b.transmit_done) { f.b.go = f.b.transmit_data = f.b.transmit_done = 0; f.b.transaction_done = 1; if(lch == ACK) { if(data_to_send) { data_to_send--; if(++bottom_out > 5) bottom_out = 0; } } } else if(f.b.sent_address) { f.b.sent_address = 0; if(lch == ACK) { chk_sum = i = 0; f.b.go = 1; if(f.b.device_to_send) { f.b.receive_data = 1; /* be sure and wrap the buffer pointers */ } else if(f.b.device_to_send_binary) { f.b.receive_binary_data = 1; /* be sure and wrap the buffer pointers */ } else { f.b.transmit_data = 1; lch = outbuff[bottom_out].mess[i++]; outp(THR,lch); } } else { f.b.transaction_done = 1; /* signal apps layer that transaction completed right or wrong */ if(!restart_transfer) { if(data_to_send) { data_to_send--; if(++bottom_out > 5) bottom_out = 0; } } } } } else // transmit register has emptied { if(f.b.sent_eot) { outp(THR,outbuff[bottom_out].addressout); i = 0; f.b.sent_eot = 0; f.b.sent_ack_nak = 0; f.b.transmit_done = 0; f.b.receive_binary_data = 0; f.b.device_to_send_binary = 0; f.b.sent_address = 1; if(outbuff[bottom_out].addressout & B7) f.b.device_to_send = 1; else if(outbuff[bottom_out].addressout & B6) f.b.device_to_send_binary = 1; } else if(f.b.sent_ack_nak) { f.b.go = f.b.sent_ack_nak = 0; f.b.transaction_done = 1; if(f.b.device_to_send || f.b.device_to_send_binary) { if(f.b.sent_nak) /* restart process if failed */ { f.word = 0; // reset al bit flags f.b.sent_eot = 1; outp(THR,EOT); // Initiate comm process } else { if(data_to_send) { data_to_send--; if(++bottom_out > 5) bottom_out = 0; } } } } else if(f.b.transmit_data && !f.b.transmit_done) // host or device sending data { lch = outbuff[bottom_out].mess[i++]; if(i>1 && (outbuff[bottom_out].mess[i-2] == ETX)) { f.b.transmit_done = 1; } outp(THR,lch); } } outp(0x20, 0x20); return(1); } /*----------------------------------------------------------------------- CheckSum will accumulate the values of the bytes in the buffer together and mask it with 7F hex to prevent a EOT on the line parameters : buffer - contains the values to accumulate -----------------------------------------------------------------------*/ char CheckSum(char *buffer) { char chk = 0; do { chk += *buffer++; } while (*buffer); chk = chk & 0x7F; return(chk); } /*----------------------------------------------------------------------- CheckCheckSum will accumulate the values of the bytes in the buffer (excluding the last byte which is the received checksum), clr the msb, and compare it with the received checksum parameters : buffer - contains the values to accumulate -----------------------------------------------------------------------*/ char CheckCheckSum(char *buffer) { char chk = 0; int itemp1; char ctemp1,ctemp2; itemp1=strlen(buffer); ctemp2=buffer[--itemp1]; /* save the recieved checksum */ buffer[itemp1]=0; /* write 0 over the checksumm */ ctemp1=CheckSum(buffer); /* calculate the checksum of the received string */ if(ctemp1!=ctemp2) /* if checksums don't match */ { chk=1; sprintf(buffer,"Checksum Error: calculated %02X, received %02X",(int)ctemp1,(int)ctemp2); position_and_print(22, 0,buffer); } return(chk); } /*-------------------------------------------------------------------- make_string will build the necessary string and insert the correct command protocols in the buffer. The start and end will need to be inserted into the buffer along with a call to CheckSum. parameters : Command : to tell the device what action to take 'W' - WAVE type of command CommandValue - to scale the command .. depends on command --------------------------------------------------------------------*/ char make_string (char Command, char *CommandValue, char *buffer) { int BufSize; char TChk; if(data_to_send < 6) { if(Command) sprintf(buffer,"%c%c%s%c\000", STX, Command, CommandValue, ETX); else sprintf(buffer,"%c%s%c\000", STX, CommandValue, ETX); // calculate the checksum and put the checksum in the buffer BufSize = strlen(buffer); TChk = CheckSum(buffer); buffer[BufSize++] = TChk; buffer[BufSize] = '\000'; if(++top_out > 5) top_out = 0; data_to_send++; return(1); } else { return(0); } } /*--------------------------------------------------------------------- init_trans wil initiate the data transfer process. device_address : device address (high bit on = device send.) ----------------------------------------------------------------------*/ void init_trans(void) { f.word = 0; // reset al bit flags ticker3 = 31; // Update the time if(outbuff[bottom_out].addressout & B7) { outp(MCR, inp(MCR) | B1); f.b.sent_eot = 1; outp(THR,EOT); // Initiate comm process } else { if(data_to_send) { outp( MCR, inp(MCR) | B1); f.b.sent_eot = 1; outp(THR,EOT); // Initiate comm process } } } /* -------------------------------------------------------------- * * Function : reset_buffer() * * Purpose : This function clears the buffer to a zero state. * * Entry : none. * * Return : none. ----------------------------------------------------------------*/ void reset_buffer(void) { sending_z_command = f.word = data_to_send = top_in = top_out = bottom_in = bottom_out = MessageAvailable = 0; /* clear any previous messages */ } /* -------------------------------------------------------------- * * Function : initCOM() * * Purpose : This function is responsible for initializing * the communications chip * * Entry : (global) stopbits = 1 or 2 * parity = NONE, EVEN, ODD * numbits = 7 or 8 * Return : none. -----------------------------------------------------------------*/ void initCOM(int port) { int i, comdata, outbaud; outp(IER, 0); /* disable interrupts */ comdata = 0; comdata = comdata | (numbits-5); /* set # of data bits */ comdata = comdata | ((stopbits-1) << 2); /* set # of stopbits */ comdata = comdata | (parity << 3); /* set parity */ // set the line control register to allow setting the BAUD int_off(); outp(LCR, 0x80); /* set bit 7*/ outbaud = (int)(BRGCLOCK/(((long) baud) << 4)); outp(THR, outbaud); // WAS out port w outp(THR+1, (outbaud >> 8)); // WAS out port w outp(LCR, comdata); /* set the bits, baud, parity */ outp(MCR, 0x0b); inp(LSR); /* Reset any pending errors */ inp(RBR); /* Read any pending character */ inp(IIR); outp(0x20, 0x20); outp(IER,0x03); /* Enable data ready interrupt & transmit data*/ outp(0x21, inp(0x21) & ~((port == COM1) ? 0x10 : 0x08)); /* enable interrupt */ reset_buffer(); int_on(); } // -------------------------------------------------------------- // // Function : Setup_RS232() // // Purpose : This function sets up RS232 communications. // // Entry : none. // // Return : none. //---------------------------------------------------------------- void Setup_RS232(int port) { ioport = (port == COM1) ? C1 : C2; int_intercept(port, isr_isr, 0); initCOM(port); /* initialize RS232 */ outp(0x20, 0x20); int_on(); } /* * out_message() initiates data transfer to the application and checks * for time outs and errors */ int out_message(int timeout) { int current, return_val = 1; current = bottom_out; while(outbuff[current].retry-- > 0) { if(!return_val) break; init_trans(); ticker3 = timeout; while(return_val) { /* * Need to test for a system escape...get_event(0) */ if(!ticker3) break; if(f.b.transaction_done) /* restart the communica */ { outbuff[current].retry++; break; } if(!sending_z_command) { if(kbhit()) { if(getch() == 0x1b) // escape key pressed { send_z_command(); } } } } if(!data_to_send) break; /* all done */ else if(outbuff[current].retry < 1) { position_and_print(23, 0, "Communication error"); // error handler } ticker3 = timeout; } return(return_val); } /* -------------------------------------------------------------- * * Function : send_command() * * Purpose : This function sends a command one of the attached devices. * * Entry : command - command to send. * * Return : 1 - sucess, 0 - failure. * ---------------------------------------------------------------- */ int send_command(char address, char *command) { int tt = top_out, return_val = 1, ttt = 1; char buff[300]; if(make_string('\000', command, outbuff[top_out].mess)) { outbuff[tt].addressout = address; outbuff[tt].retry = 5; ttt = out_message(31); outbuff[tt].mess[50] = '\000'; position_and_print(23, 0, outbuff[tt].mess); } else { return_val = 0; position_and_print(23, 0, "Communications Error..."); } if(ttt == 0) { return_val = 0; if(!sending_z_command) send_z_command(); } return(return_val); } /* -------------------------------------------------------------- * * Function : receive_command() * * Purpose : This function requests a message from one of the attached * devices. * * Entry : command - buffer to hold command from device. * flag - TRUE - going to wavelength and requesting signal so update. * - FALSE - other command. * * Return : 1 - sucess, 0 - failure. * ---------------------------------------------------------------- */ int receive_command(char address, char *command, int flag) { int i, retrys = 2, return_val = 1, tt, done = 0, filt, err, tc = 0, ttype, rangelvl; char c, tbuff[80], *ptr, *ptr2, *ptr3, bbb[80], buff[300]; double sig; restart_transfer = 1; while(retrys-- && return_val) { tt = top_out; if(make_string('\000', "I", outbuff[top_out].mess)) /*request data from the user */ { while(data_to_send) { outbuff[tt].retry = 100; outbuff[tt].addressout = address | 0x80; return_val = out_message(31); /* send the string to the wavelength drive */ if(!return_val) { f.word = 0; send_z_command(); return_val = 0; break; } } } i = 0; while(return_val && i < 100) { /* * check for user abort */ if(MessageAvailable) /* have a message so check to see if it is a Y */ { if(--MessageAvailable < 0) MessageAvailable = 0; // Decrement the message available flag strcpy(command, &inbuff[bottom_in][0]); if(++bottom_in > 5) bottom_in = 0; err = sscanf(&command[1], "%c", &c); done = 1; break; } msleep(10); i++; } if(done) break; } if(return_val) { if(!done) { position_and_print(23, 0, "..No message available"); return_val = 0; } } else reset_buffer(); return(return_val); } // // This routine will setup for receiving binary data from the serial device // int receive_binary_data(char *retbuf, int address, int numbytes) { int i, retrys = 2, return_val = 1, tt, done = 0, filt, err, tc = 0, ttype, rangelvl; char c, tbuff[80], *ptr, *ptr2, *ptr3, bbb[80], buff[300]; double sig; // // setup the binary buffer // binary_buffer = retbuf; // // setup the number of bytes to read // BinaryByteCount = numbytes; // Keep trying until a message package is available restart_transfer = 1; while(retrys-- && return_val) { tt = top_out; if(make_string('\000', "I", outbuff[top_out].mess)) /*request data from the user */ { while(data_to_send) { outbuff[tt].retry = 100; outbuff[tt].addressout = address | 0x40; // requesting binary data. return_val = out_message(130); /* send the string to the wavelength drive */ if(!return_val) { f.word = 0; send_z_command(); return_val = 0; break; } } } i = 0; while(return_val && i < 100) { /* * check for user abort */ if(BinaryMessageAvailable) /* have a message so check to see if it is a Y */ { BinaryMessageAvailable = 0; // Decrement the message available flag done = 1; break; } msleep(10); i++; } if(done) break; } if(return_val) { if(!done) { position_and_print(23, 0, "..No message available"); return_val = 0; } } else reset_buffer(); // // clear the binary buffer // binary_buffer = NULL; // // clear the number of bytes to read // BinaryByteCount = 0; return(return_val); }