ITG3200::ITG3200(uint8_t range) { readI2C(GYRADDR, 0x00, 1, gBuffer); // Who am I? #ifdef DEBUG Serial.print("ITG-3200 ID = "); Serial.println((int) gBuffer[0]); #endif // Configure ITG-3200 // Refer to DS Section 8: Register Description. sendI2C(GYRADDR, 0x15, 0x18); // 00011000 -- Sample rate divider is 24(+1), so 40 Hz // Set Range readI2C(GYRADDR, 0x16, 1, gBuffer); gBuffer[1] = range; gBuffer[1] = (gBuffer[1] << 3); // See DS. gBuffer[0] |= gBuffer[1]; sendI2C(GYRADDR, 0x16, gBuffer[0]); #ifdef DEBUG Serial.println("ITG-3200 configured!"); #endif // Zero buffer. for (int i=0; i<READ_SIZE; i++) { gBuffer[i] = 0; } }
int main() { i2cBus = open("/dev/i2c-1", O_RDWR); if (i2cBus <= 0) { printf("Error opening the i2c bus\n"); return -1; } selectI2CDevice(ACCEL_BUS_ADDRESS); // writeI2C(CTRL_REG5_XM, 0xf0); // writeI2C(CTRL_REG6_XM, 0x60); // writeI2C(CTRL_REG7_XM, 0); writeI2C(0x2D, 0x08); // enable accel while(1) { short block[3]; readI2C(ACCEL_X, 2, (unsigned char*)&block[0]); readI2C(ACCEL_Y, 2, (unsigned char*)&block[1]); readI2C(ACCEL_Z, 2, (unsigned char*)&block[2]); printf("gyro reads: %d,%d,%d\n", (int)block[0], (int)block[1], (int)block[2]); } return 0; }
int EM2874Device::getDeviceID() { uint8_t buf[2], tuner_reg; // ROMで判断 writeReg(EM28XX_REG_I2C_CLK, 0x42); buf[0] = 0; buf[1] = 0x6a; writeI2C(EEPROM_ADDR, 2, buf, false); if(!readI2C (EEPROM_ADDR, 2, buf, true)) return -1; if(buf[0] == 0x3b && buf[1] == 0x00) return 2; // Tuner Regで判断 writeReg(EM28XX_REG_I2C_CLK, 0x44); buf[0] = 0xfe; buf[1] = 0; writeI2C(DEMOD_ADDR, 2, buf, true); tuner_reg = 0x0; writeI2C(TUNER_ADDR, 1, &tuner_reg, false); readI2C (TUNER_ADDR, 1, &tuner_reg, true); buf[0] = 0xfe; buf[1] = 1; writeI2C(DEMOD_ADDR, 2, buf, true); if(tuner_reg == 0x84) // TDA18271HD return 1; return 2; }
int read2I2C(unsigned char addr) { unsigned char val_high, val_low; startI2C(addr, I2C_READ); val_high = readI2C(1); val_low = readI2C(0); stopI2C(); return ((unsigned int)val_high << 8L) | val_low; }
ITG3200::ITG3200() { spn("Init ITG-3200 starting..."); readI2C(GYRADDR, 0x00, 1, buffer); // Who am I? sp("ITG-3200 ID = "); spln((int) buffer[0]); readI2C(GYRADDR, 0x15, 2, buffer); // Sample rate divider is 1 + 1 = 2, so 1000 Hz / 2 = 500 Hz buffer[0] = 1; // Set FS_SEL = 3 as recommended on DS p. 24. // Set DLPF_CFG = 3. This signifies a 1 kHz internal sample rate with a 42 // Hz LPF bandwidth, which should be low enough to filter out the motor // vibrations. buffer[1] = (3 << 3) | 3; // FS_SEL is on bits 4 and 3. writeI2C(GYRADDR, 0x15, 2, buffer); // Set to use X gyro as clock reference as recommended on DS p. 27. buffer[0] = 1; writeI2C(GYRADDR, 0x3e, 1, buffer); spln("ITG-3200 configured!"); // Zero buffer. for (int i=0; i<6; i++) { buffer[i] = 0; } // Low-pass filter. #ifdef GYRO_LPF_DEPTH lpfIndex = 0; for (int i=0; i<3; i++) for (int j=0; j<GYRO_LPF_DEPTH; j++) lpfVal[i][j] = 0; #endif // GYRO_LPF_DEPTH for (int i=0; i<3; i++) { gZero[i] = 0; gVec[i] = 0; angle[i] = 0; } calibrated = false; }
int read1I2C(unsigned char addr) { unsigned char val; startI2C(addr, I2C_READ); val = readI2C(0); return val; }
IOReturn IOI2CDriveBayGPIO::readModifyWriteI2C( UInt8 subAddr, UInt8 value, UInt8 mask) { IOReturn status; UInt32 clientKey; UInt8 data; if (kIOReturnSuccess == (status = lockI2CBus(&clientKey))) { if (kIOReturnSuccess != (status = readI2C(subAddr, &data, 1, clientKey))) { DLOG("IOI2CDriveBayGPIO@%lx::rmw read S:0x%x error: 0x%08x\n", getI2CAddress(), subAddr, status); } else { // Apply mask and value data = ((data & ~mask) | (value & mask)); if (kIOReturnSuccess != (status = writeI2C(subAddr, &data, 1, clientKey))) { DLOG("IOI2CDriveBayGPIO@%lx::rmw write S:0x%x error: 0x%08x\n", getI2CAddress(), subAddr, status); } } unlockI2CBus(clientKey); } return status; }
// AppleLM87::getReading IOReturn AppleLM8x::getReading(UInt32 subAddress, SInt32 *value) { IOReturn status; UInt8 data; if (systemIsRestarting == TRUE) return kIOReturnOffline; status = openI2C(kLM8xBus); if(status != kIOReturnSuccess) { DLOG("AppleLM8x::getReading(0x%x) failed to open I2C bus.\n", kLM8xAddr<<1); return status; } status = readI2C((UInt8)subAddress, (UInt8 *) &data, 1); if(status != kIOReturnSuccess) { DLOG("AppleLM8x::getReading(0x%x) readI2C failed.\n", kLM8xAddr<<1); closeI2C(); return status; } closeI2C(); *value = (SInt32)data; return kIOReturnSuccess; }
void setActiveMMA8451Q (unsigned int state) { unsigned char ctl1[] = {0x2A, 0x00}; writeI2C(0x1c, ctl1, 1, 0); //0x2E 0100 0000 40 readI2C(0x1c, &(ctl1[1]) , 1, 1); if(state) ctl1[1] |= 0x01; else ctl1[1] &= 0xFE; writeI2C(0x1c,ctl1, 2, 1); }
void setOutputBit(unsigned char state){ unsigned char temp; readI2C(SlaveAddress,CTRL_REG1,&temp,1); if(state) temp &= ~CTRL_REG1_FREAD; else temp |= CTRL_REG1_FREAD; writeI2C(SlaveAddress,CTRL_REG1,&temp,1); }
void executeMMA8451Q(unsigned char* buffer, unsigned int length) { enableI2C(12); setPwrBusStatus(PM_SYSPWR, PM_ENABLE); initMMA8451Q(); attachInterrupt(mma8451qVector, 1,6, 1); setActiveMMA8451Q(1); LPM3; detachInterrupt(1,6); unsigned char statreg[2] = {0x00, 0x01}; writeI2C(0x1c, statreg, 1, 0); readI2C(0x1c, statreg , 1, 1); writeI2C(0x1c, statreg+1, 1, 0); readI2C(0x1c, buffer , 96, 1); setActiveMMA8451Q(0); disableI2C(); setPwrBusStatus(PM_SYSPWR, PM_DISABLE); return; }
Vector getOrientation() { if (i2cBus > 0) { short block[3]; readI2C(ACCEL_X, 2, (unsigned char*)&block[0]); readI2C(ACCEL_Y, 2, (unsigned char*)&block[1]); readI2C(ACCEL_Z, 2, (unsigned char*)&block[2]); float smoothingFactor = 10; static Vector vDown(0,0,0); vDown.x = ((vDown.x*smoothingFactor) + (float)block[0]/255.0f) / (smoothingFactor+1); vDown.y = ((vDown.y*smoothingFactor) + (float)block[1]/255.0f) / (smoothingFactor+1); vDown.z = ((vDown.z*smoothingFactor) + (float)block[2]/255.0f) / (smoothingFactor+1); return vDown; } return Vector(0,1,0); }
void ITG3200::poll() { readI2C(GYRADDR, 0x1d, 6, buffer); // Shift high byte to be high 8 bits and append with low byte. gRaw[0] = -((buffer[2] << 8) | buffer[3]); // Tricopter X axis is chip Y axis. gRaw[1] = -((buffer[0] << 8) | buffer[1]); // Tricopter Y axis is chip X axis. gRaw[2] = -((buffer[4] << 8) | buffer[5]); // Z axis is same. if (calibrated) { // Apply calibration values. for (int i=0; i<3; i++) { gRaw[i] -= gZero[i]; } // Low-pass filter. #ifdef GYRO_LPF_DEPTH for (int i=0; i<3; i++) { lpfVal[i][lpfIndex] = gRaw[i] / GYRO_LPF_DEPTH; gRaw[i] = 0; for (int j=0; j<GYRO_LPF_DEPTH; j++) { gRaw[i] += lpfVal[i][(lpfIndex + j) % GYRO_LPF_DEPTH]; } } lpfIndex = (lpfIndex + 1) % GYRO_LPF_DEPTH; // Increment index by 1 and loop back from GYRO_LPF_DEPTH. #endif // GYRO_LPF_DEPTH } //sp("G( "); //for (int i=0; i<3; i++) { // sp(gRaw[i]); // sp(" "); //} //spln(")"); // Read gyro temperature (DS p. 7). //readI2C(GYRADDR, TEMP_OUT, 2, buffer); //temp = 35 + (((buffer[0] << 8) | buffer[1]) + 13200)/280.0; // Convert raw gyro output values to rad/s. // Output: [0x0000 -- 0x7fff] = [ 0 -- 32767] // [0x8000 -- 0xffff] = [-32768 -- -1] // Range: [-2000, 2000] deg/s // Scale factor: 14.375 LSB / (deg/s) for (int i=0; i<3; i++) { gVec[i] = (float) gRaw[i] / 14.375 * PI/180; } //sp("G( "); //for (int i=0; i<3; i++) { // sp(gVec[i]); // sp(" "); //} //spln(")"); }
IOReturn AppleLM8x::saveRegisters() { IOReturn status; DLOG("AppleLM8x::saveRegisters(0x%x) entered.\n", kLM8xAddr<<1); status = openI2C(kLM8xBus); if(status != kIOReturnSuccess) { DLOG("AppleLM8x::saveRegisters(0x%x) failed to open I2C bus.\n", kLM8xAddr<<1); return status; } status = readI2C((UInt8)kChannelModeRegister, (UInt8 *)&savedRegisters.ChannelMode, 1); if(status != kIOReturnSuccess) { DLOG("AppleLM8x::saveRegisters(0x%x) readI2C failed.\n", kLM8xAddr<<1); closeI2C(); return status; } status = readI2C((UInt8)kConfReg1, (UInt8 *)&savedRegisters.Configuration1, 1); if(status != kIOReturnSuccess) { DLOG("AppleLM8x::saveRegisters(0x%x) readI2C failed.\n", kLM8xAddr<<1); closeI2C(); return status; } status = readI2C((UInt8)kConfReg2, (UInt8 *)&savedRegisters.Configuration2, 1); if(status != kIOReturnSuccess) { DLOG("AppleLM8x::saveRegisters(0x%x) readI2C failed.\n", kLM8xAddr<<1); closeI2C(); return status; } closeI2C(); return status; }
IOReturn IOI2CLM6x::getRemoteTemperature ( SInt32* temperature ) { UInt8 rawDataMsb; UInt8 rawDataLsb; IOReturn status = kIOReturnSuccess; require_success( ( status = readI2C( kLM6xReg_RemoteTemperatureMSB, &rawDataMsb, 1 ) ), IOI2CLM6x_getRemoteTemperature_readI2CErr1 ); require_success( ( status = readI2C( kLM6xReg_RemoteTemperatureLSB, &rawDataLsb, 1 ) ), IOI2CLM6x_getRemoteTemperature_readI2CErr2 ); // Remote temperature data is represented by a 11-bit, two's complement word with // an LSB equal to 0.125C. The data format is a left justified 16-bit word available in // two 8-bit registers. *temperature = ( ( ( ( SInt8 ) rawDataMsb ) << 16 ) | ( rawDataLsb << 8 ) ); IOI2CLM6x_getRemoteTemperature_readI2CErr2: IOI2CLM6x_getRemoteTemperature_readI2CErr1: return( status ); }
uint16_t getGyroSample(uint16_t index, uint8_t *array){ startI2C(MPU9150ADDR, WRITE); writeI2C(0x43); stopI2C(); startI2C(MPU9150ADDR, READ); for(uint8_t k=0; k<6; k++){ if(index > 54-1) break; uint8_t ackType = (k < (6-1))? ACK : NACK ; array[index++] = readI2C(ackType); } stopI2C(); return index; }
//========================================= //功能:初始化MMA8451 //输入:无 //输出:无 //返回:无 //========================================= void Init_MMA8452(void) { unsigned char temp; //设置休眠 MMA845x_Standby(); /* 设置采样频率为100Hz */ MMA845x_Output_Data_Rates(Output_Data_Rates_400); setOutput_8Bit; readI2C(SlaveAddress,CTRL_REG4,&temp,1); temp |= CTRL_REG4_INT_EN_DRDY; writeI2C(SlaveAddress,CTRL_REG4,&temp,1); readI2C(SlaveAddress,CTRL_REG5,&temp,1); temp |= CTRL_REG5_INT_CFG_DRDY; writeI2C(SlaveAddress,CTRL_REG5,&temp,1); /* 将设备切换到主动模式 */ MMA845x_Active(); }
bool EepromDev::loadFromDevice(void) { bool ret_value = false; int fd; if (openDevice(fd)) { ret_value = readI2C(fd, 0, &data_, sizeof(data_)); ::close(fd); } if (!isValidData()) loadFromDefaults(); /* Update v1 to v2 */ if (data_.version == 1) { data_.features |= feature_eepromoops; data_.eepromoops_offset = 4096; data_.eepromoops_length = 61440; data_.eeprom_size = 65536; data_.page_size = 128; if (data_.features & feature_retina) { data_.lvds1.frequency = 148500000; data_.lvds1.hactive = 1920; data_.lvds1.vactive = 1080; data_.lvds1.hback_porch = 148; data_.lvds1.hfront_porch = 88; data_.lvds1.hsync_len = 44; data_.lvds1.vback_porch = 36; data_.lvds1.vfront_porch = 4; data_.lvds1.vsync_len = 5; data_.lvds1.flags = vsync_polarity | hsync_polarity | data_width_8bit | mapping_jeida | dual_channel | channel_present; data_.lvds2.flags = channel_present; } if (data_.features & feature_hdmi) { /* Pull HDMI settings from e.g. EDID */ data_.hdmi.flags = channel_present | ignore_settings | data_width_8bit; } data_.version = 2; } return ret_value; }
IOReturn IOI2CDriveBayGPIO::callPlatformFunction( const OSSymbol *functionName, bool waitForFunction, void *param1, void *param2, void *param3, void *param4) { const char *functionNameStr; UInt8 data; IOReturn status; if (functionName == 0) return kIOReturnBadArgument; functionNameStr = functionName->getCStringNoCopy(); if (0 == strcmp(functionNameStr, kSymGPIOParentWriteGPIO)) { return readModifyWriteI2C(k9554OutputPort, (UInt8)(UInt32)param2, (UInt8)(UInt32)param3); } else if (0 == strcmp(functionNameStr, kSymGPIOParentReadGPIO)) { if (kIOReturnSuccess == (status = readI2C(k9554InputPort, &data, 1))) *(UInt32 *)param2 = (UInt32)data; return status; } else // GPIO interrupt client API... if (0 == strcmp(functionNameStr, kSymGPIOParentRegister)) return registerGPIOClient((UInt32)param1, (GPIOEventHandler)param3, (IOService*)param4, true); else if (0 == strcmp(functionNameStr, kSymGPIOParentUnregister)) return registerGPIOClient((UInt32)param1, (GPIOEventHandler)0, (IOService*)0, false); else if (0 == strcmp(functionNameStr, kSymGPIOParentEvtEnable)) return enableGPIOClient((UInt32)param1, true); else if (0 == strcmp(functionNameStr, kSymGPIOParentEvtDisable)) return enableGPIOClient((UInt32)param1, false); else if (0 == strcmp(functionNameStr, kSymGPIOParentIntCapable)) { *((UInt32 *)param1) = 1; return kIOReturnSuccess; } return super::callPlatformFunction(functionName, waitForFunction, param1, param2, param3, param4); }
IOReturn IOI2CLM6x::getLocalTemperature ( SInt32* temperature ) { IOReturn status = kIOReturnSuccess; UInt8 rawData; require_success( ( status = readI2C( kLM6xReg_LocalTemperature, &rawData, 1 ) ), IOI2CLM6x_getLocalTemperature_readI2CErr ); // Local temperature data is represented by a 8-bit, two's complement word with // an LSB equal to 1.0C. We need to shift it into a 16.16 format. *temperature = ( ( ( SInt8 ) rawData ) << 16 ); IOI2CLM6x_getLocalTemperature_readI2CErr: return( status ); }
void ITG3200::Poll() { readI2C(GYRADDR, REGADDR, READ_SIZE, gBuffer); gRaw[0] = ((gBuffer[0] << 8) | gBuffer[1]); // Shift high byte to be high 8 bits and append with low byte. gRaw[1] = ((gBuffer[2] << 8) | gBuffer[3]); gRaw[2] = ((gBuffer[4] << 8) | gBuffer[5]); for (int i=0; i<3; i++) { // Convert raw values to a nice -1 to 1 range. float tmp; if (gRaw[i] >= 0x8000) // If zero to negative rot. vel.: 2^16-1 to 2^15... tmp = -((signed) (0xFFFF - gRaw[i])); // ...subtract from 2^16-1. gVal[i] = tmp/0x8000; // Divide by maximum magnitude. } #ifdef DEBUG Serial.print("GX: "); Serial.print(gVal[0]); Serial.print(" GY: "); Serial.print(gVal[1]); Serial.print(" GZ: "); Serial.println(gVal[2]); #endif }
void BMA180::poll() { // Read data. readI2C(ACCADDR, 0x02, 6, buffer); // Store 14 bits of data (thus the division by 4 at the end). aRaw[0] = ((buffer[3] << 8) | (buffer[2] & ~0x03)) / 4; // Tricopter X axis is chip Y axis. aRaw[1] = ((buffer[1] << 8) | (buffer[0] & ~0x03)) / 4; // Tricopter Y axis is chip X axis. aRaw[2] = ((buffer[5] << 8) | (buffer[4] & ~0x03)) / 4; // Z axis is same. // Low-pass filter. #ifdef ACC_LPF_DEPTH for (int i=0; i<3; i++) { lpfVal[i][lpfIndex] = aRaw[i] / ACC_LPF_DEPTH; aRaw[i] = 0; for (int j=0; j<ACC_LPF_DEPTH; j++) { aRaw[i] += lpfVal[i][(lpfIndex + j) % ACC_LPF_DEPTH]; } } lpfIndex = (lpfIndex + 1) % ACC_LPF_DEPTH; // Increment index by 1 and loop back from ACC_LPF_DEPTH. #endif // ACC_LPF_DEPTH // Read accelerometer temperature. //readI2C(ACCADDR, 0x08, 1, buffer); //temp = -40 + 0.5 * buffer[0]; // 0.5 K/LSB // Convert raw values to multiples of gravitational acceleration. // Output: [0x1fff -- 0x0000] = [-8191 -- 0] // [0x3fff -- 0x2000] = [ 1 -- 8192] // ADC resolution varies depending on setup. See DS p. 27 or the // constructor of this class. for (int i=0; i<3; i++) { aVec[i] = (float) (aRaw[i] / res); } // TODO: Decide if this is worth the extra computational cost and define // offsets and gains in globals.h. aVec[0] = (aVec[0] + 0.0345) / 1.0365; aVec[1] = (aVec[1] - 0.0100) / 1.0300; aVec[2] = (aVec[2] + 0.0185) / 1.0285; }
//========================================= //功能:连续读出MMA8452内部加速度数据,地址范围0x01~0x06 //输入:无 //输出:无 //返回:无 //========================================= void Multiple_Read_MMA8452(void) { /*uchar i; while(I2C_SR3_BUSY); //检测总线是否空闲 I2C_CR2_START = 1; //产生起始信号 while(!I2C_SR1_SB); //查询起始位是否已发送 I2C_DR = SlaveAddress; //发送写地址,写DR将清除I2C_SR1_SB待验证 while(!I2C_SR1_ADDR); //查询地址是否发送 i = I2C_SR1; i = I2C_SR3; //清除I2C_SR1_ADDR I2C_DR = 0x01; //写数据 while(!(I2C_SR1&0x84)); I2C_CR2_START = 1; //产生起始信号 while(!I2C_SR1_SB); I2C_DR = SlaveAddress+1; //发送写地址,写DR将清除I2C_SR1_SB待验证 while(!I2C_SR1_ADDR); //查询地址是否发送 i = I2C_SR1; i = I2C_SR3; //清除I2C_SR1_ADDR for (i=0; i<6; i++) //连续读取6个地址数据,存储中BUF { if (i == 5){ //设置关闭应答 I2C_CR2_ACK = 0; I2C_CR2_STOP = 1; } while(!(I2C_SR1&0x40)); BUF[i] =I2C_DR; } I2C_CR2_ACK = 1; //开启应答*/ readI2C(SlaveAddress,0x01,BUF,6); }
//______________________________________________________________________________________ int readI2C(_i2c *p, char* dBuffer, int length) { static int nrpt=3; int to=__time__+25; if(p) { p->nrx=length; if(dBuffer[1]) writeI2C(p,dBuffer,2); else writeI2C(p,dBuffer,1); while(p->nrx && __time__< to) _proc_loop(); if(p->nrx) { Reset_I2C(p); if(--nrpt) return readI2C(p, dBuffer, length); } nrpt=3; memcpy(dBuffer,p->rxbuf,length); if(p->nrx) { return(0); } } else while(length--) dBuffer[length]=0; _CLEAR_ERROR(pfm,PFM_I2C_ERR); if(_DBG(pfm,_DBG_I2C_RX)) { _io *io=_stdio(__dbug); int i; __print(":%04d",__time__ % 10000); for(i=0;i<length;++i) __print(" %02X",p->rxbuf[i]); __print("\r\n>"); _stdio(io); } return(-1); }
IOReturn IOI2CMaxim1631::getTemp( UInt32 maximReg /* unused */, SInt32 * temp ) { IOReturn status; union { UInt16 aShort; UInt8 aByte[2]; } readBuffer; // get the temperature. // this is done by issuing a COMBINED (default for readI2C) I2C request, with // 'kReadCurrentTemp' as the "sub-addr' and reading 2 bytes, since the current // temp register is 16 bits. if (kIOReturnSuccess == (status = readI2C( kReadCurrentTemp, &readBuffer.aByte[0], 2 ))) { // temperature register format: // // MS byte: 1/sign, 7 integer // LS byte: 4/fraction, 4/zero // format the 16.16 fixed point temperature and return it // ( the 0xFFFFF000 allows for the propagation of the sign bit, // which could happen in the case of a very cold room inlet temperature ) *temp = ( ( ( ( SInt16 ) readBuffer.aShort ) << 8 ) & 0xFFFFF000 ); //DLog( "IOI2CMaxim1631::getTemp - raw data = 0x%04X, returning %08lX\n", // i2cBuffer.aShort, *temp ); } else { IOLog( "IOI2CMaxim1631::getTemp - unable to read temperature (status = 0x%08X)\n", status ); *temp = 0x7FFFFFFF; // pass back very large positive number - will probably set off warning` } return status; }
IOReturn IOI2CDevice::readI2C( UInt32 subAddress, UInt8 *data, UInt32 count, UInt32 clientKey, UInt32 mode, UInt32 retries, UInt32 timeout_uS, UInt32 options) { IOI2CCommand cmd = {0}; cmd.command = kI2CCommand_Read; cmd.mode = mode; cmd.subAddress = subAddress; cmd.count = count; cmd.buffer = data; cmd.retries = retries; cmd.timeout_uS = timeout_uS; cmd.options = options; return readI2C(&cmd, clientKey); }
IOReturn AppleLM8x::initHW(IOService *provider) { IOReturn status; UInt8 cfgReg = 0; UInt8 attempts = 0; DLOG("AppleLM8x::initHW(0x%x) entered.\n", kLM8xAddr<<1); status = openI2C(kLM8xBus); if(status != kIOReturnSuccess) { DLOG("AppleLM8x::initHW(0x%x) failed to open I2C bus.\n", kLM8xAddr<<1); return status; } // Attempt to start LM87 by setting bit 0 in Configuration Register 1. If we detect the RESET // bit, then make a second attempt. for ( ; attempts < 2; attempts++ ) { // Read Configuration Register 1 status = readI2C((UInt8)kConfReg1, (UInt8 *) &cfgReg, 1); if(status != kIOReturnSuccess) { DLOG("AppleLM8x::initHW(0x%x) readI2C failed.\n", kLM8xAddr<<1); break; } DLOG("AppleLM8x::readI2C(0x%x) retrieved data = 0x%x\n", kLM8xAddr<<1, cfgReg); // If we detect RESET, wait at least 45ms for it to clear. if ( cfgReg & kConfRegRESET ) { IOSleep(50); status = kIOReturnError; } if(status != kIOReturnSuccess) { IOLog("AppleLM8x::initHW(0x%x) readI2C detected RESET bit.\n", kLM8xAddr<<1); } // Start monitoring operations cfgReg = 0x1; // Failure of this write operation is fatal status = writeI2C((UInt8)kConfReg1, (UInt8 *)&cfgReg, 1); // Read Configuration Register 1 status = readI2C((UInt8)kConfReg1, (UInt8 *) &cfgReg, 1); if(status != kIOReturnSuccess) { DLOG("AppleLM8x::initHW(0x%x) readI2C failed.\n", kLM8xAddr<<1); break; } if ( cfgReg == kConfRegStart ) { break; } else { IOLog("AppleLM8x::readI2C(0x%x) retrieved configuration register 1 = 0x%x\n", kLM8xAddr<<1, cfgReg); } } closeI2C(); return status; }
bool IOI2CDriveBayGPIO::start(IOService *provider) { IOReturn status; OSData *data; mach_timespec_t timeout; DLOG("IOI2CDriveBayGPIO::start\n"); // Get our "reg" property.. I2C address. if (0 == (data = OSDynamicCast(OSData, provider->getProperty("reg")))) { DLOG("IOI2CDriveBayGPIO::start -- no reg property\n"); return false; } fReg = *((UInt32 *)data->getBytesNoCopy()); // Find the PCA9554M node. It provides our interrupt source... timeout.tv_sec = 30; timeout.tv_nsec = 0; if (0 == (fPCA9554M = waitForService(serviceMatching("IOI2CDriveBayMGPIO"), &timeout))) { DLOG("IOI2CDriveBayGPIO::start -- timeout waiting for IOI2CDriveBayMGPIO\n"); return false; } fConfigReg = 0xFF; // default to all input pins fPolarityReg = 0x00; // no polarity inversion // find out how to program the config register if (data = OSDynamicCast(OSData, provider->getProperty("config-reg"))) fConfigReg = (UInt8)*((UInt32 *)data->getBytesNoCopy()); // find out how to program the polarity register if (data = OSDynamicCast(OSData, provider->getProperty("polarity-reg"))) fPolarityReg = (UInt8)*((UInt32 *)data->getBytesNoCopy()); DLOG("IOI2CDriveBayGPIO(%x)::start fConfigReg = %02x fPolarityReg = %02x\n", (int)fReg, fConfigReg, fPolarityReg); // allocate my lock fClientLock = IOLockAlloc(); // Register with the combined PCA9554M DLOG("IOI2CDriveBayGPIO(%x)::start - register9554MInterruptClient\n", (int)fReg); if (kIOReturnSuccess != (status = fPCA9554M->callPlatformFunction("register9554MInterruptClient", false, (void *)fReg, (void *)&sProcess9554MInterrupt, (void *)this, (void *)true))) { DLOG("IOI2CDriveBayGPIO(%x)::start failed to register (%x)\n", (int)fReg, (int)status); return false; } // Start IOI2C services... if (false == super::start(provider)) { DLOG("IOI2CDriveBayGPIO(%x)::start -- super::start returned error\n", (int)fReg); return false; } super::callPlatformFunction("IOI2CSetDebugFlags", false, (void *)kStateFlags_kprintf, (void *)true, (void *)NULL, (void *)NULL); if (kIOReturnSuccess != readI2C(k9554OutputPort, &fOutputReg, 1)) { DLOG("IOI2CDriveBayGPIO(%x)::start -- super::start returned error\n", (int)fReg); freeI2CResources(); return false; } // start matching on children publishChildren(provider); registerService(); DLOG("IOI2CDriveBayGPIO@%lx::start succeeded\n", getI2CAddress()); return true; }
bool IOI2CMaxim1631::start( IOService *nub ) { IOReturn status; UInt8 configReg, cmdByte; DLOG("IOI2CMaxim1631::start - entered\n"); if (false == super::start(nub)) { DLOG( "IOI2CMaxim1631::start - super::start failed. Exiting...\n" ); return false; } if (!fGetSensorValueSym) fGetSensorValueSym = OSSymbol::withCString("getSensorValue"); // According to the I2C gurus, accessing the config register is done by a COMBINED mode // (default for readI2C) I2C access with the 'kAccessConfigurationByte' command as the // "sub-addr" value. if (kIOReturnSuccess != (status = readI2C( kAccessConfigurationByte, &configReg, 1 ))) { IOLog("IOI2CMaxim1631@%lx::start unable to read config reg\n", getI2CAddress()); freeI2CResources(); return false; } DLOG( "IOI2CMaxim1631::start - read config register- value = 0x%02X\n", configReg ); if ( (configReg & 0x01) != 0 ) // not in continuous conversion mode (bit 0 == 1 is 1SHOT mode) { IOLog( "IOI2CMaxim1631::start - Note: not in continuous conversion mode. Setting mode.\n" ); // should we also be setting the resolution bits here? -- bg configReg &= ~0x01; // set 1SHOT bit to zero for continuous conversion mode // to write to the config register, you perform a Standard SubAddr I2C transaction // (which is the default mode for writeI2C()), specifying 'kAccessConfigurationByte' // command as the sub-addr. if ( kIOReturnSuccess != ( status = writeI2C( kAccessConfigurationByte, &configReg, 1 )) ) { IOLog( "IOI2CMaxim1631::start - unable to turn off 1SHOT mode! Cannot provide temperature values.\n" ); freeI2CResources(); return false; } } // Tell the sensor to go into continuous temp. conversion mode. // Talked to the I2C gurus and according to the diagram for the interface diagram // for issuing the 'kStartConvertT' command, one needs to issue a Standard I2C write // transaction. The data buffer contains one (1) byte, which is the command byte, // and we override the default "mode" so that IOI2CFamily issues the correct type // of transaction. [rdar://problem/4118773] cmdByte = kStartConvertT; if ( kIOReturnSuccess != ( status = writeI2C( 0 /* no subaddr */, &cmdByte, 1, kIOI2C_CLIENT_KEY_DEFAULT, kI2CMode_Standard ) ) ) { IOLog( "IOI2CMaxim1631::start - unable to start sensor (status = 0x%08X)\n", status ); } // tell the world i'm here registerService(); // Publish any child nubs under the max1631 node... publishChildren(nub); return(true); }
BMA180::BMA180() { readI2C(ACCADDR, 0x00, 1, buffer); sp("BMA180 ID = "); spln((int) buffer[0]); // Set ee_w bit readI2C(ACCADDR, CTRLREG0, 1, buffer); buffer[0] |= 0x10; // Bitwise OR operator to set ee_w bit. writeI2C(ACCADDR, CTRLREG0, 1, buffer); // Have to set ee_w to write any other registers. // Set range. readI2C(ACCADDR, OLSB1, 1, buffer); buffer[0] &= (~0x0e); // Clear old ACC_RANGE bits. buffer[0] |= (ACC_RANGE << 1); // Need to shift left one bit; refer to DS p. 21. writeI2C(ACCADDR, OLSB1, 1, buffer); // Write new ACC_RANGE data, keep other bits the same. // Set ADC resolution (DS p. 8). res = 8000; // == 1/0.000125 // [ -1, 1] g if (ACC_RANGE == 1) res /= 1.5; // [ -1.5, 1.5] g else if (ACC_RANGE == 2) res /= 2; // [ -2, 2] g else if (ACC_RANGE == 3) res /= 3; // [ -3, 3] g else if (ACC_RANGE == 4) res /= 4; // [ -4, 4] g else if (ACC_RANGE == 5) res /= 8; // [ -8, 8] g else if (ACC_RANGE == 6) res /= 16; // [ -16, 16] g // Set bandwidth. // ACC_BW bandwidth (Hz) // 0 10 // 1 20 // 2 40 // 3 75 // 4 150 // 5 300 // 6 600 // 7 1200 readI2C(ACCADDR, BWTCS, 1, buffer); buffer[0] &= (~0xf0); // Clear bandwidth bits <7:4>. buffer[0] |= (ACC_BW << 4); // Need to shift left four bits; refer to DS p. 21. writeI2C(ACCADDR, BWTCS, 1, buffer); // Keep tcs<3:0> in BWTCS, but write new ACC_BW. // Set mode_config to 0x01 (ultra low noise mode, DS p. 28). //readI2C(ACCADDR, 0x30, 1, buffer); //buffer[0] &= (~0x03); // Clear mode_config bits <1:0>. //buffer[0] |= 0x01; //writeI2C(ACCADDR, 0x30, 1, buffer); spln("BMA180 configured!"); for (int i=0; i<3; i++) { aRaw[i] = 0; aVec[i] = 0; } // Zero buffer. for (int i=0; i<6; i++) { buffer[i] = 0; } // Low-pass filter. #ifdef ACC_LPF_DEPTH lpfIndex = 0; for (int i=0; i<3; i++) for (int j=0; j<ACC_LPF_DEPTH; j++) lpfVal[i][j] = 0; #endif // ACC_LPF_DEPTH }