128 lines
5.1 KiB
C++
128 lines
5.1 KiB
C++
/*
|
|
DigitalInputFirmata.cpp - Firmata library
|
|
Copyright (C) 2006-2008 Hans-Christoph Steiner. All rights reserved.
|
|
Copyright (C) 2010-2011 Paul Stoffregen. All rights reserved.
|
|
Copyright (C) 2009 Shigeru Kobayashi. All rights reserved.
|
|
Copyright (C) 2013 Norbert Truchsess. All rights reserved.
|
|
Copyright (C) 2009-2015 Jeff Hoefs. All rights reserved.
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2.1 of the License, or (at your option) any later version.
|
|
|
|
See file LICENSE.txt for further informations on licensing terms.
|
|
|
|
Last updated by Jeff Hoefs: November 15th, 2015
|
|
*/
|
|
|
|
#include <ConfigurableFirmata.h>
|
|
#include "DigitalInputFirmata.h"
|
|
|
|
DigitalInputFirmata *DigitalInputFirmataInstance;
|
|
|
|
void reportDigitalInputCallback(byte port, int value)
|
|
{
|
|
DigitalInputFirmataInstance->reportDigital(port, value);
|
|
}
|
|
|
|
DigitalInputFirmata::DigitalInputFirmata()
|
|
{
|
|
DigitalInputFirmataInstance = this;
|
|
Firmata.attach(REPORT_DIGITAL, reportDigitalInputCallback);
|
|
}
|
|
|
|
boolean DigitalInputFirmata::handleSysex(byte command, byte argc, byte* argv)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
void DigitalInputFirmata::outputPort(byte portNumber, byte portValue, byte forceSend)
|
|
{
|
|
// pins not configured as INPUT are cleared to zeros
|
|
portValue = portValue & portConfigInputs[portNumber];
|
|
// only send if the value is different than previously sent
|
|
if (forceSend || previousPINs[portNumber] != portValue) {
|
|
Firmata.sendDigitalPort(portNumber, portValue);
|
|
previousPINs[portNumber] = portValue;
|
|
}
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* check all the active digital inputs for change of state, then add any events
|
|
* to the Serial output queue using Serial.print() */
|
|
void DigitalInputFirmata::report(void)
|
|
{
|
|
/* Using non-looping code allows constants to be given to readPort().
|
|
* The compiler will apply substantial optimizations if the inputs
|
|
* to readPort() are compile-time constants. */
|
|
if (TOTAL_PORTS > 0 && reportPINs[0]) outputPort(0, readPort(0, portConfigInputs[0]), false);
|
|
if (TOTAL_PORTS > 1 && reportPINs[1]) outputPort(1, readPort(1, portConfigInputs[1]), false);
|
|
if (TOTAL_PORTS > 2 && reportPINs[2]) outputPort(2, readPort(2, portConfigInputs[2]), false);
|
|
if (TOTAL_PORTS > 3 && reportPINs[3]) outputPort(3, readPort(3, portConfigInputs[3]), false);
|
|
if (TOTAL_PORTS > 4 && reportPINs[4]) outputPort(4, readPort(4, portConfigInputs[4]), false);
|
|
if (TOTAL_PORTS > 5 && reportPINs[5]) outputPort(5, readPort(5, portConfigInputs[5]), false);
|
|
if (TOTAL_PORTS > 6 && reportPINs[6]) outputPort(6, readPort(6, portConfigInputs[6]), false);
|
|
if (TOTAL_PORTS > 7 && reportPINs[7]) outputPort(7, readPort(7, portConfigInputs[7]), false);
|
|
if (TOTAL_PORTS > 8 && reportPINs[8]) outputPort(8, readPort(8, portConfigInputs[8]), false);
|
|
if (TOTAL_PORTS > 9 && reportPINs[9]) outputPort(9, readPort(9, portConfigInputs[9]), false);
|
|
if (TOTAL_PORTS > 10 && reportPINs[10]) outputPort(10, readPort(10, portConfigInputs[10]), false);
|
|
if (TOTAL_PORTS > 11 && reportPINs[11]) outputPort(11, readPort(11, portConfigInputs[11]), false);
|
|
if (TOTAL_PORTS > 12 && reportPINs[12]) outputPort(12, readPort(12, portConfigInputs[12]), false);
|
|
if (TOTAL_PORTS > 13 && reportPINs[13]) outputPort(13, readPort(13, portConfigInputs[13]), false);
|
|
if (TOTAL_PORTS > 14 && reportPINs[14]) outputPort(14, readPort(14, portConfigInputs[14]), false);
|
|
if (TOTAL_PORTS > 15 && reportPINs[15]) outputPort(15, readPort(15, portConfigInputs[15]), false);
|
|
}
|
|
|
|
void DigitalInputFirmata::reportDigital(byte port, int value)
|
|
{
|
|
if (port < TOTAL_PORTS) {
|
|
reportPINs[port] = (byte)value;
|
|
if (value) outputPort(port, readPort(port, portConfigInputs[port]), true);
|
|
}
|
|
// do not disable analog reporting on these 8 pins, to allow some
|
|
// pins used for digital, others analog. Instead, allow both types
|
|
// of reporting to be enabled, but check if the pin is configured
|
|
// as analog when sampling the analog inputs. Likewise, while
|
|
// scanning digital pins, portConfigInputs will mask off values from any
|
|
// pins configured as analog
|
|
}
|
|
|
|
boolean DigitalInputFirmata::handlePinMode(byte pin, int mode)
|
|
{
|
|
if (IS_PIN_DIGITAL(pin)) {
|
|
if (mode == INPUT || mode == PIN_MODE_PULLUP) {
|
|
portConfigInputs[pin / 8] |= (1 << (pin & 7));
|
|
if (mode == INPUT) {
|
|
pinMode(PIN_TO_DIGITAL(pin), INPUT);
|
|
} else {
|
|
pinMode(PIN_TO_DIGITAL(pin), INPUT_PULLUP);
|
|
Firmata.setPinState(pin, 1);
|
|
}
|
|
return true;
|
|
} else {
|
|
portConfigInputs[pin / 8] &= ~(1 << (pin & 7));
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void DigitalInputFirmata::handleCapability(byte pin)
|
|
{
|
|
if (IS_PIN_DIGITAL(pin)) {
|
|
Firmata.write((byte)INPUT);
|
|
Firmata.write(1);
|
|
Firmata.write((byte)PIN_MODE_PULLUP);
|
|
Firmata.write(1);
|
|
}
|
|
}
|
|
|
|
void DigitalInputFirmata::reset()
|
|
{
|
|
for (byte i = 0; i < TOTAL_PORTS; i++) {
|
|
reportPINs[i] = false; // by default, reporting off
|
|
portConfigInputs[i] = 0; // until activated
|
|
previousPINs[i] = 0;
|
|
}
|
|
}
|