Solution for Bluetooth SIG hands-on training course

Dependencies:   BLE_API mbed-dev-bin nRF51822-bluetooth-mdw

Dependents:   microbit

Fork of microbit-dal-bluetooth-mdw_starter by Martin Woolley

Committer:
LancasterUniversity
Date:
Wed Jul 13 12:17:54 2016 +0100
Revision:
22:23d7b9a4b082
Parent:
1:8aa5cdb4ab67
Child:
35:8ce23bc1af38
Synchronized with git rev 7cf98c22
Author: James Devine
microbit-dal: patch for fiber_wake_on_event

fiber_wake_on_event used to crash after forking a FOB fiber.

It would attempt to obtain a new fiber context, and would place it on the wait queue.
Then when that fiber was paged in, the context of that fiber would not have been
initialised, as the function presumed schedule would be called immediately after
fiber initialisation.

This patch catches that edge case.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Jonathan Austin 1:8aa5cdb4ab67 1 /*
Jonathan Austin 1:8aa5cdb4ab67 2 The MIT License (MIT)
Jonathan Austin 1:8aa5cdb4ab67 3
Jonathan Austin 1:8aa5cdb4ab67 4 Copyright (c) 2016 British Broadcasting Corporation.
Jonathan Austin 1:8aa5cdb4ab67 5 This software is provided by Lancaster University by arrangement with the BBC.
Jonathan Austin 1:8aa5cdb4ab67 6
Jonathan Austin 1:8aa5cdb4ab67 7 Permission is hereby granted, free of charge, to any person obtaining a
Jonathan Austin 1:8aa5cdb4ab67 8 copy of this software and associated documentation files (the "Software"),
Jonathan Austin 1:8aa5cdb4ab67 9 to deal in the Software without restriction, including without limitation
Jonathan Austin 1:8aa5cdb4ab67 10 the rights to use, copy, modify, merge, publish, distribute, sublicense,
Jonathan Austin 1:8aa5cdb4ab67 11 and/or sell copies of the Software, and to permit persons to whom the
Jonathan Austin 1:8aa5cdb4ab67 12 Software is furnished to do so, subject to the following conditions:
Jonathan Austin 1:8aa5cdb4ab67 13
Jonathan Austin 1:8aa5cdb4ab67 14 The above copyright notice and this permission notice shall be included in
Jonathan Austin 1:8aa5cdb4ab67 15 all copies or substantial portions of the Software.
Jonathan Austin 1:8aa5cdb4ab67 16
Jonathan Austin 1:8aa5cdb4ab67 17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Jonathan Austin 1:8aa5cdb4ab67 18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Jonathan Austin 1:8aa5cdb4ab67 19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
Jonathan Austin 1:8aa5cdb4ab67 20 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
Jonathan Austin 1:8aa5cdb4ab67 21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
Jonathan Austin 1:8aa5cdb4ab67 22 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
Jonathan Austin 1:8aa5cdb4ab67 23 DEALINGS IN THE SOFTWARE.
Jonathan Austin 1:8aa5cdb4ab67 24 */
Jonathan Austin 1:8aa5cdb4ab67 25
Jonathan Austin 1:8aa5cdb4ab67 26 /**
Jonathan Austin 1:8aa5cdb4ab67 27 * Class definition for MicroBitPin.
Jonathan Austin 1:8aa5cdb4ab67 28 *
Jonathan Austin 1:8aa5cdb4ab67 29 * Commonly represents an I/O pin on the edge connector.
Jonathan Austin 1:8aa5cdb4ab67 30 */
Jonathan Austin 1:8aa5cdb4ab67 31 #include "MicroBitConfig.h"
Jonathan Austin 1:8aa5cdb4ab67 32 #include "MicroBitPin.h"
Jonathan Austin 1:8aa5cdb4ab67 33 #include "MicroBitButton.h"
Jonathan Austin 1:8aa5cdb4ab67 34 #include "DynamicPwm.h"
Jonathan Austin 1:8aa5cdb4ab67 35 #include "ErrorNo.h"
Jonathan Austin 1:8aa5cdb4ab67 36
Jonathan Austin 1:8aa5cdb4ab67 37 /**
Jonathan Austin 1:8aa5cdb4ab67 38 * Constructor.
Jonathan Austin 1:8aa5cdb4ab67 39 * Create a MicroBitPin instance, generally used to represent a pin on the edge connector.
Jonathan Austin 1:8aa5cdb4ab67 40 *
Jonathan Austin 1:8aa5cdb4ab67 41 * @param id the unique EventModel id of this component.
Jonathan Austin 1:8aa5cdb4ab67 42 *
Jonathan Austin 1:8aa5cdb4ab67 43 * @param name the mbed PinName for this MicroBitPin instance.
Jonathan Austin 1:8aa5cdb4ab67 44 *
Jonathan Austin 1:8aa5cdb4ab67 45 * @param capability the capabilities this MicroBitPin instance should have.
Jonathan Austin 1:8aa5cdb4ab67 46 * (PIN_CAPABILITY_DIGITAL, PIN_CAPABILITY_ANALOG, PIN_CAPABILITY_TOUCH, PIN_CAPABILITY_AD, PIN_CAPABILITY_ALL)
Jonathan Austin 1:8aa5cdb4ab67 47 *
Jonathan Austin 1:8aa5cdb4ab67 48 * @code
Jonathan Austin 1:8aa5cdb4ab67 49 * MicroBitPin P0(MICROBIT_ID_IO_P0, MICROBIT_PIN_P0, PIN_CAPABILITY_ALL);
Jonathan Austin 1:8aa5cdb4ab67 50 * @endcode
Jonathan Austin 1:8aa5cdb4ab67 51 */
Jonathan Austin 1:8aa5cdb4ab67 52 MicroBitPin::MicroBitPin(int id, PinName name, PinCapability capability)
Jonathan Austin 1:8aa5cdb4ab67 53 {
Jonathan Austin 1:8aa5cdb4ab67 54 //set mandatory attributes
Jonathan Austin 1:8aa5cdb4ab67 55 this->id = id;
Jonathan Austin 1:8aa5cdb4ab67 56 this->name = name;
Jonathan Austin 1:8aa5cdb4ab67 57 this->capability = capability;
Jonathan Austin 1:8aa5cdb4ab67 58
Jonathan Austin 1:8aa5cdb4ab67 59 // Power up in a disconnected, low power state.
Jonathan Austin 1:8aa5cdb4ab67 60 // If we're unused, this is how it will stay...
Jonathan Austin 1:8aa5cdb4ab67 61 this->status = 0x00;
Jonathan Austin 1:8aa5cdb4ab67 62 this->pin = NULL;
Jonathan Austin 1:8aa5cdb4ab67 63
Jonathan Austin 1:8aa5cdb4ab67 64 }
Jonathan Austin 1:8aa5cdb4ab67 65
Jonathan Austin 1:8aa5cdb4ab67 66 /**
Jonathan Austin 1:8aa5cdb4ab67 67 * Disconnect any attached mBed IO from this pin.
Jonathan Austin 1:8aa5cdb4ab67 68 *
Jonathan Austin 1:8aa5cdb4ab67 69 * Used only when pin changes mode (i.e. Input/Output/Analog/Digital)
Jonathan Austin 1:8aa5cdb4ab67 70 */
Jonathan Austin 1:8aa5cdb4ab67 71 void MicroBitPin::disconnect()
Jonathan Austin 1:8aa5cdb4ab67 72 {
Jonathan Austin 1:8aa5cdb4ab67 73 // This is a bit ugly, but rarely used code.
Jonathan Austin 1:8aa5cdb4ab67 74 // It would be much better to use some polymorphism here, but the mBed I/O classes aren't arranged in an inheritance hierarchy... yet. :-)
Jonathan Austin 1:8aa5cdb4ab67 75 if (status & IO_STATUS_DIGITAL_IN)
Jonathan Austin 1:8aa5cdb4ab67 76 delete ((DigitalIn *)pin);
Jonathan Austin 1:8aa5cdb4ab67 77
Jonathan Austin 1:8aa5cdb4ab67 78 if (status & IO_STATUS_DIGITAL_OUT)
Jonathan Austin 1:8aa5cdb4ab67 79 delete ((DigitalOut *)pin);
Jonathan Austin 1:8aa5cdb4ab67 80
Jonathan Austin 1:8aa5cdb4ab67 81 if (status & IO_STATUS_ANALOG_IN){
Jonathan Austin 1:8aa5cdb4ab67 82 NRF_ADC->ENABLE = ADC_ENABLE_ENABLE_Disabled; // forcibly disable the ADC - BUG in mbed....
Jonathan Austin 1:8aa5cdb4ab67 83 delete ((AnalogIn *)pin);
Jonathan Austin 1:8aa5cdb4ab67 84 }
Jonathan Austin 1:8aa5cdb4ab67 85
Jonathan Austin 1:8aa5cdb4ab67 86 if (status & IO_STATUS_ANALOG_OUT)
Jonathan Austin 1:8aa5cdb4ab67 87 {
Jonathan Austin 1:8aa5cdb4ab67 88 if(((DynamicPwm *)pin)->getPinName() == name)
Jonathan Austin 1:8aa5cdb4ab67 89 ((DynamicPwm *)pin)->release();
Jonathan Austin 1:8aa5cdb4ab67 90 }
Jonathan Austin 1:8aa5cdb4ab67 91
Jonathan Austin 1:8aa5cdb4ab67 92 if (status & IO_STATUS_TOUCH_IN)
Jonathan Austin 1:8aa5cdb4ab67 93 delete ((MicroBitButton *)pin);
Jonathan Austin 1:8aa5cdb4ab67 94
Jonathan Austin 1:8aa5cdb4ab67 95 this->pin = NULL;
Jonathan Austin 1:8aa5cdb4ab67 96 this->status = status & IO_STATUS_EVENTBUS_ENABLED; //retain event bus status
Jonathan Austin 1:8aa5cdb4ab67 97 }
Jonathan Austin 1:8aa5cdb4ab67 98
Jonathan Austin 1:8aa5cdb4ab67 99 /**
Jonathan Austin 1:8aa5cdb4ab67 100 * Configures this IO pin as a digital output (if necessary) and sets the pin to 'value'.
Jonathan Austin 1:8aa5cdb4ab67 101 *
Jonathan Austin 1:8aa5cdb4ab67 102 * @param value 0 (LO) or 1 (HI)
Jonathan Austin 1:8aa5cdb4ab67 103 *
Jonathan Austin 1:8aa5cdb4ab67 104 * @return MICROBIT_OK on success, MICROBIT_INVALID_PARAMETER if value is out of range, or MICROBIT_NOT_SUPPORTED
Jonathan Austin 1:8aa5cdb4ab67 105 * if the given pin does not have digital capability.
Jonathan Austin 1:8aa5cdb4ab67 106 *
Jonathan Austin 1:8aa5cdb4ab67 107 * @code
Jonathan Austin 1:8aa5cdb4ab67 108 * MicroBitPin P0(MICROBIT_ID_IO_P0, MICROBIT_PIN_P0, PIN_CAPABILITY_BOTH);
Jonathan Austin 1:8aa5cdb4ab67 109 * P0.setDigitalValue(1); // P0 is now HI
Jonathan Austin 1:8aa5cdb4ab67 110 * @endcode
Jonathan Austin 1:8aa5cdb4ab67 111 */
Jonathan Austin 1:8aa5cdb4ab67 112 int MicroBitPin::setDigitalValue(int value)
Jonathan Austin 1:8aa5cdb4ab67 113 {
Jonathan Austin 1:8aa5cdb4ab67 114 // Check if this pin has a digital mode...
Jonathan Austin 1:8aa5cdb4ab67 115 if(!(PIN_CAPABILITY_DIGITAL & capability))
Jonathan Austin 1:8aa5cdb4ab67 116 return MICROBIT_NOT_SUPPORTED;
Jonathan Austin 1:8aa5cdb4ab67 117
Jonathan Austin 1:8aa5cdb4ab67 118 // Ensure we have a valid value.
Jonathan Austin 1:8aa5cdb4ab67 119 if (value < 0 || value > 1)
Jonathan Austin 1:8aa5cdb4ab67 120 return MICROBIT_INVALID_PARAMETER;
Jonathan Austin 1:8aa5cdb4ab67 121
Jonathan Austin 1:8aa5cdb4ab67 122 // Move into a Digital input state if necessary.
Jonathan Austin 1:8aa5cdb4ab67 123 if (!(status & IO_STATUS_DIGITAL_OUT)){
Jonathan Austin 1:8aa5cdb4ab67 124 disconnect();
Jonathan Austin 1:8aa5cdb4ab67 125 pin = new DigitalOut(name);
Jonathan Austin 1:8aa5cdb4ab67 126 status |= IO_STATUS_DIGITAL_OUT;
Jonathan Austin 1:8aa5cdb4ab67 127 }
Jonathan Austin 1:8aa5cdb4ab67 128
Jonathan Austin 1:8aa5cdb4ab67 129 // Write the value.
Jonathan Austin 1:8aa5cdb4ab67 130 ((DigitalOut *)pin)->write(value);
Jonathan Austin 1:8aa5cdb4ab67 131
Jonathan Austin 1:8aa5cdb4ab67 132 return MICROBIT_OK;
Jonathan Austin 1:8aa5cdb4ab67 133 }
Jonathan Austin 1:8aa5cdb4ab67 134
Jonathan Austin 1:8aa5cdb4ab67 135 /**
Jonathan Austin 1:8aa5cdb4ab67 136 * Configures this IO pin as a digital input (if necessary) and tests its current value.
Jonathan Austin 1:8aa5cdb4ab67 137 *
Jonathan Austin 1:8aa5cdb4ab67 138 * @return 1 if this input is high, 0 if input is LO, or MICROBIT_NOT_SUPPORTED
Jonathan Austin 1:8aa5cdb4ab67 139 * if the given pin does not have analog capability.
Jonathan Austin 1:8aa5cdb4ab67 140 *
Jonathan Austin 1:8aa5cdb4ab67 141 * @code
Jonathan Austin 1:8aa5cdb4ab67 142 * MicroBitPin P0(MICROBIT_ID_IO_P0, MICROBIT_PIN_P0, PIN_CAPABILITY_BOTH);
Jonathan Austin 1:8aa5cdb4ab67 143 * P0.getDigitalValue(); // P0 is either 0 or 1;
Jonathan Austin 1:8aa5cdb4ab67 144 * @endcode
Jonathan Austin 1:8aa5cdb4ab67 145 */
Jonathan Austin 1:8aa5cdb4ab67 146 int MicroBitPin::getDigitalValue()
Jonathan Austin 1:8aa5cdb4ab67 147 {
Jonathan Austin 1:8aa5cdb4ab67 148 //check if this pin has a digital mode...
Jonathan Austin 1:8aa5cdb4ab67 149 if(!(PIN_CAPABILITY_DIGITAL & capability))
Jonathan Austin 1:8aa5cdb4ab67 150 return MICROBIT_NOT_SUPPORTED;
Jonathan Austin 1:8aa5cdb4ab67 151
Jonathan Austin 1:8aa5cdb4ab67 152 // Move into a Digital input state if necessary.
Jonathan Austin 1:8aa5cdb4ab67 153 if (!(status & IO_STATUS_DIGITAL_IN)){
Jonathan Austin 1:8aa5cdb4ab67 154 disconnect();
Jonathan Austin 1:8aa5cdb4ab67 155 pin = new DigitalIn(name,PullDown);
Jonathan Austin 1:8aa5cdb4ab67 156 status |= IO_STATUS_DIGITAL_IN;
Jonathan Austin 1:8aa5cdb4ab67 157 }
Jonathan Austin 1:8aa5cdb4ab67 158
Jonathan Austin 1:8aa5cdb4ab67 159 return ((DigitalIn *)pin)->read();
Jonathan Austin 1:8aa5cdb4ab67 160 }
Jonathan Austin 1:8aa5cdb4ab67 161
Jonathan Austin 1:8aa5cdb4ab67 162 int MicroBitPin::obtainAnalogChannel()
Jonathan Austin 1:8aa5cdb4ab67 163 {
Jonathan Austin 1:8aa5cdb4ab67 164 // Move into an analogue input state if necessary, if we are no longer the focus of a DynamicPWM instance, allocate ourselves again!
Jonathan Austin 1:8aa5cdb4ab67 165 if (!(status & IO_STATUS_ANALOG_OUT) || !(((DynamicPwm *)pin)->getPinName() == name)){
Jonathan Austin 1:8aa5cdb4ab67 166 disconnect();
Jonathan Austin 1:8aa5cdb4ab67 167 pin = (void *)DynamicPwm::allocate(name);
Jonathan Austin 1:8aa5cdb4ab67 168 status |= IO_STATUS_ANALOG_OUT;
Jonathan Austin 1:8aa5cdb4ab67 169 }
Jonathan Austin 1:8aa5cdb4ab67 170
Jonathan Austin 1:8aa5cdb4ab67 171 return MICROBIT_OK;
Jonathan Austin 1:8aa5cdb4ab67 172 }
Jonathan Austin 1:8aa5cdb4ab67 173
Jonathan Austin 1:8aa5cdb4ab67 174 /**
Jonathan Austin 1:8aa5cdb4ab67 175 * Configures this IO pin as an analog/pwm output, and change the output value to the given level.
Jonathan Austin 1:8aa5cdb4ab67 176 *
Jonathan Austin 1:8aa5cdb4ab67 177 * @param value the level to set on the output pin, in the range 0 - 1024
Jonathan Austin 1:8aa5cdb4ab67 178 *
Jonathan Austin 1:8aa5cdb4ab67 179 * @return MICROBIT_OK on success, MICROBIT_INVALID_PARAMETER if value is out of range, or MICROBIT_NOT_SUPPORTED
Jonathan Austin 1:8aa5cdb4ab67 180 * if the given pin does not have analog capability.
Jonathan Austin 1:8aa5cdb4ab67 181 */
Jonathan Austin 1:8aa5cdb4ab67 182 int MicroBitPin::setAnalogValue(int value)
Jonathan Austin 1:8aa5cdb4ab67 183 {
Jonathan Austin 1:8aa5cdb4ab67 184 //check if this pin has an analogue mode...
Jonathan Austin 1:8aa5cdb4ab67 185 if(!(PIN_CAPABILITY_ANALOG & capability))
Jonathan Austin 1:8aa5cdb4ab67 186 return MICROBIT_NOT_SUPPORTED;
Jonathan Austin 1:8aa5cdb4ab67 187
Jonathan Austin 1:8aa5cdb4ab67 188 //sanitise the level value
Jonathan Austin 1:8aa5cdb4ab67 189 if(value < 0 || value > MICROBIT_PIN_MAX_OUTPUT)
Jonathan Austin 1:8aa5cdb4ab67 190 return MICROBIT_INVALID_PARAMETER;
Jonathan Austin 1:8aa5cdb4ab67 191
Jonathan Austin 1:8aa5cdb4ab67 192 float level = (float)value / float(MICROBIT_PIN_MAX_OUTPUT);
Jonathan Austin 1:8aa5cdb4ab67 193
Jonathan Austin 1:8aa5cdb4ab67 194 //obtain use of the DynamicPwm instance, if it has changed / configure if we do not have one
Jonathan Austin 1:8aa5cdb4ab67 195 if(obtainAnalogChannel() == MICROBIT_OK)
Jonathan Austin 1:8aa5cdb4ab67 196 return ((DynamicPwm *)pin)->write(level);
Jonathan Austin 1:8aa5cdb4ab67 197
Jonathan Austin 1:8aa5cdb4ab67 198 return MICROBIT_OK;
Jonathan Austin 1:8aa5cdb4ab67 199 }
Jonathan Austin 1:8aa5cdb4ab67 200
Jonathan Austin 1:8aa5cdb4ab67 201 /**
Jonathan Austin 1:8aa5cdb4ab67 202 * Configures this IO pin as an analog/pwm output (if necessary) and configures the period to be 20ms,
Jonathan Austin 1:8aa5cdb4ab67 203 * with a duty cycle between 500 us and 2500 us.
Jonathan Austin 1:8aa5cdb4ab67 204 *
Jonathan Austin 1:8aa5cdb4ab67 205 * 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.
Jonathan Austin 1:8aa5cdb4ab67 206 *
Jonathan Austin 1:8aa5cdb4ab67 207 * This range can be modified to fine tune, and also tolerate different servos.
Jonathan Austin 1:8aa5cdb4ab67 208 *
Jonathan Austin 1:8aa5cdb4ab67 209 * @param value the level to set on the output pin, in the range 0 - 180.
Jonathan Austin 1:8aa5cdb4ab67 210 *
Jonathan Austin 1:8aa5cdb4ab67 211 * @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.
Jonathan Austin 1:8aa5cdb4ab67 212 *
Jonathan Austin 1:8aa5cdb4ab67 213 * @param center the center point from which to calculate the lower and upper bounds. Defaults to MICROBIT_PIN_DEFAULT_SERVO_CENTER
Jonathan Austin 1:8aa5cdb4ab67 214 *
Jonathan Austin 1:8aa5cdb4ab67 215 * @return MICROBIT_OK on success, MICROBIT_INVALID_PARAMETER if value is out of range, or MICROBIT_NOT_SUPPORTED
Jonathan Austin 1:8aa5cdb4ab67 216 * if the given pin does not have analog capability.
Jonathan Austin 1:8aa5cdb4ab67 217 */
Jonathan Austin 1:8aa5cdb4ab67 218 int MicroBitPin::setServoValue(int value, int range, int center)
Jonathan Austin 1:8aa5cdb4ab67 219 {
Jonathan Austin 1:8aa5cdb4ab67 220 //check if this pin has an analogue mode...
Jonathan Austin 1:8aa5cdb4ab67 221 if(!(PIN_CAPABILITY_ANALOG & capability))
Jonathan Austin 1:8aa5cdb4ab67 222 return MICROBIT_NOT_SUPPORTED;
Jonathan Austin 1:8aa5cdb4ab67 223
Jonathan Austin 1:8aa5cdb4ab67 224 //sanitise the servo level
Jonathan Austin 1:8aa5cdb4ab67 225 if(value < 0 || range < 1 || center < 1)
Jonathan Austin 1:8aa5cdb4ab67 226 return MICROBIT_INVALID_PARAMETER;
Jonathan Austin 1:8aa5cdb4ab67 227
Jonathan Austin 1:8aa5cdb4ab67 228 //clip - just in case
Jonathan Austin 1:8aa5cdb4ab67 229 if(value > MICROBIT_PIN_MAX_SERVO_RANGE)
Jonathan Austin 1:8aa5cdb4ab67 230 value = MICROBIT_PIN_MAX_SERVO_RANGE;
Jonathan Austin 1:8aa5cdb4ab67 231
Jonathan Austin 1:8aa5cdb4ab67 232 //calculate the lower bound based on the midpoint
Jonathan Austin 1:8aa5cdb4ab67 233 int lower = (center - (range / 2)) * 1000;
Jonathan Austin 1:8aa5cdb4ab67 234
Jonathan Austin 1:8aa5cdb4ab67 235 value = value * 1000;
Jonathan Austin 1:8aa5cdb4ab67 236
Jonathan Austin 1:8aa5cdb4ab67 237 //add the percentage of the range based on the value between 0 and 180
Jonathan Austin 1:8aa5cdb4ab67 238 int scaled = lower + (range * (value / MICROBIT_PIN_MAX_SERVO_RANGE));
Jonathan Austin 1:8aa5cdb4ab67 239
Jonathan Austin 1:8aa5cdb4ab67 240 return setServoPulseUs(scaled / 1000);
Jonathan Austin 1:8aa5cdb4ab67 241 }
Jonathan Austin 1:8aa5cdb4ab67 242
Jonathan Austin 1:8aa5cdb4ab67 243 /**
Jonathan Austin 1:8aa5cdb4ab67 244 * Configures this IO pin as an analogue input (if necessary), and samples the Pin for its analog value.
Jonathan Austin 1:8aa5cdb4ab67 245 *
Jonathan Austin 1:8aa5cdb4ab67 246 * @return the current analogue level on the pin, in the range 0 - 1024, or
Jonathan Austin 1:8aa5cdb4ab67 247 * MICROBIT_NOT_SUPPORTED if the given pin does not have analog capability.
Jonathan Austin 1:8aa5cdb4ab67 248 *
Jonathan Austin 1:8aa5cdb4ab67 249 * @code
Jonathan Austin 1:8aa5cdb4ab67 250 * MicroBitPin P0(MICROBIT_ID_IO_P0, MICROBIT_PIN_P0, PIN_CAPABILITY_BOTH);
Jonathan Austin 1:8aa5cdb4ab67 251 * P0.getAnalogValue(); // P0 is a value in the range of 0 - 1024
Jonathan Austin 1:8aa5cdb4ab67 252 * @endcode
Jonathan Austin 1:8aa5cdb4ab67 253 */
Jonathan Austin 1:8aa5cdb4ab67 254 int MicroBitPin::getAnalogValue()
Jonathan Austin 1:8aa5cdb4ab67 255 {
Jonathan Austin 1:8aa5cdb4ab67 256 //check if this pin has an analogue mode...
Jonathan Austin 1:8aa5cdb4ab67 257 if(!(PIN_CAPABILITY_ANALOG & capability))
Jonathan Austin 1:8aa5cdb4ab67 258 return MICROBIT_NOT_SUPPORTED;
Jonathan Austin 1:8aa5cdb4ab67 259
Jonathan Austin 1:8aa5cdb4ab67 260 // Move into an analogue input state if necessary.
Jonathan Austin 1:8aa5cdb4ab67 261 if (!(status & IO_STATUS_ANALOG_IN)){
Jonathan Austin 1:8aa5cdb4ab67 262 disconnect();
Jonathan Austin 1:8aa5cdb4ab67 263 pin = new AnalogIn(name);
Jonathan Austin 1:8aa5cdb4ab67 264 status |= IO_STATUS_ANALOG_IN;
Jonathan Austin 1:8aa5cdb4ab67 265 }
Jonathan Austin 1:8aa5cdb4ab67 266
Jonathan Austin 1:8aa5cdb4ab67 267 //perform a read!
Jonathan Austin 1:8aa5cdb4ab67 268 return ((AnalogIn *)pin)->read_u16();
Jonathan Austin 1:8aa5cdb4ab67 269 }
Jonathan Austin 1:8aa5cdb4ab67 270
Jonathan Austin 1:8aa5cdb4ab67 271 /**
Jonathan Austin 1:8aa5cdb4ab67 272 * Determines if this IO pin is currently configured as an input.
Jonathan Austin 1:8aa5cdb4ab67 273 *
Jonathan Austin 1:8aa5cdb4ab67 274 * @return 1 if pin is an analog or digital input, 0 otherwise.
Jonathan Austin 1:8aa5cdb4ab67 275 */
Jonathan Austin 1:8aa5cdb4ab67 276 int MicroBitPin::isInput()
Jonathan Austin 1:8aa5cdb4ab67 277 {
Jonathan Austin 1:8aa5cdb4ab67 278 return (status & (IO_STATUS_DIGITAL_IN | IO_STATUS_ANALOG_IN)) == 0 ? 0 : 1;
Jonathan Austin 1:8aa5cdb4ab67 279 }
Jonathan Austin 1:8aa5cdb4ab67 280
Jonathan Austin 1:8aa5cdb4ab67 281 /**
Jonathan Austin 1:8aa5cdb4ab67 282 * Determines if this IO pin is currently configured as an output.
Jonathan Austin 1:8aa5cdb4ab67 283 *
Jonathan Austin 1:8aa5cdb4ab67 284 * @return 1 if pin is an analog or digital output, 0 otherwise.
Jonathan Austin 1:8aa5cdb4ab67 285 */
Jonathan Austin 1:8aa5cdb4ab67 286 int MicroBitPin::isOutput()
Jonathan Austin 1:8aa5cdb4ab67 287 {
Jonathan Austin 1:8aa5cdb4ab67 288 return (status & (IO_STATUS_DIGITAL_OUT | IO_STATUS_ANALOG_OUT)) == 0 ? 0 : 1;
Jonathan Austin 1:8aa5cdb4ab67 289 }
Jonathan Austin 1:8aa5cdb4ab67 290
Jonathan Austin 1:8aa5cdb4ab67 291 /**
Jonathan Austin 1:8aa5cdb4ab67 292 * Determines if this IO pin is currently configured for digital use.
Jonathan Austin 1:8aa5cdb4ab67 293 *
Jonathan Austin 1:8aa5cdb4ab67 294 * @return 1 if pin is digital, 0 otherwise.
Jonathan Austin 1:8aa5cdb4ab67 295 */
Jonathan Austin 1:8aa5cdb4ab67 296 int MicroBitPin::isDigital()
Jonathan Austin 1:8aa5cdb4ab67 297 {
Jonathan Austin 1:8aa5cdb4ab67 298 return (status & (IO_STATUS_DIGITAL_IN | IO_STATUS_DIGITAL_OUT)) == 0 ? 0 : 1;
Jonathan Austin 1:8aa5cdb4ab67 299 }
Jonathan Austin 1:8aa5cdb4ab67 300
Jonathan Austin 1:8aa5cdb4ab67 301 /**
Jonathan Austin 1:8aa5cdb4ab67 302 * Determines if this IO pin is currently configured for analog use.
Jonathan Austin 1:8aa5cdb4ab67 303 *
Jonathan Austin 1:8aa5cdb4ab67 304 * @return 1 if pin is analog, 0 otherwise.
Jonathan Austin 1:8aa5cdb4ab67 305 */
Jonathan Austin 1:8aa5cdb4ab67 306 int MicroBitPin::isAnalog()
Jonathan Austin 1:8aa5cdb4ab67 307 {
Jonathan Austin 1:8aa5cdb4ab67 308 return (status & (IO_STATUS_ANALOG_IN | IO_STATUS_ANALOG_OUT)) == 0 ? 0 : 1;
Jonathan Austin 1:8aa5cdb4ab67 309 }
Jonathan Austin 1:8aa5cdb4ab67 310
Jonathan Austin 1:8aa5cdb4ab67 311 /**
Jonathan Austin 1:8aa5cdb4ab67 312 * Configures this IO pin as a "makey makey" style touch sensor (if necessary)
Jonathan Austin 1:8aa5cdb4ab67 313 * and tests its current debounced state.
Jonathan Austin 1:8aa5cdb4ab67 314 *
Jonathan Austin 1:8aa5cdb4ab67 315 * Users can also subscribe to MicroBitButton events generated from this pin.
Jonathan Austin 1:8aa5cdb4ab67 316 *
Jonathan Austin 1:8aa5cdb4ab67 317 * @return 1 if pin is touched, 0 if not, or MICROBIT_NOT_SUPPORTED if this pin does not support touch capability.
Jonathan Austin 1:8aa5cdb4ab67 318 *
Jonathan Austin 1:8aa5cdb4ab67 319 * @code
Jonathan Austin 1:8aa5cdb4ab67 320 * MicroBitMessageBus bus;
Jonathan Austin 1:8aa5cdb4ab67 321 *
Jonathan Austin 1:8aa5cdb4ab67 322 * MicroBitPin P0(MICROBIT_ID_IO_P0, MICROBIT_PIN_P0, PIN_CAPABILITY_ALL);
Jonathan Austin 1:8aa5cdb4ab67 323 * if(P0.isTouched())
Jonathan Austin 1:8aa5cdb4ab67 324 * {
Jonathan Austin 1:8aa5cdb4ab67 325 * //do something!
Jonathan Austin 1:8aa5cdb4ab67 326 * }
Jonathan Austin 1:8aa5cdb4ab67 327 *
Jonathan Austin 1:8aa5cdb4ab67 328 * // subscribe to events generated by this pin!
Jonathan Austin 1:8aa5cdb4ab67 329 * bus.listen(MICROBIT_ID_IO_P0, MICROBIT_BUTTON_EVT_CLICK, someFunction);
Jonathan Austin 1:8aa5cdb4ab67 330 * @endcode
Jonathan Austin 1:8aa5cdb4ab67 331 */
Jonathan Austin 1:8aa5cdb4ab67 332 int MicroBitPin::isTouched()
Jonathan Austin 1:8aa5cdb4ab67 333 {
Jonathan Austin 1:8aa5cdb4ab67 334 //check if this pin has a touch mode...
Jonathan Austin 1:8aa5cdb4ab67 335 if(!(PIN_CAPABILITY_TOUCH & capability))
Jonathan Austin 1:8aa5cdb4ab67 336 return MICROBIT_NOT_SUPPORTED;
Jonathan Austin 1:8aa5cdb4ab67 337
Jonathan Austin 1:8aa5cdb4ab67 338 // Move into a touch input state if necessary.
Jonathan Austin 1:8aa5cdb4ab67 339 if (!(status & IO_STATUS_TOUCH_IN)){
Jonathan Austin 1:8aa5cdb4ab67 340 disconnect();
Jonathan Austin 1:8aa5cdb4ab67 341 pin = new MicroBitButton(name, id);
Jonathan Austin 1:8aa5cdb4ab67 342 status |= IO_STATUS_TOUCH_IN;
Jonathan Austin 1:8aa5cdb4ab67 343 }
Jonathan Austin 1:8aa5cdb4ab67 344
Jonathan Austin 1:8aa5cdb4ab67 345 return ((MicroBitButton *)pin)->isPressed();
Jonathan Austin 1:8aa5cdb4ab67 346 }
Jonathan Austin 1:8aa5cdb4ab67 347
Jonathan Austin 1:8aa5cdb4ab67 348 /**
Jonathan Austin 1:8aa5cdb4ab67 349 * Configures this IO pin as an analog/pwm output if it isn't already, configures the period to be 20ms,
Jonathan Austin 1:8aa5cdb4ab67 350 * and sets the pulse width, based on the value it is given.
Jonathan Austin 1:8aa5cdb4ab67 351 *
Jonathan Austin 1:8aa5cdb4ab67 352 * @param pulseWidth the desired pulse width in microseconds.
Jonathan Austin 1:8aa5cdb4ab67 353 *
Jonathan Austin 1:8aa5cdb4ab67 354 * @return MICROBIT_OK on success, MICROBIT_INVALID_PARAMETER if value is out of range, or MICROBIT_NOT_SUPPORTED
Jonathan Austin 1:8aa5cdb4ab67 355 * if the given pin does not have analog capability.
Jonathan Austin 1:8aa5cdb4ab67 356 */
Jonathan Austin 1:8aa5cdb4ab67 357 int MicroBitPin::setServoPulseUs(int pulseWidth)
Jonathan Austin 1:8aa5cdb4ab67 358 {
Jonathan Austin 1:8aa5cdb4ab67 359 //check if this pin has an analogue mode...
Jonathan Austin 1:8aa5cdb4ab67 360 if(!(PIN_CAPABILITY_ANALOG & capability))
Jonathan Austin 1:8aa5cdb4ab67 361 return MICROBIT_NOT_SUPPORTED;
Jonathan Austin 1:8aa5cdb4ab67 362
Jonathan Austin 1:8aa5cdb4ab67 363 //sanitise the pulse width
Jonathan Austin 1:8aa5cdb4ab67 364 if(pulseWidth < 0)
Jonathan Austin 1:8aa5cdb4ab67 365 return MICROBIT_INVALID_PARAMETER;
Jonathan Austin 1:8aa5cdb4ab67 366
Jonathan Austin 1:8aa5cdb4ab67 367 //Check we still have the control over the DynamicPwm instance
Jonathan Austin 1:8aa5cdb4ab67 368 if(obtainAnalogChannel() == MICROBIT_OK)
Jonathan Austin 1:8aa5cdb4ab67 369 {
Jonathan Austin 1:8aa5cdb4ab67 370 //check if the period is set to 20ms
Jonathan Austin 1:8aa5cdb4ab67 371 if(((DynamicPwm *)pin)->getPeriodUs() != MICROBIT_DEFAULT_PWM_PERIOD)
Jonathan Austin 1:8aa5cdb4ab67 372 ((DynamicPwm *)pin)->setPeriodUs(MICROBIT_DEFAULT_PWM_PERIOD);
Jonathan Austin 1:8aa5cdb4ab67 373
Jonathan Austin 1:8aa5cdb4ab67 374 ((DynamicPwm *)pin)->pulsewidth_us(pulseWidth);
Jonathan Austin 1:8aa5cdb4ab67 375 }
Jonathan Austin 1:8aa5cdb4ab67 376
Jonathan Austin 1:8aa5cdb4ab67 377 return MICROBIT_OK;
Jonathan Austin 1:8aa5cdb4ab67 378 }
Jonathan Austin 1:8aa5cdb4ab67 379
Jonathan Austin 1:8aa5cdb4ab67 380 /**
Jonathan Austin 1:8aa5cdb4ab67 381 * Configures the PWM period of the analog output to the given value.
Jonathan Austin 1:8aa5cdb4ab67 382 *
Jonathan Austin 1:8aa5cdb4ab67 383 * @param period The new period for the analog output in microseconds.
Jonathan Austin 1:8aa5cdb4ab67 384 *
Jonathan Austin 1:8aa5cdb4ab67 385 * @return MICROBIT_OK on success, or MICROBIT_NOT_SUPPORTED if the
Jonathan Austin 1:8aa5cdb4ab67 386 * given pin is not configured as an analog output.
Jonathan Austin 1:8aa5cdb4ab67 387 */
Jonathan Austin 1:8aa5cdb4ab67 388 int MicroBitPin::setAnalogPeriodUs(int period)
Jonathan Austin 1:8aa5cdb4ab67 389 {
Jonathan Austin 1:8aa5cdb4ab67 390 if (!(status & IO_STATUS_ANALOG_OUT))
Jonathan Austin 1:8aa5cdb4ab67 391 return MICROBIT_NOT_SUPPORTED;
Jonathan Austin 1:8aa5cdb4ab67 392
Jonathan Austin 1:8aa5cdb4ab67 393 return ((DynamicPwm *)pin)->setPeriodUs(period);
Jonathan Austin 1:8aa5cdb4ab67 394 }
Jonathan Austin 1:8aa5cdb4ab67 395
Jonathan Austin 1:8aa5cdb4ab67 396 /**
Jonathan Austin 1:8aa5cdb4ab67 397 * Configures the PWM period of the analog output to the given value.
Jonathan Austin 1:8aa5cdb4ab67 398 *
Jonathan Austin 1:8aa5cdb4ab67 399 * @param period The new period for the analog output in milliseconds.
Jonathan Austin 1:8aa5cdb4ab67 400 *
Jonathan Austin 1:8aa5cdb4ab67 401 * @return MICROBIT_OK on success, or MICROBIT_NOT_SUPPORTED if the
Jonathan Austin 1:8aa5cdb4ab67 402 * given pin is not configured as an analog output.
Jonathan Austin 1:8aa5cdb4ab67 403 */
Jonathan Austin 1:8aa5cdb4ab67 404 int MicroBitPin::setAnalogPeriod(int period)
Jonathan Austin 1:8aa5cdb4ab67 405 {
Jonathan Austin 1:8aa5cdb4ab67 406 return setAnalogPeriodUs(period*1000);
Jonathan Austin 1:8aa5cdb4ab67 407 }
Jonathan Austin 1:8aa5cdb4ab67 408
Jonathan Austin 1:8aa5cdb4ab67 409 /**
Jonathan Austin 1:8aa5cdb4ab67 410 * Obtains the PWM period of the analog output in microseconds.
Jonathan Austin 1:8aa5cdb4ab67 411 *
Jonathan Austin 1:8aa5cdb4ab67 412 * @return the period on success, or MICROBIT_NOT_SUPPORTED if the
Jonathan Austin 1:8aa5cdb4ab67 413 * given pin is not configured as an analog output.
Jonathan Austin 1:8aa5cdb4ab67 414 */
Jonathan Austin 1:8aa5cdb4ab67 415 int MicroBitPin::getAnalogPeriodUs()
Jonathan Austin 1:8aa5cdb4ab67 416 {
Jonathan Austin 1:8aa5cdb4ab67 417 if (!(status & IO_STATUS_ANALOG_OUT))
Jonathan Austin 1:8aa5cdb4ab67 418 return MICROBIT_NOT_SUPPORTED;
Jonathan Austin 1:8aa5cdb4ab67 419
Jonathan Austin 1:8aa5cdb4ab67 420 return ((DynamicPwm *)pin)->getPeriodUs();
Jonathan Austin 1:8aa5cdb4ab67 421 }
Jonathan Austin 1:8aa5cdb4ab67 422
Jonathan Austin 1:8aa5cdb4ab67 423 /**
Jonathan Austin 1:8aa5cdb4ab67 424 * Obtains the PWM period of the analog output in milliseconds.
Jonathan Austin 1:8aa5cdb4ab67 425 *
Jonathan Austin 1:8aa5cdb4ab67 426 * @return the period on success, or MICROBIT_NOT_SUPPORTED if the
Jonathan Austin 1:8aa5cdb4ab67 427 * given pin is not configured as an analog output.
Jonathan Austin 1:8aa5cdb4ab67 428 */
Jonathan Austin 1:8aa5cdb4ab67 429 int MicroBitPin::getAnalogPeriod()
Jonathan Austin 1:8aa5cdb4ab67 430 {
Jonathan Austin 1:8aa5cdb4ab67 431 return getAnalogPeriodUs()/1000;
Jonathan Austin 1:8aa5cdb4ab67 432 }