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; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
20 #include <ao_radio_spi.h>
22 #include <ao_radio_cmac.h>
24 static struct ao_radio_spi_reply ao_radio_spi_reply;
25 static struct ao_radio_spi_request ao_radio_spi_request;
26 static volatile uint8_t ao_radio_wait_mode;
27 static volatile uint8_t ao_radio_done = 0;
28 static volatile uint8_t ao_radio_ready = 1;
29 static uint8_t ao_radio_mutex;
30 static uint8_t ao_radio_aes_seq;
32 int8_t ao_radio_cmac_rssi;
35 #define PRINTD(...) do { printf ("\r%5u %s: ", ao_tick_count, __func__); printf(__VA_ARGS__); flush(); } while(0)
43 if (ao_gpio_get(AO_RADIO_INT_PORT, AO_RADIO_INT_PIN, AO_RADIO_INT)) {
45 ao_wakeup((void *) &ao_radio_ready);
48 ao_wakeup((void *) &ao_radio_done);
53 ao_radio_master_start(void)
55 ao_spi_get_bit(AO_RADIO_CS_PORT, AO_RADIO_CS_PIN, AO_RADIO_CS,
61 ao_radio_master_stop(void)
63 ao_spi_put_bit(AO_RADIO_CS_PORT, AO_RADIO_CS_PIN, AO_RADIO_CS,
68 ao_radio_master_send(void)
72 PRINTD("send %d\n", ao_radio_spi_request.len);
75 /* Wait for radio chip to be ready for a command
78 PRINTD("Waiting radio ready\n");
79 ao_arch_block_interrupts();
80 ao_radio_ready = ao_gpio_get(AO_RADIO_INT_PORT,
81 AO_RADIO_INT_PIN, AO_RADIO_INT);
83 while (!ao_radio_ready) {
84 ret = ao_sleep((void *) &ao_radio_ready);
88 ao_arch_release_interrupts();
92 PRINTD("radio_ready %d radio_done %d\n", ao_radio_ready, ao_radio_done);
96 ao_radio_wait_mode = 0;
97 ao_radio_master_start();
98 ao_spi_send(&ao_radio_spi_request,
99 ao_radio_spi_request.len,
101 ao_radio_master_stop();
102 PRINTD("waiting for send done %d\n", ao_radio_done);
103 ao_arch_block_interrupts();
104 while (!ao_radio_done)
105 if (ao_sleep((void *) &ao_radio_done))
107 ao_arch_release_interrupts();
108 PRINTD ("sent, radio done %d isr_0 %d isr_1 %d\n", ao_radio_done, isr_0_count, isr_1_count);
109 return ao_radio_done;
113 ao_radio_get(uint8_t req, uint8_t len)
116 ao_mutex_get(&ao_radio_mutex);
117 ao_radio_spi_request.len = AO_RADIO_SPI_REQUEST_HEADER_LEN + len;
118 ao_radio_spi_request.request = req;
119 ao_radio_spi_request.setting = ao_config.radio_setting;
125 ao_mutex_put(&ao_radio_mutex);
129 ao_radio_get_data(void *d, uint8_t size)
132 ao_radio_master_start();
133 ao_spi_recv(&ao_radio_spi_reply,
134 AO_RADIO_SPI_REPLY_HEADER_LEN + size,
136 ao_radio_master_stop();
137 memcpy(d, ao_radio_spi_reply.payload, size);
138 PRINTD ("fetched %d\n", size);
142 ao_radio_recv_abort(void)
144 ao_radio_get(AO_RADIO_SPI_RECV_ABORT, 0);
145 ao_radio_master_send();
150 ao_radio_send(const void *d, uint8_t size)
152 ao_radio_get(AO_RADIO_SPI_SEND, size);
153 memcpy(&ao_radio_spi_request.payload, d, size);
154 ao_radio_master_send();
160 ao_radio_recv(void *d, uint8_t size, uint8_t timeout)
168 ao_radio_get(AO_RADIO_SPI_RECV, 0);
169 ao_radio_spi_request.recv_len = size;
170 ao_radio_spi_request.timeout = timeout;
171 recv = ao_radio_master_send();
174 ao_radio_recv_abort();
177 ao_radio_get_data(d, size);
178 recv = ao_radio_spi_reply.status;
185 ao_radio_cmac_set_key(void)
187 if (ao_radio_aes_seq == ao_config_aes_seq)
191 PRINTD ("set key\n");
192 ao_radio_get(AO_RADIO_SPI_CMAC_KEY, AO_AES_LEN);
193 memcpy(&ao_radio_spi_request.payload, &ao_config.aes_key, AO_AES_LEN);
194 ao_radio_master_send();
196 PRINTD ("key set\n");
197 ao_radio_aes_seq = ao_config_aes_seq;
201 ao_radio_cmac_send(void *packet, uint8_t len)
203 if (len > AO_CMAC_MAX_LEN)
204 return AO_RADIO_CMAC_LEN_ERROR;
206 ao_radio_cmac_set_key();
208 PRINTD ("cmac_send: send %d\n", len);
213 PRINTD ("sending packet\n");
214 ao_radio_get(AO_RADIO_SPI_CMAC_SEND, len);
215 memcpy(&ao_radio_spi_request.payload, packet, len);
216 ao_radio_master_send();
218 PRINTD ("packet sent\n");
219 return AO_RADIO_CMAC_OK;
223 ao_radio_cmac_recv(void *packet, uint8_t len, uint16_t timeout)
228 if (len > AO_CMAC_MAX_LEN)
229 return AO_RADIO_CMAC_LEN_ERROR;
231 ao_radio_cmac_set_key();
235 PRINTD ("queuing recv\n");
236 ao_radio_get(AO_RADIO_SPI_CMAC_RECV, 0);
237 ao_radio_spi_request.recv_len = len;
238 ao_radio_spi_request.timeout = timeout;
239 recv = ao_radio_master_send();
240 PRINTD ("recv queued: %d\n", recv);
243 ao_radio_recv_abort();
244 return AO_RADIO_CMAC_TIMEOUT;
247 PRINTD ("fetching data\n");
248 ao_radio_get_data(packet, len);
249 recv = ao_radio_spi_reply.status;
250 ao_radio_cmac_rssi = ao_radio_spi_reply.rssi;
252 PRINTD ("data fetched: %d %d\n", recv, ao_radio_cmac_rssi);
256 static uint8_t ao_radio_test_on;
259 ao_radio_test(uint8_t on)
262 if (!ao_radio_test_on) {
263 ao_radio_get(AO_RADIO_SPI_TEST_ON, 0);
264 ao_radio_test_on = 1;
265 ao_radio_master_send();
268 if (ao_radio_test_on) {
269 ao_radio_spi_request.len = AO_RADIO_SPI_REQUEST_HEADER_LEN;
270 ao_radio_spi_request.request = AO_RADIO_SPI_TEST_OFF;
271 ao_radio_master_send();
272 ao_radio_test_on = 0;
279 ao_radio_test_cmd(void)
283 if (ao_cmd_lex_c != '\n') {
285 mode = (uint8_t) ao_cmd_lex_u32;
291 printf ("Hit a character to stop..."); flush();
299 const struct ao_cmds ao_radio_cmds[] = {
300 { ao_radio_test_cmd, "C <1 start, 0 stop, none both>\0Radio carrier test" },
307 ao_spi_init_cs(AO_RADIO_CS_PORT, (1 << AO_RADIO_CS_PIN));
309 ao_enable_port(AO_RADIO_INT_PORT);
310 ao_exti_setup(AO_RADIO_INT_PORT,
312 AO_EXTI_MODE_RISING|AO_EXTI_MODE_FALLING,
314 ao_exti_enable(AO_RADIO_INT_PORT, AO_RADIO_INT_PIN);
315 ao_cmd_register(&ao_radio_cmds[0]);