This commit is contained in:
joan 2015-02-02 21:11:28 +00:00
parent 84b06fca73
commit 624ecb6fb0
11 changed files with 858 additions and 343 deletions

View File

@ -1,3 +1,4 @@
#
CC = gcc
AR = ar
RANLIB = ranlib
@ -80,12 +81,12 @@ $(LIB2): $(OBJ2)
# generated using gcc -MM *.c
x_pigpio.o: x_pigpio.c pigpio.h
x_pigpiod_if.o: x_pigpiod_if.c
command.o: command.c pigpio.h command.h
pig2vcd.o: pig2vcd.c pigpio.h
pigpio.o: pigpio.c pigpio.h command.h
pigpio.o: pigpio.c pigpio.h command.h custom.cext
pigpiod.o: pigpiod.c pigpio.h
pigpiod_if.o: pigpiod_if.c pigpio.h command.h pigpiod_if.h
pigs.o: pigs.c pigpio.h command.h
x_pigpio.o: x_pigpio.c pigpio.h
x_pigpiod_if.o: x_pigpiod_if.c pigpiod_if.h pigpio.h

305
command.c
View File

@ -26,7 +26,7 @@ For more information, please refer to <http://unlicense.org/>
*/
/*
This version is for pigpio version 25+
This version is for pigpio version 26+
*/
#include <stdio.h>
@ -51,6 +51,9 @@ cmdInfo_t cmdInfo[]=
{PI_CMD_BS1, "BS1", 111, 1}, // gpioWrite_Bits_0_31_Set
{PI_CMD_BS2, "BS2", 111, 1}, // gpioWrite_Bits_32_53_Set
{PI_CMD_CF1, "CF1", 195, 2}, // gpioCustom1
{PI_CMD_CF2, "CF2", 195, 6}, // gpioCustom2
{PI_CMD_GDC, "GDC", 112, 2}, // gpioGetPWMdutycycle
{PI_CMD_GPW, "GPW", 112, 2}, // gpioGetServoPulsewidth
@ -217,163 +220,167 @@ cmdInfo_t cmdInfo[]=
char * cmdUsage = "\
BC1 bits Clear specified gpios in bank 1.\n\
BC2 bits Clear specified gpios in bank 2.\n\
BR1 Read bank 1 gpios.\n\
BR2 Read bank 2 gpios.\n\
BS1 bits Set specified gpios in bank 2.\n\
BS2 bits Set specified gpios in bank 2.\n\
BC1 bits Clear specified gpios in bank 1\n\
BC2 bits Clear specified gpios in bank 2\n\
BR1 Read bank 1 gpios\n\
BR2 Read bank 2 gpios\n\
BS1 bits Set specified gpios in bank 2\n\
BS2 bits Set specified gpios in bank 2\n\
\n\
GDC u Get PWM dutycycle for gpio.\n\
GPW u Get servo pulsewidth for gpio.\n\
CF1 uvs Custom function 1\n\
CF2 uvs Custom function 2\n\
\n\
H/HELP Display command help.\n\
GDC u Get PWM dutycycle for gpio\n\
GPW u Get servo pulsewidth for gpio\n\
\n\
HC g cf Set hardware clock frequency.\n\
HP g pf pdc Set hardware PWM frequency and dutycycle.\n\
H/HELP Display command help\n\
\n\
HWVER Get hardware version.\n\
HC g cf Set hardware clock frequency\n\
HP g pf pdc Set hardware PWM frequency and dutycycle\n\
\n\
I2CC h Close I2C handle.\n\
I2CO ib id if Open I2C bus and device with flags.\n\
HWVER Get hardware version\n\
\n\
I2CPC h r wv smb Process Call: exchange register with word.\n\
I2CPK h r bvs smb Block Process Call: exchange data bytes with register.\n\
I2CC h Close I2C handle\n\
I2CO ib id if Open I2C bus and device with flags\n\
\n\
I2CRB h r smb Read Byte Data: read byte from register.\n\
I2CRD h num i2c Read bytes.\n\
I2CRI h r num smb Read I2C Block Data: read bytes from register.\n\
I2CRK h r smb Read Block Data: read data from register.\n\
I2CRS h smb Read Byte: read byte.\n\
I2CRW h r smb Read Word Data: read word from register.\n\
I2CPC h r wv smb Process Call: exchange register with word\n\
I2CPK h r bvs smb Block Process Call: exchange data bytes with register\n\
\n\
I2CWB h r bv smb Write Byte Data: write byte to register.\n\
I2CWD h bvs i2c Write data.\n\
I2CWI h r bvs smb Write I2C Block Data.\n\
I2CWK h r bvs smb Write Block Data: write data to register.\n\
I2CWQ h bit smb Write Quick: write bit.\n\
I2CWS h bv smb Write Byte: write byte.\n\
I2CWW h r wv smb Write Word Data: write word to register.\n\
I2CRB h r smb Read Byte Data: read byte from register\n\
I2CRD h num i2c Read bytes\n\
I2CRI h r num smb Read I2C Block Data: read bytes from register\n\
I2CRK h r smb Read Block Data: read data from register\n\
I2CRS h smb Read Byte: read byte\n\
I2CRW h r smb Read Word Data: read word from register\n\
\n\
M/MODES g m Set gpio mode.\n\
MG/MODEG g Get gpio mode.\n\
I2CWB h r bv smb Write Byte Data: write byte to register\n\
I2CWD h bvs i2c Write data\n\
I2CWI h r bvs smb Write I2C Block Data\n\
I2CWK h r bvs smb Write Block Data: write data to register\n\
I2CWQ h bit smb Write Quick: write bit\n\
I2CWS h bv smb Write Byte: write byte\n\
I2CWW h r wv smb Write Word Data: write word to register\n\
\n\
MICS v Delay for microseconds.\n\
MILS v Delay for milliseconds.\n\
M/MODES g m Set gpio mode\n\
MG/MODEG g Get gpio mode\n\
\n\
NB h bits Start notification.\n\
NC h Close notification.\n\
NO Request a notification.\n\
NP h Pause notification.\n\
MICS v Delay for microseconds\n\
MILS v Delay for milliseconds\n\
\n\
P/PWM u v Set gpio PWM value.\n\
NB h bits Start notification\n\
NC h Close notification\n\
NO Request a notification\n\
NP h Pause notification\n\
\n\
PARSE t Validate script.\n\
P/PWM u v Set gpio PWM value\n\
\n\
PFG u Get gpio PWM frequency.\n\
PFS u v Set gpio PWM frequency.\n\
PARSE t Validate script\n\
\n\
PIGPV Get pigpio library version.\n\
PFG u Get gpio PWM frequency\n\
PFS u v Set gpio PWM frequency\n\
\n\
PRG u Get gpio PWM range.\n\
PIGPV Get pigpio library version\n\
\n\
PROC t Store script.\n\
PROCD sid Delete script.\n\
PROCP sid Get script status and parameters.\n\
PROCR sid pars Run script.\n\
PROCS sid Stop script.\n\
PRG u Get gpio PWM range\n\
\n\
PRRG u Get gpio PWM real range.\n\
PRS u v Set gpio PWM range.\n\
PROC t Store script\n\
PROCD sid Delete script\n\
PROCP sid Get script status and parameters\n\
PROCR sid pars Run script\n\
PROCS sid Stop script\n\
\n\
PUD g p Set gpio pull up/down.\n\
PRRG u Get gpio PWM real range\n\
PRS u v Set gpio PWM range\n\
\n\
R/READ g Read gpio level.\n\
PUD g p Set gpio pull up/down\n\
\n\
S/SERVO u v Set gpio servo pulsewidth.\n\
R/READ g Read gpio level\n\
\n\
SERC h Close serial handle.\n\
SERDA h Check for serial data ready to read.\n\
SERO srd srb srf Open serial device at baud with flags.\n\
S/SERVO u v Set gpio servo pulsewidth\n\
\n\
SERR h num Read bytes from serial handle.\n\
SERRB Read byte from serial handle.\n\
SERW h bvs Write bytes to serial handle.\n\
SERWB h bv Write byte to serial handle.\n\
SERC h Close serial handle\n\
SERDA h Check for serial data ready to read\n\
SERO srd srb srf Open serial device at baud with flags\n\
\n\
SLR u num Read bit bang serial data from gpio.\n\
SLRC u Close gpio for bit bang serial data.\n\
SLRO u b db Open gpio for bit bang serial data.\n\
SERR h num Read bytes from serial handle\n\
SERRB h Read byte from serial handle\n\
SERW h bvs Write bytes to serial handle\n\
SERWB h bv Write byte to serial handle\n\
\n\
SPIC h SPI close handle.\n\
SPIO sc sb sf SPI open channel at baud with flags.\n\
SPIR h num SPI read bytes from handle.\n\
SPIW h bvs SPI write bytes to handle.\n\
SPIX h bvs SPI transfer bytes to handle.\n\
SLR u num Read bit bang serial data from gpio\n\
SLRC u Close gpio for bit bang serial data\n\
SLRO u b db Open gpio for bit bang serial data\n\
\n\
T/TICK Get current tick.\n\
SPIC h SPI close handle\n\
SPIO sc sb sf SPI open channel at baud with flags\n\
SPIR h num SPI read bytes from handle\n\
SPIW h bvs SPI write bytes to handle\n\
SPIX h bvs SPI transfer bytes to handle\n\
\n\
TRIG u pl L Trigger level for micros on gpio.\n\
T/TICK Get current tick\n\
\n\
W/WRITE g L Write level to gpio.\n\
TRIG u pl L Trigger level for micros on gpio\n\
\n\
WDOG u v Set millisecond watchdog on gpio.\n\
W/WRITE g L Write level to gpio\n\
\n\
WVAG trips Wave add generic pulses.\n\
WDOG u v Set millisecond watchdog on gpio\n\
\n\
WVAG trips Wave add generic pulses\n\
WVAS u b db hb Wave add serial data for gpio u at b baud, db databits,\n\
o bvs hb (half)stopbits, offset o micros from wave start.\n\
WVBSY Check if wave busy.\n\
WVCLR Wave clear.\n\
WVCRE Create wave from added pulses.\n\
WVDEL wid Delete waves w and higher.\n\
WVGO Wave transmit (DEPRECATED).\n\
WVGOR Wave transmit repeatedly (DEPRECATED).\n\
WVHLT Wave stop.\n\
WVNEW Start a new empty wave.\n\
WVSC ws Wave get DMA control block stats.\n\
WVSM ws Wave get micros stats.\n\
WVSP ws Wave get pulses stats.\n\
WVTX wid Transmit wave as one-shot.\n\
WVTXR wid Transmit wave repeatedly.\n\
o bvs hb (half)stopbits, offset o micros from wave start\n\
WVBSY Check if wave busy\n\
WVCLR Wave clear\n\
WVCRE Create wave from added pulses\n\
WVDEL wid Delete waves w and higher\n\
WVGO Wave transmit (DEPRECATED)\n\
WVGOR Wave transmit repeatedly (DEPRECATED)\n\
WVHLT Wave stop\n\
WVNEW Start a new empty wave\n\
WVSC ws Wave get DMA control block stats\n\
WVSM ws Wave get micros stats\n\
WVSP ws Wave get pulses stats\n\
WVTX wid Transmit wave as one-shot\n\
WVTXR wid Transmit wave repeatedly\n\
\n\
bits = a mask where (1<<g) is set for each gpio g of interest.\n\
bv = byte value (0-255).\n\
bvs = one or more byte values (0-255).\n\
cf = hardware clock frequency (4689-25M).\n\
db = data bits (1-32).\n\
g = any gpio (0-53).\n\
h = handle (>=0).\n\
hb = (half) stop bits (2-8).\n\
ib = I2C bus (0-1).\n\
id = I2C device (0-127).\n\
if = I2C flags (0).\n\
L = level (0-1).\n\
m = mode (RW540123).\n\
num = number of bytes to read.\n\
o = offset (>=0).\n\
p = pud (ODU).\n\
pars = 0 to 10 parameters for script.\n\
pdc = hardware PWM dutycycle (0-1000).\n\
pf = hardware PWM frequency (5-250K).\n\
pl = pulse length (1-100).\n\
r = register.\n\
sid = script id (>=0).\n\
sb = SPI baud.\n\
sc = SPI channel (0-1).\n\
sf = SPI flags (0-3).\n\
srd = serial device (/dev/tty*).\n\
srb = serial baud rate.\n\
srf = serial flags (0).\n\
t = text.\n\
trips = 1 or more triplets of gpios on, gpios off, delay.\n\
u = user gpio (0-31).\n\
v = value.\n\
w = wave id (>=0).\n\
ws = 0=now, 1=high, 2=max.\n\
wv = word value (0-65535).\n\
bits = a mask where (1<<g) is set for each gpio g of interest\n\
bv = byte value (0-255)\n\
bvs = one or more byte values (0-255)\n\
cf = hardware clock frequency (4689-25M)\n\
db = data bits (1-32)\n\
g = any gpio (0-53)\n\
h = handle (>=0)\n\
hb = (half) stop bits (2-8)\n\
ib = I2C bus (0-1)\n\
id = I2C device (0-127)\n\
if = I2C flags (0)\n\
L = level (0-1)\n\
m = mode (RW540123)\n\
num = number of bytes to read\n\
o = offset (>=0)\n\
p = pud (ODU)\n\
pars = 0 to 10 parameters for script\n\
pdc = hardware PWM dutycycle (0-5000)\n\
pf = hardware PWM frequency (5-50K)\n\
pl = pulse length (1-100)\n\
r = register\n\
sid = script id (>=0)\n\
sb = SPI baud\n\
sc = SPI channel (0-1)\n\
sf = SPI flags (0-3)\n\
srd = serial device (/dev/tty*)\n\
srb = serial baud rate\n\
srf = serial flags (0)\n\
t = text\n\
trips = 1 or more triplets of gpios on, gpios off, delay\n\
u = user gpio (0-31)\n\
uvs = zero or more values >= 0, any after the first two must <= 255\n\
v = value\n\
w = wave id (>=0)\n\
ws = 0=now, 1=high, 2=max\n\
wv = word value (0-65535)\n\
\n\
Numbers may be entered as hex (prefix 0x), octal (prefix 0),\n\
otherwise they are assumed to be decimal.\n\
otherwise they are assumed to be decimal\n\
";
typedef struct
@ -479,8 +486,8 @@ static errInfo_t errInfo[]=
{PI_NOT_SERVO_GPIO , "gpio is not in use for servo pulses"},
{PI_NOT_HCLK_GPIO , "gpio has no hardware clock"},
{PI_NOT_HPWM_GPIO , "gpio has no hardware PWM"},
{PI_BAD_HPWM_FREQ , "hardware PWM frequency not 5-250K"},
{PI_BAD_HPWM_DUTY , "hardware PWM dutycycle not 0-1000"},
{PI_BAD_HPWM_FREQ , "hardware PWM frequency not 5-50K"},
{PI_BAD_HPWM_DUTY , "hardware PWM dutycycle not 0-5000"},
{PI_BAD_HCLK_FREQ , "hardware clock frequency not 4689-25M"},
{PI_BAD_HCLK_PASS , "need password to use hardware clock 1"},
{PI_HPWM_ILLEGAL , "illegal, PWM in use for main clock"},
@ -940,6 +947,52 @@ int cmdParse(
break;
case 195: /* CF1 CF2
Zero or more parameters, first two >=0, rest 0-255.
*/
valid = 1;
ctl->eaten += getNum(buf+ctl->eaten, &p[1], &ctl->opt[1]);
if (ctl->opt[1] == CMD_NUMERIC)
{
if ((int)p[1] >= 0)
{
ctl->eaten += getNum(buf+ctl->eaten, &p[2], &ctl->opt[2]);
if (ctl->opt[2] == CMD_NUMERIC)
{
if ((int)p[2] >= 0)
{
pars = 0;
p8 = ext;
while (pars < CMD_MAX_PARAM)
{
ctl->eaten += getNum(buf+ctl->eaten, &tp1, &to1);
if (to1 == CMD_NUMERIC)
{
if (((int)tp1>=0) && ((int)tp1<=255))
{
pars++;
*p8++ = tp1;
}
else valid = 0;
}
else break;
}
p[3] = pars;
}
else valid = 0;
}
}
else valid = 0;
}
break;
case 196: /* WVAS
gpio baud offset char...

54
custom.cext Normal file
View File

@ -0,0 +1,54 @@
/*
This version is for pigpio version 26+
If you want customised functions replace this file with your own
definitions for gpioCustom1 and gpioCustom2.
*/
#include "pigpio.h"
int gpioCustom1(unsigned arg1, unsigned arg2, char *argx, unsigned count)
{
int i;
unsigned max;
DBG(DBG_USER, "arg1=%d arg2=%d count=%d [%s]",
arg1, arg2, count, myBuf2Str(count, argx));
CHECK_INITED;
/* for dummy just return max parameter */
if (arg1 > arg2) max = arg1; else max = arg2;
for (i=0; i<count; i++) if (argx[i] > max) max = argx[i];
return max;
}
int gpioCustom2(unsigned arg1, char *argx, unsigned count,
char *retBuf, unsigned retMax)
{
int i, j, t;
DBG(DBG_USER, "arg1=%d count=%d [%s] retMax=%d",
arg1, count, myBuf2Str(count, argx), retMax);
CHECK_INITED;
/* for dummy just return argx reversed */
if (count > retMax) count = retMax;
for (i=0, j=count-1; i<=j; i++, j--)
{
/* t used as argx and retBuf may be the same buffer */
t = argx[i];
retBuf[i] = argx[j];
retBuf[j] = t;
}
return count;
}

510
pigpio.c
View File

@ -25,10 +25,11 @@ OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>
*/
/* pigpio version 25 */
/* pigpio version 26 */
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdarg.h>
@ -39,7 +40,6 @@ For more information, please refer to <http://unlicense.org/>
#include <termios.h>
#include <signal.h>
#include <errno.h>
#include <string.h>
#include <time.h>
#include <fcntl.h>
#include <sys/ioctl.h>
@ -188,7 +188,6 @@ bit 0 READ_LAST_NOT_SET_ERROR
#define BIT (1<<(gpio&0x1F))
#define CHECK_INITED \
do \
{ \
@ -286,15 +285,18 @@ bit 0 READ_LAST_NOT_SET_ERROR
#define DMA_BUS_ADR 0x40000000
#define AUX_BASE 0x20215000
#define CLK_BASE 0x20101000
#define DMA_BASE 0x20007000
#define DMA15_BASE 0x20E05000
#define GPIO_BASE 0x20200000
#define PCM_BASE 0x20203000
#define PWM_BASE 0x2020C000
#define SPI_BASE 0x20204000
#define SYST_BASE 0x20003000
static volatile unsigned int piModel = 1;
static volatile unsigned int PI_PERI_BASE = 0x20000000;
#define AUX_BASE (PI_PERI_BASE + 0x00215000)
#define CLK_BASE (PI_PERI_BASE + 0x00101000)
#define DMA_BASE (PI_PERI_BASE + 0x00007000)
#define DMA15_BASE (PI_PERI_BASE + 0x00E05000)
#define GPIO_BASE (PI_PERI_BASE + 0x00200000)
#define PCM_BASE (PI_PERI_BASE + 0x00203000)
#define PWM_BASE (PI_PERI_BASE + 0x0020C000)
#define SPI_BASE (PI_PERI_BASE + 0x00204000)
#define SYST_BASE (PI_PERI_BASE + 0x00003000)
#define AUX_LEN 0xD8
#define CLK_LEN 0xA8
@ -1257,6 +1259,14 @@ static char *myBuf2Str(unsigned count, char *buf)
/* ----------------------------------------------------------------------- */
static void myGpioWrite(unsigned gpio, unsigned level)
{
if (level == PI_OFF) *(gpioReg + GPCLR0 + BANK) = BIT;
else *(gpioReg + GPSET0 + BANK) = BIT;
}
/* ----------------------------------------------------------------------- */
static void myGpioSleep(int seconds, int micros)
{
struct timespec ts, rem;
@ -1441,6 +1451,18 @@ static int myDoCommand(uint32_t *p, unsigned bufSize, char *buf)
}
break;
case PI_CMD_CF1:
res = gpioCustom1(p[1], p[2], buf, p[3]);
break;
case PI_CMD_CF2:
/* a couple of extra precautions for untruested 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];
break;
case PI_CMD_GDC: res = gpioGetPWMdutycycle(p[1]); break;
case PI_CMD_GPW: res = gpioGetServoPulsewidth(p[1]); break;
@ -1640,7 +1662,8 @@ static int myDoCommand(uint32_t *p, unsigned bufSize, char *buf)
if (myPermit(p[1])) res = gpioServo(p[1], p[2]);
else
{
DBG(DBG_USER, "gpioServo: gpio %d, no permission to update", p[1]);
DBG(DBG_USER,
"gpioServo: gpio %d, no permission to update", p[1]);
res = PI_NOT_PERMITTED;
}
break;
@ -2072,7 +2095,7 @@ static void waveCbOPrint(int pos)
p = rawWaveCBAdr(pos);
fprintf(stderr, "i=%lx s=%lx d=%lx len=%lx s=%lx nxt=%lx\n",
fprintf(stderr, "i=%x s=%x d=%x len=%x s=%x nxt=%x\n",
p->info, p->src, p->dst, p->length, p->stride, p->next);
}
@ -2115,6 +2138,9 @@ static int errCBsOOL(int cb, int botOOL, int topOOL)
/* ----------------------------------------------------------------------- */
#define PI_WAVE_COUNT_BLOCKS 3
#define PI_WAVE_COUNT_LENGTH 10
static int wave2Cbs(unsigned wave_mode)
{
int botCB=waveOutBotCB, botOOL=waveOutBotOOL, topOOL=waveOutTopOOL;
@ -2129,6 +2155,9 @@ static int wave2Cbs(unsigned wave_mode)
rawWave_t * waves;
int b, baseCB;
uint32_t def_next;
numWaves = wfc[wfcur];
waves = wf [wfcur];
@ -2221,6 +2250,73 @@ static int wave2Cbs(unsigned wave_mode)
p->next = waveCbPOadr(botCB) | DMA_BUS_ADR;
}
if (waves[i].flags & WAVE_FLAG_COUNT)
{
if ((status = errCBsOOL(botCB+1, botOOL, topOOL-1))) return status;
baseCB = botCB;
def_next = waveCbPOadr(baseCB+(3*PI_WAVE_COUNT_BLOCKS)) | DMA_BUS_ADR;
/* set up all the OOLs */
for (b=0; b < (PI_WAVE_COUNT_BLOCKS*(PI_WAVE_COUNT_LENGTH+1)); b++)
rawWaveSetIn(b, def_next);
for (b=0; b<PI_WAVE_COUNT_BLOCKS; b++)
rawWaveSetIn( (b*(PI_WAVE_COUNT_LENGTH+1))+1,
waveCbPOadr (baseCB+((b*PI_WAVE_COUNT_BLOCKS)+3)) | DMA_BUS_ADR);
rawWaveSetIn
(((PI_WAVE_COUNT_BLOCKS-1)*(PI_WAVE_COUNT_LENGTH+1))+7, 0);
for (b=0; b<PI_WAVE_COUNT_BLOCKS; b++)
{
/* copy BOTTOM to NEXT */
p = rawWaveCBAdr(botCB++);
p->info = NORMAL_DMA;
p->src = waveOOLPOadr
(topOOL-((b+1)*(PI_WAVE_COUNT_LENGTH+1))) | DMA_BUS_ADR;
p->dst = (waveCbPOadr(botCB+1) + 20) | DMA_BUS_ADR;
p->length = 4;
p->next = waveCbPOadr(botCB) | DMA_BUS_ADR;
/* copy BOTTOM to TOP */
p = rawWaveCBAdr(botCB++);
p->info = NORMAL_DMA;
p->src = waveOOLPOadr
(topOOL-((b+1)*(PI_WAVE_COUNT_LENGTH+1))) | DMA_BUS_ADR;
p->dst = waveOOLPOadr
(topOOL-(1+(b*(PI_WAVE_COUNT_LENGTH+1)))) | DMA_BUS_ADR;
p->length = 4;
p->next = waveCbPOadr(botCB) | DMA_BUS_ADR;
/* shift all down one */
p = rawWaveCBAdr(botCB++);
p->info = NORMAL_DMA|DMA_SRC_INC|DMA_DEST_INC;
p->src = waveOOLPOadr
(topOOL-(((b+1)*(PI_WAVE_COUNT_LENGTH+1))-1)) | DMA_BUS_ADR;
p->dst = waveOOLPOadr
(topOOL-(((b+1)*(PI_WAVE_COUNT_LENGTH+1))-0)) | DMA_BUS_ADR;
p->length = PI_WAVE_COUNT_LENGTH*4;
p->next = waveCbPOadr
(baseCB+(3*PI_WAVE_COUNT_BLOCKS)) | DMA_BUS_ADR;
}
topOOL -= PI_WAVE_COUNT_BLOCKS * (PI_WAVE_COUNT_LENGTH+1);
}
if (waves[i].usDelay)
{
if ((status = errCBsOOL(botCB+1, botOOL, topOOL))) return status;
@ -2458,6 +2554,12 @@ int rawWaveAddGeneric(unsigned numIn1, rawWave_t *in1)
--level;
}
if (out[outPos].flags & WAVE_FLAG_COUNT)
{
cbs += (3*PI_WAVE_COUNT_BLOCKS);
level -= (PI_WAVE_COUNT_BLOCKS*(PI_WAVE_COUNT_LENGTH+1));
}
outPos++;
if (inPos1 >= numIn1) tNext1 = -1;
@ -3083,102 +3185,7 @@ static unsigned old_mode_amosi;
static uint32_t old_spi_cntl0;
static uint32_t old_spi_cntl1;
static void spiInit(uint32_t flags)
{
int resvd;
resvd = PI_SPI_FLAGS_GET_RESVD(flags);
if (PI_SPI_FLAGS_GET_AUX_SPI(flags))
{
/* enable module and access to registers */
auxReg[AUX_ENABLES] |= AUXENB_SPI1;
/* save original state */
old_mode_ace0 = gpioGetMode(PI_ASPI_CE0);
old_mode_ace1 = gpioGetMode(PI_ASPI_CE1);
old_mode_ace2 = gpioGetMode(PI_ASPI_CE2);
old_mode_asclk = gpioGetMode(PI_ASPI_SCLK);
old_mode_amiso = gpioGetMode(PI_ASPI_MISO);
old_mode_amosi = gpioGetMode(PI_ASPI_MOSI);
old_spi_cntl0 = auxReg[AUX_SPI0_CNTL0_REG];
old_spi_cntl1 = auxReg[AUX_SPI0_CNTL1_REG];
/* set gpios to SPI mode */
if (!(resvd&1)) gpioSetMode(PI_ASPI_CE0, PI_ALT4);
if (!(resvd&2)) gpioSetMode(PI_ASPI_CE1, PI_ALT4);
if (!(resvd&4)) gpioSetMode(PI_ASPI_CE2, PI_ALT4);
gpioSetMode(PI_ASPI_SCLK, PI_ALT4);
gpioSetMode(PI_ASPI_MISO, PI_ALT4);
gpioSetMode(PI_ASPI_MOSI, PI_ALT4);
}
else
{
/* save original state */
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);
old_spi_cs = spiReg[SPI_CS];
old_spi_clk = spiReg[SPI_CLK];
/* set gpios to SPI mode */
if (!(resvd&1)) gpioSetMode(PI_SPI_CE0, PI_ALT0);
if (!(resvd&2)) gpioSetMode(PI_SPI_CE1, PI_ALT0);
gpioSetMode(PI_SPI_SCLK, PI_ALT0);
gpioSetMode(PI_SPI_MISO, PI_ALT0);
gpioSetMode(PI_SPI_MOSI, PI_ALT0);
}
}
void spiTerm(uint32_t flags)
{
int resvd;
resvd = PI_SPI_FLAGS_GET_RESVD(flags);
if (PI_SPI_FLAGS_GET_AUX_SPI(flags))
{
/* restore original state */
if (!(resvd&1)) gpioSetMode(PI_ASPI_CE0, old_mode_ace0);
if (!(resvd&2)) gpioSetMode(PI_ASPI_CE1, old_mode_ace1);
if (!(resvd&4)) gpioSetMode(PI_ASPI_CE2, old_mode_ace2);
gpioSetMode(PI_ASPI_SCLK, old_mode_asclk);
gpioSetMode(PI_ASPI_MISO, old_mode_amiso);
gpioSetMode(PI_ASPI_MOSI, old_mode_amosi);
auxReg[AUX_SPI0_CNTL0_REG] = old_spi_cntl0;
auxReg[AUX_SPI0_CNTL1_REG] = old_spi_cntl1;
}
else
{
/* restore original state */
if (!(resvd&1)) gpioSetMode(PI_SPI_CE0, old_mode_ce0);
if (!(resvd&2)) 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;
}
}
uint32_t _spiTXBits(char *buf, int pos, int bitlen, int msbf)
static uint32_t _spiTXBits(char *buf, int pos, int bitlen, int msbf)
{
uint32_t bits=0;
@ -3194,7 +3201,8 @@ uint32_t _spiTXBits(char *buf, int pos, int bitlen, int msbf)
return bits;
}
void _spiRXBits(char *buf, int pos, int bitlen, int msbf, uint32_t bits)
static void _spiRXBits(
char *buf, int pos, int bitlen, int msbf, uint32_t bits)
{
if (buf)
{
@ -3206,18 +3214,30 @@ void _spiRXBits(char *buf, int pos, int bitlen, int msbf, uint32_t bits)
}
}
static void spiACS(int channel, int on)
{
int gpio;
void spiGoA(
switch (channel)
{
case 0: gpio = PI_ASPI_CE0; break;
case 1: gpio = PI_ASPI_CE1; break;
default: gpio = PI_ASPI_CE2; break;
}
myGpioWrite(gpio, on);
}
static void spiGoA(
unsigned speed, /* bits per second */
uint32_t flags, /* flags */
char *txBuf, /* tx buffer */
char *rxBuf, /* rx buffer */
unsigned count) /* number of bytes */
{
char bit_cs;
char bit_ir[4] = {1, 0, 1, 0};
char bit_or[4] = {0, 1, 0, 1};
char bit_ic[4] = {0, 0, 1, 1};
int cs;
char bit_ir[4] = {1, 0, 0, 1}; /* read on rising edge */
char bit_or[4] = {0, 1, 1, 0}; /* write on rising edge */
char bit_ic[4] = {0, 0, 1, 1}; /* invert clock */
int mode, bitlen, txmsbf, rxmsbf, channel;
unsigned txCnt=0;
@ -3230,6 +3250,7 @@ void spiGoA(
mode = PI_SPI_FLAGS_GET_MODE (flags);
bitlen = PI_SPI_FLAGS_GET_BITLEN (flags);
if (!bitlen) bitlen = 8;
/* correct count for word size */
@ -3240,23 +3261,35 @@ void spiGoA(
txmsbf = !PI_SPI_FLAGS_GET_TX_LSB (flags);
rxmsbf = !PI_SPI_FLAGS_GET_RX_LSB (flags);
bit_cs = ~PI_SPI_FLAGS_GET_CSPOLS(flags);
bit_cs = (1<<channel) ^ bit_cs;
bit_cs &= 7;
cs = PI_SPI_FLAGS_GET_CSPOLS(flags) & (1<<channel);
spiDefaults = AUXSPI_CNTL0_SPEED(125000000/speed) |
AUXSPI_CNTL0_CS(bit_cs) |
AUXSPI_CNTL0_IN_RISING(bit_ir[mode]) |
AUXSPI_CNTL0_OUT_RISING(bit_or[mode]) |
AUXSPI_CNTL0_INVERT_CLK(bit_ic[mode]) |
AUXSPI_CNTL0_MSB_FIRST(txmsbf) |
AUXSPI_CNTL0_SHIFT_LEN(bitlen);
auxReg[AUX_SPI0_CNTL0_REG] = AUXSPI_CNTL0_ENABLE | AUXSPI_CNTL0_CLR_FIFOS;
if (!count)
{
auxReg[AUX_SPI0_CNTL0_REG] =
AUXSPI_CNTL0_ENABLE | AUXSPI_CNTL0_CLR_FIFOS;
usleep(10);
auxReg[AUX_SPI0_CNTL0_REG] = AUXSPI_CNTL0_ENABLE | spiDefaults;
auxReg[AUX_SPI0_CNTL1_REG] = AUXSPI_CNTL1_MSB_FIRST(rxmsbf);
return;
}
auxReg[AUX_SPI0_CNTL0_REG] = AUXSPI_CNTL0_ENABLE | spiDefaults;
auxReg[AUX_SPI0_CNTL0_REG] = AUXSPI_CNTL0_ENABLE | spiDefaults;
auxReg[AUX_SPI0_CNTL1_REG] = AUXSPI_CNTL1_MSB_FIRST(rxmsbf);
spiACS(channel, cs);
while ((txCnt < count) || (rxCnt < count))
{
statusReg = auxReg[AUX_SPI0_STAT_REG];
@ -3269,7 +3302,8 @@ void spiGoA(
{
if (!rxEmpty)
{
_spiRXBits(rxBuf, rxCnt++, bitlen, rxmsbf, auxReg[AUX_SPI0_IO_REG]);
_spiRXBits(
rxBuf, rxCnt++, bitlen, rxmsbf, auxReg[AUX_SPI0_IO_REG]);
}
}
@ -3293,7 +3327,7 @@ void spiGoA(
while ((auxReg[AUX_SPI0_STAT_REG] & AUXSPI_STAT_BUSY)) ;
auxReg[AUX_SPI0_CNTL0_REG] = spiDefaults; /* stop */
spiACS(channel, !cs);
}
static void spiGoS(
@ -3322,6 +3356,10 @@ static void spiGoS(
SPI_CS_CSPOL(cspol) |
SPI_CS_CLEAR(3);
spiReg[SPI_CS] = spiDefaults; /* stop */
if (!count) return;
if (flag3w)
{
if (ren3w < count)
@ -3401,10 +3439,17 @@ static void spiGo(
char *rxBuf,
unsigned count)
{
DBG(0, "spiGo");
if (PI_SPI_FLAGS_GET_AUX_SPI(flags))
{
DBG(0, "spiGoA");
spiGoA(speed, flags, txBuf, rxBuf, count);
}
else
{
DBG(0, "spiGoS");
spiGoS(speed, flags, txBuf, rxBuf, count);
}
}
static int spiAnyOpen(uint32_t flags)
@ -3422,6 +3467,122 @@ static int spiAnyOpen(uint32_t flags)
return 0;
}
static void spiInit(uint32_t flags)
{
uint32_t resvd, cspols;
resvd = PI_SPI_FLAGS_GET_RESVD(flags);
cspols = PI_SPI_FLAGS_GET_CSPOLS(flags);
if (PI_SPI_FLAGS_GET_AUX_SPI(flags))
{
/* enable module and access to registers */
auxReg[AUX_ENABLES] |= AUXENB_SPI1;
/* save original state */
old_mode_ace0 = gpioGetMode(PI_ASPI_CE0);
old_mode_ace1 = gpioGetMode(PI_ASPI_CE1);
old_mode_ace2 = gpioGetMode(PI_ASPI_CE2);
old_mode_asclk = gpioGetMode(PI_ASPI_SCLK);
old_mode_amiso = gpioGetMode(PI_ASPI_MISO);
old_mode_amosi = gpioGetMode(PI_ASPI_MOSI);
old_spi_cntl0 = auxReg[AUX_SPI0_CNTL0_REG];
old_spi_cntl1 = auxReg[AUX_SPI0_CNTL1_REG];
/* manually control auxiliary SPI chip selects */
if (!(resvd&1))
{
gpioSetMode(PI_ASPI_CE0, PI_OUTPUT);
myGpioWrite(PI_ASPI_CE0, !(cspols&1));
}
if (!(resvd&2))
{
gpioSetMode(PI_ASPI_CE1, PI_OUTPUT);
myGpioWrite(PI_ASPI_CE1, !(cspols&2));
}
if (!(resvd&4))
{
gpioSetMode(PI_ASPI_CE2, PI_OUTPUT);
myGpioWrite(PI_ASPI_CE2, !(cspols&4));
}
/* set gpios to SPI mode */
gpioSetMode(PI_ASPI_SCLK, PI_ALT4);
gpioSetMode(PI_ASPI_MISO, PI_ALT4);
gpioSetMode(PI_ASPI_MOSI, PI_ALT4);
}
else
{
/* save original state */
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);
old_spi_cs = spiReg[SPI_CS];
old_spi_clk = spiReg[SPI_CLK];
/* set gpios to SPI mode */
if (!(resvd&1)) gpioSetMode(PI_SPI_CE0, PI_ALT0);
if (!(resvd&2)) gpioSetMode(PI_SPI_CE1, PI_ALT0);
gpioSetMode(PI_SPI_SCLK, PI_ALT0);
gpioSetMode(PI_SPI_MISO, PI_ALT0);
gpioSetMode(PI_SPI_MOSI, PI_ALT0);
}
}
void spiTerm(uint32_t flags)
{
int resvd;
resvd = PI_SPI_FLAGS_GET_RESVD(flags);
if (PI_SPI_FLAGS_GET_AUX_SPI(flags))
{
/* disable module and access to registers */
auxReg[AUX_ENABLES] &= (~AUXENB_SPI1);
/* restore original state */
if (!(resvd&1)) gpioSetMode(PI_ASPI_CE0, old_mode_ace0);
if (!(resvd&2)) gpioSetMode(PI_ASPI_CE1, old_mode_ace1);
if (!(resvd&4)) gpioSetMode(PI_ASPI_CE2, old_mode_ace2);
gpioSetMode(PI_ASPI_SCLK, old_mode_asclk);
gpioSetMode(PI_ASPI_MISO, old_mode_amiso);
gpioSetMode(PI_ASPI_MOSI, old_mode_amosi);
auxReg[AUX_SPI0_CNTL0_REG] = old_spi_cntl0;
auxReg[AUX_SPI0_CNTL1_REG] = old_spi_cntl1;
}
else
{
/* restore original state */
if (!(resvd&1)) gpioSetMode(PI_SPI_CE0, old_mode_ce0);
if (!(resvd&2)) 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;
}
}
int spiOpen(unsigned spiChan, unsigned spiBaud, unsigned spiFlags)
{
int i, slot;
@ -3434,7 +3595,7 @@ int spiOpen(unsigned spiChan, unsigned spiBaud, unsigned spiFlags)
if (PI_SPI_FLAGS_GET_AUX_SPI(spiFlags))
{
if (gpioHardwareRevision() < 16)
SOFT_ERROR(PI_NO_AUX_SPI, "no auxiliary SPI, need a B+");
SOFT_ERROR(PI_NO_AUX_SPI, "no auxiliary SPI, need a A+/B+");
i = PI_NUM_AUX_SPI_CHANNEL;
}
@ -3450,7 +3611,11 @@ int spiOpen(unsigned spiChan, unsigned spiBaud, unsigned spiFlags)
if (spiFlags > (1<<22))
SOFT_ERROR(PI_BAD_FLAGS, "bad spiFlags (0x%X)", spiFlags);
if (!spiAnyOpen(spiFlags)) spiInit(spiFlags); /* initialise on first open */
if (!spiAnyOpen(spiFlags)) /* initialise on first open */
{
spiInit(spiFlags);
spiGo(spiBaud, spiFlags, NULL, NULL, 0);
}
slot = -1;
@ -3506,7 +3671,7 @@ int spiRead(unsigned handle, char *buf, unsigned count)
if (spiInfo[handle].state != PI_SPI_OPENED)
SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
if ((count < 1) || (count > PI_MAX_SPI_DEVICE_COUNT))
if (count > PI_MAX_SPI_DEVICE_COUNT)
SOFT_ERROR(PI_BAD_SPI_COUNT, "bad count (%d)", count);
spiGo(spiInfo[handle].speed, spiInfo[handle].flags, NULL, buf, count);
@ -3527,7 +3692,7 @@ int spiWrite(unsigned handle, char *buf, unsigned count)
if (spiInfo[handle].state != PI_SPI_OPENED)
SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
if ((count < 1) || (count > PI_MAX_SPI_DEVICE_COUNT))
if (count > PI_MAX_SPI_DEVICE_COUNT)
SOFT_ERROR(PI_BAD_SPI_COUNT, "bad count (%d)", count);
spiGo(spiInfo[handle].speed, spiInfo[handle].flags, buf, NULL, count);
@ -3548,7 +3713,7 @@ int spiXfer(unsigned handle, char *txBuf, char *rxBuf, unsigned count)
if (spiInfo[handle].state != PI_SPI_OPENED)
SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
if ((count < 1) || (count > PI_MAX_SPI_DEVICE_COUNT))
if (count > PI_MAX_SPI_DEVICE_COUNT)
SOFT_ERROR(PI_BAD_SPI_COUNT, "bad count (%d)", count);
spiGo(spiInfo[handle].speed, spiInfo[handle].flags, txBuf, rxBuf, count);
@ -3842,7 +4007,7 @@ static void dmaCbPrint(int pos)
p = dmaCB2adr(pos);
fprintf(stderr, "i=%lx s=%lx d=%lx len=%lx s=%lx nxt=%lx\n",
fprintf(stderr, "i=%x s=%x d=%x len=%x s=%x nxt=%x\n",
p->info, p->src, p->dst, p->length, p->stride, p->next);
}
@ -4153,43 +4318,30 @@ static void sigHandler(int signum)
}
else
{
if (signum == SIGUSR1)
switch(signum)
{
if (gpioCfg.dbgLevel > DBG_MIN_LEVEL)
{
--gpioCfg.dbgLevel;
}
else gpioCfg.dbgLevel = DBG_MIN_LEVEL;
case SIGUSR1:
DBG(DBG_USER, "Debug level %d\n", gpioCfg.dbgLevel);
}
else if (signum == SIGUSR2)
{
if (gpioCfg.dbgLevel < DBG_MAX_LEVEL)
{
++gpioCfg.dbgLevel;
}
else gpioCfg.dbgLevel = DBG_MAX_LEVEL;
if (gpioCfg.dbgLevel > DBG_MIN_LEVEL) --gpioCfg.dbgLevel;
else gpioCfg.dbgLevel = DBG_MIN_LEVEL;
DBG(DBG_USER, "Debug level %d\n", gpioCfg.dbgLevel);
break;
DBG(DBG_USER, "Debug level %d\n", gpioCfg.dbgLevel);
}
else if (signum == SIGPIPE)
{
/* can happen when pipe/socket is remote closed */
DBG(DBG_USER, "SIGPIPE received");
}
else if (signum == SIGCHLD)
{
/* happens when system call is made */
DBG(DBG_USER, "SIGCHLD received");
}
else
{
/* exit */
case SIGUSR2:
if (gpioCfg.dbgLevel < DBG_MAX_LEVEL) ++gpioCfg.dbgLevel;
else gpioCfg.dbgLevel = DBG_MAX_LEVEL;
DBG(DBG_USER, "Debug level %d\n", gpioCfg.dbgLevel);
break;
DBG(DBG_ALWAYS, "Unhandled signal %d, terminating\n", signum);
case SIGPIPE:
case SIGCHLD:
case SIGWINCH:
DBG(DBG_USER, "signal %d ignored", signum);
break;
exit(-1);
default:
DBG(DBG_ALWAYS, "Unhandled signal %d, terminating\n", signum);
exit(-1);
}
}
}
@ -5177,6 +5329,7 @@ static void *pthSocketThreadHandler(void *fdC)
{
/* extensions */
case PI_CMD_CF2:
case PI_CMD_I2CPK:
case PI_CMD_I2CRD:
case PI_CMD_I2CRI:
@ -7090,7 +7243,8 @@ int rawWaveAddSPI(
uint32_t on_bits, off_bits;
int tx_bit_pos;
DBG(DBG_USER, "spi=%08X off=%d spiSS=%d tx=%08X, num=%d fb=%d lb=%d spiBits=%d",
DBG(DBG_USER,
"spi=%08X off=%d spiSS=%d tx=%08X, num=%d fb=%d lb=%d spiBits=%d",
(uint32_t)spi, offset, spiSS, (uint32_t)buf, spiTxBits,
spiBitFirst, spiBitLast, spiBits);
@ -8561,7 +8715,11 @@ int gpioHardwarePWM(
{
/* record the PWM frequency and dutycycle */
hw_pwm_freq[pwm] = frequency / PI_HW_PWM_RANGE;
/* currently both channels must use the same update rate */
hw_pwm_freq[0] = frequency / PI_HW_PWM_RANGE;
hw_pwm_freq[1] = frequency / PI_HW_PWM_RANGE;
hw_pwm_duty[pwm] = dutycycle;
/* Abort any waveform transmission in progress */
@ -8768,12 +8926,25 @@ unsigned gpioHardwareRevision(void)
{
while (fgets(buf, sizeof(buf), filp) != NULL)
{
if (!strncasecmp("revision\t", buf, 9))
if (!strncmp("model name", buf, 10))
{
if (strstr (buf, "ARMv6") != NULL)
{
piModel = 1;
PI_PERI_BASE = 0x20000000;
}
else if (strstr (buf, "ARMv7") != NULL)
{
piModel = 2;
PI_PERI_BASE = 0x3F000000;
}
}
if (!strncmp("Revision", buf, 8))
{
if (sscanf(buf+strlen(buf)-5, "%x%c", &rev, &term) == 2)
{
if (term == '\n') break;
rev = 0;
if (term != '\n') rev = 0;
}
}
}
@ -8897,7 +9068,6 @@ int gpioCfgInterfaces(unsigned ifFlags)
return 0;
}
/* ----------------------------------------------------------------------- */
int gpioCfgSocketPort(unsigned port)
@ -8968,3 +9138,7 @@ int gpioCfgInternals(unsigned cfgWhat, int cfgVal)
return retVal;
}
/* include any user customisations */
#include "custom.cext"

View File

@ -31,7 +31,7 @@ For more information, please refer to <http://unlicense.org/>
#include <stdint.h>
#include <pthread.h>
#define PIGPIO_VERSION 25
#define PIGPIO_VERSION 26
/*TEXT
@ -351,8 +351,9 @@ uint32_t gpioOff;
uint32_t usDelay;
} gpioPulse_t;
#define WAVE_FLAG_READ 1
#define WAVE_FLAG_TICK 2
#define WAVE_FLAG_READ 1
#define WAVE_FLAG_TICK 2
#define WAVE_FLAG_COUNT 4
typedef struct
{
@ -383,13 +384,13 @@ int clk_us; /* clock micros */
} rawSPI_t;
typedef struct { /* linux/arch/arm/mach-bcm2708/include/mach/dma.h */
unsigned long info;
unsigned long src;
unsigned long dst;
unsigned long length;
unsigned long stride;
unsigned long next;
unsigned long pad[2];
uint32_t info;
uint32_t src;
uint32_t dst;
uint32_t length;
uint32_t stride;
uint32_t next;
uint32_t pad[2];
} rawCbs_t;
typedef void (*gpioAlertFunc_t) (int gpio,
@ -479,8 +480,8 @@ typedef void *(gpioThreadFunc_t) (void *);
/* hardware PWM */
#define PI_HW_PWM_MIN_FREQ 5
#define PI_HW_PWM_MAX_FREQ 250000
#define PI_HW_PWM_RANGE 1000
#define PI_HW_PWM_MAX_FREQ 50000
#define PI_HW_PWM_RANGE 5000
/* hardware clock */
@ -2083,8 +2084,8 @@ handle: >=0, as returned by a call to [*spiOpen*]
count: the number of bytes to read
. .
Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_SPI_COUNT, or
PI_SPI_XFER_FAILED.
Returns the number of bytes transferred if OK, otherwise
PI_BAD_HANDLE, PI_BAD_SPI_COUNT, or PI_SPI_XFER_FAILED.
D*/
@ -2100,8 +2101,8 @@ handle: >=0, as returned by a call to [*spiOpen*]
count: the number of bytes to write
. .
Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_SPI_COUNT, or
PI_SPI_XFER_FAILED.
Returns the number of bytes transferred if OK, otherwise
PI_BAD_HANDLE, PI_BAD_SPI_COUNT, or PI_SPI_XFER_FAILED.
D*/
/*F*/
@ -2118,8 +2119,8 @@ handle: >=0, as returned by a call to [*spiOpen*]
count: the number of bytes to transfer
. .
Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_SPI_COUNT, or
PI_SPI_XFER_FAILED.
Returns the number of bytes transferred if OK, otherwise
PI_BAD_HANDLE, PI_BAD_SPI_COUNT, or PI_SPI_XFER_FAILED.
D*/
@ -3052,6 +3053,48 @@ Or in PI_DISABLE_SOCK_IF to disable the socket interface.
D*/
/*F*/
int gpioCustom1(unsigned arg1, unsigned arg2, char *argx, unsigned count);
/*D
This function is available for user customisation.
It returns a single integer value.
. .
arg1: >=0
arg2: >=0
argx: extra (byte) arguments
count: number of extra arguments
. .
Returns >= 0 if OK, less than 0 indicates a user defined error.
D*/
/*F*/
int gpioCustom2(unsigned arg1, char *argx, unsigned count,
char *retBuf, unsigned retMax);
/*D
This function is available for user customisation.
It differs from gpioCustom1 in that it returns an array of bytes
rather than just an integer.
The returned value is an integer indicating the number of returned bytes.
. .
arg1: >=0
argx: extra (byte) arguments
count: number of extra arguments
retBuf: buffer for returned bytes
retMax: maximum number of bytes to return
. .
Returns >= 0 if OK, less than 0 indicates a user defined error.
The number of returned bytes must be retMax or less.
D*/
/*F*/
int gpioCfgInternals(unsigned cfgWhat, int cfgVal);
/*D
@ -3686,7 +3729,7 @@ PWMduty::0-1000
The hardware PWM dutycycle.
. .
#define PI_HW_PWM_RANGE 1000
#define PI_HW_PWM_RANGE 5000
. .
PWMfreq::5-250K
@ -3694,7 +3737,7 @@ The hardware PWM frequency.
. .
#define PI_HW_PWM_MIN_FREQ 5
#define PI_HW_PWM_MAX_FREQ 250000
#define PI_HW_PWM_MAX_FREQ 50000
. .
range::25-40000
@ -4013,6 +4056,9 @@ PARAMS*/
#define PI_CMD_HC 85
#define PI_CMD_HP 86
#define PI_CMD_CF1 87
#define PI_CMD_CF2 88
#define PI_CMD_NOIB 99
/*DEF_E*/
@ -4173,13 +4219,20 @@ after this command is issued.
#define PI_NOT_SERVO_GPIO -93 // gpio is not in use for servo pulses
#define PI_NOT_HCLK_GPIO -94 // gpio has no hardware clock
#define PI_NOT_HPWM_GPIO -95 // gpio has no hardware PWM
#define PI_BAD_HPWM_FREQ -96 // hardware PWM frequency not 5-250K
#define PI_BAD_HPWM_DUTY -97 // hardware PWM dutycycle not 0-1000
#define PI_BAD_HPWM_FREQ -96 // hardware PWM frequency not 5-50K
#define PI_BAD_HPWM_DUTY -97 // hardware PWM dutycycle not 0-5000
#define PI_BAD_HCLK_FREQ -98 // hardware clock frequency not 4689-25M
#define PI_BAD_HCLK_PASS -99 // need password to use hardware clock 1
#define PI_HPWM_ILLEGAL -100 // illegal, PWM in use for main clock
#define PI_BAD_DATABITS -101 // serial data bits not 1-32
#define PI_BAD_STOPBITS -102 // serial (half) stop bits not 2-8
#define PI_MSG_TOOBIG -103 // socket/pipe message too big
#define PI_PIGIF_ERR_0 -2000
#define PI_PIGIF_ERR_99 -2099
#define PI_CUSTOM_ERR_0 -3000
#define PI_CUSTOM_ERR_999 -3999
/*DEF_E*/

View File

@ -234,6 +234,11 @@ serial_write_byte Writes a byte to a serial device
serial_data_available Returns number of bytes ready to be read
CUSTOM
custom_1 User custom function 1
custom_2 User custom function 2
Utility
get_current_tick Get current tick (microseconds)
@ -402,6 +407,9 @@ _PI_CMD_GPW =84
_PI_CMD_HC =85
_PI_CMD_HP =86
_PI_CMD_CF1 =87
_PI_CMD_CF2 =88
_PI_CMD_NOIB= 99
# pigpio error numbers
@ -606,8 +614,8 @@ _errors=[
[PI_NOT_SERVO_GPIO , "gpio is not in use for servo pulses"],
[PI_NOT_HCLK_GPIO , "gpio has no hardware clock"],
[PI_NOT_HPWM_GPIO , "gpio has no hardware PWM"],
[PI_BAD_HPWM_FREQ , "hardware PWM frequency not 5-250K"],
[PI_BAD_HPWM_DUTY , "hardware PWM dutycycle not 0-1000"],
[PI_BAD_HPWM_FREQ , "hardware PWM frequency not 5-50K"],
[PI_BAD_HPWM_DUTY , "hardware PWM dutycycle not 0-5000"],
[PI_BAD_HCLK_FREQ , "hardware clock frequency not 4689-25M"],
[PI_BAD_HCLK_PASS , "need password to use hardware clock 1"],
[PI_HPWM_ILLEGAL , "illegal, PWM in use for main clock"],
@ -1486,8 +1494,8 @@ class pi():
pigpio daemon is started (option -t).
gpio:= see descripton
PWMfreq:= 0 (off) or 5-250K
PWMduty:= 0 (off) to 1000 (fully on).
PWMfreq:= 0 (off) or 5-50K
PWMduty:= 0 (off) to 5000 (fully on).
Returns 0 if OK, otherwise PI_NOT_PERMITTED, PI_BAD_GPIO,
PI_NOT_HPWM_GPIO, PI_BAD_HPWM_DUTY, PI_BAD_HPWM_FREQ.
@ -1514,9 +1522,9 @@ class pi():
. .
...
pi.hardware_PWM(18, 800, 250) # 800Hz 25% dutycycle
pi.hardware_PWM(18, 800, 1250) # 800Hz 25% dutycycle
pi.hardware_PWM(18, 2000, 750) # 2000Hz 75% dutycycle
pi.hardware_PWM(18, 2000, 3750) # 2000Hz 75% dutycycle
...
"""
# pigpio message format
@ -2953,6 +2961,81 @@ class pi():
"""
return _u2i(_pigpio_command(self.sl, _PI_CMD_SLRC, user_gpio, 0))
def custom_1(self, arg1=0, arg2=0, argx=[]):
"""
Calls a pigpio function customised by the user.
arg1:= >=0, default 0.
arg2:= >=0, default 0.
argx:= extra arguments (each 0-255), default empty.
The returned value is an integer which by convention
should be >=0 for OK and <0 for error.
...
value = pi.custom_1()
value = pi.custom_1(23)
value = pi.custom_1(0, 55)
value = pi.custom_1(23, 56, [1, 5, 7])
value = pi.custom_1(23, 56, b"hello")
value = pi.custom_1(23, 56, "hello")
...
"""
# I p1 arg1
# I p2 arg2
# I p3 len
## extension ##
# s len argx bytes
return u2i(_pigpio_command_ext(
self.sl, _PI_CMD_CF1, arg1, arg2, len(argx), [argx]))
def custom_2(self, arg1=0, argx=[], retMax=8192):
"""
Calls a pigpio function customised by the user.
arg1:= >=0, default 0.
argx:= extra arguments (each 0-255), default empty.
retMax:= >=0, maximum number of bytes to return, default 8192.
The returned value is a tuple of the number of bytes
returned and a bytearray containing the bytes. If
there was an error the number of bytes read will be
less than zero (and will contain the error code).
...
(count, data) = pi.custom_2()
(count, data) = pi.custom_2(23)
(count, data) = pi.custom_2(23, [1, 5, 7])
(count, data) = pi.custom_2(23, b"hello")
(count, data) = pi.custom_2(23, "hello", 128)
...
"""
# I p1 arg1
# I p2 retMax
# I p3 len
## extension ##
# s len argx bytes
# Don't raise exception. Must release lock.
bytes = u2i(_pigpio_command_ext(
self.sl, _PI_CMD_CF2, arg1, retMax, len(argx), [argx], False))
if bytes > 0:
data = self._rxbuf(bytes)
else:
data = ""
self.sl.l.release()
return bytes, data
def callback(self, user_gpio, edge=RISING_EDGE, func=None):
"""
Calls a user supplied function (a callback) whenever the
@ -3043,9 +3126,6 @@ class pi():
self.sl = _socklock()
self._notify = None
self._host = ''
self._port = 8888
self._host = host
self._port = int(port)

View File

@ -1313,6 +1313,58 @@ int serial_read(unsigned handle, char *buf, unsigned count)
int serial_data_available(unsigned handle)
{return pigpio_command(gPigCommand, PI_CMD_SERDA, handle, 0, 1);}
int custom_1(unsigned arg1, unsigned arg2, char *argx, unsigned count)
{
gpioExtent_t ext[1];
/*
p1=arg1
p2=arg2
p3=count
## extension ##
char argx[count]
*/
ext[0].size = count;
ext[0].ptr = argx;
return pigpio_command_ext(
gPigCommand, PI_CMD_CF1, arg1, arg2, count, 1, ext, 1);
}
int custom_2(unsigned arg1, char *argx, unsigned count,
char *retBuf, uint32_t retMax)
{
int bytes;
gpioExtent_t ext[1];
/*
p1=arg1
p2=retMax
p3=count
## extension ##
char argx[count]
*/
ext[0].size = count;
ext[0].ptr = argx;
bytes = pigpio_command_ext
(gPigCommand, PI_CMD_CF2, arg1, retMax, count, 1, ext, 0);
if (bytes > 0)
{
/* get the data */
recv(gPigCommand, retBuf, bytes, MSG_WAITALL);
}
pthread_mutex_unlock(&command_mutex);
return bytes;
}
int callback(unsigned user_gpio, unsigned edge, CBFunc_t f)
{return intCallback(user_gpio, edge, f, 0, 0);}

View File

@ -248,6 +248,11 @@ serial_read Reads bytes from a serial device
serial_data_available Returns number of bytes ready to be read
CUSTOM
custom_1 User custom function 1
custom_2 User custom function 2
UTILITIES
get_current_tick Get current tick (microseconds)
@ -896,8 +901,8 @@ daemon is started (option -t).
. .
gpio: see descripton
PWMfreq: 0 (off) or 5-250K
PWMduty: 0 (off) to 1000 (fully on).
PWMfreq: 0 (off) or 5-50K
PWMduty: 0 (off) to 5000 (fully on).
. .
Returns 0 if OK, otherwise PI_NOT_PERMITTED, PI_BAD_GPIO,
@ -1804,8 +1809,8 @@ handle: >=0, as returned by a call to [*spi_open*].
count: the number of bytes to read.
. .
Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_SPI_COUNT, or
PI_SPI_XFER_FAILED.
Returns the number of bytes transferred if OK, otherwise
PI_BAD_HANDLE, PI_BAD_SPI_COUNT, or PI_SPI_XFER_FAILED.
D*/
/*F*/
@ -1820,8 +1825,8 @@ handle: >=0, as returned by a call to [*spi_open*].
count: the number of bytes to write.
. .
Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_SPI_COUNT, or
PI_SPI_XFER_FAILED.
Returns the number of bytes transferred if OK, otherwise
PI_BAD_HANDLE, PI_BAD_SPI_COUNT, or PI_SPI_XFER_FAILED.
D*/
/*F*/
@ -1838,8 +1843,8 @@ handle: >=0, as returned by a call to [*spi_open*].
count: the number of bytes to transfer.
. .
Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_SPI_COUNT, or
PI_SPI_XFER_FAILED.
Returns the number of bytes transferred if OK, otherwise
PI_BAD_HANDLE, PI_BAD_SPI_COUNT, or PI_SPI_XFER_FAILED.
D*/
/*F*/
@ -1944,6 +1949,48 @@ Returns the number of bytes of data available (>=0) if OK,
otherwise PI_BAD_HANDLE.
D*/
/*F*/
int custom_1(unsigned arg1, unsigned arg2, char *argx, unsigned count);
/*D
This function is available for user customisation.
It returns a single integer value.
. .
arg1: >=0
arg2: >=0
argx: extra (byte) arguments
count: number of extra arguments
. .
Returns >= 0 if OK, less than 0 indicates a user defined error.
D*/
/*F*/
int custom_2(unsigned arg1, char *argx, unsigned count,
char *retBuf, unsigned retMax);
/*D
This function is available for user customisation.
It differs from custom_1 in that it returns an array of bytes
rather than just an integer.
The return value is an integer indicating the number of returned bytes.
. .
arg1: >=0
argx: extra (byte) arguments
count: number of extra arguments
retBuf: buffer for returned data
retMax: maximum number of bytes to return
. .
Returns >= 0 if OK, less than 0 indicates a user defined error.
Note, the number of returned bytes will be retMax or less.
D*/
/*F*/
int callback(unsigned user_gpio, unsigned edge, CBFunc_t f);
/*D

5
pigs.c
View File

@ -26,7 +26,7 @@ For more information, please refer to <http://unlicense.org/>
*/
/*
This version is for pigpio version 18+
This version is for pigpio version 26+
*/
#include <stdio.h>
@ -141,7 +141,7 @@ void print_result(int sock, int rv, cmdCmd_t cmd)
printf(cmdUsage);
break;
case 6: /* I2CPK I2CRD I2CRI I2CRK SERR SLR SPIX SPIR */
case 6: /* CF2 I2CPK I2CRD I2CRI I2CRK SERR SLR SPIX SPIR */
printf("%d", r);
if (r < 0) fatal("ERROR: %s", cmdErrStr(r));
if (r > 0)
@ -178,6 +178,7 @@ void get_extensions(int sock, int command, int res)
{
switch (command)
{
case PI_CMD_CF2:
case PI_CMD_I2CPK:
case PI_CMD_I2CRD:
case PI_CMD_I2CRI:

4
x_pigs
View File

@ -1,6 +1,6 @@
#!/bin/bash
VERSION=25
VERSION=26
GPIO=4
@ -46,7 +46,7 @@ s=$(pigs bs2 0)
if [[ $s = "" ]]; then echo "BS2 ok"; else echo "BS2 fail ($s)"; fi
s=$(pigs h)
if [[ ${#s} = 5150 ]]; then echo "HELP ok"; else echo "HELP fail (${#s})"; fi
if [[ ${#s} = 5167 ]]; then echo "HELP ok"; else echo "HELP fail (${#s})"; fi
s=$(pigs hwver)
if [[ $s -ne 0 ]]; then echo "HWVER ok"; else echo "HWVER fail ($s)"; fi

6
x_pipe
View File

@ -1,6 +1,6 @@
#!/bin/bash
VERSION=25
VERSION=26
GPIO=4
@ -52,14 +52,14 @@ if [[ $s = 0 ]]; then echo "BS2 ok"; else echo "BS2 fail ($s)"; fi
echo "h" >/dev/pigpio
read -t 1 s </dev/pigout
if [[ $s = "BC1 bits Clear specified gpios in bank 1." ]]
if [[ $s = "BC1 bits Clear specified gpios in bank 1" ]]
then echo "HELP-a ok"
else echo "HELP-a fail ($s)"
fi
read -t 1 -N 9000 </dev/pigout # dump rest of help
echo "help" >/dev/pigpio
read -t 1 s </dev/pigout
if [[ $s = "BC1 bits Clear specified gpios in bank 1." ]]
if [[ $s = "BC1 bits Clear specified gpios in bank 1" ]]
then echo "HELP-b ok"
else echo "HELP-b fail ($s)"
fi