Refactor trig functions into LUT (#476)
Replaced the use of the standard library trig functions with a LUT-based implementation instead. The standard library implementations produce more accurate results but the usage here doesn't need that. This ends up saving nearly 7kB of binary size.
This commit is contained in:
parent
7fee2c2589
commit
4f378e8726
|
@ -5,27 +5,44 @@
|
|||
#include "Symbols.h"
|
||||
#include "NotificationIcon.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
LV_IMG_DECLARE(bg_clock);
|
||||
|
||||
using namespace Pinetime::Applications::Screens;
|
||||
|
||||
#define HOUR_LENGTH 70
|
||||
#define MINUTE_LENGTH 90
|
||||
#define SECOND_LENGTH 110
|
||||
#define PI 3.14159265358979323846
|
||||
namespace {
|
||||
|
||||
// ##
|
||||
static int16_t coordinate_x_relocate(int16_t x) {
|
||||
return ((x) + LV_HOR_RES / 2);
|
||||
constexpr auto HOUR_LENGTH = 70;
|
||||
constexpr auto MINUTE_LENGTH = 90;
|
||||
constexpr auto SECOND_LENGTH = 110;
|
||||
|
||||
// sin(90) = 1 so the value of _lv_trigo_sin(90) is the scaling factor
|
||||
const auto LV_TRIG_SCALE = _lv_trigo_sin(90);
|
||||
|
||||
int16_t cosine(int16_t angle) {
|
||||
return _lv_trigo_sin(angle + 90);
|
||||
}
|
||||
|
||||
// ##
|
||||
static int16_t coordinate_y_relocate(int16_t y) {
|
||||
return (((y) -LV_HOR_RES / 2) < 0) ? (0 - ((y) -LV_HOR_RES / 2)) : ((y) -LV_HOR_RES / 2);
|
||||
int16_t sine(int16_t angle) {
|
||||
return _lv_trigo_sin(angle);
|
||||
}
|
||||
|
||||
int16_t coordinate_x_relocate(int16_t x) {
|
||||
return (x + LV_HOR_RES / 2);
|
||||
}
|
||||
|
||||
int16_t coordinate_y_relocate(int16_t y) {
|
||||
return std::abs(y - LV_HOR_RES / 2);
|
||||
}
|
||||
|
||||
lv_point_t coordinate_relocate(int16_t radius, int16_t angle) {
|
||||
return lv_point_t{
|
||||
.x = coordinate_x_relocate(radius * static_cast<int32_t>(sine(angle)) / LV_TRIG_SCALE),
|
||||
.y = coordinate_y_relocate(radius * static_cast<int32_t>(cosine(angle)) / LV_TRIG_SCALE)
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
WatchFaceAnalog::WatchFaceAnalog(Pinetime::Applications::DisplayApp* app,
|
||||
Controllers::DateTime& dateTimeController,
|
||||
Controllers::Battery& batteryController,
|
||||
|
@ -123,15 +140,12 @@ void WatchFaceAnalog::UpdateClock() {
|
|||
second = dateTimeController.Seconds();
|
||||
|
||||
if (sMinute != minute) {
|
||||
minute_point[0].x = coordinate_x_relocate(30 * sin(minute * 6 * PI / 180));
|
||||
minute_point[0].y = coordinate_y_relocate(30 * cos(minute * 6 * PI / 180));
|
||||
minute_point[1].x = coordinate_x_relocate(MINUTE_LENGTH * sin(minute * 6 * PI / 180));
|
||||
minute_point[1].y = coordinate_y_relocate(MINUTE_LENGTH * cos(minute * 6 * PI / 180));
|
||||
auto const angle = minute * 6;
|
||||
minute_point[0] = coordinate_relocate(30, angle);
|
||||
minute_point[1] = coordinate_relocate(MINUTE_LENGTH, angle);
|
||||
|
||||
minute_point_trace[0].x = coordinate_x_relocate(5 * sin(minute * 6 * PI / 180));
|
||||
minute_point_trace[0].y = coordinate_y_relocate(5 * cos(minute * 6 * PI / 180));
|
||||
minute_point_trace[1].x = coordinate_x_relocate(31 * sin(minute * 6 * PI / 180));
|
||||
minute_point_trace[1].y = coordinate_y_relocate(31 * cos(minute * 6 * PI / 180));
|
||||
minute_point_trace[0] = coordinate_relocate(5, angle);
|
||||
minute_point_trace[1] = coordinate_relocate(31, angle);
|
||||
|
||||
lv_line_set_points(minute_body, minute_point, 2);
|
||||
lv_line_set_points(minute_body_trace, minute_point_trace, 2);
|
||||
|
@ -140,15 +154,13 @@ void WatchFaceAnalog::UpdateClock() {
|
|||
if (sHour != hour || sMinute != minute) {
|
||||
sHour = hour;
|
||||
sMinute = minute;
|
||||
hour_point[0].x = coordinate_x_relocate(30 * sin((((hour > 12 ? hour - 12 : hour) * 30) + (minute * 0.5)) * PI / 180));
|
||||
hour_point[0].y = coordinate_y_relocate(30 * cos((((hour > 12 ? hour - 12 : hour) * 30) + (minute * 0.5)) * PI / 180));
|
||||
hour_point[1].x = coordinate_x_relocate(HOUR_LENGTH * sin((((hour > 12 ? hour - 12 : hour) * 30) + (minute * 0.5)) * PI / 180));
|
||||
hour_point[1].y = coordinate_y_relocate(HOUR_LENGTH * cos((((hour > 12 ? hour - 12 : hour) * 30) + (minute * 0.5)) * PI / 180));
|
||||
auto const angle = (hour * 30 + minute / 2);
|
||||
|
||||
hour_point_trace[0].x = coordinate_x_relocate(5 * sin((((hour > 12 ? hour - 12 : hour) * 30) + (minute * 0.5)) * PI / 180));
|
||||
hour_point_trace[0].y = coordinate_y_relocate(5 * cos((((hour > 12 ? hour - 12 : hour) * 30) + (minute * 0.5)) * PI / 180));
|
||||
hour_point_trace[1].x = coordinate_x_relocate(31 * sin((((hour > 12 ? hour - 12 : hour) * 30) + (minute * 0.5)) * PI / 180));
|
||||
hour_point_trace[1].y = coordinate_y_relocate(31 * cos((((hour > 12 ? hour - 12 : hour) * 30) + (minute * 0.5)) * PI / 180));
|
||||
hour_point[0] = coordinate_relocate(30, angle);
|
||||
hour_point[1] = coordinate_relocate(HOUR_LENGTH, angle);
|
||||
|
||||
hour_point_trace[0] = coordinate_relocate(5, angle);
|
||||
hour_point_trace[1] = coordinate_relocate(31, angle);
|
||||
|
||||
lv_line_set_points(hour_body, hour_point, 2);
|
||||
lv_line_set_points(hour_body_trace, hour_point_trace, 2);
|
||||
|
@ -156,10 +168,10 @@ void WatchFaceAnalog::UpdateClock() {
|
|||
|
||||
if (sSecond != second) {
|
||||
sSecond = second;
|
||||
second_point[0].x = coordinate_x_relocate(20 * sin((180 + second * 6) * PI / 180));
|
||||
second_point[0].y = coordinate_y_relocate(20 * cos((180 + second * 6) * PI / 180));
|
||||
second_point[1].x = coordinate_x_relocate(SECOND_LENGTH * sin(second * 6 * PI / 180));
|
||||
second_point[1].y = coordinate_y_relocate(SECOND_LENGTH * cos(second * 6 * PI / 180));
|
||||
auto const angle = second * 6;
|
||||
|
||||
second_point[0] = coordinate_relocate(-20, angle);
|
||||
second_point[1] = coordinate_relocate(SECOND_LENGTH, angle);
|
||||
lv_line_set_points(second_body, second_point, 2);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue