From 4cbcce81acd51a0ba9465a2326663a3b2cfa4c7a Mon Sep 17 00:00:00 2001 From: joan Date: Tue, 25 Nov 2014 14:27:33 +0000 Subject: [PATCH] V23 --- EXAMPLES/C/HALL_EFFECT_SENSOR/README | 2 + EXAMPLES/C/HALL_EFFECT_SENSOR/hall.c | 51 +++++ EXAMPLES/C/I2C_SNIFFER/README | 4 + EXAMPLES/C/I2C_SNIFFER/pig2i2c.c | 205 ++++++++++++++++++ EXAMPLES/C/IR_RECEIVER/README | 3 + EXAMPLES/C/IR_RECEIVER/ir_hasher.c | 132 +++++++++++ EXAMPLES/C/IR_RECEIVER/ir_hasher.h | 33 +++ EXAMPLES/C/IR_RECEIVER/test_ir_hasher.c | 47 ++++ EXAMPLES/C/PCF8591_YL-40/PCF8591.c | 131 +++++++++++ EXAMPLES/C/PCF8591_YL-40/README | 1 + EXAMPLES/C/POT_CAP_RECHARGE/README | 3 + EXAMPLES/C/POT_CAP_RECHARGE/pot_cap_charge.c | 94 ++++++++ EXAMPLES/C/ROTARY_ENCODER/README | 4 + EXAMPLES/C/ROTARY_ENCODER/rotary_encoder.c | 94 ++++++++ EXAMPLES/C/ROTARY_ENCODER/rotary_encoder.h | 25 +++ .../C/ROTARY_ENCODER/test_rotary_encoder.c | 47 ++++ EXAMPLES/C/WIEGAND_CODE/README | 4 + EXAMPLES/C/WIEGAND_CODE/test_wiegand.c | 42 ++++ EXAMPLES/C/WIEGAND_CODE/wiegand.c | 137 ++++++++++++ EXAMPLES/C/WIEGAND_CODE/wiegand.h | 32 +++ 20 files changed, 1091 insertions(+) create mode 100644 EXAMPLES/C/HALL_EFFECT_SENSOR/README create mode 100644 EXAMPLES/C/HALL_EFFECT_SENSOR/hall.c create mode 100644 EXAMPLES/C/I2C_SNIFFER/README create mode 100644 EXAMPLES/C/I2C_SNIFFER/pig2i2c.c create mode 100644 EXAMPLES/C/IR_RECEIVER/README create mode 100644 EXAMPLES/C/IR_RECEIVER/ir_hasher.c create mode 100644 EXAMPLES/C/IR_RECEIVER/ir_hasher.h create mode 100644 EXAMPLES/C/IR_RECEIVER/test_ir_hasher.c create mode 100644 EXAMPLES/C/PCF8591_YL-40/PCF8591.c create mode 100644 EXAMPLES/C/PCF8591_YL-40/README create mode 100644 EXAMPLES/C/POT_CAP_RECHARGE/README create mode 100644 EXAMPLES/C/POT_CAP_RECHARGE/pot_cap_charge.c create mode 100644 EXAMPLES/C/ROTARY_ENCODER/README create mode 100644 EXAMPLES/C/ROTARY_ENCODER/rotary_encoder.c create mode 100644 EXAMPLES/C/ROTARY_ENCODER/rotary_encoder.h create mode 100644 EXAMPLES/C/ROTARY_ENCODER/test_rotary_encoder.c create mode 100644 EXAMPLES/C/WIEGAND_CODE/README create mode 100644 EXAMPLES/C/WIEGAND_CODE/test_wiegand.c create mode 100644 EXAMPLES/C/WIEGAND_CODE/wiegand.c create mode 100644 EXAMPLES/C/WIEGAND_CODE/wiegand.h diff --git a/EXAMPLES/C/HALL_EFFECT_SENSOR/README b/EXAMPLES/C/HALL_EFFECT_SENSOR/README new file mode 100644 index 0000000..57f9143 --- /dev/null +++ b/EXAMPLES/C/HALL_EFFECT_SENSOR/README @@ -0,0 +1,2 @@ +Program to show status changes for a Hall effect sensor. + diff --git a/EXAMPLES/C/HALL_EFFECT_SENSOR/hall.c b/EXAMPLES/C/HALL_EFFECT_SENSOR/hall.c new file mode 100644 index 0000000..5c2f103 --- /dev/null +++ b/EXAMPLES/C/HALL_EFFECT_SENSOR/hall.c @@ -0,0 +1,51 @@ +#include + +#include + +/* +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(); +} + diff --git a/EXAMPLES/C/I2C_SNIFFER/README b/EXAMPLES/C/I2C_SNIFFER/README new file mode 100644 index 0000000..23b5594 --- /dev/null +++ b/EXAMPLES/C/I2C_SNIFFER/README @@ -0,0 +1,4 @@ +A program to passively sniff I2C transactions (100kHz bus maximum) and display the results. + +This C program uses pigpio notifications. + diff --git a/EXAMPLES/C/I2C_SNIFFER/pig2i2c.c b/EXAMPLES/C/I2C_SNIFFER/pig2i2c.c new file mode 100644 index 0000000..bf9102c --- /dev/null +++ b/EXAMPLES/C/I2C_SNIFFER/pig2i2c.c @@ -0,0 +1,205 @@ +/* +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 2) + { + gSCL = atoi(argv[1]); + gSDA = atoi(argv[2]); + + bSCL = 1< + +#include + +#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); + } +} + diff --git a/EXAMPLES/C/IR_RECEIVER/ir_hasher.h b/EXAMPLES/C/IR_RECEIVER/ir_hasher.h new file mode 100644 index 0000000..ef2278f --- /dev/null +++ b/EXAMPLES/C/IR_RECEIVER/ir_hasher.h @@ -0,0 +1,33 @@ +#ifndef IR_HASHER_H +#define IR_HASHER_H + +#include + +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 diff --git a/EXAMPLES/C/IR_RECEIVER/test_ir_hasher.c b/EXAMPLES/C/IR_RECEIVER/test_ir_hasher.c new file mode 100644 index 0000000..878bdb8 --- /dev/null +++ b/EXAMPLES/C/IR_RECEIVER/test_ir_hasher.c @@ -0,0 +1,47 @@ +#include + +#include + +#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(); +} + diff --git a/EXAMPLES/C/PCF8591_YL-40/PCF8591.c b/EXAMPLES/C/PCF8591_YL-40/PCF8591.c new file mode 100644 index 0000000..f2c0730 --- /dev/null +++ b/EXAMPLES/C/PCF8591_YL-40/PCF8591.c @@ -0,0 +1,131 @@ +#include +#include +#include +#include +#include +#include /* 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); +} + diff --git a/EXAMPLES/C/PCF8591_YL-40/README b/EXAMPLES/C/PCF8591_YL-40/README new file mode 100644 index 0000000..40428b1 --- /dev/null +++ b/EXAMPLES/C/PCF8591_YL-40/README @@ -0,0 +1 @@ +A program to display readings from the (I2C) PCF8591. diff --git a/EXAMPLES/C/POT_CAP_RECHARGE/README b/EXAMPLES/C/POT_CAP_RECHARGE/README new file mode 100644 index 0000000..530685c --- /dev/null +++ b/EXAMPLES/C/POT_CAP_RECHARGE/README @@ -0,0 +1,3 @@ +Function to time capacitor charging (through a resistance). + +The time can be used to estimate the resistance. diff --git a/EXAMPLES/C/POT_CAP_RECHARGE/pot_cap_charge.c b/EXAMPLES/C/POT_CAP_RECHARGE/pot_cap_charge.c new file mode 100644 index 0000000..811e3f7 --- /dev/null +++ b/EXAMPLES/C/POT_CAP_RECHARGE/pot_cap_charge.c @@ -0,0 +1,94 @@ +#include + +#include + +/* + 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(); +} diff --git a/EXAMPLES/C/ROTARY_ENCODER/README b/EXAMPLES/C/ROTARY_ENCODER/README new file mode 100644 index 0000000..d07037e --- /dev/null +++ b/EXAMPLES/C/ROTARY_ENCODER/README @@ -0,0 +1,4 @@ +Function to decode a mechanical rotary encoder. + +Follow the instructions in the test file to build and run. + diff --git a/EXAMPLES/C/ROTARY_ENCODER/rotary_encoder.c b/EXAMPLES/C/ROTARY_ENCODER/rotary_encoder.c new file mode 100644 index 0000000..5bccba7 --- /dev/null +++ b/EXAMPLES/C/ROTARY_ENCODER/rotary_encoder.c @@ -0,0 +1,94 @@ +#include +#include + +#include + +#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); + } +} + diff --git a/EXAMPLES/C/ROTARY_ENCODER/rotary_encoder.h b/EXAMPLES/C/ROTARY_ENCODER/rotary_encoder.h new file mode 100644 index 0000000..73f7454 --- /dev/null +++ b/EXAMPLES/C/ROTARY_ENCODER/rotary_encoder.h @@ -0,0 +1,25 @@ +#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 diff --git a/EXAMPLES/C/ROTARY_ENCODER/test_rotary_encoder.c b/EXAMPLES/C/ROTARY_ENCODER/test_rotary_encoder.c new file mode 100644 index 0000000..9f512e0 --- /dev/null +++ b/EXAMPLES/C/ROTARY_ENCODER/test_rotary_encoder.c @@ -0,0 +1,47 @@ +#include + +#include + +#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(); +} + diff --git a/EXAMPLES/C/WIEGAND_CODE/README b/EXAMPLES/C/WIEGAND_CODE/README new file mode 100644 index 0000000..38d5acb --- /dev/null +++ b/EXAMPLES/C/WIEGAND_CODE/README @@ -0,0 +1,4 @@ +Function to decode a Wiegand code. + +Follow the instructions in the test file to build and run. + diff --git a/EXAMPLES/C/WIEGAND_CODE/test_wiegand.c b/EXAMPLES/C/WIEGAND_CODE/test_wiegand.c new file mode 100644 index 0000000..8aef6d6 --- /dev/null +++ b/EXAMPLES/C/WIEGAND_CODE/test_wiegand.c @@ -0,0 +1,42 @@ +#include + +#include + +#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(); +} + diff --git a/EXAMPLES/C/WIEGAND_CODE/wiegand.c b/EXAMPLES/C/WIEGAND_CODE/wiegand.c new file mode 100644 index 0000000..5bfecd7 --- /dev/null +++ b/EXAMPLES/C/WIEGAND_CODE/wiegand.c @@ -0,0 +1,137 @@ +#include + +#include + +#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); + } +} + diff --git a/EXAMPLES/C/WIEGAND_CODE/wiegand.h b/EXAMPLES/C/WIEGAND_CODE/wiegand.h new file mode 100644 index 0000000..8deaa3a --- /dev/null +++ b/EXAMPLES/C/WIEGAND_CODE/wiegand.h @@ -0,0 +1,32 @@ +#ifndef WIEGAND_H +#define WIEGAND_H + +#include + +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 +