From 0407f9e45974b8747b8ec5e0715f85f9ad0bc713 Mon Sep 17 00:00:00 2001 From: joan Date: Tue, 12 Aug 2014 18:47:26 +0100 Subject: [PATCH] V18 --- command.c | 4 +- pigpio.3 | 106 +++++++++++++- pigpio.c | 388 +++++++++++++++++++++++++++++++++---------------- pigpio.h | 73 ++++++++-- pigpio.py | 75 +++++++--- pigpiod_if.3 | 102 ++++++++++++- pigpiod_if.c | 11 +- pigpiod_if.h | 55 ++++++- pigs.1 | 97 +++++++++++-- pigs.c | 26 ++-- setup.py | 2 +- x_pigpio.py | 6 +- x_pigpiod_if.c | 4 +- x_pigs | 2 +- x_pipe | 2 +- 15 files changed, 738 insertions(+), 215 deletions(-) diff --git a/command.c b/command.c index 5bdf55e..36f8f9e 100644 --- a/command.c +++ b/command.c @@ -26,7 +26,7 @@ For more information, please refer to */ /* -This version is for pigpio version 17+ +This version is for pigpio version 18+ */ #include @@ -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"}, diff --git a/pigpio.3 b/pigpio.3 index 533bb46..a5efe76 100644 --- a/pigpio.3 +++ b/pigpio.3 @@ -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 diff --git a/pigpio.c b/pigpio.c index 0bd05f9..aae1355 100644 --- a/pigpio.c +++ b/pigpio.c @@ -25,7 +25,7 @@ OTHER DEALINGS IN THE SOFTWARE. For more information, please refer to */ -/* pigpio version 17 */ +/* pigpio version 18 */ #include #include @@ -54,7 +54,6 @@ For more information, please refer to #include #include #include -#include #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_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= 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)); diff --git a/pigpio.h b/pigpio.h index 91ae30a..f9f0916 100644 --- a/pigpio.h +++ b/pigpio.h @@ -31,7 +31,7 @@ For more information, please refer to #include #include -#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 diff --git a/pigpio.py b/pigpio.py index a20a4bc..184255e 100644 --- a/pigpio.py +++ b/pigpio.py @@ -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). diff --git a/pigpiod_if.3 b/pigpiod_if.3 index 5fa5c23..d0029bd 100644 --- a/pigpiod_if.3 +++ b/pigpiod_if.3 @@ -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 diff --git a/pigpiod_if.c b/pigpiod_if.c index 4ac663e..62d852e 100644 --- a/pigpiod_if.c +++ b/pigpiod_if.c @@ -25,7 +25,7 @@ OTHER DEALINGS IN THE SOFTWARE. For more information, please refer to */ -/* PIGPIOD_IF_VERSION 6 */ +/* PIGPIOD_IF_VERSION 7 */ #include #include @@ -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; diff --git a/pigpiod_if.h b/pigpiod_if.h index d99c17d..796debb 100644 --- a/pigpiod_if.h +++ b/pigpiod_if.h @@ -30,7 +30,7 @@ For more information, please refer to #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. diff --git a/pigs.1 b/pigs.1 index 4154690..d3ad8a3 100644 --- a/pigs.1 +++ b/pigs.1 @@ -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 diff --git a/pigs.c b/pigs.c index 7840420..23d9bfe 100644 --- a/pigs.c +++ b/pigs.c @@ -26,7 +26,7 @@ For more information, please refer to */ /* -This version is for pigpio version 17+ +This version is for pigpio version 18+ */ #include @@ -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= 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: diff --git a/setup.py b/setup.py index 34b0e30..f4021f5 100644 --- a/setup.py +++ b/setup.py @@ -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', diff --git a/x_pigpio.py b/x_pigpio.py index 42c139d..005206e 100755 --- a/x_pigpio.py +++ b/x_pigpio.py @@ -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") diff --git a/x_pigpiod_if.c b/x_pigpiod_if.c index 9b7ca4f..7570849 100644 --- a/x_pigpiod_if.c +++ b/x_pigpiod_if.c @@ -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"); diff --git a/x_pigs b/x_pigs index 9411d5d..38e35d6 100755 --- a/x_pigs +++ b/x_pigs @@ -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 diff --git a/x_pipe b/x_pipe index 1ffb59e..ff28e1e 100755 --- a/x_pipe +++ b/x_pipe @@ -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/pigpio read -t 1 s