TETRIS: UN ROMPECABEZAS BASADO EN EL MCF5272
Transcripción
TETRIS: UN ROMPECABEZAS BASADO EN EL MCF5272
Departamento de Ingeniería Electrónica E.T.S.I. de Telecomunicación Universidad Politécnica de Madrid Laboratorio de Sistemas Electrónicos Digitales Enunciado de la práctica estándar del Laboratorio de Sistemas Electrónicos Digitales (LSED) Coldtrix: un rompecabezas basado en el MCF5272 Plan 94. Curso 2009-2010. Versión 1.1 Autores: Fernando Fernández Martínez Juan Manuel Montero Martínez Rubén San-Segundo Hernández Luis Fernando D’Haro Enríquez Juan Manuel Lucas Cuesta Ricardo de Córdoba Herralde COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 ÍNDICE GENERAL 1. INTRODUCCIÓN ............................................................................................................................................ 5 1.1 2. AVISO INICIAL .................................................................................................................................................. 6 ESPECIFICACIÓN DE REQUISITOS DEL SISTEMA ............................................................................................. 6 2.1 ANTECEDENTES ............................................................................................................................................... 6 2.2 OBJETIVO GENERAL .......................................................................................................................................... 8 2.2.1 Casos de uso ......................................................................................................................................... 11 3. SUBSISTEMA HARDWARE ............................................................................................................................13 3.1 3.2 3.3 3.4 3.5 3.6 MATRIZ DE LEDS ............................................................................................................................................ 13 FILTRADO DE LA SEÑAL .................................................................................................................................... 14 AMPLIFICADOR DE POTENCIA ............................................................................................................................ 15 CASCOS O AURICULARES .................................................................................................................................. 16 OBSERVACIONES ADICIONALES SOBRE EL HW DE ENTRADA/SALIDA .......................................................................... 16 ALIMENTACIÓN DE LOS SUBSISTEMAS ................................................................................................................. 16 4. SUBSISTEMA DIGITAL BASADO EN EL MCF5272 ...........................................................................................16 5. SUBSISTEMA SOFTWARE..............................................................................................................................17 5.1 MODELO DE REQUISITOS DE SW ....................................................................................................................... 17 5.2 MODELO DE OBJETOS ORIENTATIVO ................................................................................................................... 17 5.2.1 Tecla ..................................................................................................................................................... 17 5.2.2 Estado................................................................................................................................................... 18 5.2.3 Piezas ................................................................................................................................................... 18 5.2.4 Juego .................................................................................................................................................... 19 5.2.5 Leds ...................................................................................................................................................... 20 5.2.6 Relojes .................................................................................................................................................. 21 5.2.7 Melodía ................................................................................................................................................ 21 5.2.8 Resultados ............................................................................................................................................ 22 5.2.9 Pantalla ................................................................................................................................................ 22 5.2.10 Puerto .............................................................................................................................................. 23 5.2.11 Rutinas o métodos generales de los objetos de un sistema ............................................................ 23 5.3 MODELO DE DISEÑO ....................................................................................................................................... 23 5.3.1 Arquitectura del sistema SW ................................................................................................................ 23 5.3.2 Modelo dinámico orientativo ............................................................................................................... 24 5.3.3 Estructura obligatoria de procesos ...................................................................................................... 33 5.4 MODELO DE IMPLEMENTACIÓN ORIENTATIVO ...................................................................................................... 37 5.4.1 Codificación .......................................................................................................................................... 37 5.4.2 Ejemplo de una posible implementación del objeto relojes ................................................................. 39 5.4.3 ¿Cómo modificar un bit del puerto de salida?...................................................................................... 40 5.4.4 Optimización ........................................................................................................................................ 43 6. DESCRIPCIÓN DE LA SESIÓN -1 (ANTES DE IR AL LABORATORIO B-043) ........................................................44 6.1 7. COMENTARIOS SOBRE LAS CONEXIONES .............................................................................................................. 44 DESCRIPCIÓN DETALLADA DE LA SESIÓN 0 ...................................................................................................45 7.1 MÉTODO DE TRABAJO ..................................................................................................................................... 46 7.2 TUTORIAL INICIAL ........................................................................................................................................... 46 7.3 TUTORIAL DEL MANEJO DEL TECLADO DE LA PLACA TL04........................................................................................ 47 7.4 DISEÑO, IMPLEMENTACIÓN Y PRUEBA DE UN PRIMER PROGRAMA ............................................................................ 47 7.4.1 Estructura básica de los programas que desarrolle ............................................................................. 47 2 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 7.4.2 Subrutina para configurar el HW (hwInit) ............................................................................................ 48 7.4.3 Si tiene dudas o problemas... ............................................................................................................... 48 7.5 NOCIONES SOBRE DEPURACIÓN DE PROGRAMAS................................................................................................... 48 7.5.1 PASO 1: Obtención de una prueba fallida y previsión de la salida ....................................................... 49 7.5.2 PASO 2: Localización del error .............................................................................................................. 49 7.5.3 PASO 3: Determinación de la causa del error ....................................................................................... 50 7.5.4 PASO 4: Corregir el error ...................................................................................................................... 51 7.5.5 Consejos para errores no sistemáticos y ocasionales........................................................................... 51 7.5.6 Comentarios adicionales sobre depuración de programas .................................................................. 52 8. DESARROLLO RECOMENDADO .....................................................................................................................53 8.1 HITOS Y SESIONES ORIENTATIVAS....................................................................................................................... 53 8.1.1 Sesión -1 ............................................................................................................................................... 53 8.1.2 Hito 1: Menús y visualización ............................................................................................................... 53 8.1.3 Hito 2: Movimientos ............................................................................................................................. 55 8.1.4 Hito 3: Colisiones .................................................................................................................................. 56 8.1.5 Hito 4: Melodía de juego ...................................................................................................................... 57 8.1.6 Hito 5: Sistema final ............................................................................................................................. 57 9. MEJORAS CON PUNTUACIÓN PREDEFINIDA .................................................................................................58 9.1 9.2 9.3 9.4 10. ESTADÍSTICAS DE JUEGO (MÁXIMO 0,3 PUNTOS) .................................................................................................. 58 GENERACIÓN ALEATORIA DE PIEZAS (MÁXIMO 0,3 PUNTOS) ................................................................................... 58 GENERAR LA SEÑAL DE CADA NOTA MEDIANTE EL DAC DE LA PLATAFORMA ENT2004CF (MÁXIMO 0,5 PUNTOS) ............ 58 CONSTRUCCIÓN DE UN PROTOTIPO DEL HW EN PCB (MÁXIMO 0,5 PUNTOS) ............................................................ 59 OTRAS MEJORAS .....................................................................................................................................59 10.1 10.2 10.3 10.4 10.5 10.6 10.7 10.8 10.9 10.10 10.11 10.12 10.13 10.14 10.15 10.16 11. 11.1 11.2 11.3 11.4 VELOCIDAD O RITMO DE CAÍDA VARIABLE: NIVEL DE DIFICULTAD INCREMENTAL........................................................... 59 AMPLIACIÓN DE LA FUNCIONALIDAD POR SW ...................................................................................................... 60 PERFIL DE JUGADOR ........................................................................................................................................ 60 VISUALIZADOR DE LA SIGUIENTE PIEZA ................................................................................................................ 61 SISTEMA DE PUNTUACIÓN AVANZADO ................................................................................................................ 61 COMIENZO DE JUEGO CON BLOQUES FIJOS .......................................................................................................... 62 AMPLIACIÓN DEL SUBSISTEMA DE VISUALIZACIÓN ................................................................................................. 62 COMUNICACIÓN SERIE UTILIZANDO LA UART ...................................................................................................... 62 CONEXIÓN CON UN SERVIDOR TFTP .................................................................................................................. 62 RECEPCIÓN DE MELODÍAS POR SMS.............................................................................................................. 63 CONTROL DEL JUEGO POR MEDIO DE UN ACELERÓMETRO .................................................................................. 63 REPRODUCCIÓN DE VOZ.............................................................................................................................. 63 RECONOCIMIENTO DE VOZ .......................................................................................................................... 63 PROGRAMACIÓN (MEDIANTE COMUNICACIÓN SERIE) DE UN KIT DE REPRODUCCIÓN MP3 ......................................... 63 COMUNICACIÓN CON UNA PSP, CON UNA PDA O UN IPOD ............................................................................... 64 IMPLEMENTACIÓN DE OTROS JUEGOS ............................................................................................................ 64 EVALUACIÓN ...........................................................................................................................................64 FUNCIONAMIENTO Y EXAMEN ORAL (<=4 PUNTOS O <=3,5 PUNTOS) ...................................................................... 65 MEMORIA FINAL (<=1,5 PUNTOS) .................................................................................................................... 65 CALIDAD DEL SW (<=2,5 PUNTOS) ................................................................................................................... 65 CALIDAD DEL HW (<=0,5 PUNTOS) .................................................................................................................. 67 12. MATRÍCULAS Y DIPLOMAS DE HONOR ....................................................................................................67 13. BIBLIOGRAFÍA..........................................................................................................................................68 3 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 ÍNDICE DE FIGURAS FIGURA 1. EJEMPLOS DE DIFERENTES PLATAFORMAS CON TETRIS. ......................................................................................... 7 FIGURA 2. TECLADO MATRICIAL USADO EN EL LSED. .......................................................................................................... 10 FIGURA 4. DIAGRAMA DEL SUBSISTEMA HW DE VISUALIZACIÓN DE LA MELODÍA (8 FILAS Y 4 COLUMNAS). ................................... 14 FIGURA 5. PROPUESTA DE MONTAJE PARA LA IMPLEMENTACIÓN DEL AMPLIFICADOR DE POTENCIA. ............................................. 15 FIGURA 6. TIPOS DE PIEZA (FUENTE: SITIO WEB OFICIAL TETRIS, WWW.TETRIS.COM). ............................................................... 19 FIGURA 7. DIAGRAMA DE OBJETOS: ARQUITECTURA SOFTWARE. ........................................................................................... 22 FIGURA 9. MODELO MATRICIAL DE PIEZA: ÁREA DE OCUPACIÓN DE LA PIEZA............................................................................ 27 FIGURA 10. MODELO DE ROTACIONES PARA LAS PIEZAS. ..................................................................................................... 29 FIGURA 11. REFRESCO DE LA MATRIZ DE LEDS. .................................................................................................................. 30 FIGURA 12. REPRESENTACIÓN TEMPORAL DE LOS 3 PROCESOS. ............................................................................................ 34 ÍNDICE DE TABLAS TABLA 1. FRECUENCIAS DE LAS NOTAS MUSICALES PARA LAS ESCALAS 4, 5, 6 Y 7. ...................................................................... 9 TABLA 2. ASIGNACIÓN ESTÁNDAR DE TECLAS PARA EL JUEGO EN EL TECLADO MATRICIAL DEL LSED. ............................................. 12 TABLA 3. DETALLE DE LAS DIFERENTES CONEXIONES AL PUERTO DE SALIDA. ............................................................................. 41 TABLA 4. RELACIÓN ENTRE SESIONES DE LABORATORIO E HITOS A CONSEGUIR. ........................................................................ 53 4 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 1. Introducción El objetivo del Laboratorio de Sistemas Electrónicos Digitales es que el alumno adquiera práctica en el desarrollo de sistemas con interacción entre HW y SW y con requisitos de tiempo real, aplicando y consolidando de una manera práctica los conocimientos adquiridos principalmente en las asignaturas de tercer curso Sistemas Electrónicos Digitales y Laboratorio de Circuitos Electrónicos, partiendo de la base sobre programación adquirida en Fundamentos de la Programación y Laboratorio de Programación. Para ello deberá seguir las instrucciones aquí incluidas, que implicarán diversas fases de diseño, análisis, implementación y medida de los circuitos y programas propuestos. Igualmente se hará especial énfasis en que los alumnos adquieran una visión práctica de los problemas con los que se encuentra el diseño del hardware (HW) y el software (SW) de sistemas electrónicos a la hora de implementar prototipos reales de Laboratorio. El resultado del trabajo realizado debe quedar reflejado en una memoria final que contenga los detalles del proceso, así como los resultados obtenidos y todas aquellas cuestiones específicas que se indiquen en el enunciado. Es obligatorio entregar electrónicamente el programa en desarrollo a través del portal http://lsed.die.upm.es de acuerdo con las normas generales del LSED [1] publicadas previamente. Salvo que se indique lo contrario, la práctica propuesta contiene las especificaciones mínimas obligatorias que deben cumplir los sistemas y serán valoradas con un máximo de 8 puntos si se realiza en C y 8,5 puntos si se realiza en ensamblador. Esta nota máxima sólo se conseguirá si se cumplen todas las especificaciones, y la memoria, el código, el hardware y las respuestas en el examen oral son perfectos. La descripción del sistema de menús de la interfaz de usuario es orientativa, aunque en la evaluación se valorará la calidad de la interfaz desarrollada. Las desviaciones respecto a la interfaz de este enunciado deben ser explicadas en la memoria final. Adicionalmente a las especificaciones mínimas, se presentarán sugerencias de mejoras opcionales, dejando a los alumnos la libertad para que añadan nuevas mejoras o esquemas alternativos. Con estas mejoras o montajes alternativos añadidos al prototipo básico, y dependiendo de su dificultad y realización, se podrá alcanzar la máxima nota, 10 puntos. Añadir una mejora no garantiza que la nota final esté por encima de 8 puntos si se realiza en C y 8,5 puntos si se realiza en ensamblador; sólo ofrece la posibilidad de sumar puntos sobre la nota de la parte básica de su sistema, de su examen oral y de su memoria final. Sobre otras modalidades de práctica distintas de la estándar, remitimos al alumno a la información general de la asignatura [1]. Aquellos alumnos que deseen realizar una práctica innovadora basada en un problema o un diseño propios (o propuesto por un profesor), deberán hablar con alguno de los profesores de la asignatura y presentarle (y ser aprobada por el mismo) una propuesta de práctica donde describan en 2 o 3 páginas cuáles son los objetivos del sistema propuesto, qué recursos son necesarios para llevarlo a cabo, así como las arquitecturas HW y SW propuestas para la resolución del problema. No será admitida ninguna práctica (por muy compleja o perfecta que sea) que no se ajuste a estas normas. Sobre las consideraciones éticas del trabajo en el laboratorio, remitimos al alumno al documento publicado sobre la filosofía de los laboratorios LCEL y LSED, disponible a través del portal de la asignatura [2]. 5 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 Para cualquier consulta, no duden en dirigirse al coordinador Fernando Fernández Martínez (B109, [email protected]), o a cualquiera de los profesores del LSED en sus respectivos horarios de tutoría. Podrá encontrar éste y otros documentos relacionados, así como información actualizada sobre la asignatura, en http://lsed.die.upm.es/. Adicionalmente, el alumno dispondrá de un conjunto de vídeos explicativos y demostrativos sobre esta práctica y este enunciado. 1.1 Aviso inicial Cuando aborde la lectura de este documento, hágalo con tranquilidad y detenimiento. Frases o comentarios que no se entiendan en una primera lectura pueden encerrar avisos y recomendaciones que le serán útiles a lo largo del desarrollo del Laboratorio. No se preocupe si no alcanza a comprender todos los términos, conceptos y detalles que se discuten. Todos ellos se irán aclarando a medida que avance en la lectura de este documento. Por supuesto, asuma que necesitará varias lecturas y una reflexión a fondo sobre todo esto. Preste especial atención a todas las referencias explícitas a aspectos que se indican como obligatorios para incluir en la memoria: no quiere decir que algo no referenciado explícitamente no tenga que ser tratado, sino que nuestra experiencia demuestra que algunos de esos aspectos no son considerados por un cierto número de alumnos, lo que da lugar a desagradables sorpresas en los exámenes. A lo largo de este enunciado irá descubriendo que multitud de detalles imprescindibles de solventar en un sistema real, se dejan de lado o se simplifican notablemente. Es fundamental que tenga en cuenta que esta práctica pretende ser un ejercicio de diseño, implementación y prueba de sistemas electrónicos digitales (con una pequeña componente analógica), con lo que es seguro que encontrará decisiones de diseño y recomendaciones que harían imposible que el prototipo final construido pudiera llegar a formar parte de un sistema real. 2. Especificación de requisitos del sistema 2.1 Antecedentes Uno de los sectores de mayor auge de la industria electrónica es el de los videojuegos. Buena prueba de ello la constituyen los informes periódicos realizados por el consorcio Avista Partners (http://avistapartners.com/news-newsletter.html). Según los datos recogidos en el informe correspondiente al año 2009, a pesar de los efectos de la consabida crisis económica, se manejaron cifras superiores a los 3500 millones de dólares en acuerdos dentro del sector, y unos 1200 millones de dólares en adquisiciones. En los últimos años, una de las piedras de toque que caracteriza a los videojuegos es el elevado grado de complementariedad en el desarrollo de HW y SW especializados (lo que se refleja, en el informe anterior, en la elevada aceptación de los juegos móviles que alcanza el 82,9%). Un segundo rasgo distintivo del mercado actual de videojuegos es que, frente a juegos más tradicionales, muchas veces de carácter violento o solitario, han surgido nuevos juegos de carácter más social, cultural o colectivo, y que implican nuevos tipos de competiciones y de interacción física, nuevas habilidades puestas en juego, nuevas interfaces, etcétera. 6 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 Desde el punto de vista del HW, la gran revolución ha sido el Wiimote de Nintendo (que ha cambiado incluso el perfil de los jugadores y compradores de videojuegos), con su capacidad para detectar movimientos de manera inalámbrica y atraer nuevo público al mundo de las consolas. En torno a él proponemos la realización de una práctica alternativa, y en esta práctica estándar proponemos mejoras basadas en acelerómetros como los de dicho mando. Más recientemente, ha sido Microsoft quien ha hecho pública su intención de provocar una nueva gran revolución con el anuncio de la puesta marcha para el próximo verano de su Proyecto Natal, una manera de jugar con la videoconsola Xbox360 sin mandos, simplemente empleando gestos y la voz. Para la práctica estándar de este curso académico no hemos contemplado cotas tan ambiciosas, en su lugar hemos escogido como modelo un videojuego perteneciente al grupo de los “videojuegos rompecabezas”. En este tipo de juegos, el objetivo es resolver un puzzle visual, empleando por lo general modelos lógicos, estratégicos, reconocimiento de patrones y, en no pocos casos, habilidad manual. Dentro de este tipo de videojuegos destacan, entre otros, el conocido Buscaminas, que se puede encontrar en casi todas las distribuciones de Microsoft Windows, el conocido arcade Bomberman, y el paradigma de este tipo de videojuegos, TetrisTM, creado en 1984 por el programador ruso A. Pajitnov, y que constituirá el modelo de base a partir del cual se articula esta práctica. Figura 1. Ejemplos de diferentes plataformas con TETRISTM. 7 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 La mecánica de TetrisTM es muy simple: una serie de piezas, denominadas tetrominós, descienden a una cierta velocidad por la pantalla de juego. El jugador tiene la posibilidad de rotar las piezas según giros de 90 grados en sentido antihorario. Las piezas encajan unas sobre otras, y entre los márgenes del tablero de juego. Siempre que se consigue formar una línea horizontal completa (o más de una), dicha línea (o líneas) desaparecen, ocasionando que el resto de elementos en la pantalla desciendan, e incrementando el contador de puntuación del jugador. Si, en un momento dado, las piezas alcanzan el límite superior de la pantalla, el juego finaliza. La dificultad del juego se puede ver incrementada por diferentes factores: velocidad de caída de las piezas, posiciones iniciales del tablero ocupadas por piezas, aparición aleatoria de fragmentos de piezas en posiciones aleatorias del tablero, etcétera. Tal fue el éxito del videojuego, que innumerables versiones comenzaron a poblar las tiendas de videojuegos, los ordenadores personales y los salones recreativos de todo el mundo. La influencia de Tetris se deja notar incluso veintiséis años después de su creación, con versiones para dispositivos tan actuales como el iPod de Apple, o incluso en internet en forma de “película” basada en este videojuego (http://www.myvideo.de/watch/3983910/Tetris_Film_Trailer). En la presente práctica supondremos que un cliente (el Departamento de Ingeniería Electrónica) nos ha contratado para desarrollar un prototipo de un videojuego de rompecabezas de bajo coste, inspirado en los anteriores. Dado que el propósito de este laboratorio es eminentemente docente (con especial énfasis en la interacción HW-SW, así como en los requisitos de tiempo real), el objetivo será implementar un prototipo funcional completo. Este enunciado constituye una guía para su diseño e implementación. 2.2 Objetivo general El objetivo de la práctica es mostrar la viabilidad de la idea de diseño básica desarrollando un prototipo plenamente funcional. El programa que ejecutará el micro se realizará en ensamblador o en C (ambos están incorporados en el entorno de desarrollo EDColdFire; la calificación máxima de la práctica básica es 8 puntos si se realiza en C y 8,5 puntos si se realiza en ensamblador). El sistema digital basado en un microprocesador será la plataforma ENT2005CF disponible en el laboratorio B-043 (construida en torno a un MCF5272). Para más detalles relacionados con el sistema de desarrollo, consulte la publicación [2]. En los apartados siguientes se detallarán las arquitecturas HW y SW, haciendo énfasis en la descomposición modular del sistema, tarea clave para abordar con éxito el diseño de cualquier sistema HW o SW medianamente complejo. El objetivo general lo podemos resumir de la siguiente manera, desarrollar “un sistema digital basado en la plataforma ENT2005CF” que permita: • Mostrar en una matriz de leds de 8x4, que hará las veces de display, el área de juego en la que el jugador deberá ir encajando las piezas, diferentes formas geométricas compuestas por cuatro cuadrados conectados ortogonalmente. Para ello empleará 12 terminales digitales de salida de la plataforma ENT2005CF (8 terminales para las filas y 4 terminales para las columnas). De esta manera, el jugador observará, sucesivamente, cómo va “cayendo” una pieza tras otra a velocidad constante de la parte superior del display. El jugador no podrá impedir la caída de las piezas pero sí que podrá modificar tanto su orientación (i.e. ángulo de rotación de la pieza en sentido anti-horario 8 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 respecto a la base del área de juego, 0°, 90°, 180°, 270° respectivamente) como la posición a ocupar dentro del área de juego. • Cuando el jugador consiga completar una o varias líneas horizontales, dichas líneas deberán desaparecer. Al mismo tiempo, todas las piezas que estén por encima deberán descender una posición, liberando espacio de juego y por tanto facilitando la tarea de situar nuevas piezas. El juego acabará cuando las piezas se amontonen hasta rebasar el límite superior del área de juego. • De manera indefinida (el programa nunca dejará de monitorizar el teclado hasta que se apague el sistema), debe presentar al jugador un menú por pantalla que le permita elegir tanto un nivel de dificultad concreto como el momento de comienzo del juego. Una vez finalizada una partida, deberá volver al menú inicial. • El juego tendrá 3 niveles de dificultad entre los que el jugador deberá escoger: o en el nivel 1 las piezas caerán a una velocidad estándar (e.g. uno o dos segundos por línea); o en el nivel 2 la velocidad de caída se acelerará, por ejemplo, un 20%; o finalmente, en el nivel 3 dicha velocidad será un 40% mayor que la del nivel 1; • Medir el número de líneas horizontales completadas. Al terminar de jugar, el sistema deberá mostrar esta información en la ventana de terminal del entorno de desarrollo EDColdFire. Adicionalmente, y como una de las posibles mejoras, se sugiere la ampliación del conjunto de resultados mostrados por pantalla (e.g. el tiempo de juego medido en segundos y la relación entre ambos). • Reproducir una melodía monofónica (no es necesario reproducir varias notas a la vez), durante el transcurso del juego. Cada nota de la melodía será un tono de la frecuencia y duración adecuadas. En esta práctica, la plataforma ENT2004CF será la encargada de generar una señal cuadrada con la frecuencia de la nota a reproducir durante un tiempo determinado. Esta señal cuadrada será generada por el MCF5272 a través de la salida TOUT0 del temporizador 0 (TIMER 0) que se corresponde con el PIN 13 del conector de salidas digitales. Esta señal será aplicada sobre el HW analógico necesario para poder escuchar correctamente el audio en unos auriculares y para regular el volumen de reproducción. A continuación de la Tabla 1, donde se muestran las frecuencias (redondeadas a números enteros) de las notas correspondientes a las 4 escalas con las que vamos a trabajar en esta práctica, se incluyen las frecuencias (en Hz) y las duraciones de las notas (en milisegundos) de la melodía propuesta. Tabla 1. Frecuencias de las notas musicales para las escalas 4, 5, 6 y 7. Número 0 1 2 3 Nota Silencio DO DO# RE Octava 4 0 262 277 294 Octava 5 0 523 554 587 Octava 6 0 1047 1109 1175 Octava 7 0 2093 2217 2349 4 RE# 311 622 1245 2489 5 MI 330 659 1319 2637 6 FA 349 699 1397 2794 7 FA# 370 740 1480 2960 8 9 10 11 12 SOL SOL# LA LA# SI 392 415 440 466 494 784 831 880 932 988 1568 1661 1760 1865 1976 3136 3322 3520 3729 3951 9 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 • En la versión final, los retardos debidos a, por ejemplo, escribir por pantalla o leer el teclado no deben retardar la visualización de las piezas ni la reproducción de las notas, ni la visualización y reproducción deben retardarse entre sí (requisito de concurrencia y tiempo real). Figura 2. Teclado matricial usado en el LSED. • Las teclas que debe aceptar el sistema serán al menos 4: o las teclas ‘1’, ‘4’ y ‘7’ del teclado matricial servirán para elegir los niveles de dificultad y para desplazar las piezas durante el juego. De este modo, una pulsación de dichas teclas supondría un desplazamiento de la pieza actualmente en movimiento hacia la izquierda, hacia abajo y hacia la derecha respectivamente (siempre que dichos movimientos estén permitidos tal y como se verá más adelante en la sección 5.3.2.7). o la tecla ‘A’, que servirá para dar comienzo al juego o, una vez comenzado éste, para girar o rotar la pieza en movimiento. En este último caso, sucesivas pulsaciones de dicha tecla deberían provocar a su vez sucesivas rotaciones de la pieza a intervalos de 90º con respecto a la base de la pantalla y en sentido antihorario. • Será, igualmente, competencia del sistema SW, generar y procesar las señales necesarias para gobernar el HW externo. En relación a la melodía disponible, ésta estará guardada en memoria en forma de arrays o tablas de datos que contengan las frecuencias y las duraciones en milisegundos de cada una de las notas que componen la melodía. Las frecuencias y duraciones correspondientes a las notas de la melodía propuesta se facilitan a continuación: • Frecuencias “Tetris”={1319, 988, 1047, 1175, 1047, 988, 880, 880, 1047, 1319, 1175, 1047, 988, 988, 1047, 1175, 1319, 1047, 880, 880, 0, 1175, 1397, 1760, 1568, 1397, 1319, 1047, 1319, 1175, 1047, 988, 988, 1047, 1175, 1319, 1047, 880, 880, 0, 659, 523, 587, 494, 523, 440, 415, 659, 523, 587, 494, 523, 659, 880, 831}; /* En Hz */ • Tiempos “Tetris”={450, 225, 225, 450, 225, 225, 450, 225, 225, 450, 225, 225, 450, 225, 225, 450, 450, 450, 450, 450, 675, 450, 225, 450, 225, 225, 675, 225, 450, 225, 225, 450, 225, 225, 450, 450, 450, 450, 450, 450, 900, 900, 900, 900, 900, 900, 1800, 900, 900, 900, 900, 450, 450, 900, 1800}; /* En ms */ 10 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 2.2.1 Casos de uso En el sistema SW habrá varios actores externos: • El teclado, a través del cual el usuario puede seleccionar el nivel de dificultad, el comienzo del juego, y la orientación (i.e. rotación) o la posición de cada una de las piezas que vayan cayendo. • La matriz de leds que muestra en todo momento el estado de ocupación del área de juego y que mantiene permanentemente actualizada la posición de la pieza bajo el control del jugador. • El HW de audio (i.e. filtro y amplificador). • Las interrupciones temporizadas. Los posibles casos de uso serían: • Cada vez que se produzca una interrupción temporizada, se modificarán los contadores de tiempo. Si se está disputando una partida: o Se resolverá la posible necesidad de gestionar los ajustes oportunos para la reproducción de la siguiente nota de la melodía, o Se resolverá la posible necesidad de modificar la excitación aplicada a la matriz de leds conforme a la frecuencia de actualización elegida (i.e. refresco) de la pantalla, o Se resolverá la necesidad de modificar la posición de la pieza en movimiento, reubicándola una línea más abajo, conforme al ritmo o velocidad de caída elegido. Naturalmente, para actualizar dicha posición se tendrá en cuenta el estado de ocupación de la pantalla. De esta forma, si no fuese posible prolongar la caída de la pieza, se procedería bien a hacer aparecer una nueva pieza en la parte superior de la pantalla (en caso de que hubiese espacio para ello), o bien simplemente a dar por finalizado el juego. o Los posibles rebotes mecánicos debidos a la pulsación de una tecla o a soltarla, se suprimirán por SW. Si se pulsa una tecla una única vez, el sistema debe interpretar una única pulsación sin que le afecten los posibles rebotes en la señal que recibe del teclado. o La duración de la pulsación de cada tecla (sea breve o sea larga) no debe dar lugar a que se detecten varias pulsaciones de la misma tecla. El sistema debe ser capaz de detectar pulsaciones lo suficientemente breves como para desplazar o rotar la pieza de la manera deseada. El sistema de menús sería, de manera orientativa, el siguiente: • Al comienzo, el sistema debe presentar al usuario un menú ofreciendo la posibilidad de jugar con alguno de los 3 modos de dificultad disponibles. No se puede salir de este menú mientras no se elija un nivel de dificultad correcto. 11 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 • Antes de dar comienzo al juego se debe presentar un mensaje con el nivel de dificultad elegido. • Una vez que el usuario ha elegido uno de los niveles de dificultad disponibles, se esperará a que el usuario pulse la tecla A para comenzar a jugar. En ese momento se dará comienzo al juego y se procederá a la reproducción de la melodía y a la visualización de la primera pieza. • Una vez terminado el juego, se debe indicar el resultado de éste: el número de líneas completadas. • Así mismo, se pondrá fin al proceso de reproducción de la melodía y el menú de selección de nivel de dificultad deberá volver a aparecer para que el usuario pueda volver a elegir otra. • Pulsar cualquier otra tecla distinta de las propuestas (más abajo indicadas) durante el juego o durante el proceso de selección del nivel de dificultad no tendrá ningún efecto en el sistema básico salvo que se desee implementar una determinada mejora con más teclas útiles (e.g. pausar o cancelar el juego en curso). • Los mensajes se mostrarán en la pantalla del ordenador. Durante el juego propiamente dicho, no se muestran mensajes por pantalla hasta que termina el juego y se muestran los resultados finales. • Como los leds están organizados en forma de matriz con 12 entradas, se usarán 8 terminales para iluminar o no cada uno de los 8 leds que hay en una columna, y otros 4 para seleccionar qué columna iluminar. Para que no se perciba parpadeo, el sistema: o iluminará los leds apropiados de la primera columna durante unos 5 ms, o posteriormente, pasará a iluminar sucesivamente las siguientes columnas durante el mismo periodo de tiempo, o tras alcanzar e iluminar la última columna, volverá a la 1ª cíclicamente. • De esta manera, cada led se puede encender y apagar hasta 50 veces por segundo, produciéndose la ilusión de que los leds de varias columnas están encendidos a la vez, cuando realmente en cada instante de tiempo, sólo están siendo excitados los leds de una columna. Asignación estándar de teclas: Tabla 2. Asignación estándar de teclas para el juego en el teclado matricial del LSED. TECLA 1 TECLA 4 TECLA 7 TECLA A Nivel 1 Nivel 2 Nivel 3 Comienzo del juego 12 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 3. Subsistema Hardware Figura 3. Diagrama general de bloques del subsistema hardware completo. 3.1 Matriz de leds Conceptualmente necesitamos una matriz de 4 columnas y 8 filas de leds, matriz que podremos implementar siguiendo el esquema presentado en la Figura 4. Siguiendo dicho esquema, si aplicamos 5 voltios a una columna y 0 voltios a las demás (usando un buffer 74HC244 conectamos las columnas al puerto de salidas digitales del entrenador), y si aplicamos 5 voltios a las filas que no queramos iluminar, y 0 a las que deseemos iluminar (las conexiones entre el puerto de salida y las filas requiere otro buffer y un conjunto de resistencias para que los leds no consuman mucha corriente pero se iluminen bien), conseguiremos ir mostrando las piezas del juego ocupando diferentes posiciones en pantalla según los movimientos que hayamos realizado mediante el uso de las teclas. Los buffers tienen por objetivo no pedir mucha corriente a los puertos del entrenador (sino a los 74HC244). 13 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 Figura 4. Detalle del subsistema HW de visualización de la melodía (8 filas y 4 columnas). Como posible mejora se prevé la posibilidad de diseñar un dispositivo de visualización más elaborado que haga uso, por ejemplo, bien de un display LCD o bien de un conjunto de displays de 7 segmentos. En este último caso, podrían aprovecharse las conexiones internas del display de 7 segmentos para ahorrar conexiones horizontales, resultando además especialmente sencilla la alineación de los leds. En ambos casos (i.e. uso de un LCD o de un conjunto de displays de 7 segmentos), el procedimiento necesario para poder representar las piezas por pantalla adquiere una complejidad notable, motivo por el que esta mejora sería considerada como de dificultad alta. 3.2 Filtrado de la señal En primer lugar la señal cuadrada generada por el MCF5272 se filtra para reducir sus armónicos. Esta señal se genera a través de la salida TOUT0 del temporizador 0 (TIMER 0) que se corresponde con el PIN 13 del conector de salidas digitales. Si se aplica esta señal directamente sobre un altavoz podremos reconocer perfectamente la nota o melodía reproducida (aunque la percibiremos con una fuerte distorsión). La misión del filtro tiene como objetivo principal reducir el número de armónicos, reduciendo también la sensación de distorsión de la nota reproducida. Este filtro será un filtro paso bajo con frecuencia de corte superior o igual a 12KHz (para permitir al menos 2 armónicos de la nota con mayor frecuencia: última nota de la octava 7). En un principio podríamos pensar en generar una señal sinusoidal perfecta pero este tipo de señal no simula correctamente el sonido producido por un instrumento, el cual tiene más riqueza espectral. Por esta razón, colocaremos un filtro que reduzca los armónicos pero que mantenga al 14 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 menos los 3 primeros. En el apartado de mejoras se propondrá la generación de diferentes tipos de onda para simular diferentes instrumentos. Para la implementación de este filtro paso-bajo se propone un filtro de 2º orden Sallen-Key con ganancia unidad, similares a los desarrollados en LCEL (consultar [12], apartado 5.7). Un aspecto que debemos tener en cuenta en este caso es que la señal a filtrar es una señal digital entre 0 y 5 voltios, mientras el filtro lo alimentaremos entre –10 voltios y 10 voltios. Por esta razón es necesario eliminar la componente continua utilizando una red R-C (en configuración filtro paso alto) con valores de C y de R elevados de forma que la frecuencia de corte sea muy baja (de unos pocos Hz). A la salida del filtro debemos tener una señal de igual o menor rango dinámico que a la entrada. 3.3 Amplificador de potencia La salida de los circuitos digitales (y de muchos amplificadores operacionales con los que se construyen los filtros) tiene una limitación importante en relación con la corriente que pueden ofrecer. En muchos casos, esta corriente no es suficiente para excitar unos altavoces. Por esta razón, es necesario incluir un módulo de amplificación de potencia previo a los altavoces. Para la implementación de este módulo se recomienda utilizar el amplificador de potencia LM386 [13] utilizando alguno de los montajes que propone el fabricante (es necesario eliminar la componente continua antes de amplificar). En la Figura 5 se muestra el montaje más sencillo. Un aspecto importante que el alumno debe tener en cuenta es que este amplificador presenta una ganancia entre 20 y 200. Por esta razón, se debe incluir una etapa de atenuación que reduzca el margen dinámico de la señal. Al realizar el montaje se recomienda al alumno que consulte las hojas de especificaciones del LM386 con el fin de ajustar correctamente los niveles de las señales y de la alimentación. La impedancia del altavoz se puede modelar aproximadamente como una resistencia de unos 10 ohmios. Figura 5. Propuesta de montaje para la implementación del amplificador de potencia. 15 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 También es necesario recordar la importancia del filtrado de alimentación típico del LCEL, apartado 5.10 de [14], especialmente cuando se conecta el amplificador de potencia, que puede requerir incluso una alimentación independiente. Si no se hace, el filtro puede funcionar mal debido al ruido que le entre por su alimentación. Aunque la melodía se oiga razonablemente bien es importante comprobar con el osciloscopio el correcto funcionamiento tanto del filtro paso-bajo como del amplificador de potencia. Cuando se compruebe el funcionamiento del amplificador de potencia de forma aislada es importante probarlo utilizando señales sinusoidales (obtenidas del generador de funciones) con el fin de detectar posibles problemas de saturación. 3.4 Cascos o auriculares Finalmente la reproducción de las melodías se realizará utilizando auriculares (nunca altavoces) y con un volumen de reproducción bajo, sólo audible para las personas que tienen puesto el auricular. El motivo es no incrementar innecesariamente el ruido del laboratorio, evitando molestar al resto de compañeros. 3.5 Observaciones adicionales sobre el HW de entrada/salida Es necesario recordar que los puertos de entrada y salida disponibles en la plataforma ENT2004CF están formados por buffers digitales con resistencias de pull-down de 10 kilohmios. Si no se tiene en cuenta este hecho, se podrían producir efectos de carga no deseados al conectar el HW a la plataforma. 3.6 Alimentación de los subsistemas Los subsistemas se alimentarán con tensiones simétricas o asimétricas, según convenga. Es muy importante desacoplar las alimentaciones y alimentar en estrella; remitimos al alumno a la referencia bibliográfica [5]. Si algún elemento puede demandar picos fuertes de corriente (por ejemplo, un amplificador de potencia), puede ser muy importante filtrar de manera extraordinaria su alimentación para que estos picos no afecten al resto de la circuitería (por ejemplo, un filtro de audio). 4. Subsistema digital basado en el MCF5272 Este subsistema lo forma la plataforma ENT2005CF cuya descripción se puede consultar en [3]. El manejo del entorno de desarrollo EDColdFire y las funciones de la TRAP #15 para comunicarse con el PC son descritos detalladamente en esta referencia. Es imprescindible realizar los principales tutoriales del EDColdFire que se proponen en las referencias [3][4] para aprender el manejo de los principales recursos de la plataforma ENT2005CF que se usarán en este sistema (http://lsed.die.upm.es). 16 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 5. Subsistema Software Este subsistema lo forma el programa cargado en la plataforma ENT2004CF. Existen dos documentos de dudas y preguntas frecuentes (una para ensamblador y otro para C) de gran utilidad en la etapa inicial de toma de contacto y elaboración de los primeros programas [7][8]. 5.1 Modelo de requisitos de SW En esta asignatura, el análisis y el modelo de requisitos no son competencia exclusiva del alumno, sino que son, parcialmente, información que se le proporciona para la realización de la práctica. Supongamos que tenemos un cliente que desea que desarrollemos un prototipo de bajo coste de un juego con las características mencionadas en el apartado 2.1. Tras diversas entrevistas con este hipotético cliente, podríamos llegar a un ámbito del proyecto SW como el ya incluido previamente en la descripción del apartado 2.2 “Objetivo general”. 5.2 Modelo de objetos orientativo La labor de descubrir qué objetos o estructuras de datos son relevantes en nuestro proyecto es sistematizable sólo hasta cierto punto. Tras un análisis de los requisitos recogidos en la sección 2 (especialmente de los sustantivos y de los adjetivos y verbos que pueden sustantivarse), se ha determinado que los objetos principales pueden ser los siguientes: • Tecla: teclado, pedir, pulsación, dígitos, rebotes… • Estado: relacionado con palabras o términos como menús, niveles de dificultad, comenzar, selección, escoger, aceptar,… • Piezas: forma, ancho, alto, posición… • Juego: movimientos, traslación, rotación, colisión… • Leds: columnas, filas, matriz de leds, iluminar, visualización de las piezas, parpadeo, ocupación… • Relojes: retardos, tiempo real… • Melodía: onda cuadrada, HW, reproducir, ritmo, ralentizar, nota, nota anterior, frecuencia, duración… • Resultados: juego, medir, número de líneas completadas, tiempo de juego, mostrar… • Pantalla: escribir, ventana de terminal, ver, mensajes… • Puertos: terminales digitales de salida, excitar… 5.2.1 Tecla Representa cada símbolo pulsado por el usuario, tanto durante el juego como durante la configuración. 17 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 Deberá contar con métodos que permitan: • Inicializar convenientemente el teclado y el conjunto de variables necesarias para su oportuna exploración. • Llevar a cabo la exploración del teclado y permitir la recuperación o lectura de las diferentes pulsaciones de las teclas que lo componen. Relaciones con otros objetos: • Juego: el objeto Tecla determina los movimientos de traslación o rotación requeridos por el usuario para fijar la ubicación de las diferentes piezas. • Puertos: para detectar una tecla es necesario excitar adecuadamente algún bit o bits del puerto de salida, y leer los bits adecuados del puerto de entrada. • Estado: las respuestas a los menús de este objeto se obtienen del objeto Tecla. 5.2.2 Estado Objeto que representa las opciones escogidas por el usuario (i.e. nivel de dificultad seleccionado), el estado en que se encuentra en todo momento nuestro sistema (i.e. si se está jugando o simplemente configurando)... Es un objeto activo con un menú asociado cuyo papel ha quedado claramente definido en los casos de uso. Tendrá métodos tales como Estado.inic() o Estado.menu(). Relaciones con otros objetos: • Tecla: las teclas pulsadas para el menú del objeto Estado son proporcionadas por el objeto Tecla. • Melodía: en función del Estado, se reproduce (o no) la melodía. • Pantalla: los menús del objeto Estado se muestran en la Pantalla. • Leds: el estado de ocupación de la matriz de leds determinará el instante en que se decida la finalización de la partida en curso (i.e. que se agote el espacio disponible en la matriz para la disposición de más piezas). 5.2.3 Piezas Este objeto debe contener la información característica de cada uno de los tipos de pieza que pueden aparecer durante el juego: la anchura, la altura, la orientación y la ocupación del área de juego de cada pieza. Deberá contar con métodos que permitan: 18 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 • Inicializar las estructuras en memoria necesarias para modelar los diferentes tipos de pieza considerados en el juego, incluyendo todas las características anteriormente mencionadas. • Crear o añadir una nueva pieza al juego de alguno de los tipos anteriormente definidos. • Recuperar respectivamente los valores vigentes para las diferentes propiedades de una pieza: la anchura, la altura, la rotación y, especialmente, la ubicación de la pieza dentro del área de juego (i.e. en la matriz de leds). Relaciones con otros objetos: • Juego: el objeto Juego recuperará del objeto Piezas toda la información necesaria para resolver correctamente, conforme a las reglas de juego, cada uno de los posibles movimientos (i.e. abajo, izquierda, derecha, rotación) a los que se pueda ver sometida una pieza. Naturalmente, y con motivo de dichos movimientos, Juego actualizará pertinentemente la información de posición y orientación de la pieza controlada por el jugador. • Leds: las piezas deben visualizarse en la matriz de leds. Figura 6. Tipos de pieza (Fuente: Sitio web oficial Tetris, www.tetris.com). 5.2.4 Juego El sistema debe contar necesariamente con un objeto que defina en todo momento las características generales del juego (e.g. el nivel, la pieza actual, la pieza siguiente, el tiempo máximo de permanencia de una pieza en una determinada línea, etc.) y que garantice la integridad del juego conforme al conjunto de reglas o restricciones básicas definidas para éste. Deberá contar con métodos que permitan: • Llevar a cabo la oportuna inicialización de toda variable o estructura de datos que resulte necesaria para el desarrollo del juego. • Ejecutar los diferentes movimientos contemplados para cada pieza, véase tanto los de traslación: hacia la izquierda, hacia abajo o hacia la derecha, como los de rotación (la rotación se realizará siempre en sentido anti-horario y a intervalos regulares de 90º). • Garantizar la viabilidad de dichos movimientos mediante la comprobación de que la nueva posición de la correspondiente pieza no suponga que ésta rebase o exceda los límites definidos para el área de juego o que tenga lugar una colisión con cualquier otra pieza anteriormente ubicada en esa misma posición. 19 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 Relaciones con otros objetos: • Piezas: este objeto irá proporcionando nuevas piezas que incorporar al juego cuando sea necesario. Así mismo, Juego recibirá de éste toda la información correspondiente tanto a la pieza actual (i.e. en movimiento bajo el control del jugador) como a la siguiente (que entrará en juego inmediatamente después de la colocación de la primera). • Relojes: es el objeto que determina el momento en que debe actualizarse la posición de la pieza actualmente en juego con motivo de la caída de la misma. • Leds: el objeto Leds debe proporcionar al objeto Juego información acerca de la ocupación de las distintas posiciones en el área de juego, así como también, de las dimensiones de esta última para poder determinar la viabilidad de los movimientos de traslación o rotación de las Piezas. 5.2.5 Leds Este objeto permite mostrar las piezas del juego en una matriz de leds. Para ello debe contener información acerca de las dimensiones de la matriz y de la ocupación de las distintas posiciones que la conforman (correspondiente al encendido/apagado de cada uno de los leds). Como la matriz en cada momento sólo puede tener iluminados los leds de una de sus 4 columnas, el objeto leds debe encargarse de producir la ilusión de que las piezas caen y de hacer un barrido que (cambiando la columna iluminada cada 5 ms.) produzca la ilusión óptica de que todas las columnas están iluminadas a la vez). Deberá contar con métodos que permitan: • Inicializar convenientemente la estructura de datos en memoria que permita representar el estado de ocupación de todas y cada una de las posiciones que componen el área de juego, estado que a su vez determinará la situación de encendido o apagado de los leds correspondientes. • Pintar cualquiera de las piezas definidas en una posición determinada dentro del área de juego. • Borrar del área de juego una pieza concreta. • Borrar el área de juego al completo. • Eliminar del área de juego las líneas que estén completas (i.e. fila) y actualizarla consecuentemente. Relaciones con otros objetos: • Piezas: el objeto Piezas debe proporcionar la información correspondiente a la propia pieza que se desee pintar o borrar: la orientación, la anchura, la altura y la matriz de ocupación asociada. • Estado: que indica cuándo comenzar a visualizar. • Relojes: que proporciona la base de tiempos. 20 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 5.2.6 Relojes En los objetos anteriormente descritos es necesario contar tiempos para controlar el ritmo de caída de las piezas, la duración de los posibles rebotes de las teclas, la duración de cada una de las etapas que permiten el barrido de la matriz de leds, la duración de las notas que componen la melodía de juego, etc. Para ello se necesitarán dos temporizadores que generen interrupciones periódicas (al menos 1000 por segundo, suficiente para medir los tiempos con una precisión razonable) y un conjunto de contadores de tiempo que formarán el objeto relojes. Tendrá métodos tales como: Relojes.inic() o Relojes.actualizar(). Relaciones con otros objetos: • Melodía: para poder reproducir las distintas notas que componen la melodía, se generará para cada una de ellas una onda cuadrada con la frecuencia requerida y durante tanto tiempo como corresponda según la duración de la nota, tiempo que podrá medirse empleando el objeto relojes. • Leds: la visualización se realiza al ritmo de la melodía y va a ser necesario realizar un barrido periódico de las columnas de la matriz de leds. 5.2.7 Melodía En nuestro programa debemos disponer de toda la información relativa a la melodía propuesta para su reproducción en esta práctica: frecuencia de cada nota en Herzios, duración de cada nota en milisegundos, nota actual, si la melodía ha terminado... Los dos primeros datos son constantes, no deben ser modificados a lo largo del programa. Deberá contar con métodos que permitan: • Configurar adecuadamente la interrupción asociada al proceso de reproducción. • Inicializar el conjunto de variables y estructuras de datos en memoria necesarias para la oportuna gestión de dicha reproducción. • Arrancar el temporizador elegido para la generación de una onda cuadrada de una determinada frecuencia. • Detener ese mismo temporizador en el momento en que se agote la duración de cada una de las diferentes notas. Relaciones con otros objetos: • Estado: que determina cuándo debe comenzar la reproducción de la melodía. • Relojes: que determina cuándo se debe proceder a la reproducción de la siguiente nota. 21 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 Figura 7. Diagrama de objetos: arquitectura software. 5.2.8 Resultados Este objeto contiene los datos importantes en relación al resultado de la última partida disputada: el número de líneas completadas. Esta información debe ser enviada a la pantalla para que se pueda leer. Tendrá métodos tales como Resultados.inic(), Resultados.Actualizar () o Resultados.mostrar(). Relaciones con otros objetos: • Estado: sólo se muestran resultados tras la finalización de una partida. • Pantalla: para mostrar los resultados. 5.2.9 Pantalla Este objeto permite mostrar mensajes en la pantalla de terminal del EDColdFire, como los mensajes de los menús o los del resultado del juego. En nuestro caso, la implementación puede simplemente encapsular el manejo de la TRAP #15 (o de las funciones output() y outNum() en C). Relaciones con otros objetos: • Estado: en la pantalla se muestran los menús del objeto Estado. • Resultados: en la pantalla se muestran los resultados. 22 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 5.2.10 Puerto Este objeto permite coordinar el manejo del puerto de salida (tanto en C como en ensamblador) al que pueden acceder varios procesos. Los objetos leds y tecla deben usar los servicios del objeto puerto para evitar que un objeto modifique los bits del otro. Tendrá métodos tales como Puerto.inic(), Puerto.columnaLedsSeleccionar() o Puerto.filaLedsIluminar(). Puerto.tecladoColumnaExcitar(), Relaciones con otros objetos: • Tecla: para detectar una tecla es necesario excitar adecuadamente el puerto de salida. • Leds: para encender o apagar los leds es necesario excitar adecuadamente el puerto de salida. El objeto Leds proporciona la información correspondiente a la columna cuyos leds es necesario encender o apagar según el estado de ocupación de dicha columna en la matriz. 5.2.11 Rutinas o métodos generales de los objetos de un sistema Todos los objetos (o estructuras de datos) pueden tener asociadas al menos 2 ó 3 funciones (o métodos) generales que los manejan: • Inicializar (inic): asigna valores iniciales a las propiedades de un objeto o estructura de datos. Como parte de la simulación de un programa en C, suele abrir un fichero de depuración donde se escribirán todos los eventos y valores del objeto a lo largo del tiempo, y que permite analizar detalladamente su funcionamiento a posteriori. • Re-inicializar (reset): vuelve a darle valores a las propiedades (aunque, para la mayoría de los objetos, pueden coincidir con los valores de inicialización). • Finalizar (fin): en el caso que nos ocupa, su existencia no tiene sentido, porque los objetos no desaparecen hasta que termina el propio sistema, y no son objetos persistentes cuyas propiedades haya que guardar para inicializar posteriores ejecuciones del sistema. 5.3 Modelo de diseño En el modelo de diseño adaptamos nuestro modelo de objetos para tener en cuenta: • Los requisitos temporales capturados en el modelo de requisitos. • El HW de que disponemos (su velocidad, su arquitectura...). • El SW previo que deseamos reutilizar (la trap #15...). 5.3.1 Arquitectura del sistema SW La arquitectura de un sistema es el esqueleto o el esquema sobre el que se asienta un sistema y que varía muy poco a lo largo del tiempo, aunque permite que el resto de los módulos no arquitecturales evolucionen. Establece la división del sistema en subsistemas y regula sus relaciones, su ubicación y su sincronismo (un subsistema es un objeto o conjunto de objetos con una 23 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 interfaz definida y reducida, que pueden ser tratados como una unidad de cara al resto del sistema). Es el primer elemento de todo buen diseño, y debe estar presente desde el primer prototipo. Es frecuente comenzar un sistema diseñando e implementando un primer prototipo que recoge la arquitectura propuesta para el sistema completo, aunque los subsistemas incluidos carezcan de funcionalidad (o dispongan de una funcionalidad elemental muy alejada de la finalmente necesaria). Continuando con el ejemplo que estamos comentando, nuestro análisis de los principales objetos nos da casi directamente la arquitectura, aunque en un sistema de unas ciertas dimensiones esto no ocurre, siendo necesario emplear los diversos criterios de agrupamiento antes mencionados. Sin embargo, no es extraño que, por cada una de las conexiones del sistema con los agentes exteriores, exista un subsistema interfaz para esa conexión, de tal manera que los procesadores queden independizados del modo de intercambiar datos con el exterior (lo cual facilita su simulación e incrementa su portabilidad, por ejemplo). La arquitectura debe ser capaz de soportar: • Los requisitos de diseño impuestos por el cliente: como en nuestro caso el uso de 4 teclas, de visualizadores matriciales, de reproducir una melodía durante el juego, etc. • Los requisitos impuestos por el HW: por ejemplo, el prototipo que vamos a diseñar utilizará al menos 1 temporizador de MCF5272 para generar interrupciones periódicas. El puerto de entradas digitales será empleado para leer la tecla pulsada. El puerto de salidas digitales será utilizado para 2 objetivos: interfaz con el teclado (excitar la fila o columna que deseamos leer) e iluminar los leds de la matriz de visualización del juego. Como los puertos de salida son de sólo escritura, habrá que coordinar el uso que las rutinas de cada objetivo hacen del puerto. • El SW disponible previamente (middleware): en nuestro caso el manejo de la pantalla se debe hacer a través de la Trap #15, a fin de no tener que reprogramar la comunicación y perder un tiempo precioso. Para el manejo del teclado y los temporizadores, es imprescindible consultar los tutoriales sobre el teclado y la placa TL04, y sobre las interrupciones temporizadas, y emplear las funciones que allí se nos proporcionan. 5.3.2 Modelo dinámico orientativo Para describir la evolución de los objetos o los subsistemas a lo largo del tiempo y en función de los eventos producidos, se deben emplear diagramas de transición de estados. Un estado de un objeto se asocia a un valor o combinación de valores de sus propiedades, propiedades que son variables, hecho particularmente relevante a la hora de describir su comportamiento dinámico a lo largo del tiempo. Las transiciones entre estados son resultado de la aparición de eventos internos (un cambio en un objeto puede generar un cambio en ese objeto o en otro) o externos (pulsar una tecla o producirse una interrupción), que provocan además la ejecución de una o varias funciones del objeto. Obsérvese que el modelo dinámico forma parte del diseño, dado que se encarga de la temporización y permite articular una posible solución al problema planteado. Objetos como Tecla, Melodía, Juego, Puerto, Leds o Relojes, tienen una dinámica especial regida por máquinas de estados que a continuación describiremos. 24 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 5.3.2.1 Modelo dinámico orientativo del objeto Tecla • Espera y Detección: a priori, un teclado matricial como el de la placa TL04 requiere un barrido como el que se describe en SEDG o en el tutorial del teclado. Sin embargo, si únicamente se emplea las teclas ‘1’, ‘4’ , ‘7’ y ‘A’, que están conectadas a la misma columna y un mismo terminal de salida (el bit 0 del puerto de salida), es posible no realizar el barrido, sino excitar esa columna (en la inicialización del objeto Tecla) y leer el puerto de entrada (conectado a las filas del teclado matricial como se muestra en la Figura 2) para ver si alguna de esas teclas ha sido pulsada. Se debe registrar la tecla pulsada y el instante de tiempo de la pulsación. • Antirrebotes al pulsar: si se ha detectado una tecla, hay que registrar en qué instante de tiempo se produjo la pulsación (teniendo en cuenta un contador asociado al teclado en el objeto Relojes) y en qué tecla, y esperar un cierto tiempo por si hubiese rebotes mecánicos al pulsar (empleando un contador asociado a los rebotes en el objeto relojes). • Esperar que se suelte la tecla pulsada: una vez pasado este tiempo, hay que esperar hasta que el usuario suelte la tecla (para evitar que una pulsación larga sea interpretada como varias pulsaciones). • Antirrebotes al soltar: una vez se ha soltado la tecla por primera vez, puede que haya que esperar un cierto tiempo por si hubiese rebotes mecánicos al soltar la tecla (empleando un contador asociado a los rebotes en el objeto relojes). 5.3.2.2 Modelo dinámico orientativo del objeto Puerto Este objeto, aparentemente sencillo, se ve complicado por el hecho de que los puertos del entrenador son unidireccionales, por lo que el objeto debe guardar el último valor enviado al puerto (y por lo tanto presente en el mismo) y cuando necesite cambiar un bit, actualizar la variable guardada y volverla a enviar. Además, cuando es llamado desde el programa principal, podría tener que habilitar y deshabilitar las interrupciones para evitar que el puerto (o la variable) sean modificados a la vez por los dos procesos. 5.3.2.3 Modelo dinámico orientativo del objeto Relojes La responsabilidad de incrementar o decrementar este objeto u objetos de tipo contador correrá a cargo de las interrupciones periódicas. Concretamente, en nuestro sistema contaremos con dos interrupciones de distinta prioridad, tal y como veremos posteriormente. El comportamiento del objeto es muy simple: se incrementa o decrementa en cada interrupción, y es consultado, por ejemplo, por los procesos asociados a los objetos Tecla y Melodía, a fin de poder realizar retardos o esperar el tiempo restante para la nota actual, respectivamente. Así por ejemplo, si se implementa una estrategia antirrebotes por SW, este reloj o relojes pueden servir para no leer el teclado durante el tiempo estimado de rebotes. Si la frecuencia de interrupciones es de 1 KHz, podríamos contar tiempos en milisegundos sin más que contar el número de interrupciones de este temporizador. Por esta razón se expresará la duración de cada nota en milisegundos. Además el milisegundo es una unidad suficientemente pequeña como para garantizar una resolución aceptable tanto para la adecuada excitación de la matriz de leds como para la reproducción de las notas musicales. 25 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 Figura 8. Posición de las diferentes piezas en la matriz de leds. 5.3.2.4 Modelo dinámico orientativo del objeto Piezas Desde el punto de vista semántico toda pieza puede caracterizarse por dos propiedades fundamentales: su posición y su forma. Ambas propiedades son claramente de naturaleza dinámica toda vez que sus respectivos valores pueden ir variando a lo largo del juego. Efectivamente, tanto la posición como la forma de una determinada pieza deberán ser actualizadas convenientemente tan pronto se produzca un movimiento de traslación o de rotación, respectivamente. Para poder articular la información relativa a la posición de una determinada pieza (resultado de los diferentes movimientos de traslación realizados), y dado el modelo matricial propuesto para el área de juego (construida como una matriz de leds), lo más sencillo es emplear un sistema de coordenadas cartesianas (x, y) que permita hacer referencia a cualquiera de las posiciones del mismo. Por simplicidad, podemos hacer coincidir nuestro origen de coordenadas con cualquiera de las esquinas del área de juego. En particular, en la Figura 8, lo hemos hecho coincidir con la esquina superior izquierda. Así mismo, hemos representado el área de juego con un posible estado de ocupación en el que hemos incluido, a modo de ejemplo, una pieza de cada uno de los siete tipos contemplados en el juego. 26 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 Para cada pieza, hemos destacado la información de posición correspondiente respecto a nuestro origen de coordenadas. De este modo, podemos comprobar, por ejemplo, que el tetromino o pieza de mayor longitud (ver esquina inferior derecha) ocupa la posición (3, 4) o que el tetromino en forma de T ocupa la posición (1, 5) dentro de la matriz de leds. Para poder entender éste último caso, en el que las coordenadas de posición de la pieza corresponden a un led que no forma parte de la pieza en sí, es preciso detallar el modelo de pieza empleado. De igual modo que ocurre con el área de juego, vamos a modelar cada pieza como una matriz, la forma más simple de representarlas dada la naturaleza matricial del juego. Este modelo matricial de de pieza, para el que hemos incluido la Figura 9 a modo de ejemplo, queda definido por la altura y la anchura de la pieza que delimitarán a su vez el número de filas y columnas respectivamente de la matriz asociada (e.g. 3 filas y 2 columnas para la pieza en forma de T asumiendo la orientación en la que dicha pieza ha sido representada en la figura). Adicionalmente, dicha matriz nos permitirá representar el estado de cada uno de los leds comprendidos dentro del área de ocupación de la pieza. Concretamente, modelaremos cada una de las diferentes posiciones dentro de la matriz por medio de una variable binaria cuyo valor 1 o 0 representará respectivamente el encendido o apagado del led correspondiente. En este sentido, y a la vista del ejemplo presentado, es preciso destacar el empleo de un nuevo sistema de coordenadas auxiliar específico para cada pieza, cuyo origen, por coherencia, hemos hecho coincidir nuevamente con la esquina superior izquierda de la matriz y, por tanto, con las coordenadas de posición de la pieza dentro del área de juego (e.g. la posición (1, 5), columna 1 y fila 5, en la matriz de leds del tetromino en forma de T corresponde a la posición (0, 0) de la matriz o área de ocupación asociada a dicha pieza). De este modo podremos referenciar y recorrer fácilmente las diferentes posiciones del área de ocupación de la pieza. Tal y como puede observarse, todas las coordenadas incluidas en la figura están referidas a dicho origen de coordenadas. Figura 9. Modelo matricial de pieza: área de ocupación de la pieza. 27 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 Naturalmente, cada matriz debe tener unas dimensiones inferiores al propio área de juego (i.e. matriz de leds) que aseguren la correcta disposición en el mismo de la pieza más grande que queramos definir (al menos cuando el tablero se encuentre vacío). No obstante, tal y como puede comprobarse, este requisito no supondrá inconveniente alguno en el caso que nos ocupa, dadas las dimensiones de la pieza más grande y de la matriz de leds. Igualmente, y por simplicidad, podremos definir todas las matrices de ocupación correspondientes a los diferentes tipos de pieza con el mismo tamaño, NxN, siendo N la mayor altura, o anchura, de cualquiera de las piezas consideradas (e.g. 4x4). En relación al caso particular de los movimientos de rotación, es preciso destacar dos decisiones de diseño especialmente importantes desde el punto de vista de la implementación de nuestro sistema: • En primer lugar asumiremos que ningún movimiento de rotación afectará en modo alguno a la posición de la pieza. • En segundo lugar, extenderemos el modelo matricial de pieza para dar cabida a las diferentes formas (i.e. rotaciones) que una misma pieza podrá presentar dependiendo del giro o de la orientación de la misma con respecto a una orientación de referencia y a la base del área de juego (i.e. eje x o de abcisas). De este modo, para ejecutar la rotación de una determinada pieza simplemente será necesario llevar a cabo la oportuna actualización de la matriz de ocupación de la pieza encendiendo y apagando los leds correspondientes según la rotación elegida. En la Figura 10 hemos presentado un posible modelo con las sucesivas rotaciones para una de las piezas en forma de J. Una implementación bastante sencilla del modelo de rotaciones pasa por definir 4 matrices de ocupación para cada pieza, una por cada una de las posibles rotaciones que puede adoptar cada pieza. De ese modo, cada movimiento de rotación simplemente supone elegir en cada caso la matriz correspondiente a la rotación escogida. Nótese que para algunas piezas el número de rotaciones o matrices necesarias puede ser inferior, como ocurre para la cuadrada cuyas sucesivas rotaciones no alteran la forma de la pieza (o cuyas 4 matrices de rotación son exactamente iguales, según se mire). En cualquier caso este hecho no debe afectar al diseño toda vez que la implementación resulta más sencilla considerando que disponemos de 4 matrices para cada pieza (a pesar de que algunas puedan ser exactamente iguales). 5.3.2.5 Modelo dinámico orientativo del objeto Leds Asumiendo que será responsabilidad exclusiva del objeto Juego la oportuna actualización de la matriz asociada al área de juego, el modelo dinámico del objeto Leds resulta bastante sencillo. Este modelo está basado en la lectura o consulta de dicha matriz con objeto de aplicar sucesivamente el barrido de excitaciones necesario para que cada columna de leds pueda encenderse y apagarse hasta 50 veces por segundo, produciéndose la ilusión de que los leds de varias columnas están encendidos a la vez, cuando realmente en cada instante de tiempo, sólo están siendo excitados los leds de una determinada columna. 28 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 x x y 1(0,0) 1(1,0) 0(2,0) 0(3,0) 1(0,0) 0(1,0) 0(2,0) 0(3,0) 1(0,1) 0(1,1) 0(2,1) 0(3,1) 1(0,1) 1(1,1) 1(2,1) 0(3,1) 1(0,2) 0(1,2) 0(2,2) 0(3,2) 0(0,2) 0(1,2) 0(2,2) 0(3,2) 0(0,3) 0(1,3) 0(2,3) 0(3,3) 0(0,3) 0(1,3) 0(2,3) 0(3,3) y a) Rotación 1. b) Rotación 2. x y x 0(0,0) 1(1,0) 0(2,0) 0(3,0) 1(0,0) 1(1,0) 1(2,0) 0(3,0) 0(0,1) 1(1,1) 0(2,1) 0(3,1) 0(0,1) 0(1,1) 1(2,1) 0(3,1) 1(0,2) 1(1,2) 0(2,2) 0(3,2) 0(0,2) 0(1,2) 0(2,2) 0(3,2) 0(0,3) 0(1,3) 0(2,3) 0(3,3) 0(0,3) 0(1,3) 0(2,3) 0(3,3) c) Rotación 3. y d) Rotación 4. Figura 10. Modelo de rotaciones para las piezas. En particular, y mientras dure la partida, será necesario recorrer cíclicamente un autómata en anillo de 4 estados (4 es el número de columnas de leds). Cada columna estará iluminada durante 5 ms y a continuación se pasará a iluminar la siguiente columna. Una vez finalizado el periodo de excitación correspondiente a la última columna daremos comienzo nuevamente a un nuevo periodo de excitación de la primera. Será el contenido de la matriz asociada al área de juego el que determinará el conjunto de leds que es preciso iluminar en cada momento. En la Figura 11 hemos incluido a modo de ejemplo el esquema de excitaciones correspondiente a cada una de las etapas o estados del barrido necesario para refrescar la matriz de leds. En este ejemplo hemos asumido el mismo estado de ocupación de la matriz presentado anteriormente. El proceso a seguir para cada una de las 4 columnas puede resumirse de la siguiente manera: • recorreremos la columna de la matriz que estemos procesando (i.e. x), aquella que sea objeto de la excitación, comprobando las posiciones correspondientes a las diferentes filas (i.e. (x, 1), (x, 2),…), • sólo en caso de que la posición (x, y) contenga un valor 1 significará que debemos iluminar el led asociado a la misma. 29 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 a) Excitación de la primera columna. b) Excitación de la segunda columna. c) Excitación de la tercera columna. d) Excitación de la cuarta columna. Figura 11. Refresco de la matriz de leds. 30 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 De este modo, podemos comprobar cómo para la excitación de la primera columna en el ejemplo, cuya duración será de exactamente 5 ms, solamente es preciso excitar o iluminar los leds ubicados en las filas F3, F4, F6, F7, y F8 (o lo que es lo mismo, los leds ubicados en las posiciones (0, 2), (0, 3), (0, 5), (0, 6) y (0, 7) de la matriz empleando nuestro sistema de coordenadas). 5.3.2.6 Modelo dinámico orientativo del objeto Juego La función principal del presente objeto es aplicar en todo momento las reglas de juego ante los sucesivos movimientos de piezas llevados a cabo por el jugador. Así mismo, será igualmente el que decida acerca de la necesidad de añadir una nueva pieza al juego o de dar éste por finalizado. Para la adecuada gestión de cualquier movimiento que pueda experimentar una determinada pieza, resulta indispensable introducir el concepto de “colisión”. 5.3.2.6.1 ¿Qué es una colisión? Asumiremos que se produce una colisión toda vez que, bien como consecuencia de la propia caída de la pieza o bien al realizar algún movimiento de traslación o rotación de la misma: • dicha pieza adquiera una posición que exceda o rebase los límites definidos para el área de juego (i.e. colisión con los límites del área de juego). • o que la pieza adquiera una posición que ya estuviera anteriormente ocupada por otra pieza (i.e. colisión con otras piezas). 5.3.2.6.2 ¿Cómo gestionamos un movimiento? La clave de cualquier movimiento, ya sea de traslación o rotación, a la derecha o a la izquierda, e incluso de la propia caída de la pieza, está en la necesaria comprobación de su viabilidad, comprobación que debe realizarse previamente a la ejecución del mismo para evitar así las mencionadas colisiones. Desde este punto vista, el protocolo o secuencia de acciones necesaria para la gestión de todo movimiento de pieza puede resumirse fácilmente de la siguiente manera: • Asumiendo que el objeto Teclas ya nos ha proporcionado información acerca del movimiento específico solicitado por el jugador, en primer lugar realizaremos una copia de la pieza que es objeto del movimiento. Para mayor claridad nos referiremos a dicha pieza como piezaActual, y a la copia como piezaAuxiliar. Un posible prototipo de función que nos permitiese realizar tal copia podría tener el siguiente aspecto: CopiarPiezaTetris (Juego->piezaActual, &(Juego->piezaAuxiliar)); • A continuación, podemos proceder a borrar piezaActual del área de juego actualizando convenientemente la matriz asociada (i.e. apagando los leds correspondientes, es decir, escribiendo un 0 en las posiciones ocupadas por la pieza). Este borrado podría encontrar su equivalente en la supuesta acción de levantar la pieza del tablero de juego (con el objetivo final de probar una nueva ubicación para la misma). Un posible prototipo de función que nos permitiese realizar tal borrado podría tener el siguiente aspecto: BorrarPiezaTetris (Juego->piezaActual, &Leds->matrizAreaJuego); 31 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 • Acto seguido actualizaremos las coordenadas de posición de la copia piezaAuxiliar según el movimiento solicitado, movimiento que en caso de producirse, por ejemplo, hacia la derecha podría expresarse del siguiente modo: Juego->piezaAuxiliar.posicion_X = Juego->piezaAuxiliar.posicion_X + 1; • Una vez actualizada la posición de piezaAuxiliar es el momento de comprobar si la nueva ubicación de la pieza da lugar a colisión alguna. Si el resultado de la comprobación es negativo daremos el movimiento por válido y sólo nos restará actualizar las nuevas coordenadas de posición de piezaActual. Esta copia podría encontrar su equivalente en la supuesta acción de colocar la pieza en la ubicación ensayada dentro del tablero de juego. En caso de producirse una colisión, asumiremos que el movimiento no puede llevarse a cabo, y por tanto que la pieza debe permanecer en su posición original. Para conseguirlo simplemente bastará con volver a pintar piezaActual, tal y como veremos en el siguiente paso. Ambas acciones, la comprobación y la posible copia, podrían tener el siguiente aspecto: if (posibleMoverPieza (Juego->piezaAuxiliar, Leds->matrizAreaJuego)) { CopiarPiezaTetris (Juego->piezaAuxiliar, &(Juego->piezaActual)); } • Finalmente, tanto si el movimiento resulta posible como si no, el último paso consistirá en volver a pintar la pieza (i.e. encendiendo los leds correspondientes, es decir, escribiendo un 1 en las posiciones, en este caso definitivas, ocupadas por la pieza). Un posible prototipo de función que nos permitiese realizar tal borrado podría tener el siguiente aspecto: PintarPiezaTetris (Juego->piezaActual, &Leds->matrizAreaJuego); 5.3.2.6.3 ¿Cuándo añadir una nueva pieza o dar por finalizado el juego? En este sentido resultan particularmente importantes las colisiones que puedan producirse ante un eventual movimiento hacia abajo de la pieza (provocado por el usuario o simplemente debido a la propia caída de las piezas). En caso de que no resulte posible mover hacia bajo la pieza (por producirse una colisión) comprobaremos la posición de la pieza. Si la coordenada y correspondiente resulta negativa, condición que coincidiría con una situación en la que el espacio disponible en el área de juego se ha agotado, daremos el juego por terminado. Para poder articular este procedimiento es fundamental la adecuada inicialización de la información de posición para cada una de las piezas que entre en juego. Una posible inicialización consistiría en asignar unas coordenadas iniciales (0, altura de la pieza para la forma u orientación por defecto + 1). Por el contrario, si no fuese posible mover hacia abajo la pieza (debido a una colisión bien con el fondo o límite inferior del área de juego, o bien con las últimas piezas colocadas sobre la misma) pero la coordenada y tuviese un valor comprendido dentro del área de juego, consolidaríamos la pieza en dicha posición y procederíamos sucesivamente a comprobar si es preciso eliminar alguna línea que haya podido completarse y a añadir una nueva pieza al juego. 32 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 La decisión en cuanto a qué nueva pieza debe incorporarse al juego podría tener un carácter aleatorio (como ocurre con la versión real del juego). No obstante, esta podrá simplificarse de tal modo que simplemente suponga recorrer circularmente el array o estructura de datos en memoria que contenga la información de los diferentes tipos de pieza incorporando sucesivamente una pieza distinta en cada ocasión. 5.3.2.6.4 ¿Cómo implementar el movimiento de caída de las piezas? A diferencia del resto de movimientos, la caída de las piezas no está controlada por el jugador. Ésta se produce de forma cíclica, discontinua y a intervalos regulares de tiempo (i.e. ritmo de caída de las piezas o tiempo límite que permanece una pieza, en ausencia de movimientos provocados por el jugador, en una misma línea antes de pasar a la siguiente) cuya oportuna medición correrá a cargo de una de las interrupciones periódicas habilitadas en nuestro sistema (i.e. objeto Relojes). Cada vez que la pieza en movimiento agote el tiempo máximo que puede permanecer en una misma línea (un valor razonable para el nivel de menor dificultad puede estar alrededor de 1 ó 2 segundos), deberá actualizarse la posición de la pieza ubicándola en la línea siguiente. Por lo tanto, nos encontraremos ante un caso particular de movimiento hacia abajo cuyo detonante será el timeout identificado por el objeto Relojes en lugar de la pulsación de la tecla correspondiente. Por lo demás, la gestión de dicho movimiento deberá realizarse exactamente en los mismos términos que hemos mencionado anteriormente en la sección 5.3.2.7.2 de este mismo documento. 5.3.2.7 Modelo dinámico orientativo del objeto Melodía Este objeto tiene almacenada la melodía que debe reproducirse durante el juego. Al dar comienzo el juego, se debe comenzar a reproducir la primera nota de la melodía (i.e. onda cuadrada cuya frecuencia será igual al primer valor especificado en la secuencia de frecuencias definida para la melodía). Dicha nota se reproducirá durante el tiempo especificado por su duración correspondiente (información especificada en la secuencia de duraciones). Cuando el tiempo de reproducción de dicha nota llegue al tiempo especificado por la melodía, la nota actualmente reproducida pasará a ser la siguiente nota de la secuencia de notas a reproducir. Cuando se haya acabado de reproducir la última nota, se deberán llevar a cabo las gestiones oportunas para poder reproducir nuevamente la melodía desde el comienzo. Así mismo, una vez finalizado el juego deberá finalizarse igualmente la reproducción de la melodía. 5.3.3 Estructura obligatoria de procesos Frecuentemente, los sistemas electrónicos digitales precisan realizar diversas acciones de una manera paralela (concurrente en varios procesadores) o aparentemente paralela (ambas acciones se ejecutan entrelazadamente, produciéndose la apariencia de paralelismo si la frecuencia de conmutación entre ambas es elevada). Son los denominados procesos. La creación, ejecución, sincronización y destrucción entre procesos suele ser facilitada por el sistema operativo a través de diversas primitivas. Pero incluso en ese caso, el diseñador debe definir qué tareas o rutinas serán concurrentes, elegir los mecanismos de comunicación entre ellas, los tiempos de vida, etc. En el LSED no disponemos de un gran sistema operativo en nuestra placa de desarrollo, pero podemos definir varios procesos por medio de interrupciones periódicas, interrupciones externas y el programa principal. 33 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 En la Figura 12 se muestra el esquema de procesos propuesto para esta práctica. Dicho esquema comprende 3 procesos: el programa principal y dos interrupciones periódicas. Este esquema de procesos es obligatorio. Se puede observar que las funciones asociadas a un mismo objeto no se ejecutan necesariamente en un mismo proceso. Sobre los mecanismos de sincronización en el LSED, recomendamos la lectura del apartado 4.1.6 “Desarrollo de software de tiempo real” de [3]. Como en nuestro caso las interrupciones periódicas pueden interrumpir la ejecución del programa principal en instantes de tiempo que resultan imprevisibles cuando se escribe el código, si el programa principal necesita modificar un objeto compartido, procederá a deshabilitar las interrupciones, realizar la modificación y volver a habilitar las interrupciones. Todo este conjunto de operaciones puede encapsularse en el objeto puerto. Como el programa principal no puede interrumpir a las propias interrupciones, estas últimas no necesitan realizar ninguna operación especial. Como las TRAP son excepciones software, se ejecutan en instantes de tiempo predecibles y se puede evitar que interrupciones y programa principal las usen a la vez. En cualquier caso, el nivel de las interrupciones temporizadas debe ser inferior a 7, porque el nivel 7 no es enmascarable y dificulta mucho la depuración (la ejecución de la rutina de atención a la interrupción puede ser a su vez interrumpida por una nueva petición de interrupción). Si el nivel es 7, aunque pongamos un punto de parada en la rutina de atención a la interrupción y el programa aparentemente se detenga al llegar a él, la generación y atención de interrupciones no se detiene y nuestro programa sigue ejecutándose de una manera indeseada y difícil de predecir. 5.3.3.1 Proceso principal El proceso principal siempre existe y debe: inicializar los objetos del sistema, inicializar el HW, habilitar la aparición de interrupciones e inicializar ambos procesos de interrupción periódica (_init). Los sistemas empotrados de tiempo real suelen contener un bucle indefinido (bucleMain) que puede llevar a cabo tareas sin requisitos temporales estrictos, como puede ser en nuestro caso la lectura del teclado y la presentación en pantalla de los menús. Los resultados finales se pueden mostrar en la rutina de atención a la interrupción porque en ese momento se ha terminado la reproducción y visualización de la melodía y ya no pueden ser retardados por la impresión en pantalla. Figura 12. Representación temporal de los 3 procesos. 34 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 En nuestro caso el bucle del programa principal podría ser aproximadamente: BucleMain: while (true) if (estado.jugando==false) estado.menús() estado.jugando=true else if (tecla.leer(relojes,puerto)==TECLA_VALIDA_JUEGO) resultado.actualizarTecla(tecla) endif endif endwhile La rutina general de inicialización sería similar a: Init: swInit() hwInit() * inicializa todos los objetos/variables SW * inicializa las interrupciones y los puertos Este proceso principal es el menos prioritario de los tres porque el teclado o la escritura en la pantalla no son acciones tan críticas en el tiempo. 5.3.3.2 Primera interrupción periódica Contendrá las funciones críticas en el tiempo relacionadas con el refresco de los leds y la caída de las piezas, en particular: • Actualizar los relojes (i.e. contadores de tiempo) correspondientes. • Si estado.jugando==true o Si se ha agotado el tiempo de excitación de la columna actual de leds, Pasar a la siguiente columna. o Si se ha agotado el tiempo de permanencia en la línea actual, Mover la pieza hacia abajo. Su ejecución es cíclica, discontinua y sucede a intervalos regulares de tiempo; es concurrente con el proceso principal y la otra interrupción periódica. Sin embargo, sólo debe poder interrumpir al programa principal, no así a la otra interrupción periódica cuya prioridad, por razones que explicaremos posteriormente, será mayor. Por tanto, esta última sí que podrá interrumpir a la que ahora nos ocupa. Esta interrupción será la encargada de controlar la relacionada con el refresco de la matriz de leds, refresco del funcionamiento. Por esta razón, este proceso debe tener principal. Adicionalmente, también será la encargada de la el movimiento de caída de las piezas. parte de temporización del sistema cual depende directamente su correcto mayor prioridad que el programa temporización necesaria para articular 35 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 En nuestro sistema la rutina de atención a la interrupción periódica podría ser similar a: InterrupcionPeriodica1: guardarRegistros() interrReset() relojes.actualizar() if (estado.jugando==true) if (relojes.tiempoExcitacionColumna==PERIODO_REFRESCO_MATRIZ) leds.excitarSiguienteColumna() relojes.tiempoExcitacionColumna=0 endif if (relojes.tiempoCaidaPieza==PERIODO_CAIDA_PIEZA) relojes.tiempoCaidaPieza=0 juego.muevePiezaAbajo() endif endif restaurarRegistros() RTE 5.3.3.3 Segunda interrupción periódica Contendrá funciones críticas desde el punto de vista temporal, en este caso relacionadas con la correcta gestión de la reproducción de la melodía durante el juego. En particular las de: • Actualizar los relojes (i.e. contadores de tiempo) correspondientes. • Si estado.jugando==true o Si se ha terminado de reproducir una nota, Pasar a la siguiente nota. o Si es la última nota, Pasar a la primera nota. Su ejecución es cíclica, discontinua y sucede a intervalos regulares de tiempo. Es concurrente con el proceso principal y la otra interrupción periódica, procesos a los que debe poder interrumpir (pero por los que no puede ser interrumpida). Es el proceso con mayor prioridad de los tres. Esta interrupción es la encargada de controlar la temporización necesaria para gestionar la adecuada duración de cada una de las notas que componen la melodía de juego. Respecto a la prioridad asignada a cada una de las interrupciones periódicas, debe tenerse en cuenta el siguiente criterio: dados dos procesos cualesquiera deberá tener mayor prioridad aquél cuya interrupción requiera una oportuna respuesta o debida atención más inmediata. Desde este punto de vista, esta última interrupción es la que deberá tener mayor prioridad de las dos. El retardo debido a las acciones necesarias para llevar a cabo el refresco de los leds (i.e. operaciones de escritura en el puerto de salida) puede provocar que la melodía no se escuche correctamente (e.g. provocando que las notas tengan una duración aparente mayor de la que en realidad les corresponde). Sin embargo, el retardo debido a las operaciones necesarias para poder gestionar la reproducción de las notas (i.e. parar y arrancar el timer correspondiente para la generación una onda cuadrada de la frecuencia requerida según la nota) no debe suponer problema alguno en cuanto al oportuno refresco de la matriz de leds (visualmente imperceptible en cualquiera de los casos). 36 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 En nuestro sistema la rutina de atención a esta interrupción periódica podría ser similar a: InterrupcionPeriodica2: guardarRegistros() interrReset() relojes.actualizar() if (estado.jugando==true) if (relojes.tiempoNota==melodias.notaActual.duracion) relojes.tiempoNota=0 if (melodias.terminada==true) melodias.notaActual=0 melodias.terminada=false else melodias.siguienteNota() endif endif endif restaurarRegistros() RTE 5.4 Modelo de implementación orientativo 5.4.1 Codificación Una vez que, tras el diseño, disponemos de los modelos estáticos y dinámicos, llega el turno de convertir nuestras ideas y modelos en código ejecutable, y la dependencia del lenguaje de programación es completa. Las normas de codificación en ensamblador de rutinas con paso de parámetros, se pueden encontrar en [3] y en el libro de SEDG [7]. A la hora de codificar debe tener en cuenta los criterios de calidad establecidos en la asignatura: • La estructura general del programa en ensamblador debe responder a lo comentado en la sección 4.1.2 de [3]. • Cada subrutina debería tener un único punto de comienzo y un único punto de terminación, y no debería entrelazarse con otras subrutinas (según se comenta en el documento “Dudas y preguntas frecuentes del LSED”). Sí que es conveniente que las rutinas se aniden (una rutina llame a otra para realizar una cierto cálculo y al terminarse la segunda rutina, pueda continuar la ejecución de la primera). • Debería emplear un buen número de rutinas (subrutinas, métodos o funciones), que le ayuden a dividir cada problema en subproblemas, y que no resulten muy extensas (y por lo tanto difíciles de entender y depurar). Algunas rutinas recomendadas se han ido incluyendo a lo largo de este enunciado. Si pensamos en una media de casi 3 métodos por objeto, 25 rutinas parece un número mínimo exigible para esta práctica. • Debe emplear constantes EQU o #define que permitan reconfigurar fácilmente el sistema (las instrucciones no deberían usar números mágicos). Ejemplos típicos podrían ser: o Una constante que permita fácilmente variar la frecuencia de las interrupciones temporizadas (FREQ_INT EQU ... o bien #define FREQ_INT...). 37 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 o Una constante para modificar el retardo antirrebotes del teclado (RET_REBOT EQU... o bien #define RET_REBOT...). • Debe emplear modos de direccionamiento variados y apropiados (indexado, indirecto, post-incremento...) y usar estructuras de datos que agrupen datos interrelacionados y que faciliten la implementación (búferes, tablas de valores...). Emplear estas técnicas suele producir código más compacto y elegante, evitándose frecuentemente el abuso de la desaconsejable técnica de “copiar, pegar y modificar”. • Debe incluir comentarios orientativos en el código (comentarios que aporten información al que los lea, no que se limiten a parafrasear el código). Un ejemplo paradigmático de un mal comentario es: o ADD.L #1,D0 * incrementa el registro D0 • Debe emplear typedef, struct, switch para producir soluciones elegantes, en C. Por cada objeto debería haber al menos un typedef y un struct. Por ejemplo: typedef struct { WORD frecuencias[MAX_NUM_NOTAS]; WORD duraciones[MAX_NUM_NOTAS]; ... } Tmelodia; typedef struct { Tpieza piezas[MAX_NUM_PIEZAS]; ... } Tpiezas; • Un empleo abundante y adecuado de #include para dividir el código en subsistemas coherentes, en C. Al menos debería haber al menos un #include por objeto. Con este propósito le resultarán de utilidad las plantillas para la creación de un nuevo archivo .c o de un nuevo archivo .h disponibles en la web de la asignatura [17]. • Debe emplear pocas variables globales, sobre todo en C. Sólo parece haber 4 objetos globales: estado, relojes, puerto y resultados. Para minimizar las variables globales debe: o usar variables static locales a los métodos o funciones en C, para que esas variables sólo puedan ser usadas por ese método, pero no sean variables locales que se pierdan al terminar la ejecución de la rutina, y que así en la siguiente ejecución de la rutina, mantengan el valor que tenían al acabar la anterior ejecución: void rutinaInterrupcionConStaticLocal() { static Tmelodias melodias=...; ... } o pasar parámetros a los métodos o funciones en C: por valor (si el parámetro no va a ser variado por la rutina) o por referencia (en caso contrario). 38 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 rutinaCopiaParam(int paramPorValor,int *paramPorRefer) { * parametroPorReferencia= parametroPorValor; ... } • el empleo de punteros y arrays en C es recomendable para acceder a estructuras de datos complejas de una manera elegante. Por ejemplo, los arrays de frecuencias y duraciones antes mostrados en la Tabla 1. • No se debe emplear goto, en C. • Etc. 5.4.2 Ejemplo de una posible implementación del objeto relojes Dado que los lenguajes de programación disponibles en este laboratorio no son orientados a objetos, su implementación requiere seguir una cierta metodología. 5.4.2.1 Declaración de un objeto: tipo y variable Cada objeto puede ser implementado como un struct en C que contiene todos los datos, o implementarse como un conjunto de datos en ensamblador. Hemos elegido una implementación incrementando contadores, aunque sería perfectamente posible implementar los relojes por medio de contadores que decrementan. typedef struct { int iTiempoNota; // contador para la duración de cada nota int iTiempoDisplay; // contador de refresco de leds cada 5 ms int iTiempoCaidaPieza; // contador para el tiempo de caída de cada pieza … } Trelojes; Hay que declarar un objeto de tipo Trelojes, en el ámbito adecuado. Si consideramos que Trelojes es un objeto global porque debe ser consultado por el programa principal y las interrupciones, al comienzo de nuestro programa, en la zona de variables globales incluiremos: // objeto que permite contar el tiempo para las notas musicales // y para el refresco de los leds Trelojes relojes; 5.4.2.2 Implementación de cada método Los métodos de cada objeto, tendrán un nombre que comenzará con el nombre del objeto, un guión bajo y el nombre del método. El primer parámetro de cada método será un puntero al objeto, para poder leer sus datos y modificarlos. // número de interrupciones en cada milisegundo #define INTERR_POR_MS 1 // poner a 0 todos los contadores de tiempo void relojes_reset(Trelojes *pRelojes) { pRelojes->iTiempoNota=0; 39 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 pRelojes->iTiempoDisplay=0; … } // configurar las interrupciones periódicas // y poner a 0 todos los contadores de tiempo void relojes_inic(Trelojes *pRelojes) { relojes_reset(pRelojes); … } // incrementa todos los contadores de tiempo void relojes_actualizar(Trelojes *pRelojes) { // cada milisegundo pRelojes->iTiempoNota++; // incrementamos los tiempos en ms pRelojes->iTiempoDisplay++; … } Cuando sea necesario llamar a un método del objeto relojes se hará como indica: relojes_inic(&relojes); 5.4.2.3 Implementación como objeto local del programa principal o de la rutina de interrupción Si sólo se accediese al objeto desde la rutina de atención a la interrupción o desde rutinas llamadas por ella, no se debería declarar el objeto como global sino como local a la rutina de atención. #include “m5272lib.h” // definición del tipo BOOL y sus constantes void rutina_tout0(void) { static BOOL bPrimeraEjecucion=TRUE; static Trelojes relojes; … // inicializa todos los objetos static sólo la 1ª vez if (bPrimeraEjecucion==TRUE) { relojes_inic(&relojes); … bPrimeraEjecucion=FALSE; } … relojes_actualizar(&relojes); } 5.4.3 ¿Cómo modificar un bit del puerto de salida? En esta práctica, sólo 2 de los 3 procesos deben usar el puerto: el programa principal y la primera interrupción periódica encargada del refresco de los leds, aunque usen bits diferentes del mismo. Como los dos procesos se ejecutan aparentemente en paralelo, si no se tiene cuidado, puede haber conflictos entre ellos, llegando al extremo de que un proceso modifique sin querer los bits o los datos correspondientes a otro. 40 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 Tabla 3. Detalle de las diferentes conexiones al puerto de salida. Puerto de salida 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Conexión F7 F6 F5 F4 F3 F2 F1 F0 C3 C2 C1 C0 T3 T2 T1 T0 En los tutoriales de C se emplea la rutina set16_puertoS(), para enviar un valor de 16 bits al puerto de salida (la rutina equivalente en ensamblador hará aproximadamente un MOVE.W del dato de 16 bits a la dirección del puerto). Sin embargo, como los puertos son unidireccionales, el puerto de salida no puede ser leído. Esto implica que en ensamblador no se puede modificar correctamente un bit del puerto de salida directamente haciendo un BSET, BCLR o BCHG de un bit del puerto, porque estas instrucciones implican leer y escribir en el puerto. En C, no se puede aplicar una máscara AND (operador &) u OR (operador |) directamente al puerto para modificar un bit. En ambos casos es necesario emplear una variable auxiliar (lo que denominamos objeto Puerto). Supongamos que los 4 bits menos significativos (0-3) se emplean para excitar las columnas T0T3 del teclado (como se explica en el tutorial del mismo), los bits 4-7 para excitar las columnas C0C3 de la matriz de leds, y que se emplean los bits 8-15 del puerto para excitar las filas F0-F7 de la matriz. Cada vez que el teclado quisiese excitar una de sus columnas (si se realizase el barrido), debería poner un 1 en el bit correspondiente a esa columna del teclado, y un 0 en los otros 3 bits relacionados con el teclado, respetando el valor que tuviesen los bits relativos a los leds. Si, por ejemplo, se quiere excitar la columna 0 del teclado (T0), y se envía un 0x0001 al puerto, se comete un error: además de excitar la columna adecuada, se están poniendo a 0 todos los bits que tienen que ver con los leds, con la posible alteración del buen funcionamiento de la parte de visualización. Para poner a 1 el bit de una columna del teclado (T0-T3), lo recomendado en ensamblador sería realizar el BSET, BCLR o BCHG, sobre un registro que contiene el valor de la variable auxiliar Puerto_variable (que contiene el último valor enviado al puerto), para a continuación actualizar la variable auxiliar y enviar esa variable modificada al puerto. Tenga en cuenta que el puerto (y por lo tanto la variable auxiliar) es de 16 bits, pero las funciones BSET, BCLR o BCHG, no pueden modificar directamente una variable .W en una sola instrucción: PUERTO_S EQU $40000002 Puerto_variable DC.W * DIRECCION DEL PUERTO S 0 * esta rutina recibe a través de D0 el número del bit que poner a 1 PUERTO_SET_BIT: MOVE.L D1,-(A7) MOVE.W Puerto_variable,D1 BSET.L D0,D1 MOVE.W D1,Puerto_variable MOVE.W D1,PUERTO_S MOVE.L (A7)+,D1 RTS Para poner a 1 el bit de una columna del teclado (T0-T3), lo recomendado en C sería: #define MASCARA_TECLADO 0xFFF0 // asigna 0 a cada bit del teclado #define EXCIT_TECLADO 0x0001 typedef struct { WORD variableAux; // variable básica del objeto puerto … } TpuertoSalida; 41 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 TpuertoSalida puerto; // numColumna es la columna del teclado que excitar: 0, 1, 2 o 3 void puerto_excitaColumnaTeclado(int numColumna) { … // falta comprobar que numColumna<4 // tiene un 1 en el bit de cada una de las columnas del teclado static WORD excitaTeclado[]={0x1,0x2,0x4,0x8}; // suponemos que variableAux contiene el último dato enviado al puerto // borra sólo los bits del teclado puerto.variableAux= puerto.variableAux & MASCARA_TECLADO; // pone a 1 el bit adecuado en función de numColumna puerto.variableAux= puerto.variableAux | excitaTeclado[numColumna]; set16_puertoS(puerto.variableAux); // envía el nuevo valor al puerto … } Supongamos que los bits de las filas deben estar a 0 si queremos que la fila correspondiente se encienda (de acuerdo con la Figura 3). Apagar los leds de todas las filas salvo la fila 0 (F0) supone poner a 0 el bit de la fila 0, poner a 1 los otros 7 bits de filas, y no alterar los bits del teclado o las columnas: #define MASCARA_FILAS 0xFF00 // asigna 1 a cada bit de filas F0-F7 #define MASCARA_F0 0xFEFF // asigna 1 al bit de la fila F0 void puerto_fila0Encender(void) { // suponemos que variableAux contiene el último dato enviado al puerto // pone a 1 los bits de filas puerto.variableAux = puerto.variableAux | MASCARA_FILAS; // pone a 0 el bit adecuado puerto.variableAux = puerto.variableAux & MASCARA_F0; set16_puertoS(puerto. variableAux); // envía el nuevo valor al puerto } Supongamos que para poder encender leds de una columna debemos poner a 1 el bit correspondiente del puerto (de acuerdo con la Figura 4). Como sólo una de las columnas puede estar activa a la vez, los demás bits de columnas deben estar a 0, y para encender la segunda columna (C1) sin alterar las filas o el teclado podríamos escribir en C: #define MASCARA_COLUMNAS 0xFF0F // vale 0 en los bits de columnas C0-C3 #define MASCARA_C1 0x0020 // vale 1 en el bit de la columna C1 void columna1Activar(void) { // suponemos que variableAux contiene el último dato enviado al puerto // pone a 0 los bits de todas las columnas puerto.variableAux= puerto.variableAux & MASCARA_COLUMNAS; // pone a 1 el bit adecuado puerto.variableAux = puerto.variableAux | MASCARA_C1; set16_puertoS(puerto.variableAux); // envía el nuevo valor al puerto } 42 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 5.4.4 Optimización Aunque la optimización del código (en cuanto a consumo de memoria o de tiempo de CPU) no se puede llevar a cabo hasta la fase de implementación, un mal diseño o una mala arquitectura pueden hacer imposible esta labor en la fase de implementación, obligando a una reconsideración del diseño. Así, si nuestra arquitectura intentase actualizar el visualizador o generar las notas de audio desde el programa principal, los requisitos de temporización de estas tareas serían muy difíciles de cumplir y se podría producir un funcionamiento incorrecto: al tratarse de un defecto estructural, cualquier optimización puede estar condenada al fracaso si no revisamos la arquitectura. Aunque éste no es nuestro caso (y la arquitectura propuesta puede satisfacer los requisitos del enunciado), dado que en el LSED las prácticas son de tiempo real, no es extraño que el alumno se vea obligado a emplear una o varias de estas estrategias de optimización para conseguir solucionar el problema planteado por el enunciado. 5.4.4.1 Optimización de pequeñas rutinas en C Si una rutina es pequeña se pierde más tiempo en el proceso de entrar y salir de la rutina, que en ejecutar la rutina propiamente dicha. En estos casos puede ser interesante definirla como inline y activar un nivel de optimización del compilador distinto de 0, de tal manera que el compilador no genera una verdadera rutina y una verdadera llamada a rutina (con paso de datos a través de registros o de la pila), sino que simplemente inserta el código equivalente en el lugar donde se llamaría a la rutina, con el consiguiente ahorro de tiempo de ejecución. Por ejemplo: Trelojes relojes; // declaración del objeto // rutina que deseamos ejecutar rápidamente inline void relojes_reset(Trelojes *pRelojes) { pRelojes->iContadorBase=0; pRelojes->iTiempoNota=0; pRelojes->iTiempoDisplay=0; … } // rutina que invoca a la de puesta a 0 de relojes void otraRutina(void) { … relojes_reset(&relojes); … } El código optimizado generado por el compilador será equivalente a haber escrito directamente: // código equivalente “generado” por el compilador Trelojes relojes; // declaración del objeto void otraRutina(void) { … relojes.iContadorBase=0; relojes.iTiempoNota=0; relojes.iTiempoDisplay=0; 43 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 … } Aunque esta última implementación es más reducida y más rápida, escribirlo directamente así resulta mucho menos elegante en general, ya que el procesamiento del objeto relojes se realiza directamente sin utilizar métodos propios del objeto. Variaciones en el objeto relojes, por tanto, requerirían variar distintas partes del código y no únicamente los métodos del propio objeto relojes. 6. Descripción de la sesión -1 (antes de ir al laboratorio B-043) Aunque al principio le resulte tedioso, recomendamos al alumno que se tome su tiempo para formarse con los libros de apoyo al laboratorio publicados. Concretando algo más, debería leer, antes de empezar las sesiones del Laboratorio, al menos: • El tema 6 (de temporizadores) del libro de SEDG [9]. Prestar especial atención a la generación de interrupciones en tiempo real. • El libro de tutoriales de manejo de la plataforma ENT2004CF [3]. Como mínimo los tutoriales relacionados directamente con la práctica (temas 1, 2, 3, 4, 5, 7 y 8). • El tutorial de utilización y la ayuda para el entorno de desarrollo EDColdFire v3.0 [4], en especial el tema 3. • El capítulo 4 de [5]: con el epígrafe 4.1 y 4.2 de dicho manual le bastará. • El breve manual del Osciloscopio HAMEG HM-407 [6], en el caso de no haberlo manejado anteriormente. • Los documentos de Dudas y Problemas Frecuentes en ensamblador y en C [7][8]. También debería bajar de Internet el software EDColdFire (que incluye el ensamblador del MCF5272, y también el compilador GCC integrado para desarrollar la práctica en lenguaje C), y aprender a manejarlos en su casa. Estos programas, el manual del osciloscopio y el documento de dudas se encuentran disponibles a través del portal del LSED (http://lsed.die.upm.es/). Con el fin de aprovechar al máximo las sesiones en el Laboratorio, que son un recurso muy limitado, el alumno debe traerse los programas ya escritos de casa, donde los habrá ensamblado con EDColdFire para comprobar que el código no tiene errores de sintaxis. Durante la sesión de Laboratorio, el alumno volverá a ensamblar el programa y lo ejecutará en la plataforma ENT2004CF. Encontrará errores que ya no son de sintaxis, sino de ejecución, que corregirá en el Laboratorio: la labor de depuración es fundamental. No terminaremos este apartado sin mencionar algo obvio: el alumno debería conocer la arquitectura y el juego de instrucciones del procesador MCF5272. Recomendamos que para ello emplee la bibliografía de apoyo a la asignatura Sistemas Electrónicos Digitales como [9]. 6.1 Comentarios sobre las conexiones En relación a las diferentes conexiones con el puerto de salida deben tenerse en cuenta los siguientes aspectos: 44 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 • En el tutorial de utilización del EDColdFire [4] y en la ayuda del programa está dibujado el patillaje de los puertos; es decir, qué significa cada terminal de la plataforma (el dibujo está hecho tal como se ve el conector de la plataforma desde fuera, no hay que imaginárselo al revés o en espejo). • En el tutorial de la placa auxiliar del teclado y del LCD (TL04) (tema 7 de [3]) están igualmente disponibles los 16 terminales de entrada y los 16 de salida. Éstos están también disponibles en la web de la asignatura [18]. • En la placa auxiliar TL04, las entradas y salidas están numeradas de la misma manera que en los esquemas de entradas y salidas disponibles en web y en [3]. Uno de los conectores negros hembra de la placa TL04 está conectado a los pines 1-13 (ambas filas del mismo conector negro están redundantemente conectadas a los mismos pines) y el otro está conectado a los pines 14-25, también de manera redundante (el 26 del conector negro no está conectado). • En el futuro va a ser muy importante que la masa de la plataforma (disponible en los conectores DB25 y en la placa auxiliar) esté conectada a la masa de la fuente de alimentación (esto es, la masa debe ser única). Todos los terminales que se indican como masa en los conectores de la plataforma son el mismo punto (sólo necesitamos conectar uno de ellos). • Para las conexiones se deben usar tiras de 8x1 y 4x1 pines macho-macho planos, sin tornear, largos (25 mm), de 2,54 mm de paso. En la web de la asignatura se han publicado fotos sobre cómo conectar el HW de la práctica a la placa TL04 [19]. Estos sencillos conectores macho debéis soldarlos a vuestros cables y facilitarán las conexiones que hay que realizar cuando se llega al B-043 y que desconectar al irse. Conectar cables rígidos directamente a los conectores negros está totalmente desaconsejado, porque la conexión no es buena y provocará numerosos problemas. 7. Descripción detallada de la sesión 0 Para comenzar a abordar la Práctica en sí, el alumno tendrá dos primeras sesiones de Laboratorio introductorias en las cuales se familiarizará con el entorno de desarrollo Hardware (la plataforma ENT2004CF, aunque por motivos de seguridad, el alumno no conecta directamente su sistema al MCF5272, sino a una tarjeta de interfaz compuesta de un primer buffer digital, un conjunto de leds, una etapa de optoacopladores, y un segundo buffer digital), desarrollará el hito 1 y terminará de adquirir habilidad con el entorno de desarrollo EDColdFire (que, como bien sabe, debe haber usado previamente antes de ir al laboratorio B-043). Las partes de que se compone esta primera sesión de laboratorio son: • Realizar un pequeño tutorial inicial descrito en el capítulo 3 de [3]. • Realizar el tutorial de manejo del teclado del capítulo 7 [3]. Con este tutorial se pretende que el alumno conozca y aprenda el manejo del teclado disponible en la placa TL04 que utilizaremos como subsistema hardware de entrada de datos. De las 3 partes de las que se compone el tutorial de manejo de la placa TL04 sólo hay que realizar el tutorial de manejo del teclado, que permite imprimir en la pantalla del ordenador. 45 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 • Ejecutar, depurar y modificar un primer programa; este programa debe pedir al usuario que seleccione un nivel de dificultad (de entre los 3 posibles) pulsando una de las 3 teclas asignadas (i.e. 1, 4 o 7), y el programa debe generar un mensaje en pantalla informando del nivel de dificultad seleccionado. A continuación se solicitará al usuario la pulsación de la tecla A que debe dar comienzo al juego. Si la tecla pulsada fuese distinta, deberá presentarse un mensaje de error por pantalla advirtiendo al usuario de que la tecla que debe pulsar debe ser la A. Veamos un ejemplo de funcionamiento del programa. Sistema: Elija el nivel de dificultad del juego: (1) Fácil, (4) Medio, (7) Difícil. Usuario: Pulsa 1. Sistema: Nivel de dificultad seleccionado: Fácil. Pulse A para comenzar la partida... Usuario: Pulsa 1. Sistema: Tecla no válida. Por favor pulse A para jugar… 7.1 Método de trabajo En el PC de laboratorio, deberá crear un directorio de trabajo colgando de la carpeta “c:\alumnos” (carpeta para la que dispondrá de permisos de escritura). Ponga a ese directorio el nombre de su código de pareja de laboratorio (por ejemplo, MT23). Dentro de él vaya creando un directorio por cada sesión de acuerdo con el plan propuesto en el enunciado (sesion_1, sesion_2, etc.). Asegúrese de grabar los programas modificados en una memoria FLASH, o enviarlos por email al final de la sesión de trabajo. Para evitar problemas de copias no deseadas de su SW por parte de otros alumnos, al final de cada sesión debe borrar los ficheros .ASM, .C o .H que constituyan su práctica. Recuerde que se realizarán entregas electrónicas del SW y habrá verificación de plagios. Debe guardar al menos 2 copias en algún soporte (correo electrónico, memoria flash...). Recuerde que el contenido de los discos duros puede ser borrado como consecuencia de las tareas periódicas de mantenimiento del laboratorio. Trabajar directamente en un dispositivo de tipo pendrive con el EDColdFire en el B-043 puede dar problemas de compilación en algunos casos. Si sucede, se recomienda copiar los ficheros al disco duro (carpeta “c:\alumnos”), trabajar con ellos, y al acabar la sesión, copiarlos en el pendrive y borrarlos del disco duro. En todo caso, usar directamente este tipo de dispositivos ralentiza el proceso de compilación y ejecución. El modo correcto de abrir el programa EDColdFire es desde el menú de Inicio / Todos los programas, o desde el icono que se crea en el escritorio al instalar. 7.2 Tutorial inicial Viene descrito en el capítulo 3 de [4]. Fuera del laboratorio B-043 puede hacer algunos de los pasos que figuran en dicho libro. Como parte de este tutorial inicial se recomienda también la ejecución del programa Cochefantastico.asm. 46 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 En el laboratorio, el código fuente original de Cadena.asm y CocheFantástico.asm no se puede modificar, está protegido contra escritura. Para trabajar con él, haga una copia en su directorio de trabajo. Todos los tutoriales se encuentran en el directorio c:\archivos de programa\DIE-UPM\EDColdFire\tutoriales... 7.3 Tutorial del manejo del teclado de la placa TL04 Este tutorial viene descrito en el capítulo 7 de [3]. Con este tutorial se pretende que el alumno conozca y aprenda el manejo del teclado disponible en la placa TL04 que utilizaremos como subsistema hardware de entrada de datos. De las 3 partes de las que se compone el tutorial de manejo de la placa TL04 sólo hay que realizar el tutorial de manejo del teclado, que implementa la exploración del teclado y presenta en la pantalla del ordenador la tecla pulsada. 7.4 Diseño, implementación y prueba de un primer programa En la primera sesión el alumno debe completar su primer programa que permite elegir uno de los 3 niveles de dificultad. Para ello debe seguir la estructura que se comenta en los siguientes apartados. 7.4.1 Estructura básica de los programas que desarrolle A continuación incluimos el esqueleto del programa a desarrollar. Éste contiene las 5 partes de las que se habla en el apartado 4.1.2 de [5] y en [3]. Además, la nomenclatura que se sigue para nombrar las variables y subrutinas es la misma que la comentada en dicho manual. Con el símbolo <...> se representa algo que puede bien estar vacío, o ser una instrucción o un grupo de instrucciones que han sido omitidas. ************************************************* * ZONA DE CONSTANTES <...> ORG <valor> ************************************************* * ZONA DE VARIABLES GLOBALES <...> sinusoide DC.W … **************************************************** * PROGRAMA PRINCIPAL **************************************************** PPAL <...> * Modo supervisor. Inhabilita interrupciones <...> * Mueve el puntero de pila a una región válida BSR swInit * Subrutina configuración completa del SW BSR hwInit * Subrutina configuración completa del HW <...> * Habilita las interrupciones CPU BUCLE END BSR bucleMain BRA BUCLE PPAL * Bucle de programa principal. ************************************************* 47 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 * ZONA DE SUBRUTINAS <...> * Subrutina de configuración completa del hardware hwInit: <...> RTS * Subrutina de inicialización de las variables que lo necesiten swInit: <...> RTS * Subrutina que contiene el programa principal * cuya ejecución es típicamente periódica en el LSED bucleMain: <...> BRA FIN_MAIN ERROR: <...> FIN_MAIN RTS **************************************************** * ZONA DE RUTINAS DE ATENCIÓN A LAS INTERRUPCIONES **************************************************** * Rutina de atención a las interrupciones en el caso de * que sean necesarias INTERR: <...> FININTER RTE 7.4.2 Subrutina para configurar el HW (hwInit) En esta subrutina se deben incluir las acciones necesarias para configurar cada uno de los recursos hardware que se vayan a utilizar: interrupciones, puertos,... Hay que prestar especial atención a la configuración de recursos que comparten los mismos registros de configuración: por ejemplo las interrupciones periódicas y las interrupciones externas. Sea muy cuidadoso en la inicialización de estos registros. En relación con la frecuencia de las interrupciones periódicas se recomienda la configuración de estas interrupciones a una frecuencia de, por ejemplo, 1 KHz, a partir de la cual se puedan obtener fácilmente frecuencias menores para implementar los diferentes relojes que se necesitan a lo largo de la práctica. 7.4.3 Si tiene dudas o problemas... Se recomienda al alumno que, antes de empezar a trabajar, lea el documento de Dudas y Problemas Frecuentes del LSED, o su versión para programación en C. 7.5 Nociones sobre depuración de programas En este apartado se comentan algunas nociones interesantes para la depuración de programas. La depuración consiste en la búsqueda de errores durante el funcionamiento del programa, no durante la fase de ensamblado o compilación. En relación con los errores vamos a considerar cuatro tipos característicos: • NO sistemáticos y ocasionales: son errores que no siguen una sistemática a la hora de producirse, lo hacen de manera ocasional. Estos errores son los más complicados de detectar puesto que son difíciles de reproducir. 48 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 • NO sistemáticos pero frecuentes: aunque no siguen una sistemática, al ser frecuentes permiten reproducirlos fácilmente y definir un proceso de búsqueda. • Sistemáticos pero no frecuentes: en este caso al producirse bajo unas mismas condiciones, son errores fácilmente reproducibles y por tanto depurables. • Sistemáticos y periódicos: se producen de forma periódica y en la mayoría de los casos tienen que ver con el funcionamiento de las interrupciones periódicas. En los apartados siguiente describiremos un protocolo (o conjunto de pautas a seguir) de depuración o protocolo de búsqueda de errores aplicables en el caso de tener algún error de los últimos 3 tipos. Para el caso de errores no sistemáticos y ocasionales se ofrecerán algunos comentarios o pautas sobre las acciones de depuración que se pueden hacer para localizar el error. 7.5.1 PASO 1: Obtención de una prueba fallida y previsión de la salida En este primer paso se trata de verificar los casos de uso propuestos en el enunciado y obtener un conjunto de pruebas lo más concretas posibles para las cuales el sistema no se está comportando correctamente (según las especificaciones). Si el número de pruebas asociado a un caso de uso es pequeño (ej: pulsaciones sobre todas las teclas) se pueden realizar todas las pruebas (ej: pulsar todas las teclas y analizar comportamientos similares: entre teclas de la misma fila o columna por ejemplo). La información del tipo de error que producen unas u otras pruebas nos puede dar información muy valiosa a aplicar posteriormente en el segundo paso: localización del error. Una prueba fallida está compuesta de dos elementos imprescindibles: Un conjunto de entradas o acciones concretas (ej: pulsa la tecla C) que originan o producen una salida o un comportamiento erróneo. Realizar una previsión de cómo se debería comportar el sistema ante esas entradas o acciones (considerando el comportamiento correcto). Esta fase es la más laboriosa porque la previsión se debe realizar a bajo nivel (a nivel de registro, variable o cable), pero es imprescindible para garantizar el éxito en la localización posterior del error. 7.5.2 PASO 2: Localización del error Con la prueba fallida obtenida en el paso anterior, ejecutamos el programa (o circuito) y observamos algún efecto de salida del error (algún comportamiento erróneo). Un comportamiento erróneo se produce cuando hay un desajuste en ese punto del programa (o circuito) entre la previsión realizada y el valor obtenido o medido en una variable, registro o señal. Una vez detectado el comportamiento erróneo disponemos de dos puntos principales para comenzar el proceso de localización del error (búsqueda): • El punto de inicio: comienzo del programa, inicio de las señales de entrada,... • El punto final: lugar donde se detectó un desajuste entre la previsión para esa prueba y los valores reales de comportamiento. El proceso de búsqueda puede comenzar desde el punto de inicio (Forwardtracking) o desde el punto final (Backtracking). En ambos casos es necesario: 49 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 • Analizar las entradas y salidas de cada módulo. En el caso de “forwardtracking” si tanto las entradas como las salidas están bien (coinciden con la previsión) pasamos al siguiente módulo. En el caso de “backtracking” si tanto las entradas como las salidas están mal (no coinciden con la previsión) pasamos a analizar el módulo anterior. Cuando se detecta el módulo que está produciendo el error se comienza a analizar las diferentes partes del módulo utilizando las mismas estrategias de “forwardtracking” o “backtracking” en cada una de las partes hasta localizar una unidad atómica (indivisible, por ejemplo instrucción en programación o integrado en HW) donde las entradas están bien y las salidas mal. En este punto hemos localizado el error. 7.5.2.1 Comentarios adicionales Algunos comentarios adicionales aplicables al proceso de búsqueda del error: El proceso de localización del error requiere realizar varias ejecuciones del programa (o circuito) hasta determinar el módulo o bloque donde se encuentra dicho error. Es muy importante repetir las ejecuciones del programa realizando siempre la misma prueba. En algunos casos es difícil realizar la misma prueba pero se debe intentar reproducir las condiciones más parecidas posibles: por ejemplo, en el caso de probar pulsaciones largas de las teclas es complicado precisar en todos los casos la misma duración de la pulsación, pero se debe intentar que sea lo más parecida posible. Cuando se están analizando bloques grandes, la acción de depuración suele ser, ejecutar con puntos de parada (situados al comienzo y al final del bloque) e inspección de variables, registros o señales. Para analizar dentro de un bloque, la acción de depuración suele ser ejecutar con puntos de parada, paso a paso, e inspección de variables, registros o señales. El proceso natural es BACKTRACKING pero en muchos casos es muy difícil identificar el punto de final (punto donde la previsión y lo ocurrido son diferentes): un ejemplo es cuando un programa genera un segmetation fault sin poder ver dónde ocurre. En estos casos no hay más remedio que plantear una estrategia FORWARDTRACKING. Nota importante para el LSED: cuando ocurre un error hardware que deja al programa bloqueado, la opción más interesante para identificar el punto del final es mirar el contador de programa. En el caso de que este contador tenga un valor que no corresponde con ninguna dirección de nuestro programa, lo más probable es que el error se haya producido en la recuperación del contador de programa de la pila: tras RTS o RTE. La depuración de BUCLES puede ser muy laboriosa si el número de iteraciones del bucle es muy elevado. En primer lugar hay que ver si el error se produce en el bucle. En ese caso, el consejo es avanzar de varias en varias iteraciones utilizando la posibilidad que nos ofrecen los puntos de parada. A medida que nos vamos acercando al error vamos reduciendo el número de iteraciones que avanzamos y así hasta localizar la pasada del bucle que generó el error. 7.5.3 PASO 3: Determinación de la causa del error Una vez detectado el error se debe detectar la causa u origen de dicho error: una instrucción no válida, un modo de direccionamiento incorrecto, una variable sin inicializar,... 50 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 En este paso, al igual que en los anteriores, puede consultar al profesor, quien le dará las orientaciones oportunas para encontrar la explicación del error. 7.5.4 PASO 4: Corregir el error Una vez detectada la causa del error se debe corregir dicho error realizando un rediseño o reimplementación de esa parte del programa o circuito. Una vez realizada la modificación es necesario volver a probar el sistema con la misma prueba que nos permitió localizar el error. Si el error ha sido correctamente corregido y no había más errores adicionales, la prueba debe dejar de ser fallida y el sistema funcionará correctamente. NOTA: en el caso de que el alumno se encuentre bloqueado en la búsqueda del error se propone la posibilidad de cambiar de prueba fallida y repetir los 4 pasos que se proponen. Recuerde que en cualquier paso puede consultar con el profesor. 7.5.5 Consejos para errores no sistemáticos y ocasionales Este tipo de errores son los más complicados de detectar puesto que al ser ocasionales y no seguir un patrón conocido, cualquier proceso de localización nos puede llevar mucho tiempo. Ante esta situación, y en base a la experiencia de los profesores a lo largo de los últimos años, se proponen las siguientes recomendaciones: • Un primer consejo es que sean otros ojos (diferentes a los que han implementado el sistema) los que evalúen la posible causa del error. En este punto se aconseja a los alumnos que pregunten a los instructores y a los profesores. • Cuando se dispone de versiones anteriores del programa o circuito se propone realizar algunas de las acciones siguientes: o Analizar las diferencias con la última versión del programa o circuito que funcionaba correctamente. o Deshacer los últimos cambios e ir introduciéndolos poco a poco comprobando, en cada momento, si aparece o no el error. • En el caso de no disponer de una versión anterior, una estrategia interesante es modificar de manera controlada el sistema (programa o circuito) desarrollado. Esta modificación puede consistir en substituir un módulo por otro (e.g. si se usase el LCD, una alternativa sería imprimir en la pantalla del EDColdFire) o bien desactivar alguno de los módulos: o El último módulo implementado, el más complejo o el menos probado hasta la fecha. o El módulo relacionado con el origen de la acción que produce el fallo o el módulo donde se detecta algún desajuste entre el comportamiento real y el esperado. • Otra acción interesante es analizar puntos intermedios que permitan detectar desajustes entre el comportamiento real y el esperado. 51 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 • Para los errores de los programas que producen un error del hardware de la plataforma, es muy recomendable analizar los principales registros (PC, D0-D7 y A0-A7) con el fin de extraer información útil que nos permita detectar el error. Algunas causas muy frecuentes de este tipo de errores son: o Variables no inicializadas que producen comportamientos aleatorios. o Corrupción de la pila por mal uso de las instrucciones RTS y RTE. 7.5.6 Comentarios adicionales sobre depuración de programas • Antes de usar una función (o método) es necesario haberla declarado. Si no se hace, el compilador supone que esa función va a devolver un 'int' (declaración implícita) y nos dará avisos como los siguientes: o warning: type mismatch with previous implicit declaration o warning: previous implicit declaration of `funcionX' o warning: `funcionX' was previously implicitly declared to return `int' • Editar los ficheros fuentes (.c o .h) usando un editor que no sea el EDColdFire puede provocar problemas de compilación, debido a una diferente gestión de los retornos de carro por parte del compilador (caracteres que normalmente no se ven al editar). El fichero afectado parece ser correcto (el EDColdFire lo muestra bien, pero el compilador no lo procesa bien, pero se producen errores de compilación imprevisibles (el EDColdFire lo muestra bien, pero el compilador no lo procesa bien). Se puede intentar corregir el problema copiando el texto desde el EDColdfire, pegándolo sin formato en el bloc de notas, volviendo a copiarlo y, finalmente, pegándolo en el EDColdFire. • Si la mayoría de los datos de un “array” o “struct” son constantes y no cambian durante la ejecución del programa, se pueden inicializar directamente al declararlos, siempre y cuando se declaren como 'static' (respuesta 32 de [8]). Para declarar e inicializar una variable de tipo 'struct', se puede consultar el ejemplo 6.17 de [20] (no el 6.16, que es muy poco recomendable). El ejemplo 6.18 explica cómo inicializar un 'array', lo cual es extrapolable a 'arrays' contenidos en 'structs'. • Si se activan las optimizaciones del compilador, las variables globales que pueden ser accedidas desde el programa principal y desde las interrupciones, deberían declararse como volatile. Esta palabra clave indica al compilador que a la hora de optimizar trate de manera especial estas variables porque pueden ser modificadas por las interrupciones en instantes de tiempo impredecibles para el compilador. Ejemplo: 'volatile BOOL flag;' (explicación adicional en el capítulo 8 de [20]). • Se ha publicado una implementación en C incompleta (pero funcional) de la función printf, adaptada al EdColdFire por Víctor Miguel Morales [21]. 52 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 8. Desarrollo recomendado En este apartado se da una división y planificación orientativa del trabajo a realizar en el laboratorio, organizados en forma de hitos que conseguir y sesiones de laboratorio semanales (en la tabla se muestra la correspondencia entre sesiones e hitos): Tabla 4. Relación entre sesiones de laboratorio e hitos a conseguir. SESIÓN 0 1 2 3 4 5 6 7 8 9 10 HITO QUE CONSEGUIR 1 2 3 4 5 8.1 Hitos y sesiones orientativas Esta es una planificación orientativa en relación al posible desarrollo de la práctica. En caso de que los alumnos superen los objetivos planteados para una determinada sesión antes de la finalización de la misma, se recomienda al alumno tratar de abordar los objetivos y tareas planteados para la siguiente sesión. Igualmente, y en relación con la redacción de la memoria final, se recomienda que la realización de la memoria se vaya realizando a medida que se van consiguiendo cada uno de los hitos descritos. 8.1.1 Sesión -1 Antes de asistir a su primera sesión de laboratorio es necesario preparar el trabajo fuera del laboratorio, como se ha mencionada en un apartado previo. A través del portal web y de los libros [3] y [4] encontrará recomendaciones y materiales que le resultarán útiles en esta labor. 8.1.2 Hito 1: Menús y visualización Objetos implicados: Relojes, Leds, Piezas, Estado, Pantalla, Tecla y Puerto. 8.1.2.1 Sesión 0 Un primer objetivo ligado al hito 1 es desarrollar el sistema de menús para seleccionar el nivel de dificultad y el momento en que da comienzo el juego. 53 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 El alumno comenzará a diseñar, implementar y depurar el primer prototipo del sistema. Una vez completados los tutoriales del entorno y del teclado, el primer paso será implementar el sistema de menús, empleando únicamente las 4 teclas mencionadas en este enunciado. El siguiente paso consistirá en agregar interrupciones temporizadas a los menús. Una vez completados los tutoriales de los temporizadores, deberá conseguir provocar interrupciones a 1 KHz, interrupciones que deberán habilitarse una vez pulsada la tecla ‘A’ y que deberán contabilizarse mediante la oportuna actualización de un contador. Es muy importante traer programas diseñados y escritos en casa, para aprovechar al máximo las horas de laboratorio disponibles. El plan de pruebas propuesto en esta sesión consistiría en probar cada una de las posibilidades del sistema de menús, que las teclas no útiles son ignoradas y no provocan ningún problema, que el objeto estado se actualiza correctamente y que los mensajes en pantalla son adecuados a cada prueba. En relación a las interrupciones se deberá comprobar, haciendo uso de puntos de parada, la correcta atención de las mismas prestando especial atención a la actualización del mencionado contador. 8.1.2.2 Sesión 1 El objetivo de esta sesión consiste en incorporar el hardware necesario para visualizar el área de juego basada en la matriz de leds. Para ello se debe diseñar, implementar y probar dicho HW de visualización conectándolo al puerto digital de salida. En este caso, el programa cocheFantastico puede servir para una prueba básica incompleta de las conexiones. Como este programa va activando (poniendo a 1) cada uno de los bits del puerto de salida y los demás los pone a 0, si se emplea una configuración como la del enunciado, cuando el bit activado sea el de alguna de las columnas, se encenderán todas los leds de esa columna. 8.1.2.3 Sesión 2 Finalmente, se propone como objetivo último del hito implementar las rutinas que permitan mostrar una determinada pieza (para lo que deberá abordar el diseño de un primer modelo de pieza) en alguna posición dentro del área de juego. Para ello el alumno deberá emplear las interrupciones temporizadas añadidas durante la primera sesión. En particular, deberá aprovechar las mismas para refrescar correctamente la matriz aplicando las excitaciones oportunas en el puerto de salida. El plan de pruebas para verificar el correcto funcionamiento consiste en comprobar que todos y cada uno de los leds de las filas y las columnas se encienden correctamente al enviar al puerto de salida los valores apropiados, sin que el teclado deje de funcionar. En este sentido, será importante comprobar con el osciloscopio la correcta generación de las señales de excitación aplicadas a las diferentes columnas de la matriz de leds, señales necesarias para su oportuno refresco. A la hora de inicializar y pintar una determinada pieza deberá prestar especial atención a las coordenadas de posición en las que decida hacerlo. Por el momento, y para simplificar el proceso de verificación, asegúrese de “ubicar” la pieza en una posición adecuada, de tal modo que la pieza al completo esté comprendida dentro del área de juego. 54 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 8.1.3 Hito 2: Movimientos Objetos implicados: los mismos que para el hito anterior. 8.1.3.1 Sesión 3 Como parte de este segundo hito se propone ultimar el diseño del modelo de pieza permitiendo la representación en la matriz de leds de todos los tipos de pieza considerados en sus múltiples posibles formas. En este caso será importante verificar que el sistema es capaz de representar cualquier tipo de pieza en cualquier posición (dentro del área de juego). Igualmente, se abordará la implementación de todos los posibles movimientos contemplados en el juego: traslación (hacia la izquierda, hacia la derecha y hacia abajo) y rotación (sólo hacia la izquierda según giros de 90 grados en sentido anti-horario, al disponer de una única tecla de rotación). En relación a este objetivo será importante verificar que los leds de la matriz se encienden y se apagan correctamente (i.e. borrado) al realizar los diferentes movimientos de la pieza. El plan de pruebas para esta sesión debe prestar especial atención a la robustez de los métodos implementados para pintar y borrar una determinada pieza la matriz de leds. En particular, debe comprobarse que el método diseñado para pintar sólo lo hace dentro de los límites definidos para el área de juego. De este modo, y como parte del comportamiento esperado de nuestro sistema, debemos comprobar cómo al mover sucesivamente la pieza hacia la derecha, ésta acaba “desapareciendo” del área de juego. Igualmente, si deshacemos el recorrido anterior mediante sucesivos movimientos hacia la izquierda, la pieza debe “aparecer” nuevamente en el área de juego. Una prueba similar debe hacerse para el caso en que decidamos hacer desaparecer la pieza a través del límite izquierdo del área de juego. En caso de intentarlo hacia abajo, es preciso destacar que no será posible recuperar la posición original de la pieza al no contemplarse la posibilidad de realizar movimientos hacia arriba (a menos que incluyamos código extra que lo permita, e.g. si la pieza cae más de 5 líneas por debajo del límite inferior del área de juego, debe volver a ubicarse al comienzo de la misma). Otro detalle importante que debe tener en cuenta en todo este proceso de verificación es la conveniencia de aprovechar la pantalla. Ésta puede ser aprovechada para presentar en ella información que facilite las distintas comprobaciones requeridas (e.g. coordenadas de posición de la pieza en el área de juego, rotación actualmente seleccionada, ocupación del área de juego, etc.). 8.1.3.2 Sesión 4 Finalmente, y para completar el Hito 2, en esta sesión se propone la implementación de la caída de las piezas según el ritmo considerado para el nivel de dificultad elegido. Así, aprovechando las mismas interrupciones empleadas para la temporización asociada al refresco, mediremos el tiempo que una determinada pieza permanece en la misma línea provocando su descenso a la siguiente en caso de que dicho tiempo supere el umbral establecido. Recuerde la recomendación de tratar la caída automática de una pieza como una sucesión de movimientos hacia abajo a intervalos regulares de tiempo que no están motivados por la pulsación de la tecla correspondiente por parte del jugador. En este caso, dichos movimientos están motivados por la detección de que el tiempo que lleva la pieza actualmente seleccionada en la misma línea, ha superado el umbral definido. En este sentido, y a nivel de implementación, un único 55 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 procedimiento cuya oportuna llamada permita ejecutar dicho movimiento hacia abajo en ambos casos (i.e. pulsación y timeout) es suficiente. En esta ocasión, será importante verificar que tras ubicar una determinada pieza en una cierta posición dentro de la pantalla, la pieza acaba desapareciendo de la misma tras sucesivos descensos sin necesidad de ejecutar movimiento hacia abajo alguno. Al término de esta sesión el alumno debería haber alcanzado el Hito 2. Durante la misma tendrá lugar una revisión por parte de los profesores del estado del sistema en desarrollo. En este sentido se prestará especial atención a que los alumnos hayan superado el Hito 1. 8.1.4 Hito 3: Colisiones Objetos implicados: todos menos Melodías. 8.1.4.1 Sesiones 5 y 6 En ellas se debe implementar el juego propiamente dicho, incluyendo la necesaria detección de las colisiones que puedan producirse como resultado de los diferentes movimientos de las piezas. En caso de producirse una colisión al tratar de ejecutar un movimiento hacia abajo, deben comprobarse todas las líneas del área de juego, haciendo desaparecer las que se hayan completado y “repintando” las líneas superiores en el espacio liberado. Una vez llevada a cabo la oportuna gestión de las líneas completadas, y dependiendo del estado de ocupación del área de juego, deberán implementarse tanto la generación y puesta en juego de una nueva pieza, como la detección del posible final del juego. Asimismo, se deben calcular y mostrar los resultados contemplados, es decir, el número de líneas completadas durante el juego. Un posible procedimiento a seguir para verificar la correcta gestión de las colisiones podría consistir en deshabilitar temporalmente la caída automática de las piezas. De este modo, resultará más sencilla su comprobación cuanto éstas estén provocadas por los movimientos ejecutados por el jugador. En particular, los diferentes casos de prueba que deberá comprobar son: • colisión de una pieza tras movimiento hacia la izquierda bien con el límite izquierdo del área de juego o bien con otra pieza, • colisión de una pieza tras movimiento hacia la derecha bien con el límite derecho del área de juego o bien con otra pieza, • colisión de una pieza tras movimiento hacia abajo bien con el límite inferior del área de juego o bien con otra pieza, o en este caso en particular, deberá comprobarse igualmente que, en caso de completar una determinada línea, dicha línea es borrada y todas las que se ubicaban encima son “repintadas” correctamente una línea más abajo. Esta prueba puede extenderse al caso en que se completen simultáneamente dos, tres o incluso cuatro líneas. Igualmente, podrá aprovecharse esta prueba para comprobar la correcta actualización del contador del número de líneas completadas. 56 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 o otro de los aspectos importantes que deberá comprobar será la correcta inicialización y puesta en juego de una nueva pieza. Concretamente, deberá prestar especial atención a la decisión en cuanto a qué coordenadas iniciales de posición asignar a cada nueva pieza. El objetivo en ese sentido será asegurar que, inicialmente, sólo se pueda visualizar parcialmente cada pieza (e.g. al aparecer una pieza en forma de L sólo se deberían “ver” en el área de juego los dos primeros cuadrados correspondientes a la base o lado corto de la L). • colisión de una pieza tras movimiento de rotación (siempre hacia la izquierda o en sentido anti-horario) bien con alguno de los límites del área de juego o bien con otra pieza. En una segunda etapa podría recuperarse la caída de las piezas para, en ausencia de dichos movimientos, comprobar que las diferentes piezas comienzan a apilarse unas sobre otras hasta agotar el espacio disponible en el área de juego dando lugar a la finalización del mismo. 8.1.5 Hito 4: Melodía de juego Objetos implicados: Relojes, Estado y Melodía. 8.1.5.1 Sesiones 7 y 8 En este hito se propone incorporar el hardware analógico de audio y los mecanismos necesarios para que, al pulsar la tecla A, no sólo se inicie la partida sino que también comience la reproducción de la melodía de juego. Con ese propósito, debemos generar sucesivamente las diferentes ondas cuadradas con la frecuencia y la duración correspondiente según las notas que componen la melodía. En este sentido, para poder establecer una determinada frecuencia será necesario configurar convenientemente uno de los timers disponibles. Por otro lado, aprovecharemos las propias interrupciones para medir la duración de cada una de las notas. Igualmente, debemos garantizar que la melodía de juego pueda escucharse durante toda la partida. De este modo, si se agota la melodía antes de que finalice la partida, debemos volver a reproducirla desde el principio. Es importante verificar que las melodías suenan correctamente, que las frecuencias generadas son correctas (frecuencia y duración correspondiente a cada nota medidas con el osciloscopio) y que se puede controlar el volumen de reproducción para no molestar al resto de los alumnos. 8.1.6 Hito 5: Sistema final Objetos implicados: Todos. 8.1.6.1 Sesión 9 En esta sesión se debe completar el prototipo básico completo: hay que incluir el cálculo y visualización de resultados, y la gestión de los 3 niveles de dificultad. El plan de pruebas del prototipo final debe ser definido por el alumno y presentado en la memoria final. 57 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 8.1.6.2 Sesión 10 Durante esta sesión está prevista la realización opcional de mejoras. Es importante que no se deje para el final la redacción completa de la memoria, sino que se vaya escribiendo conforme se van construyendo y probando los diferentes subsistemas. 9. Mejoras con puntuación predefinida Se trata de modificaciones sobre las especificaciones básicas que pueden permitir al alumno alcanzar una calificación superior a 8 puntos si se realiza en C y 8,5 puntos si se realiza en ensamblador en el LSED. En este apartado se incluyen algunas mejoras con una indicación sobre la máxima calificación que se podría obtener en cada una de ellas. 9.1 Estadísticas de juego (máximo 0,3 puntos) Para la realización de esta mejora se propone la ampliación de la funcionalidad del módulo de resultados para que, además del total de líneas completadas, muestre también el tiempo o la duración del juego y la relación entre ambos (i.e. número de líneas completadas por segundo). Adicionalmente, se mostrará información acerca del número de “Tetris” conseguidos (i.e. conseguir completar 4 líneas simultáneamente). Dificultad estimada: BAJA. 9.2 Generación aleatoria de piezas (máximo 0,3 puntos) Esta mejora consistirá en conseguir que la decisión en cuanto a qué nueva pieza debe incorporarse al juego tenga un carácter aleatorio, tal y como ocurre con la versión real del juego. Para ello podrá basarse en la oportuna lectura de los 3 primeros bits del registro TCN asociado a alguno de los temporizadores empleados en la práctica. Dificultad estimada: BAJA. 9.3 Generar la señal de cada nota mediante el DAC de la plataforma ENT2004CF (máximo 0,5 puntos) En esta mejora se propone al alumno que genere las señales asociadas a las notas utilizando el conversor digital-analógico disponible en la plataforma ENT2004CF. Importante: esta mejora no exime de la implementación estándar propuesta basada en el empleo de un timer. Mediante este conversor se puede generar una señal con la forma de onda deseada. Los aspectos más importantes a considerar en esta mejora son los siguientes: • Se recomienda a los alumnos que quieran afrontar esta mejora que realicen los tutoriales del capítulo 8 del libro [3]. • Para generar señales de diferentes frecuencias es posible generar un período de la señal con un conjunto muy elevado de valores (gran resolución) que permita simular las diferentes frecuencias sin más que ir presentando una y otras muestras de la señal sin 58 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 modificar el intervalo de tiempo entre presentaciones. Para la realización de esta mejora se sugiere al alumno la consulta de [15]. • Es importante no olvidar el filtrado posterior de la señal de salida para eliminar el ruido de la conversión digital analógica (similar al propuesto en la práctica básica). • Hay que prestar especial atención a los niveles de tensión de salida del DAC con el fin de ver si es necesario hacer alguna adaptación de niveles antes de filtrar la señal y de excitar el amplificador de potencia (módulo final antes de excitar al altavoz). Dificultad estimada: MEDIA. 9.4 Construcción de un prototipo del HW en PCB (máximo 0,5 puntos) En la realización de esta mejora es obligatorio utilizar un programa comercial para el diseño de la PCB. Remitimos al alumno interesado a lo que se comenta en el enunciado y la página web de la asignatura LCEL, destacando que esta mejora es más asequible en LSED porque el circuito a diseñar y construir es más pequeño. Dificultad estimada: MEDIA. 10. Otras Mejoras Las sugerencias recogidas en este apartado tienen un carácter meramente orientativo. En todo caso, la calificación dependerá de factores como la originalidad y calidad del trabajo. Todas las mejoras propuestas (y las que puedan surgir por iniciativa del alumno) podrán llevarse a cabo de diversas maneras y con distintos grados de perfección y dificultad (de diseño y de implementación), por lo que la dificultad que se estima es meramente orientativa. Salvo que se diga lo contrario, las mejoras no eximen de realizar la práctica básica tal cual está definida en este enunciado, sino que deben ser complementos o programas adicionales. Para conocer detalles adicionales sobre la implementación o la dificultad de estas u otras mejoras, no dude en ponerse en contacto con el coordinador del LSED o con cualquiera de los profesores de la asignatura. 10.1 Velocidad o ritmo de caída variable: nivel de dificultad incremental En este caso se propone que la caída de las piezas se acelere progresivamente en la medida en que el jugador vaya completando un número determinado de líneas. Una posible implementación puede consistir en definir un ritmo inicial que tras la sucesiva consecución de grupos de 10 o 20 líneas vaya incrementándose, por ejemplo, en un 10%. Dificultad estimada: BAJA. 59 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 10.2 Ampliación de la funcionalidad por SW Es posible añadir nuevas posibilidades al sistema: • Posibilidad de reproducir nuevas melodías. • Posibilidad de subir o bajar una octava toda la canción, o incrementar o decrementar linealmente la velocidad media de reproducción según el nivel de dificultad elegido. Si se opta por esta última opción, modificar la duración de las notas de la melodía en consonancia con la mayor o menor dificultad del juego, entonces debe ralentizarse proporcionalmente (i.e. linealmente) cada nota, de tal manera que sólo se cambie el ritmo general de la melodía, no la melodía en sí. • Posibilidad de reproducir durante el menú una melodía distinta a la de juego. • ... Dificultad estimada: BAJA. 10.3 Perfil de jugador Esta mejora consiste en añadir al sistema la posibilidad de poder gestionar diferentes perfiles de jugador. El perfil contendría información específica de cada jugador como su nombre o diferentes estadísticas de juego. El sistema debería permitir introducir un nombre o identificador con el que poder referirnos a un perfil determinado. Este es un aspecto importante para esta mejora ya que supone la implementación de un teclado multi-tecla similar al de los teléfonos móviles. De este modo, antes de dar comienzo al juego, el sistema podría presentar por pantalla un menú en el que aparezcan, entre otras, las siguientes opciones: • “Seleccionar perfil”, para la selección de un perfil concreto de entre todos los disponibles en el sistema. • “Crear perfil”, que debe permitir la introducción de un nuevo perfil. • “Borrar perfil”, para el borrado de un perfil existente. Una vez elegido el perfil con el que se desea hacer uso del juego, el sistema debería recuperar las estadísticas almacenadas para el jugador correspondiente con el fin de poder actualizarlas oportunamente a lo largo de las siguientes partidas. Como es lógico, previamente a la selección de un nuevo perfil se habría almacenado un conjunto de estadísticas correspondientes al último jugador que hizo uso del sistema. Al finalizar el juego se presentaría al usuario una pantalla con sus estadísticas, las correspondientes a la última partida y las de carácter general o ligadas a todas y a cada una de las partidas que el usuario haya jugado hasta la fecha. Igualmente, y mediante la selección de la entrada oportuna en el menú mencionado anteriormente (por ejemplo, “Mostrar estadísticas”), dichas estadísticas también podrán ser presentadas a voluntad del usuario. 60 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 Al margen de las anteriormente mencionadas, otras posibles estadísticas que se proponen son las siguientes: • Puntuación total acumulada para cada nivel de dificultad. • Máximo número de líneas completadas durante una partida. • Máximo número de “Tetris” conseguidos durante una partida. • Nivel de dificultad más alto alcanzado durante una partida. • Nivel de jugador: en una escala de 1 a 5 estrellas, siendo 5 la máxima puntuación. Cada nivel de la escala puede corresponderse con un cierto umbral para la media del número de líneas completadas por partida (i.e. 1-menos de 10, 2-menos de 25, 3-menos de 50, y así sucesivamente). La incorporación de todas estas estadísticas abre la posibilidad adicional de incluir “rankings” de juego en el sistema donde se presentará a aquellos jugadores que hayan conseguido los mejores resultados para cada una de las diferentes estadísticas. Dificultad estimada: MEDIA. 10.4 Visualizador de la siguiente pieza Este visualizador está pensado como un dispositivo HW adicional que permita al jugador saber cuál va a ser la siguiente pieza que entrará en juego. En principio, podría contemplarse su posible implementación a partir de un display de 7 segmentos o de una nueva matriz de leds adicional de dimensiones 4x2. Esta mejora exigiría adaptar el HW básico ya que los terminales necesarios para manejar el display ya están siendo usados para iluminar la matriz de leds. En ese sentido, es posible que necesite hacer uso de un decodificador. En caso de optar por la alternativa SW de presentar dicha información directamente por la pantalla del PC, la mejora sería considerada de dificultad menor. Dificultad estimada: MEDIA-BAJA. 10.5 Sistema de puntuación avanzado Para llevar a cabo esta mejora será necesario definir una puntuación básica para cada línea completada. Basándonos en esa idea, permitiremos al usuario mejorar la puntuación final obtenida al conseguir completar varias líneas simultáneamente (es posible completar a la vez hasta 4 líneas, jugada que se denomina “Tetris”). De este modo, y en la medida en que el jugador vaya consiguiendo completar simultáneamente grupos de 2, 3 o 4 líneas, el jugador conseguirá incrementar el coeficiente por el que se multiplican los puntos ganados por cada una de ellas (x2, x3 y hasta x4). Dificultad estimada: BAJA. 61 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 10.6 Comienzo de juego con bloques fijos En esta ocasión se propone la implementación de un modo de juego extra en el que, al comenzar la partida, el área de juego ya se encuentre parcialmente ocupada por unos “bloques” fijos que podremos hacer desaparecer a medida que vayamos rellenando líneas con ellos. Se valorará especialmente la aleatoriedad en cuanto al número y disposición de los bloques mencionados. Dificultad estimada: MEDIA-BAJA. 10.7 Ampliación del subsistema de visualización Utilización del LCD (Liquid Cristal Display) de la placa TL04 en lugar de la pantalla del ordenador para mostrar mensajes y/o la siguiente pieza. En caso de emplear el LCD para la visualización del área de juego esta mejora supondría desarrollar un segundo programa (no exime de implementar la versión básica con HW basado en leds). Si sólo se emplea para mostrar mensajes, hay que adaptar el HW básico porque los terminales usados para manejar el LCD están siendo usados para iluminar los leds. Un ejemplo de utilización del LCD se puede consultar en el ejemplo “teclado_lcd.asm” que se muestra en el tutorial de manejo de la placa TL04 (capítulo 7 de [3]). Se valorarán detalles como: • Incluir símbolos especiales desarrollados por el alumno empleando las posibilidades que ofrece el LCD (para poder mostrar 3 columnas de notas con LCD de 2 líneas). • Implementar una barra de desplazamiento (scroll) por medio de un búfer que guarde las últimas líneas impresas (el LCD sólo puede mostrar a la vez 2 líneas de texto). • HW añadido. Dificultad estimada: MEDIA-ALTA. 10.8 Comunicación serie utilizando la UART En este caso se propone utilizar alguna de las UARTs disponibles en el ColdFire para comunicar un ordenador con el ColdFire a través del puerto serie asíncrono RS-232. Para ello debemos programar adecuadamente el puerto serie del MCF5272 siguiendo los manuales del fabricante, y conectar los puertos serie de ambos sistemas digitales mediante un cable de módem nulo. A los alumnos que lo soliciten los profesores ofrecerán un breve tutorial para el manejo de la UART. Dificultad estimada: MEDIA-BAJA. 10.9 Conexión con un servidor TFTP Esta mejora implica la programación del módulo Ethernet del MCF5272. Los profesores ofrecerán un tutorial y unos programas de ejemplo para el manejo de este módulo. Dado que los ejemplos están desarrollados en C, esta mejora se recomienda principalmente a aquellos alumnos que hagan la práctica en C. Un ejemplo de aplicación podría ser la implementación del juego en red. Dificultad estimada: MEDIA. 62 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 10.10 Recepción de melodías por SMS En este caso se debe utilizar un módulo GSM utilizando comandos AT que se envían desde el MCF5272 mediante una comunicación serie (utilizando la UART). Para la realización de esta mejora los profesores ofrecerán tanto el módulo GSM como un tutorial sobre su manejo mediante comandos AT. Dificultad estimada: MEDIA-BAJA. 10.11 Control del juego por medio de un acelerómetro Los acelerómetros ADXL320, ADXL321 ó ADXL322 proporcionan una tensión proporcional a la aceleración a la que se encuentra sometido el circuito en cada uno de los 3 ejes espaciales X, Y y Z. Empleando el convertidor ADC es posible leer esas tensiones y detectar que se producido un movimiento en el circuito y sustituir las pulsaciones del teclado por movimientos del acelerómetro. Para esta mejora se valorará especialmente su realización en PCB. Dificultad estimada: MEDIA-ALTA. 10.12 Reproducción de voz Utilizando el convertidor D/A de la ENT20004CF (mientras no se está reproduciendo la melodía) se pueden reproducir algunos mensajes orales, por ejemplo: • Menú: “A continuación elija el nivel de dificultad con el que le gustaría jugar: pulse uno para nivel ‘Fácil’, pulse dos para nivel ‘Medio’...”. • Nivel de dificultad seleccionado: “Ha elegido jugar en el nivel...”. Para guardar dichos mensajes se puede emplear la memoria DRAM disponible en el sistema. Dificultad estimada: MEDIA-BAJA. 10.13 Reconocimiento de voz Esta mejora precisa del empleo de HW externo de entrada de audio (etapa de adaptación de niveles e impedancias, filtro paso bajo antialiasing...). La aplicación consistiría en ordenar por voz las opciones del menú. Según el interés mostrado por los alumnos, a lo largo del curso se proporcionarán una o más clases de orientación e introducción al tema, creándose una lista de distribución de correo electrónico para las personas interesadas. Dificultad estimada: ALTA. 10.14 Programación (mediante comunicación serie) de un kit de reproducción mp3 En este caso se propone utilizar alguna de las UARTs disponibles en el ColdFire para programar un reproductor de música mp3 a través de comandos AT enviados por una comunicación serie. 63 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 Para abordar esta mejora es conveniente ponerse en contacto con el coordinador de la asignatura que facilitará el kit de reproducción mp3, una memoria Compact Flash y un grabador de memoria para cargar las canciones que se desea reproducir. Se puede utilizar para la reproducción de melodías, incluso mientras se está mostrando el menú o al final del juego. Dificultad estimada: MEDIA –BAJA. 10.15 Comunicación con una PSP, con una PDA o un iPod En este caso se propone utilizar alguna de las UARTs disponibles en el ColdFire para comunicarse con una PSP, con un iPod o con una PDA (quizá con módulo GPS). El material necesario para realizar esta mejora será facilitado por los profesores. Dificultad estimada: ALTA. 10.16 Implementación de otros juegos En este caso se propone aprovechar el HW de presentación desarrollado para la implementación de algún otro tipo de juego (e.g. un “Pong”, http://es.wikipedia.org/wiki/Pong). Se valorará tanto la complejidad como la originalidad del juego implementado. Dificultad estimada: ALTA. 11. Evaluación Como ya se indicó en la introducción, salvo que se haya indicado lo contrario, la práctica estándar propuesta contiene las especificaciones mínimas obligatorias que deben cumplir los sistemas y serán valoradas con un máximo de 8 puntos si se realiza en C y 8,5 puntos si se realiza en ensamblador. Esta nota máxima sólo se conseguirá si se cumplen todas las especificaciones, y la memoria, el código, el hardware y las respuestas en el examen oral son perfectos. La descripción del sistema de menús de la interfaz de usuario es orientativa, aunque en la evaluación se valorará la calidad de la interfaz desarrollada y las desviaciones respecto a la interfaz de este enunciado, deben ser explicadas en la memoria final. Obsérvese que se podría dar el caso de que suspenda alguien a quien la práctica le funciona, pero presenta graves deficiencias en los demás apartados; aunque será extremadamente improbable que esto suceda a una pareja de alumnos que hayan realizado la práctica y la memoria basándose en su propio esfuerzo y conocimiento; tenga en cuenta que en una práctica docente es tan importante cómo se hagan las cosas como el hecho mismo de hacerlas. Además de las especificaciones obligatorias se ofrece al alumno la posibilidad de realizar mejoras con puntuación máxima definida y otras mejoras con puntuación por determinar. Sobre las consideraciones éticas del trabajo en el laboratorio, remitimos al alumno a la normativa de la UPM y al documento publicado sobre la filosofía de los laboratorios LCEL y LSED, disponible a través del portal de la asignatura. Tenga en cuenta que se aplicarán métodos automáticos de detección de copias o plagios. 64 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 11.1 Funcionamiento y examen oral (<=4 puntos o <=3,5 puntos) En este apartado se pueden obtener hasta 4 puntos (si se implementa en ensamblador) o 3,5 puntos (si se implementa en C). Estos puntos provendrán (como máximo) de la comprobación por parte del profesor de que: • el prototipo desarrollado responde completamente a las especificaciones obligatorias contenidas en este enunciado, • el alumno responda correctamente a las preguntas que le formule el profesor durante el examen oral. • la nota obtenida en la revisión intermedia obligatoria. Dicha revisión forma parte de la evaluación de la asignatura, de acuerdo con el apartado 11 de las normas [1] y el apartado “Evaluación” del programa de la asignatura. La nota máxima en esa prueba es 0,6 puntos, que forman parte de los 4 o 4,5 puntos que se pueden obtener, como máximo, por “Funcionamiento y examen oral”. La calificación obtenida será comunicada al realizar el examen oral final. Se recuerda que para aprobar el examen oral es necesario un buen dominio individual del depurador del EDColdFire (cargar, ejecutar y parar un programa, establecer puntos de parada, visualizar variables o zonas de memoria, realizar modificaciones sobre un programa, etc.) de acuerdo con lo publicado en el documento de “Principios y valores” [2], especialmente en el apartado 4.4, aplicable tanto a C como a ensamblador. 11.2 Memoria final (<=1,5 puntos) La memoria final puede suponer hasta 1,5 puntos de la nota final: • la calidad de la redacción, la estructuración y la presentación del documento • las justificaciones técnicas de los valores y decisiones adoptados, • la claridad y la completitud en las explicaciones técnicas de cada uno de los módulos HW o SW • etc. 11.3 Calidad del SW (<=2,5 puntos) La calidad del SW desarrollado, explicado y documentado puntuará hasta 2,5 puntos: • La estructura general del programa en ensamblador debe responder a lo comentado en la sección 4.1.2 de [5]. • Cada subrutina debería tener un único punto de comienzo y un único punto de terminación, y no debería entrelazarse con otras subrutinas (según se comenta en el documento “Dudas y preguntas frecuentes del LSED”). Sí que es conveniente que las 65 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 rutinas se aniden (una rutina llame a otra para realizar una cierto cálculo y al terminarse la segunda rutina, pueda continuar la ejecución de la primera). • Debería emplear un buen número de rutinas (subrutinas, métodos o funciones), que le ayuden a dividir cada problema en subproblemas, y que no resulten muy extensas (y por lo tanto difíciles de entender y depurar). Algunas rutinas recomendadas se han ido incluyendo a lo largo de este enunciado. Si pensamos en una media de casi 3 métodos por objeto, 25 rutinas parece un número mínimo exigible para esta práctica. • Debe emplear constantes EQU o #define que permitan reconfigurar fácilmente el sistema (las instrucciones deberían no usar números mágicos). Ejemplos típicos podrían ser: o Una constante que permita fácilmente variar la frecuencia de las interrupciones temporizadas (FREQ_INT EQU ... o bien #define FREQ_INT...) . o Una constante para modificar el retardo antirrebotes del teclado (RET_REBOT EQU... o bien #define RET_REBOT...). • Debe emplear modos de direccionamiento variados y apropiados (indexado, indirecto, post-incremento...) y usar estructuras de datos que agrupen datos interrelacionados y que faciliten la implementación (búferes, tablas de valores...). Emplear estas técnicas suele producir código más compacto y elegante, evitándose frecuentemente el abuso de la desaconsejable técnica de “copiar, pegar y modificar”. • Debe incluir comentarios orientativos en el código (comentarios que aporten información al que los lea, no que se limiten a parafrasear el código). Un ejemplo paradigmático de un mal comentario es: o ADD.L #1,D0 * incrementa el registro D0 • Debe emplear typedef, struct, switch para producir soluciones elegantes, en C. Por cada objeto debería haber al menos un typedef y un struct. Por ejemplo: typedef struct { WORD frecuencias[MAX_NUM_NOTAS]; WORD duraciones[MAX_NUM_NOTAS]; ... } Tmelodia; typedef struct { Tmelodia melodias[MAX_NUM_MELODIAS]; ... } Tmelodias; • Un empleo abundante y adecuado de #include para dividir el código en subsistemas coherentes, en C. Al menos debería haber al menos un #include por objeto. • Debe emplear pocas variables globales, sobre todo en C. Sólo parece haber 4 objetos globales: estado, relojes, puerto y resultados. Para minimizar las variables globales debe: o usar variables static locales a los métodos o funciones en C, para que esas variables sólo puedan ser usadas por ese método, pero no sean variables locales 66 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 que se pierdan al terminar la ejecución de la rutina, y que así en la siguiente ejecución de la rutina, mantengan el valor que tenían al acabar la anterior ejecución: void rutinaInterrupcionConStaticLocal() { static Tmelodias melodias=...; ... } o pasar parámetros a los métodos o funciones en C: por valor (si el parámetro no va a ser variado por la rutina) o por referencia (en caso contrario): rutinaCopiaParam(int paramPorValor,int *paramPorRefer) { * parametroPorReferencia= parametroPorValor; ... } • El empleo de punteros y arrays en C es recomendable para acceder a estructuras de datos complejas de una manera elegante. Por ejemplo, los arrays de frecuencias y duraciones antes mostrados en la Tabla 1. • No se debe emplear goto, en C. • Etc. 11.4 Calidad del HW (<=0,5 puntos) La calidad del HW básico puede puntuar un máximo de 0,5 puntos: • estructura, • niveles de ruido presentes, etc. 12. Matrículas y diplomas de honor De acuerdo con la legislación vigente, en esta asignatura sólo se pueden asignar hasta un 5% de matrículas de honor. Como habitualmente el número de prácticas destacadas del LSED supera este límite legal tan estricto, se podrían conceder hasta 7 diplomas de honor a las mejores prácticas (o aspectos de una práctica) de alumnos que no obtengan matrícula de honor: • Diploma de honor por lo innovador que fue el sistema desarrollado. • Diploma de honor por la excelente calidad del código escrito en C. • Diploma de honor por la excelente calidad del código escrito en ensamblador. • Diploma de honor por lo innovadora que fue una de sus mejoras. • Diploma de honor por la excelente calidad del subsistema hardware. • Diploma de honor por la excelente calidad de la memoria presentada. 67 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 • Diploma de honor por la calidad del vídeo explicativo del sistema desarrollado. Este año además se podrá optar a diploma en dos nuevas categorías relacionadas con prácticas que incorporen en modo alguno algún dispositivo móvil tipo Iphone/Ipod Touch/Móvil Android: • Diploma de honor por lo innovador que fue el sistema/aplicación desarrollado con dispositivos móviles. • Diploma de honor por el excelente uso de las posibilidades/recursos ofrecidos por los dispositivos móviles (ej.: acelerómetros, GPS, brújula, etc.). A las prácticas que opten a matrícula de honor o a alguno de los diplomas (a excepción de las categorías relacionadas con la calidad SW y calidad de la memoria), se les pedirá que graben uno o varios vídeos explicativos de su práctica. Estos vídeos podrían ser incluidos en el canal de la asignatura en YouTube, si los alumnos implicados no se oponen a su difusión por este medio. El Departamento dispone de un par de cámaras con capacidad para grabar vídeos, que pueden ser usadas en el B-043. Los alumnos que reciban estas matrículas y diplomas tendrán prioridad en la concesión de Proyectos Fin de Carrera en el Departamento de Ingeniería Electrónica. La ceremonia de entrega de los Diplomas de Honor tendrá lugar en acto público celebrado en el Salón de Grados de la ETSIT. Durante la misma, se proyectará un vídeo-resumen que recoja las mejores prácticas del laboratorio. 13. Bibliografía [1] Información general del Laboratorio de Sistemas Electrónicos Digitales (LSED). http://neirol.die.upm.es/~profes/lsed/0910/public/docs/infolab-lsed0910_v1_0.pdf [2] Principios, valores, objetivos y aspectos éticos del LCEL y el LSED. http://lsed.die.upm.es/public/docs/MetaLaborariosLCELLSED.pdf [3] R. San Segundo et al, “Introducción a los Sistemas Digitales con el microcontrolador MCF5272”, Ed. Marcombo S.A., 2006a. Básico para el desarrollo de la práctica del MCF5272, dado que describe varios tutoriales para el manejo de los principales recursos de la plataforma ENT2004CF. [4] R. San Segundo et al, “Entorno de desarrollo EDColdFire V3.0” Ed. ETSIT, 2006. Básico para el desarrollo de la práctica del MCF5272, dado que describe el manejo del programa EDColdFire y contiene ejemplos sencillos para el manejo de la plataforma ENT2005CF. http://lsed.die.upm.es/public/docs/tutorialBasicoEDColdFire_v7.htm http://lsed.die.upm.es/public/docs/EDColdFire_ayuda.htm 68 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 [5] Javier Ferreiros et al, “Aspectos Prácticos de Diseño y Medida en Laboratorios de Electrónica”, Ed. ETSIT. 2002 Básico para el desarrollo de la práctica (sobre todo, el capítulo 4). [6] J.M. Montero et al. “How-To de los equipos del laboratorio” Disponible en Internet a través de http://lsed.die.upm.es/ 2006. Básico para el desarrollo del HW. http://lsed.die.upm.es/ [7] J.M Montero et al. “Dudas y preguntas frecuentes del LSED” Disponible en Internet a través del portal del LSED http://lsed.die.upm.es/ 2006. [8] J.M Montero et al. “Dudas y preguntas frecuentes del LSED Programación en C”. Especialmente útiles en las primeras fases del desarrollo. http://lsed.die.upm.es/ [9] C. Carreras et al “Sistemas Electrónicos Digitales” Ed. ETSIT. 2005 [10] Manuales del MCF5272 de Freescale. Sobre todo si se implementa en lenguaje ensamblador o se usan recursos para los cuales no hay tutoriales disponibles [11] J.M Montero et al. “Transparencias sobre programación en C para alumnos de Java”. Sobre todo si se carece de experiencia en lenguaje C. http://lsed.die.upm.es/ Básicos para el desarrollo del HW: [12] “Hojas de características del 74HC244”. http://lsed.die.upm.es/ [13] “Hojas de características del amplificador LM386”. http://lsed.die.upm.es/ [14] Enunciado de la Práctica del Laboratorio de Circuitos Electrónicos (LCEL), Curso 2007-2008, “Sistema de Comunicación Vocal por Modulación de Amplitud”. http://neirol.die.upm.es/~profes/lcel/0708/public/docs/enunciado0708-1.0.pdf [15] Enunciado de la práctica estándar del Laboratorio de Sistemas Electrónicos Digitales (LSED), Curso 2008-2009, “Piano Hero: un juego musical basadoen el MCF5272”. http://neirol.die.upm.es/~profes/lsed/0809/public/docs/Enunciado_lsed0809-v1_4.pdf [16] David Brown “Objects in Plain English” Ed Wiley & Sons, 1998 69 COLDTRIX: UN ROMPECABEZAS BASADO EN EL MCF5272 Documento riguroso y ameno, que compendia las metodologías expuestas por diversos expertos en el análisis y en el diseño orientado a objetos. [17] Plantillas para la creación de un nuevo archivo .c o de un nuevo archivo .h. http://lsed.die.upm.es/public/sw/objeto.c http://lsed.die.upm.es/public/sw/objeto.h [18] Esquemas de salida y entrada del entrenador. http://lsed.die.upm.es/public/docs/salidasEntrenador.jpg http://lsed.die.upm.es/public/docs/salidasEntrenador.jpg [19] Fotos sobre cómo conectar el HW de la práctica a la placa TL04. http://lsed.die.upm.es/public/fotos/hw1.jpg http://lsed.die.upm.es/public/fotos/hw2.jpg [20] The C book, online version of The C Book, second edition by Mike Banahan, Declan Brady and Mark Doran, originally published by Addison Wesley in 1991 (freely available). http://publications.gbdirect.co.uk/c_book/ [21] Implementación en C incompleta (pero funcional) de la función printf, adaptada al EdColdFire por Víctor Miguel Morales. http://lsed.die.upm.es/public/sw/printf.zip Esta bibliografía se puede encontrar fácilmente en Publicaciones de la ETSI Telecomunicación de la UPM, en su biblioteca o ciberteca, o en el laboratorio B-043. 70