---
# System prepended metadata

title: 'PDI-2025: PL1-LAB exercises'

---

# PDI-2025: PL1-LAB exercises

<!--
The purpose of this practice is to connect a four digits, 7-segment display to the GPIO port of the simulator.
-->

### First exercise: Send message tick

Code a program that detects when the buttons are pressed and released and  sends a message via the serial line indicating this circumstance.


For example, as is shown below if BT0 is pressed the message ***BT0 is pressed*** is printed ```cutecom``` window.

![Screenshot from 2024-01-19 11-47-08](https://hackmd.io/_uploads/SkVH7APYa.png)

![Screenshot from 2024-01-19 11-47-44](https://hackmd.io/_uploads/SyWv7RDFp.png)

Finally, when the button is released, the messge ***BT0 released*** is sent and printed in ```cutecom``` window.

![Screenshot from 2024-01-19 11-44-06](https://hackmd.io/_uploads/Hk2xX0DFp.png)

Complete the program to handle the other push buttons in the same way, sending a different message for each button. Do it using a for loop.

### Second exercise: Remote control of Leds

Extend the super loop of the previous exercise in order to receive single bytes. These bytes will represent ASCII digits from '0' to '7'. Any other value will be ignored.

The actions associated with each value are as follows:

| Value | Action | 
| -------- | -------- | 
| '0'     | Turn ON LED0     | 
| '1'     | Turn ON LED1     | 
| '2'     | Turn ON LED2     | 
| '3'     | Turn ON LED3     | 
| '4'     | Turn OFF LED0     | 
| '5'     | Turn OFF LED1     | 
| '6'     | Turn OFF LED2     | 
| '7'     | Turn OFF LED3     | 


After byte processing an "OK" is returned via the UART link. It is guaranteed that no bytes will be received until the previous "OK" is sent.

To test the program, send single bytes from input ```cutecom``` window and verify that leds lights as expected.

Code two programms, one using polling and the other using interrupts, to receive data sent from cutecom. 

 ### Final program using polling, only BT0

```c=
//---------------------------------------------------
// Final program using polling

#include "riscv_types.h"
#include "riscv_uart.h"
#include "gpio_drv.h"

#include "log.h"

uint32_t leds_masks[4] = { LED_0_MASK, LED_1_MASK, LED_2_MASK, LED_3_MASK };
    
int main()
{
	uint32_t dir, input;
	uint32_t bt0_current, bt0_previous;

	int32_t rec;

	// Enable output on bits 19..16
	dir = gpio_get_direction();
	dir |= 0x000F0000;
	gpio_set_direction( dir );

	bt0_current = 0;

	riscv_uart_enable_TX();
	riscv_print_string("PDI LAB\n");

	while(1)
	{
		input = gpio_read();
		bt0_previous = bt0_current;
		bt0_current  = input & BT_0_MASK;

		if ( bt0_current && !bt0_previous )
		// if ( !bt0_current && bt0_previous )
		{
			riscv_print_string("BT0 press...\n");
		}

		//if ( bt0_current && !bt0_previous )
		if ( !bt0_current && bt0_previous )
		{
			riscv_print_string("BT0 release...\n");
		}

		rec = riscv_getchar();

		if ( rec != -1 )
		{
			uint8_t car = (uint8_t) rec;

			if ((car >= '0') && (car <= '3')) // ON commands
			{
				// Turns LED ON only if it is OFF
				if ( (input & leds_masks[ car & 0x03 ]) == 0 )
				{
					printf("Turn LED%d on\n", (car & 0x03));
					input |= leds_masks[ car & 0x03 ];
					gpio_write( input );
				}
			} else if ((car >= '4') && (car <= '7')) // OFF commands
			{
				// Turns LED OFF only if it is ON
				if ( (input & leds_masks[ car & 0x03 ]) != 0 )
				{
					printf("Turn LED%d off\n", (car & 0x03));
					input &= ~leds_masks[ car & 0x03 ];
					gpio_write( input );
				}
			}
			else // Unknown command
			{
				printf("Command unknown [%d]\n", car );
			}
		}
	}

	return 0;
}
```

 ### Final program using polling, all buttons check

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

#include "dispatch.h"

#include "log.h"

#define NUM_BTS  4
#define NUM_LEDS 4

uint32_t leds_masks[NUM_LEDS] = { LED_0_MASK, LED_1_MASK, LED_2_MASK, LED_3_MASK };
uint32_t bts_masks[NUM_BTS] = { BT_0_MASK, BT_1_MASK, BT_2_MASK, BT_3_MASK };

int main()
{
	uint32_t dir, input;
	uint32_t bt_current[4] = { 0, 0, 0, 0 }, bt_previous[4];

	int32_t rec;

	printf("PDI LAB: Polling version: Buttons loop control\n");

	// Enable output on bits 19..16
	dir = gpio_get_direction();
	dir |= 0x000F0000;
	gpio_set_direction( dir );

	riscv_uart_enable_TX();
	riscv_uart_enable_RX();

	riscv_print_string("PDI LAB V1\n");

	while(1)
	{
		input = gpio_read();

		for ( int i = 0; i < NUM_BTS; i++)
		{
			bt_previous[i] = bt_current[i];
			bt_current[i] = input & bts_masks[i];

			if ( bt_current[i] && !bt_previous[i] )
			{
				riscv_print_string("BT");
				riscv_putchar( i + '0' );
				riscv_print_string(" press...\n");
			}

			if ( !bt_current[i] && bt_previous[i] )
			{
				riscv_print_string("BT");
				riscv_putchar( i + '0' );
				riscv_print_string(" release...\n");
			}
		} // for

		rec = riscv_getchar();

		if ( rec != -1 )
		{
			uint8_t car = (uint8_t) rec;

			if ((car >= '0') && (car <= '3')) // ON commands
			{
				// Turns LED ON only if it is OFF
				if ( (input & leds_masks[ car & 0x03 ]) == 0 )
				{
					printf("Turn LED%d on\n", (car & 0x03));
					input |= leds_masks[ car & 0x03 ];
					gpio_write( input );
				}
			} else if ((car >= '4') && (car <= '7')) // OFF commands
			{
				// Turns LED OFF only if it is ON
				if ( (input & leds_masks[ car & 0x03 ]) != 0 )
				{
					printf("Turn LED%d off\n", (car & 0x03));
					input &= ~leds_masks[ car & 0x03 ];
					gpio_write( input );
				}
			}
			else
			{
				printf("Command unknown [%d]\n", car );
			}
		} // if
	} // while

	return 0;
}
```

## Timed light

Code a programa that lights LED0 when BT0 is pressed. The led must light for 3 seconds and then must be turned off automatically.

:::spoiler
```c=
#include "riscv_types.h"
#include "riscv_uart.h"
#include "gpio_drv.h"

#include "dispatch.h"
#include "clinc.h"
#include "riscv_monotonic_clock.h" // For get_ticks_from_reset

#include "log.h"

#define _3SEG 30000000

int main()
{
	   uint32_t dir, input_current, input_previous;
	   uint32_t button_current, button_previous;

	   uint32_t on_flag = 0;

	   uint64_t init_ticks, current_ticks;

	   printf("PLAB-2\n");

	   // Enable output on bits 19..16
	   dir = gpio_get_direction();
	   dir |= 0x000F0000;
	   gpio_set_direction( dir );

	   input_current = gpio_read();

	   while(1)
	   {
		  input_previous = input_current;
		  input_current = gpio_read();

		  button_previous = input_previous & BT_0_MASK;
		  button_current  = input_current & BT_0_MASK;

		  if ( button_current && !button_previous )  // Rising edge
		  {
			if ( (input_current & LED_0_MASK) == 0 ) // If LED is off
			{
        			 // switch it on
        			 input_current |= LED_0_MASK;
        			 gpio_write( input_current );
			} // if

			on_flag = 1;
			init_ticks = get_ticks_from_reset();
		  } // if

		  if ( on_flag )
		  {
			current_ticks = get_ticks_from_reset();

			if ( (current_ticks - init_ticks) >= _3SEG )
			{
        			 input_current &= ~LED_0_MASK;
        			 gpio_write( input_current );
        			 on_flag = 0;
			} // if
		  } // if

	   } // while

	return 0;
}
```
:::
