Statistics
| Branch: | Tag: | Revision:

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