V24
authorjoan <joan@abyz.me.uk>
Wed, 17 Dec 2014 22:31:17 +0000 (22:31 +0000)
committerjoan <joan@abyz.me.uk>
Wed, 17 Dec 2014 22:31:17 +0000 (22:31 +0000)
17 files changed:
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_pigpio.c
x_pigpio.py
x_pigpiod_if.c
x_pigs
x_pipe

index 3cb325aa4c2e2e258f01e790c6ad8044d6f75871..d35e337179bb24bbcc9203343a84cac19d7a4403 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 23+
+This version is for pigpio version 24+
 */
 
 #include <stdio.h>
@@ -57,6 +57,9 @@ cmdInfo_t cmdInfo[]=
    {PI_CMD_HELP,  "H",     101, 5}, // cmdUsage
    {PI_CMD_HELP,  "HELP",  101, 5}, // cmdUsage
 
+   {PI_CMD_HC,    "HC",    121, 0}, // gpioHardwareClock
+   {PI_CMD_HP,    "HP",    131, 0}, // gpioHardwarePWM
+
    {PI_CMD_HWVER, "HWVER", 101, 4}, // gpioHardwareRevision
 
    {PI_CMD_I2CC,  "I2CC",  112, 0}, // i2cClose
@@ -226,6 +229,9 @@ GPW u            Get servo pulsewidth for gpio.\n\
 \n\
 H/HELP           Display command help.\n\
 \n\
+HC g cf          Set hardware clock frequency.\n\
+HP g pf pdc      Set hardware PWM frequency and dutycycle.\n\
+\n\
 HWVER            Get hardware version.\n\
 \n\
 I2CC h           Close I2C handle.\n\
@@ -314,7 +320,8 @@ W/WRITE g L      Write level to gpio.\n\
 WDOG u v         Set millisecond watchdog on gpio.\n\
 \n\
 WVAG trips       Wave add generic pulses.\n\
-WVAS u b o bvs   Wave add serial data with offset for gpio at baud.\n\
+WVAS u b db hb   Wave add serial data for gpio u at b baud, db databits,\n\
+     o bvs            hb (half)stopbits, offset o micros from wave start.\n\
 WVBSY            Check if wave busy.\n\
 WVCLR            Wave clear.\n\
 WVCRE            Create wave from added pulses.\n\
@@ -332,8 +339,11 @@ 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\
+db    = data bits (1-32).\n\
 g     = any gpio (0-53).\n\
 h     = handle (>=0).\n\
+hb    = (half) stop bits (2-8).\n\
 ib    = I2C bus (0-1).\n\
 id    = I2C device (0-127).\n\
 if    = I2C flags (0).\n\
@@ -343,7 +353,9 @@ num   = number of bytes to read.\n\
 o     = offset (>=0).\n\
 p     = pud (ODU).\n\
 pars  = 0 to 10 parameters for script.\n\
-pl    = pulse length (1-50).\n\
+pdc   = hardware PWM dutycycle (0-1000).\n\
+pf    = hardware PWM frequency (5-250K).\n\
+pl    = pulse length (1-100).\n\
 r     = register.\n\
 sid   = script id (>=0).\n\
 sb    = SPI baud.\n\
@@ -389,7 +401,7 @@ static errInfo_t errInfo[]=
    {PI_BAD_WDOG_TIMEOUT , "timeout not 0-60000"},
    {PI_NO_ALERT_FUNC    , "DEPRECATED"},
    {PI_BAD_CLK_PERIPH   , "clock peripheral not 0-1"},
-   {PI_BAD_CLK_SOURCE   , "clock source not 0-1"},
+   {PI_BAD_CLK_SOURCE   , "DEPRECATED"},
    {PI_BAD_CLK_MICROS   , "clock micros not 1, 2, 4, 5, 8, or 10"},
    {PI_BAD_BUF_MILLIS   , "buf millis not 100-10000"},
    {PI_BAD_DUTYRANGE    , "dutycycle range not 25-40000"},
@@ -406,7 +418,7 @@ static errInfo_t errInfo[]=
    {PI_INITIALISED      , "function called after gpioInitialise"},
    {PI_BAD_WAVE_MODE    , "waveform mode not 0-1"},
    {PI_BAD_CFG_INTERNAL , "bad parameter in gpioCfgInternals call"},
-   {PI_BAD_WAVE_BAUD    , "baud rate not 100-250000"},
+   {PI_BAD_WAVE_BAUD    , "baud rate not 50-250K(RX)/50-1M(TX)"},
    {PI_TOO_MANY_PULSES  , "waveform has too many pulses"},
    {PI_TOO_MANY_CHARS   , "waveform has too many chars"},
    {PI_NOT_SERIAL_GPIO  , "no serial read in progress on gpio"},
@@ -417,22 +429,22 @@ static errInfo_t errInfo[]=
    {PI_BAD_WVSC_COMMND  , "bad WVSC subcommand"},
    {PI_BAD_WVSM_COMMND  , "bad WVSM subcommand"},
    {PI_BAD_WVSP_COMMND  , "bad WVSP subcommand"},
-   {PI_BAD_PULSELEN     , "trigger pulse > 100 microseconds"},
+   {PI_BAD_PULSELEN     , "trigger pulse length not 1-100"},
    {PI_BAD_SCRIPT       , "invalid script"},
    {PI_BAD_SCRIPT_ID    , "unknown script id"},
    {PI_BAD_SER_OFFSET   , "add serial data offset > 30 minute"},
    {PI_GPIO_IN_USE      , "gpio already in use"},
    {PI_BAD_SERIAL_COUNT , "must read at least a byte at a time"},
-   {PI_BAD_PARAM_NUM    , "script parameter must be 0-9"},
+   {PI_BAD_PARAM_NUM    , "script parameter id not 0-9"},
    {PI_DUP_TAG          , "script has duplicate tag"},
    {PI_TOO_MANY_TAGS    , "script has too many tags"},
    {PI_BAD_SCRIPT_CMD   , "illegal script command"},
-   {PI_BAD_VAR_NUM      , "script variable must be 0-149"},
+   {PI_BAD_VAR_NUM      , "script variable id not 0-149"},
    {PI_NO_SCRIPT_ROOM   , "no more room for scripts"},
    {PI_NO_MEMORY        , "can't allocate temporary memory"},
    {PI_SOCK_READ_FAILED , "socket read failed"},
    {PI_SOCK_WRIT_FAILED , "socket write failed"},
-   {PI_TOO_MANY_PARAM   , "too many script parameters > 10"},
+   {PI_TOO_MANY_PARAM   , "too many script parameters (> 10)"},
    {PI_NOT_HALTED       , "script already running or failed"},
    {PI_BAD_TAG          , "script has unresolved tag"},
    {PI_BAD_MICS_DELAY   , "bad MICS delay (too large)"},
@@ -465,6 +477,16 @@ static errInfo_t errInfo[]=
    {PI_NO_AUX_SPI       , "need a B+ 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-250K"},
+   {PI_BAD_HPWM_DUTY    , "hardware PWM dutycycle not 0-1000"},
+   {PI_BAD_HCLK_FREQ    , "hardware clock frequency not 4689-25M"},
+   {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"},
+
 
 };
 
@@ -535,8 +557,8 @@ int cmdParse(
    char *p8;
    int32_t *p32;
    char c;
-   uint32_t tp1;
-   int8_t to1;
+   uint32_t tp1, tp2, tp3;
+   int8_t to1, to2, to3;
 
    /* Check that ext is big enough for the largest message. */
    if (ext_len < (4 * CMD_MAX_PARAM)) return CMD_EXT_TOO_SMALL;
@@ -659,7 +681,7 @@ int cmdParse(
 
          break;
 
-      case 121: /* I2CRD  I2CRR  I2CRW  I2CWB I2CWQ  P  PFS  PRS
+      case 121: /* HC I2CRD  I2CRR  I2CRW  I2CWB I2CWQ  P  PFS  PRS
                    PWM  S  SERVO  SLR  SLRO  W  WDOG  WRITE
 
                    Two positive parameters.
@@ -756,7 +778,7 @@ int cmdParse(
 
          break;
 
-      case 131: /* I2CO  I2CPC  I2CRI  I2CWB  I2CWW  SPIO  TRIG
+      case 131: /* HP I2CO  I2CPC  I2CRI  I2CWB  I2CWW  SPIO  TRIG
 
                    Three positive parameters.
                 */
@@ -926,21 +948,29 @@ int cmdParse(
                    p2 baud
                    p3 len + 4
                    ---------
+                   uint32_t databits
+                   uint32_t stophalfbits
                    uint32_t offset
                    uint8_t[len]
                 */
          ctl->eaten += getNum(buf+ctl->eaten, &p[1], &ctl->opt[1]);
          ctl->eaten += getNum(buf+ctl->eaten, &p[2], &ctl->opt[2]);
          ctl->eaten += getNum(buf+ctl->eaten, &tp1, &to1);
+         ctl->eaten += getNum(buf+ctl->eaten, &tp2, &to2);
+         ctl->eaten += getNum(buf+ctl->eaten, &tp3, &to3);
 
          if ((ctl->opt[1] == CMD_NUMERIC) && ((int)p[1] >= 0) &&
              (ctl->opt[2] == CMD_NUMERIC) && ((int)p[2] > 0) &&
-             (to1 == CMD_NUMERIC))
+             (to1 == CMD_NUMERIC) &&
+             (to2 == CMD_NUMERIC) &&
+             (to3 == CMD_NUMERIC))
          {
             pars = 0;
 
             memcpy(ext, &tp1, 4);
-            p8 = ext + 4;
+            memcpy(ext+4, &tp2, 4);
+            memcpy(ext+8, &tp3, 4);
+            p8 = ext + 12;
             while (pars < CMD_MAX_PARAM)
             {
                ctl->eaten += getNum(buf+ctl->eaten, &tp1, &to1);
@@ -953,7 +983,7 @@ int cmdParse(
                else break;
             }
 
-            p[3] = pars + 4;
+            p[3] = pars + 12;
 
             if (pars > 0) valid = 1;
          }
index 786e5f7d426aa5a458980f64ed0cf2d6e01b48e7..6abef88840cc870bb412a53c021f9022ea7e7b15 100644 (file)
--- a/pigpio.3
+++ b/pigpio.3
@@ -1516,11 +1516,11 @@ else
 
 .EE
 
-.IP "\fBint gpioWaveAddSerial(unsigned user_gpio, unsigned bbBaud, unsigned offset, unsigned numChar, char *str)\fP"
+.IP "\fBint gpioWaveAddSerial(unsigned user_gpio, unsigned bbBaud, unsigned bbBits, unsigned bbStop, unsigned offset, unsigned numBytes, char *str)\fP"
 .IP "" 4
 This function adds a waveform representing serial data to the
-existing waveform (if any).  The serial data starts offset microseconds
-from the start of the waveform.
+existing waveform (if any).  The serial data starts offset
+microseconds from the start of the waveform.
 
 .br
 
@@ -1529,11 +1529,15 @@ from the start of the waveform.
 .EX
 user_gpio: 0-31
 .br
-   bbBaud: 100-250000
+   bbBaud: 100-1000000
+.br
+   bbBits: 1-32
+.br
+   bbStop: 2-8
 .br
    offset: 0-
 .br
 numChar: 1-
numBytes: 1-
 .br
       str: an array of chars (which may contain nulls)
 .br
@@ -1544,14 +1548,20 @@ user_gpio: 0-31
 
 .br
 Returns the new total number of pulses in the current waveform if OK,
-otherwise PI_BAD_USER_GPIO, PI_BAD_WAVE_BAUD, PI_TOO_MANY_CHARS,
-PI_BAD_SER_OFFSET, or PI_TOO_MANY_PULSES.
+otherwise PI_BAD_USER_GPIO, PI_BAD_WAVE_BAUD, PI_BAD_DATABITS,
+PI_BAD_STOPBITS, PI_TOO_MANY_CHARS, PI_BAD_SER_OFFSET,
+or PI_TOO_MANY_PULSES.
+
+.br
+
+.br
+NOTES:
 
 .br
 
 .br
-The serial data is formatted as one start bit, eight data bits, and one
-stop bit.
+The serial data is formatted as one start bit, bbBits data bits, and
+bbStop/2 stop bits.
 
 .br
 
@@ -1561,6 +1571,25 @@ the same waveform.
 
 .br
 
+.br
+numBytes is the number of bytes of data in str.
+
+.br
+
+.br
+The bytes required for each character depend upon bbBits.
+
+.br
+
+.br
+For bbBits 1-8 there will be one byte per character.
+.br
+For bbBits 9-16 there will be two bytes per character.
+.br
+For bbBits 17-32 there will be four bytes per character.
+
+.br
+
 .br
 \fBExample\fP
 .br
@@ -1582,7 +1611,7 @@ str = "Hello world!";
 .br
 
 .br
-gpioWaveAddSerial(4, 9600, 0, strlen(str), str);
+gpioWaveAddSerial(4, 9600, 8, 2, 0, strlen(str), str);
 .br
 
 .br
@@ -1592,7 +1621,7 @@ for (i=0; i<MSG_LEN; i++) data[i] = i;
 .br
 // Data added is offset 1 second from the waveform start.
 .br
-gpioWaveAddSerial(4, 9600, 1000000, MSG_LEN, data);
+gpioWaveAddSerial(4, 9600, 8, 2, 1000000, MSG_LEN, data);
 .br
 
 .EE
@@ -1735,6 +1764,11 @@ determines whether the waveform is sent once or cycles endlessly.
 
 .br
 
+.br
+NOTE: Any hardware PWM started by \fBgpioHardwarePWM\fP will be cancelled.
+
+.br
+
 .br
 
 .EX
@@ -1762,6 +1796,11 @@ determines whether the waveform is sent once or cycles endlessly.
 
 .br
 
+.br
+NOTE: Any hardware PWM started by \fBgpioHardwarePWM\fP will be cancelled.
+
+.br
+
 .br
 
 .EX
@@ -2922,8 +2961,8 @@ Returns 0 if OK.
 .br
 
 .br
-The function is passed a pointer to the samples and the number
-of samples.
+The function is passed a pointer to the samples (an array of
+\fBgpioSample_t\fP),  and the number of samples.
 
 .br
 
@@ -2975,8 +3014,8 @@ Returns 0 if OK.
 .br
 
 .br
-The function is passed a pointer to the samples, the number
-of samples, and the userdata pointer.
+The function is passed a pointer to the samples (an array of
+\fBgpioSample_t\fP), the number of samples, and the userdata pointer.
 
 .br
 
@@ -3554,6 +3593,154 @@ gpioWrite_Bits_32_53_Set((1<<(32-32)) | (1<<(40-32)) | (1<<(53-32)));
 
 .EE
 
+.IP "\fBint gpioHardwareClock(unsigned gpio, unsigned clkfreq)\fP"
+.IP "" 4
+Starts a hardware clock on a gpio at the specified frequency.
+
+.br
+
+.br
+
+.EX
+   gpio: see description
+.br
+clkfreq: 0 (off) or 4689-250M
+.br
+
+.EE
+
+.br
+
+.br
+Returns 0 if OK, otherwise PI_BAD_GPIO, PI_NOT_HCLK_GPIO,
+PI_BAD_HCLK_FREQ,or PI_BAD_HCLK_PASS.
+
+.br
+
+.br
+The same clock is available on multiple gpios.  The latest
+frequency setting will be used by all gpios which share a clock.
+
+.br
+
+.br
+The gpio must be one of the following.
+
+.br
+
+.br
+
+.EX
+4   clock 0  All models
+.br
+5   clock 1  A+/B+ and compute module only (reserved for system use)
+.br
+6   clock 2  A+/B+ and compute module only
+.br
+20  clock 0  A+/B+ and compute module only
+.br
+21  clock 1  All models but Rev.2 B (reserved for system use)
+.br
+
+.br
+32  clock 0  Compute module only
+.br
+34  clock 0  Compute module only
+.br
+42  clock 1  Compute module only (reserved for system use)
+.br
+43  clock 2  Compute module only
+.br
+44  clock 1  Compute module only (reserved for system use)
+.br
+
+.EE
+
+.br
+
+.br
+Access to clock 1 is protected by a password as its use will likely
+crash the Pi.  The password is given by or'ing 0x5A000000 with the
+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.
+
+.br
+
+.br
+NOTE: Any waveform started by \fBgpioWaveTxSend\fP or \fBgpioWaveTxStart\fP
+will be cancelled.
+
+.br
+
+.br
+This function is only valid if the pigpio main clock is PCM.  The
+main clock defaults to PCM but may be overridden by a call to
+\fBgpioCfgClock\fP.
+
+.br
+
+.br
+
+.EX
+   gpio: see description
+.br
+PWMfreq: 0 (off) or 5-250K
+.br
+PWMduty: 0 (off) to 1000 (fully on).
+.br
+
+.EE
+
+.br
+
+.br
+Returns 0 if OK, otherwise PI_BAD_GPIO, PI_NOT_HPWM_GPIO,
+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.
+
+.br
+
+.br
+The gpio must be one of the following.
+
+.br
+
+.br
+
+.EX
+12  PWM channel 0  A+/B+ and compute module only
+.br
+13  PWM channel 1  A+/B+ and compute module only
+.br
+18  PWM channel 0  All models
+.br
+19  PWM channel 1  A+/B+ and compute module only
+.br
+
+.br
+40  PWM channel 0  Compute module only
+.br
+41  PWM channel 1  Compute module only
+.br
+45  PWM channel 1  Compute module only
+.br
+52  PWM channel 0  Compute module only
+.br
+53  PWM channel 1  Compute module only
+.br
+
+.EE
+
 .IP "\fBint gpioTime(unsigned timetype, int *seconds, int *micros)\fP"
 .IP "" 4
 Updates the seconds and micros variables with the current time.
@@ -3890,7 +4077,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
-peripheral and clock source.
+peripheral.
 
 .br
 
@@ -3901,7 +4088,7 @@ peripheral and clock source.
 .br
 cfgPeripheral: 0 (PWM), 1 (PCM)
 .br
-    cfgSource: 0 (OSC), 1 (PLLD)
+    cfgSource: deprecated, value is ignored
 .br
 
 .EE
@@ -3909,14 +4096,12 @@ cfgPeripheral: 0 (PWM), 1 (PCM)
 .br
 
 .br
-The timings are provided by the specified peripheral (PWM or PCM)
-using the frequency source (OSC or PLLD).
+The timings are provided by the specified peripheral (PWM or PCM).
 
 .br
 
 .br
-The default setting is 5 microseconds using the PCM peripheral
-with the PLLD source.
+The default setting is 5 microseconds using the PCM peripheral.
 
 .br
 
@@ -4438,9 +4623,59 @@ serial data.
 .br
 
 .EX
-PI_WAVE_MIN_BAUD 100
+PI_BB_MIN_BAUD 50
 .br
-PI_WAVE_MAX_BAUD 250000
+PI_BB_RX_MAX_BAUD 250000
+.br
+PI_BB_TX_MAX_BAUD 1000000
+.br
+
+.EE
+
+.br
+
+.br
+
+.IP "\fBbbBits\fP: 1-32" 0
+
+.br
+
+.br
+The number of data bits to be used when adding serial data to a
+waveform.
+
+.br
+
+.br
+
+.EX
+#define PI_MIN_WAVE_DATABITS 1
+.br
+#define PI_MAX_WAVE_DATABITS 32
+.br
+
+.EE
+
+.br
+
+.br
+
+.IP "\fBbbStop\fP: 2-8" 0
+
+.br
+
+.br
+The number of (half) stop bits to be used when adding serial data
+to a waveform.
+
+.br
+
+.br
+
+.EX
+#define PI_MIN_WAVE_HALFSTOPBITS 2
+.br
+#define PI_MAX_WAVE_HALFSTOPBITS 8
 .br
 
 .EE
@@ -4580,16 +4815,7 @@ purposes.
 .br
 
 .br
-The clock source used for the timing of DMA transfers.  May be the 19.2MHz
-crystal or the 500MHz PLL.
-
-.EX
-PI_CLOCK_OSC 0
-.br
-PI_CLOCK_PLLD 1
-.br
-
-.EE
+Deprecated.
 
 .br
 
@@ -4635,6 +4861,29 @@ A single character, an 8 bit quantity able to store 0-255.
 
 .br
 
+.IP "\fBclkfreq\fP: 4689-250M" 0
+
+.br
+
+.br
+The hardware clock frequency.
+
+.br
+
+.br
+
+.EX
+#define PI_HW_CLK_MIN_FREQ 4689
+.br
+#define PI_HW_CLK_MAX_FREQ 250000000
+.br
+
+.EE
+
+.br
+
+.br
+
 .IP "\fBcount\fP" 0
 
 .br
@@ -5167,13 +5416,14 @@ The number of bits stored in a buffer.
 
 .br
 
-.IP "\fBnumChar\fP" 0
+.IP "\fBnumBytes\fP" 0
 
 .br
 
 .br
-The number of characters in a string (used when the string might contain
-null characters, which would normally terminate the string).
+The number of bytes used to store characters in a string.  Depending
+on the number of bits per character there may be 1, 2, or 4 bytes
+per character.
 
 .br
 
@@ -5340,6 +5590,42 @@ PI_MAX_SERVO_PULSEWIDTH 2500
 
 .br
 
+.IP "\fBPWMduty\fP: 0-1000" 0
+The hardware PWM dutycycle.
+
+.br
+
+.br
+
+.EX
+#define PI_HW_PWM_RANGE 1000
+.br
+
+.EE
+
+.br
+
+.br
+
+.IP "\fBPWMfreq\fP: 5-250K" 0
+The hardware PWM frequency.
+
+.br
+
+.br
+
+.EX
+#define PI_HW_PWM_MIN_FREQ 5
+.br
+#define PI_HW_PWM_MAX_FREQ 250000
+.br
+
+.EE
+
+.br
+
+.br
+
 .IP "\fBrange\fP: 25-40000" 0
 
 .EX
@@ -6074,6 +6360,12 @@ A 16-bit word value.
 #define PI_CMD_GPW   84
 .br
 
+.br
+#define PI_CMD_HC    85
+.br
+#define PI_CMD_HP    86
+.br
+
 .br
 #define PI_CMD_NOIB  99
 .br
@@ -6120,7 +6412,7 @@ A 16-bit word value.
 .br
 #define PI_BAD_CLK_PERIPH   -17 // clock peripheral not 0-1
 .br
-#define PI_BAD_CLK_SOURCE   -18 // clock source not 0-1
+#define PI_BAD_CLK_SOURCE   -18 // DEPRECATED
 .br
 #define PI_BAD_CLK_MICROS   -19 // clock micros not 1, 2, 4, 5, 8, or 10
 .br
@@ -6158,7 +6450,7 @@ A 16-bit word value.
 .br
 #define PI_BAD_CFG_INTERNAL -34 // bad parameter in gpioCfgInternals call
 .br
-#define PI_BAD_WAVE_BAUD    -35 // baud rate not 100-250000
+#define PI_BAD_WAVE_BAUD    -35 // baud rate not 50-250K(RX)/50-1M(TX)
 .br
 #define PI_TOO_MANY_PULSES  -36 // waveform has too many pulses
 .br
@@ -6180,7 +6472,7 @@ A 16-bit word value.
 .br
 #define PI_BAD_WVSP_COMMND  -45 // bad WVSP subcommand
 .br
-#define PI_BAD_PULSELEN     -46 // trigger pulse length 100
+#define PI_BAD_PULSELEN     -46 // trigger pulse length not 1-100
 .br
 #define PI_BAD_SCRIPT       -47 // invalid script
 .br
@@ -6192,7 +6484,7 @@ A 16-bit word value.
 .br
 #define PI_BAD_SERIAL_COUNT -51 // must read at least a byte at a time
 .br
-#define PI_BAD_PARAM_NUM    -52 // script parameter must be 0-9
+#define PI_BAD_PARAM_NUM    -52 // script parameter id not 0-9
 .br
 #define PI_DUP_TAG          -53 // script has duplicate tag
 .br
@@ -6200,7 +6492,7 @@ A 16-bit word value.
 .br
 #define PI_BAD_SCRIPT_CMD   -55 // illegal script command
 .br
-#define PI_BAD_VAR_NUM      -56 // script variable must be 0-149
+#define PI_BAD_VAR_NUM      -56 // script variable id not 0-149
 .br
 #define PI_NO_SCRIPT_ROOM   -57 // no more room for scripts
 .br
@@ -6210,7 +6502,7 @@ A 16-bit word value.
 .br
 #define PI_SOCK_WRIT_FAILED -60 // socket write failed
 .br
-#define PI_TOO_MANY_PARAM   -61 // too many script parameters > 10
+#define PI_TOO_MANY_PARAM   -61 // too many script parameters (> 10)
 .br
 #define PI_NOT_HALTED       -62 // script already running or failed
 .br
@@ -6276,6 +6568,24 @@ A 16-bit word value.
 .br
 #define PI_NOT_SERVO_GPIO   -93 // gpio is not in use for servo pulses
 .br
+#define PI_NOT_HCLK_GPIO    -94 // gpio has no hardware clock
+.br
+#define PI_NOT_HPWM_GPIO    -95 // gpio has no hardware PWM
+.br
+#define PI_BAD_HPWM_FREQ    -96 // hardware PWM frequency not 5-250K
+.br
+#define PI_BAD_HPWM_DUTY    -97 // hardware PWM dutycycle not 0-1000
+.br
+#define PI_BAD_HCLK_FREQ    -98 // hardware clock frequency not 4689-25M
+.br
+#define PI_BAD_HCLK_PASS    -99 // need password to use hardware clock 1
+.br
+#define PI_HPWM_ILLEGAL    -100 // illegal, PWM in use for main clock
+.br
+#define PI_BAD_DATABITS    -101 // serial data bits not 1-32
+.br
+#define PI_BAD_STOPBITS    -102 // serial (half) stop bits not 2-8
+.br
 
 .br
 
@@ -6291,8 +6601,6 @@ A 16-bit word value.
 .br
 #define PI_DEFAULT_CLK_PERIPHERAL        PI_CLOCK_PCM
 .br
-#define PI_DEFAULT_CLK_SOURCE            PI_CLOCK_PLLD
-.br
 #define PI_DEFAULT_IF_FLAGS              0
 .br
 #define PI_DEFAULT_DMA_CHANNEL           14
index 48e0f9f988dcc44c186b995055cc891c3be67acc..6ed7db5666f795549944cebe37a2391116df5dcb 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 23 */
+/* pigpio version 24 */
 
 #include <stdio.h>
 #include <string.h>
@@ -376,6 +376,9 @@ bit 0 READ_LAST_NOT_SET_ERROR
 #define PWM_RNG2     8
 #define PWM_DAT2     9
 
+#define PWM_CTL_MSEN2 (1<<15)
+#define PWM_CTL_PWEN2 (1<<8)
+#define PWM_CTL_MSEN1 (1<<7)
 #define PWM_CTL_CLRF1 (1<<6)
 #define PWM_CTL_USEF1 (1<<5)
 #define PWM_CTL_MODE1 (1<<1)
@@ -466,12 +469,24 @@ bit 0 READ_LAST_NOT_SET_ERROR
 #define CLK_CTL_ENAB    (1 <<4)
 #define CLK_CTL_SRC(x) ((x)<<0)
 
-#define CLK_CTL_SRC_OSC  1  /*  19.2 MHz */
-#define CLK_CTL_SRC_PLLD 6  /* 500.0 MHz */
+#define CLK_SRCS 2
+
+#define CLK_CTL_SRC_OSC  1
+#define CLK_CTL_SRC_PLLD 6
+
+#define CLK_OSC_FREQ   19200000
+#define CLK_PLLD_FREQ 500000000
 
 #define CLK_DIV_DIVI(x) ((x)<<12)
 #define CLK_DIV_DIVF(x) ((x)<< 0)
 
+#define CLK_GP0_CTL 28
+#define CLK_GP0_DIV 29
+#define CLK_GP1_CTL 30
+#define CLK_GP1_DIV 31
+#define CLK_GP2_CTL 32
+#define CLK_GP2_DIV 33
+
 #define CLK_PCMCTL 38
 #define CLK_PCMDIV 39
 
@@ -628,6 +643,10 @@ bit 0 READ_LAST_NOT_SET_ERROR
 #define GPIO_WRITE     1
 #define GPIO_PWM       2
 #define GPIO_SERVO     3
+#define GPIO_HW_CLK    4
+#define GPIO_HW_PWM    5
+#define GPIO_SPI       6
+#define GPIO_I2C       7
 
 #define STACK_SIZE (256*1024)
 
@@ -714,6 +733,8 @@ bit 0 READ_LAST_NOT_SET_ERROR
 #define PI_I2C_SMBUS_BLOCK_MAX     32
 #define PI_I2C_SMBUS_I2C_BLOCK_MAX 32
 
+#define PI_MASH_MAX_FREQ 23800000
+
 /* --------------------------------------------------------------- */
 
 typedef void (*callbk_t) ();
@@ -815,12 +836,7 @@ typedef struct
 typedef struct
 {
    uint16_t valid;
-   uint16_t bits;
-   uint16_t divi;
-   uint16_t divf;
-   uint16_t mash;
    uint16_t servoIdx;
-   uint16_t pwmIdx;
 } clkCfg_t;
 
 typedef struct
@@ -884,7 +900,6 @@ typedef struct
    unsigned bufferMilliseconds;
    unsigned clockMicros;
    unsigned clockPeriph;
-   unsigned clockSource;
    unsigned DMAprimaryChannel;
    unsigned DMAsecondaryChannel;
    unsigned socketPort;
@@ -940,6 +955,13 @@ struct my_smbus_ioctl_data
    union my_smbus_data *data;
 };
 
+typedef struct
+{
+   unsigned div;
+   unsigned frac;
+   unsigned clock;
+} clkInf_t;
+
 /* --------------------------------------------------------------- */
 
 /* initialise once then preserve */
@@ -949,7 +971,6 @@ static volatile gpioCfg_t gpioCfg =
    PI_DEFAULT_BUFFER_MILLIS,
    PI_DEFAULT_CLK_MICROS,
    PI_DEFAULT_CLK_PERIPHERAL,
-   PI_DEFAULT_CLK_SOURCE,
    PI_DEFAULT_DMA_PRIMARY_CHANNEL,
    PI_DEFAULT_DMA_SECONDARY_CHANNEL,
    PI_DEFAULT_SOCKET_PORT,
@@ -965,6 +986,7 @@ static int gpioMaskSet = 0;
 /* initialise every gpioInitialise */
 
 static struct timespec libStarted;
+static int waveClockInited = 0;
 
 /* initialse if not libInitialised */
 
@@ -1010,7 +1032,7 @@ static gpioAlert_t      gpioAlert  [PI_MAX_USER_GPIO+1];
 
 static gpioGetSamples_t gpioGetSamples;
 
-static gpioInfo_t       gpioInfo   [PI_MAX_USER_GPIO+1];
+static gpioInfo_t       gpioInfo   [PI_MAX_GPIO+1];
 
 static gpioNotify_t     gpioNotify [PI_NOTIFY_SLOTS];
 
@@ -1073,20 +1095,82 @@ static volatile uint32_t * dmaOut  = MAP_FAILED;
 
 /* constant data */
 
+/*
+ 7 6 5 4 3 2 1 0
+ V . C C . M M M
+
+ V: 0 no clock, 1 has a clock
+CC: 00 CLK0, 01 CLK1, 10 CLK2
+ M: 100 ALT0, 010 ALT5
+
+ gpio4  GPCLK0 ALT0
+ gpio5  GPCLK1 ALT0 B+ and compute module only (reserved for system use)
+ gpio6  GPCLK2 ALT0 B+ and compute module only
+ gpio20 GPCLK0 ALT5 B+ and compute module only
+ gpio21 GPCLK1 ALT5 Not available on Rev.2 B (reserved for system use)
+
+ gpio32 GPCLK0 ALT0 Compute module only
+ gpio34 GPCLK0 ALT0 Compute module only
+ gpio42 GPCLK1 ALT0 Compute module only (reserved for system use)
+ gpio43 GPCLK2 ALT0 Compute module only
+ gpio44 GPCLK1 ALT0 Compute module only (reserved for system use)
+*/
+
+uint8_t clkDef[PI_MAX_GPIO + 1] =
+{
+ /*             0     1     2     3     4     5     6     7     8     9 */
+   /* 0 */   0x00, 0x00, 0x00, 0x00, 0x84, 0x94, 0xA4, 0x00, 0x00, 0x00,
+   /* 1 */   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   /* 2 */   0x82, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   /* 3 */   0x00, 0x00, 0x84, 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00,
+   /* 4 */   0x00, 0x00, 0x94, 0xA4, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00,
+   /* 5 */   0x00, 0x00, 0x00, 0x00,
+};
+
+/*
+ 7 6 5 4 3 2 1 0
+ V . . P . M M M
+
+ V: 0 no PWM, 1 has a PWM
+ P: 0 PWM0, 1 PWM1
+ M: 010 ALT5, 100 ALT0, 101 ALT1
+
+ gpio12 pwm0 ALT0
+ gpio13 pwm1 ALT0
+ gpio18 pwm0 ALT5
+ gpio19 pwm1 ALT5
+ gpio40 pwm0 ALT0
+ gpio41 pwm1 ALT0
+ gpio45 pwm1 ALT0
+ gpio52 pwm0 ALT1
+ gpio53 pwm1 ALT1
+*/
+
+uint8_t PWMDef[PI_MAX_GPIO + 1] =
+{
+   /*          0     1     2     3     4     5     6     7     8     9 */
+   /* 0 */   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   /* 1 */   0x00, 0x00, 0x84, 0x94, 0x00, 0x00, 0x00, 0x00, 0x82, 0x92,
+   /* 2 */   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   /* 3 */   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   /* 4 */   0x84, 0x94, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x00,
+   /* 5 */   0x00, 0x00, 0x85, 0x95,
+};
+
 static const clkCfg_t clkCfg[]=
 {
-   /* valid bits  divi  divf mash servo                pwm */
-      {   0,   0,    0,    0,   0,    0,                  0}, /*  0 */
-      {   1,   9,    2,  546,   1,   17,    DEFAULT_PWM_IDX}, /*  1 */
-      {   1,  19,    2,   86,   1,   16,    DEFAULT_PWM_IDX}, /*  2 */
-      {   0,  19,    3,  129,   1,    0,                  0}, /*  3 */
-      {   1,  11,    6, 4021,   1,   15,    DEFAULT_PWM_IDX}, /*  4 */
-      {   1,   8,   12,    0,   0,   14,    DEFAULT_PWM_IDX}, /*  5 */
-      {   0,  23,    5,   35,   1,    0,                  0}, /*  6 */
-      {   0,  27, 4004,    0,   1,    0,                  0}, /*  7 */
-      {   1,  51,    3,   48,   1,   13,    DEFAULT_PWM_IDX}, /*  8 */
-      {   0,  43,    4,   76,   1,    0,                  0}, /*  9 */
-      {   1,   8,   24,    0,   0,   12,    DEFAULT_PWM_IDX}, /* 10 */
+   /* valid servo */
+      {   0,    0}, /*  0 */
+      {   1,   17}, /*  1 */
+      {   1,   16}, /*  2 */
+      {   0,    0}, /*  3 */
+      {   1,   15}, /*  4 */
+      {   1,   14}, /*  5 */
+      {   0,    0}, /*  6 */
+      {   0,    0}, /*  7 */
+      {   1,   13}, /*  8 */
+      {   0,    0}, /*  9 */
+      {   1,   12}, /* 10 */
 };
 
 static const uint16_t pwmCycles[PWM_FREQS]=
@@ -1105,6 +1189,8 @@ static const uint16_t pwmRealRange[PWM_FREQS]=
 static void intNotifyBits(void);
 static void intScriptBits(void);
 static int  gpioNotifyOpenInBand(int fd);
+static void initHWClk
+   (int clkCtl, int clkDiv, int clkSrc, int divI, int divF, int MASH);
 
 /* ======================================================================= */
 
@@ -1186,9 +1272,14 @@ static uint32_t myGpioDelay(uint32_t micros)
 
    start = systReg[SYST_CLO];
 
-   if (micros <= PI_MAX_BUSY_DELAY) while ((systReg[SYST_CLO] - start) <= micros);
-
-   else myGpioSleep(micros/MILLION, micros%MILLION);
+   if (micros <= PI_MAX_BUSY_DELAY)
+   {
+      while ((systReg[SYST_CLO] - start) <= micros);
+   }
+   else
+   {
+      myGpioSleep(micros/MILLION, micros%MILLION);
+   }
 
    return (systReg[SYST_CLO] - start);
 }
@@ -1262,15 +1353,20 @@ static uint32_t myGetTick(int pos)
 
 static int myPermit(unsigned gpio)
 {
-   if (gpioMask & ((uint64_t)(1)<<gpio)) return 1; else return 0;
+   if ((gpio <= PI_MAX_GPIO) &&
+       (gpioMask & ((uint64_t)(1)<<gpio)))
+      return 1;
+   else
+      return 0;
 }
 
 /* ----------------------------------------------------------------------- */
 
 static int myDoCommand(uint32_t *p, unsigned bufSize, char *buf)
 {
-   int res, i, j, tmp;
+   int res, i, j;
    uint32_t mask;
+   uint32_t tmp1, tmp2, tmp3;
    gpioPulse_t *pulse;
    int masked;
 
@@ -1342,8 +1438,34 @@ static int myDoCommand(uint32_t *p, unsigned bufSize, char *buf)
 
       case PI_CMD_GPW: res = gpioGetServoPulsewidth(p[1]); break;
 
+      case PI_CMD_HC:
+         /* special case to allow password in upper byte */
+         if (myPermit(p[1]&0xFFFFFF)) res = gpioHardwareClock(p[1], p[2]);
+         else
+         {
+            DBG(DBG_USER,
+               "gpioHardwareClock: gpio %d, no permission to update",
+                p[1] & 0xFFFFFF);
+            res = PI_NOT_PERMITTED;
+         }
+         break;
+
       case PI_CMD_HELP: break;
 
+      case PI_CMD_HP:
+         if (myPermit(p[1]))
+         {
+            memcpy(&p[4], buf, 4);
+            res = gpioHardwarePWM(p[1], p[2], p[4]);
+         }
+         else
+         {
+            DBG(DBG_USER,
+               "gpioHardwarePWM: gpio %d, no permission to update", p[1]);
+            res = PI_NOT_PERMITTED;
+         }
+         break;
+
       case PI_CMD_HWVER: res = gpioHardwareRevision(); break;
 
 
@@ -1428,7 +1550,8 @@ static int myDoCommand(uint32_t *p, unsigned bufSize, char *buf)
          if (myPermit(p[1])) res = gpioSetMode(p[1], p[2]);
          else
          {
-            DBG(DBG_USER, "gpioSetMode: gpio %d, no permission to update", p[1]);
+            DBG(DBG_USER,
+               "gpioSetMode: gpio %d, no permission to update", p[1]);
             res = PI_NOT_PERMITTED;
          }
          break;
@@ -1569,8 +1692,6 @@ static int myDoCommand(uint32_t *p, unsigned bufSize, char *buf)
          res = spiXfer(p[1], buf, buf, p[3]);
          break;
 
-
-
       case PI_CMD_TICK: res = gpioTick(); break;
 
       case PI_CMD_TRIG:
@@ -1581,7 +1702,8 @@ static int myDoCommand(uint32_t *p, unsigned bufSize, char *buf)
          }
          else
          {
-            DBG(DBG_USER, "gpioTrigger: gpio %d, no permission to update", p[1]);
+            DBG(DBG_USER,
+               "gpioTrigger: gpio %d, no permission to update", p[1]);
             res = PI_NOT_PERMITTED;
          }
          break;
@@ -1610,17 +1732,17 @@ static int myDoCommand(uint32_t *p, unsigned bufSize, char *buf)
 
          for (i=0; i<j; i++)
          {
-            tmp = pulse[i].gpioOn & mask;
-            if (tmp != pulse[i].gpioOn)
+            tmp1 = pulse[i].gpioOn & mask;
+            if (tmp1 != pulse[i].gpioOn)
             {
-               pulse[i].gpioOn = tmp;
+               pulse[i].gpioOn = tmp1;
                masked = 1;
             }
 
-            tmp = pulse[i].gpioOff & mask;
-            if (tmp != pulse[i].gpioOff)
+            tmp1 = pulse[i].gpioOff & mask;
+            if (tmp1 != pulse[i].gpioOff)
             {
-               pulse[i].gpioOff = tmp;
+               pulse[i].gpioOff = tmp1;
                masked = 1;
             }
             DBG(DBG_SCRIPT, "on=%X off=%X delay=%d",
@@ -1637,8 +1759,11 @@ static int myDoCommand(uint32_t *p, unsigned bufSize, char *buf)
       case PI_CMD_WVAS:
          if (myPermit(p[1]))
          {
-            memcpy(&p[4], buf, 4);
-            res = gpioWaveAddSerial(p[1], p[2], p[4], p[3]-4, buf+4);
+            memcpy(&tmp1, buf, 4);   /* databits */
+            memcpy(&tmp2, buf+4, 4); /* stophalfbits */
+            memcpy(&tmp3, buf+8, 4); /* offset */
+            res = gpioWaveAddSerial
+               (p[1], p[2], tmp1, tmp2, tmp3, p[3]-12, buf+12);
          }
          else
          {
@@ -1945,43 +2070,31 @@ static void waveCbOPrint(int pos)
 
 /* ----------------------------------------------------------------------- */
 
-static void waveBitDelay(unsigned baud, unsigned * bitDelay)
+static void waveBitDelay
+   (unsigned baud, unsigned bits, unsigned stops, unsigned *bitDelay)
 {
-   unsigned fullBit, halfBit, s, e, d, m, i, err;
-
-   fullBit = 100000000 / baud;
-   halfBit =  50000000 / baud;
-
-   d = (fullBit/200)*200;
-
-   s = 0;
+   unsigned fullBit, last, diff, t, i;
 
-   e = d;
+   /* scaled 1000X */
 
-   bitDelay[0] = d/100;
+   fullBit = 1000000000 / baud;
+   last = 0;
 
-   err = d / 3;
-
-   for (i=0; i<8; i++)
+   for (i=0; i<=bits; i++)
    {
-      s = e;
-
-      m = halfBit + (i+1)*fullBit;
-
-      e = s + d;
-
-      if ((e-m) < err) e+=200;
-
-      bitDelay[i+1] = (e-s)/100;
+      t = (((i+1)*fullBit)+500)/1000;
+      diff = t - last;
+      last = t;
+      bitDelay[i] = diff;
    }
 
-   s = e;
-
-   e = ((1000000000 / baud)+100)/200*200;
-
-   bitDelay[9] = (e-s)/100;
+   t = (((bits+1)*fullBit) + ((stops*fullBit)/2) + 500)/1000;
+   diff = t - last;
+   bitDelay[i] = diff;
 }
 
+/* ----------------------------------------------------------------------- */
+
 static int errCBsOOL(int cb, int botOOL, int topOOL)
 {
    if (cb >= waveOutTopCB) return PI_TOO_MANY_CBS;
@@ -3102,8 +3215,15 @@ void spiGoA(
 
    channel = PI_SPI_FLAGS_GET_CHANNEL(flags);
    mode   =  PI_SPI_FLAGS_GET_MODE   (flags);
+
    bitlen =  PI_SPI_FLAGS_GET_BITLEN (flags);
    if (!bitlen) bitlen = 8;
+
+   /* correct count for word size */
+
+   if (bitlen >  8) count /= 2;
+   if (bitlen > 16) count /= 2;
+
    txmsbf = !PI_SPI_FLAGS_GET_TX_LSB (flags);
    rxmsbf = !PI_SPI_FLAGS_GET_RX_LSB (flags);
 
@@ -3656,6 +3776,41 @@ 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;
+
+   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);
+
+      if ((div > 1) && (div < 4096))
+      {
+         if ((!valid) || (offby < best_offby))
+         {
+            valid = 1;
+            clkInf->div = div;
+            clkInf->frac = frac;
+            clkInf->clock = c;
+            best_offby = offby;
+         }
+      }
+   }
+   return valid;
+}
+
+/* ======================================================================= */
+
 static rawCbs_t * dmaCB2adr(int pos)
 {
    int page, slot;
@@ -5435,7 +5590,7 @@ static int initDMAcbs(void)
 
 static void initPWM(unsigned bits)
 {
-   DBG(DBG_STARTUP, "");
+   DBG(DBG_STARTUP, "bits=%d", bits);
 
    /* reset PWM */
 
@@ -5478,7 +5633,7 @@ static void initPWM(unsigned bits)
 
 static void initPCM(unsigned bits)
 {
-   DBG(DBG_STARTUP, "");
+   DBG(DBG_STARTUP, "bits=%d", bits);
 
    /* disable PCM so we can modify the regs */
 
@@ -5528,14 +5683,43 @@ static void initPCM(unsigned bits)
 
 /* ----------------------------------------------------------------------- */
 
+static void initHWClk
+   (int clkCtl, int clkDiv, int clkSrc, int divI, int divF, int MASH)
+{
+   DBG(DBG_INTERNAL, "ctl=%d div=%d src=%d /I=%d /f=%d M=%d",
+      clkCtl, clkDiv, clkSrc, divI, divF, MASH);
+
+   /* kill the clock if busy, anything else isn't reliable */
+
+   if (clkReg[clkCtl] & CLK_CTL_BUSY)
+   {
+      do
+      {
+         clkReg[clkCtl] = CLK_PASSWD | CLK_CTL_KILL;
+      }
+      while (clkReg[clkCtl] & CLK_CTL_BUSY);
+   }
+
+   clkReg[clkDiv] = (CLK_PASSWD | CLK_DIV_DIVI(divI) | CLK_DIV_DIVF(divF));
+
+   usleep(10);
+
+   clkReg[clkCtl] = (CLK_PASSWD | CLK_CTL_MASH(MASH) | CLK_CTL_SRC(clkSrc));
+
+   usleep(10);
+
+   clkReg[clkCtl] |= (CLK_PASSWD | CLK_CTL_ENAB);
+}
+
 static void initClock(int mainClock)
 {
+   const unsigned BITS=10;
    int clockPWM;
    unsigned clkCtl, clkDiv, clkSrc, clkDivI, clkDivF, clkMash, clkBits;
-   char * per, * src;
+   char *per;
    unsigned micros;
 
-   DBG(DBG_STARTUP, "");
+   DBG(DBG_STARTUP, "mainClock=%d", mainClock);
 
    if (mainClock) micros = gpioCfg.clockMicros;
    else           micros = PI_WF_MICROS;
@@ -5555,48 +5739,19 @@ static void initClock(int mainClock)
       per = "PCM";
    }
 
-   if (gpioCfg.clockSource == PI_CLOCK_PLLD)
-   {
-      clkSrc  = CLK_CTL_SRC_PLLD;
-      clkDivI = 50 * micros;
-      clkDivF = 0;
-      clkMash = 0;
-      clkBits = 10;
-      src = "PLLD";
-   }
-   else
-   {
-      clkSrc  = CLK_CTL_SRC_OSC;
-      clkDivI = clkCfg[micros].divi;
-      clkDivF = clkCfg[micros].divf;
-      clkMash = clkCfg[micros].mash;
-      clkBits = clkCfg[micros].bits;
-      src = "OSC";
-   }
-
-   DBG(DBG_STARTUP, "%s %s divi=%d divf=%d mash=%d bits=%d",
-      per, src, clkDivI, clkDivF, clkMash, clkBits);
+   clkSrc  = CLK_CTL_SRC_PLLD;
+   clkDivI = 50 * micros; /* 10      MHz - 1      MHz */
+   clkBits = BITS;        /* 10/BITS MHz - 1/BITS MHz */
+   clkDivF = 0;
+   clkMash = 0;
 
-   clkReg[clkCtl] = CLK_PASSWD | CLK_CTL_KILL;
+   DBG(DBG_STARTUP, "%s PLLD divi=%d divf=%d mash=%d bits=%d",
+      per, clkDivI, clkDivF, clkMash, clkBits);
 
-   myGpioDelay(10);
+   initHWClk(clkCtl, clkDiv, clkSrc, clkDivI, clkDivF, clkMash);
 
-   clkReg[clkDiv] =
-      (CLK_PASSWD | CLK_DIV_DIVI(clkDivI) | CLK_DIV_DIVF(clkDivF));
-
-   myGpioDelay(10);
-
-   clkReg[clkCtl] =
-      (CLK_PASSWD | CLK_CTL_MASH(clkMash) | CLK_CTL_SRC(clkSrc));
-
-   myGpioDelay(10);
-
-   clkReg[clkCtl] |= (CLK_PASSWD | CLK_CTL_ENAB);
-
-   myGpioDelay(10);
-
-   if (clockPWM) initPWM(clkBits);
-   else          initPCM(clkBits);
+   if (clockPWM) initPWM(BITS);
+   else          initPCM(BITS);
 
    myGpioDelay(2000);
 }
@@ -5615,7 +5770,7 @@ static void initDMAgo(volatile uint32_t  *dmaAddr, uint32_t cbAddr)
 
    /* clear READ/FIFO/READ_LAST_NOT_SET error bits */
 
-   dmaAddr[DMA_DEBUG] = DMA_DEBUG_READ_ERR            |          
+   dmaAddr[DMA_DEBUG] = DMA_DEBUG_READ_ERR            |
                         DMA_DEBUG_FIFO_ERR            |
                         DMA_DEBUG_RD_LST_NOT_SET_ERR;
 
@@ -5676,7 +5831,10 @@ static void initClearGlobals(void)
       wfRx[i].mode         = PI_WFRX_NONE;
 
       gpioAlert[i].func    = NULL;
+   }
 
+   for (i=0; i<=PI_MAX_GPIO; i++)
+   {
       gpioInfo [i].is      = GPIO_UNDEFINED;
       gpioInfo [i].width   = 0;
       gpioInfo [i].range   = PI_DEFAULT_DUTYCYCLE_RANGE;
@@ -6074,6 +6232,7 @@ int gpioInitialise(void)
    unsigned port;
    struct sched_param param;
 
+   waveClockInited = 0;
 
    clock_gettime(CLOCK_REALTIME, &libStarted);
 
@@ -6223,11 +6382,62 @@ void gpioTerminate(void)
    fflush(NULL);
 }
 
+static void switchFunctionOff(unsigned gpio)
+{
+   unsigned clock, pwm;
+   int cctl[] = {CLK_GP0_CTL, CLK_GP1_CTL, CLK_GP2_CTL};
+
+   if (gpio <= PI_MAX_GPIO)
+   {
+      switch (gpioInfo[gpio].is)
+      {
+         case GPIO_SERVO:
+            /* switch servo off */
+            myGpioSetServo(gpio, gpioInfo[gpio].width, 0);
+            gpioInfo[gpio].width = 0;
+            break;
+
+         case GPIO_PWM:
+            /* switch pwm off */
+            myGpioSetPwm(gpio, gpioInfo[gpio].width, 0);
+            gpioInfo[gpio].width = 0;
+            break;
+
+         case GPIO_HW_CLK:
+            /* switch hardware clock off */
+            clock = (clkDef[gpio] >> 4) & 3;
+            clkReg[cctl[clock]] = CLK_PASSWD | CLK_CTL_KILL;
+            break;
+
+         case GPIO_HW_PWM:
+            /* switch hardware PWM off */
+            pwm = (PWMDef[gpio] >> 4) & 3;
+            if (pwm == 0) pwmReg[PWM_CTL] &= (~PWM_CTL_PWEN1);
+            else          pwmReg[PWM_CTL] &= (~PWM_CTL_PWEN2);
+            break;
+      }
+   }
+}
+
+static void stopHardwarePWM(void)
+{
+   int i;
+
+   for (i=0; i<= PI_MAX_GPIO; i++)
+   {
+      if (gpioInfo[i].is == GPIO_HW_PWM)
+      {
+         switchFunctionOff(i);
+         gpioInfo[i].is = GPIO_UNDEFINED;
+      }
+   }
+}
+
 /* ----------------------------------------------------------------------- */
 
 int gpioSetMode(unsigned gpio, unsigned mode)
 {
-   int reg, shift;
+   int reg, shift, old_mode;
 
    DBG(DBG_USER, "gpio=%d mode=%d", gpio, mode);
 
@@ -6242,30 +6452,18 @@ int gpioSetMode(unsigned gpio, unsigned mode)
    reg   =  gpio/10;
    shift = (gpio%10) * 3;
 
-   if (gpio <= PI_MAX_USER_GPIO)
+   old_mode = (gpioReg[reg] >> shift) & 7;
+
+   if (mode != old_mode)
    {
-      if (mode != PI_OUTPUT)
+      if (gpio <= PI_MAX_USER_GPIO)
       {
-         switch (gpioInfo[gpio].is)
-         {
-            case GPIO_SERVO:
-               /* switch servo off */
-               myGpioSetServo(gpio,
-                  gpioInfo[gpio].width/gpioCfg.clockMicros, 0);
-               break;
-
-            case GPIO_PWM:
-               /* switch pwm off */
-               myGpioSetPwm(gpio, gpioInfo[gpio].width, 0);
-               break;
-         }
-
+         switchFunctionOff(gpio);
          gpioInfo[gpio].is = GPIO_UNDEFINED;
       }
+      gpioReg[reg] = (gpioReg[reg] & ~(7<<shift)) | (mode<<shift);
    }
 
-   gpioReg[reg] = (gpioReg[reg] & ~(7<<shift)) | (mode<<shift);
-
    return 0;
 }
 
@@ -6286,7 +6484,7 @@ int gpioGetMode(unsigned gpio)
    reg   =  gpio/10;
    shift = (gpio%10) * 3;
 
-   return (*(gpioReg + reg) >> shift) & 7;
+   return (gpioReg[reg] >> shift) & 7;
 }
 
 
@@ -6350,30 +6548,22 @@ int gpioWrite(unsigned gpio, unsigned level)
    if (level > PI_ON)
       SOFT_ERROR(PI_BAD_LEVEL, "gpio %d, bad level (%d)", gpio, level);
 
-   if (gpio <= PI_MAX_USER_GPIO)
+   if (gpio <= PI_MAX_GPIO)
    {
       if (gpioInfo[gpio].is != GPIO_WRITE)
       {
          if (gpioInfo[gpio].is == GPIO_UNDEFINED)
          {
+            /* stop a glitch between setting mode then level */
             if (level == PI_OFF) *(gpioReg + GPCLR0 + BANK) = BIT;
             else                 *(gpioReg + GPSET0 + BANK) = BIT;
-            gpioSetMode(gpio, PI_OUTPUT);
-         }
-         else if (gpioInfo[gpio].is == GPIO_PWM)
-         {
-            /* switch pwm off */
-            myGpioSetPwm(gpio, gpioInfo[gpio].width, 0);
          }
-         else if (gpioInfo[gpio].is == GPIO_SERVO)
+         else
          {
-            /* switch servo off */
-            myGpioSetServo(
-               gpio, gpioInfo[gpio].width/gpioCfg.clockMicros, 0);
+            switchFunctionOff(gpio);
          }
-
-         gpioInfo[gpio].is=GPIO_WRITE;
-         gpioInfo[gpio].width=0;
+         gpioSetMode(gpio, PI_OUTPUT);
+         gpioInfo[gpio].is = GPIO_WRITE;
       }
    }
 
@@ -6402,14 +6592,12 @@ int gpioPWM(unsigned gpio, unsigned val)
    {
       if (gpioInfo[gpio].is == GPIO_UNDEFINED)
       {
-         gpioSetMode(gpio, PI_OUTPUT);
       }
-      else if (gpioInfo[gpio].is == GPIO_SERVO)
+      else
       {
-         /* switch servo off */
-         myGpioSetServo(gpio, gpioInfo[gpio].width, 0);
-         gpioInfo[gpio].width = 0;
+         switchFunctionOff(gpio);
       }
+      gpioSetMode(gpio, PI_OUTPUT);
       gpioInfo[gpio].is = GPIO_PWM;
    }
 
@@ -6488,7 +6676,7 @@ int gpioGetPWMrange(unsigned gpio)
    if (gpio > PI_MAX_USER_GPIO)
       SOFT_ERROR(PI_BAD_USER_GPIO, "bad gpio (%d)", gpio);
 
-   return (gpioInfo[gpio].range);
+   return gpioInfo[gpio].range;
 }
 
 
@@ -6570,7 +6758,7 @@ int gpioGetPWMfrequency(unsigned gpio)
    if (gpio > PI_MAX_USER_GPIO)
       SOFT_ERROR(PI_BAD_USER_GPIO, "bad gpio (%d)", gpio);
 
-   return (pwmFreq[gpioInfo[gpio].freqIdx]);
+   return pwmFreq[gpioInfo[gpio].freqIdx];
 }
 
 
@@ -6597,14 +6785,12 @@ int gpioServo(unsigned gpio, unsigned val)
    {
       if (gpioInfo[gpio].is == GPIO_UNDEFINED)
       {
-         gpioSetMode(gpio, PI_OUTPUT);
       }
-      else if (gpioInfo[gpio].is == GPIO_PWM)
+      else
       {
-         /* switch pwm off */
-         myGpioSetPwm(gpio, gpioInfo[gpio].width, 0);
-         gpioInfo[gpio].width=0;
+         switchFunctionOff(gpio);
       }
+      gpioSetMode(gpio, PI_OUTPUT);
       gpioInfo[gpio].is = GPIO_SERVO;
    }
 
@@ -6714,35 +6900,55 @@ int gpioWaveAddGeneric(unsigned numPulses, gpioPulse_t *pulses)
 int gpioWaveAddSerial
    (unsigned gpio,
     unsigned bbBaud,
+    unsigned bbBits,
+    unsigned bbStops,
     unsigned offset,
-    unsigned numChar,
-    char     *str)
+    unsigned numBytes,
+    char     *bstr)
 {
    int i, b, p, lev, c, v;
 
-   unsigned bitDelay[10];
+   uint16_t *wstr = (uint16_t *)bstr;
+   uint32_t *lstr = (uint32_t *)bstr;
+
+   unsigned bitDelay[32];
 
-   DBG(DBG_USER, "gpio=%d bbBaud=%d offset=%d numChar=%d str=[%s]",
-      gpio, bbBaud, offset, numChar, myBuf2Str(numChar, (char *)str));
+   DBG(DBG_USER,
+      "gpio=%d baud=%d bits=%d stops=%d offset=%d numBytes=%d str=[%s]",
+      gpio, bbBaud, bbBits, bbStops, offset,
+      numBytes, myBuf2Str(numBytes, (char *)bstr));
 
    CHECK_INITED;
 
    if (gpio > PI_MAX_USER_GPIO)
       SOFT_ERROR(PI_BAD_USER_GPIO, "bad gpio (%d)", gpio);
 
-   if ((bbBaud < PI_WAVE_MIN_BAUD) || (bbBaud > PI_WAVE_MAX_BAUD))
-      SOFT_ERROR(PI_BAD_WAVE_BAUD,
-         "gpio %d, bad baud rate (%d)", gpio, bbBaud);
+   if ((bbBaud < PI_BB_MIN_BAUD) || (bbBaud > PI_BB_TX_MAX_BAUD))
+      SOFT_ERROR(PI_BAD_WAVE_BAUD, "bad baud rate (%d)", bbBaud);
 
-   if (numChar > PI_WAVE_MAX_CHARS)
-      SOFT_ERROR(PI_TOO_MANY_CHARS, "too many chars (%d)", numChar);
+   if ((bbBits < PI_MIN_WAVE_DATABITS) || (bbBits > PI_MAX_WAVE_DATABITS))
+      SOFT_ERROR(PI_BAD_DATABITS, "bad number of databits (%d)", bbBits);
+
+   if ((bbStops < PI_MIN_WAVE_HALFSTOPBITS) ||
+       (bbStops > PI_MAX_WAVE_HALFSTOPBITS))
+      SOFT_ERROR(PI_BAD_STOPBITS,
+         "bad number of (half) stop bits (%d)", bbStops);
+
+   if (gpio > PI_MAX_USER_GPIO)
+      SOFT_ERROR(PI_BAD_USER_GPIO, "bad gpio (%d)", gpio);
+
+   if (numBytes > PI_WAVE_MAX_CHARS)
+      SOFT_ERROR(PI_TOO_MANY_CHARS, "too many chars (%d)", numBytes);
 
    if (offset > PI_WAVE_MAX_MICROS)
       SOFT_ERROR(PI_BAD_SER_OFFSET, "offset too large (%d)", offset);
 
-   if (!numChar) return 0;
+   if (bbBits > 8) numBytes /= 2;
+   if (bbBits > 16) numBytes /= 2;
+
+   if (!numBytes) return 0;
 
-   waveBitDelay(bbBaud, bitDelay);
+   waveBitDelay(bbBaud, bbBits, bbStops, bitDelay);
 
    p = 0;
 
@@ -6753,7 +6959,7 @@ int gpioWaveAddSerial
    if (offset > bitDelay[0]) wf[2][p].usDelay = offset;
    else                      wf[2][p].usDelay = bitDelay[0];
 
-   for (i=0; i<numChar; i++)
+   for (i=0; i<numBytes; i++)
    {
       p++;
    
@@ -6766,9 +6972,11 @@ int gpioWaveAddSerial
 
       lev = 0;
 
-      c = str[i];
+      if      (bbBits <  9) c = bstr[i];
+      else if (bbBits < 17) c = wstr[i];
+      else                  c = lstr[i];
 
-      for (b=0; b<8; b++)
+      for (b=0; b<bbBits; b++)
       {
          if (c & (1<<b)) v=1; else v=0;
 
@@ -6798,14 +7006,14 @@ int gpioWaveAddSerial
 
       /* stop bit */
 
-      if (lev) wf[2][p].usDelay += bitDelay[9];
+      if (lev) wf[2][p].usDelay += bitDelay[bbBits+1];
       else
       {
          p++;
 
          wf[2][p].gpioOn  = (1<<gpio);
          wf[2][p].gpioOff = 0;
-         wf[2][p].usDelay = bitDelay[9];
+         wf[2][p].usDelay = bitDelay[bbBits+1];
          wf[2][p].flags   = 0;
       }
    }
@@ -7014,8 +7222,6 @@ int gpioWaveTxStart(unsigned wave_mode)
 {
    /* This function is deprecated and will be removed. */
 
-   static int secondaryClockInited = 0;
-
    int cb, i;
 
    DBG(DBG_USER, "wave_mode=%d", wave_mode);
@@ -7027,10 +7233,11 @@ int gpioWaveTxStart(unsigned wave_mode)
 
    if (wfc[wfcur] == 0) return 0;
    
-   if (!secondaryClockInited)
+   if (!waveClockInited)
    {
+      stopHardwarePWM();
       initClock(0); /* initialise secondary clock */
-      secondaryClockInited = 1;
+      waveClockInited = 1;
    }
 
    dmaOut[DMA_CS] = DMA_CHANNEL_RESET;
@@ -7064,8 +7271,6 @@ int gpioWaveTxSend(unsigned wave_id, unsigned wave_mode)
 {
    rawCbs_t *p=NULL;
 
-   static int secondaryClockInited = 0;
-
    DBG(DBG_USER, "wave_id=%d wave_mode=%d", wave_id, wave_mode);
 
    CHECK_INITED;
@@ -7076,10 +7281,11 @@ int gpioWaveTxSend(unsigned wave_id, unsigned wave_mode)
    if (wave_mode > PI_WAVE_MODE_REPEAT)
       SOFT_ERROR(PI_BAD_WAVE_MODE, "bad wave mode (%d)", wave_mode);
 
-   if (!secondaryClockInited)
+   if (!waveClockInited)
    {
+      stopHardwarePWM();
       initClock(0); /* initialise secondary clock */
-      secondaryClockInited = 1;
+      waveClockInited = 1;
    }
 
    p = rawWaveCBAdr(waveInfo[wave_id].topCB);
@@ -7240,7 +7446,7 @@ int gpioSerialReadOpen(unsigned gpio, unsigned bbBaud)
    if (gpio > PI_MAX_USER_GPIO)
       SOFT_ERROR(PI_BAD_USER_GPIO, "bad gpio (%d)", gpio);
 
-   if ((bbBaud < PI_WAVE_MIN_BAUD) || (bbBaud > PI_WAVE_MAX_BAUD))
+   if ((bbBaud < PI_BB_MIN_BAUD) || (bbBaud > PI_BB_RX_MAX_BAUD))
       SOFT_ERROR(PI_BAD_WAVE_BAUD,
          "gpio %d, bad baud rate (%d)", gpio, bbBaud);
 
@@ -8175,6 +8381,193 @@ int gpioWrite_Bits_32_53_Set(uint32_t bits)
    return 0;
 }
 
+/* ----------------------------------------------------------------------- */
+
+int gpioHardwareClock(unsigned gpio, unsigned frequency)
+{
+   int cctl[] = {CLK_GP0_CTL, CLK_GP1_CTL, CLK_GP2_CTL};
+   int cdiv[] = {CLK_GP0_DIV, CLK_GP1_DIV, CLK_GP2_DIV};
+   int csrc[CLK_SRCS] = {CLK_CTL_SRC_OSC, CLK_CTL_SRC_PLLD};
+   uint32_t cfreq[CLK_SRCS]={CLK_OSC_FREQ, CLK_PLLD_FREQ};
+   unsigned clock, mode, mash;
+   int password = 0;
+   clkInf_t clkInf={0,0,0};
+
+   DBG(DBG_USER, "gpio=%d frequency=%d", gpio, frequency);
+
+   CHECK_INITED;
+
+   if ((gpio >> 24) == 0x5A) password = 1;
+
+   gpio &= 0xFFFFFF;
+
+   if (gpio > PI_MAX_GPIO)
+      SOFT_ERROR(PI_BAD_GPIO, "bad gpio (%d)", gpio);
+
+   if (!clkDef[gpio])
+      SOFT_ERROR(PI_NOT_HCLK_GPIO, "bad gpio for clock (%d)", gpio);
+
+   if (((frequency < PI_HW_CLK_MIN_FREQ) ||
+        (frequency > PI_HW_CLK_MAX_FREQ)) &&
+        (frequency))
+      SOFT_ERROR(PI_BAD_HCLK_FREQ,
+         "bad hardware clock frequency (%d)", frequency);
+
+   clock = (clkDef[gpio] >> 4) & 3;
+
+   if ((clock == 1) && (!password))
+      SOFT_ERROR(PI_BAD_HCLK_PASS,
+         "Need password to use clock 1 (%d)", gpio);
+
+   mode  = clkDef[gpio] & 7;
+   mash = frequency < PI_MASH_MAX_FREQ ? 1 : 0;
+
+   if (frequency)
+   {
+      if (chooseBestClock(&clkInf, frequency, CLK_SRCS, cfreq))
+      {
+         initHWClk(cctl[clock], cdiv[clock],
+            csrc[clkInf.clock], clkInf.div, clkInf.frac, mash);
+
+         gpioSetMode(gpio, mode);
+
+         gpioInfo[gpio].is = GPIO_HW_CLK;
+      }
+      else
+      {
+         SOFT_ERROR(PI_BAD_HCLK_FREQ,
+            "bad hardware clock frequency (%d)", frequency);
+      }
+   }
+   else
+   {
+      /* frequency 0, stop clock */
+      clkReg[cctl[clock]] = CLK_PASSWD | CLK_CTL_KILL;
+
+      if (gpioInfo[gpio].is == GPIO_HW_CLK)
+         gpioInfo[gpio].is = GPIO_UNDEFINED;
+   }
+
+   return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+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};
+
+   DBG(DBG_USER, "gpio=%d  frequency=%d dutycycle=%d",
+      gpio, frequency, dutycycle);
+
+   CHECK_INITED;
+
+   if (gpio > PI_MAX_GPIO)
+      SOFT_ERROR(PI_BAD_GPIO, "bad gpio (%d)", gpio);
+
+   if (!PWMDef[gpio])
+      SOFT_ERROR(PI_NOT_HPWM_GPIO, "bad gpio for PWM (%d)", gpio);
+
+   if (dutycycle > PI_HW_PWM_RANGE)
+      SOFT_ERROR(PI_BAD_HPWM_DUTY, "bad PWM dutycycle (%d)", dutycycle);
+
+   if (((frequency < PI_HW_PWM_MIN_FREQ) ||
+        (frequency > PI_HW_PWM_MAX_FREQ)) &&
+        (frequency))
+      SOFT_ERROR(PI_BAD_HPWM_FREQ,
+         "bad hardware PWM frequency (%d)", frequency);
+
+   if (gpioCfg.clockPeriph == PI_CLOCK_PWM)
+      SOFT_ERROR(PI_HPWM_ILLEGAL, "illegal, PWM in use for main clock");
+
+   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))
+      {
+         /* Abort any waveform transmission in progress */
+
+         if (gpioWaveTxBusy()) gpioWaveTxStop();
+
+         waveClockInited = 0;
+
+         /* preserve channel enable only and mark space mode */
+
+         old_PWM_CTL = pwmReg[PWM_CTL] &
+            (PWM_CTL_PWEN1 | PWM_CTL_MSEN1 | PWM_CTL_PWEN2 | PWM_CTL_MSEN2);
+
+         pwmReg[PWM_CTL] = 0;
+
+         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] = (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);
+         }
+
+         if (gpioInfo[gpio].is != GPIO_HW_PWM)
+         {
+            if (gpioInfo[gpio].is == GPIO_UNDEFINED)
+            {
+            }
+            else
+            {
+               switchFunctionOff(gpio);
+            }
+            gpioSetMode(gpio, mode);
+            gpioInfo[gpio].is = GPIO_HW_PWM;
+         }
+      }
+      else
+      {
+         SOFT_ERROR(PI_BAD_HPWM_FREQ,
+            "bad hardware PWM frequency (%d)", frequency/PI_HW_PWM_RANGE);
+      }
+   }
+   else
+   {
+      /* frequency 0, stop PWM */
+
+      if (gpioInfo[gpio].is == GPIO_HW_PWM)
+      {
+         if (pwm == 0) pwmReg[PWM_CTL] &= (~PWM_CTL_PWEN1);
+         else          pwmReg[PWM_CTL] &= (~PWM_CTL_PWEN2);
+
+         gpioInfo[gpio].is = GPIO_UNDEFINED;
+      }
+   }
+
+   return 0;
+}
+
 
 /* ----------------------------------------------------------------------- */
 
@@ -8347,8 +8740,7 @@ int gpioCfgBufferSize(unsigned millis)
 
 int gpioCfgClock(unsigned micros, unsigned peripheral, unsigned source)
 {
-   DBG(DBG_USER, "micros=%d peripheral=%d source=%d",
-      micros, peripheral, source);
+   DBG(DBG_USER, "micros=%d peripheral=%d", micros, peripheral);
 
    CHECK_NOT_INITED;
 
@@ -8361,12 +8753,8 @@ int gpioCfgClock(unsigned micros, unsigned peripheral, unsigned source)
    if (peripheral > PI_CLOCK_PCM)
       SOFT_ERROR(PI_BAD_CLK_PERIPH, "bad peripheral (%d)", peripheral);
 
-   if (source > PI_CLOCK_PLLD)
-      SOFT_ERROR(PI_BAD_CLK_SOURCE, "bad clock (%d)", source);
-
    gpioCfg.clockMicros = micros;
    gpioCfg.clockPeriph = peripheral;
-   gpioCfg.clockSource = source;
 
    return 0;
 }
index cab451378158a549f8ead614c29b7bea99ae15a5..6bc2e2643ab42f2898efd2c475fc608a911d8661 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 23
+#define PIGPIO_VERSION 24
 
 /*TEXT
 
@@ -177,6 +177,9 @@ gpioSerialReadOpen         Opens a gpio for bit bang serial reads
 gpioSerialRead             Reads bit bang serial data from a gpio
 gpioSerialReadClose        Closes a gpio for bit bang serial reads
 
+gpioHardwareClock          Start hardware clock on supported gpios
+gpioHardwarePWM            Start hardware PWM on supported gpios
+
 SCRIPTS
 
 gpioStoreScript            Store a script
@@ -289,6 +292,8 @@ EXPERT
 
 rawWaveAddSPI              Not intended for general use
 rawWaveAddGeneric          Not intended for general use
+rawWaveCB                  Not intended for general use
+rawWaveCBAdr               Not intended for general use
 rawWaveGetOut              Not intended for general use
 rawWaveSetOut              Not intended for general use
 rawWaveGetIn               Not intended for general use
@@ -388,29 +393,29 @@ unsigned long pad[2];
 } rawCbs_t;
 
 typedef void (*gpioAlertFunc_t)    (int      gpio,
-                                 int      level,
-                                 uint32_t tick);
+                                    int      level,
+                                    uint32_t tick);
 
 typedef void (*gpioAlertFuncEx_t)  (int      gpio,
-                                 int      level,
-                                 uint32_t tick,
-                                 void *userdata);
+                                    int      level,
+                                    uint32_t tick,
+                                    void    *userdata);
 
 typedef void (*gpioTimerFunc_t)    (void);
 
 typedef void (*gpioTimerFuncEx_t)  (void *userdata);
 
-typedef void (*gpioSignalFunc_t)   (int    signum);
+typedef void (*gpioSignalFunc_t)   (int signum);
 
 typedef void (*gpioSignalFuncEx_t) (int    signum,
-                                 void *userdata);
+                                    void  *userdata);
 
 typedef void (*gpioGetSamplesFunc_t)   (const gpioSample_t *samples,
-                                     int                  numSamples);
+                                        int                 numSamples);
 
 typedef void (*gpioGetSamplesFuncEx_t) (const gpioSample_t *samples,
-                                     int                  numSamples,
-                                     void *userdata);
+                                        int                 numSamples,
+                                        void               *userdata);
 
 typedef void *(gpioThreadFunc_t) (void *);
 
@@ -471,6 +476,17 @@ typedef void *(gpioThreadFunc_t) (void *);
 #define PI_MIN_SERVO_PULSEWIDTH 500
 #define PI_MAX_SERVO_PULSEWIDTH 2500
 
+/* hardware PWM */
+
+#define PI_HW_PWM_MIN_FREQ 5
+#define PI_HW_PWM_MAX_FREQ 250000
+#define PI_HW_PWM_RANGE 1000
+
+/* hardware clock */
+
+#define PI_HW_CLK_MIN_FREQ 4689
+#define PI_HW_CLK_MAX_FREQ 250000000
+
 #define PI_NOTIFY_SLOTS  32
 
 #define PI_NTFY_FLAGS_WDOG     (1 <<5)
@@ -478,10 +494,17 @@ typedef void *(gpioThreadFunc_t) (void *);
 
 #define PI_WAVE_BLOCKS     4
 #define PI_WAVE_MAX_PULSES (PI_WAVE_BLOCKS * 3000)
-#define PI_WAVE_MAX_CHARS  (PI_WAVE_BLOCKS *  256)
+#define PI_WAVE_MAX_CHARS  (PI_WAVE_BLOCKS *  300)
 
-#define PI_WAVE_MIN_BAUD      100
-#define PI_WAVE_MAX_BAUD      250000
+#define PI_BB_MIN_BAUD         50
+#define PI_BB_RX_MAX_BAUD  250000
+#define PI_BB_TX_MAX_BAUD 1000000
+
+#define PI_MIN_WAVE_DATABITS 1
+#define PI_MAX_WAVE_DATABITS 32
+
+#define PI_MIN_WAVE_HALFSTOPBITS 2
+#define PI_MAX_WAVE_HALFSTOPBITS 8
 
 #define PI_WAVE_MAX_MICROS (30 * 60 * 1000000) /* half an hour */
 
@@ -577,11 +600,6 @@ typedef void *(gpioThreadFunc_t) (void *);
 #define PI_CLOCK_PWM 0
 #define PI_CLOCK_PCM 1
 
-/* cfgSource: 0-1 */
-
-#define PI_CLOCK_OSC  0
-#define PI_CLOCK_PLLD 1
-
 /* DMA channel: 0-14 */
 
 #define PI_MIN_DMA_CHANNEL 0
@@ -1325,32 +1343,47 @@ D*/
 int gpioWaveAddSerial
    (unsigned user_gpio,
     unsigned bbBaud,
+    unsigned bbBits,
+    unsigned bbStop,
     unsigned offset,
-    unsigned numChar,
+    unsigned numBytes,
     char     *str);
 /*D
 This function adds a waveform representing serial data to the
-existing waveform (if any).  The serial data starts offset microseconds
-from the start of the waveform.
+existing waveform (if any).  The serial data starts offset
+microseconds from the start of the waveform.
 
 . .
 user_gpio: 0-31
-   bbBaud: 100-250000
+   bbBaud: 100-1000000
+   bbBits: 1-32
+   bbStop: 2-8
    offset: 0-
 numChar: 1-
numBytes: 1-
       str: an array of chars (which may contain nulls)
 . .
 
 Returns the new total number of pulses in the current waveform if OK,
-otherwise PI_BAD_USER_GPIO, PI_BAD_WAVE_BAUD, PI_TOO_MANY_CHARS,
-PI_BAD_SER_OFFSET, or PI_TOO_MANY_PULSES.
+otherwise PI_BAD_USER_GPIO, PI_BAD_WAVE_BAUD, PI_BAD_DATABITS,
+PI_BAD_STOPBITS, PI_TOO_MANY_CHARS, PI_BAD_SER_OFFSET,
+or PI_TOO_MANY_PULSES.
 
-The serial data is formatted as one start bit, eight data bits, and one
-stop bit.
+NOTES:
+
+The serial data is formatted as one start bit, bbBits data bits, and
+bbStop/2 stop bits.
 
 It is legal to add serial data streams with different baud rates to
 the same waveform.
 
+numBytes is the number of bytes of data in str.
+
+The bytes required for each character depend upon bbBits.
+
+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.
+
 ...
 #define MSG_LEN 8
 
@@ -1360,12 +1393,12 @@ char data[MSG_LEN];
 
 str = "Hello world!";
 
-gpioWaveAddSerial(4, 9600, 0, strlen(str), str);
+gpioWaveAddSerial(4, 9600, 8, 2, 0, strlen(str), str);
 
 for (i=0; i<MSG_LEN; i++) data[i] = i;
 
 // Data added is offset 1 second from the waveform start.
-gpioWaveAddSerial(4, 9600, 1000000, MSG_LEN, data);
+gpioWaveAddSerial(4, 9600, 8, 2, 1000000, MSG_LEN, data);
 ...
 D*/
 
@@ -1446,6 +1479,8 @@ int gpioWaveTxStart(unsigned wave_mode); /* DEPRECATED */
 This function creates and then transmits a waveform.  The mode
 determines whether the waveform is sent once or cycles endlessly.
 
+NOTE: Any hardware PWM started by [*gpioHardwarePWM*] will be cancelled.
+
 . .
 wave_mode: 0 (PI_WAVE_MODE_ONE_SHOT), 1 (PI_WAVE_MODE_REPEAT)
 . .
@@ -1464,6 +1499,8 @@ int gpioWaveTxSend(unsigned wave_id, unsigned wave_mode);
 This function transmits the waveform with id wave_id.  The mode
 determines whether the waveform is sent once or cycles endlessly.
 
+NOTE: Any hardware PWM started by [*gpioHardwarePWM*] will be cancelled.
+
 . .
   wave_id: >=0, as returned by [*gpioWaveCreate*]
 wave_mode: 0 (PI_WAVE_MODE_ONE_SHOT), 1 (PI_WAVE_MODE_REPEAT)
@@ -2237,8 +2274,8 @@ bits: the gpios of interest
 
 Returns 0 if OK.
 
-The function is passed a pointer to the samples and the number
-of samples.
+The function is passed a pointer to the samples (an array of
+[*gpioSample_t*]),  and the number of samples.
 
 Only one function can be registered.
 
@@ -2268,8 +2305,8 @@ userdata: a pointer to arbitrary user data
 
 Returns 0 if OK.
 
-The function is passed a pointer to the samples, the number
-of samples, and the userdata pointer.
+The function is passed a pointer to the samples (an array of
+[*gpioSample_t*]), the number of samples, and the userdata pointer.
 
 Only one of [*gpioGetSamplesFunc*] or [*gpioGetSamplesFuncEx*] can be
 registered.
@@ -2610,6 +2647,84 @@ gpioWrite_Bits_32_53_Set((1<<(32-32)) | (1<<(40-32)) | (1<<(53-32)));
 ...
 D*/
 
+/*F*/
+int gpioHardwareClock(unsigned gpio, unsigned clkfreq);
+/*D
+Starts a hardware clock on a gpio at the specified frequency.
+
+. .
+   gpio: see description
+clkfreq: 0 (off) or 4689-250M
+. .
+
+Returns 0 if OK, otherwise PI_BAD_GPIO, PI_NOT_HCLK_GPIO,
+PI_BAD_HCLK_FREQ,or PI_BAD_HCLK_PASS.
+
+The same clock is available on multiple gpios.  The latest
+frequency setting will be used by all gpios which share a clock.
+
+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
+21  clock 1  All models but Rev.2 B (reserved for system use)
+
+32  clock 0  Compute module only
+34  clock 0  Compute module only
+42  clock 1  Compute module only (reserved for system use)
+43  clock 2  Compute module only
+44  clock 1  Compute module only (reserved for system use)
+. .
+
+Access to clock 1 is protected by a password as its use will likely
+crash the Pi.  The password is given by or'ing 0x5A000000 with the
+gpio number.
+D*/
+
+/*F*/
+int gpioHardwarePWM(unsigned gpio, unsigned PWMfreq, unsigned PWMduty);
+/*D
+Starts hardware PWM on a gpio at the specified frequency and dutycycle.
+
+NOTE: Any waveform started by [*gpioWaveTxSend*] or [*gpioWaveTxStart*]
+will be cancelled.
+
+This function is only valid if the pigpio main clock is PCM.  The
+main clock defaults to PCM but may be overridden by a call to
+[*gpioCfgClock*].
+
+. .
+   gpio: see description
+PWMfreq: 0 (off) or 5-250K
+PWMduty: 0 (off) to 1000 (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 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
+18  PWM channel 0  All models
+19  PWM channel 1  A+/B+ and compute module only
+
+40  PWM channel 0  Compute module only
+41  PWM channel 1  Compute module only
+45  PWM channel 1  Compute module only
+52  PWM channel 0  Compute module only
+53  PWM channel 1  Compute module only
+. .
+D*/
 
 /*F*/
 int gpioTime(unsigned timetype, int *seconds, int *micros);
@@ -2802,19 +2917,17 @@ int gpioCfgClock(
    unsigned cfgMicros, unsigned cfgPeripheral, unsigned cfgSource);
 /*D
 Configures pigpio to use a particualar sample rate timed by a specified
-peripheral and clock source.
+peripheral.
 
 . .
     cfgMicros: 1, 2, 4, 5, 8, 10
 cfgPeripheral: 0 (PWM), 1 (PCM)
-    cfgSource: 0 (OSC), 1 (PLLD)
+    cfgSource: deprecated, value is ignored
 . .
 
-The timings are provided by the specified peripheral (PWM or PCM)
-using the frequency source (OSC or PLLD).
+The timings are provided by the specified peripheral (PWM or PCM).
 
-The default setting is 5 microseconds using the PCM peripheral
-with the PLLD source.
+The default setting is 5 microseconds using the PCM peripheral.
 
 The approximate CPU percentage used for each sample rate is:
 
@@ -3153,8 +3266,29 @@ The baud rate used for the transmission and reception of bit banged
 serial data.
 
 . .
-PI_WAVE_MIN_BAUD 100
-PI_WAVE_MAX_BAUD 250000
+PI_BB_MIN_BAUD 50
+PI_BB_RX_MAX_BAUD 250000
+PI_BB_TX_MAX_BAUD 1000000
+. .
+
+bbBits::1-32
+
+The number of data bits to be used when adding serial data to a
+waveform.
+
+. .
+#define PI_MIN_WAVE_DATABITS 1
+#define PI_MAX_WAVE_DATABITS 32
+. .
+
+bbStop::2-8
+
+The number of (half) stop bits to be used when adding serial data
+to a waveform.
+
+. .
+#define PI_MIN_WAVE_HALFSTOPBITS 2
+#define PI_MAX_WAVE_HALFSTOPBITS 8
 . .
 
 bit::
@@ -3209,12 +3343,7 @@ purposes.
 
 cfgSource::
 
-The clock source used for the timing of DMA transfers.  May be the 19.2MHz
-crystal or the 500MHz PLL.
-. .
-PI_CLOCK_OSC 0
-PI_CLOCK_PLLD 1
-. .
+Deprecated.
 
 cfgVal::
 
@@ -3231,6 +3360,15 @@ char::
 
 A single character, an 8 bit quantity able to store 0-255.
 
+clkfreq::4689-250M
+
+The hardware clock frequency.
+
+. .
+#define PI_HW_CLK_MIN_FREQ 4689
+#define PI_HW_CLK_MAX_FREQ 250000000
+. .
+
 count::
 
 The number of bytes to be transferred in an I2C, SPI, or Serial
@@ -3449,10 +3587,11 @@ numBits::
 
 The number of bits stored in a buffer.
 
-numChar::
+numBytes::
 
-The number of characters in a string (used when the string might contain
-null characters, which would normally terminate the string).
+The number of bytes used to store characters in a string.  Depending
+on the number of bits per character there may be 1, 2, or 4 bytes
+per character.
 
 numPar:: 0-10
 
@@ -3517,6 +3656,21 @@ PI_MIN_SERVO_PULSEWIDTH 500
 PI_MAX_SERVO_PULSEWIDTH 2500
 . .
 
+PWMduty::0-1000
+The hardware PWM dutycycle.
+
+. .
+#define PI_HW_PWM_RANGE 1000
+. .
+
+PWMfreq::5-250K
+The hardware PWM frequency.
+
+. .
+#define PI_HW_PWM_MIN_FREQ 5
+#define PI_HW_PWM_MAX_FREQ 250000
+. .
+
 range::25-40000
 . .
 PI_MIN_DUTYCYCLE_RANGE 25
@@ -3830,6 +3984,9 @@ PARAMS*/
 #define PI_CMD_GDC   83
 #define PI_CMD_GPW   84
 
+#define PI_CMD_HC    85
+#define PI_CMD_HP    86
+
 #define PI_CMD_NOIB  99
 
 /*DEF_E*/
@@ -3910,7 +4067,7 @@ after this command is issued.
 #define PI_BAD_WDOG_TIMEOUT -15 // timeout not 0-60000
 #define PI_NO_ALERT_FUNC    -16 // DEPRECATED
 #define PI_BAD_CLK_PERIPH   -17 // clock peripheral not 0-1
-#define PI_BAD_CLK_SOURCE   -18 // clock source not 0-1
+#define PI_BAD_CLK_SOURCE   -18 // DEPRECATED
 #define PI_BAD_CLK_MICROS   -19 // clock micros not 1, 2, 4, 5, 8, or 10
 #define PI_BAD_BUF_MILLIS   -20 // buf millis not 100-10000
 #define PI_BAD_DUTYRANGE    -21 // dutycycle range not 25-40000
@@ -3929,7 +4086,7 @@ after this command is issued.
 #define PI_INITIALISED      -32 // function called after gpioInitialise
 #define PI_BAD_WAVE_MODE    -33 // waveform mode not 0-1
 #define PI_BAD_CFG_INTERNAL -34 // bad parameter in gpioCfgInternals call
-#define PI_BAD_WAVE_BAUD    -35 // baud rate not 100-250000
+#define PI_BAD_WAVE_BAUD    -35 // baud rate not 50-250K(RX)/50-1M(TX)
 #define PI_TOO_MANY_PULSES  -36 // waveform has too many pulses
 #define PI_TOO_MANY_CHARS   -37 // waveform has too many chars
 #define PI_NOT_SERIAL_GPIO  -38 // no serial read in progress on gpio
@@ -3940,22 +4097,22 @@ after this command is issued.
 #define PI_BAD_WVSC_COMMND  -43 // bad WVSC subcommand
 #define PI_BAD_WVSM_COMMND  -44 // bad WVSM subcommand
 #define PI_BAD_WVSP_COMMND  -45 // bad WVSP subcommand
-#define PI_BAD_PULSELEN     -46 // trigger pulse length 100
+#define PI_BAD_PULSELEN     -46 // trigger pulse length not 1-100
 #define PI_BAD_SCRIPT       -47 // invalid script
 #define PI_BAD_SCRIPT_ID    -48 // unknown script id
 #define PI_BAD_SER_OFFSET   -49 // add serial data offset > 30 minutes
 #define PI_GPIO_IN_USE      -50 // gpio already in use
 #define PI_BAD_SERIAL_COUNT -51 // must read at least a byte at a time
-#define PI_BAD_PARAM_NUM    -52 // script parameter must be 0-9
+#define PI_BAD_PARAM_NUM    -52 // script parameter id not 0-9
 #define PI_DUP_TAG          -53 // script has duplicate tag
 #define PI_TOO_MANY_TAGS    -54 // script has too many tags
 #define PI_BAD_SCRIPT_CMD   -55 // illegal script command
-#define PI_BAD_VAR_NUM      -56 // script variable must be 0-149
+#define PI_BAD_VAR_NUM      -56 // script variable id not 0-149
 #define PI_NO_SCRIPT_ROOM   -57 // no more room for scripts
 #define PI_NO_MEMORY        -58 // can't allocate temporary memory
 #define PI_SOCK_READ_FAILED -59 // socket read failed
 #define PI_SOCK_WRIT_FAILED -60 // socket write failed
-#define PI_TOO_MANY_PARAM   -61 // too many script parameters > 10
+#define PI_TOO_MANY_PARAM   -61 // too many script parameters (> 10)
 #define PI_NOT_HALTED       -62 // script already running or failed
 #define PI_BAD_TAG          -63 // script has unresolved tag
 #define PI_BAD_MICS_DELAY   -64 // bad MICS delay (too large)
@@ -3988,6 +4145,15 @@ after this command is issued.
 #define PI_NO_AUX_SPI       -91 // need a B+ 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-250K
+#define PI_BAD_HPWM_DUTY    -97 // hardware PWM dutycycle not 0-1000
+#define PI_BAD_HCLK_FREQ    -98 // hardware clock frequency not 4689-25M
+#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
 
 /*DEF_E*/
 
@@ -3996,7 +4162,6 @@ after this command is issued.
 #define PI_DEFAULT_BUFFER_MILLIS         120
 #define PI_DEFAULT_CLK_MICROS            5
 #define PI_DEFAULT_CLK_PERIPHERAL        PI_CLOCK_PCM
-#define PI_DEFAULT_CLK_SOURCE            PI_CLOCK_PLLD
 #define PI_DEFAULT_IF_FLAGS              0
 #define PI_DEFAULT_DMA_CHANNEL           14
 #define PI_DEFAULT_DMA_PRIMARY_CHANNEL   14
index 8210a225ee986bdba0cb2348a1737a62c95efb0e..44c41e1cf0fd8b51018dd51c5eb55fafe7816796 100644 (file)
--- a/pigpio.py
+++ b/pigpio.py
@@ -1,12 +1,13 @@
 """
-pigpio is a Python module for the Raspberry which allows control
-of the general purpose input outputs (gpios).
+pigpio is a Python module for the Raspberry which talks to
+the pigpio daemon to allow control of the general purpose
+input outputs (gpios).
 
 [http://abyz.co.uk/rpi/pigpio/python.html]
 
 *Features*
 
-o pigpio Python module can be running on Windows, Macs, or Linux
+o the pigpio Python module can run on Windows, Macs, or Linux
 
 o controls one or more Pi's
 
@@ -39,7 +40,7 @@ accurate to within a few microseconds.
 
 A number of settings are determined when the pigpio daemon is started.
 
-o the sample rate (1, 2, 4, 5, 8, or 10us, default 5us).
+o the sample rate (1, 2, 4, 5, 8, or 10 us, default 5 us).
 
 o the set of gpios which may be updated (generally written to).  The
   default set is those available on the Pi board revision.
@@ -151,6 +152,9 @@ bb_serial_read_open       Open a gpio for bit bang serial reads
 bb_serial_read            Read bit bang serial data from  a gpio
 bb_serial_read_close      Close a gpio for bit bang serial reads
 
+hardware_clock            Start hardware clock on supported gpios
+hardware_PWM              Start hardware PWM on supported gpios
+
 Scripts
 
 store_script              Store a script
@@ -248,7 +252,7 @@ import threading
 import os
 import atexit
 
-VERSION = "1.13"
+VERSION = "1.14"
 
 exceptions = True
 
@@ -395,7 +399,8 @@ _PI_CMD_SERDA=82
 _PI_CMD_GDC  =83
 _PI_CMD_GPW  =84
 
-
+_PI_CMD_HC   =85
+_PI_CMD_HP   =86
 
 _PI_CMD_NOIB= 99
 
@@ -495,6 +500,15 @@ _PI_BAD_POINTER     =-90
 PI_NO_AUX_SPI       =-91
 PI_NOT_PWM_GPIO     =-92
 PI_NOT_SERVO_GPIO   =-93
+PI_NOT_HCLK_GPIO    =-94
+PI_NOT_HPWM_GPIO    =-95
+PI_BAD_HPWM_FREQ    =-96
+PI_BAD_HPWM_DUTY    =-97
+PI_BAD_HCLK_FREQ    =-98
+PI_BAD_HCLK_PASS    =-99
+PI_HPWM_ILLEGAL     =-100
+PI_BAD_DATABITS     =-101
+PI_BAD_STOPBITS     =-102
 
 # pigpio error text
 
@@ -516,7 +530,7 @@ _errors=[
    [PI_BAD_WDOG_TIMEOUT  , "timeout not 0-60000"],
    [_PI_NO_ALERT_FUNC    , "DEPRECATED"],
    [_PI_BAD_CLK_PERIPH   , "clock peripheral not 0-1"],
-   [_PI_BAD_CLK_SOURCE   , "clock source not 0-1"],
+   [_PI_BAD_CLK_SOURCE   , "DEPRECATED"],
    [_PI_BAD_CLK_MICROS   , "clock micros not 1, 2, 4, 5, 8, or 10"],
    [_PI_BAD_BUF_MILLIS   , "buf millis not 100-10000"],
    [PI_BAD_DUTYRANGE     , "dutycycle range not 25-40000"],
@@ -533,7 +547,7 @@ _errors=[
    [_PI_INITIALISED      , "function called after gpioInitialise"],
    [_PI_BAD_WAVE_MODE    , "waveform mode not 0-1"],
    [_PI_BAD_CFG_INTERNAL , "bad parameter in gpioCfgInternals call"],
-   [PI_BAD_WAVE_BAUD     , "baud rate not 100-250000"],
+   [PI_BAD_WAVE_BAUD     , "baud rate not 50-250000(RX)/1000000(TX)"],
    [PI_TOO_MANY_PULSES   , "waveform has too many pulses"],
    [PI_TOO_MANY_CHARS    , "waveform has too many chars"],
    [PI_NOT_SERIAL_GPIO   , "no serial read in progress on gpio"],
@@ -542,17 +556,17 @@ _errors=[
    [PI_BAD_WVSC_COMMND   , "bad WVSC subcommand"],
    [PI_BAD_WVSM_COMMND   , "bad WVSM subcommand"],
    [PI_BAD_WVSP_COMMND   , "bad WVSP subcommand"],
-   [PI_BAD_PULSELEN      , "trigger pulse length 100"],
+   [PI_BAD_PULSELEN      , "trigger pulse length not 1-100"],
    [PI_BAD_SCRIPT        , "invalid script"],
    [PI_BAD_SCRIPT_ID     , "unknown script id"],
    [PI_BAD_SER_OFFSET    , "add serial data offset > 30 minute"],
    [PI_GPIO_IN_USE       , "gpio already in use"],
    [PI_BAD_SERIAL_COUNT  , "must read at least a byte at a time"],
-   [PI_BAD_PARAM_NUM     , "script parameter must be 0-9"],
+   [PI_BAD_PARAM_NUM     , "script parameter id not 0-9"],
    [PI_DUP_TAG           , "script has duplicate tag"],
    [PI_TOO_MANY_TAGS     , "script has too many tags"],
    [PI_BAD_SCRIPT_CMD    , "illegal script command"],
-   [PI_BAD_VAR_NUM       , "script variable must be 0-149"],
+   [PI_BAD_VAR_NUM       , "script variable id not 0-149"],
    [PI_NO_SCRIPT_ROOM    , "no more room for scripts"],
    [PI_NO_MEMORY         , "can't allocate temporary memory"],
    [PI_SOCK_READ_FAILED  , "socket read failed"],
@@ -590,6 +604,15 @@ _errors=[
    [PI_NO_AUX_SPI        , "need a B+ 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-250K"],
+   [PI_BAD_HPWM_DUTY     , "hardware PWM dutycycle not 0-1000"],
+   [PI_BAD_HCLK_FREQ     , "hardware clock frequency not 4689-25M"],
+   [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"],
 
 ]
 
@@ -677,11 +700,11 @@ else:
    def _str(x):
       return x
 
-def u2i(number):
+def u2i(uint32):
    """
    Converts a 32 bit unsigned number to signed.
 
-   number:= an unsigned 32 bit number
+   uint32:= an unsigned 32 bit number
 
    ...
    print(u2i(4294967272))
@@ -691,19 +714,19 @@ def u2i(number):
    ...
    """
    mask = (2 ** 32) - 1
-   if number & (1 << 31):
-      v = number | ~mask
+   if uint32 & (1 << 31):
+      v = uint32 | ~mask
    else:
-      v = number & mask
+      v = uint32 & mask
    return v
 
-def _u2i(number):
+def _u2i(uint32):
    """
    Converts a 32 bit unsigned number to signed.  If the number
    is negative it indicates an error.  On error a pigpio
    exception will be raised if exceptions is True.
    """
-   v = u2i(number)
+   v = u2i(uint32)
    if v < 0:
       if exceptions:
          raise error(error_text(v))
@@ -1388,6 +1411,107 @@ class pi():
       """
       return _u2i(_pigpio_command(self.sl, _PI_CMD_BS2, bits, 0))
 
+   def hardware_clock(self, gpio, clkfreq):
+      """
+      Starts a hardware clock on a gpio at the specified frequency.
+
+         gpio:= see description
+      clkfreq:= 0 (off) or 4689-250M
+
+
+      Returns 0 if OK, otherwise PI_NOT_PERMITTED, PI_BAD_GPIO,
+      PI_NOT_HCLK_GPIO, PI_BAD_HCLK_FREQ,or PI_BAD_HCLK_PASS.
+
+      The same clock is available on multiple gpios.  The latest
+      frequency setting will be used by all gpios which share a clock.
+
+      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
+      21  clock 1  All models but Rev.2 B (reserved for system use)
+
+      32  clock 0  Compute module only
+      34  clock 0  Compute module only
+      42  clock 1  Compute module only (reserved for system use)
+      43  clock 2  Compute module only
+      44  clock 1  Compute module only (reserved for system use)
+      . .
+
+      Access to clock 1 is protected by a password as its use will
+      likely crash the Pi.  The password is given by or'ing 0x5A000000
+      with the gpio number.
+
+      ...
+      pi.hardware_clock(4, 5000) # 5 KHz clock on gpio 4
+
+      pi.hardware_clock(4, 40000000) # 40 MHz clock on gpio 4
+      ...
+      """
+      return _u2i(_pigpio_command(self.sl, _PI_CMD_HC, gpio, clkfreq))
+
+   def hardware_PWM(self, gpio, PWMfreq, PWMduty):
+      """
+      Starts hardware PWM on a gpio at the specified
+      frequency and dutycycle.
+
+      NOTE: Any waveform started by [*wave_send_once*],
+      [*wave_send_repeat*], [*wave_tx_start*], or
+      [*wave_tx_repeat*] will be cancelled.
+
+      This function is only valid if the pigpio main clock is PCM.
+      The main clock defaults to PCM but may be overridden when the
+      pigpio daemon is started (option -t).
+
+         gpio:= see descripton
+      PWMfreq:= 0 (off) or 5-250K
+      PWMduty:= 0 (off) to 1000 (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
+      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
+      18  PWM channel 0  All models
+      19  PWM channel 1  A+/B+ and compute module only
+
+      40  PWM channel 0  Compute module only
+      41  PWM channel 1  Compute module only
+      45  PWM channel 1  Compute module only
+      52  PWM channel 0  Compute module only
+      53  PWM channel 1  Compute module only
+      . .
+
+      ...
+      pi.hardware_PWM(18, 800, 250) # 800Hz 25% dutycycle
+
+      pi.hardware_PWM(18, 2000, 750) # 2000Hz 75% dutycycle
+      ...
+      """
+      # pigpio message format
+
+      # I p1 gpio
+      # I p2 PWMfreq
+      # I p3 4
+      ## extension ##
+      # I PWMdutycycle
+      extents = [struct.pack("I", PWMduty)]
+      return _u2i(_pigpio_command_ext(
+         self.sl, _PI_CMD_HP, gpio, PWMfreq, 4, extents))
+
+
    def get_current_tick(self):
       """
       Returns the current system tick.
@@ -1549,49 +1673,60 @@ class pi():
       else:
          return 0
 
-   def wave_add_serial(self, user_gpio, bb_baud, offset, data):
+   def wave_add_serial(
+      self, user_gpio, bb_baud, data, offset=0, bb_bits=8, bb_stop=2):
       """
       Adds a waveform representing serial data to the existing
-      waveform (if any).  The serial data starts offset
+      waveform (if any).  The serial data starts [*offset*]
       microseconds from the start of the waveform.
 
       user_gpio:= gpio to transmit data.  You must set the gpio mode
                   to output.
         bb_baud:= baud rate to use.
-         offset:= number of microseconds from the starts of the
-                  waveform.
            data:= the bytes to write.
+         offset:= number of microseconds from the starts of the
+                  waveform, default 0.
+        bb_bits:= number of data bits, default 8.
+        bb_stop:= number of stop half bits, default 2.
 
       Returns the new total number of pulses in the current waveform.
 
-      The serial data is formatted as one start bit, eight data bits,
-      and one stop bit.
+      The serial data is formatted as one start bit, [*bb_bits*]
+      data bits, and [*bb_stop*]/2 stop bits.
 
       It is legal to add serial data streams with different baud
       rates to the same waveform.
 
+      The bytes required for each character depend upon [*bb_bits*].
+
+      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.
+
       ...
-      pi.wave_add_serial(4, 300, 0, 'Hello world')
+      pi.wave_add_serial(4, 300, 'Hello world')
 
-      pi.wave_add_serial(4, 300, 0, b"Hello world")
+      pi.wave_add_serial(4, 300, b"Hello world")
 
-      pi.wave_add_serial(4, 300, 0, b'\\x23\\x01\\x00\\x45')
+      pi.wave_add_serial(4, 300, b'\\x23\\x01\\x00\\x45')
 
-      pi.wave_add_serial(17, 38400, 5000, [23, 128, 234])
+      pi.wave_add_serial(17, 38400, [23, 128, 234], 5000)
       ...
       """
       # pigpio message format
 
       # I p1 gpio
       # I p2 bb_baud
-      # I p3 len+4
+      # I p3 len+12
       ## extension ##
+      # I bb_bits
+      # I bb_stop
       # I offset
       # s len data bytes
       if len(data):
-         extents = [struct.pack("I", offset), data]
+         extents = [struct.pack("III", bb_bits, bb_stop, offset), data]
          return _u2i(_pigpio_command_ext(
-            self.sl, _PI_CMD_WVAS, user_gpio, bb_baud, len(data)+4, extents))
+            self.sl, _PI_CMD_WVAS, user_gpio, bb_baud, len(data)+12, extents))
       else:
          return 0
 
@@ -1663,6 +1798,9 @@ class pi():
       This function is deprecated and will be removed.
 
       Use [*wave_create*]/[*wave_send_**] instead.
+
+      NOTE: Any hardware PWM started by [*hardware_PWM*] will
+      be cancelled.
       """
       return _u2i(_pigpio_command(self.sl, _PI_CMD_WVGO, 0, 0))
 
@@ -1671,6 +1809,9 @@ class pi():
       This function is deprecated and will be removed.
 
       Use [*wave_create*]/[*wave_send_**] instead.
+
+      NOTE: Any hardware PWM started by [*hardware_PWM*] will
+      be cancelled.
       """
       return _u2i(_pigpio_command(self.sl, _PI_CMD_WVGOR, 0, 0))
 
@@ -1679,6 +1820,9 @@ class pi():
       Transmits the waveform with id wave_id.  The waveform is sent
       once.
 
+      NOTE: Any hardware PWM started by [*hardware_PWM*] will
+      be cancelled.
+
       wave_id:= >=0 (as returned by a prior call to [*wave_create*]).
 
       Returns the number of DMA control blocks used in the waveform.
@@ -1695,6 +1839,9 @@ class pi():
       until wave_tx_stop is called or another call to [*wave_send_**]
       is made.
 
+      NOTE: Any hardware PWM started by [*hardware_PWM*] will
+      be cancelled.
+
       wave_id:= >=0 (as returned by a prior call to [*wave_create*]).
 
       Returns the number of DMA control blocks used in the waveform.
@@ -2719,7 +2866,7 @@ class pi():
         bb_baud:= 300-250000, the baud rate.
 
       The serial data is held in a cyclic buffer and is read using
-      bb_serial_read.
+      [*bb_serial_read*].
 
       It is the caller's responsibility to read data from the cyclic
       buffer in a timely fashion.
@@ -2923,6 +3070,16 @@ def xref():
    bb_baud: 100 - 250000
    The baud rate used for the transmission of bit bang serial data.
 
+   bb_bits: 1-32
+
+   The number of data bits to be used when adding serial data to a
+   waveform.
+
+   bb_stop: 2-8
+
+   The number of (half) stop bits to be used when adding serial data
+   to a waveform.
+
    bit: 0-1
    A value of 0 or 1.
 
@@ -2938,6 +3095,9 @@ def xref():
    byte_val: 0-255
    A whole number.
 
+   clkfreq: 4689-250M
+   The hardware clock frequency.
+
    count:
    The number of bytes of data to be transferred.
 
@@ -2966,70 +3126,87 @@ def xref():
    RISING_EDGE = 0
 
    errnum: <0
-   PI_BAD_DUTYCYCLE = -8 
-   PI_BAD_DUTYRANGE = -21 
-   PI_BAD_FLAGS = -77 
-   PI_BAD_GPIO = -3 
-   PI_BAD_HANDLE = -25 
-   PI_BAD_I2C_ADDR = -75 
-   PI_BAD_I2C_BUS = -74 
-   PI_BAD_LEVEL = -5 
-   PI_BAD_MICS_DELAY = -64 
-   PI_BAD_MILS_DELAY = -65 
-   PI_BAD_MODE = -4 
-   PI_BAD_PARAM = -81 
-   PI_BAD_PARAM_NUM = -52 
-   PI_BAD_PUD = -6 
-   PI_BAD_PULSELEN = -46 
-   PI_BAD_PULSEWIDTH = -7 
-   PI_BAD_SCRIPT = -47 
-   PI_BAD_SCRIPT_CMD = -55 
-   PI_BAD_SCRIPT_ID = -48 
-   PI_BAD_SERIAL_COUNT = -51 
-   PI_BAD_SER_DEVICE = -79 
-   PI_BAD_SER_OFFSET = -49 
-   PI_BAD_SER_SPEED = -80 
-   PI_BAD_SPI_CHANNEL = -76 
-   PI_BAD_SPI_COUNT = -84 
-   PI_BAD_SPI_SPEED = -78 
-   PI_BAD_TAG = -63 
-   PI_BAD_USER_GPIO = -2 
-   PI_BAD_VAR_NUM = -56 
-   PI_BAD_WAVE_BAUD = -35 
-   PI_BAD_WAVE_ID = -66 
-   PI_BAD_WDOG_TIMEOUT = -15 
-   PI_BAD_WVSC_COMMND = -43 
-   PI_BAD_WVSM_COMMND = -44 
-   PI_BAD_WVSP_COMMND = -45 
-   PI_DUP_TAG = -53 
-   PI_EMPTY_WAVEFORM = -69 
-   PI_GPIO_IN_USE = -50 
-   PI_I2C_OPEN_FAILED = -71 
-   PI_I2C_READ_FAILED = -83 
-   PI_I2C_WRITE_FAILED = -82 
-   PI_NOT_HALTED = -62 
-   PI_NOT_PERMITTED = -41 
-   PI_NOT_SERIAL_GPIO = -38 
-   PI_NO_HANDLE = -24 
-   PI_NO_MEMORY = -58 
-   PI_NO_SCRIPT_ROOM = -57 
-   PI_NO_WAVEFORM_ID = -70 
-   PI_SER_OPEN_FAILED = -72 
-   PI_SER_READ_FAILED = -86 
-   PI_SER_READ_NO_DATA = -87 
-   PI_SER_WRITE_FAILED = -85 
-   PI_SOCK_READ_FAILED = -59 
-   PI_SOCK_WRIT_FAILED = -60 
-   PI_SOME_PERMITTED = -42 
-   PI_SPI_OPEN_FAILED = -73 
-   PI_SPI_XFER_FAILED = -89 
-   PI_TOO_MANY_CBS = -67 
-   PI_TOO_MANY_CHARS = -37 
-   PI_TOO_MANY_OOL = -68 
-   PI_TOO_MANY_PARAM = -61 
-   PI_TOO_MANY_PULSES = -36 
-   PI_TOO_MANY_TAGS = -54 
-   PI_UNKNOWN_COMMAND = -88 
+   PI_BAD_DATABITS = -101
+   PI_BAD_DUTYCYCLE = -8
+   PI_BAD_DUTYRANGE = -21
+   PI_BAD_FLAGS = -77
+   PI_BAD_GPIO = -3
+   PI_BAD_HANDLE = -25
+   PI_BAD_HCLK_FREQ = -98
+   PI_BAD_HCLK_PASS = -99
+   PI_BAD_HPWM_DUTY = -97
+   PI_BAD_HPWM_FREQ = -96
+   PI_BAD_I2C_ADDR = -75
+   PI_BAD_I2C_BUS = -74
+   PI_BAD_LEVEL = -5
+   PI_BAD_MICS_DELAY = -64
+   PI_BAD_MILS_DELAY = -65
+   PI_BAD_MODE = -4
+   PI_BAD_PARAM = -81
+   PI_BAD_PARAM_NUM = -52
+   PI_BAD_PUD = -6
+   PI_BAD_PULSELEN = -46
+   PI_BAD_PULSEWIDTH = -7
+   PI_BAD_SCRIPT = -47
+   PI_BAD_SCRIPT_CMD = -55
+   PI_BAD_SCRIPT_ID = -48
+   PI_BAD_SERIAL_COUNT = -51
+   PI_BAD_SER_DEVICE = -79
+   PI_BAD_SER_OFFSET = -49
+   PI_BAD_SER_SPEED = -80
+   PI_BAD_SPI_CHANNEL = -76
+   PI_BAD_SPI_COUNT = -84
+   PI_BAD_SPI_SPEED = -78
+   PI_BAD_STOPBITS = -102
+   PI_BAD_TAG = -63
+   PI_BAD_USER_GPIO = -2
+   PI_BAD_VAR_NUM = -56
+   PI_BAD_WAVE_BAUD = -35
+   PI_BAD_WAVE_ID = -66
+   PI_BAD_WDOG_TIMEOUT = -15
+   PI_BAD_WVSC_COMMND = -43
+   PI_BAD_WVSM_COMMND = -44
+   PI_BAD_WVSP_COMMND = -45
+   PI_DUP_TAG = -53
+   PI_EMPTY_WAVEFORM = -69
+   PI_GPIO_IN_USE = -50
+   PI_HPWM_ILLEGAL = -100
+   PI_I2C_OPEN_FAILED = -71
+   PI_I2C_READ_FAILED = -83
+   PI_I2C_WRITE_FAILED = -82
+   PI_NOT_HALTED = -62
+   PI_NOT_HCLK_GPIO = -94
+   PI_NOT_HPWM_GPIO = -95
+   PI_NOT_PERMITTED = -41
+   PI_NOT_PWM_GPIO = -92
+   PI_NOT_SERIAL_GPIO = -38
+   PI_NOT_SERVO_GPIO = -93
+   PI_NO_AUX_SPI = -91
+   PI_NO_HANDLE = -24
+   PI_NO_MEMORY = -58
+   PI_NO_SCRIPT_ROOM = -57
+   PI_NO_WAVEFORM_ID = -70
+   PI_SCRIPT_FAILED = 4
+   PI_SCRIPT_HALTED = 1
+   PI_SCRIPT_INITING = 0
+   PI_SCRIPT_RUNNING = 2
+   PI_SCRIPT_WAITING = 3
+   PI_SER_OPEN_FAILED = -72
+   PI_SER_READ_FAILED = -86
+   PI_SER_READ_NO_DATA = -87
+   PI_SER_WRITE_FAILED = -85
+   PI_SOCK_READ_FAILED = -59
+   PI_SOCK_WRIT_FAILED = -60
+   PI_SOME_PERMITTED = -42
+   PI_SPI_OPEN_FAILED = -73
+   PI_SPI_XFER_FAILED = -89
+   PI_TOO_MANY_CBS = -67
+   PI_TOO_MANY_CHARS = -37
+   PI_TOO_MANY_OOL = -68
+   PI_TOO_MANY_PARAM = -61
+   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.
@@ -3117,6 +3294,12 @@ def xref():
    pulsewidth:
    The servo pulsewidth in microseconds.  0 switches pulses off.
 
+   PWMduty: 0-1000
+   The hardware PWM dutycycle.
+
+   PWMfreq: 5-250K
+   The hardware PWM frequency.
+
    range_: 25-40000
    Defines the limits for the [*dutycycle*] parameter.
 
@@ -3166,6 +3349,9 @@ def xref():
    tty:
    A Pi serial tty device, e.g. /dev/ttyAMA0, /dev/ttyUSB0
 
+   uint32:
+   An unsigned 32 bit number.
+
    user_gpio: 0-31
    A Broadcom numbered gpio.
 
index 72b4c55a283c74eb0c7807c0ac36e6c215088eaa..d5b495aa4acf22ce9f8f853a7c80028ca13449f6 100644 (file)
--- a/pigpiod.1
+++ b/pigpiod.1
@@ -69,11 +69,6 @@ clock peripheral
 0=PWM 1=PCM
 default PCM
 
-.IP "\fB-u value\fP"
-clock source
-0=OSC 1=PLLD
-default PLLD
-
 .IP "\fB-x mask\fP"
 gpios which may be updated
 A 54 bit mask with (1<<n) set if the user may update gpio #n.
index 69a5dbf2a00c8833a7199864b5d6008fff7f42e8..d744560b8d06812f4bcb8b41d44ad3302fa3cf09 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 14+
+This version is for pigpio version 24+
 */
 
 #include <sys/types.h>
@@ -52,7 +52,6 @@ This program starts the pigpio library as a daemon.
 static unsigned bufferSizeMilliseconds = PI_DEFAULT_BUFFER_MILLIS;
 static unsigned clockMicros            = PI_DEFAULT_CLK_MICROS;
 static unsigned clockPeripheral        = PI_DEFAULT_CLK_PERIPHERAL;
-static unsigned clockSource            = PI_DEFAULT_CLK_SOURCE;
 static unsigned ifFlags                = PI_DEFAULT_IF_FLAGS;
 static unsigned DMAprimaryChannel      = PI_DEFAULT_DMA_PRIMARY_CHANNEL;
 static unsigned DMAsecondaryChannel    = PI_DEFAULT_DMA_SECONDARY_CHANNEL;
@@ -91,7 +90,6 @@ void usage()
       "   -p value, socket port, 1024-32000,            default 8888\n" \
       "   -s value, sample rate, 1, 2, 4, 5, 8, or 10,  default 5\n" \
       "   -t value, clock peripheral, 0=PWM 1=PCM,      default PCM\n" \
-      "   -u value, clock source, 0=OSC 1=PLLD,         default PLLD\n" \
       "   -x mask,  gpios which may be updated,         default board user gpios\n" \
       "EXAMPLE\n" \
       "sudo pigpiod -s 2 -b 200 -f\n" \
@@ -106,7 +104,7 @@ static void initOpts(int argc, char *argv[])
    uint64_t mask;
    char * endptr;
 
-   while ((opt = getopt(argc, argv, "b:d:e:fkp:s:t:u:x:")) != -1)
+   while ((opt = getopt(argc, argv, "b:d:e:fkp:s:t:x:")) != -1)
    {
       i = -1;
 
@@ -175,13 +173,6 @@ static void initOpts(int argc, char *argv[])
             else fatal("invalid -t option (%d)", i);
             break;
 
-         case 'u':
-            i = atoi(optarg);
-            if ((i >= PI_CLOCK_OSC) && (i <= PI_CLOCK_PLLD))
-               clockSource = i;
-            else fatal("invalid -u option (%d)", i);
-            break;
-
          case 'x':
             mask = strtoll(optarg, &endptr, 0);
             if (!*endptr)
@@ -261,7 +252,7 @@ int main(int argc, char **argv)
 
    gpioCfgBufferSize(bufferSizeMilliseconds);
 
-   gpioCfgClock(clockMicros, clockPeripheral, clockSource);
+   gpioCfgClock(clockMicros, clockPeripheral, 0);
 
    gpioCfgInterfaces(ifFlags);
 
@@ -318,3 +309,4 @@ int main(int argc, char **argv)
 
    return 0;
 }
+
index 63cdab477ae6509d1ee0f1b84bce86c401145ab9..576b2c3094eb2f003b9c49d63b6fcee9503f30fa 100644 (file)
@@ -1084,6 +1084,154 @@ Returns 0 if OK, otherwise PI_SOME_PERMITTED.
 A status of PI_SOME_PERMITTED indicates that the user is not
 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.
+
+.br
+
+.br
+
+.EX
+     gpio: see description
+.br
+frequency: 0 (off) or 4689-250M
+.br
+
+.EE
+
+.br
+
+.br
+Returns 0 if OK, otherwise PI_NOT_PERMITTED, PI_BAD_GPIO,
+PI_NOT_HCLK_GPIO, PI_BAD_HCLK_FREQ,or PI_BAD_HCLK_PASS.
+
+.br
+
+.br
+The same clock is available on multiple gpios.  The latest
+frequency setting will be used by all gpios which share a clock.
+
+.br
+
+.br
+The gpio must be one of the following.
+
+.br
+
+.br
+
+.EX
+4   clock 0  All models
+.br
+5   clock 1  A+/B+ and compute module only (reserved for system use)
+.br
+6   clock 2  A+/B+ and compute module only
+.br
+20  clock 0  A+/B+ and compute module only
+.br
+21  clock 1  All models but Rev.2 B (reserved for system use)
+.br
+
+.br
+32  clock 0  Compute module only
+.br
+34  clock 0  Compute module only
+.br
+42  clock 1  Compute module only (reserved for system use)
+.br
+43  clock 2  Compute module only
+.br
+44  clock 1  Compute module only (reserved for system use)
+.br
+
+.EE
+
+.br
+
+.br
+Access to clock 1 is protected by a password as its use will likely
+crash the Pi.  The password is given by or'ing 0x5A000000 with the
+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.
+
+.br
+
+.br
+NOTE: Any waveform started by \fBwave_send_once\fP, \fBwave_send_repeat\fP, \fBwave_tx_start\fP, or \fBwave_tx_repeat\fP will be cancelled.
+
+.br
+
+.br
+This function is only valid if the pigpio main clock is PCM.  The
+main clock defaults to PCM but may be overridden when the pigpio
+daemon is started (option -t).
+
+.br
+
+.br
+
+.EX
+   gpio: see descripton
+.br
+PWMfreq: 0 (off) or 5-250K
+.br
+PWMduty: 0 (off) to 1000 (fully on).
+.br
+
+.EE
+
+.br
+
+.br
+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.
+
+.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.
+
+.br
+
+.br
+The gpio must be one of the following.
+
+.br
+
+.br
+
+.EX
+12  PWM channel 0  A+/B+ and compute module only
+.br
+13  PWM channel 1  A+/B+ and compute module only
+.br
+18  PWM channel 0  All models
+.br
+19  PWM channel 1  A+/B+ and compute module only
+.br
+
+.br
+40  PWM channel 0  Compute module only
+.br
+41  PWM channel 1  Compute module only
+.br
+45  PWM channel 1  Compute module only
+.br
+52  PWM channel 0  Compute module only
+.br
+53  PWM channel 1  Compute module only
+.br
+
+.EE
+
 .IP "\fBuint32_t get_current_tick(void)\fP"
 .IP "" 4
 Gets the current system tick.
@@ -1227,11 +1375,11 @@ for gpio#1 can be added, and then gpio#2 etc.
 If the added waveform is intended to start after or within the existing
 waveform then the first pulse should consist solely of a delay.
 
-.IP "\fBint wave_add_serial(unsigned user_gpio, unsigned bbBaud, unsigned offset, unsigned numChar, char *str)\fP"
+.IP "\fBint wave_add_serial(unsigned user_gpio, unsigned bbBaud, unsigned bbBits, unsigned bbStop, unsigned offset, unsigned numBytes, char *str)\fP"
 .IP "" 4
 This function adds a waveform representing serial data to the
-existing waveform (if any).  The serial data starts offset microseconds
-from the start of the waveform.
+existing waveform (if any).  The serial data starts offset
+microseconds from the start of the waveform.
 
 .br
 
@@ -1241,10 +1389,14 @@ from the start of the waveform.
 user_gpio: 0-31.
 .br
    bbBaud: 100-250000
+.br
+   bbBits: number of data bits (1-32)
+.br
+   bbStop: number of stop half bits (2-8)
 .br
    offset: 0-
 .br
 numChar: 1-
numBytes: 1-
 .br
       str: an array of chars.
 .br
@@ -1255,8 +1407,9 @@ user_gpio: 0-31.
 
 .br
 Returns the new total number of pulses in the current waveform if OK,
-otherwise PI_BAD_USER_GPIO, PI_BAD_WAVE_BAUD, PI_TOO_MANY_CHARS, or
-PI_TOO_MANY_PULSES.
+otherwise PI_BAD_USER_GPIO, PI_BAD_WAVE_BAUD, PI_BAD_DATABITS,
+PI_BAD_STOP_BITS, PI_TOO_MANY_CHARS, PI_BAD_SER_OFFSET,
+or PI_TOO_MANY_PULSES.
 
 .br
 
@@ -1266,8 +1419,8 @@ NOTES:
 .br
 
 .br
-The serial data is formatted as one start bit, eight data bits, and one
-stop bit.
+The serial data is formatted as one start bit, \fBbbBits\fP data bits,
+and \fBbbStop\fP/2 stop bits.
 
 .br
 
@@ -1275,6 +1428,25 @@ stop bit.
 It is legal to add serial data streams with different baud rates to
 the same waveform.
 
+.br
+
+.br
+\fBnumBytes\fP is the number of bytes of data in str.
+
+.br
+
+.br
+The bytes required for each character depend upon \fBbbBits\fP.
+
+.br
+
+.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 wave_create(void)\fP"
 .IP "" 4
 This function creates a waveform from the data provided by the prior
@@ -1409,13 +1581,31 @@ Returns 0 if OK, otherwise PI_BAD_WAVE_ID.
 
 .IP "\fBint wave_tx_start(void)\fP"
 .IP "" 4
-This function is deprecated and should no longer be used.  Use
-\fBwave_create\fP/\fBwave_send_*\fP instead.
+This function is deprecated and should no longer be used.
+
+.br
+
+.br
+Use \fBwave_create\fP/\fBwave_send_*\fP instead.
+
+.br
+
+.br
+NOTE: Any hardware PWM started by \fBhardware_PWM\fP will be cancelled.
 
 .IP "\fBint wave_tx_repeat(void)\fP"
 .IP "" 4
-This function is deprecated and should no longer be used.  Use
-\fBwave_create\fP/\fBwave_send_*\fP instead.
+This function is deprecated and should no longer be used.
+
+.br
+
+.br
+Use \fBwave_create\fP/\fBwave_send_*\fP instead.
+
+.br
+
+.br
+NOTE: Any hardware PWM started by \fBhardware_PWM\fP will be cancelled.
 
 .IP "\fBint wave_send_once(unsigned wave_id)\fP"
 .IP "" 4
@@ -1424,6 +1614,11 @@ is sent once.
 
 .br
 
+.br
+NOTE: Any hardware PWM started by \fBhardware_PWM\fP will be cancelled.
+
+.br
+
 .br
 
 .EX
@@ -1446,6 +1641,11 @@ by \fBwave_tx_stop\fP).
 
 .br
 
+.br
+NOTE: Any hardware PWM started by \fBhardware_PWM\fP will be cancelled.
+
+.br
+
 .br
 
 .EX
@@ -2792,6 +2992,54 @@ PI_WAVE_MAX_BAUD 250000
 
 .br
 
+.IP "\fBbbBits\fP: 1-32" 0
+
+.br
+
+.br
+The number of data bits to be used when adding serial data to a
+waveform.
+
+.br
+
+.br
+
+.EX
+#define PI_MIN_WAVE_DATABITS 1
+.br
+#define PI_MAX_WAVE_DATABITS 32
+.br
+
+.EE
+
+.br
+
+.br
+
+.IP "\fBbbStop\fP: 2-8" 0
+
+.br
+
+.br
+The number of (half) stop bits to be used when adding serial data
+to a waveform.
+
+.br
+
+.br
+
+.EX
+#define PI_MIN_WAVE_HALFSTOPBITS 2
+.br
+#define PI_MAX_WAVE_HALFSTOPBITS 8
+.br
+
+.EE
+
+.br
+
+.br
+
 .IP "\fBbit\fP" 0
 A value of 0 or 1.
 
@@ -2878,12 +3126,15 @@ typedef void (*CBFuncEx_t)
 
 .br
 
+.IP "\fBchar\fP" 0
+A single character, an 8 bit quantity able to store 0-255.
+
 .br
 
 .br
 
-.IP "\fBchar\fP" 0
-A single character, an 8 bit quantity able to store 0-255.
+.IP "\fBclkfreq\fP: 4689-250M" 0
+The hardware clock frequency.
 
 .br
 
@@ -3138,9 +3389,10 @@ PI_ALT5 2
 
 .br
 
-.IP "\fBnumChar\fP" 0
-The number of characters in a string (used when the string might contain
-null characters, which would normally terminate the string).
+.IP "\fBnumBytes\fP" 0
+The number of bytes used to store characters in a string.  Depending
+on the number of bits per character there may be 1, 2, or 4 bytes
+per character.
 
 .br
 
@@ -3255,6 +3507,38 @@ PI_MAX_SERVO_PULSEWIDTH 2500
 
 .br
 
+.IP "\fBPWMduty\fP: 0-1000" 0
+The hardware PWM dutycycle.
+
+.br
+
+.br
+
+.EX
+#define PI_HW_PWM_RANGE 1000
+.br
+
+.EE
+
+.br
+
+.br
+
+.IP "\fBPWMfreq\fP: 5-250K" 0
+The hardware PWM frequency.
+
+.br
+
+.br
+
+.EX
+#define PI_HW_PWM_MIN_FREQ 5
+.br
+#define PI_HW_PWM_MAX_FREQ 250000
+.br
+
+.EE
+
 .br
 
 .br
index 9eddd5a437b725b84ee3e53274f2776e6b2c0ab8..488e72a020f987a8076f755c28679b40ccbc01c9 100644 (file)
@@ -25,7 +25,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 For more information, please refer to <http://unlicense.org/>
 */
 
-/* PIGPIOD_IF_VERSION 11 */
+/* PIGPIOD_IF_VERSION 13 */
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -88,9 +88,11 @@ static int gPigStarted = 0;
 
 static pthread_t *pthNotify;
 
+static pthread_mutex_t command_mutex = PTHREAD_MUTEX_INITIALIZER;
+
 /* PRIVATE ---------------------------------------------------------------- */
 
-static int pigpio_command(int fd, int command, int p1, int p2)
+static int pigpio_command(int fd, int command, int p1, int p2, int rl)
 {
    cmdCmd_t cmd;
 
@@ -99,16 +101,28 @@ static int pigpio_command(int fd, int command, int p1, int p2)
    cmd.p2  = p2;
    cmd.res = 0;
 
-   if (send(fd, &cmd, sizeof(cmd), 0) != sizeof(cmd)) return pigif_bad_send;
+   pthread_mutex_lock(&command_mutex);
+
+   if (send(fd, &cmd, sizeof(cmd), 0) != sizeof(cmd))
+   {
+      pthread_mutex_unlock(&command_mutex);
+      return pigif_bad_send;
+   }
 
    if (recv(fd, &cmd, sizeof(cmd), MSG_WAITALL) != sizeof(cmd))
+   {
+      pthread_mutex_unlock(&command_mutex);
       return pigif_bad_recv;
+   }
+
+   if (rl) pthread_mutex_unlock(&command_mutex);
 
    return cmd.res;
 }
 
 static int pigpio_command_ext
-   (int fd, int command, int p1, int p2, int p3, int extents, gpioExtent_t *ext)
+   (int fd, int command, int p1, int p2, int p3,
+    int extents, gpioExtent_t *ext, int rl)
 {
    int i;
    cmdCmd_t cmd;
@@ -118,16 +132,30 @@ static int pigpio_command_ext
    cmd.p2  = p2;
    cmd.p3  = p3;
 
-   if (send(fd, &cmd, sizeof(cmd), 0) != sizeof(cmd)) return pigif_bad_send;
+   pthread_mutex_lock(&command_mutex);
+
+   if (send(fd, &cmd, sizeof(cmd), 0) != sizeof(cmd))
+   {
+      pthread_mutex_unlock(&command_mutex);
+      return pigif_bad_send;
+   }
 
    for (i=0; i<extents; i++)
    {
       if (send(fd, ext[i].ptr, ext[i].size, 0) != ext[i].size)
+      {
+         pthread_mutex_unlock(&command_mutex);
          return pigif_bad_send;
+      }
    }
 
    if (recv(fd, &cmd, sizeof(cmd), MSG_WAITALL) != sizeof(cmd))
+   {
+      pthread_mutex_unlock(&command_mutex);
       return pigif_bad_recv;
+   }
+
+   if (rl) pthread_mutex_unlock(&command_mutex);
 
    return cmd.res;
 }
@@ -290,7 +318,7 @@ static void findNotifyBits(void)
    if (bits != gNotifyBits)
    {
       gNotifyBits = bits;
-      pigpio_command(gPigCommand, PI_CMD_NB, gPigHandle, gNotifyBits);
+      pigpio_command(gPigCommand, PI_CMD_NB, gPigHandle, gNotifyBits, 1);
    }
 }
 
@@ -474,7 +502,7 @@ int pigpio_start(char *addrStr, char *portStr)
 
          if (gPigNotify >= 0)
          {
-            gPigHandle = pigpio_command(gPigNotify, PI_CMD_NOIB, 0, 0);
+            gPigHandle = pigpio_command(gPigNotify, PI_CMD_NOIB, 0, 0, 1);
 
             if (gPigHandle < 0) return pigif_bad_noib;
             else
@@ -509,7 +537,7 @@ void pigpio_stop(void)
    {
       if (gPigHandle >= 0)
       {
-         pigpio_command(gPigNotify, PI_CMD_NC, gPigHandle, 0);
+         pigpio_command(gPigNotify, PI_CMD_NC, gPigHandle, 0, 1);
          gPigHandle = -1;
       }
 
@@ -521,7 +549,7 @@ void pigpio_stop(void)
    {
       if (gPigHandle >= 0)
       {
-         pigpio_command(gPigCommand, PI_CMD_NC, gPigHandle, 0);
+         pigpio_command(gPigCommand, PI_CMD_NC, gPigHandle, 0, 1);
          gPigHandle = -1;
       }
 
@@ -531,94 +559,116 @@ void pigpio_stop(void)
 }
 
 int set_mode(unsigned gpio, unsigned mode)
-   {return pigpio_command(gPigCommand, PI_CMD_MODES, gpio, mode);}
+   {return pigpio_command(gPigCommand, PI_CMD_MODES, gpio, mode, 1);}
 
 int get_mode(unsigned gpio)
-   {return pigpio_command(gPigCommand, PI_CMD_MODEG, gpio, 0);}
+   {return pigpio_command(gPigCommand, PI_CMD_MODEG, gpio, 0, 1);}
 
 int set_pull_up_down(unsigned gpio, unsigned pud)
-   {return pigpio_command(gPigCommand, PI_CMD_PUD, gpio, pud);}
+   {return pigpio_command(gPigCommand, PI_CMD_PUD, gpio, pud, 1);}
 
 int gpio_read(unsigned gpio)
-   {return pigpio_command(gPigCommand, PI_CMD_READ, gpio, 0);}
+   {return pigpio_command(gPigCommand, PI_CMD_READ, gpio, 0, 1);}
 
 int gpio_write(unsigned gpio, unsigned level)
-   {return pigpio_command(gPigCommand, PI_CMD_WRITE, gpio, level);}
+   {return pigpio_command(gPigCommand, PI_CMD_WRITE, gpio, level, 1);}
 
 int set_PWM_dutycycle(unsigned user_gpio, unsigned dutycycle)
-   {return pigpio_command(gPigCommand, PI_CMD_PWM, user_gpio, dutycycle);}
+   {return pigpio_command(gPigCommand, PI_CMD_PWM, user_gpio, dutycycle, 1);}
 
 int get_PWM_dutycycle(unsigned user_gpio)
-   {return pigpio_command(gPigCommand, PI_CMD_GDC, user_gpio, 0);}
+   {return pigpio_command(gPigCommand, PI_CMD_GDC, user_gpio, 0, 1);}
 
 int set_PWM_range(unsigned user_gpio, unsigned range)
-   {return pigpio_command(gPigCommand, PI_CMD_PRS, user_gpio, range);}
+   {return pigpio_command(gPigCommand, PI_CMD_PRS, user_gpio, range, 1);}
 
 int get_PWM_range(unsigned user_gpio)
-   {return pigpio_command(gPigCommand, PI_CMD_PRG, user_gpio, 0);}
+   {return pigpio_command(gPigCommand, PI_CMD_PRG, user_gpio, 0, 1);}
 
 int get_PWM_real_range(unsigned user_gpio)
-   {return pigpio_command(gPigCommand, PI_CMD_PRRG, user_gpio, 0);}
+   {return pigpio_command(gPigCommand, PI_CMD_PRRG, user_gpio, 0, 1);}
 
 int set_PWM_frequency(unsigned user_gpio, unsigned frequency)
-   {return pigpio_command(gPigCommand, PI_CMD_PFS, user_gpio, frequency);}
+   {return pigpio_command(gPigCommand, PI_CMD_PFS, user_gpio, frequency, 1);}
 
 int get_PWM_frequency(unsigned user_gpio)
-   {return pigpio_command(gPigCommand, PI_CMD_PFG, user_gpio, 0);}
+   {return pigpio_command(gPigCommand, PI_CMD_PFG, user_gpio, 0, 1);}
 
 int set_servo_pulsewidth(unsigned user_gpio, unsigned pulsewidth)
-   {return pigpio_command(gPigCommand, PI_CMD_SERVO, user_gpio, pulsewidth);}
+   {return pigpio_command(gPigCommand, PI_CMD_SERVO, user_gpio, pulsewidth, 1);}
 
 int get_servo_pulsewidth(unsigned user_gpio)
-   {return pigpio_command(gPigCommand, PI_CMD_GPW, user_gpio, 0);}
+   {return pigpio_command(gPigCommand, PI_CMD_GPW, user_gpio, 0, 1);}
 
 int notify_open(void)
-   {return pigpio_command(gPigCommand, PI_CMD_NO, 0, 0);}
+   {return pigpio_command(gPigCommand, PI_CMD_NO, 0, 0, 1);}
 
 int notify_begin(unsigned handle, uint32_t bits)
-   {return pigpio_command(gPigCommand, PI_CMD_NB, handle, bits);}
+   {return pigpio_command(gPigCommand, PI_CMD_NB, handle, bits, 1);}
 
 int notify_pause(unsigned handle)
-   {return pigpio_command(gPigCommand, PI_CMD_NB, handle, 0);}
+   {return pigpio_command(gPigCommand, PI_CMD_NB, handle, 0, 1);}
 
 int notify_close(unsigned handle)
-   {return pigpio_command(gPigCommand, PI_CMD_NC, handle, 0);}
+   {return pigpio_command(gPigCommand, PI_CMD_NC, handle, 0, 1);}
 
 int set_watchdog(unsigned user_gpio, unsigned timeout)
-   {return pigpio_command(gPigCommand, PI_CMD_WDOG, user_gpio, timeout);}
+   {return pigpio_command(gPigCommand, PI_CMD_WDOG, user_gpio, timeout, 1);}
 
 uint32_t read_bank_1(void)
-   {return pigpio_command(gPigCommand, PI_CMD_BR1, 0, 0);}
+   {return pigpio_command(gPigCommand, PI_CMD_BR1, 0, 0, 1);}
 
 uint32_t read_bank_2(void)
-   {return pigpio_command(gPigCommand, PI_CMD_BR2, 0, 0);}
+   {return pigpio_command(gPigCommand, PI_CMD_BR2, 0, 0, 1);}
 
 int clear_bank_1(uint32_t levels)
-   {return pigpio_command(gPigCommand, PI_CMD_BC1, levels, 0);}
+   {return pigpio_command(gPigCommand, PI_CMD_BC1, levels, 0, 1);}
 
 int clear_bank_2(uint32_t levels)
-   {return pigpio_command(gPigCommand, PI_CMD_BC2, levels, 0);}
+   {return pigpio_command(gPigCommand, PI_CMD_BC2, levels, 0, 1);}
 
 int set_bank_1(uint32_t levels)
-   {return pigpio_command(gPigCommand, PI_CMD_BS1, levels, 0);}
+   {return pigpio_command(gPigCommand, PI_CMD_BS1, levels, 0, 1);}
 
 int set_bank_2(uint32_t levels)
-   {return pigpio_command(gPigCommand, PI_CMD_BS2, levels, 0);}
+   {return pigpio_command(gPigCommand, PI_CMD_BS2, levels, 0, 1);}
+
+int hardware_clock(unsigned gpio, unsigned frequency)
+   {return pigpio_command(gPigCommand, PI_CMD_HC, gpio, frequency, 1);}
+
+int hardware_PWM(unsigned gpio, unsigned frequency, uint32_t dutycycle)
+{
+   gpioExtent_t ext[1];
+   
+   /*
+   p1=gpio
+   p2=frequency
+   p3=4
+   ## extension ##
+   uint32_t dutycycle
+   */
+
+   ext[0].size = sizeof(dutycycle);
+   ext[0].ptr = &dutycycle;
+
+   return pigpio_command_ext(
+      gPigCommand, PI_CMD_HP, gpio, frequency, sizeof(dutycycle), 1, ext, 1);
+}
 
 uint32_t get_current_tick(void)
-   {return pigpio_command(gPigCommand, PI_CMD_TICK, 0, 0);}
+   {return pigpio_command(gPigCommand, PI_CMD_TICK, 0, 0, 1);}
 
 uint32_t get_hardware_revision(void)
-   {return pigpio_command(gPigCommand, PI_CMD_HWVER, 0, 0);}
+   {return pigpio_command(gPigCommand, PI_CMD_HWVER, 0, 0, 1);}
 
 uint32_t get_pigpio_version(void)
-   {return pigpio_command(gPigCommand, PI_CMD_PIGPV, 0, 0);}
+   {return pigpio_command(gPigCommand, PI_CMD_PIGPV, 0, 0, 1);}
 
 int wave_clear(void)
-   {return pigpio_command(gPigCommand, PI_CMD_WVCLR, 0, 0);}
+   {return pigpio_command(gPigCommand, PI_CMD_WVCLR, 0, 0, 1);}
 
 int wave_add_new(void)
-   {return pigpio_command(gPigCommand, PI_CMD_WVNEW, 0, 0);}
+   {return pigpio_command(gPigCommand, PI_CMD_WVNEW, 0, 0, 1);}
 
 int wave_add_generic(unsigned numPulses, gpioPulse_t *pulses)
 {
@@ -638,88 +688,95 @@ int wave_add_generic(unsigned numPulses, gpioPulse_t *pulses)
    ext[0].ptr = pulses;
 
    return pigpio_command_ext(
-      gPigCommand, PI_CMD_WVAG, 0, 0, ext[0].size, 1, ext);
+      gPigCommand, PI_CMD_WVAG, 0, 0, ext[0].size, 1, ext, 1);
 }
 
 int wave_add_serial(
-   unsigned user_gpio, unsigned baud, unsigned offset,
-   unsigned numChar, char *str)
+   unsigned user_gpio, unsigned baud, uint32_t databits,
+   uint32_t stophalfbits, uint32_t offset,  unsigned numChar, char *str)
 {
-   gpioExtent_t ext[3];
+   uint8_t buf[12];
+   gpioExtent_t ext[2];
 
    /*
    p1=user_gpio
    p2=baud
-   p3=len+4
+   p3=len+12
    ## extension ##
-   unsigned offset
+   uint32_t databits
+   uint32_t stophalfbits
+   uint32_t offset
    char[len] str
    */
 
    if (!numChar) return 0;
 
-   ext[0].size = sizeof(unsigned);
-   ext[0].ptr = &offset;
+   memcpy(buf, &databits, 4);
+   memcpy(buf+4, &stophalfbits, 4);
+   memcpy(buf+8, &offset, 4);
+
+   ext[0].size = sizeof(buf);
+   ext[0].ptr = buf;
 
    ext[1].size = numChar;
    ext[1].ptr = str;
 
-   return pigpio_command_ext(
-      gPigCommand, PI_CMD_WVAS, user_gpio, baud, numChar+4, 2, ext);
+   return pigpio_command_ext(gPigCommand, PI_CMD_WVAS,
+      user_gpio, baud, numChar+sizeof(buf), 2, ext, 1);
 }
 
 int wave_create(void)
-   {return pigpio_command(gPigCommand, PI_CMD_WVCRE, 0, 0);}
+   {return pigpio_command(gPigCommand, PI_CMD_WVCRE, 0, 0, 1);}
 
 int wave_delete(unsigned wave_id)
-   {return pigpio_command(gPigCommand, PI_CMD_WVDEL, wave_id, 0);}
+   {return pigpio_command(gPigCommand, PI_CMD_WVDEL, wave_id, 0, 1);}
 
 int wave_tx_start(void) /* DEPRECATED */
-   {return pigpio_command(gPigCommand, PI_CMD_WVGO, 0, 0);}
+   {return pigpio_command(gPigCommand, PI_CMD_WVGO, 0, 0, 1);}
 
 int wave_tx_repeat(void) /* DEPRECATED */
-   {return pigpio_command(gPigCommand, PI_CMD_WVGOR, 0, 0);}
+   {return pigpio_command(gPigCommand, PI_CMD_WVGOR, 0, 0, 1);}
 
 int wave_send_once(unsigned wave_id)
-   {return pigpio_command(gPigCommand, PI_CMD_WVTX, 0, 0);}
+   {return pigpio_command(gPigCommand, PI_CMD_WVTX, 0, 0, 1);}
 
 int wave_send_repeat(unsigned wave_id)
-   {return pigpio_command(gPigCommand, PI_CMD_WVTXR, 0, 0);}
+   {return pigpio_command(gPigCommand, PI_CMD_WVTXR, 0, 0, 1);}
 
 int wave_tx_busy(void)
-   {return pigpio_command(gPigCommand, PI_CMD_WVBSY, 0, 0);}
+   {return pigpio_command(gPigCommand, PI_CMD_WVBSY, 0, 0, 1);}
 
 int wave_tx_stop(void)
-   {return pigpio_command(gPigCommand, PI_CMD_WVHLT, 0, 0);}
+   {return pigpio_command(gPigCommand, PI_CMD_WVHLT, 0, 0, 1);}
 
 int wave_get_micros(void)
-   {return pigpio_command(gPigCommand, PI_CMD_WVSM, 0, 0);}
+   {return pigpio_command(gPigCommand, PI_CMD_WVSM, 0, 0, 1);}
 
 int wave_get_high_micros(void)
-   {return pigpio_command(gPigCommand, PI_CMD_WVSM, 1, 0);}
+   {return pigpio_command(gPigCommand, PI_CMD_WVSM, 1, 0, 1);}
 
 int wave_get_max_micros(void)
-   {return pigpio_command(gPigCommand, PI_CMD_WVSM, 2, 0);}
+   {return pigpio_command(gPigCommand, PI_CMD_WVSM, 2, 0, 1);}
 
 int wave_get_pulses(void)
-   {return pigpio_command(gPigCommand, PI_CMD_WVSP, 0, 0);}
+   {return pigpio_command(gPigCommand, PI_CMD_WVSP, 0, 0, 1);}
 
 int wave_get_high_pulses(void)
-   {return pigpio_command(gPigCommand, PI_CMD_WVSP, 1, 0);}
+   {return pigpio_command(gPigCommand, PI_CMD_WVSP, 1, 0, 1);}
 
 int wave_get_max_pulses(void)
-   {return pigpio_command(gPigCommand, PI_CMD_WVSP, 2, 0);}
+   {return pigpio_command(gPigCommand, PI_CMD_WVSP, 2, 0, 1);}
 
 int wave_get_cbs(void)
-   {return pigpio_command(gPigCommand, PI_CMD_WVSC, 0, 0);}
+   {return pigpio_command(gPigCommand, PI_CMD_WVSC, 0, 0, 1);}
 
 int wave_get_high_cbs(void)
-   {return pigpio_command(gPigCommand, PI_CMD_WVSC, 1, 0);}
+   {return pigpio_command(gPigCommand, PI_CMD_WVSC, 1, 0, 1);}
 
 int wave_get_max_cbs(void)
-   {return pigpio_command(gPigCommand, PI_CMD_WVSC, 2, 0);}
+   {return pigpio_command(gPigCommand, PI_CMD_WVSC, 2, 0, 1);}
 
-int gpio_trigger(unsigned user_gpio, unsigned pulseLen, unsigned level)
+int gpio_trigger(unsigned user_gpio, unsigned pulseLen, uint32_t level)
 {
    gpioExtent_t ext[1];
    
@@ -731,11 +788,11 @@ int gpio_trigger(unsigned user_gpio, unsigned pulseLen, unsigned level)
    unsigned level
    */
 
-   ext[0].size = sizeof(level);
+   ext[0].size = sizeof(uint32_t);
    ext[0].ptr = &level;
 
    return pigpio_command_ext(
-      gPigCommand, PI_CMD_TRIG, user_gpio, pulseLen, 4, 1, ext);
+      gPigCommand, PI_CMD_TRIG, user_gpio, pulseLen, 4, 1, ext, 1);
 }
 
 int store_script(char *script)
@@ -758,7 +815,7 @@ int store_script(char *script)
    ext[0].size = len;
    ext[0].ptr = script;
 
-   return pigpio_command_ext(gPigCommand, PI_CMD_PROC, 0, 0, len, 1, ext);
+   return pigpio_command_ext(gPigCommand, PI_CMD_PROC, 0, 0, len, 1, ext, 1);
 }
 
 int run_script(unsigned script_id, unsigned numPar, uint32_t *param)
@@ -777,7 +834,7 @@ int run_script(unsigned script_id, unsigned numPar, uint32_t *param)
    ext[0].ptr = param;
 
    return pigpio_command_ext
-      (gPigCommand, PI_CMD_PROCR, script_id, 0, numPar*4, 1, ext);
+      (gPigCommand, PI_CMD_PROCR, script_id, 0, numPar*4, 1, ext, 1);
 }
 
 int script_status(unsigned script_id, uint32_t *param)
@@ -785,7 +842,7 @@ int script_status(unsigned script_id, uint32_t *param)
    int status;
    uint32_t p[PI_MAX_SCRIPT_PARAMS+1]; /* space for script status */
 
-   status = pigpio_command(gPigCommand, PI_CMD_PROCP, script_id, 0);
+   status = pigpio_command(gPigCommand, PI_CMD_PROCP, script_id, 0, 0);
 
    if (status > 0)
    {
@@ -796,36 +853,41 @@ int script_status(unsigned script_id, uint32_t *param)
       if (param) memcpy(param, p+1, sizeof(p)-4);
    }
 
+   pthread_mutex_unlock(&command_mutex);
+
    return status;
 }
 
 int stop_script(unsigned script_id)
-   {return pigpio_command(gPigCommand, PI_CMD_PROCS, script_id, 0);}
+   {return pigpio_command(gPigCommand, PI_CMD_PROCS, script_id, 0, 1);}
 
 int delete_script(unsigned script_id)
-   {return pigpio_command(gPigCommand, PI_CMD_PROCD, script_id, 0);}
+   {return pigpio_command(gPigCommand, PI_CMD_PROCD, script_id, 0, 1);}
 
 int bb_serial_read_open(unsigned user_gpio, unsigned baud)
-   {return pigpio_command(gPigCommand, PI_CMD_SLRO, user_gpio, baud);}
+   {return pigpio_command(gPigCommand, PI_CMD_SLRO, user_gpio, baud, 1);}
 
 int bb_serial_read(unsigned user_gpio, void *buf, size_t bufSize)
 {
    int bytes;
 
-   bytes = pigpio_command(gPigCommand, PI_CMD_SLR, user_gpio, bufSize);
+   bytes = pigpio_command(gPigCommand, PI_CMD_SLR, user_gpio, bufSize, 0);
 
    if (bytes > 0)
    {
       /* get the data */
       recv(gPigCommand, buf, bytes, MSG_WAITALL);
    }
+
+   pthread_mutex_unlock(&command_mutex);
+
    return bytes;
 }
 
 int bb_serial_read_close(unsigned user_gpio)
-   {return pigpio_command(gPigCommand, PI_CMD_SLRC, user_gpio, 0);}
+   {return pigpio_command(gPigCommand, PI_CMD_SLRC, user_gpio, 0, 1);}
 
-int i2c_open(unsigned i2c_bus, unsigned i2c_addr, unsigned i2c_flags)
+int i2c_open(unsigned i2c_bus, unsigned i2c_addr, uint32_t i2c_flags)
 {
    gpioExtent_t ext[1];
 
@@ -837,27 +899,30 @@ int i2c_open(unsigned i2c_bus, unsigned i2c_addr, unsigned i2c_flags)
    uint32_t i2c_flags
    */
 
-   ext[0].size = 4;
+   ext[0].size = sizeof(uint32_t);
    ext[0].ptr = &i2c_flags;
 
    return pigpio_command_ext
-      (gPigCommand, PI_CMD_I2CO, i2c_bus, i2c_addr, 4, 1, ext);
+      (gPigCommand, PI_CMD_I2CO, i2c_bus, i2c_addr, 4, 1, ext, 1);
 }
 
 int i2c_close(unsigned handle)
-   {return pigpio_command(gPigCommand, PI_CMD_I2CC, handle, 0);}
+   {return pigpio_command(gPigCommand, PI_CMD_I2CC, handle, 0, 1);}
 
 int i2c_read_device(unsigned handle, char *buf, unsigned count)
 {
    int bytes;
 
-   bytes = pigpio_command(gPigCommand, PI_CMD_I2CRD, handle, count);
+   bytes = pigpio_command(gPigCommand, PI_CMD_I2CRD, handle, count, 0);
 
    if (bytes > 0)
    {
       /* get the data */
       recv(gPigCommand, buf, bytes, MSG_WAITALL);
    }
+
+   pthread_mutex_unlock(&command_mutex);
+
    return bytes;
 }
 
@@ -877,19 +942,19 @@ int i2c_write_device(unsigned handle, char *buf, unsigned count)
    ext[0].ptr = buf;
 
    return pigpio_command_ext
-      (gPigCommand, PI_CMD_I2CWD, handle, 0, count, 1, ext);
+      (gPigCommand, PI_CMD_I2CWD, handle, 0, count, 1, ext, 1);
 }
 
 int i2c_write_quick(unsigned handle, unsigned bit)
-   {return pigpio_command(gPigCommand, PI_CMD_I2CWQ, handle, bit);}
+   {return pigpio_command(gPigCommand, PI_CMD_I2CWQ, handle, bit, 1);}
 
 int i2c_write_byte(unsigned handle, unsigned val)
-   {return pigpio_command(gPigCommand, PI_CMD_I2CWS, handle, val);}
+   {return pigpio_command(gPigCommand, PI_CMD_I2CWS, handle, val, 1);}
 
 int i2c_read_byte(unsigned handle)
-   {return pigpio_command(gPigCommand, PI_CMD_I2CRS, handle, 0);}
+   {return pigpio_command(gPigCommand, PI_CMD_I2CRS, handle, 0, 1);}
 
-int i2c_write_byte_data(unsigned handle, unsigned reg, unsigned val)
+int i2c_write_byte_data(unsigned handle, unsigned reg, uint32_t val)
 {
    gpioExtent_t ext[1];
 
@@ -901,14 +966,14 @@ int i2c_write_byte_data(unsigned handle, unsigned reg, unsigned val)
    uint32_t val
    */
 
-   ext[0].size = 4;
+   ext[0].size = sizeof(uint32_t);
    ext[0].ptr = &val;
 
    return pigpio_command_ext
-      (gPigCommand, PI_CMD_I2CWB, handle, reg, 4, 1, ext);
+      (gPigCommand, PI_CMD_I2CWB, handle, reg, 4, 1, ext, 1);
 }
 
-int i2c_write_word_data(unsigned handle, unsigned reg, unsigned val)
+int i2c_write_word_data(unsigned handle, unsigned reg, uint32_t val)
 {
    gpioExtent_t ext[1];
 
@@ -920,20 +985,20 @@ int i2c_write_word_data(unsigned handle, unsigned reg, unsigned val)
    uint32_t val
    */
 
-   ext[0].size = 4;
+   ext[0].size = sizeof(uint32_t);
    ext[0].ptr = &val;
 
    return pigpio_command_ext
-      (gPigCommand, PI_CMD_I2CWW, handle, reg, 4, 1, ext);
+      (gPigCommand, PI_CMD_I2CWW, handle, reg, 4, 1, ext, 1);
 }
 
 int i2c_read_byte_data(unsigned handle, unsigned reg)
-   {return pigpio_command(gPigCommand, PI_CMD_I2CRB, handle, reg);}
+   {return pigpio_command(gPigCommand, PI_CMD_I2CRB, handle, reg, 1);}
 
 int i2c_read_word_data(unsigned handle, unsigned reg)
-   {return pigpio_command(gPigCommand, PI_CMD_I2CRW, handle, reg);}
+   {return pigpio_command(gPigCommand, PI_CMD_I2CRW, handle, reg, 1);}
 
-int i2c_process_call(unsigned handle, unsigned reg, unsigned val)
+int i2c_process_call(unsigned handle, unsigned reg, uint32_t val)
 {
    gpioExtent_t ext[1];
 
@@ -945,11 +1010,11 @@ int i2c_process_call(unsigned handle, unsigned reg, unsigned val)
    uint32_t val
    */
 
-   ext[0].size = 4;
+   ext[0].size = sizeof(uint32_t);
    ext[0].ptr = &val;
 
    return pigpio_command_ext
-      (gPigCommand, PI_CMD_I2CPK, handle, reg, 4, 1, ext);
+      (gPigCommand, PI_CMD_I2CPK, handle, reg, 4, 1, ext, 1);
 }
 
 int i2c_write_block_data(
@@ -969,20 +1034,23 @@ int i2c_write_block_data(
    ext[0].ptr = buf;
 
    return pigpio_command_ext
-      (gPigCommand, PI_CMD_I2CWK, handle, reg, count, 1, ext);
+      (gPigCommand, PI_CMD_I2CWK, handle, reg, count, 1, ext, 1);
 }
 
 int i2c_read_block_data(unsigned handle, unsigned reg, char *buf)
 {
    int bytes;
 
-   bytes = pigpio_command(gPigCommand, PI_CMD_I2CRK, handle, reg);
+   bytes = pigpio_command(gPigCommand, PI_CMD_I2CRK, handle, reg, 0);
 
    if (bytes > 0)
    {
       /* get the data */
       recv(gPigCommand, buf, bytes, MSG_WAITALL);
    }
+
+   pthread_mutex_unlock(&command_mutex);
+
    return bytes;
 }
 
@@ -1004,18 +1072,21 @@ int i2c_block_process_call(
    ext[0].ptr = buf;
 
    bytes = pigpio_command_ext
-      (gPigCommand, PI_CMD_I2CPK, handle, reg, count, 1, ext);
+      (gPigCommand, PI_CMD_I2CPK, handle, reg, count, 1, ext, 0);
 
    if (bytes > 0)
    {
       /* get the data */
       recv(gPigCommand, buf, bytes, MSG_WAITALL);
    }
+
+   pthread_mutex_unlock(&command_mutex);
+
    return bytes;
 }
 
 int i2c_read_i2c_block_data(
-   unsigned handle, unsigned reg, char *buf, unsigned count)
+   unsigned handle, unsigned reg, char *buf, uint32_t count)
 {
    int bytes;
    gpioExtent_t ext[1];
@@ -1028,17 +1099,20 @@ int i2c_read_i2c_block_data(
    uint32_t count
    */
 
-   ext[0].size = 4;
+   ext[0].size = sizeof(uint32_t);
    ext[0].ptr = &count;
 
    bytes = pigpio_command_ext
-      (gPigCommand, PI_CMD_I2CRI, handle, reg, 4, 1, ext);
+      (gPigCommand, PI_CMD_I2CRI, handle, reg, 4, 1, ext, 0);
 
    if (bytes > 0)
    {
       /* get the data */
       recv(gPigCommand, buf, bytes, MSG_WAITALL);
    }
+
+   pthread_mutex_unlock(&command_mutex);
+
    return bytes;
 }
 
@@ -1060,10 +1134,10 @@ int i2c_write_i2c_block_data(
    ext[0].ptr = buf;
 
    return pigpio_command_ext
-      (gPigCommand, PI_CMD_I2CWI, handle, reg, count, 1, ext);
+      (gPigCommand, PI_CMD_I2CWI, handle, reg, count, 1, ext, 1);
 }
 
-int spi_open(unsigned channel, unsigned speed, unsigned flags)
+int spi_open(unsigned channel, unsigned speed, uint32_t flags)
 {
    gpioExtent_t ext[1];
 
@@ -1075,28 +1149,31 @@ int spi_open(unsigned channel, unsigned speed, unsigned flags)
    uint32_t flags
    */
 
-   ext[0].size = 4;
+   ext[0].size = sizeof(uint32_t);
    ext[0].ptr = &flags;
 
    return pigpio_command_ext
-      (gPigCommand, PI_CMD_SPIO, channel, speed, 4, 1, ext);
+      (gPigCommand, PI_CMD_SPIO, channel, speed, 4, 1, ext, 1);
 }
 
 int spi_close(unsigned handle)
-   {return pigpio_command(gPigCommand, PI_CMD_SPIC, handle, 0);}
+   {return pigpio_command(gPigCommand, PI_CMD_SPIC, handle, 0, 1);}
 
 int spi_read(unsigned handle, char *buf, unsigned count)
 {
    int bytes;
 
    bytes = pigpio_command
-      (gPigCommand, PI_CMD_SPIR, handle, count);
+      (gPigCommand, PI_CMD_SPIR, handle, count, 0);
 
    if (bytes > 0)
    {
       /* get the data */
       recv(gPigCommand, buf, bytes, MSG_WAITALL);
    }
+
+   pthread_mutex_unlock(&command_mutex);
+
    return bytes;
 }
 
@@ -1116,7 +1193,7 @@ int spi_write(unsigned handle, char *buf, unsigned count)
    ext[0].ptr = buf;
 
    return pigpio_command_ext
-      (gPigCommand, PI_CMD_SPIW, handle, 0, count, 1, ext);
+      (gPigCommand, PI_CMD_SPIW, handle, 0, count, 1, ext, 1);
 }
 
 int spi_xfer(unsigned handle, char *txBuf, char *rxBuf, unsigned count)
@@ -1136,13 +1213,16 @@ int spi_xfer(unsigned handle, char *txBuf, char *rxBuf, unsigned count)
    ext[0].ptr = txBuf;
 
    bytes = pigpio_command_ext
-      (gPigCommand, PI_CMD_SPIX, handle, 0, count, 1, ext);
+      (gPigCommand, PI_CMD_SPIX, handle, 0, count, 1, ext, 0);
 
    if (bytes > 0)
    {
       /* get the data */
       recv(gPigCommand, rxBuf, bytes, MSG_WAITALL);
    }
+
+   pthread_mutex_unlock(&command_mutex);
+
    return bytes;
 }
 
@@ -1165,17 +1245,17 @@ int serial_open(char *dev, unsigned baud, unsigned flags)
    ext[0].ptr = dev;
 
    return pigpio_command_ext
-      (gPigCommand, PI_CMD_SERO, baud, flags, len, 1, ext);
+      (gPigCommand, PI_CMD_SERO, baud, flags, len, 1, ext, 1);
 }
 
 int serial_close(unsigned handle)
-   {return pigpio_command(gPigCommand, PI_CMD_SERC, handle, 0);}
+   {return pigpio_command(gPigCommand, PI_CMD_SERC, handle, 0, 1);}
 
 int serial_write_byte(unsigned handle, unsigned val)
-   {return pigpio_command(gPigCommand, PI_CMD_SERWB, handle, val);}
+   {return pigpio_command(gPigCommand, PI_CMD_SERWB, handle, val, 1);}
 
 int serial_read_byte(unsigned handle)
-   {return pigpio_command(gPigCommand, PI_CMD_SERRB, handle, 0);}
+   {return pigpio_command(gPigCommand, PI_CMD_SERRB, handle, 0, 1);}
 
 int serial_write(unsigned handle, char *buf, unsigned count)
 {
@@ -1193,7 +1273,7 @@ int serial_write(unsigned handle, char *buf, unsigned count)
    ext[0].ptr = buf;
 
    return pigpio_command_ext
-      (gPigCommand, PI_CMD_SERW, handle, 0, count, 1, ext);
+      (gPigCommand, PI_CMD_SERW, handle, 0, count, 1, ext, 1);
 }
 
 int serial_read(unsigned handle, char *buf, unsigned count)
@@ -1201,18 +1281,21 @@ int serial_read(unsigned handle, char *buf, unsigned count)
    int bytes;
 
    bytes = pigpio_command
-      (gPigCommand, PI_CMD_SERR, handle, count);
+      (gPigCommand, PI_CMD_SERR, handle, count, 0);
 
    if (bytes > 0)
    {
       /* get the data */
       recv(gPigCommand, buf, bytes, MSG_WAITALL);
    }
+
+   pthread_mutex_unlock(&command_mutex);
+
    return bytes;
 }
 
 int serial_data_available(unsigned handle)
-   {return pigpio_command(gPigCommand, PI_CMD_SERDA, handle, 0);}
+   {return pigpio_command(gPigCommand, PI_CMD_SERDA, handle, 0, 1);}
 
 int callback(unsigned user_gpio, unsigned edge, CBFunc_t f)
    {return intCallback(user_gpio, edge, f, 0, 0);}
index f80bbe752a6ea733154482bcb82e00d574a22e77..4fc199ecebcf5cca19301edb52ce47ab73284209 100644 (file)
@@ -30,7 +30,7 @@ For more information, please refer to <http://unlicense.org/>
 
 #include "pigpio.h"
 
-#define PIGPIOD_IF_VERSION 11
+#define PIGPIOD_IF_VERSION 12
 
 /*TEXT
 
@@ -162,6 +162,9 @@ bb_serial_read_open        Opens a gpio for bit bang serial reads
 bb_serial_read             Reads bit bang serial data from a gpio
 bb_serial_read_close       Closes a gpio for bit bang serial reads
 
+hardware_clock             Start hardware clock on supported gpios
+hardware_PWM               Start hardware PWM on supported gpios
+
 SCRIPTS
 
 store_script               Store a script
@@ -823,6 +826,88 @@ A status of PI_SOME_PERMITTED indicates that the user is not
 allowed to write to one or more of the gpios.
 D*/
 
+
+/*F*/
+int hardware_clock(unsigned gpio, unsigned clkfreq);
+/*D
+Starts a hardware clock on a gpio at the specified frequency.
+
+. .
+     gpio: see description
+frequency: 0 (off) or 4689-250M
+. .
+
+Returns 0 if OK, otherwise PI_NOT_PERMITTED, PI_BAD_GPIO,
+PI_NOT_HCLK_GPIO, PI_BAD_HCLK_FREQ,or PI_BAD_HCLK_PASS.
+
+The same clock is available on multiple gpios.  The latest
+frequency setting will be used by all gpios which share a clock.
+
+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
+21  clock 1  All models but Rev.2 B (reserved for system use)
+
+32  clock 0  Compute module only
+34  clock 0  Compute module only
+42  clock 1  Compute module only (reserved for system use)
+43  clock 2  Compute module only
+44  clock 1  Compute module only (reserved for system use)
+. .
+
+Access to clock 1 is protected by a password as its use will likely
+crash the Pi.  The password is given by or'ing 0x5A000000 with the
+gpio number.
+D*/
+
+
+/*F*/
+int hardware_PWM(unsigned gpio, unsigned PWMfreq, uint32_t PWMduty);
+/*D
+Starts hardware PWM on a gpio at the specified frequency and dutycycle.
+
+NOTE: Any waveform started by [*wave_send_once*], [*wave_send_repeat*], [*wave_tx_start*], or [*wave_tx_repeat*] will be cancelled.
+
+This function is only valid if the pigpio main clock is PCM.  The
+main clock defaults to PCM but may be overridden when the pigpio
+daemon is started (option -t).
+
+. .
+   gpio: see descripton
+PWMfreq: 0 (off) or 5-250K
+PWMduty: 0 (off) to 1000 (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 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
+18  PWM channel 0  All models
+19  PWM channel 1  A+/B+ and compute module only
+
+40  PWM channel 0  Compute module only
+41  PWM channel 1  Compute module only
+45  PWM channel 1  Compute module only
+52  PWM channel 0  Compute module only
+53  PWM channel 1  Compute module only
+. .
+D*/
+
+
 /*F*/
 uint32_t get_current_tick(void);
 /*D
@@ -917,32 +1002,43 @@ D*/
 
 /*F*/
 int wave_add_serial
-   (unsigned user_gpio, unsigned bbBaud, unsigned offset,
-    unsigned numChar, char *str);
+   (unsigned user_gpio, unsigned bbBaud, unsigned bbBits,
+    unsigned bbStop, unsigned offset, unsigned numBytes, char *str);
 /*D
 This function adds a waveform representing serial data to the
-existing waveform (if any).  The serial data starts offset microseconds
-from the start of the waveform.
+existing waveform (if any).  The serial data starts offset
+microseconds from the start of the waveform.
 
 . .
 user_gpio: 0-31.
    bbBaud: 100-250000
+   bbBits: number of data bits (1-32)
+   bbStop: number of stop half bits (2-8)
    offset: 0-
 numChar: 1-
numBytes: 1-
       str: an array of chars.
 . .
 
 Returns the new total number of pulses in the current waveform if OK,
-otherwise PI_BAD_USER_GPIO, PI_BAD_WAVE_BAUD, PI_TOO_MANY_CHARS, or
-PI_TOO_MANY_PULSES.
+otherwise PI_BAD_USER_GPIO, PI_BAD_WAVE_BAUD, PI_BAD_DATABITS,
+PI_BAD_STOP_BITS, PI_TOO_MANY_CHARS, PI_BAD_SER_OFFSET,
+or PI_TOO_MANY_PULSES.
 
 NOTES:
 
-The serial data is formatted as one start bit, eight data bits, and one
-stop bit.
+The serial data is formatted as one start bit, [*bbBits*] data bits,
+and [*bbStop*]/2 stop bits.
 
 It is legal to add serial data streams with different baud rates to
 the same waveform.
+
+[*numBytes*] is the number of bytes of data in str.
+
+The bytes required for each character depend upon [*bbBits*].
+
+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*/
 
 /*F*/
@@ -1017,15 +1113,21 @@ D*/
 /*F*/
 int wave_tx_start(void);
 /*D
-This function is deprecated and should no longer be used.  Use
-[*wave_create*]/[*wave_send_**] instead.
+This function is deprecated and should no longer be used.
+
+Use [*wave_create*]/[*wave_send_**] instead.
+
+NOTE: Any hardware PWM started by [*hardware_PWM*] will be cancelled.
 D*/
 
 /*F*/
 int wave_tx_repeat(void);
 /*D
-This function is deprecated and should no longer be used.  Use
-[*wave_create*]/[*wave_send_**] instead.
+This function is deprecated and should no longer be used.
+
+Use [*wave_create*]/[*wave_send_**] instead.
+
+NOTE: Any hardware PWM started by [*hardware_PWM*] will be cancelled.
 D*/
 
 /*F*/
@@ -1034,6 +1136,8 @@ int wave_send_once(unsigned wave_id);
 This function transmits the waveform with id wave_id.  The waveform
 is sent once.
 
+NOTE: Any hardware PWM started by [*hardware_PWM*] will be cancelled.
+
 . .
 wave_id: >=0, as returned by [*wave_create*].
 . .
@@ -1049,6 +1153,8 @@ This function transmits the waveform with id wave_id.  The waveform
 cycles until cancelled (either by the sending of a new waveform or
 by [*wave_tx_stop*]).
 
+NOTE: Any hardware PWM started by [*hardware_PWM*] will be cancelled.
+
 . .
 wave_id: >=0, as returned by [*wave_create*].
 . .
@@ -1898,6 +2004,26 @@ PI_WAVE_MIN_BAUD 100
 PI_WAVE_MAX_BAUD 250000
 . .
 
+bbBits::1-32
+
+The number of data bits to be used when adding serial data to a
+waveform.
+
+. .
+#define PI_MIN_WAVE_DATABITS 1
+#define PI_MAX_WAVE_DATABITS 32
+. .
+
+bbStop::2-8
+
+The number of (half) stop bits to be used when adding serial data
+to a waveform.
+
+. .
+#define PI_MIN_WAVE_HALFSTOPBITS 2
+#define PI_MAX_WAVE_HALFSTOPBITS 8
+. .
+
 bit::
 A value of 0 or 1.
 
@@ -1935,10 +2061,12 @@ typedef void (*CBFuncEx_t)
    (unsigned user_gpio, unsigned level, uint32_t tick, void * user);
 . .
 
-
 char::
 A single character, an 8 bit quantity able to store 0-255.
 
+clkfreq::4689-250M
+The hardware clock frequency.
+
 count::
 The number of bytes to be transferred in an I2C, SPI, or Serial
 command.
@@ -2050,9 +2178,10 @@ PI_ALT4 3
 PI_ALT5 2
 . .
 
-numChar::
-The number of characters in a string (used when the string might contain
-null characters, which would normally terminate the string).
+numBytes::
+The number of bytes used to store characters in a string.  Depending
+on the number of bits per character there may be 1, 2, or 4 bytes
+per character.
 
 numPar:: 0-10
 The number of parameters passed to a script.
@@ -2103,6 +2232,20 @@ PI_MIN_SERVO_PULSEWIDTH 500
 PI_MAX_SERVO_PULSEWIDTH 2500
 . .
 
+PWMduty::0-1000
+The hardware PWM dutycycle.
+
+. .
+#define PI_HW_PWM_RANGE 1000
+. .
+
+PWMfreq::5-250K
+The hardware PWM frequency.
+
+. .
+#define PI_HW_PWM_MIN_FREQ 5
+#define PI_HW_PWM_MAX_FREQ 250000
+. .
 
 range::25-40000
 The permissible dutycycle values are 0-range.
diff --git a/pigs.1 b/pigs.1
index d9b2917d44879cb53de62b94080ed8cd6b35eeca..5449176180605e4f2f8f05df31e067c96e3d3438 100644 (file)
--- a/pigs.1
+++ b/pigs.1
@@ -419,8 +419,6 @@ ERROR: gpio is not in use for servo pulses
 
 .EE
 
-.br
-This command returns
 .br
 
 .IP "\fBH/HELP \fP - Display command help"
@@ -444,6 +442,140 @@ $ pigs help
 
 .br
 
+.IP "\fBHC g cf\fP - Set hardware clock frequency"
+.IP "" 4
+This command sets the hardware clock associated with gpio \fBg\fP to
+frequency \fBcf\fP.
+
+.br
+Upon success nothing is returned.  On error a negative status code
+will be returned.
+
+.br
+
+\fBExample\fP
+.br
+
+.EX
+$ pigs hc 4 5000 # start a 5 KHz clock on gpio 4 (clock 0)
+.br
+
+.br
+$ pigs hc 5 5000000 # start a 5 MHz clcok on gpio 5 (clock 1)
+.br
+-99
+.br
+ERROR: need password to use hardware clock 1
+.br
+
+.EE
+
+.br
+The same clock is available on multiple gpios.  The latest
+frequency setting will be used by all gpios which share a clock.
+
+.br
+The gpio must be one of the following.
+
+.br
+
+.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)
+
+.EE
+
+.br
+
+.EX
+32  clock 0  Compute module only
+34  clock 0  Compute module only
+42  clock 1  Compute module only (reserved for system use)
+43  clock 2  Compute module only
+44  clock 1  Compute module only (reserved for system use)
+
+.EE
+
+.br
+Access to clock 1 is protected by a password as its use will
+likely crash the Pi.  The password is given by or'ing 0x5A000000
+with the gpio number.
+
+.br
+
+.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.
+
+.br
+NOTE: Any waveform started by \fBWVGO\fP, \fBWVGOR\fP, \fBWVTX\fP or
+\fBWVTXR\fP will be cancelled.
+
+.br
+This function is only valid if the pigpio main clock is PCM.  The
+main clock defaults to PCM but may be overridden when the pigpio
+daemon is started (option -t).
+
+.br
+Upon success nothing is returned.  On error a negative status code
+will be returned.
+
+.br
+
+.EX
+$ pigs hp 18 100 900
+.br
+
+.br
+$ pigs hp 19 100 100
+.br
+
+.br
+$ pigs hp 19 1 100
+.br
+-96
+.br
+ERROR: hardware PWM frequency not 5-250K
+.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.
+
+.br
+The gpio must be one of the following.
+
+.br
+
+.EX
+12  PWM channel 0  A+/B+ and compute module only
+13  PWM channel 1  A+/B+ and compute module only
+18  PWM channel 0  All models
+19  PWM channel 1  A+/B+ and compute module only
+
+.EE
+
+.br
+
+.EX
+40  PWM channel 0  Compute module only
+41  PWM channel 1  Compute module only
+45  PWM channel 1  Compute module only
+52  PWM channel 0  Compute module only
+53  PWM channel 1  Compute module only
+
+.EE
+
+.br
+
 .IP "\fBHWVER \fP - Get hardware version"
 .IP "" 4
 This command returns the hardware revision of the Pi.
@@ -2603,20 +2735,36 @@ $ pigs wvag 0 0 10000 0x10 0x80 1000 0x80 0x10 9000
 
 .br
 
-.IP "\fBWVAS u b o bvs\fP - Add serial data to waveform"
+.IP "\fBWVAS u b db sb o bvs\fP - Add serial data to waveform"
 .IP "" 4
 
 .br
 This command adds a waveform representing serial data \fBbvs\fP to
 gpio \fBu\fP at \fBb\fP baud to the existing waveform (if any).
-The serial data starts \fBo\fP microseconds from the start of the waveform.
+The serial data starts \fBo\fP microseconds from the start of the
+waveform.
 
 .br
 Upon success the total number of pulses in the waveform so far is
 returned.  On error a negative status code will be returned.
 
 .br
-Data with different baud rates may be added to the same wavefrom.
+The serial data is formatted as one start bit, \fBdb\fP data bits, and
+\fBsb\fP/2 stop bits.
+
+.br
+It is legal to add serial data streams with different baud rates to
+the same waveform.
+
+.br
+The bytes required for each character depend upon \fBdb\fP.
+
+.br
+For \fBdb\fP 1-8 there will be one byte per character.
+.br
+For \fBdb\fP 9-16 there will be two bytes per character.
+.br
+For \fBdb\fP 17-32 there will be four bytes per character.
 
 .br
 
@@ -2624,13 +2772,13 @@ Data with different baud rates may be added to the same wavefrom.
 .br
 
 .EX
-$ pigs wvas 4 9600 0 0x30 0x31 0x32 0x33
+$ pigs wvas 4 9600 8 2 0 0x30 0x31 0x32 0x33
 .br
 23
 .br
 
 .br
-$ pigs wvas 7 38400 0 0x41 0x42
+$ pigs wvas 7 38400 8 2 0 0x41 0x42
 .br
 35
 .br
@@ -2808,6 +2956,9 @@ ERROR: non existent wave id
 .br
 This command transmits the current waveform.  The waveform is sent once.
 
+.br
+NOTE: Any hardware PWM started by \fBHP\fP will be cancelled.
+
 .br
 Upon success the number of DMA control blocks in the waveform is returned.
 On error a negative status code will be returned.
@@ -2820,6 +2971,9 @@ On error a negative status code will be returned.
 .br
 This command transmits the current waveform.  The waveform is sent repeatedly.
 
+.br
+NOTE: Any hardware PWM started by \fBHP\fP will be cancelled.
+
 .br
 Upon success the number of DMA control blocks in the waveform is returned.
 On error a negative status code will be returned.
@@ -3003,6 +3157,9 @@ $ pigs wvsp 2
 .br
 This command transmits the waveform with id \fBwid\fP once.
 
+.br
+NOTE: Any hardware PWM started by \fBHP\fP will be cancelled.
+
 .br
 Upon success the number of DMA control blocks in the waveform is returned.
 On error a negative status code will be returned.
@@ -3036,6 +3193,9 @@ ERROR: non existent wave id
 .br
 This command transmits the waveform with id \fBwid\fP repeatedly.
 
+.br
+NOTE: Any hardware PWM started by \fBHP\fP will be cancelled.
+
 .br
 Upon success the number of DMA control blocks in the waveform is returned.
 On error a negative status code will be returned.
@@ -3102,6 +3262,16 @@ The command expects a SPI channel.
 
 .br
 
+.IP "\fBcf\fP - hardware clock frequency (4689-250M)" 0
+The command expects a frequency.
+
+.br
+
+.IP "\fBdb\fP - serial data bits (1-32)" 0
+The command expects the number of data bits per serial character.
+
+.br
+
 .IP "\fBdev\fP - a tty serial device (/dev/tty*)" 0
 The command expects the name of a tty serial device, e.g.
 
@@ -3263,6 +3433,16 @@ 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
+The command expects a dutycycle.
+
+.br
+
+.IP "\fBpf\fP - hardware PWM frequency (5-250K)" 0
+The command expects a frequency.
+
+.br
+
 .IP "\fBpl\fP - pulse length (1-50)" 0
 The command expects a pulse length in microseconds.
 
@@ -3273,6 +3453,11 @@ The command expects an I2C register number.
 
 .br
 
+.IP "\fBsb\fP - serial stop (half) bits (2-8)" 0
+The command expects the number of stop (half) bits per serial character.
+
+.br
+
 .IP "\fBsef\fP - serial flags (32 bits)" 0
 The command expects a flag value.  No serial flags are currently defined.
 
index 32452ba1f841d464458e1f29afaa2a49c4e42454..2791a4fa084334c92df6f44eb29b3c1f00e4a122 100644 (file)
--- a/setup.py
+++ b/setup.py
@@ -3,7 +3,7 @@
 from distutils.core import setup
 
 setup(name='pigpio',
-      version='1.13',
+      version='1.14',
       author='joan',
       author_email='joan@abyz.co.uk',
       maintainer='joan',
index c7f1c888f5178957e915841c309ca96d32f49bec..5c42ad8857e8559e00d7b415dad9c29c425173d3 100644 (file)
@@ -396,7 +396,7 @@ To the lascivious pleasing of a lute.\n\
    CHECK(5, 6, e, 0, 0, "serial read open");
 
    gpioWaveClear();
-   e = gpioWaveAddSerial(GPIO, BAUD, 5000000, strlen(TEXT), TEXT);
+   e = gpioWaveAddSerial(GPIO, BAUD, 8, 2, 5000000, strlen(TEXT), TEXT);
    CHECK(5, 7, e, 3405, 0, "wave clear, wave add serial");
 
    e = gpioWaveTxStart(PI_WAVE_MODE_ONE_SHOT);
@@ -416,10 +416,10 @@ To the lascivious pleasing of a lute.\n\
    CHECK(5, 12, e, 0, 0, "serial read close");
 
    c = gpioWaveGetMicros();
-   CHECK(5, 13, c, 6158704, 0, "wave get micros");
+   CHECK(5, 13, c, 6158148, 0, "wave get micros");
 
    c = gpioWaveGetHighMicros();
-   CHECK(5, 14, c, 6158704, 0, "wave get high micros");
+   CHECK(5, 14, c, 6158148, 0, "wave get high micros");
 
    c = gpioWaveGetMaxMicros();
    CHECK(5, 15, c, 1800000000, 0, "wave get max micros");
index 3f0f4acd33243a43d2aa19a41b76464760179980..0faa461fe573274df398df06f52cecee04865c34 100755 (executable)
@@ -371,7 +371,7 @@ To the lascivious pleasing of a lute.
    CHECK(5, 6, e, 0, 0, "serial read open")
 
    pi.wave_clear()
-   e = pi.wave_add_serial(GPIO, BAUD, 5000000, TEXT)
+   e = pi.wave_add_serial(GPIO, BAUD, TEXT, 5000000)
    CHECK(5, 7, e, 3405, 0, "wave clear, wave add serial")
 
    e = pi.wave_tx_start()
@@ -396,7 +396,7 @@ To the lascivious pleasing of a lute.
    CHECK(5, 12, e, 0, 0, "serial read close")
 
    c = pi.wave_get_micros()
-   CHECK(5, 13, c, 6158704, 0, "wave get micros")
+   CHECK(5, 13, c, 6158148, 0, "wave get micros")
 
    CHECK(5, 14, 0, 0, 0, "NOT APPLICABLE")
 
@@ -439,7 +439,7 @@ To the lascivious pleasing of a lute.
    e = pi.wave_tx_stop()
    CHECK(5, 27, e, 0, 0, "wave tx stop")
 
-   e = pi.wave_add_serial(GPIO, BAUD, 5000000, TEXT)
+   e = pi.wave_add_serial(GPIO, BAUD, TEXT, 5000000)
    CHECK(5, 28, e, 3405, 0, "wave add serial")
 
    w2 = pi.wave_create()
index 82340094aa68c85c1f3fbbcbbbde069dd2711fd3..a0d7a301da4f994d8e19420184b27d90712afc86 100644 (file)
@@ -1,6 +1,6 @@
 /*
 gcc -o x_pigpiod_if x_pigpiod_if.c -lpigpiod_if -lrt -lpthread
-sudo ./x_pigpiod_if
+./x_pigpiod_if
 
 *** WARNING ************************************************
 *                                                          *
@@ -370,7 +370,7 @@ To the lascivious pleasing of a lute.\n\
    CHECK(5, 6, e, 0, 0, "serial read open");
 
    wave_clear();
-   e = wave_add_serial(GPIO, BAUD, 5000000, strlen(TEXT), TEXT);
+   e = wave_add_serial(GPIO, BAUD, 8, 2, 5000000, strlen(TEXT), TEXT);
    CHECK(5, 7, e, 3405, 0, "wave clear, wave add serial");
 
    e = wave_tx_start();
@@ -395,11 +395,11 @@ To the lascivious pleasing of a lute.\n\
    CHECK(5, 12, e, 0, 0, "serial read close");
 
    c = wave_get_micros();
-   CHECK(5, 13, c, 6158704, 0, "wave get micros");
+   CHECK(5, 13, c, 6158148, 0, "wave get micros");
 
    c = wave_get_high_micros();
-   if (c >= 6158704) c = 6158704;
-   CHECK(5, 14, c, 6158704, 0, "wave get high micros");
+   if (c > 6158148) c = 6158148;
+   CHECK(5, 14, c, 6158148, 0, "wave get high micros");
 
    c = wave_get_max_micros();
    CHECK(5, 15, c, 1800000000, 0, "wave get max micros");
diff --git a/x_pigs b/x_pigs
index a46ed26550cb8945f928ba4bbfa7202e21b3718b..db1b82d1b4973e864d6d58ccba969445dcbbc0c9 100755 (executable)
--- a/x_pigs
+++ b/x_pigs
@@ -1,6 +1,6 @@
 #!/bin/bash
 
-VERSION=23
+VERSION=24
 
 GPIO=4
 
@@ -46,7 +46,7 @@ s=$(pigs bs2 0)
 if [[ $s = "" ]]; then echo "BS2 ok"; else echo "BS2 fail ($s)"; fi
 
 s=$(pigs h)
-if [[ ${#s} = 4778 ]]; then echo "HELP ok"; else echo "HELP fail (${#s})"; fi
+if [[ ${#s} = 5150 ]]; then echo "HELP ok"; else echo "HELP fail (${#s})"; fi
 
 s=$(pigs hwver)
 if [[ $s -ne 0 ]]; then echo "HWVER ok"; else echo "HWVER fail ($s)"; fi
@@ -191,7 +191,7 @@ s=$(pigs wvclr)
 if [[ $s = "" ]]; then echo "SLR-a ok"; else echo "SLR-a fail ($s)"; fi
 s=$(pigs slro $GPIO 1200)
 if [[ $s = "" ]]; then echo "SLR-b ok"; else echo "SLR-b fail ($s)"; fi
-s=$(pigs wvas $GPIO 1200 0 0x6d 0x79 0x20 0x6e 0x61 0x6d 0x65 0x20 0x69 0x73 0x20 0x6a 0x6f 0x61 0x6e)
+s=$(pigs wvas $GPIO 1200 8 2 0 0x6d 0x79 0x20 0x6e 0x61 0x6d 0x65 0x20 0x69 0x73 0x20 0x6a 0x6f 0x61 0x6e)
 if [[ $s = 95 ]]; then echo "SLR-c ok"; else echo "SLR-c fail ($s)"; fi
 s=$(pigs m $GPIO w)
 if [[ $s = "" ]]; then echo "SLR-d ok"; else echo "SLR-d fail ($s)"; fi
@@ -242,7 +242,7 @@ if [[ $s = 0 ]]; then echo "WRITE-d ok"; else echo "WRITE-d fail ($s)"; fi
 
 s=$(pigs wvclr )
 if [[ $s = "" ]]; then echo "WVCLR ok"; else echo "WVCLR fail ($s)"; fi
-s=$(pigs wvas $GPIO 300 0 0x74 0x68 0x69 0x73 0x20 0x69 0x73 0x20 0x74 0x68 0x65 0x6e 0x20 0x77 0x69 0x6e 0x74 0x65 0x72 0x20 0x6f 0x66 0x20 0x6d 0x79 0x20 0x64 0x69 0x73 0x63 0x6f 0x6e 0x74 0x65 0x6e 0x74 0x20 0x6d 0x61 0x64 0x65 0x20 0x67 0x6c 0x6f 0x72 0x69 0x6f 0x75 0x73)
+s=$(pigs wvas $GPIO 300 8 2 0 0x74 0x68 0x69 0x73 0x20 0x69 0x73 0x20 0x74 0x68 0x65 0x6e 0x20 0x77 0x69 0x6e 0x74 0x65 0x72 0x20 0x6f 0x66 0x20 0x6d 0x79 0x20 0x64 0x69 0x73 0x63 0x6f 0x6e 0x74 0x65 0x6e 0x74 0x20 0x6d 0x61 0x64 0x65 0x20 0x67 0x6c 0x6f 0x72 0x69 0x6f 0x75 0x73)
 if [[ $s = 309 ]]; then echo "WVAS ok"; else echo "WVAS fail ($s)"; fi
 s=$(pigs wvag 16 0 5000000 0 16 5000000)
 if [[ $s = 310 ]]; then echo "WVAG ok"; else echo "WVAG fail ($s)"; fi
diff --git a/x_pipe b/x_pipe
index b4aa471520e9d5e714656c377aef3b4f91e0b1cb..6d9dafc3d4c1bfd6bf794a851957ac23d07481ec 100755 (executable)
--- a/x_pipe
+++ b/x_pipe
@@ -1,6 +1,6 @@
 #!/bin/bash
 
-VERSION=23
+VERSION=24
 
 GPIO=4
 
@@ -261,7 +261,7 @@ if [[ $s = 0 ]]; then echo "SLR-a ok"; else echo "SLR-a fail ($s)"; fi
 echo "slro $GPIO 1200" >/dev/pigpio
 read -t 1 s </dev/pigout
 if [[ $s = 0 ]]; then echo "SLR-b ok"; else echo "SLR-b fail ($s)"; fi
-echo "wvas $GPIO 1200 0 0x6d 0x79 0x20 0x6e 0x61 0x6d 0x65 0x20 0x69 0x73 0x20 0x6a 0x6f 0x61 0x6e" >/dev/pigpio
+echo "wvas $GPIO 1200 8 2 0 0x6d 0x79 0x20 0x6e 0x61 0x6d 0x65 0x20 0x69 0x73 0x20 0x6a 0x6f 0x61 0x6e" >/dev/pigpio
 read -t 1 s </dev/pigout
 if [[ $s = 95 ]]; then echo "SLR-c ok"; else echo "SLR-c fail ($s)"; fi
 echo "m $GPIO w" >/dev/pigpio
@@ -330,7 +330,7 @@ if [[ $s = 0 ]]; then echo "WRITE-d ok"; else echo "WRITE-d fail ($s)"; fi
 echo "wvclr" >/dev/pigpio
 read -t 1 s </dev/pigout
 if [[ $s = 0 ]]; then echo "WVCLR ok"; else echo "WVCLR fail ($s)"; fi
-echo "wvas $GPIO 300 0 0x74 0x68 0x69 0x73 0x20 0x69 0x73 0x20 0x74 0x68 0x65 0x20 0x77 0x69 0x6e 0x74 0x65 0x72 0x20 0x6f 0x66 0x20 0x6d 0x79 0x20 0x64 0x69 0x73 0x63 0x6f 0x6e 0x74 0x65 0x6e 0x74" >/dev/pigpio
+echo "wvas $GPIO 300 8 2 0 0x74 0x68 0x69 0x73 0x20 0x69 0x73 0x20 0x74 0x68 0x65 0x20 0x77 0x69 0x6e 0x74 0x65 0x72 0x20 0x6f 0x66 0x20 0x6d 0x79 0x20 0x64 0x69 0x73 0x63 0x6f 0x6e 0x74 0x65 0x6e 0x74" >/dev/pigpio
 read -t 1 s </dev/pigout
 if [[ $s = 215 ]]; then echo "WVAS ok"; else echo "WVAS fail ($s)"; fi
 echo "wvag 16 0 5000000 0 16 5000000" >/dev/pigpio