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 void 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 }
209 
ready_run(void * obj)210 static void ready_run(void *obj)
211 {
212 	struct s_object *s = (struct s_object *)obj;
213 
214 	LOG_DBG("");
215 
216 	switch (s->event.event_id) {
217 	case DECIMAL_POINT:
218 		insert(&s->operand_1, s->event.operand);
219 		smf_set_state(&s->ctx, &calculator_states[STATE_FRAC_1]);
220 		break;
221 	case DIGIT_1_9:
222 		insert(&s->operand_1, s->event.operand);
223 		smf_set_state(&s->ctx, &calculator_states[STATE_INT_1]);
224 		break;
225 	case DIGIT_0:
226 		/* Don't insert the leading zero */
227 		smf_set_state(&s->ctx, &calculator_states[STATE_ZERO_1]);
228 		break;
229 	case OPERATOR:
230 		s->operator_btn = s->event.operand;
231 		smf_set_state(&s->ctx, &calculator_states[STATE_OP_CHAINED]);
232 		break;
233 	default:
234 		/* Let parent state handle it: shuts up compiler warning */
235 		break;
236 	}
237 }
result_entry(void * obj)238 static void result_entry(void *obj)
239 {
240 	LOG_DBG("");
241 	set_display_mode(DISPLAY_RESULT);
242 }
243 
result_run(void * obj)244 static void result_run(void *obj)
245 {
246 	LOG_DBG("");
247 	/* Ready state handles the exits from this state */
248 }
249 
begin_entry(void * obj)250 static void begin_entry(void *obj)
251 {
252 	LOG_DBG("");
253 	set_display_mode(DISPLAY_OPERAND_1);
254 }
255 
begin_run(void * obj)256 static void begin_run(void *obj)
257 {
258 	struct s_object *s = (struct s_object *)obj;
259 
260 	LOG_DBG("");
261 
262 	switch (s->event.event_id) {
263 	case OPERATOR:
264 		/* We only care about negative */
265 		if (s->event.operand == '-') {
266 			smf_set_state(&s->ctx, &calculator_states[STATE_NEGATED_1]);
267 		}
268 		break;
269 	default:
270 		/* Let parent state handle it: shuts up compiler warning */
271 		break;
272 	}
273 }
274 
negated_1_entry(void * obj)275 static void negated_1_entry(void *obj)
276 {
277 	struct s_object *s = (struct s_object *)obj;
278 
279 	LOG_DBG("");
280 
281 	negate(&s->operand_1);
282 }
283 
negated_1_run(void * obj)284 static void negated_1_run(void *obj)
285 {
286 	struct s_object *s = (struct s_object *)obj;
287 
288 	LOG_DBG("");
289 
290 	switch (s->event.event_id) {
291 	case DECIMAL_POINT:
292 		insert(&s->operand_1, s->event.operand);
293 		smf_set_state(&s->ctx, &calculator_states[STATE_FRAC_1]);
294 		break;
295 	case DIGIT_1_9:
296 		insert(&s->operand_1, s->event.operand);
297 		smf_set_state(&s->ctx, &calculator_states[STATE_INT_1]);
298 		break;
299 	case DIGIT_0:
300 		/* Don't need to insert leading zeroes */
301 		smf_set_state(&s->ctx, &calculator_states[STATE_ZERO_1]);
302 		break;
303 	case OPERATOR:
304 		/* We only care about ignoring the negative key */
305 		if (s->event.operand == '-') {
306 			smf_set_handled(&s->ctx);
307 		}
308 		break;
309 	case CANCEL_ENTRY:
310 		setup_operand(&s->operand_1);
311 		smf_set_state(&s->ctx, &calculator_states[STATE_BEGIN]);
312 		break;
313 	default:
314 		/* Let parent state handle it: shuts up compiler warning */
315 		break;
316 	}
317 }
318 
operand_1_entry(void * obj)319 static void operand_1_entry(void *obj)
320 {
321 	LOG_DBG("");
322 	set_display_mode(DISPLAY_OPERAND_1);
323 }
324 
operand_1_run(void * obj)325 static void operand_1_run(void *obj)
326 {
327 	struct s_object *s = (struct s_object *)obj;
328 
329 	LOG_DBG("");
330 
331 	switch (s->event.event_id) {
332 	case OPERATOR:
333 		s->operator_btn = s->event.operand;
334 		smf_set_state(&s->ctx, &calculator_states[STATE_OP_ENTERED]);
335 		break;
336 	case CANCEL_ENTRY:
337 		setup_operand(&s->operand_1);
338 		smf_set_state(&s->ctx, &calculator_states[STATE_READY]);
339 		break;
340 	default:
341 		/* Let parent state handle it: shuts up compiler warning */
342 		break;
343 	}
344 }
345 
zero_1_run(void * obj)346 static void zero_1_run(void *obj)
347 {
348 	struct s_object *s = (struct s_object *)obj;
349 
350 	LOG_DBG("");
351 
352 	switch (s->event.event_id) {
353 	case DIGIT_0:
354 		/* We ignore leading zeroes */
355 		smf_set_handled(&s->ctx);
356 		break;
357 	case DIGIT_1_9:
358 		insert(&s->operand_1, s->event.operand);
359 		smf_set_state(&s->ctx, &calculator_states[STATE_INT_1]);
360 		break;
361 	case DECIMAL_POINT:
362 		insert(&s->operand_1, s->event.operand);
363 		smf_set_state(&s->ctx, &calculator_states[STATE_FRAC_1]);
364 		break;
365 	default:
366 		/* Let parent state handle it: shuts up compiler warning */
367 		break;
368 	}
369 }
370 
int_1_run(void * obj)371 static void int_1_run(void *obj)
372 {
373 	struct s_object *s = (struct s_object *)obj;
374 
375 	LOG_DBG("");
376 
377 	switch (s->event.event_id) {
378 	case DIGIT_0:
379 	case DIGIT_1_9:
380 		insert(&s->operand_1, s->event.operand);
381 		smf_set_handled(&s->ctx);
382 		break;
383 	case DECIMAL_POINT:
384 		insert(&s->operand_1, s->event.operand);
385 		smf_set_state(&s->ctx, &calculator_states[STATE_FRAC_1]);
386 		break;
387 	default:
388 		/* Let parent state handle it: shuts up compiler warning */
389 		break;
390 	}
391 }
392 
frac_1_run(void * obj)393 static void frac_1_run(void *obj)
394 {
395 	struct s_object *s = (struct s_object *)obj;
396 
397 	LOG_DBG("");
398 
399 	switch (s->event.event_id) {
400 	case DIGIT_0:
401 	case DIGIT_1_9:
402 		insert(&s->operand_1, s->event.operand);
403 		smf_set_handled(&s->ctx);
404 		break;
405 	case DECIMAL_POINT:
406 		/* Ignore further decimal points */
407 		smf_set_handled(&s->ctx);
408 		break;
409 	default:
410 		/* Let parent state handle it: shuts up compiler warning */
411 		break;
412 	}
413 }
414 
negated_2_entry(void * obj)415 static void negated_2_entry(void *obj)
416 {
417 	struct s_object *s = (struct s_object *)obj;
418 
419 	LOG_DBG("");
420 
421 	negate(&s->operand_2);
422 }
423 
negated_2_run(void * obj)424 static void negated_2_run(void *obj)
425 {
426 	struct s_object *s = (struct s_object *)obj;
427 
428 	LOG_DBG("");
429 
430 	switch (s->event.event_id) {
431 	case DECIMAL_POINT:
432 		insert(&s->operand_2, s->event.operand);
433 		smf_set_state(&s->ctx, &calculator_states[STATE_FRAC_2]);
434 		break;
435 	case DIGIT_1_9:
436 		insert(&s->operand_2, s->event.operand);
437 		smf_set_state(&s->ctx, &calculator_states[STATE_INT_2]);
438 		break;
439 	case DIGIT_0:
440 		/* Don't insert the leading zero */
441 		smf_set_state(&s->ctx, &calculator_states[STATE_ZERO_2]);
442 		break;
443 	case OPERATOR:
444 		/* We only care about ignoring the negative key */
445 		if (s->event.operand == '-') {
446 			smf_set_handled(&s->ctx);
447 		}
448 		break;
449 	case CANCEL_ENTRY:
450 		setup_operand(&s->operand_2);
451 		smf_set_state(&s->ctx, &calculator_states[STATE_OP_ENTERED]);
452 		break;
453 	default:
454 		/* Let parent state handle it: shuts up compiler warning */
455 		break;
456 	}
457 }
458 
operand_2_entry(void * obj)459 static void operand_2_entry(void *obj)
460 {
461 	LOG_DBG("");
462 	set_display_mode(DISPLAY_OPERAND_2);
463 }
464 
operand_2_run(void * obj)465 static void operand_2_run(void *obj)
466 {
467 	struct s_object *s = (struct s_object *)obj;
468 
469 	LOG_DBG("");
470 
471 	switch (s->event.event_id) {
472 	case CANCEL_ENTRY:
473 		setup_operand(&s->operand_2);
474 		smf_set_state(&s->ctx, &calculator_states[STATE_OP_ENTERED]);
475 		break;
476 	case OPERATOR:
477 		if (calculate_result(s) == 0) {
478 			/* move result into operand_1 to allow chaining */
479 			chain_calculations(s);
480 			/* Copy in new operand */
481 			s->operator_btn = s->event.operand;
482 			smf_set_state(&s->ctx, &calculator_states[STATE_OP_CHAINED]);
483 		} else {
484 			smf_set_state(&s->ctx, &calculator_states[STATE_ERROR]);
485 		}
486 		break;
487 	case EQUALS:
488 		if (calculate_result(s) == 0) {
489 			/* move result into operand_1 to allow chaining */
490 			chain_calculations(s);
491 			smf_set_state(&s->ctx, &calculator_states[STATE_RESULT]);
492 		} else {
493 			smf_set_state(&s->ctx, &calculator_states[STATE_ERROR]);
494 		}
495 		break;
496 	default:
497 		/* Let parent state handle it: shuts up compiler warning */
498 		break;
499 	}
500 }
501 
zero_2_run(void * obj)502 static void zero_2_run(void *obj)
503 {
504 	struct s_object *s = (struct s_object *)obj;
505 
506 	LOG_DBG("");
507 
508 	switch (s->event.event_id) {
509 	case DIGIT_0:
510 		/* We ignore leading zeroes */
511 		smf_set_handled(&s->ctx);
512 		break;
513 	case DIGIT_1_9:
514 		insert(&s->operand_2, s->event.operand);
515 		smf_set_state(&s->ctx, &calculator_states[STATE_INT_2]);
516 		break;
517 	case DECIMAL_POINT:
518 		insert(&s->operand_2, s->event.operand);
519 		smf_set_state(&s->ctx, &calculator_states[STATE_FRAC_2]);
520 		break;
521 	default:
522 		/* Let parent state handle it: shuts up compiler warning */
523 		break;
524 	}
525 }
526 
int_2_run(void * obj)527 static void int_2_run(void *obj)
528 {
529 	struct s_object *s = (struct s_object *)obj;
530 
531 	LOG_DBG("");
532 
533 	switch (s->event.event_id) {
534 	case DIGIT_0:
535 	case DIGIT_1_9:
536 		insert(&s->operand_2, s->event.operand);
537 		smf_set_handled(&s->ctx);
538 		break;
539 	case DECIMAL_POINT:
540 		insert(&s->operand_2, s->event.operand);
541 		smf_set_state(&s->ctx, &calculator_states[STATE_FRAC_2]);
542 		break;
543 	default:
544 		/* Let parent state handle it: shuts up compiler warning */
545 		break;
546 	}
547 }
548 
frac_2_run(void * obj)549 static void frac_2_run(void *obj)
550 {
551 	struct s_object *s = (struct s_object *)obj;
552 
553 	LOG_DBG("");
554 
555 	switch (s->event.event_id) {
556 	case DIGIT_0:
557 	case DIGIT_1_9:
558 		insert(&s->operand_2, s->event.operand);
559 		smf_set_handled(&s->ctx);
560 		break;
561 	case DECIMAL_POINT:
562 		/* Ignore further decimal points */
563 		smf_set_handled(&s->ctx);
564 		break;
565 	default:
566 		/* Let parent state handle it: shuts up compiler warning */
567 		break;
568 	}
569 }
570 
op_entered_run(void * obj)571 static void op_entered_run(void *obj)
572 {
573 	struct s_object *s = (struct s_object *)obj;
574 
575 	LOG_DBG("");
576 
577 	switch (s->event.event_id) {
578 	case DIGIT_0:
579 		/* Don't insert the leading zero */
580 		smf_set_state(&s->ctx, &calculator_states[STATE_ZERO_2]);
581 		break;
582 	case DIGIT_1_9:
583 		insert(&s->operand_2, s->event.operand);
584 		smf_set_state(&s->ctx, &calculator_states[STATE_INT_2]);
585 		break;
586 	case DECIMAL_POINT:
587 		insert(&s->operand_2, s->event.operand);
588 		smf_set_state(&s->ctx, &calculator_states[STATE_FRAC_2]);
589 		break;
590 	case OPERATOR:
591 		/* We only care about negative */
592 		if (s->event.operand == '-') {
593 			smf_set_state(&s->ctx, &calculator_states[STATE_NEGATED_2]);
594 		}
595 		break;
596 	default:
597 		/* Let parent state handle it: shuts up compiler warning */
598 		break;
599 	}
600 }
601 
op_chained_entry(void * obj)602 static void op_chained_entry(void *obj)
603 {
604 	LOG_DBG("");
605 	set_display_mode(DISPLAY_OPERAND_1);
606 }
607 
op_normal_entry(void * obj)608 static void op_normal_entry(void *obj)
609 {
610 	LOG_DBG("");
611 	set_display_mode(DISPLAY_OPERAND_2);
612 }
613 
error_entry(void * obj)614 static void error_entry(void *obj)
615 {
616 	LOG_DBG("");
617 	set_display_mode(DISPLAY_ERROR);
618 }
619 
620 /* State storage: handler functions, parent states and initial transition states */
621 /* clang-format off */
622 static const struct smf_state calculator_states[] = {
623 	[STATE_ON] =         SMF_CREATE_STATE(on_entry, on_run, NULL,
624 						NULL, &calculator_states[STATE_READY]),
625 	[STATE_READY] =      SMF_CREATE_STATE(NULL, ready_run, NULL,
626 						&calculator_states[STATE_ON],
627 						&calculator_states[STATE_BEGIN]),
628 	[STATE_RESULT] =     SMF_CREATE_STATE(result_entry, result_run,
629 						NULL, &calculator_states[STATE_READY], NULL),
630 	[STATE_BEGIN] =      SMF_CREATE_STATE(begin_entry, begin_run, NULL,
631 						&calculator_states[STATE_READY], NULL),
632 	[STATE_NEGATED_1] =  SMF_CREATE_STATE(negated_1_entry, negated_1_run, NULL,
633 						&calculator_states[STATE_ON], NULL),
634 	[STATE_OPERAND_1] =  SMF_CREATE_STATE(operand_1_entry, operand_1_run, NULL,
635 						&calculator_states[STATE_ON], NULL),
636 	[STATE_ZERO_1] =     SMF_CREATE_STATE(NULL, zero_1_run, NULL,
637 						&calculator_states[STATE_OPERAND_1], NULL),
638 	[STATE_INT_1] =      SMF_CREATE_STATE(NULL, int_1_run, NULL,
639 						&calculator_states[STATE_OPERAND_1], NULL),
640 	[STATE_FRAC_1] =     SMF_CREATE_STATE(NULL, frac_1_run, NULL,
641 						&calculator_states[STATE_OPERAND_1], NULL),
642 	[STATE_NEGATED_2] =  SMF_CREATE_STATE(negated_2_entry, negated_2_run, NULL,
643 						&calculator_states[STATE_ON], NULL),
644 	[STATE_OPERAND_2] =  SMF_CREATE_STATE(operand_2_entry, operand_2_run, NULL,
645 						&calculator_states[STATE_ON], NULL),
646 	[STATE_ZERO_2] =     SMF_CREATE_STATE(NULL, zero_2_run, NULL,
647 						&calculator_states[STATE_OPERAND_2], NULL),
648 	[STATE_INT_2] =      SMF_CREATE_STATE(NULL, int_2_run, NULL,
649 						&calculator_states[STATE_OPERAND_2], NULL),
650 	[STATE_FRAC_2] =     SMF_CREATE_STATE(NULL, frac_2_run, NULL,
651 						&calculator_states[STATE_OPERAND_2], NULL),
652 	[STATE_OP_ENTERED] = SMF_CREATE_STATE(NULL, op_entered_run, NULL,
653 						&calculator_states[STATE_ON],
654 						&calculator_states[STATE_OP_NORMAL]),
655 	[STATE_OP_CHAINED] = SMF_CREATE_STATE(op_chained_entry, NULL, NULL,
656 						&calculator_states[STATE_OP_ENTERED], NULL),
657 	[STATE_OP_NORMAL] =  SMF_CREATE_STATE(op_normal_entry, NULL, NULL,
658 						&calculator_states[STATE_OP_ENTERED], NULL),
659 	[STATE_ERROR] =      SMF_CREATE_STATE(error_entry, NULL, NULL,
660 						&calculator_states[STATE_ON], NULL),
661 };
662 /* clang-format on */
663 
post_calculator_event(struct calculator_event * event,k_timeout_t timeout)664 int post_calculator_event(struct calculator_event *event, k_timeout_t timeout)
665 {
666 	return k_msgq_put(&event_msgq, event, timeout);
667 }
668 
output_display(void)669 static void output_display(void)
670 {
671 	char *output;
672 
673 	switch (current_display_mode) {
674 	case DISPLAY_OPERAND_1:
675 		output = s_obj.operand_1.string;
676 		break;
677 	case DISPLAY_OPERAND_2:
678 		output = s_obj.operand_2.string;
679 		break;
680 	case DISPLAY_RESULT:
681 		output = s_obj.result.string;
682 		break;
683 	case DISPLAY_ERROR:
684 		output = "ERROR";
685 		break;
686 	default:
687 		output = "";
688 	}
689 	update_display(output);
690 }
691 
smf_calculator_thread(void * arg1,void * arg2,void * arg3)692 static void smf_calculator_thread(void *arg1, void *arg2, void *arg3)
693 {
694 	smf_set_initial(SMF_CTX(&s_obj), &calculator_states[STATE_ON]);
695 	while (1) {
696 		int rc;
697 
698 		rc = k_msgq_get(&event_msgq, &s_obj.event, K_FOREVER);
699 		if (rc != 0) {
700 			continue;
701 		}
702 		/* run state machine with given message */
703 
704 		LOG_INF("Received %c from GUI", s_obj.event.operand);
705 		int ret = smf_run_state(SMF_CTX(&s_obj));
706 
707 		if (ret) {
708 			/* State machine was terminated if a non-zero value is returned */
709 			break;
710 		}
711 
712 		output_display();
713 		LOG_INF("op1=%s, op=%c op2=%s res=%s", s_obj.operand_1.string, s_obj.operator_btn,
714 			s_obj.operand_2.string, s_obj.result.string);
715 	}
716 }
717 
718 K_THREAD_DEFINE(smf_calculator, SMF_THREAD_STACK_SIZE, smf_calculator_thread, NULL, NULL, NULL,
719 		SMF_THREAD_PRIORITY, 0, 0);
720