This commit is contained in:
joan 2014-08-12 18:47:26 +01:00
parent 517b42acff
commit 0407f9e459
15 changed files with 738 additions and 215 deletions

View File

@ -26,7 +26,7 @@ For more information, please refer to <http://unlicense.org/>
*/
/*
This version is for pigpio version 17+
This version is for pigpio version 18+
*/
#include <stdio.h>
@ -411,7 +411,7 @@ static errInfo_t errInfo[]=
{PI_BAD_WVSC_COMMND , "bad WVSC subcommand"},
{PI_BAD_WVSM_COMMND , "bad WVSM subcommand"},
{PI_BAD_WVSP_COMMND , "bad WVSP subcommand"},
{PI_BAD_PULSELEN , "trigger pulse > 50 microseconds"},
{PI_BAD_PULSELEN , "trigger pulse > 100 microseconds"},
{PI_BAD_SCRIPT , "invalid script"},
{PI_BAD_SCRIPT_ID , "unknown script id"},
{PI_BAD_SER_OFFSET , "add serial data offset > 30 minute"},

106
pigpio.3
View File

@ -2363,8 +2363,10 @@ PI_I2C_WRITE_FAILED.
.IP "\fBint spiOpen(unsigned spiChan, unsigned spiBaud, unsigned spiFlags)\fP"
.IP "" 4
This function returns a handle for the SPI device on the channel
Data will be transferred at baud bits per second.
This function returns a handle for the SPI device on the channel.
Data will be transferred at baud bits per second. The flags may
be used to modify the default behaviour of 4-wire operation, mode 0,
active low chip select.
.br
@ -2375,7 +2377,7 @@ Data will be transferred at baud bits per second.
.br
spiBaud: >1
.br
spiFlags: 0-3
spiFlags: 0-0xFF
.br
.EE
@ -2389,7 +2391,24 @@ PI_BAD_SPI_SPEED, PI_BAD_FLAGS, or PI_SPI_OPEN_FAILED.
.br
.br
The least significant two bits of flags define the SPI mode.
spiFlags consists of the least significant 8 bits.
.br
.br
.EX
7 6 5 4 3 2 1 0
.br
n n n n W P m m
.br
.EE
.br
.br
mm defines the SPI mode.
.br
@ -2411,6 +2430,23 @@ Mode POL PHA
.br
.br
P is 0 for active low chip select (normal) and 1 for active high.
.br
.br
W is 0 if the device is not 3-wire, 1 if the device is 3-wire.
.br
.br
nnnn defines the number of bytes (0-15) to write before switching
the MOSI line to MISO to read data. This field is ignored
if W is not set.
.br
.br
The other bits in flags should be set to zero.
@ -5483,8 +5519,64 @@ A SPI channel, 0 or 1.
.br
.br
Flags which modify a SPI open command. The two least significant bits
define the SPI mode. The other bits are undefined.
spiFlags consists of the least significant 8 bits.
.br
.br
.EX
7 6 5 4 3 2 1 0
.br
n n n n W P m m
.br
.EE
.br
.br
mm defines the SPI mode.
.br
.br
.EX
Mode POL PHA
.br
0 0 0
.br
1 0 1
.br
2 1 0
.br
3 1 1
.br
.EE
.br
.br
P is 0 for active low chip select (normal) and 1 for active high.
.br
.br
W is 0 if the device is not 3-wire, 1 if the device is 3-wire.
.br
.br
nnnn defines the number of bytes (0-15) to write before switching
the MOSI line to MISO to read data. This field is ignored
if W is not set.
.br
.br
The other bits in flags should be set to zero.
.br
@ -5992,7 +6084,7 @@ A 16-bit word value.
.br
#define PI_BAD_WVSP_COMMND -45 // bad WVSP subcommand
.br
#define PI_BAD_PULSELEN -46 // trigger pulse length > 50
#define PI_BAD_PULSELEN -46 // trigger pulse length > 100
.br
#define PI_BAD_SCRIPT -47 // invalid script
.br

388
pigpio.c
View File

@ -25,7 +25,7 @@ OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>
*/
/* pigpio version 17 */
/* pigpio version 18 */
#include <stdio.h>
#include <string.h>
@ -54,7 +54,6 @@ For more information, please refer to <http://unlicense.org/>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <sys/select.h>
#include <linux/spi/spidev.h>
#include "pigpio.h"
@ -293,17 +292,18 @@ bit 0 READ_LAST_NOT_SET_ERROR
#define GPIO_BASE 0x20200000
#define PCM_BASE 0x20203000
#define PWM_BASE 0x2020C000
#define SPI0_BASE 0x20204000
#define SPI_BASE 0x20204000
#define SYST_BASE 0x20003000
#define UART0_BASE 0x20201000
#define UART1_BASE 0x20215000
#define DMA_LEN 0x1000 /* allow access to all channels */
#define CLK_LEN 0xA8
#define DMA_LEN 0x1000 /* allow access to all channels */
#define GPIO_LEN 0xB4
#define SYST_LEN 0x1C
#define PCM_LEN 0x24
#define PWM_LEN 0x28
#define SPI_LEN 0x18
#define SYST_LEN 0x1C
#define DMA_ENABLE (0xFF0/4)
@ -482,6 +482,59 @@ bit 0 READ_LAST_NOT_SET_ERROR
#define SYST_CLO 1
#define SYST_CHI 2
/* SPI */
#define SPI_CS 0
#define SPI_FIFO 1
#define SPI_CLK 2
#define SPI_DLEN 3
#define SPI_LTOH 4
#define SPI_DC 5
#define SPI_CS_LEN_LONG (1<<25)
#define SPI_CS_DMA_LEN (1<<24)
#define SPI_CS_CSPOL2 (1<<23)
#define SPI_CS_CSPOL1 (1<<22)
#define SPI_CS_CSPOL0 (1<<21)
#define SPI_CS_RXF (1<<20)
#define SPI_CS_RXR (1<<19)
#define SPI_CS_TXD (1<<18)
#define SPI_CS_RXD (1<<17)
#define SPI_CS_DONE (1<<16)
#define SPI_CS_LEN (1<<13)
#define SPI_CS_REN (1<<12)
#define SPI_CS_ADCS (1<<11)
#define SPI_CS_INTR (1<<10)
#define SPI_CS_INTD (1<<9)
#define SPI_CS_DMAEN (1<<8)
#define SPI_CS_TA (1<<7)
#define SPI_CS_CSPOL(x) ((x)<<6)
#define SPI_CS_CLEAR(x) ((x)<<4)
#define SPI_CS_MODE(x) ((x)<<2)
#define SPI_CS_CS(x) ((x)<<0)
#define SPI_DC_RPANIC(x) ((x)<<24)
#define SPI_DC_RDREQ(x) ((x)<<16)
#define SPI_DC_TPANIC(x) ((x)<<8)
#define SPI_DC_TDREQ(x) ((x)<<0)
#define SPI_MODE0 0
#define SPI_MODE1 1
#define SPI_MODE2 2
#define SPI_MODE3 3
#define SPI_CS0 0
#define SPI_CS1 1
#define SPI_CS2 2
/* SPI gpios. */
#define PI_SPI_CE0 8
#define PI_SPI_CE1 7
#define PI_SPI_SCLK 11
#define PI_SPI_MISO 9
#define PI_SPI_MOSI 10
/* --------------------------------------------------------------- */
#define NORMAL_DMA (DMA_NO_WIDE_BURSTS | DMA_WAIT_RESP)
@ -570,8 +623,6 @@ bit 0 READ_LAST_NOT_SET_ERROR
#define SRX_BUF_SIZE 8192
#define MAX_DELAY 50
#define PI_I2C_SLAVE 0x0703
#define PI_I2C_SMBUS 0x0720
@ -726,7 +777,6 @@ typedef struct
typedef struct
{
uint16_t state;
int16_t fd;
unsigned speed;
uint32_t flags;
} spiInfo_t;
@ -937,6 +987,7 @@ static volatile uint32_t * dmaReg = MAP_FAILED;
static volatile uint32_t * gpioReg = MAP_FAILED;
static volatile uint32_t * pcmReg = MAP_FAILED;
static volatile uint32_t * pwmReg = MAP_FAILED;
static volatile uint32_t * spiReg = MAP_FAILED;
static volatile uint32_t * systReg = MAP_FAILED;
static volatile uint32_t * dmaIn = MAP_FAILED;
@ -1057,7 +1108,7 @@ static uint32_t myGpioDelay(uint32_t micros)
start = systReg[SYST_CLO];
if (micros <= MAX_DELAY) while ((systReg[SYST_CLO] - start) <= micros);
if (micros <= PI_MAX_BUSY_DELAY) while ((systReg[SYST_CLO] - start) <= micros);
else myGpioSleep(micros/MILLION, micros%MILLION);
@ -2801,31 +2852,187 @@ int i2cClose(unsigned handle)
/* ======================================================================= */
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 uint32_t spi_dummy; /* only used to prevent warning */
static void spiInit(void)
{
old_mode_ce0 = gpioGetMode(PI_SPI_CE0);
old_mode_ce1 = gpioGetMode(PI_SPI_CE1);
old_mode_sclk = gpioGetMode(PI_SPI_SCLK);
old_mode_miso = gpioGetMode(PI_SPI_MISO);
old_mode_mosi = gpioGetMode(PI_SPI_MOSI);
gpioSetMode(PI_SPI_CE0, PI_ALT0);
gpioSetMode(PI_SPI_CE1, PI_ALT0);
gpioSetMode(PI_SPI_SCLK, PI_ALT0);
gpioSetMode(PI_SPI_MISO, PI_ALT0);
gpioSetMode(PI_SPI_MOSI, PI_ALT0);
old_spi_cs = spiReg[SPI_CS];
old_spi_clk = spiReg[SPI_CLK];
}
static void spiTerm(void)
{
gpioSetMode(PI_SPI_CE0, old_mode_ce0);
gpioSetMode(PI_SPI_CE1, old_mode_ce1);
gpioSetMode(PI_SPI_SCLK, old_mode_sclk);
gpioSetMode(PI_SPI_MISO, old_mode_miso);
gpioSetMode(PI_SPI_MOSI, old_mode_mosi);
spiReg[SPI_CS] = old_spi_cs;
spiReg[SPI_CLK] = old_spi_clk;
}
#define PI_SPI_FLAGS_CHAN(x) ((x)<<30)
/*
3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
C C - - - - - - - - - - - - - - - - - - - - - - N N N N 3 P M M
CC channel
NNNN switch to 3-wire after NNNN bytes
3 3-wire part
P CS polarity
MM mode
*/
static void spiGo(
unsigned speed,
uint32_t flags,
char *txBuf,
char *rxBuf,
unsigned count)
{
unsigned txCnt=0;
unsigned rxCnt=0;
unsigned cnt, cnt4w, cnt3w;
uint32_t spiDefaults;
unsigned mode, channel, cspol, flag3w, ren3w;
mode = flags & 3;
cspol = (flags >> 2) & 1;
flag3w = (flags >> 3) & 1;
ren3w = (flags >> 4) & 15;
channel = (flags >> 30) & 3;
spiDefaults = SPI_CS_MODE(mode) |
SPI_CS_CS(channel) |
SPI_CS_CSPOL(cspol) |
SPI_CS_CLEAR(3);
if (flag3w)
{
if (ren3w < count)
{
cnt4w = ren3w;
cnt3w = count - ren3w;
}
else
{
cnt4w = count;
cnt3w = 0;
}
}
else
{
cnt4w = count;
cnt3w = 0;
}
spiReg[SPI_CLK] = 250000000/speed;
spiReg[SPI_CS] = spiDefaults | SPI_CS_TA; /* start */
cnt = cnt4w;
while((txCnt < cnt) || (rxCnt < cnt))
{
while((txCnt < cnt) && ((spiReg[SPI_CS] & SPI_CS_TXD)))
{
if (txBuf) spiReg[SPI_FIFO] = txBuf[txCnt];
else spiReg[SPI_FIFO] = 0;
txCnt++;
}
while((rxCnt < cnt) && ((spiReg[SPI_CS] & SPI_CS_RXD)))
{
if (rxBuf) rxBuf[rxCnt] = spiReg[SPI_FIFO];
else spi_dummy = spiReg[SPI_FIFO];
rxCnt++;
}
}
while (!(spiReg[SPI_CS] & SPI_CS_DONE)) ;
/* now switch to 3-wire bus */
cnt += cnt3w;
while((txCnt < cnt) || (rxCnt < cnt))
{
spiReg[SPI_CS] |= SPI_CS_REN;
while((txCnt < cnt) && ((spiReg[SPI_CS] & SPI_CS_TXD)))
{
if (txBuf) spiReg[SPI_FIFO] = txBuf[txCnt];
else spiReg[SPI_FIFO] = 0;
txCnt++;
}
while((rxCnt < cnt) && ((spiReg[SPI_CS] & SPI_CS_RXD)))
{
if (rxBuf) rxBuf[rxCnt] = spiReg[SPI_FIFO];
else spi_dummy = spiReg[SPI_FIFO];
rxCnt++;
}
}
while (!(spiReg[SPI_CS] & SPI_CS_DONE)) ;
spiReg[SPI_CS] = spiDefaults; /* stop */
}
static int spiAnyOpen(void)
{
int i;
for (i=0; i<PI_SPI_SLOTS; i++)
{
if (spiInfo[i].state == PI_SPI_OPENED) return 1;
}
return 0;
}
int spiOpen(unsigned spiChan, unsigned spiBaud, unsigned spiFlags)
{
int i, slot, fd;
char spiMode;
char spiBits = 8;
char dev[32];
int i, slot;
DBG(DBG_USER, "spiChan=%d spiBaud=%d spiFlags=0x%X",
spiChan, spiBaud, spiFlags);
CHECK_INITED;
spiMode = spiFlags & 3;
spiBits = 8;
if (spiChan >= PI_NUM_SPI_CHANNEL)
SOFT_ERROR(PI_BAD_SPI_CHANNEL, "bad spiChan (%d)", spiChan);
if (!spiBaud)
SOFT_ERROR(PI_BAD_SPI_SPEED, "bad spiBaud (%d)", spiBaud);
if (spiFlags > 3)
if (spiFlags > 256)
SOFT_ERROR(PI_BAD_FLAGS, "bad spiFlags (0x%X)", spiFlags);
if (!spiAnyOpen()) spiInit(); /* initialise on first open */
slot = -1;
for (i=0; i<PI_SPI_SLOTS; i++)
@ -2841,47 +3048,8 @@ int spiOpen(unsigned spiChan, unsigned spiBaud, unsigned spiFlags)
if (slot < 0)
SOFT_ERROR(PI_NO_HANDLE, "no SPI handles");
sprintf(dev, "/dev/spidev0.%d", spiChan);
if ((fd = open(dev, O_RDWR)) < 0)
{
/* try a modprobe */
system("/sbin/modprobe spi_bcm2708");
usleep(100000);
if ((fd = open(dev, O_RDWR)) < 0)
{
i2cInfo[slot].state = PI_SPI_CLOSED;
return PI_SPI_OPEN_FAILED;
}
}
if (ioctl(fd, SPI_IOC_WR_MODE, &spiMode) < 0)
{
close(fd);
spiInfo[slot].state = PI_SPI_CLOSED;
return PI_SPI_OPEN_FAILED;
}
if (ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &spiBits) < 0)
{
close(fd);
spiInfo[slot].state = PI_SPI_CLOSED;
return PI_SPI_OPEN_FAILED;
}
if (ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &spiBaud) < 0)
{
close(fd);
spiInfo[slot].state = PI_SPI_CLOSED;
return PI_SPI_OPEN_FAILED;
}
spiInfo[slot].fd = fd;
spiInfo[slot].speed = spiBaud;
spiInfo[slot].flags = spiFlags;
spiInfo[slot].flags = spiFlags | PI_SPI_FLAGS_CHAN(spiChan);
return slot;
}
@ -2898,20 +3066,15 @@ int spiClose(unsigned handle)
if (spiInfo[handle].state != PI_SPI_OPENED)
SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
if (spiInfo[handle].fd >= 0) close(spiInfo[handle].fd);
spiInfo[handle].fd = -1;
spiInfo[handle].state = PI_I2C_CLOSED;
if (!spiAnyOpen()) spiTerm(); /* terminate on last close */
return 0;
}
int spiRead(unsigned handle, char *buf, unsigned count)
{
int err;
struct spi_ioc_transfer spi;
DBG(DBG_USER, "handle=%d count=%d [%s]",
handle, count, myBuf2Str(count, buf));
@ -2926,25 +3089,13 @@ int spiRead(unsigned handle, char *buf, unsigned count)
if ((count < 1) || (count > PI_MAX_SPI_DEVICE_COUNT))
SOFT_ERROR(PI_BAD_SPI_COUNT, "bad count (%d)", count);
spi.tx_buf = (unsigned) NULL;
spi.rx_buf = (unsigned) buf;
spi.len = count;
spi.speed_hz = spiInfo[handle].speed;
spi.delay_usecs = 0;
spi.bits_per_word = 8;
spi.cs_change = 0;
spiGo(spiInfo[handle].speed, spiInfo[handle].flags, NULL, buf, count);
err = ioctl(spiInfo[handle].fd, SPI_IOC_MESSAGE(1), &spi);
if (err < 0) return PI_SPI_XFER_FAILED;
else return err;
return count;
}
int spiWrite(unsigned handle, char *buf, unsigned count)
{
int err;
struct spi_ioc_transfer spi;
DBG(DBG_USER, "handle=%d count=%d [%s]",
handle, count, myBuf2Str(count, buf));
@ -2959,25 +3110,13 @@ int spiWrite(unsigned handle, char *buf, unsigned count)
if ((count < 1) || (count > PI_MAX_SPI_DEVICE_COUNT))
SOFT_ERROR(PI_BAD_SPI_COUNT, "bad count (%d)", count);
spi.tx_buf = (unsigned) buf;
spi.rx_buf = (unsigned) NULL;
spi.len = count;
spi.speed_hz = spiInfo[handle].speed;
spi.delay_usecs = 0;
spi.bits_per_word = 8;
spi.cs_change = 0;
spiGo(spiInfo[handle].speed, spiInfo[handle].flags, buf, NULL, count);
err = ioctl(spiInfo[handle].fd, SPI_IOC_MESSAGE(1), &spi);
if (err < 0) return PI_SPI_XFER_FAILED;
else return err;
return count;
}
int spiXfer(unsigned handle, char *txBuf, char *rxBuf, unsigned count)
{
int err;
struct spi_ioc_transfer spi;
DBG(DBG_USER, "handle=%d count=%d [%s]",
handle, count, myBuf2Str(count, txBuf));
@ -2992,18 +3131,9 @@ int spiXfer(unsigned handle, char *txBuf, char *rxBuf, unsigned count)
if ((count < 1) || (count > PI_MAX_SPI_DEVICE_COUNT))
SOFT_ERROR(PI_BAD_SPI_COUNT, "bad count (%d)", count);
spi.tx_buf = (unsigned long)txBuf;
spi.rx_buf = (unsigned long)rxBuf;
spi.len = count;
spi.speed_hz = spiInfo[handle].speed;
spi.delay_usecs = 0;
spi.bits_per_word = 8;
spi.cs_change = 0;
spiGo(spiInfo[handle].speed, spiInfo[handle].flags, txBuf, rxBuf, count);
err = ioctl(spiInfo[handle].fd, SPI_IOC_MESSAGE(1), &spi);
if (err < 0) return PI_SPI_XFER_FAILED;
else return err;
return count;
}
/* ======================================================================= */
@ -4562,17 +4692,28 @@ static void *pthSocketThreadHandler(void *fdC)
buf[p[3]] = 0;
if (p[0] != PI_CMD_NOIB)
switch (p[0])
{
p[3] = myDoCommand(p, sizeof(buf)-1, buf);
}
else
{
p[3] = gpioNotifyOpenInBand(sock);
case PI_CMD_NOIB:
p[3] = gpioNotifyOpenInBand(sock);
/* Enable the Nagle algorithm. */
opt = 0;
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)&opt, sizeof(int));
/* Enable the Nagle algorithm. */
opt = 0;
setsockopt(
sock, IPPROTO_TCP, TCP_NODELAY, (char*)&opt, sizeof(int));
break;
case PI_CMD_PROCP:
p[3] = myDoCommand(p, sizeof(buf)-1, buf+sizeof(int));
if (p[3] >= 0)
{
memcpy(buf, &p[3], 4);
p[3] = 4 + (4*PI_MAX_SCRIPT_PARAMS);
}
break;
default:
p[3] = myDoCommand(p, sizeof(buf)-1, buf);
}
write(sock, p, 16);
@ -4585,6 +4726,7 @@ static void *pthSocketThreadHandler(void *fdC)
case PI_CMD_I2CRD:
case PI_CMD_I2CRI:
case PI_CMD_I2CRK:
case PI_CMD_PROCP:
case PI_CMD_SERR:
case PI_CMD_SLR:
case PI_CMD_SPIX:
@ -4596,14 +4738,6 @@ static void *pthSocketThreadHandler(void *fdC)
}
break;
case PI_CMD_PROCP:
if (p[3] >= 0)
{
write(sock, buf, sizeof(uint32_t)*PI_MAX_SCRIPT_PARAMS);
}
break;
default:
break;
}
@ -4830,6 +4964,11 @@ static int initPeripherals(void)
if (systReg == MAP_FAILED)
SOFT_ERROR(PI_INIT_FAILED, "mmap syst failed (%m)");
spiReg = initMapMem(fdMem, SPI_BASE, SPI_LEN);
if (spiReg == MAP_FAILED)
SOFT_ERROR(PI_INIT_FAILED, "mmap spi failed (%m)");
pwmReg = initMapMem(fdMem, PWM_BASE, PWM_LEN);
if (pwmReg == MAP_FAILED)
@ -5298,6 +5437,7 @@ static void initClearGlobals(void)
pcmReg = MAP_FAILED;
pwmReg = MAP_FAILED;
systReg = MAP_FAILED;
spiReg = MAP_FAILED;
}
/* ----------------------------------------------------------------------- */
@ -5351,6 +5491,7 @@ static void initReleaseResources(void)
if (pcmReg != MAP_FAILED) munmap((void *)pcmReg, PCM_LEN);
if (pwmReg != MAP_FAILED) munmap((void *)pwmReg, PWM_LEN);
if (systReg != MAP_FAILED) munmap((void *)systReg, SYST_LEN);
if (spiReg != MAP_FAILED) munmap((void *)spiReg, SPI_LEN);
clkReg = MAP_FAILED;
dmaReg = MAP_FAILED;
@ -5358,6 +5499,7 @@ static void initReleaseResources(void)
pcmReg = MAP_FAILED;
pwmReg = MAP_FAILED;
systReg = MAP_FAILED;
spiReg = MAP_FAILED;
if (dmaVirt != MAP_FAILED)
{
@ -7132,7 +7274,7 @@ int gpioTrigger(unsigned gpio, unsigned pulseLen, unsigned level)
if (level > PI_ON)
SOFT_ERROR(PI_BAD_LEVEL, "gpio %d, bad level (%d)", gpio, level);
if ((pulseLen > PI_MAX_PULSELEN) || (!pulseLen))
if ((pulseLen > PI_MAX_BUSY_DELAY) || (!pulseLen))
SOFT_ERROR(PI_BAD_PULSELEN,
"gpio %d, bad pulseLen (%d)", gpio, pulseLen);
@ -7476,7 +7618,7 @@ int gpioScriptStatus(unsigned script_id, uint32_t *param)
if (gpioScript[script_id].state == PI_SCRIPT_IN_USE)
{
if (param != 0)
if (param != NULL)
{
memcpy(param, gpioScript[script_id].script.par,
sizeof(uint32_t) * PI_MAX_SCRIPT_PARAMS);
@ -7773,7 +7915,7 @@ uint32_t gpioDelay(uint32_t micros)
start = systReg[SYST_CLO];
if (micros <= MAX_DELAY) while ((systReg[SYST_CLO] - start) <= micros);
if (micros <= PI_MAX_BUSY_DELAY) while ((systReg[SYST_CLO] - start) <= micros);
else gpioSleep(PI_TIME_RELATIVE, (micros/MILLION), (micros%MILLION));

View File

@ -31,7 +31,7 @@ For more information, please refer to <http://unlicense.org/>
#include <stdint.h>
#include <pthread.h>
#define PIGPIO_VERSION 17
#define PIGPIO_VERSION 18
/*TEXT
@ -481,10 +481,11 @@ typedef void *(gpioThreadFunc_t) (void *);
#define PI_WAVE_MODE_ONE_SHOT 0
#define PI_WAVE_MODE_REPEAT 1
#define PI_I2C_SLOTS 32
#define PI_SPI_SLOTS 4
#define PI_SER_SLOTS 4
/* I2C, SPI, SER */
#define PI_I2C_SLOTS 32
#define PI_SPI_SLOTS 8
#define PI_SER_SLOTS 8
#define PI_NUM_I2C_BUS 2
#define PI_NUM_SPI_CHANNEL 2
@ -492,7 +493,14 @@ typedef void *(gpioThreadFunc_t) (void *);
#define PI_MAX_I2C_DEVICE_COUNT 8192
#define PI_MAX_SPI_DEVICE_COUNT 8192
#define PI_MAX_PULSELEN 50
#define PI_SPI_FLAGS_3WREN(x) ((x)<<4)
#define PI_SPI_FLAGS_3WIRE(x) ((x)<<3)
#define PI_SPI_FLAGS_CSPOL(x) ((x)<<2)
#define PI_SPI_FLAGS_MODE(x) ((x)<<0)
/* Longest busy delay */
#define PI_MAX_BUSY_DELAY 100
/* timeout: 0-60000 */
@ -1873,19 +1881,28 @@ D*/
/*F*/
int spiOpen(unsigned spiChan, unsigned spiBaud, unsigned spiFlags);
/*D
This function returns a handle for the SPI device on the channel
Data will be transferred at baud bits per second.
This function returns a handle for the SPI device on the channel.
Data will be transferred at baud bits per second. The flags may
be used to modify the default behaviour of 4-wire operation, mode 0,
active low chip select.
. .
spiChan: 0-1
spiBaud: >1
spiFlags: 0-3
spiFlags: 0-0xFF
. .
Returns a handle (>=0) if OK, otherwise PI_BAD_SPI_CHANNEL,
PI_BAD_SPI_SPEED, PI_BAD_FLAGS, or PI_SPI_OPEN_FAILED.
The least significant two bits of flags define the SPI mode.
spiFlags consists of the least significant 8 bits.
. .
7 6 5 4 3 2 1 0
n n n n W P m m
. .
mm defines the SPI mode.
. .
Mode POL PHA
@ -1895,6 +1912,14 @@ Mode POL PHA
3 1 1
. .
P is 0 for active low chip select (normal) and 1 for active high.
W is 0 if the device is not 3-wire, 1 if the device is 3-wire.
nnnn defines the number of bytes (0-15) to write before switching
the MOSI line to MISO to read data. This field is ignored
if W is not set.
The other bits in flags should be set to zero.
D*/
@ -3521,8 +3546,32 @@ A SPI channel, 0 or 1.
spiFlags::
Flags which modify a SPI open command. The two least significant bits
define the SPI mode. The other bits are undefined.
spiFlags consists of the least significant 8 bits.
. .
7 6 5 4 3 2 1 0
n n n n W P m m
. .
mm defines the SPI mode.
. .
Mode POL PHA
0 0 0
1 0 1
2 1 0
3 1 1
. .
P is 0 for active low chip select (normal) and 1 for active high.
W is 0 if the device is not 3-wire, 1 if the device is 3-wire.
nnnn defines the number of bytes (0-15) to write before switching
the MOSI line to MISO to read data. This field is ignored
if W is not set.
The other bits in flags should be set to zero.
spiSS::
@ -3809,7 +3858,7 @@ after this command is issued.
#define PI_BAD_WVSC_COMMND -43 // bad WVSC subcommand
#define PI_BAD_WVSM_COMMND -44 // bad WVSM subcommand
#define PI_BAD_WVSP_COMMND -45 // bad WVSP subcommand
#define PI_BAD_PULSELEN -46 // trigger pulse length > 50
#define PI_BAD_PULSELEN -46 // trigger pulse length > 100
#define PI_BAD_SCRIPT -47 // invalid script
#define PI_BAD_SCRIPT_ID -48 // unknown script id
#define PI_BAD_SER_OFFSET -49 // add serial data offset > 30 minutes

View File

@ -246,7 +246,7 @@ import os
import atexit
import codecs
VERSION = "1.7"
VERSION = "1.8"
exceptions = True
@ -532,7 +532,7 @@ _errors=[
[PI_BAD_WVSC_COMMND , "bad WVSC subcommand"],
[PI_BAD_WVSM_COMMND , "bad WVSM subcommand"],
[PI_BAD_WVSP_COMMND , "bad WVSP subcommand"],
[PI_BAD_PULSELEN , "trigger pulse length > 50"],
[PI_BAD_PULSELEN , "trigger pulse length > 100"],
[PI_BAD_SCRIPT , "invalid script"],
[PI_BAD_SCRIPT_ID , "unknown script id"],
[PI_BAD_SER_OFFSET , "add serial data offset > 30 minute"],
@ -2129,7 +2129,10 @@ class pi():
def spi_open(self, spi_channel, spi_baud, spi_flags=0):
"""
Returns a handle for the SPI device on channel.
Returns a handle for the SPI device on channel. Data will be
transferred at baud bits per second. The flags may be used to
modify the default behaviour of 4-wire operation, mode 0,
active low chip select.
spi_channel:= 0 or 1, the SPI channel.
spi_baud:= >0, the transmission rate in bits per second.
@ -2140,20 +2143,32 @@ class pi():
you will always run on the local Pi use the standard SPI
modules instead.
The bottom two bits of spi_flags define the SPI mode as
follows.
spiFlags consists of the least significant 8 bits.
. .
bit bit
1 0
POL PHA Mode
0 0 0
0 1 1
1 0 2
1 1 3
7 6 5 4 3 2 1 0
n n n n W P m m
. .
The other bits in spi_flags should be set to zero.
mm defines the SPI mode.
. .
Mode POL PHA
0 0 0
1 0 1
2 1 0
3 1 1
. .
P is 0 for active low chip select (normal) and 1 for active high.
W is 0 if the device is not 3-wire, 1 if the device is 3-wire.
nnnn defines the number of bytes (0-15) to write before switching
the MOSI line to MISO to read data. This field is ignored
if W is not set.
The other bits in flags should be set to zero.
...
# open SPI device on channel 1 in mode 3 at 20000 bits per second
@ -2507,9 +2522,9 @@ class pi():
...
"""
status = _u2i(_pigpio_command(self._control, _PI_CMD_PROCP, script_id, 0))
if status >= 0:
param = struct.unpack('IIIIIIIIII', self._control.recv(40))
return status, param
if status > 0:
params = struct.unpack('I10i', self._control.recv(44))
return params[0], params[1:]
return status, ()
def stop_script(self, script_id):
@ -2975,7 +2990,33 @@ def xref():
A SPI channel.
spi_flags: 32 bit
The flags are used to encode the SPI mode in bits 0 and 1.
spi_flags consists of the least significant 8 bits.
. .
7 6 5 4 3 2 1 0
n n n n W P m m
. .
mm defines the SPI mode.
. .
Mode POL PHA
0 0 0
1 0 1
2 1 0
3 1 1
. .
P is 0 for active low chip select (normal) and 1 for active high.
W is 0 if the device is not 3-wire, 1 if the device is 3-wire.
nnnn defines the number of bytes (0-15) to write before switching
the MOSI line to MISO to read data. This field is ignored
if W is not set.
The other bits in flags should be set to zero.
t1:
A tick (earlier).

View File

@ -2165,7 +2165,9 @@ PI_I2C_WRITE_FAILED.
.IP "\fBint spi_open(unsigned spi_channel, unsigned spi_baud, unsigned spi_flags)\fP"
.IP "" 4
This function returns a handle for the SPI device on channel.
Data will be transferred at baud bits per second.
Data will be transferred at baud bits per second. The flags may
be used to modify the default behaviour of 4-wire operation, mode 0,
active low chip select.
.br
@ -2176,7 +2178,7 @@ spi_channel: 0-1.
.br
spi_baud: >1.
.br
spi_flags: 0-3.
spi_flags: see below.
.br
.EE
@ -2190,17 +2192,30 @@ PI_BAD_SPI_SPEED, PI_BAD_FLAGS, or PI_SPI_OPEN_FAILED.
.br
.br
The least significant two bits of flags define the SPI mode as follows.
spiFlags consists of the least significant 8 bits.
.br
.br
.EX
bit bit
7 6 5 4 3 2 1 0
.br
1 0
n n n n W P m m
.br
.EE
.br
.br
mm defines the SPI mode.
.br
.br
.EX
Mode POL PHA
.br
0 0 0
@ -2216,6 +2231,23 @@ Mode POL PHA
.br
.br
P is 0 for active low chip select (normal) and 1 for active high.
.br
.br
W is 0 if the device is not 3-wire, 1 if the device is 3-wire.
.br
.br
nnnn defines the number of bytes (0-15) to write before switching
the MOSI line to MISO to read data. This field is ignored
if W is not set.
.br
.br
The other bits in flags should be set to zero.
@ -3193,8 +3225,64 @@ A SPI channel, 0 or 1.
.br
.IP "\fBspi_flags\fP" 0
Flags which modify a SPI open command. The two least significant bits
define the SPI mode. The other bits are undefined.
spi_flags consists of the least significant 8 bits.
.br
.br
.EX
7 6 5 4 3 2 1 0
.br
n n n n W P m m
.br
.EE
.br
.br
mm defines the SPI mode.
.br
.br
.EX
Mode POL PHA
.br
0 0 0
.br
1 0 1
.br
2 1 0
.br
3 1 1
.br
.EE
.br
.br
P is 0 for active low chip select (normal) and 1 for active high.
.br
.br
W is 0 if the device is not 3-wire, 1 if the device is 3-wire.
.br
.br
nnnn defines the number of bytes (0-15) to write before switching
the MOSI line to MISO to read data. This field is ignored
if W is not set.
.br
.br
The other bits in flags should be set to zero.
.br

View File

@ -25,7 +25,7 @@ OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>
*/
/* PIGPIOD_IF_VERSION 6 */
/* PIGPIOD_IF_VERSION 7 */
#include <stdio.h>
#include <stdlib.h>
@ -777,16 +777,17 @@ int run_script(unsigned script_id, unsigned numPar, uint32_t *param)
int script_status(unsigned script_id, uint32_t *param)
{
int status;
uint32_t p[PI_MAX_SCRIPT_PARAMS];
uint32_t p[PI_MAX_SCRIPT_PARAMS+1]; /* space for script status */
status = pigpio_command(gPigCommand, PI_CMD_PROCP, script_id, 0);
if (status >= 0)
if (status > 0)
{
/* get the data */
recv(gPigCommand, p, sizeof(p), MSG_WAITALL);
recv(gPigCommand, p, status, MSG_WAITALL);
if (param) memcpy(param, p, sizeof(p));
status = p[0];
if (param) memcpy(param, p+1, sizeof(p)-4);
}
return status;

View File

@ -30,7 +30,7 @@ For more information, please refer to <http://unlicense.org/>
#include "pigpio.h"
#define PIGPIOD_IF_VERSION 6
#define PIGPIOD_IF_VERSION 7
/*TEXT
@ -1562,22 +1562,29 @@ D*/
int spi_open(unsigned spi_channel, unsigned spi_baud, unsigned spi_flags);
/*D
This function returns a handle for the SPI device on channel.
Data will be transferred at baud bits per second.
Data will be transferred at baud bits per second. The flags may
be used to modify the default behaviour of 4-wire operation, mode 0,
active low chip select.
. .
spi_channel: 0-1.
spi_baud: >1.
spi_flags: 0-3.
spi_flags: see below.
. .
Returns a handle (>=0) if OK, otherwise PI_BAD_SPI_CHANNEL,
PI_BAD_SPI_SPEED, PI_BAD_FLAGS, or PI_SPI_OPEN_FAILED.
The least significant two bits of flags define the SPI mode as follows.
spiFlags consists of the least significant 8 bits.
. .
7 6 5 4 3 2 1 0
n n n n W P m m
. .
mm defines the SPI mode.
. .
bit bit
1 0
Mode POL PHA
0 0 0
1 0 1
@ -1585,6 +1592,14 @@ Mode POL PHA
3 1 1
. .
P is 0 for active low chip select (normal) and 1 for active high.
W is 0 if the device is not 3-wire, 1 if the device is 3-wire.
nnnn defines the number of bytes (0-15) to write before switching
the MOSI line to MISO to read data. This field is ignored
if W is not set.
The other bits in flags should be set to zero.
D*/
@ -2087,8 +2102,32 @@ spi_channel::
A SPI channel, 0 or 1.
spi_flags::
Flags which modify a SPI open command. The two least significant bits
define the SPI mode. The other bits are undefined.
spi_flags consists of the least significant 8 bits.
. .
7 6 5 4 3 2 1 0
n n n n W P m m
. .
mm defines the SPI mode.
. .
Mode POL PHA
0 0 0
1 0 1
2 1 0
3 1 1
. .
P is 0 for active low chip select (normal) and 1 for active high.
W is 0 if the device is not 3-wire, 1 if the device is 3-wire.
nnnn defines the number of bytes (0-15) to write before switching
the MOSI line to MISO to read data. This field is ignored
if W is not set.
The other bits in flags should be set to zero.
*str::
An array of characters.

97
pigs.1
View File

@ -2172,21 +2172,56 @@ This command returns a handle to a SPI device on channel \fBc\fP.
.br
.br
Data will be transferred at \fBb\fP bits per second. The least
significant two bits of the flags \fBspf\fP determine the SPI mode. All
other bits in \fBspf\fP should be set to zero.
Data will be transferred at \fBb\fP bits per second. The flags \fBspf\fP
may be used to modify the default behaviour of 4-wire operation,
mode 0, active low chip select.
.br
The flags consists of the least significant 8 bits.
.br
.EX
Flags Mode
0 0
1 1
2 2
3 3
7 6 5 4 3 2 1 0
.br
n n n n W P m m
.br
.EE
.br
mm defines the SPI mode.
.br
.EX
Mode POL PHA
.br
0 0 0
.br
1 0 1
.br
2 1 0
.br
3 1 1
.br
.EE
.br
P is 0 for active low chip select (normal) and 1 for active high.
.br
W is 0 if the device is not 3-wire, 1 if the device is 3-wire.
.br
nnnn defines the number of bytes (0-15) to write before switching
the MOSI line to MISO to read data. This field is ignored
if W is not set.
.br
The other bits in flags should be set to zero.
.br
Upon success a handle (>=0) is returned. On error a negative status code
will be returned.
@ -3152,8 +3187,50 @@ The command expects a script id as returned by a call to \fBPROC\fP.
.br
.IP "\fBspf\fP - SPI flags (32 bits)" 0
The command expects a flag value. The least significant two bits
define the SPI mode.
The flags consists of the least significant 8 bits.
.br
.EX
7 6 5 4 3 2 1 0
.br
n n n n W P m m
.br
.EE
.br
mm defines the SPI mode.
.br
.EX
Mode POL PHA
.br
0 0 0
.br
1 0 1
.br
2 1 0
.br
3 1 1
.br
.EE
.br
P is 0 for active low chip select (normal) and 1 for active high.
.br
W is 0 if the device is not 3-wire, 1 if the device is 3-wire.
.br
nnnn defines the number of bytes (0-15) to write before switching
the MOSI line to MISO to read data. This field is ignored
if W is not set.
.br
The other bits in flags should be set to zero.
.br

26
pigs.c
View File

@ -26,7 +26,7 @@ For more information, please refer to <http://unlicense.org/>
*/
/*
This version is for pigpio version 17+
This version is for pigpio version 18+
*/
#include <stdio.h>
@ -155,15 +155,18 @@ void print_result(int sock, int rv, cmdCmd_t cmd)
break;
case 7: /* PROCP */
printf("%d", r);
if (r < 0) fatal("ERROR: %s", cmdErrStr(r));
if (r >= 0)
if (r != (4 + (4*PI_MAX_SCRIPT_PARAMS)))
{
printf("%d", r);
fatal("ERROR: %s", cmdErrStr(r));
}
else
{
p = (uint32_t *)response_buf;
printf("%d", p[0]);
for (i=0; i<PI_MAX_SCRIPT_PARAMS; i++)
{
printf(" %d", p[i]);
printf(" %d", p[i+1]);
}
}
printf("\n");
@ -175,20 +178,11 @@ void get_extensions(int sock, int command, int res)
{
switch (command)
{
case PI_CMD_PROCP:
if (res >= 0)
{
recv(sock,
response_buf,
sizeof(uint32_t)*PI_MAX_SCRIPT_PARAMS,
MSG_WAITALL);
}
break;
case PI_CMD_I2CPK:
case PI_CMD_I2CRD:
case PI_CMD_I2CRI:
case PI_CMD_I2CRK:
case PI_CMD_PROCP:
case PI_CMD_SERR:
case PI_CMD_SLR:
case PI_CMD_SPIX:

View File

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

View File

@ -610,7 +610,7 @@ def ta():
# this test needs RXD and TXD to be connected
h = pi.serial_open("/dev/ttyAMA0", 57600)
CHECK(10, 1, h, 0, 0, "serial open")
CHECK(10, 1, h>=0, 1, 0, "serial open")
(b, s) = pi.serial_read(h, 1000) # flush buffer
@ -666,7 +666,7 @@ def tb():
# this test requires an ADXL345 on I2C bus 1 addr 0x53
h = pi.i2c_open(1, 0x53)
CHECK(11, 1, h, 0, 0, "i2c open")
CHECK(11, 1, h>=0, 1, 0, "i2c open")
e = pi.i2c_write_device(h, "\x00") # move to known register
CHECK(11, 2, e, 0, 0, "i2c write device")
@ -747,7 +747,7 @@ def tc():
# this test requires a MCP3202 on SPI channel 1
h = pi.spi_open(1, 50000)
CHECK(12, 1, h, 0, 0, "spi open")
CHECK(12, 1, h>=0, 1, 0, "spi open")
(b, d) = pi.spi_xfer(h, [1,128,0])
CHECK(12, 2, b, 3, 0, "spi xfer")

View File

@ -601,11 +601,11 @@ void t9()
time_sleep(0.1);
e = script_status(s, p);
if (e != PI_SCRIPT_RUNNING) break;
if (p[9] < 1900) stop_script(s);
if (p[9] < 1600) stop_script(s);
}
c = t9_count - oc;
time_sleep(0.1);
CHECK(9, 3, c, 110, 10, "run/stop script/script status");
CHECK(9, 3, c, 410, 10, "run/stop script/script status");
e = delete_script(s);
CHECK(9, 4, e, 0, 0, "delete script");

2
x_pigs
View File

@ -86,7 +86,7 @@ s=$(pigs pfs $GPIO 800)
if [[ $s = 800 ]]; then echo "PFS-b ok"; else echo "PFS-b fail ($s)"; fi
s=$(pigs pigpv)
if [[ $s = 17 ]]; then echo "PIGPV ok"; else echo "PIGPV fail ($s)"; fi
if [[ $s = 18 ]]; then echo "PIGPV ok"; else echo "PIGPV fail ($s)"; fi
s=$(pigs prs $GPIO 255)
if [[ $s = 250 ]]; then echo "PRG-a ok"; else echo "PRG-a fail ($s)"; fi

2
x_pipe
View File

@ -119,7 +119,7 @@ if [[ $s = 800 ]]; then echo "PFS-b ok"; else echo "PFS-b fail ($s)"; fi
echo "pigpv" >/dev/pigpio
read -t 1 s </dev/pigout
if [[ $s = 17 ]]; then echo "PIGPV ok"; else echo "PIGPV fail ($s)"; fi
if [[ $s = 18 ]]; then echo "PIGPV ok"; else echo "PIGPV fail ($s)"; fi
echo "prs $GPIO 255" >/dev/pigpio
read -t 1 s </dev/pigout