diff options
Diffstat (limited to 'src/i2c.c')
-rw-r--r-- | src/i2c.c | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/src/i2c.c b/src/i2c.c new file mode 100644 index 0000000..cca68c6 --- /dev/null +++ b/src/i2c.c @@ -0,0 +1,103 @@ +#include <i2c.h> +#include <hardware.h> + +#define SDA (1 << 0) +#define SCL (1 << 1) + +void +_delay_ms(uint8_t ms); + +void +i2c_start_condition(void) +{ + port_a_data &= ~SDA; + _delay_ms(1); + port_a_data &= ~SCL; + _delay_ms(1); +} + +void +i2c_restart_condition(void) +{ + port_a_data |= SDA; + _delay_ms(1); + port_a_data |= SCL; + _delay_ms(1); + i2c_start_condition(); +} + +void +i2c_stop_condition(void) +{ + port_a_data |= SCL; + _delay_ms(1); + port_a_data |= SDA; + _delay_ms(1); +} + +void +i2c_send(uint8_t b) +{ + uint8_t i; + + for (i = 0; i < 8; ++i) { + if (b & 1) + port_a_data |= SDA; + else + port_a_data &= ~SDA; + + port_a_data |= SCL; + _delay_ms(1); + port_a_data &= ~SCL; + _delay_ms(1); + + b >>= 1; + } + + port_a_ctrl = PIO_MODE_3; + port_a_ctrl = 0x7D; + + // Read ack + port_a_data |= SCL; + _delay_ms(1); + port_a_data &= ~SCL; + _delay_ms(1); + + port_a_ctrl = PIO_MODE_3; + port_a_ctrl = 0x7C; +} + +uint8_t +i2c_recv(uint8_t ack) +{ + uint8_t i; + uint8_t b = 0; + + port_a_ctrl = PIO_MODE_3; + port_a_ctrl = 0x7D; + + for (i = 0; i < 8; ++i) { + port_a_data |= SCL; + _delay_ms(1); + if (port_a_data & 1) + b |= 1; + + port_a_data &= ~SCL; + _delay_ms(1); + b <<= 1; + } + + port_a_ctrl = PIO_MODE_3; + port_a_ctrl = 0x7C; + + if (ack) + port_a_data |= SDA; + else + port_a_data &= ~SDA; + + port_a_data |= SCL; + _delay_ms(1); + port_a_data &= ~SCL; + _delay_ms(1); + return b; +} |