Skip to content

Commit 78c99ec

Browse files
committed
Add active object example to README.md
1 parent 9634177 commit 78c99ec

File tree

1 file changed

+144
-2
lines changed

1 file changed

+144
-2
lines changed

README.md

Lines changed: 144 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ Here is the full implementation of the FSM:
3434
```C
3535
struct app {
3636
struct am_fsm fsm;
37-
/* my data */
37+
/* app data */
3838
} app;
3939

4040
static 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
9898
struct app {
9999
struct am_hsm hsm;
100-
/* my data */
100+
/* app data */
101101
} app;
102102

103103
static 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).
146146
The HSM documenation is [here](https://amast.readthedocs.io/hsm.html).
147147
The 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

Comments
 (0)