Code: state-object.h and state-object.c
Ref: 2.0.4_StateObjects, Rebel T1i / 500d State Object Initialization, 500d/T1i Task Sequencers, 550d_108_StateObjects, State machine diagrams.
StateObject structure[]
0: 'StateObject' 4: name 8: ? c: @StateTransition 10: address 14: inputs 18: states 1c: current state maybe
StateTransition[]
arg0: state object arg1: ? arg2: input
next_state = MEM(state_obj_base_addr + 8*current_state + 8*num_states*input ) transition_function = MEM(state_obj_base_addr + 8*current_state + 8*num_states*input + 4)
State machine task (AJ_UserLevel_task)[]
from [1]
struct TaskClass { uint32_t TaskClass_label uint32_t name; uint32_t enabled; // off_0x08 uint32_t task_handle; uint32_t msg_queue; void (*EventDispatch)(uint32_t, uint32_t, uint32_t, uint32_t); // off_0x14 };
void AJ_UserLevel_task( struct TaskClass * tc ) { uint32_t x, y, z, w; while (tc->enabled) { int rc = TaskClass_GetEvent(tc, &x, &y, &z, &w); if (rc != 0) continue; if (!tc->enabled) break; tc->EventDispatch(x, y, z, w); } return 0; }
How to trigger state changes?[]
Pure theory: TryPostEvent.
- TryPostEvent does this: msg_queue_post(arg0->off_0x10, ...)
- TaskClass_GetEvent does this: msg_queue_receive(arg0->off_0x10, ...)
Syntax:
TryPostEvent(TaskClass_obj, x, y, z, w)
should result in indirect call of:
TaskClass_obj->EventDispatch(x, y, z, w).
EventDispatch functions may be task-specific, but they seem to follow a pattern.
mvrEventDispatch, voiEventDispatch: s = StateTransition_main(stateobj, x, y, z, w) if (s) stateobj = s // state functions from this particular state will return the state object return s cs = GetCurrentState(stateobj) DebugMsg(*, 6, msg='***EventDispatch : Current = %d, dwEventID = %d, dwParam = %#x', cs, y, z)