CS 452/652 Spring 2025 - Assignment 0
(Version 2)
Due Date: Tue May 13, 9:00am
Introduction
In this assignment you will familiarize yourselves with the basic functionality of the Raspberry Pi, its ARM CPU, and the train controller, while learning techniques for handling asynchronous events by polling.
It is recommended that you first write, compile, and execute several simple programs for the Raspberry Pi, and only then start working on the assignment.
Description
Write a program that runs on the Raspberry Pi system.
Your program interacts with the user via the serial interface to a virtual terminal while controlling the following independent real-time activities:
- a digital clock showing minutes, seconds, and tenths of seconds, which measures time accurately, in the sense that it does not slow down or lose ticks,
- a user command interface that can be used to set train speeds and control switch turn-outs, and
- a real-time display on the terminal showing the state of the track.
The monitor should use cursor addressing (using appropriate ASCII sequences for terminal control) to display on its screen at least the following:
- the current time,
- a table of switch positions,
- a list of the most recently triggered sensors, and
- a prompt at which the user can type commands.
These four components should be organized so that the display is easy to understand.
The user command interface should support, at a minimum, the following commands.
- tr <train number> <train speed> – Set any train in motion at the desired speed (0 for stop).
- rv <train number> – The train should reverse direction. To reverse direction set the train speed to zero, wait until the train stops, send the reverse direction command, then send a speed command to re-accelerate the train to the same speed in reverse as it was going forward before the command. Do not send the reverse direction command before the train has stopped!
- sw <switch number> <switch direction> – Throw the given switch to straight (S) or curved (C). Make sure you can reliably communicate with the track and train hardware before attempting to throw switches.
IMPORTANT: A solenoid must be switched off (via Command 0x20) between 200 and 500 milliseconds after it was activated! Also, do not under any circumstances activate a switch over and over again. Doing so will burn out the solenoid!
- q – halt the program and return to boot loader (reboot).
Use the Raspberry Pi's built-in system timer (BCM Chapter 10) to implement the clock. Do not use interrupts.
Program Structure
Your program should be written as a polling loop, using I/O Channel 1 to talk to the terminal and Channel 2 to talk to the train set.
(This is the default configuration and you should always leave it so.)
The clock should not lose time.
Possibly Helpful Comments
You can use the headlight on the trains as an easy method for telling if your commands to the trains are successful.
Also, the headlights provide an indication of the current travelling direction of a train.
If you are using the various get/put/print functions from the example code for anything except debugging you are probably doing the assignment incorrectly.
The Pi-equipped workstations in the main lab have multiple serial ports.
You can run two gtkterm terminals on the workstations, with one set to the characteristics of the train interface.
In that way you can separate a hard problem, 'Is the problem that the UART transmits incorrectly or that my train commands are incorrect?' into two simpler problems.
If you send multiple consecutive commands to the Märklin control box, it might be necessary to have short pauses in between.
For most train commands, waiting 20ms should be sufficient.
For turnout switching, waiting 150ms is typically necessary.
It should not be necessary to use the Märklin 6021 manual control box other than the 'stop' and 'go' buttons (stop+go = reset).
Submission
Your readable and documented source code should be in your repository at https://git.uwaterloo.ca.
The repository must be set to 'Private' with instructor and TAs added as 'Reporter'.
Your repo should include a README-A0 file, which briefly describes how to make and operate your program.
Each student should submit a single PDF file into the A0 dropbox for this course in Learn. The PDF should include the following information:
- The commit hash value of the commit that we should be using for this assignment. The commit must be dated before the assignment deadline.
- A description of the structure of your program. Aside from testing, we will judge your program primarily on the basis of this description.
- Describe which algorithms and data structures you use and why you chose them.
- If appplicable, a description of unimplemented aspects of the assignment. Also, if you know of bugs in your implementation describe them explicitly.
- Answers to the following questions:
- How do you know that your clock does not miss updates or lose time?
- How long does the train hardware take to reply to a sensor query? (Note: To answer these questions, you need to perform and report some timing of your polling loop.)
- Make sure (test!) that the following sequence of operations results in a successful build of your program in the linux.student.cs environment. Make it clear in the README file where to find the documentation and image!
git clone <your repo>
git checkout <commit hash>
make
- The code for sensor timing measurements must be part of your submission, along with any special instructions to build, load, and run - if applicable.
We may perform code reviews with students, in which case a TA/instructor and will contact you to set up a meeting.
Three examples of highly rated documentation from previous years: