mbed.org local branch of microbit-dal. The real version lives in git at https://github.com/lancaster-university/microbit-dal

Dependencies:   BLE_API nRF51822 mbed-dev-bin

Dependents:   microbit Microbit IoTChallenge1 microbit ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MicroBitPin.cpp Source File

MicroBitPin.cpp

00001 /*
00002 The MIT License (MIT)
00003 
00004 Copyright (c) 2016 British Broadcasting Corporation.
00005 This software is provided by Lancaster University by arrangement with the BBC.
00006 
00007 Permission is hereby granted, free of charge, to any person obtaining a
00008 copy of this software and associated documentation files (the "Software"),
00009 to deal in the Software without restriction, including without limitation
00010 the rights to use, copy, modify, merge, publish, distribute, sublicense,
00011 and/or sell copies of the Software, and to permit persons to whom the
00012 Software is furnished to do so, subject to the following conditions:
00013 
00014 The above copyright notice and this permission notice shall be included in
00015 all copies or substantial portions of the Software.
00016 
00017 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00018 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00019 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
00020 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00021 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
00022 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
00023 DEALINGS IN THE SOFTWARE.
00024 */
00025 
00026 /**
00027   * Class definition for MicroBitPin.
00028   *
00029   * Commonly represents an I/O pin on the edge connector.
00030   */
00031 #include "MicroBitConfig.h"
00032 #include "MicroBitPin.h"
00033 #include "MicroBitButton.h"
00034 #include "MicroBitSystemTimer.h"
00035 #include "TimedInterruptIn.h"
00036 #include "DynamicPwm.h"
00037 #include "ErrorNo.h"
00038 
00039 /**
00040   * Constructor.
00041   * Create a MicroBitPin instance, generally used to represent a pin on the edge connector.
00042   *
00043   * @param id the unique EventModel id of this component.
00044   *
00045   * @param name the mbed PinName for this MicroBitPin instance.
00046   *
00047   * @param capability the capabilities this MicroBitPin instance should have.
00048   *                   (PIN_CAPABILITY_DIGITAL, PIN_CAPABILITY_ANALOG, PIN_CAPABILITY_AD, PIN_CAPABILITY_ALL)
00049   *
00050   * @code
00051   * MicroBitPin P0(MICROBIT_ID_IO_P0, MICROBIT_PIN_P0, PIN_CAPABILITY_ALL);
00052   * @endcode
00053   */
00054 MicroBitPin::MicroBitPin(int id, PinName name, PinCapability capability)
00055 {
00056     //set mandatory attributes
00057     this->id = id;
00058     this->name = name;
00059     this->capability = capability;
00060     this->pullMode = MICROBIT_DEFAULT_PULLMODE;
00061 
00062     // Power up in a disconnected, low power state.
00063     // If we're unused, this is how it will stay...
00064     this->status = 0x00;
00065     this->pin = NULL;
00066 
00067 }
00068 
00069 /**
00070   * Disconnect any attached mBed IO from this pin.
00071   *
00072   * Used only when pin changes mode (i.e. Input/Output/Analog/Digital)
00073   */
00074 void MicroBitPin::disconnect()
00075 {
00076     // This is a bit ugly, but rarely used code.
00077     // It would be much better to use some polymorphism here, but the mBed I/O classes aren't arranged in an inheritance hierarchy... yet. :-)
00078     if (status & IO_STATUS_DIGITAL_IN)
00079         delete ((DigitalIn *)pin);
00080 
00081     if (status & IO_STATUS_DIGITAL_OUT)
00082         delete ((DigitalOut *)pin);
00083 
00084     if (status & IO_STATUS_ANALOG_IN){
00085         NRF_ADC->ENABLE = ADC_ENABLE_ENABLE_Disabled; // forcibly disable the ADC - BUG in mbed....
00086         delete ((AnalogIn *)pin);
00087     }
00088 
00089     if (status & IO_STATUS_ANALOG_OUT)
00090     {
00091         if(((DynamicPwm *)pin)->getPinName() == name)
00092             ((DynamicPwm *)pin)->release();
00093     }
00094 
00095     if (status & IO_STATUS_TOUCH_IN)
00096         delete ((MicroBitButton *)pin);
00097 
00098     if ((status & IO_STATUS_EVENT_ON_EDGE) || (status & IO_STATUS_EVENT_PULSE_ON_EDGE))
00099         delete ((TimedInterruptIn *)pin);
00100 
00101     this->pin = NULL;
00102     this->status = 0;
00103 }
00104 
00105 /**
00106   * Configures this IO pin as a digital output (if necessary) and sets the pin to 'value'.
00107   *
00108   * @param value 0 (LO) or 1 (HI)
00109   *
00110   * @return MICROBIT_OK on success, MICROBIT_INVALID_PARAMETER if value is out of range, or MICROBIT_NOT_SUPPORTED
00111   *         if the given pin does not have digital capability.
00112   *
00113   * @code
00114   * MicroBitPin P0(MICROBIT_ID_IO_P0, MICROBIT_PIN_P0, PIN_CAPABILITY_BOTH);
00115   * P0.setDigitalValue(1); // P0 is now HI
00116   * @endcode
00117   */
00118 int MicroBitPin::setDigitalValue(int value)
00119 {
00120     // Check if this pin has a digital mode...
00121     if(!(PIN_CAPABILITY_DIGITAL & capability))
00122         return MICROBIT_NOT_SUPPORTED;
00123 
00124     // Ensure we have a valid value.
00125     if (value < 0 || value > 1)
00126         return MICROBIT_INVALID_PARAMETER;
00127 
00128     // Move into a Digital input state if necessary.
00129     if (!(status & IO_STATUS_DIGITAL_OUT)){
00130         disconnect();
00131         pin = new DigitalOut(name);
00132         status |= IO_STATUS_DIGITAL_OUT;
00133     }
00134 
00135     // Write the value.
00136     ((DigitalOut *)pin)->write(value);
00137 
00138     return MICROBIT_OK;
00139 }
00140 
00141 /**
00142   * Configures this IO pin as a digital input (if necessary) and tests its current value.
00143   *
00144   *
00145   * @return 1 if this input is high, 0 if input is LO, or MICROBIT_NOT_SUPPORTED
00146   *         if the given pin does not have digital capability.
00147   *
00148   * @code
00149   * MicroBitPin P0(MICROBIT_ID_IO_P0, MICROBIT_PIN_P0, PIN_CAPABILITY_BOTH);
00150   * P0.getDigitalValue(); // P0 is either 0 or 1;
00151   * @endcode
00152   */
00153 int MicroBitPin::getDigitalValue()
00154 {
00155     //check if this pin has a digital mode...
00156     if(!(PIN_CAPABILITY_DIGITAL & capability))
00157         return MICROBIT_NOT_SUPPORTED;
00158 
00159     // Move into a Digital input state if necessary.
00160     if (!(status & (IO_STATUS_DIGITAL_IN | IO_STATUS_EVENT_ON_EDGE | IO_STATUS_EVENT_PULSE_ON_EDGE)))
00161     {
00162         disconnect();
00163         pin = new DigitalIn(name, (PinMode)pullMode);
00164         status |= IO_STATUS_DIGITAL_IN;
00165     }
00166 
00167     if(status & (IO_STATUS_EVENT_ON_EDGE | IO_STATUS_EVENT_PULSE_ON_EDGE))
00168         return ((TimedInterruptIn *)pin)->read();
00169 
00170     return ((DigitalIn *)pin)->read();
00171 }
00172 
00173 /**
00174  * Configures this IO pin as a digital input with the specified internal pull-up/pull-down configuraiton (if necessary) and tests its current value.
00175  *
00176  * @param pull one of the mbed pull configurations: PullUp, PullDown, PullNone
00177  *
00178  * @return 1 if this input is high, 0 if input is LO, or MICROBIT_NOT_SUPPORTED
00179  *         if the given pin does not have digital capability.
00180  *
00181  * @code
00182  * MicroBitPin P0(MICROBIT_ID_IO_P0, MICROBIT_PIN_P0, PIN_CAPABILITY_BOTH);
00183  * P0.getDigitalValue(PullUp); // P0 is either 0 or 1;
00184  * @endcode
00185  */
00186 int MicroBitPin::getDigitalValue(PinMode pull)
00187 {
00188     setPull(pull);
00189     return getDigitalValue();
00190 }
00191 
00192 int MicroBitPin::obtainAnalogChannel()
00193 {
00194     // Move into an analogue input state if necessary, if we are no longer the focus of a DynamicPWM instance, allocate ourselves again!
00195     if (!(status & IO_STATUS_ANALOG_OUT) || !(((DynamicPwm *)pin)->getPinName() == name)){
00196         disconnect();
00197         pin = (void *)DynamicPwm::allocate(name);
00198         status |= IO_STATUS_ANALOG_OUT;
00199     }
00200 
00201     return MICROBIT_OK;
00202 }
00203 
00204 /**
00205   * Configures this IO pin as an analog/pwm output, and change the output value to the given level.
00206   *
00207   * @param value the level to set on the output pin, in the range 0 - 1024
00208   *
00209   * @return MICROBIT_OK on success, MICROBIT_INVALID_PARAMETER if value is out of range, or MICROBIT_NOT_SUPPORTED
00210   *         if the given pin does not have analog capability.
00211   */
00212 int MicroBitPin::setAnalogValue(int value)
00213 {
00214     //check if this pin has an analogue mode...
00215     if(!(PIN_CAPABILITY_ANALOG & capability))
00216         return MICROBIT_NOT_SUPPORTED;
00217 
00218     //sanitise the level value
00219     if(value < 0 || value > MICROBIT_PIN_MAX_OUTPUT)
00220         return MICROBIT_INVALID_PARAMETER;
00221 
00222     float level = (float)value / float(MICROBIT_PIN_MAX_OUTPUT);
00223 
00224     //obtain use of the DynamicPwm instance, if it has changed / configure if we do not have one
00225     if(obtainAnalogChannel() == MICROBIT_OK)
00226         return ((DynamicPwm *)pin)->write(level);
00227 
00228     return MICROBIT_OK;
00229 }
00230 
00231 /**
00232   * Configures this IO pin as an analog/pwm output (if necessary) and configures the period to be 20ms,
00233   * with a duty cycle between 500 us and 2500 us.
00234   *
00235   * A value of 180 sets the duty cycle to be 2500us, and a value of 0 sets the duty cycle to be 500us by default.
00236   *
00237   * This range can be modified to fine tune, and also tolerate different servos.
00238   *
00239   * @param value the level to set on the output pin, in the range 0 - 180.
00240   *
00241   * @param range which gives the span of possible values the i.e. the lower and upper bounds (center +/- range/2). Defaults to MICROBIT_PIN_DEFAULT_SERVO_RANGE.
00242   *
00243   * @param center the center point from which to calculate the lower and upper bounds. Defaults to MICROBIT_PIN_DEFAULT_SERVO_CENTER
00244   *
00245   * @return MICROBIT_OK on success, MICROBIT_INVALID_PARAMETER if value is out of range, or MICROBIT_NOT_SUPPORTED
00246   *         if the given pin does not have analog capability.
00247   */
00248 int MicroBitPin::setServoValue(int value, int range, int center)
00249 {
00250     //check if this pin has an analogue mode...
00251     if(!(PIN_CAPABILITY_ANALOG & capability))
00252         return MICROBIT_NOT_SUPPORTED;
00253 
00254     //sanitise the servo level
00255     if(value < 0 || range < 1 || center < 1)
00256         return MICROBIT_INVALID_PARAMETER;
00257 
00258     //clip - just in case
00259     if(value > MICROBIT_PIN_MAX_SERVO_RANGE)
00260         value = MICROBIT_PIN_MAX_SERVO_RANGE;
00261 
00262     //calculate the lower bound based on the midpoint
00263     int lower = (center - (range / 2)) * 1000;
00264 
00265     value = value * 1000;
00266 
00267     //add the percentage of the range based on the value between 0 and 180
00268     int scaled = lower + (range * (value / MICROBIT_PIN_MAX_SERVO_RANGE));
00269 
00270     return setServoPulseUs(scaled / 1000);
00271 }
00272 
00273 /**
00274   * Configures this IO pin as an analogue input (if necessary), and samples the Pin for its analog value.
00275   *
00276   * @return the current analogue level on the pin, in the range 0 - 1024, or
00277   *         MICROBIT_NOT_SUPPORTED if the given pin does not have analog capability.
00278   *
00279   * @code
00280   * MicroBitPin P0(MICROBIT_ID_IO_P0, MICROBIT_PIN_P0, PIN_CAPABILITY_BOTH);
00281   * P0.getAnalogValue(); // P0 is a value in the range of 0 - 1024
00282   * @endcode
00283   */
00284 int MicroBitPin::getAnalogValue()
00285 {
00286     //check if this pin has an analogue mode...
00287     if(!(PIN_CAPABILITY_ANALOG & capability))
00288         return MICROBIT_NOT_SUPPORTED;
00289 
00290     // Move into an analogue input state if necessary.
00291     if (!(status & IO_STATUS_ANALOG_IN)){
00292         disconnect();
00293         pin = new AnalogIn(name);
00294         status |= IO_STATUS_ANALOG_IN;
00295     }
00296 
00297     //perform a read!
00298     return ((AnalogIn *)pin)->read_u16();
00299 }
00300 
00301 /**
00302   * Determines if this IO pin is currently configured as an input.
00303   *
00304   * @return 1 if pin is an analog or digital input, 0 otherwise.
00305   */
00306 int MicroBitPin::isInput()
00307 {
00308     return (status & (IO_STATUS_DIGITAL_IN | IO_STATUS_ANALOG_IN)) == 0 ? 0 : 1;
00309 }
00310 
00311 /**
00312   * Determines if this IO pin is currently configured as an output.
00313   *
00314   * @return 1 if pin is an analog or digital output, 0 otherwise.
00315   */
00316 int MicroBitPin::isOutput()
00317 {
00318     return (status & (IO_STATUS_DIGITAL_OUT | IO_STATUS_ANALOG_OUT)) == 0 ? 0 : 1;
00319 }
00320 
00321 /**
00322   * Determines if this IO pin is currently configured for digital use.
00323   *
00324   * @return 1 if pin is digital, 0 otherwise.
00325   */
00326 int MicroBitPin::isDigital()
00327 {
00328     return (status & (IO_STATUS_DIGITAL_IN | IO_STATUS_DIGITAL_OUT)) == 0 ? 0 : 1;
00329 }
00330 
00331 /**
00332   * Determines if this IO pin is currently configured for analog use.
00333   *
00334   * @return 1 if pin is analog, 0 otherwise.
00335   */
00336 int MicroBitPin::isAnalog()
00337 {
00338     return (status & (IO_STATUS_ANALOG_IN | IO_STATUS_ANALOG_OUT)) == 0 ? 0 : 1;
00339 }
00340 
00341 /**
00342   * Configures this IO pin as a "makey makey" style touch sensor (if necessary)
00343   * and tests its current debounced state.
00344   *
00345   * Users can also subscribe to MicroBitButton events generated from this pin.
00346   *
00347   * @return 1 if pin is touched, 0 if not, or MICROBIT_NOT_SUPPORTED if this pin does not support touch capability.
00348   *
00349   * @code
00350   * MicroBitMessageBus bus;
00351   *
00352   * MicroBitPin P0(MICROBIT_ID_IO_P0, MICROBIT_PIN_P0, PIN_CAPABILITY_ALL);
00353   * if(P0.isTouched())
00354   * {
00355   *     //do something!
00356   * }
00357   *
00358   * // subscribe to events generated by this pin!
00359   * bus.listen(MICROBIT_ID_IO_P0, MICROBIT_BUTTON_EVT_CLICK, someFunction);
00360   * @endcode
00361   */
00362 int MicroBitPin::isTouched()
00363 {
00364     //check if this pin has a touch mode...
00365     if(!(PIN_CAPABILITY_DIGITAL & capability))
00366         return MICROBIT_NOT_SUPPORTED;
00367 
00368     // Move into a touch input state if necessary.
00369     if (!(status & IO_STATUS_TOUCH_IN)){
00370         disconnect();
00371         pin = new MicroBitButton(name, id);
00372         status |= IO_STATUS_TOUCH_IN;
00373     }
00374 
00375     return ((MicroBitButton *)pin)->isPressed();
00376 }
00377 
00378 /**
00379   * Configures this IO pin as an analog/pwm output if it isn't already, configures the period to be 20ms,
00380   * and sets the pulse width, based on the value it is given.
00381   *
00382   * @param pulseWidth the desired pulse width in microseconds.
00383   *
00384   * @return MICROBIT_OK on success, MICROBIT_INVALID_PARAMETER if value is out of range, or MICROBIT_NOT_SUPPORTED
00385   *         if the given pin does not have analog capability.
00386   */
00387 int MicroBitPin::setServoPulseUs(int pulseWidth)
00388 {
00389     //check if this pin has an analogue mode...
00390     if(!(PIN_CAPABILITY_ANALOG & capability))
00391         return MICROBIT_NOT_SUPPORTED;
00392 
00393     //sanitise the pulse width
00394     if(pulseWidth < 0)
00395         return MICROBIT_INVALID_PARAMETER;
00396 
00397     //Check we still have the control over the DynamicPwm instance
00398     if(obtainAnalogChannel() == MICROBIT_OK)
00399     {
00400         //check if the period is set to 20ms
00401         if(((DynamicPwm *)pin)->getPeriodUs() != MICROBIT_DEFAULT_PWM_PERIOD)
00402             ((DynamicPwm *)pin)->setPeriodUs(MICROBIT_DEFAULT_PWM_PERIOD);
00403 
00404         ((DynamicPwm *)pin)->pulsewidth_us(pulseWidth);
00405     }
00406 
00407     return MICROBIT_OK;
00408 }
00409 
00410 /**
00411   * Configures the PWM period of the analog output to the given value.
00412   *
00413   * @param period The new period for the analog output in microseconds.
00414   *
00415   * @return MICROBIT_OK on success, or MICROBIT_NOT_SUPPORTED if the
00416   *         given pin is not configured as an analog output.
00417   */
00418 int MicroBitPin::setAnalogPeriodUs(int period)
00419 {
00420     if (!(status & IO_STATUS_ANALOG_OUT))
00421         return MICROBIT_NOT_SUPPORTED;
00422 
00423     return ((DynamicPwm *)pin)->setPeriodUs(period);
00424 }
00425 
00426 /**
00427   * Configures the PWM period of the analog output to the given value.
00428   *
00429   * @param period The new period for the analog output in milliseconds.
00430   *
00431   * @return MICROBIT_OK on success, or MICROBIT_NOT_SUPPORTED if the
00432   *         given pin is not configured as an analog output.
00433   */
00434 int MicroBitPin::setAnalogPeriod(int period)
00435 {
00436     return setAnalogPeriodUs(period*1000);
00437 }
00438 
00439 /**
00440   * Obtains the PWM period of the analog output in microseconds.
00441   *
00442   * @return the period on success, or MICROBIT_NOT_SUPPORTED if the
00443   *         given pin is not configured as an analog output.
00444   */
00445 int MicroBitPin::getAnalogPeriodUs()
00446 {
00447     if (!(status & IO_STATUS_ANALOG_OUT))
00448         return MICROBIT_NOT_SUPPORTED;
00449 
00450     return ((DynamicPwm *)pin)->getPeriodUs();
00451 }
00452 
00453 /**
00454   * Obtains the PWM period of the analog output in milliseconds.
00455   *
00456   * @return the period on success, or MICROBIT_NOT_SUPPORTED if the
00457   *         given pin is not configured as an analog output.
00458   */
00459 int MicroBitPin::getAnalogPeriod()
00460 {
00461     return getAnalogPeriodUs()/1000;
00462 }
00463 
00464 /**
00465   * Configures the pull of this pin.
00466   *
00467   * @param pull one of the mbed pull configurations: PullUp, PullDown, PullNone
00468   *
00469   * @return MICROBIT_NOT_SUPPORTED if the current pin configuration is anything other
00470   *         than a digital input, otherwise MICROBIT_OK.
00471   */
00472 int MicroBitPin::setPull(PinMode pull)
00473 {
00474     pullMode = pull;
00475 
00476     if ((status & IO_STATUS_DIGITAL_IN))
00477     {
00478         ((DigitalIn *)pin)->mode(pull);
00479         return MICROBIT_OK;
00480     }
00481 
00482     if((status & IO_STATUS_EVENT_ON_EDGE) || (status & IO_STATUS_EVENT_PULSE_ON_EDGE))
00483     {
00484         ((TimedInterruptIn *)pin)->mode(pull);
00485         return MICROBIT_OK;
00486     }
00487 
00488     return MICROBIT_NOT_SUPPORTED;
00489 }
00490 
00491 /**
00492   * This member function manages the calculation of the timestamp of a pulse detected
00493   * on a pin whilst in IO_STATUS_EVENT_PULSE_ON_EDGE or IO_STATUS_EVENT_ON_EDGE modes.
00494   *
00495   * @param eventValue the event value to distribute onto the message bus.
00496   */
00497 void MicroBitPin::pulseWidthEvent(int eventValue)
00498 {
00499     MicroBitEvent evt(id, eventValue, CREATE_ONLY);
00500     uint64_t now = evt.timestamp;
00501     uint64_t previous = ((TimedInterruptIn *)pin)->getTimestamp();
00502 
00503     if (previous != 0)
00504     {
00505         evt.timestamp -= previous;
00506         evt.fire();
00507     }
00508 
00509     ((TimedInterruptIn *)pin)->setTimestamp(now);
00510 }
00511 
00512 /**
00513   * Interrupt handler for when an rise interrupt is triggered.
00514   */
00515 void MicroBitPin::onRise()
00516 {
00517     if(status & IO_STATUS_EVENT_PULSE_ON_EDGE)
00518         pulseWidthEvent(MICROBIT_PIN_EVT_PULSE_LO);
00519 
00520     if(status & IO_STATUS_EVENT_ON_EDGE)
00521         MicroBitEvent(id, MICROBIT_PIN_EVT_RISE);
00522 }
00523 
00524 /**
00525   * Interrupt handler for when an fall interrupt is triggered.
00526   */
00527 void MicroBitPin::onFall()
00528 {
00529     if(status & IO_STATUS_EVENT_PULSE_ON_EDGE)
00530         pulseWidthEvent(MICROBIT_PIN_EVT_PULSE_HI);
00531 
00532     if(status & IO_STATUS_EVENT_ON_EDGE)
00533         MicroBitEvent(id, MICROBIT_PIN_EVT_FALL);
00534 }
00535 
00536 /**
00537   * This member function will construct an TimedInterruptIn instance, and configure
00538   * interrupts for rise and fall.
00539   *
00540   * @param eventType the specific mode used in interrupt context to determine how an
00541   *                  edge/rise is processed.
00542   *
00543   * @return MICROBIT_OK on success
00544   */
00545 int MicroBitPin::enableRiseFallEvents(int eventType)
00546 {
00547     // if we are in neither of the two modes, configure pin as a TimedInterruptIn.
00548     if (!(status & (IO_STATUS_EVENT_ON_EDGE | IO_STATUS_EVENT_PULSE_ON_EDGE)))
00549     {
00550         disconnect();
00551         pin = new TimedInterruptIn(name);
00552 
00553         ((TimedInterruptIn *)pin)->mode((PinMode)pullMode);
00554         ((TimedInterruptIn *)pin)->rise(this, &MicroBitPin::onRise);
00555         ((TimedInterruptIn *)pin)->fall(this, &MicroBitPin::onFall);
00556     }
00557 
00558     status &= ~(IO_STATUS_EVENT_ON_EDGE | IO_STATUS_EVENT_PULSE_ON_EDGE);
00559 
00560     // set our status bits accordingly.
00561     if(eventType == MICROBIT_PIN_EVENT_ON_EDGE)
00562         status |= IO_STATUS_EVENT_ON_EDGE;
00563     else if(eventType == MICROBIT_PIN_EVENT_ON_PULSE)
00564         status |= IO_STATUS_EVENT_PULSE_ON_EDGE;
00565 
00566     return MICROBIT_OK;
00567 }
00568 
00569 /**
00570   * If this pin is in a mode where the pin is generating events, it will destruct
00571   * the current instance attached to this MicroBitPin instance.
00572   *
00573   * @return MICROBIT_OK on success.
00574   */
00575 int MicroBitPin::disableEvents()
00576 {
00577     if (status & (IO_STATUS_EVENT_ON_EDGE | IO_STATUS_EVENT_PULSE_ON_EDGE | IO_STATUS_TOUCH_IN))
00578         disconnect();
00579 
00580     return MICROBIT_OK;
00581 }
00582 
00583 /**
00584   * Configures the events generated by this MicroBitPin instance.
00585   *
00586   * 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)
00587   * 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)
00588   * 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.
00589   * MICROBIT_PIN_EVENT_NONE - Disables events for this pin.
00590   *
00591   * @param eventType One of: MICROBIT_PIN_EVENT_ON_EDGE, MICROBIT_PIN_EVENT_ON_PULSE, MICROBIT_PIN_EVENT_ON_TOUCH, MICROBIT_PIN_EVENT_NONE
00592   *
00593   * @code
00594   * MicroBitMessageBus bus;
00595   *
00596   * MicroBitPin P0(MICROBIT_ID_IO_P0, MICROBIT_PIN_P0, PIN_CAPABILITY_BOTH);
00597   * P0.eventOn(MICROBIT_PIN_EVENT_ON_PULSE);
00598   *
00599   * void onPulse(MicroBitEvent evt)
00600   * {
00601   *     int duration = evt.timestamp;
00602   * }
00603   *
00604   * bus.listen(MICROBIT_ID_IO_P0, MICROBIT_PIN_EVT_PULSE_HI, onPulse, MESSAGE_BUS_LISTENER_IMMEDIATE)
00605   * @endcode
00606   *
00607   * @return MICROBIT_OK on success, or MICROBIT_INVALID_PARAMETER if the given eventype does not match
00608   *
00609   * @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,
00610   *       please use the InterruptIn class supplied by ARM mbed.
00611   */
00612 int MicroBitPin::eventOn(int eventType)
00613 {
00614     switch(eventType)
00615     {
00616         case MICROBIT_PIN_EVENT_ON_EDGE:
00617         case MICROBIT_PIN_EVENT_ON_PULSE:
00618             enableRiseFallEvents(eventType);
00619             break;
00620 
00621         case MICROBIT_PIN_EVENT_ON_TOUCH:
00622             isTouched();
00623             break;
00624 
00625         case MICROBIT_PIN_EVENT_NONE:
00626             disableEvents();
00627             break;
00628 
00629         default:
00630             return MICROBIT_INVALID_PARAMETER;
00631     }
00632 
00633     return MICROBIT_OK;
00634 }