-/*!
+/**
* \file
* <!--
* Copyright 2003, 2004, 2005 Develer S.r.l. (http://www.develer.com/)
- * This file is part of DevLib - See devlib/README for information.
+ * This file is part of DevLib - See README.devlib for information.
* -->
*
* \brief Driver for the AVR ATMega TWI (implementation)
/*#*
*#* $Log$
+ *#* Revision 1.7 2006/07/19 12:56:26 bernie
+ *#* Convert to new Doxygen style.
+ *#*
+ *#* Revision 1.6 2006/03/20 17:49:50 bernie
+ *#* Make the TWI driver more generic to work with devices other than EEPROMS.
+ *#*
+ *#* Revision 1.5 2005/11/27 23:33:40 bernie
+ *#* Use appconfig.h instead of cfg/config.h.
+ *#*
+ *#* Revision 1.4 2005/04/11 19:10:28 bernie
+ *#* Include top-level headers from cfg/ subdir.
+ *#*
+ *#* Revision 1.3 2005/03/01 23:26:00 bernie
+ *#* Header fix.
+ *#*
+ *#* Revision 1.2 2005/01/25 08:36:56 bernie
+ *#* CONFIG_TWI_FREQ: New config param.
+ *#*
*#* Revision 1.1 2005/01/06 16:09:40 aleph
*#* Split twi/eeprom functions from eeprom module in separate twi module
*#*
*#*/
#include "twi.h"
-#include "config.h"
-#include <debug.h>
+
+#include <cfg/debug.h>
+#include <cfg/cpu.h>
+#include <cfg/macros.h> // BV()
#include <hw.h>
-#include <cpu.h>
+#include <appconfig.h>
-#include <avr/twi.h>
+#include <compat/twi.h>
/* Wait for TWINT flag set: bus is ready */
#define WAIT_TWI_READY do {} while (!(TWCR & BV(TWINT)))
-/*! \name EEPROM control codes */
-/*@{*/
-#define SLA_W 0xA0
-#define SLA_R 0xA1
-/*@}*/
+#define READ_BIT BV(0)
-/*!
+/**
* Send START condition on the bus.
*
* \return true on success, false otherwise.
}
-/*!
+/**
* Send START condition and select slave for write.
+ * \c id is the device id comprehensive of address left shifted by 1.
+ * The LSB of \c id is ignored and reset to 0 for write operation.
*
* \return true on success, false otherwise.
*/
-bool twi_start_w(uint8_t slave_addr)
+bool twi_start_w(uint8_t id)
{
- ASSERT(slave_addr < 8);
-
/*
* Loop on the select write sequence: when the eeprom is busy
* writing previously sent data it will reply to the SLA_W
*/
while (twi_start())
{
- TWDR = SLA_W | (slave_addr << 1);
+ TWDR = id & ~READ_BIT;
TWCR = BV(TWINT) | BV(TWEN);
WAIT_TWI_READY;
}
-/*!
+/**
* Send START condition and select slave for read.
+ * \c id is the device id comprehensive of address left shifted by 1.
+ * The LSB of \c id is ignored and set to 1 for read operation.
*
* \return true on success, false otherwise.
*/
-bool twi_start_r(uint8_t slave_addr)
+bool twi_start_r(uint8_t id)
{
- ASSERT(slave_addr < 8);
-
if (twi_start())
{
- TWDR = SLA_R | (slave_addr << 1);
+ TWDR = id | READ_BIT;
TWCR = BV(TWINT) | BV(TWEN);
WAIT_TWI_READY;
}
-/*!
+/**
* Send STOP condition.
*/
void twi_stop(void)
{
- TWCR = BV(TWINT) | BV(TWEN) | BV(TWSTO);
+ TWCR = BV(TWINT) | BV(TWEN) | BV(TWSTO);
+}
+
+
+/**
+ * Put a single byte in master transmitter mode
+ * to the selected slave device through the TWI bus.
+ *
+ * \return true on success, false on error.
+ */
+bool twi_put(const uint8_t data)
+{
+ TWDR = data;
+ TWCR = BV(TWINT) | BV(TWEN);
+ WAIT_TWI_READY;
+ if (TW_STATUS != TW_MT_DATA_ACK)
+ {
+ kprintf("!TW_MT_DATA_ACK: %x\n", TWSR);
+ return false;
+ }
+ return true;
}
-/*!
+/**
* Send a sequence of bytes in master transmitter mode
* to the selected slave device through the TWI bus.
*
while (count--)
{
- TWDR = *buf++;
- TWCR = BV(TWINT) | BV(TWEN);
- WAIT_TWI_READY;
- if (TW_STATUS != TW_MT_DATA_ACK)
- {
- kprintf("!TW_MT_DATA_ACK: %x\n", TWSR);
+ if (!twi_put(*buf++))
return false;
- }
}
-
return true;
}
-/*!
+/**
* Receive a sequence of one or more bytes from the
* selected slave device in master receive mode through
* the TWI bus.
}
-/*!
+/**
* Initialize TWI module.
*/
void twi_init(void)
* Set speed:
* F = CLOCK_FREQ / (16 + 2*TWBR * 4^TWPS)
*/
- #define TWI_FREQ 300000L /* ~300 kHz */
+ #ifndef CONFIG_TWI_FREQ
+ #warning Using default value of 300000L for CONFIG_TWI_FREQ
+ #define CONFIG_TWI_FREQ 300000L /* ~300 kHz */
+ #endif
#define TWI_PRESC 1 /* 4 ^ TWPS */
- TWBR = (CLOCK_FREQ / (2 * TWI_FREQ * TWI_PRESC)) - (8 / TWI_PRESC);
+ TWBR = (CLOCK_FREQ / (2 * CONFIG_TWI_FREQ * TWI_PRESC)) - (8 / TWI_PRESC);
TWSR = 0;
TWCR = BV(TWEN);
);