Separate the two state machines and use message passing between them. Thus, state machine 1 would proceed from A B C, where at state B it checks for the current results from state machine 2. If the output has changed, then state machine 1 can account for it and state machine 2 does not need to have any awareness of how state machine 1 actually works. Something like:
typedef struct StateMachine {
void(*Update)(); // function to update the state machine
int Data; // generic temp holder to survive state contexts
int State; // current state of our state machine
int *Message; // pointer to a shared integer for message passing
};
int main(void) {
int Message = 0;
/* NewStateMachine would malloc the struct, pass in the int reference
* and function pointer as well as add it to a circularly linked list */
NewStateMachine(&Message, MainLoop);
NewStateMachine(&Message, MinorLoop);
StateMachine *Current = StateMachine_CLL.First;
for(;;) {
Current->Update(Current); /* Update the current state machine */
Current = Current->Next; /* And the advance to the next one */
}
}
void MainLoop(StateMachine *this) {
switch(this.State) {
case 0:
CloseCoolantTank(1); /* safe to call if valve already closed */
CloseCoolantTank(2); /* safe to call if valve already closed */
this.State = 1;
break;
case 1:
/* we have a message, do something */
if(*this.Message) this.State = 2;
/* otherwise stall at this state until we get a message */
else this.State = 1;
break;
case 2:
if(*this.Message == 1) this.State = 3; /* warm */
else if(*this.Message == 2) this.State = 4; /* hot! */
else this.State = 0; /* cooled down, shut off valves */
this.Message = 0; /* clear the message */
break;
case 3:
OpenCoolantTank(1); /* opens the valve, safe to call if already open */
this.State = 2; /* recheck for new message */
break;
case 4:
OpenCoolantTank(2); /* opens the valve, safe to call if already open */
this.State = 3; /* also open coolant tank 1 for extra cooling */
break;
}
}
/* Monitor temperature and send messages on overheat */
void MinorLoop(StateMachine *this) {
switch(this.State) {
case 0:
this.Data = ReadADCValue();
this.State = 1;
break;
case 1:
if(this.Data > 150) *this.Message = 2;
else if(this.Data > 100) *this.Message = 1;
this.State = 0;
break;
}
}