reading EDID information from display and submission to host works
This commit is contained in:
		| @@ -87,6 +87,7 @@ | |||||||
|  *        multiple of 1000000UL (1 MHz). |  *        multiple of 1000000UL (1 MHz). | ||||||
|  */ |  */ | ||||||
| #define delay_us( us )   ( __delay_cycles( ( F_CPU / 1000000UL ) * ( us ) ) ) | #define delay_us( us )   ( __delay_cycles( ( F_CPU / 1000000UL ) * ( us ) ) ) | ||||||
|  | #define delay_ms( ms )   ( __delay_cycles( ( F_CPU / 100000000000L ) * ( ms ) ) ) | ||||||
|  |  | ||||||
| /*! \brief Preprocessor magic. | /*! \brief Preprocessor magic. | ||||||
|  * |  * | ||||||
| @@ -133,6 +134,7 @@ | |||||||
|  |  | ||||||
| /*! \brief Define the delay_us macro for GCC. */ | /*! \brief Define the delay_us macro for GCC. */ | ||||||
| #define delay_us( us )   (_delay_us( us )) | #define delay_us( us )   (_delay_us( us )) | ||||||
|  | #define delay_ms( ms )   (_delay_ms( ms )) | ||||||
|  |  | ||||||
| #define INLINE static inline | #define INLINE static inline | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										138
									
								
								edid_injector.c
									
									
									
									
									
								
							
							
						
						
									
										138
									
								
								edid_injector.c
									
									
									
									
									
								
							| @@ -44,7 +44,7 @@ | |||||||
| #define BAUDRATE	100000 | #define BAUDRATE	100000 | ||||||
| #define TWI_BAUDSETTING TWI_BAUD(F_CPU, BAUDRATE) | #define TWI_BAUDSETTING TWI_BAUD(F_CPU, BAUDRATE) | ||||||
|  |  | ||||||
| #define EDID_SLAVE_ADDRESS 0xA0 | #define EDID_SLAVE_ADDRESS 0x50 | ||||||
|  |  | ||||||
| /* TWIC is on the display side */ | /* TWIC is on the display side */ | ||||||
| TWI_t * const twiDisplay = &TWIC; | TWI_t * const twiDisplay = &TWIC; | ||||||
| @@ -65,23 +65,39 @@ ISR(TWIE_TWIS_vect) | |||||||
| 	TWI_SlaveInterruptHandler(&twisHost); | 	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) | void edid_initHostTWI(void) | ||||||
| { | { | ||||||
| 	/* Initialize TWI slave. */ | 	/* Initialize TWI slave. */ | ||||||
| 	TWI_SlaveInitializeDriver(&twisHost, twiHost, TWIC_SlaveProcessData); | 	TWI_SlaveInitializeDriver(&twisHost, | ||||||
|  | 		twiHost, | ||||||
|  | 		TWIC_SlaveProcessData); | ||||||
|  |  | ||||||
| 	TWI_SlaveInitializeModule(&twisHost, | 	TWI_SlaveInitializeModule(&twisHost, | ||||||
| 		EDID_SLAVE_ADDRESS, | 		EDID_SLAVE_ADDRESS, | ||||||
| 		TWI_SLAVE_INTLVL_MED_gc ); | 		TWI_SLAVE_INTLVL_HI_gc, | ||||||
|  | 		recvbuf, | ||||||
|  | 		sizeof(recvbuf) ); | ||||||
| } | } | ||||||
|  |  | ||||||
| void edid_initDisplayTWI(void) | void edid_initDisplayTWI(void) | ||||||
| { | { | ||||||
| 	/* Initialize TWI master. */ | 	/* Initialize TWI master. */ | ||||||
|  | 	twimDisplay.status = TWIM_STATUS_READY; | ||||||
| 	TWI_MasterInit(&twimDisplay, | 	TWI_MasterInit(&twimDisplay, | ||||||
| 	               twiDisplay, | 	               twiDisplay, | ||||||
| 	               TWI_MASTER_INTLVL_LO_gc, | 	               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 edid_genChecksum(uint8_t *ediddata) | ||||||
| { | { | ||||||
| 	uint8_t bytessum = 0; | 	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]; | 		bytessum += ediddata[i]; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return 0xff - bytessum; | 	return 0xff - bytessum + 1; | ||||||
| } | } | ||||||
|  |  | ||||||
| void edid_readFromDisplayToEEPROM(void) | uint8_t edid_readFromDisplayToEEPROM(void) | ||||||
| { | { | ||||||
| 	uint8_t displayedid[128]; | 	uint8_t const offset[1] = {0x00}; | ||||||
| 	memset(displayedid, 0, sizeof(displayedid)); | 	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 */ | 	/* set EDID Extension Block count / flags to zero */ | ||||||
|  | 	displayedid[126] = 0; | ||||||
|  |  | ||||||
| 	/* recalculate checksum */ | 	/* recalculate checksum */ | ||||||
| 	displayedid[127] = edid_genChecksum(displayedid); | 	displayedid[127] = edid_genChecksum(displayedid); | ||||||
|  |  | ||||||
| 	/* write EDID information to EEPROM */ | 	/* write EDID information to EEPROM */ | ||||||
|  | 	memcpy(edid_data, displayedid, EDID_BLOCK_LENGTH); | ||||||
|  |  | ||||||
|  | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| int main(void) | 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(); | 	edid_initDisplayTWI(); | ||||||
|  |  | ||||||
|  | 	/* Enable LO interrupt level. */ | ||||||
|  | 	PMIC.CTRL |= | ||||||
|  | 		  PMIC_LOLVLEN_bm | ||||||
|  | 		| PMIC_MEDLVLEN_bm | ||||||
|  | 		| PMIC_HILVLEN_bm; | ||||||
| 	sei(); | 	sei(); | ||||||
|  |  | ||||||
|  | 	delay_ms(20);  | ||||||
|  |  | ||||||
| 	#if 0 | 	#if 1 | ||||||
| 		TWI_MasterWriteRead(&twiMaster, | 	/* EDID standard requires a host to wait for 20ms after switching +5V | ||||||
| 		                    SLAVE_ADDRESS, | 	 * supply to display before performing the first readout attempt. | ||||||
| 		                    &sendBuffer[BufPos], | 	 * Since uC supply == display +5V supply we're waiting 20ms here. | ||||||
| 		                    1, | 	 */ | ||||||
| 		                    1); | 	for(;;) { | ||||||
|  | 		edid_readFromDisplayToEEPROM(); | ||||||
|  | 		delay_ms(1000);  | ||||||
| 		while (twiMaster.status != TWIM_STATUS_READY) { | 	} | ||||||
| 			/* Wait until transaction is complete. */ |  | ||||||
| 		} |  | ||||||
| 	#endif | 	#endif | ||||||
|  |  | ||||||
|  | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -68,6 +68,10 @@ | |||||||
|  |  | ||||||
| #include "twi_master_driver.h" | #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. | /*! \brief Initialize the TWI module. | ||||||
|  * |  * | ||||||
| @@ -86,14 +90,28 @@ void TWI_MasterInit(TWI_Master_t *twi, | |||||||
|                     uint8_t baudRateRegisterSetting) |                     uint8_t baudRateRegisterSetting) | ||||||
| { | { | ||||||
| 	twi->interface = module; | 	twi->interface = module; | ||||||
|  | 	twi->interface->CTRL = TWI_SDAHOLD_bm; | ||||||
| 	twi->interface->MASTER.CTRLA = intLevel | | 	twi->interface->MASTER.CTRLA = intLevel | | ||||||
| 	                               TWI_MASTER_RIEN_bm | | 	                               TWI_MASTER_RIEN_bm | | ||||||
| 	                               TWI_MASTER_WIEN_bm | | 	                               TWI_MASTER_WIEN_bm | | ||||||
| 	                               TWI_MASTER_ENABLE_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.BAUD = baudRateRegisterSetting; | ||||||
| 	twi->interface->MASTER.STATUS = TWI_MASTER_BUSSTATE_IDLE_gc; | 	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. | /*! \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_MasterReady(TWI_Master_t *twi) | ||||||
| { | { | ||||||
| 	bool twi_status = (twi->status & TWIM_STATUS_READY); | 	bool twi_status = (twi->status == TWIM_STATUS_READY); | ||||||
| 	return twi_status; | 	return twi_status; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -147,10 +165,14 @@ bool TWI_MasterReady(TWI_Master_t *twi) | |||||||
|  */ |  */ | ||||||
| bool TWI_MasterWrite(TWI_Master_t *twi, | bool TWI_MasterWrite(TWI_Master_t *twi, | ||||||
|                      uint8_t address, |                      uint8_t address, | ||||||
|                      uint8_t *writeData, |                      uint8_t const *writeData, | ||||||
|                      uint8_t bytesToWrite) |                      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; | 	return twi_status; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -168,9 +190,14 @@ bool TWI_MasterWrite(TWI_Master_t *twi, | |||||||
|  */ |  */ | ||||||
| bool TWI_MasterRead(TWI_Master_t *twi, | bool TWI_MasterRead(TWI_Master_t *twi, | ||||||
|                     uint8_t address, |                     uint8_t address, | ||||||
|  | 		    uint8_t *readData, | ||||||
|                     uint8_t bytesToRead) |                     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; | 	return twi_status; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -192,55 +219,57 @@ bool TWI_MasterRead(TWI_Master_t *twi, | |||||||
|  */ |  */ | ||||||
| bool TWI_MasterWriteRead(TWI_Master_t *twi, | bool TWI_MasterWriteRead(TWI_Master_t *twi, | ||||||
|                          uint8_t address, |                          uint8_t address, | ||||||
|                          uint8_t *writeData, |                          uint8_t const *writeData, | ||||||
|                          uint8_t bytesToWrite, |                          uint8_t bytesToWrite, | ||||||
|  | 			 uint8_t *readData, | ||||||
|                          uint8_t bytesToRead) |                          uint8_t bytesToRead) | ||||||
| { | { | ||||||
| 	/*Parameter sanity check. */ | 	if( !bytesToWrite || !writeData ) { | ||||||
| 	if (bytesToWrite > TWIM_WRITE_BUFFER_SIZE) { | 		writeData = NULL; | ||||||
| 		return false; | 		bytesToWrite = 0; | ||||||
| 	} | 	} | ||||||
| 	if (bytesToRead > TWIM_READ_BUFFER_SIZE) { | 	if( !bytesToRead || !readData ) { | ||||||
| 		return false; | 		readData = NULL; | ||||||
|  | 		bytesToRead = 0; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/*Initiate transaction if bus is ready. */ | 	/*Initiate transaction if bus is ready. */ | ||||||
| 	if (twi->status == TWIM_STATUS_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 { |  | ||||||
| 		return false; | 		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) | 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 arbitration lost or bus error. */ | ||||||
| 	if ((currentStatus & TWI_MASTER_ARBLOST_bm) || | 	if ((currentStatus & TWI_MASTER_ARBLOST_bm) || | ||||||
| 	    (currentStatus & TWI_MASTER_BUSERR_bm)) { | 	    (currentStatus & TWI_MASTER_BUSERR_bm)) { | ||||||
|  | #if 0 | ||||||
|  | 	PORTB.OUTSET = (1<<3); | ||||||
|  | 	PORTB.OUTCLR = (1<<3); | ||||||
|  | #endif | ||||||
|  |  | ||||||
| 		TWI_MasterArbitrationLostBusErrorHandler(twi); | 		TWI_MasterArbitrationLostBusErrorHandler(twi); | ||||||
| 	} | 		twi->interface->MASTER.STATUS = | ||||||
|  | 			  currentStatus | ||||||
|  | 			| TWI_MASTER_ARBLOST_bm | ||||||
|  | 			| TWI_MASTER_BUSERR_bm; | ||||||
|  | 	} else | ||||||
| 	/* If master write interrupt. */ | 	/* 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_MasterWriteHandler(twi); | ||||||
| 	} |  | ||||||
|  |  | ||||||
|  | 		twi->interface->MASTER.STATUS = | ||||||
|  | 			  currentStatus | ||||||
|  | 			| TWI_MASTER_WIF_bm; | ||||||
|  | 	} else | ||||||
| 	/* If master read interrupt. */ | 	/* 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_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. */ | 	/* If unexpected state. */ | ||||||
| 	else { | 	else { | ||||||
|  | #if 0 | ||||||
|  | 	PORTB.OUTSET = (1<<3); | ||||||
|  | 	PORTB.OUTCLR = (1<<3); | ||||||
|  | #endif | ||||||
| 		TWI_MasterTransactionFinished(twi, TWIM_RESULT_FAIL); | 		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. |  *  \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 bus error. */ | ||||||
| 	if (currentStatus & TWI_MASTER_BUSERR_bm) { | 	if (currentStatus & TWI_MASTER_BUSERR_bm) { | ||||||
| @@ -297,9 +362,6 @@ void TWI_MasterArbitrationLostBusErrorHandler(TWI_Master_t *twi) | |||||||
| 		twi->result = TWIM_RESULT_ARBITRATION_LOST; | 		twi->result = TWIM_RESULT_ARBITRATION_LOST; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/* Clear interrupt flag. */ |  | ||||||
| 	twi->interface->MASTER.STATUS = currentStatus | TWI_MASTER_ARBLOST_bm; |  | ||||||
|  |  | ||||||
| 	twi->status = TWIM_STATUS_READY; | 	twi->status = TWIM_STATUS_READY; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -310,36 +372,49 @@ void TWI_MasterArbitrationLostBusErrorHandler(TWI_Master_t *twi) | |||||||
|  * |  * | ||||||
|  *  \param twi The TWI_Master_t struct instance. |  *  \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. */ | 	/* Local variables used in if tests to avoid compiler warning. */ | ||||||
| 	uint8_t bytesToWrite  = twi->bytesToWrite; | 	uint8_t const bytesToWrite  = twi->bytesToWrite; | ||||||
| 	uint8_t bytesToRead   = twi->bytesToRead; | 	uint8_t const bytesToRead   = twi->bytesToRead; | ||||||
|  |  | ||||||
| 	/* If NOT acknowledged (NACK) by slave cancel the transaction. */ | 	/* 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->interface->MASTER.CTRLC = TWI_MASTER_CMD_STOP_gc; | ||||||
| 		twi->result = TWIM_RESULT_NACK_RECEIVED; | 		twi->result = TWIM_RESULT_NACK_RECEIVED; | ||||||
| 		twi->status = TWIM_STATUS_READY; | 		twi->status = TWIM_STATUS_READY; | ||||||
| 	} | 	} else | ||||||
|  |  | ||||||
| 	/* If more bytes to write, send data. */ | 	/* If more bytes to write, send data. */ | ||||||
| 	else if (twi->bytesWritten < bytesToWrite) { | 	if( twi->bytesWritten < bytesToWrite ) { | ||||||
| 		uint8_t data = twi->writeData[twi->bytesWritten]; | #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->interface->MASTER.DATA = data; | ||||||
| 		++twi->bytesWritten; | 		twi->bytesWritten++; | ||||||
| 	} | 	} else | ||||||
|  |  | ||||||
| 	/* If bytes to read, send repeated START condition + Address + | 	/* If bytes to read, send repeated START condition + Address + | ||||||
| 	 * 'R/_W = 1' | 	 * 'R/_W = 1' | ||||||
| 	 */ | 	 */ | ||||||
| 	else if (twi->bytesRead < bytesToRead) { | 	if( twi->bytesRead < bytesToRead ) { | ||||||
| 		uint8_t readAddress = twi->address | 0x01; | #if 0 | ||||||
|  | 	PORTB.OUTSET = (1<<3); | ||||||
|  | 	PORTB.OUTCLR = (1<<3); | ||||||
|  | #endif | ||||||
|  | 		uint8_t const readAddress = twi->address | 0x01; | ||||||
| 		twi->interface->MASTER.ADDR = readAddress; | 		twi->interface->MASTER.ADDR = readAddress; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/* If transaction finished, send STOP condition and set RESULT OK. */ | 	/* If transaction finished, send STOP condition and set RESULT OK. */ | ||||||
| 	else { | 	else { | ||||||
|  | #if 0 | ||||||
|  | 	PORTB.OUTSET = (1<<3); | ||||||
|  | 	PORTB.OUTCLR = (1<<3); | ||||||
|  | #endif | ||||||
| 		twi->interface->MASTER.CTRLC = TWI_MASTER_CMD_STOP_gc; | 		twi->interface->MASTER.CTRLC = TWI_MASTER_CMD_STOP_gc; | ||||||
| 		TWI_MasterTransactionFinished(twi, TWIM_RESULT_OK); | 		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. |  *  \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. */ | 	/* Fetch data if bytes to be read. */ | ||||||
| 	if (twi->bytesRead < TWIM_READ_BUFFER_SIZE) { | 	if( twi->bytesRead < bytesToRead ) { | ||||||
| 		uint8_t data = twi->interface->MASTER.DATA; | 		uint8_t const data = twi->interface->MASTER.DATA; | ||||||
| 		twi->readData[twi->bytesRead] = data; | 		twi->readData[twi->bytesRead] = data; | ||||||
| 		twi->bytesRead++; | 		twi->bytesRead++; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/* If buffer overflow, issue STOP and BUFFER_OVERFLOW condition. */ | 	/* If buffer overflow, issue STOP and BUFFER_OVERFLOW condition. */ | ||||||
| 	else { | 	else { | ||||||
| 		twi->interface->MASTER.CTRLC = TWI_MASTER_CMD_STOP_gc; | 		twi->interface->MASTER.CTRLC = TWI_MASTER_CMD_STOP_gc; | ||||||
| 		TWI_MasterTransactionFinished(twi, TWIM_RESULT_BUFFER_OVERFLOW); | 		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 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; | 		twi->interface->MASTER.CTRLC = TWI_MASTER_CMD_RECVTRANS_gc; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/* If transaction finished, issue NACK and STOP condition. */ | 	/* If transaction finished, issue NACK and STOP condition. */ | ||||||
| 	else { | 	else { | ||||||
| 		twi->interface->MASTER.CTRLC = TWI_MASTER_ACKACT_bm | | 		twi->interface->MASTER.CTRLC = //TWI_MASTER_ACKACT_bm | | ||||||
| 		                               TWI_MASTER_CMD_STOP_gc; | 		                               TWI_MASTER_CMD_STOP_gc; | ||||||
| 		TWI_MasterTransactionFinished(twi, TWIM_RESULT_OK); | 		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 twi     The TWI_Master_t struct instance. | ||||||
|  *  \param result  The result of the operation. |  *  \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->result = result; | ||||||
| 	twi->status = TWIM_STATUS_READY; | 	twi->status = TWIM_STATUS_READY; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -72,63 +72,62 @@ | |||||||
|  |  | ||||||
| /*! Transaction result enumeration. */ | /*! Transaction result enumeration. */ | ||||||
| typedef enum TWIM_RESULT_enum { | typedef enum TWIM_RESULT_enum { | ||||||
| 	TWIM_RESULT_UNKNOWN          = (0x00<<0), | 	TWIM_RESULT_UNKNOWN          , | ||||||
| 	TWIM_RESULT_OK               = (0x01<<0), | 	TWIM_RESULT_OK               , | ||||||
| 	TWIM_RESULT_BUFFER_OVERFLOW  = (0x02<<0), | 	TWIM_RESULT_BUFFER_OVERFLOW  , | ||||||
| 	TWIM_RESULT_ARBITRATION_LOST = (0x03<<0), | 	TWIM_RESULT_ARBITRATION_LOST , | ||||||
| 	TWIM_RESULT_BUS_ERROR        = (0x04<<0), | 	TWIM_RESULT_BUS_ERROR        , | ||||||
| 	TWIM_RESULT_NACK_RECEIVED    = (0x05<<0), | 	TWIM_RESULT_NACK_RECEIVED    , | ||||||
| 	TWIM_RESULT_FAIL             = (0x06<<0), | 	TWIM_RESULT_FAIL             , | ||||||
| } TWIM_RESULT_t; | } TWIM_RESULT_t; | ||||||
|  |  | ||||||
| /*! Buffer size defines */ |  | ||||||
| #define TWIM_WRITE_BUFFER_SIZE         8 |  | ||||||
| #define TWIM_READ_BUFFER_SIZE          8 |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /*! \brief TWI master driver struct | /*! \brief TWI master driver struct | ||||||
|  * |  * | ||||||
|  *  TWI master struct. Holds pointer to TWI module, |  *  TWI master struct. Holds pointer to TWI module, | ||||||
|  *  buffers and necessary varibles. |  *  buffers and necessary varibles. | ||||||
|  */ |  */ | ||||||
| typedef struct TWI_Master { | typedef struct TWI_Master { | ||||||
| 	TWI_t *interface;                  /*!< Pointer to what interface to use */ | 	TWI_t *interface;         /*!< Pointer to what interface to use */ | ||||||
| 	register8_t address;                            /*!< Slave address */ | 	uint8_t const *writeData; /*!< Data to write */ | ||||||
| 	register8_t writeData[TWIM_WRITE_BUFFER_SIZE];  /*!< Data to write */ | 	uint8_t *readData;        /*!< Read data */ | ||||||
| 	register8_t readData[TWIM_READ_BUFFER_SIZE];    /*!< Read data */ | 	uint8_t address;      /*!< Slave address */ | ||||||
| 	register8_t bytesToWrite;                       /*!< Number of bytes to write */ | 	uint8_t bytesToWrite; /*!< Number of bytes to write */ | ||||||
| 	register8_t bytesToRead;                        /*!< Number of bytes to read */ | 	uint8_t bytesToRead;  /*!< Number of bytes to read */ | ||||||
| 	register8_t bytesWritten;                       /*!< Number of bytes written */ | 	uint8_t bytesWritten; /*!< Number of bytes written */ | ||||||
| 	register8_t bytesRead;                          /*!< Number of bytes read */ | 	uint8_t bytesRead;    /*!< Number of bytes read */ | ||||||
| 	register8_t status;                             /*!< Status of transaction */ | 	uint8_t status;       /*!< Status of transaction */ | ||||||
| 	register8_t result;                             /*!< Result of transaction */ | 	uint8_t result;       /*!< Result of transaction */ | ||||||
| }TWI_Master_t; | }TWI_Master_t; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| void TWI_MasterInit(TWI_Master_t *twi, | void TWI_MasterInit(TWI_Master_t *twi, | ||||||
|                     TWI_t *module, |                     TWI_t *module, | ||||||
|                     TWI_MASTER_INTLVL_t intLevel, |                     TWI_MASTER_INTLVL_t intLevel, | ||||||
|                     uint8_t baudRateRegisterSetting); |                     uint8_t baudRateRegisterSetting); | ||||||
|  |  | ||||||
| TWI_MASTER_BUSSTATE_t TWI_MasterState(TWI_Master_t *twi); | TWI_MASTER_BUSSTATE_t TWI_MasterState(TWI_Master_t *twi); | ||||||
|  |  | ||||||
| bool TWI_MasterReady(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, | bool TWI_MasterWrite(TWI_Master_t *twi, | ||||||
|                      uint8_t address, |                      uint8_t address, | ||||||
|                      uint8_t * writeData, |                      uint8_t const * writeData, | ||||||
|                      uint8_t bytesToWrite); |                      uint8_t bytesToWrite); | ||||||
|  |  | ||||||
| bool TWI_MasterRead(TWI_Master_t *twi, | bool TWI_MasterRead(TWI_Master_t *twi, | ||||||
|                     uint8_t address, |                     uint8_t address, | ||||||
|  | 		    uint8_t * readData, | ||||||
|                     uint8_t bytesToRead); |                     uint8_t bytesToRead); | ||||||
|  |  | ||||||
| bool TWI_MasterWriteRead(TWI_Master_t *twi, | bool TWI_MasterWriteRead(TWI_Master_t *twi, | ||||||
|                          uint8_t address, |                          uint8_t address, | ||||||
|                          uint8_t *writeData, |                          uint8_t const *writeData, | ||||||
|                          uint8_t bytesToWrite, |                          uint8_t bytesToWrite, | ||||||
|  | 			 uint8_t *readData, | ||||||
|                          uint8_t bytesToRead); |                          uint8_t bytesToRead); | ||||||
|  |  | ||||||
| void TWI_MasterInterruptHandler(TWI_Master_t *twi); | 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. | /*! TWI master interrupt service routine. | ||||||
|   | |||||||
| @@ -79,7 +79,7 @@ | |||||||
|  */ |  */ | ||||||
| void TWI_SlaveInitializeDriver(TWI_Slave_t *twi, | void TWI_SlaveInitializeDriver(TWI_Slave_t *twi, | ||||||
|                                TWI_t *module, |                                TWI_t *module, | ||||||
|                                void (*processDataFunction) (void)) |                                TWI_SlaveProc processDataFunction) | ||||||
| { | { | ||||||
| 	twi->interface = module; | 	twi->interface = module; | ||||||
| 	twi->Process_Data = processDataFunction; | 	twi->Process_Data = processDataFunction; | ||||||
| @@ -102,13 +102,18 @@ void TWI_SlaveInitializeDriver(TWI_Slave_t *twi, | |||||||
|  */ |  */ | ||||||
| void TWI_SlaveInitializeModule(TWI_Slave_t *twi, | void TWI_SlaveInitializeModule(TWI_Slave_t *twi, | ||||||
|                                uint8_t address, |                                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->interface->SLAVE.CTRLA = intLevel | | ||||||
| 	                              TWI_SLAVE_DIEN_bm | | 	                              TWI_SLAVE_DIEN_bm | | ||||||
| 	                              TWI_SLAVE_APIEN_bm | | 	                              TWI_SLAVE_APIEN_bm | | ||||||
| 	                              TWI_SLAVE_ENABLE_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) | 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 bus error. */ | ||||||
| 	if (currentStatus & TWI_SLAVE_BUSERR_bm) { | 	if (currentStatus & TWI_SLAVE_BUSERR_bm) { | ||||||
| @@ -129,30 +139,30 @@ void TWI_SlaveInterruptHandler(TWI_Slave_t *twi) | |||||||
| 		twi->bytesSent = 0; | 		twi->bytesSent = 0; | ||||||
| 		twi->result = TWIS_RESULT_BUS_ERROR; | 		twi->result = TWIS_RESULT_BUS_ERROR; | ||||||
| 		twi->status = TWIS_STATUS_READY; | 		twi->status = TWIS_STATUS_READY; | ||||||
| 	} | 	} else | ||||||
|  |  | ||||||
| 	/* If transmit collision. */ | 	/* If transmit collision. */ | ||||||
| 	else if (currentStatus & TWI_SLAVE_COLL_bm) { | 	if (currentStatus & TWI_SLAVE_COLL_bm) { | ||||||
| 		twi->bytesReceived = 0; | 		twi->bytesReceived = 0; | ||||||
| 		twi->bytesSent = 0; | 		twi->bytesSent = 0; | ||||||
| 		twi->result = TWIS_RESULT_TRANSMIT_COLLISION; | 		twi->result = TWIS_RESULT_TRANSMIT_COLLISION; | ||||||
| 		twi->status = TWIS_STATUS_READY; | 		twi->status = TWIS_STATUS_READY; | ||||||
| 	} | 	} else | ||||||
|  |  | ||||||
| 	/* If address match. */ | 	/* If address match. */ | ||||||
| 	else if ((currentStatus & TWI_SLAVE_APIF_bm) && | 	if ((currentStatus & TWI_SLAVE_APIF_bm) && | ||||||
| 	        (currentStatus & TWI_SLAVE_AP_bm)) { | 	        (currentStatus & TWI_SLAVE_AP_bm)) { | ||||||
|  |  | ||||||
| 		TWI_SlaveAddressMatchHandler(twi); | 		TWI_SlaveAddressMatchHandler(twi); | ||||||
| 	} | 	} else | ||||||
|  |  | ||||||
| 	/* If stop (only enabled through slave read transaction). */ | 	/* If stop (only enabled through slave read transaction). */ | ||||||
| 	else if (currentStatus & TWI_SLAVE_APIF_bm) { | 	if (currentStatus & TWI_SLAVE_APIF_bm) { | ||||||
| 		TWI_SlaveStopHandler(twi); | 		TWI_SlaveStopHandler(twi); | ||||||
| 	} | 	} else | ||||||
|  |  | ||||||
| 	/* If data interrupt. */ | 	/* If data interrupt. */ | ||||||
| 	else if (currentStatus & TWI_SLAVE_DIF_bm) { | 	if (currentStatus & TWI_SLAVE_DIF_bm) { | ||||||
| 		TWI_SlaveDataHandler(twi); | 		TWI_SlaveDataHandler(twi); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -219,7 +229,7 @@ void TWI_SlaveStopHandler(TWI_Slave_t *twi) | |||||||
|  */ |  */ | ||||||
| void TWI_SlaveDataHandler(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); | 		TWI_SlaveWriteHandler(twi); | ||||||
| 	} else { | 	} else { | ||||||
| 		TWI_SlaveReadHandler(twi); | 		TWI_SlaveReadHandler(twi); | ||||||
| @@ -235,18 +245,20 @@ void TWI_SlaveDataHandler(TWI_Slave_t *twi) | |||||||
|  */ |  */ | ||||||
| void TWI_SlaveReadHandler(TWI_Slave_t *twi) | void TWI_SlaveReadHandler(TWI_Slave_t *twi) | ||||||
| { | { | ||||||
|  | 	uint8_t const bytesMaxRecv = twi->bytesMaxRecv; | ||||||
|  |  | ||||||
| 	/* Enable stop interrupt. */ | 	/* Enable stop interrupt. */ | ||||||
| 	uint8_t currentCtrlA = twi->interface->SLAVE.CTRLA; | 	uint8_t currentCtrlA = twi->interface->SLAVE.CTRLA; | ||||||
| 	twi->interface->SLAVE.CTRLA = currentCtrlA | TWI_SLAVE_PIEN_bm; | 	twi->interface->SLAVE.CTRLA = currentCtrlA | TWI_SLAVE_PIEN_bm; | ||||||
|  |  | ||||||
| 	/* If free space in buffer. */ | 	/* If free space in buffer. */ | ||||||
| 	if (twi->bytesReceived < TWIS_RECEIVE_BUFFER_SIZE) { | 	if( twi->bytesReceived < bytesMaxRecv ) { | ||||||
| 		/* Fetch data */ | 		/* Fetch data */ | ||||||
| 		uint8_t data = twi->interface->SLAVE.DATA; | 		uint8_t data = twi->interface->SLAVE.DATA; | ||||||
| 		twi->receivedData[twi->bytesReceived] = data; | 		twi->recvData[twi->bytesReceived] = data; | ||||||
|  |  | ||||||
| 		/* Process data. */ | 		/* Process data. */ | ||||||
| 		twi->Process_Data(); | 		twi->Process_Data(twi); | ||||||
|  |  | ||||||
| 		twi->bytesReceived++; | 		twi->bytesReceived++; | ||||||
|  |  | ||||||
| @@ -254,11 +266,12 @@ void TWI_SlaveReadHandler(TWI_Slave_t *twi) | |||||||
| 		 * complete transaction and wait for next START. Otherwise | 		 * complete transaction and wait for next START. Otherwise | ||||||
| 		 * send ACK and wait for data interrupt. | 		 * send ACK and wait for data interrupt. | ||||||
| 		 */ | 		 */ | ||||||
| 		if (twi->abort) { | 		if( twi->abort ) { | ||||||
| 			twi->interface->SLAVE.CTRLB = TWI_SLAVE_CMD_COMPTRANS_gc; | 			twi->interface->SLAVE.CTRLB = TWI_SLAVE_CMD_COMPTRANS_gc; | ||||||
| 			TWI_SlaveTransactionFinished(twi, TWIS_RESULT_ABORTED); | 			TWI_SlaveTransactionFinished(twi, TWIS_RESULT_ABORTED); | ||||||
| 			twi->abort = false; | 			twi->abort = false; | ||||||
| 		} else { | 		} | ||||||
|  | 		else { | ||||||
| 			twi->interface->SLAVE.CTRLB = TWI_SLAVE_CMD_RESPONSE_gc; | 			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) | void TWI_SlaveWriteHandler(TWI_Slave_t *twi) | ||||||
| { | { | ||||||
|  | 	uint8_t const bytesToSend = twi->bytesToSend; | ||||||
| 	/* If NACK, slave write transaction finished. */ | 	/* If NACK, slave write transaction finished. */ | ||||||
| 	if ((twi->bytesSent > 0) && (twi->interface->SLAVE.STATUS & | 	if ((twi->bytesSent > 0) && (twi->interface->SLAVE.STATUS & | ||||||
| 	                             TWI_SLAVE_RXACK_bm)) { | 	                             TWI_SLAVE_RXACK_bm)) { | ||||||
| @@ -290,7 +304,7 @@ void TWI_SlaveWriteHandler(TWI_Slave_t *twi) | |||||||
| 	} | 	} | ||||||
| 	/* If ACK, master expects more data. */ | 	/* If ACK, master expects more data. */ | ||||||
| 	else { | 	else { | ||||||
| 		if (twi->bytesSent < TWIS_SEND_BUFFER_SIZE) { | 		if( twi->bytesSent < bytesToSend ) { | ||||||
| 			uint8_t data = twi->sendData[twi->bytesSent]; | 			uint8_t data = twi->sendData[twi->bytesSent]; | ||||||
| 			twi->interface->SLAVE.DATA = data; | 			twi->interface->SLAVE.DATA = data; | ||||||
| 			twi->bytesSent++; | 			twi->bytesSent++; | ||||||
|   | |||||||
| @@ -77,11 +77,9 @@ typedef enum TWIS_RESULT_enum { | |||||||
| 	TWIS_RESULT_ABORTED            = (0x06<<0), | 	TWIS_RESULT_ABORTED            = (0x06<<0), | ||||||
| } TWIS_RESULT_t; | } TWIS_RESULT_t; | ||||||
|  |  | ||||||
| /* Buffer size defines. */ | struct TWI_Slave; | ||||||
| #define TWIS_RECEIVE_BUFFER_SIZE         8 |  | ||||||
| #define TWIS_SEND_BUFFER_SIZE            8 |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | typedef void (*TWI_SlaveProc)(struct TWI_Slave*); | ||||||
|  |  | ||||||
| /*! \brief TWI slave driver struct. | /*! \brief TWI slave driver struct. | ||||||
|  * |  * | ||||||
| @@ -89,26 +87,28 @@ typedef enum TWIS_RESULT_enum { | |||||||
|  *  buffers and necessary varibles. |  *  buffers and necessary varibles. | ||||||
|  */ |  */ | ||||||
| typedef struct TWI_Slave { | typedef struct TWI_Slave { | ||||||
| 	TWI_t *interface;                               /*!< Pointer to what interface to use*/ | 	TWI_t *interface;           /*!< Pointer to what interface to use*/ | ||||||
| 	void (*Process_Data) (void);                    /*!< Pointer to process data function*/ | 	TWI_SlaveProc Process_Data; /*!< Pointer to process data function*/ | ||||||
| 	register8_t receivedData[TWIS_RECEIVE_BUFFER_SIZE]; /*!< Read data*/ | 	uint8_t *recvData; | ||||||
| 	register8_t sendData[TWIS_SEND_BUFFER_SIZE];        /*!< Data to write*/ | 	uint8_t const *sendData;    /*!< Data to write*/ | ||||||
| 	register8_t bytesReceived;                          /*!< Number of bytes received*/ | 	uint8_t bytesMaxRecv; | ||||||
| 	register8_t bytesSent;                              /*!< Number of bytes sent*/ | 	uint8_t bytesToSend;        /*!< Number of bytes to send */ | ||||||
| 	register8_t status;                                 /*!< Status of transaction*/ | 	uint8_t bytesReceived;      /*!< Number of bytes received*/ | ||||||
| 	register8_t result;                                 /*!< Result of transaction*/ | 	uint8_t bytesSent;          /*!< Number of bytes sent*/ | ||||||
| 	bool abort;                                     /*!< Strobe to abort*/ | 	uint8_t status;             /*!< Status of transaction*/ | ||||||
|  | 	uint8_t result;             /*!< Result of transaction*/ | ||||||
|  | 	bool abort;                 /*!< Strobe to abort*/ | ||||||
| } TWI_Slave_t; | } TWI_Slave_t; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| void TWI_SlaveInitializeDriver(TWI_Slave_t *twi, | void TWI_SlaveInitializeDriver(TWI_Slave_t *twi, | ||||||
|                                TWI_t *module, |                                TWI_t *module, | ||||||
|                                void (*processDataFunction) (void)); |                                TWI_SlaveProc processDataFunction); | ||||||
|  |  | ||||||
| void TWI_SlaveInitializeModule(TWI_Slave_t *twi, | void TWI_SlaveInitializeModule(TWI_Slave_t *twi, | ||||||
|                                uint8_t address, |                                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_SlaveInterruptHandler(TWI_Slave_t *twi); | ||||||
| void TWI_SlaveAddressMatchHandler(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