203 lines
4 KiB
C
203 lines
4 KiB
C
/*
|
|
Copyright 2012-2025 <>< Charles Lohr
|
|
This file may be used for any purposes (commercial or private) just please
|
|
leave this copyright notice in there somewhere. You may cross license
|
|
this as MIT or NewBSD.
|
|
|
|
Now, generic I2C library for any GPIO-based system.
|
|
|
|
Include this in your .c file only!!!
|
|
Include it after the following are defined:
|
|
|
|
I2CDELAY_FUNC -> If you wish to override the internal delay functions.
|
|
I2CSPEEDBASE -> define speed base multiplier 1 = normal, 10 = slow, .1 =
|
|
fast; failure to define this will result in the clock being as fast as
|
|
possible. I2CNEEDGETBYTE -> Do we need to be able to read data?
|
|
|
|
I2CPREFIX -> #define to be the prefix, i.e. BOB will cause BOBConfigI2C
|
|
to be generated.
|
|
I2CNOSTATIC -> #define if you want the functions to be generated as
|
|
not-static code.
|
|
|
|
NOTE: You must initially configure the port to be outputs on both DSDA
|
|
and DSCL and set them both to be driven high.
|
|
*/
|
|
/* Example:
|
|
|
|
#define DELAY1 Delay_Us(1);
|
|
#define DELAY2 Delay_Us(2);
|
|
#define DSCL_IHIGH { funPinMode( PIN_SCL, GPIO_CFGLR_IN_PUPD ); funDigitalWrite( PIN_SCL, 1 ); }
|
|
#define DSDA_IHIGH { funPinMode( PIN_SDA, GPIO_CFGLR_IN_PUPD ); funDigitalWrite( PIN_SDA, 1 ); }
|
|
#define DSDA_INPUT { funPinMode( PIN_SDA, GPIO_CFGLR_IN_PUPD ); funDigitalWrite( PIN_SDA, 1 ); }
|
|
#define DSCL_OUTPUT { funDigitalWrite( PIN_SCL, 0 ); funPinMode( PIN_SCL, GPIO_CFGLR_OUT_2Mhz_PP ); }
|
|
#define DSDA_OUTPUT { funDigitalWrite( PIN_SDA, 0 ); funPinMode( PIN_SDA, GPIO_CFGLR_OUT_2Mhz_PP ); }
|
|
#define READ_DSDA funDigitalRead( PIN_SDA )
|
|
#define I2CNEEDGETBYTE 1
|
|
#define I2CNEEDSCAN 1
|
|
|
|
#include "static_i2c.h"
|
|
|
|
...
|
|
*/
|
|
|
|
|
|
|
|
#ifndef I2CPREFIX
|
|
#define I2CPREFIX
|
|
#endif
|
|
|
|
#ifndef I2CNOSTATIC
|
|
#define I2CSTATICODE
|
|
#else
|
|
#define I2CSTATICODE static
|
|
#endif
|
|
|
|
#ifndef I2CFNCOLLAPSE
|
|
#define INTI2CFNCOLLAPSE(PFX, name) PFX##name
|
|
#define I2CFNCOLLAPSE(PFX, name) INTI2CFNCOLLAPSE(PFX, name)
|
|
#endif
|
|
|
|
#ifndef I2CNEEDGETBYTE
|
|
#define I2CNEEDGETBYTE 1
|
|
#endif
|
|
|
|
#ifndef DSCL_IHIGH
|
|
#define DSCL_IHIGH DSCL_INPUT
|
|
#endif
|
|
|
|
#ifndef DSDA_IHIGH
|
|
#define DSDA_IHIGH DSDA_INPUT
|
|
#endif
|
|
|
|
I2CSTATICODE void I2CFNCOLLAPSE(I2CPREFIX, ConfigI2C)()
|
|
{
|
|
DSDA_IHIGH
|
|
DSCL_IHIGH
|
|
}
|
|
|
|
I2CSTATICODE void I2CFNCOLLAPSE(I2CPREFIX, SendStart)()
|
|
{
|
|
DELAY1
|
|
DSCL_IHIGH
|
|
DELAY1
|
|
DSDA_OUTPUT
|
|
DELAY1
|
|
DSCL_OUTPUT
|
|
DELAY1
|
|
}
|
|
|
|
I2CSTATICODE void I2CFNCOLLAPSE(I2CPREFIX, SendStop)()
|
|
{
|
|
DELAY1
|
|
DSDA_OUTPUT
|
|
DELAY1
|
|
DSCL_IHIGH
|
|
DELAY1
|
|
DSDA_IHIGH
|
|
DELAY1
|
|
}
|
|
|
|
// Return nonzero on failure.
|
|
I2CSTATICODE unsigned char I2CFNCOLLAPSE(I2CPREFIX, SendByte)(unsigned char data)
|
|
{
|
|
unsigned int i;
|
|
// Assume we are in a started state (DSCL = 0 & DSDA = 0)
|
|
|
|
for (i = 0; i < 8; i++)
|
|
{
|
|
DELAY1
|
|
if (data & 0x80)
|
|
{
|
|
DSDA_IHIGH
|
|
}
|
|
else
|
|
{
|
|
DSDA_OUTPUT
|
|
}
|
|
data <<= 1;
|
|
DELAY2
|
|
DSCL_IHIGH
|
|
DELAY2
|
|
DSCL_OUTPUT
|
|
}
|
|
|
|
// Immediately after sending last bit, open up DDDR for control.
|
|
DELAY1
|
|
DSDA_INPUT
|
|
DELAY1
|
|
DSCL_IHIGH
|
|
DELAY1
|
|
i = READ_DSDA;
|
|
DELAY1
|
|
DSCL_OUTPUT
|
|
DELAY1
|
|
return !!i;
|
|
}
|
|
|
|
#if I2CNEEDGETBYTE
|
|
|
|
I2CSTATICODE unsigned char I2CFNCOLLAPSE(I2CPREFIX, GetByte)(uint8_t send_nak)
|
|
{
|
|
unsigned char i;
|
|
unsigned char ret = 0;
|
|
|
|
DSDA_INPUT
|
|
|
|
for (i = 0; i < 8; i++)
|
|
{
|
|
DELAY1
|
|
DSCL_IHIGH
|
|
DELAY2
|
|
ret <<= 1;
|
|
if (READ_DSDA)
|
|
ret |= 1;
|
|
DSCL_OUTPUT
|
|
}
|
|
|
|
// Send ack.
|
|
if (send_nak)
|
|
{
|
|
}
|
|
else
|
|
{
|
|
DSDA_OUTPUT
|
|
}
|
|
|
|
DELAY1
|
|
DSCL_IHIGH
|
|
DELAY2
|
|
DSCL_OUTPUT
|
|
DELAY1
|
|
DSDA_IHIGH
|
|
|
|
return ret;
|
|
}
|
|
|
|
#endif
|
|
|
|
// In case you want SCAN code
|
|
|
|
#if I2CNEEDSCAN
|
|
|
|
I2CSTATICODE void I2CFNCOLLAPSE(I2CPREFIX, Scan)()
|
|
{
|
|
int i;
|
|
printf( " " );
|
|
for( i = 0; i < 16; i++ )
|
|
{
|
|
printf( " %x", i );
|
|
}
|
|
for( i = 0; i < 128; i++ )
|
|
{
|
|
if( ( i & 0xf ) == 0 )
|
|
{
|
|
printf( "\n%02x ", i );
|
|
}
|
|
SendStart();
|
|
int b = SendByte( i<<1 );
|
|
SendStop();
|
|
printf( "%c ", b?'.':'#' );
|
|
}
|
|
printf( "\n" );
|
|
}
|
|
#endif
|