This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Having a bit of trouble waiting for a pin to go high

I'm fairly new to working this close to hardware and am playing around with a few things.  I'm trying to bit bang i2c over a couple of gpio lines and everything seems to be working just fine until I try to read the ack/nack bit after a write.  In the attached image the address is sent just fine, but when the register is sent it appears the slave holds down the line, which should be fine.  However my code for the byte write looks like the following:

uint8 i2c_write(uint8 data, const uint32_t clockPin, const uint32_t dataPin)
{
    uint8 ndx, ack  = 0;

    nrf_gpio_cfg_output(dataPin);

    for(ndx = 0; ndx < 8; ndx++)
    {
        nrf_gpio_pin_clear(clockPin);

        //get the current bit to send
        if(data & 0x80)
        {
            nrf_gpio_pin_set(dataPin);
        }
        else
        {
            nrf_gpio_pin_clear(dataPin);
        }

        nrf_gpio_pin_set(clockPin);

        /* Ensure that the clock is high */
        if( !waitForSCL(clockPin) )
        {
            //we failed to bring the clock high
            comTimeout = TRUE;
            break;
        }

        //next bit
        data <<= 1;
    }//end for

    nrf_gpio_pin_clear(clockPin);

    nrf_gpio_cfg_input(dataPin, NRF_GPIO_PIN_NOPULL);

    nrf_gpio_pin_set(clockPin);

    /* Ensure that the clock is high */
    if( !waitForSCL(clockPin) )
    {
        //we failed to bring the clock high
        comTimeout = TRUE;
    }

    ack = nrf_gpio_pin_read(dataPin);

    // pull both lines low again
    nrf_gpio_pin_clear(clockPin);

    nrf_gpio_cfg_output(dataPin);
    I2C_LOW(dataPin);

    //acks are low, nacks are high
    return !ack;
} //end i2c_write

static boolean waitForSCL(uint32_t clockPin)
{
    uint16 maxTries = MAX_TRIES;

    while( 0 == nrf_gpio_pin_out_read(clockPin)  && (maxTries>0) )
    {
        nrf_gpio_pin_set(clockPin);
        maxTries--;
    }

    return ( maxTries > 0 );
} // end of waitForSCL

Output from logic analyzer (SCL on bottom, SDA on top):

It looks like the function waitForSCL isn't doing what I'm intending for it to do.  Since I'm setting the clock high right before I check this function it makes sense that many times the first call to nrf_gpio_pin_out_read would read the line high right away, but when the slave is clock stretching it seems to still always read that as high.  I've tried a bunch of different delays and a bunch of other stuff, but I appear to be stuck.  Most likely this is an easy fix that I'm just not familiar enough with the SDK APIs to figure out.  Thanks for any help!

Related