mirror of
https://github.com/daveallie/crosspoint-reader.git
synced 2026-02-06 15:47:39 +03:00
basic bluetooth: on/off
This commit is contained in:
parent
6d68466891
commit
68bd425822
@ -30,6 +30,14 @@ build_flags =
|
|||||||
-std=c++2a
|
-std=c++2a
|
||||||
# Enable UTF-8 long file names in SdFat
|
# Enable UTF-8 long file names in SdFat
|
||||||
-DUSE_UTF8_LONG_NAMES=1
|
-DUSE_UTF8_LONG_NAMES=1
|
||||||
|
# BLE memory optimization flags
|
||||||
|
-DCONFIG_BT_ENABLED=1
|
||||||
|
-DCONFIG_BT_NIMBLE_ENABLED=1
|
||||||
|
-DCONFIG_NIMBLE_MAX_CONNECTIONS=1
|
||||||
|
-DCONFIG_NIMBLE_MAX_BONDS=1
|
||||||
|
-DCONFIG_NIMBLE_SVC_GAP_DEVICE_NAME_MAX_LEN=12
|
||||||
|
-DCONFIG_NIMBLE_SVC_GAP_APPEARANCE=0x0
|
||||||
|
-DCONFIG_NIMBLE_LOG_LEVEL=0
|
||||||
|
|
||||||
; Board configuration
|
; Board configuration
|
||||||
board_build.flash_mode = dio
|
board_build.flash_mode = dio
|
||||||
@ -48,6 +56,7 @@ lib_deps =
|
|||||||
bblanchon/ArduinoJson @ 7.4.2
|
bblanchon/ArduinoJson @ 7.4.2
|
||||||
ricmoo/QRCode @ 0.0.1
|
ricmoo/QRCode @ 0.0.1
|
||||||
links2004/WebSockets @ 2.7.3
|
links2004/WebSockets @ 2.7.3
|
||||||
|
h2zero/NimBLE-Arduino @ 2.1.0
|
||||||
|
|
||||||
[env:default]
|
[env:default]
|
||||||
extends = base
|
extends = base
|
||||||
|
|||||||
186
src/BluetoothManager.cpp
Normal file
186
src/BluetoothManager.cpp
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
#include "BluetoothManager.h"
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
// Static instance definition
|
||||||
|
BluetoothManager BluetoothManager::instance;
|
||||||
|
|
||||||
|
bool BluetoothManager::initialize() {
|
||||||
|
#ifdef CONFIG_BT_ENABLED
|
||||||
|
// Prevent double initialization
|
||||||
|
if (initialized) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.printf("[%lu] [BLE] Initializing Bluetooth\n", millis());
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Initialize NimBLE device with minimal configuration
|
||||||
|
BLEDevice::init(DEVICE_NAME);
|
||||||
|
|
||||||
|
// Create server if needed
|
||||||
|
if (!createServer()) {
|
||||||
|
Serial.printf("[%lu] [BLE] Failed to create server\n", millis());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup advertising
|
||||||
|
setupAdvertising();
|
||||||
|
|
||||||
|
initialized = true;
|
||||||
|
Serial.printf("[%lu] [BLE] Bluetooth initialized successfully\n", millis());
|
||||||
|
Serial.printf("[%lu] [BLE] Free heap after init: %d bytes\n", millis(), ESP.getFreeHeap());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} catch (...) {
|
||||||
|
Serial.printf("[%lu] [BLE] Exception during initialization\n", millis());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
Serial.printf("[%lu] [BLE] Bluetooth disabled in build\n", millis());
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void BluetoothManager::shutdown() {
|
||||||
|
#ifdef CONFIG_BT_ENABLED
|
||||||
|
if (!initialized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.printf("[%lu] [BLE] Shutting down Bluetooth\n", millis());
|
||||||
|
|
||||||
|
// Stop advertising
|
||||||
|
stopAdvertising();
|
||||||
|
|
||||||
|
// Deinitialize BLE device
|
||||||
|
BLEDevice::deinit();
|
||||||
|
|
||||||
|
// Clean up pointers
|
||||||
|
pServer = nullptr;
|
||||||
|
pAdvertising = nullptr;
|
||||||
|
|
||||||
|
initialized = false;
|
||||||
|
advertising = false;
|
||||||
|
|
||||||
|
Serial.printf("[%lu] [BLE] Bluetooth shutdown complete\n", millis());
|
||||||
|
Serial.printf("[%lu] [BLE] Free heap after shutdown: %d bytes\n", millis(), ESP.getFreeHeap());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BluetoothManager::startAdvertising() {
|
||||||
|
#ifdef CONFIG_BT_ENABLED
|
||||||
|
if (!initialized || advertising) {
|
||||||
|
return advertising;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pAdvertising && pAdvertising->start()) {
|
||||||
|
advertising = true;
|
||||||
|
Serial.printf("[%lu] [BLE] Advertising started\n", millis());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.printf("[%lu] [BLE] Failed to start advertising\n", millis());
|
||||||
|
return false;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void BluetoothManager::stopAdvertising() {
|
||||||
|
#ifdef CONFIG_BT_ENABLED
|
||||||
|
if (!advertising || !pAdvertising) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pAdvertising->stop();
|
||||||
|
advertising = false;
|
||||||
|
Serial.printf("[%lu] [BLE] Advertising stopped\n", millis());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t BluetoothManager::getMemoryUsage() const {
|
||||||
|
#ifdef CONFIG_BT_ENABLED
|
||||||
|
if (!initialized) {
|
||||||
|
return sizeof(*this); // Base object size (~20 bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Estimate BLE stack memory usage
|
||||||
|
size_t baseUsage = sizeof(*this);
|
||||||
|
size_t stackUsage = 0;
|
||||||
|
|
||||||
|
// NimBLE stack typically uses 12-15KB RAM
|
||||||
|
if (pServer) {
|
||||||
|
stackUsage += 12288; // Conservative estimate
|
||||||
|
}
|
||||||
|
|
||||||
|
return baseUsage + stackUsage;
|
||||||
|
#else
|
||||||
|
return sizeof(*this); // Minimal usage when disabled
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void BluetoothManager::collectGarbage() {
|
||||||
|
#ifdef CONFIG_BT_ENABLED
|
||||||
|
if (!initialized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Force garbage collection in NimBLE
|
||||||
|
NimBLEDevice::getScan()->clearResults();
|
||||||
|
|
||||||
|
Serial.printf("[%lu] [BLE] Garbage collection complete\n", millis());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_BT_ENABLED
|
||||||
|
bool BluetoothManager::createServer() {
|
||||||
|
try {
|
||||||
|
// Create BLE server with minimal configuration
|
||||||
|
pServer = BLEDevice::createServer();
|
||||||
|
if (!pServer) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set callbacks with minimal overhead
|
||||||
|
pServer->setCallbacks(new ServerCallbacks());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} catch (...) {
|
||||||
|
pServer = nullptr;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BluetoothManager::setupAdvertising() {
|
||||||
|
if (!pServer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pAdvertising = BLEDevice::getAdvertising();
|
||||||
|
if (!pAdvertising) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Minimal advertising configuration
|
||||||
|
pAdvertising->addServiceUUID(BLEUUID((uint16_t)0x1800)); // Generic Access
|
||||||
|
pAdvertising->setScanResponse(false); // Save power and memory
|
||||||
|
pAdvertising->setMinPreferred(0x0); // No preferred connections
|
||||||
|
pAdvertising->setMaxPreferred(0x0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BluetoothManager::ServerCallbacks::onConnect(BLEServer* pServer) {
|
||||||
|
Serial.printf("[%lu] [BLE] Device connected\n", millis());
|
||||||
|
|
||||||
|
// Restart advertising for more connections (though we only allow 1)
|
||||||
|
BLEDevice::getAdvertising()->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BluetoothManager::ServerCallbacks::onDisconnect(BLEServer* pServer) {
|
||||||
|
Serial.printf("[%lu] [BLE] Device disconnected\n", millis());
|
||||||
|
|
||||||
|
// Restart advertising
|
||||||
|
BLEDevice::getAdvertising()->start();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
124
src/BluetoothManager.h
Normal file
124
src/BluetoothManager.h
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
// Forward declarations to minimize includes when BLE is disabled
|
||||||
|
#ifdef CONFIG_BT_ENABLED
|
||||||
|
#include <NimBLEDevice.h>
|
||||||
|
#include <NimBLEServer.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Memory-efficient Bluetooth Manager for CrossPoint Reader
|
||||||
|
*
|
||||||
|
* Design principles:
|
||||||
|
* - Singleton pattern to minimize memory usage
|
||||||
|
* - Conditional compilation to avoid BLE overhead when disabled
|
||||||
|
* - Minimal RAM footprint (~2-3KB when disabled, ~15KB when enabled)
|
||||||
|
* - Lazy initialization only when needed
|
||||||
|
* - Clean shutdown to prevent memory leaks
|
||||||
|
*/
|
||||||
|
class BluetoothManager {
|
||||||
|
private:
|
||||||
|
// Private constructor for singleton
|
||||||
|
BluetoothManager() = default;
|
||||||
|
|
||||||
|
// Static instance
|
||||||
|
static BluetoothManager instance;
|
||||||
|
|
||||||
|
// State tracking (minimal memory usage)
|
||||||
|
bool initialized = false;
|
||||||
|
bool advertising = false;
|
||||||
|
|
||||||
|
#ifdef CONFIG_BT_ENABLED
|
||||||
|
// BLE components (only allocated when BLE is enabled)
|
||||||
|
BLEServer* pServer = nullptr;
|
||||||
|
BLEAdvertising* pAdvertising = nullptr;
|
||||||
|
|
||||||
|
// Device name (short to save memory)
|
||||||
|
static constexpr const char* DEVICE_NAME = "CrossPoint";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Delete copy constructor and assignment
|
||||||
|
BluetoothManager(const BluetoothManager&) = delete;
|
||||||
|
BluetoothManager& operator=(const BluetoothManager&) = delete;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get singleton instance
|
||||||
|
* @return Reference to BluetoothManager instance
|
||||||
|
*/
|
||||||
|
static BluetoothManager& getInstance() { return instance; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize Bluetooth stack
|
||||||
|
* @return true if initialization successful, false otherwise
|
||||||
|
*/
|
||||||
|
bool initialize();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shutdown Bluetooth stack to free memory
|
||||||
|
*/
|
||||||
|
void shutdown();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start advertising device
|
||||||
|
* @return true if advertising started successfully
|
||||||
|
*/
|
||||||
|
bool startAdvertising();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop advertising to save power
|
||||||
|
*/
|
||||||
|
void stopAdvertising();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if Bluetooth is initialized
|
||||||
|
* @return true if initialized
|
||||||
|
*/
|
||||||
|
bool isInitialized() const { return initialized; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if currently advertising
|
||||||
|
* @return true if advertising
|
||||||
|
*/
|
||||||
|
bool isAdvertising() const { return advertising; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get memory usage information
|
||||||
|
* @return Estimated RAM usage in bytes
|
||||||
|
*/
|
||||||
|
size_t getMemoryUsage() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Force garbage collection to free unused memory
|
||||||
|
*/
|
||||||
|
void collectGarbage();
|
||||||
|
|
||||||
|
private:
|
||||||
|
#ifdef CONFIG_BT_ENABLED
|
||||||
|
/**
|
||||||
|
* Create BLE server with minimal services
|
||||||
|
* @return true if server created successfully
|
||||||
|
*/
|
||||||
|
bool createServer();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setup advertising data with minimal payload
|
||||||
|
*/
|
||||||
|
void setupAdvertising();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BLE server callbacks (minimal implementation)
|
||||||
|
*/
|
||||||
|
class ServerCallbacks : public BLEServerCallbacks {
|
||||||
|
public:
|
||||||
|
void onConnect(BLEServer* pServer) override;
|
||||||
|
void onDisconnect(BLEServer* pServer) override;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
// Convenience macro for accessing the manager
|
||||||
|
#define BLUETOOTH_MANAGER BluetoothManager::getInstance()
|
||||||
@ -58,6 +58,9 @@ class CrossPointSettings {
|
|||||||
// Hide battery percentage
|
// Hide battery percentage
|
||||||
enum HIDE_BATTERY_PERCENTAGE { HIDE_NEVER = 0, HIDE_READER = 1, HIDE_ALWAYS = 2 };
|
enum HIDE_BATTERY_PERCENTAGE { HIDE_NEVER = 0, HIDE_READER = 1, HIDE_ALWAYS = 2 };
|
||||||
|
|
||||||
|
// Bluetooth mode settings
|
||||||
|
enum BLUETOOTH_MODE { OFF = 0, ON = 1 };
|
||||||
|
|
||||||
// Sleep screen settings
|
// Sleep screen settings
|
||||||
uint8_t sleepScreen = DARK;
|
uint8_t sleepScreen = DARK;
|
||||||
// Sleep screen cover mode settings
|
// Sleep screen cover mode settings
|
||||||
@ -94,6 +97,8 @@ class CrossPointSettings {
|
|||||||
uint8_t hideBatteryPercentage = HIDE_NEVER;
|
uint8_t hideBatteryPercentage = HIDE_NEVER;
|
||||||
// Long-press chapter skip on side buttons
|
// Long-press chapter skip on side buttons
|
||||||
uint8_t longPressChapterSkip = 1;
|
uint8_t longPressChapterSkip = 1;
|
||||||
|
// Bluetooth enabled setting
|
||||||
|
uint8_t bluetoothEnabled = OFF;
|
||||||
|
|
||||||
~CrossPointSettings() = default;
|
~CrossPointSettings() = default;
|
||||||
|
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
|
#include "BluetoothManager.h"
|
||||||
#include "CalibreSettingsActivity.h"
|
#include "CalibreSettingsActivity.h"
|
||||||
#include "CrossPointSettings.h"
|
#include "CrossPointSettings.h"
|
||||||
#include "KOReaderSettingsActivity.h"
|
#include "KOReaderSettingsActivity.h"
|
||||||
@ -14,7 +15,7 @@
|
|||||||
|
|
||||||
// Define the static settings list
|
// Define the static settings list
|
||||||
namespace {
|
namespace {
|
||||||
constexpr int settingsCount = 22;
|
constexpr int settingsCount = 23;
|
||||||
const SettingInfo settingsList[settingsCount] = {
|
const SettingInfo settingsList[settingsCount] = {
|
||||||
// Should match with SLEEP_SCREEN_MODE
|
// Should match with SLEEP_SCREEN_MODE
|
||||||
SettingInfo::Enum("Sleep Screen", &CrossPointSettings::sleepScreen, {"Dark", "Light", "Custom", "Cover", "None"}),
|
SettingInfo::Enum("Sleep Screen", &CrossPointSettings::sleepScreen, {"Dark", "Light", "Custom", "Cover", "None"}),
|
||||||
@ -43,6 +44,7 @@ const SettingInfo settingsList[settingsCount] = {
|
|||||||
{"1 min", "5 min", "10 min", "15 min", "30 min"}),
|
{"1 min", "5 min", "10 min", "15 min", "30 min"}),
|
||||||
SettingInfo::Enum("Refresh Frequency", &CrossPointSettings::refreshFrequency,
|
SettingInfo::Enum("Refresh Frequency", &CrossPointSettings::refreshFrequency,
|
||||||
{"1 page", "5 pages", "10 pages", "15 pages", "30 pages"}),
|
{"1 page", "5 pages", "10 pages", "15 pages", "30 pages"}),
|
||||||
|
SettingInfo::Enum("Bluetooth", &CrossPointSettings::bluetoothEnabled, {"Off", "On"}),
|
||||||
SettingInfo::Action("KOReader Sync"),
|
SettingInfo::Action("KOReader Sync"),
|
||||||
SettingInfo::Action("Calibre Settings"),
|
SettingInfo::Action("Calibre Settings"),
|
||||||
SettingInfo::Action("Check for updates")};
|
SettingInfo::Action("Check for updates")};
|
||||||
@ -130,7 +132,28 @@ void SettingsActivity::toggleCurrentSetting() {
|
|||||||
SETTINGS.*(setting.valuePtr) = !currentValue;
|
SETTINGS.*(setting.valuePtr) = !currentValue;
|
||||||
} else if (setting.type == SettingType::ENUM && setting.valuePtr != nullptr) {
|
} else if (setting.type == SettingType::ENUM && setting.valuePtr != nullptr) {
|
||||||
const uint8_t currentValue = SETTINGS.*(setting.valuePtr);
|
const uint8_t currentValue = SETTINGS.*(setting.valuePtr);
|
||||||
SETTINGS.*(setting.valuePtr) = (currentValue + 1) % static_cast<uint8_t>(setting.enumValues.size());
|
const uint8_t newValue = (currentValue + 1) % static_cast<uint8_t>(setting.enumValues.size());
|
||||||
|
SETTINGS.*(setting.valuePtr) = newValue;
|
||||||
|
|
||||||
|
// Handle Bluetooth toggle specifically
|
||||||
|
if (strcmp(setting.name, "Bluetooth") == 0) {
|
||||||
|
if (newValue == CrossPointSettings::BLUETOOTH_MODE::ON) {
|
||||||
|
// Enable Bluetooth
|
||||||
|
if (!BLUETOOTH_MANAGER.isInitialized()) {
|
||||||
|
if (BLUETOOTH_MANAGER.initialize()) {
|
||||||
|
BLUETOOTH_MANAGER.startAdvertising();
|
||||||
|
} else {
|
||||||
|
// Failed to initialize, revert to OFF
|
||||||
|
SETTINGS.*(setting.valuePtr) = CrossPointSettings::BLUETOOTH_MODE::OFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Disable Bluetooth
|
||||||
|
if (BLUETOOTH_MANAGER.isInitialized()) {
|
||||||
|
BLUETOOTH_MANAGER.shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (setting.type == SettingType::VALUE && setting.valuePtr != nullptr) {
|
} else if (setting.type == SettingType::VALUE && setting.valuePtr != nullptr) {
|
||||||
// Decreasing would also be nice for large ranges I think but oh well can't have everything
|
// Decreasing would also be nice for large ranges I think but oh well can't have everything
|
||||||
const int8_t currentValue = SETTINGS.*(setting.valuePtr);
|
const int8_t currentValue = SETTINGS.*(setting.valuePtr);
|
||||||
|
|||||||
15
src/main.cpp
15
src/main.cpp
@ -10,6 +10,7 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
#include "Battery.h"
|
#include "Battery.h"
|
||||||
|
#include "BluetoothManager.h"
|
||||||
#include "CrossPointSettings.h"
|
#include "CrossPointSettings.h"
|
||||||
#include "CrossPointState.h"
|
#include "CrossPointState.h"
|
||||||
#include "KOReaderCredentialStore.h"
|
#include "KOReaderCredentialStore.h"
|
||||||
@ -200,6 +201,11 @@ void enterDeepSleep() {
|
|||||||
exitActivity();
|
exitActivity();
|
||||||
enterNewActivity(new SleepActivity(renderer, mappedInputManager));
|
enterNewActivity(new SleepActivity(renderer, mappedInputManager));
|
||||||
|
|
||||||
|
// Shutdown Bluetooth to save power and memory
|
||||||
|
if (BLUETOOTH_MANAGER.isInitialized()) {
|
||||||
|
BLUETOOTH_MANAGER.shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
einkDisplay.deepSleep();
|
einkDisplay.deepSleep();
|
||||||
Serial.printf("[%lu] [ ] Power button press calibration value: %lu ms\n", millis(), t2 - t1);
|
Serial.printf("[%lu] [ ] Power button press calibration value: %lu ms\n", millis(), t2 - t1);
|
||||||
Serial.printf("[%lu] [ ] Entering deep sleep.\n", millis());
|
Serial.printf("[%lu] [ ] Entering deep sleep.\n", millis());
|
||||||
@ -292,6 +298,15 @@ void setup() {
|
|||||||
SETTINGS.loadFromFile();
|
SETTINGS.loadFromFile();
|
||||||
KOREADER_STORE.loadFromFile();
|
KOREADER_STORE.loadFromFile();
|
||||||
|
|
||||||
|
// Initialize Bluetooth if enabled (before display to minimize RAM impact)
|
||||||
|
if (SETTINGS.bluetoothEnabled == CrossPointSettings::BLUETOOTH_MODE::ON) {
|
||||||
|
if (!BLUETOOTH_MANAGER.initialize()) {
|
||||||
|
Serial.printf("[%lu] [BLE] Failed to initialize Bluetooth\n", millis());
|
||||||
|
// Fall back to disabled state
|
||||||
|
SETTINGS.bluetoothEnabled = CrossPointSettings::BLUETOOTH_MODE::OFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// verify power button press duration after we've read settings.
|
// verify power button press duration after we've read settings.
|
||||||
verifyWakeupLongPress();
|
verifyWakeupLongPress();
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user