Skip to content
Snippets Groups Projects
Commit c85f1aaf authored by Birte Kristina Friesel's avatar Birte Kristina Friesel
Browse files

Add I2C Detect app

parent e632d5c4
No related branches found
No related tags found
No related merge requests found
#ifndef I2C_H
#define I2C_H
class I2C {
private:
I2C(const I2C &copy);
public:
I2C () {}
signed char setup();
void scan(unsigned int *results);
signed char xmit(unsigned char address,
unsigned char tx_len, unsigned char *tx_buf,
unsigned char rx_len, unsigned char *rx_buf);
};
extern I2C i2c;
#endif
#include "arch.h"
#include "driver/gpio.h"
#include "driver/stdout.h"
#if defined(MULTIPASS_ARCH_HAS_I2C) && !defined(DRIVER_SOFTI2C)
#include "driver/i2c.h"
#else
#include "driver/soft_i2c.h"
#endif
#include "driver/lm75.h"
//#include "driver/mmsimple.h"
void loop(void)
{
kout.printf_float(lm75.getTemp());
kout << endl;
//moody.toggleBlue();
}
int main(void)
{
unsigned int i2c_status[128 / (8 * sizeof(unsigned int)) + 1];
arch.setup();
gpio.setup();
kout.setup();
if (i2c.setup() != 0) {
return 1;
}
kout << "I2C setup OK" << endl;
for (unsigned char i = 0; i < sizeof(i2c_status)/sizeof(unsigned int); i++) {
i2c_status[i] = 0;
}
i2c.scan(i2c_status);
kout << " 0 1 2 3 4 5 6 7 8 9 a b c d e f";
for (unsigned char address = 0; address < 128; address++) {
if ((address & 0x0f) == 0) {
kout << endl;
kout.printf_uint8(address);
kout << ":";
}
if (i2c_status[address / (8 * sizeof(unsigned int))] & (1 << (address % (8 * sizeof(unsigned int))))) {
kout << " ";
kout.printf_uint8(address);
} else {
kout << " --";
}
}
kout << endl;
arch.idle_loop();
return 0;
}
#include "driver/i2c.h"
#include <avr/io.h>
/*
* Send an I2C (re)start condition and the EEPROM address in read mode. Returns
* after it has been transmitted successfully.
*/
static signed char i2c_start_read(unsigned char addr)
{
TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN);
while (!(TWCR & _BV(TWINT)));
if (!(TWSR & 0x18)) // 0x08 == START ok, 0x10 == RESTART ok
return -1;
// Note: The R byte ("... | 1") causes the TWI momodule to switch to
// Master Receive mode
TWDR = (addr << 1) | 1;
TWCR = _BV(TWINT) | _BV(TWEN);
while (!(TWCR & _BV(TWINT)));
if (TWSR != 0x40) // 0x40 == SLA+R transmitted, ACK receveid
return -2;
return 0;
}
/*
* Send an I2C (re)start condition and the EEPROM address in write mode.
* Returns after it has been transmitted successfully.
*/
static signed char i2c_start_write(unsigned char addr)
{
TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN);
while (!(TWCR & _BV(TWINT)));
if (!(TWSR & 0x18)) // 0x08 == START ok, 0x10 == RESTART ok
return -1;
TWDR = (addr<< 1) | 0;
TWCR = _BV(TWINT) | _BV(TWEN);
while (!(TWCR & _BV(TWINT)));
if (TWSR != 0x18) // 0x18 == SLA+W transmitted, ACK received
return -2;
return 0;
}
/*
* Send an I2C stop condition.
*/
static signed char i2c_stop()
{
TWCR = _BV(TWINT) | _BV(TWSTO) | _BV(TWEN);
}
/*
* Sends len bytes to the EEPROM. Note that this method does NOT
* send I2C start or stop conditions.
*/
static signed char i2c_send(uint8_t len, uint8_t *data)
{
uint8_t pos = 0;
for (pos = 0; pos < len; pos++) {
TWDR = data[pos];
TWCR = _BV(TWINT) | _BV(TWEN);
while (!(TWCR & _BV(TWINT)));
if (TWSR != 0x28) // 0x28 == byte transmitted, ACK received
return pos;
}
return pos;
}
/*
* Receives len bytes from the EEPROM into data. Note that this method does
* NOT send I2C start or stop conditions.
*/
static signed char i2c_receive(uint8_t len, uint8_t *data)
{
uint8_t pos = 0;
for (pos = 0; pos < len; pos++) {
if (pos == len-1) {
// Don't ACK the last byte
TWCR = _BV(TWINT) | _BV(TWEN);
} else {
// Automatically send ACK
TWCR = _BV(TWINT) | _BV(TWEN) | _BV(TWEA);
}
while (!(TWCR & _BV(TWINT)));
data[pos] = TWDR;
/*
* No error handling here -- We send the acks, the EEPROM only
* supplies raw data, so there's no way of knowing whether it's still
* talking to us or we're just reading garbage.
*/
}
return pos;
}
signed char I2C::setup()
{
TWSR = 0;
TWBR = ((F_CPU / 100000UL) - 16) / 2;
return 0;
}
void I2C::scan(unsigned int *results)
{
for (unsigned char address = 0; address < 128; address++) {
if (i2c_start_read(address) == 0) {
results[address / (8 * sizeof(unsigned int))] |= 1 << (address % (8 * sizeof(unsigned int)));
}
}
i2c_stop();
}
signed char I2C::xmit(unsigned char address,
unsigned char tx_len, unsigned char *tx_buf,
unsigned char rx_len, unsigned char *rx_buf)
{
unsigned char i;
if (tx_len) {
if (i2c_start_write(address) < 0) {
return -1;
}
if (i2c_send(tx_len, tx_buf) < 0) {
return -1;
}
}
if (rx_len) {
if (i2c_start_read(address) < 0) {
return -1;
}
if (i2c_receive(rx_len, rx_buf) < 0) {
return -1;
}
}
i2c_stop();
return 0;
}
I2C i2c;
......@@ -20,6 +20,8 @@ void SoftI2C::start()
void SoftI2C::stop()
{
gpio.output(scl);
//
gpio.output(sda);
//
gpio.input(scl);
......@@ -79,12 +81,13 @@ void SoftI2C::scan(unsigned int *results)
unsigned char i2caddr;
for (unsigned char address = 0; address < 128; address++) {
i2caddr = (address << 1) | 1;
i2caddr = (address << 1) | 0;
start();
if (tx(i2caddr)) {
results[address / (8 * sizeof(unsigned int))] |= 1 << (address % (8 * sizeof(unsigned int)));
stop();
}
}
stop();
......@@ -109,7 +112,7 @@ signed char SoftI2C::xmit(unsigned char address,
tx((address << 1) | 1);
for (i = 1; i <= rx_len; i++) {
rx_buf[i] = rx((i < rx_len) * 1);
rx_buf[i-1] = rx((i < rx_len) * 1);
}
}
......@@ -118,4 +121,10 @@ signed char SoftI2C::xmit(unsigned char address,
return 0;
}
#ifdef MULTIPASS_ARCH_esp8266
SoftI2C i2c(GPIO::d7, GPIO::d8);
#elif MULTIPASS_ARCH_arduino_nano
SoftI2C i2c(GPIO::pc5, GPIO::pc4);
#elif MULTIPASS_ARCH_msp430fr5969lp
SoftI2C i2c(GPIO::p1_6, GPIO::p1_7);
#endif
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