IEEE 802.15.4 subsystem
Sign in or create your account | Project List | Help
IEEE 802.15.4 subsystem Git Source Tree
Root/
Source at commit bb7b049f00c45e7c3cdd7dae67d10a26bf9383dc created 13 years 7 months ago. By Werner Almesberger, Literature consistently calls the Link Quality Indication LQI, not LQ. So do we now. | |
---|---|
1 | /* |
2 | * atspi/ep0.c - EP0 extension protocol |
3 | * |
4 | * Written 2008-2010 by Werner Almesberger |
5 | * Copyright 2008-2010 Werner Almesberger |
6 | * |
7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License as published by |
9 | * the Free Software Foundation; either version 2 of the License, or |
10 | * (at your option) any later version. |
11 | */ |
12 | |
13 | |
14 | #include <stdint.h> |
15 | |
16 | #ifndef NULL |
17 | #define NULL 0 |
18 | #endif |
19 | |
20 | #include "regs.h" |
21 | //#include "uart.h" |
22 | #include "usb.h" |
23 | #include "atspi/ep0.h" |
24 | #include "at86rf230.h" |
25 | #include "version.h" |
26 | |
27 | |
28 | extern void reset_rf(void); |
29 | |
30 | |
31 | #define debug(...) |
32 | #define error(...) |
33 | |
34 | |
35 | /* |
36 | * SDCC 2.8.0 had a number of code generation bugs that appeared in the big |
37 | * switch statement of my_setup. SDCC_FORCE_UPDATE forced the value of the |
38 | * "size" variable to be written to memory. This work-around doesn't seem |
39 | * to be necessary with 2.9.0, but we keep it around, just in case. |
40 | * |
41 | * Unfortunately, the setup->bRequest garbling bug is still with us. Without |
42 | * the evaluation forced with SDCC_FORCE_EVAL, sdcc gets confused about the |
43 | * value of setup->bRequest and then rejects all SETUP requests. |
44 | */ |
45 | |
46 | #define SDCC_FORCE_EVAL(type, value) \ |
47 | do { \ |
48 | static volatile type foo; \ |
49 | foo = value; \ |
50 | } while (0) |
51 | |
52 | #define SDCC_FORCE_UPDATE(type, var) \ |
53 | do { \ |
54 | volatile type foo; \ |
55 | foo = var; \ |
56 | var = foo; \ |
57 | } while (0) |
58 | |
59 | |
60 | static const uint8_t id[] = { EP0ATSPI_MAJOR, EP0ATSPI_MINOR, HW_TYPE }; |
61 | static __xdata uint8_t buf[MAX_PSDU+3]; /* command, PHDR, and LQI */ |
62 | static uint8_t size; |
63 | |
64 | |
65 | static void spi_send(uint8_t v) |
66 | { |
67 | uint8_t mask; |
68 | |
69 | for (mask = 0x80; mask; mask >>= 1) { |
70 | MOSI = !!(v & mask); |
71 | SCLK = 1; |
72 | SCLK = 0; |
73 | } |
74 | } |
75 | |
76 | |
77 | static uint8_t spi_recv(void) |
78 | { |
79 | uint8_t res = 0; |
80 | uint8_t i; |
81 | |
82 | for (i = 0; i != 8; i++) { |
83 | res = (res << 1) | MISO; |
84 | SCLK = 1; |
85 | SCLK = 0; |
86 | } |
87 | return res; |
88 | } |
89 | |
90 | |
91 | static void do_buf_write(void *user) |
92 | { |
93 | uint8_t i; |
94 | |
95 | user; /* suppress warning */ |
96 | nSS = 0; |
97 | for (i = 0; i != size; i++) |
98 | spi_send(buf[i]); |
99 | nSS = 1; |
100 | } |
101 | |
102 | |
103 | #define BUILD_OFFSET 7 /* '#' plus "65535" plus ' ' */ |
104 | |
105 | |
106 | static __bit my_setup(struct setup_request *setup) __reentrant |
107 | { |
108 | unsigned tmp; |
109 | uint8_t i; |
110 | |
111 | switch (setup->bmRequestType | setup->bRequest << 8) { |
112 | case ATSPI_FROM_DEV(ATSPI_ID): |
113 | debug("ATSPI_ID\n"); |
114 | if (setup->wLength > 3) |
115 | return 0; |
116 | usb_send(&ep0, id, setup->wLength, NULL, NULL); |
117 | return 1; |
118 | case ATSPI_FROM_DEV(ATSPI_BUILD): |
119 | debug("ATSPI_BUILD\n"); |
120 | tmp = build_number; |
121 | for (i = BUILD_OFFSET-2; tmp; i--) { |
122 | buf[i] = (tmp % 10)+'0'; |
123 | tmp /= 10; |
124 | } |
125 | buf[i] = '#'; |
126 | buf[BUILD_OFFSET-1] = ' '; |
127 | for (size = 0; build_date[size]; size++) |
128 | buf[BUILD_OFFSET+size] = build_date[size]; |
129 | size += BUILD_OFFSET-i+1; |
130 | SDCC_FORCE_EVAL(uint8_t, setup->bRequest); |
131 | if (size > setup->wLength) |
132 | return 0; |
133 | usb_send(&ep0, buf+i, size, NULL, NULL); |
134 | return 1; |
135 | |
136 | case ATSPI_TO_DEV(ATSPI_RESET): |
137 | debug("ATSPI_RESET\n"); |
138 | RSTSRC = SWRSF; |
139 | while (1); |
140 | |
141 | case ATSPI_TO_DEV(ATSPI_RF_RESET): |
142 | debug("ATSPI_RF_RESET\n"); |
143 | reset_rf(); |
144 | return 1; |
145 | |
146 | case ATSPI_TO_DEV(ATSPI_REG_WRITE): |
147 | debug("ATSPI_REG_WRITE\n"); |
148 | nSS = 0; |
149 | spi_send(AT86RF230_REG_WRITE | setup->wIndex); |
150 | spi_send(setup->wValue); |
151 | nSS = 1; |
152 | return 1; |
153 | case ATSPI_FROM_DEV(ATSPI_REG_READ): |
154 | debug("ATSPI_REG_READ\n"); |
155 | nSS = 0; |
156 | spi_send(AT86RF230_REG_READ | setup->wIndex); |
157 | *buf = spi_recv(); |
158 | nSS = 1; |
159 | usb_send(&ep0, buf, 1, NULL, NULL); |
160 | return 1; |
161 | |
162 | case ATSPI_TO_DEV(ATSPI_BUF_WRITE): |
163 | debug("ATSPI_BUF_WRITE\n"); |
164 | if (setup->wLength < 1) |
165 | return 0; |
166 | if (setup->wLength > MAX_PSDU) |
167 | return 0; |
168 | buf[0] = AT86RF230_BUF_WRITE; |
169 | buf[1] = setup->wLength; |
170 | size = setup->wLength+2; |
171 | usb_recv(&ep0, buf+2, setup->wLength, do_buf_write, NULL); |
172 | return 1; |
173 | case ATSPI_FROM_DEV(ATSPI_BUF_READ): |
174 | debug("ATSPI_BUF_READ\n"); |
175 | if (setup->wLength < 2) /* PHR+LQI */ |
176 | return 0; |
177 | if (setup->wLength > MAX_PSDU+2) /* PHR+PSDU+LQI */ |
178 | return 0; |
179 | nSS = 0; |
180 | spi_send(AT86RF230_BUF_READ); |
181 | size = spi_recv(); |
182 | if (size >= setup->wLength) |
183 | size = setup->wLength-1; |
184 | for (i = 0; i != size+1; i++) |
185 | buf[i] = spi_recv(); |
186 | nSS = 1; |
187 | usb_send(&ep0, buf, size+1, NULL, NULL); |
188 | return 1; |
189 | |
190 | case ATSPI_TO_DEV(ATSPI_SRAM_WRITE): |
191 | debug("ATSPI_SRAM_WRITE\n"); |
192 | if (setup->wIndex > SRAM_SIZE) |
193 | return 0; |
194 | if (setup->wIndex+setup->wLength > SRAM_SIZE) |
195 | return 0; |
196 | buf[0] = AT86RF230_SRAM_WRITE; |
197 | buf[1] = setup->wIndex; |
198 | size = setup->wLength+2; |
199 | usb_recv(&ep0, buf+2, setup->wLength, do_buf_write, NULL); |
200 | return 1; |
201 | case ATSPI_TO_DEV(ATSPI_SRAM_READ): |
202 | debug("ATSPI_SRAM_READ\n"); |
203 | if (setup->wIndex > SRAM_SIZE) |
204 | return 0; |
205 | if (setup->wIndex+setup->wLength > SRAM_SIZE) |
206 | return 0; |
207 | nSS = 0; |
208 | spi_send(AT86RF230_SRAM_READ); |
209 | spi_send(setup->wIndex); |
210 | for (i = 0; i != size; i++) |
211 | buf[i] = spi_recv(); |
212 | nSS = 1; |
213 | usb_send(&ep0, buf, size, NULL, NULL); |
214 | return 1; |
215 | |
216 | default: |
217 | error("Unrecognized SETUP: 0x%02x 0x%02x ...\n", |
218 | setup->bmRequestType, setup->bRequest); |
219 | return 0; |
220 | } |
221 | } |
222 | |
223 | |
224 | void ep0_init(void) |
225 | { |
226 | user_setup = my_setup; |
227 | } |
228 |