Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: BLE_API mbed-dev-bin nRF51822
Fork of microbit-dal by
Diff: source/drivers/MicroBitPin.cpp
- Revision:
- 49:88f03f3feff1
- Parent:
- 45:23b71960fe6c
- Child:
- 53:ee44932401cb
--- a/source/drivers/MicroBitPin.cpp Wed Jul 13 12:18:27 2016 +0100
+++ b/source/drivers/MicroBitPin.cpp Wed Jul 13 12:18:28 2016 +0100
@@ -31,6 +31,8 @@
#include "MicroBitConfig.h"
#include "MicroBitPin.h"
#include "MicroBitButton.h"
+#include "MicroBitSystemTimer.h"
+#include "TimedInterruptIn.h"
#include "DynamicPwm.h"
#include "ErrorNo.h"
@@ -92,8 +94,11 @@
if (status & IO_STATUS_TOUCH_IN)
delete ((MicroBitButton *)pin);
+ if ((status & IO_STATUS_EVENT_ON_EDGE) || (status & IO_STATUS_EVENT_PULSE_ON_EDGE))
+ delete ((TimedInterruptIn *)pin);
+
this->pin = NULL;
- this->status = status & IO_STATUS_EVENTBUS_ENABLED; //retain event bus status
+ this->status = 0;
}
/**
@@ -135,8 +140,9 @@
/**
* Configures this IO pin as a digital input (if necessary) and tests its current value.
*
+ *
* @return 1 if this input is high, 0 if input is LO, or MICROBIT_NOT_SUPPORTED
- * if the given pin does not have analog capability.
+ * if the given pin does not have digital capability.
*
* @code
* MicroBitPin P0(MICROBIT_ID_IO_P0, MICROBIT_PIN_P0, PIN_CAPABILITY_BOTH);
@@ -150,12 +156,16 @@
return MICROBIT_NOT_SUPPORTED;
// Move into a Digital input state if necessary.
- if (!(status & IO_STATUS_DIGITAL_IN)){
+ if (!(status & (IO_STATUS_DIGITAL_IN | IO_STATUS_EVENT_ON_EDGE | IO_STATUS_EVENT_PULSE_ON_EDGE)))
+ {
disconnect();
pin = new DigitalIn(name,PullDown);
status |= IO_STATUS_DIGITAL_IN;
}
+ if(status & (IO_STATUS_EVENT_ON_EDGE | IO_STATUS_EVENT_PULSE_ON_EDGE))
+ return ((TimedInterruptIn *)pin)->read();
+
return ((DigitalIn *)pin)->read();
}
@@ -429,4 +439,174 @@
int MicroBitPin::getAnalogPeriod()
{
return getAnalogPeriodUs()/1000;
+}
+
+/**
+ * Configures the pull of this pin.
+ *
+ * @param pull one of the mbed pull configurations: PullUp, PullDown, PullNone, OpenDrain
+ *
+ * @return MICROBIT_NOT_SUPPORTED if the current pin configuration is anything other
+ * than a digital input, otherwise MICROBIT_OK.
+ */
+int MicroBitPin::setPull(PinMode pull)
+{
+ if ((status & IO_STATUS_DIGITAL_IN))
+ {
+ ((DigitalIn *)pin)->mode(pull);
+ return MICROBIT_OK;
+ }
+
+ if((status & IO_STATUS_EVENT_ON_EDGE) || (status & IO_STATUS_EVENT_PULSE_ON_EDGE))
+ {
+ ((TimedInterruptIn *)pin)->mode(pull);
+ return MICROBIT_OK;
+ }
+
+ return MICROBIT_NOT_SUPPORTED;
+}
+
+/**
+ * This member function manages the calculation of the timestamp of a pulse detected
+ * on a pin whilst in IO_STATUS_EVENT_PULSE_ON_EDGE or IO_STATUS_EVENT_ON_EDGE modes.
+ *
+ * @param eventValue the event value to distribute onto the message bus.
+ */
+void MicroBitPin::pulseWidthEvent(int eventValue)
+{
+ MicroBitEvent evt(id, eventValue, CREATE_ONLY);
+ uint64_t now = evt.timestamp;
+ uint64_t previous = ((TimedInterruptIn *)pin)->getTimestamp();
+
+ if (previous != 0)
+ {
+ evt.timestamp -= previous;
+ evt.fire();
+ }
+
+ ((TimedInterruptIn *)pin)->setTimestamp(now);
+}
+
+/**
+ * Interrupt handler for when an rise interrupt is triggered.
+ */
+void MicroBitPin::onRise()
+{
+ if(status & IO_STATUS_EVENT_PULSE_ON_EDGE)
+ pulseWidthEvent(MICROBIT_PIN_EVT_PULSE_LO);
+
+ if(status & IO_STATUS_EVENT_ON_EDGE)
+ MicroBitEvent(id, MICROBIT_PIN_EVT_RISE);
+}
+
+/**
+ * Interrupt handler for when an fall interrupt is triggered.
+ */
+void MicroBitPin::onFall()
+{
+ if(status & IO_STATUS_EVENT_PULSE_ON_EDGE)
+ pulseWidthEvent(MICROBIT_PIN_EVT_PULSE_HI);
+
+ if(status & IO_STATUS_EVENT_ON_EDGE)
+ MicroBitEvent(id, MICROBIT_PIN_EVT_FALL);
+}
+
+/**
+ * This member function will construct an TimedInterruptIn instance, and configure
+ * interrupts for rise and fall.
+ *
+ * @param eventType the specific mode used in interrupt context to determine how an
+ * edge/rise is processed.
+ *
+ * @return MICROBIT_OK on success
+ */
+int MicroBitPin::enableRiseFallEvents(int eventType)
+{
+ // if we are in neither of the two modes, configure pin as a TimedInterruptIn.
+ if (!(status & (IO_STATUS_EVENT_ON_EDGE | IO_STATUS_EVENT_PULSE_ON_EDGE)))
+ {
+ disconnect();
+ pin = new TimedInterruptIn(name);
+
+ ((TimedInterruptIn *)pin)->mode(PullDown);
+ ((TimedInterruptIn *)pin)->rise(this, &MicroBitPin::onRise);
+ ((TimedInterruptIn *)pin)->fall(this, &MicroBitPin::onFall);
+ }
+
+ status &= ~(IO_STATUS_EVENT_ON_EDGE | IO_STATUS_EVENT_PULSE_ON_EDGE);
+
+ // set our status bits accordingly.
+ if(eventType == MICROBIT_PIN_EVENT_ON_EDGE)
+ status |= IO_STATUS_EVENT_ON_EDGE;
+ else if(eventType == MICROBIT_PIN_EVENT_ON_PULSE)
+ status |= IO_STATUS_EVENT_PULSE_ON_EDGE;
+
+ return MICROBIT_OK;
+}
+
+/**
+ * If this pin is in a mode where the pin is generating events, it will destruct
+ * the current instance attached to this MicroBitPin instance.
+ *
+ * @return MICROBIT_OK on success.
+ */
+int MicroBitPin::disableEvents()
+{
+ if (status & (IO_STATUS_EVENT_ON_EDGE | IO_STATUS_EVENT_PULSE_ON_EDGE | IO_STATUS_TOUCH_IN))
+ disconnect();
+
+ return MICROBIT_OK;
+}
+
+/**
+ * Configures the events generated by this MicroBitPin instance.
+ *
+ * MICROBIT_PIN_EVENT_ON_EDGE - Configures this pin to a digital input, and generates events whenever a rise/fall is detected on this pin. (MICROBIT_PIN_EVT_RISE, MICROBIT_PIN_EVT_FALL)
+ * MICROBIT_PIN_EVENT_ON_PULSE - Configures this pin to a digital input, and generates events where the timestamp is the duration that this pin was either HI or LO. (MICROBIT_PIN_EVT_PULSE_HI, MICROBIT_PIN_EVT_PULSE_LO)
+ * MICROBIT_PIN_EVENT_ON_TOUCH - Configures this pin as a makey makey style touch sensor, in the form of a MicroBitButton. Normal button events will be generated using the ID of this pin.
+ * MICROBIT_PIN_EVENT_NONE - Disables events for this pin.
+ *
+ * @param eventType One of: MICROBIT_PIN_EVENT_ON_EDGE, MICROBIT_PIN_EVENT_ON_PULSE, MICROBIT_PIN_EVENT_ON_TOUCH, MICROBIT_PIN_EVENT_NONE
+ *
+ * @code
+ * MicroBitMessageBus bus;
+ *
+ * MicroBitPin P0(MICROBIT_ID_IO_P0, MICROBIT_PIN_P0, PIN_CAPABILITY_BOTH);
+ * P0.eventOn(MICROBIT_PIN_EVENT_ON_PULSE);
+ *
+ * void onPulse(MicroBitEvent evt)
+ * {
+ * int duration = evt.timestamp;
+ * }
+ *
+ * bus.listen(MICROBIT_ID_IO_P0, MICROBIT_PIN_EVT_PULSE_HI, onPulse, MESSAGE_BUS_LISTENER_IMMEDIATE)
+ * @endcode
+ *
+ * @return MICROBIT_OK on success, or MICROBIT_INVALID_PARAMETER if the given eventype does not match
+ *
+ * @note In the MICROBIT_PIN_EVENT_ON_PULSE mode, the smallest pulse that was reliably detected was 85us, around 5khz. If more precision is required,
+ * please use the InterruptIn class supplied by ARM mbed.
+ */
+int MicroBitPin::eventOn(int eventType)
+{
+ switch(eventType)
+ {
+ case MICROBIT_PIN_EVENT_ON_EDGE:
+ case MICROBIT_PIN_EVENT_ON_PULSE:
+ enableRiseFallEvents(eventType);
+ break;
+
+ case MICROBIT_PIN_EVENT_ON_TOUCH:
+ isTouched();
+ break;
+
+ case MICROBIT_PIN_EVENT_NONE:
+ disableEvents();
+ break;
+
+ default:
+ return MICROBIT_INVALID_PARAMETER;
+ }
+
+ return MICROBIT_OK;
}
\ No newline at end of file
