tStatus TWI_RegisterWrite(uint8_t u8addr, uint8_t u8data, uint8_t slaveAddress) { TWI_Start(); // send a start code to begin the write uint8_t status = TWI_GetStatus(); if (status != START && status != REP_START) // start not sent/acknowledged { //Serial.print("TWI Write failed, start not sent."); //Serial.print(" Status code is: 0x"); Serial.println(status,HEX); return ERROR; } TWI_Write( (slaveAddress<<1) ); // write the address shifted so that last bit is 0, meaning write request status = TWI_GetStatus(); if (status != MT_SLA_ACK) // SLA+W was not acknowledged { TWI_Stop(); // send a stop to end failed transmission //Serial.print("TWI Write failed, sla address not sent."); //Serial.print(" Status code is: 0x"); Serial.println(status,HEX); return ERROR; } TWI_Write(u8addr); // send the address to write to status = TWI_GetStatus(); if (status != MT_DATA_ACK) // the address was not sent { // Serial.print("TWI Write failed, register address not sent"); // Serial.print(" Status code is: 0x"); Serial.println(status,HEX); return ERROR; } TWI_Write(u8data); // send the data to write status = TWI_GetStatus(); if (status != MT_DATA_ACK) { // Serial.print("TWI Write failed, data not sent"); // Serial.print(" Status code is: 0x"); Serial.println(status,HEX); return ERROR; } TWI_Stop(); return SUCCESS; }
void TWI1_IrqHandler(void) { unsigned int status = TWI_GetStatus(TWI_STACK); if(((status & TWI_SR_SVACC) == TWI_SR_SVACC) && (eeprom.acquire == 0)) { TWI_DisableIt(TWI_STACK, TWI_IER_SVACC); TWI_EnableIt(TWI_STACK, TWI_IER_RXRDY | TWI_IER_GACC | TWI_IER_NACK | TWI_IER_EOSACC | TWI_IER_SCL_WS); eeprom.acquire++; eeprom.page = 0; eeprom.offset = 0; } if(((status & TWI_SR_SVACC) == TWI_SR_SVACC) && ((status & TWI_SR_GACC) == 0) && ((status & TWI_SR_RXRDY) == TWI_SR_RXRDY)) { if(eeprom.acquire == 1) { // Acquire LSB address eeprom.page = (TWI_ReadByte(TWI_STACK) & 0xFF); eeprom.acquire++; } else if(eeprom.acquire == 2) { // Acquire MSB address eeprom.page |= (TWI_ReadByte(TWI_STACK) & 0xFF) << 8; eeprom.acquire++; } else { // Read one byte of data from master to slave device uint16_t addr = I2C_EEPROM_PAGE_SIZE*eeprom.page + eeprom.offset; i2c_eeprom_slave_set_memory(addr, TWI_ReadByte(TWI_STACK) & 0xFF); eeprom.offset++; } } else if(((status & TWI_SR_TXRDY) == TWI_SR_TXRDY) && ((status & TWI_SR_TXCOMP) == TWI_SR_TXCOMP) && ((status & TWI_SR_EOSACC) == TWI_SR_EOSACC)) { // End of transfer, end of slave access eeprom.offset = 0; eeprom.acquire = 0; eeprom.page = 0; TWI_EnableIt(TWI_STACK, TWI_IER_SVACC); TWI_DisableIt(TWI_STACK, TWI_IER_RXRDY | TWI_IDR_GACC | TWI_IDR_NACK | TWI_IER_EOSACC | TWI_IER_SCL_WS); } else if(((status & TWI_SR_SVACC) == TWI_SR_SVACC) && ((status & TWI_SR_GACC) == 0) && (eeprom.acquire == 3) && ((status & TWI_SR_SVREAD) == TWI_SR_SVREAD) && ((status & TWI_SR_NACK) == 0)) { // Write one byte of data from slave to master device uint16_t addr = I2C_EEPROM_PAGE_SIZE*eeprom.page + eeprom.offset; TWI_WriteByte(TWI_STACK, i2c_eeprom_slave_get_memory(addr)); eeprom.offset++; } }
static inline bool TWI_WaitTransferComplete(Twi *_twi, uint32_t _timeout) { uint32_t _status_reg = 0; while ((_status_reg & TWI_SR_TXCOMP) != TWI_SR_TXCOMP) { _status_reg = TWI_GetStatus(_twi); if (_status_reg & TWI_SR_NACK) return false; if (--_timeout == 0) return false; } return true; }
static inline bool TWI_WaitByteReceived(Twi *_twi, uint32_t _timeout) { uint32_t _status_reg = 0; while ((_status_reg & TWI_SR_RXRDY) != TWI_SR_RXRDY) { _status_reg = TWI_GetStatus(_twi); if (_status_reg & TWI_SR_NACK) return false; if (--_timeout == 0) return false; } return true; }
/********************************************** * \brief * * * \return none */ result_t HalExpansionPortClass::writePcaPorts(uint32_t iRegister, uint8_t *pBuffer, uint32_t bufLength) { uint32_t bufCnt=bufLength; uint32_t breakOut_cnt=0; result_t retResult=SUCCESS; TWI_StartWrite(HW_ADDR_TWI_PCA9698,HW_PCA9698_TwiAddr, iRegister,HW_PCA9698_InternalAddrLen,*pBuffer); pBuffer++; bufCnt--; while(bufCnt >0) { //if no NACK and Byte sent, then transmit next one if (TWI_SR_NACK & TWI_GetStatus(HW_ADDR_TWI_PCA9698)) { dbgOut1(eDbgAll_errEvt,'B',"HalTwiPca Unexpected NACK ",bufCnt); retResult=FAIL; break; } if (!TWI_ByteSent(HW_ADDR_TWI_PCA9698)) { if (90000 < ++breakOut_cnt) { dbgOut1(eDbgAll_errEvt,'B',"HalTwiPca TWI_SR_TXRDY exceeded ",bufCnt); retResult=FAIL; break; //Out while } continue; } breakOut_cnt = 0; TWI_WriteByte(HW_ADDR_TWI_PCA9698,*pBuffer); pBuffer++; bufCnt--; } TWI_Stop(HW_ADDR_TWI_PCA9698); while (!TWI_TransferComplete(HW_ADDR_TWI_PCA9698)) { if (90000 < ++breakOut_cnt) { dbgOut(eDbgAll_errEvt,'B',"HalTwiPca TWI_SR_TXCOMP exceeded "); break; //Out while } } return retResult; }//portInit
void TwoWire::onService(void) { // Retrieve interrupt status uint32_t sr = TWI_GetStatus(twi); if (status == SLAVE_IDLE && TWI_STATUS_SVACC(sr)) { TWI_DisableIt(twi, TWI_IDR_SVACC); TWI_EnableIt(twi, TWI_IER_RXRDY | TWI_IER_GACC | TWI_IER_NACK | TWI_IER_EOSACC | TWI_IER_SCL_WS | TWI_IER_TXCOMP); srvBufferLength = 0; srvBufferIndex = 0; // Detect if we should go into RECV or SEND status // SVREAD==1 means *master* reading -> SLAVE_SEND if (!TWI_STATUS_SVREAD(sr)) { status = SLAVE_RECV; } else { status = SLAVE_SEND; // Alert calling program to generate a response ASAP if (onRequestCallback) onRequestCallback(); else // create a default 1-byte response write((uint8_t) 0); } } if (status != SLAVE_IDLE) { if (TWI_STATUS_TXCOMP(sr) && TWI_STATUS_EOSACC(sr)) { if (status == SLAVE_RECV && onReceiveCallback) { // Copy data into rxBuffer // (allows to receive another packet while the // user program reads actual data) for (uint8_t i = 0; i < srvBufferLength; ++i) rxBuffer[i] = srvBuffer[i]; rxBufferIndex = 0; rxBufferLength = srvBufferLength; // Alert calling program onReceiveCallback( rxBufferLength); } // Transfer completed TWI_EnableIt(twi, TWI_SR_SVACC); TWI_DisableIt(twi, TWI_IDR_RXRDY | TWI_IDR_GACC | TWI_IDR_NACK | TWI_IDR_EOSACC | TWI_IDR_SCL_WS | TWI_IER_TXCOMP); status = SLAVE_IDLE; } } if (status == SLAVE_RECV) { if (TWI_STATUS_RXRDY(sr)) { if (srvBufferLength < BUFFER_LENGTH) srvBuffer[srvBufferLength++] = TWI_ReadByte(twi); } } if (status == SLAVE_SEND) { if (TWI_STATUS_TXRDY(sr) && !TWI_STATUS_NACK(sr)) { uint8_t c = 'x'; if (srvBufferIndex < srvBufferLength) c = srvBuffer[srvBufferIndex++]; TWI_WriteByte(twi, c); } } }
/** * \brief Asynchronously sends data to a slave on the TWI bus. An optional callback * function is invoked whenever the transfer is complete. * \param pTwid Pointer to a Twid instance. * \param address TWI slave address. * \param iaddress Optional slave internal address. * \param isize Number of internal address bytes. * \param pData Data buffer for storing received bytes. * \param num Data buffer to send. * \param pAsync Asynchronous transfer descriptor. * \return 0 if the transfer has been started; otherwise returns a TWI error code. */ uint8_t TWID_Write( Twid *pTwid, uint8_t address, uint32_t iaddress, uint8_t isize, uint8_t *pData, uint32_t num, Async *pAsync) { Twi *pTwi = pTwid->pTwi; AsyncTwi *pTransfer = (AsyncTwi *) pTwid->pTransfer; uint32_t timeout = 0; uint32_t status; uint8_t singleTransfer = 0; assert( pTwi != NULL ) ; assert( (address & 0x80) == 0 ) ; assert( (iaddress & 0xFF000000) == 0 ) ; assert( isize < 4 ) ; if(num == 1) singleTransfer = 1; /* Check that no transfer is already pending */ if (pTransfer) { TRACE_ERROR("TWI_Write: A transfer is already pending\n\r"); return TWID_ERROR_BUSY; } /* Asynchronous transfer */ if (pAsync) { /* Update the transfer descriptor */ pTwid->pTransfer = pAsync; pTransfer = (AsyncTwi *) pAsync; pTransfer->status = ASYNC_STATUS_PENDING; pTransfer->pData = pData; pTransfer->num = num; pTransfer->transferred = 1; /* Enable write interrupt and start the transfer */ TWI_StartWrite(pTwi, address, iaddress, isize, *pData); TWI_EnableIt(pTwi, TWI_IER_TXRDY); } /* Synchronous transfer*/ else { // Start write TWI_StartWrite(pTwi, address, iaddress, isize, *pData++); num--; if (singleTransfer) { /* Send a STOP condition */ TWI_SendSTOPCondition(pTwi); } status = TWI_GetStatus(pTwi); if(status & TWI_SR_NACK) TRACE_ERROR("TWID NACK error\n\r"); while( !(status & TWI_SR_TXRDY) && (timeout++ < TWITIMEOUTMAX) ) { status = TWI_GetStatus(pTwi); } if (timeout == TWITIMEOUTMAX) { TRACE_ERROR("TWID Timeout BS\n\r"); } timeout = 0; /* Send all bytes */ while (num > 0) { /* Wait before sending the next byte */ timeout = 0; TWI_WriteByte(pTwi, *pData++); status = TWI_GetStatus(pTwi); if(status & TWI_SR_NACK) TRACE_ERROR("TWID NACK error\n\r"); while( !(status & TWI_SR_TXRDY) && (timeout++ < TWITIMEOUTMAX) ) { status = TWI_GetStatus(pTwi); } if (timeout == TWITIMEOUTMAX) { TRACE_ERROR("TWID Timeout BS\n\r"); } num--; } /* Wait for actual end of transfer */ timeout = 0; if (!singleTransfer) { /* Send a STOP condition */ TWI_SendSTOPCondition(pTwi); } while( !TWI_TransferComplete(pTwi) && (++timeout<TWITIMEOUTMAX) ); if (timeout == TWITIMEOUTMAX) { TRACE_ERROR("TWID Timeout TC2\n\r"); } } return 0; }
/** * \brief Asynchronously reads data from a slave on the TWI bus. An optional * callback function is triggered when the transfer is complete. * \param pTwid Pointer to a Twid instance. * \param address TWI slave address. * \param iaddress Optional slave internal address. * \param isize Internal address size in bytes. * \param pData Data buffer for storing received bytes. * \param num Number of bytes to read. * \param pAsync Asynchronous transfer descriptor. * \return 0 if the transfer has been started; otherwise returns a TWI error code. */ uint8_t TWID_Read( Twid *pTwid, uint8_t address, uint32_t iaddress, uint8_t isize, uint8_t *pData, uint32_t num, Async *pAsync) { Twi *pTwi; AsyncTwi *pTransfer; uint32_t timeout = 0; uint32_t i = 0; uint32_t status; assert( pTwid != NULL ) ; pTwi = pTwid->pTwi; pTransfer = (AsyncTwi *) pTwid->pTransfer; assert( (address & 0x80) == 0 ) ; assert( (iaddress & 0xFF000000) == 0 ) ; assert( isize < 4 ) ; /* Check that no transfer is already pending*/ if (pTransfer) { TRACE_ERROR("TWID_Read: A transfer is already pending\n\r"); return TWID_ERROR_BUSY; } /* Asynchronous transfer*/ if (pAsync) { /* Update the transfer descriptor */ pTwid->pTransfer = pAsync; pTransfer = (AsyncTwi *) pAsync; pTransfer->status = ASYNC_STATUS_PENDING; pTransfer->pData = pData; pTransfer->num = num; pTransfer->transferred = 0; /* Enable read interrupt and start the transfer */ TWI_EnableIt(pTwi, TWI_IER_RXRDY); TWI_StartRead(pTwi, address, iaddress, isize); } /* Synchronous transfer*/ else { /* Start read*/ TWI_StartRead(pTwi, address, iaddress, isize); if (num != 1) { status = TWI_GetStatus(pTwi); if(status & TWI_SR_NACK) TRACE_ERROR("TWID NACK error\n\r"); timeout = 0; while( ! (status & TWI_SR_RXRDY) && (++timeout<TWITIMEOUTMAX)) { status = TWI_GetStatus(pTwi); //TRACE_ERROR("TWID status %x\n\r",TWI_GetStatus(pTwi)); } pData[0] = TWI_ReadByte(pTwi); for( i = 1; i < num - 1; i++) { status = TWI_GetStatus(pTwi); if(status & TWI_SR_NACK) TRACE_ERROR("TWID NACK error\n\r"); timeout = 0; while( ! (status & TWI_SR_RXRDY) && (++timeout<TWITIMEOUTMAX)) { status = TWI_GetStatus(pTwi); //TRACE_ERROR("TWID status %x\n\r",TWI_GetStatus(pTwi)); } pData[i] = TWI_ReadByte(pTwi); } } TWI_Stop(pTwi); status = TWI_GetStatus(pTwi); if(status & TWI_SR_NACK) TRACE_ERROR("TWID NACK error\n\r"); timeout = 0; while( ! (status & TWI_SR_RXRDY) && (++timeout<TWITIMEOUTMAX)) { status = TWI_GetStatus(pTwi); //TRACE_ERROR("TWID status %x\n\r",TWI_GetStatus(pTwi)); } pData[i] = TWI_ReadByte(pTwi); timeout = 0; status = TWI_GetStatus(pTwi); while( !(status & TWI_SR_TXCOMP) && (++timeout<TWITIMEOUTMAX)) { status = TWI_GetStatus(pTwi); //TRACE_ERROR("TWID status %x\n\r",TWI_GetStatus(pTwi)); } #if 0 /* Read all bytes, setting STOP before the last byte*/ while (num > 0) { /* Last byte ?*/ if (num == 1) { TWI_Stop(pTwi); } /* Wait for byte then read and store it*/ timeout = 0; while( !TWI_ByteReceived(pTwi) && (++timeout<TWITIMEOUTMAX) ); if (timeout == TWITIMEOUTMAX) { TRACE_ERROR("TWID Timeout BR\n\r"); } *pData++ = TWI_ReadByte(pTwi); num--; } /* Wait for transfer to be complete */ timeout = 0; while( !TWI_TransferComplete(pTwi) && (++timeout<TWITIMEOUTMAX) ); if (timeout == TWITIMEOUTMAX) { TRACE_ERROR("TWID Timeout TC\n\r"); } #endif } return 0; }
tStatus TWI_RegisterRead_Multiple(uint8_t u8addr, uint8_t* u8data, uint8_t numBytes, uint8_t slaveAddress) { TWI_Start(); // send a start code to begin the write uint8_t status = TWI_GetStatus(); if (status != START && status != REP_START) // start not sent/acknowledged { // Serial.print("TWI Read failed"); // Serial.print(" Status code is: 0x"); Serial.println(status,HEX); return ERROR; } TWI_Write( (slaveAddress<<1) ); // write the address shifted so that last bit is 0, meaning write request status = TWI_GetStatus(); if (status != MT_SLA_ACK) // SLA+W was not acknowledged { // Serial.print("TWI Read failed"); // Serial.print(" Status code is: 0x"); Serial.println(status,HEX); return ERROR; } TWI_Write(u8addr); // send the address to read from status = TWI_GetStatus(); if (status != MT_DATA_ACK) // the address was not sent { // Serial.print("TWI Read failed"); // Serial.print(" Status code is: 0x"); Serial.println(status,HEX); return ERROR; } TWI_Start(); // send a repeated start status = TWI_GetStatus(); if (status != REP_START) // start not sent { // Serial.print("TWI Read failed"); // Serial.print(" Status code is: 0x"); Serial.println(status,HEX); return ERROR; } TWI_Write( ( (slaveAddress<<1) | 1) ); // write the address shifted so that last bit is 1, meaning read request status = TWI_GetStatus(); if (status != MR_SLA_ACK) // SLA+R was not acknowledged { // Serial.print("TWI Read failed"); // Serial.print(" Status code is: 0x"); Serial.println(status,HEX); return ERROR; } for (int i=0; i<numBytes-1; i++) { u8data[i] = TWI_ReadACK(); // read the data status = TWI_GetStatus(); if (status != MR_DATA_ACK) { // Serial.print("TWI Read failed. Byte #"); Serial.print(i); // Serial.print(" Status code is: 0x"); Serial.println(status,HEX); return ERROR; } } u8data[numBytes-1] = TWI_ReadNACK(); // read the last byte, and respond with a NACK to let the slave know its the last one status = TWI_GetStatus(); if (status != MR_DATA_NACK) { // Serial.print("TWI Read failed"); // Serial.print(" Status code is: 0x"); Serial.println(status,HEX); return ERROR; } TWI_Stop(); return SUCCESS; }
tStatus TWI_RegisterRead(uint8_t u8addr, uint8_t* u8data, uint8_t slaveAddress) { TWI_Start(); // send a start code to begin the write uint8_t status = TWI_GetStatus(); if (status != START && status != REP_START) // start not sent/acknowledged { // Serial.print("TWI Read failed. Start not sent"); // Serial.print(" Status code is: 0x"); Serial.println(status,HEX); return ERROR; } TWI_Write( (slaveAddress<<1) ); // write the address shifted so that last bit is 0, meaning write request status = TWI_GetStatus(); if (status != MT_SLA_ACK) // SLA+W was not acknowledged { // Serial.print("TWI Read failed. address not sent"); // Serial.print(" Status code is: 0x"); Serial.println(status,HEX); return ERROR; } TWI_Write(u8addr); // send the address to read from status = TWI_GetStatus(); if (status != MT_DATA_ACK) // the address was not sent { // Serial.print("TWI Read failed. address of register not sent"); // Serial.print(" Status code is: 0x"); Serial.println(status,HEX); return ERROR; } TWI_Start(); // send a repeated start status = TWI_GetStatus(); if (status != REP_START) // start not sent { // Serial.print("TWI Read failed. Repeated Start not sent"); // Serial.print(" Status code is: 0x"); Serial.println(status,HEX); return ERROR; } TWI_Write( ( (slaveAddress<<1) | 1) ); // write the address shifted so that last bit is 1, meaning read request status = TWI_GetStatus(); if (status != MR_SLA_ACK) // SLA+R was not acknowledged { // Serial.print("TWI Read failed"); // Serial.print(" Status code is: 0x"); Serial.println(status,HEX); return ERROR; } *u8data = TWI_ReadNACK(); // read the data status = TWI_GetStatus(); if (status != MR_DATA_NACK) { // Serial.print("TWI Read failed"); // Serial.print(" Status code is: 0x"); Serial.println(status,HEX); return ERROR; } TWI_Stop(); return SUCCESS; }
uint8_t print_sequence(const uint8_t *buf, uint8_t i2c_addr) { uint8_t value; uint8_t size; uint8_t addr_msb = SEQ_END; uint8_t addr_lsb; uint8_t stat; size = 2; //printf(PSTR("INIT SIZE: %u\n"), init_size); while(1) { addr_msb = pgm_read_byte(buf++); //read address or command, then set buf to point to the data if(debug_output) printf("%02X ",addr_msb); if(addr_msb == SEQ_SIZE) { size = pgm_read_byte(buf++); //read the size from buf, then set buf to next register address or command if(debug_output) printf_P(PSTR("SEQ_SIZE %u\n"), size); continue; } else if(addr_msb == SEQ_END) { break; } else if(addr_msb == SEQ_DELAY) { //value = pgm_read_byte(buf++); _delay_ms(100); if(debug_output) printf_P(PSTR("SEQ_DELAY\n")); continue; } else if(addr_msb == SEQ_RESET) { if(debug_output) printf_P(PSTR("SEQ_RESET\n"), value); //Eval SharpLCD Reset Pin PORTB |= RESET_PIN; //Set High DDRB |= RESET_PIN; //Set Output //Drude SharpLCD Reset Pin PORTB |= RESETN_PIN; //Set High DDRB |= RESETN_PIN; //Set Output _delay_us(10); //Wait 10 microseconds PORTB &= ~(RESETN_PIN); //Drude Reset Pin Set Low PORTB &= ~(RESET_PIN); //Eval Reset Pin Set Low _delay_us(10); //Wait 10 microseconds PORTB |= RESET_PIN; //Eval Reset Pin Set High PORTB |= RESETN_PIN; //Drude Toshina Reset Pin Set High _delay_ms(10); //DDRB &= ~(RESET_PIN); //Set Input continue; } else if(addr_msb == SEQ_READ) { value = pgm_read_byte(buf++); addr_lsb = pgm_read_byte(buf++); if(debug_output) printf_P(PSTR("SEQ_READ %02X %02X\n"), value,addr_lsb); continue; }; TWI_Start(); // First start condition stat = TWI_GetStatus(); if (stat != 0x08) { if(debug_output) printf_P(PSTR("\nTWI_Start()\n")); return stat; } TWI_Write((i2c_addr<<1)); // Chip address + write stat = TWI_GetStatus(); if (stat != 0x18) { if(debug_output) printf_P(PSTR("\nTWI_Write(HDMICONV_ADDR)\n")); return stat; } /* if( ! i2c_start(HDMICONV_ADDR) ) { printf_P(PSTR("i2c_start failed.\n")); } */ TWI_Write(addr_msb); // Address high byte stat = TWI_GetStatus(); if (stat != 0x28) { if(debug_output) printf_P(PSTR("\nTWI_Write(addr_msb)\n")); return stat; } for(uint8_t i=0; i<=size && i<10 ; i++) { value = pgm_read_byte(buf++); if(debug_output) printf("%02X ",value); TWI_Write(value); stat = TWI_GetStatus(); if (stat != 0x28) return stat; } TWI_Stop(); // Send stop condition _delay_us(5); if(debug_output) printf("\n"); } }