/*** TMP3_WriteIIC ** ** Parameters: ** InstancePtr - PmodTMP3 object to initialize ** reg - Register to send to ** Data - Pointer to data buffer to send ** nData - Number of data values to send ** ** Return Value: ** none ** ** Errors: ** none ** ** Description: ** Writes nData data bytes to register reg ** */ void TMP3_WriteIIC(PmodTMP3* InstancePtr, u8 reg, u8 *Data, int nData) { u8 out[10]; out[0]=reg; out[1]=*Data; int Status; if (InstancePtr->currentRegister!=reg){ InstancePtr->currentRegister=reg; } Status = XIic_Start(&InstancePtr->TMP3Iic); if (Status != XST_SUCCESS) { return; } XIic_Send(InstancePtr->TMP3Iic.BaseAddress, InstancePtr->chipAddr, out, nData+1, XIIC_STOP); //XIic_MasterSend(&InstancePtr->TMP3Iic, out, nData+1); //XIic_DynMasterSend(&InstancePtr->TMP3Iic, out, nData+1); //while(XIic_IsIicBusy(&InstancePtr->TMP3Iic)); Status = XIic_Stop(&InstancePtr->TMP3Iic); if (Status != XST_SUCCESS) { return; } }
/*** TMP3_ReadIIC ** ** Parameters: ** InstancePtr - PmodTMP3 object to initialize ** reg - Register to read from ** Data - Pointer to recieve buffer ** nData - Number of data values to read ** ** Return Value: ** none ** ** Errors: ** none ** ** Description: ** Reads nData data bytes from register reg ** */ void TMP3_ReadIIC(PmodTMP3* InstancePtr, u8 reg, u8 *Data, int nData) { int Status; Status = XIic_Start(&InstancePtr->TMP3Iic); if (Status != XST_SUCCESS) { return; } if (InstancePtr->currentRegister!=reg){ //XIic_MasterSend(&InstancePtr->TMP3Iic, ®, 1); XIic_Send(InstancePtr->TMP3Iic.BaseAddress, InstancePtr->chipAddr, ®, 1, XII_REPEATED_START_OPTION); InstancePtr->currentRegister=reg; }//else{ //XIic_MasterRecv(&InstancePtr->TMP3Iic, Data, nData); //} XIic_Recv(InstancePtr->TMP3Iic.BaseAddress, InstancePtr->chipAddr, Data, nData, XIIC_STOP); //XIic_MasterSend(&InstancePtr->TMP3Iic, ®, 2); //InstancePtr->recvbytes=nData+1; //InstancePtr->recv=Data; //XIic_MasterRecv(&InstancePtr->TMP3Iic, Data, nData); Status = XIic_Stop(&InstancePtr->TMP3Iic); if (Status != XST_SUCCESS) { return; } }
int write_i2c_reg(u32 i2c_driver, u8 i2c_addr, u8 regaddr, u8 wrdata) { // uses low-level drivers to write to a i2c register // returns 1 if write successful, 0 if it failed u8 wrbuf[4]; unsigned int wrcount; wrbuf[0] = regaddr; wrbuf[1] = wrdata; wrcount = XIic_Send(i2c_driver, i2c_addr, &wrbuf[0], 2, XIIC_STOP); if (wrcount == 2) return 1; else { xil_printf("?I2C Send Error\r\n"); return 0; } }
/****************************************************************************** * This function writes a buffer of bytes to the IIC chip. * * @param ChipAddress contains the address of the chip. * @param RegAddress contains the address of the register to write to. * @param pBuffer contains the address of the data to write. * @param ByteCount contains the number of bytes in the buffer to be written. * Note that this should not exceed the page size as noted by the * constant PAGE_SIZE. * * @return The number of bytes written, a value less than that which was * specified as an input indicates an error. * * @note None. * ******************************************************************************/ int zed_iic_axi_IicWrite(zed_iic_t *pIIC, uint8_t ChipAddress, uint8_t RegAddress, uint8_t *pBuffer, uint8_t ByteCount) { uint8_t SentByteCount; uint8_t WriteBuffer[PAGE_SIZE + 1]; uint8_t Index; uint8_t StatusReg; zed_iic_axi_t *pContext = (zed_iic_axi_t *)(pIIC->pContext); #if 1 // Make sure all the Fifo's are cleared and Bus is Not busy. do { StatusReg = Xil_In8(pContext->CoreAddress + XIIC_SR_REG_OFFSET); //xil_printf("[%s] Xil_In8(pContext->CoreAddress + XIIC_SR_REG_OFFSET) => 0x%02X\n\r", pContext->szName, StatusReg ); StatusReg = StatusReg & (XIIC_SR_RX_FIFO_EMPTY_MASK | XIIC_SR_TX_FIFO_EMPTY_MASK | XIIC_SR_BUS_BUSY_MASK); } while (StatusReg != (XIIC_SR_RX_FIFO_EMPTY_MASK | XIIC_SR_TX_FIFO_EMPTY_MASK)); #endif /* * A temporary write buffer must be used which contains both the address * and the data to be written, put the address in first */ WriteBuffer[0] = RegAddress; /* * Put the data in the write buffer following the address. */ for (Index = 0; Index < ByteCount; Index++) { WriteBuffer[Index + 1] = pBuffer[Index]; } /* * Write data at the specified address. */ SentByteCount = XIic_Send(pContext->CoreAddress, ChipAddress, WriteBuffer, ByteCount + 1, XIIC_STOP); if (SentByteCount < 1) { SentByteCount = 1; } // Return the number of bytes written. return SentByteCount - 1; }
/****************************************************************************** * Function to write one byte (8-bits) to one of the registers from the audio * controller. * * @param u8RegAddr is the LSB part of the register address (0x40xx). * @param u8Data is the data byte to write. * * @return XST_SUCCESS if all the bytes have been sent to Controller. * XST_FAILURE otherwise. *****************************************************************************/ XStatus fnAudioWriteToReg(u8 u8RegAddr, u8 u8Data) { u8 u8TxData[3]; u8 u8BytesSent; u8TxData[0] = 0x40; u8TxData[1] = u8RegAddr; u8TxData[2] = u8Data; u8BytesSent = XIic_Send(XPAR_IIC_0_BASEADDR, IIC_SLAVE_ADDR, u8TxData, 3, XIIC_STOP); //check if all the bytes where sent if (u8BytesSent != 3) { return XST_FAILURE; } return XST_SUCCESS; }
int read_i2c_reg(u32 i2c_driver, u8 i2c_addr, u8 regaddr, u8* prdvalue) { // uses low-level driver to read from an i2c register // returns 1 if read successful, otherwise 0 u8 wrbuf[4]; unsigned int xcount; wrbuf[0] = regaddr; xcount = XIic_Send(i2c_driver, i2c_addr, &wrbuf[0], 1, XIIC_STOP); if (xcount != 1) { xil_printf("?I2C Send Error on Register Read\r\n"); return 0; } xcount = XIic_Recv(i2c_driver, i2c_addr, &wrbuf[0], 1, XIIC_STOP); *prdvalue = wrbuf[0]; if (xcount == 1) return 1; else { xil_printf("?I2C Recv Error on Register Read\r\n"); return 0; } }
/****************************************************************************** * Function to read one byte (8-bits) from the register space of audio controller. * * @param u8RegAddr is the LSB part of the register address (0x40xx). * @param u8RxData is the returned value * * @return XST_SUCCESS if the desired number of bytes have been read from the controller * XST_FAILURE otherwise *****************************************************************************/ XStatus fnAudioReadFromReg(u8 u8RegAddr, u8 *u8RxData) { u8 u8TxData[2]; u8 u8BytesSent, u8BytesReceived; u8TxData[0] = 0x40; u8TxData[1] = u8RegAddr; u8BytesSent = XIic_Send(XPAR_IIC_0_BASEADDR, IIC_SLAVE_ADDR, u8TxData, 2, XIIC_STOP); //check if all the bytes where sent if (u8BytesSent != 2) { return XST_FAILURE; } u8BytesReceived = XIic_Recv(XPAR_IIC_0_BASEADDR, IIC_SLAVE_ADDR, u8RxData, 1, XIIC_STOP); //check if there are missing bytes if (u8BytesReceived != 1) { return XST_FAILURE; } return XST_SUCCESS; }
/****************************************************************************** * This function reads a number of bytes from an IIC chip into a * specified buffer. * * @param ChipAddress contains the address of the IIC core. * @param RegAddress contains the address of the register to write to. * @param pBuffer contains the address of the data buffer to be filled. * @param ByteCount contains the number of bytes in the buffer to be read. * This value is constrained by the page size of the device such * that up to 64K may be read in one call. * * @return The number of bytes read. A value less than the specified input * value indicates an error. * * @note None. * ******************************************************************************/ int zed_iic_axi_IicRead(zed_iic_t *pIIC, uint8_t ChipAddress, uint8_t RegAddress, uint8_t *pBuffer, uint8_t ByteCount) { uint8_t ReceivedByteCount = 0; uint8_t SentByteCount = 0; uint8_t ControlReg; uint8_t StatusReg; int cnt = 0; zed_iic_axi_t *pContext = (zed_iic_axi_t *)(pIIC->pContext); #if 1 // Make sure all the Fifo's are cleared and Bus is Not busy. do { StatusReg = Xil_In8(pContext->CoreAddress + XIIC_SR_REG_OFFSET); //xil_printf("[%s] Xil_In8(pContext->CoreAddress + XIIC_SR_REG_OFFSET) => 0x%02X\n\r", pContext->szName, StatusReg ); StatusReg = StatusReg & (XIIC_SR_RX_FIFO_EMPTY_MASK | XIIC_SR_TX_FIFO_EMPTY_MASK | XIIC_SR_BUS_BUSY_MASK); if ((StatusReg & XIIC_SR_RX_FIFO_EMPTY_MASK) != XIIC_SR_RX_FIFO_EMPTY_MASK) { /* * The RX buffer is not empty and it is assumed there is a stale * message in there. Attempt to clear out the RX buffer, otherwise * this loop spins forever. */ XIic_ReadReg(pContext->CoreAddress, XIIC_DRR_REG_OFFSET); } /* * Check to see if the bus is busy. Since we are master, if the bus is * still busy that means that arbitration has been lost. * * According to Product Guide PG090, October 16, 2012: * * Control Register (0x100), Bit 2 MSMS: * * "Master/Slave Mode Select. When this bit is changed from 0 to 1, * the AXI IIC bus interface generates a START condition in master * mode. When this bit is cleared, a STOP condition is generated and * the AXI IIC bus interface switches to slave mode. When this bit is * cleared by the hardware, because arbitration for the bus has been * lost, a STOP condition is not generated. (See also Interrupt(0): * Arbitration Lost in Chapter 3.)" * * According to this, it should be okay to clear the master/slave mode * select to clear a false start condition with a stop and regain * arbitration over the bus. */ if ((StatusReg & XIIC_SR_BUS_BUSY_MASK) == XIIC_SR_BUS_BUSY_MASK) { ControlReg = Xil_In8(pContext->CoreAddress + XIIC_CR_REG_OFFSET); ControlReg = ControlReg & 0xFB; // Clear the MSMS bit. Xil_Out8(pContext->CoreAddress + XIIC_CR_REG_OFFSET, ControlReg); } } while (StatusReg != (XIIC_SR_RX_FIFO_EMPTY_MASK | XIIC_SR_TX_FIFO_EMPTY_MASK)); #endif // Position the Read pointer to specific location. do { StatusReg = Xil_In8(pContext->CoreAddress + XIIC_SR_REG_OFFSET); //xil_printf("[%s] Xil_In8(pContext->CoreAddress + XIIC_SR_REG_OFFSET) => 0x%02X\n\r", pContext->szName, StatusReg ); if(!(StatusReg & XIIC_SR_BUS_BUSY_MASK)) { SentByteCount = XIic_Send(pContext->CoreAddress, ChipAddress, (uint8_t *)&RegAddress, 1, XIIC_REPEATED_START); } cnt++; }while(SentByteCount != 1 && (cnt < 100)); // Error writing chip address so return SentByteCount if (SentByteCount < 1) { return SentByteCount; } // Receive the data. ReceivedByteCount = XIic_DynRecv(pContext->CoreAddress, ChipAddress, pBuffer, ByteCount); // Return the number of bytes received. return ReceivedByteCount; }
/****************************************************************************** * Configures audio codes's internal PLL. With MCLK = 12.288 MHz it configures the * PLL for a VCO frequency = 49.152 MHz. * * @param none. * * @return XST_SUCCESS if PLL is locked *****************************************************************************/ XStatus fnAudioPllConfig() { u8 u8TxData[8], u8RxData[6]; int Status; Status = fnAudioWriteToReg(R0_CLOCK_CONTROL, 0x0E); if (Status == XST_FAILURE) { if (Demo.u8Verbose) { xil_printf("\r\nError: could not write R0_CLOCK_CONTROL (0x0E)"); } return XST_FAILURE; } // Write 6 bytes to R1 // For setting the PLL with a MCLK = 12.288 MHz the datasheet suggests the // following configuration 0xXXXXXX2001 u8TxData[0] = 0x40; u8TxData[1] = 0x02; u8TxData[2] = 0x00; // byte 1 u8TxData[3] = 0x7D; // byte 2 u8TxData[4] = 0x00; // byte 3 u8TxData[5] = 0x0C; // byte 4 u8TxData[6] = 0x20; // byte 5 u8TxData[7] = 0x01; // byte 6 Status = XIic_Send(XPAR_IIC_0_BASEADDR, IIC_SLAVE_ADDR, u8TxData, 8, XIIC_STOP); if (Status != 8) { if (Demo.u8Verbose) { xil_printf("\r\nError: could not send data to R1_PLL_CONTROL (0xXXXXXX2001)"); } return XST_FAILURE; } // Poll PLL Lock bit u8TxData[0] = 0x40; u8TxData[1] = 0x02; //Wait for the PLL to lock do { XIic_Send(XPAR_IIC_0_BASEADDR, IIC_SLAVE_ADDR, u8TxData, 2, XIIC_STOP); XIic_Recv(XPAR_IIC_0_BASEADDR, IIC_SLAVE_ADDR, u8RxData, 6, XIIC_STOP); if(Demo.u8Verbose) { xil_printf("\nAudio PLL R1 = 0x%x%x%x%x%x%x", u8RxData[0], u8RxData[1], u8RxData[2], u8RxData[3], u8RxData[4], u8RxData[5]); } } while((u8RxData[5] & 0x02) == 0); //Set COREN Status = fnAudioWriteToReg(R0_CLOCK_CONTROL, 0x0F); if (Status == XST_FAILURE) { if (Demo.u8Verbose) { xil_printf("\r\nError: could not write R0_CLOCK_CONTROL (0x0F)"); } return XST_FAILURE; } return XST_SUCCESS; }