Lab 5: Polled I/O


Description
Preparation and Quiz (3 marks)
In Lab (2 marks + 1 bonus mark)
Notes

Description

In this lab you will use the polling concept for a JTAG UART (Universal Asynchronous Receiver/Transmitter that sends data over the JTAG programming cable) to control a simple game. To poll a device is to actively and continuously check its status to see if it is ready to be used in some way.

We will provide the Car World game which will be run on a PC. In this game, a car is driven around a race track in order to finish laps as fast as possible without driving off the track. Your task is to write a Nios II assembly program that will control the car (without human intervention). The program that you write will be run by the Nios II and it will communicate with the Car World game over the JTAG UART. Your program can query the state of the sensors, speed of the car, and current position on the map. Your program must then send acceleration and steering commands to drive the car.

Car World on PC controlled by DE2

The Car World Game

The goal of the Car World game is to guide the car around the track, trying to complete laps as quickly as possible. If the car drives off the track, or if F3 key of the PC keyboard is pressed, the car will reset to the starting point of the track. Below is a screenshot of the default view of the Car World game (on the left), as well as a screenshot of an alternative view (on the right), accessible through pressing F2 key of the PC keyboard.

Main view turning Secondary view turning

The car has five sensors in front. These sensors indicate whether the car is approaching the edge of track. For example, on the screenshots above, the leftmost sensor (coloured red) is reporting that it is currently off the track, while the other four sensors (coloured green) are reporting that they are on the track. Your assembly program will need to read the state of these sensors in order to make an informed decision on moving the car. Besides the sensor values, you can also read the current speed of the car, as well as its current position (x, y, and z coordinates).

To move the car you need to inform the Car World game of the desired steering and the acceleration. The text in the Car World window reports the current status of the car to help in debugging your program. To summarize, you are to write a Nios II assembly program that will continuously:

  1. Poll the sensors, speed and position data from the game,
  2. Process the collected data
  3. Adjust the steering and acceleration to keep your car moving at a reasonable speed without driving it off the track.
Your assembly program only needs to be able to drive the car so it eventually completes a lap. For example, you might start with a program that will set the initial car speed to a certain value and then continuously adjust the angle of the tires to keep the car on the track. To set the initial speed, you can set the acceleration to be positive for a short time and then set the acceleration to zero. Notice that with this approach you do not need to use the position data (x, y, and z coordinates).

However, bragging rights will be given to groups that achieve best lap times. Hence, try to optimize your code and have some fun while doing it!

The JTAG UART for User I/O

To establish communication between the Car World game and Nios II, you will be using a JTAG-based UART. A UART in general is a device which translates between parallel (many bits at a time) communication to serial (one bit at a time) communication. UARTs are often built for other serial standards such as RS-232 (e.g., "serial port"). In this lab, we will transfer data over the programming cable to avoid using a second cable. JTAG (Joint Test Action Group) is a standard interface often used for programming and debugging chips, and is used by the DE2's USB-Blaster programming. We will also use it for communicating between the Nios system and the PC.

The documentation of the JTAG UART can be found here. As listed in the documentation, bit 15 of the Data Register is a "data valid" bit. To see if data is ready to be received from the UART, one can continually poll the valid bit in a loop, and when it is valid, branch to code that handles the received data. To determine when new data can be written to the UART, one can continually, in a loop, check the available write buffer space in the Control Register[31:16]. When it is non-zero, there is room for more data to be sent to the UART.

How to Communicate with the Car World Program

The JTAG UART documentation mentioned above describes how to receive or send bytes of data. Now we proceed on describing the actual communication protocol for the Car World program that you will have to obey in order to communicate with the game.

The communication protocol for the Car World program consists of reading and writing packets of data over the JTAG UART. A packet that consists of multiple bytes must be read/written from/to the JTAG UART one byte at a time, and you must implement polling for each packet byte, as discussed above. The first byte of every packet is always the packet type. Packet types range from 0 to 5 and are in details described below. The packet length depends on the type of packet being sent.

Transmit packet types

There are in total 4 transmit packet types. These packets are sent by your program running on the Nios II to the Car World game.

Received packet types

There are 2 packet types that are sent by the Car World game as a response to transmit packet types described above.

Pseudo-code example

Below is a snippet of pseudo-code showing two subroutines for reading sensor and speed data and adjusting the tires angle.

READ_SENSORS_AND_SPEED:
  poll JTAG UART for writing
  write 2 to the JTAG UART (request sensors/speed)

  # Read response (Suggestion: Put this in a function)
  poll JTAG UART for reading
  read JTAG UART
  check that data read is 0
  poll JTAG UART for reading
  read sensor states from JTAG UART
  poll JTAG UART for reading
  read current speed from JTAG UART

  # Decide what to do
  if sensors are 0x1f
    call SET_ANGLE to steer straight
  else if sensors are 0x1e
    call SET_ANGLE to steer right
  else if sensors are 0x1c
    call SET_ANGLE to steer hard right
  else if sensors are 0x0f
    call SET_ANGLE to steer left
  else if sensors are 0x07
    call SET_ANGLE to steer hard left
  else
    hope this doesn't happen
  return

SET_ANGLE:
  poll JTAG UART for writing
  write 5 to the JTAG UART (set steering)
  poll JTAG UART for writing
  write new angle to the JTAG UART
  return

Lab Setup

  1. Please download the Lab 5 Car World package and unpack it. To start the game, ensure the DE2 is plugged in and powered on, then double click on the car_world.bat. This will:
    1. Download a modified DE2 Media Computer system onto the DE2 board. (Needed for the non-standard JTAG UART used here)
    2. Start the Car World game and establish the connection with the JTAG UART on the DE2 board.
  2. Create a new Altera Monitor project. When selecting a system, please choose <Custom System>, and specify the nios_system.sopcinfo file provided in the directory lab5_carworld/de2_car_world_system directory, as show in the figure below. Leave all the other fields blank. Alter Monitor Custom System

    For program type, specify the Assembly Program type, and then add the assembly file you wrote that will control the Car World game. Set the start offset for .text and .data sections to 0x400 (You'll need this for Lab 6).

To do these steps outside of DESL labs, besides having Altera Quartus and Altera Monitor program installed, you will need the DE2 board attached to your computer via a USB cable. If you don't have the DE2 board at home, you still must write the required Nios II assembly code and ensure that it at least compiles. For this, skip the first step and just compile your code after completing step 2.

Preparation and Quiz (3 marks)

  1. Read the documentation on the JTAG UART.
  2. Write answers to the following questions:
    1. What is the meaning of a sensor reading of 0x00?
    2. You have sent the Car World game two bytes: 0x05 followed by 0x9C. What is the meaning of this information?
    3. What bytes would you write to the JTAG UART in order to apply maximum acceleration?
  3. Write the assembly code that will guide the car around a track. Don't forget to comment your program, and use functions to keep your code organized!

Be prepared to explain

In Lab (2 marks + 1 bonus mark)

Demonstrate your working game. In the directory lab5_carworld/carworld/data/Landscape there are multiple tracks labelled for various difficulty levels (easy, medium, hard, and extreme). To change a track:

  1. If you are currently running your assembly code in the Altera Monitor Program, select Actions/Disconnect.
  2. Close all the windows opened by the car_world.bat
  3. Go to directory lab5_carworld/carworld/data/Landscape and copy the desired track file over the file landscape.txt. For example, copying landscape_medium_hill_valley.txt over landscape.txt will switch to the medium track.
  4. Run car_world.bat again and select Action/Load option in the Altera Monitor program.
You will receive:

To complete the easy tracks, the basic approach of just setting the initial speed of the car will suffice. However, due to the surface friction, the car will be slowing down, so you will probably want to adjust the speed accordingly. Moreover, the medium, hard and extreme tracks have hills which will slow down or speed up the car due to gravity, and your program will have to take this into account.

Your TA will record your best lap time on landscape_hard_hill_valley. Don't forget to submit your code.

Notes