parent
db2e29a72d
commit
6fd588e970
@ -0,0 +1,44 @@ |
||||
/*
|
||||
* Copyright 2023 jacqueline <me@jacqueline.id.au> |
||||
* |
||||
* SPDX-License-Identifier: GPL-3.0-only |
||||
*/ |
||||
|
||||
#pragma once |
||||
|
||||
#include <stdint.h> |
||||
#include <cstdint> |
||||
#include <functional> |
||||
|
||||
#include "esp_err.h" |
||||
#include "result.hpp" |
||||
|
||||
#include "gpio_expander.hpp" |
||||
#include "touchwheel.hpp" |
||||
|
||||
namespace drivers { |
||||
|
||||
class RelativeWheel { |
||||
public: |
||||
static auto Create(TouchWheel *touch) -> RelativeWheel* { return new RelativeWheel(touch); } |
||||
|
||||
explicit RelativeWheel(TouchWheel *touch); |
||||
|
||||
// Not copyable or movable.
|
||||
RelativeWheel(const RelativeWheel&) = delete; |
||||
RelativeWheel& operator=(const RelativeWheel&) = delete; |
||||
|
||||
auto Update() -> void; |
||||
|
||||
auto is_pressed() -> bool; |
||||
auto ticks() -> std::int_fast16_t; |
||||
|
||||
private: |
||||
TouchWheel *touch_; |
||||
bool is_pressed_; |
||||
bool is_first_read_; |
||||
std::int_fast16_t ticks_; |
||||
uint8_t last_angle_; |
||||
}; |
||||
|
||||
} // namespace drivers
|
@ -0,0 +1,78 @@ |
||||
/*
|
||||
* Copyright 2023 jacqueline <me@jacqueline.id.au> |
||||
* |
||||
* SPDX-License-Identifier: GPL-3.0-only |
||||
*/ |
||||
|
||||
#include "relative_wheel.hpp" |
||||
|
||||
#include <stdint.h> |
||||
#include <cstdint> |
||||
|
||||
#include "esp_log.h" |
||||
|
||||
namespace drivers { |
||||
|
||||
RelativeWheel::RelativeWheel(TouchWheel *touch)
|
||||
:touch_(touch), |
||||
is_pressed_(false), |
||||
is_first_read_(true), |
||||
ticks_(0), |
||||
last_angle_(0) {} |
||||
|
||||
auto RelativeWheel::Update() -> void { |
||||
touch_->Update(); |
||||
TouchWheelData d = touch_->GetTouchWheelData(); |
||||
is_pressed_ = d.is_touched; |
||||
|
||||
uint8_t new_angle = d.wheel_position; |
||||
if (is_first_read_) { |
||||
is_first_read_ = false; |
||||
last_angle_ = new_angle; |
||||
return; |
||||
} |
||||
|
||||
// Work out the magnitude of travel.
|
||||
uint8_t change_cw = last_angle_ - new_angle; |
||||
uint8_t change_ccw = new_angle - last_angle_; |
||||
int change = std::min(change_cw, change_ccw); |
||||
|
||||
last_angle_ = new_angle; |
||||
|
||||
// Round to eliminate noise.
|
||||
if (change <= 2) { |
||||
ticks_ = 0; |
||||
return; |
||||
} |
||||
|
||||
// Quantize into ticks.
|
||||
change /= 4; |
||||
|
||||
// Clamp to reliminate more noise.
|
||||
if (change > 10) { |
||||
change = 0; |
||||
} |
||||
|
||||
// Work out the direction of travel.
|
||||
if (change_cw > change_ccw) { |
||||
change *= -1; |
||||
} |
||||
|
||||
ticks_ = change; |
||||
} |
||||
|
||||
auto RelativeWheel::is_pressed() -> bool { |
||||
return is_pressed_; |
||||
} |
||||
|
||||
auto RelativeWheel::ticks() -> std::int_fast16_t { |
||||
int_fast16_t t = ticks_; |
||||
if (t != 0) { |
||||
ESP_LOGI("teeks", "ticks %d", t); |
||||
} |
||||
ticks_ = 0; |
||||
return t; |
||||
} |
||||
|
||||
|
||||
} // namespace drivers
|
@ -0,0 +1,28 @@ |
||||
/*
|
||||
* Copyright 2023 jacqueline <me@jacqueline.id.au> |
||||
* |
||||
* SPDX-License-Identifier: GPL-3.0-only |
||||
*/ |
||||
|
||||
#pragma once |
||||
|
||||
#include <memory> |
||||
|
||||
#include "core/lv_obj.h" |
||||
#include "core/lv_obj_tree.h" |
||||
#include "lvgl.h" |
||||
|
||||
namespace ui { |
||||
|
||||
class Screen { |
||||
public: |
||||
Screen() : root_(lv_obj_create(NULL)) {} |
||||
virtual ~Screen() { lv_obj_del(root_); } |
||||
|
||||
auto root() -> lv_obj_t* { return root_; } |
||||
|
||||
protected: |
||||
lv_obj_t* const root_; |
||||
}; |
||||
|
||||
} // namespace ui
|
@ -0,0 +1,29 @@ |
||||
/*
|
||||
* Copyright 2023 jacqueline <me@jacqueline.id.au> |
||||
* |
||||
* SPDX-License-Identifier: GPL-3.0-only |
||||
*/ |
||||
|
||||
#pragma once |
||||
|
||||
#include <memory> |
||||
|
||||
#include "lvgl.h" |
||||
|
||||
#include "screen.hpp" |
||||
|
||||
namespace ui { |
||||
namespace screens { |
||||
|
||||
class Menu : public Screen { |
||||
public: |
||||
Menu(); |
||||
~Menu(); |
||||
|
||||
private: |
||||
lv_obj_t* container_; |
||||
lv_obj_t* label_; |
||||
}; |
||||
|
||||
} // namespace screens
|
||||
} // namespace ui
|
@ -0,0 +1,30 @@ |
||||
/*
|
||||
* Copyright 2023 jacqueline <me@jacqueline.id.au> |
||||
* |
||||
* SPDX-License-Identifier: GPL-3.0-only |
||||
*/ |
||||
|
||||
#pragma once |
||||
|
||||
#include <memory> |
||||
|
||||
#include "lvgl.h" |
||||
|
||||
#include "screen.hpp" |
||||
|
||||
namespace ui { |
||||
namespace screens { |
||||
|
||||
class Splash : public Screen { |
||||
public: |
||||
Splash(); |
||||
~Splash(); |
||||
|
||||
private: |
||||
lv_obj_t* container_; |
||||
lv_obj_t* label_; |
||||
lv_obj_t* spinner_; |
||||
}; |
||||
|
||||
} // namespace screens
|
||||
} // namespace ui
|
@ -0,0 +1,11 @@ |
||||
/*
|
||||
* Copyright 2023 jacqueline <me@jacqueline.id.au> |
||||
* |
||||
* SPDX-License-Identifier: GPL-3.0-only |
||||
*/ |
||||
|
||||
#pragma once |
||||
|
||||
#include "esp_timer.h" |
||||
|
||||
#define LV_TICK_CUSTOM_SYS_TIME_EXPR (esp_timer_get_time() / 1000) |
@ -0,0 +1,30 @@ |
||||
/*
|
||||
* Copyright 2023 jacqueline <me@jacqueline.id.au> |
||||
* |
||||
* SPDX-License-Identifier: GPL-3.0-only |
||||
*/ |
||||
|
||||
#pragma once |
||||
|
||||
#include <memory> |
||||
|
||||
#include "hal/lv_hal_indev.h" |
||||
|
||||
#include "relative_wheel.hpp" |
||||
|
||||
namespace ui { |
||||
|
||||
class TouchWheelEncoder { |
||||
public: |
||||
explicit TouchWheelEncoder(std::weak_ptr<drivers::RelativeWheel> wheel); |
||||
|
||||
auto Read(lv_indev_data_t *data) -> void; |
||||
auto registration() -> lv_indev_t* { return registration_; } |
||||
|
||||
private: |
||||
lv_indev_drv_t driver_; |
||||
lv_indev_t *registration_; |
||||
std::weak_ptr<drivers::RelativeWheel> wheel_; |
||||
}; |
||||
|
||||
} // namespace ui
|
@ -0,0 +1,52 @@ |
||||
/*
|
||||
* Copyright 2023 jacqueline <me@jacqueline.id.au> |
||||
* |
||||
* SPDX-License-Identifier: GPL-3.0-only |
||||
*/ |
||||
|
||||
#include "screen_menu.hpp" |
||||
|
||||
#include "core/lv_group.h" |
||||
#include "core/lv_obj_pos.h" |
||||
#include "extra/widgets/menu/lv_menu.h" |
||||
#include "extra/widgets/spinner/lv_spinner.h" |
||||
#include "hal/lv_hal_disp.h" |
||||
#include "misc/lv_area.h" |
||||
#include "widgets/lv_label.h" |
||||
|
||||
namespace ui { |
||||
namespace screens { |
||||
|
||||
Menu::Menu() { |
||||
lv_obj_t *menu = lv_menu_create(root_); |
||||
lv_obj_set_size(menu, lv_disp_get_hor_res(NULL), lv_disp_get_ver_res(NULL)); |
||||
lv_obj_center(menu); |
||||
|
||||
lv_obj_t *main_page = lv_menu_page_create(menu, NULL); |
||||
|
||||
lv_obj_t *container; |
||||
lv_obj_t *label; |
||||
|
||||
container = lv_menu_cont_create(main_page); |
||||
label = lv_label_create(container); |
||||
lv_label_set_text(label, "I am an item"); |
||||
|
||||
container = lv_menu_cont_create(main_page); |
||||
label = lv_label_create(container); |
||||
lv_label_set_text(label, "I am also an item"); |
||||
|
||||
container = lv_menu_cont_create(main_page); |
||||
label = lv_label_create(container); |
||||
lv_label_set_text(label, "Item #3"); |
||||
|
||||
container = lv_menu_cont_create(main_page); |
||||
label = lv_label_create(container); |
||||
lv_label_set_text(label, "Yay!"); |
||||
|
||||
lv_menu_set_page(menu, main_page); |
||||
} |
||||
|
||||
Menu::~Menu() {} |
||||
|
||||
} // namespace screens
|
||||
} // namespace ui
|
@ -0,0 +1,38 @@ |
||||
/*
|
||||
* Copyright 2023 jacqueline <me@jacqueline.id.au> |
||||
* |
||||
* SPDX-License-Identifier: GPL-3.0-only |
||||
*/ |
||||
|
||||
#include "screen_splash.hpp" |
||||
|
||||
#include "core/lv_obj_pos.h" |
||||
#include "extra/widgets/spinner/lv_spinner.h" |
||||
#include "misc/lv_area.h" |
||||
#include "widgets/lv_label.h" |
||||
|
||||
namespace ui { |
||||
namespace screens { |
||||
|
||||
Splash::Splash() { |
||||
container_ = lv_obj_create(root_); |
||||
lv_obj_set_align(container_, LV_ALIGN_CENTER); |
||||
lv_obj_set_size(container_, LV_SIZE_CONTENT, LV_SIZE_CONTENT); |
||||
|
||||
label_ = lv_label_create(container_); |
||||
lv_label_set_text_static(label_, "TANGARA"); |
||||
lv_obj_set_align(label_, LV_ALIGN_TOP_MID); |
||||
|
||||
spinner_ = lv_spinner_create(container_, 1000, 60); |
||||
lv_obj_set_size(spinner_, 32, 32); |
||||
lv_obj_align_to(spinner_, label_, LV_ALIGN_OUT_BOTTOM_MID, 0, 8); |
||||
} |
||||
|
||||
Splash::~Splash() { |
||||
lv_obj_del(spinner_); |
||||
lv_obj_del(label_); |
||||
lv_obj_del(container_); |
||||
} |
||||
|
||||
} // namespace screens
|
||||
} // namespace ui
|
@ -0,0 +1,39 @@ |
||||
/*
|
||||
* Copyright 2023 jacqueline <me@jacqueline.id.au> |
||||
* |
||||
* SPDX-License-Identifier: GPL-3.0-only |
||||
*/ |
||||
|
||||
#include "wheel_encoder.hpp" |
||||
#include "hal/lv_hal_indev.h" |
||||
|
||||
namespace ui { |
||||
|
||||
void encoder_read(lv_indev_drv_t * drv, lv_indev_data_t*data){ |
||||
TouchWheelEncoder *instance = reinterpret_cast<TouchWheelEncoder*>(drv->user_data); |
||||
instance->Read(data); |
||||
} |
||||
|
||||
TouchWheelEncoder::TouchWheelEncoder(std::weak_ptr<drivers::RelativeWheel> wheel) : wheel_(wheel) { |
||||
lv_indev_drv_init(&driver_); |
||||
driver_.type = LV_INDEV_TYPE_ENCODER; |
||||
driver_.read_cb = encoder_read; |
||||
driver_.user_data = this; |
||||
|
||||
registration_ = lv_indev_drv_register(&driver_); |
||||
} |
||||
|
||||
auto TouchWheelEncoder::Read(lv_indev_data_t *data) -> void { |
||||
auto lock = wheel_.lock(); |
||||
if (lock == nullptr) { |
||||
data->state = LV_INDEV_STATE_RELEASED; |
||||
data->enc_diff = 0; |
||||
return; |
||||
} |
||||
|
||||
lock->Update(); |
||||
data->state = lock->is_pressed() ? LV_INDEV_STATE_PRESSED : LV_INDEV_STATE_RELEASED; |
||||
data->enc_diff = lock->ticks(); |
||||
} |
||||
|
||||
} // namespace ui
|
Loading…
Reference in new issue