# Traffic Light and Pedestrian Crossing Controller

This project implements a two-signal traffic light controller in ARM assembly. It controls one set of LEDs for vehicle traffic and another set for a pedestrian crossing. Two pushbuttons allow the user to start or stop the system and request a pedestrian crossing.

The assembly program is written for the ARM Thumb instruction set and uses GPIO helper functions supplied by a small C program linked through CMake.

## Features

- Vehicle traffic light with green, yellow, and red LEDs
- Pedestrian traffic light with green, yellow, and red LEDs
- Start/stop pushbutton
- Pedestrian request pushbutton
- Active-low button inputs
- 20 ms software button debounce
- Safe all-red transition before changing right-of-way
- Pedestrian request flag that is stored until it can be handled safely
- Reusable assembly routine for both traffic-light groups
- Responsive timing loops that continue checking the buttons during each phase

### Required components

- Raspberry Pi Pico-compatible development board
- 2 red LEDs
- 2 yellow LEDs
- 2 green LEDs
- 6 current-limiting resistors
- 2 momentary pushbuttons
- Breadboard and jumper wires

Use an appropriate series resistor for each LED, typically between 220 ohms and 1 kilohm depending on the LED and desired brightness.

## GPIO Assignment

| Function | GPIO |
|---|---:|
| Pedestrian green LED | GP10 |
| Pedestrian yellow LED | GP11 |
| Pedestrian red LED | GP12 |
| Vehicle green LED | GP13 |
| Vehicle yellow LED | GP14 |
| Vehicle red LED | GP15 |
| Pedestrian request button | GP16 |
| Start/stop button | GP17 |

The two buttons are active-low. Each input should normally be held high with a pull-up resistor and connected to ground when pressed.

## Program Behavior

When power is applied, the program begins with `running_flag` cleared. All LEDs remain off until the start/stop button is pressed.

Pressing the start/stop button toggles the controller between two states:

- **Stopped:** all LEDs are turned off.
- **Running:** the controller alternates between the vehicle and pedestrian light cycles.

During the vehicle phase:

1. The pedestrian signal is forced to red.
2. The vehicle green LED turns on.
3. The controller waits for the green interval while checking both buttons.
4. The vehicle signal changes to yellow.
5. A safe red transition is applied before the pedestrian phase begins.

During the pedestrian phase:

1. The vehicle signal is forced to red.
2. The pedestrian light follows its green, yellow, and red sequence.
3. New pedestrian requests are ignored while the pedestrian phase is active.
4. The program returns to the vehicle phase after the cycle is complete.

## Pedestrian Request

The pedestrian button sets `ped_flag` when:

- no pedestrian request is already pending, and
- the pedestrian phase is not already active.

If the request occurs during a green phase, the controller does not change directly from green to the opposing green signal. It first turns off green, completes the yellow interval, activates both red LEDs, waits through the all-red safety interval, and then continues to the pedestrian phase.

This prevents conflicting green indications and models the safe transition used in real traffic-control systems.

## Timing

The timing routines wait in 10 ms increments. The input argument is multiplied by 10, so one timing unit represents approximately 100 ms.

| Phase | Assembly argument | Approximate duration |
|---|---:|---:|
| Green | 100 | 10 seconds |
| Yellow | 30 | 3 seconds |
| All-red safety transition | 10 | 1 second |
| Button debounce | 20 ms delay | 20 milliseconds |

The timing is approximate because it also includes the execution time of GPIO reads, function calls, and button checks.

## Assembly State Variables

The program stores three state variables in the `.data` section:

### `running_flag`

Controls whether the traffic-light sequence is running.

- `0`: stopped
- `1`: running

### `ped_flag`

Stores a pending pedestrian request.

- `0`: no request pending
- `1`: request pending

### `ped_active`

Indicates that the pedestrian-side cycle is currently active.

- `0`: pedestrian phase inactive
- `1`: pedestrian phase active

This flag prevents repeated pedestrian requests from being registered during the active pedestrian cycle.

## Main Assembly Routines

| Routine | Purpose |
|---|---|
| `traffic_light_run` | Main control loop |
| `all_off` | Turns off all six LEDs |
| `both_red` | Turns on both red LEDs and turns off the remaining LEDs |
| `phase_wait` | Handles the green interval while checking both buttons |
| `yellow_full_duration` | Handles yellow and red timing while still checking the controls |
| `check_powerSW` | Debounces and toggles the start/stop button |
| `check_ped_button` | Debounces and stores a pedestrian request |
| `pedestrian_sequence` | Applies the both-red safety transition and clears the request |
| `set_cycle_common` | Shared green-yellow-red routine used by both signal groups |
| `set1_cycle` | Loads the vehicle GPIO numbers and calls the shared cycle |
| `set2_cycle` | Loads the pedestrian GPIO numbers and calls the shared cycle |

## External Functions

The assembly file requires the following external functions:

```c
void asm_gpio_put(unsigned int gpio, unsigned int value);
unsigned int asm_gpio_get(unsigned int gpio);
void sleep_ms(uint32_t milliseconds);
```

`asm_gpio_put` and `asm_gpio_get` can be implemented as small C wrappers around the Pico SDK GPIO functions. `sleep_ms` is supplied by `pico_stdlib`.


## Building with CMake

Before building, install and configure the Raspberry Pi Pico SDK. Make sure the `PICO_SDK_PATH` environment variable points to the SDK directory.

From the project folder, run:

```bash
mkdir build
cd build
cmake ..
cmake --build .
```

The build process should generate several output files, including a `.uf2` file.

To program the board:

1. Disconnect the board from USB.
2. Hold the BOOTSEL button.
3. Connect the board to the computer through USB.
4. Release BOOTSEL.
5. Copy the generated `.uf2` file to the USB mass-storage drive.

## Processor Target Note

The assembly source contains:

```asm
.cpu cortex-m0plus
.thumb
```

This explicitly targets the Cortex-M0+ instruction set used by the RP2040-based Raspberry Pi Pico. If the project is built for a different board or processor, verify the selected CMake board target and assembler settings.

The code uses a basic Thumb instruction subset, but the project configuration should still match the actual microcontroller being programmed.

## Source File

The main source code is contained in:

```text
traffic_light.S
```

The exported assembly entry point is:

```c
extern void traffic_light_run(void);
```

## Possible Future Improvements

- Flash the pedestrian yellow LED before returning to red
- Add a minimum vehicle-green interval before accepting a pedestrian request
- Replace polling delays with hardware timer interrupts
- Add UART status messages for debugging
- Add an emergency-stop input
- Convert the controller into an explicit finite-state-machine table
- Add a countdown display for the pedestrian crossing
- Move the circuit from a breadboard to a custom PCB

## Author

Jeremias Vigo

Electrical engineering project focused on ARM assembly, GPIO control, button debouncing, and finite-state traffic-light sequencing.