//I have been hanging on to this source for a long time after working on it for //around a year in 1988. I would like to ask that if you make some good //modifications to it, please share it with the internet community. // //Below there are notes talking about that this is a c++ dll //for Visual Basic... It is not!.. When I started the program in 1988 //that is what I was trying but it ended up being just a c++ //dos program. It was written with Microsoft Visual C++ version 1.5 //You will probably have to do some messing with it to get it to //compile in newer or other c++ compilers. The first part of //the file tells helpful info learned while writing the program. //You will discover that I cannot spell....but compilers don't care as //long as was consistent at my misspelling. My screen was set at 1280x1024 //while writing....and I wrote the lines very long... //So be sure you have line wrap shut //off with whatever you use to view this code with. //Steve Lindsay /* This is a dll. It will send a value to the lpt port. The files that go with this are this file, inoutdll.cpp and inoutdll.def Here are two declares that work for Visual Basic: Declare Function InPort Lib "inoutdll.dll" (ByVal PortNum%) As Integer Declare Sub OutPort Lib "inoutdll.dll" (ByVal PortNum%, ByVal ValueOut%) Here is how to use them in the Visual Basic program code. OutPort 888, 4 //send a 4 to the lpt1 port Value = InPort(888) //read the lpt1 port and put it in Value data status control lpt1 addresses in decimal 888 889 890 lpt2 addresses in decimal 632 633 634 *************************************************** What the 25 pins do on a lpt port 1 STROBE (CONTROL) 2 DATA BIT 0 3 DATA BIT 1 4 DATA BIT 2 5 DATA BIT 3 6 DATA BIT 4 7 DATA BIT 5 8 DATA BIT 6 9 DATA BIT 7 10 ACKNOWLEDGE (STATUS) 11 BUSY (STATUS) 12 PE (OUT OF PAPER) (STATUS) 13 PRINTER ON LINE (STATUS) 14 AUTO LINEFEED (CONTROL) 15 PRINTER ERROR (STATUS) 16 INITIALIZE PRINTER (CONTROL) 17 SELECT\DESELECT (CONTROL) 18-25 UNUSED OR GROUND __________________________________________________ How two pins go on and off for a quaduture encoder binary decimal cw ccw cw ccw 00 00 0 0 10 01 2 1 11 11 3 3 01 10 1 2 00 00 0 0 _____________________________________________________________________________________ BITWISE STUFF you can use the bitwise and (&) to a decimal number to learn if a certain bit is 0 or 1. binary counting places are as follows (like with base 10 it is 1s 10s 100s 1000s) 1=1 10=2 100=4 1000=8 10000=16 100000=32 1000000=64 10000000=128 to use the bitwise and (&) do this: Like if you have a decimal 236 (11101100) and you want to know what the fifth bit over is do this: check=236&16; if (check == 0) it is a 0 otherwise it is a one //check will not hold a one. It will only hold a zero and if not you assume //it is a one. to write back and just change a certain bit you can do this after you know the current decimal number Like with the above example if you want to change the fifth bit from a 0 to a 1 do this; change=236+16 now it will be a decimal 252 or in bits: 11111100 of course to change the same bit from a 1 to a 0 just subtract 16 from the decimal ***************************************************************************************** INTERRUPT STUFF Most computers lpt1 port is irq7 (bit 7) in the interrupt mask address (8259 chip) (decimal 33)(hex 21) Older computer with different types of video cards like cga or ega have there lpt1 irq somewhere else. Typical Assignments base addresses Addr MDPA no MDPA 0x3BC LPT1 n/a Monochrome Display and Printer Adapter (MDPA) 0x378 LPT2 LPT1 Primary Printer Adapter 0x278 LPT3 LPT2 Secondary Printer Adapter Name MDPA no MDPA LPT1 0x3BC 0x378 LPT2 0x378 0x278 LPT3 0x278 n/a Typicaly irqs are assigned like this lpt1 = irq7 lpt2 = irq5 lpt3 = ? Example to turn on the 8259 chip so it will use irq5. You have to turn off the mask bit 5 at base address of decimal 33 from a 1 to a zero. REMEMBER the first bit is bit 0 up to bit 7 that makes 8 bits in all. Be sure to first find out what all the bits are and just change bit 5 though or you will turn off or on some other irqs the will screw up the puter. It seems the only way I can keep the lpt port from I think going into a non bidirectoinal mode while changeing the lpt base+2 (the control base address) is when I send the _outp to that address turning on (1) the irq enable ack (pin 10) (fourth bit over) I have to send a decimal with a zero at the bidirectinal control bit (bit 5) even though it is suppose to be biodirectional when it is a 1. I doesn't read a 1 after you write a 0 to it but if you write a 1 to it it will act like it is in unidirectional mode and like the data pins will all be on and you cannot reset them to zerro. Also it they won't take input it will just read 255 because they are all stuck on. This may be that it is just my particular lpt port. This problem should be tested on several cards and make sure they are all doing this samething before in case the software should be slightly different to accomidate the way others work. */ #include #include #include #include #include #include #include #include #include #include //#include #define ESC 27 #define PAGEDOWN 81 #define PAGEUP 73 #define DOWNARROW 80 #define UPARROW 72 //#define interrupt_address 0x0f //interrupt decimal 15 (irq 7) the printer 1 ack pin int interrupt_address=15;//interrupt decimal 15 (hex 0x0f)(irq 7) the printer 1 ack pin // (0x0D is irq 5 (decimal 13)) address to the ack pin long double x_unit, y_unit, z_unit; long double checkbacklash_X (long double, long double); long double checkbacklash_Y (long double, long double); long double checkbacklash_Z (long double, long double); long double encoder1 = 0.000; long double encoder2 = 0.000; long double encoder3 = 0.000; long double encoder4 = 0.000; int zero_all_X=0,zero_all_Y=0,zero_all_Z=0; //for rezeroing when the backlash is on int zero_all_X_mode=0,zero_all_Y_mode=0,zero_all_Z_mode=0; int mywatch=0; //this will turn on various couts so of varibles so i can see what is going on (press "ctr z") from the encoder setup screen to turn it on. //int Portnum = 888 ; //888 is lpt1 and 632 is lpt2 int timedisplay; int check_key(); int dataport = 888, statusport = 889, controlport = 890; int just_returned_from_irq; int use_irq; //user selects rather to use IRQ or use no IRQ (1 is yes, 0 is no) //time_t checktime; //long int holdtime, currenttime; //for watching the time to rezero because this is a demo void draw_encode_screen(); void encoder_setup(char); void mode_setup(char); void rotary_setup(char); void quick_rezero(char); long double numbers_only(int, int, char message[]); //function to input just a few long double numbers int intnumbers_only(int row, int colum, char message[]); //function to input just a few int numbers void InPort (int, int); long double checkit(int, long double, long double, int); char *decimal_to_degrees(long double); long double degrees_to_decimal(char string_degrees[]); long double auto_degrees_decimal(char message[],int,int,int,int); //char=message to send, int,int is textpostion for message and int,int is place for user to type in numbers void open_scroll_help(); void overlay_box (); void bigoverlay_box (); void InPort (int); void (__interrupt __far __cdecl *oldhandler) (void); //pointer to the oldhandle on the interrupt void __cdecl __interrupt __far handler(int, int); //declare what is to come//don't need this if you put the function above the main() function //ofstream ERRORout;//used to watch errors. I can turn it on by pressing ctr Z in setup. will write a text file typedef struct { int PrevValue; int PrevPrevValue; int PrevPrevPrevValue; int possible_error; //on off switch for if the error should be displaed long int possible_error_cnt; //where the total amount of errors is stored int cnt_updown; //for the user to toggle +- in the way it counts (up or down) //used to swap the encoders neg to positive and positive to negative and to reverse the direction of the counting int changed; //for the calling function to let it know which coder changed so it only updates that one on the screen. It can update them all but if it does it has more to do and will be slower int decimal_places_shown; int conversion; int error_changed; //same as above "changed" only to let the calling funtion know if there was an error and let it decide if it should be displayed } CODER; CODER coder1, coder2, coder3; typedef struct { //int inout; long double currently_displayed; //what is currently on the screen no matter if it is currenly compensating long double dist; //how much to compensate for backlash int onoff; //is this encoder backlash turned on or off int rightleft; //direction to compensate for backlash //this is not user changeable. It is part of the backlash function itself //int user_reset; //tell if the user has just reset the left right(if so want to call whatever is on the screen as the new change point int tension; //tension can be 0 or 1 This has to do with what way to take up backlash. The user can set this to whatever int swapsign; //turned on by user in encode setup to swap the sign of the number +/- int far_enough; }BACKLASH; BACKLASH backlash_X, backlash_Y, backlash_Z; typedef struct { long double xoffset; long double yoffset; long double zoffset; }MODE; MODE mode1, mode2, mode3, mode4; int mode=0; //0 is master mode 1 is mode1, 2 is mode2, 3 is mode3, 4 is mode4 typedef struct { long int x_number_of_blips; long int y_number_of_blips; long int z_number_of_blips; int x_onoff; int y_onoff; int z_onoff; int x_display_min; //1 is display minutes and secs. and 0 is display decimal int y_display_min; int z_display_min; int x_show_revolutions; int y_show_revolutions; int z_show_revolutions; int x_cnt_rotations; int y_cnt_rotations; int z_cnt_rotations; }ROTARY; ROTARY rotary; void InPort(int timedisplay) //void __cdecl __interrupt __far handler(void) { //UDT udtRet; // int strobe; static int counter, valuechanged; static int FirstTime = 1; int t; int Value; static int loopTheDllAgain=0; //static long saveTick, save_incase_bug0, save_incase_bug1; //static int FirstAfter, SecondAfter, ThirdAfter, FourthAfter, FifthAfter, static int GotOne, ctr; static int LeaveAlone = 0; int binary [10]; //the binary number from last time the port was read int remainder, temp; int Value1, Value2, Value3; static int comparValue1, comparValue2, comparValue3; static int inport_prevValue; static int encoder1_prev, encoder2_prev, encoder3_prev; static int encoder1_prevprev, encoder2_prevprev, encoder3_prevprev; while (1 == 1)//loop forever { if (_bios_keybrd (_KEYBRD_READY)) return; //////////////////////////////////////////////////////////////// if ((rotary.x_onoff==1)&&(valuechanged==1)) { //_settextposition (3,3); cout<=rotary.x_number_of_blips) {encoder1=0; rotary.x_cnt_rotations++; } if (encoder1 <= -1) encoder1=rotary.x_number_of_blips-1; encoder1_prevprev=encoder1_prev; encoder1_prev=(int)encoder1; } if ((rotary.y_onoff==1)&&(valuechanged==1)) { if (encoder2==0) //x_cnt_rotations counts the times 360 is hit {if ((encoder2_prev==1)&&(encoder2_prevprev== 2)) rotary.y_cnt_rotations--; } if (encoder2>=rotary.y_number_of_blips) {encoder2=0; rotary.y_cnt_rotations++; } if (encoder2 <= -1) encoder2=rotary.y_number_of_blips-1; encoder2_prevprev=encoder2_prev; encoder2_prev=(int)encoder2; } if ((rotary.z_onoff==1)&&(valuechanged==1)) { if (encoder3==0) //x_cnt_rotations counts the times 360 is hit {if ((encoder3_prev==1)&&(encoder3_prevprev== 2)) rotary.z_cnt_rotations--; } if (encoder3>=rotary.z_number_of_blips) {encoder3=0; rotary.z_cnt_rotations++; } if (encoder3 <= -1) encoder3=rotary.z_number_of_blips-1; encoder3_prevprev=encoder3_prev; encoder3_prev=(int)encoder3; } //new stuff here //Value=_inp (dataport); //read the port // if (valuechanged==1) // { //if (ctr>timedisplay){valuechanged=0; ctr=0; return; } //ctr=0; //valuechanged=0; // } Value=_inp (dataport); //read the port if (Value==inport_prevValue) //this if will count up how many times the port was read (if counter ==0 will only let it go right after it has hit a 3 and is still a 3(may be a little more time this way)) {valuechanged=0; ctr++; //and if the ctr is larger than the timedisplay (set by user setup) it will if (ctr>(10*timedisplay)) //this will update the screen if the user just sits there after moveing it fast {ctr=0; return;} } //end of new stuff // Value=_inp (dataport); //read the port //original read here //if (Value==inport_prevValue) ctr++; if (Value!=inport_prevValue) {ctr=0; valuechanged=1; //ctr=0; temp=Value; for (t=0; t<=5; t++) //should be 7 for figuring out all of the 0 and 1s but it is set to 5 because we only need the first 6 0 and 1s for 3 encoders { remainder = temp % 2; //find if there is anything left after trying to fit twos into the number temp = temp / 2; //divide by 2 and save it to use here the next time around binary [t] = remainder; //put the 1 or 0 into the binary array } binary[8] = '\0'; //terminate string with null character: if (coder1.cnt_updown==1) {if ((binary[0]==0)&&(binary[1]==0)) Value1=0; if ((binary[0]==1)&&(binary[1]==0)) Value1=2; //to make it change the direction it counts swap the 1 and 2 around if ((binary[0]==0)&&(binary[1]==1)) Value1=1; //also you will need flip backlash.rightleft (1 and 2) around in the checkbacklash rezero 'if' right in the first part of checkbacklash if ((binary[0]==1)&&(binary[1]==1)) Value1=3;} else {if ((binary[0]==0)&&(binary[1]==0)) Value1=0; if ((binary[0]==1)&&(binary[1]==0)) Value1=1; //to make it change the direction it counts swap the 1 and 2 around if ((binary[0]==0)&&(binary[1]==1)) Value1=2; //also you will need flip backlash.rightleft (1 and 2) around in the checkbacklash rezero 'if' right in the first part of checkbacklash if ((binary[0]==1)&&(binary[1]==1)) Value1=3;} if (coder2.cnt_updown==1) {if ((binary[2]==0)&&(binary[3]==0)) Value2=0; if ((binary[2]==1)&&(binary[3]==0)) Value2=2; if ((binary[2]==0)&&(binary[3]==1)) Value2=1; if ((binary[2]==1)&&(binary[3]==1)) Value2=3;} //these figure out if we should work with a 0 1 2 or 3 for the encoders. even 2 or 3 encoders can change and it should keep up else {if ((binary[2]==0)&&(binary[3]==0)) Value2=0; if ((binary[2]==1)&&(binary[3]==0)) Value2=1; if ((binary[2]==0)&&(binary[3]==1)) Value2=2; if ((binary[2]==1)&&(binary[3]==1)) Value2=3;} if (coder3.cnt_updown==1) {if ((binary[4]==0)&&(binary[5]==0)) Value3=0; if ((binary[4]==1)&&(binary[5]==0)) Value3=2; if ((binary[4]==0)&&(binary[5]==1)) Value3=1; if ((binary[4]==1)&&(binary[5]==1)) Value3=3;} else {if ((binary[4]==0)&&(binary[5]==0)) Value3=0; if ((binary[4]==1)&&(binary[5]==0)) Value3=1; if ((binary[4]==0)&&(binary[5]==1)) Value3=2; if ((binary[4]==1)&&(binary[5]==1)) Value3=3;} // if (mywatch==1) //I can turn this on from the encoder setup screen by pressing ctr z // {_settextposition (1,1); // cout <=rotary.x_number_of_blips) {encoder1=0; rotary.x_cnt_rotations++; } if (encoder1 <= -1) encoder1=rotary.x_number_of_blips-1; encoder1_prevprev=encoder1_prev; encoder1_prev=(int)encoder1; } if (rotary.y_onoff==1) { if (encoder2==0) //x_cnt_rotations counts the times 360 is hit {if ((encoder2_prev==1)&&(encoder2_prevprev== 2)) rotary.y_cnt_rotations--; } if (encoder2>=rotary.y_number_of_blips) {encoder2=0; rotary.y_cnt_rotations++; } if (encoder2 <= -1) encoder2=rotary.y_number_of_blips-1; encoder2_prevprev=encoder2_prev; encoder2_prev=(int)encoder2; } if (rotary.z_onoff==1) { if (encoder3==0) //x_cnt_rotations counts the times 360 is hit {if ((encoder3_prev==1)&&(encoder3_prevprev== 2)) rotary.z_cnt_rotations--; } if (encoder3>=rotary.z_number_of_blips) {encoder3=0; rotary.z_cnt_rotations++; } if (encoder3 <= -1) encoder3=rotary.z_number_of_blips-1; encoder3_prevprev=encoder3_prev; encoder3_prev=(int)encoder3; } Value=_inp (dataport); //read the port if (Value==inport_prevValue) ctr++; if (Value!=inport_prevValue) {ctr=0; //valuechanged=1; //ctr=0; temp=Value; for (t=0; t<=5; t++) //should be 7 for figuring out all of the 0s and 1s but it is set to 5 because we only need the first 6 0 and 1s for 3 encoders { remainder = temp % 2; //find if there is anything left after trying to fit twos into the number temp = temp / 2; //divide by 2 and save it to use here the next time around binary [t] = remainder; //put the 1 or 0 into the binary array } binary[8] = '\0'; //terminate string with null character: if (coder1.cnt_updown==1) {if ((binary[0]==0)&&(binary[1]==0)) Value1=0; if ((binary[0]==1)&&(binary[1]==0)) Value1=2; //to make it change the direction it counts swap the 1 and 2 around if ((binary[0]==0)&&(binary[1]==1)) Value1=1; //also you will need flip backlash.rightleft (1 and 2) around in the checkbacklash rezero 'if' right in the first part of checkbacklash if ((binary[0]==1)&&(binary[1]==1)) Value1=3;} else {if ((binary[0]==0)&&(binary[1]==0)) Value1=0; if ((binary[0]==1)&&(binary[1]==0)) Value1=1; //to make it change the direction it counts swap the 1 and 2 around if ((binary[0]==0)&&(binary[1]==1)) Value1=2; //also you will need flip backlash.rightleft (1 and 2) around in the checkbacklash rezero 'if' right in the first part of checkbacklash if ((binary[0]==1)&&(binary[1]==1)) Value1=3;} if (coder2.cnt_updown==1) {if ((binary[2]==0)&&(binary[3]==0)) Value2=0; if ((binary[2]==1)&&(binary[3]==0)) Value2=2; if ((binary[2]==0)&&(binary[3]==1)) Value2=1; if ((binary[2]==1)&&(binary[3]==1)) Value2=3;} //these figure out if we should work with a 0 1 2 or 3 for the encoders. even 2 or 3 encoders can change and it should keep up else {if ((binary[2]==0)&&(binary[3]==0)) Value2=0; if ((binary[2]==1)&&(binary[3]==0)) Value2=1; if ((binary[2]==0)&&(binary[3]==1)) Value2=2; if ((binary[2]==1)&&(binary[3]==1)) Value2=3;} if (coder3.cnt_updown==1) {if ((binary[4]==0)&&(binary[5]==0)) Value3=0; if ((binary[4]==1)&&(binary[5]==0)) Value3=2; if ((binary[4]==0)&&(binary[5]==1)) Value3=1; if ((binary[4]==1)&&(binary[5]==1)) Value3=3;} else {if ((binary[4]==0)&&(binary[5]==0)) Value3=0; if ((binary[4]==1)&&(binary[5]==0)) Value3=1; if ((binary[4]==0)&&(binary[5]==1)) Value3=2; if ((binary[4]==1)&&(binary[5]==1)) Value3=3;} // if (mywatch==1) //I can turn this on from the encoder setup screen by pressing ctr z // {_settextposition (1,1); // cout <>dataport>>timedisplay>>x_unit>>y_unit>>z_unit >>backlash_X.dist>>backlash_Y.dist>>backlash_Z.dist >>backlash_X.onoff>>backlash_Y.onoff>>backlash_Z.onoff >>backlash_X.tension>>backlash_Y.tension>>backlash_Z.tension >>coder1.possible_error>>coder2.possible_error>>coder3.possible_error; FILEin>>coder1.decimal_places_shown>>coder2.decimal_places_shown>>coder3.decimal_places_shown >>coder1.cnt_updown>>coder2.cnt_updown>>coder3.cnt_updown >>coder1.conversion>>coder2.conversion>>coder3.conversion >>dataport>>statusport>>controlport >>interrupt_address>>imask_bit; FILEin>>rotary.x_onoff>>rotary.y_onoff>>rotary.z_onoff >>rotary.x_display_min>>rotary.y_display_min>>rotary.z_display_min >>rotary.x_number_of_blips>>rotary.y_number_of_blips>>rotary.z_number_of_blips >>rotary.x_show_revolutions>>rotary.y_show_revolutions>>rotary.z_show_revolutions >>use_irq>>timedisplay; FILEin.close(); /* ERRORout.open("error.txt", ios::out ); //opens the error.txt file so it is read for input ERRORout<<"This ERROR.TXT file is generated everytime ENCODE READ is ran"<<"\n" <<"and ends. A quadature encoder puts out input similar to this:"<<"\n\n" <<"013201320132 counting one direction"<<"\n" <<"023102310231 counting the other"<<"\n\n" <<"From looking at the current number and the past numbers it is"<<"\n" <<"determined which way it should count."<<"\n\n" <<"Each line below shows the number that the error occurred on and"<<"\n" <<"the last three values that occurred before it"<<"\n\n"; */ oldtextcolor= _gettextcolor(); //save the users computer current text color _outp (dataport, 0); //just send a 0 to the data ports to make sure none of them are turned on internally again: _settextcursor (0x2000); //no cursor //0x0707 is the regular cursor _setvideomode(_TEXTC80); _setbkcolor (9); //blue _clearscreen(_GCLEARSCREEN); //_setvideomode (_DEFAULTMODE); _settextposition (24,60); cout<<"Esc to Quit"<71)) {_settextposition (24,m); _outtext(" "); _settextposition (24,m); cout< holdtime+900) //rezero every 15 minutes 900 seconds is 15 minutes { _settextposition (17,8); cout<<" Unregistered version"<>string; //decimal=degrees_to_decimal(string); //decimal holds decimal degrees if (decimal==-99999) break; //user hit escape //cout<>string; // decimal=degrees_to_decimal(string); //decimal holds decimal degrees if (decimal==-99999) break; //user hit escape encoder2=(decimal*rotary.y_number_of_blips)/360; } if (rotary.y_display_min==0) //in display decimal { _settextposition (21,1); _outtext(" "); decimal=numbers_only (21, 25,"Enter decimal degrees "); if (decimal==-99999) break; //user hit escape encoder2=(decimal*rotary.y_number_of_blips)/360; } break; } case ('z'): { if (rotary.z_display_min==1) //in display min seconds {//_outtext(" Enter degrees, minutes, seconds\n"); //_outtext(" Seperate by comas and no spaces\n"); _settextposition (22,15); _outtext(" "); decimal=auto_degrees_decimal(" Enter degrees, minutes, seconds\n Seperate by comas and no spaces\n",19,1,22,15); //_settextposition (22,15); //cin>>string; //decimal=degrees_to_decimal(string); //decimal holds decimal degrees if (decimal==-99999) break; //user hit escape encoder3=(decimal*rotary.z_number_of_blips)/360; } if (rotary.z_display_min==0) //in display decimal { _settextposition (21,1); _outtext(" "); decimal=numbers_only (21, 25,"Enter decimal degrees "); if (decimal==-99999) break; //user hit escape encoder3=(decimal*rotary.z_number_of_blips)/360; } break; } } _settextcursor (0x2000); //cursor off goto upper; } if(cc==110) //n key number of blips in 360 {_settextcursor (0x0707); //cursor on //_settextposition (19,1); _settextposition (21,1); _outtext(" "); switch(xyzletter) {case ('x'): {longdouble=numbers_only (21, 29,"# of counts in 360 degrees "); if (longdouble==-99999) break; rotary.x_number_of_blips=(int)longdouble;break;} case ('y'): {longdouble=numbers_only (21, 34,"# of counts in 360 degrees "); if (longdouble==-99999) break; rotary.y_number_of_blips=(int)longdouble;break;} case ('z'): {longdouble=numbers_only (21, 34,"# of counts in 360 degrees "); if (longdouble==-99999) break; rotary.z_number_of_blips=(int)longdouble;break;} } _settextcursor (0x2000); //cursor off goto upper; } }while (cc!=27);// only go back after the esc key } //blips encoder //cross multipy to figure decimal degrees //----- ------ // 360 decimal degrees void mode_setup(char xyzletter) { char letter[2]; char *capital; char string[25]; int cc, a=0; long double save_offset; //long double save_1, save_2, save_3; //long int save_error; long double dif, longdouble; int x_save_tension=backlash_X.tension; int y_save_tension=backlash_Y.tension; int z_save_tension=backlash_Z.tension; // _settextwindow(5,5,21,36); //largest is 1,1,25,40//this would be full screen // _setbkcolor (1); //red=4 yellow=14 brightwhite=15 normal white =7 dede: //use this place to come back to and start over this function within the function _settextposition(25,1); _outtext(" "); _clearscreen(_GWINDOW); //_GVIEWPORT _GCLEARSCREEN _settextwindow(5,5,20,35); //largest is 1,1,25,40//this would be full screen _setbkcolor (7); _clearscreen(_GWINDOW); //_GVIEWPORT _GCLEARSCREEN letter[0]= xyzletter; letter[1]='\0'; capital = _strupr(letter); _settextcolor(15); _setbkcolor (1); _outtext(" "); _settextposition (1,8); _outtext ("Encoder "); _outtext (capital); _outtext(" Mode "); if (mode==1) _outtext("A"); if (mode==2) _outtext("B"); if (mode==3) _outtext("C"); if (mode==4) _outtext("D"); _outtext("\n\n\n\n"); _setbkcolor (7); _settextcolor(0); //black _outtext(" Reset to Zero\n\n"); _outtext(" Current Value\n\n"); _outtext(" Count up/down"); _settextcolor(4); //red _settextposition (5,4); _outtext("R"); _settextposition (7,12); _outtext("V"); _settextposition (9,4); _outtext("C"); _settextposition (25,1); _settextcolor(0); //black _outtext(" Esc"); _settextcolor(14); //yellow _settextposition (5,18); _outtext(" "); //reset spot _settextposition (7,18); _outtext(" "); //current value spot _settextposition (9,18); _outtext(" "); //+/- _settextposition (9,19); if (xyzletter=='x') {if (coder1.cnt_updown==0) cout<<"-"<backlash_X.currently_displayed) dif=encoder1-backlash_X.currently_displayed; else dif=backlash_X.currently_displayed-encoder1; if (dif>(backlash_X.dist*.25))// *.25 is the same as /4 (1/4th) //(x_unit*5)) //take about 5 units and see if we are over that many blips and if so the user must of came up from the other way with the tension before he rezeros. //so then whatever the current lash direction is it needs to be set the other way. If not leave it along. It is already set correct { if (backlash_X.tension==0) //only let it do this once per call to this function. This is to keep {backlash_X.tension=1; } else {backlash_X.tension=0; } } switch (mode) //if in any other mode than master mode {case (1): { mode1.xoffset=encoder1;break;} case (2): { mode2.xoffset=encoder1;break;} case (3): { mode3.xoffset=encoder1;break;} case (4): { mode4.xoffset=encoder1;break;} } backlash_X.currently_displayed=encoder1; zero_all_X_mode=1; //this turns on the zero stuff in the backlash function coder1.possible_error_cnt=0; //set the error counter back to zero too _settextposition (5,18);cout<<"Now Zero "<backlash_Y.currently_displayed) dif=encoder2-backlash_Y.currently_displayed; else dif=backlash_Y.currently_displayed-encoder2; if (dif>(backlash_Y.dist*.25))// *.25 is the same as /4 (1/4th) //(x_unit*5)) //take about 5 units and see if we are over that many blips and if so the user must of came up from the other way with the tension before he rezeros. //so then whatever the current lash direction is it needs to be set the other way. If not leave it along. It is already set correct { if (backlash_Y.tension==0) //only let it do this once per call to this function. This is to keep {backlash_Y.tension=1; } else {backlash_Y.tension=0; } } switch (mode) //if in any other mode than master mode {case (1): { mode1.yoffset=encoder2;break;} case (2): { mode2.yoffset=encoder2;break;} case (3): { mode3.yoffset=encoder2;break;} case (4): { mode4.yoffset=encoder2;break;} } backlash_Y.currently_displayed=encoder2; zero_all_Y_mode=1; //this turns on the zero stuff in the backlash function coder2.possible_error_cnt=0; //set the error counter back to zero too _settextposition (5,18);cout<<"Now Zero "<backlash_Z.currently_displayed) dif=encoder3-backlash_Z.currently_displayed; else dif=backlash_Z.currently_displayed-encoder3; if (dif>(backlash_Z.dist*.25))// *.25 is the same as /4 (1/4th) //(x_unit*5)) //take about 5 units and see if we are over that many blips and if so the user must of came up from the other way with the tension before he rezeros. //so then whatever the current lash direction is it needs to be set the other way. If not leave it along. It is already set correct { if (backlash_Z.tension==0) //only let it do this once per call to this function. This is to keep {backlash_Z.tension=1; } else {backlash_Z.tension=0; } } switch (mode) //if in any other mode than master mode {case (1): { mode1.zoffset=encoder3;break;} case (2): { mode2.zoffset=encoder3;break;} case (3): { mode3.zoffset=encoder3;break;} case (4): { mode4.zoffset=encoder3;break;} } backlash_Z.currently_displayed=encoder3; zero_all_Z_mode=1; //this turns on the zero stuff in the backlash function coder3.possible_error_cnt=0; //set the error counter back to zero too _settextposition (5,18);cout<<"Now Zero "<