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