Commit c85f1aaf authored by Birte Kristina Friesel's avatar Birte Kristina Friesel
Browse files

Add I2C Detect app

parent e632d5c4
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
#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
+59 −0
Original line number Diff line number Diff line
#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;
}
+146 −0
Original line number Diff line number Diff line
#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;
+11 −2
Original line number Diff line number Diff line
@@ -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