I'm using Android things with a VSIONIS keypad in reader mode, which outputs on D0 and D1 pins in Wiegand 26 format. I found a few libraries on how to do this on Arduino and have ported over the code, but cannot seem to make it work on Android Things. I'm using a Raspberry Pi 3. Does anyone have any knowledge on how to make this work?
Here's the Arduino library.
Here's the ported over code:
/**
* @author bilal
*/
public class Wiegand {
public static final String TAG = "thing:Wiegand";
long cardTempHigh = 0;
long cardTemp = 0;
long lastWiegand = 0;
long sysTick = 0;
long code = 0;
int bitCount = 0;
int wiegandType = 0;
///
long codehigh, codelow;
private static final String GPIO_PIN_D0_Name = "BCM4";
private static final String GPIO_PIN_D1_Name = "BCM5";
private Gpio mWiegand34GpioD0;
private Gpio mWiegand34GpioD1;
public void begin() {
System.out.println("wiegand begin");
lastWiegand = 0;
cardTempHigh = 0;
cardTemp = 0;
code = 0;
wiegandType = 0;
bitCount = 0;
sysTick = System.currentTimeMillis();
// final GpioPinDigitalInput D0Pin = gpio.provisionDigitalInputPin(RaspiPin.GPIO_00, PinPullResistance.PULL_UP);
// final GpioPinDigitalInput D1Pin = gpio.provisionDigitalInputPin(RaspiPin.GPIO_07, PinPullResistance.PULL_UP);
PeripheralManagerService service = new PeripheralManagerService();
Log.d("thing:Wiegand (begin)", "Available GPIO: " + service.getGpioList());
try {
// Step 1. Create GPIO connection.
mWiegand34GpioD0 = service.openGpio(GPIO_PIN_D0_Name);
mWiegand34GpioD1 = service.openGpio(GPIO_PIN_D1_Name);
// Step 2. Configure as an input.
mWiegand34GpioD0.setDirection(Gpio.DIRECTION_IN);
mWiegand34GpioD1.setDirection(Gpio.DIRECTION_IN);
// Step 3. Enable edge trigger events.
mWiegand34GpioD0.setEdgeTriggerType(Gpio.EDGE_FALLING);
mWiegand34GpioD1.setEdgeTriggerType(Gpio.EDGE_FALLING);
//Testing what this do
//mWiegand34GpioD0.setActiveType(Gpio.ACTIVE_HIGH);
// Step 4. Register an event callback.
mWiegand34GpioD0.registerGpioCallback(data_pulse0);
mWiegand34GpioD1.registerGpioCallback(data_pulse1);
} catch (IOException e) {
Log.e(TAG, "Error on PeripheralIO API", e);
}
//attachInterrupt(0, ReadD0, FALLING); // Hardware interrupt - high to low pulse
//attachInterrupt(1, ReadD1, FALLING); // Hardware interrupt - high to low pulse
}
private GpioCallback data_pulse0 = new GpioCallback() {
@Override
public boolean onGpioEdge(Gpio gpio) {
bitCount++; // Increment bit count for Interrupt connected to D0
if (bitCount > 31) { // If bit count more than 31, process high bits
cardTempHigh |= ((0x80000000 & cardTemp) >> 31); // shift value to high bits
cardTempHigh = 1;
cardTemp = 1;
} else {
cardTemp = 1; // D0 represent binary 0, so just left shift card data
}
lastWiegand = sysTick; // Keep track of last wiegand bit received
Log.d(TAG + "data_pulse0)", cardTemp + "");
return true;
}
};
private GpioCallback data_pulse1 = new GpioCallback() {
@Override
public boolean onGpioEdge(Gpio gpio) {
bitCount++; // Increment bit count for Interrupt connected to D1
if (bitCount > 31) { // If bit count more than 31, process high bits
cardTempHigh |= ((0x80000000 & cardTemp) >> 31); // shift value to high bits
cardTempHigh = 1;
cardTemp |= 1;
cardTemp = 1;
} else {
cardTemp |= 1; // D1 represent binary 1, so OR card data with 1 then
cardTemp = 1; // left shift card data
}
lastWiegand = sysTick; // Keep track of last wiegand bit received
Log.d(TAG + "data_pulse1)", cardTemp + "");
return true;
}
};
boolean available() {
return DoWiegandConversion();
}
public long getCode() {
return code;
}
long GetCardId(char bitlength) {
long cardID = 0;
if (bitlength == 26) // EM tag
cardID = (codelow & 0x1FFFFFE) >> 1;
if (bitlength == 34) { // Mifare
codehigh = codehigh & 0x03; // only need the 2 LSB of the codehigh
codehigh = 30; // shift 2 LSB to MSB
codelow = 1;
cardID = codehigh | codelow;
}
Log.d(TAG + "(GetCardId)", cardID + "");
System.out.println("cardID:" + cardID);
return cardID;
}
public boolean DoWiegandConversion() {
long cardID;
sysTick = System.currentTimeMillis();
if ((sysTick - lastWiegand) > 25) { // if no more signal coming through after 25ms
if ((bitCount == 26) || (bitCount == 34) || (bitCount == 8)) { // bitCount for keypress=8, Wiegand 26=26, Wiegand 34=34
cardTemp >>= 1; // shift right 1 bit to get back the real value - interrupt done 1 left shift in advance
if (bitCount > 32) // bit count more than 32 bits, shift high bits right to make adjustment
cardTempHigh >>= 1;
if ((bitCount == 26) || (bitCount == 34)) { // wiegand 26 or wiegand 34
cardID = GetCardId((char) bitCount);
wiegandType = bitCount;
bitCount = 0;
cardTemp = 0;
cardTempHigh = 0;
code = cardID;
return true;
} else if (bitCount == 8) { // keypress wiegand
// 8-bit Wiegand keyboard data, high nibble is the "NOT" of low nibble
// eg if key 1 pressed, data=E1 in binary 11100001 , high nibble=1110 , low nibble = 0001
char highNibble = (char) ((cardTemp & 0xf0) >> 4);
char lowNibble = (char) (cardTemp & 0x0f);
wiegandType = bitCount;
bitCount = 0;
cardTemp = 0;
cardTempHigh = 0;
if (lowNibble == (~highNibble & 0x0f)) { // check if low nibble matches the "NOT" of high nibble.
if (lowNibble == 0x0b) { // ENT pressed
code = 0x0d;
} else if (lowNibble == 0x0a) { // ESC pressed
code = 0x1b;
} else {
code = (int) lowNibble; // 0 - 9 keys
}
return true;
}
}
} else {
// well time over 25 ms and bitCount !=8 , !=26, !=34 , must be noise or nothing then.
lastWiegand = sysTick;
bitCount = 0;
cardTemp = 0;
cardTempHigh = 0;
return false;
}
}
return false;
}
}
And called from my Activity here:
Wiegand wiegand = new Wiegand();
wiegand.begin();
Log.d(TAG, wiegand.getCode() + "");
It's a work in progress but it is working: https://gist.github.com/austinn/e9b6daa322e928c8cf3e06b06cdfb3c5