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 |