--- /dev/null
+Program to show status changes for a Hall effect sensor.
+
--- /dev/null
+#include <stdio.h>
+
+#include <pigpio.h>
+
+/*
+OH3144E or equivalent Hall effect sensor
+
+Pin 1 - 5V
+Pin 2 - Ground
+Pin 3 - gpio (here P1-8, gpio 14, TXD is used)
+
+The internal gpio pull-up is enabled so that the sensor
+normally reads high. It reads low when a magnet is close.
+
+gcc -o hall hall.c -lpigpio -lrt -lpthread
+sudo ./hall
+*/
+
+#define HALL 14
+
+void alert(int gpio, int level, uint32_t tick)
+{
+ static uint32_t lastTick=0;
+
+ if (lastTick) printf("%d %.2f\n", level, (float)(tick-lastTick)/1000000.0);
+ else printf("%d 0.00\n", level);
+
+ lastTick = tick;
+}
+
+int main(int argc, char *argv[])
+{
+ int secs=60;
+
+ if (argc>1) secs = atoi(argv[1]); /* program run seconds */
+
+ if ((secs<1) || (secs>3600)) secs = 3600;
+
+ if (gpioInitialise()<0) return 1;
+
+ gpioSetMode(HALL, PI_INPUT);
+
+ gpioSetPullUpDown(HALL, PI_PUD_UP);
+
+ gpioSetAlertFunc(HALL, alert);
+
+ sleep(secs);
+
+ gpioTerminate();
+}
+
--- /dev/null
+A program to passively sniff I2C transactions (100kHz bus maximum) and display the results.
+
+This C program uses pigpio notifications.
+
--- /dev/null
+/*
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <fcntl.h>
+
+#include "pigpio.h"
+
+/*
+This software reads pigpio notification reports monitoring the I2C signals.
+
+Notifications are pipe based so this software must be run on the Pi
+being monitored.
+
+It should be able to handle a 100kHz bus. You are unlikely to get any
+usable results if the bus is running at 400kHz.
+
+gcc -o pig2i2c pig2i2c.c
+
+Do something like
+
+sudo pigpiod -s 2
+
+# get a notification handle, assume handle 0 was returned
+
+pigs no
+
+# start notifications for SCL/SDA
+
+e.g. pigs nb 0 0x3 # Rev. 1 select gpios 0/1
+e.g. pigs nb 0 0xC # Rev. 2 select gpios 2/3
+e.g. pigs nb 0 0xA00 # select gpios 9/11 (1<<9|1<<11)
+
+# run the program, specifying SCL/SDA and notification pipe
+
+./pig2i2c SCL SDA </dev/pigpioN # specify gpios for SCL/SDA and pipe N
+
+e.g. ./pig2i2c 1 0 </dev/pigpio0 # Rev.1 I2C gpios
+e.g. ./pig2i2c 3 2 </dev/pigpio0 # Rev.2 I2C gpios
+e.g. ./pig2i2c 9 11 </dev/pigpio0 # monitor external bus
+*/
+
+#define RS (sizeof(gpioReport_t))
+
+#define SCL_FALLING 0
+#define SCL_RISING 1
+#define SCL_STEADY 2
+
+#define SDA_FALLING 0
+#define SDA_RISING 4
+#define SDA_STEADY 8
+
+static char * timeStamp()
+{
+ static char buf[32];
+
+ struct timeval now;
+ struct tm tmp;
+
+ gettimeofday(&now, NULL);
+
+ localtime_r(&now.tv_sec, &tmp);
+ strftime(buf, sizeof(buf), "%F %T", &tmp);
+
+ return buf;
+}
+
+void parse_I2C(int SCL, int SDA)
+{
+ static int in_data=0, byte=0, bit=0;
+ static int oldSCL=1, oldSDA=1;
+
+ int xSCL, xSDA;
+
+ if (SCL != oldSCL)
+ {
+ oldSCL = SCL;
+ if (SCL) xSCL = SCL_RISING;
+ else xSCL = SCL_FALLING;
+ }
+ else xSCL = SCL_STEADY;
+
+ if (SDA != oldSDA)
+ {
+ oldSDA = SDA;
+ if (SDA) xSDA = SDA_RISING;
+ else xSDA = SDA_FALLING;
+ }
+ else xSDA = SDA_STEADY;
+
+ switch (xSCL+xSDA)
+ {
+ case SCL_RISING + SDA_RISING:
+ case SCL_RISING + SDA_FALLING:
+ case SCL_RISING + SDA_STEADY:
+ if (in_data)
+ {
+ if (bit++ < 8)
+ {
+ byte <<= 1;
+ byte |= SDA;
+ }
+ else
+ {
+ printf("%02X", byte);
+ if (SDA) printf("-"); else printf("+");
+ bit = 0;
+ byte = 0;
+ }
+ }
+ break;
+
+ case SCL_FALLING + SDA_RISING:
+ break;
+
+ case SCL_FALLING + SDA_FALLING:
+ break;
+
+ case SCL_FALLING + SDA_STEADY:
+ break;
+
+ case SCL_STEADY + SDA_RISING:
+ if (SCL)
+ {
+ in_data = 0;
+ byte = 0;
+ bit = 0;
+
+ printf("]\n"); // stop
+ fflush(NULL);
+ }
+ break;
+
+ case SCL_STEADY + SDA_FALLING:
+ if (SCL)
+ {
+ in_data = 1;
+ byte = 0;
+ bit = 0;
+
+ printf("["); // start
+ }
+ break;
+
+ case SCL_STEADY + SDA_STEADY:
+ break;
+
+ }
+}
+
+int main(int argc, char * argv[])
+{
+ int gSCL, gSDA, SCL, SDA, xSCL;
+ int r;
+ uint32_t level, changed, bI2C, bSCL, bSDA;
+
+ gpioReport_t report;
+
+ if (argc > 2)
+ {
+ gSCL = atoi(argv[1]);
+ gSDA = atoi(argv[2]);
+
+ bSCL = 1<<gSCL;
+ bSDA = 1<<gSDA;
+
+ bI2C = bSCL | bSDA;
+ }
+ else
+ {
+ exit(-1);
+ }
+
+ /* default to SCL/SDA high */
+
+ SCL = 1;
+ SDA = 1;
+ level = bI2C;
+
+ while ((r=read(STDIN_FILENO, &report, RS)) == RS)
+ {
+ report.level &= bI2C;
+
+ if (report.level != level)
+ {
+ changed = report.level ^ level;
+
+ level = report.level;
+
+ if (level & bSCL) SCL = 1; else SCL = 0;
+ if (level & bSDA) SDA = 1; else SDA = 0;
+
+ parse_I2C(SCL, SDA);
+ }
+ }
+ return 0;
+}
+
--- /dev/null
+Function to hash a code from an IR receiver (reading an IR remote control).
+
+Follow the instructions in the test file to build and run.
--- /dev/null
+#include <stdlib.h>
+
+#include <pigpio.h>
+
+#include "ir_hasher.h"
+
+/*
+This code forms a hash over the IR pulses generated by an
+IR remote.
+
+The remote key press is not converted into a code in the manner of
+the lirc module. No attempt is made to decode the type of protocol
+used by the remote. The hash is likely to be unique for different
+keys and different remotes but this is not guaranteed.
+
+This hashing process works for some remotes/protocols but not for
+others. The only way to find out if it works for one or more of
+your remotes is to try it and see.
+*/
+
+struct _Pi_Hasher_s
+{
+ int gpio;
+ Pi_Hasher_CB_t callback;
+ int timeout;
+ int in_code;
+ uint32_t hash_val;
+ int edges;
+ int t1;
+ int t2;
+ int t3;
+ int t4;
+};
+
+
+static uint32_t _hash(uint32_t hv, int old_val, int new_val)
+{
+ int val;
+
+ if (new_val < (old_val * 0.60)) val = 13;
+ else if (old_val < (new_val * 0.60)) val = 23;
+ else val = 2;
+
+ hv ^= val;
+ hv *= 16777619; /* FNV_PRIME_32 */
+
+ return hv;
+}
+
+static void _cb(int gpio, int level, uint32_t tick, void *user)
+{
+ Pi_Hasher_t * hasher;
+
+ hasher = user;
+
+ if (level != PI_TIMEOUT)
+ {
+ if (hasher->in_code == 0)
+ {
+ hasher->in_code = 1;
+
+ gpioSetWatchdog(gpio, hasher->timeout);
+
+ hasher->hash_val = 2166136261U; /* FNV_BASIS_32 */
+
+ hasher->edges = 1;
+
+ hasher->t1 = 0;
+ hasher->t2 = 0;
+ hasher->t3 = 0;
+ hasher->t4 = tick;
+ }
+ else
+ {
+ hasher->edges++;
+
+ hasher->t1 = hasher->t2;
+ hasher->t2 = hasher->t3;
+ hasher->t3 = hasher->t4;
+ hasher->t4 = tick;
+
+ if (hasher->edges > 3)
+ {
+ hasher->hash_val =
+ _hash(hasher->hash_val,
+ (hasher->t2)-(hasher->t1),
+ (hasher->t4)-(hasher->t3));
+ }
+ }
+ }
+ else
+ {
+ if (hasher->in_code)
+ {
+ hasher->in_code = 0;
+
+ gpioSetWatchdog(gpio, 0);
+
+ if (hasher->edges > 12) /* Anything less is probably noise. */
+ {
+ (hasher->callback)(hasher->hash_val);
+ }
+ }
+ }
+}
+
+Pi_Hasher_t *Pi_Hasher(int gpio, Pi_Hasher_CB_t callback, int timeout)
+{
+ Pi_Hasher_t *hasher;
+
+ hasher = malloc(sizeof(Pi_Hasher_t));
+
+ hasher->gpio = gpio;
+ hasher->callback = callback;
+ hasher->timeout = 5;
+
+ hasher->in_code = 0;
+
+ gpioSetMode(gpio, PI_INPUT);
+ gpioSetAlertFuncEx(gpio, _cb, hasher);
+}
+
+void Pi_Hasher_cancel(Pi_Hasher_t *hasher)
+{
+ if (hasher)
+ {
+ gpioSetAlertFunc(hasher->gpio, 0);
+
+ free(hasher);
+ }
+}
+
--- /dev/null
+#ifndef IR_HASHER_H
+#define IR_HASHER_H
+
+#include <stdint.h>
+
+typedef void (*Pi_Hasher_CB_t)(uint32_t);
+
+struct _Pi_Hasher_s;
+
+typedef struct _Pi_Hasher_s Pi_Hasher_t;
+
+Pi_Hasher_t * Pi_Hasher(int gpio, Pi_Hasher_CB_t callback, int timeout);
+ /*
+ This function establishes an IR hasher on the gpio.
+
+ A gap of timeout milliseconds without a new bit indicates
+ the end of a code.
+
+ When code end is detected the callback function is called
+ with the code hash.
+
+ A pointer to a private data type is returned. This should be passed
+ to Pi_Hasher_cancel if the hasher is to be cancelled.
+ */
+
+
+void Pi_Hasher_cancel(Pi_Hasher_t *hasher);
+ /*
+ This function releases the resources used by the hasher.
+ */
+
+
+#endif
--- /dev/null
+#include <stdio.h>
+
+#include <pigpio.h>
+
+#include "ir_hasher.h"
+
+/*
+
+REQUIRES
+
+An IR receiver output pin connected to a Pi gpio.
+
+TO BUILD
+
+gcc -o ir_hash_c test_ir_hasher.c ir_hasher.c -lpigpio -lrt
+
+TO RUN
+
+sudo ./ir_hash_c
+
+*/
+
+void callback(uint32_t hash)
+{
+ printf("hash=%u\n", hash);
+}
+
+int main(int argc, char *argv[])
+{
+ Pi_Hasher_t *hasher;
+
+ if (gpioInitialise() < 0) return 1;
+
+ /*
+ This assumes the output pin of an IR receiver is
+ connected to gpio 7.
+ */
+
+ hasher = Pi_Hasher(7, callback, 5);
+
+ sleep(300);
+
+ Pi_Hasher_cancel(hasher);
+
+ gpioTerminate();
+}
+
--- /dev/null
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <linux/i2c-dev.h>
+#include <ncurses.h> /* libncurses5-dev */
+
+/*
+2014-08-26 PCF8591.c
+
+sudo apt-get install libncurses5-dev
+
+gcc -o PCF8591 PCF8591.c -lcurses -lpigpio -lpthread
+
+sudo ./PCF8591
+*/
+
+/*
+Connect Pi 5V - VCC, Ground - Ground, SDA - SDA, SCL - SCL.
+*/
+
+#define PCF8591_I2C_ADDR 0x48
+
+/*
+ P4 The thermister voltage is provided at AIN 1.
+ P5 The photocell voltage is provided at AIN 0.
+ P6 The single turn 10K ohm trim pot voltage is provided at AIN 3.
+*/
+
+/*
+7 6 5 4 3 2 1 0
+0 X X X 0 X X X
+ | | | | | |
+ A B B C D D
+
+0 1 0 0 0 1 0 0
+
+A 0 D/A inactive
+ 1 D/A active
+
+B 00 single ended inputs
+ 01 differential inputs
+ 10 single ended and differential
+ 11 two differential inputs
+
+C 0 no auto inc
+ 1 auto inc
+
+D 00 select channel 0
+ 01 select channel 1
+ 10 select channel 2
+ 11 select channel 3
+
+*/
+
+int main(int argc, char *argv[])
+{
+ int i;
+ int r;
+ int handle;
+ char aout;
+ unsigned char command[2];
+ unsigned char value[4];
+ unsigned char str[8];
+
+ int j;
+ int key;
+
+ if (gpioInitialise() < 0) return 1;
+
+ initscr();
+ noecho();
+ cbreak();
+ nodelay(stdscr, true);
+ curs_set(0);
+
+ printw("PCF8591 + or - to change aout, any other key to quit.");
+
+ mvaddstr(10, 0, "Brightness");
+ mvaddstr(12, 0, "Temperature");
+ mvaddstr(14, 0, "?");
+ mvaddstr(16, 0, "Resistor");
+
+ refresh();
+
+ handle = i2cOpen(1, PCF8591_I2C_ADDR, 0);
+
+ command[1] = 0;
+ aout = 128;
+
+ while (1)
+ {
+ for (i=0; i<4; i++)
+ {
+ command[1] = aout;
+ command[0] = 0x40 | ((i + 1) & 0x03); // output enable | read input i
+
+ i2cWriteDevice(handle, &command, 2);
+
+ usleep(20000);
+
+ // the read is always one step behind the selected input
+ value[i] = i2cReadByte(handle);
+
+ sprintf(str, "%3d", value[i]);
+ mvaddstr(10+i+i, 12, str);
+ value[i] = value[i] / 4;
+ move(10 + i + i, 16);
+
+ for(j = 0; j < 64; j++)
+ if(j < value[i]) addch('*'); else addch(' ');
+ }
+
+ refresh();
+
+ key = getch();
+
+ if ((key == '+') || (key == '=')) aout++;
+ else if ((key == '-') || (key == '_')) aout--;
+ else if (key != -1) break;
+ }
+
+ endwin();
+
+ i2cClose(handle);
+
+ gpioTerminate();
+
+ return (0);
+}
+
--- /dev/null
+A program to display readings from the (I2C) PCF8591.
--- /dev/null
+Function to time capacitor charging (through a resistance).
+
+The time can be used to estimate the resistance.
--- /dev/null
+#include <stdio.h>
+
+#include <pigpio.h>
+
+/*
+ Measure how long a capacitor takes to charge through a resistance.
+
+ A potentimeter is used to vary the resistance.
+
+ The time taken will be proportional to the resistance.
+
+ 3V3 ----- Potentiometer --+-- Capacitor ----- Ground
+ |
+ +-- gpio
+
+
+ gcc -o pot_cap_charge pot_cap_charge.c -lpigpio -lpthread -lrt
+ sudo ./pot_cap_charge
+
+*/
+
+#define GPIO 25
+
+#define MAX_READING 1000
+
+static uint32_t rechargeTick = 0;
+
+void callback(int gpio, int level, uint32_t tick)
+{
+ static uint32_t smooth = 0;
+ static int reading = 0;
+
+ uint32_t raw;
+
+ if (level == 1) /* measure recharge time */
+ {
+ ++reading;
+
+ if (rechargeTick)
+ {
+ raw = tick - rechargeTick; /* set in main */
+
+ if (raw < MAX_READING) /* ignore outliers */
+ {
+ /* smooth using 0.8 * smooth + 0.2 * raw */
+
+ smooth = (raw + (4 * smooth)) / 5;
+
+ printf("%d %d %d\n", reading, raw, smooth);
+ }
+ else
+ {
+ /* ignore outlier, set dot at fixed position */
+ printf("%d %d %d\n", reading, 40, smooth);
+ }
+ }
+ else
+ {
+ /* ignore reschedule, set dot at fixed position */
+ printf("%d %d %d\n", reading, 20, smooth);
+ }
+ }
+}
+
+int main (int argc, char *argv[])
+{
+ uint32_t t1, t2;
+ int tDiff;
+
+ if (gpioInitialise()<0) return 1;
+
+ gpioSetAlertFunc(GPIO, callback); /* callback when GPIO changes state */
+
+ while (1)
+ {
+ gpioWrite(GPIO, PI_OFF); /* drain capacitor */
+
+ gpioDelay(200); /* microseconds */
+
+ t1 = gpioTick();
+
+ gpioSetMode(GPIO, PI_INPUT); /* start capacitor recharge */
+
+ t2 = gpioTick();
+
+ /* dump reading if rechargeTick not accurate to 3 micros */
+
+ if ((t2 - t1) < 3) rechargeTick = t1; else rechargeTick = 0;
+
+ gpioDelay(5000); /* microseconds, nominal 200 readings per second */
+ }
+
+ gpioTerminate();
+}
--- /dev/null
+Function to decode a mechanical rotary encoder.
+
+Follow the instructions in the test file to build and run.
+
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <pigpio.h>
+
+#include "rotary_encoder.h"
+
+struct _Pi_Renc_s
+{
+ int gpioA;
+ int gpioB;
+ Pi_Renc_CB_t callback;
+ int levA;
+ int levB;
+ int lastGpio;
+};
+
+/*
+
+ +---------+ +---------+ 0
+ | | | |
+ A | | | |
+ | | | |
+ +---------+ +---------+ +----- 1
+
+ +---------+ +---------+ 0
+ | | | |
+ B | | | |
+ | | | |
+ ----+ +---------+ +---------+ 1
+
+*/
+
+static void _cb(int gpio, int level, uint32_t tick, void *user)
+{
+ Pi_Renc_t *renc;
+
+ renc = user;
+
+ if (gpio == renc->gpioA) renc->levA = level; else renc->levB = level;
+
+ if (gpio != renc->lastGpio) /* debounce */
+ {
+ renc->lastGpio = gpio;
+
+ if ((gpio == renc->gpioA) && (level == 1))
+ {
+ if (renc->levB) (renc->callback)(1);
+ }
+ else if ((gpio == renc->gpioB) && (level == 1))
+ {
+ if (renc->levA) (renc->callback)(-1);
+ }
+ }
+}
+
+Pi_Renc_t * Pi_Renc(int gpioA, int gpioB, Pi_Renc_CB_t callback)
+{
+ Pi_Renc_t *renc;
+
+ renc = malloc(sizeof(Pi_Renc_t));
+
+ renc->gpioA = gpioA;
+ renc->gpioB = gpioB;
+ renc->callback = callback;
+ renc->levA=0;
+ renc->levB=0;
+ renc->lastGpio = -1;
+
+ gpioSetMode(gpioA, PI_INPUT);
+ gpioSetMode(gpioB, PI_INPUT);
+
+ /* pull up is needed as encoder common is grounded */
+
+ gpioSetPullUpDown(gpioA, PI_PUD_UP);
+ gpioSetPullUpDown(gpioB, PI_PUD_UP);
+
+ /* monitor encoder level changes */
+
+ gpioSetAlertFuncEx(gpioA, _cb, renc);
+ gpioSetAlertFuncEx(gpioB, _cb, renc);
+}
+
+void Pi_Renc_cancel(Pi_Renc_t *renc)
+{
+ if (renc)
+ {
+ gpioSetAlertFunc(renc->gpioA, 0);
+ gpioSetAlertFunc(renc->gpioB, 0);
+
+ free(renc);
+ }
+}
+
--- /dev/null
+#ifndef ROTARY_ENCODER_H
+#define ROTARY_ENCODER_H
+
+typedef void (*Pi_Renc_CB_t)(int);
+
+struct _Pi_Renc_s;
+
+typedef struct _Pi_Renc_s Pi_Renc_t;
+
+Pi_Renc_t * Pi_Renc(int gpioA, int gpioB, Pi_Renc_CB_t callback);
+/*
+ This function establishes a rotary encoder on gpioA and gpioB.
+
+ When the encoder is turned the callback function is called.
+
+ A pointer to a private data type is returned. This should be passed
+ to Pi_Renc_cancel if the rotary encoder is to be cancelled.
+*/
+
+void Pi_Renc_cancel(Pi_Renc_t *renc);
+/*
+ This function releases the resources used by the decoder.
+*/
+
+#endif
--- /dev/null
+#include <stdio.h>
+
+#include <pigpio.h>
+
+#include "rotary_encoder.h"
+
+/*
+
+REQUIRES
+
+A rotary encoder contacts A and B connected to separate gpios and
+the common contact connected to Pi ground.
+
+TO BUILD
+
+gcc -o rot_enc_c test_rotary_encoder.c rotary_encoder.c -lpigpio -lrt
+
+TO RUN
+
+sudo ./rot_enc_c
+
+*/
+
+void callback(int way)
+{
+ static int pos = 0;
+
+ pos += way;
+
+ printf("pos=%d\n", pos);
+}
+
+int main(int argc, char *argv[])
+{
+ Pi_Renc_t * renc;
+
+ if (gpioInitialise() < 0) return 1;
+
+ renc = Pi_Renc(7, 8, callback);
+
+ sleep(300);
+
+ Pi_Renc_cancel(renc);
+
+ gpioTerminate();
+}
+
--- /dev/null
+Function to decode a Wiegand code.
+
+Follow the instructions in the test file to build and run.
+
--- /dev/null
+#include <stdio.h>
+
+#include <pigpio.h>
+
+#include "wiegand.h"
+
+/*
+
+REQUIRES
+
+Wiegand contacts 0 and 1 connected to separate gpios.
+
+TO BUILD
+
+gcc -o wiegand_c test_wiegand.c wiegand.c -lpigpio -lrt
+
+TO RUN
+
+sudo ./wiegand_c
+
+*/
+
+void callback(int bits, uint32_t value)
+{
+ printf("bits=%d value=%u\n", bits, value);
+}
+
+int main(int argc, char *argv[])
+{
+ Pi_Wieg_t * w;
+
+ if (gpioInitialise() < 0) return 1;
+
+ w = Pi_Wieg(14, 15, callback, 5);
+
+ sleep(300);
+
+ Pi_Wieg_cancel(w);
+
+ gpioTerminate();
+}
+
--- /dev/null
+#include <stdlib.h>
+
+#include <pigpio.h>
+
+#include "wiegand.h"
+
+struct _Pi_Wieg_s
+{
+ int mygpio_0;
+ int mygpio_1;
+ int mytimeout;
+ int in_code;
+ int bits;
+ Pi_Wieg_CB_t mycallback;
+ uint32_t num;
+ uint32_t code_timeout;
+};
+
+void _cb(int gpio, int level, uint32_t tick, void *user)
+{
+ /*
+ Accumulate bits until both gpios 0 and 1 timeout.
+ */
+
+ Pi_Wieg_t *wieg;
+
+ wieg = user;
+
+ if (level == 0) /* a falling edge indicates a new bit */
+ {
+ if (!wieg->in_code)
+ {
+ wieg->bits = 1;
+ wieg->num = 0;
+
+ wieg->in_code = 1;
+ wieg->code_timeout = 0;
+
+ gpioSetWatchdog(wieg->mygpio_0, wieg->mytimeout);
+ gpioSetWatchdog(wieg->mygpio_1, wieg->mytimeout);
+ }
+ else
+ {
+ wieg->bits++;
+ wieg->num <<= 1;
+ }
+
+ if (gpio == wieg->mygpio_0)
+ {
+ wieg->code_timeout &= 2; /* clear gpio 0 timeout */
+ }
+ else
+ {
+ wieg->code_timeout &= 1; /* clear gpio 1 timeout */
+ wieg->num |= 1;
+ }
+ }
+ else if (level == PI_TIMEOUT)
+ {
+ if (wieg->in_code)
+ {
+ if (gpio == wieg->mygpio_0)
+ {
+ wieg->code_timeout |= 1; /* timeout gpio 0 */
+ }
+ else
+ {
+ wieg->code_timeout |= 2; /* timeout gpio 1 */
+ }
+
+ if (wieg->code_timeout == 3) /* both gpios timed out */
+ {
+ gpioSetWatchdog(wieg->mygpio_0, 0);
+ gpioSetWatchdog(wieg->mygpio_1, 0);
+
+ wieg->in_code = 0;
+
+ (wieg->mycallback)(wieg->bits, wieg->num);
+ }
+ }
+ }
+}
+
+Pi_Wieg_t * Pi_Wieg(
+ int gpio_0,
+ int gpio_1,
+ Pi_Wieg_CB_t callback,
+ int timeout)
+{
+ /*
+ Instantiate with the gpio for 0 (green wire), the gpio for 1
+ (white wire), the callback function, and the timeout in
+ milliseconds which indicates the end of a code.
+
+ The callback is passed the code length in bits and the value.
+ */
+
+ Pi_Wieg_t *wieg;
+
+ wieg = malloc(sizeof(Pi_Wieg_t));
+
+ wieg->mygpio_0 = gpio_0;
+ wieg->mygpio_1 = gpio_1;
+
+ wieg->mycallback = callback;
+
+ wieg->mytimeout = timeout;
+
+ wieg->in_code = 0;
+
+ gpioSetMode(gpio_0, PI_INPUT);
+ gpioSetMode(gpio_1, PI_INPUT);
+
+ gpioSetPullUpDown(gpio_0, PI_PUD_UP);
+ gpioSetPullUpDown(gpio_1, PI_PUD_UP);
+
+ gpioSetAlertFuncEx(gpio_0, _cb, wieg);
+ gpioSetAlertFuncEx(gpio_1, _cb, wieg);
+
+ return wieg;
+}
+
+void Pi_Wieg_cancel(Pi_Wieg_t *wieg)
+{
+ /*
+ Cancel the Wiegand decoder.
+ */
+
+ if (wieg)
+ {
+ gpioSetAlertFunc(wieg->mygpio_0, 0);
+ gpioSetAlertFunc(wieg->mygpio_1, 0);
+
+ free(wieg);
+ }
+}
+
--- /dev/null
+#ifndef WIEGAND_H
+#define WIEGAND_H
+
+#include <stdint.h>
+
+typedef void (*Pi_Wieg_CB_t)(int, uint32_t);
+
+struct _Pi_Wieg_s;
+
+typedef struct _Pi_Wieg_s Pi_Wieg_t;
+
+Pi_Wieg_t *Pi_Wieg(int gpio_0, int gpio_1, Pi_Wieg_CB_t callback, int timeout);
+ /*
+ This function establishes a Wiegand decoder on gpio_0 and gpio_1.
+
+ A gap of timeout milliseconds without a new bit indicates the
+ end of a code.
+
+ When the code is ended the callback function is called with the code
+ bit length and value.
+
+ A pointer to a private data type is returned. This should be passed
+ to Pi_Wieg_cancel if the decoder is to be cancelled.
+ */
+
+void Pi_Wieg_cancel(Pi_Wieg_t *wieg);
+ /*
+ This function releases the resources used by the decoder.
+ */
+
+#endif
+