diff --git a/EXAMPLES/C/IR_RECEIVER/ir_hasher.c b/EXAMPLES/C/IR_RECEIVER/ir_hasher.c
index ef154a1..4131b9b 100644
--- a/EXAMPLES/C/IR_RECEIVER/ir_hasher.c
+++ b/EXAMPLES/C/IR_RECEIVER/ir_hasher.c
@@ -118,6 +118,8 @@ Pi_Hasher_t *Pi_Hasher(int gpio, Pi_Hasher_CB_t callback, int timeout)
gpioSetMode(gpio, PI_INPUT);
gpioSetAlertFuncEx(gpio, _cb, hasher);
+
+ return hasher;
}
void Pi_Hasher_cancel(Pi_Hasher_t *hasher)
@@ -127,6 +129,8 @@ void Pi_Hasher_cancel(Pi_Hasher_t *hasher)
gpioSetAlertFunc(hasher->gpio, 0);
free(hasher);
+
+ hasher = NULL;
}
}
diff --git a/command.c b/command.c
index b875d11..06fc914 100644
--- a/command.c
+++ b/command.c
@@ -26,7 +26,7 @@ For more information, please refer to
*/
/*
-This version is for pigpio version 30+
+This version is for pigpio version 31+
*/
#include
@@ -494,6 +494,8 @@ static errInfo_t errInfo[]=
{PI_BAD_DATABITS , "serial data bits not 1-32"},
{PI_MSG_TOOBIG , "socket/pipe message too big"},
{PI_BAD_MALLOC_MODE , "bad memory allocation mode"},
+ {PI_TOO_MANY_PARTS , "too many I2C transaction parts"},
+ {PI_BAD_I2C_PART , "a combined I2C transaction failed"},
};
diff --git a/pigpio.3 b/pigpio.3
index b766fb5..08c5dd9 100644
--- a/pigpio.3
+++ b/pigpio.3
@@ -2062,6 +2062,42 @@ No flags are currently defined. This parameter should be set to zero.
Returns a handle (>=0) if OK, otherwise PI_BAD_I2C_BUS, PI_BAD_I2C_ADDR,
PI_BAD_FLAGS, PI_NO_HANDLE, or PI_I2C_OPEN_FAILED.
+.br
+
+.br
+For the smbus commands the low level transactions are shown at the end
+of the function description. The following abbreviations are used.
+
+.br
+
+.br
+
+.EX
+S (1 bit) : Start bit
+.br
+P (1 bit) : Stop bit
+.br
+Rd/Wr (1 bit) : Read/Write bit. Rd equals 1, Wr equals 0.
+.br
+A, NA (1 bit) : Accept and not accept bit.
+.br
+.br
+.br
+Addr (7 bits): I2C 7 bit address.
+.br
+Comm (8 bits): Command byte, a data byte which often selects a register.
+.br
+Data (8 bits): A data byte.
+.br
+Count (8 bits): A data byte containing the length of a block operation.
+.br
+
+.br
+[..]: Data sent by the device.
+.br
+
+.EE
+
.IP "\fBint i2cClose(unsigned handle)\fP"
.IP "" 4
This closes the I2C device associated with the handle.
@@ -2157,6 +2193,12 @@ PI_I2C_WRITE_FAILED.
.br
Quick command. smbus 2.0 5.5.1
+.EX
+S Addr Rd/Wr [A] P
+.br
+
+.EE
+
.IP "\fBint i2cWriteByte(unsigned handle, unsigned bVal)\fP"
.IP "" 4
This sends a single byte to the device associated with handle.
@@ -2184,6 +2226,12 @@ PI_I2C_WRITE_FAILED.
.br
Send byte. smbus 2.0 5.5.2
+.EX
+S Addr Wr [A] Data [A] P
+.br
+
+.EE
+
.IP "\fBint i2cReadByte(unsigned handle)\fP"
.IP "" 4
This reads a single byte from the device associated with handle.
@@ -2209,6 +2257,12 @@ or PI_I2C_READ_FAILED.
.br
Receive byte. smbus 2.0 5.5.3
+.EX
+S Addr Rd [A] [Data] NA P
+.br
+
+.EE
+
.IP "\fBint i2cWriteByteData(unsigned handle, unsigned i2cReg, unsigned bVal)\fP"
.IP "" 4
This writes a single byte to the specified register of the device
@@ -2239,6 +2293,12 @@ PI_I2C_WRITE_FAILED.
.br
Write byte. smbus 2.0 5.5.4
+.EX
+S Addr Wr [A] Comm [A] Data [A] P
+.br
+
+.EE
+
.IP "\fBint i2cWriteWordData(unsigned handle, unsigned i2cReg, unsigned wVal)\fP"
.IP "" 4
This writes a single 16 bit word to the specified register of the device
@@ -2269,6 +2329,12 @@ PI_I2C_WRITE_FAILED.
.br
Write word. smbus 2.0 5.5.4
+.EX
+S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A] P
+.br
+
+.EE
+
.IP "\fBint i2cReadByteData(unsigned handle, unsigned i2cReg)\fP"
.IP "" 4
This reads a single byte from the specified register of the device
@@ -2297,6 +2363,12 @@ PI_BAD_PARAM, or PI_I2C_READ_FAILED.
.br
Read byte. smbus 2.0 5.5.5
+.EX
+S Addr Wr [A] Comm [A] S Addr Rd [A] [Data] NA P
+.br
+
+.EE
+
.IP "\fBint i2cReadWordData(unsigned handle, unsigned i2cReg)\fP"
.IP "" 4
This reads a single 16 bit word from the specified register of the device
@@ -2325,6 +2397,12 @@ PI_BAD_PARAM, or PI_I2C_READ_FAILED.
.br
Read word. smbus 2.0 5.5.5
+.EX
+S Addr Wr [A] Comm [A] S Addr Rd [A] [DataLow] A [DataHigh] NA P
+.br
+
+.EE
+
.IP "\fBint i2cProcessCall(unsigned handle, unsigned i2cReg, unsigned wVal)\fP"
.IP "" 4
This writes 16 bits of data to the specified register of the device
@@ -2355,6 +2433,14 @@ PI_BAD_PARAM, or PI_I2C_READ_FAILED.
.br
Process call. smbus 2.0 5.5.6
+.EX
+S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A]
+.br
+ S Addr Rd [A] [DataLow] A [DataHigh] NA P
+.br
+
+.EE
+
.IP "\fBint i2cWriteBlockData(unsigned handle, unsigned i2cReg, char *buf, unsigned count)\fP"
.IP "" 4
This writes up to 32 bytes to the specified register of the device
@@ -2387,6 +2473,12 @@ PI_I2C_WRITE_FAILED.
.br
Block write. smbus 2.0 5.5.7
+.EX
+S Addr Wr [A] Comm [A] Count [A] Data [A] Data [A] ... [A] Data [A] P
+.br
+
+.EE
+
.IP "\fBint i2cReadBlockData(unsigned handle, unsigned i2cReg, char *buf)\fP"
.IP "" 4
This reads a block of up to 32 bytes from the specified register of
@@ -2422,6 +2514,14 @@ PI_BAD_PARAM, or PI_I2C_READ_FAILED.
.br
Block read. smbus 2.0 5.5.7
+.EX
+S Addr Wr [A] Comm [A]
+.br
+ S Addr Rd [A] [Count] A [Data] A [Data] A ... A [Data] NA P
+.br
+
+.EE
+
.IP "\fBint i2cBlockProcessCall(unsigned handle, unsigned i2cReg, char *buf, unsigned count)\fP"
.IP "" 4
This writes data bytes to the specified register of the device
@@ -2462,6 +2562,14 @@ bytes sent/received must be 32 or less.
.br
Block write-block read. smbus 2.0 5.5.8
+.EX
+S Addr Wr [A] Comm [A] Count [A] Data [A] ...
+.br
+ S Addr Rd [A] [Count] A [Data] ... A P
+.br
+
+.EE
+
.IP "\fBint i2cReadI2CBlockData(unsigned handle, unsigned i2cReg, char *buf, unsigned count)\fP"
.IP "" 4
This reads count bytes from the specified register of the device
@@ -2489,6 +2597,18 @@ i2cReg: 0-255, the register to read
Returns the number of bytes read (>0) if OK, otherwise PI_BAD_HANDLE,
PI_BAD_PARAM, or PI_I2C_READ_FAILED.
+.br
+
+.br
+
+.EX
+S Addr Wr [A] Comm [A]
+.br
+ S Addr Rd [A] [Data] A [Data] A ... A [Data] NA P
+.br
+
+.EE
+
.IP "\fBint i2cWriteI2CBlockData(unsigned handle, unsigned i2cReg, char *buf, unsigned count)\fP"
.IP "" 4
This writes 1 to 32 bytes to the specified register of the device
@@ -2516,6 +2636,16 @@ i2cReg: 0-255, the register to write
Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or
PI_I2C_WRITE_FAILED.
+.br
+
+.br
+
+.EX
+S Addr Wr [A] Comm [A] Data [A] Data [A] ... [A] Data [A] P
+.br
+
+.EE
+
.IP "\fBint spiOpen(unsigned spiChan, unsigned spiBaud, unsigned spiFlags)\fP"
.IP "" 4
This function returns a handle for the SPI device on the channel.
@@ -5697,10 +5827,6 @@ The number of bits stored in a buffer.
.br
.IP "\fBnumBytes\fP" 0
-
-.br
-
-.br
The number of bytes used to store characters in a string. Depending
on the number of bits per character there may be 1, 2, or 4 bytes
per character.
@@ -5710,21 +5836,20 @@ per character.
.br
.IP "\fBnumPar\fP: 0-10" 0
-
-.br
-
-.br
The number of parameters passed to a script.
.br
.br
+.IP "\fBnumParts\fP" 0
+The number of parts in a combined I2C transaction.
+
+.br
+
+.br
+
.IP "\fBnumPulses\fP" 0
-
-.br
-
-.br
The number of pulses to be added to a waveform.
.br
@@ -5732,10 +5857,6 @@ The number of pulses to be added to a waveform.
.br
.IP "\fBoffset\fP" 0
-
-.br
-
-.br
The associated data starts this number of microseconds from the start of
tghe waveform.
@@ -5744,21 +5865,44 @@ tghe waveform.
.br
.IP "\fB*param\fP" 0
-
-.br
-
-.br
An array of script parameters.
.br
.br
+.IP "\fB*parts\fP" 0
+An array of the part transactions which make up a combined I2C transaction.
+
+.br
+
+.br
+
+.IP "\fBpi_i2c_msg_t\fP" 0
+
+.EX
+typedef struct
+.br
+{
+.br
+ uint16_t addr; // slave address
+.br
+ uint16_t flags;
+.br
+ uint16_t len; // msg length
+.br
+ uint8_t *buf; // pointer to msg data
+.br
+} pi_i2c_msg_t;
+.br
+
+.EE
+
+.br
+
+.br
+
.IP "\fBport\fP: 1024-32000" 0
-
-.br
-
-.br
The port used to bind to the pigpio socket. Defaults to 8888.
.br
@@ -5766,10 +5910,6 @@ The port used to bind to the pigpio socket. Defaults to 8888.
.br
.IP "\fBpos\fP" 0
-
-.br
-
-.br
The position of an item.
.br
@@ -5777,10 +5917,6 @@ The position of an item.
.br
.IP "\fBprimaryChannel\fP: 0-14" 0
-
-.br
-
-.br
The DMA channel used to time the sampling of gpios and to time servo and
PWM pulses.
@@ -6902,6 +7038,12 @@ A 16-bit word value.
#define PI_MSG_TOOBIG -103 // socket/pipe message too big
.br
#define PI_BAD_MALLOC_MODE -104 // bad memory allocation mode
+.br
+#define PI_TOO_MANY_PARTS -105 // too many I2C transaction parts
+.br
+#define PI_BAD_I2C_PART -106 // a combined I2C transaction failed
+.br
+
.br
.br
diff --git a/pigpio.c b/pigpio.c
index 0559a4b..29bf97a 100644
--- a/pigpio.c
+++ b/pigpio.c
@@ -25,7 +25,9 @@ OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to
*/
-/* pigpio version 30 */
+/* pigpio version 31 */
+
+/* include ------------------------------------------------------- */
#include
#include
@@ -178,7 +180,7 @@ bit 0 READ_LAST_NOT_SET_ERROR
6 C3 System Timer Compare 3
*/
-/* --------------------------------------------------------------- */
+/* define -------------------------------------------------------- */
#define THOUSAND 1000
#define MILLION 1000000
@@ -283,14 +285,8 @@ bit 0 READ_LAST_NOT_SET_ERROR
} \
while (0)
-static volatile uint32_t piModel = 1;
-
#define PI_PERI_BUS 0x7E000000
-static volatile uint32_t pi_peri_phys = 0x20000000;
-static volatile uint32_t pi_dram_bus = 0x40000000;
-static volatile uint32_t pi_mem_flag = 0x00000004;
-
#define AUX_BASE (pi_peri_phys + 0x00215000)
#define CLK_BASE (pi_peri_phys + 0x00101000)
#define DMA_BASE (pi_peri_phys + 0x00007000)
@@ -720,6 +716,7 @@ static volatile uint32_t pi_mem_flag = 0x00000004;
#define SRX_BUF_SIZE 8192
#define PI_I2C_SLAVE 0x0703
+#define PI_I2C_RDWR 0x0707
#define PI_I2C_SMBUS 0x0720
#define PI_I2C_SMBUS_READ 1
@@ -758,7 +755,31 @@ static volatile uint32_t pi_mem_flag = 0x00000004;
#define MB_UNLOCK_MEMORY_TAG 0x3000E
#define MB_RELEASE_MEMORY_TAG 0x3000F
-/* --------------------------------------------------------------- */
+#define PI_SCRIPT_FREE 0
+#define PI_SCRIPT_RESERVED 1
+#define PI_SCRIPT_IN_USE 2
+#define PI_SCRIPT_DYING 3
+
+#define PI_SCRIPT_HALT 0
+#define PI_SCRIPT_RUN 1
+#define PI_SCRIPT_DELETE 2
+
+#define PI_SCRIPT_STACK_SIZE 256
+
+#define PI_SPI_FLAGS_CHANNEL(x) ((x&7)<<29)
+
+#define PI_SPI_FLAGS_GET_CHANNEL(x) (((x)>>29)&7)
+#define PI_SPI_FLAGS_GET_BITLEN(x) (((x)>>16)&63)
+#define PI_SPI_FLAGS_GET_RX_LSB(x) (((x)>>15)&1)
+#define PI_SPI_FLAGS_GET_TX_LSB(x) (((x)>>14)&1)
+#define PI_SPI_FLAGS_GET_3WREN(x) (((x)>>10)&15)
+#define PI_SPI_FLAGS_GET_3WIRE(x) (((x)>>9)&1)
+#define PI_SPI_FLAGS_GET_AUX_SPI(x) (((x)>>8)&1)
+#define PI_SPI_FLAGS_GET_RESVD(x) (((x)>>5)&7)
+#define PI_SPI_FLAGS_GET_CSPOLS(x) (((x)>>2)&7)
+#define PI_SPI_FLAGS_GET_MODE(x) ((x)&3)
+
+/* typedef ------------------------------------------------------- */
typedef void (*callbk_t) ();
@@ -830,17 +851,6 @@ typedef struct
pthread_t pthId;
} gpioTimer_t;
-#define PI_SCRIPT_FREE 0
-#define PI_SCRIPT_RESERVED 1
-#define PI_SCRIPT_IN_USE 2
-#define PI_SCRIPT_DYING 3
-
-#define PI_SCRIPT_HALT 0
-#define PI_SCRIPT_RUN 1
-#define PI_SCRIPT_DELETE 2
-
-#define PI_SCRIPT_STACK_SIZE 256
-
typedef struct
{
unsigned id;
@@ -892,19 +902,6 @@ typedef struct
uint32_t flags;
} spiInfo_t;
-#define PI_SPI_FLAGS_CHANNEL(x) ((x&7)<<29)
-
-#define PI_SPI_FLAGS_GET_CHANNEL(x) (((x)>>29)&7)
-#define PI_SPI_FLAGS_GET_BITLEN(x) (((x)>>16)&63)
-#define PI_SPI_FLAGS_GET_RX_LSB(x) (((x)>>15)&1)
-#define PI_SPI_FLAGS_GET_TX_LSB(x) (((x)>>14)&1)
-#define PI_SPI_FLAGS_GET_3WREN(x) (((x)>>10)&15)
-#define PI_SPI_FLAGS_GET_3WIRE(x) (((x)>>9)&1)
-#define PI_SPI_FLAGS_GET_AUX_SPI(x) (((x)>>8)&1)
-#define PI_SPI_FLAGS_GET_RESVD(x) (((x)>>5)&7)
-#define PI_SPI_FLAGS_GET_CSPOLS(x) (((x)>>2)&7)
-#define PI_SPI_FLAGS_GET_MODE(x) ((x)&3)
-
typedef struct
{
uint32_t startTick;
@@ -983,6 +980,12 @@ struct my_smbus_ioctl_data
union my_smbus_data *data;
};
+typedef struct
+{
+ pi_i2c_msg_t *msgs; /* pointers to pi_i2c_msgs */
+ uint32_t nmsgs; /* number of pi_i2c_msgs */
+} my_i2c_rdwr_ioctl_data_t;
+
typedef struct
{
unsigned div;
@@ -998,34 +1001,27 @@ typedef struct
unsigned size; /* in bytes */
} DMAMem_t;
-/* --------------------------------------------------------------- */
+/* global -------------------------------------------------------- */
/* initialise once then preserve */
-static volatile gpioCfg_t gpioCfg =
-{
- PI_DEFAULT_BUFFER_MILLIS,
- PI_DEFAULT_CLK_MICROS,
- PI_DEFAULT_CLK_PERIPHERAL,
- PI_DEFAULT_DMA_PRIMARY_CHANNEL,
- PI_DEFAULT_DMA_SECONDARY_CHANNEL,
- PI_DEFAULT_SOCKET_PORT,
- PI_DEFAULT_IF_FLAGS,
- 0,
- 0,
- PI_DEFAULT_MEM_ALLOC_MODE,
-};
+static volatile uint32_t piModel = 1;
+static volatile uint32_t pi_peri_phys = 0x20000000;
+static volatile uint32_t pi_dram_bus = 0x40000000;
+static volatile uint32_t pi_mem_flag = 0x0C;
-static volatile gpioStats_t gpioStats;
-
-static int gpioMaskSet = 0;
+static int libInitialised = 0;
/* initialise every gpioInitialise */
static struct timespec libStarted;
static int waveClockInited = 0;
-/* initialse if not libInitialised */
+static volatile gpioStats_t gpioStats;
+
+static int gpioMaskSet = 0;
+
+/* initialise if not libInitialised */
static uint64_t gpioMask;
@@ -1058,8 +1054,7 @@ static volatile uint32_t notifyBits = 0;
static volatile uint32_t scriptBits = 0;
static volatile int DMAstarted = 0;
-
-static int libInitialised = 0;
+static volatile int terminating = 0;
static int pthAlertRunning = 0;
static int pthFifoRunning = 0;
@@ -1085,19 +1080,7 @@ static gpioTimer_t gpioTimer [PI_MAX_TIMER+1];
static int pwmFreq[PWM_FREQS];
-/* no initialisation required */
-
-static unsigned bufferBlocks; /* number of blocks in buffer */
-static unsigned bufferCycles; /* number of cycles */
-
-static pthread_attr_t pthAttr;
-
-static pthread_t pthAlert;
-static pthread_t pthFifo;
-static pthread_t pthSocket;
-
-static gpioSample_t gpioSample[DATUMS];
-static gpioReport_t gpioReport[DATUMS];
+/* reset after gpioTerminated */
/* resources which must be released on gpioTerminate */
@@ -1133,7 +1116,70 @@ static volatile uint32_t * systReg = MAP_FAILED;
static volatile uint32_t * dmaIn = MAP_FAILED;
static volatile uint32_t * dmaOut = MAP_FAILED;
-/* constant data */
+static uint32_t hw_clk_freq[3];
+static uint32_t hw_pwm_freq[2];
+static uint32_t hw_pwm_duty[2];
+static uint32_t hw_pwm_real_range[2];
+
+static volatile gpioCfg_t gpioCfg =
+{
+ PI_DEFAULT_BUFFER_MILLIS,
+ PI_DEFAULT_CLK_MICROS,
+ PI_DEFAULT_CLK_PERIPHERAL,
+ PI_DEFAULT_DMA_PRIMARY_CHANNEL,
+ PI_DEFAULT_DMA_SECONDARY_CHANNEL,
+ PI_DEFAULT_SOCKET_PORT,
+ PI_DEFAULT_IF_FLAGS,
+ DBG_MIN_LEVEL,
+ 0,
+ PI_DEFAULT_MEM_ALLOC_MODE,
+};
+
+/* no initialisation required */
+
+static unsigned bufferBlocks; /* number of blocks in buffer */
+static unsigned bufferCycles; /* number of cycles */
+
+static pthread_t pthAlert;
+static pthread_t pthFifo;
+static pthread_t pthSocket;
+
+static gpioSample_t gpioSample[DATUMS];
+static gpioReport_t gpioReport[DATUMS];
+
+static uint32_t spi_dummy;
+
+static unsigned old_mode_ce0;
+static unsigned old_mode_ce1;
+static unsigned old_mode_sclk;
+static unsigned old_mode_miso;
+static unsigned old_mode_mosi;
+
+static uint32_t old_spi_cs;
+static uint32_t old_spi_clk;
+
+static unsigned old_mode_ace0;
+static unsigned old_mode_ace1;
+static unsigned old_mode_ace2;
+static unsigned old_mode_asclk;
+static unsigned old_mode_amiso;
+static unsigned old_mode_amosi;
+
+static uint32_t old_spi_cntl0;
+static uint32_t old_spi_cntl1;
+
+/* const --------------------------------------------------------- */
+
+static const uint8_t clkDef[PI_MAX_GPIO + 1] =
+{
+ /* 0 1 2 3 4 5 6 7 8 9 */
+ /* 0 */ 0x00, 0x00, 0x00, 0x00, 0x84, 0x94, 0xA4, 0x00, 0x00, 0x00,
+ /* 1 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ /* 2 */ 0x82, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ /* 3 */ 0x00, 0x00, 0x84, 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00,
+ /* 4 */ 0x00, 0x00, 0x94, 0xA4, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00,
+ /* 5 */ 0x00, 0x00, 0x00, 0x00,
+};
/*
7 6 5 4 3 2 1 0
@@ -1156,17 +1202,15 @@ CC: 00 CLK0, 01 CLK1, 10 CLK2
gpio44 GPCLK1 ALT0 Compute module only (reserved for system use)
*/
-uint32_t hw_clk_freq[3];
-
-uint8_t clkDef[PI_MAX_GPIO + 1] =
+static const uint8_t PWMDef[PI_MAX_GPIO + 1] =
{
- /* 0 1 2 3 4 5 6 7 8 9 */
- /* 0 */ 0x00, 0x00, 0x00, 0x00, 0x84, 0x94, 0xA4, 0x00, 0x00, 0x00,
- /* 1 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- /* 2 */ 0x82, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- /* 3 */ 0x00, 0x00, 0x84, 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00,
- /* 4 */ 0x00, 0x00, 0x94, 0xA4, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00,
- /* 5 */ 0x00, 0x00, 0x00, 0x00,
+ /* 0 1 2 3 4 5 6 7 8 9 */
+ /* 0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ /* 1 */ 0x00, 0x00, 0x84, 0x94, 0x00, 0x00, 0x00, 0x00, 0x82, 0x92,
+ /* 2 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ /* 3 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ /* 4 */ 0x84, 0x94, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x00,
+ /* 5 */ 0x00, 0x00, 0x85, 0x95,
};
/*
@@ -1188,21 +1232,6 @@ uint8_t clkDef[PI_MAX_GPIO + 1] =
gpio53 pwm1 ALT1
*/
-uint32_t hw_pwm_freq[2];
-uint32_t hw_pwm_duty[2];
-uint32_t hw_pwm_real_range[2];
-
-uint8_t PWMDef[PI_MAX_GPIO + 1] =
-{
- /* 0 1 2 3 4 5 6 7 8 9 */
- /* 0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- /* 1 */ 0x00, 0x00, 0x84, 0x94, 0x00, 0x00, 0x00, 0x00, 0x82, 0x92,
- /* 2 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- /* 3 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- /* 4 */ 0x84, 0x94, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x00,
- /* 5 */ 0x00, 0x00, 0x85, 0x95,
-};
-
static const clkCfg_t clkCfg[]=
{
/* valid servo */
@@ -1227,18 +1256,18 @@ static const uint16_t pwmRealRange[PWM_FREQS]=
{ 25, 50, 100, 125, 200, 250, 400, 500, 625,
800, 1000, 1250, 2000, 2500, 4000, 5000, 10000, 20000};
-/* ======================================================================= */
-
-/* Internal prototypes.
-*/
+/* prototype ----------------------------------------------------- */
static void intNotifyBits(void);
+
static void intScriptBits(void);
+
static int gpioNotifyOpenInBand(int fd);
+
static void initHWClk
(int clkCtl, int clkDiv, int clkSrc, int divI, int divF, int MASH);
-static void initDMAgo(volatile uint32_t *dmaAddr, uint32_t cbAddr);
+static void initDMAgo(volatile uint32_t *dmaAddr, uint32_t cbAddr);
/* ======================================================================= */
@@ -1444,7 +1473,7 @@ static void flushMemory(void)
static void waitForDMAstarted(void)
{
- while (!DMAstarted)
+ while ((!DMAstarted) && (!terminating))
{
if (piModel == 1) myGpioDelay(1000);
else flushMemory();
@@ -1531,7 +1560,7 @@ static int myDoCommand(uint32_t *p, unsigned bufSize, char *buf)
case PI_CMD_CF2:
- /* a couple of extra precautions for untruested code */
+ /* a couple of extra precautions for untrusted code */
if (p[2] > bufSize) p[2] = bufSize;
res = gpioCustom2(p[1], buf, p[3], buf, p[2]);
if (res > p[2]) res = p[2];
@@ -2110,7 +2139,7 @@ static void myGpioSetServo(unsigned gpio, int oldVal, int newVal)
https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface
*/
-int mbCreate(void)
+static int mbCreate(void)
{
/* <0 error */
@@ -2119,14 +2148,14 @@ int mbCreate(void)
return mknod(MB_DEV, S_IFCHR|0600, makedev(MB_DEV_MAJOR, 0));
}
-int mbOpen(void)
+static int mbOpen(void)
{
/* <0 error */
return open(MB_DEV, 0);
}
-void mbClose(int fd)
+static void mbClose(int fd)
{
close(fd);
}
@@ -2136,7 +2165,7 @@ static int mbProperty(int fd, void *buf)
return ioctl(fd, MB_IOCTL, buf);
}
-unsigned mbAllocateMemory(
+static unsigned mbAllocateMemory(
int fd, unsigned size, unsigned align, unsigned flags)
{
int i=1;
@@ -2157,7 +2186,7 @@ unsigned mbAllocateMemory(
return p[5];
}
-unsigned mbLockMemory(int fd, unsigned handle)
+static unsigned mbLockMemory(int fd, unsigned handle)
{
int i=1;
unsigned p[32];
@@ -2175,7 +2204,7 @@ unsigned mbLockMemory(int fd, unsigned handle)
return p[5];
}
-unsigned mbUnlockMemory(int fd, unsigned handle)
+static unsigned mbUnlockMemory(int fd, unsigned handle)
{
int i=1;
unsigned p[32];
@@ -2193,7 +2222,7 @@ unsigned mbUnlockMemory(int fd, unsigned handle)
return p[5];
}
-unsigned mbReleaseMemory(int fd, unsigned handle)
+static unsigned mbReleaseMemory(int fd, unsigned handle)
{
int i=1;
unsigned p[32];
@@ -2211,7 +2240,7 @@ unsigned mbReleaseMemory(int fd, unsigned handle)
return p[5];
}
-void *mbMapMem(unsigned base, unsigned size)
+static void *mbMapMem(unsigned base, unsigned size)
{
void *mem = MAP_FAILED;
@@ -2220,13 +2249,13 @@ void *mbMapMem(unsigned base, unsigned size)
return mem;
}
-int mbUnmapMem(void *addr, unsigned size)
+static int mbUnmapMem(void *addr, unsigned size)
{
/* 0 okay, -1 fail */
return munmap(addr, size);
}
-void mbDMAFree(DMAMem_t *DMAMemP)
+static void mbDMAFree(DMAMem_t *DMAMemP)
{
if (DMAMemP->handle)
{
@@ -2237,7 +2266,7 @@ void mbDMAFree(DMAMem_t *DMAMemP)
}
}
-int mbDMAAlloc(DMAMem_t *DMAMemP, unsigned size, uint32_t pi_mem_flag)
+static int mbDMAAlloc(DMAMem_t *DMAMemP, unsigned size, uint32_t pi_mem_flag)
{
DMAMemP->size = size;
@@ -3388,31 +3417,51 @@ int i2cClose(unsigned handle)
return 0;
}
+int i2cTransaction(unsigned handle, pi_i2c_msg_t *parts, unsigned numParts)
+{
+ int retval, fd;
+ my_i2c_rdwr_ioctl_data_t rdwr;
+
+ DBG(DBG_USER, "handle=%d", handle);
+
+ CHECK_INITED;
+
+ if (handle >= PI_I2C_SLOTS)
+ SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
+
+ if (i2cInfo[handle].state != PI_I2C_OPENED)
+ SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
+
+ if (parts == NULL)
+ SOFT_ERROR(PI_BAD_POINTER, "null parts");
+
+ if (numParts > PI_I2C_RDRW_IOCTL_MAX_MSGS)
+ SOFT_ERROR(PI_TOO_MANY_PARTS, "too many parts (%d)", numParts);
+
+ fd = open(PI_I2C_COMBINED, O_RDWR);
+
+ if (fd >= 0)
+ {
+ write(fd, "1", 1);
+ close(fd);
+ }
+
+ rdwr.msgs = parts;
+ rdwr.nmsgs = numParts;
+
+ retval = ioctl(i2cInfo[handle].fd, PI_I2C_RDWR, &rdwr);
+
+ DBG(0, "i2cTransaction retval=%d", retval);
+
+ if (retval >= 0) return retval;
+ else return PI_BAD_I2C_PART;
+}
+
+
/* ======================================================================= */
/*SPI */
-static uint32_t spi_dummy; /* only used to prevent warning */
-
-static unsigned old_mode_ce0;
-static unsigned old_mode_ce1;
-static unsigned old_mode_sclk;
-static unsigned old_mode_miso;
-static unsigned old_mode_mosi;
-
-static uint32_t old_spi_cs;
-static uint32_t old_spi_clk;
-
-static unsigned old_mode_ace0;
-static unsigned old_mode_ace1;
-static unsigned old_mode_ace2;
-static unsigned old_mode_asclk;
-static unsigned old_mode_amiso;
-static unsigned old_mode_amosi;
-
-static uint32_t old_spi_cntl0;
-static uint32_t old_spi_cntl1;
-
static uint32_t _spiTXBits(char *buf, int pos, int bitlen, int msbf)
{
uint32_t bits=0;
@@ -3767,7 +3816,7 @@ static void spiInit(uint32_t flags)
}
}
-void spiTerm(uint32_t flags)
+static void spiTerm(uint32_t flags)
{
int resvd;
@@ -6341,8 +6390,9 @@ static void initClearGlobals(void)
notifyBits = 0;
scriptBits = 0;
- libInitialised = 0;
- DMAstarted = 0;
+ libInitialised = 0;
+ DMAstarted = 0;
+ terminating = 0;
pthAlertRunning = 0;
pthFifoRunning = 0;
@@ -6598,19 +6648,22 @@ static void initReleaseResources(void)
int initInitialise(void)
{
- int i;
+ int rev, i;
struct sockaddr_in server;
char * portStr;
unsigned port;
struct sched_param param;
+ pthread_attr_t pthAttr;
+
+ DBG(DBG_STARTUP, "");
+
+ if (libInitialised) return PIGPIO_VERSION;
waveClockInited = 0;
clock_gettime(CLOCK_REALTIME, &libStarted);
- DBG(DBG_STARTUP, "");
-
- if (libInitialised) return PIGPIO_VERSION;
+ rev = gpioHardwareRevision();
initClearGlobals();
@@ -6623,13 +6676,11 @@ int initInitialise(void)
if (!gpioMaskSet)
{
- i = gpioHardwareRevision();
-
- if (i == 0) gpioMask = PI_DEFAULT_UPDATE_MASK_R0;
- else if (i == 17) gpioMask = PI_DEFAULT_UPDATE_MASK_COMPUTE;
- else if (i < 4) gpioMask = PI_DEFAULT_UPDATE_MASK_R1;
- else if (i < 16) gpioMask = PI_DEFAULT_UPDATE_MASK_R2;
- else gpioMask = PI_DEFAULT_UPDATE_MASK_R3;
+ if (rev == 0) gpioMask = PI_DEFAULT_UPDATE_MASK_R0;
+ else if (rev == 17) gpioMask = PI_DEFAULT_UPDATE_MASK_COMPUTE;
+ else if (rev < 4) gpioMask = PI_DEFAULT_UPDATE_MASK_R1;
+ else if (rev < 16) gpioMask = PI_DEFAULT_UPDATE_MASK_R2;
+ else gpioMask = PI_DEFAULT_UPDATE_MASK_R3;
gpioMaskSet = 1;
}
@@ -6937,10 +6988,14 @@ void gpioTerminate(void)
DBG(DBG_USER, "");
- gpioMaskSet = 0;
+ terminating = 1;
if (libInitialised)
{
+ libInitialised = 0;
+
+ gpioMaskSet = 0;
+
/* reset DMA */
DMAstarted = 0;
@@ -6948,8 +7003,6 @@ void gpioTerminate(void)
dmaIn[DMA_CS] = DMA_CHANNEL_RESET;
dmaOut[DMA_CS] = DMA_CHANNEL_RESET;
- libInitialised = 0;
-
if (gpioCfg.showStats)
{
fprintf(stderr,
@@ -8573,6 +8626,8 @@ static int intGpioSetTimerFunc(unsigned id,
int user,
void *userdata)
{
+ pthread_attr_t pthAttr;
+
DBG(DBG_INTERNAL, "id=%d millis=%d function=%08X user=%d userdata=%08X",
id, millis, (uint32_t)f, user, (uint32_t)userdata);
@@ -8587,6 +8642,14 @@ static int intGpioSetTimerFunc(unsigned id,
if (!gpioTimer[id].running)
{
+ if (pthread_attr_init(&pthAttr))
+ SOFT_ERROR(PI_TIMER_FAILED,
+ "pthread_attr_init failed (%m)");
+
+ if (pthread_attr_setstacksize(&pthAttr, STACK_SIZE))
+ SOFT_ERROR(PI_TIMER_FAILED,
+ "pthread_attr_setstacksize failed (%m)");
+
if (pthread_create(
&gpioTimer[id].pthId, &pthAttr, pthTimerTick, &gpioTimer[id]))
SOFT_ERROR(PI_TIMER_FAILED,
@@ -9377,7 +9440,7 @@ unsigned gpioHardwareRevision(void)
chars = 4;
pi_peri_phys = 0x20000000;
pi_dram_bus = 0x40000000;
- pi_mem_flag = 0x0c;
+ pi_mem_flag = 0x0C;
}
else if (strstr (buf, "ARMv7") != NULL)
{
diff --git a/pigpio.h b/pigpio.h
index be6e813..69afbc8 100644
--- a/pigpio.h
+++ b/pigpio.h
@@ -31,7 +31,7 @@ For more information, please refer to
#include
#include
-#define PIGPIO_VERSION 30
+#define PIGPIO_VERSION 31
/*TEXT
@@ -319,6 +319,8 @@ OVERVIEW*/
#define PI_LOCKFILE "/var/run/pigpio.pid"
+#define PI_I2C_COMBINED "/sys/module/i2c_bcm2708/parameters/combined"
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -399,6 +401,29 @@ uint32_t next;
uint32_t pad[2];
} rawCbs_t;
+/* max pi_i2c_msg_t per transaction */
+
+#define PI_I2C_RDRW_IOCTL_MAX_MSGS 42
+
+/* flags for pi_i2c_msg_t */
+
+#define PI_I2C_M_WR 0x0000 /* write data */
+#define PI_I2C_M_RD 0x0001 /* read data */
+#define PI_I2C_M_TEN 0x0010 /* ten bit chip address */
+#define PI_I2C_M_RECV_LEN 0x0400 /* length will be first received byte */
+#define PI_I2C_M_NO_RD_ACK 0x0800 /* if I2C_FUNC_PROTOCOL_MANGLING */
+#define PI_I2C_M_IGNORE_NAK 0x1000 /* if I2C_FUNC_PROTOCOL_MANGLING */
+#define PI_I2C_M_REV_DIR_ADDR 0x2000 /* if I2C_FUNC_PROTOCOL_MANGLING */
+#define PI_I2C_M_NOSTART 0x4000 /* if I2C_FUNC_PROTOCOL_MANGLING */
+
+typedef struct
+{
+ uint16_t addr; /* slave address */
+ uint16_t flags;
+ uint16_t len; /* msg length */
+ uint8_t *buf; /* pointer to msg data */
+} pi_i2c_msg_t;
+
typedef void (*gpioAlertFunc_t) (int gpio,
int level,
uint32_t tick);
@@ -1699,7 +1724,6 @@ user_gpio: 0-31, previously opened with [*gpioSerialReadOpen*]
Returns 0 if OK, otherwise PI_BAD_USER_GPIO, or PI_NOT_SERIAL_GPIO.
D*/
-
/*F*/
int i2cOpen(unsigned i2cBus, unsigned i2cAddr, unsigned i2cFlags);
/*D
@@ -1715,6 +1739,22 @@ No flags are currently defined. This parameter should be set to zero.
Returns a handle (>=0) if OK, otherwise PI_BAD_I2C_BUS, PI_BAD_I2C_ADDR,
PI_BAD_FLAGS, PI_NO_HANDLE, or PI_I2C_OPEN_FAILED.
+
+For the smbus commands the low level transactions are shown at the end
+of the function description. The following abbreviations are used.
+
+. .
+S (1 bit) : Start bit
+P (1 bit) : Stop bit
+Rd/Wr (1 bit) : Read/Write bit. Rd equals 1, Wr equals 0.
+A, NA (1 bit) : Accept and not accept bit.
+Addr (7 bits): I2C 7 bit address.
+Comm (8 bits): Command byte, a data byte which often selects a register.
+Data (8 bits): A data byte.
+Count (8 bits): A data byte containing the length of a block operation.
+
+[..]: Data sent by the device.
+. .
D*/
@@ -1762,6 +1802,10 @@ Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or
PI_I2C_WRITE_FAILED.
D*/
+int i2cTransaction(unsigned handle, pi_i2c_msg_t *parts, unsigned numParts);
+/*
+This performs a combined I2C transction made up of count parts.
+*/
/*F*/
int i2cWriteQuick(unsigned handle, unsigned bit);
@@ -1778,6 +1822,9 @@ Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or
PI_I2C_WRITE_FAILED.
Quick command. smbus 2.0 5.5.1
+. .
+S Addr Rd/Wr [A] P
+. .
D*/
@@ -1795,6 +1842,9 @@ Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or
PI_I2C_WRITE_FAILED.
Send byte. smbus 2.0 5.5.2
+. .
+S Addr Wr [A] Data [A] P
+. .
D*/
@@ -1811,6 +1861,9 @@ Returns the byte read (>=0) if OK, otherwise PI_BAD_HANDLE,
or PI_I2C_READ_FAILED.
Receive byte. smbus 2.0 5.5.3
+. .
+S Addr Rd [A] [Data] NA P
+. .
D*/
@@ -1830,6 +1883,9 @@ Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or
PI_I2C_WRITE_FAILED.
Write byte. smbus 2.0 5.5.4
+. .
+S Addr Wr [A] Comm [A] Data [A] P
+. .
D*/
@@ -1849,6 +1905,9 @@ Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or
PI_I2C_WRITE_FAILED.
Write word. smbus 2.0 5.5.4
+. .
+S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A] P
+. .
D*/
@@ -1867,6 +1926,9 @@ Returns the byte read (>=0) if OK, otherwise PI_BAD_HANDLE,
PI_BAD_PARAM, or PI_I2C_READ_FAILED.
Read byte. smbus 2.0 5.5.5
+. .
+S Addr Wr [A] Comm [A] S Addr Rd [A] [Data] NA P
+. .
D*/
@@ -1885,6 +1947,9 @@ Returns the word read (>=0) if OK, otherwise PI_BAD_HANDLE,
PI_BAD_PARAM, or PI_I2C_READ_FAILED.
Read word. smbus 2.0 5.5.5
+. .
+S Addr Wr [A] Comm [A] S Addr Rd [A] [DataLow] A [DataHigh] NA P
+. .
D*/
@@ -1904,6 +1969,10 @@ Returns the word read (>=0) if OK, otherwise PI_BAD_HANDLE,
PI_BAD_PARAM, or PI_I2C_READ_FAILED.
Process call. smbus 2.0 5.5.6
+. .
+S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A]
+ S Addr Rd [A] [DataLow] A [DataHigh] NA P
+. .
D*/
@@ -1925,6 +1994,9 @@ Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or
PI_I2C_WRITE_FAILED.
Block write. smbus 2.0 5.5.7
+. .
+S Addr Wr [A] Comm [A] Count [A] Data [A] Data [A] ... [A] Data [A] P
+. .
D*/
@@ -1946,6 +2018,10 @@ Returns the number of bytes read (>=0) if OK, otherwise PI_BAD_HANDLE,
PI_BAD_PARAM, or PI_I2C_READ_FAILED.
Block read. smbus 2.0 5.5.7
+. .
+S Addr Wr [A] Comm [A]
+ S Addr Rd [A] [Count] A [Data] A [Data] A ... A [Data] NA P
+. .
D*/
@@ -1972,6 +2048,10 @@ sent and a minimum of 1 byte may be received. The total number of
bytes sent/received must be 32 or less.
Block write-block read. smbus 2.0 5.5.8
+. .
+S Addr Wr [A] Comm [A] Count [A] Data [A] ...
+ S Addr Rd [A] [Count] A [Data] ... A P
+. .
D*/
@@ -1991,6 +2071,11 @@ i2cReg: 0-255, the register to read
Returns the number of bytes read (>0) if OK, otherwise PI_BAD_HANDLE,
PI_BAD_PARAM, or PI_I2C_READ_FAILED.
+
+. .
+S Addr Wr [A] Comm [A]
+ S Addr Rd [A] [Data] A [Data] A ... A [Data] NA P
+. .
D*/
@@ -2010,6 +2095,10 @@ i2cReg: 0-255, the register to write
Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or
PI_I2C_WRITE_FAILED.
+
+. .
+S Addr Wr [A] Comm [A] Data [A] Data [A] ... [A] Data [A] P
+. .
D*/
@@ -3742,38 +3831,47 @@ numBits::
The number of bits stored in a buffer.
numBytes::
-
The number of bytes used to store characters in a string. Depending
on the number of bits per character there may be 1, 2, or 4 bytes
per character.
numPar:: 0-10
-
The number of parameters passed to a script.
-numPulses::
+numParts::
+The number of parts in a combined I2C transaction.
+numPulses::
The number of pulses to be added to a waveform.
offset::
-
The associated data starts this number of microseconds from the start of
tghe waveform.
*param::
-
An array of script parameters.
-port:: 1024-32000
+*parts::
+An array of the part transactions which make up a combined I2C transaction.
+pi_i2c_msg_t::
+. .
+typedef struct
+{
+ uint16_t addr; // slave address
+ uint16_t flags;
+ uint16_t len; // msg length
+ uint8_t *buf; // pointer to msg data
+} pi_i2c_msg_t;
+. .
+
+port:: 1024-32000
The port used to bind to the pigpio socket. Defaults to 8888.
pos::
-
The position of an item.
primaryChannel:: 0-14
-
The DMA channel used to time the sampling of gpios and to time servo and
PWM pulses.
@@ -4323,6 +4421,9 @@ after this command is issued.
#define PI_BAD_STOPBITS -102 // serial (half) stop bits not 2-8
#define PI_MSG_TOOBIG -103 // socket/pipe message too big
#define PI_BAD_MALLOC_MODE -104 // bad memory allocation mode
+#define PI_TOO_MANY_PARTS -105 // too many I2C transaction parts
+#define PI_BAD_I2C_PART -106 // a combined I2C transaction failed
+
#define PI_PIGIF_ERR_0 -2000
#define PI_PIGIF_ERR_99 -2099