// ************************************************************************************************* // @fn simpliciti_main_sync // @brief Send ready-to-receive packets in regular intervals. Listen shortly for host reply. // Decode received host command and trigger action. // @param none // @return none // ************************************************************************************************* void simpliciti_main_sync(void) { uint8_t len, i; uint8_t ed_data[2]; while (1) { // Sleep 0.5sec between ready-to-receive packets // SimpliciTI has no low power delay function, so we have to use ours Timer0_A4_Delay(CONV_MS_TO_TICKS(500)); // Get radio ready. Radio wakes up in IDLE state. SMPL_Ioctl(IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_AWAKE, 0); // Send 2 byte long ready-to-receive packet to stimulate host reply ed_data[0] = SYNC_ED_TYPE_R2R; ed_data[1] = 0xCB; SMPL_SendOpt(sLinkID1, ed_data, 2, SMPL_TXOPTION_NONE); // Wait shortly for host reply SMPL_Ioctl(IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_RXON, 0); NWK_DELAY(10); // Check if a command packet was received while (SMPL_Receive(sLinkID1, simpliciti_data, &len) == SMPL_SUCCESS) { // Decode received data if (len > 0) { // Use callback function in application to decode data and react simpliciti_sync_decode_ap_cmd_callback(); // Get reply data and send out reply packet burst (19 bytes each) for (i = 0; i < simpliciti_reply_count; i++) { NWK_DELAY(10); simpliciti_sync_get_data_callback(i); SMPL_SendOpt(sLinkID1, simpliciti_data, BM_SYNC_DATA_LENGTH, SMPL_TXOPTION_NONE); } } } // Put radio back to sleep SMPL_Ioctl(IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_SLEEP, 0); // Service watchdog WDTCTL = WDTPW + WDTIS__512K + WDTSSEL__ACLK + WDTCNTCL; // Exit when flag bit SIMPLICITI_TRIGGER_STOP is set if (getFlag(simpliciti_flag, SIMPLICITI_TRIGGER_STOP)) { // Clean up SimpliciTI stack to enable restarting sInit_done = 0; break; } } }
// ************************************************************************************************* // @fn simpliciti_main_tx_only // @brief Get data through callback. Transfer data when external trigger is set. // @param none // @return none // ************************************************************************************************* void simpliciti_main_tx_only(void) { while (1) { // Get end device data from callback function simpliciti_get_ed_data_callback(); // Send data when flag bit SIMPLICITI_TRIGGER_SEND_DATA is set if (getFlag(simpliciti_flag, SIMPLICITI_TRIGGER_SEND_DATA)) { // Get radio ready. Wakes up in IDLE state. SMPL_Ioctl(IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_AWAKE, 0); // Acceleration / button events packets are 4 bytes long SMPL_SendOpt(sLinkID1, simpliciti_data, 4, SMPL_TXOPTION_NONE); // Put radio back to SLEEP state SMPL_Ioctl(IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_SLEEP, 0); clearFlag(simpliciti_flag, SIMPLICITI_TRIGGER_SEND_DATA); } // Exit when flag bit SIMPLICITI_TRIGGER_STOP is set if (getFlag(simpliciti_flag, SIMPLICITI_TRIGGER_STOP)) { // Clean up SimpliciTI stack to enable restarting sInit_done = 0; break; } } }
critical void sendToRep(packet_t *thePacket) { int i; for (i = 0; i < 10; i++) { if (SMPL_SUCCESS == SMPL_SendOpt(myLinkID, (uint8_t *) thePacket, thePacket->dlen + HEADER_SIZE, SMPL_TXOPTION_ACKREQ)) { break; } } }
void main() { BSP_Init(); // Initialisation de la librairie BSP NWK_DELAY(500); SMPL_Init(0); // Initialisation de la librairie SimpliciTI SMPL_Ioctl(IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_AWAKE, 0); // Initialisation Timer A BCSCTL3 |= LFXT1S_2; // LFXT1 = VLO TACCTL0 = CCIE; // TACCR0 interrupt enabled msg[0] = '#'; msg[1] = REPERE_ID; msg[2] = ':'; msg[3] = 'V'; msg[4] = 0; msg[5] = 0xFF; timeCounter = 250; unsyncRepere(); while (1) { SMPL_Ioctl(IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_SLEEP, 0); __bis_SR_register(LPM3_bits + GIE); SMPL_Ioctl(IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_AWAKE, 0); SMPL_SendOpt(SMPL_LINKID_USER_UUD, msg, sizeof(msg), SMPL_TXOPTION_NONE); BSP_TOGGLE_LED1(); if (timeCounter >= 300) // Quand timeCounter a été incrémenté depuis 1 minute (0.2sec x 300) { voltAction(); msg[4] = ((uint8_t*)&volt)[3]; timeCounter = 0; } } }
/****************************************************************************** * @fn SMPL_Send * * @brief Send a message to a peer application. Old API kept for * backward compatibility. Calls the new SMPL_SendOpt() with * no options. * * input parameters * @param lid - Link ID (port) from application * @param msg - pointer to message from app to be sent * @param len - length of enclosed message * * output parameters * * @return Status of operation. On a filaure the frame buffer is discarded * and the Send call must be redone by the app. * SMPL_SUCCESS * SMPL_BAD_PARAM No valid Connection Table entry for Link ID * Data in Connection Table entry bad * No message or message too long * SMPL_NOMEM No room in output frame queue * SMPL_TX_CCA_FAIL CCA failure. */ smplStatus_t SMPL_Send(linkID_t lid, uint8_t *msg, uint8_t len) { return SMPL_SendOpt(lid, msg, len, SMPL_TXOPTION_NONE); }
static void linkTo() { uint8_t msg[2]; uint8_t button, misses, done; /* Keep trying to link... */ while (SMPL_SUCCESS != SMPL_Link(&sLinkID1)) { toggleLED(1); toggleLED(2); SPIN_ABOUT_A_SECOND; } /* Turn off LEDs. */ if (BSP_LED2_IS_ON()) { toggleLED(2); } if (BSP_LED1_IS_ON()) { toggleLED(1); } /* sleep until button press... */ SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_SLEEP, 0); while (1) { button = 0; /* Send a message when either button pressed */ if (BSP_BUTTON1()) { SPIN_ABOUT_A_QUARTER_SECOND; /* debounce... */ /* Message to toggle LED 1. */ button = 1; } else if (BSP_BUTTON2()) { SPIN_ABOUT_A_QUARTER_SECOND; /* debounce... */ /* Message to toggle LED 2. */ button = 2; } if (button) { uint8_t noAck; smplStatus_t rc; /* get radio ready...awakens in idle state */ SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_AWAKE, 0); /* Set TID and designate which LED to toggle */ msg[1] = ++sTid; msg[0] = (button == 1) ? 1 : 2; done = 0; while (!done) { noAck = 0; /* Try sending message MISSES_IN_A_ROW times looking for ack */ for (misses=0; misses < MISSES_IN_A_ROW; ++misses) { if (SMPL_SUCCESS == (rc=SMPL_SendOpt(sLinkID1, msg, sizeof(msg), SMPL_TXOPTION_ACKREQ))) { /* Message acked. We're done. Toggle LED 1 to indicate ack received. */ toggleLED(1); break; } if (SMPL_NO_ACK == rc) { /* Count ack failures. Could also fail becuase of CCA and * we don't want to scan in this case. */ noAck++; } } if (MISSES_IN_A_ROW == noAck) { /* Message not acked. Toggle LED 2. */ toggleLED(2); #ifdef FREQUENCY_AGILITY /* Assume we're on the wrong channel so look for channel by * using the Ping to initiate a scan when it gets no reply. With * a successful ping try sending the message again. Otherwise, * for any error we get we will wait until the next button * press to try again. */ if (SMPL_SUCCESS != SMPL_Ping(sLinkID1)) { done = 1; } #else done = 1; #endif /* FREQUENCY_AGILITY */ } else { /* Got the ack or we don't care. We're done. */ done = 1; } } /* radio back to sleep */ SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_SLEEP, 0); } } }
// ************************************************************************************************* // @fn simpliciti_main_tx_only // @brief Get data through callback. Transfer data when external trigger is set. // @param none // @return none // ************************************************************************************************* void simpliciti_main_tx_only(void) { uint8_t len, i; uint8_t ed_data[2]; while(1) { // Get end device data from callback function simpliciti_get_ed_data_callback(); // Get radio ready. Wakes up in IDLE state. if(getFlag(simpliciti_flag, SIMPLICITI_TRIGGER_SEND_DATA) || getFlag(simpliciti_flag, SIMPLICITI_TRIGGER_RECEIVE_DATA)) { SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_AWAKE, 0); // Send data when flag bit SIMPLICITI_TRIGGER_SEND_DATA is set if (getFlag(simpliciti_flag, SIMPLICITI_TRIGGER_SEND_DATA)) { // Acceleration / button events packets are 4 bytes long SMPL_SendOpt(sLinkID1, simpliciti_data, simpliciti_payload_length, SMPL_TXOPTION_NONE); //SMPL_SendOpt(sLinkID1, simpliciti_data, simpliciti_payload_length, simpliciti_options); // reset options to default //simpliciti_options = SMPL_TXOPTION_NONE; clearFlag(simpliciti_flag, SIMPLICITI_TRIGGER_SEND_DATA); } // Receive data when flag bit SIMPLICITI_TRIGGER_RECEIVE_DATA is set if (getFlag(simpliciti_flag, SIMPLICITI_TRIGGER_RECEIVE_DATA)) { // Send 2 byte long ready-to-receive packet to stimulate host reply clearFlag(simpliciti_flag, SIMPLICITI_TRIGGER_RECEIVE_DATA); // clean up tha buffer first simpliciti_data[0] = 0x00; simpliciti_data[1] = 0x00; simpliciti_data[3] = 0x00; simpliciti_data[4] = 0x00; // generate a ready to receive packet ed_data[0] = SYNC_ED_TYPE_R2R; ed_data[1] = 0xCB; SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_RXON, 0); // we try to receive 9 times by sending a R2R packet for (i = 0; i < 10; i++) { SMPL_SendOpt(sLinkID1, ed_data, 2, SMPL_TXOPTION_NONE); //WDTCTL = WDTPW + WDTHOLD; // Wait shortly for host reply NWK_DELAY(10); while (SMPL_Receive(sLinkID1, simpliciti_data, &len) == SMPL_SUCCESS) { if (len > 0) { // Decode received data if(simpliciti_get_rvc_callback(len)) { // stop retry loop i = 10; break; } } } Timer0_A4_Delay(CONV_MS_TO_TICKS(500)); } } // Put radio back to SLEEP state SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_SLEEP, 0); } // Exit when flag bit SIMPLICITI_TRIGGER_STOP is set if (getFlag(simpliciti_flag, SIMPLICITI_TRIGGER_STOP)) { // Clean up SimpliciTI stack to enable restarting sInit_done = 0; break; } } }
//***************************************************************************** // // Link to the access point and continue processing local button requests // forever. This function is called following initialization in main() and // does not return. // //***************************************************************************** static void LinkTo(void) { uint8_t pucMsg[2]; uint8_t ucMisses, ucDone; uint8_t ucNoAck; smplStatus_t eRetcode; unsigned long ulButton; UpdateStatus(false, "Linking to Access Point"); // // Keep trying to link. Flash our "LEDs" while these attempts continue. // while (SMPL_SUCCESS != SMPL_Link(&g_sLinkID)) { ToggleLED(1); ToggleLED(2); SPIN_ABOUT_A_SECOND; } // // Turn off both LEDs now that we are linked. // SetLED(1, false); SetLED(2, false); // // Tell the user all is well. // UpdateStatus(false, "Link successful"); // // Put the radio to sleep until a button is pressed. // SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_SLEEP, 0); // // Start of the main button processing loop. // while (1) { // // Grab the button press flag and clear it. We do this since the flag // could be changed during the loop whenever function // WidgetMessageQueueProcess() is called and we don't want to miss any // button presses. // ulButton = g_ulButtonPressed; // // Has either button been pressed? // if (ulButton) { // // Clear the main button press flag. // g_ulButtonPressed = 0; // // Wake the radio up since we are about to need it. // SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_AWAKE, 0); /* Set TID and designate which LED to toggle */ pucMsg[1] = ++g_ucTid; pucMsg[0] = (ulButton == 1) ? 1 : 2; ucDone = 0; while (!ucDone) { // // Remember that we have yet to receive an ack from the AP. // ucNoAck = 0; // // Try sending the message MISSES_IN_A_ROW times looking for an // ack after each transmission. // for (ucMisses = 0; ucMisses < MISSES_IN_A_ROW; ucMisses++) { // // Send the message and request acknowledgement. // eRetcode=SMPL_SendOpt(g_sLinkID, pucMsg, sizeof(pucMsg), SMPL_TXOPTION_ACKREQ); // // Did we get the ack? // if (eRetcode == SMPL_SUCCESS) { // // Yes - Message acked. We're done. Toggle LED 1 to // indicate ack received. */ ToggleLED(1); break; } // // Did we send the message but fail to get an ack back? // if (SMPL_NO_ACK == eRetcode) { // // Count ack failures. Could also fail because of CCA // and we don't want to scan in this case. // ucNoAck++; } } // // Did we fail to get an ack after every transmission? // if (MISSES_IN_A_ROW == ucNoAck) { // // Tell the user what happened. // UpdateStatus(false, "Channel changed?"); // // Message not acked. Toggle LED 2. // ToggleLED(2); #ifdef FREQUENCY_AGILITY // // At this point, we assume we're on the wrong channel so // look for the correct channel by using Ping to initiate a // scan when it gets no reply. With a successful ping try // sending the message again. Otherwise, for any error we // get we will wait until the next button press to try // again. // if (SMPL_SUCCESS != SMPL_Ping(g_sLinkID)) { ucDone = 1; } #else ucDone = 1; #endif /* FREQUENCY_AGILITY */ } else { // // We got the ack so drop out of the transmit loop. // ucDone = 1; UpdateStatus(false, "Toggled AP LED %d", ulButton); } } // // Now that we are finished with it, put the radio back to sleep. // SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_SLEEP, 0); } // // Process the widget message queue. // WidgetMessageQueueProcess(); } }