1 /*
2 * Copyright (c) 2024 Glenn Andrews
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8 #include <zephyr/smf.h>
9 #include <stdbool.h>
10 #include "smf_calculator_thread.h"
11 #include <zephyr/logging/log.h>
12 #include <string.h>
13 #include <stdlib.h>
14 #include "main.h"
15 #include <stdio.h>
16
17 LOG_MODULE_REGISTER(smf_thread, LOG_LEVEL_DBG);
18
19 K_MSGQ_DEFINE(event_msgq, sizeof(struct calculator_event), 8, 1);
20
21 /* In theory can still overflow. A double can be hundreds of characters long */
22 #define RESULT_STRING_LENGTH 64
23
24 enum display_mode {
25 DISPLAY_OPERAND_1,
26 DISPLAY_OPERAND_2,
27 DISPLAY_RESULT,
28 DISPLAY_ERROR,
29 };
30
31 struct operand {
32 char string[CALCULATOR_STRING_LENGTH];
33 int index;
34 };
35
36 /* User defined object */
37 struct s_object {
38 /* This must be first */
39 struct smf_ctx ctx;
40
41 /* Other state specific data add here */
42 struct calculator_event event;
43
44 struct operand operand_1;
45 struct operand operand_2;
46 char operator_btn;
47 struct operand result;
48 } s_obj;
49
50 static enum display_mode current_display_mode = DISPLAY_OPERAND_1;
51
set_display_mode(enum display_mode mode)52 static void set_display_mode(enum display_mode mode)
53 {
54 current_display_mode = mode;
55 }
56
setup_operand(struct operand * op)57 static void setup_operand(struct operand *op)
58 {
59 /* indexes start at 1 because position 0 is the sign */
60 op->index = 1;
61 op->string[0] = ' '; /* space for sign */
62 op->string[1] = '0'; /* A 0 indicator to be overwritten */
63 op->string[2] = 0x00;
64 }
65
insert(struct operand * op,char digit)66 static int insert(struct operand *op, char digit)
67 {
68 if (op->index >= (CALCULATOR_STRING_LENGTH - 1)) {
69 /* Can't store an extra operand */
70 return -ENOBUFS;
71 }
72 op->string[op->index++] = digit;
73 op->string[op->index] = 0x00;
74
75 return 0;
76 }
77
negate(struct operand * op)78 static void negate(struct operand *op)
79 {
80 if (op->string[0] == ' ') {
81 op->string[0] = '-';
82 } else {
83 op->string[0] = ' ';
84 }
85 }
86
87 /**
88 * @brief copies one operand struct to another
89 * Assumes src operand is well-formed
90 */
copy_operand(struct operand * dest,struct operand * src)91 static void copy_operand(struct operand *dest, struct operand *src)
92 {
93 strncpy(dest->string, src->string, CALCULATOR_STRING_LENGTH);
94 dest->index = src->index;
95 }
96
calculate_result(struct s_object * s)97 static int calculate_result(struct s_object *s)
98 {
99 double operand_1 = strtod(s->operand_1.string, NULL);
100 double operand_2 = strtod(s->operand_2.string, NULL);
101 double result;
102 char result_string[RESULT_STRING_LENGTH];
103
104 switch (s->operator_btn) {
105 case '+':
106 result = operand_1 + operand_2;
107 break;
108 case '-':
109 result = operand_1 - operand_2;
110 break;
111 case '*':
112 result = operand_1 * operand_2;
113 break;
114 case '/':
115 if (operand_2 != 0.0) {
116 result = operand_1 / operand_2;
117 } else {
118 /* division by zero */
119 return -1;
120 }
121 break;
122 default:
123 /* unknown operator */
124 return -1;
125 }
126
127 snprintf(result_string, RESULT_STRING_LENGTH, "% f", result);
128
129 /* Strip off trailing zeroes from result */
130 for (int i = strlen(result_string) - 1; i >= 0; i--) {
131 if (result_string[i] != '0') {
132 /* was it .000? */
133 if (result_string[i] == '.') {
134 result_string[i] = 0x00;
135 } else {
136 result_string[i + 1] = 0x00;
137 }
138 break;
139 }
140 }
141
142 /* copy to the result operand */
143 strncpy(s->result.string, result_string, CALCULATOR_STRING_LENGTH - 1);
144 s->result.string[CALCULATOR_STRING_LENGTH - 1] = 0x00;
145 s->result.index = strlen(s->result.string);
146
147 return 0;
148 }
149
150 /* copy result into operand_1 and clear operand_2 to allow chaining calculations */
chain_calculations(struct s_object * s)151 static void chain_calculations(struct s_object *s)
152 {
153 copy_operand(&s->operand_1, &s->result);
154 setup_operand(&s->operand_2);
155 }
156
157 /* Declaration of possible states */
158 enum demo_states {
159 STATE_ON,
160 STATE_READY,
161 STATE_RESULT,
162 STATE_BEGIN,
163 STATE_NEGATED_1,
164 STATE_OPERAND_1,
165 STATE_ZERO_1,
166 STATE_INT_1,
167 STATE_FRAC_1,
168 STATE_NEGATED_2,
169 STATE_OPERAND_2,
170 STATE_ZERO_2,
171 STATE_INT_2,
172 STATE_FRAC_2,
173 STATE_OP_ENTERED,
174 STATE_OP_CHAINED,
175 STATE_OP_NORMAL,
176 STATE_ERROR,
177 };
178
179 /* Forward declaration of state table */
180 static const struct smf_state calculator_states[];
181
on_entry(void * obj)182 static void on_entry(void *obj)
183 {
184 struct s_object *s = (struct s_object *)obj;
185
186 LOG_DBG("");
187
188 setup_operand(&s->operand_1);
189 setup_operand(&s->operand_2);
190 setup_operand(&s->result);
191 s->operator_btn = 0x00;
192 }
193
on_run(void * obj)194 static enum smf_state_result on_run(void *obj)
195 {
196 struct s_object *s = (struct s_object *)obj;
197
198 LOG_DBG("");
199
200 switch (s->event.event_id) {
201 case CANCEL_BUTTON:
202 smf_set_state(&s->ctx, &calculator_states[STATE_ON]);
203 break;
204 default:
205 /* Let parent state handle it: shuts up compiler warning */
206 break;
207 }
208 return SMF_EVENT_PROPAGATE;
209 }
210
ready_run(void * obj)211 static enum smf_state_result ready_run(void *obj)
212 {
213 struct s_object *s = (struct s_object *)obj;
214
215 LOG_DBG("");
216
217 switch (s->event.event_id) {
218 case DECIMAL_POINT:
219 insert(&s->operand_1, s->event.operand);
220 smf_set_state(&s->ctx, &calculator_states[STATE_FRAC_1]);
221 break;
222 case DIGIT_1_9:
223 insert(&s->operand_1, s->event.operand);
224 smf_set_state(&s->ctx, &calculator_states[STATE_INT_1]);
225 break;
226 case DIGIT_0:
227 /* Don't insert the leading zero */
228 smf_set_state(&s->ctx, &calculator_states[STATE_ZERO_1]);
229 break;
230 case OPERATOR:
231 s->operator_btn = s->event.operand;
232 smf_set_state(&s->ctx, &calculator_states[STATE_OP_CHAINED]);
233 break;
234 default:
235 /* Let parent state handle it: shuts up compiler warning */
236 break;
237 }
238 return SMF_EVENT_PROPAGATE;
239 }
240
result_entry(void * obj)241 static void result_entry(void *obj)
242 {
243 LOG_DBG("");
244 set_display_mode(DISPLAY_RESULT);
245 }
246
result_run(void * obj)247 static enum smf_state_result result_run(void *obj)
248 {
249 LOG_DBG("");
250 /* Ready state handles the exits from this state */
251 return SMF_EVENT_PROPAGATE;
252 }
253
begin_entry(void * obj)254 static void begin_entry(void *obj)
255 {
256 LOG_DBG("");
257 set_display_mode(DISPLAY_OPERAND_1);
258 }
259
begin_run(void * obj)260 static enum smf_state_result begin_run(void *obj)
261 {
262 struct s_object *s = (struct s_object *)obj;
263
264 LOG_DBG("");
265
266 switch (s->event.event_id) {
267 case OPERATOR:
268 /* We only care about negative */
269 if (s->event.operand == '-') {
270 smf_set_state(&s->ctx, &calculator_states[STATE_NEGATED_1]);
271 }
272 break;
273 default:
274 /* Let parent state handle it: shuts up compiler warning */
275 break;
276 }
277 return SMF_EVENT_PROPAGATE;
278 }
279
negated_1_entry(void * obj)280 static void negated_1_entry(void *obj)
281 {
282 struct s_object *s = (struct s_object *)obj;
283
284 LOG_DBG("");
285
286 negate(&s->operand_1);
287 }
288
negated_1_run(void * obj)289 static enum smf_state_result negated_1_run(void *obj)
290 {
291 struct s_object *s = (struct s_object *)obj;
292
293 LOG_DBG("");
294
295 switch (s->event.event_id) {
296 case DECIMAL_POINT:
297 insert(&s->operand_1, s->event.operand);
298 smf_set_state(&s->ctx, &calculator_states[STATE_FRAC_1]);
299 break;
300 case DIGIT_1_9:
301 insert(&s->operand_1, s->event.operand);
302 smf_set_state(&s->ctx, &calculator_states[STATE_INT_1]);
303 break;
304 case DIGIT_0:
305 /* Don't need to insert leading zeroes */
306 smf_set_state(&s->ctx, &calculator_states[STATE_ZERO_1]);
307 break;
308 case OPERATOR:
309 /* We only care about ignoring the negative key */
310 if (s->event.operand == '-') {
311 return SMF_EVENT_HANDLED;
312 }
313 break;
314 case CANCEL_ENTRY:
315 setup_operand(&s->operand_1);
316 smf_set_state(&s->ctx, &calculator_states[STATE_BEGIN]);
317 break;
318 default:
319 /* Let parent state handle it: shuts up compiler warning */
320 break;
321 }
322 return SMF_EVENT_PROPAGATE;
323 }
324
operand_1_entry(void * obj)325 static void operand_1_entry(void *obj)
326 {
327 LOG_DBG("");
328 set_display_mode(DISPLAY_OPERAND_1);
329 }
330
operand_1_run(void * obj)331 static enum smf_state_result operand_1_run(void *obj)
332 {
333 struct s_object *s = (struct s_object *)obj;
334
335 LOG_DBG("");
336
337 switch (s->event.event_id) {
338 case OPERATOR:
339 s->operator_btn = s->event.operand;
340 smf_set_state(&s->ctx, &calculator_states[STATE_OP_ENTERED]);
341 break;
342 case CANCEL_ENTRY:
343 setup_operand(&s->operand_1);
344 smf_set_state(&s->ctx, &calculator_states[STATE_READY]);
345 break;
346 default:
347 /* Let parent state handle it: shuts up compiler warning */
348 break;
349 }
350 return SMF_EVENT_PROPAGATE;
351 }
352
zero_1_run(void * obj)353 static enum smf_state_result zero_1_run(void *obj)
354 {
355 struct s_object *s = (struct s_object *)obj;
356
357 LOG_DBG("");
358
359 switch (s->event.event_id) {
360 case DIGIT_0:
361 /* We ignore leading zeroes */
362 return SMF_EVENT_HANDLED;
363 case DIGIT_1_9:
364 insert(&s->operand_1, s->event.operand);
365 smf_set_state(&s->ctx, &calculator_states[STATE_INT_1]);
366 break;
367 case DECIMAL_POINT:
368 insert(&s->operand_1, s->event.operand);
369 smf_set_state(&s->ctx, &calculator_states[STATE_FRAC_1]);
370 break;
371 default:
372 /* Let parent state handle it: shuts up compiler warning */
373 break;
374 }
375 return SMF_EVENT_PROPAGATE;
376 }
377
int_1_run(void * obj)378 static enum smf_state_result int_1_run(void *obj)
379 {
380 struct s_object *s = (struct s_object *)obj;
381
382 LOG_DBG("");
383
384 switch (s->event.event_id) {
385 case DIGIT_0:
386 case DIGIT_1_9:
387 insert(&s->operand_1, s->event.operand);
388 return SMF_EVENT_HANDLED;
389 case DECIMAL_POINT:
390 insert(&s->operand_1, s->event.operand);
391 smf_set_state(&s->ctx, &calculator_states[STATE_FRAC_1]);
392 break;
393 default:
394 /* Let parent state handle it: shuts up compiler warning */
395 break;
396 }
397 return SMF_EVENT_PROPAGATE;
398 }
399
frac_1_run(void * obj)400 static enum smf_state_result frac_1_run(void *obj)
401 {
402 struct s_object *s = (struct s_object *)obj;
403
404 LOG_DBG("");
405
406 switch (s->event.event_id) {
407 case DIGIT_0:
408 case DIGIT_1_9:
409 insert(&s->operand_1, s->event.operand);
410 return SMF_EVENT_HANDLED;
411 case DECIMAL_POINT:
412 /* Ignore further decimal points */
413 return SMF_EVENT_HANDLED;
414 default:
415 /* Let parent state handle it: shuts up compiler warning */
416 break;
417 }
418 return SMF_EVENT_PROPAGATE;
419 }
420
negated_2_entry(void * obj)421 static void negated_2_entry(void *obj)
422 {
423 struct s_object *s = (struct s_object *)obj;
424
425 LOG_DBG("");
426
427 negate(&s->operand_2);
428 }
429
negated_2_run(void * obj)430 static enum smf_state_result negated_2_run(void *obj)
431 {
432 struct s_object *s = (struct s_object *)obj;
433
434 LOG_DBG("");
435
436 switch (s->event.event_id) {
437 case DECIMAL_POINT:
438 insert(&s->operand_2, s->event.operand);
439 smf_set_state(&s->ctx, &calculator_states[STATE_FRAC_2]);
440 break;
441 case DIGIT_1_9:
442 insert(&s->operand_2, s->event.operand);
443 smf_set_state(&s->ctx, &calculator_states[STATE_INT_2]);
444 break;
445 case DIGIT_0:
446 /* Don't insert the leading zero */
447 smf_set_state(&s->ctx, &calculator_states[STATE_ZERO_2]);
448 break;
449 case OPERATOR:
450 /* We only care about ignoring the negative key */
451 if (s->event.operand == '-') {
452 return SMF_EVENT_HANDLED;
453 }
454 break;
455 case CANCEL_ENTRY:
456 setup_operand(&s->operand_2);
457 smf_set_state(&s->ctx, &calculator_states[STATE_OP_ENTERED]);
458 break;
459 default:
460 /* Let parent state handle it: shuts up compiler warning */
461 break;
462 }
463 return SMF_EVENT_PROPAGATE;
464 }
465
operand_2_entry(void * obj)466 static void operand_2_entry(void *obj)
467 {
468 LOG_DBG("");
469 set_display_mode(DISPLAY_OPERAND_2);
470 }
471
operand_2_run(void * obj)472 static enum smf_state_result operand_2_run(void *obj)
473 {
474 struct s_object *s = (struct s_object *)obj;
475
476 LOG_DBG("");
477
478 switch (s->event.event_id) {
479 case CANCEL_ENTRY:
480 setup_operand(&s->operand_2);
481 smf_set_state(&s->ctx, &calculator_states[STATE_OP_ENTERED]);
482 break;
483 case OPERATOR:
484 if (calculate_result(s) == 0) {
485 /* move result into operand_1 to allow chaining */
486 chain_calculations(s);
487 /* Copy in new operand */
488 s->operator_btn = s->event.operand;
489 smf_set_state(&s->ctx, &calculator_states[STATE_OP_CHAINED]);
490 } else {
491 smf_set_state(&s->ctx, &calculator_states[STATE_ERROR]);
492 }
493 break;
494 case EQUALS:
495 if (calculate_result(s) == 0) {
496 /* move result into operand_1 to allow chaining */
497 chain_calculations(s);
498 smf_set_state(&s->ctx, &calculator_states[STATE_RESULT]);
499 } else {
500 smf_set_state(&s->ctx, &calculator_states[STATE_ERROR]);
501 }
502 break;
503 default:
504 /* Let parent state handle it: shuts up compiler warning */
505 break;
506 }
507 return SMF_EVENT_PROPAGATE;
508 }
509
zero_2_run(void * obj)510 static enum smf_state_result zero_2_run(void *obj)
511 {
512 struct s_object *s = (struct s_object *)obj;
513
514 LOG_DBG("");
515
516 switch (s->event.event_id) {
517 case DIGIT_0:
518 /* We ignore leading zeroes */
519 return SMF_EVENT_HANDLED;
520 case DIGIT_1_9:
521 insert(&s->operand_2, s->event.operand);
522 smf_set_state(&s->ctx, &calculator_states[STATE_INT_2]);
523 break;
524 case DECIMAL_POINT:
525 insert(&s->operand_2, s->event.operand);
526 smf_set_state(&s->ctx, &calculator_states[STATE_FRAC_2]);
527 break;
528 default:
529 /* Let parent state handle it: shuts up compiler warning */
530 break;
531 }
532 return SMF_EVENT_PROPAGATE;
533 }
534
int_2_run(void * obj)535 static enum smf_state_result int_2_run(void *obj)
536 {
537 struct s_object *s = (struct s_object *)obj;
538
539 LOG_DBG("");
540
541 switch (s->event.event_id) {
542 case DIGIT_0:
543 case DIGIT_1_9:
544 insert(&s->operand_2, s->event.operand);
545 return SMF_EVENT_HANDLED;
546 case DECIMAL_POINT:
547 insert(&s->operand_2, s->event.operand);
548 smf_set_state(&s->ctx, &calculator_states[STATE_FRAC_2]);
549 break;
550 default:
551 /* Let parent state handle it: shuts up compiler warning */
552 break;
553 }
554 return SMF_EVENT_PROPAGATE;
555 }
556
frac_2_run(void * obj)557 static enum smf_state_result frac_2_run(void *obj)
558 {
559 struct s_object *s = (struct s_object *)obj;
560
561 LOG_DBG("");
562
563 switch (s->event.event_id) {
564 case DIGIT_0:
565 case DIGIT_1_9:
566 insert(&s->operand_2, s->event.operand);
567 return SMF_EVENT_HANDLED;
568 case DECIMAL_POINT:
569 /* Ignore further decimal points */
570 return SMF_EVENT_HANDLED;
571 default:
572 /* Let parent state handle it: shuts up compiler warning */
573 break;
574 }
575 return SMF_EVENT_PROPAGATE;
576 }
577
op_entered_run(void * obj)578 static enum smf_state_result op_entered_run(void *obj)
579 {
580 struct s_object *s = (struct s_object *)obj;
581
582 LOG_DBG("");
583
584 switch (s->event.event_id) {
585 case DIGIT_0:
586 /* Don't insert the leading zero */
587 smf_set_state(&s->ctx, &calculator_states[STATE_ZERO_2]);
588 break;
589 case DIGIT_1_9:
590 insert(&s->operand_2, s->event.operand);
591 smf_set_state(&s->ctx, &calculator_states[STATE_INT_2]);
592 break;
593 case DECIMAL_POINT:
594 insert(&s->operand_2, s->event.operand);
595 smf_set_state(&s->ctx, &calculator_states[STATE_FRAC_2]);
596 break;
597 case OPERATOR:
598 /* We only care about negative */
599 if (s->event.operand == '-') {
600 smf_set_state(&s->ctx, &calculator_states[STATE_NEGATED_2]);
601 }
602 break;
603 default:
604 /* Let parent state handle it: shuts up compiler warning */
605 break;
606 }
607 return SMF_EVENT_PROPAGATE;
608 }
609
op_chained_entry(void * obj)610 static void op_chained_entry(void *obj)
611 {
612 LOG_DBG("");
613 set_display_mode(DISPLAY_OPERAND_1);
614 }
615
op_normal_entry(void * obj)616 static void op_normal_entry(void *obj)
617 {
618 LOG_DBG("");
619 set_display_mode(DISPLAY_OPERAND_2);
620 }
621
error_entry(void * obj)622 static void error_entry(void *obj)
623 {
624 LOG_DBG("");
625 set_display_mode(DISPLAY_ERROR);
626 }
627
628 /* State storage: handler functions, parent states and initial transition states */
629 /* clang-format off */
630 static const struct smf_state calculator_states[] = {
631 [STATE_ON] = SMF_CREATE_STATE(on_entry, on_run, NULL,
632 NULL, &calculator_states[STATE_READY]),
633 [STATE_READY] = SMF_CREATE_STATE(NULL, ready_run, NULL,
634 &calculator_states[STATE_ON],
635 &calculator_states[STATE_BEGIN]),
636 [STATE_RESULT] = SMF_CREATE_STATE(result_entry, result_run,
637 NULL, &calculator_states[STATE_READY], NULL),
638 [STATE_BEGIN] = SMF_CREATE_STATE(begin_entry, begin_run, NULL,
639 &calculator_states[STATE_READY], NULL),
640 [STATE_NEGATED_1] = SMF_CREATE_STATE(negated_1_entry, negated_1_run, NULL,
641 &calculator_states[STATE_ON], NULL),
642 [STATE_OPERAND_1] = SMF_CREATE_STATE(operand_1_entry, operand_1_run, NULL,
643 &calculator_states[STATE_ON], NULL),
644 [STATE_ZERO_1] = SMF_CREATE_STATE(NULL, zero_1_run, NULL,
645 &calculator_states[STATE_OPERAND_1], NULL),
646 [STATE_INT_1] = SMF_CREATE_STATE(NULL, int_1_run, NULL,
647 &calculator_states[STATE_OPERAND_1], NULL),
648 [STATE_FRAC_1] = SMF_CREATE_STATE(NULL, frac_1_run, NULL,
649 &calculator_states[STATE_OPERAND_1], NULL),
650 [STATE_NEGATED_2] = SMF_CREATE_STATE(negated_2_entry, negated_2_run, NULL,
651 &calculator_states[STATE_ON], NULL),
652 [STATE_OPERAND_2] = SMF_CREATE_STATE(operand_2_entry, operand_2_run, NULL,
653 &calculator_states[STATE_ON], NULL),
654 [STATE_ZERO_2] = SMF_CREATE_STATE(NULL, zero_2_run, NULL,
655 &calculator_states[STATE_OPERAND_2], NULL),
656 [STATE_INT_2] = SMF_CREATE_STATE(NULL, int_2_run, NULL,
657 &calculator_states[STATE_OPERAND_2], NULL),
658 [STATE_FRAC_2] = SMF_CREATE_STATE(NULL, frac_2_run, NULL,
659 &calculator_states[STATE_OPERAND_2], NULL),
660 [STATE_OP_ENTERED] = SMF_CREATE_STATE(NULL, op_entered_run, NULL,
661 &calculator_states[STATE_ON],
662 &calculator_states[STATE_OP_NORMAL]),
663 [STATE_OP_CHAINED] = SMF_CREATE_STATE(op_chained_entry, NULL, NULL,
664 &calculator_states[STATE_OP_ENTERED], NULL),
665 [STATE_OP_NORMAL] = SMF_CREATE_STATE(op_normal_entry, NULL, NULL,
666 &calculator_states[STATE_OP_ENTERED], NULL),
667 [STATE_ERROR] = SMF_CREATE_STATE(error_entry, NULL, NULL,
668 &calculator_states[STATE_ON], NULL),
669 };
670 /* clang-format on */
671
post_calculator_event(struct calculator_event * event,k_timeout_t timeout)672 int post_calculator_event(struct calculator_event *event, k_timeout_t timeout)
673 {
674 return k_msgq_put(&event_msgq, event, timeout);
675 }
676
output_display(void)677 static void output_display(void)
678 {
679 char *output;
680
681 switch (current_display_mode) {
682 case DISPLAY_OPERAND_1:
683 output = s_obj.operand_1.string;
684 break;
685 case DISPLAY_OPERAND_2:
686 output = s_obj.operand_2.string;
687 break;
688 case DISPLAY_RESULT:
689 output = s_obj.result.string;
690 break;
691 case DISPLAY_ERROR:
692 output = "ERROR";
693 break;
694 default:
695 output = "";
696 }
697 update_display(output);
698 }
699
smf_calculator_thread(void * arg1,void * arg2,void * arg3)700 static void smf_calculator_thread(void *arg1, void *arg2, void *arg3)
701 {
702 smf_set_initial(SMF_CTX(&s_obj), &calculator_states[STATE_ON]);
703 while (1) {
704 int rc;
705
706 rc = k_msgq_get(&event_msgq, &s_obj.event, K_FOREVER);
707 if (rc != 0) {
708 continue;
709 }
710 /* run state machine with given message */
711
712 LOG_INF("Received %c from GUI", s_obj.event.operand);
713 int ret = smf_run_state(SMF_CTX(&s_obj));
714
715 if (ret) {
716 /* State machine was terminated if a non-zero value is returned */
717 break;
718 }
719
720 output_display();
721 LOG_INF("op1=%s, op=%c op2=%s res=%s", s_obj.operand_1.string, s_obj.operator_btn,
722 s_obj.operand_2.string, s_obj.result.string);
723 }
724 }
725
726 K_THREAD_DEFINE(smf_calculator, SMF_THREAD_STACK_SIZE, smf_calculator_thread, NULL, NULL, NULL,
727 SMF_THREAD_PRIORITY, 0, 0);
728