/*----------------------------------------------------------------------------- * main */ int main(void) { uint8_t ret; int sioHdl; /* set clock prescaler to 2 (set clock to 7.3928 MHz) */ CLKPR = 1 << CLKPCE; CLKPR = 1; /* get module address from EEPROM */ sMyAddr = eeprom_read_byte((const uint8_t *)MODUL_ADDRESS); GetClientListFromEeprom(); PortInit(); TimerInit(); ButtonInit(); PwmInit(); ApplicationInit(); SioInit(); SioRandSeed(sMyAddr); /* sio for bus interface */ sioHdl = SioOpen("USART1", eSioBaud9600, eSioDataBits8, eSioParityNo, eSioStopBits1, eSioModeHalfDuplex); SioSetIdleFunc(sioHdl, IdleSio1); SioSetTransceiverPowerDownFunc(sioHdl, BusTransceiverPowerDown); BusTransceiverPowerDown(true); BusInit(sioHdl); spBusMsg = BusMsgBufGet(); /* warten for full operation voltage */ while (!POWER_GOOD); /* enable ints before RestorePwm() */ ENABLE_INT; TimerStart(); RestorePwm(); /* ext int for power fail: INT0 low level sensitive */ EICRA &= ~((1 << ISC01) | (1 << ISC00)); EIMSK |= (1 << INT0); ApplicationStart(); /* Hauptschleife */ while (1) { Idle(); ret = BusCheck(); ProcessBus(ret); CheckButton(); PwmCheck(); ApplicationCheck(); CheckEvent(); } return 0; }
/*----------------------------------------------------------------------------- * program start */ int main(void) { int sioHandle; uint8_t windThreshold1; uint8_t windThreshold2; MCUSR = 0; wdt_disable(); /* get module address from EEPROM */ sMyAddr = eeprom_read_byte((const uint8_t *)MODUL_ADDRESS); windThreshold1 = eeprom_read_byte((const uint8_t *)WIND_THRESHOLD1); windThreshold2 = eeprom_read_byte((const uint8_t *)WIND_THRESHOLD2); GetClientListFromEeprom(); PortInit(); TimerInit(); SioInit(); sioHandle = SioOpen("USART0", eSioBaud9600, eSioDataBits8, eSioParityNo, eSioStopBits1, eSioModeHalfDuplex); SioSetIdleFunc(sioHandle, IdleSio); SioSetTransceiverPowerDownFunc(sioHandle, BusTransceiverPowerDown); BusTransceiverPowerDown(true); BusInit(sioHandle); spRxBusMsg = BusMsgBufGet(); /* enable global interrupts */ ENABLE_INT; SendStartupMsg(); /* wait for controller startup delay for sending first state telegram */ DELAY_S(STARTUP_DELAY); while (1) { Idle(); ProcessSwitch(); ProcessBus(); if (sWind >= windThreshold1) { sWindSwitch |= 0x01; } else { sWindSwitch &= ~0x01; } if (sWind >= windThreshold2) { sWindSwitch |= 0x02; } else { sWindSwitch &= ~0x02; } } return 0; /* never reached */ }
/*----------------------------------------------------------------------------- * process bus telegrams */ static void ProcessBus(uint8_t ret) { TBusMsgType msgType; uint8_t i; bool msgForMe = false; uint8_t state; uint8_t mask8; uint8_t action; TBusDevRespInfo *pInfo; TBusDevRespActualValue *pActVal; TClient *pClient; static TBusTelegram sTxMsg; static bool sTxRetry = false; bool flag; uint8_t val8; if (sTxRetry) { sTxRetry = BusSend(&sTxMsg) != BUS_SEND_OK; return; } if (ret == BUS_MSG_OK) { msgType = spBusMsg->type; switch (msgType) { case eBusDevReqReboot: case eBusDevReqInfo: case eBusDevReqActualValue: case eBusDevReqSetValue: case eBusDevReqSwitchState: case eBusDevReqSetAddr: case eBusDevReqEepromRead: case eBusDevReqEepromWrite: case eBusDevReqSetClientAddr: case eBusDevReqGetClientAddr: case eBusDevRespActualValueEvent: if (spBusMsg->msg.devBus.receiverAddr == MY_ADDR) { msgForMe = true; } break; case eBusButtonPressed1: case eBusButtonPressed2: case eBusButtonPressed1_2: msgForMe = true; break; default: break; } } else if (ret == BUS_MSG_ERROR) { ButtonTimeStampRefresh(); } if (msgForMe == false) { return; } switch (msgType) { case eBusDevReqReboot: /* use watchdog to reboot */ /* set the watchdog timeout as short as possible (14 ms) */ cli(); wdt_enable(WDTO_15MS); /* wait for reset */ while (1); break; case eBusButtonPressed1: ButtonEvent(spBusMsg->senderAddr, 1); break; case eBusButtonPressed2: ButtonEvent(spBusMsg->senderAddr, 2); break; case eBusButtonPressed1_2: ButtonEvent(spBusMsg->senderAddr, 1); ButtonEvent(spBusMsg->senderAddr, 2); break; case eBusDevReqInfo: /* response packet */ pInfo = &sTxMsg.msg.devBus.x.devResp.info; sTxMsg.type = eBusDevRespInfo; sTxMsg.senderAddr = MY_ADDR; sTxMsg.msg.devBus.receiverAddr = spBusMsg->senderAddr; pInfo->devType = eBusDevTypePwm4; strncpy((char *)(pInfo->version), ApplicationVersion(), sizeof(pInfo->version)); pInfo->version[sizeof(pInfo->version) - 1] = '\0'; sTxRetry = BusSend(&sTxMsg) != BUS_SEND_OK; break; case eBusDevReqActualValue: /* response packet */ pActVal = &sTxMsg.msg.devBus.x.devResp.actualValue; sTxMsg.type = eBusDevRespActualValue; sTxMsg.senderAddr = MY_ADDR; sTxMsg.msg.devBus.receiverAddr = spBusMsg->senderAddr; pActVal->devType = eBusDevTypePwm4; PwmGetAll(pActVal->actualValue.pwm4.pwm, sizeof(pActVal->actualValue.pwm4.pwm)); val8 = 0; for (i = 0; i < NUM_PWM_CHANNEL; i++) { PwmIsOn(i, &flag); val8 |= flag ? 1 << i: 0; } pActVal->actualValue.pwm4.state = val8; sTxRetry = BusSend(&sTxMsg) != BUS_SEND_OK; break; case eBusDevReqSetValue: if (spBusMsg->msg.devBus.x.devReq.setValue.devType != eBusDevTypePwm4) { break; } mask8 = spBusMsg->msg.devBus.x.devReq.setValue.setValue.pwm4.set; for (i = 0; i < NUM_PWM_CHANNEL; i++) { action = (0x3 << (i * 2) & mask8) >> (i * 2); switch (action) { case 0x00: /* no action, ignore pwm[] from telegram */ break; case 0x01: /* set current pwm, ignore pwm[] from telegram */ PwmOn(i, true); break; case 0x02: /* set to pwm[] from telegram */ PwmSet(i, spBusMsg->msg.devBus.x.devReq.setValue.setValue.pwm4.pwm[i]); PwmOn(i, true); break; case 0x03: /* off, ignore pwm[] from telegram */ PwmOn(i, false); break; default: break; } } /* response packet */ sTxMsg.type = eBusDevRespSetValue; sTxMsg.senderAddr = MY_ADDR; sTxMsg.msg.devBus.receiverAddr = spBusMsg->senderAddr; sTxRetry = BusSend(&sTxMsg) != BUS_SEND_OK; break; case eBusDevReqSwitchState: state = spBusMsg->msg.devBus.x.devReq.switchState.switchState; if ((state & 0x01) != 0) { SwitchEvent(spBusMsg->senderAddr, 1, true); } else { SwitchEvent(spBusMsg->senderAddr, 1, false); } if ((state & 0x02) != 0) { SwitchEvent(spBusMsg->senderAddr, 2, true); } else { SwitchEvent(spBusMsg->senderAddr, 2, false); } /* response packet */ sTxMsg.type = eBusDevRespSwitchState; sTxMsg.senderAddr = MY_ADDR; sTxMsg.msg.devBus.receiverAddr = spBusMsg->senderAddr; sTxMsg.msg.devBus.x.devResp.switchState.switchState = state; sTxRetry = BusSend(&sTxMsg) != BUS_SEND_OK; break; case eBusDevReqSetAddr: sTxMsg.senderAddr = MY_ADDR; sTxMsg.type = eBusDevRespSetAddr; sTxMsg.msg.devBus.receiverAddr = spBusMsg->senderAddr; eeprom_write_byte((uint8_t *)MODUL_ADDRESS, spBusMsg->msg.devBus.x.devReq.setAddr.addr); sTxRetry = BusSend(&sTxMsg) != BUS_SEND_OK; break; case eBusDevReqEepromRead: sTxMsg.senderAddr = MY_ADDR; sTxMsg.type = eBusDevRespEepromRead; sTxMsg.msg.devBus.receiverAddr = spBusMsg->senderAddr; sTxMsg.msg.devBus.x.devResp.readEeprom.data = eeprom_read_byte((const uint8_t *)spBusMsg->msg.devBus.x.devReq.readEeprom.addr); sTxRetry = BusSend(&sTxMsg) != BUS_SEND_OK; break; case eBusDevReqEepromWrite: sTxMsg.senderAddr = MY_ADDR; sTxMsg.type = eBusDevRespEepromWrite; sTxMsg.msg.devBus.receiverAddr = spBusMsg->senderAddr; eeprom_write_byte((uint8_t *)spBusMsg->msg.devBus.x.devReq.readEeprom.addr, spBusMsg->msg.devBus.x.devReq.writeEeprom.data); sTxRetry = BusSend(&sTxMsg) != BUS_SEND_OK; break; case eBusDevRespActualValueEvent: pClient = sClient; for (i = 0; i < sNumClients; i++) { if ((pClient->address == spBusMsg->senderAddr) && (pClient->state == eEventWaitForConfirmation)) { TBusDevActualValuePwm4 *p; uint16_t buf[NUM_PWM_CHANNEL]; PwmGetAll(buf, sizeof(buf)); val8 = 0; for (i = 0; i < NUM_PWM_CHANNEL; i++) { PwmIsOn(i, &flag); val8 |= flag ? 1 << i: 0; } p = &spBusMsg->msg.devBus.x.devResp.actualValueEvent.actualValue.pwm4; if ((memcmp(p->pwm, buf, sizeof(buf)) == 0) && (p->state == val8)) { pClient->state = eEventConfirmationOK; } break; } pClient++; } break; case eBusDevReqSetClientAddr: sTxMsg.senderAddr = MY_ADDR; sTxMsg.type = eBusDevRespSetClientAddr; sTxMsg.msg.devBus.receiverAddr = spBusMsg->senderAddr; for (i = 0; i < BUS_MAX_CLIENT_NUM; i++) { uint8_t *p = &spBusMsg->msg.devBus.x.devReq.setClientAddr.clientAddr[i]; eeprom_write_byte((uint8_t *)(CLIENT_ADDRESS_BASE + i), *p); } sTxRetry = BusSend(&sTxMsg) != BUS_SEND_OK; GetClientListFromEeprom(); break; case eBusDevReqGetClientAddr: sTxMsg.senderAddr = MY_ADDR; sTxMsg.type = eBusDevRespGetClientAddr; sTxMsg.msg.devBus.receiverAddr = spBusMsg->senderAddr; for (i = 0; i < BUS_MAX_CLIENT_NUM; i++) { uint8_t *p = &sTxMsg.msg.devBus.x.devResp.getClientAddr.clientAddr[i]; *p = eeprom_read_byte((const uint8_t *)(CLIENT_ADDRESS_BASE + i)); } sTxRetry = BusSend(&sTxMsg) != BUS_SEND_OK; break; default: break; } }
/*----------------------------------------------------------------------------- * process received bus telegrams */ static void ProcessBus(void) { uint8_t ret; TClient *pClient; TBusMsgType msgType; uint8_t i; uint8_t *p; bool msgForMe = false; ret = BusCheck(); if (ret == BUS_MSG_OK) { msgType = spRxBusMsg->type; switch (msgType) { case eBusDevReqReboot: case eBusDevRespSwitchState: case eBusDevReqActualValue: case eBusDevReqSetClientAddr: case eBusDevReqGetClientAddr: case eBusDevReqInfo: case eBusDevReqSetAddr: case eBusDevReqEepromRead: case eBusDevReqEepromWrite: if (spRxBusMsg->msg.devBus.receiverAddr == MY_ADDR) { msgForMe = true; } break; default: break; } } if (msgForMe == false) { return; } switch (msgType) { case eBusDevReqReboot: /* reset controller with watchdog */ /* set watchdog timeout to shortest value (14 ms) */ cli(); wdt_enable(WDTO_15MS); /* wait for reset */ while (1); break; case eBusDevRespSwitchState: pClient = sClient; for (i = 0; i < sNumClients; i++) { if ((pClient->address == spRxBusMsg->senderAddr) && (pClient->state == eWaitForConfirmation)) { if (spRxBusMsg->msg.devBus.x.devResp.switchState.switchState == sWindSwitch) { pClient->state = eConfirmationOK; } break; } pClient++; } break; case eBusDevReqActualValue: sTxBusMsg.senderAddr = MY_ADDR; sTxBusMsg.type = eBusDevRespActualValue; sTxBusMsg.msg.devBus.receiverAddr = spRxBusMsg->senderAddr; sTxBusMsg.msg.devBus.x.devResp.actualValue.devType = eBusDevTypeWind; sTxBusMsg.msg.devBus.x.devResp.actualValue.actualValue.wind.state = sWindSwitch; sTxBusMsg.msg.devBus.x.devResp.actualValue.actualValue.wind.wind = sMaxWind; //sWind; BusSend(&sTxBusMsg); break; case eBusDevReqSetClientAddr: sTxBusMsg.senderAddr = MY_ADDR; sTxBusMsg.type = eBusDevRespSetClientAddr; sTxBusMsg.msg.devBus.receiverAddr = spRxBusMsg->senderAddr; for (i = 0; i < BUS_MAX_CLIENT_NUM; i++) { p = &(spRxBusMsg->msg.devBus.x.devReq.setClientAddr.clientAddr[i]); eeprom_write_byte((uint8_t *)(CLIENT_ADDRESS_BASE + i), *p); } BusSend(&sTxBusMsg); GetClientListFromEeprom(); break; case eBusDevReqGetClientAddr: sTxBusMsg.senderAddr = MY_ADDR; sTxBusMsg.type = eBusDevRespGetClientAddr; sTxBusMsg.msg.devBus.receiverAddr = spRxBusMsg->senderAddr; for (i = 0; i < BUS_MAX_CLIENT_NUM; i++) { p = &(sTxBusMsg.msg.devBus.x.devResp.getClientAddr.clientAddr[i]); *p = eeprom_read_byte((const uint8_t *)(CLIENT_ADDRESS_BASE + i)); } BusSend(&sTxBusMsg); break; case eBusDevReqInfo: sTxBusMsg.type = eBusDevRespInfo; sTxBusMsg.senderAddr = MY_ADDR; sTxBusMsg.msg.devBus.receiverAddr = spRxBusMsg->senderAddr; sTxBusMsg.msg.devBus.x.devResp.info.devType = eBusDevTypeWind; strncpy((char *)(sTxBusMsg.msg.devBus.x.devResp.info.version), version, BUS_DEV_INFO_VERSION_LEN); sTxBusMsg.msg.devBus.x.devResp.info.version[BUS_DEV_INFO_VERSION_LEN - 1] = '\0'; BusSend(&sTxBusMsg); break; case eBusDevReqSetAddr: sTxBusMsg.senderAddr = MY_ADDR; sTxBusMsg.type = eBusDevRespSetAddr; sTxBusMsg.msg.devBus.receiverAddr = spRxBusMsg->senderAddr; p = &(spRxBusMsg->msg.devBus.x.devReq.setAddr.addr); eeprom_write_byte((uint8_t *)MODUL_ADDRESS, *p); BusSend(&sTxBusMsg); break; case eBusDevReqEepromRead: sTxBusMsg.senderAddr = MY_ADDR; sTxBusMsg.type = eBusDevRespEepromRead; sTxBusMsg.msg.devBus.receiverAddr = spRxBusMsg->senderAddr; sTxBusMsg.msg.devBus.x.devResp.readEeprom.data = eeprom_read_byte((const uint8_t *)spRxBusMsg->msg.devBus.x.devReq.readEeprom.addr); BusSend(&sTxBusMsg); break; case eBusDevReqEepromWrite: sTxBusMsg.senderAddr = MY_ADDR; sTxBusMsg.type = eBusDevRespEepromWrite; sTxBusMsg.msg.devBus.receiverAddr = spRxBusMsg->senderAddr; p = &(spRxBusMsg->msg.devBus.x.devReq.writeEeprom.data); eeprom_write_byte((uint8_t *)spRxBusMsg->msg.devBus.x.devReq.readEeprom.addr, *p); BusSend(&sTxBusMsg); break; default: break; } }