Statistics
| Branch: | Tag: | Revision:

root / tidsense / assoc.c @ 172:8c8328364b9d

History | View | Annotate | Download (4.3 kB)

1
#include <config.h>
2
#include <phy.h>
3
4
#include "scheduler.h"
5
#include "nv.h"
6
#include "debug.h"
7
#include "node.h"
8
#include "command.h"
9
#include "assoc.h"
10
11
uint16_t assoc_master = 0x0000;
12
assoc_task_state_t assoc_state;
13
sched_task_t *assoc_task;
14
uint8_t assoc_cur_channel;
15
uint8_t assoc_n_failures;
16
17
struct {uint16_t n; uint16_t a; uint8_t c;} assoc_candidates[ASSOC_N_CANDIDATES];
18
19
void assoc_task_fn(void *data);
20
21
void assoc_setup(void) {
22
    assoc_task = sched_task_create(assoc_task_fn, NULL, 0, ASSOC_DELAY, SCHED_ENABLED);
23
    assoc_state = ASSOC_STATE_UNASSOCIATED;
24
    assoc_n_failures = 0;
25
}
26
27
uint16_t assoc_get_master(void) {
28
    if(assoc_state == ASSOC_STATE_ASSOCIATED) {
29
        return assoc_master;
30
    } else {
31
        return nv_get_word(default_basestation);
32
    }
33
}
34
35
void assoc_unassociate(void) {
36
    assoc_state = ASSOC_STATE_UNASSOCIATED;
37
    // Go to default channel when unassociated
38
    PHY_SetChannel(nv_get_word(default_channel));
39
    sched_task_set_interval(assoc_task, 0, ASSOC_DELAY);
40
}
41
42
void assoc_associate(uint8_t candidate) {
43
    debugf("assoc N=0x%04X A=0x%04X C=%d\n",
44
        assoc_candidates[candidate].n,
45
        assoc_candidates[candidate].a,
46
        assoc_candidates[candidate].c);
47
    assoc_master = assoc_candidates[candidate].a;
48
    PHY_SetChannel(assoc_candidates[candidate].c);
49
    assoc_state = ASSOC_STATE_ASSOCIATED;
50
    sched_task_set_interval(assoc_task, 86400, 0);
51
    assoc_n_failures = 0;
52
    nv_set_word(default_channel, assoc_candidates[candidate].c);
53
    nv_set_word(default_basestation, assoc_candidates[candidate].a);
54
}
55
56
void assoc_eval_candidates(void) {
57
    int8_t c = -1;
58
    uint8_t cp = 255;
59
    for(uint8_t i=0; i<ASSOC_N_CANDIDATES; i++) {
60
        int8_t priority = nv_get_network_priority(assoc_candidates[i].n);
61
        if(priority < 0) continue;
62
        if(priority < cp) {
63
            c = i;
64
            cp = priority;
65
        }
66
    }
67
    if(c < 0) {
68
        /* no replies from networks we'll consider */
69
        PHY_SetChannel(nv_get_word(default_channel));
70
        debugf("association failed\n");
71
        assoc_state = ASSOC_STATE_FAILED;
72
        if(++assoc_n_failures > 2) {
73
            sched_task_set_interval(assoc_task, 3600, 0);
74
            assoc_n_failures = 0;
75
        } else {
76
            sched_task_set_interval(assoc_task, 60, 0);
77
        }
78
    } else {
79
        assoc_associate(c);
80
    }
81
}
82
83
void assoc_probe(uint8_t channel) {
84
    sched_set_awake_timer(1);
85
    NWK_DataReq_t *req = network_alloc_request(10);
86
    if(!req) return;
87
    
88
    req->dstAddr = 0xFFFF;
89
    req->dstEndpoint = CONTROL_ENDPOINT;
90
    req->srcEndpoint = CONTROL_ENDPOINT;
91
    req->options = 0;
92
    req->confirm = command_data_confirm;
93
94
    cmd_header_t *req_hdr = (cmd_header_t*)req->data;
95
    req->size = sizeof(cmd_header_t);
96
97
    req_hdr->cmd = CMD_DISCOVER;
98
    req_hdr->flags = 0;
99
    req_hdr->id = cmd_get_next_id();
100
101
    PHY_SetChannel(channel);
102
    NWK_DataReq(req);
103
}
104
105
void assoc_task_fn(void *data) {
106
    switch(assoc_state) {
107
        case ASSOC_STATE_UNASSOCIATED:
108
            assoc_cur_channel = 10;
109
            for(uint8_t i=0; i<ASSOC_N_CANDIDATES; i++) {
110
                assoc_candidates[i].n = 0xFFFF;
111
            }
112
            assoc_state = ASSOC_STATE_ASSOCIATING;
113
            break;
114
        case ASSOC_STATE_ASSOCIATING:
115
            assoc_cur_channel++;
116
            if(assoc_cur_channel <= 26)
117
                assoc_probe(assoc_cur_channel);
118
            if(assoc_cur_channel > 26) assoc_eval_candidates();
119
            break;
120
        case ASSOC_STATE_FAILED:
121
            assoc_unassociate();
122
            break;
123
        case ASSOC_STATE_ASSOCIATED:
124
            //assoc_unassociate();
125
            break;
126
        default:
127
            assoc_unassociate();
128
    }
129
}
130
131
void assoc_cmd_handler(NWK_DataInd_t *ind) {
132
    cmd_discover_resp_t *resp = (cmd_discover_resp_t*)ind->data;
133
134
    if(! (resp->header.flags & CMD_RESP)) return;
135
136
    for(uint8_t i=0; i<ASSOC_N_CANDIDATES; i++) {
137
        if(assoc_candidates[i].n == 0xFFFF) {
138
            assoc_candidates[i].n = resp->net_id;
139
            assoc_candidates[i].c = assoc_cur_channel;
140
            assoc_candidates[i].a = ind->srcAddr;
141
            debugf("resp N=0x%04X A=0x%04X C=%d\n",
142
                assoc_candidates[i].n,
143
                assoc_candidates[i].a,
144
                assoc_candidates[i].c);
145
            break;
146
        }
147
    }
148
}
149
150
assoc_task_state_t assoc_get_state(void) {
151
    return assoc_state;
152
}
153