Exemple #1
0
static int TestTelegram(TBusTelegram *pTxMsg, uint8_t msgSize) {

    TBusTelegram    *pRxMsg = BusMsgBufGet();
    int             timeout;
    uint8_t         zerobuf[sizeof(TBusTelegram)];

    memset(zerobuf, 0, sizeof(zerobuf));
    memset(pRxMsg, 0, sizeof(*pRxMsg));
    if (BusSend(pTxMsg) != BUS_SEND_OK) {
        return -1;
    }
    for (timeout = 0; (timeout < RX_TIMEOUT) && (BusCheck() != BUS_MSG_OK); timeout++) {
    	usleep(1000);
    }

    if (timeout < RX_TIMEOUT) {
        if (memcmp(pTxMsg, pRxMsg, msgSize) != 0) {
        	return -1;
        }
        if (memcmp((uint8_t *)pRxMsg + msgSize, zerobuf, sizeof(TBusTelegram) - msgSize) != 0) {
        	return -1;
        }
    } else {
    	return -1;
    }
    return 0;
}
Exemple #2
0
/*-----------------------------------------------------------------------------
*  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);
}
Exemple #3
0
/*-----------------------------------------------------------------------------
*  program start
*/
int main(int argc, char *argv[]) {

    int           i;
    int           j;
    char          comPort[SIZE_COMPORT] = "";
    uint8_t       myAddr;
    bool          myAddrValid = false;
    TBusTelegram  txBusMsg;
    uint8_t       busRet;
    TBusTelegram  *pRxBusMsg;
    uint8_t       mask;
    int           flags;
    int           sioHandle;
    int           sioFd;
    fd_set        rfds;
    int           ret;
    uint8_t       val8;
    char          buffer[SIZE_CMD_BUF];
    char          *p;

    signal(SIGPIPE, sighandler);

    flags = fcntl(fileno(stdout), F_GETFL);
    fcntl(fileno(stdout), F_SETFL, flags | O_NONBLOCK);

    /* get com interface */
    for (i = 1; i < argc; i++) {
        if (strcmp(argv[i], "-c") == 0) {
            if (argc > i) {
                strncpy(comPort, argv[i + 1], sizeof(comPort) - 1);
                comPort[sizeof(comPort) - 1] = '\0';
            }
            break;
        }
    }

    /* our bus address */
    for (i = 1; i < argc; i++) {
        if (strcmp(argv[i], "-a") == 0) {
            if (argc > i) {
                myAddr = atoi(argv[i + 1]);
                myAddrValid = true;
            }
            break;
        }
    }

    if ((strlen(comPort) == 0) ||
        !myAddrValid) {
        PrintUsage();
        return 0;
    }

    sioHandle = InitBus(comPort);
    if (sioHandle == -1) {
        printf("cannot open %s\r\n", comPort);
        return -1;
    }
    sioFd = SioGetFd(sioHandle);


    for (;;) {
        FD_ZERO(&rfds);
        FD_SET(sioFd, &rfds);
        FD_SET(STDIN_FILENO, &rfds);
        ret = select(sioFd + 1, &rfds, 0, 0, 0);
        if ((ret > 0) && FD_ISSET(sioFd, &rfds)) {
            busRet = BusCheck();
            if (busRet == BUS_MSG_OK) {
                pRxBusMsg = BusMsgBufGet();
                if ((pRxBusMsg->type == eBusDevReqActualValueEvent) &&
                    ((pRxBusMsg->msg.devBus.receiverAddr == myAddr))) {
                    Print("event address %d device type ", pRxBusMsg->senderAddr);
                    switch (pRxBusMsg->msg.devBus.x.devReq.actualValueEvent.devType) {
                    case eBusDevTypeDo31:
                        Print("DO31\n");
                        for (i = 0; i < BUS_DO31_DIGOUT_SIZE_ACTUAL_VALUE; i++) {
                            for (j = 0, mask = 1; j < 8; j++, mask <<= 1) {
                                if ((i == 3) && (j == 7)) {
                                    // DO31 has 31 outputs, dont display the last bit
                                    break;
                                }
                                if (pRxBusMsg->msg.devBus.x.devReq.actualValueEvent.actualValue.do31.digOut[i] & mask) {
                                    Print("1");
                                } else {
                                    Print("0");
                                }
                            }
                        }
                        Print("\n");
                        for (i = 0; i < BUS_DO31_SHADER_SIZE_ACTUAL_VALUE; i++) {
                            Print("%02x",
                                pRxBusMsg->msg.devBus.x.devReq.actualValueEvent.actualValue.do31.shader[i]);
                            if (i < (BUS_DO31_SHADER_SIZE_ACTUAL_VALUE - 1)) {
                                Print(" ");
                            }
                        }
                        memcpy(txBusMsg.msg.devBus.x.devResp.actualValueEvent.actualValue.do31.digOut,
                               pRxBusMsg->msg.devBus.x.devReq.actualValueEvent.actualValue.do31.digOut,
                               BUS_DO31_DIGOUT_SIZE_ACTUAL_VALUE);
                        memcpy(txBusMsg.msg.devBus.x.devResp.actualValueEvent.actualValue.do31.shader,
                               pRxBusMsg->msg.devBus.x.devReq.actualValueEvent.actualValue.do31.shader,
                               BUS_DO31_SHADER_SIZE_ACTUAL_VALUE);
                        txBusMsg.msg.devBus.x.devResp.actualValueEvent.devType = eBusDevTypeDo31;
                        break;
                    case eBusDevTypeSw8:
                        Print("SW8\n");
                        val8 = pRxBusMsg->msg.devBus.x.devReq.actualValueEvent.actualValue.sw8.state;
                        for (i = 0, mask = 1; i < 8; i++, mask <<= 1) {
                            if (val8 & mask) {
                                Print("1");
                            } else {
                                Print("0");
                            }
                        }
                        txBusMsg.msg.devBus.x.devResp.actualValueEvent.actualValue.sw8.state = val8;
                        txBusMsg.msg.devBus.x.devResp.actualValueEvent.devType = eBusDevTypeSw8;
                        break;
                    default:
                        break;
                    }
                    Print("\n");
                    fflush(stdout);
                    txBusMsg.type = eBusDevRespActualValueEvent;
                    txBusMsg.senderAddr = pRxBusMsg->msg.devBus.receiverAddr;
                    txBusMsg.msg.devBus.receiverAddr = pRxBusMsg->senderAddr;
                    BusSend(&txBusMsg);
                }
            } else if (busRet == BUS_IF_ERROR) {
                Print("bus interface access error - exiting\n");
                break;
            }
        }
        if ((ret > 0) && FD_ISSET(STDIN_FILENO, &rfds)) {
            p = fgets(buffer, sizeof(buffer), stdin);
            if (p == 0) {
                printf("error/EOF on reading from stdin. exiting\n");
                ret = -1;
                break;
            }
            if (strcmp("-exit\n", p) == 0) {
                Print("OK\n");
                break;
            }
        }
    }

    SioClose(sioHandle);
    return ret;
}
Exemple #4
0
/*-----------------------------------------------------------------------------
*  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;
    }
}
Exemple #5
0
/*-----------------------------------------------------------------------------
*   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;
    }
}
Exemple #6
0
/*-----------------------------------------------------------------------------
*  program start
*/
int main(void) {

   UINT8   ret;  
   UINT16  flashWordAddr;    
   UINT16  sum;

   cli();
   MCUSR = 0;
   wdt_disable();

   /* get oscillator correction value from EEPROM */
   EEAR = OSCCAL_CORR;
   /* Start eeprom read by writing EERE */
   EECR |= (1 << EERE);
   /* read data */
   OSCCAL += EEDR;

   /* get modul adress from EEPROM */
   EEAR = MODUL_ADDRESS;
   /* Start eeprom read by writing EERE */
   EECR |= (1 << EERE);
   /* read data */
   sMyAddr = EEDR;

   /* configure pins to input with pull up */
   PORTB = 0b11111111;
   DDRB =  0b00000000;

   PORTC = 0b11111111;
   DDRC =  0b00000000;

   PORTD = 0b11111111;
   DDRD =  0b00100010;

   /* configure Timer 0 */
   /* prescaler clk/64 -> Interrupt period 256/1000000 * 64 = 16.384 ms */
   TCCR0B = 3 << CS00; 
   TIMSK0 = 1 << TOIE0;

   SioInit();
   spRxBusMsg = BusMsgBufGet();

   /* Enable change of Interrupt Vectors */
   MCUCR = (1 << IVCE);
   /* Move interrupts to Boot Flash section */
   MCUCR = (1 << IVSEL);

   /* Prüfsumme der Applikation berechnen */
   sum = 0;
   for (flashWordAddr = 0; flashWordAddr < (MAX_FIRMWARE_SIZE / 2); flashWordAddr += CHECKSUM_BLOCK_SIZE) {
      sum += FlashSum(flashWordAddr, (UINT8)CHECKSUM_BLOCK_SIZE);
   }

   if (sum != FLASH_CHECKSUM) {
      /* Fehler */
      sFwuState = WAIT_FOR_UPD_ENTER;      
   }
   sei();
      
   /* Startup-Msg senden */
   sTxBusMsg.type = eBusDevStartup;  
   sTxBusMsg.senderAddr = MY_ADDR; 
   BusSend(&sTxBusMsg);  
   SioReadFlush();
 
   /* Hauptschleife */
   while (1) {   
      ret = BusCheck();
      ProcessBus(ret);
      /* Mit timeout auf Request zum Firmwareupdate warten  */
      if (sFwuState == WAIT_FOR_UPD_ENTER_TIMEOUT) {
         if (gTimeS8 >= 4) {
            /* Application starten */
            break;
         }
      } 
   } 
            
   cli();
   
   /* Enable change of Interrupt Vectors */
   MCUCR = (1 << IVCE);
   /* Move interrupts to application section */
   MCUCR = (0 << IVSEL);

   /* jump to application */
   ApplicationEntry();
   
   /* never reach this */
   return 0;
} 
Exemple #7
0
/*-----------------------------------------------------------------------------
*  Verarbeitung der Bustelegramme
*/
static void ProcessBus(UINT8 ret) {
   
   TBusMsgType   msgType;    
   UINT16        *pData;
   UINT16        wordAddr;
   BOOL          rc;
   BOOL          msgForMe = FALSE;

   if (ret == BUS_MSG_OK) {
      msgType = spRxBusMsg->type; 
      switch (msgType) {  
         case eBusDevReqReboot:
         case eBusDevReqUpdEnter:
         case eBusDevReqUpdData:
         case eBusDevReqUpdTerm:
            if (spRxBusMsg->msg.devBus.receiverAddr == MY_ADDR) {
               msgForMe = TRUE;
            }
         default:
            break;
      }
      if (msgForMe == FALSE) {
         return;
      }

    
      if (msgType == eBusDevReqReboot) {
         /* Über Watchdog Reset auslösen */    
         /* Watchdogtimeout auf kurzeste Zeit (14 ms) stellen */                     
         cli();
         wdt_enable(WDTO_15MS);
         /* warten auf Reset */
         while (1);
      } else {
         switch (sFwuState) {
            case WAIT_FOR_UPD_ENTER_TIMEOUT:
            case WAIT_FOR_UPD_ENTER:
               if (msgType == eBusDevReqUpdEnter) {
                  /* Applicationbereich des Flash löschen */  
                  FlashErase();
                  /* Antwort senden */
                  SetMsg(eBusDevRespUpdEnter, spRxBusMsg->senderAddr);
                  BusSend(&sTxBusMsg);
                  sFwuState = WAIT_FOR_UPD_DATA;     
               }           
               break;
            case WAIT_FOR_UPD_DATA:
               if (msgType == eBusDevReqUpdData) {
                  wordAddr = spRxBusMsg->msg.devBus.x.devReq.updData.wordAddr;
                  pData = spRxBusMsg->msg.devBus.x.devReq.updData.data;
                  /* Flash programmieren */
                  rc = FlashProgram(wordAddr, pData, sizeof(spRxBusMsg->msg.devBus.x.devReq.updData.data) / 2);
                  /* Antwort senden */
                  SetMsg(eBusDevRespUpdData, spRxBusMsg->senderAddr);
                  if (rc == TRUE) {
                     /* Falls Programmierung des Block OK: empfangene wordAddr zurücksenden */
                     sTxBusMsg.msg.devBus.x.devResp.updData.wordAddr = wordAddr;
                  } else {
                     /* Problem bei Programmierung: -1 als wordAddr zurücksenden */
                     sTxBusMsg.msg.devBus.x.devResp.updData.wordAddr = -1;
                  }
                  BusSend(&sTxBusMsg);  
               } else if (msgType == eBusDevReqUpdTerm) {
                  /* programmiervorgang im Flash abschließen (falls erforderlich) */
                  rc = FlashProgramTerminate();
                  /* Antwort senden */
                  SetMsg(eBusDevRespUpdTerm, spRxBusMsg->senderAddr);
                  if (rc == TRUE) {
                     /* Falls Programmierung OK: success auf 1 setzen */
                     sTxBusMsg.msg.devBus.x.devResp.updTerm.success = 1;
                  } else {
                     /* Problem bei Programmierung: -1 als wordAddr zurücksenden */
                     sTxBusMsg.msg.devBus.x.devResp.updTerm.success = 0;
                  }
                  BusSend(&sTxBusMsg);
               }
               break;
            default:
               break;
         }
      }
   }
}
Exemple #8
0
/*-----------------------------------------------------------------------------
*  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[0];
            for (i = 0; i < BUS_MAX_CLIENT_NUM; i++) {
               if (pClient->state == eSkip) {
                  pClient++;
                  continue;
               } else if ((pClient->address == spRxBusMsg->senderAddr) &&
                          (spRxBusMsg->msg.devBus.x.devResp.switchState.switchState == sSwitchStateActual) &&
                          ((pClient->state == eWaitForConfirmation1) ||
                           (pClient->state == eWaitForConfirmation2))) {
                  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 = eBusDevTypeSw8;
            sTxBusMsg.msg.devBus.x.devResp.actualValue.actualValue.sw8.state = sSwitchStateActual;
            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);  
            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 = eBusDevTypeSw8;
            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;
      }   
   }
}
Exemple #9
0
/*-----------------------------------------------------------------------------
*  send button pressed telegram
*  telegram is repeated every 48 ms for max 8 secs 
*/
static void ProcessButton(uint8_t buttonState) {

   static uint8_t  sSequenceState = BUTTON_TX_OFF;
   static uint16_t sStartTimeS;
   static uint8_t  sTimeStampMs;
   bool            pressed;
   uint16_t        actualTimeS;
   uint8_t         actualTimeMs;

   /* buttons pull down pins to ground when pressed */
   switch (buttonState) {
      case 0:
         sTxBusMsg.type = eBusButtonPressed1_2;
         pressed = true;
         break;
      case 1:
         sTxBusMsg.type = eBusButtonPressed2;
         pressed = true;
         break;
      case 2:
         sTxBusMsg.type = eBusButtonPressed1;
         pressed = true;
         break;
      default:
         pressed = false;
         break;
   }

   switch (sSequenceState) {
      case BUTTON_TX_OFF:
         if (pressed) {
            /* begin transmission of eBusButtonPressed* telegram */
            GET_TIME_S(sStartTimeS);
            sTimeStampMs = GET_TIME_MS;
            sTxBusMsg.senderAddr = MY_ADDR;
            BusSend(&sTxBusMsg);
            sSequenceState = BUTTON_TX_ON;
         }
         break;
      case BUTTON_TX_ON:
         if (pressed) {
            GET_TIME_S(actualTimeS);
            if ((uint16_t)(actualTimeS - sStartTimeS) < BUTTON_TELEGRAM_REPEAT_TIMEOUT) {
               actualTimeMs = GET_TIME_MS; 
               if ((uint8_t)(actualTimeMs - sTimeStampMs) >= BUTTON_TELEGRAM_REPEAT_DIFF) {
                  sTimeStampMs = GET_TIME_MS;
                  sTxBusMsg.senderAddr = MY_ADDR;
                  BusSend(&sTxBusMsg);
               }
            } else {
               sSequenceState = BUTTON_TX_TIMEOUT;
            }
         } else {
            sSequenceState = BUTTON_TX_OFF;
         }
         break;
      case BUTTON_TX_TIMEOUT:
         if (!pressed) {
            sSequenceState = BUTTON_TX_OFF;
         }
         break;
      default:
         sSequenceState = BUTTON_TX_OFF;
         break;
   }
}
Exemple #10
0
/*-----------------------------------------------------------------------------
*  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;
      }
   }
}
Exemple #11
0
/*-----------------------------------------------------------------------------
*   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 
    }
}
Exemple #12
0
/*-----------------------------------------------------------------------------
*  Programstart
*/
int main(void) {

   UINT8   ret;  
   UINT16  flashWordAddr;    
   UINT16  sum;

   /* get oscillator correction value from EEPROM */
   EEAR = OSCCAL_CORR;
   /* Start eeprom read by writing EERE */
   EECR |= (1 << EERE);
   /* read data */
   OSCCAL += EEDR;

   /* get modul adress from EEPROM */
   EEAR = MODUL_ADDRESS;
   /* Start eeprom read by writing EERE */
   EECR |= (1 << EERE);
   /* read data */
   sMyAddr = EEDR;

   /* Portpins für Schaltereingänge mit Pullup konfigurieren */
   /* nicht benutzte Pin aus Ausgang Low*/
   PORTC = 0x03;
   DDRC = 0x3C;             
   
   PORTB = 0x38;
   DDRB = 0xC7;
   
   PORTD = 0x01;
   DDRD = 0xFE;

   /* configure Timer 0 */
   /* prescaler clk/64 -> Interrupt period 256/1000000 * 64 = 16.384 ms */
   TCCR0 = 3 << CS00; 
   TIMSK = 1 << TOIE0;

   SioInit();
   spRxBusMsg = BusMsgBufGet();

   /* Umschaltung der Interruptvektor-Tabelle */
   GICR = (1 << IVCE);
   /* In Bootbereich verschieben */
   GICR = (1 << IVSEL);

   /* Prüfsumme der Applikation berechnen */
   sum = 0;
   for (flashWordAddr = 0; flashWordAddr < (MAX_FIRMWARE_SIZE / 2); flashWordAddr += CHECKSUM_BLOCK_SIZE) {
      sum += FlashSum(flashWordAddr, (UINT8)CHECKSUM_BLOCK_SIZE);
   }

   if (sum != FLASH_CHECKSUM) {
      /* Fehler */
      sFwuState = WAIT_FOR_UPD_ENTER;      
   }

   sei();
                          
   /* Startup-Msg senden */
   sTxBusMsg.type = eBusDevStartup;  
   sTxBusMsg.senderAddr = MY_ADDR; 
   BusSend(&sTxBusMsg);  
   SioReadFlush();
   
   /* Hauptschleife */
   while (1) {   
      ret = BusCheck();
      ProcessBus(ret);
      /* Mit timeout auf Request zum Firmwareupdate warten  */
      if (sFwuState == WAIT_FOR_UPD_ENTER_TIMEOUT) {
         if (gTimeS8 >= 4) {
            /* Application starten */
            break;
         }
      } 
   } 
            
   cli();
   /* Umschaltung der Interruptvektor-Tabelle */
   GICR = (1 << IVCE);
   /* In Applikationsbereich verschieben */
   GICR = (0 << IVSEL);
   
   /* zur Applikation springen */       
   ApplicationEntry();
   /* hier kommen wir nicht her!!*/
   return 0;
} 
Exemple #13
0
/*-----------------------------------------------------------------------------
*  process received bus telegrams
*/
static void ProcessBus(void) {

   uint8_t     ret;
   TBusMsgType msgType;
   uint8_t     i;
   uint8_t     *p;
   bool        msgForMe = false;
   uint8_t     flags;

   uint8_t         old_osccal;
   static uint8_t  sOsccal = 0;
   uint16_t        startCnt;
   uint16_t        stopCnt;
   uint16_t        clocks;
   uint16_t        diff;
   uint16_t        seqLen;
   static int      sCount = 0;
   static uint16_t sMinDiff = 0xffff;
   static uint8_t  sMinOsccal = 0;
   uint8_t         osccal_corr;
   
   ret = BusCheck();

   if (ret == BUS_MSG_OK) {
      msgType = spRxBusMsg->type; 
      switch (msgType) {  
         case eBusDevReqReboot:
         case eBusDevReqInfo:
         case eBusDevReqSetAddr:
         case eBusDevReqEepromRead:
         case eBusDevReqEepromWrite:
         case eBusDevReqDoClockCalib:
            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 eBusDevReqInfo:
            sTxBusMsg.type = eBusDevRespInfo;  
            sTxBusMsg.senderAddr = MY_ADDR; 
            sTxBusMsg.msg.devBus.receiverAddr = spRxBusMsg->senderAddr;
            sTxBusMsg.msg.devBus.x.devResp.info.devType = eBusDevTypeSw8Cal;
            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;
         case eBusDevReqDoClockCalib:
            if (spRxBusMsg->msg.devBus.x.devReq.doClockCalib.command == eBusDoClockCalibInit) {
                sCount = 0;
                sOsccal = 0;
                sMinDiff = 0xffff;
            } else if (sCount > MAX_CAL_TEL) {
                sTxBusMsg.msg.devBus.x.devResp.doClockCalib.state = eBusDoClockCalibStateError;
                sTxBusMsg.senderAddr = MY_ADDR; 
                sTxBusMsg.type = eBusDevRespDoClockCalib;
                sTxBusMsg.msg.devBus.receiverAddr = spRxBusMsg->senderAddr;
                BusSend(&sTxBusMsg);
                break;
            }

            flags = DISABLE_INT;

            BUS_TRANSCEIVER_POWER_UP;
            PORTB = 0;

            /* 8 bytes 0x00: 8 * (1 start bit + 8 data bits) + 7 stop bits  */
            seqLen = 8 * 1000000 * 9 / 9600 + 7 * 1000000 * 1 / 9600; /* = 8229 us */
            old_osccal = OSCCAL;

            ExitComm();
            InitTimer1();

            TCCR1B = (1 << ICES1) | TIMER1_PRESCALER;

            OSCCAL = sOsccal;
            NOP_10;
            
            for (i = 0; i < 8; i++) {
                startCnt = Synchronize();
                stopCnt = ClkMeasure();
                
                clocks = stopCnt - startCnt;
                if (clocks > seqLen) {
                    diff = clocks - seqLen;
                } else {
                    diff = seqLen - clocks;
                }
                if (diff < sMinDiff) {
                    sMinDiff = diff;
                    sMinOsccal = OSCCAL;
                }
                OSCCAL++;
                NOP_4;
            }

            BUS_TRANSCEIVER_POWER_DOWN;

            InitTimer1();
            InitComm();
            sOsccal = OSCCAL;
            OSCCAL = old_osccal;

            RESTORE_INT(flags);

            if (sCount < MAX_CAL_TEL) { 
                sTxBusMsg.msg.devBus.x.devResp.doClockCalib.state = eBusDoClockCalibStateContiune;
                sCount++;
            } else {
                sTxBusMsg.msg.devBus.x.devResp.doClockCalib.state = eBusDoClockCalibStateSuccess;
                /* save the osccal correction value to eeprom */
                osccal_corr = eeprom_read_byte((const uint8_t *)OSCCAL_CORR);
                osccal_corr += sMinOsccal - old_osccal;
                eeprom_write_byte((uint8_t *)OSCCAL_CORR, osccal_corr);
                OSCCAL = sMinOsccal;
                NOP_10;
            }
            sTxBusMsg.senderAddr = MY_ADDR; 
            sTxBusMsg.type = eBusDevRespDoClockCalib;
            sTxBusMsg.msg.devBus.receiverAddr = spRxBusMsg->senderAddr;
            BusSend(&sTxBusMsg);  
            break;
         default:
            break;
      }   
   }
}