For more information, please refer to <http://unlicense.org/>
*/
-/* pigpio version 31 */
+/* pigpio version 32 */
/* include ------------------------------------------------------- */
}
#define CHECK_INITED \
+ do \
{ \
if (!libInitialised) \
{ \
return PI_NOT_INITIALISED; \
} \
} \
+ while (0)
#define CHECK_INITED_RET_NULL_PTR \
+ do \
{ \
if (!libInitialised) \
{ \
return (NULL); \
} \
} \
+ while (0)
#define CHECK_INITED_RET_NIL \
+ do \
{ \
if (!libInitialised) \
{ \
"pigpio uninitialised, call gpioInitialise()"); \
} \
} \
+ while (0)
#define CHECK_NOT_INITED \
+ do \
{ \
if (libInitialised) \
{ \
return PI_INITIALISED; \
} \
} \
+ while (0)
#define SOFT_ERROR(x, format, arg...) \
+ do \
{ \
DBG(DBG_ALWAYS, format, ## arg); \
return x; \
} \
+ while (0)
#define TIMER_ADD(a, b, result) \
+ do \
{ \
(result)->tv_sec = (a)->tv_sec + (b)->tv_sec; \
(result)->tv_nsec = (a)->tv_nsec + (b)->tv_nsec; \
(result)->tv_nsec -= BILLION; \
} \
} \
+ while (0)
#define TIMER_SUB(a, b, result) \
+ do \
{ \
(result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
(result)->tv_nsec = (a)->tv_nsec - (b)->tv_nsec; \
(result)->tv_nsec += BILLION; \
} \
} \
+ while (0)
#define PI_PERI_BUS 0x7E000000
#define PI_NOTIFY_RUNNING 3
#define PI_NOTIFY_PAUSED 4
-#define PI_WFRX_NONE 0
-#define PI_WFRX_SERIAL 1
+#define PI_WFRX_NONE 0
+#define PI_WFRX_SERIAL 1
+#define PI_WFRX_I2C 2
+#define PI_WFRX_I2C_CLK 3
+
#define PI_WF_MICROS 1
#define DATUMS 2000
#define SRX_BUF_SIZE 8192
-#define PI_I2C_SLAVE 0x0703
-#define PI_I2C_RDWR 0x0707
-#define PI_I2C_SMBUS 0x0720
+#define PI_I2C_RETRIES 0x0701
+#define PI_I2C_TIMEOUT 0x0702
+#define PI_I2C_SLAVE 0x0703
+#define PI_I2C_FUNCS 0x0705
+#define PI_I2C_RDWR 0x0707
+#define PI_I2C_SMBUS 0x0720
#define PI_I2C_SMBUS_READ 1
#define PI_I2C_SMBUS_WRITE 0
#define PI_I2C_SMBUS_BLOCK_MAX 32
#define PI_I2C_SMBUS_I2C_BLOCK_MAX 32
+#define PI_I2C_FUNC_SMBUS_QUICK 0x00010000
+#define PI_I2C_FUNC_SMBUS_READ_BYTE 0x00020000
+#define PI_I2C_FUNC_SMBUS_WRITE_BYTE 0x00040000
+#define PI_I2C_FUNC_SMBUS_READ_BYTE_DATA 0x00080000
+#define PI_I2C_FUNC_SMBUS_WRITE_BYTE_DATA 0x00100000
+#define PI_I2C_FUNC_SMBUS_READ_WORD_DATA 0x00200000
+#define PI_I2C_FUNC_SMBUS_WRITE_WORD_DATA 0x00400000
+#define PI_I2C_FUNC_SMBUS_PROC_CALL 0x00800000
+#define PI_I2C_FUNC_SMBUS_READ_BLOCK_DATA 0x01000000
+#define PI_I2C_FUNC_SMBUS_WRITE_BLOCK_DATA 0x02000000
+#define PI_I2C_FUNC_SMBUS_READ_I2C_BLOCK 0x04000000
+#define PI_I2C_FUNC_SMBUS_WRITE_I2C_BLOCK 0x08000000
+
#define PI_MASH_MAX_FREQ 23800000
#define FLUSH_PAGES 1024
#define PI_SPI_FLAGS_GET_CSPOLS(x) (((x)>>2)&7)
#define PI_SPI_FLAGS_GET_MODE(x) ((x)&3)
+#define PI_STARTING 0
+#define PI_RUNNING 1
+#define PI_ENDING 2
+
/* typedef ------------------------------------------------------- */
typedef void (*callbk_t) ();
uint16_t seqno;
uint16_t state;
uint32_t bits;
+ uint32_t lastReportTick;
int fd;
int pipe;
} gpioNotify_t;
uint16_t state;
int16_t fd;
uint32_t flags;
+ uint32_t funcs;
} i2cInfo_t;
typedef struct
typedef struct
{
- int gpio;
char *buf;
uint32_t bufSize;
int readPos;
int writePos;
- uint32_t baud; /* 50-250000 */
uint32_t fullBit; /* nanoseconds */
uint32_t halfBit; /* nanoseconds */
int timeout; /* millisconds */
uint32_t data;
int bytes; /* 1, 2, 4 */
int level;
- int mode;
int dataBits; /* 1-32 */
+} wfRxSerial_t;
+
+typedef struct
+{
+ int SDA;
+ int SCL;
+ int delay;
+ int SDAMode;
+ int SCLMode;
+ int started;
+} wfRxI2C_t;
+
+typedef struct
+{
+ int mode;
+ int gpio;
+ uint32_t baud; /* 50-250000 */
+ union
+ {
+ wfRxSerial_t s;
+ wfRxI2C_t I;
+ };
} wfRx_t;
union my_smbus_data
static volatile uint32_t notifyBits = 0;
static volatile uint32_t scriptBits = 0;
-static volatile int DMAstarted = 0;
-static volatile int terminating = 0;
+static volatile int runState = PI_STARTING;
static int pthAlertRunning = 0;
static int pthFifoRunning = 0;
/* ----------------------------------------------------------------------- */
+static char *myBuf2Str(unsigned count, char *buf)
+{
+ static char str[128];
+ int i, c;
+
+ if (count && buf)
+ {
+ if (count > 40) c = 40; else c = count;
+
+ for (i=0; i<c; i++) sprintf(str+(3*i), "%02X ", buf[i]);
+ str[(3*c)-1] = 0;
+ }
+ else str[0] = 0;
+
+ return str;
+}
+
+/* ----------------------------------------------------------------------- */
+
static int my_smbus_access(
int fd, char rw, uint8_t cmd, int size, union my_smbus_data *data)
{
struct my_smbus_ioctl_data args;
+ DBG(DBG_INTERNAL, "rw=%d reg=%d cmd=%d data=%s",
+ rw, cmd, size, myBuf2Str(data->byte+1, (char*)data));
+
args.read_write = rw;
args.command = cmd;
args.size = size;
/* ----------------------------------------------------------------------- */
-static char *myBuf2Str(unsigned count, char *buf)
+static void myGpioSetMode(unsigned gpio, unsigned mode)
{
- static char str[64];
- int i, c;
-
- if (count)
- {
- if (count > 10) c = 10; else c = count;
+ int reg, shift;
- for (i=0; i<c; i++) sprintf(str+(3*i), "%02X ", buf[i]);
- str[(3*c)-1] = 0;
- }
- else str[0] = 0;
+ reg = gpio/10;
+ shift = (gpio%10) * 3;
- return str;
+ gpioReg[reg] = (gpioReg[reg] & ~(7<<shift)) | (mode<<shift);
}
+
+
/* ----------------------------------------------------------------------- */
static void myGpioWrite(unsigned gpio, unsigned level)
/* ----------------------------------------------------------------------- */
-static void waitForDMAstarted(void)
+static void spinWhileStarting(void)
{
- while ((!DMAstarted) && (!terminating))
+ while (runState == PI_STARTING)
{
if (piModel == 1) myGpioDelay(1000);
else flushMemory();
}
break;
+ case PI_CMD_BI2CC: res = bbI2CClose(p[1]); break;
+
+ case PI_CMD_BI2CO:
+ memcpy(&p[4], buf, 4);
+ res = bbI2COpen(p[1], p[2], p[4]);
+ break;
+
+ case PI_CMD_BI2CX:
+ /* use half buffer for write, half buffer for read */
+ if (p[3] > (bufSize/2)) p[3] = bufSize/2;
+ res = bbI2CXfer(p[1], buf, p[3], buf+(bufSize/2), bufSize/2);
+ if (res > 0)
+ {
+ memcpy(buf, buf+(bufSize/2), res);
+ }
+ break;
+
case PI_CMD_BR1: res = gpioRead_Bits_0_31(); break;
case PI_CMD_BR2: res = gpioRead_Bits_32_53(); break;
p[i++] = align;
p[i++] = flags;
p[i++] = MB_END_TAG;
- p[0] = i*sizeof *p;
+ p[0] = i*sizeof(*p);
mbProperty(fd, p);
p[i++] = 4;
p[i++] = handle;
p[i++] = MB_END_TAG;
- p[0] = i*sizeof *p;
+ p[0] = i*sizeof(*p);
mbProperty(fd, p);
p[i++] = 4;
p[i++] = handle;
p[i++] = MB_END_TAG;
- p[0] = i*sizeof *p;
+ p[0] = i*sizeof(*p);
mbProperty(fd, p);
p[i++] = 4;
p[i++] = handle;
p[i++] = MB_END_TAG;
- p[0] = i*sizeof *p;
+ p[0] = i*sizeof(*p);
mbProperty(fd, p);
/* ----------------------------------------------------------------------- */
-static void waveRxSerial(wfRx_t *s, int level, uint32_t tick)
+static void waveRxSerial(wfRx_t *w, int level, uint32_t tick)
{
int diffTicks, lastLevel;
int newWritePos;
- if (s->bit >= 0)
+ if (w->s.bit >= 0)
{
- diffTicks = tick - s->startBitTick;
+ diffTicks = tick - w->s.startBitTick;
if (level != PI_TIMEOUT)
{
- s->level = level;
+ w->s.level = level;
lastLevel = !level;
}
- else lastLevel = s->level;
+ else lastLevel = w->s.level;
- while ((s->bit <= s->dataBits) && (diffTicks > (s->nextBitDiff/1000)))
+ while ((w->s.bit <= w->s.dataBits) &&
+ (diffTicks > (w->s.nextBitDiff/1000)))
{
- if (s->bit)
+ if (w->s.bit)
{
- if (lastLevel) s->data |= (1<<(s->bit-1));
+ if (lastLevel) w->s.data |= (1<<(w->s.bit-1));
}
- else s->data = 0;
+ else w->s.data = 0;
- ++(s->bit);
+ ++(w->s.bit);
- s->nextBitDiff += s->fullBit;
+ w->s.nextBitDiff += w->s.fullBit;
}
- if (s->bit > s->dataBits)
+ if (w->s.bit > w->s.dataBits)
{
- memcpy(s->buf + s->writePos, &s->data, s->bytes);
+ memcpy(w->s.buf + w->s.writePos, &w->s.data, w->s.bytes);
/* don't let writePos catch readPos */
- newWritePos = (s->writePos + s->bytes) % (s->bufSize);
+ newWritePos = (w->s.writePos + w->s.bytes) % (w->s.bufSize);
- if (newWritePos != s->readPos) s->writePos = newWritePos;
+ if (newWritePos != w->s.readPos) w->s.writePos = newWritePos;
if (level == 0)
{
- gpioSetWatchdog(s->gpio, s->timeout);
- s->bit = 0;
- s->startBitTick = tick;
- s->nextBitDiff = s->halfBit;
+ gpioSetWatchdog(w->gpio, w->s.timeout);
+ w->s.bit = 0;
+ w->s.startBitTick = tick;
+ w->s.nextBitDiff = w->s.halfBit;
}
else
{
- s->bit = -1;
- gpioSetWatchdog(s->gpio, 0);
+ w->s.bit = -1;
+ gpioSetWatchdog(w->gpio, 0);
}
}
}
if (level == 0)
{
- gpioSetWatchdog(s->gpio, s->timeout);
- s->level = 0;
- s->bit = 0;
- s->startBitTick = tick;
- s->nextBitDiff = s->halfBit;
+ gpioSetWatchdog(w->gpio, w->s.timeout);
+ w->s.level = 0;
+ w->s.bit = 0;
+ w->s.startBitTick = tick;
+ w->s.nextBitDiff = w->s.halfBit;
}
}
}
{
switch (wfRx[gpio].mode)
{
- case PI_WFRX_NONE:
- break;
-
case PI_WFRX_SERIAL:
waveRxSerial(&wfRx[gpio], level, tick);
}
if (i2cInfo[handle].state == PI_I2C_CLOSED)
SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
+ if ((i2cInfo[handle].funcs & PI_I2C_FUNC_SMBUS_QUICK) == 0)
+ SOFT_ERROR(PI_BAD_SMBUS_CMD, "SMBUS command not supported by driver");
+
if (bit > 1)
SOFT_ERROR(PI_BAD_PARAM, "bad bit (%d)", bit);
if (i2cInfo[handle].state == PI_I2C_CLOSED)
SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
+ if ((i2cInfo[handle].funcs & PI_I2C_FUNC_SMBUS_READ_BYTE) == 0)
+ SOFT_ERROR(PI_BAD_SMBUS_CMD, "SMBUS command not supported by driver");
+
if (my_smbus_access(
i2cInfo[handle].fd, PI_I2C_SMBUS_READ, 0, PI_I2C_SMBUS_BYTE, &data))
return PI_I2C_READ_FAILED;
if (i2cInfo[handle].state == PI_I2C_CLOSED)
SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
+ if ((i2cInfo[handle].funcs & PI_I2C_FUNC_SMBUS_WRITE_BYTE) == 0)
+ SOFT_ERROR(PI_BAD_SMBUS_CMD, "SMBUS command not supported by driver");
+
if (bVal > 0xFF)
SOFT_ERROR(PI_BAD_PARAM, "bad bVal (%d)", bVal);
if (i2cInfo[handle].state == PI_I2C_CLOSED)
SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
+ if ((i2cInfo[handle].funcs & PI_I2C_FUNC_SMBUS_READ_BYTE_DATA) == 0)
+ SOFT_ERROR(PI_BAD_SMBUS_CMD, "SMBUS command not supported by driver");
+
if (reg > 0xFF)
SOFT_ERROR(PI_BAD_PARAM, "bad reg (%d)", reg);
if (i2cInfo[handle].state == PI_I2C_CLOSED)
SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
+ if ((i2cInfo[handle].funcs & PI_I2C_FUNC_SMBUS_WRITE_BYTE_DATA) == 0)
+ SOFT_ERROR(PI_BAD_SMBUS_CMD, "SMBUS command not supported by driver");
+
if (reg > 0xFF)
SOFT_ERROR(PI_BAD_PARAM, "bad reg (%d)", reg);
if (i2cInfo[handle].state == PI_I2C_CLOSED)
SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
+ if ((i2cInfo[handle].funcs & PI_I2C_FUNC_SMBUS_READ_WORD_DATA) == 0)
+ SOFT_ERROR(PI_BAD_SMBUS_CMD, "SMBUS command not supported by driver");
+
if (reg > 0xFF)
SOFT_ERROR(PI_BAD_PARAM, "bad reg (%d)", reg);
if (my_smbus_access(
- i2cInfo[handle].fd, PI_I2C_SMBUS_READ, reg, PI_I2C_SMBUS_WORD_DATA, &data))
+ i2cInfo[handle].fd,
+ PI_I2C_SMBUS_READ,
+ reg,
+ PI_I2C_SMBUS_WORD_DATA,
+ &data))
return PI_I2C_READ_FAILED;
else
return 0xFFFF & data.word;
if (i2cInfo[handle].state == PI_I2C_CLOSED)
SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
+ if ((i2cInfo[handle].funcs & PI_I2C_FUNC_SMBUS_WRITE_WORD_DATA) == 0)
+ SOFT_ERROR(PI_BAD_SMBUS_CMD, "SMBUS command not supported by driver");
+
if (reg > 0xFF)
SOFT_ERROR(PI_BAD_PARAM, "bad reg (%d)", reg);
if (i2cInfo[handle].state == PI_I2C_CLOSED)
SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
+ if ((i2cInfo[handle].funcs & PI_I2C_FUNC_SMBUS_PROC_CALL) == 0)
+ SOFT_ERROR(PI_BAD_SMBUS_CMD, "SMBUS command not supported by driver");
+
if (reg > 0xFF)
SOFT_ERROR(PI_BAD_PARAM, "bad reg (%d)", reg);
data.word = wVal;
if (my_smbus_access(
- i2cInfo[handle].fd, PI_I2C_SMBUS_WRITE, reg, PI_I2C_SMBUS_PROC_CALL, &data))
+ i2cInfo[handle].fd,
+ PI_I2C_SMBUS_WRITE,
+ reg, PI_I2C_SMBUS_PROC_CALL,
+ &data))
return PI_I2C_READ_FAILED;
else
return 0xFFFF & data.word;
if (i2cInfo[handle].state == PI_I2C_CLOSED)
SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
+ if ((i2cInfo[handle].funcs & PI_I2C_FUNC_SMBUS_READ_BLOCK_DATA) == 0)
+ SOFT_ERROR(PI_BAD_SMBUS_CMD, "SMBUS command not supported by driver");
+
if (reg > 0xFF)
SOFT_ERROR(PI_BAD_PARAM, "bad reg (%d)", reg);
if (my_smbus_access(
- i2cInfo[handle].fd, PI_I2C_SMBUS_READ, reg, PI_I2C_SMBUS_BLOCK_DATA, &data))
+ i2cInfo[handle].fd,
+ PI_I2C_SMBUS_READ,
+ reg,
+ PI_I2C_SMBUS_BLOCK_DATA,
+ &data))
return PI_I2C_READ_FAILED;
else
{
if (i2cInfo[handle].state == PI_I2C_CLOSED)
SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
+ if ((i2cInfo[handle].funcs & PI_I2C_FUNC_SMBUS_WRITE_BLOCK_DATA) == 0)
+ SOFT_ERROR(PI_BAD_SMBUS_CMD, "SMBUS command not supported by driver");
+
if (reg > 0xFF)
SOFT_ERROR(PI_BAD_PARAM, "bad reg (%d)", reg);
if (i2cInfo[handle].state == PI_I2C_CLOSED)
SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
+ if ((i2cInfo[handle].funcs & PI_I2C_FUNC_SMBUS_PROC_CALL) == 0)
+ SOFT_ERROR(PI_BAD_SMBUS_CMD, "SMBUS command not supported by driver");
+
if (reg > 0xFF)
SOFT_ERROR(PI_BAD_PARAM, "bad reg (%d)", reg);
if (i2cInfo[handle].state == PI_I2C_CLOSED)
SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
+ if ((i2cInfo[handle].funcs & PI_I2C_FUNC_SMBUS_READ_I2C_BLOCK) == 0)
+ SOFT_ERROR(PI_BAD_SMBUS_CMD, "SMBUS command not supported by driver");
+
if (reg > 0xFF)
SOFT_ERROR(PI_BAD_PARAM, "bad reg (%d)", reg);
if (i2cInfo[handle].state == PI_I2C_CLOSED)
SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
+ if ((i2cInfo[handle].funcs & PI_I2C_FUNC_SMBUS_WRITE_I2C_BLOCK) == 0)
+ SOFT_ERROR(PI_BAD_SMBUS_CMD, "SMBUS command not supported by driver");
+
if (reg > 0xFF)
SOFT_ERROR(PI_BAD_PARAM, "bad reg (%d)", reg);
{
char dev[32];
int i, slot, fd;
+ uint32_t funcs;
DBG(DBG_USER, "i2cBus=%d i2cAddr=%d flags=0x%X",
i2cBus, i2cAddr, i2cFlags);
if (i2cBus >= PI_NUM_I2C_BUS)
SOFT_ERROR(PI_BAD_I2C_BUS, "bad I2C bus (%d)", i2cBus);
- if ((i2cAddr < 0x08) || (i2cAddr > 0x77))
- SOFT_ERROR(PI_BAD_I2C_ADDR, "bad I2C address (0x%X)", i2cAddr);
+// if ((i2cAddr < 0x08) || (i2cAddr > 0x77))
+// SOFT_ERROR(PI_BAD_I2C_ADDR, "bad I2C address (0x%X)", i2cAddr);
if (i2cFlags)
SOFT_ERROR(PI_BAD_FLAGS, "bad flags (0x%X)", i2cFlags);
return PI_I2C_OPEN_FAILED;
}
+ if (ioctl(fd, PI_I2C_FUNCS, &funcs) < 0)
+ {
+ funcs = -1; /* assume all smbus commands allowed */
+ }
+
i2cInfo[slot].fd = fd;
i2cInfo[slot].flags = i2cFlags;
+ i2cInfo[slot].funcs = funcs;
return slot;
}
int i2cTransaction(unsigned handle, pi_i2c_msg_t *parts, unsigned numParts)
{
- int retval, fd;
+ int retval;
my_i2c_rdwr_ioctl_data_t rdwr;
DBG(DBG_USER, "handle=%d", handle);
if (numParts > PI_I2C_RDRW_IOCTL_MAX_MSGS)
SOFT_ERROR(PI_TOO_MANY_PARTS, "too many parts (%d)", numParts);
- fd = open(PI_I2C_COMBINED, O_RDWR);
-
- if (fd >= 0)
- {
- write(fd, "1", 1);
- close(fd);
- }
-
rdwr.msgs = parts;
rdwr.nmsgs = numParts;
else return PI_BAD_I2C_PART;
}
+#ifdef ZZZZ
+
+int i2cXfer(
+ unsigned handle,
+ char *inBuf, unsigned inLen, char *outBuf, unsigned outLen)
+{
+ int i, parts, inPos, outPos, status, bytes, len_bytes,flags, addr;
+ pi_i2c_msg_t part[PI_I2C_RDRW_IOCTL_MAX_MSGS];
+
+ DBG(DBG_USER, "handle=%d inBuf=%s outBuf=%08X len=%d",
+ handle, myBuf2Str(inLen, (char *)inBuf), (int)outBuf, outLen);
+
+ CHECK_INITED;
+
+ if (handle >= PI_I2C_SLOTS)
+ SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
+
+ if (i2cInfo[handle].state != PI_I2C_OPENED)
+ SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
+
+ if (!inBuf || !inLen)
+ SOFT_ERROR(PI_BAD_POINTER, "input buffer can't be NULL");
+
+ if (!outBuf && outLen)
+ SOFT_ERROR(PI_BAD_POINTER, "output buffer can't be NULL");
+
+ parts = 0;
+ inPos = 0;
+ outPos = 0;
+ status = 0;
+ flags = 0;
+ addr = 0;
+
+ while (!status && (inPos < inLen) && (parts < PI_I2C_RDRW_IOCTL_MAX_MSGS))
+ {
+ DBG(DBG_INTERNAL, "status=%d inpos=%d inlen=%d cmd=%d",
+ status, inPos, inLen, inBuf[inPos]);
+
+ len_bytes = 1;
+
+ switch (inBuf[inPos++])
+ {
+ case PI_I2C_END:
+ status = 1;
+ break;
+
+ case PI_I2C_READ16:
+ len_bytes = 2;
+ /* fall through */
+
+ case PI_I2C_READ:
+ if (inPos <= (inLen - len_bytes))
+ {
+ if (len_bytes != 1)
+ {
+ bytes=inBuf[inPos] + (inBuf[inPos+1]<<8);
+ inPos += 2;
+ }
+ else
+ {
+ bytes=inBuf[inPos++];
+ }
+
+ if (bytes && ((bytes + outPos) < outLen))
+ {
+ part[parts].addr = addr;
+ part[parts].flags = flags;
+ part[parts].len =
+ part[parts].buf =
+
+ for (i=0; i<(bytes-1); i++)
+ {
+ outBuf[outPos++] = I2CGetByte(w, 0);
+ }
+ outBuf[outPos++] = I2CGetByte(w, 1);
+ }
+ else status = PI_BAD_BB_WLEN;
+ }
+ else status = PI_BAD_BB_WLEN;
+ break;
+
+ case PI_I2C_WRITE16:
+ len_bytes = 2;
+ /* fall through */
+
+ case PI_I2C_WRITE:
+ if (inPos <= (inLen - len_bytes))
+ {
+ if (len_bytes != 1)
+ {
+ bytes=inBuf[inPos] + (inBuf[inPos+1]<<8);
+ inPos += 2;
+ }
+ else
+ {
+ bytes=inBuf[inPos++];
+ }
+
+ if (bytes && ((bytes + inPos) < inLen))
+ {
+ for (i=0; i<(bytes-1); i++)
+ {
+ ack = I2CPutByte(w, inBuf[inPos++]);
+ if (ack) status = PI_I2C_WRITE_FAILED;
+ }
+ ack = I2CPutByte(w, inBuf[inPos++]);
+ //if (ack) status = PI_I2C_WRITE_FAILED;
+ }
+ else status = PI_BAD_BB_RLEN;
+ }
+ else status = PI_BAD_BB_RLEN;
+ break;
+
+ default:
+ status = PI_BAD_BB_CMD;
+ }
+ }
+
+ if (status >= 0) status = outPos;
+
+ return status;
+}
+#endif
/* ======================================================================= */
/* don't start until DMA started */
- waitForDMAstarted();
+ spinWhileStarting();
reportedLevel = gpioReg[GPLEV0];
myGpioDelay(5000);
- if (DMAstarted)
+ if (runState == PI_RUNNING)
{
/* should never be executed, leave code just in case */
{
if (gpioAlert[b].ex)
{
- (gpioAlert[b].func)(b, 2, tick, gpioAlert[b].userdata);
+ (gpioAlert[b].func)
+ (b, PI_TIMEOUT, tick, gpioAlert[b].userdata);
}
else
{
- (gpioAlert[b].func)(b, 2, tick);
+ (gpioAlert[b].func)
+ (b, PI_TIMEOUT, tick);
}
}
}
gpioReport[emit].seqno = seqno;
gpioReport[emit].flags = PI_NTFY_FLAGS_WDOG |
- PI_NTFY_FLAGS_BIT(b);
+ PI_NTFY_FLAGS_BIT(b);
gpioReport[emit].tick = tick;
gpioReport[emit].level = newLevel;
}
}
+ if (!emit)
+ {
+ if ((tick - gpioNotify[n].lastReportTick) > 60000000)
+ {
+ if (numSamples)
+ newLevel = gpioSample[numSamples-1].level;
+ else
+ newLevel = reportedLevel;
+
+ gpioReport[emit].seqno = seqno;
+ gpioReport[emit].flags = PI_NTFY_FLAGS_ALIVE;
+ gpioReport[emit].tick = tick;
+ gpioReport[emit].level = newLevel;
+
+ emit++;
+ seqno++;
+ }
+ }
+
if (emit)
{
+ gpioNotify[n].lastReportTick = tick;
+
if (emit > gpioStats.maxEmit) gpioStats.maxEmit = emit;
emitted = 0;
/* don't start until DMA started */
- waitForDMAstarted();
+ spinWhileStarting();
while (1)
{
{
/* extensions */
+ case PI_CMD_BI2CX:
case PI_CMD_CF2:
case PI_CMD_I2CPK:
case PI_CMD_I2CRD:
/* don't start until DMA started */
- waitForDMAstarted();
+ spinWhileStarting();
while ((fdC =
accept(fdSock, (struct sockaddr *)&client, (socklen_t*)&c)))
if ((fdMem = open("/dev/mem", O_RDWR | O_SYNC) ) < 0)
{
- DBG(DBG_STARTUP,
+ DBG(DBG_ALWAYS,
"\n" \
"+---------------------------------------------------------+\n" \
"|Sorry, you don't have permission to run this program. |\n" \
notifyBits = 0;
scriptBits = 0;
- libInitialised = 0;
- DMAstarted = 0;
- terminating = 0;
-
pthAlertRunning = 0;
pthFifoRunning = 0;
pthSocketRunning = 0;
DBG(DBG_STARTUP, "");
- if (libInitialised) return PIGPIO_VERSION;
-
waveClockInited = 0;
clock_gettime(CLOCK_REALTIME, &libStarted);
initClock(1); /* initialise main clock */
- libInitialised = 1;
-
atexit(gpioTerminate);
if (pthread_attr_init(&pthAttr))
myGpioDelay(20000);
- DMAstarted = 1;
-
return PIGPIO_VERSION;
}
{
int status;
+ if (libInitialised) return PIGPIO_VERSION;
+
+ runState = PI_STARTING;
+
status = initInitialise();
if (status < 0)
{
+ runState = PI_ENDING;
initReleaseResources();
}
+ else
+ {
+ libInitialised = 1;
+ runState = PI_RUNNING;
+ }
return status;
}
DBG(DBG_USER, "");
- terminating = 1;
-
- if (libInitialised)
- {
- libInitialised = 0;
+ if (!libInitialised) return;
- gpioMaskSet = 0;
+ runState = PI_ENDING;
- /* reset DMA */
+ gpioMaskSet = 0;
- DMAstarted = 0;
+ /* reset DMA */
- dmaIn[DMA_CS] = DMA_CHANNEL_RESET;
- dmaOut[DMA_CS] = DMA_CHANNEL_RESET;
+ if (dmaReg != MAP_FAILED) dmaIn[DMA_CS] = DMA_CHANNEL_RESET;
+ if (dmaReg != MAP_FAILED) dmaOut[DMA_CS] = DMA_CHANNEL_RESET;
#ifndef EMBEDDED_IN_VM
- if (gpioCfg.showStats)
- {
- fprintf(stderr,
- "If you didn't request stats please cut & paste the\n"
- "following and e-mail to pigpio@abyz.co.uk\n");
+ if (gpioCfg.showStats)
+ {
+ fprintf(stderr,
+ "If you didn't request stats please cut & paste the\n"
+ "following and e-mail to pigpio@abyz.co.uk\n");
- fprintf(stderr,
- "#####################################################\n");
+ fprintf(stderr,
+ "micros=%d allocMode=%d dmaInitCbs=%d DMARestarts=%d\n",
+ gpioCfg.clockMicros, gpioCfg.memAllocMode,
+ gpioStats.dmaInitCbsCount, gpioStats.DMARestarts);
- fprintf(stderr,
- "micros=%d allocMode=%d dmaInitCbs=%d DMARestarts=%d\n",
- gpioCfg.clockMicros, gpioCfg.memAllocMode,
- gpioStats.dmaInitCbsCount, gpioStats.DMARestarts);
+ fprintf(stderr,
+ "samples %u maxSamples %u maxEmit %u emitFrags %u\n",
+ gpioStats.numSamples, gpioStats.maxSamples,
+ gpioStats.maxEmit, gpioStats.emitFrags);
- fprintf(stderr,
- "samples %u maxSamples %u maxEmit %u emitFrags %u\n",
- gpioStats.numSamples, gpioStats.maxSamples,
- gpioStats.maxEmit, gpioStats.emitFrags);
+ fprintf(stderr, "cbTicks %d, cbCalls %u alertTicks %u\n",
+ gpioStats.cbTicks, gpioStats.cbCalls, gpioStats.alertTicks);
- fprintf(stderr, "cbTicks %d, cbCalls %u alertTicks %u\n",
- gpioStats.cbTicks, gpioStats.cbCalls, gpioStats.alertTicks);
+ for (i=0; i< TICKSLOTS; i++)
+ fprintf(stderr, "%9u ", gpioStats.diffTick[i]);
- for (i=0; i< TICKSLOTS; i++)
- fprintf(stderr, "%9u ", gpioStats.diffTick[i]);
+ fprintf(stderr, "\n");
- fprintf(stderr, "\n");
+ fprintf(stderr, "\n");
- fprintf(stderr,
- "#####################################################\n");
- }
-#endif
+ fprintf(stderr,
+ "#####################################################\n");
}
+#endif
initReleaseResources();
fflush(NULL);
+
+ libInitialised = 0;
}
static void switchFunctionOff(unsigned gpio)
return wfStats.maxCbs;
}
+static int read_SDA(wfRx_t *w)
+{
+ myGpioSetMode(w->I.SDA, PI_INPUT);
+ return gpioRead(w->I.SDA);
+}
+
+static void set_SDA(wfRx_t *w)
+{
+ myGpioSetMode(w->I.SDA, PI_INPUT);
+}
+
+static void clear_SDA(wfRx_t *w)
+{
+ myGpioSetMode(w->I.SDA, PI_OUTPUT);
+ myGpioWrite(w->I.SDA, 0);
+}
+
+static void clear_SCL(wfRx_t *w)
+{
+ myGpioSetMode(w->I.SCL, PI_OUTPUT);
+ myGpioWrite(w->I.SCL, 0);
+}
+
+static void I2C_delay(wfRx_t *w)
+{
+ myGpioDelay(w->I.delay);
+}
+
+static void I2C_clock_stretch(wfRx_t *w)
+{
+ uint32_t now, max_stretch=10000;
+
+ myGpioSetMode(w->I.SCL, PI_INPUT);
+ now = gpioTick();
+ while ((gpioRead(w->I.SCL) == 0) && ((gpioTick()-now) < max_stretch));
+}
+
+static void I2CStart(wfRx_t *w)
+{
+ if (w->I.started)
+ {
+ set_SDA(w);
+ I2C_delay(w);
+ I2C_clock_stretch(w);
+ I2C_delay(w);
+ }
+
+ clear_SDA(w);
+ I2C_delay(w);
+ clear_SCL(w);
+ I2C_delay(w);
+
+ w->I.started = 1;
+}
+
+static void I2CStop(wfRx_t *w)
+{
+ clear_SDA(w);
+ I2C_delay(w);
+ I2C_clock_stretch(w);
+ I2C_delay(w);
+ set_SDA(w);
+ I2C_delay(w);
+
+ w->I.started = 0;
+}
+
+static void I2CPutBit(wfRx_t *w, int bit)
+{
+ if (bit) set_SDA(w);
+ else clear_SDA(w);
+
+ I2C_delay(w);
+ I2C_clock_stretch(w);
+ I2C_delay(w);
+ clear_SCL(w);
+}
+
+static int I2CGetBit(wfRx_t *w)
+{
+ int bit;
+
+ set_SDA(w); /* let SDA float */
+ I2C_delay(w);
+ I2C_clock_stretch(w);
+ bit = read_SDA(w);
+ I2C_delay(w);
+ clear_SCL(w);
+
+ return bit;
+}
+
+static int I2CPutByte(wfRx_t *w, int byte)
+{
+ int bit, nack;
+
+ for(bit=0; bit<8; bit++)
+ {
+ I2CPutBit(w, byte & 0x80);
+ byte <<= 1;
+ }
+
+ nack = I2CGetBit(w);
+
+ return nack;
+}
+
+static uint8_t I2CGetByte(wfRx_t *w, int nack)
+{
+ int bit, byte=0;
+
+ for (bit=0; bit<8; bit++)
+ {
+ byte = (byte << 1) | I2CGetBit(w);
+ }
+
+ I2CPutBit(w, nack);
+
+ return byte;
+}
+
+int bbI2COpen(unsigned SDA, unsigned SCL, unsigned bbBaud)
+{
+ DBG(DBG_USER, "SDA=%d SCL=%d bbBaud=%d", SDA, SCL, bbBaud);
+
+ CHECK_INITED;
+
+ if (SDA > PI_MAX_USER_GPIO)
+ SOFT_ERROR(PI_BAD_USER_GPIO, "bad SDA (%d)", SDA);
+
+ if (SCL > PI_MAX_USER_GPIO)
+ SOFT_ERROR(PI_BAD_USER_GPIO, "bad SCL (%d)", SCL);
+
+ if ((bbBaud < PI_BB_MIN_BAUD) || (bbBaud > PI_BB_RX_MAX_BAUD))
+ SOFT_ERROR(PI_BAD_WAVE_BAUD,
+ "SDA %d, bad baud rate (%d)", SDA, bbBaud);
+
+ if (wfRx[SDA].mode != PI_WFRX_NONE)
+ SOFT_ERROR(PI_GPIO_IN_USE, "gpio %d is already being used", SDA);
+
+ if (wfRx[SCL].mode != PI_WFRX_NONE)
+ SOFT_ERROR(PI_GPIO_IN_USE, "gpio %d is already being used", SCL);
+
+ wfRx[SDA].gpio = SDA;
+ wfRx[SDA].mode = PI_WFRX_I2C;
+ wfRx[SDA].baud = bbBaud;
+
+ wfRx[SDA].I.started = 0;
+ wfRx[SDA].I.SDA = SDA;
+ wfRx[SDA].I.SCL = SCL;
+ wfRx[SDA].I.delay = 500000 / bbBaud;
+ wfRx[SDA].I.SDAMode = gpioGetMode(SDA);
+ wfRx[SDA].I.SCLMode = gpioGetMode(SCL);
+
+ wfRx[SCL].gpio = SCL;
+ wfRx[SCL].mode = PI_WFRX_I2C_CLK;
+
+ myGpioSetMode(SDA, PI_INPUT);
+ myGpioSetMode(SCL, PI_INPUT);
+
+ return 0;
+}
+
+
+/* ----------------------------------------------------------------------- */
+
+
+int bbI2CClose(unsigned SDA)
+{
+ DBG(DBG_USER, "SDA=%d", SDA);
+
+ CHECK_INITED;
+
+ if (SDA > PI_MAX_USER_GPIO)
+ SOFT_ERROR(PI_BAD_USER_GPIO, "bad gpio (%d)", SDA);
+
+ switch(wfRx[SDA].mode)
+ {
+ case PI_WFRX_I2C:
+
+ gpioSetMode(wfRx[SDA].I.SDA, wfRx[SDA].I.SDAMode);
+ gpioSetMode(wfRx[SDA].I.SCL, wfRx[SDA].I.SCLMode);
+
+ wfRx[wfRx[SDA].I.SDA].mode = PI_WFRX_NONE;
+ wfRx[wfRx[SDA].I.SCL].mode = PI_WFRX_NONE;
+
+ break;
+
+ default:
+
+ SOFT_ERROR(PI_NOT_I2C_GPIO, "no I2C on gpio (%d)", SDA);
+
+ break;
+
+ }
+
+ return 0;
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+int bbI2CXfer(
+ unsigned SDA,
+ char *inBuf, unsigned inLen, char *outBuf, unsigned outLen)
+{
+ int i, ack, inPos, outPos, status, bytes, len_bytes;
+ wfRx_t *w;
+
+ DBG(DBG_USER, "gpio=%d inBuf=%s outBuf=%08X len=%d",
+ SDA, myBuf2Str(inLen, (char *)inBuf), (int)outBuf, outLen);
+
+ CHECK_INITED;
+
+ if (SDA > PI_MAX_USER_GPIO)
+ SOFT_ERROR(PI_BAD_USER_GPIO, "bad gpio (%d)", SDA);
+
+ if (wfRx[SDA].mode != PI_WFRX_I2C)
+ SOFT_ERROR(PI_NOT_I2C_GPIO, "no I2C on gpio (%d)", SDA);
+
+ if (!inBuf || !inLen)
+ SOFT_ERROR(PI_BAD_POINTER, "input buffer can't be NULL");
+
+ if (!outBuf && outLen)
+ SOFT_ERROR(PI_BAD_POINTER, "output buffer can't be NULL");
+
+ w = &wfRx[SDA];
+
+ inPos = 0;
+ outPos = 0;
+ status = 0;
+
+ while (!status && (inPos < inLen))
+ {
+ DBG(DBG_INTERNAL, "status=%d inpos=%d inlen=%d cmd=%d",
+ status, inPos, inLen, inBuf[inPos]);
+
+ len_bytes = 1;
+
+ switch (inBuf[inPos++])
+ {
+ case PI_I2C_END:
+ status = 1;
+ break;
+
+ case PI_I2C_START:
+ I2CStart(w);
+ break;
+
+ case PI_I2C_STOP:
+ I2CStop(w);
+ break;
+
+ case PI_I2C_READ16:
+ len_bytes = 2;
+ /* fall through */
+
+ case PI_I2C_READ:
+ if (inPos <= (inLen - len_bytes))
+ {
+ if (len_bytes != 1)
+ {
+ bytes=inBuf[inPos] + (inBuf[inPos+1]<<8);
+ inPos += 2;
+ }
+ else
+ {
+ bytes=inBuf[inPos++];
+ }
+
+ if (bytes && ((bytes + outPos) < outLen))
+ {
+ for (i=0; i<(bytes-1); i++)
+ {
+ outBuf[outPos++] = I2CGetByte(w, 0);
+ }
+ outBuf[outPos++] = I2CGetByte(w, 1);
+ }
+ else status = PI_BAD_BB_WLEN;
+ }
+ else status = PI_BAD_BB_WLEN;
+ break;
+
+ case PI_I2C_WRITE16:
+ len_bytes = 2;
+ /* fall through */
+
+ case PI_I2C_WRITE:
+ if (inPos <= (inLen - len_bytes))
+ {
+ if (len_bytes != 1)
+ {
+ bytes=inBuf[inPos] + (inBuf[inPos+1]<<8);
+ inPos += 2;
+ }
+ else
+ {
+ bytes=inBuf[inPos++];
+ }
+
+ if (bytes && ((bytes + inPos) < inLen))
+ {
+ for (i=0; i<(bytes-1); i++)
+ {
+ ack = I2CPutByte(w, inBuf[inPos++]);
+ if (ack) status = PI_I2C_WRITE_FAILED;
+ }
+ ack = I2CPutByte(w, inBuf[inPos++]);
+ //if (ack) status = PI_I2C_WRITE_FAILED;
+ }
+ else status = PI_BAD_BB_RLEN;
+ }
+ else status = PI_BAD_BB_RLEN;
+ break;
+
+ default:
+ status = PI_BAD_BB_CMD;
+ }
+ }
+
+ if (status >= 0) status = outPos;
+
+ return status;
+}
+
+
/*-------------------------------------------------------------------------*/
int gpioSerialReadOpen(unsigned gpio, unsigned bbBaud, unsigned bbBits)
if (wfRx[gpio].mode != PI_WFRX_NONE)
SOFT_ERROR(PI_GPIO_IN_USE, "gpio %d is already being used", gpio);
- bitTime = (1000 * MILLION) / bbBaud; /* nanoseconds */
+ bitTime = (1000 * MILLION) / bbBaud; /* nanos */
- timeout = ((bbBits+2) * bitTime)/MILLION; /* milliseconds */
+ timeout = ((bbBits+2) * bitTime)/MILLION; /* millis */
if (timeout < 1) timeout = 1;
- wfRx[gpio].gpio = gpio;
- wfRx[gpio].buf = malloc(SRX_BUF_SIZE);
- wfRx[gpio].bufSize = SRX_BUF_SIZE;
- wfRx[gpio].mode = PI_WFRX_SERIAL;
- wfRx[gpio].baud = bbBaud;
- wfRx[gpio].timeout = timeout;
- wfRx[gpio].fullBit = bitTime; /* nanoseconds */
- wfRx[gpio].halfBit = (bitTime/2)+500; /* nanoseconds (500 for rounding) */
- wfRx[gpio].readPos = 0;
- wfRx[gpio].writePos = 0;
- wfRx[gpio].bit = -1;
- wfRx[gpio].dataBits = bbBits;
-
- if (bbBits < 9) wfRx[gpio].bytes = 1;
- else if (bbBits < 17) wfRx[gpio].bytes = 2;
- else wfRx[gpio].bytes = 4;
+ wfRx[gpio].gpio = gpio;
+ wfRx[gpio].mode = PI_WFRX_SERIAL;
+ wfRx[gpio].baud = bbBaud;
+
+ wfRx[gpio].s.buf = malloc(SRX_BUF_SIZE);
+ wfRx[gpio].s.bufSize = SRX_BUF_SIZE;
+ wfRx[gpio].s.timeout = timeout;
+ wfRx[gpio].s.fullBit = bitTime; /* nanos */
+ wfRx[gpio].s.halfBit = (bitTime/2)+500; /* nanos (500 for rounding) */
+ wfRx[gpio].s.readPos = 0;
+ wfRx[gpio].s.writePos = 0;
+ wfRx[gpio].s.bit = -1;
+ wfRx[gpio].s.dataBits = bbBits;
+
+ if (bbBits < 9) wfRx[gpio].s.bytes = 1;
+ else if (bbBits < 17) wfRx[gpio].s.bytes = 2;
+ else wfRx[gpio].s.bytes = 4;
gpioSetAlertFunc(gpio, waveRxBit);
int gpioSerialRead(unsigned gpio, void *buf, size_t bufSize)
{
unsigned bytes=0, wpos;
- volatile wfRx_t *p;
+ volatile wfRx_t *w;
DBG(DBG_USER, "gpio=%d buf=%08X bufSize=%d", gpio, (int)buf, bufSize);
if (wfRx[gpio].mode != PI_WFRX_SERIAL)
SOFT_ERROR(PI_NOT_SERIAL_GPIO, "no serial read on gpio (%d)", gpio);
- p = &wfRx[gpio];
+ w = &wfRx[gpio];
- if (p->readPos != p->writePos)
+ if (w->s.readPos != w->s.writePos)
{
- wpos = p->writePos;
+ wpos = w->s.writePos;
- if (wpos > p->readPos) bytes = wpos - p->readPos;
- else bytes = p->bufSize - p->readPos;
+ if (wpos > w->s.readPos) bytes = wpos - w->s.readPos;
+ else bytes = w->s.bufSize - w->s.readPos;
if (bytes > bufSize) bytes = bufSize;
/* copy in multiples of the data size in bytes */
- bytes = (bytes / p->bytes) * p->bytes;
+ bytes = (bytes / w->s.bytes) * w->s.bytes;
- if (buf) memcpy(buf, p->buf+p->readPos, bytes);
+ if (buf) memcpy(buf, w->s.buf+w->s.readPos, bytes);
- p->readPos += bytes;
+ w->s.readPos += bytes;
- if (p->readPos >= p->bufSize) p->readPos = 0;
+ if (w->s.readPos >= w->s.bufSize) w->s.readPos = 0;
}
return bytes;
}
case PI_WFRX_SERIAL:
- free(wfRx[gpio].buf);
+ free(wfRx[gpio].s.buf);
gpioSetWatchdog(gpio, 0); /* switch off timeouts */
gpioNotify[slot].bits = 0;
gpioNotify[slot].fd = fd;
gpioNotify[slot].pipe = 1;
+ gpioNotify[slot].lastReportTick = gpioTick();
return slot;
}
gpioNotify[slot].bits = 0;
gpioNotify[slot].fd = fd;
gpioNotify[slot].pipe = 0;
+ gpioNotify[slot].lastReportTick = gpioTick();
return slot;
}
start = systReg[SYST_CLO];
- if (micros <= PI_MAX_BUSY_DELAY) while ((systReg[SYST_CLO] - start) <= micros);
-
- else gpioSleep(PI_TIME_RELATIVE, (micros/MILLION), (micros%MILLION));
+ if (micros <= PI_MAX_BUSY_DELAY)
+ while ((systReg[SYST_CLO] - start) <= micros);
+ else
+ gpioSleep(PI_TIME_RELATIVE, (micros/MILLION), (micros%MILLION));
return (systReg[SYST_CLO] - start);
}
/* include any user customisations */
#include "custom.cext"
+
#include <stdint.h>
#include <pthread.h>
-#define PIGPIO_VERSION 31
+#define PIGPIO_VERSION 3202
/*TEXT
i2cReadDevice Reads the raw I2C device
i2cWriteDevice Writes the raw I2C device
-i2cWriteQuick smbus write quick
-i2cWriteByte smbus write byte
-i2cReadByte smbus read byte
-i2cWriteByteData smbus write byte data
-i2cWriteWordData smbus write word data
-i2cReadByteData smbus read byte data
-i2cReadWordData smbus read word data
-i2cProcessCall smbus process call
-i2cWriteBlockData smbus write block data
-i2cReadBlockData smbus read block data
-i2cBlockProcessCall smbus block process call
-
-i2cWriteI2CBlockData smbus write I2C block data
-i2cReadI2CBlockData smbus read I2C block data
+i2cWriteQuick SMBus write quick
+i2cWriteByte SMBus write byte
+i2cReadByte SMBus read byte
+i2cWriteByteData SMBus write byte data
+i2cWriteWordData SMBus write word data
+i2cReadByteData SMBus read byte data
+i2cReadWordData SMBus read word data
+i2cProcessCall SMBus process call
+i2cWriteBlockData SMBus write block data
+i2cReadBlockData SMBus read block data
+i2cBlockProcessCall SMBus block process call
+
+i2cWriteI2CBlockData SMBus write I2C block data
+i2cReadI2CBlockData SMBus read I2C block data
SPI
typedef struct
{
-uint16_t func;
-uint16_t size;
+ uint16_t func;
+ uint16_t size;
} gpioHeader_t;
typedef struct
{
-size_t size;
-void *ptr;
-uint32_t data;
+ size_t size;
+ void *ptr;
+ uint32_t data;
} gpioExtent_t;
typedef struct
{
-uint32_t tick;
-uint32_t level;
+ uint32_t tick;
+ uint32_t level;
} gpioSample_t;
typedef struct
{
-uint16_t seqno;
-uint16_t flags;
-uint32_t tick;
-uint32_t level;
+ uint16_t seqno;
+ uint16_t flags;
+ uint32_t tick;
+ uint32_t level;
} gpioReport_t;
typedef struct
{
-uint32_t gpioOn;
-uint32_t gpioOff;
-uint32_t usDelay;
+ uint32_t gpioOn;
+ uint32_t gpioOff;
+ uint32_t usDelay;
} gpioPulse_t;
#define WAVE_FLAG_READ 1
typedef struct
{
-uint32_t gpioOn;
-uint32_t gpioOff;
-uint32_t usDelay;
-uint32_t flags;
+ uint32_t gpioOn;
+ uint32_t gpioOff;
+ uint32_t usDelay;
+ uint32_t flags;
} rawWave_t;
typedef struct
typedef struct
{
-int clk; /* gpio for clock */
-int mosi; /* gpio for MOSI */
-int miso; /* gpio for MISO */
-int ss_pol; /* slave select off state */
-int ss_us; /* delay after slave select */
-int clk_pol; /* clock off state */
-int clk_pha; /* clock phase */
-int clk_us; /* clock micros */
+ int clk; /* gpio for clock */
+ int mosi; /* gpio for MOSI */
+ int miso; /* gpio for MISO */
+ int ss_pol; /* slave select off state */
+ int ss_us; /* delay after slave select */
+ int clk_pol; /* clock off state */
+ int clk_pha; /* clock phase */
+ int clk_us; /* clock micros */
} rawSPI_t;
typedef struct { /* linux/arch/arm/mach-bcm2708/include/mach/dma.h */
-uint32_t info;
-uint32_t src;
-uint32_t dst;
-uint32_t length;
-uint32_t stride;
-uint32_t next;
-uint32_t pad[2];
+ uint32_t info;
+ uint32_t src;
+ uint32_t dst;
+ uint32_t length;
+ uint32_t stride;
+ uint32_t next;
+ uint32_t pad[2];
} rawCbs_t;
-/* max pi_i2c_msg_t per transaction */
-
-#define PI_I2C_RDRW_IOCTL_MAX_MSGS 42
-
-/* flags for pi_i2c_msg_t */
-
-#define PI_I2C_M_WR 0x0000 /* write data */
-#define PI_I2C_M_RD 0x0001 /* read data */
-#define PI_I2C_M_TEN 0x0010 /* ten bit chip address */
-#define PI_I2C_M_RECV_LEN 0x0400 /* length will be first received byte */
-#define PI_I2C_M_NO_RD_ACK 0x0800 /* if I2C_FUNC_PROTOCOL_MANGLING */
-#define PI_I2C_M_IGNORE_NAK 0x1000 /* if I2C_FUNC_PROTOCOL_MANGLING */
-#define PI_I2C_M_REV_DIR_ADDR 0x2000 /* if I2C_FUNC_PROTOCOL_MANGLING */
-#define PI_I2C_M_NOSTART 0x4000 /* if I2C_FUNC_PROTOCOL_MANGLING */
-
typedef struct
{
uint16_t addr; /* slave address */
#define PI_NOTIFY_SLOTS 32
+#define PI_NTFY_FLAGS_ALIVE (1 <<6)
#define PI_NTFY_FLAGS_WDOG (1 <<5)
#define PI_NTFY_FLAGS_BIT(x) (((x)<<0)&31)
#define PI_MAX_I2C_DEVICE_COUNT (1<<16)
#define PI_MAX_SPI_DEVICE_COUNT (1<<16)
+/* max pi_i2c_msg_t per transaction */
+
+#define PI_I2C_RDRW_IOCTL_MAX_MSGS 42
+
+/* flags for pi_i2c_msg_t */
+
+#define PI_I2C_M_WR 0x0000 /* write data */
+#define PI_I2C_M_RD 0x0001 /* read data */
+#define PI_I2C_M_TEN 0x0010 /* ten bit chip address */
+#define PI_I2C_M_RECV_LEN 0x0400 /* length will be first received byte */
+#define PI_I2C_M_NO_RD_ACK 0x0800 /* if I2C_FUNC_PROTOCOL_MANGLING */
+#define PI_I2C_M_IGNORE_NAK 0x1000 /* if I2C_FUNC_PROTOCOL_MANGLING */
+#define PI_I2C_M_REV_DIR_ADDR 0x2000 /* if I2C_FUNC_PROTOCOL_MANGLING */
+#define PI_I2C_M_NOSTART 0x4000 /* if I2C_FUNC_PROTOCOL_MANGLING */
+
+/* bit bang I2C commands */
+
+#define PI_I2C_END 0
+#define PI_I2C_START 1
+#define PI_I2C_STOP 2
+#define PI_I2C_READ 3
+#define PI_I2C_WRITE 4
+#define PI_I2C_READ16 5
+#define PI_I2C_WRITE16 6
+
+/* combined transaction I2C flag commands */
+
+#define PI_I2C_F_CLEAR 40 /* clear flags */
+#define PI_I2C_F_TEN 41 /* ten bit chip address */
+#define PI_I2C_F_RECV_LEN 42 /* length will be first received byte */
+#define PI_I2C_F_NO_RD_ACK 43 /* if I2C_FUNC_PROTOCOL_MANGLING */
+#define PI_I2C_F_IGNORE_NAK 44 /* if I2C_FUNC_PROTOCOL_MANGLING */
+#define PI_I2C_F_REV_DIR_ADDR 45 /* if I2C_FUNC_PROTOCOL_MANGLING */
+#define PI_I2C_F_NOSTART 46 /* if I2C_FUNC_PROTOCOL_MANGLING */
+
+/* SPI */
+
#define PI_SPI_FLAGS_BITLEN(x) ((x&63)<<16)
#define PI_SPI_FLAGS_RX_LSB(x) ((x&1)<<15)
#define PI_SPI_FLAGS_TX_LSB(x) ((x&1)<<14)
Returns a handle (>=0) if OK, otherwise PI_BAD_I2C_BUS, PI_BAD_I2C_ADDR,
PI_BAD_FLAGS, PI_NO_HANDLE, or PI_I2C_OPEN_FAILED.
-For the smbus commands the low level transactions are shown at the end
+For the SMBus commands the low level transactions are shown at the end
of the function description. The following abbreviations are used.
. .
Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or
PI_I2C_WRITE_FAILED.
-Quick command. smbus 2.0 5.5.1
+Quick command. SMBus 2.0 5.5.1
. .
S Addr Rd/Wr [A] P
. .
Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or
PI_I2C_WRITE_FAILED.
-Send byte. smbus 2.0 5.5.2
+Send byte. SMBus 2.0 5.5.2
. .
S Addr Wr [A] Data [A] P
. .
Returns the byte read (>=0) if OK, otherwise PI_BAD_HANDLE,
or PI_I2C_READ_FAILED.
-Receive byte. smbus 2.0 5.5.3
+Receive byte. SMBus 2.0 5.5.3
. .
S Addr Rd [A] [Data] NA P
. .
Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or
PI_I2C_WRITE_FAILED.
-Write byte. smbus 2.0 5.5.4
+Write byte. SMBus 2.0 5.5.4
. .
S Addr Wr [A] Comm [A] Data [A] P
. .
Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or
PI_I2C_WRITE_FAILED.
-Write word. smbus 2.0 5.5.4
+Write word. SMBus 2.0 5.5.4
. .
S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A] P
. .
Returns the byte read (>=0) if OK, otherwise PI_BAD_HANDLE,
PI_BAD_PARAM, or PI_I2C_READ_FAILED.
-Read byte. smbus 2.0 5.5.5
+Read byte. SMBus 2.0 5.5.5
. .
S Addr Wr [A] Comm [A] S Addr Rd [A] [Data] NA P
. .
Returns the word read (>=0) if OK, otherwise PI_BAD_HANDLE,
PI_BAD_PARAM, or PI_I2C_READ_FAILED.
-Read word. smbus 2.0 5.5.5
+Read word. SMBus 2.0 5.5.5
. .
S Addr Wr [A] Comm [A] S Addr Rd [A] [DataLow] A [DataHigh] NA P
. .
Returns the word read (>=0) if OK, otherwise PI_BAD_HANDLE,
PI_BAD_PARAM, or PI_I2C_READ_FAILED.
-Process call. smbus 2.0 5.5.6
+Process call. SMBus 2.0 5.5.6
. .
S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A]
S Addr Rd [A] [DataLow] A [DataHigh] NA P
Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or
PI_I2C_WRITE_FAILED.
-Block write. smbus 2.0 5.5.7
+Block write. SMBus 2.0 5.5.7
. .
S Addr Wr [A] Comm [A] Count [A] Data [A] Data [A] ... [A] Data [A] P
. .
Returns the number of bytes read (>=0) if OK, otherwise PI_BAD_HANDLE,
PI_BAD_PARAM, or PI_I2C_READ_FAILED.
-Block read. smbus 2.0 5.5.7
+Block read. SMBus 2.0 5.5.7
. .
S Addr Wr [A] Comm [A]
S Addr Rd [A] [Count] A [Data] A [Data] A ... A [Data] NA P
Returns the number of bytes read (>=0) if OK, otherwise PI_BAD_HANDLE,
PI_BAD_PARAM, or PI_I2C_READ_FAILED.
-The smbus 2.0 documentation states that a minimum of 1 byte may be
+The SMBus 2.0 documentation states that a minimum of 1 byte may be
sent and a minimum of 1 byte may be received. The total number of
bytes sent/received must be 32 or less.
-Block write-block read. smbus 2.0 5.5.8
+Block write-block read. SMBus 2.0 5.5.8
. .
S Addr Wr [A] Comm [A] Count [A] Data [A] ...
S Addr Rd [A] [Count] A [Data] ... A P
. .
D*/
+int bbI2COpen(unsigned SDA, unsigned SCL, unsigned bbBaud);
+
+int bbI2CClose(unsigned SDA);
+
+int bbI2CXfer(
+ unsigned SDA,
+ char *inBuf, unsigned inLen, char *outBuf, unsigned outLen);
+
/*F*/
int spiOpen(unsigned spiChan, unsigned spiBaud, unsigned spiFlags);
#define PI_CMD_CF1 87
#define PI_CMD_CF2 88
+#define PI_CMD_BI2CC 89
+#define PI_CMD_BI2CO 90
+#define PI_CMD_BI2CX 91
+
+#define PI_CMD_I2CX 92
+
#define PI_CMD_NOIB 99
/*DEF_E*/
#define PI_BAD_WAVE_BAUD -35 // baud rate not 50-250K(RX)/50-1M(TX)
#define PI_TOO_MANY_PULSES -36 // waveform has too many pulses
#define PI_TOO_MANY_CHARS -37 // waveform has too many chars
-#define PI_NOT_SERIAL_GPIO -38 // no serial read in progress on gpio
+#define PI_NOT_SERIAL_GPIO -38 // no bit bang serial read in progress on gpio
#define PI_BAD_SERIAL_STRUC -39 // bad (null) serial structure parameter
#define PI_BAD_SERIAL_BUF -40 // bad (null) serial buf parameter
#define PI_NOT_PERMITTED -41 // gpio operation not permitted
#define PI_BAD_MALLOC_MODE -104 // bad memory allocation mode
#define PI_TOO_MANY_PARTS -105 // too many I2C transaction parts
#define PI_BAD_I2C_PART -106 // a combined I2C transaction failed
-
+#define PI_BAD_SMBUS_CMD -107 // SMBus command not supported by driver
+#define PI_NOT_I2C_GPIO -108 // no bit bang I2C in progress on gpio
+#define PI_BAD_BB_WLEN -109 // bad BB write length
+#define PI_BAD_BB_RLEN -110 // bad BB read length
+#define PI_BAD_BB_CMD -111 // bad BB command
#define PI_PIGIF_ERR_0 -2000
#define PI_PIGIF_ERR_99 -2099
#define PI_DEFAULT_UPDATE_MASK_R0 0xFFFFFFFF
#define PI_DEFAULT_UPDATE_MASK_R1 0x03E7CF93
#define PI_DEFAULT_UPDATE_MASK_R2 0xFBC7CF9C
-#define PI_DEFAULT_UPDATE_MASK_R3 0x0080400FFFFFFCLL
+#define PI_DEFAULT_UPDATE_MASK_R3 0x0080480FFFFFFCLL
#define PI_DEFAULT_UPDATE_MASK_COMPUTE 0x00FFFFFFFFFFFFLL
#define PI_DEFAULT_MEM_ALLOC_MODE PI_MEM_ALLOC_AUTO
i2c_read_device Reads the raw I2C device
i2c_write_device Writes the raw I2C device
-i2c_write_quick smbus write quick
-i2c_write_byte smbus write byte
-i2c_read_byte smbus read byte
-i2c_write_byte_data smbus write byte data
-i2c_write_word_data smbus write word data
-i2c_read_byte_data smbus read byte data
-i2c_read_word_data smbus read word data
-i2c_process_call smbus process call
-i2c_write_block_data smbus write block data
-i2c_read_block_data smbus read block data
-i2c_block_process_call smbus block process call
-
-i2c_read_i2c_block_data smbus read I2C block data
-i2c_write_i2c_block_data smbus write I2C block data
+i2c_write_quick SMBus write quick
+i2c_write_byte SMBus write byte
+i2c_read_byte SMBus read byte
+i2c_write_byte_data SMBus write byte data
+i2c_write_word_data SMBus write word data
+i2c_read_byte_data SMBus read byte data
+i2c_read_word_data SMBus read word data
+i2c_process_call SMBus process call
+i2c_write_block_data SMBus write block data
+i2c_read_block_data SMBus read block data
+i2c_block_process_call SMBus block process call
+
+i2c_read_i2c_block_data SMBus read I2C block data
+i2c_write_i2c_block_data SMBus write I2C block data
SPI
import os
import atexit
-VERSION = "1.16"
+VERSION = "1.17"
exceptions = True
PI_SCRIPT_WAITING=3
PI_SCRIPT_FAILED =4
+# notification flags
+
+NTFY_FLAGS_ALIVE = (1 << 6)
+NTFY_FLAGS_WDOG = (1 << 5)
+NTFY_FLAGS_GPIO = 31
+
# pigpio command numbers
_PI_CMD_MODES= 0
PI_BAD_STOPBITS =-102
PI_MSG_TOOBIG =-103
PI_BAD_MALLOC_MODE =-104
+_PI_TOO_MANY_PARTS =-105
+_PI_BAD_I2C_PART =-106
+PI_BAD_SMBUS_CMD =-107
+PI_NOT_I2C_GPIO =-108
# pigpio error text
[PI_BAD_WAVE_BAUD , "baud rate not 50-250000(RX)/1000000(TX)"],
[PI_TOO_MANY_PULSES , "waveform has too many pulses"],
[PI_TOO_MANY_CHARS , "waveform has too many chars"],
- [PI_NOT_SERIAL_GPIO , "no serial read in progress on gpio"],
+ [PI_NOT_SERIAL_GPIO , "no bit bang serial read in progress on gpio"],
[PI_NOT_PERMITTED , "no permission to update gpio"],
[PI_SOME_PERMITTED , "no permission to update one or more gpios"],
[PI_BAD_WVSC_COMMND , "bad WVSC subcommand"],
[PI_BAD_STOPBITS , "serial (half) stop bits not 2-8"],
[PI_MSG_TOOBIG , "socket/pipe message too big"],
[PI_BAD_MALLOC_MODE , "bad memory allocation mode"],
+ [_PI_TOO_MANY_PARTS , "too many I2C transaction parts"],
+ [_PI_BAD_I2C_PART , "a combined I2C transaction failed"],
+ [PI_BAD_SMBUS_CMD , "SMBus command not supported"],
+ [PI_NOT_I2C_GPIO , "no bit bang I2C in progress on gpio"],
]
if (cb.edge ^ newLevel):
cb.func(cb.gpio, newLevel, tick)
else:
- gpio = flags & 31
- for cb in self.callbacks:
- if cb.gpio == gpio:
- cb.func(cb.gpio, TIMEOUT, tick)
+ if flags & NTFY_FLAGS_WDOG:
+ gpio = flags & NTFY_FLAGS_GPIO
+ for cb in self.callbacks:
+ if cb.gpio == gpio:
+ cb.func(cb.gpio, TIMEOUT, tick)
self.sl.s.close()
Normally you would only use the [*i2c_**] functions if
you are or will be connecting to the Pi over a network. If
- you will always run on the local Pi use the standard smbus
+ you will always run on the local Pi use the standard SMBus
module instead.
...
"""
Sends a single bit to the device associated with handle.
- smbus 2.0 5.5.1 - Quick command.
+ SMBus 2.0 5.5.1 - Quick command.
handle:= >=0 (as returned by a prior call to [*i2c_open*]).
bit:= 0 or 1, the value to write.
"""
Sends a single byte to the device associated with handle.
- smbus 2.0 5.5.2 - Send byte.
+ SMBus 2.0 5.5.2 - Send byte.
handle:= >=0 (as returned by a prior call to [*i2c_open*]).
byte_val:= 0-255, the value to write.
"""
Reads a single byte from the device associated with handle.
- smbus 2.0 5.5.3 - Receive byte.
+ SMBus 2.0 5.5.3 - Receive byte.
handle:= >=0 (as returned by a prior call to [*i2c_open*]).
Writes a single byte to the specified register of the device
associated with handle.
- smbus 2.0 5.5.4 - Write byte.
+ SMBus 2.0 5.5.4 - Write byte.
handle:= >=0 (as returned by a prior call to [*i2c_open*]).
reg:= >=0, the device register.
Writes a single 16 bit word to the specified register of the
device associated with handle.
- smbus 2.0 5.5.4 - Write word.
+ SMBus 2.0 5.5.4 - Write word.
handle:= >=0 (as returned by a prior call to [*i2c_open*]).
reg:= >=0, the device register.
Reads a single byte from the specified register of the device
associated with handle.
- smbus 2.0 5.5.5 - Read byte.
+ SMBus 2.0 5.5.5 - Read byte.
handle:= >=0 (as returned by a prior call to [*i2c_open*]).
reg:= >=0, the device register.
Reads a single 16 bit word from the specified register of the
device associated with handle.
- smbus 2.0 5.5.5 - Read word.
+ SMBus 2.0 5.5.5 - Read word.
handle:= >=0 (as returned by a prior call to [*i2c_open*]).
reg:= >=0, the device register.
Writes 16 bits of data to the specified register of the device
associated with handle and reads 16 bits of data in return.
- smbus 2.0 5.5.6 - Process call.
+ SMBus 2.0 5.5.6 - Process call.
handle:= >=0 (as returned by a prior call to [*i2c_open*]).
reg:= >=0, the device register.
Writes up to 32 bytes to the specified register of the device
associated with handle.
- smbus 2.0 5.5.7 - Block write.
+ SMBus 2.0 5.5.7 - Block write.
handle:= >=0 (as returned by a prior call to [*i2c_open*]).
reg:= >=0, the device register.
Reads a block of up to 32 bytes from the specified register of
the device associated with handle.
- smbus 2.0 5.5.7 - Block read.
+ SMBus 2.0 5.5.7 - Block read.
handle:= >=0 (as returned by a prior call to [*i2c_open*]).
reg:= >=0, the device register.
associated with handle and reads a device specified number
of bytes of data in return.
- smbus 2.0 5.5.8 - Block write-block read.
+ SMBus 2.0 5.5.8 - Block write-block read.
handle:= >=0 (as returned by a prior call to [*i2c_open*]).
reg:= >=0, the device register.
data:= the bytes to write.
- The smbus 2.0 documentation states that a minimum of 1 byte may
+ The SMBus 2.0 documentation states that a minimum of 1 byte may
be sent and a minimum of 1 byte may be received. The total
number of bytes sent/received must be 32 or less.