2014-11-25 15:27:33 +01:00
|
|
|
#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);
|
2015-03-02 23:38:55 +01:00
|
|
|
|
|
|
|
return hasher;
|
2014-11-25 15:27:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Pi_Hasher_cancel(Pi_Hasher_t *hasher)
|
|
|
|
{
|
|
|
|
if (hasher)
|
|
|
|
{
|
|
|
|
gpioSetAlertFunc(hasher->gpio, 0);
|
|
|
|
|
|
|
|
free(hasher);
|
2015-03-02 23:38:55 +01:00
|
|
|
|
|
|
|
hasher = NULL;
|
2014-11-25 15:27:33 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|