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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MicroBit.h Source File

MicroBit.h

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 #ifndef MICROBIT_H
00027 #define MICROBIT_H
00028 
00029 #include "mbed.h"
00030 
00031 #include "MicroBitConfig.h"
00032 #include "MicroBitHeapAllocator.h"
00033 #include "MicroBitDevice.h"
00034 #include "ErrorNo.h"
00035 #include "MicroBitSystemTimer.h"
00036 #include "Matrix4.h"
00037 #include "MicroBitCompat.h"
00038 #include "MicroBitComponent.h"
00039 #include "ManagedType.h"
00040 #include "ManagedString.h"
00041 #include "MicroBitImage.h"
00042 #include "MicroBitFont.h"
00043 #include "MicroBitEvent.h"
00044 #include "DynamicPwm.h"
00045 #include "MicroBitI2C.h"
00046 #include "NotifyEvents.h"
00047 
00048 #include "MicroBitButton.h"
00049 #include "MicroBitPin.h"
00050 #include "MicroBitCompass.h"
00051 #include "MicroBitCompassCalibrator.h"
00052 #include "MicroBitAccelerometer.h"
00053 #include "MicroBitThermometer.h"
00054 #include "MicroBitLightSensor.h"
00055 #include "MicroBitMultiButton.h"
00056 
00057 #include "MicroBitSerial.h"
00058 #include "MicroBitIO.h"
00059 #include "MicroBitMatrixMaps.h"
00060 #include "MicroBitDisplay.h"
00061 
00062 #include "MicroBitFiber.h"
00063 #include "MicroBitMessageBus.h"
00064 
00065 #include "MicroBitBLEManager.h"
00066 #include "MicroBitRadio.h"
00067 #include "MicroBitStorage.h"
00068 
00069 // MicroBit::flags values
00070 #define MICROBIT_INITIALIZED                    0x01
00071 
00072 /**
00073   * Class definition for a MicroBit device.
00074   *
00075   * Represents the device as a whole, and includes member variables that represent various device drivers
00076   * used to control aspects of the micro:bit.
00077   */
00078 class MicroBit
00079 {
00080     private:
00081 
00082     /**
00083       * A listener to perform actions as a result of Message Bus reflection.
00084       *
00085       * In some cases we want to perform lazy instantiation of components, such as
00086       * the compass and the accelerometer, where we only want to add them to the idle
00087       * fiber when someone has the intention of using these components.
00088       */
00089     void                        onListenerRegisteredEvent(MicroBitEvent evt);
00090 
00091     uint8_t                     status;
00092 
00093     public:
00094 
00095     // Serial Interface
00096     MicroBitSerial              serial;
00097 
00098     // Reset Button
00099     InterruptIn                 resetButton;
00100 
00101     // Persistent key value store
00102     MicroBitStorage             storage;
00103 
00104     // I2C Interface
00105     MicroBitI2C                 i2c;
00106 
00107     // Device level Message Bus abstraction
00108     MicroBitMessageBus          messageBus;
00109 
00110     // Member variables to represent each of the core components on the device.
00111     MicroBitDisplay             display;
00112     MicroBitButton              buttonA;
00113     MicroBitButton              buttonB;
00114     MicroBitMultiButton         buttonAB;
00115     MicroBitAccelerometer       accelerometer;
00116     MicroBitCompass             compass;
00117     MicroBitCompassCalibrator   compassCalibrator;
00118     MicroBitThermometer         thermometer;
00119 
00120     //An object of available IO pins on the device
00121     MicroBitIO                  io;
00122 
00123     // Bluetooth related member variables.
00124     MicroBitBLEManager          bleManager;
00125     MicroBitRadio               radio;
00126     BLEDevice                   *ble;
00127 
00128     /**
00129       * Constructor.
00130       *
00131       * Create a representation of a MicroBit device, which includes member variables
00132       * that represent various device drivers used to control aspects of the micro:bit.
00133       */
00134     MicroBit();
00135 
00136     /**
00137       * Post constructor initialisation method.
00138       *
00139       * This call will initialised the scheduler, memory allocator and Bluetooth stack.
00140       *
00141       * This is required as the Bluetooth stack can't be brought up in a
00142       * static context i.e. in a constructor.
00143       *
00144       * @code
00145       * uBit.init();
00146       * @endcode
00147       *
00148       * @note This method must be called before user code utilises any functionality
00149       *       contained by uBit.
00150       */
00151     void init();
00152 
00153     /**
00154       * Return the friendly name for this device.
00155       *
00156       * @return A ManagedString representing the friendly name of this device.
00157       *
00158       * @code
00159       * ManagedString name = uBit.getName();
00160       * @endcode
00161       */
00162     static ManagedString getName();
00163 
00164     /**
00165       * Return the serial number of this device.
00166       *
00167       * @return A ManagedString representing the serial number of this device.
00168       *
00169       * @code
00170       * ManagedString serialNumber = uBit.getSerial();
00171       * @endcode
00172       */
00173     static ManagedString getSerial();
00174 
00175     /**
00176       * Will reset the micro:bit when called.
00177       *
00178       * @code
00179       * uBit.reset();
00180       * @endcode
00181       */
00182     void reset();
00183 
00184     /**
00185       * Delay execution for the given amount of time.
00186       *
00187       * If the scheduler is running, this will deschedule the current fiber and perform
00188       * a power efficient, concurrent sleep operation.
00189       *
00190       * If the scheduler is disabled or we're running in an interrupt context, this
00191       * will revert to a busy wait.
00192       *
00193       * Alternatively: wait, wait_ms, wait_us can be used which will perform a blocking sleep
00194       * operation.
00195       *
00196       * @param milliseconds the amount of time, in ms, to wait for. This number cannot be negative.
00197       *
00198       * @return MICROBIT_OK on success, MICROBIT_INVALID_PARAMETER milliseconds is less than zero.
00199       *
00200       * @code
00201       * uBit.sleep(20); //sleep for 20ms
00202       * @endcode
00203       *
00204       * @note This operation is currently limited by the rate of the system timer, therefore
00205       *       the granularity of the sleep operation is limited to 6 ms unless the rate of
00206       *       the system timer is modified.
00207       */
00208     void sleep(uint32_t milliseconds);
00209 
00210     /**
00211       * Seed the pseudo random number generator using the hardware random number generator.
00212       *
00213       * @code
00214       * uBit.seedRandom();
00215       * @endcode
00216       */
00217     void seedRandom();
00218 
00219     /**
00220       * Seed the pseudo random number generator using the given value.
00221       *
00222       * @param seed The 32-bit value to seed the generator with.
00223       *
00224       * @code
00225       * uBit.seedRandom(0xBB5EED);
00226       * @endcode
00227       */
00228     void seedRandom(uint32_t seed);
00229 
00230 
00231     /**
00232       * Generate a random number in the given range.
00233       * We use a simple Galois LFSR random number generator here,
00234       * as a Galois LFSR is sufficient for our applications, and much more lightweight
00235       * than the hardware random number generator built int the processor, which takes
00236       * a long time and uses a lot of energy.
00237       *
00238       * KIDS: You shouldn't use this is the real world to generate cryptographic keys though...
00239       * have a think why not. :-)
00240       *
00241       * @param max the upper range to generate a number for. This number cannot be negative.
00242       *
00243       * @return A random, natural number between 0 and the max-1. Or MICROBIT_INVALID_VALUE if max is <= 0.
00244       *
00245       * @code
00246       * uBit.random(200); //a number between 0 and 199
00247       * @endcode
00248       */
00249     int random(int max);
00250 
00251     /**
00252       * Determine the time since this MicroBit was last reset.
00253       *
00254       * @return The time since the last reset, in milliseconds.
00255       *
00256       * @note This will value overflow after 1.6 months.
00257       */
00258       //TODO: handle overflow case.
00259     unsigned long systemTime();
00260 
00261     /**
00262       * Determine the version of the micro:bit runtime currently in use.
00263       *
00264       * @return A textual description of the version of the micro:bit runtime that
00265       *         is currently running on this device.
00266       */
00267     const char *systemVersion();
00268 
00269     /**
00270       * Triggers a microbit panic where an loop will display a panic face
00271       * and the status code, if provided.
00272       *
00273       * This loop will continue for panic_timeout iterations, defaults to 0 (infinite).
00274       *
00275       * panic_timeout can be configured via a call to microbit_panic_timeout.
00276       *
00277       * @param statusCode the status code of the associated error.
00278       *
00279       * @code
00280       * microbit_panic_timeout(4);
00281       *
00282       * // will display loop for 4 iterations.
00283       * uBit.panic(10);
00284       * @endcode
00285       */
00286     void panic(int statusCode = 0);
00287 
00288     /**
00289       * Add a component to the array of system components. This component will then receive
00290       * periodic callbacks, once every tick period in interrupt context.
00291       *
00292       * @param component The component to add.
00293       *
00294       * @return MICROBIT_OK on success or MICROBIT_NO_RESOURCES if the component array is full.
00295       *
00296       * @code
00297       * // heap allocated - otherwise it will be paged out!
00298       * MicroBitDisplay* display = new MicroBitDisplay();
00299       *
00300       * uBit.addSystemComponent(display);
00301       * @endcode
00302       *
00303       * @note This interface is now deprecated, and will be removed in the next major release. Please use system_timer_add_component().
00304       */
00305     int addSystemComponent(MicroBitComponent *component);
00306 
00307     /**
00308       * Remove a component from the array of system components. This component will no longer receive
00309       * periodic callbacks.
00310       *
00311       * @param component The component to remove.
00312       *
00313       * @return MICROBIT_OK on success or MICROBIT_INVALID_PARAMETER is returned if the given component has not been previously added.
00314       *
00315       * @code
00316       * // heap allocated - otherwise it will be paged out!
00317       * MicroBitDisplay* display = new MicroBitDisplay();
00318       *
00319       * uBit.addSystemComponent(display);
00320       *
00321       * uBit.removeSystemComponent(display);
00322       * @endcode
00323       *
00324       * @note This interface is now deprecated, and will be removed in the next major release. Please use system_timer_remove_component().
00325       */
00326     int removeSystemComponent(MicroBitComponent *component);
00327 
00328     /**
00329       * Adds a component to the array of idle thread components, which are processed
00330       * when the run queue is empty.
00331       *
00332       * The system timer will poll isIdleCallbackNeeded on each component to determine
00333       * if the scheduler should schedule the idle_task imminently.
00334       *
00335       * @param component The component to add to the array.
00336       *
00337       * @return MICROBIT_OK on success or MICROBIT_NO_RESOURCES if the fiber components array is full.
00338       *
00339       * @code
00340       * MicroBitI2C i2c(I2C_SDA0, I2C_SCL0);
00341       *
00342       * // heap allocated - otherwise it will be paged out!
00343       * MicroBitAccelerometer* accelerometer = new MicroBitAccelerometer(i2c);
00344       *
00345       * fiber_add_idle_component(accelerometer);
00346       * @endcode
00347       *
00348       * @note This interface is now deprecated, and will be removed in the next major release. Please use fiber_add_idle_component().
00349       */
00350     int addIdleComponent(MicroBitComponent *component);
00351 
00352     /**
00353       * Remove a component from the array of idle thread components
00354       *
00355       * @param component The component to remove from the idle component array.
00356       *
00357       * @return MICROBIT_OK on success. MICROBIT_INVALID_PARAMETER is returned if the given component has not been previously added.
00358       *
00359       * @code
00360       * MicroBitI2C i2c(I2C_SDA0, I2C_SCL0);
00361       *
00362       * // heap allocated - otherwise it will be paged out!
00363       * MicroBitAccelerometer* accelerometer = new MicroBitAccelerometer(i2c);
00364       *
00365       * uBit.addIdleComponent(accelerometer);
00366       *
00367       * uBit.removeIdleComponent(accelerometer);
00368       * @endcode
00369       *
00370       * @note This interface is now deprecated, and will be removed in the next major release. Please use fiber_remove_idle_component().
00371       */
00372     int removeIdleComponent(MicroBitComponent *component);
00373 };
00374 
00375 /**
00376   * Return the friendly name for this device.
00377   *
00378   * @return A ManagedString representing the friendly name of this device.
00379   *
00380   * @code
00381   * ManagedString name = uBit.getName();
00382   * @endcode
00383   */
00384 inline ManagedString MicroBit::getName()
00385 {
00386     return ManagedString(microbit_friendly_name());
00387 }
00388 
00389 /**
00390   * Return the serial number of this device.
00391   *
00392   * @return A ManagedString representing the serial number of this device.
00393   *
00394   * @code
00395   * ManagedString serialNumber = uBit.getSerial();
00396   * @endcode
00397   */
00398 inline ManagedString MicroBit::getSerial()
00399 {
00400     // We take to 16 bit numbers here, as we want the full range of ID bits, but don't want negative numbers...
00401     int n1 = microbit_serial_number() & 0xffff;
00402     int n2 = (microbit_serial_number() >> 16) & 0xffff;
00403 
00404     // Simply concat the two numbers.
00405     ManagedString s1(n1);
00406     ManagedString s2(n2);
00407 
00408     return s1 + s2;
00409 }
00410 
00411 /**
00412   * Will reset the micro:bit when called.
00413   *
00414   * @code
00415   * uBit.reset();
00416   * @endcode
00417   */
00418 inline void MicroBit::reset()
00419 {
00420     if(ble && ble->getGapState().connected) {
00421 
00422         // We have a connected BLE peer. Disconnect the BLE session.
00423         ble->gap().disconnect(Gap::REMOTE_USER_TERMINATED_CONNECTION);
00424 
00425         // Wait a little while for the connection to drop.
00426         wait_ms(100);
00427     }
00428 
00429     microbit_reset();
00430 }
00431 
00432 /**
00433   * Delay execution for the given amount of time.
00434   *
00435   * If the scheduler is running, this will deschedule the current fiber and perform
00436   * a power efficient, concurrent sleep operation.
00437   *
00438   * If the scheduler is disabled or we're running in an interrupt context, this
00439   * will revert to a busy wait.
00440   *
00441   * Alternatively: wait, wait_ms, wait_us can be used which will perform a blocking sleep
00442   * operation.
00443   *
00444   * @param milliseconds the amount of time, in ms, to wait for. This number cannot be negative.
00445   *
00446   * @return MICROBIT_OK on success, MICROBIT_INVALID_PARAMETER milliseconds is less than zero.
00447   *
00448   * @code
00449   * uBit.sleep(20); //sleep for 20ms
00450   * @endcode
00451   *
00452   * @note This operation is currently limited by the rate of the system timer, therefore
00453   *       the granularity of the sleep operation is limited to 6 ms unless the rate of
00454   *       the system timer is modified.
00455   */
00456 inline void MicroBit::sleep(uint32_t milliseconds)
00457 {
00458     fiber_sleep(milliseconds);
00459 }
00460 
00461 /**
00462   * Generate a random number in the given range.
00463   * We use a simple Galois LFSR random number generator here,
00464   * as a Galois LFSR is sufficient for our applications, and much more lightweight
00465   * than the hardware random number generator built int the processor, which takes
00466   * a long time and uses a lot of energy.
00467   *
00468   * KIDS: You shouldn't use this is the real world to generate cryptographic keys though...
00469   * have a think why not. :-)
00470   *
00471   * @param max the upper range to generate a number for. This number cannot be negative.
00472   *
00473   * @return A random, natural number between 0 and the max-1. Or MICROBIT_INVALID_VALUE if max is <= 0.
00474   *
00475   * @code
00476   * uBit.random(200); //a number between 0 and 199
00477   * @endcode
00478   */
00479 inline int MicroBit::random(int max)
00480 {
00481     return microbit_random(max);
00482 }
00483 
00484 /**
00485   * Seed the pseudo random number generator using the hardware random number generator.
00486   *
00487   * @code
00488   * uBit.seedRandom();
00489   * @endcode
00490   */
00491 inline void MicroBit::seedRandom()
00492 {
00493     microbit_seed_random();
00494 }
00495 
00496 
00497 /**
00498   * Seed the pseudo random number generator using the given value.
00499   *
00500   * @param seed The 32-bit value to seed the generator with.
00501   *
00502   * @code
00503   * uBit.seedRandom(0xBB5EED);
00504   * @endcode
00505   */
00506 inline void MicroBit::seedRandom(uint32_t seed)
00507 {
00508     microbit_seed_random(seed);
00509 }
00510 
00511 
00512 /**
00513   * Add a component to the array of system components. This component will then receive
00514   * periodic callbacks, once every tick period in interrupt context.
00515   *
00516   * @param component The component to add.
00517   *
00518   * @return MICROBIT_OK on success or MICROBIT_NO_RESOURCES if the component array is full.
00519   *
00520   * @code
00521   * // heap allocated - otherwise it will be paged out!
00522   * MicroBitDisplay* display = new MicroBitDisplay();
00523   *
00524   * uBit.addSystemComponent(display);
00525   * @endcode
00526   *
00527   * @note This interface is now deprecated, and will be removed in the next major release. Please use system_timer_add_component().
00528   */
00529 inline int MicroBit::addSystemComponent(MicroBitComponent *component)
00530 {
00531     return system_timer_add_component(component);
00532 }
00533 
00534 /**
00535   * Remove a component from the array of system components. This component will no longer receive
00536   * periodic callbacks.
00537   *
00538   * @param component The component to remove.
00539   *
00540   * @return MICROBIT_OK on success or MICROBIT_INVALID_PARAMETER is returned if the given component has not been previously added.
00541   *
00542   * @code
00543   * // heap allocated - otherwise it will be paged out!
00544   * MicroBitDisplay* display = new MicroBitDisplay();
00545   *
00546   * uBit.addSystemComponent(display);
00547   *
00548   * uBit.removeSystemComponent(display);
00549   * @endcode
00550   *
00551   * @note This interface is now deprecated, and will be removed in the next major release. Please use system_timer_remove_component().
00552   */
00553 inline int MicroBit::removeSystemComponent(MicroBitComponent *component)
00554 {
00555     return system_timer_remove_component(component);
00556 }
00557 
00558 /**
00559   * Adds a component to the array of idle thread components, which are processed
00560   * when the run queue is empty.
00561   *
00562   * The system timer will poll isIdleCallbackNeeded on each component to determine
00563   * if the scheduler should schedule the idle_task imminently.
00564   *
00565   * @param component The component to add to the array.
00566   *
00567   * @return MICROBIT_OK on success or MICROBIT_NO_RESOURCES if the fiber components array is full.
00568   *
00569   * @code
00570   * MicroBitI2C i2c(I2C_SDA0, I2C_SCL0);
00571   *
00572   * // heap allocated - otherwise it will be paged out!
00573   * MicroBitAccelerometer* accelerometer = new MicroBitAccelerometer(i2c);
00574   *
00575   * fiber_add_idle_component(accelerometer);
00576   * @endcode
00577   *
00578   * @note This interface is now deprecated, and will be removed in the next major release. Please use fiber_add_idle_component().
00579   */
00580 inline int MicroBit::addIdleComponent(MicroBitComponent *component)
00581 {
00582     return fiber_add_idle_component(component);
00583 }
00584 
00585 /**
00586   * Remove a component from the array of idle thread components
00587   *
00588   * @param component The component to remove from the idle component array.
00589   *
00590   * @return MICROBIT_OK on success. MICROBIT_INVALID_PARAMETER is returned if the given component has not been previously added.
00591   *
00592   * @code
00593   * MicroBitI2C i2c(I2C_SDA0, I2C_SCL0);
00594   *
00595   * // heap allocated - otherwise it will be paged out!
00596   * MicroBitAccelerometer* accelerometer = new MicroBitAccelerometer(i2c);
00597   *
00598   * uBit.addIdleComponent(accelerometer);
00599   *
00600   * uBit.removeIdleComponent(accelerometer);
00601   * @endcode
00602   *
00603   * @note This interface is now deprecated, and will be removed in the next major release. Please use fiber_remove_idle_component().
00604   */
00605 inline int MicroBit::removeIdleComponent(MicroBitComponent *component)
00606 {
00607     return fiber_remove_idle_component(component);
00608 }
00609 
00610 
00611 /**
00612   * Determine the time since this MicroBit was last reset.
00613   *
00614   * @return The time since the last reset, in milliseconds.
00615   *
00616   * @note This will value overflow after 1.6 months.
00617   */
00618 inline unsigned long MicroBit::systemTime()
00619 {
00620     return system_timer_current_time();
00621 }
00622 
00623 
00624 /**
00625   * Determine the version of the micro:bit runtime currently in use.
00626   *
00627   * @return A textual description of the version of the micro:bit runtime that
00628   *         is currently running on this device.
00629   */
00630 inline const char *MicroBit::systemVersion()
00631 {
00632     return microbit_dal_version();
00633 }
00634 
00635 /**
00636   * Triggers a microbit panic where an loop will display a panic face
00637   * and the status code, if provided.
00638   *
00639   * This loop will continue for panic_timeout iterations, defaults to 0 (infinite).
00640   *
00641   * panic_timeout can be configured via a call to microbit_panic_timeout.
00642   *
00643   * @param statusCode the status code of the associated error.
00644   *
00645   * @code
00646   * microbit_panic_timeout(4);
00647   *
00648   * // will display loop for 4 iterations.
00649   * uBit.panic(10);
00650   * @endcode
00651   */
00652 inline void MicroBit::panic(int statusCode)
00653 {
00654     //show error and enter infinite while
00655     microbit_panic(statusCode);
00656 }
00657 
00658 #endif