TO BUILD
-gcc -o ir_hash_c test_ir_hasher.c ir_hasher.c -lpigpio -lrt
+gcc -o ir_hash_c test_ir_hasher.c ir_hasher.c -lpigpio -lrt -lpthread
TO RUN
TO BUILD
-g++ -o ir_hash_cpp test_ir_hasher.cpp ir_hasher.cpp -lpigpio -lrt
+g++ -o ir_hash_cpp test_ir_hasher.cpp ir_hasher.cpp -lpigpio -lrt -lpthread
TO RUN
+NOTE
+
+The initial part of the make, the compilation of pigpio.c,
+takes 100 seconds on early model Pis. Be patient. The overall
+install takes just over 3 minutes.
+
INSTALL
Extract the archive to a directory.
*/
/*
-This version is for pigpio version 26+
+This version is for pigpio version 30+
*/
#include <stdio.h>
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\
+cf = hardware clock frequency (4689-250M)\n\
db = data bits (1-32)\n\
g = any gpio (0-53)\n\
h = handle (>=0)\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\
+pdc = hardware PWM dutycycle (0-1M)\n\
+pf = hardware PWM frequency (1-125M)\n\
pl = pulse length (1-100)\n\
r = register\n\
sid = script id (>=0)\n\
{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-50K"},
- {PI_BAD_HPWM_DUTY , "hardware PWM dutycycle not 0-5000"},
- {PI_BAD_HCLK_FREQ , "hardware clock frequency not 4689-25M"},
+ {PI_BAD_HPWM_FREQ , "hardware PWM frequency not 1-125M"},
+ {PI_BAD_HPWM_DUTY , "hardware PWM dutycycle not 0-1M"},
+ {PI_BAD_HCLK_FREQ , "hardware clock frequency not 4689-250M"},
{PI_BAD_HCLK_PASS , "need password to use hardware clock 1"},
{PI_HPWM_ILLEGAL , "illegal, PWM in use for main clock"},
{PI_BAD_DATABITS , "serial data bits not 1-32"},
- {PI_BAD_STOPBITS , "serial (half) stop bits not 2-8"},
-
+ {PI_MSG_TOOBIG , "socket/pipe message too big"},
+ {PI_BAD_MALLOC_MODE , "bad memory allocation mode"},
};
.br
.br
-If the library isn't initialised all but the \fBgpioCfg*\fP, \fBgpioVersion\fP,
+If the library is not initialised all but the \fBgpioCfg*\fP, \fBgpioVersion\fP,
and \fBgpioHardwareRevision\fP functions will return PI_NOT_INITIALISED.
.br
.br
.br
-This function resets the DMA and PWM peripherals, releases memory, and
+This function resets the used DMA channels, releases memory, and
terminates any running threads.
.br
.br
For normal PWM the dutycycle will be out of the defined range
-for the gpio (see \fBgpioGetPWMrange\fP). If a hardware clock is
-active on the gpio the reported dutycycle will be 500 (out of 1000).
+for the gpio (see \fBgpioGetPWMrange\fP).
+
+.br
+
+.br
+If a hardware clock is active on the gpio the reported dutycycle
+will be 500000 (500k) out of 1000000 (1M).
+
+.br
+
+.br
If hardware PWM is active on the gpio the reported dutycycle
-will be out of a 1000.
+will be out of a 1000000 (1M).
.br
.br
If a hardware clock or hardware PWM is active on the gpio
-the reported range will be 1000.
+the reported range will be 1000000 (1M).
.br
.br
.br
-If a hardware clock or hardware PWM is active on the gpio
-the reported real range will be 1000.
+If a hardware clock is active on the gpio the reported real
+range will be 1000000 (1M).
+
+.br
+
+.br
+If hardware PWM is active on the gpio the reported real range
+will be approximately 250M divided by the set PWM frequency.
.br
.br
For normal PWM the frequency will be that defined for the gpio by
-\fBgpioSetPWMfrequency\fP. If a hardware clock is active on the gpio
-the reported frequency will be that set by \fBgpioHardwareClock\fP.
+\fBgpioSetPWMfrequency\fP.
+
+.br
+
+.br
+If a hardware clock is active on the gpio the reported frequency
+will be that set by \fBgpioHardwareClock\fP.
+
+.br
+
+.br
If hardware PWM is active on the gpio the reported frequency
will be that set by \fBgpioHardwarePWM\fP.
.br
For \fBbbBits\fP 1-8 there will be one byte per character.
+.br
For \fBbbBits\fP 9-16 there will be two bytes per character.
+.br
For \fBbbBits\fP 17-32 there will be four bytes per character.
.IP "\fBint gpioSerialReadClose(unsigned user_gpio)\fP"
.br
.br
-An auxiliary SPI device is available on the B+ and may be
+An auxiliary SPI device is available on the A+/B+/Pi2 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.
.br
.EX
- spiChan: 0-1 (0-2 for B+ auxiliary device)
+ spiChan: 0-1 (0-2 for A+/B+/Pi2 auxiliary device)
.br
spiBaud: 32K-125M (values above 30M are unlikely to work)
.br
.br
+.br
+Warning: modes 1 and 3 do not appear to work on the auxiliary device.
+
+.br
+
.br
.EX
.br
A is 0 for the standard SPI device, 1 for the auxiliary SPI. The
-auxiliary device is only present on the B+.
+auxiliary device is only present on the A+/B+/Pi2.
.br
.IP "\fBint gpioHardwareClock(unsigned gpio, unsigned clkfreq)\fP"
.IP "" 4
Starts a hardware clock on a gpio at the specified frequency.
+Frequencies above 30MHz are unlikely to work.
.br
.EX
gpio: see description
.br
-clkfreq: 0 (off) or 4689-250M
+clkfreq: 0 (off) or 4689-250000000 (250M)
.br
.EE
.EX
4 clock 0 All models
.br
-5 clock 1 A+/B+ and compute module only (reserved for system use)
+5 clock 1 A+/B+/Pi2 and compute module only (reserved for system use)
.br
-6 clock 2 A+/B+ and compute module only
+6 clock 2 A+/B+/Pi2 and compute module only
.br
-20 clock 0 A+/B+ and compute module only
+20 clock 0 A+/B+/Pi2 and compute module only
.br
21 clock 1 All models but Rev.2 B (reserved for system use)
.br
.IP "\fBint gpioHardwarePWM(unsigned gpio, unsigned PWMfreq, unsigned PWMduty)\fP"
.IP "" 4
Starts hardware PWM on a gpio at the specified frequency and dutycycle.
+Frequencies above 30MHz are unlikely to work.
.br
.EX
gpio: see description
.br
-PWMfreq: 0 (off) or 5-250K
+PWMfreq: 0 (off) or 1-125000000 (125M)
.br
-PWMduty: 0 (off) to 1000 (fully on).
+PWMduty: 0 (off) to 1000000 (1M)(fully on)
.br
.EE
.br
.br
-Both PWM channels share the same clock and the same update frequency.
-The latest frequency setting will be used by both PWM channels. The
-same PWM channel is available on multiple gpios. The latest
-dutycycle setting will be used by all gpios which share a PWM channel.
+The same PWM channel is available on multiple gpios. The latest
+frequency and dutycycle setting will be used by all gpios which
+share a PWM channel.
.br
.br
.EX
-12 PWM channel 0 A+/B+ and compute module only
+12 PWM channel 0 A+/B+/Pi2 and compute module only
.br
-13 PWM channel 1 A+/B+ and compute module only
+13 PWM channel 1 A+/B+/Pi2 and compute module only
.br
18 PWM channel 0 All models
.br
-19 PWM channel 1 A+/B+ and compute module only
+19 PWM channel 1 A+/B+/Pi2 and compute module only
.br
.br
.br
.br
-The hardware revision is the last 4 characters on the Revision line of
+The hardware revision is the last few characters on the Revision line of
/proc/cpuinfo.
.br
.br
The revision number can be used to determine the assignment of gpios
-to pins.
+to pins (see \fBgpio\fP).
.br
.br
-.br
-Type 1 has gpio 0 on P1-3, gpio 1 on P1-5, and gpio 21 on P1-13.
-
-.br
-
-.br
-Type 2 has gpio 2 on P1-3, gpio 3 on P1-5, gpio 27 on P1-13, and
-gpios 28-31 on P5.
-
-.br
-
-.br
-Type 3 has a 40 pin connector rather than the 26 pin connector of
-the earlier boards. Gpios 0 to 27 are brought out to the connector.
-
-.br
-
.br
Type 1 boards have hardware revision numbers of 2 and 3.
.br
.br
-Type 3 boards have hardware revision number 16.
+Type 3 boards have hardware revision numbers of 16 or greater.
.br
.IP "\fBint gpioCfgClock(unsigned cfgMicros, unsigned cfgPeripheral, unsigned cfgSource)\fP"
.IP "" 4
-Configures pigpio to use a particualar sample rate timed by a specified
+Configures pigpio to use a particular sample rate timed by a specified
peripheral.
.br
Or in PI_DISABLE_FIFO_IF to disable the pipe interface.
Or in PI_DISABLE_SOCK_IF to disable the socket interface.
-.IP "\fBint gpioCustom1(unsigned arg1, unsigned arg2, char *argx, unsigned count)\fP"
+.IP "\fBint gpioCfgMemAlloc(unsigned memAllocMode)\fP"
+.IP "" 4
+Selects the method of DMA memory allocation.
+
+.br
+
+.br
+
+.EX
+memAllocMode: 0-2
+.br
+
+.EE
+
+.br
+
+.br
+There are two methods of DMA memory allocation. The original method
+uses the /proc/self/pagemap file to allocate bus memory. The new
+method uses the mailbox property interface to allocate bus memory.
+
+.br
+
+.br
+Auto will use the mailbox method unless a larger than default buffer
+size is requested with \fBgpioCfgBufferSize\fP.
+
+.IP "\fBint gpioCfgInternals(unsigned cfgWhat, int cfgVal)\fP"
+.IP "" 4
+Used to tune internal settings.
+
+.br
+
+.br
+
+.EX
+cfgWhat: see source code
+.br
+ cfgVal: see source code
+.br
+
+.EE
+
+.IP "\fBint gpioCustom1(unsigned arg1, unsigned arg2, char *argx, unsigned argc)\fP"
.IP "" 4
This function is available for user customisation.
.br
.EX
- arg1: >=0
+arg1: >=0
.br
- arg2: >=0
+arg2: >=0
.br
- argx: extra (byte) arguments
+argx: extra (byte) arguments
.br
-count: number of extra arguments
+argc: number of extra arguments
.br
.EE
.br
Returns >= 0 if OK, less than 0 indicates a user defined error.
-.IP "\fBint gpioCustom2(unsigned arg1, char *argx, unsigned count, char *retBuf, unsigned retMax)\fP"
+.IP "\fBint gpioCustom2(unsigned arg1, char *argx, unsigned argc, char *retBuf, unsigned retMax)\fP"
.IP "" 4
This function is available for user customisation.
.br
argx: extra (byte) arguments
.br
- count: number of extra arguments
+ argc: number of extra arguments
.br
retBuf: buffer for returned bytes
.br
.br
The number of returned bytes must be retMax or less.
-.IP "\fBint gpioCfgInternals(unsigned cfgWhat, int cfgVal)\fP"
-.IP "" 4
-Used to tune internal settings.
-
-.br
-
-.br
-
-.EX
-cfgWhat: see source code
-.br
- cfgVal: see source code
-.br
-
-.EE
-
-.br
-
-.br
-Not intended for general use.
-
.IP "\fBint rawWaveAddSPI(rawSPI_t *spi, unsigned offset, unsigned spiSS, char *buf, unsigned spiTxBits, unsigned spiBitFirst, unsigned spiBitLast, unsigned spiBits)\fP"
.IP "" 4
This function adds a waveform representing SPI data to the
.br
+.IP "\fBarg1\fP" 0
+
+.br
+
+.br
+An unsigned argument passed to a user customised function. Its
+meaning is defined by the customiser.
+
+.br
+
+.br
+
+.IP "\fBarg2\fP" 0
+
+.br
+
+.br
+An unsigned argument passed to a user customised function. Its
+meaning is defined by the customiser.
+
+.br
+
+.br
+
+.IP "\fBargc\fP" 0
+
+.br
+
+.br
+The count of bytes passed to a user customised function.
+
+.br
+
+.br
+
+.IP "\fB*argx\fP" 0
+
+.br
+
+.br
+A pointer to an array of bytes passed to a user customised function.
+Its meaning and content is defined by the customiser.
+
+.br
+
+.br
+
.IP "\fBbbBaud\fP" 0
.br
.br
+.br
+There are 54 General Purpose Input Outputs (gpios) named gpio0 through
+gpio53.
+
+.br
+
+.br
+They are split into two banks. Bank 1 consists of gpio0 through
+gpio31. Bank 2 consists of gpio32 through gpio53.
+
+.br
+
+.br
+All the gpios which are safe for the user to read and write are in
+bank 1. Not all gpios in bank 1 are safe though. Type 1 boards
+have 17 safe gpios. Type 2 boards have 21. Type 3 boards have 26.
+
+.br
+
+.br
+See \fBgpioHardwareRevision\fP.
+
+.br
+
+.br
+The user gpios are marked with an X in the following table.
+
+.br
+
+.br
+
+.EX
+ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+.br
+Type 1 X X - - X - - X X X X X - - X X
+.br
+Type 2 - - X X X - - X X X X X - - X X
+.br
+Type 3 X X X X X X X X X X X X X X
+.br
+
+.br
+ 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
+.br
+Type 1 - X X - - X X X X X - - - - - -
+.br
+Type 2 - X X - - - X X X X - X X X X X
+.br
+Type 3 X X X X X X X X X X X X - - - -
+.br
+
+.EE
+
+.br
+
.br
.IP "\fBgpioAlertFunc_t\fP" 0
\fBgpioCfgInternals\fP
.br
\fBgpioCfgSocketPort\fP
+.br
+\fBgpioCfgMemAlloc\fP
.br
.br
+.IP "\fBmemAllocMode\fP: 0-2" 0
+
+.br
+
+.br
+The DMA memory allocation mode.
+
+.br
+
+.br
+
+.EX
+PI_MEM_ALLOC_AUTO 0
+.br
+PI_MEM_ALLOC_PAGEMAP 1
+.br
+PI_MEM_ALLOC_MAILBOX 2
+.br
+
+.EE
+
+.br
+
+.br
+
.IP "\fB*micros\fP" 0
.br
.br
-.IP "\fBPWMduty\fP: 0-1000" 0
+.IP "\fBPWMduty\fP: 0-1000000 (1M)" 0
The hardware PWM dutycycle.
.br
.br
.EX
-#define PI_HW_PWM_RANGE 5000
+#define PI_HW_PWM_RANGE 1000000
.br
.EE
.br
.EX
-#define PI_HW_PWM_MIN_FREQ 5
+#define PI_HW_PWM_MIN_FREQ 1
.br
-#define PI_HW_PWM_MAX_FREQ 50000
+#define PI_HW_PWM_MAX_FREQ 125000000
.br
.EE
.br
+.IP "\fB*retBuf\fP" 0
+
+.br
+
+.br
+A buffer to hold a number of bytes returned to a used customised function,
+
+.br
+
+.br
+
+.IP "\fBretMax\fP" 0
+
+.br
+
+.br
+The maximum number of bytes a user customised function should return.
+
+.br
+
+.br
+
.IP "\fB*rxBuf\fP" 0
.br
.br
+.br
+See \fBgpio\fP.
+
+.br
+
.br
.IP "\fB*userdata\fP" 0
.br
#define PI_BAD_POINTER -90 // bad (NULL) pointer
.br
-#define PI_NO_AUX_SPI -91 // need a B+ for auxiliary SPI
+#define PI_NO_AUX_SPI -91 // need a A+/B+/Pi2 for auxiliary SPI
.br
#define PI_NOT_PWM_GPIO -92 // gpio is not in use for PWM
.br
.br
#define PI_NOT_HPWM_GPIO -95 // gpio has no hardware PWM
.br
-#define PI_BAD_HPWM_FREQ -96 // hardware PWM frequency not 5-50K
+#define PI_BAD_HPWM_FREQ -96 // hardware PWM frequency not 1-125M
.br
-#define PI_BAD_HPWM_DUTY -97 // hardware PWM dutycycle not 0-5000
+#define PI_BAD_HPWM_DUTY -97 // hardware PWM dutycycle not 0-1M
.br
-#define PI_BAD_HCLK_FREQ -98 // hardware clock frequency not 4689-25M
+#define PI_BAD_HCLK_FREQ -98 // hardware clock frequency not 4689-250M
.br
#define PI_BAD_HCLK_PASS -99 // need password to use hardware clock 1
.br
.br
#define PI_MSG_TOOBIG -103 // socket/pipe message too big
.br
+#define PI_BAD_MALLOC_MODE -104 // bad memory allocation mode
+.br
.br
#define PI_PIGIF_ERR_0 -2000
#define PI_DEFAULT_UPDATE_MASK_R3 0x0080400FFFFFFCLL
.br
#define PI_DEFAULT_UPDATE_MASK_COMPUTE 0x00FFFFFFFFFFFFLL
+.br
+#define PI_DEFAULT_MEM_ALLOC_MODE PI_MEM_ALLOC_AUTO
+.br
+
.br
.EE
For more information, please refer to <http://unlicense.org/>
*/
-/* pigpio version 29 */
+/* pigpio version 30 */
#include <stdio.h>
#include <string.h>
} \
while (0)
-#define PI_PERI_PHYS 0x7E000000
-
static volatile uint32_t piModel = 1;
-static volatile uint32_t PI_PERI_BASE = 0x20000000;
-static volatile uint32_t DMA_BUS_ADR = 0x40000000;
-static volatile uint32_t DMA_BUS_CACHE = 0x00000000;
+#define PI_PERI_BUS 0x7E000000
+
+static volatile uint32_t pi_peri_phys = 0x20000000;
+static volatile uint32_t pi_dram_bus = 0x40000000;
+static volatile uint32_t pi_mem_flag = 0x00000004;
-#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_BASE (pi_peri_phys + 0x00215000)
+#define CLK_BASE (pi_peri_phys + 0x00101000)
+#define DMA_BASE (pi_peri_phys + 0x00007000)
+#define DMA15_BASE (pi_peri_phys + 0x00E05000)
+#define GPIO_BASE (pi_peri_phys + 0x00200000)
+#define PCM_BASE (pi_peri_phys + 0x00203000)
+#define PWM_BASE (pi_peri_phys + 0x0020C000)
+#define SPI_BASE (pi_peri_phys + 0x00204000)
+#define SYST_BASE (pi_peri_phys + 0x00003000)
#define AUX_LEN 0xD8
#define CLK_LEN 0xA8
#define FLUSH_PAGES 1024
+#define MB_DEV_MAJOR 100
+
+#define MB_IOCTL _IOWR(MB_DEV_MAJOR, 0, char *)
+
+#define MB_DEV "/dev/pigpio-mb"
+
+#define BUS_TO_PHYS(x) ((x)&~0xC0000000)
+
+#define MB_END_TAG 0
+#define MB_PROCESS_REQUEST 0
+
+#define MB_ALLOCATE_MEMORY_TAG 0x3000C
+#define MB_LOCK_MEMORY_TAG 0x3000D
+#define MB_UNLOCK_MEMORY_TAG 0x3000E
+#define MB_RELEASE_MEMORY_TAG 0x3000F
+
/* --------------------------------------------------------------- */
typedef void (*callbk_t) ();
unsigned ifFlags;
int dbgLevel;
unsigned showStats;
+ unsigned memAllocMode;
} gpioCfg_t;
typedef struct
unsigned clock;
} clkInf_t;
+typedef struct
+{
+ unsigned handle; /* mbAllocateMemory() */
+ uintptr_t bus_addr; /* mbLockMemory() */
+ uintptr_t *virtual_addr; /* mbMapMem() */
+ unsigned size; /* in bytes */
+} DMAMem_t;
+
/* --------------------------------------------------------------- */
/* initialise once then preserve */
PI_DEFAULT_IF_FLAGS,
0,
0,
+ PI_DEFAULT_MEM_ALLOC_MODE,
};
static volatile gpioStats_t gpioStats;
static int fdLock = -1;
static int fdMem = -1;
static int fdSock = -1;
+static int fdPmap = -1;
+static int fdMbox = -1;
-static dmaPage_t * * dmaBloc = MAP_FAILED;
+static DMAMem_t *dmaMboxBlk = MAP_FAILED;
+static uintptr_t * * dmaPMapBlk = MAP_FAILED;
static dmaPage_t * * dmaVirt = MAP_FAILED;
-static dmaPage_t * * dmaPhys = MAP_FAILED;
+static dmaPage_t * * dmaBus = MAP_FAILED;
static dmaIPage_t * * dmaIVirt = MAP_FAILED;
-static dmaIPage_t * * dmaIPhys = MAP_FAILED;
+static dmaIPage_t * * dmaIBus = MAP_FAILED;
static dmaOPage_t * * dmaOVirt = MAP_FAILED;
-static dmaOPage_t * * dmaOPhys = MAP_FAILED;
+static dmaOPage_t * * dmaOBus = MAP_FAILED;
static volatile uint32_t * auxReg = MAP_FAILED;
static volatile uint32_t * clkReg = MAP_FAILED;
uint32_t hw_pwm_freq[2];
uint32_t hw_pwm_duty[2];
+uint32_t hw_pwm_real_range[2];
uint8_t PWMDef[PI_MAX_GPIO + 1] =
{
static void myLvsPageSlot(int pos, int * page, int * slot)
{
-// *page = pos%DMAI_PAGES;
-// *slot = pos/DMAI_PAGES;
*page = pos/LVS_PER_IPAGE;
*slot = pos%LVS_PER_IPAGE;
}
static void myTckPageSlot(int pos, int * page, int * slot)
{
-// *page = pos%DMAI_PAGES;
-// *slot = pos/DMAI_PAGES;
*page = pos/TCK_PER_IPAGE;
*slot = pos%TCK_PER_IPAGE;
}
}
}
+/* ======================================================================= */
+
+/*
+https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface
+*/
+
+int mbCreate(void)
+{
+ /* <0 error */
+
+ unlink(MB_DEV);
+
+ return mknod(MB_DEV, S_IFCHR|0600, makedev(MB_DEV_MAJOR, 0));
+}
+
+int mbOpen(void)
+{
+ /* <0 error */
+
+ return open(MB_DEV, 0);
+}
+
+void mbClose(int fd)
+{
+ close(fd);
+}
+
+static int mbProperty(int fd, void *buf)
+{
+ return ioctl(fd, MB_IOCTL, buf);
+}
+
+unsigned mbAllocateMemory(
+ int fd, unsigned size, unsigned align, unsigned flags)
+{
+ int i=1;
+ unsigned p[32];
+
+ p[i++] = MB_PROCESS_REQUEST;
+ p[i++] = MB_ALLOCATE_MEMORY_TAG;
+ p[i++] = 12;
+ p[i++] = 12;
+ p[i++] = size;
+ p[i++] = align;
+ p[i++] = flags;
+ p[i++] = MB_END_TAG;
+ p[0] = i*sizeof *p;
+
+ mbProperty(fd, p);
+
+ return p[5];
+}
+
+unsigned mbLockMemory(int fd, unsigned handle)
+{
+ int i=1;
+ unsigned p[32];
+
+ p[i++] = MB_PROCESS_REQUEST;
+ p[i++] = MB_LOCK_MEMORY_TAG;
+ p[i++] = 4;
+ p[i++] = 4;
+ p[i++] = handle;
+ p[i++] = MB_END_TAG;
+ p[0] = i*sizeof *p;
+
+ mbProperty(fd, p);
+
+ return p[5];
+}
+
+unsigned mbUnlockMemory(int fd, unsigned handle)
+{
+ int i=1;
+ unsigned p[32];
+
+ p[i++] = MB_PROCESS_REQUEST;
+ p[i++] = MB_UNLOCK_MEMORY_TAG;
+ p[i++] = 4;
+ p[i++] = 4;
+ p[i++] = handle;
+ p[i++] = MB_END_TAG;
+ p[0] = i*sizeof *p;
+
+ mbProperty(fd, p);
+
+ return p[5];
+}
+
+unsigned mbReleaseMemory(int fd, unsigned handle)
+{
+ int i=1;
+ unsigned p[32];
+
+ p[i++] = MB_PROCESS_REQUEST;
+ p[i++] = MB_RELEASE_MEMORY_TAG;
+ p[i++] = 4;
+ p[i++] = 4;
+ p[i++] = handle;
+ p[i++] = MB_END_TAG;
+ p[0] = i*sizeof *p;
+
+ mbProperty(fd, p);
+
+ return p[5];
+}
+
+void *mbMapMem(unsigned base, unsigned size)
+{
+ void *mem = MAP_FAILED;
+
+ mem = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fdMem, base);
+
+ return mem;
+}
+
+int mbUnmapMem(void *addr, unsigned size)
+{
+ /* 0 okay, -1 fail */
+ return munmap(addr, size);
+}
+
+void mbDMAFree(DMAMem_t *DMAMemP)
+{
+ if (DMAMemP->handle)
+ {
+ mbUnmapMem(DMAMemP->virtual_addr, DMAMemP->size);
+ mbUnlockMemory(fdMbox, DMAMemP->handle);
+ mbReleaseMemory(fdMbox, DMAMemP->handle);
+ DMAMemP->handle = 0;
+ }
+}
+
+int mbDMAAlloc(DMAMem_t *DMAMemP, unsigned size, uint32_t pi_mem_flag)
+{
+ DMAMemP->size = size;
+
+ DMAMemP->handle =
+ mbAllocateMemory(fdMbox, size, PAGE_SIZE, pi_mem_flag);
+
+ if (DMAMemP->handle)
+ {
+ DMAMemP->bus_addr = mbLockMemory(fdMbox, DMAMemP->handle);
+
+ DMAMemP->virtual_addr =
+ mbMapMem(BUS_TO_PHYS(DMAMemP->bus_addr), size);
+
+ return 1;
+ }
+ return 0;
+}
+
+
/* ======================================================================= */
rawCbs_t * rawWaveCBAdr(int cbNum)
page = pos/CBS_PER_OPAGE;
slot = pos%CBS_PER_OPAGE;
- return (uint32_t) &dmaOPhys[page]->cb[slot];
+ return (uint32_t) &dmaOBus[page]->cb[slot];
}
/* ----------------------------------------------------------------------- */
waveOOLPageSlot(pos, &page, &slot);
- return (uint32_t) &dmaOPhys[page]->OOL[slot];
+ return (uint32_t) &dmaOBus[page]->OOL[slot];
}
p->info = NORMAL_DMA |
DMA_DEST_DREQ |
DMA_PERIPHERAL_MAPPING(2);
- p->dst = ((PCM_BASE + PCM_FIFO*4) & 0x00ffffff) | PI_PERI_PHYS;
+ p->dst = ((PCM_BASE + PCM_FIFO*4) & 0x00ffffff) | PI_PERI_BUS;
}
else
{
p->info = NORMAL_DMA |
DMA_DEST_DREQ |
DMA_PERIPHERAL_MAPPING(5);
- p->dst = ((PWM_BASE + PWM_FIFO*4) & 0x00ffffff) | PI_PERI_PHYS;
+ p->dst = ((PWM_BASE + PWM_FIFO*4) & 0x00ffffff) | PI_PERI_BUS;
}
- p->src = (uint32_t) (&dmaOPhys[0]->periphData) | DMA_BUS_ADR;
+ p->src = (uint32_t) (&dmaOBus[0]->periphData);
p->length = 4 * 20 / PI_WF_MICROS; /* 20 micros delay */
- p->next = waveCbPOadr(botCB) | DMA_BUS_ADR;
+ p->next = waveCbPOadr(botCB);
repeatCB = botCB;
p = rawWaveCBAdr(botCB++);
p->info = NORMAL_DMA;
- p->src = waveOOLPOadr(botOOL++) | DMA_BUS_ADR;
- p->dst = ((GPIO_BASE + (GPSET0*4)) & 0x00ffffff) | PI_PERI_PHYS;
+ p->src = waveOOLPOadr(botOOL++);
+ p->dst = ((GPIO_BASE + (GPSET0*4)) & 0x00ffffff) | PI_PERI_BUS;
p->length = 4;
- p->next = waveCbPOadr(botCB) | DMA_BUS_ADR;
+ p->next = waveCbPOadr(botCB);
}
if (waves[i].gpioOff)
p = rawWaveCBAdr(botCB++);
p->info = NORMAL_DMA;
- p->src = waveOOLPOadr(botOOL++) | DMA_BUS_ADR;
- p->dst = ((GPIO_BASE + (GPCLR0*4)) & 0x00ffffff) | PI_PERI_PHYS;
+ p->src = waveOOLPOadr(botOOL++);
+ p->dst = ((GPIO_BASE + (GPCLR0*4)) & 0x00ffffff) | PI_PERI_BUS;
p->length = 4;
- p->next = waveCbPOadr(botCB) | DMA_BUS_ADR;
+ p->next = waveCbPOadr(botCB);
}
if (waves[i].flags & WAVE_FLAG_READ)
p = rawWaveCBAdr(botCB++);
p->info = NORMAL_DMA;
- p->src = ((GPIO_BASE + (GPLEV0*4)) & 0x00ffffff) | PI_PERI_PHYS;
- p->dst = waveOOLPOadr(--topOOL) | DMA_BUS_ADR;
+ p->src = ((GPIO_BASE + (GPLEV0*4)) & 0x00ffffff) | PI_PERI_BUS;
+ p->dst = waveOOLPOadr(--topOOL);
p->length = 4;
- p->next = waveCbPOadr(botCB) | DMA_BUS_ADR;
+ p->next = waveCbPOadr(botCB);
}
if (waves[i].flags & WAVE_FLAG_TICK)
p = rawWaveCBAdr(botCB++);
p->info = NORMAL_DMA;
- p->src = ((SYST_BASE + (SYST_CLO*4)) & 0x00ffffff) | PI_PERI_PHYS;
- p->dst = waveOOLPOadr(--topOOL) | DMA_BUS_ADR;
+ p->src = ((SYST_BASE + (SYST_CLO*4)) & 0x00ffffff) | PI_PERI_BUS;
+ p->dst = waveOOLPOadr(--topOOL);
p->length = 4;
- p->next = waveCbPOadr(botCB) | DMA_BUS_ADR;
+ p->next = waveCbPOadr(botCB);
}
if (waves[i].flags & WAVE_FLAG_COUNT)
baseCB = botCB;
- def_next = waveCbPOadr(baseCB+(3*PI_WAVE_COUNT_BLOCKS)) | DMA_BUS_ADR;
+ def_next = waveCbPOadr(baseCB+(3*PI_WAVE_COUNT_BLOCKS));
/* set up all the OOLs */
for (b=0; b < (PI_WAVE_COUNT_BLOCKS*(PI_WAVE_COUNT_LENGTH+1)); b++)
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);
+ waveCbPOadr (baseCB+((b*PI_WAVE_COUNT_BLOCKS)+3)));
rawWaveSetIn
(((PI_WAVE_COUNT_BLOCKS-1)*(PI_WAVE_COUNT_LENGTH+1))+7, 0);
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;
+ (topOOL-((b+1)*(PI_WAVE_COUNT_LENGTH+1)));
+ p->dst = (waveCbPOadr(botCB+1) + 20);
p->length = 4;
- p->next = waveCbPOadr(botCB) | DMA_BUS_ADR;
+ p->next = waveCbPOadr(botCB);
/* copy BOTTOM to TOP */
p->info = NORMAL_DMA;
p->src = waveOOLPOadr
- (topOOL-((b+1)*(PI_WAVE_COUNT_LENGTH+1))) | DMA_BUS_ADR;
+ (topOOL-((b+1)*(PI_WAVE_COUNT_LENGTH+1)));
p->dst = waveOOLPOadr
- (topOOL-(1+(b*(PI_WAVE_COUNT_LENGTH+1)))) | DMA_BUS_ADR;
+ (topOOL-(1+(b*(PI_WAVE_COUNT_LENGTH+1))));
p->length = 4;
- p->next = waveCbPOadr(botCB) | DMA_BUS_ADR;
+ p->next = waveCbPOadr(botCB);
/* shift all down one */
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;
+ (topOOL-(((b+1)*(PI_WAVE_COUNT_LENGTH+1))-1));
p->dst = waveOOLPOadr
- (topOOL-(((b+1)*(PI_WAVE_COUNT_LENGTH+1))-0)) | DMA_BUS_ADR;
+ (topOOL-(((b+1)*(PI_WAVE_COUNT_LENGTH+1))-0));
p->length = PI_WAVE_COUNT_LENGTH*4;
p->next = waveCbPOadr
- (baseCB+(3*PI_WAVE_COUNT_BLOCKS)) | DMA_BUS_ADR;
+ (baseCB+(3*PI_WAVE_COUNT_BLOCKS));
}
topOOL -= PI_WAVE_COUNT_BLOCKS * (PI_WAVE_COUNT_LENGTH+1);
DMA_DEST_DREQ |
DMA_PERIPHERAL_MAPPING(2);
- p->dst = ((PCM_BASE + PCM_FIFO*4) & 0x00ffffff) | PI_PERI_PHYS;
+ p->dst = ((PCM_BASE + PCM_FIFO*4) & 0x00ffffff) | PI_PERI_BUS;
}
else
{
DMA_DEST_DREQ |
DMA_PERIPHERAL_MAPPING(5);
- p->dst = ((PWM_BASE + PWM_FIFO*4) & 0x00ffffff) | PI_PERI_PHYS;
+ p->dst = ((PWM_BASE + PWM_FIFO*4) & 0x00ffffff) | PI_PERI_BUS;
}
- p->src = (uint32_t) (&dmaOPhys[0]->periphData) | DMA_BUS_ADR;
+ p->src = (uint32_t) (&dmaOBus[0]->periphData);
p->length = 4 * ((waves[i].usDelay+half)/PI_WF_MICROS);
- p->next = waveCbPOadr(botCB) | DMA_BUS_ADR;
+ p->next = waveCbPOadr(botCB);
}
}
{
if (wave_mode == PI_WAVE_MODE_ONE_SHOT)
p->next = 0;
- else p->next = waveCbPOadr(repeatCB) | DMA_BUS_ADR;
+ else p->next = waveCbPOadr(repeatCB);
}
status = botCB - waveOutBotCB;
static int chooseBestClock
(clkInf_t *clkInf, unsigned f, unsigned numc, unsigned *cf)
{
- unsigned c;
- unsigned div, frac, basef, offby, best_offby, valid;
+ int c, valid, offby, offby2, best_offby;
+ uint32_t div;
+ uint64_t frac;
valid = 0;
best_offby = 0;
for (c=0; c<numc; c++)
{
- basef = cf[c];
- div = basef / f;
- frac = basef - (div * f);
- frac = (frac * 4096) / f;
-
- offby = basef - (div * f) - ((frac * f) / 4096);
+ div = cf[c] / f;
if ((div > 1) && (div < 4096))
{
- if ((!valid) || (offby < best_offby))
+ if (f < PI_MASH_MAX_FREQ)
+ {
+ frac = cf[c] - (div * f);
+ frac = (frac * 4096) / f;
+ offby = cf[c] - (div * f) - ((frac * f) / 4096);
+ if (frac < 4095)
+ {
+ offby2 = cf[c] - (div * f) - (((frac+1) * f) / 4096);
+ if (offby2 < 0) offby2 = -offby2;
+ if (offby2 < offby)
+ {
+ offby = offby2;
+ frac++;
+ }
+ }
+ }
+ else
+ {
+ frac = 0;
+ offby = cf[c] - (div * f);
+ if (div < 4095)
+ {
+ offby2 = cf[c] - ((div+1) * f);
+ if (offby2 < 0) offby2 = -offby2;
+ if (offby2 < offby)
+ {
+ offby = offby2;
+ div++;
+ }
+ }
+ }
+
+ if ((!valid) || (offby <= best_offby))
{
valid = 1;
clkInf->div = div;
while (1)
{
- cb = (cbAddr - ((int)dmaIPhys[page] | DMA_BUS_ADR)) / 32;
+ cb = (cbAddr - ((int)dmaIBus[page])) / 32;
if (cb < CBS_PER_IPAGE)
{
while (1)
{
- cb = (cbAddr - ((int)dmaOPhys[page] | DMA_BUS_ADR)) / 32;
+ cb = (cbAddr - ((int)dmaOBus[page])) / 32;
if (cb < CBS_PER_OPAGE)
{
static uint32_t dmaPwmDataAdr(int pos)
{
- return (uint32_t) &dmaIPhys[pos]->periphData;
+ return (uint32_t) &dmaIBus[pos]->periphData;
}
/* ----------------------------------------------------------------------- */
page = pos/ON_PER_IPAGE;
slot = pos%ON_PER_IPAGE;
- return (uint32_t) &dmaIPhys[page]->gpioOn[slot];
+ return (uint32_t) &dmaIBus[page]->gpioOn[slot];
}
/* ----------------------------------------------------------------------- */
myOffPageSlot(pos, &page, &slot);
- return (uint32_t) &dmaIPhys[page]->gpioOff[slot];
+ return (uint32_t) &dmaIBus[page]->gpioOff[slot];
}
/* ----------------------------------------------------------------------- */
myTckPageSlot(pos, &page, &slot);
- return (uint32_t) &dmaIPhys[page]->tick[slot];
+ return (uint32_t) &dmaIBus[page]->tick[slot];
}
/* ----------------------------------------------------------------------- */
myLvsPageSlot(pos, &page, &slot);
- return (uint32_t) &dmaIPhys[page]->level[slot];
+ return (uint32_t) &dmaIBus[page]->level[slot];
}
/* ----------------------------------------------------------------------- */
page = (pos/CBS_PER_IPAGE);
slot = (pos%CBS_PER_IPAGE);
- return (uint32_t) &dmaIPhys[page]->cb[slot];
+ return (uint32_t) &dmaIBus[page]->cb[slot];
}
/* ----------------------------------------------------------------------- */
p = dmaCB2adr(b);
p->info = NORMAL_DMA;
- p->src = dmaGpioOnAdr(pos) | DMA_BUS_ADR;
- p->dst = ((GPIO_BASE + (GPSET0*4)) & 0x00ffffff) | PI_PERI_PHYS;
+ p->src = dmaGpioOnAdr(pos);
+ p->dst = ((GPIO_BASE + (GPSET0*4)) & 0x00ffffff) | PI_PERI_BUS;
p->length = 4;
- p->next = dmaCbAdr(b+1) | DMA_BUS_ADR;
+ p->next = dmaCbAdr(b+1);
}
/* ----------------------------------------------------------------------- */
p = dmaCB2adr(b);
p->info = NORMAL_DMA;
- p->src = ((SYST_BASE + (SYST_CLO*4)) & 0x00ffffff) | PI_PERI_PHYS;
- p->dst = dmaTickAdr(pos) | DMA_BUS_ADR;
+ p->src = ((SYST_BASE + (SYST_CLO*4)) & 0x00ffffff) | PI_PERI_BUS;
+ p->dst = dmaTickAdr(pos);
p->length = 4;
- p->next = dmaCbAdr(b+1) | DMA_BUS_ADR;
+ p->next = dmaCbAdr(b+1);
}
/* ----------------------------------------------------------------------- */
p = dmaCB2adr(b);
p->info = NORMAL_DMA;
- p->src = dmaGpioOffAdr(pos) | DMA_BUS_ADR;
- p->dst = ((GPIO_BASE + (GPCLR0*4)) & 0x00ffffff) | PI_PERI_PHYS;
+ p->src = dmaGpioOffAdr(pos);
+ p->dst = ((GPIO_BASE + (GPCLR0*4)) & 0x00ffffff) | PI_PERI_BUS;
p->length = 4;
- p->next = dmaCbAdr(b+1) | DMA_BUS_ADR;
+ p->next = dmaCbAdr(b+1);
}
/* ----------------------------------------------------------------------- */
p = dmaCB2adr(b);
p->info = NORMAL_DMA;
- p->src = ((GPIO_BASE + (GPLEV0*4)) & 0x00ffffff) | PI_PERI_PHYS;
- p->dst = dmaReadLevelsAdr(pos) | DMA_BUS_ADR;
+ p->src = ((GPIO_BASE + (GPLEV0*4)) & 0x00ffffff) | PI_PERI_BUS;
+ p->dst = dmaReadLevelsAdr(pos);
p->length = 4;
- p->next = dmaCbAdr(b+1) | DMA_BUS_ADR;
+ p->next = dmaCbAdr(b+1);
}
/* ----------------------------------------------------------------------- */
if (gpioCfg.clockPeriph == PI_CLOCK_PCM)
{
p->info = NORMAL_DMA | TIMED_DMA(2);
- p->dst = ((PCM_BASE + PCM_FIFO*4) & 0x00ffffff) | PI_PERI_PHYS;
+ p->dst = ((PCM_BASE + PCM_FIFO*4) & 0x00ffffff) | PI_PERI_BUS;
}
else
{
p->info = NORMAL_DMA | TIMED_DMA(5);
- p->dst = ((PWM_BASE + PWM_FIFO*4) & 0x00ffffff) | PI_PERI_PHYS;
+ p->dst = ((PWM_BASE + PWM_FIFO*4) & 0x00ffffff) | PI_PERI_BUS;
}
- p->src = dmaPwmDataAdr(b%DMAI_PAGES) | DMA_BUS_ADR;
+ p->src = dmaPwmDataAdr(b%DMAI_PAGES);
p->length = 4;
- p->next = dmaCbAdr(b+1) | DMA_BUS_ADR;
+ p->next = dmaCbAdr(b+1);
}
/* ----------------------------------------------------------------------- */
p = dmaCB2adr(b);
- p->next = dmaCbAdr(0) | DMA_BUS_ADR;
+ p->next = dmaCbAdr(0);
DBG(DBG_STARTUP, "DMA page type count = %d", sizeof(dmaIPage_t));
}
else
{
- if (!stopped)
- {
- DBG(DBG_STARTUP, "****** STOPPED ******");
- stopped = 1;
- }
+ stopped = 1;
myGpioDelay(5000);
if (DMAstarted)
{
+ /* should never be executed, leave code just in case */
+
+ gpioCfg.showStats = 1;
+
dmaInitCbs();
flushMemory();
- initDMAgo((uint32_t *)dmaIn, (uint32_t)dmaIPhys[0]);
+ initDMAgo((uint32_t *)dmaIn, (uint32_t)dmaIBus[0]);
myGpioDelay(5000); /* let DMA run for a while */
oldSlot = dmaCurrentSlot(dmaNowAtICB());
gpioStats.DMARestarts++;
diff += (TICKSLOTS/2);
- if (diff < 0) gpioStats.diffTick[0]++;
+ if (diff < 0)
+ {
+ /* shouldn't happen */
+
+ gpioCfg.showStats = 1;
+
+ gpioStats.diffTick[0]++;
+ }
else if (diff >= TICKSLOTS)
+ {
+ /* shouldn't happen */
+
+ gpioCfg.showStats = 1;
+
gpioStats.diffTick[TICKSLOTS-1]++;
+ }
else gpioStats.diffTick[diff]++;
}
/* ----------------------------------------------------------------------- */
-static int initZaps
-(
- int pmapFd,
- dmaPage_t *dmaV1,
- dmaPage_t *dmaV2[],
- dmaPage_t *dmaP[],
- int pages)
-{
- int n;
- long index;
- off_t offset;
- ssize_t t;
- int status;
- uint32_t pageAdr2;
- unsigned long long pa;
-
- DBG(DBG_STARTUP, "");
-
- status = 0;
-
- pageAdr2 = (uint32_t) dmaV2[0];
-
- index = ((uint32_t)dmaV1 / PAGE_SIZE) * 8;
-
- offset = lseek(pmapFd, index, SEEK_SET);
-
- if (offset != index)
- SOFT_ERROR(PI_INIT_FAILED, "lseek pagemap failed (%m)");
-
- for (n=0; n<pages; n++)
- {
- t = read(pmapFd, &pa, sizeof(pa));
-
- if (t != sizeof(pa))
- SOFT_ERROR(PI_INIT_FAILED, "read pagemap failed (%m)");
-
- DBG(DBG_STARTUP, "pf%d=%016llX", n, pa);
-
- dmaP[n] = (dmaPage_t *) (uint32_t) (PAGE_SIZE * (pa & 0xFFFFFFFF));
-
- dmaV2[n] = mmap
- (
- (void *)pageAdr2,
- PAGE_SIZE,
- PROT_READ|PROT_WRITE,
- MAP_SHARED|MAP_FIXED|MAP_LOCKED|MAP_NORESERVE,
- fdMem,
- (uint32_t)dmaP[n] | DMA_BUS_CACHE
- );
-
- pageAdr2 += PAGE_SIZE;
-
- if (dmaP[n] == 0) status = 1;
- }
-
- return status;
-}
-
-/* ----------------------------------------------------------------------- */
-
static uint32_t * initMapMem(int fd, uint32_t addr, uint32_t len)
{
return (uint32_t *) mmap(0, len,
/* ----------------------------------------------------------------------- */
-static int initDMAblock(int pagemapFd, int block)
+static int initZaps
+ (int pmapFd, void *virtualBase, int basePage, int pages)
+{
+ int n;
+ long index;
+ off_t offset;
+ ssize_t t;
+ uint32_t physical;
+ int status;
+ uint32_t pageAdr;
+ unsigned long long pa;
+
+ DBG(DBG_STARTUP, "");
+
+ status = 0;
+
+ pageAdr = (uint32_t) dmaVirt[basePage];
+
+ index = ((uint32_t)virtualBase / PAGE_SIZE) * 8;
+
+ offset = lseek(pmapFd, index, SEEK_SET);
+
+ if (offset != index)
+ SOFT_ERROR(PI_INIT_FAILED, "lseek pagemap failed (%m)");
+
+ for (n=0; n<pages; n++)
+ {
+ t = read(pmapFd, &pa, sizeof(pa));
+
+ if (t != sizeof(pa))
+ SOFT_ERROR(PI_INIT_FAILED, "read pagemap failed (%m)");
+
+ DBG(DBG_STARTUP, "pf%d=%016llX", n, pa);
+
+ physical = 0x3FFFFFFF & (PAGE_SIZE * (pa & 0xFFFFFFFF));
+
+ if (physical)
+ {
+ dmaBus[basePage+n] = (dmaPage_t *) (physical | pi_dram_bus);
+
+ dmaVirt[basePage+n] = mmap
+ (
+ (void *)pageAdr,
+ PAGE_SIZE,
+ PROT_READ|PROT_WRITE,
+ MAP_SHARED|MAP_FIXED|MAP_LOCKED|MAP_NORESERVE,
+ fdMem,
+ physical
+ );
+ }
+ else status = 1;
+
+ pageAdr += PAGE_SIZE;
+ }
+
+ return status;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static int initPagemapBlock(int block)
{
int trys, ok;
unsigned pageNum;
- DBG(DBG_STARTUP, "");
+ DBG(DBG_STARTUP, "block=%d", block);
- dmaBloc[block] = mmap(
+ dmaPMapBlk[block] = mmap(
0, (PAGES_PER_BLOCK*PAGE_SIZE),
PROT_READ|PROT_WRITE,
MAP_SHARED|MAP_ANONYMOUS|MAP_NORESERVE|MAP_LOCKED,
-1, 0);
- if (dmaBloc[block] == MAP_FAILED)
+ if (dmaPMapBlk[block] == MAP_FAILED)
SOFT_ERROR(PI_INIT_FAILED, "mmap dma block %d failed (%m)", block);
/* force allocation of physical memory */
- memset((void *)dmaBloc[block], 0, (PAGES_PER_BLOCK*PAGE_SIZE));
+ memset((void *)dmaPMapBlk[block], 0xAA, (PAGES_PER_BLOCK*PAGE_SIZE));
- memset((void *)dmaBloc[block], 0xFF, (PAGES_PER_BLOCK*PAGE_SIZE));
+ memset((void *)dmaPMapBlk[block], 0xFF, (PAGES_PER_BLOCK*PAGE_SIZE));
- memset((void *)dmaBloc[block], 0, (PAGES_PER_BLOCK*PAGE_SIZE));
+ memset((void *)dmaPMapBlk[block], 0, (PAGES_PER_BLOCK*PAGE_SIZE));
pageNum = block * PAGES_PER_BLOCK;
while ((trys < 10) && !ok)
{
- if (initZaps(pagemapFd,
- dmaBloc[block],
- &dmaVirt[pageNum],
- &dmaPhys[pageNum],
+ if (initZaps(fdPmap,
+ dmaPMapBlk[block],
+ pageNum,
PAGES_PER_BLOCK) == 0) ok = 1;
else myGpioDelay(50000);
return 0;
}
+static int initMboxBlock(int block)
+{
+ int n, ok;
+ unsigned page;
+ uintptr_t virtualAdr;
+ uintptr_t busAdr;
+
+ DBG(DBG_STARTUP, "block=%d", block);
+
+ ok = mbDMAAlloc
+ (&dmaMboxBlk[block], PAGES_PER_BLOCK * PAGE_SIZE, pi_mem_flag);
+
+ if (!ok) SOFT_ERROR(PI_INIT_FAILED, "init mbox zaps failed");
+
+ page = block * PAGES_PER_BLOCK;
+
+ virtualAdr = (uintptr_t) dmaMboxBlk[block].virtual_addr;
+ busAdr = dmaMboxBlk[block].bus_addr;
+
+ for (n=0; n<PAGES_PER_BLOCK; n++)
+ {
+ dmaVirt[page+n] = (dmaPage_t *) virtualAdr;
+ dmaBus[page+n] = (dmaPage_t *) busAdr;
+ virtualAdr += PAGE_SIZE;
+ busAdr += PAGE_SIZE;
+ }
+
+ return 0;
+}
+
/* ----------------------------------------------------------------------- */
-static int initDMAcbs(void)
+static int initAllocDMAMem(void)
{
- int pid;
- char str[64];
- int pagemapFd;
int i, servoCycles, superCycles;
+ int status;
DBG(DBG_STARTUP, "");
gpioCfg.bufferMilliseconds, gpioCfg.clockMicros,
bufferBlocks, bufferCycles);
- /* allocate memory for pointers to virtual and physical pages */
-
- dmaBloc = mmap(
- 0, (bufferBlocks+PI_WAVE_BLOCKS)*sizeof(dmaPage_t *),
- PROT_READ|PROT_WRITE,
- MAP_PRIVATE|MAP_ANONYMOUS|MAP_LOCKED,
- -1, 0);
-
- if (dmaBloc == MAP_FAILED)
- SOFT_ERROR(PI_INIT_FAILED, "mmap dma virtual failed (%m)");
+ /* allocate memory for pointers to virtual and bus memory pages */
dmaVirt = mmap(
0, PAGES_PER_BLOCK*(bufferBlocks+PI_WAVE_BLOCKS)*sizeof(dmaPage_t *),
if (dmaVirt == MAP_FAILED)
SOFT_ERROR(PI_INIT_FAILED, "mmap dma virtual failed (%m)");
- dmaPhys = mmap(
+ dmaBus = mmap(
0, PAGES_PER_BLOCK*(bufferBlocks+PI_WAVE_BLOCKS)*sizeof(dmaPage_t *),
PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS|MAP_LOCKED,
-1, 0);
- if (dmaPhys == MAP_FAILED)
- SOFT_ERROR(PI_INIT_FAILED, "mmap dma physical failed (%m)");
+ if (dmaBus == MAP_FAILED)
+ SOFT_ERROR(PI_INIT_FAILED, "mmap dma bus failed (%m)");
- dmaIPhys = (dmaIPage_t **) dmaPhys;
dmaIVirt = (dmaIPage_t **) dmaVirt;
+ dmaIBus = (dmaIPage_t **) dmaBus;
- dmaOPhys = (dmaOPage_t **)(dmaPhys + (PAGES_PER_BLOCK*bufferBlocks));
dmaOVirt = (dmaOPage_t **)(dmaVirt + (PAGES_PER_BLOCK*bufferBlocks));
+ dmaOBus = (dmaOPage_t **)(dmaBus + (PAGES_PER_BLOCK*bufferBlocks));
- pid = getpid();
+ if ((gpioCfg.memAllocMode == PI_MEM_ALLOC_PAGEMAP) ||
+ ((gpioCfg.memAllocMode == PI_MEM_ALLOC_AUTO) &&
+ (gpioCfg.bufferMilliseconds > PI_DEFAULT_BUFFER_MILLIS)))
+ {
+ /* pagemap allocation of DMA memory */
- sprintf(str, "/proc/%d/pagemap", pid);
+ dmaPMapBlk = mmap(
+ 0, (bufferBlocks+PI_WAVE_BLOCKS)*sizeof(dmaPage_t *),
+ PROT_READ|PROT_WRITE,
+ MAP_PRIVATE|MAP_ANONYMOUS|MAP_LOCKED,
+ -1, 0);
- pagemapFd = open(str, O_RDONLY);
-
- if (pagemapFd < 0)
- SOFT_ERROR(PI_INIT_FAILED, "open pagemap failed(%m)");
+ if (dmaPMapBlk == MAP_FAILED)
+ SOFT_ERROR(PI_INIT_FAILED, "pagemap mmap block failed (%m)");
+
+ fdPmap = open("/proc/self/pagemap", O_RDONLY);
+
+ if (fdPmap < 0)
+ SOFT_ERROR(PI_INIT_FAILED, "pagemap open failed(%m)");
+
+ for (i=0; i<(bufferBlocks+PI_WAVE_BLOCKS); i++)
+ {
+ status = initPagemapBlock(i);
+ if (status < 0)
+ {
+ close(fdPmap);
+ return status;
+ }
+ }
+
+ close(fdPmap);
+
+ DBG(DBG_STARTUP, "dmaPMapBlk=%08X dmaIn=%08X",
+ (uint32_t)dmaPMapBlk, (uint32_t)dmaIn);
+ }
+ else
+ {
+ /* mailbox allocation of DMA memory */
+
+ dmaMboxBlk = mmap(
+ 0, (bufferBlocks+PI_WAVE_BLOCKS)*sizeof(DMAMem_t),
+ PROT_READ|PROT_WRITE,
+ MAP_PRIVATE|MAP_ANONYMOUS|MAP_LOCKED,
+ -1, 0);
- for (i=0; i<(bufferBlocks+PI_WAVE_BLOCKS); i++) initDMAblock(pagemapFd, i);
+ if (dmaMboxBlk == MAP_FAILED)
+ SOFT_ERROR(PI_INIT_FAILED, "mmap mbox block failed (%m)");
- close(pagemapFd);
+ if (mbCreate() < 0)
+ SOFT_ERROR(PI_INIT_FAILED, "mbox create failed(%m)");
- DBG(DBG_STARTUP, "dmaBloc=%08X dmaIn=%08X",
- (uint32_t)dmaBloc, (uint32_t)dmaIn);
+ fdMbox = mbOpen();
+
+ if (fdMbox < 0)
+ SOFT_ERROR(PI_INIT_FAILED, "mbox open failed(%m)");
+
+ for (i=0; i<(bufferBlocks+PI_WAVE_BLOCKS); i++)
+ {
+ status = initMboxBlock(i);
+ if (status < 0)
+ {
+ mbClose(fdMbox);
+ return status;
+ }
+ }
+
+ mbClose(fdMbox);
+
+ DBG(DBG_STARTUP, "dmaMboxBlk=%08X dmaIn=%08X",
+ (uint32_t)dmaMboxBlk, (uint32_t)dmaIn);
+ }
DBG(DBG_STARTUP,
"gpioReg=%08X pwmReg=%08X pcmReg=%08X clkReg=%08X auxReg=%08X",
(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]);
+ DBG(DBG_STARTUP, "dmaIBus[%d]=%08X", i, (uint32_t)dmaIBus[i]);
if (gpioCfg.dbgLevel >= DBG_DMACBS)
{
dmaAddr[DMA_CS] = DMA_INTERRUPT_STATUS | DMA_END_FLAG;
- dmaAddr[DMA_CONBLK_AD] = cbAddr | DMA_BUS_ADR;
+ dmaAddr[DMA_CONBLK_AD] = cbAddr;
/* clear READ/FIFO/READ_LAST_NOT_SET error bits */
fdMem = -1;
fdSock = -1;
- dmaBloc = MAP_FAILED;
+ dmaMboxBlk = MAP_FAILED;
+ dmaPMapBlk = MAP_FAILED;
dmaVirt = MAP_FAILED;
- dmaPhys = MAP_FAILED;
+ dmaBus = MAP_FAILED;
auxReg = MAP_FAILED;
clkReg = MAP_FAILED;
systReg = MAP_FAILED;
spiReg = MAP_FAILED;
+ if (dmaBus != MAP_FAILED)
+ {
+ munmap(dmaBus,
+ PAGES_PER_BLOCK*(bufferBlocks+PI_WAVE_BLOCKS)*sizeof(dmaPage_t *));
+ }
+
+ dmaBus = MAP_FAILED;
+
if (dmaVirt != MAP_FAILED)
{
for (i=0; i<PAGES_PER_BLOCK*(bufferBlocks+PI_WAVE_BLOCKS); i++)
dmaVirt = MAP_FAILED;
- if (dmaPhys != MAP_FAILED)
+ if (dmaPMapBlk != MAP_FAILED)
{
- for (i=0; i<PAGES_PER_BLOCK*(bufferBlocks+PI_WAVE_BLOCKS); i++)
+ for (i=0; i<(bufferBlocks+PI_WAVE_BLOCKS); i++)
{
- munmap(dmaPhys[i], PAGE_SIZE);
+ munmap(dmaPMapBlk[i], PAGES_PER_BLOCK*PAGE_SIZE);
}
- munmap(dmaPhys,
- PAGES_PER_BLOCK*(bufferBlocks+PI_WAVE_BLOCKS)*sizeof(dmaPage_t *));
+ munmap(dmaPMapBlk, (bufferBlocks+PI_WAVE_BLOCKS)*sizeof(dmaPage_t *));
}
- dmaPhys = MAP_FAILED;
+ dmaPMapBlk = MAP_FAILED;
- if (dmaBloc != MAP_FAILED)
+ if (dmaMboxBlk != MAP_FAILED)
{
+ fdMbox = mbOpen();
+
for (i=0; i<(bufferBlocks+PI_WAVE_BLOCKS); i++)
{
- munmap(dmaBloc[i], PAGES_PER_BLOCK*PAGE_SIZE);
+ mbDMAFree(&dmaMboxBlk[bufferBlocks+PI_WAVE_BLOCKS-i-1]);
}
- munmap(dmaBloc, (bufferBlocks+PI_WAVE_BLOCKS)*sizeof(dmaPage_t *));
+ mbClose(fdMbox);
+
+ munmap(dmaMboxBlk, (bufferBlocks+PI_WAVE_BLOCKS)*sizeof(DMAMem_t));
}
- dmaBloc = MAP_FAILED;
+ dmaMboxBlk = MAP_FAILED;
if (inpFifo != NULL)
{
close(fdSock);
fdSock = -1;
}
-}
-
-/* ======================================================================= */
-
-int getBitInBytes(int bitPos, char *buf, int numBits)
-{
- int bitp, bufp;
- if (bitPos < numBits)
+ if (fdPmap != -1)
{
- bufp = bitPos / 8;
- bitp = 7 - (bitPos % 8);
- if (buf[bufp] & (1<<bitp)) return 1;
+ close(fdPmap);
+ fdPmap = -1;
}
- return 0;
+ if (fdMbox != -1)
+ {
+ close(fdMbox);
+ fdMbox = -1;
+ }
+}
+
+int initInitialise(void)
+{
+ int i;
+ struct sockaddr_in server;
+ char * portStr;
+ unsigned port;
+ struct sched_param param;
+
+ waveClockInited = 0;
+
+ clock_gettime(CLOCK_REALTIME, &libStarted);
+
+ DBG(DBG_STARTUP, "");
+
+ if (libInitialised) return PIGPIO_VERSION;
+
+ initClearGlobals();
+
+ if (initCheckPermitted() < 0) return PI_INIT_FAILED;
+
+ fdLock = initGrabLockFile();
+
+ if (fdLock < 0)
+ SOFT_ERROR(PI_INIT_FAILED, "Can't lock %s", PI_LOCKFILE);
+
+ if (!gpioMaskSet)
+ {
+ i = gpioHardwareRevision();
+
+ if (i == 0) gpioMask = PI_DEFAULT_UPDATE_MASK_R0;
+ else if (i == 17) gpioMask = PI_DEFAULT_UPDATE_MASK_COMPUTE;
+ else if (i < 4) gpioMask = PI_DEFAULT_UPDATE_MASK_R1;
+ else if (i < 16) gpioMask = PI_DEFAULT_UPDATE_MASK_R2;
+ else gpioMask = PI_DEFAULT_UPDATE_MASK_R3;
+
+ gpioMaskSet = 1;
+ }
+
+ sigSetHandler();
+
+ if (initPeripherals() < 0) return PI_INIT_FAILED;
+
+ if (initAllocDMAMem() < 0) return PI_INIT_FAILED;
+
+ /* done with /dev/mem */
+
+ if (fdMem != -1)
+ {
+ close(fdMem);
+ fdMem = -1;
+ }
+
+ param.sched_priority = sched_get_priority_max(SCHED_FIFO);
+
+ sched_setscheduler(0, SCHED_FIFO, ¶m);
+
+ initClock(1); /* initialise main clock */
+
+ libInitialised = 1;
+
+ atexit(gpioTerminate);
+
+ if (pthread_attr_init(&pthAttr))
+ SOFT_ERROR(PI_INIT_FAILED, "pthread_attr_init failed (%m)");
+
+ if (pthread_attr_setstacksize(&pthAttr, STACK_SIZE))
+ SOFT_ERROR(PI_INIT_FAILED, "pthread_attr_setstacksize failed (%m)");
+
+ if (pthread_create(&pthAlert, &pthAttr, pthAlertThread, &i))
+ SOFT_ERROR(PI_INIT_FAILED, "pthread_create alert failed (%m)");
+
+ pthAlertRunning = 1;
+
+ if (!(gpioCfg.ifFlags & PI_DISABLE_FIFO_IF))
+ {
+ if (pthread_create(&pthFifo, &pthAttr, pthFifoThread, &i))
+ SOFT_ERROR(PI_INIT_FAILED, "pthread_create fifo failed (%m)");
+
+ pthFifoRunning = 1;
+ }
+
+ if (!(gpioCfg.ifFlags & PI_DISABLE_SOCK_IF))
+ {
+ fdSock = socket(AF_INET , SOCK_STREAM , 0);
+
+ if (fdSock == -1)
+ SOFT_ERROR(PI_INIT_FAILED, "socket failed (%m)");
+
+ portStr = getenv(PI_ENVPORT);
+
+ if (portStr) port = atoi(portStr); else port = gpioCfg.socketPort;
+
+ server.sin_family = AF_INET;
+ server.sin_addr.s_addr = INADDR_ANY;
+ server.sin_port = htons(port);
+
+ if (bind(fdSock,(struct sockaddr *)&server , sizeof(server)) < 0)
+ SOFT_ERROR(PI_INIT_FAILED, "bind to port %d failed (%m)", port);
+
+ if (pthread_create(&pthSocket, &pthAttr, pthSocketThread, &i))
+ SOFT_ERROR(PI_INIT_FAILED, "pthread_create socket failed (%m)");
+
+ pthSocketRunning = 1;
+ }
+
+ myGpioDelay(10000);
+
+ dmaInitCbs();
+
+ flushMemory();
+
+ initDMAgo((uint32_t *)dmaIn, (uint32_t)dmaIBus[0]);
+
+ myGpioDelay(20000);
+
+ DMAstarted = 1;
+
+ return PIGPIO_VERSION;
+}
+
+
+/* ======================================================================= */
+
+int getBitInBytes(int bitPos, char *buf, int numBits)
+{
+ int bitp, bufp;
+
+ if (bitPos < numBits)
+ {
+ bufp = bitPos / 8;
+ bitp = 7 - (bitPos % 8);
+ if (buf[bufp] & (1<<bitp)) return 1;
+ }
+
+ return 0;
}
/* ----------------------------------------------------------------------- */
int gpioInitialise(void)
{
- int i;
- struct sockaddr_in server;
- char * portStr;
- unsigned port;
- struct sched_param param;
-
- waveClockInited = 0;
-
- clock_gettime(CLOCK_REALTIME, &libStarted);
-
- DBG(DBG_STARTUP, "");
-
- if (libInitialised) return PIGPIO_VERSION;
-
- initClearGlobals();
-
- if (initCheckPermitted() < 0) return PI_INIT_FAILED;
-
- fdLock = initGrabLockFile();
-
- if (fdLock < 0)
- SOFT_ERROR(PI_INIT_FAILED, "Can't lock %s", PI_LOCKFILE);
-
- if (!gpioMaskSet)
- {
- i = gpioHardwareRevision();
-
- if (i == 0) gpioMask = PI_DEFAULT_UPDATE_MASK_R0;
- else if (i == 17) gpioMask = PI_DEFAULT_UPDATE_MASK_COMPUTE;
- else if (i < 4) gpioMask = PI_DEFAULT_UPDATE_MASK_R1;
- else if (i < 16) gpioMask = PI_DEFAULT_UPDATE_MASK_R2;
- else gpioMask = PI_DEFAULT_UPDATE_MASK_R3;
-
- gpioMaskSet = 1;
- }
-
- sigSetHandler();
-
- if (initPeripherals() < 0) return PI_INIT_FAILED;
-
- if (initDMAcbs() < 0) return PI_INIT_FAILED;
-
- /* done with /dev/mem */
-
- if (fdMem != -1)
- {
- close(fdMem);
- fdMem = -1;
- }
-
- param.sched_priority = sched_get_priority_max(SCHED_FIFO);
-
- sched_setscheduler(0, SCHED_FIFO, ¶m);
-
- initClock(1); /* initialise main clock */
-
- libInitialised = 1;
-
- atexit(gpioTerminate);
-
- if (pthread_attr_init(&pthAttr))
- SOFT_ERROR(PI_INIT_FAILED, "pthread_attr_init failed (%m)");
-
- if (pthread_attr_setstacksize(&pthAttr, STACK_SIZE))
- SOFT_ERROR(PI_INIT_FAILED, "pthread_attr_setstacksize failed (%m)");
-
- if (pthread_create(&pthAlert, &pthAttr, pthAlertThread, &i))
- SOFT_ERROR(PI_INIT_FAILED, "pthread_create alert failed (%m)");
-
- pthAlertRunning = 1;
-
- if (!(gpioCfg.ifFlags & PI_DISABLE_FIFO_IF))
- {
- if (pthread_create(&pthFifo, &pthAttr, pthFifoThread, &i))
- SOFT_ERROR(PI_INIT_FAILED, "pthread_create fifo failed (%m)");
+ int status;
- pthFifoRunning = 1;
- }
+ status = initInitialise();
- if (!(gpioCfg.ifFlags & PI_DISABLE_SOCK_IF))
+ if (status < 0)
{
- fdSock = socket(AF_INET , SOCK_STREAM , 0);
-
- if (fdSock == -1)
- SOFT_ERROR(PI_INIT_FAILED, "socket failed (%m)");
-
- portStr = getenv(PI_ENVPORT);
-
- if (portStr) port = atoi(portStr); else port = gpioCfg.socketPort;
-
- server.sin_family = AF_INET;
- server.sin_addr.s_addr = INADDR_ANY;
- server.sin_port = htons(port);
-
- if (bind(fdSock,(struct sockaddr *)&server , sizeof(server)) < 0)
- SOFT_ERROR(PI_INIT_FAILED, "bind to port %d failed (%m)", port);
-
- if (pthread_create(&pthSocket, &pthAttr, pthSocketThread, &i))
- SOFT_ERROR(PI_INIT_FAILED, "pthread_create socket failed (%m)");
-
- pthSocketRunning = 1;
+ initReleaseResources();
}
- myGpioDelay(10000);
-
- dmaInitCbs();
-
- flushMemory();
-
- initDMAgo((uint32_t *)dmaIn, (uint32_t)dmaIPhys[0]);
-
- myGpioDelay(20000);
-
- DMAstarted = 1;
-
- return PIGPIO_VERSION;
- }
+ return status;
+}
/* ----------------------------------------------------------------------- */
if (gpioCfg.showStats)
{
fprintf(stderr,
- "micros=%d dmaInitCbs=%d DMA restarts=%d\n",
- gpioCfg.clockMicros, gpioStats.dmaInitCbsCount,
- gpioStats.DMARestarts);
+ "If you didn't request stats please cut & paste the\n"
+ "following and e-mail to pigpio@abyz.co.uk\n");
+
+ fprintf(stderr,
+ "#####################################################\n");
+
+ fprintf(stderr,
+ "micros=%d allocMode=%d dmaInitCbs=%d DMARestarts=%d\n",
+ gpioCfg.clockMicros, gpioCfg.memAllocMode,
+ gpioStats.dmaInitCbsCount, gpioStats.DMARestarts);
- fprintf(stderr, "samples %u maxSamples %u maxEmit %u emitFrags %u\n",
+ fprintf(stderr,
+ "samples %u maxSamples %u maxEmit %u emitFrags %u\n",
gpioStats.numSamples, gpioStats.maxSamples,
gpioStats.maxEmit, gpioStats.emitFrags);
- fprintf(stderr, "cb time %d, calls %u alert ticks %u\n",
+ fprintf(stderr, "cbTicks %d, cbCalls %u alertTicks %u\n",
gpioStats.cbTicks, gpioStats.cbCalls, gpioStats.alertTicks);
for (i=0; i< TICKSLOTS; i++)
fprintf(stderr, "%9u ", gpioStats.diffTick[i]);
fprintf(stderr, "\n");
+
+ fprintf(stderr,
+ "#####################################################\n");
}
}
int gpioGetPWMrealRange(unsigned gpio)
{
+ unsigned pwm;
+
DBG(DBG_USER, "gpio=%d", gpio);
CHECK_INITED;
switch (gpioInfo[gpio].is)
{
case GPIO_HW_PWM:
+ pwm = (PWMDef[gpio] >> 4) & 3;
+ return hw_pwm_real_range[pwm];
+
case GPIO_HW_CLK:
return PI_HW_PWM_RANGE;
for (i=0; i<cb; i++) waveCbOPrint(i);
}
- initDMAgo((uint32_t *)dmaOut, (uint32_t)dmaOPhys[0]);
+ initDMAgo((uint32_t *)dmaOut, (uint32_t)dmaOBus[0]);
return cb;
p = rawWaveCBAdr(waveInfo[wave_id].topCB);
if (wave_mode == PI_WAVE_MODE_ONE_SHOT) p->next = 0;
- else p->next = waveCbPOadr(waveInfo[wave_id].botCB+1) | DMA_BUS_ADR;
+ else p->next = waveCbPOadr(waveInfo[wave_id].botCB+1);
dmaOut[DMA_CS] = DMA_CHANNEL_RESET;
uint32_t cfreq[CLK_SRCS]={CLK_OSC_FREQ, CLK_PLLD_FREQ};
unsigned clock, mode, mash;
int password = 0;
+ double f;
clkInf_t clkInf={0,0,0};
DBG(DBG_USER, "gpio=%d frequency=%d", gpio, frequency);
{
if (chooseBestClock(&clkInf, frequency, CLK_SRCS, cfreq))
{
- /* record the clock frequency */
-
- hw_clk_freq[clock] = frequency;
+ if (clkInf.frac == 0) mash = 0;
initHWClk(cctl[clock], cdiv[clock],
csrc[clkInf.clock], clkInf.div, clkInf.frac, mash);
gpioSetMode(gpio, mode);
gpioInfo[gpio].is = GPIO_HW_CLK;
+
+ f = (double) cfreq[clkInf.clock] /
+ ((double)clkInf.div + ((double)clkInf.frac / 4096.0));
+
+ hw_clk_freq[clock] = (f + 0.5);
+
+ DBG(DBG_USER, "cf=%d div=%d frac=%d mash=%d",
+ cfreq[clkInf.clock], clkInf.div, clkInf.frac, mash);
}
else
{
int gpioHardwarePWM(
unsigned gpio, unsigned frequency, unsigned dutycycle)
{
- int csrc[CLK_SRCS] = {CLK_CTL_SRC_OSC, CLK_CTL_SRC_PLLD};
- uint32_t cfreq[CLK_SRCS]={CLK_OSC_FREQ, CLK_PLLD_FREQ};
uint32_t old_PWM_CTL;
- unsigned pwm, mode,mash;
- clkInf_t clkInf={0,0,0};
+ unsigned pwm, mode;
+ uint32_t real_range, real_dutycycle;
DBG(DBG_USER, "gpio=%d frequency=%d dutycycle=%d",
gpio, frequency, dutycycle);
pwm = (PWMDef[gpio] >> 4) & 3;
mode = PWMDef[gpio] & 7;
- frequency *= PI_HW_PWM_RANGE;
-
- mash = frequency < PI_MASH_MAX_FREQ ? 1 : 0;
-
if (frequency)
{
- if (chooseBestClock(&clkInf, frequency, CLK_SRCS, cfreq))
- {
- /* record the PWM frequency and dutycycle */
+ real_range = ((double)CLK_PLLD_FREQ / (2.0 * frequency)) + 0.5;
+ real_dutycycle = ((uint64_t)dutycycle * real_range) / PI_HW_PWM_RANGE;
- /* currently both channels must use the same update rate */
+ /* record the set PWM frequency and dutycycle */
- hw_pwm_freq[0] = frequency / PI_HW_PWM_RANGE;
- hw_pwm_freq[1] = frequency / PI_HW_PWM_RANGE;
+ hw_pwm_freq[pwm] =
+ ((double)CLK_PLLD_FREQ / ( 2.0 * real_range)) + 0.5;
- hw_pwm_duty[pwm] = dutycycle;
+ hw_pwm_duty[pwm] = dutycycle;
- /* Abort any waveform transmission in progress */
+ hw_pwm_real_range[pwm] = real_range;
- if (gpioWaveTxBusy()) gpioWaveTxStop();
+ /* Abort any waveform transmission in progress */
- waveClockInited = 0;
+ if (gpioWaveTxBusy()) gpioWaveTxStop();
- /* preserve channel enable only and mark space mode */
+ waveClockInited = 0;
- old_PWM_CTL = pwmReg[PWM_CTL] &
- (PWM_CTL_PWEN1 | PWM_CTL_MSEN1 | PWM_CTL_PWEN2 | PWM_CTL_MSEN2);
+ /* preserve channel enable only and mark space mode */
- pwmReg[PWM_CTL] = 0;
+ old_PWM_CTL = pwmReg[PWM_CTL] &
+ (PWM_CTL_PWEN1 | PWM_CTL_MSEN1 | PWM_CTL_PWEN2 | PWM_CTL_MSEN2);
- myGpioDelay(10);
-
- initHWClk(CLK_PWMCTL, CLK_PWMDIV,
- csrc[clkInf.clock], clkInf.div, clkInf.frac, mash);
-
- if (pwm == 0)
- {
- pwmReg[PWM_RNG1] = PI_HW_PWM_RANGE;
- myGpioDelay(10);
- pwmReg[PWM_DAT1] = dutycycle;
- myGpioDelay(10);
+ pwmReg[PWM_CTL] = 0;
- pwmReg[PWM_CTL] = (old_PWM_CTL | PWM_CTL_PWEN1 | PWM_CTL_MSEN1);
- }
- else
- {
- pwmReg[PWM_RNG2] = PI_HW_PWM_RANGE;
- myGpioDelay(10);
- pwmReg[PWM_DAT2] = dutycycle;
- myGpioDelay(10);
-
- pwmReg[PWM_CTL] = (old_PWM_CTL | PWM_CTL_PWEN2 | PWM_CTL_MSEN2);
- }
+ myGpioDelay(10);
- if (gpioInfo[gpio].is != GPIO_HW_PWM)
- {
- switchFunctionOff(gpio);
+ initHWClk(CLK_PWMCTL, CLK_PWMDIV, CLK_CTL_SRC_PLLD, 2, 0, 0);
- gpioSetMode(gpio, mode);
+ if (pwm == 0)
+ {
+ pwmReg[PWM_RNG1] = real_range;
+ myGpioDelay(10);
+ pwmReg[PWM_DAT1] = real_dutycycle;
+ myGpioDelay(10);
- gpioInfo[gpio].is = GPIO_HW_PWM;
- }
+ pwmReg[PWM_CTL] = (old_PWM_CTL | PWM_CTL_PWEN1 | PWM_CTL_MSEN1);
}
else
{
- SOFT_ERROR(PI_BAD_HPWM_FREQ,
- "bad hardware PWM frequency (%d)", frequency/PI_HW_PWM_RANGE);
+ pwmReg[PWM_RNG2] = real_range;
+ myGpioDelay(10);
+ pwmReg[PWM_DAT2] = real_dutycycle;
+ myGpioDelay(10);
+
+ pwmReg[PWM_CTL] = (old_PWM_CTL | PWM_CTL_PWEN2 | PWM_CTL_MSEN2);
+ }
+
+ if (gpioInfo[gpio].is != GPIO_HW_PWM)
+ {
+ switchFunctionOff(gpio);
+
+ gpioSetMode(gpio, mode);
+
+ gpioInfo[gpio].is = GPIO_HW_PWM;
}
}
else
{
piModel = 1;
chars = 4;
- PI_PERI_BASE = 0x20000000;
- DMA_BUS_ADR = 0x40000000;
- DMA_BUS_CACHE = 0x40000000;
+ pi_peri_phys = 0x20000000;
+ pi_dram_bus = 0x40000000;
+ pi_mem_flag = 0x0c;
}
else if (strstr (buf, "ARMv7") != NULL)
{
piModel = 2;
chars = 6;
- PI_PERI_BASE = 0x3F000000;
- DMA_BUS_ADR = 0xC0000000;
- DMA_BUS_CACHE = 0x00000000;
+ pi_peri_phys = 0x3F000000;
+ pi_dram_bus = 0xC0000000;
+ pi_mem_flag = 0x04;
}
}
}
}
+/* ----------------------------------------------------------------------- */
+
+int gpioCfgMemAlloc(unsigned memAllocMode)
+{
+ DBG(DBG_USER, "memAllocMode=%d", memAllocMode);
+
+ CHECK_NOT_INITED;
+
+ if (memAllocMode > PI_MEM_ALLOC_MAILBOX)
+ SOFT_ERROR(
+ PI_BAD_MALLOC_MODE, "bad mem alloc mode (%d)", memAllocMode);
+
+ gpioCfg.memAllocMode = memAllocMode;
+
+ return 0;
+}
+
+
/* ----------------------------------------------------------------------- */
int gpioCfgInternals(unsigned cfgWhat, int cfgVal)
#include <stdint.h>
#include <pthread.h>
-#define PIGPIO_VERSION 29
+#define PIGPIO_VERSION 30
/*TEXT
All the functions which return an int return < 0 on error.
-If the library isn't initialised all but the [*gpioCfg**], [*gpioVersion*],
+If the library is not initialised all but the [*gpioCfg**], [*gpioVersion*],
and [*gpioHardwareRevision*] functions will return PI_NOT_INITIALISED.
If the library is initialised the [*gpioCfg**] functions will
gpioWaveGetHighPulses Length of longest waveform so far
gpioWaveGetMaxPulses Absolute maximum allowed pulses
-gpioWaveGetCbs Length in cbs of the current waveform
+gpioWaveGetCbs Length in control blocks of the current waveform
gpioWaveGetHighCbs Length of longest waveform so far
-gpioWaveGetMaxCbs Absolute maximum allowed cbs
+gpioWaveGetMaxCbs Absolute maximum allowed control blocks
gpioWaveTxStart Creates/transmits a waveform (DEPRECATED)
gpioCfgInterfaces Configure user interfaces
gpioCfgInternals Configure miscellaneous internals
gpioCfgSocketPort Configure socket port
+gpioCfgMemAlloc Configure DMA memory allocation mode
+
+CUSTOM
+
+gpioCustom1 User custom function 1
+gpioCustom2 User custom function 2
UTILITIES
#define PI_LOW 0
#define PI_HIGH 1
-/* level: only reported for gpio timeout, see gpioSetWatchdog */
+/* level: only reported for gpio time-out, see gpioSetWatchdog */
#define PI_TIMEOUT 2
/* hardware PWM */
-#define PI_HW_PWM_MIN_FREQ 5
-#define PI_HW_PWM_MAX_FREQ 50000
-#define PI_HW_PWM_RANGE 5000
+#define PI_HW_PWM_MIN_FREQ 1
+#define PI_HW_PWM_MAX_FREQ 125000000
+#define PI_HW_PWM_RANGE 1000000
/* hardware clock */
#define PI_DISABLE_FIFO_IF 1
#define PI_DISABLE_SOCK_IF 2
+/* memAllocMode */
+
+#define PI_MEM_ALLOC_AUTO 0
+#define PI_MEM_ALLOC_PAGEMAP 1
+#define PI_MEM_ALLOC_MAILBOX 2
/*F*/
int gpioInitialise(void);
Call before program exit.
-This function resets the DMA and PWM peripherals, releases memory, and
+This function resets the used DMA channels, releases memory, and
terminates any running threads.
...
PI_BAD_USER_GPIO or PI_NOT_PWM_GPIO.
For normal PWM the dutycycle will be out of the defined range
-for the gpio (see [*gpioGetPWMrange*]). If a hardware clock is
-active on the gpio the reported dutycycle will be 500 (out of 1000).
+for the gpio (see [*gpioGetPWMrange*]).
+
+If a hardware clock is active on the gpio the reported dutycycle
+will be 500000 (500k) out of 1000000 (1M).
+
If hardware PWM is active on the gpio the reported dutycycle
-will be out of a 1000.
+will be out of a 1000000 (1M).
Normal PWM range defaults to 255.
D*/
. .
If a hardware clock or hardware PWM is active on the gpio
-the reported range will be 1000.
+the reported range will be 1000000 (1M).
...
r = gpioGetPWMrange(23);
user_gpio: 0-31
. .
-If a hardware clock or hardware PWM is active on the gpio
-the reported real range will be 1000.
+If a hardware clock is active on the gpio the reported real
+range will be 1000000 (1M).
+
+If hardware PWM is active on the gpio the reported real range
+will be approximately 250M divided by the set PWM frequency.
...
rr = gpioGetPWMrealRange(17);
. .
For normal PWM the frequency will be that defined for the gpio by
-[*gpioSetPWMfrequency*]. If a hardware clock is active on the gpio
-the reported frequency will be that set by [*gpioHardwareClock*].
+[*gpioSetPWMfrequency*].
+
+If a hardware clock is active on the gpio the reported frequency
+will be that set by [*gpioHardwareClock*].
+
If hardware PWM is active on the gpio the reported frequency
will be that set by [*gpioHardwarePWM*].
The bytes returned for each character depend upon the number of
data bits [*bbBits*] specified in the [*gpioSerialReadOpen*] command.
-For [*bbBits*] 1-8 there will be one byte per character.
-For [*bbBits*] 9-16 there will be two bytes per character.
+For [*bbBits*] 1-8 there will be one byte per character.
+For [*bbBits*] 9-16 there will be two bytes per character.
For [*bbBits*] 17-32 there will be four bytes per character.
D*/
be used to 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
+An auxiliary SPI device is available on the A+/B+/Pi2 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.
. .
- spiChan: 0-1 (0-2 for B+ auxiliary device)
+ spiChan: 0-1 (0-2 for A+/B+/Pi2 auxiliary device)
spiBaud: 32K-125M (values above 30M are unlikely to work)
spiFlags: see below
. .
mm defines the SPI mode.
+Warning: modes 1 and 3 do not appear to work on the auxiliary device.
+
. .
Mode POL PHA
0 0 0
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+.
+auxiliary device is only present on the A+/B+/Pi2.
W is 0 if the device is not 3-wire, 1 if the device is 3-wire. Standard
SPI device only.
int gpioHardwareClock(unsigned gpio, unsigned clkfreq);
/*D
Starts a hardware clock on a gpio at the specified frequency.
+Frequencies above 30MHz are unlikely to work.
. .
gpio: see description
-clkfreq: 0 (off) or 4689-250M
+clkfreq: 0 (off) or 4689-250000000 (250M)
. .
Returns 0 if OK, otherwise PI_BAD_GPIO, PI_NOT_HCLK_GPIO,
. .
4 clock 0 All models
-5 clock 1 A+/B+ and compute module only (reserved for system use)
-6 clock 2 A+/B+ and compute module only
-20 clock 0 A+/B+ and compute module only
+5 clock 1 A+/B+/Pi2 and compute module only (reserved for system use)
+6 clock 2 A+/B+/Pi2 and compute module only
+20 clock 0 A+/B+/Pi2 and compute module only
21 clock 1 All models but Rev.2 B (reserved for system use)
32 clock 0 Compute module only
int gpioHardwarePWM(unsigned gpio, unsigned PWMfreq, unsigned PWMduty);
/*D
Starts hardware PWM on a gpio at the specified frequency and dutycycle.
+Frequencies above 30MHz are unlikely to work.
NOTE: Any waveform started by [*gpioWaveTxSend*] or [*gpioWaveTxStart*]
will be cancelled.
. .
gpio: see description
-PWMfreq: 0 (off) or 5-250K
-PWMduty: 0 (off) to 1000 (fully on).
+PWMfreq: 0 (off) or 1-125000000 (125M)
+PWMduty: 0 (off) to 1000000 (1M)(fully on)
. .
Returns 0 if OK, otherwise PI_BAD_GPIO, PI_NOT_HPWM_GPIO,
PI_BAD_HPWM_DUTY, PI_BAD_HPWM_FREQ, or PI_HPWM_ILLEGAL.
-Both PWM channels share the same clock and the same update frequency.
-The latest frequency setting will be used by both PWM channels. The
-same PWM channel is available on multiple gpios. The latest
-dutycycle setting will be used by all gpios which share a PWM channel.
+The same PWM channel is available on multiple gpios. The latest
+frequency and dutycycle setting will be used by all gpios which
+share a PWM channel.
The gpio must be one of the following.
. .
-12 PWM channel 0 A+/B+ and compute module only
-13 PWM channel 1 A+/B+ and compute module only
+12 PWM channel 0 A+/B+/Pi2 and compute module only
+13 PWM channel 1 A+/B+/Pi2 and compute module only
18 PWM channel 0 All models
-19 PWM channel 1 A+/B+ and compute module only
+19 PWM channel 1 A+/B+/Pi2 and compute module only
40 PWM channel 0 Compute module only
41 PWM channel 1 Compute module only
If the hardware revision can not be found or is not a valid hexadecimal
number the function returns 0.
-The hardware revision is the last 4 characters on the Revision line of
+The hardware revision is the last few characters on the Revision line of
/proc/cpuinfo.
The revision number can be used to determine the assignment of gpios
-to pins.
+to pins (see [*gpio*]).
There are at least three types of board.
-Type 1 has gpio 0 on P1-3, gpio 1 on P1-5, and gpio 21 on P1-13.
-
-Type 2 has gpio 2 on P1-3, gpio 3 on P1-5, gpio 27 on P1-13, and
-gpios 28-31 on P5.
-
-Type 3 has a 40 pin connector rather than the 26 pin connector of
-the earlier boards. Gpios 0 to 27 are brought out to the connector.
-
Type 1 boards have hardware revision numbers of 2 and 3.
Type 2 boards have hardware revision numbers of 4, 5, 6, and 15.
-Type 3 boards have hardware revision number 16.
+Type 3 boards have hardware revision numbers of 16 or greater.
for "Revision : 0002" the function returns 2.
for "Revision : 000f" the function returns 15.
int gpioCfgClock(
unsigned cfgMicros, unsigned cfgPeripheral, unsigned cfgSource);
/*D
-Configures pigpio to use a particualar sample rate timed by a specified
+Configures pigpio to use a particular sample rate timed by a specified
peripheral.
. .
/*F*/
-int gpioCustom1(unsigned arg1, unsigned arg2, char *argx, unsigned count);
+int gpioCfgMemAlloc(unsigned memAllocMode);
+/*D
+Selects the method of DMA memory allocation.
+
+. .
+memAllocMode: 0-2
+. .
+
+There are two methods of DMA memory allocation. The original method
+uses the /proc/self/pagemap file to allocate bus memory. The new
+method uses the mailbox property interface to allocate bus memory.
+
+Auto will use the mailbox method unless a larger than default buffer
+size is requested with [*gpioCfgBufferSize*].
+D*/
+
+/*F*/
+int gpioCfgInternals(unsigned cfgWhat, int cfgVal);
+/*D
+Used to tune internal settings.
+
+. .
+cfgWhat: see source code
+ cfgVal: see source code
+. .
+D*/
+
+/*F*/
+int gpioCustom1(unsigned arg1, unsigned arg2, char *argx, unsigned argc);
/*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
+arg1: >=0
+arg2: >=0
+argx: extra (byte) arguments
+argc: number of extra arguments
. .
Returns >= 0 if OK, less than 0 indicates a user defined error.
/*F*/
-int gpioCustom2(unsigned arg1, char *argx, unsigned count,
+int gpioCustom2(unsigned arg1, char *argx, unsigned argc,
char *retBuf, unsigned retMax);
/*D
This function is available for user customisation.
. .
arg1: >=0
argx: extra (byte) arguments
- count: number of extra arguments
+ argc: number of extra arguments
retBuf: buffer for returned bytes
retMax: maximum number of bytes to return
. .
D*/
-/*F*/
-int gpioCfgInternals(unsigned cfgWhat, int cfgVal);
-/*D
-Used to tune internal settings.
-
-. .
-cfgWhat: see source code
- cfgVal: see source code
-. .
-
-Not intended for general use.
-D*/
-
-
/*F*/
int rawWaveAddSPI(
rawSPI_t *spi,
A pointer to a void object passed to a thread started by gpioStartThread.
+arg1::
+
+An unsigned argument passed to a user customised function. Its
+meaning is defined by the customiser.
+
+arg2::
+
+An unsigned argument passed to a user customised function. Its
+meaning is defined by the customiser.
+
+argc::
+
+The count of bytes passed to a user customised function.
+
+*argx::
+
+A pointer to an array of bytes passed to a user customised function.
+Its meaning and content is defined by the customiser.
+
bbBaud::
The baud rate used for the transmission and reception of bit banged
A Broadcom numbered gpio, in the range 0-53.
+There are 54 General Purpose Input Outputs (gpios) named gpio0 through
+gpio53.
+
+They are split into two banks. Bank 1 consists of gpio0 through
+gpio31. Bank 2 consists of gpio32 through gpio53.
+
+All the gpios which are safe for the user to read and write are in
+bank 1. Not all gpios in bank 1 are safe though. Type 1 boards
+have 17 safe gpios. Type 2 boards have 21. Type 3 boards have 26.
+
+See [*gpioHardwareRevision*].
+
+The user gpios are marked with an X in the following table.
+
+. .
+ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+Type 1 X X - - X - - X X X X X - - X X
+Type 2 - - X X X - - X X X X X - - X X
+Type 3 X X X X X X X X X X X X X X
+
+ 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
+Type 1 - X X - - X X X X X - - - - - -
+Type 2 - X X - - - X X X X - X X X X X
+Type 3 X X X X X X X X X X X X - - - -
+. .
+
gpioAlertFunc_t::
. .
typedef void (*gpioAlertFunc_t) (int gpio, int level, uint32_t tick);
[*gpioCfgPermissions*]
[*gpioCfgInterfaces*]
[*gpioCfgInternals*]
-[*gpioCfgSocketPort*]
+[*gpioCfgSocketPort*]
+[*gpioCfgMemAlloc*]
gpioGetSamplesFunc_t::
. .
A 32-bit word value.
+memAllocMode:: 0-2
+
+The DMA memory allocation mode.
+
+. .
+PI_MEM_ALLOC_AUTO 0
+PI_MEM_ALLOC_PAGEMAP 1
+PI_MEM_ALLOC_MAILBOX 2
+. .
+
*micros::
A value representing microseconds.
PI_MAX_SERVO_PULSEWIDTH 2500
. .
-PWMduty::0-1000
+PWMduty::0-1000000 (1M)
The hardware PWM dutycycle.
. .
-#define PI_HW_PWM_RANGE 5000
+#define PI_HW_PWM_RANGE 1000000
. .
PWMfreq::5-250K
The hardware PWM frequency.
. .
-#define PI_HW_PWM_MIN_FREQ 5
-#define PI_HW_PWM_MAX_FREQ 50000
+#define PI_HW_PWM_MIN_FREQ 1
+#define PI_HW_PWM_MAX_FREQ 125000000
. .
range::25-40000
} rawWaveInfo_t;
. .
+*retBuf::
+
+A buffer to hold a number of bytes returned to a used customised function,
+
+retMax::
+
+The maximum number of bytes a user customised function should return.
+
*rxBuf::
A pointer to a buffer to receive data.
0-31, a Broadcom numbered gpio.
+See [*gpio*].
+
*userdata::
A pointer to arbitrary user data. This may be used to identify the instance.
#define PI_UNKNOWN_COMMAND -88 // unknown command
#define PI_SPI_XFER_FAILED -89 // spi xfer/read/write failed
#define PI_BAD_POINTER -90 // bad (NULL) pointer
-#define PI_NO_AUX_SPI -91 // need a B+ for auxiliary SPI
+#define PI_NO_AUX_SPI -91 // need a A+/B+/Pi2 for auxiliary SPI
#define PI_NOT_PWM_GPIO -92 // gpio is not in use for PWM
#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-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_HPWM_FREQ -96 // hardware PWM frequency not 1-125M
+#define PI_BAD_HPWM_DUTY -97 // hardware PWM dutycycle not 0-1M
+#define PI_BAD_HCLK_FREQ -98 // hardware clock frequency not 4689-250M
#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_BAD_MALLOC_MODE -104 // bad memory allocation mode
#define PI_PIGIF_ERR_0 -2000
#define PI_PIGIF_ERR_99 -2099
#define PI_DEFAULT_UPDATE_MASK_R2 0xFBC7CF9C
#define PI_DEFAULT_UPDATE_MASK_R3 0x0080400FFFFFFCLL
#define PI_DEFAULT_UPDATE_MASK_COMPUTE 0x00FFFFFFFFFFFFLL
+#define PI_DEFAULT_MEM_ALLOC_MODE PI_MEM_ALLOC_AUTO
+
/*DEF_E*/
#endif
import os
import atexit
-VERSION = "1.15"
+VERSION = "1.16"
exceptions = True
PI_HPWM_ILLEGAL =-100
PI_BAD_DATABITS =-101
PI_BAD_STOPBITS =-102
+PI_MSG_TOOBIG =-103
+PI_BAD_MALLOC_MODE =-104
# pigpio error text
[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"],
+ [PI_NO_AUX_SPI , "need a A+/B+/Pi2 for auxiliary SPI"],
[PI_NOT_PWM_GPIO , "gpio is not in use for PWM"],
[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-50K"],
- [PI_BAD_HPWM_DUTY , "hardware PWM dutycycle not 0-5000"],
- [PI_BAD_HCLK_FREQ , "hardware clock frequency not 4689-25M"],
+ [PI_BAD_HPWM_FREQ , "hardware PWM frequency not 1-125M"],
+ [PI_BAD_HPWM_DUTY , "hardware PWM dutycycle not 0-1M"],
+ [PI_BAD_HCLK_FREQ , "hardware clock frequency not 4689-250M"],
[PI_BAD_HCLK_PASS , "need password to use hardware clock 1"],
[PI_HPWM_ILLEGAL , "illegal, PWM in use for main clock"],
[PI_BAD_DATABITS , "serial data bits not 1-32"],
[PI_BAD_STOPBITS , "serial (half) stop bits not 2-8"],
+ [PI_MSG_TOOBIG , "socket/pipe message too big"],
+ [PI_BAD_MALLOC_MODE , "bad memory allocation mode"],
]
For normal PWM the dutycycle will be out of the defined range
- for the gpio (see [*get_PWM_range*]). If a hardware clock is
- active on the gpio the reported dutycycle will be 500
- (out of 1000). If hardware PWM is active on the gpio the
- reported dutycycle will be out of a 1000.
+ for the gpio (see [*get_PWM_range*]).
+
+ If a hardware clock is active on the gpio the reported
+ dutycycle will be 500000 (500k) out of 1000000 (1M).
+
+ If hardware PWM is active on the gpio the reported dutycycle
+ will be out of a 1000000 (1M).
...
pi.set_PWM_dutycycle(4, 25)
user_gpio:= 0-31.
If a hardware clock or hardware PWM is active on the gpio
- the reported range will be 1000.
+ the reported range will be 1000000 (1M).
...
pi.set_PWM_range(9, 500)
user_gpio:= 0-31.
- If a hardware clock or hardware PWM is active on the gpio
- the reported real range will be 1000.
+ If a hardware clock is active on the gpio the reported
+ real range will be 1000000 (1M).
+
+ If hardware PWM is active on the gpio the reported real range
+ will be approximately 250M divided by the set PWM frequency.
...
pi.set_PWM_frequency(4, 800)
Returns the frequency (in Hz) used for the gpio.
For normal PWM the frequency will be that defined for the gpio
- by [*set_PWM_frequency*]. If a hardware clock is active on the
- gpio the reported frequency will be that set by [*hardware_clock*].
+ by [*set_PWM_frequency*].
+
+ If a hardware clock is active on the gpio the reported frequency
+ will be that set by [*hardware_clock*].
+
If hardware PWM is active on the gpio the reported frequency
will be that set by [*hardware_PWM*].
def hardware_clock(self, gpio, clkfreq):
"""
Starts a hardware clock on a gpio at the specified frequency.
+ Frequencies above 30MHz are unlikely to work.
gpio:= see description
- clkfreq:= 0 (off) or 4689-250M
+ clkfreq:= 0 (off) or 4689-250000000 (250M)
Returns 0 if OK, otherwise PI_NOT_PERMITTED, PI_BAD_GPIO,
. .
4 clock 0 All models
- 5 clock 1 A+/B+ and compute module only (reserved for system use)
- 6 clock 2 A+/B+ and compute module only
- 20 clock 0 A+/B+ and compute module only
+ 5 clock 1 A+/B+/Pi2 and compute module only
+ (reserved for system use)
+ 6 clock 2 A+/B+/Pi2 and compute module only
+ 20 clock 0 A+/B+/Pi2 and compute module only
21 clock 1 All models but Rev.2 B (reserved for system use)
32 clock 0 Compute module only
def hardware_PWM(self, gpio, PWMfreq, PWMduty):
"""
- Starts hardware PWM on a gpio at the specified
- frequency and dutycycle.
+ Starts hardware PWM on a gpio at the specified frequency
+ and dutycycle. Frequencies above 30MHz are unlikely to work.
NOTE: Any waveform started by [*wave_send_once*],
[*wave_send_repeat*], [*wave_tx_start*], or
pigpio daemon is started (option -t).
gpio:= see descripton
- PWMfreq:= 0 (off) or 5-50K
- PWMduty:= 0 (off) to 5000 (fully on).
+ PWMfreq:= 0 (off) or 1-125000000 (125M).
+ PWMduty:= 0 (off) to 1000000 (1M)(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.
- Both PWM channels share the same clock and the same update
- frequency. The latest frequency setting will be used by
- both PWM channels. The same PWM channel is available on
- multiple gpios. The latest dutycycle setting will be used
+ The same PWM channel is available on multiple gpios.
+ The latest frequency and dutycycle setting will be used
by all gpios which share a PWM channel.
The gpio must be one of the following.
. .
- 12 PWM channel 0 A+/B+ and compute module only
- 13 PWM channel 1 A+/B+ and compute module only
+ 12 PWM channel 0 A+/B+/Pi2 and compute module only
+ 13 PWM channel 1 A+/B+/Pi2 and compute module only
18 PWM channel 0 All models
- 19 PWM channel 1 A+/B+ and compute module only
+ 19 PWM channel 1 A+/B+/Pi2 and compute module only
40 PWM channel 0 Compute module only
41 PWM channel 1 Compute module only
. .
...
- pi.hardware_PWM(18, 800, 1250) # 800Hz 25% dutycycle
+ pi.hardware_PWM(18, 800, 250000) # 800Hz 25% dutycycle
- pi.hardware_PWM(18, 2000, 3750) # 2000Hz 75% dutycycle
+ pi.hardware_PWM(18, 2000, 750000) # 2000Hz 75% dutycycle
...
"""
# pigpio message format
"""
Returns the Pi's hardware revision number.
- The hardware revision is the last 4 characters on the Revision
- line of /proc/cpuinfo.
+ The hardware revision is the last few characters on the
+ Revision line of /proc/cpuinfo.
The revision number can be used to determine the assignment
- of gpios to pins.
+ of gpios to pins (see [*gpio*]).
There are at least three types of board.
- Type 1 has gpio 0 on P1-3, gpio 1 on P1-5, and gpio 21 on P1-13
- (revision numbers 2 and 3).
+ Type 1 boards have hardware revision numbers of 2 and 3.
- Type 2 has gpio 2 on P1-3, gpio 3 on P1-5, gpio 27 on P1-13,
- and gpios 28-31 on P5 (revision numbers of 4, 5, 6, and 15).
+ Type 2 boards have hardware revision numbers of 4, 5, 6, and 15.
- Type 3 has a 40 pin connector rather than the 26 pin connector
- of the earlier boards. Gpios 0 to 27 are brought out to the
- connector (revision number 16).
+ Type 3 boards have hardware revision numbers of 16 or greater.
If the hardware revision can not be found or is not a valid
hexadecimal number the function returns 0.
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
+ An auxiliary SPI device is available on the A+/B+/Pi2 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-1 (0-2 for B+ auxiliary device).
+ spi_channel:= 0-1 (0-2 for A+/B+/Pi2 auxiliary device).
spi_baud:= 32K-125M (values above 30M are unlikely to work).
spi_flags:= see below.
mm defines the SPI mode.
+ WARNING: modes 1 and 3 do not appear to work on
+ the auxiliary device.
+
. .
Mode POL PHA
0 0 0
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+.
+ The auxiliary device is only present on the A+/B+/Pi2.
W is 0 if the device is not 3-wire, 1 if the device is 3-wire.
Standard SPI device only.
data bits [*bb_bits*] specified in the [*bb_serial_read_open*]
command.
- For [*bb_bits*] 1-8 there will be one byte per character.
- For [*bb_bits*] 9-16 there will be two bytes per character.
+ For [*bb_bits*] 1-8 there will be one byte per character.
+ For [*bb_bits*] 9-16 there will be two bytes per character.
For [*bb_bits*] 17-32 there will be four bytes per character.
...
def xref():
"""
+ arg1:
+ An unsigned argument passed to a user customised function. Its
+ meaning is defined by the customiser.
+
+ arg2:
+ An unsigned argument passed to a user customised function. Its
+ meaning is defined by the customiser.
+
+ argx:
+ An array of bytes passed to a user customised function.
+ Its meaning and content is defined by the customiser.
+
bb_baud: 100 - 250000
The baud rate used for the transmission of bit bang serial data.
RISING_EDGE = 0
errnum: <0
- PI_BAD_DATABITS = -101
- PI_BAD_DUTYCYCLE = -8
- PI_BAD_DUTYRANGE = -21
- PI_BAD_FLAGS = -77
- PI_BAD_GPIO = -3
- PI_BAD_HANDLE = -25
- PI_BAD_HCLK_FREQ = -98
- PI_BAD_HCLK_PASS = -99
- PI_BAD_HPWM_DUTY = -97
- PI_BAD_HPWM_FREQ = -96
- PI_BAD_I2C_ADDR = -75
- PI_BAD_I2C_BUS = -74
- PI_BAD_LEVEL = -5
- PI_BAD_MICS_DELAY = -64
- PI_BAD_MILS_DELAY = -65
- PI_BAD_MODE = -4
- PI_BAD_PARAM = -81
- PI_BAD_PARAM_NUM = -52
- PI_BAD_PUD = -6
- PI_BAD_PULSELEN = -46
- PI_BAD_PULSEWIDTH = -7
- PI_BAD_SCRIPT = -47
- PI_BAD_SCRIPT_CMD = -55
- PI_BAD_SCRIPT_ID = -48
- PI_BAD_SERIAL_COUNT = -51
- PI_BAD_SER_DEVICE = -79
- PI_BAD_SER_OFFSET = -49
- PI_BAD_SER_SPEED = -80
+ . .
+ PI_BAD_DATABITS = -101
+ PI_BAD_DUTYCYCLE = -8
+ PI_BAD_DUTYRANGE = -21
+ PI_BAD_FLAGS = -77
+ PI_BAD_GPIO = -3
+ PI_BAD_HANDLE = -25
+ PI_BAD_HCLK_FREQ = -98
+ PI_BAD_HCLK_PASS = -99
+ PI_BAD_HPWM_DUTY = -97
+ PI_BAD_HPWM_FREQ = -96
+ PI_BAD_I2C_ADDR = -75
+ PI_BAD_I2C_BUS = -74
+ PI_BAD_LEVEL = -5
+ PI_BAD_MICS_DELAY = -64
+ PI_BAD_MILS_DELAY = -65
+ PI_BAD_MODE = -4
+ PI_BAD_PARAM = -81
+ PI_BAD_PARAM_NUM = -52
+ PI_BAD_PUD = -6
+ PI_BAD_PULSELEN = -46
+ PI_BAD_PULSEWIDTH = -7
+ PI_BAD_SCRIPT = -47
+ PI_BAD_SCRIPT_CMD = -55
+ PI_BAD_SCRIPT_ID = -48
+ PI_BAD_SERIAL_COUNT = -51
+ PI_BAD_SER_DEVICE = -79
+ PI_BAD_SER_OFFSET = -49
+ PI_BAD_SER_SPEED = -80
PI_BAD_SPI_CHANNEL = -76
PI_BAD_SPI_COUNT = -84
PI_BAD_SPI_SPEED = -78
PI_TOO_MANY_PULSES = -36
PI_TOO_MANY_TAGS = -54
PI_UNKNOWN_COMMAND = -88
+ . .
frequency: 0-40000
Defines the frequency to be used for PWM on a gpio.
gpio: 0-53
A Broadcom numbered gpio. All the user gpios are in the range 0-31.
+ There are 54 General Purpose Input Outputs (gpios) named gpio0
+ through gpio53.
+
+ They are split into two banks. Bank 1 consists of gpio0
+ through gpio31. Bank 2 consists of gpio32 through gpio53.
+
+ All the gpios which are safe for the user to read and write are in
+ bank 1. Not all gpios in bank 1 are safe though. Type 1 boards
+ have 17 safe gpios. Type 2 boards have 21. Type 3 boards have 26.
+
+ See [*get_hardware_revision*].
+
+ The user gpios are marked with an X in the following table.
+
+ . .
+ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ Type 1 X X - - X - - X X X X X - - X X
+ Type 2 - - X X X - - X X X X X - - X X
+ Type 3 X X X X X X X X X X X X X X
+
+ 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
+ Type 1 - X X - - X X X X X - - - - - -
+ Type 2 - X X - - - X X X X - X X X X X
+ Type 3 X X X X X X X X X X X X - - - -
+ . .
+
gpio_off:
A mask used to select gpios to be operated on. See [*bits*].
pulsewidth:
The servo pulsewidth in microseconds. 0 switches pulses off.
- PWMduty: 0-1000
+ PWMduty: 0-1000000 (1M)
The hardware PWM dutycycle.
- PWMfreq: 5-250K
+ PWMfreq: 1-125000000 (125M)
The hardware PWM frequency.
range_: 25-40000
An I2C device register. The usable registers depend on the
actual device.
+ retMax: >=0
+ The maximum number of bytes a user customised function
+ should return, default 8192.
+
script:
The text of a script to store on the pigpio daemon.
Not all the gpios within this range are usable, some are reserved
for system use.
+ See [*gpio*].
+
wait_timeout: 0.0 -
The number of seconds to wait in wait_for_edge before timing out.
.br
.SH OPTIONS
+.IP "\fB-a value\fP"
+DMA memory allocation mode
+0=AUTO, 1=PMAP, 2=MBOX
+default AUTO
+
.IP "\fB-b value\fP"
gpio sample buffer in milliseconds
100-10000
.br
.br
-Only the default gpios for the board revision or those specified by the -x option may be updated.
+Only the user gpios for the board type or those specified by the -x option may be updated.
.br
.br
.EX
-Revision 1 boards 0x03E6CF93
+Type 1 boards 0x03E6CF93
.br
-Revision 2 boards 0xFBC6CF9C
+Type 2 boards 0xFBC6CF9C
.br
-Revision 3 boards 0x0FFFFFFC
+Type 3 boards 0x0FFFFFFC
.br
.EE
.br
.br
-The activity LED may be written (gpio 16 for Rev.1/2
-boards, gpio 47 for Rev.3 boards).
+The activity LED may be written (gpio 16 for type 1 and 2
+boards, gpio 47 for type 3 boards).
.br
.br
-The high USB power mode gpio may be written (gpio 38 for Rev.3 boards).
+The high USB power mode gpio may be written (gpio 38 for type 3 boards).
.SH SEE ALSO
*/
/*
-This version is for pigpio version 24+
+This version is for pigpio version 30+
*/
#include <sys/types.h>
static unsigned DMAprimaryChannel = PI_DEFAULT_DMA_PRIMARY_CHANNEL;
static unsigned DMAsecondaryChannel = PI_DEFAULT_DMA_SECONDARY_CHANNEL;
static unsigned socketPort = PI_DEFAULT_SOCKET_PORT;
+static unsigned memAllocMode = PI_DEFAULT_MEM_ALLOC_MODE;
static uint64_t updateMask = -1;
static int updateMaskSet = 0;
{
fprintf(stderr, "\n" \
"Usage: sudo pigpiod [OPTION] ...\n" \
+ " -a value, DMA mode, 0=AUTO, 1=PMAP, 2=MBOX, default AUTO\n" \
" -b value, gpio sample buffer in milliseconds, default 120\n" \
" -d value, primary DMA channel, 0-14, default 14\n" \
" -e value, secondary DMA channel, 0-6, default 5\n" \
uint64_t mask;
char * endptr;
- while ((opt = getopt(argc, argv, "b:d:e:fkp:s:t:x:")) != -1)
+ while ((opt = getopt(argc, argv, "a:b:d:e:fkp:s:t:x:")) != -1)
{
i = -1;
switch (opt)
{
+ case 'a':
+ i = atoi(optarg);
+ if ((i >= PI_MEM_ALLOC_AUTO) && (i <= PI_MEM_ALLOC_MAILBOX))
+ memAllocMode = i;
+ else fatal("invalid -a option (%d)", i);
+ break;
+
case 'b':
i = atoi(optarg);
if ((i >= PI_BUF_MILLIS_MIN) && (i <= PI_BUF_MILLIS_MAX))
gpioCfgSocketPort(socketPort);
+ gpioCfgMemAlloc(memAllocMode);
+
if (updateMaskSet) gpioCfgPermissions(updateMask);
/* start library */
.br
For normal PWM the dutycycle will be out of the defined range
-for the gpio (see \fBget_PWM_range\fP). If a hardware clock is
-active on the gpio the reported dutycycle will be 500 (out of 1000).
+for the gpio (see \fBget_PWM_range\fP).
+
+.br
+
+.br
+If a hardware clock is active on the gpio the reported dutycycle
+will be 500000 (500k) out of 1000000 (1M).
+
+.br
+
+.br
If hardware PWM is active on the gpio the reported dutycycle
-will be out of a 1000.
+will be out of a 1000000 (1M).
.IP "\fBint set_PWM_range(unsigned user_gpio, unsigned range)\fP"
.IP "" 4
.br
If a hardware clock or hardware PWM is active on the gpio the
-reported range will be 1000.
+reported range will be 1000000 (1M).
.IP "\fBint get_PWM_real_range(unsigned user_gpio)\fP"
.IP "" 4
.br
.br
-If a hardware clock or hardware PWM is active on the gpio the
-reported real range will be 1000.
+If a hardware clock is active on the gpio the reported
+real range will be 1000000 (1M).
+
+.br
+
+.br
+If hardware PWM is active on the gpio the reported real range
+will be approximately 250M divided by the set PWM frequency.
+
+.br
+
+.br
.IP "\fBint set_PWM_frequency(unsigned user_gpio, unsigned frequency)\fP"
.IP "" 4
.br
For normal PWM the frequency will be that defined for the gpio by
-\fBset_PWM_frequency\fP. If a hardware clock is active on the gpio the
-reported frequency will be that set by \fBhardware_clock\fP. If hardware
-PWM is active on the gpio the reported frequency will be that set by
-\fBhardware_PWM\fP.
+\fBset_PWM_frequency\fP.
+
+.br
+
+.br
+If a hardware clock is active on the gpio the reported frequency
+will be that set by \fBhardware_clock\fP.
+
+.br
+
+.br
+If hardware PWM is active on the gpio the reported frequency
+will be that set by \fBhardware_PWM\fP.
.br
.IP "\fBint hardware_clock(unsigned gpio, unsigned clkfreq)\fP"
.IP "" 4
Starts a hardware clock on a gpio at the specified frequency.
+Frequencies above 30MHz are unlikely to work.
.br
.EX
gpio: see description
.br
-frequency: 0 (off) or 4689-250M
+frequency: 0 (off) or 4689-250000000 (250M)
.br
.EE
.EX
4 clock 0 All models
.br
-5 clock 1 A+/B+ and compute module only (reserved for system use)
+5 clock 1 A+/B+/Pi2 and compute module only (reserved for system use)
.br
-6 clock 2 A+/B+ and compute module only
+6 clock 2 A+/B+/Pi2 and compute module only
.br
-20 clock 0 A+/B+ and compute module only
+20 clock 0 A+/B+/Pi2 and compute module only
.br
21 clock 1 All models but Rev.2 B (reserved for system use)
.br
.IP "\fBint hardware_PWM(unsigned gpio, unsigned PWMfreq, uint32_t PWMduty)\fP"
.IP "" 4
Starts hardware PWM on a gpio at the specified frequency and dutycycle.
+Frequencies above 30MHz are unlikely to work.
.br
.EX
gpio: see descripton
.br
-PWMfreq: 0 (off) or 5-50K
+PWMfreq: 0 (off) or 1-125000000 (125M)
.br
-PWMduty: 0 (off) to 5000 (fully on).
+PWMduty: 0 (off) to 1000000 (1M)(fully on)
.br
.EE
.br
.br
-Both PWM channels share the same clock and the same update frequency.
-The latest frequency setting will be used by both PWM channels. The
-same PWM channel is available on multiple gpios. The latest
-dutycycle setting will be used by all gpios which share a PWM channel.
+The same PWM channel is available on multiple gpios. The latest
+frequency and dutycycle setting will be used by all gpios which
+share a PWM channel.
.br
.br
.EX
-12 PWM channel 0 A+/B+ and compute module only
+12 PWM channel 0 A+/B+/Pi2 and compute module only
.br
-13 PWM channel 1 A+/B+ and compute module only
+13 PWM channel 1 A+/B+/Pi2 and compute module only
.br
18 PWM channel 0 All models
.br
-19 PWM channel 1 A+/B+ and compute module only
+19 PWM channel 1 A+/B+/Pi2 and compute module only
.br
.br
.br
.br
-The hardware revision is the last 4 characters on the Revision line
+The hardware revision is the last few characters on the Revision line
of /proc/cpuinfo.
.br
.br
The revision number can be used to determine the assignment of gpios
-to pins.
-
-.br
-
-.br
-There are currently three types of board.
-
-.br
+to pins (see \fBgpio\fP).
.br
-Type 1 has gpio 0 on P1-3, gpio 1 on P1-5, and gpio 21 on P1-13.
.br
-
-.br
-Type 2 has gpio 2 on P1-3, gpio 3 on P1-5, gpio 27 on P1-13, and
-gpios 28-31 on P5.
-
-.br
-
-.br
-Type 3 has a 40 pin connector rather than the 26 pin connector of
-the earlier boards. Gpios 0 to 27 are brought out to the connector.
+There are at least three types of board.
.br
.br
.br
-Type 3 boards have hardware revision number 16.
+Type 3 boards have hardware revision numbers of 16 or greater.
.IP "\fBuint32_t get_pigpio_version(void)\fP"
.IP "" 4
.br
For \fBbbBits\fP 1-8 there will be one byte per character.
+.br
For \fBbbBits\fP 9-16 there will be two bytes per character.
+.br
For \fBbbBits\fP 17-32 there will be four bytes per character.
.IP "\fBint bb_serial_read_close(unsigned user_gpio)\fP"
.br
.br
-An auxiliary SPI device is available on the B+ and may be
+An auxiliary SPI device is available on the A+/B+/Pi2 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.
.br
.EX
-spi_channel: 0-1 (0-2 for B+ auxiliary device).
+spi_channel: 0-1 (0-2 for A+/B+/Pi2 auxiliary device).
.br
spi_baud: 32K-125M (values above 30M are unlikely to work).
.br
.br
+.br
+Warning: modes 1 and 3 do not appear to work on the auxiliary device.
+
+.br
+
.br
.EX
.br
A is 0 for the standard SPI device, 1 for the auxiliary SPI. The
-auxiliary device is only present on the B+.
+auxiliary device is only present on the A+/B+/Pi2.
.br
Returns the number of bytes of data available (>=0) if OK,
otherwise PI_BAD_HANDLE.
-.IP "\fBint custom_1(unsigned arg1, unsigned arg2, char *argx, unsigned count)\fP"
+.IP "\fBint custom_1(unsigned arg1, unsigned arg2, char *argx, unsigned argc)\fP"
.IP "" 4
This function is available for user customisation.
.br
.EX
- arg1: >=0
+arg1: >=0
.br
- arg2: >=0
+arg2: >=0
.br
- argx: extra (byte) arguments
+argx: extra (byte) arguments
.br
-count: number of extra arguments
+argc: number of extra arguments
.br
.EE
.br
Returns >= 0 if OK, less than 0 indicates a user defined error.
-.IP "\fBint custom_2(unsigned arg1, char *argx, unsigned count, char *retBuf, unsigned retMax)\fP"
+.IP "\fBint custom_2(unsigned arg1, char *argx, unsigned argc, char *retBuf, unsigned retMax)\fP"
.IP "" 4
This function is available for user customisation.
.EX
arg1: >=0
.br
- argx: extra (byte) arguments
+ argc: extra (byte) arguments
.br
count: number of extra arguments
.br
.br
+.IP "\fBarg1\fP" 0
+An unsigned argument passed to a user customised function. Its
+meaning is defined by the customiser.
+
+.br
+
+.br
+
+.IP "\fBarg2\fP" 0
+An unsigned argument passed to a user customised function. Its
+meaning is defined by the customiser.
+
+.br
+
+.br
+
+.IP "\fBargc\fP" 0
+The count of bytes passed to a user customised function.
+
+.br
+
+.br
+
+.IP "\fB*argx\fP" 0
+A pointer to an array of bytes passed to a user customised function.
+Its meaning and content is defined by the customiser.
+
+.br
+
+.br
+
+.br
+
+.br
+
.IP "\fBbbBaud\fP" 0
The baud rate used for the transmission and reception of bit banged
serial data.
.br
-.IP "\fBclkfreq\fP: 4689-250M" 0
+.IP "\fBclkfreq\fP: 4689-250000000 (250M)" 0
The hardware clock frequency.
.br
.br
+.br
+There are 54 General Purpose Input Outputs (gpios) named gpio0 through
+gpio53.
+
+.br
+
+.br
+They are split into two banks. Bank 1 consists of gpio0 through
+gpio31. Bank 2 consists of gpio32 through gpio53.
+
+.br
+
+.br
+All the gpios which are safe for the user to read and write are in
+bank 1. Not all gpios in bank 1 are safe though. Type 1 boards
+have 17 safe gpios. Type 2 boards have 21. Type 3 boards have 26.
+
+.br
+
+.br
+See \fBget_hardware_revision\fP.
+
+.br
+
+.br
+The user gpios are marked with an X in the following table.
+
+.br
+
+.br
+
+.EX
+ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+.br
+Type 1 X X - - X - - X X X X X - - X X
+.br
+Type 2 - - X X X - - X X X X X - - X X
+.br
+Type 3 X X X X X X X X X X X X X X
+.br
+
+.br
+ 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
+.br
+Type 1 - X X - - X X X X X - - - - - -
+.br
+Type 2 - X X - - - X X X X - X X X X X
+.br
+Type 3 X X X X X X X X X X X X - - - -
+.br
+
+.EE
+
+.br
+
.br
.IP "\fBgpioPulse_t\fP" 0
.br
-.IP "\fBPWMduty\fP: 0-1000" 0
+.IP "\fBPWMduty\fP: 0-1000000 (1M)" 0
The hardware PWM dutycycle.
.br
.br
.EX
-#define PI_HW_PWM_RANGE 1000
+#define PI_HW_PWM_RANGE 1000000
.br
.EE
.br
-.IP "\fBPWMfreq\fP: 5-250K" 0
+.IP "\fBPWMfreq\fP: 1-125000000 (125M)" 0
The hardware PWM frequency.
.br
.br
.EX
-#define PI_HW_PWM_MIN_FREQ 5
+#define PI_HW_PWM_MIN_FREQ 1
.br
-#define PI_HW_PWM_MAX_FREQ 250000
+#define PI_HW_PWM_MAX_FREQ 125000000
.br
.EE
.br
+.IP "\fB*retBuf\fP" 0
+A buffer to hold a number of bytes returned to a used customised function,
+
+.br
+
+.br
+
+.IP "\fBretMax\fP" 0
+The maximum number of bytes a user customised function should return.
+
+.br
+
+.br
+
+.br
+
+.br
+
.IP "\fB*rxBuf\fP" 0
A pointer to a buffer to receive data.
.br
+.br
+See \fBgpio\fP.
+
+.br
+
.br
.IP "\fB*userdata\fP" 0
For more information, please refer to <http://unlicense.org/>
*/
-/* PIGPIOD_IF_VERSION 13 */
+/* PIGPIOD_IF_VERSION 14 */
#include <stdio.h>
#include <stdlib.h>
#include "pigpio.h"
-#define PIGPIOD_IF_VERSION 13
+#define PIGPIOD_IF_VERSION 14
/*TEXT
Returns 0 if OK, otherwise PI_BAD_USER_GPIO or PI_NOT_PWM_GPIO.
For normal PWM the dutycycle will be out of the defined range
-for the gpio (see [*get_PWM_range*]). If a hardware clock is
-active on the gpio the reported dutycycle will be 500 (out of 1000).
+for the gpio (see [*get_PWM_range*]).
+
+If a hardware clock is active on the gpio the reported dutycycle
+will be 500000 (500k) out of 1000000 (1M).
+
If hardware PWM is active on the gpio the reported dutycycle
-will be out of a 1000.
+will be out of a 1000000 (1M).
D*/
/*F*/
otherwise PI_BAD_USER_GPIO.
If a hardware clock or hardware PWM is active on the gpio the
-reported range will be 1000.
+reported range will be 1000000 (1M).
D*/
/*F*/
Returns the real range used for the gpio if OK,
otherwise PI_BAD_USER_GPIO.
-If a hardware clock or hardware PWM is active on the gpio the
-reported real range will be 1000.
+If a hardware clock is active on the gpio the reported
+real range will be 1000000 (1M).
+
+If hardware PWM is active on the gpio the reported real range
+will be approximately 250M divided by the set PWM frequency.
+
D*/
/*F*/
. .
For normal PWM the frequency will be that defined for the gpio by
-[*set_PWM_frequency*]. If a hardware clock is active on the gpio the
-reported frequency will be that set by [*hardware_clock*]. If hardware
-PWM is active on the gpio the reported frequency will be that set by
-[*hardware_PWM*].
+[*set_PWM_frequency*].
+
+If a hardware clock is active on the gpio the reported frequency
+will be that set by [*hardware_clock*].
+
+If hardware PWM is active on the gpio the reported frequency
+will be that set by [*hardware_PWM*].
Returns the frequency (in hertz) used for the gpio if OK,
otherwise PI_BAD_USER_GPIO.
int hardware_clock(unsigned gpio, unsigned clkfreq);
/*D
Starts a hardware clock on a gpio at the specified frequency.
+Frequencies above 30MHz are unlikely to work.
. .
gpio: see description
-frequency: 0 (off) or 4689-250M
+frequency: 0 (off) or 4689-250000000 (250M)
. .
Returns 0 if OK, otherwise PI_NOT_PERMITTED, PI_BAD_GPIO,
. .
4 clock 0 All models
-5 clock 1 A+/B+ and compute module only (reserved for system use)
-6 clock 2 A+/B+ and compute module only
-20 clock 0 A+/B+ and compute module only
+5 clock 1 A+/B+/Pi2 and compute module only (reserved for system use)
+6 clock 2 A+/B+/Pi2 and compute module only
+20 clock 0 A+/B+/Pi2 and compute module only
21 clock 1 All models but Rev.2 B (reserved for system use)
32 clock 0 Compute module only
int hardware_PWM(unsigned gpio, unsigned PWMfreq, uint32_t PWMduty);
/*D
Starts hardware PWM on a gpio at the specified frequency and dutycycle.
+Frequencies above 30MHz are unlikely to work.
NOTE: Any waveform started by [*wave_send_once*], [*wave_send_repeat*], [*wave_tx_start*], or [*wave_tx_repeat*] will be cancelled.
. .
gpio: see descripton
-PWMfreq: 0 (off) or 5-50K
-PWMduty: 0 (off) to 5000 (fully on).
+PWMfreq: 0 (off) or 1-125000000 (125M)
+PWMduty: 0 (off) to 1000000 (1M)(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,
or PI_HPWM_ILLEGAL.
-Both PWM channels share the same clock and the same update frequency.
-The latest frequency setting will be used by both PWM channels. The
-same PWM channel is available on multiple gpios. The latest
-dutycycle setting will be used by all gpios which share a PWM channel.
+The same PWM channel is available on multiple gpios. The latest
+frequency and dutycycle setting will be used by all gpios which
+share a PWM channel.
The gpio must be one of the following.
. .
-12 PWM channel 0 A+/B+ and compute module only
-13 PWM channel 1 A+/B+ and compute module only
+12 PWM channel 0 A+/B+/Pi2 and compute module only
+13 PWM channel 1 A+/B+/Pi2 and compute module only
18 PWM channel 0 All models
-19 PWM channel 1 A+/B+ and compute module only
+19 PWM channel 1 A+/B+/Pi2 and compute module only
40 PWM channel 0 Compute module only
41 PWM channel 1 Compute module only
/*D
Get the Pi's hardware revision number.
-The hardware revision is the last 4 characters on the Revision line
+The hardware revision is the last few characters on the Revision line
of /proc/cpuinfo.
If the hardware revision can not be found or is not a valid
hexadecimal number the function returns 0.
The revision number can be used to determine the assignment of gpios
-to pins.
-
-There are currently three types of board.
+to pins (see [*gpio*]).
-Type 1 has gpio 0 on P1-3, gpio 1 on P1-5, and gpio 21 on P1-13.
-
-Type 2 has gpio 2 on P1-3, gpio 3 on P1-5, gpio 27 on P1-13, and
-gpios 28-31 on P5.
-
-Type 3 has a 40 pin connector rather than the 26 pin connector of
-the earlier boards. Gpios 0 to 27 are brought out to the connector.
+There are at least three types of board.
Type 1 boards have hardware revision numbers of 2 and 3.
Type 2 boards have hardware revision numbers of 4, 5, 6, and 15.
-Type 3 boards have hardware revision number 16.
+Type 3 boards have hardware revision numbers of 16 or greater.
D*/
/*F*/
The bytes returned for each character depend upon the number of
data bits [*bbBits*] specified in the [*bb_serial_read_open*] command.
-For [*bbBits*] 1-8 there will be one byte per character.
-For [*bbBits*] 9-16 there will be two bytes per character.
+For [*bbBits*] 1-8 there will be one byte per character.
+For [*bbBits*] 9-16 there will be two bytes per character.
For [*bbBits*] 17-32 there will be four bytes per character.
D*/
be used to 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
+An auxiliary SPI device is available on the A+/B+/Pi2 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-1 (0-2 for B+ auxiliary device).
+spi_channel: 0-1 (0-2 for A+/B+/Pi2 auxiliary device).
spi_baud: 32K-125M (values above 30M are unlikely to work).
spi_flags: see below.
. .
mm defines the SPI mode.
+Warning: modes 1 and 3 do not appear to work on the auxiliary device.
+
. .
Mode POL PHA
0 0 0
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+.
+auxiliary device is only present on the A+/B+/Pi2.
W is 0 if the device is not 3-wire, 1 if the device is 3-wire. Standard
SPI device only.
D*/
/*F*/
-int custom_1(unsigned arg1, unsigned arg2, char *argx, unsigned count);
+int custom_1(unsigned arg1, unsigned arg2, char *argx, unsigned argc);
/*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
+arg1: >=0
+arg2: >=0
+argx: extra (byte) arguments
+argc: number of extra arguments
. .
Returns >= 0 if OK, less than 0 indicates a user defined error.
/*F*/
-int custom_2(unsigned arg1, char *argx, unsigned count,
+int custom_2(unsigned arg1, char *argx, unsigned argc,
char *retBuf, unsigned retMax);
/*D
This function is available for user customisation.
The return value is an integer indicating the number of returned bytes.
. .
arg1: >=0
- argx: extra (byte) arguments
+ argc: extra (byte) arguments
count: number of extra arguments
retBuf: buffer for returned data
retMax: maximum number of bytes to return
is used unless overridden by the PIGPIO_ADDR environment
variable.
+arg1::
+An unsigned argument passed to a user customised function. Its
+meaning is defined by the customiser.
+
+arg2::
+An unsigned argument passed to a user customised function. Its
+meaning is defined by the customiser.
+
+argc::
+The count of bytes passed to a user customised function.
+
+*argx::
+A pointer to an array of bytes passed to a user customised function.
+Its meaning and content is defined by the customiser.
+
+
bbBaud::
The baud rate used for the transmission and reception of bit banged
serial data.
char::
A single character, an 8 bit quantity able to store 0-255.
-clkfreq::4689-250M
+clkfreq::4689-250000000 (250M)
The hardware clock frequency.
count::
gpio::
A Broadcom numbered gpio, in the range 0-53.
+There are 54 General Purpose Input Outputs (gpios) named gpio0 through
+gpio53.
+
+They are split into two banks. Bank 1 consists of gpio0 through
+gpio31. Bank 2 consists of gpio32 through gpio53.
+
+All the gpios which are safe for the user to read and write are in
+bank 1. Not all gpios in bank 1 are safe though. Type 1 boards
+have 17 safe gpios. Type 2 boards have 21. Type 3 boards have 26.
+
+See [*get_hardware_revision*].
+
+The user gpios are marked with an X in the following table.
+
+. .
+ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+Type 1 X X - - X - - X X X X X - - X X
+Type 2 - - X X X - - X X X X X - - X X
+Type 3 X X X X X X X X X X X X X X
+
+ 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
+Type 1 - X X - - X X X X X - - - - - -
+Type 2 - X X - - - X X X X - X X X X X
+Type 3 X X X X X X X X X X X X - - - -
+. .
+
gpioPulse_t::
. .
typedef struct
PI_MAX_SERVO_PULSEWIDTH 2500
. .
-PWMduty::0-1000
+PWMduty::0-1000000 (1M)
The hardware PWM dutycycle.
. .
-#define PI_HW_PWM_RANGE 1000
+#define PI_HW_PWM_RANGE 1000000
. .
-PWMfreq::5-250K
+PWMfreq::1-125000000 (125M)
The hardware PWM frequency.
. .
-#define PI_HW_PWM_MIN_FREQ 5
-#define PI_HW_PWM_MAX_FREQ 250000
+#define PI_HW_PWM_MIN_FREQ 1
+#define PI_HW_PWM_MAX_FREQ 125000000
. .
range::25-40000
PI_MAX_DUTYCYCLE_RANGE 40000
. .
+*retBuf::
+A buffer to hold a number of bytes returned to a used customised function,
+
+retMax::
+The maximum number of bytes a user customised function should return.
+
+
*rxBuf::
A pointer to a buffer to receive data.
user_gpio::
0-31, a Broadcom numbered gpio.
+See [*gpio*].
+
*userdata::
A pointer to arbitrary user data. This may be used to identify the instance.
.br
.EX
-$ pigs bc2 0x8000 # clear gpio 47 (activity LED on B+)
+$ pigs bc2 0x8000 # clear gpio 47 (activity LED on A+/B+/Pi2)
.br
.br
.br
.EX
-$ pigs bs2 0x40 # set gpio 38 (enable high current mode B+)
+$ pigs bs2 0x40 # set gpio 38 (enable high current mode A+/B+/Pi2)
.br
.br
.br
+.IP "\fBCF1 uvs\fP - Custom function 1"
+.IP "" 4
+
+.br
+This command calls a user customised function. The meaning of
+any paramaters and the returned value is defined by the
+customiser.
+
+.br
+
+.IP "\fBCF2 uvs\fP - Custom function 2"
+.IP "" 4
+
+.br
+This command calls a user customised function. The meaning of
+any paramaters and the returned value is defined by the
+customiser.
+
+.br
+
.IP "\fBGDC u\fP - Get gpio PWM dutycycle"
.IP "" 4
.br
For normal PWM the dutycycle will be out of the defined range
-for the gpio (see \fBPRG\fP). If a hardware clock is active on
-the gpio the reported dutycycle will be 500 (out of 1000).
+for the gpio (see \fBPRG\fP).
+
+.br
+If a hardware clock is active on the gpio the reported
+dutycycle will be 500000 (500k) out of 1000000 (1M).
+
+.br
If hardware PWM is active on the gpio the reported dutycycle
-will be out of a 1000.
+will be out of a 1000000 (1M).
.br
.IP "\fBHC g cf\fP - Set hardware clock frequency"
.IP "" 4
This command sets the hardware clock associated with gpio \fBg\fP to
-frequency \fBcf\fP.
+frequency \fBcf\fP. Frequencies above 30MHz are unlikely to work.
.br
Upon success nothing is returned. On error a negative status code
.EX
4 clock 0 All models
-5 clock 1 A+/B+ and compute module only (reserved for system use)
-6 clock 2 A+/B+ and compute module only
-20 clock 0 A+/B+ and compute module only
-21 clock 1 All models but Rev.2 B (reserved for system use)
+5 clock 1 A+/B+/Pi2 and compute module only (reserved for system use)
+6 clock 2 A+/B+/Pi2 and compute module only
+20 clock 0 A+/B+/Pi2 and compute module only
+21 clock 1 All models but Type 2 B (reserved for system use)
.EE
.IP "\fBHP g pf pdc\fP - Set hardware PWM frequency and dutycycle"
.IP "" 4
This command sets the hardware PWM associated with gpio \fBg\fP to
-frequency \fBpf\fP with dutycycle \fBpdc\fP.
+frequency \fBpf\fP with dutycycle \fBpdc\fP. Frequencies above 30MHz
+are unlikely to work.
.br
NOTE: Any waveform started by \fBWVGO\fP, \fBWVGOR\fP, \fBWVTX\fP or
.br
.EX
-$ pigs hp 18 100 4000 # 80% dutycycle
+$ pigs hp 18 100 800000 # 80% dutycycle
.br
.br
-$ pigs hp 19 100 1000 # 20% dutycycle
+$ pigs hp 19 100 200000 # 20% dutycycle
.br
.br
-$ pigs hp 19 1 100
+$ pigs hp 19 125000001 100000
.br
-96
.br
-ERROR: hardware PWM frequency not 5-50K
+ERROR: hardware PWM frequency not 1-125M
.br
.EE
.br
-Both PWM channels share the same clock and the same update frequency.
-The latest frequency setting will be used by both PWM channels. The
-same PWM channel is available on multiple gpios. The latest
-dutycycle setting will be used by all gpios which share a PWM channel.
+The same PWM channel is available on multiple gpios. The latest
+frequency and dutycycle setting will be used by all gpios which
+share a PWM channel.
.br
The gpio must be one of the following.
.br
.EX
-12 PWM channel 0 A+/B+ and compute module only
-13 PWM channel 1 A+/B+ and compute module only
+12 PWM channel 0 A+/B+/Pi2 and compute module only
+13 PWM channel 1 A+/B+/Pi2 and compute module only
18 PWM channel 0 All models
-19 PWM channel 1 A+/B+ and compute module only
+19 PWM channel 1 A+/B+/Pi2 and compute module only
.EE
This command returns the hardware revision of the Pi.
.br
-The hardware revision is found in the last 4 characters on the Revision
+The hardware revision is found in the last 4 characters on the Type sion
line of /proc/cpuinfo.
.br
number the command returns 0.
.br
-The revision number can be used to determine the assignment of gpios to pins.
+The revision number can be used to determine the assignment of gpios
+to pins (see \fBg\fP).
.br
There are currently three types of board.
-.br
-Type 1 has gpio 0 on P1-3, gpio 1 on P1-5, and gpio 21 on P1-13.
-
-.br
-Type 2 has gpio 2 on P1-3, gpio 3 on P1-5, gpio 27 on P1-13, and
-gpios 28-31 on P5.
-
-.br
-Type 3 has a 40 pin connector rather than the 26 pin connector of
-the earlier boards. Gpios 0 to 27 are brought out to the connector
-(although gpios 0 and 1 are reserved).
-
.br
Type 1 boards have hardware revision numbers of 2 and 3.
Type 2 boards have hardware revision numbers of 4, 5, 6, and 15.
.br
-Type 3 boards have hardware revision number 16.
+Type 3 boards have hardware revision numbers of 16 or greater.
.br
for "Revision : 0002" the command returns 2.
.br
For normal PWM the frequency will be that defined for the gpio
-by \fBPFS\fP. If a hardware clock is active on the gpio
-the reported frequency will be that set by \fBHC\fP.
+by \fBPFS\fP.
+
+.br
+If a hardware clock is active on the gpio the reported frequency
+will be that set by \fBHC\fP.
+
+.br
If hardware PWM is active on the gpio the reported frequency
will be that set by \fBHP\fP.
.br
If a hardware clock or hardware PWM is active on the gpio the reported
-range will be 1000.
+range will be 1000000 (1M).
.br
This command returns the real underlying range used by gpio \fBu\fP.
.br
-If a hardware clock or hardware PWM is active on the gpio the
-reported range will be 1000.
+If a hardware clock is active on the gpio the reported
+real range will be 1000000 (1M).
.br
-Upon success the real range is returned. On error a negative status code
-will be returned.
+If hardware PWM is active on the gpio the reported real range
+will be approximately 250M divided by the set PWM frequency.
+
+.br
+On error a negative status code will be returned.
.br
See \fBPRS\fP.
mode 0, active low chip select.
.br
-An auxiliary SPI device is available on the B+ and may be
+An auxiliary SPI device is available on the A+/B+/Pi2 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.
.br
mm defines the SPI mode.
+.br
+Warning: modes 1 and 3 do not appear to work on the auxiliary device.
+
.br
.EX
.br
A is 0 for the standard SPI device, 1 for the auxiliary SPI. The
-auxiliary device is only present on the B+.
+auxiliary device is only present on the A+/B+/Pi2.
.br
W is 0 if the device is not 3-wire, 1 if the device is 3-wire. Standard
.br
All the gpios which are safe for the user to read and write are in bank 1.
-Not all gpios in bank 1 are safe though. Rev.1 boards have 17 safe gpios.
-Rev.2 boards have 21. Rev.3 boards have 26.
+Not all gpios in bank 1 are safe though. Type 1 boards have 17 safe gpios.
+Type 2 boards have 21. Type 3 boards have 26.
+
+.br
+See \fBHWVER\fP.
.br
The user gpios are marked with an X in the following table.
.br
.EX
- 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
-Rev.1 X X - - X - - X X X X X - - X X
-Rev.2 - - X X X - - X X X X X - - X X
-Rev.3 X X X X X X X X X X X X X X
-
- 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
-Rev.1 - X X - - X X X X X - - - - - -
-Rev.2 - X X - - - X X X X - X X X X X
-Rev.3 X X X X X X X X X X X X - - - -
+ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+Type 1 X X - - X - - X X X X X - - X X
+Type 2 - - X X X - - X X X X X - - X X
+Type 3 X X X X X X X X X X X X X X
+
+ 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
+Type 1 - X X - - X X X X X - - - - - -
+Type 2 - X X - - - X X X X - X X X X X
+Type 3 X X X X X X X X X X X X - - - -
.EE
.br
-.IP "\fBpdc\fP - hardware PWM dutycycle (0-1000)" 0
+.IP "\fBpdc\fP - hardware PWM dutycycle (0-1000000)" 0
The command expects a dutycycle.
.br
-.IP "\fBpf\fP - hardware PWM frequency (5-250K)" 0
+.IP "\fBpf\fP - hardware PWM frequency (1-125M)" 0
The command expects a frequency.
.br
-.IP "\fBpl\fP - pulse length (1-50)" 0
+.IP "\fBpl\fP - pulse length (1-100)" 0
The command expects a pulse length in microseconds.
.br
.br
+.IP "\fBuvs\fP - values" 0
+The command expects an arbitrary number of >=0 values (possibly none).
+Any after the first two must be <= 255.
+
+.br
+
.IP "\fBv\fP - value" 0
The command expects a number.
.br
.SS Commands
.br
-All the normal pigs commands may be used within a script.
+All the normal pigs commands may be used within a script. However
+commands which return more than an integer will be of little use.
.br
The following commands are only legal within a script.
from distutils.core import setup
setup(name='pigpio',
- version='1.15',
+ version='1.16',
author='joan',
author_email='joan@abyz.co.uk',
maintainer='joan',
#!/bin/bash
-VERSION=29
-
GPIO=4
#
# of tests indicate a problem.
#
+echo "Testing pigs I/F"
+
+s=$(pigs pigpv)
+echo "pigpio version $s"
+
s=$(pigs bc1 0)
if [[ $s = "" ]]; then echo "BC1 ok"; else echo "BC1 fail ($s)"; fi
s=$(pigs pfs $GPIO 800)
if [[ $s = 800 ]]; then echo "PFS-b ok"; else echo "PFS-b fail ($s)"; fi
-s=$(pigs pigpv)
-if [[ $s = $VERSION ]]; then echo "PIGPV ok"; else echo "PIGPV fail ($s)"; fi
-
s=$(pigs prs $GPIO 255)
if [[ $s = 250 ]]; then echo "PRG-a ok"; else echo "PRG-a fail ($s)"; fi
s=$(pigs prg $GPIO)
#!/bin/bash
-VERSION=29
-
GPIO=4
#
# of tests indicate a problem.
#
+echo "Testing pipe I/F"
+
+echo "pigpv" >/dev/pigpio
+read -t 1 s </dev/pigout
+echo "pigpio version $s"
+
echo "bc1 0" >/dev/pigpio
read -t 1 s </dev/pigout
if [[ $s = 0 ]]; then echo "BC1 ok"; else echo "BC1 fail ($s)"; fi
read -t 1 s </dev/pigout
if [[ $s = 800 ]]; then echo "PFS-b ok"; else echo "PFS-b fail ($s)"; fi
-echo "pigpv" >/dev/pigpio
-read -t 1 s </dev/pigout
-if [[ $s = $VERSION ]]; then echo "PIGPV ok"; else echo "PIGPV fail ($s)"; fi
-
echo "prs $GPIO 255" >/dev/pigpio
read -t 1 s </dev/pigout
if [[ $s = 250 ]]; then echo "PRG-a ok"; else echo "PRG-a fail ($s)"; fi