#include <io/lpc23xx.h>
-
-#define I2C_READBIT BV(0)
-
/*
*
*/
#if 1
/* I2C 0 */
-
#define I2C_PCONP PCONP_PCI2C0
#define I2C_CONSET I20CONSET
#define I2C_CONCLR I20CONCLR
#define I2C_SCLL I20SCLL
#define I2C_STAT I20STAT
#define I2C_DAT I20DAT
- #define I2C_SDA_PINSEL_MASK I2C_SDA0_PINSEL_MASK
- #define I2C_SCL_PINSEL_MASK I2C_SCL0_PINSEL_MASK
- #define I2C_SDA_PINSEL I2C_SDA0_PINSEL
- #define I2C_SCL_PINSEL I2C_SCL0_PINSEL
+ #define I2C_PINSEL_PORT PINSEL1
+ #define I2C_PINSEL I2C0_PINSEL
+ #define I2C_PINSEL_MASK I2C0_PINSEL_MASK
+ #define I2C_PCLKSEL PCLKSEL0
+ #define I2C_PCLK_MASK I2C0_PCLK_MASK
+ #define I2C_PCLK_DIV8 I2C0_PCLK_DIV8
#else
/* I2C 1 */
+ #error
#endif
-#define GET_STATUS() (I2C_STAT)
+#define GET_STATUS() ((uint8_t)I2C_STAT)
+/*
+ * Wait that SI bit is set.
+ *
+ * Note: this bit is set when the I2C state changes. However, entering
+ * state F8 does not set SI since there is nothing for an interrupt service
+ * routine to do in that case.
+ */
+#define WAIT_SI() while( !(I2C_CONSET & BV(I2CON_SI)) )
static uint8_t i2c_builtin_start(void)
{
+ // Clear all pending flags.
+ I2C_CONCLR = BV(I2CON_STAC) | BV(I2CON_SIC) | BV(I2CON_AAC);
+
+ // Set start and ack bit.
I2C_CONSET = BV(I2CON_STA) | BV(I2CON_AA);
- while( !(I2C_CONSET & BV(I2CON_SI)) );
+ WAIT_SI();
return true;
}
ticks_t start = timer_clock();
while (i2c_builtin_start())
{
- uint32_t status = GET_STATUS();
+ uint8_t status = GET_STATUS();
+ /* Start status ok, set addres and the R/W bit */
if ((status == I2C_STAT_SEND) || (status == I2C_STAT_RESEND))
I2C_DAT = id & ~I2C_READBIT;
if (status == I2C_STAT_SLAW_ACK)
return true;
else if (status == I2C_STAT_ARB_LOST)
+ {
+ LOG_ERR("Arbitration lost\n");
break;
+ }
else if (timer_clock() - start > ms_to_ticks(CONFIG_I2C_START_TIMEOUT))
{
LOG_ERR("Timeout on I2C START\n");
{
if (i2c_builtin_start())
{
- uint32_t status = GET_STATUS();
+ uint8_t status = GET_STATUS();
+ /* Start status ok, set addres and the R/W bit */
if ((status == I2C_STAT_SEND) || (status == I2C_STAT_RESEND))
I2C_DAT = id | I2C_READBIT;
/* Clear the start bit and clear the SI bit */
I2C_CONCLR = BV(I2CON_SIC) | BV(I2CON_STAC);
- while( !(I2C_CONSET & BV(I2CON_SI)) );
+ WAIT_SI();
status = GET_STATUS();
if (status == I2C_STAT_SLAR_ACK)
return true;
+
+ else if (status == I2C_STAT_SLAR_ACK)
+ {
+ LOG_ERR("SLAR NACK:%02x\n", status);
+ }
else if (status == I2C_STAT_ARB_LOST)
- return false;
+ {
+ LOG_ERR("ARB Lost:%02x\n", status);
+ }
}
return false;
void i2c_builtin_stop(void)
{
+ /* Set the stop bit */
I2C_CONSET = BV(I2CON_STO);
+ /* Clear pending flags */
I2C_CONCLR = BV(I2CON_STAC) | BV(I2CON_SIC) | BV(I2CON_AAC);
}
bool i2c_send(const void *_buf, size_t count)
{
const uint8_t *buf = (const uint8_t *)_buf;
- uint32_t status = 0;
+ uint8_t status = 0;
while (count)
{
I2C_DAT = *buf++;
- I2C_CONSET = BV(I2CON_AA);
I2C_CONCLR = BV(I2CON_SIC);
count--;
- while( !(I2C_CONSET & BV(I2CON_SI)) );
+ WAIT_SI();
status = GET_STATUS();
+
if (status == I2C_STAT_DATA_ACK)
continue;
else if (status == I2C_STAT_DATA_NACK)
{
- LOG_ERR("send:%02x\n", (uint8_t)status);
+ LOG_ERR("Data NACK\n");
return false;
}
- else if (status == 0xf8)
+ else if (status == I2C_STAT_ERROR)
{
- LOG_ERR("send:%02x\n", (uint8_t)status);
+ LOG_ERR("I2C error.\n");
return false;
}
- else if (status == 0x10)
+ else if (status == I2C_STAT_UNKNOW)
{
- LOG_ERR("send:%02x\n", (uint8_t)status);
+ LOG_ERR("I2C unable to read status.\n");
return false;
}
uint8_t *buf = (uint8_t *)_buf;
uint8_t status = GET_STATUS();
-// LOG_ERR("recv:%02x\n", (uint8_t)status);
+ /* Ready for read */
+ I2C_CONSET = BV(I2CON_AA);
+ I2C_CONCLR = BV(I2CON_SIC);
+
+ WAIT_SI();
while (count)
{
*buf++ = I2C_DAT;
+ /*
+ * Set ack bit if we want read more byte, otherwise
+ * we disable it
+ */
if (count > 1)
I2C_CONSET = BV(I2CON_AA);
else
I2C_CONCLR = BV(I2CON_SIC);
count--;
- while( !(I2C_CONSET & BV(I2CON_SI)) );
+ WAIT_SI();
status = GET_STATUS();
if (status == I2C_STAT_RDATA_ACK)
continue;
else if (status == I2C_STAT_RDATA_NACK)
- {
- // LOG_ERR("recv:%02x\n", (uint8_t)status);
return true;
- }
- else if (status == 0xf8)
+ else if (status == I2C_STAT_ERROR)
{
- LOG_ERR("recv:%02x\n", (uint8_t)status);
+ LOG_ERR("I2C error.\n");
return false;
}
- else if (status == 0x10)
+ else if (status == I2C_STAT_UNKNOW)
{
- LOG_ERR("recv:%02x\n", (uint8_t)status);
+ LOG_ERR("I2C unable to read status.\n");
return false;
}
}
* Bit Frequency = Fplk / (I2C_I2SCLH + I2C_I2SCLL)
* value of I2SCLH and I2SCLL must be different
*/
- PCLKSEL0 &= ~I2C0_PCLK_MASK;
- PCLKSEL0 |= I2C0_PCLK_DIV8;
+ I2C_PCLKSEL &= ~I2C_PCLK_MASK;
+ I2C_PCLKSEL |= I2C_PCLK_DIV8;
I2C_SCLH = (((CPU_FREQ / 8) / CONFIG_I2C_FREQ) / 2) + 1;
I2C_SCLL = (((CPU_FREQ / 8) / CONFIG_I2C_FREQ) / 2);
ASSERT(I2C_SCLH > 4 || I2C_SCLL > 4);
/* Assign pins to SCL and SDA (P0_27, P0_28) */
- PINSEL1 &= ~I2C_PINSEL_MASK;
- PINSEL1 |= I2C_PINSEL;
+ I2C_PINSEL_PORT &= ~I2C_PINSEL_MASK;
+ I2C_PINSEL_PORT |= I2C_PINSEL;
// Enable I2C
I2C_CONSET = BV(I2CON_I2EN);