*/
/*
-This version is for pigpio version 23+
+This version is for pigpio version 24+
*/
#include <stdio.h>
{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
\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\
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\
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\
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\
{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"},
{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"},
{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)"},
{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"},
+
};
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;
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.
break;
- case 131: /* I2CO I2CPC I2CRI I2CWB I2CWW SPIO TRIG
+ case 131: /* HP I2CO I2CPC I2CRI I2CWB I2CWW SPIO TRIG
Three positive parameters.
*/
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);
else break;
}
- p[3] = pars + 4;
+ p[3] = pars + 12;
if (pars > 0) valid = 1;
}
.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
.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
.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
.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
.br
.br
-gpioWaveAddSerial(4, 9600, 0, strlen(str), str);
+gpioWaveAddSerial(4, 9600, 8, 2, 0, strlen(str), str);
.br
.br
.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
.br
+.br
+NOTE: Any hardware PWM started by \fBgpioHardwarePWM\fP will be cancelled.
+
+.br
+
.br
.EX
.br
+.br
+NOTE: Any hardware PWM started by \fBgpioHardwarePWM\fP will be cancelled.
+
+.br
+
.br
.EX
.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
.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
.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.
.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
.br
cfgPeripheral: 0 (PWM), 1 (PCM)
.br
- cfgSource: 0 (OSC), 1 (PLLD)
+ cfgSource: deprecated, value is ignored
.br
.EE
.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
.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
.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
.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
.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
.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
#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
.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
.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
.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
.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
.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
.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
.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
.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
For more information, please refer to <http://unlicense.org/>
*/
-/* pigpio version 23 */
+/* pigpio version 24 */
#include <stdio.h>
#include <string.h>
#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)
#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
#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)
#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) ();
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
unsigned bufferMilliseconds;
unsigned clockMicros;
unsigned clockPeriph;
- unsigned clockSource;
unsigned DMAprimaryChannel;
unsigned DMAsecondaryChannel;
unsigned socketPort;
union my_smbus_data *data;
};
+typedef struct
+{
+ unsigned div;
+ unsigned frac;
+ unsigned clock;
+} clkInf_t;
+
/* --------------------------------------------------------------- */
/* initialise once then preserve */
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,
/* initialise every gpioInitialise */
static struct timespec libStarted;
+static int waveClockInited = 0;
/* initialse if not libInitialised */
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];
/* 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]=
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);
/* ======================================================================= */
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);
}
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;
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;
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;
res = spiXfer(p[1], buf, buf, p[3]);
break;
-
-
case PI_CMD_TICK: res = gpioTick(); break;
case PI_CMD_TRIG:
}
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;
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",
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
{
/* ----------------------------------------------------------------------- */
-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;
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);
/* ======================================================================= */
+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;
static void initPWM(unsigned bits)
{
- DBG(DBG_STARTUP, "");
+ DBG(DBG_STARTUP, "bits=%d", bits);
/* reset PWM */
static void initPCM(unsigned bits)
{
- DBG(DBG_STARTUP, "");
+ DBG(DBG_STARTUP, "bits=%d", bits);
/* disable PCM so we can modify the regs */
/* ----------------------------------------------------------------------- */
+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;
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);
}
/* 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;
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;
unsigned port;
struct sched_param param;
+ waveClockInited = 0;
clock_gettime(CLOCK_REALTIME, &libStarted);
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);
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;
}
reg = gpio/10;
shift = (gpio%10) * 3;
- return (*(gpioReg + reg) >> shift) & 7;
+ return (gpioReg[reg] >> shift) & 7;
}
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;
}
}
{
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;
}
if (gpio > PI_MAX_USER_GPIO)
SOFT_ERROR(PI_BAD_USER_GPIO, "bad gpio (%d)", gpio);
- return (gpioInfo[gpio].range);
+ return gpioInfo[gpio].range;
}
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];
}
{
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;
}
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;
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++;
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;
/* 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;
}
}
{
/* This function is deprecated and will be removed. */
- static int secondaryClockInited = 0;
-
int cb, i;
DBG(DBG_USER, "wave_mode=%d", 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;
{
rawCbs_t *p=NULL;
- static int secondaryClockInited = 0;
-
DBG(DBG_USER, "wave_id=%d wave_mode=%d", wave_id, wave_mode);
CHECK_INITED;
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);
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);
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;
+}
+
/* ----------------------------------------------------------------------- */
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;
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;
}
#include <stdint.h>
#include <pthread.h>
-#define PIGPIO_VERSION 23
+#define PIGPIO_VERSION 24
/*TEXT
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
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
} 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 *);
#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)
#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 */
#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
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
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*/
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)
. .
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)
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.
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.
...
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);
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:
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::
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::
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
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
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
#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*/
#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
#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
#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)
#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*/
#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
"""
-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
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.
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
import os
import atexit
-VERSION = "1.13"
+VERSION = "1.14"
exceptions = True
_PI_CMD_GDC =83
_PI_CMD_GPW =84
-
+_PI_CMD_HC =85
+_PI_CMD_HP =86
_PI_CMD_NOIB= 99
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
[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"],
[_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"],
[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"],
[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"],
]
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))
...
"""
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))
"""
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.
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
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))
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))
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.
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.
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.
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.
byte_val: 0-255
A whole number.
+ clkfreq: 4689-250M
+ The hardware clock frequency.
+
count:
The number of bytes of data to be transferred.
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.
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.
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.
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.
*/
/*
-This version is for pigpio version 14+
+This version is for pigpio version 24+
*/
#include <sys/types.h>
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;
" -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" \
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;
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)
gpioCfgBufferSize(bufferSizeMilliseconds);
- gpioCfgClock(clockMicros, clockPeripheral, clockSource);
+ gpioCfgClock(clockMicros, clockPeripheral, 0);
gpioCfgInterfaces(ifFlags);
return 0;
}
+
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.
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
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
.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
.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
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
.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
.br
+.br
+NOTE: Any hardware PWM started by \fBhardware_PWM\fP will be cancelled.
+
+.br
+
.br
.EX
.br
+.br
+NOTE: Any hardware PWM started by \fBhardware_PWM\fP will be cancelled.
+
+.br
+
.br
.EX
.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.
.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
.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
.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
For more information, please refer to <http://unlicense.org/>
*/
-/* PIGPIOD_IF_VERSION 11 */
+/* PIGPIOD_IF_VERSION 13 */
#include <stdio.h>
#include <stdlib.h>
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;
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;
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;
}
if (bits != gNotifyBits)
{
gNotifyBits = bits;
- pigpio_command(gPigCommand, PI_CMD_NB, gPigHandle, gNotifyBits);
+ pigpio_command(gPigCommand, PI_CMD_NB, gPigHandle, gNotifyBits, 1);
}
}
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
{
if (gPigHandle >= 0)
{
- pigpio_command(gPigNotify, PI_CMD_NC, gPigHandle, 0);
+ pigpio_command(gPigNotify, PI_CMD_NC, gPigHandle, 0, 1);
gPigHandle = -1;
}
{
if (gPigHandle >= 0)
{
- pigpio_command(gPigCommand, PI_CMD_NC, gPigHandle, 0);
+ pigpio_command(gPigCommand, PI_CMD_NC, gPigHandle, 0, 1);
gPigHandle = -1;
}
}
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)
{
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];
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)
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)
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)
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)
{
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];
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;
}
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];
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];
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];
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(
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;
}
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];
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;
}
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];
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;
}
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)
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;
}
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)
{
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)
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);}
#include "pigpio.h"
-#define PIGPIOD_IF_VERSION 11
+#define PIGPIOD_IF_VERSION 12
/*TEXT
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
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
/*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*/
/*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*/
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*].
. .
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*].
. .
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.
(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.
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.
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.
.EE
-.br
-This command returns
.br
.IP "\fBH/HELP \fP - Display command 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.
.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
.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
.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.
.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.
.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.
.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.
.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.
.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.
.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.
from distutils.core import setup
setup(name='pigpio',
- version='1.13',
+ version='1.14',
author='joan',
author_email='joan@abyz.co.uk',
maintainer='joan',
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);
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");
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()
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")
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()
/*
gcc -o x_pigpiod_if x_pigpiod_if.c -lpigpiod_if -lrt -lpthread
-sudo ./x_pigpiod_if
+./x_pigpiod_if
*** WARNING ************************************************
* *
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();
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");
#!/bin/bash
-VERSION=23
+VERSION=24
GPIO=4
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
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
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
#!/bin/bash
-VERSION=23
+VERSION=24
GPIO=4
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
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