1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
|
#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);
return hasher;
}
void Pi_Hasher_cancel(Pi_Hasher_t *hasher)
{
if (hasher)
{
gpioSetAlertFunc(hasher->gpio, 0);
free(hasher);
hasher = NULL;
}
}
|