microbit-dal/inc/MicroBitDisplay.h

568 lines
18 KiB
C
Raw Normal View History

#ifndef MICROBIT_DISPLAY_H
#define MICROBIT_DISPLAY_H
/**
* Core Configuration settings.
*/
#define MICROBIT_DISPLAY_REFRESH_PERIOD ((float)FIBER_TICK_PERIOD_MS / (float)1000)
/**
* MessageBus Event Codes
*/
#define MICROBIT_DISPLAY_EVT_ANIMATION_COMPLETE 1
#define MICROBIT_DISPLAY_EVT_FREE 2
/**
* I/O configurations for common devices.
*/
#if MICROBIT_DISPLAY_TYPE == MICROBUG_REFERENCE_DEVICE
#define MICROBIT_DISPLAY_ROW_COUNT 5
#define MICROBIT_DISPLAY_ROW_PINS P0_0, P0_1, P0_2, P0_3, P0_4
#define MICROBIT_DISPLAY_COLUMN_COUNT 5
#define MICROBIT_DISPLAY_COLUMN_PINS P0_24, P0_25, P0_28, P0_29, P0_30
#endif
#if MICROBIT_DISPLAY_TYPE == MICROBIT_3X9
#define MICROBIT_DISPLAY_ROW_COUNT 3
#define MICROBIT_DISPLAY_ROW_PINS P0_12, P0_13, P0_14
#define MICROBIT_DISPLAY_COLUMN_COUNT 9
#define MICROBIT_DISPLAY_COLUMN_PINS P0_15, P0_16, P0_17, P0_18, P0_19, P0_24, P0_25, P0_28, P0_29
#endif
#if MICROBIT_DISPLAY_TYPE == MICROBIT_SB1
#define MICROBIT_DISPLAY_ROW_COUNT 9
#define MICROBIT_DISPLAY_ROW_PINS P0_15, P0_16, P0_17, P0_18, P0_19, P0_24, P0_25, P0_28, P0_29
#define MICROBIT_DISPLAY_COLUMN_COUNT 3
#define MICROBIT_DISPLAY_COLUMN_PINS P0_12, P0_13, P0_14
#endif
#if MICROBIT_DISPLAY_TYPE == MICROBIT_SB2
#define MICROBIT_DISPLAY_ROW_COUNT 3
#define MICROBIT_DISPLAY_ROW_PINS P0_13, P0_14, P0_15
#define MICROBIT_DISPLAY_COLUMN_COUNT 9
#define MICROBIT_DISPLAY_COLUMN_PINS P0_4, P0_5, P0_6, P0_7, P0_8, P0_9, P0_10, P0_11, P0_12
#define MICROBIT_DISPLAY_COLUMN_START P0_4
#endif
//
// Internal constants
//
#define MICROBIT_DISPLAY_WIDTH 5
#define MICROBIT_DISPLAY_HEIGHT 5
#define MICROBIT_DISPLAY_SPACING 1
#define MICROBIT_DISPLAY_ERROR_CHARS 4
#define MICROBIT_DISPLAY_GREYSCALE_BIT_DEPTH 8
#define MICROBIT_DISPLAY_ANIMATE_DEFAULT_POS -255
#include "mbed.h"
microbit: Added configurable concurrency modes for MicroBitMessageBus handlers. MessageBus handlers can now have one of four concurrency modes for the eventuality of an event being raised whilst a previous event is still being processed. An additional (optional) parameter is provided to the listen() functions to allow this to be selected on a per event handler basis. The permissable options are: MESSAGE_BUS_LISTENER_REENTRANT: The event handler is fired with the new event, regardless of whether or not a previous event is still be processed by that handler. MESSAGE_BUS_LISTENER_QUEUE_IF_BUSY: The new event is queued until such a time as the previous event has completed execution. The new event is then processed. This option does not preclude the processing of the new event by other event handlers. MESSAGE_BUS_LISTENER_DROP_IF_BUSY: The new event is dropped, and will never be processed the the event handler. This option does not preclude the processing of the new event by other event handlers. MESSAGE_BUS_LISTENER_NONBLOCKING: The event handler is self-declaring that it never blocks. This flag is used purely for optimisation, as it permits direct execution of the event hadnelr without inducing any overhead from the scheduler. In addition, the following minor revisions were made in this release: * Cleanup of the #include dependencies contained in the microbit-dal .h files * Bugfix to the scheduler block on event matching code. * Introduced a MICROBIT_ID_ALERT MessageBus channel, for general purpose eventing using nonces.
2015-09-11 15:39:38 +00:00
#include "ManagedString.h"
#include "MicroBitComponent.h"
#include "MicroBitImage.h"
#include "MicroBitFont.h"
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
};
enum DisplayRotation {
MICROBIT_DISPLAY_ROTATION_0,
MICROBIT_DISPLAY_ROTATION_90,
MICROBIT_DISPLAY_ROTATION_180,
MICROBIT_DISPLAY_ROTATION_270
};
struct MatrixPoint {
uint8_t x;
uint8_t y;
};
/**
* Class definition for a MicroBitDisplay.
*
* A MicroBitDisplay represents the LED matrix array on the MicroBit device.
*/
class MicroBitDisplay : public MicroBitComponent
{
uint8_t width;
uint8_t height;
uint8_t brightness;
uint8_t strobeRow;
uint8_t strobeBitMsk;
uint8_t rotation;
uint8_t mode;
uint8_t greyscaleBitMsk;
uint8_t timingCount;
Timeout renderTimer;
MicroBitFont font;
//
// State used by all animation routines.
//
// The animation mode that's currently running (if any)
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;
// Flag to indicate if image has been rendered to screen yet (or not)
bool scrollingImageRendered;
static const MatrixPoint matrixMap[MICROBIT_DISPLAY_COLUMN_COUNT][MICROBIT_DISPLAY_ROW_COUNT];
// 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();
/**
* 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 in the next char 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 shared MessageBus
* @param eventCode The ID of the event that has occurred.
*/
microbit: Added configurable concurrency modes for MicroBitMessageBus handlers. MessageBus handlers can now have one of four concurrency modes for the eventuality of an event being raised whilst a previous event is still being processed. An additional (optional) parameter is provided to the listen() functions to allow this to be selected on a per event handler basis. The permissable options are: MESSAGE_BUS_LISTENER_REENTRANT: The event handler is fired with the new event, regardless of whether or not a previous event is still be processed by that handler. MESSAGE_BUS_LISTENER_QUEUE_IF_BUSY: The new event is queued until such a time as the previous event has completed execution. The new event is then processed. This option does not preclude the processing of the new event by other event handlers. MESSAGE_BUS_LISTENER_DROP_IF_BUSY: The new event is dropped, and will never be processed the the event handler. This option does not preclude the processing of the new event by other event handlers. MESSAGE_BUS_LISTENER_NONBLOCKING: The event handler is self-declaring that it never blocks. This flag is used purely for optimisation, as it permits direct execution of the event hadnelr without inducing any overhead from the scheduler. In addition, the following minor revisions were made in this release: * Cleanup of the #include dependencies contained in the microbit-dal .h files * Bugfix to the scheduler block on event matching code. * Introduced a MICROBIT_ID_ALERT MessageBus channel, for general purpose eventing using nonces.
2015-09-11 15:39:38 +00:00
void sendAnimationCompleteEvent();
/**
* Blocks the current fiber until the display is available (i.e. not effect is being displayed).
* Animations are queued until their time to display.
*/
void waitForFreeDisplay();
public:
// The mutable bitmap buffer being rendered to the LED matrix.
MicroBitImage image;
/**
* Constructor.
* Create a representation of a display of a given size.
* The display is initially blank.
*
* @param x the width of the display in pixels.
* @param y the height of the display in pixels.
*
* Example:
* @code
* MicroBitDisplay display(MICROBIT_ID_DISPLAY, 5, 5),
* @endcode
*/
MicroBitDisplay(uint16_t id, uint8_t x, uint8_t y);
/**
* 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.
2015-11-01 18:22:27 +00:00
* @param delay Optional parameter - the time for which to show the character. Zero displays the character forever.
* @return MICROBIT_OK, MICROBIT_BUSY is the screen is in use, or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
* uBit.display.printAsync('p');
* uBit.display.printAsync('p',100);
* @endcode
*/
2015-11-01 18:22:27 +00:00
int printAsync(char c, int delay = 0);
/**
* Prints the given string to the display, one character at a time.
* Uses the given delay between characters.
* 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.
* @return MICROBIT_OK, or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
* uBit.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 (default 0)
* @param y The vertical position on the screen to display the image (default 0)
* @param alpha Treats the brightness level '0' as transparent (default 0)
2015-11-01 18:22:27 +00:00
* @param delay The time to delay between characters, in milliseconds. set to 0 to display forever. (default 0).
*
* Example:
* @code
* MicrobitImage i("1,1,1,1,1\n1,1,1,1,1\n");
* uBit.display.print(i,400);
* @endcode
*/
2015-11-01 18:22:27 +00:00
int printAsync(MicroBitImage i, int x, int y, int alpha, int delay = 0);
/**
* Prints the given character to the display.
*
* @param c The character to display.
* @param delay The time to delay between characters, in milliseconds. Must be > 0.
2015-11-01 18:22:27 +00:00
* @return MICROBIT_OK, MICROBIT_CANCELLED or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
* uBit.display.print('p');
* @endcode
*/
int print(char c, int delay = 0);
/**
* Prints the given string to the display, one character at a time.
* Uses the given delay between characters.
* 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. Must be > 0.
2015-11-01 18:22:27 +00:00
* @return MICROBIT_OK, MICROBIT_CANCELLED or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
* uBit.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 text has been displayed.
*
* @param i The image to display.
* @param delay The time to display the image for, or zero to show the image forever. Must be >= 0.
2015-11-01 18:22:27 +00:00
* @return MICROBIT_OK, MICROBIT_BUSY if the display is already in use, or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
* MicrobitImage i("1,1,1,1,1\n1,1,1,1,1\n");
* uBit.display.print(i,400);
* @endcode
*/
2015-11-01 18:22:27 +00:00
int print(MicroBitImage i, int x, int y, int alpha, int delay = 0);
/**
* Scrolls the given string to the display, from right to left.
* Uses the given delay between characters.
* Returns immediately, and executes the animation asynchronously.
*
* @param s The string to display.
* @param delay The time to delay between each update to the display, in milliseconds. Must be > 0.
2015-11-01 18:22:27 +00:00
* @return MICROBIT_OK, MICROBIT_BUSY if the display is already in use, or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
* uBit.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 to delay between each update to the display, in milliseconds. Must be > 0.
* @param stride The number of pixels to move in each update. Default value is the screen width.
2015-11-01 18:22:27 +00:00
* @return MICROBIT_OK, MICROBIT_BUSY if the display is already in use, or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
* MicrobitImage i("1,1,1,1,1\n1,1,1,1,1\n");
* uBit.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 to the display, from right to left.
* Uses the given delay between characters.
* Blocks the calling thread until all the text has been displayed.
*
* @param s The string to display.
* @param delay The time to delay between each update to the display, in milliseconds. Must be > 0.
2015-11-01 18:22:27 +00:00
* @return MICROBIT_OK, MICROBIT_CANCELLED or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
* uBit.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 to delay between each update to the display, in milliseconds. Must be > 0.
* @param stride The number of pixels to move in each update. Default value is the screen width.
2015-11-01 18:22:27 +00:00
* @return MICROBIT_OK, MICROBIT_CANCELLED or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
* MicrobitImage i("1,1,1,1,1\n1,1,1,1,1\n");
* uBit.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 to the display, in milliseconds. Must be > 0.
* @param stride The number of pixels to move in each update. Default value is the screen width.
2015-11-01 18:22:27 +00:00
* @return MICROBIT_OK, MICROBIT_BUSY if the screen is in use, or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @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);
* uBit.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 image The image to display.
* @param delay The time to delay between each update to the display, in milliseconds. Must be > 0.
* @param stride The number of pixels to move in each update. Default value is the screen width.
2015-11-01 18:22:27 +00:00
* @return MICROBIT_OK, MICROBIT_CANCELLED or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @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);
* uBit.display.animate(i,100,5);
* @endcode
*/
int animate(MicroBitImage image, int delay, int stride, int startingPosition = MICROBIT_DISPLAY_ANIMATE_DEFAULT_POS);
/**
* Sets the display brightness to the specified level.
* @param b The brightness to set the brightness to, in the range 0..255.
* @return MICROBIT_OK, or MICROBIT_INVALID_PARAMETER
*
* Example:
* @code
* uBit.display.setBrightness(255); //max brightness
* @endcode
*/
int setBrightness(int b);
/**
* Sets the mode of the display.
* @param mode The mode to swap the display into. (can be either DISPLAY_MODE_GREYSCALE, or DISPLAY_MODE_NORMAL)
*
* Example:
* @code
* uBit.display.setDisplayMode(DISPLAY_MODE_GREYSCALE); //per pixel brightness
* @endcode
*/
void setDisplayMode(DisplayMode mode);
/**
* Fetches the current brightness of this display.
* @return the brightness of this display, in the range 0..255.
*
* Example:
* @code
* uBit.display.getBrightness(); //the current brightness
* @endcode
*/
int getBrightness();
/**
* Rotates the display to the given position.
* Axis aligned values only.
*
* Example:
* @code
* uBit.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.
*
* Example:
* @code
* uBit.display.enable(); //reenables the display mechanics
* @endcode
*/
void enable();
/**
* Disables the display, should only be called if the display is enabled.
* Display must be disabled to avoid MUXing of edge connector pins.
*
* Example:
* @code
* uBit.display.disable(); //disables the display
* @endcode
*/
void disable();
/**
* Clears the current image on the display.
* Simplifies the process, you can also use uBit.display.image.clear
*
* Example:
* @code
* uBit.display.clear(); //clears the display
* @endcode
*/
void clear();
/**
* Displays "=(" and an accompanying status code infinitely.
* @param statusCode the appropriate status code - 0 means no code will be displayed. Status codes must be in the range 0-255.
*
* Example:
* @code
* uBit.display.error(20);
* @endcode
*/
void error(int statusCode);
/**
* Updates the font property of this object with the new font.
* @param font the new font that will be used to render characters..
*/
void setFont(MicroBitFont font);
/**
* Retreives the font object used for rendering characters on the display.
*/
MicroBitFont getFont();
/**
* Captures the bitmap currently being rendered on the display.
*/
MicroBitImage screenShot();
};
#endif