Merge branch 'BjoernSch-master'

This commit is contained in:
joan 2016-08-14 10:46:54 +01:00
commit 68ab0a9525
4 changed files with 631 additions and 17 deletions

View File

@ -49,6 +49,10 @@ cmdInfo_t cmdInfo[]=
{PI_CMD_BI2CO, "BI2CO", 131, 0}, // bbI2COpen
{PI_CMD_BI2CZ, "BI2CZ", 193, 6}, // bbI2CZip
{PI_CMD_BSPIC, "BSPIC", 112, 0}, // bbSPIClose
{PI_CMD_BSPIO, "BSPIO", 134, 0}, // bbSPIOpen
{PI_CMD_BSPIX, "BSPIX", 193, 6}, // bbSPIXfer
{PI_CMD_BR1, "BR1", 101, 3}, // gpioRead_Bits_0_31
{PI_CMD_BR2, "BR2", 101, 3}, // gpioRead_Bits_32_53
@ -256,6 +260,11 @@ BC2 bits Clear GPIO in bank 2\n\
BI2CC sda Close bit bang I2C\n\
BI2CO sda scl baud | Open bit bang I2C\n\
BI2CZ sda ... I2C bit bang multiple transactions\n\
\n\
BSPIC cs Close bit bang SPI\n\
BSPIO cs miso mosi sclk baud flag | Open bit bang SPI\n\
BSPIX cs ... SPI bit bang transfer\n\
\n\
BR1 Read bank 1 GPIO\n\
BR2 Read bank 2 GPIO\n\
BS1 bits Set GPIO in bank 1\n\
@ -529,6 +538,8 @@ static errInfo_t errInfo[]=
{PI_FILE_IS_A_DIR , "file is a directory"},
{PI_BAD_SHELL_STATUS , "bad shell return status"},
{PI_BAD_SCRIPT_NAME , "bad script name"},
{PI_BAD_SPI_BAUD , "bad SPI baud rate, not 50-500k"},
{PI_NOT_SPI_GPIO , "no bit bang SPI in progress on GPIO"},
};
@ -599,8 +610,8 @@ int cmdParse(
char *p8;
int32_t *p32;
char c;
uint32_t tp1=0, tp2=0, tp3=0;
int8_t to1, to2, to3;
uint32_t tp1=0, tp2=0, tp3=0, tp4=0, tp5=0;
int8_t to1, to2, to3, to4, to5;
int eaten;
/* Check that ext is big enough for the largest message. */
@ -653,7 +664,7 @@ int cmdParse(
case 112: /* BI2CC FC GDC GPW I2CC I2CRB
MG MICS MILS MODEG NC NP PADG PFG PRG
PROCD PROCP PROCS PRRG R READ SLRC SPIC
WVDEL WVSC WVSM WVSP WVTX WVTXR
WVDEL WVSC WVSM WVSP WVTX WVTXR BSPIC
One positive parameter.
*/
@ -914,6 +925,36 @@ int cmdParse(
break;
case 134: /* BSPIO
Six parameters. First to Fifth positive.
Sixth may be negative when interpreted as an int.
*/
ctl->eaten += getNum(buf+ctl->eaten, &p[1], &ctl->opt[1]);
ctl->eaten += getNum(buf+ctl->eaten, &tp1, &to1);
ctl->eaten += getNum(buf+ctl->eaten, &tp2, &to2);
ctl->eaten += getNum(buf+ctl->eaten, &tp3, &to3);
ctl->eaten += getNum(buf+ctl->eaten, &tp4, &to4);
ctl->eaten += getNum(buf+ctl->eaten, &tp5, &to5);
if ((ctl->opt[1] > 0) && ((int)p[1] >= 0) &&
(to1 == CMD_NUMERIC) && ((int)tp1 >= 0) &&
(to2 == CMD_NUMERIC) && ((int)tp2 >= 0) &&
(to3 == CMD_NUMERIC) && ((int)tp3 >= 0) &&
(to4 == CMD_NUMERIC) && ((int)tp4 >= 0) &&
(to5 == CMD_NUMERIC))
{
p[3] = 5 * 4;
memcpy(ext, &tp1, 4);
memcpy(ext, &tp2, 4);
memcpy(ext, &tp3, 4);
memcpy(ext, &tp4, 4);
memcpy(ext, &tp5, 4);
valid = 1;
}
break;
case 191: /* PROCR
One to 11 parameters, first positive,
@ -971,6 +1012,7 @@ int cmdParse(
break;
case 193: /* BI2CZ FW I2CWD I2CZ SERW SPIW SPIX
BSPIX
Two or more parameters, first >=0, rest 0-255.
*/

336
pigpio.c
View File

@ -752,6 +752,10 @@ Assumes two counters per block. Each counter 4 * 16 (16^4=65536)
#define PI_WFRX_SERIAL 1
#define PI_WFRX_I2C 2
#define PI_WFRX_I2C_CLK 3
#define PI_WFRX_SPI_MISO 4
#define PI_WFRX_SPI_MOSI 5
#define PI_WFRX_SPI_CS 6
#define PI_WFRX_SPI_SCLK 7
#define PI_WF_MICROS 1
@ -846,6 +850,8 @@ Assumes two counters per block. Each counter 4 * 16 (16^4=65536)
#define PI_SPI_FLAGS_GET_RESVD(x) (((x)>>5)&7)
#define PI_SPI_FLAGS_GET_CSPOLS(x) (((x)>>2)&7)
#define PI_SPI_FLAGS_GET_MODE(x) ((x)&3)
#define PI_SPI_FLAGS_GET_CPHA(x) ((x)&1)
#define PI_SPI_FLAGS_GET_CPOL(x) ((x)&2)
#define PI_STARTING 0
#define PI_RUNNING 1
@ -1095,6 +1101,21 @@ typedef struct
int started;
} wfRxI2C_t;
typedef struct
{
int MISO;
int MOSI;
int CS;
int SCLK;
int delay;
int spiFlags;
int MISOMode;
int MOSIMode;
int CSMode;
int SCLKMode;
int started;
} wfRxSPI_t;
typedef struct
{
int mode;
@ -1104,6 +1125,7 @@ typedef struct
{
wfRxSerial_t s;
wfRxI2C_t I;
wfRxSPI_t S;
};
} wfRx_t;
@ -1757,10 +1779,9 @@ static int myDoCommand(uint32_t *p, unsigned bufSize, char *buf)
{
int res, i, j;
uint32_t mask;
uint32_t tmp1, tmp2, tmp3;
uint32_t tmp1, tmp2, tmp3, tmp4, tmp5;
gpioPulse_t *pulse;
int masked;
res = 0;
switch (p[0])
@ -1793,7 +1814,9 @@ static int myDoCommand(uint32_t *p, unsigned bufSize, char *buf)
}
break;
case PI_CMD_BI2CC: res = bbI2CClose(p[1]); break;
case PI_CMD_BI2CC:
res = bbI2CClose(p[1]);
break;
case PI_CMD_BI2CO:
memcpy(&p[4], buf, 4);
@ -1810,6 +1833,25 @@ static int myDoCommand(uint32_t *p, unsigned bufSize, char *buf)
}
break;
case PI_CMD_BSPIO:
memcpy(&tmp1, buf, 4); // MISO
memcpy(&tmp2, buf+4, 4); // MOSI
memcpy(&tmp3, buf+8, 4); // SCLK
memcpy(&tmp4, buf+12, 4);// baud
memcpy(&tmp5, buf+16, 4);// flags
res = bbSPIOpen(p[1], tmp1, tmp2, tmp3, tmp4, tmp5);
break;
case PI_CMD_BSPIC:
res = bbSPIClose(p[1]);
break;
case PI_CMD_BSPIX:
if (p[3] > bufSize) p[3] = bufSize;
res = bbSPIXfer(p[1], buf, buf, p[3]);
break;
case PI_CMD_BR1: res = gpioRead_Bits_0_31(); break;
case PI_CMD_BR2: res = gpioRead_Bits_32_53(); break;
@ -1995,8 +2037,6 @@ static int myDoCommand(uint32_t *p, unsigned bufSize, char *buf)
}
break;
case PI_CMD_MICS:
if (p[1] <= PI_MAX_MICS_DELAY) myGpioDelay(p[1]);
else res = PI_BAD_MICS_DELAY;
@ -2144,8 +2184,9 @@ static int myDoCommand(uint32_t *p, unsigned bufSize, char *buf)
case PI_CMD_SLRI: res = gpioSerialReadInvert(p[1], p[2]); break;
case PI_CMD_SPIC: res = spiClose(p[1]); break;
case PI_CMD_SPIC:
res = spiClose(p[1]);
break;
case PI_CMD_SPIO:
memcpy(&p[4], buf, 4);
@ -6651,6 +6692,7 @@ static void *pthSocketThreadHandler(void *fdC)
case PI_CMD_SLR:
case PI_CMD_SPIX:
case PI_CMD_SPIR:
case PI_CMD_BSPIX:
if (((int)p[3]) > 0)
{
@ -9744,6 +9786,26 @@ static int read_SDA(wfRx_t *w)
return gpioRead(w->I.SDA);
}
static void set_CS(wfRx_t *w)
{
myGpioWrite(w->S.CS, PI_SPI_FLAGS_GET_CSPOLS(w->S.spiFlags));
}
static void clear_CS(wfRx_t *w)
{
myGpioWrite(w->S.CS, !PI_SPI_FLAGS_GET_CSPOLS(w->S.spiFlags));
}
static void set_SCLK(wfRx_t *w)
{
myGpioWrite(w->S.SCLK, !PI_SPI_FLAGS_GET_CPOL(w->S.spiFlags));
}
static void clear_SCLK(wfRx_t *w)
{
myGpioWrite(w->S.SCLK, PI_SPI_FLAGS_GET_CPOL(w->S.spiFlags));
}
static void set_SDA(wfRx_t *w)
{
myGpioSetMode(w->I.SDA, PI_INPUT);
@ -9766,6 +9828,11 @@ static void I2C_delay(wfRx_t *w)
myGpioDelay(w->I.delay);
}
static void SPI_delay(wfRx_t *w)
{
myGpioDelay(w->S.delay);
}
static void I2C_clock_stretch(wfRx_t *w)
{
uint32_t now, max_stretch=10000;
@ -9775,6 +9842,30 @@ static void I2C_clock_stretch(wfRx_t *w)
while ((gpioRead(w->I.SCL) == 0) && ((gpioTick()-now) < max_stretch));
}
static void bbSPIStart(wfRx_t *w)
{
if (w->S.started)
{
clear_SCLK(w);
clear_CS(w);
SPI_delay(w);
}
clear_SCLK(w);
set_CS(w);
w->S.started = 1;
}
static void bbSPIStop(wfRx_t *w)
{
clear_CS(w);
clear_SCLK(w);
SPI_delay(w);
w->S.started = 0;
}
static void I2CStart(wfRx_t *w)
{
if (w->I.started)
@ -9859,6 +9950,73 @@ static uint8_t I2CGetByte(wfRx_t *w, int nack)
return byte;
}
static uint8_t bbSPIXferByte(wfRx_t *w, char txByte)
{
uint8_t bit, rxByte=0;
if (PI_SPI_FLAGS_GET_CPHA(w->S.spiFlags))
{
for (bit=0; bit<8; bit++)
{
if (PI_SPI_FLAGS_GET_TX_LSB(w->S.spiFlags))
{
myGpioWrite(w->S.MOSI, txByte & 0x01);
txByte >>= 1;
}
else
{
myGpioWrite(w->S.MOSI, txByte & 0x80);
txByte <<= 1;
}
set_SCLK(w);
SPI_delay(w);
if (PI_SPI_FLAGS_GET_RX_LSB(w->S.spiFlags))
{
rxByte = (rxByte >> 1) | myGpioRead(w->S.MISO) << 7;
}
else
{
rxByte = (rxByte << 1) | myGpioRead(w->S.MISO);
}
clear_SCLK(w);
SPI_delay(w);
}
}
else
{
for (bit=0; bit<8; bit++)
{
if (PI_SPI_FLAGS_GET_TX_LSB(w->S.spiFlags))
{
myGpioWrite(w->S.MOSI, txByte & 0x01);
txByte >>= 1;
}
else
{
myGpioWrite(w->S.MOSI, txByte & 0x80);
txByte <<= 1;
}
if (PI_SPI_FLAGS_GET_RX_LSB(w->S.spiFlags))
{
rxByte = (rxByte >> 1) | myGpioRead(w->S.MISO) << 7;
}
else
{
rxByte = (rxByte << 1) | myGpioRead(w->S.MISO);
}
set_SCLK(w);
SPI_delay(w);
clear_SCLK(w);
SPI_delay(w);
}
}
return rxByte;
}
int bbI2COpen(unsigned SDA, unsigned SCL, unsigned baud)
{
DBG(DBG_USER, "SDA=%d SCL=%d baud=%d", SDA, SCL, baud);
@ -9901,6 +10059,73 @@ int bbI2COpen(unsigned SDA, unsigned SCL, unsigned baud)
return 0;
}
int bbSPIOpen(unsigned CS, unsigned MISO, unsigned MOSI, unsigned SCLK, unsigned baud, unsigned spiFlags)
{
DBG(DBG_USER, "MISO=%d MOSI=%d CS=%d SCLK=%d baud=%d", MISO, MOSI, CS, SCLK, baud);
CHECK_INITED;
if (CS > PI_MAX_USER_GPIO)
SOFT_ERROR(PI_BAD_USER_GPIO, "bad CS (%d)", CS);
if (MISO > PI_MAX_USER_GPIO)
SOFT_ERROR(PI_BAD_USER_GPIO, "bad MISO (%d)", MISO);
if (MOSI > PI_MAX_USER_GPIO)
SOFT_ERROR(PI_BAD_USER_GPIO, "bad MOSI (%d)", MOSI);
if (SCLK > PI_MAX_USER_GPIO)
SOFT_ERROR(PI_BAD_USER_GPIO, "bad SCLK (%d)", SCLK);
if ((baud < PI_BB_SPI_MIN_BAUD) || (baud > PI_BB_SPI_MAX_BAUD))
SOFT_ERROR(PI_BAD_SPI_BAUD,
"CS %d, bad baud rate (%d)", CS, baud);
if (wfRx[CS].mode != PI_WFRX_NONE)
SOFT_ERROR(PI_GPIO_IN_USE, "gpio %d is already being used, mode %d", CS, wfRx[CS].mode);
if (!((wfRx[MISO].mode == PI_WFRX_NONE) || (wfRx[MISO].mode == PI_WFRX_SPI_MISO)) || (MISO == CS))
SOFT_ERROR(PI_GPIO_IN_USE, "gpio %d is already being used, mode %d", MISO, wfRx[MISO].mode);
if (!((wfRx[MOSI].mode == PI_WFRX_NONE) || (wfRx[MOSI].mode == PI_WFRX_SPI_MOSI)) || (MOSI == CS) || (MOSI == MISO))
SOFT_ERROR(PI_GPIO_IN_USE, "gpio %d is already being used, mode %d", MOSI, wfRx[MOSI].mode);
if (!((wfRx[SCLK].mode == PI_WFRX_NONE) || (wfRx[SCLK].mode == PI_WFRX_SPI_SCLK)) || (SCLK == CS) || (SCLK == MISO) || (SCLK == MOSI))
SOFT_ERROR(PI_GPIO_IN_USE, "gpio %d is already being used, mode %d", SCLK, wfRx[SCLK].mode);
wfRx[MISO].gpio = MISO;
wfRx[MISO].mode = PI_WFRX_SPI_MISO;
wfRx[MOSI].gpio = MOSI;
wfRx[MOSI].mode = PI_WFRX_SPI_MOSI;
wfRx[SCLK].gpio = SCLK;
wfRx[SCLK].mode = PI_WFRX_SPI_SCLK;
wfRx[CS].gpio = CS;
wfRx[CS].mode = PI_WFRX_SPI_CS;
wfRx[CS].baud = baud;
wfRx[CS].S.started = 0;
wfRx[CS].S.MISO = MISO;
wfRx[CS].S.MOSI = MOSI;
wfRx[CS].S.CS = CS;
wfRx[CS].S.SCLK = SCLK;
wfRx[CS].S.delay = (500000 / baud) - 1;
wfRx[CS].S.spiFlags = spiFlags;
wfRx[CS].S.MISOMode = gpioGetMode(MISO);
wfRx[CS].S.MOSIMode = gpioGetMode(MOSI);
wfRx[CS].S.CSMode = gpioGetMode(CS);
wfRx[CS].S.SCLKMode = gpioGetMode(SCLK);
myGpioSetMode(MISO, PI_INPUT);
myGpioSetMode(MOSI, PI_OUTPUT);
myGpioSetMode(CS, PI_OUTPUT);
myGpioSetMode(SCLK, PI_OUTPUT);
return 0;
}
/* ----------------------------------------------------------------------- */
@ -9937,6 +10162,103 @@ int bbI2CClose(unsigned SDA)
return 0;
}
int bbSPIClose(unsigned CS)
{
DBG(DBG_USER, "CS=%d", CS);
CHECK_INITED;
if (CS > PI_MAX_USER_GPIO)
SOFT_ERROR(PI_BAD_USER_GPIO, "bad gpio (%d)", CS);
switch(wfRx[CS].mode)
{
case PI_WFRX_SPI_CS:
myGpioSetMode(wfRx[CS].S.MISO, wfRx[CS].S.MISOMode);
myGpioSetMode(wfRx[CS].S.MOSI, wfRx[CS].S.MOSIMode);
myGpioSetMode(wfRx[CS].S.CS, wfRx[CS].S.CSMode);
myGpioSetMode(wfRx[CS].S.SCLK, wfRx[CS].S.SCLKMode);
wfRx[wfRx[CS].S.MISO].mode = PI_WFRX_NONE;
wfRx[wfRx[CS].S.MOSI].mode = PI_WFRX_NONE;
wfRx[wfRx[CS].S.CS].mode = PI_WFRX_NONE;
wfRx[wfRx[CS].S.SCLK].mode = PI_WFRX_NONE;
break;
default:
SOFT_ERROR(PI_NOT_SPI_GPIO, "no SPI on gpio (%d)", CS);
break;
}
return 0;
}
/*-------------------------------------------------------------------------*/
int bbSPIXfer(
unsigned CS,
char *inBuf,
char *outBuf,
unsigned len)
{
int pos, status;
char txByte, rxByte;
wfRx_t *w;
DBG(DBG_USER, "CS=%d inBuf=%s outBuf=%08X len=%d",
CS, myBuf2Str(len, (char *)inBuf), (int)outBuf, len);
CHECK_INITED;
if (CS > PI_MAX_USER_GPIO)
SOFT_ERROR(PI_BAD_USER_GPIO, "bad gpio (%d)", CS);
if (wfRx[CS].mode != PI_WFRX_SPI_CS)
SOFT_ERROR(PI_NOT_SPI_GPIO, "no SPI on gpio (%d)", CS);
if (!inBuf || !len)
SOFT_ERROR(PI_BAD_POINTER, "input buffer can't be NULL");
if (!outBuf && len)
SOFT_ERROR(PI_BAD_POINTER, "output buffer can't be NULL");
w = &wfRx[CS];
status = 0;
bbSPIStart(w);
for (pos=0; pos < len; pos++)
{
if (PI_SPI_FLAGS_GET_TX_LSB(w->S.spiFlags))
{
txByte = inBuf[pos];
}
else
{
txByte = inBuf[len - pos - 1];
}
rxByte = bbSPIXferByte(w, txByte);
if (PI_SPI_FLAGS_GET_RX_LSB(w->S.spiFlags))
{
outBuf[pos] = rxByte;
}
else
{
outBuf[len - pos - 1] = rxByte;
}
DBG(DBG_INTERNAL, "pos=%d len=%d sent=%d recvd=%d", pos, len, txByte, rxByte);
}
bbSPIStop(w);
status = len;
return status;
}
/*-------------------------------------------------------------------------*/
int bbI2CZip(

View File

@ -285,6 +285,10 @@ spiRead Reads bytes from a SPI device
spiWrite Writes bytes to a SPI device
spiXfer Transfers bytes with a SPI device
bbSPIOpen Opens GPIO for bit banging SPI
bbSPIClose Closes GPIO for bit banging SPI
bbSPIXfer Performs multiple bit banged SPI transactions
SERIAL
serOpen Opens a serial device
@ -592,6 +596,9 @@ typedef void *(gpioThreadFunc_t) (void *);
#define PI_BB_I2C_MIN_BAUD 50
#define PI_BB_I2C_MAX_BAUD 500000
#define PI_BB_SPI_MIN_BAUD 50
#define PI_BB_SPI_MAX_BAUD 250000
#define PI_BB_SER_MIN_BAUD 50
#define PI_BB_SER_MAX_BAUD 250000
@ -2619,6 +2626,92 @@ SDA: 0-31, the SDA GPIO used in a prior call to [*bbI2COpen*]
Returns 0 if OK, otherwise PI_BAD_USER_GPIO, or PI_NOT_I2C_GPIO.
D*/
/*F*/
int bbSPIOpen(unsigned CS, unsigned MISO, unsigned MOSI, unsigned SCLK, unsigned baud, unsigned spiFlags);
/*D
This function selects a set of GPIO for bit banging SPI at a
specified baud rate.
Bit banging SPI allows the use of different GPIO for SPI than
for the hardware SPI ports.
. .
CS: 0-31
MISO: 0-31
MOSI: 0-31
SCLK: 0-31
baud: 50-250000
spiFlags: see below
. .
spiFlags consists of the least significant 22 bits.
. .
21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
b b b b b b R T n n n n W A u2 u1 u0 p2 p1 p0 m m
. .
mm defines the SPI mode.
. .
Mode POL PHA
0 0 0
1 0 1
2 1 0
3 1 1
. .
p0 is 0 if CEx is active low (default) and 1 for active high.
T is 1 if the least significant bit is transmitted on MOSI first, the
default (0) shifts the most significant bit out first.
R is 1 if the least significant bit is received on MISO first, the
default (0) receives the most significant bit first.
The other bits in flags should be set to zero.
Returns 0 if OK, otherwise PI_BAD_USER_GPIO, PI_BAD_SPI_BAUD, or
PI_GPIO_IN_USE.
D*/
/*F*/
int bbSPIClose(unsigned CS);
/*D
This function stops bit banging SPI on a set of GPIO previously
opened with [*bbSPIOpen*].
. .
CS: 0-31, the CS GPIO used in a prior call to [*bbSPIOpen*]
. .
Returns 0 if OK, otherwise PI_BAD_USER_GPIO, or PI_NOT_SPI_GPIO.
D*/
/*F*/
int bbSPIXfer(
unsigned CS,
char *inBuf,
char *outBuf,
unsigned len);
/*D
This function executes an bit banged SPI transfer. The data
to be sent is specified by the contents of inBuf, received data
is stored into outBuf.
len specifies the amount of bytes to be transferred.
. .
CS: 0-31 (as used in a prior call to [*bbSPIOpen*])
inBuf: pointer to buffer to hold data to be sent
outBuf: pointer to buffer to hold returned data
len: size of data transfer
. .
Returns >= 0 if OK (the number of bytes read), otherwise
PI_BAD_USER_GPIO, PI_NOT_SPI_GPIO or PI_BAD_POINTER.
The returned SPI data is stored in consecutive locations of outBuf.
D*/
/*F*/
int bbI2CZip(
unsigned SDA,
@ -5450,6 +5543,10 @@ PARAMS*/
#define PI_CMD_SHELL 110
#define PI_CMD_BSPIC 111
#define PI_CMD_BSPIO 112
#define PI_CMD_BSPIX 113
/*DEF_E*/
/*
@ -5654,6 +5751,8 @@ after this command is issued.
#define PI_FILE_IS_A_DIR -138 // file is a directory
#define PI_BAD_SHELL_STATUS -139 // bad shell return status
#define PI_BAD_SCRIPT_NAME -140 // bad script name
#define PI_BAD_SPI_BAUD -141 // bad SPI baud rate, not 50-500k
#define PI_NOT_SPI_GPIO -142 // no bit bang SPI in progress on GPIO
#define PI_PIGIF_ERR_0 -2000
#define PI_PIGIF_ERR_99 -2099

153
pigpio.py
View File

@ -238,6 +238,10 @@ spi_read Reads bytes from a SPI device
spi_write Writes bytes to a SPI device
spi_xfer Transfers bytes with a SPI device
bb_spi_open Opens GPIO for bit banging SPI
bb_spi_close Closes GPIO for bit banging SPI
bb_spi_xfer Transfers bytes with bit banging SPI
Serial
serial_open Opens a serial device
@ -359,6 +363,19 @@ FROM_START=0
FROM_CURRENT=1
FROM_END=2
SPI_CS_HIGH_ACTIVE = 1 << 2
SPI_CS0_HIGH_ACTIVE = 1 << 2
SPI_CS1_HIGH_ACTIVE = 1 << 3
SPI_CS2_HIGH_ACTIVE = 1 << 4
SPI_RX_LSBFIRST = 1 << 15
SPI_TX_LSBFIRST = 1 << 14
SPI_MODE_0 = 0
SPI_MODE_1 = 1
SPI_MODE_2 = 2
SPI_MODE_3 = 3
SPI_CPOL = 2
SPI_CPHA = 1
# pigpio command numbers
_PI_CMD_MODES= 0
@ -497,6 +514,10 @@ _PI_CMD_FS =108
_PI_CMD_FL =109
_PI_CMD_SHELL=110
_PI_CMD_BSPIC=111
_PI_CMD_BSPIO=112
_PI_CMD_BSPIX=113
# pigpio error numbers
_PI_INIT_FAILED =-1
@ -640,6 +661,8 @@ PI_NO_FILE_ACCESS =-137
PI_FILE_IS_A_DIR =-138
PI_BAD_SHELL_STATUS =-139
PI_BAD_SCRIPT_NAME =-140
PI_BAD_SPI_BAUD =-141
PI_NOT_SPI_GPIO =-142
# pigpio error text
@ -782,7 +805,8 @@ _errors=[
[PI_FILE_IS_A_DIR , "file is a directory"],
[PI_BAD_SHELL_STATUS , "bad shell return status"],
[PI_BAD_SCRIPT_NAME , "bad script name"],
[PI_BAD_SPI_BAUD , "bad SPI baud rate, not 50-500k"],
[PI_NOT_SPI_GPIO , "no bit bang SPI in progress on GPIO"],
]
class _socklock:
@ -2946,6 +2970,133 @@ class pi():
return bytes, data
def bb_spi_open(self, CS, MISO, MOSI, SCLK, baud=100000, spi_flags=0):
"""
This function selects a set of GPIO for bit banging SPI at a
specified baud rate.
Bit banging SPI allows the use of different GPIO for SPI than
for the hardware SPI ports.
CS := 0-31
MISO := 0-31
MOSI := 0-31
SCLK := 0-31
baud := 50-250000
spiFlags := see below
spiFlags consists of the least significant 22 bits.
...
21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
b b b b b b R T n n n n W A u2 u1 u0 p2 p1 p0 m m
...
mm defines the SPI mode, defaults to 0
...
Mode CPOL CPHA
0 0 0
1 0 1
2 1 0
3 1 1
...
Use the following constants to set the Mode:
pigpio.SPI_MODE_0,
pigpio.SPI_MODE_1,
pigpio.SPI_MODE_2 or
pigpio.SPI_MODE_3
or use
pigpio.SPI_CPOL and/ or
pigpio.SPI_CPHA
p0 is 0 if CS is active low (default) and 1 for active high.
Use pigpio.SPI_CS_HIGH_ACTIVE to set this flag.
T is 1 if the least significant bit is transmitted on MOSI first,
the default (0) shifts the most significant bit out first.
Use pigpio.SPI_TX_LSBFIRST to set this flag.
R is 1 if the least significant bit is received on MISO first,
the default (0) receives the most significant bit first.
Use pigpio.SPI_RX_LSBFIRST to set this flag.
The other bits in spiFlags should be set to zero.
Returns 0 if OK, otherwise PI_BAD_USER_GPIO, PI_BAD_SPI_BAUD, or
PI_GPIO_IN_USE.
...
pi.bb_spi_open(CS, MISO, MOSI, SCLK,
baud=100000,
spi_flags=pigpio.SPI_MODE_1 | pigpio.SPI_CS_HIGH_ACTIVE)
...
"""
# I p1 CS
# I p2 0
# I p3 20
## extension ##
# I MISO
# I MOSI
# I SCLK
# I baud
# I spi_flags
extents = [struct.pack("IIIII", MISO, MOSI, SCLK, baud, spi_flags)]
return _u2i(_pigpio_command_ext(
self.sl, _PI_CMD_BSPIO, CS, 0, 20, extents))
def bb_spi_close(self, CS):
"""
This function stops bit banging SPI on a set of GPIO
previously opened with [*bb_spi_open*].
CS:= 0-31, the CS GPIO used in a prior call to [*bb_ispi_open*]
Returns 0 if OK, otherwise PI_BAD_USER_GPIO, or PI_NOT_SPI_GPIO.
...
pi.bb_spi_close(CS)
...
"""
return _u2i(_pigpio_command(self.sl, _PI_CMD_BSPIC, CS, 0))
def bb_spi_xfer(self, CS, data):
"""
This function executes an bit banged SPI transfer. The data
to be sent is specified by the contents of data, received data
is returned as a bytestring.
CS:= 0-31 (as used in a prior call to [*bbSPIOpen*])
data:= data to be sent
Returns >= 0 if OK (the number of bytes read), otherwise
PI_BAD_USER_GPIO, PI_NOT_SPI_GPIO or PI_BAD_POINTER.
The received SPI data returned as ab bytearray
...
pi.bb_spi_xfer(CS, data)
...
"""
# I p1 SDA
# I p2 0
# I p3 len
## extension ##
# s len data bytes
# Don't raise exception. Must release lock.
bytes = u2i(_pigpio_command_ext(
self.sl, _PI_CMD_BSPIX, CS, 0, len(data), [data], False))
if bytes > 0:
data = self._rxbuf(bytes)
else:
data = ""
self.sl.l.release()
return bytes, data
def bb_i2c_open(self, SDA, SCL, baud=100000):
"""
This function selects a pair of GPIO for bit banging I2C at a