Revision history for Perl extension WiringPi::API.
3.1802 UNREL
- Switched from using die() to croak()
- Completely rewrote the C pin interrupt routine to fix a bug where
multiple interrupts did not work correctly
- Update required version of wiringPi to 3.18
- Fixed broken camelCase exports that resolved to no XS sub:
wpiToGpio -> wpiPinToGpio, lcdDefChar -> lcdCharDef,
lcdPutChar -> lcdPutchar
- Implemented wiringPiVersion(), which was exported but never defined;
added wiringpi_version() returning the wiringPi library version (the
string in scalar context, a (major, minor) pair in list context)
- Added t/20-board_map_precheck.t validating the phys/wpi/gpio pin maps
against the installed wiringPi, and t/25-wiringpi_version.t
- Aligned XS prototypes with the wiringPi 3.18 headers: lcdSendCommand()
second arg char -> unsigned char, and digitalReadByte() return type
int -> unsigned int
- Makefile.PL: corrected the stale "version 2.36+" message to report the
actual minimum required wiringPi version (3.18)
- Bumped $VERSION 2.3617 -> 3.1801 (note: 2.x -> 3.x scheme change for
downstream version pins); refreshed POD/README version references from
2.36 to 3.18 and updated the copyright year
- BREAKING: removed setup_sys()/setup_phys() and the backing
wiringPiSetupSys()/wiringPiSetupPhys() XS wraps; only setup() and
setup_gpio() remain supported
- Added Perl wrappers + exports + POD for XS subs that previously had no
Perl layer: soft_pwm_create/soft_pwm_write/soft_pwm_stop,
pi_lock/pi_unlock, and digital_read_byte/digital_read_byte2/
digital_write_byte/digital_write_byte2 (the byte-bank ops are
unsupported on the Raspberry Pi 5 - see POD)
- Wrapped the timing/scheduling core: delay, delayMicroseconds
(delay_microseconds), millis, micros, piMicros64 (pi_micros64) and
piHiPri (pi_hi_pri) - XS + Perl + POD
- Implemented the previously-unimplemented setPadDrive (set_pad_drive),
setPadDrivePin (set_pad_drive_pin), pwmToneWrite (pwm_tone_write) and
gpioClockSet (gpio_clock_set) - XS + Perl + POD
- Wrapped board/identity helpers: piBoardId (pi_board_id, returns a list
or hashref), piBoard40Pin (pi_board40_pin), piRP1Model (pi_rp1_model),
getPinModeAlt (get_pin_mode_alt), wiringPiGlobalMemoryAccess
(wiringpi_global_memory_access) and wiringPiUserLevelAccess
(wiringpi_user_level_access) - XS + Perl + POD
- Wrapped the 3.3 setup variants wiringPiSetupPinType
(wiringpi_setup_pin_type) and wiringPiSetupGpioDevice
(wiringpi_setup_gpio_device, libgpiod char-device backend) plus
wiringPiGpioDeviceGetFd (wiringpi_gpio_device_get_fd); added the
WPI_PIN_BCM / WPI_PIN_WPI constants (new :constants export tag). The
wrappers croak on anything but BCM/WPI - physical-pin setup stays
unsupported (WPI_PIN_PHYS is not exported)
- Wrapped the I2C block/raw additions: i2c_read_block
(wiringPiI2CReadBlockData), i2c_raw_read (wiringPiI2CRawRead),
i2c_write_block (wiringPiI2CWriteBlockData) and i2c_raw_write
(wiringPiI2CRawWrite) - reads return a list of bytes, writes take an
array reference; up to 255 bytes
- Implemented i2c_interface() (maps to wiringPiI2CSetupInterface); it
previously croaked "not available"
- Wrapped the SPI additions: spi_get_fd (wiringPiSPIGetFd),
spi_setup_mode (wiringPiSPISetupMode) and spi_close (wiringPiSPIClose)
- XS + Perl + POD
- Wrapped softTone: soft_tone_create (softToneCreate), soft_tone_write
(softToneWrite) and soft_tone_stop (softToneStop) - XS + Perl + POD.
softServo is not built into the wiringPi 3.18 library, so it is not
wrapped
- Fixed i2c_read_word() to read a 16-bit register (wiringPiI2CReadReg16)
instead of an 8-bit one; it now returns the full word (return value
changes for callers that relied on the truncated value)
- Fixed i2c_setup() address validation: it rejected any multi-digit
address (e.g. 72 / 0x48); it now accepts full decimal and 0x-hex
addresses and croaks on non-numeric input
- Fixed shift_reg_setup() range guards: the && in the bounds checks
could never be true, so out-of-range $num_pins (0-32) and pin
numbers (0-40) were silently passed through; they now croak
- XS serialGets() and spiDataRW() now croak() on error instead of
calling exit(), which killed the whole interpreter; the errors are
now catchable. Replaced the spiDataRW() variable-length stack array
with a heap buffer (Newx/Safefree)
- Moved #define PERL_NO_GET_CONTEXT above the perl headers so the
context optimisation actually applies (it was a no-op after the
include) - internal build change, no consumer-visible effect
- lcd_char_def() no longer writes a stray newline to the display
before defining the character (visible only if a consumer relied on
that side effect)
- Removed a duplicate pwm_set_range entry from the export list
(internal; pwm_set_range is still exported and unchanged)
- Removed the dead testChar export: it was listed in @EXPORT_OK /
:all / :perl but backed by no XS or Perl sub (importing succeeded,
calling it died). An :all or explicit import of testChar now fails
at use-time instead
- Added interrupt edge constants INT_EDGE_SETUP / INT_EDGE_FALLING /
INT_EDGE_RISING / INT_EDGE_BOTH (exported via :constants and :all)
- set_interrupt() now validates its arguments and croaks on bad input:
$pin must be a positive integer, $edge must be INT_EDGE_FALLING (1),
INT_EDGE_RISING (2) or INT_EDGE_BOTH (3), and $callback must be a
CODE reference
- Wrapped wiringPiISRStop($pin) to stop/remove an armed interrupt
(exported via :wiringPi and :all)
- Reworked the interrupt subsystem to use wiringPi's wiringPiISR2()
with a self-pipe: the wiringPi ISR thread now writes a fixed event
record to a pipe instead of calling a Perl callback from a foreign
thread, removing the per-pin trampolines and the dispatcher thread
(eliminates the cross-thread callback races). Added interrupt_fd()
returning the readable end of the pipe; the Perl-side dispatch
helpers (wait_interrupts/dispatch_interrupts) follow
- Removed the camelCase setInterrupt export (use set_interrupt()) and
the dead, never-exposed initThread
- Added the interrupt dispatch helpers: dispatch_interrupts() drains all
pending events from the self-pipe and runs each pin's callback with
($edge, $timestamp_us); wait_interrupts($timeout_ms) selects on the
interrupt fd then dispatches. set_interrupt() callbacks fire again,
now in whichever interpreter services the fd. Added interrupt_dropped()
returning the count of events lost to a full pipe
- Added interrupt teardown: stop_interrupt($pin) stops the wiringPi ISR
for that pin and forgets its callback; stop_interrupts() stops every
armed pin, closes the self-pipe and resets state (a later
set_interrupt() re-creates it). No dispatcher thread to join
- set_interrupt() takes an optional 4th argument $debounce_us (default 0)
passed through to wiringPiISR2(); rewrote the INTERRUPT FUNCTIONS POD
for the self-pipe dispatch model (no threaded Perl required) and fixed
pre-existing POD errors (the ADC FUNCTIONS / digitalReadByte internal
links and stray whitespace) so podchecker is clean
- Added t/75-interrupts.t: hardware-free coverage of the constants,
set_interrupt() validation and dispatch routing on every run, plus
real-GPIO exercisers (both numbering schemes, re-arm, fork background,
teardown) gated behind PI_BOARD. Verified the full interrupt chain on
Pi 5 hardware with no leaks or fd leaks attributable to the module
- Added background_interrupt($pin, $edge, $callback, $debounce_us): forks
a child that arms the interrupt and runs $callback on each edge, for
fire-while-busy handling with one call. Returns a handle with stop/pid/
running; stop() is idempotent, a DESTROY + END block reap the child so
a forgotten stop() can't leak a zombie. Args validated before forking
- Added auto_dispatch_interrupts($bool): puts the interrupt fd into async
(SIGIO) mode and installs a $SIG{IO} handler so set_interrupt()
callbacks fire automatically in-process with no dispatch loop; runs at
Perl safe points (lock-free shared state); disable restores the prior
handler. Both verified on Pi 5 hardware
- Added last_interrupt(): returns a hashref {pin, pin_bcm, edge, status,
ts_us} for the most recently dispatched event (undef if none), so a
callback - which only receives ($edge, $ts_us) - can obtain the BCM pin
and status. The self-pipe record widened to carry wfiStatus.pinBCM and
wfiStatus.statusOK (now a 24-byte {pin, pin_bcm, edge, status, ts}
record); the callback signature is unchanged
- Added interrupt_buffer([$bytes]): get/set the self-pipe capacity
(F_GETPIPE_SZ/F_SETPIPE_SZ). May be set before arming (applied when the
pipe is created) and persists across stop_interrupts(). Documented the
overflow policy in the interrupt_dropped() POD: edges FIFO-queue and,
on a full pipe, are dropped (not merged, not blocked) and counted - so
loss is never silent
- Added run_interrupt_loop($timeout_ms, $max) and stop_interrupt_loop():
a blocking dispatch loop so you needn't write "wait_interrupts while 1"
yourself. Returns the total dispatched; stops on stop_interrupt_loop()
(callback/signal-safe) or after $max events; sleeps rather than
busy-spinning when nothing is armed
- background_interrupt() gained an optional trailing options hashref; the
{results => 1} option ships the callback's defined return value back to
the parent over a length-framed pipe, drained via the handle's read()
(non-blocking) / fh() (for select). Default behaviour is unchanged
- Added background_interrupts([$pin,$edge,$cb,$deb], ...): one shared
background child services many pins (instead of one child per pin). The
handle adds arm($pin)/disarm($pin) over a control pipe (callbacks are
fixed at fork time; the control channel toggles the registered set)
- auto_dispatch_interrupts() now takes an optional second argument, the
delivery signal (default SIGIO). A named signal (eg 'USR1') is wired
via F_SETSIG so it won't clash with other SIGIO/O_ASYNC users
- set_interrupt() now accepts an optional trailing options hashref; the
{auto_dispatch => 1} (or {auto_dispatch => 'USR1'}) option turns on
auto-dispatch as part of arming (the process-wide switch)
- Added lib/WiringPi/API/INTERRUPTS.pod (perldoc WiringPi::API::INTERRUPTS):
a complete, runnable guide to the interrupt API (cooperative dispatch,
hands-off auto_dispatch/background, the shared-child and results
channels, queue sizing, and the code flow)
- Fixed a heap buffer overflow in serial_gets(): the Perl wrapper passed
a zero-length scalar that the XS serialGets() then wrote up to $nbytes
into. serialGets() is now a self-allocating XSUB (Newx/Safefree) that
returns the exact bytes read; serial_gets() is binary-safe (embedded
NULs and trailing whitespace preserved - no more unpack "A*") and
validates its arguments. serialGets() also clears O_NONBLOCK on the fd
so the port's VTIME read timeout applies (short/idle reads return the
partial data instead of spuriously failing), and croaks on a read
error. Documented serial_gets() in the POD (it was exported but
previously undocumented)
- Hardened the XS spiDataRW() (backing spi_data()): each av_fetch() is
now NULL-checked so a sparse or undefined element in the data aref
croaks cleanly instead of crashing, each byte is converted once
(was twice), and the function was rewritten as an idiomatic PPCODE
XSUB (dropping the plagued dXSARGS-in-plain-C + PL_markstack_ptr
juggling). Behaviour for valid input is unchanged - it still returns
a list of the bytes read
- Fixed an out-of-bounds read in physPinToWpi() (and the phys_to_wpi()
wrapper): it indexed the 64-entry phys_wpi_map with no bounds check,
so a physical pin number below 0 or above 63 read past the array.
Out-of-range input now returns the -1 "no such pin" sentinel; the
Perl wrapper mirrors the guard (and treats undef/non-integer as -1).
Added t/80-phys_to_wpi_bounds.t
- Added worker($body, \%opts): forks a child that runs $body repeatedly
in the background (no "use threads", no threaded Perl needed), for
hands-off background GPIO work. Returns a WiringPi::API::Worker handle
with idempotent stop/pid/running; a DESTROY + END block reap the child
so a forgotten stop() can't leak a zombie. $body is validated to be a
CODE reference before forking
- worker() gained {results => 1} and {shared => 1} options that ship
$body's defined return value back to the parent over a length-framed
pipe. {results} streams every value, drained via the handle's read()
(non-blocking) / fh() (for select); {shared} keeps only the latest
value (lossy, non-blocking child write) read via the handle's value().
Default behaviour is unchanged
- worker() gained {interval => $secs} (the helper paces the loop, so the
body needs no sleep of its own) and {once => 1} (run the body exactly
once, then the child exits and running() goes false). interval is
validated to be a positive number before forking; stop() stays
responsive during an interval sleep
- worker() gained {mechanism => 'fork'|'thread'} (default 'fork'). The
opt-in 'thread' mechanism runs the body in an ithread for shared-memory
ergonomics; it croaks clearly if threads is not loaded, and rejects the
{results}/{shared} pipe channels (use a shared variable with pi_lock).
threads::shared is required only on this path - the module never loads
threads itself and stays usable on non-threaded Perl
- pi_lock()/pi_unlock() now validate the lock key (0..3) and croak on a
bad key, instead of passing it through to the XS layer unchecked
- Documented the worker concurrency API in the POD: a new "CONCURRENCY /
BACKGROUND WORKERS" section covering worker(), all its options, the
handle, the setup-once-in-main contract and a hands-off one-liner, plus
a cross-link from THREAD/LOCK FUNCTIONS
- Added t/85-worker.t covering worker(): argument-validation croaks,
pi_lock/pi_unlock key validation, handle lifecycle (pid/running/
idempotent stop), child reaping, the {results}/{shared} channels and
{once}/{interval} pacing off-Pi, plus a PI_BOARD-gated block driving a
real pin through a worker (self-skips without hardware)
- background_interrupts() handle now rejects read()/fh() with a clear
message instead of silently returning undef: the shared-child handle
has no per-pin results channel (that is the singular
background_interrupt({results => 1}) contract). The methods were only
inherited from the lifecycle base class, never part of the documented
plural surface
- t/pod-coverage.t whitelists the undocumented C-wrapper subs via
Pod::Coverage trustme so the author test passes; remove each name as
its POD is written
- Split the background interrupt/worker handle classes
(WiringPi::API::BackgroundInterrupt, ::BackgroundInterrupts, ::Worker,
::WorkerThread) out of API.pm into their own lib files, each with its
own POD; API.pm now use()s them
- Reorganized the @wpi_c_functions and @wpi_perl_functions export lists
into labelled groups (setup and pin ops first, then alphabetical),
and expanded the EXPORT_OK POD to list every Perl wrapper in the same
grouping
- pin_mode_alt() now accepts ALT6-ALT8 (8-10) on the Pi 5 (RP1), where
wiringPi supports them; the 0-7 range is unchanged on a Pi 0-4. Added
POD documenting the RP1 alt-function differences and t/90-pin_mode_alt.t
- Source all constants from RPi::Const (now a prerequisite, min 1.05)
instead of defining them locally; the :constants/:all tags re-export
them, so every existing name (WPI_PIN_*, INT_EDGE_*) is unchanged
2.3616 2018-03-27
- merged PR#34; Ensure that one test always runs if PI_BOARD (Thanks
for the pull request James Keenan!)
- added check in Makefile.PL to ensure that we're on version 2.36+ of
wiringPi
2.3615 2018-03-23
- added graceful exit from Makefile.PL if wiringPi header file is not
found (closes #33)(Thanks James Keenan for the report)
- EXPORT_TAGS POD did not include all tags (fixes #32)
2.3614 2017-07-08
- added t/15-wpi_to_gpio.t to test #12
- exposed pwm_set_range(), had missed that one previously
- exposed pwm_set_clock(), maps to pwmSetClock(int divisor) (closes #30)
- implemented/exposed pwm_set_mode() to set the PWM mode
- added "PROTOTYPES: DISABLE" to XS file to quell warning (closes #31)
- added test/sg_servo.pl as an example of the new PWM capabilities (full
tests will be run via RPi::WiringPi auto test platform)
2.3613 2017-07-01
- integrated wiringSerial, providing basic serial interface support
2.3612 2017-06-24
- added pin_mode_alt() due to an issue found in RPi::WiringPi. Upon
that module's cleanup() routine, we need to ensure all pins are back
to real default
- in relation to stevieb9/rpi-lcd#6, added a warning in lcd_init() POD
to always check the return value of the function for a -1 error, else
if you continue on, the code will segfault
2.3611 2017-06-23
- fix i2c_read_word(). It had the same issue with not sending $data in
as i2c_write_word() did in the last releases Changes entry
- the issue in the last release regarding Arduino I2C comms has been
solved. See the forum post update in the last entry
2.3610_02 2017-06-22
- updated Changes with proper date
- removed all traces of Software PWM from code and documentation, as
even Gordon himself advises not to use it
- added file information and copyright to the .h and .xs files
- fix bug in i2c_write_word(), $data param wasn't being sent in, which
resulted in an argument error being thrown from the wiringPi
library
- putting out as a trial. There are issues with RPi to Arduino I2C
comms...
(see https://www.raspberrypi.org/forums/viewtopic.php?f=33&t=186661)
2.3609 2017-03-26
- fix unicode POD error
- fix declaration issue for digitalReadByte2()
- add a 0.02 second delay in pull_up_down(), as it wasn't returning
fast enough to re-init the pin (this broke interrupts)
2.3608 2017-03-13
- clarified POD for lcd_put_char() and lcd_char_def()
- clean up test XS code
- remove all code related to creating threads. That's out of scope for
this project (closes #2)
- moved all XS/C declarations into a separate API.h file from API.xs
- changed versioning scheme from 2.36.x to 2.360x
2.36.7 2017-03-09
- disable tests when not on a Pi board (within a BEGIN block)
- added INLINE.h to MANIFEST file (re-closes #8)
- fix bug in lcd_init(), where we weren't extracting the values from the
argument hash, thereby too many args were being passed into lcdInit()
C function (closes #27)
- added a workaround for lcd_char_def(). For some reason, we need to
print a zero-width char before calling the C function lcdCharDef().
One day I'll need to sort out why (closes #26)
- in lcd_char_def(), changed from "V0C*" to "C[8]" for pack()
- removed duplicate test declaration in t/00-load.t
- removed the :wiringPi and :perl export tags from POD, we only
advertise :all now, which only exports the Perl functions (all are
still available in code though)
2.36.6 2017-02-22
- added in I2C support (work on #22)
- fix a boatload of C warnings due to functions not being pre-declared
(work on #25)
- added -lrt to LIBS in Makefile.PL to correct a "shm_open() undefined
symbol" error when testing with "make test" (closes #25)
- removed taint from tests
- added $state param for lcd_cursor_blink() in POD (closes #24)
- fix miniscule POD error (closes #17)
- added "barometric" to the POD's bmp180 section (closes #16)
- POD typo fix (closes #15)
- replaced BCM with GPIO in POD (closes #14)
- fix output constant in get_alt() in POD (PWM_OUT) (closes #13)
2.36.5 2017-02-13
- lower-cased Inline functions in XS file
2.36.4 2017-01-26
- modified spiDataRW(). It now returns a Perl array containing the same
number of elements as was sent in. A write aref is sent in (with
dummy bytes in each element) for the size of array you want back that
contains the read data (fixes #23)
2.36.3 2017-01-22
- changed TOC to "TABLE OF CONTENTS" in POD (closes #18)
- modified dist description in POD
- added blurb in softpwm section that this functionality is quite
unreliable
- removed the code that skipped over the first interrupt in XS, as
the new wiringPi corrected the issue internally
- added POD for ads1115_setup()
- added test file for wiringPi's representation of the ADS1115 ADC
- added support for communicating on the SPI bus (spi_setup() and
spi_data()
- added spiDataRW() (C), which wraps wiringPiSPIDataRW() so that we
can accept an AV* (aref) before transforming it into the proper
unsigned char* before sending it to wiringPiSPIDataRW()
2.36.2 2017-01-19
- added function table of contents to POD
- added declaration of custom wiringPiVersion() in XS, but left it
commented out as it will break CPAN installs at this time
- added version.patch file in patches/, patch sent to Gordon
- all four setup routines added to test/setup.pl
- added in wiringPi's support for the Adafruit ADS1115 analog to digital
converter (I'm going to do a rewrite of this code to support 1015, as
well as allowing all ADC options to be configurable, and hope it gets
included in the next wiringPi cut)
- added docs/, which includes Fritzing diagrams and schematics
- added DEVELOPER FUNCTIONS section in POD for dev testing of private,
unpublished or unreleased functions
- added pseudoPinsSetup() for testing purposes
- reworded POD for setup() routines, as we no longer require root level
access to run our scripts (yay!)
- wrote test/pwm.pl, fully tests the hardware PWM functionality
- added test/pud.pl, testing for pull up/down internal resistors
- changed board_rev() references in POD to gpio_layout() (fixes #9)
- added test/pin_translations.pl, test all pin translation functions
- added pinModeAlt() as a developer function (allows setting any pin to
any valid mode)
- added digitalReadByte(), digitalReadByte2(), digitalWriteByte() and
digitalWriteByte2() as developer functions. Reads and writes an 8-bit
byte to/from the first and second bank of eight GPIO pins respectively
- added setup tests, since an issue was found that causes some calls to
crash the system (journal, RO), added root checks. Notes taken on
sourcing the issue(s)
2.36.1 2017-01-15
- changed version numbering scheme. x.yy.z: x.yy represents the version
of wiringPi we fully support, and z represents updates to this Perl
distribution
- renamed examples/ to samples/ so they don't show up on the CPAN's
front page for the distribution
- added exports for physPinToWpi() and phys_to_wpi() to correct a test
breakage
2.36 2017-01-14
- major updates, we now require wiringPi v2.36+
- changed version numbering scheme. We now match the wiringPi version
number that we fully support
- changed piBoardRev() to piGpioLayout(), and board_rev() to
gpio_laout() per changes in wiringPi.c/h
- added analogRead()/analog_read() and analogWrite()/analog_write() to
support the BMP180 sensor
- added bmp180_setup()/bmp180Setup()
- added bmp180_temp() and bmp180_pressure()
- added POD for all the new functionality
1.05 2017-01-13
- added support for the SR74HC595 shift register (shift_reg_setup() for
Perl, and the original sr595Setup())
- added examples/sr.pl for the shift register code
1.04 2016-08-22
- implemented softPwmCreate(), softPwmWrite() and softPwmStop(), perl:
soft_pwm_create(), soft_pwm_write(), soft_pwm_stop()
- interrupts now work; added code to stop the erroneous extra call to
the handler on first interrupt
1.03 2016-08-18
- fixed call to SetupGpio(), case was wrong
- renamed gpio_scheme() call to pin_scheme()
- removed erroneous call to external module (pin_scheme())
- POD cleanup, re-worded $pin descriptions, and fixed up setup*()
routine explanations
1.02 2016-08-16
- removed references to wiringPi pin numbering scheme being the default
- added clarification in setup*() routine POD
1.00 2016-08-16
- new export tags, :wiringPi exports the originally named wiringPi
functions directly from XS. :perl exports the Perl representation
of the functions, and :all exports them all
- setup_sys() now exports all BCM pins with a system call with sudo,
which alleviates the need to run as user root
- interrupt code now implemented and working
- renamed to WiringPi::API
0.06 2016-08-13
- moved arg validation out of Core and into upper-layer client
software. The idea is to keep this module as close to the C code
as possible, so if this module is used directly, C will handle the
problem
- wrote custom physPinToWpi() C function, and added a phys_to_wpi()
caller
- we now shift off the object or class name if it is present in all
sub calls
- all parameter error handling out, and put it into the upper layers...
we now pretty much call the C functions directly with little overhead
0.05 2016-08-11
- added all of the wiringPiDev shared library LCD functions, and
mapped them in ::Core
0.04 2016-08-10
- wiringPiSetupPhys() has been implemented
- added piBoardRev(), wpiPinToGpio(), physPinToGpio() and pwmSetRange()
functions
- added Perl->C mappings in POD
0.03 2016-08-10
- added repo info to Makefile.PL
- added get_alt(), maps to C getAlt(). This returns the current mode
of a pin. Why it's not called getMode() is beyond me ;)
0.02 2016-08-10
- added notices to POD
- added POD for pwm_write()
0.01 2016-08-10
- separated out from RPi::WiringPi
- most core and system functions implemented