Skip to content

Commit

Permalink
Merge pull request #761 from andrewdavidmackenzie/pigg_625
Browse files Browse the repository at this point in the history
Pigg 625
  • Loading branch information
andrewdavidmackenzie authored Jan 7, 2025
2 parents ea94f4d + 6b15e88 commit be2414e
Show file tree
Hide file tree
Showing 27 changed files with 1,100 additions and 849 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,9 @@ tokio = { version = "1.42", default-features = false, features = ["time", "rt",
log = { version = "0.4.22", default-features = false }

# used by piggui in GUI only
iced_aw = { git = "https://github.com/iced-rs/iced_aw.git", version = "0.11", default-features = false, features = ["menu"] }
# TODO
#iced_aw = { git = "https://github.com/iced-rs/iced_aw.git", version = "0.11", default-features = false, features = ["menu"] }
iced_aw = { git = "https://github.com/andrewdavidmackenzie/iced_aw.git", version = "0.11", default-features = false, features = ["menu"] }
iced_futures = { version = "0.13", default-features = false }
plotters-iced = { version = "0.11", default-features = false }
plotters = { version = "0.3", default-features = false, features = [
Expand Down Expand Up @@ -113,7 +115,6 @@ inherits = "release"
skip_optional_dependencies = true
denylist = ["no_std"]


[package.metadata.docs.rs]
features = ["iroh", "tcp"]
rustdoc-args = ["--cfg", "docsrs"]
5 changes: 4 additions & 1 deletion porky/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,12 @@ build-pico-w:
build-pico:
cargo build --release --bin porky --features "pico"

run:
run-w:
cargo run --release --bin porky_w --features "pico_w"

run:
cargo run --release --bin porky --features "pico"

install-uf2:
curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash
cargo binstall elf2uf2-rs
Expand Down
181 changes: 4 additions & 177 deletions porky/src/gpio.rs
Original file line number Diff line number Diff line change
@@ -1,30 +1,28 @@
use crate::gpio_input_monitor::monitor_input;
use crate::hw_definition::config::HardwareConfig;
use crate::hw_definition::config::HardwareConfigMessage;
use crate::hw_definition::config::HardwareConfigMessage::{
IOLevelChanged, NewConfig, NewPinConfig,
};
use crate::hw_definition::config::InputPull;
use crate::hw_definition::config::{HardwareConfig, LevelChange};
use crate::hw_definition::pin_function::PinFunction;
use crate::hw_definition::pin_function::PinFunction::{Input, Output};
use crate::hw_definition::{BCMPinNumber, PinLevel};
use crate::HARDWARE_EVENT_CHANNEL;
#[cfg(feature = "wifi")]
use cyw43::Control;
use defmt::{error, info};
use embassy_executor::Spawner;
use embassy_futures::select::{select, Either};
use embassy_rp::gpio::Flex;
use embassy_rp::gpio::Level;
use embassy_rp::gpio::Pull;
use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
use embassy_sync::channel::Channel;
use embassy_sync::channel::{Receiver, Sender};
use embassy_time::Instant;
use heapless::FnvIndexMap;

/// The configured/not-configured state of the GPIO Pins on the Pi Pico, and how to access them
/// as 3 of them are accessed via Cyw43 and others via gpio API
enum GPIOPin<'a> {
pub enum GPIOPin<'a> {
Available(Flex<'a>),
GPIOInput(
(
Expand All @@ -39,51 +37,11 @@ enum GPIOPin<'a> {
GPIOOutput(Flex<'a>),
}

static mut GPIO_PINS: FnvIndexMap<BCMPinNumber, GPIOPin, 32> = FnvIndexMap::new();
pub static mut GPIO_PINS: FnvIndexMap<BCMPinNumber, GPIOPin, 32> = FnvIndexMap::new();

static RETURNER: Channel<ThreadModeRawMutex, Flex, 1> = Channel::new();
static SIGNALLER: Channel<ThreadModeRawMutex, bool, 1> = Channel::new();

/// Wait until a level change on an input occurs and then send it via TCP to GUI
#[embassy_executor::task(pool_size = 32)]
async fn monitor_input(
bcm_pin_number: BCMPinNumber,
signaller: Receiver<'static, ThreadModeRawMutex, bool, 1>,
returner: Sender<'static, ThreadModeRawMutex, Flex<'static>, 1>,
mut flex: Flex<'static>,
) {
let mut level = flex.get_level();
send_input_level(bcm_pin_number, level).await;

loop {
match select(flex.wait_for_any_edge(), signaller.receive()).await {
Either::First(()) => {
let new_level = flex.get_level();
if new_level != level {
send_input_level(bcm_pin_number, flex.get_level()).await;
level = new_level;
}
}
Either::Second(_) => {
info!("Monitor returning Pin");
// Return the Flex pin and exit the task
let _ = returner.send(flex).await;
break;
}
}
}
}

/// Send a detected input level change back to the GUI, timestamping with the Duration since boot
async fn send_input_level(bcm: BCMPinNumber, level: Level) {
let level_change = LevelChange::new(
level == Level::High,
Instant::now().duration_since(Instant::MIN).into(),
);
let hardware_event = IOLevelChanged(bcm, level_change);
HARDWARE_EVENT_CHANNEL.sender().send(hardware_event).await;
}

fn into_level(value: PinLevel) -> Level {
match value {
true => Level::High,
Expand Down Expand Up @@ -145,7 +103,6 @@ async fn apply_pin_config<'a>(

match new_pin_function {
PinFunction::None => {
info!("Setting new pin function to: None");
// if we recovered a pin above - then leave it as
if let Some(flex) = flex_pin {
unsafe {
Expand All @@ -156,7 +113,6 @@ async fn apply_pin_config<'a>(
}

Input(pull) => {
info!("Setting new pin function to: Input");
match flex_pin {
Some(mut flex) => {
flex.set_as_input();
Expand Down Expand Up @@ -305,132 +261,3 @@ pub async fn apply_config_change<'a>(
HardwareConfigMessage::GetConfig => { /* Nothing to do in GPIO */ }
}
}

/// Pins available to be programmed, but are not connected to header
/// WL_GPIO0 - via CYW43 - Connected to user LED
/// WL_GPIO1 - via CYW43 - Output controls on-board SMPS power save pin
/// WL_GPIO2 - via CYW43 - Input VBUS sense - high if VBUS is present, else low
///
/// GPIO Pins Used Internally that are not in the list below
/// GP23 - Output wireless on signal - used by embassy
/// GP24 - Output/Input wireless SPI data/IRQ
/// GP25 - Output wireless SPI CS- when high enables GPIO29 ADC pin to read VSYS
/// GP29 - Output/Input SPI CLK/ADC Mode to measure VSYS/3
///
/// Refer to $ProjectRoot/assets/images/pi_pico_w_pinout.png
pub struct HeaderPins {
// Physical Pin # 1 - GP0
// Maybe in use by Debug-Probe
#[cfg(not(feature = "debug-probe"))]
pub pin_0: embassy_rp::peripherals::PIN_0,
// Physical Pin # 2 - GP1
// Maybe in use by Debug-Probe
#[cfg(not(feature = "debug-probe"))]
pub pin_1: embassy_rp::peripherals::PIN_1,
// Physical Pin # 3 - GROUND
// Physical Pin # 4 - GP2
pub pin_2: embassy_rp::peripherals::PIN_2,
// Physical Pin # 5 - GP3
pub pin_3: embassy_rp::peripherals::PIN_3,
// Physical Pin # 6 - GP4
pub pin_4: embassy_rp::peripherals::PIN_4,
// Physical Pin # 7 - GP5
pub pin_5: embassy_rp::peripherals::PIN_5,
// Physical Pin # 8 - GROUND
// Physical Pin # 9 - GP6
pub pin_6: embassy_rp::peripherals::PIN_6,
// Physical Pin # 10 - GP7
pub pin_7: embassy_rp::peripherals::PIN_7,
// Physical Pin # 11 - GP8
pub pin_8: embassy_rp::peripherals::PIN_8,
// Physical Pin # 12 - GP9
pub pin_9: embassy_rp::peripherals::PIN_9,
// Physical Pin # 13 - GROUND
// Physical Pin # 14 - GP10
pub pin_10: embassy_rp::peripherals::PIN_10,
// Physical Pin # 15 - GP11
pub pin_11: embassy_rp::peripherals::PIN_11,
// Physical Pin # 16 - GP12
pub pin_12: embassy_rp::peripherals::PIN_12,
// Physical Pin # 17 - GP13
pub pin_13: embassy_rp::peripherals::PIN_13,
// Physical Pin # 18 - GROUND
// Physical Pin # 19 - GP14
pub pin_14: embassy_rp::peripherals::PIN_14,
// Physical Pin # 20 - GP15
pub pin_15: embassy_rp::peripherals::PIN_15,
// Physical Pin # 21 - GP16
pub pin_16: embassy_rp::peripherals::PIN_16,
// Physical Pin # 22 - GP17
pub pin_17: embassy_rp::peripherals::PIN_17,
// Physical Pin # 23 - GROUND
// Physical Pin # 24 - GP18
pub pin_18: embassy_rp::peripherals::PIN_18,
// Physical Pin # 25 - GP19
pub pin_19: embassy_rp::peripherals::PIN_19,
// Physical Pin # 26 - GP20
pub pin_20: embassy_rp::peripherals::PIN_20,
// Physical Pin # 27 - GP21
pub pin_21: embassy_rp::peripherals::PIN_21,
// Physical Pin # 28 - GROUND
// Physical Pin # 29 - GP22
pub pin_22: embassy_rp::peripherals::PIN_22,
// Physical Pin # 30 - RUN
// Physical Pin # 31 - GP26
pub pin_26: embassy_rp::peripherals::PIN_26,
// Physical Pin # 32 - GP27
pub pin_27: embassy_rp::peripherals::PIN_27,
// Physical Pin # 33 - GROUND
// Physical Pin # 34 - GP28
pub pin_28: embassy_rp::peripherals::PIN_28,
// Physical Pin # 35 - ADC_VREF
// Physical Pin # 36 - 3V3
// Physical Pin # 37 - 3V3_EN
// Physical Pin # 38 - GROUND
// Physical Pin # 39 - VSYS
// Physical Pin # 40 - VBUS
}

/// Take the set of available pins not used by other functions, including the three pins that
/// are connected via the CYW43 Wi-Fi chip. Create [Flex] Pins out of each of the GPIO pins.
/// Put them all into the GPIO_PINS map, marking them as available
/// NOTE: All pin numbers are GPIO (BCM) Pin Numbers, not physical pin numbers
/// TODO we need to find a way to control these other pins
/// let _ = GPIO_PINS.insert(0, GPIOPin::CYW43Output); // GP0 connected to CYW43 chip
// #[cfg(not(feature = "debug-probe"))]
// let _ = GPIO_PINS.insert(1, GPIOPin::CYW43Output); // GP1 connected to CYW43 chip
// #[cfg(not(feature = "debug-probe"))]
// let _ = GPIO_PINS.insert(2, GPIOPin::CYW43Input); // GP2 connected to CYW43 chip
pub fn setup_pins(header_pins: HeaderPins) {
unsafe {
#[cfg(not(feature = "debug-probe"))]
let _ = GPIO_PINS.insert(0, GPIOPin::Available(Flex::new(header_pins.pin_0)));
#[cfg(not(feature = "debug-probe"))]
let _ = GPIO_PINS.insert(1, GPIOPin::Available(Flex::new(header_pins.pin_1)));
let _ = GPIO_PINS.insert(2, GPIOPin::Available(Flex::new(header_pins.pin_2)));
let _ = GPIO_PINS.insert(3, GPIOPin::Available(Flex::new(header_pins.pin_3)));
let _ = GPIO_PINS.insert(4, GPIOPin::Available(Flex::new(header_pins.pin_4)));
let _ = GPIO_PINS.insert(5, GPIOPin::Available(Flex::new(header_pins.pin_5)));
let _ = GPIO_PINS.insert(6, GPIOPin::Available(Flex::new(header_pins.pin_6)));
let _ = GPIO_PINS.insert(7, GPIOPin::Available(Flex::new(header_pins.pin_7)));
let _ = GPIO_PINS.insert(8, GPIOPin::Available(Flex::new(header_pins.pin_8)));
let _ = GPIO_PINS.insert(9, GPIOPin::Available(Flex::new(header_pins.pin_9)));
let _ = GPIO_PINS.insert(10, GPIOPin::Available(Flex::new(header_pins.pin_10)));
let _ = GPIO_PINS.insert(11, GPIOPin::Available(Flex::new(header_pins.pin_11)));
let _ = GPIO_PINS.insert(12, GPIOPin::Available(Flex::new(header_pins.pin_12)));
let _ = GPIO_PINS.insert(13, GPIOPin::Available(Flex::new(header_pins.pin_13)));
let _ = GPIO_PINS.insert(14, GPIOPin::Available(Flex::new(header_pins.pin_14)));
let _ = GPIO_PINS.insert(15, GPIOPin::Available(Flex::new(header_pins.pin_15)));
let _ = GPIO_PINS.insert(16, GPIOPin::Available(Flex::new(header_pins.pin_16)));
let _ = GPIO_PINS.insert(17, GPIOPin::Available(Flex::new(header_pins.pin_17)));
let _ = GPIO_PINS.insert(18, GPIOPin::Available(Flex::new(header_pins.pin_18)));
let _ = GPIO_PINS.insert(19, GPIOPin::Available(Flex::new(header_pins.pin_19)));
let _ = GPIO_PINS.insert(20, GPIOPin::Available(Flex::new(header_pins.pin_20)));
let _ = GPIO_PINS.insert(21, GPIOPin::Available(Flex::new(header_pins.pin_21)));
let _ = GPIO_PINS.insert(22, GPIOPin::Available(Flex::new(header_pins.pin_22)));
let _ = GPIO_PINS.insert(26, GPIOPin::Available(Flex::new(header_pins.pin_26)));
let _ = GPIO_PINS.insert(27, GPIOPin::Available(Flex::new(header_pins.pin_27)));
let _ = GPIO_PINS.insert(28, GPIOPin::Available(Flex::new(header_pins.pin_28)));
}
info!("GPIO Pins setup");
}
49 changes: 49 additions & 0 deletions porky/src/gpio_input_monitor.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
use crate::hw_definition::config::HardwareConfigMessage::IOLevelChanged;
use crate::hw_definition::config::LevelChange;
use crate::hw_definition::BCMPinNumber;
use crate::HARDWARE_EVENT_CHANNEL;
use defmt::info;
use embassy_futures::select::{select, Either};
use embassy_rp::gpio::{Flex, Level};
use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
use embassy_sync::channel::{Receiver, Sender};
use embassy_time::Instant;

/// Wait until a level change on an input occurs and then send it via TCP to GUI
#[embassy_executor::task(pool_size = 32)]
pub async fn monitor_input(
bcm_pin_number: BCMPinNumber,
signaller: Receiver<'static, ThreadModeRawMutex, bool, 1>,
returner: Sender<'static, ThreadModeRawMutex, Flex<'static>, 1>,
mut flex: Flex<'static>,
) {
let mut level = flex.get_level();
send_input_level(bcm_pin_number, level).await;

loop {
match select(flex.wait_for_any_edge(), signaller.receive()).await {
Either::First(()) => {
let new_level = flex.get_level();
if new_level != level {
send_input_level(bcm_pin_number, flex.get_level()).await;
level = new_level;
}
}
Either::Second(_) => {
info!("Monitor returning Pin");
let _ = returner.send(flex).await;
break;
}
}
}
}

/// Send a detected input level change back to the GUI, timestamping with the Duration since boot
async fn send_input_level(bcm: BCMPinNumber, level: Level) {
let level_change = LevelChange::new(
level == Level::High,
Instant::now().duration_since(Instant::MIN).into(),
);
let hardware_event = IOLevelChanged(bcm, level_change);
HARDWARE_EVENT_CHANNEL.sender().send(hardware_event).await;
}
17 changes: 2 additions & 15 deletions porky/src/persistence.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
use crate::flash;
use crate::flash::DbFlash;
use crate::hw_definition::config::HardwareConfig;
#[cfg(feature = "wifi")]
use crate::hw_definition::config::HardwareConfigMessage;
#[cfg(feature = "wifi")]
use crate::hw_definition::config::HardwareConfigMessage::{
IOLevelChanged, NewConfig, NewPinConfig,
GetConfig, IOLevelChanged, NewConfig, NewPinConfig,
};
#[cfg(feature = "wifi")]
use crate::hw_definition::description::SsidSpec;
use crate::hw_definition::pin_function::PinFunction;
#[cfg(feature = "wifi")]
use crate::hw_definition::pin_function::PinFunction::Output;
use crate::hw_definition::BCMPinNumber;
#[cfg(feature = "wifi")]
Expand Down Expand Up @@ -59,7 +56,6 @@ pub async fn get_config<'p>(
HardwareConfig { pin_functions }
}

#[cfg(feature = "wifi")]
pub async fn store_config_change<'p>(
db: &Database<DbFlash<Flash<'p, FLASH, Blocking, { flash::FLASH_SIZE }>>, NoopRawMutex>,
hardware_config_message: &HardwareConfigMessage,
Expand All @@ -77,10 +73,6 @@ pub async fn store_config_change<'p>(

// Need to do deletes and writes in separate transactions - with keys in ascending order
wtx = db.write_transaction().await;
info!(
"Storing config for {} pins in Flash DB",
config.pin_functions.len()
);
// Write the new pin configs for all pins in the config
for (bcm, pin_function) in &config.pin_functions {
let bytes = postcard::to_slice(&pin_function, &mut buf)
Expand All @@ -93,20 +85,15 @@ pub async fn store_config_change<'p>(
let bytes =
postcard::to_slice(&pin_function, &mut buf).map_err(|_| "Deserialization error")?;
wtx.write(&[*bcm], bytes).await.map_err(|_| "Write Error")?;
info!("Stored config for 1 pin in FlashDB");
}
IOLevelChanged(bcm, level_change) => {
// Write the new pin config (including the new output level), replacing any old one
let pin_function: PinFunction = Output(Some(level_change.new_level));
let bytes =
postcard::to_slice(&pin_function, &mut buf).map_err(|_| "Deserialization error")?;
wtx.write(&[*bcm], bytes).await.map_err(|_| "Write Error")?;
info!(
"Stored config for 1 Output pin with value '{}' in FlashDB",
level_change.new_level
);
}
HardwareConfigMessage::GetConfig => { /* Nothing to do in persistence */ }
GetConfig => { /* Nothing to do in persistence */ }
}

wtx.commit().await.map_err(|_| "Commit error")
Expand Down
Loading

0 comments on commit be2414e

Please sign in to comment.