amiro-lld / source / deca_instance_tag.c @ 9e45662e
History | View | Annotate | Download (33.802 KB)
| 1 | fce9feec | Robin Ewers | /*! ----------------------------------------------------------------------------
|
|---|---|---|---|
| 2 | * @file instance_tag.c
|
||
| 3 | * @brief Decawave tag application state machine for TREK demo
|
||
| 4 | *
|
||
| 5 | * @attention
|
||
| 6 | *
|
||
| 7 | * Copyright 2016 (c) Decawave Ltd, Dublin, Ireland.
|
||
| 8 | *
|
||
| 9 | * All rights reserved.
|
||
| 10 | *
|
||
| 11 | * @author Decawave
|
||
| 12 | */
|
||
| 13 | |||
| 14 | #include <deca_instance.h> |
||
| 15 | #if defined(AMIROLLD_CFG_USE_DW1000) || defined(__DOXYGEN__)
|
||
| 16 | |||
| 17 | #include <alld_dw1000.h> |
||
| 18 | #include <alld_dw1000_regs.h> |
||
| 19 | #include <string.h> |
||
| 20 | |||
| 21 | |||
| 22 | // -------------------------------------------------------------------------------------------------------------------
|
||
| 23 | // Data Definitions
|
||
| 24 | // -------------------------------------------------------------------------------------------------------------------
|
||
| 25 | |||
| 26 | // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||
| 27 | // NOTE: the maximum RX timeout is ~ 65ms
|
||
| 28 | // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||
| 29 | |||
| 30 | |||
| 31 | // -------------------------------------------------------------------------------------------------------------------
|
||
| 32 | // Functions
|
||
| 33 | // -------------------------------------------------------------------------------------------------------------------
|
||
| 34 | |||
| 35 | /**
|
||
| 36 | * @brief this function either enables the receiver (delayed)
|
||
| 37 | *
|
||
| 38 | **/
|
||
| 39 | void tag_enable_rx(uint32_t dlyTime)
|
||
| 40 | {
|
||
| 41 | instance_data_t* inst = instance_get_local_structure_ptr(0);
|
||
| 42 | //subtract preamble duration (because when instructing delayed TX the time is the time of SFD,
|
||
| 43 | //however when doing delayed RX the time is RX on time)
|
||
| 44 | dwt_setdelayedtrxtime(dlyTime - inst->preambleDuration32h) ; |
||
| 45 | if(dwt_rxenable(DWT_START_RX_DELAYED|DWT_IDLE_ON_DLY_ERR)) //delayed rx |
||
| 46 | {
|
||
| 47 | //if the delayed RX failed - time has passed - do immediate enable
|
||
| 48 | //led_on(LED_PC9);
|
||
| 49 | dwt_setpreambledetecttimeout(0); //clear preamble timeout as RX is turned on early/late |
||
| 50 | dwt_setrxtimeout((uint16_t)inst->fwto4RespFrame_sy*2); //reconfigure the timeout before enable |
||
| 51 | //longer timeout as we cannot do delayed receive... so receiver needs to stay on for longer
|
||
| 52 | dwt_rxenable(DWT_START_RX_IMMEDIATE); |
||
| 53 | dwt_setpreambledetecttimeout(PTO_PACS); //configure preamble timeout
|
||
| 54 | dwt_setrxtimeout((uint16_t)inst->fwto4RespFrame_sy); //restore the timeout for next RX enable
|
||
| 55 | //inst->lateRX++;
|
||
| 56 | //led_off(LED_PC9);
|
||
| 57 | } |
||
| 58 | |||
| 59 | } |
||
| 60 | |||
| 61 | /* @fn instanceProcessRXTimeoutTag
|
||
| 62 | * @brief function to process RX timeout event
|
||
| 63 | * */
|
||
| 64 | void tag_process_rx_timeout(instance_data_t *inst)
|
||
| 65 | {
|
||
| 66 | //inst->rxTimeouts ++ ;
|
||
| 67 | |||
| 68 | #if(DISCOVERY == 1) |
||
| 69 | if(inst->twrMode == GREETER)
|
||
| 70 | {
|
||
| 71 | inst->instToSleep = TRUE ; |
||
| 72 | // initiate the re-transmission of the poll that was not responded to
|
||
| 73 | inst->testAppState = TA_TXE_WAIT ; |
||
| 74 | inst->nextState = TA_TXBLINK_WAIT_SEND ; |
||
| 75 | } |
||
| 76 | else
|
||
| 77 | #endif
|
||
| 78 | {
|
||
| 79 | |||
| 80 | #if (TAG_HASTO_RANGETO_A0 == 0) |
||
| 81 | if(inst->rxResponseMask == 0) //if any response have been received send a Final else go to SLEEP |
||
| 82 | {
|
||
| 83 | inst->instToSleep = TRUE ; //set sleep to TRUE so that tag will go to DEEP SLEEP before next ranging attempt
|
||
| 84 | inst->testAppState = TA_TXE_WAIT ; |
||
| 85 | inst->nextState = TA_TXPOLL_WAIT_SEND ; |
||
| 86 | } |
||
| 87 | #else
|
||
| 88 | |||
| 89 | //if tag times out - no response (check if we are to send a final)
|
||
| 90 | //send the final only if it has received response from anchor 0
|
||
| 91 | if((inst->previousState == TA_TXPOLL_WAIT_SEND)
|
||
| 92 | && ((inst->rxResponseMask & 0x1) == 0) |
||
| 93 | ) |
||
| 94 | {
|
||
| 95 | inst->instToSleep = TRUE ; //set sleep to TRUE so that tag will go to DEEP SLEEP before next ranging attempt
|
||
| 96 | inst->testAppState = TA_TXE_WAIT ; |
||
| 97 | inst->nextState = TA_TXPOLL_WAIT_SEND ; |
||
| 98 | } |
||
| 99 | #endif
|
||
| 100 | else if (inst->previousState == TA_TXFINAL_WAIT_SEND) //got here from main (error sending final - handle as timeout) |
||
| 101 | {
|
||
| 102 | dwt_forcetrxoff(); //this will clear all events
|
||
| 103 | inst->instToSleep = TRUE ; |
||
| 104 | // initiate the re-transmission of the poll that was not responded to
|
||
| 105 | inst->testAppState = TA_TXE_WAIT ; |
||
| 106 | inst->nextState = TA_TXPOLL_WAIT_SEND ; |
||
| 107 | } |
||
| 108 | else //send the final |
||
| 109 | {
|
||
| 110 | // initiate the transmission of the final
|
||
| 111 | inst->testAppState = TA_TXE_WAIT ; |
||
| 112 | inst->nextState = TA_TXFINAL_WAIT_SEND ; |
||
| 113 | } |
||
| 114 | |||
| 115 | } |
||
| 116 | } |
||
| 117 | |||
| 118 | /**
|
||
| 119 | * @brief function to re-enable the receiver and also adjust the timeout before sending the final message
|
||
| 120 | * if it is time so send the final message, the callback will notify the application, else the receiver is
|
||
| 121 | * automatically re-enabled
|
||
| 122 | *
|
||
| 123 | * this function is only used for tag when ranging to other anchors
|
||
| 124 | */
|
||
| 125 | uint8_t tag_rx_reenable(uint16_t sourceAddress, uint8_t error) |
||
| 126 | {
|
||
| 127 | uint8_t type_pend = DWT_SIG_DW_IDLE; |
||
| 128 | uint8_t anc = sourceAddress & 0x3;
|
||
| 129 | instance_data_t* inst = instance_get_local_structure_ptr(0);
|
||
| 130 | |||
| 131 | switch(anc)
|
||
| 132 | {
|
||
| 133 | //if we got Response from anchor 3 - this is the last expected response - send the final
|
||
| 134 | case 3: |
||
| 135 | type_pend = DWT_SIG_DW_IDLE; |
||
| 136 | break;
|
||
| 137 | |||
| 138 | //if we got response from anchor 0, 1, or 2 - go back to wait for next anchor's response
|
||
| 139 | //if we got response from 0, then still expecting 3, so remainingRespToRx set to 3
|
||
| 140 | case 0: |
||
| 141 | case 1: |
||
| 142 | case 2: |
||
| 143 | default:
|
||
| 144 | if(inst->remainingRespToRx > 0) //can get here as result of error frame so need to check |
||
| 145 | {
|
||
| 146 | //can't use anc address as this is an error frame, so just re-enable TO based on remainingRespToRx count
|
||
| 147 | if(error == 0) |
||
| 148 | {
|
||
| 149 | switch (anc)
|
||
| 150 | {
|
||
| 151 | case 0: |
||
| 152 | inst->remainingRespToRx = 3; //expecting 3 more responses |
||
| 153 | break;
|
||
| 154 | case 1: |
||
| 155 | inst->remainingRespToRx = 2; //expecting 2 more responses |
||
| 156 | break;
|
||
| 157 | case 2: |
||
| 158 | inst->remainingRespToRx = 1; //expecting 1 more response |
||
| 159 | break;
|
||
| 160 | } |
||
| 161 | } |
||
| 162 | //Poll sent at tagPollTxTime_32bit
|
||
| 163 | //1st response is delayTime + fixedReplyDelayAnc32h - preambleDuration_32MSBs
|
||
| 164 | //2nd is delayTime + fixedReplyDelayAnc32h - preambleDuration_32MSBs + fixedReplyDelayAnc32h
|
||
| 165 | tag_enable_rx(inst->tagPollTxTime32h + |
||
| 166 | (MAX_ANCHOR_LIST_SIZE-inst->remainingRespToRx+1)*(inst->fixedReplyDelayAnc32h));
|
||
| 167 | |||
| 168 | type_pend = DWT_SIG_RX_PENDING ; |
||
| 169 | } |
||
| 170 | else //finished waiting for responses - no responses left to receive... send a final |
||
| 171 | {
|
||
| 172 | type_pend = DWT_SIG_DW_IDLE; //report timeout - send the final if due to be sent
|
||
| 173 | } |
||
| 174 | break;
|
||
| 175 | |||
| 176 | } |
||
| 177 | |||
| 178 | return type_pend;
|
||
| 179 | } |
||
| 180 | |||
| 181 | /**
|
||
| 182 | * @brief this function handles frame error event, it will either signal TO or re-enable the receiver
|
||
| 183 | */
|
||
| 184 | void tag_handle_error_unknownframe(event_data_t dw_event)
|
||
| 185 | {
|
||
| 186 | instance_data_t* inst = instance_get_local_structure_ptr(0);
|
||
| 187 | |||
| 188 | if(inst->twrMode != GREETER)
|
||
| 189 | {
|
||
| 190 | //re-enable the receiver (after error frames as we are not using auto re-enable
|
||
| 191 | //for ranging application rx error frame is same as TO - as we are not going to get the expected frame
|
||
| 192 | inst->remainingRespToRx--; //got something (need to reduce timeout (for remaining responses))
|
||
| 193 | |||
| 194 | dw_event.typePend = tag_rx_reenable(0, 1); //check if receiver will be re-enabled or it's time to send the final |
||
| 195 | } |
||
| 196 | else
|
||
| 197 | {
|
||
| 198 | dw_event.typePend = DWT_SIG_DW_IDLE; //in GREETER mode only waiting for 1 frame
|
||
| 199 | } |
||
| 200 | |||
| 201 | dw_event.type = 0;
|
||
| 202 | //dw_event.typeSave = 0x40 | DWT_SIG_RX_TIMEOUT;
|
||
| 203 | dw_event.rxLength = 0;
|
||
| 204 | |||
| 205 | instance_putevent(dw_event, DWT_SIG_RX_TIMEOUT); |
||
| 206 | } |
||
| 207 | |||
| 208 | /**
|
||
| 209 | * @brief this is the receive timeout event callback handler
|
||
| 210 | */
|
||
| 211 | void rx_to_cb_tag(const dwt_cb_data_t *rxd) |
||
| 212 | {
|
||
| 213 | (void) rxd;
|
||
| 214 | event_data_t dw_event; |
||
| 215 | |||
| 216 | //microcontroller time at which we received the frame
|
||
| 217 | dw_event.uTimeStamp = portGetTickCnt(); |
||
| 218 | tag_handle_error_unknownframe(dw_event); |
||
| 219 | } |
||
| 220 | |||
| 221 | /**
|
||
| 222 | * @brief this is the receive error event callback handler
|
||
| 223 | */
|
||
| 224 | void rx_err_cb_tag(const dwt_cb_data_t *rxd) |
||
| 225 | {
|
||
| 226 | (void) rxd;
|
||
| 227 | event_data_t dw_event; |
||
| 228 | |||
| 229 | //microcontroller time at which we received the frame
|
||
| 230 | dw_event.uTimeStamp = portGetTickCnt(); |
||
| 231 | tag_handle_error_unknownframe(dw_event); |
||
| 232 | } |
||
| 233 | |||
| 234 | /**
|
||
| 235 | * @brief this is the receive event callback handler, the received event is processed and the instance either
|
||
| 236 | * responds by sending a response frame or re-enables the receiver to await the next frame
|
||
| 237 | * once the immediate action is taken care of the event is queued up for application to process
|
||
| 238 | */
|
||
| 239 | void rx_ok_cb_tag(const dwt_cb_data_t *rxd) |
||
| 240 | {
|
||
| 241 | instance_data_t* inst = instance_get_local_structure_ptr(0);
|
||
| 242 | uint8_t rxTimeStamp[5] = {0, 0, 0, 0, 0}; |
||
| 243 | |||
| 244 | uint8_t rxd_event = 0;
|
||
| 245 | uint8_t fcode_index = 0;
|
||
| 246 | uint8_t srcAddr_index = 0;
|
||
| 247 | event_data_t dw_event; |
||
| 248 | |||
| 249 |