added debugging
Fork of BLE_nRF8001 by
BLE_nRF8001/utility/hal_aci_tl.cpp@0:075ea2812998, 2014-10-17 (annotated)
- Committer:
- RedBearLab
- Date:
- Fri Oct 17 22:40:32 2014 +0800
- Revision:
- 0:075ea2812998
BLE_nRF8001 library first commit
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
RedBearLab | 0:075ea2812998 | 1 | /* Copyright (c) 2014, Nordic Semiconductor ASA |
RedBearLab | 0:075ea2812998 | 2 | * |
RedBearLab | 0:075ea2812998 | 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
RedBearLab | 0:075ea2812998 | 4 | * of this software and associated documentation files (the "Software"), to deal |
RedBearLab | 0:075ea2812998 | 5 | * in the Software without restriction, including without limitation the rights |
RedBearLab | 0:075ea2812998 | 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
RedBearLab | 0:075ea2812998 | 7 | * copies of the Software, and to permit persons to whom the Software is |
RedBearLab | 0:075ea2812998 | 8 | * furnished to do so, subject to the following conditions: |
RedBearLab | 0:075ea2812998 | 9 | * |
RedBearLab | 0:075ea2812998 | 10 | * The above copyright notice and this permission notice shall be included in all |
RedBearLab | 0:075ea2812998 | 11 | * copies or substantial portions of the Software. |
RedBearLab | 0:075ea2812998 | 12 | * |
RedBearLab | 0:075ea2812998 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
RedBearLab | 0:075ea2812998 | 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
RedBearLab | 0:075ea2812998 | 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
RedBearLab | 0:075ea2812998 | 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
RedBearLab | 0:075ea2812998 | 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
RedBearLab | 0:075ea2812998 | 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
RedBearLab | 0:075ea2812998 | 19 | * SOFTWARE. |
RedBearLab | 0:075ea2812998 | 20 | */ |
RedBearLab | 0:075ea2812998 | 21 | |
RedBearLab | 0:075ea2812998 | 22 | /** @file |
RedBearLab | 0:075ea2812998 | 23 | @brief Implementation of the ACI transport layer module |
RedBearLab | 0:075ea2812998 | 24 | */ |
RedBearLab | 0:075ea2812998 | 25 | |
RedBearLab | 0:075ea2812998 | 26 | #include "hal_platform.h" |
RedBearLab | 0:075ea2812998 | 27 | #include "hal_aci_tl.h" |
RedBearLab | 0:075ea2812998 | 28 | #include "aci_queue.h" |
RedBearLab | 0:075ea2812998 | 29 | |
RedBearLab | 0:075ea2812998 | 30 | /* |
RedBearLab | 0:075ea2812998 | 31 | PIC32 supports only MSbit transfer on SPI and the nRF8001 uses LSBit |
RedBearLab | 0:075ea2812998 | 32 | Use the REVERSE_BITS macro to convert from MSBit to LSBit |
RedBearLab | 0:075ea2812998 | 33 | The outgoing command and the incoming event needs to be converted |
RedBearLab | 0:075ea2812998 | 34 | */ |
RedBearLab | 0:075ea2812998 | 35 | //For mbed as the transmission has to be reversed, the next definitions have to be added |
RedBearLab | 0:075ea2812998 | 36 | #define REVERSE_BITS(byte) (((reverse_lookup[(byte & 0x0F)]) << 4) + reverse_lookup[((byte & 0xF0) >> 4)]) |
RedBearLab | 0:075ea2812998 | 37 | static const uint8_t reverse_lookup[] = { 0, 8, 4, 12, 2, 10, 6, 14,1, 9, 5, 13,3, 11, 7, 15 }; |
RedBearLab | 0:075ea2812998 | 38 | |
RedBearLab | 0:075ea2812998 | 39 | static void m_aci_data_print(hal_aci_data_t *p_data); |
RedBearLab | 0:075ea2812998 | 40 | static void m_aci_event_check(void); |
RedBearLab | 0:075ea2812998 | 41 | static void m_aci_isr(void); |
RedBearLab | 0:075ea2812998 | 42 | static void m_aci_pins_set(aci_pins_t *a_pins_ptr); |
RedBearLab | 0:075ea2812998 | 43 | static inline void m_aci_reqn_disable (void); |
RedBearLab | 0:075ea2812998 | 44 | static inline void m_aci_reqn_enable (void); |
RedBearLab | 0:075ea2812998 | 45 | static void m_aci_q_flush(void); |
RedBearLab | 0:075ea2812998 | 46 | static bool m_aci_spi_transfer(hal_aci_data_t * data_to_send, hal_aci_data_t * received_data); |
RedBearLab | 0:075ea2812998 | 47 | |
RedBearLab | 0:075ea2812998 | 48 | static uint8_t spi_readwrite(uint8_t aci_byte); |
RedBearLab | 0:075ea2812998 | 49 | |
RedBearLab | 0:075ea2812998 | 50 | static bool aci_debug_print = false; |
RedBearLab | 0:075ea2812998 | 51 | |
RedBearLab | 0:075ea2812998 | 52 | aci_queue_t aci_tx_q; |
RedBearLab | 0:075ea2812998 | 53 | aci_queue_t aci_rx_q; |
RedBearLab | 0:075ea2812998 | 54 | |
RedBearLab | 0:075ea2812998 | 55 | static aci_pins_t *a_pins_local_ptr; |
RedBearLab | 0:075ea2812998 | 56 | |
RedBearLab | 0:075ea2812998 | 57 | void m_aci_data_print(hal_aci_data_t *p_data) |
RedBearLab | 0:075ea2812998 | 58 | { |
RedBearLab | 0:075ea2812998 | 59 | const uint8_t length = p_data->buffer[0]; |
RedBearLab | 0:075ea2812998 | 60 | uint8_t i; |
RedBearLab | 0:075ea2812998 | 61 | serial.printf("%d", length); |
RedBearLab | 0:075ea2812998 | 62 | serial.printf(" :"); |
RedBearLab | 0:075ea2812998 | 63 | for (i=0; i<=length; i++) |
RedBearLab | 0:075ea2812998 | 64 | { |
RedBearLab | 0:075ea2812998 | 65 | serial.printf("%02X", p_data->buffer[i]); |
RedBearLab | 0:075ea2812998 | 66 | serial.printf(", "); |
RedBearLab | 0:075ea2812998 | 67 | } |
RedBearLab | 0:075ea2812998 | 68 | serial.printf(""); |
RedBearLab | 0:075ea2812998 | 69 | } |
RedBearLab | 0:075ea2812998 | 70 | |
RedBearLab | 0:075ea2812998 | 71 | /* |
RedBearLab | 0:075ea2812998 | 72 | Interrupt service routine called when the RDYN line goes low. Runs the SPI transfer. |
RedBearLab | 0:075ea2812998 | 73 | */ |
RedBearLab | 0:075ea2812998 | 74 | static void m_aci_isr(void) |
RedBearLab | 0:075ea2812998 | 75 | { |
RedBearLab | 0:075ea2812998 | 76 | hal_aci_data_t data_to_send; |
RedBearLab | 0:075ea2812998 | 77 | hal_aci_data_t received_data; |
RedBearLab | 0:075ea2812998 | 78 | |
RedBearLab | 0:075ea2812998 | 79 | // Receive from queue |
RedBearLab | 0:075ea2812998 | 80 | if (!aci_queue_dequeue_from_isr(&aci_tx_q, &data_to_send)) |
RedBearLab | 0:075ea2812998 | 81 | { |
RedBearLab | 0:075ea2812998 | 82 | /* queue was empty, nothing to send */ |
RedBearLab | 0:075ea2812998 | 83 | data_to_send.status_byte = 0; |
RedBearLab | 0:075ea2812998 | 84 | data_to_send.buffer[0] = 0; |
RedBearLab | 0:075ea2812998 | 85 | } |
RedBearLab | 0:075ea2812998 | 86 | |
RedBearLab | 0:075ea2812998 | 87 | // Receive and/or transmit data |
RedBearLab | 0:075ea2812998 | 88 | m_aci_spi_transfer(&data_to_send, &received_data); |
RedBearLab | 0:075ea2812998 | 89 | |
RedBearLab | 0:075ea2812998 | 90 | if (!aci_queue_is_full_from_isr(&aci_rx_q) && !aci_queue_is_empty_from_isr(&aci_tx_q)) |
RedBearLab | 0:075ea2812998 | 91 | { |
RedBearLab | 0:075ea2812998 | 92 | m_aci_reqn_enable(); |
RedBearLab | 0:075ea2812998 | 93 | } |
RedBearLab | 0:075ea2812998 | 94 | |
RedBearLab | 0:075ea2812998 | 95 | // Check if we received data |
RedBearLab | 0:075ea2812998 | 96 | if (received_data.buffer[0] > 0) |
RedBearLab | 0:075ea2812998 | 97 | { |
RedBearLab | 0:075ea2812998 | 98 | if (!aci_queue_enqueue_from_isr(&aci_rx_q, &received_data)) |
RedBearLab | 0:075ea2812998 | 99 | { |
RedBearLab | 0:075ea2812998 | 100 | /* Receive Buffer full. |
RedBearLab | 0:075ea2812998 | 101 | Should never happen. |
RedBearLab | 0:075ea2812998 | 102 | Spin in a while loop. |
RedBearLab | 0:075ea2812998 | 103 | */ |
RedBearLab | 0:075ea2812998 | 104 | while(1); |
RedBearLab | 0:075ea2812998 | 105 | } |
RedBearLab | 0:075ea2812998 | 106 | |
RedBearLab | 0:075ea2812998 | 107 | // Disable ready line interrupt until we have room to store incoming messages |
RedBearLab | 0:075ea2812998 | 108 | if (aci_queue_is_full_from_isr(&aci_rx_q)) |
RedBearLab | 0:075ea2812998 | 109 | { |
RedBearLab | 0:075ea2812998 | 110 | //detachInterrupt(a_pins_local_ptr->interrupt_number); |
RedBearLab | 0:075ea2812998 | 111 | } |
RedBearLab | 0:075ea2812998 | 112 | } |
RedBearLab | 0:075ea2812998 | 113 | |
RedBearLab | 0:075ea2812998 | 114 | return; |
RedBearLab | 0:075ea2812998 | 115 | } |
RedBearLab | 0:075ea2812998 | 116 | |
RedBearLab | 0:075ea2812998 | 117 | /* |
RedBearLab | 0:075ea2812998 | 118 | Checks the RDYN line and runs the SPI transfer if required. |
RedBearLab | 0:075ea2812998 | 119 | */ |
RedBearLab | 0:075ea2812998 | 120 | static void m_aci_event_check(void) |
RedBearLab | 0:075ea2812998 | 121 | { |
RedBearLab | 0:075ea2812998 | 122 | hal_aci_data_t data_to_send; |
RedBearLab | 0:075ea2812998 | 123 | hal_aci_data_t received_data; |
RedBearLab | 0:075ea2812998 | 124 | |
RedBearLab | 0:075ea2812998 | 125 | // No room to store incoming messages |
RedBearLab | 0:075ea2812998 | 126 | if (aci_queue_is_full(&aci_rx_q)) |
RedBearLab | 0:075ea2812998 | 127 | { |
RedBearLab | 0:075ea2812998 | 128 | return; |
RedBearLab | 0:075ea2812998 | 129 | } |
RedBearLab | 0:075ea2812998 | 130 | |
RedBearLab | 0:075ea2812998 | 131 | // If the ready line is disabled and we have pending messages outgoing we enable the request line |
RedBearLab | 0:075ea2812998 | 132 | if (HIGH == digitalRead(a_pins_local_ptr->rdyn_pin)) |
RedBearLab | 0:075ea2812998 | 133 | { |
RedBearLab | 0:075ea2812998 | 134 | if (!aci_queue_is_empty(&aci_tx_q)) |
RedBearLab | 0:075ea2812998 | 135 | { |
RedBearLab | 0:075ea2812998 | 136 | m_aci_reqn_enable(); |
RedBearLab | 0:075ea2812998 | 137 | } |
RedBearLab | 0:075ea2812998 | 138 | |
RedBearLab | 0:075ea2812998 | 139 | return; |
RedBearLab | 0:075ea2812998 | 140 | } |
RedBearLab | 0:075ea2812998 | 141 | |
RedBearLab | 0:075ea2812998 | 142 | // Receive from queue |
RedBearLab | 0:075ea2812998 | 143 | if (!aci_queue_dequeue(&aci_tx_q, &data_to_send)) |
RedBearLab | 0:075ea2812998 | 144 | { |
RedBearLab | 0:075ea2812998 | 145 | /* queue was empty, nothing to send */ |
RedBearLab | 0:075ea2812998 | 146 | data_to_send.status_byte = 0; |
RedBearLab | 0:075ea2812998 | 147 | data_to_send.buffer[0] = 0; |
RedBearLab | 0:075ea2812998 | 148 | } |
RedBearLab | 0:075ea2812998 | 149 | |
RedBearLab | 0:075ea2812998 | 150 | // Receive and/or transmit data |
RedBearLab | 0:075ea2812998 | 151 | m_aci_spi_transfer(&data_to_send, &received_data); |
RedBearLab | 0:075ea2812998 | 152 | |
RedBearLab | 0:075ea2812998 | 153 | /* If there are messages to transmit, and we can store the reply, we request a new transfer */ |
RedBearLab | 0:075ea2812998 | 154 | if (!aci_queue_is_full(&aci_rx_q) && !aci_queue_is_empty(&aci_tx_q)) |
RedBearLab | 0:075ea2812998 | 155 | { |
RedBearLab | 0:075ea2812998 | 156 | m_aci_reqn_enable(); |
RedBearLab | 0:075ea2812998 | 157 | } |
RedBearLab | 0:075ea2812998 | 158 | |
RedBearLab | 0:075ea2812998 | 159 | // Check if we received data |
RedBearLab | 0:075ea2812998 | 160 | if (received_data.buffer[0] > 0) |
RedBearLab | 0:075ea2812998 | 161 | { |
RedBearLab | 0:075ea2812998 | 162 | if (!aci_queue_enqueue(&aci_rx_q, &received_data)) |
RedBearLab | 0:075ea2812998 | 163 | { |
RedBearLab | 0:075ea2812998 | 164 | /* Receive Buffer full. |
RedBearLab | 0:075ea2812998 | 165 | Should never happen. |
RedBearLab | 0:075ea2812998 | 166 | Spin in a while loop. |
RedBearLab | 0:075ea2812998 | 167 | */ |
RedBearLab | 0:075ea2812998 | 168 | while(1); |
RedBearLab | 0:075ea2812998 | 169 | } |
RedBearLab | 0:075ea2812998 | 170 | } |
RedBearLab | 0:075ea2812998 | 171 | |
RedBearLab | 0:075ea2812998 | 172 | return; |
RedBearLab | 0:075ea2812998 | 173 | } |
RedBearLab | 0:075ea2812998 | 174 | |
RedBearLab | 0:075ea2812998 | 175 | /** @brief Point the low level library at the ACI pins specified |
RedBearLab | 0:075ea2812998 | 176 | * @details |
RedBearLab | 0:075ea2812998 | 177 | * The ACI pins are specified in the application and a pointer is made available for |
RedBearLab | 0:075ea2812998 | 178 | * the low level library to use |
RedBearLab | 0:075ea2812998 | 179 | */ |
RedBearLab | 0:075ea2812998 | 180 | static void m_aci_pins_set(aci_pins_t *a_pins_ptr) |
RedBearLab | 0:075ea2812998 | 181 | { |
RedBearLab | 0:075ea2812998 | 182 | a_pins_local_ptr = a_pins_ptr; |
RedBearLab | 0:075ea2812998 | 183 | } |
RedBearLab | 0:075ea2812998 | 184 | |
RedBearLab | 0:075ea2812998 | 185 | static inline void m_aci_reqn_disable (void) |
RedBearLab | 0:075ea2812998 | 186 | { |
RedBearLab | 0:075ea2812998 | 187 | digitalWrite(a_pins_local_ptr->reqn_pin, 1); |
RedBearLab | 0:075ea2812998 | 188 | } |
RedBearLab | 0:075ea2812998 | 189 | |
RedBearLab | 0:075ea2812998 | 190 | static inline void m_aci_reqn_enable (void) |
RedBearLab | 0:075ea2812998 | 191 | { |
RedBearLab | 0:075ea2812998 | 192 | digitalWrite(a_pins_local_ptr->reqn_pin, 0); |
RedBearLab | 0:075ea2812998 | 193 | } |
RedBearLab | 0:075ea2812998 | 194 | |
RedBearLab | 0:075ea2812998 | 195 | static void m_aci_q_flush(void) |
RedBearLab | 0:075ea2812998 | 196 | { |
RedBearLab | 0:075ea2812998 | 197 | //noInterrupts(); |
RedBearLab | 0:075ea2812998 | 198 | /* re-initialize aci cmd queue and aci event queue to flush them*/ |
RedBearLab | 0:075ea2812998 | 199 | aci_queue_init(&aci_tx_q); |
RedBearLab | 0:075ea2812998 | 200 | aci_queue_init(&aci_rx_q); |
RedBearLab | 0:075ea2812998 | 201 | //interrupts(); |
RedBearLab | 0:075ea2812998 | 202 | } |
RedBearLab | 0:075ea2812998 | 203 | |
RedBearLab | 0:075ea2812998 | 204 | static bool m_aci_spi_transfer(hal_aci_data_t * data_to_send, hal_aci_data_t * received_data) |
RedBearLab | 0:075ea2812998 | 205 | { |
RedBearLab | 0:075ea2812998 | 206 | uint8_t byte_cnt; |
RedBearLab | 0:075ea2812998 | 207 | uint8_t byte_sent_cnt; |
RedBearLab | 0:075ea2812998 | 208 | uint8_t max_bytes; |
RedBearLab | 0:075ea2812998 | 209 | |
RedBearLab | 0:075ea2812998 | 210 | m_aci_reqn_enable(); |
RedBearLab | 0:075ea2812998 | 211 | |
RedBearLab | 0:075ea2812998 | 212 | // Send length, receive header |
RedBearLab | 0:075ea2812998 | 213 | byte_sent_cnt = 0; |
RedBearLab | 0:075ea2812998 | 214 | received_data->status_byte = spi_readwrite(data_to_send->buffer[byte_sent_cnt++]); |
RedBearLab | 0:075ea2812998 | 215 | // Send first byte, receive length from slave |
RedBearLab | 0:075ea2812998 | 216 | received_data->buffer[0] = spi_readwrite(data_to_send->buffer[byte_sent_cnt++]); |
RedBearLab | 0:075ea2812998 | 217 | if (0 == data_to_send->buffer[0]) |
RedBearLab | 0:075ea2812998 | 218 | { |
RedBearLab | 0:075ea2812998 | 219 | max_bytes = received_data->buffer[0]; |
RedBearLab | 0:075ea2812998 | 220 | } |
RedBearLab | 0:075ea2812998 | 221 | else |
RedBearLab | 0:075ea2812998 | 222 | { |
RedBearLab | 0:075ea2812998 | 223 | // Set the maximum to the biggest size. One command byte is already sent |
RedBearLab | 0:075ea2812998 | 224 | max_bytes = (received_data->buffer[0] > (data_to_send->buffer[0] - 1)) |
RedBearLab | 0:075ea2812998 | 225 | ? received_data->buffer[0] |
RedBearLab | 0:075ea2812998 | 226 | : (data_to_send->buffer[0] - 1); |
RedBearLab | 0:075ea2812998 | 227 | } |
RedBearLab | 0:075ea2812998 | 228 | |
RedBearLab | 0:075ea2812998 | 229 | if (max_bytes > HAL_ACI_MAX_LENGTH) |
RedBearLab | 0:075ea2812998 | 230 | { |
RedBearLab | 0:075ea2812998 | 231 | max_bytes = HAL_ACI_MAX_LENGTH; |
RedBearLab | 0:075ea2812998 | 232 | } |
RedBearLab | 0:075ea2812998 | 233 | |
RedBearLab | 0:075ea2812998 | 234 | // Transmit/receive the rest of the packet |
RedBearLab | 0:075ea2812998 | 235 | for (byte_cnt = 0; byte_cnt < max_bytes; byte_cnt++) |
RedBearLab | 0:075ea2812998 | 236 | { |
RedBearLab | 0:075ea2812998 | 237 | received_data->buffer[byte_cnt+1] = spi_readwrite(data_to_send->buffer[byte_sent_cnt++]); |
RedBearLab | 0:075ea2812998 | 238 | } |
RedBearLab | 0:075ea2812998 | 239 | |
RedBearLab | 0:075ea2812998 | 240 | // RDYN should follow the REQN line in approx 100ns |
RedBearLab | 0:075ea2812998 | 241 | m_aci_reqn_disable(); |
RedBearLab | 0:075ea2812998 | 242 | |
RedBearLab | 0:075ea2812998 | 243 | return (max_bytes > 0); |
RedBearLab | 0:075ea2812998 | 244 | } |
RedBearLab | 0:075ea2812998 | 245 | |
RedBearLab | 0:075ea2812998 | 246 | void hal_aci_tl_debug_print(bool enable) |
RedBearLab | 0:075ea2812998 | 247 | { |
RedBearLab | 0:075ea2812998 | 248 | aci_debug_print = enable; |
RedBearLab | 0:075ea2812998 | 249 | } |
RedBearLab | 0:075ea2812998 | 250 | |
RedBearLab | 0:075ea2812998 | 251 | void hal_aci_tl_pin_reset(void) |
RedBearLab | 0:075ea2812998 | 252 | { |
RedBearLab | 0:075ea2812998 | 253 | if (NULL != a_pins_local_ptr->reset_pin) |
RedBearLab | 0:075ea2812998 | 254 | { |
RedBearLab | 0:075ea2812998 | 255 | pinMode(a_pins_local_ptr->reset_pin, OUTPUT); |
RedBearLab | 0:075ea2812998 | 256 | |
RedBearLab | 0:075ea2812998 | 257 | if ((REDBEARLAB_SHIELD_V1_1 == a_pins_local_ptr->board_name) || |
RedBearLab | 0:075ea2812998 | 258 | (REDBEARLAB_SHIELD_V2012_07 == a_pins_local_ptr->board_name)) |
RedBearLab | 0:075ea2812998 | 259 | { |
RedBearLab | 0:075ea2812998 | 260 | //The reset for the Redbearlab v1.1 and v2012.07 boards are inverted and has a Power On Reset |
RedBearLab | 0:075ea2812998 | 261 | //circuit that takes about 100ms to trigger the reset |
RedBearLab | 0:075ea2812998 | 262 | digitalWrite(a_pins_local_ptr->reset_pin, 1); |
RedBearLab | 0:075ea2812998 | 263 | delay(100); |
RedBearLab | 0:075ea2812998 | 264 | digitalWrite(a_pins_local_ptr->reset_pin, 0); |
RedBearLab | 0:075ea2812998 | 265 | } |
RedBearLab | 0:075ea2812998 | 266 | else |
RedBearLab | 0:075ea2812998 | 267 | { |
RedBearLab | 0:075ea2812998 | 268 | digitalWrite(a_pins_local_ptr->reset_pin, 1); |
RedBearLab | 0:075ea2812998 | 269 | digitalWrite(a_pins_local_ptr->reset_pin, 0); |
RedBearLab | 0:075ea2812998 | 270 | digitalWrite(a_pins_local_ptr->reset_pin, 1); |
RedBearLab | 0:075ea2812998 | 271 | } |
RedBearLab | 0:075ea2812998 | 272 | } |
RedBearLab | 0:075ea2812998 | 273 | } |
RedBearLab | 0:075ea2812998 | 274 | |
RedBearLab | 0:075ea2812998 | 275 | bool hal_aci_tl_event_peek(hal_aci_data_t *p_aci_data) |
RedBearLab | 0:075ea2812998 | 276 | { |
RedBearLab | 0:075ea2812998 | 277 | if (!a_pins_local_ptr->interface_is_interrupt) |
RedBearLab | 0:075ea2812998 | 278 | { |
RedBearLab | 0:075ea2812998 | 279 | m_aci_event_check(); |
RedBearLab | 0:075ea2812998 | 280 | } |
RedBearLab | 0:075ea2812998 | 281 | |
RedBearLab | 0:075ea2812998 | 282 | if (aci_queue_peek(&aci_rx_q, p_aci_data)) |
RedBearLab | 0:075ea2812998 | 283 | { |
RedBearLab | 0:075ea2812998 | 284 | return true; |
RedBearLab | 0:075ea2812998 | 285 | } |
RedBearLab | 0:075ea2812998 | 286 | |
RedBearLab | 0:075ea2812998 | 287 | return false; |
RedBearLab | 0:075ea2812998 | 288 | } |
RedBearLab | 0:075ea2812998 | 289 | |
RedBearLab | 0:075ea2812998 | 290 | bool hal_aci_tl_event_get(hal_aci_data_t *p_aci_data) |
RedBearLab | 0:075ea2812998 | 291 | { |
RedBearLab | 0:075ea2812998 | 292 | bool was_full; |
RedBearLab | 0:075ea2812998 | 293 | |
RedBearLab | 0:075ea2812998 | 294 | if (!a_pins_local_ptr->interface_is_interrupt && !aci_queue_is_full(&aci_rx_q)) |
RedBearLab | 0:075ea2812998 | 295 | { |
RedBearLab | 0:075ea2812998 | 296 | m_aci_event_check(); |
RedBearLab | 0:075ea2812998 | 297 | } |
RedBearLab | 0:075ea2812998 | 298 | |
RedBearLab | 0:075ea2812998 | 299 | was_full = aci_queue_is_full(&aci_rx_q); |
RedBearLab | 0:075ea2812998 | 300 | |
RedBearLab | 0:075ea2812998 | 301 | if (aci_queue_dequeue(&aci_rx_q, p_aci_data)) |
RedBearLab | 0:075ea2812998 | 302 | { |
RedBearLab | 0:075ea2812998 | 303 | if (aci_debug_print) |
RedBearLab | 0:075ea2812998 | 304 | { |
RedBearLab | 0:075ea2812998 | 305 | serial.printf(" E"); |
RedBearLab | 0:075ea2812998 | 306 | m_aci_data_print(p_aci_data); |
RedBearLab | 0:075ea2812998 | 307 | } |
RedBearLab | 0:075ea2812998 | 308 | |
RedBearLab | 0:075ea2812998 | 309 | if (was_full && a_pins_local_ptr->interface_is_interrupt) |
RedBearLab | 0:075ea2812998 | 310 | { |
RedBearLab | 0:075ea2812998 | 311 | /* Enable RDY line interrupt again */ |
RedBearLab | 0:075ea2812998 | 312 | //attachInterrupt(a_pins_local_ptr->interrupt_number, m_aci_isr, LOW); |
RedBearLab | 0:075ea2812998 | 313 | } |
RedBearLab | 0:075ea2812998 | 314 | |
RedBearLab | 0:075ea2812998 | 315 | /* Attempt to pull REQN LOW since we've made room for new messages */ |
RedBearLab | 0:075ea2812998 | 316 | if (!aci_queue_is_full(&aci_rx_q) && !aci_queue_is_empty(&aci_tx_q)) |
RedBearLab | 0:075ea2812998 | 317 | { |
RedBearLab | 0:075ea2812998 | 318 | m_aci_reqn_enable(); |
RedBearLab | 0:075ea2812998 | 319 | } |
RedBearLab | 0:075ea2812998 | 320 | |
RedBearLab | 0:075ea2812998 | 321 | return true; |
RedBearLab | 0:075ea2812998 | 322 | } |
RedBearLab | 0:075ea2812998 | 323 | |
RedBearLab | 0:075ea2812998 | 324 | return false; |
RedBearLab | 0:075ea2812998 | 325 | } |
RedBearLab | 0:075ea2812998 | 326 | |
RedBearLab | 0:075ea2812998 | 327 | void hal_aci_tl_init(aci_pins_t *a_pins, bool debug) |
RedBearLab | 0:075ea2812998 | 328 | { |
RedBearLab | 0:075ea2812998 | 329 | aci_debug_print = debug; |
RedBearLab | 0:075ea2812998 | 330 | |
RedBearLab | 0:075ea2812998 | 331 | /* Needs to be called as the first thing for proper intialization*/ |
RedBearLab | 0:075ea2812998 | 332 | m_aci_pins_set(a_pins); |
RedBearLab | 0:075ea2812998 | 333 | |
RedBearLab | 0:075ea2812998 | 334 | /* |
RedBearLab | 0:075ea2812998 | 335 | The SPI lines used are mapped directly to the hardware SPI |
RedBearLab | 0:075ea2812998 | 336 | MISO MOSI and SCK |
RedBearLab | 0:075ea2812998 | 337 | Change here if the pins are mapped differently |
RedBearLab | 0:075ea2812998 | 338 | |
RedBearLab | 0:075ea2812998 | 339 | The SPI library assumes that the hardware pins are used |
RedBearLab | 0:075ea2812998 | 340 | */ |
RedBearLab | 0:075ea2812998 | 341 | spi.format(8,0); |
RedBearLab | 0:075ea2812998 | 342 | spi.frequency(2000000); |
RedBearLab | 0:075ea2812998 | 343 | |
RedBearLab | 0:075ea2812998 | 344 | /* Initialize the ACI Command queue. This must be called after the delay above. */ |
RedBearLab | 0:075ea2812998 | 345 | aci_queue_init(&aci_tx_q); |
RedBearLab | 0:075ea2812998 | 346 | aci_queue_init(&aci_rx_q); |
RedBearLab | 0:075ea2812998 | 347 | |
RedBearLab | 0:075ea2812998 | 348 | //Configure the IO lines |
RedBearLab | 0:075ea2812998 | 349 | pinMode(a_pins->rdyn_pin, INPUT_PULLUP); |
RedBearLab | 0:075ea2812998 | 350 | pinMode(a_pins->reqn_pin, OUTPUT); |
RedBearLab | 0:075ea2812998 | 351 | |
RedBearLab | 0:075ea2812998 | 352 | if (NULL != a_pins->active_pin) |
RedBearLab | 0:075ea2812998 | 353 | { |
RedBearLab | 0:075ea2812998 | 354 | pinMode(a_pins->active_pin, INPUT); |
RedBearLab | 0:075ea2812998 | 355 | } |
RedBearLab | 0:075ea2812998 | 356 | /* Pin reset the nRF8001, required when the nRF8001 setup is being changed */ |
RedBearLab | 0:075ea2812998 | 357 | hal_aci_tl_pin_reset(); |
RedBearLab | 0:075ea2812998 | 358 | |
RedBearLab | 0:075ea2812998 | 359 | /* Set the nRF8001 to a known state as required by the datasheet*/ |
RedBearLab | 0:075ea2812998 | 360 | digitalWrite(a_pins->reqn_pin, 1); |
RedBearLab | 0:075ea2812998 | 361 | |
RedBearLab | 0:075ea2812998 | 362 | delay(30); //Wait for the nRF8001 to get hold of its lines - the lines float for a few ms after the reset |
RedBearLab | 0:075ea2812998 | 363 | |
RedBearLab | 0:075ea2812998 | 364 | /* Attach the interrupt to the RDYN line as requested by the caller */ |
RedBearLab | 0:075ea2812998 | 365 | if (a_pins->interface_is_interrupt) |
RedBearLab | 0:075ea2812998 | 366 | { |
RedBearLab | 0:075ea2812998 | 367 | // We use the LOW level of the RDYN line as the atmega328 can wakeup from sleep only on LOW |
RedBearLab | 0:075ea2812998 | 368 | //attachInterrupt(a_pins->interrupt_number, m_aci_isr, LOW); |
RedBearLab | 0:075ea2812998 | 369 | } |
RedBearLab | 0:075ea2812998 | 370 | } |
RedBearLab | 0:075ea2812998 | 371 | |
RedBearLab | 0:075ea2812998 | 372 | bool hal_aci_tl_send(hal_aci_data_t *p_aci_cmd) |
RedBearLab | 0:075ea2812998 | 373 | { |
RedBearLab | 0:075ea2812998 | 374 | const uint8_t length = p_aci_cmd->buffer[0]; |
RedBearLab | 0:075ea2812998 | 375 | bool ret_val = false; |
RedBearLab | 0:075ea2812998 | 376 | |
RedBearLab | 0:075ea2812998 | 377 | if (length > HAL_ACI_MAX_LENGTH) |
RedBearLab | 0:075ea2812998 | 378 | { |
RedBearLab | 0:075ea2812998 | 379 | return false; |
RedBearLab | 0:075ea2812998 | 380 | } |
RedBearLab | 0:075ea2812998 | 381 | |
RedBearLab | 0:075ea2812998 | 382 | ret_val = aci_queue_enqueue(&aci_tx_q, p_aci_cmd); |
RedBearLab | 0:075ea2812998 | 383 | if (ret_val) |
RedBearLab | 0:075ea2812998 | 384 | { |
RedBearLab | 0:075ea2812998 | 385 | if(!aci_queue_is_full(&aci_rx_q)) |
RedBearLab | 0:075ea2812998 | 386 | { |
RedBearLab | 0:075ea2812998 | 387 | // Lower the REQN only when successfully enqueued |
RedBearLab | 0:075ea2812998 | 388 | m_aci_reqn_enable(); |
RedBearLab | 0:075ea2812998 | 389 | } |
RedBearLab | 0:075ea2812998 | 390 | |
RedBearLab | 0:075ea2812998 | 391 | if (aci_debug_print) |
RedBearLab | 0:075ea2812998 | 392 | { |
RedBearLab | 0:075ea2812998 | 393 | serial.printf("C"); //ACI Command |
RedBearLab | 0:075ea2812998 | 394 | m_aci_data_print(p_aci_cmd); |
RedBearLab | 0:075ea2812998 | 395 | } |
RedBearLab | 0:075ea2812998 | 396 | } |
RedBearLab | 0:075ea2812998 | 397 | |
RedBearLab | 0:075ea2812998 | 398 | return ret_val; |
RedBearLab | 0:075ea2812998 | 399 | } |
RedBearLab | 0:075ea2812998 | 400 | |
RedBearLab | 0:075ea2812998 | 401 | static uint8_t spi_readwrite(const uint8_t aci_byte) |
RedBearLab | 0:075ea2812998 | 402 | { |
RedBearLab | 0:075ea2812998 | 403 | uint8_t tmp_byte; |
RedBearLab | 0:075ea2812998 | 404 | tmp_byte = REVERSE_BITS(aci_byte); |
RedBearLab | 0:075ea2812998 | 405 | tmp_byte = spi.write(tmp_byte); |
RedBearLab | 0:075ea2812998 | 406 | return REVERSE_BITS(tmp_byte); |
RedBearLab | 0:075ea2812998 | 407 | } |
RedBearLab | 0:075ea2812998 | 408 | |
RedBearLab | 0:075ea2812998 | 409 | bool hal_aci_tl_rx_q_empty (void) |
RedBearLab | 0:075ea2812998 | 410 | { |
RedBearLab | 0:075ea2812998 | 411 | return aci_queue_is_empty(&aci_rx_q); |
RedBearLab | 0:075ea2812998 | 412 | } |
RedBearLab | 0:075ea2812998 | 413 | |
RedBearLab | 0:075ea2812998 | 414 | bool hal_aci_tl_rx_q_full (void) |
RedBearLab | 0:075ea2812998 | 415 | { |
RedBearLab | 0:075ea2812998 | 416 | return aci_queue_is_full(&aci_rx_q); |
RedBearLab | 0:075ea2812998 | 417 | } |
RedBearLab | 0:075ea2812998 | 418 | |
RedBearLab | 0:075ea2812998 | 419 | bool hal_aci_tl_tx_q_empty (void) |
RedBearLab | 0:075ea2812998 | 420 | { |
RedBearLab | 0:075ea2812998 | 421 | return aci_queue_is_empty(&aci_tx_q); |
RedBearLab | 0:075ea2812998 | 422 | } |
RedBearLab | 0:075ea2812998 | 423 | |
RedBearLab | 0:075ea2812998 | 424 | bool hal_aci_tl_tx_q_full (void) |
RedBearLab | 0:075ea2812998 | 425 | { |
RedBearLab | 0:075ea2812998 | 426 | return aci_queue_is_full(&aci_tx_q); |
RedBearLab | 0:075ea2812998 | 427 | } |
RedBearLab | 0:075ea2812998 | 428 | |
RedBearLab | 0:075ea2812998 | 429 | void hal_aci_tl_q_flush (void) |
RedBearLab | 0:075ea2812998 | 430 | { |
RedBearLab | 0:075ea2812998 | 431 | m_aci_q_flush(); |
RedBearLab | 0:075ea2812998 | 432 | } |