---
# System prepended metadata

title: 'PDI-KISS: Solución ejercicio de autoevaluación'

---

# PDI-KISS Enunciado

[Enunciado del ejercicio](https://docs.google.com/document/d/1IEZb6pdCYwG2lYsVNfKQOlWM0U_pWKRQ/edit?usp=sharing&ouid=110814349318583191439&rtpof=true&sd=true)


# PDI-KISS: Solución ejercicio de autoevaluación

```c=
#include "riscv_types.h"
#include "riscv_uart.h"
#include "dispatch.h"

#include "log.h"

#define GAP_1_DECIMA 1000000 // tick 10 veces por segundo

#define FEND 0xC0 // Valor del delimitador de una trama KISS

// Global variables
// KISS frame array and control variables
uint32_t idx = 0, in_frame = 0, flag = 0;
uint8_t kiss_frame[256];

// Contador para el control del tiempo
uint32_t timer_counter;

// UART RX IRQ handler
void uart_rx_irq_handler (void)
{
uint8_t rec;

	rec = (uint8_t)riscv_getchar();

	if ( in_frame )
	{
		// Save received value
		kiss_frame[ idx ] = rec;
		idx++;

		if ( rec == FEND ) // fin de trama, procesar el mensaje
		{
			flag = 1;
			in_frame = 0;
		}
	}
	else
	{
		if ( rec == FEND ) // comienzo de trama, procesar el mensaje
		{
			in_frame = 1;

			// Save received value
			kiss_frame[ idx ] = rec;
			idx++;

			// La ISR del timer se ejecuta 10 veces por segundo
			// Esperaré tres segundos como máximo para la recepción de la cabecera
			timer_counter = 30;
		}
		else
		{
			printf("Not in frame -> discard data: %02X\n", rec );
		}
	}
}

void timer_handler(void)
{
	if ( in_frame )
	{
		timer_counter--;

		if ( timer_counter == 0)
		{
			// Descarto lo recibido y reseteo las variables de control
			printf("\nTimeout: Not received endding FEND.\nDiscarding data...\n");
			in_frame = 0;
			idx = 0;
		}
	}
}

int main()
{
	char mensaje[256];

	// TX/RX enable
	riscv_uart_enable_TX();
	riscv_uart_enable_RX();

	install_local_timer_handler( timer_handler );
	local_timer_set_gap( GAP_1_DECIMA ); // CLINT timer clock is 10Mh
	enable_timer_clinc_irq();

	// Install UART RX ISR and enable interrupts processing
	install_irq_handler( UART_IRQ, uart_rx_irq_handler );
	riscv_uart_enable_RI();       // Enable RX irq
	plic_irq_unmask( UART_IRQ );  // PLIC UART irq unmask
	enable_ext_irq();    	      // Enable MIE.MEI
	enable_irq();	              // Global interrupt enable

	while (1) // Super loop
	{
		if ( flag ) // Frame is complete when flag is set
		{
			// Hay que extraer el mensaje para poder imprimirlo
			// El mensaje comienza en la tercera posición, kiss_frame[2]
			// La logitud del mensaje es idx - 3

			uint32_t lng_mensaje = idx - 3;
			for (int i = 0; i < lng_mensaje; i++)
			{
				mensaje[i] = kiss_frame[i+2];
			}

			// Para poder imprimir el mensaje hay que poner el fin de cadena al final
			mensaje[ lng_mensaje] = '\0';

			printf("Mesaje recibido: %s\n", mensaje);

			// Send response
			riscv_putchar( FEND );
			riscv_putchar( 0 );
			riscv_putchar( (uint8_t)lng_mensaje);
			riscv_putchar( FEND );

			// Reset tc_header control variables
			flag  = 0;
			idx   = 0;
		}
	} // while(1)


	return 0;
}
```