1 // *******************************************************************
    2 //   I2C Master Library for Custom DPA Handlers                      *
    3 // *******************************************************************
    4 // Copyright (c) IQRF Tech s.r.o.
    5 //
    6 // File:    $RCSfile: I2Cmaster.c,v $
    7 // Version: $Revision: 1.5 $
    8 // Date:    $Date: 2020/04/02 09:53:06 $
    9 //
   10 // Revision history:
   11 //   2020/01/02  Release for DPA 4.11
   12 //
   13 // *********************************************************************
   14 
   15 #ifndef __I2C_MASTER__
   16 #define __I2C_MASTER__
   17 
   18 //############################################################################################
   19 
   20 // Default I2C speed value. Redefine at your code if needed.
   21 // #define I2Cfrequency      100000
   22 
   23 // Define to keep value read by i2c_readXYZ in the global variable i2cReadData
   24 // i2cReadData_GLOBAL
   25 
   26 // I2C routines. Note: routines do not modify FSR1
   27 void i2c_init();
   28 void i2c_shutdown();
   29 void i2c_waitForIdle();
   30 void i2c_start( uns8 address );
   31 void i2c_startAndWrite( uns8 i2cWriteData, uns8 address );
   32 void i2c_stop();
   33 uns8 i2c_read( bit ack );
   34 uns8 i2c_readACK();
   35 uns8 i2c_readNACK();
   36 uns8 i2c_readNACKandStop();
   37 void i2c_write( uns8 i2cWriteData );  // Note: also does not modify FSR0
   38 void i2c_writeAndStop( uns8 i2cWriteData );
   39 
   40 #ifdef i2cReadData_GLOBAL
   41 uns8 i2cReadData;
   42 #endif
   43 
   44 //############################################################################################
   45 #else
   46 
   47 #pragma library 1               // Compile only used methods
   48 
   49 // I2C SCL frequency [Hz]
   50 #ifndef I2Cfrequency
   51 #define I2Cfrequency      100000
   52 #endif
   53 
   54 #ifndef i2c_start_ENTRY
   55 #define i2c_start_ENTRY() do {} while (0)
   56 #endif
   57 
   58 #ifndef i2c_stop_EXIT
   59 #define i2c_stop_EXIT()   do {} while (0)
   60 #endif
   61 
   62 #ifndef USE_FSRx
   63 //############################################################################################
   64 void writeToSSPCON2( uns8 value )
   65 //############################################################################################
   66 {
   67   writeToRAM( &SSPCON2, value );
   68 }
   69 #else
   70 #define writeToSSPCON2( value ) SSPCON2 = (value)
   71 #endif
   72 
   73 #ifndef USE_FSRx
   74 //############################################################################################
   75 void writeOredToSSPCON2( uns8 value @ W )
   76 //############################################################################################
   77 {
   78   writeToSSPCON2( SSPCON2 | value );
   79 }
   80 #else
   81 #define writeOredToSSPCON2( value ) SSPCON2 |= (value)
   82 #endif
   83 
   84 //############################################################################################
   85 void i2c_init()
   86 //############################################################################################
   87 {
   88   // SCL as input
   89   TRISC.3 = 1;
   90   // SDA as input
   91   TRISC.4 = 1;
   92 
   93   // I2C: Synchronous Serial Port Enable, I2C Master mode
   94 #ifndef USE_FSRx
   95   writeToRAM( &SSPCON1, 0b0010.1000 );
   96 #else
   97   SSPCON1 = 0b0010.1000;
   98 #endif
   99   writeToSSPCON2( 0x00 );
  100 
  101   // I2C SCL frequency
  102   SSPADD = ( F_OSC / I2Cfrequency / 4 ) - 1;
  103   // Disable slew rate control
  104   SMP = 1;
  105 }
  106 
  107 //############################################################################################
  108 void i2c_shutdown()
  109 //############################################################################################
  110 {
  111   // I2C master mode     SSPCON = 0
  112 #ifndef USE_FSRx
  113   writeToRAM( &SSPCON1, 0x00 );
  114 #else
  115   SSPCON1 = 0x00;
  116 #endif
  117 }
  118 
  119 //############################################################################################
  120 #ifndef i2c_waitForIdle_REDEFINE
  121 void i2c_waitForIdle()
  122 //############################################################################################
  123 {
  124   // Wait for idle and not writing
  125   while ( ( SSPCON2 & 0b0001.1111 ) != 0 || RW_ );
  126 }
  127 #endif
  128 
  129 //############################################################################################
  130 void i2c_start( uns8 address )
  131 //############################################################################################
  132 {
  133   i2c_start_ENTRY();
  134 
  135   i2c_waitForIdle();
  136   // SEN = 1
  137   writeOredToSSPCON2( 0x01 );
  138   i2c_write( address );
  139 }
  140 
  141 //############################################################################################
  142 void i2c_startAndWrite( uns8 i2cWriteData, uns8 address @ W )
  143 //############################################################################################
  144 {
  145   i2c_start( address );
  146   i2c_write( i2cWriteData );
  147 }
  148 
  149 //############################################################################################
  150 void i2c_stop()
  151 //############################################################################################
  152 {
  153   i2c_waitForIdle();
  154   // PEN = 1
  155   writeOredToSSPCON2( 0x04 );
  156 
  157   i2c_stop_EXIT();
  158 }
  159 
  160 //############################################################################################
  161 uns8 i2c_read( bit ack )
  162 //############################################################################################
  163 {
  164   i2c_waitForIdle();
  165   // RCEN = 1
  166   writeOredToSSPCON2( 0x08 );
  167   i2c_waitForIdle();
  168 
  169 #ifndef i2cReadData_GLOBAL
  170   uns8  // Local, not global static variable
  171 #endif
  172     i2cReadData = SSPBUF;
  173 
  174   i2c_waitForIdle();
  175 
  176   // Acknowledge, ACKDT = 0
  177   writeToSSPCON2( SSPCON2 & ~0x20 );
  178   if ( !ack )
  179     // Not acknowledge, ACKDT = 1 
  180     writeOredToSSPCON2( 0x20 );
  181 
  182   // Send acknowledge sequence from ACKDT, ACKEN = 1 
  183   writeOredToSSPCON2( 0x10 );
  184   return i2cReadData;
  185 }
  186 
  187 //############################################################################################
  188 uns8 i2c_readACK()
  189 //############################################################################################
  190 {
  191   return i2c_read( TRUE );
  192 }
  193 
  194 //############################################################################################
  195 uns8 i2c_readNACK()
  196 //############################################################################################
  197 {
  198   return i2c_read( FALSE );
  199 }
  200 
  201 //############################################################################################
  202 uns8 i2c_readNACKandStop()
  203 //############################################################################################
  204 {
  205   uns8 data = i2c_readNACK();
  206   i2c_stop();
  207   return data;
  208 }
  209 
  210 //############################################################################################
  211 void i2c_write( uns8 i2cWriteData )
  212 //############################################################################################
  213 {
  214   i2c_waitForIdle();
  215   SSPBUF = i2cWriteData;
  216 }
  217 
  218 //############################################################################################
  219 void i2c_writeAndStop( uns8 i2cWriteData @ W )
  220 //############################################################################################
  221 {
  222   i2c_write( i2cWriteData );
  223   i2c_stop();
  224 }
  225 //############################################################################################
  226 
  227 #pragma library 0
  228 
  229 #endif
  230 //############################################################################################