#include "project.h" #define SCL GPIO6 #define SDA GPIO7 static uint8_t set (uint8_t sda, uint8_t scl) { uint8_t ret; if (sda) gpio_set (GPIOB, SDA); else gpio_clear (GPIOB, SDA); if (scl) gpio_set (GPIOB, SCL); else gpio_clear (GPIOB, SCL); delay_us (10); ret = (gpio_get (GPIOB, SDA) & SDA) ? 1 : 0; return ret; } uint8_t i2cb_send (uint8_t wot) { uint8_t i; printf ("%02x", wot); for (i = 0; i < 8; ++i) { set (wot & 0x80, 0); set (wot & 0x80, 1); set (wot & 0x80, 0); wot <<= 1; } set (1, 0); i = set (1, 1); set (1, 0); printf ("%c", i ? '!' : '.'); return i; } uint8_t i2cb_send_addr (uint8_t addr, uint8_t rnw) { return i2cb_send (addr << 1 | rnw); } uint8_t i2cb_read (uint8_t ack) { uint8_t i, wot = 0; for (i = 0; i < 8; ++i) { wot <<= 1; set (1, 0); wot |= set (1, 1); set (1, 0); } set (ack, 0); set (ack, 1); set (ack, 0); return wot; } void i2cb_start (void) { printf ("S"); set (1, 1); set (0, 1); set (0, 0); } void i2cb_stop (void) { printf ("R\n"); set (0, 0); set (0, 1); set (1, 1); } int i2cb_start_transaction (uint8_t a, uint8_t rnw) { i2cb_start (); return i2cb_send_addr (a, rnw); } void i2cb_reset (void) { i2cb_start (); i2cb_stop (); i2cb_start (); i2cb_stop (); } void i2cb_scan (void) { uint8_t r; uint16_t i; i2cb_reset (); printf ("Probing bus\n"); for (i = 0; i < 128; ++i) { i2cb_start (); i2cb_stop (); i2cb_start (); r = i2cb_send ((i << 1) | I2C_WRITE); i2cb_stop (); if (!r) printf ("Found device at address 0x%x\n", i); } printf ("Done\n"); i2cb_reset (); } void i2cb_init (void) { gpio_set_mode (GPIOB, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, SCL); gpio_set_mode (GPIOB, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, SDA); set (1, 1); #ifdef DEBUG_I2C printf ("T11 %d:%d\n", !!(SDA_IN_REG & SDA_VAL), !!(SCL_IN_REG & SCL_VAL)); #endif set (0, 1); #ifdef DEBUG_I2C printf ("T01 %d:%d\n", !!(SDA_IN_REG & SDA_VAL), !!(SCL_IN_REG & SCL_VAL)); #endif set (1, 0); #ifdef DEBUG_I2C printf ("T10 %d:%d\n", !!(SDA_IN_REG & SDA_VAL), !!(SCL_IN_REG & SCL_VAL)); #endif set (1, 1); #ifdef DEBUG_I2C printf ("T11 %d:%d\n", !!(SDA_IN_REG & SDA_VAL), !!(SCL_IN_REG & SCL_VAL)); #endif }