EDF - OnePIC MCU  v1.1.0
source/base/OnePIC_i2c.c
Go to the documentation of this file.
00001 
00016 #include "Compiler.h"
00017 #include "bsp.h"
00018 #include "TimeDelay.h"
00019 #include "OnePIC_i2c.h"
00020 
00025 struct i2cBus bus1 = {
00026         I2C_IDLE,
00027         0,// no stopLock
00028         0,// offset 0
00029         (void *)0,
00030         &bus1.req
00031 };
00032         
00038 int i2cIdle(struct i2cBus *bus)
00039 {
00040         return bus->mstate == I2C_IDLE;
00041 }
00042 #if defined __PIC24F__
00043 #define __I2C1_ISR    __attribute__((interrupt, shadow, auto_psv)) 
00047 void __I2C1_ISR _MI2C1Interrupt(void)
00048 #elif defined __PICC__
00049 
00052 void ISR_i2c(void)
00053 #elif defined(__PIC32MX__)
00054 
00057 void ISR_i2c(void)
00058 #endif
00059 {
00060         struct trb *req = bus1.req;
00061 
00062         I2C_INTERRUPT_FLAG = 0;         // Clear Interrupt Flag
00063         if (req)
00064         {
00065             // Clear flag
00066                 if (I2C_BCL_MASTER_BUS_COLLISION)
00067                 {
00068                         bus1.mstate = I2C_STARTING;     // try again from scratch
00069                         bus1.bufOffset = 0;
00070                         I2C_BCL_MASTER_BUS_COLLISION = 0;
00071                         I2C_SEN_START_CONDITION_ENABLE = 1;
00072                 }
00073                 else
00074                 {
00075                 Nop();
00076                         switch (bus1.mstate)
00077                         {
00078                                 case I2C_IDLE:
00079                                         bus1.mstate = I2C_ERRORS;
00080                                         break;
00081                                 case I2C_STARTING:
00082                                         bus1.bufOffset = 0;
00083                                         if (req->txLen)
00084                                         {
00085                                                 bus1.mstate = I2C_XMITING;
00086                                                 I2C_TRANSMIT_REGISTER = (req->addr << 1);
00087                                         }
00088                                         else if (req->rxLen)
00089                                         {
00090                                                 bus1.mstate = I2C_RECEIVEADDR;
00091                                                 I2C_TRANSMIT_REGISTER = (req->addr << 1) | 1;
00092                                         }
00093                                         else
00094                                         {
00095                                                 bus1.mstate = I2C_ERRORS;
00096                                         }
00097                                         break;
00098                                 case I2C_RESTARTING:
00099                                         bus1.mstate = I2C_RECEIVEADDR;
00100                                         I2C_TRANSMIT_REGISTER = (req->addr << 1) | 1;
00101                                         break;
00102                                 case I2C_XMITING:
00103                                         req->status =  I2C_ACK_STATUS;
00104                                         if (bus1.bufOffset < req->txLen)
00105                                         {
00106                                                 I2C_TRANSMIT_REGISTER = (req->txBuf[bus1.bufOffset++]);
00107                                         }
00108                                         else if (req->rxLen)
00109                                         {
00110                                                 bus1.mstate = I2C_RESTARTING;
00111                                                 I2C_REPEATED_START_ENABLE = 1;
00112                                         }
00113                                         else
00114                                         {
00115                                                 bus1.mstate = I2C_STOPPING;
00116                                                 Delay10us(5);           // WARNING! : Delay in interrupt handler
00117                                                 I2C_STOP_CONDITION_ENABLE = 1;
00118                                         }
00119                                         break;
00120                                 case I2C_RECEIVEADDR:
00121                                         req->status = I2C_ACK_STATUS;
00122                                         if (req->status)        // NACKed
00123                                         {
00124                                                 bus1.mstate = I2C_STOPPING;
00125                                                 I2C_STOP_CONDITION_ENABLE = 1;
00126                                         }
00127                                         else    // ACKed
00128                                         {
00129                                                 bus1.mstate = I2C_RECEIVING;
00130                                                 bus1.bufOffset = 0;
00131                                                 I2C_RECIEVE_ENABLE = 1;
00132                                         }
00133                                         break;
00134                                 case I2C_RECEIVING:
00135                                         bus1.mstate = I2C_ACKING;
00136                                         req->rxBuf[bus1.bufOffset++] = I2C_RECIEVE_REGISTER;
00137                                         I2C_ACK_DATA = (bus1.bufOffset < req->rxLen) ? 0 : 1;
00138                                     I2C_ACK_SEQ_ENABLE = 1;
00139                                         break;
00140                                 case I2C_ACKING:
00141                                         if (bus1.bufOffset < req->rxLen)
00142                                         {
00143                                                 bus1.mstate = I2C_RECEIVING;
00144                                                 I2C_RECIEVE_ENABLE = 1;
00145                                         }
00146                                         else
00147                                         {
00148                                                 bus1.mstate = I2C_STOPPING;
00149                                                 I2C_STOP_CONDITION_ENABLE = 1;
00150                                         }
00151                                         break;
00152                                 case I2C_STOPPING:
00153                                         if ((req->status & 1) && req->retries)
00154                                         {
00155                                                 --req->retries;
00156                                                 bus1.mstate     = I2C_STARTING;
00157                                                 I2C_SEN_START_CONDITION_ENABLE = 1;
00158                                         }
00159                                         else
00160                                         {
00161                                                 req->status |= 0x80;    // set done bit
00162                                                 if (bus1.stopLock)
00163                                                 {
00164                                                         bus1.mstate = I2C_STOP_IN_ENQ;
00165                                                 }
00166                                                 else if (req->next)
00167                                                 {
00168                                                         bus1.mstate     = I2C_STARTING;
00169                                                         bus1.req        = req->next;
00170                                                         I2C_SEN_START_CONDITION_ENABLE = 1;
00171                                                 }
00172                                                 else
00173                                                 {
00174                                                         bus1.mstate = I2C_IDLE;
00175                                                 }
00176                                         }
00177                                         break;
00178                                 default:
00179                                         break;
00180                 
00181                         }
00182                 }
00183         }
00184 
00185 }
00186 
00187 
00188 
00189 
00195 void trbEnQ(struct i2cBus *bus, struct trb *req)
00196 {
00197         req->status = 0;
00198         struct trb *reqTemp;
00199         if (bus->mstate == I2C_IDLE)
00200         {
00201                 bus->mstate     = I2C_STARTING;
00202                 bus->req        = req;
00203                 bus->tail       = &req->next;
00204                 I2C_SEN_START_CONDITION_ENABLE = 1;
00205         }
00206         else
00207         {
00208                 bus->stopLock   = 1;
00209                 *bus->tail = req;                       // add to queue
00210                 bus->tail = &req->next;         // advance the tail pointer
00211                 bus->stopLock = 0;
00212                 if (bus->mstate == I2C_STOP_IN_ENQ)     // pretend we're in handler
00213                 {
00214                     reqTemp = bus->req->next;
00215                     bus->mstate     = I2C_STARTING;
00216                     bus->req        = reqTemp;
00217 //                        bus->req = 2;
00218                     I2C_SEN_START_CONDITION_ENABLE = 1;
00219                 }
00220         }
00221 }
00225 void I2CInit (void)
00226 {
00227         I2C_INTERRUPT_FLAG = 0; // clear interrupt
00228         I2C_INTERRUPT_ENABLE = 1;       // enable I2C1 master interrupts
00229         //I2C master :: clock = Fosc / (4 * (SSPADD + 1))E
00230 #ifdef __PICC__
00231         I2C_MODULE_SETUP_MASTER_3 = 1;
00232         I2C_MODULE_SETUP_MASTER_2 = 0;
00233         I2C_MODULE_SETUP_MASTER_1 = 0;
00234         I2C_MODULE_SETUP_MASTER_0 = 0;
00235 #endif
00236 #ifdef __PIC32MX__
00237     INTConfigureSystem(INT_SYSTEM_CONFIG_MULT_VECTOR);
00238     INTEnableInterrupts();
00239     INTSetVectorPriority(INT_I2C_1_VECTOR, INT_PRIORITY_LEVEL_4);
00240     INTClearFlag(INT_I2C1);
00241     INTClearFlag(INT_I2C1B);
00242     INTClearFlag(INT_I2C1M);
00243     INTEnable(INT_I2C1, INT_ENABLED);
00244     INTEnable(INT_I2C1B, INT_ENABLED);
00245     INTEnable(INT_I2C1M, INT_ENABLED);
00246 #endif // __PIC32mx__
00247 
00248         I2C_BRG = 0x27;//GetPeripheralClock() / I2CFREQ - 2;
00249         I2C_MODULE_ENABLE = 1;  // enable I2C1
00250         I2C_DISABLE_SLEW_CONTROL = 1;
00251 }