mirror of https://github.com/joan2937/pigpio
Added Software SPI
Added Software SPI: bbSPIopen bbSPIclose bbSPIxfer Some documentation is not finished yet.
This commit is contained in:
parent
5fcd079681
commit
c91dbb5220
48
command.c
48
command.c
|
@ -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.
|
||||
*/
|
||||
|
|
332
pigpio.c
332
pigpio.c
|
@ -748,10 +748,14 @@ Assumes two counters per block. Each counter 4 * 16 (16^4=65536)
|
|||
#define PI_NOTIFY_RUNNING 3
|
||||
#define PI_NOTIFY_PAUSED 4
|
||||
|
||||
#define PI_WFRX_NONE 0
|
||||
#define PI_WFRX_SERIAL 1
|
||||
#define PI_WFRX_I2C 2
|
||||
#define PI_WFRX_I2C_CLK 3
|
||||
#define PI_WFRX_NONE 0
|
||||
#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;
|
||||
|
@ -2139,13 +2179,14 @@ static int myDoCommand(uint32_t *p, unsigned bufSize, char *buf)
|
|||
case PI_CMD_SLRC: res = gpioSerialReadClose(p[1]); break;
|
||||
|
||||
case PI_CMD_SLRO:
|
||||
memcpy(&p[4], buf, 4);
|
||||
res = gpioSerialReadOpen(p[1], p[2], p[4]); break;
|
||||
memcpy(&p[4], buf, 4);
|
||||
res = gpioSerialReadOpen(p[1], p[2], p[4]); break;
|
||||
|
||||
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,71 @@ 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);
|
||||
|
@ -9888,7 +10044,7 @@ int bbI2COpen(unsigned SDA, unsigned SCL, unsigned baud)
|
|||
wfRx[SDA].I.started = 0;
|
||||
wfRx[SDA].I.SDA = SDA;
|
||||
wfRx[SDA].I.SCL = SCL;
|
||||
wfRx[SDA].I.delay = 500000 / baud;
|
||||
wfRx[SDA].I.delay = (500000 / baud) - 1;
|
||||
wfRx[SDA].I.SDAMode = gpioGetMode(SDA);
|
||||
wfRx[SDA].I.SCLMode = gpioGetMode(SCL);
|
||||
|
||||
|
@ -9901,6 +10057,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;
|
||||
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 +10160,87 @@ 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;
|
||||
wfRx_t *w;
|
||||
|
||||
DBG(DBG_USER, "gpio=%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++)
|
||||
{
|
||||
DBG(DBG_INTERNAL, "pos=%d len=%d sent=%d",
|
||||
pos, len, inBuf[pos]);
|
||||
outBuf[pos] = bbSPIXferByte(w, inBuf[pos]);
|
||||
DBG(DBG_INTERNAL, "recvd=%d", outBuf[pos]);
|
||||
}
|
||||
bbSPIStop(w);
|
||||
|
||||
status = len;
|
||||
|
||||
return status;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
int bbI2CZip(
|
||||
|
|
93
pigpio.h
93
pigpio.h
|
@ -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 500000
|
||||
|
||||
#define PI_BB_SER_MIN_BAUD 50
|
||||
#define PI_BB_SER_MAX_BAUD 250000
|
||||
|
||||
|
@ -2619,6 +2626,86 @@ 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-500000
|
||||
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.
|
||||
|
||||
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
|
||||
outLen: size of output buffer
|
||||
. .
|
||||
|
||||
Returns >= 0 if OK (the number of bytes read), otherwise
|
||||
PI_BAD_USER_GPIO, PI_NOT_SPI_GPIO or PI_BAD_POINTER.
|
||||
|
||||
The returned I2C data is stored in consecutive locations of outBuf.
|
||||
D*/
|
||||
|
||||
/*F*/
|
||||
int bbI2CZip(
|
||||
unsigned SDA,
|
||||
|
@ -5450,6 +5537,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 +5745,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
|
||||
|
|
69
pigpio.py
69
pigpio.py
|
@ -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
|
||||
|
@ -497,6 +501,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 +648,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 +792,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 +2957,62 @@ class pi():
|
|||
return bytes, data
|
||||
|
||||
|
||||
def bb_spi_open(self, CS, MISO, MOSI, SCLK, baud=100000, spi_flags=1):
|
||||
"""
|
||||
###
|
||||
"""
|
||||
# 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):
|
||||
"""
|
||||
###
|
||||
"""
|
||||
# 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
|
||||
|
|
Loading…
Reference in New Issue