feat: initial version
This commit is contained in:
@@ -0,0 +1,18 @@
|
|||||||
|
[build]
|
||||||
|
target = "thumbv6m-none-eabi"
|
||||||
|
|
||||||
|
[target.thumbv6m-none-eabi]
|
||||||
|
rustflags = [
|
||||||
|
"-C",
|
||||||
|
"link-arg=--nmagic",
|
||||||
|
"-C",
|
||||||
|
"link-arg=-Tlink.x",
|
||||||
|
"-C",
|
||||||
|
"no-vectorize-loops",
|
||||||
|
]
|
||||||
|
|
||||||
|
runner = "picotool load --update --verify --execute -t elf"
|
||||||
|
|
||||||
|
# This runner will find a supported SWD debug probe and flash your RP2040 over
|
||||||
|
# SWD:
|
||||||
|
# runner = "probe-rs run --chip RP2040"
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
/target
|
||||||
Vendored
+5
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"rust-analyzer.cargo.target": "thumbv6m-none-eabi",
|
||||||
|
"rust-analyzer.cargo.allTargets": false,
|
||||||
|
"rust-analyzer.check.allTargets": false
|
||||||
|
}
|
||||||
Generated
+1174
File diff suppressed because it is too large
Load Diff
+14
@@ -0,0 +1,14 @@
|
|||||||
|
[package]
|
||||||
|
name = "pico"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
cortex-m-rt = "0.7.5"
|
||||||
|
embedded-graphics = "0.8.2"
|
||||||
|
embedded-hal = "1.0.0"
|
||||||
|
heapless = "0.9.3"
|
||||||
|
panic-halt = "1.0.0"
|
||||||
|
rp2040-boot2 = "0.3.0"
|
||||||
|
rp2040-hal = { version = "0.12.0", features = ["critical-section-impl"] }
|
||||||
|
ssd1306 = "0.10.0"
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
use std::fs::File;
|
||||||
|
use std::io::Write;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// Put the linker script somewhere the linker can find it
|
||||||
|
let out = PathBuf::from(std::env::var_os("OUT_DIR").unwrap());
|
||||||
|
let memory_x = include_bytes!("memory.x");
|
||||||
|
let mut f = File::create(out.join("memory.x")).unwrap();
|
||||||
|
f.write_all(memory_x).unwrap();
|
||||||
|
println!("cargo:rustc-link-search={}", out.display());
|
||||||
|
println!("cargo:rerun-if-changed=build.rs");
|
||||||
|
println!("cargo:rerun-if-changed=memory.x");
|
||||||
|
}
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
MEMORY {
|
||||||
|
BOOT2 : ORIGIN = 0x10000000, LENGTH = 0x100
|
||||||
|
/*
|
||||||
|
* Here we assume you have 2048 KiB of Flash. This is what the Pi Pico
|
||||||
|
* has, but your board may have more or less Flash and you should adjust
|
||||||
|
* this value to suit.
|
||||||
|
*/
|
||||||
|
FLASH : ORIGIN = 0x10000100, LENGTH = 2048K - 0x100
|
||||||
|
/*
|
||||||
|
* RAM consists of 4 banks, SRAM0-SRAM3, with a striped mapping.
|
||||||
|
* This is usually good for performance, as it distributes load on
|
||||||
|
* those banks evenly.
|
||||||
|
*/
|
||||||
|
RAM : ORIGIN = 0x20000000, LENGTH = 256K
|
||||||
|
/*
|
||||||
|
* RAM banks 4 and 5 use a direct mapping. They can be used to have
|
||||||
|
* memory areas dedicated for some specific job, improving predictability
|
||||||
|
* of access times.
|
||||||
|
* Example: Separate stacks for core0 and core1.
|
||||||
|
*/
|
||||||
|
SRAM4 : ORIGIN = 0x20040000, LENGTH = 4k
|
||||||
|
SRAM5 : ORIGIN = 0x20041000, LENGTH = 4k
|
||||||
|
|
||||||
|
/* SRAM banks 0-3 can also be accessed directly. However, those ranges
|
||||||
|
alias with the RAM mapping, above. So don't use them at the same time!
|
||||||
|
SRAM0 : ORIGIN = 0x21000000, LENGTH = 64k
|
||||||
|
SRAM1 : ORIGIN = 0x21010000, LENGTH = 64k
|
||||||
|
SRAM2 : ORIGIN = 0x21020000, LENGTH = 64k
|
||||||
|
SRAM3 : ORIGIN = 0x21030000, LENGTH = 64k
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
EXTERN(BOOT2_FIRMWARE)
|
||||||
|
|
||||||
|
SECTIONS {
|
||||||
|
/* ### Boot loader
|
||||||
|
*
|
||||||
|
* An executable block of code which sets up the QSPI interface for
|
||||||
|
* 'Execute-In-Place' (or XIP) mode. Also sends chip-specific commands to
|
||||||
|
* the external flash chip.
|
||||||
|
*
|
||||||
|
* Must go at the start of external flash, where the Boot ROM expects it.
|
||||||
|
*/
|
||||||
|
.boot2 ORIGIN(BOOT2) :
|
||||||
|
{
|
||||||
|
KEEP(*(.boot2));
|
||||||
|
} > BOOT2
|
||||||
|
} INSERT BEFORE .text;
|
||||||
|
|
||||||
|
SECTIONS {
|
||||||
|
/* ### Boot ROM info
|
||||||
|
*
|
||||||
|
* Goes after .vector_table, to keep it in the first 512 bytes of flash,
|
||||||
|
* where picotool can find it
|
||||||
|
*/
|
||||||
|
.boot_info : ALIGN(4)
|
||||||
|
{
|
||||||
|
KEEP(*(.boot_info));
|
||||||
|
} > FLASH
|
||||||
|
|
||||||
|
} INSERT AFTER .vector_table;
|
||||||
|
|
||||||
|
/* move .text to start /after/ the boot info */
|
||||||
|
_stext = ADDR(.boot_info) + SIZEOF(.boot_info);
|
||||||
|
|
||||||
|
SECTIONS {
|
||||||
|
/* ### Picotool 'Binary Info' Entries
|
||||||
|
*
|
||||||
|
* Picotool looks through this block (as we have pointers to it in our
|
||||||
|
* header) to find interesting information.
|
||||||
|
*/
|
||||||
|
.bi_entries : ALIGN(4)
|
||||||
|
{
|
||||||
|
/* We put this in the header */
|
||||||
|
__bi_entries_start = .;
|
||||||
|
/* Here are the entries */
|
||||||
|
KEEP(*(.bi_entries));
|
||||||
|
/* Keep this block a nice round size */
|
||||||
|
. = ALIGN(4);
|
||||||
|
/* We put this in the header */
|
||||||
|
__bi_entries_end = .;
|
||||||
|
} > FLASH
|
||||||
|
} INSERT AFTER .text;
|
||||||
|
|
||||||
|
SECTIONS {
|
||||||
|
.flash_end : {
|
||||||
|
__flash_binary_end = .;
|
||||||
|
} > FLASH
|
||||||
|
} INSERT AFTER .uninit;
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
use panic_halt as _;
|
||||||
|
use rp2040_hal::{
|
||||||
|
Timer,
|
||||||
|
clocks::ClocksManager,
|
||||||
|
gpio::Pins,
|
||||||
|
pac::{self, I2C0, RESETS},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[unsafe(link_section = ".boot2")]
|
||||||
|
#[used]
|
||||||
|
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER_GENERIC_03H;
|
||||||
|
const XTAL_FREQ_HZ: u32 = 12_000_000u32;
|
||||||
|
|
||||||
|
pub struct PicoParts {
|
||||||
|
pub timer: Timer,
|
||||||
|
pub pins: Pins,
|
||||||
|
pub i2c0: I2C0,
|
||||||
|
pub resets: RESETS,
|
||||||
|
pub clocks: ClocksManager,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setup() -> PicoParts {
|
||||||
|
let mut pac = pac::Peripherals::take().unwrap();
|
||||||
|
let mut watchdog = rp2040_hal::Watchdog::new(pac.WATCHDOG);
|
||||||
|
let clocks = rp2040_hal::clocks::init_clocks_and_plls(
|
||||||
|
XTAL_FREQ_HZ,
|
||||||
|
pac.XOSC,
|
||||||
|
pac.CLOCKS,
|
||||||
|
pac.PLL_SYS,
|
||||||
|
pac.PLL_USB,
|
||||||
|
&mut pac.RESETS,
|
||||||
|
&mut watchdog,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let timer = rp2040_hal::Timer::new(pac.TIMER, &mut pac.RESETS, &clocks);
|
||||||
|
let sio = rp2040_hal::Sio::new(pac.SIO);
|
||||||
|
|
||||||
|
let pins = rp2040_hal::gpio::Pins::new(
|
||||||
|
pac.IO_BANK0,
|
||||||
|
pac.PADS_BANK0,
|
||||||
|
sio.gpio_bank0,
|
||||||
|
&mut pac.RESETS,
|
||||||
|
);
|
||||||
|
|
||||||
|
PicoParts {
|
||||||
|
timer,
|
||||||
|
pins,
|
||||||
|
i2c0: pac.I2C0,
|
||||||
|
resets: pac.RESETS,
|
||||||
|
clocks,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
use embedded_hal::digital::InputPin;
|
||||||
|
use rp2040_hal::{
|
||||||
|
Timer,
|
||||||
|
gpio::{FunctionNull, FunctionSio, Pin, PullDown, PullUp, SioInput, bank0::*},
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
lights::{PedestrianLight, TrafficLight},
|
||||||
|
phases::{PHASES, Phase},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct TrafficController {
|
||||||
|
pub phase_index: usize,
|
||||||
|
pub phase_start: u64,
|
||||||
|
pub main_traffic_light: TrafficLight<Gpio0, Gpio1, Gpio2>,
|
||||||
|
pub north_traffic_light: TrafficLight<Gpio3, Gpio4, Gpio5>,
|
||||||
|
pub south_traffic_light: TrafficLight<Gpio6, Gpio7, Gpio8>,
|
||||||
|
pub pedestrian_light: PedestrianLight<Gpio9, Gpio10>,
|
||||||
|
pub button: Pin<Gpio11, FunctionSio<SioInput>, PullUp>,
|
||||||
|
pub button_state: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TrafficController {
|
||||||
|
pub fn new(
|
||||||
|
gpio0: Pin<Gpio0, FunctionNull, PullDown>,
|
||||||
|
gpio1: Pin<Gpio1, FunctionNull, PullDown>,
|
||||||
|
gpio2: Pin<Gpio2, FunctionNull, PullDown>,
|
||||||
|
gpio3: Pin<Gpio3, FunctionNull, PullDown>,
|
||||||
|
gpio4: Pin<Gpio4, FunctionNull, PullDown>,
|
||||||
|
gpio5: Pin<Gpio5, FunctionNull, PullDown>,
|
||||||
|
gpio6: Pin<Gpio6, FunctionNull, PullDown>,
|
||||||
|
gpio7: Pin<Gpio7, FunctionNull, PullDown>,
|
||||||
|
gpio8: Pin<Gpio8, FunctionNull, PullDown>,
|
||||||
|
gpio9: Pin<Gpio9, FunctionNull, PullDown>,
|
||||||
|
gpio10: Pin<Gpio10, FunctionNull, PullDown>,
|
||||||
|
gpio11: Pin<Gpio11, FunctionNull, PullDown>,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
phase_index: 0,
|
||||||
|
phase_start: 0,
|
||||||
|
|
||||||
|
main_traffic_light: TrafficLight::new(
|
||||||
|
gpio0.into_push_pull_output(),
|
||||||
|
gpio1.into_push_pull_output(),
|
||||||
|
gpio2.into_push_pull_output(),
|
||||||
|
),
|
||||||
|
|
||||||
|
north_traffic_light: TrafficLight::new(
|
||||||
|
gpio3.into_push_pull_output(),
|
||||||
|
gpio4.into_push_pull_output(),
|
||||||
|
gpio5.into_push_pull_output(),
|
||||||
|
),
|
||||||
|
|
||||||
|
south_traffic_light: TrafficLight::new(
|
||||||
|
gpio6.into_push_pull_output(),
|
||||||
|
gpio7.into_push_pull_output(),
|
||||||
|
gpio8.into_push_pull_output(),
|
||||||
|
),
|
||||||
|
|
||||||
|
pedestrian_light: PedestrianLight::new(
|
||||||
|
gpio9.into_push_pull_output(),
|
||||||
|
gpio10.into_push_pull_output(),
|
||||||
|
),
|
||||||
|
|
||||||
|
button: gpio11.into_pull_up_input(),
|
||||||
|
button_state: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_inputs(&mut self) {
|
||||||
|
if !PHASES[self.phase_index].accepts_button_request {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.button.is_low().unwrap_or(false) {
|
||||||
|
self.button_state = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn next_phase(&mut self, now: u64) {
|
||||||
|
self.phase_index = (self.phase_index + 1) % PHASES.len();
|
||||||
|
self.phase_start = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn apply_phase(&mut self, phase: &Phase) {
|
||||||
|
self.main_traffic_light.set(&phase.main);
|
||||||
|
self.north_traffic_light.set(&phase.north);
|
||||||
|
self.south_traffic_light.set(&phase.south);
|
||||||
|
self.pedestrian_light.set(&phase.pedestrian);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn execute_cycle(&mut self, timer: &Timer) {
|
||||||
|
let now = timer.get_counter().ticks();
|
||||||
|
let elapsed = now.wrapping_sub(self.phase_start);
|
||||||
|
if elapsed < PHASES[self.phase_index].duration {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let previous_was_button_phase = PHASES[self.phase_index].requires_button_request;
|
||||||
|
self.next_phase(now);
|
||||||
|
if !self.button_state {
|
||||||
|
while PHASES[self.phase_index].requires_button_request {
|
||||||
|
self.next_phase(now);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let next_is_button_phase = PHASES[self.phase_index].requires_button_request;
|
||||||
|
|
||||||
|
if !previous_was_button_phase && next_is_button_phase {
|
||||||
|
self.button_state = false;
|
||||||
|
}
|
||||||
|
self.apply_phase(&PHASES[self.phase_index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
use embedded_graphics::{
|
||||||
|
Drawable,
|
||||||
|
geometry::Point,
|
||||||
|
mono_font::{MonoTextStyle, ascii::FONT_6X10},
|
||||||
|
pixelcolor::BinaryColor,
|
||||||
|
text::Text,
|
||||||
|
};
|
||||||
|
use rp2040_hal::{
|
||||||
|
I2C,
|
||||||
|
fugit::{Rate, RateExtU32},
|
||||||
|
gpio::{
|
||||||
|
FunctionI2C, Pin, PullUp,
|
||||||
|
bank0::{Gpio16, Gpio17},
|
||||||
|
},
|
||||||
|
pac::{I2C0, RESETS},
|
||||||
|
};
|
||||||
|
use ssd1306::{
|
||||||
|
I2CDisplayInterface, Ssd1306, mode::{BufferedGraphicsMode, DisplayConfig}, prelude::I2CInterface,
|
||||||
|
rotation::DisplayRotation, size::DisplaySize128x64,
|
||||||
|
};
|
||||||
|
|
||||||
|
type DisplayI2c = I2C<
|
||||||
|
I2C0,
|
||||||
|
(
|
||||||
|
Pin<Gpio16, FunctionI2C, PullUp>,
|
||||||
|
Pin<Gpio17, FunctionI2C, PullUp>,
|
||||||
|
),
|
||||||
|
>;
|
||||||
|
|
||||||
|
type OledDisplay =
|
||||||
|
Ssd1306<I2CInterface<DisplayI2c>, DisplaySize128x64, BufferedGraphicsMode<DisplaySize128x64>>;
|
||||||
|
|
||||||
|
pub struct DisplayModule {
|
||||||
|
display: OledDisplay,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DisplayModule {
|
||||||
|
pub fn new(
|
||||||
|
sda: Pin<Gpio16, FunctionI2C, PullUp>,
|
||||||
|
scl: Pin<Gpio17, FunctionI2C, PullUp>,
|
||||||
|
i2c0: I2C0,
|
||||||
|
resets: &mut RESETS,
|
||||||
|
freq: Rate<u32, 1, 1>,
|
||||||
|
) -> Self {
|
||||||
|
let i2c = I2C::i2c0(i2c0, sda, scl, 400.kHz(), resets, freq);
|
||||||
|
let interface = I2CDisplayInterface::new(i2c);
|
||||||
|
let mut display = Ssd1306::new(interface, DisplaySize128x64, DisplayRotation::Rotate0)
|
||||||
|
.into_buffered_graphics_mode();
|
||||||
|
|
||||||
|
display.init().unwrap();
|
||||||
|
|
||||||
|
Self { display }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn print(&mut self, text: &str) {
|
||||||
|
let style = MonoTextStyle::new(&FONT_6X10, BinaryColor::On);
|
||||||
|
|
||||||
|
Text::new(text, Point::new(0, 16), style)
|
||||||
|
.draw(&mut self.display)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
self.display.flush().unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
use embedded_hal::digital::OutputPin;
|
||||||
|
use rp2040_hal::gpio::{FunctionSio, Pin, PinId, PullDown, SioOutput};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum TrafficLightColor {
|
||||||
|
Red,
|
||||||
|
Yellow,
|
||||||
|
Green,
|
||||||
|
RedYellow,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct TrafficLight<P1: PinId, P2: PinId, P3: PinId> {
|
||||||
|
red_light: Pin<P1, FunctionSio<SioOutput>, PullDown>,
|
||||||
|
yellow_light: Pin<P2, FunctionSio<SioOutput>, PullDown>,
|
||||||
|
green_light: Pin<P3, FunctionSio<SioOutput>, PullDown>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<P1: PinId, P2: PinId, P3: PinId> TrafficLight<P1, P2, P3> {
|
||||||
|
pub fn new(
|
||||||
|
red_light: Pin<P1, FunctionSio<SioOutput>, PullDown>,
|
||||||
|
yellow_light: Pin<P2, FunctionSio<SioOutput>, PullDown>,
|
||||||
|
green_light: Pin<P3, FunctionSio<SioOutput>, PullDown>,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
red_light,
|
||||||
|
yellow_light,
|
||||||
|
green_light,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set(&mut self, color: &TrafficLightColor) {
|
||||||
|
self.red_light.set_low().ok();
|
||||||
|
self.yellow_light.set_low().ok();
|
||||||
|
self.green_light.set_low().ok();
|
||||||
|
|
||||||
|
match color {
|
||||||
|
TrafficLightColor::Red => {
|
||||||
|
self.red_light.set_high().ok();
|
||||||
|
}
|
||||||
|
TrafficLightColor::Yellow => {
|
||||||
|
self.yellow_light.set_high().ok();
|
||||||
|
}
|
||||||
|
TrafficLightColor::Green => {
|
||||||
|
self.green_light.set_high().ok();
|
||||||
|
}
|
||||||
|
TrafficLightColor::RedYellow => {
|
||||||
|
self.red_light.set_high().ok();
|
||||||
|
self.yellow_light.set_high().ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum PedestrianLightColor {
|
||||||
|
Red,
|
||||||
|
Green,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PedestrianLight<P1: PinId, P2: PinId> {
|
||||||
|
red_light: Pin<P1, FunctionSio<SioOutput>, PullDown>,
|
||||||
|
green_light: Pin<P2, FunctionSio<SioOutput>, PullDown>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<P1: PinId, P2: PinId> PedestrianLight<P1, P2> {
|
||||||
|
pub fn new(
|
||||||
|
red_light: Pin<P1, FunctionSio<SioOutput>, PullDown>,
|
||||||
|
green_light: Pin<P2, FunctionSio<SioOutput>, PullDown>,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
red_light,
|
||||||
|
green_light,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set(&mut self, color: &PedestrianLightColor) {
|
||||||
|
self.red_light.set_low().ok();
|
||||||
|
self.green_light.set_low().ok();
|
||||||
|
|
||||||
|
match color {
|
||||||
|
PedestrianLightColor::Red => {
|
||||||
|
self.red_light.set_high().ok();
|
||||||
|
}
|
||||||
|
PedestrianLightColor::Green => {
|
||||||
|
self.green_light.set_high().ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+57
@@ -0,0 +1,57 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
mod boilerplate;
|
||||||
|
mod controller;
|
||||||
|
mod display;
|
||||||
|
mod lights;
|
||||||
|
mod phases;
|
||||||
|
|
||||||
|
use boilerplate::*;
|
||||||
|
use controller::*;
|
||||||
|
use phases::*;
|
||||||
|
use rp2040_hal::Clock;
|
||||||
|
|
||||||
|
use crate::display::DisplayModule;
|
||||||
|
|
||||||
|
#[rp2040_hal::entry]
|
||||||
|
fn main() -> ! {
|
||||||
|
let PicoParts {
|
||||||
|
timer,
|
||||||
|
pins,
|
||||||
|
i2c0,
|
||||||
|
mut resets,
|
||||||
|
clocks,
|
||||||
|
} = setup();
|
||||||
|
|
||||||
|
let mut display = {
|
||||||
|
let sda = pins.gpio16.reconfigure();
|
||||||
|
let scl = pins.gpio17.reconfigure();
|
||||||
|
let freq = clocks.system_clock.freq();
|
||||||
|
|
||||||
|
DisplayModule::new(sda, scl, i2c0, &mut resets, freq)
|
||||||
|
};
|
||||||
|
display.print("Hello Pico");
|
||||||
|
|
||||||
|
let mut traffic_controller = TrafficController::new(
|
||||||
|
pins.gpio0,
|
||||||
|
pins.gpio1,
|
||||||
|
pins.gpio2,
|
||||||
|
pins.gpio3,
|
||||||
|
pins.gpio4,
|
||||||
|
pins.gpio5,
|
||||||
|
pins.gpio6,
|
||||||
|
pins.gpio7,
|
||||||
|
pins.gpio8,
|
||||||
|
pins.gpio9,
|
||||||
|
pins.gpio10,
|
||||||
|
pins.gpio11,
|
||||||
|
);
|
||||||
|
traffic_controller.phase_start = timer.get_counter().ticks();
|
||||||
|
traffic_controller.apply_phase(&PHASES[0]);
|
||||||
|
|
||||||
|
loop {
|
||||||
|
traffic_controller.read_inputs();
|
||||||
|
traffic_controller.execute_cycle(&timer);
|
||||||
|
}
|
||||||
|
}
|
||||||
+140
@@ -0,0 +1,140 @@
|
|||||||
|
use crate::lights::{PedestrianLightColor, TrafficLightColor};
|
||||||
|
|
||||||
|
pub struct Phase {
|
||||||
|
pub duration: u64,
|
||||||
|
pub main: TrafficLightColor,
|
||||||
|
pub north: TrafficLightColor,
|
||||||
|
pub south: TrafficLightColor,
|
||||||
|
pub pedestrian: PedestrianLightColor,
|
||||||
|
pub requires_button_request: bool,
|
||||||
|
pub accepts_button_request: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const PHASES: [Phase; 14] = [
|
||||||
|
Phase {
|
||||||
|
duration: 500_000,
|
||||||
|
main: TrafficLightColor::RedYellow,
|
||||||
|
north: TrafficLightColor::Red,
|
||||||
|
south: TrafficLightColor::Red,
|
||||||
|
pedestrian: PedestrianLightColor::Red,
|
||||||
|
requires_button_request: false,
|
||||||
|
accepts_button_request: true,
|
||||||
|
},
|
||||||
|
Phase {
|
||||||
|
duration: 500_000,
|
||||||
|
main: TrafficLightColor::Green,
|
||||||
|
north: TrafficLightColor::Red,
|
||||||
|
south: TrafficLightColor::Red,
|
||||||
|
pedestrian: PedestrianLightColor::Red,
|
||||||
|
requires_button_request: false,
|
||||||
|
accepts_button_request: true,
|
||||||
|
},
|
||||||
|
Phase {
|
||||||
|
duration: 500_000,
|
||||||
|
main: TrafficLightColor::Yellow,
|
||||||
|
north: TrafficLightColor::Red,
|
||||||
|
south: TrafficLightColor::Red,
|
||||||
|
pedestrian: PedestrianLightColor::Red,
|
||||||
|
requires_button_request: false,
|
||||||
|
accepts_button_request: true,
|
||||||
|
},
|
||||||
|
Phase {
|
||||||
|
duration: 500_000,
|
||||||
|
main: TrafficLightColor::Red,
|
||||||
|
north: TrafficLightColor::Red,
|
||||||
|
south: TrafficLightColor::Red,
|
||||||
|
pedestrian: PedestrianLightColor::Red,
|
||||||
|
requires_button_request: false,
|
||||||
|
accepts_button_request: true,
|
||||||
|
},
|
||||||
|
Phase {
|
||||||
|
duration: 500_000,
|
||||||
|
main: TrafficLightColor::Red,
|
||||||
|
north: TrafficLightColor::RedYellow,
|
||||||
|
south: TrafficLightColor::Red,
|
||||||
|
pedestrian: PedestrianLightColor::Red,
|
||||||
|
requires_button_request: false,
|
||||||
|
accepts_button_request: true,
|
||||||
|
},
|
||||||
|
Phase {
|
||||||
|
duration: 500_000,
|
||||||
|
main: TrafficLightColor::Red,
|
||||||
|
north: TrafficLightColor::Green,
|
||||||
|
south: TrafficLightColor::Red,
|
||||||
|
pedestrian: PedestrianLightColor::Red,
|
||||||
|
requires_button_request: false,
|
||||||
|
accepts_button_request: true,
|
||||||
|
},
|
||||||
|
Phase {
|
||||||
|
duration: 500_000,
|
||||||
|
main: TrafficLightColor::Red,
|
||||||
|
north: TrafficLightColor::Yellow,
|
||||||
|
south: TrafficLightColor::Red,
|
||||||
|
pedestrian: PedestrianLightColor::Red,
|
||||||
|
requires_button_request: false,
|
||||||
|
accepts_button_request: true,
|
||||||
|
},
|
||||||
|
Phase {
|
||||||
|
duration: 500_000,
|
||||||
|
main: TrafficLightColor::Red,
|
||||||
|
north: TrafficLightColor::Red,
|
||||||
|
south: TrafficLightColor::Red,
|
||||||
|
pedestrian: PedestrianLightColor::Red,
|
||||||
|
requires_button_request: false,
|
||||||
|
accepts_button_request: true,
|
||||||
|
},
|
||||||
|
Phase {
|
||||||
|
duration: 500_000,
|
||||||
|
main: TrafficLightColor::Red,
|
||||||
|
north: TrafficLightColor::Red,
|
||||||
|
south: TrafficLightColor::RedYellow,
|
||||||
|
pedestrian: PedestrianLightColor::Red,
|
||||||
|
requires_button_request: false,
|
||||||
|
accepts_button_request: true,
|
||||||
|
},
|
||||||
|
Phase {
|
||||||
|
duration: 500_000,
|
||||||
|
main: TrafficLightColor::Red,
|
||||||
|
north: TrafficLightColor::Red,
|
||||||
|
south: TrafficLightColor::Green,
|
||||||
|
pedestrian: PedestrianLightColor::Red,
|
||||||
|
requires_button_request: false,
|
||||||
|
accepts_button_request: true,
|
||||||
|
},
|
||||||
|
Phase {
|
||||||
|
duration: 500_000,
|
||||||
|
main: TrafficLightColor::Red,
|
||||||
|
north: TrafficLightColor::Red,
|
||||||
|
south: TrafficLightColor::Yellow,
|
||||||
|
pedestrian: PedestrianLightColor::Red,
|
||||||
|
requires_button_request: false,
|
||||||
|
accepts_button_request: true,
|
||||||
|
},
|
||||||
|
Phase {
|
||||||
|
duration: 500_000,
|
||||||
|
main: TrafficLightColor::Red,
|
||||||
|
north: TrafficLightColor::Red,
|
||||||
|
south: TrafficLightColor::Red,
|
||||||
|
pedestrian: PedestrianLightColor::Red,
|
||||||
|
requires_button_request: false,
|
||||||
|
accepts_button_request: true,
|
||||||
|
},
|
||||||
|
Phase {
|
||||||
|
duration: 500_000,
|
||||||
|
main: TrafficLightColor::Red,
|
||||||
|
north: TrafficLightColor::Red,
|
||||||
|
south: TrafficLightColor::Red,
|
||||||
|
pedestrian: PedestrianLightColor::Green,
|
||||||
|
requires_button_request: true,
|
||||||
|
accepts_button_request: false,
|
||||||
|
},
|
||||||
|
Phase {
|
||||||
|
duration: 500_000,
|
||||||
|
main: TrafficLightColor::Red,
|
||||||
|
north: TrafficLightColor::Red,
|
||||||
|
south: TrafficLightColor::Red,
|
||||||
|
pedestrian: PedestrianLightColor::Red,
|
||||||
|
requires_button_request: true,
|
||||||
|
accepts_button_request: false,
|
||||||
|
},
|
||||||
|
];
|
||||||
Reference in New Issue
Block a user