/* PUENTE.C
Control de un puente levadizo accionado neumáticamente, mediante puerto paralelo
2002 Víctor R. González - Angelberto Mieres
*/
#include <stdio.h>
#include <dos.h>
#include "paralelo.h"
#define APAGADO 0x00 /* D0-D7, pin 2-9, desactivados */
#define SIRENA 0x01 /* D0, pin 2, zumbador */
#define ROJO 0x02 /* D1, pin 3, LED */
#define VERDE 0x04 /* D2, pin 4, LED */
#define AMBAR 0x08 /* D3, pin 5, LED */
#define PUENTE_SUBE 0x10 /* D4, pin 6, electroválvula */
#define PUENTE_BAJA 0x20 /* D5, pin 7, electroválvula */
#define PULSA_ALIM 0x80 /* D7, pin 9, alimentación pulsadores */
#define BARCO_VIENE 0x0 /* S6, pin 10 alto, detector IR */
#define PULSA_SUBIR 0x0 /* S7#,pin 11 bajo, pulsador n/c de subida */
#define PULSA_BAJAR 0x0 /* S5, pin 12 bajo, pulsador n/a de bajada */
/* El estado normal de los sensores (desactivados) es: S7#=1, S6=1, S5=1 */
#define T_ROJO 5 /* duración (en segundos) de la luz roja */
#define T_VERDE 5 /* duración (en segundos) de la luz verde */
#define T_AMBAR 2 /* duración (en segundos) de la luz ambar */
#define T_PARPADEO 400 /* duración (en milisegundos) del parpadeo de la luz ambar */
#define T_SUBIDA 3 /* duración (en segundos) de la elevación del puente */
#define T_BAJADA 3 /* duración (en segundos) de la bajada del puente */
#define T_ESPERA 10 /* período (en milisegundos) de atención al teclado */
/* Activa las señales adecuadas del puerto */
#define Activa(valor) if (en_marcha) {outportb (DATOS, valor | PULSA_ALIM); printf("Enviado: 0x%X\n", valor);}
#define SensorSubir() (inportb (ESTADO) & 0x80) /* Toma sólo bit 7 de ESTADO */
#define SensorBarco() (inportb (ESTADO) & 0x40) /* Toma sólo bit 6 de ESTADO */
#define SensorBajar() (inportb (ESTADO) & 0x20) /* Toma sólo bit 5 de ESTADO */
#define Apaga() outportb (DATOS, APAGADO) /* Desactiva las salidas */
int ParaleloIni (void);/* Detecta el puerto paralelo */
void Espera (float); /* Espera con atención al teclado y a las entradas digitales */
char en_marcha; /* Indica el funcionamiento o el fin del proceso */
void main (void)
{
/* Realiza el control si se detecta el puerto paralelo */
if ( ParaleloIni() != LPT_NINGUNO ) {
Activa (PULSA_ALIM); /* Activa alimentación circuito pulsadores */
en_marcha = TRUE;
/* Secuencia periódica de los semáforos
esperando suceso de teclado o entrada digital */
do {
Activa (VERDE); Espera (T_VERDE);
Activa (AMBAR); Espera (T_AMBAR);
Activa (ROJO); Espera (T_ROJO);
} while( en_marcha );
Apaga(); /* Apaga las señales del puerto */
}
else {
printf ("No se encuentra ningún puerto paralelo\n");
exit(1);
}
}
/*
Realiza una espera activa de <t> segundos.
Atiende al teclado y a las entradas digitales cada 10 ms
*/
void Espera (float t)
{
int t_max = 1000*t; /* tiempo a esperar (en ms) */
int crono = 0; /* tiempo transcurrido (en ms) */
int periodo= T_ESPERA;
int tecla, sens_barco, barco = FALSE;
char puente_arriba = FALSE;
/* Espera hasta que se agota el crono */
while (en_marcha && crono < t_max) {
if ( kbhit() ) tecla = getch(); /* Comprueba teclado */
sens_barco = SensorBarco(); /* Comprueba presencia del barco */
if (tecla == '+' || SensorSubir() == PULSA_SUBIR || (!barco && sens_barco == BARCO_VIENE)) {
if (sens_barco == BARCO_VIENE) barco = TRUE;
/* Eleva las hojas del puente */
for (crono=0; crono< 1000*T_SUBIDA; crono += 2*T_PARPADEO) {
Activa (SIRENA + PUENTE_SUBE + AMBAR);
delay (T_PARPADEO);
Activa (SIRENA + PUENTE_SUBE);
delay (T_PARPADEO);
}
Activa (SIRENA);
puente_arriba = TRUE;
tecla = 0;
crono = 0;
} else
if( tecla == '-' || (!barco && SensorBajar() == PULSA_BAJAR) || (barco && sens_barco != BARCO_VIENE)) {
barco = FALSE;
/* Baja las hojas del puente */
for (crono=0; crono< 1000*T_BAJADA; crono += 2*T_PARPADEO) {
Activa (SIRENA + PUENTE_BAJA + AMBAR);
delay (T_PARPADEO);
Activa (SIRENA + PUENTE_BAJA);
delay (T_PARPADEO);
}
Apaga();
puente_arriba = FALSE;
tecla = 0;
crono = t_max; /* Sale del modo espera */
} else
if( tecla == 'f' ) {
/* Finaliza; si el puente está elevado, lo baja */
if (puente_arriba) {
Activa (PUENTE_BAJA);
delay (1000*T_BAJADA);
}
en_marcha = FALSE;
} else
if (puente_arriba) {
/* Si el puente sigue elevado, la sirena suena y las luces ambar parpadean */
Activa (SIRENA + AMBAR);
delay (T_PARPADEO);
Activa (SIRENA);
delay (T_PARPADEO);
} else {
/* Espera hasta nueva comprobación de teclado y pulsadores */
delay (periodo);
crono += periodo;
}
}
}
/* Identifica los puertos paralelos instalados en el PC
Devuelve (ver paralelo.h):
LPT_NINGUNO: si no hay puertos instalados
LPT_OTROS : si el primer puerto es de tipo desconocido
LPT_SPP : si el primer puerto es SPP
LPT_BIDIR : si el primer puerto es bidireccional
LPT_EPP : si el primer puerto es EPP
LPT_ECP : si el primer puerto es ECP
*/
int ParaleloIni (void)
{
unsigned int PuertoNum, Puerto, NumPuertos;
unsigned int Byte, tmp;
char PuertoEPP;
int PuertoTipo;
char *PuertoNombre[]={"", "Estandar (SPP)", "Bidireccional", "EPP", "ECP"};
/* Busca la dirección de E/S de los puertos instalados */
NumPuertos = 0;
PuertoTipo = LPT_NINGUNO;
for (PuertoNum=1; PuertoNum<=3; PuertoNum++) {
_lpt_dir[PuertoNum] = peek(0x0040,0x0008 + (PuertoNum-1)*2);
if (_lpt_dir[PuertoNum] == 0)
printf ("No se encuentra puerto asignado a LPT%d \n", PuertoNum);
else {
printf ("La dirección asignada a LPT%d es 0x%X\n", PuertoNum, _lpt_dir[PuertoNum]);
NumPuertos++;
}
}
if (NumPuertos > 0 ) {
/* Detecta el tipo de puerto del primero hallado */
printf ("\nPuerto seleccionado: LPT%d en 0x%X. ", LPT_NUM, LPT_BASE);
/* Prueba puerto ECP */
Byte = inportb (CONTROL_EXT) & 0x03; /* toma bits 0 y 1 de CONTROL_EXT */
if (Byte == 1) {
Byte = inportb (CONTROL);
tmp = Byte;
outportb (CONTROL, Byte ^ 0x03); /* pone a 0 los bits 0 y 1 de CONTROL */
Byte = inportb(CONTROL_EXT) & 0x03;
if (Byte == 1) PuertoTipo = LPT_ECP;
outportb (CONTROL, tmp); /* restaura CONTROL */
}
/* Prueba puerto EPP */
if (!PuertoTipo) {
PuertoEPP = FALSE;
if (LPT_BASE != 0x03BC) {
Byte = inportb (ESTADO);
tmp = Byte;
outportb (ESTADO, Byte & (~0x01) ); /* Pone a 0 el bit 0 de ESTADO */
for (Puerto=REG_EPP_PRI; Puerto<=REG_EPP_ULT; Puerto++) {
outportb (Puerto, 0x55);
Byte = inportb (Puerto);
if (Byte == 0x55) {
outportb (Puerto, 0xAA);
Byte = inportb (Puerto);
PuertoEPP = (Byte == 0xAA);
if (!PuertoEPP) break;
}
}
outportb (ESTADO, tmp); /* restaura bit 1 de ESTADO */
}
if (PuertoEPP) PuertoTipo = LPT_EPP;
}
/* Prueba puerto SPP */
if (!PuertoTipo) {
Byte = inportb (CONTROL);
tmp = Byte;
outportb (CONTROL, Byte | 0x20 ); /* Pone a 1 el bit 5 de CONTROL (entrada de DATOS) */
outportb (DATOS, 0x55);
Byte = inportb (DATOS);
if (Byte == 0x55) {
outportb (CONTROL, Byte | 0x20 ); /* Pone a 1 el bit 5 de CONTROL (entrada de DATOS) */
outportb (DATOS, 0xAA);
Byte = inportb (DATOS);
if (Byte == 0xAA) PuertoTipo = LPT_SPP;
}
outportb (CONTROL, tmp); /* Restaura el bit 5 de CONTROL */
}
/* Prueba puerto bidireccional */
if (!PuertoTipo) {
Byte = inportb (CONTROL);
tmp = Byte;
outportb (CONTROL, Byte | 0x20 ); /* Pone a el 1 bit 5 de CONTROL (entrada de DATOS)*/
outportb (DATOS, 0x55);
Byte = inportb (DATOS);
if (Byte != 0x55) {
outportb (CONTROL, Byte | 0x20 ); /* Pone a el 1 bit 5 de CONTROL (entrada de DATOS) */
outportb (DATOS, 0xAA);
Byte = inportb (DATOS);
if (Byte != 0xAA) PuertoTipo = LPT_BIDIR;
}
outportb (CONTROL, tmp); /* Restaura el bit 5 de CONTROL */
}
if (PuertoTipo) {
printf("Puerto tipo: %s (%i)\n", PuertoNombre[PuertoTipo], PuertoTipo);
/* Pone DATOS en modo salida */
DATOS_out();
/* Pone las salidas en bajo */
outportb (DATOS, 0x00); /* reg. de DATOS */
outportb (CONTROL, inportb (CONTROL) & 0xFB); /* nibble bajo del reg. de CONTROL */
} else {
PuertoTipo= LPT_OTROS; /* Puerto de tipo desconocido */
printf("Puerto de tipo desconocido\n");
}
} /* NumPuertos > 0 */
return( LPT_TIPO = PuertoTipo );
}