Beispiel #1
0
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Initiates an async read operation
void ee_readAHandler(void)
{
	switch(_asyncStep)
	{
		// send a start signal
		case ASYNC_NEXT_START:
			_asyncStep = ASYNC_NEXT_DEVICE;
			i2cSendStartAsync(ee_readAHandler);
			break;

		// send SLA+R
		case ASYNC_NEXT_DEVICE:
			if (i2cGetStatus() != TW_START)
			{
				_asyncError();
				break;
			}

			_asyncStep = ASYNC_NEXT_NACK;
			i2cSendByteAsync(_device | I2C_READ, ee_readAHandler);
			break;

		// setup TWI module to NACK the response
		case ASYNC_NEXT_NACK:
			if (i2cGetStatus() != TW_MR_SLA_ACK)
			{
				_asyncError();
				break;
			}

			_asyncStep = ASYNC_NEXT_READ;
			i2cNackA(ee_readAHandler);
			break;

		// capture the received data	
		case ASYNC_NEXT_READ:
			if (i2cGetStatus() != TW_MR_DATA_NACK)
			{
				_asyncError();
				break;
			}

			// read received data
			_data = i2cGetReceivedByte();

			i2cSendStop();

			// mark transaction as complete
			_eeComplete(_data);

			// increment the address pointer	
			incrementAddress();

			break;
	}
}
Beispiel #2
0
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Maps the selected page to the device & address, and writes the device and address
// bytes to the device, leaving it in a state to accept more data.
EE_STATUS __writeActiveAddress(uint16_t page)
{
	// map device and address to selected page
	ee_mapdevice(page);

	// send start condition
	i2cSendStart();
	i2cWaitForComplete();

	// send device address with write
	i2cSendByte(_device & I2C_WRITE);
	i2cWaitForComplete();

	// check if device is present and live
	// device did not ACK it's address,
	// data will not be transferred
	// return error
	if (i2cGetStatus() != TW_MT_SLA_ACK)
	{
		i2cSendStop();
		return I2C_ERROR_NODEV;
	}

	// address MSB
	i2cSendByte(_address >> 8);
	i2cWaitForComplete();

	// address LSB
	i2cSendByte(_address & 0xFF);
	i2cWaitForComplete();

	return I2C_OK;
}
Beispiel #3
0
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void ee_poll(void)
{
	/*
	ACKNOWLEDGE POLLING: Once the internally timed write cycle has started and the
	EEPROM inputs are disabled, acknowledge polling can be initiated. This involves sending a
	start condition followed by the device address word. The read/write bit is representative of the
	operation desired. Only if the internal write cycle has completed will the EEPROM respond with
	a zero, allowing the read or write sequence to continue.
	*/

	while(1)
	{
		i2cSendStart();
		i2cWaitForComplete();

		i2cSendByte(_device & I2C_WRITE);
		i2cWaitForComplete();

		if (i2cGetStatus() == TW_MT_SLA_ACK)
		{
			i2cSendStop();
			//i2cWaitForComplete();
			break;
		}
	}
}
Beispiel #4
0
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Performs an I2C acknoledge for the EEPROM.  If the device is busy, it will NACK
bool ee_busy(void)
{
	i2cSendStart();
	i2cWaitForComplete();

	i2cSendByte(_device & I2C_WRITE);
	i2cWaitForComplete();

	if (i2cGetStatus() == TW_MT_SLA_ACK)
	{
		i2cSendStop();
		return false;
	}

	return true;
}
Beispiel #5
0
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Performs an asynchronous page read
void ee_readBytesHandler(void)
{
	// setting the current page in the device requires setting up the
	// device for a 'write' operation, but aborting the write before
	// sending any data to the chip.  a re-start is initiated with the
	// device which starts the sequential read
	switch (_asyncStep)
	{
		// send start signal
		case ASYNC_MULTI_START:
			_asyncStep = ASYNC_MULTI_DEVICE;
			i2cSendStartAsync(ee_readBytesHandler);
			break;

		// send device address with write
		case ASYNC_MULTI_DEVICE:
			if (i2cGetStatus() != TW_START)
			{
				_asyncError();
				break;
			}

			_asyncStep = ASYNC_MULTI_ADDRMSB;
			i2cSendByteAsync(_device & I2C_WRITE, ee_readBytesHandler);
		break;

		// send address MSB
		case ASYNC_MULTI_ADDRMSB:
			if (i2cGetStatus() != TW_MT_SLA_ACK)
			{
				_asyncError();
				break;
			}

			_asyncStep = ASYNC_MULTI_ADDRLSB;
			i2cSendByteAsync(_address >> 8, ee_readBytesHandler);
		break;

		// send address LSB
		case ASYNC_MULTI_ADDRLSB:
			if (i2cGetStatus() != TW_MT_DATA_ACK)
			{
				_asyncError();
				break;
			}

			_asyncStep = ASYNC_MULTI_READ;
			i2cSendByteAsync(_address & 0xff, ee_readBytesHandler);
		break;

		// prepare appropriate reply for recceived byte(s)
		case ASYNC_MULTI_READ:
			_asyncStep = ASYNC_MULTI_NEXT;
			if (_bufferLen)
				i2cAckA(ee_readBytesHandler);
			else
				i2cNackA(ee_readBytesHandler);
			break;

		// get the byte and
		case ASYNC_MULTI_NEXT:
			if (_bufferLen > 0)
			{
				_bufferLen--;
				*_pbuffer++ = i2cGetReceivedByte();
				_asyncStep = ASYNC_MULTI_READ;

				// increment the address pointer	
				incrementAddress();
			}
			else
				_asyncStep = ASYNC_MULTI_STOP;
			break;

		// end the transaction
		case ASYNC_MULTI_STOP:
			if (i2cGetStatus() != TW_MT_DATA_ACK)
			{
				_asyncError();
				break;
			}

			i2cSendStop();

			_eeComplete(0);
		break;
	}
}
Beispiel #6
0
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void ee_setPageAHandler(void)
{
	// setting the current page in the device requires setting up the
	// device for a 'write' operation, but aborting the write before
	// sending any data to the chip.  a re-start is initiated with the
	// device which starts the sequential read
	switch (_asyncStep)
	{
		// send start signal
		case ASYNC_SEND_START:
			_asyncStep = ASYNC_SEND_DEVICE;
			i2cSendStartAsync(&ee_setPageAHandler);
			return;

		// send device address with write
		case ASYNC_SEND_DEVICE:
			if (i2cGetStatus() != TW_START)
			{
				_asyncError();
				return;
			}

			_asyncStep = ASYNC_SEND_ADDRMSB;
			i2cSendByteAsync(_device & I2C_WRITE, &ee_setPageAHandler);
			return;

		// send address MSB
		case ASYNC_SEND_ADDRMSB:
			if (i2cGetStatus() != TW_MT_SLA_ACK)
			{
				_asyncError();
				return;
			}

			_asyncStep = ASYNC_SEND_ADDRLSB;
			i2cSendByteAsync(_address >> 8, &ee_setPageAHandler);
			return;

		// send address LSB
		case ASYNC_SEND_ADDRLSB:
			if (i2cGetStatus() != TW_MT_DATA_ACK)
			{
				_asyncError();
				return;
			}

			_asyncStep = ASYNC_SEND_STOP;
			i2cSendByteAsync(_address & 0xff, &ee_setPageAHandler);
			return;

		// end the transaction
		case ASYNC_SEND_STOP:
			if (i2cGetStatus() != TW_MT_DATA_ACK)
			{
				_asyncError();
				return;
			}

			i2cSendStop();

			_eeComplete(0);
			return;
	}
}
Beispiel #7
0
// ************ EDP Master operations ************
u08 edpSendCommand(u08 deviceAddr, u08 cmdLength, EdpCommand* edpCommand)
{
	EdpReply* edpCommandReply = (EdpReply*)EdpCommandReplyBuffer;
	u08* sendData;
	u08* replyData;
	u08 replyLength;
	u08 checksum;

	// initialize response variables
	edpCommandReply->Length = 0;
	EdpCommandReplyChecksum = 0;

	#ifdef EDP_DEBUG
	rprintf("\r\nBegin EdpSendCommand, TWSR:0x%x\r\n",inb(TWSR));
	#endif

	// disable TWI interrupt
	cbi(TWCR, TWIE);

	// clear TWI interface
	//outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK));

	// send start condition
	i2cSendStart();
	i2cWaitForComplete();
	#ifdef EDP_DEBUG
	rprintf("Sent Start, TWSR:0x%x\r\n",inb(TWSR));
	#endif

	// send device address with write
	i2cSendByte( (deviceAddr&0xFE) );
	i2cWaitForComplete();
	#ifdef EDP_DEBUG
	rprintf("Sent Device Address+Write, TWSR:0x%x\r\n",inb(TWSR));
	#endif

	// check if device is present and live
	if( i2cGetStatus() != TW_MT_SLA_ACK)
	{
		// device did not ACK it's address, command will not continue
		// transmit stop condition
		// leave with TWEA on for slave receiving
		i2cSendStop();
		while( !(inb(TWCR) & BV(TWSTO)) );
		#ifdef EDP_DEBUG
		rprintf("No Device!, Sent Stop, TWSR:0x%x\r\n",inb(TWSR));
		#endif
		// enable TWI interrupt
		sbi(TWCR, TWIE);
		// return error
		return EDP_COMMAND_NODEV;
	}

	// send data
	sendData = (u08*)edpCommand;
	checksum = 0;
	while(cmdLength)
	{
		i2cSendByte( *sendData );
		i2cWaitForComplete();
		#ifdef EDP_DEBUG
		rprintf("Sent Data, TWSR:0x%x\r\n",inb(TWSR));
		#endif
		checksum += *sendData++;
		cmdLength--;
	}

	// send the checksum
	i2cSendByte( ~checksum );
	i2cWaitForComplete();
	#ifdef EDP_DEBUG
	rprintf("Sent Checksum, TWSR:0x%x\r\n",inb(TWSR));
	#endif

	// send repeated start condition
	i2cSendStart();
	i2cWaitForComplete();
	#ifdef EDP_DEBUG
	rprintf("Sent Repeated Start, TWSR:0x%x\r\n",inb(TWSR));
	#endif

	// send device address with read
	i2cSendByte( deviceAddr|0x01 );
	i2cWaitForComplete();
	#ifdef EDP_DEBUG
	rprintf("Sent Device Address+Read, TWSR:0x%x\r\n",inb(TWSR));
	#endif

	// read response code, return NACK
	i2cReceiveByte(FALSE);
	i2cWaitForComplete();
	#ifdef EDP_DEBUG
	rprintf("Read Data, TWSR:0x%x\r\n",inb(TWSR));
	#endif
	EdpCommandResponseCode = i2cGetReceivedByte();

	if(EdpCommandResponseCode==EDP_RESP_DATA_REPLY)
	{
		// a data reply is being sent

		// send repeated start condition
		i2cSendStart();
		i2cWaitForComplete();
		
		// send device address with read
		i2cSendByte( deviceAddr|0x01 );
		i2cWaitForComplete();

		// get length, return ACK
		i2cReceiveByte(TRUE);
		i2cWaitForComplete();
		edpCommandReply->Length = i2cGetReceivedByte();
		// set temp variables
		replyLength = edpCommandReply->Length;
		replyData = edpCommandReply->Data;

		// get data, return ACKs
		// preset checksum with the datalength byte
		checksum = replyLength;
		while(replyLength > 1)
		{
			i2cReceiveByte(TRUE);	// receive data byte and return ACK
			i2cWaitForComplete();
			*replyData = i2cGetReceivedByte();
			checksum += *replyData++;
			replyLength--;
		}

		// get last data (actually the checksum), return NACK (last-byte signal)
		i2cReceiveByte(FALSE);
		i2cWaitForComplete();
		*replyData = i2cGetReceivedByte();
		// add received checksum+1 to our checksum, the result should be zero
		checksum += (*replyData) + 1;
		// save the reply checksum
		EdpCommandReplyChecksum = checksum;
	}
	
	// transmit stop condition
	// leave with TWEA on for slave receiving
	i2cSendStop();
	while( !(inb(TWCR) & BV(TWSTO)) );
	#ifdef EDP_DEBUG
	rprintf("Sent Stop, TWSR:0x%x\r\n",inb(TWSR));
	#endif
	
	// enable TWI interrupt
	sbi(TWCR, TWIE);

	return EDP_COMMAND_OK;
}
Beispiel #8
0
bool TwoWire::busy(void){
  return ((i2cGetStatus(i2c) & 16 )==16);
}