Skip to content

Commit 4f378e8

Browse files
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.
1 parent 7fee2c2 commit 4f378e8

1 file changed

Lines changed: 44 additions & 32 deletions

File tree

src/displayapp/screens/WatchFaceAnalog.cpp

Lines changed: 44 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,44 @@
55
#include "Symbols.h"
66
#include "NotificationIcon.h"
77

8-
#include <cmath>
9-
108
LV_IMG_DECLARE(bg_clock);
119

1210
using namespace Pinetime::Applications::Screens;
1311

14-
#define HOUR_LENGTH 70
15-
#define MINUTE_LENGTH 90
16-
#define SECOND_LENGTH 110
17-
#define PI 3.14159265358979323846
12+
namespace {
13+
14+
constexpr auto HOUR_LENGTH = 70;
15+
constexpr auto MINUTE_LENGTH = 90;
16+
constexpr auto SECOND_LENGTH = 110;
17+
18+
// sin(90) = 1 so the value of _lv_trigo_sin(90) is the scaling factor
19+
const auto LV_TRIG_SCALE = _lv_trigo_sin(90);
20+
21+
int16_t cosine(int16_t angle) {
22+
return _lv_trigo_sin(angle + 90);
23+
}
24+
25+
int16_t sine(int16_t angle) {
26+
return _lv_trigo_sin(angle);
27+
}
28+
29+
int16_t coordinate_x_relocate(int16_t x) {
30+
return (x + LV_HOR_RES / 2);
31+
}
1832

19-
// ##
20-
static int16_t coordinate_x_relocate(int16_t x) {
21-
return ((x) + LV_HOR_RES / 2);
33+
int16_t coordinate_y_relocate(int16_t y) {
34+
return std::abs(y - LV_HOR_RES / 2);
2235
}
2336

24-
// ##
25-
static int16_t coordinate_y_relocate(int16_t y) {
26-
return (((y) -LV_HOR_RES / 2) < 0) ? (0 - ((y) -LV_HOR_RES / 2)) : ((y) -LV_HOR_RES / 2);
37+
lv_point_t coordinate_relocate(int16_t radius, int16_t angle) {
38+
return lv_point_t{
39+
.x = coordinate_x_relocate(radius * static_cast<int32_t>(sine(angle)) / LV_TRIG_SCALE),
40+
.y = coordinate_y_relocate(radius * static_cast<int32_t>(cosine(angle)) / LV_TRIG_SCALE)
41+
};
2742
}
2843

44+
} // namespace
45+
2946
WatchFaceAnalog::WatchFaceAnalog(Pinetime::Applications::DisplayApp* app,
3047
Controllers::DateTime& dateTimeController,
3148
Controllers::Battery& batteryController,
@@ -123,15 +140,12 @@ void WatchFaceAnalog::UpdateClock() {
123140
second = dateTimeController.Seconds();
124141

125142
if (sMinute != minute) {
126-
minute_point[0].x = coordinate_x_relocate(30 * sin(minute * 6 * PI / 180));
127-
minute_point[0].y = coordinate_y_relocate(30 * cos(minute * 6 * PI / 180));
128-
minute_point[1].x = coordinate_x_relocate(MINUTE_LENGTH * sin(minute * 6 * PI / 180));
129-
minute_point[1].y = coordinate_y_relocate(MINUTE_LENGTH * cos(minute * 6 * PI / 180));
143+
auto const angle = minute * 6;
144+
minute_point[0] = coordinate_relocate(30, angle);
145+
minute_point[1] = coordinate_relocate(MINUTE_LENGTH, angle);
130146

131-
minute_point_trace[0].x = coordinate_x_relocate(5 * sin(minute * 6 * PI / 180));
132-
minute_point_trace[0].y = coordinate_y_relocate(5 * cos(minute * 6 * PI / 180));
133-
minute_point_trace[1].x = coordinate_x_relocate(31 * sin(minute * 6 * PI / 180));
134-
minute_point_trace[1].y = coordinate_y_relocate(31 * cos(minute * 6 * PI / 180));
147+
minute_point_trace[0] = coordinate_relocate(5, angle);
148+
minute_point_trace[1] = coordinate_relocate(31, angle);
135149

136150
lv_line_set_points(minute_body, minute_point, 2);
137151
lv_line_set_points(minute_body_trace, minute_point_trace, 2);
@@ -140,26 +154,24 @@ void WatchFaceAnalog::UpdateClock() {
140154
if (sHour != hour || sMinute != minute) {
141155
sHour = hour;
142156
sMinute = minute;
143-
hour_point[0].x = coordinate_x_relocate(30 * sin((((hour > 12 ? hour - 12 : hour) * 30) + (minute * 0.5)) * PI / 180));
144-
hour_point[0].y = coordinate_y_relocate(30 * cos((((hour > 12 ? hour - 12 : hour) * 30) + (minute * 0.5)) * PI / 180));
145-
hour_point[1].x = coordinate_x_relocate(HOUR_LENGTH * sin((((hour > 12 ? hour - 12 : hour) * 30) + (minute * 0.5)) * PI / 180));
146-
hour_point[1].y = coordinate_y_relocate(HOUR_LENGTH * cos((((hour > 12 ? hour - 12 : hour) * 30) + (minute * 0.5)) * PI / 180));
157+
auto const angle = (hour * 30 + minute / 2);
158+
159+
hour_point[0] = coordinate_relocate(30, angle);
160+
hour_point[1] = coordinate_relocate(HOUR_LENGTH, angle);
147161

148-
hour_point_trace[0].x = coordinate_x_relocate(5 * sin((((hour > 12 ? hour - 12 : hour) * 30) + (minute * 0.5)) * PI / 180));
149-
hour_point_trace[0].y = coordinate_y_relocate(5 * cos((((hour > 12 ? hour - 12 : hour) * 30) + (minute * 0.5)) * PI / 180));
150-
hour_point_trace[1].x = coordinate_x_relocate(31 * sin((((hour > 12 ? hour - 12 : hour) * 30) + (minute * 0.5)) * PI / 180));
151-
hour_point_trace[1].y = coordinate_y_relocate(31 * cos((((hour > 12 ? hour - 12 : hour) * 30) + (minute * 0.5)) * PI / 180));
162+
hour_point_trace[0] = coordinate_relocate(5, angle);
163+
hour_point_trace[1] = coordinate_relocate(31, angle);
152164

153165
lv_line_set_points(hour_body, hour_point, 2);
154166
lv_line_set_points(hour_body_trace, hour_point_trace, 2);
155167
}
156168

157169
if (sSecond != second) {
158170
sSecond = second;
159-
second_point[0].x = coordinate_x_relocate(20 * sin((180 + second * 6) * PI / 180));
160-
second_point[0].y = coordinate_y_relocate(20 * cos((180 + second * 6) * PI / 180));
161-
second_point[1].x = coordinate_x_relocate(SECOND_LENGTH * sin(second * 6 * PI / 180));
162-
second_point[1].y = coordinate_y_relocate(SECOND_LENGTH * cos(second * 6 * PI / 180));
171+
auto const angle = second * 6;
172+
173+
second_point[0] = coordinate_relocate(-20, angle);
174+
second_point[1] = coordinate_relocate(SECOND_LENGTH, angle);
163175
lv_line_set_points(second_body, second_point, 2);
164176
}
165177
}

0 commit comments

Comments
 (0)