// Functions that directly control the hardware #include "CM_LIB.h" #include "CM_I2C.h" #include "CM_I2C_L.h" #include "hal_interface_api.h" #include // Delay void cm_Delay(uint8_t ucDelay) { uint32_t ucTimer; uint8_t a,b = 0; while(ucDelay) { ucTimer = 2000; while(ucTimer) { ucTimer--; a = b; } ucDelay--; } } // 1/2 Clock Cycle transition to HIGH // void cm_Clockhigh(void) { cm_Delay(1); CM_CLK_HI; cm_Delay(1); } // 1/2 Clock Cycle transition to LOW // void cm_Clocklow(void) { cm_Delay(1); CM_CLK_LO; cm_Delay(1); } // Do one full clock cycle // // Changed 1/19/05 to eliminate one level of return stack requirements // void cm_ClockCycle(void) { cm_Clocklow(); cm_Clockhigh(); } // Do a number of clock cycles // void cm_ClockCycles(uint8_t ucCount) { uint8_t i; for (i = 0; i < ucCount; ++i) cm_ClockCycle(); } // Send a start sequence // // Modified 7-21-04 to correctly set SDA to be an output // void cm_Start(void) { cm_Delay(50);//by jgw for delay to avoid i2c dead because of too fast CM_DATA_OUT; // Data line must be an output to send a start sequence //cm_Clocklow(); CM_DATA_HI; cm_Delay(4); cm_Clockhigh(); cm_Delay(4); CM_DATA_LO; cm_Delay(8); cm_Clocklow(); cm_Delay(8); } // Send a stop sequence // // Modified 7-21-04 to correctly set SDA to be an output // void cm_Stop(void) { cm_Delay(10);//by jgw for delay to avoid i2c dead because of too fast CM_DATA_OUT; // Data line must be an output to send a stop sequence cm_Clocklow(); CM_DATA_LO; cm_Delay(4); cm_Clockhigh(); cm_Delay(8); CM_DATA_HI; cm_Delay(4); } // Write a byte // // Returns 0 if write successed, 1 if write fails failure // // Modified 7-21-04 to correctly control SDA // uint8_t cm_Write(uint8_t ucData) { uint8_t i; cm_Delay(10);//by jgw for delay to avoid i2c dead because of too fast CM_DATA_OUT; // Set data line to be an output for(i=0; i<8; i++) { // Send 8 bits of data cm_Clocklow(); if (ucData&0x80) CM_DATA_HI; else CM_DATA_LO; cm_Clockhigh(); ucData = ucData<<1; } cm_Clocklow(); // wait for the ack CM_DATA_IN; // Set data line to be an input cm_Delay(8); cm_Clockhigh(); while(i>1) { // loop waiting for ack (loop above left i == 8) cm_Delay(2); if (CM_DATA_RD) i--; // if SDA is high level decrement retry counter else i = 0; } cm_Clocklow(); CM_DATA_OUT; // Set data line to be an output return i; } // Send a ACK or NAK or to the device void cm_AckNak(uint8_t ucAck) { cm_Delay(10);//by jgw for delay to avoid i2c dead because of too fast CM_DATA_OUT; // Data line must be an output to send an ACK cm_Clocklow(); if (ucAck) CM_DATA_LO; // Low on data line indicates an ACK else CM_DATA_HI; // High on data line indicates an NACK cm_Delay(2); cm_Clockhigh(); cm_Delay(8); cm_Clocklow(); } // Read a byte from device, MSB // // Modified 7-21-04 to correctly control SDA // uint8_t cm_Read(void) { uint8_t i; uint8_t rByte = 0; CM_DATA_IN; // Set data line to be an input CM_DATA_HI; for(i=0x80; i; i=i>>1) { cm_ClockCycle(); if (CM_DATA_RD) rByte |= i; cm_Clocklow(); } CM_DATA_OUT; // Set data line to be an output return rByte; } void cm_WaitClock(uint8_t loop) { uint8_t i, j; CM_DATA_LO; for(j=0; j