developer.mbed.org branch of Lancaster University's microbit library. The real home for this is https://github.com/lancaster-university/microbit

Dependencies:   microbit-dal

Dependents:   microbit-samples microbit_snake microbit_snake microbit-letter-game ... more

Committer:
Jonathan Austin
Date:
Thu Apr 07 01:30:13 2016 +0100
Revision:
1:af427e419320
Child:
5:8052323b72d2
Synchronized with git rev 5de0824717

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Jonathan Austin 1:af427e419320 1 /*
Jonathan Austin 1:af427e419320 2 The MIT License (MIT)
Jonathan Austin 1:af427e419320 3
Jonathan Austin 1:af427e419320 4 Copyright (c) 2016 British Broadcasting Corporation.
Jonathan Austin 1:af427e419320 5 This software is provided by Lancaster University by arrangement with the BBC.
Jonathan Austin 1:af427e419320 6
Jonathan Austin 1:af427e419320 7 Permission is hereby granted, free of charge, to any person obtaining a
Jonathan Austin 1:af427e419320 8 copy of this software and associated documentation files (the "Software"),
Jonathan Austin 1:af427e419320 9 to deal in the Software without restriction, including without limitation
Jonathan Austin 1:af427e419320 10 the rights to use, copy, modify, merge, publish, distribute, sublicense,
Jonathan Austin 1:af427e419320 11 and/or sell copies of the Software, and to permit persons to whom the
Jonathan Austin 1:af427e419320 12 Software is furnished to do so, subject to the following conditions:
Jonathan Austin 1:af427e419320 13
Jonathan Austin 1:af427e419320 14 The above copyright notice and this permission notice shall be included in
Jonathan Austin 1:af427e419320 15 all copies or substantial portions of the Software.
Jonathan Austin 1:af427e419320 16
Jonathan Austin 1:af427e419320 17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Jonathan Austin 1:af427e419320 18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Jonathan Austin 1:af427e419320 19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
Jonathan Austin 1:af427e419320 20 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
Jonathan Austin 1:af427e419320 21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
Jonathan Austin 1:af427e419320 22 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
Jonathan Austin 1:af427e419320 23 DEALINGS IN THE SOFTWARE.
Jonathan Austin 1:af427e419320 24 */
Jonathan Austin 1:af427e419320 25
Jonathan Austin 1:af427e419320 26 #include "MicroBitConfig.h"
Jonathan Austin 1:af427e419320 27 /*
Jonathan Austin 1:af427e419320 28 * The underlying Nordic libraries that support BLE do not compile cleanly with the stringent GCC settings we employ
Jonathan Austin 1:af427e419320 29 * If we're compiling under GCC, then we suppress any warnings generated from this code (but not the rest of the DAL)
Jonathan Austin 1:af427e419320 30 * The ARM cc compiler is more tolerant. We don't test __GNUC__ here to detect GCC as ARMCC also typically sets this
Jonathan Austin 1:af427e419320 31 * as a compatability option, but does not support the options used...
Jonathan Austin 1:af427e419320 32 */
Jonathan Austin 1:af427e419320 33 #if !defined(__arm)
Jonathan Austin 1:af427e419320 34 #pragma GCC diagnostic ignored "-Wunused-function"
Jonathan Austin 1:af427e419320 35 #pragma GCC diagnostic push
Jonathan Austin 1:af427e419320 36 #pragma GCC diagnostic ignored "-Wunused-parameter"
Jonathan Austin 1:af427e419320 37 #endif
Jonathan Austin 1:af427e419320 38
Jonathan Austin 1:af427e419320 39 #include "MicroBit.h"
Jonathan Austin 1:af427e419320 40
Jonathan Austin 1:af427e419320 41 #include "nrf_soc.h"
Jonathan Austin 1:af427e419320 42
Jonathan Austin 1:af427e419320 43 /*
Jonathan Austin 1:af427e419320 44 * Return to our predefined compiler settings.
Jonathan Austin 1:af427e419320 45 */
Jonathan Austin 1:af427e419320 46 #if !defined(__arm)
Jonathan Austin 1:af427e419320 47 #pragma GCC diagnostic pop
Jonathan Austin 1:af427e419320 48 #endif
Jonathan Austin 1:af427e419320 49
Jonathan Austin 1:af427e419320 50 #if CONFIG_ENABLED(MICROBIT_DBG)
Jonathan Austin 1:af427e419320 51 // We create and initialize to NULL here, but MicroBitSerial will automatically update this as needed in its constructor.
Jonathan Austin 1:af427e419320 52 RawSerial* SERIAL_DEBUG = NULL;
Jonathan Austin 1:af427e419320 53 #endif
Jonathan Austin 1:af427e419320 54
Jonathan Austin 1:af427e419320 55 /**
Jonathan Austin 1:af427e419320 56 * Constructor.
Jonathan Austin 1:af427e419320 57 *
Jonathan Austin 1:af427e419320 58 * Create a representation of a MicroBit device, which includes member variables
Jonathan Austin 1:af427e419320 59 * that represent various device drivers used to control aspects of the micro:bit.
Jonathan Austin 1:af427e419320 60 */
Jonathan Austin 1:af427e419320 61 MicroBit::MicroBit() :
Jonathan Austin 1:af427e419320 62 serial(USBTX, USBRX),
Jonathan Austin 1:af427e419320 63 resetButton(MICROBIT_PIN_BUTTON_RESET),
Jonathan Austin 1:af427e419320 64 storage(),
Jonathan Austin 1:af427e419320 65 i2c(I2C_SDA0, I2C_SCL0),
Jonathan Austin 1:af427e419320 66 messageBus(),
Jonathan Austin 1:af427e419320 67 display(),
Jonathan Austin 1:af427e419320 68 buttonA(MICROBIT_PIN_BUTTON_A, MICROBIT_ID_BUTTON_A),
Jonathan Austin 1:af427e419320 69 buttonB(MICROBIT_PIN_BUTTON_B, MICROBIT_ID_BUTTON_B),
Jonathan Austin 1:af427e419320 70 buttonAB(MICROBIT_ID_BUTTON_A,MICROBIT_ID_BUTTON_B, MICROBIT_ID_BUTTON_AB),
Jonathan Austin 1:af427e419320 71 accelerometer(i2c),
Jonathan Austin 1:af427e419320 72 compass(i2c, accelerometer, storage),
Jonathan Austin 1:af427e419320 73 compassCalibrator(compass, accelerometer, display),
Jonathan Austin 1:af427e419320 74 thermometer(storage),
Jonathan Austin 1:af427e419320 75 io(MICROBIT_ID_IO_P0,MICROBIT_ID_IO_P1,MICROBIT_ID_IO_P2,
Jonathan Austin 1:af427e419320 76 MICROBIT_ID_IO_P3,MICROBIT_ID_IO_P4,MICROBIT_ID_IO_P5,
Jonathan Austin 1:af427e419320 77 MICROBIT_ID_IO_P6,MICROBIT_ID_IO_P7,MICROBIT_ID_IO_P8,
Jonathan Austin 1:af427e419320 78 MICROBIT_ID_IO_P9,MICROBIT_ID_IO_P10,MICROBIT_ID_IO_P11,
Jonathan Austin 1:af427e419320 79 MICROBIT_ID_IO_P12,MICROBIT_ID_IO_P13,MICROBIT_ID_IO_P14,
Jonathan Austin 1:af427e419320 80 MICROBIT_ID_IO_P15,MICROBIT_ID_IO_P16,MICROBIT_ID_IO_P19,
Jonathan Austin 1:af427e419320 81 MICROBIT_ID_IO_P20),
Jonathan Austin 1:af427e419320 82 bleManager(storage),
Jonathan Austin 1:af427e419320 83 radio(),
Jonathan Austin 1:af427e419320 84 ble(NULL)
Jonathan Austin 1:af427e419320 85 {
Jonathan Austin 1:af427e419320 86 // Clear our status
Jonathan Austin 1:af427e419320 87 status = 0;
Jonathan Austin 1:af427e419320 88
Jonathan Austin 1:af427e419320 89 // Bring up soft reset functionality as soon as possible.
Jonathan Austin 1:af427e419320 90 resetButton.mode(PullUp);
Jonathan Austin 1:af427e419320 91 resetButton.fall(this, &MicroBit::reset);
Jonathan Austin 1:af427e419320 92 }
Jonathan Austin 1:af427e419320 93
Jonathan Austin 1:af427e419320 94 /**
Jonathan Austin 1:af427e419320 95 * Post constructor initialisation method.
Jonathan Austin 1:af427e419320 96 *
Jonathan Austin 1:af427e419320 97 * This call will initialised the scheduler, memory allocator and Bluetooth stack.
Jonathan Austin 1:af427e419320 98 *
Jonathan Austin 1:af427e419320 99 * This is required as the Bluetooth stack can't be brought up in a
Jonathan Austin 1:af427e419320 100 * static context i.e. in a constructor.
Jonathan Austin 1:af427e419320 101 *
Jonathan Austin 1:af427e419320 102 * @code
Jonathan Austin 1:af427e419320 103 * uBit.init();
Jonathan Austin 1:af427e419320 104 * @endcode
Jonathan Austin 1:af427e419320 105 *
Jonathan Austin 1:af427e419320 106 * @note This method must be called before user code utilises any functionality
Jonathan Austin 1:af427e419320 107 * contained by uBit.
Jonathan Austin 1:af427e419320 108 */
Jonathan Austin 1:af427e419320 109 void MicroBit::init()
Jonathan Austin 1:af427e419320 110 {
Jonathan Austin 1:af427e419320 111 if (status & MICROBIT_INITIALIZED)
Jonathan Austin 1:af427e419320 112 return;
Jonathan Austin 1:af427e419320 113
Jonathan Austin 1:af427e419320 114 #if CONFIG_ENABLED(MICROBIT_HEAP_ALLOCATOR)
Jonathan Austin 1:af427e419320 115 // Bring up a nested heap allocator.
Jonathan Austin 1:af427e419320 116 microbit_create_nested_heap(MICROBIT_NESTED_HEAP_SIZE);
Jonathan Austin 1:af427e419320 117 #endif
Jonathan Austin 1:af427e419320 118
Jonathan Austin 1:af427e419320 119 // Bring up fiber scheduler.
Jonathan Austin 1:af427e419320 120 scheduler_init(messageBus);
Jonathan Austin 1:af427e419320 121
Jonathan Austin 1:af427e419320 122 // Seed our random number generator
Jonathan Austin 1:af427e419320 123 seedRandom();
Jonathan Austin 1:af427e419320 124
Jonathan Austin 1:af427e419320 125 // Create an event handler to trap any handlers being created for I2C services.
Jonathan Austin 1:af427e419320 126 // We do this to enable initialisation of those services only when they're used,
Jonathan Austin 1:af427e419320 127 // which saves processor time, memeory and battery life.
Jonathan Austin 1:af427e419320 128 messageBus.listen(MICROBIT_ID_MESSAGE_BUS_LISTENER, MICROBIT_EVT_ANY, this, &MicroBit::onListenerRegisteredEvent);
Jonathan Austin 1:af427e419320 129
Jonathan Austin 1:af427e419320 130 status |= MICROBIT_INITIALIZED;
Jonathan Austin 1:af427e419320 131
Jonathan Austin 1:af427e419320 132 #if CONFIG_ENABLED(MICROBIT_BLE_PAIRING_MODE)
Jonathan Austin 1:af427e419320 133 // Test if we need to enter BLE pairing mode...
Jonathan Austin 1:af427e419320 134 int i=0;
Jonathan Austin 1:af427e419320 135 sleep(100);
Jonathan Austin 1:af427e419320 136 while (buttonA.isPressed() && buttonB.isPressed() && i<10)
Jonathan Austin 1:af427e419320 137 {
Jonathan Austin 1:af427e419320 138 sleep(100);
Jonathan Austin 1:af427e419320 139 i++;
Jonathan Austin 1:af427e419320 140
Jonathan Austin 1:af427e419320 141 if (i == 10)
Jonathan Austin 1:af427e419320 142 {
Jonathan Austin 1:af427e419320 143 #if CONFIG_ENABLED(MICROBIT_HEAP_ALLOCATOR) && CONFIG_ENABLED(MICROBIT_HEAP_REUSE_SD)
Jonathan Austin 1:af427e419320 144 microbit_create_heap(MICROBIT_SD_GATT_TABLE_START + MICROBIT_SD_GATT_TABLE_SIZE, MICROBIT_SD_LIMIT);
Jonathan Austin 1:af427e419320 145 #endif
Jonathan Austin 1:af427e419320 146 // Start the BLE stack, if it isn't already running.
Jonathan Austin 1:af427e419320 147 if (!ble)
Jonathan Austin 1:af427e419320 148 {
Jonathan Austin 1:af427e419320 149 bleManager.init(getName(), getSerial(), messageBus, true);
Jonathan Austin 1:af427e419320 150 ble = bleManager.ble;
Jonathan Austin 1:af427e419320 151 }
Jonathan Austin 1:af427e419320 152
Jonathan Austin 1:af427e419320 153 // Enter pairing mode, using the LED matrix for any necessary pairing operations
Jonathan Austin 1:af427e419320 154 bleManager.pairingMode(display, buttonA);
Jonathan Austin 1:af427e419320 155 }
Jonathan Austin 1:af427e419320 156 }
Jonathan Austin 1:af427e419320 157 #endif
Jonathan Austin 1:af427e419320 158
Jonathan Austin 1:af427e419320 159 // Attempt to bring up a second heap region, using unused memory normally reserved for Soft Device.
Jonathan Austin 1:af427e419320 160 #if CONFIG_ENABLED(MICROBIT_HEAP_ALLOCATOR) && CONFIG_ENABLED(MICROBIT_HEAP_REUSE_SD)
Jonathan Austin 1:af427e419320 161 #if CONFIG_ENABLED(MICROBIT_BLE_ENABLED)
Jonathan Austin 1:af427e419320 162 microbit_create_heap(MICROBIT_SD_GATT_TABLE_START + MICROBIT_SD_GATT_TABLE_SIZE, MICROBIT_SD_LIMIT);
Jonathan Austin 1:af427e419320 163 #else
Jonathan Austin 1:af427e419320 164 microbit_create_heap(MICROBIT_SRAM_BASE, MICROBIT_SD_LIMIT);
Jonathan Austin 1:af427e419320 165 #endif
Jonathan Austin 1:af427e419320 166 #endif
Jonathan Austin 1:af427e419320 167
Jonathan Austin 1:af427e419320 168 #if CONFIG_ENABLED(MICROBIT_BLE_ENABLED)
Jonathan Austin 1:af427e419320 169 // Start the BLE stack, if it isn't already running.
Jonathan Austin 1:af427e419320 170 if (!ble)
Jonathan Austin 1:af427e419320 171 {
Jonathan Austin 1:af427e419320 172 bleManager.init(getName(), getSerial(), messageBus, false);
Jonathan Austin 1:af427e419320 173 ble = bleManager.ble;
Jonathan Austin 1:af427e419320 174 }
Jonathan Austin 1:af427e419320 175 #endif
Jonathan Austin 1:af427e419320 176 }
Jonathan Austin 1:af427e419320 177
Jonathan Austin 1:af427e419320 178 /**
Jonathan Austin 1:af427e419320 179 * A listener to perform actions as a result of Message Bus reflection.
Jonathan Austin 1:af427e419320 180 *
Jonathan Austin 1:af427e419320 181 * In some cases we want to perform lazy instantiation of components, such as
Jonathan Austin 1:af427e419320 182 * the compass and the accelerometer, where we only want to add them to the idle
Jonathan Austin 1:af427e419320 183 * fiber when someone has the intention of using these components.
Jonathan Austin 1:af427e419320 184 */
Jonathan Austin 1:af427e419320 185 void MicroBit::onListenerRegisteredEvent(MicroBitEvent evt)
Jonathan Austin 1:af427e419320 186 {
Jonathan Austin 1:af427e419320 187 switch(evt.value)
Jonathan Austin 1:af427e419320 188 {
Jonathan Austin 1:af427e419320 189 case MICROBIT_ID_BUTTON_AB:
Jonathan Austin 1:af427e419320 190 // A user has registered to receive events from the buttonAB multibutton.
Jonathan Austin 1:af427e419320 191 // Disable click events from being generated by ButtonA and ButtonB, and defer the
Jonathan Austin 1:af427e419320 192 // control of this to the multibutton handler.
Jonathan Austin 1:af427e419320 193 //
Jonathan Austin 1:af427e419320 194 // This way, buttons look independent unless a buttonAB is requested, at which
Jonathan Austin 1:af427e419320 195 // point button A+B clicks can be correclty handled without breaking
Jonathan Austin 1:af427e419320 196 // causal ordering.
Jonathan Austin 1:af427e419320 197 buttonA.setEventConfiguration(MICROBIT_BUTTON_SIMPLE_EVENTS);
Jonathan Austin 1:af427e419320 198 buttonB.setEventConfiguration(MICROBIT_BUTTON_SIMPLE_EVENTS);
Jonathan Austin 1:af427e419320 199 buttonAB.setEventConfiguration(MICROBIT_BUTTON_ALL_EVENTS);
Jonathan Austin 1:af427e419320 200 break;
Jonathan Austin 1:af427e419320 201
Jonathan Austin 1:af427e419320 202 case MICROBIT_ID_COMPASS:
Jonathan Austin 1:af427e419320 203 // A listener has been registered for the compass.
Jonathan Austin 1:af427e419320 204 // The compass uses lazy instantiation, we just need to read the data once to start it running.
Jonathan Austin 1:af427e419320 205 // Touch the compass through the heading() function to ensure it is calibrated. if it isn't this will launch any associated calibration algorithms.
Jonathan Austin 1:af427e419320 206 compass.heading();
Jonathan Austin 1:af427e419320 207
Jonathan Austin 1:af427e419320 208 break;
Jonathan Austin 1:af427e419320 209
Jonathan Austin 1:af427e419320 210 case MICROBIT_ID_ACCELEROMETER:
Jonathan Austin 1:af427e419320 211 // A listener has been registered for the accelerometer.
Jonathan Austin 1:af427e419320 212 // The accelerometer uses lazy instantiation, we just need to read the data once to start it running.
Jonathan Austin 1:af427e419320 213 accelerometer.updateSample();
Jonathan Austin 1:af427e419320 214 break;
Jonathan Austin 1:af427e419320 215
Jonathan Austin 1:af427e419320 216 case MICROBIT_ID_THERMOMETER:
Jonathan Austin 1:af427e419320 217 // A listener has been registered for the thermometer.
Jonathan Austin 1:af427e419320 218 // The thermometer uses lazy instantiation, we just need to read the data once to start it running.
Jonathan Austin 1:af427e419320 219 thermometer.updateSample();
Jonathan Austin 1:af427e419320 220 break;
Jonathan Austin 1:af427e419320 221 }
Jonathan Austin 1:af427e419320 222 }