/** * @brief Main function of the Terminal Target application * @ingroup App_API */ int main(void) { /* Initialize all layers */ if (nwk_init() != NWK_SUCCESS) { /* something went wrong during initialization */ pal_alert(); } /* disable pull-ups */ MCUCR |= (1u << PUD); #ifdef FLASH_NVRAM pal_ps_set(EE_IEEE_ADDR,IEEE_ADDRESS_BYTES, &tal_pib_IeeeAddress); #endif /* Initialize LEDs. */ pal_led_init(); pal_led(LED_START, LED_ON); /* indicating application is started */ pal_led(LED_NWK_SETUP, LED_OFF); /* indicating network is started */ pal_led(LED_DATA, LED_OFF); /* indicating data reception */ /* * The stack is initialized above, hence the global interrupts are enabled * here. */ pal_global_irq_enable(); /** * @brief TWI and QT600 interface initialization */ int i; twi_master_init(); RESET_QT600_PIN_INIT(); RESET_QT600_ON(); for (i = 0; i < 100 ; i++) asm("nop"); /* Endless while loop */ while (1) { app_task(); /* Application task */ if(rf4ce_new_msg == 1) { twi_send_message(); TX_index = 0; rf4ce_new_msg = 0; } nwk_task(); /* RF4CE network layer task */ } }
/** * @brief Main function of the Wireless UART application */ int main(void) { /* Initialize the TAL layer */ if (tal_init() != MAC_SUCCESS) { // something went wrong during initialization pal_alert(); } /* Calibrate MCU's RC oscillator */ pal_calibrate_rc_osc(); /* Initialize LEDs */ pal_led_init(); pal_led(LED_START, LED_ON); // indicating application is started pal_led(LED_DATA_RX, LED_OFF); // indicating data reception pal_led(LED_DATA_TX, LED_OFF); // indicating successfull data transmission /* * The stack is initialized above, hence the global interrupts are enabled * here. */ pal_global_irq_enable(); /* Initialize the serial interface used for communication with terminal program */ if (pal_sio_init(SIO_CHANNEL) != MAC_SUCCESS) { // something went wrong during initialization pal_alert(); } /* Configure TX frame and transceiver */ configure_frame_sending(); /* Switch receiver on */ tal_rx_enable(PHY_RX_ON); #if(SEND_BLOCKWISE==true) start_timer(); #endif /* Endless while loop */ while (1) { pal_task(); /* Handle platform specific tasks, like serial interface */ tal_task(); /* Handle transceiver specific tasks */ #if(!(SEND_BLOCKWISE==true)) app_task(); /* Application task */ #endif } }
/** * @brief Callback that is called if data has been received by trx. * * @param rx_frame_array Pointer to data array containing received frame */ void tal_rx_frame_cb(uint8_t *rx_frame_array) { uint8_t rx_payload_len = rx_frame_array[0] - FRAME_OVERHEAD; uint8_t *rx_payload_ptr = rx_frame_array + FRAME_OVERHEAD + LENGTH_FIELD_LEN - FCS_LEN; uint8_t sio_len_rx; /* Print received data to terminal program. */ bool sio_ongoing = true; do { sio_len_rx = pal_sio_tx(SIO_CHANNEL, rx_payload_ptr, rx_payload_len); if (sio_len_rx < rx_payload_len) { rx_payload_len -= sio_len_rx; rx_payload_ptr += sio_len_rx; pal_task(); } else { sio_ongoing = false; } } while (sio_ongoing); pal_led(LED_DATA_RX, LED_TOGGLE); // indicating data recption }
/** * @brief Notify the application of the status of its request to to change the * value of a NIB attribute. * * @param Status nwk status * @param NIBAttribute NIBAttribute * @param NIBAttributeIndex NIBAttributeIndex */ void nlme_set_confirm(nwk_enum_t Status, nib_attribute_t NIBAttribute, uint8_t NIBAttributeIndex) { if (Status != NWK_SUCCESS) { return; } if (NIBAttribute == nwkBaseChannel) { pal_timer_start(T_LED_TIMER, PAIR_WAIT_PERIOD, TIMEOUT_RELATIVE, (FUNC_PTR)led_handling, NULL); pal_led(LED_NWK_SETUP, LED_ON); dev_type_t RecDevTypeList[DEVICE_TYPE_LIST_SIZE]; profile_id_t RecProfileIdList[PROFILE_ID_LIST_SIZE]; RecDevTypeList[0] = SUPPORTED_DEV_TYPE_0; RecProfileIdList[0] = SUPPORTED_PROFILE_ID_0; pbp_rec_pair_request(APP_CAPABILITIES, RecDevTypeList, RecProfileIdList); return; } /* Keep compiler happy */ UNUSED(NIBAttributeIndex); }
/** * @brief LED handling including timer control . */ static void led_handling(void *callback_parameter) { switch (node_status) { case PUSH_BUTTON_PAIRING: case ALL_IN_ONE_START: pal_timer_start(T_LED_TIMER, PAIR_WAIT_PERIOD, TIMEOUT_RELATIVE, (FUNC_PTR)led_handling, NULL); pal_led(LED_NWK_SETUP, LED_TOGGLE); break; default: pal_timer_stop(T_LED_TIMER); pal_led(LED_DATA, LED_OFF); pal_led(LED_NWK_SETUP, LED_OFF); break; } /* Keep compiler happy */ UNUSED(callback_parameter); }
/** * @brief Application task */ static void app_task(void) { uint8_t number_of_bytes_to_be_transmitted; if (tx_state == TX_IDLE) { number_of_bytes_to_be_transmitted = pal_sio_rx(SIO_CHANNEL, sio_rx_data, MAX_APP_DATA_LENGTH); // If bytes are received via UART/USB, transmit the bytes. if (number_of_bytes_to_be_transmitted > 0) { pal_led(LED_START, LED_TOGGLE); // indicate data processing tx_state = TX_ONGOING; tx_buffer[PL_POS_SEQ_NUM]++; /* Check for maximum allowed IEEE 802.15.4 frame length. */ if (number_of_bytes_to_be_transmitted > aMaxMACSafePayloadSize) { number_of_bytes_to_be_transmitted = aMaxMACSafePayloadSize; } /* Update mpdu length within frame. */ tx_buffer[0] = number_of_bytes_to_be_transmitted + FRAME_OVERHEAD; /* Copy MSDU (actual MAC payload) into frame. */ /* * Note: Usually the MSDU is copied beginning from the end of * the frame. Since the header is always the same for this * application, the start of the MSDU is always the same position. * Therefore the payload copying is done from the beginning. */ memcpy(&tx_buffer[LENGTH_FIELD_LEN + FRAME_OVERHEAD - FCS_LEN], sio_rx_data, number_of_bytes_to_be_transmitted); tal_tx_frame(tx_buffer, CSMA_UNSLOTTED, true); } } else if (tx_state == TX_RETRY) { tx_state = TX_ONGOING; /* Retransmit the previous frame until frame transmission was successful. */ tal_tx_frame(tx_buffer, CSMA_UNSLOTTED, true); } }
/** * @brief Prints the status of push button pairing and if status is success, * then send the cmd discovery to controller. * * @param Status nwk status * @param PairingRef Pairing Ref of the new entry. */ void pbp_pair_confirm(nwk_enum_t Status, uint8_t PairingRef) { if(Status != NWK_SUCCESS) { target_auto_start = true; node_status = IDLE; } #ifdef ZRC_CMD_DISCOVERY else if (Status == NWK_SUCCESS) { pal_led(LED_NWK_SETUP, LED_OFF); node_status = CMD_DISCOVERING; zrc_cmd_disc_request(PairingRef); } #endif }
/** * @brief Handles the rc command indications at terminal target. * * @param PairingRef Pairing reference * @param nsduLength Length of the payload. * @param nsdu Actual payload * @param RxLinkQuality Link quality of received packet. * @param RxFlags Rx Flags. */ void zrc_cmd_indication(uint8_t PairingRef, uint8_t nsduLength, uint8_t *nsdu, uint8_t RxLinkQuality, uint8_t RxFlags) { zrc_cmd_frm_t *zrc_frm; // Switch LED on indicating data reception pal_led(LED_DATA, LED_TOGGLE); /* Check with frame control field which kind of data is indicated */ zrc_frm = (zrc_cmd_frm_t *)nsdu; switch (zrc_frm->fcf) { #ifdef RF4CE_TARGET case USER_CONTROL_PRESSED: { /** * Receive the data on RF4CE Link, Store in Tx_Buffer and Send to * TWI interface */ int i; /* Keep compiler happy */ UNUSED(i); #ifdef _GENERIC_QDEBUG_ for(i = 1 ; i < nsduLength ; i++) PutChar(nsdu[i]); rf4ce_new_msg = 1; #endif /* _GENERIC_QDEBUG_ */ } break;/*case USER_CONTROL_PRESSED */ #endif /* #ifdef RF4CE_TARGET */ default: break; } /* Keep compiler happy */ UNUSED(RxFlags); UNUSED(PairingRef); UNUSED(RxLinkQuality); }
/** * @brief Callback that is called once tx is done. * * @param status Status of the transmission procedure */ void tal_tx_frame_done_cb(retval_t status) { if (status == MAC_SUCCESS) { uint8_t tx_payload_len = tx_buffer[0] - FRAME_OVERHEAD; uint8_t *tx_payload_ptr = tx_buffer + FRAME_OVERHEAD + LENGTH_FIELD_LEN - FCS_LEN; uint8_t sio_len_tx; /* Print transmitted bytes to terminal program. */ bool sio_ongoing = true; do { sio_len_tx = pal_sio_tx(SIO_CHANNEL, tx_payload_ptr, tx_payload_len); if (sio_len_tx < tx_payload_len) { tx_payload_len -= sio_len_tx; tx_payload_ptr += sio_len_tx; pal_task(); } else { sio_ongoing = false; } } while (sio_ongoing); pal_led(LED_DATA_TX, LED_TOGGLE); // indicating successfull data transmission /* After transmission is completed, allow next transmission. */ tx_state = TX_IDLE; } else if (status == MAC_CHANNEL_ACCESS_FAILURE) /* * Channel access failure is the only transmission failure that makes sense * to be handled within this application. For handling other status codes, * such as MAC_NO_ACK, this is probably the wrong application on the wrong layer. * For absolutely reliable transmission, please use a MAC or TAL based * application. The Tiny-TAL is not designed for such a purpose. * * In case of channel access failure the frame is retried. */ { /* Transmission was not successful, initiate retry. */ tx_state = TX_RETRY; //TODO: retry counter? } else /* * Other transmission status codes, such as MAC_NO_ACK are not handled * within this application. * The transmission is considered as beeing completed for this frame. */ { tx_state = TX_IDLE; #if(ALERT_ON_ERROR==true) pal_alert(); #endif } }
/** * @brief decode state machine. * */ void decode_machine(void) { uint16_t inv; //interval inv = cal_interval(); //printf("%u\r\n", inv); switch (dec.state){ case Waiting: if( dec.acsr & ( 1 << ACO) ) { //rising dec.state = Sta0; //goto start bit } dec_update_tmr(); break; // case Sta0: if ( !( dec.acsr & ( 1 << ACO) ) ) {//falling if( ( inv >= DECODE_TMR_FREQ_2KHZ_MIN ) && (inv <= DECODE_TMR_FREQ_2KHZ_MAX)){ dec.state = Bit0; //goto bit0 odd = 0; //clear odd parity cnt } else{ dec.state = Waiting; } } else{ dec.state = Waiting; } dec_update_tmr(); break; // case Sta1: if ( dec.acsr & ( 1 << ACO) ) { //rising if( ( inv >= DECODE_TMR_FREQ_2KHZ_MIN ) && (inv <= DECODE_TMR_FREQ_2KHZ_MAX)) dec.state = Sta2; else //falling dec.state = Waiting; } else{ dec.state = Waiting; } dec_update_tmr(); break; // case Sta2: if ( !( dec.acsr & ( 1 << ACO) ) ) { //falling if( ( inv >= DECODE_TMR_FREQ_2KHZ_MIN ) && (inv <= DECODE_TMR_FREQ_2KHZ_MAX)) dec.state = Sta3; else dec.state = Waiting; } else{ dec.state = Waiting; } dec_update_tmr(); break; // case Sta3: if ( dec.acsr & ( 1 << ACO) ) { //rising if( ( inv >= DECODE_TMR_FREQ_2KHZ_MIN ) && (inv <= DECODE_TMR_FREQ_2KHZ_MAX)) dec.state = Bit7; else //falling dec.state = Waiting; } else{ dec.state = Waiting; } dec_update_tmr(); break; // case Bit0: if( ( inv >= DECODE_TMR_FREQ_2KHZ_MIN ) && (inv <= DECODE_TMR_FREQ_2KHZ_MAX)){ dec_update_tmr(); if ( dec.acsr & ( 1 << ACO) ) {//rising dec.data |= ( 1 << BIT0 ) ; odd++; } else{ //falling dec.data &= ~( 1 << BIT0 ) ; } dec.state = Bit1; } else if (inv > DECODE_TMR_FREQ_2KHZ_MAX ) { dec.state = Waiting; dec_update_tmr(); } break; // case Bit1: if( ( inv >= DECODE_TMR_FREQ_2KHZ_MIN ) && (inv <= DECODE_TMR_FREQ_2KHZ_MAX)){ dec_update_tmr(); if ( dec.acsr & ( 1 << ACO) ) {//rising dec.data |= ( 1 << BIT1 ) ; odd++; } else{ //falling dec.data &= ~( 1 << BIT1 ) ; } dec.state = Bit2; } else if (inv > DECODE_TMR_FREQ_2KHZ_MAX ) { dec.state = Waiting; dec_update_tmr(); } break; // case Bit2: if( ( inv >= DECODE_TMR_FREQ_2KHZ_MIN ) && (inv <= DECODE_TMR_FREQ_2KHZ_MAX)){ dec_update_tmr(); if ( dec.acsr & ( 1 << ACO) ) {//rising dec.data |= ( 1 << BIT2 ) ; odd++; } else{ //falling dec.data &= ~( 1 << BIT2 ) ; } dec.state = Bit3; } else if (inv > DECODE_TMR_FREQ_2KHZ_MAX ) { dec.state = Waiting; dec_update_tmr(); } break; // case Bit3: if( ( inv >= DECODE_TMR_FREQ_2KHZ_MIN ) && (inv <= DECODE_TMR_FREQ_2KHZ_MAX)){ dec_update_tmr(); if ( dec.acsr & ( 1 << ACO) ) {//rising dec.data |= ( 1 << BIT3 ) ; odd++; } else{ //falling dec.data &= ~( 1 << BIT3 ) ; } dec.state = Bit4; } else if (inv > DECODE_TMR_FREQ_2KHZ_MAX ) { dec.state = Waiting; dec_update_tmr(); } break; // case Bit4: if( ( inv >= DECODE_TMR_FREQ_2KHZ_MIN ) && (inv <= DECODE_TMR_FREQ_2KHZ_MAX)){ dec_update_tmr(); if ( dec.acsr & ( 1 << ACO) ) {//rising dec.data |= ( 1 << BIT4 ) ; odd++; } else{ //falling dec.data &= ~( 1 << BIT4 ) ; } dec.state = Bit5; } else if (inv > DECODE_TMR_FREQ_2KHZ_MAX ) { dec.state = Waiting; dec_update_tmr(); } break; // case Bit5: if( ( inv >= DECODE_TMR_FREQ_2KHZ_MIN ) && (inv <= DECODE_TMR_FREQ_2KHZ_MAX)){ dec_update_tmr(); if ( dec.acsr & ( 1 << ACO) ) {//rising dec.data |= ( 1 << BIT5 ) ; odd++; } else{ //falling dec.data &= ~( 1 << BIT5 ) ; } dec.state = Bit6; } else if (inv > DECODE_TMR_FREQ_2KHZ_MAX ) { dec.state = Waiting; dec_update_tmr(); } break; // case Bit6: if( ( inv >= DECODE_TMR_FREQ_2KHZ_MIN ) && (inv <= DECODE_TMR_FREQ_2KHZ_MAX)){ dec_update_tmr(); if ( dec.acsr & ( 1 << ACO) ) {//rising dec.data |= ( 1 << BIT6 ) ; odd++; } else{ //falling dec.data &= ~( 1 << BIT6 ) ; } dec.state = Bit7; } else if (inv > DECODE_TMR_FREQ_2KHZ_MAX ) { dec.state = Waiting; dec_update_tmr(); } break; // case Bit7: if( ( inv >= DECODE_TMR_FREQ_2KHZ_MIN ) && (inv <= DECODE_TMR_FREQ_2KHZ_MAX)){ dec_update_tmr(); if ( dec.acsr & ( 1 << ACO) ) {//rising dec.data |= ( 1 << BIT7 ) ; odd++; } else{ //falling dec.data &= ~( 1 << BIT7 ) ; } //sio_putchar(dec.data); dec.state = Parity; } else if (inv > DECODE_TMR_FREQ_2KHZ_MAX ) { dec.state = Waiting; dec_update_tmr(); } break; // case Parity: if( ( inv >= DECODE_TMR_FREQ_2KHZ_MIN ) && (inv <= DECODE_TMR_FREQ_2KHZ_MAX)){ dec_update_tmr(); if ( ( 0 == (odd % 2 ) ) && ( dec.acsr & ( 1 << ACO ) ) ) {//there is even 1(s) dec.state = Sto0; //rev 1 is ok when odd parity } else if( ( 1 == (odd % 2 ) ) && !( dec.acsr & ( 1 << ACO ) ) ){ //there is odd 1(s) dec.state = Sto0; //rev 0 is ok when odd parity } else{ dec.state = Waiting; } } else if (inv > DECODE_TMR_FREQ_2KHZ_MAX ) { dec.state = Waiting; dec_update_tmr(); } break; // case Sto0: if( ( inv >= DECODE_TMR_FREQ_2KHZ_MIN ) && (inv <= DECODE_TMR_FREQ_2KHZ_MAX)){ dec_update_tmr(); if ( dec.acsr & ( 1 << ACO ) ) {//stop bit should be always 1 pal_led(LED_2, LED_ON); sio_putchar(dec.data); pal_led(LED_2, LED_OFF); } dec.state = Waiting; } else if (inv > DECODE_TMR_FREQ_2KHZ_MAX ) { dec.state = Waiting; dec_update_tmr(); } break; // default: break; // } }