An I2C Scanner, to test that your I2C can be detected. Works with the NRF51 Development Kit.

Dependencies:   mbed-src-nrf51822

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers wire.cpp Source File

wire.cpp

00001 /*
00002  
00003     Copyright (c) 2014 RedBearLab, All rights reserved.
00004  
00005     This library is free software; you can redistribute it and/or
00006     modify it under the terms of the GNU Lesser General Public
00007     License as published by the Free Software Foundation; either
00008     version 2.1 of the License, or (at your option) any later version.
00009  
00010     This library is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00013     See the GNU Lesser General Public License for more details.
00014  
00015     You should have received a copy of the GNU Lesser General Public
00016     License along with this library; if not, write to the Free Software
00017     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00018  
00019     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00020     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00021     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
00022     IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
00023     CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
00024     TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
00025     SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00026  
00027 */
00028  
00029 #include "wire.h"
00030 #include "nrf_soc.h"
00031 #include "nrf_sdm.h"
00032  
00033 //extern Serial pc;
00034 /**********************************************************************
00035 name :
00036 function : return: 0--SUCCESS, 1--FAIL
00037 **********************************************************************/
00038 bool TwoWire::twi_master_clear_bus(void)
00039 {
00040     bool bus_clear;
00041     uint32_t twi_state;
00042     uint32_t sck_pin_config;
00043     uint32_t sda_pin_config;
00044     
00045     twi_state = twi->ENABLE;
00046     twi->ENABLE = TWI_ENABLE_ENABLE_Disabled << TWI_ENABLE_ENABLE_Pos;
00047     
00048     sck_pin_config = NRF_GPIO->PIN_CNF[SCL_Pin]; 
00049     NRF_GPIO->PIN_CNF[SCL_Pin] = (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) 
00050                                   | (GPIO_PIN_CNF_DRIVE_S0D1     << GPIO_PIN_CNF_DRIVE_Pos) 
00051                                   | (GPIO_PIN_CNF_PULL_Pullup    << GPIO_PIN_CNF_PULL_Pos)  
00052                                   | (GPIO_PIN_CNF_INPUT_Connect  << GPIO_PIN_CNF_INPUT_Pos) 
00053                                   | (GPIO_PIN_CNF_DIR_Output     << GPIO_PIN_CNF_DIR_Pos);
00054  
00055     sda_pin_config = NRF_GPIO->PIN_CNF[SDA_Pin];    
00056     NRF_GPIO->PIN_CNF[SDA_Pin] = (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) 
00057                                   | (GPIO_PIN_CNF_DRIVE_S0D1     << GPIO_PIN_CNF_DRIVE_Pos) 
00058                                   | (GPIO_PIN_CNF_PULL_Pullup    << GPIO_PIN_CNF_PULL_Pos)  
00059                                   | (GPIO_PIN_CNF_INPUT_Connect  << GPIO_PIN_CNF_INPUT_Pos) 
00060                                   | (GPIO_PIN_CNF_DIR_Output     << GPIO_PIN_CNF_DIR_Pos);  
00061                                   
00062     NRF_GPIO->OUTSET = ( 1 << SCL_Pin );
00063     NRF_GPIO->OUTSET = ( 1 << SDA_Pin );
00064     TWI_DELAY(4);
00065     
00066     if( ( (NRF_GPIO->IN >> SCL_Pin) & 0X1UL ) && ( (NRF_GPIO->IN >> SDA_Pin) & 0x1UL ) )
00067     {
00068         bus_clear = 0;
00069     }
00070     else
00071     {
00072         uint_fast8_t index;
00073         bus_clear = 1;
00074         for( index=18; index--;)
00075         {
00076             NRF_GPIO->OUTCLR = ( 1 << SCL_Pin );
00077             TWI_DELAY(4);
00078             NRF_GPIO->OUTSET = ( 1 << SDA_Pin );
00079             TWI_DELAY(4);
00080             
00081             if( (NRF_GPIO->IN >> SDA_Pin) & 0x1UL == 1 )
00082             {
00083                 bus_clear = 0;
00084                 break;
00085             }
00086         }
00087     }
00088     
00089     NRF_GPIO->PIN_CNF[SCL_Pin] = sck_pin_config;
00090     NRF_GPIO->PIN_CNF[SDA_Pin]  = sda_pin_config;
00091  
00092     twi->ENABLE = twi_state;    
00093     
00094     return bus_clear;
00095 }
00096  
00097 /**********************************************************************
00098 name :
00099 function : return: 0--SUCCESS, 1--FAIL
00100 **********************************************************************/
00101 bool TwoWire::twi_master_init(void)
00102 {   
00103     uint8_t softdevice_enabled;
00104     //uint32_t err_code = NRF_SUCCESS;
00105  
00106     NRF_GPIO->PIN_CNF[SCL_Pin] = (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
00107                                   | (GPIO_PIN_CNF_DRIVE_S0D1     << GPIO_PIN_CNF_DRIVE_Pos)
00108                                   | (GPIO_PIN_CNF_PULL_Pullup    << GPIO_PIN_CNF_PULL_Pos)
00109                                   | (GPIO_PIN_CNF_INPUT_Connect  << GPIO_PIN_CNF_INPUT_Pos)
00110                                   | (GPIO_PIN_CNF_DIR_Input      << GPIO_PIN_CNF_DIR_Pos);  
00111                                   
00112     NRF_GPIO->PIN_CNF[SDA_Pin] = (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
00113                                   | (GPIO_PIN_CNF_DRIVE_S0D1     << GPIO_PIN_CNF_DRIVE_Pos)
00114                                   | (GPIO_PIN_CNF_PULL_Pullup    << GPIO_PIN_CNF_PULL_Pos)
00115                                   | (GPIO_PIN_CNF_INPUT_Connect  << GPIO_PIN_CNF_INPUT_Pos)
00116                                   | (GPIO_PIN_CNF_DIR_Input      << GPIO_PIN_CNF_DIR_Pos);
00117                                   
00118     twi->EVENTS_RXDREADY = 0;
00119     twi->EVENTS_TXDSENT  = 0;
00120     twi->PSELSCL = SCL_Pin;
00121     twi->PSELSDA = SDA_Pin;
00122     twi->FREQUENCY = twi_frequency; //TWI_FREQUENCY_FREQUENCY_K100 << TWI_FREQUENCY_FREQUENCY_Pos;
00123     
00124     sd_softdevice_is_enabled(&softdevice_enabled);
00125     //APP_ERROR_CHECK(err_code);
00126     if (softdevice_enabled == 0)
00127     {   
00128         NRF_PPI->CH[7].EEP  =   (uint32_t)&twi->EVENTS_BB;
00129         NRF_PPI->CH[7].TEP  =   (uint32_t)&twi->TASKS_SUSPEND;
00130         NRF_PPI->CHEN &= ~(1 << 7);
00131     }
00132     else
00133     {
00134         sd_ppi_channel_assign(7, &twi->EVENTS_BB, &twi->TASKS_SUSPEND);
00135         //APP_ERROR_CHECK(err_code);
00136         sd_ppi_channel_enable_clr(1 << 7);
00137         //APP_ERROR_CHECK(err_code);
00138     }
00139     
00140     twi->ENABLE = TWI_ENABLE_ENABLE_Enabled << TWI_ENABLE_ENABLE_Pos;  
00141     
00142     return twi_master_clear_bus();
00143 }
00144 /**********************************************************************
00145 name :
00146 function : return: 0--SUCCESS, 1--FAIL
00147 **********************************************************************/
00148 uint8_t TwoWire::twi_master_write(uint8_t *data, uint8_t data_length, uint8_t issue_stop_condition)
00149 {
00150     uint32_t timeout = MAX_TIMEOUT_LOOPS;
00151     
00152     if(data_length == 0)
00153     {
00154         return 1;
00155     }
00156     twi->TXD = *data++;
00157     twi->TASKS_STARTTX = 1;
00158     while(1)
00159     {   
00160         while( (twi->EVENTS_TXDSENT == 0) && (--timeout) );//&& (twi->EVENTS_ERROR == 0) );
00161         
00162         if( 0 == timeout )//|| twi->EVENTS_ERROR != 0)
00163         {   
00164             twi->EVENTS_ERROR = 0;
00165             twi->ENABLE     = TWI_ENABLE_ENABLE_Disabled << TWI_ENABLE_ENABLE_Pos; 
00166             twi->POWER        = 0; 
00167             TWI_DELAY(5);
00168             twi->POWER        = 1; 
00169             twi->ENABLE     = TWI_ENABLE_ENABLE_Enabled << TWI_ENABLE_ENABLE_Pos;
00170             
00171             twi_master_init();
00172             return 1;
00173         }
00174         twi->EVENTS_TXDSENT = 0;
00175         if( --data_length == 0)
00176         {   
00177             break;
00178         }
00179         
00180         twi->TXD = *data++;
00181     }
00182     if(issue_stop_condition)
00183     {   
00184         twi->EVENTS_STOPPED = 0;
00185         twi->TASKS_STOP     = 1;
00186         while(twi->EVENTS_STOPPED == 0)
00187         {
00188             //do nothing, wait for stop sequence is sent
00189         }       
00190     }
00191     return 0;
00192 }
00193 /**********************************************************************
00194 name :
00195 function : return: 0--SUCCESS, 1--FAIL
00196 **********************************************************************/
00197 uint8_t TwoWire::twi_master_read(uint8_t *data, uint8_t data_length, uint8_t issue_stop_condition)
00198 {   
00199     uint8_t softdevice_enabled;
00200     uint32_t timeout = MAX_TIMEOUT_LOOPS;// err_code = NRF_SUCCESS;
00201  
00202     sd_softdevice_is_enabled(&softdevice_enabled);
00203     //APP_ERROR_CHECK(err_code);
00204     if( 0 == data_length )
00205     {
00206         return 1;
00207     }
00208     else if( 1== data_length )//&& issue_stop_condition == 1)
00209     {
00210         if (softdevice_enabled == 0)
00211         {   
00212             NRF_PPI->CH[7].EEP = (uint32_t)&twi->EVENTS_BB;
00213             NRF_PPI->CH[7].TEP = (uint32_t)&twi->TASKS_STOP;
00214             NRF_PPI->CHEN |= (1 << 7);
00215         }
00216         else
00217         {
00218             sd_ppi_channel_assign(7, &twi->EVENTS_BB, &twi->TASKS_STOP);
00219             //APP_ERROR_CHECK(err_code);
00220             sd_ppi_channel_enable_set(1 << 7);
00221             //APP_ERROR_CHECK(err_code);
00222         }
00223     }
00224     else
00225     {   
00226         if (softdevice_enabled == 0)
00227         {   
00228             NRF_PPI->CH[7].EEP = (uint32_t)&twi->EVENTS_BB;
00229             NRF_PPI->CH[7].TEP = (uint32_t)&twi->TASKS_SUSPEND;
00230             NRF_PPI->CHEN |= (1 << 7);
00231         }
00232         else
00233         {
00234             sd_ppi_channel_assign(7, &twi->EVENTS_BB, &twi->TASKS_SUSPEND);
00235             //APP_ERROR_CHECK(err_code);
00236             sd_ppi_channel_enable_set(1 << 7);
00237             //APP_ERROR_CHECK(err_code);          
00238         }
00239     }
00240     
00241     twi->EVENTS_RXDREADY = 0;
00242     twi->TASKS_STARTRX = 1;
00243     
00244     while(1)
00245     {   
00246         while( twi->EVENTS_RXDREADY == 0 && (--timeout) )
00247         {
00248             //do nothing, just wait
00249         }
00250     
00251         if( timeout == 0 )
00252         {   
00253             twi->EVENTS_ERROR = 0;
00254             twi->ENABLE       = TWI_ENABLE_ENABLE_Disabled << TWI_ENABLE_ENABLE_Pos; 
00255             twi->POWER        = 0; 
00256             TWI_DELAY(5);
00257             twi->POWER        = 1; 
00258             twi->ENABLE       = TWI_ENABLE_ENABLE_Enabled << TWI_ENABLE_ENABLE_Pos;
00259     
00260             twi_master_init();          
00261           
00262             return 1;           
00263         }
00264         
00265         twi->EVENTS_RXDREADY = 0;
00266         *data++ = twi->RXD;
00267     
00268         if( --data_length == 1 )
00269         {   
00270             if (softdevice_enabled == 0)
00271             {   
00272                 //NRF_PPI->CH[7].EEP = (uint32_t)&twi->EVENTS_BB;
00273                 NRF_PPI->CH[7].TEP = (uint32_t)&twi->TASKS_STOP;
00274             }
00275             else
00276             {
00277                 sd_ppi_channel_assign(7, &twi->EVENTS_BB, &twi->TASKS_STOP);
00278                 //APP_ERROR_CHECK(err_code);
00279             }
00280         }
00281         
00282         if( data_length == 0 )
00283         {   
00284             twi->TASKS_STOP = 1;
00285             break;
00286         }
00287         TWI_DELAY(20);
00288         twi->TASKS_RESUME = 1;
00289     }
00290     while( twi->EVENTS_STOPPED == 0 )
00291     {
00292         //do nothing
00293     }
00294  
00295     twi->EVENTS_STOPPED = 0;
00296     
00297     if (softdevice_enabled == 0)
00298     {       
00299         NRF_PPI->CHEN &= ~(1 << 7);
00300     }
00301     else
00302     {
00303         sd_ppi_channel_enable_clr( 1 << 7 );
00304         //APP_ERROR_CHECK(err_code);
00305     }
00306     return 0;
00307 }
00308  
00309 /**********************************************************************
00310 name :
00311 function : 
00312 **********************************************************************/
00313 TwoWire::TwoWire(NRF_TWI_Type *twi_use)
00314 {
00315     twi = twi_use;
00316     
00317     RX_BufferIndex  = 0;
00318     RX_BufferLength = 0;
00319     TX_BufferIndex  = 0;
00320     TX_BufferLength = 0;
00321     
00322     Transform_Addr  = 0;
00323     
00324     twi_status      = UNINITIALIZED;
00325 }
00326 /**********************************************************************
00327 name :
00328 function : 
00329 **********************************************************************/
00330 void TwoWire::begin(uint32_t scl, uint32_t sda, uint8_t speed)
00331 {     
00332     if( speed == 2 )
00333     {
00334         twi_frequency = TWI_FREQUENCY_FREQUENCY_K400;
00335     }
00336     else if( speed == 1 )
00337     {
00338         twi_frequency = TWI_FREQUENCY_FREQUENCY_K250;
00339     }
00340     else
00341     {
00342         twi_frequency = TWI_FREQUENCY_FREQUENCY_K100;   
00343     }
00344     
00345     SCL_Pin = scl;
00346     SDA_Pin = sda;
00347     twi_master_init();
00348  
00349     twi_status = MASTER_IDLE;   
00350 }
00351 /**********************************************************************
00352 name :
00353 function : 
00354 **********************************************************************/
00355 void TwoWire::begin()
00356 {
00357     begin(TWI_SCL, TWI_SDA, 0);
00358 }
00359 /**********************************************************************
00360 name :
00361 function : 
00362 **********************************************************************/
00363 void TwoWire::beginTransmission( uint8_t address )
00364 {
00365     Transform_Addr = address;
00366     TX_BufferIndex = 0;
00367     twi_status = MASTER_SEND;
00368 }
00369 /**********************************************************************
00370 name :
00371 function : 
00372 **********************************************************************/
00373 void TwoWire::beginTransmission( int address )
00374 {
00375     beginTransmission( (uint8_t)address );
00376 }
00377 /**********************************************************************
00378 name :
00379 function :  return: 0--SUCCESS, 1--FAIL
00380 **********************************************************************/
00381 uint8_t TwoWire::endTransmission( uint8_t stop)
00382 {
00383     uint8_t twi_flag = 1;
00384  
00385     if(TX_BufferLength > 0 && !(twi_master_clear_bus()) )
00386     {   
00387         twi->ADDRESS = ( Transform_Addr >> 1);
00388         twi_flag = twi_master_write(TX_Buffer, TX_BufferLength, stop);
00389     }
00390     
00391     TX_BufferLength = 0;
00392     twi_status = MASTER_IDLE;
00393  
00394     return twi_flag;
00395 }
00396 /**********************************************************************
00397 name :
00398 function : return: 0--SUCCESS, 1--FAIL
00399 **********************************************************************/
00400 uint8_t TwoWire::endTransmission(void)
00401 {
00402     uint8_t twi_flag;
00403     
00404     twi_flag = endTransmission(1);
00405     
00406     return twi_flag;
00407 }
00408 /**********************************************************************
00409 name :
00410 function : return: 0--SUCCESS, -1--FAIL,
00411 **********************************************************************/
00412 int TwoWire::write(uint8_t data)
00413 {
00414     if(twi_status == MASTER_SEND)
00415     {   
00416         if(TX_BufferLength >= BUFF_MAX_LENGTH)
00417         {
00418             return -1;
00419         }
00420         TX_Buffer[TX_BufferLength++] = data;
00421         return 0;
00422     }
00423     else
00424     {
00425         return -1;
00426     }
00427 }
00428 /**********************************************************************
00429 name :
00430 function : return: -1--FAIL, else--the length of data stored
00431 **********************************************************************/
00432 int TwoWire::write(const uint8_t *data, size_t quantity )
00433 {
00434     if( twi_status == MASTER_SEND )
00435     {
00436         for( size_t i=0; i<quantity; ++i )
00437         {   
00438             if(TX_BufferLength >= BUFF_MAX_LENGTH)
00439             {
00440                 return i;
00441             }
00442             TX_Buffer[TX_BufferLength++] = data[i];
00443         }
00444     }
00445     else
00446     {
00447         return -1;
00448     }
00449     
00450     return quantity;
00451 }
00452 /**********************************************************************
00453 name :
00454 function : return: 0--SUCCESS, 1--FAIL
00455 **********************************************************************/
00456 uint8_t TwoWire::requestFrom(uint8_t addr, uint8_t quantity, uint8_t stop)
00457 {
00458     uint8_t twi_flag = 1;
00459     
00460     if(quantity > BUFF_MAX_LENGTH)
00461     {   
00462         quantity = BUFF_MAX_LENGTH;
00463     }
00464     if(quantity > 0 && !(twi_master_clear_bus()) )
00465     {   
00466         twi->ADDRESS = ( addr >> 1 );
00467         twi_flag = twi_master_read(RX_Buffer, quantity, stop);
00468     }
00469     RX_BufferIndex = 0;
00470     RX_BufferLength = quantity;
00471     
00472     return twi_flag;
00473 }
00474 /**********************************************************************
00475 name :
00476 function : 
00477 **********************************************************************/
00478 uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity)
00479 {
00480     return requestFrom((uint8_t) address, (uint8_t) quantity, (uint8_t) true);
00481 }
00482 /**********************************************************************
00483 name :
00484 function : 
00485 **********************************************************************/
00486 uint8_t TwoWire::requestFrom(int address, int quantity) 
00487 {
00488     return requestFrom((uint8_t) address, (uint8_t) quantity, (uint8_t) true);
00489 }
00490 /**********************************************************************
00491 name :
00492 function : 
00493 **********************************************************************/
00494 uint8_t TwoWire::requestFrom(int address, int quantity, int sendStop) 
00495 {
00496     return requestFrom((uint8_t) address, (uint8_t) quantity, (uint8_t) sendStop);
00497 }
00498 /**********************************************************************
00499 name :
00500 function : return:-1--FAIL, else:the length of data that could be read
00501 **********************************************************************/
00502 int TwoWire::available(void)
00503 {
00504     if(RX_BufferIndex <= RX_BufferLength)
00505     {
00506         return (RX_BufferLength - RX_BufferIndex);
00507     }
00508     else
00509     {
00510         return -1;
00511     }
00512 }
00513 /**********************************************************************
00514 name :
00515 function : 
00516 **********************************************************************/
00517 int TwoWire::read(void)
00518 {
00519     if(RX_BufferIndex < RX_BufferLength)
00520     {
00521         return RX_Buffer[RX_BufferIndex++];
00522     }
00523     else
00524     {
00525         return -1;
00526     }
00527 }
00528