/*----------------------------------------------------------------------------- * Led Statemachine */ void LedCheck(void) { uint16_t currTimeMs; uint8_t i; TState *pState; GET_TIME_MS16(currTimeMs); pState = &sLedState[0]; for (i = 0; i < NUM_LED; i++) { if ((pState->offTime != FOREVER) && (pState->onTime != FOREVER)) { if (pState->state == LED_ON) { if (((uint16_t)(currTimeMs - pState->switchTime)) >= pState->onTime) { pState->switchTime = currTimeMs; LedOff(i); if (pState->cyclic == false) { pState->offTime = FOREVER; } } } else { if (((uint16_t)(currTimeMs - pState->switchTime)) >= pState->offTime) { pState->switchTime = currTimeMs; LedOn(i); } } } pState++; } }
/*----------------------------------------------------------------------------- * send the startup msg. Delay depends on module address */ static void SendStartupMsg(void) { uint16_t startCnt; uint16_t cntMs; uint16_t diff; /* send startup message */ /* delay depends on module address (address * 100 ms) */ GET_TIME_MS16(startCnt); do { GET_TIME_MS16(cntMs); diff = cntMs - startCnt; } while (diff < ((uint16_t)MY_ADDR * 100)); sTxBusMsg.type = eBusDevStartup; sTxBusMsg.senderAddr = MY_ADDR; BusSend(&sTxBusMsg); }
/*----------------------------------------------------------------------------- * post state changes to registered bus clients */ static void CheckEvent(void) { static uint8_t sActualClient = 0xff; /* actual client's index being processed */ static uint16_t sChangeTestTimeStamp; TClient *pClient; uint16_t actualTime16; bool actValChanged; static bool sNewClientCycleDelay = false; static uint16_t sNewClientCycleTimeStamp; TBusDevReqActualValueEvent *pActVal; bool getNextClient; uint8_t nextClient; static uint16_t sCurPwmActVal[NUM_PWM_CHANNEL]; static bool sCurPwmState[NUM_PWM_CHANNEL]; uint8_t i; uint8_t val8; if (sNumClients == 0) { return; } /* do the change detection not in each cycle */ GET_TIME_MS16(actualTime16); if (((uint16_t)(actualTime16 - sChangeTestTimeStamp)) >= CHANGE_DETECT_CYCLE_TIME_MS) { PwmGetAll(sCurPwmActVal, sizeof(sCurPwmActVal)); for (i = 0; i < NUM_PWM_CHANNEL; i++) { PwmIsOn(i, &sCurPwmState[i]); } if ((memcmp(sCurPwmActVal, sOldPwmActVal, sizeof(sCurPwmActVal)) == 0) && (memcmp(sCurPwmState, sOldPwmState, sizeof(sCurPwmActVal)) == 0)) { actValChanged = false; } else { actValChanged = true; } if (actValChanged) { memcpy(sOldPwmActVal, sCurPwmActVal, sizeof(sOldPwmActVal)); memcpy(sOldPwmState, sCurPwmState, sizeof(sOldPwmState)); sActualClient = 0; sNewClientCycleDelay = false; InitClientState(); } sChangeTestTimeStamp = actualTime16; } if (sActualClient == 0xff) { return; } if (sNewClientCycleDelay) { if (((uint16_t)(actualTime16 - sNewClientCycleTimeStamp)) < RETRY_CYCLE_TIME_MS) { return; } else { sNewClientCycleDelay = false; } } pClient = &sClient[sActualClient]; getNextClient = true; switch (pClient->state) { case eEventInit: pActVal = &sTxBusMsg.msg.devBus.x.devReq.actualValueEvent; sTxBusMsg.type = eBusDevReqActualValueEvent; sTxBusMsg.senderAddr = MY_ADDR; sTxBusMsg.msg.devBus.receiverAddr = pClient->address; pActVal->devType = eBusDevTypePwm4; memcpy(pActVal->actualValue.pwm4.pwm, sCurPwmActVal, sizeof(pActVal->actualValue.pwm4.pwm)); val8 = 0; for (i = 0; i < NUM_PWM_CHANNEL; i++) { val8 |= sCurPwmState[i] ? 1 << i : 0; } pActVal->actualValue.pwm4.state = val8; if (BusSend(&sTxBusMsg) == BUS_SEND_OK) { pClient->state = eEventWaitForConfirmation; pClient->requestTimeStamp = actualTime16; } else { getNextClient = false; } break; case eEventWaitForConfirmation: if ((((uint16_t)(actualTime16 - pClient->requestTimeStamp)) >= RESPONSE_TIMEOUT_MS) && (pClient->state != eEventMaxRetry)) { if (pClient->curRetry < pClient->maxRetry) { /* try again */ pClient->curRetry++; getNextClient = false; pClient->state = eEventInit; } else { pClient->state = eEventMaxRetry; } } break; case eEventConfirmationOK: break; default: break; } if (getNextClient) { nextClient = GetUnconfirmedClient(sActualClient); if (nextClient <= sActualClient) { sNewClientCycleDelay = true; sNewClientCycleTimeStamp = actualTime16; } sActualClient = nextClient; } }
/*----------------------------------------------------------------------------- * send switch state change to clients * - client address list is read from eeprom * - if there is no confirmation from client within RESPONSE_TIMEOUT2 * the next client in list is processed * - telegrams to clients without response are repeated again and again * til telegrams to all clients in list are confirmed * - if switchStateChanged occurs while client confirmations are missing * actual client process is canceled and the new state telegram is sent * to clients */ static void ProcessSwitch(uint8_t switchState) { static uint8_t sActualClient = 0xff; /* actual client's index being processed */ static uint16_t sChangeTimeStamp; TClient *pClient; uint8_t i; uint16_t actualTime16; uint8_t actualTime8; bool switchStateChanged; bool startProcess; if ((switchState ^ sSwitchStateOld) != 0) { switchStateChanged = true; } else { switchStateChanged = false; } if (switchStateChanged) { if (sActualClient < BUS_MAX_CLIENT_NUM) { pClient = &sClient[sActualClient]; if (pClient->state == eWaitForConfirmation1) { startProcess = false; } else { startProcess = true; sSwitchStateOld = switchState; } } else { startProcess = true; sSwitchStateOld = switchState; } if (startProcess == true) { sSwitchStateActual = switchState; GET_TIME_MS16(sChangeTimeStamp); /* set up client descriptor array */ sActualClient = 0; pClient = &sClient[0]; for (i = 0; i < BUS_MAX_CLIENT_NUM; i++) { pClient->address = eeprom_read_byte((const uint8_t *)(CLIENT_ADDRESS_BASE + i)); if (pClient->address != BUS_CLIENT_ADDRESS_INVALID) { pClient->state = eInit; } else { pClient->state = eSkip; } pClient++; } } } if (sActualClient < BUS_MAX_CLIENT_NUM) { GET_TIME_MS16(actualTime16); if (((uint16_t)(actualTime16 - sChangeTimeStamp)) < RETRY_TIMEOUT2_MS) { pClient = &sClient[sActualClient]; if (pClient->state == eConfirmationOK) { /* get next client */ sActualClient = GetUnconfirmedClient(sActualClient); if (sActualClient < BUS_MAX_CLIENT_NUM) { pClient = &sClient[sActualClient]; } else { /* we are ready */ } } switch (pClient->state) { case eInit: sTxBusMsg.type = eBusDevReqSwitchState; sTxBusMsg.senderAddr = MY_ADDR; sTxBusMsg.msg.devBus.receiverAddr = pClient->address; sTxBusMsg.msg.devBus.x.devReq.switchState.switchState = sSwitchStateActual; BusSend(&sTxBusMsg); pClient->state = eWaitForConfirmation1; GET_TIME_MS16(pClient->requestTimeStamp); break; case eWaitForConfirmation1: actualTime8 = GET_TIME_MS; if (((uint8_t)(actualTime8 - pClient->requestTimeStamp)) >= RESPONSE_TIMEOUT1_MS) { pClient->state = eWaitForConfirmation2; GET_TIME_MS16(pClient->requestTimeStamp); } break; case eWaitForConfirmation2: GET_TIME_MS16(actualTime16); if (((uint16_t)(actualTime16 - pClient->requestTimeStamp)) >= RESPONSE_TIMEOUT2_MS) { /* set client for next try after the other clients */ pClient->state = eInit; /* try next client */ sActualClient = GetUnconfirmedClient(sActualClient); } break; default: break; } } else { sActualClient = 0xff; } } }
/*----------------------------------------------------------------------------- * post state changes to registered bus clients */ static void ProcessSwitch(void) { static uint8_t sActualClient = 0xff; /* actual client's index being processed */ static uint16_t sChangeTimeStamp; TClient *pClient; uint16_t actualTime16; static bool sNewClientCycleDelay = false; static uint16_t sNewClientCycleTimeStamp; uint8_t rc; bool getNextClient; uint8_t nextClient; bool switchStateChanged; if (sNumClients == 0) { return; } if ((sWindSwitch ^ sWindSwitchOld) != 0) { switchStateChanged = true; } else { switchStateChanged = false; } /* do the change detection not in each cycle */ GET_TIME_MS16(actualTime16); if (switchStateChanged) { sChangeTimeStamp = actualTime16; sActualClient = 0; sNewClientCycleDelay = false; InitClientState(); sWindSwitchOld = sWindSwitch; } if (sActualClient == 0xff) { return; } if (sNewClientCycleDelay) { if (((uint16_t)(actualTime16 - sNewClientCycleTimeStamp)) < RETRY_CYCLE_TIME_MS) { return; } else { sNewClientCycleDelay = false; } } pClient = &sClient[sActualClient]; getNextClient = true; switch (pClient->state) { case eInit: sTxBusMsg.type = eBusDevReqSwitchState; sTxBusMsg.senderAddr = MY_ADDR; sTxBusMsg.msg.devBus.receiverAddr = pClient->address; sTxBusMsg.msg.devBus.x.devReq.switchState.switchState = sWindSwitch; rc = BusSend(&sTxBusMsg); if (rc == BUS_SEND_OK) { pClient->state = eWaitForConfirmation; pClient->requestTimeStamp = actualTime16; } else { getNextClient = false; } break; case eWaitForConfirmation: if (((uint16_t)(actualTime16 - pClient->requestTimeStamp)) >= RESPONSE_TIMEOUT_MS) { /* try once more */ pClient->state = eInit; getNextClient = false; } break; case eConfirmationOK: break; default: break; } if (getNextClient) { nextClient = GetUnconfirmedClient(sActualClient); if (nextClient <= sActualClient) { sNewClientCycleDelay = true; sNewClientCycleTimeStamp = actualTime16; } sActualClient = nextClient; } if (((uint16_t)(actualTime16 - sChangeTimeStamp)) > RETRY_TIMEOUT_MS) { sActualClient = 0xff; // stop } }
/*----------------------------------------------------------------------------- * Ledzustand ändern */ void LedSet(TLedState state) { uint16_t currTimeMs; TState *pState; GET_TIME_MS16(currTimeMs); switch (state) { case eLedRedOff: LedOff(0); sLedState[0].offTime = FOREVER; break; case eLedRedOn: LedOn(0); sLedState[0].onTime = FOREVER; break; case eLedGreenOff: LedOff(1); sLedState[1].offTime = FOREVER; break; case eLedGreenOn: LedOn(1); sLedState[1].onTime = FOREVER; break; case eLedRedFlashSlow: pState = &sLedState[0]; pState->onTime = FLASH_TIME; pState->offTime = LONG_CYCLE; pState->cyclic = true; pState->switchTime = currTimeMs; LedOn(0); break; case eLedGreenFlashSlow: pState = &sLedState[1]; pState->onTime = FLASH_TIME; pState->offTime = LONG_CYCLE; pState->cyclic = true; pState->switchTime = currTimeMs; LedOn(1); break; case eLedRedFlashFast: pState = &sLedState[0]; pState->onTime = FLASH_TIME; pState->offTime = SHORT_CYCLE; pState->cyclic = true; pState->switchTime = currTimeMs; LedOn(0); break; case eLedGreenFlashFast: pState = &sLedState[1]; pState->onTime = FLASH_TIME; pState->offTime = SHORT_CYCLE; pState->cyclic = true; pState->switchTime = currTimeMs; LedOn(1); break; case eLedRedBlinkSlow: pState = &sLedState[0]; pState->onTime = SLOW_BLINK; pState->offTime = SLOW_BLINK; pState->cyclic = true; pState->switchTime = currTimeMs; LedOn(0); break; case eLedGreenBlinkSlow: pState = &sLedState[1]; pState->onTime = SLOW_BLINK; pState->offTime = SLOW_BLINK; pState->cyclic = true; pState->switchTime = currTimeMs; LedOn(1); break; case eLedRedBlinkFast: pState = &sLedState[0]; pState->onTime = FAST_BLINK; pState->offTime = FAST_BLINK; pState->cyclic = true; pState->switchTime = currTimeMs; LedOn(0); break; case eLedGreenBlinkFast: pState = &sLedState[1]; pState->onTime = FAST_BLINK; pState->offTime = FAST_BLINK; pState->cyclic = true; pState->switchTime = currTimeMs; LedOn(1); break; case eLedRedBlinkOnceShort: pState = &sLedState[0]; pState->onTime = FAST_BLINK; pState->offTime = 0; pState->cyclic = false; pState->switchTime = currTimeMs; LedOn(0); break; case eLedRedBlinkOnceLong: pState = &sLedState[0]; pState->onTime = SLOW_BLINK; pState->offTime = 0; pState->cyclic = false; pState->switchTime = currTimeMs; LedOn(0); break; case eLedGreenBlinkOnceShort: pState = &sLedState[1]; pState->onTime = FAST_BLINK; pState->offTime = 0; pState->cyclic = false; pState->switchTime = currTimeMs; LedOn(1); break; case eLedGreenBlinkOnceLong: pState = &sLedState[1]; pState->onTime = SLOW_BLINK; pState->offTime = 0; pState->cyclic = false; pState->switchTime = currTimeMs; LedOn(1); break; default: break; } }