/*Requires Delay after call*/ uint8 MagReadByte(uint8 registerAddress, uint8 *readPtr) { /* Pointer to the register address */ //uint8 *writePtr = ®isterAddress;/* changed writeptr to ®isterAddress*/ uint8 i2c_status = I2C_MasterClearStatus(); //LCD_ClearDisplay(); LCD_Position(1,7); LCD_PrintInt8(i2c_status); I2C_MasterClearReadBuf(); I2C_MasterClearWriteBuf(); /* Start the I2C transmission for a read */ uint8 status = I2C_MasterWriteBuf(SLAVE_ADDRESS, ®isterAddress, 1, I2C_MODE_NO_STOP); /*wait for the tranmission to finish */ while (I2C_MasterStatus() && !I2C_MSTAT_WR_CMPLT){} /* Needed because of some bug in the psoc I2C tramission */ CyDelay(1); /* read a byte using I2C */ //return I2C_MasterReadBuf(SLAVE_ADDRESS, readPtr, 1, I2C_MODE_REPEAT_START); //or TO ENSURE READ IS COMPLETE BEFORE ADDITIONAL CODE EXECUTED status |= I2C_MasterReadBuf(SLAVE_ADDRESS,readPtr , 1, I2C_MODE_REPEAT_START); while (I2C_MasterStatus() && !I2C_MSTAT_RD_CMPLT){} CyDelay(1); //Needed because of some bug in the psoc I2C tramission return status; }
void RunNunchuck(void){ uint8 clear[] = {0x00}; uint8 buffer[16]; unsigned short wiichuck[7]; Err_LED_1_Write(0); Err_LED_2_Write(0); JoystickInit(); I2C_Start(); InitNunchuck(); for(;;) { I2C_MasterClearStatus(); CyDelay(1); I2C_MasterWriteBuf(0x52, clear, 1, I2C_MODE_COMPLETE_XFER); CyDelay(1); I2C_MasterWriteBuf(0x52, clear, 1, I2C_MODE_COMPLETE_XFER); CyDelay(1); I2C_MasterWriteBuf(0x52, clear, 1, I2C_MODE_COMPLETE_XFER); CyDelay(1); if (0u != (I2C_MasterStatus() & I2C_MSTAT_ERR_XFER)){ InitNunchuck(); }else{ I2C_MasterClearStatus(); CyDelay(1); I2C_MasterReadBuf(0x52, buffer, 6, I2C_MODE_COMPLETE_XFER); // Nunchuck data is 6 bytes, but for whatever reason, MEMOREX Wireless Nunchuck wants to send 8... CyDelay(1); if (0u != (I2C_MasterStatus() & I2C_MSTAT_ERR_XFER)){ InitNunchuck(); }else{ wiichuck[0] = buffer[1];// X Axis Joystick wiichuck[1] = buffer[0];// Y Axis Joystick wiichuck[2] = (((unsigned short) buffer[2]) << 2) + (((unsigned short) buffer[5]) & (3<<2)); // X Axis Accel wiichuck[3] = (((unsigned short) buffer[3]) << 2) + (((unsigned short) buffer[5]) & (3<<4)); // Y Axis Accel wiichuck[4] = (((unsigned short) buffer[4]) << 2) + (((unsigned short) buffer[5]) & (3<<6)); // Z Axis Accel wiichuck[5] = buffer[5] & (1 << 1) ? 0 : 1; //'C' Button wiichuck[6] = buffer[5] & (1 << 0) ? 0 : 1; //'Z' Button if(wiichuck[5]) JoystickOut(128,128); else JoystickOut(wiichuck[0],wiichuck[1]); } } Err_LED_2_Write(~Err_LED_2_Read()); CyDelay(100); } }
void InitNunchuck(){ uint8 init1[2] = {0xF0, 0x55}; uint8 init2[2] = {0xFB, 0x00}; uint8 finish = 0; Err_LED_1_Write(1); JoystickOut(128,128); while(finish==0){ I2C_MasterClearStatus(); I2C_MasterWriteBuf(0x52, init1, 2, I2C_MODE_COMPLETE_XFER); CyDelay(1); if (0u == (I2C_MasterStatus() & I2C_MSTAT_ERR_XFER)){ I2C_MasterClearStatus(); I2C_MasterWriteBuf(0x52, init2, 2, I2C_MODE_COMPLETE_XFER); CyDelay(1); if (0u == (I2C_MasterStatus() & I2C_MSTAT_ERR_XFER)){ finish = 1; } } CyDelay(100); } Err_LED_1_Write(0); }
/** Blocking reading data. * @param obj The i2c object * @param address 7-bit address (last bit is 1) * @param data The buffer for receiving * @param length Number of bytes to read * @param stop Stop to be generated after the transfer is done * @return Number of read bytes */ int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) { if (!obj->initied) { CyGlobalIntEnable; I2C_Start(); obj->initied = 1; } int status = I2C_MasterReadBuf(address, (uint8_t*)data, length, stop ? I2C_MODE_COMPLETE_XFER : I2C_MODE_NO_STOP); if (status != I2C_MSTR_NO_ERROR) { debug("mbed I2C read failed with error: %i\r\n", status); return 0; } int timeout = 100, to = 0; while((I2C_MasterStatus() & (I2C_MSTAT_RD_CMPLT | I2C_MSTAT_ERR_XFER)) == 0 && to++ < timeout) { CyDelayUs(10); } if (I2C_MasterStatus() & I2C_MSTAT_ERR_XFER) { debug("i2c read failed with status: 0x%X\r\n!",I2C_MasterStatus()); return 0; } if (to == timeout) { debug("I2C read timeout!\r\n"); return 0; } return length; }
/** * @brief Read multiple bytes from the MAG3110 * @details User supplies the register that we are going to read from and the buffer that we are going to place the data * that we read from the MAG3110. REQUIRES DELAY AFTER CALL * * @param registerAddress Address of the first register we are going to read * @param readPtr Pointer to the buffer that the data that we read will be placed * @param size Number of bytes that we are going to read from the MAG3110 * @return Error status of the function */ uint8 MagReadMultipleByte(uint8 registerAddress, uint8 *readPtr,uint8 size) { uint8 i2c_status = I2C_MasterClearStatus(); LCD_Position(1,7); LCD_PrintInt8(i2c_status); I2C_MasterClearReadBuf(); I2C_MasterClearWriteBuf(); /* We start by writng the slave address and the register we are going to start the rea from*/ uint8 status = I2C_MasterWriteBuf(SLAVE_ADDRESS, ®isterAddress, 1, I2C_MODE_NO_STOP); /*wait for the tranmission to finish */ while (I2C_MasterStatus() && !I2C_MSTAT_RD_CMPLT){} /* Needed because of some bug in the psoc I2C tramission */ CyDelay(1); /* read data from the MAG I2C */ //return I2C_MasterReadBuf(SLAVE_ADDRESS,readPtr , size, I2C_MODE_REPEAT_START); //or TO ENSURE READ IS COMPLETE BEFORE ADDITIONAL CODE EXECUTED status |= I2C_MasterReadBuf(SLAVE_ADDRESS,readPtr , size, I2C_MODE_REPEAT_START); while (I2C_MasterStatus() && !I2C_MSTAT_RD_CMPLT){} CyDelay(1); //Needed because of some bug in the psoc I2C tramission return status; }
/** * @brief Write multiple bytes of data to the MAG3110 in sequential memory * @details User supplies the register that the write will start on. User also supplues a buffer of data to write * to the MAG3110 and the size of the buffer as well. * * @param firstRegister Register the sequential write will start on * @param bufferPtr Pointer that points to the buffer of data to write * @param size umber of elements that are in the buffer * @return Error status of the function */ uint8 MagWriteMultipleBytes(uint8 firstRegister, uint8 *bufferPtr, uint8 size) { /* Create a new buffer that has that has the firstRegistsre as first element and the other elements as the data pointed to in bufferPtr */ uint8 i2c_status = I2C_MasterClearStatus(); //LCD_ClearDisplay(); LCD_Position(1,7); LCD_PrintInt8(i2c_status); I2C_MasterClearReadBuf(); I2C_MasterClearWriteBuf(); /* Pinter to the write buffer that will be written */ /* Set the first element of the buffer equal to the first register we will write to */ //*(Global_WritePtr) = firstRegister; /* Tranfers the data from the buffer that was passed to the function to the buffer that is to be written */ //uint8 i = 1; //for(i=1;i<=size;i++) //{ // *(Global_WritePtr+i) = bufferPtr[i-1]; //} /* Set the first element of the buffer equal to the first register we will write to */ uint8 j; for(j = size;j>0;j--) { bufferPtr[j] = bufferPtr[j-1]; } bufferPtr[0] = firstRegister; /* Write multiple bytes to the MAG3110 */ uint8 status = I2C_MasterWriteBuf(SLAVE_ADDRESS, bufferPtr, (size+1), I2C_MODE_COMPLETE_XFER); while (I2C_MasterStatus() && !I2C_MSTAT_WR_CMPLT){} /* Needed because of some bug in the psoc I2C tramission */ CyDelay(1); //functioncomplete_flag = 1;/*set Flag for write completion*/ return status; }
/* * @brief Write a byte to the MAG3110 * @details Takes a register address that we are going to write to and a byte of datat that we will write to the register * * @param registerAddress Address of the register on the MAG3110 * @param data Byte that will be written to the MAG3110 * * @return Error status of the function */ uint8 MagWriteByte(uint8 registerAddress, uint8 value) { //functioncomplete_flag = 0;/*set Flag for function Incomplete*/ I2C_MasterClearReadBuf(); I2C_MasterClearWriteBuf(); uint8 i2c_status = I2C_MasterClearStatus(); //LCD_ClearDisplay(); LCD_Position(1,7); LCD_PrintInt8(i2c_status); /* Buffer that holds the data to be written */ uint8 writeBuffer[2] = {registerAddress, value}; /* Pointer to the buffer that will be written */ uint8 *writePtr = writeBuffer; /* Write to MAG3110 */ uint8 status = I2C_MasterWriteBuf(SLAVE_ADDRESS, writePtr, 2, I2C_MODE_COMPLETE_XFER); /*Wait for transmission to finish*/ while (I2C_MasterStatus() && !I2C_MSTAT_WR_CMPLT){} CyDelay(1); //functioncomplete_flag = 1;/*set Flag for function complete*/ return status; }
/***************************************************************************** ** Function name: I2C_IRQHandler ** ** Descriptions: I2C interrupt handler ** ** parameters: None ** Returned value: None ** *****************************************************************************/ void I2C_IRQHandler(void) { uint32_t active = LPC_I2C->INTSTAT; uint32_t i2cmststate = LPC_I2C->STAT & MASTER_STATE_MASK; /* Only check Master and Slave State */ uint32_t i2cslvstate = LPC_I2C->STAT & SLAVE_STATE_MASK; uint32_t i; if ( active ) { I2CInterruptCount++; } #if I2C_MONITOR_MODE I2C_MonitorStatus(LPC_I2C, active); #endif /* If monitor mode is turned on, it needs to be the highest priority, otherwise, the slave TX and RX may stretch/release the clock and grab the data already. When that happens, Monitor may have missed a clock already. */ if(active & STAT_MONRDY) { I2CMonBuffer[I2CMonRXCount++] = LPC_I2C->MONRXDAT; if ( I2CMonRXCount == I2C_MONBUFSIZE ) { I2CMonRXCount = 0; } } /* The error interrupts should have higher priority too before data can be processed. */ #if TIMEOUT_ENABLED /* I2C timeout related interrupts. */ I2C_I2CTimeoutStatus(LPC_I2C, active); #endif /* master related interrupts. */ I2C_MasterStatus(LPC_I2C, active); if ( active & STAT_MSTPEND ) { LPC_I2C->INTENCLR = STAT_MSTPEND; /* Below five states are for Master mode: IDLE, TX, RX, NACK_ADDR, NAC_TX. IDLE is not under consideration for now. */ switch ( i2cmststate ) { case STAT_MSTIDLE: default: I2CMstIdleCount++; mstidle = 1; break; case STAT_MSTRX: I2CMstRXCount++; mstrxrdy = 1; break; case STAT_MSTTX: I2CMstTXCount++; msttxrdy = 1; break; case STAT_MSTNACKADDR: I2CMstNACKAddrCount++; break; case STAT_MSTNACKTX: I2CMstNACKTXCount++; break; } } /* slave related interrupts. */ I2C_SlaveStatus(LPC_I2C, active); if ( active & STAT_SLVPEND ) { LPC_I2C->INTENCLR = STAT_SLVPEND; /* Below three states are for Slave mode: Address Received, TX, and RX. */ switch ( i2cslvstate ) { case STAT_SLVRX: slvrxrdy = 1; I2CSlaveRXBuffer[I2CSlvRXCount++] = LPC_I2C->SLVDAT; if ( I2CSlvRXCount != I2C_BUFSIZE ) { LPC_I2C->SLVCTL = CTL_SLVCONTINUE; } else { LPC_I2C->SLVCTL = CTL_SLVNACK | CTL_SLVCONTINUE; I2CSlvRXCount = 0; for ( i = 0; i < I2C_BUFSIZE; i++ ) { /* copy data from SlaveReceive buffer and send the received data back to the master if "SlaveTX" is seen. */ I2CSlaveTXBuffer[i] = I2CSlaveRXBuffer[i]; } } LPC_I2C->INTENSET = STAT_SLVPEND; break; case STAT_SLVTX: slvtxrdy = 1; LPC_I2C->SLVDAT = I2CSlaveTXBuffer[I2CSlvTXCount++]; LPC_I2C->SLVCTL = CTL_SLVCONTINUE; if ( I2CSlvTXCount == I2C_BUFSIZE ) { I2CSlvTXCount = 0; for ( i = 0; i < I2C_BUFSIZE; i++ ) /* clear buffer */ { /* If "SlaveTX" is done, clear the slave tx buffer. If the next packet is slave rx, the slave tx will be filled again. If the next packet is slave tx again, "0"s will be sent out on the bus. */ I2CSlaveTXBuffer[i] = 0; } } LPC_I2C->INTENSET = STAT_SLVPEND; break; case STAT_SLVADDR: /* slave address is received. */ /* slaveaddrrcvd, slavetxrdy, and slaverxrdy are not used anymore as slave tx and rx are handled inside the ISR now. I2C_SlaveSendData(), I2C_SlaveReceiveData(), I2C_SlaveReceiveSend() are for polling mode only. */ slvaddrrcvd = 1; I2CSlvAddrCount++; LPC_I2C->SLVCTL = CTL_SLVCONTINUE; LPC_I2C->INTENSET = STAT_SLVPEND; break; default: break; } } return; }