forked from auracaster/openocd
We want to keep the tri-state buffers located between the FPGA and the board, in 'Z' state until we launch an i2c connection. We launch an i2c start condition, make the SCL direction 'OUT' to start the i2c protocol and at the end of the i2c connection at the stop condition, we re-make the tri-state buffers at 'Z' state. Change-Id: Ic597a70d0427832547f6b539864c24ce20a18c64 Signed-off-by: Ahmed BOUDJELIDA <aboudjelida@nanoxplore.com> Reviewed-on: https://review.openocd.org/c/openocd/+/7989 Tested-by: jenkins Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
145 lines
2.4 KiB
C
145 lines
2.4 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
/****************************************************************************
|
|
File : i2c.cpp *
|
|
Contents : i2c bit-bang library *
|
|
Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. *
|
|
<aboudjelida@nanoxplore.com> *
|
|
<ahmederrachedbjld@gmail.com> *
|
|
*****************************************************************************/
|
|
|
|
#include "i2c.h"
|
|
#include "io.h"
|
|
#include "delay.h"
|
|
#include "reg_ezusb.h"
|
|
|
|
void start_cd(void)
|
|
{
|
|
PIN_SCL_DIR = 0;
|
|
PIN_SDA_DIR = 0;
|
|
delay_us(10);
|
|
PIN_SDA = 0; //SDA = 1;
|
|
delay_us(1);
|
|
PIN_SCL = 0; //SCL = 1;
|
|
delay_us(1);
|
|
}
|
|
|
|
void repeated_start(void)
|
|
{
|
|
PIN_SDA = 1;
|
|
delay_us(1);
|
|
PIN_SCL = 1;
|
|
delay_us(1);
|
|
PIN_SDA = 0;
|
|
delay_us(1);
|
|
PIN_SCL = 0;
|
|
delay_us(1);
|
|
}
|
|
|
|
void stop_cd(void)
|
|
{
|
|
PIN_SDA = 0;
|
|
delay_us(1);
|
|
PIN_SCL = 1;
|
|
delay_us(1);
|
|
PIN_SDA = 1;
|
|
delay_us(1);
|
|
PIN_SDA_DIR = 1;
|
|
delay_us(1);
|
|
PIN_SCL_DIR = 1;
|
|
delay_us(1);
|
|
}
|
|
|
|
void clock_cd(void)
|
|
{
|
|
PIN_SCL = 1;
|
|
delay_us(1);
|
|
PIN_SCL = 0;
|
|
delay_us(1);
|
|
}
|
|
|
|
void send_ack(void)
|
|
{
|
|
PIN_SDA = 0;
|
|
delay_us(1);
|
|
PIN_SCL = 1;
|
|
delay_us(1);
|
|
PIN_SCL = 0;
|
|
delay_us(1);
|
|
}
|
|
|
|
void send_nack(void)
|
|
{
|
|
PIN_SDA = 1;
|
|
delay_us(1);
|
|
PIN_SCL = 1;
|
|
delay_us(1);
|
|
PIN_SCL = 0;
|
|
delay_us(1);
|
|
}
|
|
|
|
bool get_ack(void)
|
|
{
|
|
PIN_SDA_DIR = 1;
|
|
delay_us(1);
|
|
OED = 0xFE;
|
|
PIN_SCL = 1;
|
|
delay_us(1);
|
|
bool ack = PIN_SDA;
|
|
PIN_SCL = 0;
|
|
delay_us(1);
|
|
OED = 0xFF;
|
|
PIN_SDA_DIR = 0;
|
|
delay_us(1);
|
|
return ack;
|
|
}
|
|
|
|
/* here address(8 bits) = adr (7 bits) + type (1 bit) */
|
|
uint8_t get_address(uint8_t adr, uint8_t rdwr)
|
|
{
|
|
adr &= 0x7F;
|
|
adr = adr << 1;
|
|
adr |= (rdwr & 0x01);
|
|
return adr;
|
|
}
|
|
|
|
/* here send bit after bit and clocking scl with each bit */
|
|
void send_byte(uint8_t input)
|
|
{
|
|
for (uint8_t i = 0; i < 8; i++) {
|
|
if ((input & 0x80)) {
|
|
PIN_SDA = 1;
|
|
delay_us(1);
|
|
clock_cd();
|
|
} else {
|
|
PIN_SDA = 0;
|
|
delay_us(1);
|
|
clock_cd();
|
|
}
|
|
input = input << 1;
|
|
}
|
|
}
|
|
|
|
/* here receive bit after bit and clocking scl with each bit */
|
|
|
|
uint8_t receive_byte(void)
|
|
{
|
|
PIN_SDA_DIR = 1; //FX2 <-- FPGA
|
|
OED = 0xFE;
|
|
uint8_t input = 0x00;
|
|
for (uint8_t i = 0; i < 8; i++) {
|
|
PIN_SCL = 1;
|
|
delay_us(1);
|
|
input = input << 1;
|
|
if (PIN_SDA == 1)
|
|
input |= 0x01;
|
|
else
|
|
input |= 0X00;
|
|
|
|
PIN_SCL = 0;
|
|
delay_us(1);
|
|
}
|
|
OED = 0xFF;
|
|
PIN_SDA_DIR = 0;
|
|
return input;
|
|
}
|