-/*
+/*
* Copyright Droids Corporation (2007)
- *
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* params are : hwstatus, index of byte in frame, byte value */
static void (*g_recv_byte_event)(uint8_t, uint8_t, uint8_t) = NULL;
-/** send event, called when transmit is complete
+/** send event, called when transmit is complete
* param is error code : 0 if success */
static void (*g_send_event)(int8_t) = NULL;
/**
* mode is I2C_MODE_UNINIT, I2C_MODE_MASTER, I2C_MODE_MULTIMASTER or
* I2C_MODE_SLAVE. Parameter add is the address in slave mode, it is
- * composed from:
+ * composed from:
* b7 : true if the uC can be addressed with GENCALL
* b0-6: slave address
*/
-void
+void
i2c_init(i2c_mode_t mode, uint8_t add)
{
uint8_t flags;
IRQ_LOCK(flags);
-
+
if (mode == I2C_MODE_UNINIT) {
/* disable all */
TWCR = 0;
}
TWBR = I2C_BITRATE;
-
+
/* prescaler */
if (I2C_PRESCALER & 1)
sbi(TWSR, TWPS0);
if (I2C_PRESCALER & 2)
sbi(TWSR, TWPS1);
-
+
/* change for TWAR format */
TWAR = add << 1 ;
-
+
/* general call */
if (add & 0x80)
sbi(TWAR, TWGCE);
-
+
/* init vars */
g_mode = mode;
g_status = I2C_STATUS_READY;
}
-/**
+/**
* Register a function that is called when a buffer is received. The
* user application is always notified when data frame is received.
* Arguments of the callback are:
- * - (recv_buf, n>0) if transmission succedded. The first parameter
+ * - (recv_buf, n>0) if transmission succedded. The first parameter
* contains the address of the reception buffer and
* the second contains the number of received bytes.
* - (NULL, err<0) if the transmission failed (slave not answering
- * or arbiteration lost). The first parameter is
+ * or arbiteration lost). The first parameter is
* NULL and the second contains the error code.
*/
-void
+void
i2c_register_recv_event(void (*event)(uint8_t *, int8_t))
{
uint8_t flags;
IRQ_UNLOCK(flags);
}
-/**
+/**
* Register a function that is called when a byte is received.
* Arguments of the callback are: (hwstatus, numbyte, byte). The user
* app can modify the g_recv_size value, which is the number of bytes
* to be received in the frame: this can be done by calling
* i2c_set_recv_size().
*/
-void
+void
i2c_register_recv_byte_event(void (*event)(uint8_t, uint8_t, uint8_t))
{
uint8_t flags;
* - Else, the number of transmitted bytes is given, including the
* one that was not acked.
*/
-void
+void
i2c_register_send_event(void (*event)(int8_t))
{
uint8_t flags;
/**
* Send a buffer. Return 0 if xmit starts correctly.
* On error, return < 0.
- * - If mode is slave, dest_add should be I2C_ADD_MASTER, and transmission
- * starts when the master transmits a clk.
- * - If mode is master and if dest_add != I2C_ADD_MASTER, it will transmit
- * a START condition if bus is available (the uc will act as a
+ * - If mode is slave, dest_add should be I2C_ADD_MASTER, and transmission
+ * starts when the master transmits a clk.
+ * - If mode is master and if dest_add != I2C_ADD_MASTER, it will transmit
+ * a START condition if bus is available (the uc will act as a
* master)
* - If mode is master and if dest_add == I2C_ADD_MASTER, the uC will
* act as a slave, and data will be sent when the uC will be
* addressed.
* The transmission will be processed with these params until a
- * i2c_flush() is called.
- * The 'ctrl' parameter is composed by the flags I2C_CTRL_SYNC and
+ * i2c_flush() is called.
+ * The 'ctrl' parameter is composed by the flags I2C_CTRL_SYNC and
* I2C_CTRL_DONT_RELEASE_BUS
*/
-int8_t
-i2c_send(uint8_t dest_add, uint8_t *buf, uint8_t size, uint8_t ctrl)
+int8_t
+i2c_send(uint8_t dest_add, uint8_t *buf, uint8_t size, uint8_t ctrl)
{
uint8_t flags;
-
+
IRQ_LOCK(flags);
if (g_mode == I2C_MODE_UNINIT) {
IRQ_UNLOCK(flags);
return -ENXIO;
}
-
+
if (g_status & (I2C_STATUS_MASTER_XMIT |
I2C_STATUS_MASTER_RECV |
I2C_STATUS_SLAVE_XMIT_WAIT |
return 0;
return g_sync_res;
}
-
+
return -ESUCCESS;
}
* the same parameters as the last call. It safe to call it from the
* send_event, but else the send buffer may have been overwritten.
*/
-int8_t
-i2c_resend(void)
+int8_t
+i2c_resend(void)
{
return i2c_send(g_dest, g_send_buf, g_send_size, g_ctrl);
}
/**
* same but for recv
*/
-int8_t
-i2c_rerecv(void)
+int8_t
+i2c_rerecv(void)
{
return i2c_recv(g_dest, g_recv_size, g_ctrl);
}
TWCR = 0;
g_status = I2C_STATUS_READY;
#ifdef CONFIG_MODULE_I2C_MASTER
- if (g_mode == I2C_MODE_MASTER)
+ if (g_mode == I2C_MODE_MASTER)
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWIE);
else
#endif
- TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWIE) |
+ TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWIE) |
(1<<TWSTO) | (1<<TWEA);
IRQ_UNLOCK(flags);
}
IRQ_UNLOCK(flags);
return -ENXIO;
}
-
+
if (g_status != I2C_STATUS_READY) {
IRQ_UNLOCK(flags);
return -EBUSY;
g_ctrl = ctrl;
g_recv_size = size;
g_status |= I2C_STATUS_MASTER_RECV;
- g_dest = dest_add ;
+ g_dest = dest_add ;
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWIE) | (1<<TWSTA);
IRQ_UNLOCK(flags);
return 0;
return g_sync_res;
}
-
+
return -ESUCCESS;
#endif
}
/**
* Try to flush the current operation, before it is started. The
- * i2c module is then tagged as ready. If it returns 0, the flush was
- * a success, and i2c_send() can be called. Else, it means that
- * a transmission was running.
+ * i2c module is then tagged as ready. If it returns 0, the flush was
+ * a success, and i2c_send() can be called. Else, it means that
+ * a transmission was running.
*/
int8_t i2c_flush(void)
{
g_status &= ~(I2C_STATUS_SLAVE_XMIT_WAIT);
IRQ_UNLOCK(flags);
-
+
return -ESUCCESS;
}
IRQ_UNLOCK(flags);
return -EINVAL;
}
-
+
g_recv_size = size;
IRQ_UNLOCK(flags);
return -EBUSY;
}
- if (size > g_recv_nbytes)
+ if (size > g_recv_nbytes)
size = g_recv_nbytes;
memcpy(buf, g_recv_buf, size);
switch(hard_status) {
#ifdef CONFIG_MODULE_I2C_MASTER
- case TW_START:
+ case TW_START:
case TW_REP_START:
/* a start has been transmitted, transmit SLA+W which is :
- * b7-1: slave address
+ * b7-1: slave address
* b0 : 0 (write operation) or 1 (read) */
if (g_status & I2C_STATUS_MASTER_RECV) {
TWDR = (g_dest << 1) | (0x01);
break;
case TW_MT_DATA_NACK:
- /* we transmitted data but slave sent us a NACK.
+ /* we transmitted data but slave sent us a NACK.
* Notify the number of bytes sent, including the one
* that were not acked, and send a stop condition */
g_status |= (I2C_STATUS_OP_FINISHED | I2C_STATUS_NEED_XMIT_EVT);
break;
-
+
/* MASTER RECEIVER */
if (g_recv_size > 1)
command |= (1<<TWEA);
break;
-
+
case TW_MR_SLA_NACK:
/* the slave does not answer, send a stop condition */
g_recv_nbytes = -ENOENT;
}
else if (g_status & I2C_STATUS_MASTER_RECV) {
g_send_nbytes = -EAGAIN;
- g_status |= I2C_STATUS_NEED_XMIT_EVT;
+ g_status |= I2C_STATUS_NEED_XMIT_EVT;
}
/* g_status |= I2C_STATUS_OP_FINISHED; */ /* ?? or not ? */
break;
-#endif
+#endif
+
-
/* SLAVE RECEIVER */
case TW_SR_ARB_LOST_SLA_ACK:
break;
case TW_SR_GCALL_DATA_NACK:
- case TW_SR_DATA_NACK:
+ case TW_SR_DATA_NACK:
/* receive last data byte (our buffer is full) */
if (g_recv_nbytes < g_recv_size) {
g_recv_buf[g_recv_nbytes] = TWDR;
g_recv_nbytes++;
}
break;
-
+
case TW_SR_STOP:
/* the master sent a stop condition, notify app */
g_status |= (I2C_STATUS_OP_FINISHED | I2C_STATUS_NEED_RECV_EVT);
break;
-
+
/* SLAVE TRANSMITTER */
case TW_ST_ARB_LOST_SLA_ACK:
- case TW_ST_SLA_ACK:
+ case TW_ST_SLA_ACK:
/* slave is addressed. If it is not ready, send a 0 as
* last byte. */
g_send_nbytes = 0;
TWDR = 0;
g_send_size=0;
}
- /* else:
+ /* else:
* if there is only 1 byte to transmit, we don't
- * need to send ack, else set TWEA. */
+ * need to send ack, else set TWEA. */
else {
if (g_send_size > 1) {
command |= (1<<TWEA);
g_status &= ~(I2C_STATUS_SLAVE_XMIT_WAIT);
g_status |= I2C_STATUS_SLAVE_XMIT;
break;
-
+
case TW_ST_DATA_ACK:
/* transmitting data, if there is more than one byte
* to send, send ack */
g_status |= (I2C_STATUS_OP_FINISHED | I2C_STATUS_NEED_XMIT_EVT);
break;
-
+
/* COMMON */
case TW_BUS_ERROR:
command |= (1<<TWSTO);
g_status |= I2C_STATUS_OP_FINISHED;
break;
-
+
default :
/* default ... what can we do ? */
g_status |= I2C_STATUS_OP_FINISHED;
break;
}
-
+
#if I2C_DEBUG == 1
g_prev_status = g_status;
#endif
I2C_STATUS_OP_FINISHED);
}
}
-
+
/* Callback events if necessary (if not sync) */
if ( ! (g_ctrl & I2C_CTRL_SYNC) ) {
if ( (g_status & I2C_STATUS_NEED_XMIT_EVT) && g_send_event) {
else {
if ( g_status & (I2C_STATUS_MASTER_XMIT | I2C_STATUS_SLAVE_XMIT) )
g_sync_res = g_send_nbytes;
- else
+ else
g_sync_res = g_recv_nbytes;
}
g_status &= ~(I2C_STATUS_NEED_XMIT_EVT | I2C_STATUS_NEED_RECV_EVT);
-
+
#if I2C_DEBUG == 1
g_command = command;
#endif
* (by calling i2c_send() or i2c_recv(), we don't need to
* send it (we are back in MASTER_SEND or MASTER_RECV mode) */
if (TWCR & (1<<TWINT))
- TWCR = command;
+ TWCR = command;
}