This commit is contained in:
joan 2016-10-30 15:30:20 +00:00
parent abe5f12942
commit c31a2fa6b2
15 changed files with 3552 additions and 175 deletions

View File

@ -26,7 +26,7 @@ For more information, please refer to <http://unlicense.org/>
*/
/*
This version is for pigpio version 56+
This version is for pigpio version 57+
*/
#include <stdio.h>
@ -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;

View File

@ -26,7 +26,7 @@ For more information, please refer to <http://unlicense.org/>
*/
/*
This version is for pigpio version 56+
This version is for pigpio version 57+
*/
#ifndef COMMAND_H

578
pigpio.3
View File

@ -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

441
pigpio.c
View File

@ -25,7 +25,7 @@ OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>
*/
/* 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)
r = read(serInfo[handle].fd, &x, 1);
if (r == 1)
return ((int)x) & 0xFF;
else if (r == 0)
return PI_SER_READ_NO_DATA;
else if ((r == -1) && (errno == EAGAIN))
return PI_SER_READ_NO_DATA;
else
return PI_SER_READ_FAILED;
}
return ((int)x) & 0xFF;
}
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<<b);
if (eventAlert[b].func)
{
if (eventAlert[b].ex)
{
(eventAlert[b].func)(b, eTick, eventAlert[b].userdata);
}
else
{
(eventAlert[b].func)(b, eTick);
}
}
}
eventAlert[b].fired = 0;
}
/* call alert callbacks for each bit transition */
if (changedBits & alertBits)
@ -5677,7 +5753,7 @@ static void alertEmit(
gpioNotify[n].state = PI_NOTIFY_CLOSED;
}
else if (gpioNotify[n].state == PI_NOTIFY_RUNNING)
else if (gpioNotify[n].state != PI_NOTIFY_CLOSED)
{
bits = gpioNotify[n].bits;
@ -5685,6 +5761,8 @@ static void alertEmit(
seqno = gpioNotify[n].seqno;
if (gpioNotify[n].state == PI_NOTIFY_RUNNING)
{
/* check to see if any bits have changed for this
notification.
@ -5740,8 +5818,37 @@ static void alertEmit(
newLevel = reportedLevel;
report[emit].seqno = seqno;
report[emit].flags = PI_NTFY_FLAGS_WDOG |
PI_NTFY_FLAGS_BIT(b);
report[emit].flags =
PI_NTFY_FLAGS_WDOG | PI_NTFY_FLAGS_BIT(b);
report[emit].tick = eTick;
report[emit].level = newLevel;
emit++;
seqno++;
}
}
}
}
/* check to see if any events are due
eventBits is the set of events
*/
if (eventBits & gpioNotify[n].eventBits)
{
for (b=0; b<=PI_MAX_EVENT; b++)
{
if (eventBits & gpioNotify[n].eventBits & (1<<b))
{
if (numSamples)
newLevel = sample[numSamples-1].level;
else
newLevel = reportedLevel;
report[emit].seqno = seqno;
report[emit].flags =
PI_NTFY_FLAGS_EVENT | PI_NTFY_FLAGS_BIT(b);
report[emit].tick = eTick;
report[emit].level = newLevel;
@ -5895,6 +6002,28 @@ static void alertEmit(
}
}
if (eventBits & scriptEventBits)
{
for (n=0; n<PI_MAX_SCRIPTS; n++)
{
if ((gpioScript[n].state == PI_SCRIPT_IN_USE) &&
(gpioScript[n].run_state == PI_SCRIPT_WAITING) &&
(gpioScript[n].eventBits & eventBits))
{
pthread_mutex_lock(&gpioScript[n].pthMutex);
if (gpioScript[n].run_state == PI_SCRIPT_WAITING)
{
gpioScript[n].changedBits =
gpioScript[n].eventBits & eventBits;
pthread_cond_signal(&gpioScript[n].pthCond);
}
pthread_mutex_unlock(&gpioScript[n].pthMutex);
}
}
}
if (numSamples) reportedLevel = sample[numSamples-1].level;
}
@ -6206,6 +6335,30 @@ static void scrSwap(int *v1, int *v2)
/* ----------------------------------------------------------------------- */
static int scrEvtWait(gpioScript_t *s, uint32_t bits)
{
pthread_mutex_lock(&s->pthMutex);
if (s->request == PI_SCRIPT_RUN)
{
s->run_state = PI_SCRIPT_WAITING;
s->eventBits = bits;
intScriptEventBits();
pthread_cond_wait(&s->pthCond, &s->pthMutex);
s->waitBits = 0;
intScriptEventBits();
s->run_state = PI_SCRIPT_RUNNING;
}
pthread_mutex_unlock(&s->pthMutex);
return s->changedBits;
}
/* ----------------------------------------------------------------------- */
static int scrWait(gpioScript_t *s, uint32_t bits)
{
pthread_mutex_lock(&s->pthMutex);
@ -6339,6 +6492,8 @@ static void *pthScript(void *x)
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)
{++s->script.par[p1o]; F=s->script.par[p1o];}
@ -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; i<PWM_FREQS; i++)
@ -7665,6 +7833,7 @@ static void initReleaseResources(void)
/* release mmap'd memory */
if (auxReg != MAP_FAILED) munmap((void *)auxReg, AUX_LEN);
if (bscsReg != MAP_FAILED) munmap((void *)bscsReg, BSCS_LEN);
if (clkReg != MAP_FAILED) munmap((void *)clkReg, CLK_LEN);
if (dmaReg != MAP_FAILED) munmap((void *)dmaReg, DMA_LEN);
if (gpioReg != MAP_FAILED) munmap((void *)gpioReg, GPIO_LEN);
@ -7674,6 +7843,7 @@ static void initReleaseResources(void)
if (spiReg != MAP_FAILED) munmap((void *)spiReg, SPI_LEN);
auxReg = MAP_FAILED;
bscsReg = MAP_FAILED;
clkReg = MAP_FAILED;
dmaReg = MAP_FAILED;
gpioReg = MAP_FAILED;
@ -9894,7 +10064,7 @@ int gpioWaveGetMaxCbs(void)
static int read_SDA(wfRx_t *w)
{
myGpioSetMode(w->I.SDA, PI_INPUT);
return gpioRead(w->I.SDA);
return myGpioRead(w->I.SDA);
}
static void set_SDA(wfRx_t *w)
@ -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<PI_MAX_SCRIPTS; i++)
{
if (gpioScript[i].state == PI_SCRIPT_IN_USE)
{
bits |= gpioScript[i].eventBits;
}
}
scriptEventBits = bits;
}
static void intNotifyBits(void)
{
int i;
@ -11463,8 +11856,17 @@ static int intGpioSetTimerFunc(unsigned id,
{
if (gpioTimer[id].running)
{
/* destroy thread */
if (pthread_self() == gpioTimer[id].pthId)
{
gpioTimer[id].running = 0;
gpioTimer[id].func = 0;
pthread_exit(NULL);
}
else
{
if (pthread_cancel(gpioTimer[id].pthId))
SOFT_ERROR(PI_TIMER_FAILED, "timer %d, cancel failed (%m)", id);
@ -11472,7 +11874,8 @@ static int intGpioSetTimerFunc(unsigned id,
SOFT_ERROR(PI_TIMER_FAILED, "timer %d, join failed (%m)", id);
gpioTimer[id].running = 0;
gpioTimer[id].func = f;
gpioTimer[id].func = 0;
}
}
}
@ -11566,11 +11969,19 @@ void gpioStopThread(pthread_t *pth)
CHECK_INITED_RET_NIL;
if (pth)
{
if (pthread_self() == *pth)
{
free(pth);
pthread_exit(NULL);
}
else
{
pthread_cancel(*pth);
pthread_join(*pth, NULL);
free(pth);
}
}
}
/* ----------------------------------------------------------------------- */

379
pigpio.h
View File

@ -31,7 +31,7 @@ For more information, please refer to <http://unlicense.org/>
#include <stdint.h>
#include <pthread.h>
#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<<n).
e.g. to select bits 5, 9, 23 you could use (1<<5) | (1<<9) | (1<<23).
*bsc_xfer::
A pointer to a [*bsc_xfer_t*] object used to control a BSC transfer.
bsc_xfer_t::
. .
typedef struct
{
uint32_t control; // Write
int rxCnt; // Read only
char rxBuf[BSC_FIFO_SIZE]; // Read only
int txCnt; // Write
char txBuf[BSC_FIFO_SIZE]; // Write
} bsc_xfer_t;
. .
*buf::
A buffer to hold data being sent or being received.
@ -4866,7 +5193,7 @@ The number may vary between 0 and range (default 255) where
0 is off and range is fully on.
edge::0-2
The type of GPIO edge to generate an intrrupt. See [*gpioSetISRFunc*],
The type of GPIO edge to generate an interrupt. See [*gpioSetISRFunc*]
and [*gpioSetISRFuncEx*].
. .
@ -4875,6 +5202,21 @@ FALLING_EDGE 1
EITHER_EDGE 2
. .
event::0-31
An event is a signal used to inform one or more consumers
to start an action.
eventFunc_t::
. .
typedef void (*eventFunc_t) (int event, uint32_t tick);
. .
eventFuncEx_t::
. .
typedef void (*eventFuncEx_t)
(int event, uint32_t tick, void *userdata);
. .
f::
A function.
@ -4931,8 +5273,8 @@ typedef void (*gpioAlertFunc_t) (int gpio, int level, uint32_t tick);
gpioAlertFuncEx_t::
. .
typedef void (*gpioAlertFuncEx_t)
(int gpio, int level, uint32_t tick, void *userdata);
typedef void (*eventFuncEx_t)
(int event, int level, uint32_t tick, void *userdata);
. .
gpioCfg*::
@ -5026,8 +5368,13 @@ One of
handle::>=0
A number referencing an object opened by one of [*fileOpen*],
[*gpioNotifyOpen*], [*i2cOpen*], [*serOpen*], [*spiOpen*].
A number referencing an object opened by one of
[*fileOpen*]
[*gpioNotifyOpen*]
[*i2cOpen*]
[*serOpen*]
[*spiOpen*]
i2cAddr:: 0-0x7F
The address of a device on the I2C bus.
@ -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

576
pigpio.py
View File

@ -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<<event
class _callback_ADT:
"""An ADT class to hold callback information."""
@ -1007,7 +1044,9 @@ class _callback_thread(threading.Thread):
self.go = False
self.daemon = True
self.monitor = 0
self.event_bits = 0
self.callbacks = []
self.events = []
self.sl.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sl.s.settimeout(None)
self.sl.s.connect((host, port))
@ -1039,6 +1078,28 @@ class _callback_thread(threading.Thread):
_pigpio_command(
self.control, _PI_CMD_NB, self.handle, self.monitor)
def append_event(self, callb):
"""
Adds an event callback to the notification thread.
"""
self.events.append(callb)
self.event_bits = self.event_bits | callb.bit
_pigpio_command(self.control, _PI_CMD_EVM, self.handle, self.event_bits)
def remove_event(self, callb):
"""
Removes an event callback from the notification thread.
"""
if callb in self.events:
self.events.remove(callb)
new_event_bits = 0
for c in self.events:
new_event_bits |= c.bit
if new_event_bits != self.event_bits:
self.event_bits = new_event_bits
_pigpio_command(
self.control, _PI_CMD_EVM, self.handle, self.event_bits)
def run(self):
"""Runs the notification thread."""
@ -1071,7 +1132,12 @@ class _callback_thread(threading.Thread):
gpio = flags & NTFY_FLAGS_GPIO
for cb in self.callbacks:
if cb.gpio == gpio:
cb.func(cb.gpio, TIMEOUT, tick)
cb.func(gpio, TIMEOUT, tick)
elif flags & NTFY_FLAGS_EVENT:
event = flags & NTFY_FLAGS_GPIO
for cb in self.events:
if cb.event == event:
cb.func(event, tick)
self.sl.s.close()
@ -1118,6 +1184,52 @@ class _callback:
self._reset = True
self.count = 0
class _event:
"""A class to provide event callbacks."""
def __init__(self, notify, event, func=None):
"""
Initialise an event and adds it to the notification thread.
"""
self._notify = notify
self.count=0
self._reset = False
if func is None:
func=self._tally
self.callb = _event_ADT(event, func)
self._notify.append_event(self.callb)
def cancel(self):
"""
Cancels a event callback by removing it from the
notification thread.
"""
self._notify.remove_event(self.callb)
def _tally(self, event, tick):
"""Increment the event callback called count."""
if self._reset:
self._reset = False
self.count = 0
self.count += 1
def tally(self):
"""
Provides a count of how many times the default tally
callback has triggered.
The count will be zero if the user has supplied their own
callback function.
"""
return self.count
def reset_tally(self):
"""
Resets the tally count to zero.
"""
self._reset = True
self.count = 0
class _wait_for_edge:
"""Encapsulates waiting for GPIO edges."""
@ -1136,6 +1248,24 @@ class _wait_for_edge:
"""Sets wait_for_edge triggered."""
self.trigger = True
class _wait_for_event:
"""Encapsulates waiting for an event."""
def __init__(self, notify, event, timeout):
"""Initialises wait_for_event."""
self._notify = notify
self.callb = _event_ADT(event, self.func)
self.trigger = False
self._notify.append_event(self.callb)
self.start = time.time()
while (self.trigger == False) and ((time.time()-self.start) < timeout):
time.sleep(0.05)
self._notify.remove_event(self.callb)
def func(self, event, tick):
"""Sets wait_for_event triggered."""
self.trigger = True
class pi():
def _rxbuf(self, count):
@ -1501,7 +1631,7 @@ class pi():
E.g. if the function returns 15 then the notifications must be
read from /dev/pigpio15.
Notifications have the following structure.
Notifications have the following structure:
. .
H seqno
@ -1513,16 +1643,20 @@ class pi():
seqno: starts at 0 each time the handle is opened and then
increments by one for each report.
flags: two flags are defined, PI_NTFY_FLAGS_WDOG and
PI_NTFY_FLAGS_ALIVE.
flags: three flags are defined, PI_NTFY_FLAGS_WDOG,
PI_NTFY_FLAGS_ALIVE, and PI_NTFY_FLAGS_EVENT.
PI_NTFY_FLAGS_WDOG, if bit 5 is set then bits 0-4 of the
If bit 5 is set (PI_NTFY_FLAGS_WDOG) then bits 0-4 of the
flags indicate a GPIO which has had a watchdog timeout.
PI_NTFY_FLAGS_ALIVE, if bit 6 is set this indicates a keep
If bit 6 is set (PI_NTFY_FLAGS_ALIVE) this indicates a keep
alive signal on the pipe/socket and is sent once a minute
in the absence of other notification activity.
If bit 7 is set (PI_NTFY_FLAGS_EVENT) then bits 0-4 of the
flags indicate an event which has been triggered.
tick: the number of microseconds since system boot. It wraps
around after 1h12m.
@ -1732,7 +1866,7 @@ class pi():
The same clock is available on multiple GPIO. The latest
frequency setting will be used by all GPIO which share a clock.
The GPIO must be one of the following.
The GPIO must be one of the following:
. .
4 clock 0 All models
@ -1783,7 +1917,7 @@ class pi():
The latest frequency and dutycycle setting will be used
by all GPIO which share a PWM channel.
The GPIO must be one of the following.
The GPIO must be one of the following:
. .
12 PWM channel 0 All models but A and B
@ -2418,7 +2552,7 @@ class pi():
For the SMBus commands the low level transactions are shown
at the end of the function description. The following
abbreviations are used.
abbreviations are used:
. .
S (1 bit) : Start bit
@ -3229,7 +3363,7 @@ class pi():
...
(count, data) = pi.bb_i2c_zip(
h, [4, 0x53, 2, 7, 1, 0x32, 2, 6, 6, 3, 0])
SDA, [4, 0x53, 2, 7, 1, 0x32, 2, 6, 6, 3, 0])
...
The following command codes are supported:
@ -3293,6 +3427,261 @@ class pi():
self.sl.l.release()
return bytes, data
def event_trigger(self, event):
"""
This function signals the occurrence of an event.
event:= 0-31, the event
Returns 0 if OK, otherwise PI_BAD_EVENT_ID.
An event is a signal used to inform one or more consumers
to start an action. Each consumer which has registered an
interest in the event (e.g. by calling [*event_callback*]) will
be informed by a callback.
One event, EVENT_BSC (31) is predefined. This event is
auto generated on BSC slave activity.
The meaning of other events is arbitrary.
Note that other than its id and its tick there is no data associated
with an event.
...
pi.event_trigger(23)
...
"""
return _u2i(_pigpio_command(self.sl, _PI_CMD_EVT, event, 0))
def bsc_xfer(self, bsc_control, data):
"""
This function provides a low-level interface to the
SPI/I2C Slave peripheral. This peripheral allows the
Pi to act as a slave device on an I2C or SPI bus.
I can't get SPI to work properly. I tried with a
control word of 0x303 and swapped MISO and MOSI.
The function sets the BSC mode, writes any data in
the transmit buffer to the BSC transmit FIFO, and
copies any data in the BSC receive FIFO to the
receive buffer.
bsc_control:= see below
data:= the data bytes to place in the transmit FIFO.
The returned value is a tuple of the status (see below),
the number of bytes read, and a bytearray containing the
read bytes. If there was an error the status will be less
than zero (and will contain the error code).
Note that the control word sets the BSC mode. The BSC will
stay in that mode until a different control word is sent.
The BSC peripheral uses GPIO 18 (SDA) and 19 (SCL)
in I2C mode and GPIO 18 (MOSI), 19 (SCLK), 20 (MISO),
and 21 (CE) in SPI mode. You need to swap MISO/MOSI
between master and slave.
When a zero control word is received GPIO 18-21 will be reset
to INPUT mode.
bsc_control consists of the following bits:
. .
22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
a a a a a a a - - IT HC TF IR RE TE BK EC ES PL PH I2 SP EN
. .
Bits 0-13 are copied unchanged to the BSC CR register. See
pages 163-165 of the Broadcom peripherals document for full
details.
aaaaaaa @ defines the I2C slave address (only relevant in I2C mode)
IT @ invert transmit status flags
HC @ enable host control
TF @ enable test FIFO
IR @ invert receive status flags
RE @ enable receive
TE @ enable transmit
BK @ abort operation and clear FIFOs
EC @ send control register as first I2C byte
ES @ send status register as first I2C byte
PL @ set SPI polarity high
PH @ set SPI phase high
I2 @ enable I2C mode
SP @ enable SPI mode
EN @ enable BSC peripheral
The status has the following format:
. .
20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
S S S S S R R R R R T T T T T RB TE RF TF RE TB
. .
Bits 0-15 are copied unchanged from the BSC FR register. See
pages 165-166 of the Broadcom peripherals document for full
details.
SSSSS @ number of bytes successfully copied to transmit FIFO
RRRRR @ number of bytes in receieve FIFO
TTTTT @ number of bytes in transmit FIFO
RB @ receive busy
TE @ transmit FIFO empty
RF @ receive FIFO full
TF @ transmit FIFO full
RE @ receive FIFO empty
TB @ transmit busy
...
(status, count, data) = pi.bsc_xfer(0x330305, "Hello!")
...
"""
# I p1 control
# I p2 0
# I p3 len
## extension ##
# s len data bytes
# Don't raise exception. Must release lock.
bytes = u2i(_pigpio_command_ext(
self.sl, _PI_CMD_BSCX, bsc_control, 0, len(data), [data], False))
if bytes > 0:
rx = self._rxbuf(bytes)
status = struct.unpack('I', rx[0:4])[0]
bytes -= 4
data = rx[4:]
else:
status = bytes
bytes = 0
data = bytearray(b'')
self.sl.l.release()
return status, bytes, data
def bsc_i2c(self, i2c_address, data=[]):
"""
This function allows the Pi to act as a slave I2C device.
The data bytes (if any) are written to the BSC transmit
FIFO and the bytes in the BSC receive FIFO are returned.
i2c_address:= the I2C slave address.
data:= the data bytes to transmit.
The returned value is a tuple of the status, the number
of bytes read, and a bytearray containing the read bytes.
See [*bsc_xfer*] for details of the status value.
If there was an error the status will be less than zero
(and will contain the error code).
Note that an i2c_address of 0 may be used to close
the BSC device and reassign the used GPIO (18/19)
as inputs.
This example assumes GPIO 2/3 are connected to GPIO 18/19.
...
#!/usr/bin/env python
import time
import pigpio
I2C_ADDR=0x13
def i2c(id, tick):
global pi
s, b, d = pi.bsc_i2c(I2C_ADDR)
if b:
if d[0] == ord('t'): # 116 send 'HH:MM:SS*'
print("sent={} FR={} received={} [{}]".
format(s>>16, s&0xfff,b,d))
s, b, d = pi.bsc_i2c(I2C_ADDR,
"{}*".format(time.asctime()[11:19]))
elif d[0] == ord('d'): # 100 send 'Sun Oct 30*'
print("sent={} FR={} received={} [{}]".
format(s>>16, s&0xfff,b,d))
s, b, d = pi.bsc_i2c(I2C_ADDR,
"{}*".format(time.asctime()[:10]))
pi = pigpio.pi()
if not pi.connected:
exit()
# Respond to BSC slave activity
e = pi.event_callback(pigpio.EVENT_BSC, i2c)
pi.bsc_i2c(I2C_ADDR) # Configure BSC as I2C slave
time.sleep(600)
e.cancel()
pi.bsc_i2c(0) # Disable BSC peripheral
pi.stop()
...
While running the above.
. .
$ i2cdetect -y 1
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- 13 -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
$ pigs i2co 1 0x13 0
0
$ pigs i2cwd 0 116
$ pigs i2crd 0 9 -a
9 10:13:58*
$ pigs i2cwd 0 116
$ pigs i2crd 0 9 -a
9 10:14:29*
$ pigs i2cwd 0 100
$ pigs i2crd 0 11 -a
11 Sun Oct 30*
$ pigs i2cwd 0 100
$ pigs i2crd 0 11 -a
11 Sun Oct 30*
$ pigs i2cwd 0 116
$ pigs i2crd 0 9 -a
9 10:23:16*
$ pigs i2cwd 0 100
$ pigs i2crd 0 11 -a
11 Sun Oct 30*
. .
"""
if i2c_address:
control = (i2c_address<<16)|0x305
else:
control = 0
return self.bsc_xfer(control, data)
def spi_open(self, spi_channel, baud, spi_flags=0):
"""
Returns a handle for the SPI device on channel. Data will be
@ -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

View File

@ -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

View File

@ -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*/

View File

@ -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

View File

@ -25,7 +25,7 @@ OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>
*/
/* PIGPIOD_IF2_VERSION 8 */
/* PIGPIOD_IF2_VERSION 9 */
#include <stdio.h>
#include <stdlib.h>
@ -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;
@ -309,6 +327,8 @@ static void dispatch_notification(int pi, gpioReport_t *r)
}
}
else
{
if ((r->flags) & PI_NTFY_FLAGS_WDOG)
{
g = (r->flags) & 31;
@ -324,6 +344,23 @@ static void dispatch_notification(int pi, gpioReport_t *r)
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;
}
}
}
}
static void *pthNotifyThread(void *x)
@ -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);}

View File

@ -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<<n).
e.g. to select bits 5, 9, 23 you could use (1<<5) | (1<<9) | (1<<23).
bsc_xfer_t::
. .
typedef struct
{
uint32_t control; // Write
int rxCnt; // Read only
char rxBuf[BSC_FIFO_SIZE]; // Read only
int txCnt; // Write
char txBuf[BSC_FIFO_SIZE]; // Write
} bsc_xfer_t;
. .
*bscxfer::
A pointer to a [*bsc_xfer_t*] object used to control a BSC transfer.
*buf::
A buffer to hold data being sent or being received.
@ -3331,8 +3628,15 @@ bVal::0-255 (Hex 0x0-0xFF, Octal 0-0377)
An 8-bit byte value.
callback_id::
A >=0, as returned by a call to [*callback*] or [*callback_ex*]. This is
passed to [*callback_cancel*] to cancel the callback.
A value >=0, as returned by a call to a callback function, one of
[*callback*]
[*callback_ex*]
[*event_callback*]
[*event_callback_ex*]
The id is passed to [*callback_cancel*] or [*event_callback_cancel*]
to cancel the callback.
CBFunc_t::
. .
@ -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.

283
pigs.1
View File

@ -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.

40
pigs.c
View File

@ -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<r; i++)
{
ch = response_buf[i];
if (printFlags & PRINT_HEX) printf(" %hhx", ch);
else if (printFlags & PRINT_ASCII)
{
if (isprint(ch) || (ch == '\n') || (ch == '\r'))
printf("%c", ch);
else printf("\\x%02hhx", ch);
}
else printf(" %hhu", response_buf[i]);
}
}
printf("\n");
break;
}
}
@ -224,6 +259,7 @@ void get_extensions(int sock, int command, int res)
switch (command)
{
case PI_CMD_BI2CZ:
case PI_CMD_BSCX:
case PI_CMD_BSPIX:
case PI_CMD_CF2:
case PI_CMD_FL:

View File

@ -3,7 +3,7 @@
from distutils.core import setup
setup(name='pigpio',
version='1.33',
version='1.34',
author='joan',
author_email='joan@abyz.co.uk',
maintainer='joan',

2
x_pigs
View File

@ -50,7 +50,7 @@ s=$(pigs bs2 0)
if [[ $s = "" ]]; then echo "BS2 ok"; else echo "BS2 fail ($s)"; fi
s=$(pigs h)
if [[ ${#s} = 5273 ]]; then echo "HELP ok"; else echo "HELP fail (${#s})"; fi
if [[ ${#s} = 5384 ]]; then echo "HELP ok"; else echo "HELP fail (${#s})"; fi
s=$(pigs hwver)
if [[ $s -ne 0 ]]; then echo "HWVER ok"; else echo "HWVER fail ($s)"; fi