Logo Studenta

sim14

Esta es una vista previa del archivo. Inicie sesión para ver el archivo original

/** @file sim10.c
 *
 *	@date 20 de septiembre de 2022
 *	@version 1.0
 *
 *	@authors Vera, Pablo Martín.
 *
 *	@brief Archivo fuente que simula al puerto 0x200 y se utiliza para validar
 *		 	el programa del ejercicio 14. Los resultados esperados son:
 candidato votos
 -------- --------
 0 0
 1 3
 2 0
 3 1
 4 1
 5 0
 6 5
 7 0
 *
 *	@note Solo se puede habilitar el puerto con dirección 0x200. Los demás
 *	 puertos se toman como que no están disponibles en la PC.
 *
 *
/** \addtogroup Simulador para ejercicio 14 de puertos.
 * @{
 */
/*==================[bibliotecas]============================================*/
#include <stdio.h>
#include <stdlib.h>
/*==================[macros]=================================================*/
/**	@def PUERTO_BASE
 *	@brief Dirección base del puerto disponible según este simulador.*/
#define PUERTO_BASE 0x200
/**	@def CANT_ELEM_VEC(x)
 *	@brief Macro para calcular la cantidad de elementos de un vector "X".*/
#define CANT_ELEM_VEC(x) (sizeof(x) / sizeof(x[0]))
/*==============================[Tipos de datos]=============================*/
typedef enum{
	CANDIDATO0,
	CANDIDATO1,
	CANDIDATO2,
	CANDIDATO3,
	CANDIDATO4,
	CANDIDATO5,
	CANDIDATO6,
	CANDIDATO7
}CANDIDATO_t;
typedef enum{
	SINC_OFF,
	SINC_ON
}sincStatus_t;
typedef enum{
	FIN_OFF,
	FIN_ON
}finStatus_t;
typedef enum{
	DESHABILITADO,
	HABILITADO,
	ERROR_ESTADO
}portStatus_t;
typedef struct{
	unsigned int dir;
	portStatus_t estado;
}puerto_t;
typedef enum{
	OK,
	ERROR1,
	ERROR2,
	ERROR3
}estadoActivacion_t;
struct infoXXSim
{
	unsigned char s:1;
	unsigned char :3;
	unsigned char candidato:3;
	unsigned char f:1;
};
union puertoXXSim
{
	struct infoXXSim campos;
	unsigned char dato;
};
/*==================[declaración de variables internas]======================*/
/**@var dirPuertos
 * @brief Vector que almacena la dirección y estado del puerto 0x200, el cual
 *		 inicialmente está deshabilitado.*/
static puerto_t dirPuertos[] = {
	{ .dir = PUERTO_BASE, .estado = DESHABILITADO}
};
/*==================[definición de funciones internas]=======================*/
/** @fn unsigned char ArmarDatoPuerto (finStatus_t fin,
									 CANDIDATO_t mol,
									 sincStatus_t sinc)
 * 	@brief Permite armar un valor de 8 bits según los datos del bit de fin, de
 *		 sincronismo y de los bits de CANDIDATO.
 *	@return unsigned char Dato armado para ser enviado al puerto.
 */
unsigned char ArmarDatoPuerto (finStatus_t fin, CANDIDATO_t candidato, sincStatus_t sinc)
{
	/* Declaraciones locales */
 union puertoXXSim byte;
	/* Cuerpo de la función*/
	byte.campos.candidato = candidato;
	byte.campos.f = fin;
	byte.campos.s = sinc;
	return byte.dato;
}
/** @fn int BuscarPuerto (puerto_t portVec[], int cnt, unsigned int port)
 * 	@brief Permite buscar en forma secuencial la dirección "port" dentro del
	 vector "portVec" el cual tiene "cnt" elementos.
 *	@return int que vale:
 *		-1: No se encontró al "port" en "porVec".
 *		otro valor: Se encontró.
 */
int BuscarPuerto (puerto_t portVec[], int cnt, unsigned int port)
{
	/* Declaraciones locales */
	int i = 0;
	int pos = -1;
	/* Cuerpo de la función*/
	while(i < cnt && pos == -1){
		if(portVec[i].dir == port){
			pos = i;
		}
		else{
			i++;
		}
	}
	return pos;
}
/** @fn int ioperm (unsigned int port, unsigned int cant, int accion)
 * 	@brief Permite habilitar o deshabilitar una cantidad entera de puertos consecutivos.
 *	@return estadoActivacion_t que vale:
 *		OK: Se habilita/deshabilita correctamente.
 *		ERROR1: Error por valores de cant y/o accion.
 *		ERROR2: Error por dirección del puerto.
 *		ERROR3: Error por direcciones consecutivas de puertos.
 */
int ioperm (unsigned int port, unsigned int cant, int accion)
{
	/* Declaraciones locales */
	unsigned int i = 0;
	int pos;
	estadoActivacion_t activacion;
	portStatus_t estadoASetear;
	/* Cuerpo de la función*/
	/*Se guarda el estado a setear. Aunque "estadoASetear" sea enum, admite
	 *valores negativos y mayores a 1.*/
	switch(accion){
		case 0: estadoASetear = DESHABILITADO;
				break;
		case 1: estadoASetear = HABILITADO;
				break;
		default: estadoASetear = ERROR_ESTADO;
	}
	/*Se validan los parámetros formales.*/
	if(cant > 0 && (estadoASetear == HABILITADO || estadoASetear == DESHABILITADO) ){
		/*Se hace primero una búsqueda secuencial de la dirección "port" en el
		 *vector "dirPuertos".*/
		pos = BuscarPuerto(dirPuertos, CANT_ELEM_VEC(dirPuertos), port);
		/*Si se encuentra el puerto, se chequea que los puertos consecutivos se
		 *puedan habilitar. Por defecto, se supone que se pueden habilitar hasta
		 *que se demuestre lo contrario.*/
		if(pos != -1){
			i = 1;
			activacion = OK;
			/*Se buscan los puertos consecutivos en el vector "dirPuertos".*/
			while(i < cant && activacion == OK){
				if((port + i) != dirPuertos[pos + i].dir){
					activacion = ERROR3;
				}
				else{
					i++;
				}
			}
			/*Se habilitan/deshabilitan si es posible.*/
			if(activacion == OK){
				for (i = 0; i < cant; i++){
					dirPuertos[pos + i].estado = estadoASetear;
				}
			}
		}
		else{
			activacion = ERROR2;
		}
	}
	else{
		activacion = ERROR1;
	}
	return activacion;
}
/** @fn void MostrarError()
 * 	@brief Muestra un mensaje de error en caso de que existe uno cuando se usa la función "inb".
 */
void MostrarError()
{
	/* Declaraciones locales */
	/* Cuerpo de la función*/
	printf("\n\n****************************************************************************************\n");
	printf("ERROR. El puerto, por el que desea leer un dato, no existe o no esta habilitado.\n");
	printf("****************************************************************************************\n");
}
/*Para esta función se consideraron los siguientes casos:
 *	-Datos válidos de los CANDIDATOs 1, 4 y 6.
 *	-Recibir en forma consecutiva el mismo dato válido, para que se contemple
 *	 la situación de error en la que no se espere que el bit S pase de 1 a 0.
 *	-Bit F en 1 cuando el dato NO es válido para que el usuario solo analice
 *	 ese bit si el dato es válido. De no hacerlo, el programa se cierra.
 *	-Bit F en 1 en caso de agotarse los casos. En otras palabras, si se lee más
 * de 16 veces, se tiene siempre luego la condición de fin. */
unsigned char inb( int port)
{
	/* Declaraciones locales */
	static int orden =1;
	int pos;
	unsigned char valor = 0;
	/* Cuerpo de la función*/
	/*Se verifica que el puerto está habilitado*/
	pos = BuscarPuerto(dirPuertos, CANT_ELEM_VEC(dirPuertos), port);
	if( pos == -1 || dirPuertos[pos].estado == DESHABILITADO){
		MostrarError();
	}
	else
	{
		switch(orden)
		{
			case 1: valor= ArmarDatoPuerto(FIN_ON, CANDIDATO0, 1);
					break;
			case 2: valor= ArmarDatoPuerto(FIN_ON, CANDIDATO0, 1);
					break;
			case 3: valor = ArmarDatoPuerto(FIN_OFF, CANDIDATO1, 0);
					break;
			case 4: valor = ArmarDatoPuerto(FIN_OFF, CANDIDATO1, 0);
					break;
			case 5: valor = ArmarDatoPuerto(FIN_ON, CANDIDATO1, 0);
					break;
			case 6: valor = ArmarDatoPuerto(FIN_OFF, CANDIDATO1, 1);
					break;
			case 7: valor = ArmarDatoPuerto(FIN_OFF, CANDIDATO1, 0);
					break;
			case 8: valor = ArmarDatoPuerto(FIN_OFF, CANDIDATO3, 0);
					break;
			case 9: valor = ArmarDatoPuerto(FIN_OFF, CANDIDATO3, 1);
					break;
			case 10: valor = ArmarDatoPuerto(FIN_OFF, CANDIDATO4, 0);;
					 break;
			case 11: valor = ArmarDatoPuerto(FIN_OFF, CANDIDATO5, 0);
					 break;
			case 12: valor = ArmarDatoPuerto(FIN_OFF, CANDIDATO6, 1);
					 break;
			case 13: valor = ArmarDatoPuerto(FIN_OFF, CANDIDATO6, 0);
					 break;
			case 14: valor = ArmarDatoPuerto(FIN_OFF, CANDIDATO6, 1);
					 break;
			case 15: valor = ArmarDatoPuerto(FIN_OFF, CANDIDATO6, 0);
break;
			case 16: valor = ArmarDatoPuerto(FIN_OFF, CANDIDATO6, 1);
					 break;
			default: valor = ArmarDatoPuerto(FIN_ON, CANDIDATO0, 0);
					 break;
		}
		orden++;
	}
	return valor;
}
/** @} doxygen end group definition */
/*==================[fin del archivo]============================================*/

Continuar navegando