2022-11-12 20:13:09 +00:00
|
|
|
|
#include "main_view.h"
|
2023-07-22 17:30:21 +00:00
|
|
|
|
#include <math.h>
|
2022-11-12 20:13:09 +00:00
|
|
|
|
#include <furi.h>
|
|
|
|
|
#include <furi_hal.h>
|
|
|
|
|
#include <gui/elements.h>
|
|
|
|
|
#include "../../lightmeter.h"
|
|
|
|
|
#include "../../lightmeter_helper.h"
|
|
|
|
|
|
|
|
|
|
#define WORKER_TAG "Main View"
|
|
|
|
|
|
|
|
|
|
static const int iso_numbers[] = {
|
|
|
|
|
[ISO_6] = 6,
|
|
|
|
|
[ISO_12] = 12,
|
|
|
|
|
[ISO_25] = 25,
|
|
|
|
|
[ISO_50] = 50,
|
|
|
|
|
[ISO_100] = 100,
|
|
|
|
|
[ISO_200] = 200,
|
|
|
|
|
[ISO_400] = 400,
|
|
|
|
|
[ISO_800] = 800,
|
|
|
|
|
[ISO_1600] = 1600,
|
|
|
|
|
[ISO_3200] = 3200,
|
|
|
|
|
[ISO_6400] = 6400,
|
|
|
|
|
[ISO_12800] = 12800,
|
|
|
|
|
[ISO_25600] = 25600,
|
|
|
|
|
[ISO_51200] = 51200,
|
|
|
|
|
[ISO_102400] = 102400,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const int nd_numbers[] = {
|
|
|
|
|
[ND_0] = 0,
|
|
|
|
|
[ND_2] = 2,
|
|
|
|
|
[ND_4] = 4,
|
|
|
|
|
[ND_8] = 8,
|
|
|
|
|
[ND_16] = 16,
|
|
|
|
|
[ND_32] = 32,
|
|
|
|
|
[ND_64] = 64,
|
|
|
|
|
[ND_128] = 128,
|
|
|
|
|
[ND_256] = 256,
|
|
|
|
|
[ND_512] = 512,
|
|
|
|
|
[ND_1024] = 1024,
|
|
|
|
|
[ND_2048] = 2048,
|
|
|
|
|
[ND_4096] = 4096,
|
|
|
|
|
};
|
|
|
|
|
|
2023-02-26 02:46:50 +00:00
|
|
|
|
const float aperture_numbers[] = {
|
2022-11-12 20:13:09 +00:00
|
|
|
|
[AP_1] = 1.0,
|
|
|
|
|
[AP_1_4] = 1.4,
|
|
|
|
|
[AP_2] = 2.0,
|
|
|
|
|
[AP_2_8] = 2.8,
|
|
|
|
|
[AP_4] = 4.0,
|
|
|
|
|
[AP_5_6] = 5.6,
|
|
|
|
|
[AP_8] = 8,
|
|
|
|
|
[AP_11] = 11,
|
|
|
|
|
[AP_16] = 16,
|
|
|
|
|
[AP_22] = 22,
|
|
|
|
|
[AP_32] = 32,
|
|
|
|
|
[AP_45] = 45,
|
|
|
|
|
[AP_64] = 64,
|
|
|
|
|
[AP_90] = 90,
|
|
|
|
|
[AP_128] = 128,
|
|
|
|
|
};
|
|
|
|
|
|
2023-02-26 02:46:50 +00:00
|
|
|
|
const float speed_numbers[] = {
|
2022-11-12 20:13:09 +00:00
|
|
|
|
[SPEED_8000] = 1.0 / 8000, [SPEED_4000] = 1.0 / 4000, [SPEED_2000] = 1.0 / 2000,
|
|
|
|
|
[SPEED_1000] = 1.0 / 1000, [SPEED_500] = 1.0 / 500, [SPEED_250] = 1.0 / 250,
|
2023-02-26 02:46:50 +00:00
|
|
|
|
[SPEED_125] = 1.0 / 125, [SPEED_60] = 1.0 / 60, [SPEED_48] = 1.0 / 48,
|
|
|
|
|
[SPEED_30] = 1.0 / 30, [SPEED_15] = 1.0 / 15, [SPEED_8] = 1.0 / 8,
|
|
|
|
|
[SPEED_4] = 1.0 / 4, [SPEED_2] = 1.0 / 2, [SPEED_1S] = 1.0,
|
|
|
|
|
[SPEED_2S] = 2.0, [SPEED_4S] = 4.0, [SPEED_8S] = 8.0,
|
|
|
|
|
[SPEED_15S] = 15.0, [SPEED_30S] = 30.0,
|
2022-11-12 20:13:09 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct MainView {
|
|
|
|
|
View* view;
|
|
|
|
|
LightMeterMainViewButtonCallback cb_left;
|
2023-07-22 17:30:21 +00:00
|
|
|
|
LightMeterMainViewButtonCallback cb_right;
|
2022-11-12 20:13:09 +00:00
|
|
|
|
void* cb_context;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
void lightmeter_main_view_set_left_callback(
|
|
|
|
|
MainView* lightmeter_main_view,
|
|
|
|
|
LightMeterMainViewButtonCallback callback,
|
|
|
|
|
void* context) {
|
|
|
|
|
with_view_model(
|
|
|
|
|
lightmeter_main_view->view,
|
|
|
|
|
MainViewModel * model,
|
|
|
|
|
{
|
|
|
|
|
UNUSED(model);
|
|
|
|
|
lightmeter_main_view->cb_left = callback;
|
|
|
|
|
lightmeter_main_view->cb_context = context;
|
|
|
|
|
},
|
|
|
|
|
true);
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-22 17:30:21 +00:00
|
|
|
|
void lightmeter_main_view_set_right_callback(
|
|
|
|
|
MainView* lightmeter_main_view,
|
|
|
|
|
LightMeterMainViewButtonCallback callback,
|
|
|
|
|
void* context) {
|
|
|
|
|
with_view_model(
|
|
|
|
|
lightmeter_main_view->view,
|
|
|
|
|
MainViewModel * model,
|
|
|
|
|
{
|
|
|
|
|
UNUSED(model);
|
|
|
|
|
lightmeter_main_view->cb_right = callback;
|
|
|
|
|
lightmeter_main_view->cb_context = context;
|
|
|
|
|
},
|
|
|
|
|
true);
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-12 20:13:09 +00:00
|
|
|
|
static void main_view_draw_callback(Canvas* canvas, void* context) {
|
|
|
|
|
furi_assert(context);
|
|
|
|
|
MainViewModel* model = context;
|
|
|
|
|
|
|
|
|
|
canvas_clear(canvas);
|
|
|
|
|
|
2023-02-26 02:46:50 +00:00
|
|
|
|
// draw button
|
|
|
|
|
canvas_set_font(canvas, FontSecondary);
|
|
|
|
|
elements_button_left(canvas, "Config");
|
2022-11-12 20:13:09 +00:00
|
|
|
|
|
2023-02-26 02:46:50 +00:00
|
|
|
|
if(!model->lux_only) {
|
|
|
|
|
// top row
|
|
|
|
|
draw_top_row(canvas, model);
|
2022-11-12 20:13:09 +00:00
|
|
|
|
|
2023-02-26 02:46:50 +00:00
|
|
|
|
// add f, T values
|
|
|
|
|
canvas_set_font(canvas, FontBigNumbers);
|
2022-11-12 20:13:09 +00:00
|
|
|
|
|
2023-02-26 02:46:50 +00:00
|
|
|
|
// draw f icon and number
|
|
|
|
|
canvas_draw_icon(canvas, 15, 17, &I_f_10x14);
|
|
|
|
|
draw_aperture(canvas, model);
|
2022-11-12 20:13:09 +00:00
|
|
|
|
|
2023-02-26 02:46:50 +00:00
|
|
|
|
// draw T icon and number
|
|
|
|
|
canvas_draw_icon(canvas, 15, 34, &I_T_10x14);
|
|
|
|
|
draw_speed(canvas, model);
|
2022-11-12 20:13:09 +00:00
|
|
|
|
|
2023-02-26 02:46:50 +00:00
|
|
|
|
// draw ND number
|
|
|
|
|
draw_nd_number(canvas, model);
|
2022-11-12 20:13:09 +00:00
|
|
|
|
|
2023-02-26 02:46:50 +00:00
|
|
|
|
// draw EV number
|
|
|
|
|
canvas_set_font(canvas, FontSecondary);
|
|
|
|
|
draw_EV_number(canvas, model);
|
2022-11-12 20:13:09 +00:00
|
|
|
|
|
2023-02-26 02:46:50 +00:00
|
|
|
|
// draw mode indicator
|
|
|
|
|
draw_mode_indicator(canvas, model);
|
|
|
|
|
} else {
|
2023-07-22 17:30:21 +00:00
|
|
|
|
elements_button_right(canvas, "Reset");
|
2023-02-26 02:46:50 +00:00
|
|
|
|
draw_lux_only_mode(canvas, model);
|
|
|
|
|
}
|
2022-11-12 20:13:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void main_view_process(MainView* main_view, InputEvent* event) {
|
|
|
|
|
with_view_model(
|
|
|
|
|
main_view->view,
|
|
|
|
|
MainViewModel * model,
|
|
|
|
|
{
|
|
|
|
|
if(event->type == InputTypePress) {
|
|
|
|
|
if(event->key == InputKeyUp) {
|
|
|
|
|
switch(model->current_mode) {
|
|
|
|
|
case FIXED_APERTURE:
|
|
|
|
|
if(model->aperture < AP_NUM - 1) model->aperture++;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case FIXED_SPEED:
|
|
|
|
|
if(model->speed < SPEED_NUM - 1) model->speed++;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
} else if(event->key == InputKeyDown) {
|
|
|
|
|
switch(model->current_mode) {
|
|
|
|
|
case FIXED_APERTURE:
|
|
|
|
|
if(model->aperture > 0) model->aperture--;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case FIXED_SPEED:
|
|
|
|
|
if(model->speed > 0) model->speed--;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
} else if(event->key == InputKeyOk) {
|
|
|
|
|
switch(model->current_mode) {
|
|
|
|
|
case FIXED_SPEED:
|
|
|
|
|
model->current_mode = FIXED_APERTURE;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case FIXED_APERTURE:
|
|
|
|
|
model->current_mode = FIXED_SPEED;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool main_view_input_callback(InputEvent* event, void* context) {
|
|
|
|
|
furi_assert(context);
|
|
|
|
|
MainView* main_view = context;
|
|
|
|
|
bool consumed = false;
|
|
|
|
|
|
|
|
|
|
if(event->type == InputTypeShort && event->key == InputKeyLeft) {
|
|
|
|
|
if(main_view->cb_left) {
|
|
|
|
|
main_view->cb_left(main_view->cb_context);
|
|
|
|
|
}
|
|
|
|
|
consumed = true;
|
2023-07-22 17:30:21 +00:00
|
|
|
|
} else if(event->type == InputTypeShort && event->key == InputKeyRight) {
|
|
|
|
|
if(main_view->cb_right) {
|
|
|
|
|
main_view->cb_right(main_view->cb_context);
|
|
|
|
|
}
|
|
|
|
|
consumed = true;
|
2022-11-12 20:13:09 +00:00
|
|
|
|
} else if(event->type == InputTypeShort && event->key == InputKeyBack) {
|
|
|
|
|
} else {
|
|
|
|
|
main_view_process(main_view, event);
|
|
|
|
|
consumed = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return consumed;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MainView* main_view_alloc() {
|
|
|
|
|
MainView* main_view = malloc(sizeof(MainView));
|
|
|
|
|
main_view->view = view_alloc();
|
|
|
|
|
view_set_context(main_view->view, main_view);
|
|
|
|
|
view_allocate_model(main_view->view, ViewModelTypeLocking, sizeof(MainViewModel));
|
|
|
|
|
view_set_draw_callback(main_view->view, main_view_draw_callback);
|
|
|
|
|
view_set_input_callback(main_view->view, main_view_input_callback);
|
|
|
|
|
|
|
|
|
|
return main_view;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void main_view_free(MainView* main_view) {
|
|
|
|
|
furi_assert(main_view);
|
|
|
|
|
view_free(main_view->view);
|
|
|
|
|
free(main_view);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
View* main_view_get_view(MainView* main_view) {
|
|
|
|
|
furi_assert(main_view);
|
|
|
|
|
return main_view->view;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void main_view_set_lux(MainView* main_view, float val) {
|
|
|
|
|
furi_assert(main_view);
|
|
|
|
|
with_view_model(
|
2023-07-22 17:30:21 +00:00
|
|
|
|
main_view->view,
|
|
|
|
|
MainViewModel * model,
|
|
|
|
|
{
|
|
|
|
|
model->lux = val;
|
|
|
|
|
model->peakLux = fmax(model->peakLux, val);
|
|
|
|
|
|
|
|
|
|
model->luxHistogram[model->luxHistogramIndex++] = val;
|
|
|
|
|
model->luxHistogramIndex %= LUX_HISTORGRAM_LENGTH;
|
|
|
|
|
},
|
|
|
|
|
true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void main_view_reset_lux(MainView* main_view) {
|
|
|
|
|
furi_assert(main_view);
|
|
|
|
|
with_view_model(
|
|
|
|
|
main_view->view, MainViewModel * model, { model->peakLux = 0; }, true);
|
2022-11-12 20:13:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void main_view_set_EV(MainView* main_view, float val) {
|
|
|
|
|
furi_assert(main_view);
|
|
|
|
|
with_view_model(
|
|
|
|
|
main_view->view, MainViewModel * model, { model->EV = val; }, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void main_view_set_response(MainView* main_view, bool val) {
|
|
|
|
|
furi_assert(main_view);
|
|
|
|
|
with_view_model(
|
|
|
|
|
main_view->view, MainViewModel * model, { model->response = val; }, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void main_view_set_iso(MainView* main_view, int iso) {
|
|
|
|
|
furi_assert(main_view);
|
|
|
|
|
with_view_model(
|
|
|
|
|
main_view->view, MainViewModel * model, { model->iso = iso; }, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void main_view_set_nd(MainView* main_view, int nd) {
|
|
|
|
|
furi_assert(main_view);
|
|
|
|
|
with_view_model(
|
|
|
|
|
main_view->view, MainViewModel * model, { model->nd = nd; }, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void main_view_set_aperture(MainView* main_view, int aperture) {
|
|
|
|
|
furi_assert(main_view);
|
|
|
|
|
with_view_model(
|
|
|
|
|
main_view->view, MainViewModel * model, { model->aperture = aperture; }, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void main_view_set_speed(MainView* main_view, int speed) {
|
|
|
|
|
furi_assert(main_view);
|
|
|
|
|
with_view_model(
|
|
|
|
|
main_view->view, MainViewModel * model, { model->speed = speed; }, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void main_view_set_dome(MainView* main_view, bool dome) {
|
|
|
|
|
furi_assert(main_view);
|
|
|
|
|
with_view_model(
|
|
|
|
|
main_view->view, MainViewModel * model, { model->dome = dome; }, true);
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-26 02:46:50 +00:00
|
|
|
|
void main_view_set_lux_only(MainView* main_view, bool lux_only) {
|
|
|
|
|
furi_assert(main_view);
|
|
|
|
|
with_view_model(
|
|
|
|
|
main_view->view, MainViewModel * model, { model->lux_only = lux_only; }, true);
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-22 17:30:21 +00:00
|
|
|
|
void main_view_set_measurement_resolution(MainView* main_view, int measurement_resolution) {
|
|
|
|
|
furi_assert(main_view);
|
|
|
|
|
with_view_model(
|
|
|
|
|
main_view->view,
|
|
|
|
|
MainViewModel * model,
|
|
|
|
|
{ model->measurement_resolution = measurement_resolution; },
|
|
|
|
|
true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void main_view_set_device_addr(MainView* main_view, int device_addr) {
|
|
|
|
|
furi_assert(main_view);
|
|
|
|
|
with_view_model(
|
|
|
|
|
main_view->view, MainViewModel * model, { model->device_addr = device_addr; }, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void main_view_set_sensor_type(MainView* main_view, int sensor_type) {
|
|
|
|
|
furi_assert(main_view);
|
|
|
|
|
with_view_model(
|
|
|
|
|
main_view->view, MainViewModel * model, { model->sensor_type = sensor_type; }, true);
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-12 20:13:09 +00:00
|
|
|
|
bool main_view_get_dome(MainView* main_view) {
|
|
|
|
|
furi_assert(main_view);
|
|
|
|
|
bool val = false;
|
|
|
|
|
with_view_model(
|
|
|
|
|
main_view->view, MainViewModel * model, { val = model->dome; }, true);
|
|
|
|
|
return val;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void draw_top_row(Canvas* canvas, MainViewModel* context) {
|
|
|
|
|
MainViewModel* model = context;
|
|
|
|
|
|
|
|
|
|
char str[12];
|
|
|
|
|
|
|
|
|
|
if(!model->response) {
|
|
|
|
|
canvas_draw_box(canvas, 0, 0, 128, 12);
|
|
|
|
|
canvas_set_color(canvas, ColorWhite);
|
|
|
|
|
canvas_set_font(canvas, FontPrimary);
|
|
|
|
|
canvas_draw_str(canvas, 24, 10, "No sensor found");
|
|
|
|
|
canvas_set_color(canvas, ColorBlack);
|
|
|
|
|
} else {
|
|
|
|
|
model->iso_val = iso_numbers[model->iso];
|
|
|
|
|
if(model->nd > 0) model->iso_val /= nd_numbers[model->nd];
|
|
|
|
|
|
|
|
|
|
if(model->lux > 0) {
|
|
|
|
|
if(model->current_mode == FIXED_APERTURE) {
|
|
|
|
|
model->speed_val = 100 * pow(aperture_numbers[model->aperture], 2) /
|
|
|
|
|
(double)model->iso_val / pow(2, model->EV);
|
|
|
|
|
} else {
|
|
|
|
|
model->aperture_val = sqrt(
|
|
|
|
|
pow(2, model->EV) * (double)model->iso_val *
|
|
|
|
|
(double)speed_numbers[model->speed] / 100);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO when T:30, f/0 instead of f/128
|
|
|
|
|
|
|
|
|
|
canvas_draw_line(canvas, 0, 10, 128, 10);
|
|
|
|
|
|
|
|
|
|
canvas_set_font(canvas, FontPrimary);
|
|
|
|
|
// metering mode A – ambient, F – flash
|
2023-02-26 02:46:50 +00:00
|
|
|
|
// canvas_draw_str_aligned(canvas, 1, 1, AlignLeft, AlignTop, "A");
|
2022-11-12 20:13:09 +00:00
|
|
|
|
|
|
|
|
|
snprintf(str, sizeof(str), "ISO: %d", iso_numbers[model->iso]);
|
|
|
|
|
canvas_draw_str_aligned(canvas, 19, 1, AlignLeft, AlignTop, str);
|
|
|
|
|
|
|
|
|
|
canvas_set_font(canvas, FontSecondary);
|
|
|
|
|
snprintf(str, sizeof(str), "lx: %.0f", (double)model->lux);
|
|
|
|
|
canvas_draw_str_aligned(canvas, 87, 2, AlignLeft, AlignTop, str);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void draw_aperture(Canvas* canvas, MainViewModel* context) {
|
|
|
|
|
MainViewModel* model = context;
|
|
|
|
|
|
|
|
|
|
char str[12];
|
|
|
|
|
|
|
|
|
|
switch(model->current_mode) {
|
|
|
|
|
case FIXED_APERTURE:
|
|
|
|
|
if(model->response) {
|
|
|
|
|
if(model->aperture < AP_8) {
|
|
|
|
|
snprintf(str, sizeof(str), "/%.1f", (double)aperture_numbers[model->aperture]);
|
|
|
|
|
} else {
|
|
|
|
|
snprintf(str, sizeof(str), "/%.0f", (double)aperture_numbers[model->aperture]);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
snprintf(str, sizeof(str), " ---");
|
|
|
|
|
}
|
|
|
|
|
canvas_draw_str_aligned(canvas, 27, 15, AlignLeft, AlignTop, str);
|
|
|
|
|
break;
|
|
|
|
|
case FIXED_SPEED:
|
|
|
|
|
if(model->aperture_val < aperture_numbers[0] || !model->response) {
|
|
|
|
|
snprintf(str, sizeof(str), " ---");
|
|
|
|
|
} else if(model->aperture_val < aperture_numbers[AP_8]) {
|
|
|
|
|
snprintf(str, sizeof(str), "/%.1f", (double)normalizeAperture(model->aperture_val));
|
|
|
|
|
} else {
|
|
|
|
|
snprintf(str, sizeof(str), "/%.0f", (double)normalizeAperture(model->aperture_val));
|
|
|
|
|
}
|
|
|
|
|
canvas_draw_str_aligned(canvas, 27, 15, AlignLeft, AlignTop, str);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void draw_speed(Canvas* canvas, MainViewModel* context) {
|
|
|
|
|
MainViewModel* model = context;
|
|
|
|
|
|
|
|
|
|
char str[12];
|
|
|
|
|
|
|
|
|
|
switch(model->current_mode) {
|
|
|
|
|
case FIXED_APERTURE:
|
|
|
|
|
if(model->lux > 0 && model->response) {
|
|
|
|
|
if(model->speed_val < 1 && model->speed_val > 0) {
|
|
|
|
|
snprintf(str, sizeof(str), ":1/%.0f", 1 / (double)normalizeTime(model->speed_val));
|
|
|
|
|
} else {
|
|
|
|
|
snprintf(str, sizeof(str), ":%.0f", (double)normalizeTime(model->speed_val));
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
snprintf(str, sizeof(str), " ---");
|
|
|
|
|
}
|
|
|
|
|
canvas_draw_str_aligned(canvas, 27, 34, AlignLeft, AlignTop, str);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case FIXED_SPEED:
|
|
|
|
|
if(model->response) {
|
|
|
|
|
if(model->speed < SPEED_1S) {
|
|
|
|
|
snprintf(str, sizeof(str), ":1/%.0f", 1 / (double)speed_numbers[model->speed]);
|
|
|
|
|
} else {
|
|
|
|
|
snprintf(str, sizeof(str), ":%.0f", (double)speed_numbers[model->speed]);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
snprintf(str, sizeof(str), " ---");
|
|
|
|
|
}
|
|
|
|
|
canvas_draw_str_aligned(canvas, 27, 34, AlignLeft, AlignTop, str);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void draw_mode_indicator(Canvas* canvas, MainViewModel* context) {
|
|
|
|
|
MainViewModel* model = context;
|
|
|
|
|
|
|
|
|
|
switch(model->current_mode) {
|
|
|
|
|
case FIXED_SPEED:
|
|
|
|
|
canvas_set_font(canvas, FontBigNumbers);
|
|
|
|
|
canvas_draw_str_aligned(canvas, 3, 36, AlignLeft, AlignTop, "*");
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case FIXED_APERTURE:
|
|
|
|
|
canvas_set_font(canvas, FontBigNumbers);
|
|
|
|
|
canvas_draw_str_aligned(canvas, 3, 17, AlignLeft, AlignTop, "*");
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void draw_nd_number(Canvas* canvas, MainViewModel* context) {
|
|
|
|
|
MainViewModel* model = context;
|
|
|
|
|
|
|
|
|
|
char str[9];
|
|
|
|
|
|
2023-02-26 02:46:50 +00:00
|
|
|
|
canvas_set_font(canvas, FontSecondary);
|
|
|
|
|
|
2022-11-12 20:13:09 +00:00
|
|
|
|
if(model->response) {
|
|
|
|
|
snprintf(str, sizeof(str), "ND: %d", nd_numbers[model->nd]);
|
|
|
|
|
} else {
|
|
|
|
|
snprintf(str, sizeof(str), "ND: ---");
|
|
|
|
|
}
|
|
|
|
|
canvas_draw_str_aligned(canvas, 87, 20, AlignLeft, AlignBottom, str);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void draw_EV_number(Canvas* canvas, MainViewModel* context) {
|
|
|
|
|
MainViewModel* model = context;
|
|
|
|
|
|
|
|
|
|
char str[7];
|
|
|
|
|
|
|
|
|
|
if(model->lux > 0 && model->response) {
|
|
|
|
|
snprintf(str, sizeof(str), "EV: %1.0f", (double)model->EV);
|
|
|
|
|
canvas_draw_str_aligned(canvas, 87, 29, AlignLeft, AlignBottom, str);
|
|
|
|
|
} else {
|
|
|
|
|
canvas_draw_str_aligned(canvas, 87, 29, AlignLeft, AlignBottom, "EV: --");
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-02-26 02:46:50 +00:00
|
|
|
|
|
|
|
|
|
void draw_lux_only_mode(Canvas* canvas, MainViewModel* context) {
|
|
|
|
|
MainViewModel* model = context;
|
|
|
|
|
|
|
|
|
|
if(!model->response) {
|
|
|
|
|
canvas_draw_box(canvas, 0, 0, 128, 12);
|
|
|
|
|
canvas_set_color(canvas, ColorWhite);
|
|
|
|
|
canvas_set_font(canvas, FontPrimary);
|
|
|
|
|
canvas_draw_str(canvas, 24, 10, "No sensor found");
|
|
|
|
|
canvas_set_color(canvas, ColorBlack);
|
|
|
|
|
} else {
|
|
|
|
|
char str[12];
|
|
|
|
|
|
|
|
|
|
canvas_set_font(canvas, FontPrimary);
|
|
|
|
|
|
|
|
|
|
canvas_draw_line(canvas, 0, 10, 128, 10);
|
|
|
|
|
canvas_draw_str_aligned(canvas, 64, 1, AlignCenter, AlignTop, "Lux meter mode");
|
|
|
|
|
|
|
|
|
|
canvas_set_font(canvas, FontBigNumbers);
|
|
|
|
|
snprintf(str, sizeof(str), "%.0f", (double)model->lux);
|
2023-07-22 17:30:21 +00:00
|
|
|
|
canvas_draw_str_aligned(canvas, 80, 22, AlignRight, AlignCenter, str);
|
2023-02-26 02:46:50 +00:00
|
|
|
|
|
|
|
|
|
canvas_set_font(canvas, FontSecondary);
|
2023-07-22 17:30:21 +00:00
|
|
|
|
canvas_draw_str_aligned(canvas, 85, 29, AlignLeft, AlignBottom, "Lux now");
|
|
|
|
|
|
|
|
|
|
canvas_set_font(canvas, FontPrimary);
|
|
|
|
|
snprintf(str, sizeof(str), "%.0f", (double)model->peakLux);
|
|
|
|
|
canvas_draw_str_aligned(canvas, 80, 39, AlignRight, AlignCenter, str);
|
|
|
|
|
|
|
|
|
|
canvas_set_font(canvas, FontSecondary);
|
|
|
|
|
canvas_draw_str_aligned(canvas, 85, 43, AlignLeft, AlignBottom, "Lux peak");
|
|
|
|
|
|
|
|
|
|
for(int i = 0; i < LUX_HISTORGRAM_LENGTH; i++) {
|
|
|
|
|
float lux =
|
|
|
|
|
model->luxHistogram[(i + model->luxHistogramIndex) % LUX_HISTORGRAM_LENGTH];
|
|
|
|
|
int barHeight = log10(lux) / log10(LUX_HISTORGRAM_LOGBASE);
|
|
|
|
|
canvas_draw_line(
|
|
|
|
|
canvas,
|
|
|
|
|
LUX_HISTORGRAM_LEFT + i,
|
|
|
|
|
LUX_HISTORGRAM_BOTTOM,
|
|
|
|
|
LUX_HISTORGRAM_LEFT + i,
|
|
|
|
|
LUX_HISTORGRAM_BOTTOM - barHeight);
|
|
|
|
|
}
|
2023-02-26 02:46:50 +00:00
|
|
|
|
}
|
|
|
|
|
}
|