2 * Copyright © 2012 Keith Packard <keithp@keithp.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
19 #include <ao_radio_spi.h>
21 #include <ao_radio_cmac.h>
23 static __xdata struct ao_radio_spi_reply ao_radio_spi_reply;
24 static __xdata struct ao_radio_spi_request ao_radio_spi_request;
25 static volatile __xdata uint8_t ao_radio_done = 1;
26 static __xdata uint8_t ao_radio_mutex;
28 __xdata int8_t ao_radio_cmac_rssi;
31 #define PRINTD(...) do { printf ("\r%s: ", __func__); printf(__VA_ARGS__); flush(); } while(0)
39 ao_exti_disable(AO_RADIO_INT_PORT, AO_RADIO_INT_PIN);
41 ao_wakeup((void *) &ao_radio_done);
45 ao_radio_master_delay(void)
48 // for (i = 0; i < 1000; i++)
54 ao_radio_master_start(void)
56 ao_radio_master_delay();
57 ao_spi_get_bit(AO_RADIO_CS_PORT, AO_RADIO_CS_PIN, AO_RADIO_CS,
63 ao_radio_master_stop(void)
65 ao_spi_put_bit(AO_RADIO_CS_PORT, AO_RADIO_CS_PIN, AO_RADIO_CS,
71 ao_radio_master_send(void)
74 printf ("radio not done in ao_radio_master_send\n");
75 PRINTD("send %d\n", ao_radio_spi_request.len);
77 ao_exti_enable(AO_RADIO_INT_PORT, AO_RADIO_INT_PIN);
78 ao_radio_master_start();
79 ao_spi_send(&ao_radio_spi_request,
80 ao_radio_spi_request.len,
82 ao_radio_master_stop();
84 while (!ao_radio_done)
85 if (ao_sleep((void *) &ao_radio_done)) {
86 printf ("ao_radio_master awoken\n");
90 PRINTD ("sent, radio done %d\n", ao_radio_done);
92 printf ("radio didn't finish after ao_radio_master_send\n");
97 ao_radio_get(uint8_t req, uint8_t len)
100 ao_mutex_get(&ao_radio_mutex);
101 ao_radio_spi_request.len = AO_RADIO_SPI_REQUEST_HEADER_LEN + len;
102 ao_radio_spi_request.request = req;
103 ao_radio_spi_request.setting = ao_config.radio_setting;
109 ao_mutex_put(&ao_radio_mutex);
113 ao_radio_get_data(__xdata void *d, uint8_t size)
117 PRINTD ("send fetch req\n");
118 ao_radio_spi_request.len = AO_RADIO_SPI_REQUEST_HEADER_LEN;
119 ao_radio_spi_request.request = AO_RADIO_SPI_RECV_FETCH;
120 ao_radio_spi_request.recv_len = size;
121 ret = ao_radio_master_send();
122 PRINTD ("fetch req sent %d\n", ret);
125 ao_radio_master_start();
126 ao_spi_recv(&ao_radio_spi_reply,
127 AO_RADIO_SPI_REPLY_HEADER_LEN + size,
129 ao_radio_master_stop();
130 ao_xmemcpy(d, ao_radio_spi_reply.payload, size);
131 PRINTD ("fetched %d\n", size);
135 ao_radio_recv_abort(void)
137 ao_radio_get(AO_RADIO_SPI_RECV_ABORT, 0);
138 ao_radio_master_send();
143 ao_radio_send(const void *d, uint8_t size)
145 ao_radio_get(AO_RADIO_SPI_SEND, size);
146 ao_xmemcpy(&ao_radio_spi_request.payload, d, size);
147 ao_radio_master_send();
153 ao_radio_recv(__xdata void *d, uint8_t size)
161 ao_radio_get(AO_RADIO_SPI_RECV, 0);
162 ao_radio_spi_request.recv_len = size;
163 recv = ao_radio_master_send();
166 ao_radio_recv_abort();
169 ao_radio_get_data(d, size);
171 recv = ao_radio_spi_reply.status;
179 ao_radio_cmac_send(__xdata void *packet, uint8_t len) __reentrant
181 if (len > AO_CMAC_MAX_LEN)
182 return AO_RADIO_CMAC_LEN_ERROR;
184 PRINTD ("cmac_send: send %d\n", len);
187 PRINTD ("set key\n");
188 ao_radio_get(AO_RADIO_SPI_CMAC_KEY, AO_AES_LEN);
189 ao_xmemcpy(&ao_radio_spi_request.payload, &ao_config.aes_key, AO_AES_LEN);
190 ao_radio_master_send();
192 PRINTD ("key set\n");
197 PRINTD ("sending packet\n");
198 ao_radio_get(AO_RADIO_SPI_CMAC_SEND, len);
199 ao_xmemcpy(&ao_radio_spi_request.payload, packet, len);
200 ao_radio_master_send();
202 PRINTD ("packet sent\n");
203 return AO_RADIO_CMAC_OK;
207 ao_radio_cmac_recv(__xdata void *packet, uint8_t len, uint16_t timeout) __reentrant
212 if (len > AO_CMAC_MAX_LEN)
213 return AO_RADIO_CMAC_LEN_ERROR;
217 PRINTD ("setting key\n");
218 ao_radio_get(AO_RADIO_SPI_CMAC_KEY, AO_AES_LEN);
219 ao_radio_spi_request.timeout = timeout;
220 ao_xmemcpy(&ao_radio_spi_request.payload, &ao_config.aes_key, AO_AES_LEN);
221 recv = ao_radio_master_send();
223 PRINTD ("key set: %d\n", recv);
227 PRINTD ("queuing recv\n");
228 ao_radio_get(AO_RADIO_SPI_CMAC_RECV, 0);
229 ao_radio_spi_request.recv_len = len;
230 recv = ao_radio_master_send();
231 PRINTD ("recv queued: %d\n", recv);
234 ao_radio_recv_abort();
235 return AO_RADIO_CMAC_TIMEOUT;
238 PRINTD ("fetching data\n");
239 ao_radio_get_data(packet, len);
240 recv = ao_radio_spi_reply.status;
241 ao_radio_cmac_rssi = ao_radio_spi_reply.rssi;
243 PRINTD ("data fetched: %d %d\n", recv, ao_radio_cmac_rssi);
247 static uint8_t ao_radio_test_on;
250 ao_radio_test(uint8_t on)
253 if (!ao_radio_test_on) {
254 ao_radio_get(AO_RADIO_SPI_TEST_ON, 0);
255 ao_radio_test_on = 1;
256 ao_radio_master_send();
259 if (ao_radio_test_on) {
260 ao_radio_spi_request.len = AO_RADIO_SPI_REQUEST_HEADER_LEN;
261 ao_radio_spi_request.request = AO_RADIO_SPI_TEST_OFF;
262 ao_radio_master_send();
263 ao_radio_test_on = 0;
270 ao_radio_test_cmd(void)
274 if (ao_cmd_lex_c != '\n') {
276 mode = (uint8_t) ao_cmd_lex_u32;
282 printf ("Hit a character to stop..."); flush();
290 __code struct ao_cmds ao_radio_cmds[] = {
291 { ao_radio_test_cmd, "C <1 start, 0 stop, none both>\0Radio carrier test" },
298 ao_spi_init_cs(AO_RADIO_CS_PORT, (1 << AO_RADIO_CS_PIN));
300 ao_enable_port(AO_RADIO_INT_PORT);
301 ao_exti_setup(AO_RADIO_INT_PORT,
303 AO_EXTI_MODE_FALLING,
305 ao_cmd_register(&ao_radio_cmds[0]);