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