diff --git a/firmware/application/CMakeLists.txt b/firmware/application/CMakeLists.txt index 03d7bc00..3b090eb0 100644 --- a/firmware/application/CMakeLists.txt +++ b/firmware/application/CMakeLists.txt @@ -116,6 +116,7 @@ set(CPPSRC ${COMMON}/message_queue.cpp ${COMMON}/hackrf_hal.cpp portapack.cpp + ${COMMON}/backlight.cpp ${COMMON}/portapack_shared_memory.cpp baseband_api.cpp ${COMMON}/portapack_persistent_memory.cpp diff --git a/firmware/application/event_m0.cpp b/firmware/application/event_m0.cpp index 8c35a523..411becd7 100644 --- a/firmware/application/event_m0.cpp +++ b/firmware/application/event_m0.cpp @@ -123,11 +123,12 @@ void EventDispatcher::set_display_sleep(const bool sleep) { // TODO: Distribute display sleep message more broadly, shut down data generation // on baseband side, since all that data is being discarded during sleep. if( sleep ) { - portapack::io.lcd_backlight(false); + portapack::backlight()->off(); portapack::display.sleep(); } else { portapack::display.wake(); - portapack::io.lcd_backlight(true); + // Don't turn on backlight here. + // Let frame sync handler turn on backlight after repaint. } display_sleep = sleep; }; @@ -268,6 +269,8 @@ void EventDispatcher::handle_lcd_frame_sync() { DisplayFrameSyncMessage message; message_map.send(&message); painter.paint_widget_tree(top_widget); + + portapack::backlight()->on(); } void EventDispatcher::handle_switches() { diff --git a/firmware/application/portapack.cpp b/firmware/application/portapack.cpp index 038e865b..6a1e032f 100644 --- a/firmware/application/portapack.cpp +++ b/firmware/application/portapack.cpp @@ -31,6 +31,7 @@ using namespace hackrf::one; #include "clock_manager.hpp" +#include "backlight.hpp" #include "touch_adc.hpp" #include "audio.hpp" @@ -56,6 +57,9 @@ portapack::IO io { portapack::gpio_unused, }; +portapack::BacklightCAT4004 backlight_cat4004; +portapack::BacklightOnOff backlight_on_off; + lcd::ILI9341 display; I2C i2c0(&I2CD0); @@ -147,6 +151,12 @@ static const portapack::cpld::Config& portapack_cpld_config() { ; } +Backlight* backlight() { + return (portapack_model() == PortaPackModel::R2_20170522) + ? static_cast(&backlight_cat4004) + : static_cast(&backlight_on_off); +} + static void shutdown_base() { clock_manager.shutdown(); @@ -272,6 +282,7 @@ bool init() { void shutdown() { gpdma::controller.disable(); + backlight()->off(); display.shutdown(); radio::disable(); diff --git a/firmware/application/portapack.hpp b/firmware/application/portapack.hpp index be579b7d..01a94448 100644 --- a/firmware/application/portapack.hpp +++ b/firmware/application/portapack.hpp @@ -29,6 +29,7 @@ #include "spi_pp.hpp" #include "si5351.hpp" #include "lcd_ili9341.hpp" +#include "backlight.hpp" #include "radio.hpp" #include "clock_manager.hpp" @@ -53,4 +54,6 @@ extern TemperatureLogger temperature_logger; bool init(); void shutdown(); +Backlight* backlight(); + } /* namespace portapack */ diff --git a/firmware/common/backlight.cpp b/firmware/common/backlight.cpp new file mode 100644 index 00000000..d4c00479 --- /dev/null +++ b/firmware/common/backlight.cpp @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2017 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * 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, 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; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "backlight.hpp" + +#include "portapack_io.hpp" + +namespace portapack { + +void BacklightOnOff::on() { + if( !is_on() ) { + io.lcd_backlight(true); + on_ = true; + } +} + +void BacklightOnOff::off() { + if( is_on() ) { + io.lcd_backlight(false); + on_ = false; + } +} + +void BacklightCAT4004::set_level(const value_t value) { + auto target = value; + + // Clip target value to valid range. + if( target < 0 ) { + target = 0; + } + if( target > maximum_level ) { + target = maximum_level; + } + + if( is_on() ) { + pulses(target); + } else { + level_ = target; + } +} + +void BacklightCAT4004::on() { + if( !is_on() ) { + io.lcd_backlight(true); + halPolledDelay(ticks_setup); + on_ = true; + + // Just enabled driver, initial value is maximum. + const auto target_level = level(); + level_ = maximum_level; + + pulses(target_level); + } +} + +void BacklightCAT4004::off() { + if( is_on() ) { + io.lcd_backlight(false); + chThdSleepMilliseconds(ms_pwrdwn); + on_ = false; + } +} + +void BacklightCAT4004::pulses(value_t target) { + while(level() != target) { + pulse(); + } +} + +void BacklightCAT4004::pulse() { + io.lcd_backlight(false); + halPolledDelay(ticks_lo); + io.lcd_backlight(true); + halPolledDelay(ticks_hi); + + level_ -= 1; + if( level_ < 0 ) { + level_ = levels() - 1; + } +} + +} /* namespace portapack */ diff --git a/firmware/common/backlight.hpp b/firmware/common/backlight.hpp new file mode 100644 index 00000000..cb06471c --- /dev/null +++ b/firmware/common/backlight.hpp @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2017 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * 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, 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; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#pragma once + +#include + +namespace portapack { + +class Backlight { +public: + using value_t = int_fast8_t; + + virtual ~Backlight() = default; + + virtual value_t levels() const = 0; + + virtual void set_level(const value_t value) = 0; + virtual value_t level() const = 0; + + virtual void increase() = 0; + virtual void decrease() = 0; + + virtual void on() = 0; + virtual void off() = 0; + + virtual bool is_on() const = 0; +}; + +class BacklightBase : public Backlight { +public: + void increase() override { + set_level(level() + 1); + } + + void decrease() override { + set_level(level() - 1); + } +}; + +class BacklightOnOff : public BacklightBase { +public: + value_t levels() const override { + return 1; + } + + void set_level(const value_t) override { + } + + value_t level() const override { + return levels() - 1; + } + + void on() override; + void off() override; + + bool is_on() const override { + return on_; + } + +private: + static constexpr value_t maximum_level = 1; + + bool on_ { false }; +}; + +class BacklightCAT4004 : public BacklightBase { +public: + value_t levels() const override { + return maximum_level + 1; + } + + void set_level(const value_t value) override; + + value_t level() const override { + return level_; + } + + void on() override; + void off() override; + + bool is_on() const override { + return on_; + } + +private: + static constexpr value_t initial_brightness = 25; + static constexpr value_t maximum_level = 31; + + static constexpr uint32_t ticks_setup = 204e6 * 10e-6; + static constexpr uint32_t ms_pwrdwn = 5; + static constexpr uint32_t ticks_lo = 204e6 * 1e-6; + static constexpr uint32_t ticks_hi = 204e6 * 1e-6; + + value_t level_ { initial_brightness }; + bool on_ { false }; + + void pulses(value_t target); + void pulse(); +}; + +} /* namespace portapack */ diff --git a/firmware/common/lcd_ili9341.cpp b/firmware/common/lcd_ili9341.cpp index a7908453..8a80ca2d 100644 --- a/firmware/common/lcd_ili9341.cpp +++ b/firmware/common/lcd_ili9341.cpp @@ -270,12 +270,9 @@ void lcd_vertical_scrolling_start_address( void ILI9341::init() { lcd_reset(); lcd_init(); - - io.lcd_backlight(1); } void ILI9341::shutdown() { - io.lcd_backlight(0); lcd_reset(); }