added debugging
Fork of BLE_nRF8001 by
Embed:
(wiki syntax)
Show/hide line numbers
hal_aci_tl.cpp
Go to the documentation of this file.
00001 /* Copyright (c) 2014, Nordic Semiconductor ASA 00002 * 00003 * Permission is hereby granted, free of charge, to any person obtaining a copy 00004 * of this software and associated documentation files (the "Software"), to deal 00005 * in the Software without restriction, including without limitation the rights 00006 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00007 * copies of the Software, and to permit persons to whom the Software is 00008 * furnished to do so, subject to the following conditions: 00009 * 00010 * The above copyright notice and this permission notice shall be included in all 00011 * copies or substantial portions of the Software. 00012 * 00013 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00014 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00015 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00016 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00017 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00018 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 00019 * SOFTWARE. 00020 */ 00021 00022 /** @file 00023 @brief Implementation of the ACI transport layer module 00024 */ 00025 00026 #include "hal_platform.h " 00027 #include "hal_aci_tl.h" 00028 #include "aci_queue.h" 00029 00030 /* 00031 PIC32 supports only MSbit transfer on SPI and the nRF8001 uses LSBit 00032 Use the REVERSE_BITS macro to convert from MSBit to LSBit 00033 The outgoing command and the incoming event needs to be converted 00034 */ 00035 //For mbed as the transmission has to be reversed, the next definitions have to be added 00036 #define REVERSE_BITS(byte) (((reverse_lookup[(byte & 0x0F)]) << 4) + reverse_lookup[((byte & 0xF0) >> 4)]) 00037 static const uint8_t reverse_lookup[] = { 0, 8, 4, 12, 2, 10, 6, 14,1, 9, 5, 13,3, 11, 7, 15 }; 00038 00039 static void m_aci_data_print(hal_aci_data_t *p_data); 00040 static void m_aci_event_check(void); 00041 static void m_aci_isr(void); 00042 static void m_aci_pins_set(aci_pins_t *a_pins_ptr); 00043 static inline void m_aci_reqn_disable (void); 00044 static inline void m_aci_reqn_enable (void); 00045 static void m_aci_q_flush(void); 00046 static bool m_aci_spi_transfer(hal_aci_data_t * data_to_send, hal_aci_data_t * received_data); 00047 00048 static uint8_t spi_readwrite(uint8_t aci_byte); 00049 00050 static bool aci_debug_print = false; 00051 00052 aci_queue_t aci_tx_q; 00053 aci_queue_t aci_rx_q; 00054 00055 static aci_pins_t *a_pins_local_ptr; 00056 00057 void m_aci_data_print(hal_aci_data_t *p_data) 00058 { 00059 const uint8_t length = p_data->buffer[0]; 00060 uint8_t i; 00061 serial.printf("%d", length); 00062 serial.printf(" :"); 00063 for (i=0; i<=length; i++) 00064 { 00065 serial.printf("%02X", p_data->buffer[i]); 00066 serial.printf(", "); 00067 } 00068 serial.printf(""); 00069 } 00070 00071 /* 00072 Interrupt service routine called when the RDYN line goes low. Runs the SPI transfer. 00073 */ 00074 static void m_aci_isr(void) 00075 { 00076 hal_aci_data_t data_to_send; 00077 hal_aci_data_t received_data; 00078 00079 // Receive from queue 00080 if (!aci_queue_dequeue_from_isr(&aci_tx_q, &data_to_send)) 00081 { 00082 /* queue was empty, nothing to send */ 00083 data_to_send.status_byte = 0; 00084 data_to_send.buffer[0] = 0; 00085 } 00086 00087 // Receive and/or transmit data 00088 m_aci_spi_transfer(&data_to_send, &received_data); 00089 00090 if (!aci_queue_is_full_from_isr(&aci_rx_q) && !aci_queue_is_empty_from_isr(&aci_tx_q)) 00091 { 00092 m_aci_reqn_enable(); 00093 } 00094 00095 // Check if we received data 00096 if (received_data.buffer[0] > 0) 00097 { 00098 if (!aci_queue_enqueue_from_isr(&aci_rx_q, &received_data)) 00099 { 00100 /* Receive Buffer full. 00101 Should never happen. 00102 Spin in a while loop. 00103 */ 00104 while(1); 00105 } 00106 00107 // Disable ready line interrupt until we have room to store incoming messages 00108 if (aci_queue_is_full_from_isr(&aci_rx_q)) 00109 { 00110 //detachInterrupt(a_pins_local_ptr->interrupt_number); 00111 } 00112 } 00113 00114 return; 00115 } 00116 00117 /* 00118 Checks the RDYN line and runs the SPI transfer if required. 00119 */ 00120 static void m_aci_event_check(void) 00121 { 00122 hal_aci_data_t data_to_send; 00123 hal_aci_data_t received_data; 00124 00125 // No room to store incoming messages 00126 if (aci_queue_is_full(&aci_rx_q)) 00127 { 00128 return; 00129 } 00130 00131 // If the ready line is disabled and we have pending messages outgoing we enable the request line 00132 if (HIGH == digitalRead(a_pins_local_ptr->rdyn_pin)) 00133 { 00134 if (!aci_queue_is_empty(&aci_tx_q)) 00135 { 00136 m_aci_reqn_enable(); 00137 } 00138 00139 return; 00140 } 00141 00142 // Receive from queue 00143 if (!aci_queue_dequeue(&aci_tx_q, &data_to_send)) 00144 { 00145 /* queue was empty, nothing to send */ 00146 data_to_send.status_byte = 0; 00147 data_to_send.buffer[0] = 0; 00148 } 00149 00150 // Receive and/or transmit data 00151 m_aci_spi_transfer(&data_to_send, &received_data); 00152 00153 /* If there are messages to transmit, and we can store the reply, we request a new transfer */ 00154 if (!aci_queue_is_full(&aci_rx_q) && !aci_queue_is_empty(&aci_tx_q)) 00155 { 00156 m_aci_reqn_enable(); 00157 } 00158 00159 // Check if we received data 00160 if (received_data.buffer[0] > 0) 00161 { 00162 if (!aci_queue_enqueue(&aci_rx_q, &received_data)) 00163 { 00164 /* Receive Buffer full. 00165 Should never happen. 00166 Spin in a while loop. 00167 */ 00168 while(1); 00169 } 00170 } 00171 00172 return; 00173 } 00174 00175 /** @brief Point the low level library at the ACI pins specified 00176 * @details 00177 * The ACI pins are specified in the application and a pointer is made available for 00178 * the low level library to use 00179 */ 00180 static void m_aci_pins_set(aci_pins_t *a_pins_ptr) 00181 { 00182 a_pins_local_ptr = a_pins_ptr; 00183 } 00184 00185 static inline void m_aci_reqn_disable (void) 00186 { 00187 digitalWrite(a_pins_local_ptr->reqn_pin, 1); 00188 } 00189 00190 static inline void m_aci_reqn_enable (void) 00191 { 00192 digitalWrite(a_pins_local_ptr->reqn_pin, 0); 00193 } 00194 00195 static void m_aci_q_flush(void) 00196 { 00197 //noInterrupts(); 00198 /* re-initialize aci cmd queue and aci event queue to flush them*/ 00199 aci_queue_init(&aci_tx_q); 00200 aci_queue_init(&aci_rx_q); 00201 //interrupts(); 00202 } 00203 00204 static bool m_aci_spi_transfer(hal_aci_data_t * data_to_send, hal_aci_data_t * received_data) 00205 { 00206 uint8_t byte_cnt; 00207 uint8_t byte_sent_cnt; 00208 uint8_t max_bytes; 00209 00210 m_aci_reqn_enable(); 00211 00212 // Send length, receive header 00213 byte_sent_cnt = 0; 00214 received_data->status_byte = spi_readwrite(data_to_send->buffer[byte_sent_cnt++]); 00215 // Send first byte, receive length from slave 00216 received_data->buffer[0] = spi_readwrite(data_to_send->buffer[byte_sent_cnt++]); 00217 if (0 == data_to_send->buffer[0]) 00218 { 00219 max_bytes = received_data->buffer[0]; 00220 } 00221 else 00222 { 00223 // Set the maximum to the biggest size. One command byte is already sent 00224 max_bytes = (received_data->buffer[0] > (data_to_send->buffer[0] - 1)) 00225 ? received_data->buffer[0] 00226 : (data_to_send->buffer[0] - 1); 00227 } 00228 00229 if (max_bytes > HAL_ACI_MAX_LENGTH) 00230 { 00231 max_bytes = HAL_ACI_MAX_LENGTH; 00232 } 00233 00234 // Transmit/receive the rest of the packet 00235 for (byte_cnt = 0; byte_cnt < max_bytes; byte_cnt++) 00236 { 00237 received_data->buffer[byte_cnt+1] = spi_readwrite(data_to_send->buffer[byte_sent_cnt++]); 00238 } 00239 00240 // RDYN should follow the REQN line in approx 100ns 00241 m_aci_reqn_disable(); 00242 00243 return (max_bytes > 0); 00244 } 00245 00246 void hal_aci_tl_debug_print(bool enable) 00247 { 00248 aci_debug_print = enable; 00249 } 00250 00251 void hal_aci_tl_pin_reset(void) 00252 { 00253 if (NULL != a_pins_local_ptr->reset_pin) 00254 { 00255 pinMode(a_pins_local_ptr->reset_pin, OUTPUT); 00256 00257 if ((REDBEARLAB_SHIELD_V1_1 == a_pins_local_ptr->board_name) || 00258 (REDBEARLAB_SHIELD_V2012_07 == a_pins_local_ptr->board_name)) 00259 { 00260 //The reset for the Redbearlab v1.1 and v2012.07 boards are inverted and has a Power On Reset 00261 //circuit that takes about 100ms to trigger the reset 00262 digitalWrite(a_pins_local_ptr->reset_pin, 1); 00263 delay(100); 00264 digitalWrite(a_pins_local_ptr->reset_pin, 0); 00265 } 00266 else 00267 { 00268 digitalWrite(a_pins_local_ptr->reset_pin, 1); 00269 digitalWrite(a_pins_local_ptr->reset_pin, 0); 00270 digitalWrite(a_pins_local_ptr->reset_pin, 1); 00271 } 00272 } 00273 } 00274 00275 bool hal_aci_tl_event_peek(hal_aci_data_t *p_aci_data) 00276 { 00277 if (!a_pins_local_ptr->interface_is_interrupt) 00278 { 00279 m_aci_event_check(); 00280 } 00281 00282 if (aci_queue_peek(&aci_rx_q, p_aci_data)) 00283 { 00284 return true; 00285 } 00286 00287 return false; 00288 } 00289 00290 bool hal_aci_tl_event_get(hal_aci_data_t *p_aci_data) 00291 { 00292 bool was_full; 00293 00294 if (!a_pins_local_ptr->interface_is_interrupt && !aci_queue_is_full(&aci_rx_q)) 00295 { 00296 m_aci_event_check(); 00297 } 00298 00299 was_full = aci_queue_is_full(&aci_rx_q); 00300 00301 if (aci_queue_dequeue(&aci_rx_q, p_aci_data)) 00302 { 00303 if (aci_debug_print) 00304 { 00305 serial.printf(" E"); 00306 m_aci_data_print(p_aci_data); 00307 } 00308 00309 if (was_full && a_pins_local_ptr->interface_is_interrupt) 00310 { 00311 /* Enable RDY line interrupt again */ 00312 //attachInterrupt(a_pins_local_ptr->interrupt_number, m_aci_isr, LOW); 00313 } 00314 00315 /* Attempt to pull REQN LOW since we've made room for new messages */ 00316 if (!aci_queue_is_full(&aci_rx_q) && !aci_queue_is_empty(&aci_tx_q)) 00317 { 00318 m_aci_reqn_enable(); 00319 } 00320 00321 return true; 00322 } 00323 00324 return false; 00325 } 00326 00327 void hal_aci_tl_init(aci_pins_t *a_pins, bool debug) 00328 { 00329 aci_debug_print = debug; 00330 00331 /* Needs to be called as the first thing for proper intialization*/ 00332 m_aci_pins_set(a_pins); 00333 00334 /* 00335 The SPI lines used are mapped directly to the hardware SPI 00336 MISO MOSI and SCK 00337 Change here if the pins are mapped differently 00338 00339 The SPI library assumes that the hardware pins are used 00340 */ 00341 spi.format(8,0); 00342 spi.frequency(2000000); 00343 00344 /* Initialize the ACI Command queue. This must be called after the delay above. */ 00345 aci_queue_init(&aci_tx_q); 00346 aci_queue_init(&aci_rx_q); 00347 00348 //Configure the IO lines 00349 pinMode(a_pins->rdyn_pin, INPUT_PULLUP); 00350 pinMode(a_pins->reqn_pin, OUTPUT); 00351 00352 if (NULL != a_pins->active_pin) 00353 { 00354 pinMode(a_pins->active_pin, INPUT); 00355 } 00356 /* Pin reset the nRF8001, required when the nRF8001 setup is being changed */ 00357 hal_aci_tl_pin_reset(); 00358 00359 /* Set the nRF8001 to a known state as required by the datasheet*/ 00360 digitalWrite(a_pins->reqn_pin, 1); 00361 00362 delay(30); //Wait for the nRF8001 to get hold of its lines - the lines float for a few ms after the reset 00363 00364 /* Attach the interrupt to the RDYN line as requested by the caller */ 00365 if (a_pins->interface_is_interrupt) 00366 { 00367 // We use the LOW level of the RDYN line as the atmega328 can wakeup from sleep only on LOW 00368 //attachInterrupt(a_pins->interrupt_number, m_aci_isr, LOW); 00369 } 00370 } 00371 00372 bool hal_aci_tl_send(hal_aci_data_t *p_aci_cmd) 00373 { 00374 const uint8_t length = p_aci_cmd->buffer[0]; 00375 bool ret_val = false; 00376 00377 if (length > HAL_ACI_MAX_LENGTH) 00378 { 00379 return false; 00380 } 00381 00382 ret_val = aci_queue_enqueue(&aci_tx_q, p_aci_cmd); 00383 if (ret_val) 00384 { 00385 if(!aci_queue_is_full(&aci_rx_q)) 00386 { 00387 // Lower the REQN only when successfully enqueued 00388 m_aci_reqn_enable(); 00389 } 00390 00391 if (aci_debug_print) 00392 { 00393 serial.printf("C"); //ACI Command 00394 m_aci_data_print(p_aci_cmd); 00395 } 00396 } 00397 00398 return ret_val; 00399 } 00400 00401 static uint8_t spi_readwrite(const uint8_t aci_byte) 00402 { 00403 uint8_t tmp_byte; 00404 tmp_byte = REVERSE_BITS(aci_byte); 00405 tmp_byte = spi.write(tmp_byte); 00406 return REVERSE_BITS(tmp_byte); 00407 } 00408 00409 bool hal_aci_tl_rx_q_empty (void) 00410 { 00411 return aci_queue_is_empty(&aci_rx_q); 00412 } 00413 00414 bool hal_aci_tl_rx_q_full (void) 00415 { 00416 return aci_queue_is_full(&aci_rx_q); 00417 } 00418 00419 bool hal_aci_tl_tx_q_empty (void) 00420 { 00421 return aci_queue_is_empty(&aci_tx_q); 00422 } 00423 00424 bool hal_aci_tl_tx_q_full (void) 00425 { 00426 return aci_queue_is_full(&aci_tx_q); 00427 } 00428 00429 void hal_aci_tl_q_flush (void) 00430 { 00431 m_aci_q_flush(); 00432 }
Generated on Tue Jul 12 2022 15:15:46 by 1.7.2