271 lines
7 KiB
C
271 lines
7 KiB
C
/*
|
|
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
|
|
*
|
|
* This file is part of Open5GS.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Affero General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "ogs-core.h"
|
|
#include "core/abts.h"
|
|
|
|
enum bomb_signal_t {
|
|
UP_SIG = OGS_FSM_USER_SIG,
|
|
DOWN_SIG,
|
|
ARM_SIG
|
|
};
|
|
|
|
typedef struct _tick_event_t {
|
|
int id;
|
|
} tick_event_t;
|
|
|
|
typedef struct _bomb_t {
|
|
ogs_fsm_t fsm;
|
|
uint8_t timeout;
|
|
uint8_t code;
|
|
uint8_t defuse;
|
|
} bomb_t;
|
|
|
|
void bomb_initial(bomb_t *s, tick_event_t *e);
|
|
void bomb_setting(bomb_t *s, tick_event_t *e);
|
|
void bomb_timing(bomb_t *s, tick_event_t *e);
|
|
|
|
void bomb_initial(bomb_t *s, tick_event_t *e)
|
|
{
|
|
s->timeout = 10;
|
|
OGS_FSM_TRAN(s, &bomb_setting);
|
|
}
|
|
|
|
void bomb_setting(bomb_t *s, tick_event_t *e)
|
|
{
|
|
switch (e->id) {
|
|
case UP_SIG:
|
|
if (s->timeout < 12) {
|
|
++s->timeout;
|
|
}
|
|
break;
|
|
case DOWN_SIG:
|
|
if (s->timeout > 8) {
|
|
--s->timeout;
|
|
}
|
|
break;
|
|
case ARM_SIG:
|
|
OGS_FSM_TRAN(s, &bomb_timing);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void bomb_timing(bomb_t *s, tick_event_t *e)
|
|
{
|
|
switch (e->id) {
|
|
case OGS_FSM_ENTRY_SIG:
|
|
s->code = 0;
|
|
break;
|
|
case UP_SIG:
|
|
s->code <<= 1;
|
|
s->code |= 1;
|
|
break;
|
|
case DOWN_SIG:
|
|
s->code <<= 1;
|
|
break;
|
|
case ARM_SIG:
|
|
if (s->code == s->defuse) {
|
|
OGS_FSM_TRAN(s, &bomb_setting);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void test1_func(abts_case *tc, void *data)
|
|
{
|
|
bomb_t bomb;
|
|
tick_event_t tick_event;
|
|
|
|
ogs_fsm_init(&bomb, &bomb_initial, 0, 0);
|
|
bomb.defuse = 14;
|
|
ABTS_PTR_EQUAL(tc, &bomb_setting, OGS_FSM_STATE(&bomb));
|
|
ABTS_INT_EQUAL(tc, 10, bomb.timeout);
|
|
|
|
tick_event.id = UP_SIG;
|
|
ogs_fsm_dispatch(&bomb, &tick_event);
|
|
ABTS_PTR_EQUAL(tc, &bomb_setting, OGS_FSM_STATE(&bomb));
|
|
ABTS_INT_EQUAL(tc, 11, bomb.timeout);
|
|
ogs_fsm_dispatch(&bomb, &tick_event);
|
|
ABTS_PTR_EQUAL(tc, &bomb_setting, OGS_FSM_STATE(&bomb));
|
|
ABTS_INT_EQUAL(tc, 12, bomb.timeout);
|
|
ogs_fsm_dispatch(&bomb, &tick_event);
|
|
ABTS_PTR_EQUAL(tc, &bomb_setting, OGS_FSM_STATE(&bomb));
|
|
ABTS_INT_EQUAL(tc, 12, bomb.timeout);
|
|
|
|
tick_event.id = DOWN_SIG;
|
|
ogs_fsm_dispatch(&bomb, &tick_event);
|
|
ABTS_PTR_EQUAL(tc, &bomb_setting, OGS_FSM_STATE(&bomb));
|
|
ABTS_INT_EQUAL(tc, 11, bomb.timeout);
|
|
ogs_fsm_dispatch(&bomb, &tick_event);
|
|
ABTS_PTR_EQUAL(tc, &bomb_setting, OGS_FSM_STATE(&bomb));
|
|
ABTS_INT_EQUAL(tc, 10, bomb.timeout);
|
|
ogs_fsm_dispatch(&bomb, &tick_event);
|
|
ABTS_PTR_EQUAL(tc, &bomb_setting, OGS_FSM_STATE(&bomb));
|
|
ABTS_INT_EQUAL(tc, 9, bomb.timeout);
|
|
ogs_fsm_dispatch(&bomb, &tick_event);
|
|
ABTS_PTR_EQUAL(tc, &bomb_setting, OGS_FSM_STATE(&bomb));
|
|
ABTS_INT_EQUAL(tc, 8, bomb.timeout);
|
|
ogs_fsm_dispatch(&bomb, &tick_event);
|
|
ABTS_PTR_EQUAL(tc, &bomb_setting, OGS_FSM_STATE(&bomb));
|
|
ABTS_INT_EQUAL(tc, 8, bomb.timeout);
|
|
|
|
tick_event.id = ARM_SIG;
|
|
ogs_fsm_dispatch((ogs_fsm_t *)&bomb, &tick_event);
|
|
ABTS_PTR_EQUAL(tc, &bomb_timing, OGS_FSM_STATE(&bomb));
|
|
ABTS_INT_EQUAL(tc, 0, bomb.code);
|
|
|
|
tick_event.id = UP_SIG;
|
|
ogs_fsm_dispatch((ogs_fsm_t *)&bomb, &tick_event);
|
|
ABTS_PTR_EQUAL(tc, &bomb_timing, OGS_FSM_STATE(&bomb));
|
|
ABTS_INT_EQUAL(tc, 1, bomb.code);
|
|
|
|
tick_event.id = UP_SIG;
|
|
ogs_fsm_dispatch((ogs_fsm_t *)&bomb, &tick_event);
|
|
ABTS_PTR_EQUAL(tc, &bomb_timing, OGS_FSM_STATE(&bomb));
|
|
ABTS_INT_EQUAL(tc, 3, bomb.code);
|
|
|
|
tick_event.id = UP_SIG;
|
|
ogs_fsm_dispatch((ogs_fsm_t *)&bomb, &tick_event);
|
|
ABTS_PTR_EQUAL(tc, &bomb_timing, OGS_FSM_STATE(&bomb));
|
|
ABTS_INT_EQUAL(tc, 7, bomb.code);
|
|
|
|
tick_event.id = DOWN_SIG;
|
|
ogs_fsm_dispatch((ogs_fsm_t *)&bomb, &tick_event);
|
|
ABTS_PTR_EQUAL(tc, &bomb_timing, OGS_FSM_STATE(&bomb));
|
|
ABTS_INT_EQUAL(tc, 14, bomb.code);
|
|
|
|
tick_event.id = ARM_SIG;
|
|
ogs_fsm_dispatch((ogs_fsm_t *)&bomb, &tick_event);
|
|
ABTS_PTR_EQUAL(tc, &bomb_setting, OGS_FSM_STATE(&bomb));
|
|
}
|
|
|
|
enum alarm_signal_e {
|
|
TICK_SIG = OGS_FSM_USER_SIG,
|
|
ALARM_SET_SIG,
|
|
ALARM_ON_SIG,
|
|
ALARM_OFF_SIG,
|
|
ALARM_SIG,
|
|
CLOCK_12H_SIG,
|
|
CLOCK_24H_SIG,
|
|
TIME_SIG,
|
|
TERMINATE_SIG
|
|
};
|
|
|
|
typedef struct alarm_s {
|
|
ogs_fsm_t fsm;
|
|
uint32_t time;
|
|
} alarm_t;
|
|
|
|
typedef struct set_event_s {
|
|
int id;
|
|
uint8_t digit;
|
|
} set_event_t;
|
|
|
|
typedef struct time_event_s {
|
|
int id;
|
|
uint8_t current_time;
|
|
} time_event_t;
|
|
|
|
void alarm_initial(alarm_t *s, set_event_t *e);
|
|
void alarm_off(alarm_t *s, set_event_t *e);
|
|
void alarm_on(alarm_t *s, time_event_t *e);
|
|
|
|
void alarm_initial(alarm_t *s, set_event_t *e)
|
|
{
|
|
s->time = 12*60;
|
|
OGS_FSM_TRAN(s, &alarm_off);
|
|
}
|
|
|
|
void alarm_off(alarm_t *s, set_event_t *e)
|
|
{
|
|
uint32_t alarm;
|
|
|
|
switch (e->id) {
|
|
case OGS_FSM_ENTRY_SIG:
|
|
s->time = (s->time/60)*100 + s->time%60;
|
|
break;
|
|
case OGS_FSM_EXIT_SIG:
|
|
s->time = (s->time/100)*60 + s->time%100;
|
|
break;
|
|
case ALARM_ON_SIG:
|
|
OGS_FSM_TRAN(s, &alarm_on);
|
|
break;
|
|
case ALARM_SET_SIG:
|
|
alarm = (10 * s->time
|
|
+ e->digit) % 10000;
|
|
if ((alarm / 100 < 24) && (alarm % 100 < 60)) {
|
|
s->time = alarm;
|
|
}
|
|
else
|
|
{
|
|
s->time = 0;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void alarm_on(alarm_t *s, time_event_t *e)
|
|
{
|
|
switch (e->id) {
|
|
case OGS_FSM_ENTRY_SIG:
|
|
break;
|
|
case ALARM_SET_SIG:
|
|
break;
|
|
case ALARM_OFF_SIG:
|
|
OGS_FSM_TRAN(s, &alarm_off);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void test2_func(abts_case *tc, void *data)
|
|
{
|
|
alarm_t alarm;
|
|
set_event_t set_event;
|
|
time_event_t time_event;
|
|
|
|
ogs_fsm_init(&alarm, &alarm_initial, 0, 0);
|
|
ABTS_PTR_EQUAL(tc, &alarm_off, OGS_FSM_STATE(&alarm));
|
|
ABTS_INT_EQUAL(tc, 1200, alarm.time);
|
|
|
|
set_event.id = ALARM_ON_SIG;
|
|
ogs_fsm_dispatch(&alarm, &set_event);
|
|
ABTS_PTR_EQUAL(tc, &alarm_on, OGS_FSM_STATE(&alarm));
|
|
ABTS_INT_EQUAL(tc, 720, alarm.time);
|
|
|
|
time_event.id = ALARM_OFF_SIG;
|
|
ogs_fsm_dispatch(&alarm, &time_event);
|
|
ABTS_PTR_EQUAL(tc, &alarm_off, OGS_FSM_STATE(&alarm));
|
|
ABTS_INT_EQUAL(tc, 1200, alarm.time);
|
|
|
|
set_event.id = ALARM_SET_SIG;
|
|
set_event.digit = 0;
|
|
ogs_fsm_dispatch(&alarm, &set_event);
|
|
ABTS_PTR_EQUAL(tc, &alarm_off, OGS_FSM_STATE(&alarm));
|
|
ABTS_INT_EQUAL(tc, 2000, alarm.time);
|
|
}
|
|
|
|
abts_suite *test_fsm(abts_suite *suite)
|
|
{
|
|
suite = ADD_SUITE(suite)
|
|
|
|
abts_run_test(suite, test1_func, NULL);
|
|
abts_run_test(suite, test2_func, NULL);
|
|
|
|
return suite;
|
|
}
|