Sie sind auf Seite 1von 311

ING. LUIS G. URIBE C.

Ingeniería Digital:
Aspectos
Técnicos
Tercera Edición
Diciembre 2010, V3c
ING. LUIS GUILLERMO URIBE CATAÑO

Aspectos Técnicos de la Ingeniería Digital

 2008,  2010 Ing. Luis G. Uribe C.


Caracas, Venezuela

P-i
Contenido

PRÓLOGO ................................................................. 6 FALLAS EN NUESTROS MODELOS MENTALES ....25

FALLA EN VUELO DE AIR CANADA ................28


ABSTRACT .......................................................... 6
EL CODIDAC, Computador Digital Didáctico. .....29
Un nombre como telón de fondo ......................... 6
LOS ORÍGENES ....................................................29
INTRODUCCIÓN .................................................. 7
EL ENTRENAMIENTO...........................................29
A QUÉ SE ENFRENTA UN INGENIERO DEL ÁREA
LA ARQUITECTURA .............................................29
DE DIGITALES ......................................................... 7
LAS INSTRUCCIONES ..........................................30
Observaciones sobre términos empleados ........ 10
LOS MODIFICADORES..........................................30
PLAN DEL DOCUMENTO ................................... 11
EL SUBSISTEMA DE ENTRADA Y SALIDA ...........30
HISTORIA ................................................................. 13
LOS CÓDIGOS DE OPERACIÓN ............................31
INTRODUCCIÓN .................................................. 13
EL EDITOR ...........................................................31
¿CUÁL FUE EL PRIMER PROGRAMA QUE SE
EL FORMATO DE LOS NÚMEROS.........................31
ENSAMBLÓ? ............................................................. 14
LA CALCULADORA...............................................31
FALLA EN TOMÓGRAFOS AXIALES EN CARACAS,
LA ESTRUCTURA .................................................32
1980.......................................................................... 15
DATOS ESTADÍSTICOS ........................................32
Qué hacer si se interrumpe una operación ........ 15
LAS PRUEBAS EN FRÍO .......................................33

EL CONGRESO DE INGENIEROS JAVERIANOS ...33


Qué hacer en casos de rearranque..................... 15
EL PRIMER ENCENDIDO ......................................33
Las desviaciones................................................. 17 SUMMA CUM LAUDAE .........................................34

LAS FALLAS DEL MARS CLIMATE ORBITER Y LA PRESENTACIÓN EN SOCIEDAD...................... 34

DEL MARS POLAR LANDER, 1999 ........................ 17 EPÍLOGO ..............................................................35

FALLA DEL COHETE EUROPEO ARIANE 5 ......... 17 FOTOS ..................................................................36

Introducción ........................................................ 17 BIBLIOGRAFÍA.....................................................38

PROYECTOS..............................................................39
Cadena Inversa de Eventos Técnicos................. 18
PROYECTOS I, INTRODUCCIÓN .........................39

Comentarios Sobre el Escenario de la Falla....... 19 ASPECTOS GENERALES.....................................39

PRODUCTO, MERCADO, ADMINISTRACIÓN ......39


Los Procedimientos de Prueba y Calificación .... 21
THINK BIG... OR SMALL?..................................40

Conclusiones ....................................................... 24 INTERROGANTES PARA LA INVESTIGACIÓN .....43


CÓMO SE PLANIFICA UN PROYECTO ............. 44 ARMADO DE CIRCUITOS...........................................70
ASPECTOS PREVIOS .......................................... 44
BLINDAJE Y CABLEADO ...........................................71
DISEÑO CONCEPTUAL ....................................... 44

CRONOGRAMA (TENTATIVO) DE TRABAJO .... 45 EXPERIMENTACIÓN..................................................71


ENMIENDAS AL CRONOGRAMA DE TRABAJO .... 45
QUÉ CHIPS USAR .....................................................72
DISEÑO FUNCIONAL HARDWARE, SOFTWARE........ 45
DOS LINKS FABULOSOS.........................................72
DESCRIPCIÓN...................................................... 45
“C”........................................................................73

ENMIENDAS AL DISEÑO FUNCIONAL ................. 45 PROGRAMAR LA FLASH ....................................77

INTEN, INTDSB; TRAZAS ...................................77


DISEÑO FUNCIONAL: HARDWARE ......................... 46
A FAVOR DE “C”................................................78
DISEÑO FUNCIONAL: SOFTWARE .......................... 46
"PESADILLA ¿HARDWARE O SOFTWARE?" .......79
DISEÑO DETALLE HARDWARE, SOFTWARE ........... 47
PREMISA DE URIBE: ............................................80
DESCRIPCIÓN...................................................... 48

"PERDER LOS ARCHIVOS"......................................80


DISEÑO DE DETALLE DE HARDWARE .................. 48
CITAS CITABLES..................................................81
DISEÑO DE DETALLE DE SOFTWARE................... 48
PROYECTOS II ....................................................82
Ambiente de Desarrollo....................................... 49
DOCUMENTACIÓN ...............................................82
VARIOS ..................................................................... 49
ESTACIÓN METEOROLÓGICA ALTAS PRESTACIONES....82
PRUEBAS HARDWARE, SOFTWARE: PROTOTIPO.... 49

PROTOTIPO ......................................................... 50 IDEAS PARA MANUALES DEL PROYECTO ...........82

PRUEBAS DE SOFTWARE ......................................... 50 MANUAL USO E INSTALACIÓN PROTOTIPO ............82

PRUEBAS DE HARDWARE ........................................ 50 MANUAL TÉCNICO...................................................83

PRUEBAS DE SISTEMA............................................. 50 EXPLICACIÓN ...........................................................83

DOCUMENTACIÓN DEL SISTEMA ..................... 51 CONCLUSIÓN............................................................83


A NIVEL DE PRODUCTO: .................................. 51

A NIVEL DE FABRICACIÓN:.............................. 51 BIBLIOGRAFÍA CONSULTADA Y SITIOS WEB EN

A NIVEL DE C/EQUIPO, FICHA TÉCNICA:........... 51 LOS QUE SE SOPORTÓ ..........................................83

INSTALACIÓN Y GARANTÍA.............................. 52
ANEXOS ....................................................................83
RESGUARDO DEL PRODUCTO .......................... 52

RESPALDO ........................................................... 53 EXTRAS.....................................................................84

DETALLE (CHECK-LIST √) .................................. 53


SCADA.......................................................................84
COMUNICACIÓN.................................................. 67
INTRODUCCIÓN ...................................................84
FLUJO DE CAJA: ZERO CASHFLOW ............... 67

FAST PROTOTYPING ......................................... 68 CONSTITUCIÓN ........................................................85

QUE FUNCIONE.................................................. 69
ESPECIFICACIONES DEL PROYECTO.....................85
KISS .................................................................... 70

TEMAS VARIOS QUE SON “PURO ORO” ........ 70 ESTACIÓN MAESTRA................................................86

CONCEPTOS BÁSICOS DE ELECTRÓNICA. ...... 70


SUBSISTEMA DE ADQUISICIÓN DE DATOS ............. 86 - INTEGRADORES DE SISTEMAS .............................. 105

- ARQUITECTURA ABIERTA Y ESTÁNDAR ...............106


SUBSISTEMA DE PRESENTACIÓN DE INFORMACIÓN 86
- INGENIERÍA REVERSA DE PROTOCOLOS ..............107

GENERACIÓN Y PROCESAMIENTO DE ALARMAS ... 87 - PRESENCIA LOCAL .................................................107

- INNOVACIÓN TECNOLÓGICA .................................107


CONTROL REMOTO .................................................. 87
¿CÓMO? ....................................................................107

COMUNICACIÓN CON LAS RTU DEL CAMPO........... 87


¿QUÉ? .......................................................................108

RTU........................................................................... 88
¿DÓNDE?...................................................................108

ADQUISICIÓN DE DATOS ANALÓGICOS (AI) ........... 88


¿CUÁNTO? ................................................................108

ADQUISICIÓN DE DATOS DIGITALES (DI)................ 88


¿CON QUÉ? ...............................................................109

CONTROL (DO) ......................................................... 89


¿PARA QUÉ? .............................................................109

COMUNICACIÓN CON LA ESTACIÓN MAESTRA ...... 89


- RESUMEN................................................................109

ANTEPROYECTO ...................................................... 90 BIBLIOGRAFÍA.....................................................112

DATA LOGGER......................................................... 91 CIRCUITOS DIGITALES............................................113

TÍTULO DEL PROYECTO.................................... 91 INTRODUCCIÓN...................................................113

REALIDAD Y ELECTRÓNICA ANALÓGICA ........114


CONTRATANTE DEL PROYECTO............................ 91
¿POR QUÉ EL NOMBRE DE “ANALÓGICO”? ........114

OBJETIVOS DEL PROYECTO.................................. 91 EJEMPLO DE TRANSDUCCIÓN ............................114

ELECTR. DIGITAL: CARAC. IMPORTANTES ........115


DESCR. EQUIPOS A SER DESARROLLADOS ............ 91
1) REPRESENTACIÓN NUMÉRICA ...........................115

CARACT. FUNCIONALES MÍNIMAS DEL SISTEMA ... 91 2) VARIABLES DISCRETAS, INMUNIDAD A RUIDO ..115

3) EXACTITUD, PRECISIÓN Y RESOLUCIÓN .........116


SUBSISTEMA DE APLICACIÓN FINAL ................... 93
4) CNTRL ERRORES: DETECCIÓN, CORRECCIÓN ....117

5) ALMACENAMIENTO DE INFORMACIÓN..............118
ASPECTOS EXTRAS QUE DEBEN CONSIDERAR .. 93
6) PROCESAMIENTO DE LA VARIABLE TIEMPO ......118
FAT, SAT: FORMULARIOS DE EJEMPLO .............. 94
7) ESTANDARIZACIÓN..............................................118
FAT: DOCUMENTO DE ACEPTACIÓN EN
CONVERSIÓN ENTRE BASES ............................119
FÁBRICA (PARA EL “DATA LOGGER”).................. 94 1) CONVERS. DECIMAL-BINARIO O HEXADEC. ........119

SAT: DOCUMENTO ACEPTACIÓN EN SITIO MÉTODO CONVENCIONAL ...................................119

(“DATA LOGGER”) ................................................... 97


MÉTODO RECOMENDADO.........................................119

ZigZag al pensamiento lineal ............................. 99


2) CONVERSIÓN DE BINARIO A DECIMAL................120
Excepciones a TODO........................................... 99
MÉTODO CONVENCIONAL ...................................120
OPINIÓN EMPRESARIAL-I ................................... 100

Invention Is a Flower, Innovation Is a Weed ...... 100 MÉTODO RECOMENDADO.........................................120

OPINIÓN EMPRESARIAL-II .................................. 105 3) CONVERSIÓN DE HEXADECIMAL A DECIMAL......121


MÉTODO CONVENCIONAL .................................. 121 IDENTIFICACIÓN DE ENTRADAS Y SALIDAS ...........137

MÉTODO RECOMENDADO ........................................ 121 UNA SOLUCIÓN: PLANTEAMIENTO..........................138

4) CONVERSIÓN DE OCTAL A DECIMAL .................. 121


PROGRAMACIÓN DE LA SOLUCIÓN .........................140
LAB0.................................................................... 122

PROTOBOARD ..................................................... 123 SOLUCIÓN VÍA ROM .................................................142

CIRCUITOS INTEGRADOS Y ALAMBRES............. 123


SOLUCIÓN VÍA MULTIPLEXER .................................143
FUENTES DE ALIMENTACIÓN ............................. 125

INTERRUPTORES ................................................ 125 IMPACTO AL AGREGAR ENTRADAS Y SALIDAS ......143

FAN OUT .............................................................. 126 PROBLEMA TÍPICO: EDP CENTER ............................145


ENTRADAS NO USADAS ...................................... 126
CAMBIOS EN EL PROBLEMA ...............................146
CUIDADOS CON LOS CMOS................................. 127
INTRODUCCIÓN AL CÓDIGO HAMMING...........146
CONDENSADORES DE DESACOPLE .................... 127
GENERALIDADES .................................................146
EQUIPO Y SALIDAS ............................................. 128
HAMMING PARA UN BIT DE INFORMACIÓN........147
QUÉ VA A FALLAR EN PROYECTOS DE LAB.... 129
HAMMING PARA 4 BITS DE INFORMACIÓN (Y 3 DE
1) FAN OUT............................................................... 129
PARIDAD: 7,4) ...........................................................150

2) AND POR EL PULSO DE RELOJ ............................ 129 DETECCIÓN DE (2) ERRORES Y CORRECCIÓN DE (1)

ERROR CON CÓDIGO HAMMING...............................152


3) ESTADO INICIAL .................................................. 130
CÓDIGO HAMMING PROGRAMADO EN “C” Y

4) SEÑALES NO SINCRONIZADAS ........................... 131 ASSEMBLER PIC 16F84A ..........................................153

CÓDIGO HAMMING COMENTADO ........................156


5) SEÑALES MÁS RÁPIDAS QUE PULSO RELOJ ...... 131 CURIOSIDADES ...................................................160

REDES SECUENCIALES .......................................161


6) FALTA DE SOPORTE PARA "DEBUGGING" .......... 131
INTRODUCCIÓN ...................................................161
7) SWITCHES CON REBOTE ..................................... 131 CONCEPTO DE ESTADO: PROF. GIRATORIO .......161

UNA SOLUCIÓN: PLANTEAMIENTO....................162


8) LED. CARGAS NO TTL .......................................... 131
PROGRAMACIÓN DE LA SOLUCIÓN ....................164

9) ALIMENTACIÓN DEL PROTOBOARD .................... 131 EJEMPLO2: SECUENCIA 111, SOLAPAMIENTO ..166

PROGRAMACIÓN “111” CON SOLAPAMIENTO....166


10) SOLDADURA!!! .................................................... 132
EJEMPLO3: SECUENCIA 111 SIN SOLAPAR........167

11) CONDENSADORES DE DESACOPLE ................... 132 PROGRAMACIÓN “111” SIN SOLAPAMIENTO .....167

HÁGASE LA LUZ ................................................168


12) DIAGRAMAS ....................................................... 133
1) RECONECTADOR ..................................................168

13) IMPROVISACIÓN E INGENIO... Vs. ¡ MÉTODO ! . 134 2) COMPORTAMIENTO ASINCRÓNICO ....................169

3) “ARRANCADOR” (STARTER)................................169
14) MAL USO DE LOS INSTRUMENTOS ................... 135
4) CONVERTIR FLIP-FLOPS CON “CLEAR”, EN

BIESTABLES CON “PRESET” ..................................170


15) LA JUSTIFICACIÓN ............................................ 135
REPRESENTACIÓN NUMÉRICA ..........................171
REDES COMBINATORIAS .................................... 137
INTRODUCCIÓN ...................................................171
PROBLEMA: FÁBRICA DE CHOCOLATES ................. 137
EJERCICIOS ........................................................ 175 BIBLIOGRAFÍA.....................................................247

MOTIVACIÓN ....................................................... 175 MICROCONTROLADORES .........................................248


REDES COMBINATORIAS ........................................ 175
INTRODUCCIÓN...................................................248
1) ALARMA PARA LAS CÁPSULAS APOLO........... 175 CONDITION CODE REGISTER: C, Z, N y V....252

COMPARAR ES RESTAR .........................................252


2) LA SOCIEDAD Y LOS ACCIONISTAS ................ 177
UNSIGNED ................................................................253
3) CONTROL AUTOMÁTICO DE VELOCIDAD ............ 178 SIGNED .....................................................................256

UNSIGNED REVISITED..............................................258
4) FRENAR LOS COHETES...................................... 179
COMPARACIONES PARA EL PIC.......................260

5) MONTACARGAS ................................................... 180 LIBRERÍA DE TIMERS PARA HC08 ..................267

PRUEBA LIBRERÍA DE TIMERS ........................269


6) CALDERA .............................................................. 180
EJERCICIOS ADICIONALES................................271

7) CALCULADORA BRAILLE .................................... 181 PLANTEAMENTO INICIAL ........................................271

1) EJERCICIOS DE REEMPLAZO .............................271


REDES SECUENCIALES ........................................... 182
2) MANEJO DE UNA IMPRESORA GPIB ................272
1) JUEGO DE PING-PONG (BASIC) [Solución]...... 182
3) EL JUEGO DE LA VIDA [Solución] ...................273

2) CERRADURA DE COMBINACIÓN ........................ 184 PLANTEAMIENTO .....................................................273

3) UN ASCENSOR INTERESANTE........................... 184 SOLUCIÓN (Programa life2.c) ................................274

4) REPRESENTACIÓN NUMÉRICA ........................... 184 FSM Algorithm keep data safe ............................289

BIBLIOGRAFÍA.....................................................293
5) DADO ELECTRÓNICO ........................................... 185
INGENIERÍA DIGITAL EN LA ACADEMIA ..................294
BIBLIOGRAFÍA .................................................... 186
INTRODUCCIÓN...................................................294
PROGRAMACIÓN GENERAL ..................................... 187 Enfoque hacia Solución de Problemas ...........295

INTRODUCCIÓN .................................................. 187 maestría y destrezas.........................................295

DÍGITOS DE VERIFICACIÓN .............................. 187 computadoras: Componentes de Diseño ..........296

PARECE SIMPLE................................................. 194 CELULARES: Componentes de Diseño..............296

RECURSIVIDAD ................................................... 196 Estructura de la cadena de digitales.............297

ROMANOS Y ARÁBIGOS.................................... 198 PREREQUISITOS: .................................................297

PI ......................................................................... 200 PROGRAMACIÓN I y II ......................................297

POLÍTICA Y MECANISMOS................................ 201 ELECTRÓNICA DIGITAL.......................................303

REALLY SIMPLY HASH ..................................... 218 LABORATORIO DE ELECTRÓNICA DIGITAL ........303

SASSERT ............................................................. 220 ARQUITECTURA DE COMPUTADORES y ...........305

ROUNDS UP TO A POWER OF 2 .................... 221 Lab. ARQUITECTURA COMPUTADORES .............305

PROGRAMACIÓN POR REGLAS ........................ 229 SISTEMAS OPERATIVOS .....................................307

ANTI REBOTE (Debouncing) ............................. 236 ELECTIVAS ..........................................................308

DEBOUNCING Y MÁQUINAS DE ESTADO ....... 237 Anexo: Referencias y Bibliografía ......................309

DEBOUNCING DE VARIOS BITS....................... 240

SECUENCIADOR DE EVENTOS, SOE................. 241


I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

PRÓLOGO

Aspectos prácticos que complementan los conocimientos de


Ingeniería Digital.

 ABSTRACT

S
I usted trabaja en el campo de los circuitos digitales, los microcomputadores (incluidos como
componentes), los sistemas operativos, las telecomunicaciones de datos y similares, estas notas pueden
resultarle de utilidad, pues su propósito es el de ir más allá de los conocimientos impartidos en
los planes de estudio, que por lo común tratan estos temas sólo a nivel de sistemas y omiten
referirse en detalle al hardware, al software, a los algoritmos y a los problemas prácticos.

Este material incursiona en las áreas ya mencionadas pero, desde luego, presupone en el lector el
conocimiento básico de dichos temas, adquirido con la formación académica convencional.

Un nombre como telón de fondo


Al comenzar mi actividad fuera del “campus” universitario, después de 15 años a dedicación completa
como alumno de electrónica y profesor de “digitales”, encontré un pequeño libro, “Technical Aspects
of Data Communication”, por John E. McNamara, de cuya lectura obtuve enormes beneficios. Mis
conocimientos en esa área eran a nivel de “sistemas” (ecuaciones y bloques). Cuando yo hablaba de
línea de comunicación, el libro me enseñaba lazos de corriente; las marcas y espacios, como se llamaban
desde Morse, ahora eran –12 y +12 voltios. Los cables pasaron de ser simples líneas a tener longitudes
limitantes, ¡y acotaban las velocidades de transmisión! Las conexiones seguían normas y estándares
nominados; los puntos de “tierra” fijaban sus posiciones, y no era igual conectarlos en un lugar que en
otro. El sistema asíncrono de mi viejo teleimpresor se materializó en los UART; la paridad se vistió de
polinomio y los CRC serpenteaban entre registros de desplazamiento y compuertas EXOR. Los
protocolos dejaron sus vestiduras tabulares y mostraron desnudas sus secuencias de bits. Hasta el
confort logrado cuando las centrales telefónicas eliminaron el “retorno del sonido”, hubo que aprender
a deshabilitarlo con “supresores del eliminador de eco”; claro, a las personas les convenía porque solo
parlamentaba una de las dos, mientras la otra escuchaba, ¡ pero las computadoras insistían en
comunicarse al mismo tiempo !

P-6
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Estas notas, emulando un poco aquella referencia tan útil, ofrecen aspectos técnicos que complementan
los conocimientos teóricos de los cursos regulares y sus libros de texto. Se incluyen temas provocativos,
ejercicios y problemas, resueltos y por resolver, en las áreas de la Ingeniería Digital. Se cubre el aspecto
técnico, pero también ciertas facetas gerenciales relacionadas con los proyectos.

No hay forma tan eficaz como Aprender Haciendo (ah!), pero ese método no está exento de
problemas. Por ejemplo, para aplicarlo al estudio de los circuitos digitales, la programación de
microcontroladores o los sistemas operativos, se requiere manejar con precisión una enorme cantidad
de detalles. Esa es una diferencia entre el enfoque del aula, y el del laboratorio; y entre comprender el
meollo de los conceptos, y ostentar la destreza del Maestro. Estas notas pretenden mostrar una pequeña
pero importante fracción de esos detalles, que se necesitan para la praxis, y que no se consiguen con
facilidad ni en claustros ni bibliotecas. Desde luego, siendo ilimitado el ámbito de lo que desconocemos,
este aporte resultará siempre insuficiente, con independencia de su extensión.

 INTRODUCCIÓN
A QUÉ SE ENFRENTA UN INGENIERO DEL ÁREA DE DIGITALES
La siguiente categorización es tomada de mi experiencia profesional −que en su mayoría ha sido en el
área de Desarrollo de Proyectos− y pretende plasmar el cúmulo de actividades que vi enfrentar a los
ingenieros especializados en Sistemas Digitales. El propósito es el de ayudar a ubicar al estudiante y al
joven profesional en lo que pueden ser líneas de acción del egresado con esta especialización.

Qué hace un Ingeniero con mención en Sistemas Digitales…

 Detecta necesidades concretas,  de equipos realizables bajo capacidades


disponibles de procesamiento limitadas
 Solubles en el ámbito de la especialidad de
Sistemas Digitales  Produce especificaciones funcionales de:
 sistemas,
 Elabora especificaciones de compra de:
 equipos y
 partes y
 subsistemas electrónicos
 componentes electrónicos
 Diseña circuitos, y programas asociados a
 Obtiene especificaciones (electrónicas) de
la manipulación del hardware (firmware)
diseño, contemplando factores tan
disímiles como:  Elabora prototipos, maquetas y modelos
 ubicación y alineación de antenas,  Prueba, verifica y valida, circuitos y sus
 normas y estándares aplicables, programas asociados, pertenecientes a
 seguridad intrínseca, subsistemas electrónicos
 consideraciones de consumo de energía  Especifica, para la producción:
y de generación de calor,  módulos,
 tipos de gabinetes (housing),  ensamblaje,
 diseño para una vida útil determinada...  cableado,

P-7
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

 gabinetes,  Elabora planes detallados y precisos para


 interconexión entre subsistemas, el diseño de hardware y software
 interfaces eléctricas,  Genera rutinas de autodiagnóstico y diseña
 protocolos de intercambio de dispositivos a prueba de fallas
información
 Aplica metodologías apropiadas para el
 Genera protocolos para pruebas en fábrica diseño de circuitos impresos
(FAT), y en el sitio de instalación (SAT)
 Realiza pruebas en fábrica y en sitio, para  Se vincula al proceso de realimentación,
garantizar parámetros tales como la desarrollo y administración de versiones
disponibilidad, y demás consideraciones de mejoradas del producto
diseño:  Evalúa desastres y catástrofes; hace análisis
 rendimiento, post mortem
 escalabilidad,
 Realiza mantenimiento en general; y
 extremos ambientales,
define las políticas de reparación, la
 Instala equipos estrategia y su logística
 Determina la logística de transporte y  Maneja proveedores principales y
almacenaje de subsistemas y equipos suplidores alternos
 Lleva a cabo pruebas de campo
 Integra sistemas
 Redacta:
 Calibra y afiere instrumentos
 Documentación,

 Manuales técnicos,  Ejecuta la prueba y validación de normas


 Manuales de operación,
 Hace consultoría
 Manuales de usuario,

 "Brochures"
 Determina en forma concreta y objetiva las
necesidades de mano de obra para los
 Presta la garantía de equipos y sistemas proyectos
 Resguarda apropiadamente el producto:
Respalda documentos, programas, ampara  Es preciso en la estimación de cuánto
los ambientes de desarrollo tiempo van a tomar las diversas fases de un
diseño o proyecto
 Lidera Ingenieros y demás personal
técnico  Garantiza la escalabilidad del producto
 Entrena y ejerce la docencia, tanto "in  Administra y gerencia proyectos
house" como para entidades externas
 Asume la Gerencia Técnica
 Lleva y entiende procesos contables y
administrativos relacionados con la  Aprovecha las redes y el Internet para la
Gerencia de Proyectos interconexión moderna de subsistemas

P-8
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

En algunos casos, personal técnico de nivel inferior al de Ingeniero puede abocarse a algunas de estas
actividades, que deberán en todo caso ser supervisadas. Este solapamiento de responsabilidades es
común en todas las profesiones, y es de grado, no de competencia. Hay otras zonas de interacción entre
carreras, como la Ingeniería Eléctrica y la Electrónica, o las que surgen con el Ingeniero en
Computación, o con el de Instrumentación, y hasta con el Administrador y el Economista.

El Ingeniero en Sistemas Digitales es un profesional capacitado para:

 Analizar,  bajo restricciones de consumo,


 Especificar  generación de calor,
 para una ubicación,  producción de ruido,
 según normas y estándares,  confiabilidad,
 rendimiento
sistemas, subsistemas y equipos, con la clase apropiada de gabinete (housing), y para una vida útil
especificada.
En cuanto a los equipos con los que se relaciona,
el Ingeniero con mención en Sistemas Digitales puede:

 Configurarlos,  Verificar la  Hacer análisis post


 Componerlos, disponibilidad y demás mortem,
consideraciones de Mantenimiento
 Diseñarlos, 
diseño preventivo,
 Normalizarlos,
 rendimiento,  Mantenimiento
 Investigar sobre ellos,
 escalabilidad, correctivo;
 Hacerlos evolucionar,
 extremos  Manejar proveedores;
 Operarlos, ambientales;  Calibrar y Aferir equipos
 Planear,  Transportarlos, e instrumentos;
 Programarlos,  Almacenarlos;  Demostrar y validar el
 Mantenerlos,  Administrar el grupo de cumplimiento de
 Adaptarlos, Ingenieros y demás normas;
 Producirlos, personal técnico,  Hacer Consultorías;
 Interconectarlos,  Dar entrenamiento tanto  Calibrar tiempos,
 Repararlos, "in house" como  Costos y recursos de los
externamente, proyectos;
 Documentarlos e
 Debe elaborar planes  Llevar una Gerencia
 Instalarlos; para el diseño de técnica y
 Debe generar protocolos hardware y software;
para pruebas en fábrica y  Aprovechar el Internet
 Circuitos impresos; para la interconexión de
en sitio;
 Evaluar mejoras al subsistemas.
producto;

P-9
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Quedan muchos aspectos por tocar, como la Venta Técnica, y el contacto con otras disciplinas como la
electrónica, de la cual se nutre; la electromedicina, la instrumentación, el control industrial, las
telecomunicaciones, la computación, y todas aquellas áreas a las cuales la especialización en Digitales les
sirve de pilar y sustento.

Lo más deseable sería que, para lograr un título de Ingeniero con especialización en esta área, se
cubriera la mayor cantidad de los elementos expuestos en este perfil. En todo caso, los primeros años
de trabajo deben servir para complementar las deficiencias que pueda manifestar el profesional.

Observaciones sobre algunos términos empleados


Siendo el inglés la lingua mater de la investigación electrónica, resulta en ocasiones difícil elaborar en esa
materia un texto en castellano que no incurra en anglicismos, y aquellos que lo hacen pueden terminar
en un galimatías. Recuerdo algún impreso que traducía “Master Clear” como Limpieza Maestra, o
“buffer” como Memorias Tampón, y “flip-flops” por básculas.

Incluyo algunas definiciones tomadas del diccionario de la Real Academia Española en línea, para
ayudar a explicar el uso que en este texto se les da:

hardware.
(Voz ingl.).
1. m. Inform. Conjunto de los componentes que integran la parte material de una
computadora.
software.
(Voz ingl.).
1. m. Inform. Conjunto de programas, instrucciones y reglas informáticas para ejecutar ciertas
tareas en una computadora.
técnico, ca.
5. f. Conjunto de procedimientos y recursos de que se sirve una ciencia o un arte.

Real Academia Española © Todos los derechos reservados

P-10
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

 PLAN DEL DOCUMENTO


Nuestra presentación se encuentra distribuida a lo largo de seis capítulos. En el primero se hace una
introducción histórica en la que se reseñan algunos de los accidentes más notables relacionados con la
Ingeniería Digital, resaltando las causas que los ocasionaron, y se describe un mecanismo perverso que
afecta nuestros propios modelos mentales. Disfruté enormemente el análisis del impecable documento
técnico: “Report by the Inquiry Board”, sobre las fallas del vuelo 501 del Ariane 5, y el estudio sobre el
accidente aeronáutico de Kegworth, que resalta el fenómeno que yo llamo: “Contra-evidencia”,
enemigo número uno del método científico, y yo espero que la lectura de todos los casos sirva para
abrir nuestras mentes y mantenernos alertas. En la revisión de 2010 agregué una semblanza de mi
trabajo de grado en 1969, el primer computador digital colombiano: el CoDiDac ; se incluyen un par de
fotografías.

El segundo capítulo enfoca el tema de los PROYECTOS, en general, motivando una metodología para la
planificación de proyectos de Ingeniería Digital, aspectos prácticos como el financiamiento de los
mismos, y unas interminables listas de detalles que es necesario no olvidar cuando se va a presentar un
proyecto. La aproximación ha servido como guía en mis cursos de Laboratorio de Proyectos II y III; el
notable detalle de mi presentación surgió como respuesta a un grupo de estudiantes que, al ser
conminados a discriminar las distintas etapas y facetas de un diseño, no llegaron ni a seis. Cuando los
forcé a imaginarse al menos cien ítems dijeron que eso era imposible, y el grupo que hizo el mayor
esfuerzo no pasó de 25. Por eso me senté y lo desglosé en cien (100) pasos, advirtiéndoles que
proyectos serios pueden tener centenares y hasta miles de actividades. El propósito fundamental es
establecer una metodología que permita, entre otras cosas, dar a conocer el nivel de progreso al que se
ha llegado en el desarrollo, lo que es fundamental para establecer pautas de corrección, tanto en tiempos
como en el uso del dinero y demás recursos involucrados. Si un proyecto no se ve como un proceso
realimentado, resultará una casualidad si se llega a cumplir con algunos de los objetivos: Tiempo de
entrega, funcionalidades desarrolladas, costos presupuestados, calidad del sistema desarrollado. En la
revisión de 2010 añadí dos Opiniones Empresariales, una para enfatizar la importancia del empeño y la
dedicación por encima de la genialidad, y mi visión de cómo una decisión estratégica-tecnológica tomó
desde los años 80 las compañías en que trabajé, propias y ajenas, y las catapultó hasta finales del siglo.

El tercer capítulo hace una introducción a los circuitos digitales, presentando sus características más
resaltantes, en el entendido de que muchos de nuestros estudiantes ni siquiera saben el por qué del
nombre de los circuitos analógicos, ni diferencian muy bien entre conceptos básicos como resolución,
precisión y exactitud. Asimismo, hay un apartado denominado Laboratorio Cero, en el que se señalan
aspectos elementales que considerar para la elaboración de prácticas y proyectos de circuitos digitales, el
uso del protoboard, condensadores de desacople, planos de tierra y similares. Sería un avance notable si
lográramos que nuestros estudiantes se hicieran su propia Lista de Verificación, o Check-List, como las
que son de obligatorio cumplimiento en profesiones tales como las de Piloto Aeronáutico o Marítimo,
en las que no se puede dejar a la memoria la verificación y constatación de las condiciones de los
equipos y el seguimiento de los procedimientos requeridos para la seguridad de sus misiones. Incluí en
la revisión de 2010 una aproximación novedosa a los sistemas numéricos.

P-11
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

El cuarto capítulo trata de provocar al lector con aspectos modernos, a veces no muy bien entendidos,
de la programación, como la aplicación de reglas, “static asserts”, representación apropiada de Máquinas
de Estado, filtraje en entradas digitales (eliminadores de rebote; secuenciadores de eventos), sistemas de
verificación para entrada manual de información, vía teclado, y diferenciación entre políticas y
mecanismos en la concepción moderna de la programación. Agregué un concepto novedoso, los
“Transversal Counters”, que permiten optimizar la realización de contadores cuando éstos cubren
rangos muy pequeños (de cuatro pasos, por ejemplo), los cuales desperdiciarían memoria si se los
implementara empleando un byte para cada uno.

El quinto capítulo sirve como complemento a los cursos de programación de microcontroladores, con
una serie de ejercicios propuestos y algunos resueltos, como el Juego de la Vida, para la familia PIC
16Fxxx, y otros para el Freescale (antes Motorola) HC08. A la actualización de 2010 le agregué una
metodología para realizar comparaciones entre números con signo, para máquinas que carecen del
soporte necesario (PIC), como lo es el bit de overflow. Este tema es tan poco comprendido, que
Andrew Tanenbaum, en su libro sobre Arquitectura del Computador, diseña su MIC-1, incluyendo un
error de concepto en cuanto a las comparaciones entre números con signo, hechas sin el soporte de
hardware adecuado, o sin aplicar técnicas como las que yo ofrezco. Anexé también, un artículo que
EDN me publicó en febrero de 2010, donde propongo una sencilla FSM que garantiza la seguridad de
la información almacenada, cuando ésta se constituye como agregados de varios (muchos) bytes, ante
eventualidades como pérdida de la alimentación eléctrica en el dispositivo.

Finalmente, agregué un capítulo entero, el sexto, en el que expongo mi propuesta de lo que deberían
ser los cursos de Programación, Digitales, Arquitectura del Computador y Sistemas Operativos, en una
carrera concreta: la de Telecomunicaciones en la UCAB.

Se ha dejado de lado para una futura entrega, la presentación de algunos temas de la parte más
importante del estudio de los microcomputadores: La Entrada y Salida, como soporte a los cursos de
arquitectura, y que incluirían conceptos y detalles del manejo de Colas e Interrupciones, enmarcados
dentro del campo de las comunicaciones seriales en los PC y también referidos específicamente a los
microcontroladores PIC y Freescale, pero el tamaño actual del documento hace necesaria esta
limitación.

Es de esperar, por lo que aquí se prologa, que este documento sea de utilidad como referencia a los
interesados en simplificar sus vidas, que buena falta nos hace, y de complemento a la literatura cotidiana
en la materia.

El autor, que ha tenido la fortuna de haber transitado durante 41 años el camino del desarrollo
tecnológico, y ha recorriendo desde el relé y el tubo de vacío hasta el Pentium y el Internet, ofrece con
el mayor placer esta pequeña contribución.

Ing. Luis G. Uribe C.


Caracas, julio de 2008,
febrero, octubre de 2010

P-12
1
Capítulo

HISTORIA
“Quien no conoce la historia está condenado a repetirla”, Jorge Santayana.

 INTRODUCCIÓN

E
STAS pequeñas referencias históricas se incluyen aquí porque relatan acontecimientos de los
que hay que extraer importantes conclusiones para incorporarlas a nuestra actividad
profesional cotidiana. El método científico, sustento del impresionante desarrollo tecnológico
actual, es un procedimiento iterativo que se basa en corregir errores: “trial and error”; en general,
se observan los hecho pertinentes, se presenta una hipótesis que los explique; se predicen sucesos
futuros, que ocurrirían de ser ciertas nuestras suposiciones; se diseñan pruebas experimentales para
comprobar los vaticinios que, si se producen, le dan solidez al postulado y lo promueven,
categorizándolo como teoría o ley natural; en caso de encontrar desviaciones en los eventos predichos,
se rechaza o se modifica la anterior hipótesis, se genera una nueva y se repite el ciclo. Los
procedimientos y resultados de las pruebas deben ser públicos, al menos entre la comunidad científica,
para permitir la verificación de investigadores independientes.

En un lapso tan amplio es muy probable que ya se haya escrito todo lo que puede decirse como
introducción al tema. Sin embargo, es importantísimo y resulta siempre conveniente, poner en
Perspectiva la Ingeniería Digital para quienes van a estudiarla; tal es el propósito de la siguiente
presentación, escrita como ambientación hacia nuestros lectores y alumnos que se adentran en el
torbellino actual de las Técnicas Digitales.
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

¿CUÁL FUE EL PRIMER PROGRAMA QUE SE ENSAMBLÓ?


Se había logrado ya cierto avance desde los iniciales mastodontes (Eniac [Von Neumann], Mark I
[Harvard]); ya la programación no se hacía empleando “patch-cords”, sino que un código pequeño, el
“Bootstrap”, llevaba a memoria uno más completo (el Loader, Absolute or Relocating), que se
encargaba de leer de los programas, sus imágenes binarias de memoria, y almacenarlas en la
computadora (se seguía codificando en binario, pero desde Von Neumann ya no se hacía con cables...).

Grace Murray Hopper, mujer de gran inteligencia, Almirante de la armada norteamericana, fue pionera
entre las programadoras y la descubridora del primer “bug”, una polilla que quedó aprisionada en
medio de los contactos de un relé; ella hizo el primer “debugging” al extraer la mariposa con una pinza
de depilar, para pegarla en la bitácora de la computadora.

Grace analizó el procedimiento que se empleaba para codificar un problema, que consistía en escribir en
papel el programa: Símbolos que representaban instrucciones, y los que identificaban localidades de
memoria; luego, en forma manual se buscaban las equivalencias con los valores binarios que la máquina
entendía. La científica pensó básicamente en hacer un programa que automatizara ese proceso de
traducción. Ella hizo el código, en binario, para leer tarjetas perforadas con los símbolos y generar un
módulo objeto, en binario.

Cuando ya su ensamblador, escrito en binario, a mano, estaba funcionando, lo primero que hizo, muy
sagazmente, fue ejecutarlo para convertir las fuentes simbólicas de su propio código, ¡ a binario !, lo que
produjo una copia exacta del programa que estaba haciendo la traducción. Ahora, ya tenía cómo generar
automáticamente el binario del Ensamblador, a partir de las fuentes, así que las posteriores
modificaciones y agregados que le hizo a su programa las realizó en Simbólico (en Assembler, como
se llamaría luego), y con el ensamblador anterior obtuvo el siguiente y el siguiente, en una cadena que
aún no se detiene. Ya nunca más se escribió un programa en binario (excepto por necedad).

¡ En otras palabras, el primer programa que se “ensambló” fue el mismo ensamblador !

De ahí en adelante el procedimiento se ha repetido siempre: Uno de los objetivos de cada


compilador nuevo es procesarse a sí mismo. Interesante... Así, el primer C, por ejemplo, se
codificó en Assembler, y su trabajo inicial fue ese, a partir de las fuentes de C, escritas en C. De
esta manera, cuando hubo que corregirlo o agregarle características al lenguaje, la actividad ya no
se hizo en Assembler, sino en C. El compilador viejo de C crea la versión nueva, corregida y
aumentada. El Perl se compila en Perl...

C1-14
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

FALLA EN TOMÓGRAFOS AXIALES COMPUTARIZADOS EN CARACAS, 1980


En 1978 abandoné la comodidad de 15 años de vida universitaria y asumí la gerencia técnica de la
compañía que representaba, para Venezuela, a DEC (Digital Equipment Corporation), segunda
empresa de importancia en el mundo en materia de computadoras digitales, después de IBM. El gerente
técnico de uno de mis clientes, exalumno mío de la USB, con el que me relacionaba pues le
prestábamos servicio de mantenimiento a las computadoras de sus tomógrafos, me narró un percance
ocurrido a una paciente a la que le hicieron un estudio en una clínica caraqueña. Lo cuento tal como lo
recuerdo.

La unidad que hacía las radiaciones y recababa la información para estructurar el TAC estaba gobernada
en esa época por una minicomputadora PDP-11/34, que recibía instrucciones del técnico radiólogo a
través de un teclado similar al de los actuales PC. El operador introdujo los datos específicos para esa
exploración y un par de órdenes complementarias, y el tomógrafo comenzó su proceso de excitación y
lectura. En un momento el radiólogo vaciló y decidió detener el examen, para lo cual canceló la
secuencia oprimiendo la combinación de teclas “Control-C”, lo que era común en esa época pre-PC. El
software estaba escrito para “abortar” toda actividad ulterior y rearrancar si recibía la señal de
interrupción, por lo que se posicionó otra vez en su estado inicial pero sin desenergizar el irradiador; así, se
sometió a la paciente a dosis de radiación por encima de los niveles aceptables.

Varias cosas pueden aprenderse de aquí:


QUÉ HACER CUANDO SE INTERRUMPE UNA OPERACIÓN

Un secuenciador, de equipos que interactúan con procesos como el descrito (u otros


industriales; ejemplo, el control de una grúa en una factoría), no puede simplemente retornar a
la posición de recibir comandos si se lo instruye para terminar anticipadamente su actividad; hay
que garantizar que todos los elementos bajo su control queden en la posición inicial correcta, la
cual tiene que ser estudiada y establecida con absoluta precisión y escrupulosa meticulosidad
para cada uno de ellos.
QUÉ HACER EN CASOS DE REARRANQUE

Esta condición hay que extenderla a cualquier otra clase de posibles reinicio, por anomalías
internas o exteriores. Ejemplo de una falla interior sería cuando se produce un “overlfow” en
alguna operación, o una división por cero (esta última eventualidad hace que DOS y Windows
terminen [aborten] un proceso, con un mensaje en la pantalla; ese comportamiento no es
tolerable, como ya se explicó, y el programador tiene que tomar todas las previsiones que
garanticen que deja las unidades bajo su control, en ese estado inicial del que se habló). Ejemplo
de un error externo sería una falla de energía eléctrica; en tal caso, al rearrancar, el controlador
debe asegurarse de dejar todo de acuerdo al estado inicial. Si, por ejemplo, su sistema está
trasladando la grúa hacia un extremo de la fábrica, y una intermitencia en la electricidad
“resetea” su microcontrolador, su programa no puede simplemente quedarse esperando órdenes
del operador, porque el motor continuará trasladando su carga y ocasionará un accidente (como
tumbar la pared del extremo y destrozar la fábrica, dependiendo de la instalación. Cfr. switches de
fin de carrera en un capítulo posterior)

C1-15
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

En una situación bien diferente que aprovecho para comentar, aparecen los mismos inconvenientes.
Casi todo estudiante que tiene que resolver el problema de enviar de manera automatizada, desde su
dispositivo microcontrolador, un correo electrónico con información destinada a un servidor, plantea la
solución mediante esta secuencia de actividades:
Comenzar por el Final
» comandar al sistema (modem) para que tome Modelo Obvio pero
Equivocado es lo Correcto...
la línea (“levantar el auricular”); » aguardar el
tono de marcar; » digitar el número telefónico Dialer

del servidor; » verificar que se atienda la llamada;


» intercambiar la identificación y la clave de
acceso; » enviar el correo; » esperar la
Tomar la línea Tomar la línea

confirmación; » terminar la transacción (“colgar


el teléfono”)..., ¡ y está mal ! Tono de Tono de
Marcar? si Marcar? si
Ese es el mismo orden que seguía también el no no
“dialer” de Win95/98; yo lo usaba hacia 1995 y
esa era su secuencia. Sin embargo, a veces se Digitar Número Digitar Número

distinguía, por el sonido, que el modem


encontraba dificultades al realizar la
comunicación; siendo que a mi equipo le llevaba si
Atendió la
llamada?
si
Atendió la
llamada?

minutos enterarse, yo interrumpía a mano el no no

proceso mediante un punto sensible en la


pantalla, “Cancel”. Ahora, al tratar de repetir la Enviar
Identificación
Enviar
Identificación
llamada, el “dialer” comenzaba, inmutable, la y
Correo
y
Correo

misma cadencia: » levantar el auricular; » esperar


el tono de marcar... pero resulta que al cancelar COLGAR
la secuencia anterior, el driver simplemente salía COLGAR
de memoria, y dejaba el modem esperando el resto de Dialer
las acciones (que contestaran, etc.). Así, al COLGAR
reintentar tomar la línea, lo que mi PC
encontraba no era un tono de marcar, sino la
señal de ocupado... y ya no podía establecerse,
nunca más, ninguna llamada ¡ hasta
reiniciarar el PC .! En una versión, bastante posterior, Microsoft corrigió el problema haciendo que lo
primero que ejecuta su “dialer” cuando uno lo invoca es COLGAR EL TELÉFONO, que era
exactamente el último paso de la secuencia original. Por eso dijo Blaise Pascal, al terminar de fabricar su
calculadora mecánica, llena de engranajes:
“La última cosa que se aprende al armar algo, es qué colocar de primero”
Pasos similares deben darse, por ejemplo, en el controlador de la grúa industrial: Al encenderlo o
arrancarlo, hay que comandar los motores a fin de que se detengan. Para el tomógrafo, si el sistema
comenzara apagando el radiador (y detuviera el mecanismo que mueve la cama, o que hace girar el
cilindro, etc.) la paciente hubiera resultado ilesa a pesar de tan sensible falla de programación.
Suena como si un error corrigiera otro. ¡ Y a lo mejor ! La ley de Murphy sobre la Incertidumbre dice:

“Usted puede saber que algo ha fallado, solo cuando comete un número impar de equivocaciones”.

C1-16
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

LAS DESVIACIONES

Una observación recurrente a lo largo de esta obra es: Cuando a un programador se le da una
especificación, probablemente tenga perfectamente definida la serie normal de pasos de la
operación (como en la llamada telefónica). Y es casi seguro que esa secuencia estará probada (es
impensable que usted no verifique, al menos, ¡ lo que se le pidió !), así que su programa
funcionará... ¡ siempre que no haya desviaciones ! Allí, en las circunstancias excepcionales al
comportamiento normal, es donde el ingeniero debe lucirse: ¿Qué pasa si la llamada se
termina? ¿Y cuando el ISP no contesta?, ¿Si el microcontrolador se muere y la grúa se aproxima
a 30 km/h a la pared de la fábrica? Todas estas preguntas, y muchas más, tienen que encontrar
una acción apropiada en su diseño; ese es precisamente su trabajo.

LAS FALLAS DEL MARS CLIMATE ORBITER Y DEL MARS POLAR LANDER, 1999
Estas dos naves formaron parte del Mars Surveyor ’98 Program; ambas se destruyeron, en septiembre y
diciembre del 99, debido a un error de navegación ocasionado porque la famosísima compañía
Lockheed Martin, subcontratista de la NASA, usó en sus programas unidades imperiales (pound-
seconds [millas]) y el resto de los participantes empleó el sistema métrico decimal (newton-
seconds [kilómetros]). El Mars Climate Orbiter, en particular, tenía que entrar en órbita a 150 km por
encima de Marte, pero confundiendo millas con kilómetros a toda lo largo de su travesía, acumuló una
diferencia en el cálculo de la distancia que lo hizo comenzar a maniobrar cuando ya estaba muy cerca, a
solo 57 km. La atmósfera marciana lo quemó.

¿Cómo puede pasar un error tan grosero en instituciones tan avanzadas?

LA FALLA DEL COHETE EUROPEO ARIANE 5


“Las suposiciones son la madre de los grandes desaciertos” Refranero popular.

Esta descripción se basa en el “Report by the Inquiry Board” sobre las fallas del vuelo 501 del Ariane 5.
Todo ingeniero debería leer el documento original (cfr. bibliografía), reflexionar sobre él y extraer
profundas verdades; es espectacular por su enfoque metodológico, sus análisis y conclusiones; resulta
muy ilustrativo sobre lo que no debe hacerse, y nos ilumina acerca de por qué a veces se toman ciertas
decisiones absurdas.

La narración original tiene muchos términos que se repiten una y otra vez, pero eso resulta inevitable
por ser eminentemente técnica. Mis disculpas, pero que eso no opaque la importancia del artículo.

INTRODUCCIÓN

El 4 de junio de 1996 el vuelo de inauguración del cohete Ariane 5 terminó en desastre. 40 segundos
después de iniciarse la secuencia de despegue, a una altura de 3700 m, el transportador se salió de su
ruta, se fracturó y explotó. La secuencia inversa de sucesos fue la siguiente:

C1-17
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

CADENA INVERSA DE EVENTOS TÉCNICOS

 El cohete comenzó a desintegrarse a las H0+39 segundos debido a los grandes esfuerzos
aerodinámicos producidos por encontrarse en un ángulo de ataque de más de 20 grados, lo que
ocasionó la separación de los propulsores del cohete principal, activando la secuencia de
autodestrucción.

 El inconveniente con el ángulo de ataque se debió a la deflexión completa de los propulsores de


combustible sólido y del motor principal, Vulcano.

 Dichas deflexiones fueron ordenadas por el software del computador de abordo (“On-Board
Computer”, OBC), en base a los datos transmitidos por el sistema de referencia inercial (SRI 2). Parte
de esa información no correspondía a lecturas apropiadas, sino a secuencias de diagnóstico del
computador del SRI 2, que fueron interpretadas como información de vuelo...

 La razón por la que el SRI 2 activo no envió información correcta de altitud fue porque esa unidad
había declarado una falla debido a una excepción de software.

 El OBC no pudo comunicarse con el computador de respaldo, SRI 1, porque esa unidad había
dejado de trabajar 72 milisegundos antes por la misma razón que SRI 2.

 La excepción interna del software SRI se originó durante una conversión de datos de un valor de
punto flotante de 64 bits a uno entero de 16, que resultó en Operand Error. Estas conversiones,
escritas en leguaje Ada, no estaban protegidas contra generación de Operand Errors, aunque las
demás, comparables y en el mismo lugar del código, sí lo estaban.

 El error ocurrió en una sección del software que solo realiza alineación inicial de la plataforma de
lanzamiento, y únicamente produce resultados significativos antes del despegue, después de lo cual
esta función no tiene ningún propósito ¡!

 La función de alineación se dejó operativa 50 segundos después de comenzar el modo de vuelo del
SRI, que ocurre a H0-3 segundos en el Ariane 5; por eso, cuando se realiza el despegue sigue
operando 40 segundos más. Ese requisito era del Ariane 4 y no se necesitaba para el 5.

 El Operand Error sucedió debido a que se obtuvo un valor inesperadamente alto de una función
interna de alineación llamada BH, Horizontal Bias, relacionada con la velocidad horizontal leída desde
la plataforma. Este valor se calcula como indicador de la precisión de la Alineación en el tiempo.

 El valor de BH fue mucho mayor a lo esperado porque la parte inicial de la trayectoria del Ariane 5
difiere de la del 4, lo que produce como resultado velocidades horizontales considerablemente más
altas.

Los eventos internos del SRI que condujeron a la falla se reprodujeron por medio de la simulación. Más
aún, ambos SRI se recuperaron y el contexto de la falla se determinó con precisión leyendo las

C1-18
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

memorias. Y al examinar el código fuente del software demostró consistencia con el escenario de la
falla.

COMENTARIOS SOBRE EL ESCENARIO DE LA FALLA

En resumidas cuentas, las principales causas técnicas que ocasionaron la falla fueron  el Operand
Error al cambiar la representación de la variable BH,  y la falta de protección en el mecanismo de
conversión, lo que ocasionó que los computadores SRI se detuvieran.

La razón por la cual esta conversión no tenía protección es porque no se esperaba una carga mayor al
80% en el computador SRI. Para determinar las vulnerabilidades del código desprotegido se analizó cada
una de las operaciones que podían generar una excepción, incluyendo el Operand Error. En particular,
se revisaron todas las conversiones de valores de punto flotante a enteros, encontrándose que ese riesgo
existía en 7 variables, de las cuales solo 4 se protegieron (lo que consiste en activar un mecanismo en el
lenguaje ADA). En la documentación directa del código fuente no se encontró ninguna justificación
para dejar esas tres variables desprotegidas...

La razón, en todo caso, fue que ellas estaban limitadas físicamente, o que había un gran margen de
seguridad, lo cual resultó ser una suposición falsa en el caso de la variable BH. La decisión de proteger
unas variables sí y otras no, fue tomada de manera conjunta por compañeros del proyecto situados en
varios niveles de la escala jerárquica contractual.

¡ No se emplearon datos reales de ninguna trayectoria para analizar el comportamiento de las variables
desprotegidas y, peor aún, se acordó no incluir la trayectoria del Ariane 5 entre los requisitos y
especificaciones del SRI !

Aunque se identificó la fuente del Operand Error, esto por sí mismo no causó la falla de la misión... La
especificación del mecanismo de atención y manejo de excepciones también contribuyó, puesto que allí
se indica que, ante la ocurrencia de cualquier clase de excepción, debería  indicarse la falla en el bus de
datos,  almacenarse el contexto de la falla en memoria EEPROM (que se recobró de los despojos del
Ariane 5 y se leyó) y, finalmente,  el SRI debería desactivarse (shut down).

Al final esta decisión de hacer que el procesador cesara de operar fue la que resultó fatal. El
rearranque no es factible porque la altitud es muy difícil de recalcular después de que se lo ha
desactivado; por tanto, el Sistema Inercial de Referencia se vuelve inútil. La razón detrás de esta acción
tan drástica (shut down) subyace en la cultura existente dentro del programa Ariane de solo atender
desperfectos del hardware que ocurran al azar; por tanto, el manejo de excepciones –o de errores–
está diseñado para ese tipo de fallas aleatorias, que bien podrían resolverse por un sistema
apropiado de respaldo.

Aunque la falla en realidad ocurrió por un error sistemático en el diseño del software, se habrían podido
introducir mecanismos que mitigaran esa clase de problemas. Por ejemplo, los computadores dentro de los
SRIs podrían haber continuado suministrando sus mejores estimados de la información de altitud que
se requería (Nota de Uribe: Muchos sistemas industriales y de control establecen esta clase de estimados
en aquellos valores que dejan de poderse leer o evaluar; se emplean técnicas matemáticas que lo
permiten, en base a la redundancia que existe en las diversas topologías. Por ejemplo, no es necesario

C1-19
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

medir los voltajes en todos los nodos de una red eléctrica, porque las leyes de Kirchhoff permiten
establecer muchos valores no medidos en base a las lecturas hechas en los demás puntos)

Hay razones para preocuparse de que a una excepción de software se le permita, o inclusive requiera,
provocar un paro en un procesador mientras está a cargo de equipo crítico para la misión. De hecho la
pérdida de una función del software es riesgosa porque el mismo programa corre en ambas unidades
SRI. En el caso del Ariane 501, esto ocasionó la desconexión de dos unidades de equipo críticas, que
aún estaban operativas.

El requisito original para continuar la operación del software de Alineación después del despegue se
estableció 10 años antes en los primeros modelos del Ariane, para permitir encarar un evento muy
improbable: Que se detuviera la cuenta regresiva entre -9 segundos, cuando comienza el modo de vuelo
en los SRI del Ariane 4, y -5 segundos cuando se inicializan en el equipo de despegue ciertos procesos,
que toman horas para detenerlos. Los 50 segundos seleccionados para esta operación de Alineación
continuada se basaron en el tiempo que le llevaría a los dispositivos de tierra reasumir el control
completo del equipo de despegue, en la eventualidad de un “hold”. Esta característica especial hizo
posible rearrancar la cuenta regresiva en las primeras versiones del Ariane sin esperar por el
alineamiento normal, que toma 45 minutos o más.

Pero ese requisito no aplica al Ariane 5, cuya secuencia de preparación es diferente, y se mantuvo muy
probablemente por razones de sentido común, basadas presumiblemente en la opinión de que, a menos
que se demostrara lo contrario, no resultaba acertado hacer cambios en software que funcionaba
bien en el Ariane 4.

Aún en los casos en los que el requisito fuera válido, sigue siendo cuestionable que la función de
Alineación continúe operando después de despegar. La Alineación envuelve la aplicación de filtros
matemáticos complejos para hacer coincidir el eje x con el eje de gravedad, y localizar la dirección norte
de la tierra. La presunción de la Alineación previa al vuelo es que se conoce con exactitud la posición de
la plataforma y que ésta es fija. Por eso la función de Alineación se ve completamente destrozada
cuando se realiza durante el vuelo, pues las mediciones de los movimientos se interpretan como valores
fuera de posición (offsets) de los sensores y de otros coeficientes que caracterizan el comportamiento de
ellos.

Retornando al error de programación, hay que enfatizar que el software es una expresión de un diseño
altamente detallado y no falla en el mismo sentido en que lo hace un sistema mecánico. Más aún, el
software es flexible y expresivo, y fomenta la incorporación de requisitos de muy altas expectativas, que
a su vez inducen implementaciones complejas, muy difíciles de evaluar.

Un tema subyacente en el desarrollo del Ariane 5 es la polarización hacia mitigar las fallas aleatorias. El
suplidor de los SRI se limitó simplemente a seguir al pie de la letra las especificaciones que se le dieron,
que estipulaban que en el evento de cualquier excepción detectada debería detener el procesador. La que
ocurrió no se debió a eventos al azar, sino a un error de diseño. Se la detectó bien pero el manejo fue
equivocado, por el punto de vista asumido de que “el software debe considerarse correcto hasta
que se demuestre lo contrario”. Hay razones para creer también que esta visión es aceptada en otras
áreas del diseño del software del Ariane 5, cuando lo más acertado es la concepción opuesta, de que el

C1-20
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

software debe suponerse incorrecto hasta que, aplicando los mejores métodos prácticos aceptados
en la actualidad, pueda demostrarse que es correcto.

Esto significa que el software crítico, en el sentido de que si falla pone en riesgo la
misión, tiene que estar identificado a un nivel muy detallado, que el comportamiento
excepcional debe quedar confinado, y que una política de respaldo razonable también
necesita tomar en consideración las fallas de software.

LOS PROCEDIMIENTOS DE PRUEBA Y CALIFICACIÓN

La calificación del Sistema de Control de Vuelo para el Ariane 5 sigue un procedimiento estándar y se
realiza en los siguientes niveles:

 Calificación del Equipo

 Calificación del Software (On Board Computer Software)

 Etapa de Integración

 Tests para la Validación del Sistema

La lógica aplicada consiste en verificar en cada nivel lo que no pudo realizarse en el anterior; así se
obtiene, eventualmente, cobertura completa de las pruebas de cada subsistema y del sistema integrado.

En el caso del SRI se condujo la prueba a nivel de equipo de manera rigurosa con relación a todos los
factores ambientales y, en realidad, más allá de lo que se esperaba para el Ariane 5. Sin embargo, no se
realizó ninguna prueba para verificar que el SRI se comportaría correctamente al ser sujeto a la cuenta
regresiva, a la secuencia de vuelo y a la trayectoria del Ariane 5.

Hay que notar que por razones físicas no es posible probar el SRI como una “caja negra” en el
ambiente de vuelo, a menos que uno haga pruebas completamente realistas, pero sí es posible hacerlas
en tierra inyectando señales simuladas de los acelerómetros, de acuerdo a los parámetros de vuelo
predichos, empleando mesas giratorias para simular los movimientos angulares del equipo. Si el suplidor
hubiera hecho estas verificaciones de manera independiente, o como parte de la prueba de aceptación,
se hubiera descubierto el mecanismo de falla.

La explicación principal para la ausencia de tan vital prueba es, como ya se mencionó, que la
especificación del SRI no incluye la trayectoria del Ariane 5 como un requisito funcional.

El comité de evaluación también notó que la especificación del sistema del SRI no indica restricciones
operacionales que emerjan de la implementación escogida. Tal declaración de limitaciones, que debería
ser mandatoria para cada dispositivo crítico para la misión, habría servido para identificar cualquier
incumplimiento con la trayectoria del Ariane 5.

C1-21
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

La otra oportunidad que se tuvo de detectar el mecanismo de falla con anticipación, fue durante las
numerosas pruebas y simulaciones que se efectuaron en las Instalaciones para la Simulación Funcional,
ISF, que está al lado del Arquitecto Industrial. El alcance de las pruebas del ISF califica:

 El comportamiento del guía, la navegación y el control dentro del contexto completo del vuelo,

 La operación redundante de los sensores,

 Las funciones dedicadas de las etapas,

 El cumplimiento del software de vuelo (On Board Computer) con todo el equipamiento del Sistema
Eléctrico del Control de Vuelo

Se corrieron muchas simulaciones a lazo cerrado del vuelo completo, incluyendo la operación del
segmento de tierra, flujo de la telemetría y la dinámica del lanzamiento para verificar:

 La trayectoria nominal

 Las degradaciones de la trayectoria con respecto a los parámetros internos del sistema de lanzamiento

 ... y en relación a los parámetros atmosféricos

 Fallas en los equipos, los consecuentes aislamientos, y su recuperación

Durante esas pruebas muchos dispositivos estaban presentes físicamente y se ejercitaron, pero no los
dos SRI, que se simularon mediante módulos de software especialmente desarrollados. Algunas pruebas
de lazo abierto, para verificar el cumplimiento del On Board Computer y el SRI se ejecutaron con los
SRI reales. Pero solo pruebas de integración a nivel eléctrico, y de cumplimiento a bajo nivel
(comunicación entre buses).

No es mandatorio, aunque sí preferible, que todas las partes de un subsistema estén presentes en todas
las pruebas en algún cierto nivel. Algunas veces esto no es físicamente factible, o resulta imposible
ejercitarlos completamente, o de alguna manera que sea representativa. En esos casos resulta lógico
reemplazarlos con simuladores, pero solo después de una revisión minuciosa para garantizar que las
pruebas previas han cubierto el escenario completo.

Este procedimiento es especialmente importante para la prueba final del sistema, antes de que pueda
usárselo de forma operativa. Para poder entender la explicación dada para no incluir los SRIs en la
simulación a lazo cerrado hay que describir la configuración de las pruebas que han debido realizarse.

Como resulta imposible simular las grandes aceleraciones lineales que se producen en el despegue, en
los tres ejes, en una mesa de pruebas, hay dos maneras de colocar el SRI en el lazo:

A. Colocarlo en una mesa dinámica de 3 ejes (para estimular el Anillo de Láser Giroscópicos) y sustituir
la salida análoga de los acelerómetros (que no pueden estimularse en forma mecánica) por

C1-22
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

simulación, mediante un conector de prueba, dedicado, y una tarjeta electrónica diseñada para este
propósito.

B. Sustituir tanto la salida analógica de los acelerómetros como el Anillo de Láser Giroscópicos
mediante un conector de prueba, dedicado, con señales producidas vía simulación.

La primera aproximación puede suministrar una simulación exacta, y es bastante costosa; la segunda es
más barata y su comportamiento depende esencialmente de la exactitud de la simulación. En ambos
casos se prueba gran parte de la electrónica y el software completo, en ambientes reales de operación.

Cuando se definió la filosofía de prueba para el proyecto, se reconoció la importancia de tener los SRIs
en el anillo, y se seleccionó el método B de arriba. Pero con posterioridad se cambió de opinión y se
decidió no tener los SRIs concretos en el lazo, por los siguientes motivos:

 Los SRIs pueden considerarse completamente calificados, al nivel de Calificación del Equipo

 La precisión del software de navegación en el On Board Computer depende de manera crítica de la


precisión de las medidas del SRI. En las Instalaciones para la Simulación Funcional, ISF, no puede
obtenerse tal precisión creando las señales de prueba por medios electrónicos.

 Es imposible simular los modos de falla con equipo real, y solo puede hacerse con modelos.

 El período base del SRI es de 1 milisegundo en tanto que el del simulador ISF es de 6 milisegundos,
lo cual complica la electrónica de las interfaces y puede reducir más aún la precisión de la simulación.

La opinión del comité de evaluación es que estos argumentos son válidos técnicamente, pero como el
propósito de las pruebas del sistema simulado no es únicamente verificar las interfaces, sino el sistema
como un todo para una aplicación particular, había en definitiva un riesgo al suponer que equipo tan
crítico como los SRI habrían sido validados mediante la Calificación del Equipo solamente, o por su uso
previo en el Ariane 4.

A pesar de que es deseable una alta precisión en la simulación, en las pruebas de sistema del ISF, resulta
claramente mejor un compromiso en la precisión, pero conseguir todos los demás objetivos, entre
ellos el de probar la acertada integración en el sistema de equipos tales como el SRI. La precisión del
sistema de navegación y guía puede demostrarse efectivamente mediante análisis y simulación
por computadora.

Finalmente hay que hacer notar que el método definitivo de prevenir fallas son las revisiones, que
forman parte integral del diseño y del proceso de calificación, y que se ejecutan a todos los niveles y
envuelven a la mayoría de los involucrados en el proyecto, así como a los expertos externos. En un
programa de esta naturaleza, se arreglan literalmente miles de problemas y de fallas potenciales,
de una manera exitosa, en el proceso de revisión, y es obvio que resulta difícil detectar errores de
diseño de software del tipo que fue la causa técnica principal de la falla del 501. Sin embargo, también
resulta evidente que las limitaciones del software del SRI no se analizaron en toda su extensión
mediante revisiones, y que ni siquiera se cayó en cuenta de que la cobertura de las pruebas

C1-23
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

realizadas fue inadecuada para exponer dichas limitaciones. Ni se pensó por un momento en
las posibles implicaciones de permitir que el software de Alineación operara durante el vuelo.

En este sentido, el proceso de revisión y prueba fue un factor importante que contribuyó a la falla.

CONCLUSIONES

a. No hubo eventos relacionados con la falla, surgidos durante la preparación del vuelo y la cuenta
regresiva.
b. Las condiciones meteorológicas en el momento del lanzamiento eran aceptables y no jugaron parte
en la falla. Tampoco se encontraron otros factores externos que fueran de relevancia.
c. El encendido de los motores y el despegue fueron nominales en esencia, y algunos efectos
ambientales (ruido y vibración) no resultaron de relevancia alguna para la falla. Se encontró que el
comportamiento de los propulsores estuvo dentro de las especificaciones.
d. 36.7 segundos después de H0 (aproximadamente a los 30 segundos de despegar) el computador
dentro del Sistema Inercial de Referencia de Respaldo, que estaba trabajando en stand-by para el
control de trayectoria y altitud se volvió inoperativo. La causa fue una variable interna relacionada con
la velocidad horizontal, y que excedió un límite que existía en el software de este computador.
e. Aproximadamente 0.05 segundos después el Sistema Inercial de Referencia Activo, idéntico al de
respaldo en hardware y software, falló por la misma razón. Como el sistema de respaldo ya estaba
inoperativo, no pudo obtenerse información correcta del sistema de control de trayectoria y altitud, y
la pérdida de la misión fue inevitable.
f. Como resultado de esta falla, el sistema activo de referencia inercial transmitió, esencialmente,
información de diagnóstico al computador principal de la misión, que la interpretó como
información de vuelo y donde se usó para realizar cálculos para el control de vuelo.
g. En base a dichos cálculos el computador principal comandó los motores para hacer grandes
correcciones, para unas desviaciones de altitud que en realidad no habían ocurrido...
h. Debido a fuerzas aerodinámicas ocurrió un cambio rápido de altitud que hizo que el cohete se
desintegrara a los 39 segundos después de H0.
i. El mecanismo de autodestrucción se inició automáticamente después de la desintegración, como está
diseñado, a una altitud de 4 Km. y una distancia de 1 Km. de la plataforma de lanzamiento.
j. La chatarra se regó en un área de 5 x 2.5 km2. Entre los equipos recuperados se encuentran los dos
sistemas de referencia inercial, que se usaron para el análisis.
k. El sistema de referencia inercial del Ariane 5 es en esencia común al sistema que vuela en la actualidad
en el Ariane 4. La parte del software que causó la interrupción en la operación de los computadores
del sistema inercial se usa antes del lanzamiento para alinear los sistemas de referencia inercial y, en el
Ariane 4, también para habilitar cualquier rápido realineamiento en caso de una suspensión tardía en
la cuenta regresiva. Esta función de re-Alineación, que no sirve ningún propósito en el Ariane 5, se
retuvo de todas maneras por razones de comodidad, y se permitió extender su operación, 40
segundos más allá del lanzamiento.

C1-24
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

l. Durante el diseño del software del sistema de referencia inercial usado en el Ariane 4 y el 5, se tomó
la decisión de no proteger el computador del sistema inercial contra valores excesivos relacionados
con la velocidad horizontal, protección que sí se suministró a otras secciones del software de
Alineación. Al tomar esta decisión de diseño no se analizó ni se entendió por completo qué valores
podía asumir esta variable en particular, si se dejaba operar el software más allá del despegue.
m. En los vuelos del Ariane 4 que usaron el mismo tipo de sistema de referencia inercial, nunca hubo
tales fallas, porque la trayectoria durante los primeros 40 segundos de vuelo es tal que esa variable, en
particular, relacionada con la velocidad horizontal, no puede alcanzar, dentro de márgenes
operacionales adecuados, valores más allá de los límites presentes en el software.
n. El Ariane 5 tiene una aceleración inicial más alta y una trayectoria que consigue llevar la velocidad
horizontal a 5 veces más que la del Ariane 4. Esto hace que, dentro de los 40 segundos en
cuestión, el valor excesivo haga que los computadores del sistema inercial cesen de operar.
o. El propósito de los procesos de revisión, que involucran a los socios más grandes en el programa
Ariane 5 es validar decisiones de diseño y obtener calificaciones de vuelo. En este proceso, las
limitaciones del software de Alineación no se analizaron en profundidad y no se tomó conciencia de
las posibles implicaciones que tenía permitir que continuara operando durante el vuelo.
p. La especificación del sistema inercial de referencia y las pruebas que se hicieron a nivel de equipo, no
incluyeron información sobre la trayectoria particular del Ariane 5. En consecuencia no se probó la
función de re-Alineación bajo condiciones de vuelo simuladas para el Ariane 5, y por tanto no se
descubrió el error de diseño.
q. Hubiera sido técnicamente posible incluir casi todo el sistema de referencia inercial íntegro en las
pruebas de simulación del sistema completo que se efectuaron. Pero por una serie de razones se
decidió usar la salida simulada del sistema de referencia inercial, en vez del sistema en sí mismo, o de
una simulación mucho más detallada. Si se hubiera incluido el sistema se habría detectado la falla.
r. Luego del vuelo se hicieron simulaciones en computadores, con el software del sistema de referencia
inercial y en un ambiente simulado, incluyendo la trayectoria actual del vuelo del Ariane 501, y se
reprodujo la cadena fatal de eventos que ocasionó la falla en el sistema de referencia inercial.

En resumen, la falla del Ariane 501 se debió a una pérdida completa de información de navegación y
altitud, 37 segundos después de la secuencia de encendido del motor principal, debida a errores en la
especificación y diseño del software del sistema de referencia inercial.

Las revisiones y pruebas extensivas que se realizaron durante el programa de desarrollo del Ariane 5 no
incluyeron análisis y verificaciones adecuados del sistema de referencia inercial ni del sistema de control
de vuelo completo, que hubieran detectado la falla potencial.

FALLAS EN NUESTROS MODELOS MENTALES


A veces lo más difícil de tener en cuenta no es ni el hardware ni el software: Somos nosotros mismos!

Hay un fenómeno psicológico que afecta profundamente la aplicabilidad de los modelos mentales
que nos hacemos automáticamente ante las diversas situaciones de la vida: Cuando dos eventos
consecutivos ocurren de acuerdo a las expectativas de un operador, esa situación tiende a reforzar

C1-25
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

la confianza depositada en el modelo mental que hemos elaborado de la particular situación; sin
embargo, dichos eventos pueden surgir en forma consecutiva por azar, debido a razones que en
realidad difieren de las que el operador les otorga. A pesar de ello, dada la consistencia entre los
datos del entorno y las expectativas del operador, éste llega a suponer que uno de los eventos es
causa del otro. Cuando esta falsa creencia ocurre, se asume de manera equivocada que el modelo
mental es válido y este error puede producir consecuencias desastrosas.
Así pues, los humanos tienden a considerar que su visión de la realidad es correcta cuando hay
eventos que acaecen de acuerdo a sus expectativas; sin embargo, como ya hemos dicho, muchas
veces dos eventos pueden darse en la secuencial esperada, sin que tengan por ello ninguna relación
de causa a efecto. Cuando este es el caso los humanos tienden a tratar la evidencia de que
disponen como si en realidad reflejara el mundo de manera exhaustiva, convencidos,
equivocadamente, de que han logrado entender a cabalidad el problema o fenómeno que les
concierne.
En procesos dinámicos puede ocurrir que al comienzo el modelo sea válido, pero con el tiempo, y
posiblemente con la degradación de una determinada situación (por un accidente o falla, por
ejemplo), el modelo resulte sobre simplificado, y por la urgencia, lleguemos a tomar en
consideración solo los mejores predictores de los estados del sistema, e ignoremos la información
periférica que no se ajusta. Desde el concepto de la “racionalidad acotada” de Simon (1957) se
acepta que preferimos soluciones económicas y adecuadas antes que soluciones perfectas pero
costosas. En otras palabras, la gente tiende a satisfacer, más que a optimizar, acogiéndose a una
solución que parece suficientemente buena, aún si ésta resulta sub-óptima.
El siguiente es un ejemplo, tomado de un episodio de la aeronáutica (el accidente de Kegworth;
1989) para ilustrar este tipo de inconveniente. La calamidad, con 47 víctimas mortales, fue
ocasionada por el manejo equivocado que se le dio a un incidente en el motor izquierdo (#1). Un
aspa se desprendió del motor, ocasionando vibraciones severas en el avión, y humo que se
introdujo por el sistema de aire acondicionado de la aeronave. Pero la tripulación creyó que el motor
dañado era el derecho (#2). En la grabadora de la cabina de mando se escucha indecisión; el
primer oficial le responde al capitán: “...es el izq..., ¡es el derecho!”..., lo apagaron... y esto resultó
en una disminución de la vibración del motor izquierdo, ¡el que en realidad estaba dañado! (¿?), y
hasta se terminó el humo.
En base a lo anterior, la tripulación dedujo que había hecho la decisión correcta y se comenzó un
aterrizaje de emergencia. En realidad el motor izquierdo continuó con un nivel anormal de
vibración durante algunos minutos, pero los pilotos no lo notaron... Como además le bajaron la
potencia a ese motor para comenzar el descenso, la vibración se redujo bastante, quedando solo
un poco por encima del valor normal. A los 10 minutos, al incrementar otra vez la potencia para
mantener la altitud durante la etapa final del descenso, otra vez aumentaron muchísimo las
vibraciones, el motor perdió potencia y se declaró una alarma de incendio en esa turbina. Con afán
comenzaron entonces a tratar de rearrancar el motor derecho, pero ya era tarde y no hubo tiempo
suficiente; el ahora inevitable impacto ocurrió a media milla náutica de la pista.
Otros factores también contribuyeron a este accidente, además de los errores ya planteados de la
tripulación. Ninguno de los pilotos reportó, cuando los entrevistaron, haber visto indicaciones de
las vibraciones en el Engine Instrument System (EIS). Es más, el capitán declaró que rara vez miraba
los indicadores de vibración porque según su propia experiencia en otros aviones, éstos no eran

C1-26
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

confiables (se les “pegaban” las agujas). Hay que notar que en este modelo de avión los indicadores
son digitales (numéricos), pero el 64% de los pilotos reportó en una encuesta que estos
indicadores modernos no eran tan efectivos como los viejos para llamar su atención ante cambios
rápidos en los motores, y el 74% dijo preferir los indicadores antiguos. Para colmo, estos
dispositivos no incluyen ni indicativos sonoros (“beeps”) ni medios visuales complementarios
(parpadeos) para alertar sobre lecturas excesivas...
Además, la carga de trabajo de la tripulación se incrementó fuera de control; el piloto trató de
mantenerse en fase con la evolución del incidente: Al apagar el motor #2 (el bueno) se oye en la
grabación que decía: “Ok; qué indicaciones en realidad tuvimos..., grandes vibraciones en el avión,
humo...”, pero al llegar a este punto las comunicaciones de radio los interrumpieron desde la torre
de control, la aeromoza entró para reportar que los pasajeros tenían pánico, lo cual distrajo más
aún al piloto quien tuvo que hacer un anuncio por el micrófono para calmarlos, y tanto el capitán
como el copiloto tuvieron que hacer más llamadas a la torre, en preparación al aterrizaje de
emergencia; todo esto afectó negativamente el grado de control de la situación.
Por último hay que anotar que a pesar de que tanto el capitán como el primer oficial eran
experimentados pilotos, con 13,000 y 3,200 horas de vuelo, respectivamente, entre ambos solo tenían
76 horas de experiencia en ese modelo de avión (Boeing 737-400).
Lo que ocurre con los modelos mentales en un mundo cambiante es que los involucrados,
tratando de ahorrar en recursos cognoscitivos, se polarizan de tal manera que llegan a aceptar con
facilidad, confirmaciones que son solo parciales, y en vez de darles un alto valor a las evidencias
contradictorias, las personas tienden a aceptar solo información consistente con lo
que esperan ; este fenómeno se conoce como polarización en la confirmación (Klayman & Ha,
1989). El corolario es que la gente no le presta atención a la información que contradice el
modelo; para colmo, en el caso del accidente narrado la decisión (equivocada) coincidió con la
reducción en el nivel de los síntomas por veinte minutos, lo cual hizo más difícil aún de integrar la
evidencia contraria disponible a continuación. Los operadores, en general, son más propensos a
rechazar cualquier información que no es consistente con sus expectativas, que a actualizar sus
modelos mentales, pues esto tiene costos en los que ellos no siempre pueden incurrir en
situaciones que se tornan críticas y muy exigentes en el uso del tiempo. Al final lo que sucede es
que los datos se reinterpretan abusivamente para ajustarlos al modelo que los operadores tienen de
la situación, siguiendo la línea del menor esfuerzo. Así, se les asigna significado a datos aleatorios,
que no lo tienen, si se ajustan a su visión del mundo para ese momento, con lo que
equivocadamente mantienen como válidas, representaciones que se alejan de la realidad.
En situaciones dinámicas una razón para ésto es que los operadores tratan de evitar el costo de
revisar sus modelos mentales, porque esos modelos son los que les dan la sensación de estar más
en control. Es decir, satisfacen. Y la urgencia del momento hace que se mantengan los modelos
mentales inclusive después de detectar contradicciones.
A este fenómeno yo lo llamo: “Contra-evidencia”, y no se limita a situaciones de emergencia; en
ocasiones tomamos decisiones en cierta dirección pero, al revisarlas en perspectiva, se nos hacen
patente hechos que desdeñamos, y que de haber sido tomados en cuenta nos habrían hecho girar
180 grados…
La “Contra-evidencia” es la enemiga número uno del método científico.

C1-27
 FALLA EN VUELO DE AIR CANADA
A principios de la década de los 80, uno de los nuevos Boing 737 de Air Canada se quedó súbitamente
sin combustible cuando volaba a 8000 Km de altura, a media distancia de su destino final. La tripulación
reaccionó con prontitud, se localizó una pista de aterrizaje cercana y el piloto aproximó el avión en una
maniobra difícil, haciendo gala de gran pericia porque se asegura que este avión no “planea”; es decir,
que requiere los motores para volar (una frase que escuché indicaba que “planea como un piano”).

Hubo varias peripecias anecdóticas porque, justo al divisar la pista pudieron observar que esta era
empleada para carreras locales de automovilismo y había varios vehículos ocupándola y compitiendo en
ese momento. El avión no anunció su llegada, porque volaba en absoluto silencio sin sus turbinas y no
tienen algo parecido a cornetas de carro para llamar la atención.

Algunos de los que hacían carne a la parrilla al costado, alcanzaron a darse cuenta y avisar a gritos a los
que entorpecían el aterrizaje, pero había dos niños en bicicleta que dieron un giro de 180 grados y
pedalearon casi hasta enloquecer, corriendo frente al avión que venía a más de 300 Km/hora.

El piloto recostó la nave contra una barrera de separación tratando de aumentar la eficiencia del
frenado, y el recalentamiento por fricción casi comenzó un incendio. Los ocupantes pudieron bajar,
entorpecidos un tanto por el hecho de que se había perdido el tren delantero y la nariz tocaba la pista y,
en esa posición, los toboganes asumieron una inclinación inapropiada.

Comenzada la investigación, luego de pasado el susto, salieron a flote varias torpezas que hicieron que la
gasolina se acabara en pleno vuelo, cuando apenas habían recorrido, como ya se dijo, la mitad de la
distancia proyectada. En primer lugar, se determinó que la empresa y la tripulación sabían que el avión
tenía averiado el sistema de indicación de combustible, por lo que los pilotos no tuvieron aviso de que la
gasolina se estaba agotando antes de tiempo. Pero, desde luego, si se hubiera cargado la cantidad
apropiada, esto no hubiera sucedido…

Indagando para averiguar por qué se había llenado el tanque solo hasta la mitad de la cantidad requerida
se dictaminó que para la fecha en Canadá se había adoptado el sistema métrico decimal (como en el
resto de Norteamérica) y que se estaban ajustando a él, acostumbrados a usar el sistema de medidas
Imperial, o sistema Británico de Unidades. Es de anotar que en el campo de la aviación, del combustible
no se habla indicando volumen sino peso. El personal de tierra que aprovisiona con gasolina al avión,
hace un cálculo basado en la distancia y convierte el volumen a kilos, y esa cantidad de kilos es la que se
le suministra. Pero, por falta de entrenamiento, el cálculo se hizo a libras. Como una libra es alrededor
de medio kilo, al llenar las 30,000 unidades solicitadas, en realidad solo cargaron 15,000 kilos, pues lo
que se consiguió fueron 30,000 libras. Ese error en las medidas, hechas en un sistema y no en el otro,
fue la causa del desastre del Mars Climate Orbiter y del Mars Polar Lander en 1999, ya reseñado.

Como el combustible es extremadamente pesado en relación a la carga, solo se le pone al avión una
cantidad justa, más una holgura que permita compensar vientos de frente imprevistos, que decrementan
la velocidad de la nave. Así que se puede decir que si se necesitaban para llegar, 30,000 kilos, 15,000 Kg
alcanzaban solo para llegar a la mitad del recorrido, que fue lo que en realidad ocurrió.
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

 EL CODIDAC, COMPUTADOR DIGITAL DIDÁCTICO.


LOS ORÍGENES
Finalizaba 1969, último año de mi carrera; la compañía norteamericana Texas Instruments había
donado a la Facultad de Electrónica una caja con más de 4.000 circuitos digitales integrados, TTL
en su mayoría. El decano de entonces, ingeniero Sandro Sandri –nuestro profesor de Técnicas
Digitales– pensó que sería interesante construir un "simulador" de un computador, con propósitos
didácticos, que sirviera para demostrar a los estudiantes el funcionamiento de tales dispositivos, y
así lo propuso como tema de Tesis. Hay que mencionar, a modo de ambientación histórica, que
por esos años los computadores eran escasísimos en Colombia, y en el área académica sólo dos
universidades los poseían; si mi memoria no me abandona, éstos eran el IBM 360/44 de la
Universidad de los Andes, en el que practicábamos el FORTRAN, y el IBM 650, antigualla de la
Universidad Nacional, que luego cambió por un 1401 en el que posteriormente aprendí PL/I,
programación lineal y cómo hacer compiladores.
EL ENTRENAMIENTO
El tema propuesto por la facultad tenía varios alicientes, siendo el patrocinio institucional uno
bien importante. Hacia noviembre del 69 nos habíamos inscrito ya en el proyecto las 12 personas
requeridas, y comenzó la etapa de diseño, que duró 6 meses. Nuestra aproximación original
consistió en que sería tan difícil simular un computador como realizarlo de verdad, por lo cual
decidimos olvidarnos del "simulador" y hacer uno real: el "Computador Digital Didáctico",
CODIDAC.

Un reto que encarábamos tenía que ver con el hecho de que los dispositivos electrónicos en los
que habíamos sido adiestrados durante los 5 años anteriores, eran primordialmente tubos o
válvulas de vacío, y el proyecto requería la aplicación de la tecnología de los circuitos integrados,
desconocida por nosotros, y que era dos niveles superior a la otra, pasando por encima de los
transistores. Además, tanto nuestros conocimientos en el área, como la bibliografía a la que
teníamos acceso, eran exiguos e insuficientes; libros clásicos como el de Iván Flores hacían
referencia a métodos y procedimientos empleados una década atrás, o más, y resultaban superados
y completamente inaplicables.

A buena hora logramos que la NCR en Medellín nos aceptara para darnos un entrenamiento
teórico-práctico en sus instalaciones; allí nos mostraron desinteresadamente lo que eran los
computadores NCR de esa época: por fin vimos uno de cerca, y hasta pudimos tocarlo por
primera vez.
LA ARQUITECTURA
Empezada, pues, la etapa de diseño, definimos en primer lugar la Arquitectura: El computador
tendría una consola de operador, que albergaría el teletipo o télex Olivetty, vieja reliquia italiana,
color verde militar, proveniente de la segunda guerra mundial, que se encontraba arrumada en el
laboratorio de Comunicaciones y que permitiría tanto suministrarle datos al computador, mediante
el teclado, como imprimir sus resultados en el clásico rollo de papel. La automatización para la
introducción de información en mayores volúmenes (bibliotecas de funciones, bases de datos) se
haría mediante el lector adjunto de cinta de papel perforada. Además, habría un tablero para el

C1-29
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

despliegue de la información interna más sobresaliente: registros, direcciones e instrucciones, y


una botonera para los interruptores de encendido y demás funciones que no fuera práctico realizar
desde el teletipo.
LAS INSTRUCCIONES
El conjunto de instrucciones que ejecutaría el computador fue diseñado cuidadosamente, e incluyó
comandos para lectura de datos, impresión, las cuatro operaciones aritméticas, toma de decisiones
y bifurcación en el flujo de control, desplazamientos de información a derecha e izquierda,
movimiento de datos entre diversas posiciones de memoria, borrado, espera y parada o
finalización. Un total de 14 instrucciones, todas codificadas en castellano. Nuestra aproximación
era, desde luego, que el CODIDAC pudiera realizar las operaciones que se programaban en el
FORTRAN de la época, que era, por cierto, FORTRAN a secas; no había aún ni FORTRAN II, o
FORTRAN IV, ¡sólo FORTRAN!

La belleza y el poderío de las instrucciones del CODIDAC, que lo diferencian de cualquier otro
computador, puede apreciarse en primer lugar, en la existencia de Clases de Información
definidas al nivel del lenguaje de máquina. Permítanme explicar esto un poco mejor. En los
computadores convencionales, tipo Von Neumann, la naturaleza de un elemento de información
no le es inherente; el significado se lo proporcionan las instrucciones que lo manipulan. Así, por
ejemplo, si sumo A con B, es la instrucción de suma la que les concede significación numérica a
las variables involucradas; pero si el programador hubiera almacenado un texto en esas posiciones
A y B, el computador no tendría forma de saberlo…

¡En nuestro caso no era así! Por ejemplo, la instrucción para desplazar información lo hacía de
una manera, si el operando contenía un número, y de otra muy diferente si representaba un texto.
En caso de números, el resultado siempre era un número; desplazar, digamos, un número
negativo, producía otro número negativo. En caso de textos, el resultado siempre era un texto.

¡Incluso las Instrucciones pertenecían a una Clase! lo que permitía realizar con ellas operaciones
aritméticas –sobre los campos numéricos correspondientes a las direcciones de los operandos– a
fin de facilitar la manipulación de subíndices, estructuras, etc.
LOS MODIFICADORES
Un segundo aspecto sobresaliente era la forma como un modificador cambiaba las operaciones, de
simples a repetitivas. Se podía así, con una sola instrucción de máquina (IM: IMprima), imprimir un
único valor… o también un rango completo de resultados (IR: Imprima Repetitivamente).

EL SUBSISTEMA DE ENTRADA Y SALIDA


He aquí otra faceta importantísima: El subsistema de Entrada y Salida formaba parte intrínseca de la
Arquitectura del procesador, con instrucciones específicas, más poderosas que el INPUT o
PRINT de ciertos lenguajes de alto nivel –como el Basic– y muy superiores al IN y al OUT de
simples registros, que figuran en los microprocesadores actuales. Solo arquitecturas muy complejas
incluyeron alguna vez instrucciones para el manejo de "canales" de entrada y salida.

C1-30
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Tamaña sorpresa me llevé cuando estudié el novedoso mini computador PDP-11, cuatro años después,
y ¡no encontré por ninguna parte las instrucciones de entrada y salida!

LOS CÓDIGOS DE OPERACIÓN


Como el aspecto didáctico era preeminente, los códigos de operación tuvieron una base
mnemónica de fácil comprensión y recordación. Cuando dos palabras designaban un comando, se
tomaba la primera letra de cada una para conformar dicho código, que era inteligible por la
máquina así, directamente, sin mediar ni compilación ni ensamblaje ni traducción entre los
símbolos y el módulo objeto. Era una máquina cuasi simbólica. Así por ejemplo, "Acepte
Información" se codificaba como "AI", y eran esas mismas letras, la 'A' y la 'I', en código baudot
de 5 bits, las que se almacenaban dentro de la memoria del CODIDAC como Código de
Instrucción.

Si el comando estaba designado por una sola voz imperativa, como "SUME", por ejemplo, el
código se conformaba con las dos (2) primeras letras: "SU".

Y si se requería el modificador de iteración para ejecutar repetidas veces una instrucción, se reemplazaba
la segunda letra por una R; por ejemplo: AR era Acepte información de manera Repetitiva (desde,
hasta), SR sumariaba un área completa de memoria, etc.

EL EDITOR
Para permitir la carga del programa desde el teletipo, el CODIDAC tenía, obviamente, un editor de texto
pero, compuesto por ¡CIRCUITOS! No era, como correspondía, un programa de software: ¡Estaba
hecho en hardware, con compuertas y flip-flops! Para invocarlo se encontraba el respectivo
interruptor en la consola, identificado como "Función Programa", y también el "Botón de Corrección"
para deshacer entuertos tipográficos.

EL FORMATO DE LOS NÚMEROS


La información numérica básica se representaba en NBCD (ahora conocido como BCD), empleando la
inusual alternativa de “signo y magnitud”, y era de "formato fijo": El número de cifras decimales se
preestablecía, mediante selectores en la consola, yendo desde ningún decimal para números enteros, hasta
"11" decimales. En cada "palabra", o posición elemental de memoria, cabían 12 dígitos BCD, en el caso
de números, o 16 letras si se trataba de textos. La unidad de salida imprimía la “Coma” de los números
en la posición decimal designada, y obviaba la escritura de ceros no significativos a la izquierda del
punto; es decir, que ¡el FORMAT estaba también incluido en la electrónica!

LA CALCULADORA
Sobrecogedora resultó, ante nuestra inexperiencia, la pregunta que alguien nos hiciera un día
cuando muy entusiasmados le mostrábamos el diseño funcional, por ahí a los 5 meses de
comenzado el proyecto. "¿Y cómo hago para sumar dos números?" Le explicamos que, desde
luego, se hacía un programa que se almacenaba primero en la memoria y que incluiría
instrucciones para leer los dos números, sumarlos, imprimirlos y detenerse. "¿Todo eso para

C1-31
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

sumar 2 más 2?" Lo que él esperaba era poder escribir "2 + 2" y obtener un resultado... ¡Quería
una calculadora!

Nos pusimos a pensar que, después de todo, haber diseñado tremendo equipo y no poder hacer ni
"2+2" resultaba realmente inexcusable, así que MODIFICAMOS EL DISEÑO para incorporarle
el selector de Operaciones Inmediatas, que convertía al CODIDAC en ¡CALCULADORA!
(¿CALDIDAC?)

Y así fue. Ningún otro computador del planeta tuvo tal característica... Como se ve, no teníamos muy
clara la diferencia entre las calculadoras transistorizadas (las había HP, de escritorio: nada de bolsillo; eso
vino años después) y los computadores; también desconocíamos el aporte real que el software hubiera
podido hacer al proyecto... ¡Lo que tendríamos que haber hecho era un Programa “Calculadora”!

LA ESTRUCTURA
La realización de la máquina fue del tipo serial, con lógica secuencial convencional, no
microprogramada. Era espectacular observar la entrada de la información en los registros
aritméticos, desplegados en la consola por medio de pequeñas luces de neón, rojas (¡no se habían
inventado los LEDs!). Primero entraba, por ejemplo, el multiplicando al Registro A, luego,
seleccionándolo mediante un conmutador de perilla, se veía el ingreso del multiplicador al Registro
B; después se veía cómo se generaba el producto, dígito a dígito sobre el Registro C y finalmente,
cómo salía el resultado por el otro extremo –información siempre serpenteante– para alojarse en
la memoria.

Teníamos selectores que permitían trabajar a máxima velocidad (¡600 Kilo Hertz!) o en lenta
animación para permitir el seguimiento del flujo de información con mayor claridad (¡habíamos
inventado el botón de "Turbo"!). Tenía, desde luego, un interruptor de paso a paso para seguir, pulso
a pulso, las secuencias internas; uno para detener la operación de un programa en cualquier
instante y otro para continuarla. Y no faltaba el Master Reset (que IBM eliminó con el
advenimiento del PS/2, porque sus máquinas dizque nunca jamás se congelarían... ¡mmm!)
DATOS ESTADÍSTICOS
Algunas cifras pueden ayudarnos a visualizar el tamaño del proyecto. Además de los 4.000 y pico
circuitos integrados se necesitaron 300 transistores, hicimos 200 tarjetas de circuito impreso;
pusimos 160.000 puntos de soldadura –cautín en ristre–, perforamos 155.000 agujeros con el
taladro de mano; hubo 16.000 cablecitos de alambre telefónico, con una longitud total superior a
los 2.500 metros, y se emplearon más de 5 kilos de soldadura de estaño.

Fueron diez las fuentes de alimentación, de 5 Voltios a 10 amperios cada una, amén de las fuentecitas
de voltajes elevados para manejar los neones, el teleimpresor, etc. Estaban todas alojadas en un gabinete
metálico independiente, y los dos disipadores principales tenían ¡la altura del gabinete! (como 1,70
metros). El consumo de nuestro “micro” estaba por encima de los 3 kilovatios y la generación de calor
hizo indispensable la colocación en el gabinete electrónico, de una pequeña turbina eléctrica para forzar
la circulación del aire, y de un poderoso ventilador alojado en la base del gabinete de alimentación.

C1-32
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

LAS PRUEBAS EN FRÍO


Terminado el diseño se generaron los diagramas eléctricos y de conexión para todos los
subsistemas, y en reuniones plenarias del grupo de trabajo se verificó en frío, a lápiz, pulso a
pulso de reloj, el comportamiento esperado del conglomerado, antes de proceder a la realización
de los circuitos impresos. No había programas de simulación tales como Spice...

Por cierto que en los primeros dibujos que hicimos para obtener de ellos los negativos fotográficos
necesarios para la confección de los circuitos impresos, empleamos "rapidógrafos" de tinta china, pero
luego vino la modernidad... y conseguimos en USA unas cintas adhesivas negras que se pegaban como
“pistas” en el papel, en vez de dibujarlas, y también unos “ojetes” o redondeles que iban en los sitios de
perforación, para permitir el paso de los terminales de los "chips" y otros componentes: ¡Diseño
ayudado por Calcomanías!

EL CONGRESO DE INGENIEROS JAVERIANOS


La culminación de la parte teórica del diseño coincidió con el Primer Congreso de Ingenieros de la
Universidad; el comité organizador, habiendo oído por allí de nuestro proyecto, tuvo la gentileza
de invitarnos a presentárselos en una de las sesiones de trabajo, a pesar de que nosotros no éramos
todavía ingenieros diplomados. Hicimos una preparación intensiva, llevamos un montón de hojas
para el viejo rota folios, de puño y letra de un arquitecto amigo que siempre nos criticaba
señalando que los ingenieros teníamos la manía de la simetría. Realmente él sabía su oficio, y el
material que nos elaboró (no había Power Point...) quedó bastante presentable.

Muy orondos atendimos a nuestra comparecencia ante el conglomerado de ingenieros, quienes


nos aplaudieron de manera por demás entusiasta. No cabíamos de orgullo hasta que,
intempestivamente, el nuevo decano de la Facultad, Hernando Correa, tomó la voz para
descalificarnos en público, diciendo que no había forma ni manera posibles de hacer un
computador en el país. Su voz resuena aún en mis oídos, 40 años después, y yo sé que también en
el de mis cada vez más atónitos compañeros: "Hay qué ver si funciona...", chilló ante la gran
audiencia. "Y es más, si no funciona, ustedes no se gradúan; ¡yo se los garantizo!".

Increíble, ¿verdad? ¿Podría la Academia habernos propuesto un tema de tesis inviable? ¿Y si el


proyecto sí era factible, cuál era el sentido de tamaño anatema? Hasta ese día, jamás se nos había
pasado por la cabeza, ni remotamente, que nuestro proyecto pudiera no funcionar… Lo cierto es
que el reto de Correa sirvió, más que ningún otro factor individual, como acicate para que
lleváramos a feliz culminación el proyecto.
EL PRIMER ENCENDIDO
Habiendo terminado de construir el artefacto, e interconectado que hubimos todos los
subsistemas en el garaje de nuestro compañero Francisco Viveros (¿recuerdan el nacimiento de Apple,
en un garaje, o el de la HP?), nos reunimos un día de octubre de 1970 –los 12 del patíbulo, como se nos
había sentenciado–, y hacia las 7 de la noche lo encendimos; le suministré las primeras instrucciones
desde la consola, sentado ante el teleimpresor: "Master Reset, Función Programa, Inicie"...

Nada. No ocurrió absolutamente nada… Nunca la desilusión ofreció tan palpable expresión...

C1-33
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Encontramos, días después, que en contra de todo lo esperado –dadas las pruebas estadísticas de
verificación de la calidad que habíamos realizado en un comienzo–, muchos de los circuitos
integrados estaban dañados. ¡Precisamente por no haber pasado el control de calidad era que
nos los habían regalado! Nos llevó dos meses más: desoldar, verificar, extender circuitos,
analizar y casi enloquecer, para que operara por fin el CODIDAC, como lo habíamos concebido.

Puedo decir que, de la inmensa cantidad de cables que conectamos, sólo cinco (5) de ellos estuvieron
mal ubicados, gracias al procedimiento de conexión y verificación inmediata que seguíamos, con dos
grupos de trabajo simultáneos: el que hacía el trabajo, y el otro que constataba inmediata e
independientemente que la actividad hubiera quedado hecho tal como se requería.

SUMMA CUM LAUDAE


Hubo nuevas directivas en la facultad, Rodrigo Mejía y José Gabriel Maldonado, y no tardaron
mucho en percatarse de la magnitud y la importancia de nuestro trabajo. Nos ofrecieron un salón
en las instalaciones de la facultad, para uso nuestro exclusivo, a fin de que abandonáramos el
garaje y finalizáramos el trabajo dentro del recinto universitario, de donde jamás debió salir; nos
condonaron una pequeña deuda, a manera de ayuda financiera para nuestros ya muy exiguos
presupuestos (o el de nuestros padres, quiero decir), y Alfonso Charum, nuestro valiente tutor de
la Universidad Nacional, quien sin conocer mucho del tema puso en juego su prestigio profesional
en el afán de ayudarnos, solicitó que se nos otorgara el título Summa cum Laudae, petición a la
cual la Universidad accedió.

Por mi parte, allí zanjamos diferencias la institución y yo.


LA PRESENTACIÓN EN SOCIEDAD
Habiéndolo visto extraoficialmente todo el claustro profesoral, concurrimos finalmente a la
presentación formal y “defensa” de la tesis, con todo el diseño, planos, circuitos, análisis,
aproximaciones, y hasta unos programas de demostración.

Para aceptar la publicación de la parte escrita era requisito presentar un borrador a máquina. Solo
la Unidad de Control, que yo mismo mecanografié en mi vieja máquina de escribir Rémington,
ocupó 1.000 páginas, con dos copias hechas usando papel carbón, una para el tutor y otra para nosotros.
Muy pocos pueden imaginarse el trabajo que eso significó. El libro, que fue editado en una
tipografía comercial, con todas las de la ley, y del que se imprimieron y repartieron 100 ejemplares,
contó con un total de 500 páginas. Aún tengo dos o tres ejemplares en mi biblioteca.

El primer programa que hice para la demostración era uno en el que el CODIDAC se presentaba a
sí mismo, escribiendo en el teleimpresor un texto que repetíamos en voz alta para la copiosa
audiencia; en un momento dado el CODIDAC simulaba que atendía al teléfono –ante el repique
previamente planificado del timbre del aparato–. El segundo programa lo escribí también para la
presentación, y consistía en un juego en el que ganaba quien, haciendo unas sumas, sucesivas y
alternativas de números del uno al diez, llegara primero al cien. Desde luego, ¡el CODIDAC
siempre ganaba! Fue interesantísimo porque varios profesores se sentaron a jugar un rato esa
noche ante el teletipo. Puede decirse que también fuimos pioneros en los juegos de computadores...

C1-34
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

EPÍLOGO
Mucho se queda en “el tintero” acerca de la vivencia de ese año y medio de intenso trabajo, auto
coordinado, muy disciplinado, de los 12 estudiantes participantes: Los viajes dentro del país, el de
un mes de María Helena a Nueva York a comprar los componentes que faltaban (acababan de
inventar el monostable SN74121, que resultó insustituible en nuestro diseño), el haber conseguido
cofinanciamiento de COLCIENCIAS para la edición del libro, y las ayudas recibidas de mucha,
muchísima gente, como el arquitecto Polo, diseñador del precioso mueble de agradables
tonalidades naranja y amarilla ("Big Orange...", para contraponerlo al “Big Blue” que representa
a IBM); de Aluminios Wonder que manufacturó y nos obsequió los racks; Induacero que regaló la
consola, y aquella inconmensurable cantidad de revisores, dibujantes, correctores de pruebas,
linotipistas, fanáticos y familiares, quienes nos dieron su soporte y nos brindaron su amistad para
regocijarse ampliamente con nosotros cuando alcanzamos la meta.

La ceremonia de grado fue de gran gala, exclusivamente para nuestro grupo de graduandos,
estrenando –casi– el nuevo teatro de la Universidad, y contó con la asistencia de tantos y tantos
seres queridos, ahora ausentes.

La prensa recogió la noticia: "Computador hecho en garaje", "Primer computador hecho en el


país". Aún conservo los artículos del Espectador de Bogotá y de algunos diarios de Medellín.

Uno de estos días Alejandro, mi hijo menor, viendo en televisión un documental sobre la historia
de la computación, en donde resaltaba el trabajo de Steve Jobs –el creador del Apple en un garaje–
me comentó: "¿Cómo es que Ustedes fueron tan parecidos en sus comienzos y el resultado fue tan
diferente?"

Realmente no lo sé. Me imagino que el garaje de Steve fue uno más orientado a los negocios, en
cambio que el nuestro lo fue más hacia lo académico. Yo estoy muy contento a pesar de todo, Steve. Sin
embargo, habría que reflexionar en cómo el entorno puede facultar o deprimir iniciativas del todo
similares, y rogar porque nuestro actual ambiente mejore de una vez por todas. Hay una enorme
potencialidad en este país, completamente derrotada en aras de la insanía social.

A mí el proyecto me sirvió para muchas otras cosas más: la Javeriana me ofreció mi primer
empleo, trabajo como profesor e investigador en el área de sistemas digitales; allí me ennovié con
Elízabeth, en unos cursos de actualización que este joven ingeniero dictó, muy orgulloso, a los
antiguos egresados, y por éstas mismas credenciales me contrató también la Universidad Simón
Bolívar en Venezuela. Y aquí estamos, 40 años después... Hicimos proyectos industriales de
avanzada, imbuidos con el orgullo de que nuestros productos fueron mejores que los de las
grandes corporaciones, y que hicimos un montón de cosas, ¡antes!

C1-35
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

FOTOS

Consola
Pueden apreciar el teleimpresor y su sistema adjunto de perforación y alimentación de cinta de
papel, y en el panel lateral, vertical, un ícono para cada uno de los 14 comandos, el indicador
de direcciones (Program Counter, arriba a la derecha, en “Nixies”), la botonera a la altura de la
mesa; el registro en que se desplegaba la información interna del procesador, y nuestra cara de
felicidad. La foto es del diario El Espectador de Bogotá, del viernes 19 de febrero del 71.

En la siguiente lámina, también de El Espectador, aparezco señalando el cableado en la parte trasera


del mueble del procesador. Lo que se ve corresponde a una cuarta (1/4) parte de ese mueble. Pueden
así darse una idea aproximada de la altura y del tamaño físico del CODIDAC..

C1-36
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

C1-37
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

 BIBLIOGRAFÍA
http://ei.cs.vt.edu/~history/50th/30.minute.show.html

http://en.wikipedia.org/wiki/Computer_bug

http://en.wikipedia.org/wiki/Mars_Climate_Orbiter (unidades métricas e inglesas)

ftp://ftp.hq.nasa.gov/pub/pao/reports/1999/MCO_report.pdf

http://en.wikipedia.org/wiki/Mars_Polar_Lander

http://americanhistory.si.edu/collections/object.cfm?key=35&objkey=30

http://en.wikipedia.org/wiki/Ariane_5_Flight_501

http://homepages.inf.ed.ac.uk/perdita/Book/ariane5rep.html

C1-38
2
Capítulo

PROYECTOS
"Perfection is finally attained, not when there is no longer anything to add, but when
there is no longer anything to take away..." (Antoine De Saint-Exupéry)

 PROYECTOS I, INTRODUCCIÓN

E
L tema de los proyectos no solo cubriría un libro entero, sino toda una especialización. Y la
Gerencia de Proyectos no es la parte menos importante, si se la compara en relación al aspecto
técnico intrínseco. Pero como no pienso rescribir lo que ya está impreso, quiero aportar solo
algunas ideas generales, extraídas de mi propia experiencia de 20 años de dirigir grupos de
ingenieros (1982-2002) en el desarrollo de diversos tipos de proyectos, desde la implantación de
sistemas foráneos y su adaptación al medio nacional (SCADAS, computadoras industriales), hasta el
desarrollo de tecnología vernácula en la rama de los sistemas de supervisión y control para la industria
eléctrica venezolana (RTUs, Registradores de Fallas, SCADAS); desde sistemas de télex y procesadores de
palabras, cuando el vocablo “PC” no había sido inventado, hasta sistemas en que Clientes
microcomputarizados se comunican con Servidores en Internet, para formar una red de supervisión de
la calidad de la energía.

 ASPECTOS GENERALES
PRODUCTO, MERCADO, ADMINISTRACIÓN
Aprendí que el aspecto técnico, el Producto, no era suficiente para establecer una empresa con
porvenir, que eran necesarios también el Mercado, y la Administración. En Mercado se agrupan las
ventas, la publicidad, las relaciones públicas, su investigación, y de la mayor importancia, la existencia de
necesidades genuinas que satisfacer y, por sobre todo, El Cliente. En Administración se engloban las
cobranzas, las finanzas, los recursos humanos y la detestable pero necesaria atención a la miríada de
obligaciones públicas, impuestos y regulaciones (en ese orden descendente de importancia).

La dirección de una compañía pequeña, más que una Gerencia General, precisa de una Gerencia
Técnica que maneje esos tres aspectos fundamentales: Producto, Mercado y Administración.

Vi a mi competencia caer, ostentando un buen producto, regular administración, y un manejo pésimo


del Mercado y de El Cliente. La vi venirse abajo con un cliente cautivo en el bolsillo, una
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

administración común y corriente, y un producto pésimo. Y yo mismo desaparecí, con productos de


grandes prestaciones técnicas, una pésima administración..., y un mercado que se desmoronó en 2002…
Por cierto, algo por lo que pagué muy caro por aprender es que no hay socio bueno.
Cuando un ingeniero encara sus primeros proyectos y quiere sopesar las facetas más importantes a las
que se enfrenta, encuentra un telón de fondo recurrente: “¿Debo pensar en grande, y lanzarme a las más
aventuradas empresas, o tengo que atender a los detalles?”.

Desde luego, ahora sé que ambos aspectos son importantes, y que el fracaso cuando se emprenden
proyectos ambiciosos puede buscarse en el descuido a los detalles, pero que también el ser minucioso
no conduce a nada si no se tiene una visión en grande, progresista, del negocio. También encontré que
es muy difícil que en una misma persona coincidan las cualidades necesarias para cubrir los dos aspectos
al mismo tiempo. Los soñadores suelen adorar la composición y menospreciar las pinceladas, y los
talladores pueden materializar un relicario de la nada e ignorar el equilibrio de formas, luces y colores.

THINK BIG... OR SMALL?


Pues no estamos solos en tan grotesca encrucijada. Les cuento en breve, lo que viví.

En 1978 asumí la Gerencia Técnica de la compañía que representaba a Digital Equipment


Corporation para Venezuela. DEC era entonces, con sus 15,000 empleados, el segundo suplidor de
computadoras en el mundo, después de IBM, que para la fecha tenía alrededor de 50,000 personas en
su nómina. Para que noten la diferencia entre las dos empresas, las ventas de DEC igualaban a lo que
IBM invertía en R&D: Investigación y Desarrollo. DEC había comenzado sus operaciones
produciendo módulos que realizaban diversas funciones, el equivalente de nuestros circuitos integrados
MSI actuales; había profundizado en una innovación de la tecnología que se ha mantenido como
disciplina hasta nuestros días: RTL, o Register Transfer Logic, los Algoritmic State Machines modernos. Su
principal logro en el campo de las computadoras, después de unos sistemas mas o menos grandes
(DecSystem-10 y DecSystem-20) fue la introducción de las primeras Minicomputadoras, siendo sus
estrellas la PDP-8 primero, la PDP-11 luego (del cual los micros modernos copiaron gran cantidad de
conceptos) y el sistema VAX-780 después.

Hacia 1980 algún directivo innovador en DEC decidió realizar un gigantesco salto hacia adelante en la
organización, tratando de aproximarse más a IBM... Como las grandes corporaciones norteamericanas,
DEC se encargaba de hacer fluir sus políticas por toda la organización (una especie de adoctrinamiento,
o lavado de cerebro); recuerdo que un día nos llegaron unos cuadros, enmarcados, destinados a ser
colocados en la pared, detrás del escritorio de los gerentes, con un letrero inmenso que decía:

Think Big
Cada división, área y unidad en DEC debía cambiar su cultura para implantar estrategias, programas y
planes que elevaran su “performance” (rendimiento) a toda costa y, fundamentalmente, sus ganancias
(profits). Fue así que decidieron no producir computadoras… completas, sino que cada local se
especializaría: Habría fábricas de discos, factorías de CPUs, manufactureras de impresoras,
ensambladoras de monitores...

C2-40
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

¡ Tampoco se integrarían los sistemas en la fábrica !, sino que se “unirían” en los muelles desde
donde se despachaban los camiones con la mercancía (On the deck merge).

Excelente..., muy bien. Pero recuerdo que una de las computadoras que me llegó en esos días tenía las
tarjetas enchufadas al revés. ¡ Mentira que ese equipo hubiera sido probado !

Siendo lo más importante despachar y facturar, empezaron a faltar pequeñas partes en cada caja
(¡ trampa !), como los cables de alimentación de monitores e impresoras. En USA eso no era mucho
problema: El técnico que estaba instalando la computadora simplemente llamaba a la fábrica por
teléfono, y vía “Overnight delivery” (Federal Express) recibía los faltantes al día siguiente a las 8 a.m. En
Venezuela... yo podía estar 45 y hasta 60 días esperando la importación de dichas piezas. Lo cierto es
que yo no podía cobrarle al disgustado cliente (centenares de miles de dólares), pues casi nunca
se conseguían en el país los cables y conectores (los de alimentación de los CPU, en particular, eran
bastante especiales de DEC; los de las impresoras tampoco los había localmente, y pare usted de
contar)

No se detuvo ahí la innovación del “Piense en Grande”…

Otro sector de Digital, el de la Documentación Técnica, no tuvo mejor idea para comenzar a hacer
ganancias inmediatas, que cobrar 15 veces más los manuales técnicos (antes se pagaban $10 por un
conjunto de planos, que de la noche a la mañana pasó a costar $150). Y el área de Entrenamiento, para
no quedarse atrás, elevó el precio de sus cursos. Ambos factores hicieron que mis propios costos de
servicio (como empresa independiente, representante local de DEC en Venezuela) subieran
astronómicamente, mientras que a IBM de Venezuela, mi aplastante competidor, le salía el
mantenimiento por una cifra nominal (transfer costs). Para nuestros clientes, el mantenimiento pasó a
ser prohibitivo. Nótese que adentro de DEC no importaba demasiado, ya que unas unidades le
facturaban a otras los servicios cuando un gerente quería entrenar un técnico (eso era sacar dinero de
un bolsillo para ponerlo en el otro). Igual daba un valor bajo que alto. Eso sí, creían ellos..., desde el
punto de vista de los “resultados”, cada unidad producía ahora 15 veces más, de un solo plumazo...
En nuestro país, en cambio, si una computadora no funcionaba, ¡ al cliente poco le importaba si era por
el CPU dañado (los nuestros nunca fallaban; los de IBM sí), o por que le faltaba un cable !

Para empeorar el panorama (los males nunca llegan solos), el sector de mercadeo de DEC, siempre
pensando en grande, decidió que si ofrecía infinidad de modelos de cada opción se abrirían más y más
mercados y oportunidades de venta. Pero ahora, yo (en Venezuela) sólo podía vender 2 ó 3 equipos de
cada modelo (unidades de disco, por ejemplo, o CPUs) antes de que fueran obsoletos y Digital sacara
unos más modernos (exactamente como ocurre en la actualidad con los Pentium y los PC). Como mi
contrato de representación me exigía tener un (1) kit de repuestos por cada 10 unidades (o fracción),
pues el costo de esas partes en lugar de promediarse entre 10 lo hacía entre 3! Y mis técnicos,
obligados a tomar cursos de entrenamiento en fábrica, para cada modelo (siempre según mi contrato),
pues se la pasaban en USA dizque estudiando la pléyade de opciones y modelos, en lugar de andar en el
mantenimiento e instalación de equipos en Venezuela, que era su función y vía única y real de ingresos
de la compañía venezolana.

C2-41
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

En año y medio, DEC estaba al borde de


la quiebra, gracias a su flamante:
“Think Big”

Llegó entonces otro director... que reaccionando según la dialéctica de Hegel, impulsó la
contrarreforma, y un día nos enviaron otros cuadros enmarcados... destinados a reemplazar a los
anteriores... con un letrero inmenso que decía:

Think Small

Se decretó ahora que lo fundamental eran el detalle y la minuciosidad...

DEC desapareció luego de unos 35 años de existencia.

IBM aún sobrevive, superando los 100 años

Resulta, pues, que lo importante es la armonía entre todos los factores involucrados. Esta es la
postura “Sistémica Holística” actual (grandes palabras...)

C2-42
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

 INTERROGANTES PARA UNA INVESTIGACIÓN


“El Pastelero”
Hay por lo menos 10 puntos importantes que siempre deben tenerse en cuenta y definirse para cada
faceta de un proyecto. He aquí mi nemotecnia para mi amigo Quique (Enrique):
“Qui(én)qué: ¡ He reñido a un pastelero ! Por_qué Cuándo Dónde Cómo,
Para_Qué hablan Acerca_de Cuánto, si no hay Con_qué?”
¿Qué? ¿Dónde? ¿Cuánto?
¿Quién? ¿Cómo? ¿Con qué?
¿Por qué? ¿Para qué?
¿Cuándo? ¿Acerca de?
¿Acerca de? Se refiere a los temas o contenidos en los cuáles se centrará el proyecto.
¿Para qué? Comprende los objetivos, o lo que se quiere lograr con el proyecto (a corto, mediano
y largo plazo). Constituye el punto de llegada del trabajo y los logros sucesivos a lo
largo del proceso.
¿Qué? Se refiere al tipo de actividad que va a realizarse. Se debe precisar exactamente lo que
va a hacerse, sin que quede lugar a dudas... Parece de Perogrullo, pero es muy
difícil.
¿Quién? (o quiénes), Asigna sin ambigüedades las diversas responsabilidades y actividades del
proyecto
¿Por qué? Es la justificación de cada actividad. Todo tiene un por qué, aunque no sea técnico
necesariamente. Ejemplo: realizar una obra porque así ahorran impuestos…
¿Cuándo? Constituye la programación en tiempo y en etapas; se fijan fechas y períodos
destinados a cada fase del proyecto (Duración). Debe especificarse cada paso, la
secuencia, la prioridad, y el momento en el que se realizará. No se crean que porque
han llenado unos cuantos campos en "MSProject" u otra herramienta similar, ya con
eso es suficiente. Hace falta CRITERIO. Uno de los puntos más notables en
donde falla un proyecto es en el Cuándo.
¿Dónde? Se refiere al alcance geográfico o ubicación espacial donde se llevará a cabo cada
actividad (diseño, programación, pruebas, instalación, etc.) ¿Obvio? Uno de mis
proyectos iba a realizarse en la planta Tacoa, Caracas. Y así se cotizó. Luego resultó
que, bueno..., Tacoa no está, en realidad, en Caracas. Había como hora y media de
trayecto (ida y regreso: Tres horas), con lo que hubo que alojar el personal en un hotel
de Catia La Mar, y se pagaron viáticos, residencia, alimentación, transporte, alquiler de
vehículos, etc., SIN que ésto pudiera cobrársele al cliente (las cotizaciones son a precio
fijo). Gastos extras se restan directamente del profit (las ganancias), y pueden llevar a
pérdida un proyecto.
¿Cómo? El cómo define los métodos, las técnicas; las tácticas y las estrategias que van a
utilizarse en las diversas etapas del proyecto, para alcanzar los objetivos. ¡ Es el
“know-how” por el que le pagan !

C2-43
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

¿Cuánto? Implica la elaboración del estudio de costos y el presupuesto del proyecto, así como
las alternativas de financiamiento. Debe incluir la determinación del factor
Costo/Beneficio del proyecto. Esta pregunta es vital para la sobrevivencia de una
compañía, y es su razón de ser. Y un cliente al que se le hace ver que no está
gastando, sino que va a ahorrar..., es un cliente dispuesto a comprar.
¿Con qué? Define los recursos o materiales necesarios para el desarrollo del proyecto.

 CÓMO SE PLANIFICA UN PROYECTO


Hay que repetir que este no es el tema completo de la planificación de proyectos; son solo guías que
intentan sobre todo motivar y orientar el trabajo en las asignaturas que tienen laboratorio y diseño en la
universidad.
ASPECTOS PREVIOS
Todo comienza (con el usuario) identificando una necesidad; se determinan sus requisitos: metas y
restricciones, y dependiendo del tamaño del problema, y de las normas internas de la empresa que hace
la solicitud, se generan unas Especificaciones, un Pliego de Licitación y se hace una Licitación; también
puede ser que se haga una Negociación Directa. Como resultado, el cliente tiene una Oferta; si fue una
licitación se hace la adjudicación al mejor oferente, de acuerdo a los parámetros de evaluación, que
suelen incluir aspectos económicos y técnicos.

Normalmente, después de la adjudicación, en donde hay por una parte un pliego de licitación, que
contiene entre otras cosas las Especificaciones (lo que el cliente quiere), y por otra la oferta del ganador
(lo que él propone), se pasa por una etapa de consolidación, en donde se genera un documento
conocido como Statement of Work (SOW; cfr. IEEE/EIA standard 12207, 1996), que es el que se
emplea para hacer el diseño definitivo, y para generar otros documentos, tales como la lista de
“deliverables” (qué cosas concretas se le van a entregar al cliente), documento de Factory Acceptance
Test (FAT, cómo van a ser las pruebas que se harán en la fábrica, antes de que el sistema se traslade al
lugar del cliente), Site Acceptance Test (SAT, qué pruebas se realizarán con los equipos ya instalados en
el campo) y otros documentos más, entre los que está el “COMMISIONING” (puesta en marcha del
sistema, en el sitio final).
Todo lo anterior se encuentra fuera de los objetivos de esta obra, por lo que continuamos con el primer
paso del diseño propiamente dicho.
DISEÑO CONCEPTUAL
Esta etapa es Fundamental; deben analizarse diferentes aproximaciones conceptuales al diseño del
proyecto. Esto incluye la evaluación al menos de los siguientes factores, que incluyen requisitos tanto
funcionales (operaciones) como las restricciones (normativas, peso, tamaño, color, costo, ambiente):
 cuáles partes deben realizarse en Hardware y cuáles en Software;
 consideraciones de tamaño (si debe caber en un espacio predeterminado),
 costo (cuáles son los límites),
 materiales que deben emplearse (tecnología de semiconductores; materiales especiales para la caja),
 sistemas de comunicación (email, FTP, RS-232 normal),

C2-44
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

 alternativas de interconexión (entre equipos; con las interfaces; con la maestra: Lazo de corriente,
fibra óptica),
 análisis de las dificultades de la instalación,
 tiempos de ejecución (cuáles son los parámetros; esto indicará la cantidad de recursos que habrá que
asignar), etc.

Como resultado de esta actividad, el Líder del Proyecto genera un Documento de Diseño
Conceptual. Es importante obtener la aceptación del cliente (a través de la Gerencia de Operaciones)
del documento de Diseño Conceptual, ya que éste es el momento más apropiado para debatir
cualquier discrepancia de parte del Cliente, antes de continuar con el proyecto.

El Diseño Conceptual tomará un tiempo muy corto, porque es muy probable que esta actividad ya se haya
adelantado con anterioridad en la empresa, durante la etapa de cotización e interacción con el cliente,
previa a la orden de compra.

CRONOGRAMA (TENTATIVO) DE TRABAJO


Terminada la etapa de Diseño Conceptual puede realizarse un Cronograma de Trabajo, indicando las
duraciones estimadas de las etapas siguientes del proyecto. Este cronograma SIEMPRE es tentativo, y
será evaluado semanalmente entre el Líder del Proyecto y la gerencia, a fin de determinar las posibles
desviaciones y tomar los correctivos necesarios. Las siguientes etapas pueden refinarlo y modificarlo…

ENMIENDAS AL CRONOGRAMA DE TRABAJO

Cualquier cambio en el cronograma deberá ser nuevamente aprobado por la gerencia como enmiendas
al cronograma original.

DISEÑO FUNCIONAL: HARDWARE Y SOFTWARE


DESCRIPCIÓN

Se descompone el proyecto, definido según el documento de Diseño Conceptual, en los diferentes


módulos de Hardware y de Software que realizarán FUNCIONES específicas. El documento de Diseño
Funcional deberá contener diagramas que muestren las interrelaciones entre las diferentes partes.

Terminada esta actividad se realizará una revisión del Cronograma de Trabajo, afinando algunos tiempos,
según pueda determinarse con la nueva óptica que se tiene al finalizar el Diseño Funcional, mediante
enmiendas al cronograma original.

ENMIENDAS AL DISEÑO FUNCIONAL

Discrepancias que surjan en el Diseño Funcional al realizar algunas de las etapas subsiguientes, deberán ser
reportadas inmediatamente a la gerencia a fin de tomar una decisión y recibir la aceptación de los
posibles desvíos. Esto se hará como enmiendas al Diseño Funcional.

También una modificación en el Diseño Conceptual puede generar (hacia abajo) una enmienda al Diseño
Funcional.

C2-45
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Los cambios al Diseño Funcional deben generar las enmiendas que correspondan en toda la cadena
subsecuente comenzando por el Diseño de Detalle, y al Diseño Conceptual, si fuera pertinente. Si cambian
algunas funciones de alto nivel (las que “ve” el usuario), de manera que impacten al cliente, es
imperativo obtener su aprobación explícita para evitar, al momento de la entrega, modificaciones en esta
instancia que impliquen: Recodificaciones, repeticiones de tarjetas, etc.

DISEÑO FUNCIONAL: HARDWARE


La parte del Diseño Funcional correspondiente al Hardware debe incluir la definición completa,
precisa, exacta, detallada; sin vaguedades (todo debe estar cuantificado) de todos y cada uno de los
siguientes puntos (los que correspondan):

 CPU (características de velocidad, longitud de palabra, familia, cantidad de CPU’s y función de cada
uno)
 Memorias (cantidad, tipo)
 Almacenamiento secundario (tipo, tamaño)
 Interfaces varias (seriales, paralelas: Cantidad, tipo)
 Módulos de conversión A/D (número de bits, velocidad, necesidad de filtraje, voltajes o corrientes
que van a manejarse, necesidades de Sample&Hold)
 Módulos de entrada digital (cantidad, definición de los niveles de tensión y corriente de entrada que
van a manejarse, filtrajes necesarios, aislamientos)
 Unidades acondicionadoras de analógicos (AIM)
 Unidades acondicionadoras de digitales (DIM)
 Unidades de interfaz con las señales analógicas provenientes del campo (AFI)
 Unidades de interfaz con las señales digitales provenientes del campo (DFI)
 Aisladores galvánicos para señales analógicas (ISOs)
 Optoaisladores para señales digitales
 Modems
 Otros optoacopladores
 Relés (capacidades de los contactos, tiempos de conmutación, “duty cycle”)
 Gabinetes (tamaño, norma NEMA, capacidad de entrada, salida y control)
 Previsiones de alambrado de señal, de control, de comunicaciones, etc.

Si hubiera restricciones que limiten la agrupación de unas funciones con otras, en una misma tarjeta o
“backplane”, deberán señalarse claramente aquí. Si pueden emplearse elementos suplidos por otros
(Fuentes, Modems, Computadoras, Tarjetas con Microprocesadores, etc.) o diseñados previamente en la compañía,
debe también indicarse a este nivel. Si es necesario modificar algunos elementos empleados por la
compañía anteriormente, deberán señalarse aquí las diferencias que deben introducirse.
El Líder de Proyecto producirá un Documento de Diseño Funcional del Hardware, con la
definición completa, precisa, exacta y detallada de todas las funciones necesarias para el proyecto,
ateniéndose siempre al Documento de Diseño Conceptual.
DISEÑO FUNCIONAL: SOFTWARE
El Diseño Funcional del Software incluirá la descripción de las diferentes prestaciones de alto nivel (las
funciones que “ve” el usuario): Protocolo de comunicaciones, cantidad de información que va a
transmitirse y su velocidad, categorización de las informaciones (analógicos rápidos, lentos; scan normal,

C2-46
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

scan de seguridad), capacidades de control, funciones de diagnóstico, interfaz con el usuario, interfaz de
mantenimiento, funciones de respaldo (en caso de que haya necesidad), funciones de cálculo específicas
(FFT, etc.), necesidades de multitarea, spooling, comunicación en back-ground, etc.
Deben incluirse diagramas de despliegues (si algo tiene que mostrarse en la pantalla, aquí hay que incluir
un diagrama, o foto, de dicha pantalla), editores, menús, reportes (si algo va a imprimirse, aquí tiene que
mostrar un facsímil). Obsérvese que los facsímiles se incluyen ANTES de haber generado ni una sola
línea de código para producirlos), etc. Deben identificarse los programas que van a ser modificados (en
caso de que ya la compañía haya hecho programas similares con anterioridad) o creados nuevos.
Funciones que no ve el usuario, pero que tienen que estar incluidas en la actual etapa son, por ejemplo,
las rutinas de autodiagnóstico. En este caso es bien importante definir qué acciones deberán tomarse en
caso de detectarse una falla: Reportes, señales, etc. Cada posible falla detectable deberá tener su
especificación correspondiente. (Como de costumbre, no tiene sentido incluir una rutina de diagnóstico
si no está claramente especificada qué acción inteligente y apropiada deberá adoptarse en caso de
detectar una falla. Normalmente ¡ apagar el equipo es lo menos indicado !)
Si hubiera funciones que han de operar en CPU’s diferentes (8031, HC08, etc.), hay que indicarlo. Si
pueden emplearse rutinas suplidas por otros (Spoolers de impresión, rutinas estándar de comunicación
[Xmodem], FFT, librerías “.VI”, de CRC, etc.) o codificadas previamente en la compañía, debe también
indicarse a este nivel. Si es necesario modificar algunos de los anteriores elementos deberán señalarse las
diferencias que se necesita introducirles.
Al evaluar ciertas funciones como impresión de reportes y adquisición de información, el Comité de
Diseño debe determinar claramente si van a realizarse como multitareas, en cuyo caso hay que definir las
prioridades, o si la adquisición de información va a realizarse en background, con garantía de que no se
pierda información, o si va a realizarse una actividad con exclusión de la otra, sopesándose lo
apropiado de esta decisión. Cuando se trata de una maestra, que no tiene necesidad de tiempo real para
la adquisición de la información, ya que el dispositivo que actúa en tiempo real es el que está en las
instalaciones, esta definición puede hacerse de una cierta manera; en cambio, si se trata de una unidad de
campo, debe tenerse muy presente que su actividad primordial es la de adquisición y almacenamiento de
información en tiempo real; las demás deben supeditársele.
Cambios fundamentales en el software estándar de la compañía (como por ejemplo en sus Rutinas de
Tiempo Real), deben seguir un proceso mucho más riguroso aún, debido a lo sensibles que resultan
pues son el núcleo de la gran mayoría de sus productos (es decir, si están funcionando, y probadas,
RESÍSTASE A MODIFICARLAS ni siquiera levemente).
El Líder de Proyecto producirá un documento de Diseño Funcional del Software, con la definición completa
de todas las funciones necesarias, ateniéndose siempre al documento de Diseño Conceptual.
DISEÑO DE DETALLE: HARDWARE Y SOFTWARE
Noten que hasta aquí:
NO HEMOS ESCRITO NI UNA LÍNEA DE CÓDIGO,
NI HEMOS ARMADO CIRCUITO ALGUNO...

C2-47
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Las mayores economías y mejores prestaciones en un equipo,


no se consiguen cuando se lo está programando, o se lo arma:

SE LOGRAN EN LA ETAPA DE DISEÑO


Allí es donde tiene que aplicar la creatividad y el ingenio, Ingeniero...

DESCRIPCIÓN

Esta etapa se basa en el documento de Diseño Funcional. Cualquier discrepancia que surja en el Diseño de
Detalle con aquél, deberá ser reportada inmediatamente al Comité de Diseño y a la gerencia a fin de tomar
una decisión y recibir la aprobación de la posible desviación. Esto se hará como enmiendas al
documento de Diseño Funcional, que hay que anexar, debidamente aprobadas por la gerencia, a su
correspondiente Carpeta de Trabajo.

Si el proyecto es de envergadura, habrá un Líder de Hardware y un Líder de Software, bajo la coordinación


del Gerente del Proyecto.

DISEÑO DE DETALLE DE HARDWARE


La actividad comienza generando un  Diseño de Implementación, que muestra en el Hardware las
relaciones entre las diversas tarjetas,  definición de interfaces entre ellas (cómo se van a conectar unas
con otras),  mostrando el funcionamiento mediante diagramas electrónicos. El Diseño de Implementación
será finalmente revisado para constatar que se cumplen todos los requisitos de las etapas anteriores;
como resultado se obtiene el  Diseño de Detalle de cada tarjeta, que permite producir la
descripción detallada (diseño electrónico) de cada una, que ya no admite cambios posteriores.

Como anexo A al documento de Diseño de Detalle de Hardware, se señalarán todas las pruebas que deben
realizarse para la verificación de la operabilidad de cada tarjeta. Las pruebas deben ser completas y
describirse en profundidad, de manera de permitir su empleo en otras etapas de la operación, tales
como: Control de calidad, pruebas de aceptación, etc. Debe incluirse la descripción de equipos de
prueba necesarios en esta etapa. Asimismo, deben anexarse los Programas de Prueba que permitan
constatar la operación de cada tarjeta, y que servirán posteriormente, en la etapa de producción.

Como anexo B deben incluirse todas las indicaciones de error (leds encendidos, etc.) que sean
producidos por cada tarjeta cuando se detecte una falla en ellas.

DISEÑO DE DETALLE DE SOFTWARE


La actividad comienza generando un  Diseño de Implementación de Software mostrando las
 relaciones entre las diversas rutinas,  definición de variables (locales y externas; nombres,
significados, uso),  indicando el lenguaje en que se hará el desarrollo,  mostrando un diagrama de
flujo o, en su defecto, un listado de pseudo código. El Diseño de Implementación será finalmente revisado
para constatar que se cumplen todos los requisitos exigidos. Como resultado se obtiene el  Diseño de
Detalle de cada Función, con la programación detallada de las rutinas, no sujeta a cambios
posteriores.

C2-48
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Como anexo A al documento de Diseño de Detalle de Software, se señalarán todas las pruebas que deben
realizarse para verificar la operabilidad de cada función. Las pruebas deben ser completas, describirse
en profundidad y hay que anexar los Programas de Prueba que permitan constatar la operación de cada
función, si fueran necesarios. Como anexo B deben incluirse todos los mensajes de error y las demás
señalizaciones de error (leds encendidos, marcas en la pantalla, etc.) que sean producidos por cada
función de software cuando se detecte una falla interna.
AMBIENTE DE DESARROLLO

Será homogéneo: Cada máquina de la compañía tendrá la estructura de directorios mínima común
para los discos, definida en el Documento de Estandarización de Computadoras. Se emplearán los
mismos lenguajes (C, MASM x86, Assembler 8047, CodeWarrior, WinIDE, etc.), con los compiladores
estándar de la compañía (no se aceptarán otros lenguajes, ni otros compiladores)
En caso de ser necesario usar Rutinas de Tiempo Real, se emplearán las que son estándar de la
compañía, las cuales serán verificadas para establecer su uniformidad y evitar productos
contemporáneos establecidos sobre versiones variadas (e inapropiadas) de dichas rutinas.
Los archivos “make” formarán parte de la documentación y si no se usa un formato autodescriptivo
(como en Unix), se anexará un “make.doc” que explique todo el comportamiento del archivo “make”.
No es aceptable entregar el diseño de detalle sin los correspondientes archivos “make” y “make.doc”.
VARIOS
Si surgieran problemas en la operación del Hardware, en desacuerdo al diseño original y éstos pudieran
ser corregidos por Software, empleando técnicas como promediación de señales ante presencia de
ruidos no previstos en los conversores, filtrajes de oscilaciones no esperadas (ni especificadas), etc. (la
vida real es así), éstos procedimientos tienen que ser sometidos a estricta aprobación de la gerencia. De lo
contrario termina el implementador de turno derrumbando todo el castillo de naipes al imponer sus
propios criterios técnicos, que no tienen que ser, y casi nunca son, los de la compañía. A toda costa hay
que evitar que las ocurrencias del programador de menor jerarquía prevalezcan sobre la organización.
De manera análoga, errores de operación en el Software (c’est la vie), en desacuerdo al diseño original y
que “pudieran” ser apropiadamente corregidos o socorridos por Hardware, empleando elementos tales
como restauraciones de la operación (Reboots), mediante el uso de temporizadores electrónicos
(Watch Dog Timers), etc., tienen que ser sometidos también a la más estricta aprobación de la gerencia.
Asimismo, la puesta en marcha de equipos sin la inclusión de una o más funciones originalmente
concebidas y decididas (tales como no activar las tarjetas de “Watch-Dog Timer”, o dejar las rutinas de
diagnóstico desactivadas, u otros despropósitos similares), tienen que ser aprobados por la gerencia.
PRUEBAS DE HARDWARE Y SOFTWARE: PROTOTIPO
Como parte del Diseño de Detalle debe generarse un Plan de Pruebas, que incluye tanto el Hardware como
el Software, que debe formar parte del procedimiento de la aceptación del Diseño de Detalle, y que debe
cubrir no solo las facetas más elementales, sino que ha de ser lo más completo posible, a fin de
establecer cualquier inconveniente antes de comenzar la producción en serie.

C2-49
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

PROTOTIPO

Para verificar el Diseño de Detalle se necesitan prototipos (que pueden ser completos o parciales) antes de
realizar la elaboración completa y la prueba definitiva de las tarjetas, y antes de dar por aceptada la
codificación completa de las rutinas y la prueba definitiva de las mismas. Además, el prototipo pretende
demostrar el sistema trabajando como un todo.

Es importante establecer una frontera clara entre Producción y Desarrollo en cuanto al prototipo, a fin
de evitar que se entremezclen responsabilidades: Echar a andar un equipo está plenamente bajo la égida
de Producción; poner a punto un prototipo es claramente una obligación de Desarrollo.

PRUEBAS DE SOFTWARE

El plan de pruebas de software será detallado y completo, y pretende evitar la ocurrencia de potenciales
problemas tales como rutinas de interrupción que no preserven el valor de algún registro y que ante una
secuencia de interrupciones pueda producir una falla, intermitente o esporádica. En la eventualidad de
descubrirse errores, debe generarse una solución conjuntamente con el Comité de Diseño.

PRUEBAS DE HARDWARE

El plan de pruebas de hardware será detallado y completo, y pretende verificar la operatividad del
equipamiento y el trabajo en ambiente hostil. En la eventualidad de descubrirse errores, debe generarse
una solución conjuntamente con el Comité de Diseño.

El plan de pruebas de hardware debe evitar que en la etapa de producción se produzcan parches,
techitos, “piggy-back’s”, cablecitos, producción de circuitos impresos nuevos, etc., medidas que a ese
nivel hay que realizárselas a toda la producción.

De ninguna manera la prueba verdadera se realizará en el sitio definitivo de instalación del equipo (se
realizará antes, en el laboratorio).

PRUEBAS DE SISTEMA

Los sistemas nuevos deben demostrarse trabajando como un todo. Esto incluye la verificación de la
operatividad bajo las condiciones de operación extremas previsibles. Pruebas especiales solicitadas por
el cliente, como por ejemplo “Surge Withstand Capability” (cfr. SWC, Ansi standard C37.90.1, 2002,
IEEE standard 472, 1974), deben realizarse a nivel de prototipo, antes de pasar a la etapa de
producción, por los mismos motivos indicados atrás.

HAY QUE DUPLICAR EL AMBIENTE DE TRABAJO REAL o, en su defecto, llevar un prototipo


(“plan piloto”) al sitio de trabajo final; lo primero puede ser muy difícil de realizar en sí mismo,
dependiendo de las circunstancias, y en ocasiones genera un proyecto de mayor envergadura que lo que
estamos haciendo. Suponga que va a instalar un equipo de control para una planta de la industria
petrolera. Usted no puede simplemente llegar con su equipo, encenderlo, y ver qué pasa. Pero simular el
comportamiento de la planta, y que su equipo interactúe con el simulador, a fin de verificarlo, pueden
ser palabras mayores, muy mayores…

C2-50
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Un día me llamó una compañía de Arizona solicitando mi soporte técnico para instalar un sistema que
habían desarrollado para la planta de Jose, Lagoven (subsidiaria de PDVSA en aquel entonces, cerca de
Barcelona). Lo habían instalado y lo único que lograban hacer era: ¡ “shut-down” de la planta ! (es decir,
levantaban el sistema, y éste apagaba toda la instalación). Apagar una planta de procesamiento de
petróleo, como se comprenderá, implica costos multi-millonarios en dólares. Desde luego, la empresa
diseñadora NO había probado a cabalidad su sistema, pues carecían de un simulador de la planta. Eso
siempre pasa, pero la solución no puede ser venir a probar en las instalaciones del cliente.

Un Alto Horno de una siderúrgica como Sidor, por ejemplo, NO puede apagarse jamás, pues hay que
volverlo a construir. Así que no se permiten fallas en el sistema, que lo reinicialicen.

 DOCUMENTACIÓN DEL SISTEMA


A NIVEL DE PRODUCTO:
 Descripción del sistema (Cómo opera; cómo lo va usar el cliente; cómo se lo va a manipular)
 Especificación funcional del sistema y subsistemas
 Documento de diseño
 Diseño de detalle
 Plan de pruebas
 Definición de módulos de software
 Listados de codificación comentados
 Manual de usuario (Cómo se instala; cómo lo mantiene)
 Recomendaciones y procedimientos de calibración
 Recomendaciones, frecuencias y procedimientos de mantenimiento preventivo
 Recomendaciones y procedimientos de mantenimiento correctivo
 Instrucciones de instalación
 Revisiones de código y de diseño de hardware
 Copias de ejecutables y ROMs

A NIVEL DE FABRICACIÓN:
 Especificación de Producción
Lista de partes y subassemblies (kits)

A NIVEL DE CADA EQUIPO, FICHA TÉCNICA IDENTIFICANDO:


 Lote de producción
 Fecha
 Serial
 Modificaciones hechas después de control de calidad, justificando quién y por qué
 Base de datos de cableado y sus modificaciones, si las hubiera
 Reparaciones hechas después de instalación, justificando quién y por qué
 Versiones de hardware y de software; modificaciones hechas después de manufactura

C2-51
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

 INSTALACIÓN Y GARANTÍA
Puede ser que usted requiera instalar su sistema (commisioning), o no, dependiendo del tipo de proyecto.
En todo caso viene luego una etapa de garantía y corrección de fallas en el sitio en donde finalmente
estará operativo. Nada de esto será reseñado aquí.

 RESGUARDO DEL PRODUCTO


Los componentes fundamentales de cada producto, que permiten duplicarlo sin mayor esfuerzo,
incluyen, en papel y en archivos de computadora (documentos legibles electrónicamente):

 Partes y piezas, absolutamente detalladas; con copia de las órdenes de compra que se realizaron
 Instrucciones completas de ensamblaje
 Diseños de AutoCad y planos de fabricación metalmecánica
 Bibliotecas de AutoCad empleadas
 Diseños de OrCad completos
 Bibliotecas de OrCad empleadas
 Archivos para fabricación de impresos
 Fotolitos
 Programas ejecutables, en ROM
 Fuentes de los programas
 Ambiente de desarrollo:
 Compilador
 Bibliotecas
La información, además, debería ser auditada, como mínimo, en relación a su consistencia; es decir,
que sin depender ni de una máquina en particular, ni de las personas directamente involucradas, un
ingeniero independiente tiene que poder lograr, de manera autónoma:
 Que los códigos fuente generen correctamente todos los ejecutables (binarios idénticos a los que
producen los ingenieros)
 Que los archivos OrCad y AutoCad generen exactamente los planos e instrucciones de manufactura
respectivos
 Que los DOC produzcan los manuales y demás información técnica
 Que los Kits puedan comprarse en los suplidores indicados, a los precios estipulados, y con las
identificaciones disponibles, en los plazos señalados en los documentos de “despiece” (system break-
down).
Uno se encuentra con MUCHAS SORPRESAS: Lo anterior, casi nunca sucede... Como gerente
de proyectos, primero, y luego como vicepresidente de investigación y desarrollo, siempre
terminaban en mi escritorio los proyectos de aquellos ingenieros que decidían tomar rumbos fuera
de la empresa. Y era con mucho esfuerzo que podían marcharse sin quebrantar el día a día de la
compañía. Lograr la repetibilidad de un proyecto era fundamental para mi equilibrio psíquico y la
estabilidad de la organización.

C2-52
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

RESPALDO
Debe haber procedimientos de respaldo, responsabilidad de cada empleado, para:
 Cotizaciones
 Ofertas
 Programas
 Manuales
 Archivos de AutoCad y OrCad
 Bibliotecas

 DETALLE (CHECK-LIST √)
Es común que en mis cursos de Proyectos les advierta a los estudiantes que su plan no puede ser una
copia del cronograma de evaluación que sigue el profesor. Para poder hacer la planificación de las
actividades, hay que saber qué va a hacerse, y estimar cuánto tiempo va a llevar (y en los proyectos reales
hay que contestar el decálogo del El Pastelero: Cuánto va a costar, dónde se realizará, cuáles recursos
se emplearán, y así con todas ellas)

Es entonces evidente que si no logramos visualizar un proyecto estratificado en muchas partes


(actividades, responsabilidades, etapas), no será posible tener un plan de trabajo adecuado. Así que
siempre les pido que dividan el proyecto EN CIEN PARTES. Esto jamás ocurre... A lo máximo que
llegan es por allá a veintitantas...

Para que vean que sí es posible, les anexo un ejercicio que hice, donde hay 86 ítems diferentes, todos
susceptibles de una adecuada planificación. Esto, para un proyecto de laboratorio sin grandes
pretensiones. Para uno real, la itemización requerirá centenares y hasta varios miles de actividades.
Además, la versión que uso en la actualidad tiene 98 ítems; no la anexo porque es menos genérica.

Muchos de los siguientes apartados tienen que dar lugar a múltiples aspectos más para considerar,
porque se aplican a diversidad de unidades, o secciones, que hay que trabajar por separado. En el
diseño, cada apartado diferente es un ítem separado. Hay que comprender acerca de qué versa el
proyecto y para qué será, y en cada aspecto establecer qué es con exactitud, quién lo realizará, por
qué; cuándo y con qué duración (Pert); en dónde se ejecutará; cómo (los métodos, las técnicas, las
tácticas y las estrategias que van a utilizarse), cuál será su costo (cuánto) y qué recursos se necesitarán
(con qué).

Todo comienza con la ESPECIFICACIÓN DEL SISTEMA o producto que el cliente, tanto exterior como
interior de nuestra compañía, debe suministrar (muchos proyectos son internos). Hay ocasiones en que
aquel conoce sus necesidades pero no está en capacidad de generar la Especificación para un proyecto;
en ese caso se atraviesa por una etapa anterior, en la cual un ente externo (asesor o compañía de
ingeniería) analiza el problema y produce la especificación. Otras veces el cliente piensa que puede
cambiar algún aspecto de su actividad, o emprender una nueva, pero no tiene idea de qué podría ser;
entonces se retrocede más aún para estudiar la operación de la compañía y proponer alternativas para
una nueva operación, lo que genera una lista de necesidades y de ahí la Especificación.

C2-53
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

DISEÑO CONCEPTUAL: √
1. Analizar y exponer diferentes aproximaciones conceptuales al diseño del proyecto
(deben ser VARIAS; más de 2) Evaluar qué partes deben realizarse en Hardware y
cuáles en Software. Explicar por qué (por ejemplo, podría resultar mejor generar
algunas señales con osciladores del tipo 555 que con el micro; o podría ser
imperativo usar conversores A/D externos, por razones de resolución o velocidad.
También podría ser que NO hubiera que incluir ciertas piezas de hardware, como
determinados filtros, si pudieran realizarse por software). Para cada aspecto del
diseño (cada parte que usted incluya) tiene que haber una justificación explícita de
por qué es mejor hacerla por hardware o por software, según su criterio

2. Deben incluirse consideraciones de tamaño y forma (características físicas, en


general) para las secciones relevantes de su equipo (si éste tiene, por ejemplo, que
caber en un espacio predeterminado)

3. Costo: Deben establecerse los límites impuestos desde afuera del proyecto

4. Cuando haya alternativas, deben determinarse las clases de Materiales que van a
emplearse (tecnología de semiconductores; materiales especiales para la caja,
pinturas, soportes, etc.)

5. Debe detallar los Sistemas de comunicación disponibles o que deben usarse: Email,
FTP, RS-232 normal, infrarrojo, radio: Tecnologías WiFi, Zigbee, si fuera el caso

6. Alternativas de interconexión (entre equipos; con las interfaces; con la maestra:


Lazo de corriente, fibra óptica) Cada unidad que deba interactuar con otras
requiere una explicación y un razonamiento de por qué se va a establecer de una
manera y no de otra

7. Análisis de las dificultades de la instalación: Ver cómo impacta el ambiente de


trabajo (en el que se va a operar el sistema) en sus decisiones de diseño: Caja,
soportes, aislamientos térmicos, pinturas, gabinetes presurizados, etc.
8. Tiempos de ejecución de las actividades: Comparándolos con los parámetros
externos puede establecerse la cantidad de recursos que habrá que asignarse
(ejemplo: Si determina que la programación va a tomar 3 meses, y usted tiene un
solo mes para entregarla, necesitará 3 o más programadores. [Nota: En el caso del
software, la relación NO es lineal])
9. Se realizarán experimentos y pruebas para definir aspectos indeterminados en la
especificación. Ejemplos: √ Establecer cómo interfieren diversas unidades, como
los ADC, temporizadores y comunicaciones; √ Determinar longitudes de onda de
dispositivos infrarrojos y ultrasónicos; √ Asegurarse de cuáles son exactamente las
diferentes frecuencias de modulación. √ Caracterizar componentes novedosos;
apoyarse en sus hojas de especificaciones técnicas. √ Las potencias y frecuencias a
las que se trabajará, ¿son seguras tanto para el usuario como para el ambiente?

C2-54
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

10. El RESULTADO de los puntos considerados es el Documento de Diseño


C o n c e p t u a l del sistema, producto o servicio, que según su criterio resuelva el
problema planteado en la Especificación. En la vida real, hay que obtener por
escrito la aceptación del cliente: Éste es la oportunidad para resolver discrepancias,
NO en el momento de la entrega, meses después

11. Se genera el Cronograma de Trabajo. Como toda proyección de lo que sucederá


en el futuro, habrá que adivinar, pero mientras más experiencia tenga más precisos
resultarán sus pronósticos. ¿Sabe usted ya, cuántas instrucciones por hora realiza?
¿Cómo puede, si no lo sabe, determinar el tiempo se le va a dedicar a un
programa?)

DISEÑO FUNCIONAL: HARDWARE Y SOFTWARE


12. Descomposición de su diseño en Módulos (Funciones específicas). Incluir Diagramas
que muestren las interrelaciones entre las diferentes partes

13. Puede refinarse el Cronograma de Trabajo original para incluir mayor lujo de
detalles, ahora que ya se tiene la concepción funcional. Usted difícilmente puede
modificar el cronograma. Cómo pudo saber antes, cuánto tiempo dedicarle a cada
actividad, sin tener el detalle del proyecto? La experiencia y el buen juicio se lo dirá.
Note que si se equivoca y necesita más tiempo del presupuestado, usted pierde
dinero [usted paga los retrasos]; si ofrece cronogramas más largos de lo necesario,
para cubrirse en salud, resultarán más altos sus costos y el proyecto se lo
adjudicarán a la competencia. (This game is not so easy after all)

DISEÑO FUNCIONAL: HARDWARE


14. Definición completa, precisa, exacta, detallada, cuantificada, sin vaguedades, de:

15. CPU (características de velocidad, longitud de palabra, familia, cantidad de CPU’s y


función de cada uno). Analizar VARIAS alternativas y justificar su elección.

16. Si hacen falta, incluir memoria externa; definir cantidad y tipo.

17. Especificar el almacenamiento secundario (tipo: Escoger entre la diversidad de


alternativas: Magnética, semiconductora, portátil, enchufable; identificar el tamaño.
Justificación de todo)

18. Interfaces varias: Seriales, paralelas; cantidad y tipo (teclados, displays, sonido, impresoras…)
19. Módulos de conversión A/D: Número de bits requeridos (justificar), velocidad,
necesidades especiales de filtraje; voltajes o corrientes que van a manejarse,
necesidades de dispositivos de Sample&Hold; justificación por qué si, o por qué
no, etc. Si se sobrepasan las características del micro seleccionado, y se requieren
componentes externos, explicar por qué, y cómo se van a interconectar (I2C, SPI,
otros buses)

C2-55
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

20. Módulos de entrada digital (cantidad, niveles de tensión o corriente de entrada que
van a manejarse, filtrajes necesarios, aislamientos. Si se requieren componentes
externos, explicar por qué, y cómo se van a interconectar)
21. Unidades acondicionadoras de analógicos (AIM): Filtros de entrada,
amplificadores, aisladores analógicos, desacoples, mecanismos de conexión con los
dispositivos externos; si se llegara a requerir independizar el sistema de cómputo
(micro) de las señales del campo (externas), indicar qué mecanismos de
interposición va a utilizar.
22. Unidades acondicionadoras de digitales (DIM): Filtros de entrada, aisladores
ópticos, desacoples, mecanismos de conexión con los dispositivos externos; si
llegara a necesitar independizar el campo y el sistema de cómputo (micro), indique
qué mecanismos de interposición va a utilizar.
23. Unidades de interfaz con las señales analógicas provenientes del campo (AFI):
Transductores, transmisores, etc. Clase y cantidad. Ver cómo se van a “muestrear”
las señales, si se requiere que sean sincrónicas las muestras, y cómo se las va a
adquirir en caso de que sean mucho más que las que puede manejar directamente el
microcontrolador (este es siempre el caso en la vida real).
24. Unidades de interfaz con las señales digitales provenientes del campo (DFI): Tipo
de dispositivos digitales externos (interruptores, semiconductores), ubicación
(distancia), método de transmisión, cantidades (ver cómo se va a multiplexar una
gran cantidad de interruptores externos, en caso de que haya que adquirir grandes
cantidades de “status” (este también es casi siempre el caso en la vida real).
25. Determinar qué Aisladores galvánicos va a emplear para señales analógicas (ISOs)
si su sistema lo requiere.
26. Optoaisladores para señales digitales (éstos son muy sencillos y económicos,
comparados con los analógicos). Establecer con claridad la forma de alimentación
que permita en realidad que unos dispositivos estén completamente aislados de
otros. Recuerde que no puede haber nada en común; mucho menos la tierra!
27. Definición de Modems y otros mecanismos de interconexión, como radios, etc.
28. Otros optoacopladores (de potencia, para controlar señales externas; en las líneas
de comunicación, como los que se usan en los PC del Lab. C para evitar que se
quemen las tarjetas madre). Cada punto que requiere, o no requiere,
consideraciones de aislamiento, debe ser razonado. Por qué sí o por qué no, y de
qué tipo.
29. Relés (capacidades de los contactos, tiempos de conmutación, “duty cycle”,
maneras de “mojar” los contactos)

30. Gabinetes (tamaño; norma NEMA, si aplica; capacidad de: Entrada, salida y
control)

C2-56
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

31. Previsiones de alambrado de señales de control, de comunicaciones, etc.

32. Señalar restricciones que limiten la agrupación de unas funciones con otras, en una
misma tarjeta, o “backplane”. Por ejemplo: Podría no convenir que se conectaran
en la misma tarjeta los conversores analógicos con el control de potencia. O los
radios con el micro, etc.

33. Indicar si pueden emplearse elementos suplidos por otros (no todo hay que fabricarlo. A lo
mejor fuentes, Modems, Computadoras, Tarjetas con Microprocesadores, etc., hay que comprarlos como
subsistemas) o si pueden emplear dichos elementos cuando han sido diseñados
previamente en la compañía. Si fuera necesario modificar algunos elementos
empleados por la compañía anteriormente para adaptarlos al proyecto actual,
deberán señalarse aquí las diferencias y mejoras que hay que introducirles.

34. RESULTADO: Documento de Diseño F u n c i on a l del Hardware.

DISEÑO FUNCIONAL: SOFTWARE


Debe incluir la descripción de las funciones de alto nivel (las que “ve” el usuario; estas
deben ser aparentes de la especificación original):

35. Protocolos de comunicaciones (cómo va a transmitirse la información entre las


diversas unidades que interactuarán entre sí; si los protocolos serán de la industria,
o propios. En este caso hay que incluir simulaciones que garanticen la integridad del protocolo,
y la recuperación y control de situaciones anómalas, al estilo de los errores de comunicación, las
reposiciones inesperadas del hardware (reboots), interferencias, etc. No es nada trivial diseñar un
protocolo...

36. Cantidad de información que va a transmitirse y su velocidad. Estos parámetros


tienen que cuantificarse. En caso de que haya alternativas, explicar la selección
(por qué)

37. Categorización de las informaciones; por ejemplo: Si hay “analógicos rápidos”, o


señales analógicas que necesiten ser adquiridas a alta velocidad y con tiempos muy
precisos entre muestras (sincrónicas); si hay analógicos lentos, que puedan leerse a
conveniencia del micro, si además del “scan normal”, en donde a lo mejor se
procesan solo valores que hayan cambiado significativamente, también amerite
incluir “scans de seguridad”, que lean informaciones viejas a pesar de no haberse
detectado cambios significativos en ellas; con qué frecuencia. La estrategia precede a la
funcionalidad
38. Capacidades de control: Qué señales deben manipularse. Características de dichas
señales. Si son SCRs, relés, señales optoacopladas. A qué velocidad; cuánto debe
durar cada pulso de control. Cómo será la secuencia para encender o activar un
punto en el campo, y cuál para cerrarlo. Algo que no puede tolerarse es que una falla
en su dispositivo produzca activaciones indeseadas en las señales de control.
Garantizar esto es de crucial importancia, porque lo que sí está claro es que ¡ su sistema

C2-57
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

fallará ! (todos lo hacen). Así que en una industria, el manejo de las señales de control
no es tan sencillo como colocar activadores en el micro (relés, SCR’s), y listo. Nada de
eso. Se necesita garantizar, mediante procesos dinámicos, que una falla en su equipo
no activará inadvertidamente las señales que él controla

39. Funciones de diagnóstico: Dentro del ciclo infinito del microcontrolador pueden y
deben incluirse lecturas que permitan saber si las unidades externas están
funcionando: Si una fuente se cayó, si algún dispositivo de comunicaciones falló, o
la computadora externa, etc. Es importante establecer la estrategia: Qué va a hacer
su sistema en caso de que alguna de estas cosas suceda. Si no se le ocurre qué hacer,
es preferible no programar nada! Pero normalmente un diseño tiene que prever
qué acciones tomar cuando algo falla; al menos las cosas previsibles. Y la alternativa
tiene que ser inteligente, y razonada, para cada cosa que se prevea que puede fallar

40. Interfaz con el usuario (MMI): Cómo interactuará el usuario con su sistema:
Teclado, voz, pantalla, bombillos o leds, otros mecanismos (controles remotos),
etc. Qué funciones debe incluir en su sistema para manejar la interacción con el
usuario (lectura de caracteres, por interrupciones o vía “encuesta” [polling];
determinación de buffers circulares, tamaño, previsión de overflow y acciones
consecuentes, diversas rutinas de conversión; manejo de CRCs u otros mecanismos
de control de error)

41. Interfaz de Mantenimiento. Hay funciones, diferentes a las normales, que le


permiten al encargado del servicio realizar las labores de mantenimiento. Hay que
establecer cuáles son esas funciones, y cómo operarán

42. Funciones de respaldo, en caso de que haya necesidad. La información adquirida, y


no transmitida, puede ser preciosa. Por ejemplo, si el sistema fuera un contador de
personas para el Metro de Caracas, y al final de la tarde hubiera un apagón, no por
eso usted puede darse el lujo de “perder” la cuenta de cuántos usuarios habían
entrado a los trenes

43. Funciones de cálculo específicas (FFT, etc). Hay que establecer todas las que
necesite; identificarlas, e incluirlas dentro de las actividades que hay que realizar.

44. Necesidades de multitarea, spooling, comunicación en back-ground, etc. Debe


incluir un pequeño sistema operativo? Debe comprarlo, o hacerlo como parte del
proyecto?

45. Diagramas de despliegues. Si algo tiene que mostrarse en la pantalla, aquí hay que
incluir un diagrama, o foto, de dicha pantalla

46. Editores, menús, reportes. Si algo va a imprimirse, aquí tiene que mostrarse un
facsímile de lo que va a imprimirse. Obsérvese que los facsímiles se incluyen
ANTES de haber generado una sola línea de código para producirlos

C2-58
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

47. Identificar programas que van a ser modificados (en caso de que ya la compañía, o
usted, haya hecho algunos similares con anterioridad), o creados nuevos.

Funciones y actividades que el usuario no ve, pero que se incluirán en esta etapa son:

48. Rutinas de autodiagnóstico:

49. Sistema de Detección de fallas; definir qué estrategia deberá seguirse y qué acciones
se tomarán en caso de detectarse fallas: Reportes, señales, alarmas, etc.

50. Cada posible falla detectable deberá tener su especificación correspondiente. Como
de costumbre, no tiene sentido incluir una rutina de diagnóstico, si no está
claramente especificada qué acción inteligente y apropiada deberá adoptarse en
caso de detectar una falla. Normalmente, ¡ apagar el equipo NO es lo indicado !

51. Indicar si hay funciones que han de operar en diferentes CPU’s (Pentium, 8031,
HC08, etc.). Proponer qué estrategia se va a emplear en su elaboración (diseño
independiente para c/u; una misma copia del programa, que se compile y funcione
en c/u, etc)

52. Indicar si pueden emplearse rutinas suplidas por otros (modificándolas o no):
Spoolers de impresión, rutinas estándar de comunicación Xmodem, FFT, etc.
Tener en cuenta, no el desarrollo, pero sí su incorporación e integración al resto de
las rutinas y programas.

53. Indicar si pueden emplearse rutinas codificadas previamente, modificándolas


(señalar las diferencias que hay que introducirles) o sin modificación.

54. Identificar qué funciones van a realizarse como multitareas (como impresión de
reportes, adquisición de información, procesamiento y transmisión de datos,
simultáneamente). Las decisiones varían si no se tiene necesidad de tiempo real para la
adquisición y almacenamiento de la información, o si la actividad primordial es la
de adquisición de información en tiempo real; en este caso, las demás actividades
deben supeditársele.

55. Evaluar si habrá cambios fundamentales en el software estándar de la compañía


(por ejemplo, en las rutinas de tiempo real, que las empresas suelen desarrollar,
probar y comercializar en gran cantidad de productos y proyectos); en tal caso,
debe seguirse un proceso muy riguroso (si están funcionando y probadas, RESÍSTASE
A MODIFICARLAS)

56. RESULTADO: Documento de Diseño Funcional del Software.

C2-59
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

DISEÑO DE DETALLE

Hasta aquí NO HEMOS ESCRITO NI UNA LÍNEA DE CÓDIGO, NI HEMOS ARMADO CIRCUITO ALGUNO...

DISEÑO DE DETALLE: HARDWARE


Debe incluir un Diseño de Implementación, que muestre en el Hardware:

57. Las relaciones entre las diversas tarjetas y módulos

58. La definición de las Interfaces entre ellos (cómo se van a conectar unos con otros)

59. Debe mostrarse el funcionamiento de tarjetas y módulos mediante Diagramas


Electrónicos.

60. Hay que identificar todos los componentes, sus proveedores principales y los
secundarios (second sources), poniendo especial cuidado en no olvidar los
indispensables Condensadores de Desacople para los ICs: De qué tipo, de qué valor; ubicación

61. Se seleccionarán los Condensadores de Desacople para las Fuentes y el sistema de


baterías.

62. Se detallará el diseño y disposición de los diferentes Blindajes y el Cableado; se hará


la determinación y ubicación de los Planos de Tierra, para la apropiada anulación
del Campo Eléctrico. Se explicará cómo se va a cablear, aprovechando los Planos
de Tierra y el Chasis para eliminar la radiación entrante y saliente.

63. Se identificará qué cables serán entorchados, apantallados, etc.

64. Se identificarán los Circuitos impresos de múltiples capas, indicando en cada caso
cuántas capas serán, y el propósito. Se señalarán dónde se manufacturará cada
tarjeta (y los costos).
65. Definir dónde irán cables planos; su clase, el tipo de conector que llevarán, etc.

66. Se identificarán las diversas impedancias características, en los sitios que lo ameriten
y se indicarán las apropiadas terminaciones. Deben anotarse aquellos sitios en que
no sea necesario terminar o acoplar las impedancias.
67. Identificar con absoluta exactitud y claridad, para aquellos pines del
microprocesador que deben reprogramarse como salidas, cómo va a garantizar
que todo funcione perfectamente entre el momento en que se alimenta el
micro y el instante en que las señales pasan de ser entradas a ser salidas.
Qué ocurre si el micro se “guinda” después de alimentarlo, pero antes de
programar perfectamente las salidas? No puede permitirse que haya cortos circuitos
entre componentes externos, ni siquiera durante intervalos muy cortos, porque si
en el ínterin llegara a congelarse el programa, el corto circuito destruirá los
componentes

C2-60
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

68. RESULTADO: Diseño de Detalle de cada tarjeta, que permite la generación de


los PCB (printed circuit boards) y la manufactura completa de las mismas.

69. Anexo A: Pruebas para verificar la operabilidad de cada tarjeta. Deben ser
completas y describirse en profundidad, para permitir su empleo en otras etapas,
como control de calidad, pruebas de aceptación (FAT), etc. Debe incluirse la
descripción de los Equipos de Prueba necesarios; especificar si serán alquilados o
comprados; incluir también los “Programas de Calibración y Prueba”, que
servirán luego en la etapa de producción. En su defecto, hay que anexar el
procedimiento manual, completo, que hay que seguir para las pruebas. Debe definir
cuáles (y cuántos) serán dicho programas para el Diagnóstico del Hardware
(Hardware Diagnostics): El micro, sus bloques funcionales, las diversas entradas a
cada dispositivo, los motores, los transmisores y receptores, los acopladores. Casi
todo el hardware que vaya a incluir necesitará programas de diagnóstico. Definir
también cuáles piezas del equipo NO requerirán estos programas, por qué, y en ese
caso cómo se probarán.

Indicar también qué Programas de Calibración va a necesitar (en los conversores,


temporizadores, transmisores y receptores, sensores) Deberá indicarlas qué piezas
no necesitarán estos programas, con su justificación (se calibrarán a mano?, por
qué? ¿no necesitan ajuste?; etc)

La estrategia de Depuración (debugging) del proyecto: Hardware Y Software hay


que establecerla con antelación; si no sabe cómo lo va a probar, probablemente no vale la pena ni
comenzar a programar, o armar.

70. Anexo B: Se identificarán las Indicaciones de Error (leds encendidos, sirenas, etc.)
que sean producidos por cada tarjeta cuando se detecte una falla en ellas. La
descripción debe ser completa y detallada; por ejemplo, si hay luces que parpadean
a diferentes velocidades, o hacen beeps de diversas formas, etc.

DISEÑO DE DETALLE: SOFTWARE


Incluye un Diseño de Implementación, que muestra en el Software:

71. Las relaciones entre las diversas rutinas, mediante un diagrama apropiado (En
proyectos de tamaño considerable, puede estudiarse la necesidad de hacer una
descripción empleando UML: Universal Modeling Language)

72. Definición de variables (locales, estáticas, externas; nombres, significados, uso;


“include files”)

73. Selección del lenguaje en que se hará el desarrollo (C, assembler, Java, etc.)

74. Diagrama de flujo y posiblemente listados de pseudo código

C2-61
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

75. RESULTADO: Diseño de Detalle de cada función, que permita realizar la


codificación de cada una, y cada subrutina, módulo y programa de los subsistemas.

76. Anexo A: Pruebas para verificar la operabilidad de cada función. Deben ser
completas, describirse en profundidad y deben anexarse los Programas de Prueba
que permitan constatar la operación de cada función, si fueran necesarios o, en su
defecto, el procedimiento completo que hay que seguir para las pruebas.

77. Anexo B: Incluir todos los mensajes de error y todas las otras señalizaciones de
error (leds encendidos, marcas en la pantalla, etc.) que sean producidos por cada
función de software ante la detección de una falla interna.

VARIOS (PELIGROSOS) EN LA ETAPA FINAL

78. Llegada la etapa de producir el dispositivo (probablemente un prototipo), si se


llegan a encontrar problemas en el Hardware (ruidos, imprecisiones,
inestabilidades), que pueden ser corregidos por Software (promediación de señales,
filtrajes, etc. la vida real es así), tienen que quedar explícitas esas correcciones en la
documentación del proyecto (bitácora) y ser aprobados por el Gerente de
Proyectos (o por el profesor, en caso de nuestros cursos)
79. Si se llegan a encontrar errores en el Software, y usted piensa que se pueden
corregir por Hardware (haciendo, por ejemplo, “reboots” mediante Watch Dog
Timers, etc.) tienen que quedar documentados de manera explícita en la bitácora
del proyecto y ser aprobados por el Gerente de Proyectos de la compañía (o el
profesor del curso)
80. La puesta en marcha de equipos sin la inclusión de funciones originales (por
ejemplo, sin activar las protecciones, o el “watch-dog timer”, sin las rutinas de
diagnóstico, sin algún componente mecánico), tiene que ser igualmente aprobada.

PRUEBAS DE HARDWARE Y SOFTWARE: PROTOTIPO


81. Planes detallados y completos. Se pretende evitar problemas (rutinas de
interrupción defectuosas) y demostrar la funcionalidad (ver anexo a continuación,
pruebas tomadas del IEEE Standard for Software Test Documentation (Std 829-
1998)

PRUEBAS DE HARDWARE
82. Evitar que en producción se produzcan parches, techitos, “piggy-back’s”,
cablecitos, producción de circuitos impresos nuevos, etc., medidas que a ese nivel
hay que realizárselas a toda la producción

83. De ninguna manera la verificación del diseño se realizará en el sitio del cliente: Se
hará en el laboratorio.

C2-62
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

PRUEBAS DE SOFTWARE

84. Evitar “parches”.

PRUEBAS DEL SISTEMA

85. Los Sistemas nuevos deben demostrarse trabajando como un todo. Esto incluye la
verificación de la operatividad bajo las condiciones de operación extremas
previsibles (System Exerciser). Pruebas especiales solicitadas por el cliente, tales
como Surge Withstand, etc., deben realizarse a nivel de prototipo, antes de pasar a
la etapa de Producción.

86. HAY QUE DUPLICAR EL AMBIENTE DE TRABAJO REAL o, en su


defecto, llevar un prototipo (“piloto”) al sitio de trabajo final.

TOMEN NOTA: Sistemas de control a lazo cerrado tienen que probarse ANTES
de incorporarlos a una planta o fábrica; de lo contrario, los errores pueden ser
devastadores. Pero muy probablemente haya que hacerse un dispositivo que simule
la planta (lo cual puede ser un proyecto en sí mismo, hasta más complejo
que el proyecto original).

Está descartado que un ingeniero incorpore un sistema de control a lazo


cerrado en una planta, sin haberlo probado antes, simulando el proceso. Debe
definir con exactitud cómo será su System Exerciser

C2-63
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Tomado del: IEEE Standard for Software Test Documentation (Std 829-1998).

TESTING

 Component Testing: Conducted to verify the implementation of the design for one software element
(e.g., unit, module) or a collection of software elements. Sometimes called unit testing. The purpose of
component testing is to ensure that the program logic is complete and correct and ensuring that the
component works as designed.

 Integration Testing (System Testing): Testing conducted in which software, hardware or both
elements are combined and tested until the entire system has been integrated. The purpose here is to
ensure that design objectives are met and that the software, as a complete entity, complies with
operational requirements

 Conversion Testing: To ensure that all data elements and historical data are converted from an old system format to the new system format.

 Job Stream Testing: Testing to ensure that the application operates in the production environment.

 Interface Testing: Testing done to ensure that the application operates efficiently and effectively outside
the application boundary with all interface systems.

 Security Testing: Testing done to ensure that the application systems control and auditability features of
the application are functional.

 Recovery: Testing done to ensure that application restart and backup and recovery facilities operate as
designed.

 Performance: Testing done to ensure that the application performs to customer expectations (response
time, availability, portability, and scalability)

 Regression Testing done to ensure that applied changes to the application have not adversely affected
previously tested functionality

 Acceptance Testing

Testing conducted to determine whether or not a system satisfies the acceptance criteria and to enable the
customer to determine whether or not to accept the system. Acceptance testing ensures that customer
requirements' objectives are met and that all components are correctly included in a customer
package.

 Beta Testing done by the customer, using a pre-release version of the product to verify and validate that
the system meets business functional requirements. Detect application faults, failures, and defects.

C2-64
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

PASS / FAIL CRITERIA


Specify the criteria to be used to determine whether each item has passed or failed testing.

 Suspension Criteria
Specify criteria to suspend all or a portion of the testing activity on test items associated with the plan.
 Resumption Criteria
Specify the conditions that need to be met to resume testing activities after suspension. Specify the test
items that must be repeated when testing is resumed
 Approval Criteria
Specify the conditions that need to be met to approve test results. Define the formal testing approval
process.

ERRORES COMUNES

Verifique al menos los siguientes aspectos:

1. LEDs sin resistencias


2. Código de resistencias (valores de condensadores)
3. Capucha Punta Osciloscopio (¡ no usar la punta para “clavarla” en el protoboard !)
4. Osciloscopio mal manejado: √ Punta atenuadora; √ descalibración
5. Armar el circuito y encenderlo de una (porsia...) Así van a quemar el micro...
6. Síndrome del “empty main()”: ¡ Todo en sus programas está “pegado” de las
interrupciones !

CUANDO TODO FALLA

1. Tenga a mano diagramas: Bloques, lógico y circuital; esté seguro de la ubicación


2. Asegúrese de haber hecho la simulación
3. Fundamental probar la circuitería (protoboard) ANTES de conectar el micro.
Generar a mano las señales que provendrían del micro; así saben si los LEDs
encienden o no. Cuando el circuito externo esté bien, puede conectarse el micro
4. En el peor caso: Quite TODO y comience paso a paso: Sólo el micro, con un
programa viejo (¡ que seguro funcione !). Añadir luego una entrada y constatar que
la leamos bien. Si ni siquiera eso funciona, estamos MUY MAL, pero es fácil
verificar qué falla: La fuente está apagada o desconectada; hay resistencias en serie
con la alimentación del chip; el osciloscopio tiene la entrada apagada...
5. Método Incremental: Un pequeño paso; prueba, y verificación... repita
6. "Perder los archivos" ¡ NO ES EXCUSA PARA RETARDAR EL PROYECTO !
7. "No puedo leer el floppy, o el Pendrive, con mi proyecto": TAMPOCO
8. "Un virus dañó el disco duro, con todo y proyecto": MENOS
9. Perdí el Pendrive; lo mojaron en la lavandería ¡!
10. El cuidado con la información hace referencia a los programas, y a los circuitos
impresos (Orcad), diseños metalmecánicos (Autocad), toda la documentación
(cliente e interna: MSWord, Excel, MSProject), notas de entrega, facturas, etc.

C2-65
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

ESTÁNDARES

IEEE (están todos en la biblioteca de la USB):

 AnsiC37.90.1-2002(IEEE-472,1974).pdf: Surge Withstand Capability (SWC; hardware)

 AnsiC37.90.2-2004(IEEE-472,1974).pdf: Withstand Capability (SWC; hardware)

 IEEE1008(SoftwareTesting).pdf

 IEEE12207(Software).pdf: Software life cycle processes

 Normas Nema (Nema 12: Interiores; Nema 4X)

 Cada aspecto del diseño electrónico tiene un estándar que lo cubre, procedimientos
internacionales que hay que cumplir. Usted debe estar atento de ellos: IEEE, ANSI, IEC, UL...

 Y cada país tiene los suyos. La normalización en Venezuela es Covenin.

 Además, ISO-9000... para producción. Nada entra a Europa sin ISO-9000. Mi opinión en relación a ese
estándar, me la reservo por el momento.

C2-66
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

 COMUNICACIÓN
El problema más difícil en una relación humana, y los proyectos no escapan a él, es la COMUNICACIÓN.
El cliente cree
que dijo todo lo
que quería, con
claridad; el analis-
ta entiende algo
bastante diferente;
el programa se
aleja mucho de lo
que se especificó;
en fin: Aquí solo
se puede rozar el
tema, pues ni está
resuelto, ni hay
espacio, pero esta
gráfica es una
manera ilustrativa
y muy simpática
de representarlo.

 FLUJO DE CAJA: ZERO CASHFLOW


Una técnica muy empleada para hacer la Programación Financiera es la del “Zero Cash Flow”, que
consiste en lograr que quien desarrolla el proyecto no desembolse NADA de su propio dinero a lo largo
de todo el trabajo. Esto es fundamental, sobre todo en compañías pequeñas que no tienen suficiente
capacidad financiera, o que no cuentan con un historial crediticio. Para lograr un “Zero Cash Flow” se
debe establecer, en cada ítem importante del proyecto (milestone), el momento en que el cliente va
haciendo pagos para cubrir cada etapa; por ejemplo: Se da comienzo al proyecto cuando se ha recibido
la Cuota Inicial (“down payment”); llegado el momento de ordenar la compra de insumos
(computadoras que van a instalarse, periféricos, etc.), se debe hacer otra aportación, y así sucesivamente.
Los clientes corporativos (sobre todo si son oficiales) suelen no entregar dinero en anticipo sin una
garantía; aparecen entonces las Fianzas (Bid bond, o fianza de licitación; están también las de fiel
cumplimiento, la de anticipo, fianza de garantía, etc.), que son avales que, por ejemplo, las Compañías
de Seguros otorgan al cliente, a quien para cobrarse o resarcirse (recuperar su anticipo) sólo le basta con
indicarle a la aseguradora que quiere Ejecutar La Fianza; no tiene que hacer grandes justificaciones de
por qué. (La aseguradora con toda certeza procederá a embargar al suplidor para a su vez recuperar su
dinero, probablemente ejecutando algún documento que le habrá firmado previamente para ello:
Hipoteca, giros, letras de cambio, “side letters”, etc.)

C2-67
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

En cada etapa se vence una fianza y hay que entregar una nueva para continuar. Una fianza de licitación
garantiza la seriedad de una oferta (que si le otorgan el proyecto a cierto suplidor, éste estará ahí para
ejecutarlo; se hace porque el Cliente no desea perder tiempo evaluando propuestas que no sean “en
firme”). Con la inicial va la correspondiente Fianza de Anticipo. Hay fianzas de Fiel Cumplimiento, de
Garantía y más.

Es importante notar dos cosas: Si no puede convenirse con el cliente una estructura de pagos del tipo
“Zero Cash Flow” (en algún momento se prevé que faltará dinero), hay que garantizar el
financiamiento externo!!!, probablemente con un banco. Es importantísimo considerar los
intereses como “costos” del proyecto, que hay que cargárselos al cliente; de lo contrario, será el banco
quien haga las ganancias y, el Suplidor… sólo el trabajo.

Proporciones: En relación con este tema financiero, es importante observar las proporciones que a
veces ocurren con algunos proyectos o trabajos. Recuerdo haber emprendido varios viajes a Puerto
Ordaz, por ciertos trabajos de asesoría, y caer en cuenta de cuánto estaba costando el pasaje en avión
(Bs. 100.000 en su época), el hotel (Bs. 160.000 al día), alquiler de vehículo (Bs. 60.000 diarios),
restaurantes, etc. ¿Y cuánto estaba cobrando yo por mi labor? Quienes realmente ganaban con mi
trabajo eran Avensa (en esa época), el Intercontinental y demás compañías “accesorias”!!!. Y a
pesar de que el cliente estaba dispuesto a reconocer esos gastos, mi propia ganancia quedaba eclipsada
ante los demás desembolsos. Hay que ver si eso tiene sentido, o no...

 FAST PROTOTYPING
Como acabamos de ilustrar, uno de los principales y más graves inconvenientes en los proyectos (y en la
vida, en general) son los problemas de comunicación. Una cosa creemos nosotros que el cliente (el
profesor) pidió, y otra muy distinta está pensando él. Así, ¿cuántas veces no vi en mi vida profesional,
la culminación de un proyecto, para encontrar que en el acto de entrega el cliente indicaba que no era
eso lo que había solicitado?

Una forma de lidiar con este problema en Proyectos de Desarrollo que pueden durar varios años,
consiste en realizar a la mayor brevedad posible un “prototipo” del mismo, que permita al cliente ver y
aprobar el funcionamiento del sistema. Se requiere validar tanto el Hardware como el Software. El
cliente podrá ver cómo serán las pantallas con las que se interactuará con los programas; cuáles los
campos de información que hay que llenar, en qué orden; cuánto se ayudará con el mouse y cuánto con
el teclado, etc. En relación al Hardware, podrá verse también cuánto espacio se requerirá, cómo se
instalará, si cabrá en el sitio previsto, o si las puertas y demás lugares de acceso están donde sean más
convenientes. Un prototipo presentado con la mayor antelación no garantiza que no se encontrarán
problemas y malentendidos después, pero es realmente una ayuda invaluable.

Como parte del ejercicio puede acordarse con el cliente que acepte: Reportes, pantallas,
procedimientos..., firmando un acta y los mímicos de los reportes, etc., de tal manera que al finalizar el
proyecto (y cuando probablemente la persona que lo vaya a recibir sea otra, porque la que contrató el
proyecto acaba de renunciar, o fue ascendido...), se tenga al menos respaldo escrito, aval del trabajo que se
ha hecho.

C2-68
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Son innumerables las oportunidades en que encontré este problema: Una persona recibiendo (o
desaprobando, mejor dicho) un proyecto que, al aplicar su criterio de cómo debía funcionar algo, o
qué debería habérsele entregado..., no coincidía con lo que se había producido, tras largos, arduos y
costosos años de trabajo...

 QUE FUNCIONE
Desafortunadamente para el ingeniero de diseño, tanto el cliente como sus jefes tienen una visión
sesgada del estado del proyecto de usted (y sus profesores también); ellos ven su desarrollo de la
siguiente manera: Suponga que usted ha resuelto perfectamente el problema de la alimentación eléctrica;
la parte del aislamiento de las señales, la amplificación, el filtro de orden “n”, la conversión de la señal; la
RAM funciona impecablemente; usted probó en forma independiente el protocolo de comunicaciones;
los interruptores para realizar la interfaz con el usuario en su equipo están operativos... Pero si el cliente,
nuestros jefes o profesores, no ven que algunos datos del campo van y vienen entre el equipo y el PC,
ni observan que se presente información en la pantalla, aun cuando ésta sea un poco maltrecha; si no
hay movimiento de luces en el equipo..., su percepción será que al proyecto le falta una eternidad, que
usted se encuentra estancado... Su calificación instantánea en el curso será mínima.
Si, por el contrario, el ingeniero emplea la fuente del laboratorio en vez de su propio sistema de
alimentación de energía; la señal aún no tiene aislamiento, ni conformación ni amplificación (se
inyectan valores de 0 a 5 voltios, provenientes –no de termocuplas– sino del generador que tenemos a
nuestra disposición); si la comunicación aún no sigue el protocolo, sino que es un vaciado a ciegas de
la información; si la velocidad de transferencias es de 9600 bps porque usted no ha logrado vencer la
barrera del sonido; si no se verifican ni paridades ni CRCs..., la percepción de todo el
mundo será que el proyecto va bien encaminado (“e pur se muove”, como decía
Galileo), y que sólo faltan los “accesorios”. ¡ Su calificación instantánea en la asignatura estará por
encima del mínimo ! y posiblemente a usted realmente le falte mucho más que al personaje del ejemplo
anterior. ¡ No importa ! Viendo tanta actividad, el cliente y su jefe estarán tentados a flexibilizar su
cronograma.
Esta es una particularización del “Fast Prototyping” del que hablé con anterioridad. No lo olvide,
aunque, probablemente, sus profesores del Laboratorio no flexibilicen nada...
En todo caso, una buena recomendación para todo proyecto consiste en que Usted siga estas tres fases:
 Primero, que funcione (aunque cojee, tal como acabo de describir)
 Luego, que funcione bien (que la información sea real, las comunicaciones también, etc.)
 Finalmente, que funcione de manera óptima (que no se usen las fuentes del laboratorio, que
los filtros sean de verdad y que el proyecto cumpla con todo lo que se pidió)
Es harto difícil demostrar que filtros y amplificadores, optoacopladores y micros están todos bien, y que
lo único que falta es integrarlos.

Una integración progresiva calma los nervios.

C2-69
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

 KISS
Edsger W. Dijkstra, famosísimo computista contemporáneo, de apellido impronunciable, aconsejaba a
su séquito en relación a su método preferido para lograr que inmensos proyectos de programación
culminaran a satisfacción; el método KISS: “Keep It Simple, Stupid!”.

En la vida real, todos se oponen al principio KISS. El cliente cree que quiere cosas complicadas; el
gerente de ventas se empeña en agregarle características (“features”) al proyecto, que ya casi no cabe en el
micro; y a muchos de mis ingenieros (a usted mismo) no le da nota hacer cosas sencillas. Un proyecto
simple se convierte en un gran desarrollo, por el placer de complicar. Luego, obviamente no funciona, y
hay que comenzar la dolorosa depuración (debugging).

Hoy en día en mis laboratorios de proyectos siempre pido que cada grupo agregue al esquema básico
que propongo, algo que denominamos “la aplicación”. Y en cuántas me veo para lograr que pongan los
pies en la tierra. Todos quieren llegar a la luna, en el lapso de un trimestre…

Por eso es importante la cita de Antoine De Saint-Exupéry que encabeza este capítulo, en relación a la
simplicidad que debe orientar el desarrollo de los proyectos. O, como indicaba Albert Einstein: “Make
everything as simple as possible, but not simpler ”.

 TEMAS VARIOS QUE SON “PURO ORO”


CONCEPTOS BÁSICOS DE ELECTRÓNICA.
ARMADO DE CIRCUITOS.

Debo decir que siempre detecto fallas fundamentales en aspectos técnicos BÁSICOS relacionados con
el ARMADO de los circuitos, que PUEDEN ser los culpables del funcionamiento incorrecto en sus
anteriores proyectos, y lo serán también en el futuro, si no los subsanan.

Más o menos la mitad de los alumnos de digitales y demás proyectos de electrónica manifestaron no
haber ni oído sobre la necesidad y el uso de los Condensadores de Desacople! No tiene mucho sentido
conceptualizar un proyecto, por ejemplo, de digitales, perfectamente ceñido a los cánones lógicos y de
programación, y luego encontrarse con que el prototipo presenta fallas aleatorias, que nunca terminan
por individualizarse.

No tiene mucha gracia hacer bien un diseño y luego omitir el uso de condensadores de desacople al
armarlo, o traer la alimentación desde la fuente hasta el Protoboard mediante un famélico cablecito #22,
y pretender que todos los integrados reciban un apropiado Vcc!!!

Denle una mirada con detenimiento a la sección que llamé "Lab0 ", hoy y después... Esa es "La Biblia".
Aunque no fue redactado específicamente para nuestros Laboratorios de digitales y de proyectos, y por
tanto existen muchas lagunas en él en aspectos que no considera, como por ejemplo en la parte
analógica..., por lo menos puede servirles parcialmente como lista de verificación de algunos conceptos
que necesitarían aprender.

C2-70
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Hago el comentario de que a lo mejor a su profesor de digitales se le pasó explicarles a tiempo la


importancia de aspectos tales como el de los Condensadores de Desacople, pero tampoco son ustedes
muy proactivos; les hubiera bastado con abrir cualquier libro del área, como el Wakerly, que ha sido el
texto designado desde hace ya un buen tiempo, y habrían encontrado qué son, para qué se aplican, cuál
es su importancia, etc.

En la vida profesional a usted no lo van a evaluar por lo que los profesores dejaron de enseñarle, ni eso
le servirá de atenuante cuando desconozca un concepto fundamental.

Usted siempre será el responsable directo, único y exclusivo de lo que ignora.


BLINDAJE Y CABLEADO

Revisen también los conceptos sobre:

 Plano de Tierra,
 Cargas Virtuales,
 Anulación de Campo Eléctrico mediante Plano de Tierra,
 Anulación de efectos del Campo Magnético mediante Plano de Tierra,
 Modo de cablear aprovechando un Plano de Tierra o el Chasis,
 Uso de cables entorchados, etc.,

que son aspectos en los que, según he podido observar, suelen tener lagunas serias nuestros estudiantes.
Espero que apliquen estas técnicas en el armado de sus proyectos.

Si necesitan alguna ayuda en relación a estos temas, consulten con sus profesores de electrónica.

Les quedan muchas otras cosas por considerar, tales como:

 circuitos impresos de múltiples capas,

 cables planos,

 impedancias características y terminación, etc.

EXPERIMENTACIÓN

Cuando ya se está haciendo un proyecto, EL INGENIERO NO PUEDE IGNORAR ningún aspecto


técnico fundamental en relación a él. Pero, antes de comenzar, a lo mejor uno desconoce muchas cosas.

Cuando algo no se sabe, lo importante es IDENTIFICARLO, y APRENDERLO.

C2-71
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Una parte importantísima del aprendizaje se obtiene de la EXPERIMENTACIÓN. Suponga que usted
quiere determinar, por ejemplo, si un cierto protocolo de comunicación interferirá con la forma como
ha decidido tomar las muestras del conversor análogo a digital. Sin dejar del todo el análisis concienzudo
del problema, lo mejor es que se haga un pequeño experimento ¡ y salga de una vez de dudas !
Recomiendo que hagan UNA CANTIDAD APRECIABLE DE EXPERIMENTOS, ANTES de
hacer la propuesta de sus proyectos, para permitirles conocer con certeza aquellos aspectos que ahora
puedan considerar oscuros.

QUÉ CHIPS USAR

Me ha sorprendido que no tengan acceso electrónico a *algún* manual APROPIADO de circuitos


digitales. Ya que es así, déjenme decirles que TODOS fabricante importante (National Semiconductors,
Fairchild, Analog Devices, Burr Brown, Texas Instruments, etc.) tienen publicados manuales (PDF) que
son joyas, realmente. Además, NO VENDEN su mercancía si no tienen un manual así, y NO
VENDEN tampoco si no tienen NOTAS de Aplicaciones (Application Notes), en donde llevan de la
mano al ingeniero para que use sus chips.
Les recomiendo, en particular, el "LOGIC Pocket Data Book" de la Texas Instruments, que es un
compendio de *TODOS* los chips digitales que se usan actualmente; sus especificaciones técnicas, la
distribución de los terminales, etc.
Les recomiendo bajarlo (6.4 Megabytes) para su uso personal. Les será muy útil.
http://www-s.ti.com/sc/psheets/scyd013/scyd013b.pdf
NOTA: De tanto en tanto parece ser que el webmaster de la Texas se queda sin coger oficio y, por
ocioso, no se le ocurre mejor idea que la de mover ligeramente de sitio los documentos de su 'site', lo
que hace que los links queden obsoletos. Sin embargo, siempre termino localizando el documento
haciendo una búsqueda por la palabra "pocket".
En segundo lugar, valdría la pena que obtuvieran el listado de componentes del almacén, ya que allí
aparecen también los chips más empleados.
Por último, no quiero ni preguntarles si saben lo que es Open Colector, Tri-State, Schmitt Trigger, el
555. ¡Espero que lo sepan! Todos estos temas tienen que dominarlos, para su vida profesional, y para
uno que otro Quiz de Laboratorio.
DOS LINKS FABULOSOS
La suscripción a EDN es GRATUITA: http://www.reed-electronics.com/ednmag/subscribe.asp
El MIT, Massachusetts Institute of Technology, ha publicado:
“Every lecture, every handout, every quiz. All online. For free. Meet the global geeks getting an
MIT education, open source-style.”
*TODAS SUS CLASES, MATERIAL DE LOS PROFESORES, TODOS LOS QUICES, EN
LÍNEA Y GRATIS*. El trabajo de publicación comenzó en septiembre del 2000, con un costo de $10
millones por año durante 10 años (en el 2010 estará disponible todo el material)

C2-72
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Ustedes pueden explorar lo que hay publicado en: http://ocw.mit.edu/index.html


Imagino que saben calibrar qué clase de institución es el MIT. Es el mejor instituto tecnológico del
mundo, y ofrece tan valiosa información, gratis y al alcance de la mano del planeta entero.
No dejen de mirar qué se dicta, por ejemplo, en:
http://ocw.mit.edu/OcwWeb/Electrical-Engineering-and-Computer-Science/indexa.htm

“C”
Si ustedes son como otros grupos, es muy probable que la mayoría maneje el lenguaje “C” ¡ como si
fuera Basic !
Si no entienden claramente:
 expresiones que involucren apuntadores,
 el operador coma,
 el operador ternario,
 los manejos de bits (tal como 1<<0, etc.),
 las estructuras
 las Uniones...
 los bit fields

se les va a hacer muy difícil comprender los programas que a veces les envío, y mucho más, hacer los
suyos propios para el laboratorio.
El C es un lenguaje que permite manejar los recursos de Hardware, tanto a nivel del PC como del
Freescale (antiguo Motorola) excepto que quieran hacerlos en Assembler, lo cual debería estar
prohibido. Un problema de comunicaciones puede llevarnos 10 líneas en C, y 5 páginas en Assembler;
una hora en C y un mes en Assembler...
El siguiente es un pequeño COMPENDIO que escribí para ilustrar 'union, struct y typedef', y unos
ejemplos de uso común. Donde aparece la forma estática xxx.yyy, también puede emplearse un pointer:
ppp->yyy (dinámico)
Revisen, en todo caso, los manuales de C.
Si aun así permanecen en la penumbra, recuerden que no debe insistir en trabajar en assembler sólo
porque desconoce el C. APRENDA C.
También hay un breve "Compendio de BIT FIELDS" que escribí para que vean su definición y
manejo.
En primer lugar, va una estructura definiendo los bits de Status del registro LINE_STATUS del puerto
de comunicaciones en el PC.
Luego va una manera de almacenar los 31 bits de la dirección _Y_ el bit de "valid", en la misma
dirección de memoria, sin tener que ocuparse de andar haciendo máscaras para extraer ese bit y
separarlo de la dirección...

C2-73
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

// COMPENDIO: ESTRUCTURAS Y UNIONES Luis G. Uribe C C11F4 L24A6   
  void main( void ) 
struct s_one {         // Define el formato de la estructura  {                      // USOS: 
   char data[32];      // ... pero no define ninguna variable   
   int  tag[32];       // ... con ese formato... 's_one' es el     Two.data[3] = 'a'; 
};         // ... "tag" o idlentificación de esta estructura.     one.tag[4] = 5; 
     tree.data[5] = 'b'; 
struct  {              // Define el formato de la estructura,     four.tag[2] = 6; 
   char data[32]; // ... SIN tag. Por tanto, no puede utilizarse     cache.four2.tag[2] = 7; 
   int  tag[32];       // ... después, para definir variables.     cache.x[3] = 7; 
} Two;           // Seguramente que "Two" es la única estructura     five.x[2] = '7'; 
                       // ... con este formato!     cache2.tree2.data[4] = 'c'; 
     cache2.x[1] = 'c'; 
struct s_one one;    // Ahora se define aquí una variable (se le   
                 // ... concede ESPACIO), con el formato 's_one'  } 
   
struct  s_tree {     // Esta define AMBAS cosas de una sola vez:   
   char data[32];// ... el formato s_tree y una variable 'tree'   
   int  tag[32];   
} tree;   
   
 
typedef struct{// Define UN TIPO con el formato de la estructura 
 
   char data[32];      // ... pero no define ninguna variable 
   int  tag[32];       // ... con ese formato... 'tfour' es el  // Embeded.c, Luis G. Uribe C., C26Y4 
} tfour;               // ... tipo de esta estructura.  // Example: Transfer Serial received chars to Parallel Port A 
   
tfour four;     // Ahora se define una variable 'four' del tipo  // ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
                // ... 'tfour'  // REVIEW NEXT CODE... 
   
union {       // Union SIN nombre. Solo podrá declararse 'cache'  // Define Register Addresses 
   tfour four2;      // ... como variable de este tipo de union   
   char x[2];  volatile char *RBuf =(char *)0xFFFFFFE0;// Input Serial I/O Port 
} cache;  volatile char *SStat =(char *)0xFFFFFFE2;//Serial I/O Stat. Port 
  char *PAOut        =(char *)0xFFFFFFF1; //Parallel Output A Port 
char *PADir        =(char *)0xFFFFFFF2; // A Port Address 
union ufive{      // Union CON nombre. No reserva espacio; solo 
 
   tfour four2;   // ... define el formato 
#define SReady ( 1 << 0 )   // Bit 0 is ready on SStat Register 
   char x[2]; 
 
}; 
void main( void ) 
 

union ufive five; // Ahora define five como variable consistente     // Init Paralel Port 
                       // ... de la union ufive     *PADir = 0xFF;      // Configure Port A for Output 
   
union {         // Igual a 'cache' (arriba), excepto que se usa     // Transfer Characters 
  struct s_tree tree2;// ESTA LINEA con tree2 que AQUI se define     for(;;) {                    // For Ever 
  char x[2];         while( ( *SStat & SReady ) == 0 ) //Wait for Ready status 
} cache2;             ;    /* empty while */ 
         *PAOut = *RBuf; 
   } 

 
// ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 

C2-74
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

// ... AND COMPARE WITH THE FOLLOWING PROGRAM:  // COMPENDIO DE BIT FIELDS 
  // Luis G. Uribe C., V13F4 
// Define Register Addresses   
  /* OJO CON LAS ALINEACIONES Y LOS 'HUECOS' CUANDO LA INFORMACION 
#define RBuf (volatile char *)0xFFFFFFE0;//Input Serial I/O Port           ALMACENADA NO MIDE EXACTAMENTE UNA PALABRA (int, long... ) */ 
#define SStat (volatile char *)0xFFFFFFE2;//Serial I/O Stat Port   
#define PAOut (char *)0xFFFFFFF1; // Parallel Output A Port  #include <stdio.h> 
#define PADir (char *)0xFFFFFFF2; // A Port Address   
  struct LINE_STATUS { 
#define SReady ( 1 << 0 ) // Bit 0 is ready on SStat Register     unsigned int dta_rdy : 1;   // bit0 
     unsigned int ovr_run : 1;   // bit1 
void main( void )     unsigned int par_err : 1;   // ... 
{     unsigned int frm_err : 1; 
   /* Init Paralel Port */     unsigned int brk_det : 1; 
   *PADir = 0xFF;       /* Configure Port A for Output */     unsigned int xmt_rdy : 1; 
     unsigned int xmt_empty : 1; 
   /* Transfer Characters */     unsigned int no_resp : 1;   // bit7 
   for(;;) {                    // For Ever  } ls;           // variable ls, de tipo struct LINE_STATUS 
       while( ( *SStat & SReady ) == 0 )//Wait for Ready status   
           ;    /* empty while */  struct { 
       *PAOut = *RBuf;     unsigned long address : 31; // bit0 a bit30: TAG 
   }     unsigned long valid   : 1;  // bit31 
}  } tag; 
   
 
void main( void ) 
{                      // USOS: 
 
unsigned int rcv_errs = ls.ovr_run | ls.par_err | ls.frm_err | 
                        ls.brk_det | ls.no_resp; 
 
unsigned long address = 0x7FFFFFFFL; // comienza con 0111... 
tag.address = address; 
 
// Observe que no hay necesidad de hacer máscaras... 
 
tag.valid   = 0; 
printf( "tag bit is %u\n", tag.valid ); 
 
tag.valid = ~tag.valid; 
printf( "tag bit is %u\n", tag.valid ); 
 
printf( "Address is %08lX\n", tag.address ); 
 
tag.address = 0xF0000000L;   // comienza con        1111 0000... 
                             // Observe que imprime 0111 0000 
printf( "Address is %08lX\n", tag.address ); 
 

 

C2-75
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Otras muchas cosas ignoraban del “C” mis exalumnos (¿Y ustedes?):
void rutina( void ) { 
   static int i;   // <<< static: Desconocido por ustedes 
... 

Qué significa "static"?

Una variable definida fuera de cualquier función (main, rutina, etc.,) es VISIBLE por todas las rutinas de
un mismo archivo (Para hacer visible una variable en más de un archivo, hay que categorizarla como
'extern')

Dentro de una rutina, las variables definidas son visibles solamente ahí. Sin embargo, las que se definen
automáticamente (variables "automáticas"), además de ser visibles sólo dentro de la rutina que las
define, también son volátiles, es decir, que desaparecen al retornar la rutina.

¿Qué hacer cuando se requiere que ciertos valores permanezcan de llamada en llamada de una
subrutina?

Podría declararse una variable global, pero eso no es lo que normalmente uno quiere, ya que se trata de
mantener la mayor privacidad posible en las variables (¡ para no parecerse al BASIC !), de tal manera de
disminuir la posibilidad de equivocar el uso de unas variable por otras!

La solución es declarar la variable DENTRO de una rutina, pero con el atributo "static".

Este tipo de variables se usan en rutinas recursivas.

El calificativo "static" se emplea también así:


static int rutina( void ) { 
 ... 

Ahora se le ha aplicado a la definición de una subrutina. El resultado es ESCONDER el nombre de esa


rutina, de tal manera que sea vista SOLO dentro del archivo en el que se la define. Así, podríamos tener
rutinas con el mismo nombre, en otros archivos, sin que hubiera colisiones.

Un error que trajeron a mi atención en un curso pasado: c = c++;

¡ No funciona ! (Es decir, si c comienza en cero, al terminar la instrucción ¡ c CONTINUA en cero !)

Pero SÍ FUNCIONA. Lo malo es que programaron la instrucción equivocada. En primer lugar, porque
para incrementar una variable bastaba con hacer: c++; NO se necesita la asignación!!!

Pero la asignación le está diciendo al compilador que haga lo siguiente:

C2-76
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Tome el valor actual de la expresión C++ (0). Guárdelo momentáneamente en una variable temporal (0).
Incremente C (1 para c++).

Tome el valor temporal (0) y colóquelo en c (c = c++, o sea: c = 0)

Y FIN. (C termina valiendo 0 otra vez) ¿Ven?

Por último. Al programar el microcontroladores, NO OLVIDEN que son MICROs, no Mainframes.


En especial, su RAM es minúscula y ustedes tienen que optimizar su empleo!

PROGRAMAR LA FLASH
Si se quiere guardar información en la Flash (por ejemplo, la correspondiente a la Configuración de su
equipo...): Hay ejemplos en los manuales de los microcontroladores. Es SENCILLÍSIMO.

A ustedes les toca, sin embargo, averiguar cuántas veces puede programarse en su vida útil, el micro. Es
un número FINITO, del orden de los cientos de miles. Está en los manuales.

Supongan que le contrataron un contador de las personas que viajan en el metro. Usted diseña y
construye los equipos, los instala en las entradas de todas las estaciones, y el sistema comienza muy bien.
Es más, el primer día ya pudo entregar la cifra de los pasajeros transportados. Pero el siguiente día se va
la energía eléctrica al final de la jornada, y todos sus contadores se borraron.

Eso es inaceptable. Lo que corresponde es que usted grabe los resultados en FLASH (EEPROM).

Ahora, si entran cien mil personas al día en una estación, en un solo día, o en dos, usted habrá excedido
la especificación del número de veces máximo que puede grabarse la Flash… Necesita otra solución.

INTEN, INTDSB; TRAZAS


Puede ser útil que ENSAYEN (experimenten) a hacer interrupt enable y disable desde C.

Una de las recomendaciones que siempre doy consiste en hacerles ver que, un proyecto que no puede
TRAZARSE, no es factible debuggearlo. Y así no puede ponerse a punto.

Cuando veo proyectos SIN leds que parpadeen anunciando el paso por los diversos estados, o que NO
envían información de STATUS hacia el PC, desde donde, luego, se pueda hacer un análisis (si algo está
funcionando mal, lo que ES SIEMPRE EL CASO), o que no pueden detener y continuar a voluntad...
veo proyectos que no van a funcionar!

Les propongo un lema: Si no lo puede probar, ¡ NI SI QUIERA LO PROGRAME !

Generarse una estrategia de DEBUG es más importante que generar la estrategia de operación del
sistema (bueno; a veces exagero...) Y no debe comenzar a pensar en cómo se va a probar su sistema,
una vez que éste no opera.

C2-77
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

A FAVOR DE “C”
Los electrónicos suelen aprender *un poco* de Assembler (Intel MASM, Motorola WinIDE, PIC
MPLAB...) como parte de algún curso de arquitectura en donde se quieren realzar aspectos tales como:
Conjunto de Instrucciones, Modos de Direccionamiento, lenguaje de máquina, proceso ensamblador,
etc. Luego, al pasar a proyectos complejos, quieren mantenerse trabajando en ASSEMBLER, con la
excusa de “ya manejan la herramienta”, y porque no quieren o no pueden estudiar una nueva.

Miren: Si el Assembler diera beneficios, programas y sistemas tan complejos como Linux, o Windows,
se escribirían en Assembler. ¡ Y SE ESCRIBEN EN C !

Sólo el hecho de que usted termine su proyecto, y que el cliente decida cambiar la plataforma (de
Motorola a Intel, por ejemplo), y que a su software, en C, le baste una recompilada (y algunos ajustes
menores), en tanto que un proyecto escrito en assembler HAYA QUE BOTARLO A LA BASURA Y
COMENZARLO DE NUEVO, sería suficiente argumento para JAMÁS programar en assembler.

Eso sí: Para trabajar en “C”, HAY QUE SABER “C”.

TEST: Si Ud. no entiende TODOS los componentes de c/línea, debe estudiar más C...
1) 
#define defq( in, n ) char q##in[ n ]; que in 
#define initq( in )   in.base = in.put = in.get = q##in;   \ 
                      in.n = 0; in.size = sizeof( q##in ); \ 
                      in.limit = in.base + in.size 
 
#define enq( in, c ) ( in.n >= in.size ? EOF :             \ 
                         ( *in.put ++ = (uchar) c,         \ 
                           ( in.put = in.put >= in.limit ? \ 
                                      in.base : in.put     \ 
                           ),                              \ 
                           in.n ++, c                      \ 
                         )                                 \ 
                     ) 
 
2) 
#ifdef COM2 
 #define BASE   ( 0x2F8 ) /* 0x2F8 para COM2 */ 
#else // COM1 (default) 
 #define BASE   ( 0x3F8 ) /* 0x3F8 para COM1 */ 
#endif 
 
#define RCV_DATA  ( BASE + 0 ) 
#define XMT_DATA  ( BASE + 0 ) 
 
/* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */ 
/*  Interrupt Enable Register and Bits  */ 
 
#define INT_ENABLE   ( BASE + 1 ) 
#define RCV_INT  ( 1 << 0 ) 
#define XMT_INT  ( 1 << 1 ) 
#define STAT_INT   ( 1 << 2 ) 
#define MDM_INT ( 1 << 3 ) 
 
#define pic_inten(vec) ( outp( MASK_PORT, inp( MASK_PORT )   \ 
                        & ~ ( 1 << vec ) ) ) 

C2-78
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

"LA PESADILLA ¿HARDWARE O SOFTWARE?"


¿Saben qué es una pesadilla?

Es poner a funcionar un programa sobre una plataforma de hardware de la cual ni siquiera se sabe si
trabaja bien, o si está intermitente... Cuando algo falla, usted nunca sabrá si es un problema con el
programa, o con el hardware.

Los proyectos del estilo de un Scada, o una Estación Meteorológica, suelen realizarse al menos por dos
grupos de trabajo diferentes en las compañías: El de Hardware y el de Software. (Pueden haber muchos
más grupos: Partes metalmecánicas, gabinetes, cableado, instalación, pruebas, integración de hardware,
diseño mecánico, pinturas; software básico, sistema operativo, programas de aplicaciones, integración de
software... integración de sistemas, "commissioning"… son solo algunos ejemplos)

El grupo de Hardware tiene que diseñar una tarjeta con determinadas características, y que obedezca
ciertas restricciones.

El grupo de Software, parte de las especificaciones del Hardware y va produciendo los programas que
adquieren información, la filtran, la manipulan, obtienen valores diversos, la almacenan y la transmiten.

En algún momento el primer grupo anuncia que el Hardware está listo, y se lo entrega a la gente de
programación para la integración final. La gente de Software no ha podido probar sus programas,
porque no tenían el hardware, hasta ahora... Sólo los ha simulado.

Muchas veces la gente de Hardware da por concluida su actividad ("tiene un producto") en el momento
en que puede encender el equipo sin que se salten los fusibles, algunos leds parpadean y a lo mejor
pueden hacerse algunas conversiones de análogo a digital. Aun cuando el procedimiento de aceptación
de Hardware sea mucho más riguroso que lo que aquí esbozo, y se incluyan programas de prueba y
calibración, puede no ser suficiente...

Ningún departamento de Software suele aceptar por buena, la palabra del departamento de Hardware
cuando éste dice que la tarjeta recién diseñada funciona a la perfección. SERÍA SU RUINA. El grupo de
Hardware tiene que aplicar una serie de pruebas que garanticen que 1) la tarjeta está bien diseñada y 2)
que está bien manufacturada (operativa)

El procedimiento varía de un caso al otro, pero siempre la gente de Hardware tiene que disponer de
Programas de Diagnóstico de Hardware para sus productos. Estos programas tienen que ser lo
suficientemente sencillos, como para garantizar que están buenos mediante simple inspección. (Si son
muy complicados y fallan, volvemos a lo mismo: ¿Fue el hardware o el programa de diagnóstico?
Cuando trabajé en DEC, no era nada raro encontrar que muchos diagnósticos fallaban)

Hay comúnmente dos clases de Programas de Diagnóstico de Hardware: Programas individuales que
prueban cada pieza del hardware y determina si está operativa o no, según especificaciones.
Normalmente un programa por cada pieza (uno para el conversor A/D, otro para las comunicaciones,
uno para la memoria, etc.). Cuando el subsistema es muy complejo, puede haber varios programas
para la misma unidad: El de la verificación del almacenamiento, el de aseguramiento de las lecturas, etc.

C2-79
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

La segunda clase de Diagnósticos son los System Exercisers, que verifican la integridad del sistema
cuando se le añaden diversas unidades de hardware. Ellos garantizan que, unidades probadas
individualmente como operativas, también trabajan armónicamente en conjunto (muchas veces no
ocurre así, y al querer hacer funcionar ciertas partes del conversor A/D, interfiere con la memoria, etc.)

Recién cuando se ha probado la operatividad de cada pieza de hardware y se está conforme, y se ha


verificado que las interrelaciones entre subsistemas son armónicas y no se entorpecen unas unidades
con otras, es cuando pueden comenzar las pruebas del Software propiamente dicho.

Ustedes que, además, trabajan en un soporte delicado (Protoboard, baquelita), en donde siempre están
bajo la posibilidad de que algo se suelte y el hardware no trabaje, tienen que planificar una batería de
programas de Diagnóstico que les permitan RÁPIDAMENTE estar seguros de que su hardware
opera perfectamente.

PREMISA DE URIBE:

No puede "debuggearse" el hardware y el software al mismo tiempo...


Un tercer tipo de programas usados en manufactura, además de los ejercitadores y los de diagnóstico,
son por ejemplo los de Calibración. Ellos permiten fácilmente ajustar los amplificadores y otros
dispositivos que requieran, caso por caso, determinados toques a fin de cubrir el rango completo, o que
ciertos valores de entrada produzcan unas bien conocidas cifras de salida, etc. Son "utilitarios".

Dentro de su proyecto usted debe identificar, además de las cosas obvias en que ya había pensado, las
herramientas de diagnóstico que le ayudarán a ponerlo a punto. No hacerlo es garantía de que su
sistema no funcionará adecuadamente.

Les recuerdo:

Un proyecto que no puede TRAZARSE, no puede "debuggearse".


Y así no puede ponerse a punto…
Generar una estrategia de DEBUGGING es TAN importante como generar la de operación del
sistema. Y no debe comenzar a pensar en cómo se va a probar su sistema, una vez que éste no
funcione.

"PERDER LOS ARCHIVOS"


Las excusas más socorridas de los últimos tiempos, en los proyectos, son:

 "No puedo leer el floppy/Pendrive con mi proyecto"

 "Un virus dañó el disco duro, con todo y proyecto"

C2-80
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Ni en el laboratorio, y menos en su práctica profesional, pueden usar como excusa que se les dañó la PC
y que por lo tanto los meses de esfuerzo dedicados al proyecto se fueron por el desaguadero... Si se le
presenta una situación así, solo demostrará IRRESPONSABILIDAD de su parte para con el trabajo.

En esta época, es su obligación tener acumuladas copias de respaldo INCREMENTAL, que les
permitan SIEMPRE devolverse a una situación en la cual Uds. (y la compañía) pierden a lo sumo unas
cuantas horas de trabajo.

Recuerden: INCREMENTAL BACKUP.

En la época del PKZIP/WinZip/WinRAR y similares, y del correo electrónico bueno, bonito y barato
(GMail), en donde ustedes pueden enviarse a sí mismos correos periódicos con las copia incrementales
de respaldo, NO HAY DERECHO a que se pierda un proyecto, o la calificación de un laboratorio,
porque se les dañó el disco...

Hay también sitios en el Internet donde le regalan espacio en disco (que comprimido alcanza cada uno
para guardar muchos archivos)

Cuando ha tomado precauciones, ¡ hasta desde un Cibercafé puede recuperar su información !

NO LO OLVIDE:

Una Estrategia de Respaldo es fundamental en el desarrollo de cualquier proyecto


Están advertidos: Excusas de tal naturaleza son inaceptables, ahora y luego. En la universidad, proyecto
borrado es proyecto reprobado. En la vida como ingeniero implica, al menos, un despido.

Además, en la actividad profesional esta advertencia ¡ no se limita a los programas ! Todo lo que esté en
medio magnético debe respaldarse, como:  los circuitos impresos (Orcad),  diseños metalmecánicos
(Autocad),  toda la documentación del cliente y la interna (MSWord, Excel, MSProject)

CITAS CITABLES
"In theory, there is not much difference between theory and practice... But, in practice, there is!", Yogi Berra.

"Your Project isn't going to end… until it's completed!"

"You can observe a lot just by watching"

"You give 100 percent in the first half of the Project, and if that isn't enough, in the second half you give what's left"

"The most important things in life are that that are least important"

"When you come to a fork in the road, take it"

C2-81
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

 PROYECTOS II
Algunos ejemplos de Proyectos en el Laboratorio

DOCUMENTACIÓN

V
OY a presentar como ejemplo, dos desarrollos típicos del Laboratorio de Proyectos. Los
requisitos van más adelante; incluiré por el momento la identificación de la información que
los estudiantes deben entregar como parte del proyecto. También es indispensable, en el
laboratorio o en su vida profesional, llevar una Bitácora.

“ESTACIÓN METEOROLÓGICA DE ALTAS PRESTACIONES”

IDEAS PARA MANUALES DEL PROYECTO

 Se deben construir dos escritos, uno a manera de manual del producto y otro un informe
técnico del mismo.

 Ambos tipos de escritos deben venir en papel impreso

MANUAL DE USO E INSTALACIÓN DEL PROTOTIPO

 Título.

 Uso o descripción del mismo en forma breve.

 Descripción de cómo trabaja de manera directa y corta.

 Listado con las especificaciones y estándares que cumple.

 Descripción de la instalación: Requerimientos de potencia y el entorno físico.

 Seguridad industrial, del equipo y las personas.

 Lo anterior puede realizar se a manera de tríptico o folletín.

C2-82
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

MANUAL TÉCNICO

 Carátula con título del proyecto  Diagrama en bloques


particular desarrollado.
 Diagrama eléctrico
 Índice del manual incluyendo la
referencia a los gráficos y anexos.  Descripción de lo que hace (cómo
trabaja cada etapa)
 Breve descripción del proyecto.
 Normas que cumple, en caso de que
 Sobre el proyecto desarrollado: aplique alguna

 Diagrama de flujo

EXPLICACIÓN

 Describa cada bloque de manera breve e independiente. Coloque los circuitos desarrollados,
descríbalos de manera concisa y directa. En el caso de los programas, solo coloque el diagrama
de flujo del algoritmo y coméntelo. Los detalles de programación y listados del programa deben
ir en un anexo claramente indicado y referenciado desde aquí.

 Comente los problemas encontrados durante el desarrollo y la solución adoptada. Qué fallas
aun persisten y como cree puedan corregirse.

CONCLUSIÓN

 Experticias desarrolladas durante el  Costos finales gastados en el hardware


transcurso del laboratorio. y el número de horas/hombre que
realmente le dedicó.
 Mejoras posibles al mismo.

BIBLIOGRAFÍA CONSULTADA Y SITIOS WEB EN LOS QUE SE


SOPORTÓ

ANEXOS

 Estos deben clasificarse e indicarse en forma clara.

 Coloque aquí de manera detallada los circuitos empleados, que deben estar claramente
identificados y brevemente comentados en cuanto a su funcionamiento.

 Los flujos de los programas en CodeWarrior y LabView deben estar a manera de bloques y su
código identificado con el bloque respectivo y comentado adecuadamente.

C2-83
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

EXTRAS

Deben añadir lo indicado en el llamado “Avance Inteligente”:

 ¿Usará fuente-UPS-Batería Solar o pilas?

 Diseño de la maqueta virtual (indicar el tamaño)

 Fusibles: ¿Qué clase y de qué valor?

 A futuro, ¿pensó en la facilidad del ensamblaje? Comentar.

 Cómo solucionará la tolerancia de los componentes por unidad - por lote?

 ¿Requiere indicación de “low-battery”?

 ¿Tiene recuperación automática en caso de fallas? (watch-dog)

 ¿Qué harán con la basura de la producción?

 ¿Existe reciclaje (producción)?

 ¿Cómo arreglarán los daños, a nivel de componente o cambiando tarjetas? Comente.

 ¿Qué tiempo de garantía darán? ¿En qué modalidad? (¿deben traer el equipo a su taller; o
ustedes irán al sitio a repararlo?

 “Isla de trabajo” mínima para fabricar. “Isla de trabajo” mínima para instalar.

 Expansión a futuro: ¿Pueden realizar otras mediciones/actividades?

SCADA
INTRODUCCIÓN

Un “Supervisory Control and Data Acquisition (SCADA) SYSTEM” está destinado a permitir al
personal de operación, la vigilancia y el gobierno de localidades industriales lejanas, que pueden ser de
muy variada naturaleza, como edificios, viviendas, subestaciones eléctricas, instalaciones industriales y
manufactureras, pozos petroleros y similares.

A diferencia de otros sistemas, un SCADA funciona primordialmente “a lazo abierto”, siendo


indispensable la actividad de un operador humano para emitir las órdenes que se ejecutan, finalmente,
en el proceso. Lo anterior, sin demérito de algunas actividades minoritarias que pueden operar a “lazo
cerrado”, tanto localmente en las instalaciones remotas (PLC, Programmable Local Controller), como a
través de Estaciones de Aplicaciones (PCs). Pero la responsabilidad de las acciones y decisiones reposa,
eminentemente, en una persona.

C2-84
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

CONSTITUCIÓN

Un SCADA se conforma mediante 3 subsistemas: La Estación Maestra, las Unidades Terminales


Remotas o RTU y el sistema de comunicaciones que los interconecta. Las RTU, a su vez, podrían ser
Maestras de otras unidades que jerárquicamente se encuentren debajo, llamadas RTU Esclavas.

La Estación Maestra tiene como función hacer un barrido en el tiempo, de los valores que adquieren en
el campo las RTU; mantiene archivos históricos con toda esa información; la evalúa y valida contra
diversos límites que impone el usuario y, en caso de violaciones, genera alarmas, auditivas y visuales,
para alertar de condiciones anómalas al operador. Permite al encargado tomar acciones para controlar
las instalaciones distantes, cerrando o abriendo, a lo lejos, válvulas y solenoides, emitiendo consignas a
los PLC remotos, etc.

La RTU se diseña para estar atenta a las solicitudes periódicas de información que hace la Maestra, y
cuando se lo ordenan, envía los valores analógicos leídos del campo, que con mucha probabilidad
provienen de “transductores”, esos dispositivos que convierten a información electrónica, parámetros
físicos tales como temperaturas, flujos, presiones, posiciones, etc. Es posible, de igual manera, que la
RTU produzca valores “calculados”; este es el caso, por ejemplo, cuando la misma remota lee señales
eléctricas instantáneas de corriente alterna y produce valores RMS para enviarlos al “Despacho” o
Centro de Control (CC). Las RTU también leen valores digitales, procedentes de interruptores o
contactos, cerrados o abiertos, que representan posiciones tales como puerta cerrada o abierta,
dispositivo operativo o inoperativo, etc.

Por último, las RTU permiten del operador accionar equipos a distancia, para abrir interruptores, o
cerrarlos, activar o desactivar unidades en la planta, etc. Algunas RTU pueden a veces entregar valores
analógicos a unidades que en el campo pudieran necesitarlo; tal es el caso de valores “consigna” que se
proporcionan a los PLC y otros subsistemas de control local instalados en el campo.

El medio de comunicaciones que permite la interacción entre Maestra y Remotas puede ser organizado
alrededor de una variedad de topologías, como líneas telefónicas, dedicadas o discadas, fibra óptica,
radio, Internet, etc. Uno o varios “protocolos”, o disciplinas de intercambio, encapsulan la información
que se transfiere de un lugar a otro, garantizando que llegue al destino correcto sin errores. Muchos
protocolos existen o persisten en este tipo de sistemas que van cruzando ya los 40 años desde sus
orígenes, siendo algunos de los más renombrados el Modbus (Modicon), DNP (Harris), Asea (ABB),
Sinaut (Siemens), Fieldbus, y los venerables Honeywel 7024 y Conitel 2020, entre una multitud.

ESPECIFICACIONES DEL PROYECTO

Diseñar un pequeño SCADA conformado por dos (2) RTUs operando en el microprocesador Intel x86
(PC) bajo protocolo Modbus, y una (1) Estación Maestra en un PC, interconectados los tres mediante
los puertos seriales de comunicación.

Uno de los dos integrantes de cada grupo será el encargado del diseño y puesta en marcha de la Maestra,
en tanto que el segundo participante asumirá iguales responsabilidades con las Remotas. La evaluación
será individual. En caso de que la Maestra, o la RTU, no funcionen, se hará la entrega empleando
software comercial.

C2-85
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

ESTACIÓN MAESTRA

El software de la Estación Maestra correrá en el PC y deberá tener como mínimo los siguientes
subsistemas:

 Adquisición de Datos

 Presentación de Información

 Generación y Procesamiento de Alarmas

 Control Remoto

 Comunicación con las RTU del campo

Quedan excluidas muchas funciones comunes, como el manejo histórico de información, generación de
reportes, operación redundante (hot stand-by), estadísticas de comunicaciones, editor de base de datos,
configurador del sistema, generador de despliegues, y aplicaciones tales como control mediante
“recetas”, control estadístico, control automático, generación de secuencias coordinadas, etc., las que se
mencionan solo para que tengan idea de lo que se ofrece en este mercado.

SUBSISTEMA DE ADQUISICIÓN DE DATOS

Debe recabar la información del campo, de manera secuencial, empleando al máximo la funcionalidad
del protocolo Modbus, que se verá reducida a los valores que la RTU puede manejar y que serán
definidos a continuación. El tiempo entre barrido y barrido lo define el diseñador, pero deberá tener
una frecuencia suficientemente alta, para permitir evaluar prontamente las modificaciones que se
produzcan en los valores del campo. Si por alguna razón la RTU deja de responder, se deberá esperar
un tiempo máximo antes de indicar visualmente la situación de “Falla de Comunicaciones”, caso en el
cual el Subsistema de Presentación de Información debería proporcionar algún valor convenido, como
el promedio histórico, o el último valor leído, identificándolo claramente ante los ojos del operador para
que no confunda valores reales con cantidades supuestas.

SUBSISTEMA DE PRESENTACIÓN DE INFORMACIÓN

Debe mantener actualizados en la pantalla los valores que se van leyendo. Cuando se trata de variables
analógicas hay normalmente por lo menos dos clases de valores: “raw” o crudos, que son simplemente
los datos numéricos que se transmiten; en nuestro caso serían números de 0 a 255 (conversor analógico
a digital de 8 bits), correspondiendo a valores de entre 0 y 5 voltios; y los valores de Ingeniería, que
representan unidades físicas como temperaturas, presiones o voltajes, y que se obtienen manipulando
matemáticamente las cantidades “raw”. Para nuestro caso será preferible presentar valores de Ingeniería,
pero las conversiones serán muy simples, tales como Val_Ing = ‘Val_0 + raw*K’.

La información digital debe presentarse adecuadamente, de manera que pueda distinguirse con rapidez
el estado de cada interruptor del campo. Además de un símbolo apropiado (O y X, para Abierto y
Cerrado), deberá agregársele color. En la industria eléctrica se estila que Rojo sea para un circuito

C2-86
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

energizado, y Verde para abierto (esto es todo lo contrario a la convención de los ingenieros
electrónicos, que suelen indicar con Verde una señal activa, correcta, y con Rojo los errores!)

Se excluyen en nuestro proyecto funciones tales como la presentación por pantalla de gráficos de
tendencia, o de secciones de valores históricos (los que se mencionan solo para que tengan idea de lo
que se ofrece en el mercado).

GENERACIÓN Y PROCESAMIENTO DE ALARMAS

Cada valor presentado debe compararse con límites superiores e inferiores, y en caso de excederlos se
alertará al operador mediante la corneta del PC y empleando en la pantalla algún sistema de mensaje,
por ejemplo escribiendo una línea en la parte inferior de la pantalla, y señalando de alguna forma el valor
problemático (con colores, asteriscos, parpadeos, etc.)

Se utilizarán para las señales continuas (AI, Analog Inputs) los indicadores Hi, Lo y HiHi y LoLo (alto,
alto alto, bajo y bajo bajo), con lo cual se definen la región normal, una zona de alerta y una de alarma.
El diseñador del sistema definirá los valores de las alertas (Hi y Lo) y de las alarmas (HiHi y LoLo).

CONTROL REMOTO

Debe existir la capacidad para que el operador ordene el cierre o apertura de un relé a través de una
salida digital (DO, Digital Output) activada por la RTU, y que se simulará convenientemente en la RTU.

Se excluyen en nuestro proyecto funciones tales como la de tener un contacto para ordenar la apertura
(trip) y otro distinto para el cierre (close), lo que es la práctica más común (Se menciona para que tengan
idea de lo que se ofrece en el mercado).

COMUNICACIÓN CON LAS RTU DEL CAMPO

Se empleará como capa física (Physical Layer) el sistema de comunicación serial del PC, y como Capa de
Red (Data Link Layer), un subconjunto apropiado del protocolo Modbus RTU (funciones de lectura de
analógicos, lectura de “coils” o digitales, y activación y desactivación de “coils” para el control). Debe
incluirse la funcionalidad de CRC (Cyclic Redundancy Check) o LRC (Longitudinal Redundancy
Check), definidos por el protocolo según sea el caso (Modbus–RTU o Modbus–ASCII
respectivamente). La velocidad no debe ser motivo de preocupación en el desarrollo de este sistema,
por lo cual bien puede trabajarse a 1200 bps, lo que además resulta corriente en la realidad.

El Modbus tiene dos modalidades de operación, conocidas como Modbus–RTU, y el Modbus–ASCII.


La primera requiere el empleo de una función polinómica para el cálculo del CRC (Cyclic Redundancy
Check). La segunda precisa una simple verificación (LRC: Longitudinal Redundancy Check) que
corresponde a los ExOr de cada uno de los bytes del mensaje. El método más empleado es el Modbus
Binario y su procedimiento de verificación es el CRC. (Para ambos sistemas, CRC y LRC, refiérase a la
documentación oficial del Modbus, publicada en Modulo7)

Se excluyen en este proyecto las demás funciones definidas por el protocolo (que ustedes deberán
revisar, para informarse)

C2-87
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Hay que tener especial precaución en el diseño para no caer en situaciones de descoordinación, en las
cuales alguno de los dos extremos pierde un símbolo o byte, y ahora nunca jamás se sincronicen (incluir
Watch-dogs, Timers...)
RTU
El software de la RTU correrá en el microprocesador Intel x86 (PC) y deberá tener los siguientes
subsistemas:
Adquisición de Datos Analógicos (2 AI)
Adquisición de Datos Digitales (8 DI)
Control (1 DO)
Comunicación con la Estación Maestra
Quedan excluidas en nuestro proyecto muchas funciones comunes, como el envío espontáneo de
información a la Maestra SCADA, ya que no está soportado por el Modbus. De esta manera, la RTU es
una unidad verdaderamente esclava o supeditada. Tampoco se elaboran valores calculados; simplemente
se envían los leídos (no se está simulando, por ejemplo, la conversión de señales sinusoidales a RMS).
Como tampoco se pide que la RTU tenga ninguna funcionalidad de control local, tipo PLC, resulta
innecesario leer tanto valores digitales como analógicos “antes” de que llegue la solicitud respectiva por
parte de la Maestra. Así que el funcionamiento es bastante secuencial: Llega una solicitud, se la analiza,
se procesa dicha solicitud (leyendo, por ejemplo, los valores analógicos), se elabora la trama de
transmisión y se envía de vuelta la información correspondiente.
Cada RTU dentro del sistema SCADA debe poseer una dirección única. Utilice el número del mesón
como la dirección.
ADQUISICIÓN DE DATOS ANALÓGICOS (AI)
Los valores considerados serán simplemente dos (2) analógicos de 0 a 5 voltios, y las señales que en la
vida real provendrían de los transductores se simularán mediante el teclado, para permitir la prueba de
concepto. El tipo de señales simuladas varía muy lentamente, como lo haría por ejemplo la temperatura
de una planta, y a este tipo de señales se las conoce como señales DC (aunque en realidad sí varían).
Se excluye la adquisición de señales AC, que requerirían que la RTU sí estuviera trabajando
permanentemente en el cálculo de, por ejemplo, los valores RMS, o los componentes armónicos, etc.
ADQUISICIÓN DE DATOS DIGITALES (DI)
Los valores considerados serán solo 8 bits de un puerto elegido por el diseñador, y las señales de prueba
se alimentarán mediante 7 teclas para permitir la prueba del concepto (para el octavo bit, vea el próximo
párrafo).
Uno de los 8 bits digitales de entrada siempre se conectar de alguna manera a los relés de control, de tal
manera que la Unidad Maestra tenga una realimentación en cuanto al estado de esos dispositivos. Así,

C2-88
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

por ejemplo, si se manda a abrir un relé, la siguiente lectura de digitales enviará a la Maestra el valor del
contacto, indicándole al operador si en realidad se abrió o no el interruptor. Igualmente ocurre al
ordenarse un cierre. De lo contrario el operador trabajaría a ciegas, sin saber si sus órdenes se están en
realidad realizando o no.

Se excluye en nuestro proyecto la adquisición de señales digitales con procesamiento, como por ejemplo
el que se requeriría para “marcarlas” con una etiqueta que indicara el instante en el que ocurrió una
activación (cierre o apertura: Secuenciadores de Eventos, SOE). Se excluyen así mismo los Digitales con
Memoria, que recuerdan si un contacto cambió entre barridos (“scans”) de la maestra; (esto funcionaría
así: Si un contacto está reportado como cerrado en la Estación Maestra, y ocurre que se abre, pero antes
de llegar la solicitud de su lectura, vuelve a cerrarse –caso, por ejemplo, de una puerta, cuando la
Maestra requiere la información de los digitales el valor enviado será cerrado, que es como está ahora, y
en el Centro de Control no se habrán enterado de que en el ínterin hubo algún cambio. Esto se
menciona para que sepan lo que se ofrece en este mercado).

CONTROL (DO)

Debe incluirse la simulación de al menos un relé mediante el cual pueda materializarse una función de
control remoto, por parte del operador.

En un equipo real debe diseñarse muy bien el circuito de manejo del relé, a fin de evitar que los picos
inversos producidos por su bobina dañen permanentemente el resto de la electrónica.

Se excluyen en nuestro proyecto funciones tales como la de autoretención, que permitirían mantener el
estado (abierto o cerrado) de un relé en caso de falla de la alimentación eléctrica para la RTU (lo que se
ofrece por lo común en este mercado).

COMUNICACIÓN CON LA ESTACIÓN MAESTRA

Se empleará como capa física (Physical Layer) el sistema de comunicación serial del PC y como Capa de
Red (Data Link Layer), un subconjunto apropiado del protocolo Modbus RTU (funciones de lectura de
analógicos, lectura de “coils” o digitales, y activación y desactivación de “coils” para el control). Debe
incluirse la funcionalidad de CRC (Cyclic Redundancy Check) o LRC (Longitudinal Redundancy
Check), definidos por el protocolo según sea el caso (Modbus–RTU o Modbus–Ascii respectivamente).
Puede trabajarse a 1200 bps.

El Modbus debe ser RTU o ASCII, dependiendo de lo que se seleccionó para la Unidad Maestra y el
cálculo del campo de verificación debe ser el que corresponda: CRC o LRC.

Se excluyen en nuestro proyecto las demás funciones definidas por el protocolo (que deberán revisar,
para informarse)

Hay que tener especial precaución para no caer en situaciones de descoordinación, en las cuales alguno
de los dos extremos pierde un símbolo o byte, y ahora nunca jamás se sincronicen (Watch-dogs,
Timers...).

C2-89
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

ANTEPROYECTO

El Anteproyecto debe incluir todas las definiciones que a cada uno correspondan y todas las
funcionalidades, según se ha indicado en este documento, y que son, entre otras:

 Qué modalidad del Modbus se escogió (RTU, ASCII)


 Qué señales están simulando, y qué rangos tendrán sus valores
 Ecuaciones que usarán para convertir a unidades de ingeniería
 Tiempo entre barridos
 Qué funciones (3) del Modbus estarán usando
 Qué acciones tomará para evitar el “congelamiento” en las comunicaciones
 Qué valores se proporcionarán en caso de perder la telemedida (“supuestos”)
 Cómo diferenciará en la pantalla los valores leídos de los valores “supuestos”
 De qué manera indicará los valores analógicos (barras horizontales, verticales, relojes, etc.)
 Cómo mostrará las zonas normal, alerta (baja y alta), alarma (baja y alta) (Se sugieren colores
Verde, Amarillo y Rojo)
 Cómo se identificarán en la corneta del PC las alertas y las alarmas
 Cómo se “reconoce” (o acepta) una alarma, para que cesen los parpadeos y termine el sonido
por la corneta
 Cómo serán los despliegues de la información digital; cómo representará los ceros y cómo los
unos (qué símbolos y qué colores empleará)
 Cómo mostrará la simulación del Control
 Asegúrese de incluir la realimentación automática del control, sobre uno de los 8 bits de entrada
digital

El Proyecto debe incluir todas las funcionalidades y definiciones hechas en el Anteproyecto (itemizadas
arriba).

El Software y la documentación deben incluir, y en las fuentes quedar resaltadas, todas las
funcionalidades y definiciones hechas en el Anteproyecto. Además, debe suministrarse en un floppy el
listado de los programas, comentados, modulares, en donde se destaquen:

 La rutina principal  Subsistema de transmisión y recepción


 Los manejos de colas  Simulaciones
 Los manejos de interrupciones  Presentación de información
 Definición de variables  Generación y procesamiento de
 Inicializaciones alarmas
 Manejo de error  Control remoto
 Cálculos de CRC/LRC  etc.

C2-90
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

DATA LOGGER
TÍTULO DEL PROYECTO

Diseño y construcción de un “Sistema de adquisición de datos, portátil, con capacidad de comunicación


serial y almacenamiento local”.

CONTRATANTE DEL PROYECTO

La empresa contratante desea el diseño de prototipos de desarrollo, para posteriormente construir uno
industrial. En este contrato no se llegara a la implantación del prototipo industrial. Se desea el diseño y
entrega del primero, para analizarlo en el laboratorio.

OBJETIVOS DEL PROYECTO

Los objetivos del proyecto a realizar por los Ingenieros de Desarrollo son:

 Diseño y montaje de un Sistema de Adquisición de Datos Portátil con capacidades de


comunicación con una estación central.
 Los subsistemas de Adquisición, Acondicionamiento, Alimentación y Aplicación Final, deben
contar con las características funcionales mínimas indicadas en el siguiente apartado.
 Deberá entregar la lista de componentes del prototipo: Número de parte, descripción (incluye:
Si es montaje convencional o de superficie, características especiales como temperatura de
operación, voltaje, etc.), proveedor, "third party", cantidad requerida, mínimo lote por pedir,
precio unitario, precio total, tiempo de entrega, comentarios (back log, descontinuado, si hay
reemplazo), así como todos los esquemáticos con sus informes explicativos.
 Deberá entregar una Bitácora de Trabajo donde recoja todas y cada una de las ideas,
documentación, copias de manuales empleados, problemas encontrados con sus soluciones,
planteamientos efectuados en el Desarrollo del Sistema de Adquisición, ideas desechadas, etc.
La Bitácora es su diario de trabajo.
 Deberá entregar manuales técnicos de operación, así como un informe detallado de explicación
de los esquemáticos.

DESCRIPCIÓN DE LOS EQUIPOS A SER DESARROLLADOS

CARACTERÍSTICAS FUNCIONALES MÍNIMAS DEL SISTEMA

El subsistema de Adquisición de datos debe contar con las siguientes características mínimas:

 Debe ser un sistema basado en microprocesadores.

 Debe entregarse el diseño del impreso en EAGLE, ORCAD, etc.

 El subsistema o tarjeta de adquisición podrá usarse en tres modos principales:

C2-91
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

 Modo de adquisición “Independiente”, en el cual el sistema funciona parecido a como lo


hace un “Data Logger”. Adquiere información por un período de tiempo fijo y a una tasa
de muestreo fija, esos datos son guardados para su posterior transmisión a un Sistema
Central (basado en PC podría ser). PROTOCOLO: La comunicación con el PC se
establecerá mediante un protocolo simple, del tipo de la familia XModem (XModem,
YModem, ZModem), o un subconjunto apropiado del MODBUS.
 Modo de adquisición “En – línea”, en el cual se adquiere un dato y se transmite a un PC,
donde el dato es visualizado. PROTOCOLO: La comunicación con el PC se establecerá
sin protocolo; el "Sistema de adquisición de datos portátil simplemente enviará, de manera
permanente, los datos adquiridos, codificados en ASCII, terminados en caracteres CR, LF.
Es responsabilidad del PC leer convenientemente la información recibida.
 Modo de adquisición “Por ráfagas”, en el cual el sistema adquiere datos por un período de
tiempo finito y a tasa definida, luego bajo petición de un sistema central transmite lo
adquirido y espera una nueva orden de adquisición. PROTOCOLO: La comunicación con
el PC se establecerá mediante el mismo protocolo empleado en la opción 1) arriba (familia
XModem).
Nota: La escogencia de uno de los 3 modos principales se hará mediante un selector localizado en el
panel frontal del instrumento (no será una operación de comando remoto, originada desde el PC).

 El sistema deberá ser capaz de adquirir, mínimo, dos señales analógicas de ±5 Voltios. Las
señales deben ser leídas en modo diferencial o en modo unipolar. Indique la precisión de su
sistema de adquisición, siempre que se aproveche todo el rango dinámico de la entrada.
 El diseño debe incluir la definición de la tasa máxima de muestreo que Usted puede ofrecer en
cada uno de los distintos modos de operación; deberá tomar en cuenta la existencia de memoria
adicional, que Usted deberá incluir en su diseño. Deberá indicarse también el tiempo máximo
de adquisición.
 El subsistema de adquisición también debe ser capaz de manejar 8 señales digitales,
programables como entradas o salidas digitales.
 El subsistema de adquisición deberá incorporar el manejo de memoria adicional a la interna del
microprocesador, que será usada para el almacenamiento temporal de la data adquirida.
 El subsistema de adquisición debe contar con un sistema de comunicación serial con una
estación central, basada en PC. La comunicación debe poder realizarse hasta 115.2 kbps.
El subsistema de Acondicionamiento consistirá en la electrónica adecuada para el manejo de dos señales
analógicas, de las cuales Usted debe definir sus características. Usted puede proponer dos tipos de señal
que desee procesar, o puede elegirlas de la lista indicada más abajo. El diseño del módulo de
acondicionamiento tomará en cuenta:
 La salida típica de los sensores o características de las señales a medir (por ejemplo, lazos de
corriente, voltajes DC ó AC, etc.)
 La entrada máxima de la etapa de adquisición, sin despreciar la resolución del sistema.
 Medidas de anti – aliasing.

C2-92
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Usted puede proponer cualquier par de señales a ser adquiridas, pero sólo a modo ilustrativo indicamos
una lista de posibles tipos de señales a ser procesadas:

 Temperatura.  Strain gauges (señales provenientes de


 Lazos de corriente (0 – 20 mA). puentes resistivos).
 Micrófono.  Potencia eléctrica.
 Nivel de líquidos.  Factor de potencia y armónicos.
 Voltajes DC (Salidas de fuentes DC  Caracterización de una fuente DC.
con sus características: Rizado, ruido,  Frecuencia.
etc.).  Presión.
 Voltajes AC.  Caracterización y pruebas de
 Corriente DC. transformadores.
 Corriente AC.

Debe entregarse el impreso de esta tarjeta diseñado en EAGLE, ORCAD, etc.


SUBSISTEMA DE APLICACIÓN FINAL

Es un sistema totalmente libre que Usted debe diseñar y proponer. Es un requisito de la empresa que la
aplicación final sea desarrollada bajo LABVIEW. Por supuesto su aplicación dependerá en parte de la
señal que desee procesar. Sólo a modo ilustrativo exponemos algunos sistemas posibles, que de ninguna
forma deben coartar su libertad de proponer aplicaciones diferentes.
Algunos ejemplos de aplicaciones podrían ser:

 Analizador de respuesta al impulso.  Sistema de pruebas de


 Analizador de espectro. transformadores.
 Espectrogramas.  Sistema de supervisión de calidad del
 Analizador de Bode. servicio eléctrico.
 Sistema supervisorio sencillo.  Osciloscopio Digital
 Analizador de voz.
ASPECTOS EXTRAS QUE DEBEN CONSIDERAR

 Calidad del diseño del sistema de alimentación y carga de baterías junto con la calidad del diseño
del sistema usando componentes de bajo consumo.
 Diseño de caja (sólo planos y modelo virtual). El sellamiento será de tipo NEMA 4X
 Consideraciones de aislamiento de las señales analógicas.
 Diseño de un protocolo de pruebas para el sistema y los respectivos sub – sistemas.
 Control y programación de ganancias y offset en la etapa de acondicionamiento.
 Generación de señales que actúen sobre circuitería que genere, a su vez, la señal a ser procesada.
 Buena implementación del Modo “En – línea”, evitando la pérdida de datos (implementación
de sistemas CRC, u otros, para supervisar la entrega de los datos al PC).

C2-93
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

FAT, SAT: FORMULARIOS DE EJEMPLO


FAT: DOCUMENTO DE ACEPTACIÓN EN FÁBRICA (PARA EL
“DATA LOGGER”)

Grupo #____, Integrantes: _________________________,


__________________________

CARACTERÍS-
TICAS
GENERALES

√ 1. Alambre tipo telefónico, de un solo conductor (usualmente de tamaño #22)


2. Todos los chips insertados con la misma orientación
3. Cables con la longitud adecuada. removida ½ in. en los extremos. Cortados en
ángulo de 45º
4. Verificar que no pasan cables por encima de los ICs.
5. Observar si los cables van aplanados contra el protoboard y ORDENADOS.
6. Ver si están codificadas mediante colores en los cables las categorías de las
señales que se distribuyen: Rojo: 5V, Negro: Tierra, Morado: Control, Naranja:
Datos, Café: Direcciones, y similares.
7. Ver que los componentes no se calienten fuera de lo normal.
8. Verificar que “switches” de reposición y de corredera, “push buttons”,
contactos de relés, han sido apropiadamente conectados, con resistencias de
pull-up o pull-down, eliminando el rebote (hardware o software)
9. Verificar que se ha conservado el fan out de cada salida, en particular señales de
amplia distribución, como relojes, reset, buses de direcciones y de datos.
Constatar que se revisó apropiadamente el consumo de las entradas que se
conectan a cada salida (En algunos circuitos ciertas señales como el Reloj
tienen FAN-IN de 2, o más)
10. Verificar que los niveles de tensión y corriente, y el fan out, están bien en las
interconexiones entre familias CMOS y TTL, TTL-LS, y cualquier otra
diferente que se haya empleado. Comprobar el apropiado uso de “buffers”
TTL o “drivers”
11. Ver si se han dejado entradas AL AIRE o si se ha empleado directamente la
fuente de alimentación como un “1”, sin la apropiada resistencia limitadora de
corriente.
12. Si alguna entrada se ha colocado a tierra a través de una resistencia, revisar por
qué, y verificar que el valor del pull-down sea apropiado.
13. Determinar si se han manipulado apropiadamente los CMOS: Si se han usado
bolsas conductoras especiales para transportarlas; si el estudiante toca un
terminal que esté conectado a tierra antes de manipular estos ICs con la mano,
o con un cautín o un instrumento.

C2-94
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

14. Verificar la existencia correcta de condensadores de desacoples: Entre el


terminal de Vcc y el de tierra de cada IC, lo más cercanamente posible al IC.
15. Verificar que el alumno emplea correctamente el generador de señales, el
multímetro y el osciloscopio, las “puntas lógicas” y los pulsadores (si los hay).
16. Comprobar que todos los LEDs tienen su resistencia limitadora de corriente
17. Si algunos LED se han conectado con el ánodo a la salida y el cátodo a tierra,
verificar que se ha garantizado que los voltajes y corrientes de esa salida se
mantienen en el rango de operación del circuito que lo maneja (sobre todo si
esa señal es una salida directa de un biestable, o si esa señal se encuentra
conectada a otras entradas lógicas)
18. Constatar que si hay compuertas que multiplican en and lógico, el pulso de
reloj por una combinación de salidas de Flip-Flops (FF), lo hacen con el borde
correcto del reloj.
19. Comprobar que la inicialización de toda la circuitería se realiza apropiadamente.
20. Garantizar que todas las señales asíncronas han sido sincronizadas.
21. Constatar la existencia de una infraestructura apropiada para efectuar la puesta
en marcha: Corrimiento de secuencias –paso a paso o a baja velocidad–,
existencia de señales indicativas del estado del circuito o del flujo de
información, “test points”, y de un mecanismo de inyección de señales externas
que garanticen el resultado.
22. Validar que la conexión de las fuentes de alimentación es la apropiada, que se
han hecho las estimaciones de carga del circuito, que se tienen los desacoples
indispensables a la entrada, y las demás consideraciones comunes.
23. Revisar la calidad de las soldaduras (si se ha hecho alguna).
24. Tener a mano, aunque sea en borrador, el diagrama en bloques del sistema en
el que se destaquen los subsistemas y sus interrelaciones. Tener una descripción
del Algoritmo basada en el Diagrama en Bloques; explicar claramente la forma
en que su circuito opera.
25. Tener a mano, aunque sea en borrador, el diagrama lógico, que muestre con
detalle los componentes (contadores, registros, sumadores) y sus conexiones,
mediante compuertas AND/OR, o NAND.
26. Tener a mano, aunque sea en borrador, el diagrama eléctrico y de
interconexión, identificando cada componente (74LSxx o similar), sus pines,
cuáles pines están conectados o desconectados.
27. Mostrar que cada etapa del diseño ha sido realizada empleando las técnicas
apropiadas enseñadas en la teoría (que ustedes no se basan en concepciones
empíricas). Recuerde que a usted no se le va a calificar sólo por el resultado,
SINO TAMBIÉN POR LA METODOLOGÍA. Usted tiene que demostrar
que sabe. El resultado es importante, pero es la metodología la que garantiza el
resultado (con un poco de ingenio...)
28. Validar las justificaciones para las diferentes decisiones que se tomaron.
29. Indique EL TIEMPO que emplearon en cada parte del diseño (análisis, diseño,
fabricación, pruebas)

C2-95
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

30. Entregar borrador con la lista de componentes: Número de parte, descripción,


precio estimado.

ESPECIFICA-
CIONES
PARTICULARES

1. Debe ser un sistema basado en microprocesadores. Se usará el HC908.


2. Recibir el Modo de Adquisición “En – línea”, en el cual se adquiere un
dato y se transmite al PC, donde es visualizado. PROTOCOLO: La
comunicación con el PC se establecerá sin protocolo; el "Sistema de
adquisición de datos portátil simplemente enviará, de manera permanente,
los datos adquiridos, codificados en ASCII, terminados en caracteres CR,
LF.
3. Verificar que el PC lee convenientemente la información recibida.
4. Verificar que el sistema deberá ser capaz de adquirir, dos señales analógicas
de ±5 Voltios.
5. Verificar que las señales deben poder ser leídas en modo diferencial o en
modo simple.
6. Indique y demuestre la precisión de su sistema de adquisición, que debe
aprovechar todo el rango dinámico de la entrada.
7. Indique y verifique la tasa máxima de muestreo que Usted puede ofrecer.
8. Verifique que cumple con el tiempo máximo de adquisición.
9. Muestre las 8 señales digitales, y que sean programables como entradas o
salidas.
10. Verifique que su sistema incorpora memoria externa, y que ésta funciona.
11. Verifique el comportamiento del sistema de comunicación serial con el PC
(¿velocidad?)
12. Verifique que el subsistema de Acondicionamiento tiene la electrónica
adecuada para el manejo de dos señales analógicas, según su especificación
de sus características.
13. Constate que su subsistema de Acondicionamiento opera correctamente
con lo que sería la salida típica de los sensores, y con las características de
las señales que usted va a medir (por ejemplo, lazos de corriente, voltajes
DC ó AC, etc. Especifique cuáles son)
14. Muestre que el rango dinámico de la entrada de la etapa de adquisición se
ajusta a la resolución del sistema.
15. Indique qué medidas tomó para evitar el aliasing; verifique el rango de
frecuencias de funcionamiento.
16. OPCIONAL: Muestre si incluyó un control y programación de ganancias y
offset en la etapa de acondicionamiento.
17. OPCIONAL: Muestre si incluyó la generación de salidas para actuar sobre
circuitería que genere a su vez la señal a ser procesada (actuadores sobre

C2-96
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

circuitería externa para implantar la aplicación final).


Se debe suministrar impresa, cualquier documentación relacionada, como la Especificación de
Características de sus señales de entrada.
SAT: DOCUMENTO ACEPTACIÓN EN SITIO (“DATA LOGGER”)
Grupo #____, Integrantes: _________________________,
__________________________
CARACTERÍSTI-
CAS GENERALES

1. El día de la entrega deberá tener su equipo listo para ser evaluado, a la 1:30 pm
en punto. El profesor decidirá sobre la marcha el orden de la recepción. Ese día
no es momento de armar, verificar, montar, soldar o probar... Es solo día de
entrega.
2. Es obligación de los estudiantes tener lista la infraestructura necesaria para
verificar cada cosa: Programa para probar la funcionalidad de la memoria,
método para probar las comunicaciones, etc., al menos para los ítems descritos
a continuación.
3. El equipo debe cumplir con todas las características que se probaron en la
primera entrega (FAT)
ESPECIFICA-
CIONES
PARTICULARES

1. Demostrar el modo de configuración. Al menos debe poder escoger y


programar cada uno de los 3 siguientes modos de operación, y el número de
bits de entrada y salida.
2. Demostrar el modo de Adquisición “En – línea”, en el cual su equipo enviará,
de manera permanente, los datos adquiridos, codificados en ASCII, terminados
en caracteres CR, LF. En el PC debe verse un listado eterno con el siguiente
formato:
3. Demostrar el modo de adquisición "Independiente", en el cual el sistema
funciona parecido a un "Data Logger". Adquiere datos por un período de
tiempo fijo y a una tasa de muestreo fija, esos datos son guardados para su
posterior transmisión a un Sistema Central (basado en PC). La comunicación
con el PC se establecerá mediante el protocolo XModem.
4. Modo de adquisición "Por ráfagas", en el cual el sistema adquiere datos por un
período de tiempo finito y a tasa definida, luego bajo petición de un sistema
central transmite (XModem) lo adquirido y espera una nueva orden de
adquisición.
5. Demostrar la funcionalidad del subsistema de Aplicación Final que Usted
diseñó.
6. OPCIONAL: Muestre si incluyó un control y programación de ganancias y
offset en la etapa de acondicionamiento.

C2-97
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

7. OPCIONAL: Muestre si incluyó la generación de señales para actuar sobre


circuitería que genere a su vez la señal a ser procesada (señales de actuación
sobre circuitería externa para implantar la aplicación final).
8. OPCIONAL: Muestre si incluyó mecanismos extra (crc) para evitar problemas
de comunicaciones.

DOCUMENTACIÓN
DEL SISTEMA

1. Deberá entregar la lista de componentes del prototipo: Número de parte,


descripción (incluye: Si es montaje convencional o de superficie,
características especiales como temperatura de operación, voltaje, etc.),
proveedor, "third party", cantidad requerida, mínimo lote por pedir,
precio unitario y precio total, tiempo de entrega, comentarios (back log,
descontinuado, si hay reemplazo).
2. Deberá entregar todos los esquemáticos con sus informes explicativos
detallados.
3. Deberá entregar la Bitácora de Trabajo donde recopiló todas y cada una de las
ideas, documentación, copias de manuales empleados, problemas encontrados
con sus soluciones, planteamientos efectuados en el Desarrollo del Sistema de
Adquisición, ideas desechadas, etc. La Bitácora es su diario de trabajo.
4. Deberá entregar Manuales Técnicos de Operación.
5. Debe entregarse el arte (layout) del impreso de esta tarjeta diseñado en
EAGLE, ORCAD, etc.
6. Debe suministrar las características completas para el par de señales que
emplearon en su aplicación indicando (sin limitarse a): Frecuencia de operación,
temperatura, rangos, impedancias, voltajes, corrientes, fuerzas, etc.
7. Suministrar la especificación completa del subsistema de Aplicación Final que
Usted diseñó.
8.
9.
10.
11.
12.
13.

Se debe suministrar impresa, cualquier documentación relacionada, como la Especificación de Características de sus señales de entrada.

C2-98
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

 ZIGZAG AL PENSAMIENTO LINEAL


Excepciones a TODO
Normalmente los sistemas que diseñamos funcionan como es debido… mientras el entorno se mantenga
dentro de los parámetros “esperados”, o especificados.

Es decir, si por ejemplo usted tiene que diseñar un sistema de POS (Point of Sale), seguro que su
programa arrancará en un estado inicial apropiado cuando llega el próximo cliente, su terminal irá
leyendo la identificación de cada artículo, buscará en su base de datos el precio, multiplicará por la
cantidad de unidades registradas, irá totalizando el valor de la venta para todos los artículos, calculará el
IVA; al finalizar usted habrá previsto que se ingrese el dinero suficiente para cubrir el total, o podrá
escoger entre algún medio alternativo de pago (tarjeta de crédito, o débito), entregará el vuelto si
corresponde, imprimirá la factura y estará pendiente de atender al siguiente comprador!

Esto ocurre hasta con los diseños que hacen los ingenieros menos hábiles... Y muchas veces las pruebas
de aceptación se limitan a verificar que su sistema opera bien ante el mencionado comportamiento
“esperado”.

Lo importantes es que los acontecimientos fuera del comportamiento normal, o rectilíneo, que habrán
de sobrevenir con seguridad (según Morphy) hayan sido previstos por usted!

Yo conocí precisamente un sistema POS que se instaló, previa aprobación por el cliente, en una gran
tienda por departamentos, tipo Éxito, y al momento de la inauguración las colas daban varias vueltas a la
manzana… porque el sistema no funcionaba. ¿Cómo podía ser, si se había probado y aceptado?

Muy sencillo; una señora llegó con los artículos que compró, entre ellos una camisa, y después de que el
cajero la registró, la clienta decidió que ese color en realidad no le gustaba, y que ya no quería llevarse la
prenda. Pero el sistema no tenía previsto ninguna devolución… Y todo se trancó porque la única
alternativa era… finalizar la secuencia, descrita arriba como la “esperada”. Algo similar pasó en otros
terminales de venta vecinos: en uno, a la persona no le alcanzó el efectivo cuando se llegó a la
totalización; quiso devolver algún artículo, y eso no fue posible porque… tampoco estaba prevista dicha
desviación. Otro cliente pidió cancelar con tarjeta de crédito pero no recibió la aprobación del banco;
cuando quiso pagar en efectivo… no pudo hacerlo, pues la alternativa de cambiar a último momento de
forma de pago, tampoco estaba prevista.

Al programador lo despidieron deshonrosamente pero, en realidad, el problema se sitúa a nivel de la


concepción o análisis del sistema.

En nuestro ámbito de la electrónica ocurren situaciones similares; ante cada decisión, hay alternativas
que analizamos e incorporamos en nuestros proyectos…, y hay otras que ni las pensamos. Son éstas
las que, cuando acontecen, irrumpen contra nuestro producto o nuestros programas, con resultados
desastrosos.

C2-99
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Piensen, por ejemplo, en sus fuentes de alimentación lineales. La sección de 5 voltios tiene como
entrada: 12V. Qué pasará si el regulador de 5 V (7805) se quema? Una posibilidad (muy alta) es que los
12V de entrada del 7805 aparezcan a la salida!

Ni a sus chips TTL, ni a su microcontrolador CMOS, NI A SU PENTIUM (de US$ 1,200),


que estén siendo alimentados con SU fuente, LES VA A CONVENIR que les suministren 12 Voltios
en lugar de cinco. Miren las especificaciones y verán que, por ejemplo, los TTL tienen un "maximum
absolute rate" de 7 V, durante muy poco tiempo (un segundo), en la fuente de alimentación. Después
de eso, los chips se dañan por disipación de calor (se queman...); probablemente se fracturan, o incluso
las conexiones internas se vaporizan.

Entonces, USTEDES tienen que tomar previsiones ANTES de conectar un PENTIUM o algún
dispositivo de costo e importancia similar, a SU fuente de alimentación. Los equipos con los que trabajé
durante muchísimos años, empleaban un circuito "CROWBAR". Recuerde que un simple
fusible NO resolverá sus problemas porque, como dice la conseja, "cuando se coloca un fusible para
proteger un semiconductor, el semiconductor protegerá al fusible..." (El semiconductor se quema
y se “abre” antes que el fusible)

Los circuitos Crowbar, de protección contra sobrevoltajes a la salida de las fuentes de alimentación, son
de uso común; no instale su proyecto sin incluir uno. El fusible suele ser de reposición; es decir, basta
con oprimirlo para que vuelva a funcionar; con esto se evita que la unidad esté fuera de servicio por
largos períodos de tiempo.

 OPINIÓN EMPRESARIAL-I
Invention Is a Flower, Innovation Is a Weed

MIT’s Technology Review, November/December 1999

Bob Metcalfe, the inventor of Ethernet and founder of 3Com shares some lessons
with young innovators

Bob Metcalfe’s career traces the trajectory of innovation. He started in the academy, as an
undergraduate at MIT and a graduate student at Harvard. In his doctoral dissertation he laid the
theoretical foundations for a novel method of boosting the power of personal computers: network
them. At Xerox PARC, he turned that theory into something called Ethernet. Xerox wasn’t particularly
successful at exploiting Ethernet commercially, so Metcalfe decided to try himself, founding 3Com to
do the job. After many incarnations at 3Com, he cashed in his chips and became, in his words, a
“technology pundit,” who writes a column for InfoWorld, organizes some of the information world’s
best conferences, and sits on the board of Technology Review. TR asked Metcalfe to tell us what he learned
as he followed the trajectory of innovation from the lab bench to the boardroom and beyond.

C2-100
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Prologue
Why should you listen to me about innovation? Maybe you shouldn’t. (Especially if what you need is
gentle encouragement.)

True, I lived for eight years in Boston’s Route 128 high-tech innovation zone, back when it was
working. True, I lived and prospered for 22 years in Silicon Valley. True, I invented Ethernet, a
computer networking technology that now connects more than 100 million computers to the Internet.
True, 20 years ago I founded 3Com Corporation, which now does more than $5 billion in annual sales.
And true, my personal fortune is a significant fraction of a milliGates.

But Silicon Valley-style high-tech entrepreneurship is certainly not the only way to innovate. It’s just
that, right off, I can’t think of any others.

Disclaimers
Before sharing a few lessons I’ve learned from inventing and innovating, I’d best disclaim a bit.
Consider the fact that today we have computers fast enough to compute the trajectory of a thrown rock
in real time. If you wanted to gather the equations to compute the rock’s trajectory, the last thing you
would do is interview the rock.

Most successful entrepreneurs I’ve met have no idea about the reasons for their success. They were
thrown—like rocks. I had the good fortune to be thrown into Silicon Valley. My trajectory was a
mystery to me then, and only a little less so now.

Another disclaimer: I’m a sample of one. My experience is not statistically significant. So you’re going to
have to read a lot of lessons learned by many different innovators before you can put together
something that holds up. And even after you do that, keep in mind that after 40 years of tennis, I can
tell you to get your racket back early, move your feet, and step into the ball. But then you’re going to
have to spend a lot of time on the court practicing before you can put it all together and beat me.

Enough disclaimers. Here are some lessons I think I’ve learned.

1. Selling Matters
I have a six-story townhouse in Boston overlooking MIT on the Charles River. I often invite young
engineers and would-be entrepreneurs over to schmooze. Many of them tell me my townhouse is
beautiful and they hope to invent something like Ethernet that will get them such a house.

The picture they have in their heads is of me lounging around on the beanbag chairs in a conference
room at Xerox PARC in 1973. They see me having this idea for a computer network and submitting it
as an invention proposal to Xerox. Then they envision me putting my feet up and letting the royalties
roll in until I have enough to come up with the down payment on the townhouse with the river view.

My picture—the actual picture—is different. It’s the picture of innovation rather than invention, the
weed instead of the flower. In my picture it’s the dead of winter and I am in the dark in a Ramada Inn

C2-101
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

in Schenectady, New York. A telephone is ringing with my wake-up call at 6 a.m., which is 3 a.m. in
California, where I flew in from last night. I don’t know yet where I am, or where that damn ringing is
coming from, but within the hour I’ll be in front of hostile strangers selling them on me, my company,
and its strange products, which they have no idea they need.

If I persist, selling like this for 10 years, and I do it better and better each time, and I build a team to do
everything else better and better each time, then I get the townhouse. Not because of any flowery flash
of genius in some academic hothouse.

Most engineers don’t understand that selling matters. They think that on the food chain of life,
salespeople are below green slime. They don’t understand that nothing happens until something gets
sold. The way I think about it is that there are three sets of people in the world. There is the set of
people who will buy your products no matter what (think of your mother). There’s the set who will
never buy your products (think of your competitors). Both are much smaller than the set of people who
will buy your products if the products are competently sold to them. That vast middle set is why sales is
so important, and it represents one of the key differences between invention, which comes up with a
brilliant new idea, and innovation, which gets that inspiration out into the world.

Sales may not matter in invention, but it matters—in a very big way—in innovation.

2. At a Startup, Jobs Grow Faster Than People


In 1982 I suddenly lost my job as 3Com’s CEO and became our vice president of sales and marketing. Take
this as a measure of our desperation. I knew we needed feet on the street, people to actually ask our
customers for orders. I didn’t have too many choices—it wasn’t a very big company at the time—so I
started looking over the available candidates.

Dave didn’t initially look very promising, since he wasn’t in sales. (He was a production engineer.) But
he was single, his dad was a salesman, and he could move that week, so I assigned him the entire eastern
United States as his 3Com sales territory. This is one of history’s bad decisions with a good outcome.

Since his background wasn’t in sales, Dave wasn’t a good bet to succeed in the huge job I gave him. But
he was smart and energetic and he learned fast. Pretty soon, orders started doubling. The volume of
sales was improving so quickly that I “promoted” Dave—from head of the entire eastern United States
to head of the northeastern region. Again, he succeeded, and I was able to “promote” him again, this
time by giving him the Washington D.C. metro area. After another strong run of successes, Dave went
up the down staircase again by taking over all private label sales in Washington.

If you counted from the top, as people tend to do in big companies, Dave was getting demoted each
time. If you counted from the bottom, each reduction in territory in our rapidly growing company was a
big promotion with more responsibility and higher compensation. This is an example of how in small
successful startups the jobs grow faster than the people, not the other way around, the way they do in
big companies.

C2-102
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

3. Don’t Hire—Recruit

Lesson #2, that jobs grow faster than people in successful startups, implies something very important
about the people you bring into such a startup.

First, don’t “hire” anyone. B people hire C people—they collect resumes and choose the person they
want to honor with a job. A people recruit A people. The people you need for a growing startup already
hold jobs much bigger than the ones you need to fill. You have to recruit them, beg them almost, to
take the small jobs you’re offering. Those with imagination will see that the company has the potential
to grow so quickly that the small job will soon be much bigger than the stable position they hold at a big
company. Forget about big company notions of performance. A people can perform easily 10 times
better than B people, sometimes 100 times, or 1,000. The worst thing you can do is rush to fill a job
with a B or C person. That could be very costly, perhaps even fatal, to your company. Wait until you
can recruit the A person who can see the future and grow with it.

4. People Have Operating Ranges


The fact that jobs are growing so explosively at startups has other important consequences. Consider
operating ranges. Everybody has one.

From $0 to $1 million per month I ran sales and brought in the orders, mostly through personal selling.
After that, sales became too technical for that approach to work. Mike took over and carried the
company from $1 million to $3 million per month. After a brief stall, Chuck took us to $5 million per
month. John took over from Chuck to get us to $25 million per month. Then Bob took the company
to $400 million per month. In each of these cases, our head of sales succeeded within his operating
range. After that, a ruthless change had to be made to bring the company to its next plateau.

How do you know when it’s time for a change? How can you tell when the person who did such a great
job six months ago has hit the upper limit of his or her operating range? The first sign is a decline in
performance— salespeople missing quotas, engineers slipping schedules. At first it looks like the plans
were too ambitious; then it’s everybody else’s fault. At some point, unless things start improving,
sometimes even before the proof is conclusive, changes must be made. You have to be able to say, “If
you can’t do it, we’ll just have to find someone who can.” If you wait too long for the person to learn
what they need to know or for conclusive proof of whose fault it is, you may bring the whole enterprise
down. Better to risk the lawsuit for wrongful discharge and save the venture.

5. Don’t Listen to Your Customers


In 1982, 3Com Corporation was the sole supplier of Ethernet cards to a startup called Sun
Microsystems. These cards were for Multibus-compatible computers, and so internally we called them
MEs (really). Sun and its competitors were buying MEs at ever-increasing rates, and they wanted us to
make a cheaper, faster next-generation card. Our salespeople were right there with our big customers:
They demanded we work on what internally we called the ME II (naturally referred to internally as the
“me too”).

C2-103
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

We knew, however, that Sun was planning to design Ethernet connections into their computers, and
that Intel, designer of the Multibus, was planning a competitive ME. Despite overwhelming customer
demand, we decided not to develop the ME II. Some of our salespeople quit in disgust, because we
were “not listening to our customers.”

They were right; we weren’t. Instead, we invested the time of our excellent engineers in designing an
Ethernet card, called internally the IE, externally the EtherLink, for the new IBM Personal Computer.
Today, there are no Multibus computers left, but 3Com ships more than 20 million EtherLinks per
year.

The lesson? Well, of course I’m taking some license by saying that the lesson is you shouldn’t listen to
your customers. The real lesson is that you have to choose which customers to listen to very carefully.
And, even then, you cannot necessarily give them what they say they want. You have to develop
products that your customers will need by the time you are able to deliver them. If you don’t, when the
development cycle is finished, and you’re ready to ship, you will be offering what the customer said he
wanted last year. And any salesman will tell you it’s easier to give a customer what he needs now than to
sell him something you insist he said he wanted last year.

6. Plan for Success


But if you do look ahead successfully and see what the market wants, you will only create new problems.
During 1983, for example, 3Com was in the tornado for exactly this reason: We had ignored our customers
and salespeople and guessed right about what the market would want—Ethernet for personal computers. In
the third quarter, we grew 85 percent in three months, which almost killed the company. We sold much
more than we could deliver, leaving a backlog of unsatisfied customers for our competitors to unhook. We
didn’t have enough people to answer all our customer support calls. Our production programs slipped
behind schedule.

I remember our CEO, Bill, saying we would never grow that fast again. But I pointed out to Bill that
Compaq had the year before gone from zero to 10 times our size in one year. Our problem was not that we
had grown 85 percent in three months. It was that we had planned to grow only 15 percent. Which is to say
that you can plan too conservatively. (I hasten to add that if you have to err on one side or the other, it is
better to plan conservatively. Just don’t overdo it.)

7. Be an Entrepreneur, Not a Visionary

In 1982 my board of directors starting calling me a visionary, and I ate it up. Next thing I knew, I wasn’t
CEO anymore. Turns out, nobody wants visionaries running companies. At my level of the game,
being called a visionary was faint praise.

Here’s the difference between a visionary and an entrepreneur. Both have visions, which are a dime a
dozen. But an entrepreneur has, in addition to visions, plans. In addition to plans, actions. You might
have heard that 80 percent of winning is just showing up. Well, showing up is an action, like taking that
wake-up call in the dark in the Ramada Inn in Schenectady. I wouldn’t touch a visionary with a 10-foot
pole.

C2-104
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Being a company’s proud founder is also foolish. As they build their companies, many people walk
around saying to their employees, “I am the founder and you’re not.” You want every employee of your
company to be a founder. To have and therefore feel ownership.

8. Know Your Own Operating Range

In 1990, I “retired” from 3Com exactly 11 years after incorporating it. I should have gone three years
earlier. Twice the board of directors chose someone other than me to be CEO of 3Com. In 1982, when
I didn’t flounce out the door, but instead got sales and marketing. And again in 1990, when I retired
amicably.

Putting together the board of 3Com was one of my proudest accomplishments. I built that board with
the best people I could find. When they decided someone else was better qualified to be 3Com’s CEO,
who was I to argue? Both times, in retrospect, they were right. By 1990, 3Com had outgrown me.
Fortunately I had a board smart enough to know that I had succeeded in moving 3Com out of my own
operating range. You should be so lucky.

 OPINIÓN EMPRESARIAL-II
Estrategia Tecnológica: Nuestra Fortaleza

Yo no poseo la verdad de las cosas; nadie lo hace. Lo que sí puedo es decirles qué hice en 38 años de
ejercicio liberal de la ingeniería, aquí, en nuestro entorno…, y ustedes mismos pueden obtener sus
propias conclusiones. A mí me funcionó…

- INTEGRADORES DE SISTEMAS
Entendiéndose por ello que no hay que reinventar la rueda en la solución de problemas. Por ejemplo,
un equipo Registrador de Fallas para las subestaciones eléctricas tiene, entre otras, una unidad que
procesa información, toma decisiones y ejecuta acciones tales como comunicarse con su estación
maestra. Esto es claramente un computador (un PC). No hay que diseñar ninguno, sino ubicar uno en
el mercado con las características industriales necesarias y el precio adecuado. Para la comunicación se
necesita un módem; hay que comprar uno, ojalá Motorola. Y así sucesivamente con las demás
funcionalidades: conversores AD, redes locales, Wi-Fi, etc.

Un Integrador de Sistemas es aquel que define el problema a nivel conceptual, y lo resuelve empleando
un arreglo de unidades o subsistemas que, fundamentalmente, no construye sino que adquiere de
terceros. A veces recibe el nombre de OEM. La Integración de Sistemas es una opción muy apropiada a
nuestra propia dimensión económica (Venezuela y Latinoamérica; societaria y personal), y presenta
muchas ventajas, como la del manejo de la obsolescencia tecnológica, que es una de la mayor
importancia. Para ilustrar este factor traigo un ejemplo tomado de la experiencia de uno de mis
proyectos. Cuando comencé seleccionando el primer PC industrial, éste se basaba en un Intel 8088.
Pero cuando realmente nos llegó (siempre pasa tiempo entre la oferta y la realización del proyecto…),
ya empleaba un 80286. Para nuestro siguiente proyecto, ya era un 386 y así sucesivamente, sin que

C2-105
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

nosotros tuviéramos que estar con la angustia de cambiar presupuestos o cotizaciones, ni andar en una
debacle de rediseños. Y lo mismo que con el PC ocurría con los módems, los conversores, las
interfaces... TODO.

Pude así ofrecer siempre equipos con funcionalidades modernas, como sincronización vía GPS,
módems de fibra óptica, fuentes de alimentación eficientísimas, discos de gran tamaño, memorias al
gusto, radios, celulares, comunicación con tecnología Spread Spectrum, etc. Y lo que a nivel de software
comenzó costando $60, ahora es gratis: Sistemas Operativos (Linux), TCP/IP..., todo al alcance de la
mano. ¿Les dije que el corazón del PC cuesta $65? OJO…

- ARQUITECTURA ABIERTA Y ESTÁNDAR


El hardware de mis equipos se basó SIEMPRE en el PC (industrial single board al principio; Credit
Card Computer después), por lo que todas las interfaces y periféricos fueron estándar, lo que trajo
consigo precios muy competitivos, facilidad de consecución, variedad al seleccionar, existencia de
suficientes profesionales bien entrenados y con amplios conocimientos en el área, y todas aquellas
ventajas que se derivan de emplear un dispositivo estándar de amplia divulgación.

Dentro del software dos lineamientos resultaron igualmente exitosos: El lenguaje de programación que
escogí fue el “C”, y mis equipos se basaron en un sistema operativo estándar (DOS). ¡PUNTO! Todos
querían programar en Assembler…

Estas guías hicieron que mis sistemas pudieran desarrollarse programando en el PC de cada cual, sin
apelar a grandes y costosos sistemas de desarrollo. La estandarización hizo que fuera sencillo comprar
módulos o subrutinas también en el área de software. Si un equipo en particular tenía que manejar una
impresora, yo compraba un “spooler” por $60. Las rutinas de comunicaciones eran estándar y costaban
$60. Si se necesitaba procesamiento de señales (FFT), para el PC/C/DOS se conseguía con sólo tronar
el dedo ($60).

Cuando tracé estas directivas (1981) no parecieron nada obvias; de hecho, mis competidores nacionales
e internacionales trabajaban reinventando siempre la rueda: sus procesadores eran diseñados por ellos y
para ellos; los sistemas operativos eran del estilo del iRMX86, costosos y desconocidos por los
venezolanos. El lenguaje de programación era el PL/M, y en algunos casos, el Assembler (cada micro
tiene el suyo propio…), el Basic y el Pascal, para los que no existía la plétora de librerías y paquetes que
siempre se consiguieron para el PC, el “C” y el DOS, ni a tan buenos precios... ¡y hasta gratis!

Si nuestros competidores necesitaban una unidad de comunicaciones seriales, era todo un proyecto de
ingeniería, lo mismo si querían añadirle una interfaz local de video al equipo. Para mí, todo esto era
estándar, obtenible, bueno, actualizado y económico. Mis propios jefes y colegas no opinaban lo mismo
que yo… ¡La mayoría quería diseñar TODO!

¡YO APOSTÉ A LA ESTANDARIZACIÓN… Y GANÉ!

C2-106
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

- INGENIERÍA REVERSA DE PROTOCOLOS


Mis equipos tenían que insertarse en grandes y multimillonarios sistemas preexistentes, por lo que
debíamos comunicarnos de tal manera que aquellos nos aceptaran y entendieran. Esto implicaba, entre
otras cosas, hablar sus propios “protocolos” de comunicaciones, que no eran normalmente públicos,
sino más bien reservados: ¡Mantener el lenguaje de comunicaciones privado ayudaba a las grandes
compañías a espantar la competencia!

Una de nuestras grandes fortalezas fue la de aprender a hablar cuanto protocolo existió. De esa manera
pudimos conectarnos con sistemas Asea, Siemens (Sinaut), Honeywell (7024), Conitel (2020), Modbus,
DNP, TCP/IP, y con una miríada de lenguas y dialectos que, al hablarlos, posibilitaron nuestra
inserción en los grandes sistemas de la competencia. Esto lo logramos capturando con un PC las
comunicaciones entre la central y unas RTU de prueba, y ensayando diversos comandos, hasta obtener
unos registros que luego analizábamos en profundidad. Así fue con casi todos los que menciono…

- PRESENCIA LOCAL
Una gran diferencia que establecimos en Venezuela con nuestros competidores fue que, en nuestro
segmento de actividades, nuestra presencia era contundente y nuestra atención permanente. No nos
limitamos a la oficina convencional, con un gerente y una secretaria, y una llamada a Europa para
solicitar ayuda. Nuestra respuesta era inmediata. Un equipo, por ejemplo, hizo contacto por accidente
con una línea de 69KV y la descarga lo vaporizó; en cuestión de horas habíamos instalado otro para
resolver la contingencia del cliente, sin detenernos a esperar órdenes de compra o pagos de anticipos.

A nuestros competidores les aplicamos la máxima: “De lejos, hasta los muy grandes parecen
pequeños...”, y nosotros estábamos “Tan cerca que parecíamos grandes...”

- INNOVACIÓN TECNOLÓGICA
De los 9 o 10 aspectos principales que definen toda actividad, en mis compañías innovamos por lo
menos en 6:

¿CÓMO?

Innovar en el “CÓMO” implica que cosas que se realizaban de una manera, se hagan después
de otra completamente nueva. En nuestro caso resalta el concepto de remotas sin
transductores, o “transducerless” (XLS). Originalmente las remotas no leían directamente las
señales de voltaje y de corriente, sino que se interponían unos módulos “transductores” que
convertían dichas variables en corrientes (4-20 mA), proporcionales a su valor RMS. Pero,
habiendo puesto el poder de un PC dentro de nuestros equipos, nos animamos a eliminar el
transductor, leyendo directamente de los Transformadores de Potencial y de Corriente en las
subestaciones, y haciendo dentro de la remota todo el procesamiento de señales para establecer
los valores RMS. La nuestra fue una de las primeras remotas en el mundo en establecer este
concepto, y definitivamente fuimos los primeros en Venezuela, y quizás en Latinoamérica. Esto
dio lugar a que las compañías locales que tenían los transductores de tensión y corriente como
su rubro principal, desaparecieran… Ellas los habían diseñado como unidades basadas en
micros… OJO…

C2-107
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Otro aspecto que podemos mencionar en el “CÓMO” es el de la transmisión de la


información, que antes se hacía vía línea telefónica; nosotros aprovechamos en varios casos la
infraestructura eléctrica para enviar la información empleando los mismos conductores de
distribución (Spread Spectrum).

¿QUÉ?

Innovar en el “qué” es más difícil porque hay que aguzar más la imaginación. Pero nuestro
Panel Mímico Local, ubicado en la puerta del gabinete de la unidad remota y que despliega
sobre un diagrama unifilar, mediante dispositivos luminosos, el estado energizado o
desenergizado de los diversos circuitos, así como los datos de tensión y de corriente, y otros
valores calculados, como las potencias y la frecuencia (¿QUÉ más podemos hacer? podemos
calcular localmente potencia activa, reactiva, la frecuencia, los componentes armónicos...), es
una respuesta a ¿QUÉ otras cosas podemos hacer, ahora que nuestro procesador no es un
simple microcontrolador convencional, sino un poderoso PC industrial? Fuimos pioneros en
estos desarrollos, en Venezuela y el mundo.

Otro aspecto fue el de hacer de nuestra remota (¿QUÉ?) un concentrador, que se comportara
como unidad maestra hacia un grupo de remotas pequeñas, y hacia el Scada se presentara como
una sola remota grande. Así resolvimos un problema que impedía que ciertos sistemas antiguos
pudieran leer más información del campo, no porque se hubiera rebasado el límite en la
cantidad de información, sino porque se había llegado al tope en el número de remotas que se
podían definir. Así que hicimos aparecer como si fueran menos remotas, pero más grandes.

¿DÓNDE?

Nuestros equipos se ubicaban normalmente en las instalaciones del suplidor de energía eléctrica.
Nosotros decidimos instalarlos también (¿DÓNDE?) en el sitio del consumidor. De ahí nació
nuestro IaM.

¿CUÁNTO?

Analizando un proyecto para la subestación Cuatricentenario, en la frontera, donde Colombia


se interconecta con Venezuela, nos llamó la atención que se iban a necesitar tres (3) RTU: una
para informar a Edelca, que suple la energía, otra para Cadafe o Enelven, que forman la punta
final del extremo Venezolano, y otra para ISA, que es el instituto de interconexión eléctrica
Colombiano. Y quedaba abierto el campo para requerir más remotas, para Opsis y para Corelca
(Colombia)... Notamos que realmente lo que se requería era una remota con (¿CUÁNTOS?)
tres o más canales de comunicación y VARIOS protocolos, lo que resultaba fácil de hacer… en
nuestra plataforma.

C2-108
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

El precio bajo fue otra de las maneras de comenzar nuestras operaciones, ya que las compañías
suplidoras de remotas, no teniendo competencia, fundamentalmente por lo oscuro y restringido
de sus protocolos, vendían las suyas (¿en CUANTO?) a precios acordes a su carácter de
mercado cautivo.

En relación con el tamaño (¿CUÁNTO mide?), nuestro IaM se lleva las palmas, al unir todas las
funcionalidades previas en un espacio muy reducido (como una caja de zapatos).

¿CON QUÉ?

Como ya dijimos, hacer nuestros equipos (¿CON QUÉ?) empleando elementos estándar como
el PC y sus accesorios, fue uno de los primeros aspectos en los que innovamos.

¿PARA QUÉ?

En esta área cambiamos el uso (¿PARA QUÉ?) de nuestros equipos, que siempre encontraron
su razón de ser en la supervisión y el control de las redes del suplidor de electricidad.
Estableciendo una relación, en muchos casos directa, entre el consumo de electricidad y los
procesos industriales, el dueño de una fábrica puede supervisar su factoría, vía Internet y desde
la comodidad de su estancia, empleando nuestros equipos supervisores IaM.

- RESUMEN

Las decisiones que tomé en las compañías donde trabajé, mías o ajenas, fueron trascendentales. Al usar
el PC obtuvimos:

 que cualquier ingeniero que contratábamos tenía experiencia en la programación de PCs; no así en
los microcontroladores. Esto nos suministró una base amplísima de profesionales para los
proyectos.

 que en el costo final, la diferencia entre un PC y un micro fue mínima, dado que los costos NO
están en el chip, y sí en el desarrollo;

 que el inmenso poder sobrante (cañón matando mosquitos) terminó siendo aprovechado con
mucha imaginación, como por ejemplo eliminando los clásicos transductores e incorporándolos
dentro de la RTU (que tenía mucho CPU libre), pudiendo manejar multiprotocolos, teniendo
un producto listo para interconectarse a redes LAN y al Internet, pudiendo ofrecer los llamados
"puntos calculados" (potencias activa, reactiva y total en base a voltajes y corrientes; consumos,
energías, componentes armónicos de las señales, procesamientos FFT)...

Para un primer proyecto recomiendo:

 el PC (industrial o credit card PC),


 programado en C (MSVC, GCC),
 bajo DOS (o Linux-RT, o FreeDOS),
 empleando PCs estándar como estaciones de desarrollo para programación y prueba.

C2-109
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Si después de hacer la verificación del concepto se requiriera una producción en masa, y el precio fuera
esencial (en nuestro caso el precio NUNCA fue esencial; la competencia siempre estuvo MUY por
encima de nuestras cifras), entonces quizás valga la pena una segunda etapa de optimización que, a lo
mejor, pudiera incluir uno o varios microcontroladores en reemplazo juicioso del PC (pero no creo…)

Seguro que esta opinión no fue ni es compartida por (algunos de) mis colegas. Las compañías
venezolanas con las que competí usaron el criterio contrario, y sus desarrollos se los comieron: nunca
pudieron recuperar los costos de ingeniería.

En nuestro caso, esa estrategia (PC, C, DOS, open architecture) catapultó las compañías desde 1986
hasta nuestros días:

 nada de micros "home made",


 nada de programación en Assembler,
 nada de Sistemas Operativo ad-hoc, o de no emplear ningún sistema operativo,
 nada de arquitecturas cerradas, en donde uno tiene que diseñar y construir hasta las cosas más
elementales que los demás obtiene "for free"

Como ventajas subsidiarias de mi decisión estratégica (a 20 años) encontramos que las rutinas que se
fueron necesitando las obtuvimos siempre por un precio menor a $60:

 spoolers,
 rutinas de comunicación,
 paquetes de procesamiento de datos,
 FFT,
 graficadores en pantalla,
 rutinas de impresión, etc.,

y la GRAN mayoría de ellas se consiguieron GRATIS:

 TCP/IP,
 SMTP,
 POP3,
 CHAP,
 PPP para acceso telefónico,
 y toda esa inmensidad de software regalado que se obtiene para tal infraestructura.

C2-110
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Para que puedan tomarle el pulso al costo, tamaño y capacidades de los PCs embebidos, (credit card
PC), cfr.:

- http://www.compulab.co.il/x270cm/html/x270-cm-datasheet.htm
- http://www.compulab.co.il/x270cm/html/x270-cm-price.htm

EL RESTO:

Fuentes: Lambda, Kepco;

Conversores: Analog Devices, Burr-Brown;

Modems: Motorola;

Otros PC Industriales: Advantech, (Pro-Log);

Proveedores varios: Digi-Key, Allied Electronics, Jameco, Newark.

Circuitos Impresos, hechos en USA. Y montados allá…

Suministros Locales: Gabinetes (Valencia, Caracas), pintura, cable (en un proyecto, solo el cable costó
$100.000. Mi departamento de compras ha debido obtener $30.000 de descuento, pero no lo hizo…
Stultorum infinitus est numerus: El número de estúpidos es infinito)

C2-111
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

 BIBLIOGRAFÍA
Además de la reseñada in situ dentro del texto:

Basic concepts of real-time operating systems.mht:


http://linuxdevices.com/articles/AT4627965573.html

D_ Kalinsky Associates - Whitepaper Architecture of Device I-O Drivers.mht


http://www.kalinskyassociates.com/Wpaper4.html

STATEMENT OF WORK, Marc A. Brauer, rfsow.pdf

Varios:
http://phoenix.nmt.edu/~rison/ee321_fall02/labs/

http://www.epanorama.net/ (incluye bar codes)

Buscar pelotas de golf:


http://phoenix.nmt.edu/~rison/ee382_spr03/ee382.html

Todos los cursos: analógicos, digitales...


http://phoenix.nmt.edu/~rison/ee321_fall02/homepage.html

C2-112
I N G . L U I S G . U R I B E C

3
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Capítulo

CIRCUITOS DIGITALES

Motivación y ambientación

 INTRODUCCIÓN

A
PARTIR del segundo tercio del siglo 19 se conocía ya el electroimán; con él se fabricó el
primer dispositivo de código Morse, que evolucionó hacia el telégrafo y luego al teléfono. A
comienzos del siglo 20 ya se empleaban complejos circuitos hechos con relés, sobre todo
centrales de conmutación telefónica. A pesar de que Boole desarrolló su álgebra a mediados
del siglo 19, no fue hasta 1938 que Claude Shannon planteó aplicarla a los Sistemas Digitales. Quine
primero, Karnaugh y McCluskey después, consolidaron el estado actual del basamento del diseño
digital.

En un lapso tan amplio es muy probable que ya se haya escrito todo lo que puede decirse como
introducción al tema. Sin embargo, es muy importante y resulta siempre conveniente poner en
Perspectiva la Ingeniería Digital para quienes van a estudiarla; tal es el propósito de la siguiente
presentación, como introducción y ambientación para nuestros lectores y alumnos que se adentran en el
torbellino actual de las Técnicas Digitales.

C3-113
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

 REALIDAD Y ELECTRÓNICA ANALÓGICA

L
OS fenómenos físicos con los que interactuamos en el mundo real son mecánicos, y los
percibimos como si fueran continuos aunque casi todos, al estilo de la emisión de energía, sean
cuánticos, o discretos. Antes del advenimiento de la electrónica, la manipulación de estos
procesos físicos: Su amplificación, transmisión, medición y control..., se hacía por medios
mecánicos, hidráulicos o neumáticos. Por ejemplo:

 La veleta servía para controlar la posición de un molino de viento;


 Una palanca operaba como timón de una embarcación;
 Un cuerno o bocina amplificaba sonidos.
 La transmisión de la fuerza era hecha mediante ejes, correas o tubos.
 Un dispositivo para suavizar los movimientos bruscos (filtro) se armaba con amortiguadores
(muelles, resortes, cámaras con aceite), y
 Un gobernador de Watt controlaba la velocidad, aprovechando el giro de unas esferas.

¿POR QUÉ EL NOMBRE DE “ANALÓGICO”?


Estos sistemas vinieron con la electrónica, llamados así porque operan sobre voltajes, corrientes o
impedancias, que son similares –o análogos– a los fenómenos físicos que representan. Estas señales
electrónicas, análogas a las variables reales, tienen su misma forma, y son obtenidas directamente del
campo, o del proceso, mediante transductores (transducers, Xducers).

Por ejemplo, observemos el fenómeno que ocurre cuando hablamos: El sonido de nuestra voz es, en
realidad, un conjunto de alteraciones en la presión del aire que nos rodea, que obligan a la masa de gases
a moverse con desplazamientos ondulatorios de vaivén, cuyas elongaciones están en proporción directa
a la intensidad sonora o volumen de nuestras expresiones (gritos, susurros). Las diferentes frecuencias
con que varía la presión corresponden a la altura de los sonidos que emitimos: Mayores vibraciones
para los agudos, y menores en las voces graves.

EJEMPLO DE TRANSDUCCIÓN

 La posición –lineal o  Temperaturas,  Radiaciones,


angular–,  Vibraciones,  Niveles (de líquidos),
 El desplazamiento,  Presiones neumáticas,  PH (químico),
 Las fuerzas,  Flujos (de fluidos),  Luz, etc.

son ejemplo de cantidades que se convierten, o traducen, a variables electrónicas que son directamente
proporcionales a los fenómenos mecánicos externos que modelan. (NB: En comunicaciones, las
antorchas y banderas de señales, y el telégrafo, fueron digitales desde el principio...)

C3-114
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

 ELECTRÓNICA DIGITAL: CARACTERÍSTICAS


IMPORTANTES
1) REPRESENTACIÓN NUMÉRICA
Las técnicas Digitales son una rama de la electrónica, que toman su nombre porque no representan los
fenómenos como los sistemas analógicos, sino que lo hacen expresándolos mediante una serie de
números, o cifras digitales (dígitos). La primera ventaja de representar así los fenómenos externos
estriba en que el procesamiento es eminentemente aritmético. Por ejemplo, para amplificar una
señal al doble de su valor se requiere… simplemente multiplicarla por 2. Para filtrarla y eliminarle
componentes indeseadas basta con aplicarle un algoritmo matemático a la representación numérica, o
digital, de la señal de entrada. Un proceso de control se convierte en un procedimiento aritmético, que
analiza los números que representan la señal de entrada en diversos instantes de tiempo y toman
decisiones. Por ejemplo, un control digital de temperatura es un dispositivo que lee las cifras que
representan cada valor de la variable externa, y decide si hay que encender el calefactor, o apagarlo, al
sobrepasar los límites inferior o superior impuestos al artefacto.

Es una gran ventaja poder sumar, multiplicar, integrar... o efectuar cualquier otro procesamiento
numérico sobre las variables. Y es muy importante también que todas ellas compartan la misma
representación numérica, y que los algoritmos dependan sólo de este factor, y no de que unos números
representen, por ejemplo, temperaturas mientras que otros simbolicen flujos.

2) VARIABLES DISCRETAS, INMUNIDAD AL RUIDO


La segunda gran característica de los sistemas digitales es que son discretos, como contraposición a los
analógicos, que son continuos. Esto quiere decir que solamente son significativos ciertos valores, y
como no se necesita distinguir entre todos ellos, los componentes que los procesan son sencillos de
elaborar. En el caso de la variable más elemental, se requiere que represente sólo dos posiciones:
Abierto o cerrado; saturación o en corte; cinco voltios o cero. Nada pasa en el intermedio, así que, por
ejemplo, si una señal debe estar en un nivel alto o bajo, y tal situación va a ser representada por 5 ó 0
voltios, y si en un momento determinado dicha señal se encuentra en 4 voltios, el discriminador puede
asumir que el estado es “alto”. Y si vale 3 V también. En cambio, si la señal mide 2 V el dispositivo
indicará que el estado es “bajo”, y hará lo mismo si el valor es de 1 V. (Estas cifras se presentan como
ejemplo, no son reales...)

Se denomina inmunidad al ruido a la diferencia entre aquellos dos rangos que sean claramente
discernibles como un valor o el otro. Los sistemas digitales tienden a ser altamente inmunes al ruido.
Señales espurias de importante magnitud pueden superponerse a las variables sin que ocasionen la
interpretación errónea de las mismas.

Está claro entonces que los sistemas digitales discriminan el ruido por niveles: De cierto valor hacia
arriba, se supone la variable en el estado “alto”, y disminuyendo desde allí, que está en “bajo”. Eliminar
el ruido en los sistemas analógicos requiere filtros, que operan dejando pasar la banda de frecuencias de
la señal y eliminan las demás, que pertenecen al ruido. Pero si una interferencia, aunque sea pequeña,
tiene el mismo componente armónico que la señal, puede resultar imposible de eliminar.

C3-115
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

3) EXACTITUD, PRECISIÓN Y RESOLUCIÓN


 Exactitud (“accuracy”) es un indicativo de qué tan de cerca representa la señal medida, el
valor real de la variable. Usualmente se especifica de dos maneras: a) como un porcentaje de la
escala total (full scale) o b) como un porcentaje de la lectura actual.

Por ejemplo, una señal analógica puede especificarse con una exactitud de 0.1% de la escala total,
lo que significa que para cualquier valor leído el error absoluto será el mismo que para la escala
completa. Esto implica que una medición que se ubique en el 10% de la escala, tendrá un error del
1%.

Instrumentos con especificaciones de error de 1% de la lectura, son iguales, o mejores, que


aquellos con exactitudes del 1% de la escala completa.

La exactitud refleja los inconvenientes introducidos por todas las posibles fuentes de error; por
tanto depende de factores tales como resolución, linealidad, repetibilidad, ganancia,
estabilidad y rango dinámico.

 La Precisión (“precision”) se refiere al número de dígitos significativos con los que puede
expresarse una variable.

 Resolución (“resolution”) indica el menor cambio discernible con un instrumento.

A veces precisión y resolución significan lo mismo. Nótese que precisión no implica exactitud; es
posible que pueda discernirse un cambio con una resolución de 1 parte en 10.000, y que la exactitud
sea menor: Una en 1.000, por ejemplo. Al revés esto no es posible: ¡ no puede tenerse una exactitud
que sea superior a la precisión o a la resolución !

La tercera gran característica de los sistemas digitales es que se puede incrementar su resolución
simplemente aumentando el número de dígitos elementales (bits) que se usan en la representación: 8,
10, 12, 16 y 24 bits son comunes para codificar música en un CD de audio. Es factible aumentar la
exactitud con que se manipulan los datos adentro de los sistemas digitales, a cualquier valor deseado. Y
las informaciones pueden adquirirse desde el exterior con niveles impresionantes también de exactitud
y resolución.

Ejemplo: Los sistemas de seguimiento de satélites, con láser y codificadores de posición angular (shaft
encoders), obtienen con 18 bits una resolución mejor que 5s de arco (2^18 = 262.144 partes de
circunferencia).

Ejemplo: Un termómetro digital de cuarzo tiene grandes niveles de exactitud y resolución. Miden la
frecuencia, dependiente de la temperatura, de un oscilador de cuarzo. Tiene resoluciones de 0.0001ºC, y
exactitudes absolutas de 0.1ºC.

C3-116
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

En el eje vertical de la Figura 1 se


indica una cantidad de referencia.
De ella se hacen varias medidas,
que se centran alrededor de otro
valor. La distancia que separa estas
dos (2) cifras es la exactitud
(“accuracy”). Mientras más exacto
es un sistema, el promedio de las
medidas tomadas se acercará más al
valor de referencia. Ahora, la mayor
o menor precisión se representa
por lo ancho o estrecho de la
campana de Gauss. Mientras más
compacta sea la gráfica habrá
mayor precisión en las medidas,
porque una curva es apretada si casi
todas las aproximaciones indican el
mismo valor, y es ancha si las
estimaciones difieren bastante unas
de otras (menor precisión).

Un sistema ideal tiene buena


exactitud y una gran precisión. Fig. 1: Exactitud, Precisión, Resolución
Se puede conseguir aceptable
precisión y pobre exactitud. En la figura esto indicaría que todas las medidas se centran, muy
estrechamente, alrededor de un valor... ¡ equivocado !

¡ Lo que sí no puede tenerse es una buena exactitud con mala precisión !

La resolución (“resolution”) indica también la granularidad con que pueden diferenciarse unas
medidas de otras. Si la resolución fuera mala, el gráfico de la Fig. 1 quedaría formado por pequeños
segmentos de líneas rectas horizontales. Mientras peor sea la resolución, más “discreto” será el gráfico
de las medidas (como una escalera). Si la resolución aumenta, los valores asumen mayor cantidad de
posiciones diferentes, y el gráfico se verá más suave o “continuo”.

4) CONTROL DE ERRORES: DETECCIÓN Y CORRECCIÓN


Además de lo ya dicho en relación a la inmunidad al ruido para cada variable elemental (bit), y que
mayores resoluciones se logran agregando bits, también pueden concebirse códigos que controlen
errores que, aunque difíciles de ocurrir, podrían presentarse en la lectura de bits individuales, y que los
detecten e incluso los corrijan. Un ejemplo en telecomunicaciones consiste en añadirle un bit (de
paridad) a cada conjunto de 8 (byte), de tal manera que siempre el número de “unos” sea par o impar. Si
se presentara un error en un bit de uno de los símbolos (cambio de un cero por un uno, o viceversa),
podría fácilmente detectarse ese error contando en el receptor el número de bits, y viendo si cumple con
la paridad establecida. Si hay un error puede indicársele al transmisor que repita la comunicación (este
mecanismo se conoce como ARQ: Automatic Repeat Request)

C3-117
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Otra forma de control de error consiste en que, una vez puesto a punto un sistema digital, basta con
duplicarlo para obtener copias que funcionen exactamente igual que el prototipo, sin necesidad de
ajustes ni calibraciones, propios de los sistemas analógicos, que usan potenciómetros, condensadores
variables e inductores de núcleo ajustable. Los de esta tecnología, una vez que uno los reproduce,
necesitan pasar por las manos de personal técnico especializado que los entone; de lo contrario no
funcionan. Pero uno digital no precisa ajustes (al menos, en teoría...)

5) ALMACENAMIENTO DE INFORMACIÓN
Los sistemas digitales graban datos de maneras que perduran en el tiempo mucho más allá que los
sistemas análogos, que emplean dispositivos tales como condensadores en los que almacenan ciertos
voltajes, pero que luego se van descargando y perdiendo paulatinamente la información. Esto es cierto
bien sea que los valores en los dispositivos digitales estén representados por huecos, magnetizaciones de
elementos en discos, o posiciones de interruptores.

6) PROCESAMIENTO DE LA VARIABLE TIEMPO


Un sistema digital que toma muestras a determinados intervalos puede luego procesarlas a velocidades
diferentes, de forma repetida si se quiere (para efectuar promedios y eliminar el ruido), o, por ejemplo,
para incluir dentro de una evaluación, una copia de sí misma, a lo mejor desplazada en el tiempo (si lo
que se quiere es obtener la convolución). Estas modalidades son infinitamente más fáciles de realizar en
un sistema digital que en su contrapartida analógica.

El procesamiento en el dominio de la frecuencia, de señales dependientes del tiempo, es muy simple de


manera digital, aplicándoles por ejemplo transformadas del tipo FFT (Fast Fourier Transform)

Otro aspecto notable relacionado con la manipulación de la variable tiempo lo constituyen los sistemas
que programan o secuencian la operación de plantas o procesos, y que son fundamentales para la
automatización industrial, lo mismo que las “Máquinas de control numérico”, que leen sus instrucciones
desde una cinta o un disco externo y producen, en serie, piezas metal-mecánicas trabajadas con taladros,
esmeriles y otra diversidad de utensilios para el maquinado.

7) ESTANDARIZACIÓN
Una gran ventaja de los sistemas digitales es la existencia de multitud de componentes estándar, como
compuertas, memorias, microcontroladores y microprocesadores, y de subsistemas completos similares
a impresoras, monitores, módems, computadoras, interfaces de redes, motores de paso, codificadores,
teclados y sistemas para el despliegue de información. La cantidad de transistores en los circuitos
integrados se duplica cada 18 meses (ley de Moore) y sus precios bajan irremisiblemente.

Después del hardware programable vino el software, que lo potencia de una manera exponencial,
haciéndolo reusable. Antes, un televisor era sólo eso. Ahora, un PC puede ser un TV, o un pasacintas
(VHS, CD, DVDs), o un sistema de composición musical, o uno para la autoría de textos, etc.

C3-118
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

 CONVERSIÓN ENTRE BASES

E
STE tema se trata con suficiente propiedad en los libros de texto; sin embargo, por lo general
los estudiantes no logran entenderlo al punto de no necesitar calculadora para las operaciones.
Los siguientes ejemplos se enfocan solo en números enteros; los procedimientos pueden
extrapolarse de manera sencilla a la parte fraccional, pero esta representación se emplea mucho
menos en el día a día.

1) CONVERSIÓN DE DECIMAL A BINARIO O A HEXADECIMAL


MÉTODO CONVENCIONAL

El procedimiento común que se emplea para la conversión de decimal a binario consiste en ir


dividiendo el número decimal por 2 hasta que ya no pueda continuarse; luego se toman los residuos de
cada operación, en sentido inverso. Por ejemplo: Convertir 843 a binario:

843 ÷ 2 = 421, R=1 421 ÷ 2 = 210, R=1 210 ÷ 2 = 105, R=0 105 ÷ 2 =  52, R=1 


 52 ÷ 2 =  26, R=0  26 ÷ 2 =  13, R=0  13 ÷ 2 =   6, R=1   6 ÷ 2 =   3, R=0 
  3 ÷ 2 =   1, R=1   1 ÷ 2 =   0, R=1  
 
La tabla se lee de izquierda a derecha, y de arriba a abajo. Los residuos se toman comenzando por el
último, que TODAS LAS VECES es “1”. De hecho, la división final siempre es la misma (uno dividido
por 2: Cociente 0 y residuo 1), no importa de cuál número, mayor que cero, estemos hablando.

Entonces, 843 en binario es: 1101001011.

MÉTODO RECOMENDADO

Para acelerar el proceso hay que realizar menos divisiones, lo que se logra convirtiendo el número a una
base auxiliar intermedia, más grande, siendo la más empleada la base 16 (hexadecimal). Una vez hecha
esta conversión, obtener el resultado en binario es inmediato, puesto que las bases que son potencias de
dos, como la octal y la hexadecimal, se convierten a binario por simple inspección.

Sin embargo, dividir por 16 no siempre se le facilita al alumno, que se ayuda a veces con la calculadora.
El método recomendado es el de convertir a octal (base 8) , pues las divisiones por
8 sí son muy sencillas, y de ahí a binario o a hexadecimal, según se solicite. El ejemplo anterior sería:

843 ÷ 8 = 105, R=3 105 ÷ 8 =  13, R=1  13 ÷ 8 =   1, R=5   1 ÷ 8 =   0, R=1 

843 en octal es: 1513, y en binario (directo del octal): 1 101 001 011, idéntico al ejemplo original.

Si se pide en hexadecimal, el resultado puede extraerse del número binario en forma trivial e inmediata:

11 0100 1011 (reacomodado en grupos de a cuatro, de derecha a izquierda): 34B (hex).

C3-119
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

2) CONVERSIÓN DE BINARIO A DECIMAL


MÉTODO CONVENCIONAL

El método que más se emplea es el de obtener el valor en decimal de cada “1”, de acuerdo a la notación
posicional. Ejemplo: Convertir a decimal el número: 1011 0100: (Observe que TODAS las cantidades
binarias, menos el cero, comienzan con “1” a la izquierda. Sin embargo, a veces se agregan ceros, no
significativos, para hacer que el último grupo de la izquierda tenga 3 o 4 bits y así acomodar con
propiedad los números octales o hexadecimales).

128 64 32 16   8 4 2 1 
 1   0  1  1   0 1 0 0 
 
128 + 32 + 16 + 4 = 180 decimal. 

MÉTODO RECOMENDADO

Se denomina “doble y sume”, y consiste en procesar los números binarios, de izquierda a derecha, con
la siguiente aproximación: Tome el primero de la izquierda (que debe ser un “1”; los ceros no
significativos se pueden ignorar); si no hay más columnas ya ha obtenido el resultado; si hay una más,
multiplique por 2 la cifra que lleva (doble) y súmele el valor que se encuentre en esa columna de la
derecha.

Para nuestro ejemplo el resultado es así:

1  0  1  1    0  1  0  0. Tomamos el primer “1”. Como hay al menos una columna a la diestra,


multiplicamos nuestro “1” por 2, y le sumamos lo que hay en ella, que en este caso es un “0”. El
resultado hasta ahora es “2”.

Como aún hay otra más a la diestra, doblamos el valor que tenemos y sumamos el “1” que hay en esta
columna: 2*2 + 1 = 5.

Para la siguiente columna: 5*2 + 1 = 11.

Siguiente: 11*2 + 0 = 22.

Próxima: 22*2 + 1 = 45.

Penúltima: 45*2 + 0 = 90.

Última: 90*2 + 0 = 180, que era el valor original.

C3-120
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

3) CONVERSIÓN DE HEXADECIMAL A DECIMAL


MÉTODO CONVENCIONAL

El método que más se emplea es el de obtener el valor en decimal de cada columna, de acuerdo a la
notación posicional.

Ejemplo: Convertir a decimal el número: 9AB:

256 16  1 
 9   A  B 
 
9*256 + 10*16 + 11*1 = 2475 decimal. (Recuerde que en hex, A es 10 y B es 11) 

MÉTODO RECOMENDADO

Es el equivalente al “doble y sume”, y consiste en procesar los números hexadecimales, de izquierda a


derecha, de la siguiente manera: Se toma el primero de la izquierda, si ya no hay más columnas ya se ha
obtenido el resultado; si hay una columna más, se multiplica por 16 la cifra que llevemos y se le suma el
valor que se encuentre en esa columna de la derecha.

Para nuestro ejemplo el resultado es así:

9 A B. Tomamos el “9”. Como hay una columna a la derecha (al menos), multiplicamos nuestro “9”
por 16, y le sumamos lo que hay a la derecha, que en este caso es un “10”. El resultado hasta ahora es
9*16 + 10 = 154.

Como hay una columna a la derecha, multiplicamos por 16 el valor que tenemos y sumamos el “11”
que hay en esta columna: 154*16 + 11 = 2475.

4) CONVERSIÓN DE OCTAL A DECIMAL


Es similar al procedimiento convenido para convertir de hexadecimal a decimal, sólo que se multiplica
ahora por 8, que es la base.

C3-121
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

 LAB0

A
LGUNOS estudiantes llegan a sus prácticas de circuitos o electrónica digital con deficiencias
que les dificultan alcanzar el mayor provecho posible. En estas breves notas se pretende
subsanar varias carencias, y advertir sobre los procedimientos que deben seguirse en la
elaboración de sus proyectos, las dificultades con las que pueden encontrarse, y una que otra
recomendación importante.

Los temas que se repasan son los siguientes:

 Uso del Laboratorio


 inserción y extracción de circuitos
integrados en el Protoboard.
 Alimentación de los componentes.
 Consideraciones con los interruptores.
 Carga máxima de las señales (Fan out).
 Entradas no usadas.
 Cuidados con el manejo de los CMOS.
 Uso obligatorio de condensadores de
desacople.
 Leds, Indicadores 7 Segmentos y equipos
de prueba.
 ¡ Qué va a fallar en sus proyectos de
laboratorio !

C3-122
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

PROTOBOARD
Cada tira del “protoboard” suele tener un canal central. A lado y lado hay 64 filas de 5 columnas de
terminales para Circuitos (huecos), de 0.1 in., correspondientes al espaciado estándar de los pines en los
Circuitos Integrados. Los 5 huecos en cada columna están
interconectados eléctricamente entre sí. El espacio en el canal
central es de 0.3 in., el mismo que existe entre las líneas de
terminales de los circuitos estándar de 14, 16 y 18 pines en los
dispositivos DIP (Dual In-line Package). Al introducir uno de estos
circuitos quedan 4 huecos sin usar por c/terminal del chip, que se
emplean para interconexiones punto a punto con otros circuitos, las
alimentaciones, los LEDS de salidas y los interruptores de entrada.

Circuitos más grandes, como los de 24 terminales, tienen una


separación entre líneas de 0.6 in., por lo que dejan menos agujeros
libres para las interconexiones. También pueden incluirse
componentes discretos como resistencias, condensadores de paso o
desacople y transistores. (Nota: Resistencias de más de ¼ de vatio, y
otros componentes como condensadores grandes, tienen terminales
muy gruesos que ¡ dañarán el conector del “protoboard” si se
los fuerza !)

Normalmente hay también dos columnas a lado y lado, con terminales interconectados, que sirven para
distribuir alimentación, tierra y señales comunes como relojes, resets, etc.

El cableado debe hacerse con alambre tipo telefónico, de un solo conductor (usualmente de tamaño
#22). En ningún caso debe emplearse alambre de múltiples hilos o “pelos”. (Si no lo sabe ya, debe
averiguar por su cuenta cómo se numeran los conductores, y tener una idea exacta de lo que es un
conductor telefónico, #22)

CIRCUITOS INTEGRADOS Y ALAMBRES


Los chips son sencillos de insertar en el protoboard, una vez que se los acondiciona, porque no suelen
venir con los terminales verticales, sino un poco inclinados hacia fuera, para que las máquinas de
inserción automática puedan manejarlos con facilidad. Así que a los ICs nuevos, hay que retornarles sus
terminales a la vertical, de manera que su espaciamiento sea exactamente 0.3 in. Esto puede hacerse o
con los dedos de la mano, o con unas pinzas largas.

También pueden insertarse “sockets” en el protoboard, que luego alojarán ICs que resultan costosos.
De esta manera, nunca se tienen que mover estos ICs de sus sockets.

Esta es una distribución aceptable de componentes en un protoboard.

C3-123
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

(Foto, cortesía de R. Berdayés)


Para remover los chips tiene que usar una herramienta especial de extracción, porque quitarlos a
mano los destroza (daña sus terminales ¡ y los dedos !). Es una especie de “U” metálica, cubierta de
material plástico aislante, muy sencilla y económica de conseguir. ¡ No vaya al laboratorio sin ella !

Todos los chips deben insertarse con la misma orientación para facilitar el alambrado y el
“debugging”. Normalmente los ICs tienen una marca o muesca que señala dónde está el terminal #1.
La mayoría de los ICs tienen la tierra abajo a la extrema derecha (pin #7) y la alimentación arriba en el
terminal situado más hacia la izquierda (pin #14), y también los protoboards exhiben normalmente la
alimentación con esa misma orientación. Recuerde verificar doblemente la localización exacta de los
terminales de energía eléctrica en sus chips. Colocar mal la fuente es un error casi siempre destructivo
para el IC (porque queda, por ejemplo, el Vcc a la salida de una puerta).

Los cables se insertan y se remueven mejor con la ayuda de unas pinzas. Se necesita también un
pelacables que permita cortarlos con la longitud adecuada y removerles ½ in. aproximadamente en los
extremos. Los cables que se inserten deben ser nuevos, porque así son más fáciles de introducir. Los
cables muy usados son difíciles de insertar, y si se logra finalmente colocarlos, probablemente dañen el hueco
del protoboard. Si se quiere reusar un cable que ya no entra con facilidad, corte de nuevo el extremo y
vuélvalo a pelar. La punta del cable debe quedar biselada en ángulo de 45º.

C3-124
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

N o p a s e c a b l e s p o r e n c i m a d e l o s I C s . ¡ R o d é e l o s ! Esto facilita el
debugging y el cambio de componentes, en caso de ser necesario. Los cables deben estar lo más
aplanados contra el protoboard que sea posible. Y deben estar ORDENADOS. Trate de mantener
codificadas, mediante colores en los cables, las categorías de las señales que se distribuyen. Por ejemplo:

Rojo: 5V Negro: Tierra Morado: Control Naranja: Datos Café: Direcciones

En un cableado mal hecho, remover una conexión puede tener consecuencias impredecibles en el
comportamiento del circuito, pues pueden extraerse, sin pensar, hilos que no se deseaba mover.

En un cableado ordenado, el profesor puede, al menos, tratar de ayudar cuando algo falle.

FUENTES DE ALIMENTACIÓN
Normalmente las fuentes de energía eléctrica vienen protegidas de manera que un corto a su salida lo
único que hace es desactivarla hasta que se lo elimina, pero lo que sí resulta seguramente catastrófico
es, por ejemplo, conectar invertida la polaridad de Vcc y Tierra!!! Casi siempre que se conecta invertido
un IC es garantía de que el chip se quemará.

SIEMPRE: ALGUIEN INSERTA EN EL PROGRAMADOR…

¡EL MICRO AL REVÉS!

Aunque una única salida de un IC TTL puede cortocircuitarse a tierra sin que el chip se queme por
disipación, lo que sí es cierto es que conectarle el Vcc a la salida de la compuerta la quemará, si
ésta va a saturación. A veces este tipo de corto circuito no daña un IC CMOS, pero sí le reduce su vida
útil, o termina por quemarlo si dicha situación se prolonga en el tiempo por varios minutos.

Entonces, cuando alimente un proyecto, lo primero que hay que revisar es que ninguno de los
componentes eche HUMO. Y luego, tocarlos para ver que ninguno se caliente fuera de lo normal (con
precaución, porque los micros suelen calentarse bastante; no sea que se queme la mano).

Los IC CMOS tienen un problema particular: Si se aplica señal en sus entradas, ANTES de que se le
haya conectado la alimentación (Vcc y tierra), puede dañarse la estructura interna del IC, o pueden
activarse SCRs parásitos, que hacen que si a continuación se aplica la alimentación de energía, el IC se
ponga en corto (Vcc a tierra)

INTERRUPTORES
Los “switches” de reposición, los de corredera, los “push buttons” y los contactos de relés, pueden
servir como entradas alimentando 0 y 1 al circuito. Normalmente estos interruptores presentan lo que
se conoce como “bouncing”, que son múltiples aperturas y cierres, que pueden durar entre 10 y 40 ms
(menos de 20 ms típico). Hay que tener cuidado de conectar este tipo de interruptores a través de
latches SR u otros dispositivos similares que garanticen que cada conmutación se refleje como una sola
transición porque, de lo contrario, si se alimenta, por ejemplo, un contador, éste avanzará muchos pasos
cuando debería contar sólo uno.

C3-125
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

FAN OUT
Es la capacidad que tienen las salidas de unos dispositivos de manejar las entradas de otras compuertas.
Normalmente se mide su número; por ejemplo, si la salida de una compuerta TTL puede absorber 16
mA en su nivel bajo, y una entrada de ese mismo tipo de compuerta entrega -1,6 mA cuando se la lleva
al mismo nivel, puede decirse que el fan out es 10 para voltajes bajos. Si, además, ese terminal puede
entregar –400 uA en nivel alto, y la respectiva entrada consume 40 uA, el fan out es de 10 también en el
voltaje alto. Y el fan out, en general, es el valor más pequeño escogido de entre los dos anteriores. En
nuestro ejemplo, el fan out es de 10.

En general los CMOS tienen un fan out de 20. (Verificarlo con cada línea de productos en particular).

Uno suele escoger una familia de ICs para trabajar, y emplear TODOS los ICs de allí. En ocasiones
especiales, hay entradas que presentan más de una carga unitaria (sucede a veces con los terminales de
Clock de ciertos ICs...). Hay que tener cuidado, porque entonces ya no son 10 circuitos los que una
salida puede manejar. Pero, en general, es fácil tener en cuenta esta condición cuando sólo se emplean
chips de una misma familia.

Si hay que emplear mezcla de familias, por ejemplo CMOS y TTL, la regla de oro es que una salida
CMOS sólo puede cargarse con UNA entrada TTL. Lo que se suele hacer, entonces, es que para
conectar una sección hecha con CMOS con otra realizada con TTL, se coloca en la mitad (a modo de
interfaz) unos circuitos “buffers” TTL o “drivers”, que hay que seleccionar del manual TTL. En
todo caso, hay que verificar que la salida CMOS en realidad sí pueda manejar el buffer escogido.

ENTRADAS NO USADAS
Lo que NUNCA HAY QUE HACER es dejar AL AIRE las entradas que no se usan; es decir, sin
conectarlas. Esto es fuente de dolores de cabeza con su diseño. Si es una entrada de una compuerta con
funcionalidad AND, la no usada debe llevarse a un “1”.

NOTE: La fuente de alimentación NO ES UN “1”. Si se la aplica directamente a entradas no


usadas, hay una alta probabilidad de que un “overshoot” al aplicar la energía, dañe permanentemente los
IC.

Recuerde, por ejemplo, que una compuerta TTL tiene que alimentarse con 5V; 6V es el máximo
absoluto, y 7V quemarán con toda seguridad el IC. Los CMOS tienen un rango más grande, pero
también hay que respetar los límites.

Entonces, lo que se hace para conectar las entradas no usadas a “1” es:

Una compuerta no usada se la coloca de tal manera que su salida esté en “1”, y de allí pueden
alimentarse hasta 10 entradas al aire. (Si la compuerta es NAND, basta con conectar sus entradas a
“0” para que su salida esté en “1”)
ó:

C3-126
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Se colocan a Vcc, a través de una (1 K, por ejemplo), que limita la corriente que pueda generarse en
caso de overshoot. Hay que tener en cuenta, de todas maneras, de no conectar una cantidad muy grande
de entradas, tal que el voltaje baje de los 3.5 V.

Si la entrada al aire está en una compuerta con funcionalidad OR, hay que conectarla a “0”.
Normalmente se conectan directamente al bus de tierra del circuito. Aquí no hay problemas con
overshoot. Casi nunca las entradas se colocan a tierra a través de una resistencia.

Note: Las resistencias que se conectan a Vcc se llaman de “pull up”, y las que pudieran conectarse
eventualmente a tierra serían de “pull down”. (¿Para qué podría usted querer conectar algo así?
!PIENSE!)

CUIDADOS CON LOS CMOS


NUNCA TOQUE UNA COMPUERTA CMOS. JAMÁS. Tocarla es garantía de dañarla si usted
ha estado un rato en un asiento de cuero, o sobre una alfombra, y si la humedad relativa del ambiente es
baja, usted se carga con electricidad estática; como las compuertas CMOS tienen impedancias altísimas
en sus entradas, unos pocos electrones desprendidos al tocar el chip, significarán muchos voltios en los
terminales del CMOS, quemándolo.

Los ICs deben transportarse dentro de bolsas conductoras especiales, que hacen que la posible
electricidad estática se reparta, o no se produzca. Permanentemente usted debería conectarse a un
terminal que esté conectado a tierra, antes de tocar estos ICs con la mano, o con un cautín o un
instrumento. Si toma el micro con la mano y lo guardar en el bolsillo de la camisa..., usted se está
buscando que se le queme. Después no pida prórroga en su proyecto. ¡ Y si es un Pentium ($1,000),
usted está despedido del trabajo y quebrado !

CONDENSADORES DE DESACOPLE
Tanto los IC del tipo TTL, con salida “totem
pole”, como los CMOS, tienen una estructura a la
salida compuesta por un transistor encima y otro
debajo. Cuando el de arriba está cortado, el de
abajo se satura, y viceversa. Que el transistor
inferior tenga como carga otro transistor (una
carga no resistiva, sino activa), es lo que hace que
la capacitancia (parásita) que tiene que manejar, se
cargue y se descargue muy rápidamente,
lográndose con ello tiempos de conmutación muy
pequeños, ya que la resistencia del transistor de
arriba es muy pequeña.

Sin embargo, esta configuración presenta un


inconveniente muy grave. En el tránsito de un
estado a otro, hay un momento en que ambos
transistores están conduciendo (región activa). En
un TTL, si asumiéramos que durante este breve instante los dos transistores están en saturación

C3-127
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

(realmente andan por región activa, pero de esta manera simplifico el análisis), más o menos puede
decirse que hay un pico de corriente aproximadamente igual a 5V / 130 Ohms (que es el valor de la
carga del transistor de arriba, para TTL. He despreciado los voltajes de saturación y el del diodo). Esto
es aproximadamente igual a 40 mA, POR CADA SALIDA del chip. Los IC están diseñados para que el
calor generado por este pico no los dañe. Note que si hay más de una salida conmutándose dentro del
mismo IC, el problema empeora.

Además, los circuitos complejos suelen ser sincrónicos, lo que significa que cambian todas las señales
AL MISMO TIEMPO, bajo el comando de una señal de reloj. Entonces, si tenemos 10 IC, c/u con 40
mA u 80 mA o más, podemos tener picos de más de medio amperio, y hasta de más de uno, en la
fuente!!! Debido a la impedancia de salida de la alimentación, y a la del cableado de distribución de la
alimentación, estos picos pueden hacer que la fuente tenga una disminución en su valor, de la misma
duración y forma. Estos “glitches” en el suministro de energía pueden lograr, con mucha probabilidad,
que circuitos realimentados, como contadores y registros, cambien de estado inopinadamente.

Es necesario resolver la situación, para lo cual debe conectarse, entre el terminal de Vcc y el de tierra
de cada IC, y lo más cerca posible al IC, un condensador de desacople (“decoupling capacitor”) que
absorba, en el sitio, el pico de corriente, y no se lo pase a la fuente de alimentación. El valor de este
condensador suele ser entre 0.01 uF y 0.1 uF, de cerámica. Un circuito que NO tenga este
condensador, está mal diseñado, NO IMPORTA SI FUNCIONA...

El mismo problema se presenta, y más agravado, en los CMOS, ya que éstos ni siquiera tienen
resistencias de carga: Sólo los dos transistores P y N a la salida.

EQUIPO Y SALIDAS
Solemos contar con un generador de pulsos al que le cambiamos el período y el “dutty cycle” de la onda
para ajustarlo a nuestro diseño.

Para ver los valores a veces se usan el multímetro y el osciloscopio, y también unas “puntas lógicas” que
despliegan de manera luminosa el estado de encendido o apagado de cada línea. También suele haber
unos pulsadores, que permiten inyectar señales inclusive en terminales que están conectados...

Las salidas suelen ser LEDs (diodos luminosos), que consumen como norma entre 10 y 16 mA, y el
voltaje en sus terminales, cuando conducen casi siempre es de unos 1.2 V (estas características hay que
verificarlas caso por caso con el manual de especificaciones; cambian dependiendo, por ejemplo, del
color del LED!). Si se va a alimentar un LED desde una compuerta, éste tiene que tener una
resistencia limitadora de corriente, en serie, que garantice que los parámetros antes mencionados se
cumplan; de lo contrario se quemará el LED (y posiblemente la compuerta?)

Cuando el dispositivo de salida es un “7 segmentos” o similar, hay que escoger el circuito que lo maneje,
de acuerdo a su característica, pues hay de dos tipos: Ánodo común y de cátodo común.

C3-128
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

QUÉ COSAS VAN A FALLAR EN SUS PROYECTOS DE LABORATORIO!!!


Los conceptos de esta sección no necesariamente los va a comprender el primer día de clase. Guarde el
documento hasta que la necesidad se presente más adelante. Recomiendo imprimir estas hojas, y
tenerlas como un "check list".

1) FAN OUT

Si no lleva una contabilidad estricta de cuántas cargas ha colocado en las diferentes salidas de las
compuertas y flip-flops (FF) que las manejan, el circuito:

simulará bien (en EWB, Simulink o PSpice)..., pero no funcionará en el protoboard.

Una señal que va por todas partes es, por ejemplo: El reloj; otra, el Reset...

Verifique cuál es el Fan Out de la familia de chips que está usando. Úselos TODOS de la misma familia.
Por ejemplo, que todos sean 74LSxxx. Cuando mezcla familias, la regla normalizada no funciona, y
usted debe hacer cálculos de voltajes y corrientes individualmente, para saber cómo conectar las
salidas de una familia de Circuitos Integrados, con otras... (No es que no se pueda hacer; sólo que ahora
no es tan fácil como contar del 1 al 10)

El Fan Out suele ser 10 normalizado, para TTL, y 20 para CMOS (VERIFIQUE LA VALIDEZ DE
ESTA PREMISA CON LA FAMILIA DE CHIPS QUE VA A EMPLEAR); es decir, que cada salida
puede manejar hasta un máximo de 10/20 terminales de entrada (de componentes de la misma familia).
Si hay más cargas que 10/20, hay que replicar las señales. Para ésto debe tratar que las replicadas tengan
el mismo retraso; es decir, que todas pasen por igual número de negadores/buffers/drivers, etc. Esto
TIENE QUE HACERSE ASÍ SIEMPRE, pero sobre todo si la señal ES LA DEL RELOJ. Todas las
señales que lógicamente sean "el reloj", pero que no sean eléctricamente las mismas (relojes replicados),
deben subir y bajar lo más sincronizadamente posible las unas a las otras; de lo contrario, usted no
tendrá UN reloj, sino varios...; ¡ su diseño no será SINCRÓNICO! (¡y no funcionará !)

Debe cerciorase de que todas las entradas tengan FAN-IN de 1 (En algunos circuitos antiguos ciertas
señales, como el Reloj, tenían un FAN-IN de 2, o más... Entonces, esas no cuentan como 1, sino que
son 2... Nada se pierde con verificar)

2) MULTIPLICACIÓN (AND) POR EL PULSO DE RELOJ

Si hay por lo menos una compuerta que está multiplicando (and) el pulso de reloj por una combinación
de salidas de Flip-Flops (FF), la forma en que todo funcione a la perfección es que el reloj ejecute las
transiciones CON EL BORDE DE BAJADA. La lógica detrás de esto es la siguiente:

Sea: Z = f(Q1...Qn) * Cp

Mientras el reloj está en cero, la compuerta que multiplica el pulso de reloj por una combinación de
salidas de FF (f(Q1...Qn) en la ecuación de Z), está entonces en cero. El reloj sube ahora a 1. Si
f(Q1...Qn) vale 1, Z comienza a valer "Cp". Note que, ahora, NADA en "f(Q1...Qn)" se mueve, ya que

C3-129
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

TODO cambio en Q1...Qn se hará SOLO con el borde de bajada del reloj (esa es la premisa de diseño
de redes sincrónicas).

Luego de permanecer un cierto tiempo en 1, el reloj baja a cero. INMEDIATAMENTE la señal Z vale
CERO. Ahora, sí es cierto que "f(Q1...Qn)" se mueve, y pueden producirse picos, riesgos estáticos y
dinámicos, multiplicaciones de variables afirmadas por variables negadas (spikes), etc.

Esto ¡ AHORA NO IMPORTA !, ya que Cp vale CERO y cierra el paso de todos esos inconvenientes,
hacia Z.

Note que si el reloj está haciendo cambios con el flanco de subida, usted TENDRÁ PROBLEMAS CON
LA ECUACIÓN Z, que se reflejarán en que Z no valdrá UN "Cp", sino que podrá tener picos. Usted
seguramente necesitará muchas de estas señales, que irán a contadores y a otras unidades que tienen
memoria. Si son contadores, éstos se adelantarán.

Todo iría muy bien si usara un reloj que opere con el borde de bajada. Solo hay un problema: La gran
mayoría de los Flip-Flops y Contadores se activa con el borde de ¡¡ Subida !!.

La solución consiste en tomar la fuente de reloj, NEGARLA para llevarla a los Flip-Flops y Contadores
que se activen con el borde de subida, y en los sitios en donde haya que hacer funciones del tipo Z =
f(Q1...Qn) * Cp, continuar empleando la señal AFIRMADA. (cfr. referencias tales como el Wakerly)

También se deben ecualizar las trayectorias del reloj afirmado y negado, para evitar, en lo posible,
retrasos. Y si tienen que mezclar circuitos que operan con el borde de subida, con los que funcionan
con el de bajada, HAY QUE HACERLO CON EXTREMO CUIDADO.

3) ESTADO INICIAL

En el laboratorio solemos hacerla la inicialización a mano, empleando un botón de MASTER RESET.


Si su circuito de inicialización es simple (sólo el botón y sus drivers), PUEDE existir el problema de que
la señal de reset se desactive (vaya a 1) muy cerca del momento en que el reloj está cambiando también.
Esto PUEDE (o no) producir una carrera, y dar al traste con el funcionamiento del circuito (Lo ideal
sería que NO hubiera pulsos de reloj hasta un rato después de terminado el lapso de inicialización)

La solución se logra haciendo que el estado inicial esté representado por un sólo
flip-flop, que se pone en 1 cuando todos los demás FF (y contadores, etc.) se ponen
en cero. Luego, con el primer pulso de reloj, y sin que medie ninguna otra señal,
se pasa al estado siguiente, que es REALMENTE el primero de su circuito. De esta
manera, si hay algún problema como el mencionado, lo más que puede ocurrir es
que haya un retraso de un pulso de reloj antes de comenzar todo a funcionar como
estaba previsto... (cfr. Hágase la Luz en este mismo capítulo)

C3-130
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

4) SEÑALES NO SINCRONIZADAS

En nuestras redes secuenciales, TODAS las señales tienen que estar SINCRONIZADAS. Las entradas
manuales o provenientes de otros subsistemas, están desincronizadas. Hay que sincronizarlas (además
de eliminarles el REBOTE).

Una señal debe sincronizarse EN UN SOLO PUNTO (un sólo FF), cuya salida ES la señal que se usa.
Por ningún motivo puede sincronizarse una señal EN VARIAS PARTES.

5) SEÑALES MÁS RÁPIDAS QUE EL PULSO DE RELOJ

Suponga que diseñó un control de semáforos, con un reloj de 30 segundos. Si su circuito es sincrónico,
cuando una persona llegue al botón para activar el paso de peatones y lo oprima, tiene que activarse el
FF de sincronización. El problema es que el pulso de reloj puede demorar un promedio de 15 segundos
antes de activarse (30 segundos máximo) ¡ El peatón no tiene por qué estar pendiente de este detalle !
Entonces, es necesario almacenar la acción de ese botón hasta que llegue el pulso de reloj. Se necesita
un FF SIN reloj (el primer S-R [Eccles-Jordan] que se estudia en clase, con 2 compuertas Nand
realimentadas). En una entrada estará el botón del peatón, y por la otra su circuito deberá devolver ese
FF a cero, cuando haya procesado esa entrada.

6) FALTA DE SOPORTE PARA "DEBUGGING"

Si usted no puede verificar la operación de su circuito, Pulso a Pulso o a baja velocidad, Instrucción por
Instrucción, paso a paso... ¡ está bien lejos de ponerlo a funcionar ! Al concebir su diseño tiene que
pensar en poder ver por qué no funciona. (“Si no sabe cómo lo va a probar, ni siquiera lo arme”;
recomendación de Uribe)

7) SWITCHES CON REBOTE

Este problema tiene una solución clara y específica, que se aprende en la teoría, tanto en redes
combinatorias como si emplea microcontroladores. ¡ NO INVENTE !

8) LED. CARGAS NO TTL

Los LED en circuitos TTL tienen que estar manejados por un buffer. Si los coloca a tierra
DIRECTAMENTE a la salida de un FF TTL, ¡ éste no funcionará !. Si los coloca a tierra a la salida de
compuertas TTL que luego va a emplear en otras secciones, no funcionarán. Un LED a tierra hace
que la salida TTL del circuito al cual se conectó, YA NO SEA UNA SEÑAL TTL APROPIADA
PARA FUNCIONAR en el resto del circuito digital (los valores de voltaje y la capacidad de manejo de
corriente de la compuerta, seguramente estarán muy afectados). Si son CMOS, puede ser otra cosa...

9) ALIMENTACIÓN DEL PROTOBOARD

Algunos vienen con su propia fuente (5V @ 700 mA). Deben notar que, al poblarlos con circuitos TTL
de la serie LS, los Protoboards probablemente se están sobrepasando de los 700 mA... (uno no

C3-131
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

imaginaría que componentes tan pequeños consumieran TANTO...); esto hace que la fuente salga de su
punto de trabajo, con lo que se consigue:

 Que el voltaje baje de 5V, violando posiblemente el nivel de trabajo satisfactorio garantizado para
los chips
 Que la fuente salga de regulación, por lo cual el voltaje DC comienza a tener "ripple", que es una
ondulación (AC) superpuesta a la menguada señal DC.

El resultado neto es que el circuito no funciona, lo hace intermitentemente, u opera hasta que lo vaya a
presentar... EFECTO ENTREGA --corolario de Uribe sobre la ley de Murphy--:

"Todo proyecto de Digitales funcionará hasta el momento en que lo vaya a presentar; ahí dejará de hacerlo.
Los profesores que lo vieron trabajar la tarde anterior no podrán asistir a la entrega definitiva,
a atestiguar fehacientemente que no es sólo bla-bla lo que se va a decir..."

10) SOLDADURA!!!

Es cierto que puede estar prohibido realizar soldaduras en el recinto de los laboratorios, pues algunos
han quemado con un cautín los valiosos y flamantes instrumentos nuevos... Pero eso NO significa que
los interruptores no tengan qué soldarse a los cables que van a servir para conectarlos al circuito. Los
conductores pelados, entorchados en los terminales de los interruptores, no hacen buen contacto (tanto
que se preocupan del rebote, para luego venir a dejar flojos los terminales...) HAY QUE
SOLDARLOS. Pueden hacerlo en sus casas, en el corredor, PERO HÁGANLO...

11) CONDENSADORES DE DESACOPLE

Ya lo dijimos con anterioridad: Durante las transiciones hay un pico de corriente de aproximadamente
40 mA, POR CADA SALIDA del chip. Si hay varias señales conmutándose dentro del mismo IC (que
es lo más común...) el problema empeora. Y como los circuitos complejos suelen ser sincrónicos, todas
las señales cambian AL MISMO TIEMPO. ¡ PEOR ! Si tenemos 20 IC, cada uno con 80 mA o más,
podemos tener picos de más de UN (1) amperio en la fuente de alimentación!!!
Debido a la impedancia de salida de la fuente (empeorada por la resistividad del Protoboard!!! y la del
cableado de distribución de la alimentación, y si usan cablecitos MUY DELGADOS para conectar el
Protoboard a la fuente), estos picos se suman y pueden hacer que la alimentación tenga una
disminución en su valor. Estos “glitches” en la alimentación pueden hacer que circuitos realimentados
(contadores y registros), cambien de estado inopinadamente.
Es necesario resolver esta situación, para lo cual DEBE CONECTARSE, entre el terminal de Vcc y el
de tierra de cada IC, y lo más cercanamente posible al IC (para evitar introducir INDUCTANCIAS
parásitas, que empeoran el asunto), un condensador de desacople (decoupling capacitor) que absorba
el pico de corriente, y no se lo pase a la fuente de alimentación. El valor de este condensador suele ser
entre 0.01 uF y 0.1 uF. Son condensadores cerámicos.
UN CIRCUITO SIN ESTOS CONDENSADORES, ESTÁ MAL DISEÑADO,
¡ AUNQUE FUNCIONE !

C3-132
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

A veces (en trabajos que no van a producción), nos las arreglamos con UN condensador de desacople
por cada 10 Circuitos Integrados... PERO HAY QUE COLOCARLOS. NO LO OLVIDE.

NOTA: En alguna oportunidad alguien conectó los condensadores de desacople, en serie entre la fuente de alimentación y
el Protoboard! Eso no es lo que esta nota señala... y el circuito de ninguna manera funcionará así, ¡ como es apenas lógico
esperar ! De hecho, el alumno, a quien no le funcionaba el circuito, me llamó y me dijo que ya lo había arreglado, al retirarle
todos los condensadores de desacople...

12) DIAGRAMAS

La mayoría tiende a usar como documentación principal de diseño, el diagrama circuital extraído de
EWB, Simulink o PSpice. Esto es ABSOLUTAMENTE INCONVENIENTE. Cuando se está en la
etapa de diseño, lo importante es establecer la funcionalidad de los diversos subsistemas (contadores,
multiplexores, sumadores...) y las relaciones que existen entre ellos (el sumador se conecta a la salida de
XXX; el contador #1 se alimenta de la entrada YYY en el momento o estado ZZZ, etc.)

Es FUNDAMENTAL generar primero un  DIAGRAMA EN BLOQUES, en el que se destaquen


dichos subsistemas y sus interrelaciones (cfr. Wakerly, distintos tipos de diagramas y el momento
apropiado de su APLICACIÓN).

Sobre ese Diagrama en Bloques es que se diseña el Algoritmo, que es la forma en que su circuito
operará. Usted. puede describir su algoritmo de manera verbal, o empleando un lenguaje de
programación cualquiera, o alguno específico (ABEL, VHDL, Verilog) o, inclusive, un Diagrama de
Estados. Lo importante es que estén conscientes de que su sistema NECESITA un algoritmo, que es el
que va a producir como resultado que su circuito funcione.

Después de lo anterior, hay que hacer un  DIAGRAMA LÓGICO, que muestre con un mayor nivel
de detalle los componentes (contadores, registros, sumadores) y sus conexiones, mediante compuertas
AND/OR, o NAND.

Ambos diagramas, el de Bloques y el Lógico, sirven para explicar al profesor –y a usted mismo– el
funcionamiento de su circuito. Nótese que aquí no aparece por ningún lado cuáles son los pines de tal o
cual chip, ni cómo se alimenta el Vcc, ni cuáles pines están conectados o desconectados. Ese nivel de
detalle viene después, cuando ya se sabe que el algoritmo funciona, operando sobre sus
correspondientes subsistemas (llamados también el "Data Path")

Por último se pasa su diagrama lógico al EWB, el Simulink o el PSpice (si es que va a simularlo), o al
Protoboard; allí sí es necesario un diagrama final: El  CIRCUITAL, en el que aparecen los chips,
identificados con sus nombres (74LS193, 74LS00, etc.) y no por función; se muestran las conexiones
entre pines, alimentaciones, etc.

Diseñar directamente a nivel de Diagrama Circuital, OSCURECE. Pero, ocurre... que el EWB, el
Simulink y el Pspice sólo manejan bien el Diagrama Circuital (esto no es estrictamente cierto, pero
trabajar con las compuertas y los Flip-Flops individuales no es, aparentemente, lo que los alumnos
suelen hacer...)

C3-133
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Esta es una ocasión en la que ¡ LA COMPUTADORA ENTORPECE SU TRABAJO !

De ser este su caso, RETORNE AL MILENARIO ¡ PAPEL Y LÁPIZ !. ¡ No todas las etapas de su
trabajo tienen que hacerse con la computadora !

Otro ejemplo de la computadora entorpeciendo su trabajo se ve cuando se pide en el laboratorio que


representen por escrito el algoritmo, bien sea como un diagrama de estados o uno de flujo. La reacción
inmediata del estudiante es buscar en el PC el PAINT, el PAINT-BRUSH o alguna herramienta similar,
y comenzar a dibujar circulitos...

¡ REGRESE INMEDIATAMENTE AL PAPEL Y LÁPIZ !

No pierda tiempo. Cuando ya su algoritmo funcione, y su diagrama esté bien, puede ser que un
dibujante se lo pase –en la oficina– usando Flow, Visio, o cualquier otra herramienta apropiada (Si usted
aprendiera, en otro curso, a emplearlas, estaría muy bien visto también; ¡ pero no se deje atrapar ni
por la herramienta ni por el PC !)

13) IMPROVISACIÓN E INGENIO... VS. ¡ MÉTODO !

Algunos no hacen sus diseños empleando las técnicas enseñadas en la teoría. Son renuentes a creer que
necesitan un algoritmo; piensan que pueden diseñarlo todo poniendo una compuerta aquí, otra allá, y un
monoestable acullá....

El fenómeno es similar a quien, durante su juventud, se decide a tocar la guitarra. Toma el instrumento
de la familia, aprende algunos acordes, sus amigos se le unen para cantar rancheras trasnochadas, se
convierte en el alma de las veladas..., pero no podrá nunca dar un concierto. Para eso tendría que
ESTUDIAR la técnica, aprender armonía, solfeo, lectura musical, hacerse un repertorio... y muchas
cosas más.

Es la diferencia entre un profesional y un aficionado. Usted tiene que ser un profesional. Los
aficionados no aplican

Si pone de lado lo que se le enseña, y trabaja sin emplear la técnica, está haciendo su proyecto como si
no hubiera tomado el curso. Sucedería igual si, durante el semestre anterior, algún amigo le hubiera
pedido que le ayudara a diseñar, por ejemplo, un juego de Ping-Pong. Seguramente que, con su ingenio,
¿algo habría resuelto...? Esta cualidad es fundamental en los ingenieros, ¡ PERO NO ES
SUFICIENTE ! Por eso se va a la universidad.

Algo parecido ocurriría si usted encontrara una persona accidentada en la carretera y la ayudara,
devolviéndole las vísceras al estómago y amordazándolo estrechamente con sábanas mientras lo llevan
al hospital. Muy comedido de su parte, muchas gracias; pero no podrá decirse por eso que usted es un
médico o un doctor.

Un algoritmo es un procedimiento. Su circuito va a seguir –si es que ha de funcionar– un


procedimiento. La descripción del algoritmo puede ser verbal, o realizarse mediante un Diagrama de
Flujo, como hacen los programadores, o puede ser descrito mediante un Diagrama de Estados (todos

C3-134
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

los diagramas resultan más o menos equivalentes; usted selecciona el que mejor le calza). O puede ser
presentado empleando algún lenguaje de programación, que se escoge convenientemente. (Si un
programa necesita o no de un diagrama de flujo previo, puede ser discutible).

Tener el algoritmo expresado mediante un lenguaje de programación le permitiría, de paso, simularlo, y


así poder garantizar que su algoritmo realmente funciona. (Además, podría después emplear técnicas
automatizadas que generarían el circuito final, a partir de su programa: VHDL, ABEL, Verilog, etc. cfr.
el código de varios problemas resueltos aquí, como el del Juego de Ping-Pong)

Recuerde que a usted no se le va a calificar sólo por el resultado, SINO TAMBIÉN POR LA
METODOLOGÍA. Usted tiene que demostrar que sabe. El resultado es importante, pero es la
metodología la que garantiza el resultado (ayudada con un poco de ingenio...)

!CUIDADO CON LA IMPROVISACIÓN!

Otro tema en el que inventamos es en el de la programación. Resulta que usted ha tomado sus cursos
de electrónica y digitales; sabe elaborar su diseño; emplea condensadores de desacople; lleva el control
del fan-out..., pero al final, hay que hacer un programa para el micro. Y entonces usted se enfrenta a
conceptos tales como colas, procesos, semáforos, interrupciones, drivers, expropiación y apropiación de
recursos, todo lo cual se estudia en Sistemas o en una licenciatura de Computación. Usted, sin embargo,
no tiene cursos apropiados y decide “improvisar”.

Tenga mucho cuidado. Esa no es una actitud profesional.

Su diseño puede padecer defectos ocultos, que para un profesional serían evidentes, pero no así a los
ojos del improvisado. Y usted tiene una responsabilidad social. Su proyecto puede ocasionar toda
clase de inconvenientes, algunos de los cuales pueden resultar, inclusive, mortales (piense en una falla en
el control de un tomógrafo. cfr. capítulo 1, en Tomógrafos Computarizados, y la falla del Ariane 5).

14) MAL USO DE LOS INSTRUMENTOS

Un grupo quemó su microcontrolador haciendo lo siguiente: Empleó el osciloscopio para ajustar la


fuente de 5 V. DC, pero olvidó revisar si la punta estaba atenuada por 10 o no. Sí, tenía activo el
divisor; y cuando midieron 5 V, la fuente estaba entregando 50 V. Además, en un arranque inverosímil,
le pidieron prestado el micro a sus compañeros (no sé qué pensaban verificar) y se lo dañaron también!

Otros frieron su microcomputador siguiendo el mismo procedimiento, pero ahora la punta NO estaba
atenuada... Sólo que las perillas de calibración estaban al otro extremo, fuera de su posición
convencional. Y cuando midieron 5 V la fuente estaba entregando 12V. Si un cirujano blandiera su
bisturí con tan desacertada maestría, lo demandarían e iría preso. Ustedes también son profesionales...

15) LA JUSTIFICACIÓN

En algún proyecto los alumnos se decidieron a usar 16 LEDs. Cuando pregunté por qué no 4, 5, 7 o 12,
me dijeron que el demultiplexor que consiguieron era de 4 a 16... ¡ Esa no es realmente ninguna razón !

C3-135
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Sería como si a usted le hubieran recetado 4 pastillas para curarse de alguna infección, y se hubiera
tomado 20, porque 20 eran las que traía el frasco que el farmaceuta le dio.
Usted se está dejando atrapar por el entorno. Note que, pensándolo un poco, hubiera podido reducir
los 16 LEDs a 8, sólo con no usar todas las salidas DCBA del contador (¡ que también lo atrapó !), sino
solamente CBA. O podría haber hecho que el contador no llegara a 16 sino hasta el número que creyera
conveniente para su diseño. En todo caso, esto demuestra que les suele faltar el primer paso del diseño:
LA ESPECIFICACIÓN TÉCNICA.
Éste es el documento mediante el cual, el cliente solicita la funcionalidad que desea en el proyecto que
encomendó. Si el cliente quiere 7 LEDs, una de dos: O el ingeniero lo convence de que son mejores 8 o
4, o le tiene que entregar 7 LEDs. No le puede salir con 16 dizque porque su decodificador era de 4 a
16!!! Usted le va a hacer comprar a su cliente (¡ su papá !) LEDs que no necesita, más todo el soporte
asociado: Resistencias de 330 Ohms, posiblemente drivers, espacio en el protoboard ("Real Estate";
necesitará uno más grande que si hubiera usado 7 LEDs), y habrá perdido confiabilidad ("Reliability"),
que es inversamente proporcional a la cantidad de componentes empleados.
En resumen: Sus proyectos tienen que incluir:
 La Especificación Técnica de su diseño, que debe con precisión contener, como mínimo:
 Qué va a tener su circuito (cuantos LEDs, interruptores y demás elementos de interacción con los
usuarios).
 Cómo va a funcionar: Cuándo gana un jugador; cómo se representa el evento ganancioso. Si su
proyecto es, por ejemplo, un frecuencímetro: Cómo mide frecuencia, período, etc.; cuántos dígitos
se van a representar; cómo va a eliminar el 10% de error ocasionado por el +- 1 conteo, que
produce un error de 1 en 10)
 El Diagrama en Bloques, tal como mencionamos arriba, acompañado de la descripción exacta del
algoritmo. Yo prefiero que me lo den en algún lenguaje de programación (BASIC, C, JAVA), y que
me muestren la simulación.
 El Diagrama Lógico, tal como mencionamos arriba.
 El Diagrama Circuital.
 La simulación en el EWB, el Simulink o el PSpice
 El protoboard con el circuito, según el Diagrama Circuital (o el impreso, si corresponde).
 Es fundamental que anote EL TIEMPO empleado en cada parte del diseño, para que lo reporte en el
informe final, en el cual deberá indicar los costos de análisis, diseño, fabricación, pruebas,
componentes, etc. Lleve siempre su bitácora!
 Si es su primer diseño digital, es importante que se vaya acostumbrando a pensar que hay un mundo
real, más allá de lo académico, en el cual no sólo es importante que funcionen las cosas, sino que
deben ser pautadas mediante cronogramas de trabajo, especificaciones, etapas de diseño,
presupuestos y costos, e informes.
Finalmente, no dejen que los exámenes le resten impulso a su actividad.

La elaboración de un proyecto no es una etapa de descanso que se da en el laboratorio


para que ustedes tengan facilidad de presentar sus exámenes de teoría…

Hay que cumplir con todo. "C'est la vie".

C3-136
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

 REDES COMBINATORIAS

PROBLEMA TÍPICO: LA FÁBRICA DE CHOCOLATES

E
L gerente de una fábrica de chocolates, de profesión Administrador de Empresas, tiene un
serio problema en su línea de producción; la sección que elabora las pastillas individuales
funciona muy bien, y entrega su producto a una banda transportadora atendida por dos
operadoras (Lucy y Ethel) que se sientan enfrente la una de la otra. De un recipiente común a
ambas empleadas, sacan las cajas en donde deben empacar los chocolates, las sitúan en una pequeña
plataforma localizada convenientemente, toman algunas pastillas de las que pasan enfrente por la banda
transportadora, y las van empacando hasta llenar la medida; cierran la caja, la colocan en una repisa
situada al lado de cada operadora, y reinician la operación, que continúa así durante toda la jornada.

A usted lo han llamado para que automatice esa sección de la fábrica, pues a veces surgen
inconvenientes que resultan en la pérdida de la mercancía. El gerente le cuenta que cuando llueve casi
siempre falta una operadora; la que queda no alcanza a empacar todas las pastillas que se transportan,
con lo que las excedentes caen al suelo y hay que desecharlas por razones sanitarias.

Cuando están presentes ambas empleadas ocurre también que las cajas se terminan, por falla temporal
en el proceso de mantener una cantidad suficiente, y el resultado es el mismo: los chocolates se pierden.

Otras veces alguna empleada se ausenta a tomar café, o a realizar alguna diligencia personal, y en el
ínterin se repite el problema. Por cierto, el gerente le dice a usted, como parte de su problemática, que la
cafetera no debería encender si no hay al menos una operadora presente.

En una rápida inspección a la planta usted se percata de que la banda transportadora posee tres
interruptores –identificados como Parada, Despacio o Rápido– por medio de los cuales el personal de
mantenimiento puede operar el dispositivo. Los controles son tales que también pueden operarse de
forma remota, aplicándoles un voltaje DC, siendo 5 voltios el valor que los activa y 0 voltios el que los
desactiva…

IDENTIFICACIÓN DE ENTRADAS Y SALIDAS

La función principal de un ingeniero es resolver problemas, como parte de lo cual debe pasar por un
proceso de comprensión y análisis, que incluye la identificación de las variables de entrada, que son las
que le van a servir para generar las salidas que produzcan el comportamiento esperado. Es importante
tamizar la presentación que el cliente le hace de sus necesidades, porque no siendo él un especialista en
Ingeniería Digital, es muy probable que haya aspectos que le ha mencionado con angustia, pero de los
cuales, en realidad, puede prescindirse. Por ejemplo, si usted está pensando en adquirir un dispositivo
que indique si llueve en su área de influencia, olvídelo. En nuestro caso, aun cuando la lluvia fuera la
causa de la ausencia de alguna operadora, lo importante es que la empleada no está; la razón de su
ausencia no tiene mayores consecuencias.

C3-137
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Si no se acierta con la selección precisa de las entradas, se presentan dos problemas de orden diferente,
bien sea que sobren entradas, bien sea que falten. Por ejemplo, si usted no cae en cuenta de que no
necesita detectar si llueve o no, su solución será más costosa de lo necesario, pero muy probablemente
funcionará bien. En cambio, si usted olvida, por ejemplo, tomar en consideración las Cajas, su solución
no funcionará: cuando falten Cajas los chocolates se perderán, usted no podrá cobrar por sus servicios
y posiblemente hasta le entablen una demanda…

Entonces, lo importante es seleccionar un conjunto exacto de entradas sobre las cuales su sistema va
a tomar decisiones; si escoge de más, posiblemente su sistema también funcionará bien, a expensas de que
le va a resultar más caro, pero si su selección e identificación de variables de entrada está por debajo del
mínimo imprescindible, su sistema fallará.

Identificar las salidas tiene una importancia similar. Si está decidido a automatizar la cafetera, piénselo
dos veces. El orden de importancia de la solución del problema en la banda transportadora es enorme,
pues hay mucho dinero involucrado. La importancia de atender la cafetera es mínima. No mezcle
problemas disímiles. Convenza al gerente de que se olvide de la cafetera, pues probablemente el
ahorro que pueda obtener allí no será suficiente ni para pagar lo que usted va a cobrarle por resolver el
problema. En todo caso, un temporizador económico, comprado en alguna tienda de suministros
eléctricos, es todo lo que con toda seguridad se necesite…

Ahora que se ha olvidado de la cafetera puede concentrarse en el problema principal. Las variables que
debe manipular (las salidas del sistema que usted va a diseñar) son los elementos de control que en este
caso existen en la banda transportadora: Parada, Despacio o Rápido.

UNA SOLUCIÓN: PLANTEAMIENTO

En esta época en que por $1 puede comprarse un chip microcontrolador, dispositivo programable en
su propio lenguaje ensamblador, o en el popular “C”, la primera alternativa, y quizás la solución
definitiva se centre en un elemento así. Esos dispositivos son verdaderos microcomputadores
encapsulados en un chip, de entre 8 y 48 terminales, por los cuales un programa puede leer el valor de
algún interruptor, como entrada, siguiendo normalmente la misma convención anterior: 0 voltios
indican que la variable no se ha activado y 5 voltios señalan que sí.

En relación a las salidas, su programa puede producir voltajes de 0 ó 5 voltios en los terminales
correspondientes, pudiéndose emplear 0V para desactivar alguna variable externa y 5V para activarla.

Si el fenómeno que se desea controlar produce entradas con otros rangos de voltajes, o si sus salidas
deben tener valores distintos, es su responsabilidad suministrar unidades que normalicen estas variables
y las hagan compatibles con el micro. Asimismo hay que tomar en cuenta otras necesidades, como
eliminar ruidos (filtros), amplificar o atenuar señales, incluir resistencias limitadoras de corriente, etc.

Podemos suponer, entonces, que contamos con un microcontrolador que tiene un número de
terminales de entrada, de los cuales escogeremos tres, uno para saber si hay Cajas o no, lo cual es muy
simple: puede colocarse en la base del recipiente en el que se alojan, un soporte con un mecanismo de
resorte, calibrado, de tal manera que cuando no haya cajas el soporte se levante, abriendo un
microswitch que produce 0 voltios. Cuando hay cajas el microswitch se activa y entrega 5 voltios.

C3-138
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Dos terminales adicionales pueden conectarse a llaves de las operadoras; cuando ellas se sientan a
trabajar deben insertar su llave dentro de una cerradura que activa un interruptor que, generando los
voltajes 0 ó 5, indicará si la operadora está presente no. Para garantizar que la operadora no se vaya sin
quitar la llave, puede fijársela, por ejemplo, al cinturón…
Supondremos también que tenemos acceso a tres terminales de salida que entregarán 0 o 5 voltios e
irán a conectarse a los elementos de control de la cinta: Parada, Despacio o Rápido.

En estas condiciones, la solución a este ejercicio puede plantearse mediante la siguiente tabla. En ella, 0
voltios se representará por “0”: inactivo, pero el voltaje correspondiente a 5 voltios, a veces en realidad
son 12v, 3v, 2v, 1.8v… por lo que suele representarse simplemente por el dígito “1”: activo.

Index  INPUTS OUTPUTS


(“C” 
Table) C L E P D R
0 0 0 0 1 0 0
1 0 0 1 1 0 0
2 0 1 0 1 0 0
3 0 1 1 1 0 0
4 1 0 0 1 0 0
5 1 0 1 0 1 0
6 1 1 0 0 1 0
7 1 1 1 0 0 1 
Al lado izquierdo se colocan las variables de entrada, C, L y E. Una señal independiente, como se ha
dicho, solo puede tomar el valor 0 o 1. Cuando tenemos que analizar dos (2) entradas, hay que estudiar
todas las posibilidades; es decir, ver qué ocurre cuando una variable vale 0, mientras la otra toma los
valores 0 y 1, y cuando la primera está en 1, la otra puede tomar de nuevo los valores 0 ó 1. De esta
manera, las alternativas –o combinaciones– que hay que analizar para dos (2) variables, son 4. Y en
general, habrá un total de 2^n, donde n es el número de variables de entrada. En nuestro caso tenemos
3 entradas, y por tanto las combinaciones son las 8 que se incluyeron en la tabla.

Tenga en cuenta que la sección izquierda de la tabla tiene que hacerla en forma automática, con rapidez,
seguridad y certeza; las combinaciones entre las variables de entrada son como las líneas que forman los
renglones en el papel rayado que usted usa. Si alguna vez no tiene papel rayado, sino blanco, tendrá que
hacer usted mismo las líneas, pero por ese trabajo no le van a pagar... Ese es problema suyo.

Así pues, en estas tablas, denominadas Tablas de Verdad, las combinaciones entre las variables de
entrada se dan por sentadas; usted tiene que hacerlas con prontitud, y no es ahí donde radica la
dificultad para la solución del problema. Dicho de otra manera, si usted llega al examen y no está seguro
de cómo hacer las combinaciones de entrada… está perdiendo un tiempo precioso. Ejercítese; haga 256
combinaciones distintas (8 variables) hasta alcanzar automatismo y agilidad en esta operación.

Analizando la tabla se observa que las primeras cuatro filas tienen el factor común: que C==0, lo que
significa que no hay Cajas; por tanto, la cinta transportadora debe Pararse: P=1, tal como se plasma en

C3-139
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

la tabla. La quinta fila representa la primera posición en la que sí hay cajas, C==1, pero no hay ninguna
operadora (es sábado, o está de noche), por tanto también aquí la cinta debe pararse, y P=1.

En las dos siguientes filas hay Cajas pero solo está presente una empleada; por tanto la cinta debe
moverse Despacio, así que D=1. Y solo en la última posición se cumplen las condiciones que hacen que
la cinta pueda moverse a alta velocidad: hay Cajas, están presentes Lucy y Ethel, y por tanto, R=1.

PROGRAMACIÓN DE LA SOLUCIÓN

Una forma de programar la solución a este ejercicio consiste en ver la tabla como si fuera un arreglo de
una dimensión, trabajable en lenguaje “C”. Usted recordará que este tipo de estructura de datos tiene
dos dimensiones en los lenguajes de programación: la ubicación y el contenido. La posición es un
ordinal (no negativo), que identifica el elemento de la tabla mediante su índice; en “C” los arreglos
comienzan en la posición “0” y progresan hasta alcanzar “n-1” para un total de “n” elementos (otros
lenguajes colocan el primer elemento en la primera posición).

De esta manera pueden leerse los tres terminales de entrada, generar con sus valores un índice que le
sirva al programa para extraer de la tabla las respuestas, pues eso son los valores almacenados ahí…

Así, si las entradas llegan en 100, extraeremos, según el ordenamiento de la tabla el quinto elemento (el
que tiene índice 4); como pude verse allí se han almacenado los valores: P=0, D=1, R=0 (010). Se llevan
esos valores a los correspondientes terminales de salida, y eso hará que la cinta transportadora vaya
moviéndose Despacio, como hemos definido.
El programa tiene el siguiente aspecto:
void main( void ) 
{  char entrada;     // 8 bits; los 3 primeros son C (I2), L (I1), E (I0) 
   char salida;      // 8 bits; los 3 primeros son P (O2), D (O1), R (O0) 
 
   char tabla[] = { b100, b100, b100, b100, b100, b010, b010, b001 }; 
                         // transcripción directa de la Tabla de Verdad 
 
   while( 1 ) {          // o for(;;): forever. Este programa nunca termina 
      entrada = input(); // input() es función de biblioteca. Retorna el 
                         // .. valor de los 3 bits de entrada. 
      salida  = tabla[ entrada ]; 
      output( salida );  // output() es función de biblioteca. Lleva al 
                         // .. exterior del micro, los 3 bits de salida. 
   } 

 
Si su compilador de “C” no entiende el símbolo b100 como un número, usted pude agregar al
comienzo unas definiciones del siguiente tenor:
#define  b000   0 
#define  b100   4 
#define  b010   2 
#define  b001   1 
(etc…)

C3-140
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

De dónde obtuvimos las equivalencias numéricas de los símbolos bxxx? A pesar de que ahora estamos
tratando con las salidas, podemos mirar la tabla en la sección de entrada; vemos allí cómo, por ejemplo,
b100 corresponde a la fila 4, y así sucesivamente.

Y llegamos al momento de hacer una observación notable. Las combinaciones de entrada con las
cuales hicimos la tabla, no tienen ninguna connotación numérica. Son las ocho posibles formas de
analizar todos los casos de “activo” o “no activo”, 0 o 1, que pueden establecerse con las tres variables.
Pero cuando indicamos cuál sería una posible tabla para que el “C” la manejara, a cada posición le
asignamos un índice, un entero ordinal, de 0 a 7 en nuestro ejemplo (8 valores), porque la
enumeración es la manera más elemental de identificación o individualización.

Ahora, somos libres de establecer una codificación, que es completamente arbitraria (todas las
codificaciones lo son), y bien podemos decir que al número decimal 0 puede asignársele el 000, al 1 se lo
hace corresponder con el 001, el 2 con el 010, y así sucesivamente hasta llegar al 7, que tiene designado
el 111 como código. De esta manera hemos representado unos símbolos que todos reconocemos como
números decimales, mediante otros que son combinaciones de valores ceros y unos.

Si analizamos la estructura de la codificación notamos que al codificar, los números decimales se


representan solo con ceros y unos; de ahí que tome el nombre de representación “binaria”, lo que
significa que solo dos números participan. También podemos tratar de escribir el código como si los
ceros y unos tuvieran el mismo sentido de coeficientes de una potencia, tal como hacemos en decimal,
en donde la potencia es diez, y por tanto las posiciones representan las unidades (10^0), las decenas
(10^1), centenas (10^2), etc.

En nuestro caso vemos que sí, que la primera columna puede verse como si representara las unidades
(2^0), la siguiente 2 (2^1), y en secuencia: 4 (2^2), 8 (2^3), etc. Como en decimal correspondían las
potencias de 10, ahora lo hacen todas las potencias de 2.

Una observación adicional, para remarcar el hecho de que esta es una de una cantidad indeterminada de
formas de hacer codificaciones para los números decimales. Si hubiéramos tomado, por ejemplo, la
secuencia 000, 001, 011, 010, 110, 111, 101, 100…, que es preeminente como veremos después (código
Gray), los números tendrían una codificación diferente, y ahora inclusive el código resultante no sería ni
siquiera “analítico”, significando con ésto que no hay una fórmula que produzca el número decimal a
partir de una sumatoria de exponentes de 2^0, 2^1, 2^2, 2^3, etc., cuyos coeficientes son los ceros y unos
del número binario.

Hay que hacer varios comentarios en relación al programa. En primer lugar, este tipo de programación,
en donde un microcontrolador está evaluando continuamente las variables de entrada y produce en
consecuencia valores de salida, son ciclos infinitos. Un dispositivo para controlar un horno de
microondas, o un televisor digital, nunca reposan: sus programas nunca terminan. Esta programación se
la conoce como propia de sistemas “embebidos”.

Después, si recordamos que un microcontrolador en la actualidad tiene tiempos de ejecución de entre 1


microsegundo y de 100 a 1000 veces menores, podemos pensar que es muy probable que resulte
exagerado pasar mirando las entradas y produciendo las salidas a tan altísima velocidad, cuando ni las

C3-141
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

cajas se acaban tan rápido, ni las operadoras aparecen y desaparecen así. Podríamos introducir un
“retardo” apropiado, por ejemplo de 500 milisegundos, al finalizar el ciclo, y todo funcionaría igual.
Ahora, inclusive, podría usarse ese tiempo del retardo para agregar más código dentro del micro, y
lograr que realizara funciones adicionales, si se necesitaran, sin interferir con el control del proceso. Esa
es la función de la orientación a múltiples tareas.

Por último, esta aproximación tiene una gran ventaja, que es en sí misma un gran inconveniente.
Cualquier problema de esta naturaleza (que se denominan redes Combinatorias) puede resolverse con el
mismo programa. Basta con escribir la tabla correspondiente, que relaciona entradas con salidas, y el
mismo código lo resolverá, pues éste es absolutamente general: hay una tabla en la cual, para todas las
entradas se han establecido todas las salidas. Se leen las entradas, se busca la respuesta en la tabla, y ese
es el valor que se le suministra a la planta.
16
Pero un problema con 16 variables de entrada ocupará 2^ posiciones, que son 65536, posiblemente
demasiado grande para un microcontrolador corriente. Y la velocidad de crecimiento de dicha tabla es,
como ya sabemos, exponencial; por cada variable de entrada que se incluya, la tabla se duplica. Así que
muy probablemente haya que establecer otras vías que minimicen el problema.

Pero, si hay capacidad de almacenamiento, ningún método es superior a éste.

Ejercicio: Realice un programa equivalente, en lenguaje ensamblador del micro.

SOLUCIÓN VÍA ROM

Un microcontrolador que lee una tabla, realiza unas funciones mínimas en comparación con sus
posibilidades. Este micro puede conceptualizarse como un pequeño CPU al que se le ha adosado una
memoria, en la que vive la información de la tabla. Esto significa que a lo mejor podemos reemplazar el
CPU por una circuitería muy simple que realice la misma función. Así, quedaría aislado el elemento de
memoria, que comercialmente se conoce como ROM/PROM/EPROM/EEPROM/Flash.

Una ROM es una tabla, armada solo con componentes electrónicos, en la cual se graban los datos,
ubicándolos en las mismas posiciones que vimos en el programa en “C”. Pero para leer la información,
basta con conectarle o alimentarle al chip de ROM, el índice que define la información que debemos
leer. Este índice se conoce como la “dirección” de la celda que dentro de la ROM contiene la
información que ella debe suministrar. Y los terminales por donde salen los datos son el puerto o bus de
“datos”. Los tamaños de cada uno de estos elementos dependen del modelo del dispositivo. Los valores
típicos corresponden a 8 bits para datos, y 16 para direcciones, pero hay toda una gama por ver.

En los dos casos que hasta aquí hemos visto, la manera como se introduce la información (tabla y
programa) dentro del correspondiente chip, es ejecutando un programa normalmente suministrado por
quien produce el dispositivo, y casi siempre gratuito y, mediante un módulo de programación, que se
conecta al PC empleando el puerto de comunicación serial, o el puerto de impresora, o el USB, y que
normalmente también es suplido por el manufacturante del chip, en donde éste puede alojarse mientras
el programa traslada la información entre el PC y el microcontrolador o la ROM.

C3-142
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

No es nada más complicado que eso. A esta operación se la conoce, por razones históricas, como
“quemar” el chip, y la tarjeta es la “quemadora”. En realidad, “programar el chip” y “tarjeta
programadora” son expresiones más ajustadas a la verdad.

SOLUCIÓN VÍA MULTIPLEXER

Si tomamos una “tajada” de la ROM, y extraemos una columna de datos, la salida será solo de un
elemento, aun cuando la cantidad de posiciones para él sigue siendo la misma que en el caso de la
memoria. La ventaja de esta aproximación es que hay un chip, llamado Multiplexor, que realiza esa
función de “tajada” de ROM.

Un multiplexor es un dispositivo que tiene el equivalente a la dirección, pero que aquí se denominan
convencionalmente “selectores”, y una única salida, a la cual se le pasa la información proveniente del
conjunto de entradas que posee, y que son 2^n, para un multiplexor de “n” selectores. Dicho de otra
manera, un multiplexor tiene “n” selectores, 2^n entradas, y una (1) salida que asume el valor de una de
las 2^n entradas, aquella designada mediante los “n” selectores.

Ejemplos de Multiplexores: El 74LS153 tiene 2 entradas, 1 selector y una salida. Se dice que es un
multiplexor de 2 a 1, y se lo representa como “2/1”.
El 74LS157 tiene 4 entradas, 2 selectores y una salida; es un multiplexor de 4/1.
El 74LS151 tiene 8 entradas, 3 selectores y una salida; es un multiplexor de 8/1.
Si se quiere resolver un problema que tenga más de una salida, como es el caso de la fábrica de
chocolates, hay que incluir un multiplexor por cada una. Los selectores se interconectan todos entre sí,
pues son un factor común al problema, y sus entradas se conectan a ceros y unos, de acuerdo a la tajada
correspondiente a cada salida, en la Tabla de Verdad. Así que dibujar el circuito que resuelve un
problema con multiplexores, es una tarea trivial. Prácticamente el trabajo termina cuando se finaliza de
escribir la tabla. (Esto es cierto también para la solución vía microcontrolador, y vía ROM).
IMPACTO AL AGREGAR ENTRADAS Y SALIDAS

Ya discutimos en relación a que el número de entradas y salidas debería ser el justo, pero que en caso de
error es siempre peor incluir de menos que de más. Ahora, el impacto de agregar entradas y salidas a un
problema tampoco es el mismo.
Por cada entrada que se agregue, el tamaño de la tabla se duplica; el crecimiento es exponencial. Así, si
tuviéramos que agregar la variable “<<LL>>ueve”, la tabla quedaría como se muestra a continuación.
Desde luego, puede verse que la nueva variable no tiene ninguna incidencia en las respuestas, que se
repiten iguales tanto si llueve como si escampa, según lo habíamos previsto. Pero lo importante es
mostrar cómo la tabla ha duplicado su tamaño, con un crecimiento que podíamos llamar “vertical”.
Ahora si lo que agregamos es una señal de salida (por ejemplo, encender la <<CAFE>>tera), la tabla,
según puede verse, solo crece en una columna más; el crecimiento no es exponencial sino lineal.

C3-143
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Index  4 INPUTS OUTPUTS


(“C” 
Table) <<LL>> C L E P D R
0 0 0 0 0 1 0 0
1 0 0 0 1 1 0 0
2 0 0 1 0 1 0 0
3 0 0 1 1 1 0 0
4 0 1 0 0 1 0 0
5 0 1 0 1 0 1 0
6 0 1 1 0 0 1 0
7 0 1 1 1 0 0 1
8 1 0 0 0 1 0 0
9 1 0 0 1 1 0 0
10 1 0 1 0 1 0 0
11 1 0 1 1 1 0 0
12 1 1 0 0 1 0 0
13 1 1 0 1 0 1 0
14 1 1 1 0 0 1 0
15 1 1 1 1 0 0 1 

Index  INPUTS 4 OUTPUTS


(“C” 
Table) C L E P D R <<CAFE>>
0 0 0 0 1 0 0 0
1 0 0 1 1 0 0 1
2 0 1 0 1 0 0 1
3 0 1 1 1 0 0 1
4 1 0 0 1 0 0 0
5 1 0 1 0 1 0 1
6 1 1 0 0 1 0 1
7 1 1 1 0 0 1 1 

A veces resulta imprescindible reducir el número de variables de entrada, para volver manejable un
problema que se nos escapa al análisis simultáneo por la cantidad de posiciones envueltas en la tabla.

Disminuir el número de salidas también es importante, aunque el impacto de las entradas es


exponencial, como ya dijimos. Observe, por ejemplo, que en el ejercicio original, una de las salidas
puede expresarse en términos de las otras dos, porque no son linealmente independientes. Así,
podemos decir que Rápido se activa cuando ni se activa Parado ni se activa Despacio.

Y para ilustrar la manera de reducir entradas, asuma que está diseñando una cerradura de combinación,
y tiene 8 teclas de entrada, que sólo pueden oprimirse una a la vez. Siguiendo el mismo esquema por

C3-144
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

medio del cual anteriormente codificamos los números del 0 al 7 en binario natural, empleando 3
posiciones o bits (binary digits), podemos también hacer que cada una de las 8 teclas genere tres bits,
con su codificación binaria (o cualquier otra codificación que resulte apropiada), con lo cual estamos
dividiendo el problema en dos partes: En la primera, las entradas son 8 interruptores y las salidas 3 bits.
Para el resto del problema, las entradas ahora son solo 3 bits, en vez de las 8 originales, haciendo que el
problema resulte en una tabla de 8 posiciones máximo, en vez de las 256 posiciones que habría que
analizar para los 8 interruptores del comienzo.

PROBLEMA TÍPICO: EDP CENTER

E
L director de un centro electrónico de procesamiento de datos (EDP), de profesión
Economista, tiene un serio problema en su compañía. Hay un Data Switch (DS) que distribuye
la información entrante (2 Gbps) a dos procesadores FW1 y FW0, especie de FireWalls que
filtran la información que les llega, a una velocidad máxima (pico) de 1 Gbps cada uno. Si los
procesadores FW aceptan la información entrante, la almacenan en un Servidor de Archivos (FS), del
cual se distribuyen los datos dentro del EDP.

A usted lo han llamado para que automatice esa sección de la empresa, pues a veces surgen
inconvenientes que resultan en la pérdida de información. El director le refiere que los procesadores
FW dependen cada uno de un UPS (Uninterruptible Power Supply) para cubrir las eventualidades de
que se vaya la energía eléctrica, lo cual sucede cada vez con más frecuencia en este país. Cuando no hay
luz, a veces falla alguno de los procesadores antes de que regrese el suministro de electricidad, pues el
tiempo de operación de los UPS depende de la cantidad de energía almacenada en sus baterías, y como
las circunstancias de consumo no son idénticas, unos acumuladores pueden tener menos carga en un
momento dado que otros. El FW que queda operativo solo alcanza a procesar la mitad de la
información entrante, por lo que se pierden importantes archivos de datos.
En ocasiones ocurre también que el FS se copa porque los clientes no leen la información a tiempo y no
la mueven a las estaciones locales de trabajo, y el resultado es el mismo: archivos que se pierden.
Otras veces tienen que apagar algún FW para hacerle mantenimiento: preventivo (limpieza, ajuste y
calibración) o correctivo (suplantación de partes, actualización) y en el ínterin se repite el problema. Por
cierto, el gerente le dice a usted, como parte de la problemática que él tiene, que hay una cafetera para
uso de los técnicos, que debería apagarse por las noches puesto que el personal solo trabaja de día.
En una rápida inspección a la oficina usted observa que el Data Switch posee una consola con tres
entradas –identificadas como Stop, Half Speed o Full– por medio de los cuales el personal de
operaciones puede manipular el dispositivo. Estos controles son tales que también pueden operarse de
forma remota, aplicando un voltaje DC a un terminal: 5 voltios los activa y 0 voltios los desactiva…
Los FW suministran también una salida cada uno, y cuando están operativos colocan 5V allí para
encender una lámpara indicativa; el File Server (FS) entrega también una señal similar, que informa si
está operativo o no, lo que incluye si se le llenó el disco, o también si por cualquier otro motivo hubo
que apagarlo.

C3-145
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Aunque usted no lo crea, este problema es EXACTAMENTE IGUAL al de la Fábrica de Chocolates,


y usted debería poder identificar apropiadamente las entradas y las salidas, hacer la tabla de verdad,
resolverlo mediante un programa en “C” que lea las entradas y obtenga las respuestas de una Tabla, así
como empleando ROM, Mux, Decoders (DeMux), etc.

CAMBIOS EN EL PROBLEMA

Suponga que remozan el FW1 para que pueda aceptar picos de trabajo de 2 Mbps, lo que implica que si
FW0 sale de funcionamiento, FW1 está en capacidad de mantener ambas cargas de trabajo. Analice el
impacto que tendría este cambio en sus soluciones: con microcontrolador, con ROM, con
Multiplexores y Decoders (Demultiplexores); ¿qué cambios físicos tiene que hacer para acoplar sus
soluciones a la nueva situación? Explique.

Algunos micros y ROMs pueden programarse en la misma tarjeta en que están trabajando (no hay que
extraerlos para conectarlos a la tarjeta “quemadora”). ¿Qué importancia tiene este hecho para su
problema, si cambian algunos parámetros de funcionamiento en la empresa? ¿Qué puede decir de la
solución con Multiplexores? Y qué de los DeMux?

También tiene que solucionar el problema en la forma clásica: con compuertas AND, OR, NOT y con
circuitos NAND y NOR…

Los ejercicios que se plantean en “C” usted debe codificarlos en Assembler y simularlos en el
MPLAB.

 INTRODUCCIÓN AL CÓDIGO HAMMING


GENERALIDADES

C
UANDO se habla del auge de los circuitos digitales resulta indispensable mencionar que –por
su naturaleza de sistemas discretos– solamente son significativos ciertos valores y, como no es
necesario distinguir entre todo el rango, los componentes digitales son más sencillos de
elaborar que los analógicos. Así, la variable más elemental (un bit) debe representar sólo dos
posiciones: abierto o cerrado; saturado o en corte; 5 voltios o 0 voltios. Nada pasa en el intermedio, así
que si, por ejemplo, una señal debe estar en un nivel alto o bajo, y esta situación va a ser representada
por 5V ó por 0V, y en un momento determinado dicha señal se encuentra en 4 voltios –debido a un
ruido o a una imperfección–, el discriminador puede asumir que el estado es “alto”. Y si está en 3V
también. En cambio, si la señal está en 2V el dispositivo indicará que el estado es “bajo”, y hará lo
mismo si el valor es de 1V. Se denomina inmunidad al ruido a la diferencia entre aquellos dos rangos
que sean claramente discernibles como un valor o el otro. Los sistemas digitales son altamente inmunes
al ruido. Señales espurias importantes, o de gran magnitud, pueden superponerse a las variables, sin que
ocasionen la interpretación errónea de las mismas.

Pero, desde luego, en los canales de comunicación pueden ocurrir disturbios de tal naturaleza que,
eventualmente, ocasionen pérdida de información. Los sistemas digitales, sin embargo, pueden codificar

C3-146
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

la información de tal manera que resulte posible detectar y corregir dichos errores, según demostró
Hamming (Richard Wesley) en 1950. Un caso común en telecomunicaciones consiste en añadirle un bit
a cada símbolo compuesto de 8 bits (un byte), de tal manera de lograr que siempre el número de bits en
“uno” sea par, o impar. A este noveno bit se lo conoce como bit de paridad (par o impar) y tiene la
propiedad de producir un conjunto de caracteres codificados de tal manera que, si aparece un solo error,
el símbolo que se produce no forma parte del grupo correcto de caracteres, lo cual hace factible
identificarlo como equivocado. Si ocurriera, pues, un único error en un byte (cambio de un bit cero por
un uno, o viceversa), podría detectarse el error simplemente contando, en el receptor, el número de
bits, y viendo si cumple lo establecido en cuanto al criterio de paridad. Si hubiera un error, normalmente
no podría decirse en cuál bit ocurrió, pero puede indicársele al extremo transmisor que repita la
comunicación del último segmento de información (ARQ, Automatic Repeat reQuest).

A veces no es factible emplear el ARQ; por ejemplo, si el canal de comunicación transmite información
en un solo sentido (TV o Broadcasting), o si la distancia que separa los equipos es muy grande (entre la
Tierra y Marte). Es posible corregir estos errores en el destino, sin apelar a la retransmisión (“forward
error correction”). Por ejemplo, si para enviar un 0 se transmite “000” y para un 1 se despacha un
“111”, un único bit erróneo podría corregirse con facilidad dejando que el valor correcto sea
determinado por la mayoría recibida. Así, si se obtiene 111, 101, 011 o 110 podemos suponer que la
información transmitida fue un 1 en su origen (111), ya que la mayoría así lo indica (recuérdese que esto
supone que la información, o llega correcta –111– o a lo sumo con un único bit equivocado). También,
si llega 000, 001, 010 o 100, se sabe que la información transmitida fue un 0 (000).

CÓDIGO HAMMING PARA UN BIT DE INFORMACIÓN


Hamming se aproximó al problema suponiendo que el 000 y el 111 que acabamos de ver no eran
repeticiones de la información, como aparentan, sino que los valores de los bits redundantes podían
obtenerse a partir del cálculo de las paridades.

En la discusión anterior en relación a los bits de paridad, se indicó que son un método empleado para
detectar cuándo hay UN error en un símbolo. Supongamos que tenemos caracteres de una longitud de
8 bits (elementos de este tamaño se llaman bytes en computación y octetos en telecomunicaciones). Si
se ha estimado que la probabilidad de que ocurran dos o más errores en un símbolo es despreciable,
puede detectarse si hay un bit recibido equivocadamente, añadiendo a la información un noveno bit,
que se define de tal manera que él obligue a que el número de bits con valor “uno” sea par (paridad
par), o impar (si se escoge paridad impar). Así, el símbolo 10101010 se transmitirá como 010101010 si
la paridad es par, siendo el bit agregado a la izquierda el correspondiente a la paridad par, que vale 0 para
que el número de bits en “uno” sea par (4 unos transmitidos). Si el símbolo que fuera a enviarse hubiera
sido 11101010, quedaría como 111101010. Aquí el bit de paridad que añadimos es un “uno”, para hacer
que los 5 bits que en la información original valen “uno” (5 es impar) se conviertan en 6, que es un
número par de unos.

Ahora, bajo el supuesto de que la información llega bien, o a lo sumo tiene un bit equivocado (en aquellos
casos en que la probabilidad de dos o más errores sea ínfima), la forma de establecer el estado de la
recepción de cada byte consiste en verificar –en el destino– si el número de “unos” recibido cumple con
el criterio de paridad escogido, par o impar. Si se apega, se asume que el símbolo se transmitió bien; si la

C3-147
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

paridad no corresponde, se asume que hay un error en la transmisión. En este caso, no se sabe cuál de
los 9 bits sea el equivocado, pero al receptor le basta con solicitar el reenvío del último bloque de
información, para solucionar el problema (ARQ).

Hamming colocó los bits de paridad y el de información en posiciones clave, que le permitieron
identificar, no solamente si había error, sino en cuál columna se encontraba dicho error.
Básicamente, las combinaciones de las paridades identifican si no hay error y, de haberlo, en cuál
columna se encuentra dicho error. Para que eso ocurra las paridades (pares en estos ejemplos) deberán
generarse como sigue:

P1 = I3 
P2 = I3 

La idea es formar la siguiente tabla:

I3 P2 P1 
x     x 
x  x 

con la que se quiere significar que la primera paridad se establece entre P1 e I3 y la segunda entre P2 e 
I3. De la tabla puede apreciarse que si sólo falla la paridad entre P1  e  I3 –y nada más–, la única
posibilidad es que P1 sea el elemento equivocado, ya que si el error estuviera en I3 (el otro integrante de
la primera paridad), por necesidad tendría también que dar equivocada la segunda paridad, establecida
entre P2  e  I3. (Este párrafo es muy importante; por favor, no continúe hasta haberlo
comprendido a la perfección)

De manera similar, si sólo falla la paridad entre P2 e I3 –y nada más–, la única posibilidad es que P2 se
haya recibido mal, ya que si el error estuviera en I3 (el otro integrante de la paridad entre P2 e I3),
también tendría que dar equivocada la primera paridad, establecida entre P1  e  I3. Y por el mismo
razonamiento, si llegan equivocadas las dos paridades, establecida la primera entre P1 e I3 y la segunda
entre P2 e I3, el error tiene que estar en el bit I3.

En este caso tan sencillo, las paridades, y la inclusión triple de la información, resultan equivalentes...
Después de computado el bloque de información que tiene que transmitirse, se realiza el análisis de la
información que llega al extremo receptor:

I3  P2  P1 

Se calculan los bits de paridad recibidos, que identifican si hay error en alguna de las paridades:

E1 = P1  I3 (Note: P tendría que ser igual a I ¡por definición!; por tanto, el E1 = P1  I3 debería ser
“0” siempre. Solo vale “1” cuando difieren..., y esto señala, precisamente, un error.)

E2 = P2  I3 

C3-148
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

cuyas combinaciones generan las siguientes posibilidades:

    Un error;   
columna con error: 
E2  E1  3  2  1  0 
0  0        Sin error 
0  1      1   
1  0    2     
1  1  3       

Es importante destacar que si se conoce cuál columna está equivocada, también se la puede arreglar,
ya que si la información que llegó fue un 0 –por ejemplo– y se determina que es errónea,
necesariamente se sabe que debió llegar un 1. Por tanto, para arreglar un bit que se conoce que
llegó mal, basta con negar su valor para corregirlo.

Como el caso de un solo bit de información es tan simple, podemos analizar todas las 8 combinaciones
en el extremo receptor (en el transmisor, los dos únicos conjuntos posibles son: 000 y 111):

Vector de Entrada  Cálculo de las paridades  Vector de Salida 


recibidas  (O3 es realmente el bit de 
información; los demás son 
bits de paridad) 
I3  P2  P1  E2  E1  Columna  O3  O2  O1 
Errónea 
0  0  0  0  0  No  0  0  0 
error 
0  0  1  0  1  1  0  0  0 
0  1  0  1  0  2  0  0  0 
0  1  1  1  1  3  1  1  1 
1  0  0  1  1  3  0  0  0 
1  0  1  1  0  2  1  1  1 
1  1  0  0  1  1  1  1  1 
1  1  1  0  0  No  1  1  1 
error 

Cada bit de salida es igual al de entrada, si no hay error en esa columna, y es igual al negado
de la entrada si esa columna es errónea. A un circuito que cumple con la exigencia de que su salida,
a veces es igual a la entrada, y a veces al negado de la entrada, se lo llama un “negador condicional”,
que se construye con una compuerta Xor, ya que este circuito tiene la siguiente tabla:

Negate  Input  Output 


0  0  0 
0  1  1 
1  0  1 
1  1  0 

C3-149
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Una forma de ver el Xor es diciendo que Output es igual a Input, si Negate es 0 (no negación), y
Output es igual a Input negada, si Negate es 1 (sí hay negación). Por eso se dice que el Xor es un
negador condicional.

Para terminar de construir el corrector Hamming, hay que convertir el código binario formado por
E2,E1 en 4 líneas: L0,L1,L2,L3 tales que, si L0 vale 1, no hay error en el código; si alguna de las otras
salidas L1,L2,L3 vale uno, el error estará en esa específica columna. Un circuito así es un
“decodificador de 2  (E2,  E1)  a  4  (L0,L1,L2,L3)”, y se obtiene construyendo cada uno de los
mintérminos de la función.

Así: L0 = E2’ * E1’, L1 = E2’ * E1, L2 = E2 * E1’, L3 = E2 * E1, o con un decodificador


comercial (MSI). Cada columna de salida queda entonces definida como: On = In  Ln, para n = 1, 
2, 3.

CÓDIGO HAMMING PARA CUATRO BITS DE INFORMACIÓN (Y 3 DE PARIDAD: 7,4)


En el caso de un solo bit de información, la redundancia resulta excesiva, ya que para enviar un bit ¡hay
que transmitir tres! Si fuera una comunicación telefónica ¡necesitaríamos tres (3) celulares! Pero
Hamming encontró que el número de bits del bloque de información es: 2^n – 1. Así, para n=2, el
tamaño del bloque es 3, y como 2 son las paridades, queda 1 solo bit de información. Para n=3 la
situación mejora, ya que el tamaño del bloque es ahora de 7, y por tanto el número de bits de
información es: 7–3=4. Para 4 de paridad la situación se convierte en 15 bits en total y 11 de
información (¡mucho mejor !).

Tres bits de paridad producen un bloque de información de 7 bits en total, con 4 de información (7,4).
Para que los de paridad permitan identificar la columna de error, las paridades deben establecerse de
siguiente manera:

      Column 
P4  P2  P1  Number 
0  0  0  0 (No error) 
0  0  1  P1 
0  1  0  P2 
0  1  1  I3 
1  0  0  P4 
1  0  1  I5 
1  1  0  I6 
1  1  1  I7 

En consecuencia las paridades se generan como sigue:

P1 = I3  I5  I7  P2 = I3  I6  I7  P4 = I5  I6  I7 

Se transmite el bloque así conformado y el receptor verifica el estado de la información y corrige un


error si lo detecta:

C3-150
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

I7  I6  I5  P4  I3  P2  P1 

Se calculan los bits que indican si hay error en alguna de las paridades calculadas al transmitirse la
información:

E1 = P1  I3  I5  I7, E2 = P2  I3  I6  I7, E4 = P4  I5  I6  I7 

(Observe E1. Arriba se definió P1=I3I5I7. Si se reemplaza este valor en la ecuación, puede
escribirse E1 = P1xmt  P1rcv. Este valor tendría que ser “0” siempre, según la ecuación del ExOr.
Sólo da “1” cuando P1xmt (I3xmt  I5xmt  I7xmt) difiere del P1rcv (I3rcv  I5rcv  I7rcv).
Por eso si E1 vale 1 detecta un error. Igual ocurre para los demás bits de error E2,E4, etc.

Por último, observe que estas ecuaciones para determinar si hay o no error, son para paridad par; los
cálculos para la GENERACIÓN se niegan si se trata de Paridad Impar (even) ¿Qué cree que
pasará con los de la DETECCIÓN de error cuando la paridad Hamming sea Impar (odd)? Si
no lo sabe, haga un ejercicio con 2 paridades impares y un bit de información; genere las
paridades, valide el resultado, introduzca un error y vea si se detecta o no. ¿Cuál es su
conclusión ?

      Columna con error: 
E4  E2  E1  7  6  5  4  3  2  1  0 
0  0  0                no 
error 
0  0  1              1   
0  1  0            2     
0  1  1          3       
1  0  0        4         
1  0  1      5           
1  1  0    6             
1  1  1  7               

Se decodifican las 8 posibilidades mediante un decodificador que en este caso es de 3 a 8. Si L0 vale 1,


no hay error en el código. Si alguna de las otras salidas L1, L2, ..., L7 vale uno, quiere decir que el
error está en la correspondiente columna asociada:

L0 = E4’ * E2’ * E1’,  L1 = E4’ * E2’ * E1,  L2 = E4’ * E2  * E1’,  L3 = E4’ * E2  * E1 
 
L4 = E4  * E2’ * E1’,  L5 = E4  * E2’ * E1,  L6 = E4  * E2  * E1’,  L7 = E4  * E2  * E1 

Cada columna de salida queda definida como: On = In  Ln, para n = 1, 2, ..., 7 (es decir, la salida es
igual a la entrada, si no hay error, o la salida es igual al negado de la entrada, si para esa columna hay
un error). Un Diagrama Lógico le debería resultar trivial de construir en base al planteamiento anterior.

Como ejemplo del funcionamiento supongamos que llega equivocado el bit I7:

C3-151
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

  I7 I6  I5  P4  I3  P2  P1 


Enviada  1  0  1  0  0  1  0 
Recibida  0  0  1  0  0  1  0 
Cálculo 
De  I7  I6  I5  E4  I3  E2  E1 
Errores 
Error en 
      1    1  1 
Col. 7 
Corregida  1  0  1  0  0  1  0 

Ahora supongamos que el bit equivocado es el P4:

  I7  I6  I5  P4  I3  P2  P1 


Enviada  1  0  1  0  0  1  0 
Recibida  1  0  1  1  0  1  0 
Cálculo 
De  I7  I6  I5  E4  I3  E2  E1 
Errores 
Error en 
      1    0  0 
Col. 4 
Corregida  1  0  1  0  0  1  0 

Usted debe poder repetir todo el procedimiento de generación, verificación y corrección para el caso en
que las paridades Hamming sean impares.

DETECCIÓN DE (2) ERRORES Y CORRECCIÓN DE (1) ERROR CON CÓDIGO HAMMING


Si en el planteamiento anterior, a la codificación resultante se le agrega un bit PE que controle la paridad
(par [even] para este ejemplo) de toda la trama Hamming, y al terminar de corregir, el receptor vuelve a
verificar la paridad (par) completa para ver si hay error (PEE), puede verse fácilmente con algunos
ejemplos que, si ocurren dos errores, el procedimiento Hamming se engañará, y corregirá lo que él
cree que es un error; por tanto, el resultado serán dos bits invertidos, pues en realidad llegaron mal,
¡más otro invertido por la corrección equivocada! Significa que la paridad total cambia (3
inversiones), y al compararla con la recibida dará diferente; por tanto, la verificación PEE indicará que
debe descartarse la trama completa, pues se sabe que está mal (detección de dos errores) pero se
ignora dónde…

  PEE  PE  I7  I6  I5  P4  I3  P2  P1 


    1  1  0  1  0  0  1  0 
Ej.1  1  1  1  0  1  0  0/1  0  1 
Ej.2  1  1  1  1  1  1  0  1/0  0 
Ej.3  1  1  0  0  1  0/1  1  1  0 
Ej.4  1  0  0/1  0  1  0  0  1  0 

Ej.1: P1,P2 llegan mal; por tanto, E4=0;E2=1;E1=1: Hamming corregirá erróneamente el bit I3; PEE=1:
2 errores!

C3-152
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Ej.2: P4,I6 llegan mal; E4=0;E2=1;E1=0: Hamming corregirá erróneamente el bit P2;  PEE=1:  2
errores!
Ej.3: I3,I7 llegan mal; E4=1;E2=0;E1=0: Hamming corregirá erróneamente el bit P4; PEE=1: 2
errores!

Ej.4: PE,I7 llegan mal; E4=1;E2=1;E1=1: Hamming corregirá el bit I7 (esto es correcto); PEE=1:
2 errores!

Note que en el último ejemplo, aunque Hamming sí corrigió el bit I7, que fue el que llegó
dañado, ¡no lo sabe!, puesto que hubo dos errores, según lo dictamina PEE=1: Hay que
descartar la trama pues no se sabe cuáles fueron esos 2 errores…
Cuando se descarta una trama porque no se puede corregir, debido a la aparición de dos errores, es
necesario emplear un método como el ARQ, descrito arriba.

Por último, si los errores no están uniformemente distribuidos, sino que llegan en paquetes (bursts,
como cuando cae un rayo), para una longitud máxima del burst de error, de N bits, se pueden agrupar
N filas de tramas Hamming antes de enviarlas, y se las transmite POR COLUMNA, no por fila. El
receptor reagrupa el mensaje otra vez en N filas; si llegó un paquete de N, o menos de N bits dañados,
éstos corresponderán, a lo sumo, a un bit erróneo por fila ¡y esta es exactamente la situación que el
procedimiento Hamming puede corregir!

Este método aplica solo si los retardos introducidos por el almacenamiento temporal de las N filas, no
resultan intolerables para el sistema; por ejemplo, si se trata de comunicaciones telefónicas, transmisión
de audio y video, etc., los retardos deben ser muy cortos para que pasen desapercibidos. Pero si estamos
transmitiendo datos del tipo información bancaria, o archivos similares, off-line, es posible que el retardo
debido al buffering de las N filas no represente mayores inconvenientes para el usuario.

Usted debe ser capaz de (hacer un programa que) tomar un archivo, dividirlo en tramas Hamming que se
almacenan en N filas, donde N es el tamaño máximo del burst de errores, transmitirlo por columnas,
recibirlo por columnas, recomponerlo otra vez en N filas y corregir hasta un máximo de N filas con a lo
sumo un error en cada una. Si no se sabe N, hay que calcularlo; por ejemplo, si las perturbaciones
electromagnéticas (centellas, arranques de motores, etc.) duran M milisegundos (ms) y la velocidad de
transmisión es de V bits por segundo (bps), haciendo una simple división se puede calcular el número
de bits dañados en cada eventualidad. Calcule cuánto tiempo lleva almacenar N filas Hamming, y vea si
está dentro de lo especificado; si no, pruebe a aumentar la velocidad de transmisión, y si logra un valor
factible, esa puede ser la solución para la corrección de errores que llegan en bursts de hasta N bits
dañados a su sistema.

(Nota: Tenga en cuenta que incrementar la velocidad de transferencia de un canal puede aumentar la
probabilidad de ocurrencia de errores)

CÓDIGO HAMMING PROGRAMADO EN “C” Y ASSEMBLER PIC 16F84A

C3-153
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Cuando se pide un programa para Generar y transmitir el código Hamming a partir de N bits de información, lo más común es que se aborde el problema
individualizando cada bit de entrada y de manera secuencial se vayan estableciendo los diversos ExOrs para los bits de Paridad, de acuerdo a las ecuaciones
planteadas. Las entradas son los N bits de información, y las salidas conforman la trama Hamming completa: bits de información más bits de paridad.
Asimismo, si hay que realizar el código para Detectar y Corregir un error en una trama Hamming en el lado receptor, la aproximación es similar: se
individualiza cada bit y se van formando las ecuaciones de Error, también explicadas con anterioridad.
Pero no siempre la descripción del problema corresponde al algoritmo idóneo para resolverlo. Fíjese que se puede hacer un programa que mimetice
la materialización que con circuitos ExOr se planteó en la explicación antecedente. Se incluye un programa, a vía de ejemplo, que toma 4 bits de información y
generan la trama Hamming (7,4), que luego realizar el proceso inverso, del lado receptor. Si requiere un transmisor, o un receptor, tome solo la ½ del código, y
ajuste levemente algunas secciones, como por ejemplo, el receptor tiene que incluir la lectura de los 7 bits de la trama Hamming, que en el ejemplo no se leen.
(Usar 2 tablas es directo, pero como cada elemento mide máximo 4 bits, DESPERDICIA ESPACIO: Las 2 tablas caben en UNA.
Se agrega también, en ROJO, el código que utiliza solo UNA tabla …)

// Hamming.c, Luis G. Uribe C., M09N2010. Use tables         Pc = Hamming[ RcvX ]; 
  //     Pc = Col_Hamming[ RcvX ] & 0x0F;    // Lower half nibble 
// char Hamming[]={0,3,5,6,6,5,3,0, 7,4,2,1,1,2,4,7}; // ORIGINAL         if( Rcv & 0x08 )        // This is MSB; if "1": value is 
char Hamming[]={0,3,5,6,6,5,3,0}; //Seen in binary: In the             Pc = ~Pc & 0x07; //..negated from table: 3 lower bits 
           // ... above table, Upper half is lower half, NEGATED!         EX = ( Pc ^ ( Rcv >> 4 ) ) & 0x0F; //Xor gives "1" on each 
char column[] = {0,0,0,1,0,2,4,8}; // Info is: I3I2I1I0 (8,4,2,1)         E  = column[ EX ]; //..different bit. Get bit # from table 
           // 0 means: do NOT negate bit, cause there is no error  //     E  = Col_Hamming[ EX ] >> 4 & 0x0F; // Higher half nibble 
//char Col_Hamming[] = { 0,3,5,1<<4|6,6,2<<4|5,4<<4|3,8<<4 };         Rcv ^= E;               // Negate bit to correct it ! 
void main(void) //..or error is in a Parity bit: not correct it         Rcv &= 0x0F;       // Assure 4 bits. Outp corrected value 
{       }  // EndWhile 
   char input,                 // input variable, 4 bits  }  // EndMain 
        inputX,  // indeX formed w/3 lower input bits (Hamming[])   
        P,                     // Parity (sender)   
        Pc,                    // Parity (Calculated, receiver)  Debug this program using input = 0xF5 (0x05 data + spurious bits) 
        Xmt,                   // Composed value to xmit: P,I 
        Rcv,               // Received value. Rcv != Xmt on error  Change “Rcv” from 0x55 to 0x57 to reflect one received error on 
        RcvX,              // Receptor IndeX, 3 lower Rcv bits  original bit I5. 
        E,       // Error Syndrome. Points to bit number on error  Algorithm fixes data back to 0x05 !!! 
        EX;          // IndeX to get bit # to negate on column[]   
   while( 1 ) {  Now debug using input = 0xFF ( 0x0F data + spurious bits). 
       input  = 0;             // values from 0..15 
       input &= 0x0F;          // assure 0..15  Change “Rcv” from 0x7F to 0x7E to reflect received error on 
       inputX = input & 0x07;  // take 3 lower bits  original bit I3. 
  Algorithm fixes data back to 0x0F !!! 
       P = Hamming[ inputX ];   
//     P = Col_Hamming[ inputX ] & 0x0F;   // Lower half nibble 
       if( input & 0x08 )      // This is MSB; if "1": value is  Draw Logic Diagram, assigning input/output pins to 
           P = ~P & 0x07;   //..negated from table: 3 lower bits  16F84A (note that this is ONE program intended to 
       Xmt = input | P << 4;  simulate both: Hamming Generation  AND  Correction). 
// ... ...  Xmit data to Receiver (SIMULATED FAKE) 
       Rcv = Xmt; 
       RcvX = Rcv & 0x07;      // take 3 lower bits for indeX 

C3-154
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

   andlw   0x07                ; inputX = input & 0x07; 3 lower bits 
; Luis G. Uribe, Hamming.asm C10N2010.  ;   movwf  inputX              ; .. inputX NOT Needed: W used instead 
; ... Derivado de Hamming.C (;//  COMMENTED)     call    Hamming             ; P = Hamming[ inputX ]; 
   __CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC  ;   andlw  0x0F 
   LIST     P=16F84A      movwf  P                   ; .. 
   INCLUDE  <P16F84A.INC>   
; INCLUDED CODE FOR USING ONLY ONE TABLE (IN RED)     btfsc   input, 3            ; if(input & 0x08) // MSB; if 1, value is: 
;//char input, inputX, P, Pc, Xmt, Rcv, RcvX, E, EX;      comf   P, W                ; P = ~P & 0x07; ..is ~P, 3 lower bits 
      andlw  0x07                ; // values from 0..15. TRUCO!! Repite 
   CBLOCK 0X0C                 ; Use 0X20 for 16F877      movwf  P                   ; ..'andlw' SIN necesidad: Es OK... 
       input                   ;// input variable, 4 bits   
       inputX      ;// indeX formed w/3 lower input bits (Hamming[])     swapf   P, W                ; Xmt = input | P << 4; 
       P                       ;// Parity (sender)      iorwf  input, W            ; .. 
       Pc                      ;// Parity (Calculated, receiver)      movwf  PORTB               ; .. 
       Rcv                     ;// Received value. Rcv != Xmt ? on error  ;// ... Xmit data to Receiver. **SIMULATED**: NO REAL Received DATA 
       ; VARS NOT USED in this Assembly simulation: Xmt, RcvX, E, EX     movwf   Rcv                 ; Rcv = Xmt; 
   ENDC     andlw   0x07                ; RcvX=Rcv & 0x07; 3 bits BREAK HERE!! 
  ;   movwf  RcvX                ; ..'RcvX' NOT needed: W used instead 
   ORG 0                       ; Program Starts at address 0   
    goto   main                ; .. but jumps ahead to main, to make     call    Hamming             ; Pc = Hamming[ RcvX ]; 
                               ; .. room to Hamming[] & column[] tables  ;   andlw  0x0F 
      movwf  Pc                  ; .. 
;//char Hamming[] = { 0,3,5,6,6,5,3,0, 7,4,2,1,1,2,4,7 }; // ORIGINAL   
;  //NOTE: Seen in binary: In the above table, Upper half is lower half,     btfsc   Rcv, 3              ; if( Rcv & 0x08 ) MSB; if 1, value is: 
;  // NEGATED!, so:       comf   Pc, W               ; Pc = ~Pc & 0x07; negated from table 
;char Hamming[] = {0,3,5,6,6,5,3,0};      andlw  0x07                ; // values from 0..15 
;      movwf  Pc                  ; .. 
Hamming:   ; P=Hamming[inputX]; W starts as 'inputX'; 'P' returns in W          
;column:     swapf   Rcv, W              ; ( Rcv >> 4 ) 
   addwf   PCL, F      xorwf  Pc, W               ; .. Pc ^ (Rcv >> 4) //Xor gives diff.  
    DT .0, .3, .5, .6, .6, .5, .3, .0      andlw  0x0F                ; .. ( Pc ^ ( Rcv >> 4 ) ) & 0x0F 
;   DT .0, .3, .5, .1<<.4|.6, .6, .2<<.4|.5, .4<<.4|.3, .8<<.4  ;   movwf  EX                  ; .. EX = (Pc ^ ( Rcv >> 4 )) & 0x0F; 
      call   column              ; E  = column[ EX ]; 
;char column[]  = { 0,0,0,1,0,2,4,8 };  // Info is: I3I2I1I0 (8,4,2,1)  ;   movwf  E                   ; .. Bit # from table. 'E' NOT used: W 
; 0 means: does NOT negate any bit, because there is no error  ;   rrf   E,F 
;  ;   rrf   E,F 
column:    ; E = column[ EX ]; W starts as 'EX'; 'E' returns in W Reg  ;   rrf   E,F 
   addwf   PCL, F  ;   rrf   E,W 
    DT .0, .0, .0, .1, .0, .2, .4, .8  ;   andlw 0x0F                ; .. ( Pc ^ ( Rcv >> 4 ) ) & 0x0F 
main:     xorwf   Rcv, W              ; Rcv ^= E; Negate bit to correct it ! 
   clrf    PORTB               ; Set PORTB Initial Output (all 0s)      andlw  0x0F                ; ..Rcv &= 0x0F; 4 bits! OUT NO PARITY 
   bsf     STATUS, RP0         ; Switch to BANK1, to Address TRISB      movwf  PORTB 
   clrf    TRISB               ; Set PORTB All Outputs (all 0s)   goto      while1              ; }  // EndWhile (Do this... for ever) 
                               ; PORTA: all Inputs (by default)     END                         ; }  // EndMain 
   bcf     STATUS, RP0         ; Switch back to BANK0: Normal state.  Debug with input = 0xF5 (0x05 data + spurious bits). 
while1:  Change Rcv from 0x55 to 0x57 to reflect received error on original bit I5 
   movfw   PORTA               ; Get input values to generate Hamming  Algorithm fixes data back to: 0x05 !!! 
    andlw  0x0F                ; // values from 0..15. BREAK HERE!!!  Now debug with input = 0xFF ( 0x0F data + spurious bits). 
    movwf  input               ; ..  Change Rcv from 0x7F to 0x7E to reflect received error on original bit I3 
  Algorithm fixes data back to: 0x0F !!!

C3-155
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

CÓDIGO HAMMING COMENTADO


// char Hamming[] = { 0,3,5,6,6,5,3,0, 7,4,2,1,1,2,4,7 };  // ORIGINAL 
Esta tabla sale de tomar como entradas los 4 bits de información, hacer las 16 combinaciones entre ellos
y calcular los diferentes bits de Paridad, P4P2P1. Se trata, como es costumbre al resolver problemas
combinatorios, de establecer en una tabla todas las posibles respuestas que pueden obtenerse para todas
las combinaciones de entrada.
#  I3  I2  I1  I0  P4  P2  P1  dec.    #  I3  I2  I1  I0  P4  P2  P1  dec. 

0  0  0  0  0  0  0  0  0    8  1  0  0  0  1  1  1  7 

1  0  0  0  1  0  1  1  3    9  1  0  0  1  1  0  0  4 

2  0  0  1  0  1  0  1  5    10  1  0  1  0  0  1  0  2 

3  0  0  1  1  1  1  0  6    11  1  0  1  1  0  0  1  1 

4  0  1  0  0  1  1  0  6    12  1  1  0  0  0  0  1  1 

5  0  1  0  1  1  0  1  5    13  1  1  0  1  0  1  0  2 

6  0  1  1  0  0  1  1  3    14  1  1  1  0  1  0  0  4 

7  0  1  1  1  0  0  0  0    15  1  1  1  1  1  1  1  7 

Si se observa con detenimiento puede notar que los valores de P4P2P1, en la tabla de la derecha son los
negados de las posiciones correspondientes en la tabla de la izquierda. Esto nos permite almacenar solo
la mitad de la tabla, y dependiendo del valor del bit I3, tomar el valor almacenado, o negarlo.
Otra curiosidad con esta tabla es que los valores se repiten con simetría horizontal inversa: primero
comienzan: 0,3,5,6, y luego los valores continúan en reversa: 6,5,3,0. Esta observación no nos
permite almacenar la mitad de la tabla resultante, lo que darían solo 4 filas en lugar de las 16 originales,
porque la receta para obtener una mitad a partir de la otra no es tan sencilla como en la primera
reducción. Así, un programa que almacenara solo 4 filas, y pretendiera obtener las 16, no sería al
parecer, tan simple como el que aquí hemos presentado.
char Hamming[] = { 0,3,5,6,6,5,3,0 };  //Seen in binary: Upper half is 
                                       //.. lower half, NEGATED! 
Así resulta, pues, la tabla para calcular los 16 valores Hamming necesarios para 4 bits de información.
char column[]  = { 0,0,0,1,0,2,4,8 };  // Info is: I3I2I1I0 (8,4,2,1) 
                   // 0: does NOT negate bit, cause there is no error 
Ahora bien; el circuito que Genera la trama Hamming no almacena internamente los bits en las mismas
posiciones que estudiamos para la “trama” Hamming. Aquí, los 4 bits de información entran juntos,
uno al lado del otro: I3I2I1I0, que corresponden a los bits 8,4,2,1. Cuando la rutina en el lado
transmisor va a Corregir un error, primero, solo va a corregir los bits de Información; si hubiera un
error en los bits de Paridad, no los corrige (al receptor solo le importa LA INFORMACIÓN). Y
segundo, como los bits no están ordenados en las posiciones indicadas por la trama Hamming, sino que

C3-156
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

están todos seguidos, esta tabla convierte el error (que antes señalaba claramente en qué columna estaba
el error), en un número que indica dónde se encuentra ese bit de la trama Hamming, señalado por el
síndrome de Error (E4E2E1). En esta tabla, un cero significa que no hay que corregir nada. Los ceros
están en la posición cero de E4E2E1, puesto que ese síndrome señala que no hay error (no hay que
corregir nada), y también cuando los errores correspondan a los bit de paridad (que no se corrigen,
aunque hubieran llegado mal). Así, las posiciones 0, 1, 2 y 4 llevan 0. Las demás posiciones tienen un
solo uno (en binario), que corresponde a la posición del bit que hay que corregir. Si E4E2E1 es 3, hay que
corregir el bit I3 de la trama Hamming, que está almacenado en el Bit_1 de la variable; por eso en la
posición 3 hay un 1. Si el síndrome E4E2E1 es 5, hay que corregir I5 de la trama Hamming, que está
almacenado en el Bit_2; por eso en la posición 5 hay un 2. Y con el mismo criterio, en la posición 6 hay
un 4 y en la 7 un 8. Esta tabla “column” convierte los síndromes E4E2E1 en el número del bit que hay
que negar para arreglar un error, o 0 si no hay que negar ninguno.
   char input,                 // input variable, 4 bits 
La variable que va a recibir los 4 bits de entrada del ejemplo.
        inputX,    // indeX formed w/3 lower input bits (Hamming[]) 
Aquí se guardan los 3 bits inferiores de la entrada, pues recuérdese que la tabla usa solo estos 3 bits, y
que el cuarto, que está almacenado en input, lo único que determina es si se niega o no el valor leído de
la tabla Hamming.
        P,                     // Parity (sender) 
Esta variable aloja los 3 bits de paridad que van a generarse y enviarse al receptor.
        Pc,                    // Parity (Calculated, receiver) 
Aquí se almacena la paridad vista en el receptor.
        Xmt,                   // Composed value to xmit: P,I 
En Xmt se agrupan los bits que van a transmitirse, y que corresponden a los de información, y a los de
Paridad que acaban de calcularse.
        Rcv,                   // Received value. Rcv != Xmt on error 
En esta variable se aloja la información que llega al equipo receptor. Desde luego, si hay un error, este
valor será diferente a Xmt.
        RcvX,                  // Receptor IndeX, 3 lower Rcv bits 
La estrategia que empleé en el receptor merece destacarse: Si atacamos el receptor como un
problema convencional de circuitos combinatorios, tendremos 7 bits de entrada para elaborar la tabla
(128 posiciones) y el tamaño no resulta conveniente. Pero podemos emplear otra aproximación: usar
como entradas solamente los 4 bits de información (tal como hizo el transmisor); calcular los bits de
Paridad que han debido llegar y compararlos con los que en realidad llegaron. Si son iguales, no
hay error; si son diferentes, las posiciones en las que no coincide el valor de Paridad calculado y el
recibido, conforman los bits de error, E. En RcvX se almacenan los 3 bits de más bajo órden de la
Información recibida, y se usan como índice para leer la tabla Hamming.
        E,         // Error Syndrome. Points to bit number on error 

C3-157
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

El error leído de la tabla se almacena en esta variable (negado o no, según corresponda).
        EX;            // IndeX to get bit # to negate on column[] 
EX indica el síndrome de error, y sirve para leer de la tabla column el número del bit que hay que negar, si
es que hay alguno.
   while( 1 ) { 
       input  = 0;             // values from 0..15 
       input &= 0x0F;          // assure 0..15 
       inputX = input & 0x07;  // take 3 lower bits 
 
En la primera línea se pueden inyectar valores de entrada, del 0..15, con el debugger. La siguiente
instrucción confina los valores leídos a números cuyo rango va del 0..15. Y en la siguiente línea se
obtienen los 3 bits de menor órden, que servirán para leer la tabla Hamming.
       P = Hamming[ inputX ]; 
       if( input & 0x08 )      // This is MSB; if "1": value is 
           P = ~P & 0x07;      // .. negated from table: 3 lower bits 
Se calcula la paridad, según los bits de información, leyéndola de la tabla, y si el bit I3 está en 1, se niega
el valor obtenido de la tabla, según se indicó anteriormente en la explicación.
       Xmt = input | P << 4; 
Se conforma una sola variable para transmitir la información, que lleva los 4 bits de I en el la mitad baja
del byte y los 3 bits de Paridad en el byte superior.
// ... ...  Xmit data to Receiver 
       Rcv = Xmt; 
       RcvX = Rcv & 0x07;      // take 3 lower bits for indeX 
       Pc = Hamming[ RcvX ]; 
       if( Rcv & 0x08 )        // This is MSB; if "1": value is 
           Pc = ~Pc & 0x07;    // .. negated from table: 3 lower bits 
 
Ahora se simula el proceso en el receptor, para lo cual se ejecuta Rcv = Xmt;. De manera análoga a la
que se siguió en el transmisor, se toman los 3 bits inferiores, se los almacena en RcvX y se usa esta
variable para leer la paridad correspondiente de la tabla Hamming, la que se guarda en Pc (Paridad
Calculada). Se niega o no, el valor leído según el bit #4 de la información recibida: if(Rcv & 0x08)…
       EX = ( Pc ^ ( Rcv >> 4 ) ) & 0x0F;  // Xor gives "1" on each 
       E  = column[ EX ];  // .. different bit. Get bit # from table  
Se toma la paridad recibida (  Rcv  >>  4  ), se sacan las diferencias con la Paridad Calculada,
empleando: ( Pc ^ ( Rcv >> 4 ) ); y se guarda ese valor, que corresponde al síndrome de Error EX
(que indica, según Hamming, la posición de la columna en donde hay un error). Empleando el
síndrome como índice para leer la tabla columna, se obtiene el número de la columna de la variable Rcv,
que hay que negar para obtener el resultado correcto.
       Rcv ^= E;               // Negate bit to correct it ! 
       Rcv &= 0x0F;            // Assure 4 bits. Outp corrected value 

C3-158
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Se niega el bit designado y se limita la respuesta a 4 bits mediante la máscara 0x0F. Note que si E vale 0,
no se niega ningún bit.
Para verificar el programa, y visualizar cómo el método corrige errores, se propone emplear la siguiente
metodología:
Debug using input = 0xF5 (0x05 data + spurious bits). 
Change “Rcv” from 0x55 to 0x57 to reflect received error on bit org. I5. 
Algorithm fixes data back to 0x05. 
 
Now debug using input = 0xFF ( 0x0F data + spurious bits). 
Change “Rcv” from 0x7F to 0x7E to reflect received error on bit org. I3. 
Algorithm fixes data back to 0x0F. 
 
Draw Logic Diagram, assigning input/output pins to 16F84A (note that this is ONE 
program, to simulate both: Hamming Generation AND Correction). 
 
El código en Assembler sigue la misma lógica del código en C (y se han incluído las líneas equivalentes
en C dentro del texto, para ayudar a entender el programa en Assembler), por lo que no es de esperar
que sea necesario repetir la explicación anterior.

C3-159
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

 CURIOSIDADES
Números en hexadecimal, escogidos de tal forma que aparentan ser palabras comunes del vocabulario,
como “DECODIFICADO”, “EFICIENCIA”, “OFICIO”, “CODICIA”, etc. El “1” representa la “i” (“DIA” es
“0xD1A”) y el “0” a la “O” (“ODA” es “0x0DA”); los demás son símbolos hexadecimales en propiedad.

 
Convertir de Hexadecimal a Binario: 
DEC0DIF1CADO =  CABECE0 =  DE1DAD = 
EF1CAC1A     =  C0D1C1A =  C0D1CE = 
ED1F1C10     =  BAB1ECA =  B1F1D0 = 
DECAD1C0     =  AC1D1CO =  B1F1D0 = 
D1AD1C0      =  DEC1DE  =  B1C0CA = 
 
Convertir de Hexadecimal a Octal: 
 
B0CAD0 =  0F1C10 =  CA0BA = 
B0BADA =  F1DE0 =  C0F1A = 
ACAC1A =  F0B1A =  C0C0A = 
ABAD1A =  EFEB0 =  BE0D0 = 
1DEAD0 =  D10D0 = 
0F1D10 =  CACA0 = 
 
Realizar las siguientes operaciones en Hexadecimal: 
 
BAB1A + B0C10 =  AD0BE ‐ AD0B0 =  ‐ ACAB0 + AC1D0 =  ‐ ABAC0 ‐ 1CAC0 = 
 
  0B1CE 
+ F0F0 
+ F0C0 
+ DED0 
====== 
 
DAD0 ‐ D0D0 + D0CE ‐ CEB0 = 
 
Realizar las siguientes operaciones en binario: 
 
CAC0 + CAB0 =  C0DA ‐ C0D0 =  ‐ C0CA + C0C0 =  ‐ C0BA ‐ B1C1 =
 
 
  B0FE 
+ B0DA 
+ B0CA 
+ B0CA 
====== 
 
B0B0 ‐ A1DA + 1DEA ‐ 1DE0 + DEAD = 
 
Realizar en decimal; dar respuestas en binario (usar Hex como intermedio): 
 
1B1D + 0DEA =  0D10 ‐ 0C10 =  ‐ 0B0E + 01D0 =  ‐ FE0 ‐ F1E =
 
 
  F1A 
+ EC0 
+ D1A 
+ D10 
===== 
 
C1D ‐ C1A + B1D ‐ B0A = 
1DA * 1D0 = 
1BA * 0DA = 
0CA * 0CA = 

C3-160
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

 REDES SECUENCIALES

INTRODUCCIÓN

L
OS métodos y el enfoque que presento para diseñar Circuitos Digitales, Combinatorios y
Secuenciales, hacen énfasis preponderante en el empleo de microcontroladores, a diferencia
de la literatura convencional pues, en general, no se aborda el tema de similar manera en libros
de texto que, con gran acogida, versan sobre el diseño lógico, según puede corroborarse al ojear
las referencias universalmente preferidas en asignaturas de este tipo.

Los que alguna vez hicieron una práctica de laboratorio para implementar con un micro, todas las 16
funciones de dos variables, recordarán cómo puede implementárselas todas al mismo tiempo utilizando una
simple tabla para definirlas simultáneamente, lo cual resulta muy sencillo y conveniente, al menos desde
el punto de vista conceptual, y salvando siempre las peculiaridades de cada familia de micros con sus
recovecos y sus, a veces, retorcidos conjuntos de instrucciones.

CONCEPTO DE “ESTADO”: EL PROFESOR GIRATORIO

S
I, por ejemplo, hemos diseñado una red combinatoria para sumar dos valores, y le introducimos
como datos de entrada los números 3 y 5, la respuesta será 8. Si más tarde volvemos a sumar 3
más 5, obtendremos 8 de nuevo. Y, si mañana repetimos la operación, el resultado volverá a ser
(o sorpresa) ¡el mismo! En un circuito Combinatorio, las salidas son siempre, funciones exclusivas
de las entradas que se le presentan. Para una determinada combinación, la salida será la misma todas las
veces, con independencia, sobre todo, de la variable “tiempo” (el antes y el ahora).

Suponga por un momento que nos encontramos en el salón de clase, y que tenemos un interruptor cuya
función manifiesta es la de ordenarle al profesor: “Gire 180 grados”. Si usted lo activa, y le pregunta a
alguien que está por fuera del aula: “¿Hacia dónde mira ahora el profesor?”, con seguridad la respuesta
incluirá, a su vez, un interrogante: “Depende; ¿a dónde miraba él originalmente: al tablero o a los alumnos?”. Para
que nuestro interlocutor pueda saber a dónde quedó mirando el profesor, no le basta con conocer el
valor de la entrada (“Gire 180 grados” o “Quédese quieto”); tiene que saber también la posición del profesor,
en el momento en que lo instruyeron para girar o para permanecer inmóvil.

Toda Información que se precise conocer –además de las Entradas– para determinar con
certeza el Resultado que, en un instante dado, provocará determinado Estímulo de Entrada,
representa el “Estado” del sistema o del circuito. Como tal información debe residir dentro del
Sistema (no es externa, como las entradas), tiene que reposar en una “Memoria” apropiada.

C3-161
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

En el ejemplo anterior, el profesor solo tiene dos posibilidades (o estados): o mira a los estudiantes, o al
tablero. Para representar esos estados bastaría con asignar una Variable de Estado, con sus dos valores
lógicos, cero y uno. Podemos decir (o “asignar”), por ejemplo, que, de esa variable de Estado, el valor
0 indica: el profesor está de cara a los estudiantes, mientras que el 1 indica que mira al tablero.

El Estado Futuro del profesor depende de su comportamiento previo, que está resumido en el Estado
Presente, y para saber ahora, lo que pasó antes, es preciso “memorizar” la historia…, toda, o alguna
parte de ella. Así pues, las Variables de Estado son elementos booleanos que residen en unidades
de memoria, y resumen –o representan– el pasado relevante del sistema.

En situaciones más complejas que las de nuestro ejemplo pueden necesitarse más variables para
representar los Estados de un sistema. Tal como ocurría en las “codificaciones” que vimos en redes
Combinatorias, para representar ahora “N” Estados, se necesitan “n” variables de Estado tales que:
n
2  >= N. Así, por ejemplo, si nos piden diseñar un circuito que “cuente” las personas que hay en el
salón, si ya hubiera 4 alumnos y llegara uno más, el circuito indicaría 5; es decir, el estado futuro a partir
del 4 es el 5, si entra un individuo más. Pero si el contador señalara que ya se contabilizaron 6 alumnos
en el salón, al entrar otro la cuenta pasaría de 6 a 7, pues el estado futuro al que se llega a partir del 6,
cuando entra alguien más, es el 7. Si el valor máximo del contador fuera, por ejemplo, N=16, se
4
necesitarían al menos n=4 variables de Estado para su codificación, ya que 2 = 16, lo que satisface la
relación antes señalada.

Observe que siempre pueden usarse variables de más, pues la inigualdad se sigue satisfaciendo al
crecer n, pero es altamente probable que al introducir variables de estado por encima de las necesarias
se incrementen los costos del circuito; por eso, trate en lo posible de codificar los estados, casi siempre,
con el mínimo número de variables y, en general, intente también que los estados distintos con los
que usted representa un problema, se mantengan en un mínimo.

Un circuito Combinatorio es un caso particular de uno Secuencial, en el que solo hay un estado; si se le
asignara una variable de Estado, ésta tendría, siempre, un valor: por ejemplo el cero (o el uno). Una variable
booleanas que solo asume un valor dentro del contexto de un problema, no aparece en la formulación
del mismo; por tanto, en realidad, no se precisa de ninguna variable de Estado para definir un circuito
Combinatorio; es decir: Una red Combinatoria no necesita usar ninguna celda de memoria.

UNA SOLUCIÓN: PLANTEAMIENTO


Al igual que hicimos al tratar los circuitos Combinatorios, en esta época de generalización de los tan
económicos y muy convenientes microcontroladores, la primera alternativa de solución de un
problema secuencial –y quizás la definitiva– se centra también en ellos.

Si además de lo dicho antes, en el ejemplo del Profesor Giratorio, el sistema tuviera que generar una
“salida” Z, que estuviera en 1 para indicar que el profesor mira a los estudiantes (y en 0 sería
cuando mira al tablero); podríamos hacer una representación del ejercicio mediante una tabla, así:

C3-162
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Index  Estado  “S”  INPUT I  Estado  Estado Futuro S+:  Salida  Z 


(“C” Table)  Presente S:  (esta columna  (G180°)  Futuro  (esta columna  Z  (esta 
o codifi‐ 0: mira a los  reemplaza la de la    S+  reemplaza la de la    columna 
cación:  estudiantes,  izquierda, si se  vale:    izquierda, si se  es:  reemplaza la 
c/Estado  1: mira al  emplean etiquetas  será:  emplean etiquetas    de la 
| Input  tablero  en vez de números)  en vez de números)    izquierda, 
vale:  (Mealy)  para 
Moore) 
0 (b00)  0  Mira_Tablero  0  0  Mira_Tablero  1  1 
1 (b01)  1  1  Mira_Estudiantes  1 
2 (b10)  0  1  Mira_Estudiantes  0 
1  Mira_Estudiantes  0 
3 (b11)  1  0  Mira_Tablero  0 

Esta tabla recibe el nombre de Tabla de Estados, o Tabla de Transiciones (entre estados). A la izquierda
se indican el Estado Presente y las Entradas y éstos, en su conjunto, determinan cuál SERÁ el Estado
Futuro del sistema, y cuál ES su salida. Para individualizar y facilitar la identificación de cada fila se ha
añadido un número cardinal, entre 0 y 3 (el Index de la Tabla). El estado 0 es el inicial.

Note: Como solo hay dos (2) estados, se han nombrado como 0 y 1, pero éstos dos símbolos NO son números binarios: Si
hubiera más estados se identificarían, por ejemplo, como 0, 1, 2 y 3. Y ni siquiera tienen por qué ser números: podemos
identificarlos con etiquetas sugestivas, tales como: “mira_tablero”, “mira_estudiantes”. (Las columnas resaltadas en
este color son redundantes; reemplazarían a las de su izquierda si los nombres no fueran 0 y 1, sino etiquetas sugestivas).

En este ejemplo, la salida resultó ser la misma para cada estado, independientemente de si la entrada
vale cero o vale uno, lo que quiere decir que la salida NO depende de la entrada: La salida está asociada
solo al Estado. A sistemas de esta naturaleza se los conoce como Máquinas de Moore. En otras
circunstancias puede ocurrir que, para un mismo estado, la salida sí tenga un valor distinto, según las
diferentes combinaciones de entrada: Esas son Máquinas de Mealy y las salidas dependen del estado
en que se encuentre el circuito y del valor que tengan las entradas.

Otras varias clases más de circuitos: Los hay sin entradas; se denominan “autónomos” (como los
contadores simples). Los hay sin salidas; se asume que éstas se toman directamente de las variables de
Estado. Otros dependen de las entradas, y también de las salidas pretéritas; se los llama “máquinas de
memoria finita”.

En la fila 0 el estado es 0 (“mira los estudiantes”); la entrada 0 significa que no se quiere hacer girar al
profesor, por lo tanto éste no se moverá, y en el estado siguiente (futuro) el profesor seguirá mirando a
los estudiantes, lo que se representa también con el símbolo 0 para el estado futuro. La salida, según se
pide, es un 1 para indicar que se está de cara a los estudiantes.

En la fila 1 se activa la entrada (1), indicándole al profesor que gire 180°. Como en esa combinación el
estado presente vale 0 (el profesor mira a los estudiantes), el estado futuro será 1; la salida vale 1, pues en
la situación correspondiente a esa fila, el profesor mira a los estudiantes.

En la siguiente posición, la 2, no se le indica al profesor que se mueva (entrada 0); como esta fila señala
que el profesor mira a la pizarra (estado presente 1), el estado futuro seguirá siendo el mismo que el
presente, 1. La salida vale 0, dado que no se está mirando a los estudiantes.
Finalmente, en la fila 3 también se activa la entrada (1), con lo cual el profesor procederá a girar. Como
éste mira al tablero (estado presente 1), el estado futuro será 0 (mirará a los estudiantes); la salida para
esa fila es 0, pues el profesor no está mirando a los estudiantes sino al tablero.

C3-163
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

PROGRAMACIÓN DE LA SOLUCIÓN

Como se pretende inducir de manera preponderante, el empleo de micros para solucionar problemas
digitales, podemos indicar que una forma de programar la solución a este ejercicio consiste en ver la
tabla como si fuera un arreglo de una dimensión, manipulable en lenguaje “C”, siguiendo la tónica de la
solución que planteamos en redes combinatorias al emplear micros. Este tipo de estructura de datos
tiene dos dimensiones en los lenguajes de programación: la ubicación y el contenido. La posición es un
ordinal (no negativo), que identifica el elemento de la tabla mediante su índice. Recuerde que en “C”
los arreglos comienzan en la posición “0” y progresan hasta alcanzar n-1 para un total de “n” elementos.

De esta manera el proceso es como sigue: Leer el terminal de entrada, I, concatenarle el valor del
estado presente, S, para generar un índice, Ix, compuesto por S|I, que sirva para extraer de la tabla las
+
respuestas: Estado futuro S y Salida actual Z, pues eso son los valores almacenados allí…

Para efectos del programa, el Estado Presente S se denominará PS (Present State) y el Estado Futuro
+
S será: NS (Next State). El código tiene el siguiente aspecto:

void main( void ) 
{  char I;           // Input  (8 bits); solo se usa el primero: I0 
   char Z;           // Output (8 bits); solo se usa el primero, Z0 
   // Indice tabla: b00, b01, b10, b11   Contenido: Tabla de Verdad 
   char tabla[] = { b01, b11, b10, b00 };      //  NS  | Z 
   char PS = 0;      // Present State; hay que inicializarlo... 
   char Ix;          // Indice para la tabla[] 
 
   while( 1 ) {      // o for(;;): forever. Este programa nunca termina 
      I = input();   // input(): función de biblioteca. Retorna el 
                     // .. valor del bit (o bits) de entrada, I. 
      Ix = PS | I;   // agregado, vía OR, de PS e I 
      PS = tabla[ Ix ] & b0000_0010;  // NS se convierte en PS 
      Z  = tabla[ Ix ] & b0000_0001;  // Toma solo “Z” 
      output( Z );    // output(): función de biblioteca. Lleva el 
                      // .. bit de salida al exterior del micro. 
      usleep( 1000000 ); // Espere un segundo antes de continuar 
}
}
Recuerde que si su compilador de “C” no entiende los símbolos b100, b0000_0010 o similares, como
representación de números en binario, usted debe agregar unas definiciones del siguiente tenor:
#define  b00          0 
#define  b01          1 
#define  b11          3 
#define  b0000_0001   1 
#define  b0000_0010   2 
(etc…) 

C3-164
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Aquí hay también varios comentarios en relación al código. En primer lugar, este tipo de programación,
en donde un microcontrolador está leyendo continuamente las variables de entrada y produce en
consecuencia valores de salida, son ciclos infinitos, tal como dijimos que son los que controlan un
horno de microondas o un televisor digital: nunca reposan, sus programas nunca terminan y ésto es
típico o característico de los de sistemas “embebidos”.
Como los micros en la actualidad tiene tiempos de ejecución muy veloces (menos, o mucho menos de
un microsegundo por instrucción), podemos introducir un “retardo” apropiado (usleep), por ejemplo
de un segundo (1 millón de microsegundos), al finalizar el ciclo, para dar tiempo al usuario a activar una
vez la entrada sin que el pobre profesor gire y gire como una centrífuga. Sin el retardo, el micro ve que
el botón se puso en 1 y transita hacia el estado futuro 1; inmediatamente vuelve a mirar la entrada, que
sigue en 1 (porque ningún usuario puede retirar el dedo a esa velocidad); por tanto, el programa vuelve a
cambiar de estado y el profesor inicia un nuevo giro, y así en vertiginosa sucesión. Si el tiempo escogido
para el retardo no fuera el apropiado, puede ajustare su valor; si ningún tiempo resultara conveniente,
habrá que introducir una nueva señal de sincronización (Ck), que le indique al programa cuándo es
apropiado leer la entrada I. El programa, al ver la activación de Ck procederá a realizar su trabajo y, al
final, se quedará esperando hasta que Ck retorne a cero, antes de continuar y repetir el lazo.
La gran ventaja de la aproximación que emplea tablas para resolver los problemas secuenciales, igual a
como resultó la solución equivalente para implementar redes combinatorias, es que cualquier problema
de esta naturaleza (redes Secuenciales) puede resolverse con el mismo algoritmo. Basta con escribir la
tabla correspondiente, que relaciona estados presentes y entradas, con salidas y estados futuros, y el
mismo algoritmo los resolverá, pues éste es absolutamente general: Hay una tabla en la cual, para
todas las combinaciones de entradas y de estados presentes, se han establecido todas las Salidas y los
Estados Futuros. Se leen las entradas, se forma un Índice agregando las Entradas al estado Presente, se
buscan las respuestas en la tabla y con ellas se actualiza el Estado Presente, se genera la Salida y se repite
el ciclo (previo retardo, o sincronización externa, según corresponda).
Note que al igual que en redes combinatorias, un problema con 16 entradas, entre variables externas y
de Estado (internas), ocupará 2^16 posiciones (65536), posiblemente demasiadas para un micro corriente.
Y recuérdese que dicha tabla crece de manera exponencial pues, como se sabe, cada nueva variable, de
entrada o de Estado, hace duplicar el número de celdas de la tabla. Así que hay que establecer
alternativas si es que el problema se sale de control.
Pero, si hay capacidad de almacenamiento, ningún método es superior a éste.

Ejercicio: Realice un programa equivalente, en lenguaje ensamblador del micro.

C3-165
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

EJEMPLO #2: SECUENCIA “111” CON SOLAPAMIENTO


Index  Estado  INPUT I  Estado  Salida   
(“C” Table) 
o codificación:  Presente  (G180°)  Futuro  Z 
c/Estado  S:  vale:  S+  es: 
| Input  vale:  será: 
0 (b000)  0  0  0  0   
1 (b001)  1  1  0   
2 (b010)  0  0  0   

3 (b011)  1  2  0   
4 (b100)  0  0  0   

2  Mealy 
5 (b101)  1  2  1 
Tabla de Estados, o Tabla de Transiciones (entre estados)

PROGRAMACIÓN “111” CON SOLAPAMIENTO


void main( void ) 
{  char I;           // Input  (8 bits); solo se usa el primero: I0 
   char Z;           // Output (8 bits); solo se usa el primero, Z0 
   // Indice tabla: b00 0, b00 1, b01 0, b01 1, b01 1, b01 1  Tabla de Verdad 
   char tabla[] = { b00 0, b01 0, b00 0, b10 0, b00 0, b10 1,  };  //  NS  | Z 
   char PS = 0;      // Present State; hay que inicializarlo... 
   char Ix;          // Indice para la tabla[] 
 
   while( 1 ) {      // o for(;;): forever. Este programa nunca termina 
      I = input();   // input(): función de biblioteca. Retorna el 
                     // .. valor del bit (o bits) de entrada, I. 
      Ix = PS | I;   // agregado, vía OR, de PS e I 
      PS = tabla[ Ix ] & b0000_0110;  // NS se convierte en PS 
      Z  = tabla[ Ix ] & b0000_0001;  // toma solo “Z” 
      output( Z );    // output(): función de biblioteca. Lleva el 
                      // .. bit de salida al exterior del micro. 
      usleep( 1000000 ); // Espere un segundo antes de continuar 
   } 

Puede verse que la estructura del programa es idéntica a la del ejercicio anterior; solo cambia la máscara
que se emplea para aislar el NS leído de la tabla, puesto que ahora hay dos (2) bits para codificar el
Estado de la máquina, y en el ejercicio previo había solo un (1) bit para ello.

Ejercicio: Realice un programa equivalente, en lenguaje ensamblador del micro.

C3-166
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

EJEMPLO #3: SECUENCIA “111” SIN SOLAPAMIENTO


Index  Estado  INPUT I  Estado  Salida   
(“C” Table)  + 
o codificación:  Presente  (G180°)  Futuro S Z 
c/Estado  S:  vale:  será:  es: 
| Input  vale: 
0 (b0000)  0  3(b011_)  0   

1 (b0001)  1  1(b001_)  0   
2 (b0010)  0  4(b100_)  0   

3 (b0011)  1  2(b010_)  0   
4 (b0100)  0  0(b000_)  0   

2  Mealy 
5 (b0101)  1  0(b000_)  1 
6 (b0110)  0  4(b100_)  0   

7 (b0111)  1  4(b100_)  0   
8 (b1000)  0  0(b000_)  0   

9 (b1001)  1  0(b000_)  0   
Tabla de Estados, o Tabla de Transiciones (entre estados)
Detecta 111: (0)1/0->(1) (1)1/0->(2) (2)1/1->(0)
No Detecta 111: (0)0/0->(3) (1)0/0->(4) (2)0/0->(0) (3)X/0->(4) (4)X/0->(0)

PROGRAMACIÓN “111” SIN SOLAPAMIENTO


void main( void ) 
{  char I;           // Input  (8 bits); solo se usa el primero: I0 
   char Z;           // Output (8 bits); solo se usa el primero, Z0 
   char tabla[] =    // arriba: ubicación, abajo: contenido ( NS  | Z) 
//b000 0, b000 1, b001 0, b001 1, b010 0, b010 1, b011 0, b011 1, b100 0, b100 1 
 {b011 0, b001 0, b100 0, b010 0, b000 0, b000 1, b100 0, b100 0, b000 0, b000 0}; 
   char PS = 0;      // Present State; hay que inicializarlo... 
   char Ix;          // Indice para la tabla[] 
   while( 1 ) {      // o for(;;): forever. Este programa nunca termina 
      I = input();   // input(): función de biblioteca. Retorna el 
                     // .. valor del bit (o bits) de entrada, I. 
      Ix = PS | I;   // agregado, vía OR, de PS e I 
      PS = tabla[ Ix ] & b0000_1110;  // NS se convierte en PS 
      Z  = tabla[ Ix ] & b0000_0001;  // toma solo “Z” 
      output( Z );    // output(): función de biblioteca. Lleva el 
                      // .. bit de salida al exterior del micro. 
      usleep( 1000000 ); // Espere un segundo antes de continuar 
   } 

La estructura del programa sigue siendo idéntica a la del anterior; solo cambia la máscara que se emplea
para aislar el NS leído de la tabla, pues ahora hay tres (3) bits para codificar el Estado de la máquina.
Ejercicio: Realice un programa equivalente, en lenguaje ensamblador del micro.

C3-167
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

 HÁGASE LA LUZ

E
L diseñador digital novel suele entender bastante bien la operación de sus circuitos “en estado
estacionario”, es decir, una vez que llevan algún tiempo conectados a la alimentación eléctrica
(5 V DC típica). Los autores de libros de texto tienen su temática depurada y hasta uniforme, y
casi cualquier tomo moderno cubre ciertos recovecos teóricos como la pulcra sincronización
de las señales de entrada –indispensable premisa para el diseño de redes secuenciales sincrónicas–; la
apropiada captura de información externa con duración menor a la de uno de los sempiternos pulsos
del reloj maestro; la eliminación de rebotes; los condensadores de desacople, la incorporación de
resistencias limitadoras de corriente en las entradas no usadas y demás aspectos técnicos relacionados.

Pero hay una zona oscura que casi nunca se toca, en la que el ingeniero digital navega a tientas, a pesar
de ser esencial para el funcionamiento de sus proyectos: La adecuada materialización automática del
debido “estado inicial”, al momento de encender su equipo.

1) RECONECTADOR
A este respecto hay que indicar que el voltaje de alimentación debe aplicarse de tal
manera que se satisfagan los requisitos de estabilidad en el oscilador maestro, del
cual se deriva el mecanismo de reloj; es común que haya que esperar un tiempo
considerable, comparado con los valores de trabajo del equipo, a fin de que la
oscilación obtenga el voltaje y la frecuencia deseados, máxime si en su diseño se
incluyen técnicas de PLL (Phase Lock Loop), comunes en los microcontroladores
(por ejemplo, Freescale). No resulta conveniente usar la señal de reloj hasta que no
haya alcanzado su valor estacionario de diseño. Lo usual es inhabilitar sobre todo
los flip-flops, lo que se logra generando una señal de “Clear” que dura entre 100 y
500 ms, con un circuito RC simple y una compuerta del tipo Schmitt Trigger
(74xx14 o similar). Este dispositivo se conoce como el “ Reconectador ”.

Al aplicarle la alimentación al circuito de la figura, el condensador tarda en cargarse un tiempo


determinado por su constante RC, que debe especificarse según sea necesario para lograr la estabilidad
de los osciladores. La salida del Schmitt Trigger se lleva a todos los puntos de “Estado Inicial”,
probablemente las señales de “Clear” de los flip-flops. Si éstas se activan en un nivel bajo, lo que es
típico, hace falta añadirle un negador al circuito de la figura, además de las consideraciones referentes al
fan-out o carga de esta señal, pues se puede exceder con facilidad la capacidad normal de las
compuertas, implicando la adición de buffers/drivers. El diodo inverso, en paralelo con la resistencia,
sirve para descargar con rapidez el condensador y reinicializar todo el proceso de nuevo, en caso de que
la fuente baje a cero, por un apagón, o un “glitch”.

Si se necesitara un nivel mayor de control sobre el voltaje, porque pudieran aparecer en la fuente de
alimentación niveles intermedios, menores de 4.5 V –lo que es previsible en dispositivos con pilas– que
ameritaran desconectar el circuito, podría incluirse un “Supervisor de Voltaje”, al estilo del TL7705.

C3-168
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

2) COMPORTAMIENTO ASINCRÓNICO
Ahora bien; ni el supervisor ni el más simple reconectador de la figura resuelven a priori un problema
de sincronización, sutil pero vital, que consiste en que si no se toman mayores medidas, el reloj
comienza a aparecer en todas partes –no influyendo en el comportamiento del circuito, gracias a que la
señal de “Clear” la mantiene activa el reconectador– pero cuando el Schmitt Trigger cambia de estado,
lo hace de manera asincrónica respecto al reloj. Terrible inconveniente que viola la norma que exige
garantía de que todas las señales, incluyendo el “Clear”, tengan un valor estable cierto tiempo antes de
la llegada del reloj. Si no se sigue ese precepto el resultado es que algunos flip-flops pueden comenzar a
“ver” el pulso de reloj, y otros no... y así, el comportamiento del circuito se vuelve indeterminado.

Cuándo y cuánto afecta este problema a un dispositivo depende de la probabilidad de que el fenómeno
aleatorio produzca una ventana de tiempo inapropiada. Puede ser que el circuito funcione bien una y
otra vez, pero si la probabilidad de que falle no es nula el diseño tiene un error, que es imperativo corregir.

3) “ARRANCADOR” (STARTER)
El siguiente circuito garantiza el estado inicial previsto por el diseñador, a pesar de la incertidumbre
mencionada en los párrafos anteriores. Por facilidad, el ejemplo hace referencia a aquellas máquinas que
se programan con un flip-flop por estado, pero el concepto puede ampliarse a diseños con contadores
comerciales, o ad-hoc, que necesiten inicialización sincrónica o a asincrónica.

Se muestran sólo dos FFs, representando


cada uno un estado. El FF de la izquierda es
el único de todos que tiene activación inicial
vía Preset; los demás lo hacen mediante
Clear; así que el primer flip-flop asume el
valor 1 y los demás, 0: 10.

Tal como se indicó, la señal de Estado


Inicial (Power-up) se encuentra conectada a
los Preset y Clear apropiados y se activa un
largo tiempo (100 a 500 ms), durante el cual
el reloj comienza a entrar de manera estable
a todos los FFs, sin efecto alguno pues la señal de Estado Inicial está activa. Ahora, cuando se
desactivan los Clear y Presets, liberando los FFs para que comience la secuencia de estados, al compás
del Reloj, se ve que el estado futuro del primer FF es 1, producido por la compuerta and, su propia Q en
1, y la Q’ del segundo flip-flop, que aún está en 0 (Q en 0; Q’ en 1). Si el primer pulso en llegar no fuera
visto por el FF de la derecha, la situación se mantendría exactamente así: 10, hasta la llegada del próximo
pulso. Nótese que el FF de la izquierda mantiene su estado en 1, vea –o no– el pulso de reloj.

Cuando finalmente el segundo flip-flop cambia de estado (11), ahora sí es verdad que todos están en
sincronismo (las señales de la red cambian sólo con el borde de subida del Reloj); el estado es: Ambos flip-flops en
1 (11) y, luego, el hecho que el flip-flop de la derecha asuma el valor de 1 hará que el FF de la izquierda
vaya finalmente a 0 (01), de donde no saldrá jamás, salvo que se reanude la secuencia de energización al
volver a encender el circuito, o mediante una señal externa de Reset (no representada en la figura).

C3-169
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Siendo una red con un FF por estado, el hecho de que ambos flip-flops de la figura se encuentren
alguna vez en 1 imposibilita la utilización de la Q del flip-flop izquierdo para algún otro propósito en el
circuito; es decir, ese biestable sirve únicamente para arrancar la secuencia (starter).

4) CONVERTIR FLIP-FLOPS CON “CLEAR”, EN BIESTABLES CON “PRESET”


Este es un problema práctico que los principiantes no
saben resolver. Espero que mi solución resulte
provocativa, y les llame la atención el ver que basta con
cambiar el nombre de las entradas y las salidas para
resolverlo. Quién iba a creerlo...

Hay alumnos que cuando necesitan un flip-flop con


Preset y los que están a la mano solo tienen Clear, salen
de compras. Intento mostrar cómo hacer que flip-flops
como los 74xx73, 74xx107 o similares, para flip-flops JK;
y los 74xx174 (ver figura), 74xx175, etc., para tipo D, que
sólo tienen Clear, se comporten como si lo que
tuvieran fuera Preset. Analice a conciencia el caso
particular del 74174, hex D-type flip-flops with clear. Son
seis biestables tipo D, con una sola entrada de Clear
común a los 6, y de cada uno sale exclusivamente su Q;
la Q’ (negada) no tiene un terminal asignado en el 174.

En los flip-flops tipo JK la conversión es fácil, porque son absolutamente simétricos: La trayectoria de la
J va por las compuertas superiores y llega a la Q, y la K entra por las inferiores y progresa hasta la Q’. El
Clear va también por la línea inferior, la correspondiente a la K. Ahora, si renombramos los terminales
(sí; las denominaciones son una convención, ¿o no?), y llamamos J a la anterior K, K a la vieja J; lo que
conocíamos como Q lo nombramos Q’ y viceversa, la Q’ es la Q..., todo seguirá siendo igual para la
nueva denominación de los terminales, sólo que ahora ¡ la señal de Clear se ha convertido en Preset !

El flip-flop tipo T también es absolutamente simétrico, puesto que no es otra cosa que un JK con las
entradas unidas, por lo que el método se aplica igual.

Como los flip-flops que más se usan, sobre todo a nivel de PLD (FPGA, PAL, PLA, etc.) son los tipo
D (con Clear), resulta de la mayor importancia descubrir cómo convertirlos para que el Clear opere
como Preset...

Si recordamos que para hacer un tipo D con JK, la


D se conecta a la J, y a la K va la D’, podemos
deducir que, para convertir un flip-flop tipo D,
con Clear, en uno con Preset, bastará con
incluir un negador en la entrada D, y otro a la
salida Q, como muestra la figura de la derecha:

C3-170
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

 REPRESENTACIÓN NUMÉRICA
Los Números son la Clase Fundamenal de Información Digital

INTRODUCCIÓN

C
UANDO hicimos el ejercicio de la Fábrica de Chocolates fuimos viendo que las variables de
entrada, Lucy, Ethel y las Cajas de cartón, se caracterizaban porque asumían solo dos valores:
las empleadas, o estaban presentes en la fábrica, o no se encontraban, y había, o no había cajas.
La representación de esas variables ha ido transcurriendo históricamente por los símbolos On‐
Off,  High‐Low  (H‐L),  True‐False  (T‐F)  y  1‐0, y su materialización electrónica corresponde
normalmente a dos voltajes, siendo +5V  y  0V los más utilizados. Una sola variable puede asumir,
entonces, las combinaciones 0 o 1. Para analizar un problema como el de la Fábrica de Chocolates se
hace necesario entender lo que sucede cuando ocurren distintas combinaciones entre las variables.
Dijimos que estudiar lo que pasaba, dependiendo de la asistencia de las dos operadoras, correspondía a
ver primero qué acontecía si Lucy no estaba (0), mientras Ethel asumía, a su vez, sus dos oportunidades,
0 y 1. Y luego se veía lo que ocurría cuando Lucy sí estaba (1) y Ethel repetía sus dos representaciones,
0 y 1. De esta manera pasamos de dos (2) posibilidades para una sola variable (0, 1) a cuatro (4) para
dos variables: 0 0, 0 1, 1 0, 1 1. Para incluir las Cajas como tercera variable había que analizar las
cuatro combinaciones que acabamos de referir, asumiendo que no había Cajas (0), y luego repetir el
análisis cuando sí hubiera Cajas (1), lo que produciría una tabla con 8 posiciones (y, en general, 2^n
posibilidades a analizar para n variables): 0 00, 0 01, 0 10, 0 11, 1 00, 1 01, 1 10, 1 11. Los
diversos grupos en realidad no se separan por espacios como aquí, sino que en cada combinación los
ceros y unos van unidos: 000, 001, 010, 011, 100, 101, 110, 111.

Para cada uno de estas “combinaciones” hay que definir las salidas correspondientes a cada situación; en
sistemas Digitales, también las salidas suelen ser discretas, binarias (dos valores). Cuando indicamos
cómo representar esa tabla en el lenguaje de programación “C” (char Tabla[8]), vimos que para cada
una de las 8 combinaciones, las tres variables de salida de la fábrica (control de las velocidades de la cinta
transportadora) asumirían unos valores u otros; resultó apenas natural sugerir que la primera
combinación, la 000, se alojara en la primera posición de la Tabla, la segunda, 001, en la siguiente, y así
sucesivamente. Como cada elemento de una tabla en “C” se individualiza mediante un índice (index), y
los índices en este lenguaje corresponden a números ordinales (sin signo) que comienzan en 0 y, en el
ejemplo, van hasta el 7, resultó apenas natural la asociación entre estos números ordinales y las
combinaciones que se establecieron entre las variables, o sea:

0: 000, 1: 001, 2: 010, 3: 011, 4: 100, 5: 101, 6: 110, 7: 111

Hay que repetir aquí que las combinaciones originales de la tabla, para las posiciones que van del 000 al
111, no tienen ninguna connotación numérica: son simplemente combinaciones entre valores
booleanos. Pero si de manera espontánea o natural, aceptamos la asociación que resulta entre números
en base 10 y dichas combinaciones binarias, habremos llegado a una de las más frecuentes
codificaciones para representarlos en binario números en base 10. Así, pues, revise los diferentes
grupos de 3 bits para familiarizarse con la denominada Codificación de Decimal en Binario Natural,

C3-171
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

o BCD (Binary Coded Decimal), en donde la palabra Natural apenas refleja la manera tan espontánea
como aceptamos esta asociación o codificación. Para representar números ordinales mayores a 7,
habrá que agregar bits a la izquierda, hasta llegar a la casilla cuyo índice necesitamos representar (los
índices de la tabla en “C”).

Hay muchas técnicas para elaborar las combinaciones entre variables; usted debe consultarlas en
cualquier libro introductorio de Digitales. Baste con resaltar que, si se mira la tabla por columnas, la
primera (unidades) va cambiando siempre: 0, 1, 0, 1… La segunda columna varía con la mitad de la
frecuencia que la primera: 0, 0, 1, 1…, y así sucesivamente, de derecha a izquierda.

Asimismo, si analizamos con detenimiento los números binarios resultantes, notaremos que cuando la
primera columna aporta un valor para identificar la cantidad decimal (cuando hay un 1 en esa columna),
el agregado corresponde a 2^0: 1, el de la segunda columna: 2^1: 2, la tercera: 2^2: 4, etc. Así como en
el sistema decimal las columnas o posiciones son potencias de diez (1, 10, 100), en BCD son potencias
de dos: 1, 2, 4, 8, 16…

Hay otras cosas que podemos inferir también, como las reglas para las operaciones de suma y resta:
Como cada uno de los guarismos de la tabla está separado del siguiente por una unidad, podemos
analizar la suma del primero más uno: 000 + 001, respuesta 001; vemos que se aplican las reglas:
0 + 1 = 1 y 0+0=0.
Al revisar la siguiente suma, 001 + 001, resultado 010, vemos que hay una regla adicional:
1 + 1 = 0 y lleva 1 (el acarreo, o carry, que se suma en la siguiente columna como 1 + 0 = 1).
La última regla está repetida, porque la suma es conmutativa: 0 + 1 = 1 + 0 = 1.

Para la resta puede hacerse un análisis similar y obtener así las cuatro reglas resultantes, pero como no
vamos a hacer muchas restas, y no se pretende describir aquí toda la teoría, sino complementar el
material que comúnmente leemos, se deja como ejercicio al interesado.

Las sumas van muy bien siempre pero las restas, como ocurre también en nuestra aritmética decimal
ordinaria, funcionan correctamente solo si no se pretende restarle a una cifra, otra de mayor valor: no se
puede substraer 3 de 2.

Lo que hacemos en base 10 para efectuar operaciones en las cuales se queda debiendo (como retirar del
banco 100, cuando solo tenemos 10, para lo cual debe pedirse un préstamo de al menos 90), hay que poder indicar esa
situación: que se queda debiendo, lo cual corresponde a lo que denominamos un resultado “negativo”.
Y se necesita un símbolo extra, el “signo”, para diferenciar los números positivos de los negativos. En
nuestra aritmética corriente, al signo se lo identifica con un símbolo diferente a los números, que van
del 0 al 9 en decimal: éste símbolo es el “+” o el “-”. Pero nuestros circuitos digitales solo aceptan la
representación On‐Off, High‐Low (H‐L), True‐False (T‐F), 1‐0, siendo, desde luego, el 1 y el 0 la
más usada (y, hay que repetirlo una vez más, estos 1 y 0 NO son números: son símbolos
arbitrarios que caprichosamente usamos para indicar: existencia o ausencia de un elemento o
variable del problema, cerrado o abierto, verdadero o falso…)

C3-172
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Así que como nos vemos compelidos a emplear los mismos dos símbolos que también se usan para
representar los dígitos binarios, una forma de significar que éste 0 o 1 es un signo, y no un dígito, es por
su posición; quedamos, entonces, en que el signo en binario es un 0 o un 1, que se encuentra en una
determinada posición, fija y conocida, dentro de las casillas o columnas que representan el número.

Cuál valor será usado como el signo positivo y cuál como el negativo, y en qué columna, son, con
mucho, decisiones arbitrarias, como lo son todas las maneras de codificación, y que consisten, en
términos generales, en seleccionar un conjunto de elementos de un “alfabeto” para representar
información que en su origen emplea símbolos de otro alfabeto. Un pequeño detalle, más o menos
insignificante, puede servir para sesgar nuestra decisión a la hora de seleccionar el símbolo que
identificará el signo: Ya vimos, de la codificación BCD para números sin signo (arriba), que el cero
decimal corresponde a 0...00, una secuencia de varios ceros, tantos como se necesiten en un momento
dado. No se vería nada mal que también el cero, en números representados “con signo”
correspondiera a esa misma secuencia 0...00. Si es así, el signo positivo se codificará como un 0, y por
tanto, el negativo será un 1. En cuanto a la posición en dónde alojarlo, la convención más empleada es
la de colocar el signo a la izquierda de los guarismos numéricos…, pero más de una computadora
emplea convenciones numéricas en las que se coloca el signo a la derecha; por ejemplo, la
representación “decimal empaquetado” de los sistemas 360/370 de IBM.

En el siguiente paso en la escogencia de códigos para representar números con signo, hay que ver qué
conviene más. Para comenzar, poder escribir el +2 como 0010, y el -2 como 1010 sería genial desde el
punto de vista de la persona que escribe la cifra: al guarismo que representa el número (010, si
empleamos, como ejemplo, tres bits más signo) basta con agregarle, a la izquierda, el signo: cero para
positivo y uno para negativo. A esta representación se la conoce en la literatura como “signo y
magnitud” y, a pesar de lo simple que resulta de escribir, tiene varios inconvenientes que lo reducen a
un sistema intermedio, auxiliar entre lo que conviene al usuario y lo que es bueno para el equipo. Uno
de los problemas aparece cuando queremos sumar cantidades de signos contrarios; por ejemplo, +2 con
-2. Si tratáramos de aplicar las mismas reglas básicas aprendidas anteriormente para sumar cantidades
sin signo, el resultado sería:  0010  +  1010  =  S100. Hemos colocado “S” en la posición del signo,
porque aún no hemos decidido qué hacer con esa casilla... Pero, independientemente de lo que
decidamos en relación a “S”, queda claro que el resultado anterior debería ser cero (0000) y no es ni
parecido.

Un segundo intento de codificación surge al tratar de imaginar que el odómetro o cuenta-kilómetros de


un carro está hecho con números binarios. Si tengo un vehículo nuevo, cero kilómetros, y para sacarlo
del concesionario tengo que manejarlo cuidadosamente en reversa…, al llegar afuera observaré que el
contador marcará… 999999. Si el contador estuviera en binario, comenzando en cero (0000), y yo lo
devolviera uno (-1), el resultado sería: 1111. Así que ésta puede ser una buena codificación para el
número ‐1:  1111. Retroceder uno más lo llevaría a ‐2:  1110, y por esa vía, a la siguiente tabla:
“Números representados en Complemento a 2” (2’s complement):

C3-173
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Números    Números  Números sin 


Positivos  Negativos  Signo 
+0  0000        15  1111 
+1  0001    ‐1  1111  14  1110 
+2  0010    ‐2  1110  13  1101 
+3  0011    ‐3  1101  12  1100 
+4  0100    ‐4  1100  11  1011 
+5  0101    ‐5  1011  10  1010 
+6  0110    ‐6  1010  9  1001 
+7  0111    ‐7  1001  8  1000 
      ‐8  1000  7  0111 
6  0110 
5  0101 
4  0100 
La tabla de Números sin Signo, con resolución de cuatro bits, está ordenada al 3  0011 
2  0010 
revés de las otras dos, de abajo hacia arriba. Se ve que si se quiere retroceder el 1  0001 
odómetro un paso a partir del cero (bajar un escalón, desde el 0000), el valor 0  0000 
resultante será 1111, como si la tabla fuera circular y el fondo y el techo se
tocaran; fueran vecinos. En un odómetro ocurre así: cuando se llega al
máximo kilometraje el contador “da la vuelta” y llega a cero. Al ir al contrario, el contador también da la
vuelta, al tratar de ir debajo del cero, colocándose en el techo.

Si quisiéramos sumar, como antes, +2 con -2 representados en este nuevo código, aplicando las
anteriores reglas básicas de la suma, el resultado sería: 0010 + 1110 = S000. Bastante conveniente sería
si el signo resultante “S” fuera 0, lo que se lograría si también sumáramos los signos: 

0010 + 1110 (+ 1000: carry) = 0000.

Esto NO tiene sentido en nuestra representación decimal, pero en esta representación binaria, y
asumiendo que los valores de los bits, 0 y 1 fueran numéricos, aun cuando representen los signos… el
resultado queda de maravilla. Observe que hay un acarreo (carry) desde la última posición hacia la
izquierda; éste se descarta. Todas estas normas van completando las reglas de la adición, en este
representación numérica, que se conoce como “complemento a 2”, o “2’s complement”.

Tres características son destacables: hay un solo cero (otras representaciones tienen DOS códigos para
referirse al mismo cero), el código no es simétrico: abarca desde ‐(2^n) hasta (2^n)‐1 (en este ejemplo,
desde ‐8 hasta +7), y hay dos (2) números que son sus propios negativos: el cero y el -8:

‐0 = 0;  ‐8 = ‐8.
Para obtener -N (bien sea N positivo o negativo), hay varios métodos: a) se niega el número (cambiar
ceros por unos y viceversa) y al resultado se le suma 1; b) se resta de una fila llena de unos y al resultado
se le suma 1; y c) se va componiendo la respuesta copiando desde N los bits de derecha a izquierda,
hasta que copia el primer uno; de ahí en adelante los bits se copian negados.

Ejemplo: obtener -(-3): a) ‐(1101) = 0010 + 1 = 0011 (3)


b) 1111 – 1101 = 0010, +1 = 0011 (observe que restar un número de 1111, es lo mismo que negarlo)
c) ‐(1101) = 0011.

C3-174
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

 EJERCICIOS
MOTIVACIÓN
Los estudiantes suelen quejarse de que la literatura que introduce el tema de Circuitos o Electrónica
Digital ofrece problemas muy simples, divorciados de las aplicaciones reales, y omiten establecer con
claridad una metodología de solución de problemas de cierta magnitud. Por eso se incluye el
planteamiento de los siguientes problemas.

Lo primero que hay que hacer en cada ejercicio de Circuitos Digitales es un Programa en lenguaje C, en
el que las entradas se simulan leyendo el teclado (getchar), y las salidas mediante impresiones en la
pantalla del PC (putchar; printf). Esto se debe, en primer lugar, a que los alumnos han de saber
programar como requisito de estas asignaturas; en segundo término, porque un programa es la manera
idónea de formular una solución (algoritmo), y no hay mejor simulación que hacerlo correr. En tercer
lugar, si se codifica con especial atención puede ejecutarse directamente en un microcontrolador, que
son los dispositivos que se utilizarán el 99.99100% de las veces en la vida real para resolver los
problemas, pues esta es la era de los dispositivos electrónicos programables. Y, por último, si no
pudiera, por algún motivo, implantarse el programa directamente desde C, siempre es un paso
importantísimo para su codificación en el Assembler propio de cada microcontrolador.

Otros lenguajes aplican también, en especial Java, C++, Basic, Visual Basic (cfr. ejercicio de Ping-Pong
más adelante)

Nota: Observe con detenimiento los ejercicios combinatorios 3, 4, 5 y 6: Son el mismo problema con diferente
fraseo.

REDES COMBINATORIAS

1) ALARMA PARA LAS CÁPSULAS APOLO

A) PRIMERA El sistema de alimentación eléctrica de las naves Apolo


PROPOSICIÓN es tan crítico, que recibe suministro redundante de Cápsula
APOLO

energía DC, de tres (3) fuentes de alimentación


independientes; cada una se conecta a través de un diodo para
evitar que un eventual daño (por ejemplo, un corto circuito a la
salida de una fuente) afecte a las demás.

El sistema cumple muy bien su trabajo suministrando fluido


eléctrico confiable en forma continua, pero tiene el inconveniente
de que, precisamente porque todo opera con normalidad, incluso
cuando fallan uno o dos dispositivos externos, los astronautas podrían no enterarse de cuándo están en
situación de riesgo. Por eso hay que diseñar un sistema visual y audible que les indique el estado de
funcionamiento de las tres baterías solares, de la siguiente forma: Se instalarán a la salida de cada batería
(antes del diodo) unos sensores en paralelo, que pueden ser, por ejemplo, relés o dispositivos
electrónico apropiados (CR en la siguiente figura), que suministren un “1” lógico cuando se encuentren

C3-175
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

en operación normal y “0” si el voltaje ha disminuido por debajo de un cierto límite preestablecido y
prudencial.

Habrá una señal verde (V) que, de estar encendida, indicará que las
tres baterías se encuentran operando correctamente; una luz
amarilla (Am) se alumbrará cuando una y sólo una de las baterías CR
Cápsula
APOLO

haya salido de funcionamiento (el amarillo indica precaución: Ha


habido un defecto que obligará a los astronautas a desconectar
aquella parte del equipo no indispensable, pero el viaje puede CR

continuar); por último, estará el indicativo rojo (R) que encenderá


cuando dos baterías cualesquiera, o las tres (?), se hayan dañado (el
roja es señal de peligro: Es menester economizar energía al máximo
CR

y utilizar los acumuladores auxiliares de abordo para la maniobra de


regreso inmediato). Las situaciones de alarma amarilla y roja activarán además una sirena, para llamar la
atención de los tripulantes, que tienen que mirar el tablero para ver qué ha ocurrido. El indicador verde
no va acompañado de sonidos. Diseñar el sistema lógico (compuertas, contactos, relés, switches; no
incluya por ahora otros circuitos electrónicos o de potencia necesarios, y que sí van en la vida real...)

B) Este ejercicio es, además, ejemplo de cómo van evolucionando los requerimientos de los
MANTENIMIENTO clientes..., que nunca piensan en todos los escenarios la primera vez, y obligan luego al
departamento de Ingeniería a hacer rediseños (parches) en forma permanente... Pero el
cliente y los empleados son el capital más importante que una empresa puede tener, y el más volátil
también.

El circuito que usted diseñó en el paso anterior ¡ funcionó a la perfección ! pero cuando los
astronautas tenían que retirar una fuente de alimentación solar para hacerle Mantenimiento Preventivo
(PM) de rutina (limpieza, verificación de su estado de operatividad, medición de los voltajes generados y
demás parámetros de diseño) se producía una alarma de Alerta Amarilla enloquecedora. Se decidió que
cuando fuera a trabajarse en el equipo se desactivaría la corneta por completo, agregando una llave (K)
que el astronauta debía insertar y girar para indicarle al sistema que se estaba por comenzar el
mantenimiento. Modifique su diseño para incluir la nueva entrada y altere en concordancia el
comportamiento del circuito.

C) SOLUCIÓN Habiéndose implementado la propuesta del punto anterior ocurrió que uno de los
PEOR QUE LA astronautas olvidó retirar la llave cuando finalizó el trabajo, con tan mala suerte que al día
ENFERMEDAD siguiente se dañó una batería, y el sistema de alarmas no advirtió a la tripulación sobre el
acontecimiento... ¡ DURANTE SEMANAS ! El cliente quiere, de nuevo, que usted modifique su
diseño a fin de que si se daña una batería mientras está introducida la llave K, opere la Alarma Roja y
por esa vía, la corneta. Decida usted qué hacer en otros casos no contemplados; por ejemplo, si se
dañan dos (2) baterías cuando está insertada la llave K (¿Ulular? ¿Flashing o parpadeo?) ¿Puede eliminar
el efecto de la llave después de un tiempo prudencial?

D) Como el sistema de alimentación DC es vital, la paranoia cunde entre los astronautas y


VERIFICABILIDAD personal de tierra en relación a poder garantizar que si las alarmas no se activan, en realidad
DE SU CIRCUITO las baterías están bien, ¡ no porque se haya dañado alguna sección del circuito detector ! Por

C3-176
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

eso le piden una vez más que rediseñe el dispositivo para añadirle uno o dos botones externos que
permitan ejercitar los leds y la sirena momentáneamente (y así asegurarse de que encienden y apagan
bien los unos, y suena como corresponde la otra). Además, debe incluirse un mecanismo que permita
simular, a mano, el comportamiento de las baterías y certificar así que el circuito opera
satisfactoriamente. También le piden avanzar el diseño para que si, por ejemplo, la señal Verde no está
encendida (indicando que una o más fuentes de alimentación se encuentran fuera de servicio), y
tampoco se enciende la amarilla, se active inmediatamente la roja, con independencia de ninguna otra
circunstancia.

NOTA: Es ideal que durante la etapa de análisis del problema, que antecede al diseño, se establezcan con
la mayor exactitud todos los posibles escenarios, a fin de producir el diseño definitivo con el menor
número de iteraciones. Sin embargo, para hacer su trabajo, ¡ es preferible descomponerlo todo otra
vez en partes ! Imagine cómo podría diseñar este sistema considerando todas las entradas y salidas a la
vez... (Baterías B1, B2, B3, K, Lamp-On, Lamp-Off, Sirena-On, Dummy para batería D1, D2, D3,
Botón de TEST...): ¡ A mano, sería prácticamente IMPOSIBLE !

2) LA SOCIEDAD Y LOS ACCIONISTAS

A) Los 4 dueños de una sociedad poseen 20, 22, 27 y 31 acciones. Las decisiones se toman por
PLANTEAMENTO mayoría. Diseñe un circuito que determine si se aprueba o se deniega un acuerdo; incluya
INICIAL una luz que represente “aprobado” y otra para “denegado”. Defina las entradas y
especifique cómo debe operarlas el votante. Suministre:

 Tabla de Verdad  Implementación de d) con compuertas


 Solución con ROM AND, OR, NOT
 Implementación con “multiplexores”  Implementación de d) con compuertas
 Minimización con MK NAND
 Implementación con “decodificadores”
B) SEGURIDAD Comente si usted cree que hasta ahora hace falta o no, agregar una capacidad de “lamp
test” para verificar si el sistema de despliegue de información trabaja bien (por qué sí, o por
qué no).

C) CONFORT Dependiendo de cómo van votando los accionistas, las luces pueden pasar de “denegado”
a “aprobado” y viceversa. Estos resultados espurios exasperan bastante a los electores; para
impedir su aparición, añada una señal más: “Output Enable”, que le permita al Presidente habilitar la
salida sólo cuando la totalidad de los accionistas manifiesten que ya votaron; añada una (1) tercera luz
que muestre esa condición y se encienda cuando “todos votaron”. (¿Hará falta ahora la funcionalidad
del “lamp test”? Diga por qué sí o por qué no)

D) ALTERNATIVAS Diseñe (Tabla de Verdad, MK, compuertas nand) las siguientes dos variaciones, que
eliminan la entrada extra del Presidente (punto C), diferenciando si un accionista “no votó”
o “votó 0” (que no es lo mismo...) Active en forma automática las salidas: “aprobado”, “denegado” y
“todos votaron”, sólo cuando el total de los accionistas lo haya hecho. Variaciones: 1) cada elector
cuenta con un botón que representa sí y no, y otro para votó, o no. 2) cada socio tiene un interruptor

C3-177
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

indicativo de sí, y con otro señala no; si activa ambos debe hacérsele una advertencia local (el parpadeo
de una luz al lado de sus botones), y declarar que no ha votado. (Comente sobre incluir ahora, o no, la
funcionalidad del “lamp test” ¿Por qué sí o por qué no?)

E) CAMBIO DE La composición accionaria varía a 4 grupos de 24, 26, 24 y 26 acciones respectivamente.


ACCIONES Haga un rediseño del punto D para desplegar el hecho de que ahora puede haber
empates; incluya una nueva luz que lo indique, y evite activar las salidas de “aprobado” y
“denegado” en este caso. Agregue una luz de “aún no han votado todos” y diga ¿qué opina ahora sobre
incluir o no, el “lamp test”?

3) CONTROL AUTOMÁTICO DE VELOCIDAD

Diseñar el sistema CAV para un automóvil. El conductor tiene acceso, en el volante, a un interruptor
que manipula con el dedo pulgar; cuando quiere que su vehículo se desplace controlado
automáticamente, acelera el carro en forma convencional y al llegar a la velocidad deseada mueve el
botón de “latch” a su posición “activa” y lo deja allí. El circuito debe almacenar el valor de velocidad
que hay en ese momento, para lo cual se cuenta con un dispositivo de “Memoria” al que le entra por un
lado el número binario que corresponde a la velocidad instantánea y que, al activarse el botón de
“latch”, almacena el número que en ese preciso momento había en sus entradas (Usted puede ignorar
cómo funciona el dispositivo de memoria y emplearlo como una “caja negra” [black box]). La salida
permanente de la “Memoria” es el valor “consigna”, almacenado. El vehículo tiene un artefacto que
mide la velocidad y que consta de un pequeño engranaje en la caja de velocidades, al cual se le acopla un
cable de acero que gira a razón de un cierto número de veces por segundo, de manera proporcional a la
velocidad del carro. Se posee también un “Tacómetro Electrónico” que convierte las revoluciones de la
“guaya” en un número binario de 7 bits que indica en todo momento la velocidad a la que se desplaza el
automóvil, en Km/hora (entre 0 y 127 Km/h). De allí precisamente se toma la lectura que se almacena
en la Memoria al presionarse el “latch”.

Su sistema CAV debe producir una señal digital “A” que active automáticamente el acelerador (sin
intervención del chofer) cuando se dictamine que la velocidad se ha reducido por debajo del valor
deseado, y debe también producir una señal digital “F” que active el sistema de freno hidráulico cuando
la velocidad haya subido por encima del límite establecido. Tanto el mecanismo de aceleración como el
de frenado operan de manera suave, sin producir grandes cambios ni sobresaltos, a fin de que la travesía
sea lo más confortable posible; usted no tiene qué pensar en cómo hacer esa parte, pues ésta ya viene
incluida dentro de los controles del vehículo; basta con que su circuito active las señales de Acelerar y de
Frenar, que del resto se encargará el automóvil. Lo que sí debe incluir es un ciclo de histéresis que evite
pasar de Aceleración a Frenado en forma muy seguida; para esto, su sistema sólo debe acelerar cuando
la velocidad sea inferior al valor “consigna” menos 12.5%, y frenar al sobrepasarla en un 12.5%.

Para deshabilitar el Control Automático de Velocidad el conductor regresa el “latch” a su posición de


reposo, en la cual se desactivan las señales de aceleración y de frenado.

Presente 1) un Diagrama de Bloques y una descripción verbal que indique, a nivel funcional, los
diversos componentes que va a emplear en su diseño y sus interconexiones y, 2) un Diagrama Lógico

C3-178
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

para cada bloque funcional (comparadores, sumadores, etc.), con el diseño realizado con compuertas
Nand.

4) FRENAR LOS COHETES

Diseñar el “Controlador de Frenado para la Ejecución de la Maniobra de Regreso a Tierra” de cierto


vehículo espacial, que emplea para detenerse 3 motores independientes, de combustible sólido. Una vez
emprendido el reingreso, si el piloto precisa una operación lenta (V0 en la tabla):  No se activa ningún
motor si el transbordador aún está “Detenido” (0);  enciende uno (1) si su velocidad es “Lenta” o
“Normal”,  y dos (2) en caso de que venga “Sobreacelerado”. Si se necesita realizar la maniobra de
frenado más fuerte se emplea la posición V1; de nuevo:  no se enciende ningún motor (0) si el
transporte está “Detenido”;  se prende uno (1) si su velocidad es “Lenta”,  dos (2) si es “Normal”
y  tres (3) si está “Sobreacelerado”. Para V2 y V3 se indican las posibilidades en la tabla. El sistema
dispondrá de una palanca de velocidades, lineal como la de un carro automático, que usted debe incluir
en su diseño para especificar el frenado, de manera creciente, como: V0, V1, V2 y V3. También cuenta
con un sistema externo (que usted no tiene que diseñar) que mide la velocidad actual de la nave y se la
suministra a su Controlador, mediante dos (2) dígitos codificados en BCD (de 00 a 99 Km/minuto). El
vehículo se considera “Detenido” por debajo de los 39 Km/m; en movimiento “Lento” hasta 59
Km/m, y 89 Km/m son el límite de velocidad “Normal”. De 90 Km/m en adelante está
“Sobreacelerado”.

La NASA resume la operación así:

a) Apoyándose en un Diagrama en Sobreacelerado 2 3 3 3


Bloques explique un dispositivo que Normal 1 2 3 3
materialice su diseño, identificando Lento 1 1 2 3
 las señales de entrada que ha Detenido 0 0 0 0
planeado emplear y  cómo serán V0 V1 V2 V3
físicamente ( si son switches, de Los números indican cuántos motores deben encenderse
para cada condición. Usted debe decidir cuáles.
qué clase; si necesitan resistencias de
pull-up o pull-down;  si son señales
lógicas)  Debe dividir el problema en tres (3) etapas por lo menos, a fin de hacerlo manejable, y
explicar en detalle su criterio para esa separación.  En particular debe indicar:  de dónde obtiene
todas las entradas para cada etapa;  cómo las codifica;  de qué manera produce los resultados; 
cuáles salidas de una sección sirven de entradas a las siguientes, etc. (AYUDA: Los motores SON
salidas: ¡ Usted va a controlarlos !)

b) Además de la función principal de su controlador (manejar el reingreso a tierra) está la de


Supervisión; añada despliegues (Leds) que indiquen:  el rango de velocidad en que se encuentra la
nave (una luz para cada uno: De Detenido a Sobreacelerado);  qué comando ha seleccionado el
operador (de V0 a V3);  una luz intermitente y una alarma audible si está “Sobreacelerado”. Suponga
que los actuadores que necesita operan con señales TTL.

C3-179
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

c) Diseñe cada bloque de su diagrama y construya Diagramas Lógicos (compuertas, exors, etc.) Las
secciones que pueda elaborar empleando circuitos integrados (CI) estándar serán mucho mejor
evaluadas que si las tiene que construir usted mismo. Emplee la mayor integración que pueda (LSI, MSI,
SSI); es decir, si necesita, por ejemplo, circuitos sumadores, es preferible usar “full adders” en lugar de
hacerlos con compuertas o Exors, y así para cualquier otra función que haya incluido, como
decodificadores, normales y de prioridad, etc. NO tiene que identificar los chips con su número (ej.:
7400), pero las funciones empleadas TIENEN que existir en el mercado. No puede inventarse chips...
Si no las conoce mejor diseñarlas a su medida.

5) MONTACARGAS

Se trata de diseñar un dispositivo para supervisar y controlar un montacargas de émbolo hidráulico que
se desplaza hasta una altura de 12 m. Cuando la carga está ya lista en la plataforma, abajo, el operario
oprime el botón de Subir, que inicia el movimiento suave de la plataforma arrancando una (1) bomba
hidráulica (B1) que inyecta aceite al pistón, hasta que se alcanza el primer sensor de posición (S1), que
produce un “1” cuando el pistón pasa por ahí; esto hace que se encienda la segunda bomba (B2) para
obtener la máxima fuerza de ascensión; el operador puede soltar ahora, a discreción, el botón de Subir,
y el montacargas continuará su rápida elevación. El siguiente sensor (S2), a 11 m. del piso, hace que se
detenga la primera bomba (B1) para desacelerar el movimiento; el sensor de “Fin_de_Carrera” (FdC) se
encuentra en el punto preciso para detener TODO el movimiento. Las dos (2) bombas hidráulicas, que
hay que controlar, se activan, para fortuna suya, con solo suministrarles un “1”. Deben encenderse
cinco (5) LEDs: “LSubir”, mientras la plataforma esté ascendiendo; “LB1” y “LB2”, en tanto que
estén siendo energizadas las respectivas bombas B1 y B2; “LDetenidoAbajo” mientras la plataforma se
encuentra abajo en reposo; y “LDetenidoArriba”, cuando la plataforma active el “Fin_de_Carrera”
(FdC) (usted debe indicar, con toda precisión, cómo intenta manejar los LEDs)

El LED de “LDetenidoArriba” debe parpadear con período de 0.6 segundos (0.4 s on, 0.2 s off)
Ninguna bomba encenderá, bajo ninguna circunstancia, si está activo el interruptor FdC de
“Fin_de_Carrera” (quiere decir que ningún punto ES condición de indiferencia, si FdC vale 1).
Ninguna bomba encenderá hasta que no hayan pasado al menos 10 minutos desde que se la
apagó.
Resuelva el ejercicio sólo para hacer subir la plataforma; no se preocupe luego de cómo hacerla bajar; su
problema comienza abajo y termina arriba.

6) CALDERA

Diseñe un dispositivo con compuertas TTL (Ojo: “NO” son CMOS), que supervise y controle una
caldera para producir el vapor que mueve un generador eléctrico de 400 Kva. Se poseen 3 grupos
independientes de quemadores de gasoil. Si se desea una operación lenta, el operador enciende sólo el
primer grupo, y va agregándole el segundo y el tercero si ve que necesita acelerar el calentamiento de la
caldera. El sistema calefactor dispondrá de comandos (switches) que usted debe incluir en su diseño
para efectuar las operaciones: Apagada, Moderada, Acelerada y Ultra acelerada. También se cuenta con
un sistema que mide la temperatura de la caldera y la suministra, para suerte suya, en 3 dígitos
codificados en BCD (000 a 999 ºC). La caldera se considera “Fría” por debajo de 300 ºC; luego, “Tibia”

C3-180
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

hasta 599 ºC, y después, “Caliente” hasta 899 ºC. De los 900 ºC hacia arriba es “Sobrecalentada”, lo que
constituye una situación de riesgo que usted debe considerar y apagar inmediatamente TODOS los
quemadores, SIN QUE NINGUNA OTRA CONDICIÓN SE INTERPONGA. [Produzca estas
señales con comparadores, desde el termómetro BCD]
El cliente sumariza la operación así:

Sobreca‐ 0  0  0  0  a) Explique con LUJO DE DETALLES, apoyándose en un Diagrama


lentada  en Bloques, un dispositivo que materialice su diseño, incluyendo cuáles
Caliente  0  1  2  3 
son las señales de entrada que ha planeado emplear y cómo serán
Tibia  0  2  3  3 
Fría  0  3  3  3 
físicamente (switches, de qué clase; señales lógicas). Debe dividir el
  Apa‐  Mode‐  Acele‐  Ultra‐  problema en etapas, a fin de hacerlo manejable, y explicar en detalle su
gada  rada  rada  Acel.  criterio para escoger dichas etapas. Además de la función principal de su
Los números indican cuántos quemadores  controlador (manejar el calentamiento de la caldera) está la de
deben encenderse para cada condición.  Supervisión; añada despliegues que indiquen: –el rango de temperatura
en que se encuentra la caldera (cuatro luces, una para cada rango); qué
comando ha seleccionado el operador; una luz intermitente y una
alarma audible si se ha llegado al estado de Sobrecalentada. En todos los
casos suponga que los actuadores que necesite operan con señales
compatibles con TTL.
b) Diseñe cada bloque de su diagrama y construya un Diagrama Lógico
(compuertas, exors, etc.) Use al máximo circuitos integrados estándar. Si
necesita por ejemplo, sumadores, use chips sumadores en vez de
hacerlos con compuertas o Exors, y así para cualesquiera otras funciones.

7) CALCULADORA BRAILLE

Se está preparando una calculadora para personas ciegas, en la que cada número debe representarse
mediante un dispositivo de salida, consistente en un pequeño recuadro con 6 micro-solenoides (ver
figura), que cuando se activan o energizan hacen que sobresalga levemente un pequeño punzón,
conformando dinámicamente las marcas que codifican información en código braille. Diseñar el
dispositivo con circuitos AND, OR y NOT, sólo para la posición numérica de las unidades (las decenas,
centenas, etc. serán circuitos similares, agregados a la izquierda de las unidades), de acuerdo a la
codificación de los números en Braille, indicada en la figura. Las entradas se representan en forma
Binaria Natural, del 0 al 9, identificándose los bits de entrada como I3, I2, I1, I0. Los mapas y las tablas
debe hacerlas conservando este mismo orden. Las salidas se identifican de la “a” a la “f” (ver figura).

Out ID 1 2 3 4 5 6 7 8 9 0
a b ● ∙  ● ∙  ● ●  ● ●  ● ∙  ● ●  ● ●  ● ∙  ∙ ●  ∙ ● 
c d ∙ ∙  ● ∙  ∙ ∙  ∙ ●  ∙ ●  ● ∙  ● ●  ● ●  ● ∙  ● ● 
e f ∙ ∙ ∙ ∙ ∙ ∙ ∙ ∙ ∙ ∙ ∙ ∙ ∙ ∙ ∙ ∙ ∙ ∙ ∙ ∙

C3-181
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

REDES SECUENCIALES
1) JUEGO DE PING-PONG (BASIC) [SOLUCIÓN]
Este entretenimiento se presenta a vía de ejemplo reducido, pues sólo usa 4 Leds, en vez de los 12
propuestos en el laboratorio, y gana el primero que llegue a 5 puntos. La idea es hacer notar que el
lenguaje es sencillo; no se necesita más si lo que se desea es realizar una implementación con
compuertas y flip-flops, y tiene la ventaja de ser “interpretado”, lo que significa que pueden hacerse
cambios y verificarlos sin pasar por el proceso de compilarlo. Para jugar se necesita el “QBASIC.EXE”,
que puede encontrarse en el web, o algún otro interpretador de Basic como Powerbasic.

Obsérvese que cada instrucción numerada corresponde a un estado de la FSM (Finite State Machine), y
que si se ha planeado implementarla con un flip-flop por estado, la correspondencia entre instrucciones
numeradas y biestables es uno a uno (UN FLIP-FLOP de control por cada instrucción numerada)

El juego de Ping-Pong digital, estará conformado por dos secciones: Una de Simulación del juego y una
de Anotación.

Simulación del Esta etapa estará compuesta por:


Juego
12 emisores luminosos (LED) que simularán el recorrido de la pelota.
 2 pulsadores que simularán los jugadores.

Anotación Se conformará esta etapa por un conjunto de 2 elementos luminosos de 7 segmentos, uno
para cada jugador, para la presentación del conteo de los puntos obtenidos durante el
juego.

Reglas del Juego Cada jugador debe retornar la pelota cuando se encienda el primer led correspondiente
a su zona, de lo contrario el jugador contrario anotará un punto.
El inicio del juego no deberá estar asignado a un jugador específico, es decir, se debe poder iniciar
un juego en cualquier lado de la cancha.
Ganará un juego el primer jugador que marque 5 puntos, a no ser que ambos jugadores marquen
4 puntos; en este caso ganará el juego el primer jugador que posteriormente marque dos puntos
más que el jugador contrario.

C3-182
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

'PingPong.bas; Luis G. Uribe C., D15J3 V20J3 L23J3  80  L3 = 1: INPUT "P1‐Responde ", P1 
'Para jugar: "QBASIC.EXE pinpon2b.bas" y Run‐Start      IF P1 = 1 THEN GOTO 110  
'..(en el Menú)  90  L2 = 1: INPUT "P1‐Responde ", P1 
'Juego REDUCIDO: Usa sólo 4 Leds, y gana el primero      IF P1 = 1 THEN GOTO 110  
'..que llegue a 5  100 L1 = 1: INPUT "P1:Responde: ", P1 
'C/Instrucción numerada es UN FLIP‐FLOP de control      IF P1 <> 1 THEN GOTO 110 ELSE GOTO 30 : 'P2Responde 
'‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐  '‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ Ruptura de Secuencia 
   
'Init. Se llega aquí sólo por "pup": Power Up signal.  110 'P1ERR 
   C1 = 0: C2 = 0:   'Init. asíncronamente los contadores      PRINT "P1ERR"   : 'This instruction ONLY for Simulation 
      C2 = C2 + 1: 'Inc Count2 
10  'SLoop:             'Aquí comienzan los pulsos de reloj  120 IF C2 = 5 THEN GOTO 180 : 'GOTO C2Win 
    INPUT "P1‐10 ", P1   
    IF P1 = 1 THEN GOTO 30 : 'P1‐Saca  130 'P1toPlay 
      INPUT "P1‐Saca  ", P1 
20  INPUT "P2‐10 ", P2      IF P1 = 1 THEN GOTO 30 ELSE GOTO 130 
    IF P2 = 1 THEN GOTO 70 : 'P2‐Saca  '‐‐‐30: P2Responde; else P1toPlay (130) 
    GOTO 10 : 'GOTO SLoop  '‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ Ruptura de Secuencia 
'‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ Ruptura de Secuencia   
  140 'P2ERR 
30  'P1‐Saca, 'P2Responde      PRINT "P2ERR"   : 'This instruction ONLY for Simulation 
    INPUT "P1‐Saca, P2Responde ", P1      C1 = C1 + 1: 'Inc Count1 
    IF P1 = 1 THEN GOTO 110 : 'P1Error; P1 must return to 0  150 IF C1 = 5 THEN GOTO 170 : 'GOTO C1Win 
    L1 = 1: INPUT "P2‐Responde ", P2   
    IF P2=1 THEN GOTO 140 :  'P2ERR  160 'P2toPlay 
40  L2 = 1: INPUT "P2‐Responde ", P2: IF P2=1 THEN GOTO 140       INPUT "P2‐Saca ", P2 
50  L3 = 1: INPUT "P2‐Responde ", P2: IF P2=1 THEN GOTO 140       IF P2 = 1 THEN GOTO 70 ELSE GOTO 160 
60  L4 = 1: INPUT "P2:Responde: ",P2  '‐‐‐70: P1Responde; else P2toPlay (160) 
    IF P2<>1 THEN GOTO 140 ELSE GOTO 70 : 'P1Respond  '‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ Ruptura de Secuencia 
'‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ Ruptura de Secuencia (No necesaria...)   
  170 PRINT "C1Win": 'C1Win 
70  'P2‐Saca, 'P1Responde  '‐‐‐Equivalente al FLASHING del resultado 
    INPUT "P2‐Saca, P1Responde ", P2      END 
    IF P2 = 1 THEN GOTO 140   
'‐‐‐   140 es P2Error; P2 must return to 0  180 PRINT "C2Win": 'C2Win 
    L4 = 1: INPUT "P1‐Responde ", P1  '‐‐‐Equivalente al FLASHING del resultado 
    IF P1 = 1 THEN GOTO 110 :  'P1ERR      END
 

C3-183
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

2) CERRADURA DE COMBINACIÓN
Se posee un teclado de 10 botones individuales de reposición (push-buttons abierto/cerrado, SPST
[Single Pole Single Through]), numerados del 0 al 9 y colocados en fila sobre una botonera. Diseñe con ella
una llave electrónica que, si se sigue cierta secuencia de N valores, accionará durante 2 segundos una
válvula solenoide que abre la cerradura. Activar más de una tecla al tiempo inhabilita el sistema por una
(1) hora. Su programa debe detectar cuándo se ha oprimido un botón y eliminar rebotes; en ningún caso
debe su sistema dar ni indicios que sirvan para adivinar la clave. Dos segundos es el tiempo máximo que
separa las entradas; si no se cumple con él, su circuito deshabilitará el sistema durante 5 minutos. El
usuario podrá reiniciar (Reset) el equipo si queda inhabilitado, tocando consecutivamente las teclas 0, 9,
1, 8, 2, 7, 3, 6, 4, 5 (visualice bien la secuencia, sobre la botonera, y verá que es fácil de recordar). Una
vez hecho el programa, definir una nueva clave sólo deberá requerir del usuario, la introducción de una
tabla tipo “DT” en su PIC 16F84A, con la secuencia de números que la conforman, ¡ y nada más !
(Cambiar una tabla con constantes en el Freescale). La determinación de la cantidad N, etc., debe
hacerla automáticamente su programa (se sugiere que cuente cuántos elementos hay en la tabla, sin que
el usuario tenga que hacerlo; para eso está el microcontrolador). Defina usted el tamaño máximo de la
secuencia, que no será menor a 10 números, y la longitud mínima, que deberá ser superior a 4 dígitos.

3) UN ASCENSOR INTERESANTE

Un elevador cuya puerta permite sólo el paso de una persona tiene un sensor que genera un pulso
muy estrecho cada vez que el peso aumenta (10 Kg. o más), y un sistema óptico en la entrada, que
genera una señal que se activa mientras alguien intercepta la luz, al pasar por la puerta. Diseñe
(diagrama lógico COMPLETO) un circuito que permita determinar el número de personas que
hay dentro del ascensor, de manera que si éste es superior a 7 no arranque, y genere una señal de
“exceso de personas y/o peso”. Además, debe producir una salida que pueda luego emplearse para
impedir que la puerta se cierre, antes de 10 segundos después que pasó el último usuario.

Recuerde: a) Garantizar que su circuito leerá las señales externas aunque éstas sean muy estrechas en
relación al propio pulso de reloj de usted, y b) Sincronizar TODAS las entradas externas para que su
circuito sea absolutamente sincrónico. Asegúrese de incluir en su diseño el diagrama de estados y el
período de su señal de reloj. c) Genere su estado inicial de la manera correcta. d) Indique cómo es su
circuito de “power-on reset”, e incluya todas aquellas cosas que además crea convenientes para el
esclarecimiento de su diseño.

4) REPRESENTACIÓN NUMÉRICA

Diseñe un circuito Secuencial Sincrónico, con una línea de entrada serial, I(t), por donde viene un flujo
de bits que representa Información numérica codificada en complemento a 2, de longitud indeterminada,
comenzando por el bit menos significativo (LSB: las unidades). Hay una segunda señal de entrada, C
(Complemente), que opera así:  Un cambio, o transición en C, señala que en la entrada I(t) acaba de
aparecer el bit de las unidades de un nuevo número.  El valor que toma C hace que la salida sea
así:  Mientras C == 0, Z(t) = I(t);  Mientras C == 1, Z(t) = Complemento a 2 de I(t).
Haga el Diagrama de Estados (Mealy); verifíquelo mediante el número 1000 (entra como: 0,0,0,1: primero
las unidades); tanto para C=0 como para C=1. (Autoevaluación). Obtenga Z(t) y ecuaciones de Control de los
flipflops tipo D. Repita, asumiendo que la información está representada en complemento a 1.

C3-184
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

5) DADO ELECTRÓNICO

Programe en Assembler el PIC 16F84A, con cristal de 4 MHz, para que funcione como
un Dado Electrónico que genere a máxima velocidad números entre 1 y 15 cuando se
active el pulsador de PLAY, hasta que se detenga obedeciendo el de STOP, y muestre al
exterior la información obtenida al pararse. La secuencia debe ser “pseudoaleatoria”,
empleando un registro de desplazamiento de cuatro bits con las siguientes ecuaciones para flip-
flops tipo D: D0  =  Q1;  D1 = Q2;  D2  =  Q3;  D3  =  Q0*~Q1  +  ~Q0*Q1; Su programa debe
mimetizar apropiadamente ese método.

Incluya la “eliminación de rebotes” por software (delay de 20 ms), empleando alguna librería de
retardos apropiada y conocida (que no tiene que programar, pero sí indicar cómo se usa).

El único hardware externo será: un display de 7-segmentos y Cátodo común (encienden con un “1”),
con resistencias R (no tiene que calcularlas) apropiadas para que la corriente de cada rama sea de 20 mA, y
un Led adicional, también a 20 mA, que servirá para indicar las decenas (apagado representa el cero
de las decenas del resultado; encendido representa el uno).

¿Alguna razón importante para tener que manejar el Led adicional usando “0” para encenderlo?

No voy a resolverlo aquí, pero sí quiero llamar la atención en varios puntos. En primer lugar, si se mira
bien verá que no se necesita el interruptor de PLAY; el micro puede estar siempre contando, sin
visualizar la secuencia, y cuando se oprime STOP se expone el resultado. Al liberar STOP el micro
continúa con su conteo aleatorio. Si el cliente insistiera en tener dos botones, puede ponerse uno de
ellos de adorno; la operación será tal como se especificó, pero ese interruptor no se necesita.

En segundo lugar, para no violar las especificaciones técnicas de Microchip, no se puede sacar más de
20 mA por cada salida en nivel alto por el PORTA, ni absorber más de 25 mA en nivel bajo. Pero el
total de PORTA es de 50 mA en alto y 80 mA en bajo. En PORTB la situación es que no se puede
sacar más de 20 mA por cada salida en nivel alto, ni absorber más de 25 mA en nivel bajo, y el total de
PORTB es de 100 mA en alto y 150 mA en bajo. Como los 7-Segmentos son de cátodo común, para
encender cada LED hay que colocar un “1”; a 20 mA por LED y 100 mA en total, no pueden
conectarse más de cinco (5) salidas en PORTB. Las otras dos (2) irán por el PORTA, el cual queda bien,
ya que 20 mA en alto y 50 mA en total corresponden bien a los dos (2) LED restantes. Ambos puertos
quedan completos desde el punto de vista del suministro de corriente (manejando el 7-Segmentos en
alto). Falta un (1) LED: el de las decenas. No puede conectarse para ser manejado en alto en ninguno de
los dos puertos disponibles, así que por eso es necesario manejarlo para que encienda con “0” (Esa es la
razón importante para tener que manejar el Led adicional con “0” para encenderlo). Ahora quedan por
manejar los dos interruptores; que ojalá fuera uno (STOP). Pueden colocarse los dos en cualquier
puerto, o uno en PORTA y el otro en PORTB. Lo importante con los interruptores es colocarlos para
que al oprimirse activen un camino a tierra, a través de una resistencia de “pull-up” de alto valor. Con 40
KOhms, la corriente por cada interruptor será de 0.1 mA, lo cual está muy bien.

C3-185
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

 BIBLIOGRAFÍA
APPLICATION NOTE 287, Switch Bounce and Other Dirty Little Secrets:
http://www.maxim-ic.com/legal

A Guide to Debouncing, April, 2006, Jack G. Ganssle


Por suscripción, a jack@ganssle.com

C3-186
4
Capítulo
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

PROGRAMACIÓN GENERAL
Todo el mundo debería aprender a programar computadoras; hoy es una necesidad
equivalente a saber leer y escribir.

 INTRODUCCIÓN

E
L tema de la programación se reserva, no un capítulo ni un libro; abarca toda una profesión y
hasta la vida entera. Es una actividad profundamente gratificadora, ampliamente creativa y una
forma sin parangón de materializar ideas. Yo creo que programar es una manera de Arte. A
diferencia de mis hijos, mi primera experiencia en programación fue tardía, en mis cursos de
Fortran de la universidad, pero el pináculo del éxtasis y del deleite lo alcancé al realizar el CODIDAC,
primer COmputador DIgital colombiano, y probablemente también de Latinoamérica, diseñado y
construido con propósitos diDÁCticos entre 1969 y 1971 en la Universidad Javeriana de Bogotá. Nunca
antes fue tan palpable para mí, como entonces –y tan sobrecogedora– la sensación de presenciar la
concreción del curso del pensamiento. Fue embelesante y arrobador ver cómo casi discurría aquel
artefacto, de materia moldeada con nuestras manos; cómo tomaba decisiones, ejecutaba operaciones,
hablaba, escribía, leía y reaccionaba... tanto el hardware, primero, como los programas y juegos que para
él desarrollé después.

En este capítulo se pretende mostrar temas interesantes y útiles, rara vez encontrados en libros
especializados en el tema, y que aplican tanto a la programación de sistemas a nivel de estaciones de
trabajo y servidores, como también a los dispositivos hechos con microcontroladores “embebidos”.

 DÍGITOS DE VERIFICACIÓN
Sobre el tema genérico de la detección y corrección de errores y los programas asociados se encuentra
bastante información: Manejo de bits de paridad, cálculos de códigos LRC (tipo “check-sum”);
evaluación de polinomios CRC, bit a bit y mediante tablas; código Hamming para un bit y para ráfagas
de errores... El Internet y las telecomunicaciones abundan en este tema.

Existe, sin embargo, para aplicaciones que deben operar con códigos introducidos a mano por el
usuario o por un operador, la necesidad de tomar medidas para asegurar que no se trastocan los dígito,
o se omite alguna cifra, lo que pudiera generar otro identificador, también válido, pero indeseado.

C4-187
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Cuando las personas usan códigos numéricos como los que identifican cuentas bancarias, tarjetas de
crédito, artículos de una tienda por departamentos, etc., bien sea que se dactilen en un teclado de
computadora o en algún cajero automático, se digiten empleando el teléfono, o se los lea en voz alta
para los demás, existe la tendencia a cometer ciertos errores con mucha más frecuencia que otros.

De acuerdo a Hamming, padre de los códigos de detección y corrección de errores, las anomalías más
comunes que comenten las personas en estas circunstancias son el intercambio de dos dígitos
adyacentes de un número (por ejemplo, el 67 se escribe como 76) y doblar el dígito equivocado de un
trío (el 667 se convierte en 677)

Verhoeff profundizó aún más en el tema, con los siguientes resultados:

 Errores sencillos: a se convierte en b (60% a 95% de todos los errores)


 Omitir o añadir un dígito (10% a 20%; corregible en códigos de longitud fija)
 Transposiciones adyacentes: ab se torna en ba (10% a 20%)
 Errores gemelos: aa se troca en bb (0.5% a 1.5%)
 Transposiciones de salto: acb se vuelve bca (0.5% a 1.5%)
 Errores gemelos de salto: aca se cambia por bcb (menos del 1%)
 Errores fonéticos (en inglés): a0 se escucha como 1a (por ejemplo, thirty y thirteen pueden
confundirse; 0.5% a 1.5%)

En forma similar al CRC o LRC, se le añade a esta clase de códigos un dígito de verificación (check
digit) con el propósito de detectar tales errores. No se emplean CRCs, a pesar de ser más robustos,
porque éstos generan demasiados dígitos y los usuarios detestan oprimir tantas teclas.

Hay una variedad considerable de algoritmos para la generación del dígito de verificación, cada uno con
fortalezas y debilidades; entre los más destacados están:

 IBM check (módulo 9) usado en la mayoría de las tarjetas de crédito (visa, mastercard, etc.)
 ISBN módulo 11, que forma parte de los códigos de identificación de libros (International
Standard Book Number)
 Electronic Funds Transfer Routing Number check, que se emplea aplicado a los códigos con
que se transfieren depósitos electrónicos entre bancos (ABA: American Bank Association)
 UPC check, para productos identificados con códigos de barras (Universal Product Code)
 Dual Mod 10
 Arithmetic Mod 10
 Arithmetic Mod 11
 Geometric Mod 11
 Geometric Mod 10
 Verhoeff’s dihedral group D5

Los diversos “módulos” mencionados arriba implican que como parte del algoritmo se realiza una
división (por 9, 10 u 11, en los ejemplos mencionados) y se toma el residuo. Hay que observar que si la
división es por 11, los posibles residuos van del 0 al 10, sobrepasándose en uno (1) la cantidad de dígitos

C4-188
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

decimales (0-9), por lo que códigos como el ISBN emplean en este caso un décimo símbolo, una “X”,
lo que resulta incómodo de manipular en teclados numéricos convencionales, como los telefónicos.

Sobre las clasificaciones mencionadas se consiguen algoritmos y programas con profusión; sin embargo,
el método más completo es el de Verhoeff, que detecta:

 todas las oportunidades en que se  más del 95% de los “twin errors jump
comete un (1) solo error, transpositions and jump twin errors”
 todas las transposiciones adyacentes,  y la mayoría de los errores fonéticos en
inglés.

C4-189
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Su solución incluye la realización de multiplicaciones entre los diversos dígitos del código, considerados
como integrantes de un “dihedral group D5”, que no es conmutativa, lo que significa que a*b no es
siempre igual a b*a). La tabla de multiplicar en estas condiciones es la siguiente (hay 4 cuadrantes):

0 1 2 3 4 5 6 7 8 9

0 0 1 2 3 4 5 6 7 8 9

1 1 2 3 4 0 6 7 8 9 5

2 2 3 4 0 1 7 8 9 5 6

3 3 4 0 1 2 8 9 5 6 7

4 4 0 1 2 3 9 5 6 7 8

5 5 9 8 7 6 0 4 3 2 1

6 6 5 9 8 7 1 0 4 3 2

7 7 6 5 9 8 2 1 0 4 3

8 8 7 6 5 9 3 2 1 0 4

9 9 8 7 6 5 4 3 2 1 0

La ecuación de Verhoeff genera el dígito de verificación, y para determinar si hay error o no, se lo
incluye, y un nuevo recálculo sobre el código extendido debe dar “cero” si el ingreso es correcto
(como en el caso de algunos CRCs, que cuando se le agregan al mensaje original y se repite el
algoritmo sobre el mensaje ampliado, producen un valor global de “cero”). Obsérvese que el dígito
de verificación de Verhoeff toma la primera posición en el código; como lo usual es añadirlo al
final, la rutina que se suministra incluye funciones para reversar una y otra vez los dígitos de la cifra
original.

Ciertos errores pasan sin ser detectados por este algoritmo como, por ejemplo, la mayoría de los
“jump twin errors” que involucran dígitos con diferencias de 5, como 050 y 505, 161 y 616, 272 y
727, 494 y 949), pero sí captura, por ejemplo, el 383 y 838.

Además, para eliminar los casos en que se añade o pierde algún dígito, es recomendable emplear
códigos de tamaño fijo, que se verifican totalizando el número de cifras introducidas.

La descripción matemática del algoritmo de Verhoeff y el “dihedral group D5” sobrepasan los
alcances de esta presentación, pero sí pueden encontrarse a continuación las rutinas en C, y un
programa de prueba. Van dos listados; el primero, genérico, para uso en estaciones de trabajo o

C4-190
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

servidores, el segundo para microcontroladores embebidos, que optimiza el uso de la memoria


empaquetando dos (2) matrices en un solo arreglo de caracteres, aprovechando el hecho de
que la información que las conforman es módulo 10 (del 0 al 9); por tanto cada dígito necesita 4
bits, y caben 2 dígitos en cada byte (“char”).

Se recomienda leer antes el primer programa, que es más claro, para no abrumarse con la
presentación del segundo. Desde luego, este último puede emplearse también en estaciones de
trabajo…, no está vedado.

Los siguientes valores sirven como testigos para verificar la operatividad del programa:

 1  15049306861336613
 15  150493068613366131
 150  1504930686133661313
 1504  15049306861336613137
 15049  150493068613366131371
 150493  1504930686133661313711
 1504930  15049306861336613137119
 15049306  150493068613366131371194
 150493068  1504930686133661313711942
 1504930686  15049306861336613137119424
 15049306861  150493068613366131371194249
 150493068613  1504930686133661313711942494
 1504930686133  15049306861336613137119424949
 15049306861336  150493068613366131371194249498
 150493068613366  1504930686133661313711942494983
 1504930686133661  15049306861336613137119424949836

Por último, comenzando con 1, 2, 3..., 0, y repitiendo el ciclo hasta completar las 127 posiciones
de la línea de entrada, el código de verificación que se produce es el 6 .

C4-191
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

// ChkDigit.c, Luis G. Uribe C. M04S7  int Op[10][10] = { { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, }, 
//                     { 1, 2, 3, 4, 0, 6, 7, 8, 9, 5, }, 
//          VERHOEFF'S DIHEDRAL GROUP D5 DIGITS CHECK                     { 2, 3, 4, 0, 1, 7, 8, 9, 5, 6, }, 
//                     { 3, 4, 0, 1, 2, 8, 9, 5, 6, 7, }, 
// SUMMARY: When keying numbers (codes, amounts) people tend                     { 4, 0, 1, 2, 3, 9, 5, 6, 7, 8, }, 
// ..to make certain kinds of mistakes more often than others.                     { 5, 9, 8, 7, 6, 0, 4, 3, 2, 1, }, 
// ..J. Verhoeff (Error Detecting Decimal Codes, Mathematical                     { 6, 5, 9, 8, 7, 1, 0, 4, 3, 2, }, 
// ..Centre Tract 29, Amsterdam, 1969) categorizes:                     { 7, 6, 5, 9, 8, 2, 1, 0, 4, 3, }, 
//                     { 8, 7, 6, 5, 9, 3, 2, 1, 0, 4, }, 
// .>Single errors: a becomes b (60%‐‐95% of all errors)                     { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, }, }; 
// .>Omitting or adding a digit (10%‐‐20%) [detected counting   
// ..number of digits in fixed format codes: credit cards, etc]  /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */ 
// .>Adjacent transpositions: ab becomes ba (10%‐‐20%)  char Verhoeff ( char *line, char compute )                /*()*/ 
// .>Twin errors: aa becomes bb (0.5%‐‐1.5%)  {  char check; 
// .>Jump transpositions: acb becomes bca (0.5%‐‐1.5%)     unsigned int i; 
// .>Jump twin errors: aca becomes bcb (below 1%)     char *tmp = "0"; 
// .>Phonetic errors: a0 becomes 1a [since the two have similar   
// ..pronunciations in English: thirty & thirteen] (.5%‐‐1.5%)     strrev( line );         // strrev: reverse a string on place 
//     check = 0; 
// SOLUTION: Add ONE redundant digit. More used:     for( i = 0; i < strlen( line ); i++ ) 
// ISBN mod 11 (awkward: use 0..9 and X, difficult to key)         check=Op[ check ][ F[(i+compute)%8][line[ i ] ‐ '0'] ]; 
// IBM (used by most credit card companies)   
// Electronic Funds Transfer (ABA EFT) used between banks      strrev( line ); 
// Universal Product Code (UPC bar code; similar to IBM)     if( compute ) { 
// Verhoeff's Dihedral Group D5 (multiplication in this group is         tmp[ 0 ] = Inv[ check ] + '0'; 
// ..NOT commutative i.e., a*b is not always equal to b*a).         strcat( line, tmp ); 
// See program bellow. Consult references for further analysis.         return Inv[ check ]; 
     } 
/* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */     return check; 
// Include Files & DEFINES   
#include <stdio.h>  } 
#include <string.h>   
  /* ********************************************************** */ 
#define LINESIZE   130 // would be smaller for a ATM or similar  void main ( void )                                        /*()*/ 
  {   static char line[ LINESIZE ]; 
#define compute(l)     Verhoeff( (l), 1 )   
#define check(l)       Verhoeff( (l), 0 )     for( ;; ) { 
         fputs( "Initial Number: ", stdout ); 
/* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */         gets( line ); 
// GLOBAL VARIABLES         compute( line ); 
static         puts( line ); 
int F[8][10] =   { { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, },   
                   { 1, 5, 7, 6, 2, 8, 3, 0, 9, 4, },         fputs( "Verificar: ", stdout ); 
                   { 5, 8, 0, 3, 7, 9, 6, 1, 4, 2, },         gets( line ); 
                   { 8, 9, 1, 6, 0, 4, 3, 5, 2, 7, },         if( check( line ) == 0 )    // check()==0 mean ok 
                   { 9, 4, 5, 3, 1, 2, 6, 8, 7, 0, },             puts( "OK" ); 
                   { 4, 2, 8, 6, 5, 7, 3, 9, 0, 1, },         else                    // May use a while(check) to wait  
                   { 2, 7, 9, 3, 8, 0, 6, 4, 1, 5, },             puts( "Try again" );// ..until key in correct code! 
                   { 7, 0, 4, 6, 9, 1, 3, 2, 5, 8, }, };     } 
static  }
char Inv[10] =     { 0, 4, 3, 2, 1, 5, 6, 7, 8, 9, }; 
static 

C4-192
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

// ChkDig4.c, Luis G. Uribe C. M04S7, for embedded     char check; 
//            VERHOEFF'S DIHEDRAL GROUP D5 DIGITS CHECK     unsigned int i; 
//     char *tmp = "0"; 
// Because all numbers are module 10 (0..9), we may store BOTH   
// ..arrays, F[] and Op[], in one single char array, FOp[].     strrev( line );         // strrev: reverse a string on place 
// ..We use 3 macros to assist us: s(a,b) to store both numbers   
// ..in one byte over FOp[], F(a,b) to retrieve the F[] array     check = 0; 
// ..and Op(a,b) to retrieve the Op[] array, from FOp[].   
/* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */     for( i = 0; i < strlen( line ); i++ ) 
// Include Files & DEFINES         check=Op(check,F(((i + compute) % 8),(line[ i ] ‐ '0'))); 
#include <stdio.h>   
#include <string.h>     strrev( line ); 
#define LINESIZE   130 // would be smaller for a ATM and phones   
/* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */     if( compute ) { 
static char Verhoeff ( char *line, char compute )         /*()*/         tmp[ 0 ] = Inv[ check ] + '0'; 
{         strcat( line, tmp ); 
#define compute(b) Verhoeff( (b), 1 )  // fake routines for bet‐         return Inv[ check ]; 
#define check(b)   Verhoeff( (b), 0 )  // ..ter understanding     } 
// Ancillary Macros   
#define s(F,Op)   ((F)<<4|(Op))          // store  F,Op in Fop[]     return check; 
#define F(a,b)     (FOp[(a)][(b)]>>4)    // retrieve F  from FOp   
#define Op(a,b)   ((FOp[(a)][(b)])&0x0F) // retrieve Op from FOp  } 
   
static unsigned char Inv[10] = { 0, 4, 3, 2, 1, 5, 6, 7, 8, 9};   
   
static unsigned     // Store F at left of FOp, Op at right   
char FOp[10][10]= { s(0,0), s(1,1), s(2,2), s(3,3), s(4,4),   
                    s(5,5), s(6,6), s(7,7), s(8,8), s(9,9)},  /* ********************************************************** */ 
                  { s(1,1), s(5,2), s(7,3), s(6,4), s(2,0),  void main ( void )                                        /*()*/ 
                    s(8,6), s(3,7), s(0,8), s(9,9), s(4,5)},  { 
                  { s(5,2), s(8,3), s(0,4), s(3,0), s(7,1),     static char line[ LINESIZE ]; 
                    s(9,7), s(6,8), s(1,9), s(4,5), s(2,6)},   
                  { s(8,3), s(9,4), s(1,0), s(6,1), s(0,2),     for( ;; ) { 
                    s(4,8), s(3,9), s(5,5), s(2,6), s(7,7)},         fputs( "Initial Number: ", stdout ); 
                  { s(9,4), s(4,0), s(5,1), s(3,2), s(1,3),         gets( line ); 
                    s(2,9), s(6,5), s(8,6), s(7,7), s(0,8)},         compute( line ); 
                  { s(4,5), s(2,9), s(8,8), s(6,7), s(5,6),         puts( line ); 
                    s(7,0), s(3,4), s(9,3), s(0,2), s(1,1)},   
                  { s(2,6), s(7,5), s(9,9), s(3,8), s(8,7),         fputs( "Verificar: ", stdout ); 
                    s(0,1), s(6,0), s(4,4), s(1,3), s(5,2)},         gets( line ); 
                  { s(7,7), s(0,6), s(4,5), s(6,9), s(9,8),         if( check( line ) == 0 ) 
                    s(1,2), s(3,1), s(2,0), s(5,4), s(8,3)},             puts( "OK" ); 
                  {     8,      7,      6,      5,      9,         else 
                        3,      2,      1,      0,      4,},             puts( "Try again" ); 
                  {     9,      8,      7,      6,      5,     } 
                        4,      3,      2,      1,      0 }};  } 
 
 
 

C4-193
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

 PARECE SIMPLE
Este ejemplo lo presento porque muchos estudiantes fallan al codificar problemas similares en C:

“Escriba un programa que genere una sola vez los números del 0 al 255 inclusive, empleando
sólo variables de tipo “char”.

Se le ha enseñado al buen programador que todos los ciclos que escriba deben tener siempre, una
forma o estructura muy bien definida, siempre la misma, para evitar errores del tipo “más menos uno”
(off by one error), que hacen que los “loops” a veces ejecuten una pasada de más, o de menos. La
forma suele ser ésta:

   char i; 
   for( i = 0; i < LIMIT; i ++ ) 

Se garantiza que un “for” así siempre realizará LIMIT pasadas, con la variable de control variando de 0 a
LIMIT‐1, siempre que en el ciclo no se altere i. Por tanto se estará tentado a codificar la solución así:

   for( i = 0; i < 256; i ++ ) 

lo que –supone quien programa– cubriría precisamente el rango solicitado. Claro que 256 está por
encima de lo que puede representarse en un byte, que es un requisito… Si i ha de ser un byte, lo mejor
será escribir el for así:

   for( i = 0; i <= 255; i ++ ) 

Todo arreglado: El rango es el acordado, las variables son “char” y las constantes caben todas en
un byte…
!Equivocación!
Ese código nunca concluye; es un “loop” infinito. La razón es la siguiente: Cuando i llega a 255 la
condición i  <=  255 aún se cumple, por lo que se repite el lazo para las acciones concernientes a
i == 255 (imprimir i, por ejemplo); al llegar a la finalización del for se incrementa primero i y se regresa
a la comparación (i <= 255) a ver si se concluyó el trabajo; sin embargo, al incrementar i, ésta pasa a
valer cero, pues en variables restringidas a un byte, incrementar 255, máxima representación, lo
convierte en cero (“rollover”); cero es una cantidad válida para ese rango, y el ciclo continúa sin final.

Entonces nuestro nervioso codificador estrella (¿o estrellado?) opta por proponer el siguiente cambio:

   char i; 
   for( i = 0; i < 255; i ++ ){    printf( "i vale… /* ejemplo incompleto */ } 
   printf( "i vale… /* ejemplo incompleto */ 

Ahora sí es verdad. Cuando i vaya por 254 se entra en el loop, al final i se incrementa y vale 255;
ahora i no es menor que 255 y el ciclo termina. Como faltó una pasada, se repite el código una

C4-194
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

vez más al finalizar el “for”, lo cual no resulta bonito en extremo, pero lo principal es que
funcione. (El printf del ejemplo está incompleto; es sólo para indicar que ahí ha de ejecutarse algo
para cada valor de i).
!PEOR!
Ese ciclo hace mucho rato que está mal, porque “char” es “signed char” en la implementación
estándar ANSI del C; así que después de 127, i toma valores negativos, que siempre van a ser
inferiores a 255; el ciclo jamás termina pues i siempre resulta válida para todos los valores que asume.

Y por qué al 255 no lo trata el compilador como ‐128? En el texto de referencia por excelencia, “The C
Programming Language”, por Kernighan y Ritchie (éste último es el inventor del lenguaje...), en la Pág.
171 dice a la letra:

“The type of an integer constant depends on its form, value and suffix. If it is unsuffixed and decimal, it
has the first of these types in which its value can be represented:
int, long int, unsigned long int. 
Así que 255 se representa como esa cantidad, en el espacio reservado para un entero, y siempre será
positivo, y por tanto mayor que todos los números entre ‐128 y 127.

Hay varias alternativas de solución. Una consiste en lo siguiente:

   #include <stdio.h> 
   unsigned char i; 
 
   void main ( void ) 
   {  unsigned char i;    // ahora sí es “unsigned” 
 
      for( i = 0; i < 255; i ++ ) { 
          printf( "%3u ", i );        // note el empleo de %3u (unsigned) 
      } 
      printf( "%3u ", i ); 
   }
El “for” realiza el trabajo de 0 a 254 inclusive, al llegar a 255 termina y se ejecuta la acción, una vez más,
por fuera del ciclo (como ya dije, nada excepcionalmente hermoso, pero funcional).

Similares problemas ocurrirían si se pidiera llegar a alguna de las fronteras representadas por enteros
[uint: 65535] o enteros largos [ulong: 4.294,967.295]; el problema solo tiene que ver con la finalización
del ciclo. En el caso del “ulong” es peor, porque a veces uno puede colocar como variable de control,
una cuya representación tiene más tamaño del que se pide en el problema; por ejemplo, int para llegar a
256 y long para ir hasta 65535, pero no es fácil conseguir algo más largo que long …

Una nota aclaratoria: Algunos compiladores para sistemas embebidos toman como representación por
defecto el “unsigned char”, lo cual ocasiona toda clase de inconvenientes pues se apartan del estándar
ANSI; como ejemplo está el Codewarrior para microcontroladores Freescale (antes Motorola).

C4-195
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

 RECURSIVIDAD
Hay aproximaciones a la programación que sorprenden y, a mí, me alelan. Uno de los ejercicios clásicos
que más deslumbran se llama Las Torres de Hanoi, inventado por el matemático francés Édouard
Lucas en 1883. Se tienen tres postes y una serie de discos que reposan, de mayor a menor, en el
primero. El ejercicio consiste en ir moviendo uno a
uno los discos, hasta trasladar la pila original a la
tercera torre, la de la derecha, respetando una sola
regla: Nunca un anillo grande puede colocarse
encima de uno más pequeño.

Varias consejas adornan el juego: Dicen que algunos


monjes están en la tarea de resolver uno de estos ejercicios, con 64 discos de oro; cuando terminen
sobrevendrá el fin del mundo, pero podemos estar tranquilos porque se ha calculado que el número de
jugadas será de 2^64-1; si les lleva un segundo cada movimiento, tardarán unos 584.542 millones de
años, y se estima en la actualidad que la creación tiene como 13.700 millones de años, así que los monjes
tardarán en terminar su juego unas 43 veces más que la edad actual del universo. (Note que el problemita
de premiar al inventor del juego de Ajedrez con un granito de trigo por el primer cuadro del tablero, dos por el
segundo, y así sucesivamente, doblando siempre en cada posición la cantidad de granos del cuadro anterior, tiene la
misma respuesta numérica: 2^64-1. Si cada grano de trigo pesa 1/5 de gramo, la producción de trigo necesaria
para pagar el premio llegaría al equivalente de 460 toneladas por cada uno de los 8 mil millones de personas
que habitan la tierra, cuando en realidad la producción promedio anual de trigo en la actualidad sólo asciende a
592 millones de toneladas, por lo que habría que acopiar la producción completa de 6,232 millones de
años, a las cifras actuales, para conseguir el “puñado” de trigo que, según el rey, fue lo que le pidió aquel anónimo
genio. La mitad de la edad del universo produciendo trigo para pagarle…

Si piensan en jugar con unas 12 fichas, verán que el enfoque tradicional (ir tanteando...) no resulta tan
sencillo. Pero puede formularse el problema de una manera recursiva, y entonces verán cómo la
solución es en realidad muy simple y elegante.

La formulación recursiva es la siguiente: Para pasar N discos desde la torre a (izquierda) hasta la b
(derecha), usando la del centro, t, en forma temporal, basta con trasladar N-1 discos desde a hasta t,
ubicar el disco restante (el más grande de la pila) en b, y luego colocarle encima los N-1 discos que
estaban en t.

Para escribir un programa resulta más conveniente numerar las torres como 1, 2 y 3, en vez de
identificarlas con letras. Así, para mover discos desde la 1 hasta la 3, se usa la 2 como temporal, y en
general, para mover algo desde la torre a hasta la b (ahora a y b representan valores numéricos), se usa
la torre “6-a-b” como temporal. Si no lo ve a la primera, escriba las posibles combinaciones y verá
cómo funciona esa cifra mágica.

Este programa lo denomino Hanoi mínimo, porque luego se le pueden poner muchos adornos a fin de
que se vean discos de colores moviéndose lentamente en la pantalla. Pero la esencia del algoritmo es la
que aquí presento. Al correr, el programa irá escribiendo de dónde a donde hay que mover una ficha. A

C4-196
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

continuación del código va un ejemplo de una corrida. Si recortan unas fichas de papel y van siguiendo
los movimientos que indica el programa, podrán hacerse una idea de cómo funciona el algoritmo.

// HANOImin.C, Luis G. Uribe C.: J23M6 J08F7


// The power of recursive calling: To move n disks from tower 1 to 3, 
// .. move n‐1 disks to tower 2 (tmp), then move disk n to tower 3, 
// .. finally move the n‐1 disks from tower 2 to 3. THAT'S IT ! 
 
const int N = 3;   // define here NUMBER OF DISKS; compile and go 
 
void hanoi( int n, int a, int b );    // function prototype 
 
/* *************************************************************** */ 
void main ( void )                     /* HANOImin.C */        /*()*/ 

   hanoi( N, 1, 3 );   // MOVE n disks from tower 1 to 3. That's all 
 
}  /* main() */ 
 
/* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */ 
void hanoi ( int n, int a, int b )                             /*()*/ 

   int t;              // temporarily tower to move n‐1 disks 
 
   if( n == 1 ) {      // Got only 1 disk? It's easy! JUST MOVE IT ON 
       putchar( a + '0' );  putchar( '>' );  putchar( b + '0' ); 
       while ( getchar() == 0 );   // Press 'Enter' to continue... 
       return; 
   } 
 
   t  =  6 ‐ a ‐ b;        // Now, THIS is a magic number... 
   hanoi( n ‐ 1, a, t );   // move all n ‐ 1 disks from tower a to t 
   hanoi( 1    , a, b );   // move the remaining 1 disk from a to b 
   hanoi( n ‐ 1, t, b );   // then move the n‐1 disks from t to b !! 
 
}  /* hanoi() */ 
 
 
Para 3 fichas: 
 
1>3 1>2 3>2 1>3 2>1 2>3 1>3 (ficha de la torre 1 a la 3, de la 1 a la 2, 3 a 2, etc.) 
Observen que las reglas se siguen, y se necesitan 7 movimientos: 2^3‐1 
 
 
Para 4 fichas, 15 movimientos: 
 
1>2 1>3 2>3 1>2 3>1 3>2 1>2 1>3 2>3 2>1 3>1 2>3 1>2 1>3 2>3 

C4-197
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

 ROMANOS Y ARÁBIGOS
Este ejercicio es un abrebocas a los alardes de creatividad. Se trata de una rutina clásica de conversión de números, esta vez entre romanos y arábigos,
que funciona en ambos sentidos, tomando la información de la línea de comandos: romans n...n [1..3999] MCM...

Como siempre, hay que validar la información suministrada por el usuario, para verificar que corresponda a cifras bien formadas, tanto si son
arábigas como si son números romanos. Para validar los Arábigos basta con determinar si están dentro del rango, que hemos definido según la
usanza, como: Mayor que cero y Menor que 4000. Pero validar el número romano es complicado, porque a veces la información está compuesta por
dos y hasta tres símbolos repetidos. Pero a veces el pensamiento lineal no es la mejor solución a un problema; miremos una alternativa:
char *_id = "romans.c,  Luis G. Uribe C, J13S2007\n"   
"Conversion between Arabic and Roman numbers (both ways)\n"  #define SIZE   ( sizeof( romans ) / sizeof( roman ) ) 
"08F1991 M13S4 D20S8 .\n\n"  #define PRINT      TRUE 
"    USAGE: romans n...n [1..3999] MCM... (may be mixed)\n";  #define NO_PRINT   FALSE 
   
/* Include Files */  /* ******************************************************* */ 
  void main ( int argc, char ** argv )                   /*()*/ 
#include <ctype.h>     // isdigit()  {  /* romans.c */ 
#include <stdio.h>     // printf, puts   
#include <stdlib.h>    // exit(), atoi()     int v; 
#include <string.h>    // str*()   
     if( argc == 1 ) {   // cmnd line need 1 parameter at least 
/* Typedefs */         puts( _id ); 
         exit( 1 ); 
typedef struct {     } 
   int   order;   /* Número que rompe la secuencia   */   
   char *symbol;  /* Símbolo que define 'order'      */     while ( * ++ argv ) {   // may give several (mixed) inputs 
}  roman;         if( isdigit( ** argv ) ) {  // 0‐9 means input Arabic 
             printf( "Arabic  '%4d'\t\tis romanic: '", 
typedef enum { FALSE, TRUE } bool;                      v = atoi( * argv ) ); 
             toRoman( v, PRINT ); 
           puts( "'" ); 
/* Function Prototypes */ 
       }else {                     // else input is Roman 
int  toArabic( char * s ); 
           strupr( * argv ); 
void toRoman( int i, bool prnt ); 
           printf("Roman '%s'\tis arbic:    ", * argv ); 
 
           if((v = toArabic( *argv )) > 0) { // error if v<=0 
/* External Variables */                 printf( "'%d'\n", v ); 
             } 
char   buf[ 60 ];         } 
roman romans[] =  {      } 
       1000, "M",    900, "CM",    500, "D",     400, "CD",      exit( 0 ); 
        100, "C",     90, "XC",     50, "L",      40, "XL",   
         10, "X",      9, "IX",      5, "V",       4, "IV",  }  /* main() */ 
          1, "I"   
       }; 
void toRoman ( int i, bool print )                       /*()*/ 
 
{  /* toRoman(): Arabic to Roman conversion */ 
/* Defines */   

C4-198
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

   int   j;             if(strncmp( rp‐>symbol, s, q = (j % 2)+1 ) == 0) { 
   roman *rp;                  /* rp: romans pointer */                 n += rp ‐> order; 
                 s += q; 
   if( i >= 4000 || i <= 0 ) { // Validate arabic input                 err = FALSE; 
       strcpy( buf, "Error" );             } 
       if( print ) {         } 
           printf( "\tRomans.c Error. Range: 1 .. 3999" );         if( err ) { 
       }           error: 
       return;             puts( "\tRomans.c Error. Bad Roman Number" ); 
   }             return ‐1; 
         } 
   for(*buf ='\0',j=0, rp = &romans[ 0 ]; j < SIZE; j++, rp++){     } 
       for( ; i >= rp ‐> order; i ‐= rp ‐> order ) {                      
           strcat( buf, rp‐>symbol );     // Validate Romanic input 
       }     // CLEVER: because validating romans is complicated, use 
   }     // ..this approach: Calculate Arabic (this, we know how to); 
   if( print ) {     // ..silent reconvert it to Romanic (also, we know how to 
       printf( "%s", buf );     // ..do this), and then: BOTH strings must compare 'equals' 
   }     // ..for Roman input to be valid! 
   
}  /* toRoman() */     toRoman( n, NO_PRINT );      // Silent reconvert n to roman 
     if( strcmp( buf, str ) == 0 ) { // reconverted Arabic == 
int toArabic ( char * s )                                /*()*/         return n;           // ..original Romanic, return Arabic 
{  /* toArabic(): Roman to Arabic conversion */     } 
     goto error;                // ..else, signal error 
   bool    err;   
   char   *str = s;  }  /* toArabic() */ 
   int     j, n = 0, q;   
   roman *rp;                  /* rp: romans pointer */  #if 0 
  Arabic   '2007'  is roman: 'MMVII' 
   while( *s ) {  Roman 'MCMXCVII' is arbic:  '1997' 
       err = TRUE;  #endif
       for(j = 0, rp = &romans[ 0 ]; j < SIZE; j ++, rp ++) { 

Cuando vamos a convertir de romano a arábigo, hay que validar la entrada en romanos, que es lo difícil. Como ya sabemos convertir de arábigo a
romanos, y es fácil, lo que se hace es convertir primero el número (antes de validarlo) de romano a arábigo, reconvertirlo de arábigo a romano, y
comparar las dos cadenas de caracteres; si son iguales, la entrada era válida. Por ejemplo, si se introduce el número 4 como una serie de cuatro unos
(IIII, lo que es inapropiado para Romanos), la rutina los convierte a 4 en arábigo; lo reconvierte a romanos, lo que produce el valor correcto: IV, y
como las dos secuencias son diferentes se advierte al usuario que ha habido una entrada inapropiada. Pero si la entrada es correcta, como en el
ejemplo (Roman 'MCMXCVII' is arbic: '1997'), se convierte el 'MCMXCVII', lo que produce '1997', se lo reconvierte a romanos y vuelve a dar:
'MCMXCVII', por lo que se sabe que la entrada era apropiada, y se imprime el resultado.

C4-199
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

 PI
3.141592 653589 793 238462 643383 279502 884197 169399 375105 820974 944592 307816 406286
208998 628034 825342 11

A veces vemos métodos ingeniosos para obtener ciertos resultados, como éste, pensado para aproximar
el valor de PI lanzando números al azar... ¿Qué tienen que ver los números al azar... con PI ?

// pi.c (by random), Luis G. Uribe C., V14S7 
// OBSERVACIÓN: El área del círculo unitario (radio 1) es PI. El cuadrado 
// ..en el que se encuentra inscrito dicho círculo, tiene lado 2 y área 4. 
// ..La relación entre las dos áreas (círculo/cuadrado) es PI/4. De una 
// ..cantidad TOT, muy grande (100 millones) de puntos tomados al azar dentro
// ..del cuadrado, algunos estarán también dentro del círculo (InCircle).
// ..La relación entre esas dos cifras se aproxima a PI/4, y por tanto PI será: 
// ..   “4 * InCircle / TOT” 
 
#include <stdio.h> 
#include <stdlib.h> 
#include <time.h> 
#define  STEP 1000000L                 // one million 
 
void main( void ) 

   double x, y;            // coordenadas de un punto en el espacio 
   double InCircle = 0;    // puntos tomados por azar, en el círculo 
   double tot      = 0;    // total de puntos, dentro del cuadrado 
   double range    = 0;    // var. aux, para impresión 
 
   srand( (unsigned)time( NULL ) );    // randomize 
   putchar( '\n' ); 
 
   printf( "Valor al que debe aproximarse PI:\n%s\n\n",  // Referencia! 
" 3.141592653589793,238,462,643,383,279,502,884,197,169,399,375,105\n" 
"                   820,974,944,592,307,816,406,286,208,998,628,034," 
           "825,342,11" ); 
 
   for(;;) {                           // choose x,y by random 
       x=(double)rand() / RAND_MAX;    // RAND_MAX is 2,147,483,647 
       y=(double)rand() / RAND_MAX;    // range is 0..1 
       if( x*x + y*y <= 1.0 )          // x,y inside circle? 
           InCircle++; 
if( ++tot > range ) { // inc tot, and conditional print
           printf( "\r%‐ 18.15f, % 19.0f",4.0 *InCircle / tot, tot ); 
           range += STEP;              // get new range to print 
       } 
   } 

Se imprime uno de cada millón de resultados, para no ralentizar el procesador; printf( "\r sobrescribe los valores.

C4-200
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

 POLÍTICA Y MECANISMOS
“Politics and Mechanisms” es un concepto clave y fundamental en la programación moderna. Aunado
al “Top-Down design”, es la base de la actual Orientación a Objetos, y los conceptos fundamentales
que nos enseñan: Encapsulación, ocultamiento, independencia y desacople entre módulos.

En programación, la Política significa “lo que hay que hacer”, y los Mecanismos “cómo se va a
hacer”. Si se logran escribir los programas indicando primero la serie de actividades que hay que hacer,
con independencia del cómo, y al final se implementan dichas actividades o políticas, y si la separación
es absoluta, se tendrá un sistema al que podrá cambiársele el sustrato (hardware, configuraciones) con
sólo modificar las partes que se relacionan; el programa principal no habrá que tocarlo. Esto es
fundamental cuando queremos que nuestras aplicaciones corran con libertad en variedad de
configuraciones de hardware, como es el caso en los sistemas embebidos.

Para ilustrar el tema acerca de Política y Mecanismos, lo que voy a comenzar yo por hacer es un programa
de animación que muestre en la pantalla del PC una película, cuyas secuencias estarán en texto común y
corriente (no son bit maps) porque así se mantiene la simpleza del programa y enfocamos los conceptos.

¿Con qué información se alimentará el programa? Un archivo con la serie de secuencias (frames), cuyo
formato será muy simple; cada frame consistirá en una secuencia de caracteres ASCII imprimibles, que
representarán las escenas en la pantalla del PC. La primera línea contiene un número, a la izquierda, que
indica cuántas veces hay que desplegar esa figura antes de pasar a la otra. Como ejemplo, dos escenas
tomadas de La Guerra de las Galaxias, por Simon Jansen (ver referencias); se muestra la princesa Leia
colocando la grabación en R2D2. El dibujo está formado por 13 líneas de 67 caracteres máximo.
11 
                       ,=== 
                      (@o o@ 
                       \ ‐/ 
                     //~  ~~\          ___ 
                    /  (   ) \        / ()\ 
                   /_/\    /\_|     _|_____|_ 
                    \\ \\ /| ||    | | === | | 
                      @| | | @     |_|  O  |_| 
                       | | |        ||  O  || 
                       | | |        ||__*__|| 
                      /  |  \      |~ \___/ ~| 
                      ~~~~~~~      /=\     /=\ 
______________________(_)(__\______[_]_____[_]_____________________ 

 
                            ,=== 
                           (@o o@ 
                          / \_‐/       ___ 
                         /| |) )      /() \ 
                        |  \ \/__   _|_____|_ 
                        |   \____@=| | === | | 
                        |   |      |_|  O  |_| 
                        | | |       ||  O  || 
                        | | |       ||__*__|| 
                       /  |  \     |~ \___/ ~| 
                       ~~~~~~~     /=\     /=\ 
_______________________(_)(__\_____[_]_____[_]_____________________

C4-201
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

La pantalla tendrá información adicional a la de la película, con el siguiente formato:


// ===================== Screen usage (80Colsx24Rows):======================= 
// 0123456789d123456789v123456789t123456789c123456789L123456789s123456789F123456789 
//00 
//01 
//02 
//03 
//04     +‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+ 
//..     |                     P.I.C.T.U.R.E                                | 
//..     |                                                                  | 
//22 Input field number or new frame time                                   | 
//23Foot G Uribe C V03G7 Art: Simon Jansen Inp. # to JUMP; '=#': Time. 32109|
Aquí se indica el lugar que ocupará la proyección (picture, líneas 5 a 21, columnas 6 a 73), y dos líneas
debajo de todo, donde se agrega información como el número del frame (32109), y algún recordatorio
de cómo puede el usuario situarse en un frame en particular (jump) o cambiar el tiempo de exposición
de los frames. Por defecto se tomará un tiempo de 67 milisegundos por frame, equivalentes a 15
frames/segundo. (Las películas en televisión tienen 24 frames por segundo, y en el cine son de 30)

A continuación la representación de las Políticas de este programa (lo que hay que hacer); mírenlo bien:
// ascmat2.c, AsciiMation, Luis G. Uribe C., L30L7 
// ...Politics & Mechanisms Separation 
// ================================================================== 
// This file has ONLY ***POLITICS*** (WHAT will be done);
// ..There are  NO  implied Mechanisms (or How things will be done). 
// In some places this is called pseudo code, but we have arranged to 
// ..show you one ‘C’ implementation, using Include Files and MACROS 
 
#include "ascmat2.h"   // Defines and implements almost ALL Semantics 
                       // ..except for second and deeper levels inside 
// ****************************************************************** 
// Main Level Politics: 
DefineGlobals(); 
 
void main( int argc, char **argv ) 
{  DefineLocals(); 
 
   OpenInputDataFile(); 
   InitTimers(); 
   PrintStaticFooter(); 
 
Restart: 
   InitProcess( xy, frame ); 
   DoUntilEOF() { 
       GetRepeatFactor(); 
       FillFrameBuffer(); 
       DrawFrames( WithRepeatFactor ); 
       PrintVariableFooter(); 
       CatchNew( Time, Frame, RestartOnError ); 
   } 
}  

C4-202
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Primero figura: Identificación (ascmat2.c), autor (Luis  G  Uribe), fecha (L30L7), tema, comentarios
(Políticas de primer nivel, ningún Mecanismo). A veces se llama pseudo código; pero es código en C.
Luego está #include "ascmat2.h" donde se implementa casi toda la semántica (se le da “significado” al
pseudo código; no es “toda” porque la parte de graficación y temporización se tratan aparte)
Después va el primer nivel de Política. Define variables globales (DefineGlobals();); todo programa
puede tenerlas; son visibles por varias rutinas, como los buffers; aquí se ordena su definición; obsérvese,
sin embargo, que ésta, propiamente dicha, no aparece aún, pues forma parte de los Mecanismos…
A continuación comienza main (void  main(  int  argc,  char  **argv  )  {). Se definen variables
locales (DefineLocals();); es más que probable que todo programa tenga variables locales, invisibles
para las demás rutinas, como contadores internos, por ejemplo, y se indica que aquí han de definirse; sin
embargo, la materialización en realidad no aparece aún, pues forma también parte de los Mecanismos…
Después de los prolegómenos, que pueden ser idénticos en la mayoría de los programas, vienen las
instrucciones más específicas del programa, comenzando por la instrucción de que se abra el archivo de
datos de entrada (OpenInputDataFile();). Al profundizar un poco más veremos que esta sección trata
de localizar un archivo de nombre determinado (asciimat.txt) y en caso de no encontrarlo, pregunta
al usuario por otro nombre.
Luego se inicializa el subsistema de temporización, que habrá de marcar el paso de 67 milisegundos por
frame (InitTimers();). De más está recalcar que aquí no tenemos ni idea de cómo vamos a medir este
tiempo, ni nos interesa; esto forma parte de los Mecanismos.
Al final se imprime la parte estática de la pantalla (PrintStaticFooter();), según se definió antes.
Ahora sí viene el proceso iterativo. Fíjense que hasta aquí, nadie pensaría que esto es C, ¡pero sí lo es!
Algún indicio de que así es lo tenemos con main y la llave (void main(int argc, char **argv){), los
puntos y comas, los paréntesis…
Lo que va a hacerse a continuación es: Inicializar los procesos (InitProcess(  xy,  frame  );); por
ejemplo, debe colocarse el cursor en la posición de la línea de entrada donde el usuario puede escribir
para escoger un frame en especial, o cambiar el tiempo de exposición de los cuadros, y hasta que se
termine el archivo (DoUntilEOF() {) se va a repetir el proceso de: Leer cuántas veces hay que mostrar el
siguiente frame (GetRepeatFactor();), leer la información del mismo (FillFrameBuffer();), dibujarlo
y esperar según el factor de repetición (DrawFrames( WithRepeatFactor );), actualizar la variable del
pie de la pantalla (PrintVariableFooter();) y ver si el usuario desea realizar algún cambio por teclado
(CatchNew( Time, Frame, RestartOnError );). Note que en caso de que se ordene mostrar un frame
inexistente, la política consistirá en rearrancar el proceso (Restart:). Errores de temporización (tiempos
muy pequeños, por ejemplo), se tratarán automáticamente, sin molestar al usuario, escogiendo valores
por defecto para subsanar esas situaciones. ¿Vieron qué fácil es?
No solo parece sencillo, sino que es muy conveniente. Supongamos que escogemos una cierta forma de
medir el tiempo, como por ejemplo, ejecutar inmensos loops de instrucciones, a fin de perder los
milisegundos necesarios. Si luego se desea cambiar este mecanismo, porque se va a correr el programa
en máquinas más rápidas y los viejos loops ya no satisfacen los retrasos, el programa sigue inmutable.
Mientras la interfaz con la parte de Mecanismos (las rutinas que definen el API: Application Program
Interface, sus parámetros) mantengan la consistencia, nada hay que cambiarle al código.
Analicemos ahora el #include "ascmat2.h":

C4-203
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

// ascmat2.h, AsciiMation, Luis G. Uribe C., L30L7 V03G7 C05S7  // ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
// ...Politics & Mechanisms Separation  // Second Level Politics: 
// This file has ONLY **MECHANISMS** (HOW Politics will be done)  // Init timers, change attribute used by cls(), and do cls() 
// ..(Politics is What will be done)   
/* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */  #define    InitTimers()                                       \ 
/* Include Project Specific Files */                                                                \ 
#include <ctype.h>     IniTimers();                                               \ 
#include <stdio.h>     clsatt = FG( BOLD | BROWN ) | BG( BLUE ); /*cls attribute*/\ 
#include <stdlib.h>     cls();                                                     \ 
#include <string.h>   
  // ============================================================ 
#include "rtc.h"  // Global Variables definitions 
extern volatile unsigned int timers[ 8 ];  #define DefineGlobals()                                       \ 
                                                                \ 
#include "video.h"  char buff[BUFLINES ][ BUFCOLUMNS]; /* screen buf. Uses 17,74*/\ 
  char line[LINESIZE];   /* buffer to get frame number */       \ 
// =============================================================  extern int clsatt; /* att. used by cls(); user modifiable d*/ \ 
// Parameter definitions taken from Jansen's site  // ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
#define NLINES     13     // 13 Lines per frame  // Local Variables definitions 
#define NCOLUMNS   74     // 74 Columns per line in frame  #define DefineLocals()                                        \ 
#define TIME       67     // 67 mseconds per frame (15 frm/sec)                                                                \ 
  FILE *fp;               /* input file pointer         */      \ 
// ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐  int  i;                 /* variable used in loops     */      \ 
// Other constants  int  buffLen;           /* Buffer Lenght              */      \ 
#define BUFLINES   25     // 25 Lines per frame  int  repeat;            /* number to repeat each frame*/      \ 
#define BUFCOLUMNS 80     // 80 Columns per line  int  n;                 /* times repeated each frame  */      \ 
#define LINESIZE   80     // 80 chars, Line Size  int  r, c;              /* (r)ow and (c)olumn         */      \ 
  long f;                 /* frames                     */      \ 
#define MAXREPEAT  69     // 69, as seen inside input file...  long frame = 0;         /* frame counter              */      \ 
#define BEGINLINE   4     //  4  long nframe;            /* new frame to jump          */      \ 
#define BEGINCOL    6     //  6  int  time  = TIME;                                            \ 
  char *file = "asciimat.txt";   /* default input file name */  \ 
#define INPUTLINE  22     // 22  // ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
#define INPUTCOL    0     //  0  // Open input data file 
#define FOOTERLINE 23     // 23  #define    OpenInputDataFile()                                \ 
                                                                \ 
// ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐     if( *argv[ 1 ] ) {                                         \ 
// MACROS definitions (ancillary)         file = argv[ 1 ];                                      \ 
#define DoUntilEOF()       while( 1 )     }                                                          \ 
#define TryNextFrame()     continue     if( ! ( fp = fopen( file, "r" ) ) ) {                      \ 
         printf("Oooops... Input file '%s' not present\n",file);\ 
#define AdjustEOL()                                           \         exit(0);                                               \ 
   buffLen = strlen( buff[ i ] );                             \     }                                                          \ 
   if( buff[ i ][ buffLen ? buffLen ‐ 1 : 0 ] ==  '\n' ) {    \  // ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
       buff[ i ][ buffLen ? buffLen ‐ 1 : 0 ] =   '\0';       \  #define PrintStaticFooter() /*line 23, diff. cols on screen */\ 
   }                                                          \                                                                \ 
   if( buff[ i ][ buffLen ? buffLen ‐ 1 : 0 ] ==  '\r' ) {    \    PrintSC(23, 0,"Prog: ", BOLD | GREEN | BG(BLUE) );          \ 
       buff[ i ][ buffLen ? buffLen ‐ 1 : 0 ]  = '\0';        \    PrintSC(23, 6,"G Uribe C V03G7 ", BOLD | BROWN | BG(BLUE) );\ 
   }                                                          \    PrintSC(23,22,"Art:", BOLD | GREEN | BG(BLUE) );            \ 
   buffLen = strlen( buff[ i ] );                             \    PrintSC(23,26,"Simon Jansen ", BOLD | WHITE | BG(BLUE) );   \ 
    PrintSC(23,39,"Inp. # to JUMP; '=#': Time. ",               \ 
            WHITE|BG(BLUE));                                    \ 

C4-204
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

// ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐             }                                                  \ 
#define InitProcess(xy, frame)                                \             for( c = 0; c < BUFCOLUMNS; c ++ ) {/*draw frame*/ \ 
                                                              \                 CharFillXY(r+BEGINLINE,c+BEGINCOL,buff[r][c],  \ 
   gotoxy(INPUTLINE,INPUTCOL );     /* bios function */       \                      BOLD | BROWN | BG( BLUE ) );              \ 
   frame = 0;                       /* init frame counter */  \             }                                                  \ 
// ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐         }                                                      \ 
#define GetRepeatFactor()                                     \         /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */ \ 
                                                              \         /* dinamic footer */                                   \ 
   if( ! fgets( buff[ 0 ], BUFCOLUMNS, fp ) ) {               \                                                                \ 
       exit( 0 );       /* EOF. exit() triggers clean‐up */   \          WTimer( 0 );                                          \ 
   }                    /* ..See rtc_int_dsb() in rtc.c */    \                                                                \ 
   repeat = atoi( buff[ 0 ] );                                \     }   /* Endfor( n = 0; n < repeat; n ++ ) */                \ 
   if( repeat <= 0 || repeat > MAXREPEAT ) { /* error */      \  // ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
       TryNextFrame();       /* ...skip */                    \  #define    PrintVariableFooter()                              \ 
   }                                                          \                                                                \ 
// ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐  sprintf( line, "Frame:%7ld", ++frame );                       \ 
#define FillFrameBuffer()                                     \  PrintSC( FOOTERLINE, 67, line, WHITE | BG( BLUE ) );          \ 
                                                              \  // ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
   for( i = 0; i < NLINES; i ++ ) {                           \  #define    CatchNew( Time, Frame, RestartOnError )            \ 
       if( ! fgets( buff[ i ], BUFCOLUMNS, fp ) ) {           \                                                                \ 
           exit( 0 );    /* EOF; exit() triggers clean‐up */  \     /*jump to any frame; write the frame number and <ENTER>*/  \ 
       }                                                      \     /* NOTE: Frames NOT adjusted by repeating factor to KISS*/ \ 
       AdjustEOL();                                           \                                                                \ 
                                                              \     if( kbhit() ) {                                            \ 
      /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */ \         gets( line );             /* get new frame number */   \ 
      /* fill end of buffer with blanks   */                  \         PrintSC( INPUTLINE, INPUTCOL,                          \ 
       for( c = buffLen; c < BUFCOLUMNS; c ++ ) {             \                 "            ", /*erase input data*/           \ 
           buff[ i ][ c ] = ' ';                              \             BOLD | BROWN | BG( BLUE ) );                       \ 
       }                                                      \         if(! isdigit(line[0] ) ) {  /* time begins with '=' */ \ 
   }                                                          \             time = atoi( &line[ 1 ] );  /* get new time */     \ 
// ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐         } else {                                               \ 
#define    DrawFrames( WithRepeatFactor )                     \             nframe = atoi( line ); /* get frame nmbr */        \ 
                                                              \             if( nframe < frame ) {                             \ 
   for( n = 0; n < repeat; n ++ ) {                           \                 fseek( fp, 0, SEEK_SET ); /* reposition file*/ \ 
       SetimerMS( 0, time );                                  \                 frame = 0;                                     \ 
                                                              \             }                                                  \ 
       /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */ \             for( f = frame; f < nframe; f ++ ) {/*read new */  \ 
       /*Draw ONE frame */                                    \                 for( i = 0; i < NLINES; i ++ ) {/* ..frame */  \ 
       /*First, move picture BEGINLINE (4) lines down */      \                     if(! fgets(buff[i], BUFCOLUMNS, fp ) ) {   \ 
                                                              \                         fseek(fp,0,SEEK_SET);/*restart on EOF*/\ 
       for( i = 0; i < BEGINLINE; i ++ ) {                    \                         goto Restart; /*sorry for using goto */\ 
           LineFill( i, ' ', BOLD | BROWN | BG( BLUE ) );     \                     }                                          \ 
       }                                                      \                     AdjustEOL();                               \ 
       /*‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */ \                 }                                              \ 
       /*Draw now */                                          \             }                                                  \ 
                                                              \             frame = nframe;                                    \ 
       for( r = 0; r < NLINES; r ++ ) {                       \         }   /* EndElse if( ! isdigit( line[ 0 ] ) )  */        \ 
           /*‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */ \         gotoxy( INPUTLINE, INPUTCOL );                         \ 
           /*1st move picture BEGINCOL (6) spaces from left*/ \     } /* Endif( kbhit() )  */                                  \ 
           for( c = 0; c < BEGINCOL; c ++ ) {                 \ 
               CharFillXY(r,c, ' ',BOLD | BROWN | BG(BLUE));  \ 
 

C4-205
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

De nuevo, el archivo comienza con una sección de identificación (ascmat2.h, AsciiMation), autor
(Luis G. Uribe C.), fecha (C05S7) y propósito (Politics & Mechanisms Separation), include Project
Specific Files, entre las que resaltan: #include  "rtc.h"  y "video.h", que definen parte de las
funcionalidades para los temporizadores y el manejador de la pantalla.

A continuación vienen algunas definiciones de parámetros para caracterizar las dimensiones de la


proyección en la pantalla, y algunas otras para establecer el tamaño del buffer de pantalla
(char buff[BUFLINES ][ BUFCOLUMNS];), cuál es el máximo valor esperado para el factor de repetición
de un mismo frame (#define  MAXREPEAT    69), en qué parte comienza la sección útil de la pantalla
(#define BEGINLINE 4, BEGINCOL 6), dónde va a estar la línea que el usuario emplea para dialogar con
el programa (#define INPUTLINE 22, INPUTCOL 0), y la línea donde se presentará la información del
pié de pantalla (#define FOOTERLINE 23).

Luego está la sección que define las primeras partes de los Mecanismos; comienza con MACROS 
definitions, en donde están las principales, identificadas de forma que su nombre indique con
precisión la funcionalidad: DoUntilEOF(),  TryNextFrame(),  AdjustEOL() (adecúa el End Of Line.
Note que esta AdjustEOL() sirve para manipular sólo un buffer de nombre “buff”; podría rescribirse de
manera genérica, para cualquier buffer). 

Después viene una sección en donde se implementan la inicialización de los InitTimers(), que a su vez
llama la función IniTimers();, la implementación de DefineGlobals(), donde destacan el buffer de
pantalla (char buff[BUFLINES][BUFCOLUMNS]) y el de línea (char line[LINESIZE]).

A continuación las variables locales de main (DefineLocals()), con el indicador de archivos (FILE 
*fp;), una variable utilitaria para el control de lazos de repetición (int i;), la longitud del buffer (int 
buffLen;), el factor de repetición del frame (int repeat;), las veces que ya lleva repetido un frame (int  
n;), las variables para memorizar la fila y columna (int  r, c;), la cantidad de frames (long frame;), el
número del frame que se desea comandar por teclado (long  nframe;), una variable auxiliar para
recorrer los frames (long f;), cuánto es el tiempo para el frame (int  time  = TIME;), inicializado en
TIME para comenzar y el nombre del archivo que se toma por defecto (char  *file  = 
"asciimat.txt";).

Luego se incluyen las materializaciones de OpenInputDataFile(), que leer el nombre del archivo desde
la línea de comandos (file = argv[ 1 ];), en caso de que el usuario quiera emplear uno diferente, y
también el manejo de error por si no se encuentre el archivo indicado (printf(…); y exit(0);)

La rutina de PrintStaticFooter() se basa en funciones primitivas (PrintSC()) definidas en #include 


"video.h" arriba; luego vienen InitProcess(xy,frame), FillFrameBuffer() y  GetRepeatFactor();
este último incluye TryNextFrame(), que como ven: #define TryNextFrame() continue, es un alias
por “continue”; es decir, presupone que éste código estará encerrado dentro de un while() o for().
Podría rescribirse para que devuelva un valor, según el cual pueda llamarse en forma condicionada, el
“continue”, a fin de hacerlo explícito. Sin embargo se escribió así, tratando de sobreenfatizar el tema de
la separación de Políticas y Mecanismos, para que fueran lo menos visibles dentro de la Política
decisiones como ésta. Ciertamente que la reusabilidad de TryNextFrame() es cuestionable…

C4-206
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

DrawFrames( WithRepeatFactor ) invoca primitivas del subsistema temporizador:


(SetimerMS( 0, time ); y WTimer( 0 );),
y también las del subsistema graficador:
(LineFill( i, ' ', BOLD | BROWN | BG( BLUE ) ); y
CharFillXY(r,c, ' ',BOLD | BROWN | BG(BLUE));).

Vienen de último PrintVariableFooter(), y CatchNew( Time, Frame, RestartOnError ).

Revise con cuidado el código que viene a continuación; verá que no es difícil. Algunas realizaciones no
se emplean por lo común; están colocadas aquí para resaltar al máximo la separación entre Políticas y
Mecanismos, pero en C no resultan siempre tan nítidas de escribir como en otros lenguajes,
probablemente orientados a objeto como el C++, C# o Java.

A continuación analizaremos los timers y el subsistema de despliegue, "rtc" y "video".

Varias técnicas son indispensables para el trabajo en tiempo real. De ellas, el manejo de temporizadores,
que le permiten al programa llevar varios flujos de secuencias en el tiempo, son de las más importantes.

La primera aproximación tiene como objetivo la sencillez; se basa en la función _bios_timeofday, que
devuelve el número de ticks ocurridos desde que se encendió la máquina o desde que se reinicializó la
función del BIOS. Un tick es un número de 32 bits (long) que representa cuentas de 54.92 ms/tick
(milisegundos/tick). La siguiente es una secuencia típica:

   long t2; 
   _bios_timeofday( _TIME_GETCLOCK, &t2 ); 

La variable t2, cuya dirección se pasa en la llamada (&t2), recibe el número de ticks. Normalmente uno
se construye una batería de temporizadores por software, que consisten en variables en las cuales usted
registrará el tiempo futuro en el que debe ocurrir algún evento. Una cantidad común es de 8
temporizadores, que son un arreglo de “longs”, algo así como:

volatile long timersMS[ 8 ];  // timers en MS (miliseconds) 

pero usted puede seleccionar la cantidad que necesite.

Se programan las siguientes funciones de Soporte: SetimerMS, Timeout, WTimer y WaitMS_on.

SetimerMS: Recibe como parámetros, el número del temporizador que usted quiere activar (del 0 al 7)
y la cantidad de milisegundos (MS) que a futuro deberán indicarle a usted que ha expirado ese lapso.
Note que el valor que debe almacenar corresponde al tiempo actual (devuelto por la llamada al BIOS),
más el número de milisegundos deseados. Tenga la precaución de convertir a milisegundos el número
de ticks que devuelve el BIOS (sabiendo que son 54.92 ms/tick)

C4-207
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Timeout: Retorna verdadero o falso (“1” o “0”), dependiendo de si el tiempo actual (que se lo
proporciona la función del BIOS) ha sobrepasado (1), o no (0), el tiempo registrado dentro del
temporizador que se le pasa como parámetro, del 0 al 7. No olvide que para comparar el valor de los
ticks con el del timer, tiene que convertir los ticks a milisegundos, que es lo que está almacenado en los
timers.

Wtimer: Es una función en la que usted especifica el número del temporizador deseado, y ésta espera
en un lazo, sin devolver el control al programa principal, hasta que Timout le indica que ya se venció el
lapso registrado en el temporizador. Este tipo de funciones, en las que el procesador se bloquea
esperando por la ocurrencia de un evento, desperdician el tiempo de la máquina pero, en ocasiones, en
realidad el programa no puede continuar haciendo nada hasta que ese evento suceda...

WaitMS_on: Esta es una función compuesta, que recibe como parámetros el número del temporizador
sobre el cual usted tiene que esperar sin que el programa continue más allá, y el número de milisegundos
que desea. Esta es una llamada a: SetimerMS y Wtimer, la que a su vez llama a Timeout.

Miremos el código, que está dividido en dos archivos, rtc.h y rtc.h:

C4-208
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

/* ********************************************************** */  /* =========================================================== */ 
// rtc.h, bios time usage Luis G Uribe C L13M6 C05S7  void SetimerMS (int timer, int timeMS )                    /*()*/ 
  { 
/* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */   
// Include Files     long t2; 
   
#include <bios.h>     _bios_timeofday( _TIME_GETCLOCK, &t2 ); 
#include <conio.h>   
     timersMS[ timer & ( NTIMERS ‐ 1 ) ] = 
#define NTIMERS    8   // This MUST be a power of 2: 2, 4, 8, 16...        (( t2 * 5492 ) / 100) + (long)timeMS;   // 54.92 mSec/tick 
   
/* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */  }  /* SetimerMS() */ 
// Function Prototypes   
  /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */ 
void IniTimers( void );  int Timeout (int timer)                                    /*()*/ 
void SetimerMS(  int timer, int timeMS );  { 
int  Timeout( int timer );   
void WTimer( int timer );     long t2; 
void WaitMS_on(  int timer, int timeMS );   
     kbhit();                        // Enable Ctrl‐C testing! 
     _bios_timeofday( _TIME_GETCLOCK, &t2 ); 
     if( timersMS[timer & (NTIMERS ‐ 1) ] >= (( t2 * 5492 ) / 100 )) 
         return( 0 ); 
     return( 1 ); 
   
  }  /* Timeout() */ 
   
  /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */ 
  void WTimer (int timer)                                    /*()*/ 
  { 
   
     while( ! Timeout( timer ) ) 
         ; 
   
  }  /* WTimer() */ 
   
   
  void WaitMS_on (int timer, int timeMS)                     /*()*/ 
/* *********************************************************** */  { 
// rtc.c, bios time usage Luis G. Uribe C. L13M6 L16O6   
     SetimerMS( timer, timeMS ); 
/* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */     WTimer( timer ); 
// Include Files   
  }  /* WaitMS_on() */ 
#include "rtc.h"   
  void IniTimers (void)                                      /*()*/ 
/* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */  { 
// Global Variables         /* Do nothing in this implementation of timers */ 
   
  }  /* IniTimers() */ 
volatile long timersMS[ NTIMERS ]; 
 

C4-209
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

De acuerdo a lo anterior, el subsistema temporizador ha sido diseñado con las siguientes


funcionalidades:  Debe poder inicializar los distintos timers (void  IniTimers(  void  );),
 posicionar un cierto timer (tomado de un grupo de #define  NTIMERS  8) en cualquier valor, en
milisegundos (void SetimerMS(  int timer, int timeMS );),  debe poder investigar si cierto timer
ya expiró (int  Timeout( int timer );),  suspender la operación del programa hasta que un timer
expire (void WTimer( int timer );)  y una operación compuesta, que inicializa un timer y suspende
la operación hasta que éste termine (void WaitMS_on(  int timer, int timeMS );).

Los 8 timers están representados por: volatile long timersMS[NTIMERS]; esta forma de exponer las
funcionalidades establece una interfaz con el susbsistema (API), del cuál no se ven mayores
interioridades; es decir, son las Políticas; luego vendrán los Mecanismos, susceptibles de cambiar.

Como ya se advirtió, se ha escogido para comenzar una implementación muy elemental; por ejemplo, el
SetimerMS(int  timer,  inttimeMS) funciona de la siguiente manera: Se lee la hora actual
(_bios_timeofday(  _TIME_GETCLOCK,  &t2  );), se la convierte a milisegundos aplicando la fórmula
((t2*5492)/100), se le suma el número de milisegundos estipulado (+  (long)timeMS;), y se lo
almacena en el temporizador requerido: timersMS[ timer & ( NTIMERS ‐ 1 ) ] =.

Verificar si un temporizador expiró (int Timeout (int timer)) consiste simplemente en comparar la


hora actual con la hora almacenada para el timer, todo convertido a milisegundos: if(  timersMS[ 
timer & (NTIMERS‐1)] >= ((t2 * 5492)/100)); retorna 1 si expiró, 0 de lo contrario.

Esperar hasta que un temporizador expire (void WTimer ( int timer )) es muy sencillo:

while( ! Timeout( timer ) ) /* empty while */ ;

Y la funcionalidad compuesta: void WaitMS_on ( int timer, int timeMS ), consiste en SetimerMS( 


timer, timeMS ); WTimer( timer ); 

En esta implementación, void IniTimers ( void ) no desempeña ningún papel.

Resulta que, si bien es muy sencillo el subsistema de temporizadores tal como aquí se muestra, tiene
algunos compromisos: El tiempo mínimo, en un PC, está alrededor de 54.92 mSec/tick, por lo que
podría resultar conveniente reemplazar el Mecanismo por uno basado en interrupciones del Real Time
Clock (rtc), con lo que se puede llevar la granularidad a un (1) milisegundo. Otras arquitecturas de
estaciones de trabajo, como el Macintosh, u otros sistemas operativos, como Linux, no tienen
exactamente ésta misma funcionalidad del _bios_timeofday( _TIME_GETCLOCK, &t2 ); del DOS, por
lo que habrá que modificar los Mecanismos para adecuarlos, en caso de necesidad.
Incluyo sólo para ilustrar el tema, las no tan simples rutinas del Real Time Clock por
interrupciones en el PC, con exactamente la misma interfaz anterior, pero con un Mecanismo
muy diferente; maneja las interrupciones directamente (en las rutinas anteriores, el bios manejaba
las interrupciones, pero la granularidad no es tan buena, como ya se dijo). Verá que el código es
mucho más complejo, con mayor nivel de detalle, de acuerdo al chip que se maneja. Ensaye
reemplazar los anteriores rtc.h y rtc.c por éstos nuevos; verá cómo todo funciona a la
perfección, ¡sin tener que hacer ningún otro cambio!

C4-210
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

/* rtc.h: Luis G. Uribe C., S29N2003 v22O4 J27E5 M12D6 C05S7    */  //            1011b ‐  31250     uSec (2^15/2^10 = 2^ 5 Hz) 
  //            1100b ‐  62500     uSec (2^15/2^11 = 2^ 4 Hz) 
/* External Variables                                           */  //            1101b ‐ 125000     uSec (2^15/2^12 = 2^ 3 Hz) 
  //            1110b ‐ 250000     uSec (2^15/2^13 = 2^ 2 Hz) 
void    far  *old_rtc_vec;  //            1111b ‐ 500000     uSec (2^15/2^14 = 2^ 1 Hz) 
volatile unsigned long ticks;   
volatile unsigned int timers[ 8 ];  /* Status Register B                                            */ 
  #define RTC_SRB 0x0B          /* Status Register B (read/write) */ 
/* Macros definitions                                           */  #define RTC_ALL_INTS    0x8F  /* all possible interrupt sources */ 
#define  WTimer(t)     { while( timers[ t ] ) kbhit() ; }  #define RTC_PERIODIC_INT   (1<<6) 
#define  Timeout(t)    ( timers[ t ] ? 0 : !0 )   
  //  Bit 7 ‐ 1 aborts update cycle, 0 enables 
/* Function Prototypes                                          */  //  Bit 6 ‐ 1 enables periodic interrupt 
//  Bit 5 ‐ 1 enables alarm interrupt 
void IniTimers( void ); 
//  Bit 4 ‐ 1 enables update‐ended interrupt 
void WaitMS_on( unsigned int t, unsigned int time ); 
//  Bit 3 ‐ 1 enables square wave output 
void SetimerMS( unsigned int t, unsigned int time ); 
//  Bit 2 ‐   Data Mode               ‐ 0: BCD, 1: Binary 
 
//  Bit 1 ‐   24/12 hour selection    ‐ 1 enables 24 hour mode 
void interrupt far rtc_int( void ),  rtc_int_dsb( int signal ); 
//  Bit 0 ‐   Daylight Savings Enable ‐ 1 enables 
void rtc_int_dsb2( void ); 
void fin ( int sig );   
  /* Status Register C                                            */ 
#define RTC_SRC 0x0c           /* Status Register C (Read only) */ 
/* Include Files */ 
 
#include <conio.h> 
// 0Ch Status Register C (Read only) 
#include <dos.h> 
//  Bit 7 ‐ Interrupt request flag‐1 when any or all of bits 6‐4 are 
#include <stdio.h> 
//          1 and appropriate enables (Register B) are set to 1. 
#include <stdlib.h> 
//          Generates IRQ 8 when triggered. 
 
//  Bit 6 ‐ Periodic Interrupt flag 
/*  RTC Addresses, Vector & Registers A, B and C:               */  //  Bit 5 ‐ Alarm Interrupt flag 
#define RTC_add    0X70  //  Bit 4 ‐ Update‐Ended Interrupt Flag 
#define RTC_data   0X71  //  Bit 3‐0 ??? 
#define RTC_vect   0X70   
 
/*  PIC Addresses and RTC related interrupt enable bits         */ 
/* Status Register A;   cfr. prof. Luis Alvarado: RTC.ASM, 1999 */  #define RTC_PIC_INTEN  ( ~ (1<<0) )   /* enable mask in PIC2 */ 
#define RTC_SRA 0x0A          /* Status Register A (read/write) */  #define RTC2_ENABLE    ( ~ (1<<2) )   /* enable PIC2 in PIC1 */ 
#define UIP    ( 1<<7 ) /* Update in Progress. ouputs undefined */   
#define Khz_8  0x03 /* 0011b: 122.070 uSec (2^15/2^2 = 2^13 Hz) */  #define EOI_PORT1  0x20 
#define Khz_def 0x06 /* 0110b: 976.562 uSec (2^15/2^5 = 2^10 Hz)*/  #define EOI_PORT2  0xA0 
  #define EOI        0x20 
// Bit 6,5,4‐22 stage divider. 010b ‐ 32.768 Khz time base (default)   
//  Bit 3‐0 ‐ Rate selection bits for interrupt.  #define PIC1_Mask  0x21 
//            0000b ‐ none  #define PIC2_Mask  0xA1 
//            0001b ‐   
//            0010b ‐  #define sti    _enable() 
//  Khz_8:    0011b ‐    122.070 uSec (2^15/2^ 2 = 2^13 Hz)  #define cli    _disable() 
//            0100b ‐    244.140 uSec (2^15/2^ 3 = 2^12 Hz)   
//            0101b ‐    488.281 uSec (2^15/2^ 4 = 2^11 Hz)  #pragma intrinsic( _enable, _disable ) 
//  Khz_def:  0110b ‐    976.562 uSec (2^15/2^ 5 = 2^10 Hz) default  #pragma intrinsic( inp, outp ) 
//            0111b ‐   1953.123 uSec (2^15/2^ 6 = 2^ 9 Hz)   
//            1000b ‐   3906.247 uSec (2^15/2^ 7 = 2^ 8 Hz) 
//            1001b ‐   7812.495 uSec (2^15/2^ 8 = 2^ 7 Hz)  /* Include Files */ 
//            1010b ‐  15625     uSec (2^15/2^ 9 = 2^ 6 Hz)  #include <signal.h> 

C4-211
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

/* rtc.c: Luis G. Uribe C., S29N2003 v22O4 J27E5 C13D6 C05S7   */     /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */ 
     // Limpiar cualquier posible interrupt pendiente 
/* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */   
/* Include Files */     outp( RTC_add, RTC_SRC );  
     inp( RTC_data );           /* dummy read, clear any pending */ 
#include "rtc.h"   
     /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */ 
/* =========================================================== */     // Inicializar todos los timers en 0 
void IniTimers ( void )                                    /*()*/   
{     ticks = 0L;                     /* init values */ 
   
   volatile unsigned int   tmp;     for( i = 0; i < 8; i ++ ) 
   int i;         timers[ i ] = 0;            /* init values */ 
   
   /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */     /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */ 
   // RTC Setup.El ORDEN de estas operaciones hay que mantenerlo!     // Habilitar interrupciones globales del CPU 
   
   old_rtc_vec = _dos_getvect( RTC_vect );     // SAVE OLD VEC     sti; 
   signal ( SIGINT, fin );                     /* CONTROL C */   
   atexit( rtc_int_dsb2 );  }  /* IniTimers() */ 
   
   /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */  /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */ 
   // Programar nueva velocidad  void interrupt far rtc_int ( void )                        /*()*/ 
  {      /* rtc_int() */     // Nueva rutina de interrupcion 
   cli;                                // RTC *needs* CLI     int i; 
   outp( RTC_add, RTC_SRA );    
   tmp = ( inp( RTC_data ) & 0xF0 ) | Khz_8;     /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */ 
     // Reconocer (borrar) el interrupt que acaba de generarse en RTC 
   outp( RTC_add, RTC_SRA );   
   outp( RTC_data, tmp );     outp( RTC_add, RTC_SRC );  
     inp( RTC_data );            /* clear any pending interrupts */ 
   /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */   
   // Colocar nuevo versión, con nuestra rutina de interrupciones     /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */ 
     // Incrementar 'ticks' (LONG) 
   _dos_setvect( RTC_vect, rtc_int );  // Set new RTC Vector   
   cli;                                // DOS makes STI. Redo CLI     ticks ++; 
     /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */ 
   /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */     // Procesar 8 siguientes timers (INT). Si ya están en cero, no 
   // Programar Interrupt periódico en RTC     // ..se hace nada con ellos; de lo contrario, se los decrementa 
   
   outp( RTC_add, RTC_SRB );      for( i = 0; i < 8; i ++ ) 
   tmp = ( inp( RTC_data ) & RTC_ALL_INTS ) | RTC_PERIODIC_INT;         if( timers[ i ] )           // skip if timer is zero already 
             timers[ i ] ‐‐; 
   outp( RTC_add, RTC_SRB );      /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */ 
   outp( RTC_data, tmp );     // Reconocer el interrupt en los dos PICs. El orden de estas 
     // ..operaciones es siempre importante 
   /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */   
   // Habilitar que el RTC interrumpa por el segundo PIC;     outp( EOI_PORT2, EOI ); 
   // ..habilitar que el segundo PIC entre al primer PIC     outp( EOI_PORT1, EOI ); 
   
   outp( PIC2_Mask, inp( PIC2_Mask ) & RTC_PIC_INTEN );  }  /* rtc_int() */ // RTI: Retorno de interrupt: CLEAR CPU IREQ 
   outp( PIC1_Mask, inp( PIC1_Mask ) & RTC2_ENABLE );   

C4-212
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

/* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */     if( signal == SIGINT ) 
void rtc_int_dsb ( int signal )                            /*()*/         exit( signal ); 
{    /* com_int_dis() */     // invoked by control‐c, and at end   
  }   /* rtc_int_dis() */ 
   volatile unsigned int   tmp;   
   static done = 0;   /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */ 
  void rtc_int_dsb2 ( void )                                 /*()*/ 
   if( done )  return;  {      /* com_int_dis2() */   // Ancillary routine, invoked atexit 
                               // ..cause cannot have any parameters 
   /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */     rtc_int_dsb( 0 ); 
   // RTC necesita CLI para su programación. Se deja la velocidad   
   // ..estandar: Khz_def  }   /* rtc_int_dis2() */ 
   
   cli;  /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */ 
   outp( RTC_add, RTC_SRA );   // WaitMS_on() implements a delay using RTC.C 
   tmp = ( inp( RTC_data ) & 0xF0 ) | Khz_def;   
  void WaitMS_on (unsigned int t, unsigned int time) //milliS/*()*/ 
   outp( RTC_add, RTC_SRA );  { 
   outp( RTC_data, tmp );   
     SetimerMS( t, time ); 
   /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */     WTimer( t ); 
   // Se recupera el vector original. CLI porque DOS retorna con STI    
  }   /* WaitMS_on() */ 
   _dos_setvect( RTC_vect, old_rtc_vec );   
   cli;  /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */ 
  // SetimerMS() implements a delay using RTC.C 
   /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */   
   // Se deshabilitan las interrupciones del RTC en el PIC2  void SetimerMS (unsigned int t,unsigned int time ) //milliS/*()*/ 
   // ..Sería preferible haber guardado el valor original de los  { 
   // ..PICs al empezar, y restaurar sus valores aquí   
     timers[t] = (int)( ((long)time * 1000) / 122);// 122 uSec/tick 
   outp( PIC2_Mask, inp( PIC2_Mask ) & ~ RTC_PIC_INTEN );   
   sti;  }   /* Setimer() */ 
   
  /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */ 
   /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */  void fin ( int sig )                                       /*()*/ 
   // Se imprimen los ticks finales y se hace call exit  { 
   
   getchar();      exit( 0 ); 
   fprintf( stderr, "\n\nFinal TICKs: %lu\n", ticks );   
   done++;  }   /* fin() */ 
 

C4-213
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Por último, revisemos el subsistema de despliegue de información:

 
/* video.h, Luis G. Uribe C., J04Y06, video defines            */  void ScreenFill( int ch, int att ); 
   
/* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */  int CharGetXY( int row, int col ); 
/* Include Files */   
  void gotoxy( int x, int y); 
#include <conio.h>      // for getch()   
  /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */ 
/* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */  /* Some Defines and Enums */ 
/* Macros and Typedefs */   
  #define VIDEO  (int far *)0xB8000000 // Base Address for Video VGA 
#if !defined uchar   
   typedef unsigned char uchar;  // Standard Mode (3): 80 columns * 25 lines 
#endif   
#if !defined uint  #define NCOLS  80        // Number of Columns (chars/line) 0..79 
   typedef unsigned int  uint;  #define NROWS  24 //25   // Number of Rows (Lines) 0..24 
#endif   
  // The screen is seen as a vector of integers (2 bytes) 
#define FG( c )    (  (c) & 0x0F )             // ForeGround  // .. The first (even) byte is the Character to be displayed 
#define BG( c )    ( ((c) & 0x0F ) << 4 )      // BackGround  // .. The second (odd) byte is the Attribute of the character 
  // Attribute Bits 2, 1, 0: Foreground color 
// ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐  // Attribute Bits 6, 5, 4: Background color, 
// Fill one possition with 'ch' char and 'att' attributte,  // .. with same meaning as Foreground Colors 
// .. at 'poss' possition (See how to build and use a Macro)   
// Note: CharFill receives poss, uint far *; cast it to uchar  enum colors {        // both for Foreground & B_ackground 
   // normal colors: 
#define CharFill(pos,ch,att ) *((uchar far *)(pos))     = (ch), \     BLACK,  BLUE,  GREEN,  CYAN,  RED,   MAGENTA,   BROWN,   WHITE, 
                              *(((uchar far *)(pos))+1) = (att);\   // BOLD   colors: 
                               kbhit()     B_BLACK,B_BLUE,B_GREEN,B_CYAN,B_RED, B_MAGENTA, B_BROWN, B_WHITE, 
   // Special color ID: 
#define CharGet( pos )        *((uint far *)(pos))     YELLOW = B_BROWN, 
  }; 
/* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */   
/* Function Prototypes */  // Attribute's Bit 3 (decimal 8) is BOLD, so adding '8' to colors 
  // .. redefine them as BOLD chars (i.e., BOLD BROWN is Yellow) 
void CharFillXY( int row, int column, int ch, int att );   
void cls( void );          // Clear Screen  #define BOLD  ( 1 << 3 )   // Bold: Attribute Bit 3 (decimal 128) 
void LineFill( int row, int ch, int att );   
void PrintLines( int Att );  // Attribute's Bit 7 (decimal 128) is Foreground Blink 
void PrintSC(  int row, int column, char * string, int att );   
void PrintSCr( int row, int column, char * string, int att );  #define BLINK ( 1 << 7 )   // Attribute Bit 7 is Foreground Blink 
void ScreenFill( int FillCh, int Att ); 
 
/* video.c, Luis G. Uribe C., J04Y06, C13D6 video functions    */ 
 
/* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */ 
/* Include Files */ 
#include "video.h" 

C4-214
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

/* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */  /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */ 
void CharFillXY ( int row, int col, int cht, int atr )     /*()*/  void PrintSCr ( int row, int col, char * string, int att ) /*()*/ 
{  { 
   int far * pvideo = VIDEO;     while( *string ) { 
   int pos = ( row * NCOLS ) + col;  // video RAM lineal position         CharFillXY( row, col, *string, att ); 
         string ++; 
   if( ( pos >= 0) && ( pos < NROWS * NCOLS ) ) { // OK         col ‐‐; 
       pvideo += pos;          // else: print at begining of RAM     } 
   }   
   CharFill( pvideo, cht, atr );  } 
}   
  /* =========================================================== */ 
/* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */  int CharGetXY ( int row, int col )                         /*()*/ 
void LineFill ( int row, int ch, int att )                 /*()*/  { 
{     int pos = ( row * NCOLS ) + col; // video RAM lineal position 
   int col;     int far * pvideo = VIDEO + pos; 
   
   for(col = 0; col < NCOLS; col ++ ) {     if( ( pos >= 0) && ( pos < NROWS * NCOLS ) ) { // OK 
       CharFillXY( row, col, ch, att );         return CharGet( pvideo ); 
   }     } 
}     return '\0'; 
   
/* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */  } 
void ScreenFill( int ch, int att )                         /*()*/   
{  /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */ 
   int row;  #include <dos.h> 
   
   for( row = 0; row < NROWS; row ++ ) {  void   gotoxy( int x, int y )                              /*()*/ 
       LineFill( row, ch, att );  { 
   }     typedef union REGS Regs; 
}   
     Regs regs; 
/* ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ */   
int clschar = ' ';         // global variables for cls character     regs.h.dl = (unsigned char)y;       // BIOS video driver 
int clsatt  = FG( WHITE ); // ..and attribute     regs.h.dh = (unsigned char)x;       // .. int 10h, funt. 02h 
     regs.h.bh = 0;                      // .. positions the cursor 
/* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */     regs.h.ah = 0x2; 
void cls (void)                                            /*()*/     int86( 0x10, &regs, &regs ); 
{   
   ScreenFill( clschar, clsatt );  }      /* gotoxy() */ 

 
/* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */ 
void PrintSC ( int row, int col, char * string, int att )  /*()*/ 

   while( *string ) { 
       CharFillXY( row, col, *string, att ); 
       string ++; 
       col ++; 
   } 
 

C4-215
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

El manejo de la pantalla de video sirve bien para estudiar la clase denominada “memory-mapped
I/O” en su forma más elemental (sin handshaking). Además, toda presentación de información que
emplee atributos como colores de las letras y del fondo, parpadeo, sobre intensidad, etc., necesitan la
aplicación de los procedimientos que aquí se presentan.

Se define primero el módulo elemental: CharFill( poss, ch, att ), macro que escribe un símbolo
determinado (ch) en una posición lineal, entera, (poss) y con los atributos definidos en att:

#define CharFill(poss,ch,att ) {*((char far *)(poss))    = (ch),   \ 
                             *(((char far *)(poss))+1)=(att);} 

Se añaden a continuación las definiciones de soporte necesarias, tales como la dirección base de la
memoria de video, los nombres para los 8 colores, en base a estas definiciones principales, se genera las
funciones de Soporte:

CharFillXY (row, column, ch, att) que presente la ilusión de que la pantalla está estructurada en filas
y columnas, lo que es más cómodo de manejar que CharFill, dependiendo del caso. Se incluyen
decisiones inteligentes que confinan el almacenamiento al área de memoria asignado para el video, aún
si los parámetros de entrada, row y column, tienen valores ilegítimos (números negativos, o que
produzcan direcciones de memoria más allá del área de video).

LineFill() llena con una letra y un atributo, escogidos por el usuario, una línea determinada.

ScreenFill(), con parámetros apropiados que usted deberá señalar, explicando sus razones. El
propósito aquí es el de llenar la pantalla completa con un símbolo y su atributo, escogidos por el
usuario.

cls() (clear screen), que debe borrar la pantalla, rellenándola de espacios, con características de letra
blanca en fondo negro, que es lo convencional. Esta rutina no lleva parámetros, pero usted debe
definirla de tal manera que el usuario pueda cambiar el símbolo y los atributos que cls() emplea. Indique
cual será su aproximación para ofrecer esta facilidad.

PrintSC (row, column, string, att) imprime una cadena de caracteres “string” a partir de la posición
definida por row y column, aplicando a todos los caracteres el mismo atributo att. Esta función maneja
bien el posible cambio de fila, en caso de que el texto sobresalga de la línea actual en la pantalla.

En el código (video.h) se encuentran macros auxiliares para manipular el ForeGround (#define FG(c) 


((c)&0x0F)) y el BackGround (#define BG(c) (((c)&0x0F)<<4)). A continuación vienen las macros
de más bajo nivel, CharFill(pos,ch,att) para llenar una posición con un carácter y su atributo, y
CharGet(pos) para leer de la memoria de video una cierta posición. Estas dos macros direccionan las
posiciones en la memoria de video, considerándolas como compuestas por dos (2) bytes: Uno para la
letra y otro para el atributo.

Después vienen los prototipos de las diversas funciones, la posición de la memoria de video (#define 
VIDEO (int far *)0xB8000000), el tamaño de la pantalla, en columnas y filas (en este caso, algunos

C4-216
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

dispositivos tienen 24 líneas, entre tanto que otros tienen 25; se emplean 24 para ser compatibles con
ambos)

Se definen los colores asignando símbolos a los números que entiende el hardware, y dos símbolos
auxiliares, BOLD (1<<3) y BLINK (1<<7).

En  video.c  se incorporan las rutinas de mayor nivel, soportadas por las de más baja jerarquía, ya
referidas. void CharFillXY(int row,int col,int cht,int atr), recibe el número de una fila, una
columna, el símbolo que se quiere representar y su atributo; convierte fila y columna a la posición lineal
entera que la macro CharFill() entiende, y la llama. 

LineFill(int  row,int  ch,int  att) llama repetidas veces la rutina anterior (CharFillXY());
ScreenFill(int  ch,int  att) llama a CharFillXY(); void  cls()se basa en ScreenFill(), y void 
PrintSC(int row,int col,char *string,int att) requiere a CharFillXY(). 

Una nota final para advertir que la implementación de un sistema no siempre se hace Top-Down; a
veces se comienza, como en el caso de video.c, desde las primitivas más elementales, y se va
construyendo el sistema hacia arriba (Down-Top)

Recuerden que la magia que sirve para reemplazar un sistema tan sencillo como el de los
temporizadores originales, por el que maneja directamente, por interrupciones, el chip del timer del PC,
estriba en la Separación de Políticas y Mecanismos, y la definición y aseguramiento de la
Interfaz (API).

C4-217
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

 REALLY SIMPLY HASH


En la programación de sistemas embebidos, pero también en las estaciones de trabajo y servidores, es
recurrente la necesidad de almacenar y recuperar (store and retrieval) información mediante algún tipo
de clave. Ya hemos hablado de la necesidad de proteger estos códigos cuando deben ser manipulados a
mano por el usuario, mediante dígitos de verificación. Hay claves seriales, que se forman en secuencia
numérica, como los números que se asignan para manejar los turnos en algunos sistemas de colas. Otras
claves se componen mediante dígitos (y a veces letras) que agregan información al código; así, los
primeros dos números pueden identificar el suplidor, los otros dos el modelo, uno más la ubicación,
etc., según las necesidades del usuario.

Lo cierto es que muchas veces sucede que el número de claves es muy superior a la cantidad de artículos
que en realidad hay que identificar. Por ejemplo, una de mis cuentas de ahorro tiene 20 dígitos, con lo
cual se podrían asignar 100 millones de millones de millones de cuentas (100 trillones). Aún si
descartáramos un dígito de verificación y 4 o 5 que pueden ser internacionales, cien billones de
posibilidades en la asignación de cuentas bancarias parecen exceder cualquier escenario comercial.

Otro ejemplo corriente es cuando se usa el nombre para buscar datos asociados en una tabla. Mi hijo
mayor, Alejandro Uribe (sin incluir más nombres ni el segundo apellido), alcanza las 13 letras. Si se
emplearan todas las 26 letras en la conformación de nombres, podrían identificarse 2.5 trillones de
personas. Aún si las combinaciones son mucho menores, la cantidad es muy elevada.

Parece evidente entonces que en tales casos el número de identificación no puede usarse directamente
como índice para tener acceso a la información. La gente de computación trabaja este tema bajo el
nombre de table loockup; el algoritmo se llama una búsqueda por “hash”, en donde el nombre o el
código se convierten en un número entero pequeño, que es el que en realidad se emplea como índice.

El siguiente es una modificación del recomendado por K&R, válido para cadenas de caracteres; la
denomino RSHash (Really Simple Hash) por la moda actual de simplificar viejos protocolos de red, y
bautizarlos así, como el RSS: Really Simple Sindication):

/* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */ 
unsigned int hash( char *s )                                   /*()*/ 

   unsigned int hashval; 
 
   for( hashval = 0; *s != '\0'; s++ ) 
       hashval = (*s ‐ 'A' ) + (31 * hashval); 
   return hashval % HASHSIZE;  // See: hashval | 1 
}
(K&R usan: hashval = *s + 31 * hashval;)

C4-218
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

                                                           #if 0     // ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
hash.c, Luis G. Uribe C., L20J2005. Prueba de función hash M24L7     // print table 
                                                           #endif   
/* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */     printf( "Total sample: %d; HashSize: %d\n\n", 
// Include files         TotalSample, HASHSIZE ); 
   
#include <stdio.h>     for( Doubles = i = 0; i < HASHSIZE; i ++ ) { 
         // don't verify all CHECKSIZE elements; just HASHSIZE 
/* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */         if( check[ i ] ) { 
// Function defintions             if( check[ i ] > 1 ) { 
                 Doubles ++; 
unsigned int hash( char *s );             } 
             printf( "%3d ", i ); 
#define HASHSIZE 101             for( j = 0; j < check[ i ]; j ++ ) { 
                 putchar( '*' ); 
/* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */             } 
// Global Variables. May change table contens w/different strings             putchar( '\n' ); 
         } 
char *tabla[] = {     } 
   "Abboud",       "Almansor",     "Alzamora",     "Anda",   
   "Anzola",       "Azuaje",       "Benadivas",    "Bentolila",     // ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
   "Castillo",     "Chang",        "Correia",      "De Majo",     // calculate % with one decimal, not using floating point 
   "De Sousa",     "Garcia",       "Gonzalez",     "Issa",   
   "Jauregui",     "Jimenez",      "Liendo",       "Lopez",     // ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
   "Ma",           "Machado",      "Machado",      "Marquez",     // Ancillary variables 
   "Mata",         "Mencia",       "Mendez",       "Perez",     decimals = Doubles * 100 * 10 / TotalSample; 
   "Pignatari",    "Rangel",       "Rosario",      "Tremont",     integers = decimals / 10; 
   "Wasylkowski",  "Zambrano",   
};     fraction = decimals ‐ integers * 10; 
     printf( "\nUsed %d, Doubles %d, Merit Figure " 
             "(Used/TotalSample%; should aproach 100%%): %d.%1d%%\n",  
#define CHECKSIZE 256  // HASHSIZE 101, may grow up to 256 (SAssert)         TotalSample ‐ Doubles /*=Used*/, Doubles, 
char check[ CHECKSIZE ];   // global: linker init to 0's         (TotalSample‐ Doubles) * 100 / TotalSample, fraction); 
   
  }
/* =========================================================== */ 
void main( void )                                          /*()*/ 
{   
   int i, j, TotalSample, Doubles, decimals, integers, fraction;  /* *********************************************************** */ 
   unsigned int HIndex;  unsigned int hash( char *s )                               /*()*/ 
  { 
   TotalSample = sizeof( tabla ) / sizeof( char * );     unsigned int hashval; 
   
   // ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐     for( hashval = 0; *s != '\0'; s++ ) { 
   // load table using hash function as an index         hashval = (*s ‐ 'A' ) + (31 * hashval); 
     } 
   for( i = 0; i < TotalSample; i++ ) {     return hashval % HASHSIZE; 
       HIndex = hash( tabla[ i ] );  }
       check[ HIndex ] ++ ; 
   } 
 

C4-219
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

La estadística del programa anterior arroja los siguientes resultados con los datos allí presentes:

Used 28, Doubles 6, Merit Figure (Used/TotalSample; should aproach 100%): 82.6% 

Los “dobles” indican que hubo 6 localidades de memoria por la que compitieron dos nombres; en ese
caso hay que establecer una rutina de búsqueda secuencial (cfr. K&R). Pude haber “triples” y más.

Es conveniente que HASHSIZE (101 en el ejemplo) sea un número primo.

 SASSERT
Es muy importante verificar ciertas suposiciones en los programas; el C provee desde siempre un
mecanismo, la macro assert(), para pruebas dinámicas, es decir, cuando el programa está ejecutando. Se
encuentra definido en <assert.h>, y puede tener el siguiente aspecto:

/* assert.h: assert macro      */ 
 
#if !defined(NDEBUG) 
  #define assert(p) if(!(p)){fprintf(stderr,     \ 
      "Assertion failed: %s, file %s, line %d\n",\ 
      #p, __FILE__, __LINE__); abort(); } 
#else 
  #define assert(p) 
#endif 

La ventaja del mecanismo es que uno compila su programa con las verificaciones activas y cuando ya lo
ha depurado no hay que reeditarlo para quitárselas; basta con incluir definir el identificador NDEBUG.
Recuerde que esto puede hacerlo mediante un #define, o también incluyendo un “/D” en la línea de
comando al invocar al compilador (cc /DNDEBUG), así que es todo muy simple.

Lo que quisiéramos es poder extender este tipo de verificaciones también al momento de compilar
(Static asserts), para verificar si ciertas condiciones se cumplen, por ejemplo, que algunas constantes
tengan determinados valores (tamaños de buffers, por ejemplo), o que sean potencias de 2 (a veces se
aprovecha la expresión K-1 para obtener una máscara llena de 1’s, la cual se aplica a los apuntadores o
subíndices que operan ciertos buffers, para lograr, por ejemplo, el efecto de redondeo: Wrap around.
Pero ésto solo funciona si K es potencia de 2).

Igualmente se puede verificar que la máquina para la que se compila el programa tenga enteros de 2
bytes, o de 4; que sus chars sean signed, en fin, una cadena de suposiciones que, de llegar a fallar, harían
que nuestro programa no corriera.

Se presenta a continuación una forma excelente pero desconocida de lograr este propósito,
simplemente incluyendo un #define con Sassert (Static assert). Se incluye un programa de ejemplo:

C4-220
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

 
#define  Sassert(e)  do{ enum { Sassert__ = 1/(e) }; } while (0) 
 
// if Sassert fails print: "error C2057: expected constant expression" 
// Sassert (static assert) macro does NOT generate run time code 
 
void main( void ) 

   getchar();          // filling instructions 
 
   // ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
// EXAMPLE: Ensure 'char' is a signed type
   // 
   // Note that this Static Assert, Sassert, will run fine on MSVC 
   // ..(Microsoft Visual C), but will fail miserably on CODEWARRIOR 
   // ..This is due to the fact that CodeWarrior uses UNSIGNED chars 
   // ..by default. The last ANSI standar C enforecs chars to be 
   // ..SIGNED by default but people on Metrowerks did not pay attention. 
 
   Sassert( (char)‐1 == ‐1 ); 
 
   puts( "Hola" );     // filling instructions 
 
 

Al correr este programa en MSVC, compila bien; bajo Codewarrior compila mal, produciendo el error
anunciado: "expected constant expression".

El mensaje no es exactamente lo que uno quisiera, pero esto es lo más que puede estirarse este truco.

 ROUNDS UP TO A POWER OF 2
A veces hay algoritmos para manejar por ejemplo buffers circulares, que se simplifican sobremanera si
sus tamaños son potencias de dos. Miremos una hipotética rutina de encolar: A la izquierda, genérica
con buffers que pueden tener cualquier tamaño; a la derecha para tamaños de buffer potencias de 2:

#define BUFSIZE 13 //NOT a 2’s power  #define BUFMASK   (BUFSIZE‐1) 
   
     if( n >= size ) return EOF; 
   if( n >= size ) return EOF;     buf[put++] = (uchar)c; //put incr 
   buf[put++] = (uchar)c; //put incr     put &= BUFMASK; //wrap around 
   put = put >= BUFSIZE ?      
     0 : put;  //wrap around     n ++; 
   n ++;     return c & 0xFF; 
   return c & 0xFF; 
 
#define BUFSIZE   16  // 2’s power 

C4-221
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

En la rutina del lado izquierdo, si hay espacio se encola el símbolo y se actualiza (incrementa) el
pointer: *q‐>put ++ = (uchar) c;, si este incremento sobrepasa el final del buffer, se le ajusta el valor
al pointer, con la dirección de la base del buffer (wrap around), de lo contrario se lo deja así: q‐>put = 
q‐>put >= q‐>limit ? q‐>base : q‐>put;. Esta operación requiere una comparación, y si es el caso,
un movimiento de datos.

Ahora miremos al lado derecho, cómo sería la misma rutina si el tamaño del buffer fuera potencia de 2.
Las partes en que difieren las dos rutinas se muestran en negrita. Se define el tamaño del buffer,
#define BUFSIZE  16, que tiene que ser potencia de 2. Se define la máscara, que contiene unos (1’s) en
todos los bits del tamaño del BUFZISE (4 bits): #define BUFMASK (BUFSIZE‐1); como BUFSIZE es 
16, BUFMASK, que vale: BUFSIZE‐1 será 15, que son 4 unos: 1111.

Ahora, corregir el apuntador se convirtió en: q‐>put &= BUFMASK;, es decir, se cambia el apuntador, por
su valor en AND con 1111 (0xF). Así, mientras put toma los valores del 0 al 15, esos mismos, en AND
con 0xF, siguen produciendo valores del 0 al 15; cuando put llegue a 16, el AND lo convierte en 0, y se
repite la secuencia de 0 a 15. El AND con 0xF confina el resultado al rango entre 0 y 15. (NOTA: Hay un
caso aún más particular, cuando la potencia de dos forma frontera con un byte [256] o con un entero
[32768]; en ese caso, si las operaciones se realizan en char o int, el “wrap around” es automático al
incrementar de la última posición [255 o 32767], pues el resultado de esa operación es cero]

Esto está perfecto, si se usan tamaños de buffers (en nuestro ejemplo) que sean potencias de dos puede
emplearse rutinas especialmente ajustadas para que resulten muy eficientes, pero suele ocurrir que quien
escribe las rutinas (de encolar y desencolar en nuestro caso y, en general, las rutinas que empleen este
último método para acelerar el proceso de actualizar los índices de acceso a los arreglos), no es el mismo
usuario o programador del resto del código. ¿Cómo garantiza el programador del paquete de colas, que
el usuario de sus rutinas no escogerá un número BUFSIZE que no sea potencia de 2? Porque es claro que
su método sólo funciona para potencias de dos.

Emplear el Sassert de la sección anterior sería correcto pero ¿cuál expresión, en C, indica si un número
es, o no, potencia de dos? Ese es el propósito del siguiente desarrollo.

Comenzaremos viendo una forma dinámica, por programa, que se calcula en “run time”, a diferencia de
la forma estática, por macros, que se calcula en “compile time”, y que hacia donde luego iremos.
Sabemos que 'nbits', el número de bits de un 'number', es (parteEntera)log2(number)+1; supondremos
también que el cero necesita al menos un bit; de esta manera, 0 bits puede usarse para marcar error. Así,
'number' (global) comienza en uno. 'number' también es global (variable de entrada)

void calculo ( int i )                                         /*()*/ 

   if( i >= number )   return; 
   nbits ++; 
   i <<= 1; 
   i ++; 
   calculo( i ); 

Un ejemplo para ver cómo funciona el algoritmo:

C2-222
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

// q#2‐R.c, Luis G. Uribe C. J30G7  /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */ 
// Answer to Quiz #2, Arquitectura USB, Jun2007  void calculo ( int i )                                     /*()*/ 
// This algorithm gets Log2N. Log2N+1 is the number of bits  { 
// ..needed to represent the number (assume ‘0’ needs 1 bit)     if( i >= number ) 
         return; 
/* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */     nbits ++; 
// Include Files     i <<= 1; 
     i ++; 
#include <stdio.h>     calculo( i ); 
  } 
/* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */   
// Function Prototypes and typedefs  /* =========================================================== */ 
  typedef unsigned long  ulong; 
typedef unsigned long  ulong;   
typedef unsigned char  uchar;  #define    SPACES  7   // number of spaces in a 32 bits string 
  #define    N      32   // max # of bits that xtobinf may process 
char *xtobinf( ulong d, int nbits, ulong mark );  #define    FS     ' '  // field separator; space by default 
void calculo( int i );   
  char *xtobinf ( ulong d, int nbits, ulong mark )           /*()*/ 
/* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */  {  /* xtobinf() */ 
// Macros & defines   
     /* binf.c 7‐Oct‐84, takes a ***LONG*** (d) and makes string with 
#define NBITS(n)     ( sizeof(n) * 8 <= 32 ? sizeof(n) * 8 : 32 )      * ..x ascii 0's and 1's, space separated. Return string address 
// MARK defines where to insert spaces, in a 32 bits string      * xtobin, 14‐may‐88 (UXS.LIB) 
#define    MARK (ulong)(       (1L<<28) | (1L<<24) | (1L<<20)| \      * xtobinf get nbits & MARK from parameter list L‐August‐20‐2007 
                    (1L<<16) | (1L<<12) | (1L<< 8) | (1L<< 4))      */ 
/* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */   
// Global Variables     // ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
     // Local Variables 
int  nbits;   
int  number;     static char buf[ N + 1 + SPACES ];  // to fit 32 bits 
     char *bp = buf; 
/* *********************************************************** */     ulong  msk; 
void main ( void )                                         /*()*/   
{     // ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
   int i;     // Code 
   
   for( i = 0; i < 256; i ++ ) {     nbits = nbits <= N ? nbits : N;     // up to 32 bits 
       nbits  = 1;     for( msk = 1uL << (nbits ‐ 1);  msk;  msk >>= 1 ) { 
       number = i;         *bp++ = (char)( ( d & msk )  !=  0 ) + '0'; 
       calculo( 1 );         if( msk & mark ) { 
       printf( "number = %s (%3d,0x%02X); nbits = %1d\n",             *bp++ = FS; 
                xtobinf( (uchar)i, NBITS( (uchar)i ), MARK ),         } 
                i, i, nbits );     } 
   }     *bp = '\0'; 
}     return  buf; 
   
}  /* xtobinf() */ 

C4-223
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

El programa evalúa el número de bits necesarios para representar los primeros 256 números,
comenzando en cero (for( i = 0; i < 256; i ++ ) {). (NOTA: ¿Recuerdan el problema que vimos
con anterioridad, que fallaba en un for como éste? Aquí no falla, porque la variable de control, i, es un
entero)

Inicializa el número de bits en uno (nbits = 1;), inicializa la variable global number = i; (este ejercicio
es la solución, en C, a un quiz en Assembler del HC08, de la USB, por eso las variables globales…) y
llama nuestra rutina (calculo( 1 );), con parámetro inicial “1”. Luego escribe el número y los bits que
se necesitan para representarlo:
numero = 0000 0000 (  0,0x00); nbits = 1  numero = 0001 1010 ( 26,0x1A); nbits = 5 
numero = 0000 0001 (  1,0x01); nbits = 1  numero = 0001 1011 ( 27,0x1B); nbits = 5 
numero = 0000 0010 (  2,0x02); nbits = 2  numero = 0001 1100 ( 28,0x1C); nbits = 5 
numero = 0000 0011 (  3,0x03); nbits = 2  numero = 0001 1101 ( 29,0x1D); nbits = 5 
numero = 0000 0100 (  4,0x04); nbits = 3  numero = 0001 1110 ( 30,0x1E); nbits = 5 
numero = 0000 0101 (  5,0x05); nbits = 3  numero = 0001 1111 ( 31,0x1F); nbits = 5 
numero = 0000 0110 (  6,0x06); nbits = 3  numero = 0010 0000 ( 32,0x20); nbits = 6 
numero = 0000 0111 (  7,0x07); nbits = 3  numero = 0010 0001 ( 33,0x21); nbits = 6 
numero = 0000 1000 (  8,0x08); nbits = 4   
numero = 0000 1001 (  9,0x09); nbits = 4  ... 
numero = 0000 1010 ( 10,0x0A); nbits = 4   
numero = 0000 1011 ( 11,0x0B); nbits = 4  numero = 0011 1110 ( 62,0x3E); nbits = 6 
numero = 0000 1100 ( 12,0x0C); nbits = 4  numero = 0011 1111 ( 63,0x3F); nbits = 6 
numero = 0000 1101 ( 13,0x0D); nbits = 4  numero = 0100 0000 ( 64,0x40); nbits = 7 
numero = 0000 1110 ( 14,0x0E); nbits = 4  numero = 0100 0001 ( 65,0x41); nbits = 7 
numero = 0000 1111 ( 15,0x0F); nbits = 4   
numero = 0001 0000 ( 16,0x10); nbits = 5  ... 
numero = 0001 0001 ( 17,0x11); nbits = 5   
numero = 0001 0010 ( 18,0x12); nbits = 5  numero = 0111 1110 (126,0x7E); nbits = 7 
numero = 0001 0011 ( 19,0x13); nbits = 5  numero = 0111 1111 (127,0x7F); nbits = 7 
numero = 0001 0100 ( 20,0x14); nbits = 5  numero = 1000 0000 (128,0x80); nbits = 8 
numero = 0001 0101 ( 21,0x15); nbits = 5  numero = 1000 0001 (129,0x81); nbits = 8 
numero = 0001 0110 ( 22,0x16); nbits = 5  ... 
numero = 0001 0111 ( 23,0x17); nbits = 5  numero = 1111 1110 (254,0xFE); nbits = 8 
numero = 0001 1000 ( 24,0x18); nbits = 5  numero = 1111 1111 (255,0xFF); nbits = 8
numero = 0001 1001 ( 25,0x19); nbits = 5 

Lo que nos interesa por el momento no es el número de bits necesarios para representar un número,
sino calcular la potencia de dos que más se le aproxima. Modificando un poco el programa anterior
(ya no es recursivo y tiene más condiciones), vemos que el siguiente procedimiento genera el resultado
que queremos. Se ha separado el programa en un header (q2.h) y el main (q2.c). q2.h es bastante
estándar, incluye el número de bits (#define NBITS(n) ( sizeof(n) * 8 <= 32 ? sizeof(n)*8 : 
32)) y la máscara que identifica los espacios separadores (#define MARK (ulong)((1L<<28)|(1L<<24)| 
(1L<<20)|(1L<<16)|(1L<<12)|(1L<<8)|(1L<<4))) para la función *xtobinf();, encargada de
imprimir un entero en el equivalente binario (los espacios están en la posición 4, 8, 12, 16, 20, 24 y 28, y
pueden cambiarse con solo modificar MARK.

C4-224
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

// q2.h, Luis G. Uribe C. J30G7  /* *********************************************************** */ 
  void main ( void )                                         /*()*/ 
// Include Files  { 
     int i, nbits, number, exp; 
#include <conio.h>   
#include <stdio.h>     for(number = 0; number < 1<<BITS /* i.e. 2^BITS */; number++) { 
         if( number > (1<<(BITS))/2 ) {  // 129...255, for BITS == 8 
/* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */             nbits = exp = 0;    // Error: need > BITS to represent 
// Function Prototypes and typedefs         } 
         else if( number == 0 || number == 1 ) 
typedef unsigned long  ulong;             nbits = exp = 1; 
typedef unsigned char  uchar;         else { 
         //‐‐‐‐ Algorithm to get 'nbits' to represent 'number' ‐‐‐‐ 
char *xtobinf( ulong d, int nbits, ulong mark );             nbits  = i = 1; //'0'needs one bit; else use: nbits=i=0 
             while( i < number ) { 
/* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ for xtobinf() ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */                 nbits ++; 
// MACROS & DEFINES                 i <<= 1;  i |= 1;   // LSL, right introducing 1 
             }  // endwhile             LSL: Logical Shift Left 
#define NBITS(n)     ( sizeof(n) * 8 <= 32 ? sizeof(n) * 8 : 32 )         }  // endif 
   
// MARK defines where to insert spaces, in a 32 bits string     //‐‐‐‐‐ ROUND UP 'NBITS' TO NEXT (LEAST) POWER OF 2 (lp2) ‐‐‐‐ 
#define    MARK (ulong)(       (1L<<28) | (1L<<24) | (1L<<20) | \     // ASSUMPTION: 0 rounds up to 1; i.e.: it is needed one bit at 
                    (1L<<16) | (1L<<12) | (1L<< 8) | (1L<< 4) )     // ..least to represent 0 (others make 0 round up to 0) 
     // ‐ If number is already 2's power use it; else use next number. 
     //   2, for example, has 2 bits; 1<<(2‐1) is 2; so use 2. 
     //   3 also has 2 bits; 1<<(2‐1) != 3, use 1<<(2):4 (next to 3) 
     // 
// q2.c, Luis G. Uribe C. L03S7     // ASSUMPTIONS: log2(0) == 0; Represent ERROR_LOG as ‐1. 
   
// Algorithm to print 'nbits', ammount of bits needed to represent         if( nbits > 1 ) { 
// ..a 'number'; round up 'nbits' to 'exp', least power of 2 to             if( ( exp = 1<<nbits‐1 ) != number ) { 
// ..hold the 'number' (lp2), and (int)Log2 of the number too.                 exp = 1<<(nbits); 
//             } 
// NOTE: 'nbits', the # of bits of a 'number' == log2(number)+1;         } 
// ..So, (integer part of)log2(number) == 'nbits'‐1         printf( "number = %s (%3d,0x%02X); nbits = %3d, " 
//                 "exp_lp2 = %3d, Log2 = %3d\n", 
//ASSUMPTION: Need 1 bit at list to represent #0; others use 0 bits                  xtobinf((uchar)number, NBITS((uchar)number ),MARK), 
                  number, number, nbits, exp, nbits ? nbits ‐ 1 : 0); 
/* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */     }   // endfor 
// Include Files & DEFINES  } 
   
#include "q2.h"   
  /* =========================================================== */ 
#define BITS     8   // number of bits of numbers to be evaluated  char *xtobinf ( ulong d, int nbits, ulong mark )           /*()*/ 
  { 
   /* xtobinf() */ 
 
   // SEE THIS ROUTINE IN THE PRECEEDING PROGRAM, ABOVE 
 
}  /* xtobinf() */ 

C4-225
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

El programa imprime el ‘number’ (binario, decimal y hexadecimal: =0000 0000( 0,0x00)), ‘nbits’, la
próxima potencia de dos, ‘exp_lp2’ y el Log2, para los primeros 256 números, comenzando en 0
(#define  BITS  8). Supone que se necesita al menos un bit para representar el número cero (otros
autores asumen que el cero necesita cero bits).

El ‘for’: for(  number  =  0;  number  <  1<<BITS  /*  i.e.  2^BITS  */;  number++  )  { 
es estándar; una curiosidad es la forma como representa el límite superior (number < 1<<BITS, o 2^8).

Anticipa que los números mayores a la mitad del rango no pueden representarse con el número de bits
(BITS) indicado: if( number > (1<<(BITS))/2 ) { nbits = exp = 0;. También maneja de manera
separada (fuera del for) el número ‘0’ y el ‘1’ (else if( N==0 || N==1 )  nbits = exp = 1;).

La parte genérica comienza obteniendo primero los 'nbits' necesarios para representar el 


'number', suponiendo un mínimo de un bit (nbits = i = 1;), y aplica el mismo algoritmo que
vimos en el programa anterior, en la página de arriba, sólo que no emplea recursión:
while( i < number ) { nbits ++; i <<= 1;  i |= 1;   // logical shift left, LSL, right introducing 1.

Luego se obtiene el redondeo (ROUND UP 'NBITS' TO NEXT (LEAST) POWER OF 2 (lp2)). Las suposiciones


son: 0 redondea a 1; si un número ya es potencia de 2, se lo usa, de lo contrario se usa la siguiente
potencia de dos. Por ejemplo, 2 tiene 2 bits, así que 1<<(2‐1) is 2; por tanto se usa el 2. En cambio, el
3 también tiene 3 bits, pero como 1<<(2‐1) es distinto de 3, se usa 4. La última suposición está con
respecto a: log2(0) == 0;.

Todo lo recientemente dicho, tomando el 2 y el 3 como ejemplos, puede expresarse así:


       if( nbits > 1 ) { 
           if( ( exp = 1<<nbits‐1 ) != number ) { 
               exp = 1<<(nbits); 
           } 
       } 
 
N=0000 0000(  0,0x00);bits=1,lp2=  1,Log2=0  N=0010 0000( 32,0x20);bits=6,lp2= 32,Log2=5 
N=0000 0001(  1,0x01);bits=1,lp2=  1,Log2=0  N=0010 0001( 33,0x21);bits=6,lp2= 64,Log2=5 
N=0000 0010(  2,0x02);bits=2,lp2=  2,Log2=1  ... 
N=0000 0011(  3,0x03);bits=2,lp2=  4,Log2=1  N=0011 1111( 63,0x3F);bits=6,lp2= 64,Log2=5 
N=0000 0100(  4,0x04);bits=3,lp2=  4,Log2=2  N=0100 0000( 64,0x40);bits=7,lp2= 64,Log2=6 
...  N=0100 0001( 65,0x41);bits=7,lp2=128,Log2=6 
N=0000 0111(  7,0x07);bits=3,lp2=  8,Log2=2  ... 
N=0000 1000(  8,0x08);bits=4,lp2=  8,Log2=3  N=0111 1111(127,0x7F);bits=7,lp2=128,Log2=6 
N=0000 1001(  9,0x09);bits=4,lp2= 16,Log2=3  N=1000 0000(128,0x80);bits=8,lp2=128,Log2=7 
...  N=1000 0001(129,0x81);bits=0,lp2=  0,Log2=0 
N=0000 1111( 15,0x0F);bits=4,lp2= 16,Log2=3  N=1000 0010(130,0x82);bits=0,lp2=  0,Log2=0 
N=0001 0000( 16,0x10);bits=5,lp2= 16,Log2=4  ... 
N=0001 0001( 17,0x11);bits=5,lp2= 32,Log2=4  N=1111 1110(254,0xFE);bits=0,lp2=  0,Log2=0 
...  N=1111 1111(255,0xFF);bits=0,lp2=  0,Log2=0 
N=0001 1111( 31,0x1F);bits=5,lp2= 32,Log2=4  ...

C4-226
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Si lo único que pretendemos es obtener la potencia de dos que más se le aproxima a un número,
podemos simplificar el programa anterior y dedicarnos sólo a eso. La rutina principal puede escribirse
de otra forma. A diferencia de los ejemplos que le anteceden, éste supone que cero no necesita bits para
representarse (se representa con cero bits). Aplica, además, hasta unsigned long, así:

/* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */ 
/* Round up to a power of 2. */ 
 
ulong lp2 ( ulong x ) 

   ‐‐x; 
   x |= x >> 1; 
   x |= x >> 2; 
   x |= x >> 4; 
   x |= x >> 8; 
   x |= x >>16; 
   return ++x; 

Para ver cómo funciona, hice un ejemplo sólo de 4 bits (>>1 y >>2 únicamente):

init: 0000 ( 0,0x0)  =================== 
‐‐x:  1111 (15,0xF)  init: 0101 ( 5,0x5) 
>>1:  1111 (15,0xF)  ‐‐x:  0100 ( 4,0x4) 
>>2:  1111 (15,0xF)  >>1:  0110 ( 6,0x6) 
++x   0000 ( 0,0x0)  >>2:  0111 ( 7,0x7) 
===================  ++x   1000 ( 8,0x8) 
init: 0001 ( 1,0x1)  =================== 
‐‐x:  0000 ( 0,0x0)  init: 0110 ( 6,0x6) 
>>1:  0000 ( 0,0x0)  ‐‐x:  0101 ( 5,0x5) 
>>2:  0000 ( 0,0x0)  >>1:  0111 ( 7,0x7) 
++x   0001 ( 1,0x1)  >>2:  0111 ( 7,0x7) 
===================  ++x   1000 ( 8,0x8) 
init: 0010 ( 2,0x2)  =================== 
‐‐x:  0001 ( 1,0x1)  init: 0111 ( 7,0x7) 
>>1:  0001 ( 1,0x1)  ‐‐x:  0110 ( 6,0x6) 
>>2:  0001 ( 1,0x1)  >>1:  0111 ( 7,0x7) 
++x   0010 ( 2,0x2)  >>2:  0111 ( 7,0x7) 
===================  ++x   1000 ( 8,0x8) 
init: 0011 ( 3,0x3)  =================== 
‐‐x:  0010 ( 2,0x2)  init: 1000 ( 8,0x8) 
>>1:  0011 ( 3,0x3)  ‐‐x:  0111 ( 7,0x7) 
>>2:  0011 ( 3,0x3)  >>1:  0111 ( 7,0x7) 
++x   0100 ( 4,0x4)  >>2:  0111 ( 7,0x7) 
===================  ++x   1000 ( 8,0x8) 
init: 0100 ( 4,0x4)  =================== 
‐‐x:  0011 ( 3,0x3)  Error for x = 0x9: need more than4 bits 
>>1:  0011 ( 3,0x3) 
>>2:  0011 ( 3,0x3) 
++x   0100 ( 4,0x4) 

C4-227
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Todo lo anterior está muy bien, cuando se desea calcular los valores mencionados de manera
programática (en run time), pero para un static assert no sirve. Lo que se necesita es una macro que
calcule, en “compile time”, la potencia de dos que más se le aproxima a un número.

Aquí presento el programa anterior en forma de macro (lp2Macro.c):

Tomen aliento…

#define lp2(x) (((((((x)‐1|((x)‐1)>>1)|((x)‐1|((x)‐1)>>1)>>2)         |\ 
                   (((x)‐1|((x)‐1)>>1)|((x)‐1|((x)‐1)>>1)>>2)>>4)     |\ 
                  ((((x)‐1|((x)‐1)>>1)|((x)‐1|((x)‐1)>>1)>>2)         |\ 
                   (((x)‐1|((x)‐1)>>1)|((x)‐1|((x)‐1)>>1)>>2)>>4)>>8) |\ 
                 (((((x)‐1|((x)‐1)>>1)|((x)‐1|((x)‐1)>>1)>>2)         |\ 
                   (((x)‐1|((x)‐1)>>1)|((x)‐1|((x)‐1)>>1)>>2)>>4)     |\ 
                  ((((x)‐1|((x)‐1)>>1)|((x)‐1|((x)‐1)>>1)>>2)         |\ 
(((x)-1|((x)-1)>>1)|((x)-1|((x)-1)>>1)>>2)>>4)>>8)>>16)+1)

Ahora, para tratar de entender la macro voy a describirla por partes…


#define lp2a_(x)    ((x)‐1) 
#define lp2a_1(x)   (lp2a_(x)>>1) 
#define lp2a1(x)    (lp2a_(x) | lp2a_1(x)) 
#define lp2a1_2(x)  (lp2a1(x)>>2) 
#define lp2a2(x)    (lp2a1(x) | lp2a1_2(x)) 
#define lp2a2_4(x)  (lp2a2(x)>>4) 
#define lp2a4(x)    (lp2a2(x) | lp2a2_4(x)) 
#define lp2a4_8(x)  (lp2a4(x)>>8) 
#define lp2a8(x)    (lp2a4(x) | lp2a4_8(x)) 
#define lp2a8_16(x) (lp2a8(x)>>16) 
#define lp2M(x)     (lp2a8(x) | lp2a8_16(x)) 
 
#define lp2(x)      (lp2M(x)+1) 

Pueden usar cualquiera de las dos, pero una vez obtenida la primera, y visto que funciona, yo usaría esa.
Para probarla, pueden modificar el programa anterior q2.c, incluyendo la macro y agregando en el
printf: lp2( number ); el resto queda igual, así:

    printf( "number=%s(%3d,0x%02X); nbits=%3d, " 
            " exp_lp2=%3d, exp_lp2M=%3d, Log2=%3d\n", 
             xtobinf((uchar)number, NBITS( (uchar)number ), MARK), 
            number, number, nbits, exp, lp2( number ), 
            nbits ? nbits ‐ 1 : 0 ); 

C2-228
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Y, el Sassert() que buscábamos puede escribirse ahora como:

/* 2n‐1V2.c, Luis G. Uribe C., Tuesday, August 28, 2007 */ 
// macro lp2 Rounds up to a power of 2, up to 32 bits 
 
// if Sassert fail print: " expected constant expression" 
#define  Sassert(e)  do{ enum { Sassert__ = 1/(e) }; } while (0) 
 
#define lp2(x) (((((((x)‐1|((x)‐1)>>1)|((x)‐1|((x)‐1)>>1)>>2)         |\ 
                   (((x)‐1|((x)‐1)>>1)|((x)‐1|((x)‐1)>>1)>>2)>>4)     |\ 
                  ((((x)‐1|((x)‐1)>>1)|((x)‐1|((x)‐1)>>1)>>2)         |\ 
                   (((x)‐1|((x)‐1)>>1)|((x)‐1|((x)‐1)>>1)>>2)>>4)>>8) |\ 
                 (((((x)‐1|((x)‐1)>>1)|((x)‐1|((x)‐1)>>1)>>2)         |\ 
                   (((x)‐1|((x)‐1)>>1)|((x)‐1|((x)‐1)>>1)>>2)>>4)     |\ 
                  ((((x)‐1|((x)‐1)>>1)|((x)‐1|((x)‐1)>>1)>>2)         |\ 
(((x)-1|((x)-1)>>1)|((x)-1|((x)-1)>>1)>>2)>>4)>>8)>>16)+1)
 
#include <stdio.h> 
 
/* =============================================================== */ 
void main( void ) 

 
#define TST 100  // ensayar con 128, 255, 256... 
 
   Sassert( TST == lp2( TST ) );  // si TST es potencia de 2 
   printf( "Size is %u\n", lp2( TST ) ); 
 
}

Desde luego, la macro ‘lp2’ debe ir en un include file, para ocultarla.

 PROGRAMACIÓN POR REGLAS


Analicen el siguiente código, que es autoexplicativo, según presumo:

C4-229
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

// rules02a.c, Luis G. Uribe C., M04J2007. Coding by the Rules...  // ..scenery over speed and, YES: I am a pilot. THE PROGRAM ABORTS! 
//  // ..This case is NOT covered by our rules... 
//                 PARADIGMS IN MODERN PROGRAMMING   
//  /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */ 
// Some real life problems may be programmed accordingly to rules  // Include Files 
// ..used to define diverse circumstances and the actions that we   
// ..must do. Some times we may include Tables, and look‐up table  #include <assert.h>    // do NOT #define NDEBUG to disable asserts: 
// ..routines to model our code like in event driven programming  #undef assert          // THIS will disable asserts BUT continue to  
// ..(similar as combinatorial digital circuits; there we would use  #define assert(x)  (x) // .. execute the code passed to them!!! 
// ..ROMs to store the tables). But some times the tables could be  #include <stdio.h> 
// ..very large, and not so easy to store them in our scarce Flash  #include <stdlib.h> 
// ..resources...  #include <ctype.h> 
//   
// The following example will show how to deal with this rules in  /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */ 
// .."C" language. We have an ‐input section to read all external  // Standard Typedefs 
// ..information used by the rules; ‐then we apply the rules,   
// ..‐verify the system consistency, as depicted bellow, ‐and  #undef FALSE       // Some of our booleans are 3 valued variables: 
// ..finally perform some actions, following the rules...  #undef TRUE        // ..True, False, and UNKNOW: not already defined 
//   
// A very big concern should be to *Warrant* the CONSISTENCY of the  typedef enum { FALSE, TRUE, UNKNOWN } bool; 
// ..rules; i.e: ALL CASES MUST BE COVERED. French Ariane‐5 space   
// ..rocket blew up because a condition existed that was not covered  /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */ 
// ..by the rules. We use here 'assert(verify_rules())' to detect  // Defines 
// ..any inconsistencies, that will appear as "no decisions made"   
// ..based on the rules. But ALL cases/ranges must be TESTED in the  #define  SPEED_HIGH    200 
// ..bench, to see if the assert fires under any circumstances.  #define  SPEED_MEDIUM  100 
// ..Asserts are NOT a runtime/production solutions: They abort the  #define  SPEED_LOW      60 
// ..process (and the Ariane will blow up!)   
//  #define  BUF_SIZE        6    // 'gets' represents a security breach 
// NOTE: The nature of this problem does not reside inside the code;                                // ..Space to hold: 300<CR><LF><0> max 
// ..it belongs to the external specifications... See that, no   
// ..matter how good you code a program, it will fail badly to work  /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */ 
// ..properly if the specs it mimic are all wrong. This is the  // Function Prototypes 
// ..reason why you must postpone writing code, the most that it is   
// ..possible.  bool rules( void ); 
//  bool verify_rules( void ); 
// The solution is to WARRANT THAT ALL CASES ARE COVERED.   
//  /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */ 
// See that one could take some default action if the verify routine  // External Variables Definition; make up the rules 
// ..detects "no action defined", but you MUST be very confident on   
// ..your decisions in this matter.  int  av_speed;         // kph 
//   
// In the Ariane‐5, the default action was to abort the program (as  // NOTE: In small embedded systems you should avoid 'enums' because 
// ..in here), under the assumption that the back‐up computer would  // ..    they define integers (2 bytes), instead of chars or bits! 
// ..take over, and solve the problem. The second computer began to  // ..    that would preserve more your scarcely memory resources 
// ..work, indeed, to enface the same problem!, because it was not a   
// ..hardware malfunction; they were mere inconsistent rules that  bool like_scenery,     // this is up to the user to decide 
// ..did not cover all cases and not covered such input data       is_pilot,         // ...and this 
// ..combination.   
//       // ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
// As an example, we have tolerated inconsistencies in this program.       fly,              // depends on "calculated" average speed 
// ..Try and run the it with: 100 kph, 1 hour, NOT: prefer       fly_commercial,   // if you must FLY, and you are NOT a pilot 

C4-230
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

     fly_cessna,       // if you must FLY, you ARE a pilot, LIKE the         drive             = 
                       // ..scenery & AVE. SPEED  <=  SPEED_MEDIUM         drive_m_cycle     = 
     fly_jet,          // if you must FLY, are a pilot         drive_car         = 
                       // ..and the ave. speed is <= SPEED_HIGH kph         impossible_speed  =   UNKNOWN; 
   
     // ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐         test_rules_assert = test_verify_rules_assert = FALSE; 
     drive,            // drive, not fly, for ave. speed<= SPEED_LOW   
     drive_m_cycle,    // TRUE if you must DRIVE and LIKE scenery         // ========================================================== 
                       // 0: you must DRIVE but DON'T like scenery         // 2) This mimics DATA ACQ portion of Real Time systems 
     drive_car,        // drive a car if you should drive (not fly)   
                       // ..and won't use a motor cycle         // ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
         // Distance 
     // ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐   
     impossible_speed; // for calculated average speeds > SPEED_HIGH         printf( "How far are you going (kilometers)? " ); 
         gets( buff );          // 'gets' represents a SECURITY BREACH 
         distance = atoi( buff ); 
bool test_rules_assert,        // this variables used for testing   
     test_verify_rules_assert; // ..purposes only         // ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
         // Time. Evaluate average speed, av_speed 
   
/* ************************************************************** */         printf( "How much time do you have for the trip (hours)? " ); 
void main ( void )                                            /*()*/         gets( buff ); 
{         assert( time = atoi( buff ) ); 
   // ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐         av_speed = distance / time;    // Internally calculated value 
   // Local Variables Definition   
   // ..NOTE: Buffers should be static or dynamically allocated         // ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
   // ..(malloc), to keep them away from the STACK!         // Pleasure or business? 
   
   int  distance,              // rounded to kilometers         printf( "Do you prefer scenery over speed? (y/N)? " ); 
        time;                  // rounded to hours         gets( buff ); 
         like_scenery = ( tolower( buff[ 0 ] ) == 'y' ); 
   static char buff[BUF_SIZE]; // to accept users' input responses   
         // ‐‐‐‐‐‐‐‐‐‐‐‐‐‐ only for debugging purposes: 
   // ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐         test_rules_assert = ( buff[ 0 ] == 'Y' );  // 'Y' trigger var 
   // Present program, then loop for ever (Press Ctrl‐C to finish)   
         // ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
   printf( " I am programmed to help you with your"         // Are you a pilot by yourself? 
           " traveling plans (press ^C to finish)" );   
   printf( "\n======================================"         printf( "Are you a pilot? (y/N)? " ); 
             "======================================\n\n" );         gets( buff ); 
         is_pilot = ( tolower( buff[ 0 ] ) == 'y' ); 
   while( TRUE ) {     // This 'while' mimics the ever lasting loop   
                       // ..normally found in all embedded systems         // ‐‐‐‐‐‐‐‐‐‐‐‐‐‐ only for debugging purposes: 
       // ==========================================================         test_verify_rules_assert = ( buff[ 0 ] == 'Y' );  // 'Y' 
       // 1) Always init variables dynamically, inside the loop   
         // ========================================================== 
       like_scenery      =         // 3) Apply Rules with the recently acquired external data 
       is_pilot          =         // .. Abort program if rules does NOT verify 
       fly               =   
       fly_commercial    =         assert( rules() );             // ASSERTS: NOT INTENDED TO BE 
       fly_cessna        =         assert( verify_rules() );       // ..USED ON FINAL PRODUCTS 
       fly_jet           =   

C4-231
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

     // ..final value of the variable will DEPEND ON THE ORDER of the 
       // ==========================================================     // ..rules. The one that fires first prevents the other from 
       // 4) Perform some Actions! (This is what they pay us for!!)     // ..firing. You must be aware of this behavior... Note that you 
     // ..may reformulate the rules, in such a manner to stop one 
       if( impossible_speed == TRUE )     // ..decision from being reevaluated later. 
          printf("\nAv. speed (%d) is impossible: more than %d k/h",     // 
                  av_speed, SPEED_HIGH );     // NOTE: In some cases there could be the possibility for the 
     // ..evaluating loop not to end. We include 'safe', a safety 
       if( fly_commercial == TRUE )     // ..counter to take this in account 
           printf( "\nFly commercial." );   
     /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */ 
       if( fly_cessna == TRUE )     // Defines (these are globals...) 
           printf( "\nRent a cessna and fly low." );   
     #define  SAFE  10u    // Max nmbr of iterations through eval loop 
       if( fly_jet == TRUE )   
           printf( "\nRent a Jet and fly high." );     // ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
     // Local Variables Definition 
       if( drive_m_cycle == TRUE )   
          printf("\nTake your motorcycle and ride the back roads.");     bool evaluating    = TRUE;      // Continue on the decision loop 
     unsigned char safe = SAFE + 1;  // Limit number of iterations 
       if( drive_car == TRUE )   
           printf( "\nThere's nothing for it but to drive a car." );     // ‐‐‐‐‐‐‐‐‐‐‐‐‐‐ only for debugging purposes: 
     if( test_rules_assert ) 
      printf("\n‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐\n");         safe = 1; 
   
   }   // endWhile     // ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
     // Main evaluation loop 
}  /* main() */   
     while( evaluating  &&  ‐‐safe ) { 
         evaluating = FALSE;         // Set‐up loop break by default 
/* ============================================================== */   
bool rules ( void )                                           /*()*/         // ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
{         // Dependencies on impossible_speed 
   // Some problems may be seen as a set of inputs used to choose a   
   // ..set of outputs (pure combinatorial, as in digital circuits).         if( impossible_speed == TRUE ) { // then all output variables 
   // ..But in other cases, some outputs may depend on previously             fly_commercial = FALSE;      // ..shall be set to FALSE 
   // ..evaluated outputs. In this case, the evaluation must be             fly_cessna     = FALSE; 
   // ..integrated into a loop, that cycles if in the last iteration             fly_jet        = FALSE; 
   // ..some values were changed, that could imply new changes in             drive_m_cycle  = FALSE; 
   // ..results already evaluated.             drive_car      = FALSE; 
   //   
   // STRATEGY: use 'evaluating'= TRUE to force loop cycling. Inside             break;              // this rule ends 'while' immediately 
   // ..the loop, begin assuming 'evaluating' to be FALSE, and turn         } 
   // ..'evaluating' TRUE if some variables have been changed.   
   // ..This insures that the module will repeat until it exhaust         // ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
   // ..all changes.         // Dependencies on av_speed 
   //   
   // We must prevent rules that have fired in a previous iteration         if( av_speed > SPEED_HIGH && impossible_speed == UNKNOWN ) { 
   // ..from firing again, which would cause the function to loop             impossible_speed = TRUE;    // now var may be reevaluated 
   // ..endlessly. This is accomplished using variables that are             evaluating = TRUE;          // continue in the while loop 
   // ..three‐valued (TRUE, FALSE and UNKNOWN), initialized to         } 
   // ..UNKNOWN. Now, shall two rules affect the same variable, the   

C4-232
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

       if( av_speed > SPEED_LOW && fly == UNKNOWN ) {             evaluating    = TRUE; 
           fly        = TRUE;         } 
           evaluating = TRUE;   
       }     } /* endwhile */ 
       if( av_speed <= SPEED_LOW && drive == UNKNOWN ) {   
           drive      = TRUE;     if( safe ) 
           evaluating = TRUE;         return TRUE; 
       }     return FALSE; 
   
       // ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐  }  /* rules() */ 
       // Should I fly? If so: commercial, cessna or jet?   
   
       if(    fly == TRUE && is_pilot == FALSE    
           && fly_commercial == UNKNOWN ) {   
  /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */ 
           fly_commercial = TRUE;  bool verify_rules ( void )                                    /*()*/ 
           evaluating     = TRUE;  { 
       }     // CRITERIA: Some action must be taken so, at least one output 
       if(   fly == TRUE && is_pilot == TRUE && like_scenery == TRUE     // ..variable should take a TRUE value. Note that 'NOT TRUE' 
           && av_speed <= SPEED_MEDIUM && fly_cessna == UNKNOWN ) {     // ..is NOT same as FALSE, due to the UNKNOWN value. 
     // 
           fly_cessna = TRUE;     // In other circumstances, it could be a failure if more than one 
           evaluating = TRUE;     // ..action is fired by the rules. Not this case..., 
       }   
     // ‐‐‐‐‐‐‐‐‐‐‐‐‐‐ only for debugging purposes: 
       if(    fly == TRUE && is_pilot == TRUE     if( test_verify_rules_assert ) 
           && SPEED_MEDIUM < av_speed && av_speed <= SPEED_HIGH         return FALSE;       // bad 
           && fly_jet == UNKNOWN ) {   
     if(    impossible_speed != TRUE && fly_commercial != TRUE 
           fly_jet    = TRUE;          && fly_cessna       != TRUE && fly_jet        != TRUE 
           evaluating = TRUE;         && drive_m_cycle    != TRUE && drive_car      != TRUE ) 
       }   
         return FALSE;       // bad: no one action was activated 
       // ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐   
       // should I drive instead? And, if so, car or motorcycle?     return TRUE;        // good: one or more actions were activated 
   
       if(    drive == TRUE && drive_m_cycle == FALSE  }  /* verify_rules() */
           && drive_car == UNKNOWN ) { 
 
           drive_car  = TRUE;  
           evaluating = TRUE; 
       } 
       if(    drive == TRUE && like_scenery == TRUE 
           && drive_m_cycle == UNKNOWN ) { 
 
           drive_m_cycle = TRUE;  
           evaluating    = TRUE; 
       } 
       if(    drive == TRUE && like_scenery == FALSE 
           && drive_m_cycle == UNKNOWN ) { 
 
           drive_m_cycle = FALSE;  

C4-233
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

La Programación por Reglas va en el sentido de separar la Política de los Mecanismos. Este código no
está tan nítidamente dividido como el de la animación ASCII que vimos al principio, pero se le
aproxima bastante.

Algunos comentarios en relación al programa: La forma que se estila para deshabilitar los asserts, una
vez que el programa ha sido depurado es, como ya hemos dicho, incluir un #define NDEBUG  antes del
<assert.h>. Sin embargo, a veces, uno incluye código que debe ejecutarse tanto si se está depurando el
programa como si ya está en operación. No se debe andar editando el programa cuando ya
funciona, pues con alta probabilidad LO HECHARÁ A PERDER, DESPUÉS DE “DEBUGEADO”.

Recomiendo emplear la siguiente estrategia en este caso: En vez del #define NDEBUG, cuando ya no
desee los asserts, incluya las siguientes DOS LÍNEAS de código, debajo del #include <assert.h>: 
 
#undef assert          // THIS will disable asserts BUT continue to  
#define assert(x)  (x) // ...execute the code passed to them!!! 

Se ha redefinido la llamada a assert, incluyéndole un parámetro: assert(x), simplemente para lograr la


ejecución del código identificado por dicho parámetro: (x).

Note también la definición preferida de los valores booleanos, que se han resaltado en este código,
porque se está empleando un tercer valor: UNKNOWN. Primero se los “borra” (#undef  FALSE), por si
estuvieran definidos con anterioridad (en algún include file, por ejemplo). Luego se los define con tres
valores: typedef enum { FALSE, TRUE, UNKNOWN } bool;

Durante la definición de parámetros se hace un comentario en el código: Que 'gets' represents a 


security breach. Esta función está desaprobado (“deprecated”), porque es el sitio por donde más
aprovechan los piratas para irrumpir en el código de los demás. Es debido a que 'gets' no valida que la
cantidad de información que se le suministra, esté confinada al buffer en el que la está leyendo. Si uno
define un buffer de 10 posiciones, y el usuario le proporciona 100, o 10.000 letras, o más, la información
va a quedar almacenada en sitios que no le pertenecen, y el programa va a operar mal, o abortar.

Es preferible emplear fgets(), uno de cuyos parámetros es el tamaño máximo que el sistema va a
permitir pasar a nuestro buffer. De esa manera estamos protegidos. Note que en los ejercicios anteriores
donde he usado 'gets', la información va a llegar por el teclado, y el sistema operativo limita la entrada
al tamaño que hemos definido para nuestro buffer. En todo caso, si el intruso logra “redirigir” la
entrada para tomarla desde un archivo, el tamaño del buffer ya no seguirá protegido por el sistema...

Se menciona también que los sistemas embebidos deben evitar el uso de 'enums', porque C los define
como enteros, y éstos suelen ser 2 bytes hasta en las máquinas más pequeñas…

En el mismo orden de ideas, definir booleanos como enteros es un desperdicio de memoria. Hay que
tratar de declarar campos de bits y definirlos allí (bit fields). En nuestro ejemplo actual, se necesitan 2
bits por cada booleano, y como la idea es hacer una presentación del tema de Reglas, no hemos puesto
objeción al empleo de este tipo de booleanos, pero esté avisado.

C4-234
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Pregunta: ¿Por qué se coloca static  char  buff[BUF_SIZE];? Porque, si no es ‘static’, será
automático, y las variables automáticas emplean espacio en el stack, que suele ser escaso, sobre todo en
microcontroladores. Definirlo como ‘static’ hace que su espacio se tome de otra parte (el “heap”), que
no compromete el stack. ¿Por qué no se puso global, si tampoco las variables globales ocupan stack?
Porque hay que hacer el máximo posible por ocultar las variables (y las estructuras de datos, en
general) de unas rutinas, de las demás funciones, para eliminar engranajes entre ellas.

Observe que, luego de leer algunas variables, las pasamos por “assert”: assert(time= atoi(buff)). De
esta forma garantizamos que se cumpla con ciertas condiciones. Recuerde que los “assert” NO van a
dejarse para el programa en producción (ya que abortan la operación del programa, en caso de
falla); lo que se suele hacer, en caso de querer validar la entrada que el operador nos suministra, es
establecer una rutina de validación, que probablemente repita la solicitud de entrada de información, en
caso de detectar alguna anomalía.

Abortar un programa en la cara del usuario, solo porque éste introdujo un valor
inválido, no es muy amable por parte del programador...

Por eso se coloca una advertencia bien grande:

       assert( rules() );             // ASSERTS: NOT INTENDED TO BE 
       assert( verify_rules() );       // ..USED ON FINAL PRODUCTION 

Fíjense cómo se llamó a la rutina que procesa las reglas: rules(), y cómo se verifica su consistencia:
verify_rules()

Más adelante se hace la advertencia de que, en ciertas condiciones, puede darse el caso de que una rutina
de evaluación, que se repite para recalcular ciertos valores con algunos otros que también han sido
calculados ahí, nunca termine. Es por esto que hemos incluido un contador:

#define  SAFE  10u    // Max number of iterations through eval loop.

C4-235
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

 ANTI REBOTE (DEBOUNCING)


Los contactos electromecánicos de teclados y otras entradas a nuestros circuitos digitales, como los
relés, ejecutan varias conexiones y separaciones (rebotes) cuando los oprimimos, y a veces también al
momento de abrirlos; el tiempo entre comenzar a actuar, hasta poder decir que ya operó, puede ir desde
menos de 100 nanosegundos hasta 50 milisegundos, siendo una figura comercial común: Menos de 10
milisegundos (si sus interruptores rebotan por más de 16 milisegundos, ¡deséchelos!).

Algunos switches tienen problema solo cuando cierran; otros, cuando abren, y algunos en ambos casos.
Como de ellos hay gran cantidad de clases: DPDT (Double Pole, Double “Throw” [doble “polo”,
doble conmutación; es decir, hay un contacto galvánico en la posición cerrado y otro en la posición
abierto]), SPDT (Single Pole, Double “Throw” [un “polo”, doble conmutación; es decir, hay un
contacto galvánico en la posición cerrado, que se abre al hacer la conmutación para la posición
inactiva]), DPST, SPST, etc.), hay que cuidarse del rebote tanto al cerrar como al abrir.

Hay dos criterios si la solución es circuital; 1) emplear un flip-flop Set-Reset sin reloj (biestable “Ecless-
Jordan”, o “latch” S-R [Set-Reset]), lo cual requiere que el interruptor tenga 3 salidas, una en el medio,
que se conecta a tierra, y las otras dos, una que hace contacto cuando el interruptor está “abierto” y la
otra que hace conexión cuando lo cerramos (SPDT). 2) usar interruptores más baratos, que sólo tienen
2 terminales (SPST): Se coloca un filtro pasabajos, RC, y un Schmitt-trigger (dispositivo con histéresis).
Note que la circuitería externa (RC y Schmitt-trigger) puede llegar a ser una alternativa más costosa que
utilizar un SPST; sin embargo, el “costo” escondido es que el SPST utiliza dos (2) contactos de la lógica,
en tanto que la otra aproximación usa uno sólo. Cuando trabajamos con microcontroladores o FPGAs,
los pines del chip son el recurso más escaso (ésta es la razón por la cual, en ciertos
microcontroladores, un mismo pin puede emplearse como entrada digital, o salida, o entrada
analógica, o terminal de comunicaciones seriales, o comparador, o generador de pulsos PWM, o entrada
del cristal, u oscilador externo... En el chip caben todos eso recursos, pero pines no hay)

Cuando tenemos un microcontrolador, se tratará de maximizar el uso del software a fin de mantener al
mínimo el hardware externo; por eso es común que el interruptor SPST se conecte directamente al
micro, sin filtros pasabajos ni Schmitt-triggers. (Nota: Si las señales vienen “del campo”, y traen ruido,
por ejemplo, de una planta industrial, u otras anomalías, como voltajes de modo común, permanentes o
inducidos, etc., es indispensable adecuar dichas señales antes de entrar a la circuitería; pero esta etapa es
anterior a todo lo que estamos mencionando, y muy probablemente ¡nada de eso se pueda arreglar
dentro del microcontrolador!, y hay que tenerlo en cuenta también cuando se usan “latches”)

Hay varias estrategias que suelen aplicarse por software. Comencemos diciendo que (casi) nunca debe
colocarse un SPST sin filtraje electrónico externo, a una línea de interrupciones (IRQ, KB). Eso suele
complicar el diseño, pues los rebotes interrumpen repetidas veces, y si se incluye un temporizador por
software, que a su vez emplea interrupciones, hay que estar pendientes de desactivar las interrupciones
del switch en cuestión, rehabilitar las interrupciones generales hasta que la rutina de interrupciones del
temporizador señale que ha expirado el lapso programado, y proceder a dejar todo tal como estaba.

C4-236
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

La opción más sencilla es leer, en el momento que corresponda (sin que el switch interrumpa…), el
estado del interruptor de entrada, y en caso de detectar alguna transición, activar un temporizador de 20
milisegundos. Solo al expirar el lapso se vuelve a leer el interruptor, y si ha mantenido el valor que
ocasionó la entrada a la rutina de debouncing, se acepta la transición; de lo contrario se asume que no
hubo ninguna, y se continúa en el sitio apropiado del programa, según el problema. Algo así como:
   Forever { 
       // Here inputPin was 0. If inputPin == 1; there has been a change 
 
       if( inputPin() == 1 ) { 
           WaitMS_on( 0, 20 );     // debounce on close 
           if( inputPin() == 1 ) } // inputPin really is closed (ON) 
              Exec_What_You_Do_If_InputPin is_ON(); 
               Wait( inputPin == 0 ); 
               WaitMS_on( 0, 20 ); // debounce on open too... 
           }   // else, inputPin had a glitch; ignore it and continue 
       }else { // inputPin is OFF 
           Exec_What_You_Do_Whenever_InputPin is_OFF(); 
       } 
   }   // endForever 
Nota: Al terminar la actividad que se ejecuta cada vez que hay un cambio a “1”, la máquina de estados
debería esperar que la entrada retorne a 0; (lo que se hace con: Wait(inputPin == 0)) porque de lo
contrario, al repetir el ciclo, volvería a ser cierto el: if(inputPin()  ==  1){, pero esa activación del
usuario ¡ya fue atendida! La secuencia es: Esperar la activación del interruptor por parte del usuario;
cuando esto sucede, ejecutar lo que se le solicitó y, luego, esperar a que el usuario retire el dedo del
control para volver a comenzar la secuencia.
Otra cosa: Se pensaría que mientras se ejecuta la espera final, Wait( inputPin == 0 ); y se da la vuelta,
pueden perderse activaciones del interruptor por parte del usuario. Hay que resaltar que los tiempos de
reacción de una persona (la capacidad de activar, desactivar, y volver a activar uno u otro de los
botones) son del orden de los centenares de milisegundos (nadie oprime un botón más de 10 veces
por segundo; no, si no se está jugando con el teclado). Veinte milisegundos es poco en relación a
nuestra velocidad de respuesta.

 DEBOUNCING Y MÁQUINAS DE ESTADO


Solo como ilustración se repite el ejemplo, en forma de Máquina de Estados:
enum STATES { WaitInputPin_1, DebounceOn_1,        case TestInputPinIsReally_1: 
              TestInputPinIsReally_1,          if( inputPin == 1 ) {  // really “1” 
              WaitInputPinReturnTo_0 };              Exec_Code_For_InputPin_1(); 
state = WaitInputPin_1;              state = WaitInputPinReturnTo_0; 
Forever {          }else state = WaitInputPin_1; //glitch 
    switch( state ) {        break;         
      case WaitInputPin_1:        case WaitInputPinReturnTo_0: 
        if(inputPin == 1) state= DebounceOn_1;          if( inputPin == 0 ) { 
        else Exec_Code_For_InputPin_0();              WaitMS_on(0, 20); // debounce “0” 
      break;                      state = WaitInputPin_1; 
      case DebounceOn_1:          } 
        WaitMS_on( 0, 20 ); // debounce on 1        break;         
        state = TestInputPinIsReally_1;      }   // endswitch 
      break;          }   //endForever 
         

C4-237
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Esta es una de varias maneras de implementar la Máquina de Estados, que son una alternativa
excelente para codificar este y otros tipos de problemas. Se ha exagerado la cantidad de estados (en
realidad, no hacen falta tantos para este ejemplo), a fin de mostrar cómo sería la mecánica.
Ahora bien: En una aplicación en la que hay otras cosas por hacer, y donde el microcontrolador no
puede darse el lujo de sentarse a perder el tiempo esperando a que se elimine el rebote (WaitMS_on(0,20)),
el programa suele correr en un ciclo dentro del cual, una actividad es preguntar por una bandera que
indica si el temporizador ya terminó. La presentación de una rutina así puede resultar muy oscurecida
con sus detalles, máxime si son dos o más los interruptores sujetos a debouncing. Es decir, andar
pendientes de la lógica del programa, dirigida por los interruptores, y a la vez tener que incluir la rutina
de debouncing, puede crear un programa bastante retorcido.
Para que se vea cómo resultaría un código así, anexo el programa de la siguiente página.
Una alternativa para mejorar la presentación y el manejo del problema de mezclar el debouncing con la
lógica del programa consiste en que sea la misma rutina temporizadora, que supuestamente corre por
interrupciones, la que realice en el trasfondo (background) la eliminación del rebote. Así, habrá una o
varias posiciones de memoria (variables) cuyos bits serán una copia “limpia” de los verdaderos
interruptores. Cuando el programa lee una variable, ya no tiene que lidiar con el problema de
debouncing. Fíjense que si se le quita el manejo del rebote al programa original, éste quede muy simple:
   Forever { 
       // Here, you know inputPin is 0. If inputPin == 1; there 
       // ..has been a change 
       if( inputPin() == 1 ) { 
Exec_What_You_Do_If_InputPin_ON();
           Wait( inputPin == 0 ); 
           } 
       }else { // inputPin is OFF 
Exec_What_You_Do_If_InputPin_OFF();
       } 
   }   // endForever 

La solución, con forma de Máquina de Estados:


enum STATES { WaitInputPin_1,  
              WaitInputPinReturnTo_0 }; 
state = WaitInputPin_1; 
Forever { 
    switch( state ) { 
      case WaitInputPin_1: 
        if( inputPin == 1 ) { 
            Exec_Code_For_InputPin_1(); 
            state = WaitInputPinReturnTo_0; 
        }else Exec_Code_For_InputPin_0(); 
      break; 
 
      case WaitInputPinReturnTo_0: 
        if( inputPin == 0 ) { 
            state = WaitInputPin_1; 
        } 
      break; 
    }   // endswitch 
}   //endForever 

C4-238
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

 
// fil‐tst.c, Luis G. Uribe C., D09S7     Forever { 
// Código para mostrar las complicaciones de un programa cuando         // Here, you know inputPin == 0; if inputPin == 1; 
//..se mezcla la lógica principal, y el debouncing.         // ..there has been a change 
   
// ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐         switch( state ) { 
// Las siguientes son definiciones FICTICIAS, que ayudan en           case WaitInputPin_1: 
// ..la verificación de la operación del programa.             if( inputPin == 1 ) { 
// ..Desde el debugger se puede cambiar inputPin = 1, para simular                 state = Debounce_1; 
// ..una entrada; t = 1 simula que ya expiró el timer (Timeout(t))             }else { 
// Las dos rutinas Exec_ sólo llaman a ‘kbhit()’, para poder                 Exec_What_You_Do_If_InputPin_OFF(); 
// ..detener el programa con Ctrl‐C, si se entra en un loop             } 
// ..infinito.           break; 
   
#define SetimerMS( t, T ) (t=0)           case Debounce_1: 
#define Timeout( t )   (t)             SetimerMS( t, 20 ); 
#define Exec_What_You_Do_If_InputPin_ON()  kbhit()             state = TestInputPinIsReally_1; 
#define Exec_What_You_Do_If_InputPin_OFF() kbhit()           break; 
   
// ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐         
// Otras definiciones útiles     case TestInputPinIsReally_1: 
             if( Timeout( t ) ) { 
#define TRUE  1                 if( inputPin == 1 ) {   // really ON 
#define FALSE 0                     Exec_What_You_Do_If_InputPin_ON(); 
#define Forever    for(;;)                     state = WaitInputPinReturnsTo_0; 
                 }else { 
void main( void )                     state = WaitInputPin_1;    // ignore glitch 
{                 } 
   int  t = 0;             } 
   int  state, inputPin = 0;           break; 
   enum STATES { WaitInputPin_1, Debounce_1,   
                 TestInputPinIsReally_1,           case WaitInputPinReturnsTo_0: 
                 WaitInputPinReturnsTo_0,             if( inputPin == 0 ) { 
                 WaitTimeoutForInputPin_0 };                 SetimerMS( t, 20 );     // debounce on open too... 
   state = WaitInputPin_1;                 state = WaitTimeoutForInputPin_0; 
             } 
         break; 
 
         case WaitTimeoutForInputPin_0: 
           if( Timeout( t ) ) { 
               state = WaitInputPin_1;    // ignore glitch 
           } 
         break; 
 
       }   // endswitch 
 
   }   // endForever 

 
 

C4-239
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Como ya se dijo, #define SetimerMS( t, T ) (t=0) cambia la función del subsistema de timers, que


ya hemos usado con anterioridad, a fin de permitirnos manipular el código con el debugger y así
demostrar su funcionamiento. En este caso, (t=0) sirve para inicializar la rutina de Timeout( t ). Esta,
a su vez, devuelve el valor “t”; por tanto, para simular que ya expiró el timer, basta con cambiar desde
el debugger el valor de “t”.

Se definen las constantes enum STATES, dándoles a los estados nombres que sean muy sugestivos
de la actividad que en ellos habrá de realizarse. El Forever es bastante parecido al programa
anterior, excepto que en vez de los WaitMS_on( 0, 20 ); que bloquean el procesador, se usa ahora
SetimerMS(t,20); acompañada luego por el if( Timeout( t ) ) {.

 DEBOUNCING DE VARIOS BITS


Ya que se ha visto la importancia de colocar en la rutina de interrupciones
del timer, la funcionalidad de eliminar el rebote de varios interruptores a la
vez, y suministrar una visión “virtual” de estos bits de entrada, “limpios”
(sin rebote), pongamos como ejemplo el debouncing de los 4 bits
mostrados en la figura; note que se activan bajo y los supondremos
conectados a la parte inferior del puerto de entrada inputPins4.
int Get4Switches ( void ) {                      /*()*/ 
   int LocalVirtualSwitches=0x000F;// 00000000 00001111 
   for( x = 0; x < 5; x ++ ) { 
       LocalVirtualSwitches &= ~inputPins4; 
       WaitMS_on( 0, 4 ); 
   }   // endFor 
   return LocalVirtualSwitches & ~inputPins4; 

En primer lugar hay que hacer notar que se inicializan los bit en “unos” (LocalVirtualSwitches  = 
0x000F;), ya que la activación externa es con ceros. Aquí se han consideran solo los 4 bits de la derecha.
Dentro del ciclo se leen los 4 bits externos, inputPins4; se los niega para convertir a “unos” los que
están activos (~inputPins4), y se hace and (&) con el valor previo de LocalVirtualSwitches
(LocalVirtualSwitches &= ~inputPins4;); luego se espera 4 ms, repitiendo el lazo 5 veces, para un
total de 20 ms. Para producir el resultado se hace un último and: return LocalVirtualSwitches &= 
~inputPins4;, al cual no hay que agregarle un WaitMS_on( 0, 4 ) final. Observe que la variable se
llama LocalVirtualSwitches porque ella no puede ser leída en cualquier momento por otras rutinas,
pues durante los 20 ms. que dura Get4Switches, su contenido es espurio. Debe haber una rutina que
haga: GlobalVirtualSwitches = Get4Switches();
Si las entradas fueran activas en uno, se quitaría el negador:
  LocalVirtualSwitches &= inputPins4;.
Una entrada tiene que mantener su valor, inalterado durante el ciclo completo; o la rutina devuelve un
cero en su posición. Una rutina genérica debería permitir identificar cada bit, con un parámetro, como
activo en 0 o en 1.

C4-240
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

 * (NextState) will become:                                        * 
 *                                                                 * 
 SECUENCIADOR DE EVENTOS,   
 

SOE  
 *     NextState = Filter_AND  |  ( ActualState  &  Filter_OR )    * 
 *                                                                 * 
   *     being:                                                      * 
/* *************************************************************** *   *                                                                 * 
 *                                                                 *   *         Filter_AND:  the AND of all PREVIOUS  NFILTER  bits     * 
 *                   SOE  FILTERING  ALGORITHM                     *   *                      with the current input value               * 
 *                   =========================                     *   *                                                                 * 
 *                                                                 *   *         Filter_OR:   the OR  of all PREVIOUS  NFILTER  bits     * 
 *                                    Luis G. Uribe C, L15E1 D07Y6 *   *                      with the current input value               * 
 *                                                                 *   *                                                                 * 
 *                                                                 *   *         ActualState: Last filter output                         * 
 *     The output will be 0 if it has been 0 for the last  NFILTER *   *                                                                 * 
 *         milliseconds at least                                   *   *         NextState:   Next filter output                         * 
 *                                                                 *   *                                                                 * 
 *     The output will be 1 if it has been 1 for the last  NFILTER *   *                                                                 * 
 *         milliseconds at least                                   *   *     This means:                                                 * 
 *                                                                 *   *                                                                 * 
 *     Otherwise, the output will remain in its actual value       *   *         NextState = 1 if ALL Filter_AND are 1: 1 | ...          * 
 *         (ActualState)                                           *   *         NextState = 0 if ALL Filter_OR  are 0: 0 | ( PS & 0 )   * 
 *                                                                 *   *                                                                 * 
 *                                                                 *   *     Otherwise, some bits are 1  and  some bits are 0, so:       * 
 * FILTER DATA STRUCTURES:                                         *   *                                                                 * 
 * ======================                                          *   *         NextState = ActualState                                 * 
 *                                                                 *   *                                                                 * 
 * We will need the actual  InputData, plus one array of size      *   *                                                                 * 
 * 'NFILTER' (Filter time in milliseconds, NFILTER > 0), to hold   *   * For each one millisecond separated input value, the main        * 
 * the last NFILTER  one millisecond separated input values.       *   * processing loop will be as follows:                             * 
 * Normally, we  process 8/16/32 input bits at a time, so the      *   *                                                                 * 
 * array will be NFILTER bytes (8), words (16) or longs (32)       *   *     // Read next value into 'InputData'; i.e: Filter[ NFILTER ] * 
 *                                                                 *   *                                                                 * 
 * The Data, for any given  NFILTER  size, could be held in a      *   *     For( ( Filter_AND = 0xFFFF, Filter_OR  = 0x0000, j = 0 );   * 
 * matrix of size  ** 'NFILTER + 1' **  with the following layout: *   *          j < NFILTER;  j++ )                                    * 
 *                                                                 *   *                                                                 * 
 * uchar, uint or ulong                                            *   *     // include *ALL* ANDs, ORs, and the required data shifts    * 
 *        Filter[ 0 ],                                             *   *                                                                 * 
 *          Filter[ 1 ],                                           *   *         Filter_AND  &=  Filter[ j ];                            * 
 *          Filter[ 2 ],                                           *   *         Filter_OR   |=  Filter[ j ];                            * 
 *          ...                                                    *   *         Filter[ j ]  =  Filter[ j + 1 ];                        * 
 *          Filter[ NFILTER ‐ 1 ],                                 *   *                                                                 * 
 *        InputData;                   // i.e.: Filter[ NFILTER ]  *   *     Endfor                                                      * 
 *                                                                 *   *                                                                 * 
 *                                                                 *   *     // Output Global Data                                       * 
 * PROCEDURE:                                                      *   *                                                                 * 
 * =========                                                       *   *     Filter_AND = 1: All Ones                                    * 
 *                                                                 *   *     Filter_OR  = 0: All Zeroes                                  * 
 * For any given input value, we will stablish the AND and the OR  *   *                                                                 * 
 * of it with all the last NFILTER stored values. The output value *   *     Filter_AND = 0: One or more Zeroes                          * 

C4-241
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

 *     Filter_OR  = 1: One or more Ones                            *  uint   Values[] = { 
 *                                                                 *  /* t00 */ 0x0182, // xxxx xxxx 1‐‐‐ ‐‐‐‐ 
 *     So: True Table and Karnaugh Map are:                       *   
 *                                                                *  /* t01 ‐ t08 */ 0x0283, 0x0381, 0x0480, 0x0582, 
 *     Filter_AND Filter_OR | NextState                           *                  0x0683, 0x0781, 0x0880, 0x0982, 
 *             0   0        |  0                                  *   
 *             0   1        |  ActualState (Don't change)         *  /* t09 */ 0x1080, // change 1‐‐‐ ‐‐‐‐ in t0 seen in t10, even if it 
 *             1   0        |  Imposible                          *  /* t10 */ 0x1102, // ..changes back to 0: 0‐‐‐ ‐‐1‐ here! 
 *             1   1        |  1                                  *  /* t11 */ 0x2203, // ‐‐‐‐ ‐‐‐1 
 *                                                                *   
 *                                                                *  /* t12 ‐ t19 */ 0x3303, 0x4403, 0x5503, 0x6603, 
 *                  \Filter_AND,Filter_OR                         *                  0x7703, 0x8803, 0x9903, 0xAA03,  
 *                   \         |Filter_AND                        *   
 *       ActualState  \ 00  01 |11  10 |                          *  /* t20 */ 0xBB03, // change 0‐‐‐ ‐‐1‐ on t10 seen here 
 *                     +‐‐‐+‐‐‐+‐‐‐+‐‐‐+                          *  /* t21 */ 0x0102, // seen change ‐‐‐‐ ‐‐‐1 in t11; chg. to ‐‐‐‐ ‐‐‐0 
 *                   0 | 0 | 0 |(1 | ‐)|                          *   
 *                  ‐‐‐+‐‐‐+‐‐‐+‐‐‐+‐‐‐+                          *  /* t22 ‐ t30 */ 0x0206, 0x0300, 0x0402, 0x0506, 
 *       ActualState 1 | 0 |(1 |(1)| ‐)|                          *                  0x0602, 0x0700, 0x0806, 0x0902, 0x1000, 
 *                  ‐‐‐+‐‐‐+‐‐‐+‐‐‐+‐‐‐+                          *   
 *                         |       |                              *  /* t31 */ 0x0102, // seen ‐‐‐‐ ‐‐‐0 value from t21 
 *                         |Filter_OR                             *  /* t32 */ 0x0000 
 *                                                                *       
 *                     MK for NextState                           *  }; 
 *                                                                *   
 *                                                                *  /* ============================================================== */ 
 *     NextState    = Filter_AND  |  ActualState  &  Filter_OR;   *  /* Filter Global Parameter                                        */ 
 *                                                                *   
 *     ChangeInData = ActualState ^  NextState;                   *  #define NFILTER    10      // Filter Milliseconds; CHANGE as needed 
 *                                                                *   
 *     // Set Auxiliary Data                                      *   
 *                                                                *  /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */ 
 *     ActualState  = NextState;                                  *  /* Include Files                                                  */ 
 *                                                                */   
   #include <stdio.h> 
/* ************************************************************** */   
#include "ezc.h"  /* ============================================================== */ 
  /* Soe_Filter Prototype & Private Global Accessible Data;         */ 
ID = "Soe_Tst  Luis G. Uribe C, L15E1 S06Y6: \n"  /* ... *** move this into  "soe_filter.h" ***                     */ 
     "         Soe Filtering Algorithm\n";   
  void Soe_Filter( uint Input ); 
USAGE = "USAGE: Soe_Tst\n";   
  uint   Filter[ NFILTER + 1 ],  // Global data init on 0's by linker 
/* ============================================================== */         NextState,  
/* External Variables                                              */         ChangeInData; 
   
/* 33 input values on this example; must be  >  NFILTER at least. *   
 * In the example values are valid only in the Lower BYTE. Values *  /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */ 
 * on the Upper byte are all spurious                             */  /* Number of Elements on this Example                             */ 
  /*   Following expresion automatically computes de size of the    */ 
/*   data array defined above by the user, for this example       */ 
 
#define    EX_SIZE     ( sizeof( Values ) / sizeof( Values[ 0 ] ) ) 

C4-242
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

  /* ============================================================== */ 
/* ============================================================== */  void   Soe_Filter( uint Input )                               /*()*/ 
void   main( void )  Begin  /* Soe_Filter() */ 
Begin  /* soe_tst.c */   
  /* Returns:                                                       * 
   /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */   *                                                                * 
   /* Local Variables                                             */   * NextState    = Filter_AND  |  ActualState  &  Filter_OR;       * 
   * ChangeInData = ActualState ^  NextState;                       * 
   uint    i;   *                                                                * 
   */ 
   /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */   
   /* Process                                                     */     /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */ 
     /* Local Variables                                             */ 
   puts( _id );   
     static  uint    ActualState = 0; 
   /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */   
   /* For each incomming value, call Soe_Filter()                 */     uint    Filter_AND,  
             Filter_OR,  
   For( i = 0; i < EX_SIZE; i++ )             i; 
       printf( "i = %02u, Input = %04X,", i, Values[ i ] );   
     /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */ 
       Soe_Filter( Values[ i ] );     /* Load read data                                              */ 
   
       printf( " Output = %04X", NextState );     Filter[ NFILTER ] = Input;     // sizeof(Filter) is 'NFILTER + 1' 
       printf( ChangeInData ? ", Change = %04X\n" : "\n",   
               ChangeInData );   
     /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */ 
   Endfor     /* Process each input value through the Filter                 */ 
   
End    /* soe_tst.c */     For( ( Filter_AND = 0xFFFF, Filter_OR  = 0x0000, i = 0 ); 
          i < NFILTER;  i++ ) 
   
       Filter_AND  &=  Filter[ i ]; 
       Filter_OR   |=  Filter[ i ]; 
       Filter[ i ]  =  Filter[ i + 1 ]; 
 
   Endfor 
 
   /* Output Global Data   */ 
 
   NextState    = Filter_AND  |  ActualState  &  Filter_OR; 
   ChangeInData = ActualState ^  NextState; 
 
   /* Set Auxiliary Data   */ 
 
   ActualState  = NextState; 
 
End    /* Soe_Filter() */ 
 
 

C4-243
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

En este ejercicio hay varias cosas interesantes que resaltar. En primer lugar, es un subsistema que operó
en equipos comerciales, supervisando muchos centenares de puntos (1024); la rutina corría cada
milisegundo (la resolución requerida era de 1 ms); si se encontraba alguna diferencia entre el estado
presente y el anterior (algún bit había cambiado), se le hacía un “time stamp”, registrándolo con la
marca de tiempo, a fin de establecer la hora exacta de la ocurrencia de dicho cambio. El proceso
posterior, para almacenar un registro histórico, hacer los reportes correspondientes y demás manejo de
alarmas, etc., es una función de la Unidad Maestra. Para alguno de los protocolos de comunicaciones
que emplearon este subsistema, como el DNP, la clase de datos SOE es nativa; para otros, como el
Modbus, hubo que hacer una expansión de las capacidades en las Maestras, porque la función de
secuenciador de eventos, SOE, no es nativa en Modbus. Sin embargo, la transferencia de todas maneras
resultó muy sencilla, y se escogieron funciones dentro del grupo que los usuarios pueden definir. Esto
no evitó que hubiera que reprogramar la Maestra Modbus.
El objetivo de la rutina SOE es producir una salida que será 0 si la variable digital ha sido 0 continuo
por lo menos durante los últimos NFILTER milisegundos; y producirá un 1 a la salida si la variable
digital ha sido 1 continuo al menos durante los últimos NFILTER milisegundos. De lo contrario la
salida permanecerá en su valor presente.
Las estructuras de información necesarias para apoyar el desarrollo del algoritmo de este filtro son las
siguientes: La entrada actual, InputData, más un arreglo de tamaño 'NFILTER' (Filter time in milliseconds, 
NFILTER > 0), que almacenará los últimos valores de entrada, separados un milisegundo (La cifra de un
milisegundo no es esencial para la operación del filtro; éste puede actuar más lento, o a mayor velocidad
si hay tiempo disponible en la rutina del temporizador en un equipo en particular)
Normalmente se realiza el proceso de 8/16/32 bits a la vez, así que el arreglo será de bytes (8), words (16) 
o  longs  (32). Para cualquier tamaño de NFILTER, la información puede almacenarse en una matriz de
tamaño 'NFILTER + 1', con la siguiente definición:
 uchar, uint or ulong 
        Filter[ 0 ],    // este, al menos, es mandatorio; 
          Filter[ 1 ],  // los demás dependen de la profunidad 
          Filter[ 2 ],  // ..del filtro 
          ... hasta: 
          Filter[ NFILTER ‐ 1 ], // A continuación se almacena: 
        InputData;               // i.e.: Filter[ NFILTER ] 

El procedimiento se expone a continuación: Para cada vector de entrada, se establece el AND  y   el OR
entre él y los últimos NFILTER elementos almacenados; el valor resultante obedece a la siguiente ecuación:

     NextState = Filter_AND  |  ( ActualState  &  Filter_OR ) siendo: 

Filter_AND: el AND de todos los PREVIOS NFILTER bits con el valor de entrada actual,
Filter_OR: el OR de todos los PREVIOS NFILTER bits con el valor de entrada actual;
ActualState: la última salida del filtro, y
NextState:   la siguiente salida del filtro.

De acuerdo a lo anterior, NextState será 1 si TODOS los Filter_AND son 1; NextState será 0 si TODOS los
Filter_OR son 0, y si no, algunos bits serán 1 y algunos serán 0, por lo que: NextState = ActualState.

El procesamiento que se hace cada milisegundo será, entonces:

C4-244
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

  // Read next value into 'InputData'; i.e: Filter[ NFILTER ] 
     For( ( Filter_AND = 0xFFFF, Filter_OR  = 0x0000, i = 0 ); 
          i < NFILTER;  i++ ) 
     // include *ALL* ANDs, ORs, and the required data shifts 
         Filter_AND  &=  Filter[ i ]; 
         Filter_OR   |=  Filter[ i ]; 
         Filter[ i ]  =  Filter[ i + 1 ]; 
     Endfor 
 
Al final del ciclo, las posibilidades de salida (para cada bit) son:
     Filter_AND = 1, para todos unos  en el intervalo NFILTER 
     Filter_OR  = 0, para todos ceros en el intervalo NFILTER 
     Filter_AND = 0, uno o más ceros  en el intervalo NFILTER 
     Filter_OR  = 1, uno o más unos   en el intervalo NFILTER 
 
Pueden representarse mediante una tabla de verdad (para cada bit individual):
    Filter_AND, Filter_OR | NEXTSTATE       
             0   0        |  0 
             0   1        |  ActualState (Don't change) 
             1   0        |  Imposible (don’t care) 
             1   1        |  1 
También pueden representarse las posibilidades mediante un Mapa de Karnaugh, de donde puede
sacarse la ecuación de salida:
                  \Filter_AND,Filter_OR 
                   \         |Filter_AND 
       ActualState  \ 00  01 |11  10 | 
                     +‐‐‐+‐‐‐+‐‐‐+‐‐‐+ 
                   0 | 0 | 0 | 1 | ‐ | 
                  ‐‐‐+‐‐‐+‐‐‐+‐‐‐+‐‐‐+ 
       ActualState 1 | 0 | 1 | 1 | ‐ | 
                  ‐‐‐+‐‐‐+‐‐‐+‐‐‐+‐‐‐+ 
                         |       | 
                         |Filter_OR 
 
                       Z = NextState 
 
     NextState    = Filter_AND  |  ActualState  &  Filter_OR; 
 
     ChangeInData = ActualState ^  NextState; 
 
     // Variable interna, auxiliar: 
     ActualState  = NextState; 

Además de las rutinas hay un programa de prueba. Las secuencias de prueba que han de llevar las
variables han sido estudiadas con mucho cuidado; hay 33 valores de entrada que se comentan a
continuación (note que la cantidad de valores de entrada debe ser mayor que NFILTER para apreciar una
salida):
uint   Values[] = { 
/* t00 */ 0x0182, // xxxx xxxx 1‐‐‐ ‐‐‐‐ (estos son 8 bits: 0x0082. Los 8 bits más altos 
//                                        representan valores de entrada espúreos xxxx xxx) 
/* t01 ‐ t08 */ 0x0283, 0x0381, 0x0480, 0x0582, 
                0x0683, 0x0781, 0x0880, 0x0982, 
 
/* t09 */ 0x1080, // el cambio 1‐‐‐ ‐‐‐‐ en t0 es visto in t10, aún si después 
/* t10 */ 0x1102, // ..se devuelve el cambio a 0: 0‐‐‐ ‐‐1‐ aquí! 
/* t11 */ 0x2203, // ‐‐‐‐ ‐‐‐1 

C4-245
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

/* t12 ‐ t19 */ 0x3303, 0x4403, 0x5503, 0x6603, 
                0x7703, 0x8803, 0x9903, 0xAA03,  
/* t20 */ 0xBB03, // aquí se ve el cambio 0‐‐‐ ‐‐1‐ de t10 
/* t21 */ 0x0102, // aquí se ve el cambio ‐‐‐‐ ‐‐‐1 de t11; chg. to: ‐‐‐‐ ‐‐‐0 
 
/* t22 ‐ t30 */ 0x0206, 0x0300, 0x0402, 0x0506, 
                0x0602, 0x0700, 0x0806, 0x0902, 0x1000, 
/* t31 */ 0x0102, // seen ‐‐‐‐ ‐‐‐0 value from t21 
/* t32 */ 0x0000 
     
El parámetro global del filtro es #define NFILTER    10 (milisegundos), que puede cambiarse a voluntad.
En el programa se anota la información que debería pasarse a un include file "soe_filter.h".

Fíjense cómo el programa calcula el número de elementos con los que va a trabajar: #define  EX_SIZE 
(sizeof(Values)/sizeof(Values[0]));
es el tamaño total de Values, en bytes, dividido en la cantidad de bytes
que mide un elemento, el Values[0].

El resultado de aplicar el algoritmo a ese conjunto de datos es el siguiente:


/* The above input values on this example will produce the following 
 * results: 
 *  
 * Soe_Tst2 Luis G. Uribe C, L15E1: Soe Filtering Algorithm 
 *  
 * i = 00, Input = 0182, Output = 0000 
 * i = 01, Input = 0283, Output = 0000 
 * i = 02, Input = 0381, Output = 0000 
 * i = 03, Input = 0480, Output = 0000 
 * i = 04, Input = 0582, Output = 0000 
 * i = 05, Input = 0683, Output = 0000 
 * i = 06, Input = 0781, Output = 0000 
 * i = 07, Input = 0880, Output = 0000 
 * i = 08, Input = 0982, Output = 0000 
 * i = 09, Input = 1080, Output = 0000 
 * i = 10, Input = 1102, Output = 0080, Change = 0080 
 * i = 11, Input = 2203, Output = 0080 
 * i = 12, Input = 3303, Output = 0080 
 * i = 13, Input = 4403, Output = 0080 
 * i = 14, Input = 5503, Output = 0080 
 * i = 15, Input = 6603, Output = 0080 
 * i = 16, Input = 7703, Output = 0080 
 * i = 17, Input = 8803, Output = 0080 
 * i = 18, Input = 9903, Output = 0080 
 * i = 19, Input = AA03, Output = 0080 
 * i = 20, Input = BB03, Output = 0002, Change = 0082 
 * i = 21, Input = 0102, Output = 0003, Change = 0001 
 * i = 22, Input = 0206, Output = 0003 
 * i = 23, Input = 0300, Output = 0003 
 * i = 24, Input = 0402, Output = 0003 
 * i = 25, Input = 0506, Output = 0003 
 * i = 26, Input = 0602, Output = 0003 
 * i = 27, Input = 0700, Output = 0003 
 * i = 28, Input = 0806, Output = 0003 
 * i = 29, Input = 0902, Output = 0003 
 * i = 30, Input = 1000, Output = 0003 
 * i = 31, Input = 0102, Output = 0002, Change = 0001 
 * i = 32, Input = 0000, Output = 0002 
 *  
 */ 

Solo falta en este código, extraer los valores para los que hubo cambio y agregarles el “time stamp”.

C4-246
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

 BIBLIOGRAFÍA
Hamming, R. W., Coding and Information Theory, 2e, Prentice-Hall, 1986, p. 27

Verhoeff, J., Error Detecting Decimal Codes, Mathematical Centre Tract 29, The Mathematical Centre,
Amsterdam, 1969.

http://www.augustana.ab.ca/~mohrj/algorithms/checkdigit.html, (Jonathan Mohr, 1999)

http://en.dahnielson.com/2006/09/verhoeff.html, Anders Dahnielson

http://mathworld.wolfram.com/DihedralGroupD5.html

http://mathworld.wolfram.com/DihedralGroup.html

C4-247
5
Capítulo
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

MICROCONTROLADORES

“Neglected topics…”

 INTRODUCCIÓN

D
OS puntos de vista opuestos son tradicionales en nuestro ambiente, al momento de focalizar
los objetivos que deben perseguirse en el estudio de la Arquitectura del Computador y sus
a lateres; uno, pretende comprender los virtuosos alcances logrados, cada vez más esotéricos,
y centran su atención en multiprocesadores y multicores, cachés de múltiples niveles y su
coherencia; virtualización, y las profundidades de la segmentación, el pipelining; la ejecución de
instrucciones fuera de secuencia, identificar de registros internos mediante sinónimos, temas todos
esenciales a quienes deseen integrar el plantel de compañías como Intel.

Yo prefiero un enfoque más pragmático, centrado en la utilización que de esa tecnología podemos
hacer, que potencie el estudio de las interfaces de entrada y salida (I/O Interfacing): Hardware y
software; rutinas de interrupción, colas; reentrancia, recursividad y, en nuestro ámbito –que bastante
difiere del Ingeniero de Computación, la programación en tiempo real, “debouncing”, manejo de
secuencias de eventos (SOE), la serialización de sucesos asíncronos, el modelaje de problemas como
Máquinas de Estado; el handshaking entre periféricos, los filtros de entrada y salida (para señales
analógicas, y digitales), el problema del “aliasing” y su solución moderna; fuentes de error de conversión
analógico-digital (en ambos sentidos), estudio de periféricos de comunicación serial, I2C…

No lo tomen a mal; al autor le fascina el tema del diseño de computadoras (fue su tesis de grado) y se
arroba ante la astucia de nuestros tiempos, pero en el aspecto didáctico prefiere el pragmatismo, que le
asigna prelación al uso apropiado de la tecnología, previendo que a muy pocos de nosotros nos
estará dado incursionar en la concepción y desarrollo de tan avanzados sistemas. Si bien es cierto que
trabajando con FPGAs y similares siempre podremos incluir en ellos procesadores especiales, no es
menos real reconocer que la cantidad de problemas que pueden resolverse con un microcontrolador es
altísima. En su vida profesional, nuestros ingenieros enfrentarán 99 proyectos basados en un micro,
contra 1 desarrollo sustentado en FPGA. Yo prefiero enseñar para esos 99.

C5-248
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Debo decir, a vía de ejemplo, que de todos los desarrollos en los que participé durante mi carrera solo
un (1) diseño no se hizo con un microprocesador y requirió hardware especializado (una tarjeta de
conversión ADC, para 32/64 canales, a suficiente velocidad como para hacer tambalear el bus de
entrada y salida del Pentium). Todos los demás proyectos se centraron en un micro que, en mi caso,
siempre fue un 80x86-Pentium, configurado la mayor parte del tiempo como un “Credit Card PC”, por
alrededor de los U.S.$ 100 (un regalo).

Los libros de texto tienden también a soslayar conceptos básicos, importantísimos si las circunstancias
dictan que debamos trabajar con microcontroladores en bajo nivel, lo que suele ocurrir cuando parte de
nuestro desarrollo incluye dispositivos pequeños y económicos, como los de la familia PIC 16Fxxx (el
16F88, por ejemplo). A veces encontramos que el diseñador en realidad desconoce, por ejemplo, la
diferencia entre hacer comparaciones numéricas con cantidades sin signo o entre números en
complemento a dos. Él no distingue muy bien entre el Carry y el Overflow, ni sabe cómo y cuándo (y
por qué) emplear el uno o el otro. Es claro que si trabajamos en lenguajes de alto nivel como el “C”, lo
cual es recomendable siempre que sea posible, el problema pierde relevancia pues el lenguaje y el
compilador se encargan del asunto; si usamos el Assembler del Pentium o del HC08, tampoco es tan
importante porque esos conjuntos de instrucciones son ricos e incluyen códigos especializados para
cada tipo de dato, con y sin signo (signed, unsigned), pero en una buena parte de los diseños es
fundamental diferenciar bien entre estos dos tipos de representación numérica.

La confusión reinante es tan grande a la hora de comprender cabalmente conceptos fundamentales, que
una de las instrucciones más importantes del HC08 (TAP, Transfer Accumulator to Processor Status
Word) tiene esta única anotación en el “CPU08 Central Processor Unit, Reference Manual, CPU08RM/AD,
Rev. 3, 2/2001”, pág. 219:

“Note: The TAP instruction was added to improve testability of the CPU08 and so,
few practical applications of the instruction exist.”
También en el mismo manual, pág. 50:

“In rare cases it may be useful to allow an interrupt routine to be interrupted. However, nesting is
discouraged because it greatly complicates a system and rarely improves system performance.”
El anónimo personaje perpetrador de tan infames párrafos, incluidos en el Manual de Referencia de tan
prestigiosa y avanzada empresa, no tiene ni la menor idea de lo que dice. Uno de los ejercicios que
incluyo en este capítulo está concebido para poder medir tiempos (por interrupciones) ¡dentro de una
rutina de interrupción! (al hacer el debouncing de la entrada “INT” [en su rutina de interrupciones]
empleando el timer [interrupción anidada]). Esto, como se verá, difícilmente puede realizarse sin hacer
caso omiso a los párrafos arriba resaltados.

Para destacar lo profunda que puede ser esta confusión, incluyo directamente desde mi buzón de
correo, correspondencia cursada con los conocidísimos profesores Andrew Tanenbaum y John F.
Wakerly, donde les hago notar falencias graves, de concepto, inaceptables –en el caso de Tanenbaum–
en un libro de Arquitectura del Computador, y sus respuestas reconociendo tales errores:

C5-249
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Caracas, jueves 28 de mayo del 2009

Ref: Prof. Tanenbaum: MIC1 implementation for branches, ARE WRONG!

Je, je... Tanenbaum me contestó:

At 04:37 p.m. 28/05/2009, Andy Tanenbaum wrote:


Mi Correo Original:
I was reviewing your IJVM, both in chapters 4 and 5 (JVM), and I was very surprised
to note that you included conditional branches on Signed operands: IFLT and the like...
But, professor, your Mic-1 hardware only have two condition codes: Z and N.
Even if it is not absolutely impossible to work around this limitations to arrive to a
correct implementation of conditional branches on Signed operands, the Mic-1 microcode for
IFLT takes action based on bit N only..., but you cannot decide only based on this bit:
- You need help from other sources of information, like the Overflow bit (V),
that is missing in your Mic-1... (or need help from another suitable procedures, not used in
the microprogram for IFLT)
So, Mic-1 implementation for Signed conditional branches are wrong.
They only work if you are lucky, and the subtractions employed like "Compare" substitutes
do not produce an overflow condition... something that nobody is in the position to warrant…
Isn’t it?
Being yours an introductory material for Computer Architecture, I think this mistake really is
something that should be reworked and better explained.
We have being using your book by the hundreds each year...

Best regards,

Prof. Luis G. Uribe.


At 04:37 p.m. 28/05/2009, Andy Tanenbaum wrote:

Thank you very much. I'll take a careful look at this when I revise the book.
Interestingly enough, you are the only person to note this in at least 10 years!

Andy Tanenbaum

Y, ahora, los dedos se me mueven solos... para copiarles una respuesta similar, de Wakerly:

Caracas, Jun 30/2006

Hello Prof. Wakerly,

I was reviewing the 4th edition of your Digital Design book, and have some comments to do in
regards to the Manchester coding on Fig. 2-17, pag. 70 of the english version.

It seems to me that this is not exactly the code used in the original Ethernet local area

C5-250
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

networks, as you say in pag. 73, as it was INVERTED:


- a zero encoded as a 1-to-0 transition, and
- a one encoded as a 0-to-1 transition,

as refered in the IEEE 802.3 documentation.

This may put your readers one "NOT Gate" short... 

Same comments apply to the 3th edition.

And you are not alone at all: Prof. Tanenbaum has the same mistake in his Computer
Networks, 4ed.

I wish you the best.

Regards,

Prof. Uribe

Date: Fri, 30 Jun 2006 10:08:48 -0700

Hi Luis,

That is very interesting...

Of course, either "polarity" can be used and get a code with the same properties (pros
and cons), but I went with the first definition that I found in my references when I first
wrote this. As it turns out, I was lucky, and that reference used the same polarity
as the original paper, which was published in 1949, the year of my birth.

But, yes, I see now, the IEEE uses the opposite polarity. They are "wrong" :) .
I should clean up that language to make it more clear for the next one person
out of 100,000 that catches this mistake :) .

In the meantime, if you send me your PayPal account address, I will be glad to send
you US$5 as a reward for being the first to find this error.

El gobierno nunca me dejó hacer efectivos mis 5 dólares... Pero esa es otra historia. Luego,
Wakerly tuvo que regalarme $20 más, por el mismo libro (ejemplar que, a su vez, me había
regalado la editorial Prentice-Hall !!)

Saludos,

Prof. G. Uribe

C5-251
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

 CONDITION CODE REGISTER: C, Z, N Y V


COMPARAR ES RESTAR
Los micros más pequeños ni siquiera incluyen instrucciones para comparar 2 cantidades. Supongamos
que deseamos tomar decisiones del tipo:
A   >   B ,  A   = =   B   y   A   <   B , y las compuestas: A   > =   B ,  A   ! =   B   y   A   < =   B    
en un indefenso microcontrolador como el 16F88, cuyo conjunto de instrucciones es uno en el que
precisamente no figuran operaciones de comparación. Lo primero es notar que este grupo de relaciones
puede reescribirse de la siguiente manera, sin alterar su significado:
A ‐ B   >   0 ,  A ‐ B   = =   0 ,  A ‐ B   < 0 ,  A ‐ B   > =   0 ,  A ‐ B   ! =   0   y   A ‐ B   < =   0   
El cambio es conveniente porque en un procesador siempre podemos restar, bien sea mediante el
correspondiente código de substracción (casi todos en la tierra lo tienen: hasta el PIC !), o sumando al
minuendo el negativo del sustraendo. Además, todos los computadores tienen un indicativo, Z (cero):
un bit del registro CCR (Condition Code Register), PSW (Processor Status Word), Flags o similar.
Cuando Z vale, 1 significa que el resultado de la última operación fue cero; de lo contrario, Z vale 0. El
bit Z resuelve directamente las comparaciones por igualdad: A ‐ B   = =   0     y     A ‐ B   ! =   0 .

Para establecer las demás relaciones hace falta más información. Ahora, piense que la resta indicada en
 tiene diferentes significados si las dos cantidades involucradas tienen signo o no, y que la mecánica
involucrada en ambos casos es diferente. Por eso el resto del desarrollo lo estableceremos en dos partes,
una para cantidades que no tienen signo (ordinales, índices, direcciones de memoria), y otra para las que
sí tienen signo (cardinales, variables físicas, cuentas contables), y que están codificadas en complemento
a dos (2´s complement).

La nomenclatura convencional emplea las siguientes relaciones (en inglés), que se expresan primero para
cantidades SIN signo, y se hace un parangón con las informaciones CON signo:

 UNSIGNED  SIGNED
 Higher than (HI)   Greater than (GT) 
 Higher than or Same (HIS)   Greater than or Equal to (GE) 
 Lower than (LO)   Less than (LT) 
 Lower than or Same (LOS)   Less than or Equal to (LE) 
 Same (EQ)   Equal (EQ) 
 Different (NE)   Not Equal (NE) 

Se emplea “superior” (higher) para “unsigned”, y “mayor” (greater) para “signed”. Algo similar ocurre
con “inferior” (lower) para “unsigned”, y “menor” (less) para “signed”. Es fundamental no confundir
la terminología, o los resultados pueden ser erróneos. Si emplea “C”, las relaciones se escriben igual
para ambos tipos de datos (A < B, por ejemplo); el compilador sabe si usar una comparación con signo
o sin signo, de acuerdo al “type” asociado a las variables: signed o unsigned. En un programa en “C”,
uno normalmente lee siempre “A < B” como; “A menor que B”, sin importar el tipo…

C5-252
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

UNSIGNED
Necesitamos al menos tres ejemplos para mostrar cómo funciona la comparación, o resta, al determinar

A ‐ B   >   0 ,  A ‐ B   = =   0 ,  A ‐ B   <   0  
Los otros casos son combinaciones lógicas que incluyen mezclas de las anteriores (mayor o igual, etc).
Por simplicidad emplearemos cantidades que puedan representarse en dos (2) bits.
1) Comparar 2 con 1; ver cómo se comporta la resta y qué produce que nos indique que 2 > 1:

    Resta   
Borrows  0  ‐1       
    1  0  +2   
  ‐  0  1  ‐1   
    0  1  +1  Z == 0 

Lo primero es decir que no hubo borrow final (Borrow == 0 en la columna izquierda, la del tercer
bit). Si A >= B no hay que pedir prestado nada a la izquierda y, por tanto, B == 0 indica que A >= B.
Como el resultado no fue cero (fue +1), entonces el bit Z vale 0. Esta bandera descarta que A sea igual a
B; por tanto entre las dos condiciones, Borrow == 0 y Z == 0, indican a las claras que A > B.

Hay que indicar también que todos los procesadores modernos codifican los enteros y las
cantidades de punto fijo, en complemento a 2, y los que tienen código de operación para la resta,
internamente la ejecutan sumando as minuendo el negativo (en complemento a 2) del sustraendo.
¿Cómo podemos estar hablando de representar números negativos, si acabamos de decir que estamos
en la sección en que las cantidades no poseen signo (unsigned)? Bueno; la contradicción consiste en
que, si no hubiera restas, no habría necesidad de signos. El signo se necesitó en la aritmética cuando
comenzaron a hacerse restas, en donde a una cierta cantidad se le trataba de quitar una más grande.
Obviamente eso no es posible si no se incluye el signo. Así que, si hay instrucción de resta, hay signo
involucrado, queramos o no.

En este caso, lo que el hardware ejecuta en realidad, en vez de una resta, es la siguiente suma:

2’s complement Add 
Carries  1         
    1  0  +2   
  +  1  1  +(‐1) 
    0  1  +1  Z == 0 

Observe que si se usan sin modificar los mismos “full-adders” para hacer la suma del negativo del
sustraendo: +(‐1), el resultado no es el Borrow, sino el Carry final, QUE ES EL NEGADO DEL
BORROW que resultó al hacer la resta a mano. Por eso se dice que los circuitos sumadores completos
entregan: Carry/Not_Borrow (C/~B).

Ahora el indicativo de que 2 > 1, es entonces que C == 1 y Z == 0.

C5-253
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

2) Comparar 2 con 2; ver cómo se comporta la resta y qué produce que nos indica que 2 == 2:
    Resta   
Borrows  0         
    1  0  +2   
  ‐  1  0  ‐2   
    0  0  +0  Z == 1 

Hay que indicar que aquí tampoco hubo borrow final (Borrow == 0 en la columna izquierda, la del
tercer bit). Es obvio que si A  ==  B, no es necesario pedir prestado nada a la izquierda y, por tanto,
Borrow == 0. Sin embargo, lo que en realidad indica que A == B es el hecho de que Z == 1. Eso es
suficiente.
Otra vez vemos que lo que el hardware ejecuta es la siguiente suma, en vez de la resta señalada:
2’s complement Add 
Carries  1         
    1  0  +2   
  +  1  0  +(‐2) 
    0  0  +0  Z == 1 

C == 1 (negado del Borrow de la tabla anterior), pero es Z == 1 lo que señala que las dos cantidades
son iguales.

3) Por último, comparar 2 con 3; determinar cómo la resta nos indica que 2 < 3:
    Resta   
Borrows  ‐1  ‐1       
    1  0  +2   
  ‐  1  1  ‐3   
    1  1  ‐1  Z == 0 

En primer lugar vemos que ahora sí hubo borrow final (Borrow == 1 en la columna izquierda, la del
tercer bit). Si A < B sí hay que pedir prestado a la columna de la izquierda y, por tanto, B == 1 indica
que A < B. Como el resultado no fue cero (fue ‐1), entonces el bit Z vale 0, pero esta bandera no se
necesita, ya que siempre que A sea menor que B, el que Borrow == 1, indican a las claras que A < B
(A menor que B).
Como señalamos antes, en este caso, unsigned o no unsigned, el resultado es negativo. Así que
una manera que algunos usan para ver la última fila de la tabla anterior, es como si los números en
realidad tuvieran tres (3) bits en la representación (habíamos dicho que eran solo dos), y que la tercera
columna (la del Borrow) corresponde al signo (que era positivo, o cero, en todas partes, menos ahora,
que dio una cantidad negativa…) Y podemos constatar que el negativo de 11 es 01, es decir, que el
resultado fue menos 1. (Salvo que habíamos asumido que los números… no tenían signo.)
Resumamos el caso para comparación de números SIN signo, diciendo que:
Si el resultado es negativo (Borrow == 1), entonces A < B.
Y si el resultado es positivo (Borrow == 0), entonces A > B o A == B, y el discriminador entre
esas dos (2) posibilidades ahora es:

Si Z == 1,  A == B; si Z == 0, entonces A > B.

C5-254
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Para ver otra vez lo que el hardware realiza (una suma, en vez de la resta señalada), tenemos:
2’s complement Add 
Carries           
    1  0  +2   
  +  0  1  +(‐3) 
    1  1  ‐1  Z == 0 

C == 0 (negado del Borrow de la tabla anterior); eso indica, per se, que A < B.

Estas condiciones pueden incorporarse en un Mapa de Karnaugh (MK); como el Borrow no existe,
sino el Carry, según acabamos de indicar, las variables que definen las entradas al MK son C y Z:

Z  Z 
 
C    0  1 

 
0  A > B  A == B 

C  1  A < B  ‐‐X‐‐ 

Así, las ecuaciones que resultan para comparar números SIN signo, son las siguientes:
1) A > B = C’ * Z’ 

2) A == B = Z 

3) A != B = Z’ 

4) A < B = C 

5) A >= B = C’ 

6) A <= B = C + Z 

C5-255
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Una nota adicional, en relación a la familia PIC; Microchip suministra el Carry negado (el Borrow
original de nuestros ejercicios); por tanto, en el Mapa de Karnaugh para los microcontroladores 16F88,
por ejemplo, hay que invertir las dos filas del MK de arriba. El manual de Microchip indica que, para la
operación de resta, el Carry asume el valor de lo que ellos denominan: Signo del resultado (exactamente
C’ de nuestro desarrollo). Intel, Motorola, IBM (mainframes), DEC, y todos los demás procesadores
que conozco, excepto el PIC, utilizan la tabla que acabamos de desarrollar. Desde luego, en las
ecuaciones hay que intercambiar C por C’ para el PIC.

SIGNED
Establezcamos las relaciones necesarias para A ‐ B   >   0 ,  A ‐ B   = =   0 ,  A ‐ B   <   0 , cuando la
información tiene signo. Los ejemplos los representaremos con 3 bits, siendo el más de la izquierda el
del signo. La información, como ya se dijo, se representa en complemento a dos. En este caso haremos
directamente lo que el hardware realiza, es decir, en vez de restar, se suma al minuendo el negativo del
sustraendo: 

1) Comparar 2 con 1; ver cómo se comporta la resta y qué produce que nos indique que 2 > 1:
2’s complement Add 
  S: 
       
Sign 
Carries   1         
  0  1  0  +2   
+  1  1  1  +(‐1) 
0  0  0  1  +1  Z == 0 

Ahora sí, la tercera columna es el signo, dicho con propiedad. Si el resultado de la resta es S == 0
(positivo), significa que A >= B. Como Z == 0, necesariamente la respuesta es que A > B.

O sea que el indicativo de que 2 > 1 es, entonces, que S == 0  y  Z==0.

Comparemos ‐2 con ‐3; tendría que dar que ‐2 > ‐3:


2’s complement Add 
  S: 
       
Sign 
Carries   1         
  1  1  0  ‐2   
+  0  1  1  ‐(‐3): +3 
1  0  0  1  +1  Z == 0 

S == 0  y  Z== 0 indican de que ‐2 >‐1.

Uno más: Comparemos 1 con ‐1; tendría que dar que 1 > ‐1:
2’s complement Add 
  S: 
       
Sign 
Carries   1         
  0  0  1  +1   
+  0  0  1  ‐(‐1): +1 
1  0  1  0  +2  Z == 0 

S == 0  y  Z == 0 indican de que 1 >‐1.

C5-256
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Ahora, cuando trabajamos con números con signo, puede ocurrir un fenómeno nuevo. Si sumamos
dos números positivos, y el resultado es negativo, o si sumamos dos números negativos, y el resultado
es positivo, esto es indicativo de que se produjo una cifra tal, que no puede representarse con el número
de bits asignados (normalmente, 8, 16, 32, 64, en las máquinas actuales). Este inconveniente se
denomina OVerflow, y en casi todos los micros (excepto en el PIC), existe una variable V, que vale 1 si
hubo overflow, lo que indica además, que el signo actual del resultado está mal. Esto es conveniente,
porque si tenemos el signo N, y sabemos que está mal (V == 1), entonces podemos averiguar cuál era el
signo correcto del resultado, que es lo que nos indica si A  >  B o no. La corrección se hace así: Si
V == 0, S == N; pero si V == 1, S == N’ (lo contrario de lo que tenemos).
La ecuación para S, en términos de N (signo obtenido del resultado, sin corregir), y el V, es la siguiente:
S = N ^ V  (^ es XOR) 

Y A > B = S’ *  Z’, que se corrige como: A > B = (N ^ V) ’ * Z’


Un ejemplo con Overflow: Comparemos 3 con ‐3; tendría que dar que 3 > ‐3:
2’s complement Add 
  S: 
       
Sign 
Carries   1  1       
  0  1  1  +3   
+  0  1  1  ‐(‐3): +3 
0  1  1  0  ‐2  Z == 0 

V == 1 (suma de dos números positivos, con resultado negativo; 3+3 dio ‐2 cuando ha debido ser
+6, que no puede representarse en dos bits de mantisa y uno de signo)
Así que (N ^ V) ’ * Z’ = (1 ^ 1) ’ * Z’ = 1; por tanto, 3>‐3.
Note que el resultado real (‐6) no nos interesa para la comparación; sólo el signo del resultado, que ya
sabemos cómo corregirlo.
2) Comparar 2 con 2; ver cómo se comporta la resta y qué produce que nos indica que 2 == 2:
2’s complement Add 
  S: 
       
Sign 
Carries   1         
  0  1  0  +2   
+  1  1  0  +(‐2) 
1  0  0  0  +0  Z == 1 

Como en el caso unsigned, lo importante aquí es que Z  ==  1; por tanto las dos cantidades son
iguales. Cuando Z == 1, no miramos el signo (que siempre es positivo); por tanto no hay que corregir
nada (no hay overflow cuando el resultado es cero). Al comparar por igualdad, restando, da lo
mismo que los números tengan signo o no.
3) Por último, comparar 2 con 3; determinar cómo la resta nos indica que 2 < 3:
2’s complement Add 
  S: 
       
Sign 
Carries           
  0  1  0  +2   
+  1  0  1  ‐(+3): +(‐3) 
0  1  1  1  ‐1  Z == 0 

A < B = S, o sea que corregido queda:  A < B = N ^ V 

C5-257
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

En nuestro ejemplo: N==1; V == 0; por tanto S == 1 ^ 0 = 1; por tanto, 2 < 3.

Estas condiciones pueden incorporarse en un Mapa de Karnaugh (MK); las variables que definen
las entradas al MK son S y Z:

Z  Z 
 
S    0  1 

 
0  A > B  A == B 

S  1  A < B  ‐‐X‐‐ 

Y S = N ^ V (^ es XOR)

Así, las ecuaciones que resultan para comparar números CON signo, son las siguientes:
7) A >B  = (N ^ V)’ * Z’ 

8) A == B = Z 

9) A != B = Z’ 

10) A < B = (N ^ V) 

11) A >= B = (N ^ V)’ 

12) A <= B = (N ^ V) + Z 

Los PIC solo tienen el Carry (negado) y el Z; por tanto, para realizar comparaciones con cantidades
signed hay que averiguar N, el signo del resultado (que probablemente queda en el registro W, y por
tanto es sencillo de encontrar: es el bit7 de W) y hay que calcular V, lo cual es un poco más complejo:
V = (SA  ^ SB)’ * (SA  ^ SR), que es la manera de expresar, en álgebra booleana, que el signo de A es
igual al de B y distinto del signo del Resultado.

UNSIGNED REVISITED
El caso Unsigned es el más simple; aún así, de las ecuaciones de arriba se deduce que a veces el
programador tiene que mirar más de un bit, dependiendo de cuál comparación está haciendo. Hay una
forma de intercambiar los operandos, de manera de tener que analizar solo UN bit; esto resulta muy
conveniente, y este tema es ignorado normalmente en los libros de texto.

C5-258
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

Vimos que los resultados de restar “A ‐ B” pueden sintetizarse en un Mapa de Karnaugh (MK) como el
que sigue; dijimos que nuestro libro de referencia de PICs está MUY equivocado en cuanto a definir las
condiciones para las 6 relaciones comparativas que pueden establecerse entre dos variables (no que no
funcionen, pero el programador tiene que trabajar el doble o el triple si ha de seguir sus indicaciones)

El MK lo obtuvimos haciendo restas de A  ‐  B para valores en los que A resultaba: mayor, igual o
menor que B. Hicimos notar que el Borrow (lo que “Presto”), tal como lo define Microchip, y que
para la resta se almacena en el bit C (Carry), está al revés de la gran mayoría de los computadores (lo
que significa que a la tabla hay que invertirle las posiciones de C,  0  y  1, para los demás
microcomputadores).

Del MK pueden obtenerse qué condiciones definen las posibles relaciones comparativas entre números
unsigned:

; “A‐B” Establish AF > BF, AF = BF or AF < BF:: 
; “STATUS” FLAGS C(b0) and Z(b2) FOR SUBTRACTION (i.e: compare) are: 

;                |   Z 
;     C\Z   0    |   1 
;       +‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐+   KARNAUGH Map 
;       | A<B(W) |        |   Simple: 
;      0|   LO   |   ‐‐‐  |     BEQ (Z = 1), BHI (C = 0 if cmp B,A), 
;    ‐‐‐+‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐+     .. BLO (C = 0) 
;      1| A>B(W) | A=B(W) |   COMPOSED: 
;    C  |   HI   |   EQ   |     BNE (Z = 0), BLOS (C = 1 if cmp B,A), 
;    ‐‐‐+‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐+     .. BHIS (C = 1) 

; (This information is NOT so clearly shown as above, in Microchip's 
;  ..literature...) 
; (BAD, VERY BAD in: "Microcontrolador PIC16F84 Desarrollo de 
;  .. Proyectos, 2° ed. 2006, Palacios, Remiro, López", pag. 123...) 
Lo que no vimos en clase es que las seis (6) relaciones mostradas, en realidad son solo tres (3); las otras
son el complemento de las primeras:

   Main  | Complement 
=========+=========== 
 A >  B  | A <= B 
 A >= B  | A <  B 
 
 A == B  | A != B 
La igualdad y desigualdad la define el bit Z (si al restar dos cantidades, el resultado es cero [Z == 1], es
porque son iguales; lo contrario [Z == 0] significa que son distintas (!=)

De las relaciones principales de mayor, mayor igual, vemos del MK que A > B se define cuando:
C == 1 & Z == 0. Si en vez de obtener: A ‐ B, hacemos la resta intercambiando las variables: B ‐ A,
ahora A > B se convierte en el complemento, y está definido, del MK, como C == 0.

Asimismo, A <= B resulta en el MK original como: ~C | Z, pero si cambiamos las variables al restar, se
convierte en C == 1.

C5-259
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

; “B‐A”;  
; “STATUS” FLAGS C(b0) and Z(b2) FOR SUBTRACTION (i.e: compare) are: 

;                |   Z 
;     C\Z   0    |   1 
;       +‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐+ 
;       |  A>B   |        | 
;      0|   HI   |   ‐‐‐  | 
;    ‐‐‐+‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐+ 
;      1|  A<B   | A=B(W) | 
;    C  |   LO   |   EQ   | 
;    ‐‐‐+‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐+ 
 
De esta manera, “manque les pese a los autores del libro de referencia”, basta siempre con mirar
uno solo de los bits C, Z para determinar las 6 posibles relaciones comparativas entre números. Eso
es lo que está programado en la librería adjunta: “Branches`.inc”

 COMPARACIONES PARA EL PIC


La siguiente librería implementa con MACROS todos los saltos, con signo y sin signo, para la familia
PIC 16Fxxx, pues el método nativo es muy primitivo, incluye comparaciones sin signo, y también con
signo, a pesar de que el PIC no tiene bit de overflow, V. El método empleado se explica en detalle en la
librería, y consiste en convertir los números de complemento a dos, a exceso 2^n; en esta representación
los números pasan de tener signo a no tenerlo, pero obtienen entre ellos una relación de “Alto a Bajo”
(Higher to Low) que es la misma que tenían de “Mayor a Menor” (Greater to Less). Al aplicarle a los
números así representados, las operaciones de comparación entre números sin signo, se producen
resultados Higher to Low que se corresponden a los que han debido dar (Greater to Less). Además, el
cambio de representación se logra de una manera muy simple: negando el bit del signo.

C5-260
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

   NOLIST  ;  
; ALL 'BRANCHES.INC', PROF. LUIS G. URIBE C. C10M2010 (V2.0A)  ; THE STATUS FLAGS C & Z FOR *SUBTRACTION* (A‐B: COMPARE A VS. B): 
;  ; (INDICATED FOR 'A‐B', EXCEPT WHEN NOTED TO BE REVERSED: 'B‐A' <<< ) 
; ALL "COMPARE" POSSIBILITIES, SIGNED AND UNSIGNED, FOR PIC16FXXX,  ; "W" STANDS FOR WORKING REGISTER IN MICROCHIP'S PICS 
; .. MICROCHIP FAMILY OF MICROCONTROLERS  ; 
;  ;                |   Z 
; ** CAUTION **: SOME MACROS IN THIS LIBRARY ARE NOT REENTRANT!!!  ;     C\Z   0    |   1 
;    YOUR ISR MUST SAVE '_BR' FILE REGISTER IF USING SIGNED BRANCHES  ;       +‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐+   KARNAUGH MAP   (‐‐‐‐: DON'T CARE) 
;    (IN ADDITION TO W, STATUS AND SO ON)  ;       | A<B(W) |        |   SIMPLE:   BEQ  (Z == 1 FOR A‐B), 
;  ;      0|   LO   |  ‐‐‐‐  |     ..      BHI  (C == 0 FOR B‐A), <<< 
; "ADDR", "ADD"            STANDS FOR ADDRESS  ;    ‐‐‐+‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐+     ..      BLO  (C == 0 FOR A‐B) 
; "AF,BF"                  A & B REGISTER OPERANDS TO BE COMPARED  ;      1| A>B(W) | A==B(W)|   COMPOSED: BNE  (Z == 0 FOR A‐B), 
; "L"   STANDS FOR LITERAL (COMPARE A TO CONSTANT L)  ;    C  |   HI   |   EQ   |     ..      BLOS (C == 1 FOR B‐A), <<< 
; "Z"   STANDS FOR ZERO    (COMPARE A AGAINST TACIT, IMPLICIT ZERO)  ;    ‐‐‐+‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐+     ..      BHIS (C == 1 FOR A‐B) 
; "CC": CARRY CLEAR        "CS":  CARRY SET  ; 
; "EQ": EQUALS             "NE":  NOT EQUALS (DIFFERENT)  ; (NOT SO CLEARLY SHOWN AS ABOVE IN MICROCHIP'S LITERATURE...) 
; "HI": HIGHER             "HIS": HIGHER OR SAME        (UNSIGNED)  ; (BAD, VERY BAD EXPRESSED IN SEVERAL FAMOUS TEXT BOOKS...) 
; "LO": LOWER              "LOS": LOWER  OR SAME        (UNSIGNED)  ; 
; "GT": GREATER THAN       "GE":  GREATER THAN OR EQUAL (SIGNED)  ; NOTE: YOU NEED TO TEST ONLY ONE FLAG TO FULL‐FIT ALL CASES 
; "LT": LESS THAN          "LE":  LESS THAN OR EQUAL    (SIGNED)  ;       TO DO SO, SOME MACROS WILL REVERSE OPERANDS AS NEEDED (<<<) 
; "CB"  STANDS FOR "COMPARE AND BRANCH"  ; 
;  ;                          REVERSING: B‐A 
; EXAMPLE OF SYNTAX:   "CBHIZ AF, ADD" STANDS FOR:  ;          (COMPARE B VS. A, BUT LOOKING FOR A‐B RESULTS) 
;  COMPARE AF (A REGISTER FILE OPERAND) AGAINST ZERO; BRANCH TO ADD  ; "STATUS" FLAGS C (B0), Z (B2) FOR SUBTRACTION ARE (PIC 16FXXX CODE) 
;   ADDRESS IF AF IS HIGHER; ELSE EXEC NEXT INSTRUCTION IN SEQUENCE.  ; 
;  ;            |   Z 
; MACROS INCLUDED:  ; C\Z   0    |   1          ‐‐‐ UNSIGNED, SIGNED,  PIC16FXXX CODE ‐‐‐ 
;  ;   +‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐+ SIMPLE:   A‐B EQ, EQ BTFSC STATUS,Z; GOTO ADD 
; ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐ GENERAL ‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐‐  ;   |  A>B   |        |   ..  >>> B‐A HI, GT BTFSS STATUS,C; GOTO ADD 
; BCC   ADD       | BCS   ADD       |                ;  0|   HI   |   ‐‐‐  |   ..      A‐B LO, LT BTFSS STATUS,C; GOTO ADD 
; CBEQ  AF,BF,ADD | CBEQL  AF,L,ADD | CBEQZ  AF,ADD  ; ‐‐+‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐+ COMPOSED: B‐A NE, NE BTFSS STATUS,Z; GOTO ADD 
; CBNE  AF,BF,ADD | CBNEL  AF,L,ADD | CBNEZ  AF,ADD  ;  1|  A<B   | A==B(W)|   ..  >>> B‐A LOS,LE BTFSC STATUS,C; GOTO ADD 
;  ;C  |   LO   |   EQ   |   ..      A‐B HIS,GE BTFSC STATUS,C; GOTO ADD 
; ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐ UNSIGNED ‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐‐  ; ‐‐+‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐+ 
; CBHI  AF,BF,ADD | CBHIL  AF,L,ADD | CBHIZ  AF,ADD   
; CBHIS AF,BF,ADD | CBHISL AF,L,ADD | BHISZ: ALWAYS BRANCH !  ; ANCILIARY MACROS INCLUDED (INTERNAL USE ONLY): 
; CBLO  AF,BF,ADD | CBLOL  AF,L,ADD | BLOZ:  NEVER  BRANCH !  ; 
; CBLOS AF,BF,ADD | CBLOSL AF,L,ADD | CBLOSZ AF,ADD  ; BEQ    ADDRESS       BHI    ADDRESS          BHIS   ADDRESS 
;  ; BLO    ADDRESS       BLOS   ADDRESS          BNE    ADDRESS 
; ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐ SIGNED ‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐‐  ; CMP    A, B          CMPL   A, L             CMPLI  L, A 
; CBGT  AF,BF,ADD | CBGTL  AF,L,ADD | CBGTZ  AF,ADD  ; CMPZI  A  (VS. 0)    CPLIS  L, A             CPLS   A, L 
; CBGE  AF,BF,ADD | CBGEL  AF,L,ADD | CBGEZ  AF,ADD  ; CPS    A, B          CPZIS  A                CPZS   A 
; CBLT  AF,BF,ADD | CBLTL  AF,L,ADD | CBLTZ  AF,ADD   
; CBLE  AF,BF,ADD | CBLEL  AF,L,ADD | CBLEZ  AF,ADD  ; OTHER MACROS INCLUDED (PROGRAMMERS MAY FREELY USE THEM): 
;  ; 
; ESTABLISH: AF > BF,  AF == BF  OR  AF < BF, (FOR CMP),  OR  ; LOOP   A, ADDRESS ; 'DEC' AS LOOP CONTROL 
;            AF > L,   AF == L   OR  AF < L   (FOR CMPL)  ; LOOPI  A, ADDRESS ; 'INC' AS LOOP CONTROL 
;            AF > 0,   AF == 0   OR  AF < 0   (FOR CMPZI) 

C5-261
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

; MOVFF  A, B              MOVLF  L, A  ;‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
; BTFJS  F, B, ADDRESS     BTFBS  F, B, ADDRESS  BHIS   MACRO   ADDRESS         ; BRANCH IF HIGHER OR SAME (ANCILIARY) 
; BTFJC  F, B, ADDRESS     BTFBC  F, B, ADDRESS          BTFSC  STATUS, C       ; GOTO ADDRESS IF C == 1 (HIGHER/SAME) 
; BTFCS  F, B, ADDRESS     BTFCC  F, B, ADDRESS          GOTO   ADDRESS 
; WAITBS F, B              WAITBC F, B         ENDM 
; SAVREGS WSAVE, PSWSAVE   RSTREGS WSAVE, PSWSAVE   
; NEG    A                 NEGW  ; UNSIGNED BRANCHES, SIMPLE: 
; TST    A  ; 
;  ;   BEQ (Z == 1), BHI (C == 0, IF CMP B, A), BLO (C == 0) 
;‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐  ; 
CMP    MACRO   A, B            ; COMPARE 2 FILE REGISTERS (ANCILIARY) 
CBEQ   MACRO   A, B, ADDRESS   ; COMPARE AF TO BF; BRANCH IF EQUALS 
        MOVFW  B 
        CMP    A, B 
        SUBWF  A, W            ; COMPARE A, B(W) (A‐B) 
        BEQ    ADDRESS 
       ENDM 
       ENDM 
;‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
 
CMPL   MACRO   A, L            ; CMP FILE, CONSTANT (L) (ANCILIARY) 
        MOVLW  L  CBEQL  MACRO   A, L, ADDRESS   ; COMPARE AF TO LITERAL; JMP IF EQUALS 
        SUBWF  A, W            ; COMPARE A, L(W) (A‐L)          CMPL   A, L 
       ENDM          BEQ    ADDRESS 
;‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐         ENDM 
CMPLI  MACRO   L, A            ; CMP INVERTED K (L), FILE (ANCILIARY)   
        MOVFW  A  CBEQZ  MACRO   A, ADDRESS      ; COMPARE AF TO ZERO; JMP IF EQUALS 
        SUBLW  L               ; V2.0: COMPARE B, A(W)          MOVF   A, F            ; .. (THIS IS CMPZ) SET Z ACCORDINGLY 
       ENDM          BEQ    ADDRESS 
;‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐         ENDM 
CMPZI  MACRO   A               ; CMP FILE VS. 0 (ANCILIARY)   
        MOVFW  A               ; V2.0: CMP B, A  CBLO   MACRO   A, B, ADDRESS   ; COMPARE AF TO BF; BRANCH IF LOWER 
        SUBLW  0               ; V2.0: COMPARE B, A(W)          CMP    A, B 
       ENDM          BLO    ADDRESS 
;‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐         ENDM 
BEQ    MACRO   ADDRESS         ; BRANCH IF EQUALS (ANCILIARY)   
        BTFSC  STATUS, Z       ; GOTO ADDRESS IF Z == 1  CBLOL  MACRO   A, L, ADDRESS   ; COMPARE AF TO LITERAL; JUMP IF LOWER 
        GOTO   ADDRESS          CMPL   A, L 
       ENDM          BLO    ADDRESS 
;‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐         ENDM 
#DEFINE    BHI     BLO         ; V2.0: IF CMP B, A (ANCILIARY)   
;‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐  CBHI   MACRO   A, B, ADDRESS   ; COMPARE AF TO BF; BRANCH IF HIGHER 
BLO    MACRO   ADDRESS         ; BRANCH IF LOWER (ANCILIARY)          CMP    B, A            ; V2.0: CMP B, A (B‐A) 
        BTFSS  STATUS, C       ; GOTO ADDRESS IF C == 0          BHI    ADDRESS 
        GOTO   ADDRESS         ENDM 
       ENDM   
;‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐  CBHIL  MACRO   A, L, ADDRESS   ; COMPARE AF TO LITERAL; JMP IF HIGHER 
BNE    MACRO   ADDRESS         ; BRANCH IF NOT EQUALS (ANCILIARY)          CMPLI  L, A            ; V2.0: CMP L, A (L‐A) 
        BTFSS  STATUS, Z       ; GOTO ADDRESS IF Z == 0          BHI    ADDRESS 
        GOTO   ADDRESS         ENDM 
       ENDM   
;‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
CBHIZ  MACRO   A, ADDRESS      ; COMPARE AF TO ZERO; JUMP IF HIGHER 
#DEFINE    BLOS    BHIS        ; V2.0: IF CMP B, A (B‐A; ANCILIARY) 

C5-262
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

        CMPZI  A               ; 0‐A          BLOS   ADDRESS 
        BHI    ADDRESS         ENDM 
       ENDM   
  ; MORE ANCILLARY BRANCHES (PROGRAMMERS MAY FREELY USE THEM): 
; UNSIGNED BRANCHES, COMPOSED:  ; 
;  ;   BCS (C == 1), BCC (C == 0) 
;   BNE (Z == 0), BLOS (C == 1, IF CMP B, A), BHIS (C == 1)  ;   (USEFULL TO SIGNAL RETURN STATUS FROM SUBROUTINES, VIA C BIT) 
;  ; 
CBNE   MACRO   A, B, ADDRESS   ; COMPARE AF TO BF; JUMP IF NOT EQUALS  BCC    MACRO   ADDRESS         ; BRANCH IF CARRY CLEAR 
        CMP    A, B            ; (SHOULD BE B‐A BUT IT'S SAME FOR EQ)          BTFSS  STATUS, C       ; GOTO ADDRESS IF C == 0 
        BNE    ADDRESS         ; BRANCH IF NOT EQUALS          GOTO   ADDRESS 
       ENDM         ENDM 
   
CBNEL  MACRO   A, L, ADDRESS   ; COMPARE AF,LITERAL;JMP IF NOT EQUALS  BCS    MACRO   ADDRESS         ; BRANCH IF CARRY SET 
        CMPL   A, L            ; (SHOULD BE L‐A BUT IT'S SAME FOR EQ)          BTFSC  STATUS, C       ; GOTO ADDRESS IF C == 1 
        BNE    ADDRESS         ; BRANCH IF NOT EQUALS          GOTO   ADDRESS 
       ENDM         ENDM 
   
CBNEZ  MACRO   A, ADDRESS      ; COMPARE AF, ZERO; JUMP IF NOT EQUALS  ;                   HOW THE SIGNED BRANCHES WORK? 
        MOVF   A, F            ; .. (THIS IS CMPZ) SET Z ACCORDINGLY  ; 
        BNE    ADDRESS         ; BRANCH IF NOT EQUALS  ; TO MAKE SIGNED BRANCHES WORK YOU MAY FOLLOW THIS SIMPLE TRICK,  
       ENDM  ; .. HIDDEN VERY, VERY DEEPLY IN THE DARK SIDE OF THE MATH THEORY. 
  ; .. YOU HARDLY SEE THE FOLLOWING MATERIAL IN ANY MATH TEXT BOOK... 
CBHIS  MACRO   A, B, ADDRESS   ; CMP AF TO BF; JMP IF HIGHER OR SAME  ; 
        CMP    A, B  ; AS AN EXAMPLE: FOR 3 BITS SIGNED NUMBERS, IN 2'S COMPLEMENT, THE 
        BHIS   ADDRESS  ; .. FOLLOWING HIGHER TO LOW ORDER APPLIES (TABLE 1 BELOW). OBVIOUS‐ 
       ENDM  ; .. LY, FOR THE NEGATIVE NUMBERS EVEN IF THEY ARE LESS THAN THE POS‐ 
  ; .. SITIVE ONES, THEY ALL ARE HIGHER THAN THEM (IF SEEN AS UNSIGNED) 
CBHISL MACRO   A, L, ADDRESS   ; CMP AF TO LITERAL;JMP IF HIGHER|SAME  ; 
        CMPL   A, L  ; THIS HAS BEEN A VERY WELL KNOWN FACT OVER THE YEARS, AND THIS 
        BLOS   ADDRESS  ; .. CAUSED THE ADOPTION OF ONE MORE BIT IN THE CONDITION CODES: 
       ENDM  ; .. THE OVERFLOW BIT (USUALLY: V, N, C, Z; N FOR NEGATIVE. MORE BITS 
  ; .. ARE COMMONLY FOUND, LIKE PARITY [INTEL] AND DC, DECIMAL CARRY, 
CBLOS  MACRO   A, B, ADDRESS   ; COMPARE AF TO BF; JUMP IF LOWER|SAME  ; .. FOR BCD ARITHMETIC [4 BIT NIBBLES]. MORE STATUS BITS, AS 
        CMP    B, A            ; V2.0: CMP B, A (B‐A)  ; .. INTERRUPT FLAGS, INTERRUPT ENABLE BITS, PROCESSOR MODE, ETC., 
        BLOS   ADDRESS  ; .. CONFORM ALL THE PROCESSOR STATUS WORD, PSW) 
       ENDM  ; 
  ; BUT WHAT MUST BE DONE IN SMALL MICROCONTROLERS THAN ONLY HAVE 
; .. TWO(2) FLAGS: THE Z AND THE C BITS, AS CONDITION CODES (CCR)? 
CBLOSL MACRO   A, L, ADDRESS   ; COMPARE AF TO LIT; JMP IF LOWER|SAME 

        CMPLI  L, A            ; V2.0: CMP L, A (L‐A) 

        BLOS   ADDRESS 
; URIBE'S OBSERVATION: 
       ENDM 

 
; RECODE THE SIGNED, CUMBERSOME NUMBERS, INTO EXCESS 2^(N‐1) (ADD +4 
CBLOSZ MACRO   A, ADDRESS      ; COMPARE AF TO ZERO;JMP IF LOWER|SAME  ; .. TO ALL FIGURES IN THE EXAMPLE; SEE TABLE 2). NOW, YOU CAN SEE 
        MOVFW  A               ; V2.0: CMP 0, A  ; .. THAT THE NEW CODED NUMBERS (TABLE 2) EXHIBIT THE HIGHER TO LOW 
        SUBLW  0               ; 0‐A(W)  ; .. ORDER USED IN THE UNSIGNED REPRESENTATION; SO, YOU CAN APPLY THE 

C5-263
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

; .. STANDARD UNSIGNED BRANCHES TO THEM, ON THE PIC MCUS, AND THE         ENDM 
; .. ANSWERS YOU WILL GET ARE THE CORRECT ONES FOR THE ORIGINAL  ;‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
; .. SIGNED 2'S COMPLEMENT NUMBERS!  RCODLW MACRO   L               ; RECODE LITERAL L (INTO W) 
;          MOVLW  L 
; NOTE: TO RECODE A NUMBER YOU ONLY NEED TO NEGATE THE SIGN BIT. IF           XORLW  B'10000000'    ; RECODE L (INSIDE W) 
; .. IT IS 0, TURN IT TO 1, AND IF IT IS 1, TURN IT TO 0         ENDM 
; YOU DON'T EVEN NEED TO CHECK THE SIGN BIT; JUST ONLY MAKE THE EXOR  ;‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
; ..BETWEEN THE DATA BYTE AND THE LITERAL B'10000000'. THAT'S ALL!  RCODLF MACRO   L               ; RECODE LITERAL L (TO TMP FILE: _BR) 
;           MOVLW  L 
; TABLE 1: 2'S COMPLEMENT FOR 3 BITS NUMBERS (1: SIGN, 2: MANTISSA).           XORLW  B'10000000' 
; TABLE 2: TABLE 1 RECODED TO EXCESS 2^(N‐1)" ("+4" IN THIS EXAMPLE;           MOVWF  _BR 
; .. +128 FOR ONE BYTE NUMBERS)         ENDM 
;  ;‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
;               TABLE 1  TABLE 1B    TABLE 2 (ADD +4 TO TABLE 1)  CPS    MACRO   A, B            ; COMPARE SIGNED, FILE REGISTERS A & B 
;              ‐‐‐‐‐‐‐‐  ‐‐‐‐‐‐‐‐   ‐‐‐‐‐‐‐‐          RCODF  A               ; RECODE A (TO TMP FILE: _BR) 
;                3: 011   ‐1: 111     3: 111          RCODFW B               ; RECODE B INTO W 
;                2: 010   ‐2: 110     2: 110          SUBWF  _BR, W          ; COMPARE A(_BR), B(W) (A‐B) 
;                1: 001   ‐3: 101     1: 101         ENDM 
;                0: 000   ‐4: 100     0: 100  ;‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
;               ‐1: 111    3: 011    ‐1: 011  CPLS   MACRO   A, L            ; CPS FILE REGISTER VS. CONSTANT (L) 
;               ‐2: 110    2: 010    ‐2: 010          RCODF  A               ; RECODE A (TO TMP FILE: _BR) 
;               ‐3: 101    1: 001    ‐3: 001          RCODLW L               ; RECODE L (INTO W) 
;               ‐4: 100    0: 000    ‐4: 000          SUBWF  _BR, W          ; COMPARE A(_BR), L(W) (A‐L) 
;         ENDM 
; RESERVE LOCAL VARIABLES. ** NOTE: THIS LIBRARY IS NOT REENTRANT!!!  ;‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
  CPLIS  MACRO   L, A            ; CPLS INVERTED, K (L) VS. REGISTER 
       CBLOCK          RCODLF L               ; RECODE L (TO TMP FILE: _BR) 
        _BR    ; ** ISR SHOULD SAVE '_BR' IF USING SIGNED BRANCHES!**          RCODFW A               ; RECODE A INTO W 
       ENDC          SUBWF  _BR, W          ; V2.0: COMPARE L(_BR), A(W) (L‐A) 
         ENDM 
;‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
; ANCILIARY MACROS (INTERNAL USE): 
CPZS    MACRO  A               ; CPS FILE REGISTER VS. 0 

         RCODF  A              ; RECODE A (TO TMP FILE: _BR) 
; CPS  A, B (COMPARE SIGNED)    CPZIS A   (CPS 0 VS. A) 
         MOVLW  B'10000000'    ; ZERO; RECODE ZERO (INSIDE W) 
; CPLS A, L (CPS VAR,CONSTANT)  CPLIS L,A (CPS VAR CONSTANT INVERTED) 
         SUBWF  _BR, W         ; COMPARE A(_BR), L(W) (A‐0) 
; RCODF  A (RECODE A INTO TMP _BR) RCODFW A (RECODE A INTO W) 
       ENDM 
; RCODLW L (RECODE L INTO W)       RCODLF L (RECODE L TO TMP: _BR) 
;‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 

CPZIS   MACRO   A              ; CPZS INVERTED, 0 VS. FILE REGISTER  
;‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
        MOVLW  B'10000000'     ; ZERO; RECODE ZERO (TO TMP FILE: _BR) 
RCODF  MACRO   A               ; RECODE A INTO TMP FILE: _BR 
         MOVWF  _BR 
        MOVFW  A 
        RCODFW A               ; RECODE A (INTO W) 
         XORLW  B'10000000' 
        SUBWF  _BR, W          ; V2.0: COMPARE 0(_BR), A(W) (0‐A) 
         MOVWF  _BR 
       ENDM 
       ENDM 
 
;‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
RCODFW MACRO   B               ; RECODE FILE REGISTER B INTO W  ; SIGNED BRANCHES, SIMPLE:    (BEQ & BNE ARE SAME AS FOR UNSIGNED) 
        MOVFW  B  ; 
         XORLW  B'10000000'    ; RECODE B (INSIDE W)  ;   CBGT (V2.0: CMP B, A INSTEAD OF A, B; C == 0, AFTER RECODING) 
;        NEGATED CONDITION: DO NOT JUMP ON:  C == 1,  

C5-264
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

;   CBLT (C == 0, AFTER RECODING)          BHI    ADDRESS         ; .. GOTO ADDRESS IF C == 0 (A GT L) 
;        NEGATED CONDITION: DO NOT JUMP ON:  C == 1         ENDM 
;   
; REMEMBER: RECODING CONVERTS BOTH OPERANDS FROM SIGNED INTO UNSIGNED  CBGTZ  MACRO   A, ADDRESS      ; CBGT W/LITERAL ZERO (C.A.R.E.) 
; ..(EXCESS 127), COMPARE THEM AS UNSIGNED AND TAKE THE CORRESPONDING          CPZIS  A               ; V2.0: CHG CMP A, 0 TO: CMP 0, A 
; ..UNSIGNED BRANCHES. CLEVER; ISN'T IT?          BHI    ADDRESS         ; .. GOTO ADDRESS IF C == 0 (A GT 0) 
;           ENDM 
CBGT   MACRO   A, B, ADDRESS   ; COMPARE AND BRANCH IF GREATER THAN   
        CPS    B, A            ; V2.0: B‐A  CBLTL  MACRO   A, L, ADDRESS   ; CBLT LITERAL 
        BHI    ADDRESS         ; .. GOTO ADDRESS IF C == 0 (A GT B)          CPLS   A, L 
       ENDM          BLO   ADDRESS          ; .. GOTO ADDRESS IF C == 0 (A LT L) 
         ENDM 
CBLT   MACRO   A, B, ADDRESS   ; COMPARE AND BRANCH IF LESS THAN   
        CPS    A, B  CBLTZ  MACRO   A, ADDRESS      ; CBLT W/LITERAL ZERO 
        BLO    ADDRESS         ; .. GOTO ADDRESS IF C == 0 (A LT B)          CPZS   A 
       ENDM          BLO    ADDRESS         ; .. GOTO ADDRESS IF C == 0 (A LT 0) 
         ENDM 
; SIGNED BRANCHES: COMPOSED:   (EQ IS SAME AS FOR UNSIGNED)   
;  ; SIGNED BRANCHES; COMPARE REGISTER TO LITERAL: COMPOSED: 
;   CBLE (V2.0: CMP B, A INSTEAD OF A, B; C == 1, AFTER RECODING)  ; 
;   CBGE (C == 1, AFTER RECODING)  ;   CBLEL (V2.0: CMP L, A INSTEAD OF A, L; C == 1, AFTER RECODING) 
;  ;   CBGEL (C == 1, AFTER RECODING) 
CBLE   MACRO   A, B, ADDRESS   ; COMPARE&BRANCH IF LESS THAN OR EQUAL  ; 
        CPS    B, A            ; V2.0: CHG CMP A, B TO: CMP B, A  CBLEL  MACRO   A, L, ADDRESS   ; CBLE LITERAL 
        BLOS   ADDRESS         ; .. IF C == 1 (A LE B)          CPLIS  L, A            ; V2.0: CHG CMP A, L TO: CMP L, A 
       ENDM          BLOS   ADDRESS         ; .. GOTO ADDRESS IF C == 1 (A LE L) 
         ENDM 
CBGE   MACRO   A, B, ADDRESS   ; CMP&BRANCH IF GREATHER THAN OR EQUAL   
        CPS    A, B  CBLEZ  MACRO   A, ADDRESS      ; CBLE W/LITERAL ZERO 
        BHIS   ADDRESS         ; .. IF C == 1 (A GE B)          CPZIS   A              ; V2.0: CHG CMP A, L TO: CMP L, A 
       ENDM          BLOS   ADDRESS         ; .. GOTO ADDRESS IF C == 1 (A LE 0) 
         ENDM 
; SIGNED BRANCHES WITH LITERAL; SIMPLE:   
;  CBGEL  MACRO   A, L, ADDRESS   ; CBGE LITERAL 
;   CBGTL (V2.0: CMP L, A INSTEAD OF A, L; C == 0, AFTER RECODING)          CPLS   A, L 
;         NEGATED CONDITION: DO NOT JUMP ON:  C == 1          BHIS   ADDRESS         ; .. IF C == 1 (A GE B) 
;   CBLTL (C == 0, AFTER RECODING)         ENDM 
;         NEGATED CONDITION: DO NOT JUMP ON:  C == 1   
;  CBGEZ  MACRO   A, ADDRESS      ; CBGE W/LITERAL ZERO 
; FOLLOWING LITERAL MACROS ASSUME COMPARISON BETWEEN A REGISTER AND A          CPZS   A 
; .. LITERAL.          BHIS   ADDRESS         ; .. IF C == 1 (A GE 0) 
;         ENDM 
; (SIGNED BRANCHES TO COMPARE BETWEEN A LITERAL  AND  A REGISTER   
; ... ARE LEFT AS AN EXERCISE TO THE READER... IF NEEDED).  ; SIGNED BRANCHES TO COMPARE BETWEEN A LITERAL  AND  A REGISTER (IN 
;  ; ... THIS ORDER) ARE LEFT AS AN EXERCISE TO THE READER (IF NEEDED). 
CBGTL  MACRO   A, L, ADDRESS   ; CBGT LITERAL   
        CPLIS  L, A            ; V2.0: CMP L, A 

C5-265
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

; MORE HANDY MACROS (NOT VERY RELATED TO COMPARISONS)  WAITBS MACRO   F, B            ; WAIT FOR BIT SET  IN FILE 
;         LOCAL   LOOP 
LOOP   MACRO   A, ADDRESS      ; 'DEC' AS LOOP CONTROL  LOOP:   BTFSS  F, B 
        DECFSZ A, F          GOTO   LOOP 
        GOTO   ADDRESS         ENDM 
       ENDM  ;‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
;‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐  WAITBC MACRO   F, B            ; WAIT FOR BIT CLEAR IN FILE 
LOOPI  MACRO   A, ADDRESS      ; 'INC' AS LOOP CONTROL         LOCAL   LOOP 
        INCFSZ A, F  LOOP:   BTFSC  F, B 
        GOTO   ADDRESS          GOTO   LOOP 
       ENDM         ENDM 
;‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐   
MOVFF  MACRO   A, B            ; MOVE FILE TO FILE  SAVREGS MACRO  WSAVE, PSWSAVE  ; SAVE W & PSW FOR ISR, **FOR 16F84A** 
        MOVW   A, W          MOVWF  WSAVE           ; SAVE OFF CURRENT W REGISTER CONTENTS 
        MOVWF  B                                 ; ..MOVWF *NEVER* CHANGE STATUS 
       ENDM          MOVFW  STATUS          ; MOVE STATUS REGISTER INTO W REGISTER 
;‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐                                 ; ..MOVFW *CHANGE* STATUS, BUT... 
MOVLF  MACRO   L, A            ; MOVE LITERAL TO FILE                                 ; ..AFTER STORING IT INTO W 
        MOVLW  L           MOVWF PSWSAVE         ; SAVE OFF CONTENTS OF STATUS REGISTER 
        MOVWF  A          CLRF   STATUS          ; SELECT BANK 0 (BY DEFAULT). D16G09 
       ENDM         ENDM      ; YOU MAY NEED TO SAVE MORE REGISTERS FOR OTHER MCUS 
;‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐   
BTFJS  MACRO   F, B, ADDRESS   ; BIT TEST FILE AND JUMP IF SET  RSTREGS MACRO  WSAVE, PSWSAVE  ; RESTORE SAVED W & PSW FOR RFIE 
        BTFSC  F, B          MOVFW  PSWSAVE         ; RETRIEVE COPY OF STATUS REGISTER 
        GOTO   ADDRESS           MOVWF STATUS          ; ..RESTORE PRE‐ISR STATUS CONTENTS 
       ENDM                                 ; ..MOVWF *NEVER* CHANGE STATUS 
;‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐          SWAPF  WSAVE, F        ; RESTORE PRE‐ISR W REGISTER CONTENTS 
#DEFINE    BTFBS   BTFJS       ; .. AND BRANCH IF SET (ALIAS TO JUMP)           SWAPF WSAVE, W        ; .. SWAP DOES NOT CHANGE STATUS FLAGS 
;‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐          RETFIE                 ; RETURN FROM INT. AND INT. ENABLE 
BTFJC  MACRO   F, B, ADDRESS   ; BIT TEST FILE AND JUMP IF CLEAR         ENDM 
        BTFSS  F, B   
        GOTO   ADDRESS  NEG    MACRO   A               ; MAKE ‐A (NEGATIVE A) 
       ENDM 
        COMF   A, F 
;‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
         INCF  A, F 
#DEFINE    BTFBC   BTFJC       ; .. & BRANCH IF CLEAR (ALIAS TO JUMP) 
       ENDM 
;‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐  ;‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
BTFCS  MACRO   F, B, ADDRESS   ; BIT TEST FILE AND CALL IF SET  NEGW   MACRO                   ; MAKE ‐W (NEGATIVE W) 
        BTFSC  F, B          SUBLW  0               ; W = 0 ‐ W 
        CALL   ADDRESS 
       ENDM 
       ENDM 
;‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
;‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
TST    MACRO   A               ; COMPARE REGISTER AGAINST '0'; 
BTFCC  MACRO   F, B, ADDRESS   ; BIT TEST FILE AND CALL IF CLEAR 
        MOVF   A, F            ; .. (THIS IS CMPZ) SET Z ACCORDINGLY 
        BTFSS  F, B 
       ENDM 
        CALL   ADDRESS 
 
       ENDM     LIST
;‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 

C5-266
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

 LIBRERÍA DE TIMERS PARA HC08


; DEFINES 
 
;ram:      SET     Z_RAMStart  ; << Put THIS into Main program << 
 
La siguiente librería implementa una batería de 8 timers, por interrupciones, rom:       SET     ROMStart    ; $8000 
para el Freescale HC908, bajo CodeWarrior, similar a la anterior (del PIC) initStack: EQU     $240 
 
; Timers8G.inc: Luis G. Uribe C., Basic 8 Timers Support  ;‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
; ..L24N3 L08N4 J01D5 M27F7 V09M7 D08L7 J16A2009 V29Y2009  ; Defines Bits for TBM Programming 
; V29Y9: Use more MACROS   
; J16A9: Codewarrior version  ; ..TBCR ($1C) bits 
; D08L7: Included TimeOut macro for semantics enhacement.  TBON           EQU   (1 << 1)  ; ..Bit #1 
; M27F7: Init8MhzClock run 7,987,200 Hz instead 8Mhz, to fit 9600 bps  TBIE           EQU   (1 << 2)  ; ..Bit #2 
; ..in SCI  TBIE.bit       EQU   2         ; ..Bit #2 
; J01D5: ISR is INTERRUPTIBLE from any other devices, despite the  TACK           EQU   (1 << 3)  ; ..Bit #3 (Write ONLY. Read as 0) 
; ..wrong advise from Motorola handbooks, seen in class.  TACKbit        EQU   3         ; ..Bit #3 (Write ONLY. Read as 0) 
; ..As ISR is non reentrant, Auto‐disable TBM interrupts before CLI  MS_1024        EQU   %01010000 ; bits 6,5,4: '.101...' 
   
; CONFIG1 Register 
; DATA DEFINITION. 
LVIandCOP_OFF  EQU   $31       ; See CONFIG1 Register... 
; Define 8 timers Global Variables 
 
; Note: Macro directives (DW, $IF...) cannnot go into macros... GOK! 
;  ; More MACRO DEFINITIONS 
; NOTE: REQUIRES  'org ram'  **BEFORE**  INCLUDE 'timers8G.inc'   
; ..in main program, to make this data definitions work!  TimeOut:   MACRO   timer, gotoAddress  ; timer is always a CONSTANT 
;   
; *** ALL following variables  *MUST*  reside on ZERO page! ***             brset   \1, TimerFlags, \2 
   
; TimerDef: MACRO and Variables DEFINITION             ENDM 
   
TimerDef:   MACRO timer  Setimer:   MACRO   timer,time  ; time is a CONSTANT or a VARIABLE 
   
Timer\1:    DS  2             pshh                ; save H:X 
Timer\1.Rdy EQU \1             pshx                ; .. 
             psha                ; save ACC 
           ENDM             tpa                 ; push CCS saves IMask status 
             psha                ; ... 
           TimerDef 0             sei                 ; DISABLE INTERRUPTS (IMask=1) 
           TimerDef 1             bclr    \1, TimerFlags  ; Make timer X NOT Ready 
           TimerDef 2             ldhx    \2          ; time in milliseconds (50) 
           TimerDef 3             sthx    Timer\1     ; .. 
           TimerDef 4             bne     \@nxt       ; Skip 'bset' 
           TimerDef 5             bset    \1, TimerFlags  ; Make timer X Ready... 
           TimerDef 6   
           TimerDef 7  \@nxt:     pula                ; Pull CCS recover IMask saved 
             tap                 ; ...status 
TimerFlags: DS  1              ; 8 bit flags: Timer0,Timer1..             pula                ; restore ACC 

C5-267
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

           pulx                ; restore H:X   
           pulh                ; ..             ENDM 
   
           ENDM   
  ; TBM INIT. This is the base for Timer Support 
Wait_on:   MACRO        timer, time ; time is Constant or Variable   
  Init8Timers:   MACRO  
           Setimer \1, \2             clrx 
           brclr   \1, TimerFlags, *; Wait 'time' mseconds on 'timer'             clrh 
   
           ENDM             sthx    Timer0      ; Init Timer0 to 0 
             sthx    Timer1      ; Init Timer1 to 0 
; Ancillary MACRO DEFINITIONS             sthx    Timer2      ; Init Timer2 to 0 
             sthx    Timer3      ; Init Timer3 to 0 
UpdateTmr: MACRO  Timer             sthx    Timer4      ; Init Timer4 to 0 
             sthx    Timer5      ; Init Timer5 to 0 
           ldhx    \1          ; load H:X and compare TimerXX             sthx    Timer6      ; Init Timer6 to 0 
           beq     \@Next      ; ..(16 bits) to see if it is 0             sthx    Timer7      ; Init Timer7 to 0 
   
           aix     #‐1         ; not 0?: decrement             clr     TimerFlags  ; clear ALL 8 bit timers flags 
           sthx    \1   
           bne     \@Next             mov     #(TACK | MS_1024 | TBON | TBIE) , TBCR 
           bset    \1.Rdy, TimerFlags  ; 0?: Mark Timer0 READY                                 ; set TACK, select 1024Hz,  
\@Next:                                 ; ..Set TBON, Enable TBM interrupts 
           ENDM             ENDM 
   
; Program VCO to 32 MHz from 32768 Hz cristal (8 MHz VCO bus clock)  ; TBM Interrupt Service Routine (ISR). 90 cycles... 
; ..V09M07: run @7,987,200 Hz instead of 8Mhz, to fit 9600 bps in SCI  ; Now ISR is interruptible from any other devices; non reentrant 
; ....Now: N=975; before: N=977. See below   
; *** REMEMBER *** to give 'Xtal' command in Debugger to 32768 Hz  TIM8INT:   MACRO 
   
Init8MhzClock: MACRO             bclr TBIE.bit, TBCR ;*SELF‐DISABLE TBM Interrupts* in TBCR 
           bclr    PCTL_PLLON,PCTL ; Turn OFF PLL (ON by default)             bset TACKbit, TBCR  ; Set TBCR TACK bit to ACK Interrupt 
             cli                 ;Enable ALL Interrupts other than this  
           mov     #$02, PCTL  ; Set P=0 for PRE[1:0],              pshh                ; Not saved by interrupt proc 
                               ; ..E=2 for VPR[1:0]   
             UpdateTmr Timer0 
           mov     #$CF, PMSL  ; N=975($03CF) for MUL[11:0]             UpdateTmr Timer1 
           mov     #$03, PMSH  ; ..pms L:MUL[7:0], H:MUL[11:8]             UpdateTmr Timer2 
             UpdateTmr Timer3 
           mov     #$D0, PMRS  ; Set L=208($D0) for VRS[7:0]             UpdateTmr Timer4 
           mov     #$01, PMDS  ; Set R=1 for RDS[3:0]             UpdateTmr Timer5 
             UpdateTmr Timer6 
           bset    PCTL_PLLON, PCTL; Turn ON  PLL             UpdateTmr Timer7 
           bset    PBWC_AUTO, PBWC ;Enable Auto Bandwidth Control   
           brclr   PBWC_LOCK, PBWC, * ; 2KCycles til LOCK bit is set  ; TBISRexit: 
           bset    PCTL_BCS, PCTL  ; Set VCO clock as Sys. Clock   

C5-268
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

TBISRexit:   
           sei                 ; Disable CPU Interrupts   ; ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
           bset TBIE.bit, TBCR ; Re‐enable TBM Interrupts in TBCR  ; Parameter definitions 
           pulh                ; Not restored by interrupt process   
           rti                 ; ..Return from Interrupt  ram:   SET     Z_RAMStart  ; $40. 512 RAM bytes 
   
           ENDM  ;==================================================================== 
  ; Global Variables 
       END   
         org ram                 ; Put this *BEFORE* 'timers8G.inc' 
 
       NOLIST 
 PRUEBA LIBRERÍA DE TIMERS        INCLUDE 'timers8G.inc'  ; Timer Support: Variables & Macros 
       LIST 
 
Se demuestra cómo usar los temporizadores, que van por interrupciones, ;******************************************************************** 
dentro de otra rutina de interrupciones, (versión Freescale HC908). ; MAIN PROGRAM HEADER: 
 
       org rom 
   
;********************************************************************  Main:  mov     #LVIandCOP_OFF, CONFIG1 ; a) Turn off LVI & COP 
; Programa Tim8_IRQ‐G.asm: Timer calls inside IRQ ISR, J01M7 D12A2009         ldhx    #initStack      ; b) Set up SP 
; Luis G. Uribe C., J16A2009 V29Y2009         txs                     ; ... 
;   
; Program to show interactions between TBM timers8 interrupt routines         clra                    ; Init ACC to fool Debuger... 
; ..and 'IRQ' interrupts, when it is needed to request timer delays   
; ..from IRQISR. This is a typical case when you need to rearm global         Init8MHzClock           ; c) 
; ..interrupts, DESPITE DE ADVISE IN CONTRARY FROM MOTOROLA TECHNICAL         Init8Timers             ; ... 
; ..DOCUMENTS...   
;         ;‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
; ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐         ; IRQ interrupts: Enabled by default, on Power On 
; Include files   
  ;‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
       NOLIST  ; Main Loop 
       INCLUDE 'MC68HC908GP32.inc'   
       LIST         cli                     ; Enable Global interrupts NOW 
   
;‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐  again: inca 
; EQU Definitions         bra     again 
   
; INTSCR  EQU $001d  ;==================================================================== 
  ; PROGRAM TRAILER: 
IMASK.bit:     EQU   1                 ; ..Bit #1  ; 
IMASK:         EQU   (1 << IMASK.bit)  ; ..Bit #1  ; 1) TIM8INT Macro 
IRQACK.bit:    EQU   2                 ; ..Bit #2  ; 2) Define Interrupt Vectors 
IRQACK:        EQU   (1 << IRQACK.bit) ; ..Bit #2  ; 
IRQF.bit:      EQU   3                 ; ..Bit #3  ;‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
IRQF:          EQU   (1 << IRQF.bit)   ; ..Bit #3  ; TMB Interrupt Service Routine 

C5-269
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

         ;‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
TBMISR:         ; PUT HERE ANY ORIGINAL CODE FOR THIS ISR 
       TIM8INT         ; .. 
         ;‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
;‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐   
; IRQ INTERRUPT SERVICE ROUTINE  IRQISRexit: 
;         sei                     ; Disable CPU Interrupts; never mess 
; IRQ has one of the highest priorities in the HC08, and the higher                                 ; ..with hardware enable bits if 
; ..hardware priority, below Reset and SWI. That is ok for                                 ; ..interrupts are enabled 
; ..responsiveness but care must be taken to assure that no priority         bclr     IMASK.bit, INTSCR  ; Re‐enable IRQ interrupts 
; ..inversion ocurrs through long ISR times, using debouncing delays,         pulh                    ; Not restored by interrupt process 
; ..for example. If this is the case, you MUST auto‐desable the IRQ         rti                     ; Return from Interrupt 
; ..interrupts and renable global interruptos, to permit other lower  ;‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
; ..peripherals access.  ; Interrupt Vectors 
   
IRQISR:  dummy_isr:                     ; Must be placed in Rom Space 
       ; NOTE: NO  'bset IRQF.bit,INTSCR'  required here to Ack IRQ':         rti 
       ; ..IRQ' Interrupt is Acknowledged through 'Vector Fetch'.   
       ; ..cfr. Technical Data, page 176. Verify using Simulation...         org     INT_TBM         ; Increasing priority from bottom up 
   
       bset     IMASK.bit, INTSCR  ; **SELF‐DISABLE IRQ' Interrupts**         DC.W    TBMISR          ;TBM (Si usa Init8Timers...) 
       cli                 ; Enable ALL (other than this) Interrupts         DC.W        dummy_isr   ; ADC Conversion Complete 
       pshh                ; Not saved by interrupt proc         DC.W        dummy_isr   ; Keyboard 
         DC.W        dummy_isr   ; SCI Transmit 
       ;‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐         DC.W        dummy_isr   ; ..SCI Receive 
       ; delaying process 20 MSeconds the IRQISR helps to avoid         DC.W        dummy_isr   ; ..SCI Error 
       ; ..multiple interrupts due to contact bounce on IRQ' pin         DC.W        dummy_isr   ; SPI Transmit 
         DC.W        dummy_isr   ; ..SPI Receive 
       Wait_on 7, #20      ; 20 MSeconds for debouncing. This only         DC.W        dummy_isr   ; TIM2 Overflow 
                           ; ..works if TBM is enabled to interrupt..         DC.W        dummy_isr   ; ..TIM2 Channel 1 
                           ; ..Should you include NOP loops to delay,         DC.W        dummy_isr   ; ..TIM2 Channel 0 
                           ; ..you CAN'NOT block all other peripheral         DC.W        dummy_isr   ; TIM1 Overflow 
                           ; ..interrupts. You must follow this same         DC.W        dummy_isr   ; ..TIM1 Channel 1 
                           ; ..strategy.         DC.W        dummy_isr   ; ..TIM1 Channel 0 
         DC.W        dummy_isr   ; PLL 
       ;‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐         DC.W    IRQISR          ; IRQ <<< WARNING: Need PON IntDisable 
       ; *** NOTE ***:         DC.W        dummy_isr   ; SWI 
       ;         DC.W    Main            ; RESET. Maximum priority. Asynch. 
       ; Timer 7 MUST NOT be used anywhere else!   
       ; ..It belongs exclusively to this 'IRQISR'         END 
       ; 
 

C5-270
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

 EJERCICIOS ADICIONALES
PLANTEAMENTO INICIAL
Estos problemas están pensados para realizarse empleando el microcontrolador PIC 16F84A, pero
pueden programarse para otros modelos, así como el Freescale HC908 (o cualquier otro
microcontrolador que desee). La idea es que el estudiante debe poder hacer cualquiera de las funciones
TTL, empleando para ello un microcontrolador.

La primera cosa que debe hacer es resolver todos los ejercicios anteriores, de lógica combinatoria y
secuencial, empleando microcontroladores (PIC, Freescale, etc.) Lo segundo es comparar la dificultad
de una solución y otra. Analice el hardware de ambas propuestas, los diagramas de estado (máquinas
secuenciales) y los de flujo (programas en el micro), e intente visualizar las dificultades que se derivarían
si tuviera que cambiar la especificación original, para cada una de las soluciones alternativas.

1) EJERCICIOS DE REEMPLAZO
Hacer para el PIC 16F84A, programas completos en Assembler (deben correr bajo MPLAB
[WinIDE para HC08]) que ejecuten c/u de las siguientes funciones; incluir los Diagramas de Flujo
(o el código en C, bien estructurado), y las simulaciones:
 Decoder/Demultiplexer de 1 a 8 (una [1] entrada “I”, una [1] entrada “Enable”, tres [3]
selectores, “S2S1S0”; ocho [8] salidas, “O7O6…O1O0”)
 Multiplexer de 8 a 1 (ocho [8] entradas, “I7I6…I1I0”; tres [3] selectores, “S2S1S0”, una [1]
entrada “Enable”, una [1] salida “Z”)
 Full Adder (A+B); A y B tienen c/u 4 bits. Resultado: 5 bits. Ver si puede colocar una entrada
de Carry-IN y una señal ‘ADD/~SUBSTRACT’ (Nota: Los dispositivos PIC16F628 y
PIC16F88 puede operar con un oscilador interno, de 4MHz y 8MHz respectivamente, lo que
deja libres los 2 pines del cristal, que pueden usarse como 2 terminales de entrada o salida,
adicionales a los del PIC16F84. El PIC16F877 tiene, desde luego, más puertos de entrada y
salida)
 Comparador de A y B; A y B tienen c/u 4 bits. Resultado: A> B, A == B, A<B.
 Emule un subset del 7486, para 4 Exors, c/u con 2 entradas y una salida
 Contador Up/~Down de 0 a 15 (salidas DCBA). Otras entradas: ~MasterClear, ~LOAD,
entradas DCBA para el Load; Clock.
 Ídem al (6), pero de 0 a 9
 Registro de entrada serie y salida paralelo (1 entrada ‘I’, 1 Clock, 1 entrada Left/~Right, 4
salidas)
 Registro de entrada paralelo y salida serie (4 entradas ‘I’, 1 Clock, 1 entrada Left/~Right, 4
salidas)
 Un Procesador de “Código Hamming”, para 4 bits de información (Entrada: I7I6I5I3, salidas
I7I6I5P4I3P2P1), que permita ambas funciones: Generador de Código y Corrector de Error.
 Emule una ROM de 256 posiciones, de 5 bits de longitud para cada posición. Cuando se le da
la dirección (8 bits de entrada, por uno de los puertos de entrada), su programa debe localizar

C5-271
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

la posición correspondiente y sacar los 5 bits de información por un puerto de salida, de su


elección.
Algunas soluciones analizan las entradas una por una, en una cadena interminable de “ifs”. Así no se
hace, normalmente; los circuitos combinatorios (o la parte combinacional de los circuitos secuenciales)
pueden resolverse mediante Tablas (DT: Define Table). Pueden emplear subrutinas (CALL), a lo mejor
pasándoles como parámetros los bits (ceros y unos) leídos de las entradas, y que devuelvan el resultado
en W. También pueden usarse Macros.

2) MANEJO DE UNA IMPRESORA GPIB


En 1972 HP produjo un estándar de interconexión, el HPIB (HP Interface Bus), adoptado como el IEEE488-75 General Purpose I.B. Esta es una
sobre simplificación en cuanto a señales, mecanismos y número de periféricos que allí se definen.

Diseñe un sistema que le permita a su PIC 16F84A actuar como dispositivo emisor, para enviar datos a
una impresora (LP), que tiene interfaz GPIB y se comporta sólo como dispositivo receptor de datos. El
protocolo para la Transferencia de Información tiene la siguiente secuencia (ver el siguiente texto y su
diagrama de tiempo asociado):

 Esperar a que la impresora coloque RFD  Hacer que DAV’ valga 1 (datos no
(Ready For Data) en 1 (impresora válidos)
ociosa)  Esperar a que la impresora coloque DAC
 Dar a LP el código de la letra (ASCII, 7 en 0 (Data ACcepted), confirmando que
bits) sabe que ya la información no es válida
 Hacer que DAV’ (! Data AVailable) valga  El PIC puede retirar ya los datos (si
0, indicando información lista para el LP hiciera falta); comienza la secuencia para
 Esperar a que la impresora coloque RFD otra letra...
en 0 (LP no está disponible pues va a
procesar los datos)
 Esperar a que LP coloque DAC en 1;

 PIC_          

Data /\/\/\/\/\/\/\/\/\ /\/\


100 uS 100 uS
DAV’

PRINTER
RFD

DAC
 

C5-272
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

NO todos los estados duran el mismo tiempo; asuma un mínimo de 100 microsegundos (uS) entre cada
transición emanada de su PIC. El t. máximo no está definido. Para inicializar la interfaz del LP, su
PIC debe llevar a 0 la línea IFC (InterFace Clear) al menos 100 uS, dejarla luego en 1 para actividad
normal. (Por sencillez no se considera aquí código para inicializar la I m p r e s o r a en sí)

En su Diagrama en Bloques indique todas las conexiones entre el PIC y la impresora, que tiene 8 bits
de entrada (usted genera sólo 7; ¿qué hace con el octavo?)

Su sistema debe imprimir la frase: “Feliz 2007\nQue pase su examen\n”_

Su código ha de seguir las técnicas de “Structured Programming y Top-Down Design” (estudiadas en


los cursos de programación), con al menos 4 niveles (tiene que definir y codificar todo). Si no sabe hacer
subrutinas (CALL, RETURN), vea algún texto de microprocesadores, consulte sus asignaciones y
referencias del Laboratorio, o escriba macros...; en todo caso, produzca código de tal manera que se
distinga claramente cada uno de los siguientes 4 niveles de subrutinas:

LEVEL 0  LEVEL 1  LEVEL 2  LEVEL 3 


Main()   
 
      some general PIC INIT routines..  ...   
initSystem()  initGpib()  outpIFC() 
...  initPrinter()    ... 
... 
... 
more generic PIC INIT routines.. 

printDOC( TABLE )  printLINE (“Feliz Año\n”)  printCHAR(‘F’)  inpRFD() 


...  printCHAR(‘e’)  outpData(‘
TABLE:  printLINE(“Que pase su  printCHAR(‘l’)  F’) 
“Feliz año\n”  curso\n”)  printCHAR(‘i’)  outpDAV() 
”Que pase su  ...  ...  inpDAC() 
curso\n”  ... 
... 

(Esto es sólo un bosquejo mínimo de las funcionalidades del software; incluya todo lo que sea
necesario: antes, entre y después de las subrutinas indicadas)

3) EL JUEGO DE LA VIDA [Solución]


PLANTEAMIENTO

Empleando 12 LEDs (3 filas, 4 columnas) diseñe con un PIC 16F84A un sistema que ejecute el
llamado Juego de la Vida; en él, los LEDs encendidos representan organismos y cada celda tiene
adyacentes otras 8. El arreglo “plano” formado por los 12 LEDs, representa una esfera (3
dimensiones), por lo que las celdas del techo se “tocan” con las del piso, y las del borde derecho son
vecinas a las del izquierdo. Cada organismo puede tener hasta 8 vecinos; la sobrevivencia y
reproducción de los organismos en cada generación, dependen de la cantidad de vecinos, según estas 4
reglas:

C5-273
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

 Si un organismo no tiene vecinos (0), o solo está acompañado por uno (1), MORIRÁ de soledad.
 Si un organismo tiene dos (2) o tres (3) vecinos, SOBREVIVIRÁ hasta la próxima generación.
 Si un organismo tiene cuatro vecinos o más (>= 4), MORIRÁ a causa de la sobrepoblación.
 En una celda vacía que tiene exactamente tres (3) organismos vecinos, habrá un NACIMIENTO.

Todos los cambios ocurrirán al mismo tiempo; el futuro de cada entidad se basa solo de la actual
generación, con independencia de lo que les vaya a ocurrir a sus vecinos en el estado siguiente. Incluya
retardos adecuados para permitir la observación de las transformaciones en los LEDs.

Sugerencia #1: Emplee 2 arreglos, CURG (CURRENT GENERATION O GENERACIÓN ACTUAL) y NEXTG
(NEXT GENERATION O PRÓXIMA GENERACIÓN), c/u de 3X4 (BITS o BYTES), que contengan un 0 en las
celdas que no alberguen un organismo vivo, y un valor distinto de 0 en caso contrario.

Para cada celda en CURG, el programa mira sus 8 vecinos y establece los cambios para la siguiente etapa;
almacena el resultado en la posición correspondiente de NEXTG y, después de procesar todas las celdas
de CURG, copia NEXTG sobre CURG y procede a actualizar los LEDs de salida.

Sugerencia #2: La parte del programa que analiza las adyacencias se simplifica, al considerar los
bordes, si usa arreglos de 5X6 [(3+2)X(4+2)] Note: Se duplican: la fila del piso, en la nueva fila,
encima del techo, y ésta, en la nueva fila, debajo del piso; la columna derecha se replica en la nueva de la
izquierda y viceversa. Así, los bordes originales ven adyacencias con mayor facilidad.

Explique si sus arreglos son de bits o de bytes y por qué; señale la correspondencia que establecerá
entre sus arreglos y los terminales de salida.

Como parte de la simulación de su programa emplee esta secuencia infinita. A la izquierda, la población
original; luego 4 sucesivas generaciones:

X X X X X X X X X X
X X X X X X X X
X X X X X X X X X  

Este pasatiempo fue desarrollado por el matemático J. Conway de la Universidad de Cambridge (cfr.
bibliografía); resulta interesante con muchos más de 16 organismos, mínimo 64. En el original los
bordes no son adyacentes.

SOLUCIÓN (PROGRAMA LIFE2.C)

Las técnicas del capítulo sobre programación recomiendan, entre otras cosas, separar Políticas y
Mecanismos (cfr. Cap. 4, Técnicas de Programación). La primera solución a este ejemplo se presenta en
lenguaje C y consta de 3 archivos:

C5-274
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

 life2.c
Contiene exclusivamente las Políticas (QUÉ hay que hacer), sin la más mínima referencia a
los Mecanismos (cómo se va a hacer).
 life2.h
Los Mecanismos (CÓMO se va a hacer) se han dividido en dos: 1) Macros y código en línea
se encuentran en este archivo
 life2tr.c
Las Funciones están en este otro documento.
Para compilar: cc life2.c. Correr el programa bajo el debugger para verificar su comportamiento.
También anexo la solución completa que escribí en Assembler para el PIC 16F84A (life.asm;
996 líneas; 462 sin comentarios ni líneas en blanco). Ciertas particularidades del PIC (por ejemplo,
código que debe estar situado en ciertas posiciones), hacen que la versión actual en Assembler y la
del original en C no aparezcan tan apegadas, pero siempre pueden observarse las diferentes
funciones del C representadas en Assembler. Se ha incluido como comentario, parte del código en
C, para ayudar a asociar un texto con otro. Este podría ser el programa en Assembler
más extenso que un estudiante novel de PICs llegue a ver en mucho tiempo. Gran
esfuerzo del profesor; ojalá los alumnos tengan similar dedicación...
El programa debe simularse bajo MPLab; verifique que las figuras presentadas en los puertos A y
B corresponden con las del ejemplo, arriba en esta misma página. Para correrlo en un PIC real hay
que añadirle rutinas de retardo, o algún otro mecanismo que permita separar la presentación de
generaciones sucesivas, y así poder observar el juego en los Leds.

C5-275
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

// life2.c, Ing. Luis G. Uribe C., V03G7   
// ...Politics & Mechanisms Separation  /* ================================================================*/ 
// ==================================================================  // Typedefs, Defines, macros (DoForEver), Function Prototypes, and 
//     This file serves well to illustrate the algorithm, instead  // (perhaps) external variables, should be hidden into a header file 
//     of using a flow diagram; also you may get the assembly   
//     program working directly from here  /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐*/ 
//  /* Typdefs                                                         */ 
// This file has ONLY ***POLITICS*** (WHAT will be done);   
// ..There are NO implied Mechanisms (or How things will be done).  typedef unsigned int uint; 
   
/* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐*/  typedef struct {               // Structure to define the 8 bits 
/* Include Files                                                   */      uint Bit0 : 1;             // ..from a byte Port 
      uint Bit1 : 1; 
#include "life2.h"      uint Bit2 : 1; 
      uint Bit3 : 1; 
DefineGlobals();      uint Bit4 : 1; 
      uint Bit5 : 1; 
/* *************************************************************** */      uint Bit6 : 1; 
void   main ( int argc, char ** argv )                         /*()*/      uint Bit7 : 1; 
{  } Port; 
   
   DefineLocals();   
  /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐*/ 
   InitProcess();  /* Defines                                                         */ 
   
   LoopForever() {  // Define L0 .. L11 as shortcuts to the PortX.BitY names: 
       copyNext2ActualAndDisplay();   
       getNextGen();  #define L0     PortB.Bit0      // Leds have following order: 
   }  #define L1     PortB.Bit1      // L0  L1  L2  L3 
  #define L2     PortB.Bit2      // L4  L5  L6  L7 
}  #define L3     PortB.Bit3      // L8  L9  L10 L11 
  #define L4     PortB.Bit4 
#include "life2Tr.c"  #define L5     PortB.Bit5      // First 8 Leds in PortB 
  #define L6     PortB.Bit6      // ..Reminding 4 Leds in PortA 
  #define L7     PortB.Bit7 
// life2.h, Ing. Luis G. Uribe C., V03G7   
// This file has ONLY ***MECHANISMS*** (HOW Politics will be done)  #define L8     PortA.Bit0      // NOTE: We use PORTS A & B to drive 
// ..(Politics: What will be done)  #define L9     PortA.Bit1      // ..the LEDs, and to store the 
// Mechanisms are divided in two: macros and in‐line code (this file)  #define L10    PortA.Bit2      // ..Current Generation too, so we 
// ..and functions (life2tr.c)  #define L11    PortA.Bit3      // ..preserve RAM memory 
   
/* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */   
/* Include Proyect Specific Files */  // Shortcuts to the nextGenX.BitY names: 
   
#include <stdio.h>  #define N0     nextGenB.Bit0   // This bits represent the NextGen 
#include <stdlib.h>  #define N1     nextGenB.Bit1   // .. array, and use 2 bytes of RAM 
  #define N2     nextGenB.Bit2 
  #define N3     nextGenB.Bit3 

C5-276
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

#define N4     nextGenB.Bit4  int neighborOrganisms;     /* Living beings surrounding a cell */  \ 
#define N5     nextGenB.Bit5  int neighbor_i;            /* The i'th neighbor                */  \ 
#define N6     nextGenB.Bit6   
#define N7     nextGenB.Bit7   
  // ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
#define N8     nextGenA.Bit0  #define InitProcess()                                              \ 
#define N9     nextGenA.Bit1                                                                     \ 
#define N10    nextGenA.Bit2     N0  = X;  N1  = _;  N2  = _;  N3  = X;  /* This implies that */ \ 
#define N11    nextGenA.Bit3     N4  = _;  N5  = _;  N6  = _;  N7  = _;  /* ..PIC drives the  */ \ 
     N8  = X;  N9  = _;  N10 = _;  N11 = _;  /* ..LEDs to ground. */ \ 
#define X      1               // To show initial data in a more   
#define _      0               // .. descriptive way   
  // ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
#define FIRSTCELL   0            #define forEachCell()                                              \ 
#define LASTCELL   12                                                                     \ 
#define NEIGHBORS   8     for( cellPosition = FIRSTCELL; cellPosition < LASTCELL;         \ 
         cellPosition ++ )                                           \ 
/* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐*/   
/* Macro Definitions (General)                                     */  // ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
  #define forEachNeighbor()                                          \ 
#define LoopForever()  while( 1 )                                                                     \ 
     for( neighborOrganisms = neighbor_i  =  0;                      \ 
/* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐*/          neighbor_i < NEIGHBORS; neighbor_i ++ )                    \ 
/* Function Prototypes                                             */   
  // ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
int  applyRule( int cellPosition, int neighborOrganisms );  #define getNextGen()                                               \ 
int  fVecino( int neighbor_i, int cellPosition );                                                                     \ 
void getNextGenf( int cellPosition, int applyRule );         forEachCell() {                                             \ 
             forEachNeighbor() {                                     \ 
                 neighborOrganisms +=                                \ 
// ==================================================================                     fVecino( neighbor_i, cellPosition );            \ 
// Macro for Global Variables definitions                 getNextGenf( cellPosition,                          \ 
                     applyRule( cellPosition, neighborOrganisms ) ); \ 
// This variables need to be seen for several subroutines; they could             }                                                       \ 
// ..be passed as parameters, but in the Assembly language for the         }                                                           \ 
// .. small PIC, we prefer they to be global   
  // ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 
#define DefineGlobals()                                            \  #define copyNext2ActualAndDisplay()                                \ 
                                                                   \                                                                     \ 
Port PortA, PortB, nextGenB, nextGenA;                             \  /* Copy nextGenX array into PortX bits; this will light the LEDs*/ \ 
                                                                     \ 
     L0  = N0;  L1  = N1;  L2  = N2;  L3  = N3;                      \ 
// ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐     L4  = N4;  L5  = N5;  L6  = N6;  L7  = N7;                      \ 
// Macro for Local Variables definitions     L8  = N8;  L9  = N9;  L10 = N10; L11 = N11;                     \ 
                                                                     \ 
#define DefineLocals()                                             \  /* The following lines are used to verify program under PC. */     \ 
                                                                   \  /* Comment them out for running in the PIC microcontroller */      \ 
int cellPosition;          /* Twelve: 0..11                    */  \                                                                     \ 

C5-277
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

   printf( "%c ",   L0  == X ? 'X' : '_' );    /* 1st line */      \         case 11: thereIsAnOrganism = L11; break; 
   printf( "%c ",   L1  == X ? 'X' : '_' );                        \     } 
   printf( "%c ",   L2  == X ? 'X' : '_' );                        \   
   printf( "%c \n", L3  == X ? 'X' : '_' );                        \   
   printf( "%c ",   L4  == X ? 'X' : '_' );    /* 2nd line */      \   
   printf( "%c ",   L5  == X ? 'X' : '_' );                        \   
   printf( "%c ",   L6  == X ? 'X' : '_' );                        \   
   printf( "%c \n", L7  == X ? 'X' : '_' );    /* 3rd line */      \   
   printf( "%c ",   L8  == X ? 'X' : '_' );                        \     if( thereIsAnOrganism ) {   // in this cellPosition 
   printf( "%c ",   L9  == X ? 'X' : '_' );                        \         switch( neighborOrganisms ) {   // Who many? 
   printf( "%c ",   L10 == X ? 'X' : '_' );                        \   
   printf( "%c \n", L11 == X ? 'X' : '_' );    /* finish frame */  \             case 0:             // Will be DEAD, as if by loneliness 
                                                                   \             case 1: 
   getchar();  /* This will simulate DELAY; ENTER continues. */    \                 return 0; 
               /* Press Control‐C or Control‐Break to finish.*/    \             break; 
   
             case 2:             // Will SURVIVE 
// lifetr.c, Ing. Luis G. Uribe C., trailing file V03G7             case 3: 
// This file has ONLY ***MECHANISMS*** (HOW Politics will be done)                 return 1; 
// ..(Politics: What will be done)             break; 
// Mechanisms are divided in two: macros and in‐line code (life2.h)   
// ..and functions (this trailing file)             case 4: 
             default: 
/* =============================================================== */                 return 0;       // Will be DEAD, as if by overcrowding 
int applyRule( int cellPosition, int neighborOrganisms )       /*()*/             break; 
{         } 
     } 
   // Returns 1 if the rules imply that there will be an organism in   
   // ..the next generation for this amount of neighborOrganisms.     // NOTE: There are implied else statements here, above and below. 
   // Note that returning 1 implies to light the LED, and it will     // ..Above, because all cases execute a 'return' statement and 
   // ..happen if the cell was empty and a new organism has born, or     // ..give up program flow control to the calling routine. 
   // ..if a preexistent organism has survived. Zero means to turn     // Same occurs bellow. 
   // ..off the LED.      // 
     // CELL IS EMPTY if program comes to run this instructions, so, 
   int thereIsAnOrganism;     // the rules now are: 
   
   switch( cellPosition ) {     if( neighborOrganisms == 3 ) 
       case 0:  thereIsAnOrganism = L0;  break;         return 1;   // WILL BORN !!! 
       case 1:  thereIsAnOrganism = L1;  break;   
       case 2:  thereIsAnOrganism = L2;  break;     return 0;               // cell was, and will continue to be empty 
       case 3:  thereIsAnOrganism = L3;  break;   
       case 4:  thereIsAnOrganism = L4;  break;  }  /* applyRule() */ 
       case 5:  thereIsAnOrganism = L5;  break;   
       case 6:  thereIsAnOrganism = L6;  break;   
       case 7:  thereIsAnOrganism = L7;  break;  /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */ 
       case 8:  thereIsAnOrganism = L8;  break;  int fVecino ( int neighbor_i, int cellPosition )               /*()*/ 
       case 9:  thereIsAnOrganism = L9;  break;  { 
       case 10: thereIsAnOrganism = L10; break;   

C5-278
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

   // Function Vecino returns 1 if there is a i'th neighbor organism             switch( neighbor_i ) {      // Eight neighbors: from 0..7 
   // .. (0..7) for some actual 'cellPosition' (0..12);                 case 0: return L11; case 1: return L8; 
   // Returns 0 if the neighbor_i is an empty cell.                 case 2: return L9;  case 3: return L3; 
   //                 case 4: return L1;  case 5: return L7; 
   // NOTE: The Current Generation information is stored in the same                 case 6: return L4;  case 7: return L5; 
   //       ..bits of Ports A & B used to light the LEDs, so             } 
   //       ..returning the LED bit from PORT is returning it's value         break; 
   //   
   
   
   // THIS ARE THE 8 NEIGHBORS FOR EACH CELL:   
   // ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐   
   // 0:  11,  8,  9,  3,  1,  7,  4,  5         case 1: 
   // 1:   8,  9, 10,  0,  2,  4,  5,  6             switch( neighbor_i ) { 
   // 2:   9, 10, 11,  1,  3,  5,  6,  7                 case 0: return L8;  case 1: return L9; 
   // 3:  10, 11,  8,  2,  0,  6,  7,  4                 case 2: return L10; case 3: return L0; 
   // 4:   3,  0,  1,  7,  5,  11, 8,  9                 case 4: return L2;  case 5: return L4; 
   // 5:   0,  1,  2,  4,  6,  8,  9, 10                 case 6: return L5;  case 7: return L6; 
   // 6:   1,  2,  3,  5,  7,  9, 10, 11             } 
   // 7:   2,  3,  0,  6,  4, 10, 11,  8         break; 
   // 8:   7,  4,  5, 11,  9,  3,  0,  1   
   // 9:   4,  5,  6,  8, 10,  0,  1,  2         case 2: 
   // 10:  5,  6,  7,  9, 11,  1,  2,  3             switch( neighbor_i ) { 
   // 11:  6,  7,  4, 10,  8,  2,  3,  0                 case 0: return L9;  case 1: return L10; 
   //                 case 2: return L11; case 3: return L1; 
   // HOW WE IMPLEMENT fVecino:                 case 4: return L3;  case 5: return L5; 
   //                 case 6: return L6;  case 7: return L7; 
   // We use a 12*8 = 96 positions table to implement this function;             } 
   // ..this 'brute force' approach takes RAM but is straightforward:         break; 
   // ..you only need to read the neighbors to each cell from the   
   // ..check board for the game, and make‐up following switch/cases         case 3: 
   // ..control structures.             switch( neighbor_i ) { 
   //                 case 0: return L10; case 1: return L11; 
   // MINIMIZATIONS COULD BE DONE.                 case 2: return L8;  case 3: return L2; 
   // For example, store TWO values in each byte, using it's 2                 case 4: return L0;  case 5: return L6; 
   // ..nibbles (half the RAM).                 case 6: return L7;  case 7: return L4; 
   // ..Or develop some algorithmic relationships between files and             } 
   // ..columns IDs for each cell and it's neighbors; you may help         break; 
   // ..yourself replying border rows and columns to make processing   
   // ..easy.         case 4: 
   // Note that working with rows and columns need the main program             switch( neighbor_i ) { 
   // ..change current strategy, from looping through 12 cells to                 case 0: return L3;  case 1: return L0; 
   // ..looping through 3 rows, then looping through 4 columns.                 case 2: return L1;  case 3: return L7; 
   //                  case 4: return L5;  case 5: return L11; 
   // *** NONE OF THIS WAS DONE HERE ***                 case 6: return L8;  case 7: return L9; 
             } 
   switch( cellPosition ) {           // Twelve values: form 0..11         break; 
       case 0:   

C5-279
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

       case 5:                 case 2: return L7;  case 3: return L9; 
           switch( neighbor_i ) {                 case 4: return L11; case 5: return L1; 
               case 0: return L0;  case 1: return L1;                 case 6: return L2;  case 7: return L3; 
               case 2: return L2;  case 3: return L4;             } 
               case 4: return L6;  case 5: return L8;         break; 
               case 6: return L9;  case 7: return L10;   
           }   
       break;         case 11: 
             switch( neighbor_i ) { 
       case 6:                 case 0: return L6;  case 1: return L7; 
           switch( neighbor_i ) {                 case 2: return L4;  case 3: return L10; 
               case 0: return L1;  case 1: return L2;                 case 4: return L8;  case 5: return L2; 
               case 2: return L3;  case 3: return L5;                 case 6: return L3;  case 7: return L0; 
               case 4: return L7;  case 5: return L9;             } 
               case 6: return L10; case 7: return L11;         break; 
           }     } 
       break;   
  }  /* fVecino() */ 
       case 7:   
           switch( neighbor_i ) {   
               case 0: return L2;  case 1: return L3;  /* ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ */ 
               case 2: return L0;  case 3: return L6;  void getNextGenf ( int cellPosition,                           /*()*/ 
               case 4: return L4;  case 5: return L10;                     int resultsOfApplyingRules )                /*()*/ 
               case 6: return L11; case 7: return L8;  { 
           }   
       break;     // Produce the Next Generation Element for this cellPosition, 
     // ..into internal nextGen B & A variables (they are GLOBALS). 
       case 8:     // Uses the result of applying game's Rule to this cell, with it's 
           switch( neighbor_i ) {     // ..calculated amount of neighborOrganisms (See calling routine) 
               case 0: return L7;  case 1: return L4;     // Return values accessing global variables. 
               case 2: return L5;  case 3: return L11;   
               case 4: return L9;  case 5: return L3;     switch( cellPosition ) { 
               case 6: return L0;  case 7: return L1;         case 0:  N0  = resultsOfApplyingRules; break; 
           }         case 1:  N1  = resultsOfApplyingRules; break; 
       break;         case 2:  N2  = resultsOfApplyingRules; break; 
         case 3:  N3  = resultsOfApplyingRules; break; 
       case 9:         case 4:  N4  = resultsOfApplyingRules; break; 
           switch( neighbor_i ) {         case 5:  N5  = resultsOfApplyingRules; break; 
               case 0: return L4;  case 1: return L5;         case 6:  N6  = resultsOfApplyingRules; break; 
               case 2: return L6;  case 3: return L8;         case 7:  N7  = resultsOfApplyingRules; break; 
               case 4: return L10; case 5: return L0;   
               case 6: return L1;  case 7: return L2;         case 8:  N8  = resultsOfApplyingRules; break; 
           }         case 9:  N9  = resultsOfApplyingRules; break; 
       break;         case 10: N10 = resultsOfApplyingRules; break; 
         case 11: N11 = resultsOfApplyingRules; break; 
       case 10:     } 
           switch( neighbor_i ) {   
               case 0: return L5;  case 1: return L6;  }  /* getNextGen() */ 

C5-280
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

 
l i f e . a s m
 
; Ing. Luis G. Uribe C., M06F7         resultsOfApplyingRules  ; auxiliary     goto    readL5 
                 ;.. variable for getNextGen     goto    readL6 
 __CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON &     ENDC     goto    readL7 
_XT_OSC       goto    readL8 
    LIST       P=16F84A     ORG     0     goto    readL9 
    INCLUDE  <P16F84A.INC>     goto main;     goto    readL10 
; Defines       goto    readL11 
#define    L0  PORTB,0     ORG     0x004     ; Interrupt vector  ; this code, from 'applyRule', need to be 
#define    L1  PORTB,1  ;  goto delay;  ;..in lower memory 
#define    L2  PORTB,2     nop   
#define    L3  PORTB,3    lowerThan4: 
#define    L4  PORTB,4  ; int applyRule( int cellPosition,     movfw   neighborOrganisms   ; for this 
#define    L5  PORTB,5            ;..int neighborOrganisms ) /*()*/                           ;..cellPosition? 
#define    L6  PORTB,6  ;     addwf   PCL,F 
#define    L7  PORTB,7  ; Returns 1 if the rules imply that there  applyRuleTable: 
#define    L8  PORTA,0  ;..will be an organism in the next     goto    rule0 
#define    L9  PORTA,1  ;..generation for this amount of     goto    rule1 
#define    L10 PORTA,2  ;..neighborOrganisms.     goto    rule2 
#define    L11 PORTA,3  ; Note that returning 1 implies to light on     goto    rule3 
  ;..the LED, and it will happen if the cell   
#define    N0  nextGenB,0  ;..was empty and a new organism has born,  ; this code, from 'fVecino', need to be in 
#define    N1  nextGenB,1  ;..or if preexistent organism has survived.  ;..lower memory 
#define    N2  nextGenB,2  ;Zero means to turn off the LED.   
#define    N3  nextGenB,3  ;  fVecino: 
#define    N4  nextGenB,4  ; NOTE: This routine header must be placed     clrf    vecino 
#define    N5  nextGenB,5  ;..near the beginning, to avoid problems     movfw   cellPosition 
#define    N6  nextGenB,6  ;..with  addwf PCL,F     addwf   cellPosition,W 
#define    N7  nextGenB,7       addwf   cellPosition,W 
  applyRule:     addwf   cellPosition,W 
#define    N8  nextGenA,0     CBLOCK     addwf   cellPosition,W 
#define    N9  nextGenA,1         thereIsAnOrganism     addwf   cellPosition,W 
#define    N10 nextGenA,2     ENDC     addwf   cellPosition,W 
#define    N11 nextGenA,3       addwf   cellPosition,W 
     clrf    thereIsAnOrganism   
; Variables Definition     movfw   cellPosition          ;; ;TODO:     addwf   neighbor_i,W 
   CBLOCK  0x10              ;..restrain cellPosition 0..11     addwf   PCL,F 
       nextGenB        ; internal copy of     addwf   PCL,F   
            ;..PORTB, for next Generation  applyReadTable:  fVecinoTable: 
       nextGenA  ; internal copy of PORTA     goto    readL0     goto RL11 
       cellPosition       ; Twelve: 0..11     goto    readL1     goto RL8 
       neighborOrganisms       ; Living     goto    readL2     goto RL9 
             ;..beings surrounding a cell     goto    readL3     goto RL3 
       neighbor_i      ; The i'th neighbor     goto    readL4     goto RL1 
   goto RL7 

C5-281
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

   goto RL4     goto RL1     goto RL10 


   goto RL5     goto RL2     goto RL8 
     goto RL3     goto RL2 
   goto RL8     goto RL5     goto RL3 
   goto RL9     goto RL7     goto RL0 
   goto RL10     goto RL9   
   goto RL0     goto RL10  ; this code, from 'getNextGen', need to be 
   goto RL2     goto RL11  ;..in lower memory 
   goto RL4       getNextGen: 
   goto RL5     goto RL2   
   goto RL6     goto RL3     movfw   cellPosition 
     goto RL0     addwf   PCL,F 
   goto RL9     goto RL6   
   goto RL10     goto RL4  getNextGenTable: 
   goto RL11     goto RL10     goto NextN0 
   goto RL1     goto RL11     goto NextN1 
   goto RL3     goto RL8     goto NextN2 
   goto RL5          goto NextN3 
   goto RL6     goto RL7     goto NextN4 
   goto RL7     goto RL4     goto NextN5 
        goto RL5     goto NextN6 
   goto RL10     goto RL11     goto NextN7 
   goto RL11     goto RL9     goto NextN8 
   goto RL8     goto RL3     goto NextN9 
   goto RL2     goto RL0     goto NextN10 
   goto RL0     goto RL1     goto NextN11 
   goto RL6        
   goto RL7     goto RL4  main: 
   goto RL4     goto RL5 
        goto RL6  init: 
   goto RL3     goto RL8     clrf    PORTB       ; First, set Port B 
   goto RL0     goto RL10               ;..to SAFE/Innocuous value Now 
   goto RL1     goto RL0               ;.. Program Port B for output: 
   goto RL7     goto RL1     clrf    PORTA       ; Set Port A too 
   goto RL5     goto RL2     bsf     STATUS,RP0  ; .. STATUS bit (5) 
   goto RL11                           ;.. = 1: Select Bank 1 
   goto RL8     goto RL5     clrf    TRISB       ; .. All bits of 
   goto RL9     goto RL6              ;..Port B configured for Output 
        goto RL7     movlw   b'1110000'  ; .. PortA, Bits 
   goto RL0     goto RL9                 ;..0, 1, 2 &  3, for Output 
   goto RL1     goto RL11     movwf   TRISA 
   goto RL2     goto RL1     bcf     STATUS,RP0  ; .. STATUS bit 
   goto RL4     goto RL2                   ;..5 = 0: ReSelect Bank 0 
   goto RL6     goto RL3   
   goto RL8          ; Use following example (beginning and 
   goto RL9     goto RL6     ;..following states shown) 
   goto RL10     goto RL7  ;RB b0 b1 b2 b3 X _ _ X   X _ _ X   _ X X _ 
        goto RL4  ;RB b4 b5 b6 b7 _ _ _ _   X _ _ X   _ X X _ 

C5-282
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

;RA b0 b1 b2 b3 X _ _ _   X _ _ X   _ X X _  for1:                  ;..'resultsOfApplyingRules' 


       movwf   resultsOfApplyingRules 
   ; init next Generation with above     clrf    cellPosition   
   ;..example pattern:       call    getNextGen  ; for cellPosition 
  for1test:              ;..and resultsOfApplyingRules 
   movlw   b'00001001' ; NOTE: Bits are in     movlw   .12   
          ;..REVERSE order from the above!!     subwf   cellPosition,W  for1loop: 
   movwf   nextGenB    ; .. table     btfsc   STATUS,Z    ; Goto nextGen if     incf    cellPosition,F 
                        ;..cellPosition == 12     goto    for1test 
   movlw   b'00000001' ; Note: only bits     goto    for1end     ; Fall into for2, if   
                       ;..0..3 are in use                         ;..cellPosition < 12  for1end: 
   movwf   nextGenA    ; .. in PORTA       goto LoopForever 
  for1body:   
   ; MAIN PROGRAM FLOW:  ;     for(neighborOrganisms=neighbor_i=0;  ; int applyRule( int cellPosition, 
   ; ‐ First, copy internally stored              ;..neighbor_i<8;neighbor_i++) { 
;..          int neighborOrganisms ) /*()*/ 
   ; ..'nextGeneration'   data into  for2: 

   ; ..actualGeneration  (this will light     clrf    neighborOrganisms  ; Returns 1 if the rules imply that there 
   ; ..the LEDs!!!). Note that above     clrf    neighbor_i  ;..will be an organism in the next 
   ; ..initializes 'nextGeneration' instead  for2test:  ;..generation for this amount of 
   ; ..of actualGeneration LEDs ...     movlw   .8 
;..neighborOrganisms. 
   ;     subwf   neighbor_i,W 
; Note that returning 1 implies to light 
   ; ‐ Loop through all twelve     btfsc   STATUS,Z    ; Goto for2end if 
;..the LED, and it will happen if the cell 
   ; ..cellPositions; for each, inspect                           ;..neighbor_i == 8 
;..was empty and a new organism has born, 
   ; ..all it's eight neighbors and count     goto    for2end 
;..or if a preexistent organism has 
   ; ..how many are alive, into    ;..survived. 
   ; ..'neighborOrganisms' variable  for2body:  ;..Zero means to turn off the LED.  
   ;  ;     neighborOrganisms +=  ; NOTE: This routine header must be placed 
   ; ‐ Then, get the nextGeneration cell  ;..       fVecino(neighbor_i,cellPosition);  ;..near the beginning, to avoid problems 
   ; ..position into nextGen array,    ;..with  addwf PCL,F 
   ; ..applying game's rules to actual     call    fVecino  ;; FOLLOWING CODE HAS BEEN MOVED UP IN MEM. 
   ; ..cellPosition           ; fVecino(neighbor_i,cellPosition)  ;; ;applyRule: 
   ;           ;..RetVal: W  ;; ; 
   ; ‐ Loop for ever     movfw   vecino  ;; ;   CBLOCK 
     addwf   neighborOrganisms,F  ;; ;       thereIsAnOrganism 
LoopForever:    ;; ;   ENDC 
  for2loop:  ;; ; 
copyNext2ActualAndDisplay:     ;; ;TODO:     incf    neighbor_i,F  ;; ;   clrf    thereIsAnOrganism    
                       ;..DELAY w/Timer0     goto    for2test  ;; ;   movfw   cellPosition       ;; ;TODO: 
   movfw   nextGenB                 ;..restrain cellPosition 0..11 
   movwf   PORTB  for2end:  ;; ;   addwf   PCL,F 
  ; getNextGen( cellPosition,  ;; ; 
   movfw   nextGenA  ;..           applyRule(cellPosition,  ;; ;applyReadTable: 
   movwf   PORTA  ;..                    neighborOrganisms));  ;; ;   goto    readL0 
   nop    ;; ;   goto    readL1 
     call    applyRule   ; for cellPosition  ;; ;   goto    readL2 
;  for( cellPosition = 0;                    :..and neighborOrganisms.  ;; ;   goto    readL3 
;..cellPosition < 12; cellPosition ++ ) {                         ; RetVal in  ;; ;   goto    readL4 

C5-283
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

;; ;   goto    readL5  readL10:  ; this code, from 'applyRule', need to be 


;; ;   goto    readL6     btfsc   L10  ;..in lower memory 
;; ;   goto    readL7     incf    thereIsAnOrganism,F  ;; FOLLOWING CODE HAS BEEN MOVED UP IN MEM. 
;; ;   goto    readL8     goto    theRules  ;; ;lowerThan4: 
;; ;   goto    readL9  readL11:  ;; ;   movfw   thereIsAnOrganism   ; in 
;; ;   goto    readL10     btfsc   L11                       ;..this cellPosition? 
;; ;   goto    readL11     incf    thereIsAnOrganism,F  ;; ;   addwf   PCL,F 
  ;  goto    theRules  ;; ;applyRuleTable: 
readL0:    ;; ;   goto    rule0 
   btfsc   L0  theRules:  ;; ;   goto    rule1 
   incf    thereIsAnOrganism,F  ;    if( thereIsAnOrganism ) {   // in this  ;; ;   goto    rule2 
   goto    theRules                              ;..cellPosition  ;; ;   goto    rule3 
readL1:  ;        switch( neighborOrganisms ){// How  rule0: 
   btfsc   L1                                     ;..many?  rule1: 
   incf    thereIsAnOrganism,F  ;            case 0:             // DEAD by  rule4: 
   goto    theRules                               ;.. loneliness     retlw   .0 
readL2:  ;            case 1:   
   btfsc   L2  ;                return 0;  rule2: 
   incf    thereIsAnOrganism,F  ;            break;  rule3: 
   goto    theRules  ;      retlw   .1 
readL3:  ;            case 2:             // SURVIVE   
   btfsc   L3  ;            case 3:  born: 
   incf    thereIsAnOrganism,F  ;                return 1;  ; CELL IS EMPTY if program comes to run 
   goto    theRules  ;            break;  ;..this instructions, so now the rules are: 
readL4:  ;   ;    if( neighborOrganisms == 3 ) 
   btfsc   L4  ;            case 4:  ;        return 1;   // WILL BORN !!! 
   incf    thereIsAnOrganism,F  ;            default:  ;   return 0;             // cell was, and 
   goto    theRules  ;                return 0;       // DEAD by                ;..will continue to be empty 
readL5:                              ;..overcrowding     movfw   neighborOrganisms 
   btfsc   L5  ;            break;     sublw   .3 
   incf    thereIsAnOrganism,F       btfsc   STATUS,Z    ; Goto for2end if 
   goto    theRules     movf    thereIsAnOrganism,F ; ... in                         ;..neighbor_i == 8 
readL6:                        ;..this cellPosition?     retlw   .1 
   btfsc   L6     btfsc   STATUS,Z            ; goto born     retlw   .0 
   incf    thereIsAnOrganism,F                         ;..if cell is empty   
   goto    theRules     goto    born 
readL7:  ; fVecino: 
organismInCell: 
   btfsc   L7  ; int fVecino ( int neighbor_i, 
   movlw   .4                  ; First, 
   incf    thereIsAnOrganism,F                 ;..int cellPosition ) /*()*/ 
                 ;..test to see if >= 4 
   goto    theRules  ; Function Vecino returns 1 if there is a 
   subwf   neighborOrganisms,W ; Compare 
readL8:  ;..i'th neighbor organism (0..7) for some 
              ;..neighborOrganisms, L(w) 
   btfsc   L8  ;..actual 'cellPosition' (0..12); 
   btfsc   STATUS,C            ; goto  ; Returns 0 if the neighbor_i is an empty 
   incf    thereIsAnOrganism,F        ;..Address if C == 1 (higher/same) 
   goto    theRules  ;..cell. 
   goto    rule4     ; goto rule4 is better  ;  
readL9:                            ;..than: retlw .0 
   btfsc   L9  ; NOTE: The Current Generation information 
   goto   lowerThan4           ; to place 
   incf    thereIsAnOrganism,F  ;..is stored in the same bits of Ports A & 
          ;..'lowerThan4' in lower memory 
   goto    theRules  ;..B used to light the LEDs, so returning 
 

C5-284
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

;..the LED bit from PORT is returning it's  ;           switch( neighbor_i ) {    // 8  ;       }; break; 


;..value                      ;..neighbors: from 0..7  ;       case 7: 
;   ;   case 0: return L11; case 1: return L8;  ;           switch( neighbor_i ) { 
; THIS ARE THE 8 NEIGHBORS FOR EACH CELL:  ;   case 2: return L9;  case 3: return L3;  ;   case 0: return L2;  case 1: return L3; 
; ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐  ;   case 4: return L1;  case 5: return L7;  ;   case 2: return L0;  case 3: return L6; 
;  0: 11,  8,  9,  3,  1,  7,  4,  5  ;   case 6: return L4;  case 7: return L5;  ;   case 4: return L4;  case 5: return L10; 
;  1:  8,  9, 10,  0,  2,  4,  5,  6  ;       }; break;  ;   case 6: return L11; case 7: return L8; 
;  2:  9, 10, 11,  1,  3,  5,  6,  7  ;       case 1:  ;       }; break; 
;  3: 10, 11,  8,  2,  0,  6,  7,  4  ;           switch( neighbor_i ) {  ;       case 8: 
;  4:  3,  0,  1,  7,  5,  11, 8,  9  ;   case 0: return L8;  case 1: return L9;  ;           switch( neighbor_i ) { 
;  5:  0,  1,  2,  4,  6,  8,  9, 10  ;   case 2: return L10; case 3: return L0;  ;   case 0: return L7;  case 1: return L4; 
;  6:  1,  2,  3,  5,  7,  9, 10, 11  ;   case 4: return L2;  case 5: return L4;  ;   case 2: return L5;  case 3: return L11; 
;  7:  2,  3,  0,  6,  4, 10, 11,  8  ;   case 6: return L5;  case 7: return L6;  ;   case 4: return L9;  case 5: return L3; 
;  8:  7,  4,  5, 11,  9,  3,  0,  1  ;       }; break;  ;   case 6: return L0;  case 7: return L1; 
;  9:  4,  5,  6,  8, 10,  0,  1,  2  ;       case 2:  ;       }; break; 
; 10:  5,  6,  7,  9, 11,  1,  2,  3  ;           switch( neighbor_i ) {  ;       case 9: 
; 11:  6,  7,  4, 10,  8,  2,  3,  0  ;   case 0: return L9;  case 1: return L10;  ;           switch( neighbor_i ) { 
;   ;   case 2: return L11; case 3: return L1;  ;   case 0: return L4;  case 1: return L5; 
; HOW WE IMPLEMENT fVecino:  ;   case 4: return L3;  case 5: return L5;  ;   case 2: return L6;  case 3: return L8; 
;   ;   case 6: return L6;  case 7: return L7;  ;   case 4: return L10; case 5: return L0; 
; We use a 12*8 = 96 positions table to  ;       }; break;  ;   case 6: return L1;  case 7: return L2; 
;..implement this function; this 'brute  ;       case 3:  ;       }; break; 
;..force' approach takes RAM but is  ;           switch( neighbor_i ) {  ;       case 10: 
;..straightforward: you only need to read  ;   case 0: return L10; case 1: return L11;  ;           switch( neighbor_i ) { 
;..the neighbors to each cell from the  ;   case 2: return L8;  case 3: return L2;  ;   case 0: return L5;  case 1: return L6; 
; ..check board for the game, and make‐up  ;   case 4: return L0;  case 5: return L6;  ;   case 2: return L7;  case 3: return L9; 
;..following switch/cases control  ;   case 6: return L7;  case 7: return L4;  ;   case 4: return L11; case 5: return L1; 
;..structures.  ;       }; break;  ;   case 6: return L2;  case 7: return L3; 
  ;       case 4:  ;       }; break; 
; MINIMIZATIONS COULD BE DONE.  ;           switch( neighbor_i ) {  ;       case 11: 
; For example, store TWO values in each  ;   case 0: return L3;  case 1: return L0;  ;           switch( neighbor_i ) { 
;..byte, using it's 2 nibbles (half the  ;   case 2: return L1;  case 3: return L7;  ;   case 0: return L6;  case 1: return L7; 
;..RAM).  ;   case 4: return L5;  case 5: return L11;  ;   case 2: return L4;  case 3: return L10; 
; ..Or develop some algorithmic ;..relationships  ;   case 6: return L8;  case 7: return L9;  ;   case 4: return L8;  case 5: return L2; 
between files and columns  ;       }; break;  ;   case 6: return L3;  case 7: return L0; 
;..IDs for each cell and it's neighbors;  ;       case 5:  ;       }; break; 
;..you may help yourself replying border  ;           switch( neighbor_i ) {  ; } 
;..rows and columns to make processing easy  ;   case 0: return L0;  case 1: return L1;   
; Note that working with rows and columns  ;   case 2: return L2;  case 3: return L4;  ;  make a table, using 
;..need the main program change current  ;   case 4: return L6;  case 5: return L8;  ;.. cellPosition * 8 + neighbor_I 
;..strategy, from looping through 12 cells  ;   case 6: return L9;  case 7: return L10;  ;.. as an index: 
;..to looping through 3 rows, then looping  ;       }; break;   
;..through 4 columns.  ;       case 6:     CBLOCK 
; *** NONE OF THIS WAS DONE HERE ***     .  ;           switch( neighbor_i ) {         vecino 
  ;   case 0: return L1;  case 1: return L2;     ENDC 
;   switch( cellPosition ) {// 12 values:  ;   case 2: return L3;  case 3: return L5;   
                             ;..form 0..11  ;   case 4: return L7;  case 5: return L9;  ; this code, from 'fVecino', need to be in 
;       case 0:  ;   case 6: return L10; case 7: return L11;  ;..lower memory 

C5-285
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

;; FOLLOWING CODE HAS BEEN MOVED UP IN MEM.  ;; ;   goto RL6  ;; ;    


;; ;fVecino:  ;; ;   goto RL7  ;; ;   goto RL4 
;; ;   clrf    vecino  ;; ;   goto RL4  ;; ;   goto RL5 
;; ;   movfw   cellPosition  ;; ;     ;; ;   goto RL6 
;; ;   addwf   cellPosition,W  ;; ;   goto RL3  ;; ;   goto RL8 
;; ;   addwf   cellPosition,W  ;; ;   goto RL0  ;; ;   goto RL10 
;; ;   addwf   cellPosition,W  ;; ;   goto RL1  ;; ;   goto RL0 
;; ;   addwf   cellPosition,W  ;; ;   goto RL7  ;; ;   goto RL1 
;; ;   addwf   cellPosition,W  ;; ;   goto RL5  ;; ;   goto RL2 
;; ;   addwf   cellPosition,W  ;; ;   goto RL11  ;; ;    
;; ;   addwf   cellPosition,W  ;; ;   goto RL8  ;; ;   goto RL5 
;; ;  ;; ;   goto RL9  ;; ;   goto RL6 
;; ;   addwf   neighbor_i,W  ;; ;     ;; ;   goto RL7 
;; ;   addwf   PCL,F  ;; ;   goto RL0  ;; ;   goto RL9 
;; ;  ;; ;   goto RL1  ;; ;   goto RL11 
;; ;fVecinoTable:  ;; ;   goto RL2  ;; ;   goto RL1 
;; ;   goto RL11  ;; ;   goto RL4  ;; ;   goto RL2 
;; ;   goto RL8  ;; ;   goto RL6  ;; ;   goto RL3 
;; ;   goto RL9  ;; ;   goto RL8  ;; ;    
;; ;   goto RL3  ;; ;   goto RL9  ;; ;   goto RL6 
;; ;   goto RL1  ;; ;   goto RL10  ;; ;   goto RL7 
;; ;   goto RL7  ;; ;     ;; ;   goto RL4 
;; ;   goto RL4  ;; ;   goto RL1  ;; ;   goto RL10 
;; ;   goto RL5  ;; ;   goto RL2  ;; ;   goto RL8 
;; ;  ;; ;   goto RL3  ;; ;   goto RL2 
;; ;   goto RL8  ;; ;   goto RL5  ;; ;   goto RL3 
;; ;   goto RL9  ;; ;   goto RL7  ;; ;   goto RL0 
;; ;   goto RL10  ;; ;   goto RL9   
;; ;   goto RL0  ;; ;   goto RL10  RL0: 
;; ;   goto RL2  ;; ;   goto RL11     btfsc   L0 
;; ;   goto RL4  ;; ;        incf    vecino,F 
;; ;   goto RL5  ;; ;   goto RL2     return 
;; ;   goto RL6  ;; ;   goto RL3  RL1: 
;; ;  ;; ;   goto RL0     btfsc   L1 
;; ;   goto RL9  ;; ;   goto RL6     incf    vecino,F 
;; ;   goto RL10  ;; ;   goto RL4     return 
;; ;   goto RL11  ;; ;   goto RL10  RL2: 
;; ;   goto RL1  ;; ;   goto RL11     btfsc   L2 
;; ;   goto RL3  ;; ;   goto RL8     incf    vecino,F 
;; ;   goto RL5  ;; ;        return 
;; ;   goto RL6  ;; ;   goto RL7  RL3: 
;; ;   goto RL7  ;; ;   goto RL4     btfsc   L3 
;; ;     ;; ;   goto RL5     incf    vecino,F 
;; ;   goto RL10  ;; ;   goto RL11     return 
;; ;   goto RL11  ;; ;   goto RL9  RL4: 
;; ;   goto RL8  ;; ;   goto RL3     btfsc   L4 
;; ;   goto RL2  ;; ;   goto RL0     incf    vecino,F 
;; ;   goto RL0  ;; ;   goto RL1     return 

C5-286
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

RL5:  ;     case 3:  N3 = resultsOfApplyingRules;     movf    resultsOfApplyingRules,F 


   btfsc   L5  ;     break;               ; test resultsOfApplyingRules 
   incf    vecino,F  ;     case 4:  N4 = resultsOfApplyingRules;     btfss   STATUS,Z 
   return  ;     break;     bsf     N1  ; set bit N1 conditionally 
RL6:  ;     case 5:  N5 = resultsOfApplyingRules;     return 
   btfsc   L6  ;     break;   
   incf    vecino,F  ;     case 6:  N6 = resultsOfApplyingRules;  NextN2: 
   return  ;     break;     bcf     N2 
RL7:  ;     case 7:  N7 = resultsOfApplyingRules;     movf    resultsOfApplyingRules,F 
   btfsc   L7  ;     break;               ; test resultsOfApplyingRules 
   incf    vecino,F  ;     case 8:  N8 = resultsOfApplyingRules;     btfss   STATUS,Z 
   return  ;     break;     bsf     N2  ; set bit N2 conditionally 
RL8:  ;     case 9:  N9 = resultsOfApplyingRules;     return 
   btfsc   L8  ;     break;   
   incf    vecino,F  ;     case 10: N10= resultsOfApplyingRules;  NextN3: 
   return  ;     break;     bcf     N3 
RL9:  ;     case 11: N11= resultsOfApplyingRules;     movf    resultsOfApplyingRules,F 
   btfsc   L9  ;     break;               ; test resultsOfApplyingRules 
   incf    vecino,F  ;this code getNextGen needed in low memory     btfss   STATUS,Z 
   return  ;; FOLLOWING CODE HAS BEEN MOVED UP IN MEM.     bsf     N3  ; set bit N3 conditionally 
RL10:       return 
   btfsc   L10  ;; ;getNextGen:   
   incf    vecino,F  ;; ;   movfw   cellPosition  NextN4: 
   return  ;; ;   addwf   PCL,F     bcf     N4 
RL11:  ;; ;getNextGenTable:     movf    resultsOfApplyingRules,F 
   btfsc   L11  ;; ;   goto NextN0               ; test resultsOfApplyingRules 
   incf    vecino,F  ;; ;   goto NextN1     btfss   STATUS,Z 
   return  ;; ;   goto NextN2     bsf     N4  ; set bit N4 conditionally 
  ;; ;   goto NextN3     return 
;void getNextGen (int cellPosition,  ;; ;   goto NextN4   
;..     int resultsOfApplyingRules) /*()*/  ;; ;   goto NextN5  NextN5: 
;..  ;; ;   goto NextN6     bcf     N5 
; Produce the Next Generation Element for  ;; ;   goto NextN7     movf    resultsOfApplyingRules,F 
;..this cellPosition, into internal nextGen  ;; ;   goto NextN8               ; test resultsOfApplyingRules 
;..B & A variables (they are GLOBALS).  ;; ;   goto NextN9     btfss   STATUS,Z 
;..  ;; ;   goto NextN10     bsf     N5  ; set bit N5 conditionally 
; Uses the result of applying game's Rule  ;; ;   goto NextN11     return 
;..to this cell, with it's calculated     
;..amount of neighborOrganisms (See  NextN0:  NextN6: 
;..calling routine)     bcf     N0     bcf     N6 
; Return values accessing global variables.     movf    resultsOfApplyingRules,F     movf    resultsOfApplyingRules,F 
;      switch( cellPosition ) {               ; test resultsOfApplyingRules               ; test resultsOfApplyingRules 
;     case 0:  N0 = resultsOfApplyingRules;     btfss   STATUS,Z     btfss   STATUS,Z 
;     break;     bsf     N0  ; set bit N0 conditionally     bsf     N6  ; set bit N6 conditionally 
;     case 1:  N1 = resultsOfApplyingRules;     return     return 
;     break;     
;     case 2:  N2 = resultsOfApplyingRules;  NextN1:  NextN7: 
;     break;     bcf     N1     bcf     N7 

C5-287
I N G . L U I S G . U R I B E C
ASPECTOS TÉCNICOS DE LA INGENIERÍA DIGITAL

   movf    resultsOfApplyingRules,F       btfss   STATUS,Z 
             ; test resultsOfApplyingRules  NextN9:     bsf     N10  ; set bit N10 conditionally 
   btfss   STATUS,Z     bcf     N9     return 
   bsf     N7  ; set bit N7 conditionally     movf    resultsOfApplyingRules,F   
   return               ; test resultsOfApplyingRules  NextN11: 
     btfss   STATUS,Z     bcf     N11 
NextN8:     bsf     N9  ; set bit N9 conditionally     movf    resultsOfApplyingRules,F 
   bcf     N8     return               ; test resultsOfApplyingRules 
   movf    resultsOfApplyingRules,F       btfss   STATUS,Z 
             ; test resultsOfApplyingRules  NextN10:     bsf     N11  ; set bit N11 conditionally 
   btfss   STATUS,Z     bcf     N10     return 
   bsf     N8  ; set bit N8 conditionally     movf    resultsOfApplyingRules,F     END
   return               ; test resultsOfApplyingRules 

C5-288
I N G . L U I S G . U R I B E C
A S P E C T O S T É C N I C O S D E L A I N G E N I E R Í A D I G I T A L

 FSM ALGORITHM KEEP DATA SAFE


“Against power failures and other interruptions”

Mantener la integridad de la información contra fallas de energía y otras suspensiones de la operatividad


de un equipo es un problema de amplio espectro, que complica el manejo de datos multi-bytes (casi
todos, como registros en tablas), que se atienden en equipos pequeños, como procesadores embebidos, y
también en grandes sistemas de bases de datos.

Se pretende que el almacenamiento de esos registros sea "atómico", y las medidas que se toman
funcionan bien para ambientes de múltiples procesos (semáforos, mutexes), pues ellas evitan que varios
usuarios modifiquen simultáneamente un campo que está ocupado por otro; pero eventos externos,
tales como una falla de alimentación, un accidente con el botón de re-arranque, o causas circunstanciales
en un canal de comunicaciones, pueden hacer que la escritura se interrumpa a la mitad del proceso, sin
culminar, con lo cual, al reiniciarse el sistema, una porción de los datos almacenados corresponderá a
información nueva, en tanto que la otra parte será obsoleta.

Si se está, por ejemplo, reservando un asiento en un avión, terminará registrándose un pasajero con su
nombre e identificación, en la posición de otro viajero.

Si un sistema embebido está grabando información pertinente a la energía eléctrica consumida en una
instalación, terminará un valor de consumo, alojado junto a una fecha anterior.

Desde luego, DB2, Sybase, Oracle, Posgres y otros grandes sistemas de bases de datos, tienen resuelto
este problema, pero cuando se trata de microprocesadores embebidos, cálculos complicados como
CRCs, usados para establecer la equivalencia entre una imagen y su respaldo, resultan inconvenientes.

Mi propuesta es una simple máquina de estados finitos (FSM), con cuatro posiciones, unas de ellas de
transición; ésta garantiza que no importa en qué parte del ciclo de escritura se re-arranca el sistema, la
información nunca será inconsistente. Desde luego, puede ocurrir que el último registro no se asiente,
pero eso es lo que pasa cuando el indispensable soporte de energía desaparece; lo que esta FMS
garantiza es que, si se almacena un dato, éste será coherente; de lo contrario, se rechaza.

Si está haciendo una reservación para viajar, el sistema lo "bota" si se va la luz, y toca volver a comenzar,
pero no ocurrirá que piense que hizo su reservación, y resulte que es Ud. pero en la fecha equivocada.

En el campo de los microcontroladores, he observado soluciones que van desde ignorar olímpicamente
el problema (si se va la energía, alguien tendrá que venir a corregir las inconsistencias...), hasta realizar
cálculos tipo CRC, o más imbricados aún, para evaluar el estado de la información y de su respaldo. Y
algunas alternativas que vi en varios libros de texto, no toleran para nada cualquier clase de falla de
energía…

Lástima que en el espacio de la revista solo haya lugar para presentar el algoritmo, sin un Marco de
Referencia. Así, el artículo resulta útil solo si para quienes saben de qué se trata el problema.

C5-289
I N G . L U I S G . U R I B E C
A S P E C T O S T É C N I C O S D E L A I N G E N I E R Í A D I G I T A L

C5-290
I N G . L U I S G . U R I B E C
A S P E C T O S T É C N I C O S D E L A I N G E N I E R Í A D I G I T A L

C5-291
I N G . L U I S G . U R I B E C
A S P E C T O S T É C N I C O S D E L A I N G E N I E R Í A D I G I T A L

C5-292
I N G . L U I S G . U R I B E C
A S P E C T O S T É C N I C O S D E L A I N G E N I E R Í A D I G I T A L

 BIBLIOGRAFÍA
Introduction to Embedded Microcomputer Systems. Jonathan W. Valvano, Thomson
Brooks/Cole, 2003. ISBN 0-534-39177-X

Computers as Components, Wayne Wolf, Elsevier, 2005. ISBN 0-12-369459-0

Microcontrolador PIC16F84 Desarrollo de Proyectos, 2ª ed. 2006, Palacios, Remiro, López, Alfa-
Omega

Microcontroladores PIC16F84, Diseño práctico de aplicaciones, Angulo Usategui, et. al, 2ª


parte, 2ª ed., 2006, McGraw Hill, ISBN 84-481-4627-1

Embedded Software, The Works, Colin Walls, Elsevier, 2006, ISBN 0-7506-7954-9

High-Performance Embedded Computing, Wayne Wolf, Elsevier, 2007, ISBN 0-12-369485-X

C5-293
6
Capítulo
I N G . L U I S G . U R I B E C
A S P E C T O S T É C N I C O S D E L A I N G E N I E R Í A D I G I T A L

INGENIERÍA DIGITAL EN LA ACADEMIA


“Cadena de Digitales: Una razón para cambiar…”

 INTRODUCCIÓN

A
comienzos de 2009 hice un análisis del pensum de Digitales en la Universidad Católica Andrés
Bello, cuya argumentación representa mi pensamiento crítico de lo que debería estudiarse en el
área de la Ingeniería Digital a nivel de pregrado. Presento un resumen en este capítulo, como
vía para su divulgación y para estimular la discusión y adaptación del mismo.

El actual plan de estudios de Ingeniería de Telecomunicaciones de la UCAB tiene una secuencia de


asignaturas que identificamos como “Cadena de Digitales”, conformada de la siguiente manera:

1) Programación I
2) Programación II
3) Electrónica Digital
4) Laboratorio de Electrónica Digital
5) Arquitectura de Computadores
6) Laboratorio de Arquitectura de Computadores
7) Sistemas de Operación

Mi criterio para evaluar las asignaturas de la cadena se apoya en aspectos medulares, de gran valor
directriz, como lo son:

 Enfoque del pensum hacia la Solución de Problemas


 Adquirir profunda maestría y destrezas en al menos dos áreas centrales de la carrera
 Incorporación de las computadoras como Componentes de Diseño (Ref. 1)

C5-294
I N G . L U I S G . U R I B E C
A S P E C T O S T É C N I C O S D E L A I N G E N I E R Í A D I G I T A L

 ENFOQUE DEL PENSUM HACIA LA SOLUCIÓN


DE PROBLEMAS
Un ingeniero es en esencia, eso: Un profesional que resuelve problemas.

Hay una queja habitual en relación al rendimiento y desempeño de los alumnos en la cadena de digitales,
que se difunde hasta cubrir el trabajo de grado: “Los estudiantes deberían ostentar mayor habilidad para resolver
problemas”.

Las diversas asignaturas y cadenas deben contribuir todas ellas a la consecución de este objetivo común,
vital, permitiendo que los alumnos perfeccionen sus aptitudes en la solución de problemas; para ello es
importante:

 Dedicar más esfuerzo a la síntesis (diseño de proyectos: aplicación activa de conocimientos,


criterios y restricciones al cumplimiento de objetivos, consecución de metas y obtención de
logros)
 que al análisis (comprensión de dispositivos, observación pasiva de sistemas y componentes).

 MAESTRÍA Y DESTREZAS
No hay forma tan eficaz como aprender haciendo, pero ese método no está exento de dificultades; por
ejemplo, para aplicarlo al estudio de los circuitos digitales, a la programación de microcontroladores o a
los sistemas operativos, se requiere manejar con precisión lo que puede llegar a ser una considerable
cantidad de detalles. Esa es la diferencia fundamental entre:

 El enfoque del aula (teoría), y la perspectiva del laboratorio (praxis);


y también entre:
 Comprender el meollo de los conceptos (conocimientos vastos), y ostentar Maestría en el área
(especialización).

La amplitud del conocimiento es importante, pero también es crucial que el profesional logre dominio
magistral en al menos dos (2) sectores de su carrera, de ser posible, porque de allí obtiene: Satisfacción
personal y Valoración de su capacidad para el logro, y para la consecución del éxito.

Considero fundamental adoptar un enfoque holístico en relación al tema Proyectos, en general: Que
motive una metodología para la planificación de desarrollos de ingeniería, que contemple aspectos
prácticos, múltiples y muy diversos, como por ejemplo el financiamiento de los mismos, y la elaboración
de listas (“check lists”), con detalles que es necesario no olvidar cuando se va a planificar un proyecto.

Aún así no encuentro manera de incluir este tema dentro de la secuencia actual de digitales en la Escuela
de Telecomunicaciones (aunque sí se encuentra en la USB), en particular por el problema de los créditos
semestrales que, según me dicen, rebasarían ya lo conveniente. Así, muy a mi pesar –pues estoy
convencido de que otro más exitoso sería el perfil del egresado– no tocaré más el asunto de los
Proyectos en esta propuesta.

C5-295
I N G . L U I S G . U R I B E C
A S P E C T O S T É C N I C O S D E L A I N G E N I E R Í A D I G I T A L

 COMPUTADORAS: COMPONENTES DE DISEÑO


Las “Credit Card Computers”, PC basados en microprocesadores Intel equivalentes al Pentium, y que
cuestan de $60 en adelante, dependiendo de la cantidad, son tecnológica y económicamente ganadoras,
dentro de la inmensa gama de “componentes”, todos muy importantes, como los microcontroladores,
los microprocesadores individuales, los FPGA, ASICS y demás circuitos complejos, en especial en la
realidad local donde se desenvuelven nuestros profesionales…
En el área particular de las telecomunicaciones, hay una relación muy estrecha entre los dispositivos de
uso cotidiano (conmutadores, enrutadores, puentes, servidores, centrales telefónicas, etc.) y las
computadoras, grandes o pequeñas.

Es imprescindible que nuestros estudiantes logren un dominio instrumental de las PC


modernas, que les permita desenvolverse con toda comodidad en su uso y aplicación.
Resulta tan poco relevante al ingeniero de Telecomunicaciones (o al Electrónico de la USB), conocer los
intríngulis del diseño de, por ejemplo, un Pentium, o un filtro integrado, como inútil le es saber qué
contienen los circuitos integrados. Por apasionantes que puedan resultar estos temas, lo fundamental
es dominar su uso y aplicación como componentes de diseño.
Y no se trata de emplear los PC como herramienta de oficina, en la preparación de informes, el “chat” y
la mensajería electrónica, que eso lo hacen el ama de casa y las secretarias, sin demeritar a nadie.
Corresponde a nuestros estudiantes aplicarlos a la adquisición de datos, la transmisión automatizada de
información, el control de instalaciones industriales, la robótica, la telemática, las redes de datos y
actividades tecnológicas similares.
Dicho esto, toma enseguida singular preponderancia el tema de la PROGRAMACIÓN:
Todo el mundo debería aprender a programar computadoras; hoy es una necesidad,
equivalente a saber leer y escribir.

 CELULARES: COMPONENTES DE DISEÑO


Si queremos enseñar Ingeniería de Avanzada, y no puede ser de otra forma en las áreas de las
Telecomunicaciones y la Electrónica, entonces ni siquiera es tan moderno el tema de los PCs como
Componentes de Diseño. Hay un empuje tremendo del lado de las comunicaciones móviles, pues los
aparatos que se emplean ya no son simples teléfonos: Son verdaderos computadores con capacidades
que bordean las de los PCs y en algunos casos las superan: interfaces táctiles; sensores incorporados:
magnéticos, GPS, temperatura, acelerómetros. Medios de comunicación: WiFi, Bluethoot, iRDA, voz y
datos (a altas velocidades) vía la red celular, y los sistemas operativos que soportan, como Android, de
tan vertiginoso crecimiento gracias a la tecnología que suministra: Linux, threads, múltiples CPUs, Java,
APIs para mapas, geolocalización… y la plétora de aplicaciones como reconocimiento de voz, auxilio al
viajero, acceso a bases de datos ilimitadas, con precios, productos, oportunidades…
No incorporar los telefónos Celulares como Elemento de Diseño en nuestras carreras, es
seguir enseñado ¡ Ingeniería de mediados del Siglo 20 !

C5-296
I N G . L U I S G . U R I B E C
A S P E C T O S T É C N I C O S D E L A I N G E N I E R Í A D I G I T A L

 ESTRUCTURA DE LA CADENA DE DIGITALES


Visto de lejos, el esquema actual de la Cadena de Digitales en la Escuela de Telecomunicaciones podría
resultar, in abstracto, medianamente apropiado, aunque susceptible de prolongarlo con algunas electivas.

PREREQUISITOS:
La matemática que necesitamos en nuestra Cadena de Digitales debe partir de la base que es fundamental
que el programador comprenda cómo se representa la información numérica en los sistemas digitales,
cuáles son las distintas fuentes de error (redondeo, truncamiento, etc.), cómo se propagan los errores, y todo
lo que tiene que ver con aritmética entera, en punto flotante (overflow, underflow) y en punto fijo, así
como el análisis de sensibilidad, estabilidad y criterios de convergencia, y la validación de modelos para
valores extremos. (Ref. 4). Es fundamental verificar que el contenido del párrafo anterior se esté
cubriendo efectivamente dentro de las asignaturas de Cálculo.

PROGRAMACIÓN I y II
En la secuencia de Programación I y II existen varios asuntos para corregir, y muchos aspectos qué
consensuar entre los diversos profesores...

EL LENGUAJE Lo primero es decidir qué lenguaje enseñar. Es notoria la diversidad de opiniones al


respecto. Ya hace 5 años, en diciembre de 2003, planteé por primera vez algunos aspectos
relativos al tema de los cursos de Programación (“Observaciones en Relación a las Deficiencias en
el Aprendizaje del Lenguaje "C", desde la óptica del curso “’Arquitectura del Computador’”.
Desde entonces no cesa la disparidad.

 Varios docentes juzgan que hay que emplear Pascal, por motivos pedagógicos, pues sostienen que
éste es un lenguaje ideal para enseñar los conceptos de programación (aunque luego nadie lo
utilice en ambientes comerciales, e institutos como el MIT y la UPC ni lo mencionan).
 Yo he propuesto el “C” por las razones que expondré más adelante.
 Otros piensan que el lenguaje que hay que aprender es el Assembler…
 E, incluso, están los que dicen que no hay que enseñar ningún lenguaje,
 O que cualquiera… da igual.
 Hay quienes sugieren Mathlab, Mathematica, Labview…
 Hemos recibido opiniones, locales unas, foráneas otras (UPC), que sostienen que el lenguaje es
Java, en telecomunicaciones.
 El Perl…
 Y, desde luego, no hay que olvidarse del C++.
 Están los que abogan por lenguajes funcionales, como el Erlang (Ericson Language) o el Haskell,
que aprovechan muy bien, hoy, los recursos de los modernos “multicore”.
 El MIT, a nivel introductorio (que es de lo que nos estamos ocupando aquí) usó Scheme (con
cierto parecido al Lisp) hasta hace 6 meses…
 …pero lo han cambiado a Python (“Why are you using Python? Python is interpreted, has
relatively simple syntax and semantics, is unobtrusively object-oriented, is broadly available, and has lots of
useful libraries”).

C5-297
I N G . L U I S G . U R I B E C
A S P E C T O S T É C N I C O S D E L A I N G E N I E R Í A D I G I T A L

cfr.: http://MITEECS-NewCurriculum6-1,6-3,6-2inEECS.htm

Yo agregaría que Python, al igual que Perl, introducen a los profesionales de telecomunicaciones
paradigmas invaluables, como las Expresiones Regulares que, si bien se emplean también en otros
programas y lenguajes, como awk, y en utilitarios como sed o grep, éstos no están necesariamente
tan difundidos como Perl y Python dentro del área de Servidores, Enrutadores, etc.

A mí me encantaría que usáramos Python con todos los adornos que acabo de mencionar, pero Perl y
Python resultan, en mi humilde opinión (contraria a la del MIT), rudos como primer lenguaje de
programación: Abarcan demasiados tópicos para nuestra disponibilidad horaria. Habría que reducir el
alcance… ¡y entonces a lo mejor quedarían convertidos en cursos de “C”!

Como tema relacionado, observo que para la programación de aplicaciones en telefonía celular, están
más o menos parejos el C++ (Qualcomm) y el Java (Nokia, BlackBerri, Android)
(http://code.google.com/android/). Parece que el futuro, en esta área, será de Java…

En la comprensión, uso y aplicación de los Sistemas Operativos, el “C” ocupa un lugar de


preponderancia indiscutible. En circuitos digitales, el “C” lo hace bastante bien expresando Máquinas de
Estados Finitos (FSM), y en la actualidad hay gran proyección del “C” como programa de diseño de
silicio, al estilo del Verilog, System Verilog y el VHDL. (Cfr. referencias 2, 3, 4)

Por último, si bien esto puede cambiar, en aplicaciones embebidas se usa “C” mucho más que el C++.

Así las cosas, propongo adoptar el “C” como lenguaje medular para toda la Cadena de Digitales.

EL programa En el Apéndice-A se incluyen como referencia algunas páginas tomadas del programa del
curso “6.189 A Gentle Introduction to Programming Using Python” del MIT, para permitir
comparar lo que se cubre en ese instituto con nuestro propio plan de estudios (hay que mirar a la Meca).

 Lo primero es decir que: Aprender a programar no es lo mismo que saber arrojar a destajo unas
cuantas líneas de código sin misericordia ni concierto. Cada vez más, el trabajo del profesional en
Telecomunicaciones termina materializado en un programa. Si no se conocen los fundamentos de la
Ingeniería de Software, el resultado será siempre artesanal (lo que mi ilustre asesor de software
llama “Programación Ingenua”), lo cual es muy peligroso.

Nuestro profesional tiene que enfrentarse a conceptos tales como colas, procesos, semáforos,
interrupciones, drivers, expropiación y apropiación de recursos… todo lo cual se estudia en Sistemas
o en una licenciatura de Computación. Si no tiene los conocimientos apropiados, es muy probable
que se decida a “improvisar”. Hay que tener mucho cuidado: Esa no es una actitud profesional…

Un programa diseñado sin aplicar los conocimientos apropiados puede padecer defectos ocultos,
que para un profesional serían evidentes, pero no así a los ojos del improvisado. Y el ingeniero tiene
una responsabilidad social. Es factible que su proyecto ocasione toda clase de inconvenientes,
algunos de los cuales pueden resultar, inclusive, mortales (como sería, por ejemplo, un error en el
programa que controla un tomógrafo, que podría sobre-exponer al paciente, o la falla del cohete
Ariane 5, generada por un estúpido error de programación).

C5-298
I N G . L U I S G . U R I B E C
A S P E C T O S T É C N I C O S D E L A I N G E N I E R Í A D I G I T A L

En todo caso, nuestro pensum no contempla un curso, ni siquiera una electiva, en el área de Ingeniería
de Software, por lo que: Es importantísimo obtener el máximo rendimiento de los dos (2) cursos de
programación con los que contamos.
 En segundo lugar, el lenguaje que se estudie tiene que enseñarse bien, completo, para que apoye
con firmeza los cursos y proyectos futuros.

La siguiente es la relación que hice en el 2003, de las inaceptables lagunas en el conocimiento del
lenguaje “C”, propiamente dicho, que detecté en mi curso de Arquitectura del Computador. Este
problema es similar en las dos universidades a las que asisto: la UCAB y la USB. La situación no ha
mejorado mucho en ninguna de las dos, 8 años después…
El lenguaje “C” ha sido visto como un Ensamblador de alto nivel porque, a pesar de poseer gran
independencia, tanto de la Máquina (del Pentium al PowerPC, de los micros a las estaciones de trabajo)
como del Sistema Operativo (del DOS al Windows, al Unix/Linux y a los celulares), ha permitido
durante 30 años manipular la estructura circuital subyacente de las computadoras, de manera
Apropiada (mimetizando modos de direccionamiento, manejando puertos, y permitiendo atender las
interrupciones) y Conveniente (al facilitar su transporte entre plataformas) sin ser, desde luego, una
panacea (ningún lenguaje lo es).
Las características que lo hacen idóneo para escribir en él sistemas operativos del calibre del Unix/Linux
o el Windows (entre 11 MLCC y 29 MLCC, o millones de líneas de código en “C”), lo califican también como
vehículo conveniente y útil para expresar con él gran cantidad de conceptos de la Arquitectura del
Computador (manejo de interfaces, procesamiento de entrada y salida, interrupciones), con la ventaja de
que ese material es útil con bastante independencia del hardware, y en un nivel más limitado también del
software. Pero a nuestros estudiantes les hace falta que se les enseñe, además de lo que ya conocen, los
siguientes conceptos, mínimos, de los que carecen, y que son fundamentales en el estudio del “C”:
1) Manejo de apuntadores

Tienen inconvenientes con expresiones tan sencillas como: *ptr++, lo cual hace inservible el lenguaje
para enseñarles hasta las cosas más simples. Tampoco saben establecer la diferencia con *(ptr++).
¿Qué se está Incrementado? ¿Qué se está Referenciado?

Si no se les va a entrenar bien en el manejo de apuntadores, es mejor no enseñarles “C”.

2) Macros
Lo desconocen todo: Continuadores (\) y concatenadores (##) como en:
#define initq( in )     in.base = in.put = in.get = q##in;      \ 
                        in.n = 0;  in.size = sizeof( q##in );   \ 
                        in.limit = in.base + in.size 
O en la siguiente macro, usada en debugging (empleando #):

#define DBP(x) (fprintf(stderr,"<%d> '%s' >%d<\n", __LINE__, #x, \ 
                       _i_=(x)),_i_) 
 

C5-299
I N G . L U I S G . U R I B E C
A S P E C T O S T É C N I C O S D E L A I N G E N I E R Í A D I G I T A L

3) Operadores

No tienen idea del efecto del operador coma (,) ni de la existencia del operador ternario (?:), como en:
#define enq( in, c )    ( in.n  >=  in.size  ?  EOF:            \ 
                          ( *in.put ++ = (uchar) c,             \ 
                            ( in.put = in.put >= in.limit  ?    \ 
                                       in.base : in.put ),      \ 
                             in.n ++,  c  )  ) 

Por tanto no entienden cuál es el valor de expresiones como éstas, que son fundamentales en
Arquitectura (comunicaciones de datos, manejo de colas), Sistemas Operativos, etc.

4) Manejo y Enmascaramiento de bits

Expresiones como: #define DTR   ( 1  <<  0 )    /* Data Terminal Ready  */ 


no les dicen absolutamente nada a nuestros estudiantes, y son el pan diario en Arquitectura, en
Comunicaciones y desde luego, en Sistemas Operativos.

Otras como: #define pic_inten( vec ) ( outp( MASK_PORT, inp( MASK_PORT ) &  ~(1 << (vec)) ) ) 


les resultan del todo incomprensibles. (Usadas en las mismas materias antes mencionadas).

5) Expresiones lógicas

No les son claras cosas como:  return( g = x < 20 ); o: return g = x < 20; 

6) Manejo de bloques {}

Como en:
#define com_inten()    { DTR_ON(); RTS_ON(); rcv_inten();       \ 
                         inp( LINE_STATUS ); inp( RCV_DATA );   \ 
                         inp( INT_ID ); inp( MODEM_STATUS );    \ 
                         board_inten();  pic_inten( VECTOR ); } 
7) Casting

Los castings son indispensables; sin saber qué son, no se puede programar en “C”.
/* Compute segment of memory pointed to  */ 
#define SEG(p) ((unsigned) (((unsigned long) (void far *) (p)) >> 16L)) 

O en:
/* Construct far void pointer  */ 
#define FP(seg,off) ((void far *) ((((unsigned long) (unsigned) \ 
                    (seg)) << 16L) | ((unsigned long) (unsigned) (off)))) 
 
Sin comprender estas macros difícilmente pueden tratarse los registros de Segmento del Pentium, en
Arquitectura del Computador, o direccionarse directamente la memoria de video en el PC.

C5-300
I N G . L U I S G . U R I B E C
A S P E C T O S T É C N I C O S D E L A I N G E N I E R Í A D I G I T A L

8) Include Files; C preprocessor

No conocen la manera de: a) declarar y b) definir variables empleando el mismo conjunto de “include
files” (#undef extrn). Desconocen el uso de condicionales (#if) y de pragmas:
#pragma intrinsic( _enable, _disable ) 

9) Standard Library; Unix System Interface

Desconocen por completo tanto la librería estándar como la interfaz con el Unix, que fue la propia
razón original de ser del lenguaje “C”. Por ejemplo, ni escucharon de 'setjmp()' y 'longjmp()', que
son fundamentales para estructurar corrutinas y cambios de contexto en procesos cooperativos,
'malloc()' para el uso dinámico de memoria; los conceptos inherentes a las señales (signal.h), etc.;

Estas carencias obstaculizan seriamente la comprensión y el manejo de la comunicación con


el usuario (Control‐C) o entre procesos ('raise()'), o el encadenamiento de funciones mediante
atexit(). (Ver el complemento de este punto abajo, en el numeral “11”)

10) Diagramas de Flujo

Aunque éstos aparecen en el programa, no se enseñan, porque esa metodología dizque ya no se


emplea en programación moderna. Eso podría ser verdad para informáticos (EDP, IT), ingenieros de
sistemas, licenciados o ingenieros de computación... Viendo la tendencia moderna hacia UML, yo
personalmente lo dudo.
Pero resulta que en Electrónica Digital, una forma de enseñar Diagramas de Estado es basándose en
los Diagramas de Flujo, que debieron haber estudiado y no lo hicieron…
En resumidas cuentas, no se les enseña “C”. El resultado de esto es que en Arquitectura del
Computador hay que hacer tutoriales forzados, y al llegar a Sistemas Operativos no están en capacidad
ni siquiera de acercarse a una consola elemental de Unix.
Para un curso moderno de Sistemas Operacionales (Unix), orientado al Electrónico o al ingeniero de
Telecomunicaciones, un conocimiento a fondo del lenguaje “C” resulta imprescindible.
Una pequeña digresión:
Cuando lo que se les ha enseñado es C++, los cursos también adolecen del mismo decálogo de
inconvenientes arriba descritos… más algunos propios, como que no se estudia lo que es el sistema de
manejo de errores particular del C++.
Y si lo que se les ha dado es Java (porque la falta de uniformidad y criterio no campea solo en
nuestra escuela; también los profesores de programación traen cada uno su propia y personal
perspectiva…), entonces tampoco se enseñan Threads… Yo juzgaría (¡exagero!) que la única razón
para enseñar Java en Telecomunicaciones, en lugar de C++, son los Threads! Si éstos se dejan de
lado, entonces no sé de qué estamos hablando.
Es indispensable, además, asignar el número de horas apropiado a los cursos de programación…

C5-301
I N G . L U I S G . U R I B E C
A S P E C T O S T É C N I C O S D E L A I N G E N I E R Í A D I G I T A L

Si se escoge el C++, hay que cubrir “C” y C++ , porque el C++ no tiene hasta el presente acogida y
penetración suficiente en el ámbito de los sistemas embebidos. Haciendo paquetes de nómina y
contabilidad, puede ser que el C++ sea lo que haya que usar; programando servidores en
microcontroladores, para colocarlos en un sistema distribuido de adquisición de datos y supervisión de
procesos, aún hoy, pese a la tendencia, el “C” es lo que se emplea en la industria. (Referencias 5 y 6)
11) Punto complementario #1
En relación al punto 9) arriba: Standard Library; Unix System Interface, las funciones y macros que
hay que estudiar son al menos las siguientes, tomadas de la librería estándar (Cfr. “The C programming
Language”, Kernighan & Ritchie, segunda edición, 1998, Apéndice B, Standard Library)
File Operations <stdin.h> 
fclose, fflush, fopen, freopen, remove, rename, setbuf, setvbuf, tmpfile, tmpnam,tmpnam,
 
Formatted Output <stdin.h> 
fprintf, printf, sprintf, vfprintf, vprintf, vsprintf,
Formatted Input <stdin.h> 
fscanf, scanf, sscanf,  
 
Character Input and Output Functions <stdin.h> 
fgetc, fgets, fputc, fputs, getc, getchar, gets, putc, putchar, puts, ungetc,  
 
Direct Input and Output Functions <stdin.h> 
fread, fwrite,  
 
File Positioning Functions <stdin.h> 
fgetpos, fseek, fsetpos, ftell, rewind,  
 
Error Functions <stdin.h> 
clearerr, feof, ferror, perror,  
 
Character Class Tests <ctype.h> 
isalpha,  iscntrl,isdigit,isgraph,islower,islower,  isprint,ispunct,isspace,isupper,isupper, 
isxdigit,tolower, toupper,  
 
String Functions: <string.h> 
memchr,  memcmp,  memcpymemmove,  memset,  strcat,  strchr,  strcmp,  strcspn,  strerror,  strlen, 
strncat, strncmp, strncpy,strpbrk, strrchr, strspn, strstr, strtok,  
 
Mathematical Functions: <math.h> 
acos, asin,  atan, atan2, ceil,  cos,  cosh, exp,  fabs, floor,  fmod, frexp, ldexp, log, log10, 
modf, pow, sinh, sqrt, tan, tanh,  
Utility Functions: <stdlib.h> 
abort,  abs,  atexit,  atof,  atoi,  atol,  bsearch,  calloc,  div_t  div,  exit,  free,  getenv,  labs, 
ldiv_t ldivmalloc, qsortrand, realloc, srand, strtod, strtolstrtoul, system,  
 
Diagnostics: <assert.h> 
assert, 
 
Variable Argument Lists: <stdarg.h> 
va_start, va_arg, va_end,  
 
Non‐local Jumps: <setjmp.h> 
setjmp, longjmp,  corrutinas  
 

C5-302
I N G . L U I S G . U R I B E C
A S P E C T O S T É C N I C O S D E L A I N G E N I E R Í A D I G I T A L

Signals: <signal.h> 
signal, raise,  
 
Date and Time Functions: <time.h> 
asctime, clock, ctime, difftime, gmtime, localtime, mktime, time, 
 
Además, es importante –como ya se dijo– hablarles del sistema de entrada y salida de bajo nivel
(<io.h>), que es la interfaz con Unix, básico para potenciar el curso de Sistemas Operativos:
access,  chmod,  chsize,  close,  creat,  dup,  dup2,  eof,  filelength,  isatty,  locking,  lseek, 
mktemp, open, read, setmode, sopen, tell, umask, unlink, write, file handles, standar input, 
standar output, standar error, redirección, etc. 
 

Si no se enseña la librería estándar tal como se describe aquí,


el curso de “C” no resultará apropiado para la cadena,
y entonces la Arquitectura del Computador,
y buena parte del curso de Sistemas Operativos,
en los que se supone que programan sistemas
aplicando el lenguaje completo al PC
(con y sin la ayuda de Unix/Linux),
no servirán de mucho…
12) Punto complementario #2

Desde luego, un curso de programación que incluya el lenguaje “C” (u otro lenguaje cualquiera), tiene que
venir acompañado de Técnicas de Depuración (debugging), pues la mayor actividad de un
programador es precisamente ésta. Es importante que el estudiante tenga manejo instrumental de
“gdb” (y quizás “ddd”: Data Display Debugger) para aplicar las estrategias aprendidas de debugging.
En cuanto a la plataforma que debe emplearse en estos cursos, se recomienda Linux gcc y los
estudiantes tienen que hacerse de ella en sus propios PC. Si no puede instalarse Linux, hay que usar
Cygwin, o distribuciones “live” que corran desde CD (como Ubuntu o Knoppix), o alguna máquina virtual
(como VirtualBox, de Oracle, que además de muy buena, es gratuita).
Asimismo, no puede ser que el estudiante termine dos cursos de programación y no se haya dado ni
cuenta del proceso que se sigue en el desarrollo de sus programas:
Make, Compile, Link, Program Image, Loader, Librarian, Rom, Ram,  
Data Sections, TEXT, DATA, HEAP, STACK... 

ELECTRÓNICA DIGITAL

LABORATORIO DE ELECTRÓNICA DIGITAL


Es más fácil criticar los cursos que dictan los demás, que los nuestros propios…

Una nota aclaratoria para quienes lo desconozcan: La Escuela de Telecomunicaciones tiene un


convenio con la UPC de Barcelona, por el cual algunos estudiantes pueden tener una doble titularidad;
para que esto sea posible nuestros programas de pregrado tienen que ser lo suficientemente parecidos a
los de la UPC, a fin de que el estudiante pueda tomar las asignaturas de último año en España, sin

C5-303
I N G . L U I S G . U R I B E C
A S P E C T O S T É C N I C O S D E L A I N G E N I E R Í A D I G I T A L

inconvenientes importantes debidos a los prerrequisitos académicos. El pensum ha sido sometido a la


evaluación de la UPC en su oportunidad, como parte del convenio; y queda claro, dicho por la prof.
Mayra Narváez en un correo de octubre de 2005 que: “En relación a la asignatura Sistemas de Operación,
debemos orientarla de acuerdo a los contenidos de la UPC, debido a que es fundamental igualar estos contenidos.”

EL programa El de Electrónica Digital es casi con exactitud el mismo que el equivalente en la UPC:
Circuitos y Sistemas Electrónicos II (11472, 6 créditos, 4,5T, 1,5A, 0L), tanto en el contenido
como en la estructura del curso. En cuanto a la bibliografía, las cuatro referencias básicas (Wakerly 2002,
Tocci 2000, Mano 2001: Principles of Digital Design y Gajski 1996) y las complementarias (Mano2002:
Logic and Computer Design Fundamentals, Kleitz 2001) van a la vanguardia en la materia, aquí y allá.

Mi observación es que, fuera de lo que dicen los programas, la UPC emplea el Altera y su excepcional
infraestructura de software gratuito; nosotros reemplazamos los FPGA por los microcontroladores.

En mi opinión, a nivel de pregrado y en nuestro medio local, manejar con soltura el tema de los
microcontroladores es de mucha mayor relevancia que dominar los FPGA, porque hay mayor cantidad
de aplicaciones que podemos, en la práctica, darles a los microcontroladores, por encima de las pocas y
muy escogidas que nuestras empresas pueden darle a los FPGA.

Detrás de esto hay varias razones: de economía, pues los FPGA, la infraestructura para trabajar con ellos, y
la experticia necesaria, son más costosos que los equivalentes para microcontroladores; de requerimientos:
normalmente los problemas que debemos resolver localmente alcanzan a ser cubiertos sin dificultad
con microcontroladores que, además, siempre van desarrollándose velozmente y presentan cada vez
herramientas de mayor poder y sencillez en su manejo; de crecimiento: en capacidad computacional,
aumentando el número de bits a 16 y 32, y cada vez con menores precios y mayor cantidad de módulos
integrados (conversores, comparadores, comunicaciones seriales, protocolos I2C, SPI, Bluetooth, USB).

La Aunque la forma de presentar a los estudiantes el Contenido Programático depende del


implementación profesor, mientras se cubra adecuadamente la asignatura, quiero comentar –como
referencia– que suelo darles el material de Redes Combinatorias (odio llamarlas
“combinacionales”) en orden inverso al común de los autores: Comenzando el primer día de clase
ilustrando cómo se resuelve un problema industrial con un computador (después de mostrarles un
microcontrolador y una “Credit Card Computer”, junto con sus potencialidades y precios); esta presentación
obviamente se hace en “C”, empleando un “while” infinito que lee las respuestas de una tabla, usando
un índice conformado por los bits que representan las entradas, y enmascarando la actividad de entrada
y salida en sus correspondientes funciones de biblioteca… Se supone que los estudiantes saben “C”…

A continuación introduzco fugazmente las ROM (toda la familia, hasta las Flash), pues como el
programa anterior en “C” sólo lee de una tabla, es fácil convencer al estudiante de que podemos tener
almacenada sólo la tabla en un chip, y leerla mediante un mecanismo externo que evite tener que usar
un CPU solo para eso... Luego les muestro cómo un Multiplexor puede verse como una “tajada
vertical” de una ROM, de un bit de ancho, y voy resolviendo siempre el mismo problema con cada
diferente alternativa (microcontrolador, rom, multiplexor, decodificadores), haciendo énfasis en que
desde el “vamos”, los alumnos de Digitales pueden resolver problemas reales y “cobrar” por eso,

C5-304
I N G . L U I S G . U R I B E C
A S P E C T O S T É C N I C O S D E L A I N G E N I E R Í A D I G I T A L

lo que al fin de cuentas es su objetivo principal al estudiar una carrera, sin que ni siquiera se haya hecho
mención de temas tales como álgebra de Boole, minimización de funciones y compuertas sueltas.

En las redes secuenciales, los Diagramas de Estados se presentan por analogía con los de Flujo, y las
soluciones en código “C”. Poder llamar funciones genéricas, mediante apuntadores a funciones, facilita
muchísimo el material; por eso los estudiantes tienen que conocer el lenguaje, de lo contrario esta
alternativa no funciona bien, y es una pena. También se introducen la materialización de las Máquinas
de Estado, vía programas, empleando la estructura básica del “Switch” de “C”.

Se incentiva siempre a los alumnos a resolver todos sus problemas mediante programas en “C”, que ya
deberían saber manejar si tuvieran que hacerlos correr en un PC (o en un microcomputador); se los
encamina para que los ejecuten en sus PC, con el fin de eliminar errores de lógica en la concepción del
algoritmo que están tratando de implementar, y luego de que el problema resuelto en “C” funciona
bien, aprenden a sacar todas las ecuaciones necesarias para armar su circuito en su protoboard,
directamente a partir del programa en “C” (si fuera el caso). Esta metodología no se emplea en los libros
de texto, pero en algún momento los alumnos terminan por asimilar también el material convencional,
de una manera sencilla, y se muestran siempre confiados en sí mismos al tener la garantía de que este
método les ofrece un camino viable hacia una solución exitosa de los problemas.

En la parte de microcontroladores nos apoyamos en el Microchip de la serie 16Fxxx, con su ambiente


de soporte, el MPLAB. En la USB se emplea el compilador “C” de Codewarrior (Freescale).

Aquí recomiendo ampliamente cambiarnos con urgencia al PIC 16F88, sucesor actual del 16F84, pin a
pin compatible con él, con una cantidad de periféricos adicionales, capacidad de usar un oscilador
estable interno, sin cristal ni componentes externos, lo que libera más terminales para su uso en entradas
y salidas (16);

 tiene incorporados periféricos de comunicaciones AUSART, I2C, SPI,


 dos timers de 8 bits y uno de 16, PWM de 10 bits;
 la memoria de programa es de 4K, la EEPROM 256 bytes,
 la RAM es de 368 bytes
 tiene 7 canales ADC de 10 bits
 y el precio en dólares es 1/3 por debajo del 16F84 ($2 en cantidad).

ARQUITECTURA DE COMPUTADORES y

Laboratorio de ARQUITECTURA DE COMPUTADORES

EL programa DE En el papel, esta asignatura es idéntica a Arquitectura y Sistemas Operacionales I (11477, 6


TEORÍA créditos, 3T, 1,5A, 1,5L) de la UPC. No sólo el contenido es igual, sino que también cuando
yo he dictado este curso hemos coincidido con la UPC, sin previo conocimiento, en el orden
en que se presentan los temas, lo cual me sorprende porque yo estructuré mi cronograma un poco de
cabeza, fuera de secuencia –según los libros de referencia– para lograr que el laboratorio tuviera algo de
sincronismo con la teoría.

C5-305
I N G . L U I S G . U R I B E C
A S P E C T O S T É C N I C O S D E L A I N G E N I E R Í A D I G I T A L

En Lenguaje de Máquina (18 horas) comienzan en la UPC por conjuntos de instrucciones y modos de
direccionamiento, tanto en general como particularizando para el microcomputador Pentium, igual que
nosotros. Siguen con Programación de Entrada y Salida (16 horas), tal como lo tenemos planteado, y
terminan con Interpretación a nivel de Lenguaje de Máquina, igual que aquí.

Nuestra dedicación horaria a los temas difiere de la suya, porque pasamos parte del peso de la teoría al
laboratorio, a fin de que allí los alumnos perfeccionen los temas de Assembler, Conjunto de
Instrucciones y Modos de Direccionamiento. Algunos aspectos que tocamos nosotros, en la UPC no
los abordan, tales como Jerarquías de Memoria, Buses (PCI, USB, etc), y otros que se elaboran
mediante monografías (RISC, RAID, Punto Flotante, etc.) porque el tiempo no alcanza para presentarlos
en clase.

Nuestros libros de referencia: Stallings, Tanenbaum, Brey y hasta el viejo Hamacher son los mismos
recomendados en la UPC.

EL programa DE El laboratorio estuvo originalmente integrado a la teoría. En la UPC introducen en el


LABORATORIO laboratorio el "C"; la familia del 80x86, estructuras de datos, subrutinas y entrada y salida.
Nosotros, además de lo anterior, hacemos prácticas preliminares en Assembler (2 o 3
semanas) y proyectos en los que se enseñan técnicas de "interfacing hardware & software".

En UPC la infraestructura comenzó con TurboC, de Borland, pero ahora han cambiado a Linux gcc.

La Estas asignaturas han tenido casi cinco años en que, con el mismo contenido programático,
implementación el enfoque particular que cada profesor le imprime a su sección difiere tanto de los demás,
que a veces puede pensarse que, más que secciones, se trata de cursos distintos.

La principal diferencia está en la interpretación que cada profesor hace del propósito de la asignatura, y de
cómo encaja ésta dentro de la secuencia general. Esto ocurre tanto en la USB como en la Católica.

A veces se pone énfasis extraordinario en lograr que se vea lo que es una computadora por dentro
(“insight”), cómo es su estructura y la del CPU, y hasta se llega a diseñar una autóctona en clase. En el
laboratorio se trata de generar interés lúdico en el alumno como táctica motivacional, a través de
proyectos vistosos, pero sin conexión alguna con temas relacionados –ni antes ni después– con la
carrera, como sí lo serían si implementaran algo de redes de PCs o emplearan protocolos de
comunicación. Y a pesar de permitir que los estudiantes usen el “C”, o cualquier otro lenguaje de
programación, la presentación medular está centrada en el Assembler.

Los estudiantes que progresan de esta manera hacia asignaturas superiores en la cadena de digitales
(Sistemas Operativos), o fuera de ella (Laboratorio de Telemática, Trabajo Especial de Grado,
segunda titularidad en la UPC) se encuentran en desventaja relativa frente a sus compañeros, en
cuanto al manejo instrumental del lenguaje “C”, o al no haber tenido la oportunidad de estructurar
proyectos orientados hacia la comunicación de datos.

C5-306
I N G . L U I S G . U R I B E C
A S P E C T O S T É C N I C O S D E L A I N G E N I E R Í A D I G I T A L

Mi propuesta es mantener la misma organización de la UPC:


promoviendo el uso del “C”
para que los estudiantes puedan trabajar empleando un lenguaje
del que ya han tenido preparación previa adecuada
(de seguirse los lineamientos aquí propuestos en cuanto a los cursos de programación),
y que se eviten la sobrecarga de estudiar un lenguaje nuevo, nada fácil,
y hacerlo a un nivel suficiente como para permitirles sacar adecuadamente sus proyectos,
dentro de las limitaciones de créditos que tienen estas asignaturas;
además, el Assembler nunca más lo emplearán en el futuro académico, o profesional…
Deben realizarse en el curso, proyectos con alto contenido de telecomunicaciones.
Propongo que en estos cursos de pregrado, el Assembler se mantenga
al mínimo necesario para enseñar conjuntos de instrucciones, modos de direccionamiento
y algunos conceptos básicos más, según el programa.
Que el empleo del “C” aquí, ayude al perfeccionamiento de la herramienta
(aunque solo sea por la reiteración en su empleo),
lo que les ayudará en los cursos posteriores.
No quiere decir que no se estudien rudimentos de Assembler, ni de estructura interna del computador,
como están contemplados en el programa.

Mi propuesta corresponde solo a una situación de enfoque,


coordinación y optimización de recursos.

SISTEMAS OPERATIVOS

EL programa Este curso se parece bastante al de la UPC, con la salvedad de que allá introducen temas de
redes (TCP/IP, Sockets BSD) y en nuestro plan de estudios esto es asunto de otras
asignaturas. En ambas instituciones los cursos tienen una carencia que en mi opinión es de grueso
calibre: estas asignaturas no tienen laboratorio. En la UPC hay una (1) práctica opcional.
Al enseñar Sistemas de Operación resulta más que natural apoyarse en el laboratorio

Yo he desarrollado una metodología que implica que los alumnos hagan un conjunto de prácticas en sus
propios computadores personales para irle tomando el pulso, como usuarios, al Unix/Linux, y
desarrollan proyectos que les permiten ver en concreto la materialización de los conceptos de procesos,
threads, semáforos y mutex, en el primero, y los recursos del Shell y como 150 programas utilitarios de
uso y aplicación común, en el segundo, que con toda seguridad les harán más fácil sus vidas en las
asignaturas posteriores, y en el ejercicio profesional, habida cuenta de que tanto los cursos siguientes
como la actividad del graduado se apoyan notablemente en Unix/Linux.

Para no tener problemas por instalaciones defectuosas en sus PC, o derivado del uso equivocado de
algunos comandos como rm, estudié varias alternativas que les permitieran emplear Unix/Linux en sus
computadoras de manera segura.

C5-307
I N G . L U I S G . U R I B E C
A S P E C T O S T É C N I C O S D E L A I N G E N I E R Í A D I G I T A L

Analicé el uso de Bochs 2.3.5, simulador de PC; en él se pueden correr Linux (probé una distribución
Debian), Minix (versión 3 funciona muy bien) y Unix BSD.

Pero el empleo de distribuciones de Linux, gratuitas, completas, que corren directamente desde el CD
sin interferir en lo más mínimo con el disco duro del PC (permitiendo al usuario trabajar como root,
pero evitando la ocurrencia de errores catastróficos, bastante probables mientras se aprende) fue la más
atractiva. Se usan Knoppix 5.1.1 y Ubuntu 8 (mi preferencia es Knoppix, que empleo desde hace años,
desde la versión 3.3, pero Ubunto ha comenzado a emplearse en cursos superiores en la Escuela de
Telecomunicaciones, por lo que sería sensato hacer lo mismo en Sistemas Operativos).

También analicé QEmu y otras máquinas virtuales como Xen (para Servidores) y VMware (pago). El
Laptop que llevo a mis clases tiene instalada una máquina virtual, gratuita y muy buena, VirtualBox de
Oracle (no es cualquier máquina virtual); en ella corro Knoppix con lo cual no necesito llevar el CD y es
más rápida. La transferencia de archivos entre Knoppix y Windows para reportes y demás actividades
que se hacen fuera de Linux, la realizo vía pendrive, y funciona muy bien, tanto desde la máquina virtual
como a partir de la propia distribución en CD. Compartir archivos está también al alcance de un click.
Desde 2008 tuvimos la gran oportunidad de dedicarle a la asignatura un laboratorio de la Escuela en
forma permanente y los estudiantes realizan sus prácticas y proyectos en él, guiados por los instructores.
Y desde 2010 se incluyó el sistema operativo Android y se hacen prácticas simples que permiten iniciar
al estudiante en las bondades de estas plataformas, para lo cual contamos con el soporte que tan
gentilmente nos dieron Motorola y MoviStar, lo que hizo posible la programación de celulares reales.

ELECTIVAS
Yo propondría que se estudiara la forma de estructurar Electivas en Ingeniería Digital, que
cubrieran áreas como:
 Gerencia o Administración de Proyectos en Electrónica y Telecomunicaciones
 Programación de Teléfonos Celulares (aplicaciones)
 Automatización de procesos industriales mediante la transferencia de correos (email)
 …O vía mensajes SMS
 El uso de RSS en la supervisión de procesos
 El uso de Celulares en el control y la supervisión de procesos
 Aplicación de tecnologías como el RFID a la telemetría…
 Incorporación de GPS en actividades de supervisión
 Sistemas Operativos para Teléfonos Celulares (Android)

C5-308
I N G . L U I S G . U R I B E C
A S P E C T O S T É C N I C O S D E L A I N G E N I E R Í A D I G I T A L

 ANEXO: REFERENCIAS Y BIBLIOGRAFÍA


“6.189 Introduction to Programming Using Python”, MIT:
ocw.mit.edu/ans15436/ZipForEndUsers/6/6-189January--IAP--2008/6-189January--IAP--2008.zip

“Computers As Components”, Wayne Wolf, Elsevier, 2005, ISBN: 0123694590

MIT: http://www.eecs.mit.edu/ug/newcurriculum/ugcur-newsletter06.html

Definición formal del Accreditation Board for Engineering and Technology, USA: “Engineering is the profession in
which a knowledge of the mathematical and natural sciences gained by study, experience, and
practice is applied with judgment to develop ways to utilize, economically, the materials and forces of
nature for the benefit of mankind”, Principles of Engineering, Wiley, 1982, p. 8

Al leer la historia del descubrimiento del Efecto Mariposa, por E. Lorenz (1961), me resulta incómodo
observar que él se sorprendiera al ver que su programa de simulación de las condiciones atmosféricas, se
comportaba de manera diferente cada vez que lo corría, introducido a mano resultados parciales anteriores,
redondeados a 3 cifras, que imprimía su aplicación. Siendo meteorologista del MIT… no debería haberse
sorprendido; tendría que haberlo anticiparlo...

Translating sequential code to Ct code:


http://www.ddj.com/212700261?cid=RSSfeed_DDJ_All

Ct: C for Throughput Computing:


http://www.ddj.com/212700222?cid=RSSfeed_DDJ_All

Concurrent programming in Haskell:


http://research.microsoft.com/en-us/um/people/simonpj/papers/parallel/AFP08-notes.pdf

www.upc.edu/es; www.deusto.es/

C5-309

Das könnte Ihnen auch gefallen