diff --git a/command.c b/command.c
index 2a5d0dc..82e1c74 100644
--- a/command.c
+++ b/command.c
@@ -26,7 +26,7 @@ For more information, please refer to
*/
/*
-This version is for pigpio version 56+
+This version is for pigpio version 57+
*/
#include
@@ -55,6 +55,8 @@ cmdInfo_t cmdInfo[]=
{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
@@ -65,6 +67,9 @@ cmdInfo_t cmdInfo[]=
{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
@@ -217,6 +222,7 @@ cmdInfo_t cmdInfo[]=
{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},
@@ -267,15 +273,21 @@ BSPIX cs ... SPI bit bang transfer\n\
\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\
@@ -547,6 +559,7 @@ static errInfo_t errInfo[]=
{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"},
};
@@ -1018,10 +1031,12 @@ int cmdParse(
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]);
@@ -1048,7 +1063,7 @@ int cmdParse(
p[3] = pars;
- if (pars) valid = 1;
+ if (pars || (p[0]==PI_CMD_BSCX)) valid = 1;
}
break;
diff --git a/command.h b/command.h
index c27d64f..eede592 100644
--- a/command.h
+++ b/command.h
@@ -26,7 +26,7 @@ For more information, please refer to
*/
/*
-This version is for pigpio version 56+
+This version is for pigpio version 57+
*/
#ifndef COMMAND_H
diff --git a/pigpio.3 b/pigpio.3
index 6902953..47e6a8a 100644
--- a/pigpio.3
+++ b/pigpio.3
@@ -1484,23 +1484,30 @@ by one for each report.
.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.
@@ -3453,6 +3460,249 @@ End
.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
@@ -4097,6 +4347,11 @@ handle: >=0, as returned by a call to \fBserOpen\fP
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
@@ -4144,9 +4399,14 @@ handle: >=0, as returned by a call to \fBserOpen\fP
.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
@@ -5519,6 +5779,191 @@ gpioSetPad(0, 16); // set pad 0 strength to 16 mA
.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
@@ -7045,6 +7490,43 @@ e.g. to select bits 5, 9, 23 you could use (1<<5) | (1<<9) | (1<<23).
.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
@@ -7282,7 +7764,7 @@ The number may vary between 0 and range (default 255) where
.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
@@ -7303,6 +7785,40 @@ EITHER_EDGE 2
.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
@@ -7425,9 +7941,9 @@ typedef void (*gpioAlertFunc_t) (int gpio, int level, uint32_t tick);
.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
@@ -7649,8 +8165,20 @@ One of
.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
@@ -8137,6 +8665,10 @@ A thread identifier.
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
@@ -8820,16 +9352,24 @@ In the calling function:
.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
@@ -8839,12 +9379,16 @@ In the receiving function:
.br
.br
-user_type my_userdata = *(user_type*)userdata;
+.EX
+user_type my_userdata = *(user_type*)userdata;
.br
.br
free(userdata);
+.br
+
+.EE
.br
@@ -9182,6 +9726,16 @@ A 16-bit word value.
#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
@@ -9480,6 +10034,8 @@ A 16-bit word value.
.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
diff --git a/pigpio.c b/pigpio.c
index 4ad429b..912f689 100644
--- a/pigpio.c
+++ b/pigpio.c
@@ -25,7 +25,7 @@ OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to
*/
-/* pigpio version 56 */
+/* pigpio version 57 */
/* include ------------------------------------------------------- */
@@ -298,6 +298,7 @@ bit 0 READ_LAST_NOT_SET_ERROR
#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)
@@ -309,6 +310,7 @@ bit 0 READ_LAST_NOT_SET_ERROR
#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
@@ -922,6 +924,15 @@ typedef struct
} gpioAlert_t;
+typedef struct
+{
+ callbk_t func;
+ unsigned ex;
+ void *userdata;
+ int ignore;
+ int fired;
+} eventAlert_t;
+
typedef struct
{
unsigned gpio;
@@ -968,6 +979,7 @@ typedef struct
unsigned request;
unsigned run_state;
uint32_t waitBits;
+ uint32_t eventBits;
uint32_t changedBits;
pthread_t *pthIdp;
pthread_mutex_t pthMutex;
@@ -987,6 +999,7 @@ typedef struct
uint16_t seqno;
uint16_t state;
uint32_t bits;
+ uint32_t eventBits;
uint32_t lastReportTick;
int fd;
int pipe;
@@ -1232,6 +1245,8 @@ static volatile uint32_t gFilterBits = 0;
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;
@@ -1240,6 +1255,8 @@ static int pthSocketRunning = 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;
@@ -1289,6 +1306,7 @@ static dmaOPage_t * * dmaOVirt = MAP_FAILED;
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;
@@ -1351,6 +1369,8 @@ static unsigned old_mode_amosi;
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] =
@@ -1445,6 +1465,8 @@ static void intNotifyBits(void);
static void intScriptBits(void);
+static void intScriptEventBits(void);
+
static int gpioNotifyOpenInBand(int fd);
static void initHWClk
@@ -1805,6 +1827,7 @@ static int myDoCommand(uint32_t *p, unsigned bufSize, char *buf)
uint32_t mask;
uint32_t tmp1, tmp2, tmp3, tmp4, tmp5;
gpioPulse_t *pulse;
+ bsc_xfer_t xfer;
int masked;
res = 0;
@@ -1857,6 +1880,20 @@ static int myDoCommand(uint32_t *p, unsigned bufSize, char *buf)
}
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
@@ -1952,6 +1989,10 @@ static int myDoCommand(uint32_t *p, unsigned bufSize, char *buf)
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:
@@ -4807,6 +4848,7 @@ int serWriteByte(unsigned handle, unsigned bVal)
int serReadByte(unsigned handle)
{
+ int r;
char x;
DBG(DBG_USER, "handle=%d", handle);
@@ -4819,15 +4861,19 @@ int serReadByte(unsigned 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);
- return ((int)x) & 0xFF;
+ 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;
+
+ else
+ return PI_SER_READ_FAILED;
}
int serWrite(unsigned handle, char *buf, unsigned count)
@@ -4880,7 +4926,7 @@ int serRead(unsigned handle, char *buf, unsigned count)
}
else
{
- buf[r] = 0;
+ if (r < count) buf[r] = 0;
return r;
}
}
@@ -5562,7 +5608,7 @@ static void alertEmit(
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;
@@ -5586,6 +5632,36 @@ static void alertEmit(
}
}
+ 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<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);
@@ -6337,7 +6490,9 @@ static void *pthScript(void *x)
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)
@@ -6736,6 +6891,7 @@ static void *pthSocketThreadHandler(void *fdC)
/* extensions */
case PI_CMD_BI2CZ:
+ case PI_CMD_BSCX:
case PI_CMD_CF2:
case PI_CMD_FL:
case PI_CMD_FR:
@@ -7012,6 +7168,11 @@ static int initPeripherals(void)
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;
}
@@ -7576,6 +7737,13 @@ static void initClearGlobals(void)
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; iI.SDA, PI_INPUT);
- return gpioRead(w->I.SDA);
+ return myGpioRead(w->I.SDA);
}
static void set_SDA(wfRx_t *w)
@@ -9925,7 +10095,7 @@ static void I2C_clock_stretch(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)
@@ -10236,6 +10406,118 @@ int bbI2CZip(
/* ----------------------------------------------------------------------- */
+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));
@@ -10744,6 +11026,98 @@ int gpioSerialReadClose(unsigned gpio)
}
+/* ----------------------------------------------------------------------- */
+
+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(
@@ -11159,6 +11533,25 @@ static void intScriptBits(void)
}
+static void intScriptEventBits(void)
+{
+ int i;
+ uint32_t bits;
+
+ bits = 0;
+
+ for (i=0; i
#include
#include
-#define PIGPIO_VERSION 56
+#define PIGPIO_VERSION 57
/*TEXT
@@ -289,6 +289,10 @@ bbSPIOpen Opens GPIO for bit banging SPI
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
@@ -310,6 +314,13 @@ fileWrite Writes bytes to a file
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
@@ -482,6 +493,20 @@ typedef struct
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);
@@ -491,6 +516,13 @@ typedef void (*gpioAlertFuncEx_t) (int gpio,
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);
@@ -588,6 +620,7 @@ typedef void *(gpioThreadFunc_t) (void *);
#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)
@@ -696,6 +729,49 @@ typedef void *(gpioThreadFunc_t) (void *);
#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
@@ -825,6 +901,14 @@ typedef void *(gpioThreadFunc_t) (void *);
#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
@@ -1525,15 +1609,19 @@ typedef struct
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.
@@ -2704,6 +2792,127 @@ End
...
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,
@@ -3063,6 +3272,8 @@ handle: >=0, as returned by a call to [*serOpen*]
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*/
@@ -3094,8 +3305,10 @@ handle: >=0, as returned by a call to [*serOpen*]
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*/
@@ -3885,6 +4098,104 @@ gpioSetPad(0, 16); // set pad 0 strength to 16 mA
...
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);
@@ -4771,6 +5082,22 @@ A convenient way to set bit n is to or in (1<=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.
@@ -5231,6 +5578,7 @@ pud::0-2
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
@@ -5522,17 +5870,21 @@ following technique.
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::
@@ -5697,6 +6049,11 @@ PARAMS*/
#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*/
/*
@@ -5755,6 +6112,7 @@ after this command is issued.
#define PI_CMD_X 839
#define PI_CMD_XA 840
#define PI_CMD_XOR 841
+#define PI_CMD_EVTWT 842
/*DEF_S Error Codes*/
@@ -5903,6 +6261,7 @@ after this command is issued.
#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
diff --git a/pigpio.py b/pigpio.py
index b0962d5..b22202e 100644
--- a/pigpio.py
+++ b/pigpio.py
@@ -56,7 +56,7 @@ If you wish to handle the returned status yourself you should set
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
@@ -242,6 +242,11 @@ bb_spi_open Opens GPIO for bit banging SPI
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
@@ -264,6 +269,12 @@ file_write Writes bytes to a file
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
@@ -288,7 +299,7 @@ import threading
import os
import atexit
-VERSION = "1.33"
+VERSION = "1.34"
exceptions = True
@@ -337,6 +348,7 @@ PI_SCRIPT_FAILED =4
# notification flags
+NTFY_FLAGS_EVENT = (1 << 7)
NTFY_FLAGS_ALIVE = (1 << 6)
NTFY_FLAGS_WDOG = (1 << 5)
NTFY_FLAGS_GPIO = 31
@@ -376,6 +388,8 @@ SPI_CS_HIGH_ACTIVE = 1 << 2
SPI_TX_LSBFIRST = 1 << 14
SPI_RX_LSBFIRST = 1 << 15
+EVENT_BSC = 31
+
# pigpio command numbers
_PI_CMD_MODES= 0
@@ -518,6 +532,11 @@ _PI_CMD_BSPIC=111
_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
@@ -663,6 +682,7 @@ 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
# pigpio error text
@@ -807,13 +827,14 @@ _errors=[
[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
@@ -823,7 +844,7 @@ E.g. export PIGPIO_ADDR=soft, export PIGPIO_PORT=8888
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"""
@@ -981,6 +1002,22 @@ def _pigpio_command_ext(sl, cmd, p1, p2, p3, extents, rl=True):
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< 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
@@ -3545,6 +3934,8 @@ class pi():
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)
...
@@ -3567,18 +3958,19 @@ class pi():
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:
@@ -4079,7 +4471,7 @@ class pi():
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
@@ -4100,7 +4492,7 @@ class pi():
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 ..
@@ -4110,14 +4502,14 @@ class pi():
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
@@ -4137,7 +4529,7 @@ class pi():
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)
@@ -4284,7 +4676,7 @@ class pi():
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")
@@ -4328,7 +4720,7 @@ class pi():
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
@@ -4359,6 +4751,7 @@ class pi():
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
@@ -4400,6 +4793,45 @@ class pi():
"""
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.
@@ -4435,6 +4867,29 @@ class pi():
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)):
@@ -4511,12 +4966,12 @@ class pi():
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.
@@ -4580,6 +5035,18 @@ def xref():
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.
@@ -4615,9 +5082,12 @@ def xref():
range_ @ Fully On
edge: 0-2
+
+ . .
EITHER_EDGE = 2
FALLING_EDGE = 1
RISING_EDGE = 0
+ . .
errnum: <0
@@ -4732,10 +5202,17 @@ def xref():
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
@@ -4743,7 +5220,7 @@ def xref():
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
@@ -4781,7 +5258,7 @@ def xref():
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
@@ -4808,8 +5285,13 @@ def xref():
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.
@@ -4831,6 +5313,8 @@ def xref():
level logic.
level: 0-1 (2)
+
+ . .
CLEAR = 0
HIGH = 1
LOW = 0
@@ -4838,6 +5322,7 @@ def xref():
ON = 1
SET = 1
TIMEOUT = 2 # only returned for a watchdog timeout
+ . .
MISO:
The GPIO used for the MISO signal when bit banging SPI.
@@ -4846,6 +5331,7 @@ def xref():
1.The operational mode of a GPIO, normally INPUT or OUTPUT.
+ . .
ALT0 = 4
ALT1 = 5
ALT2 = 6
@@ -4854,13 +5340,16 @@ def xref():
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.
@@ -4892,9 +5381,11 @@ def xref():
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.
@@ -4943,9 +5434,11 @@ def xref():
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
@@ -5003,13 +5496,20 @@ def xref():
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
diff --git a/pigpiod_if.3 b/pigpiod_if.3
index 284a3ae..2fe7ed2 100644
--- a/pigpiod_if.3
+++ b/pigpiod_if.3
@@ -3612,6 +3612,11 @@ handle: >=0, as returned by a call to \fBserial_open\fP.
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
@@ -3662,6 +3667,11 @@ handle: >=0, as returned by a call to \fBserial_open\fP.
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
diff --git a/pigpiod_if.h b/pigpiod_if.h
index 6706b9d..6200a79 100644
--- a/pigpiod_if.h
+++ b/pigpiod_if.h
@@ -2318,6 +2318,8 @@ handle: >=0, as returned by a call to [*serial_open*].
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*/
@@ -2350,6 +2352,8 @@ handle: >=0, as returned by a call to [*serial_open*].
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*/
diff --git a/pigpiod_if2.3 b/pigpiod_if2.3
index 66ad4e0..5b25e0c 100644
--- a/pigpiod_if2.3
+++ b/pigpiod_if2.3
@@ -1008,23 +1008,30 @@ by one for each report.
.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.
@@ -4423,6 +4430,11 @@ handle: >=0, as returned by a call to \fBserial_open\fP.
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
@@ -4474,9 +4486,14 @@ handle: >=0, as returned by a call to \fBserial_open\fP.
.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
@@ -5331,8 +5348,8 @@ pigif_duplicate_callback, or pigif_bad_callback.
.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
@@ -5355,7 +5372,7 @@ The function returns 0 if OK, otherwise pigif_callback_not_found.
.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
@@ -5391,6 +5408,479 @@ a \fBcallback\fP function.
.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
@@ -5484,6 +5974,43 @@ e.g. to select bits 5, 9, 23 you could use (1<<5) | (1<<9) | (1<<23).
.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.
@@ -5510,8 +6037,24 @@ An 8-bit byte value.
.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
@@ -5536,7 +6079,7 @@ typedef void (*CBFunc_t)
.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
@@ -5643,6 +6186,50 @@ of the error.
.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.
@@ -5745,11 +6332,11 @@ typedef struct
.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
@@ -5773,8 +6360,20 @@ typedef void *(gpioThreadFunc_t) (void *);
.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
@@ -6196,6 +6795,10 @@ The hardware PWM frequency.
.IP "\fBrange\fP: 25-40000" 0
The permissible dutycycle values are 0-range.
+.br
+
+.br
+
.EX
PI_MIN_DUTYCYCLE_RANGE 25
.br
@@ -6404,6 +7007,10 @@ thread.
.IP "\fBtimeout\fP" 0
A GPIO watchdog timeout in milliseconds.
+.br
+
+.br
+
.EX
PI_MIN_WDOG_TIMEOUT 0
.br
@@ -6472,16 +7079,24 @@ In the calling function:
.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
@@ -6491,12 +7106,16 @@ In the receiving function:
.br
.br
-user_type my_userdata = *(user_type*)userdata;
+.EX
+user_type my_userdata = *(user_type*)userdata;
.br
.br
free(userdata);
+.br
+
+.EE
.br
@@ -6510,7 +7129,16 @@ Denoting no parameter is required
.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
@@ -6524,7 +7152,14 @@ A number representing a waveform created by \fBwave_create\fP.
.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
diff --git a/pigpiod_if2.c b/pigpiod_if2.c
index 842fb4b..d94732a 100644
--- a/pigpiod_if2.c
+++ b/pigpiod_if2.c
@@ -25,7 +25,7 @@ OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to
*/
-/* PIGPIOD_IF2_VERSION 8 */
+/* PIGPIOD_IF2_VERSION 9 */
#include
#include
@@ -74,6 +74,19 @@ struct callback_s
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];
@@ -82,6 +95,7 @@ static int gPigCommand [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];
@@ -93,6 +107,9 @@ static int gCancelState [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)
@@ -278,6 +295,7 @@ static int pigpioOpenSocket(char *addr, char *port)
static void dispatch_notification(int pi, gpioReport_t *r)
{
callback_t *p;
+ evtCallback_t *ep;
uint32_t changed;
int l, g;
@@ -310,18 +328,37 @@ static void dispatch_notification(int pi, gpioReport_t *r)
}
else
{
- g = (r->flags) & 31;
-
- p = gCallBackFirst;
-
- while (p)
+ if ((r->flags) & PI_NTFY_FLAGS_WDOG)
{
- if (((p->pi) == pi) && ((p->gpio) == g))
+ g = (r->flags) & 31;
+
+ p = gCallBackFirst;
+
+ while (p)
{
- if (p->ex) (p->f)(pi, g, PI_TIMEOUT, r->tick, p->user);
- else (p->f)(pi, g, PI_TIMEOUT, r->tick);
+ 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)
+ {
+ g = (r->flags) & 31;
+
+ ep = geCallBackFirst;
+
+ while (ep)
+ {
+ 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;
}
}
}
@@ -447,8 +484,90 @@ static int intCallback(
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;
@@ -1875,3 +1994,114 @@ int wait_for_edge(int pi, unsigned user_gpio, unsigned edge, double timeout)
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);}
+
diff --git a/pigpiod_if2.h b/pigpiod_if2.h
index ced2c9a..dc6f701 100644
--- a/pigpiod_if2.h
+++ b/pigpiod_if2.h
@@ -121,7 +121,7 @@ set_servo_pulsewidth Start/stop servo pulses on a GPIO
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
@@ -257,6 +257,11 @@ bb_spi_open Opens GPIO for bit banging SPI
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
@@ -278,6 +283,14 @@ file_write Writes bytes to a file
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
@@ -306,10 +319,18 @@ typedef void (*CBFunc_t)
(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
@@ -788,15 +809,19 @@ typedef struct
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.
@@ -2743,6 +2768,8 @@ handle: >=0, as returned by a call to [*serial_open*].
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*/
@@ -2775,8 +2802,10 @@ handle: >=0, as returned by a call to [*serial_open*].
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*/
@@ -3237,8 +3266,8 @@ user_gpio: 0-31.
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*/
@@ -3256,7 +3285,7 @@ D*/
/*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.
. .
@@ -3276,6 +3305,258 @@ a [*callback*] function.
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
@@ -3320,6 +3601,22 @@ A convenient way to set bit n is to or in (1<=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::
. .
@@ -3343,7 +3647,7 @@ typedef void (*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::
@@ -3390,6 +3694,24 @@ errnum::
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.
@@ -3440,9 +3762,9 @@ gpioPulse_t::
. .
typedef struct
{
-uint32_t gpioOn;
-uint32_t gpioOff;
-uint32_t usDelay;
+ uint32_t gpioOn;
+ uint32_t gpioOff;
+ uint32_t usDelay;
} gpioPulse_t;
. .
@@ -3452,8 +3774,13 @@ typedef void *(gpioThreadFunc_t) (void *);
. .
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.
@@ -3640,6 +3967,7 @@ The hardware PWM frequency.
range::25-40000
The permissible dutycycle values are 0-range.
+
. .
PI_MIN_DUTYCYCLE_RANGE 25
PI_MAX_DUTYCYCLE_RANGE 40000
@@ -3731,6 +4059,7 @@ thread.
timeout::
A GPIO watchdog timeout in milliseconds.
+
. .
PI_MIN_WDOG_TIMEOUT 0
PI_MAX_WDOG_TIMEOUT 60000
@@ -3761,29 +4090,40 @@ following technique.
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.
diff --git a/pigs.1 b/pigs.1
index f8fcb7a..28bc9bf 100644
--- a/pigs.1
+++ b/pigs.1
@@ -484,11 +484,211 @@ ERROR: no permission to update one or more GPIO
.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
@@ -744,6 +944,72 @@ configuration settings to \fBv\fP.
.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.
@@ -4672,6 +4938,11 @@ the transmission of serial data (I2C/SPI/serial link, waves).
.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.
@@ -4736,6 +5007,12 @@ The command expects the name of a tty serial device, e.g.
.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.
@@ -5343,6 +5620,7 @@ CMP x Compare x with accumulator F=A-x
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
@@ -5383,6 +5661,9 @@ x may be a constant, a parameter (p0-p9), or a variable (v0-v149).
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.
diff --git a/pigs.c b/pigs.c
index 3395f2f..24f1fee 100644
--- a/pigs.c
+++ b/pigs.c
@@ -172,8 +172,8 @@ void print_result(int sock, int rv, cmdCmd_t cmd)
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));
@@ -216,6 +216,41 @@ void print_result(int sock, int rv, cmdCmd_t cmd)
}
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