Example ti send and receive messages between 2 Microbits

Dependencies:   microbit-dal

Fork of microbit by Lancaster University

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MicroBit.cpp Source File

MicroBit.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 #include "MicroBitConfig.h"
00027 /*
00028  * The underlying Nordic libraries that support BLE do not compile cleanly with the stringent GCC settings we employ
00029  * If we're compiling under GCC, then we suppress any warnings generated from this code (but not the rest of the DAL)
00030  * The ARM cc compiler is more tolerant. We don't test __GNUC__ here to detect GCC as ARMCC also typically sets this
00031  * as a compatability option, but does not support the options used...
00032  */
00033 #if !defined(__arm)
00034 #pragma GCC diagnostic ignored "-Wunused-function"
00035 #pragma GCC diagnostic push
00036 #pragma GCC diagnostic ignored "-Wunused-parameter"
00037 #endif
00038 
00039 #include "MicroBit.h"
00040 
00041 #include "nrf_soc.h"
00042 
00043 /*
00044  * Return to our predefined compiler settings.
00045  */
00046 #if !defined(__arm)
00047 #pragma GCC diagnostic pop
00048 #endif
00049 
00050 #if CONFIG_ENABLED(MICROBIT_DBG)
00051 // We create and initialize to NULL here, but MicroBitSerial will automatically update this as needed in its constructor.
00052 RawSerial* SERIAL_DEBUG = NULL;
00053 #endif
00054 
00055 /**
00056   * Constructor.
00057   *
00058   * Create a representation of a MicroBit device, which includes member variables
00059   * that represent various device drivers used to control aspects of the micro:bit.
00060   */
00061 MicroBit::MicroBit() :
00062     serial(USBTX, USBRX),
00063     resetButton(MICROBIT_PIN_BUTTON_RESET),
00064     storage(),
00065     i2c(I2C_SDA0, I2C_SCL0),
00066     messageBus(),
00067     display(),
00068     buttonA(MICROBIT_PIN_BUTTON_A, MICROBIT_ID_BUTTON_A),
00069     buttonB(MICROBIT_PIN_BUTTON_B, MICROBIT_ID_BUTTON_B),
00070     buttonAB(MICROBIT_ID_BUTTON_A,MICROBIT_ID_BUTTON_B, MICROBIT_ID_BUTTON_AB),
00071     accelerometer(i2c),
00072     compass(i2c, accelerometer, storage),
00073     compassCalibrator(compass, accelerometer, display),
00074     thermometer(storage),
00075     io(MICROBIT_ID_IO_P0,MICROBIT_ID_IO_P1,MICROBIT_ID_IO_P2,
00076        MICROBIT_ID_IO_P3,MICROBIT_ID_IO_P4,MICROBIT_ID_IO_P5,
00077        MICROBIT_ID_IO_P6,MICROBIT_ID_IO_P7,MICROBIT_ID_IO_P8,
00078        MICROBIT_ID_IO_P9,MICROBIT_ID_IO_P10,MICROBIT_ID_IO_P11,
00079        MICROBIT_ID_IO_P12,MICROBIT_ID_IO_P13,MICROBIT_ID_IO_P14,
00080        MICROBIT_ID_IO_P15,MICROBIT_ID_IO_P16,MICROBIT_ID_IO_P19,
00081        MICROBIT_ID_IO_P20),
00082     bleManager(storage),
00083     radio(),
00084     ble(NULL)
00085 {
00086     // Clear our status
00087     status = 0;
00088 
00089     // Bring up soft reset functionality as soon as possible.
00090     resetButton.mode(PullUp);
00091     resetButton.fall(this, &MicroBit::reset);
00092 }
00093 
00094 /**
00095   * Post constructor initialisation method.
00096   *
00097   * This call will initialised the scheduler, memory allocator and Bluetooth stack.
00098   *
00099   * This is required as the Bluetooth stack can't be brought up in a
00100   * static context i.e. in a constructor.
00101   *
00102   * @code
00103   * uBit.init();
00104   * @endcode
00105   *
00106   * @note This method must be called before user code utilises any functionality
00107   *       contained by uBit.
00108   */
00109 void MicroBit::init()
00110 {
00111     if (status & MICROBIT_INITIALIZED)
00112         return;
00113 
00114 #if CONFIG_ENABLED(MICROBIT_HEAP_ALLOCATOR)
00115     // Bring up a nested heap allocator.
00116     microbit_create_nested_heap(MICROBIT_NESTED_HEAP_SIZE);
00117 #endif
00118 
00119     // Bring up fiber scheduler.
00120     scheduler_init(messageBus);
00121 
00122     // Seed our random number generator
00123     seedRandom();
00124 
00125     // Create an event handler to trap any handlers being created for I2C services.
00126     // We do this to enable initialisation of those services only when they're used,
00127     // which saves processor time, memeory and battery life.
00128     messageBus.listen(MICROBIT_ID_MESSAGE_BUS_LISTENER, MICROBIT_EVT_ANY, this, &MicroBit::onListenerRegisteredEvent);
00129 
00130     status |= MICROBIT_INITIALIZED;
00131 
00132 #if CONFIG_ENABLED(MICROBIT_BLE_PAIRING_MODE)
00133     // Test if we need to enter BLE pairing mode...
00134     int i=0;
00135     sleep(100);
00136     while (buttonA.isPressed() && buttonB.isPressed() && i<10)
00137     {
00138         sleep(100);
00139         i++;
00140 
00141         if (i == 10)
00142         {
00143 #if CONFIG_ENABLED(MICROBIT_HEAP_ALLOCATOR) && CONFIG_ENABLED(MICROBIT_HEAP_REUSE_SD)
00144             microbit_create_heap(MICROBIT_SD_GATT_TABLE_START + MICROBIT_SD_GATT_TABLE_SIZE, MICROBIT_SD_LIMIT);
00145 #endif
00146             // Start the BLE stack, if it isn't already running.
00147             if (!ble)
00148             {
00149                 bleManager.init(getName(), getSerial(), messageBus, true);
00150                 ble = bleManager.ble;
00151             }
00152 
00153             // Enter pairing mode, using the LED matrix for any necessary pairing operations
00154             bleManager.pairingMode(display, buttonA);
00155         }
00156     }
00157 #endif
00158 
00159     // Attempt to bring up a second heap region, using unused memory normally reserved for Soft Device.
00160 #if CONFIG_ENABLED(MICROBIT_HEAP_ALLOCATOR) && CONFIG_ENABLED(MICROBIT_HEAP_REUSE_SD)
00161 #if CONFIG_ENABLED(MICROBIT_BLE_ENABLED)
00162     microbit_create_heap(MICROBIT_SD_GATT_TABLE_START + MICROBIT_SD_GATT_TABLE_SIZE, MICROBIT_SD_LIMIT);
00163 #else
00164     microbit_create_heap(MICROBIT_SRAM_BASE, MICROBIT_SD_LIMIT);
00165 #endif
00166 #endif
00167 
00168 #if CONFIG_ENABLED(MICROBIT_BLE_ENABLED)
00169     // Start the BLE stack, if it isn't already running.
00170     if (!ble)
00171     {
00172         bleManager.init(getName(), getSerial(), messageBus, false);
00173         ble = bleManager.ble;
00174     }
00175 #endif
00176 }
00177 
00178 /**
00179   * A listener to perform actions as a result of Message Bus reflection.
00180   *
00181   * In some cases we want to perform lazy instantiation of components, such as
00182   * the compass and the accelerometer, where we only want to add them to the idle
00183   * fiber when someone has the intention of using these components.
00184   */
00185 void MicroBit::onListenerRegisteredEvent(MicroBitEvent evt)
00186 {
00187     switch(evt.value)
00188     {
00189         case MICROBIT_ID_BUTTON_AB:
00190             // A user has registered to receive events from the buttonAB multibutton.
00191             // Disable click events from being generated by ButtonA and ButtonB, and defer the
00192             // control of this to the multibutton handler.
00193             //
00194             // This way, buttons look independent unless a buttonAB is requested, at which
00195             // point button A+B clicks can be correclty handled without breaking
00196             // causal ordering.
00197             buttonA.setEventConfiguration(MICROBIT_BUTTON_SIMPLE_EVENTS);
00198             buttonB.setEventConfiguration(MICROBIT_BUTTON_SIMPLE_EVENTS);
00199             buttonAB.setEventConfiguration(MICROBIT_BUTTON_ALL_EVENTS);
00200             break;
00201 
00202         case MICROBIT_ID_COMPASS:
00203             // A listener has been registered for the compass.
00204             // The compass uses lazy instantiation, we just need to read the data once to start it running.
00205             // Touch the compass through the heading() function to ensure it is calibrated. if it isn't this will launch any associated calibration algorithms.
00206             compass.heading();
00207 
00208             break;
00209 
00210         case MICROBIT_ID_ACCELEROMETER:
00211         case MICROBIT_ID_GESTURE:
00212             // A listener has been registered for the accelerometer.
00213             // The accelerometer uses lazy instantiation, we just need to read the data once to start it running.
00214             accelerometer.updateSample();
00215             break;
00216 
00217         case MICROBIT_ID_THERMOMETER:
00218             // A listener has been registered for the thermometer.
00219             // The thermometer uses lazy instantiation, we just need to read the data once to start it running.
00220             thermometer.updateSample();
00221             break;
00222     }
00223 }