title: Wiegand 26 protocol on Android Things
body: <p>I'm using Android things with a VSIONIS keypad in reader mode, which outputs on D0 and D1 pins in Wiegnad 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?</p>
  
  <p>Here's the <a href="https://github.com/monkeyboard/Wiegand-Protocol-Library-for-Arduino/blob/master/Wiegand.cpp" rel="nofollow noreferrer">Arduino library</a>.</p>
  
  <p>Here's the ported over code:</p>
  
  <pre><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++; // Increament bit count for Interrupt connected to D0
              if (bitCount &gt; 31) { // If bit count more than 31, process high bits
                  cardTempHigh |= ((0x80000000 &amp; cardTemp) &gt;&gt; 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 &gt; 31) { // If bit count more than 31, process high bits
  
                  cardTempHigh |= ((0x80000000 &amp; cardTemp) &gt;&gt; 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 &amp; 0x1FFFFFE) &gt;&gt; 1;
  
          if (bitlength == 34) { // Mifare
              codehigh = codehigh &amp; 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) &gt; 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 &gt;&gt;= 1; // shift right 1 bit to get back the real value - interrupt done 1 left shift in advance
                  if (bitCount &gt; 32) // bit count more than 32 bits, shift high bits right to make adjustment
                      cardTempHigh &gt;&gt;= 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 &amp; 0xf0) &gt;&gt; 4);
                      char lowNibble = (char) (cardTemp &amp; 0x0f);
                      wiegandType = bitCount;
                      bitCount = 0;
                      cardTemp = 0;
                      cardTempHigh = 0;
  
                      if (lowNibble == (~highNibble &amp; 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;
      }
  }
  </code></pre>
  
  <p>And called from my Activity here:</p>
  
  <pre><code>Wiegand wiegand = new Wiegand();
  wiegand.begin();
  Log.d(TAG, wiegand.getCode() + "");
  </code></pre>