mirror of
https://github.com/ByteWelder/Tactility.git
synced 2026-08-17 23:55:04 +00:00
Remove and refactor old HAL components
This commit is contained in:
parent
29e80cfd65
commit
0d10797e92
@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
#include <Tactility/SystemEvents.h>
|
#include <Tactility/SystemEvents.h>
|
||||||
#include <Tactility/LogMessages.h>
|
#include <Tactility/LogMessages.h>
|
||||||
#include <Tactility/hal/Configuration.h>
|
|
||||||
#include <Tactility/hal/gps/GpsConfiguration.h>
|
#include <Tactility/hal/gps/GpsConfiguration.h>
|
||||||
#include <Tactility/kernel/Kernel.h>
|
#include <Tactility/kernel/Kernel.h>
|
||||||
#include <Tactility/lvgl/LvglSync.h>
|
#include <Tactility/lvgl/LvglSync.h>
|
||||||
|
|||||||
@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
#include <Tactility/LogMessages.h>
|
#include <Tactility/LogMessages.h>
|
||||||
#include <Tactility/SystemEvents.h>
|
#include <Tactility/SystemEvents.h>
|
||||||
#include <Tactility/hal/Configuration.h>
|
|
||||||
#include <Tactility/hal/gps/GpsConfiguration.h>
|
#include <Tactility/hal/gps/GpsConfiguration.h>
|
||||||
#include <Tactility/kernel/Kernel.h>
|
#include <Tactility/kernel/Kernel.h>
|
||||||
#include <Tactility/service/gps/GpsService.h>
|
#include <Tactility/service/gps/GpsService.h>
|
||||||
|
|||||||
@ -2,7 +2,6 @@
|
|||||||
#include "hal/SdlKeyboard.h"
|
#include "hal/SdlKeyboard.h"
|
||||||
#include "hal/SimulatorPower.h"
|
#include "hal/SimulatorPower.h"
|
||||||
|
|
||||||
#include <Tactility/hal/Configuration.h>
|
|
||||||
|
|
||||||
#define TAG "hardware"
|
#define TAG "hardware"
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
#include <Tactility/Tactility.h>
|
#include <Tactility/Tactility.h>
|
||||||
|
|
||||||
#include <tactility/driver.h>
|
|
||||||
#include <devicetree.h>
|
#include <devicetree.h>
|
||||||
|
|
||||||
#ifdef ESP_PLATFORM
|
#ifdef ESP_PLATFORM
|
||||||
@ -9,30 +8,15 @@
|
|||||||
#include <Simulator.h>
|
#include <Simulator.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_TT_USE_DEPRECATED_HAL
|
|
||||||
// Each board project declares this variable
|
|
||||||
extern const tt::hal::Configuration hardwareConfiguration;
|
|
||||||
#else
|
|
||||||
// Legacy placeholder (required until legacy HAL is cleaned up everywhere)
|
|
||||||
extern const tt::hal::Configuration hardwareConfiguration = {};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
void app_main() {
|
void app_main() {
|
||||||
static const tt::Configuration config = {
|
|
||||||
/**
|
|
||||||
* Auto-select a board based on the ./sdkconfig.board.* file
|
|
||||||
* that you copied to ./sdkconfig before you opened this project.
|
|
||||||
*/
|
|
||||||
.hardware = &hardwareConfiguration
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef ESP_PLATFORM
|
#ifdef ESP_PLATFORM
|
||||||
tt_init_tactility_c(); // ELF bindings for side-loading on ESP32
|
tt_init_tactility_c(); // ELF bindings for side-loading on ESP32
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
tt::run(config, dts_modules, dts_devices);
|
tt::run(dts_modules, dts_devices);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // extern
|
} // extern
|
||||||
@ -1,11 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "tactility/concurrent/dispatcher.h"
|
#include <tactility/concurrent/dispatcher.h>
|
||||||
#include "tactility/device.h"
|
#include <tactility/device.h>
|
||||||
#include "tactility/module.h"
|
#include <tactility/module.h>
|
||||||
#include <Tactility/app/AppManifest.h>
|
#include <Tactility/app/AppManifest.h>
|
||||||
#include <Tactility/hal/Configuration.h>
|
|
||||||
#include <Tactility/service/ServiceManifest.h>
|
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
@ -40,27 +38,12 @@ private:
|
|||||||
DispatcherHandle_t handle;
|
DispatcherHandle_t handle;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** @brief The configuration for the operating system
|
|
||||||
* It contains the hardware configuration, apps and services
|
|
||||||
*/
|
|
||||||
struct Configuration {
|
|
||||||
/** HAL configuration (drivers) */
|
|
||||||
const hal::Configuration* hardware = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Main entry point for Tactility.
|
* @brief Main entry point for Tactility.
|
||||||
* @param dtsModules List of modules from devicetree, null-terminated, non-null parameter
|
* @param dtsModules List of modules from devicetree, null-terminated, non-null parameter
|
||||||
* @param dtsDevices Array that is terminated with DTS_DEVICE_TERMINATOR
|
* @param dtsDevices Array that is terminated with DTS_DEVICE_TERMINATOR
|
||||||
*/
|
*/
|
||||||
void run(const Configuration& config, Module* dtsModules[], DtsDevice dtsDevices[]);
|
void run(Module* dtsModules[], DtsDevice dtsDevices[]);
|
||||||
|
|
||||||
/**
|
|
||||||
* While technically nullable, this instance is always set if tt_init() succeeds.
|
|
||||||
* Could return nullptr if init was not called.
|
|
||||||
* @return the Configuration instance that was passed on to tt_init() if init is successful
|
|
||||||
*/
|
|
||||||
const Configuration* getConfiguration();
|
|
||||||
|
|
||||||
/** Provides access to the dispatcher that runs on the main task.
|
/** Provides access to the dispatcher that runs on the main task.
|
||||||
* @warning This dispatcher is used for WiFi and might block for some time during WiFi connection.
|
* @warning This dispatcher is used for WiFi and might block for some time during WiFi connection.
|
||||||
@ -68,11 +51,4 @@ const Configuration* getConfiguration();
|
|||||||
*/
|
*/
|
||||||
MainDispatcher getMainDispatcher();
|
MainDispatcher getMainDispatcher();
|
||||||
|
|
||||||
namespace hal {
|
|
||||||
|
|
||||||
/** While technically this configuration is nullable, it's never null after initHeadless() is called. */
|
|
||||||
const Configuration* getConfiguration();
|
|
||||||
|
|
||||||
} // namespace hal
|
|
||||||
|
|
||||||
} // namespace tt
|
} // namespace tt
|
||||||
|
|||||||
@ -1,24 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <tactility/hal/Device.h>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace tt::hal {
|
|
||||||
|
|
||||||
typedef bool (*InitBoot)();
|
|
||||||
|
|
||||||
typedef std::vector<std::shared_ptr<Device>> DeviceVector;
|
|
||||||
|
|
||||||
typedef std::shared_ptr<Device> (*CreateDevice)();
|
|
||||||
|
|
||||||
struct Configuration {
|
|
||||||
/**
|
|
||||||
* Used for powering on the peripherals manually.
|
|
||||||
*/
|
|
||||||
const InitBoot initBoot = nullptr;
|
|
||||||
|
|
||||||
const std::function<DeviceVector()> createDevices = [] { return DeviceVector(); };
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
@ -1,63 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <tactility/hal/Device.h>
|
|
||||||
|
|
||||||
#include <lvgl.h>
|
|
||||||
|
|
||||||
namespace tt::hal::touch {
|
|
||||||
class TouchDevice;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace tt::hal::display {
|
|
||||||
|
|
||||||
class DisplayDriver;
|
|
||||||
|
|
||||||
class DisplayDevice : public Device {
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
Type getType() const override { return Type::Display; }
|
|
||||||
|
|
||||||
/** Starts the internal driver */
|
|
||||||
virtual bool start() = 0;
|
|
||||||
virtual bool stop() = 0;
|
|
||||||
|
|
||||||
virtual void setPowerOn(bool turnOn) {}
|
|
||||||
virtual bool isPoweredOn() const { return true; }
|
|
||||||
virtual bool supportsPowerControl() const { return false; }
|
|
||||||
|
|
||||||
/** For e-paper screens */
|
|
||||||
virtual void requestFullRefresh() {}
|
|
||||||
|
|
||||||
/** Blocks until any frame already handed to this display has physically
|
|
||||||
* finished drawing. Displays that draw synchronously within their flush
|
|
||||||
* callback can rely on the default no-op; displays with an asynchronous
|
|
||||||
* refresh pipeline (e.g. e-paper, where a full refresh can take seconds)
|
|
||||||
* should override this so callers can safely do something irreversible
|
|
||||||
* (like cutting power) right after a screen update. */
|
|
||||||
virtual void waitForFlushComplete() {}
|
|
||||||
|
|
||||||
/** Could return nullptr if not started */
|
|
||||||
virtual std::shared_ptr<touch::TouchDevice> getTouchDevice() = 0;
|
|
||||||
|
|
||||||
/** Set a value in the range [0, 255] */
|
|
||||||
virtual void setBacklightDuty(uint8_t backlightDuty) { /* NO-OP */ }
|
|
||||||
virtual bool supportsBacklightDuty() const { return false; }
|
|
||||||
|
|
||||||
/** Set a value in the range [0, 255] */
|
|
||||||
virtual void setGammaCurve(uint8_t index) { /* NO-OP */ }
|
|
||||||
virtual uint8_t getGammaCurveCount() const { return 0; }
|
|
||||||
|
|
||||||
virtual bool supportsLvgl() const = 0;
|
|
||||||
virtual bool startLvgl() = 0;
|
|
||||||
virtual bool stopLvgl() = 0;
|
|
||||||
|
|
||||||
/** Could return nullptr if not started */
|
|
||||||
virtual lv_display_t* getLvglDisplay() const = 0;
|
|
||||||
|
|
||||||
virtual bool supportsDisplayDriver() const = 0;
|
|
||||||
/** Could return nullptr if not supported */
|
|
||||||
virtual std::shared_ptr<DisplayDriver> getDisplayDriver() = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace tt::hal::display
|
|
||||||
@ -1,37 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <Tactility/Lock.h>
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
namespace tt::hal::display {
|
|
||||||
|
|
||||||
enum class ColorFormat {
|
|
||||||
Monochrome, // 1 bpp
|
|
||||||
BGR565,
|
|
||||||
BGR565Swapped,
|
|
||||||
RGB565,
|
|
||||||
RGB565Swapped,
|
|
||||||
RGB888
|
|
||||||
};
|
|
||||||
|
|
||||||
class DisplayDriver {
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
virtual ~DisplayDriver() = default;
|
|
||||||
|
|
||||||
virtual ColorFormat getColorFormat() const = 0;
|
|
||||||
virtual uint16_t getPixelWidth() const = 0;
|
|
||||||
virtual uint16_t getPixelHeight() const = 0;
|
|
||||||
virtual bool drawBitmap(int xStart, int yStart, int xEnd, int yEnd, const void* pixelData) = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns direct pointers to the panel's hardware frame buffer(s), if the
|
|
||||||
* underlying driver supports it (DPI/MIPI-DSI panels only).
|
|
||||||
* @param[out] outBuffers receives up to 2 frame buffer pointers
|
|
||||||
* @return number of buffers written to outBuffers (0 if unsupported)
|
|
||||||
*/
|
|
||||||
virtual uint8_t getFrameBuffers(void* outBuffers[2]) const { return 0; }
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,26 +0,0 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <Tactility/hal/display/DisplayDriver.h>
|
|
||||||
|
|
||||||
#include <tactility/device.h>
|
|
||||||
|
|
||||||
namespace tt::hal::display {
|
|
||||||
|
|
||||||
/** Wraps a TactilityKernel Device of type DISPLAY_TYPE as a DisplayDriver. */
|
|
||||||
class KernelDisplayDriver final : public DisplayDriver {
|
|
||||||
|
|
||||||
::Device* device;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
explicit KernelDisplayDriver(::Device* device);
|
|
||||||
|
|
||||||
ColorFormat getColorFormat() const override;
|
|
||||||
uint16_t getPixelWidth() const override;
|
|
||||||
uint16_t getPixelHeight() const override;
|
|
||||||
bool drawBitmap(int xStart, int yStart, int xEnd, int yEnd, const void* pixelData) override;
|
|
||||||
uint8_t getFrameBuffers(void* outBuffers[2]) const override;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,24 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <tactility/hal/Device.h>
|
|
||||||
|
|
||||||
#include <lvgl.h>
|
|
||||||
|
|
||||||
namespace tt::hal::encoder {
|
|
||||||
|
|
||||||
class Display;
|
|
||||||
|
|
||||||
class EncoderDevice : public Device {
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
Type getType() const override { return Type::Encoder; }
|
|
||||||
|
|
||||||
virtual bool startLvgl(lv_display_t* display) = 0;
|
|
||||||
virtual bool stopLvgl() = 0;
|
|
||||||
|
|
||||||
/** Could return nullptr if not started */
|
|
||||||
virtual lv_indev_t* getLvglIndev() = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,34 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
namespace tt::hal::gpio {
|
|
||||||
|
|
||||||
typedef unsigned int Pin;
|
|
||||||
constexpr Pin NO_PIN = -1;
|
|
||||||
|
|
||||||
/** @warning The order must match GpioMode from tt_hal_gpio.h */
|
|
||||||
enum class Mode {
|
|
||||||
Disable = 0,
|
|
||||||
Input,
|
|
||||||
Output,
|
|
||||||
OutputOpenDrain,
|
|
||||||
InputOutput,
|
|
||||||
InputOutputOpenDrain
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Configure a single pin */
|
|
||||||
bool configure(Pin pin, Mode mode, bool pullUp, bool pullDown);
|
|
||||||
|
|
||||||
/** Configure a set of pins defined by their bit index */
|
|
||||||
bool configureWithPinBitmask(uint64_t pinBitMask, Mode mode, bool pullUp, bool pullDown);
|
|
||||||
|
|
||||||
bool setMode(Pin pin, Mode mode);
|
|
||||||
|
|
||||||
bool getLevel(Pin pin);
|
|
||||||
|
|
||||||
bool setLevel(Pin pin, bool level);
|
|
||||||
|
|
||||||
int getPinCount();
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -46,7 +46,10 @@ private:
|
|||||||
std::shared_ptr<std::function<void(Device::Id id, const minmea_sentence_rmc&)>> onData;
|
std::shared_ptr<std::function<void(Device::Id id, const minmea_sentence_rmc&)>> onData;
|
||||||
};
|
};
|
||||||
|
|
||||||
const GpsConfiguration configuration;
|
::Device* uartDevice;
|
||||||
|
uint32_t baudRate;
|
||||||
|
GpsModel model;
|
||||||
|
|
||||||
RecursiveMutex mutex;
|
RecursiveMutex mutex;
|
||||||
std::unique_ptr<Thread> thread;
|
std::unique_ptr<Thread> thread;
|
||||||
bool threadInterrupted = false;
|
bool threadInterrupted = false;
|
||||||
@ -54,7 +57,6 @@ private:
|
|||||||
std::vector<RmcSubscription> rmcSubscriptions;
|
std::vector<RmcSubscription> rmcSubscriptions;
|
||||||
GgaSubscriptionId lastSatelliteSubscriptionId = 0;
|
GgaSubscriptionId lastSatelliteSubscriptionId = 0;
|
||||||
RmcSubscriptionId lastRmcSubscriptionId = 0;
|
RmcSubscriptionId lastRmcSubscriptionId = 0;
|
||||||
GpsModel model = GpsModel::Unknown;
|
|
||||||
State state = State::Off;
|
State state = State::Off;
|
||||||
|
|
||||||
int32_t threadMain();
|
int32_t threadMain();
|
||||||
@ -65,9 +67,18 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
explicit GpsDevice(GpsConfiguration configuration) : configuration(std::move(configuration)) {}
|
explicit GpsDevice(
|
||||||
|
::Device* uartDevice,
|
||||||
|
uint32_t baudRate,
|
||||||
|
GpsModel model // Choosing "Unknown" will result in a probe
|
||||||
|
) : uartDevice(uartDevice), baudRate(baudRate), model(model) {
|
||||||
|
assert(uartDevice != nullptr);
|
||||||
|
device_get(uartDevice);
|
||||||
|
};
|
||||||
|
|
||||||
~GpsDevice() override = default;
|
~GpsDevice() override {
|
||||||
|
device_put(uartDevice);
|
||||||
|
}
|
||||||
|
|
||||||
Type getType() const override { return Type::Gps; }
|
Type getType() const override { return Type::Gps; }
|
||||||
|
|
||||||
|
|||||||
@ -1,49 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <tactility/hal/Device.h>
|
|
||||||
#include <tactility/drivers/i2c_controller.h>
|
|
||||||
|
|
||||||
namespace tt::hal::i2c {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents an I2C peripheral at a specific port and address.
|
|
||||||
* It helps to read and write registers.
|
|
||||||
*
|
|
||||||
* All read and write calls are thread-safe.
|
|
||||||
* @deprecated Use the device API from the Kernel project
|
|
||||||
*/
|
|
||||||
class I2cDevice : public Device {
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
::Device* controller;
|
|
||||||
uint8_t address;
|
|
||||||
|
|
||||||
static constexpr TickType_t DEFAULT_TIMEOUT = 1000 / portTICK_PERIOD_MS;
|
|
||||||
|
|
||||||
bool read(uint8_t* data, size_t dataSize, TickType_t timeout = DEFAULT_TIMEOUT);
|
|
||||||
bool write(const uint8_t* data, uint16_t dataSize, TickType_t timeout = DEFAULT_TIMEOUT);
|
|
||||||
bool writeRead(const uint8_t* writeData, size_t writeDataSize, uint8_t* readData, size_t readDataSize, TickType_t timeout = DEFAULT_TIMEOUT);
|
|
||||||
bool readRegister8(uint8_t reg, uint8_t& result) const;
|
|
||||||
bool writeRegister(uint8_t reg, const uint8_t* data, uint16_t dataSize, TickType_t timeout = DEFAULT_TIMEOUT);
|
|
||||||
bool writeRegister8(uint8_t reg, uint8_t value) const;
|
|
||||||
bool readRegister12(uint8_t reg, float& out) const;
|
|
||||||
bool readRegister14(uint8_t reg, float& out) const;
|
|
||||||
bool readRegister16(uint8_t reg, uint16_t& out) const;
|
|
||||||
bool bitOn(uint8_t reg, uint8_t bitmask) const;
|
|
||||||
bool bitOff(uint8_t reg, uint8_t bitmask) const;
|
|
||||||
bool bitOnByIndex(uint8_t reg, uint8_t index) const { return bitOn(reg, 1 << index); }
|
|
||||||
bool bitOffByIndex(uint8_t reg, uint8_t index) const { return bitOff(reg, 1 << index); }
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
explicit I2cDevice(::Device* controller, uint32_t address) : controller(controller), address(address) {}
|
|
||||||
|
|
||||||
Type getType() const override { return Type::I2c; }
|
|
||||||
|
|
||||||
::Device* getController() const { return controller; }
|
|
||||||
|
|
||||||
uint8_t getAddress() const { return address; }
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace tt::hal::i2c
|
|
||||||
@ -1,27 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <tactility/hal/Device.h>
|
|
||||||
|
|
||||||
#include <lvgl.h>
|
|
||||||
|
|
||||||
namespace tt::hal::keyboard {
|
|
||||||
|
|
||||||
class Display;
|
|
||||||
|
|
||||||
class KeyboardDevice : public Device {
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
Type getType() const override { return Type::Keyboard; }
|
|
||||||
|
|
||||||
virtual bool startLvgl(lv_display_t* display) = 0;
|
|
||||||
virtual bool stopLvgl() = 0;
|
|
||||||
|
|
||||||
/** @return true when the keyboard currently is physically attached */
|
|
||||||
virtual bool isAttached() const = 0;
|
|
||||||
|
|
||||||
/** Could return nullptr if not started */
|
|
||||||
virtual lv_indev_t* getLvglIndev() = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,63 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <tactility/hal/Device.h>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace tt::hal::power {
|
|
||||||
|
|
||||||
class PowerDevice : public Device {
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
PowerDevice();
|
|
||||||
~PowerDevice() override;
|
|
||||||
|
|
||||||
Type getType() const override { return Type::Power; }
|
|
||||||
|
|
||||||
enum class MetricType {
|
|
||||||
IsCharging, // bool
|
|
||||||
Current, // int32_t, mAh - battery current: either during charging (positive value) or discharging (negative value)
|
|
||||||
BatteryVoltage, // uint32_t, mV
|
|
||||||
ChargeLevel, // uint8_t [0, 100]
|
|
||||||
};
|
|
||||||
|
|
||||||
union MetricData {
|
|
||||||
int32_t valueAsInt32 = 0;
|
|
||||||
uint32_t valueAsUint32;
|
|
||||||
uint8_t valueAsUint8;
|
|
||||||
float valueAsFloat;
|
|
||||||
bool valueAsBool;
|
|
||||||
};
|
|
||||||
|
|
||||||
virtual bool supportsMetric(MetricType type) const = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return false when metric is not supported or (temporarily) not available.
|
|
||||||
*/
|
|
||||||
virtual bool getMetric(MetricType type, MetricData& data) = 0;
|
|
||||||
|
|
||||||
virtual bool supportsChargeControl() const { return false; }
|
|
||||||
virtual bool isAllowedToCharge() const { return false; }
|
|
||||||
virtual void setAllowedToCharge(bool canCharge) { /* NO-OP*/ }
|
|
||||||
|
|
||||||
virtual bool supportsQuickCharge() const { return false; }
|
|
||||||
virtual bool isQuickChargeEnabled() const { return false; }
|
|
||||||
virtual void setQuickChargeEnabled(bool enabled) { /* NO-OP */ }
|
|
||||||
|
|
||||||
virtual bool supportsPowerOff() const { return false; }
|
|
||||||
virtual void powerOff() { /* NO-OP*/ }
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
/** Creates the kernel-level power_supply device that exposes this instance to TactilityKernel. */
|
|
||||||
void createPowerSupplyDevice();
|
|
||||||
|
|
||||||
/** Destroys the kernel-level power_supply device created by createPowerSupplyDevice(). */
|
|
||||||
void destroyPowerSupplyDevice();
|
|
||||||
|
|
||||||
std::string kernelDeviceName;
|
|
||||||
KernelDevice kernelDevice {};
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,22 +0,0 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <Tactility/hal/touch/TouchDriver.h>
|
|
||||||
|
|
||||||
#include <tactility/device.h>
|
|
||||||
|
|
||||||
namespace tt::hal::touch {
|
|
||||||
|
|
||||||
/** Wraps a TactilityKernel Device of type POINTER_TYPE as a TouchDriver. */
|
|
||||||
class KernelTouchDriver final : public TouchDriver {
|
|
||||||
|
|
||||||
::Device* device;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
explicit KernelTouchDriver(::Device* device);
|
|
||||||
|
|
||||||
bool getTouchedPoints(uint16_t* x, uint16_t* y, uint16_t* strength, uint8_t* pointCount, uint8_t maxPointCount) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,36 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <tactility/hal/Device.h>
|
|
||||||
#include "TouchDriver.h"
|
|
||||||
|
|
||||||
#include <lvgl.h>
|
|
||||||
|
|
||||||
namespace tt::hal::touch {
|
|
||||||
|
|
||||||
class Display;
|
|
||||||
|
|
||||||
class TouchDevice : public Device {
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
Type getType() const override { return Type::Touch; }
|
|
||||||
|
|
||||||
virtual bool start() = 0;
|
|
||||||
virtual bool stop() = 0;
|
|
||||||
|
|
||||||
virtual bool supportsLvgl() const = 0;
|
|
||||||
virtual bool startLvgl(lv_display_t* display) = 0;
|
|
||||||
virtual bool stopLvgl() = 0;
|
|
||||||
|
|
||||||
/** Could return nullptr if not started */
|
|
||||||
virtual lv_indev_t* getLvglIndev() = 0;
|
|
||||||
|
|
||||||
virtual bool supportsTouchDriver() = 0;
|
|
||||||
|
|
||||||
virtual bool supportsCalibration() const { return false; }
|
|
||||||
|
|
||||||
/** Could return nullptr if not supported */
|
|
||||||
virtual std::shared_ptr<TouchDriver> getTouchDriver() = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,25 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
namespace tt::hal::touch {
|
|
||||||
|
|
||||||
class TouchDriver {
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the coordinates for the currently touched points on the screen.
|
|
||||||
*
|
|
||||||
* @param[in] x array of X coordinates
|
|
||||||
* @param[in] y array of Y coordinates
|
|
||||||
* @param[in] strength optional array of strengths (nullable)
|
|
||||||
* @param[in] pointCount the number of points currently touched on the screen
|
|
||||||
* @param[in] maxPointCount the maximum number of points that can be touched at once
|
|
||||||
*
|
|
||||||
* @return true when touched and coordinates are available
|
|
||||||
*/
|
|
||||||
virtual bool getTouchedPoints(uint16_t* x, uint16_t* y, uint16_t* strength, uint8_t* pointCount, uint8_t maxPointCount) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Tactility/hal/Configuration.h"
|
|
||||||
|
|
||||||
namespace tt::hal {
|
|
||||||
|
|
||||||
void init(const Configuration& configuration);
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <Tactility/lvgl/Lvgl.h>
|
|
||||||
|
|
||||||
namespace tt::lvgl {
|
|
||||||
|
|
||||||
void attachDevices();
|
|
||||||
|
|
||||||
void detachDevices();
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -14,8 +14,6 @@
|
|||||||
#include <Tactility/app/AppRegistration.h>
|
#include <Tactility/app/AppRegistration.h>
|
||||||
#include <Tactility/file/File.h>
|
#include <Tactility/file/File.h>
|
||||||
#include <Tactility/file/FileLock.h>
|
#include <Tactility/file/FileLock.h>
|
||||||
#include <Tactility/hal/HalPrivate.h>
|
|
||||||
#include <Tactility/lvgl/LvglPrivate.h>
|
|
||||||
#include <Tactility/network/NtpPrivate.h>
|
#include <Tactility/network/NtpPrivate.h>
|
||||||
#include <Tactility/service/ServiceManifest.h>
|
#include <Tactility/service/ServiceManifest.h>
|
||||||
#include <Tactility/service/ServiceRegistration.h>
|
#include <Tactility/service/ServiceRegistration.h>
|
||||||
@ -41,6 +39,8 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "Tactility/Paths.h"
|
#include "Tactility/Paths.h"
|
||||||
|
#include "Tactility/SystemEvents.h"
|
||||||
|
#include "Tactility/hal/SdCard.h"
|
||||||
|
|
||||||
|
|
||||||
#include <Tactility/bluetooth/Bluetooth.h>
|
#include <Tactility/bluetooth/Bluetooth.h>
|
||||||
@ -49,7 +49,6 @@ namespace tt {
|
|||||||
|
|
||||||
constexpr auto* TAG = "Tactility";
|
constexpr auto* TAG = "Tactility";
|
||||||
|
|
||||||
static const Configuration* config_instance = nullptr;
|
|
||||||
static DispatcherHandle_t mainDispatcherHandle = dispatcher_alloc();
|
static DispatcherHandle_t mainDispatcherHandle = dispatcher_alloc();
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@ -183,8 +182,6 @@ static void registerInternalApps() {
|
|||||||
}
|
}
|
||||||
if (device_exists_of_type(&DISPLAY_TYPE)) {
|
if (device_exists_of_type(&DISPLAY_TYPE)) {
|
||||||
addAppManifest(app::kerneldisplay::manifest);
|
addAppManifest(app::kerneldisplay::manifest);
|
||||||
} else if (hal::hasDevice(hal::Device::Type::Display)) {
|
|
||||||
addAppManifest(app::display::manifest);
|
|
||||||
}
|
}
|
||||||
addAppManifest(app::files::manifest);
|
addAppManifest(app::files::manifest);
|
||||||
addAppManifest(app::fileselection::manifest);
|
addAppManifest(app::fileselection::manifest);
|
||||||
@ -366,11 +363,9 @@ void registerApps() {
|
|||||||
registerInstalledAppsFromFileSystems();
|
registerInstalledAppsFromFileSystems();
|
||||||
}
|
}
|
||||||
|
|
||||||
void run(const Configuration& config, Module* dtsModules[], DtsDevice dtsDevices[]) {
|
void run(Module* dtsModules[], DtsDevice dtsDevices[]) {
|
||||||
LOG_I(TAG, "Tactility v%s on %s (%s)", TT_VERSION, CONFIG_TT_DEVICE_NAME, CONFIG_TT_DEVICE_ID);
|
LOG_I(TAG, "Tactility v%s on %s (%s)", TT_VERSION, CONFIG_TT_DEVICE_NAME, CONFIG_TT_DEVICE_ID);
|
||||||
|
|
||||||
assert(config.hardware);
|
|
||||||
|
|
||||||
LOG_I(TAG, "Initializing kernel");
|
LOG_I(TAG, "Initializing kernel");
|
||||||
if (kernel_init(dtsModules, dtsDevices) != ERROR_NONE) {
|
if (kernel_init(dtsModules, dtsDevices) != ERROR_NONE) {
|
||||||
LOG_E(TAG, "Failed to initialize kernel");
|
LOG_E(TAG, "Failed to initialize kernel");
|
||||||
@ -383,23 +378,25 @@ void run(const Configuration& config, Module* dtsModules[], DtsDevice dtsDevices
|
|||||||
// crypt-module
|
// crypt-module
|
||||||
check(module_construct_add_start(&crypt_module) == ERROR_NONE);
|
check(module_construct_add_start(&crypt_module) == ERROR_NONE);
|
||||||
|
|
||||||
// Assign early so starting services can use it
|
|
||||||
config_instance = &config;
|
|
||||||
|
|
||||||
#ifdef ESP_PLATFORM
|
#ifdef ESP_PLATFORM
|
||||||
initEsp();
|
initEsp();
|
||||||
#endif
|
#endif
|
||||||
file::setFindLockFunction(file::findLock);
|
file::setFindLockFunction(file::findLock);
|
||||||
settings::initTimeZone();
|
settings::initTimeZone();
|
||||||
hal::init(*config.hardware);
|
|
||||||
|
// Remnants of the old HAL
|
||||||
|
kernel::publishSystemEvent(kernel::SystemEvent::BootInitHalBegin);
|
||||||
|
hal::sdcard::mountAll();
|
||||||
|
kernel::publishSystemEvent(kernel::SystemEvent::BootInitHalEnd);
|
||||||
|
|
||||||
network::ntp::init();
|
network::ntp::init();
|
||||||
bluetooth::systemStart();
|
bluetooth::systemStart();
|
||||||
|
|
||||||
registerAndStartPrimaryServices();
|
registerAndStartPrimaryServices();
|
||||||
|
|
||||||
lvgl_module_configure((LvglModuleConfig) {
|
lvgl_module_configure((LvglModuleConfig) {
|
||||||
.on_start = lvgl::attachDevices,
|
.on_start = nullptr,
|
||||||
.on_stop = lvgl::detachDevices,
|
.on_stop = nullptr,
|
||||||
.task_priority = THREAD_PRIORITY_HIGHER,
|
.task_priority = THREAD_PRIORITY_HIGHER,
|
||||||
/** Minimum seems to be about 3500. In some scenarios, the WiFi app crashes at 8192,
|
/** Minimum seems to be about 3500. In some scenarios, the WiFi app crashes at 8192,
|
||||||
* so we now have 9120 to run in a stable manner. We should figure out a way to avoid this.
|
* so we now have 9120 to run in a stable manner. We should figure out a way to avoid this.
|
||||||
@ -411,7 +408,7 @@ void run(const Configuration& config, Module* dtsModules[], DtsDevice dtsDevices
|
|||||||
});
|
});
|
||||||
check(module_construct(&lvgl_module) == ERROR_NONE);
|
check(module_construct(&lvgl_module) == ERROR_NONE);
|
||||||
check(module_add(&lvgl_module) == ERROR_NONE);
|
check(module_add(&lvgl_module) == ERROR_NONE);
|
||||||
lvgl::start();
|
module_start(&lvgl_module);
|
||||||
|
|
||||||
registerAndStartSecondaryServices();
|
registerAndStartSecondaryServices();
|
||||||
|
|
||||||
@ -428,11 +425,6 @@ void run(const Configuration& config, Module* dtsModules[], DtsDevice dtsDevices
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** return the configuration or nullptr if it's not initialized */
|
|
||||||
const Configuration* getConfiguration() {
|
|
||||||
return config_instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
MainDispatcher getMainDispatcher() {
|
MainDispatcher getMainDispatcher() {
|
||||||
return MainDispatcher(mainDispatcherHandle);
|
return MainDispatcher(mainDispatcherHandle);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,7 +9,6 @@
|
|||||||
#include <Tactility/app/AppContext.h>
|
#include <Tactility/app/AppContext.h>
|
||||||
#include <Tactility/app/AppPaths.h>
|
#include <Tactility/app/AppPaths.h>
|
||||||
#include <Tactility/app/alertdialog/AlertDialog.h>
|
#include <Tactility/app/alertdialog/AlertDialog.h>
|
||||||
#include <Tactility/hal/display/DisplayDevice.h>
|
|
||||||
#include <Tactility/hal/usb/Usb.h>
|
#include <Tactility/hal/usb/Usb.h>
|
||||||
#include <Tactility/lvgl/Style.h>
|
#include <Tactility/lvgl/Style.h>
|
||||||
#include <Tactility/service/loader/Loader.h>
|
#include <Tactility/service/loader/Loader.h>
|
||||||
@ -36,10 +35,6 @@ constexpr auto* TAG = "Boot";
|
|||||||
|
|
||||||
extern const AppManifest manifest;
|
extern const AppManifest manifest;
|
||||||
|
|
||||||
static std::shared_ptr<hal::display::DisplayDevice> getHalDisplay() {
|
|
||||||
return hal::findFirstDevice<hal::display::DisplayDevice>(hal::Device::Type::Display);
|
|
||||||
}
|
|
||||||
|
|
||||||
class BootApp : public App {
|
class BootApp : public App {
|
||||||
|
|
||||||
// Snapshot of hal::usb::isUsbBootMode(), taken before the boot thread starts and
|
// Snapshot of hal::usb::isUsbBootMode(), taken before the boot thread starts and
|
||||||
@ -58,31 +53,7 @@ class BootApp : public App {
|
|||||||
getCpuAffinityConfiguration().system
|
getCpuAffinityConfiguration().system
|
||||||
);
|
);
|
||||||
|
|
||||||
static void setupHalDisplay() {
|
static void setupDisplay() {
|
||||||
const auto hal_display = getHalDisplay();
|
|
||||||
if (hal_display == nullptr) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
settings::display::DisplaySettings settings;
|
|
||||||
if (settings::display::load(settings)) {
|
|
||||||
if (hal_display->getGammaCurveCount() > 0) {
|
|
||||||
hal_display->setGammaCurve(settings.gammaCurve);
|
|
||||||
LOG_I(TAG, "Gamma curve %d", settings.gammaCurve);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
settings = settings::display::getDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hal_display->supportsBacklightDuty()) {
|
|
||||||
LOG_I(TAG, "Backlight %d", settings.backlightDuty);
|
|
||||||
hal_display->setBacklightDuty(settings.backlightDuty);
|
|
||||||
} else {
|
|
||||||
LOG_I(TAG, "No backlight");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void setupKernelDisplay() {
|
|
||||||
auto* display = device_find_first_by_type(&DISPLAY_TYPE);
|
auto* display = device_find_first_by_type(&DISPLAY_TYPE);
|
||||||
// Boards not yet migrated to the kernel display driver register a placeholder device (so
|
// Boards not yet migrated to the kernel display driver register a placeholder device (so
|
||||||
// the devicetree node resolves) with a NULL api - nothing for this function to act on.
|
// the devicetree node resolves) with a NULL api - nothing for this function to act on.
|
||||||
@ -161,8 +132,8 @@ class BootApp : public App {
|
|||||||
|
|
||||||
// TODO: Support for multiple displays
|
// TODO: Support for multiple displays
|
||||||
LOG_I(TAG, "Setup display");
|
LOG_I(TAG, "Setup display");
|
||||||
setupHalDisplay();
|
setupDisplay();
|
||||||
setupKernelDisplay();
|
LOG_I(TAG, "Prepare file systems");
|
||||||
prepareFileSystems();
|
prepareFileSystems();
|
||||||
|
|
||||||
#ifdef CONFIG_TT_USER_DATA_LOCATION_SD
|
#ifdef CONFIG_TT_USER_DATA_LOCATION_SD
|
||||||
|
|||||||
@ -1,9 +1,8 @@
|
|||||||
#ifdef ESP_PLATFORM
|
#ifdef ESP_PLATFORM
|
||||||
|
|
||||||
#include <Tactility/Timer.h>
|
|
||||||
#include <Tactility/Tactility.h>
|
#include <Tactility/Tactility.h>
|
||||||
|
#include <Tactility/Timer.h>
|
||||||
#include <Tactility/app/AppManifest.h>
|
#include <Tactility/app/AppManifest.h>
|
||||||
#include <Tactility/lvgl/Lvgl.h>
|
|
||||||
#include <Tactility/lvgl/LvglSync.h>
|
#include <Tactility/lvgl/LvglSync.h>
|
||||||
#include <Tactility/lvgl/Style.h>
|
#include <Tactility/lvgl/Style.h>
|
||||||
#include <Tactility/lvgl/Toolbar.h>
|
#include <Tactility/lvgl/Toolbar.h>
|
||||||
@ -14,6 +13,7 @@
|
|||||||
|
|
||||||
#include <tactility/log.h>
|
#include <tactility/log.h>
|
||||||
#include <tactility/lvgl_icon_shared.h>
|
#include <tactility/lvgl_icon_shared.h>
|
||||||
|
#include <tactility/lvgl_module.h>
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <lvgl.h>
|
#include <lvgl.h>
|
||||||
@ -33,7 +33,7 @@ class DevelopmentApp final : public App {
|
|||||||
Timer timer = Timer(Timer::Type::Periodic, pdMS_TO_TICKS(1000), [this] {
|
Timer timer = Timer(Timer::Type::Periodic, pdMS_TO_TICKS(1000), [this] {
|
||||||
auto lock = lvgl::getSyncLock()->asScopedLock();
|
auto lock = lvgl::getSyncLock()->asScopedLock();
|
||||||
// TODO: There's a crash when this is called when the app is being destroyed
|
// TODO: There's a crash when this is called when the app is being destroyed
|
||||||
if (lock.lock(lvgl::defaultLockTime) && lvgl::isStarted()) {
|
if (lock.lock(lvgl::defaultLockTime) && module_is_started(&lvgl_module)) {
|
||||||
updateViewState();
|
updateViewState();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,310 +0,0 @@
|
|||||||
#include <Tactility/Tactility.h>
|
|
||||||
|
|
||||||
#include <tactility/lvgl_icon_shared.h>
|
|
||||||
|
|
||||||
#ifdef ESP_PLATFORM
|
|
||||||
#include <Tactility/service/displayidle/DisplayIdleService.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <Tactility/app/App.h>
|
|
||||||
#include <Tactility/hal/display/DisplayDevice.h>
|
|
||||||
#include <Tactility/lvgl/Toolbar.h>
|
|
||||||
#include <Tactility/settings/DisplaySettings.h>
|
|
||||||
|
|
||||||
#include <lvgl.h>
|
|
||||||
#include <tactility/log.h>
|
|
||||||
#include <tactility/lvgl_module.h>
|
|
||||||
|
|
||||||
namespace tt::app::display {
|
|
||||||
|
|
||||||
constexpr auto* TAG = "Display";
|
|
||||||
|
|
||||||
static std::shared_ptr<hal::display::DisplayDevice> getHalDisplay() {
|
|
||||||
return hal::findFirstDevice<hal::display::DisplayDevice>(hal::Device::Type::Display);
|
|
||||||
}
|
|
||||||
|
|
||||||
class HalDisplayApp final : public App {
|
|
||||||
|
|
||||||
settings::display::DisplaySettings displaySettings;
|
|
||||||
bool displaySettingsUpdated = false;
|
|
||||||
lv_obj_t* timeoutSwitch = nullptr;
|
|
||||||
lv_obj_t* timeoutDropdown = nullptr;
|
|
||||||
lv_obj_t* screensaverDropdown = nullptr;
|
|
||||||
|
|
||||||
static void onBacklightSliderEvent(lv_event_t* event) {
|
|
||||||
auto* slider = static_cast<lv_obj_t*>(lv_event_get_target(event));
|
|
||||||
auto* app = static_cast<HalDisplayApp*>(lv_event_get_user_data(event));
|
|
||||||
auto hal_display = getHalDisplay();
|
|
||||||
assert(hal_display != nullptr);
|
|
||||||
|
|
||||||
if (hal_display->supportsBacklightDuty()) {
|
|
||||||
int32_t slider_value = lv_slider_get_value(slider);
|
|
||||||
app->displaySettings.backlightDuty = static_cast<uint8_t>(slider_value);
|
|
||||||
app->displaySettingsUpdated = true;
|
|
||||||
hal_display->setBacklightDuty(app->displaySettings.backlightDuty);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void onGammaSliderEvent(lv_event_t* event) {
|
|
||||||
auto* slider = static_cast<lv_obj_t*>(lv_event_get_target(event));
|
|
||||||
auto hal_display = hal::findFirstDevice<hal::display::DisplayDevice>(hal::Device::Type::Display);
|
|
||||||
auto* app = static_cast<HalDisplayApp*>(lv_event_get_user_data(event));
|
|
||||||
assert(hal_display != nullptr);
|
|
||||||
|
|
||||||
if (hal_display->getGammaCurveCount() > 0) {
|
|
||||||
int32_t slider_value = lv_slider_get_value(slider);
|
|
||||||
app->displaySettings.gammaCurve = static_cast<uint8_t>(slider_value);
|
|
||||||
app->displaySettingsUpdated = true;
|
|
||||||
hal_display->setGammaCurve(app->displaySettings.gammaCurve);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void onOrientationSet(lv_event_t* event) {
|
|
||||||
auto* app = static_cast<HalDisplayApp*>(lv_event_get_user_data(event));
|
|
||||||
auto* dropdown = static_cast<lv_obj_t*>(lv_event_get_target(event));
|
|
||||||
uint32_t selected_index = lv_dropdown_get_selected(dropdown);
|
|
||||||
LOG_I(TAG, "Selected %u", (unsigned)selected_index);
|
|
||||||
auto selected_orientation = static_cast<settings::display::Orientation>(selected_index);
|
|
||||||
if (selected_orientation != app->displaySettings.orientation) {
|
|
||||||
app->displaySettings.orientation = selected_orientation;
|
|
||||||
app->displaySettingsUpdated = true;
|
|
||||||
lv_display_set_rotation(lv_display_get_default(), settings::display::toLvglDisplayRotation(selected_orientation));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void onTimeoutSwitch(lv_event_t* event) {
|
|
||||||
auto* app = static_cast<HalDisplayApp*>(lv_event_get_user_data(event));
|
|
||||||
auto* sw = static_cast<lv_obj_t*>(lv_event_get_target(event));
|
|
||||||
bool enabled = lv_obj_has_state(sw, LV_STATE_CHECKED);
|
|
||||||
app->displaySettings.backlightTimeoutEnabled = enabled;
|
|
||||||
app->displaySettingsUpdated = true;
|
|
||||||
if (app->timeoutDropdown) {
|
|
||||||
if (enabled) {
|
|
||||||
lv_obj_clear_state(app->timeoutDropdown, LV_STATE_DISABLED);
|
|
||||||
if (app->screensaverDropdown) {
|
|
||||||
lv_obj_clear_state(app->screensaverDropdown, LV_STATE_DISABLED);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
lv_obj_add_state(app->timeoutDropdown, LV_STATE_DISABLED);
|
|
||||||
if (app->screensaverDropdown) {
|
|
||||||
lv_obj_add_state(app->screensaverDropdown, LV_STATE_DISABLED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void onTimeoutChanged(lv_event_t* event) {
|
|
||||||
auto* app = static_cast<HalDisplayApp*>(lv_event_get_user_data(event));
|
|
||||||
auto* dropdown = static_cast<lv_obj_t*>(lv_event_get_target(event));
|
|
||||||
uint32_t idx = lv_dropdown_get_selected(dropdown);
|
|
||||||
// Map dropdown index to ms: 0=15s,1=30s,2=1m,3=2m,4=5m,5=Never
|
|
||||||
static const uint32_t values_ms[] = {15000, 30000, 60000, 120000, 300000, 0};
|
|
||||||
if (idx < (sizeof(values_ms)/sizeof(values_ms[0]))) {
|
|
||||||
app->displaySettings.backlightTimeoutMs = values_ms[idx];
|
|
||||||
app->displaySettingsUpdated = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void onScreensaverChanged(lv_event_t* event) {
|
|
||||||
auto* app = static_cast<HalDisplayApp*>(lv_event_get_user_data(event));
|
|
||||||
auto* dropdown = static_cast<lv_obj_t*>(lv_event_get_target(event));
|
|
||||||
uint32_t idx = lv_dropdown_get_selected(dropdown);
|
|
||||||
// Validate index bounds before casting to enum
|
|
||||||
if (idx >= static_cast<uint32_t>(settings::display::ScreensaverType::Count)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto selected_type = static_cast<settings::display::ScreensaverType>(idx);
|
|
||||||
if (selected_type != app->displaySettings.screensaverType) {
|
|
||||||
app->displaySettings.screensaverType = selected_type;
|
|
||||||
app->displaySettingsUpdated = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
void onShow(AppContext& app, lv_obj_t* parent) override {
|
|
||||||
displaySettings = settings::display::loadOrGetDefault();
|
|
||||||
auto ui_density = lvgl_get_ui_density();
|
|
||||||
|
|
||||||
lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN);
|
|
||||||
lv_obj_set_style_pad_row(parent, 0, LV_STATE_DEFAULT);
|
|
||||||
|
|
||||||
auto hal_display = getHalDisplay();
|
|
||||||
assert(hal_display != nullptr);
|
|
||||||
|
|
||||||
lvgl::toolbar_create(parent, app);
|
|
||||||
|
|
||||||
auto* main_wrapper = lv_obj_create(parent);
|
|
||||||
lv_obj_set_flex_flow(main_wrapper, LV_FLEX_FLOW_COLUMN);
|
|
||||||
lv_obj_set_width(main_wrapper, LV_PCT(100));
|
|
||||||
lv_obj_set_flex_grow(main_wrapper, 1);
|
|
||||||
|
|
||||||
// Backlight slider
|
|
||||||
|
|
||||||
if (hal_display->supportsBacklightDuty()) {
|
|
||||||
auto* brightness_wrapper = lv_obj_create(main_wrapper);
|
|
||||||
lv_obj_set_size(brightness_wrapper, LV_PCT(100), LV_SIZE_CONTENT);
|
|
||||||
lv_obj_set_style_pad_hor(brightness_wrapper, 0, LV_STATE_DEFAULT);
|
|
||||||
lv_obj_set_style_border_width(brightness_wrapper, 0, LV_STATE_DEFAULT);
|
|
||||||
if (ui_density != LVGL_UI_DENSITY_COMPACT) {
|
|
||||||
lv_obj_set_style_pad_ver(brightness_wrapper, 4, LV_STATE_DEFAULT);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* brightness_label = lv_label_create(brightness_wrapper);
|
|
||||||
lv_label_set_text(brightness_label, "Brightness");
|
|
||||||
lv_obj_align(brightness_label, LV_ALIGN_LEFT_MID, 0, 0);
|
|
||||||
|
|
||||||
auto* brightness_slider = lv_slider_create(brightness_wrapper);
|
|
||||||
lv_obj_set_width(brightness_slider, LV_PCT(50));
|
|
||||||
lv_obj_align(brightness_slider, LV_ALIGN_RIGHT_MID, 0, 0);
|
|
||||||
lv_slider_set_range(brightness_slider, 0, 255);
|
|
||||||
lv_obj_add_event_cb(brightness_slider, onBacklightSliderEvent, LV_EVENT_VALUE_CHANGED, this);
|
|
||||||
|
|
||||||
lv_slider_set_value(brightness_slider, displaySettings.backlightDuty, LV_ANIM_OFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gamma slider
|
|
||||||
|
|
||||||
if (hal_display->getGammaCurveCount() > 0) {
|
|
||||||
auto* gamma_wrapper = lv_obj_create(main_wrapper);
|
|
||||||
lv_obj_set_size(gamma_wrapper, LV_PCT(100), LV_SIZE_CONTENT);
|
|
||||||
lv_obj_set_style_pad_hor(gamma_wrapper, 0, LV_STATE_DEFAULT);
|
|
||||||
lv_obj_set_style_border_width(gamma_wrapper, 0, LV_STATE_DEFAULT);
|
|
||||||
if (ui_density != LVGL_UI_DENSITY_COMPACT) {
|
|
||||||
lv_obj_set_style_pad_ver(gamma_wrapper, 4, LV_STATE_DEFAULT);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* gamma_label = lv_label_create(gamma_wrapper);
|
|
||||||
lv_label_set_text(gamma_label, "Gamma");
|
|
||||||
lv_obj_align(gamma_label, LV_ALIGN_LEFT_MID, 0, 0);
|
|
||||||
lv_obj_set_y(gamma_label, 0);
|
|
||||||
|
|
||||||
auto* gamma_slider = lv_slider_create(gamma_wrapper);
|
|
||||||
lv_obj_set_width(gamma_slider, LV_PCT(50));
|
|
||||||
lv_obj_align(gamma_slider, LV_ALIGN_RIGHT_MID, 0, 0);
|
|
||||||
lv_slider_set_range(gamma_slider, 0, hal_display->getGammaCurveCount());
|
|
||||||
lv_obj_add_event_cb(gamma_slider, onGammaSliderEvent, LV_EVENT_VALUE_CHANGED, this);
|
|
||||||
|
|
||||||
uint8_t curve_index = displaySettings.gammaCurve;
|
|
||||||
lv_slider_set_value(gamma_slider, curve_index, LV_ANIM_OFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Orientation
|
|
||||||
|
|
||||||
auto* orientation_wrapper = lv_obj_create(main_wrapper);
|
|
||||||
lv_obj_set_size(orientation_wrapper, LV_PCT(100), LV_SIZE_CONTENT);
|
|
||||||
lv_obj_set_style_pad_all(orientation_wrapper, 0, LV_STATE_DEFAULT);
|
|
||||||
lv_obj_set_style_border_width(orientation_wrapper, 0, LV_STATE_DEFAULT);
|
|
||||||
|
|
||||||
auto* orientation_label = lv_label_create(orientation_wrapper);
|
|
||||||
lv_label_set_text(orientation_label, "Orientation");
|
|
||||||
lv_obj_align(orientation_label, LV_ALIGN_LEFT_MID, 0, 0);
|
|
||||||
|
|
||||||
auto* orientation_dropdown = lv_dropdown_create(orientation_wrapper);
|
|
||||||
// Note: order correlates with settings::display::Orientation item order
|
|
||||||
lv_dropdown_set_options(orientation_dropdown, "Landscape\nPortrait Right\nLandscape Flipped\nPortrait Left");
|
|
||||||
lv_obj_align(orientation_dropdown, LV_ALIGN_RIGHT_MID, 0, 0);
|
|
||||||
lv_obj_add_event_cb(orientation_dropdown, onOrientationSet, LV_EVENT_VALUE_CHANGED, this);
|
|
||||||
// Set the dropdown to match current orientation enum
|
|
||||||
lv_dropdown_set_selected(orientation_dropdown, static_cast<uint16_t>(displaySettings.orientation));
|
|
||||||
|
|
||||||
// Screen timeout
|
|
||||||
|
|
||||||
if (hal_display->supportsBacklightDuty()) {
|
|
||||||
auto* timeout_wrapper = lv_obj_create(main_wrapper);
|
|
||||||
lv_obj_set_size(timeout_wrapper, LV_PCT(100), LV_SIZE_CONTENT);
|
|
||||||
lv_obj_set_style_pad_all(timeout_wrapper, 0, LV_STATE_DEFAULT);
|
|
||||||
lv_obj_set_style_border_width(timeout_wrapper, 0, LV_STATE_DEFAULT);
|
|
||||||
|
|
||||||
auto* timeout_label = lv_label_create(timeout_wrapper);
|
|
||||||
lv_label_set_text(timeout_label, "Auto screen off");
|
|
||||||
lv_obj_align(timeout_label, LV_ALIGN_LEFT_MID, 0, 0);
|
|
||||||
|
|
||||||
timeoutSwitch = lv_switch_create(timeout_wrapper);
|
|
||||||
if (displaySettings.backlightTimeoutEnabled) {
|
|
||||||
lv_obj_add_state(timeoutSwitch, LV_STATE_CHECKED);
|
|
||||||
}
|
|
||||||
lv_obj_align(timeoutSwitch, LV_ALIGN_RIGHT_MID, 0, 0);
|
|
||||||
lv_obj_add_event_cb(timeoutSwitch, onTimeoutSwitch, LV_EVENT_VALUE_CHANGED, this);
|
|
||||||
|
|
||||||
auto* timeout_select_wrapper = lv_obj_create(main_wrapper);
|
|
||||||
lv_obj_set_size(timeout_select_wrapper, LV_PCT(100), LV_SIZE_CONTENT);
|
|
||||||
lv_obj_set_style_pad_all(timeout_select_wrapper, 0, LV_STATE_DEFAULT);
|
|
||||||
lv_obj_set_style_border_width(timeout_select_wrapper, 0, LV_STATE_DEFAULT);
|
|
||||||
|
|
||||||
auto* timeout_value_label = lv_label_create(timeout_select_wrapper);
|
|
||||||
lv_label_set_text(timeout_value_label, "Timeout");
|
|
||||||
lv_obj_align(timeout_value_label, LV_ALIGN_LEFT_MID, 0, 0);
|
|
||||||
|
|
||||||
timeoutDropdown = lv_dropdown_create(timeout_select_wrapper);
|
|
||||||
lv_dropdown_set_options(timeoutDropdown, "15 seconds\n30 seconds\n1 minute\n2 minutes\n5 minutes\nNever");
|
|
||||||
lv_obj_align(timeoutDropdown, LV_ALIGN_RIGHT_MID, 0, 0);
|
|
||||||
lv_obj_add_event_cb(timeoutDropdown, onTimeoutChanged, LV_EVENT_VALUE_CHANGED, this);
|
|
||||||
// Initialize dropdown selection from settings
|
|
||||||
uint32_t ms = displaySettings.backlightTimeoutMs;
|
|
||||||
uint32_t idx = 2; // default 1 minute
|
|
||||||
if (ms == 15000) idx = 0;
|
|
||||||
else if (ms == 30000)
|
|
||||||
idx = 1;
|
|
||||||
else if (ms == 60000)
|
|
||||||
idx = 2;
|
|
||||||
else if (ms == 120000)
|
|
||||||
idx = 3;
|
|
||||||
else if (ms == 300000)
|
|
||||||
idx = 4;
|
|
||||||
else if (ms == 0)
|
|
||||||
idx = 5;
|
|
||||||
lv_dropdown_set_selected(timeoutDropdown, idx);
|
|
||||||
if (!displaySettings.backlightTimeoutEnabled) {
|
|
||||||
lv_obj_add_state(timeoutDropdown, LV_STATE_DISABLED);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Screensaver type
|
|
||||||
auto* screensaver_wrapper = lv_obj_create(main_wrapper);
|
|
||||||
lv_obj_set_size(screensaver_wrapper, LV_PCT(100), LV_SIZE_CONTENT);
|
|
||||||
lv_obj_set_style_pad_all(screensaver_wrapper, 0, LV_STATE_DEFAULT);
|
|
||||||
lv_obj_set_style_border_width(screensaver_wrapper, 0, LV_STATE_DEFAULT);
|
|
||||||
|
|
||||||
auto* screensaver_label = lv_label_create(screensaver_wrapper);
|
|
||||||
lv_label_set_text(screensaver_label, "Screensaver");
|
|
||||||
lv_obj_align(screensaver_label, LV_ALIGN_LEFT_MID, 0, 0);
|
|
||||||
|
|
||||||
screensaverDropdown = lv_dropdown_create(screensaver_wrapper);
|
|
||||||
// Note: order correlates with settings::display::ScreensaverType enum order
|
|
||||||
lv_dropdown_set_options(screensaverDropdown, "None\nBouncing Balls\nMystify\nMatrix Rain\nStackChan");
|
|
||||||
lv_obj_align(screensaverDropdown, LV_ALIGN_RIGHT_MID, 0, 0);
|
|
||||||
lv_obj_add_event_cb(screensaverDropdown, onScreensaverChanged, LV_EVENT_VALUE_CHANGED, this);
|
|
||||||
lv_dropdown_set_selected(screensaverDropdown, static_cast<uint16_t>(displaySettings.screensaverType));
|
|
||||||
if (!displaySettings.backlightTimeoutEnabled) {
|
|
||||||
lv_obj_add_state(screensaverDropdown, LV_STATE_DISABLED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void onHide(AppContext& app) override {
|
|
||||||
if (displaySettingsUpdated) {
|
|
||||||
// Dispatch it, so file IO doesn't block the UI
|
|
||||||
const settings::display::DisplaySettings settings_to_save = displaySettings;
|
|
||||||
getMainDispatcher().dispatch([settings_to_save] {
|
|
||||||
settings::display::save(settings_to_save);
|
|
||||||
#ifdef ESP_PLATFORM
|
|
||||||
// Notify DisplayIdle service to reload settings
|
|
||||||
auto displayIdle = service::displayidle::findService();
|
|
||||||
if (displayIdle) {
|
|
||||||
displayIdle->reloadSettings();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
extern const AppManifest manifest = {
|
|
||||||
.appId = "Display",
|
|
||||||
.appName = "Display",
|
|
||||||
.appIcon = LVGL_ICON_SHARED_DISPLAY_SETTINGS,
|
|
||||||
.appCategory = Category::Settings,
|
|
||||||
.createApp = create<HalDisplayApp>
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
@ -4,13 +4,11 @@
|
|||||||
|
|
||||||
#include <Tactility/app/AppContext.h>
|
#include <Tactility/app/AppContext.h>
|
||||||
#include <Tactility/app/AppRegistration.h>
|
#include <Tactility/app/AppRegistration.h>
|
||||||
#include <Tactility/hal/display/DisplayDevice.h>
|
|
||||||
#include <Tactility/service/loader/Loader.h>
|
#include <Tactility/service/loader/Loader.h>
|
||||||
|
|
||||||
#include <lvgl.h>
|
#include <lvgl.h>
|
||||||
#include <tactility/device.h>
|
#include <tactility/device.h>
|
||||||
#include <tactility/drivers/power_supply.h>
|
#include <tactility/drivers/power_supply.h>
|
||||||
#include <tactility/hal/Device.h>
|
|
||||||
#include <tactility/lvgl_fonts.h>
|
#include <tactility/lvgl_fonts.h>
|
||||||
#include <tactility/lvgl_icon_shared.h>
|
#include <tactility/lvgl_icon_shared.h>
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
#include "tactility/lvgl_module.h"
|
#include <tactility/lvgl_module.h>
|
||||||
|
|
||||||
|
|
||||||
#include <Tactility/RecursiveMutex.h>
|
#include <Tactility/RecursiveMutex.h>
|
||||||
|
|||||||
@ -1,83 +0,0 @@
|
|||||||
#include <Tactility/SystemEvents.h>
|
|
||||||
#include <Tactility/Tactility.h>
|
|
||||||
#include <Tactility/hal/Configuration.h>
|
|
||||||
#include <Tactility/hal/SdCard.h>
|
|
||||||
#include <Tactility/hal/display/DisplayDevice.h>
|
|
||||||
#include <Tactility/hal/touch/TouchDevice.h>
|
|
||||||
|
|
||||||
#include <tactility/check.h>
|
|
||||||
#include <tactility/hal/Device.h>
|
|
||||||
#include <tactility/log.h>
|
|
||||||
|
|
||||||
namespace tt::hal {
|
|
||||||
|
|
||||||
constexpr auto* TAG = "Hal";
|
|
||||||
|
|
||||||
void registerDevices(const Configuration& configuration) {
|
|
||||||
LOG_I(TAG, "Registering devices");
|
|
||||||
|
|
||||||
auto devices = configuration.createDevices();
|
|
||||||
for (auto& device : devices) {
|
|
||||||
registerDevice(device);
|
|
||||||
|
|
||||||
// Register attached devices
|
|
||||||
if (device->getType() == Device::Type::Display) {
|
|
||||||
const auto display = std::static_pointer_cast<display::DisplayDevice>(device);
|
|
||||||
assert(display != nullptr);
|
|
||||||
const std::shared_ptr<Device> touch = display->getTouchDevice();
|
|
||||||
if (touch != nullptr) {
|
|
||||||
registerDevice(touch);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void startDisplays() {
|
|
||||||
LOG_I(TAG, "Starting displays & touch");
|
|
||||||
auto displays = hal::findDevices<display::DisplayDevice>(Device::Type::Display);
|
|
||||||
for (auto& display : displays) {
|
|
||||||
LOG_I(TAG, "%s starting", display->getName().c_str());
|
|
||||||
if (!display->start()) {
|
|
||||||
LOG_E(TAG, "%s start failed", display->getName().c_str());
|
|
||||||
} else {
|
|
||||||
LOG_I(TAG, "%s started", display->getName().c_str());
|
|
||||||
|
|
||||||
if (display->supportsBacklightDuty()) {
|
|
||||||
LOG_I(TAG, "Setting backlight");
|
|
||||||
display->setBacklightDuty(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto touch = display->getTouchDevice();
|
|
||||||
if (touch != nullptr) {
|
|
||||||
LOG_I(TAG, "%s starting", touch->getName().c_str());
|
|
||||||
if (!touch->start()) {
|
|
||||||
LOG_E(TAG, "%s start failed", touch->getName().c_str());
|
|
||||||
} else {
|
|
||||||
LOG_I(TAG, "%s started", touch->getName().c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void init(const Configuration& configuration) {
|
|
||||||
kernel::publishSystemEvent(kernel::SystemEvent::BootInitHalBegin);
|
|
||||||
|
|
||||||
if (configuration.initBoot != nullptr) {
|
|
||||||
check(configuration.initBoot(), "Init boot failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
registerDevices(configuration);
|
|
||||||
|
|
||||||
sdcard::mountAll(); // Warning: This needs to happen BEFORE displays are initialized on the SPI bus
|
|
||||||
|
|
||||||
startDisplays(); // Warning: SPI displays need to start after SPI SD cards are mounted
|
|
||||||
|
|
||||||
kernel::publishSystemEvent(kernel::SystemEvent::BootInitHalEnd);
|
|
||||||
}
|
|
||||||
|
|
||||||
const Configuration* getConfiguration() {
|
|
||||||
return tt::getConfiguration()->hardware;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
@ -1,59 +0,0 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
#include <Tactility/hal/display/KernelDisplayDriver.h>
|
|
||||||
|
|
||||||
#include <tactility/drivers/display.h>
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <cassert>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
namespace tt::hal::display {
|
|
||||||
|
|
||||||
static ColorFormat toColorFormat(DisplayColorFormat format) {
|
|
||||||
switch (format) {
|
|
||||||
case DISPLAY_COLOR_FORMAT_MONOCHROME:
|
|
||||||
return ColorFormat::Monochrome;
|
|
||||||
case DISPLAY_COLOR_FORMAT_BGR565:
|
|
||||||
return ColorFormat::BGR565;
|
|
||||||
case DISPLAY_COLOR_FORMAT_BGR565_SWAPPED:
|
|
||||||
return ColorFormat::BGR565Swapped;
|
|
||||||
case DISPLAY_COLOR_FORMAT_RGB565:
|
|
||||||
return ColorFormat::RGB565;
|
|
||||||
case DISPLAY_COLOR_FORMAT_RGB565_SWAPPED:
|
|
||||||
return ColorFormat::RGB565Swapped;
|
|
||||||
case DISPLAY_COLOR_FORMAT_RGB888:
|
|
||||||
return ColorFormat::RGB888;
|
|
||||||
default:
|
|
||||||
std::unreachable();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
KernelDisplayDriver::KernelDisplayDriver(::Device* device) : device(device) {
|
|
||||||
assert(device_get_type(device) == &DISPLAY_TYPE);
|
|
||||||
}
|
|
||||||
|
|
||||||
ColorFormat KernelDisplayDriver::getColorFormat() const {
|
|
||||||
return toColorFormat(display_get_color_format(device));
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t KernelDisplayDriver::getPixelWidth() const {
|
|
||||||
return display_get_resolution_x(device);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t KernelDisplayDriver::getPixelHeight() const {
|
|
||||||
return display_get_resolution_y(device);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool KernelDisplayDriver::drawBitmap(int xStart, int yStart, int xEnd, int yEnd, const void* pixelData) {
|
|
||||||
return display_draw_bitmap(device, xStart, yStart, xEnd, yEnd, pixelData) == ERROR_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t KernelDisplayDriver::getFrameBuffers(void* outBuffers[2]) const {
|
|
||||||
uint8_t count = std::min<uint8_t>(display_get_frame_buffer_count(device), 2);
|
|
||||||
for (uint8_t i = 0; i < count; i++) {
|
|
||||||
display_get_frame_buffer(device, i, &outBuffers[i]);
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,87 +0,0 @@
|
|||||||
#include <Tactility/hal/gpio/Gpio.h>
|
|
||||||
|
|
||||||
#ifdef ESP_PLATFORM
|
|
||||||
#include <driver/gpio.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace tt::hal::gpio {
|
|
||||||
|
|
||||||
#ifdef ESP_PLATFORM
|
|
||||||
|
|
||||||
constexpr gpio_num_t toEspPin(Pin pin) { return static_cast<gpio_num_t>(pin); }
|
|
||||||
|
|
||||||
constexpr gpio_mode_t toEspGpioMode(Mode mode) {
|
|
||||||
switch (mode) {
|
|
||||||
case Mode::Input:
|
|
||||||
return GPIO_MODE_INPUT;
|
|
||||||
case Mode::Output:
|
|
||||||
return GPIO_MODE_OUTPUT;
|
|
||||||
case Mode::OutputOpenDrain:
|
|
||||||
return GPIO_MODE_OUTPUT_OD;
|
|
||||||
case Mode::InputOutput:
|
|
||||||
return GPIO_MODE_INPUT_OUTPUT;
|
|
||||||
case Mode::InputOutputOpenDrain:
|
|
||||||
return GPIO_MODE_INPUT_OUTPUT_OD;
|
|
||||||
case Mode::Disable:
|
|
||||||
default:
|
|
||||||
return GPIO_MODE_DISABLE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool getLevel(Pin pin) {
|
|
||||||
#ifdef ESP_PLATFORM
|
|
||||||
return gpio_get_level(toEspPin(pin)) == 1;
|
|
||||||
#else
|
|
||||||
return false;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
bool setLevel(Pin pin, bool level) {
|
|
||||||
#ifdef ESP_PLATFORM
|
|
||||||
return gpio_set_level(toEspPin(pin), level) == ESP_OK;
|
|
||||||
#else
|
|
||||||
return true;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
int getPinCount() {
|
|
||||||
#ifdef ESP_PLATFORM
|
|
||||||
return GPIO_NUM_MAX;
|
|
||||||
#else
|
|
||||||
return 16;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
bool configureWithPinBitmask(uint64_t pinBitMask, Mode mode, bool pullUp, bool pullDown) {
|
|
||||||
#ifdef ESP_PLATFORM
|
|
||||||
gpio_config_t sd_gpio_config = {
|
|
||||||
.pin_bit_mask = pinBitMask,
|
|
||||||
.mode = toEspGpioMode(mode),
|
|
||||||
.pull_up_en = pullUp ? GPIO_PULLUP_ENABLE : GPIO_PULLUP_DISABLE,
|
|
||||||
.pull_down_en = pullDown ? GPIO_PULLDOWN_ENABLE : GPIO_PULLDOWN_DISABLE,
|
|
||||||
.intr_type = GPIO_INTR_DISABLE,
|
|
||||||
};
|
|
||||||
return gpio_config(&sd_gpio_config) == ESP_OK;
|
|
||||||
#else
|
|
||||||
return true;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
bool configure(Pin pin, Mode mode, bool pullUp, bool pullDown) {
|
|
||||||
#ifdef ESP_PLATFORM
|
|
||||||
return configureWithPinBitmask(BIT64(toEspPin(pin)), mode, pullUp, pullDown);
|
|
||||||
#else
|
|
||||||
return true;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
bool setMode(Pin pin, Mode mode) {
|
|
||||||
#ifdef ESP_PLATFORM
|
|
||||||
return gpio_set_direction(toEspPin(pin), toEspGpioMode(mode)) == ESP_OK;
|
|
||||||
#endif
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -2,8 +2,6 @@
|
|||||||
#include "Tactility/service/gps/GpsService.h"
|
#include "Tactility/service/gps/GpsService.h"
|
||||||
#include "Tactility/file/ObjectFile.h"
|
#include "Tactility/file/ObjectFile.h"
|
||||||
|
|
||||||
#include <Tactility/TactilityCore.h>
|
|
||||||
|
|
||||||
namespace tt::hal::gps {
|
namespace tt::hal::gps {
|
||||||
|
|
||||||
const char* toString(GpsModel model) {
|
const char* toString(GpsModel model) {
|
||||||
|
|||||||
@ -17,34 +17,27 @@ constexpr auto* TAG = "GpsDevice";
|
|||||||
int32_t GpsDevice::threadMain() {
|
int32_t GpsDevice::threadMain() {
|
||||||
uint8_t buffer[GPS_UART_BUFFER_SIZE];
|
uint8_t buffer[GPS_UART_BUFFER_SIZE];
|
||||||
|
|
||||||
auto* uart = device_find_by_name(configuration.uartName);
|
UartConfig uartConfig = {
|
||||||
if (uart == nullptr) {
|
.baud_rate = baudRate,
|
||||||
LOG_E(TAG, "Failed to find UART %s", configuration.uartName);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct UartConfig uartConfig = {
|
|
||||||
.baud_rate = configuration.baudRate,
|
|
||||||
.data_bits = UART_CONTROLLER_DATA_8_BITS,
|
.data_bits = UART_CONTROLLER_DATA_8_BITS,
|
||||||
.parity = UART_CONTROLLER_PARITY_DISABLE,
|
.parity = UART_CONTROLLER_PARITY_DISABLE,
|
||||||
.stop_bits = UART_CONTROLLER_STOP_BITS_1
|
.stop_bits = UART_CONTROLLER_STOP_BITS_1
|
||||||
};
|
};
|
||||||
|
|
||||||
error_t error = uart_controller_set_config(uart, &uartConfig);
|
error_t error = uart_controller_set_config(uartDevice, &uartConfig);
|
||||||
if (error != ERROR_NONE) {
|
if (error != ERROR_NONE) {
|
||||||
LOG_E(TAG, "Failed to configure UART %s: %s", configuration.uartName, error_to_string(error));
|
LOG_E(TAG, "Failed to configure UART %s: %s", uartDevice->name, error_to_string(error));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
error = uart_controller_open(uart);
|
error = uart_controller_open(uartDevice);
|
||||||
if (error != ERROR_NONE) {
|
if (error != ERROR_NONE) {
|
||||||
LOG_E(TAG, "Failed to open UART %s: %s", configuration.uartName, error_to_string(error));
|
LOG_E(TAG, "Failed to open UART %s: %s", uartDevice->name, error_to_string(error));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
GpsModel model = configuration.model;
|
|
||||||
if (model == GpsModel::Unknown) {
|
if (model == GpsModel::Unknown) {
|
||||||
model = probe(uart);
|
model = probe(uartDevice);
|
||||||
if (model == GpsModel::Unknown) {
|
if (model == GpsModel::Unknown) {
|
||||||
LOG_E(TAG, "Probe failed");
|
LOG_E(TAG, "Probe failed");
|
||||||
setState(State::Error);
|
setState(State::Error);
|
||||||
@ -52,10 +45,9 @@ int32_t GpsDevice::threadMain() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
mutex.lock();
|
mutex.lock();
|
||||||
this->model = model;
|
|
||||||
mutex.unlock();
|
mutex.unlock();
|
||||||
|
|
||||||
if (!init(uart, model)) {
|
if (!init(uartDevice, model)) {
|
||||||
LOG_E(TAG, "Init failed");
|
LOG_E(TAG, "Init failed");
|
||||||
setState(State::Error);
|
setState(State::Error);
|
||||||
return -1;
|
return -1;
|
||||||
@ -66,7 +58,7 @@ int32_t GpsDevice::threadMain() {
|
|||||||
// Reference: https://gpsd.gitlab.io/gpsd/NMEA.html
|
// Reference: https://gpsd.gitlab.io/gpsd/NMEA.html
|
||||||
while (!isThreadInterrupted()) {
|
while (!isThreadInterrupted()) {
|
||||||
size_t bytes_read = 0;
|
size_t bytes_read = 0;
|
||||||
uart_controller_read_until(uart, buffer, GPS_UART_BUFFER_SIZE, '\n', true, &bytes_read, 100 / portTICK_PERIOD_MS);
|
uart_controller_read_until(uartDevice, buffer, GPS_UART_BUFFER_SIZE, '\n', true, &bytes_read, 100 / portTICK_PERIOD_MS);
|
||||||
|
|
||||||
// Thread might've been interrupted in the meanwhile
|
// Thread might've been interrupted in the meanwhile
|
||||||
if (isThreadInterrupted()) {
|
if (isThreadInterrupted()) {
|
||||||
@ -110,8 +102,8 @@ int32_t GpsDevice::threadMain() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uart_controller_close(uart) != ERROR_NONE) {
|
if (uart_controller_close(uartDevice) != ERROR_NONE) {
|
||||||
LOG_W(TAG, "Failed to stop UART %s", configuration.uartName);
|
LOG_W(TAG, "Failed to stop UART %s", uartDevice->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@ -1,81 +0,0 @@
|
|||||||
#include "Tactility/hal/i2c/I2cDevice.h"
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
namespace tt::hal::i2c {
|
|
||||||
|
|
||||||
bool I2cDevice::read(uint8_t* data, size_t dataSize, TickType_t timeout) {
|
|
||||||
return i2c_controller_read(controller, address, data, dataSize, timeout) == ERROR_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool I2cDevice::write(const uint8_t* data, uint16_t dataSize, TickType_t timeout) {
|
|
||||||
return i2c_controller_write(controller, address, data, dataSize, timeout) == ERROR_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool I2cDevice::writeRead(const uint8_t* writeData, size_t writeDataSize, uint8_t* readData, size_t readDataSize, TickType_t timeout) {
|
|
||||||
return i2c_controller_write_read(controller, address, writeData, writeDataSize, readData, readDataSize, timeout) == ERROR_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool I2cDevice::writeRegister(uint8_t reg, const uint8_t* data, uint16_t dataSize, TickType_t timeout) {
|
|
||||||
return i2c_controller_write_register(controller, address, reg, data, dataSize, timeout) == ERROR_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool I2cDevice::readRegister12(uint8_t reg, float& out) const {
|
|
||||||
std::uint8_t data[2] = {0};
|
|
||||||
if (i2c_controller_read_register(controller, address, reg, data, 2, DEFAULT_TIMEOUT) == ERROR_NONE) {
|
|
||||||
out = (data[0] & 0x0F) << 8 | data[1];
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool I2cDevice::readRegister14(uint8_t reg, float& out) const {
|
|
||||||
std::uint8_t data[2] = {0};
|
|
||||||
if (i2c_controller_read_register(controller, address, reg, data, 2, DEFAULT_TIMEOUT) == ERROR_NONE) {
|
|
||||||
out = (data[0] & 0x3F) << 8 | data[1];
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool I2cDevice::readRegister16(uint8_t reg, uint16_t& out) const {
|
|
||||||
std::uint8_t data[2] = {0};
|
|
||||||
if (i2c_controller_read_register(controller, address, reg, data, 2, DEFAULT_TIMEOUT) == ERROR_NONE) {
|
|
||||||
out = data[0] << 8 | data[1];
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool I2cDevice::readRegister8(uint8_t reg, uint8_t& result) const {
|
|
||||||
return i2c_controller_write_read(controller, address, ®, 1, &result, 1, DEFAULT_TIMEOUT) == ERROR_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool I2cDevice::writeRegister8(uint8_t reg, uint8_t value) const {
|
|
||||||
return i2c_controller_write_register(controller, address, reg, &value, 1, DEFAULT_TIMEOUT) == ERROR_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool I2cDevice::bitOn(uint8_t reg, uint8_t bitmask) const {
|
|
||||||
uint8_t state;
|
|
||||||
if (readRegister8(reg, state)) {
|
|
||||||
state |= bitmask;
|
|
||||||
return writeRegister8(reg, state);
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool I2cDevice::bitOff(uint8_t reg, uint8_t bitmask) const {
|
|
||||||
uint8_t state;
|
|
||||||
if (readRegister8(reg, state)) {
|
|
||||||
state &= ~bitmask;
|
|
||||||
return writeRegister8(reg, state);
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace tt::hal::i2c
|
|
||||||
@ -1,172 +0,0 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
#include <Tactility/hal/power/PowerDevice.h>
|
|
||||||
|
|
||||||
#include <tactility/check.h>
|
|
||||||
#include <tactility/device.h>
|
|
||||||
#include <tactility/driver.h>
|
|
||||||
#include <tactility/drivers/power_supply.h>
|
|
||||||
|
|
||||||
#include <format>
|
|
||||||
|
|
||||||
namespace tt::hal::power {
|
|
||||||
|
|
||||||
#define GET_POWER_DEVICE(device) (static_cast<PowerDevice*>(device_get_driver_data(device)))
|
|
||||||
|
|
||||||
static PowerDevice::MetricType toMetricType(PowerSupplyProperty property) {
|
|
||||||
switch (property) {
|
|
||||||
case POWER_SUPPLY_PROP_IS_CHARGING:
|
|
||||||
return PowerDevice::MetricType::IsCharging;
|
|
||||||
case POWER_SUPPLY_PROP_CURRENT:
|
|
||||||
return PowerDevice::MetricType::Current;
|
|
||||||
case POWER_SUPPLY_PROP_VOLTAGE:
|
|
||||||
return PowerDevice::MetricType::BatteryVoltage;
|
|
||||||
case POWER_SUPPLY_PROP_CAPACITY:
|
|
||||||
default:
|
|
||||||
return PowerDevice::MetricType::ChargeLevel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int toIntValue(PowerDevice::MetricType type, const PowerDevice::MetricData& data) {
|
|
||||||
switch (type) {
|
|
||||||
case PowerDevice::MetricType::IsCharging:
|
|
||||||
return data.valueAsBool ? 1 : 0;
|
|
||||||
case PowerDevice::MetricType::Current:
|
|
||||||
return data.valueAsInt32;
|
|
||||||
case PowerDevice::MetricType::BatteryVoltage:
|
|
||||||
return static_cast<int>(data.valueAsUint32);
|
|
||||||
case PowerDevice::MetricType::ChargeLevel:
|
|
||||||
default:
|
|
||||||
return data.valueAsUint8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool apiSupportsProperty(::Device* device, PowerSupplyProperty property) {
|
|
||||||
return GET_POWER_DEVICE(device)->supportsMetric(toMetricType(property));
|
|
||||||
}
|
|
||||||
|
|
||||||
static error_t apiGetProperty(::Device* device, PowerSupplyProperty property, PowerSupplyPropertyValue* outValue) {
|
|
||||||
auto* power_device = GET_POWER_DEVICE(device);
|
|
||||||
auto metric_type = toMetricType(property);
|
|
||||||
if (!power_device->supportsMetric(metric_type)) {
|
|
||||||
return ERROR_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
PowerDevice::MetricData data;
|
|
||||||
if (!power_device->getMetric(metric_type, data)) {
|
|
||||||
return ERROR_NOT_FOUND;
|
|
||||||
}
|
|
||||||
outValue->int_value = toIntValue(metric_type, data);
|
|
||||||
return ERROR_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool apiSupportsChargeControl(::Device* device) {
|
|
||||||
return GET_POWER_DEVICE(device)->supportsChargeControl();
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool apiIsAllowedToCharge(::Device* device) {
|
|
||||||
return GET_POWER_DEVICE(device)->isAllowedToCharge();
|
|
||||||
}
|
|
||||||
|
|
||||||
static error_t apiSetAllowedToCharge(::Device* device, bool allowed) {
|
|
||||||
auto* power_device = GET_POWER_DEVICE(device);
|
|
||||||
if (!power_device->supportsChargeControl()) {
|
|
||||||
return ERROR_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
power_device->setAllowedToCharge(allowed);
|
|
||||||
return ERROR_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool apiSupportsQuickCharge(::Device* device) {
|
|
||||||
return GET_POWER_DEVICE(device)->supportsQuickCharge();
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool apiIsQuickChargeEnabled(::Device* device) {
|
|
||||||
return GET_POWER_DEVICE(device)->isQuickChargeEnabled();
|
|
||||||
}
|
|
||||||
|
|
||||||
static error_t apiSetQuickChargeEnabled(::Device* device, bool enabled) {
|
|
||||||
auto* power_device = GET_POWER_DEVICE(device);
|
|
||||||
if (!power_device->supportsQuickCharge()) {
|
|
||||||
return ERROR_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
power_device->setQuickChargeEnabled(enabled);
|
|
||||||
return ERROR_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool apiSupportsPowerOff(::Device* device) {
|
|
||||||
return GET_POWER_DEVICE(device)->supportsPowerOff();
|
|
||||||
}
|
|
||||||
|
|
||||||
static error_t apiPowerOff(::Device* device) {
|
|
||||||
auto* power_device = GET_POWER_DEVICE(device);
|
|
||||||
if (!power_device->supportsPowerOff()) {
|
|
||||||
return ERROR_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
power_device->powerOff();
|
|
||||||
return ERROR_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static error_t startDevice(::Device*) { return ERROR_NONE; }
|
|
||||||
static error_t stopDevice(::Device*) { return ERROR_NONE; }
|
|
||||||
|
|
||||||
static PowerSupplyApi powerSupplyApi {
|
|
||||||
.supports_property = apiSupportsProperty,
|
|
||||||
.get_property = apiGetProperty,
|
|
||||||
.supports_charge_control = apiSupportsChargeControl,
|
|
||||||
.is_allowed_to_charge = apiIsAllowedToCharge,
|
|
||||||
.set_allowed_to_charge = apiSetAllowedToCharge,
|
|
||||||
.supports_quick_charge = apiSupportsQuickCharge,
|
|
||||||
.is_quick_charge_enabled = apiIsQuickChargeEnabled,
|
|
||||||
.set_quick_charge_enabled = apiSetQuickChargeEnabled,
|
|
||||||
.supports_power_off = apiSupportsPowerOff,
|
|
||||||
.power_off = apiPowerOff,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const char* powerSupplyCompatible[] = { "hal-power-device", nullptr };
|
|
||||||
|
|
||||||
static Driver powerSupplyDriver {
|
|
||||||
.name = "hal-power-device",
|
|
||||||
.compatible = powerSupplyCompatible,
|
|
||||||
.start_device = startDevice,
|
|
||||||
.stop_device = stopDevice,
|
|
||||||
.api = &powerSupplyApi,
|
|
||||||
.device_type = &POWER_SUPPLY_TYPE,
|
|
||||||
.owner = nullptr,
|
|
||||||
.internal = nullptr,
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Registers the "hal-power-device" driver with the kernel on first use. */
|
|
||||||
static Driver& getPowerSupplyDriver() {
|
|
||||||
static const bool registered = [] {
|
|
||||||
check(driver_construct_add(&powerSupplyDriver) == ERROR_NONE);
|
|
||||||
return true;
|
|
||||||
}();
|
|
||||||
(void)registered;
|
|
||||||
return powerSupplyDriver;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PowerDevice::createPowerSupplyDevice() {
|
|
||||||
kernelDeviceName = std::format("power-supply-{}", getId());
|
|
||||||
kernelDevice.name = kernelDeviceName.c_str();
|
|
||||||
check(device_construct(&kernelDevice) == ERROR_NONE);
|
|
||||||
check(device_add(&kernelDevice) == ERROR_NONE);
|
|
||||||
device_set_driver(&kernelDevice, &getPowerSupplyDriver());
|
|
||||||
check(device_start(&kernelDevice) == ERROR_NONE);
|
|
||||||
device_set_driver_data(&kernelDevice, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PowerDevice::destroyPowerSupplyDevice() {
|
|
||||||
device_set_driver_data(&kernelDevice, nullptr);
|
|
||||||
check(device_stop(&kernelDevice) == ERROR_NONE);
|
|
||||||
check(device_remove(&kernelDevice) == ERROR_NONE);
|
|
||||||
check(device_destruct(&kernelDevice) == ERROR_NONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
PowerDevice::PowerDevice() {
|
|
||||||
createPowerSupplyDevice();
|
|
||||||
}
|
|
||||||
|
|
||||||
PowerDevice::~PowerDevice() {
|
|
||||||
destroyPowerSupplyDevice();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,24 +0,0 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
#include <Tactility/hal/touch/KernelTouchDriver.h>
|
|
||||||
|
|
||||||
#include <tactility/drivers/pointer.h>
|
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
|
|
||||||
namespace tt::hal::touch {
|
|
||||||
|
|
||||||
// Bus reads are expected to complete quickly; bound the wait so a stalled controller can't block the LVGL indev poll.
|
|
||||||
static constexpr TickType_t READ_TIMEOUT = pdMS_TO_TICKS(10);
|
|
||||||
|
|
||||||
KernelTouchDriver::KernelTouchDriver(::Device* device) : device(device) {
|
|
||||||
assert(device_get_type(device) == &POINTER_TYPE);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool KernelTouchDriver::getTouchedPoints(uint16_t* x, uint16_t* y, uint16_t* strength, uint8_t* pointCount, uint8_t maxPointCount) {
|
|
||||||
if (pointer_read_data(device, READ_TIMEOUT) != ERROR_NONE) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return pointer_get_touched_points(device, x, y, strength, pointCount, maxPointCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,205 +0,0 @@
|
|||||||
#include <Tactility/hal/Configuration.h>
|
|
||||||
#include <Tactility/hal/encoder/EncoderDevice.h>
|
|
||||||
#include <Tactility/hal/display/DisplayDevice.h>
|
|
||||||
#include <Tactility/hal/keyboard/KeyboardDevice.h>
|
|
||||||
#include <Tactility/hal/touch/TouchDevice.h>
|
|
||||||
#include <Tactility/lvgl/Keyboard.h>
|
|
||||||
#include <Tactility/lvgl/Lvgl.h>
|
|
||||||
#include <Tactility/lvgl/LvglSync.h>
|
|
||||||
#include <Tactility/service/ServiceRegistration.h>
|
|
||||||
#include <Tactility/settings/DisplaySettings.h>
|
|
||||||
#include <Tactility/settings/TouchCalibrationSettings.h>
|
|
||||||
|
|
||||||
#include <tactility/device.h>
|
|
||||||
#include <tactility/drivers/backlight.h>
|
|
||||||
#include <tactility/log.h>
|
|
||||||
#include <tactility/lvgl_module.h>
|
|
||||||
#include <tactility/lvgl_pointer.h>
|
|
||||||
#include <tactility/module.h>
|
|
||||||
|
|
||||||
#include <lvgl.h>
|
|
||||||
|
|
||||||
namespace tt::lvgl {
|
|
||||||
|
|
||||||
constexpr auto* TAG = "LVGL";
|
|
||||||
|
|
||||||
bool isStarted() {
|
|
||||||
return module_is_started(&lvgl_module);
|
|
||||||
}
|
|
||||||
|
|
||||||
void attachDevices() {
|
|
||||||
LOG_I(TAG, "Adding devices");
|
|
||||||
|
|
||||||
auto lock = getSyncLock()->asScopedLock();
|
|
||||||
lock.lock();
|
|
||||||
|
|
||||||
// Start displays (their related touch devices start automatically within)
|
|
||||||
|
|
||||||
LOG_I(TAG, "Start displays");
|
|
||||||
auto hal_displays= hal::findDevices<hal::display::DisplayDevice>(hal::Device::Type::Display);
|
|
||||||
for (const auto& display: hal_displays) {
|
|
||||||
if (display->supportsLvgl()) {
|
|
||||||
if (display->startLvgl()) {
|
|
||||||
LOG_I(TAG, "Started %s", display->getName().c_str());
|
|
||||||
} else {
|
|
||||||
LOG_E(TAG, "Start failed for %s", display->getName().c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* primary_lvgl_display = lv_disp_get_default();
|
|
||||||
if (primary_lvgl_display != nullptr) {
|
|
||||||
LOG_I(TAG, "Set default display rotation");
|
|
||||||
auto settings = settings::display::loadOrGetDefault();
|
|
||||||
lv_display_rotation_t rotation = settings::display::toLvglDisplayRotation(settings.orientation);
|
|
||||||
if (rotation != lv_display_get_rotation(primary_lvgl_display)) {
|
|
||||||
lv_display_set_rotation(primary_lvgl_display, rotation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start touch
|
|
||||||
|
|
||||||
if (primary_lvgl_display != nullptr) {
|
|
||||||
LOG_I(TAG, "Start touch devices");
|
|
||||||
auto touch_devices = hal::findDevices<hal::touch::TouchDevice>(hal::Device::Type::Touch);
|
|
||||||
for (const auto& touch_device: touch_devices) {
|
|
||||||
// Start any touch devices that haven't been started yet
|
|
||||||
if (touch_device->supportsLvgl() && touch_device->getLvglIndev() == nullptr) {
|
|
||||||
if (touch_device->startLvgl(primary_lvgl_display)) {
|
|
||||||
LOG_I(TAG, "Started %s", touch_device->getName().c_str());
|
|
||||||
} else {
|
|
||||||
LOG_E(TAG, "Start failed for %s", touch_device->getName().c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply touch calibration (kernel POINTER_TYPE model only - see tactility/lvgl_pointer.h)
|
|
||||||
LOG_I(TAG, "Apply touch calibration");
|
|
||||||
auto touch_calibration_settings = settings::touch::loadOrGetDefault();
|
|
||||||
if (touch_calibration_settings.enabled && settings::touch::isValid(touch_calibration_settings)) {
|
|
||||||
auto* pointer_indev = lvgl_pointer_get_default();
|
|
||||||
if (pointer_indev != nullptr) {
|
|
||||||
struct LvglPointerCalibration calibration = {
|
|
||||||
.x_min = touch_calibration_settings.xMin,
|
|
||||||
.x_max = touch_calibration_settings.xMax,
|
|
||||||
.y_min = touch_calibration_settings.yMin,
|
|
||||||
.y_max = touch_calibration_settings.yMax,
|
|
||||||
};
|
|
||||||
if (lvgl_pointer_set_calibration(pointer_indev, &calibration) != ERROR_NONE) {
|
|
||||||
LOG_E(TAG, "Failed to apply saved touch calibration");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start keyboards
|
|
||||||
LOG_I(TAG, "Start keyboards");
|
|
||||||
auto keyboards = hal::findDevices<hal::keyboard::KeyboardDevice>(hal::Device::Type::Keyboard);
|
|
||||||
for (const auto& keyboard: keyboards) {
|
|
||||||
if (keyboard->isAttached()) {
|
|
||||||
if (keyboard->startLvgl(primary_lvgl_display)) {
|
|
||||||
lv_indev_t* keyboard_indev = keyboard->getLvglIndev();
|
|
||||||
hardware_keyboard_set_indev(keyboard_indev);
|
|
||||||
LOG_I(TAG, "Started %s", keyboard->getName().c_str());
|
|
||||||
} else {
|
|
||||||
LOG_E(TAG, "Start failed for %s", keyboard->getName().c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start encoders
|
|
||||||
LOG_I(TAG, "Start encoders");
|
|
||||||
auto encoders = hal::findDevices<hal::encoder::EncoderDevice>(hal::Device::Type::Encoder);
|
|
||||||
for (const auto& encoder: encoders) {
|
|
||||||
if (encoder->startLvgl(primary_lvgl_display)) {
|
|
||||||
LOG_I(TAG, "Started %s", encoder->getName().c_str());
|
|
||||||
} else {
|
|
||||||
LOG_E(TAG, "Start failed for %s", encoder->getName().c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Restart services
|
|
||||||
|
|
||||||
// We search for the manifest first, because during the initial start() during boot
|
|
||||||
// the service won't be registered yet.
|
|
||||||
if (service::findManifestById("Gui") != nullptr) {
|
|
||||||
if (service::getState("Gui") == SERVICE_STATE_STOPPED) {
|
|
||||||
service::startService("Gui");
|
|
||||||
} else {
|
|
||||||
LOG_E(TAG, "Gui service is not in Stopped state");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We search for the manifest first, because during the initial start() during boot
|
|
||||||
// the service won't be registered yet.
|
|
||||||
if (service::findManifestById("Statusbar") != nullptr) {
|
|
||||||
if (service::getState("Statusbar") == SERVICE_STATE_STOPPED) {
|
|
||||||
service::startService("Statusbar");
|
|
||||||
} else {
|
|
||||||
LOG_E(TAG, "Statusbar service is not in Stopped state");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void detachDevices() {
|
|
||||||
LOG_I(TAG, "Removing devices");
|
|
||||||
|
|
||||||
auto lock = getSyncLock()->asScopedLock();
|
|
||||||
lock.lock();
|
|
||||||
|
|
||||||
// Stop services that highly depend on LVGL
|
|
||||||
|
|
||||||
service::stopService("Statusbar");
|
|
||||||
service::stopService("Gui");
|
|
||||||
|
|
||||||
// Stop keyboards
|
|
||||||
|
|
||||||
LOG_I(TAG, "Stopping keyboards");
|
|
||||||
auto keyboards = hal::findDevices<hal::keyboard::KeyboardDevice>(hal::Device::Type::Keyboard);
|
|
||||||
for (auto keyboard: keyboards) {
|
|
||||||
if (keyboard->getLvglIndev() != nullptr) {
|
|
||||||
keyboard->stopLvgl();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stop touch
|
|
||||||
|
|
||||||
LOG_I(TAG, "Stopping touch");
|
|
||||||
// The display generally stops their own touch devices, but we'll clean up anything that didn't
|
|
||||||
auto touch_devices = hal::findDevices<hal::touch::TouchDevice>(hal::Device::Type::Touch);
|
|
||||||
for (auto touch_device: touch_devices) {
|
|
||||||
if (touch_device->getLvglIndev() != nullptr) {
|
|
||||||
touch_device->stopLvgl();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stop encoders
|
|
||||||
|
|
||||||
LOG_I(TAG, "Stopping encoders");
|
|
||||||
// The display generally stops their own touch devices, but we'll clean up anything that didn't
|
|
||||||
auto encoder_devices = hal::findDevices<hal::encoder::EncoderDevice>(hal::Device::Type::Encoder);
|
|
||||||
for (auto encoder_device: encoder_devices) {
|
|
||||||
if (encoder_device->getLvglIndev() != nullptr) {
|
|
||||||
encoder_device->stopLvgl();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Stop displays (and their touch devices)
|
|
||||||
|
|
||||||
LOG_I(TAG, "Stopping displays");
|
|
||||||
auto displays = hal::findDevices<hal::display::DisplayDevice>(hal::Device::Type::Display);
|
|
||||||
for (auto display: displays) {
|
|
||||||
if (display->supportsLvgl() && display->getLvglDisplay() != nullptr && !display->stopLvgl()) {
|
|
||||||
LOG_E(TAG, "Failed to detach display from LVGL");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void start() {
|
|
||||||
check(module_start(&lvgl_module) == ERROR_NONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void stop() {
|
|
||||||
check(module_stop(&lvgl_module) == ERROR_NONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
@ -3,6 +3,8 @@
|
|||||||
#include <Tactility/Tactility.h>
|
#include <Tactility/Tactility.h>
|
||||||
#include <Tactility/lvgl/Toolbar.h>
|
#include <Tactility/lvgl/Toolbar.h>
|
||||||
|
|
||||||
|
#include "tactility/drivers/pointer.h"
|
||||||
|
|
||||||
#include <Tactility/lvgl/Spinner.h>
|
#include <Tactility/lvgl/Spinner.h>
|
||||||
#include <Tactility/service/loader/Loader.h>
|
#include <Tactility/service/loader/Loader.h>
|
||||||
|
|
||||||
@ -154,7 +156,7 @@ lv_obj_t* toolbar_create(lv_obj_t* parent, const std::string& title) {
|
|||||||
// If we don't have a touch device, we assume there's some other kind of input like a keyboard, an encoder or button control
|
// If we don't have a touch device, we assume there's some other kind of input like a keyboard, an encoder or button control
|
||||||
// In that scenario we want to automatically have the close button selected so the user doesn't have to press the widget selection
|
// In that scenario we want to automatically have the close button selected so the user doesn't have to press the widget selection
|
||||||
// an extra time for every screen.
|
// an extra time for every screen.
|
||||||
if (!hal::hasDevice(hal::Device::Type::Touch)) {
|
if (!device_has_active_by_type(&POINTER_TYPE)) {
|
||||||
lv_group_focus_obj(toolbar->close_button);
|
lv_group_focus_obj(toolbar->close_button);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,32 +2,28 @@
|
|||||||
|
|
||||||
#include <Tactility/service/displayidle/DisplayIdleService.h>
|
#include <Tactility/service/displayidle/DisplayIdleService.h>
|
||||||
|
|
||||||
#include "Screensaver.h"
|
|
||||||
#include "BouncingBallsScreensaver.h"
|
#include "BouncingBallsScreensaver.h"
|
||||||
#include "MatrixRainScreensaver.h"
|
#include "MatrixRainScreensaver.h"
|
||||||
#include "MystifyScreensaver.h"
|
#include "MystifyScreensaver.h"
|
||||||
|
#include "Screensaver.h"
|
||||||
#include "StackChanScreensaver.h"
|
#include "StackChanScreensaver.h"
|
||||||
|
|
||||||
#include <tactility/log.h>
|
|
||||||
#include <Tactility/CoreDefines.h>
|
|
||||||
#include <Tactility/hal/display/DisplayDevice.h>
|
|
||||||
#include <Tactility/lvgl/LvglSync.h>
|
|
||||||
#include <Tactility/service/ServiceContext.h>
|
|
||||||
#include <Tactility/service/ServiceManifest.h>
|
#include <Tactility/service/ServiceManifest.h>
|
||||||
#include <Tactility/service/ServiceRegistration.h>
|
#include <Tactility/service/ServiceRegistration.h>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
||||||
|
#include <tactility/log.h>
|
||||||
|
#include <tactility/drivers/display.h>
|
||||||
|
#include <tactility/drivers/backlight.h>
|
||||||
|
#include <tactility/lvgl_module.h>
|
||||||
|
|
||||||
namespace tt::service::displayidle {
|
namespace tt::service::displayidle {
|
||||||
|
|
||||||
constexpr auto* TAG = "DisplayIdle";
|
constexpr auto* TAG = "DisplayIdle";
|
||||||
|
|
||||||
constexpr uint32_t kWakeActivityThresholdMs = 100;
|
constexpr uint32_t kWakeActivityThresholdMs = 100;
|
||||||
|
|
||||||
static std::shared_ptr<hal::display::DisplayDevice> getDisplay() {
|
|
||||||
return hal::findFirstDevice<hal::display::DisplayDevice>(hal::Device::Type::Display);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DisplayIdleService::stopScreensaverCb(lv_event_t* e) {
|
void DisplayIdleService::stopScreensaverCb(lv_event_t* e) {
|
||||||
auto* self = static_cast<DisplayIdleService*>(lv_event_get_user_data(e));
|
auto* self = static_cast<DisplayIdleService*>(lv_event_get_user_data(e));
|
||||||
lv_event_stop_bubbling(e);
|
lv_event_stop_bubbling(e);
|
||||||
@ -35,8 +31,34 @@ void DisplayIdleService::stopScreensaverCb(lv_event_t* e) {
|
|||||||
lv_display_trigger_activity(nullptr);
|
lv_display_trigger_activity(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void setBacklightBrightness(uint8_t brightness) {
|
||||||
|
::Device* display;
|
||||||
|
if (device_get_first_active_by_type(&DISPLAY_TYPE, &display) == ERROR_NONE) {
|
||||||
|
::Device* backlight;
|
||||||
|
if (display_get_backlight(display, &backlight) == ERROR_NONE) {
|
||||||
|
device_get(backlight);
|
||||||
|
backlight_set_brightness(backlight, brightness);
|
||||||
|
device_put(backlight);
|
||||||
|
}
|
||||||
|
device_put(display);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool hasDisplayWithBacklight() {
|
||||||
|
::Device* display;
|
||||||
|
bool result = false;
|
||||||
|
if (device_get_first_active_by_type(&DISPLAY_TYPE, &display) == ERROR_NONE) {
|
||||||
|
::Device* backlight;
|
||||||
|
if (display_get_backlight(display, &backlight) == ERROR_NONE) {
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
device_put(display);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void DisplayIdleService::stopScreensaver() {
|
void DisplayIdleService::stopScreensaver() {
|
||||||
if (!lvgl::lock(100)) {
|
if (!lvgl_try_lock(100)) {
|
||||||
// Lock failed - keep flag set to retry on next tick
|
// Lock failed - keep flag set to retry on next tick
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -52,7 +74,7 @@ void DisplayIdleService::stopScreensaver() {
|
|||||||
lv_obj_delete(screensaverOverlay);
|
lv_obj_delete(screensaverOverlay);
|
||||||
screensaverOverlay = nullptr;
|
screensaverOverlay = nullptr;
|
||||||
}
|
}
|
||||||
lvgl::unlock();
|
lvgl_unlock();
|
||||||
stopScreensaverRequested.store(false, std::memory_order_relaxed);
|
stopScreensaverRequested.store(false, std::memory_order_relaxed);
|
||||||
|
|
||||||
// Reset auto-off state
|
// Reset auto-off state
|
||||||
@ -60,10 +82,10 @@ void DisplayIdleService::stopScreensaver() {
|
|||||||
backlightOff = false;
|
backlightOff = false;
|
||||||
|
|
||||||
// Restore backlight if display was dimmed
|
// Restore backlight if display was dimmed
|
||||||
auto display = getDisplay();
|
if (wasDimmed) {
|
||||||
if (display && wasDimmed) {
|
setBacklightBrightness(restoreDuty);
|
||||||
display->setBacklightDuty(restoreDuty);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
displayDimmed = wasDimmed ? false : displayDimmed;
|
displayDimmed = wasDimmed ? false : displayDimmed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,11 +146,11 @@ void DisplayIdleService::updateScreensaver() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DisplayIdleService::tick() {
|
void DisplayIdleService::tick() {
|
||||||
if (!lvgl::lock(100)) {
|
if (!lvgl_try_lock(100)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (lv_display_get_default() == nullptr) {
|
if (lv_display_get_default() == nullptr) {
|
||||||
lvgl::unlock();
|
lvgl_unlock();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,10 +174,7 @@ void DisplayIdleService::tick() {
|
|||||||
screensaver->stop();
|
screensaver->stop();
|
||||||
screensaver.reset();
|
screensaver.reset();
|
||||||
}
|
}
|
||||||
auto display = getDisplay();
|
setBacklightBrightness(0);
|
||||||
if (display) {
|
|
||||||
display->setBacklightDuty(0);
|
|
||||||
}
|
|
||||||
backlightOff = true;
|
backlightOff = true;
|
||||||
} else {
|
} else {
|
||||||
updateScreensaver();
|
updateScreensaver();
|
||||||
@ -163,7 +182,7 @@ void DisplayIdleService::tick() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lvgl::unlock();
|
lvgl_unlock();
|
||||||
|
|
||||||
// Check stop request early for faster response
|
// Check stop request early for faster response
|
||||||
if (stopScreensaverRequested.load(std::memory_order_acquire)) {
|
if (stopScreensaverRequested.load(std::memory_order_acquire)) {
|
||||||
@ -171,23 +190,22 @@ void DisplayIdleService::tick() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto display = getDisplay();
|
if (hasDisplayWithBacklight()) {
|
||||||
if (display != nullptr && display->supportsBacklightDuty()) {
|
|
||||||
if (!cachedDisplaySettings.backlightTimeoutEnabled || cachedDisplaySettings.backlightTimeoutMs == 0) {
|
if (!cachedDisplaySettings.backlightTimeoutEnabled || cachedDisplaySettings.backlightTimeoutMs == 0) {
|
||||||
if (displayDimmed) {
|
if (displayDimmed) {
|
||||||
display->setBacklightDuty(cachedDisplaySettings.backlightDuty);
|
setBacklightBrightness(cachedDisplaySettings.backlightDuty);
|
||||||
displayDimmed = false;
|
displayDimmed = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!displayDimmed && inactive_ms >= cachedDisplaySettings.backlightTimeoutMs) {
|
if (!displayDimmed && inactive_ms >= cachedDisplaySettings.backlightTimeoutMs) {
|
||||||
if (!lvgl::lock(100)) {
|
if (!lvgl_try_lock(100)) {
|
||||||
return; // Retry on next tick
|
return; // Retry on next tick
|
||||||
}
|
}
|
||||||
activateScreensaver();
|
activateScreensaver();
|
||||||
lvgl::unlock();
|
lvgl_unlock();
|
||||||
// Turn off backlight for "None" screensaver (just black screen)
|
// Turn off backlight for "None" screensaver (just black screen)
|
||||||
if (cachedDisplaySettings.screensaverType == settings::display::ScreensaverType::None) {
|
if (cachedDisplaySettings.screensaverType == settings::display::ScreensaverType::None) {
|
||||||
display->setBacklightDuty(0);
|
setBacklightBrightness(0);
|
||||||
}
|
}
|
||||||
displayDimmed = true;
|
displayDimmed = true;
|
||||||
} else if (displayDimmed && (inactive_ms < kWakeActivityThresholdMs)) {
|
} else if (displayDimmed && (inactive_ms < kWakeActivityThresholdMs)) {
|
||||||
@ -231,7 +249,7 @@ void DisplayIdleService::onStop(ServiceContext& service) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DisplayIdleService::startScreensaver() {
|
void DisplayIdleService::startScreensaver() {
|
||||||
if (!lvgl::lock(100)) {
|
if (!lvgl_try_lock(100)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,12 +258,11 @@ void DisplayIdleService::startScreensaver() {
|
|||||||
cachedDisplaySettings = settings::display::loadOrGetDefault();
|
cachedDisplaySettings = settings::display::loadOrGetDefault();
|
||||||
|
|
||||||
activateScreensaver();
|
activateScreensaver();
|
||||||
lvgl::unlock();
|
lvgl_unlock();
|
||||||
|
|
||||||
// Turn off backlight for "None" screensaver
|
// Turn off backlight for "None" screensaver
|
||||||
auto display = getDisplay();
|
if (hasDisplayWithBacklight() && cachedDisplaySettings.screensaverType == settings::display::ScreensaverType::None) {
|
||||||
if (display && cachedDisplaySettings.screensaverType == settings::display::ScreensaverType::None) {
|
setBacklightBrightness(0);
|
||||||
display->setBacklightDuty(0);
|
|
||||||
}
|
}
|
||||||
displayDimmed = true;
|
displayDimmed = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -157,8 +157,17 @@ bool GpsService::startReceiving() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& configuration: configurations) {
|
for (const auto& configuration: configurations) {
|
||||||
auto device = std::make_shared<GpsDevice>(configuration);
|
::Device* uart_device;
|
||||||
addGpsDevice(device);
|
if (device_get_by_name(configuration.uartName, &uart_device) == ERROR_NONE) {
|
||||||
|
auto gps_device = std::make_shared<GpsDevice>(
|
||||||
|
uart_device,
|
||||||
|
configuration.baudRate,
|
||||||
|
configuration.model
|
||||||
|
);
|
||||||
|
addGpsDevice(gps_device);
|
||||||
|
} else {
|
||||||
|
LOG_E(TAG, "Failed to find device %s", configuration.uartName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset times before starting devices to avoid race with incoming data
|
// Reset times before starting devices to avoid race with incoming data
|
||||||
|
|||||||
@ -1,16 +1,18 @@
|
|||||||
#ifdef ESP_PLATFORM
|
#ifdef ESP_PLATFORM
|
||||||
|
|
||||||
#include <Tactility/CoreDefines.h>
|
#include <display/lv_display.h>
|
||||||
#include <Tactility/hal/keyboard/KeyboardDevice.h>
|
|
||||||
#include <Tactility/lvgl/LvglSync.h>
|
|
||||||
|
#include <Tactility/Timer.h>
|
||||||
#include <Tactility/service/ServiceContext.h>
|
#include <Tactility/service/ServiceContext.h>
|
||||||
#include <Tactility/service/ServiceManifest.h>
|
#include <Tactility/service/ServiceManifest.h>
|
||||||
#include <Tactility/service/ServiceRegistration.h>
|
#include <Tactility/service/ServiceRegistration.h>
|
||||||
#include <Tactility/settings/KeyboardSettings.h>
|
#include <Tactility/settings/KeyboardSettings.h>
|
||||||
#include <Tactility/Timer.h>
|
|
||||||
|
|
||||||
#include <tactility/device.h>
|
#include <tactility/device.h>
|
||||||
#include <tactility/drivers/backlight.h>
|
#include <tactility/drivers/backlight.h>
|
||||||
|
#include <tactility/drivers/keyboard.h>
|
||||||
|
#include <tactility/lvgl_module.h>
|
||||||
|
|
||||||
namespace tt::service::keyboardidle {
|
namespace tt::service::keyboardidle {
|
||||||
|
|
||||||
@ -20,11 +22,15 @@ class KeyboardIdleService final : public Service {
|
|||||||
bool keyboardDimmed = false;
|
bool keyboardDimmed = false;
|
||||||
settings::keyboard::KeyboardSettings cachedKeyboardSettings;
|
settings::keyboard::KeyboardSettings cachedKeyboardSettings;
|
||||||
|
|
||||||
static std::shared_ptr<hal::keyboard::KeyboardDevice> getKeyboard() {
|
|
||||||
return hal::findFirstDevice<hal::keyboard::KeyboardDevice>(hal::Device::Type::Keyboard);
|
|
||||||
}
|
|
||||||
|
|
||||||
static Device* getKeyboardBacklight() {
|
static Device* getKeyboardBacklight() {
|
||||||
|
::Device* keyboard;
|
||||||
|
if (device_get_first_active_by_type(&KEYBOARD_TYPE, &keyboard) == ERROR_NONE) {
|
||||||
|
::Device* backlight = nullptr;
|
||||||
|
keyboard_get_backlight(keyboard, &backlight); // disregard result
|
||||||
|
device_put(keyboard);
|
||||||
|
return backlight; // WARNING: did not increase refcount
|
||||||
|
}
|
||||||
|
// TODO: Remove after all drivers are migrated
|
||||||
return device_find_by_name("keyboard_backlight");
|
return device_find_by_name("keyboard_backlight");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,14 +47,13 @@ class KeyboardIdleService final : public Service {
|
|||||||
|
|
||||||
// Query LVGL inactivity once for both checks
|
// Query LVGL inactivity once for both checks
|
||||||
uint32_t inactive_ms = 0;
|
uint32_t inactive_ms = 0;
|
||||||
if (lvgl::lock(100)) {
|
if (lvgl_try_lock(100)) {
|
||||||
inactive_ms = lv_display_get_inactive_time(nullptr);
|
inactive_ms = lv_display_get_inactive_time(nullptr);
|
||||||
lvgl::unlock();
|
lvgl_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle keyboard backlight
|
// Handle keyboard backlight
|
||||||
auto keyboard = getKeyboard();
|
if (device_has_active_by_type(&KEYBOARD_TYPE)) {
|
||||||
if (keyboard != nullptr && keyboard->isAttached()) {
|
|
||||||
// If timeout disabled, ensure backlight restored if we had dimmed it
|
// If timeout disabled, ensure backlight restored if we had dimmed it
|
||||||
if (!cachedKeyboardSettings.backlightTimeoutEnabled || cachedKeyboardSettings.backlightTimeoutMs == 0) {
|
if (!cachedKeyboardSettings.backlightTimeoutEnabled || cachedKeyboardSettings.backlightTimeoutMs == 0) {
|
||||||
if (keyboardDimmed) {
|
if (keyboardDimmed) {
|
||||||
@ -89,8 +94,7 @@ public:
|
|||||||
timer = nullptr;
|
timer = nullptr;
|
||||||
}
|
}
|
||||||
// Ensure keyboard restored on stop
|
// Ensure keyboard restored on stop
|
||||||
auto keyboard = getKeyboard();
|
if (device_has_active_by_type(&KEYBOARD_TYPE) && keyboardDimmed) {
|
||||||
if (keyboard && keyboardDimmed) {
|
|
||||||
setKeyboardBacklightBrightness(cachedKeyboardSettings.backlightEnabled ? cachedKeyboardSettings.backlightBrightness : 0);
|
setKeyboardBacklightBrightness(cachedKeyboardSettings.backlightEnabled ? cachedKeyboardSettings.backlightBrightness : 0);
|
||||||
keyboardDimmed = false;
|
keyboardDimmed = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,25 +1,27 @@
|
|||||||
#include <Tactility/lvgl/Statusbar.h>
|
#include <Tactility/lvgl/Statusbar.h>
|
||||||
|
|
||||||
|
#include <tactility/lvgl_module.h>
|
||||||
|
#include "tactility/module.h"
|
||||||
|
|
||||||
#include <Tactility/Mutex.h>
|
#include <Tactility/Mutex.h>
|
||||||
#include <Tactility/Timer.h>
|
#include <Tactility/Timer.h>
|
||||||
#include <tactility/drivers/power_supply.h>
|
#include <Tactility/bluetooth/Bluetooth.h>
|
||||||
#include <tactility/filesystem/file_system.h>
|
|
||||||
#include <Tactility/lvgl/Lvgl.h>
|
|
||||||
#include <Tactility/lvgl/LvglSync.h>
|
#include <Tactility/lvgl/LvglSync.h>
|
||||||
#include <Tactility/service/ServiceContext.h>
|
#include <Tactility/service/ServiceContext.h>
|
||||||
#include <Tactility/service/ServicePaths.h>
|
#include <Tactility/service/ServicePaths.h>
|
||||||
#include <Tactility/service/ServiceRegistration.h>
|
#include <Tactility/service/ServiceRegistration.h>
|
||||||
#include <Tactility/bluetooth/Bluetooth.h>
|
|
||||||
#include <tactility/drivers/bluetooth.h>
|
|
||||||
#include <tactility/drivers/bluetooth_serial.h>
|
|
||||||
#include <tactility/drivers/bluetooth_midi.h>
|
|
||||||
#include <tactility/device.h>
|
|
||||||
#include <tactility/drivers/usb_host_hid.h>
|
|
||||||
#include <tactility/drivers/usb_host_midi.h>
|
|
||||||
#include <tactility/drivers/usb_host_msc.h>
|
|
||||||
#include <Tactility/service/gps/GpsService.h>
|
#include <Tactility/service/gps/GpsService.h>
|
||||||
#include <Tactility/service/wifi/Wifi.h>
|
#include <Tactility/service/wifi/Wifi.h>
|
||||||
#include <tactility/check.h>
|
#include <tactility/check.h>
|
||||||
|
#include <tactility/device.h>
|
||||||
|
#include <tactility/drivers/bluetooth.h>
|
||||||
|
#include <tactility/drivers/bluetooth_midi.h>
|
||||||
|
#include <tactility/drivers/bluetooth_serial.h>
|
||||||
|
#include <tactility/drivers/power_supply.h>
|
||||||
|
#include <tactility/drivers/usb_host_hid.h>
|
||||||
|
#include <tactility/drivers/usb_host_midi.h>
|
||||||
|
#include <tactility/drivers/usb_host_msc.h>
|
||||||
|
#include <tactility/filesystem/file_system.h>
|
||||||
|
|
||||||
#include <tactility/lvgl_icon_statusbar.h>
|
#include <tactility/lvgl_icon_statusbar.h>
|
||||||
|
|
||||||
@ -267,15 +269,15 @@ class StatusbarService final : public Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void update() {
|
void update() {
|
||||||
if (lvgl::isStarted()) {
|
if (module_is_started(&lvgl_module)) {
|
||||||
if (lvgl::lock(100)) {
|
if (lvgl_try_lock(100)) {
|
||||||
updateGpsIcon();
|
updateGpsIcon();
|
||||||
updateBluetoothIcon();
|
updateBluetoothIcon();
|
||||||
updateWifiIcon();
|
updateWifiIcon();
|
||||||
updateSdCardIcon();
|
updateSdCardIcon();
|
||||||
updatePowerStatusIcon();
|
updatePowerStatusIcon();
|
||||||
updateUsbIcon();
|
updateUsbIcon();
|
||||||
lvgl::unlock();
|
lvgl_unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,6 @@
|
|||||||
#include <Tactility/file/PropertiesFile.h>
|
#include <Tactility/file/PropertiesFile.h>
|
||||||
#include <Tactility/Paths.h>
|
#include <Tactility/Paths.h>
|
||||||
#include <tactility/hal/Device.h>
|
#include <tactility/hal/Device.h>
|
||||||
#include <Tactility/hal/display/DisplayDevice.h>
|
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|||||||
@ -1,23 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool tt_gps_has_coordinates();
|
|
||||||
|
|
||||||
bool tt_gps_get_coordinates(
|
|
||||||
float* longitude,
|
|
||||||
float* latitude,
|
|
||||||
float* speed,
|
|
||||||
float* course,
|
|
||||||
int* day,
|
|
||||||
int* month,
|
|
||||||
int* year
|
|
||||||
);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
@ -1,34 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
DEVICE_TYPE_I2C,
|
|
||||||
DEVICE_TYPE_DISPLAY,
|
|
||||||
DEVICE_TYPE_TOUCH,
|
|
||||||
DEVICE_TYPE_SDCARD,
|
|
||||||
DEVICE_TYPE_KEYBOARD,
|
|
||||||
DEVICE_TYPE_POWER,
|
|
||||||
DEVICE_TYPE_GPS
|
|
||||||
} TtDeviceType;
|
|
||||||
|
|
||||||
typedef uint32_t DeviceId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find one or more devices of a certain type.
|
|
||||||
* @param[in] type the type to look for
|
|
||||||
* @param[inout] deviceIds the output ids, which should fit at least maxCount amount of devices
|
|
||||||
* @param[out] count the resulting number of device ids that were returned
|
|
||||||
* @param[in] maxCount the maximum number of items that the "deviceIds" output can contain (minimum value is 1)
|
|
||||||
* @return true if one or more devices were found
|
|
||||||
*/
|
|
||||||
bool tt_hal_device_find(TtDeviceType type, DeviceId* deviceIds, uint16_t* count, uint16_t maxCount);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
@ -1,100 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <tt_hal_device.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <freertos/FreeRTOS.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef void* DisplayDriverHandle;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
COLOR_FORMAT_MONOCHROME, // 1 bpp
|
|
||||||
COLOR_FORMAT_BGR565,
|
|
||||||
COLOR_FORMAT_BGR565_SWAPPED,
|
|
||||||
COLOR_FORMAT_RGB565,
|
|
||||||
COLOR_FORMAT_RGB565_SWAPPED,
|
|
||||||
COLOR_FORMAT_RGB888
|
|
||||||
} ColorFormat;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the display driver interface is supported for this device.
|
|
||||||
* @param[in] displayId the identifier of the display device
|
|
||||||
* @return true if the driver is supported.
|
|
||||||
*/
|
|
||||||
bool tt_hal_display_driver_supported(DeviceId displayId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allocate a driver object for the specified displayId.
|
|
||||||
* @warning check whether the driver is supported by calling tt_hal_display_driver_supported() first
|
|
||||||
* @param[in] displayId the identifier of the display device
|
|
||||||
* @return the driver handle
|
|
||||||
*/
|
|
||||||
DisplayDriverHandle tt_hal_display_driver_alloc(DeviceId displayId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Free the memory for the display driver.
|
|
||||||
* @param[in] handle the display driver handle
|
|
||||||
*/
|
|
||||||
void tt_hal_display_driver_free(DisplayDriverHandle handle);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Lock the display device. Call this function before doing any draw calls.
|
|
||||||
* Certain display devices are on a shared bus (e.g. SPI) so they must run
|
|
||||||
* mutually exclusive with other devices on the same bus (e.g. SD card)
|
|
||||||
* @param[in] handle the display driver handle
|
|
||||||
* @param[in] timeout the maximum amount of ticks to wait for getting a lock
|
|
||||||
* @return true if the lock was acquired
|
|
||||||
*/
|
|
||||||
bool tt_hal_display_driver_lock(DisplayDriverHandle handle, TickType_t timeout);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unlock the display device. Must be called exactly once after locking.
|
|
||||||
* @param[in] handle the display driver handle
|
|
||||||
*/
|
|
||||||
void tt_hal_display_driver_unlock(DisplayDriverHandle handle);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param[in] handle the display driver handle
|
|
||||||
* @return the native color format for this display
|
|
||||||
*/
|
|
||||||
ColorFormat tt_hal_display_driver_get_colorformat(DisplayDriverHandle handle);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param[in] handle the display driver handle
|
|
||||||
* @return the horizontal resolution of the display
|
|
||||||
*/
|
|
||||||
uint16_t tt_hal_display_driver_get_pixel_width(DisplayDriverHandle handle);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param[in] handle the display driver handle
|
|
||||||
* @return the vertical resolution of the display
|
|
||||||
*/
|
|
||||||
uint16_t tt_hal_display_driver_get_pixel_height(DisplayDriverHandle handle);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Draw pixels on the screen. Make sure to call the lock function first and unlock afterwards.
|
|
||||||
* Many draw calls can be done inbetween a single lock and unlock.
|
|
||||||
* @param[in] handle the display driver handle
|
|
||||||
* @param[in] xStart the starting x coordinate for rendering the pixel data
|
|
||||||
* @param[in] yStart the starting y coordinate for rendering the pixel data
|
|
||||||
* @param[in] xEnd the last x coordinate for rendering the pixel data (absolute pixel value, not relative to xStart!)
|
|
||||||
* @param[in] yEnd the last y coordinate for rendering the pixel data (absolute pixel value, not relative to yStart!)
|
|
||||||
* @param[in] pixelData a buffer of pixels. the data is placed as "RowRowRowRow". The size depends on the ColorFormat
|
|
||||||
*/
|
|
||||||
void tt_hal_display_driver_draw_bitmap(DisplayDriverHandle handle, int xStart, int yStart, int xEnd, int yEnd, const void* pixelData);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get direct pointers to the display's hardware frame buffer(s), if supported.
|
|
||||||
* Only available for panels with direct CPU-addressable frame buffers (e.g. MIPI-DSI/DPI).
|
|
||||||
* @param[in] handle the display driver handle
|
|
||||||
* @param[out] outBuffers receives up to 2 frame buffer pointers
|
|
||||||
* @return number of buffers written to outBuffers (0 if unsupported)
|
|
||||||
*/
|
|
||||||
uint8_t tt_hal_display_driver_get_frame_buffers(DisplayDriverHandle handle, void* outBuffers[2]);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
@ -1,24 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** @deprecated NON-FUNCTIONAL - WILL BE REMOVED SOON */
|
|
||||||
typedef unsigned int GpioPin;
|
|
||||||
|
|
||||||
/** @deprecated NON-FUNCTIONAL - WILL BE REMOVED SOON */
|
|
||||||
#define GPIO_NO_PIN -1
|
|
||||||
|
|
||||||
/** @deprecated NON-FUNCTIONAL - WILL BE REMOVED SOON */
|
|
||||||
bool tt_hal_gpio_get_level(GpioPin pin);
|
|
||||||
|
|
||||||
/** @deprecated NON-FUNCTIONAL - WILL BE REMOVED SOON */
|
|
||||||
int tt_hal_gpio_get_pin_count();
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
@ -1,48 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "tt_hal_device.h"
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef void* TouchDriverHandle;
|
|
||||||
/**
|
|
||||||
* Check if the touch driver interface is supported for this device.
|
|
||||||
* @param[in] touchDeviceId the identifier of the touch device
|
|
||||||
* @return true if the driver is supported.
|
|
||||||
*/
|
|
||||||
bool tt_hal_touch_driver_supported(DeviceId touchDeviceId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allocate a driver object for the specified touchDeviceId.
|
|
||||||
* @warning check whether the driver is supported by calling tt_hal_touch_driver_supported() first
|
|
||||||
* @param[in] touchDeviceId the identifier of the touch device
|
|
||||||
* @return the driver handle
|
|
||||||
*/
|
|
||||||
TouchDriverHandle tt_hal_touch_driver_alloc(DeviceId touchDeviceId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Free the memory for the touch driver.
|
|
||||||
* @param[in] handle the touch driver handle
|
|
||||||
*/
|
|
||||||
void tt_hal_touch_driver_free(TouchDriverHandle handle);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the coordinates for the currently touched points on the screen.
|
|
||||||
*
|
|
||||||
* @param[in] handle the touch driver handle
|
|
||||||
* @param[in] x array of X coordinates
|
|
||||||
* @param[in] y array of Y coordinates
|
|
||||||
* @param[in] strength array of strengths (with the minimum size of maxPointCount) or NULL
|
|
||||||
* @param[in] pointCount the number of points currently touched on the screen
|
|
||||||
* @param[in] maxPointCount the maximum number of points that can be touched at once
|
|
||||||
*
|
|
||||||
* @return true when touched and coordinates are available
|
|
||||||
*/
|
|
||||||
bool tt_hal_touch_driver_get_touched_points(TouchDriverHandle handle, uint16_t* x, uint16_t* y, uint16_t* strength, uint8_t* pointCount, uint8_t maxPointCount);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
@ -1,159 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <freertos/FreeRTOS.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
||||||
* WARNING: THIS API IS NON-FUNCTIONAL AND DEPRECATED.
|
|
||||||
* IT WILL BE REMOVED IN A FUTURE RELEASE ONCE OFFICIAL APPS ARE MIGRATED.
|
|
||||||
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @file tt_hal_uart.h
|
|
||||||
* @brief C HAL interface for UART devices used by Tactility C modules.
|
|
||||||
*
|
|
||||||
* This header exposes a minimal, C-compatible UART API that mirrors the higher-level
|
|
||||||
* C++ UART interface (see Tactility/hal/uart).
|
|
||||||
*
|
|
||||||
* General notes:
|
|
||||||
* - Start the UART before I/O using tt_hal_uart_start(); stop it with tt_hal_uart_stop().
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef void* UartHandle; /**< Opaque handle to an underlying UART instance. */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the number of UART devices available on this platform.
|
|
||||||
* @return Count of discoverable UARTs (0 if none).
|
|
||||||
*/
|
|
||||||
size_t tt_hal_uart_get_count();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the user-friendly name of a UART by index.
|
|
||||||
* @param index Zero-based UART index in the range [0, tt_hal_uart_get_count()).
|
|
||||||
* @param[out] name Destination buffer to receive a null-terminated name.
|
|
||||||
* @param nameSizeLimit Size in bytes of the destination buffer. The name will be
|
|
||||||
* truncated to fit and always null-terminated if the size
|
|
||||||
* is greater than 0.
|
|
||||||
* @return true if a name was written to the buffer; false if the index is out of range
|
|
||||||
* or on other failure.
|
|
||||||
*/
|
|
||||||
bool tt_hal_uart_get_name(size_t index, char* name, size_t nameSizeLimit);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Allocate an opaque UART handle by index.
|
|
||||||
*
|
|
||||||
* Allocation does not start the hardware; call tt_hal_uart_start() to begin I/O.
|
|
||||||
*
|
|
||||||
* @param index Zero-based UART index.
|
|
||||||
* @return A valid UartHandle on success; NULL on failure (e.g., invalid index or already in use).
|
|
||||||
*/
|
|
||||||
UartHandle tt_hal_uart_alloc(size_t index);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Release a previously allocated UART handle and any associated resources.
|
|
||||||
* @param handle Handle returned by tt_hal_uart_alloc()
|
|
||||||
*/
|
|
||||||
void tt_hal_uart_free(UartHandle handle);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Start the UART so it can perform I/O.
|
|
||||||
* @param handle A valid UART handle.
|
|
||||||
* @return true on success; false on failure.
|
|
||||||
*/
|
|
||||||
bool tt_hal_uart_start(UartHandle handle);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Query whether the UART has been started.
|
|
||||||
* @param handle A valid UART handle.
|
|
||||||
* @return true if started; false otherwise.
|
|
||||||
*/
|
|
||||||
bool tt_hal_uart_is_started(UartHandle handle);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Stop the UART
|
|
||||||
* @param handle A valid UART handle.
|
|
||||||
* @return true on success; false on failure.
|
|
||||||
*/
|
|
||||||
bool tt_hal_uart_stop(UartHandle handle);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Read up to bufferSize bytes into buffer.
|
|
||||||
*
|
|
||||||
* This call may block up to timeout ticks waiting for data. It returns the actual
|
|
||||||
* number of bytes placed into the buffer, which can be less than bufferSize if
|
|
||||||
* fewer bytes became available before the timeout expired.
|
|
||||||
*
|
|
||||||
* @param handle A valid UART handle.
|
|
||||||
* @param[out] buffer Destination buffer.
|
|
||||||
* @param bufferSize Capacity of the destination buffer in bytes.
|
|
||||||
* @param timeout Maximum time to wait in ticks. Use 0 for non-blocking; use TT_MAX_TICKS
|
|
||||||
* to wait indefinitely.
|
|
||||||
* @return The number of bytes read (0 on timeout with no data). Never exceeds bufferSize.
|
|
||||||
*/
|
|
||||||
size_t tt_hal_uart_read_bytes(UartHandle handle, char* buffer, size_t bufferSize, TickType_t timeout);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Read a single byte.
|
|
||||||
*
|
|
||||||
* @param handle A valid UART handle.
|
|
||||||
* @param[out] output Where to store the read byte.
|
|
||||||
* @param timeout Maximum time to wait in ticks. Use 0 for non-blocking; use TT_MAX_TICKS
|
|
||||||
* to wait indefinitely.
|
|
||||||
* @return true if a byte was read and stored in output; false on timeout or failure.
|
|
||||||
*/
|
|
||||||
bool tt_hal_uart_read_byte(UartHandle handle, char* output, TickType_t timeout);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Write up to bufferSize bytes from buffer.
|
|
||||||
*
|
|
||||||
* This call may block up to timeout ticks waiting for transmit queue space. It returns
|
|
||||||
* the number of bytes accepted for transmission.
|
|
||||||
*
|
|
||||||
* @param handle A valid UART handle.
|
|
||||||
* @param[in] buffer Source buffer containing bytes to write.
|
|
||||||
* @param bufferSize Number of bytes to write from buffer.
|
|
||||||
* @param timeout Maximum time to wait in ticks. Use 0 for non-blocking; use TT_MAX_TICKS
|
|
||||||
* to wait indefinitely.
|
|
||||||
* @return The number of bytes written (may be less than bufferSize on timeout).
|
|
||||||
*/
|
|
||||||
size_t tt_hal_uart_write_bytes(UartHandle handle, const char* buffer, size_t bufferSize, TickType_t timeout);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the number of bytes currently available to read without blocking.
|
|
||||||
* @param handle A valid UART handle.
|
|
||||||
* @return The count of bytes available in the receive buffer.
|
|
||||||
*/
|
|
||||||
size_t tt_hal_uart_available(UartHandle handle);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set the UART baud rate.
|
|
||||||
* @param handle A valid UART handle.
|
|
||||||
* @param baud_rate Desired baud rate in bits per second (e.g., 115200).
|
|
||||||
* @return true on success; false if the rate is unsupported or on error.
|
|
||||||
*/
|
|
||||||
bool tt_hal_uart_set_baud_rate(UartHandle handle, size_t baud_rate);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the current UART baud rate.
|
|
||||||
* @param handle A valid UART handle.
|
|
||||||
* @return The configured baud rate in bits per second.
|
|
||||||
*/
|
|
||||||
uint32_t tt_hal_uart_get_baud_rate(UartHandle handle);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Flush the UART input (receive) buffer, discarding any unread data.
|
|
||||||
* @param handle A valid UART handle.
|
|
||||||
*/
|
|
||||||
void tt_hal_uart_flush_input(UartHandle handle);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
@ -1,29 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <freertos/FreeRTOS.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define TT_LVGL_DEFAULT_LOCK_TIME 500 // 500 ticks = 500 ms
|
|
||||||
|
|
||||||
/** @return true if LVGL is started and active */
|
|
||||||
bool tt_lvgl_is_started();
|
|
||||||
|
|
||||||
/** Start LVGL and related background services */
|
|
||||||
void tt_lvgl_start();
|
|
||||||
|
|
||||||
/** Stop LVGL and related background services */
|
|
||||||
void tt_lvgl_stop();
|
|
||||||
|
|
||||||
/** Lock the LVGL context. Call this before doing LVGL-related operations from a non-LVLG thread */
|
|
||||||
bool tt_lvgl_lock(TickType_t timeout);
|
|
||||||
|
|
||||||
/** Unlock the LVGL context */
|
|
||||||
void tt_lvgl_unlock();
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
@ -1,45 +0,0 @@
|
|||||||
#include "tt_gps.h"
|
|
||||||
#include <Tactility/service/gps/GpsService.h>
|
|
||||||
|
|
||||||
using namespace tt::service;
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
|
|
||||||
bool tt_gps_has_coordinates() {
|
|
||||||
auto service = gps::findGpsService();
|
|
||||||
return service != nullptr && service->hasCoordinates();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool tt_gps_get_coordinates(
|
|
||||||
float* longitude,
|
|
||||||
float* latitude,
|
|
||||||
float* speed,
|
|
||||||
float* course,
|
|
||||||
int* day,
|
|
||||||
int* month,
|
|
||||||
int* year
|
|
||||||
) {
|
|
||||||
auto service = gps::findGpsService();
|
|
||||||
|
|
||||||
if (service == nullptr) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
minmea_sentence_rmc rmc;
|
|
||||||
|
|
||||||
if (!service->getCoordinates(rmc)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
*longitude = minmea_tocoord(&rmc.longitude);
|
|
||||||
*latitude = minmea_tocoord(&rmc.latitude);
|
|
||||||
*speed = minmea_tocoord(&rmc.speed);
|
|
||||||
*course = minmea_tocoord(&rmc.course);
|
|
||||||
*day = rmc.date.day;
|
|
||||||
*month = rmc.date.month;
|
|
||||||
*year = rmc.date.year;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,48 +0,0 @@
|
|||||||
#include "tt_hal_device.h"
|
|
||||||
|
|
||||||
#include <tactility/check.h>
|
|
||||||
|
|
||||||
#include <tactility/hal/Device.h>
|
|
||||||
|
|
||||||
static tt::hal::Device::Type toTactilityDeviceType(TtDeviceType type) {
|
|
||||||
switch (type) {
|
|
||||||
case DEVICE_TYPE_I2C:
|
|
||||||
return tt::hal::Device::Type::I2c;
|
|
||||||
case DEVICE_TYPE_DISPLAY:
|
|
||||||
return tt::hal::Device::Type::Display;
|
|
||||||
case DEVICE_TYPE_TOUCH:
|
|
||||||
return tt::hal::Device::Type::Touch;
|
|
||||||
case DEVICE_TYPE_SDCARD:
|
|
||||||
return tt::hal::Device::Type::SdCard;
|
|
||||||
case DEVICE_TYPE_KEYBOARD:
|
|
||||||
return tt::hal::Device::Type::Keyboard;
|
|
||||||
case DEVICE_TYPE_POWER:
|
|
||||||
return tt::hal::Device::Type::Power;
|
|
||||||
case DEVICE_TYPE_GPS:
|
|
||||||
return tt::hal::Device::Type::Gps;
|
|
||||||
default:
|
|
||||||
check(false, "Device::Type not supported");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
|
|
||||||
bool tt_hal_device_find(TtDeviceType type, DeviceId* deviceIds, uint16_t* count, uint16_t maxCount) {
|
|
||||||
assert(maxCount > 0);
|
|
||||||
|
|
||||||
int16_t currentIndex = -1;
|
|
||||||
uint16_t maxIndex = maxCount - 1;
|
|
||||||
|
|
||||||
findDevices<tt::hal::Device>(toTactilityDeviceType(type), [&](const auto& device) {
|
|
||||||
currentIndex++;
|
|
||||||
deviceIds[currentIndex] = device->getId();
|
|
||||||
// Continue if there is storage capacity left
|
|
||||||
return currentIndex < maxIndex;
|
|
||||||
});
|
|
||||||
|
|
||||||
*count = currentIndex + 1;
|
|
||||||
|
|
||||||
return currentIndex >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,93 +0,0 @@
|
|||||||
#include "tt_hal_display.h"
|
|
||||||
|
|
||||||
#include <tactility/check.h>
|
|
||||||
|
|
||||||
#include <tactility/hal/Device.h>
|
|
||||||
#include <Tactility/hal/display/DisplayDevice.h>
|
|
||||||
#include <Tactility/hal/display/DisplayDriver.h>
|
|
||||||
|
|
||||||
static ColorFormat toColorFormat(tt::hal::display::ColorFormat format) {
|
|
||||||
switch (format) {
|
|
||||||
case tt::hal::display::ColorFormat::Monochrome:
|
|
||||||
return COLOR_FORMAT_MONOCHROME;
|
|
||||||
case tt::hal::display::ColorFormat::BGR565:
|
|
||||||
return COLOR_FORMAT_BGR565;
|
|
||||||
case tt::hal::display::ColorFormat::BGR565Swapped:
|
|
||||||
return COLOR_FORMAT_BGR565_SWAPPED;
|
|
||||||
case tt::hal::display::ColorFormat::RGB565:
|
|
||||||
return COLOR_FORMAT_RGB565;
|
|
||||||
case tt::hal::display::ColorFormat::RGB565Swapped:
|
|
||||||
return COLOR_FORMAT_RGB565_SWAPPED;
|
|
||||||
case tt::hal::display::ColorFormat::RGB888:
|
|
||||||
return COLOR_FORMAT_RGB888;
|
|
||||||
default:
|
|
||||||
check(false, "ColorFormat not supported");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct DriverWrapper {
|
|
||||||
std::shared_ptr<tt::hal::display::DisplayDriver> driver;
|
|
||||||
DriverWrapper(std::shared_ptr<tt::hal::display::DisplayDriver> driver) : driver(driver) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
static std::shared_ptr<tt::hal::display::DisplayDevice> findValidDisplayDevice(tt::hal::Device::Id id) {
|
|
||||||
auto device = tt::hal::findDevice(id);
|
|
||||||
if (device == nullptr || device->getType() != tt::hal::Device::Type::Display) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return std::reinterpret_pointer_cast<tt::hal::display::DisplayDevice>(device);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
|
|
||||||
bool tt_hal_display_driver_supported(DeviceId id) {
|
|
||||||
auto display = findValidDisplayDevice(id);
|
|
||||||
return display != nullptr && display->supportsDisplayDriver();
|
|
||||||
}
|
|
||||||
|
|
||||||
DisplayDriverHandle tt_hal_display_driver_alloc(DeviceId id) {
|
|
||||||
auto display = findValidDisplayDevice(id);
|
|
||||||
assert(display->supportsDisplayDriver());
|
|
||||||
return new DriverWrapper(display->getDisplayDriver());
|
|
||||||
}
|
|
||||||
|
|
||||||
void tt_hal_display_driver_free(DisplayDriverHandle handle) {
|
|
||||||
auto wrapper = static_cast<DriverWrapper*>(handle);
|
|
||||||
delete wrapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool tt_hal_display_driver_lock(DisplayDriverHandle handle, TickType_t timeout) {
|
|
||||||
// TODO: re-implement with SPI lock
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void tt_hal_display_driver_unlock(DisplayDriverHandle handle) {
|
|
||||||
// TODO: re-implement with SPI lock
|
|
||||||
}
|
|
||||||
|
|
||||||
ColorFormat tt_hal_display_driver_get_colorformat(DisplayDriverHandle handle) {
|
|
||||||
auto wrapper = static_cast<DriverWrapper*>(handle);
|
|
||||||
return toColorFormat(wrapper->driver->getColorFormat());
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t tt_hal_display_driver_get_pixel_width(DisplayDriverHandle handle) {
|
|
||||||
auto wrapper = static_cast<DriverWrapper*>(handle);
|
|
||||||
return wrapper->driver->getPixelWidth();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t tt_hal_display_driver_get_pixel_height(DisplayDriverHandle handle) {
|
|
||||||
auto wrapper = static_cast<DriverWrapper*>(handle);
|
|
||||||
return wrapper->driver->getPixelHeight();
|
|
||||||
}
|
|
||||||
|
|
||||||
void tt_hal_display_driver_draw_bitmap(DisplayDriverHandle handle, int xStart, int yStart, int xEnd, int yEnd, const void* pixelData) {
|
|
||||||
auto wrapper = static_cast<DriverWrapper*>(handle);
|
|
||||||
wrapper->driver->drawBitmap(xStart, yStart, xEnd, yEnd, pixelData);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t tt_hal_display_driver_get_frame_buffers(DisplayDriverHandle handle, void* outBuffers[2]) {
|
|
||||||
auto wrapper = static_cast<DriverWrapper*>(handle);
|
|
||||||
return wrapper->driver->getFrameBuffers(outBuffers);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,43 +0,0 @@
|
|||||||
#include "tt_hal_touch.h"
|
|
||||||
|
|
||||||
#include <tactility/hal/Device.h>
|
|
||||||
#include "Tactility/hal/touch/TouchDevice.h"
|
|
||||||
#include "Tactility/hal/touch/TouchDriver.h"
|
|
||||||
|
|
||||||
struct DriverWrapper {
|
|
||||||
std::shared_ptr<tt::hal::touch::TouchDriver> driver;
|
|
||||||
DriverWrapper(std::shared_ptr<tt::hal::touch::TouchDriver> driver) : driver(driver) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
static std::shared_ptr<tt::hal::touch::TouchDevice> findValidTouchDevice(tt::hal::Device::Id id) {
|
|
||||||
auto device = tt::hal::findDevice(id);
|
|
||||||
if (device == nullptr || device->getType() != tt::hal::Device::Type::Touch) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return std::reinterpret_pointer_cast<tt::hal::touch::TouchDevice>(device);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
|
|
||||||
bool tt_hal_touch_driver_supported(DeviceId id) {
|
|
||||||
auto touch = findValidTouchDevice(id);
|
|
||||||
return touch != nullptr && touch->supportsTouchDriver();
|
|
||||||
}
|
|
||||||
|
|
||||||
TouchDriverHandle tt_hal_touch_driver_alloc(DeviceId id) {
|
|
||||||
auto touch = findValidTouchDevice(id);
|
|
||||||
assert(touch->supportsTouchDriver());
|
|
||||||
return new DriverWrapper(touch->getTouchDriver());
|
|
||||||
}
|
|
||||||
|
|
||||||
void tt_hal_touch_driver_free(TouchDriverHandle handle) {
|
|
||||||
DriverWrapper* wrapper = static_cast<DriverWrapper*>(handle);
|
|
||||||
delete wrapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool tt_hal_touch_driver_get_touched_points(TouchDriverHandle handle, uint16_t* x, uint16_t* y, uint16_t* strength, uint8_t* pointCount, uint8_t maxPointCount) {
|
|
||||||
DriverWrapper* wrapper = static_cast<DriverWrapper*>(handle);
|
|
||||||
return wrapper->driver->getTouchedPoints(x, y, strength, pointCount, maxPointCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,61 +0,0 @@
|
|||||||
#include "tt_hal_uart.h"
|
|
||||||
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
|
|
||||||
size_t tt_hal_uart_get_count() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool tt_hal_uart_get_name(size_t index, char* name, size_t nameSizeLimit) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
UartHandle tt_hal_uart_alloc(size_t index) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void tt_hal_uart_free(UartHandle handle) {
|
|
||||||
}
|
|
||||||
|
|
||||||
bool tt_hal_uart_start(UartHandle handle) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool tt_hal_uart_is_started(UartHandle handle) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool tt_hal_uart_stop(UartHandle handle) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t tt_hal_uart_read_bytes(UartHandle handle, char* buffer, size_t bufferSize, TickType_t timeout) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool tt_hal_uart_read_byte(UartHandle handle, char* output, TickType_t timeout) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t tt_hal_uart_write_bytes(UartHandle handle, const char* buffer, size_t bufferSize, TickType_t timeout) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t tt_hal_uart_available(UartHandle handle) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool tt_hal_uart_set_baud_rate(UartHandle handle, size_t baud_rate) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t tt_hal_uart_get_baud_rate(UartHandle handle) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void tt_hal_uart_flush_input(UartHandle handle) {
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -5,13 +5,7 @@
|
|||||||
#include "tt_app_fileselection.h"
|
#include "tt_app_fileselection.h"
|
||||||
#include "tt_app_selectiondialog.h"
|
#include "tt_app_selectiondialog.h"
|
||||||
#include "tt_bundle.h"
|
#include "tt_bundle.h"
|
||||||
#include "tt_gps.h"
|
|
||||||
#include "tt_hal_device.h"
|
|
||||||
#include "tt_hal_display.h"
|
|
||||||
#include "tt_hal_touch.h"
|
|
||||||
#include "tt_hal_uart.h"
|
|
||||||
#include <tt_lock.h>
|
#include <tt_lock.h>
|
||||||
#include "tt_lvgl.h"
|
|
||||||
#include "tt_lvgl_keyboard.h"
|
#include "tt_lvgl_keyboard.h"
|
||||||
#include "tt_lvgl_spinner.h"
|
#include "tt_lvgl_spinner.h"
|
||||||
#include "tt_lvgl_toolbar.h"
|
#include "tt_lvgl_toolbar.h"
|
||||||
@ -299,42 +293,6 @@ const esp_elfsym main_symbols[] {
|
|||||||
ESP_ELFSYM_EXPORT(tt_bundle_put_bool),
|
ESP_ELFSYM_EXPORT(tt_bundle_put_bool),
|
||||||
ESP_ELFSYM_EXPORT(tt_bundle_put_int32),
|
ESP_ELFSYM_EXPORT(tt_bundle_put_int32),
|
||||||
ESP_ELFSYM_EXPORT(tt_bundle_put_string),
|
ESP_ELFSYM_EXPORT(tt_bundle_put_string),
|
||||||
ESP_ELFSYM_EXPORT(tt_gps_has_coordinates),
|
|
||||||
ESP_ELFSYM_EXPORT(tt_gps_get_coordinates),
|
|
||||||
ESP_ELFSYM_EXPORT(tt_hal_device_find),
|
|
||||||
ESP_ELFSYM_EXPORT(tt_hal_display_driver_alloc),
|
|
||||||
ESP_ELFSYM_EXPORT(tt_hal_display_driver_draw_bitmap),
|
|
||||||
ESP_ELFSYM_EXPORT(tt_hal_display_driver_free),
|
|
||||||
ESP_ELFSYM_EXPORT(tt_hal_display_driver_get_colorformat),
|
|
||||||
ESP_ELFSYM_EXPORT(tt_hal_display_driver_get_pixel_height),
|
|
||||||
ESP_ELFSYM_EXPORT(tt_hal_display_driver_get_pixel_width),
|
|
||||||
ESP_ELFSYM_EXPORT(tt_hal_display_driver_lock),
|
|
||||||
ESP_ELFSYM_EXPORT(tt_hal_display_driver_unlock),
|
|
||||||
ESP_ELFSYM_EXPORT(tt_hal_display_driver_supported),
|
|
||||||
ESP_ELFSYM_EXPORT(tt_hal_display_driver_get_frame_buffers),
|
|
||||||
ESP_ELFSYM_EXPORT(tt_hal_touch_driver_supported),
|
|
||||||
ESP_ELFSYM_EXPORT(tt_hal_touch_driver_alloc),
|
|
||||||
ESP_ELFSYM_EXPORT(tt_hal_touch_driver_free),
|
|
||||||
ESP_ELFSYM_EXPORT(tt_hal_touch_driver_get_touched_points),
|
|
||||||
ESP_ELFSYM_EXPORT(tt_hal_uart_get_count),
|
|
||||||
ESP_ELFSYM_EXPORT(tt_hal_uart_get_name),
|
|
||||||
ESP_ELFSYM_EXPORT(tt_hal_uart_alloc),
|
|
||||||
ESP_ELFSYM_EXPORT(tt_hal_uart_free),
|
|
||||||
ESP_ELFSYM_EXPORT(tt_hal_uart_start),
|
|
||||||
ESP_ELFSYM_EXPORT(tt_hal_uart_is_started),
|
|
||||||
ESP_ELFSYM_EXPORT(tt_hal_uart_stop),
|
|
||||||
ESP_ELFSYM_EXPORT(tt_hal_uart_read_bytes),
|
|
||||||
ESP_ELFSYM_EXPORT(tt_hal_uart_read_byte),
|
|
||||||
ESP_ELFSYM_EXPORT(tt_hal_uart_write_bytes),
|
|
||||||
ESP_ELFSYM_EXPORT(tt_hal_uart_available),
|
|
||||||
ESP_ELFSYM_EXPORT(tt_hal_uart_set_baud_rate),
|
|
||||||
ESP_ELFSYM_EXPORT(tt_hal_uart_get_baud_rate),
|
|
||||||
ESP_ELFSYM_EXPORT(tt_hal_uart_flush_input),
|
|
||||||
ESP_ELFSYM_EXPORT(tt_lvgl_is_started),
|
|
||||||
ESP_ELFSYM_EXPORT(tt_lvgl_lock),
|
|
||||||
ESP_ELFSYM_EXPORT(tt_lvgl_unlock),
|
|
||||||
ESP_ELFSYM_EXPORT(tt_lvgl_start),
|
|
||||||
ESP_ELFSYM_EXPORT(tt_lvgl_stop),
|
|
||||||
ESP_ELFSYM_EXPORT(tt_lvgl_software_keyboard_show),
|
ESP_ELFSYM_EXPORT(tt_lvgl_software_keyboard_show),
|
||||||
ESP_ELFSYM_EXPORT(tt_lvgl_software_keyboard_hide),
|
ESP_ELFSYM_EXPORT(tt_lvgl_software_keyboard_hide),
|
||||||
ESP_ELFSYM_EXPORT(tt_lvgl_software_keyboard_is_enabled),
|
ESP_ELFSYM_EXPORT(tt_lvgl_software_keyboard_is_enabled),
|
||||||
|
|||||||
@ -1,26 +0,0 @@
|
|||||||
#include <Tactility/lvgl/Lvgl.h>
|
|
||||||
#include <Tactility/lvgl/LvglSync.h>
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
|
|
||||||
bool tt_lvgl_is_started() {
|
|
||||||
return tt::lvgl::isStarted();
|
|
||||||
}
|
|
||||||
|
|
||||||
void tt_lvgl_start() {
|
|
||||||
tt::lvgl::start();
|
|
||||||
}
|
|
||||||
|
|
||||||
void tt_lvgl_stop() {
|
|
||||||
tt::lvgl::stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool tt_lvgl_lock(TickType_t timeout) {
|
|
||||||
return tt::lvgl::getSyncLock()->lock(timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
void tt_lvgl_unlock() {
|
|
||||||
tt::lvgl::getSyncLock()->unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -392,6 +392,15 @@ error_t device_get_first_by_type(const struct DeviceType* type, struct Device**
|
|||||||
*/
|
*/
|
||||||
error_t device_get_first_active_by_type(const struct DeviceType* type, struct Device** out_device);
|
error_t device_get_first_active_by_type(const struct DeviceType* type, struct Device** out_device);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if there is an active device of the provided type.
|
||||||
|
*
|
||||||
|
* @param[in] type non-null device type pointer
|
||||||
|
* @retval ERROR_NOT_FOUND if no started device of that type exists
|
||||||
|
* @retval ERROR_NONE on success; caller must call device_put(*out_device) exactly once
|
||||||
|
*/
|
||||||
|
bool device_has_active_by_type(const struct DeviceType* type);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the first device whose driver matches the given compatible string and atomically take a
|
* Find the first device whose driver matches the given compatible string and atomically take a
|
||||||
* reference on it. See device_get_by_name() for why this is preferred over
|
* reference on it. See device_get_by_name() for why this is preferred over
|
||||||
|
|||||||
@ -37,6 +37,15 @@ struct KeyboardApi {
|
|||||||
* @retval ERROR_NONE when the operation was successful
|
* @retval ERROR_NONE when the operation was successful
|
||||||
*/
|
*/
|
||||||
error_t (*read_key)(struct Device* device, struct KeyboardKeyData* data);
|
error_t (*read_key)(struct Device* device, struct KeyboardKeyData* data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the baclight if the keyboard has one.
|
||||||
|
* @param[in] device the keyboard device
|
||||||
|
* @param[out] backlight_device the output backlight device
|
||||||
|
* @retval ERROR_NONE when the backlight_device was set
|
||||||
|
* @retval ERROR_NOT_SUPPORTED when this device has no backlight
|
||||||
|
*/
|
||||||
|
error_t (*get_backlight)(struct Device* device, struct Device** backlight_device);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -44,6 +53,16 @@ struct KeyboardApi {
|
|||||||
*/
|
*/
|
||||||
error_t keyboard_read_key(struct Device* device, struct KeyboardKeyData* data);
|
error_t keyboard_read_key(struct Device* device, struct KeyboardKeyData* data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the backlight if the keyboard has one.
|
||||||
|
* @param[in] device the keyboard device
|
||||||
|
* @param[out] backlight_device the output backlight device
|
||||||
|
* @retval ERROR_NONE when the backlight_device was set
|
||||||
|
* @retval ERROR_NOT_SUPPORTED when this device has no backlight
|
||||||
|
*/
|
||||||
|
error_t keyboard_get_backlight(struct Device* device, struct Device** backlight_device);
|
||||||
|
|
||||||
|
|
||||||
extern const struct DeviceType KEYBOARD_TYPE;
|
extern const struct DeviceType KEYBOARD_TYPE;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@ -585,6 +585,20 @@ error_t device_get_first_active_by_type(const DeviceType* type, Device** out_dev
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool device_has_active_by_type(const struct DeviceType* type) {
|
||||||
|
ledger_lock();
|
||||||
|
bool found = false;
|
||||||
|
for (auto* device : ledger.devices) {
|
||||||
|
auto* driver = device->internal->driver;
|
||||||
|
if (driver != nullptr && driver->device_type == type && device->internal->state.started) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ledger_unlock();
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
error_t device_get_first_by_compatible(const char* compatible, Device** out_device) {
|
error_t device_get_first_by_compatible(const char* compatible, Device** out_device) {
|
||||||
ledger_lock();
|
ledger_lock();
|
||||||
Device* found = nullptr;
|
Device* found = nullptr;
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
#include <tactility/drivers/keyboard.h>
|
#include <tactility/drivers/keyboard.h>
|
||||||
|
#include <tactility/error.h>
|
||||||
#include <tactility/device.h>
|
#include <tactility/device.h>
|
||||||
|
|
||||||
#define KEYBOARD_DRIVER_API(driver) ((struct KeyboardApi*)driver->api)
|
#define KEYBOARD_DRIVER_API(driver) ((struct KeyboardApi*)driver->api)
|
||||||
@ -11,6 +12,16 @@ error_t keyboard_read_key(Device* device, KeyboardKeyData* data) {
|
|||||||
return KEYBOARD_DRIVER_API(driver)->read_key(device, data);
|
return KEYBOARD_DRIVER_API(driver)->read_key(device, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
error_t keyboard_get_backlight(Device* device, Device** backlight_device) {
|
||||||
|
const auto* driver = device_get_driver(device);
|
||||||
|
|
||||||
|
if (KEYBOARD_DRIVER_API(driver)->get_backlight == nullptr) {
|
||||||
|
return ERROR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return KEYBOARD_DRIVER_API(driver)->get_backlight(device, backlight_device);
|
||||||
|
}
|
||||||
|
|
||||||
const DeviceType KEYBOARD_TYPE {
|
const DeviceType KEYBOARD_TYPE {
|
||||||
.name = "keyboard"
|
.name = "keyboard"
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user