From 72d6c50a2224f9d6d0d7f9bb516f9a8698b5a58d Mon Sep 17 00:00:00 2001 From: Wolfgang Draxinger Date: Mon, 23 Dec 2013 14:16:07 +0100 Subject: reading EDID information from display and submission to host works --- twi_master_driver.c | 240 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 160 insertions(+), 80 deletions(-) (limited to 'twi_master_driver.c') diff --git a/twi_master_driver.c b/twi_master_driver.c index c7f9695..8c5a695 100644 --- a/twi_master_driver.c +++ b/twi_master_driver.c @@ -68,6 +68,10 @@ #include "twi_master_driver.h" +static void TWI_MasterWriteHandler(TWI_Master_t *twi); +static void TWI_MasterReadHandler(TWI_Master_t *twi); +static void TWI_MasterTransactionFinished(TWI_Master_t *twi, uint8_t result); +static void TWI_MasterArbitrationLostBusErrorHandler(TWI_Master_t *twi); /*! \brief Initialize the TWI module. * @@ -86,14 +90,28 @@ void TWI_MasterInit(TWI_Master_t *twi, uint8_t baudRateRegisterSetting) { twi->interface = module; + twi->interface->CTRL = TWI_SDAHOLD_bm; twi->interface->MASTER.CTRLA = intLevel | TWI_MASTER_RIEN_bm | TWI_MASTER_WIEN_bm | TWI_MASTER_ENABLE_bm; + + #if 1 + twi->interface->MASTER.CTRLB = + TWI_MASTER_TIMEOUT_200US_gc; + #endif + twi->interface->MASTER.BAUD = baudRateRegisterSetting; twi->interface->MASTER.STATUS = TWI_MASTER_BUSSTATE_IDLE_gc; + + twi->status = TWIM_STATUS_READY; } +void TWI_MasterForceIdle(TWI_Master_t *twi) +{ + twi->interface->MASTER.STATUS = TWI_MASTER_BUSSTATE_IDLE_gc; + twi->status = TWIM_STATUS_READY; +} /*! \brief Returns the TWI bus state. * @@ -128,7 +146,7 @@ TWI_MASTER_BUSSTATE_t TWI_MasterState(TWI_Master_t *twi) */ bool TWI_MasterReady(TWI_Master_t *twi) { - bool twi_status = (twi->status & TWIM_STATUS_READY); + bool twi_status = (twi->status == TWIM_STATUS_READY); return twi_status; } @@ -147,10 +165,14 @@ bool TWI_MasterReady(TWI_Master_t *twi) */ bool TWI_MasterWrite(TWI_Master_t *twi, uint8_t address, - uint8_t *writeData, + uint8_t const *writeData, uint8_t bytesToWrite) { - bool twi_status = TWI_MasterWriteRead(twi, address, writeData, bytesToWrite, 0); + bool twi_status = TWI_MasterWriteRead(twi, + address, + writeData, bytesToWrite, + NULL, 0); + return twi_status; } @@ -168,9 +190,14 @@ bool TWI_MasterWrite(TWI_Master_t *twi, */ bool TWI_MasterRead(TWI_Master_t *twi, uint8_t address, + uint8_t *readData, uint8_t bytesToRead) { - bool twi_status = TWI_MasterWriteRead(twi, address, 0, 0, bytesToRead); + bool twi_status = TWI_MasterWriteRead(twi, + address, + NULL, 0, + readData, bytesToRead); + return twi_status; } @@ -192,55 +219,57 @@ bool TWI_MasterRead(TWI_Master_t *twi, */ bool TWI_MasterWriteRead(TWI_Master_t *twi, uint8_t address, - uint8_t *writeData, + uint8_t const *writeData, uint8_t bytesToWrite, + uint8_t *readData, uint8_t bytesToRead) { - /*Parameter sanity check. */ - if (bytesToWrite > TWIM_WRITE_BUFFER_SIZE) { - return false; + if( !bytesToWrite || !writeData ) { + writeData = NULL; + bytesToWrite = 0; } - if (bytesToRead > TWIM_READ_BUFFER_SIZE) { - return false; + if( !bytesToRead || !readData ) { + readData = NULL; + bytesToRead = 0; } /*Initiate transaction if bus is ready. */ - if (twi->status == TWIM_STATUS_READY) { - - twi->status = TWIM_STATUS_BUSY; - twi->result = TWIM_RESULT_UNKNOWN; - - twi->address = address<<1; - - /* Fill write data buffer. */ - for (uint8_t bufferIndex=0; bufferIndex < bytesToWrite; bufferIndex++) { - twi->writeData[bufferIndex] = writeData[bufferIndex]; - } - - twi->bytesToWrite = bytesToWrite; - twi->bytesToRead = bytesToRead; - twi->bytesWritten = 0; - twi->bytesRead = 0; - - /* If write command, send the START condition + Address + - * 'R/_W = 0' - */ - if (twi->bytesToWrite > 0) { - uint8_t writeAddress = twi->address & ~0x01; - twi->interface->MASTER.ADDR = writeAddress; - } - - /* If read command, send the START condition + Address + - * 'R/_W = 1' - */ - else if (twi->bytesToRead > 0) { - uint8_t readAddress = twi->address | 0x01; - twi->interface->MASTER.ADDR = readAddress; - } - return true; - } else { + if( twi->status != TWIM_STATUS_READY ) { return false; } + + twi->status = TWIM_STATUS_BUSY; + twi->result = TWIM_RESULT_UNKNOWN; + + twi->address = (address << 1); + + twi->writeData = writeData; + twi->readData = readData; + twi->bytesToWrite = bytesToWrite; + twi->bytesToRead = bytesToRead; + twi->bytesWritten = 0; + twi->bytesRead = 0; + + /* If write command, send the START condition + Address + + * 'R/_W = 0' + */ + if( twi->bytesToWrite > 0 ) { + uint8_t const writeAddress = twi->address & ~0x01; + twi->interface->MASTER.ADDR = writeAddress; + + uint8_t const data = twi->writeData[0]; + twi->interface->MASTER.DATA = data; + twi->bytesWritten++; + } else + /* If read command, send the START condition + Address + + * 'R/_W = 1' + */ + if( twi->bytesToRead > 0 ) { + uint8_t const readAddress = twi->address | 0x01; + twi->interface->MASTER.ADDR = readAddress; + } + + return true; } @@ -252,28 +281,64 @@ bool TWI_MasterWriteRead(TWI_Master_t *twi, */ void TWI_MasterInterruptHandler(TWI_Master_t *twi) { - uint8_t currentStatus = twi->interface->MASTER.STATUS; +#if 0 + PORTB.OUTSET = (1<<3); + PORTB.OUTCLR = (1<<3); +#endif + uint8_t const currentStatus = twi->interface->MASTER.STATUS; /* If arbitration lost or bus error. */ if ((currentStatus & TWI_MASTER_ARBLOST_bm) || (currentStatus & TWI_MASTER_BUSERR_bm)) { +#if 0 + PORTB.OUTSET = (1<<3); + PORTB.OUTCLR = (1<<3); +#endif TWI_MasterArbitrationLostBusErrorHandler(twi); - } - + twi->interface->MASTER.STATUS = + currentStatus + | TWI_MASTER_ARBLOST_bm + | TWI_MASTER_BUSERR_bm; + } else /* If master write interrupt. */ - else if (currentStatus & TWI_MASTER_WIF_bm) { + if (currentStatus & TWI_MASTER_WIF_bm) { +#if 0 + PORTB.OUTSET = (1<<3); + PORTB.OUTCLR = (1<<3); +#endif TWI_MasterWriteHandler(twi); - } + twi->interface->MASTER.STATUS = + currentStatus + | TWI_MASTER_WIF_bm; + } else /* If master read interrupt. */ - else if (currentStatus & TWI_MASTER_RIF_bm) { + if (currentStatus & TWI_MASTER_RIF_bm) { +#if 0 + PORTB.OUTSET = (1<<3); + PORTB.OUTCLR = (1<<3); +#endif TWI_MasterReadHandler(twi); - } + twi->interface->MASTER.STATUS = + currentStatus + | TWI_MASTER_RIF_bm; + } else + /* Bus went idle (timeout) */ + if( (currentStatus & TWI_MASTER_BUSSTATE_IDLE_gc) + == TWI_MASTER_BUSSTATE_IDLE_gc ) { + TWI_MasterTransactionFinished(twi, TWIM_RESULT_UNKNOWN); + } /* If unexpected state. */ else { +#if 0 + PORTB.OUTSET = (1<<3); + PORTB.OUTCLR = (1<<3); +#endif TWI_MasterTransactionFinished(twi, TWIM_RESULT_FAIL); + + twi->interface->MASTER.STATUS = currentStatus; } } @@ -284,9 +349,9 @@ void TWI_MasterInterruptHandler(TWI_Master_t *twi) * * \param twi The TWI_Master_t struct instance. */ -void TWI_MasterArbitrationLostBusErrorHandler(TWI_Master_t *twi) +static void TWI_MasterArbitrationLostBusErrorHandler(TWI_Master_t *twi) { - uint8_t currentStatus = twi->interface->MASTER.STATUS; + uint8_t const currentStatus = twi->interface->MASTER.STATUS; /* If bus error. */ if (currentStatus & TWI_MASTER_BUSERR_bm) { @@ -297,9 +362,6 @@ void TWI_MasterArbitrationLostBusErrorHandler(TWI_Master_t *twi) twi->result = TWIM_RESULT_ARBITRATION_LOST; } - /* Clear interrupt flag. */ - twi->interface->MASTER.STATUS = currentStatus | TWI_MASTER_ARBLOST_bm; - twi->status = TWIM_STATUS_READY; } @@ -310,36 +372,49 @@ void TWI_MasterArbitrationLostBusErrorHandler(TWI_Master_t *twi) * * \param twi The TWI_Master_t struct instance. */ -void TWI_MasterWriteHandler(TWI_Master_t *twi) +static void TWI_MasterWriteHandler(TWI_Master_t *twi) { /* Local variables used in if tests to avoid compiler warning. */ - uint8_t bytesToWrite = twi->bytesToWrite; - uint8_t bytesToRead = twi->bytesToRead; + uint8_t const bytesToWrite = twi->bytesToWrite; + uint8_t const bytesToRead = twi->bytesToRead; /* If NOT acknowledged (NACK) by slave cancel the transaction. */ - if (twi->interface->MASTER.STATUS & TWI_MASTER_RXACK_bm) { + if( twi->interface->MASTER.STATUS & TWI_MASTER_RXACK_bm ) { +#if 0 + PORTB.OUTSET = (1<<3); + PORTB.OUTCLR = (1<<3); +#endif twi->interface->MASTER.CTRLC = TWI_MASTER_CMD_STOP_gc; twi->result = TWIM_RESULT_NACK_RECEIVED; twi->status = TWIM_STATUS_READY; - } - + } else /* If more bytes to write, send data. */ - else if (twi->bytesWritten < bytesToWrite) { - uint8_t data = twi->writeData[twi->bytesWritten]; + if( twi->bytesWritten < bytesToWrite ) { +#if 0 + PORTB.OUTSET = (1<<3); + PORTB.OUTCLR = (1<<3); +#endif + uint8_t const data = twi->writeData[twi->bytesWritten]; twi->interface->MASTER.DATA = data; - ++twi->bytesWritten; - } - + twi->bytesWritten++; + } else /* If bytes to read, send repeated START condition + Address + * 'R/_W = 1' */ - else if (twi->bytesRead < bytesToRead) { - uint8_t readAddress = twi->address | 0x01; + if( twi->bytesRead < bytesToRead ) { +#if 0 + PORTB.OUTSET = (1<<3); + PORTB.OUTCLR = (1<<3); +#endif + uint8_t const readAddress = twi->address | 0x01; twi->interface->MASTER.ADDR = readAddress; } - /* If transaction finished, send STOP condition and set RESULT OK. */ else { +#if 0 + PORTB.OUTSET = (1<<3); + PORTB.OUTCLR = (1<<3); +#endif twi->interface->MASTER.CTRLC = TWI_MASTER_CMD_STOP_gc; TWI_MasterTransactionFinished(twi, TWIM_RESULT_OK); } @@ -353,32 +428,36 @@ void TWI_MasterWriteHandler(TWI_Master_t *twi) * * \param twi The TWI_Master_t struct instance. */ -void TWI_MasterReadHandler(TWI_Master_t *twi) +static void TWI_MasterReadHandler(TWI_Master_t *twi) { +#if 1 + PORTB.OUTTGL = (1<<3); + PORTB.OUTTGL = (1<<3); +#endif + + /* Local variable used in if test to avoid compiler warning. */ + uint8_t const bytesToRead = twi->bytesToRead; + /* Fetch data if bytes to be read. */ - if (twi->bytesRead < TWIM_READ_BUFFER_SIZE) { - uint8_t data = twi->interface->MASTER.DATA; + if( twi->bytesRead < bytesToRead ) { + uint8_t const data = twi->interface->MASTER.DATA; twi->readData[twi->bytesRead] = data; twi->bytesRead++; } - /* If buffer overflow, issue STOP and BUFFER_OVERFLOW condition. */ else { twi->interface->MASTER.CTRLC = TWI_MASTER_CMD_STOP_gc; TWI_MasterTransactionFinished(twi, TWIM_RESULT_BUFFER_OVERFLOW); } - /* Local variable used in if test to avoid compiler warning. */ - uint8_t bytesToRead = twi->bytesToRead; - /* If more bytes to read, issue ACK and start a byte read. */ - if (twi->bytesRead < bytesToRead) { + if( twi->bytesRead < bytesToRead ) { twi->interface->MASTER.CTRLC = TWI_MASTER_CMD_RECVTRANS_gc; } /* If transaction finished, issue NACK and STOP condition. */ else { - twi->interface->MASTER.CTRLC = TWI_MASTER_ACKACT_bm | + twi->interface->MASTER.CTRLC = //TWI_MASTER_ACKACT_bm | TWI_MASTER_CMD_STOP_gc; TWI_MasterTransactionFinished(twi, TWIM_RESULT_OK); } @@ -392,8 +471,9 @@ void TWI_MasterReadHandler(TWI_Master_t *twi) * \param twi The TWI_Master_t struct instance. * \param result The result of the operation. */ -void TWI_MasterTransactionFinished(TWI_Master_t *twi, uint8_t result) +static void TWI_MasterTransactionFinished(TWI_Master_t *twi, uint8_t result) { twi->result = result; twi->status = TWIM_STATUS_READY; } + -- cgit v1.2.3