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