Skip to content

Commit

Permalink
Merge pull request #28 from hnez/backlight
Browse files Browse the repository at this point in the history
backlight: dim the backlight when in screensaver mode
  • Loading branch information
hnez committed Sep 26, 2023
2 parents d398d60 + ca20e8d commit f18e3f0
Show file tree
Hide file tree
Showing 6 changed files with 194 additions and 0 deletions.
24 changes: 24 additions & 0 deletions openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,30 @@ paths:
schema:
$ref: '#/components/schemas/Alerts'

/v1/tac/display/backlight/brightness:
get:
summary: Get the current backlight brightness (between 0.0, and 1.0)
tags: [User Interface]
responses:
'200':
content:
application/json:
schema:
type: number
put:
summary: Set the current backlight brightness (between 0.0 and 1.0)
tags: [User Interface]
requestBody:
content:
application/json:
schema:
type: number
responses:
'204':
description: The display brightness was set sucessfully
'400':
description: The value could not be parsed as a number

/v1/tac/display/buttons:
put:
summary: Simulate a button press/release on the device
Expand Down
67 changes: 67 additions & 0 deletions src/backlight.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// This file is part of tacd, the LXA TAC system daemon
// Copyright (C) 2023 Pengutronix e.K.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

use anyhow::Result;
use async_std::prelude::*;
use async_std::sync::Arc;
use async_std::task::spawn;
use log::warn;

mod demo_mode;

#[cfg(feature = "demo_mode")]
use demo_mode::{Backlight as SysBacklight, Brightness, SysClass};

#[cfg(not(feature = "demo_mode"))]
use sysfs_class::{Backlight as SysBacklight, Brightness, SysClass};

use crate::broker::{BrokerBuilder, Topic};

pub struct Backlight {
pub brightness: Arc<Topic<f32>>,
}

impl Backlight {
pub fn new(bb: &mut BrokerBuilder) -> Result<Self> {
let brightness = bb.topic_rw("/v1/tac/display/backlight/brightness", Some(1.0));

let (mut rx, _) = brightness.clone().subscribe_unbounded();

let backlight = SysBacklight::new("backlight")?;
let max_brightness = backlight.max_brightness()?;

spawn(async move {
while let Some(fraction) = rx.next().await {
let brightness = (max_brightness as f32) * fraction;
let mut brightness = brightness.clamp(0.0, max_brightness as f32) as u64;

// A brightness of 0 turns the backlight off completely.
// If the user selects something low but not zero they likely
// want a dim glow, not completely off.
if fraction > 0.01 && brightness == 0 {
brightness = 1;
}

if let Err(e) = backlight.set_brightness(brightness) {
warn!("Failed to set LED pattern: {}", e);
}
}
});

Ok(Self { brightness })
}
}
90 changes: 90 additions & 0 deletions src/backlight/demo_mode.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// This file is part of tacd, the LXA TAC system daemon
// Copyright (C) 2023 Pengutronix e.K.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

use std::io::{Error, ErrorKind, Result};
use std::path::{Path, PathBuf};
use std::str::{from_utf8, FromStr};

use sysfs_class::{set_trait_method, trait_method};

pub trait SysClass: Sized {
fn class() -> &'static str;
unsafe fn from_path_unchecked(path: PathBuf) -> Self;
fn path(&self) -> &Path;

fn new(id: &str) -> Result<Self> {
let inst = unsafe { Self::from_path_unchecked(id.into()) };
Ok(inst)
}

fn read_file<P: AsRef<Path>>(&self, name: P) -> Result<String> {
let path = self.path().join(name);
let path = path.to_str().unwrap();

if path == "backlight/max_brightness" {
Ok("8".to_string())
} else {
Err(Error::new(ErrorKind::NotFound, format!("{path} not found")))
}
}

fn parse_file<F: FromStr, P: AsRef<Path>>(&self, name: P) -> Result<F> {
self.read_file(name)?
.parse()
.map_err(|_| Error::new(ErrorKind::InvalidData, "too bad"))
}

fn write_file<P: AsRef<Path>, S: AsRef<[u8]>>(&self, name: P, data: S) -> Result<()> {
let path = self.path().join(name);
let path = path.to_str().unwrap();
let data = from_utf8(data.as_ref()).unwrap();

log::info!("Backlight: Write {} to {}", data, path);

Ok(())
}
}

pub trait Brightness {
fn brightness(&self) -> Result<u64>;
fn max_brightness(&self) -> Result<u64>;
fn set_brightness(&self, val: u64) -> Result<()>;
}

pub struct Backlight {
path: PathBuf,
}

impl SysClass for Backlight {
fn class() -> &'static str {
"backlight"
}

unsafe fn from_path_unchecked(path: PathBuf) -> Self {
Self { path }
}

fn path(&self) -> &Path {
&self.path
}
}

impl Brightness for Backlight {
trait_method!(brightness parse_file u64);
trait_method!(max_brightness parse_file u64);
set_trait_method!("brightness", set_brightness u64);
}
4 changes: 4 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use futures::{select, FutureExt};

mod adc;
mod backlight;
mod broker;
mod dbus;
mod digital_io;
Expand All @@ -36,6 +37,7 @@ mod usb_hub;
mod watchdog;

use adc::Adc;
use backlight::Backlight;
use broker::BrokerBuilder;
use dbus::DbusSession;
use digital_io::DigitalIo;
Expand Down Expand Up @@ -64,6 +66,7 @@ async fn main() -> Result<(), std::io::Error> {
let mut bb = BrokerBuilder::new();

// Expose hardware on the TAC via the broker framework.
let backlight = Backlight::new(&mut bb).unwrap();
let led = Led::new(&mut bb);
let adc = Adc::new(&mut bb).await.unwrap();
let dut_pwr = DutPwrThread::new(
Expand Down Expand Up @@ -117,6 +120,7 @@ async fn main() -> Result<(), std::io::Error> {
let ui = {
let resources = UiResources {
adc,
backlight,
dig_io,
dut_pwr,
iobus,
Expand Down
1 change: 1 addition & 0 deletions src/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ use screens::{splash, ActivatableScreen, AlertScreen, NormalScreen, Screen};

pub struct UiResources {
pub adc: crate::adc::Adc,
pub backlight: crate::backlight::Backlight,
pub dig_io: crate::digital_io::DigitalIo,
pub dut_pwr: crate::dut_power::DutPwrThread,
pub iobus: crate::iobus::IoBus,
Expand Down
8 changes: 8 additions & 0 deletions src/ui/screens/screensaver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ struct Active {
widgets: WidgetContainer,
locator: Arc<Topic<bool>>,
alerts: Arc<Topic<AlertList>>,
brightness: Arc<Topic<f32>>,
}

impl ActivatableScreen for ScreenSaverScreen {
Expand Down Expand Up @@ -159,11 +160,16 @@ impl ActivatableScreen for ScreenSaverScreen {

let locator = ui.locator.clone();
let alerts = ui.alerts.clone();
let brightness = ui.res.backlight.brightness.clone();

// Dim to 10% brightness in screensaver mode
brightness.set(0.1);

let active = Active {
widgets,
locator,
alerts,
brightness,
};

Box::new(active)
Expand All @@ -177,6 +183,8 @@ impl ActiveScreen for Active {
}

async fn deactivate(mut self: Box<Self>) -> Display {
// Restore full backlight brightness
self.brightness.set(1.0);
self.widgets.destroy().await
}

Expand Down

0 comments on commit f18e3f0

Please sign in to comment.