V30
authorjoan <joan@abyz.me.uk>
Wed, 25 Feb 2015 20:34:52 +0000 (20:34 +0000)
committerjoan <joan@abyz.me.uk>
Wed, 25 Feb 2015 20:34:52 +0000 (20:34 +0000)
17 files changed:
EXAMPLES/C/IR_RECEIVER/test_ir_hasher.c
EXAMPLES/CPP/IR_RECEIVER/test_ir_hasher.cpp
README
command.c
pigpio.3
pigpio.c
pigpio.h
pigpio.py
pigpiod.1
pigpiod.c
pigpiod_if.3
pigpiod_if.c
pigpiod_if.h
pigs.1
setup.py
x_pigs
x_pipe

index 878bdb832a9d2a69fd4448269f22c8afdd3eaa53..28673b79726455c0326618a8811cad8136394054 100644 (file)
@@ -12,7 +12,7 @@ An IR receiver output pin connected to a Pi gpio.
 
 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
 
index a852220db216355023deb6a06637e8304be328cc..40788cc968758074845286eda6dfa4522c4ceda1 100644 (file)
@@ -12,7 +12,7 @@ An IR receiver output pin connected to a Pi gpio.
 
 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
 
diff --git a/README b/README
index 381a237e06c9f0001dee2d7800e04ac2947ba885..8b975e268abf1ac758952812ff8bae6afc924214 100644 (file)
--- a/README
+++ b/README
@@ -1,3 +1,9 @@
+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.
index 53b807478ef85d92e55244a0ac94e41d553d24b6..b875d1181a470ebbc9780fb78355a128953f8daa 100644 (file)
--- a/command.c
+++ b/command.c
@@ -26,7 +26,7 @@ For more information, please refer to <http://unlicense.org/>
 */
 
 /*
-This version is for pigpio version 26+
+This version is for pigpio version 30+
 */
 
 #include <stdio.h>
@@ -345,7 +345,7 @@ WVTXR wid        Transmit wave repeatedly\n\
 bits  = a mask where (1<<g) is set for each gpio g of interest\n\
 bv    = byte value (0-255)\n\
 bvs   = one or more byte values (0-255)\n\
-cf    = hardware clock frequency (4689-25M)\n\
+cf    = hardware clock frequency (4689-250M)\n\
 db    = data bits (1-32)\n\
 g     = any gpio (0-53)\n\
 h     = handle (>=0)\n\
@@ -359,8 +359,8 @@ num   = number of bytes to read\n\
 o     = offset (>=0)\n\
 p     = pud (ODU)\n\
 pars  = 0 to 10 parameters for script\n\
-pdc   = hardware PWM dutycycle (0-5000)\n\
-pf    = hardware PWM frequency (5-50K)\n\
+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\
@@ -486,14 +486,14 @@ static errInfo_t errInfo[]=
    {PI_NOT_SERVO_GPIO   , "gpio is not in use for servo pulses"},
    {PI_NOT_HCLK_GPIO    , "gpio has no hardware clock"},
    {PI_NOT_HPWM_GPIO    , "gpio has no hardware PWM"},
-   {PI_BAD_HPWM_FREQ    , "hardware PWM frequency not 5-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"},
 
 };
 
index 1d0231cde2cad19fe5e51083564ffa2435b14a8c..b766fb5c842f26847b0773d0d4425b01f6d38ceb 100644 (file)
--- a/pigpio.3
+++ b/pigpio.3
@@ -154,7 +154,7 @@ All the functions which return an int return < 0 on error.
 .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
@@ -230,7 +230,7 @@ Call before program exit.
 .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
@@ -531,10 +531,19 @@ PI_BAD_USER_GPIO or PI_NOT_PWM_GPIO.
 
 .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
 
@@ -628,7 +637,7 @@ user_gpio: 0-31
 
 .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
 
@@ -660,8 +669,14 @@ user_gpio: 0-31
 .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
 
@@ -807,8 +822,17 @@ user_gpio: 0-31
 
 .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.
 
@@ -1985,7 +2009,9 @@ data bits \fBbbBits\fP specified in the \fBgpioSerialReadOpen\fP command.
 
 .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"
@@ -2500,7 +2526,7 @@ active low chip select.
 .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.
 
@@ -2509,7 +2535,7 @@ 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
@@ -2548,6 +2574,11 @@ mm defines the SPI mode.
 
 .br
 
+.br
+Warning: modes 1 and 3 do not appear to work on the auxiliary device.
+
+.br
+
 .br
 
 .EX
@@ -2578,7 +2609,7 @@ ux is 0 if the CEx gpio is reserved for SPI (default) and 1 otherwise.
 
 .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
 
@@ -3641,6 +3672,7 @@ gpioWrite_Bits_32_53_Set((1<<(32-32)) | (1<<(40-32)) | (1<<(53-32)));
 .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
 
@@ -3649,7 +3681,7 @@ Starts a hardware clock on a gpio at the specified frequency.
 .EX
    gpio: see description
 .br
-clkfreq: 0 (off) or 4689-250M
+clkfreq: 0 (off) or 4689-250000000 (250M)
 .br
 
 .EE
@@ -3678,11 +3710,11 @@ The gpio must be one of the following.
 .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
@@ -3711,6 +3743,7 @@ gpio number.
 .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
 
@@ -3732,9 +3765,9 @@ main clock defaults to PCM but may be overridden by a call to
 .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
@@ -3748,10 +3781,9 @@ PI_BAD_HPWM_DUTY, PI_BAD_HPWM_FREQ, or PI_HPWM_ILLEGAL.
 .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
 
@@ -3763,13 +3795,13 @@ The gpio must be one of the following.
 .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
@@ -3998,14 +4030,14 @@ number the function returns 0.
 .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
 
@@ -4014,23 +4046,6 @@ There are at least three types of board.
 
 .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.
 
@@ -4042,7 +4057,7 @@ Type 2 boards have hardware revision numbers of 4, 5, 6, and 15.
 .br
 
 .br
-Type 3 boards have hardware revision number 16.
+Type 3 boards have hardware revision numbers of 16 or greater.
 
 .br
 
@@ -4121,7 +4136,7 @@ sample   4       8  12  18   31   55  107  ---
 
 .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
@@ -4309,7 +4324,50 @@ The default setting (0) is that both interfaces are enabled.
 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.
 
@@ -4323,13 +4381,13 @@ It returns a single integer value.
 .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
@@ -4339,7 +4397,7 @@ count: number of extra arguments
 .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.
 
@@ -4359,7 +4417,7 @@ The returned value is an integer indicating the number of returned bytes.
 .br
   argx: extra (byte) arguments
 .br
count: number of extra arguments
 argc: number of extra arguments
 .br
 retBuf: buffer for returned bytes
 .br
@@ -4378,27 +4436,6 @@ Returns >= 0 if OK, less than 0 indicates a user defined error.
 .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
@@ -4724,6 +4761,53 @@ A pointer to a void object passed to a thread started by gpioStartThread.
 
 .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
@@ -5086,6 +5170,61 @@ A Broadcom numbered gpio, in the range 0-53.
 
 .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
@@ -5139,6 +5278,8 @@ One of
 \fBgpioCfgInternals\fP
 .br
 \fBgpioCfgSocketPort\fP
+.br
+\fBgpioCfgMemAlloc\fP
 
 .br
 
@@ -5451,6 +5592,31 @@ A 32-bit word value.
 
 .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
@@ -5704,7 +5870,7 @@ PI_MAX_SERVO_PULSEWIDTH 2500
 
 .br
 
-.IP "\fBPWMduty\fP: 0-1000" 0
+.IP "\fBPWMduty\fP: 0-1000000 (1M)" 0
 The hardware PWM dutycycle.
 
 .br
@@ -5712,7 +5878,7 @@ The hardware PWM dutycycle.
 .br
 
 .EX
-#define PI_HW_PWM_RANGE 5000
+#define PI_HW_PWM_RANGE 1000000
 .br
 
 .EE
@@ -5729,9 +5895,9 @@ The hardware PWM frequency.
 .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
@@ -5864,6 +6030,28 @@ typedef struct
 
 .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
@@ -6221,6 +6409,11 @@ If gpio#n may be written then bit (1<<n) is set.
 
 .br
 
+.br
+See \fBgpio\fP.
+
+.br
+
 .br
 
 .IP "\fB*userdata\fP" 0
@@ -6682,7 +6875,7 @@ A 16-bit word value.
 .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
@@ -6692,11 +6885,11 @@ A 16-bit word value.
 .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
@@ -6708,6 +6901,8 @@ A 16-bit word value.
 .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
@@ -6758,6 +6953,10 @@ A 16-bit word value.
 #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
index b3da40795e3ad6f742a08b846218da38b61e0807..0559a4bc826c15825399bf45f2e029c09bf9e716 100644 (file)
--- a/pigpio.c
+++ b/pigpio.c
@@ -25,7 +25,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 For more information, please refer to <http://unlicense.org/>
 */
 
-/* pigpio version 29 */
+/* pigpio version 30 */
 
 #include <stdio.h>
 #include <string.h>
@@ -283,23 +283,23 @@ bit 0 READ_LAST_NOT_SET_ERROR
    }                                                               \
    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
@@ -742,6 +742,22 @@ static volatile uint32_t DMA_BUS_CACHE  = 0x00000000;
 
 #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) ();
@@ -915,6 +931,7 @@ typedef struct
    unsigned ifFlags;
    int      dbgLevel;
    unsigned showStats;
+   unsigned memAllocMode;
 } gpioCfg_t;
 
 typedef struct
@@ -973,6 +990,14 @@ 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 */
@@ -988,6 +1013,7 @@ static volatile gpioCfg_t gpioCfg =
    PI_DEFAULT_IF_FLAGS,
    0,
    0,
+   PI_DEFAULT_MEM_ALLOC_MODE,
 };
 
 static volatile gpioStats_t gpioStats;
@@ -1081,16 +1107,19 @@ static FILE * outFifo = NULL;
 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;
@@ -1161,6 +1190,7 @@ uint8_t clkDef[PI_MAX_GPIO + 1] =
 
 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] =
 {
@@ -1337,8 +1367,6 @@ static void myOffPageSlot(int pos, int * page, int * slot)
 
 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;
 }
@@ -1347,8 +1375,6 @@ static void myLvsPageSlot(int pos, int * page, int * slot)
 
 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;
 }
@@ -2078,6 +2104,159 @@ static void myGpioSetServo(unsigned gpio, int oldVal, int newVal)
    }
 }
 
+/* ======================================================================= */
+
+/*
+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)
@@ -2100,7 +2279,7 @@ static uint32_t waveCbPOadr(int pos)
    page = pos/CBS_PER_OPAGE;
    slot = pos%CBS_PER_OPAGE;
 
-   return (uint32_t) &dmaOPhys[page]->cb[slot];
+   return (uint32_t) &dmaOBus[page]->cb[slot];
 }
 
 /* ----------------------------------------------------------------------- */
@@ -2131,7 +2310,7 @@ static uint32_t waveOOLPOadr(int pos)
 
    waveOOLPageSlot(pos, &page, &slot);
 
-   return (uint32_t) &dmaOPhys[page]->OOL[slot];
+   return (uint32_t) &dmaOBus[page]->OOL[slot];
 }
 
 
@@ -2224,19 +2403,19 @@ static int wave2Cbs(unsigned wave_mode)
       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;
 
@@ -2251,10 +2430,10 @@ static int wave2Cbs(unsigned wave_mode)
          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)
@@ -2266,10 +2445,10 @@ static int wave2Cbs(unsigned wave_mode)
          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)
@@ -2279,10 +2458,10 @@ static int wave2Cbs(unsigned wave_mode)
          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)
@@ -2292,10 +2471,10 @@ static int wave2Cbs(unsigned wave_mode)
          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)
@@ -2304,7 +2483,7 @@ static int wave2Cbs(unsigned wave_mode)
 
          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++)
@@ -2312,7 +2491,7 @@ static int wave2Cbs(unsigned wave_mode)
 
          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);
@@ -2326,11 +2505,11 @@ static int wave2Cbs(unsigned wave_mode)
             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 */
 
@@ -2339,12 +2518,12 @@ static int wave2Cbs(unsigned wave_mode)
             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 */
 
@@ -2353,13 +2532,13 @@ static int wave2Cbs(unsigned wave_mode)
             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);
@@ -2379,7 +2558,7 @@ static int wave2Cbs(unsigned wave_mode)
                         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
          {
@@ -2387,12 +2566,12 @@ static int wave2Cbs(unsigned wave_mode)
                         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);
       }
    }
 
@@ -2400,7 +2579,7 @@ static int wave2Cbs(unsigned wave_mode)
    {
       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;
@@ -4003,24 +4182,52 @@ int serDataAvailable(unsigned handle)
 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;
@@ -4077,7 +4284,7 @@ static unsigned dmaNowAtICB(void)
 
    while (1)
    {
-      cb = (cbAddr - ((int)dmaIPhys[page] | DMA_BUS_ADR)) / 32;
+      cb = (cbAddr - ((int)dmaIBus[page])) / 32;
 
       if (cb < CBS_PER_IPAGE)
       {
@@ -4120,7 +4327,7 @@ unsigned rawWaveCB(void)
 
    while (1)
    {
-      cb = (cbAddr - ((int)dmaOPhys[page] | DMA_BUS_ADR)) / 32;
+      cb = (cbAddr - ((int)dmaOBus[page])) / 32;
 
       if (cb < CBS_PER_OPAGE)
       {
@@ -4155,7 +4362,7 @@ static unsigned dmaCurrentSlot(unsigned pos)
 
 static uint32_t dmaPwmDataAdr(int pos)
 {
-   return (uint32_t) &dmaIPhys[pos]->periphData;
+   return (uint32_t) &dmaIBus[pos]->periphData;
 }
 
 /* ----------------------------------------------------------------------- */
@@ -4167,7 +4374,7 @@ static uint32_t dmaGpioOnAdr(int pos)
    page = pos/ON_PER_IPAGE;
    slot = pos%ON_PER_IPAGE;
 
-   return (uint32_t) &dmaIPhys[page]->gpioOn[slot];
+   return (uint32_t) &dmaIBus[page]->gpioOn[slot];
 }
 
 /* ----------------------------------------------------------------------- */
@@ -4178,7 +4385,7 @@ static uint32_t dmaGpioOffAdr(int pos)
 
    myOffPageSlot(pos, &page, &slot);
 
-   return (uint32_t) &dmaIPhys[page]->gpioOff[slot];
+   return (uint32_t) &dmaIBus[page]->gpioOff[slot];
 }
 
 /* ----------------------------------------------------------------------- */
@@ -4189,7 +4396,7 @@ static uint32_t dmaTickAdr(int pos)
 
    myTckPageSlot(pos, &page, &slot);
 
-   return (uint32_t) &dmaIPhys[page]->tick[slot];
+   return (uint32_t) &dmaIBus[page]->tick[slot];
 }
 
 /* ----------------------------------------------------------------------- */
@@ -4200,7 +4407,7 @@ static uint32_t dmaReadLevelsAdr(int pos)
 
    myLvsPageSlot(pos, &page, &slot);
 
-   return (uint32_t) &dmaIPhys[page]->level[slot];
+   return (uint32_t) &dmaIBus[page]->level[slot];
 }
 
 /* ----------------------------------------------------------------------- */
@@ -4212,7 +4419,7 @@ static uint32_t dmaCbAdr(int pos)
    page = (pos/CBS_PER_IPAGE);
    slot = (pos%CBS_PER_IPAGE);
 
-   return (uint32_t) &dmaIPhys[page]->cb[slot];
+   return (uint32_t) &dmaIBus[page]->cb[slot];
 }
 
 /* ----------------------------------------------------------------------- */
@@ -4224,10 +4431,10 @@ static void dmaGpioOnCb(int b, int pos)
    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);
 }
 
 /* ----------------------------------------------------------------------- */
@@ -4239,10 +4446,10 @@ static void dmaTickCb(int b, int pos)
    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);
 }
 
 /* ----------------------------------------------------------------------- */
@@ -4254,10 +4461,10 @@ static void dmaGpioOffCb(int b, int pos)
    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);
 }
 
 /* ----------------------------------------------------------------------- */
@@ -4269,10 +4476,10 @@ static void dmaReadLevelsCb(int b, int pos)
    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);
 }
 
 /* ----------------------------------------------------------------------- */
@@ -4286,17 +4493,17 @@ static void dmaDelayCb(int b)
    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);
 }
 
 /* ----------------------------------------------------------------------- */
@@ -4338,7 +4545,7 @@ static void dmaInitCbs(void)
 
    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));
 
@@ -4469,19 +4676,19 @@ static void * pthAlertThread(void *x)
       }
       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++;
@@ -4544,10 +4751,23 @@ static void * pthAlertThread(void *x)
 
             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]++;
          }
@@ -5524,66 +5744,6 @@ static int initGrabLockFile(void)
 
 /* ----------------------------------------------------------------------- */
 
-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,
@@ -5683,29 +5843,89 @@ static int initPeripherals(void)
 
 /* ----------------------------------------------------------------------- */
 
-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;
 
@@ -5725,10 +5945,9 @@ static int initDMAblock(int pagemapFd, int 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);
 
@@ -5740,14 +5959,42 @@ static int initDMAblock(int pagemapFd, int block)
    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, "");
 
@@ -5771,16 +6018,7 @@ static int initDMAcbs(void)
       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 *),
@@ -5791,36 +6029,92 @@ static int initDMAcbs(void)
    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",
@@ -5828,7 +6122,7 @@ static int initDMAcbs(void)
       (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)
    {
@@ -6019,7 +6313,7 @@ static void initDMAgo(volatile uint32_t  *dmaAddr, uint32_t cbAddr)
 
    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 */
 
@@ -6129,9 +6423,10 @@ static void initClearGlobals(void)
    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;
@@ -6206,6 +6501,14 @@ static void initReleaseResources(void)
    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++)
@@ -6219,30 +6522,33 @@ static void initReleaseResources(void)
 
    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)
    {
@@ -6276,22 +6582,155 @@ static void initReleaseResources(void)
       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, &param);
+
+   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;
 }
 
 /* ----------------------------------------------------------------------- */
@@ -6477,123 +6916,17 @@ void rawDumpScript(unsigned script_id)
 
 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, &param);
-
-   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;
+}
 
 
 /* ----------------------------------------------------------------------- */
@@ -6620,21 +6953,32 @@ void gpioTerminate(void)
       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");
       }
    }
 
@@ -6958,6 +7302,8 @@ int gpioGetPWMrange(unsigned gpio)
 
 int gpioGetPWMrealRange(unsigned gpio)
 {
+   unsigned pwm;
+
    DBG(DBG_USER, "gpio=%d", gpio);
 
    CHECK_INITED;
@@ -6968,6 +7314,9 @@ int gpioGetPWMrealRange(unsigned gpio)
    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;
 
@@ -7552,7 +7901,7 @@ int gpioWaveTxStart(unsigned wave_mode)
       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;
 
@@ -7584,7 +7933,7 @@ int gpioWaveTxSend(unsigned wave_id, unsigned wave_mode)
    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;
 
@@ -8698,6 +9047,7 @@ int gpioHardwareClock(unsigned gpio, unsigned frequency)
    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);
@@ -8733,9 +9083,7 @@ int gpioHardwareClock(unsigned gpio, unsigned 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);
@@ -8743,6 +9091,14 @@ int gpioHardwareClock(unsigned gpio, unsigned frequency)
          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
       {
@@ -8767,11 +9123,9 @@ int gpioHardwareClock(unsigned gpio, unsigned frequency)
 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);
@@ -8799,73 +9153,63 @@ int gpioHardwarePWM(
    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
@@ -9031,17 +9375,17 @@ unsigned gpioHardwareRevision(void)
                {
                   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;
                }
             }
          }
@@ -9193,6 +9537,24 @@ int gpioCfgSocketPort(unsigned port)
 }
 
 
+/* ----------------------------------------------------------------------- */
+
+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)
index 53c6b0691dd0eaed55d9b4e1a7b9bdafae2fc9df..be6e8139c2633ea0f6ffce4c18b212798df3d273 100644 (file)
--- a/pigpio.h
+++ b/pigpio.h
@@ -31,7 +31,7 @@ For more information, please refer to <http://unlicense.org/>
 #include <stdint.h>
 #include <pthread.h>
 
-#define PIGPIO_VERSION 29
+#define PIGPIO_VERSION 30
 
 /*TEXT
 
@@ -93,7 +93,7 @@ For examples of usage see the C programs within the pigpio archive file.
 
 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
@@ -211,9 +211,9 @@ gpioWaveGetPulses          Length in pulses of the current waveform
 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)
 
@@ -271,6 +271,12 @@ gpioCfgPermissions         Configure the gpio access permissions
 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
 
@@ -441,7 +447,7 @@ typedef void *(gpioThreadFunc_t) (void *);
 #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
 
@@ -479,9 +485,9 @@ typedef void *(gpioThreadFunc_t) (void *);
 
 /* 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 */
 
@@ -620,6 +626,11 @@ typedef void *(gpioThreadFunc_t) (void *);
 #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);
@@ -654,7 +665,7 @@ Returns nothing.
 
 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.
 
 ...
@@ -814,10 +825,13 @@ Returns between 0 (off) and range (fully on) 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 [*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*/
@@ -869,7 +883,7 @@ 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).
 
 ...
 r = gpioGetPWMrange(23);
@@ -887,8 +901,11 @@ PI_BAD_USER_GPIO.
 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);
@@ -964,8 +981,11 @@ user_gpio: 0-31
 . .
 
 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*].
 
@@ -1661,8 +1681,8 @@ or PI_NOT_SERIAL_GPIO.
 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*/
 
@@ -2001,12 +2021,12 @@ Data will be transferred at baud bits per second.  The flags may
 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
 . .
@@ -2023,6 +2043,8 @@ spiFlags consists of the least significant 22 bits.
 
 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
@@ -2036,7 +2058,7 @@ px is 0 if CEx is active low (default) and 1 for active high.
 ux is 0 if the CEx gpio is reserved for SPI (default) and 1 otherwise.
 
 A is 0 for the standard SPI device, 1 for the auxiliary SPI.  The
-auxiliary device is only present on the B+.
+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.
@@ -2678,10 +2700,11 @@ D*/
 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,
@@ -2694,9 +2717,9 @@ The gpio must be one of the following.
 
 . .
 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
@@ -2715,6 +2738,7 @@ D*/
 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.
@@ -2725,25 +2749,24 @@ main clock defaults to PCM but may be overridden by a call to
 
 . .
    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
@@ -2871,27 +2894,19 @@ Returns the hardware revision.
 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. 
@@ -2943,7 +2958,7 @@ D*/
 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.
 
 . .
@@ -3054,17 +3069,45 @@ D*/
 
 
 /*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.
@@ -3072,7 +3115,7 @@ D*/
 
 
 /*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.
@@ -3084,7 +3127,7 @@ The returned value is an integer indicating the number of returned bytes.
 . .
   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
 . .
@@ -3095,20 +3138,6 @@ The number of returned bytes must be retMax or less.
 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,
@@ -3329,6 +3358,25 @@ D*/
 
 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
@@ -3475,6 +3523,32 @@ 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 [*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);
@@ -3497,7 +3571,8 @@ One of
 [*gpioCfgPermissions*] 
 [*gpioCfgInterfaces*] 
 [*gpioCfgInternals*] 
-[*gpioCfgSocketPort*]
+[*gpioCfgSocketPort*] 
+[*gpioCfgMemAlloc*]
 
 gpioGetSamplesFunc_t::
 . .
@@ -3625,6 +3700,16 @@ lVal::0-4294967295 (Hex 0x0-0xFFFFFFFF, Octal 0-37777777777)
 
 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.
@@ -3725,19 +3810,19 @@ PI_MIN_SERVO_PULSEWIDTH 500
 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
@@ -3797,6 +3882,14 @@ typedef struct
 } 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.
@@ -3933,6 +4026,8 @@ 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.
@@ -4214,19 +4309,20 @@ after this command is issued.
 #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
@@ -4253,6 +4349,8 @@ after this command is issued.
 #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
index a4f206199450c7933c0b7a01a3a89fd6889ec870..42518fcf9fc02322b42a6307b23b3c7af95437e4 100644 (file)
--- a/pigpio.py
+++ b/pigpio.py
@@ -257,7 +257,7 @@ import threading
 import os
 import atexit
 
-VERSION = "1.15"
+VERSION = "1.16"
 
 exceptions = True
 
@@ -517,6 +517,8 @@ PI_BAD_HCLK_PASS    =-99
 PI_HPWM_ILLEGAL     =-100
 PI_BAD_DATABITS     =-101
 PI_BAD_STOPBITS     =-102
+PI_MSG_TOOBIG       =-103
+PI_BAD_MALLOC_MODE  =-104
 
 # pigpio error text
 
@@ -609,18 +611,20 @@ _errors=[
    [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"],
 
 ]
 
@@ -1059,10 +1063,13 @@ class pi():
 
 
       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)
@@ -1098,7 +1105,7 @@ class pi():
       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)
@@ -1115,8 +1122,11 @@ class pi():
 
       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)
@@ -1157,8 +1167,11 @@ class pi():
       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*].
 
@@ -1441,9 +1454,10 @@ class pi():
    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,
@@ -1456,9 +1470,10 @@ class pi():
 
       . .
       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
@@ -1482,8 +1497,8 @@ class pi():
 
    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
@@ -1494,25 +1509,23 @@ class pi():
       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
@@ -1522,9 +1535,9 @@ class pi():
       . .
 
       ...
-      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
@@ -1559,23 +1572,19 @@ class pi():
       """
       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.
@@ -2424,12 +2433,12 @@ class pi():
       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.
 
@@ -2447,6 +2456,9 @@ class pi():
 
       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
@@ -2461,7 +2473,7 @@ class pi():
       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.
@@ -2930,8 +2942,8 @@ class pi():
       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.
 
       ...
@@ -3183,6 +3195,18 @@ class pi():
 
 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.
 
@@ -3242,34 +3266,35 @@ def xref():
    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
@@ -3323,6 +3348,7 @@ def xref():
    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.
@@ -3334,6 +3360,32 @@ def xref():
    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*].
 
@@ -3410,10 +3462,10 @@ def xref():
    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
@@ -3425,6 +3477,10 @@ def xref():
    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.
 
@@ -3476,6 +3532,8 @@ def xref():
    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.
 
index d5b495aa4acf22ce9f8f853a7c80028ca13449f6..3152b1612b0e04969af7c042600c003b29e3f40f 100644 (file)
--- a/pigpiod.1
+++ b/pigpiod.1
@@ -29,6 +29,11 @@ pigpiod accepts the following configuration options
 .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
@@ -110,18 +115,18 @@ All gpios may be read.
 .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
@@ -158,13 +163,13 @@ There are two special cases.
 .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
 
index d744560b8d06812f4bcb8b41d44ad3302fa3cf09..da4fb8af8d9e5906df1506643c8a868f592678e4 100644 (file)
--- a/pigpiod.c
+++ b/pigpiod.c
@@ -26,7 +26,7 @@ For more information, please refer to <http://unlicense.org/>
 */
 
 /*
-This version is for pigpio version 24+
+This version is for pigpio version 30+
 */
 
 #include <sys/types.h>
@@ -56,6 +56,7 @@ static unsigned ifFlags                = PI_DEFAULT_IF_FLAGS;
 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;
@@ -82,6 +83,7 @@ void usage()
 {
    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" \
@@ -104,12 +106,19 @@ static void initOpts(int argc, char *argv[])
    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))
@@ -260,6 +269,8 @@ int main(int argc, char **argv)
 
    gpioCfgSocketPort(socketPort);
 
+   gpioCfgMemAlloc(memAllocMode);
+
    if (updateMaskSet) gpioCfgPermissions(updateMask);
 
    /* start library */
index c6397938df4e332df7c26ecdf8c881e0990297e5..4b639c31d04a9a4151844580c5ec04f7de0238ef 100644 (file)
@@ -461,10 +461,19 @@ Returns 0 if OK, otherwise PI_BAD_USER_GPIO or PI_NOT_PWM_GPIO.
 
 .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
@@ -548,7 +557,7 @@ otherwise PI_BAD_USER_GPIO.
 
 .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
@@ -573,8 +582,18 @@ otherwise PI_BAD_USER_GPIO.
 .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
@@ -677,10 +696,19 @@ user_gpio: 0-31.
 
 .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
 
@@ -1117,6 +1145,7 @@ allowed to write to one or more of the gpios.
 .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
 
@@ -1125,7 +1154,7 @@ Starts a hardware clock on a gpio at the specified frequency.
 .EX
      gpio: see description
 .br
-frequency: 0 (off) or 4689-250M
+frequency: 0 (off) or 4689-250000000 (250M)
 .br
 
 .EE
@@ -1154,11 +1183,11 @@ The gpio must be one of the following.
 .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
@@ -1187,6 +1216,7 @@ gpio number.
 .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
 
@@ -1207,9 +1237,9 @@ daemon is started (option -t).
 .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
@@ -1224,10 +1254,9 @@ or PI_HPWM_ILLEGAL.
 .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
 
@@ -1239,13 +1268,13 @@ The gpio must be one of the following.
 .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
@@ -1288,7 +1317,7 @@ Get the Pi's hardware revision number.
 .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
@@ -1301,29 +1330,12 @@ hexadecimal number the function returns 0.
 
 .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
 
@@ -1338,7 +1350,7 @@ Type 2 boards have hardware revision numbers of 4, 5, 6, and 15.
 .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
@@ -1993,7 +2005,9 @@ data bits \fBbbBits\fP specified in the \fBbb_serial_read_open\fP command.
 
 .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"
@@ -2512,7 +2526,7 @@ active low chip select.
 .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.
 
@@ -2521,7 +2535,7 @@ 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
@@ -2560,6 +2574,11 @@ mm defines the SPI mode.
 
 .br
 
+.br
+Warning: modes 1 and 3 do not appear to work on the auxiliary device.
+
+.br
+
 .br
 
 .EX
@@ -2590,7 +2609,7 @@ ux is 0 if the CEx gpio is reserved for SPI (default) and 1 otherwise.
 
 .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
 
@@ -2887,7 +2906,7 @@ handle: >=0, as returned by a call to \fBserial_open\fP.
 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.
 
@@ -2901,13 +2920,13 @@ It returns a single integer value.
 .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
@@ -2917,7 +2936,7 @@ count: number of extra arguments
 .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.
 
@@ -2935,7 +2954,7 @@ The return value is an integer indicating the number of returned bytes.
 .EX
   arg1: >=0
 .br
-  argx: extra (byte) arguments
+  argc: extra (byte) arguments
 .br
  count: number of extra arguments
 .br
@@ -3086,6 +3105,41 @@ variable.
 
 .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.
@@ -3247,7 +3301,7 @@ A single character, an 8 bit quantity able to store 0-255.
 
 .br
 
-.IP "\fBclkfreq\fP: 4689-250M" 0
+.IP "\fBclkfreq\fP: 4689-250000000 (250M)" 0
 The hardware clock frequency.
 
 .br
@@ -3338,6 +3392,61 @@ A Broadcom numbered gpio, in the range 0-53.
 
 .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
@@ -3621,7 +3730,7 @@ PI_MAX_SERVO_PULSEWIDTH 2500
 
 .br
 
-.IP "\fBPWMduty\fP: 0-1000" 0
+.IP "\fBPWMduty\fP: 0-1000000 (1M)" 0
 The hardware PWM dutycycle.
 
 .br
@@ -3629,7 +3738,7 @@ The hardware PWM dutycycle.
 .br
 
 .EX
-#define PI_HW_PWM_RANGE 1000
+#define PI_HW_PWM_RANGE 1000000
 .br
 
 .EE
@@ -3638,7 +3747,7 @@ The hardware PWM dutycycle.
 
 .br
 
-.IP "\fBPWMfreq\fP: 5-250K" 0
+.IP "\fBPWMfreq\fP: 1-125000000 (125M)" 0
 The hardware PWM frequency.
 
 .br
@@ -3646,9 +3755,9 @@ The hardware PWM frequency.
 .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
@@ -3672,6 +3781,24 @@ PI_MAX_DUTYCYCLE_RANGE 40000
 
 .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.
 
@@ -3815,6 +3942,11 @@ A whole number >= 0.
 
 .br
 
+.br
+See \fBgpio\fP.
+
+.br
+
 .br
 
 .IP "\fB*userdata\fP" 0
index 95866b276bd3d40ae19ff7cf867013cac56ea052..0f5020c5bc82c4e92f50ca43293a91d7ff808975 100644 (file)
@@ -25,7 +25,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 For more information, please refer to <http://unlicense.org/>
 */
 
-/* PIGPIOD_IF_VERSION 13 */
+/* PIGPIOD_IF_VERSION 14 */
 
 #include <stdio.h>
 #include <stdlib.h>
index b256d4662d8461560d5b81160f9276feddb29d2f..4db7071bdecd4bcdbf2d97e3e825caf6a0fd3186 100644 (file)
@@ -30,7 +30,7 @@ For more information, please refer to <http://unlicense.org/>
 
 #include "pigpio.h"
 
-#define PIGPIOD_IF_VERSION 13
+#define PIGPIOD_IF_VERSION 14
 
 /*TEXT
 
@@ -471,10 +471,13 @@ user_gpio: 0-31.
 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*/
@@ -520,7 +523,7 @@ Returns the dutycycle 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 range will be 1000.
+reported range will be 1000000 (1M).
 D*/
 
 /*F*/
@@ -535,8 +538,12 @@ user_gpio: 0-31.
 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*/
@@ -593,10 +600,13 @@ user_gpio: 0-31.
 . .
 
 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.
@@ -854,10 +864,11 @@ D*/
 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,
@@ -870,9 +881,9 @@ The gpio must be one of the following.
 
 . .
 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
@@ -892,6 +903,7 @@ D*/
 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.
 
@@ -901,26 +913,25 @@ 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,
 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
@@ -948,30 +959,22 @@ uint32_t get_hardware_revision(void);
 /*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*/
@@ -1404,8 +1407,8 @@ or PI_NOT_SERIAL_GPIO.
 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*/
 
@@ -1727,12 +1730,12 @@ Data will be transferred at baud bits per second.  The flags may
 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.
 . .
@@ -1749,6 +1752,8 @@ spi_flags consists of the least significant 22 bits.
 
 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
@@ -1762,7 +1767,7 @@ px is 0 if CEx is active low (default) and 1 for active high.
 ux is 0 if the CEx gpio is reserved for SPI (default) and 1 otherwise.
 
 A is 0 for the standard SPI device, 1 for the auxiliary SPI.  The
-auxiliary device is only present on the B+.
+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.
@@ -1950,17 +1955,17 @@ otherwise PI_BAD_HANDLE.
 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.
@@ -1968,7 +1973,7 @@ D*/
 
 
 /*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.
@@ -1979,7 +1984,7 @@ rather than just an integer.
 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
@@ -2068,6 +2073,22 @@ the pigpio daemon.  It may be NULL in which case localhost
 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.
@@ -2137,7 +2158,7 @@ typedef void (*CBFuncEx_t)
 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::
@@ -2180,6 +2201,32 @@ by its dutycycle.
 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
@@ -2305,19 +2352,19 @@ PI_MIN_SERVO_PULSEWIDTH 500
 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
@@ -2327,6 +2374,13 @@ PI_MIN_DUTYCYCLE_RANGE 25
 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.
 
@@ -2390,6 +2444,8 @@ A whole number >= 0.
 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.
 
diff --git a/pigs.1 b/pigs.1
index 78ff421209f30847c60470917762be013a3e93c6..0afa9c538c5a00a85faa9259b3f355ce252fcd28 100644 (file)
--- a/pigs.1
+++ b/pigs.1
@@ -236,7 +236,7 @@ will be returned.
 .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
@@ -336,7 +336,7 @@ will be returned.
 .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
@@ -351,6 +351,26 @@ ERROR: no permission to update one or more gpios
 
 .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
 
@@ -363,10 +383,15 @@ status code will be returned.
 
 .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
 
@@ -452,7 +477,7 @@ $ pigs help
 .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
@@ -488,10 +513,10 @@ The gpio must be one of the following.
 
 .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
 
@@ -516,7 +541,8 @@ with the gpio number.
 .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
@@ -534,28 +560,27 @@ will be returned.
 .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.
@@ -563,10 +588,10 @@ 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
 
@@ -588,7 +613,7 @@ The gpio must be one of the following.
 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
@@ -596,23 +621,12 @@ If the hardware revision can not be found or is not a valid hexadecimal
 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.
 
@@ -620,7 +634,7 @@ 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.
@@ -1491,8 +1505,13 @@ status code will be returned.
 
 .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.
 
@@ -1626,7 +1645,7 @@ will be returned.
 
 .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
 
@@ -1857,12 +1876,15 @@ ERROR: unknown script id
 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.
@@ -2412,7 +2434,7 @@ may be used to modify the default behaviour of 4-wire operation,
 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.
 
@@ -2432,6 +2454,9 @@ The flags consists of the least significant 22 bits.
 .br
 mm defines the SPI mode.
 
+.br
+Warning:  modes 1 and 3 do not appear to work on the auxiliary device.
+
 .br
 
 .EX
@@ -2456,7 +2481,7 @@ ux is 0 if the CEx gpio is reserved for SPI (default) and 1 otherwise.
 
 .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
@@ -3334,8 +3359,11 @@ Bank 2 consists of gpio32 through gpio53.
 
 .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.
@@ -3343,15 +3371,15 @@ 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
 
@@ -3466,17 +3494,17 @@ The command expects 0 to 10 numbers as parameters to be passed to the script.
 
 .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
@@ -3545,6 +3573,12 @@ See \fBg\fP
 
 .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.
 
@@ -3766,7 +3800,8 @@ Each script has
 .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.
index 6e6be8a51965c93ced080262479f17b559ff9047..8fec0ac6a27df287643b3a62e84604e4639bc264 100644 (file)
--- a/setup.py
+++ b/setup.py
@@ -3,7 +3,7 @@
 from distutils.core import setup
 
 setup(name='pigpio',
-      version='1.15',
+      version='1.16',
       author='joan',
       author_email='joan@abyz.co.uk',
       maintainer='joan',
diff --git a/x_pigs b/x_pigs
index f4242fb5b4309ccb8bde2f227f72649d23f4912e..143ff4e5b70608c3aa3b410e36f84dc9d237a40b 100755 (executable)
--- a/x_pigs
+++ b/x_pigs
@@ -1,7 +1,5 @@
 #!/bin/bash
 
-VERSION=29
-
 GPIO=4
 
 #
@@ -21,6 +19,11 @@ 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
 
@@ -91,9 +94,6 @@ if [[ $s = 10 ]]; then echo "PFS-a ok"; else echo "PFS-a 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)
diff --git a/x_pipe b/x_pipe
index f83a3e9cf1a8775e8c1ed5a50f84a4a28704012c..0697b243202106936c72ff5d13423b96d28e6247 100755 (executable)
--- a/x_pipe
+++ b/x_pipe
@@ -1,7 +1,5 @@
 #!/bin/bash
 
-VERSION=29
-
 GPIO=4
 
 #
@@ -20,6 +18,12 @@ 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
@@ -123,10 +127,6 @@ echo "pfs $GPIO 800" >/dev/pigpio
 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