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
Diff: inc/drivers/MicroBitDisplay.h
- Revision:
- 1:8aa5cdb4ab67
- Child:
- 20:ad2a5c7debf4
diff -r fb15f7887843 -r 8aa5cdb4ab67 inc/drivers/MicroBitDisplay.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/inc/drivers/MicroBitDisplay.h Thu Apr 07 01:33:22 2016 +0100 @@ -0,0 +1,639 @@ +/* +The MIT License (MIT) + +Copyright (c) 2016 British Broadcasting Corporation. +This software is provided by Lancaster University by arrangement with the BBC. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + +#ifndef MICROBIT_DISPLAY_H +#define MICROBIT_DISPLAY_H + +#include "mbed.h" +#include "MicroBitConfig.h" +#include "ManagedString.h" +#include "MicroBitComponent.h" +#include "MicroBitImage.h" +#include "MicroBitFont.h" +#include "MicroBitMatrixMaps.h" +#include "MicroBitLightSensor.h" + +/** + * Event codes raised by MicroBitDisplay + */ +#define MICROBIT_DISPLAY_EVT_ANIMATION_COMPLETE 1 +#define MICROBIT_DISPLAY_EVT_LIGHT_SENSE 2 + +// +// Internal constants +// + +#define MICROBIT_DISPLAY_SPACING 1 +#define MICROBIT_DISPLAY_GREYSCALE_BIT_DEPTH 8 +#define MICROBIT_DISPLAY_ANIMATE_DEFAULT_POS -255 + +enum AnimationMode { + ANIMATION_MODE_NONE, + ANIMATION_MODE_STOPPED, + ANIMATION_MODE_SCROLL_TEXT, + ANIMATION_MODE_PRINT_TEXT, + ANIMATION_MODE_SCROLL_IMAGE, + ANIMATION_MODE_ANIMATE_IMAGE, + ANIMATION_MODE_PRINT_CHARACTER +}; + +enum DisplayMode { + DISPLAY_MODE_BLACK_AND_WHITE, + DISPLAY_MODE_GREYSCALE, + DISPLAY_MODE_BLACK_AND_WHITE_LIGHT_SENSE +}; + +enum DisplayRotation { + MICROBIT_DISPLAY_ROTATION_0, + MICROBIT_DISPLAY_ROTATION_90, + MICROBIT_DISPLAY_ROTATION_180, + MICROBIT_DISPLAY_ROTATION_270 +}; + +/** + * Class definition for MicroBitDisplay. + * + * A MicroBitDisplay represents the LED matrix array on the micro:bit. + */ +class MicroBitDisplay : public MicroBitComponent +{ + uint8_t width; + uint8_t height; + uint8_t brightness; + uint8_t strobeRow; + uint8_t rotation; + uint8_t mode; + uint8_t greyscaleBitMsk; + uint8_t timingCount; + uint32_t col_mask; + + Timeout renderTimer; + PortOut *LEDMatrix; + + // + // State used by all animation routines. + // + + // The animation mode that's currently running (if any) + volatile AnimationMode animationMode; + + // The time in milliseconds between each frame update. + uint16_t animationDelay; + + // The time in milliseconds since the frame update. + uint16_t animationTick; + + // Stop playback of any animations + void stopAnimation(int delay); + + // + // State for scrollString() method. + // This is a surprisingly intricate method. + // + // The text being displayed. + ManagedString scrollingText; + + // The index of the character currently being displayed. + uint16_t scrollingChar; + + // The number of pixels the current character has been shifted on the display. + uint8_t scrollingPosition; + + // + // State for printString() method. + // + // The text being displayed. NULL if no message is scheduled for playback. + // We *could* get some reuse in here with the scroll* variables above, + // but best to keep it clean in case kids try concurrent operation (they will!), + // given the small RAM overhead needed to maintain orthogonality. + ManagedString printingText; + + // The index of the character currently being displayed. + uint16_t printingChar; + + // + // State for scrollImage() method. + // + // The image being displayed. + MicroBitImage scrollingImage; + + // The number of pixels the image has been shifted on the display. + int16_t scrollingImagePosition; + + // The number of pixels the image is shifted on the display in each quantum. + int8_t scrollingImageStride; + + // A pointer to an instance of light sensor, if in use + MicroBitLightSensor* lightSensor; + + // Flag to indicate if image has been rendered to screen yet (or not) + bool scrollingImageRendered; + + const MatrixMap &matrixMap; + + // Internal methods to handle animation. + + /** + * Periodic callback, that we use to perform any animations we have running. + */ + void animationUpdate(); + + /** + * Called by the display in an interval determined by the brightness of the display, to give an impression + * of brightness. + */ + void renderFinish(); + + /** + * Translates a bit mask to a bit mask suitable for the nrf PORT0 and PORT1. + * Brightness has two levels on, or off. + */ + void render(); + + /** + * Renders the current image, and drops the fourth frame to allow for + * sensors that require the display to operate. + */ + void renderWithLightSense(); + + /** + * Translates a bit mask into a timer interrupt that gives the appearence of greyscale. + */ + void renderGreyscale(); + + /** + * Internal scrollText update method. + * Shift the screen image by one pixel to the left. If necessary, paste in the next char. + */ + void updateScrollText(); + + /** + * Internal printText update method. + * Paste the next character in the string. + */ + void updatePrintText(); + + /** + * Internal scrollImage update method. + * Paste the stored bitmap at the appropriate point. + */ + void updateScrollImage(); + + /** + * Internal animateImage update method. + * Paste the stored bitmap at the appropriate point and stop on the last frame. + */ + void updateAnimateImage(); + + /** + * Broadcasts an event onto the defult EventModel indicating that the + * current animation has completed. + */ + void sendAnimationCompleteEvent(); + + /** + * Blocks the current fiber until the display is available (i.e. does not effect is being displayed). + * Animations are queued until their time to display. + */ + void waitForFreeDisplay(); + + /** + * Blocks the current fiber until the current animation has finished. + * If the scheduler is not running, this call will essentially perform a spinning wait. + */ + void fiberWait(); + + /** + * Enables or disables the display entirely, and releases the pins for other uses. + * + * @param enableDisplay true to enabled the display, or false to disable it. + */ + void setEnable(bool enableDisplay); + +public: + // The mutable bitmap buffer being rendered to the LED matrix. + MicroBitImage image; + + /** + * Constructor. + * + * Create a software representation the micro:bit's 5x5 LED matrix. + * The display is initially blank. + * + * @param id The id the display should use when sending events on the MessageBus. Defaults to MICROBIT_ID_DISPLAY. + * + * @param map The mapping information that relates pin inputs/outputs to physical screen coordinates. + * Defaults to microbitMatrixMap, defined in MicroBitMatrixMaps.h. + * + * @code + * MicroBitDisplay display; + * @endcode + */ + MicroBitDisplay(uint16_t id = MICROBIT_ID_DISPLAY, const MatrixMap &map = microbitMatrixMap); + + /** + * Stops any currently running animation, and any that are waiting to be displayed. + */ + void stopAnimation(); + + /** + * Frame update method, invoked periodically to strobe the display. + */ + virtual void systemTick(); + + /** + * Prints the given character to the display, if it is not in use. + * + * @param c The character to display. + * + * @param delay Optional parameter - the time for which to show the character. Zero displays the character forever, + * or until the Displays next use. + * + * @return MICROBIT_OK, MICROBIT_BUSY is the screen is in use, or MICROBIT_INVALID_PARAMETER. + * + * @code + * display.printAsync('p'); + * display.printAsync('p',100); + * @endcode + */ + int printCharAsync(char c, int delay = 0); + + /** + * Prints the given ManagedString to the display, one character at a time. + * Returns immediately, and executes the animation asynchronously. + * + * @param s The string to display. + * + * @param delay The time to delay between characters, in milliseconds. Must be > 0. + * Defaults to: MICROBIT_DEFAULT_PRINT_SPEED. + * + * @return MICROBIT_OK, or MICROBIT_INVALID_PARAMETER. + * + * @code + * display.printAsync("abc123",400); + * @endcode + */ + int printAsync(ManagedString s, int delay = MICROBIT_DEFAULT_PRINT_SPEED); + + /** + * Prints the given image to the display, if the display is not in use. + * Returns immediately, and executes the animation asynchronously. + * + * @param i The image to display. + * + * @param x The horizontal position on the screen to display the image. Defaults to 0. + * + * @param y The vertical position on the screen to display the image. Defaults to 0. + * + * @param alpha Treats the brightness level '0' as transparent. Defaults to 0. + * + * @param delay The time to delay between characters, in milliseconds. Defaults to 0. + * + * @code + * MicrobitImage i("1,1,1,1,1\n1,1,1,1,1\n"); + * display.print(i,400); + * @endcode + */ + int printAsync(MicroBitImage i, int x = 0, int y = 0, int alpha = 0, int delay = 0); + + /** + * Prints the given character to the display. + * + * @param c The character to display. + * + * @param delay Optional parameter - the time for which to show the character. Zero displays the character forever, + * or until the Displays next use. + * + * @return MICROBIT_OK, MICROBIT_CANCELLED or MICROBIT_INVALID_PARAMETER. + * + * @code + * display.printAsync('p'); + * display.printAsync('p',100); + * @endcode + */ + int printChar(char c, int delay = 0); + + /** + * Prints the given string to the display, one character at a time. + * + * Blocks the calling thread until all the text has been displayed. + * + * @param s The string to display. + * + * @param delay The time to delay between characters, in milliseconds. Defaults + * to: MICROBIT_DEFAULT_PRINT_SPEED. + * + * @return MICROBIT_OK, MICROBIT_CANCELLED or MICROBIT_INVALID_PARAMETER. + * + * @code + * display.print("abc123",400); + * @endcode + */ + int print(ManagedString s, int delay = MICROBIT_DEFAULT_PRINT_SPEED); + + /** + * Prints the given image to the display. + * Blocks the calling thread until all the image has been displayed. + * + * @param i The image to display. + * + * @param x The horizontal position on the screen to display the image. Defaults to 0. + * + * @param y The vertical position on the screen to display the image. Defaults to 0. + * + * @param alpha Treats the brightness level '0' as transparent. Defaults to 0. + * + * @param delay The time to display the image for, or zero to show the image forever. Defaults to 0. + * + * @return MICROBIT_OK, MICROBIT_BUSY if the display is already in use, or MICROBIT_INVALID_PARAMETER. + * + * @code + * MicrobitImage i("1,1,1,1,1\n1,1,1,1,1\n"); + * display.print(i,400); + * @endcode + */ + int print(MicroBitImage i, int x = 0, int y = 0, int alpha = 0, int delay = 0); + + /** + * Scrolls the given string to the display, from right to left. + * Returns immediately, and executes the animation asynchronously. + * + * @param s The string to display. + * + * @param delay The time to delay between characters, in milliseconds. Defaults + * to: MICROBIT_DEFAULT_SCROLL_SPEED. + * + * @return MICROBIT_OK, MICROBIT_BUSY if the display is already in use, or MICROBIT_INVALID_PARAMETER. + * + * @code + * display.scrollAsync("abc123",100); + * @endcode + */ + int scrollAsync(ManagedString s, int delay = MICROBIT_DEFAULT_SCROLL_SPEED); + + /** + * Scrolls the given image across the display, from right to left. + * Returns immediately, and executes the animation asynchronously. + * + * @param image The image to display. + * + * @param delay The time between updates, in milliseconds. Defaults + * to: MICROBIT_DEFAULT_SCROLL_SPEED. + * + * @param stride The number of pixels to shift by in each update. Defaults to MICROBIT_DEFAULT_SCROLL_STRIDE. + * + * @return MICROBIT_OK, MICROBIT_BUSY if the display is already in use, or MICROBIT_INVALID_PARAMETER. + * + * @code + * MicrobitImage i("1,1,1,1,1\n1,1,1,1,1\n"); + * display.scrollAsync(i,100,1); + * @endcode + */ + int scrollAsync(MicroBitImage image, int delay = MICROBIT_DEFAULT_SCROLL_SPEED, int stride = MICROBIT_DEFAULT_SCROLL_STRIDE); + + /** + * Scrolls the given string across the display, from right to left. + * Blocks the calling thread until all text has been displayed. + * + * @param s The string to display. + * + * @param delay The time to delay between characters, in milliseconds. Defaults + * to: MICROBIT_DEFAULT_SCROLL_SPEED. + * + * @return MICROBIT_OK, MICROBIT_CANCELLED or MICROBIT_INVALID_PARAMETER. + * + * @code + * display.scroll("abc123",100); + * @endcode + */ + int scroll(ManagedString s, int delay = MICROBIT_DEFAULT_SCROLL_SPEED); + + /** + * Scrolls the given image across the display, from right to left. + * Blocks the calling thread until all the text has been displayed. + * + * @param image The image to display. + * + * @param delay The time between updates, in milliseconds. Defaults + * to: MICROBIT_DEFAULT_SCROLL_SPEED. + * + * @param stride The number of pixels to shift by in each update. Defaults to MICROBIT_DEFAULT_SCROLL_STRIDE. + * + * @return MICROBIT_OK, MICROBIT_CANCELLED or MICROBIT_INVALID_PARAMETER. + * + * @code + * MicrobitImage i("1,1,1,1,1\n1,1,1,1,1\n"); + * display.scroll(i,100,1); + * @endcode + */ + int scroll(MicroBitImage image, int delay = MICROBIT_DEFAULT_SCROLL_SPEED, int stride = MICROBIT_DEFAULT_SCROLL_STRIDE); + + /** + * "Animates" the current image across the display with a given stride, finishing on the last frame of the animation. + * Returns immediately. + * + * @param image The image to display. + * + * @param delay The time to delay between each update of the display, in milliseconds. + * + * @param stride The number of pixels to shift by in each update. + * + * @param startingPosition the starting position on the display for the animation + * to begin at. Defaults to MICROBIT_DISPLAY_ANIMATE_DEFAULT_POS. + * + * @return MICROBIT_OK, MICROBIT_BUSY if the screen is in use, or MICROBIT_INVALID_PARAMETER. + * + * @code + * const int heart_w = 10; + * const int heart_h = 5; + * const uint8_t heart[] = { 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, }; + * + * MicroBitImage i(heart_w,heart_h,heart); + * display.animateAsync(i,100,5); + * @endcode + */ + int animateAsync(MicroBitImage image, int delay, int stride, int startingPosition = MICROBIT_DISPLAY_ANIMATE_DEFAULT_POS); + + /** + * "Animates" the current image across the display with a given stride, finishing on the last frame of the animation. + * Blocks the calling thread until the animation is complete. + * + * + * @param delay The time to delay between each update of the display, in milliseconds. + * + * @param stride The number of pixels to shift by in each update. + * + * @param startingPosition the starting position on the display for the animation + * to begin at. Defaults to MICROBIT_DISPLAY_ANIMATE_DEFAULT_POS. + * + * @return MICROBIT_OK, MICROBIT_CANCELLED or MICROBIT_INVALID_PARAMETER. + * + * @code + * const int heart_w = 10; + * const int heart_h = 5; + * const uint8_t heart[] = { 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, }; + * + * MicroBitImage i(heart_w,heart_h,heart); + * display.animate(i,100,5); + * @endcode + */ + int animate(MicroBitImage image, int delay, int stride, int startingPosition = MICROBIT_DISPLAY_ANIMATE_DEFAULT_POS); + + /** + * Configures the brightness of the display. + * + * @param b The brightness to set the brightness to, in the range 0 - 255. + * + * @return MICROBIT_OK, or MICROBIT_INVALID_PARAMETER + * + * @code + * display.setBrightness(255); //max brightness + * @endcode + */ + int setBrightness(int b); + + /** + * Configures the mode of the display. + * + * @param mode The mode to swap the display into. One of: DISPLAY_MODE_GREYSCALE, + * DISPLAY_MODE_BLACK_AND_WHITE, DISPLAY_MODE_BLACK_AND_WHITE_LIGHT_SENSE + * + * @code + * display.setDisplayMode(DISPLAY_MODE_GREYSCALE); //per pixel brightness + * @endcode + */ + void setDisplayMode(DisplayMode mode); + + /** + * Retrieves the mode of the display. + * + * @return the current mode of the display + */ + int getDisplayMode(); + + /** + * Fetches the current brightness of this display. + * + * @return the brightness of this display, in the range 0..255. + * + * @code + * display.getBrightness(); //the current brightness + * @endcode + */ + int getBrightness(); + + /** + * Rotates the display to the given position. + * + * Axis aligned values only. + * + * @code + * display.rotateTo(MICROBIT_DISPLAY_ROTATION_180); //rotates 180 degrees from original orientation + * @endcode + */ + void rotateTo(DisplayRotation position); + + /** + * Enables the display, should only be called if the display is disabled. + * + * @code + * display.enable(); //Enables the display mechanics + * @endcode + * + * @note Only enables the display if the display is currently disabled. + */ + void enable(); + + /** + * Disables the display, which releases control of the GPIO pins used by the display, + * which are exposed on the edge connector. + * + * @code + * display.disable(); //disables the display + * @endcode + * + * @note Only disables the display if the display is currently enabled. + */ + void disable(); + + /** + * Clears the display of any remaining pixels. + * + * `display.image.clear()` can also be used! + * + * @code + * display.clear(); //clears the display + * @endcode + */ + void clear(); + + /** + * Updates the font that will be used for display operations. + * + * @param font the new font that will be used to render characters. + * + * @note DEPRECATED! Please use MicroBitFont::setSystemFont() instead. + */ + void setFont(MicroBitFont font); + + /** + * Retrieves the font object used for rendering characters on the display. + * + * @note DEPRECATED! Please use MicroBitFont::getSystemFont() instead. + */ + MicroBitFont getFont(); + + /** + * Captures the bitmap currently being rendered on the display. + * + * @return a MicroBitImage containing the captured data. + */ + MicroBitImage screenShot(); + + /** + * Gives a representative figure of the light level in the current environment + * where are micro:bit is situated. + * + * Internally, it constructs an instance of a MicroBitLightSensor if not already configured + * and sets the display mode to DISPLAY_MODE_BLACK_AND_WHITE_LIGHT_SENSE. + * + * This also changes the tickPeriod to MICROBIT_LIGHT_SENSOR_TICK_SPEED so + * that the display does not suffer from artifacts. + * + * @return an indicative light level in the range 0 - 255. + * + * @note this will return 0 on the first call to this method, a light reading + * will be available after the display has activated the light sensor for the + * first time. + */ + int readLightLevel(); + + /** + * Destructor for MicroBitDisplay, where we deregister this instance from the array of system components. + */ + ~MicroBitDisplay(); +}; + +#endif