I2C example for BLE Nano and RedBearLab nRF51822. It demonstrates how to use I2C to communicate with AT24C512 EEPROM device.

Dependencies:   mbed BLE_API nRF51822

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers wire.cpp Source File

wire.cpp

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