reading EDID information from display and submission to host works
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
138
edid_injector.c
138
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];
|
||||
|
||||
/* read 128 EDID bytes from display */
|
||||
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);
|
||||
|
||||
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));
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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++;
|
||||
|
||||
@@ -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);
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user