Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,7 @@ path = "examples/rust/multi_zone.rs"
[[example]]
name = "error_handling"
path = "examples/rust/error_handling.rs"

[[example]]
name = "standby"
path = "examples/rust/standby.rs"
2 changes: 1 addition & 1 deletion examples/c/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ LIB_DIR = ../../target/debug
LIB = $(LIB_DIR)/libglider_api.so
LDFLAGS = -Wl,-rpath,$(abspath $(LIB_DIR))

TARGETS = getting_started redraw mode_guide multi_zone error_handling
TARGETS = getting_started redraw mode_guide multi_zone error_handling standby

all: $(TARGETS)

Expand Down
43 changes: 43 additions & 0 deletions examples/c/standby.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Standby — put the display into low-power standby and wake it again.
*
* The display blanks the panel and stops updating while in standby.
* Call glider_exit_standby() to resume normal operation.
*
* make standby && ./standby
*/

#include <stdio.h>
#include <unistd.h>
#include "glider-api.h"

#define STANDBY_SECS 3

int main(void) {
Display *display = glider_open();
if (!display) {
fprintf(stderr, "Could not connect to display.\n");
return 1;
}

printf("Entering standby...\n");
if (glider_enter_standby(display) != SUCCESS) {
fprintf(stderr, "enter_standby failed.\n");
glider_close(display);
return 1;
}
printf("Display is in standby. Waiting %d seconds...\n", STANDBY_SECS);

sleep(STANDBY_SECS);

printf("Exiting standby...\n");
if (glider_exit_standby(display) != SUCCESS) {
fprintf(stderr, "exit_standby failed.\n");
glider_close(display);
return 1;
}
printf("Done — display resumed.\n");

glider_close(display);
return 0;
}
33 changes: 33 additions & 0 deletions examples/python/standby.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
"""
Standby — put the display into low-power standby and wake it again.

The display blanks the panel and stops updating while in standby.
Call exit_standby() to resume normal operation.

Run with a Glider connected to a device running firmware v??? or later.

python examples/python/standby.py
"""

import time
from glider_api import Display, DisplayConfig

STANDBY_SECS = 3

config = DisplayConfig.glider_standard()

try:
display = Display.new_with_config(config)
except TypeError as e:
print(f"Could not connect: {e}")
raise SystemExit(1)

print("Entering standby...")
display.enter_standby()
print(f"Display is in standby. Waiting {STANDBY_SECS} seconds...")

time.sleep(STANDBY_SECS)

print("Exiting standby...")
display.exit_standby()
print("Done — display resumed.")
35 changes: 35 additions & 0 deletions examples/rust/standby.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//! Standby — put the display into low-power standby and wake it again.
//!
//! The display blanks the panel and stops updating while in standby.
//! Call `exit_standby` to resume normal operation.
//!
//! ```
//! cargo run --example standby
//! ```

use std::{thread, time::Duration};

use glider_api::{Display, DisplayConfig};

const STANDBY_SECS: u64 = 3;

fn main() -> Result<(), Box<dyn std::error::Error>> {
let config = DisplayConfig::glider_standard();

let display = Display::new_with_config(&config).map_err(|e| {
eprintln!("Could not connect: {e}");
e
})?;

println!("Entering standby...");
display.enter_standby()?;
println!("Display is in standby. Waiting {STANDBY_SECS} seconds...");

thread::sleep(Duration::from_secs(STANDBY_SECS));

println!("Exiting standby...");
display.exit_standby()?;
println!("Done — display resumed.");

Ok(())
}
55 changes: 55 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ pub enum Mode {
}

const REPORT_ID_CONTROL: u8 = 5;
const USBCMD_POWERDOWN: u8 = 0x01;
const USBCMD_POWERUP: u8 = 0x02;
const USBCMD_REDRAW: u8 = 0x04;
const USBCMD_SETMODE: u8 = 0x05;

Expand Down Expand Up @@ -294,6 +296,37 @@ impl Display {
device.0.read_timeout(&mut response, 200).to_py_err()?;
parse_response(&response)
}

/// Put the display into standby, blanking the panel and reducing power draw.
///
/// The display stops updating until [`Display::exit_standby`] is called.
/// Call [`Display::exit_standby`] to resume normal operation.
///
/// Raises `TypeError` on USB communication errors or if the firmware
/// rejects the command.
pub fn enter_standby(&self) -> PyResult<()> {
let buf = build_display_packet(USBCMD_POWERDOWN, 0x0000, &Rect::new(0, 0, 0, 0));
let device = self.device.lock().unwrap();
device.0.write(&buf).to_py_err()?;

let mut response: [u8; 16] = [0; 16];
device.0.read_timeout(&mut response, 200).to_py_err()?;
parse_response(&response)
}

/// Wake the display from standby and resume normal operation.
///
/// Raises `TypeError` on USB communication errors or if the firmware
/// rejects the command.
pub fn exit_standby(&self) -> PyResult<()> {
let buf = build_display_packet(USBCMD_POWERUP, 0x0000, &Rect::new(0, 0, 0, 0));
let device = self.device.lock().unwrap();
device.0.write(&buf).to_py_err()?;

let mut response: [u8; 16] = [0; 16];
device.0.read_timeout(&mut response, 200).to_py_err()?;
parse_response(&response)
}
}

fn build_display_packet(cmd: u8, param: u16, area: &Rect) -> BytesMut {
Expand Down Expand Up @@ -389,6 +422,28 @@ pub extern "C" fn glider_redraw(d: *mut Display, area: Rect) -> Response {
unsafe { &*d }.redraw(&area).into()
}

/// Put the display into standby, blanking the panel and reducing power draw.
///
/// Returns `SUCCESS` (85) on success or `FAILURE` (0) on error.
#[no_mangle]
pub extern "C" fn glider_enter_standby(d: *mut Display) -> Response {
if d.is_null() {
return Response::Failure;
}
unsafe { &*d }.enter_standby().into()
}

/// Wake the display from standby and resume normal operation.
///
/// Returns `SUCCESS` (85) on success or `FAILURE` (0) on error.
#[no_mangle]
pub extern "C" fn glider_exit_standby(d: *mut Display) -> Response {
if d.is_null() {
return Response::Failure;
}
unsafe { &*d }.exit_standby().into()
}

#[pymodule]
fn glider_api(m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_class::<Display>()?;
Expand Down