Skip to content

Commit

Permalink
pbio/port: Add explicit poweroff hook.
Browse files Browse the repository at this point in the history
Partially implements #265
  • Loading branch information
laurensvalk committed Jan 17, 2025
1 parent 1677902 commit a1cf040
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 3 deletions.
9 changes: 9 additions & 0 deletions lib/pbio/include/pbio/port_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@
* capabilities for a port.
*/
typedef enum {
/**
* No mode specified.
*/
PBIO_PORT_MODE_NONE = 0,
/**
* The port is in LEGO Powered Up mode, auto-detecting official active and
* passive components. Runs LEGO UART Messaging protocol when a LUMP device
Expand All @@ -53,6 +57,8 @@ typedef enum {

void pbio_port_init(void);

bool pbio_port_poweroff_is_ready(void);

void pbio_port_stop_user_actions(bool reset);

pbio_error_t pbio_port_get_port(pbio_port_id_t id, pbio_port_t **port);
Expand Down Expand Up @@ -82,6 +88,9 @@ pbio_error_t pbio_port_set_mode(pbio_port_t *port, pbio_port_mode_t mode);
static inline void pbio_port_init(void) {
}

static inline bool pbio_port_poweroff_is_ready(void) {
}

static inline void pbio_port_stop_user_actions(bool reset) {
}

Expand Down
28 changes: 28 additions & 0 deletions lib/pbio/src/port.c
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,30 @@ void pbio_port_stop_user_actions(bool reset) {
}
}

/**
* Prepares the system for power off by turning off all sensors and motors.
*
* @return Whether the system is ready to power off.
*/

bool pbio_port_poweroff_is_ready(void) {
// Stops motors if active, ignoring sensors that need permanent power.
pbio_port_stop_user_actions(true);

// We also want to power off sensors that need power now and stop their
// processes from triggering any further actions.
for (uint8_t i = 0; i < PBIO_CONFIG_PORT_NUM_PORTS; i++) {
pbio_port_t *port = &ports[i];
pbio_port_set_mode(port, PBIO_PORT_MODE_NONE);
}

// Use ioport platform-specific needs for power off.
pbdrv_ioport_enable_vcc(PBDRV_IOPORT_VCC_SHUTDOWN);

// REVISIT: Test button quirk here.
return true;
}

void pbio_port_process_poll(void *port) {
if (!port) {
return;
Expand Down Expand Up @@ -512,6 +536,10 @@ pbio_error_t pbio_port_set_mode(pbio_port_t *port, pbio_port_mode_t mode) {
port->mode = mode;

switch (mode) {
case PBIO_PORT_MODE_NONE:
pbdrv_ioport_p5p6_set_mode(port->pdata->pins, port->uart_dev, PBDRV_IOPORT_P5P6_MODE_GPIO_ADC);
pbio_port_p1p2_set_power(port, PBIO_PORT_POWER_REQUIREMENTS_NONE);
return PBIO_SUCCESS;
case PBIO_PORT_MODE_LEGO_PUP:
// Physical modes for this mode will be set by the process so this
// is all we need to do here.
Expand Down
10 changes: 7 additions & 3 deletions lib/pbio/sys/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@

#include <stdint.h>

#include <pbdrv/ioport.h>
#include <pbdrv/reset.h>
#include <pbdrv/usb.h>
#include <pbio/main.h>
#include <pbio/port_interface.h>
#include <pbio/protocol.h>
#include <pbsys/core.h>
#include <pbsys/main.h>
Expand Down Expand Up @@ -129,8 +129,6 @@ int main(int argc, char **argv) {
// Now lower-level processes may shutdown and/or power off.
pbsys_status_set(PBIO_PYBRICKS_STATUS_SHUTDOWN);

pbdrv_ioport_enable_vcc(PBDRV_IOPORT_VCC_SHUTDOWN);

// The power could be held on due to someone pressing the center button
// or USB being plugged in, so we have this loop to keep pumping events
// to turn off most of the peripherals and keep the battery charger running.
Expand All @@ -140,6 +138,12 @@ int main(int argc, char **argv) {
while (pbio_do_one_event()) {
}

// Prepare ports for power off but don't turn off power yet if
// ports are not ready.
if (!pbio_port_poweroff_is_ready()) {
continue;
}

#if PBSYS_CONFIG_BATTERY_CHARGER
// On hubs with USB battery chargers, we can't turn off power while
// USB is connected, otherwise it disables the op-amp that provides
Expand Down

0 comments on commit a1cf040

Please sign in to comment.