mirror of https://github.com/joan2937/pigpio
V57
This commit is contained in:
parent
abe5f12942
commit
c31a2fa6b2
23
command.c
23
command.c
|
@ -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;
|
||||
|
|
|
@ -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
578
pigpio.3
|
@ -1484,23 +1484,30 @@ by one for each report.
|
|||
.br
|
||||
|
||||
.br
|
||||
flags: two flags are defined, PI_NTFY_FLAGS_WDOG and PI_NTFY_FLAGS_ALIVE.
|
||||
flags: three flags are defined, PI_NTFY_FLAGS_WDOG,
|
||||
PI_NTFY_FLAGS_ALIVE, and PI_NTFY_FLAGS_EVENT.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
PI_NTFY_FLAGS_WDOG, if bit 5 is set then bits 0-4 of the flags
|
||||
If bit 5 is set (PI_NTFY_FLAGS_WDOG) then bits 0-4 of the flags
|
||||
indicate a GPIO which has had a watchdog timeout.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
PI_NTFY_FLAGS_ALIVE, if bit 6 is set this indicates a keep alive
|
||||
If bit 6 is set (PI_NTFY_FLAGS_ALIVE) this indicates a keep alive
|
||||
signal on the pipe/socket and is sent once a minute in the absence
|
||||
of other notification activity.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
If bit 7 is set (PI_NTFY_FLAGS_EVENT) then bits 0-4 of the flags
|
||||
indicate an event which has been triggered.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
tick: the number of microseconds since system boot. It wraps around
|
||||
after 1h12m.
|
||||
|
@ -3453,6 +3460,249 @@ End
|
|||
|
||||
.EE
|
||||
|
||||
.IP "\fBint bscXfer(bsc_xfer_t *bsc_xfer)\fP"
|
||||
.IP "" 4
|
||||
This function provides a low-level interface to the
|
||||
SPI/I2C Slave peripheral. This peripheral allows the
|
||||
Pi to act as a slave device on an I2C or SPI bus.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
I can't get SPI to work properly. I tried with a
|
||||
control word of 0x303 and swapped MISO and MOSI.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
The function sets the BSC mode, writes any data in
|
||||
the transmit buffer to the BSC transmit FIFO, and
|
||||
copies any data in the BSC receive FIFO to the
|
||||
receive buffer.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
|
||||
.EX
|
||||
bsc_xfer:= a structure defining the transfer
|
||||
.br
|
||||
|
||||
.br
|
||||
typedef struct
|
||||
.br
|
||||
{
|
||||
.br
|
||||
uint32_t control; // Write
|
||||
.br
|
||||
int rxCnt; // Read only
|
||||
.br
|
||||
char rxBuf[BSC_FIFO_SIZE]; // Read only
|
||||
.br
|
||||
int txCnt; // Write
|
||||
.br
|
||||
char txBuf[BSC_FIFO_SIZE]; // Write
|
||||
.br
|
||||
} bsc_xfer_t;
|
||||
.br
|
||||
|
||||
.EE
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
To start a transfer set control (see below) and copy the bytes to
|
||||
be sent (if any) to txBuf and set the byte count in txCnt.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
Upon return rxCnt will be set to the number of received bytes placed
|
||||
in rxBuf.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
Note that the control word sets the BSC mode. The BSC will stay in
|
||||
that mode until a different control word is sent.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
The BSC peripheral uses GPIO 18 (SDA) and 19 (SCL) in I2C mode
|
||||
and GPIO 18 (MOSI), 19 (SCLK), 20 (MISO), and 21 (CE) in SPI mode. You
|
||||
need to swap MISO/MOSI between master and slave.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
When a zero control word is received GPIO 18-21 will be reset
|
||||
to INPUT mode.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
The returned function value is the status of the transfer (see below).
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
If there was an error the status will be less than zero
|
||||
(and will contain the error code).
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
The most significant word of the returned status contains the number
|
||||
of bytes actually copied from txBuf to the BSC transmit FIFO (may be
|
||||
less than requested if the FIFO already contained untransmitted data).
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
control consists of the following bits.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
|
||||
.EX
|
||||
22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
.br
|
||||
a a a a a a a - - IT HC TF IR RE TE BK EC ES PL PH I2 SP EN
|
||||
.br
|
||||
|
||||
.EE
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
Bits 0-13 are copied unchanged to the BSC CR register. See
|
||||
pages 163-165 of the Broadcom peripherals document for full
|
||||
details.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
aaaaaaa defines the I2C slave address (only relevant in I2C mode)
|
||||
.br
|
||||
IT invert transmit status flags
|
||||
.br
|
||||
HC enable host control
|
||||
.br
|
||||
TF enable test FIFO
|
||||
.br
|
||||
IR invert receive status flags
|
||||
.br
|
||||
RE enable receive
|
||||
.br
|
||||
TE enable transmit
|
||||
.br
|
||||
BK abort operation and clear FIFOs
|
||||
.br
|
||||
EC send control register as first I2C byte
|
||||
.br
|
||||
ES send status register as first I2C byte
|
||||
.br
|
||||
PL set SPI polarity high
|
||||
.br
|
||||
PH set SPI phase high
|
||||
.br
|
||||
I2 enable I2C mode
|
||||
.br
|
||||
SP enable SPI mode
|
||||
.br
|
||||
EN enable BSC peripheral
|
||||
.br
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
The returned status has the following format
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
|
||||
.EX
|
||||
20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
.br
|
||||
S S S S S R R R R R T T T T T RB TE RF TF RE TB
|
||||
.br
|
||||
|
||||
.EE
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
Bits 0-15 are copied unchanged from the BSC FR register. See
|
||||
pages 165-166 of the Broadcom peripherals document for full
|
||||
details.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
SSSSS number of bytes successfully copied to transmit FIFO
|
||||
.br
|
||||
RRRRR number of bytes in receieve FIFO
|
||||
.br
|
||||
TTTTT number of bytes in transmit FIFO
|
||||
.br
|
||||
RB receive busy
|
||||
.br
|
||||
TE transmit FIFO empty
|
||||
.br
|
||||
RF receive FIFO full
|
||||
.br
|
||||
TF transmit FIFO full
|
||||
.br
|
||||
RE receive FIFO empty
|
||||
.br
|
||||
TB transmit busy
|
||||
.br
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
The following example shows how to configure the BSC peripheral as
|
||||
an I2C slave with address 0x13 and send four bytes.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
\fBExample\fP
|
||||
.br
|
||||
|
||||
.EX
|
||||
bsc_xfer_t xfer;
|
||||
.br
|
||||
|
||||
.br
|
||||
xfer.control = (0x13<<16) | 0x305;
|
||||
.br
|
||||
|
||||
.br
|
||||
memcpy(xfer.txBuf, "ABCD", 4);
|
||||
.br
|
||||
xfer.txCnt = 4;
|
||||
.br
|
||||
|
||||
.br
|
||||
status = bscXfer(&xfer);
|
||||
.br
|
||||
|
||||
.br
|
||||
if (status >= 0)
|
||||
.br
|
||||
{
|
||||
.br
|
||||
// process transfer
|
||||
.br
|
||||
}
|
||||
.br
|
||||
|
||||
.EE
|
||||
|
||||
.IP "\fBint bbSPIOpen(unsigned CS, unsigned MISO, unsigned MOSI, unsigned SCLK, unsigned baud, unsigned spiFlags)\fP"
|
||||
.IP "" 4
|
||||
This function selects a set of GPIO for bit banging SPI with
|
||||
|
@ -4097,6 +4347,11 @@ handle: >=0, as returned by a call to \fBserOpen\fP
|
|||
Returns the read byte (>=0) if OK, otherwise PI_BAD_HANDLE,
|
||||
PI_SER_READ_NO_DATA, or PI_SER_READ_FAILED.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
If no data is ready PI_SER_READ_NO_DATA is returned.
|
||||
|
||||
.IP "\fBint serWrite(unsigned handle, char *buf, unsigned count)\fP"
|
||||
.IP "" 4
|
||||
This function writes count bytes from buf to the the serial port
|
||||
|
@ -4144,9 +4399,14 @@ handle: >=0, as returned by a call to \fBserOpen\fP
|
|||
.br
|
||||
|
||||
.br
|
||||
Returns the number of bytes read (>0) if OK, otherwise PI_BAD_HANDLE,
|
||||
Returns the number of bytes read (>0=) if OK, otherwise PI_BAD_HANDLE,
|
||||
PI_BAD_PARAM, or PI_SER_READ_NO_DATA.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
If no data is ready zero is returned.
|
||||
|
||||
.IP "\fBint serDataAvailable(unsigned handle)\fP"
|
||||
.IP "" 4
|
||||
This function returns the number of bytes available
|
||||
|
@ -5519,6 +5779,191 @@ gpioSetPad(0, 16); // set pad 0 strength to 16 mA
|
|||
|
||||
.EE
|
||||
|
||||
.IP "\fBint eventMonitor(unsigned handle, uint32_t bits)\fP"
|
||||
.IP "" 4
|
||||
This function selects the events to be reported on a previously
|
||||
opened handle.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
|
||||
.EX
|
||||
handle: >=0, as returned by \fBgpioNotifyOpen\fP
|
||||
.br
|
||||
bits: a bit mask indicating the events of interest
|
||||
.br
|
||||
|
||||
.EE
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
Returns 0 if OK, otherwise PI_BAD_HANDLE.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
A report is sent each time an event is triggered providing the
|
||||
corresponding bit in bits is set.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
See \fBgpioNotifyBegin\fP for the notification format.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
\fBExample\fP
|
||||
.br
|
||||
|
||||
.EX
|
||||
// Start reporting events 3, 6, and 7.
|
||||
.br
|
||||
|
||||
.br
|
||||
// bit 76543210
|
||||
.br
|
||||
// (0xC8 = 0b11001000)
|
||||
.br
|
||||
|
||||
.br
|
||||
eventMonitor(h, 0xC8);
|
||||
.br
|
||||
|
||||
.EE
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
|
||||
.IP "\fBint eventSetFunc(unsigned event, eventFunc_t f)\fP"
|
||||
.IP "" 4
|
||||
Registers a function to be called (a callback) when the specified
|
||||
event occurs.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
|
||||
.EX
|
||||
event: 0-31
|
||||
.br
|
||||
f: the callback function
|
||||
.br
|
||||
|
||||
.EE
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
Returns 0 if OK, otherwise PI_BAD_EVENT_ID.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
One function may be registered per event.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
The function is passed the event, and the tick.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
The callback may be cancelled by passing NULL as the function.
|
||||
|
||||
.IP "\fBint eventSetFuncEx(unsigned event, eventFuncEx_t f, void *userdata)\fP"
|
||||
.IP "" 4
|
||||
Registers a function to be called (a callback) when the specified
|
||||
event occurs.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
|
||||
.EX
|
||||
event: 0-31
|
||||
.br
|
||||
f: the callback function
|
||||
.br
|
||||
userdata: pointer to arbitrary user data
|
||||
.br
|
||||
|
||||
.EE
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
Returns 0 if OK, otherwise PI_BAD_EVENT_ID.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
One function may be registered per event.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
The function is passed the event, the tick, and the ueserdata pointer.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
The callback may be cancelled by passing NULL as the function.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
Only one of \fBeventSetFunc\fP or \fBeventSetFuncEx\fP can be
|
||||
registered per event.
|
||||
|
||||
.IP "\fBint eventTrigger(unsigned event)\fP"
|
||||
.IP "" 4
|
||||
This function signals the occurrence of an event.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
|
||||
.EX
|
||||
event: 0-31, the event
|
||||
.br
|
||||
|
||||
.EE
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
Returns 0 if OK, otherwise PI_BAD_EVENT_ID.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
An event is a signal used to inform one or more consumers
|
||||
to start an action. Each consumer which has registered an interest
|
||||
in the event (e.g. by calling \fBeventSetFunc\fP) will be informed by
|
||||
a callback.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
One event, PI_EVENT_BSC (31) is predefined. This event is
|
||||
auto generated on BSC slave activity.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
The meaning of other events is arbitrary.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
Note that other than its id and its tick there is no data associated
|
||||
with an event.
|
||||
|
||||
.IP "\fBint shell(char *scriptName, char *scriptString)\fP"
|
||||
.IP "" 4
|
||||
This function uses the system call to execute a shell script
|
||||
|
@ -7045,6 +7490,43 @@ e.g. to select bits 5, 9, 23 you could use (1<<5) | (1<<9) | (1<<23).
|
|||
|
||||
.br
|
||||
|
||||
.IP "\fB*bsc_xfer\fP" 0
|
||||
A pointer to a \fBbsc_xfer_t\fP object used to control a BSC transfer.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
|
||||
.IP "\fBbsc_xfer_t\fP" 0
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
|
||||
.EX
|
||||
typedef struct
|
||||
.br
|
||||
{
|
||||
.br
|
||||
uint32_t control; // Write
|
||||
.br
|
||||
int rxCnt; // Read only
|
||||
.br
|
||||
char rxBuf[BSC_FIFO_SIZE]; // Read only
|
||||
.br
|
||||
int txCnt; // Write
|
||||
.br
|
||||
char txBuf[BSC_FIFO_SIZE]; // Write
|
||||
.br
|
||||
} bsc_xfer_t;
|
||||
.br
|
||||
|
||||
.EE
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
|
||||
.IP "\fB*buf\fP" 0
|
||||
|
||||
.br
|
||||
|
@ -7282,7 +7764,7 @@ The number may vary between 0 and range (default 255) where
|
|||
.br
|
||||
|
||||
.IP "\fBedge\fP: 0-2" 0
|
||||
The type of GPIO edge to generate an intrrupt. See \fBgpioSetISRFunc\fP,
|
||||
The type of GPIO edge to generate an interrupt. See \fBgpioSetISRFunc\fP
|
||||
and \fBgpioSetISRFuncEx\fP.
|
||||
|
||||
.br
|
||||
|
@ -7303,6 +7785,40 @@ EITHER_EDGE 2
|
|||
|
||||
.br
|
||||
|
||||
.IP "\fBevent\fP: 0-31" 0
|
||||
An event is a signal used to inform one or more consumers
|
||||
to start an action.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
|
||||
.IP "\fBeventFunc_t\fP" 0
|
||||
|
||||
.EX
|
||||
typedef void (*eventFunc_t) (int event, uint32_t tick);
|
||||
.br
|
||||
|
||||
.EE
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
|
||||
.IP "\fBeventFuncEx_t\fP" 0
|
||||
|
||||
.EX
|
||||
typedef void (*eventFuncEx_t)
|
||||
.br
|
||||
(int event, uint32_t tick, void *userdata);
|
||||
.br
|
||||
|
||||
.EE
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
|
||||
.IP "\fBf\fP" 0
|
||||
|
||||
.br
|
||||
|
@ -7425,9 +7941,9 @@ typedef void (*gpioAlertFunc_t) (int gpio, int level, uint32_t tick);
|
|||
.IP "\fBgpioAlertFuncEx_t\fP" 0
|
||||
|
||||
.EX
|
||||
typedef void (*gpioAlertFuncEx_t)
|
||||
typedef void (*eventFuncEx_t)
|
||||
.br
|
||||
(int gpio, int level, uint32_t tick, void *userdata);
|
||||
(int event, int level, uint32_t tick, void *userdata);
|
||||
.br
|
||||
|
||||
.EE
|
||||
|
@ -7649,8 +8165,20 @@ One of
|
|||
.br
|
||||
|
||||
.br
|
||||
A number referencing an object opened by one of \fBfileOpen\fP,
|
||||
\fBgpioNotifyOpen\fP, \fBi2cOpen\fP, \fBserOpen\fP, \fBspiOpen\fP.
|
||||
A number referencing an object opened by one of
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
\fBfileOpen\fP
|
||||
.br
|
||||
\fBgpioNotifyOpen\fP
|
||||
.br
|
||||
\fBi2cOpen\fP
|
||||
.br
|
||||
\fBserOpen\fP
|
||||
.br
|
||||
\fBspiOpen\fP
|
||||
|
||||
.br
|
||||
|
||||
|
@ -8137,6 +8665,10 @@ A thread identifier.
|
|||
The setting of the pull up/down resistor for a GPIO, which may be off,
|
||||
pull-up, or pull-down.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
|
||||
.EX
|
||||
PI_PUD_OFF 0
|
||||
.br
|
||||
|
@ -8820,16 +9352,24 @@ In the calling function:
|
|||
.br
|
||||
|
||||
.br
|
||||
|
||||
.EX
|
||||
user_type *userdata;
|
||||
.br
|
||||
.br
|
||||
.br
|
||||
user_type my_userdata;
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
userdata = malloc(sizeof(user_type));
|
||||
.br
|
||||
.br
|
||||
.br
|
||||
*userdata = my_userdata;
|
||||
.br
|
||||
|
||||
.EE
|
||||
|
||||
.br
|
||||
|
||||
|
@ -8839,12 +9379,16 @@ In the receiving function:
|
|||
.br
|
||||
|
||||
.br
|
||||
user_type my_userdata = *(user_type*)userdata;
|
||||
|
||||
.EX
|
||||
user_type my_userdata = *(user_type*)userdata;
|
||||
.br
|
||||
|
||||
.br
|
||||
free(userdata);
|
||||
.br
|
||||
|
||||
.EE
|
||||
|
||||
.br
|
||||
|
||||
|
@ -9182,6 +9726,16 @@ A 16-bit word value.
|
|||
#define PI_CMD_BSPIX 113
|
||||
.br
|
||||
|
||||
.br
|
||||
#define PI_CMD_BSCX 114
|
||||
.br
|
||||
|
||||
.br
|
||||
#define PI_CMD_EVM 115
|
||||
.br
|
||||
#define PI_CMD_EVT 116
|
||||
.br
|
||||
|
||||
.br
|
||||
|
||||
.EE
|
||||
|
@ -9480,6 +10034,8 @@ A 16-bit word value.
|
|||
.br
|
||||
#define PI_NOT_SPI_GPIO -142 // no bit bang SPI in progress on GPIO
|
||||
.br
|
||||
#define PI_BAD_EVENT_ID -143 // bad event id
|
||||
.br
|
||||
|
||||
.br
|
||||
#define PI_PIGIF_ERR_0 -2000
|
||||
|
|
441
pigpio.c
441
pigpio.c
|
@ -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
379
pigpio.h
|
@ -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
576
pigpio.py
|
@ -56,7 +56,7 @@ If you wish to handle the returned status yourself you should set
|
|||
pigpio.exceptions to False.
|
||||
|
||||
You may prefer to check the returned status in only a few parts
|
||||
of your code. In that case do the following.
|
||||
of your code. In that case do the following:
|
||||
|
||||
...
|
||||
pigpio.exceptions = False
|
||||
|
@ -242,6 +242,11 @@ bb_spi_open Opens GPIO for bit banging SPI
|
|||
bb_spi_close Closes GPIO for bit banging SPI
|
||||
bb_spi_xfer Transfers bytes with bit banging SPI
|
||||
|
||||
I2C/SPI_Slave
|
||||
|
||||
bsc_xfer I2C/SPI as slave transfer
|
||||
bsc_i2c I2C as slave transfer
|
||||
|
||||
Serial
|
||||
|
||||
serial_open Opens a serial device
|
||||
|
@ -264,6 +269,12 @@ file_write Writes bytes to a file
|
|||
file_seek Seeks to a position within a file
|
||||
file_list List files which match a pattern
|
||||
|
||||
Events
|
||||
|
||||
event_callback Sets a callback for an event
|
||||
event_trigger Triggers an event
|
||||
wait_for_event Wait for an event
|
||||
|
||||
Custom
|
||||
|
||||
custom_1 User custom function 1
|
||||
|
@ -288,7 +299,7 @@ import threading
|
|||
import os
|
||||
import atexit
|
||||
|
||||
VERSION = "1.33"
|
||||
VERSION = "1.34"
|
||||
|
||||
exceptions = True
|
||||
|
||||
|
@ -337,6 +348,7 @@ PI_SCRIPT_FAILED =4
|
|||
|
||||
# notification flags
|
||||
|
||||
NTFY_FLAGS_EVENT = (1 << 7)
|
||||
NTFY_FLAGS_ALIVE = (1 << 6)
|
||||
NTFY_FLAGS_WDOG = (1 << 5)
|
||||
NTFY_FLAGS_GPIO = 31
|
||||
|
@ -376,6 +388,8 @@ SPI_CS_HIGH_ACTIVE = 1 << 2
|
|||
SPI_TX_LSBFIRST = 1 << 14
|
||||
SPI_RX_LSBFIRST = 1 << 15
|
||||
|
||||
EVENT_BSC = 31
|
||||
|
||||
# pigpio command numbers
|
||||
|
||||
_PI_CMD_MODES= 0
|
||||
|
@ -518,6 +532,11 @@ _PI_CMD_BSPIC=111
|
|||
_PI_CMD_BSPIO=112
|
||||
_PI_CMD_BSPIX=113
|
||||
|
||||
_PI_CMD_BSCX =114
|
||||
|
||||
_PI_CMD_EVM =115
|
||||
_PI_CMD_EVT =116
|
||||
|
||||
# pigpio error numbers
|
||||
|
||||
_PI_INIT_FAILED =-1
|
||||
|
@ -663,6 +682,7 @@ PI_BAD_SHELL_STATUS =-139
|
|||
PI_BAD_SCRIPT_NAME =-140
|
||||
PI_BAD_SPI_BAUD =-141
|
||||
PI_NOT_SPI_GPIO =-142
|
||||
PI_BAD_EVENT_ID =-143
|
||||
|
||||
# pigpio error text
|
||||
|
||||
|
@ -807,13 +827,14 @@ _errors=[
|
|||
[PI_BAD_SCRIPT_NAME , "bad script name"],
|
||||
[PI_BAD_SPI_BAUD , "bad SPI baud rate, not 50-500k"],
|
||||
[PI_NOT_SPI_GPIO , "no bit bang SPI in progress on GPIO"],
|
||||
[PI_BAD_EVENT_ID , "bad event id"],
|
||||
]
|
||||
|
||||
except_a = "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n{}"
|
||||
_except_a = "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n{}"
|
||||
|
||||
except_z = "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"
|
||||
_except_z = "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"
|
||||
|
||||
except1 = """
|
||||
_except_1 = """
|
||||
Did you start the pigpio daemon? E.g. sudo pigpiod
|
||||
|
||||
Did you specify the correct Pi host/port in the environment
|
||||
|
@ -823,7 +844,7 @@ E.g. export PIGPIO_ADDR=soft, export PIGPIO_PORT=8888
|
|||
Did you specify the correct Pi host/port in the
|
||||
pigpio.pi() function? E.g. pigpio.pi('soft', 8888)"""
|
||||
|
||||
except2 = """
|
||||
_except_2 = """
|
||||
Do you have permission to access the pigpio daemon?
|
||||
Perhaps it was started with sudo pigpiod -nlocalhost"""
|
||||
|
||||
|
@ -981,6 +1002,22 @@ def _pigpio_command_ext(sl, cmd, p1, p2, p3, extents, rl=True):
|
|||
if rl: sl.l.release()
|
||||
return res
|
||||
|
||||
class _event_ADT:
|
||||
"""
|
||||
An ADT class to hold event callback information.
|
||||
"""
|
||||
|
||||
def __init__(self, event, func):
|
||||
"""
|
||||
Initialises an event callback ADT.
|
||||
|
||||
event:= the event id.
|
||||
func:= a user function taking one argument, the event id.
|
||||
"""
|
||||
self.event = event
|
||||
self.func = func
|
||||
self.bit = 1<<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
|
||||
|
|
10
pigpiod_if.3
10
pigpiod_if.3
|
@ -3612,6 +3612,11 @@ handle: >=0, as returned by a call to \fBserial_open\fP.
|
|||
Returns the read byte (>=0) if OK, otherwise PI_BAD_HANDLE,
|
||||
PI_SER_READ_NO_DATA, or PI_SER_READ_FAILED.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
If no data is ready PI_SER_READ_NO_DATA is returned.
|
||||
|
||||
.IP "\fBint serial_write(unsigned handle, char *buf, unsigned count)\fP"
|
||||
.IP "" 4
|
||||
This function writes count bytes from buf to the the serial port
|
||||
|
@ -3662,6 +3667,11 @@ handle: >=0, as returned by a call to \fBserial_open\fP.
|
|||
Returns the number of bytes read (>0) if OK, otherwise PI_BAD_HANDLE,
|
||||
PI_BAD_PARAM, PI_SER_READ_NO_DATA, or PI_SER_WRITE_FAILED.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
If no data is ready zero is returned.
|
||||
|
||||
.IP "\fBint serial_data_available(unsigned handle)\fP"
|
||||
.IP "" 4
|
||||
Returns the number of bytes available to be read from the
|
||||
|
|
|
@ -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*/
|
||||
|
|
673
pigpiod_if2.3
673
pigpiod_if2.3
|
@ -1008,23 +1008,30 @@ by one for each report.
|
|||
.br
|
||||
|
||||
.br
|
||||
flags: two flags are defined, PI_NTFY_FLAGS_WDOG and PI_NTFY_FLAGS_ALIVE.
|
||||
flags: three flags are defined, PI_NTFY_FLAGS_WDOG,
|
||||
PI_NTFY_FLAGS_ALIVE, and PI_NTFY_FLAGS_EVENT.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
PI_NTFY_FLAGS_WDOG, if bit 5 is set then bits 0-4 of the flags
|
||||
If bit 5 is set (PI_NTFY_FLAGS_WDOG) then bits 0-4 of the flags
|
||||
indicate a GPIO which has had a watchdog timeout.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
PI_NTFY_FLAGS_ALIVE, if bit 6 is set this indicates a keep alive
|
||||
If bit 6 is set (PI_NTFY_FLAGS_ALIVE) this indicates a keep alive
|
||||
signal on the pipe/socket and is sent once a minute in the absence
|
||||
of other notification activity.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
If bit 7 is set (PI_NTFY_FLAGS_EVENT) then bits 0-4 of the flags
|
||||
indicate an event which has been triggered.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
tick: the number of microseconds since system boot. It wraps around
|
||||
after 1h12m.
|
||||
|
@ -4423,6 +4430,11 @@ handle: >=0, as returned by a call to \fBserial_open\fP.
|
|||
Returns the read byte (>=0) if OK, otherwise PI_BAD_HANDLE,
|
||||
PI_SER_READ_NO_DATA, or PI_SER_READ_FAILED.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
If no data is ready PI_SER_READ_NO_DATA is returned.
|
||||
|
||||
.IP "\fBint serial_write(int pi, unsigned handle, char *buf, unsigned count)\fP"
|
||||
.IP "" 4
|
||||
This function writes count bytes from buf to the the serial port
|
||||
|
@ -4474,9 +4486,14 @@ handle: >=0, as returned by a call to \fBserial_open\fP.
|
|||
.br
|
||||
|
||||
.br
|
||||
Returns the number of bytes read (>0) if OK, otherwise PI_BAD_HANDLE,
|
||||
Returns the number of bytes read (>=0) if OK, otherwise PI_BAD_HANDLE,
|
||||
PI_BAD_PARAM, PI_SER_READ_NO_DATA, or PI_SER_WRITE_FAILED.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
If no data is ready zero is returned.
|
||||
|
||||
.IP "\fBint serial_data_available(int pi, unsigned handle)\fP"
|
||||
.IP "" 4
|
||||
Returns the number of bytes available to be read from the
|
||||
|
@ -5331,8 +5348,8 @@ pigif_duplicate_callback, or pigif_bad_callback.
|
|||
.br
|
||||
|
||||
.br
|
||||
The callback is called with the GPIO, edge, tick, and user, whenever
|
||||
the GPIO has the identified edge.
|
||||
The callback is called with the GPIO, edge, tick, and the userdata
|
||||
pointer, whenever the GPIO has the identified edge.
|
||||
|
||||
.IP "\fBint callback_cancel(unsigned callback_id)\fP"
|
||||
.IP "" 4
|
||||
|
@ -5355,7 +5372,7 @@ The function returns 0 if OK, otherwise pigif_callback_not_found.
|
|||
|
||||
.IP "\fBint wait_for_edge(int pi, unsigned user_gpio, unsigned edge, double timeout)\fP"
|
||||
.IP "" 4
|
||||
This function waits for edge on the GPIO for up to timeout
|
||||
This function waits for an edge on the GPIO for up to timeout
|
||||
seconds.
|
||||
|
||||
.br
|
||||
|
@ -5391,6 +5408,479 @@ a \fBcallback\fP function.
|
|||
|
||||
.br
|
||||
The function returns 1 if the edge occurred, otherwise 0.
|
||||
|
||||
.IP "\fBint bsc_xfer(int pi, bsc_xfer_t *bscxfer)\fP"
|
||||
.IP "" 4
|
||||
This function provides a low-level interface to the
|
||||
SPI/I2C Slave peripheral. This peripheral allows the
|
||||
Pi to act as a slave device on an I2C or SPI bus.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
I can't get SPI to work properly. I tried with a
|
||||
control word of 0x303 and swapped MISO and MOSI.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
The function sets the BSC mode, writes any data in
|
||||
the transmit buffer to the BSC transmit FIFO, and
|
||||
copies any data in the BSC receive FIFO to the
|
||||
receive buffer.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
|
||||
.EX
|
||||
pi: >=0 (as returned by \fBpigpio_start\fP).
|
||||
.br
|
||||
bscxfer: a structure defining the transfer.
|
||||
.br
|
||||
|
||||
.br
|
||||
typedef struct
|
||||
.br
|
||||
{
|
||||
.br
|
||||
uint32_t control; // Write
|
||||
.br
|
||||
int rxCnt; // Read only
|
||||
.br
|
||||
char rxBuf[BSC_FIFO_SIZE]; // Read only
|
||||
.br
|
||||
int txCnt; // Write
|
||||
.br
|
||||
char txBuf[BSC_FIFO_SIZE]; // Write
|
||||
.br
|
||||
} bsc_xfer_t;
|
||||
.br
|
||||
|
||||
.EE
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
To start a transfer set control (see below) and copy the bytes to
|
||||
be sent (if any) to txBuf and set the byte count in txCnt.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
Upon return rxCnt will be set to the number of received bytes placed
|
||||
in rxBuf.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
The returned function value is the status of the transfer (see below).
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
If there was an error the status will be less than zero
|
||||
(and will contain the error code).
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
The most significant word of the returned status contains the number
|
||||
of bytes actually copied from txBuf to the BSC transmit FIFO (may be
|
||||
less than requested if the FIFO already contained untransmitted data).
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
Note that the control word sets the BSC mode. The BSC will stay in
|
||||
that mode until a different control word is sent.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
The BSC peripheral uses GPIO 18 (SDA) and 19 (SCL) in I2C mode
|
||||
and GPIO 18 (MOSI), 19 (SCLK), 20 (MISO), and 21 (CE) in SPI mode. You
|
||||
need to swap MISO/MOSI between master and slave.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
When a zero control word is received GPIO 18-21 will be reset
|
||||
to INPUT mode.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
control consists of the following bits.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
|
||||
.EX
|
||||
22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
.br
|
||||
a a a a a a a - - IT HC TF IR RE TE BK EC ES PL PH I2 SP EN
|
||||
.br
|
||||
|
||||
.EE
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
Bits 0-13 are copied unchanged to the BSC CR register. See
|
||||
pages 163-165 of the Broadcom peripherals document for full
|
||||
details.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
aaaaaaa defines the I2C slave address (only relevant in I2C mode)
|
||||
.br
|
||||
IT invert transmit status flags
|
||||
.br
|
||||
HC enable host control
|
||||
.br
|
||||
TF enable test FIFO
|
||||
.br
|
||||
IR invert receive status flags
|
||||
.br
|
||||
RE enable receive
|
||||
.br
|
||||
TE enable transmit
|
||||
.br
|
||||
BK abort operation and clear FIFOs
|
||||
.br
|
||||
EC send control register as first I2C byte
|
||||
.br
|
||||
ES send status register as first I2C byte
|
||||
.br
|
||||
PL set SPI polarity high
|
||||
.br
|
||||
PH set SPI phase high
|
||||
.br
|
||||
I2 enable I2C mode
|
||||
.br
|
||||
SP enable SPI mode
|
||||
.br
|
||||
EN enable BSC peripheral
|
||||
.br
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
The returned status has the following format
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
|
||||
.EX
|
||||
20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
.br
|
||||
S S S S S R R R R R T T T T T RB TE RF TF RE TB
|
||||
.br
|
||||
|
||||
.EE
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
Bits 0-15 are copied unchanged from the BSC FR register. See
|
||||
pages 165-166 of the Broadcom peripherals document for full
|
||||
details.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
SSSSS number of bytes successfully copied to transmit FIFO
|
||||
.br
|
||||
RRRRR number of bytes in receieve FIFO
|
||||
.br
|
||||
TTTTT number of bytes in transmit FIFO
|
||||
.br
|
||||
RB receive busy
|
||||
.br
|
||||
TE transmit FIFO empty
|
||||
.br
|
||||
RF receive FIFO full
|
||||
.br
|
||||
TF transmit FIFO full
|
||||
.br
|
||||
RE receive FIFO empty
|
||||
.br
|
||||
TB transmit busy
|
||||
.br
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
The following example shows how to configure the BSC peripheral as
|
||||
an I2C slave with address 0x13 and send four bytes.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
\fBExample\fP
|
||||
.br
|
||||
|
||||
.EX
|
||||
bsc_xfer_t xfer;
|
||||
.br
|
||||
|
||||
.br
|
||||
xfer.control = (0x13<<16) | 0x305;
|
||||
.br
|
||||
|
||||
.br
|
||||
memcpy(xfer.txBuf, "ABCD", 4);
|
||||
.br
|
||||
xfer.txCnt = 4;
|
||||
.br
|
||||
|
||||
.br
|
||||
status = bsc_xfer(pi, &xfer);
|
||||
.br
|
||||
|
||||
.br
|
||||
if (status >= 0)
|
||||
.br
|
||||
{
|
||||
.br
|
||||
// process transfer
|
||||
.br
|
||||
}
|
||||
.br
|
||||
|
||||
.EE
|
||||
|
||||
.IP "\fBint bsc_i2c(int pi, int i2c_addr, bsc_xfer_t *bscxfer)\fP"
|
||||
.IP "" 4
|
||||
This function allows the Pi to act as a slave I2C device.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
The data bytes (if any) are written to the BSC transmit
|
||||
FIFO and the bytes in the BSC receive FIFO are returned.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
|
||||
.EX
|
||||
pi: >=0 (as returned by \fBpigpio_start\fP).
|
||||
.br
|
||||
i2c_addr: 0-0x7F.
|
||||
.br
|
||||
bscxfer: a structure defining the transfer.
|
||||
.br
|
||||
|
||||
.br
|
||||
typedef struct
|
||||
.br
|
||||
{
|
||||
.br
|
||||
uint32_t control; // N/A
|
||||
.br
|
||||
int rxCnt; // Read only
|
||||
.br
|
||||
char rxBuf[BSC_FIFO_SIZE]; // Read only
|
||||
.br
|
||||
int txCnt; // Write
|
||||
.br
|
||||
char txBuf[BSC_FIFO_SIZE]; // Write
|
||||
.br
|
||||
} bsc_xfer_t;
|
||||
.br
|
||||
|
||||
.EE
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
txCnt is set to the number of bytes to be transmitted, possibly
|
||||
zero. The data itself should be copied to txBuf.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
Any received data will be written to rxBuf with rxCnt set.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
See \fBbsc_xfer\fP for details of the returned status value.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
If there was an error the status will be less than zero
|
||||
(and will contain the error code).
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
Note that an i2c_address of 0 may be used to close
|
||||
the BSC device and reassign the used GPIO (18/19)
|
||||
as inputs.
|
||||
|
||||
.IP "\fBint event_callback(int pi, unsigned event, evtCBFunc_t f)\fP"
|
||||
.IP "" 4
|
||||
This function initialises an event callback.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
|
||||
.EX
|
||||
pi: >=0 (as returned by \fBpigpio_start\fP).
|
||||
.br
|
||||
event: 0-31.
|
||||
.br
|
||||
f: the callback function.
|
||||
.br
|
||||
|
||||
.EE
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
The function returns a callback id if OK, otherwise pigif_bad_malloc,
|
||||
pigif_duplicate_callback, or pigif_bad_callback.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
The callback is called with the event id, and tick, whenever the
|
||||
event occurs.
|
||||
|
||||
.IP "\fBint event_callback_ex(int pi, unsigned event, evtCBFuncEx_t f, void *userdata)\fP"
|
||||
.IP "" 4
|
||||
This function initialises an event callback.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
|
||||
.EX
|
||||
pi: >=0 (as returned by \fBpigpio_start\fP).
|
||||
.br
|
||||
event: 0-31.
|
||||
.br
|
||||
f: the callback function.
|
||||
.br
|
||||
userdata: a pointer to arbitrary user data.
|
||||
.br
|
||||
|
||||
.EE
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
The function returns a callback id if OK, otherwise pigif_bad_malloc,
|
||||
pigif_duplicate_callback, or pigif_bad_callback.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
The callback is called with the event id, the tick, and the userdata
|
||||
pointer whenever the event occurs.
|
||||
|
||||
.IP "\fBint event_callback_cancel(unsigned callback_id)\fP"
|
||||
.IP "" 4
|
||||
This function cancels an event callback identified by its id.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
|
||||
.EX
|
||||
callback_id: >=0, as returned by a call to \fBevent_callback\fP or
|
||||
.br
|
||||
\fBevent_callback_ex\fP.
|
||||
.br
|
||||
|
||||
.EE
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
The function returns 0 if OK, otherwise pigif_callback_not_found.
|
||||
|
||||
.IP "\fBint wait_for_event(int pi, unsigned event, double timeout)\fP"
|
||||
.IP "" 4
|
||||
This function waits for an event for up to timeout seconds.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
|
||||
.EX
|
||||
pi: >=0 (as returned by \fBpigpio_start\fP).
|
||||
.br
|
||||
event: 0-31.
|
||||
.br
|
||||
timeout: >=0.
|
||||
.br
|
||||
|
||||
.EE
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
The function returns when the event occurs or after the timeout.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
The function returns 1 if the event occurred, otherwise 0.
|
||||
|
||||
.IP "\fBint event_trigger(int pi, unsigned event)\fP"
|
||||
.IP "" 4
|
||||
This function signals the occurrence of an event.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
|
||||
.EX
|
||||
pi: >=0 (as returned by \fBpigpio_start\fP).
|
||||
.br
|
||||
event: 0-31.
|
||||
.br
|
||||
|
||||
.EE
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
Returns 0 if OK, otherwise PI_BAD_EVENT_ID.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
An event is a signal used to inform one or more consumers
|
||||
to start an action. Each consumer which has registered an interest
|
||||
in the event (e.g. by calling \fBevent_callback\fP) will be informed by
|
||||
a callback.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
One event, PI_EVENT_BSC (31) is predefined. This event is
|
||||
auto generated on BSC slave activity.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
The meaning of other events is arbitrary.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
Note that other than its id and its tick there is no data associated
|
||||
with an event.
|
||||
.SH PARAMETERS
|
||||
|
||||
.br
|
||||
|
@ -5484,6 +5974,43 @@ e.g. to select bits 5, 9, 23 you could use (1<<5) | (1<<9) | (1<<23).
|
|||
|
||||
.br
|
||||
|
||||
.IP "\fBbsc_xfer_t\fP" 0
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
|
||||
.EX
|
||||
typedef struct
|
||||
.br
|
||||
{
|
||||
.br
|
||||
uint32_t control; // Write
|
||||
.br
|
||||
int rxCnt; // Read only
|
||||
.br
|
||||
char rxBuf[BSC_FIFO_SIZE]; // Read only
|
||||
.br
|
||||
int txCnt; // Write
|
||||
.br
|
||||
char txBuf[BSC_FIFO_SIZE]; // Write
|
||||
.br
|
||||
} bsc_xfer_t;
|
||||
.br
|
||||
|
||||
.EE
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
|
||||
.IP "\fB*bscxfer\fP" 0
|
||||
A pointer to a \fBbsc_xfer_t\fP object used to control a BSC transfer.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
|
||||
.IP "\fB*buf\fP" 0
|
||||
A buffer to hold data being sent or being received.
|
||||
|
||||
|
@ -5510,8 +6037,24 @@ An 8-bit byte value.
|
|||
.br
|
||||
|
||||
.IP "\fBcallback_id\fP" 0
|
||||
A >=0, as returned by a call to \fBcallback\fP or \fBcallback_ex\fP. This is
|
||||
passed to \fBcallback_cancel\fP to cancel the callback.
|
||||
A value >=0, as returned by a call to a callback function, one of
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
\fBcallback\fP
|
||||
.br
|
||||
\fBcallback_ex\fP
|
||||
.br
|
||||
\fBevent_callback\fP
|
||||
.br
|
||||
\fBevent_callback_ex\fP
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
The id is passed to \fBcallback_cancel\fP or \fBevent_callback_cancel\fP
|
||||
to cancel the callback.
|
||||
|
||||
.br
|
||||
|
||||
|
@ -5536,7 +6079,7 @@ typedef void (*CBFunc_t)
|
|||
.EX
|
||||
typedef void (*CBFuncEx_t)
|
||||
.br
|
||||
(unsigned user_gpio, unsigned level, uint32_t tick, void * user);
|
||||
(unsigned user_gpio, unsigned level, uint32_t tick, void * userdata);
|
||||
.br
|
||||
|
||||
.EE
|
||||
|
@ -5643,6 +6186,50 @@ of the error.
|
|||
|
||||
.br
|
||||
|
||||
.IP "\fBevent\fP: 0-31" 0
|
||||
An event is a signal used to inform one or more consumers
|
||||
to start an action.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
|
||||
.IP "\fBevtCBFunc_t\fP" 0
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
|
||||
.EX
|
||||
typedef void (*evtCBFunc_t)
|
||||
.br
|
||||
(int pi, unsigned event, uint32_t tick);
|
||||
.br
|
||||
|
||||
.EE
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
|
||||
.IP "\fBevtCBFuncEx_t\fP" 0
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
|
||||
.EX
|
||||
typedef void (*evtCBFuncEx_t)
|
||||
.br
|
||||
(int pi, unsigned event, uint32_t tick, void *userdata);
|
||||
.br
|
||||
|
||||
.EE
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
|
||||
.IP "\fBf\fP" 0
|
||||
A function.
|
||||
|
||||
|
@ -5745,11 +6332,11 @@ typedef struct
|
|||
.br
|
||||
{
|
||||
.br
|
||||
uint32_t gpioOn;
|
||||
uint32_t gpioOn;
|
||||
.br
|
||||
uint32_t gpioOff;
|
||||
uint32_t gpioOff;
|
||||
.br
|
||||
uint32_t usDelay;
|
||||
uint32_t usDelay;
|
||||
.br
|
||||
} gpioPulse_t;
|
||||
.br
|
||||
|
@ -5773,8 +6360,20 @@ typedef void *(gpioThreadFunc_t) (void *);
|
|||
.br
|
||||
|
||||
.IP "\fBhandle\fP: >=0" 0
|
||||
A number referencing an object opened by one of \fBfile_open\fP,
|
||||
\fBi2c_open\fP, \fBnotify_open\fP, \fBserial_open\fP, and \fBspi_open\fP.
|
||||
A number referencing an object opened by one of
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
\fBfile_open\fP
|
||||
.br
|
||||
\fBi2c_open\fP
|
||||
.br
|
||||
\fBnotify_open\fP
|
||||
.br
|
||||
\fBserial_open\fP
|
||||
.br
|
||||
\fBspi_open\fP
|
||||
|
||||
.br
|
||||
|
||||
|
@ -6196,6 +6795,10 @@ The hardware PWM frequency.
|
|||
.IP "\fBrange\fP: 25-40000" 0
|
||||
The permissible dutycycle values are 0-range.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
|
||||
.EX
|
||||
PI_MIN_DUTYCYCLE_RANGE 25
|
||||
.br
|
||||
|
@ -6404,6 +7007,10 @@ thread.
|
|||
.IP "\fBtimeout\fP" 0
|
||||
A GPIO watchdog timeout in milliseconds.
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
|
||||
.EX
|
||||
PI_MIN_WDOG_TIMEOUT 0
|
||||
.br
|
||||
|
@ -6472,16 +7079,24 @@ In the calling function:
|
|||
.br
|
||||
|
||||
.br
|
||||
|
||||
.EX
|
||||
user_type *userdata;
|
||||
.br
|
||||
.br
|
||||
.br
|
||||
user_type my_userdata;
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
userdata = malloc(sizeof(user_type));
|
||||
.br
|
||||
.br
|
||||
.br
|
||||
*userdata = my_userdata;
|
||||
.br
|
||||
|
||||
.EE
|
||||
|
||||
.br
|
||||
|
||||
|
@ -6491,12 +7106,16 @@ In the receiving function:
|
|||
.br
|
||||
|
||||
.br
|
||||
user_type my_userdata = *(user_type*)userdata;
|
||||
|
||||
.EX
|
||||
user_type my_userdata = *(user_type*)userdata;
|
||||
.br
|
||||
|
||||
.br
|
||||
free(userdata);
|
||||
.br
|
||||
|
||||
.EE
|
||||
|
||||
.br
|
||||
|
||||
|
@ -6510,7 +7129,16 @@ Denoting no parameter is required
|
|||
.br
|
||||
|
||||
.IP "\fBwave_add_*\fP" 0
|
||||
One of \fBwave_add_new\fP, \fBwave_add_generic\fP, \fBwave_add_serial\fP.
|
||||
One of
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
\fBwave_add_new\fP
|
||||
.br
|
||||
\fBwave_add_generic\fP
|
||||
.br
|
||||
\fBwave_add_serial\fP
|
||||
|
||||
.br
|
||||
|
||||
|
@ -6524,7 +7152,14 @@ A number representing a waveform created by \fBwave_create\fP.
|
|||
.br
|
||||
|
||||
.IP "\fBwave_send_*\fP" 0
|
||||
One of \fBwave_send_once\fP, \fBwave_send_repeat\fP.
|
||||
One of
|
||||
|
||||
.br
|
||||
|
||||
.br
|
||||
\fBwave_send_once\fP
|
||||
.br
|
||||
\fBwave_send_repeat\fP
|
||||
|
||||
.br
|
||||
|
||||
|
|
232
pigpiod_if2.c
232
pigpiod_if2.c
|
@ -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);}
|
||||
|
||||
|
|
378
pigpiod_if2.h
378
pigpiod_if2.h
|
@ -121,7 +121,7 @@ set_servo_pulsewidth Start/stop servo pulses on a GPIO
|
|||
get_servo_pulsewidth Get the servo pulsewidth in use on a GPIO
|
||||
|
||||
callback Create GPIO level change callback
|
||||
callback_ex Create GPIO level change callback
|
||||
callback_ex Create GPIO level change callback, extended
|
||||
callback_cancel Cancel a callback
|
||||
wait_for_edge Wait for GPIO level change
|
||||
|
||||
|
@ -257,6 +257,11 @@ bb_spi_open Opens GPIO for bit banging SPI
|
|||
bb_spi_close Closes GPIO for bit banging SPI
|
||||
bb_spi_xfer Transfers bytes with bit banging SPI
|
||||
|
||||
I2C/SPI_SLAVE
|
||||
|
||||
bsc_xfer I2C/SPI as slave transfer
|
||||
bsc_i2c I2C as slave transfer
|
||||
|
||||
SERIAL
|
||||
|
||||
serial_open Opens a serial device
|
||||
|
@ -278,6 +283,14 @@ file_write Writes bytes to a file
|
|||
file_seek Seeks to a position within a file
|
||||
file_list List files which match a pattern
|
||||
|
||||
EVENTS
|
||||
|
||||
event_callback Sets a callback for an event
|
||||
event_callback_ex Sets a callback for an event, extended
|
||||
event_callback_cancel Cancel an event callback
|
||||
event_trigger Triggers an event
|
||||
wait_for_event Wait for an event
|
||||
|
||||
CUSTOM
|
||||
|
||||
custom_1 User custom function 1
|
||||
|
@ -306,10 +319,18 @@ typedef void (*CBFunc_t)
|
|||
(int pi, unsigned user_gpio, unsigned level, uint32_t tick);
|
||||
|
||||
typedef void (*CBFuncEx_t)
|
||||
(int pi, unsigned user_gpio, unsigned level, uint32_t tick, void * user);
|
||||
(int pi, unsigned user_gpio, unsigned level, uint32_t tick, void *userdata);
|
||||
|
||||
typedef struct callback_s callback_t;
|
||||
|
||||
typedef void (*evtCBFunc_t)
|
||||
(int pi, unsigned event, uint32_t tick);
|
||||
|
||||
typedef void (*evtCBFuncEx_t)
|
||||
(int pi, unsigned event, uint32_t tick, void *userdata);
|
||||
|
||||
typedef struct evtCallback_s evtCallback_t;
|
||||
|
||||
/*F*/
|
||||
double time_time(void);
|
||||
/*D
|
||||
|
@ -788,15 +809,19 @@ typedef struct
|
|||
seqno: starts at 0 each time the handle is opened and then increments
|
||||
by one for each report.
|
||||
|
||||
flags: two flags are defined, PI_NTFY_FLAGS_WDOG and PI_NTFY_FLAGS_ALIVE.
|
||||
flags: three flags are defined, PI_NTFY_FLAGS_WDOG,
|
||||
PI_NTFY_FLAGS_ALIVE, and PI_NTFY_FLAGS_EVENT.
|
||||
|
||||
PI_NTFY_FLAGS_WDOG, if bit 5 is set then bits 0-4 of the flags
|
||||
If bit 5 is set (PI_NTFY_FLAGS_WDOG) then bits 0-4 of the flags
|
||||
indicate a GPIO which has had a watchdog timeout.
|
||||
|
||||
PI_NTFY_FLAGS_ALIVE, if bit 6 is set this indicates a keep alive
|
||||
If bit 6 is set (PI_NTFY_FLAGS_ALIVE) this indicates a keep alive
|
||||
signal on the pipe/socket and is sent once a minute in the absence
|
||||
of other notification activity.
|
||||
|
||||
If bit 7 is set (PI_NTFY_FLAGS_EVENT) then bits 0-4 of the flags
|
||||
indicate an event which has been triggered.
|
||||
|
||||
tick: the number of microseconds since system boot. It wraps around
|
||||
after 1h12m.
|
||||
|
||||
|
@ -2743,6 +2768,8 @@ handle: >=0, as returned by a call to [*serial_open*].
|
|||
|
||||
Returns the read byte (>=0) if OK, otherwise PI_BAD_HANDLE,
|
||||
PI_SER_READ_NO_DATA, or PI_SER_READ_FAILED.
|
||||
|
||||
If no data is ready PI_SER_READ_NO_DATA is returned.
|
||||
D*/
|
||||
|
||||
/*F*/
|
||||
|
@ -2775,8 +2802,10 @@ handle: >=0, as returned by a call to [*serial_open*].
|
|||
count: the maximum number of bytes to read.
|
||||
. .
|
||||
|
||||
Returns the number of bytes read (>0) if OK, otherwise PI_BAD_HANDLE,
|
||||
Returns the number of bytes read (>=0) if OK, otherwise PI_BAD_HANDLE,
|
||||
PI_BAD_PARAM, PI_SER_READ_NO_DATA, or PI_SER_WRITE_FAILED.
|
||||
|
||||
If no data is ready zero is returned.
|
||||
D*/
|
||||
|
||||
/*F*/
|
||||
|
@ -3237,8 +3266,8 @@ user_gpio: 0-31.
|
|||
The function returns a callback id if OK, otherwise pigif_bad_malloc,
|
||||
pigif_duplicate_callback, or pigif_bad_callback.
|
||||
|
||||
The callback is called with the GPIO, edge, tick, and user, whenever
|
||||
the GPIO has the identified edge.
|
||||
The callback is called with the GPIO, edge, tick, and the userdata
|
||||
pointer, whenever the GPIO has the identified edge.
|
||||
D*/
|
||||
|
||||
/*F*/
|
||||
|
@ -3256,7 +3285,7 @@ D*/
|
|||
/*F*/
|
||||
int wait_for_edge(int pi, unsigned user_gpio, unsigned edge, double timeout);
|
||||
/*D
|
||||
This function waits for edge on the GPIO for up to timeout
|
||||
This function waits for an edge on the GPIO for up to timeout
|
||||
seconds.
|
||||
|
||||
. .
|
||||
|
@ -3276,6 +3305,258 @@ a [*callback*] function.
|
|||
The function returns 1 if the edge occurred, otherwise 0.
|
||||
D*/
|
||||
|
||||
/*F*/
|
||||
int bsc_xfer(int pi, bsc_xfer_t *bscxfer);
|
||||
/*D
|
||||
This function provides a low-level interface to the
|
||||
SPI/I2C Slave peripheral. This peripheral allows the
|
||||
Pi to act as a slave device on an I2C or SPI bus.
|
||||
|
||||
I can't get SPI to work properly. I tried with a
|
||||
control word of 0x303 and swapped MISO and MOSI.
|
||||
|
||||
The function sets the BSC mode, writes any data in
|
||||
the transmit buffer to the BSC transmit FIFO, and
|
||||
copies any data in the BSC receive FIFO to the
|
||||
receive buffer.
|
||||
|
||||
. .
|
||||
pi: >=0 (as returned by [*pigpio_start*]).
|
||||
bscxfer: a structure defining the transfer.
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t control; // Write
|
||||
int rxCnt; // Read only
|
||||
char rxBuf[BSC_FIFO_SIZE]; // Read only
|
||||
int txCnt; // Write
|
||||
char txBuf[BSC_FIFO_SIZE]; // Write
|
||||
} bsc_xfer_t;
|
||||
. .
|
||||
|
||||
To start a transfer set control (see below) and copy the bytes to
|
||||
be sent (if any) to txBuf and set the byte count in txCnt.
|
||||
|
||||
Upon return rxCnt will be set to the number of received bytes placed
|
||||
in rxBuf.
|
||||
|
||||
The returned function value is the status of the transfer (see below).
|
||||
|
||||
If there was an error the status will be less than zero
|
||||
(and will contain the error code).
|
||||
|
||||
The most significant word of the returned status contains the number
|
||||
of bytes actually copied from txBuf to the BSC transmit FIFO (may be
|
||||
less than requested if the FIFO already contained untransmitted data).
|
||||
|
||||
Note that the control word sets the BSC mode. The BSC will stay in
|
||||
that mode until a different control word is sent.
|
||||
|
||||
The BSC peripheral uses GPIO 18 (SDA) and 19 (SCL) in I2C mode
|
||||
and GPIO 18 (MOSI), 19 (SCLK), 20 (MISO), and 21 (CE) in SPI mode. You
|
||||
need to swap MISO/MOSI between master and slave.
|
||||
|
||||
When a zero control word is received GPIO 18-21 will be reset
|
||||
to INPUT mode.
|
||||
|
||||
control consists of the following bits.
|
||||
|
||||
. .
|
||||
22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
a a a a a a a - - IT HC TF IR RE TE BK EC ES PL PH I2 SP EN
|
||||
. .
|
||||
|
||||
Bits 0-13 are copied unchanged to the BSC CR register. See
|
||||
pages 163-165 of the Broadcom peripherals document for full
|
||||
details.
|
||||
|
||||
aaaaaaa @ defines the I2C slave address (only relevant in I2C mode)
|
||||
IT @ invert transmit status flags
|
||||
HC @ enable host control
|
||||
TF @ enable test FIFO
|
||||
IR @ invert receive status flags
|
||||
RE @ enable receive
|
||||
TE @ enable transmit
|
||||
BK @ abort operation and clear FIFOs
|
||||
EC @ send control register as first I2C byte
|
||||
ES @ send status register as first I2C byte
|
||||
PL @ set SPI polarity high
|
||||
PH @ set SPI phase high
|
||||
I2 @ enable I2C mode
|
||||
SP @ enable SPI mode
|
||||
EN @ enable BSC peripheral
|
||||
|
||||
The returned status has the following format
|
||||
|
||||
. .
|
||||
20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
S S S S S R R R R R T T T T T RB TE RF TF RE TB
|
||||
. .
|
||||
|
||||
Bits 0-15 are copied unchanged from the BSC FR register. See
|
||||
pages 165-166 of the Broadcom peripherals document for full
|
||||
details.
|
||||
|
||||
SSSSS @ number of bytes successfully copied to transmit FIFO
|
||||
RRRRR @ number of bytes in receieve FIFO
|
||||
TTTTT @ number of bytes in transmit FIFO
|
||||
RB @ receive busy
|
||||
TE @ transmit FIFO empty
|
||||
RF @ receive FIFO full
|
||||
TF @ transmit FIFO full
|
||||
RE @ receive FIFO empty
|
||||
TB @ transmit busy
|
||||
|
||||
The following example shows how to configure the BSC peripheral as
|
||||
an I2C slave with address 0x13 and send four bytes.
|
||||
|
||||
...
|
||||
bsc_xfer_t xfer;
|
||||
|
||||
xfer.control = (0x13<<16) | 0x305;
|
||||
|
||||
memcpy(xfer.txBuf, "ABCD", 4);
|
||||
xfer.txCnt = 4;
|
||||
|
||||
status = bsc_xfer(pi, &xfer);
|
||||
|
||||
if (status >= 0)
|
||||
{
|
||||
// process transfer
|
||||
}
|
||||
...
|
||||
D*/
|
||||
|
||||
/*F*/
|
||||
int bsc_i2c(int pi, int i2c_addr, bsc_xfer_t *bscxfer);
|
||||
/*D
|
||||
This function allows the Pi to act as a slave I2C device.
|
||||
|
||||
The data bytes (if any) are written to the BSC transmit
|
||||
FIFO and the bytes in the BSC receive FIFO are returned.
|
||||
|
||||
. .
|
||||
pi: >=0 (as returned by [*pigpio_start*]).
|
||||
i2c_addr: 0-0x7F.
|
||||
bscxfer: a structure defining the transfer.
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t control; // N/A
|
||||
int rxCnt; // Read only
|
||||
char rxBuf[BSC_FIFO_SIZE]; // Read only
|
||||
int txCnt; // Write
|
||||
char txBuf[BSC_FIFO_SIZE]; // Write
|
||||
} bsc_xfer_t;
|
||||
. .
|
||||
|
||||
txCnt is set to the number of bytes to be transmitted, possibly
|
||||
zero. The data itself should be copied to txBuf.
|
||||
|
||||
Any received data will be written to rxBuf with rxCnt set.
|
||||
|
||||
See [*bsc_xfer*] for details of the returned status value.
|
||||
|
||||
If there was an error the status will be less than zero
|
||||
(and will contain the error code).
|
||||
|
||||
Note that an i2c_address of 0 may be used to close
|
||||
the BSC device and reassign the used GPIO (18/19)
|
||||
as inputs.
|
||||
D*/
|
||||
|
||||
/*F*/
|
||||
int event_callback(int pi, unsigned event, evtCBFunc_t f);
|
||||
/*D
|
||||
This function initialises an event callback.
|
||||
|
||||
. .
|
||||
pi: >=0 (as returned by [*pigpio_start*]).
|
||||
event: 0-31.
|
||||
f: the callback function.
|
||||
. .
|
||||
|
||||
The function returns a callback id if OK, otherwise pigif_bad_malloc,
|
||||
pigif_duplicate_callback, or pigif_bad_callback.
|
||||
|
||||
The callback is called with the event id, and tick, whenever the
|
||||
event occurs.
|
||||
D*/
|
||||
|
||||
/*F*/
|
||||
int event_callback_ex(int pi, unsigned event, evtCBFuncEx_t f, void *userdata);
|
||||
/*D
|
||||
This function initialises an event callback.
|
||||
|
||||
. .
|
||||
pi: >=0 (as returned by [*pigpio_start*]).
|
||||
event: 0-31.
|
||||
f: the callback function.
|
||||
userdata: a pointer to arbitrary user data.
|
||||
. .
|
||||
|
||||
The function returns a callback id if OK, otherwise pigif_bad_malloc,
|
||||
pigif_duplicate_callback, or pigif_bad_callback.
|
||||
|
||||
The callback is called with the event id, the tick, and the userdata
|
||||
pointer whenever the event occurs.
|
||||
D*/
|
||||
|
||||
/*F*/
|
||||
int event_callback_cancel(unsigned callback_id);
|
||||
/*D
|
||||
This function cancels an event callback identified by its id.
|
||||
|
||||
. .
|
||||
callback_id: >=0, as returned by a call to [*event_callback*] or
|
||||
[*event_callback_ex*].
|
||||
. .
|
||||
|
||||
The function returns 0 if OK, otherwise pigif_callback_not_found.
|
||||
D*/
|
||||
|
||||
/*F*/
|
||||
int wait_for_event(int pi, unsigned event, double timeout);
|
||||
/*D
|
||||
This function waits for an event for up to timeout seconds.
|
||||
|
||||
. .
|
||||
pi: >=0 (as returned by [*pigpio_start*]).
|
||||
event: 0-31.
|
||||
timeout: >=0.
|
||||
. .
|
||||
|
||||
The function returns when the event occurs or after the timeout.
|
||||
|
||||
The function returns 1 if the event occurred, otherwise 0.
|
||||
D*/
|
||||
|
||||
/*F*/
|
||||
int event_trigger(int pi, unsigned event);
|
||||
/*D
|
||||
This function signals the occurrence of an event.
|
||||
|
||||
. .
|
||||
pi: >=0 (as returned by [*pigpio_start*]).
|
||||
event: 0-31.
|
||||
. .
|
||||
|
||||
Returns 0 if OK, otherwise PI_BAD_EVENT_ID.
|
||||
|
||||
An event is a signal used to inform one or more consumers
|
||||
to start an action. Each consumer which has registered an interest
|
||||
in the event (e.g. by calling [*event_callback*]) will be informed by
|
||||
a callback.
|
||||
|
||||
One event, PI_EVENT_BSC (31) is predefined. This event is
|
||||
auto generated on BSC slave activity.
|
||||
|
||||
The meaning of other events is arbitrary.
|
||||
|
||||
Note that other than its id and its tick there is no data associated
|
||||
with an event.
|
||||
D*/
|
||||
|
||||
/*PARAMS
|
||||
|
||||
active :: 0-1000000
|
||||
|
@ -3320,6 +3601,22 @@ A convenient way to set bit n is to or in (1<<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
283
pigs.1
|
@ -484,11 +484,211 @@ ERROR: no permission to update one or more GPIO
|
|||
|
||||
.br
|
||||
|
||||
.IP "\fBBSCX bctl bvs\fP - BSC I2C/SPI transfer"
|
||||
.IP "" 4
|
||||
|
||||
.br
|
||||
This command performs a BSC I2C/SPI slave transfer as defined by
|
||||
\fBbctl\fP with data \fBbvs\fP.
|
||||
|
||||
.br
|
||||
I can't get SPI to work properly. I tried with a
|
||||
control word of 0x303 and swapped MISO and MOSI.
|
||||
|
||||
.br
|
||||
The command sets the BSC mode and writes any data \fBbvs\fP
|
||||
to the BSC transmit FIFO. It returns the data count (at least 1
|
||||
for the status word), the status word, followed by any data bytes
|
||||
read from the BSC receive FIFO.
|
||||
|
||||
.br
|
||||
Note that the control word sets the BSC mode. The BSC will stay in
|
||||
that mode until a different control word is sent.
|
||||
|
||||
.br
|
||||
For I2C use a control word of (I2C address << 16) + 0x305.
|
||||
|
||||
.br
|
||||
E.g. to talk as I2C slave with address 0x13 use 0x130305.
|
||||
|
||||
.br
|
||||
The BSC peripheral uses GPIO 18 (SDA) and 19 (SCL) in I2C mode
|
||||
and GPIO 18 (MOSI), 19 (SCLK), 20 (MISO), and 21 (CE) in SPI mode. You
|
||||
need to swap MISO/MOSI between master and slave.
|
||||
|
||||
.br
|
||||
When a zero control word is received GPIO 18-21 will be reset
|
||||
to INPUT mode.
|
||||
|
||||
.br
|
||||
The control word consists of the following bits.
|
||||
|
||||
.br
|
||||
|
||||
.EX
|
||||
22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
.br
|
||||
a a a a a a a - - IT HC TF IR RE TE BK EC ES PL PH I2 SP EN
|
||||
.br
|
||||
|
||||
.EE
|
||||
|
||||
.br
|
||||
Bits 0-13 are copied unchanged to the BSC CR register. See
|
||||
pages 163-165 of the Broadcom peripherals document for full
|
||||
details.
|
||||
|
||||
.br
|
||||
|
||||
.EX
|
||||
aaaaaaa defines the I2C slave address (only relevant in I2C mode)
|
||||
IT invert transmit status flags
|
||||
HC enable host control
|
||||
TF enable test FIFO
|
||||
IR invert receive status flags
|
||||
RE enable receive
|
||||
TE enable transmit
|
||||
BK abort operation and clear FIFOs
|
||||
EC send control register as first I2C byte
|
||||
ES send status register as first I2C byte
|
||||
PL set SPI polarity high
|
||||
PH set SPI phase high
|
||||
I2 enable I2C mode
|
||||
SP enable SPI mode
|
||||
EN enable BSC peripheral
|
||||
|
||||
.EE
|
||||
|
||||
.br
|
||||
The returned status has the following format
|
||||
|
||||
.br
|
||||
|
||||
.EX
|
||||
20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
.br
|
||||
S S S S S R R R R R T T T T T RB TE RF TF RE TB
|
||||
.br
|
||||
|
||||
.EE
|
||||
|
||||
.br
|
||||
Bits 0-15 are copied unchanged from the BSC FR register. See
|
||||
pages 165-166 of the Broadcom peripherals document for full
|
||||
details.
|
||||
|
||||
.br
|
||||
|
||||
.EX
|
||||
SSSSS number of bytes successfully copied to transmit FIFO
|
||||
RRRRR number of bytes in receieve FIFO
|
||||
TTTTT number of bytes in transmit FIFO
|
||||
RB receive busy
|
||||
TE transmit FIFO empty
|
||||
RF receive FIFO full
|
||||
TF transmit FIFO full
|
||||
RE receive FIFO empty
|
||||
TB transmit busy
|
||||
|
||||
.EE
|
||||
|
||||
.br
|
||||
This example assumes that GPIO 2/3 are connected to GPIO 18/19.
|
||||
|
||||
.br
|
||||
|
||||
\fBExample\fP
|
||||
.br
|
||||
|
||||
.EX
|
||||
$ pigs bscx 0x130305 # start BSC as I2C slave 0x13
|
||||
.br
|
||||
1 18
|
||||
.br
|
||||
|
||||
.br
|
||||
$ i2cdetect -y 1
|
||||
.br
|
||||
0 1 2 3 4 5 6 7 8 9 a b c d e f
|
||||
.br
|
||||
00: -- -- -- -- -- -- -- -- -- -- -- -- --
|
||||
.br
|
||||
10: -- -- -- 13 -- -- -- -- -- -- -- -- -- -- -- --
|
||||
.br
|
||||
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
|
||||
.br
|
||||
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
|
||||
.br
|
||||
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
|
||||
.br
|
||||
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
|
||||
.br
|
||||
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
|
||||
.br
|
||||
70: -- -- -- -- -- -- -- --
|
||||
.br
|
||||
|
||||
.br
|
||||
$ pigs i2co 1 0x13 0 # get handle for device 0x13 on bus 1
|
||||
.br
|
||||
0
|
||||
.br
|
||||
|
||||
.br
|
||||
$ pigs i2cwd 0 90 87 51 9 23 # write 5 bytes
|
||||
.br
|
||||
|
||||
.br
|
||||
$ pigs bscx 0x130305 # check for data
|
||||
.br
|
||||
6 18 90 87 51 9 23
|
||||
.br
|
||||
|
||||
.br
|
||||
$ pigs bscx 0x130305 11 13 15 17 # check for data and send 4 bytes
|
||||
.br
|
||||
1 262338
|
||||
.br
|
||||
|
||||
.br
|
||||
$ pigs i2crd 0 4 # read 4 bytes
|
||||
.br
|
||||
4 11 13 15 17
|
||||
.br
|
||||
|
||||
.br
|
||||
$ pigs i2cwd 0 90 87 51 9 23 # write 5 bytes
|
||||
.br
|
||||
$ pigs bscx 0x130305 11 13 15 17 # check for data and send 4 bytes
|
||||
.br
|
||||
6 262338 90 87 51 9 23
|
||||
.br
|
||||
|
||||
.br
|
||||
$ pigs i2crd 0 4
|
||||
.br
|
||||
4 11 13 15 17
|
||||
.br
|
||||
|
||||
.br
|
||||
$ pigs bscx 0x130305 22 33 44 55 66
|
||||
.br
|
||||
1 327938
|
||||
.br
|
||||
$ pigs i2crd 0 5
|
||||
.br
|
||||
5 22 33 44 55 66
|
||||
.br
|
||||
|
||||
.EE
|
||||
|
||||
.br
|
||||
|
||||
.IP "\fBBSPIC cs\fP - Close bit bang SPI"
|
||||
.IP "" 4
|
||||
|
||||
.br
|
||||
This function stops bit banging SPI on a set of GPIO
|
||||
This command stops bit banging SPI on a set of GPIO
|
||||
opened with \fBBSPIO\fP.
|
||||
|
||||
.br
|
||||
|
@ -744,6 +944,72 @@ configuration settings to \fBv\fP.
|
|||
|
||||
.br
|
||||
|
||||
.IP "\fBEVM h bits\fP - Set events to monitor"
|
||||
.IP "" 4
|
||||
This command starts event reporting on handle \fBh\fP (returned by
|
||||
a prior call to \fBNO\fP).
|
||||
|
||||
.br
|
||||
Upon success nothing is returned. On error a negative status code
|
||||
will be returned.
|
||||
|
||||
.br
|
||||
The notification gets reports for each event specified by \fBbits\fP.
|
||||
|
||||
.br
|
||||
|
||||
\fBExample\fP
|
||||
.br
|
||||
|
||||
.EX
|
||||
$ pigs evm 0 -1 # Shorthand for events 0-31.
|
||||
.br
|
||||
$ pigs evm 0 0xf0 # Get notifications for events 4-7.
|
||||
.br
|
||||
|
||||
.br
|
||||
$ pigs evm 1 0xf
|
||||
.br
|
||||
-25
|
||||
.br
|
||||
ERROR: unknown handle
|
||||
.br
|
||||
|
||||
.EE
|
||||
|
||||
.br
|
||||
|
||||
.IP "\fBEVT event\fP - Trigger event"
|
||||
.IP "" 4
|
||||
This command triggers event \fBevent\fP.
|
||||
|
||||
.br
|
||||
One event, number 31, is predefined. This event is
|
||||
auto generated on BSC slave activity.
|
||||
|
||||
.br
|
||||
|
||||
\fBExample\fP
|
||||
.br
|
||||
|
||||
.EX
|
||||
$ pigs evt 12
|
||||
.br
|
||||
$ pigs evt 5
|
||||
.br
|
||||
|
||||
.br
|
||||
$ pigs evt 32
|
||||
.br
|
||||
-143
|
||||
.br
|
||||
ERROR: bad event id
|
||||
.br
|
||||
|
||||
.EE
|
||||
|
||||
.br
|
||||
|
||||
.IP "\fBFC h\fP - Close file handle"
|
||||
.IP "" 4
|
||||
This command closes a file handle \fBh\fP previously opened with \fBFO\fP.
|
||||
|
@ -4672,6 +4938,11 @@ the transmission of serial data (I2C/SPI/serial link, waves).
|
|||
|
||||
.br
|
||||
|
||||
.IP "\fBbctl\fP - BSC control word" 0
|
||||
The command expects a BSC control word, see \fBBSCX\fP.
|
||||
|
||||
.br
|
||||
|
||||
.IP "\fBbit\fP - bit value (0-1)" 0
|
||||
The command expects 0 or 1.
|
||||
|
||||
|
@ -4736,6 +5007,12 @@ The command expects the name of a tty serial device, e.g.
|
|||
|
||||
.br
|
||||
|
||||
.IP "\fBevent\fP - 0-31" 0
|
||||
An event is a signal used to inform one or more consumers
|
||||
to start an action.
|
||||
|
||||
.br
|
||||
|
||||
.IP "\fBfile\fP - a file name" 0
|
||||
The file name must match an entry in /opt/pigpio/access.
|
||||
|
||||
|
@ -5343,6 +5620,7 @@ CMP x Compare x with accumulator F=A-x
|
|||
DCR y Decrement register --*y; F=*y
|
||||
DCRA Decrement accumulator --A; F=A
|
||||
DIV x Divide x into accumulator A/=x; F=A
|
||||
EVTWT Wait for an event to occur A=wait(x); F=A
|
||||
HALT Halt Halt
|
||||
INR y Increment register ++*y; F=*y
|
||||
INRA Increment accumulator ++A; F=A
|
||||
|
@ -5383,6 +5661,9 @@ x may be a constant, a parameter (p0-p9), or a variable (v0-v149).
|
|||
y may be a parameter (p0-p9), or a variable (v0-v149). If p or v isn't
|
||||
specified y is assumed to be a variable.
|
||||
|
||||
.br
|
||||
The EVTWT command parameter is a bit-mask with 1 set for events of interest.
|
||||
|
||||
.br
|
||||
The WAIT command parameter is a bit-mask with 1 set for GPIO of interest.
|
||||
|
||||
|
|
40
pigs.c
40
pigs.c
|
@ -172,8 +172,8 @@ void print_result(int sock, int rv, cmdCmd_t cmd)
|
|||
break;
|
||||
|
||||
case 6: /*
|
||||
BI2CZ CF2 FL FR I2CPK I2CRD I2CRI I2CRK I2CZ
|
||||
SERR SLR SPIX SPIR
|
||||
BI2CZ CF2 FL FR I2CPK I2CRD I2CRI I2CRK
|
||||
I2CZ SERR SLR SPIX SPIR
|
||||
*/
|
||||
printf("%d", r);
|
||||
if (r < 0) fatal("ERROR: %s", cmdErrStr(r));
|
||||
|
@ -216,6 +216,41 @@ void print_result(int sock, int rv, cmdCmd_t cmd)
|
|||
}
|
||||
printf("\n");
|
||||
break;
|
||||
|
||||
case 8: /*
|
||||
BSCX
|
||||
*/
|
||||
if (r < 0)
|
||||
{
|
||||
printf("%d", r);
|
||||
fatal("ERROR: %s", cmdErrStr(r));
|
||||
}
|
||||
|
||||
p = (uint32_t *)response_buf;
|
||||
printf("%d %d", r-3, p[0]);
|
||||
|
||||
if (r > 4)
|
||||
{
|
||||
if (printFlags == PRINT_ASCII) printf(" ");
|
||||
|
||||
for (i=4; i<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:
|
||||
|
|
2
setup.py
2
setup.py
|
@ -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
2
x_pigs
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue