Skip to content
Snippets Groups Projects
Commit fe15574c authored by dnahm's avatar dnahm
Browse files

Adapted to comments

parent 7bab826c
No related branches found
No related tags found
No related merge requests found
......@@ -144,12 +144,9 @@ extern "C" {
/** @} */
/**
* @name I2C configuration
* @{
* @brief I2C configuration
*/
#define I2C_NUMOF 1
#define I2C_0_EN 1
#define I2C_IRQ_PRIO 1
#ifdef __cplusplus
}
......
......@@ -105,12 +105,9 @@ extern "C" {
/** @} */
/**
* @name I2C configuration
* @{
* @brief I2C configuration
*/
#define I2C_NUMOF 1
#define I2C_0_EN 1
#define I2C_IRQ_PRIO 1
#ifdef __cplusplus
}
......
......@@ -42,6 +42,15 @@ enum {
PORT_G = 6, /**< port G */
};
/**
* @name Defines for the I2C interface
* @{
*/
#define I2C_PORT_REG PORTD
#define I2C_PIN_MASK (1 << PORTD0) | (1 << PORTD1)
#define I2C_POWER_REG PRR0
/** @} */
#ifdef __cplusplus
}
#endif
......
......@@ -44,6 +44,15 @@ enum {
PORT_L = 10 /**< port L */
};
/**
* @name Defines for the I2C interface
* @{
*/
#define I2C_PORT_REG PORTD
#define I2C_PIN_MASK (1 << PORTD0) | (1 << PORTD1)
#define I2C_POWER_REG PRR0
/** @} */
#ifdef __cplusplus
}
#endif
......
......@@ -41,6 +41,15 @@ enum {
PORT_D = 3 /**< port D */
};
/**
* @name Defines for the I2C interface
* @{
*/
#define I2C_PORT_REG PORTC
#define I2C_PIN_MASK (1 << PORTC4) | (1 << PORTC5)
#define I2C_POWER_REG PRR
/** @} */
#ifdef __cplusplus
}
#endif
......
......@@ -7,13 +7,14 @@
*/
/**
* @addtogroup driver_periph
* @ingroup cpu_atmega_common
* @ingroup drivers_periph_i2c
* @{
*
* @file
* @brief Low-level I2C driver implementation fot atmega common
*
* @note This implementation only implements the 7-bit addressing mode.
* @note This implementation only implements the 7-bit addressing mode.
*
* @author Dimitri Nahm <dimitri.nahm@haw-hamburg.de>
*
......@@ -24,38 +25,35 @@
#include "cpu.h"
#include "mutex.h"
#include "assert.h"
#include "periph/i2c.h"
#include "periph_conf.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
#define MT_START 0x08
#define MT_ADDRESS_ACK 0x18
#define MT_DATA_ACK 0x28
#define MR_ADDRESS_ACK 0x40
#define ENABLE_DEBUG (0)
/* guard file in case no I2C device is defined */
#if I2C_NUMOF
#define MT_START 0x08
#define MT_START_REPEATED 0x10
#define MT_ADDRESS_ACK 0x18
#define MT_DATA_ACK 0x28
#define MR_ADDRESS_ACK 0x40
/* static function definitions */
static int _start(uint8_t address, uint8_t rw_flag);
static int _write(const uint8_t *data, int length);
static void _stop(void);
/**
* @brief Array holding one pre-initialized mutex for each I2C device
*/
static mutex_t locks[] = {
#if I2C_0_EN
[I2C_0] = MUTEX_INIT,
#endif
};
static mutex_t lock = MUTEX_INIT;
int i2c_init_master(i2c_t dev, i2c_speed_t speed)
{
/* TWI Bit Rate Register - division factor for the bit rate generator*/
int twibrr;
/* TWI Bit Rate Register - division factor for the bit rate generator */
uint8_t twibrr;
/* TWI Prescaler Bits - default 0 */
uint8_t twipb = 0;
/* check if the line is valid */
if (dev >= I2C_NUMOF) {
......@@ -64,25 +62,49 @@ int i2c_init_master(i2c_t dev, i2c_speed_t speed)
/* calculate speed configuration */
switch (speed) {
case I2C_SPEED_LOW:
if (CLOCK_CORECLOCK > 20000000U || CLOCK_CORECLOCK < 1000000U) {
return -2;
}
twibrr = ((CLOCK_CORECLOCK/10000)-16)/(2*4); // CLK Prescaler 4
twipb = 1;
break;
case I2C_SPEED_NORMAL:
if (CLOCK_CORECLOCK > 50000000U || CLOCK_CORECLOCK < 2000000U) {
return -2;
}
twibrr = ((CLOCK_CORECLOCK/100000)-16)/2;
break;
case I2C_SPEED_FAST:
if (CLOCK_CORECLOCK < 7500000U) {
return -2;
}
twibrr = ((CLOCK_CORECLOCK/400000)-16)/2;
break;
case I2C_SPEED_FAST_PLUS:
if (CLOCK_CORECLOCK < 18000000U) {
return -2;
}
twibrr = ((CLOCK_CORECLOCK/1000000)-16)/2;
break;
case I2C_SPEED_HIGH:
if (CLOCK_CORECLOCK < 62000000U) {
return -2;
}
twibrr = ((CLOCK_CORECLOCK/3400000)-16)/2;
break;
default:
return -2;
}
/* set pull-up on SCL and SDA */
#if defined (CPU_ATMEGA2560) || defined (CPU_ATMEGA1281)
PORTD |= (1 << PORTD0) | (1 << PORTD1);
#endif
#ifdef CPU_ATMEGA328P
PORTC |= (1 << PORTC4) | (1 << PORTC5);
#endif
I2C_PORT_REG |= (I2C_PIN_MASK);
/* enable I2C clock */
i2c_poweron(dev);
......@@ -90,7 +112,9 @@ int i2c_init_master(i2c_t dev, i2c_speed_t speed)
/* disable device */
TWCR &= ~(1 << TWEN);
/* configure I2C clock */
TWBR = twibrr;
TWBR = twibrr; // Set TWI Bit Rate Register
TWSR &= ~(0x03); // Reset TWI Prescaler Bits
TWSR |= twipb; // Set TWI Prescaler Bits
/* enable device */
TWCR |= (1 << TWEN);
......@@ -99,19 +123,15 @@ int i2c_init_master(i2c_t dev, i2c_speed_t speed)
int i2c_acquire(i2c_t dev)
{
if (dev >= I2C_NUMOF) {
return -1;
}
mutex_lock(&locks[dev]);
assert(dev < I2C_NUMOF);
mutex_lock(&lock);
return 0;
}
int i2c_release(i2c_t dev)
{
if (dev >= I2C_NUMOF) {
return -1;
}
mutex_unlock(&locks[dev]);
assert(dev < I2C_NUMOF);
mutex_unlock(&lock);
return 0;
}
......@@ -124,24 +144,24 @@ int i2c_read_bytes(i2c_t dev, uint8_t address, void *data, int length)
{
uint8_t *my_data = data;
if ((unsigned int)dev >= I2C_NUMOF) {
return -1;
}
assert((dev < I2C_NUMOF) && (length > 0));
/* send start condition and slave address */
if (_start(address, I2C_FLAG_READ) != 0)
if (_start(address, I2C_FLAG_READ) != 0) {
return 0;
}
for (int i = 0; i < length; i++) {
/* Send NACK for last received byte */
if ((length-i) == 1)
if ((length - i) == 1) {
TWCR = (1 << TWEN) | (1 << TWINT);
else
}
else {
TWCR = (1 << TWEA) | (1 << TWEN) | (1 << TWINT);
}
DEBUG("Wait for byte %i\n", i+1);
/* Wait for TWINT Flag set. This indicates that DATA has been received.*/
while (!(TWCR & (1 << TWINT)))
{}
while (!(TWCR & (1 << TWINT))) {}
/* receive data byte */
my_data[i] = TWDR;
DEBUG("Byte %i received\n", i+1);
......@@ -160,13 +180,12 @@ int i2c_read_reg(i2c_t dev, uint8_t address, uint8_t reg, void *data)
int i2c_read_regs(i2c_t dev, uint8_t address, uint8_t reg, void *data, int length)
{
if ((unsigned int)dev >= I2C_NUMOF) {
return -1;
}
assert((dev < I2C_NUMOF) && (length > 0));
/* start transmission and send slave address */
if (_start(address, I2C_FLAG_WRITE) != 0)
if (_start(address, I2C_FLAG_WRITE) != 0) {
return 0;
}
/* send register address and wait for complete transfer to be finished*/
if (_write(&reg, 1) != 1) {
......@@ -174,8 +193,6 @@ int i2c_read_regs(i2c_t dev, uint8_t address, uint8_t reg, void *data, int lengt
return 0;
}
_stop();
/* now start a new start condition and receive data */
return i2c_read_bytes(dev, address, data, length);
}
......@@ -189,13 +206,12 @@ int i2c_write_bytes(i2c_t dev, uint8_t address, const void *data, int length)
{
int bytes = 0;
if ((unsigned int)dev >= I2C_NUMOF) {
return -1;
}
assert((dev < I2C_NUMOF) && (length > 0));
/* start transmission and send slave address */
if (_start(address, I2C_FLAG_WRITE) != 0)
if (_start(address, I2C_FLAG_WRITE) != 0) {
return 0;
}
/* send out data bytes */
bytes = _write(data, length);
......@@ -208,10 +224,6 @@ int i2c_write_bytes(i2c_t dev, uint8_t address, const void *data, int length)
int i2c_write_reg(i2c_t dev, uint8_t address, uint8_t reg, uint8_t data)
{
if ((unsigned int)dev >= I2C_NUMOF) {
return -1;
}
return i2c_write_regs(dev, address, reg, &data, 1);
}
......@@ -219,17 +231,17 @@ int i2c_write_regs(i2c_t dev, uint8_t address, uint8_t reg, const void *data, in
{
int bytes = 0;
if ((unsigned int)dev >= I2C_NUMOF) {
return -1;
}
assert((dev < I2C_NUMOF) && (length > 0));
/* start transmission and send slave address */
if (_start(address, I2C_FLAG_WRITE) != 0)
if (_start(address, I2C_FLAG_WRITE) != 0) {
return 0;
}
/* send register address and wait for complete transfer to be finished*/
if (_write(&reg, 1))
if (_write(&reg, 1)) {
/* write data to register */
bytes = _write(data, length);
}
/* finish transfer */
_stop();
/* return number of bytes send */
......@@ -238,26 +250,14 @@ int i2c_write_regs(i2c_t dev, uint8_t address, uint8_t reg, const void *data, in
void i2c_poweron(i2c_t dev)
{
if (dev < I2C_NUMOF) {
#if defined (CPU_ATMEGA2560) || defined (CPU_ATMEGA1281)
PRR0 &= ~(1 << PRTWI);
#endif
#ifdef CPU_ATMEGA328P
PRR &= ~(1 << PRTWI);
#endif
}
assert(dev < I2C_NUMOF);
I2C_POWER_REG &= ~(1 << PRTWI);
}
void i2c_poweroff(i2c_t dev)
{
if (dev < I2C_NUMOF) {
#if defined (CPU_ATMEGA2560) || defined (CPU_ATMEGA1281)
PRR0 |= (1 << PRTWI);
#endif
#ifdef CPU_ATMEGA328P
PRR |= (1 << PRTWI);
#endif
}
assert(dev < I2C_NUMOF);
I2C_POWER_REG |= (1 << PRTWI);
}
static int _start(uint8_t address, uint8_t rw_flag)
......@@ -267,36 +267,41 @@ static int _start(uint8_t address, uint8_t rw_flag)
DEBUG("START condition transmitted\n");
/* Wait for TWINT Flag set. This indicates that the START has been
transmitted, and ACK/NACK has been received.*/
while (!(TWCR & (1 << TWINT)))
{}
* transmitted, and ACK/NACK has been received.*/
while (!(TWCR & (1 << TWINT))) {}
/* Check value of TWI Status Register. Mask prescaler bits.
If status different from START go to ERROR */
if ((TWSR & 0xF8) != MT_START) {
DEBUG("I2C Status Register is different from START\n");
* If status different from START go to ERROR */
if ((TWSR & 0xF8) == MT_START) {
DEBUG("I2C Status is: START\n");
}
else if ((TWSR & 0xF8) == MT_START_REPEATED) {
DEBUG("I2C Status is: START REPEATED\n");
}
else {
DEBUG("I2C Status Register is different from START/START_REPEATED\n");
_stop();
return -1;
}
else
DEBUG("I2C Status Register is: START\n");
/* Load ADDRESS and R/W Flag into TWDR Register.
Clear TWINT bit in TWCR to start transmission of ADDRESS */
* Clear TWINT bit in TWCR to start transmission of ADDRESS */
TWDR = (address << 1) | rw_flag;
TWCR = (1 << TWINT) | (1 << TWEN);
DEBUG("ADDRESS and FLAG transmitted\n");
/* Wait for TWINT Flag set. This indicates that ADDRESS has been transmitted.*/
while (!(TWCR & (1 << TWINT)))
{}
while (!(TWCR & (1 << TWINT))) {}
/* Check value of TWI Status Register. Mask prescaler bits.
If status different from ADDRESS ACK go to ERROR */
if ((TWSR & 0xF8) == MT_ADDRESS_ACK)
* If status different from ADDRESS ACK go to ERROR */
if ((TWSR & 0xF8) == MT_ADDRESS_ACK) {
DEBUG("ACK has been received for ADDRESS (write)\n");
else if ((TWSR & 0xF8) == MR_ADDRESS_ACK)
}
else if ((TWSR & 0xF8) == MR_ADDRESS_ACK) {
DEBUG("ACK has been received for ADDRESS (read)\n");
}
else {
DEBUG("NOT ACK has been received for ADDRESS\n");
_stop();
......@@ -308,38 +313,36 @@ static int _start(uint8_t address, uint8_t rw_flag)
static int _write(const uint8_t *data, int length)
{
int i = 0;
for (i = 0; i < length; i++) {
for (int i = 0; i < length; i++) {
/* Load DATA into TWDR Register.
Clear TWINT bit in TWCR to start transmission of data */
* Clear TWINT bit in TWCR to start transmission of data */
TWDR = data[i];
TWCR = (1 << TWINT) | (1 << TWEN);
DEBUG("Byte %i transmitted\n", i+1);
/* Wait for TWINT Flag set. This indicates that DATA has been transmitted.*/
while (!(TWCR & (1 << TWINT)))
{}
while (!(TWCR & (1 << TWINT))) {}
/* Check value of TWI Status Register. Mask prescaler bits. If status
different from MT_DATA_ACK, return number of transmitted bytes */
* different from MT_DATA_ACK, return number of transmitted bytes */
if ((TWSR & 0xF8) != MT_DATA_ACK) {
DEBUG("NACK has been received for BYTE %i\n", i+1);
return i;
}
else
else {
DEBUG("ACK has been received for BYTE %i\n", i+1);
}
}
return i;
return length;
}
static void _stop(void)
{
/* Reset I2C Interrupt Flag and transmit STOP condition */
TWCR = (1 << TWINT) | (1 << TWSTO) | (1 << TWEN);
while (TWCR & (1 << TWSTO))
{}
/* Wait for STOP Flag reset. This indicates that STOP has been transmitted.*/
while (TWCR & (1 << TWSTO)) {}
DEBUG("STOP condition transmitted\n");
TWCR = 0;
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment