*/
/*
-This version is for pigpio version 56+
+This version is for pigpio version 57+
*/
#include <stdio.h>
{PI_CMD_BS1, "BS1", 111, 1}, // gpioWrite_Bits_0_31_Set
{PI_CMD_BS2, "BS2", 111, 1}, // gpioWrite_Bits_32_53_Set
+ {PI_CMD_BSCX, "BSCX", 193, 8}, // bscXfer
+
{PI_CMD_BSPIC, "BSPIC", 112, 0}, // bbSPIClose
{PI_CMD_BSPIO, "BSPIO", 134, 0}, // bbSPIOpen
{PI_CMD_BSPIX, "BSPIX", 193, 6}, // bbSPIXfer
{PI_CMD_CGI, "CGI", 101, 4}, // gpioCfgGetInternals
{PI_CMD_CSI, "CSI", 111, 1}, // gpioCfgSetInternals
+ {PI_CMD_EVM, "EVM", 122, 1}, // eventMonitor
+ {PI_CMD_EVT, "EVT", 112, 0}, // eventTrigger
+
{PI_CMD_FC, "FC", 112, 0}, // fileClose
{PI_CMD_FG, "FG", 121, 0}, // gpioGlitchFilter
{PI_CMD_DCR , "DCR" , 113, 0},
{PI_CMD_DCRA , "DCRA" , 101, 0},
{PI_CMD_DIV , "DIV" , 111, 0},
+ {PI_CMD_EVTWT, "EVTWT", 111, 0},
{PI_CMD_HALT , "HALT" , 101, 0},
{PI_CMD_INR , "INR" , 113, 0},
{PI_CMD_INRA , "INRA" , 101, 0},
\n\
BR1 Read bank 1 GPIO\n\
BR2 Read bank 2 GPIO\n\
+\n\
BS1 bits Set GPIO in bank 1\n\
BS2 bits Set GPIO in bank 2\n\
\n\
+BSCX bctl bvs BSC I2C/SPI transfer\n\
+\n\
CF1 ... Custom function 1\n\
CF2 ... Custom function 2\n\
\n\
CGI Configuration get internals\n\
CSI v Configuration set internals\n\
\n\
+EVM h bits Set events to monitor\n\
+EVT n Trigger event\n\
+\n\
FC h Close file handle\n\
FG g steady Set glitch filter on GPIO\n\
FL pat n List files which match pattern\n\
{PI_BAD_SCRIPT_NAME , "bad script name"},
{PI_BAD_SPI_BAUD , "bad SPI baud rate, not 50-500k"},
{PI_NOT_SPI_GPIO , "no bit bang SPI in progress on GPIO"},
+ {PI_BAD_EVENT_ID , "bad event id"},
};
break;
- case 193: /* BI2CZ FW I2CWD I2CZ SERW SPIW SPIX
- BSPIX
+ case 193: /* BI2CZ BSCX BSPIX FW I2CWD I2CZ SERW
+ SPIW SPIX
Two or more parameters, first >=0, rest 0-255.
+
+ BSCX is special case one or more.
*/
ctl->eaten += getNum(buf+ctl->eaten, &p[1], &ctl->opt[1]);
p[3] = pars;
- if (pars) valid = 1;
+ if (pars || (p[0]==PI_CMD_BSCX)) valid = 1;
}
break;
*/
/*
-This version is for pigpio version 56+
+This version is for pigpio version 57+
*/
#ifndef COMMAND_H
.br
.br
-flags: two flags are defined, PI_NTFY_FLAGS_WDOG and PI_NTFY_FLAGS_ALIVE.
+flags: three flags are defined, PI_NTFY_FLAGS_WDOG,
+PI_NTFY_FLAGS_ALIVE, and PI_NTFY_FLAGS_EVENT.
.br
.br
-PI_NTFY_FLAGS_WDOG, if bit 5 is set then bits 0-4 of the flags
+If bit 5 is set (PI_NTFY_FLAGS_WDOG) then bits 0-4 of the flags
indicate a GPIO which has had a watchdog timeout.
.br
.br
-PI_NTFY_FLAGS_ALIVE, if bit 6 is set this indicates a keep alive
+If bit 6 is set (PI_NTFY_FLAGS_ALIVE) this indicates a keep alive
signal on the pipe/socket and is sent once a minute in the absence
of other notification activity.
.br
+.br
+If bit 7 is set (PI_NTFY_FLAGS_EVENT) then bits 0-4 of the flags
+indicate an event which has been triggered.
+
+.br
+
.br
tick: the number of microseconds since system boot. It wraps around
after 1h12m.
.EE
+.IP "\fBint bscXfer(bsc_xfer_t *bsc_xfer)\fP"
+.IP "" 4
+This function provides a low-level interface to the
+SPI/I2C Slave peripheral. This peripheral allows the
+Pi to act as a slave device on an I2C or SPI bus.
+
+.br
+
+.br
+I can't get SPI to work properly. I tried with a
+control word of 0x303 and swapped MISO and MOSI.
+
+.br
+
+.br
+The function sets the BSC mode, writes any data in
+the transmit buffer to the BSC transmit FIFO, and
+copies any data in the BSC receive FIFO to the
+receive buffer.
+
+.br
+
+.br
+
+.EX
+bsc_xfer:= a structure defining the transfer
+.br
+
+.br
+typedef struct
+.br
+{
+.br
+ uint32_t control; // Write
+.br
+ int rxCnt; // Read only
+.br
+ char rxBuf[BSC_FIFO_SIZE]; // Read only
+.br
+ int txCnt; // Write
+.br
+ char txBuf[BSC_FIFO_SIZE]; // Write
+.br
+} bsc_xfer_t;
+.br
+
+.EE
+
+.br
+
+.br
+To start a transfer set control (see below) and copy the bytes to
+be sent (if any) to txBuf and set the byte count in txCnt.
+
+.br
+
+.br
+Upon return rxCnt will be set to the number of received bytes placed
+in rxBuf.
+
+.br
+
+.br
+Note that the control word sets the BSC mode. The BSC will stay in
+that mode until a different control word is sent.
+
+.br
+
+.br
+The BSC peripheral uses GPIO 18 (SDA) and 19 (SCL) in I2C mode
+and GPIO 18 (MOSI), 19 (SCLK), 20 (MISO), and 21 (CE) in SPI mode. You
+need to swap MISO/MOSI between master and slave.
+
+.br
+
+.br
+When a zero control word is received GPIO 18-21 will be reset
+to INPUT mode.
+
+.br
+
+.br
+The returned function value is the status of the transfer (see below).
+
+.br
+
+.br
+If there was an error the status will be less than zero
+(and will contain the error code).
+
+.br
+
+.br
+The most significant word of the returned status contains the number
+of bytes actually copied from txBuf to the BSC transmit FIFO (may be
+less than requested if the FIFO already contained untransmitted data).
+
+.br
+
+.br
+control consists of the following bits.
+
+.br
+
+.br
+
+.EX
+22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+.br
+ a a a a a a a - - IT HC TF IR RE TE BK EC ES PL PH I2 SP EN
+.br
+
+.EE
+
+.br
+
+.br
+Bits 0-13 are copied unchanged to the BSC CR register. See
+pages 163-165 of the Broadcom peripherals document for full
+details.
+
+.br
+
+.br
+aaaaaaa defines the I2C slave address (only relevant in I2C mode)
+.br
+IT invert transmit status flags
+.br
+HC enable host control
+.br
+TF enable test FIFO
+.br
+IR invert receive status flags
+.br
+RE enable receive
+.br
+TE enable transmit
+.br
+BK abort operation and clear FIFOs
+.br
+EC send control register as first I2C byte
+.br
+ES send status register as first I2C byte
+.br
+PL set SPI polarity high
+.br
+PH set SPI phase high
+.br
+I2 enable I2C mode
+.br
+SP enable SPI mode
+.br
+EN enable BSC peripheral
+.br
+
+.br
+
+.br
+The returned status has the following format
+
+.br
+
+.br
+
+.EX
+20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+.br
+ S S S S S R R R R R T T T T T RB TE RF TF RE TB
+.br
+
+.EE
+
+.br
+
+.br
+Bits 0-15 are copied unchanged from the BSC FR register. See
+pages 165-166 of the Broadcom peripherals document for full
+details.
+
+.br
+
+.br
+SSSSS number of bytes successfully copied to transmit FIFO
+.br
+RRRRR number of bytes in receieve FIFO
+.br
+TTTTT number of bytes in transmit FIFO
+.br
+RB receive busy
+.br
+TE transmit FIFO empty
+.br
+RF receive FIFO full
+.br
+TF transmit FIFO full
+.br
+RE receive FIFO empty
+.br
+TB transmit busy
+.br
+
+.br
+
+.br
+The following example shows how to configure the BSC peripheral as
+an I2C slave with address 0x13 and send four bytes.
+
+.br
+
+.br
+\fBExample\fP
+.br
+
+.EX
+bsc_xfer_t xfer;
+.br
+
+.br
+xfer.control = (0x13<<16) | 0x305;
+.br
+
+.br
+memcpy(xfer.txBuf, "ABCD", 4);
+.br
+xfer.txCnt = 4;
+.br
+
+.br
+status = bscXfer(&xfer);
+.br
+
+.br
+if (status >= 0)
+.br
+{
+.br
+ // process transfer
+.br
+}
+.br
+
+.EE
+
.IP "\fBint bbSPIOpen(unsigned CS, unsigned MISO, unsigned MOSI, unsigned SCLK, unsigned baud, unsigned spiFlags)\fP"
.IP "" 4
This function selects a set of GPIO for bit banging SPI with
Returns the read byte (>=0) if OK, otherwise PI_BAD_HANDLE,
PI_SER_READ_NO_DATA, or PI_SER_READ_FAILED.
+.br
+
+.br
+If no data is ready PI_SER_READ_NO_DATA is returned.
+
.IP "\fBint serWrite(unsigned handle, char *buf, unsigned count)\fP"
.IP "" 4
This function writes count bytes from buf to the the serial port
.br
.br
-Returns the number of bytes read (>0) if OK, otherwise PI_BAD_HANDLE,
+Returns the number of bytes read (>0=) if OK, otherwise PI_BAD_HANDLE,
PI_BAD_PARAM, or PI_SER_READ_NO_DATA.
+.br
+
+.br
+If no data is ready zero is returned.
+
.IP "\fBint serDataAvailable(unsigned handle)\fP"
.IP "" 4
This function returns the number of bytes available
.EE
+.IP "\fBint eventMonitor(unsigned handle, uint32_t bits)\fP"
+.IP "" 4
+This function selects the events to be reported on a previously
+opened handle.
+
+.br
+
+.br
+
+.EX
+handle: >=0, as returned by \fBgpioNotifyOpen\fP
+.br
+ bits: a bit mask indicating the events of interest
+.br
+
+.EE
+
+.br
+
+.br
+Returns 0 if OK, otherwise PI_BAD_HANDLE.
+
+.br
+
+.br
+A report is sent each time an event is triggered providing the
+corresponding bit in bits is set.
+
+.br
+
+.br
+See \fBgpioNotifyBegin\fP for the notification format.
+
+.br
+
+.br
+\fBExample\fP
+.br
+
+.EX
+// Start reporting events 3, 6, and 7.
+.br
+
+.br
+// bit 76543210
+.br
+// (0xC8 = 0b11001000)
+.br
+
+.br
+eventMonitor(h, 0xC8);
+.br
+
+.EE
+
+.br
+
+.br
+
+.IP "\fBint eventSetFunc(unsigned event, eventFunc_t f)\fP"
+.IP "" 4
+Registers a function to be called (a callback) when the specified
+event occurs.
+
+.br
+
+.br
+
+.EX
+event: 0-31
+.br
+ f: the callback function
+.br
+
+.EE
+
+.br
+
+.br
+Returns 0 if OK, otherwise PI_BAD_EVENT_ID.
+
+.br
+
+.br
+One function may be registered per event.
+
+.br
+
+.br
+The function is passed the event, and the tick.
+
+.br
+
+.br
+The callback may be cancelled by passing NULL as the function.
+
+.IP "\fBint eventSetFuncEx(unsigned event, eventFuncEx_t f, void *userdata)\fP"
+.IP "" 4
+Registers a function to be called (a callback) when the specified
+event occurs.
+
+.br
+
+.br
+
+.EX
+ event: 0-31
+.br
+ f: the callback function
+.br
+userdata: pointer to arbitrary user data
+.br
+
+.EE
+
+.br
+
+.br
+Returns 0 if OK, otherwise PI_BAD_EVENT_ID.
+
+.br
+
+.br
+One function may be registered per event.
+
+.br
+
+.br
+The function is passed the event, the tick, and the ueserdata pointer.
+
+.br
+
+.br
+The callback may be cancelled by passing NULL as the function.
+
+.br
+
+.br
+Only one of \fBeventSetFunc\fP or \fBeventSetFuncEx\fP can be
+registered per event.
+
+.IP "\fBint eventTrigger(unsigned event)\fP"
+.IP "" 4
+This function signals the occurrence of an event.
+
+.br
+
+.br
+
+.EX
+event: 0-31, the event
+.br
+
+.EE
+
+.br
+
+.br
+Returns 0 if OK, otherwise PI_BAD_EVENT_ID.
+
+.br
+
+.br
+An event is a signal used to inform one or more consumers
+to start an action. Each consumer which has registered an interest
+in the event (e.g. by calling \fBeventSetFunc\fP) will be informed by
+a callback.
+
+.br
+
+.br
+One event, PI_EVENT_BSC (31) is predefined. This event is
+auto generated on BSC slave activity.
+
+.br
+
+.br
+The meaning of other events is arbitrary.
+
+.br
+
+.br
+Note that other than its id and its tick there is no data associated
+with an event.
+
.IP "\fBint shell(char *scriptName, char *scriptString)\fP"
.IP "" 4
This function uses the system call to execute a shell script
.br
+.IP "\fB*bsc_xfer\fP" 0
+A pointer to a \fBbsc_xfer_t\fP object used to control a BSC transfer.
+
+.br
+
+.br
+
+.IP "\fBbsc_xfer_t\fP" 0
+
+.br
+
+.br
+
+.EX
+typedef struct
+.br
+{
+.br
+ uint32_t control; // Write
+.br
+ int rxCnt; // Read only
+.br
+ char rxBuf[BSC_FIFO_SIZE]; // Read only
+.br
+ int txCnt; // Write
+.br
+ char txBuf[BSC_FIFO_SIZE]; // Write
+.br
+} bsc_xfer_t;
+.br
+
+.EE
+
+.br
+
+.br
+
.IP "\fB*buf\fP" 0
.br
.br
.IP "\fBedge\fP: 0-2" 0
-The type of GPIO edge to generate an intrrupt. See \fBgpioSetISRFunc\fP,
+The type of GPIO edge to generate an interrupt. See \fBgpioSetISRFunc\fP
and \fBgpioSetISRFuncEx\fP.
.br
.br
+.IP "\fBevent\fP: 0-31" 0
+An event is a signal used to inform one or more consumers
+to start an action.
+
+.br
+
+.br
+
+.IP "\fBeventFunc_t\fP" 0
+
+.EX
+typedef void (*eventFunc_t) (int event, uint32_t tick);
+.br
+
+.EE
+
+.br
+
+.br
+
+.IP "\fBeventFuncEx_t\fP" 0
+
+.EX
+typedef void (*eventFuncEx_t)
+.br
+ (int event, uint32_t tick, void *userdata);
+.br
+
+.EE
+
+.br
+
+.br
+
.IP "\fBf\fP" 0
.br
.IP "\fBgpioAlertFuncEx_t\fP" 0
.EX
-typedef void (*gpioAlertFuncEx_t)
+typedef void (*eventFuncEx_t)
.br
- (int gpio, int level, uint32_t tick, void *userdata);
+ (int event, int level, uint32_t tick, void *userdata);
.br
.EE
.br
.br
-A number referencing an object opened by one of \fBfileOpen\fP,
-\fBgpioNotifyOpen\fP, \fBi2cOpen\fP, \fBserOpen\fP, \fBspiOpen\fP.
+A number referencing an object opened by one of
+
+.br
+
+.br
+\fBfileOpen\fP
+.br
+\fBgpioNotifyOpen\fP
+.br
+\fBi2cOpen\fP
+.br
+\fBserOpen\fP
+.br
+\fBspiOpen\fP
.br
The setting of the pull up/down resistor for a GPIO, which may be off,
pull-up, or pull-down.
+.br
+
+.br
+
.EX
PI_PUD_OFF 0
.br
.br
.br
+
+.EX
user_type *userdata;
.br
+.br
+.br
user_type my_userdata;
-
.br
.br
userdata = malloc(sizeof(user_type));
.br
+.br
+.br
*userdata = my_userdata;
+.br
+
+.EE
.br
.br
.br
-user_type my_userdata = *(user_type*)userdata;
+.EX
+user_type my_userdata = *(user_type*)userdata;
.br
.br
free(userdata);
+.br
+
+.EE
.br
#define PI_CMD_BSPIX 113
.br
+.br
+#define PI_CMD_BSCX 114
+.br
+
+.br
+#define PI_CMD_EVM 115
+.br
+#define PI_CMD_EVT 116
+.br
+
.br
.EE
.br
#define PI_NOT_SPI_GPIO -142 // no bit bang SPI in progress on GPIO
.br
+#define PI_BAD_EVENT_ID -143 // bad event id
+.br
.br
#define PI_PIGIF_ERR_0 -2000
For more information, please refer to <http://unlicense.org/>
*/
-/* pigpio version 56 */
+/* pigpio version 57 */
/* include ------------------------------------------------------- */
#define PI_PERI_BUS 0x7E000000
#define AUX_BASE (pi_peri_phys + 0x00215000)
+#define BSCS_BASE (pi_peri_phys + 0x00214000)
#define CLK_BASE (pi_peri_phys + 0x00101000)
#define DMA_BASE (pi_peri_phys + 0x00007000)
#define DMA15_BASE (pi_peri_phys + 0x00E05000)
#define SYST_BASE (pi_peri_phys + 0x00003000)
#define AUX_LEN 0xD8
+#define BSCS_LEN 0x40
#define CLK_LEN 0xA8
#define DMA_LEN 0x1000 /* allow access to all channels */
#define GPIO_LEN 0xB4
} gpioAlert_t;
+typedef struct
+{
+ callbk_t func;
+ unsigned ex;
+ void *userdata;
+ int ignore;
+ int fired;
+} eventAlert_t;
+
typedef struct
{
unsigned gpio;
unsigned request;
unsigned run_state;
uint32_t waitBits;
+ uint32_t eventBits;
uint32_t changedBits;
pthread_t *pthIdp;
pthread_mutex_t pthMutex;
uint16_t seqno;
uint16_t state;
uint32_t bits;
+ uint32_t eventBits;
uint32_t lastReportTick;
int fd;
int pipe;
static volatile uint32_t nFilterBits = 0;
static volatile uint32_t wdogBits = 0;
+static volatile uint32_t scriptEventBits = 0;
+
static volatile int runState = PI_STARTING;
static int pthAlertRunning = 0;
static gpioAlert_t gpioAlert [PI_MAX_USER_GPIO+1];
+static eventAlert_t eventAlert [PI_MAX_EVENT+1];
+
static gpioISR_t gpioISR [PI_MAX_USER_GPIO+1];
static gpioGetSamples_t gpioGetSamples;
static dmaOPage_t * * dmaOBus = MAP_FAILED;
static volatile uint32_t * auxReg = MAP_FAILED;
+static volatile uint32_t * bscsReg = MAP_FAILED;
static volatile uint32_t * clkReg = MAP_FAILED;
static volatile uint32_t * dmaReg = MAP_FAILED;
static volatile uint32_t * gpioReg = MAP_FAILED;
static uint32_t old_spi_cntl0;
static uint32_t old_spi_cntl1;
+static uint32_t bscFR;
+
/* const --------------------------------------------------------- */
static const uint8_t clkDef[PI_MAX_GPIO + 1] =
static void intScriptBits(void);
+static void intScriptEventBits(void);
+
static int gpioNotifyOpenInBand(int fd);
static void initHWClk
uint32_t mask;
uint32_t tmp1, tmp2, tmp3, tmp4, tmp5;
gpioPulse_t *pulse;
+ bsc_xfer_t xfer;
int masked;
res = 0;
}
break;
+ case PI_CMD_BSCX:
+ xfer.control = p[1];
+ if (p[3] > BSC_FIFO_SIZE) p[3] = BSC_FIFO_SIZE;
+ xfer.txCnt = p[3];
+ if (p[3]) memcpy(&xfer.txBuf, buf, p[3]);
+ res = bscXfer(&xfer);
+ if (res >= 0)
+ {
+ memcpy(buf, &res, 4);
+ res = 4 + xfer.rxCnt;
+ if (res > 4) memcpy(buf+4, &xfer.rxBuf, res-4);
+ }
+ break;
+
case PI_CMD_BSPIO:
memcpy(&tmp1, buf+ 0, 4); // MISO
case PI_CMD_CSI: res = gpioCfgSetInternals(p[1]); break;
+ case PI_CMD_EVM: res = eventMonitor(p[1], p[2]); break;
+
+ case PI_CMD_EVT: res = eventTrigger(p[1]); break;
+
case PI_CMD_FC: res = fileClose(p[1]); break;
case PI_CMD_FG:
int serReadByte(unsigned handle)
{
+ int r;
char x;
DBG(DBG_USER, "handle=%d", handle);
if (serInfo[handle].state != PI_SER_OPENED)
SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
- if (read(serInfo[handle].fd, &x, 1) != 1)
- {
- if (errno == EAGAIN)
- return PI_SER_READ_NO_DATA;
- else
- return PI_SER_READ_FAILED;
- }
+ r = read(serInfo[handle].fd, &x, 1);
+
+ if (r == 1)
+ return ((int)x) & 0xFF;
+
+ else if (r == 0)
+ return PI_SER_READ_NO_DATA;
+
+ else if ((r == -1) && (errno == EAGAIN))
+ return PI_SER_READ_NO_DATA;
- return ((int)x) & 0xFF;
+ else
+ return PI_SER_READ_FAILED;
}
int serWrite(unsigned handle, char *buf, unsigned count)
}
else
{
- buf[r] = 0;
+ if (r < count) buf[r] = 0;
return r;
}
}
uint32_t oldLevel, newLevel;
int32_t diff;
int emit, seqno, emitted;
- uint32_t changes, bits, timeoutBits;
+ uint32_t changes, bits, timeoutBits, eventBits;
int d;
int b, n, v;
int err;
}
}
+ eventBits = 0;
+
+ if (bscFR != (bscsReg[BSC_FR]&0xffff))
+ {
+ bscFR = bscsReg[BSC_FR]&0xffff;
+ eventAlert[PI_EVENT_BSC].fired = 1;
+ }
+
+ for (b=0; b<=PI_MAX_EVENT; b++)
+ {
+ if (eventAlert[b].fired && (!eventAlert[b].ignore))
+ {
+ eventBits |= (1<<b);
+
+ if (eventAlert[b].func)
+ {
+ if (eventAlert[b].ex)
+ {
+ (eventAlert[b].func)(b, eTick, eventAlert[b].userdata);
+ }
+ else
+ {
+ (eventAlert[b].func)(b, eTick);
+ }
+ }
+ }
+
+ eventAlert[b].fired = 0;
+ }
+
/* call alert callbacks for each bit transition */
if (changedBits & alertBits)
gpioNotify[n].state = PI_NOTIFY_CLOSED;
}
- else if (gpioNotify[n].state == PI_NOTIFY_RUNNING)
+ else if (gpioNotify[n].state != PI_NOTIFY_CLOSED)
{
bits = gpioNotify[n].bits;
seqno = gpioNotify[n].seqno;
- /* check to see if any bits have changed for this
- notification.
+ if (gpioNotify[n].state == PI_NOTIFY_RUNNING)
+ {
+ /* check to see if any bits have changed for this
+ notification.
- bits is the set of notification bits
- changedBits is the set of changed bits
- */
+ bits is the set of notification bits
+ changedBits is the set of changed bits
+ */
- if (changedBits & bits)
- {
- oldLevel = reportedLevel & bits;
+ if (changedBits & bits)
+ {
+ oldLevel = reportedLevel & bits;
+
+ for (d=0; d<numSamples; d++)
+ {
+ newLevel = sample[d].level & bits;
+
+ if (newLevel != oldLevel)
+ {
+ report[emit].seqno = seqno;
+ report[emit].flags = 0;
+ report[emit].tick = sample[d].tick;
+ report[emit].level = sample[d].level;
- for (d=0; d<numSamples; d++)
+ oldLevel = newLevel;
+
+ emit++;
+ seqno++;
+ }
+ }
+ }
+
+ /* check to see if any watchdogs are due for this
+ notification.
+
+ bits is the set of notification bits
+ timeoutBits is the set of timed out bits
+ */
+
+ bits = gpioNotify[n].bits;
+
+ if (timeoutBits & bits)
{
- newLevel = sample[d].level & bits;
+ /* at least one watchdog has fired for this
+ notification.
+ */
- if (newLevel != oldLevel)
+ for (b=0; b<=PI_MAX_USER_GPIO; b++)
{
- report[emit].seqno = seqno;
- report[emit].flags = 0;
- report[emit].tick = sample[d].tick;
- report[emit].level = sample[d].level;
+ if (timeoutBits & bits & (1<<b))
+ {
+ if (numSamples)
+ newLevel = sample[numSamples-1].level;
+ else
+ newLevel = reportedLevel;
- oldLevel = newLevel;
+ report[emit].seqno = seqno;
+ report[emit].flags =
+ PI_NTFY_FLAGS_WDOG | PI_NTFY_FLAGS_BIT(b);
+ report[emit].tick = eTick;
+ report[emit].level = newLevel;
- emit++;
- seqno++;
+ emit++;
+ seqno++;
+ }
}
}
}
- /* check to see if any watchdogs are due for this
- notification.
+ /* check to see if any events are due
- bits is the set of notification bits
- timeoutBits is the set of timed out bits
+ eventBits is the set of events
*/
- bits = gpioNotify[n].bits;
-
- if (timeoutBits & bits)
+ if (eventBits & gpioNotify[n].eventBits)
{
- /* at least one watchdog has fired for this
- notification.
- */
-
- for (b=0; b<=PI_MAX_USER_GPIO; b++)
+ for (b=0; b<=PI_MAX_EVENT; b++)
{
- if (timeoutBits & bits & (1<<b))
+ if (eventBits & gpioNotify[n].eventBits & (1<<b))
{
if (numSamples)
newLevel = sample[numSamples-1].level;
newLevel = reportedLevel;
report[emit].seqno = seqno;
- report[emit].flags = PI_NTFY_FLAGS_WDOG |
- PI_NTFY_FLAGS_BIT(b);
+ report[emit].flags =
+ PI_NTFY_FLAGS_EVENT | PI_NTFY_FLAGS_BIT(b);
report[emit].tick = eTick;
report[emit].level = newLevel;
}
}
+ if (eventBits & scriptEventBits)
+ {
+ for (n=0; n<PI_MAX_SCRIPTS; n++)
+ {
+ if ((gpioScript[n].state == PI_SCRIPT_IN_USE) &&
+ (gpioScript[n].run_state == PI_SCRIPT_WAITING) &&
+ (gpioScript[n].eventBits & eventBits))
+ {
+ pthread_mutex_lock(&gpioScript[n].pthMutex);
+
+ if (gpioScript[n].run_state == PI_SCRIPT_WAITING)
+ {
+ gpioScript[n].changedBits =
+ gpioScript[n].eventBits & eventBits;
+ pthread_cond_signal(&gpioScript[n].pthCond);
+ }
+
+ pthread_mutex_unlock(&gpioScript[n].pthMutex);
+ }
+ }
+ }
+
if (numSamples) reportedLevel = sample[numSamples-1].level;
}
/* ----------------------------------------------------------------------- */
+static int scrEvtWait(gpioScript_t *s, uint32_t bits)
+{
+ pthread_mutex_lock(&s->pthMutex);
+
+ if (s->request == PI_SCRIPT_RUN)
+ {
+ s->run_state = PI_SCRIPT_WAITING;
+ s->eventBits = bits;
+ intScriptEventBits();
+
+ pthread_cond_wait(&s->pthCond, &s->pthMutex);
+
+ s->waitBits = 0;
+ intScriptEventBits();
+ s->run_state = PI_SCRIPT_RUNNING;
+ }
+
+ pthread_mutex_unlock(&s->pthMutex);
+
+ return s->changedBits;
+}
+
+/* ----------------------------------------------------------------------- */
+
static int scrWait(gpioScript_t *s, uint32_t bits)
{
pthread_mutex_lock(&s->pthMutex);
case PI_CMD_DIV: A/=p1; F=A; PC++; break;
- case PI_CMD_HALT: s->run_state = PI_SCRIPT_HALTED; break;
+ case PI_CMD_HALT: s->run_state = PI_SCRIPT_HALTED; break;
+
+ case PI_CMD_EVTWT: A=scrEvtWait(s, p1); F=A; PC++; break;
case PI_CMD_INR:
if (instr.opt[1] == CMD_PAR)
/* extensions */
case PI_CMD_BI2CZ:
+ case PI_CMD_BSCX:
case PI_CMD_CF2:
case PI_CMD_FL:
case PI_CMD_FR:
if (padsReg == MAP_FAILED)
SOFT_ERROR(PI_INIT_FAILED, "mmap pads failed (%m)");
+ bscsReg = initMapMem(fdMem, BSCS_BASE, BSCS_LEN);
+
+ if (bscsReg == MAP_FAILED)
+ SOFT_ERROR(PI_INIT_FAILED, "mmap bscs failed (%m)");
+
return 0;
}
gpioTimer[i].func = NULL;
}
+ for (i=0; i<=PI_MAX_EVENT; i++)
+ {
+ eventAlert[i].func = NULL;
+ eventAlert[i].ignore = 0;
+ eventAlert[i].fired = 0;
+ }
+
/* calculate the usable PWM frequencies */
for (i=0; i<PWM_FREQS; i++)
/* release mmap'd memory */
if (auxReg != MAP_FAILED) munmap((void *)auxReg, AUX_LEN);
+ if (bscsReg != MAP_FAILED) munmap((void *)bscsReg, BSCS_LEN);
if (clkReg != MAP_FAILED) munmap((void *)clkReg, CLK_LEN);
if (dmaReg != MAP_FAILED) munmap((void *)dmaReg, DMA_LEN);
if (gpioReg != MAP_FAILED) munmap((void *)gpioReg, GPIO_LEN);
if (spiReg != MAP_FAILED) munmap((void *)spiReg, SPI_LEN);
auxReg = MAP_FAILED;
+ bscsReg = MAP_FAILED;
clkReg = MAP_FAILED;
dmaReg = MAP_FAILED;
gpioReg = MAP_FAILED;
static int read_SDA(wfRx_t *w)
{
myGpioSetMode(w->I.SDA, PI_INPUT);
- return gpioRead(w->I.SDA);
+ return myGpioRead(w->I.SDA);
}
static void set_SDA(wfRx_t *w)
myGpioSetMode(w->I.SCL, PI_INPUT);
now = gpioTick();
- while ((gpioRead(w->I.SCL) == 0) && ((gpioTick()-now) < max_stretch));
+ while ((myGpioRead(w->I.SCL) == 0) && ((gpioTick()-now) < max_stretch));
}
static void I2CStart(wfRx_t *w)
/* ----------------------------------------------------------------------- */
+void bscInit(int mode)
+{
+ bscsReg[BSC_CR]=0; /* clear device */
+ bscsReg[BSC_RSR]=0; /* clear underrun and overrun errors */
+ bscsReg[BSC_SLV]=0; /* clear I2C slave address */
+ bscsReg[BSC_IMSC]=0xf; /* mask off all interrupts */
+ bscsReg[BSC_ICR]=0x0f; /* clear all interrupts */
+
+ gpioSetMode(BSC_SDA_MOSI, PI_ALT3);
+ gpioSetMode(BSC_SCL_SCLK, PI_ALT3);
+
+ if (mode > 1) /* SPI uses all GPIO */
+ {
+ gpioSetMode(BSC_MISO, PI_ALT3);
+ gpioSetMode(BSC_CE_N, PI_ALT3);
+ }
+}
+
+void bscTerm(int mode)
+{
+ bscsReg[BSC_CR] = 0; /* clear device */
+ bscsReg[BSC_RSR]=0; /* clear underrun and overrun errors */
+ bscsReg[BSC_SLV]=0; /* clear I2C slave address */
+
+ gpioSetMode(BSC_SDA_MOSI, PI_INPUT);
+ gpioSetMode(BSC_SCL_SCLK, PI_INPUT);
+
+ if (mode > 1)
+ {
+ gpioSetMode(BSC_MISO, PI_INPUT);
+ gpioSetMode(BSC_CE_N, PI_INPUT);
+ }
+}
+
+int bscXfer(bsc_xfer_t *xfer)
+{
+ static int bscMode = 0;
+
+ int copied=0;
+ int active, mode;
+
+ DBG(DBG_USER, "control=0x%X (sa=0x%X, cr=0x%X) tx=%d [%s]",
+ xfer->control,
+ ((xfer->control)>>16) & 127,
+ (xfer->control) & 0x3fff,
+ xfer->txCnt,
+ myBuf2Str(xfer->txCnt, (char *)xfer->txBuf));
+
+ CHECK_INITED;
+
+ eventAlert[PI_EVENT_BSC].ignore = 1;
+
+ if (xfer->control)
+ {
+ /*
+ bscMode (0=None, 1=I2C, 2=SPI) tracks which GPIO have been
+ set to BSC mode
+ */
+ if (xfer->control & 2) mode = 2; /* SPI */
+ else mode = 1; /* assume I2C */
+
+ if (mode > bscMode)
+ {
+ bscInit(bscMode);
+ bscMode = mode;
+ }
+ }
+ else
+ {
+ if (bscMode) bscTerm(bscMode);
+ bscMode = 0;
+ return 0; /* leave ignore set */
+ }
+
+ xfer->rxCnt = 0;
+
+ bscsReg[BSC_SLV] = ((xfer->control)>>16) & 127;
+ bscsReg[BSC_CR] = (xfer->control) & 0x3fff;
+ bscsReg[BSC_RSR]=0; /* clear underrun and overrun errors */
+
+ active = 1;
+
+ while (active)
+ {
+ active = 0;
+
+ while ((copied < xfer->txCnt) &&
+ (!(bscsReg[BSC_FR] & BSC_FR_TXFF)))
+ {
+ bscsReg[BSC_DR] = xfer->txBuf[copied++];
+ active = 1;
+ }
+
+ while ((xfer->rxCnt < BSC_FIFO_SIZE) &&
+ (!(bscsReg[BSC_FR] & BSC_FR_RXFE)))
+ {
+ xfer->rxBuf[xfer->rxCnt++] = bscsReg[BSC_DR];
+ active = 1;
+ }
+
+ myGpioSleep(0, 200);
+ }
+
+ bscFR = bscsReg[BSC_FR] & 0xffff;
+
+ eventAlert[PI_EVENT_BSC].ignore = 0;
+
+ return (copied<<16) | bscFR;
+}
+
+/* ----------------------------------------------------------------------- */
+
static void set_CS(wfRx_t *w)
{
myGpioWrite(w->S.CS, PI_SPI_FLAGS_GET_CSPOL(w->S.spiFlags));
}
+/* ----------------------------------------------------------------------- */
+
+static int intEventSetFunc(
+ unsigned event,
+ void * f,
+ int user,
+ void * userdata)
+{
+ DBG(DBG_INTERNAL, "event=%d function=%08X, user=%d, userdata=%08X",
+ event, (uint32_t)f, user, (uint32_t)userdata);
+
+ eventAlert[event].ex = user;
+ eventAlert[event].userdata = userdata;
+
+ eventAlert[event].func = f;
+
+ return 0;
+}
+
+
+/* ----------------------------------------------------------------------- */
+
+int eventSetFunc(unsigned event, eventFunc_t f)
+{
+ DBG(DBG_USER, "event=%d function=%08X", event, (uint32_t)f);
+
+ CHECK_INITED;
+
+ if (event > PI_MAX_EVENT)
+ SOFT_ERROR(PI_BAD_EVENT_ID, "bad event (%d)", event);
+
+ intEventSetFunc(event, f, 0, NULL);
+
+ return 0;
+}
+
+
+/* ----------------------------------------------------------------------- */
+
+int eventSetFuncEx(unsigned event, eventFuncEx_t f, void *userdata)
+{
+ DBG(DBG_USER, "event=%d function=%08X userdata=%08X",
+ event, (uint32_t)f, (uint32_t)userdata);
+
+ CHECK_INITED;
+
+ if (event > PI_MAX_EVENT)
+ SOFT_ERROR(PI_BAD_EVENT_ID, "bad event (%d)", event);
+
+ intEventSetFunc(event, f, 1, userdata);
+
+ return 0;
+}
+
+
+/* ----------------------------------------------------------------------- */
+
+int eventMonitor(unsigned handle, uint32_t bits)
+{
+ DBG(DBG_USER, "handle=%d bits=%08X", handle, bits);
+
+ CHECK_INITED;
+
+ if (handle >= PI_NOTIFY_SLOTS)
+ SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
+
+ if (gpioNotify[handle].state <= PI_NOTIFY_CLOSING)
+ SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
+
+ gpioNotify[handle].eventBits = bits;
+
+ return 0;
+}
+
+
+/* ----------------------------------------------------------------------- */
+
+int eventTrigger(unsigned event)
+{
+ DBG(DBG_USER, "event=%d", event);
+
+ CHECK_INITED;
+
+ if (event > PI_MAX_EVENT)
+ SOFT_ERROR(PI_BAD_EVENT_ID, "bad event (%d)", event);
+
+ eventAlert[event].fired = 1;
+
+ return 0;
+}
+
+
/* ----------------------------------------------------------------------- */
static int intGpioSetAlertFunc(
}
+static void intScriptEventBits(void)
+{
+ int i;
+ uint32_t bits;
+
+ bits = 0;
+
+ for (i=0; i<PI_MAX_SCRIPTS; i++)
+ {
+ if (gpioScript[i].state == PI_SCRIPT_IN_USE)
+ {
+ bits |= gpioScript[i].eventBits;
+ }
+ }
+
+ scriptEventBits = bits;
+}
+
+
static void intNotifyBits(void)
{
int i;
{
if (gpioTimer[id].running)
{
+
/* destroy thread */
- if (pthread_cancel(gpioTimer[id].pthId))
- SOFT_ERROR(PI_TIMER_FAILED, "timer %d, cancel failed (%m)", id);
+ if (pthread_self() == gpioTimer[id].pthId)
+ {
+ gpioTimer[id].running = 0;
+ gpioTimer[id].func = 0;
+ pthread_exit(NULL);
+ }
+ else
+ {
+ if (pthread_cancel(gpioTimer[id].pthId))
+ SOFT_ERROR(PI_TIMER_FAILED, "timer %d, cancel failed (%m)", id);
- if (pthread_join(gpioTimer[id].pthId, NULL))
- SOFT_ERROR(PI_TIMER_FAILED, "timer %d, join failed (%m)", id);
+ if (pthread_join(gpioTimer[id].pthId, NULL))
+ SOFT_ERROR(PI_TIMER_FAILED, "timer %d, join failed (%m)", id);
- gpioTimer[id].running = 0;
- gpioTimer[id].func = f;
+ gpioTimer[id].running = 0;
+ gpioTimer[id].func = 0;
+ }
}
}
if (pth)
{
- pthread_cancel(*pth);
- pthread_join(*pth, NULL);
- free(pth);
+ if (pthread_self() == *pth)
+ {
+ free(pth);
+ pthread_exit(NULL);
+ }
+ else
+ {
+ pthread_cancel(*pth);
+ pthread_join(*pth, NULL);
+ free(pth);
+ }
}
}
#include <stdint.h>
#include <pthread.h>
-#define PIGPIO_VERSION 56
+#define PIGPIO_VERSION 57
/*TEXT
bbSPIClose Closes GPIO for bit banging SPI
bbSPIXfer Performs multiple bit banged SPI transactions
+I2C/SPI_SLAVE
+
+bscXfer I2C/SPI as slave transfer
+
SERIAL
serOpen Opens a serial device
fileSeek Seeks to a position within a file
fileList List files which match a pattern
+EVENTS
+
+eventMonitor Sets the events to monitor
+eventSetFunc Request an event callback
+eventSetFuncEx Request an event callback, extended
+eventTrigger Trigger an event
+
CONFIGURATION
gpioCfgBufferSize Configure the GPIO sample buffer size
uint8_t *buf; /* pointer to msg data */
} pi_i2c_msg_t;
+/* BSC FIFO size */
+
+#define BSC_FIFO_SIZE 16
+
+typedef struct
+{
+ uint32_t control; /* Write */
+ int rxCnt; /* Read only */
+ char rxBuf[BSC_FIFO_SIZE]; /* Read only */
+ int txCnt; /* Write */
+ char txBuf[BSC_FIFO_SIZE]; /* Write */
+} bsc_xfer_t;
+
+
typedef void (*gpioAlertFunc_t) (int gpio,
int level,
uint32_t tick);
uint32_t tick,
void *userdata);
+typedef void (*eventFunc_t) (int event,
+ uint32_t tick);
+
+typedef void (*eventFuncEx_t) (int event,
+ uint32_t tick,
+ void *userdata);
+
typedef void (*gpioISRFunc_t) (int gpio,
int level,
uint32_t tick);
#define PI_NOTIFY_SLOTS 32
+#define PI_NTFY_FLAGS_EVENT (1 <<7)
#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_SPI_FLAGS_CSPOLS(x) ((x&7)<<2)
#define PI_SPI_FLAGS_MODE(x) ((x&3))
+/* BSC registers */
+
+#define BSC_DR 0
+#define BSC_RSR 1
+#define BSC_SLV 2
+#define BSC_CR 3
+#define BSC_FR 4
+#define BSC_IFLS 5
+#define BSC_IMSC 6
+#define BSC_RIS 7
+#define BSC_MIS 8
+#define BSC_ICR 9
+#define BSC_DMACR 10
+#define BSC_TDR 11
+#define BSC_GPUSTAT 12
+#define BSC_HCTRL 13
+#define BSC_DEBUG_I2C 14
+#define BSC_DEBUG_SPI 15
+
+#define BSC_CR_TESTFIFO 2048
+#define BSC_CR_RXE 512
+#define BSC_CR_TXE 256
+#define BSC_CR_BRK 128
+#define BSC_CR_CPOL 16
+#define BSC_CR_CPHA 8
+#define BSC_CR_I2C 4
+#define BSC_CR_SPI 2
+#define BSC_CR_EN 1
+
+#define BSC_FR_RXBUSY 32
+#define BSC_FR_TXFE 16
+#define BSC_FR_RXFF 8
+#define BSC_FR_TXFF 4
+#define BSC_FR_RXFE 2
+#define BSC_FR_TXBUSY 1
+
+/* BSC GPIO */
+
+#define BSC_SDA_MOSI 18
+#define BSC_SCL_SCLK 19
+#define BSC_MISO 20
+#define BSC_CE_N 21
+
/* Longest busy delay */
#define PI_MAX_BUSY_DELAY 100
#define MAX_CONNECT_ADDRESSES 256
+/* events */
+
+#define PI_MAX_EVENT 31
+
+/* Event auto generated on BSC slave activity */
+
+#define PI_EVENT_BSC 31
+
/*F*/
int gpioInitialise(void);
/*D
seqno: starts at 0 each time the handle is opened and then increments
by one for each report.
-flags: two flags are defined, PI_NTFY_FLAGS_WDOG and PI_NTFY_FLAGS_ALIVE.
+flags: three flags are defined, PI_NTFY_FLAGS_WDOG,
+PI_NTFY_FLAGS_ALIVE, and PI_NTFY_FLAGS_EVENT.
-PI_NTFY_FLAGS_WDOG, if bit 5 is set then bits 0-4 of the flags
+If bit 5 is set (PI_NTFY_FLAGS_WDOG) then bits 0-4 of the flags
indicate a GPIO which has had a watchdog timeout.
-PI_NTFY_FLAGS_ALIVE, if bit 6 is set this indicates a keep alive
+If bit 6 is set (PI_NTFY_FLAGS_ALIVE) this indicates a keep alive
signal on the pipe/socket and is sent once a minute in the absence
of other notification activity.
+If bit 7 is set (PI_NTFY_FLAGS_EVENT) then bits 0-4 of the flags
+indicate an event which has been triggered.
+
tick: the number of microseconds since system boot. It wraps around
after 1h12m.
...
D*/
+/*F*/
+int bscXfer(bsc_xfer_t *bsc_xfer);
+/*D
+This function provides a low-level interface to the
+SPI/I2C Slave peripheral. This peripheral allows the
+Pi to act as a slave device on an I2C or SPI bus.
+
+I can't get SPI to work properly. I tried with a
+control word of 0x303 and swapped MISO and MOSI.
+
+The function sets the BSC mode, writes any data in
+the transmit buffer to the BSC transmit FIFO, and
+copies any data in the BSC receive FIFO to the
+receive buffer.
+
+. .
+bsc_xfer:= a structure defining the transfer
+
+typedef struct
+{
+ uint32_t control; // Write
+ int rxCnt; // Read only
+ char rxBuf[BSC_FIFO_SIZE]; // Read only
+ int txCnt; // Write
+ char txBuf[BSC_FIFO_SIZE]; // Write
+} bsc_xfer_t;
+. .
+
+To start a transfer set control (see below) and copy the bytes to
+be sent (if any) to txBuf and set the byte count in txCnt.
+
+Upon return rxCnt will be set to the number of received bytes placed
+in rxBuf.
+
+Note that the control word sets the BSC mode. The BSC will stay in
+that mode until a different control word is sent.
+
+The BSC peripheral uses GPIO 18 (SDA) and 19 (SCL) in I2C mode
+and GPIO 18 (MOSI), 19 (SCLK), 20 (MISO), and 21 (CE) in SPI mode. You
+need to swap MISO/MOSI between master and slave.
+
+When a zero control word is received GPIO 18-21 will be reset
+to INPUT mode.
+
+The returned function value is the status of the transfer (see below).
+
+If there was an error the status will be less than zero
+(and will contain the error code).
+
+The most significant word of the returned status contains the number
+of bytes actually copied from txBuf to the BSC transmit FIFO (may be
+less than requested if the FIFO already contained untransmitted data).
+
+control consists of the following bits.
+
+. .
+22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+ a a a a a a a - - IT HC TF IR RE TE BK EC ES PL PH I2 SP EN
+. .
+
+Bits 0-13 are copied unchanged to the BSC CR register. See
+pages 163-165 of the Broadcom peripherals document for full
+details.
+
+aaaaaaa @ defines the I2C slave address (only relevant in I2C mode)
+IT @ invert transmit status flags
+HC @ enable host control
+TF @ enable test FIFO
+IR @ invert receive status flags
+RE @ enable receive
+TE @ enable transmit
+BK @ abort operation and clear FIFOs
+EC @ send control register as first I2C byte
+ES @ send status register as first I2C byte
+PL @ set SPI polarity high
+PH @ set SPI phase high
+I2 @ enable I2C mode
+SP @ enable SPI mode
+EN @ enable BSC peripheral
+
+The returned status has the following format
+
+. .
+20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+ S S S S S R R R R R T T T T T RB TE RF TF RE TB
+. .
+
+Bits 0-15 are copied unchanged from the BSC FR register. See
+pages 165-166 of the Broadcom peripherals document for full
+details.
+
+SSSSS @ number of bytes successfully copied to transmit FIFO
+RRRRR @ number of bytes in receieve FIFO
+TTTTT @ number of bytes in transmit FIFO
+RB @ receive busy
+TE @ transmit FIFO empty
+RF @ receive FIFO full
+TF @ transmit FIFO full
+RE @ receive FIFO empty
+TB @ transmit busy
+
+The following example shows how to configure the BSC peripheral as
+an I2C slave with address 0x13 and send four bytes.
+
+...
+bsc_xfer_t xfer;
+
+xfer.control = (0x13<<16) | 0x305;
+
+memcpy(xfer.txBuf, "ABCD", 4);
+xfer.txCnt = 4;
+
+status = bscXfer(&xfer);
+
+if (status >= 0)
+{
+ // process transfer
+}
+...
+D*/
+
/*F*/
int bbSPIOpen(
unsigned CS, unsigned MISO, unsigned MOSI, unsigned SCLK,
Returns the read byte (>=0) if OK, otherwise PI_BAD_HANDLE,
PI_SER_READ_NO_DATA, or PI_SER_READ_FAILED.
+
+If no data is ready PI_SER_READ_NO_DATA is returned.
D*/
/*F*/
count: the maximum number of bytes to read
. .
-Returns the number of bytes read (>0) if OK, otherwise PI_BAD_HANDLE,
+Returns the number of bytes read (>0=) if OK, otherwise PI_BAD_HANDLE,
PI_BAD_PARAM, or PI_SER_READ_NO_DATA.
+
+If no data is ready zero is returned.
D*/
...
D*/
+/*F*/
+int eventMonitor(unsigned handle, uint32_t bits);
+/*D
+This function selects the events to be reported on a previously
+opened handle.
+
+. .
+handle: >=0, as returned by [*gpioNotifyOpen*]
+ bits: a bit mask indicating the events of interest
+. .
+
+Returns 0 if OK, otherwise PI_BAD_HANDLE.
+
+A report is sent each time an event is triggered providing the
+corresponding bit in bits is set.
+
+See [*gpioNotifyBegin*] for the notification format.
+
+...
+// Start reporting events 3, 6, and 7.
+
+// bit 76543210
+// (0xC8 = 0b11001000)
+
+eventMonitor(h, 0xC8);
+...
+
+D*/
+
+/*F*/
+int eventSetFunc(unsigned event, eventFunc_t f);
+/*D
+Registers a function to be called (a callback) when the specified
+event occurs.
+
+. .
+event: 0-31
+ f: the callback function
+. .
+
+Returns 0 if OK, otherwise PI_BAD_EVENT_ID.
+
+One function may be registered per event.
+
+The function is passed the event, and the tick.
+
+The callback may be cancelled by passing NULL as the function.
+D*/
+
+/*F*/
+int eventSetFuncEx(unsigned event, eventFuncEx_t f, void *userdata);
+/*D
+Registers a function to be called (a callback) when the specified
+event occurs.
+
+. .
+ event: 0-31
+ f: the callback function
+userdata: pointer to arbitrary user data
+. .
+
+Returns 0 if OK, otherwise PI_BAD_EVENT_ID.
+
+One function may be registered per event.
+
+The function is passed the event, the tick, and the ueserdata pointer.
+
+The callback may be cancelled by passing NULL as the function.
+
+Only one of [*eventSetFunc*] or [*eventSetFuncEx*] can be
+registered per event.
+D*/
+
+/*F*/
+int eventTrigger(unsigned event);
+/*D
+This function signals the occurrence of an event.
+
+. .
+event: 0-31, the event
+. .
+
+Returns 0 if OK, otherwise PI_BAD_EVENT_ID.
+
+An event is a signal used to inform one or more consumers
+to start an action. Each consumer which has registered an interest
+in the event (e.g. by calling [*eventSetFunc*]) will be informed by
+a callback.
+
+One event, PI_EVENT_BSC (31) is predefined. This event is
+auto generated on BSC slave activity.
+
+The meaning of other events is arbitrary.
+
+Note that other than its id and its tick there is no data associated
+with an event.
+D*/
+
/*F*/
int shell(char *scriptName, char *scriptString);
e.g. to select bits 5, 9, 23 you could use (1<<5) | (1<<9) | (1<<23).
+*bsc_xfer::
+A pointer to a [*bsc_xfer_t*] object used to control a BSC transfer.
+
+bsc_xfer_t::
+
+. .
+typedef struct
+{
+ uint32_t control; // Write
+ int rxCnt; // Read only
+ char rxBuf[BSC_FIFO_SIZE]; // Read only
+ int txCnt; // Write
+ char txBuf[BSC_FIFO_SIZE]; // Write
+} bsc_xfer_t;
+. .
+
*buf::
A buffer to hold data being sent or being received.
0 is off and range is fully on.
edge::0-2
-The type of GPIO edge to generate an intrrupt. See [*gpioSetISRFunc*],
+The type of GPIO edge to generate an interrupt. See [*gpioSetISRFunc*]
and [*gpioSetISRFuncEx*].
. .
EITHER_EDGE 2
. .
+event::0-31
+An event is a signal used to inform one or more consumers
+to start an action.
+
+eventFunc_t::
+. .
+typedef void (*eventFunc_t) (int event, uint32_t tick);
+. .
+
+eventFuncEx_t::
+. .
+typedef void (*eventFuncEx_t)
+ (int event, uint32_t tick, void *userdata);
+. .
+
f::
A function.
gpioAlertFuncEx_t::
. .
-typedef void (*gpioAlertFuncEx_t)
- (int gpio, int level, uint32_t tick, void *userdata);
+typedef void (*eventFuncEx_t)
+ (int event, int level, uint32_t tick, void *userdata);
. .
gpioCfg*::
handle::>=0
-A number referencing an object opened by one of [*fileOpen*],
-[*gpioNotifyOpen*], [*i2cOpen*], [*serOpen*], [*spiOpen*].
+A number referencing an object opened by one of
+
+[*fileOpen*]
+[*gpioNotifyOpen*]
+[*i2cOpen*]
+[*serOpen*]
+[*spiOpen*]
i2cAddr:: 0-0x7F
The address of a device on the I2C bus.
The setting of the pull up/down resistor for a GPIO, which may be off,
pull-up, or pull-down.
+
. .
PI_PUD_OFF 0
PI_PUD_DOWN 1
In the calling function:
+. .
user_type *userdata;
user_type my_userdata;
userdata = malloc(sizeof(user_type));
*userdata = my_userdata;
+. .
In the receiving function:
+. .
user_type my_userdata = *(user_type*)userdata;
free(userdata);
+. .
void::
#define PI_CMD_BSPIO 112
#define PI_CMD_BSPIX 113
+#define PI_CMD_BSCX 114
+
+#define PI_CMD_EVM 115
+#define PI_CMD_EVT 116
+
/*DEF_E*/
/*
#define PI_CMD_X 839
#define PI_CMD_XA 840
#define PI_CMD_XOR 841
+#define PI_CMD_EVTWT 842
/*DEF_S Error Codes*/
#define PI_BAD_SCRIPT_NAME -140 // bad script name
#define PI_BAD_SPI_BAUD -141 // bad SPI baud rate, not 50-500k
#define PI_NOT_SPI_GPIO -142 // no bit bang SPI in progress on GPIO
+#define PI_BAD_EVENT_ID -143 // bad event id
#define PI_PIGIF_ERR_0 -2000
#define PI_PIGIF_ERR_99 -2099
pigpio.exceptions to False.
You may prefer to check the returned status in only a few parts
-of your code. In that case do the following.
+of your code. In that case do the following:
...
pigpio.exceptions = False
bb_spi_close Closes GPIO for bit banging SPI
bb_spi_xfer Transfers bytes with bit banging SPI
+I2C/SPI_Slave
+
+bsc_xfer I2C/SPI as slave transfer
+bsc_i2c I2C as slave transfer
+
Serial
serial_open Opens a serial device
file_seek Seeks to a position within a file
file_list List files which match a pattern
+Events
+
+event_callback Sets a callback for an event
+event_trigger Triggers an event
+wait_for_event Wait for an event
+
Custom
custom_1 User custom function 1
import os
import atexit
-VERSION = "1.33"
+VERSION = "1.34"
exceptions = True
# notification flags
+NTFY_FLAGS_EVENT = (1 << 7)
NTFY_FLAGS_ALIVE = (1 << 6)
NTFY_FLAGS_WDOG = (1 << 5)
NTFY_FLAGS_GPIO = 31
SPI_TX_LSBFIRST = 1 << 14
SPI_RX_LSBFIRST = 1 << 15
+EVENT_BSC = 31
+
# pigpio command numbers
_PI_CMD_MODES= 0
_PI_CMD_BSPIO=112
_PI_CMD_BSPIX=113
+_PI_CMD_BSCX =114
+
+_PI_CMD_EVM =115
+_PI_CMD_EVT =116
+
# pigpio error numbers
_PI_INIT_FAILED =-1
PI_BAD_SCRIPT_NAME =-140
PI_BAD_SPI_BAUD =-141
PI_NOT_SPI_GPIO =-142
+PI_BAD_EVENT_ID =-143
# pigpio error text
[PI_BAD_SCRIPT_NAME , "bad script name"],
[PI_BAD_SPI_BAUD , "bad SPI baud rate, not 50-500k"],
[PI_NOT_SPI_GPIO , "no bit bang SPI in progress on GPIO"],
+ [PI_BAD_EVENT_ID , "bad event id"],
]
-except_a = "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n{}"
+_except_a = "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n{}"
-except_z = "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"
+_except_z = "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"
-except1 = """
+_except_1 = """
Did you start the pigpio daemon? E.g. sudo pigpiod
Did you specify the correct Pi host/port in the environment
Did you specify the correct Pi host/port in the
pigpio.pi() function? E.g. pigpio.pi('soft', 8888)"""
-except2 = """
+_except_2 = """
Do you have permission to access the pigpio daemon?
Perhaps it was started with sudo pigpiod -nlocalhost"""
if rl: sl.l.release()
return res
+class _event_ADT:
+ """
+ An ADT class to hold event callback information.
+ """
+
+ def __init__(self, event, func):
+ """
+ Initialises an event callback ADT.
+
+ event:= the event id.
+ func:= a user function taking one argument, the event id.
+ """
+ self.event = event
+ self.func = func
+ self.bit = 1<<event
+
class _callback_ADT:
"""An ADT class to hold callback information."""
self.go = False
self.daemon = True
self.monitor = 0
+ self.event_bits = 0
self.callbacks = []
+ self.events = []
self.sl.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sl.s.settimeout(None)
self.sl.s.connect((host, port))
_pigpio_command(
self.control, _PI_CMD_NB, self.handle, self.monitor)
+ def append_event(self, callb):
+ """
+ Adds an event callback to the notification thread.
+ """
+ self.events.append(callb)
+ self.event_bits = self.event_bits | callb.bit
+ _pigpio_command(self.control, _PI_CMD_EVM, self.handle, self.event_bits)
+
+ def remove_event(self, callb):
+ """
+ Removes an event callback from the notification thread.
+ """
+ if callb in self.events:
+ self.events.remove(callb)
+ new_event_bits = 0
+ for c in self.events:
+ new_event_bits |= c.bit
+ if new_event_bits != self.event_bits:
+ self.event_bits = new_event_bits
+ _pigpio_command(
+ self.control, _PI_CMD_EVM, self.handle, self.event_bits)
+
def run(self):
"""Runs the notification thread."""
gpio = flags & NTFY_FLAGS_GPIO
for cb in self.callbacks:
if cb.gpio == gpio:
- cb.func(cb.gpio, TIMEOUT, tick)
+ cb.func(gpio, TIMEOUT, tick)
+ elif flags & NTFY_FLAGS_EVENT:
+ event = flags & NTFY_FLAGS_GPIO
+ for cb in self.events:
+ if cb.event == event:
+ cb.func(event, tick)
self.sl.s.close()
self._reset = True
self.count = 0
+class _event:
+ """A class to provide event callbacks."""
+
+ def __init__(self, notify, event, func=None):
+ """
+ Initialise an event and adds it to the notification thread.
+ """
+ self._notify = notify
+ self.count=0
+ self._reset = False
+ if func is None:
+ func=self._tally
+ self.callb = _event_ADT(event, func)
+ self._notify.append_event(self.callb)
+
+ def cancel(self):
+ """
+ Cancels a event callback by removing it from the
+ notification thread.
+ """
+ self._notify.remove_event(self.callb)
+
+ def _tally(self, event, tick):
+ """Increment the event callback called count."""
+ if self._reset:
+ self._reset = False
+ self.count = 0
+ self.count += 1
+
+ def tally(self):
+ """
+ Provides a count of how many times the default tally
+ callback has triggered.
+
+ The count will be zero if the user has supplied their own
+ callback function.
+ """
+ return self.count
+
+ def reset_tally(self):
+ """
+ Resets the tally count to zero.
+ """
+ self._reset = True
+ self.count = 0
+
class _wait_for_edge:
"""Encapsulates waiting for GPIO edges."""
"""Sets wait_for_edge triggered."""
self.trigger = True
+class _wait_for_event:
+ """Encapsulates waiting for an event."""
+
+ def __init__(self, notify, event, timeout):
+ """Initialises wait_for_event."""
+ self._notify = notify
+ self.callb = _event_ADT(event, self.func)
+ self.trigger = False
+ self._notify.append_event(self.callb)
+ self.start = time.time()
+ while (self.trigger == False) and ((time.time()-self.start) < timeout):
+ time.sleep(0.05)
+ self._notify.remove_event(self.callb)
+
+ def func(self, event, tick):
+ """Sets wait_for_event triggered."""
+ self.trigger = True
+
class pi():
def _rxbuf(self, count):
E.g. if the function returns 15 then the notifications must be
read from /dev/pigpio15.
- Notifications have the following structure.
+ Notifications have the following structure:
. .
H seqno
seqno: starts at 0 each time the handle is opened and then
increments by one for each report.
- flags: two flags are defined, PI_NTFY_FLAGS_WDOG and
- PI_NTFY_FLAGS_ALIVE.
+ flags: three flags are defined, PI_NTFY_FLAGS_WDOG,
+ PI_NTFY_FLAGS_ALIVE, and PI_NTFY_FLAGS_EVENT.
- PI_NTFY_FLAGS_WDOG, if bit 5 is set then bits 0-4 of the
+ If bit 5 is set (PI_NTFY_FLAGS_WDOG) then bits 0-4 of the
flags indicate a GPIO which has had a watchdog timeout.
- PI_NTFY_FLAGS_ALIVE, if bit 6 is set this indicates a keep
+ If bit 6 is set (PI_NTFY_FLAGS_ALIVE) this indicates a keep
alive signal on the pipe/socket and is sent once a minute
in the absence of other notification activity.
+ If bit 7 is set (PI_NTFY_FLAGS_EVENT) then bits 0-4 of the
+ flags indicate an event which has been triggered.
+
+
tick: the number of microseconds since system boot. It wraps
around after 1h12m.
The same clock is available on multiple GPIO. The latest
frequency setting will be used by all GPIO which share a clock.
- The GPIO must be one of the following.
+ The GPIO must be one of the following:
. .
4 clock 0 All models
The latest frequency and dutycycle setting will be used
by all GPIO which share a PWM channel.
- The GPIO must be one of the following.
+ The GPIO must be one of the following:
. .
12 PWM channel 0 All models but A and B
For the SMBus commands the low level transactions are shown
at the end of the function description. The following
- abbreviations are used.
+ abbreviations are used:
. .
S (1 bit) : Start bit
...
(count, data) = pi.bb_i2c_zip(
- h, [4, 0x53, 2, 7, 1, 0x32, 2, 6, 6, 3, 0])
+ SDA, [4, 0x53, 2, 7, 1, 0x32, 2, 6, 6, 3, 0])
...
The following command codes are supported:
self.sl.l.release()
return bytes, data
+ def event_trigger(self, event):
+ """
+ This function signals the occurrence of an event.
+
+ event:= 0-31, the event
+
+ Returns 0 if OK, otherwise PI_BAD_EVENT_ID.
+
+ An event is a signal used to inform one or more consumers
+ to start an action. Each consumer which has registered an
+ interest in the event (e.g. by calling [*event_callback*]) will
+ be informed by a callback.
+
+ One event, EVENT_BSC (31) is predefined. This event is
+ auto generated on BSC slave activity.
+
+ The meaning of other events is arbitrary.
+
+ Note that other than its id and its tick there is no data associated
+ with an event.
+
+ ...
+ pi.event_trigger(23)
+ ...
+ """
+ return _u2i(_pigpio_command(self.sl, _PI_CMD_EVT, event, 0))
+
+
+ def bsc_xfer(self, bsc_control, data):
+ """
+ This function provides a low-level interface to the
+ SPI/I2C Slave peripheral. This peripheral allows the
+ Pi to act as a slave device on an I2C or SPI bus.
+
+ I can't get SPI to work properly. I tried with a
+ control word of 0x303 and swapped MISO and MOSI.
+
+
+ The function sets the BSC mode, writes any data in
+ the transmit buffer to the BSC transmit FIFO, and
+ copies any data in the BSC receive FIFO to the
+ receive buffer.
+
+ bsc_control:= see below
+ data:= the data bytes to place in the transmit FIFO.
+
+ The returned value is a tuple of the status (see below),
+ the number of bytes read, and a bytearray containing the
+ read bytes. If there was an error the status will be less
+ than zero (and will contain the error code).
+
+ Note that the control word sets the BSC mode. The BSC will
+ stay in that mode until a different control word is sent.
+
+ The BSC peripheral uses GPIO 18 (SDA) and 19 (SCL)
+ in I2C mode and GPIO 18 (MOSI), 19 (SCLK), 20 (MISO),
+ and 21 (CE) in SPI mode. You need to swap MISO/MOSI
+ between master and slave.
+
+ When a zero control word is received GPIO 18-21 will be reset
+ to INPUT mode.
+
+ bsc_control consists of the following bits:
+
+ . .
+ 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+ a a a a a a a - - IT HC TF IR RE TE BK EC ES PL PH I2 SP EN
+ . .
+
+ Bits 0-13 are copied unchanged to the BSC CR register. See
+ pages 163-165 of the Broadcom peripherals document for full
+ details.
+
+ aaaaaaa @ defines the I2C slave address (only relevant in I2C mode)
+ IT @ invert transmit status flags
+ HC @ enable host control
+ TF @ enable test FIFO
+ IR @ invert receive status flags
+ RE @ enable receive
+ TE @ enable transmit
+ BK @ abort operation and clear FIFOs
+ EC @ send control register as first I2C byte
+ ES @ send status register as first I2C byte
+ PL @ set SPI polarity high
+ PH @ set SPI phase high
+ I2 @ enable I2C mode
+ SP @ enable SPI mode
+ EN @ enable BSC peripheral
+
+ The status has the following format:
+
+ . .
+ 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+ S S S S S R R R R R T T T T T RB TE RF TF RE TB
+ . .
+
+ Bits 0-15 are copied unchanged from the BSC FR register. See
+ pages 165-166 of the Broadcom peripherals document for full
+ details.
+
+ SSSSS @ number of bytes successfully copied to transmit FIFO
+ RRRRR @ number of bytes in receieve FIFO
+ TTTTT @ number of bytes in transmit FIFO
+ RB @ receive busy
+ TE @ transmit FIFO empty
+ RF @ receive FIFO full
+ TF @ transmit FIFO full
+ RE @ receive FIFO empty
+ TB @ transmit busy
+
+ ...
+ (status, count, data) = pi.bsc_xfer(0x330305, "Hello!")
+ ...
+ """
+ # I p1 control
+ # I p2 0
+ # I p3 len
+ ## extension ##
+ # s len data bytes
+
+ # Don't raise exception. Must release lock.
+ bytes = u2i(_pigpio_command_ext(
+ self.sl, _PI_CMD_BSCX, bsc_control, 0, len(data), [data], False))
+ if bytes > 0:
+ rx = self._rxbuf(bytes)
+ status = struct.unpack('I', rx[0:4])[0]
+ bytes -= 4
+ data = rx[4:]
+ else:
+ status = bytes
+ bytes = 0
+ data = bytearray(b'')
+ self.sl.l.release()
+ return status, bytes, data
+
+ def bsc_i2c(self, i2c_address, data=[]):
+ """
+ This function allows the Pi to act as a slave I2C device.
+
+ The data bytes (if any) are written to the BSC transmit
+ FIFO and the bytes in the BSC receive FIFO are returned.
+
+ i2c_address:= the I2C slave address.
+ data:= the data bytes to transmit.
+
+ The returned value is a tuple of the status, the number
+ of bytes read, and a bytearray containing the read bytes.
+
+ See [*bsc_xfer*] for details of the status value.
+
+ If there was an error the status will be less than zero
+ (and will contain the error code).
+
+ Note that an i2c_address of 0 may be used to close
+ the BSC device and reassign the used GPIO (18/19)
+ as inputs.
+
+ This example assumes GPIO 2/3 are connected to GPIO 18/19.
+
+ ...
+ #!/usr/bin/env python
+ import time
+ import pigpio
+
+ I2C_ADDR=0x13
+
+ def i2c(id, tick):
+ global pi
+
+ s, b, d = pi.bsc_i2c(I2C_ADDR)
+ if b:
+ if d[0] == ord('t'): # 116 send 'HH:MM:SS*'
+
+ print("sent={} FR={} received={} [{}]".
+ format(s>>16, s&0xfff,b,d))
+
+ s, b, d = pi.bsc_i2c(I2C_ADDR,
+ "{}*".format(time.asctime()[11:19]))
+
+ elif d[0] == ord('d'): # 100 send 'Sun Oct 30*'
+
+ print("sent={} FR={} received={} [{}]".
+ format(s>>16, s&0xfff,b,d))
+
+ s, b, d = pi.bsc_i2c(I2C_ADDR,
+ "{}*".format(time.asctime()[:10]))
+
+ pi = pigpio.pi()
+
+ if not pi.connected:
+ exit()
+
+ # Respond to BSC slave activity
+
+ e = pi.event_callback(pigpio.EVENT_BSC, i2c)
+
+ pi.bsc_i2c(I2C_ADDR) # Configure BSC as I2C slave
+
+ time.sleep(600)
+
+ e.cancel()
+
+ pi.bsc_i2c(0) # Disable BSC peripheral
+
+ pi.stop()
+ ...
+
+ While running the above.
+
+ . .
+ $ i2cdetect -y 1
+ 0 1 2 3 4 5 6 7 8 9 a b c d e f
+ 00: -- -- -- -- -- -- -- -- -- -- -- -- --
+ 10: -- -- -- 13 -- -- -- -- -- -- -- -- -- -- -- --
+ 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+ 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+ 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+ 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+ 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+ 70: -- -- -- -- -- -- -- --
+
+ $ pigs i2co 1 0x13 0
+ 0
+
+ $ pigs i2cwd 0 116
+ $ pigs i2crd 0 9 -a
+ 9 10:13:58*
+
+ $ pigs i2cwd 0 116
+ $ pigs i2crd 0 9 -a
+ 9 10:14:29*
+
+ $ pigs i2cwd 0 100
+ $ pigs i2crd 0 11 -a
+ 11 Sun Oct 30*
+
+ $ pigs i2cwd 0 100
+ $ pigs i2crd 0 11 -a
+ 11 Sun Oct 30*
+
+ $ pigs i2cwd 0 116
+ $ pigs i2crd 0 9 -a
+ 9 10:23:16*
+
+ $ pigs i2cwd 0 100
+ $ pigs i2crd 0 11 -a
+ 11 Sun Oct 30*
+ . .
+ """
+ if i2c_address:
+ control = (i2c_address<<16)|0x305
+ else:
+ control = 0
+ return self.bsc_xfer(control, data)
+
def spi_open(self, spi_channel, baud, spi_flags=0):
"""
Returns a handle for the SPI device on channel. Data will be
handle:= >=0 (as returned by a prior call to [*serial_open*]).
+ If no data is ready a negative error code will be returned.
+
...
b = pi.serial_read_byte(h1)
...
return _u2i(
_pigpio_command(self.sl, _PI_CMD_SERWB, handle, byte_val))
- def serial_read(self, handle, count):
+ def serial_read(self, handle, count=1000):
"""
Reads up to count bytes from the device associated with handle.
handle:= >=0 (as returned by a prior call to [*serial_open*]).
- count:= >0, the number of bytes to read.
+ count:= >0, the number of bytes to read (defaults to 1000).
- The returned value is a tuple of the number of bytes read and a
- bytearray containing the bytes. If there was an error the
+ The returned value is a tuple of the number of bytes read and
+ a bytearray containing the bytes. If there was an error the
number of bytes read will be less than zero (and will contain
the error code).
+ If no data is ready a bytes read of zero is returned.
...
(b, d) = pi.serial_read(h2, 100)
if b > 0:
Where more than one entry matches a file the most specific rule
applies. If no entry matches a file then access is denied.
- Suppose /opt/pigpio/access contains the following entries
+ Suppose /opt/pigpio/access contains the following entries:
. .
/home/* n
may be created in that directory.
In an attempt to prevent risky permissions the following paths are
- ignored in /opt/pigpio/access.
+ ignored in /opt/pigpio/access:
. .
a path containing ..
Mode
- The mode may have the following values.
+ The mode may have the following values:
Constant @ Value @ Meaning
FILE_READ @ 1 @ open file for reading
FILE_WRITE @ 2 @ open file for writing
FILE_RW @ 3 @ open file for reading and writing
- The following values may be or'd into the mode.
+ The following values may be or'd into the mode:
Name @ Value @ Meaning
FILE_APPEND @ 4 @ All writes append data to the end of the file
if not pi.connected:
exit()
- # Assumes /opt/pigpio/access contains the following line.
+ # Assumes /opt/pigpio/access contains the following line:
# /ram/*.c r
handle = pi.file_open("/ram/pigpio.c", pigpio.FILE_READ)
if not pi.connected:
exit()
- # Assumes /opt/pigpio/access contains the following line.
+ # Assumes /opt/pigpio/access contains the following line:
# /ram/*.c r
c, d = pi.file_list("/ram/p*.c")
the shell script exit function. If the script can't be
found 32512 will be returned.
- The following table gives some example returned statuses.
+ The following table gives some example returned statuses:
Script exit status @ Returned system call status
1 @ 256
return _u2i(_pigpio_command_ext(
self.sl, _PI_CMD_SHELL, ls, 0, ls+lp+1, [shellscr+'\x00'+pstring]))
+
def callback(self, user_gpio, edge=RISING_EDGE, func=None):
"""
Calls a user supplied function (a callback) whenever the
"""
return _callback(self._notify, user_gpio, edge, func)
+ def event_callback(self, event, func=None):
+ """
+ Calls a user supplied function (a callback) whenever the
+ specified event is signalled.
+
+ event:= 0-31.
+ func:= user supplied callback function.
+
+ The user supplied callback receives two parameters, the event id,
+ and the tick.
+
+ If a user callback is not specified a default tally callback is
+ provided which simply counts events. The count may be retrieved
+ by calling the tally function. The count may be reset to zero
+ by calling the reset_tally function.
+
+ The callback may be cancelled by calling the event_cancel function.
+
+ An event may have multiple callbacks (although I can't think of
+ a reason to do so).
+
+ ...
+ def cbf(event, tick):
+ print(event, tick)
+
+ cb1 = pi.event_callback(22, cbf)
+
+ cb2 = pi.event_callback(4)
+
+ print(cb2.tally())
+
+ cb2.reset_tally()
+
+ cb1.event_cancel() # To cancel callback cb1.
+ ...
+ """
+
+ return _event(self._notify, event, func)
+
def wait_for_edge(self, user_gpio, edge=RISING_EDGE, wait_timeout=60.0):
"""
Wait for an edge event on a GPIO.
a = _wait_for_edge(self._notify, user_gpio, edge, wait_timeout)
return a.trigger
+ def wait_for_event(self, event, wait_timeout=60.0):
+ """
+ Wait for an event.
+
+ event:= 0-31.
+ wait_timeout:= >=0.0 (default 60.0).
+
+ The function returns when the event is signalled or after
+ the number of seconds specified by timeout has expired.
+
+ The function returns True if the event is detected,
+ otherwise False.
+
+ ...
+ if pi.wait_for_event(23):
+ print("event detected")
+ else:
+ print("wait for event timed out")
+ ...
+ """
+ a = _wait_for_event(self._notify, event, wait_timeout)
+ return a.trigger
+
def __init__(self,
host = os.getenv("PIGPIO_ADDR", ''),
port = os.getenv("PIGPIO_PORT", 8888)):
s = "Can't connect to pigpio at {}({})".format(str(h), str(port))
- print(except_a.format(s))
+ print(_except_a.format(s))
if exception == 1:
- print(except1)
+ print(_except_1)
else:
- print(except2)
- print(except_z)
+ print(_except_2)
+ print(_except_z)
def stop(self):
"""Release pigpio resources.
bits = (1<<1) | (1<<7) | (1<<23)
+ bsc_control:
+
+ . .
+ 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+ a a a a a a a - - IT HC TF IR RE TE BK EC ES PL PH I2 SP EN
+ . .
+
+ aaaaaaa defines the I2C slave address (only relevant in I2C mode)
+
+ Bits 0-13 are copied unchanged to the BSC CR register. See
+ pages 163-165 of the Broadcom peripherals document.
+
byte_val: 0-255
A whole number.
range_ @ Fully On
edge: 0-2
+
+ . .
EITHER_EDGE = 2
FALLING_EDGE = 1
RISING_EDGE = 0
+ . .
errnum: <0
PI_FILE_IS_A_DIR = -138
PI_BAD_SHELL_STATUS = -139
PI_BAD_SCRIPT_NAME = -140
+ PI_BAD_SPI_BAUD = -141
+ PI_NOT_SPI_GPIO = -142
+ PI_BAD_EVENT_ID = -143
. .
+ event:0-31
+ An event is a signal used to inform one or more consumers
+ to start an action.
+
file_mode:
- The mode may have the following values.
+ The mode may have the following values
. .
FILE_READ 1
FILE_RW 3
. .
- The following values can be or'd into the file open mode.
+ The following values can be or'd into the file open mode
. .
FILE_APPEND 4
See [*get_hardware_revision*].
- The user GPIO are marked with an X in the following table.
+ The user GPIO are marked with an X in the following table
. .
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
of a pulse.
handle: >=0
- A number referencing an object opened by one of [*file_open*],
- [*i2c_open*], [*notify_open*], [*serial_open*], [*spi_open*].
+ A number referencing an object opened by one of the following
+
+ [*file_open*]
+ [*i2c_open*]
+ [*notify_open*]
+ [*serial_open*]
+ [*spi_open*]
host:
The name or IP address of the Pi running the pigpio daemon.
level logic.
level: 0-1 (2)
+
+ . .
CLEAR = 0
HIGH = 1
LOW = 0
ON = 1
SET = 1
TIMEOUT = 2 # only returned for a watchdog timeout
+ . .
MISO:
The GPIO used for the MISO signal when bit banging SPI.
1.The operational mode of a GPIO, normally INPUT or OUTPUT.
+ . .
ALT0 = 4
ALT1 = 5
ALT2 = 6
ALT5 = 2
INPUT = 0
OUTPUT = 1
+ . .
2. The mode of waveform transmission.
+ . .
WAVE_MODE_ONE_SHOT = 0
WAVE_MODE_REPEAT = 1
WAVE_MODE_ONE_SHOT_SYNC = 2
WAVE_MODE_REPEAT_SYNC = 3
+ . .
MOSI:
The GPIO used for the MOSI signal when bit banging SPI.
The string to be passed to a [*shell*] script to be executed.
pud: 0-2
+ . .
PUD_DOWN = 1
PUD_OFF = 0
PUD_UP = 2
+ . .
pulse_len: 1-100
The length of the trigger pulse in microseconds.
seek_from: 0-2
Direction to seek for [*file_seek*].
+ . .
FROM_START=0
FROM_CURRENT=1
FROM_END=2
+ . .
seek_offset:
The number of bytes to move forward (positive) or backwards
The number of seconds to wait in [*wait_for_edge*] before timing out.
wave_add_*:
- One of [*wave_add_new*] , [*wave_add_generic*], [*wave_add_serial*].
+ One of the following
+
+ [*wave_add_new*]
+ [*wave_add_generic*]
+ [*wave_add_serial*]
wave_id: >=0
A number referencing a wave created by [*wave_create*].
wave_send_*:
- One of [*wave_send_once*], [*wave_send_repeat*].
+ One of the following
+
+ [*wave_send_once*]
+ [*wave_send_repeat*]
wdog_timeout: 0-60000
Defines a GPIO watchdog timeout in milliseconds. If no level
Returns the read byte (>=0) if OK, otherwise PI_BAD_HANDLE,
PI_SER_READ_NO_DATA, or PI_SER_READ_FAILED.
+.br
+
+.br
+If no data is ready PI_SER_READ_NO_DATA is returned.
+
.IP "\fBint serial_write(unsigned handle, char *buf, unsigned count)\fP"
.IP "" 4
This function writes count bytes from buf to the the serial port
Returns the number of bytes read (>0) if OK, otherwise PI_BAD_HANDLE,
PI_BAD_PARAM, PI_SER_READ_NO_DATA, or PI_SER_WRITE_FAILED.
+.br
+
+.br
+If no data is ready zero is returned.
+
.IP "\fBint serial_data_available(unsigned handle)\fP"
.IP "" 4
Returns the number of bytes available to be read from the
Returns the read byte (>=0) if OK, otherwise PI_BAD_HANDLE,
PI_SER_READ_NO_DATA, or PI_SER_READ_FAILED.
+
+If no data is ready PI_SER_READ_NO_DATA is returned.
D*/
/*F*/
Returns the number of bytes read (>0) if OK, otherwise PI_BAD_HANDLE,
PI_BAD_PARAM, PI_SER_READ_NO_DATA, or PI_SER_WRITE_FAILED.
+
+If no data is ready zero is returned.
D*/
/*F*/
.br
.br
-flags: two flags are defined, PI_NTFY_FLAGS_WDOG and PI_NTFY_FLAGS_ALIVE.
+flags: three flags are defined, PI_NTFY_FLAGS_WDOG,
+PI_NTFY_FLAGS_ALIVE, and PI_NTFY_FLAGS_EVENT.
.br
.br
-PI_NTFY_FLAGS_WDOG, if bit 5 is set then bits 0-4 of the flags
+If bit 5 is set (PI_NTFY_FLAGS_WDOG) then bits 0-4 of the flags
indicate a GPIO which has had a watchdog timeout.
.br
.br
-PI_NTFY_FLAGS_ALIVE, if bit 6 is set this indicates a keep alive
+If bit 6 is set (PI_NTFY_FLAGS_ALIVE) this indicates a keep alive
signal on the pipe/socket and is sent once a minute in the absence
of other notification activity.
.br
+.br
+If bit 7 is set (PI_NTFY_FLAGS_EVENT) then bits 0-4 of the flags
+indicate an event which has been triggered.
+
+.br
+
.br
tick: the number of microseconds since system boot. It wraps around
after 1h12m.
Returns the read byte (>=0) if OK, otherwise PI_BAD_HANDLE,
PI_SER_READ_NO_DATA, or PI_SER_READ_FAILED.
+.br
+
+.br
+If no data is ready PI_SER_READ_NO_DATA is returned.
+
.IP "\fBint serial_write(int pi, unsigned handle, char *buf, unsigned count)\fP"
.IP "" 4
This function writes count bytes from buf to the the serial port
.br
.br
-Returns the number of bytes read (>0) if OK, otherwise PI_BAD_HANDLE,
+Returns the number of bytes read (>=0) if OK, otherwise PI_BAD_HANDLE,
PI_BAD_PARAM, PI_SER_READ_NO_DATA, or PI_SER_WRITE_FAILED.
+.br
+
+.br
+If no data is ready zero is returned.
+
.IP "\fBint serial_data_available(int pi, unsigned handle)\fP"
.IP "" 4
Returns the number of bytes available to be read from the
.br
.br
-The callback is called with the GPIO, edge, tick, and user, whenever
-the GPIO has the identified edge.
+The callback is called with the GPIO, edge, tick, and the userdata
+pointer, whenever the GPIO has the identified edge.
.IP "\fBint callback_cancel(unsigned callback_id)\fP"
.IP "" 4
.IP "\fBint wait_for_edge(int pi, unsigned user_gpio, unsigned edge, double timeout)\fP"
.IP "" 4
-This function waits for edge on the GPIO for up to timeout
+This function waits for an edge on the GPIO for up to timeout
seconds.
.br
.br
The function returns 1 if the edge occurred, otherwise 0.
+
+.IP "\fBint bsc_xfer(int pi, bsc_xfer_t *bscxfer)\fP"
+.IP "" 4
+This function provides a low-level interface to the
+SPI/I2C Slave peripheral. This peripheral allows the
+Pi to act as a slave device on an I2C or SPI bus.
+
+.br
+
+.br
+I can't get SPI to work properly. I tried with a
+control word of 0x303 and swapped MISO and MOSI.
+
+.br
+
+.br
+The function sets the BSC mode, writes any data in
+the transmit buffer to the BSC transmit FIFO, and
+copies any data in the BSC receive FIFO to the
+receive buffer.
+
+.br
+
+.br
+
+.EX
+ pi: >=0 (as returned by \fBpigpio_start\fP).
+.br
+bscxfer: a structure defining the transfer.
+.br
+
+.br
+typedef struct
+.br
+{
+.br
+ uint32_t control; // Write
+.br
+ int rxCnt; // Read only
+.br
+ char rxBuf[BSC_FIFO_SIZE]; // Read only
+.br
+ int txCnt; // Write
+.br
+ char txBuf[BSC_FIFO_SIZE]; // Write
+.br
+} bsc_xfer_t;
+.br
+
+.EE
+
+.br
+
+.br
+To start a transfer set control (see below) and copy the bytes to
+be sent (if any) to txBuf and set the byte count in txCnt.
+
+.br
+
+.br
+Upon return rxCnt will be set to the number of received bytes placed
+in rxBuf.
+
+.br
+
+.br
+The returned function value is the status of the transfer (see below).
+
+.br
+
+.br
+If there was an error the status will be less than zero
+(and will contain the error code).
+
+.br
+
+.br
+The most significant word of the returned status contains the number
+of bytes actually copied from txBuf to the BSC transmit FIFO (may be
+less than requested if the FIFO already contained untransmitted data).
+
+.br
+
+.br
+Note that the control word sets the BSC mode. The BSC will stay in
+that mode until a different control word is sent.
+
+.br
+
+.br
+The BSC peripheral uses GPIO 18 (SDA) and 19 (SCL) in I2C mode
+and GPIO 18 (MOSI), 19 (SCLK), 20 (MISO), and 21 (CE) in SPI mode. You
+need to swap MISO/MOSI between master and slave.
+
+.br
+
+.br
+When a zero control word is received GPIO 18-21 will be reset
+to INPUT mode.
+
+.br
+
+.br
+control consists of the following bits.
+
+.br
+
+.br
+
+.EX
+22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+.br
+ a a a a a a a - - IT HC TF IR RE TE BK EC ES PL PH I2 SP EN
+.br
+
+.EE
+
+.br
+
+.br
+Bits 0-13 are copied unchanged to the BSC CR register. See
+pages 163-165 of the Broadcom peripherals document for full
+details.
+
+.br
+
+.br
+aaaaaaa defines the I2C slave address (only relevant in I2C mode)
+.br
+IT invert transmit status flags
+.br
+HC enable host control
+.br
+TF enable test FIFO
+.br
+IR invert receive status flags
+.br
+RE enable receive
+.br
+TE enable transmit
+.br
+BK abort operation and clear FIFOs
+.br
+EC send control register as first I2C byte
+.br
+ES send status register as first I2C byte
+.br
+PL set SPI polarity high
+.br
+PH set SPI phase high
+.br
+I2 enable I2C mode
+.br
+SP enable SPI mode
+.br
+EN enable BSC peripheral
+.br
+
+.br
+
+.br
+The returned status has the following format
+
+.br
+
+.br
+
+.EX
+20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+.br
+ S S S S S R R R R R T T T T T RB TE RF TF RE TB
+.br
+
+.EE
+
+.br
+
+.br
+Bits 0-15 are copied unchanged from the BSC FR register. See
+pages 165-166 of the Broadcom peripherals document for full
+details.
+
+.br
+
+.br
+SSSSS number of bytes successfully copied to transmit FIFO
+.br
+RRRRR number of bytes in receieve FIFO
+.br
+TTTTT number of bytes in transmit FIFO
+.br
+RB receive busy
+.br
+TE transmit FIFO empty
+.br
+RF receive FIFO full
+.br
+TF transmit FIFO full
+.br
+RE receive FIFO empty
+.br
+TB transmit busy
+.br
+
+.br
+
+.br
+The following example shows how to configure the BSC peripheral as
+an I2C slave with address 0x13 and send four bytes.
+
+.br
+
+.br
+\fBExample\fP
+.br
+
+.EX
+bsc_xfer_t xfer;
+.br
+
+.br
+xfer.control = (0x13<<16) | 0x305;
+.br
+
+.br
+memcpy(xfer.txBuf, "ABCD", 4);
+.br
+xfer.txCnt = 4;
+.br
+
+.br
+status = bsc_xfer(pi, &xfer);
+.br
+
+.br
+if (status >= 0)
+.br
+{
+.br
+ // process transfer
+.br
+}
+.br
+
+.EE
+
+.IP "\fBint bsc_i2c(int pi, int i2c_addr, bsc_xfer_t *bscxfer)\fP"
+.IP "" 4
+This function allows the Pi to act as a slave I2C device.
+
+.br
+
+.br
+The data bytes (if any) are written to the BSC transmit
+FIFO and the bytes in the BSC receive FIFO are returned.
+
+.br
+
+.br
+
+.EX
+ pi: >=0 (as returned by \fBpigpio_start\fP).
+.br
+i2c_addr: 0-0x7F.
+.br
+ bscxfer: a structure defining the transfer.
+.br
+
+.br
+typedef struct
+.br
+{
+.br
+ uint32_t control; // N/A
+.br
+ int rxCnt; // Read only
+.br
+ char rxBuf[BSC_FIFO_SIZE]; // Read only
+.br
+ int txCnt; // Write
+.br
+ char txBuf[BSC_FIFO_SIZE]; // Write
+.br
+} bsc_xfer_t;
+.br
+
+.EE
+
+.br
+
+.br
+txCnt is set to the number of bytes to be transmitted, possibly
+zero. The data itself should be copied to txBuf.
+
+.br
+
+.br
+Any received data will be written to rxBuf with rxCnt set.
+
+.br
+
+.br
+See \fBbsc_xfer\fP for details of the returned status value.
+
+.br
+
+.br
+If there was an error the status will be less than zero
+(and will contain the error code).
+
+.br
+
+.br
+Note that an i2c_address of 0 may be used to close
+the BSC device and reassign the used GPIO (18/19)
+as inputs.
+
+.IP "\fBint event_callback(int pi, unsigned event, evtCBFunc_t f)\fP"
+.IP "" 4
+This function initialises an event callback.
+
+.br
+
+.br
+
+.EX
+ pi: >=0 (as returned by \fBpigpio_start\fP).
+.br
+event: 0-31.
+.br
+ f: the callback function.
+.br
+
+.EE
+
+.br
+
+.br
+The function returns a callback id if OK, otherwise pigif_bad_malloc,
+pigif_duplicate_callback, or pigif_bad_callback.
+
+.br
+
+.br
+The callback is called with the event id, and tick, whenever the
+event occurs.
+
+.IP "\fBint event_callback_ex(int pi, unsigned event, evtCBFuncEx_t f, void *userdata)\fP"
+.IP "" 4
+This function initialises an event callback.
+
+.br
+
+.br
+
+.EX
+ pi: >=0 (as returned by \fBpigpio_start\fP).
+.br
+ event: 0-31.
+.br
+ f: the callback function.
+.br
+userdata: a pointer to arbitrary user data.
+.br
+
+.EE
+
+.br
+
+.br
+The function returns a callback id if OK, otherwise pigif_bad_malloc,
+pigif_duplicate_callback, or pigif_bad_callback.
+
+.br
+
+.br
+The callback is called with the event id, the tick, and the userdata
+pointer whenever the event occurs.
+
+.IP "\fBint event_callback_cancel(unsigned callback_id)\fP"
+.IP "" 4
+This function cancels an event callback identified by its id.
+
+.br
+
+.br
+
+.EX
+callback_id: >=0, as returned by a call to \fBevent_callback\fP or
+.br
+\fBevent_callback_ex\fP.
+.br
+
+.EE
+
+.br
+
+.br
+The function returns 0 if OK, otherwise pigif_callback_not_found.
+
+.IP "\fBint wait_for_event(int pi, unsigned event, double timeout)\fP"
+.IP "" 4
+This function waits for an event for up to timeout seconds.
+
+.br
+
+.br
+
+.EX
+ pi: >=0 (as returned by \fBpigpio_start\fP).
+.br
+ event: 0-31.
+.br
+timeout: >=0.
+.br
+
+.EE
+
+.br
+
+.br
+The function returns when the event occurs or after the timeout.
+
+.br
+
+.br
+The function returns 1 if the event occurred, otherwise 0.
+
+.IP "\fBint event_trigger(int pi, unsigned event)\fP"
+.IP "" 4
+This function signals the occurrence of an event.
+
+.br
+
+.br
+
+.EX
+ pi: >=0 (as returned by \fBpigpio_start\fP).
+.br
+event: 0-31.
+.br
+
+.EE
+
+.br
+
+.br
+Returns 0 if OK, otherwise PI_BAD_EVENT_ID.
+
+.br
+
+.br
+An event is a signal used to inform one or more consumers
+to start an action. Each consumer which has registered an interest
+in the event (e.g. by calling \fBevent_callback\fP) will be informed by
+a callback.
+
+.br
+
+.br
+One event, PI_EVENT_BSC (31) is predefined. This event is
+auto generated on BSC slave activity.
+
+.br
+
+.br
+The meaning of other events is arbitrary.
+
+.br
+
+.br
+Note that other than its id and its tick there is no data associated
+with an event.
.SH PARAMETERS
.br
.br
+.IP "\fBbsc_xfer_t\fP" 0
+
+.br
+
+.br
+
+.EX
+typedef struct
+.br
+{
+.br
+ uint32_t control; // Write
+.br
+ int rxCnt; // Read only
+.br
+ char rxBuf[BSC_FIFO_SIZE]; // Read only
+.br
+ int txCnt; // Write
+.br
+ char txBuf[BSC_FIFO_SIZE]; // Write
+.br
+} bsc_xfer_t;
+.br
+
+.EE
+
+.br
+
+.br
+
+.IP "\fB*bscxfer\fP" 0
+A pointer to a \fBbsc_xfer_t\fP object used to control a BSC transfer.
+
+.br
+
+.br
+
.IP "\fB*buf\fP" 0
A buffer to hold data being sent or being received.
.br
.IP "\fBcallback_id\fP" 0
-A >=0, as returned by a call to \fBcallback\fP or \fBcallback_ex\fP. This is
-passed to \fBcallback_cancel\fP to cancel the callback.
+A value >=0, as returned by a call to a callback function, one of
+
+.br
+
+.br
+\fBcallback\fP
+.br
+\fBcallback_ex\fP
+.br
+\fBevent_callback\fP
+.br
+\fBevent_callback_ex\fP
+
+.br
+
+.br
+The id is passed to \fBcallback_cancel\fP or \fBevent_callback_cancel\fP
+to cancel the callback.
.br
.EX
typedef void (*CBFuncEx_t)
.br
- (unsigned user_gpio, unsigned level, uint32_t tick, void * user);
+ (unsigned user_gpio, unsigned level, uint32_t tick, void * userdata);
.br
.EE
.br
+.IP "\fBevent\fP: 0-31" 0
+An event is a signal used to inform one or more consumers
+to start an action.
+
+.br
+
+.br
+
+.IP "\fBevtCBFunc_t\fP" 0
+
+.br
+
+.br
+
+.EX
+typedef void (*evtCBFunc_t)
+.br
+ (int pi, unsigned event, uint32_t tick);
+.br
+
+.EE
+
+.br
+
+.br
+
+.IP "\fBevtCBFuncEx_t\fP" 0
+
+.br
+
+.br
+
+.EX
+typedef void (*evtCBFuncEx_t)
+.br
+ (int pi, unsigned event, uint32_t tick, void *userdata);
+.br
+
+.EE
+
+.br
+
+.br
+
.IP "\fBf\fP" 0
A function.
.br
{
.br
-uint32_t gpioOn;
+ uint32_t gpioOn;
.br
-uint32_t gpioOff;
+ uint32_t gpioOff;
.br
-uint32_t usDelay;
+ uint32_t usDelay;
.br
} gpioPulse_t;
.br
.br
.IP "\fBhandle\fP: >=0" 0
-A number referencing an object opened by one of \fBfile_open\fP,
-\fBi2c_open\fP, \fBnotify_open\fP, \fBserial_open\fP, and \fBspi_open\fP.
+A number referencing an object opened by one of
+
+.br
+
+.br
+\fBfile_open\fP
+.br
+\fBi2c_open\fP
+.br
+\fBnotify_open\fP
+.br
+\fBserial_open\fP
+.br
+\fBspi_open\fP
.br
.IP "\fBrange\fP: 25-40000" 0
The permissible dutycycle values are 0-range.
+.br
+
+.br
+
.EX
PI_MIN_DUTYCYCLE_RANGE 25
.br
.IP "\fBtimeout\fP" 0
A GPIO watchdog timeout in milliseconds.
+.br
+
+.br
+
.EX
PI_MIN_WDOG_TIMEOUT 0
.br
.br
.br
+
+.EX
user_type *userdata;
.br
+.br
+.br
user_type my_userdata;
-
.br
.br
userdata = malloc(sizeof(user_type));
.br
+.br
+.br
*userdata = my_userdata;
+.br
+
+.EE
.br
.br
.br
-user_type my_userdata = *(user_type*)userdata;
+.EX
+user_type my_userdata = *(user_type*)userdata;
.br
.br
free(userdata);
+.br
+
+.EE
.br
.br
.IP "\fBwave_add_*\fP" 0
-One of \fBwave_add_new\fP, \fBwave_add_generic\fP, \fBwave_add_serial\fP.
+One of
+
+.br
+
+.br
+\fBwave_add_new\fP
+.br
+\fBwave_add_generic\fP
+.br
+\fBwave_add_serial\fP
.br
.br
.IP "\fBwave_send_*\fP" 0
-One of \fBwave_send_once\fP, \fBwave_send_repeat\fP.
+One of
+
+.br
+
+.br
+\fBwave_send_once\fP
+.br
+\fBwave_send_repeat\fP
.br
For more information, please refer to <http://unlicense.org/>
*/
-/* PIGPIOD_IF2_VERSION 8 */
+/* PIGPIOD_IF2_VERSION 9 */
#include <stdio.h>
#include <stdlib.h>
callback_t *next;
};
+struct evtCallback_s
+{
+
+ int id;
+ int pi;
+ int event;
+ CBF_t f;
+ void * user;
+ int ex;
+ evtCallback_t *prev;
+ evtCallback_t *next;
+};
+
/* GLOBALS ---------------------------------------------------------------- */
static int gPiInUse [MAX_PI];
static int gPigHandle [MAX_PI];
static int gPigNotify [MAX_PI];
+static uint32_t gEventBits [MAX_PI];
static uint32_t gNotifyBits [MAX_PI];
static uint32_t gLastLevel [MAX_PI];
static callback_t *gCallBackFirst = 0;
static callback_t *gCallBackLast = 0;
+static evtCallback_t *geCallBackFirst = 0;
+static evtCallback_t *geCallBackLast = 0;
+
/* PRIVATE ---------------------------------------------------------------- */
static void _pml(int pi)
static void dispatch_notification(int pi, gpioReport_t *r)
{
callback_t *p;
+ evtCallback_t *ep;
uint32_t changed;
int l, g;
}
else
{
- g = (r->flags) & 31;
+ if ((r->flags) & PI_NTFY_FLAGS_WDOG)
+ {
+ g = (r->flags) & 31;
- p = gCallBackFirst;
+ p = gCallBackFirst;
- while (p)
+ while (p)
+ {
+ if (((p->pi) == pi) && ((p->gpio) == g))
+ {
+ if (p->ex) (p->f)(pi, g, PI_TIMEOUT, r->tick, p->user);
+ else (p->f)(pi, g, PI_TIMEOUT, r->tick);
+ }
+ p = p->next;
+ }
+ }
+ else if ((r->flags) & PI_NTFY_FLAGS_EVENT)
{
- if (((p->pi) == pi) && ((p->gpio) == g))
+ g = (r->flags) & 31;
+
+ ep = geCallBackFirst;
+
+ while (ep)
{
- if (p->ex) (p->f)(pi, g, PI_TIMEOUT, r->tick, p->user);
- else (p->f)(pi, g, PI_TIMEOUT, r->tick);
+ if (((ep->pi) == pi) && ((ep->event) == g))
+ {
+ if (ep->ex) (ep->f)(pi, g, r->tick, ep->user);
+ else (ep->f)(pi, g, r->tick);
+ }
+ ep = ep->next;
}
- p = p->next;
}
}
}
return pigif_bad_callback;
}
+static void findEventBits(int pi)
+{
+ evtCallback_t *ep;
+ uint32_t bits = 0;
+
+ ep = geCallBackFirst;
+
+ while (ep)
+ {
+ if (ep->pi == pi) bits |= (1<<(ep->event));
+ ep = ep->next;
+ }
+
+ if (bits != gEventBits[pi])
+ {
+ gEventBits[pi] = bits;
+ pigpio_command(pi, PI_CMD_EVM, gPigHandle[pi], gEventBits[pi], 1);
+ }
+}
+
+static void _ewfe(
+ int pi, unsigned event, uint32_t tick, void *user)
+{
+ *(int *)user = 1;
+}
+
+static int intEventCallback(
+ int pi, unsigned event, void *f, void *user, int ex)
+{
+ static int id = 0;
+ evtCallback_t *ep;
+
+ if ((event >=0) && (event < 32) && f)
+ {
+ /* prevent duplicates */
+
+ ep = geCallBackFirst;
+
+ while (ep)
+ {
+ if ((ep->pi == pi) &&
+ (ep->event == event) &&
+ (ep->f == f))
+ {
+ return pigif_duplicate_callback;
+ }
+ ep = ep->next;
+ }
+
+ ep = malloc(sizeof(evtCallback_t));
+
+ if (ep)
+ {
+ if (!geCallBackFirst) geCallBackFirst = ep;
+
+ ep->id = id++;
+ ep->pi = pi;
+ ep->event = event;
+ ep->f = f;
+ ep->user = user;
+ ep->ex = ex;
+ ep->next = 0;
+ ep->prev = geCallBackLast;
+
+ if (ep->prev) (ep->prev)->next = ep;
+ geCallBackLast = ep;
+
+ findEventBits(pi);
+
+ return ep->id;
+ }
+
+ return pigif_bad_malloc;
+ }
+
+ return pigif_bad_callback;
+}
+
static int recvMax(int pi, void *buf, int bufsize, int sent)
{
+ /*
+ Copy at most bufSize bytes from the receieved message to
+ buf. Discard the rest of the message.
+ */
uint8_t scratch[4096];
int remaining, fetch, count;
return triggered;
}
+int bsc_xfer(int pi, bsc_xfer_t *bscxfer)
+{
+ int bytes;
+ int status;
+ gpioExtent_t ext[1];
+
+ /*
+ p1=control
+ p2=0
+ p3=len
+ ## extension ##
+ char buf[len]
+ */
+
+ ext[0].size = bscxfer->txCnt;
+ ext[0].ptr = bscxfer->txBuf;
+
+ bytes = pigpio_command_ext
+ (pi, PI_CMD_BSCX, bscxfer->control, 0, bscxfer->txCnt, 1, ext, 0);
+
+ if (bytes > 0)
+ {
+ recvMax(pi, &status, 4, 4);
+ status = ntohl(status);
+ bytes -= 4;
+ bytes = recvMax(pi, bscxfer->rxBuf, sizeof(bscxfer->rxBuf), bytes);
+ bscxfer->rxCnt = bytes;
+ }
+ else
+ {
+ status = bytes;
+ }
+
+ _pmu(pi);
+
+ return status;
+}
+
+
+int bsc_i2c(int pi, int i2c_addr, bsc_xfer_t *bscxfer)
+{
+ int control = 0;
+
+ if (i2c_addr) control = (i2c_addr<<16) | 0x305;
+ bscxfer->control = control;
+ return bsc_xfer(pi, bscxfer);
+}
+
+
+int event_callback(int pi, unsigned event, evtCBFunc_t f)
+ {return intEventCallback(pi, event, f, 0, 0);}
+
+int event_callback_ex(
+ int pi, unsigned event, evtCBFuncEx_t f, void *user)
+ {return intEventCallback(pi, event, f, user, 1);}
+
+int event_callback_cancel(unsigned id)
+{
+ evtCallback_t *ep;
+ int pi;
+
+ ep = geCallBackFirst;
+
+ while (ep)
+ {
+ if (ep->id == id)
+ {
+ pi = ep->pi;
+
+ if (ep->prev) {ep->prev->next = ep->next;}
+ else {geCallBackFirst = ep->next;}
+
+ if (ep->next) {ep->next->prev = ep->prev;}
+ else {geCallBackLast = ep->prev;}
+
+ free(ep);
+
+ findEventBits(pi);
+
+ return 0;
+ }
+ ep = ep->next;
+ }
+ return pigif_callback_not_found;
+}
+
+int wait_for_event(int pi, unsigned event, double timeout)
+{
+ int triggered = 0;
+ int id;
+ double due;
+
+ if ((pi < 0) || (pi >= MAX_PI) || !gPiInUse[pi])
+ return pigif_unconnected_pi;
+
+ if (timeout <= 0.0) return 0;
+
+ due = time_time() + timeout;
+
+ id = event_callback_ex(pi, event, _ewfe, &triggered);
+
+ while (!triggered && (time_time() < due)) time_sleep(0.05);
+
+ event_callback_cancel(id);
+
+ return triggered;
+}
+
+int event_trigger(int pi, unsigned event)
+ {return pigpio_command(pi, PI_CMD_EVM, event, 0, 1);}
+
get_servo_pulsewidth Get the servo pulsewidth in use on a GPIO
callback Create GPIO level change callback
-callback_ex Create GPIO level change callback
+callback_ex Create GPIO level change callback, extended
callback_cancel Cancel a callback
wait_for_edge Wait for GPIO level change
bb_spi_close Closes GPIO for bit banging SPI
bb_spi_xfer Transfers bytes with bit banging SPI
+I2C/SPI_SLAVE
+
+bsc_xfer I2C/SPI as slave transfer
+bsc_i2c I2C as slave transfer
+
SERIAL
serial_open Opens a serial device
file_seek Seeks to a position within a file
file_list List files which match a pattern
+EVENTS
+
+event_callback Sets a callback for an event
+event_callback_ex Sets a callback for an event, extended
+event_callback_cancel Cancel an event callback
+event_trigger Triggers an event
+wait_for_event Wait for an event
+
CUSTOM
custom_1 User custom function 1
(int pi, unsigned user_gpio, unsigned level, uint32_t tick);
typedef void (*CBFuncEx_t)
- (int pi, unsigned user_gpio, unsigned level, uint32_t tick, void * user);
+ (int pi, unsigned user_gpio, unsigned level, uint32_t tick, void *userdata);
typedef struct callback_s callback_t;
+typedef void (*evtCBFunc_t)
+ (int pi, unsigned event, uint32_t tick);
+
+typedef void (*evtCBFuncEx_t)
+ (int pi, unsigned event, uint32_t tick, void *userdata);
+
+typedef struct evtCallback_s evtCallback_t;
+
/*F*/
double time_time(void);
/*D
seqno: starts at 0 each time the handle is opened and then increments
by one for each report.
-flags: two flags are defined, PI_NTFY_FLAGS_WDOG and PI_NTFY_FLAGS_ALIVE.
+flags: three flags are defined, PI_NTFY_FLAGS_WDOG,
+PI_NTFY_FLAGS_ALIVE, and PI_NTFY_FLAGS_EVENT.
-PI_NTFY_FLAGS_WDOG, if bit 5 is set then bits 0-4 of the flags
+If bit 5 is set (PI_NTFY_FLAGS_WDOG) then bits 0-4 of the flags
indicate a GPIO which has had a watchdog timeout.
-PI_NTFY_FLAGS_ALIVE, if bit 6 is set this indicates a keep alive
+If bit 6 is set (PI_NTFY_FLAGS_ALIVE) this indicates a keep alive
signal on the pipe/socket and is sent once a minute in the absence
of other notification activity.
+If bit 7 is set (PI_NTFY_FLAGS_EVENT) then bits 0-4 of the flags
+indicate an event which has been triggered.
+
tick: the number of microseconds since system boot. It wraps around
after 1h12m.
Returns the read byte (>=0) if OK, otherwise PI_BAD_HANDLE,
PI_SER_READ_NO_DATA, or PI_SER_READ_FAILED.
+
+If no data is ready PI_SER_READ_NO_DATA is returned.
D*/
/*F*/
count: the maximum number of bytes to read.
. .
-Returns the number of bytes read (>0) if OK, otherwise PI_BAD_HANDLE,
+Returns the number of bytes read (>=0) if OK, otherwise PI_BAD_HANDLE,
PI_BAD_PARAM, PI_SER_READ_NO_DATA, or PI_SER_WRITE_FAILED.
+
+If no data is ready zero is returned.
D*/
/*F*/
The function returns a callback id if OK, otherwise pigif_bad_malloc,
pigif_duplicate_callback, or pigif_bad_callback.
-The callback is called with the GPIO, edge, tick, and user, whenever
-the GPIO has the identified edge.
+The callback is called with the GPIO, edge, tick, and the userdata
+pointer, whenever the GPIO has the identified edge.
D*/
/*F*/
/*F*/
int wait_for_edge(int pi, unsigned user_gpio, unsigned edge, double timeout);
/*D
-This function waits for edge on the GPIO for up to timeout
+This function waits for an edge on the GPIO for up to timeout
seconds.
. .
The function returns 1 if the edge occurred, otherwise 0.
D*/
+/*F*/
+int bsc_xfer(int pi, bsc_xfer_t *bscxfer);
+/*D
+This function provides a low-level interface to the
+SPI/I2C Slave peripheral. This peripheral allows the
+Pi to act as a slave device on an I2C or SPI bus.
+
+I can't get SPI to work properly. I tried with a
+control word of 0x303 and swapped MISO and MOSI.
+
+The function sets the BSC mode, writes any data in
+the transmit buffer to the BSC transmit FIFO, and
+copies any data in the BSC receive FIFO to the
+receive buffer.
+
+. .
+ pi: >=0 (as returned by [*pigpio_start*]).
+bscxfer: a structure defining the transfer.
+
+typedef struct
+{
+ uint32_t control; // Write
+ int rxCnt; // Read only
+ char rxBuf[BSC_FIFO_SIZE]; // Read only
+ int txCnt; // Write
+ char txBuf[BSC_FIFO_SIZE]; // Write
+} bsc_xfer_t;
+. .
+
+To start a transfer set control (see below) and copy the bytes to
+be sent (if any) to txBuf and set the byte count in txCnt.
+
+Upon return rxCnt will be set to the number of received bytes placed
+in rxBuf.
+
+The returned function value is the status of the transfer (see below).
+
+If there was an error the status will be less than zero
+(and will contain the error code).
+
+The most significant word of the returned status contains the number
+of bytes actually copied from txBuf to the BSC transmit FIFO (may be
+less than requested if the FIFO already contained untransmitted data).
+
+Note that the control word sets the BSC mode. The BSC will stay in
+that mode until a different control word is sent.
+
+The BSC peripheral uses GPIO 18 (SDA) and 19 (SCL) in I2C mode
+and GPIO 18 (MOSI), 19 (SCLK), 20 (MISO), and 21 (CE) in SPI mode. You
+need to swap MISO/MOSI between master and slave.
+
+When a zero control word is received GPIO 18-21 will be reset
+to INPUT mode.
+
+control consists of the following bits.
+
+. .
+22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+ a a a a a a a - - IT HC TF IR RE TE BK EC ES PL PH I2 SP EN
+. .
+
+Bits 0-13 are copied unchanged to the BSC CR register. See
+pages 163-165 of the Broadcom peripherals document for full
+details.
+
+aaaaaaa @ defines the I2C slave address (only relevant in I2C mode)
+IT @ invert transmit status flags
+HC @ enable host control
+TF @ enable test FIFO
+IR @ invert receive status flags
+RE @ enable receive
+TE @ enable transmit
+BK @ abort operation and clear FIFOs
+EC @ send control register as first I2C byte
+ES @ send status register as first I2C byte
+PL @ set SPI polarity high
+PH @ set SPI phase high
+I2 @ enable I2C mode
+SP @ enable SPI mode
+EN @ enable BSC peripheral
+
+The returned status has the following format
+
+. .
+20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+ S S S S S R R R R R T T T T T RB TE RF TF RE TB
+. .
+
+Bits 0-15 are copied unchanged from the BSC FR register. See
+pages 165-166 of the Broadcom peripherals document for full
+details.
+
+SSSSS @ number of bytes successfully copied to transmit FIFO
+RRRRR @ number of bytes in receieve FIFO
+TTTTT @ number of bytes in transmit FIFO
+RB @ receive busy
+TE @ transmit FIFO empty
+RF @ receive FIFO full
+TF @ transmit FIFO full
+RE @ receive FIFO empty
+TB @ transmit busy
+
+The following example shows how to configure the BSC peripheral as
+an I2C slave with address 0x13 and send four bytes.
+
+...
+bsc_xfer_t xfer;
+
+xfer.control = (0x13<<16) | 0x305;
+
+memcpy(xfer.txBuf, "ABCD", 4);
+xfer.txCnt = 4;
+
+status = bsc_xfer(pi, &xfer);
+
+if (status >= 0)
+{
+ // process transfer
+}
+...
+D*/
+
+/*F*/
+int bsc_i2c(int pi, int i2c_addr, bsc_xfer_t *bscxfer);
+/*D
+This function allows the Pi to act as a slave I2C device.
+
+The data bytes (if any) are written to the BSC transmit
+FIFO and the bytes in the BSC receive FIFO are returned.
+
+. .
+ pi: >=0 (as returned by [*pigpio_start*]).
+i2c_addr: 0-0x7F.
+ bscxfer: a structure defining the transfer.
+
+typedef struct
+{
+ uint32_t control; // N/A
+ int rxCnt; // Read only
+ char rxBuf[BSC_FIFO_SIZE]; // Read only
+ int txCnt; // Write
+ char txBuf[BSC_FIFO_SIZE]; // Write
+} bsc_xfer_t;
+. .
+
+txCnt is set to the number of bytes to be transmitted, possibly
+zero. The data itself should be copied to txBuf.
+
+Any received data will be written to rxBuf with rxCnt set.
+
+See [*bsc_xfer*] for details of the returned status value.
+
+If there was an error the status will be less than zero
+(and will contain the error code).
+
+Note that an i2c_address of 0 may be used to close
+the BSC device and reassign the used GPIO (18/19)
+as inputs.
+D*/
+
+/*F*/
+int event_callback(int pi, unsigned event, evtCBFunc_t f);
+/*D
+This function initialises an event callback.
+
+. .
+ pi: >=0 (as returned by [*pigpio_start*]).
+event: 0-31.
+ f: the callback function.
+. .
+
+The function returns a callback id if OK, otherwise pigif_bad_malloc,
+pigif_duplicate_callback, or pigif_bad_callback.
+
+The callback is called with the event id, and tick, whenever the
+event occurs.
+D*/
+
+/*F*/
+int event_callback_ex(int pi, unsigned event, evtCBFuncEx_t f, void *userdata);
+/*D
+This function initialises an event callback.
+
+. .
+ pi: >=0 (as returned by [*pigpio_start*]).
+ event: 0-31.
+ f: the callback function.
+userdata: a pointer to arbitrary user data.
+. .
+
+The function returns a callback id if OK, otherwise pigif_bad_malloc,
+pigif_duplicate_callback, or pigif_bad_callback.
+
+The callback is called with the event id, the tick, and the userdata
+pointer whenever the event occurs.
+D*/
+
+/*F*/
+int event_callback_cancel(unsigned callback_id);
+/*D
+This function cancels an event callback identified by its id.
+
+. .
+callback_id: >=0, as returned by a call to [*event_callback*] or
+[*event_callback_ex*].
+. .
+
+The function returns 0 if OK, otherwise pigif_callback_not_found.
+D*/
+
+/*F*/
+int wait_for_event(int pi, unsigned event, double timeout);
+/*D
+This function waits for an event for up to timeout seconds.
+
+. .
+ pi: >=0 (as returned by [*pigpio_start*]).
+ event: 0-31.
+timeout: >=0.
+. .
+
+The function returns when the event occurs or after the timeout.
+
+The function returns 1 if the event occurred, otherwise 0.
+D*/
+
+/*F*/
+int event_trigger(int pi, unsigned event);
+/*D
+This function signals the occurrence of an event.
+
+. .
+ pi: >=0 (as returned by [*pigpio_start*]).
+event: 0-31.
+. .
+
+Returns 0 if OK, otherwise PI_BAD_EVENT_ID.
+
+An event is a signal used to inform one or more consumers
+to start an action. Each consumer which has registered an interest
+in the event (e.g. by calling [*event_callback*]) will be informed by
+a callback.
+
+One event, PI_EVENT_BSC (31) is predefined. This event is
+auto generated on BSC slave activity.
+
+The meaning of other events is arbitrary.
+
+Note that other than its id and its tick there is no data associated
+with an event.
+D*/
+
/*PARAMS
active :: 0-1000000
e.g. to select bits 5, 9, 23 you could use (1<<5) | (1<<9) | (1<<23).
+bsc_xfer_t::
+
+. .
+typedef struct
+{
+ uint32_t control; // Write
+ int rxCnt; // Read only
+ char rxBuf[BSC_FIFO_SIZE]; // Read only
+ int txCnt; // Write
+ char txBuf[BSC_FIFO_SIZE]; // Write
+} bsc_xfer_t;
+. .
+
+*bscxfer::
+A pointer to a [*bsc_xfer_t*] object used to control a BSC transfer.
+
*buf::
A buffer to hold data being sent or being received.
An 8-bit byte value.
callback_id::
-A >=0, as returned by a call to [*callback*] or [*callback_ex*]. This is
-passed to [*callback_cancel*] to cancel the callback.
+A value >=0, as returned by a call to a callback function, one of
+
+[*callback*]
+[*callback_ex*]
+[*event_callback*]
+[*event_callback_ex*]
+
+The id is passed to [*callback_cancel*] or [*event_callback_cancel*]
+to cancel the callback.
CBFunc_t::
. .
CBFuncEx_t::
. .
typedef void (*CBFuncEx_t)
- (unsigned user_gpio, unsigned level, uint32_t tick, void * user);
+ (unsigned user_gpio, unsigned level, uint32_t tick, void * userdata);
. .
char::
A negative number indicating a function call failed and the nature
of the error.
+event::0-31
+An event is a signal used to inform one or more consumers
+to start an action.
+
+evtCBFunc_t::
+
+. .
+typedef void (*evtCBFunc_t)
+ (int pi, unsigned event, uint32_t tick);
+. .
+
+evtCBFuncEx_t::
+
+. .
+typedef void (*evtCBFuncEx_t)
+ (int pi, unsigned event, uint32_t tick, void *userdata);
+. .
+
f::
A function.
. .
typedef struct
{
-uint32_t gpioOn;
-uint32_t gpioOff;
-uint32_t usDelay;
+ uint32_t gpioOn;
+ uint32_t gpioOff;
+ uint32_t usDelay;
} gpioPulse_t;
. .
. .
handle::>=0
-A number referencing an object opened by one of [*file_open*],
-[*i2c_open*], [*notify_open*], [*serial_open*], and [*spi_open*].
+A number referencing an object opened by one of
+
+[*file_open*]
+[*i2c_open*]
+[*notify_open*]
+[*serial_open*]
+[*spi_open*]
i2c_addr::0-0x7F
The address of a device on the I2C bus.
range::25-40000
The permissible dutycycle values are 0-range.
+
. .
PI_MIN_DUTYCYCLE_RANGE 25
PI_MAX_DUTYCYCLE_RANGE 40000
timeout::
A GPIO watchdog timeout in milliseconds.
+
. .
PI_MIN_WDOG_TIMEOUT 0
PI_MAX_WDOG_TIMEOUT 60000
In the calling function:
+. .
user_type *userdata;
user_type my_userdata;
userdata = malloc(sizeof(user_type));
*userdata = my_userdata;
+. .
In the receiving function:
+. .
user_type my_userdata = *(user_type*)userdata;
free(userdata);
+. .
void::
Denoting no parameter is required
wave_add_*::
-One of [*wave_add_new*], [*wave_add_generic*], [*wave_add_serial*].
+One of
+
+[*wave_add_new*]
+[*wave_add_generic*]
+[*wave_add_serial*]
wave_id::
A number representing a waveform created by [*wave_create*].
wave_send_*::
-One of [*wave_send_once*], [*wave_send_repeat*].
+One of
+
+[*wave_send_once*]
+[*wave_send_repeat*]
wVal::0-65535 (Hex 0x0-0xFFFF, Octal 0-0177777)
A 16-bit word value.
.br
+.IP "\fBBSCX bctl bvs\fP - BSC I2C/SPI transfer"
+.IP "" 4
+
+.br
+This command performs a BSC I2C/SPI slave transfer as defined by
+\fBbctl\fP with data \fBbvs\fP.
+
+.br
+I can't get SPI to work properly. I tried with a
+control word of 0x303 and swapped MISO and MOSI.
+
+.br
+The command sets the BSC mode and writes any data \fBbvs\fP
+to the BSC transmit FIFO. It returns the data count (at least 1
+for the status word), the status word, followed by any data bytes
+read from the BSC receive FIFO.
+
+.br
+Note that the control word sets the BSC mode. The BSC will stay in
+that mode until a different control word is sent.
+
+.br
+For I2C use a control word of (I2C address << 16) + 0x305.
+
+.br
+E.g. to talk as I2C slave with address 0x13 use 0x130305.
+
+.br
+The BSC peripheral uses GPIO 18 (SDA) and 19 (SCL) in I2C mode
+and GPIO 18 (MOSI), 19 (SCLK), 20 (MISO), and 21 (CE) in SPI mode. You
+need to swap MISO/MOSI between master and slave.
+
+.br
+When a zero control word is received GPIO 18-21 will be reset
+to INPUT mode.
+
+.br
+The control word consists of the following bits.
+
+.br
+
+.EX
+22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+.br
+ a a a a a a a - - IT HC TF IR RE TE BK EC ES PL PH I2 SP EN
+.br
+
+.EE
+
+.br
+Bits 0-13 are copied unchanged to the BSC CR register. See
+pages 163-165 of the Broadcom peripherals document for full
+details.
+
+.br
+
+.EX
+aaaaaaa defines the I2C slave address (only relevant in I2C mode)
+IT invert transmit status flags
+HC enable host control
+TF enable test FIFO
+IR invert receive status flags
+RE enable receive
+TE enable transmit
+BK abort operation and clear FIFOs
+EC send control register as first I2C byte
+ES send status register as first I2C byte
+PL set SPI polarity high
+PH set SPI phase high
+I2 enable I2C mode
+SP enable SPI mode
+EN enable BSC peripheral
+
+.EE
+
+.br
+The returned status has the following format
+
+.br
+
+.EX
+20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+.br
+ S S S S S R R R R R T T T T T RB TE RF TF RE TB
+.br
+
+.EE
+
+.br
+Bits 0-15 are copied unchanged from the BSC FR register. See
+pages 165-166 of the Broadcom peripherals document for full
+details.
+
+.br
+
+.EX
+SSSSS number of bytes successfully copied to transmit FIFO
+RRRRR number of bytes in receieve FIFO
+TTTTT number of bytes in transmit FIFO
+RB receive busy
+TE transmit FIFO empty
+RF receive FIFO full
+TF transmit FIFO full
+RE receive FIFO empty
+TB transmit busy
+
+.EE
+
+.br
+This example assumes that GPIO 2/3 are connected to GPIO 18/19.
+
+.br
+
+\fBExample\fP
+.br
+
+.EX
+$ pigs bscx 0x130305 # start BSC as I2C slave 0x13
+.br
+1 18
+.br
+
+.br
+$ i2cdetect -y 1
+.br
+ 0 1 2 3 4 5 6 7 8 9 a b c d e f
+.br
+00: -- -- -- -- -- -- -- -- -- -- -- -- --
+.br
+10: -- -- -- 13 -- -- -- -- -- -- -- -- -- -- -- --
+.br
+20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+.br
+30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+.br
+40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+.br
+50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+.br
+60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+.br
+70: -- -- -- -- -- -- -- --
+.br
+
+.br
+$ pigs i2co 1 0x13 0 # get handle for device 0x13 on bus 1
+.br
+0
+.br
+
+.br
+$ pigs i2cwd 0 90 87 51 9 23 # write 5 bytes
+.br
+
+.br
+$ pigs bscx 0x130305 # check for data
+.br
+6 18 90 87 51 9 23
+.br
+
+.br
+$ pigs bscx 0x130305 11 13 15 17 # check for data and send 4 bytes
+.br
+1 262338
+.br
+
+.br
+$ pigs i2crd 0 4 # read 4 bytes
+.br
+4 11 13 15 17
+.br
+
+.br
+$ pigs i2cwd 0 90 87 51 9 23 # write 5 bytes
+.br
+$ pigs bscx 0x130305 11 13 15 17 # check for data and send 4 bytes
+.br
+6 262338 90 87 51 9 23
+.br
+
+.br
+$ pigs i2crd 0 4
+.br
+4 11 13 15 17
+.br
+
+.br
+$ pigs bscx 0x130305 22 33 44 55 66
+.br
+1 327938
+.br
+$ pigs i2crd 0 5
+.br
+5 22 33 44 55 66
+.br
+
+.EE
+
+.br
+
.IP "\fBBSPIC cs\fP - Close bit bang SPI"
.IP "" 4
.br
-This function stops bit banging SPI on a set of GPIO
+This command stops bit banging SPI on a set of GPIO
opened with \fBBSPIO\fP.
.br
.br
+.IP "\fBEVM h bits\fP - Set events to monitor"
+.IP "" 4
+This command starts event reporting on handle \fBh\fP (returned by
+a prior call to \fBNO\fP).
+
+.br
+Upon success nothing is returned. On error a negative status code
+will be returned.
+
+.br
+The notification gets reports for each event specified by \fBbits\fP.
+
+.br
+
+\fBExample\fP
+.br
+
+.EX
+$ pigs evm 0 -1 # Shorthand for events 0-31.
+.br
+$ pigs evm 0 0xf0 # Get notifications for events 4-7.
+.br
+
+.br
+$ pigs evm 1 0xf
+.br
+-25
+.br
+ERROR: unknown handle
+.br
+
+.EE
+
+.br
+
+.IP "\fBEVT event\fP - Trigger event"
+.IP "" 4
+This command triggers event \fBevent\fP.
+
+.br
+One event, number 31, is predefined. This event is
+auto generated on BSC slave activity.
+
+.br
+
+\fBExample\fP
+.br
+
+.EX
+$ pigs evt 12
+.br
+$ pigs evt 5
+.br
+
+.br
+$ pigs evt 32
+.br
+-143
+.br
+ERROR: bad event id
+.br
+
+.EE
+
+.br
+
.IP "\fBFC h\fP - Close file handle"
.IP "" 4
This command closes a file handle \fBh\fP previously opened with \fBFO\fP.
.br
+.IP "\fBbctl\fP - BSC control word" 0
+The command expects a BSC control word, see \fBBSCX\fP.
+
+.br
+
.IP "\fBbit\fP - bit value (0-1)" 0
The command expects 0 or 1.
.br
+.IP "\fBevent\fP - 0-31" 0
+An event is a signal used to inform one or more consumers
+to start an action.
+
+.br
+
.IP "\fBfile\fP - a file name" 0
The file name must match an entry in /opt/pigpio/access.
DCR y Decrement register --*y; F=*y
DCRA Decrement accumulator --A; F=A
DIV x Divide x into accumulator A/=x; F=A
+EVTWT Wait for an event to occur A=wait(x); F=A
HALT Halt Halt
INR y Increment register ++*y; F=*y
INRA Increment accumulator ++A; F=A
y may be a parameter (p0-p9), or a variable (v0-v149). If p or v isn't
specified y is assumed to be a variable.
+.br
+The EVTWT command parameter is a bit-mask with 1 set for events of interest.
+
.br
The WAIT command parameter is a bit-mask with 1 set for GPIO of interest.
break;
case 6: /*
- BI2CZ CF2 FL FR I2CPK I2CRD I2CRI I2CRK I2CZ
- SERR SLR SPIX SPIR
+ BI2CZ CF2 FL FR I2CPK I2CRD I2CRI I2CRK
+ I2CZ SERR SLR SPIX SPIR
*/
printf("%d", r);
if (r < 0) fatal("ERROR: %s", cmdErrStr(r));
}
printf("\n");
break;
+
+ case 8: /*
+ BSCX
+ */
+ if (r < 0)
+ {
+ printf("%d", r);
+ fatal("ERROR: %s", cmdErrStr(r));
+ }
+
+ p = (uint32_t *)response_buf;
+ printf("%d %d", r-3, p[0]);
+
+ if (r > 4)
+ {
+ if (printFlags == PRINT_ASCII) printf(" ");
+
+ for (i=4; i<r; i++)
+ {
+ ch = response_buf[i];
+
+ if (printFlags & PRINT_HEX) printf(" %hhx", ch);
+
+ else if (printFlags & PRINT_ASCII)
+ {
+ if (isprint(ch) || (ch == '\n') || (ch == '\r'))
+ printf("%c", ch);
+ else printf("\\x%02hhx", ch);
+ }
+ else printf(" %hhu", response_buf[i]);
+ }
+ }
+ printf("\n");
+ break;
+
}
}
switch (command)
{
case PI_CMD_BI2CZ:
+ case PI_CMD_BSCX:
case PI_CMD_BSPIX:
case PI_CMD_CF2:
case PI_CMD_FL:
from distutils.core import setup
setup(name='pigpio',
- version='1.33',
+ version='1.34',
author='joan',
author_email='joan@abyz.co.uk',
maintainer='joan',
if [[ $s = "" ]]; then echo "BS2 ok"; else echo "BS2 fail ($s)"; fi
s=$(pigs h)
-if [[ ${#s} = 5273 ]]; then echo "HELP ok"; else echo "HELP fail (${#s})"; fi
+if [[ ${#s} = 5384 ]]; then echo "HELP ok"; else echo "HELP fail (${#s})"; fi
s=$(pigs hwver)
if [[ $s -ne 0 ]]; then echo "HWVER ok"; else echo "HWVER fail ($s)"; fi