Statistics
| Branch: | Tag: | Revision:

root / tidsense / command.c @ 166:1a6a85e8d2e7

History | View | Annotate | Download (5.5 kB)

1
#include <nwk.h>
2
#include <string.h>
3
4
#include <util/delay.h>
5
6
#include "config.h"
7
#include "debug.h"
8
#include "node.h"
9
#include "nv.h"
10
#include "sysclock.h"
11
#include "ota.h"
12
#include "scheduler.h"
13
#include "tidsense.h"
14
#include "power.h"
15
#include "assoc.h"
16
#include "ota.h"
17
#include "i2cmaster.h"
18
#include "command.h"
19
20
uint32_t cmd_next_id = 0;
21
sched_task_t *status_task;
22
sched_task_t *gpio_task;
23
24
i2c_bus_t *cmd_i2c_bus = NULL;
25
26
void command_data_confirm(NWK_DataReq_t *req) {
27
    switch(req->status) {
28
        case NWK_SUCCESS_STATUS:
29
            app_handle_ack(req->control);
30
            //debugf("cmd: ok\n");
31
            break;
32
        case NWK_ERROR_STATUS:
33
        case NWK_NO_ACK_STATUS:
34
        case NWK_PHY_NO_ACK_STATUS:
35
            debugf("cmd: no reply (%d)\n", req->status);
36
            break;
37
        case NWK_NO_ROUTE_STATUS:
38
            debugf("cmd: no route\n");
39
            break;
40
        default:
41
            debugf("cmd: unhandled status sending response (%d)\n", req->status);
42
            break;
43
    }
44
    network_free_request(req);
45
}
46
47
void command_set_i2c_bus(i2c_bus_t *bus) {
48
    cmd_i2c_bus = bus;
49
}
50
51
void cmd_setup_resp(command_id_t cmd, NWK_DataReq_t *req, void *hdr, NWK_DataInd_t *ind) {
52
    req->dstAddr = ind->srcAddr;
53
    req->dstEndpoint = CONTROL_ENDPOINT;
54
    req->srcEndpoint = CONTROL_ENDPOINT;
55
    req->options = NWK_OPT_ACK_REQUEST;
56
    req->confirm = command_data_confirm;
57
58
    cmd_header_t *req_hdr = (cmd_header_t*)ind->data;
59
    cmd_header_t *resp_hdr = (cmd_header_t*)hdr;
60
61
    resp_hdr->cmd = cmd;
62
    resp_hdr->flags = CMD_RESP;
63
    resp_hdr->id = req_hdr->id;
64
}
65
66
void cmd_setup_req(command_id_t cmd, NWK_DataReq_t *req, uint16_t dest) {
67
    req->dstAddr = dest;
68
    req->dstEndpoint = CONTROL_ENDPOINT;
69
    req->srcEndpoint = CONTROL_ENDPOINT;
70
    req->options = NWK_OPT_ACK_REQUEST;
71
    req->confirm = command_data_confirm;
72
73
    cmd_header_t *req_hdr = (cmd_header_t*)req->data;
74
75
    req_hdr->cmd = cmd;
76
    req_hdr->flags = 0;
77
    req_hdr->id = cmd_next_id++;
78
}
79
80
void cmd_nodeinfo(NWK_DataInd_t *ind) {
81
    NWK_DataReq_t *resp = network_alloc_request(100);
82
    if(!resp) {
83
        return;
84
    }
85
86
    cmd_nodeinfo_resp_t *nodeinfo = (cmd_nodeinfo_resp_t*)&resp->data[0];
87
88
    if(ind) {
89
        cmd_setup_resp(CMD_NODEINFO, resp, nodeinfo, ind);
90
    } else {
91
        cmd_setup_req(CMD_NODEINFO, resp, assoc_get_master());
92
    }
93
94
    resp->size = sizeof(cmd_nodeinfo_resp_t);
95
96
    memcpy(&nodeinfo->version_info, &version_info, sizeof(version_info_t));
97
    nodeinfo->ota_state = ota_get_state();
98
    nodeinfo->ota_progress = ota_get_progress();
99
100
    NWK_DataReq(resp);
101
}
102
103
void cmd_gpio_handler(NWK_DataInd_t *ind) {
104
    if(nv_has_feature(FEATURE_CHARGER_RELAY)) {
105
        PORTA.OUTSET = PIN7_bm;
106
        sched_task_enable(gpio_task);
107
    }
108
}   
109
110
void gpio_task_fn(void) {
111
    PORTA.OUTCLR = PIN7_bm;
112
}
113
114
bool cmd_i2c_write(NWK_DataInd_t *ind) {
115
    if(!cmd_i2c_bus) return false;
116
117
    NWK_DataReq_t *resp = network_alloc_request(100);
118
    if(!resp) {
119
        return false;
120
    }
121
122
    cmd_i2c_t *req_cmd = (cmd_i2c_t*)&ind->data[0];
123
    cmd_i2c_t *resp_cmd = (cmd_i2c_t*)&resp->data[0];
124
125
    resp_cmd->addr = req_cmd->addr;
126
    resp_cmd->reg = req_cmd->reg;
127
    resp_cmd->size = 0;
128
129
    cmd_setup_resp(CMD_I2C_WRITE, resp, resp_cmd, ind);
130
    resp_cmd->status = i2c_write_generic(cmd_i2c_bus, req_cmd->addr, 
131
        req_cmd->reg, &req_cmd->data[0], req_cmd->size);
132
133
    resp->size = sizeof(cmd_i2c_t) + resp_cmd->size;
134
    NWK_DataReq(resp);
135
    return true;
136
}
137
138
bool cmd_i2c_read(NWK_DataInd_t *ind) {
139
    if(!cmd_i2c_bus) return false;
140
141
    NWK_DataReq_t *resp = network_alloc_request(100);
142
    if(!resp) {
143
        return false;
144
    }
145
146
    cmd_i2c_t *req_cmd = (cmd_i2c_t*)&ind->data[0];
147
    cmd_i2c_t *resp_cmd = (cmd_i2c_t*)&resp->data[0];
148
149
    resp_cmd->addr = req_cmd->addr;
150
    resp_cmd->reg = req_cmd->reg;
151
    resp_cmd->size = 0;
152
153
    cmd_setup_resp(CMD_I2C_READ, resp, resp_cmd, ind);
154
    resp_cmd->status = i2c_read_generic(cmd_i2c_bus, req_cmd->addr,
155
        req_cmd->reg, &resp_cmd->data[0], req_cmd->size);
156
    if(resp_cmd->status == I2C_SUCCESS) {
157
        resp_cmd->size = req_cmd->size;
158
    }
159
160
    resp->size = sizeof(cmd_i2c_t) + resp_cmd->size;
161
    NWK_DataReq(resp);
162
    return true;
163
}
164
165
static bool command_data_ind(NWK_DataInd_t *ind) {
166
    command_id_t cmd = ind->data[0];
167
    //debugf("rcmd: %d\n", cmd);
168
    switch(cmd) {
169
        case CMD_NODEINFO:
170
            cmd_nodeinfo(ind);
171
            return true;
172
        case CMD_DISCOVER:
173
            assoc_cmd_handler(ind);
174
            return true;
175
        case CMD_SETGPIO:
176
            cmd_gpio_handler(ind);
177
            return true;
178
        case CMD_OTASTART:
179
        case CMD_OTAREQUEST:
180
        case CMD_OTASTATUSREQUEST:
181
        case CMD_REBOOT:
182
            ota_cmd_handler(ind);
183
            return true;
184
        case CMD_I2C_WRITE:
185
            return cmd_i2c_write(ind);
186
        case CMD_I2C_READ:
187
            return cmd_i2c_read(ind);
188
        default: debugf("cmd: unknown command (%d)\n", cmd);
189
    }
190
    return false;
191
}
192
193
void cmd_periodic_status_task(void) {
194
    if(assoc_get_state() == ASSOC_STATE_ASSOCIATED) {
195
        power_radio_on();
196
        cmd_nodeinfo(NULL);
197
        sched_task_set_interval(status_task, 300, 0);
198
    }
199
}
200
201
void command_setup(void) {
202
    NWK_OpenEndpoint(CONTROL_ENDPOINT, command_data_ind);
203
    status_task = sched_task_create(cmd_periodic_status_task, 10, 0, SCHED_ENABLED);
204
205
    if(nv_has_feature(FEATURE_CHARGER_RELAY)) {
206
        PORTA.DIRSET = PIN7_bm;
207
        PORTA.OUTCLR = PIN7_bm;
208
        gpio_task = sched_task_create(gpio_task_fn, 0, 500, SCHED_ONESHOT);
209
    }
210
}
211
212
uint32_t cmd_get_next_id(void) {
213
    return cmd_next_id++;
214
}
215