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 --- avr_compiler.h | 2 + edid_injector.c | 138 ++++++++++++++++++++++++----- twi_master_driver.c | 240 +++++++++++++++++++++++++++++++++----------------- twi_master_driver.h | 59 ++++++------- twi_slave_driver.c | 52 +++++++---- twi_slave_driver.h | 34 +++---- vga_edid_injector.brd | Bin 30793 -> 30793 bytes vga_edid_injector.sch | Bin 185298 -> 185298 bytes 8 files changed, 356 insertions(+), 169 deletions(-) diff --git a/avr_compiler.h b/avr_compiler.h index 5d1c738..5c7cabc 100644 --- a/avr_compiler.h +++ b/avr_compiler.h @@ -87,6 +87,7 @@ * multiple of 1000000UL (1 MHz). */ #define delay_us( us ) ( __delay_cycles( ( F_CPU / 1000000UL ) * ( us ) ) ) +#define delay_ms( ms ) ( __delay_cycles( ( F_CPU / 100000000000L ) * ( ms ) ) ) /*! \brief Preprocessor magic. * @@ -133,6 +134,7 @@ /*! \brief Define the delay_us macro for GCC. */ #define delay_us( us ) (_delay_us( us )) +#define delay_ms( ms ) (_delay_ms( ms )) #define INLINE static inline diff --git a/edid_injector.c b/edid_injector.c index b938d85..a87fc56 100644 --- a/edid_injector.c +++ b/edid_injector.c @@ -44,7 +44,7 @@ #define BAUDRATE 100000 #define TWI_BAUDSETTING TWI_BAUD(F_CPU, BAUDRATE) -#define EDID_SLAVE_ADDRESS 0xA0 +#define EDID_SLAVE_ADDRESS 0x50 /* TWIC is on the display side */ TWI_t * const twiDisplay = &TWIC; @@ -65,23 +65,39 @@ ISR(TWIE_TWIS_vect) TWI_SlaveInterruptHandler(&twisHost); } +#define EDID_BLOCK_LENGTH 128 -void TWIC_SlaveProcessData(void) +static uint8_t edid_data[EDID_BLOCK_LENGTH]; +static uint8_t edid_offset; +static uint8_t recvbuf[1]; + +void TWIC_SlaveProcessData(TWI_Slave_t * const twi) { + if( twi->bytesReceived ) { + edid_offset = twi->recvData[0]; + } + twi->sendData = edid_data + edid_offset; + twi->bytesToSend = sizeof(edid_data) - edid_offset; } void edid_initHostTWI(void) { /* Initialize TWI slave. */ - TWI_SlaveInitializeDriver(&twisHost, twiHost, TWIC_SlaveProcessData); + TWI_SlaveInitializeDriver(&twisHost, + twiHost, + TWIC_SlaveProcessData); + TWI_SlaveInitializeModule(&twisHost, EDID_SLAVE_ADDRESS, - TWI_SLAVE_INTLVL_MED_gc ); + TWI_SLAVE_INTLVL_HI_gc, + recvbuf, + sizeof(recvbuf) ); } void edid_initDisplayTWI(void) { /* Initialize TWI master. */ + twimDisplay.status = TWIM_STATUS_READY; TWI_MasterInit(&twimDisplay, twiDisplay, TWI_MASTER_INTLVL_LO_gc, @@ -99,52 +115,128 @@ void edid_initDisplayTWI(void) } +uint8_t edid_checkData(uint8_t const *ediddata) +{ + uint8_t checksum = 0; + for(uint8_t i = 0; i < EDID_BLOCK_LENGTH; i++) { + checksum += ediddata[i]; + } + if( 0 != checksum ) { + return 1; /* checksum failed */ + } + + if( 0 != ediddata[0] ) { + return 2; /* headerbyte[0] != 0 */ + } + + for(uint8_t i = 1; i < 7; i++) { + if( 0xff != ediddata[i] ) { + return 3; /* headerbyte[1..6] != 0xff */ + } + } + + if( 0 != ediddata[7] ) { + return 4; /* headerbyte[7] != 0 */ + } + + return 0; /* EDID data passed checks */ +} + uint8_t edid_genChecksum(uint8_t *ediddata) { uint8_t bytessum = 0; - for(size_t i = 0; i < 127; i++) { + for(uint8_t i = 0; i < EDID_BLOCK_LENGTH-1; i++) { bytessum += ediddata[i]; } - return 0xff - bytessum; + return 0xff - bytessum + 1; } -void edid_readFromDisplayToEEPROM(void) +uint8_t edid_readFromDisplayToEEPROM(void) { - uint8_t displayedid[128]; - memset(displayedid, 0, sizeof(displayedid)); + uint8_t const offset[1] = {0x00}; + uint8_t displayedid[EDID_BLOCK_LENGTH]; + + uint8_t error = 0; + uint8_t retry = 20; + while( retry-- ) { + TWI_MasterForceIdle(&twimDisplay); + delay_ms(1); + + /* set EDID offset to 0 */ + if( !TWI_MasterWriteRead(&twimDisplay, + EDID_SLAVE_ADDRESS, + offset, + sizeof(offset), + displayedid, + sizeof(displayedid) ) ) { + PORTB.OUTCLR = (1<<3); + PORTB.OUTSET = (1<<3); + }; + + while( !TWI_MasterReady(&twimDisplay) ) { + delay_ms(1); + } + delay_ms(1); - /* read 128 EDID bytes from display */ + if( twimDisplay.result != TWIM_RESULT_OK ) { + error = 1; + continue; + } + + if( edid_checkData(displayedid) ) { + error = 2; + continue; + } + + break; + } + if( !retry ) { + return error; + } /* set EDID Extension Block count / flags to zero */ + displayedid[126] = 0; /* recalculate checksum */ displayedid[127] = edid_genChecksum(displayedid); /* write EDID information to EEPROM */ + memcpy(edid_data, displayedid, EDID_BLOCK_LENGTH); + + return 0; } int main(void) { - edid_initHostTWI(); + memset(edid_data, 0, sizeof(edid_data)); - edid_initDisplayTWI(); + PORTB.DIR = (1<<3); + PORTE.DIR = (1<<2) | (1<<3); + edid_initHostTWI(); + edid_initDisplayTWI(); + /* Enable LO interrupt level. */ + PMIC.CTRL |= + PMIC_LOLVLEN_bm + | PMIC_MEDLVLEN_bm + | PMIC_HILVLEN_bm; sei(); + delay_ms(20); - #if 0 - TWI_MasterWriteRead(&twiMaster, - SLAVE_ADDRESS, - &sendBuffer[BufPos], - 1, - 1); - - - while (twiMaster.status != TWIM_STATUS_READY) { - /* Wait until transaction is complete. */ - } + #if 1 + /* EDID standard requires a host to wait for 20ms after switching +5V + * supply to display before performing the first readout attempt. + * Since uC supply == display +5V supply we're waiting 20ms here. + */ + for(;;) { + edid_readFromDisplayToEEPROM(); + delay_ms(1000); + } #endif + + return 0; } 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; } + diff --git a/twi_master_driver.h b/twi_master_driver.h index c6620f7..d0e8f57 100644 --- a/twi_master_driver.h +++ b/twi_master_driver.h @@ -72,63 +72,62 @@ /*! Transaction result enumeration. */ typedef enum TWIM_RESULT_enum { - TWIM_RESULT_UNKNOWN = (0x00<<0), - TWIM_RESULT_OK = (0x01<<0), - TWIM_RESULT_BUFFER_OVERFLOW = (0x02<<0), - TWIM_RESULT_ARBITRATION_LOST = (0x03<<0), - TWIM_RESULT_BUS_ERROR = (0x04<<0), - TWIM_RESULT_NACK_RECEIVED = (0x05<<0), - TWIM_RESULT_FAIL = (0x06<<0), + TWIM_RESULT_UNKNOWN , + TWIM_RESULT_OK , + TWIM_RESULT_BUFFER_OVERFLOW , + TWIM_RESULT_ARBITRATION_LOST , + TWIM_RESULT_BUS_ERROR , + TWIM_RESULT_NACK_RECEIVED , + TWIM_RESULT_FAIL , } TWIM_RESULT_t; -/*! Buffer size defines */ -#define TWIM_WRITE_BUFFER_SIZE 8 -#define TWIM_READ_BUFFER_SIZE 8 - - /*! \brief TWI master driver struct * * TWI master struct. Holds pointer to TWI module, * buffers and necessary varibles. */ typedef struct TWI_Master { - TWI_t *interface; /*!< Pointer to what interface to use */ - register8_t address; /*!< Slave address */ - register8_t writeData[TWIM_WRITE_BUFFER_SIZE]; /*!< Data to write */ - register8_t readData[TWIM_READ_BUFFER_SIZE]; /*!< Read data */ - register8_t bytesToWrite; /*!< Number of bytes to write */ - register8_t bytesToRead; /*!< Number of bytes to read */ - register8_t bytesWritten; /*!< Number of bytes written */ - register8_t bytesRead; /*!< Number of bytes read */ - register8_t status; /*!< Status of transaction */ - register8_t result; /*!< Result of transaction */ + TWI_t *interface; /*!< Pointer to what interface to use */ + uint8_t const *writeData; /*!< Data to write */ + uint8_t *readData; /*!< Read data */ + uint8_t address; /*!< Slave address */ + uint8_t bytesToWrite; /*!< Number of bytes to write */ + uint8_t bytesToRead; /*!< Number of bytes to read */ + uint8_t bytesWritten; /*!< Number of bytes written */ + uint8_t bytesRead; /*!< Number of bytes read */ + uint8_t status; /*!< Status of transaction */ + uint8_t result; /*!< Result of transaction */ }TWI_Master_t; - - void TWI_MasterInit(TWI_Master_t *twi, TWI_t *module, TWI_MASTER_INTLVL_t intLevel, uint8_t baudRateRegisterSetting); + TWI_MASTER_BUSSTATE_t TWI_MasterState(TWI_Master_t *twi); + bool TWI_MasterReady(TWI_Master_t *twi); + +void TWI_MasterForceIdle(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_MasterRead(TWI_Master_t *twi, uint8_t address, + uint8_t * readData, uint8_t bytesToRead); + 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); + void TWI_MasterInterruptHandler(TWI_Master_t *twi); -void TWI_MasterArbitrationLostBusErrorHandler(TWI_Master_t *twi); -void TWI_MasterWriteHandler(TWI_Master_t *twi); -void TWI_MasterReadHandler(TWI_Master_t *twi); -void TWI_MasterTransactionFinished(TWI_Master_t *twi, uint8_t result); /*! TWI master interrupt service routine. diff --git a/twi_slave_driver.c b/twi_slave_driver.c index d6eecc2..341ed6f 100644 --- a/twi_slave_driver.c +++ b/twi_slave_driver.c @@ -79,7 +79,7 @@ */ void TWI_SlaveInitializeDriver(TWI_Slave_t *twi, TWI_t *module, - void (*processDataFunction) (void)) + TWI_SlaveProc processDataFunction) { twi->interface = module; twi->Process_Data = processDataFunction; @@ -102,13 +102,18 @@ void TWI_SlaveInitializeDriver(TWI_Slave_t *twi, */ void TWI_SlaveInitializeModule(TWI_Slave_t *twi, uint8_t address, - TWI_SLAVE_INTLVL_t intLevel) + TWI_SLAVE_INTLVL_t intLevel, + uint8_t *recvData, + uint8_t bytesMaxRecv ) { + twi->bytesMaxRecv = bytesMaxRecv; + twi->recvData = recvData; + twi->interface->SLAVE.CTRLA = intLevel | TWI_SLAVE_DIEN_bm | TWI_SLAVE_APIEN_bm | TWI_SLAVE_ENABLE_bm; - twi->interface->SLAVE.ADDR = (address<<1); + twi->interface->SLAVE.ADDR = (address << 1); } @@ -121,7 +126,12 @@ void TWI_SlaveInitializeModule(TWI_Slave_t *twi, */ void TWI_SlaveInterruptHandler(TWI_Slave_t *twi) { - uint8_t currentStatus = twi->interface->SLAVE.STATUS; +#if 1 + PORTE.OUTSET = (1<<2); + PORTE.OUTCLR = (1<<2); +#endif + + uint8_t const currentStatus = twi->interface->SLAVE.STATUS; /* If bus error. */ if (currentStatus & TWI_SLAVE_BUSERR_bm) { @@ -129,30 +139,30 @@ void TWI_SlaveInterruptHandler(TWI_Slave_t *twi) twi->bytesSent = 0; twi->result = TWIS_RESULT_BUS_ERROR; twi->status = TWIS_STATUS_READY; - } + } else /* If transmit collision. */ - else if (currentStatus & TWI_SLAVE_COLL_bm) { + if (currentStatus & TWI_SLAVE_COLL_bm) { twi->bytesReceived = 0; twi->bytesSent = 0; twi->result = TWIS_RESULT_TRANSMIT_COLLISION; twi->status = TWIS_STATUS_READY; - } + } else /* If address match. */ - else if ((currentStatus & TWI_SLAVE_APIF_bm) && + if ((currentStatus & TWI_SLAVE_APIF_bm) && (currentStatus & TWI_SLAVE_AP_bm)) { TWI_SlaveAddressMatchHandler(twi); - } + } else /* If stop (only enabled through slave read transaction). */ - else if (currentStatus & TWI_SLAVE_APIF_bm) { + if (currentStatus & TWI_SLAVE_APIF_bm) { TWI_SlaveStopHandler(twi); - } + } else /* If data interrupt. */ - else if (currentStatus & TWI_SLAVE_DIF_bm) { + if (currentStatus & TWI_SLAVE_DIF_bm) { TWI_SlaveDataHandler(twi); } @@ -219,7 +229,7 @@ void TWI_SlaveStopHandler(TWI_Slave_t *twi) */ void TWI_SlaveDataHandler(TWI_Slave_t *twi) { - if (twi->interface->SLAVE.STATUS & TWI_SLAVE_DIR_bm) { + if( twi->interface->SLAVE.STATUS & TWI_SLAVE_DIR_bm ) { TWI_SlaveWriteHandler(twi); } else { TWI_SlaveReadHandler(twi); @@ -235,18 +245,20 @@ void TWI_SlaveDataHandler(TWI_Slave_t *twi) */ void TWI_SlaveReadHandler(TWI_Slave_t *twi) { + uint8_t const bytesMaxRecv = twi->bytesMaxRecv; + /* Enable stop interrupt. */ uint8_t currentCtrlA = twi->interface->SLAVE.CTRLA; twi->interface->SLAVE.CTRLA = currentCtrlA | TWI_SLAVE_PIEN_bm; /* If free space in buffer. */ - if (twi->bytesReceived < TWIS_RECEIVE_BUFFER_SIZE) { + if( twi->bytesReceived < bytesMaxRecv ) { /* Fetch data */ uint8_t data = twi->interface->SLAVE.DATA; - twi->receivedData[twi->bytesReceived] = data; + twi->recvData[twi->bytesReceived] = data; /* Process data. */ - twi->Process_Data(); + twi->Process_Data(twi); twi->bytesReceived++; @@ -254,11 +266,12 @@ void TWI_SlaveReadHandler(TWI_Slave_t *twi) * complete transaction and wait for next START. Otherwise * send ACK and wait for data interrupt. */ - if (twi->abort) { + if( twi->abort ) { twi->interface->SLAVE.CTRLB = TWI_SLAVE_CMD_COMPTRANS_gc; TWI_SlaveTransactionFinished(twi, TWIS_RESULT_ABORTED); twi->abort = false; - } else { + } + else { twi->interface->SLAVE.CTRLB = TWI_SLAVE_CMD_RESPONSE_gc; } } @@ -281,6 +294,7 @@ void TWI_SlaveReadHandler(TWI_Slave_t *twi) */ void TWI_SlaveWriteHandler(TWI_Slave_t *twi) { + uint8_t const bytesToSend = twi->bytesToSend; /* If NACK, slave write transaction finished. */ if ((twi->bytesSent > 0) && (twi->interface->SLAVE.STATUS & TWI_SLAVE_RXACK_bm)) { @@ -290,7 +304,7 @@ void TWI_SlaveWriteHandler(TWI_Slave_t *twi) } /* If ACK, master expects more data. */ else { - if (twi->bytesSent < TWIS_SEND_BUFFER_SIZE) { + if( twi->bytesSent < bytesToSend ) { uint8_t data = twi->sendData[twi->bytesSent]; twi->interface->SLAVE.DATA = data; twi->bytesSent++; diff --git a/twi_slave_driver.h b/twi_slave_driver.h index c09c43b..ca10b82 100644 --- a/twi_slave_driver.h +++ b/twi_slave_driver.h @@ -77,11 +77,9 @@ typedef enum TWIS_RESULT_enum { TWIS_RESULT_ABORTED = (0x06<<0), } TWIS_RESULT_t; -/* Buffer size defines. */ -#define TWIS_RECEIVE_BUFFER_SIZE 8 -#define TWIS_SEND_BUFFER_SIZE 8 - +struct TWI_Slave; +typedef void (*TWI_SlaveProc)(struct TWI_Slave*); /*! \brief TWI slave driver struct. * @@ -89,26 +87,28 @@ typedef enum TWIS_RESULT_enum { * buffers and necessary varibles. */ typedef struct TWI_Slave { - TWI_t *interface; /*!< Pointer to what interface to use*/ - void (*Process_Data) (void); /*!< Pointer to process data function*/ - register8_t receivedData[TWIS_RECEIVE_BUFFER_SIZE]; /*!< Read data*/ - register8_t sendData[TWIS_SEND_BUFFER_SIZE]; /*!< Data to write*/ - register8_t bytesReceived; /*!< Number of bytes received*/ - register8_t bytesSent; /*!< Number of bytes sent*/ - register8_t status; /*!< Status of transaction*/ - register8_t result; /*!< Result of transaction*/ - bool abort; /*!< Strobe to abort*/ + TWI_t *interface; /*!< Pointer to what interface to use*/ + TWI_SlaveProc Process_Data; /*!< Pointer to process data function*/ + uint8_t *recvData; + uint8_t const *sendData; /*!< Data to write*/ + uint8_t bytesMaxRecv; + uint8_t bytesToSend; /*!< Number of bytes to send */ + uint8_t bytesReceived; /*!< Number of bytes received*/ + uint8_t bytesSent; /*!< Number of bytes sent*/ + uint8_t status; /*!< Status of transaction*/ + uint8_t result; /*!< Result of transaction*/ + bool abort; /*!< Strobe to abort*/ } TWI_Slave_t; - - void TWI_SlaveInitializeDriver(TWI_Slave_t *twi, TWI_t *module, - void (*processDataFunction) (void)); + TWI_SlaveProc processDataFunction); void TWI_SlaveInitializeModule(TWI_Slave_t *twi, uint8_t address, - TWI_SLAVE_INTLVL_t intLevel); + TWI_SLAVE_INTLVL_t intLevel, + uint8_t *recvData, + uint8_t bytesMaxRecv ); void TWI_SlaveInterruptHandler(TWI_Slave_t *twi); void TWI_SlaveAddressMatchHandler(TWI_Slave_t *twi); diff --git a/vga_edid_injector.brd b/vga_edid_injector.brd index 8732a34..bee5ff7 100644 Binary files a/vga_edid_injector.brd and b/vga_edid_injector.brd differ diff --git a/vga_edid_injector.sch b/vga_edid_injector.sch index 48ff306..ee42e43 100644 Binary files a/vga_edid_injector.sch and b/vga_edid_injector.sch differ -- cgit v1.2.3