For more information, please refer to <http://unlicense.org/>
*/
-/* pigpio version 20 */
+/* pigpio version 21 */
#include <stdio.h>
#include <string.h>
#define DMA_BUS_ADR 0x40000000
+#define AUX_BASE 0x20215000
#define CLK_BASE 0x20101000
#define DMA_BASE 0x20007000
#define DMA15_BASE 0x20E05000
#define PWM_BASE 0x2020C000
#define SPI_BASE 0x20204000
#define SYST_BASE 0x20003000
-#define UART0_BASE 0x20201000
-#define UART1_BASE 0x20215000
+#define AUX_LEN 0xD8
#define CLK_LEN 0xA8
#define DMA_LEN 0x1000 /* allow access to all channels */
#define GPIO_LEN 0xB4
#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_LEN_LONG (1<<25)
+#define SPI_CS_DMA_LEN (1<<24)
+#define SPI_CS_CSPOLS(x) ((x)<<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_CS1 1
#define SPI_CS2 2
-/* SPI gpios. */
+/* standard SPI gpios (ALT0) */
#define PI_SPI_CE0 8
#define PI_SPI_CE1 7
#define PI_SPI_MISO 9
#define PI_SPI_MOSI 10
+/* auxiliary SPI gpios (ALT4) */
+
+#define PI_ASPI_CE0 18
+#define PI_ASPI_CE1 17
+#define PI_ASPI_CE2 16
+#define PI_ASPI_MISO 19
+#define PI_ASPI_MOSI 20
+#define PI_ASPI_SCLK 21
+
+/* AUX */
+
+#define AUX_IRQ 0
+#define AUX_ENABLES 1
+
+#define AUX_MU_IO_REG 16
+#define AUX_MU_IER_REG 17
+#define AUX_MU_IIR_REG 18
+#define AUX_MU_LCR_REG 19
+#define AUX_MU_MCR_REG 20
+#define AUX_MU_LSR_REG 21
+#define AUX_MU_MSR_REG 22
+#define AUX_MU_SCRATCH 23
+#define AUX_MU_CNTL_REG 24
+#define AUX_MU_STAT_REG 25
+#define AUX_MU_BAUD_REG 26
+
+#define AUX_SPI0_CNTL0_REG 32
+#define AUX_SPI0_CNTL1_REG 33
+#define AUX_SPI0_STAT_REG 34
+#define AUX_SPI0_PEEK_REG 35
+
+#define AUX_SPI0_IO_REG 40
+#define AUX_SPI0_TX_HOLD 44
+
+#define AUX_SPI1_CNTL0_REG 48
+#define AUX_SPI1_CNTL1_REG 49
+#define AUX_SPI1_STAT_REG 50
+#define AUX_SPI1_PEEK_REG 51
+
+#define AUX_SPI1_IO_REG 56
+#define AUX_SPI1_TX_HOLD 60
+
+#define AUXENB_SPI2 (1<<2)
+#define AUXENB_SPI1 (1<<1)
+#define AUXENB_UART (1<<0)
+
+#define AUXSPI_CNTL0_SPEED(x) ((x)<<20)
+#define AUXSPI_CNTL0_CS(x) ((x)<<17)
+#define AUXSPI_CNTL0_POSTINP (1<<16)
+#define AUXSPI_CNTL0_VAR_CS (1<<15)
+#define AUXSPI_CNTL0_VAR_WIDTH (1<<14)
+#define AUXSPI_CNTL0_DOUT_HOLD(x) ((x)<<12)
+#define AUXSPI_CNTL0_ENABLE (1<<11)
+#define AUXSPI_CNTL0_IN_RISING(x) ((x)<<10)
+#define AUXSPI_CNTL0_CLR_FIFOS (1<<9)
+#define AUXSPI_CNTL0_OUT_RISING(x) ((x)<<8)
+#define AUXSPI_CNTL0_INVERT_CLK(x) ((x)<<7)
+#define AUXSPI_CNTL0_MSB_FIRST(x) ((x)<<6)
+#define AUXSPI_CNTL0_SHIFT_LEN(x) ((x)<<0)
+
+#define AUXSPI_CNTL1_CS_HIGH(x) ((x)<<8)
+#define AUXSPI_CNTL1_TX_IRQ (1<<7)
+#define AUXSPI_CNTL1_DONE_IRQ (1<<6)
+#define AUXSPI_CNTL1_MSB_FIRST(x)((x)<<1)
+#define AUXSPI_CNTL1_KEEP_INPUT (1<<0)
+
+#define AUXSPI_STAT_TX_FIFO(x) ((x)<<28)
+#define AUXSPI_STAT_RX_FIFO(x) ((x)<<20)
+#define AUXSPI_STAT_TX_FULL (1<<10)
+#define AUXSPI_STAT_TX_EMPTY (1<<9)
+#define AUXSPI_STAT_RX_EMPTY (1<<7)
+#define AUXSPI_STAT_BUSY (1<<6)
+#define AUXSPI_STAT_BITS(x) ((x)<<0)
+
/* --------------------------------------------------------------- */
#define NORMAL_DMA (DMA_NO_WIDE_BURSTS | DMA_WAIT_RESP)
uint32_t flags;
} spiInfo_t;
+#define PI_SPI_FLAGS_CHANNEL(x) ((x&7)<<29)
+
+#define PI_SPI_FLAGS_GET_CHANNEL(x) (((x)>>29)&7)
+#define PI_SPI_FLAGS_GET_BITLEN(x) (((x)>>16)&63)
+#define PI_SPI_FLAGS_GET_RX_LSB(x) (((x)>>15)&1)
+#define PI_SPI_FLAGS_GET_TX_LSB(x) (((x)>>14)&1)
+#define PI_SPI_FLAGS_GET_3WREN(x) (((x)>>10)&15)
+#define PI_SPI_FLAGS_GET_3WIRE(x) (((x)>>9)&1)
+#define PI_SPI_FLAGS_GET_AUX_SPI(x) (((x)>>8)&1)
+#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)
+
typedef struct
{
uint32_t startTick;
static dmaOPage_t * * dmaOVirt = MAP_FAILED;
static dmaOPage_t * * dmaOPhys = MAP_FAILED;
-static volatile uint32_t * clkReg = MAP_FAILED;
-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 * auxReg = MAP_FAILED;
+static volatile uint32_t * clkReg = MAP_FAILED;
+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;
-static volatile uint32_t * dmaOut = MAP_FAILED;
+static volatile uint32_t * dmaIn = MAP_FAILED;
+static volatile uint32_t * dmaOut = MAP_FAILED;
/* constant data */
/* ======================================================================= */
+/*SPI */
+
+static uint32_t spi_dummy; /* only used to prevent warning */
+
static unsigned old_mode_ce0;
static unsigned old_mode_ce1;
static unsigned old_mode_sclk;
static uint32_t old_spi_cs;
static uint32_t old_spi_clk;
-static uint32_t spi_dummy; /* only used to prevent warning */
+static unsigned old_mode_ace0;
+static unsigned old_mode_ace1;
+static unsigned old_mode_ace2;
+static unsigned old_mode_asclk;
+static unsigned old_mode_amiso;
+static unsigned old_mode_amosi;
-static void spiInit(void)
+static uint32_t old_spi_cntl0;
+static uint32_t old_spi_cntl1;
+
+static void spiInit(uint32_t flags)
{
- 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);
+ 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_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);
+ 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];
- 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);
+ }
}
-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);
+void spiTerm(uint32_t flags)
+{
+ int resvd;
- spiReg[SPI_CS] = old_spi_cs;
- spiReg[SPI_CLK] = old_spi_clk;
+ 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;
+ }
}
-#define PI_SPI_FLAGS_CHAN(x) ((x)<<30)
+uint32_t _spiTXBits(char *buf, int pos, int bitlen, int msbf)
+{
+ uint32_t bits=0;
-/*
-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(
+ if (buf)
+ {
+ if (bitlen <= 8) bits = *((( uint8_t*)buf)+pos);
+ else if (bitlen <= 16) bits = *(((uint16_t*)buf)+pos);
+ else bits = *(((uint32_t*)buf)+pos);
+
+ if (msbf) bits <<= (32-bitlen);
+ }
+
+ return bits;
+}
+
+void _spiRXBits(char *buf, int pos, int bitlen, int msbf, uint32_t bits)
+{
+ if (buf)
+ {
+ if (!msbf) bits >>= (32-bitlen);
+
+ if (bitlen <= 8) *((( uint8_t*)buf)+pos) = bits;
+ else if (bitlen <= 16) *(((uint16_t*)buf)+pos) = bits;
+ else *(((uint32_t*)buf)+pos) = bits;
+ }
+}
+
+
+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 mode, bitlen, txmsbf, rxmsbf, channel;
+ unsigned txCnt=0;
+ unsigned rxCnt=0;
+ uint32_t spiDefaults;
+ uint32_t statusReg;
+ int txFull, rxEmpty;
+
+ channel = PI_SPI_FLAGS_GET_CHANNEL(flags);
+ mode = PI_SPI_FLAGS_GET_MODE (flags);
+ bitlen = PI_SPI_FLAGS_GET_BITLEN (flags);
+ if (!bitlen) bitlen = 8;
+ 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;
+
+ 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;
+
+ auxReg[AUX_SPI0_CNTL0_REG] = AUXSPI_CNTL0_ENABLE | spiDefaults;
+ auxReg[AUX_SPI0_CNTL1_REG] = AUXSPI_CNTL1_MSB_FIRST(rxmsbf);
+
+ while ((txCnt < count) || (rxCnt < count))
+ {
+ statusReg = auxReg[AUX_SPI0_STAT_REG];
+
+ rxEmpty = statusReg & AUXSPI_STAT_RX_EMPTY;
+
+ txFull = (((statusReg>>28)&15) > 2);
+
+ if (rxCnt < count)
+ {
+ if (!rxEmpty)
+ {
+ _spiRXBits(rxBuf, rxCnt++, bitlen, rxmsbf, auxReg[AUX_SPI0_IO_REG]);
+ }
+ }
+
+ if (txCnt < count)
+ {
+ if (!txFull)
+ {
+ if (txCnt != (count-1))
+ {
+ auxReg[AUX_SPI0_TX_HOLD] =
+ _spiTXBits(txBuf, txCnt++, bitlen, txmsbf);
+ }
+ else
+ {
+ auxReg[AUX_SPI0_IO_REG] =
+ _spiTXBits(txBuf, txCnt++, bitlen, txmsbf);
+ }
+ }
+ }
+ }
+
+ while ((auxReg[AUX_SPI0_STAT_REG] & AUXSPI_STAT_BUSY)) ;
+
+ auxReg[AUX_SPI0_CNTL0_REG] = spiDefaults; /* stop */
+}
+
+static void spiGoS(
unsigned speed,
uint32_t flags,
char *txBuf,
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) |
+ unsigned mode, channel, cspol, cspols, flag3w, ren3w;
+ uint32_t status;
+
+ channel = PI_SPI_FLAGS_GET_CHANNEL(flags);
+ mode = PI_SPI_FLAGS_GET_MODE (flags);
+ cspols = PI_SPI_FLAGS_GET_CSPOLS(flags);
+ cspol = (cspols>>channel) & 1;
+ flag3w = PI_SPI_FLAGS_GET_3WIRE(flags);
+ ren3w = PI_SPI_FLAGS_GET_3WREN(flags);
+
+ spiDefaults = SPI_CS_MODE(mode) |
+ SPI_CS_CSPOLS(cspols) |
+ SPI_CS_CS(channel) |
+ SPI_CS_CSPOL(cspol) |
SPI_CS_CLEAR(3);
if (flag3w)
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++;
- }
+ status = spiReg[SPI_CS];
- while((rxCnt < cnt) && ((spiReg[SPI_CS] & SPI_CS_RXD)))
+ while((rxCnt < cnt) && ((status & SPI_CS_RXD)))
{
if (rxBuf) rxBuf[rxCnt] = spiReg[SPI_FIFO];
else spi_dummy = spiReg[SPI_FIFO];
rxCnt++;
}
+
+ while((txCnt < cnt) && ((status & SPI_CS_TXD)))
+ {
+ if (txBuf) spiReg[SPI_FIFO] = txBuf[txCnt];
+ else spiReg[SPI_FIFO] = 0;
+ txCnt++;
+ }
}
while (!(spiReg[SPI_CS] & SPI_CS_DONE)) ;
cnt += cnt3w;
+ spiReg[SPI_CS] |= SPI_CS_REN;
+
while((txCnt < cnt) || (rxCnt < cnt))
{
- spiReg[SPI_CS] |= SPI_CS_REN;
+ status = spiReg[SPI_CS];
- 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)))
+ while((rxCnt < cnt) && ((status & SPI_CS_RXD)))
{
if (rxBuf) rxBuf[rxCnt] = spiReg[SPI_FIFO];
else spi_dummy = spiReg[SPI_FIFO];
rxCnt++;
}
+
+ while((txCnt < cnt) && ((status & SPI_CS_TXD)))
+ {
+ if (txBuf) spiReg[SPI_FIFO] = txBuf[txCnt];
+ else spiReg[SPI_FIFO] = 0;
+ txCnt++;
+ }
}
while (!(spiReg[SPI_CS] & SPI_CS_DONE)) ;
spiReg[SPI_CS] = spiDefaults; /* stop */
}
-static int spiAnyOpen(void)
+static void spiGo(
+ unsigned speed,
+ uint32_t flags,
+ char *txBuf,
+ char *rxBuf,
+ unsigned count)
{
- int i;
+ if (PI_SPI_FLAGS_GET_AUX_SPI(flags))
+ spiGoA(speed, flags, txBuf, rxBuf, count);
+ else
+ spiGoS(speed, flags, txBuf, rxBuf, count);
+}
+
+static int spiAnyOpen(uint32_t flags)
+{
+ int i, aux;
+
+ aux = PI_SPI_FLAGS_GET_AUX_SPI(flags);
for (i=0; i<PI_SPI_SLOTS; i++)
{
- if (spiInfo[i].state == PI_SPI_OPENED) return 1;
+ if ((spiInfo[i].state == PI_SPI_OPENED) &&
+ (PI_SPI_FLAGS_GET_AUX_SPI(spiInfo[i].flags) == aux))
+ return 1;
}
return 0;
}
CHECK_INITED;
- if (spiChan >= PI_NUM_SPI_CHANNEL)
+ if (PI_SPI_FLAGS_GET_AUX_SPI(spiFlags))
+ {
+ if (gpioHardwareRevision() < 16)
+ SOFT_ERROR(PI_NO_AUX_SPI, "no auxiliary SPI, need a B+");
+
+ i = PI_NUM_AUX_SPI_CHANNEL;
+ }
+ else
+ i = PI_NUM_STD_SPI_CHANNEL;
+
+ if (spiChan >= i)
SOFT_ERROR(PI_BAD_SPI_CHANNEL, "bad spiChan (%d)", spiChan);
- if (!spiBaud)
+ if ((spiBaud < MIN_SPI_SPEED) || (spiBaud > MAX_SPI_SPEED))
SOFT_ERROR(PI_BAD_SPI_SPEED, "bad spiBaud (%d)", spiBaud);
- if (spiFlags > 256)
+ if (spiFlags > (1<<22))
SOFT_ERROR(PI_BAD_FLAGS, "bad spiFlags (0x%X)", spiFlags);
- if (!spiAnyOpen()) spiInit(); /* initialise on first open */
+ if (!spiAnyOpen(spiFlags)) spiInit(spiFlags); /* initialise on first open */
slot = -1;
SOFT_ERROR(PI_NO_HANDLE, "no SPI handles");
spiInfo[slot].speed = spiBaud;
- spiInfo[slot].flags = spiFlags | PI_SPI_FLAGS_CHAN(spiChan);
+ spiInfo[slot].flags = spiFlags | PI_SPI_FLAGS_CHANNEL(spiChan);
return slot;
}
spiInfo[handle].state = PI_I2C_CLOSED;
- if (!spiAnyOpen()) spiTerm(); /* terminate on last close */
+ if (!spiAnyOpen(spiInfo[handle].flags))
+ spiTerm(spiInfo[handle].flags); /* terminate on last close */
return 0;
}
if (pcmReg == MAP_FAILED)
SOFT_ERROR(PI_INIT_FAILED, "mmap pcm failed (%m)");
+ auxReg = initMapMem(fdMem, AUX_BASE, AUX_LEN);
+
+ if (auxReg == MAP_FAILED)
+ SOFT_ERROR(PI_INIT_FAILED, "mmap aux failed (%m)");
+
return 0;
}
DBG(DBG_STARTUP, "dmaBloc=%08X dmaIn=%08X",
(uint32_t)dmaBloc, (uint32_t)dmaIn);
- DBG(DBG_STARTUP, "gpioReg=%08X pwmReg=%08X pcmReg=%08X clkReg=%08X",
+ DBG(DBG_STARTUP,
+ "gpioReg=%08X pwmReg=%08X pcmReg=%08X clkReg=%08X auxReg=%08X",
(uint32_t)gpioReg, (uint32_t)pwmReg,
- (uint32_t)pcmReg, (uint32_t)clkReg);
+ (uint32_t)pcmReg, (uint32_t)clkReg, (uint32_t)auxReg);
for (i=0; i<DMAI_PAGES; i++)
DBG(DBG_STARTUP, "dmaIPhys[%d]=%08X", i, (uint32_t)dmaIPhys[i]);
dmaVirt = MAP_FAILED;
dmaPhys = MAP_FAILED;
+ auxReg = MAP_FAILED;
clkReg = MAP_FAILED;
dmaReg = MAP_FAILED;
gpioReg = MAP_FAILED;
/* release mmap'd memory */
+ if (auxReg != MAP_FAILED) munmap((void *)auxReg, AUX_LEN);
if (clkReg != MAP_FAILED) munmap((void *)clkReg, CLK_LEN);
if (dmaReg != MAP_FAILED) munmap((void *)dmaReg, DMA_LEN);
if (gpioReg != MAP_FAILED) munmap((void *)gpioReg, GPIO_LEN);
if (systReg != MAP_FAILED) munmap((void *)systReg, SYST_LEN);
if (spiReg != MAP_FAILED) munmap((void *)spiReg, SPI_LEN);
+ auxReg = MAP_FAILED;
clkReg = MAP_FAILED;
dmaReg = MAP_FAILED;
gpioReg = MAP_FAILED;
import atexit
import codecs
-VERSION = "1.10"
+VERSION = "1.11"
exceptions = True
PI_SER_READ_NO_DATA =-87
PI_UNKNOWN_COMMAND =-88
PI_SPI_XFER_FAILED =-89
+_PI_BAD_POINTER =-90
+PI_NO_AUX_SPI =-91
# pigpio error text
[PI_SER_READ_NO_DATA , "ser read no data available"],
[PI_UNKNOWN_COMMAND , "unknown command"],
[PI_SPI_XFER_FAILED , "SPI xfer/read/write failed"],
+ [_PI_BAD_POINTER , "bad (NULL) pointer"],
+ [PI_NO_AUX_SPI , "need a B+ for auxiliary SPI"],
]
class _socklock:
Normally you would only use the [*i2c_**] functions if
you are or will be connecting to the Pi over a network. If
you will always run on the local Pi use the standard smbus
- modules instead.
+ module instead.
...
h = pi.i2c_open(1, 0x53) # open device at address 0x53 on bus 1
# Don't raise exception. Must release lock.
bytes = u2i(_pigpio_command_ext(
- self.sl, _PI_CMD_I2CPK, handle, reg, len(data), [data]), False)
+ self.sl, _PI_CMD_I2CPK, handle, reg, len(data), [data], False))
if bytes > 0:
data = self._rxbuf(bytes)
else:
# Don't raise exception. Must release lock.
bytes = u2i(_pigpio_command_ext(
- self.sl, _PI_CMD_I2CRI, handle, reg, 4, extents), False)
+ self.sl, _PI_CMD_I2CRI, handle, reg, 4, extents, False))
if bytes > 0:
data = self._rxbuf(bytes)
else:
modify the default behaviour of 4-wire operation, mode 0,
active low chip select.
+ An auxiliary SPI device is available on the B+ and may be
+ selected by setting the A bit in the flags. The auxiliary
+ device has 3 chip selects and a selectable word size in bits.
+
+
spi_channel:= 0 or 1, the SPI channel.
spi_baud:= >0, the transmission rate in bits per second.
spi_flags:= see below.
Normally you would only use the [*spi_**] functions if
you are or will be connecting to the Pi over a network. If
you will always run on the local Pi use the standard SPI
- modules instead.
+ module instead.
- spiFlags consists of the least significant 8 bits.
+ spi_flags consists of the least significant 22 bits.
. .
- 7 6 5 4 3 2 1 0
- n n n n W P m m
+ 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
+ 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.
+ px is 0 if CEx is active low (default) and 1 for active high.
+
+ ux is 0 if the CEx gpio is reserved for SPI (default)
+ and 1 otherwise.
+
+ A is 0 for the standard SPI device, 1 for the auxiliary SPI.
+ The auxiliary device is only present on the B+.
W is 0 if the device is not 3-wire, 1 if the device is 3-wire.
+ Standard SPI device only.
- 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.
+ 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. Standard SPI device only.
+
+ T is 1 if the least significant bit is transmitted on MOSI
+ first, the default (0) shifts the most significant bit out
+ first. Auxiliary SPI device only.
+
+ R is 1 if the least significant bit is received on MISO
+ first, the default (0) receives the most significant bit
+ first. Auxiliary SPI device only.
+
+ bbbbbb defines the word size in bits (0-32). The default (0)
+ sets 8 bits per word. Auxiliary SPI device only.
The other bits in flags should be set to zero.
# Don't raise exception. Must release lock.
bytes = u2i(_pigpio_command_ext(
- self.sl, _PI_CMD_SPIX, handle, 0, len(data), [data]), False)
+ self.sl, _PI_CMD_SPIX, handle, 0, len(data), [data], False))
if bytes > 0:
data = self._rxbuf(bytes)
else:
Normally you would only use the [*serial_**] functions if
you are or will be connecting to the Pi over a network. If
you will always run on the local Pi use the standard serial
- modules instead.
+ module instead.
...
h1 = pi.serial_open("/dev/ttyAMA0", 300)
A SPI channel.
spi_flags: 32 bit
-
- 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.
+ See [*spi_open*].
t1:
A tick (earlier).