Пример #1
0
//!	Combined i2c send+receive format
status_t
i2c_send_receive(const i2c_bus *bus, int slaveAddress, const uint8 *writeBuffer,
	size_t writeLength, uint8 *readBuffer, size_t readLength)
{
	status_t status = send_start_condition(bus);
	if (status != B_OK)
		return status;

	status = send_slave_address(bus, slaveAddress, true);
	if (status != B_OK)
		goto err;

	status = send_bytes(bus, writeBuffer, writeLength);
	if (status != B_OK)
		goto err;

	status = send_start_condition(bus);
	if (status != B_OK)
		return status;

	status = send_slave_address(bus, slaveAddress, false);
	if (status != B_OK)
		goto err;

	status = receive_bytes(bus, readBuffer, readLength);
	if (status != B_OK)
		goto err;

	return send_stop_condition(bus);

err:
	TRACE("%s: Cancelling transmission\n", __func__);
	send_stop_condition(bus);
	return status;
}
Пример #2
0
static void handle_tw_status(struct twi_transfer *xfer, uint8_t twstat)
{
	uint8_t *buffer = xfer->buffer;

	switch (twstat) {
	default:
		stop_transfer(xfer, TWI_STAT_BUSERROR);
		break;
	case TW_START:
	case TW_REP_START:
		if (xfer->status & TWI_XFER_READ)
			TWDR = (xfer->address << 1) | 1;
		else
			TWDR = (xfer->address << 1);
		TWCR_write(1 << TWIE);
		break;
	case TW_MT_DATA_ACK:
	case TW_MR_DATA_ACK:
	case TW_MR_DATA_NACK:
	case TW_MT_SLA_ACK:
		if (xfer->status & TWI_XFER_READ) {
			buffer[xfer->offset++] = TWDR;

			if (xfer->offset == xfer->read_size) {
				stop_transfer(xfer, TWI_STAT_FINISHED);
			} else {
				if (xfer->offset + 1 == xfer->read_size)
					TWCR_write(1 << TWIE);
				else
					TWCR_write((1 << TWIE) | (1 << TWEA));
			}
		} else {
			if (xfer->offset == xfer->write_size) {
				if (xfer->read_size) {
					xfer->status |= TWI_XFER_READ;
					xfer->offset = 0;
					send_start_condition();
				} else
					stop_transfer(xfer, TWI_STAT_FINISHED);
			} else {
				TWDR = buffer[xfer->offset++];
				TWCR_write(1 << TWIE);
			}
		}
		break;
	case TW_MR_SLA_ACK:
		if (xfer->offset + 1 == xfer->read_size)
			TWCR_write(1 << TWIE);
		else
			TWCR_write((1 << TWIE) | (1 << TWEA));
		break;
	}
}
Пример #3
0
void twi_transfer(struct twi_transfer *xfer)
{
#ifdef TWI_SYNC
	twi_size_t i;
	uint8_t *buffer = xfer->buffer;

	if (xfer->write_size) {
		i2c_start(xfer->address << 1);
		for (i = 0; i < xfer->write_size; i++)
			i2c_write(buffer[i]);
		if (!xfer->read_size)
			i2c_stop();
	}
	if (xfer->read_size) {
		i2c_start((xfer->address << 1) | 1);
		for (i = 0; i < xfer->read_size; i++) {
			if (i + 1 == xfer->read_size)
				buffer[i] = i2c_readNak();
			else
				buffer[i] = i2c_readAck();
		}
		i2c_stop();
	}
	if (xfer->callback)
		xfer->callback(xfer, TWI_STAT_FINISHED);

#else /* TWI_SYNC */

	uint8_t sreg;

	xfer->offset = 0;
	xfer->next = NULL;
	xfer->status = 0;
	if (!xfer->write_size)
		xfer->status |= TWI_XFER_READ;
	transfer_set_status(xfer, TWI_STAT_INPROGRESS);

	sreg = irq_disable_save();

	if (twi.last_xfer)
		twi.last_xfer->next = xfer;
	twi.last_xfer = xfer;
	if (!twi.first_xfer) {
		twi.first_xfer = xfer;
		send_start_condition();
	}
	irq_restore(sreg);
#endif
}
Пример #4
0
static void stop_transfer(struct twi_transfer *xfer,
			  enum twi_status new_status)
{
	send_stop_condition();

	transfer_set_status(xfer, new_status);

	twi.first_xfer = xfer->next;
	if (twi.first_xfer)
		send_start_condition();
	else
		twi.last_xfer = NULL;

	if (xfer->callback)
		xfer->callback(xfer, new_status);
}