main_view.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. #include "main_view.h"
  2. #include <furi.h>
  3. #include <furi_hal.h>
  4. #include <gui/elements.h>
  5. #include "../../lightmeter.h"
  6. #include "../../lightmeter_helper.h"
  7. #define WORKER_TAG "Main View"
  8. static const int iso_numbers[] = {
  9. [ISO_6] = 6,
  10. [ISO_12] = 12,
  11. [ISO_25] = 25,
  12. [ISO_50] = 50,
  13. [ISO_100] = 100,
  14. [ISO_200] = 200,
  15. [ISO_400] = 400,
  16. [ISO_800] = 800,
  17. [ISO_1600] = 1600,
  18. [ISO_3200] = 3200,
  19. [ISO_6400] = 6400,
  20. [ISO_12800] = 12800,
  21. [ISO_25600] = 25600,
  22. [ISO_51200] = 51200,
  23. [ISO_102400] = 102400,
  24. };
  25. static const int nd_numbers[] = {
  26. [ND_0] = 0,
  27. [ND_2] = 2,
  28. [ND_4] = 4,
  29. [ND_8] = 8,
  30. [ND_16] = 16,
  31. [ND_32] = 32,
  32. [ND_64] = 64,
  33. [ND_128] = 128,
  34. [ND_256] = 256,
  35. [ND_512] = 512,
  36. [ND_1024] = 1024,
  37. [ND_2048] = 2048,
  38. [ND_4096] = 4096,
  39. };
  40. static const float aperture_numbers[] = {
  41. [AP_1] = 1.0,
  42. [AP_1_4] = 1.4,
  43. [AP_2] = 2.0,
  44. [AP_2_8] = 2.8,
  45. [AP_4] = 4.0,
  46. [AP_5_6] = 5.6,
  47. [AP_8] = 8,
  48. [AP_11] = 11,
  49. [AP_16] = 16,
  50. [AP_22] = 22,
  51. [AP_32] = 32,
  52. [AP_45] = 45,
  53. [AP_64] = 64,
  54. [AP_90] = 90,
  55. [AP_128] = 128,
  56. };
  57. static const float speed_numbers[] = {
  58. [SPEED_8000] = 1.0 / 8000, [SPEED_4000] = 1.0 / 4000, [SPEED_2000] = 1.0 / 2000,
  59. [SPEED_1000] = 1.0 / 1000, [SPEED_500] = 1.0 / 500, [SPEED_250] = 1.0 / 250,
  60. [SPEED_125] = 1.0 / 125, [SPEED_60] = 1.0 / 60, [SPEED_30] = 1.0 / 30,
  61. [SPEED_15] = 1.0 / 15, [SPEED_8] = 1.0 / 8, [SPEED_4] = 1.0 / 4,
  62. [SPEED_2] = 1.0 / 2, [SPEED_1S] = 1.0, [SPEED_2S] = 2.0,
  63. [SPEED_4S] = 4.0, [SPEED_8S] = 8.0, [SPEED_15S] = 15.0,
  64. [SPEED_30S] = 30.0,
  65. };
  66. struct MainView {
  67. View* view;
  68. LightMeterMainViewButtonCallback cb_left;
  69. void* cb_context;
  70. };
  71. void lightmeter_main_view_set_left_callback(
  72. MainView* lightmeter_main_view,
  73. LightMeterMainViewButtonCallback callback,
  74. void* context) {
  75. with_view_model(
  76. lightmeter_main_view->view,
  77. MainViewModel * model,
  78. {
  79. UNUSED(model);
  80. lightmeter_main_view->cb_left = callback;
  81. lightmeter_main_view->cb_context = context;
  82. },
  83. true);
  84. }
  85. static void main_view_draw_callback(Canvas* canvas, void* context) {
  86. furi_assert(context);
  87. MainViewModel* model = context;
  88. // FURI_LOG_D("MAIN VIEW", "Drawing");
  89. canvas_clear(canvas);
  90. // top row
  91. draw_top_row(canvas, model);
  92. // add f, T values
  93. canvas_set_font(canvas, FontBigNumbers);
  94. // draw f icon and number
  95. canvas_draw_icon(canvas, 15, 17, &I_f_10x14);
  96. draw_aperture(canvas, model);
  97. // draw T icon and number
  98. canvas_draw_icon(canvas, 15, 34, &I_T_10x14);
  99. draw_speed(canvas, model);
  100. // draw button
  101. canvas_set_font(canvas, FontSecondary);
  102. elements_button_left(canvas, "Config");
  103. // draw ND number
  104. draw_nd_number(canvas, model);
  105. // draw EV number
  106. canvas_set_font(canvas, FontSecondary);
  107. draw_EV_number(canvas, model);
  108. // draw mode indicator
  109. draw_mode_indicator(canvas, model);
  110. }
  111. static void main_view_process(MainView* main_view, InputEvent* event) {
  112. with_view_model(
  113. main_view->view,
  114. MainViewModel * model,
  115. {
  116. if(event->type == InputTypePress) {
  117. if(event->key == InputKeyUp) {
  118. switch(model->current_mode) {
  119. case FIXED_APERTURE:
  120. if(model->aperture < AP_NUM - 1) model->aperture++;
  121. break;
  122. case FIXED_SPEED:
  123. if(model->speed < SPEED_NUM - 1) model->speed++;
  124. break;
  125. default:
  126. break;
  127. }
  128. } else if(event->key == InputKeyDown) {
  129. switch(model->current_mode) {
  130. case FIXED_APERTURE:
  131. if(model->aperture > 0) model->aperture--;
  132. break;
  133. case FIXED_SPEED:
  134. if(model->speed > 0) model->speed--;
  135. break;
  136. default:
  137. break;
  138. }
  139. } else if(event->key == InputKeyOk) {
  140. switch(model->current_mode) {
  141. case FIXED_SPEED:
  142. model->current_mode = FIXED_APERTURE;
  143. break;
  144. case FIXED_APERTURE:
  145. model->current_mode = FIXED_SPEED;
  146. break;
  147. default:
  148. break;
  149. }
  150. }
  151. }
  152. },
  153. true);
  154. }
  155. static bool main_view_input_callback(InputEvent* event, void* context) {
  156. furi_assert(context);
  157. MainView* main_view = context;
  158. bool consumed = false;
  159. if(event->type == InputTypeShort && event->key == InputKeyLeft) {
  160. if(main_view->cb_left) {
  161. main_view->cb_left(main_view->cb_context);
  162. }
  163. consumed = true;
  164. } else if(event->type == InputTypeShort && event->key == InputKeyBack) {
  165. } else {
  166. main_view_process(main_view, event);
  167. consumed = true;
  168. }
  169. return consumed;
  170. }
  171. MainView* main_view_alloc() {
  172. MainView* main_view = malloc(sizeof(MainView));
  173. main_view->view = view_alloc();
  174. view_set_context(main_view->view, main_view);
  175. view_allocate_model(main_view->view, ViewModelTypeLocking, sizeof(MainViewModel));
  176. view_set_draw_callback(main_view->view, main_view_draw_callback);
  177. view_set_input_callback(main_view->view, main_view_input_callback);
  178. return main_view;
  179. }
  180. void main_view_free(MainView* main_view) {
  181. furi_assert(main_view);
  182. view_free(main_view->view);
  183. free(main_view);
  184. }
  185. View* main_view_get_view(MainView* main_view) {
  186. furi_assert(main_view);
  187. return main_view->view;
  188. }
  189. void main_view_set_lux(MainView* main_view, float val) {
  190. furi_assert(main_view);
  191. with_view_model(
  192. main_view->view, MainViewModel * model, { model->lux = val; }, true);
  193. }
  194. void main_view_set_EV(MainView* main_view, float val) {
  195. furi_assert(main_view);
  196. with_view_model(
  197. main_view->view, MainViewModel * model, { model->EV = val; }, true);
  198. }
  199. void main_view_set_response(MainView* main_view, bool val) {
  200. furi_assert(main_view);
  201. with_view_model(
  202. main_view->view, MainViewModel * model, { model->response = val; }, true);
  203. }
  204. void main_view_set_iso(MainView* main_view, int iso) {
  205. furi_assert(main_view);
  206. with_view_model(
  207. main_view->view, MainViewModel * model, { model->iso = iso; }, true);
  208. }
  209. void main_view_set_nd(MainView* main_view, int nd) {
  210. furi_assert(main_view);
  211. with_view_model(
  212. main_view->view, MainViewModel * model, { model->nd = nd; }, true);
  213. }
  214. void main_view_set_aperture(MainView* main_view, int aperture) {
  215. furi_assert(main_view);
  216. with_view_model(
  217. main_view->view, MainViewModel * model, { model->aperture = aperture; }, true);
  218. }
  219. void main_view_set_speed(MainView* main_view, int speed) {
  220. furi_assert(main_view);
  221. with_view_model(
  222. main_view->view, MainViewModel * model, { model->speed = speed; }, true);
  223. }
  224. void main_view_set_dome(MainView* main_view, bool dome) {
  225. furi_assert(main_view);
  226. with_view_model(
  227. main_view->view, MainViewModel * model, { model->dome = dome; }, true);
  228. }
  229. bool main_view_get_dome(MainView* main_view) {
  230. furi_assert(main_view);
  231. bool val = false;
  232. with_view_model(
  233. main_view->view, MainViewModel * model, { val = model->dome; }, true);
  234. return val;
  235. }
  236. void draw_top_row(Canvas* canvas, MainViewModel* context) {
  237. MainViewModel* model = context;
  238. char str[12];
  239. if(!model->response) {
  240. canvas_draw_box(canvas, 0, 0, 128, 12);
  241. canvas_set_color(canvas, ColorWhite);
  242. canvas_set_font(canvas, FontPrimary);
  243. canvas_draw_str(canvas, 24, 10, "No sensor found");
  244. canvas_set_color(canvas, ColorBlack);
  245. } else {
  246. model->iso_val = iso_numbers[model->iso];
  247. if(model->nd > 0) model->iso_val /= nd_numbers[model->nd];
  248. if(model->lux > 0) {
  249. if(model->current_mode == FIXED_APERTURE) {
  250. model->speed_val = 100 * pow(aperture_numbers[model->aperture], 2) /
  251. (double)model->iso_val / pow(2, model->EV);
  252. } else {
  253. model->aperture_val = sqrt(
  254. pow(2, model->EV) * (double)model->iso_val *
  255. (double)speed_numbers[model->speed] / 100);
  256. }
  257. }
  258. // TODO when T:30, f/0 instead of f/128
  259. canvas_draw_line(canvas, 0, 10, 128, 10);
  260. canvas_set_font(canvas, FontPrimary);
  261. // metering mode A – ambient, F – flash
  262. canvas_draw_str_aligned(canvas, 1, 1, AlignLeft, AlignTop, "A");
  263. snprintf(str, sizeof(str), "ISO: %d", iso_numbers[model->iso]);
  264. canvas_draw_str_aligned(canvas, 19, 1, AlignLeft, AlignTop, str);
  265. canvas_set_font(canvas, FontSecondary);
  266. snprintf(str, sizeof(str), "lx: %.0f", (double)model->lux);
  267. canvas_draw_str_aligned(canvas, 87, 2, AlignLeft, AlignTop, str);
  268. }
  269. }
  270. void draw_aperture(Canvas* canvas, MainViewModel* context) {
  271. MainViewModel* model = context;
  272. char str[12];
  273. switch(model->current_mode) {
  274. case FIXED_APERTURE:
  275. if(model->response) {
  276. if(model->aperture < AP_8) {
  277. snprintf(str, sizeof(str), "/%.1f", (double)aperture_numbers[model->aperture]);
  278. } else {
  279. snprintf(str, sizeof(str), "/%.0f", (double)aperture_numbers[model->aperture]);
  280. }
  281. } else {
  282. snprintf(str, sizeof(str), " ---");
  283. }
  284. canvas_draw_str_aligned(canvas, 27, 15, AlignLeft, AlignTop, str);
  285. break;
  286. case FIXED_SPEED:
  287. if(model->aperture_val < aperture_numbers[0] || !model->response) {
  288. snprintf(str, sizeof(str), " ---");
  289. } else if(model->aperture_val < aperture_numbers[AP_8]) {
  290. snprintf(str, sizeof(str), "/%.1f", (double)normalizeAperture(model->aperture_val));
  291. } else {
  292. snprintf(str, sizeof(str), "/%.0f", (double)normalizeAperture(model->aperture_val));
  293. }
  294. canvas_draw_str_aligned(canvas, 27, 15, AlignLeft, AlignTop, str);
  295. break;
  296. default:
  297. break;
  298. }
  299. }
  300. void draw_speed(Canvas* canvas, MainViewModel* context) {
  301. MainViewModel* model = context;
  302. char str[12];
  303. switch(model->current_mode) {
  304. case FIXED_APERTURE:
  305. if(model->lux > 0 && model->response) {
  306. if(model->speed_val < 1 && model->speed_val > 0) {
  307. snprintf(str, sizeof(str), ":1/%.0f", 1 / (double)normalizeTime(model->speed_val));
  308. } else {
  309. snprintf(str, sizeof(str), ":%.0f", (double)normalizeTime(model->speed_val));
  310. }
  311. } else {
  312. snprintf(str, sizeof(str), " ---");
  313. }
  314. canvas_draw_str_aligned(canvas, 27, 34, AlignLeft, AlignTop, str);
  315. break;
  316. case FIXED_SPEED:
  317. if(model->response) {
  318. if(model->speed < SPEED_1S) {
  319. snprintf(str, sizeof(str), ":1/%.0f", 1 / (double)speed_numbers[model->speed]);
  320. } else {
  321. snprintf(str, sizeof(str), ":%.0f", (double)speed_numbers[model->speed]);
  322. }
  323. } else {
  324. snprintf(str, sizeof(str), " ---");
  325. }
  326. canvas_draw_str_aligned(canvas, 27, 34, AlignLeft, AlignTop, str);
  327. break;
  328. default:
  329. break;
  330. }
  331. }
  332. void draw_mode_indicator(Canvas* canvas, MainViewModel* context) {
  333. MainViewModel* model = context;
  334. switch(model->current_mode) {
  335. case FIXED_SPEED:
  336. canvas_set_font(canvas, FontBigNumbers);
  337. canvas_draw_str_aligned(canvas, 3, 36, AlignLeft, AlignTop, "*");
  338. break;
  339. case FIXED_APERTURE:
  340. canvas_set_font(canvas, FontBigNumbers);
  341. canvas_draw_str_aligned(canvas, 3, 17, AlignLeft, AlignTop, "*");
  342. break;
  343. default:
  344. break;
  345. }
  346. }
  347. void draw_nd_number(Canvas* canvas, MainViewModel* context) {
  348. MainViewModel* model = context;
  349. char str[9];
  350. if(model->response) {
  351. snprintf(str, sizeof(str), "ND: %d", nd_numbers[model->nd]);
  352. } else {
  353. snprintf(str, sizeof(str), "ND: ---");
  354. }
  355. canvas_draw_str_aligned(canvas, 87, 20, AlignLeft, AlignBottom, str);
  356. }
  357. void draw_EV_number(Canvas* canvas, MainViewModel* context) {
  358. MainViewModel* model = context;
  359. char str[7];
  360. if(model->lux > 0 && model->response) {
  361. snprintf(str, sizeof(str), "EV: %1.0f", (double)model->EV);
  362. canvas_draw_str_aligned(canvas, 87, 29, AlignLeft, AlignBottom, str);
  363. } else {
  364. canvas_draw_str_aligned(canvas, 87, 29, AlignLeft, AlignBottom, "EV: --");
  365. }
  366. }