move xbee rx in rc proto
[protos/xbee-avr.git] / rc_proto.c
1 /*
2  * Copyright (c) 2013, Olivier MATZ <zer0@droids-corp.org>
3  * All rights reserved.
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  *     * Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *     * Redistributions in binary form must reproduce the above copyright
10  *       notice, this list of conditions and the following disclaimer in the
11  *       documentation and/or other materials provided with the distribution.
12  *     * Neither the name of the University of California, Berkeley nor the
13  *       names of its contributors may be used to endorse or promote products
14  *       derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #include <string.h>
29
30 #include <aversive.h>
31 #include <aversive/queue.h>
32
33 #include <stdint.h>
34
35 #include <uart.h>
36
37 #include <parse.h>
38 #include <rdline.h>
39 #include <timer.h>
40 #include <xbee.h>
41
42 #include "callout.h"
43 #include "rc_proto.h"
44 #include "xbee_user.h"
45 #include "main.h"
46
47 /* */
48 struct rc_proto_power_levels {
49         uint8_t ttl;
50         uint16_t power_db;
51 };
52 static struct rc_proto_power_levels power_levels[MAX_POWER_LEVEL];
53
54 /* update power level when we receive the answer from DB */
55 static int8_t update_power_level(int8_t retcode, void *frame, unsigned len,
56         void *arg)
57 {
58         struct xbee_atresp_hdr *atresp = (struct xbee_atresp_hdr *)frame;
59         int level = (intptr_t)arg;
60         uint8_t db;
61
62         /* nothing more to do, error is already logged by xbee_user */
63         if (retcode < 0)
64                 return retcode;
65
66         /* XXX check if this test is correct */
67         if (len < sizeof(struct xbee_atresp_hdr) + sizeof(uint8_t)) {
68                 /* XXX stats */
69                 return -1;
70         }
71
72         db = atresp->data[0];
73         power_levels[level].power_db = db;
74         power_levels[level].ttl = 2;
75         return 0;
76 }
77
78 /* when we receive a power probe, ask the DB value to the xbee */
79 void rc_proto_rx_power_probe(int power_level)
80 {
81         (void)power_level;
82         xbeeapp_send_atcmd("DB", NULL, 0, update_power_level, NULL);
83 }
84
85 /* send a hello message */
86 int8_t rc_proto_send_hello(uint64_t addr, void *data, uint8_t data_len)
87 {
88         struct rc_proto_echo_req hdr;
89         struct xbee_msg msg;
90
91         hdr.type = RC_PROTO_HELLO;
92         hdr.datalen = data_len;
93
94         msg.iovlen = 2;
95         msg.iov[0].buf = &hdr;
96         msg.iov[0].len = sizeof(hdr);
97         msg.iov[1].buf = data;
98         msg.iov[1].len = data_len;
99
100         return xbeeapp_send_msg(addr, &msg, NULL, NULL);
101 }
102
103
104 #if 0
105 #define N_SERVO 6
106 #define SERVO_NBITS 10
107 uint16_t servos[N_SERVO] = { 0x123, 0x234, 0x321, 0x123, 0x234, 0x321 };
108
109 int8_t servo2buf(uint8_t *buf, uint8_t len, uint8_t servo_mask,
110                   uint8_t pow, uint8_t seq)
111 {
112         uint8_t i = 0, num;
113         uint8_t remain_bits;
114         uint8_t servo_bits = 0;
115         uint16_t servo_val;
116         uint8_t tmp;
117
118         if (len < 2)
119                 return -1;
120
121         memset(buf, 0, len);
122         buf[i++] = servo_mask;
123         buf[i++] = ((seq & 0x1f) << 3) | (pow & 0x7);
124         remain_bits = 8;
125
126         for (num = 0; num < N_SERVO; num++) {
127                 if (!(servo_mask & (1 << num)))
128                         continue;
129                 servo_val = servos[num];
130                 servo_bits = SERVO_NBITS;
131
132                 tmp = (servo_val >> (servo_bits - remain_bits));
133                 tmp &= ((1 << remain_bits) - 1);
134                 if (i >= len)
135                         return -1;
136                 buf[i++] |= tmp;
137
138                 servo_bits = 10 - remain_bits;
139                 tmp = servo_val & ((1 << servo_bits) - 1);
140                 tmp <<= (8 - servo_bits);
141                 if (i >= len)
142                         return -1;
143                 buf[i] = tmp;
144
145                 if (servo_bits == 8) {
146                         i++;
147                         remain_bits = 8;
148                 }
149                 else
150                         remain_bits = 8 - servo_bits;
151         }
152
153         if (remain_bits != 8)
154                 i++;
155
156         return i;
157 }
158
159 int8_t buf2servo(uint8_t *buf, uint8_t len)
160 {
161         uint8_t mask, count = 0;
162         uint8_t num = 0;
163         uint8_t pow, seq;
164         uint16_t val;
165
166         if (len < 2)
167                 return -1;
168
169         mask = buf[0];
170         if (mask > 0x3f)
171                 return -1;
172         pow = buf[1] & 0x07;
173         seq = buf[1] >> 5;
174
175         for (num = 0; num < N_SERVO; num++) {
176                 if ((1<<num) & mask)
177                         count++;
178         }
179         switch (count) {
180                 case 1: if (len != 4) return -1; break;
181                 case 2: if (len != 5) return -1; break;
182                 case 3: if (len != 6) return -1; break;
183                 case 4: if (len != 7) return -1; break;
184                 case 5: if (len != 9) return -1; break;
185                 case 6: if (len != 10) return -1; break;
186                 default: return -1;
187         }
188
189         for (num = 0; ((1<<num) & mask) == 0; num++) {
190                 if (num >= N_SERVO)
191                         return 0;
192         }
193
194         val = buf[2];
195         val <<= 2;
196         val |= (buf[3] >> 6);
197
198         for (num++; ((1<<num) & mask) == 0; num++) {
199                 if (num >= N_SERVO)
200                         return 0;
201         }
202
203         val = buf[3] & 0x3f;
204         val <<= 4;
205         val |= (buf[4] >> 4);
206
207         for (num++; ((1<<num) & mask) == 0; num++) {
208                 if (num >= N_SERVO)
209                         return 0;
210         }
211
212         val = buf[4] & 0xf;
213         val <<= 6;
214         val |= (buf[5] >> 2);
215
216         for (num++; ((1<<num) & mask) == 0; num++) {
217                 if (num >= N_SERVO)
218                         return 0;
219         }
220
221         val = buf[5] & 0x3;
222         val <<= 8;
223         val |= (buf[6]);
224
225         for (num++; ((1<<num) & mask) == 0; num++) {
226                 if (num >= N_SERVO)
227                         return 0;
228         }
229
230         val = buf[7];
231         val <<= 2;
232         val |= (buf[8] >> 6);
233
234         for (num++; ((1<<num) & mask) == 0; num++) {
235                 if (num >= N_SERVO)
236                         return 0;
237         }
238
239         val = buf[8];
240         val <<= 4;
241         val |= (buf[9] >> 4);
242
243         return 0;
244 }
245 #endif
246
247 int rc_proto_rx(struct xbee_recv_hdr *recvframe, unsigned len)
248 {
249         unsigned int datalen;
250         struct rc_proto_hdr *rch = (struct rc_proto_hdr *) &recvframe->data;
251
252         if (len <  sizeof(*recvframe))
253                 return -1;
254
255         datalen = len - sizeof(*recvframe);
256         if (datalen < sizeof(struct rc_proto_hdr))
257                 return -1;
258
259         switch (rch->type) {
260 #if 0
261                 case RC_PROTO_TYPE_CHANNEL: {
262                         struct rc_proto_channel *rcc =
263                                 (struct rc_proto_channel *) recvframe->data;
264                         int16_t val;
265                         if (datalen != sizeof(struct rc_proto_channel))
266                                 return -1;
267                         val = ntohs(rcc->axis[0]);
268                         val >>= 6;
269                         val += 512;
270                         spi_servo_set(0, val);
271                         break;
272                 }
273 #endif
274                 case RC_PROTO_POWER_PROBE: {
275                         struct rc_proto_power_probe *rcpb =
276                                 (struct rc_proto_power_probe *) recvframe->data;
277
278                         if (datalen != sizeof(*rcpb))
279                                 return -1;
280
281                         if (rcpb->power_level >= MAX_POWER_LEVEL)
282                                 return -1;
283
284                         //rc_proto_rx_range(rcpb->power_level);
285
286                         break;
287                 }
288
289                 case RC_PROTO_HELLO: {
290                         struct rc_proto_hello *rch =
291                                 (struct rc_proto_hello *) recvframe->data;
292
293                         NOTICE(E_USER_XBEE, "recv hello len=%d",
294                                 rch->datalen);
295                         /* XXX stats */
296                         break;
297                 }
298                 default:
299                         return -1;
300         }
301
302         return 0;
303 }