---
title: Práctica 1. Entorno de Modelado Gráfico basado en Componentes EDROOM sobre RTEMS
description: Enunciado de la Práctica 1 del laboratorio de Gestión de Datos a Bordo del Grado en Física e Instrumentación Espacial de la Universidad de Alcalá
tags: OBDH-GFIE, laboratorio
robots: noindex, nofollow
---
# Práctica 1. Entorno de Modelado Gráfico basado en Componentes EDROOM sobre RTEMS
<div style="text-align: justify">
El objetivo de esta práctica es que el estudiante aprenda a modelar gráficamente un sistema software basado en componentes y a utilizar la herramienta EDROOM que soporta este modelado. Además, utilizará la herramienta para genera código C++ automáticamente para la plataforma RTEMS / LEON3 con el fin de ejecutar el código binario sobre la placa Nexys-A7. Para ello, el estudiante deberá seguir el mismo procedimiento que en la Práctica 0 y utilizar una *toolchain* de compilación cruzada para la arquitectura SPARC integrada en el entorno Eclipse. Además, utilizará la herramienta GRMON para controlar el despliegue y depuración sobre la Nexys-A7 y una configuración de depuración Eclipse que utilice sparc-elf-gdb para conectarse a GRMON a través del puerto 2222.
:::info
EDROOM es una aplicación para Windows que puede ser ejecutada en Linux gracias a la virtualización de servicios que proporciona Wine. En este guión se va a indicar como instalar Wine y ejecutar EDROOM en Ubuntu, de forma que se puedan crear los modelos EDROOM desde la máquina virtual Ubuntu y generar el código directamente sobre el proyecto Eclipse que se da como punto de partida. Sin embargo, si deseais crear los modelos en nativo desde Windows, lo que es altamente recomendable para disponer de una mejor interfaz gráfica, podéis subir el proyecto Eclipse a vuestro repositorio de github asociado a la asignatura y usar el cliente Windows de github https://desktop.github.com/ para hacer un *clone* del proyecto eclipse. Una vez hecho el *clone* en Windows, se generará el código sobre él desde la aplicación EDROOM y se hará un *push* al repositorio del proyecto eclipse con el código generado. Finalmente, se volverá a trabajar en Ubuntu, haciendo un *pull* del proyecto actualizado y utilizando Eclipse para compilar el proyecto y desplegar el binario sobre la Nexys-A7 con la ayuda de GRMON.
:::
</div>
## Parte 1: Instalación de EDROOM sobre Ubuntu empleando Wine
<div style="text-align: justify">
Para instalar Wine basta con completar los siguientes comandos.
```shell
sudo apt-get update
sudo apt-get install wine32
```
Una vez instalado Wine, debéis completar la descarga del ejecutable de la aplicación EDROOM [(Enlace para descargar el .zip de la aplicación) ](https://universidaddealcala-my.sharepoint.com/:u:/g/personal/o_rodriguez_uah_es/IQAbt74qpupRQ59WPNtlzYIgAcC4ZD4Y2VRh0C7SYfl7Eag?e=HbbR9B), para posteriormente moverlo al directorio EDROOM ubicado en vuestro directorio de trabajo (`/home/atcsol`) y descomprimirlo. La siguiente secuencia de comandos os permite completar toda la instalación tras la descarga del archivo:
```shell
cd /home/atcsol
mkdir EDROOM
mv Dowloads/EDROOM.exe.zip EDROOM
cd /home/atcsol/EDROOM
unzip EDROOM.exe.zip
```
Una vez disponible la aplicación, lanzad su ejecución de EDROOM con el siguiente comando:
```shell
wine ./EDROOM.exe
```
Tras la inicialización, la herramienta EDROOM mostrará la siguiente ventana en pantalla.

</div>
## Parte 2: Ejemplo de modelo EDROOM
<div style="text-align: justify">
Para comprender como se modelan sistemas multitarea de tiempo real empleando EDROOM, vamos a utilizar un ejemplo sobre el que utilizaremos los elementos más significativos del lenguaje de modelado. El ejemplo nos permitirá crear una aplicación sobre la placa Nexys-A7 que ya utilizamos en la práctica 0.
:::info
La aplicación EDROOM generará código C++ utilizando los identificadores que vosotros utilicéis al modelar el sistema, por lo que es necesario que utilicéis identificadores que sean compatibles con el lenguaje de programación C++. Estos identificadores, al igual que en el código C, empezarán por una letra, no incluirán espacios y podrán incluir dígitos pero no caracteres especiales.
:::
### 2.1 - Creación de un nuevo modelo EDROOM
Para comenzar, crearemos un nuevo modelo utilizando el botón `New` que aparece en la parte izquierda de la barra de herramientas superior de la herramienta:

El siguiente formulario se abrirá para que podáis determinar el nombre del modelo, que por defecto será `Model1`:
<img width="45%" src="https://hackmd.io/_uploads/HJ1_G9kop.png"
style="display: block; margin: auto"></img>
Cambiaréis el nombre del modelo para que se llame `ExampleNexys` (sin espacios) tal como aparece en la siguiente figura.
<img width="45%" src="https://hackmd.io/_uploads/SJE-XqyjT.png"
style="display: block; margin: auto"></img>
:::info
La aplicación, para guardar el modelo, creará un directorio con el nombre que le asignéis. Este directorio estará ubicado dentro del directorio `Models`, que también crea la herramienta en el caso de que no exista, y que estará ubicado en el mismo directorio desde donde ejecutáis EDROOM.
:::
Una vez cambiado el nombre, pulsaréis el botón `OK` y , tal como aparece en la siguiente figura, dispondréis de un lienzo en blanco, etiquetado con el nombre `ExampleNexys`, que os indica que el modelo está abierto y está listo para su edición.

</div>
### 2.2 - Creación de las Clases Componente
<div style="text-align: justify">
El sistema que vamos a modelar consta de tres tareas, cada una de ellas modelada mediante un componente. Las tareas realizan funciones diferentes dentro del sistema, y por tanto, tienen código distinto, por lo que los componentes que las modelan serán, cada una de ellas, instancias de una Clase Componente diferente. La primera tarea que realizaremos sobre el modelo será añadir estas tres clases componente que necesitamos. La primera de ellas, denominada CCSystemMng, tendrá como tarea coordinar todo el sistema. Para crearla, pulsaremos sobre el botón `New Component Class` de la barra de herramientas que se muestra a continuación:

Una vez pulsado el botón, se abrirá un formulario para darle un nombre a la Clase Componente, que deberá ser, tal como hemos indicado, `CCSystemMng`. La siguiente figura muestra el formulario con el nombre ya introducido.
:::info
Todas las clases Componente que vais a crear van a tener, por defecto, el `Component Type = Proactive`. Debéis mantener siempre ese tipo, ya que el resto de tipos de componente no tienen todas las funcionalides habilitadas.
:::
<img width="45%" src="https://hackmd.io/_uploads/BJjsKqJo6.png"
style="display: block; margin: auto"></img>
Una vez creada, su nombre aparecerá en la lista de clases componente del proyecto. Esta lista se encuentra en la pestaña `Current Project` del panel situado en la parte derecha de la aplicación. La siguiente figura muestra como queda el panel tras añadir la Clase Componente `CCSystemMng` al modelo.
<img width="65%" src="https://hackmd.io/_uploads/H1fwh9kiT.png"
style="display: block; margin: auto"></img>
<br/>
La pestaña `Current Project` de la figura anterior nos permite, además, **acceder a todas las clases del proyecto**: **las Clases Componente, las Clases Protocolo y las Clases Dato**. Para hacer visible la lista de cada una de estas clases disponemos de los puntos de selección etiquetados`Comp.C.`, `Protoc. C,` y `Data C.`
A continuación, y con el fin de modelar el sistema que nos hemos propuesto construir, deberemos añadir otras dos clases componente más al modelo. Los nombres de estas clases son `CCLEDMng` y `CCDisplaysMng`. La siguiente figura muestra como queda la lista de clases componentes una vez estas clases han sido creadas.
<img width="65%" src="https://hackmd.io/_uploads/rJqQbJYi6.png"
style="display: block; margin: auto"></img>
:::info
La lista mostrada en la figura anterior tiene, además de las tres clases componentes creadas, una más denominada `ExampleNexys`. Esto es debido a que, al crear un nuevo modelo, EDROOM crea siempre una Clase Componente con el nombre del modelo. En esta clase, que denominaremos Clase Componente Principal, se deberán instanciar **los componentes que queremos que se desplieguen en el sistema y cuyo código vamos a generar**. La Clase Componente Principal puede ser un mero contenedor de los componentes del sistema o, en cambio, podemos dotarla de funcionalidad. En este último caso, EDROOM también creará un componente instacia de esta clase al generar el código del sistema modelado.
:::
</div>
### 2.2 - Instancianción de los componentes del sistema
<div style="text-align: justify">
Como ya hemos indicado, para incluir un componente en el sistema es necesario instanciarlo en la Clase Componente Principal `ExampleNexys`. Para ello, y teniendo activa la pestaña `Current Project` del panel situado a la derecha, nos aseguraremos que la Clase Componente `ExampleNexys` está en edición **haciendo doble clic** sobre su identificador. A continuación, mantendremos pulsado el botón izquierdo del ratón sobre una de clases (Tomaremos `CSystemMng` como la primera a instanciar), y arrastraremos sobre el lienzo en blanco. De esa forma conseguiremos crear una instancia de la clase seleccionada, es decir, **añadiremos un componente a nuestro sistema**. La siguiente figura muestra el estado tras esta instanciación:
<img width="65%" src="https://hackmd.io/_uploads/BJhJ7oyja.png"
style="display: block; margin: auto"></img>
A continuación, y con el fin de modelar el sistema que nos hemos propuesto construir, deberemos añadir otras dos Clases Componente al modelo. Los nombres que les daremos a estas clases son `CCLEDMng` y `CCDisplaysMng`, de forma que la lista de clases del panel de la derecha de la ventana principal deberá aparecer con la siguiente configuración:
<img width="65%" src="https://hackmd.io/_uploads/rJqQbJYi6.png"
style="display: block; margin: auto"></img>
Para completar las instanciaciones nos aseguraremos, de nuevo, de que sobre la pestaña `Current Project`, es la Clase Componente Principal `ExampleNexys` la que está en edición (haciendo doble clic sobre su identificador). A continuación ya podermos crear instancias de las clases `CCLEDMng` y `CCDisplaysMng`, de forma que los componentes instanciados aparezcan de acuerdo a la siguiente figura:
<img width="65%" src="https://hackmd.io/_uploads/H1q7bkKia.png"
style="display: block; margin: auto"></img>
Con la instanciación de los componentes sobre la Clase Componente Principal `ExampleNexys` queda establecida la estructura de tareas de nuestro sistema. El siguiente paso va a consistir en establecer la topología de comunicación entre los componentes y los protocolos que deben respetar en esa comunicación. Para ello será necesario crear las Clases Protocolo del proyecto, instanciar luego los puertos sobre las Clases Componente, y finalizar con el establecimiento de las conexiones. A continuación se va a explicar cómo dar estos pasos.
</div>
### 2.3 - Creación de las Clases Protocolo
<div style="text-align: justify">
Las Clases Protocolo permiten definir la comunicación entre los componentes, así como la respuesta ante interrupciones. Para crear una Clase Protocolo pulsaremos sobre el botón `New Protocol Class` de la barra de herramientas:

Se abrirá un formulario para darle un nombre a la Clase Protocolo. Para definir la comunicación entre los componentes `SystemMng` y `LEDMng` vamos a crear una Clase Protocolo denominada CPLEDMngCtrl, tal como muestra la siguiente figura:
<img width="65%" src="https://hackmd.io/_uploads/SJgJqGAuja.png"
style="display: block; margin: auto"></img>
:::info
Todas las Clases Protocolo se crean, por defecto, para definir la comunicación entre componentes. El resto de posibles tipos de Clases Protocolo a definir (`Shared Resource Access` o `Handle IRQ`) permiten, respectivamente, establecer el acceso a un recurso compartido y definir la respuesta ante una interrupción. En este modelo veremos, más adelante, un ejemplo de este último tipo de Clase Protocolo.
:::
Una vez creada la clase protocolo, esta aparecerá en la lista de protocolos de la pestaña `Current Project` del panel que se encuentra a la derecha de la ventan principal. La siguiente figura muestra la clase `CPLEDMngCtrl` en dicha lista.
<img width="85%" src="https://hackmd.io/_uploads/BkHF8ROia.png"
style="display: block; margin: auto"></img>
Haciendo *doble clic* sobre el nombre de la clase en esa lista, se abrirá un formulario que nos permitirá definir el protocolo asociado a esa clase. La siguiente figura muestra este formulario:

El formulario presenta, a su izquierda, listas para mostrar los mensajes de entrada y salida definidos para la Clase Protocolo. Debajo de cada lista hay un botón que permite añadir nuevos mensajes a la lista. Utilizaremos, a continuación, el botón `New Input Message` para añadir un nuevo mensaje de entrada. De acuerdo al análisis que ya hemos realizado, vamos a crear un nuevo mensaje **asíncrono**, que tenga **`SLEDStart` como identificador** ( recordemos que el identificador era el `Signal` del mensaje), y que su **dato adjunto sea de tipo TEDROOMUInt8**. Para definir este mensaje, editaremos sobre el formulario el campo `Signal Name`, fijándolo a `SLEDStart`, selecionaremos de la lista `Data Class` el tipo `TEDROOMUInt8`, y en la configuración de la sincronización, ubicada en el subpanel `Synchronization` de la parte inferior, seleccionaremos la opción `Asynchronous`. Tras esta definición, los campos deberían quedar como muestra la siguiente figura, y deberemos dar al botón `Add` para dar por añadido el mensaje al protocolo.
<img width="65%" src="https://hackmd.io/_uploads/BJxJqfR_i6.png"
style="display: block; margin: auto"></img>
A continuación, y usando el botón `New Output Message` se va a añadir un nuevo mensaje de salida, también de tipo **asíncrono**, y que tenga **`SLEDReady` como identificador**, y **sin dato adjunto**, es decir, que tenga un tipo `NULL`. La siguiente figura muestra cómo deberían quedar los campos tras su definición, antes de pulsar el botón `Add` para dar por añadido el mensaje al protocolo.
<img width="65%" src="https://hackmd.io/_uploads/S1UDCA_sp.png"
style="display: block; margin: auto"></img>
Finalmente, vamos a añadir dos mensajes, uno de entrada y otro de salida, que permitan establecer una comunicación síncrona entre dos componentes. El mensaje de iniciación lo definiremos como **mensaje de entrada de tipo `Invoke`**, tendrá como identificador `SToggleLEDShift`, y **no tendrá dato adjunto**, es decir, el campo `Name` de su `Data Class` aparecerá con el valor `NULL`. El siguiente formulario muestra la configuración del formulario que debéis definir para este mensaje.
<img width="65%" src="https://hackmd.io/_uploads/HkyqG0_sp.png"
style="display: block; margin: auto"></img>
La respuesta a este mensaje de iniciación será un **mensaje de salida de tipo `Reply`**, tendrá como identificador `SLEDShiftToggled`, y **no tendrá dato adjunto**, es decir, el campo `Name` de su `Data Class` aparecerá con el valor `NULL`. Además, al seleccionar el sincronismo del mensaje como de tipo `Reply`, será necesario indicar a qué mensaje de tipo `Invoke` responde. En nuestro caso será el mensaje con identificador `SToggleLEDShift`. El siguiente formulario muestra la configuración del formulario que debéis utilizar para definir este mensaje.
<img width="65%" src="https://hackmd.io/_uploads/B1J9fCuo6.png"
style="display: block; margin: auto"></img>
Una vez añadidos los 4 mensajes, la configuración de la Clase Protocolo será la que aparece en la siguiente figura:

<br/>
Es posible editar un mensaje añadido a la Clase Protocolo haciendo *clic* sobre el mensaje y utilizando el panel `Message Edition Box` de la parte inferior derecha. En la siguiente figura se muestra la edición del mensaje `SLEDStart`:
:::info
Para salvar la edición de un mensaje es necesario hacer *clic* en el botón **`Edit Message`**
:::
<br/>

</div>
<br/>
<div style="text-align: justify">
Una vez añadidos todos los mensajes a la Clase Protocolo, se hará *clic* en el botón **`Modify`** para salvar la edición realizada.
:::info
Si no se hace *clic* en el botón **`Modify`** no se salvará la Clase Protocolo y se perderán los mensajes añadidos.
:::
Una vez definida la clase `CPLEDMngCtrl`, se procedera a crear la Clase Protocolo `CPDisplaysMngCtrl` que define la comunicación entre los componentes `SystemMng` y `DisplaysMng`. Para ello se utilizará, de nuevo, el botón `New Protocol Class` de la barra de herramientas, y se completará el campo `Name` del formulario, tal como aparece en la siguiente figura:
</div>
<br/>
<img width="65%" src="https://hackmd.io/_uploads/Byk5fCdia.png"
style="display: block; margin: auto"></img>
<br/>
:::danger
---
#### Tarea a realizar:
Definid los mensajes de la Clase Protocolo `CPDisplaysMngCtrl` de acuerdo a la descripción mostrada en la siguiente figura:
---
:::
<img width="75%" src="https://hackmd.io/_uploads/rkAlPlKip.png"
style="display: block; margin: auto"></img>
<br/>
<div style="text-align: justify">
Una vez añadidos estos 3 mensajes, el formulario de definición de la Clase Protocolo `CPDisplaysMngCtrl` será el que aparece en la siguiente figura:
</div>
<br/>

<div style="text-align: justify">
:::info
Recordad que deberéis hacer *clic* en el botón **`Modify`** para salvar la Clase Protocolo y los mensajes añadidos.
:::
Por último, vamos a añadir a nuestro modelo la Clase Protocolo `CPSerialCommand` que permita definir la respuesta ante una interrupción. Para ello, en la creación de esta Clase Protocolo marcaremos la opción `Handle IRQ`, tal como se muestra en la siguiente figura:
</div>
<br/>
<img width="65%" src="https://hackmd.io/_uploads/Hky9fAuja.png"
style="display: block; margin: auto"></img>
<br/>
<div style="text-align: justify">
La definición de la Clase Protocolo asociada a una interrupción requiere determinar el código que se instalará como manejador de interrupción (*Top-Half*) y, cuando sea necesario, el código de una tarea (*Bottom-Half*) que completa el manejo de la interrupción y gestiona el envío de un mensaje al componente que instancia el puerto de interrupción. La siguiente figura muestra la ventana de edición del (*Top-Half*) y el (*Bottom-Half*) para la Clase Protocolo `CPSerialCommand`:
</div>
<br/>

<div style="text-align: justify">
La configuración del (*Top-Half*) define el vector de interrupción asociado a la interrupción y el tipo del dato que se quiere enviar al componente (en el caso de que se decida necesario). En función de estos dos parámetros quedaran definidas dos variables. Una que permite manejar el dato que será enviado al componente, y otra que determina si es necesario "despertar" al (*Bottom-Half*). En la siguiente figura se muestra la ubiciación de estos parámetros y los valores que deben asignarse para la clase `CPSerialCommand`
</div>
<br/>
<img width="75%" src="https://hackmd.io/_uploads/r1sxZ-Ki6.png"
style="display: block; margin: auto"></img>
<div style="text-align: justify">
En la parte derecha del formulario quedará definida la configuración del (*Bottom-Half*). En este caso se debe determinar, en primer lugar, si se desea crear o no una tarea de (*Bottom-Half*). En el caso de que sí sea necesario, se configurará, además, si se desea tener la posibilidad de enviar un mensaje al componente cuando se produzca una interrupcion. Una variable, cuyo nombre está asociado al vector de interrupción seleccionado en el (*Top-Half*), nos permiete controlar cuándo es necesario enviar el mensaje al componente. En la siguiente figura se muestra la ubiciación de estos parámetros y los valores que deben asignarse para la clase `CPSerialCommand`:
</div>
<br/>
<img width="75%" src="https://hackmd.io/_uploads/S1Lkx-YiT.png"
style="display: block; margin: auto"></img>
<div style="text-align: justify">
Finalmente, en la parte inferior izquierda se puede determinar el código del (*Top-Half*) y en la derecha el del (*Bottom-Half*). El siguiente código es el añadido para el (*Top-Half*) de la clase `CPSerialCommand`:
</div>
<br/>
```c=
EDROOMVarIRQ18=leon3_getchar();
EDROOMIRQ18BottomHalfSignal=true;
switch(EDROOMVarIRQ18){
case('T'):
case('t'):
case('I'):
case('i'):
break;
default:
EDROOMIRQ18BottomHalfSignal=false;
}
```
:::danger
---
#### Tarea a realizar:
Siguiendo las instrucciones anteriores, completad la Clase Protocolo `CPSerialCommand` de forma quede configurada de acuerdo a la siguiente figura:
---
:::

### 2.4 - Instanciación de puertos
<div style="text-align: justify">
La instanciación de los puertos de comunicaciones y atención a interrupciones se realiza seleccionando en la lista de Clases Protocolo la clase correspondiente, y arrastrando sobre la Clase Componente que se pretende editar. En la siguiente figura se muestra la clase `CCSystemMng` tras la instanciación de sus puertos de comunicaciones con los dos componentes y el puerto `SerialCommand` asociado a la interrupción de la UART.
</div>
<br/>
<img width="75%" src="https://hackmd.io/_uploads/HyzBSZtoa.jpg"
style="display: block; margin: auto"></img>
<br/>
<div style="text-align: justify">
Para conseguir que los puertos sean conjugados, será necesario hacer *doble clic* sobre ellos y marcar la opción `Conjugated`, tal como muestra la siguiente figura:
</div>
<br/>
<img width="45%" src="https://hackmd.io/_uploads/BJL9KZYsa.png"
style="display: block; margin: auto"></img>
<br/>
<div style="text-align: justify">
#### Instanciación de un puerto de *Timing* (Timer)
Además de poder instanciar puertos de las Clases Protocolo que definene las comunicaciones entre componentes y la atención a interrupciones, EDROOM permite instanciar un tipo de puertos de *Timing* para solicitar los servicios de temporización. Para esta instanciación será necesario activar el modo **Añadir Timer** haciendo clic sobre el botón  de la barra de herramientas situada en la parte izquierda de la ventana principal.
</div>
<br/>

<div style="text-align: justify">
Seleccionando la Clase Componente que se quiere editar, y una vez activado el modo **Añadir Timer**, bastará con hacer *clic* sobre el lienzo de la Clase Componente para instanciar un puerto de *Timing*.
</div>
<br/>
:::danger
---
#### Tarea a realizar:
Editad la Clase Componente `CCLEDMng` añadiendo los puertos que se muestran en la siguiente figura:
---
:::
<br/>
<img width="75%" src="https://hackmd.io/_uploads/rk_45bFop.png"
style="display: block; margin: auto"></img>
<br/>
:::danger
---
#### Tarea a realizar:
Editad la Clase Componente `CCDisplaysMng` añadiendo los puertos que se muestran en la siguiente figura:
---
:::
<br/>
<img width="75%" src="https://hackmd.io/_uploads/rkP29bKiT.png"
style="display: block; margin: auto"></img>
<br/>
### 2.5 - Conexión entre puertos
<div style="text-align: justify">
Una vez definidos los puertos en todas las Clases Componentes podremos conectarlos editando la Clase Componente Principal `ExampleNexys`. Para ello es necesario activar el **modo conexión** mediante el botón  de la barra de herramientas situada en la parte izquierda. Una vez activado el **modo conexión**, basta con hacer *clic* sobre el puerto origen y arrastrar manteniendo el botón pulsado, hasta el puerto destino. Tras establecer las conexiones, el modelo deberá mostrar la siguiente topología de comunicaciones:
</div>
<br/>
<img width="75%" src="https://hackmd.io/_uploads/S14Sx1FoT.png"
style="display: block; margin: auto"></img>
### 2.6 - Definición del comportamiento de la Clase Componente CCSystemMng (Parte 1)
<div style="text-align: justify">
El comportamiento de cada Clase Componente se define mediante una máquina de estados. El botón `Edit Behaviour`  , que se situa en la parte superior de la ventana principal , da acceso a la ventana de edición del comportamiento de la Clase Componente que está en edición.
Para editar el comportamiento de la clase `CCSystemMng`, por tanto, la seleccionaremos en la lista de Clases Componentes de la ventana principal, y utilizando el botón , accederemos a la ventana de edición de su máquina de estados.
La siguiente figura muestra el contenido inicial de la ventana de edición del comportamiento de la clase `CCSystemMng`. El lienzo de la izquierda muestra su contexto `Top` que, inicialmente, sólo contiente el estado inicial representado gráficamente por el símbolo <img width="6%" src="https://hackmd.io/_uploads/r1Ib2iFjT.png"
style="float: block; margin:none"></img> .
<img width="90%" src="https://hackmd.io/_uploads/H1vcjsto6.png"
style="display: block; margin: auto"></img>
</div>
<div style="text-align: justify">
En la parte superior izquierda de esta ventana, se ubica la barra de herramientas que permite editar la máquina de estados de la Clase Componente. La siguiente figura muestra esta barra de herramientas:
</div>
<br/>

<br/>
<div style="text-align: justify">
Cada uno de los botones de esta barra de herramientas tiene una función asociada que describimos a continuación:
<br/>
* <img width="6%" src="https://hackmd.io/_uploads/SJ4lvadoT.png"
style="float: block; margin:none"></img> `Selection mode` : Permite seleccionar los elementos de la máquina de estados.
* <img width="6%" src="https://hackmd.io/_uploads/BkElPTdj6.png"
style="float: block; margin:none"></img> `New State` : Se utiliza para añadir nuevos estados.
* <img width="6%" src="https://hackmd.io/_uploads/r1BgDauip.png"
style="float: block; margin:none"></img> `New Transition or Branch` : Se utiliza para añadir transiciones o ramas.
* <img width="6%" src="https://hackmd.io/_uploads/BJVeP6djT.png"
style="float: block; margin:none"></img> `New Join Point` : Se utiliza para añadir puntos de unión (*Join Points*).
* <img width="6%" src="https://hackmd.io/_uploads/ryElPT_ja.png"
style="float: block; margin:none"></img> `New Choice Point` : Se utiliza para añadir puntos de elección.
<br/>
:::info
Dejando el cursor sobre cada botón, se obtiene información sobre su función.
:::
<br/>
</div>
#### Máquina de estados del contexto `Top` de la Clase Componente `CCSystemMng`
<div style="text-align: justify">
Utilizando la barra de herramientas descrita, se podrán añadir los estados, transiciones, puntos de elección, ramas, y puntos de unión que definen la máquina de estados.
</div>
<br/>
<div style="text-align: justify">
:::info
Las transiciones entre estados se deben crear empleando como origen y destino **la parte interna del borde** del estado, no el centro del estado, ya que el editor sólo detecta esa posición como válida para crear una transición. Lo mismo ocurre con las transiciones cuyo destino es un punto de elección y con las ramas que parten de él. Ambas deben crearse empleando el borde interno del punto de elección como destino y origen, respectivamente.
:::
<br/>
:::danger
---
#### Tarea a realizar
Cread la siguiente máquina de estados que define el comportamiento del contexto `Top` de la clase `CCSystemMng`:
---
:::
</div>
<br/>

#### Edición de los nombres de los estados del contexto `Top` de la Clase Componente `CCSystemMng`
<div style="text-align: justify">
Los estados deben recibir nombres significativos que nos indiquen su papel dentro de la máquina de estados. Para editar el nombre de un estado bastará con hacer *doble clic* sobre él, y se abrirá un formulario que permite, entre otras cosas, determinar su campo `Name`. La siguiente figura muestra este formulario en el que se ha editado el estado `SubEstado1` cambiando su campo `Name` a `StartUp`:
<img width="75%" src="https://hackmd.io/_uploads/BkWGyntia.png"
style="display: block; margin: auto"></img>
<br/>
:::danger
---
#### Tarea a realizar
Editar la máquina de estados para modificar los nombres de los estados, pasándose a llamarse `StartUp` y `Ready`, de acuerdo a la siguiente figura:
---
:::

#### Variables y Constantes del comportamiento de CCSystemMng
<div style="text-align: justify">
Además de una máquina de estados, la definición del comportamiento a nivel de detalle de una Clase Componente requiere, generalmente, añadir un conjunto de **Variables** y **Constantes**. Para ello se debe seleccionar la pestaña `Vars and Consts` del panel que se encuentra a la derecha de la ventana y, utilizando el menú contextual (botón derecho), ejecutar la opción `New Variable or Constant` de acuerdo a la siguiente figura:
<img width="75%" src="https://hackmd.io/_uploads/r1ExwT_sp.png"
style="display: block; margin: auto"></img>
El formulario que aparece nos permite definir el Nombre de la variable (`Name`), su valor inicial (`Init Value`), así como el tipo de la variable (`Class`). La siguiente figura muestra, como ejemplo, la creación de la variable `VCommand`, que será utilizada en la clase CCSystemMng para capturar el comando recibido a través del puerto serie:
<img width="55%" src="https://hackmd.io/_uploads/HkNgn6dsa.png"
style="display: block; margin: auto"></img>
El formulario permite, además, definir constantes marcando la opción `Constant` que aparece en la parte inferior izquierda del formulario. En la siguiente figura se muestra, como ejemplo, la creación de la constante `CLEDPerido100Ms` de la clase CCSystemMng que nos permite determinar el período inicial de desplazamiento de los LEDs, fijándolo a 100 milisegundos.
<img width="55%" src="https://hackmd.io/_uploads/ryip0TOi6.png"
style="display: block; margin: auto"></img>
:::danger
---
#### Tarea a realizar
Añadir la variable `VCommand` y la constante `CLEDPerido100Ms` al contexto `Top` de `CCSystemMng` de acuerdo a lo especificado en los dos formularios anteriores.
---
:::
#### Definición de un contexto de segundo nivel añadiendo subestados al estado `StartUp`
El comportamiento de la clase `CCSystemMng` está definido por una máquina de estados de dos niveles. El segundo nivel del comportamiento gestiona la inicialización de los otros componentes del sistema, `LEDMng` y `DisplaysMng`, y se implementa mediante la definición de un contexto propio para el estado `StartUp`. Para acceder a ese contexto propio debemos seleccionar el estado `StartUp` haciendo *clic* sobre él (aparecerá con el borde en azul). Una vez seleccionado, pulsarmos el botón derecho del ratón y aparecerá un menú contextual con 3 opciones, tal como aparece en la siguiente figura:
<img width="85%" src="https://hackmd.io/_uploads/HJmj7nniT.png"
style="display: block; margin: auto"></img>
Para editar el contexto interno de `StartUp` elegiremos la opción `Go to State Context` haciendo *clic* sobre dicha opción. Al entrar en el contexto interno de `StartUp` nos encontraremos una máquina de estados vacía (sin estados), pero en la que se distinguen un punto de entrada denominado `Transition0`, representado gráficamente con el elemento <img width="6%" src="https://hackmd.io/_uploads/Hy5-K_Tja.png"
style="float: block; margin:none"></img> , y un punto de salida denominado `Transition1`, representado gráficamente por el elemento <img width="6%" src="https://hackmd.io/_uploads/H19S9OTjp.png"
style="float: block; margin:none"> .
Los puntos de entrada y salida del contexto interno de un estado están generados por transiciones definidas en el contexto superior que, respectivamente, llegan o salen de ese estado. En este caso, `Transition0` está definida en el contexto`Top` como una transición de llegada al estado `StartUp`, mientras que `Transition1` es una transición de partida. La siguiente figura muestra la situación inicial de este contexto con los citados puntos de entrada y salida:

En este contexto, y para implementar la inicialización de los dos componentes `LEDMng` y `DisplaysMng`, vamos a incluir dos estados, que denominaremos `WaitLEDReady` y `WaitDisplaysReady` (asignarles los nombres haciendo doble clic sobre ellos), que representan la espera de una notificación de que cada uno de estos componentes está listos. Para ello, y tilizando la herramienta <img width="6%" src="https://hackmd.io/_uploads/BkElPTdj6.png"
style="float: block; margin:none"></img> ya explicada previamente, añadiremos ambos estados. A continuación, y empleando la herramienta de creación de transiciones <img width="6%" src="https://hackmd.io/_uploads/r1BgDauip.png"
style="float: block; margin:none"></img>, completaremos la máquina de estados de este segundo nivel del comportamiento de acuerdo a la siguiente figura:

Finalmente, vamos a editar los nombres de las transiciones definidas en este nivel, con el fin de que representen la acción que van a tener asociada, que es la inicialización de los LEDs (`StartLED`), la inicialización del Display (`StartDisplay`) y la detección de la situación en la que los Displays ya están listos (`DisplaysReady`). Para editar el nombre de una transición (`Transicion0`), basta hacer doble *clic* sobre ella y aparecerá el siguiente formulario donde cambiaremos el nombre de la transición tal como aparece en la siguiente figura.

:::danger
---
#### Tarea a realizar
Editar el nombre de las transiciones de este contexto para que aparezcan tal como muestar la siguiente figura.
---
:::

Una vez completados los nombres de las transicione de este contexto, vamos a volver al contexto superior. Para ello, pulsaremos el botón derecho del ratón y aparecerá un menú contextual con la opción (`Go up Previous Context ...`) , tal como aparece en la siguiente figura:
<img width="85%" src="https://hackmd.io/_uploads/ry9OI5_t1l.png"
style="display: block; margin: auto"></img>
<br/>
:::danger
---
#### Tarea a realizar
Editar el nombre de las transiciones y ramas del contexto Top (haciendo doble *clic* sobre ellas) para que aparezcan tal como muestar la siguiente figura.
---
:::

#### Definición de las acciones del comportamiento a partir del escenario de respuesta al evento de reset del sistema
El sistema que se pretende desarrollar debe de responder a un conjunto de eventos. La respuesta a cada evento la podemos especificar mediante escenarios en los que se definen las acciones a ejecutar y los mensajes que intercambian los componentes para controlar la secuencia de ejecución de estas acciones. El primero de los escenarios que se va a definir es el que se muestra en la siguiente figura y que corresponde a la respuesta que debe dar el sistema tras un reset.

Sobre este escenario podemos anotar los estados en los que se encuentra cada componente cuando ejecuta cada acción, pudiendo, de esa forma, enlazar el diseño mediante el diagrama de estados del comportamiento del componente con la respuesta de acuerdo al escenario. La siguiente figura muestra esta anotación.

Volviendo al diagrama de estados de la clase CCSystemMng, podemos añadir las acciones que se han definido sobre el escenario editando la respuesta de las distintas transiciones. Por ejemplo, la ejecución de la acción (`FInit():`), asociada a inicialización, la vamos ejecutar como respuesta transición (`Init`).

Para ello se hara doble *clic* sobre la transición y aparecerá el formulario sobre el que se pueden definir las acciones de respuesta.

Pulsando el botón `New Action` podemos añadir la acción `FInit()` y editar su código.

:::danger
---
#### Tarea a realizar
Darle a la acción el nombre `FInit()` y copiar en su definición el siguiente código:
---
:::
#### CCSystemMng::CTXTop::FInit()
```c=
SerialCommand.MaskIRQ();
SerialCommand.InstallHandler();
leon3_uart_ctrl_rx_irq_enable();
leon3_uart_ctrl_rx_enable();
SerialCommand.UnMaskIRQ();
nexys_srg_gpio_init_buttons_switches();
nexys_srg_gpio_init_leds_7segs_displays();
```
Tras editar el código y pulsando el botón `OK` podemos ver cómo la acción `FInit()` aparece asociada a la transición.

Siguiendo con la definición del escenario `EvReset`, al entrar en el contexto `StartUp` el componente `SystemMngCtrl` debe enviar al componente `LEDMng` un mensaje con identificador `SLEDStart`. Esta funcionalidad la incoporamos al diseño editando la transición `StartLED` del contexto `StartUp` **haciendo doble clic** sobre dicha transición...

... asociando a su disparo la ejecución de la acción `FSendLEDStart()` ...

...y definiendo la acción `FSendLEDStart()` de acuerdo a la siguiente definición que incluye una sentencia para definir dato adjunto tomando su valor de la constante `CLEDPeriod100Ms`.

:::danger
---
#### Tarea a realizar
Añadir la acción `FSendLEDStart()` de acuerdo al anterior cuadro de diálogo y copiar en su definición el siguiente código :
---
:::
#### CCSystemMng::CTXTop::CTXStartUp:FSendLEDStart()
```c=
// Complete Data
*pSLEDStart_Data=CLEDPeriod100Ms;
```
La transición `StartDisplay`, por su parte, tiene como condición de disparo la llegada del mensaje de respuesta `SLEDReady`. De manera análoga a la transición anterior, la acción `FSendDisplaysStart()` a ejecutar hará efectivo el envio de un mensaje que indique la inicialización del componente `DisplaysMng`.

De acuerdo al escenario `EvReset`, el identificador del mensaje asíncrono que debe enviar esta acción es `SDisplaysStart`. La siguiente figura muestra configuración de la acción para hacer efectivo el envío de este mensaje asíncrono:

Finalmente, el escenario `EvReset` se puede completar asignando los estados de los componentes `LEDMng` y `DisplaysMng`, tal como muestra la siguiente figura:

De acuerdo a este escenario, será necesario modificar el diagrama de estados de las clases componente `CCLEDMng` y `CCDisplaysMng` para incoporar los nuevos estados asignados. Las siguientes secciones detallan cómo debe ser esta modificación.
### 2.7 - Definición del comportamiento de las Clase Componente CCLEDMng (Parte 1)
Analizando el escenario `EvReset` se comprueba que es necesario añadir dos nuevos estados a la clase `CCLEDMng`: `Idle` y `Ready`.
:::danger
---
#### Tarea a realizar
Añadir al comportamiento de la clase `CCLEDMng` el siguiente diagrama de estados:
---
:::

El escenario, además, determina cuál debe ser la respuesta definida en la clase componente `CCLEDMng` al recibir el mensaje `SLEDStart`.
:::danger
---
#### Tarea a realizar
Sobre este diagrama de estados, añadir la siguiente respuesta a la recepción del mensaje `SLEDStart`, correspondiente a la transición `Start`.
---
:::

Siendo el código de la acción `FGetShiftPeriod()`el siguiente:
#### CCLEDMng::CTXTop::FGetShiftPeriod()
```c=
// Data access
VShiftPeriodMicrosecs=varSLEDStart*100000;
//Limit Period
if(VShiftPeriodMicrosecs > CMaxShiftPeriodMicrosecs)
VShiftPeriodMicrosecs=CMaxShiftPeriodMicrosecs;
else if (varSLEDStart < CMinShiftPeriodMicrosecs)
VShiftPeriodMicrosecs=CMinShiftPeriodMicrosecs;
//Get Time reference
VTimeRef.GetTime();
```
Mientras que la acción `FProgShift()` programa un timer absoluta de acuerdo a la siguiente configuración:

#### CCLEDMng::CTXTop::FProgShift()
```c=
VTimeRef+=Pr_Time(0,VShiftPeriodMicrosecs); // interval of X sec + Y microsec
time= VTimeRef;
```
Finalmente, la acción `FSendLEDReady()` envía un mensaje asíncrono con señal `SLEDReady` tal como muestra la siguiente configuración:

#### Declaración de variables de la clase CCLEDMng
El código de estas acciones requiere, además, la definición del siguiente conjunto de variables y constantes que permiten controlar cómo es el desplazamiento del LED:
<img width="45%" src="https://hackmd.io/_uploads/rka0pAZqJg.png"
style="display: block; margin: auto"></img>
<img width="45%" src="https://hackmd.io/_uploads/SkTRpA-5kx.png"
style="display: block; margin: auto"></img>
<img width="45%" src="https://hackmd.io/_uploads/BkpCaAZ9Jl.png"
style="display: block; margin: auto"></img>
<img width="45%" src="https://hackmd.io/_uploads/BkpCaAZ9Jl.png"
style="display: block; margin: auto"></img>
<img width="45%" src="https://hackmd.io/_uploads/BJT2MM1aJe.png"
style="display: block; margin: auto"></img>
### 2.8 - Definición del comportamiento de la Clase Componente CCDisplaysMng (Parte 1)
Una vez definida la respuesta del componente`LEDMng` relativa al escenario `EvReset`, se procederá a definir la del componente `DisplayMng`, para lo que será neceario actualizar el comportamiento de la Clase Componente es `CCDisplaysMng`:
:::danger
---
#### Tarea a realizar
Añadir al comportamiento de la clase `CCDisplaysMng` el siguiente diagrama de estados:
---
:::

El escenario, además, determina cuál debe ser la respuesta definida en la clase componente `CCDisplaysMng` al recibir el mensaje `SDisplaysStart`.
:::danger
---
#### Tarea a realizar
Sobre este diagrama de estados, añadir la siguiente respuesta a la recepción del mensaje `SDisplaysStart`, correspondiente a la transición `Start`.
---
:::

Siendo la acción `FProgDisplaysRefresh()` la que programa un timer relativo con un intervalo de 1 ms de acuerdo a la siguiente configuración:

#### CCDisplaysMng::CTXTop::FProgDisplaysRefresh()
```c=
interval = Pr_Time(0,1000); // interval of X sec + Y microsec
```
****
Mientras que la acción `FSendDisplaysReady()` envía un mensaje asíncrono con señal `SDisplaysReady` tal como muestra la siguiente configuración:

El código previo al envío inicializa los Displays mediante las siguientes sentencias:
#### CCDisplaysMng::CTXTop::FSendDisplaysReady()
```c=
for(uint8_t i=0; i < 8 ; i++)
VDisplays7SegValue[i]=0;
nexys_srg_gpio_set_7seg_digit(7, 0) ;
```
****
#### Declaración de variable de la clase CCDisplaysMng
El código de la acción `FSendDisplaysReady()` requiere la utilización de un array, denominado `VDisplays7SegValue`, donde almacenar el valor actual de cada display. La siguiente figura muestra la declaración de este array:
<img width="45%" src="https://hackmd.io/_uploads/rk-cgJf5kg.png"
style="display: block; margin: auto"></img>
### 2.9 - Definición del comportamiento de las Clase Componente CCLEDMng (Parte 2)
Además, de dar respuesta al reset, el componente `LEDMng` debe programar períodicamente un timer para controlar el deplazamiento de los LEDS. La siguiente figura muestra el escenario que define esta programación periódica:

El diagrama de estados de la clase del componente `CCLEDMng` añade una nueva transición `ShiftTimeout` para controlar el desplazamiento de los LEDS

Para esa transición, y de acuerdo al escenario, vamos a necesitar ejecutar dos acciones del mismo tipo de forma secuencial: una que realiza el desplazamiento de los LEDs `FShiftLEDs()`, y otra ya definida previamente, denominada `FProgShift()`, que vuelve a programar el timer para disparar el siguiente desplazamiento. Para componer dos acciones es necesario primero definir las acciones simples. Dado que `FProgShift()` ya está definida, necesitaremos definir `FShiftLEDs()` utilizando el menú `New Basic Action` de la pestaña `Funtions`.
<img width="50%" src="https://hackmd.io/_uploads/SyX8JO-5kg.png"
style="display: block; margin: auto"></img>
Una vez abierto el cuadro de dialogo, se debe completar el código de la acción tal como se muestra en la siguiente figura:

, siendo el código de la acción el siguiente:
#### CCLEDMng::CTXTop::FShiftLEDs()
```c=
nexys_srg_gpio_turn_off_led(VLEDPos);
if(VShiftDirection){
VLEDPos=(VLEDPos + 1)%10;
}else{
if(VLEDPos){
VLEDPos--;
}else{
VLEDPos=9;
}
}
nexys_srg_gpio_turn_on_led(VLEDPos);
```
#### Declaración de variable de la clase CCLEDMng
El código de la acción `FShiftLEDs()` requiere la utilización de una variable `VLEDPos` que controle la posición actual del LED. La siguiente figura muestra la declaración de esta variable:
<img width="50%" src="https://hackmd.io/_uploads/BkpCaAZckx.png"
style="display: block; margin:auto">
#### Creación de la Composite Action
Una vez creadas las acciones siemples, podemos crear la acción compuesta utilizando el menú `New Composite Action` ubicado, de nuevo, en la pestaña `Functions`
<img width="50%" src="https://hackmd.io/_uploads/SyX8JO-5kg.png"
style="display: block; margin: auto"></img>
Y configuraremos la secuencia de las dos acciones tal como aparece en la siguiente figura, nombrándola`FCShiftTimeout`

En la transición `ShiftTimeout` configuraremos su disparo para asociarlo al timeout del Timer, y como respuesta asociaremos la acción compuesta que acabamos de definir `FCShiftTimeout`

### 2.10 - Definición del comportamiento de las Clase Componente CCDisplaysMng (Parte 2)
Análogamente, el componente `DisplaysMng` debe programar períodicamente un timer para controlar el refresco de los Displays. La siguiente figura muestra este escenario

Para incluir esta programación, el diagrama de estados de la Clase Componente `CCDisplaysMng` debe añadir una nueva transición, que se denomina `RefreshDisplays`, que controla el refresco de los Displays. La siguiente figura muestra esta transición:

Para esa transición, y de acuerdo al escenario, vamos a necesitar ejecutar la acción`FProgDisplayRefresh()` tal como se representa en la siguiente figura:

El código de esta acción utiliza un timer relativo para programa el refresco cada 1000 microsegundos tal como se muestra en la siguiente figura:

Además, en la entrada al estado `Ready` se ejecutará la acción `FRefreshDisplays()` que hace efectivo el refresco de los displays

La definición de esta acción se hará de acuerdo a la siguiente figura:

Siendo el código de la acción el siguiente:
#### CCDisplaysMng::CTXTop::FRefreshDisplays()
```c=
for(uint16_t i=0; i < 1000 ; i++ )
nexys_srg_gpio_seg_7seg_array(8,VDisplays7SegValue);
```
### 2.11 - Definición de la respuesta del sistema a comandos recibidos a través del puerto serie
Los siguientes tres escenarios definen la respuesta que debe de tener el sistema a comandos recibidos a través del puerto serie.



Para implementar estos escenarios será necesario modificar el comportamiento de las tres clases componentes, lo que se realizará en las siguientes secciones:
### 2.12 - Definición del comportamiento de la Clase Componente CCSystemMng (Parte 2)
El comportamiento de la clase `CCSystemMng`, definido en la siguiente figura, utiliza la transición `GetCommand` para tratar el comando recibido. Los nuevos escenarios, por tanto, van a requerir modificaciones tanto en la transición `GetCommand` como en las ramas que parten del punto de elección al que llega esta transición.

Específicamente, la transición `GetCommand` deberá capturar el caracter recibido por el puerto serie para poder ser después analizado en las distintas guardas asociadas a las ramas. La configuración de esta transición, así como de las ramas del punto de elección, se muestran a continuación, incluyendo, además, el código de la acción `FGetCommand()` asociada a la transición, el de las guardas de las ramas `GCmdIsToogleLEDShift()` y`GCmdIsIncreaseDisplays()`, y el de las acciones asociadas a cada una de las ramas `FInvokeToggleLEDShift()` y`FSendIncreaseDisplays()`
#### Transición `GetCommand`

#### Acción CCSystemMng::CTXTop::FGetCommand()

##### Código
```c=
// Data access
VCommand=varEDROOMIRQsignal;
```
</div>
#### Rama `IncreaseDisplays`

#### Guarda CCSystemMng::CTXTop::GCmdIsIncreaseDisplays()

##### Código
```c=
return (('i'==VCommand) || ('I'==VCommand));
```
#### Acción CCSystemMng::CTXTop::FSendIncreaseDisplays()

#### Rama `ToggleLEDShift`

#### Guarda CCSystemMng::CTXTop::GCmdIsToggleLEDShift()

##### Código
```c=
return (('t'==VCommand) || ('T'==VCommand));
```
#### Acción CCSystemMng::CTXTop::FInvokeToggleLEDShift()

#### Rama `NotValidCommand`

### 2.13 - Definición del comportamiento de la Clase Componente CCLEDMng (Parte 3)
:::danger
---
#### Tarea a realizar
Añadir al comportamiento de la clase `CCLEDMng` la transición` ToggleShift` de acuerdo al siguiente diagrama de estados:
---
:::

Una vez editado el comportamiento, editar la transición `ToggleShift` (Haciendo doble clic sobre ella) para poder definir su condición de disparo y la acción `FToggleShift()` que tiene asociada. La siguiente figura muestra la condición de disparo asignada que, de acuerdo al escenario `EvToggleShifts` definido anteriormente, debe corresponder a un mensaje `SToggleShifts` recibido por el puerto `LEDMngCtrl`

La acción `FReplyLEDShiftToggled()` la crearemos utilizando el botón `New Reply` que completaremos con el siguiente código que cambia el sentido del desplazamiento de los LEDS, y responde con el mensaje síncrono (Msg->Reply) con señal`SLEDShiftToggled` que es la respuesta al Invoke recibido.

##### Código de FReplyLEDShiftToggled()
```c=
VShiftDirection=!VShiftDirection;
```
Para implementar el desplazamiento de los LEDs necesitamos declarar las siguientes variables:
<img width="50%" src="https://hackmd.io/_uploads/SkpCaA-5Jl.png"
style="display: block; margin:auto">
<img width="50%" src="https://hackmd.io/_uploads/BkpCaAZckx.png"
style="display: block; margin:auto">
### 2.14 - Definición del comportamiento de la Clase Componente CCDisplaysMng (Parte 3)
#### Variables del
:::danger
---
#### Tarea a realizar
Añadir al comportamiento de la clase `CCDisplaysMng` la transición` IncreaseDisplays` de acuerdo al siguiente diagrama de estados:
---
:::

Una vez editado el comportamiento, editar la transición `IncreaseDisplays` (Haciendo doble clic sobre ella) para poder definir su condición de disparo y la acción `FIncreaseDisplays()` que tiene asociada. La siguiente figura muestra la condición de disparo asignada que, de acuerdo al escenario `EvIncreaseDisplays` definido anteriormente, debe corresponder a un mensaje `SIncreaseDisplays` recibido por el puerto `DisplaysMngCtrl`

La acción `FIncreaseDisplays()` la crearemos utilizando el botón `New Action` que completaremos con el siguiente código que incrementa el valor mostrado por los displays.

##### Código
```c=
nexys_srg_gpio_increase_seg_7seg_array(VDisplays7SegValue);
```
## Parte 3: Generación de Código
<div style="text-align: justify">
Una vez que tenemos completado el modelo, el último proceso a realizar es la generación del código. Para ello tendremos primero que fijar las opciones de generación. Dentro del Menu `Tools`, seleccionando el menú `Options` se abrirá un formulario. En la pestaña* MESP Options* tendréis que fijar las opciones relativas al path donde se genera el código y al formato de la función `main` y la sentencia `return`.
:::info
Las opciones están de acuerdo al `path` de la máquina virtual. Si vuestro proyecto Eclipse está en otra ubicación, deberéis utilizar el `path` correspondiente.
:::
La siguiente figura muestra cómo deberían quedar las opciones de generación:

Una vez fijadas las opciones, podréis generar el código con la opción `Generate MESP Code` del menú `Tools`:
<img width="45%" src="https://hackmd.io/_uploads/rkY0ijyj6.png"
style="display: block; margin: auto"></img>
</div>