@@ -34,7 +34,7 @@ Here is the full implementation of the FSM:
3434``` C
3535struct app {
3636 struct am_fsm fsm;
37- /* my data */
37+ /* app data */
3838} app;
3939
4040static enum am_rc state_a (struct app * me, const struct am_event * event) {
@@ -97,7 +97,7 @@ Here is the full implementation of the HSM:
9797``` C
9898struct app {
9999 struct am_hsm hsm;
100- /* my data */
100+ /* app data */
101101} app;
102102
103103static enum am_rc superstate (struct app * me, const struct am_event * event) {
@@ -146,6 +146,148 @@ The HSM API can be found [here](https://amast.readthedocs.io/api.html#hsm).
146146The HSM documenation is [here](https://amast.readthedocs.io/hsm.html).
147147The library requires less than 3kB of memory.
148148
149+ ### Active Object
150+
151+ Here is a full implementation of one active object with two states.
152+
153+ It demonstrate several features:
154+
155+ 1. creating the active object
156+ 2. creating and maintaining a timer
157+ 3. event pubplishing
158+ 4. creating a regular tasks, for blocking calls like
159+ sleep and waiting for user input
160+
161+ ```C
162+ enum {
163+ APP_EVT_SWITCH_MODE = AM_EVT_USER,
164+ APP_EVT_PUB_MAX,
165+ APP_EVT_TIMER,
166+ };
167+
168+ struct app {
169+ struct am_ao ao;
170+ struct am_timer *timer;
171+ /* app data */
172+ };
173+
174+ /* events are allocated from this memory pool */
175+ static struct am_timer m_event_pool[1] AM_ALIGNED(AM_ALIGN_MAX);
176+ /* event publish/subscribe memory */
177+ static struct am_ao_subscribe_list m_pubsub_list[APP_EVT_PUB_MAX];
178+ /* active object incoming events queue */
179+ static const struct am_event *m_queue[2];
180+
181+ static enum am_rc app_state_a(struct app *me, const struct am_event *event) {
182+ switch (event->id) {
183+ case APP_EVT_SWITCH_MODE:
184+ return AM_HSM_TRAN(app_state_b);
185+ }
186+ return AM_HSM_SUPER(am_hsm_top);
187+ }
188+
189+ static enum am_rc app_state_b(struct app *me, const struct am_event *event) {
190+ switch (event->id) {
191+ case AM_EVT_HSM_ENTRY:
192+ am_timer_arm_ticks(&app->timer, /*ticks=*/10, /*interval=*/0);
193+ return AM_HSM_HANDLED();
194+ case AM_EVT_HSM_EXIT:
195+ am_timer_disarm(me->timer);
196+ return AM_HSM_HANDLED();
197+ case APP_EVT_SWITCH_MODE:
198+ return AM_HSM_TRAN(app_state_a);
199+ case APP_EVT_TIMER:
200+ /* app specific timer actions are done here */
201+ am_timer_arm_ticks(&app->timer, /*ticks=*/10, /*interval=*/0);
202+ return AM_HSM_HANDLED();
203+ }
204+ return AM_HSM_SUPER(am_hsm_top);
205+ }
206+
207+ static enum am_rc app_init(struct app *me, const struct am_event *event) {
208+ am_ao_subscribe(&me->ao, APP_EVT_SWITCH_MODE);
209+ return AM_HSM_TRAN(app_state_a);
210+ }
211+
212+ static void app_ctor(struct app *me) {
213+ memset(me, 0, sizeof(*me));
214+ am_ao_ctor(&me->ao, AM_HSM_STATE_CTOR(app_init));
215+ me->timer = am_timer_allocate(
216+ APP_EVT_TIMER, sizeof(*me->timer), AM_PAL_TICK_DOMAIN_DEFAULT, &me->ao
217+ );
218+ }
219+
220+ static void ticker_task(void *param) {
221+ am_pal_wait_all_tasks();
222+
223+ uint32_t now_ticks = am_pal_time_get_tick(AM_PAL_TICK_DOMAIN_DEFAULT);
224+ while (am_ao_get_cnt() > 0) {
225+ am_pal_sleep_till_ticks(AM_PAL_TICK_DOMAIN_DEFAULT, now_ticks + 1);
226+ now_ticks += 1;
227+ am_timer_tick(AM_PAL_TICK_DOMAIN_DEFAULT);
228+ }
229+ }
230+
231+ static void input_task(void *param) {
232+ am_pal_wait_all_tasks();
233+
234+ int ch;
235+ while ((ch = getc(stdin)) != EOF) {
236+ if ('\n' == ch) {
237+ static struct am_event event = {.id = APP_EVT_SWITCH_MODE};
238+ am_ao_publish(&event);
239+ }
240+ }
241+ }
242+
243+ int main(void) {
244+ am_ao_state_ctor(/*cfg=*/NULL);
245+
246+ am_event_add_pool(
247+ m_event_pool,
248+ sizeof(m_event_pool),
249+ sizeof(m_event_pool[0]),
250+ AM_ALIGNOF(am_timer_t)
251+ );
252+
253+ am_ao_init_subscribe_list(m_pubsub_list, AM_COUNTOF(m_pubsub_list));
254+
255+ struct app m;
256+ app_ctor(&m);
257+
258+ am_ao_start(
259+ &m.ao,
260+ (struct am_ao_prio){.ao = AM_AO_PRIO_MAX, .task = AM_AO_PRIO_MAX},
261+ /*queue=*/m_queue, /*nqueue=*/AM_COUNTOF(m_queue),
262+ /*stack=*/NULL, /*stack_size=*/0, /*name=*/"app", /*init_event=*/NULL
263+ );
264+
265+ /* ticker thread to feed timers */
266+ am_pal_task_create(
267+ "ticker",
268+ AM_AO_PRIO_MIN,
269+ /*stack=*/NULL, /*stack_size=*/0,
270+ /*entry=*/ticker_task, /*arg=*/NULL
271+ );
272+
273+ /* user input controlling thread */
274+ am_pal_task_create(
275+ "input",
276+ AM_AO_PRIO_MIN,
277+ /*stack=*/NULL, /*stack_size=*/0,
278+ /*entry=*/input_task, /*arg=*/&m
279+ );
280+
281+ while (am_ao_get_cnt() > 0) {
282+ am_ao_run_all();
283+ }
284+
285+ am_ao_state_dtor();
286+
287+ return 0;
288+ }
289+ ```
290+
149291## Architecture Diagram
150292
151293![ Architecture Diagram] ( docs/amast-app-diagram.jpg )
0 commit comments