Universidad de Costa Rica Facultad de Ingeniería Escuela de Ingeniería Eléctrica IE – 0502 Proyecto Eléctrico Implementación de un codificador y decodificador fuente para un sistema de comunicación digital Por: Luis Felipe Córdoba Morales Ciudad Universitaria Rodrigo Facio Setiembre del 2007 Implementación de un codificador y decodificador fuente para un sistema de comunicación digital Por: Luis Felipe Córdoba Morales Sometido a la Escuela de Ingeniería Eléctrica de la Facultad de Ingeniería de la Universidad de Costa Rica como requisito parcial para optar por el grado de: BACHILLER EN INGENIERÍA ELÉCTRICA Aprobado por el Tribunal: _________________________________ Ing. Diego Castro Hernández Profesor Guía _________________________________ Ing. Lucía Acuña Avendaño Profesor lector _______________________________ Ing. Victor Hugo Chacón Prendas, M.Sc. Profesor lector i DEDICATORIA A mis padres, por su apoyo, su esfuerzo, su trabajo… ii RECONOCIMIENTOS A Jaime Escalona, estudiante de la Escuela de Ingeniería Eléctrica, por la ayuda brindada en la adquisición de la tarjeta del microcontrolador. iii ÍNDICE GENERAL ÍNDICE DE FIGURAS......................................................................................vi ÍNDICE DE TABLAS.......................................................................................vii NOMENCLATURA.........................................................................................viii RESUMEN..........................................................................................................ix CAPÍTULO 1: Introducción..............................................................................1 1.1 Objetivos...........................................................................................................................5 1.2 Metodología......................................................................................................................6 CAPÍTULO 2: Desarrollo teórico......................................................................7 2.1Generalidades de Probabilidad .........................................................................................7 2.2Fuentes de información .....................................................................................................8 2.2.1Medida de la información en las fuentes de información ............................................12 2.3Codificación fuente .........................................................................................................15 2.3.1Teorema de codificación fuente ...................................................................................16 2.4Técnicas de compresión .................................................................................................18 2.4.1Técnicas de compresión sin pérdidas............................................................................18 2.4.1.1Compresores estadísticos...........................................................................................18 2.4.1.1.1 Codificación Shannon - Fano ............................................................................18 2.4.1.1.2 Codificación Huffman .......................................................................................20 2.4.1.1.3 Codificación Aritmética......................................................................................23 2.4.1.1.4 Codificación Predictiva.......................................................................................26 2.4.1.1.5 Codificación de Golomb y Codificación Rice....................................................27 2.4.1.2Compresores sustitucionales......................................................................................28 2.4.1.2.1LZ77, LZ78 y demás variaciones...........................................................................28 2.4.1.3Otros tipos de codificación .......................................................................................30 2.4.1.3.1Codificación Run-length.........................................................................................30 2.4.1.3.2 Codificación Burrows - Wheeler...........................................................................30 2.4.1.3.3Técnicas varias........................................................................................................31 CAPÍTULO 3: Microcontrolador MC68HC11..............................................33 3.1 Introducción ..................................................................................................................33 3.2 Especificaciones generales .............................................................................................34 3.3 Puerto D y la Interfaz de comunicación serial asíncrona ...............................................37 3.4 Mecanismo de interrupciones del SCI............................................................................38 CAPÍTULO 4. Implementación del Codificador Fuente ..............................42 iv 4.1 Escogencia de los símbolos............................................................................................42 4.2 Codificación....................................................................................................................45 4.3 Implementación...............................................................................................................48 4.4 Software de interfaz con el usuario.................................................................................49 4.5 Programa de codificación y decodificación ...................................................................53 4.5.4 Subrutinas: ..................................................................................................................54 4.6 Manual de usuario de la aplicación.................................................................................61 4.6.1 Modos de uso...............................................................................................................61 ............................................................................................................................64 CAPÍTULO 5: Conclusiones y recomendaciones...........................................65 BIBLIOGRAFÍA...............................................................................................69 APÉNDICES......................................................................................................70 ANEXOS............................................................................................................98 v ÍNDICE DE FIGURAS Figura 2.1 Digitalización de una señal analógica............................................11 Figura 2.2 Planos de información según Schouten.........................................12 Figura 2.3 Descomposición de una decisión de tres posibilidades................13 Figura 2.4 Entropía en el caso de dos posibilidades con probabilidades p y (1-p).....................................................................................................................14 Figura 2.5 Construcción del árbol de Huffman con dos símbolos codificados .............................................................................................................................22 Figura 3.1 Familia 68HC11..............................................................................35 Figura 3.2 Velocidades de comunicación configurables para la SCI del MC68HC11........................................................................................................40 .............................................................................................................................41 Figura 3.3 Bits relativos a la interrupción producida por la SCI1 .............41 vi ÍNDICE DE TABLAS Tabla 2.1 Ensemble de la fuente A ..................................................................19 Tabla 2.1 Ensemble de la fuente A codificado................................................20 Tabla 4.1 Símbolos del texto en español y su probabilidad aproximada de aparición.............................................................................................................43 Tabla 4.2 Símbolos de texto en español y su codificación..............................46 Tabla 4.4 Símbolos del teclado de la computadora sin codificar .................49 vii NOMENCLATURA PAM Pulse Amplitud Modulation (Modulación por amplitud de pulso). Señal de valor continuo y M-ARY PAM BCD tiempo discreto. Señal PAM con M niveles de cuantización Binary Coded Decimal (Decimal codificado en minario) Sistema de numeración binario, en que se representan las unidades, decenas, etc., con MCU números binarios. Micro Controller Controladora) viii Unit (Unidad Micro RESUMEN El objetivo general de este proyecto fue implementar un codificador y decodificador fuente utilizando un microcontrolador de la familia MC68HC11. Se hizo una investigación sobre codificación fuente, mostrando la evolución histórica, presentando algunos de los distintos tipos de códigos que existen, sus principios de funcionamiento, diferencias, ventajas y desventajas, y algunos algoritmos de implementación. Además realizó el estudio necesario para conocer la forma en que debía programarse el dispositivo que se propuso para éste fin. Se definió como metodo de codificación el de Huffman, para un conjunto de 108 símbolos, correspondientes a caracteres que normalmente aparecen en los textos en español. Se desarrolló un código fuente de intercambio de datos tanto para el MCU como para la computadora, además de una interfaz con el usuario. Finalmente se procedió a escribir un Manual de usuario para futuras referencias. Entre los resultados alcanzados se obtuvo tasas de compresión de hasta 40%, sin embargo una de las principales conclusiones fue que el desempeño de la compresión depende del origen del texto, pues el cálculo de las probabilidades de los símbolos se realizó para un texto mayormente constituido por letras minúsculas. En este sentido, se puede obtener tasas de compresión negativas, si los textos a comprimir poseen solamente caracteres en mayúscula. Además el tamaño del texto generador de las probabilidades debió ser bastante grande para obtener resultados confiables. Finalmente se propone el desarrollo de los demás bloques del sistema de comunicación de manera que se pueda realizar el proceso de transmisión y recepción en su totalidad. ix CAPÍTULO 1: Introducción El siglo XX se ha visto caracterizado desde sus inicios por grandes avances tecnológicos en distintas áreas del quehacer humano. En el campo de las telecomunicaciones, se incursionó en la transmisión de información como la voz, en aplicaciones como la radio y el teléfono, el video producido por la incipiente industria televisiva, y datos como en el telégrafo y más adelante en redes de computadoras. En 1948, Claude Elwood Shannon, publicó su trabajo "Una Teoría Matemática de la Comunicación", donde demostró, entre otras cosas, que las fuentes de información se pueden medir y que el mensaje transmitido consiste básicamente en una parte sin información y una parte que contiene toda la información necesaria para reconstruirlo. Aparecen así los conceptos de redundancia e irrelevancia. El primero corresponde a las partes del mensaje que son conocidas por el receptor y por lo tanto no es necesario transmitirlas. Se podría decir entonces que al suprimirlas, no se afectará la integridad del mensaje. Esta eliminación de información se logra a través de técnicas de compresión sin pérdidas. El segundo término corresponde a la parte de un mensaje que se puede eliminar sin temor a perder información del mismo, pues son “elementos que carecen de importancia o significación”1, o sea, son excepciones de alguna información que no es indispensable para la comprensión del mensaje. Esta eliminación de información se logra a través de técnicas de compresión con pérdidas. Un ejemplo claro de esto es la telefonía, que utiliza un modelo auditivo con un ancho de banda de apenas 3000 Hz, a pesar de que un ser humano puede producir sonidos de entre 20 Hz y 20000 Hz. 1 Adaptado de Irrelevante. Diccionario Océano Uno, edición 2001 1 La eliminación de redundancias e irrelevancias disminuye notablemente el tamaño del mensaje, sin afectar considerablemente la información que se desea transmitir. La publicación igualmente hace referencia a la relación entre la potencia de la señal y el ruido presente en el canal. Según esto se puede determinar la tasa de datos máxima a la cual se puede transmitir en un canal ruidoso. Este ruido es energía no deseada introducida a la señal transmitida por fuentes ajenas al transmisor Además, se menciona el compromiso entre la cantidad de información que se desea enviar y la capacidad de transmisión del medio utilizado, pues ningún medio tiene un ancho de banda infinito. Toda esta teoría es fundamental en el estudio y desarrollo de los sistemas de comunicación digital, que son sistemas que manipulan una señal, generalmente analógica, convirtiéndola en una sucesión de símbolos binarios con un determinado índice de transmisión (cuya unidad son bits /segundo) que serán transmitidos por algún medio, ya sea hilos de cobre, hilos de fibra óptica o el aire. Este tipo de sistema de comunicación puede ser divido en el transmisor, compuesto por la fuente, el codificador fuente, el codificador de canal y el modulador; y el receptor, que lo forman el decodificador fuente, el decodificador de canal, el demodulador y el destino. Finalmente está el canal, que no pertenece ni al transmisor ni al receptor. La fuente es quien genera la información que se desea transmitir. En este bloque también se incluye la parte que digitaliza la señal. El codificador fuente comprime la señal digital, eliminando las redundancias y las irrelevancias. 2 El decodificador fuente restituye las redundancias eliminadas por el codificador fuente. Las irrelevancias no son estrictamente necesarias para la compresión del mensaje; además no hay manera de restituirlas. El codificador de canal agrega bits a la trama de datos, para que el decodificador de canal detecte y/o corrija errores que pueda presentar la señal al recibirla. Estos errores son producto del ruido presente en el canal de comunicación. El canal, que es el medio por el cual se transmite la información. El modulador adapta la señal digital (discreta) para que pueda ser transmitida por un canal continuo. El demodulador convierte esta señal adaptada en un flujo de símbolos binarios nuevamente. Se puede considerar que al incluir el modulador y el demodulador, el canal continuo se convierte en un canal discreto. Por último, el destino es quien recibe e interpreta la información enviada. En este bloque se incluye también la parte que, de ser necesario, convierte la señal a analógica. En este trabajo, se estudiará uno de los bloques antes citados: el codificador fuente, con sus distintas técnicas de codificación. Además, se implementará un sistema basado en el microcontrolador MC68HC11 de Freescale para realizar las funciones de codificación y decodificación fuente. El propósito de la codificación fuente es la transmisión rápida de la información, proporcionando una secuencia de bits que represente fielmente la información de la fuente eliminando la redundancia y la irrelevancia y asignando códigos que representen distorsiones mínimas si hay errores en la transmisión. Existen varias técnicas de codificación, las cuales serán descritas en este trabajo. Luego, se utilizará una de ellas para implementarla el sistema. 3 Se tomará como la fuente de información una de tipo discreta sin memoria. A pesar de existir más tipos de fuentes, este tipo supone cierta facilidad a la hora de implementar el algoritmo de codificación ya que no considera la dependencia que pueda existir entre los símbolos que ya han aparecido y los que están por aparecer. 4 1.1 Objetivos 1.1.1 Objetivo general Implementar un codificador y decodificador fuente utilizando un microcontrolador de la familia MC68HC11 1.1.2 Objetivos específicos 1. Realizar una investigación bibliográfica acerca de los diferentes algoritmos de codificación y decodificación fuente. 2. Describir la evolución histórica de este tipo de codificación. 3. Implementar el codificador y decodificador fuente para un sistema de comunicación digital, considerando una fuente discreta sin memoria. 4. Implementar un sistema de prueba del codificador y decodificador fuente implementado. 5. Desarrollar un manual de usuario para el sistema implementado que describa el uso tanto del dispositivo como del mecanismo de prueba. 5 1.2 Metodología Se hará la investigación sobre codificación fuente, mostrando la evolución histórica, presentado los distintos tipos de códigos que existen, mostrando sus principios de funcionamiento, diferencias, ventajas y desventajas y finalmente en los casos que ameriten, su algoritmo de implementación. Además se realizará el estudio necesario para conocer la forma en que debe programarse el dispositivo. Esto es, la lectura de las hojas de datos del chip, el manual de la tarjeta entrenadora con la que se desarrollará el sistema, la AD11C24DXSP32K, de Technological Arts, Canadá; y los manuales de programación de 68HC11 disponibles en Internet. Una vez determinado cual algoritmo de codificación se implementará, basado en la extensión del programa, la complejidad de la implementación del algoritmo y los recursos disponibles en la tarjeta entrenadora, se escribirá un programa para el dispositivo preferiblemente en lenguaje ensamblador y se realizarán las pruebas necesarias para depurarlo. En el momento en que el programa desarrollado cumpla las expectativas, será grabado en la memoria del módulo y se realizarán las pruebas necesarias en el sistema implementado y se redactará el Manual de Usuario del sistema desarrollado. 6 CAPÍTULO 2: Desarrollo teórico 2.1 Generalidades de Probabilidad La teoría de la probabilidad es la teoría matemática que modela los fenómenos aleatorios2. En los sistemas de comunicación digital esta teoría es necesaria para describir las fuentes de información. Se dice que un espacio de eventos I está constituido por una serie de eventos elementales ak ({a1,a2,…,ak,,…,aK}). Un evento A es un subconjunto de I, y cada vez que se de un evento elemental ak que pertenezca a A, entonces sucedió A. La probabilidad se puede definir desde un punto de vista estadístico, según Richard von Mises, como sigue: n N ( A) N →∞ N p ( A) = lim hN ( A) = lim N →∞ (2.1-1) Esto es, que la probabilidad de un evento A es igual al límite cuando N tiende a infinito del cociente entre el numero de veces que se dio el evento A, tras la realización de N experimentos, y el numero de estos experimentos (N). O visto de otra forma, la frecuencia relativa de un evento aproxima hasta lograr igualar a la probabilidad de ocurrencia del mismo, conforme el número de experimentos es muy grande. La independencia estadística, de eventos simples, se define como: p (u N / u N −1 ) = p (u N ) (2.1-2) La independencia estadística, de eventos conjuntos, se define como: p (u N , u N −1 ,..., u1 ) = p (u N ) ⋅ p (u N −1 ) ⋅ ... ⋅ p (u1 ) 2 http://es.wikipedia.org/wiki/Teor%C3%ADa_de_la_probabilidad 7 (2.1-3) Entonces, la probabilidad de un evento simple N dado el evento N-1, es igual a la probabilidad de solo el evento N, o sea, su probabilidad de ocurrencia no depende de la ocurrencia de otro(s) eventos. Esta definición se extiende para la probabilidad conjunta, donde la ocurrencia de varios eventos simultáneamente corresponde al producto de las probabilidades independientes. En las fuentes discretas sin memoria, se considera como eventos independientes los distintos elementos del alfabeto que esta entrega. 2.2 Fuentes de información Una fuente de información es un elemento que entrega una señal, que contiene información acerca de la naturaleza o comportamiento de algún fenómeno. Esta señal puede ser analógica, como una señal de audio o video, o puede ser digital, como los datos de un disco compacto. Es importante resaltar las fuentes digitales, pues en sus salidas solo se da un número finito de valores en determinados instantes de tiempo. Las fuentes pueden clasificarse basándose en la variable independiente tiempo, en: • Fuentes de tiempo continuo: la función está definida para cualquier valor de la variable independiente. • Fuentes de tiempo discreto: la función sólo está definida para un conjunto contable de instantes de tiempo. Pero se pueden clasificar también según el rango de valores que cubren las señales, en este caso: 8 • Fuentes continuas o de amplitud continua: el valor de la función toma un rango continuo de valores. • Fuentes discretas o de amplitud discreta: el valor de la función sólo toma un conjunto finito de valores. A cada uno de estos valores lo llamamos símbolo. El conjunto de todos los símbolos se suele llamar alfabeto. La elección del alfabeto es, en cierto modo, arbitraria. Estas dos clasificaciones son ortogonales, o sea, existen fuentes continuas de tiempo continuo, fuentes continuas de tiempo discreto, fuentes discretas de tiempo continuo y fuentes discretas de tiempo discreto. A pesar de esto, en la práctica sólo se encuentran dos tipos: las llamadas fuentes analógicas, que son fuentes continuas de tiempo continuo; y las llamadas fuentes digitales, que son fuentes discretas de tiempo discreto3. Como se mencionó anteriormente, una fuente digital posee un número limitado de códigos de salida. Al conjunto de estos códigos se les llama alfabeto. Las fuentes digitales se suelen clasificar según la relación que tenga un símbolo del alfabeto con los que le preceden de la siguiente manera: • Fuentes sin memoria: los símbolos son estadísticamente independientes entre sí. De esta manera, los símbolos que hayan aparecido hasta el momento no van a condicionar al símbolo presente ni a posteriores. • Fuentes con memoria: la aparición de los símbolos no es estadísticamente independiente. Es decir, si han aparecido M–1 símbolos, el símbolo M-ésimo está condicionado por los anteriores. 3 En realidad no existen fuentes digitales. El concepto de fuente digital se fundamenta en la manera de interpretar la señal que entrega la fuente. 9 En este proyecto se trabajará con Fuentes discretas sin memoria. Estos símbolos que aparecen a la salida del bloque fuente, son generalmente producto de una serie de procesos que se dan en el bloque fuente, mas específicamente en su convertidor de señales analógicas a digitales. Estos procesos son: • Muestreo: corresponde a tomar muestras de la señal original, en intervalos de tiempo definidos, convirtiendo la señal a una señal de valor continuo pero de tiempo discreto. Se le conoce como señal PAM. • Cuantización: Corresponde a asignar cierto valor fijo a los valores de la señal PAM que estén dentro de un intervalo de cuantización L. Se le conoce como señal M-ARY PAM, donde M es el número de niveles de cuantización (L+1). • Codificación binaria: Corresponde a la asignación de un código de longitud fija a cada uno de los niveles asignados a la señal M-ARY PAM. Este proceso convierte la señal M-ARY PAM a una secuencia de unos y ceros. Comúnmente se le llama señal PCM. El conjunto de todos los posibles códigos se conoce como el alfabeto. 10 Figura 2.1 Digitalización de una señal analógica 11 2.2.1 Medida de la información en las fuentes de información A una fuente la caracterizan su alfabeto y la probabilidad de aparición de cada uno de los símbolos (códigos) de ese alfabeto. La información que representa este conjunto de símbolos se puede dividir en cuatro partes, a saber: la conocida o redundante, la desconocida o no redundante, la relevante o significativa y la irrelevante o no significativa. La figura 2.2 muestra un diagrama de la división de la información en planos (Schouten). De estos planos, solamente la parte que es a la vez relevante y no redundante, o sea la parte interesante, debe transmitirse al receptor. Cada una de estas partes puede definirse matemáticamente con ayuda de la teoría de la información. Redundante No redundante Irrelevante Relevante Interesante Figura 2.2 Planos de información según Schouten 12 “Supóngase que se tiene un grupo de n eventos con probabilidades de ocurrencia p1,p2, …,pn. Estas probabilidades es lo único que conocemos del evento a ocurrir. ¿Podemos encontrar una medida de cuanta “elección” está involucrada en la selección del evento o de cuanta incertidumbre se tiene de la salida? Si esa medida existiera, digamos H ( pi ) , es razonable que esta requiera cumplir con: • H debe ser continua en pi • Si todos los pi son iguales, p i = 1 , entonces H debe ser una función monotónica n creciente en pi. Con eventos igualmente probables, hay más incertidumbre cuando hay más eventos posibles. • Si una elección fuera dividida en dos elecciones sucesivas, el valor original de H debería ser la suma ponderada de los valores individuales de H. Esto se ilustra en la figura 2.3 1 1 1 1 1 1 2 1 H , , = H , + H , 2 3 6 2 2 2 3 3 Figura 2.3 Descomposición de una decisión de tres posibilidades 13 El coeficiente de 1/2 esta ahí pues la elección entre 2/3 y 1/3 ocurre solo la mitad de las veces. Teorema: La única H que satisface las 3 suposiciones arriba citadas es de la forma n H = − K ∑ pi log( pi ) 2.2.1-1 i =1 ;donde K es una constante positiva, pi es la probabilidad del símbolo i-ésimo del alfabeto y log(pi) es la cantidad de información que contiene el mismo. A esta cantidad se le conoce como entropía de la fuente. (…) La entropía en el caso de dos posibilidades con probabilidades p y q=1-p, tiene una gráfica de la siguiente forma: Figura 2.4 Entropía en el caso de dos posibilidades con probabilidades p y (1-p) 14 La cantidad H tiene un número de propiedades interesantes que la sustentan como una medida razonable de la decisión o la información. • H = 0 si y solo si todas la pi son cero excepto una, que tiene valor unitario. Así, solo cuando estamos seguros de la salida, H desaparece. De otra forma es positiva. • Para un n dado, H es máximo e igual a log(n) cuando todas las pi son iguales. Esta es intuitivamente la situación más incierta. Entonces, la entropía H siempre es menor o igual al logaritmo del número de símbolos n del alfabeto. El contenido de decisión Ho, referido a un solo símbolo del alfabeto, se da en la condición de igualdad en la ecuación 2.2.1-2. Se utiliza un logaritmo en base 2 para que las unidades sean bits/símbolo H ≤ log 2 K (2.2.1-2) ”4 El contenido de decisión Ho está constituido por la entropía de la fuente y por la redundancia. El teorema de codificación fuente demuestra que una fuente discreta sin memoria puede representarse sin pérdidas de información con un índice de transmisión no menor a la entropía de la fuente. Esto significa que podría eliminarse por completo la redundancia de la fuente. 2.3 4 Codificación fuente Adaptado de: Shannon, C.E. “A mathematical theory of communication” p.10-11 15 Cuando una señal es digitalizada5, a la salida del bloque fuente se obtiene un número definido de posibles niveles. Codificar esta señal consiste en asignar una y solamente una palabra de código a cada uno de estos niveles. Esta asignación de códigos es completamente arbitraria, y en este sentido existen muchos códigos, por ejemplo el código binario puro, el código BCD, el código Gray. Estos códigos tienen una característica en común: dado un número de niveles de cuantización, todas las palabras de código poseen la misma longitud. En comunicaciones, esta no es una característica muy deseable, pues los datos requerirían mucha capacidad en el canal de comunicación. Existen técnicas para asignar códigos de longitud variable a estas palabras de longitud fija, de manera que se le asignen palabras de código cortas a los elementos mas probables, o sea, los que poseen menos información y palabras de código mas largas a los elementos menos probables, que contienen mayor cantidad de información. Estas técnicas se conocen como técnicas de codificación fuente y proveen algoritmos con los cuales se elimina por completo, o casi por completo, la redundancia de la fuente. 2.3.1 Teorema de codificación fuente A los códigos de una fuente discreta sin memoria A con un alfabeto de n símbolos se les puede asignar palabras de un código prefijo, tal que la longitud media x de las palabras de código satisface la siguiente relación: H ( A) H ( A) ≤x< +1 log 2 ( n ) log 2 ( n ) 5 La señal también puede ser una señal digital y no requerir digitalización. 16 (2.3.1-1) Donde: K x = ∑ p ( ak ) ⋅ xk (2.3.1-2) k =1 ;p(ak) es la probabilidad de ocurrencia del k-ésimo símbolo fuente y x k es el número de elementos de código utilizados en las palabras de código. En un código prefijo la parte inicial de todas las palabras de código son diferentes, esto es una condición suficiente pero no necesaria para que el código pueda decodificarse en forma inequívoca. Una condición necesaria para la construcción de este tipo de códigos es que las longitudes de las palabras de código satisfagan (2.3.1-3) K ∑n −xk ≤1 (2.3.1-3) k =1 donde n es la cantidad de símbolos de código (si es binario n=2). La redundancia R por símbolo fuente es: R = H o − H = log 2 K − H = x ⋅ log 2 n − H (2.3.1-4) Cuando la codificación es de longitud variable, se sustituye x por x en (2.3.1-4) y se obtiene lo que se conoce como redundancia residual Rc. Cuando los códigos no tienen redundancia residual, se dice que son códigos óptimos, en caso contrario, son códigos no óptimos. Esto sucede cuando las probabilidades de los símbolos del alfabeto son potencias enteras de D 17 2.4 Técnicas de compresión Las técnicas de compresión consisten básicamente en dos algoritmos: • Compresión: Lleva la información original X a una representación Xc que requiere menos bits que X. • Descompresión: A partir de Xc genera una reconstrucción Y de la información original X. En general, se puede hablar de dos tipos de compresión: • Compresión sin pérdidas: La reconstrucción Y es idéntica a X, se utiliza donde no sea permitida la pérdida de información, por ejemplo textos. • Compresión con pérdidas: La reconstrucción Y tiene menos información que X, introduciendo distorsiones tolerable, entonces la pérdida de información no es perceptible; por ejemplo en la compresión de voz para sistemas telefónicos móviles. Cada uno de estos tipos de compresión utiliza distintas bases para su aplicación. 2.4.1 Técnicas de compresión sin pérdidas 2.4.1.1Compresores estadísticos Los compresores estadísticos se fundamentan en la probabilidad de aparición de los símbolos para asignar los nuevos códigos. 2.4.1.1.1 Codificación Shannon - Fano 18 Es una técnica de compresión no óptima, propuesta por C.E. Shannon en el documento “A Mathematical Theory of Communication” en 1948 y produce códigos prefijo. Utiliza un alfabeto de símbolos de longitud fija y sus probabilidades para construir los nuevos códigos de la siguiente manera: 1. Para una lista de símbolos, debe obtenerse la frecuencia de aparición de cada uno. 2. Ordenar los símbolos de izquierda a derecha en orden descendente de ocurrencia 3. Divida la lista en dos partes, de manera que la suma de las frecuencias de cada mitad sea lo más cercana a la otra. 4. A la mitad de la izquierda se le asigna el bit 0, mientras que a la de la derecha el 1 5. Repetir los pasos 3 y 4 en cada una de las mitades, hasta que cada símbolo sea una hoja del árbol de codificación. Ej: Sean los siguientes símbolos con sus respectivas frecuencias de aparición Tabla 2.1 Ensemble de la fuente A A1 A2 A3 A4 A5 2 5 9 7 10 1. A5 A4 A3 A2 A1 2. A5 A3 (0) / A4 A2 A1 (1) 3. A5 (00) / A3 (01) // A4 (10)/ A2 A1 (11) 4. A5 (00) / A3 (01) /// A4 (10) // A2 (110) /A1 (111) Finalmente 19 Tabla 2.1 Ensemble de la fuente A codificado A1 11 1 2.4.1.1.2 A2 11 0 A3 A4 A5 01 10 00 Codificación Huffman Fue desarrollada por David A. Huffman durante sus estudios de doctorado en el Instituto Técnico de Massachusetts y publicada en 1952 en el documento "A Method for the Construction of Minimum-Redundancy Codes” En 1951 el profesor Robert Fano permitió a Huffman y sus compañeros en el curso “Teoría de la Información” escoger entre realizar un examen final o presentar un trabajo, cuyo objetivo era encontrar un código binario más eficiente. Huffman finalmente logró encontrar un algoritmo más eficiente que los existentes, solucionando la mayor parte de los errores en el algoritmo de Shannon – Fano. La solución se basa en construir un árbol binario, pero desde la raíz. En el documento original, Huffman plantea una serie de restricciones para crear códigos de redundancia mínima: “Las siguientes restricciones básicas serán impuestas en un código de ensemble: 1. Dos mensajes no pueden consistir en un arreglo idéntico de dígitos de codificación. 2. Los códigos de mensaje serán construidos de tal manera que ninguna indicación adicional es necesaria para especificar donde un mensaje empieza y 20 termina una vez que el punto de inicio de la secuencia de mensajes es conocida. La restricción 2 implica que ningún mensaje sea codificado de manera que sus dígitos aparezcan en el mismo orden de los primeros dígitos de un código mas grande.(…) 3. L(1) ≤ L( 2 ) ≤ ...L( N −1) = L( N ) ; donde L es el largo del n-ésimo mensaje 4. Al menos dos, y no mas de D mensajes con tamaños de código L(N) tienen códigos que difieren solamente en su dígito final. 5. Cualquier secuencia de L(N) – 1 dígitos debe ser usada como un código de mensaje o debe tener uno de sus prefijos usados como código de mensaje.”6 Es importante destacar que es su publicación, Huffman aplica este método no solo para alfabetos binarios (D = 2), sino que lo generaliza para alfabetos n-arios (D = n) El algoritmo de codificación de Huffman es muy similar al de Shannon – Fano, y consiste en lo siguiente 1. Empezar con tantas hojas como símbolos halla. 2. Ordene en fila todos los símbolos del símbolo menos probable al más probable 3. Mientras haya mas de un nodo en la fila: 1. Separe los dos nodos con menor peso. 2. Cree un nuevo nodo interno con los dos nodos removidos como ramas y la suma de sus pesos como el nuevo peso. 6 Adaptado de D.A. Huffman, “Proceedings of the I.R.E.”, sept 1952 21 3. Ordene este nuevo nodo dentro de la fila anterior (que ya no tiene los nodos removidos 4. El último nodo es el nodo raíz. El árbol está completado La figura 2.5 ilustra el proceso de construcción del árbol Luego, los códigos pueden asignarse escribiendo un cero en el elemento superior de la llave, y un uno en el inferior, como lo muestra la figura 2.5. También puede asignarse de manera inversa, el uno arriba y el cero abajo. Es indispensable que la manera escogida se aplique por igual en todos los nodos, de lo contrario se obtendrán resultados erróneos. La codificación de Huffman, además, tiene las siguientes variaciones: • n-ario: Es la extensión para un D > 2, que se considera en el trabajo original de D.A. Huffman. • Adaptativo: Construye el código mientras lee los símbolos fuente en cada transmisión. Figura 2.5 Construcción del árbol de Huffman con dos símbolos codificados 22 Existen además propuestas de variaciones de codificaciones Huffman, pero no poseen algoritmo de implementación; • De longitud limitada: hace lo mismo que la técnica original, pero tiene una restricción en cuanto a la longitud máxima de palabra de código. • De costo desigual de letras: En el código Morse, transmitir un espacio toma más tiempo de transmisión que transmitir un punto, por lo que es más costoso. De igual forma, las palabras del alfabeto codificado pueden no tener longitud uniforme debido al medio de transmisión. La técnica de peso desigual de letras busca minimizar también este efecto. 2.4.1.1.3 Codificación Aritmética A diferencia de la codificación Huffman, donde es necesario que la probabilidad de los símbolos sea una potencia negativa de dos para eliminar la redundancia residual, la codificación aritmética codifica una secuencia de entrada de símbolos del alfabeto fuente mediante un número representado en punto flotante. Estos códigos son especialmente útiles cuando se trabaja con alfabetos pequeños o con distribuciones de probabilidad muy sesgadas. El primer código aritmético fue ideado por Meter Elías antes de 1963, en un trabajo no publicado. La primera publicación del código Elías aparece en el texto Information theory and coding 7 de N. Abramson; sin embargo, hay muchos esquemas prácticos de codificación. El primero de ellos no estuvo disponible sino hasta 1976, en un trabajo por Jorma Rissanen y Richard Pasco 7 N. Abramson, Information theory and coding. New York: McGraw-Hill, 1963. 23 El proceso de codificación aritmética se basa en asignar a cada símbolo un intervalo entre 0 y 1, de forma que la amplitud de cada intervalo sea igual a la probabilidad de cada símbolo. La suma de las amplitudes de los intervalos debe ser igual a la unidad. Previamente es necesario establecer un orden entre los símbolos. No es necesario seguir algún criterio especial para establecer un orden entre los símbolos del alfabeto fuente, pero el orden establecido debe ser conocido por el decodificador para poder hacer una correcta decodificación en la recepción. Para realizar la codificación de una determinada cadena de entrada se siguen los siguientes pasos: 1. Se selecciona el primer símbolo de la secuencia de entrada y localizar el intervalo asociado a ese símbolo. 2. A continuación se selecciona el siguiente símbolo y se localiza su intervalo. Se multiplican los extremos de este intervalo por la longitud del intervalo asociado al símbolo anterior (es decir, por la probabilidad del símbolo anterior) y los resultados se suman al extremo inferior del intervalo asociado al símbolo anterior para obtener unos nuevos extremos inferior y superior. 3. El paso anterior se repite hasta que todos los símbolos del mensaje hayan sido procesados. Para el símbolo i-ésimo se calcula su intervalo de la siguiente forma: Inf i = Inf i −1 + ( Supi −1 − Inf i −1 ) ⋅ Inf i −1 Supi = Inf i −1 + ( Supi −1 − Inf i −1 ) ⋅ Supi −1 24 4. Por último se selecciona un valor dentro del intervalo del último símbolo de la secuencia. Este valor representará la secuencia que queremos enviar. Cuando se transmite un valor al receptor es necesario indicar cuantos símbolos se han enviado para que el receptor sepa cuando debe finalizar el proceso de descompresión. Para indicar esto existen dos técnicas. La primera consiste en enviar antes del valor elegido el número de símbolos que se han comprimido en binario. De esta forma el receptor sabrá cuantos símbolos han sido comprimidos antes de comenzar el proceso de descompresión. La segunda técnica consiste en utilizar en el alfabeto un símbolo más con una probabilidad asociada. Este símbolo será un símbolo especial que indicará el final de una secuencia de símbolos comprimidos. Al igual que el resto, éste será comprimido por el emisor después del último símbolo que se quiere comprimir. El receptor sabrá cuando debe finalizar el proceso de descompresión al interpretar el último símbolo descomprimido como un símbolo especial. En el proceso de decodificación se utiliza la tabla original en la que se habían asignado unos intervalos iniciales a cada símbolo. El receptor recibe a través del canal un número decimal en punto flotante. Lo primero que se hace es comprobar en la tabla a que intervalo pertenece ese valor y el símbolo al que se le ha asociado ese intervalo será el primer símbolo que se ha transmitido. A continuación se le resta al número recibido el extremo inferior del intervalo al que pertenece, y el resultado se divide por la longitud del intervalo. Con el número obtenido repetimos el proceso anterior. Este proceso se repite hasta que todos los símbolos del mensaje hayan sido procesados. 25 Por último, debemos tener en cuenta dos problemas relacionados con esa técnica de codificación. El primer problema está en que el número de decimales aumenta con la cantidad de símbolos del alfabeto fuente. El segundo problema relacionado con el uso de esta técnica es que cuando los extremos inferior y superior de un intervalo están muy próximos pueden producirse errores al asignar el intervalo en la fase de decodificación. 2.4.1.1.4 Codificación Predictiva Este tipo de codificación, al contrario de las anteriores, es completamente adaptativa. Estos procuran predecir el siguiente mensaje de la entrada tomando como referencia tomando como base el conocimiento de la entrada procesada hasta el momento. Si el mensaje actual coincide con el predicho, éste se codificará con un número menor de bits. En caso contrario, su codificación se hará con más bits, que permitirán entonces sincronizar el descompresor para que mantenga sus tablas internas iguales a las del compresor, sin pasárselas explícitamente. En general son más rápidos y fáciles de implementar que los anteriores, por lo que se convierten en una solución barata para sistemas en tiempo real, con relaciones de compresión aceptables. El Predictor, creado en 1987 por Timo Raita y Jukka Teuhola, de la Universidad de Turku, Finlandia; es quizá el más rápido jamás diseñado. Éste funciona básicamente de la siguiente manera: 26 • Crea una matriz de 256 filas y 256 columnas donde guarda en la casilla mi,j, el byte que siguió a las dos anteriores salidas ASCII i y j. Si la predicción de esta salida es correcta, la salida será un bit puesto a 1, de lo contrario será cero. Además actualiza la tabla para que la siguiente vez, sea capaz de predecir ese mismo evento. Así también se sincroniza el descompresor. • El descompresor parte de una tabla vacía. Al recibir un 1 sabe que el mensaje recibido es el que se encuentra en la tabla en la posición indicada por los dos últimos mensajes resultado de la descompresión realizada hasta el momento. Si recibe un cero, la información recibida será el mensaje puro, y podrá actualizar la tabla (igual que el compresor) 2.4.1.1.5 Codificación de Golomb y Codificación Rice La codificación de Golomb fue inventada por Solomon W. Golomb en 1966, y responde óptimamente para alfabetos con distribuciones geométricas, esto es, cuando los valores pequeños son muchísimo mas probables que los valores grandes. La codificación Rice es una variación de la codificación Golomb, que inventado y desarrollado independientemente por Robert F. Rice. Es un código donde el parámetro variable es una potencia de dos. Esto lo hace extremadamente eficiente para uso en computadoras, pues la división es un desplazamiento de bits y la operación residuo se convierte en un enmascaramiento de bits. Se utiliza en compresión sin pérdida de audio e imágenes. 27 2.4.1.2Compresores sustitucionales En la práctica, a menudo existe una estructura en los datos, es decir secuencias repetitivas o patrones en la información. Las técnicas basadas en diccionario explotan la estructura de los datos para incrementar la cantidad de compresión. En este sentido, cuando la información tiene pocas cadenas de símbolos muy repetitivas, este es un mecanismo de compresión muy provechoso. Hay dos posibles tipos de diccionarios, los estáticos y los dinámicos. El primer tipo es apropiado cuando se conoce la estructura repetitiva de los datos. En él, se almacenan los patrones más frecuentes y las palabras de código. Durante la compresión, si el patrón que ocurre no está en el diccionario, se codifica separadamente cada símbolo del patrón. El segundo tipo es adecuado para compresores generales aplicables a fuentes de distintas características, construyen el diccionario conforme procesan la entrada y el descompresor reconstruye el mismo diccionario La gran mayoría de técnicas basadas en diccionario son variantes de los métodos propuestos por Jacob Ziv y Abrahan Lempel en dos artículos de 1977 y 1978, de ahí, los nombres de dichos algoritmos: LZ77 y LZ78 2.4.1.2.1 LZ77, LZ78 y demás variaciones El algoritmo LZ77 logra la compresión reemplazando porciones de datos con referencias de datos que ya han pasado por el codificador (o el decodificador). Una referencia es codificada como un par de números conocidos como par longitud – distancia. Esto es, que la siguiente longitud es igual al que esta exactamente distancia caracteres atrás en la cadena. 28 Tanto el codificador como el decodificador, deben tener un registro de la información más reciente (2kB – 32kB). A este registro se le llama ventana deslizante. El algoritmo LZ78 trata de trabajar con información futura. Lo hace buscando por adelantado en el buffer de entrada y lo compara con su diccionario. Se buscará en el buffer hasta que no pueda encontrar una coincidencia con el diccionario; entonces, la salida será la localización en el diccionario, si hay alguna disponible, la longitud de la coincidencia y el carácter que causo la no coincidencia. La palabra resultante se agrega al diccionario. A pesar de su popularidad inicial, esta cayó abruptamente pues en las primeras decadas luego de su aparición, algunas partes del LZ78 fueron patentadas. Las variaciones más populares de estos algoritmos son: • LZW, creada por Terry Welch en 1984. Se utiliza en el formato de imagen GIF y TIFF, y actualmente en software de Adobe Acrobat. • LZSS, creada en 1982 por James Storer y Thomas Szymanski. Su principal diferencia es que en LZ77 la referencia del diccionario puede ser mas larga que la cadena a reemplazar mientras en LZSS dichas referencias son omitidas si la longitud es menor que un punto de quiebre. Además, LZSS usa banderas de un bit para indicar cuando el próximo trozo de datos es literal o una referencia a un par distancia – longitud. • LZMA, en desarrollo desde 1998, presenta una alta razón de compresión y un diccionario de compresión de tamaño variable. Se basa en el LZ77 y un range encoger (codificación similar a la aritmética). Forma parte de las herramientas de compresión 7z y 7-Zip 29 • DEFLATE, originalmente definido por Phil Katz a finales de los años 80, que usa una combinación del LZ77 y codificación Huffman, y es parte de la herramienta de compresión PKZIP. 2.4.1.3Otros tipos de codificación 2.4.1.3.1 Codificación Run-length Consiste en una técnica de compresión donde segmentos de datos repetidos son codificados como un solo valor y una cuenta, en lugar del segmento original. 2.4.1.3.2 Codificación Burrows - Wheeler Fue inventada por Michael Burrows y David Wheeler en 1994 y está basada en una transformada (BWT) descubierta por Wheeler en 1983. Cuando una cadena de caracteres es transformada por la BWT, ninguno de sus caracteres cambia de valor. La transformación permuta el orden de los caracteres. Si la cadena original tiene muchas subcadenas que se repiten, entonces la cadena transformada tendrá muchos lugares donde un mismo carácter es repetido muchas veces en la línea. Esto es deseable para compresión facilita la aplicación de técnicas como la transformada mover al frente o la codificación run-length. 30 2.4.1.3.3 Técnicas varias Compresión de audio • Técnica sin pérdidas de Apple – ALAC (Apple Lossless Audio Codec) • Codificación de Audio sin pérdidas, también conocido como as MPEG-4 ALS • Transferencia directa de Flujo – DST (Direct Stream Transfer) • Dolby de Verdadera Alta Definición - Dolby TrueHD • Sistema de Teatro Digital de alta definición Audio Maestro – DTS-HD Master Audio • Codec de Audio Gratis sin Pérdidas – Free Lossless Audio Codec – FLAC • Empaquetamiento sin Pérdidas Meridiano – Meridian Lossless Parking – MLP • Monkey's Audio – APE • OptimFROG • RealAudio sin pérdidas • Shorten – SHN • True Audio sin pérdidas – TTA • WavPack sin perdidas • Windows Media sin pérdidas Compresión de gráficos • Optimizacion binaria adaptativa - Adaptive Binary Optimization – ABO • Formato de intercambio de gráficos (Sin pérdida, pero contiene un rango limitado de colores) – Graphics interchange format – GIF 31 • Estandar del Joint Bi-level Image Experts Group (compresión con o sin pérdida para imágenes blanco y negro ) - JBIG2 • Estandar del Joint Photographic Expert Group (Estandar de compresión sin pérdida o con muy poca) – JPEG – LS • incluye un metodo de compresion sin pérdida, demostrado por Sunil Kumar, Prof de la Universidad Estatal de San Diego - JPEG 2000 • Archivo de gráficos progresivo (con o sin pérdida) – Progressive Graphics File PGF • Red de gráficos portátil – Portable Network Graphics – PNG • Codec sin pérdidas Qbit - Qbit Lossless Codec • Formato de archivo de imagen etiquetado – Tagged Image File Format – TIFF • incluye un método de compresión sin pérdida – WMPhoto Compresión de video • Codec de animación – Animation codec • Codec de video CamStudio - CamStudio Video Codec • Codec de video RGB sin pérdidas, basado en compresión de imagen PNG - CorePNG • Codec de Video FF 1 codificador experimental de alta compresión sin ppérdidas FFV1 • Estándar capaz de proporcionar una buena calidad de imagen con tasas binarias notablemente inferiores a los estándares previos (MPEG-2, H.263 o MPEG-4 parte 2) - H.264/MPEG-4 AVC • Codec de video “open source” - Lagarith • Codec de video sin pérdidas de la Universidad de Moscú - MSU Lossless Video Codec 32 CAPÍTULO 3: Microcontrolador MC68HC11 3.1 Introducción Recibe el nombre de controlador el dispositivo que se emplea para el gobierno de uno o varios procesos. Aunque este concepto ha permanecido invariable a través del tiempo, su implementación física ha variado frecuentemente. Un microcontrolador es un circuito integrado de alta escala de integración que incorpora la mayor parte de los elementos que configuran un controlador. Un microcontrolador dispone normalmente de los siguientes componentes: • Procesador o CPU o Unidad Central de Procesamiento, por sus siglas en inglés. • Memoria RAM para almacenar los datos temporales generados por el programa • Memoria para almacenar el programa principal. Ésta puede ser tipo ROM, PROM, EPROM o EEPROM. En algunos casos, la aplicación también podría guarda datos importantes que se desea permanezcan aunque se desenergice la aplicación en memoria tipo EEPROM. • Líneas de E/S para comunicarse con el exterior. A los grupos que forman estas líneas se les denomina puertos. En algunos casos, como en la familia HC11, estas líneas pueden estar compartidas por algún otro recurso del microcontrolador, como se verá mas adelante. • Diversos módulos para el control de periféricos como temporizadores, interfaz de comunicación serie o paralela, convertidores analógico/digital y digital/analógico, entre otros. 33 • Generador de impulsos de reloj que sincronizan el funcionamiento de todo el sistema. La incorporación de un microcontrolador en aplicaciones presenta ventajas como: • Aumento de prestaciones pues poseer un mayor control sobre un determinado elemento representa una mejora considerable en el mismo. • Aumento de la fiabilidad pues al reemplazar un elevado número de elementos por un microcontrolador se disminuye el riesgo de averías y se precisan menos ajustes. • Reducción del tamaño en el producto acabado dado que la integración del microcontrolador en un solo chip disminuye el volumen y la mano de obra. • Mayor flexibilidad: las características de control están programadas por lo que su modificación sólo necesita cambios en el programa de instrucciones. El microcontrolador es en definitiva un circuito integrado que incluye todos los componentes de un computador. Debido a su reducido tamaño es posible montar el controlador en el propio dispositivo al que gobierna. En este caso el controlador recibe el nombre de controlador empotrado (embedded controller). 3.2 Especificaciones generales La familia Motorola 68HC11 también conocida como HC11 o 6811 es una familia de microcontroladores, derivada del microprocesador Motorola 6800. Estos dispositivos siguen la Arquitectura Eckert-Mauchly, en la que la memoria de programa, de datos y de entrada/salida se direcciona en un único mapa de memoria. En la figura 3.1 se pueden ver algunas de las variantes de la familia HC11 con sus principales características. 34 Todos los microcontroladores de la familia 68HC11 poseen dos acumuladores de ocho bits cada uno, conocidos como A y B, además de un acumulador virtual D, que es la concatenación de A y B, dando como resultado un registro de 16 bits, con A como la parte alta del mismo. También se tienen dos registros índice de 16 bits conocidos como X y Y. Finalmente, posee también un registro de banderas, de cuyo estado dependen las instrucciones de saltos condicionales, un puntero de pila (esta pila se direcciona generalmente en el tope de la memoria RAM, aunque puede hacerse en cualquier lugar de ésta) y un contador de programa. Figura 3.1 Familia 68HC11 35 Los 68HC11 tienen cinco puertos externos nombrados con las letras A, B, C, D y E, cada uno de ocho bits excepto el D, que es de seis bits. A continuación se describe cada uno de los puertos, junto con los recursos del microcontrolador están compartidos en ellos: • El puerto A dispone de 3 pines de entrada, 4 pines de salida y uno configurable como entrada o como salida. Se encuentra mapeado en memoria en la dirección 1000 h. Los pines del puerto A están compartidos por los siguientes recursos: comparadores, acumulador de pulsos y capturadores. • El puerto B tiene 8 bits de salida. En el modo no expandido del MCU se comporta como un puerto de salida. Si el microcontrolador se utiliza en modo expandido (para acceder memoria externa al chip) el puerto B se utiliza para manejar el byte alto del bus de direcciones. Su dirección es la 1004h. • El puerto C es un puerto de entrada/salida. En el modo no expandido sus 8 bits pueden actuar como entradas o salidas independientes, según cómo se configuren los bits en el registro DDRC (1007h). Un cero en un bit del registro DDRC configura el pin correspondiente para entrada. Un uno lo hace para salida. La dirección del puerto C es 1003h. Si el microcontrolador funciona en modo expandido el puerto C actúa como la parte baja del bus de direcciones multiplexada con el bus de datos. • El puerto E es un puerto de 8 bits de entrada. Está situado en la dirección 100Ah y comparte pines con los 8 canales del convertidor A/D 36 Existe un dispositivo integrado de TEKMOS cuyo número de parte es TK68HC24 y permite el uso del modo extendido y la función de líneas de entrada/salida digital de los puertos B y C conjuntamente. 3.3 Puerto D y la Interfaz de comunicación serial asíncrona Al igual que el puerto C, D es un puerto de entrada o salida pero de solamente seis bits, al que se pueden configurar independientemente estas líneas como entrada o salida. El puerto esta mapeado en la dirección. 1088h. Además de esta función, también se pueden establecer protocolos de comunicación serie síncrona y asíncrona. La Interfaz Serie Asíncrona, o SCI por sus siglas en inglés, permite que dos dispositivos establezcan comunicación serial. El Bit 0 del puerto D corresponde al bit de recepción (Rx) y por esta línea ingresan los bits de datos desde el dispositivo externo. El Bit 1 corresponde al bit de transmisión (Tx) y por esta línea salen los bits de datos hacia el dispositivo externo. La SCI es un sistema asíncrono tipo UART full-duplex, que utiliza un formato estándar sin-regreso-a-cero (NRZ, por sus siglas en inglés), esto es un bit de inicio, ocho de datos (o nueve, según se configure) y uno de parada. Un generador de baud rate deriva valores estándar de comunicación a partir del reloj principal del microcontrolador. Este sistema se configura, controla y monitorea a través de cinco registros que se detallan a continuación: • BAUD: Normalmente éste registro se escribe una vez durante la inicialización del microcontrolador para fijar el baud rate de la comunicación. Esta velocidad es la misma para transmisión y recepción y se deriva del reloj del bus del microcontrolador. 37 Para este fin, se utiliza un divisor de dos etapas. La figura 3.2 contiene la lista de posibles configuraciones para la velocidad del SCI. Los bits SPx y SCRx son parte del registro BAUD. • SCCR1: Es el registro de control 1 y se encarga de configurar la cantidad de bits de datos, tanto para el transmisor como para el receptor. Además, configura la opción de WAKE UP, en que el receptor se queda con las interrupciones inhibidas esperando un evento hardware externo, (asociado a la línea de recepción), que le devuelva al estado activo con interrupciones. Esta opcion se recomienda para aumentar la eficiencia en sistemas multireceptores pero de poco tráfico. Si el bit WAKE esta activado entonces se espera hasta detectar una marca de dirección, si por el contrario esta desactivado se espera hasta detectar que la línea de recepción esta vacía. • SCCR2: Es el registro de control 2 y determina si las interrupciones de transmisión y recepción están activadas o no y permite habilitar el transmisor y el receptor. • SCSR: Es un registro de estado que activa las banderas para que se ejecuten las interrupciones habilitadas con el SCCR2 • SCDR: Es el registro al cual se escriben y del cual se leen los datos que se intercambian por la SCI. 3.4 Mecanismo de interrupciones del SCI. Existen cuatro causas de interrupción en el SCI, al aparecer alguna de estas se activa su bit correspondiente en el registro de estado. El SCI sólo tiene asociado un vector de interrupción por lo que sólo existe una rutina de servicio. Esta rutina de servicio tiene que leer 38 el registro de estado (SCSR) y detectar cuál de las 4 causas de interrupción ha ocurrido. Según la cual bifurcará a una rutina o a otra. Finalmente se retornará con RTI. Es importante hacer notar que siempre que haya un bit a 1 en el registro de estado, la CPU lo interpretará como una petición de interrupción y llamará a la rutina de servicio del SCI, por lo tanto es muy importante poner el bit correspondiente a cero para que al terminar la rutina de servicio la CPU no se vuelva a interrumpir por la permanencia de dicho bit todavía en estado alto. Esto último es un punto muy importante. Supónganse que se produce una interrupción en el SCI porque se ha recibido un carácter. El bit correspondiente del registro de estado se pondrá en alto indicando el evento. La CPU detecta que este bit está activado y pasa a ejecutar la rutina de servicio del SCI. Si esta rutina no pone a cero este bit, al terminar la subrutina el bit seguirá activado y la CPU lo tomará como una nueva interrupción que se ha producido, con lo que se volverá a ejecutar la rutina de servicio. Así permanecerá la CPU en un ciclo infinito ejecutando constantemente la rutina de servicio del SCI hasta que se produzca un reset externo. Los bits del registro de estado no se pueden poner a cero directamente. Para ponerlos a cero es preciso leer el registro SCSR y a continuación leer el registro de datos SCDR. La figura 3.3 muestra las causas de interrupción, el bit del registro de estado asociado a cada una y el bit del registro de control 2 que las enmascara. 39 Figura 3.2 Velocidades de comunicación configurables para la SCI del MC68HC118 8 Microcontrolador 68HC11: Fundamentos, recursos y programación. Doblado A, Cristina et al. 40 Figura 3.3 Bits relativos a la interrupción producida por la SCI1 41 CAPÍTULO 4. Implementación del Codificador Fuente 4.1 Escogencia de los símbolos El fin principal de la aplicación es mostrar de una manera clara el resultado de un proceso de codificación y decodificación fuente. Se decidió entonces que utilizar texto para dicho fin era una buena opción pues los caracteres se representan en una computadora como códigos de ocho bits. Los símbolos que se codificaron se encuentran en la tabla 4.1 y corresponden a las letras que comúnmente aparecen en textos en español y a algunos símbolos de un teclado con distribución latinoamericana que podrían introducirse como parte de un texto. Además se incluyó los correspondientes a la estructura del texto, o sea, espacios, saltos de línea y tabulaciones. Para determinar las probabilidades de los símbolos se analizó, con un programa escrito en lenguaje C, cuyo código fuente puede consultarse en la sección de anexos; un texto de aproximadamente treinta y cinco mil caracteres contando los espacios, y se utilizó la relación (2.1-1) donde h(n) es cada carácter y N el total de caracteres en el texto. Además, para determinar las probabilidades de los símbolos que no aparecían en el texto, se tomo la probabilidad residual y se dividió entre estos. Debe recordarse que los símbolos representados en las computadoras corresponden a códigos binarios de ocho bits, como se mencionó anteriormente, llamado Código Americano Estándar para Intercambio de Información ASCII, por sus siglas en inglés (American Standard Code for Information Interchange) en una de sus versiones extendidas, pues la versión original de siete bits no contemplaba caracteres especiales de otros idiomas, como por ejemplo las vocales tildadas. 42 Tabla 4.1 Símbolos del texto en español y su probabilidad aproximada de aparición Símbolo Probabilidad a A Á á e E É é i I Í í o O Ó ó u U Ú ú b B c C d D f F g G h H j J k K l L m M n N p P q Q r R 0,086825 0,000673 0,000035 0,002624 0,111618 0,002296 0,000017 0,001968 0,052261 0,000328 0,000134 0,003505 0,067022 0,000311 0,000134 0,005421 0,033615 0,000242 0,000134 0,000898 0,009237 0,000466 0,037914 0,000691 0,039485 0,000380 0,005697 0,000224 0,009030 0,000276 0,005404 0,000363 0,002521 0,000086 0,000242 0,000035 0,046512 0,001347 0,022013 0,001019 0,057976 0,000570 0,020027 0,000742 0,008581 0,000121 0,048998 0,000242 Símbolo Probabilidad s S t T v V w W x X y Y z Z ñ Ñ ü Ü espacio , . tabulación salto de línea ; : ? ¿ ¡ ! " ‘ 1 2 3 4 5 6 7 8 9 0 = + * / \ 0,055783 0,001036 0,037448 0,000466 0,008788 0,000138 0,000397 0,000138 0,001916 0,000138 0,006388 0,000242 0,002486 0,000121 0,001416 0,00013448 0,00013448 0,00013448 0,162048 0,010411 0,006181 0,001105 0,001191 0,000414 0,000742 0,000242 0,000242 0,00013448 0,00013448 0,003021 0,000017 0,000829 0,000449 0,000173 0,000069 0,000294 0,000242 0,000224 0,00019 0,000535 0,000622 0,00013448 0,00013448 0,000483 0,00013448 0,000155 0,00013448 43 Símbol o Probabilidad < > # ( ( [ ] % $ @ _ & ~ 0,00013448 0,00013448 0,00013448 0,00013448 0,00013448 0,00013448 0,00013448 0,00013448 0,00013448 0,00013448 0,00013448 0,00013448 0,00013448 El análisis del texto y de los resultados tabulados en la tabla 4.1, brindó los siguientes resultados: • Contenido de Decisión: La relación (2.2.1-2) indica el contenido de decisión referido a un solo símbolo del alfabeto. Al aplicar esta relación se determina cuantos bits por símbolo se necesitan para describir la información que en este caso brindan los 108 símbolos escogidos. Entonces, con K = 108 se obtiene: H0 = 6,7549 Bit/Símbolo El contenido de decisión es igual a la suma de la redundancia del código y al contenido medio de información, o sea, Ho = R + H • (4.1-1) Entropía de la fuente: La relación (2.2.1-1) indica la entropía de la fuente, o sea, el mínimo índice de transmisión en bit por símbolo que se necesitan para transmitir la información sin pérdidas. Debe recordarse que la información que se transmitirá sin pérdidas es aquella que se conoce, o sea, para la cual fue calculada el código Huffman. Si aparece un símbolo desconocido, este se perderá debido a que no fue tomado en cuenta para generación del código. En la relación (2.2.1-1) se sustituye el valor de K por 1, pues esta constante sólo cuantifica una unidad de medida9. 9 “…(the constant K merely amounts to a choice of a unit of measure)…” Shannon, C.E. A mathematical theory of communication. 1948, p-11 Luego de realizar toda la suma, se obtiene el siguiente resultado H: 4,3743 Bit/Símbolo • Redundancia: La redundancia corresponde a la diferencia entre el máximo y el mínimo de bit por símbolo que se requieren para describir la información, al despejarla de (4.1-1). Para esta aplicación, la redundancia los caracteres ASCII corresponde a R = 2,3806 Bit/Símbolo 4.2 Codificación Como se mencionó en el capítulo anterior, el algoritmo de Huffman consiste básicamente en construir una lista con los símbolos y sus probabilidades, ordenados en forma descendente, y sumar recursivamente las dos probabilidades más pequeñas, pudiendo ser una de ellas, o ambas, el resultado de sumas anteriores. Para el desarrollo de esta aplicación, dicho árbol se hizo a mano, y puede encontrarse la sección de anexos. La tabla 4.2 muestra los resultados de esta codificación. Tabla 4.2 Símbolos de texto en español y su codificación Símbolo Código Símbolo Código Símbolo Código a A Á á e E É é i I Í í o O Ó ó u U Ú ú b B c C d D f F g G h H j J k K l L m M n N p P q Q r R s 1111 0000110001 00101101010100 00000011 011 101011011 0010110101010101 101010010 0100 00001101000 1010110010000 00101100 1001 00001100000 1010110010011 0000101 10100 101010011100 1010110010010 0010110111 1110001 00101101101 10111 0000110101 11101 00101001100 0000111 001011010100 1110000 101011010101 0000100 00001101001 00000010 0000000010011 101010001101 001011010101011 0001 000011001 00100 1010100110 1000 10101101011 111001 0010100101 1010101 1010100111010 0011 101010001100 0101 S t T v V w W x X y Y z Z ñ Ñ ü Ü espacio . , ; : Salto de línea Tabulación ? ¿ ¡ ! " ‘ 1 2 3 4 5 6 7 8 9 0 = + * / \ < > 1010110000 10110 00101101100 1010111 000000001000 00101001101 1010110101001 101010000 1010110101000 0010111 101010001111 00000001 0010110101011 000011011 1010110010101 1010110010100 1010110010111 110 0010101 000001 00101001111 0010100100 1010110100 # ( ) [ ] % $ @ _ & ~ 1010110011111 1010110011110 1010110001001 1010110001000 1010110001011 1010110001010 1010110001101 1010110001100 1010110001111 1010110001110 1010100111011 000000000 101010001110 101010001011 1010110010110 1010110011001 00101000 0010110101010100 0010110100 00101101011 000011000011 0000000010010 00000000101 101010001010 001010011101 001010011100 10101001111 0000000011 1010110011000 1010110011011 10101000100 1010110011010 000011000010 1010110010001 1010110011101 1010110011100 A partir de los resultados mostrados en la tabla 4.2 se calculó lo siguiente: • Longitud media de las palabras de código: De la relación (2.3.1-2) se puede calcular la longitud media de las palabras de código de los símbolos codificados. x = 4,4095 Bit/Símbolo • Redundancia residual: La redundancia residual aparece cuando las probabilidades de ocurrencia de los símbolos originales son potencias enteras negativas de 2, como 1/4,1/8, etc. En este caso, la redundancia residual del código generado es Rc = 0,0352 Bit/Símbolo La redundancia residual puede reducirse codificando en bloques de caracteres, en lugar de carácter por carácter, sin embargo el número de combinaciones es 1082 (este es el límite superior, pues algunas combinaciones tiene una probabilidad muy pequeña, por ejemplo “wx” que puede aparecer en modelos de productos en un catálogo) lo cual genera una larga lista de símbolos, y mayor tiempo de procesamiento. 47 4.3 Implementación El dispositivo implementado consiste de dos elementos: 4.3.1 El software de interfaz con el usuario: Un programa desarrollado en lenguaje C, se encarga de manejar un menú en el que se direccionan los archivos que se van a utilizar y se escoge entre cuatro opciones: codificar, decodificar, ver un archivo de texto o salir del programa. Una vez escogida opción de codificación o decodificación, el programa se encarga de enviar, uno por uno, los caracteres de un archivo fuente de tipo texto para realizar la función escogida en el menú. Finalmente, cuando se realiza la codificación o la decodificación, el programa entrega la estadística de los archivos fuente y destino, en cuanto al tamaño de ambos y la tasa de compresión. 4.3.2 El software de compresión y descompresión: Un programa desarrollado en lenguaje ensamblador, y descargado en la memoria del microcontrolador MC68HC11, se encarga de recibir los caracteres que envía la computadora y los convierte según sea la función que esté realizando (codificación o descodificación). En caso de que el símbolo a codificar sea desconocido por el MCU, este devuelve el código del espacio, el cual se va a ver reflejado durante la decodificación. Esto semeja la mensajería de texto a través de la red de telefonía celular, en que algunos aparatos se presenta éste símbolo en lugar de algunos caracteres cuando se recibe el mensaje. Por ejemplo, suponiendo que en el texto se 48 encuentre el símbolo “ç” como en la palabra “Barça”, el decodificador devolverá la palabra “Bar a”. Esto representa una ventaja ante símbolos desconocidos, pues al codificarlos como espacios en blanco, se disminuye el tamaño del símbolo de ocho bits a solo tres. En la tabla 4.4 se encuentra una serie de símbolos que no se tomaron en cuenta en el alfabeto codificado. Tabla 4.4 Símbolos del teclado de la computadora sin codificar Símbolo 4.4 º ª | · ¬ ` ^ { } ¨ ç € Software de interfaz con el usuario El programa de interfaz con el usuario posee dos partes importantes: 4.4.1 La inicialización: Crea algunas variables que se utilizaran dentro del programa y configura el puerto serie para una adecuada comunicación. El puerto serie de la computadora posee un grupo de registros a partir de su dirección base (3F8h para el COM1), y es necesario configurar algunos de ellos para establecer los parámetros de la transmisión y recepción antes de poder utilizar el puerto. 49 La función outportb del lenguaje C, da salida a un byte a través del registro escogido. En el programa en cuestión, PORT1 corresponde a la dirección 3F8h que es el registro de lectura y escritura del puerto serie (COM1); y desplazamientos relativos a esta dirección seleccionan uno de los registros de estado o configuración. En total son siete registros. En el caso de esta aplicación la selección del byte 000Ch para el baud-rate determina una velocidad de transmisión y recepción de 9600 bits por segundo. Este valor debe coincidir con la velocidad de transmisión seleccionada para el MCU. Debido a las características de ambos dispositivos de transmisión serie, no puede configurarse una velocidad de transferencia mayor. Finalmente debe elegirse el modo de trabajo: Codificación, decodificación, visualización de un archivo o salir del programa. 4.4.2 Intercambio de datos: El intercambio de datos se da de manera diferente para codificación y decodificación. En el primer caso, el programa entra en un ciclo que se ejecuta mientras no se haya encontrado el final del archivo. Durante este ciclo, el programa toma del archivo fuente de la codificación el siguiente carácter a enviar, lo escribe en el puerto de salida y luego entra en un ciclo de espera mientras confirma una recepción. En el momento en que esto sucede, se lee el carácter entrante, correspondiente a un uno o un cero que representarán alguno de los bits de la cadena, el cual será inmediatamente escrito en el archivo destino de la codificación. En el 50 momento en que se dejen de recibir los caracteres de la cadena de unos y ceros, el programa solicitará avanzar al siguiente caracter hasta finalizar el proceso. En el caso de la decodificación, de nuevo se entra en un ciclo hasta encontrar el final del archivo. Durante el ciclo, el programa envía un uno o cero desde el archivo fuente de la decodificación (que debería coincidir con el archivo destino de la codificación para un adecuado funcionamiento) y puede recibir dos posibles códigos: Un carácter de control (06h) que indicará que se debe enviar otro caracter pues aún no se ha encontrado una secuencia de bits apropiada dentro de la tabla de decodificación. Cuando se recibe un código diferente de 06h el programa escribe dicho carácter en el archivo destino de la decodificación. Finalmente, en caso de una falla en la comunicación, existe una variable que mide la espera en la recepción de caracteres, por lo que si ésta alcanza un límite fijo preprogramado, la aplicación termina, indicando que hubo un error en la comunicación. La figura 4.1 muestra el diagrama de flujo de dicho programa. Las decisiones son verdaderas hacia la izquierda. El código fuente completo del software de interfaz, puede encontrarse en la sección de anexos. 51 Inicialización ¿Codificar, Decodificar, Abrir archivo, Salir ? NO NO ¿C? NO ¿D? SI NO ¿A? SI SI ¿S? SI FIN Ruta ORIGEN Ruta DESTINO Ruta ORIGEN Ruta DESTINO Ruta ORIGEN ¿Abrió? ¿Abrió? ¿Abrió? SI SI Codificación ORIGEN >>> DESTINO NO NO SI Decodificación ORIGEN >>> DESTINO NO “ORIGEN” Figura 4.1 Diagrama de flujo del programa de interfaz con el usuario 52 4.5 Programa de codificación y decodificación El programa descargado en el MCU consta de cinco secciones: 4.5.1 Definición de las variables y los parámetros de trabajo: se definen todas las constantes, variables, direcciones de memoria y de los registros del puerto serie del MCU, conocido como Interfaz de Comunicación Serie SCI, por sus siglas en inglés; y algunas máscaras de configuración para el SCI. 4.5.2 Inicialización: se configura el SCI para una adecuada comunicación con la computadora que le envía los símbolos. Esta configuración se logra escribiendo las mascaras de configuración sobre los registros apropiados del SCI del MCU. 4.5.3 Lazo principal del programa: El lazo principal del programa se encarga de determinar el trabajo a realizar sobre los datos de entrada, ya sea codificarlos o decodificarlos. En el caso de la codificación, el dispositivo compara el símbolo de entrada contra una serie de símbolos tabulados en orden descendente de probabilidad. Una vez determinado el símbolo de entrada, una subrutina envía la cadena de unos y ceros correspondiente a dicho símbolo, y luego regresa a esperar un nuevo caracter. Para la decodificación el proceso que se lleva a cabo 53 es un tanto diferente, pues al ser las cadenas de unos y ceros de longitud variable, el dispositivo debe retener la secuencia que ha ido recibiendo, por lo que se creó una subrutina de recepción de bits para evitar que el programa no pierda la secuencia de bits previa. Una vez que el programa ha alcanzado el final de una de las ramas del árbol de codificación, envía el caracter correspondiente y regresa a la base del árbol para iniciar nuevamente el proceso. En ambos casos, cuando se recibe el caracter escape (2710, 1Bh) el programa finaliza el proceso y regresa a esperar que se le indique cual tarea realizar. Mientras está realizándose la codificación o decodificación, el dispositivo activa un led, para indicar que se esta en una de estas dos tareas. 4.5.4 Subrutinas: Las subrutinas implementadas son las siguientes: 4.5.4.1 Enviar byte: Se encarga de colocar un byte en el registro de salida de la SCI únicamente cuando éste se encuentre vacío, esto para evitar truncar una transmisión saliente. 4.5.4.2 Enviar cadena: Se encarga de ir moviéndose a lo largo de las cadenas de unos y ceros, enviando uno a uno los caracteres de la cadena llamando a la subrutina Enviar Byte. Esta transmisión termina cuando la subrutina encuentra el byte FFh. 54 4.5.4.3 Esperar bit: Se encarga de recibir los unos y ceros del archivo fuente de la decodificación, además de abandonar la decodificación en caso de recibir el codigo de la función escape. Esta subrutina es llamada en cada paso por una bifurcación del árbol de codificación. 4.5.4.4 Atención a interrupciones del SCI: Esta subrutina es llamada por el MCU cada vez que la bandera de recepción de datos por el SCI se pone en estado alto. Esta bandera pertenece a uno de los registros propios de la SCI y activación se da automáticamente cuando se llena el registro de recepción. La subrutina se encarga de copiar el byte recibido al registro temporal COMANDO ubicado en la memoria RAM para poder accesarlo cuando se salga de la subrutina, además de activar una bandera temporal de recepción llamada PENDIENTE para que el programa principal haga uso del byte guardado en COMANDO. 4.5.5 Tabla: Se creó una tabla con los códigos de longitud variable correspondientes a cada símbolo de entrada del dispositivo, pues al representar la compresión como texto, cada uno y cada cero ocupa un byte en la memoria. De la tabla se hace uso cargando la dirección donde esta el primer “bit” del código, y desplazándose mientras se está enviando del caracter correspondiente hasta que se encuentra la secuencia FFh que indica que ahí finaliza la cadena. Las siguientes figuras muestran el diagrama de flujo del lazo principal dicho programa y de sus subrutinas. Todas las decisiones son verdaderas hacia la izquierda. 55 Inicializaci ón Opción NO SI ¿C? NO ¿D? SI SI Recibe Recibe (esperar bit) SI ¿Recibido = Tabulado? NO ¿Recibido = Escape? Carga X con dirección de cadena Envía carácter codifivado (enviar cadena) SI NO ¿Recibido ≠ Escape? SI Carga X con la dirección de espacio Envío de código espacio para carácter desconocido (Enviar cadena) Envío carácter decodificado (Enviar byte) NO ¿Secuencia = Tabulado? NO Envío carácter de control (Enviar byte) Figura 4.2 Diagrama de flujo del programa de compresión y descompresión 56 NO ¿TDRE = 0? SI Cargar (Transmite) byte en SCDR RTS Figura 4.3 Diagrama de flujo de la subrutina enviar byte ¿Acumulador = FFh? SI NO Cargar (Transmite) byte en SCDR RTS Incrementa índice X (direcciona la cadena) Figura 4.4 Diagrama de flujo de la subrutina enviar cadena 57 NO Cargar PENDIENTE ¿Hay PENDIENTE? SI Cargar COMANDO SI ¿COMANDO = Salir? Redireccionar hacia MENU NO RTS Figura 4.5 Diagrama de flujo de la subrutina esperar bit 58 Carga SCSR Carga SCDR Guarda en COMANDO Carga VERDADERO Guarda en PENDIENTE RTS Figura 4.6 Diagrama de flujo de la subrutina de atención a interrupción de la SCI 59 4.6 Manual de usuario de la aplicación Para utilizar el codificador y decodificador fuente, es necesario contar con el siguiente equipo: • Una computadora con Microsoft® Windows o MS-DOS. • Programa de Terminal si desea usarse dicho modo de operación • Al menos un puerto de comunicación serial. • Un tomacorriente cercano disponible para conectar la fuente de potencia de la tarjeta con el microprocesador 4.6.1 Modos de uso El dispositivo implementado puede utilizarse de cualesquiera dos formas, y esto no afectará su funcionamiento o desempeño, pero si reducirá las opciones. . 4.6.1.1 Modo Terminal: Si se quiere realizar una codificación en tiempo real, o la verificación del código de un símbolo específico, sin necesidad de crear un archivo fuente ni destino, se puede acceder al microprocesador directamente desde un programa de terminal, como MGTEK MiniIDE o la hyperterminal del Windows. Dentro de la terminal, deberá especificarse que tarea se desea realizar, codificación o decodificación, con las teclas “c” o “d”. Para saber si se está dentro del ciclo, se debe observar el estado del led incluido en la tarjeta del MCU y verificar si está 60 encendido o no. Una vez que se determina esto, se pueden introducir los datos directamente desde el teclado y verificar los resultados. 4.6.1.1.1 Configuración: La terminal debe tener los siguientes valores de configuración: 4.6.1.1.2 Baud Rate: 9600 Bps Bits de datos (Data Bits): 8 Bits de parada (Stop Bits): 1 Paridad (Parity): sin paridad Posibles errores: Si no se tuviera respuesta en la pantalla, o los datos presentados no son los correctos, debe verificarse la velocidad de transmisión configurada en la terminal y el puerto COM utilizado, la alimentación de la tarjeta, la conexión y el estado del cable de comunicación. 4.6.1.2 Modo Consola: Cuando se desea realizar la codificación o decodificación de un texto sin preocuparse por introducir su contenido manualmente, debe utilizarse este modo de operación, que implica iniciar la aplicación de interfaz con el usuario CDFuente.exe. En ella, se despliega inicialmente una pantalla con las opciones del menú (ver figura 4.7). En cualquiera de los tres casos, codificar, decodificar o abrir un archivo; debe especificarse la ruta de los archivos con los que se desea trabajar. 61 El formato de la ruta es el siguiente: <unidad de almacenamiento> :\ <directorio 1> \...\ <directorio N> \<nombre_archivo>.txt ; y no debe exceder los 80 caracteres. Si al especificar la ruta solamente se indica el nombre del archivo, dicho archivo tratará de ser abierto por la aplicación desde el mismo directorio en el que se encuentre el archivo ejecutable. Finalmente, aparte de los archivos de tipo TXT, también son compatibles las extensiones .C y .H 4.6.1.2.1 Configuración: Para este modo de operación no se requiere ninguna configuración, esta se hace automáticamente dentro del programa. 4.6.1.2.2 Posibles errores: Existe la posibilidad que al querer realizar alguna de las tareas se presente un error. Si, luego de haber asignado una ruta, el programa devuelva en la pantalla “Problemas con los ficheros”, puede deberse a la ausencia del directorio especificado, a la ausencia del archivo fuente especificado (si el archivo destino no existe, la aplicación lo crea); o a que la ruta especificada excede los ochenta caracteres de longitud, y por 62 tanto se trunca eliminando los caracteres en exceso. En cualquier caso la aplicación regresa al menú principal, asegurándose que si hay algún otro fichero fue abierto, éste sea cerrado apropiadamente. Por otra parte, si la apertura de los archivos es exitosa, pero la computadora no logra comunicarse con el dispositivo, se genera un “Error de comunicación” pues se vence el timeout preprogramado y de nuevo el programa regresa al menú principal, asegurándose que cada fichero abierto, éste sea cerrado apropiadamente. Las razones de este problema son: cable de comunicación está desconectado de la computadora o de la tarjeta, mal conectado a la tarjeta del MCU o cable dañado, el puerto escogido en la computadora no corresponda al COM1, o que la tarjeta del MCU se encuentre apagada o desenergizada del todo. Una vez corregido el problema, o si no se presentó problema alguno, el dispositivo debe funcionar adecuadamente, y tras realizar la tarea especificada devuelve una estadística del nivel de compresión alcanzado. 63 CAPÍTULO 5: Conclusiones y recomendaciones Dichosamente se logró cumplir con todos los objetivos que se plantearon para desarrollar el proyecto. Tanto la investigación realizada, como la aplicación implementada, permiten plantear un proyecto para dar seguimiento a éste. Con esta herramienta se espera que los estudiantes del área de electrónica y telecomunicaciones, así como el público en general, tengan a su disposición una herramienta de sencilla manipulación que permite observar de una manera más clara un proceso de compresión y descompresión. Además, este proyecto también permite asociar la codificación y decodificación fuente con la decodificación de canal, pues se puede manipular externamente el archivo destino de la codificación para simular errores en la transmisión cambiando los bits que se deseen en dicho archivo y observar el resultado que generan estos errores de transmisión a la hora de decodificarlo. Las principales conclusiones obtenidas son: • La teoría de la información permite realizar un análisis cuantitativo de los códigos de longitud fija que pueda conformar algún alfabeto en particular y así poder determinar cual es el máximo de bits por símbolo realmente necesarios en un código (contenido de decisión por símbolo), cuantos bits por símbolo como mínimo son necesarios para transmitir el mensaje (entropía de la fuente) sin perder 64 información y cuanto se “desperdicia” de espacio de almacenamiento o ancho de banda si se guardara o transmitiera el mensaje sin comprimir (redundancia). • Los métodos de compresión de información son un avance muy importante en el mundo del almacenamiento y transmisión de la información, pues permiten un mayor aprovechamiento de los medios de almacenamiento y transmisión de datos, al eliminar todo aquello que por alguna razón es innecesario incluir. • Los métodos de compresión estudiados contemplan solo una parte de la amplia gama que actualmente existe, pues en este trabajo no se tomo en cuenta los métodos de compresión con pérdidas. Sin embargo la robustez de algunos de estos métodos hace que sean la base de implementación en sistemas de compresión de uso frecuente, como lo es la técnica LZW utilizada en archivos de imagen tipo GIF. • Actualmente la codificación Huffman, que se utilizó en el desarrollo de la aplicación de este proyecto, comúnmente es utilizada como un método adicional en algunos compresores. DEFLATE (algoritmo de PKZIP) y codecs multimedia como JPEG y MP3 tienen un modelo principal, una cuantización y luego una codificación Huffman. • Los microcontroladores son dispositivos muy versátiles y permiten implementar una amplia gama de aplicaciones debido a todos los recursos que poseen. En la realización de este proyecto fue indispensable que el microcontrolador contara con 65 la SCI para poder intercambiar datos con la computadora. Además, por esta misma flexibilidad del dispositivo, fácilmente se puede mejorar la aplicación. • Es muy importante hacer un estudio lo suficientemente grande de los símbolos a codificar para que la aproximación de probabilidades por frecuencias relativas sea válida. En este caso, a pesar de que al principio se analizaron textos largos, los resultados eran más consistentes conforme aumentaba el tamaño del texto analizado. Fue necesario además, analizar varios textos para ratificar los resultados obtenidos. • El desempeño de la compresión depende del origen del texto. Como las probabilidades se calcularon a partir de textos estándar, si el texto a codificar posee solo caracteres en mayúscula, o estos representan una gran mayoría de los caracteres, la tasa de compresión puede resultar negativa. Esto se debe a que los códigos Huffman asignados a muchos de estos caracteres poseen más de 8 bits, y al realizar el cálculo de la diferencia de bits intercambiados esta resulta en un número negativo. • La velocidad de los procesos de codificación y decodificación se ve afectada por dos aspectos, primero, por que no puede configurarse una velocidad superior a los 9600 bps debido a la incompatibilidad entre las otras velocidades configurables del puerto serie de la computadora y de la SCI; y segundo por las esperas que deben hacer ambos programas a que los respectivos registros se llenen o se vacíen y que se activen las banderas de estado para realizar las tareas pertinentes. 66 Además como en todo proceso de desarrollo es necesario realizar constantes revisiones para una depuración y mejoramiento de los proyectos. En el caso de la aplicación desarrollada, se puede pensar en aplicar una o varias de las recomendaciones que a continuación se mencionan para así alcanzar un mejor aprovechamiento de la herramienta • Realizar las mejoras necesarias al código fuente de ambos programas para mejorar las velocidades de los procesos de codificación y decodificación. • Buscar la forma de lograr una aplicación modular, en la que también pueda agregarse un codificador y decodificador de canal, de manera que el estudiante pueda observar las dos aplicaciones funcionando conjuntamente. • Implementar otro tipo codificador fuente, siempre para texto en español, de manera que el estudiante pueda comparar el desempeño de los distintos codificadores. • Implementar la función de “aprender” los códigos, de manera que se pueda variar el alfabeto de la fuente de una manera rápida y sencilla, haciendo que el codificador y decodificador funcione con archivos de diferente naturaleza como lo son las imágenes. 67 BIBLIOGRAFÍA Libros: 1. Couch, L.W. “Sistemas de comunicación digitales y analógicos”, 5 edición, Prentice Hall, 1998. 2. Proakis, J.G. “Digital Communications”, 4 edición, McGraw – Hill, 2001. 3. Stremler, F.G. “Sistemas de comunicación”, Alfaomega, México, 1989. Publicaciones 4. Huffman, D.A. “A method for the construction of minimum-redundancy codes” Setiembre, 1952. 5. Shannon, C.E. “A Mathematical Theory of Communication”, October, 1948. 6. Golomb, S.W. “Run-Length Encodings”, en IEEE Transactions on information theory, Julio, 1966. 7. Said, A. “Introduction to Arithmetic Coding - Theory and Practice”, HP Laboratories, 2004 8. Rissanen, J. Langdon, G.G. Jr. “Arithmetic Coding”, IBM Research Division Laboratories, 1979. 9. Martin, G.N.N. “Range encoding, an algorithm for removing redundancy from a digitised message”, IBM UK Scientific Center, 1979. 10. Burrows, M.Wheeler, D.J. “A Block-sorting Lossless Data Compression Algorithm”, Systems Research Center, 1994. 11. Ziv, J. Lempel A. “A Universal Algorithm for Sequential Data Compression”, en IEEE Transactions on information theory, Mayo, 1977. 68 Manuales de Referencia: 12. Freescale Semiconductors, Inc. “M68HC11 Microcontrollers Reference Manual”, Rev. 6.1,2007. 13. Technological Arts. “Using your ADAPT11C24DX starter package”, Canada, 2001. 14. Doblado, C. Gónzalez, J. Prieto-Moreno, A. San Martin, J. “MICROCONTROLADOR 68HC11: Fundamentos, recursos y programación”, Páginas web: 15. “Introducción al microcontrolador MC68HC11”, ttp://lc.fie.umich.mx/~jrincon/cur6811.pdf 16. “Interfacing the Serial / RS232 port” V5.0, http://www.senet.com.au/~cpeacock 17. “Distorsión”, http://cain.eie.fceia.unr.edu.ar/ftp/Comunicaciones/Teor%EDa %20Tasa%20Distorsion.ppt 18. “Tema 7: Cuantificación escalar” http://decsai.ugr.es/ccd/transparencias/07_cuantificacion_escalar_bn2.pdf 19. Material vario sobre codificación y compresión de datos, y compresión de datos, http://decsai.ugr.es/ccd/complementario.html 20. Material vario sobre codificación http://perseo.dif.um.es/~roque/ci/index.html#Apuntes 21. Definiciones varias en es.wikipedia.org 69 APÉNDICES 70 Apéndice A: Códigos fuente de los programas Proba.CPP: Especifica la frecuencia de aparición de un caracter en un texto #include <stdio.h> #include <stdlib.h> #include <dos.h> #include <conio.h> #include <io.h> int main() { char seguir='s'; float caracter,total; FILE *origen; unsigned char temp,letra; char ruta[40]; clrscr(); printf("Ruta del archivo, al terminar presione ENTER: "); fflush(stdin); origen=fopen(gets(ruta),"r"); if(origen==NULL) exit(1); while(seguir=='s') //Este ciclo busca el caracter especificado e imprime su frecuencia relativa de aparición respecto al total de caracteres { caracter=0; total=0; printf("\ncaracter a analizar, al terminar presione ENTER: "); fflush(stdin); scanf("%c",&letra); rewind(origen); while(feof(origen)==0)//Este ciclo asigna los valores para el cálculo de la frecuencia relativa { temp=getc(origen); if(temp==letra) caracter++; total++; } rintf("\nProbabilidad = %f\n",caracter/total); printf("seguir con otro caracter? (s=si)"); fflush(stdin); scanf("%c",&seguir); } return(0); } CDFuente.CPP: Programa de interfaz con el usuario 71 #include <stdio.h> #include <stdlib.h> #include <dos.h> #include <conio.h> #include <io.h> #define PORT1 0x3F8 int main(void) { int c; long timeout; FILE *origen, *destino; unsigned char letra, flush=' ', control; char opcion,ruta_fuente[80], ruta_destino[80]; float char_enviado=0, char_recibido=0,bit_enviado=0,bit_recibido=0,tasa; outportb(PORT1 + 1 , 0); /* Enciende las interrupciones del puerto 1 */ outportb(PORT1 + 3 , 0x80); /* activa el DLAB */ outportb(PORT1 + 0 , 0x0C); /* Configuacion del Baud rate - parte baja del la palabra del Divisor Latch */ outportb(PORT1 + 1 , 0x00); /* parte alta del la palabra del Divisor Latch */ outportb(PORT1 + 3 , 0x03); /* 8 Bits, sin paridad, 1 Bit de parada, configuracion tradicional */ outportb(PORT1 + 2 , 0xC7); /* Registro de control FIFO */ outportb(PORT1 + 4 , 0x0B); /* Enciende DTR, RTS, y OUT2 */ clrscr(); outportb(PORT1,27); flush=inportb(PORT1); menu: char_enviado=0; char_recibido=0;bit_enviado=0;bit_recibido=0,tasa; printf("\n\tUniversidad de Costa Rica\n\tFacultad de Ingenier¡a\n\tEscuela de Ingenieria El‚ctrica\n\tProyecto El‚ctrico IE-0502\n\tCodificador y Decodificador Fuente\n\tLuis Felipe C¢rdoba MoralesA41675\n\tDiciembre 2007"); denuevo: printf("\n\t\n\tQue desea hacer?\n\tC = Codificar\n\tD = Decodificar\n\tA = Abrir y ver un archivo de texto\n\t\n\tS = Salir\n\t\n\tOpcion: "); scanf("%c", &opcion); if(opcion!='a'&&opcion!='A'&&opcion!='c'&&opcion!='C'&&opcion!='d'&&opcion!='D'&&opcion! ='s'&&opcion!='S') { fflush(stdin); goto denuevo; } if(opcion=='c'||opcion=='C') { printf("\n\n\tIndique la ruta del archivo de texto que desea codificar,\n\tal terminar presione ENTER: "); fflush(stdin); origen=fopen(gets(ruta_fuente),"r"); 72 if (origen==NULL) { printf( "\n\tProblemas con la apertura del fichero %s\n",ruta_fuente ); outportb(PORT1,27); printf("\n\n\tPresione cualquier tecla para continuar"); getch(); clrscr(); goto menu; } printf("\n\n\tIndique la ruta del archivo de texto al que desea \n\tescribir la codificación,al terminar presione ENTER:\n\n\t"); fflush(stdin); destino=fopen(gets(ruta_destino),"w"); if (destino==NULL) { printf( "\n\tProblemas con la apertura del fichero %s\n",ruta_destino ); outportb(PORT1,27); printf("\n\n\tPresione cualquier tecla para continuar"); if (fclose(origen)!=0) printf( "Problemas al cerrar el fichero %s\n",ruta_fuente ); getch(); clrscr(); goto menu; } outportb(PORT1,'c'); goto Codificar; } if(opcion=='d'||opcion=='D') { printf("\n\n\tIndique la ruta del archivo de texto que desea decodificar,\n\tal terminar presione ENTER: "); fflush(stdin); origen=fopen(gets(ruta_fuente),"r"); if (origen==NULL) { printf( "\n\tProblemas con la apertura del fichero %s\n",ruta_fuente ); outportb(PORT1,27); printf("\n\n\tPresione cualquier tecla para continuar"); getch(); clrscr(); goto menu; } printf("\n\n\tIndique la ruta del archivo de texto al que desea escribir\n\tla decodificacion,tal terminar presione ENTER:\n\n\t "); fflush(stdin); destino=fopen(gets(ruta_destino),"w"); if (destino==NULL) { printf( "\n\tProblemas con la apertura del fichero %s\n",ruta_destino ); outportb(PORT1,27); if (fclose(origen)!=0) printf( "Problemas al cerrar el fichero %s\n",ruta_fuente ); 73 printf("\n\n\tPresione cualquier tecla para continuar"); getch(); clrscr(); goto menu; } outportb(PORT1,'d'); goto Decodificar; } if(opcion=='a'||opcion=='A') { printf("\n\n\tIndique la ruta del archivo de texto que desea abrir,\n\tal terminar presione ENTER: "); fflush(stdin); origen=fopen(gets(ruta_fuente),"r"); if (origen==NULL) { printf( "Problemas al abrir el fichero %s\n",ruta_fuente ); printf("\n\n\tPresione cualquier tecla para continuar"); getch(); clrscr(); goto menu; } printf("\n\n"); while(feof(origen)==0) { letra=getc(origen); printf("%c",letra); delay(3); } printf("\n\n\n\tPresione cualquier tecla para continuar"); getch(); if (fclose(origen)!=0) { printf( "Problemas con la cerradura del fichero.\n" ); printf("\n\n\tPresione cualquier tecla para continuar"); getch(); clrscr(); goto menu; } clrscr(); goto menu; } if(opcion=='s'||opcion=='S') { goto Fin; } /*ESTA ES LA PARTE DE ENVIO DE CARACTERES Y RECEPCION DE UNOS Y CEROS */ char_enviado=0; char_recibido=0; bit_enviado=0; bit_recibido=0; Codificar: 74 printf("\n\tCodificando..."); letra=getc(origen); timeout=0; while (feof(origen)==0) { Enviar_char: if(inportb(PORT1 + 5)==0x60) { outportb(PORT1,letra); char_enviado++; goto Recibir_char; } flush=inportb(PORT1); goto Enviar_char; Recibir_char: if(inportb(PORT1 + 5)==0x61||inportb(PORT1 + 5)==0x21) { timeout=0; letra=inportb(PORT1); putc(letra,destino); bit_recibido++; RecibirSig_char: if(inportb(PORT1 + 5)==0x61||inportb(PORT1 + 5)==0x21) { timeout=0; letra=inportb(PORT1); putc(letra,destino); bit_recibido++; goto RecibirSig_char; } timeout++; if (timeout==2000000) { printf("\n\n\tERROR DE COMUNICACION!!!\n\n"); outportb(PORT1,27); if (fclose(origen)!=0) printf( "Problemas al cerrar el fichero %s\n",ruta_fuente ); if (fclose(destino)!=0) printf( "Problemas al cerrar el fichero %s\n",ruta_destino ); printf("\n\n\tPresione cualquier tecla para continuar"); getch(); clrscr(); goto menu; } goto Siguiente_char; } timeout++; if (timeout==2000000) { printf("\n\n\tERROR DE COMUNICACION!!!\n\n"); 75 outportb(PORT1,27); if (fclose(origen)!=0) printf( "Problemas al cerrar el fichero %s\n",ruta_fuente ); if (fclose(destino)!=0) printf( "Problemas al cerrar el fichero %s\n",ruta_destino ); printf("\n\n\tPresione cualquier tecla para continuar"); getch(); clrscr(); goto menu; } goto Recibir_char; Siguiente_char: letra=getc(origen); } outportb(PORT1,27); fflush(stdin); if (fclose(origen)!=0) printf( "Problemas al cerrar el fichero origen.txt\n" ); if (fclose(destino)!=0) printf( "Problemas al cerrar el fichero destino.txt\n" ); printf("\n\tCodificacion terminada!"); tasa=(1-(bit_recibido/(char_enviado*8)))*100; printf("\n\n\tSe enviaron %.0f bits de caracteres, se recibieron %.0f bits.\n\tLa tasa de compresion es del %.2f %\n\n",char_enviado*8,bit_recibido,tasa); printf("\n\n\tPresione cualquier tecla para continuar"); getch(); clrscr(); goto menu; /*ESTA ES LA PARTE DE ENVIO DE UNOS Y CEROS Y RECEPCION DE CARACTERES*/ Decodificar: printf("\n\tDecodificando..."); letra=getc(origen); timeout=0; while (feof(origen)==0) { Enviar_bit: if(inportb(PORT1 + 5)==0x60) { outportb(PORT1,letra); bit_enviado++; goto Recibir_bit; } flush=inportb(PORT1); goto Enviar_bit; Recibir_bit: if(inportb(PORT1 + 5)==0x61||inportb(PORT1 + 5)==0x21) { 76 timeout=0; letra=inportb(PORT1); if(letra!=6) { putc(letra,destino); char_recibido++; } goto Siguiente_bit; } timeout++; if (timeout==2000000) { printf("\n\n\tERROR DE COMUNICACION!!!\n\n"); outportb(PORT1,27); if (fclose(origen)!=0) printf( "Problemas al cerrar el fichero %s\n",ruta_fuente ); if (fclose(destino)!=0) printf( "Problemas al cerrar el fichero %s\n",ruta_destino ); printf("\n\n\tPresione cualquier tecla para continuar"); getch(); clrscr(); goto menu; } goto Recibir_bit; Siguiente_bit: letra=getc(origen); } outportb(PORT1,27); fflush(stdin); printf("\n\tDecodificacion terminada!"); tasa=(1-(bit_enviado/(char_recibido*8)))*100; printf("\n\n\tSe enviaron %.0f bits, se recibieron %.0f bits de caracteres.\n\tLa tasa de compresion era del %.2f %\n\n",bit_enviado,char_recibido*8,tasa); if (fclose(origen)!=0) printf( "Problemas al cerrar el fichero origen.txt\n" ); if (fclose(destino)!=0) printf( "Problemas al cerrar el fichero destino.txt\n" ); printf("\n\n\tPresione cualquier tecla para continuar"); getch(); clrscr(); goto menu; Fin: flush=' '; printf("\n%c",flush); return (0); } 77 baud equ rbase+$2b rate control sccr1 equ rbase+$2c register 1 sccr2 equ rbase+$2d register 2 scsr equ rbase+$2e register scdr equ rbase+$2f read (rdr) and write (tdr) CDFuente.ASM: Programa del MCU ; Universidad de Costa Rica ; Facultad de Ingenieria ; Escuela de Ingenieria Electrica ; Proyecto Eléctrico IE-0502 ; Codificador y decodificador fuente ; Luis Felipe Córdoba Morales A41675 ; Diciembre 2007 ;sci baud ;sci control ;sci control ;sci status ;sci data, ; Direcciones del sistema RAM rbase equ $0000 equ $1000 ;Direccion base para los registros STACK equ $00FF ;Direccion inicial de la Pila, en la parte alta de la RAM EEPROM equ $8000 ;Direccion de la memoria EEPROM en Sistemas Adapt11C24DX con 32K EEPROM ; Constantes VERDADERO equ FALSO equ ACK equ arribo de bit y codigo incompleto CODIFICAR equ DECODIFICAR equ SALIR equ Escape CR equ carro LF equ SP equ $FF $00 $06 ;Indicador de $63 ;tecla C $64 ;tecla D $1B ;Código Tecla $D ;retorno de rmb ; Mascaras bdmsk96 equ %00110000 ; (baud) 9600 baud with 8 MHz crystal bdmsk24 equ %00110010 ; (baud) 2400 baud with 8 MHz crystal bdmsk12 equ %00110011 ; (baud) 1200 baud with 8 MHz crystal ptdmsk equ %00000010 ; (ddrd) Direccion de las Entradas del puerto D, excepto TXD sc2msk2 equ %00101100 ; (sccr2)enable tx & rx and Rx Interrupt ********************************** Programa ******************************* $A ;nueva linea $20 ; espacio org EEPROM init ;Direccion (etiqueta) a la que apunta el vector de interrupcion RESET org RAM ; Variables de sistema COMANDO Caracter pprog equ rbase+$3b ;Registro de control de programacion de la EEPROM hprio equ rbase+$3c ;Mayor prioridad de interrupcion sei 1 ;usado por Recibir 1 ;usado lds #STACK puntero de pila ;inicializa el ldaa #ptdmsk ;inicializa el ; Variables Booleanas PENDIENTE rmb ProcessCommand por ; Registros portd equ rbase+$08 communications ddrd equ rbase+$09 register, portd ;portd, ;data serial direction 78 puerto D staa ddrd ldaa #bdmsk96 ;baud=9600 staa baud ldaa #sc2msk2 staa sccr2 ;Habilita el receptor y el transmisor del SCI y las interrupciones de del receptor ldaa scdr buffer del receptor ;Lectura para vaciar el a: clr PENDIENTE clr COMANDO cli interrupciones ;habilita o: ;comandos n: Inicio ldaa PENDIENTE recibidos via interrupción SCI cmpa #VERDADERO bne Inicio MostrarEleccion s: clr PENDIENTE ldaa COMANDO cmpa beq cmpa beq #'C' Codificacion #'c' Codificacion i: cmpa beq cmpa beq #'D' Deco #'d' Deco r: jmp Inicio l: Deco jmp Decodificacion Codificacion ldaa $1000 eora #$40 staa $1000 d: Esperarletra ldaa PENDIENTE ;comandos recibidos via interrupcion del SCI cmpa #VERDADERO bne Esperarletra clr PENDIENTE ldaa COMANDO cmpa #' ' bne e ldx #COD_ESPACIO jsr EnviarCadena jmp Esperarletra e: cmpa #'e' bne a ldx #COD_e jsr EnviarCadena c: t: u: 79 jmp Esperarletra cmpa #'a' bne o ldx #COD_a jsr EnviarCadena jmp Esperarletra cmpa #'o' bne n ldx #COD_o jsr EnviarCadena jmp Esperarletra cmpa #'n' bne s ldx #COD_n jsr EnviarCadena jmp Esperarletra cmpa #'s' bne i ldx #COD_s jsr EnviarCadena jmp Esperarletra cmpa #'i' bne r ldx #COD_i jsr EnviarCadena jmp Esperarletra cmpa #'r' bne l ldx #COD_r jsr EnviarCadena jmp Esperarletra cmpa #'l' bne d ldx #COD_l jsr EnviarCadena jmp Esperarletra cmpa #'d' bne c ldx #COD_d jsr EnviarCadena jmp Esperarletra cmpa #'c' bne t ldx #COD_c jsr EnviarCadena jmp Esperarletra cmpa #'t' bne u ldx #COD_t jsr EnviarCadena jmp Esperarletra cmpa #'u' bne m ldx #COD_u jsr EnviarCadena jmp Esperarletra m: cmpa #'m' bne p ldx #COD_m jsr EnviarCadena jmp Esperarletra p: cmpa #'p' bne coma ldx #COD_p jsr EnviarCadena jmp Esperarletra coma: cmpa #',' bne b ldx #COD_coma jsr EnviarCadena jmp Esperarletra b: cmpa #'b' bne g ldx #COD_b jsr EnviarCadena jmp Esperarletra g: cmpa #'g' bne v ldx #COD_g jsr EnviarCadena jmp Esperarletra v: cmpa #'v' bne q ldx #COD_v jsr EnviarCadena jmp Esperarletra q: cmpa #'q' bne ye ldx #COD_q jsr EnviarCadena jmp Esperarletra ye: cmpa #'y' bne punto ldx #COD_y jsr EnviarCadena jmp Esperarletra punto cmpa #'.' bne f ldx #COD_punto jsr EnviarCadena jmp Esperarletra f: cmpa #'f' bne otil ldx #COD_f jsr EnviarCadena jmp Esperarletra otil: cmpa #'ó' bne h ldx #COD_otil jsr EnviarCadena jmp Esperarletra h: cmpa #'h' bne itil ldx #COD_h jsr EnviarCadena jmp Esperarletra itil: cmpa #'í' bne comillas ldx #COD_itil jsr EnviarCadena jmp Esperarletra comillas cmpa #'”' bne atil ldx #COD_comillas jsr EnviarCadena jmp Esperarletra atil cmpa #'á' bne j ldx #COD_atil jsr EnviarCadena jmp Esperarletra j: cmpa #'j' bne z ldx #COD_j jsr EnviarCadena jmp Esperarletra z: cmpa #'z' bne emay ldx #COD_z jsr EnviarCadena jmp Esperarletra emay: cmpa #'E' bne etil ldx #COD_emay jsr EnviarCadena jmp Esperarletra etil: cmpa #'é' bne ex ldx #COD_etil jsr EnviarCadena jmp Esperarletra ex: cmpa #'x' bne n2 ldx #COD_x jsr EnviarCadena jmp Esperarletra n2: cmpa #'ñ' bne lmay ldx #COD_n2 jsr EnviarCadena jmp Esperarletra lmay: cmpa #'L' bne NL_LF1 ldx #COD_lmay jsr EnviarCadena jmp Esperarletra NL_LF1: 80 cmpa #10 bne tabular ldx #COD_NL_LF jsr EnviarCadena jmp Esperarletra tabular: cmpa #9 bne smay ldx #COD_tabular jsr EnviarCadena jmp Esperarletra smay: cmpa #'S' bne mmay ldx #COD_smay jsr EnviarCadena jmp Esperarletra mmay cmpa #'M' bne util ldx #COD_mmay jsr EnviarCadena jmp Esperarletra util: cmpa #'ú' bne uno ldx #COD_util jsr EnviarCadena jmp Esperarletra uno: cmpa #'1' bne pmay ldx #COD_uno jsr EnviarCadena jmp Esperarletra pmay: cmpa #'P' bne dospuntos ldx #COD_pmay jsr EnviarCadena jmp Esperarletra dospuntos: cmpa #':' bne cmay ldx #COD_dospuntos jsr EnviarCadena jmp Esperarletra cmay: cmpa #'C' bne amay ldx #COD_cmay jsr EnviarCadena jmp Esperarletra amay cmpa #'A' bne cero ldx #COD_amay jsr EnviarCadena jmp Esperarletra cero cmpa #'0' bne nmay ldx #COD_cero jsr EnviarCadena jmp Esperarletra nmay cmpa #'N' bne nueve ldx #COD_nmay jsr EnviarCadena jmp Esperarletra nueve: cmpa #'9' bne menos ldx #COD_nueve jsr EnviarCadena jmp Esperarletra menos: cmpa #'-' bne bmay ldx #COD_menos jsr EnviarCadena jmp Esperarletra bmay: cmpa #'B' bne tmay ldx #COD_bmay jsr EnviarCadena jmp Esperarletra tmay: cmpa #'T' bne dos ldx #COD_tmay jsr EnviarCadena jmp Esperarletra dos: cmpa #'2' bne puntoycoma ldx #COD_dos jsr EnviarCadena jmp Esperarletra puntoycoma: cmpa #';' bne w ldx #COD_puntoycoma jsr EnviarCadena jmp Esperarletra w: cmpa #'w' bne dmay ldx #COD_w jsr EnviarCadena jmp Esperarletra dmay: cmpa #'D' bne hmay ldx #COD_dmay jsr EnviarCadena jmp Esperarletra hmay: cmpa #'H' bne imay ldx #COD_hmay jsr EnviarCadena jmp Esperarletra imay: cmpa #'I' bne omay ldx #COD_imay jsr EnviarCadena jmp Esperarletra omay: cmpa #'O' bne cinco ldx #COD_omay 81 jsr EnviarCadena jmp Esperarletra cinco: cmpa #'5' bne gmay ldx #COD_cinco jsr EnviarCadena jmp Esperarletra gmay: cmpa #'G' bne umay ldx #COD_gmay jsr EnviarCadena jmp Esperarletra umay: cmpa #'U' bne k ldx #COD_umay jsr EnviarCadena jmp Esperarletra k: cmpa #'k' bne rmay ldx #COD_k jsr EnviarCadena jmp Esperarletra rmay: cmpa #'R' bne ymay ldx #COD_rmay jsr EnviarCadena jmp Esperarletra ymay: cmpa #'Y' bne pregcierra ldx #COD_ymay jsr EnviarCadena jmp Esperarletra pregcierra: cmpa #'?' bne pregabre ldx #COD_pregcierra jsr EnviarCadena jmp Esperarletra pregabre cmpa #'¿' bne seis ldx #COD_pregabre jsr EnviarCadena jmp Esperarletra seis: cmpa #'6' bne fmay ldx #COD_seis jsr EnviarCadena jmp Esperarletra fmay: cmpa #'F' bne siete ldx #COD_fmay jsr EnviarCadena jmp Esperarletra siete: cmpa #'7' bne ocho ldx #COD_siete jsr EnviarCadena jmp Esperarletra cmpa #'8' bne tres ldx #COD_ocho jsr EnviarCadena jmp Esperarletra tres: cmpa #'3' bne slash ldx #COD_tres jsr EnviarCadena jmp Esperarletra slash: cmpa #'/' bne vmay ldx #COD_slash jsr EnviarCadena jmp Esperarletra vmay: cmpa #'V' bne wmay ldx #COD_vmay jsr EnviarCadena jmp Esperarletra wmay: cmpa #'W' bne xmay ldx #COD_wmay jsr EnviarCadena jmp Esperarletra xmay: cmpa #'X' bne backslash ldx #COD_xmay jsr EnviarCadena jmp Esperarletra backslash: cmpa #'\' bne imaytil ldx #COD_backslash jsr EnviarCadena jmp Esperarletra imaytil: cmpa #'Í' bne omaytil ldx #COD_imaytil jsr EnviarCadena jmp Esperarletra omaytil: cmpa #'Ó' bne umaytil ldx #COD_omaytil jsr EnviarCadena jmp Esperarletra umaytil: cmpa #'Ú' bne n2may ldx #COD_umaytil jsr EnviarCadena jmp Esperarletra n2may: cmpa #'Ñ' bne udir ldx #COD_n2may jsr EnviarCadena jmp Esperarletra ocho: 82 udir: cmpa #'ü' bne udirmay ldx #COD_udir jsr EnviarCadena jmp Esperarletra udirmay: cmpa #'Ü' bne admirabre ldx #COD_udirmay jsr EnviarCadena jmp Esperarletra admirabre: cmpa #'¡' bne admircierra ldx #COD_admirabre jsr EnviarCadena jmp Esperarletra admircierra: cmpa #'!' bne igual ldx #COD_admircierra jsr EnviarCadena jmp Esperarletra igual: cmpa #'=' bne mas ldx #COD_igual jsr EnviarCadena jmp Esperarletra mas: cmpa #'+' bne asterisco ldx #COD_mas jsr EnviarCadena jmp Esperarletra asterisco: cmpa #'*' bne menor ldx #COD_asterisco jsr EnviarCadena jmp Esperarletra menor: cmpa #'<' bne mayor ldx #COD_menor jsr EnviarCadena jmp Esperarletra mayor: cmpa #'>' bne numero ldx #COD_mayor jsr EnviarCadena jmp Esperarletra numero: cmpa #'#' bne parabre ldx #COD_numero jsr EnviarCadena jmp Esperarletra parabre: cmpa #'(' bne parcierra ldx #COD_parabre jsr EnviarCadena jmp Esperarletra parcierra: cmpa #')' bne corcheteabre ldx #COD_parcierra jsr EnviarCadena jmp Esperarletra corcheteabre: cmpa #'[' bne corchetecierra ldx #COD_corcheteabre jsr EnviarCadena jmp Esperarletra corchetecierra: cmpa #']' bne porcentaje ldx #COD_corchetecierra jsr EnviarCadena jmp Esperarletra porcentaje: cmpa #'%' bne dolar ldx #COD_porcentaje jsr EnviarCadena jmp Esperarletra dolar: cmpa #'$' bne arroba ldx #COD_dolar jsr EnviarCadena jmp Esperarletra arroba: cmpa #'@' bne subraya ldx #COD_arroba jsr EnviarCadena jmp Esperarletra subraya: cmpa #'_' bne andpers ldx #COD_subraya jsr EnviarCadena jmp Esperarletra andpers: cmpa #'&' bne virgulilla ldx #COD_and jsr EnviarCadena jmp Esperarletra virgulilla: cmpa #'~' bne qmay ldx #COD_virgulilla jsr EnviarCadena jmp Esperarletra qmay: cmpa #'Q' bne zmay ldx #COD_qmay jsr EnviarCadena jmp Esperarletra zmay: cmpa #'Z' bne jmay ldx #COD_zmay jsr EnviarCadena jmp Esperarletra jmay: cmpa #'J' bne cuatro 83 cuatro: amaytil kmay: emaytil: comilla ldx #COD_jmay jsr EnviarCadena jmp Esperarletra cmpa #'4' bne amaytil ldx #COD_cuatro jsr EnviarCadena jmp Esperarletra cmpa #'Á' bne kmay ldx #COD_amaytil jsr EnviarCadena jmp Esperarletra cmpa #'K' bne emaytil ldx #COD_kmay jsr EnviarCadena jmp Esperarletra cmpa #'É' bne comilla ldx #COD_emaytil jsr EnviarCadena jmp Esperarletra cmpa #"'" bne SALIDA ldx #COD_comilla jsr EnviarCadena jmp Esperarletra SALIDA bne PrimerBit jsr Esperarbit cmpa #'1' bne c0 jmp c1 c0: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c00 jmp c01 c00: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c000 jmp c001 c000: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c0000 jmp c0001 c0000: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c00000 jmp c00001 c00000: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c000000 jmp c000001 c000000: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c0000000 jmp c0000001 c0000000: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c00000000 jmp c00000001 c00000000: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c000000000 jmp c000000001 cmpa #SALIR Esperarletra2 PCX1 ldaa $1000 eora #$40 staa $1000 jmp Inicio Esperarletra2 ldx #COD_ESPACIO jsr EnviarCadena jmp Esperarletra ; ******************************************** * ; DECODIFICACION ; ******************************************** * Decodificacion ldaa $1000 eora #$40 staa $1000 84 c000000000: ldaa #13 jsr EnviarByte ldaa #10 jsr EnviarByte jmp PrimerBit c1: cmpa #'1' bne c0010 ldaa #'r' jsr EnviarByte jmp PrimerBit c0010: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' beq c00101 ldaa #'m' jsr EnviarByte jmp PrimerBit c00101: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c001010 jmp c001011 c001010: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c0010100 ldaa #'.' jsr EnviarByte jmp PrimerBit c0010100: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'0' bne c00101001 ldaa #'"' jsr EnviarByte jmp PrimerBit ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c10 jmp c11 c10: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c100 jmp c101 c100: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c1000 ldaa #'o' jsr EnviarByte jmp PrimerBit c1000: ldaa #'n' jsr EnviarByte jmp PrimerBit c01: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c010 jmp c011 c010: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c0100 ldaa #'s' jsr EnviarByte jmp PrimerBit c0100: ldaa #'i' jsr EnviarByte jmp PrimerBit c001: c00101001: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c001010010 jmp c001010011 c001010010: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c0010100100 ldaa #'P' jsr EnviarByte jmp PrimerBit c0010100100: ldaa #':' jsr EnviarByte jmp PrimerBit ldaa #ACK jsr EnviarByte jsr Esperarbit c001010011: ldaa #ACK jsr EnviarByte 85 jsr Esperarbit cmpa #'1' bne c0010100110 jmp c0010100111 c0010100110: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c00101001100 ldaa #'w' jsr EnviarByte jmp PrimerBit c00101001100: ldaa #'D' jsr EnviarByte jmp PrimerBit jsr EnviarByte jsr Esperarbit cmpa #'1' bne c0000000010 ldaa #'0' jsr EnviarByte jmp PrimerBit c0000000010: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c00000000100 ldaa #'5' jsr EnviarByte jmp PrimerBit c0001: ldaa #'l' jsr EnviarByte jmp PrimerBit c00001: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c000010 jmp c000011 c00000000100: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' beq c000000001001 ldaa #'V' jsr EnviarByte jmp PrimerBit c000000001001: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c0000000010010 ldaa #'J' jsr EnviarByte jmp PrimerBit c0000000010010: ldaa #'4' jsr EnviarByte jmp PrimerBit c000010: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c0000100 ldaa #'ó' jsr EnviarByte jmp PrimerBit c0000100: ldaa #'h' jsr EnviarByte jmp PrimerBit c000001: ldaa #',' jsr EnviarByte jmp PrimerBit c0000001: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c00000010 ldaa #'á' jsr EnviarByte jmp PrimerBit c00000010: ldaa #'j' jsr EnviarByte jmp PrimerBit c00000001: ldaa #'z' jsr EnviarByte jmp PrimerBit c000000001: c011: ldaa #'e' jsr EnviarByte jmp PrimerBit c000011: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c0000110 ldaa #'f' jsr EnviarByte jmp PrimerBit c0000110: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c00001100 jmp c00001101 c00001100: ldaa #ACK jsr EnviarByte ldaa #ACK 86 jsr Esperarbit cmpa #'1' bne c000011000 ldaa #'L' jsr EnviarByte jmp PrimerBit c000011000: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c0000110000 ldaa #'A' jsr EnviarByte jmp PrimerBit c0000110000: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'0' bne c00001100001 ldaa #'O' jsr EnviarByte jmp PrimerBit c00001100001: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c000011000010 ldaa #'3' jsr EnviarByte jmp PrimerBit c000011000010: ldaa #'/' jsr EnviarByte jmp PrimerBit jsr EnviarByte jmp PrimerBit c00001101000: ldaa #'I' jsr EnviarByte jmp PrimerBit c001011: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c0010110 ldaa #'y' jsr EnviarByte jmp PrimerBit c0010110: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'0' bne c00101101 ldaa #'í' jsr EnviarByte jmp PrimerBit c00101101: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c001011010 jmp c001011011 c001011010: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'0' bne c0010110101 ldaa #'1' jsr EnviarByte jmp PrimerBit c00001101: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c000011010 ldaa #'ñ' jsr EnviarByte jmp PrimerBit c000011010: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c0000110100 ldaa #'C' jsr EnviarByte jmp PrimerBit c0000110100: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c00001101000 ldaa #'H' c0010110101: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c00101101010 ldaa #'2' jsr EnviarByte jmp PrimerBit c00101101010: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'0' bne c001011010101 ldaa #'F' jsr EnviarByte jmp PrimerBit c001011010101: ldaa #ACK 87 jsr EnviarByte jsr Esperarbit cmpa #'1' bne c0010110101010 ldaa #'Z' jsr EnviarByte jmp PrimerBit c0010110101010: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'0' bne c00101101010101 ldaa #'Á' jsr EnviarByte jmp PrimerBit c00101101010101: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c001011010101010 ldaa #'K' jsr EnviarByte jmp PrimerBit c001011010101010: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c0010110101010100 ldaa #'É' jsr EnviarByte jmp PrimerBit c0010110101010100: ldaa #"'" jsr EnviarByte jmp PrimerBit c0010100111: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c00101001110 ldaa #';' jsr EnviarByte jmp PrimerBit jsr EnviarByte jsr Esperarbit cmpa #'1' bne c0010110110 ldaa #'ú' jsr EnviarByte jmp PrimerBit c0010110110: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c00101101100 ldaa #'B' jsr EnviarByte jmp PrimerBit c00101101100: ldaa #'T' jsr EnviarByte jmp PrimerBit c11: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'0' bne c111 ldaa #' ' jsr EnviarByte jmp PrimerBit c111: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c1110 ldaa #'a' jsr EnviarByte jmp PrimerBit c1110: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c11100 ldaa #'d' jsr EnviarByte jmp PrimerBit c11100: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c111000 ldaa #'p' jsr EnviarByte jmp PrimerBit c111000: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c1110000 ldaa #'b' c00101001110: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c001010011100 ldaa #'7' jsr EnviarByte jmp PrimerBit c001010011100: ldaa #'8' jsr EnviarByte jmp PrimerBit c001011011: ldaa #ACK 88 jsr EnviarByte jmp PrimerBit c1110000: ldaa #'g' jsr EnviarByte jmp PrimerBit bne c101010001 ldaa #'x' jsr EnviarByte jmp PrimerBit c101010001: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c1010100010 jmp c1010100011 c1010100010: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'0' bne c10101000101 ldaa #'-' jsr EnviarByte jmp PrimerBit c10101000101: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c101010001010 ldaa #'¿' jsr EnviarByte jmp PrimerBit c101010001010: ldaa #'6' jsr EnviarByte jmp PrimerBit c1010100011: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c10101000110 jmp c10101000111 c10101000110: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c101010001100 ldaa #'k' jsr EnviarByte jmp PrimerBit c101010001100: ldaa #'R' jsr EnviarByte jmp PrimerBit c101: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'0' bne c1011 jmp c1010 c1011: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c10110 ldaa #'c' jsr EnviarByte jmp PrimerBit c10110: ldaa #'t' jsr EnviarByte jmp PrimerBit c1010: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'0' bne c10101 ldaa #'u' jsr EnviarByte jmp PrimerBit c10101: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c101010 jmp c101011 c101010: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c1010100 ldaa #'q' jsr EnviarByte jmp PrimerBit c1010100: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c10101000 jmp c10101001 c10101000: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'0' c10101000111: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c101010001110 ldaa #'Y' jsr EnviarByte jmp PrimerBit c101010001110: ldaa #'?' 89 jsr EnviarByte jmp PrimerBit c1010110: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'0' bne c10101101 jmp c10101100 c10101101: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c101011010 ldaa #'E' jsr EnviarByte jmp PrimerBit c101011010: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'0' bne c1010110101 ldaa #9 jsr EnviarByte jmp PrimerBit c1010110101: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c10101101010 ldaa #'N' jsr EnviarByte jmp PrimerBit c10101101010: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c101011010100 ldaa #'G' jsr EnviarByte jmp PrimerBit c101011010100: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c1010110101000 ldaa #'W' jsr EnviarByte jmp PrimerBit c1010110101000: ldaa #'X' jsr EnviarByte jmp PrimerBit c10101100: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c101011000 jmp c101011001 c101011000: ldaa #ACK c10101001: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'0' bne c101010011 ldaa #'é' jsr EnviarByte jmp PrimerBit c101010011: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'0' bne c1010100111 ldaa #'M' jsr EnviarByte jmp PrimerBit c1010100111: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c10101001110 ldaa #'9' jsr EnviarByte jmp PrimerBit c10101001110: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'0' bne c101010011101 ldaa #'U' jsr EnviarByte jmp PrimerBit c101010011101: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c1010100111010 ldaa #'~' jsr EnviarByte jmp PrimerBit c1010100111010: ldaa #'Q' jsr EnviarByte jmp PrimerBit c101011: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c1010110 ldaa #'v' jsr EnviarByte jmp PrimerBit 90 jsr EnviarByte jsr Esperarbit cmpa #'0' bne c1010110001 ldaa #'S' jsr EnviarByte jmp PrimerBit c1010110001: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c10101100010 jmp c10101100011 c10101100010: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c101011000100 jmp c101011000101 c101011000100: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c1010110001000 ldaa #')' jsr EnviarByte jmp PrimerBit c1010110001000: ldaa #'[' jsr EnviarByte jmp PrimerBit c10101100011: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c101011000110 jmp c101011000111 c101011000110: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c1010110001100 ldaa #'$' jsr EnviarByte jmp PrimerBit c1010110001100: ldaa #'@' jsr EnviarByte jmp PrimerBit c1010110001010: ldaa #'%' jsr EnviarByte jmp PrimerBit c101011000111: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c1010110001110 ldaa #'_' jsr EnviarByte jmp PrimerBit c1010110001110: ldaa #'&' jsr EnviarByte jmp PrimerBit c101011001: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c1010110010 jmp c1010110011 c1010110010: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c10101100100 jmp c10101100101 c10101100100: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c101011001000 jmp c101011001001 c101011001000: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c1010110010000 ldaa #'\' jsr EnviarByte jmp PrimerBit c1010110010000: ldaa #'Í' jsr EnviarByte jmp PrimerBit c101011001001: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c1010110010010 ldaa #'Ó' jsr EnviarByte jmp PrimerBit c1010110010010: ldaa #'Ú' jsr EnviarByte jmp PrimerBit c101011000101: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c1010110001010 ldaa #']' jsr EnviarByte jmp PrimerBit 91 c10101100101: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c101011001010 jmp c101011001011 jsr EnviarByte jsr Esperarbit cmpa #'1' bne c1010110011010 ldaa #'+' jsr EnviarByte jmp PrimerBit c1010110011010: ldaa #'*' jsr EnviarByte jmp PrimerBit c101011001010: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c1010110010100 ldaa #'Ñ' jsr EnviarByte jmp PrimerBit c1010110010100: ldaa #'ü' jsr EnviarByte jmp PrimerBit c10101100111: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c101011001110 jmp c101011001111 c101011001110: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c1010110011100 ldaa #'<' jsr EnviarByte jmp PrimerBit c1010110011100: ldaa #'>' jsr EnviarByte jmp PrimerBit c101011001011: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c1010110010110 ldaa #'Ü' jsr EnviarByte jmp PrimerBit c1010110010110: ldaa #'i' jsr EnviarByte jmp PrimerBit c101011001111: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c1010110011110 ldaa #'#' jsr EnviarByte jmp PrimerBit c1010110011110: ldaa #'(' jsr EnviarByte jmp PrimerBit c1010110011: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c10101100110 jmp c10101100111 c10101100110: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c101011001100 jmp c101011001101 c101011001100: ldaa #ACK jsr EnviarByte jsr Esperarbit cmpa #'1' bne c1010110011000 ldaa #'!' jsr EnviarByte jmp PrimerBit c1010110011000: ldaa #'=' jsr EnviarByte jmp PrimerBit ;*********Procedimientos********* EnviarByte ; Transmite un byte, contenido en el registro A, al PC via el SCI. SB1 ldab scsr;espera que el registro de transmision de datos esté vacio empty (TDRE) bpl SB1 staa scdr ;envia byte rts EnviarCadena ;X contiene la direccion inicial de la cadena c101011001101: ldaa #ACK 92 RV1 COD_d fcc '11101' fcb $ff cmpa #$FF beq RVX jsr EnviarByte inx jmp RV1 COD_c fcc '10111' fcb $ff COD_t fcc '10110' fcb $ff rts COD_u fcc '10100' fcb $ff COD_m fcc '00100' fcb $ff COD_p fcc '111001' fcb $ff ldaa 0,X ;$FF denota el final de la cadena RVX Esperarbit ldaa PENDIENTE ;commands received via SCI interrupt cmpa #VERDADERO bne Esperarbit clr PENDIENTE ldaa COMANDO COD_coma '000001' cmpa #SALIR bne Retornar ldaa $1000 eora #$40 staa $1000 pula pula ldx #Inicio pshx fcc fcb Retornar COD_b fcc '1110001' fcb $ff COD_g fcc '1110000' fcb $ff COD_v fcc '1010111' fcb $ff COD_q fcc '1010101' fcb $ff COD_y fcc '0010111' fcb $ff rts ;*********** Tabla de Codificacion ********* COD_ESPACIO fcc COD_e fcc COD_a fcc COD_o COD_n COD_s fcc fcc fcc '110' fcb '011' fcb '1111' fcb '1001' fcb '1000' fcb '0101' fcb $ff $ff COD_punto '0010101' $ff fcc fcb COD_r COD_l fcc fcc fcc $ff $ff COD_f fcc $ff COD_otil '0000101' $ff '0000111' fcb $ff fcc fcb COD_i $ff '0100' fcb $ff COD_h '0011' fcb $ff COD_itil '00101100' '0001' fcb $ff fcc '0000100' fcb $ff fcc fcb 93 $ff $ff COD_comillas '10101000' fcc fcb COD_pmay '0010100101' $ff fcc fcb COD_atil '00000011' fcb COD_dospuntos '0010100100' $ff fcc fcb COD_j COD_z fcc fcc COD_emay '101011011' '00000010' fcb $ff COD_smay '1010110000' COD_util '0010110111' fcb COD_menos '10101000100' fcb COD_bmay '00101101101' fcb COD_tmay '00101101100' $ff fcc $ff fcb COD_dos '00101101011' $ff fcc $ff fcb COD_puntoycoma '00101001111' $ff fcc $ff COD_w $ff fcc $ff fcc $ff fcc $ff fcc $ff fcc $ff fcc fcb $ff fcb $ff fcc '00101001101' fcb COD_uno '0010110100' COD_nueve '10101001111' fcc fcb $ff fcc fcb fcc fcb COD_mmay '1010100110' fcc COD_nmay '10101101011' fcc fcb $ff $ff fcc fcb COD_tabular '1010110100' COD_cero '0000000011' '101010000' fcb $ff fcb COD_NL_LF '000000000' fcc fcb fcc $ff $ff fcc fcb COD_lmay '000011001' COD_amay '0000110001' fcb fcb $ff fcc fcb fcc COD_etil '101010010' COD_n2 '000011011' COD_cmay '0000110101' '00000001' fcb $ff fcb COD_x $ff fcc $ff fcc fcb COD_dmay '00101001100' $ff fcc fcb 94 $ff COD_hmay '00001101001' COD_imay '00001101000' fcc COD_xmay '1010110101000' fcc COD_backslash '1010110010001' COD_imaytil '1010110010000' $ff COD_omaytil '1010110010011' $ff $ff COD_n2may '1010110010101' $ff fcb COD_udir '1010110010100' $ff fcb COD_udirmay '1010110010111' $ff fcb COD_admirabre '1010110010110' $ff $ff fcc fcb 95 $ff fcc fcb fcc $ff fcc fcb fcc $ff fcc fcb fcc $ff fcc fcb fcc $ff fcc fcb COD_umaytil '1010110010010' $ff fcc fcb fcc fcb fcc fcb fcc fcb $ff $ff fcc fcb $ff $ff '101010001101' fcb $ff fcb COD_siete '001010011101' COD_wmay '1010110101001' fcb fcc $ff $ff fcc fcb $ff fcc fcb COD_umay '101010011100' COD_fmay '001011010100' COD_vmay '000000001000' fcc fcb COD_seis '101010001010' fcc fcb COD_gmay '101011010101' $ff $ff fcc fcb COD_pregabre '101010001011' COD_slash '000011000010' fcb COD_cinco '00000000101' COD_pregcierra '101010001110' fcc $ff fcc fcb COD_ymay '101010001111' COD_tres '000011000011' fcb COD_omay '00001100000' $ff $ff fcc fcb COD_rmay '101010001100' fcc fcb fcb COD_k COD_ocho '001010011100' fcc $ff COD_admircierra '1010110011001' fcc fcb COD_igual '1010110011000' COD_menor '1010110011101' COD_corcheteabre '1010110001000' COD_zmay '0010110101011' $ff $ff $ff $ff $ff COD_corchetecierra '1010110001011' $ff fcb COD_comilla '0010110101010100' $ff fcb ;**********Rutina de interrupciones*********** atencion $ff fcc fcb a ; SCI Input Interrupt Handler ; Recibe bytes del SCI. Activa la bandera COMANDO_PENDIENTE. SerInputInt COD_arroba '1010110001100' $ff $ff fcc fcb $ff fcc fcb fcc $ff fcc fcb fcc $ff fcc fcb COD_emaytil '0010110101010101' $ff fcc fcb COD_kmay '001011010101011' $ff fcc fcb COD_amaytil '00101101010100' $ff fcc fcb COD_cuatro '0000000010010' $ff fcc fcb COD_jmay '0000000010011' $ff fcc fcb fcc fcb COD_dolar '1010110001101' $ff fcc fcb COD_porcentaje '1010110001010' COD_qmay '1010100111010' $ff fcc fcb fcc fcb COD_parcierra '1010110001001' $ff fcc fcb COD_parabre '1010110011110' COD_virgulilla '1010100111011' $ff fcc fcb fcc fcb COD_numero '1010110011111' $ff fcc fcb COD_mayor '1010110011100' COD_and '1010110001110' fcc fcb fcc fcb fcc fcb COD_asterisco '1010110011010' $ff fcc fcb COD_mas '1010110011011' COD_subraya '1010110001111' $ff ldaa scsr ldaa scdr RDRF 96 ;limpia staa ldaa staa rti COMANDO #VERDADERO PENDIENTE ;********* Vector de reset****************** org FDB Interrupcion y $FFD6 SerInputInt ;vector SCI org $FFFE FDB init ;vector reset 97 ANEXOS 98