Codigo fuente en C del controlador de 4 Motores PapUnipolares...

#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
#include <conio.h>
#include <math.h>
#include <string.h>
#include <conio.h>

/***** Declaracion de variables globales *****/
int           gaiPortInst[3]     = {0,0,0};
int           giPortID           = 0x378;
unsigned char gaucCharCodif[18];
unsigned long gaulPasos[4];                         /*Contador de los pasos del Motor*/
char          gcFileOpen         = '0';
int           gaiTimeRet[2]      = {1,1};           /*Tiempo de retardo en milisegundos*/
char          gacModo[80];
int           giPortMode = 1;                       /* SPP -> 0 , ECP-EPP -> 1*/
int           giLogMode  = 0;                       /* LOG -> 1*/
FILE*         gflFileIH;
FILE*         gflFileLOG;
/***** Declaracion de estructuras *****/

/***** Declaracion de Defines *****/
#define DEFMOTOFF -1000

#define DEFPPTITFG 14
#define DEFPPTITBG 1
#define DEFPPDATFG 15
#define DEFPPDATBG 3
#define DEFPPINFFG 15
#define DEFPPINFBG 4
#define DEFPPMSGFG 14
#define DEFPPMSGBG 5
#define DEFPPCMDFG 14
#define DEFPPCMDBG 0

#define DEFPPDATCX 40
#define DEFPPDATCY 5
#define DEFPPCNTCX 1
#define DEFPPCNTCY 12
#define DEFPPMSGCX 3
#define DEFPPMSGCY 21
#define DEFPPCMDCX 3
#define DEFPPCMDCY 24

/***** Declaracion de funciones *****/
void vFunPPrintInit ( void );
void vFunPPrintMsg  ( char *acMsg );
void vFunPPrintData ( void );

char cFunGetCmdChar ( int iCnd );
int  iFunGetCmdInt  ( void );
void vFunGetCmdStr  ( char *acStr );

int           iFunFindLPTPort (void);
void          vFunInitGVar    (int iModo);
unsigned char ucFunMgMPAP     (int iMotor, int iDir);
void          vFunError       (char *acMsg);
int           iFunConfig      (void);
void          vFunSetOrigen   (void);
int           fprCsplit       (char *strn, char sep, int pos, char *ret);
void          vLeeFich        (FILE *fin);
int           iMoveCarr       (int iD1, int iD2, int iD3, int iD4);
int           iMCKBhit        (void);
int           iSendLptData    (int iPortID, int iTimeRetOn, int iTimeRetOff,
           int iCod1, int iCod2, int iCod3, int iCod4);

int iffgetLine(FILE *fich, char *cadena);
void vPonDesp(void);

/**************************************************************************/
/***** FUNCION MAIN *****/
/**************************************************************************/
int main (int argc, char **argv) {
 int iT;
 int iTt;

 gcFileOpen = '0';

 if (argc > 1) {
  for(iTt = 1 ; iTt <= argc ; iTt++) {
 if (strcmp(argv[iTt], "SPP") == 0) { giPortMode = 0;}
 if (strcmp(argv[iTt], "LOG") == 0) { giLogMode  = 1;}

  }
 }

 if (giLogMode == 1) {
  if ((gflFileLOG = fopen("Cnc4MPap.log", "w")) == NULL) {
 vFunError("No se ha podido crear el fichero LOG...");
  }
  fprintf (gflFileLOG, "Generando el Fichero de comandos...");
 }
 

 vFunInitGVar(2);                                        /*Inicializo las variables globales*/

 if (iFunFindLPTPort() == 0) {
  vFunError("No se ha encontrado LPT instalado en el PC");
 }

 vFunPPrintInit();                                       /* Imprimo Pantalla Inicio */

 iT = 0;
 while (gaiPortInst[iT] == 0) iT++;                      /*Busco el primer puerto LPT disponible*/
 giPortID = gaiPortInst[iT];

 vFunPPrintData();                                       /* Imprimo los Datos en Pantalla */

 for (iT = 0; iT < 3; iT++) {
  if (gaiPortInst[iT] != 0) {
 iSendLptData (gaiPortInst[iT], gaiTimeRet[0], gaiTimeRet[1], DEFMOTOFF, DEFMOTOFF, DEFMOTOFF, DEFMOTOFF);
  }
 }

 while ((iT = iFunConfig()) != -1) {
  if (iT == 1) {
   if (gcFileOpen == '1') {
  iSendLptData (giPortID, gaiTimeRet[0], gaiTimeRet[1], DEFMOTOFF, DEFMOTOFF, DEFMOTOFF, DEFMOTOFF);
  vLeeFich(gflFileIH);                                    /*Lee el fichero y mueve los motores*/
  iSendLptData (giPortID, gaiTimeRet[0], gaiTimeRet[1], DEFMOTOFF, DEFMOTOFF, DEFMOTOFF, DEFMOTOFF);
  fclose (gflFileIH);
  gcFileOpen = '0';

  textcolor(DEFPPDATFG);
  textbackground(DEFPPDATBG);
  gotoxy(DEFPPDATCX, DEFPPDATCY + 5);
  cprintf("                                         ");
  textcolor(DEFPPCMDFG);
  textbackground(DEFPPCMDBG);
  gotoxy(DEFPPCMDCX, DEFPPCMDCY);
   } else {
  vFunPPrintMsg("ERROR: No se ha encontrado Canal Abierto de fichero de Comandos");
   }
  }
 }

 if (giLogMode == 1) {
  fclose (gflFileLOG);
 }

 vPonDesp();

 return (0);
}
 

/**************************************************************************/
/***** ALGORITMO DE FUNCIONES ESPECIFICAS DE REPRESENTACION EN PANTALLA ***/
/**************************************************************************/
/* Inicializa el formato de la pantalla*/
void vFunPPrintInit( void ) {
 textmode (C80);
 gotoxy(1, 1);

 /* Imprimiendo Titulo */
 textcolor(DEFPPTITFG);
 textbackground(DEFPPTITBG);
 cprintf("                                                                                ");
 cprintf(" CNC4MPAP - Controlador 4 Motores Paso a Paso por LPT con 74LS374 (FPR-20/10/01)");
 cprintf("                                                                                ");

 /*Imprimiendo Datos*/
 textcolor(DEFPPDATFG);
 textbackground(DEFPPDATBG);
 cprintf("                                                                                ");
 cprintf("  1  PUERTO LPT1 (0x%3x)                ",gaiPortInst[0]);
 cprintf("                                        ");
 cprintf("  2  PUERTO LPT2 (0x%3x)                ",gaiPortInst[1]);
 cprintf("                                        ");
 cprintf("  3  PUERTO LPT3 (0x%3x)                ",gaiPortInst[2]);
 cprintf("                                        ");

 cprintf("     MODO ACTIVACION (4-S, 5-D, 6-S+D)                                          ");
 cprintf("  v  VELOCIDAD CONTROLADOR (TON, TOFF)                                          ");
 cprintf("  f  FICHERO DE COMANDOS                                                        ");

 cprintf("                                                                                ");
 cprintf("                                                                                ");

 /*Imprimiendo Informacion*/
 textcolor(DEFPPINFFG);
 textbackground(DEFPPINFBG);
 cprintf("                                                                                ");
 cprintf(" Informacion:                                                                   ");
 cprintf("  o  Establecer Origen de los Motores (Desplazamiento Manual)                   ");
 cprintf("  i  Inicio de la ejecucion del Fichero de comandos                             ");
 cprintf("                                                                                ");
 cprintf("  s  SALIR DEL PROGRAMA                                                         ");
 cprintf("                                                                                ");

 /*Imprimiendo Mensajes*/
 textcolor(DEFPPMSGFG);
 textbackground(DEFPPMSGBG);
 cprintf(" Mensaje:                                                                       ");
 cprintf("                                                                                ");
 cprintf("                                                                                ");

 /*Imprimiendo Comandos*/
 textcolor(DEFPPCMDFG);
 textbackground(DEFPPCMDBG);
 cprintf(" Comandos:                                                                      ");
 cprintf("                                                                                ");
// cprintf("                                                                                ");

 gotoxy(DEFPPCMDCX, DEFPPCMDCY);
}

/**************************************************************************/
/*Funcion que Gestiona los Mensajes por pantalla*/
void vFunPPrintMsg (char *acMsg) {
 textcolor(DEFPPMSGFG);
 textbackground(DEFPPMSGBG);
 gotoxy(1, DEFPPMSGCY);

 cprintf("                                                                                ");
 gotoxy(DEFPPMSGCX, DEFPPMSGCY);
 cprintf("%s", acMsg);

 textcolor(DEFPPCMDFG);
 textbackground(DEFPPCMDBG);
 gotoxy(DEFPPCMDCX, DEFPPCMDCY);

 if (giLogMode == 1) {
  fprintf (gflFileLOG, "\nMSG    : %s", acMsg);
 }
}

/**************************************************************************/
/*Funcion que Gestiona los Datos por pantalla*/
void vFunPPrintData (void) {
 int iT;

 textcolor(DEFPPDATFG);
 textbackground(DEFPPDATBG);
 for (iT = 0; iT < 3 ; iT ++) {
  if (gaiPortInst[iT] != giPortID) {
 gotoxy(DEFPPDATCX, DEFPPDATCY + iT);
 cprintf("           ");
  } else {
 gotoxy(DEFPPDATCX, DEFPPDATCY + iT);
 cprintf("   ACTIVADO");
  }
 }

 gotoxy(DEFPPDATCX, DEFPPDATCY + 3);
 cprintf("                                         ");
 gotoxy(DEFPPDATCX, DEFPPDATCY + 3);
 cprintf("   %s", gacModo);

 gotoxy(DEFPPDATCX, DEFPPDATCY + 4);
 cprintf("                                         ");
 gotoxy(DEFPPDATCX, DEFPPDATCY + 4);
 cprintf("   %d  -  %d", gaiTimeRet[0], gaiTimeRet[1]);

 gotoxy(1, DEFPPCNTCY);
 cprintf("                                                                                ");
 gotoxy(DEFPPCNTCX, DEFPPCNTCY);
 cprintf("  C1: %10lu", gaulPasos[0]);
 cprintf("  C2: %10lu", gaulPasos[1]);
 cprintf("  C3: %10lu", gaulPasos[2]);
 cprintf("  C4: %10lu", gaulPasos[3]);

 textcolor(DEFPPCMDFG);
 textbackground(DEFPPCMDBG);
 gotoxy(DEFPPCMDCX, DEFPPCMDCY);
}
 
 
 

/**************************************************************************/
/*Funcion que obtiene un entero desde la linea de comandos*/
int iFunGetCmdInt ( void ) {
 char acTmp[80];

 textcolor(DEFPPCMDFG);
 textbackground(DEFPPCMDBG);
 gotoxy(1, DEFPPCMDCY);
 cprintf("                                                                                ");
 gotoxy(DEFPPCMDCX, DEFPPCMDCY);

 scanf("%s", acTmp);
 return (atoi(acTmp));
}

/**************************************************************************/
/*Funcion que obtiene un caracter desde la linea de comandos*/
char cFunGetCmdChar ( int iCnd ) {
 char cCar;

 textcolor(DEFPPCMDFG);
 textbackground(DEFPPCMDBG);
 gotoxy(1, DEFPPCMDCY);
 cprintf("                                                                                ");
 gotoxy(DEFPPCMDCX, DEFPPCMDCY);

 switch (iCnd) {
  case 0 : {
 cCar = getch();
 break;
  }
  case 1 : {
 cCar = getche();
 break;
  }
  default: {
  }
 }
 return (cCar);
}

/**************************************************************************/
/*Funcion que obtiene un String desde la linea de comandos*/
void vFunGetCmdStr ( char *acStr ) {

 textcolor(DEFPPCMDFG);
 textbackground(DEFPPCMDBG);
 gotoxy(1, DEFPPCMDCY);
 cprintf("                                                                                ");
 gotoxy(DEFPPCMDCX, DEFPPCMDCY);

 scanf("%s", acStr);
}

/**************************************************************************/
/***** ALGORITMO DE FUNCIONES ESPECIFICAS DEL CONTROLADOR             *****/
/**************************************************************************/
/*Busca los puertos paralelos instalados en el PC*/
int iFunFindLPTPort (void) {
 int iT;
 int iTmp = 0;
 unsigned uTmp;

 for (iT=0; iT<3; iT++) {
  uTmp = *(unsigned far *) (MK_FP(0x40, 0x008 + (iT * 2)));
  if (uTmp != 0) {
 gaiPortInst[iT] = (int) uTmp;
 iTmp++;
  } else {
 gaiPortInst[iT] = 0;
  }
 }
 return (iTmp);
}
 

/*Inicializa las variables globales especiales*/
void vFunInitGVar (int iModo) {
 /*Inicializo El Vector de Codificacion de Pasos*/
  gaulPasos[0] = (unsigned long) 2e9;               /*Motor 0*/
  gaulPasos[1] = gaulPasos[0];                      /*Motor 1*/
  gaulPasos[2] = gaulPasos[0];                      /*Motor 2*/
  gaulPasos[3] = gaulPasos[0];                      /*Motor 3*/
 /*Inicializo El Vector de Codificacion de Pasos*/
  switch (iModo) {
 case 0: { /* SIMPLE activacion */
  strcpy(gacModo, "SIMPLE ACTIVACION");
 /*Motor 0*/
  gaucCharCodif[0] = 0x01;        /*Posicion  1: 0001=0x1 ,invertido: 1110=0xe*/
  gaucCharCodif[1] = 0x02;        /*Posicion  3: 0010=0x2 ,invertido: 1101=0xd*/
  gaucCharCodif[2] = 0x04;        /*Posicion  5: 0100=0x4 ,invertido: 1011=0xb*/
  gaucCharCodif[3] = 0x08;        /*Posicion  7: 1000=0x8 ,invertido: 0111=0x7*/
  gaucCharCodif[4] = 0x01;        /*Posicion  1: 0001=0x1 ,invertido: 1110=0xe*/
  gaucCharCodif[5] = 0x02;        /*Posicion  3: 0010=0x2 ,invertido: 1101=0xd*/
  gaucCharCodif[6] = 0x04;        /*Posicion  5: 0100=0x4 ,invertido: 1011=0xb*/
  gaucCharCodif[7] = 0x08;        /*Posicion  7: 1000=0x8 ,invertido: 0111=0x7*/
  gaucCharCodif[8] = 0x00;        /*Posicion  0: 0000=0x0 ,invertido: 1111=0xf*/
 /*Motor 1*/
  gaucCharCodif[9] = 0x10;        /*Posicion  1: 0001=0x1 ,invertido: 1110=0xe*/
  gaucCharCodif[10]= 0x20;        /*Posicion  3: 0010=0x2 ,invertido: 1101=0xd*/
  gaucCharCodif[11]= 0x40;        /*Posicion  5: 0100=0x4 ,invertido: 1011=0xb*/
  gaucCharCodif[12]= 0x80;        /*Posicion  7: 1000=0x8 ,invertido: 0111=0x7*/
  gaucCharCodif[13]= 0x10;        /*Posicion  1: 0001=0x1 ,invertido: 1110=0xe*/
  gaucCharCodif[14]= 0x20;        /*Posicion  3: 0010=0x2 ,invertido: 1101=0xd*/
  gaucCharCodif[15]= 0x40;        /*Posicion  5: 0100=0x4 ,invertido: 1011=0xb*/
  gaucCharCodif[16]= 0x80;        /*Posicion  7: 1000=0x8 ,invertido: 0111=0x7*/
  gaucCharCodif[17]= 0x00;        /*Posicion  0: 0000=0x0 ,invertido: 1111=0xf*/
  break;
 }
 case 1: { /* DOBLE activacion */
  strcpy(gacModo, "DOBLE ACTIVACION");
 /*Motor 0*/
  gaucCharCodif[0] = 0x03;        /*Posicion  2: 0011=0x3 ,invertido: 1100=0xc*/
  gaucCharCodif[1] = 0x06;        /*Posicion  4: 0110=0x6 ,invertido: 1001=0x9*/
  gaucCharCodif[2] = 0x0c;        /*Posicion  6: 1100=0xc ,invertido: 0011=0x3*/
  gaucCharCodif[3] = 0x09;        /*Posicion  8: 1001=0x9 ,invertido: 0110=0x6*/
  gaucCharCodif[4] = 0x03;        /*Posicion  2: 0011=0x3 ,invertido: 1100=0xc*/
  gaucCharCodif[5] = 0x06;        /*Posicion  4: 0110=0x6 ,invertido: 1001=0x9*/
  gaucCharCodif[6] = 0x0c;        /*Posicion  6: 1100=0xc ,invertido: 0011=0x3*/
  gaucCharCodif[7] = 0x09;        /*Posicion  8: 1001=0x9 ,invertido: 0110=0x6*/
  gaucCharCodif[8] = 0x00;        /*Posicion  0: 0000=0x0 ,invertido: 1111=0xf*/
 /*Motor 1*/
  gaucCharCodif[9] = 0x30;        /*Posicion  2: 0011=0x3 ,invertido: 1100=0xc*/
  gaucCharCodif[10]= 0x60;        /*Posicion  4: 0110=0x6 ,invertido: 1001=0x9*/
  gaucCharCodif[11]= 0xc0;        /*Posicion  6: 1100=0xc ,invertido: 0011=0x3*/
  gaucCharCodif[12]= 0x90;        /*Posicion  8: 1001=0x9 ,invertido: 0110=0x6*/
  gaucCharCodif[13]= 0x30;        /*Posicion  2: 0011=0x3 ,invertido: 1100=0xc*/
  gaucCharCodif[14]= 0x60;        /*Posicion  4: 0110=0x6 ,invertido: 1001=0x9*/
  gaucCharCodif[15]= 0xc0;        /*Posicion  6: 1100=0xc ,invertido: 0011=0x3*/
  gaucCharCodif[16]= 0x90;        /*Posicion  8: 1001=0x9 ,invertido: 0110=0x6*/
  gaucCharCodif[17]= 0x00;        /*Posicion  0: 0000=0x0 ,invertido: 1111=0xf*/
  break;
 }
 case 2: { /* DOBLE+SIMPLE activacion */
  strcpy(gacModo, "SIMPLE + DOBLE");
 /*Motor 0*/
  gaucCharCodif[0] = 0x01;        /*Posicion  1: 0001=0x1 ,invertido: 1110=0xe*/
  gaucCharCodif[1] = 0x03;        /*Posicion  2: 0011=0x3 ,invertido: 1100=0xc*/
  gaucCharCodif[2] = 0x02;        /*Posicion  3: 0010=0x2 ,invertido: 1101=0xd*/
  gaucCharCodif[3] = 0x06;        /*Posicion  4: 0110=0x6 ,invertido: 1001=0x9*/
  gaucCharCodif[4] = 0x04;        /*Posicion  5: 0100=0x4 ,invertido: 1011=0xb*/
  gaucCharCodif[5] = 0x0c;        /*Posicion  6: 1100=0xc ,invertido: 0011=0x3*/
  gaucCharCodif[6] = 0x08;        /*Posicion  7: 1000=0x8 ,invertido: 0111=0x7*/
  gaucCharCodif[7] = 0x09;        /*Posicion  8: 1001=0x9 ,invertido: 0110=0x6*/
  gaucCharCodif[8] = 0x00;        /*Posicion  0: 0000=0x0 ,invertido: 1111=0xf*/
 /*Motor 1*/
  gaucCharCodif[9] = 0x10;        /*Posicion  1: 0001=0x1 ,invertido: 1110=0xe*/
  gaucCharCodif[10]= 0x30;        /*Posicion  2: 0011=0x3 ,invertido: 1100=0xc*/
  gaucCharCodif[11]= 0x20;        /*Posicion  3: 0010=0x2 ,invertido: 1101=0xd*/
  gaucCharCodif[12]= 0x60;        /*Posicion  4: 0110=0x6 ,invertido: 1001=0x9*/
  gaucCharCodif[13]= 0x40;        /*Posicion  5: 0100=0x4 ,invertido: 1011=0xb*/
  gaucCharCodif[14]= 0xc0;        /*Posicion  6: 1100=0xc ,invertido: 0011=0x3*/
  gaucCharCodif[15]= 0x80;        /*Posicion  7: 1000=0x8 ,invertido: 0111=0x7*/
  gaucCharCodif[16]= 0x90;        /*Posicion  8: 1001=0x9 ,invertido: 0110=0x6*/
  gaucCharCodif[17]= 0x00;        /*Posicion  0: 0000=0x0 ,invertido: 1111=0xf*/
  break;
 }
 default: {
  break;
 }
  }
}

/**************************************************************************/
/*Devuelve el caracter con la codificacion del paso para el motor iMotor*/
 /*Variable con las codificaciones de los polos -> gaucCharCodif[2,9]*/
 /*Variable con los contadores de los pasos     -> gaulPasos[motores]*/
unsigned char ucFunMgMPAP (int iMotor, int iDir) {
 char acMsg[80];
 int iMotor1;

 if ((gaulPasos[iMotor]+iDir) < (unsigned long) 1000 ||
   (gaulPasos[iMotor]+iDir) > (unsigned long) 4e9) {

  sprintf(acMsg, "AVISO: Contador %d proximo a limite de rango, se RESETEA...", iMotor + 1);
  vFunPPrintMsg(acMsg);

  gaulPasos[iMotor] = (unsigned long) 2e9 + gaulPasos[iMotor] % 8;

  vFunPPrintData();
 }

 if (iMotor < 2) {
  iMotor1 = iMotor;
 } else {
  iMotor1 = iMotor - 2;
 }

 if (iDir == DEFMOTOFF) {
  return (gaucCharCodif[iMotor1 * 9 + 8]);
 }

 gaulPasos[iMotor] += iDir;
 return (gaucCharCodif[iMotor1 * 9 + (int) (gaulPasos[iMotor] % 8)]);

 /*FRAN - Imprimir el estado de las bobinas de los motores*/
}

/**************************************************************************/
/*Funcion de control de errores*/
void vFunError (char *acMsg) {
 char acMsg1[80];
 sprintf(acMsg1, "ERROR + FIN: %s", acMsg);
 vFunPPrintMsg(acMsg1);

 if (gcFileOpen == '1') {
  fclose (gflFileIH);
 }

 iSendLptData (giPortID, gaiTimeRet[0], gaiTimeRet[1], DEFMOTOFF, DEFMOTOFF, DEFMOTOFF, DEFMOTOFF);

 vPonDesp();

 exit(0);
}

/**************************************************************************/
/*Configura las propiedades del ploter*/
int iFunConfig(void) {
 int  iRet = 0;
 char acTmp[80];
 char acTmp1[80];

 acTmp[0]='\0';

 while (iRet == 0) {
  iSendLptData (giPortID, gaiTimeRet[0], gaiTimeRet[1], DEFMOTOFF, DEFMOTOFF, DEFMOTOFF, DEFMOTOFF);
  vFunPPrintMsg("Especificar Opcion de configuracion...");

  switch (cFunGetCmdChar(1)) {
 case '1': {
  if (gaiPortInst[0] != 0) {
   giPortID = gaiPortInst[0];
   vFunPPrintData();
  } else {
   vFunPPrintMsg("ERROR: El puerto LPT1 no esta instalado en el PC");
  }
  break;
 }
 case '2': {
  if (gaiPortInst[1] != 0) {
   giPortID = gaiPortInst[1];
   vFunPPrintData();
  } else {
   vFunPPrintMsg("ERROR: El puerto LPT2 no esta instalado en el PC");
  }
  break;
 }
 case '3': {
  if (gaiPortInst[2] != 0) {
   giPortID = gaiPortInst[2];
   vFunPPrintData();
  } else {
   vFunPPrintMsg("ERROR: El puerto LPT3 no esta instalado en el PC");
  }
  break;
 }
 case '4': {
  vFunInitGVar(0);                                    /*Inicializo las variables globales*/
  vFunPPrintData();
  break;
 }
 case '5': {
  vFunInitGVar(1);                                    /*Inicializo las variables globales*/
  vFunPPrintData();
  break;
 }
 case '6': {
  vFunInitGVar(2);                                    /*Inicializo las variables globales*/
  vFunPPrintData();
  break;
 }
 case 'f': {
  if (gcFileOpen == '1') {
   vFunPPrintMsg("ERROR: Opcion no valida, existe un fichero en curso...");
   delay(2000);
   break;
  }

  vFunPPrintMsg("Especificar Nombre del fichero sin extension '.fpt'...");
  vFunGetCmdStr(acTmp1);
  strcat(acTmp1, ".fpt");

  while ((gflFileIH = fopen(acTmp1, "r")) == NULL) {
   vFunPPrintMsg("ERROR: Nombre de Fichero Incorrecto, 'q' para abandonar...");
   vFunGetCmdStr(acTmp1);
   if (strcmp("q" ,acTmp1) == 0) break;
   strcat(acTmp1, ".fpt");
  }

  textcolor(DEFPPDATFG);
  textbackground(DEFPPDATBG);
  gotoxy(DEFPPDATCX, DEFPPDATCY + 5);
  cprintf("                                         ");
  gotoxy(DEFPPDATCX, DEFPPDATCY + 5);

  if (strcmp("q" ,acTmp1)) {
   rewind(gflFileIH);
   gcFileOpen = '1';
   cprintf("   %s", acTmp1);
  } else {
   cprintf("               ");
  }

  textcolor(DEFPPCMDFG);
  textbackground(DEFPPCMDBG);
  gotoxy(DEFPPCMDCX, DEFPPCMDCY);

  break;
 }
 case 'o': {
  vFunSetOrigen();
  break;
 }
 case 'v': {
  vFunPPrintMsg("Estableciendo Velocidad (Ton ->RETURN)");

  gaiTimeRet[0] = iFunGetCmdInt();
  vFunPPrintMsg("Estableciendo Velocidad (Toff ->RETURN)");

  gaiTimeRet[1] = iFunGetCmdInt();

  if (gaiTimeRet[0] < 1) gaiTimeRet[0] = 1;                    /*Tiempo de Retardo de los Motores*/
  if (gaiTimeRet[1] < 0) gaiTimeRet[1] = 0;                    /*Tiempo de Retardo de los Motores*/

  vFunPPrintData();
  break;
 }
 case 'i': {
  vFunPPrintMsg("Ejecucion Normal del Fichero de Comandos...");
  iRet = 1;
  break;
 }
 case 's': {
  vFunPPrintMsg("ESTA SEGURO QUE DESEA ABANDONAR EL PROGRAMA ? (s->si): ");

  if (cFunGetCmdChar(1) == 's') iRet = -1;
  break;
 }
 default: {
 }
  }
 }

 gotoxy(1, DEFPPCMDCY);
 cprintf("                                                                                 ");
 gotoxy(DEFPPCMDCX, DEFPPCMDCY);

 return (iRet);
}

/**************************************************************************/
/*Desplaza manualmente los motores*/
void vFunSetOrigen(void) {
 int iD1;
 int iD2;
 int iD3;
 int iD4;
 char acTmp[80];

// gaulPasos[0] = 2e9 + gaulPasos[0] % 8;                   /*Motor 0*/
// gaulPasos[1] = 2e9 + gaulPasos[1] % 8;                   /*Motor 1*/
// gaulPasos[2] = 2e9 + gaulPasos[2] % 8;                   /*Motor 2*/
// gaulPasos[3] = 2e9 + gaulPasos[3] % 8;                   /*Motor 3*/

// vFunPPrintMsg("Contadores Reseteados...");
 vFunPPrintData();

 vFunPPrintMsg("Introducir coordenadas Motor 1...");
 iD1 = iFunGetCmdInt();

 vFunPPrintMsg("Introducir coordenadas Motor 2...");
 iD2 = iFunGetCmdInt();

 vFunPPrintMsg("Introducir coordenadas Motor 3...");
 iD3 = iFunGetCmdInt();

 vFunPPrintMsg("Introducir coordenadas Motor 4...");
 iD4 = iFunGetCmdInt();

 sprintf(acTmp,"Pasos a Procesar: %d %d %d %d", iD1, iD2, iD3, iD4);
 vFunPPrintMsg(acTmp);
 delay(3000),
 iMoveCarr(iD1, iD2, iD3, iD4);

// gaulPasos[0] = 2e9 + gaulPasos[0] % 8;           /*Motor 0*/
// gaulPasos[1] = 2e9 + gaulPasos[1] % 8;           /*Motor 1*/
// gaulPasos[2] = 2e9 + gaulPasos[2] % 8;           /*Motor 2*/
// gaulPasos[3] = 2e9 + gaulPasos[3] % 8;           /*Motor 3*/

// vFunPPrintMsg("Contadores Reseteados...");
 vFunPPrintData();

 iSendLptData (giPortID, gaiTimeRet[0], gaiTimeRet[1], DEFMOTOFF, DEFMOTOFF, DEFMOTOFF, DEFMOTOFF);
}

/**************************************************************************/
/*Extrae las cadenas internas entre el separador sep en la posicion pos*/
int fprCsplit (char *strn, char sep, int pos, char *ret) {
 int it;
 int ij;
 int istrl;
 int ailisep[10] = {-1,-2,-2,-2,-2,-2,-2,-2,-2,-2};

 istrl = strlen(strn);
 ij = 1;
 for (it = 0 ; it < istrl ; it++) {
  if (strn[it] == sep) {
 ailisep[ij] = it;
 ij++;
  }
 }
 ailisep[ij] = istrl;

 if (ailisep[pos] == -2) {
  ret[0] = '\0';
  return (-1);
 }
 if (ailisep[pos+1] - ailisep[pos] < 2) {
  ret[0] = '\0';
  return (pos);
 }

 ij = 0;
 for (it = ailisep[pos]+1 ; it < ailisep[pos+1] ; it++) {
  ret[ij] = strn[it];
  ij++;
 }
 ret[ij] = '\0';
 return (pos);

}

/**************************************************************************/
/*Lee el fichero de datos y mueve los motores*/
void vLeeFich(FILE *fin) {
 int iCline = 0;
 int iCmd;
 char aTmp[80];
 char acTmp1[80];
 char acD1[80];
 char acD2[80];
 char acD3[80];
 char acD4[80];
 int iD1;
 int iD2;
 int iD3;
 int iD4;
 int iE1 = 1;
 int iE2 = 1;
 int iE3 = 1;
 int iE4 = 1;

 iffgetLine(fin, aTmp);
 if (fprCsplit (aTmp, ',', 0, acD1) == -1) {
  sprintf(acTmp1, "(%5d)ComandoFichero: No se ha encontrado comando en linea %s", iCline, aTmp);
  vFunPPrintMsg(acTmp1);
 }
 iCmd = atoi(acD1);

 while (iCmd != -1 && feof(fin) != 1) {
  if (kbhit() != 0) {
 cFunGetCmdChar(0);
 vFunPPrintMsg("DESEA ABORTAR EL FICHERO EN CURSO?  (s->si): ");
 if (cFunGetCmdChar(1) == 's') goto vLeeFich_exit;

 if (iFunConfig() == -1) {
  vFunError("Cancelacion desde el Teclado...");
 }
  }

  switch (iCmd) {
 case 0: {                                         /*Comentario*/
  break;
 }
 case 1: {                                         /*Establece la Velocidad*/
  if (fprCsplit (aTmp, ',', 1, acD1) == -1) { /*ERROR*/ };
  iD1 = atoi(acD1);
  if (fprCsplit (aTmp, ',', 2, acD2) == -1) { /*ERROR*/ };
  iD2 = atoi(acD2);

  if (iD1 < 1) {
   gaiTimeRet[0] = 1;
   sprintf(acTmp1, "(%5d)ComandoFichero: ERROR: Configurando Tiempo ON  %dms. negativa", iCline, iD1);
   vFunPPrintMsg(acTmp1);
   if (iFunConfig() == -1) {
  vFunError("Cancelacion desde el Teclado...");
   }
  } else {
   gaiTimeRet[0] = iD1;
   sprintf(acTmp1, "(%5d)ComandoFichero: Configurando Tiempo ON  a %dms.", iCline, iD1);
   vFunPPrintMsg(acTmp1);
  }

  if (iD2 < 0) {
   gaiTimeRet[1] = 0;
   sprintf(acTmp1, "(%5d)ComandoFichero: ERROR: Configurando Tiempo OFF %dms. negativa", iCline, iD2);
   vFunPPrintMsg(acTmp1);
   if (iFunConfig() == -1) {
  vFunError("Cancelacion desde el Teclado...");
   }
  } else {
   gaiTimeRet[1] = iD2;
   sprintf(acTmp1, "(%5d)ComandoFichero: Configurando Tiempo OFF a %dms.", iCline, iD2);
   vFunPPrintMsg(acTmp1);
  }
  break;
 }
 case 2: {                                         /*Establece el Puerto de Comunicacion*/
  if (fprCsplit (aTmp, ',', 1, acD1) == -1) { /*ERROR*/ };
  iD1 = atoi(acD1);

  if (iD1 > 0 && iD1 < 4 && gaiPortInst[iD1-1] != 0) {
   giPortID = gaiPortInst[iD1-1];
   sprintf(acTmp1, "(%5d)ComandoFichero: Configurando Puerto de comunicacion LPT%d", iCline, iD1);
   vFunPPrintMsg(acTmp1);
  } else {
   sprintf(acTmp1, "(%5d)ComandoFichero: ERROR: Puerto de comunicacion LPT%d no Valido", iCline, iD1);
   vFunPPrintMsg(acTmp1);
   if (iFunConfig() == -1) {
  vFunError("Cancelacion desde el Teclado...");
   }
  }
  break;
 }
 case 3: {                                         /*Muestra un mensaje en la pantalla*/
  if (fprCsplit (aTmp, ',', 1, acD1) == -1) { /*ERROR*/ };
  if (fprCsplit (aTmp, ',', 2, acD2) == -1) { /*ERROR*/ };

  sprintf(acTmp1, "(%5d)ComandoFichero: MENSAJE=> %s - %s", iCline, acD1, acD2);
  vFunPPrintMsg(acTmp1);
  break;
 }
 case 4: {                                         /*Hace una pausa*/
  if (fprCsplit (aTmp, ',', 1, acD1) == -1) { /*ERROR*/ };
  iD1 = atoi(acD1);

  if (iD1 > 0 ) {
   sprintf(acTmp1, "(%5d)ComandoFichero: PAUSA de %ds.", iCline, iD1);
   vFunPPrintMsg(acTmp1);
   delay(iD1 * 1000);
  } else {
   sprintf(acTmp1, "(%5d)ComandoFichero: PAUSA INDEFINIDA, pulse RETURN para continuar.", iCline);
   vFunPPrintMsg(acTmp1);
   cFunGetCmdChar(0);
  }
  break;
 }
 case 5: {                                         /*Establece el modo de activacion de los motores*/
  if (fprCsplit (aTmp, ',', 1, acD1) == -1) { /*ERROR*/ };
  iD1 = atoi(acD1);

  if (iD1 > -1 && iD1 < 3) {
   vFunInitGVar(iD1);
   sprintf(acTmp1, "(%5d)ComandoFichero: Modo Activacion seleccionado: %d", iCline, iD1);
   vFunPPrintMsg(acTmp1);
  } else {
   sprintf(acTmp1, "(%5d)ComandoFichero: ERROR en Modo Activacion seleccionado.", iCline);
   vFunPPrintMsg(acTmp1);
   if (iFunConfig() == -1) {
  vFunError("Cancelacion desde el Teclado...");
   }
  }
  break;
 }
 case 9: {                                         /*Establece el factor de escala*/
  if (fprCsplit (aTmp, ',', 1, acD1) == -1) { /*ERROR*/ };
  iD1 = atoi(acD1);
  if (fprCsplit (aTmp, ',', 2, acD2) == -1) { /*ERROR*/ };
  iD2 = atoi(acD2);
  if (fprCsplit (aTmp, ',', 3, acD3) == -1) { /*ERROR*/ };
  iD3 = atoi(acD3);
  if (fprCsplit (aTmp, ',', 4, acD4) == -1) { /*ERROR*/ };
  iD4 = atoi(acD4);

  iE1 = iD1;
  iE2 = iD2;
  iE3 = iD3;
  iE4 = iD4;

  sprintf(acTmp1, "(%5d)ComandoFichero: Configurando Factor de Escala: %d, %d, %d, %d", iCline, iE1, iE2, iE3, iE4);
  vFunPPrintMsg(acTmp1);

  break;
 }
 case 10: {                                         /*Mueve el Carro*/
  if (fprCsplit (aTmp, ',', 1, acD1) == -1) { /*ERROR*/ };
  iD1 = atoi(acD1);
  if (fprCsplit (aTmp, ',', 2, acD2) == -1) { /*ERROR*/ };
  iD2 = atoi(acD2);
  if (fprCsplit (aTmp, ',', 3, acD3) == -1) { /*ERROR*/ };
  iD3 = atoi(acD3);
  if (fprCsplit (aTmp, ',', 4, acD4) == -1) { /*ERROR*/ };
  iD4 = atoi(acD4);

  sprintf(acTmp1, "(%5d)ComandoFichero: Movimiento de motores: %d %d %d %d", iCline, iD1, iD2, iD3, iD4);
  vFunPPrintMsg(acTmp1);
  if ((iMoveCarr(iE1*iD1, iE2*iD2, iE3*iD3, iE4*iD4)) == -1) goto vLeeFich_exit;
  vFunPPrintData();
  break;
 }
 default: {
  sprintf(acTmp1, "(%5d)ComandoFichero: Orden %d Desconocida", iCline, iCmd);
  vFunPPrintMsg(acTmp1);
  delay(2000);
 }
  }

  iffgetLine(fin, aTmp);
  if (fprCsplit (aTmp, ',', 0, acD1) == -1) {
 sprintf(acTmp1, "(%5d)ComandoFichero: No se ha encontrado comando en linea %s", iCline, aTmp);
 vFunPPrintMsg(acTmp1);
  }
  iCmd = atoi(acD1);
  iCline++;
 }

vLeeFich_exit:
 sprintf(acTmp1, "(%5d)ComandoFichero: FIN DE EJECUCION DEL FICHERO", iCline);
 vFunPPrintMsg(acTmp1);
 delay(2000);
}

/**************************************************************************/
/*Operacion de presionar tecla en funcion iMoveCarr*/
int iMCKBhit (void) {
 char cT;

 cT = cFunGetCmdChar(0);

 switch (cT) {
  case '-': {
 gaiTimeRet[0] --;
 gaiTimeRet[1] --;
 if (gaiTimeRet[0] < 1) gaiTimeRet[0] = 1;        /*Tiempo de Retardo de los Motores*/
 if (gaiTimeRet[1] < 0) gaiTimeRet[1] = 0;        /*Tiempo de Retardo de los Motores*/
 break;
  }
  case '+': {
 gaiTimeRet[0] ++;
 break;
  }
  default: {
 vFunPPrintMsg("DESEA ABORTAR EL FICHERO EN CURSO? (s->si): ");
 if (cFunGetCmdChar(1) == 's') return(-1);
 if (iFunConfig() == -1) {
  vFunError("Cancelacion desde el Teclado...");
 }
  }
 }
 vFunPPrintData();
 return(0);
}

/**************************************************************************/
/*Mueve el carro la cantidad que se le especifique*/
int iMoveCarr(int iD1, int iD2, int iD3, int iD4) {
 int iT1;
 int iMaxPasos = 0;                                  /*Maximo Numero de Pasos*/
 int iSent1;                                         /*sentido de avance*/
 int iSent2;                                         /*sentido de avance*/
 int iSent3;                                         /*sentido de avance*/
 int iSent4;                                         /*sentido de avance*/
 double dProp1;                                      /*Relacion PasosMax, PasisI*/
 double dProp2;                                      /*Relacion PasosMax, PasisI*/
 double dProp3;                                      /*Relacion PasosMax, PasisI*/
 double dProp4;                                      /*Relacion PasosMax, PasisI*/
 double dCnt1;                                       /*Contador de pasos*/
 double dCnt2;                                       /*Contador de pasos*/
 double dCnt3;                                       /*Contador de pasos*/
 double dCnt4;                                       /*Contador de pasos*/
 int iCod1;                                          /*Codigo Motor*/
 int iCod2;                                          /*Codigo Motor*/
 int iCod3;                                          /*Codigo Motor*/
 int iCod4;                                          /*Codigo Motor*/
 int iCnt1=0;                                        /*Control Encendido Motores*/
 int iCnt2=0;                                        /*Control Encendido Motores*/
 int iCnt3=0;                                        /*Control Encendido Motores*/
 int iCnt4=0;                                        /*Control Encendido Motores*/

 if (iD1 == 0 && iD2 == 0 && iD3 == 0 && iD4 == 0) {
  return(0);
 }

 if (abs(iD1) > iMaxPasos) iMaxPasos = abs(iD1);
 if (abs(iD2) > iMaxPasos) iMaxPasos = abs(iD2);
 if (abs(iD3) > iMaxPasos) iMaxPasos = abs(iD3);
 if (abs(iD4) > iMaxPasos) iMaxPasos = abs(iD4);
 

 if (iD1 != 0) {
  iSent1 = iD1 / abs(iD1);
  dProp1 = (double) iMaxPasos / (double) abs(iD1);
 } else {
  iSent1 = 0;
  dProp1 = (double) iMaxPasos + 1.0;
 }
 if (iD2 != 0) {
  iSent2 = iD2 / abs(iD2);
  dProp2 = (double) iMaxPasos / (double) abs(iD2);
 } else {
  iSent2 = 0;
  dProp2 = (double) iMaxPasos + 1.0;
 }
 if (iD3 != 0) {
  iSent3 = iD3 / abs(iD3);
  dProp3 = (double) iMaxPasos / (double) abs(iD3);
 } else {
  iSent3 = 0;
  dProp3 = (double) iMaxPasos + 1.0;
 }
 if (iD4 != 0) {
  iSent4 = iD4 / abs(iD4);
  dProp4 = (double) iMaxPasos / (double) abs(iD4);
 } else {
  iSent4 = 0;
  dProp4 = (double) iMaxPasos + 1.0;
 }

 dCnt1 = dProp1;
 dCnt2 = dProp2;
 dCnt3 = dProp3;
 dCnt4 = dProp4;

 for (iT1 = 1 ; iT1 <= iMaxPasos ; iT1 ++) {
  if ((double) iT1 + 0.0001 >= dCnt1) {
 iCod1 = iSent1;
 dCnt1 += dProp1;
 iCnt1 = 0;
  } else {
 iCod1 = 0;
 iCnt1 ++;
  }
  if ((double) iT1 + 0.0001 >= dCnt2) {
 iCod2 = iSent2;
 dCnt2 += dProp2;
 iCnt2 = 0;
  } else {
 iCod2 = 0;
 iCnt2 ++;
  }
  if ((double) iT1 + 0.0001 >= dCnt3) {
 iCod3 = iSent3;
 dCnt3 += dProp3;
 iCnt3 = 0;
  } else {
 iCod3 = 0;
 iCnt3 ++;
  }
  if ((double) iT1 + 0.0001 >= dCnt4) {
 iCod4 = iSent4;
 dCnt4 += dProp4;
 iCnt4 = 0;
  } else {
 iCod4 = 0;
 iCnt4 ++;
  }

  if (iCnt1 > 10) {iCod1 = DEFMOTOFF;}
  if (iCnt2 > 10) {iCod2 = DEFMOTOFF;}
  if (iCnt3 > 10) {iCod3 = DEFMOTOFF;}
  if (iCnt4 > 10) {iCod4 = DEFMOTOFF;}

  iSendLptData (giPortID, gaiTimeRet[0], gaiTimeRet[1], iCod1, iCod2, iCod3, iCod4);

  if (kbhit() != 0) {
 if (iMCKBhit() == -1) return(-1);
  }
 }

 return (0);
}
 

/**************************************************************************/
/*Manda los datos al controlador de motores*/
/*RECORDAR: Los datos de control estan INVERTIDOS*/
int iSendLptData (int iPortID, int iTimeRetOn, int iTimeRetOff,
      int iCod1, int iCod2, int iCod3, int iCod4) {
 unsigned char ucCod1;                                        /*Codigo Binario Motores*/
 unsigned char ucCod2;                                        /*Codigo Binario Motores*/
 unsigned char ucCod3;                                        /*Codigo Binario Motores*/
 unsigned char ucCod4;                                        /*Codigo Binario Motores*/

 ucCod1 = ucFunMgMPAP (0, iCod1);
 ucCod2 = ucFunMgMPAP (1, iCod2);
 ucCod3 = ucFunMgMPAP (2, iCod3);
 ucCod4 = ucFunMgMPAP (3, iCod4);

 outportb(iPortID + 2, 0x03);
 if (giPortMode == 0) { while (inportb(iPortID + 2) != 0x03);}
 outportb(iPortID, ucCod1 + ucCod2);
 if (giPortMode == 0) { while (inportb(iPortID) != ucCod1 + ucCod2);}
 outportb(iPortID + 2, 0x02);
 if (giPortMode == 0) { while (inportb(iPortID + 2) != 0x02);}
 outportb(iPortID, ucCod3 + ucCod4);
 if (giPortMode == 0) { while (inportb(iPortID) != ucCod3 + ucCod4);}
 outportb(iPortID + 2, 0x00);
 if (giPortMode == 0) { while (inportb(iPortID + 2) != 0x00);}
 delay (iTimeRetOn);

 if (giLogMode == 1) {
  fprintf (gflFileLOG, "\nCODSEND: %5d, %5d, %5d, %5d", iCod1, iCod2, iCod3, iCod4);
  fprintf (gflFileLOG, " -> HEX: 0x%2x, 0x%2x, 0x%2x, 0x%2x", ucCod1, ucCod2, ucCod3, ucCod4);
 }

 if (gaiTimeRet[1] > 0) {
  ucCod1 = ucFunMgMPAP (0, DEFMOTOFF);
  ucCod2 = ucFunMgMPAP (1, DEFMOTOFF);
  ucCod3 = ucFunMgMPAP (2, DEFMOTOFF);
  ucCod4 = ucFunMgMPAP (3, DEFMOTOFF);

  outportb(iPortID + 2, 0x03);
  if (giPortMode == 0) { while (inportb(iPortID + 2) != 0x03);}
  outportb(iPortID, ucCod1 + ucCod2);
  if (giPortMode == 0) { while (inportb(iPortID) != ucCod1 + ucCod2);}
  outportb(iPortID + 2, 0x02);
  if (giPortMode == 0) { while (inportb(iPortID + 2) != 0x02);}
  outportb(iPortID, ucCod3 + ucCod4);
  if (giPortMode == 0) { while (inportb(iPortID) != ucCod3 + ucCod4);}
  outportb(iPortID + 2, 0x00);
  if (giPortMode == 0) { while (inportb(iPortID + 2) != 0x00);}
  delay (iTimeRetOff);

  if (giLogMode == 1) {
 fprintf (gflFileLOG, "\nCODSEND: %5d, %5d, %5d, %5d", iCod1, iCod2, iCod3, iCod4);
 fprintf (gflFileLOG, " -> HEX: 0x%2x, 0x%2x, 0x%2x, 0x%2x", ucCod1, ucCod2, ucCod3, ucCod4);
  }
 }

 return (0);
}

/***********************************************************************/
/* Funcion que lee una cadena de caracteres desde un fichero */
int iffgetLine(FILE *fich, char *cadena) {
 unsigned int t=0;
 char carac;
 int iValReturn = 1;

 if (feof(fich)) {
  iValReturn = -1;
  goto iffgetLine_exit;
 }
 /* aqui se lee del fichero hasta encontrar un caracter de cambio de linea */
 while((carac=fgetc(fich)) != EOF && carac != '\n') {
  cadena[t]=carac;
  t++;
 }
 cadena[t]='\0';
 iValReturn = t;

iffgetLine_exit:
 return(iValReturn);
}

/***********************************************************************/
/* Funcion que escribe la despedida en la pantalla al salir            */
void vPonDesp(void) {
 clrscr();
 textcolor(15);
 textbackground(0);

 printf("\n");
 printf("\nCNC4MPAP - Controlador 4 Motores Paso a Paso por LPT con 74LS374  (FPR-2/7/01)");
 printf("\n");
 printf("\n    Programado para el control de 4 motores paso a paso unipolares de 4 fases");
 printf("\n     y por doble envio de se¤al a los 74LS374 que controlan los ULN2803");
 printf("\n");
 printf("\n    Desarrollado Por: Francisco Pantano Rubi¤o a 20/10/2001");
 printf("\n");
 printf("\n    Para el proyecto de CncFoam y CncFresa");
 printf("\n");
 printf("\n");
 printf("\n                             e-mail: franpr@terra.es");
 printf("\n                             web:    www.terra.es/personal/franpr");
 printf("\n");
 printf("\n");
}