4.2 Arquitectura software:
La figura 4-2 muestra la arquitectura software del sistema de modulación FSK implementado en esta práctica:
Figura 4-2. Arquitectura software del modulador FSK.
Se ha modificado la arquitectura utilizada en lab3 para utilizar interrupciones en lugar de encuesta para la generación de las muestras de salida.
Modificaciones:
En la inicialización se incluye la habilitación de la interrupción del puerto I2S.
En el ejecutivo cíclico, se incluye una llamada a la función
lab4()que calcula una nueva muestra de la señal a generar. Esta muestra se almacena en un buffer circular (objetog_tx_buffer) que comunica el bucle principal con la rutina de servicio de interrupción (ISR) del puerto I2S.Se incluye la rutina de servicio de interrupción del puerto I2S, que se encarga de enviar las muestras al códec WM8731.
4.1.1 Comunicación bucle principal - ISR:
La comunicación entre el bucle principal y la rutina de servicio de interrupción del puerto I2S se realiza mediante un buffer circular de 8 muestras.
El bucle principal genera las muestras de la señal FSK y las almacena en el buffer circular.
La ISR del puerto I2S extrae las muestras del buffer circular y las envía al códec WM8731.
Para evitar condiciones de carrera en el acceso al buffer circular, se deshabilitan las interrupciones al acceder al buffer desde el bucle principal.
Descripción del buffer circular:
El buffer consta de los siguientes elementos:
buffer[]: Array que almacena las muestras generadas.head: Índice de la siguiente muestra a escribir por el bucle principal.tail: Índice de la siguiente muestra a leer por la ISR.
Operaciones principales:
- apilado (push):
Si hay espacio en el buffer (no está lleno), se escribe una muestra en la posición
heady se actualizahead.- desapilado (pop):
Si hay muestras disponibles en el buffer (no está vacío), se lee la muestra en la posición
taily se actualizatail.
Condiciones de buffer lleno y vacío:
Buffer lleno:
(head + 1) % BUFFER_SIZE == tail. Esta condición supone que el número de muestras en el buffer esBUFFER_SIZE - 1.Buffer vacío:
head == tail
La figura 4-3 muestra la clase CIRC_BUF que utilizaremos para implementar el
buffer circular. De esta clase se crearán dos instancias (objetos): una para la
transmisión g_tx_buffer y otra para la recepción g_rx_buffer
(se utilizará en lab5).
Figura 4-3. Clase CIRC_BUF.
Diseño y pruebas clase CIRC_BUF
Preparación del entorno.
Descarga y descomprime el archivo de recursos
lab4en tu espacio de trabajo.Los archivos
circ_buf.hycirc_buf.cque implementan la clase CIRC_BUF están ubicados en la carpetasrc.
Configuración del proyecto.
Abre el proyecto lab4.
Selecciona el target
Test_Circ_buf, que utiliza un simulador para la depuración del código. Esto permite desarrollar y validar el software sin necesidad de disponer del hardware físico.
Tareas a realizar.
Escribe el código de la clase
CIRC_BUFen el archivocirc_buf.c. Encontrarás la descripción del comportamiento de los métodos en el archivocirc_buf.h.Los objetos
g_tx_bufferyg_rx_bufferse definen en el archivocirc_buf.ccomo variables globales.Asegúrate de que el código compila correctamente y no genera errores.
Revisa los casos de prueba definidos en la función
main(), ubicada en el archivotest/test_circ_buf.c.
Herramientas de análisis.
Inicializa el debugger
y abre la herramienta
Analyzer desde el menú:.
Analyzer mostrará la evolución temporal de las variables globales:
g_TestN: número de test.
Ejecuta la aplicación
y corrige cualquier error funcional hasta que la
clase CIRC_BUFcumpla con la especificación deseada. Si no hay errores, la variableg_TestNdebe alcanzar el valor F al finalizar
Test y Resultados esperados.
El fichero
test/test_circ_buf.cincluye los siguientes casos de prueba:Test 1. Comprobar que el buffer está vacío tras inicialización.
Test 2. Comprobar que el buffer no está lleno tras inicialización.
Test 3. Comprobar que la lectura en vacío devuelve error y pone ceros.
Test 4. Llenar el buffer hasta CIRC_BUF_SIZE-1 (el último push debe fallar).
Test 5. Comprobar que el buffer está lleno.
Test 6. Comprobar que el buffer no está vacío cuando está lleno.
Test 7. Leer todos los elementos y comprobar el orden de salida.
Test 8. Comprobar que el buffer está vacío tras vaciado.
Test 9. Comprobar que el pop en vacío sigue devolviendo error y ceros.
Test A. Comprobar que el push vuelve a funcionar tras vaciar el buffer.
Test B. Test adicional: comprobación de wrap-around de head y tail (llenar y vaciar varias veces).
Asegúrate de que todos los casos se ejecutan correctamente y producen los resultados esperados.