Official Sheffield ARMBand micro:bit program

Committer:
MrBedfordVan
Date:
Mon Oct 17 12:41:20 2016 +0000
Revision:
0:b9164b348919
Official Sheffield ARMBand Micro:bit program

Who changed what in which revision?

UserRevisionLine numberNew contents of line
MrBedfordVan 0:b9164b348919 1 /*
MrBedfordVan 0:b9164b348919 2 The MIT License (MIT)
MrBedfordVan 0:b9164b348919 3
MrBedfordVan 0:b9164b348919 4 Copyright (c) 2016 British Broadcasting Corporation.
MrBedfordVan 0:b9164b348919 5 This software is provided by Lancaster University by arrangement with the BBC.
MrBedfordVan 0:b9164b348919 6
MrBedfordVan 0:b9164b348919 7 Permission is hereby granted, free of charge, to any person obtaining a
MrBedfordVan 0:b9164b348919 8 copy of this software and associated documentation files (the "Software"),
MrBedfordVan 0:b9164b348919 9 to deal in the Software without restriction, including without limitation
MrBedfordVan 0:b9164b348919 10 the rights to use, copy, modify, merge, publish, distribute, sublicense,
MrBedfordVan 0:b9164b348919 11 and/or sell copies of the Software, and to permit persons to whom the
MrBedfordVan 0:b9164b348919 12 Software is furnished to do so, subject to the following conditions:
MrBedfordVan 0:b9164b348919 13
MrBedfordVan 0:b9164b348919 14 The above copyright notice and this permission notice shall be included in
MrBedfordVan 0:b9164b348919 15 all copies or substantial portions of the Software.
MrBedfordVan 0:b9164b348919 16
MrBedfordVan 0:b9164b348919 17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
MrBedfordVan 0:b9164b348919 18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
MrBedfordVan 0:b9164b348919 19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
MrBedfordVan 0:b9164b348919 20 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
MrBedfordVan 0:b9164b348919 21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
MrBedfordVan 0:b9164b348919 22 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
MrBedfordVan 0:b9164b348919 23 DEALINGS IN THE SOFTWARE.
MrBedfordVan 0:b9164b348919 24 */
MrBedfordVan 0:b9164b348919 25
MrBedfordVan 0:b9164b348919 26 /**
MrBedfordVan 0:b9164b348919 27 * Class definition for MicroBitDisplay.
MrBedfordVan 0:b9164b348919 28 *
MrBedfordVan 0:b9164b348919 29 * A MicroBitDisplay represents the LED matrix array on the micro:bit.
MrBedfordVan 0:b9164b348919 30 */
MrBedfordVan 0:b9164b348919 31 #include "MicroBitConfig.h"
MrBedfordVan 0:b9164b348919 32 #include "MicroBitDisplay.h"
MrBedfordVan 0:b9164b348919 33 #include "MicroBitSystemTimer.h"
MrBedfordVan 0:b9164b348919 34 #include "MicroBitFiber.h"
MrBedfordVan 0:b9164b348919 35 #include "ErrorNo.h"
MrBedfordVan 0:b9164b348919 36 #include "NotifyEvents.h"
MrBedfordVan 0:b9164b348919 37
MrBedfordVan 0:b9164b348919 38 const int greyScaleTimings[MICROBIT_DISPLAY_GREYSCALE_BIT_DEPTH] = {1, 23, 70, 163, 351, 726, 1476, 2976};
MrBedfordVan 0:b9164b348919 39
MrBedfordVan 0:b9164b348919 40 /**
MrBedfordVan 0:b9164b348919 41 * Constructor.
MrBedfordVan 0:b9164b348919 42 *
MrBedfordVan 0:b9164b348919 43 * Create a software representation the micro:bit's 5x5 LED matrix.
MrBedfordVan 0:b9164b348919 44 * The display is initially blank.
MrBedfordVan 0:b9164b348919 45 *
MrBedfordVan 0:b9164b348919 46 * @param id The id the display should use when sending events on the MessageBus. Defaults to MICROBIT_ID_DISPLAY.
MrBedfordVan 0:b9164b348919 47 *
MrBedfordVan 0:b9164b348919 48 * @param map The mapping information that relates pin inputs/outputs to physical screen coordinates.
MrBedfordVan 0:b9164b348919 49 * Defaults to microbitMatrixMap, defined in MicroBitMatrixMaps.h.
MrBedfordVan 0:b9164b348919 50 *
MrBedfordVan 0:b9164b348919 51 * @code
MrBedfordVan 0:b9164b348919 52 * MicroBitDisplay display;
MrBedfordVan 0:b9164b348919 53 * @endcode
MrBedfordVan 0:b9164b348919 54 */
MrBedfordVan 0:b9164b348919 55 MicroBitDisplay::MicroBitDisplay(uint16_t id, const MatrixMap &map) :
MrBedfordVan 0:b9164b348919 56 matrixMap(map),
MrBedfordVan 0:b9164b348919 57 image(map.width*2,map.height)
MrBedfordVan 0:b9164b348919 58 {
MrBedfordVan 0:b9164b348919 59 uint32_t row_mask;
MrBedfordVan 0:b9164b348919 60
MrBedfordVan 0:b9164b348919 61 this->id = id;
MrBedfordVan 0:b9164b348919 62 this->width = map.width;
MrBedfordVan 0:b9164b348919 63 this->height = map.height;
MrBedfordVan 0:b9164b348919 64 this->rotation = MICROBIT_DISPLAY_ROTATION_0;
MrBedfordVan 0:b9164b348919 65
MrBedfordVan 0:b9164b348919 66 row_mask = 0;
MrBedfordVan 0:b9164b348919 67 col_mask = 0;
MrBedfordVan 0:b9164b348919 68 strobeRow = 0;
MrBedfordVan 0:b9164b348919 69 row_mask = 0;
MrBedfordVan 0:b9164b348919 70
MrBedfordVan 0:b9164b348919 71 for (int i = matrixMap.rowStart; i < matrixMap.rowStart + matrixMap.rows; i++)
MrBedfordVan 0:b9164b348919 72 row_mask |= 0x01 << i;
MrBedfordVan 0:b9164b348919 73
MrBedfordVan 0:b9164b348919 74 for (int i = matrixMap.columnStart; i < matrixMap.columnStart + matrixMap.columns; i++)
MrBedfordVan 0:b9164b348919 75 col_mask |= 0x01 << i;
MrBedfordVan 0:b9164b348919 76
MrBedfordVan 0:b9164b348919 77 LEDMatrix = new PortOut(Port0, row_mask | col_mask);
MrBedfordVan 0:b9164b348919 78
MrBedfordVan 0:b9164b348919 79 this->greyscaleBitMsk = 0x01;
MrBedfordVan 0:b9164b348919 80 this->timingCount = 0;
MrBedfordVan 0:b9164b348919 81 this->setBrightness(MICROBIT_DISPLAY_DEFAULT_BRIGHTNESS);
MrBedfordVan 0:b9164b348919 82 this->mode = DISPLAY_MODE_BLACK_AND_WHITE;
MrBedfordVan 0:b9164b348919 83 this->animationMode = ANIMATION_MODE_NONE;
MrBedfordVan 0:b9164b348919 84 this->lightSensor = NULL;
MrBedfordVan 0:b9164b348919 85
MrBedfordVan 0:b9164b348919 86 system_timer_add_component(this);
MrBedfordVan 0:b9164b348919 87
MrBedfordVan 0:b9164b348919 88 status |= MICROBIT_COMPONENT_RUNNING;
MrBedfordVan 0:b9164b348919 89 }
MrBedfordVan 0:b9164b348919 90
MrBedfordVan 0:b9164b348919 91 /**
MrBedfordVan 0:b9164b348919 92 * Internal frame update method, used to strobe the display.
MrBedfordVan 0:b9164b348919 93 *
MrBedfordVan 0:b9164b348919 94 * TODO: Write a more efficient, complementary variation of this method for the case where
MrBedfordVan 0:b9164b348919 95 * MICROBIT_DISPLAY_ROW_COUNT > MICROBIT_DISPLAY_COLUMN_COUNT.
MrBedfordVan 0:b9164b348919 96 */
MrBedfordVan 0:b9164b348919 97 void MicroBitDisplay::systemTick()
MrBedfordVan 0:b9164b348919 98 {
MrBedfordVan 0:b9164b348919 99 if(!(status & MICROBIT_COMPONENT_RUNNING))
MrBedfordVan 0:b9164b348919 100 return;
MrBedfordVan 0:b9164b348919 101
MrBedfordVan 0:b9164b348919 102 if(mode == DISPLAY_MODE_BLACK_AND_WHITE_LIGHT_SENSE)
MrBedfordVan 0:b9164b348919 103 {
MrBedfordVan 0:b9164b348919 104 renderWithLightSense();
MrBedfordVan 0:b9164b348919 105 return;
MrBedfordVan 0:b9164b348919 106 }
MrBedfordVan 0:b9164b348919 107
MrBedfordVan 0:b9164b348919 108 // Move on to the next row.
MrBedfordVan 0:b9164b348919 109 strobeRow++;
MrBedfordVan 0:b9164b348919 110
MrBedfordVan 0:b9164b348919 111 //reset the row counts and bit mask when we have hit the max.
MrBedfordVan 0:b9164b348919 112 if(strobeRow == matrixMap.rows)
MrBedfordVan 0:b9164b348919 113 strobeRow = 0;
MrBedfordVan 0:b9164b348919 114
MrBedfordVan 0:b9164b348919 115 if(mode == DISPLAY_MODE_BLACK_AND_WHITE)
MrBedfordVan 0:b9164b348919 116 render();
MrBedfordVan 0:b9164b348919 117
MrBedfordVan 0:b9164b348919 118 if(mode == DISPLAY_MODE_GREYSCALE)
MrBedfordVan 0:b9164b348919 119 {
MrBedfordVan 0:b9164b348919 120 greyscaleBitMsk = 0x01;
MrBedfordVan 0:b9164b348919 121 timingCount = 0;
MrBedfordVan 0:b9164b348919 122 renderGreyscale();
MrBedfordVan 0:b9164b348919 123 }
MrBedfordVan 0:b9164b348919 124
MrBedfordVan 0:b9164b348919 125 // Update text and image animations if we need to.
MrBedfordVan 0:b9164b348919 126 this->animationUpdate();
MrBedfordVan 0:b9164b348919 127 }
MrBedfordVan 0:b9164b348919 128
MrBedfordVan 0:b9164b348919 129 void MicroBitDisplay::renderFinish()
MrBedfordVan 0:b9164b348919 130 {
MrBedfordVan 0:b9164b348919 131 *LEDMatrix = 0;
MrBedfordVan 0:b9164b348919 132 }
MrBedfordVan 0:b9164b348919 133
MrBedfordVan 0:b9164b348919 134 void MicroBitDisplay::render()
MrBedfordVan 0:b9164b348919 135 {
MrBedfordVan 0:b9164b348919 136 // Simple optimisation.
MrBedfordVan 0:b9164b348919 137 // If display is at zero brightness, there's nothing to do.
MrBedfordVan 0:b9164b348919 138 if(brightness == 0)
MrBedfordVan 0:b9164b348919 139 return;
MrBedfordVan 0:b9164b348919 140
MrBedfordVan 0:b9164b348919 141 // Calculate the bitpattern to write.
MrBedfordVan 0:b9164b348919 142 uint32_t row_data = 0x01 << (matrixMap.rowStart + strobeRow);
MrBedfordVan 0:b9164b348919 143 uint32_t col_data = 0;
MrBedfordVan 0:b9164b348919 144
MrBedfordVan 0:b9164b348919 145 for (int i = 0; i < matrixMap.columns; i++)
MrBedfordVan 0:b9164b348919 146 {
MrBedfordVan 0:b9164b348919 147 int index = (i * matrixMap.rows) + strobeRow;
MrBedfordVan 0:b9164b348919 148
MrBedfordVan 0:b9164b348919 149 int x = matrixMap.map[index].x;
MrBedfordVan 0:b9164b348919 150 int y = matrixMap.map[index].y;
MrBedfordVan 0:b9164b348919 151 int t = x;
MrBedfordVan 0:b9164b348919 152
MrBedfordVan 0:b9164b348919 153 if(rotation == MICROBIT_DISPLAY_ROTATION_90)
MrBedfordVan 0:b9164b348919 154 {
MrBedfordVan 0:b9164b348919 155 x = width - 1 - y;
MrBedfordVan 0:b9164b348919 156 y = t;
MrBedfordVan 0:b9164b348919 157 }
MrBedfordVan 0:b9164b348919 158
MrBedfordVan 0:b9164b348919 159 if(rotation == MICROBIT_DISPLAY_ROTATION_180)
MrBedfordVan 0:b9164b348919 160 {
MrBedfordVan 0:b9164b348919 161 x = width - 1 - x;
MrBedfordVan 0:b9164b348919 162 y = height - 1 - y;
MrBedfordVan 0:b9164b348919 163 }
MrBedfordVan 0:b9164b348919 164
MrBedfordVan 0:b9164b348919 165 if(rotation == MICROBIT_DISPLAY_ROTATION_270)
MrBedfordVan 0:b9164b348919 166 {
MrBedfordVan 0:b9164b348919 167 x = y;
MrBedfordVan 0:b9164b348919 168 y = height - 1 - t;
MrBedfordVan 0:b9164b348919 169 }
MrBedfordVan 0:b9164b348919 170
MrBedfordVan 0:b9164b348919 171 if(image.getBitmap()[y*(width*2)+x])
MrBedfordVan 0:b9164b348919 172 col_data |= (1 << i);
MrBedfordVan 0:b9164b348919 173 }
MrBedfordVan 0:b9164b348919 174
MrBedfordVan 0:b9164b348919 175 // Invert column bits (as we're sinking not sourcing power), and mask off any unused bits.
MrBedfordVan 0:b9164b348919 176 col_data = ~col_data << matrixMap.columnStart & col_mask;
MrBedfordVan 0:b9164b348919 177
MrBedfordVan 0:b9164b348919 178 // Write the new bit pattern
MrBedfordVan 0:b9164b348919 179 *LEDMatrix = col_data | row_data;
MrBedfordVan 0:b9164b348919 180
MrBedfordVan 0:b9164b348919 181 //timer does not have enough resolution for brightness of 1. 23.53 us
MrBedfordVan 0:b9164b348919 182 if(brightness != MICROBIT_DISPLAY_MAXIMUM_BRIGHTNESS && brightness > MICROBIT_DISPLAY_MINIMUM_BRIGHTNESS)
MrBedfordVan 0:b9164b348919 183 renderTimer.attach_us(this, &MicroBitDisplay::renderFinish, (((brightness * 950) / (MICROBIT_DISPLAY_MAXIMUM_BRIGHTNESS)) * system_timer_get_period()));
MrBedfordVan 0:b9164b348919 184
MrBedfordVan 0:b9164b348919 185 //this will take around 23us to execute
MrBedfordVan 0:b9164b348919 186 if(brightness <= MICROBIT_DISPLAY_MINIMUM_BRIGHTNESS)
MrBedfordVan 0:b9164b348919 187 renderFinish();
MrBedfordVan 0:b9164b348919 188 }
MrBedfordVan 0:b9164b348919 189
MrBedfordVan 0:b9164b348919 190 void MicroBitDisplay::renderWithLightSense()
MrBedfordVan 0:b9164b348919 191 {
MrBedfordVan 0:b9164b348919 192 //reset the row counts and bit mask when we have hit the max.
MrBedfordVan 0:b9164b348919 193 if(strobeRow == matrixMap.rows + 1)
MrBedfordVan 0:b9164b348919 194 {
MrBedfordVan 0:b9164b348919 195 MicroBitEvent(id, MICROBIT_DISPLAY_EVT_LIGHT_SENSE);
MrBedfordVan 0:b9164b348919 196 strobeRow = 0;
MrBedfordVan 0:b9164b348919 197 }
MrBedfordVan 0:b9164b348919 198 else
MrBedfordVan 0:b9164b348919 199 {
MrBedfordVan 0:b9164b348919 200 render();
MrBedfordVan 0:b9164b348919 201 this->animationUpdate();
MrBedfordVan 0:b9164b348919 202
MrBedfordVan 0:b9164b348919 203 // Move on to the next row.
MrBedfordVan 0:b9164b348919 204 strobeRow++;
MrBedfordVan 0:b9164b348919 205 }
MrBedfordVan 0:b9164b348919 206
MrBedfordVan 0:b9164b348919 207 }
MrBedfordVan 0:b9164b348919 208
MrBedfordVan 0:b9164b348919 209 void MicroBitDisplay::renderGreyscale()
MrBedfordVan 0:b9164b348919 210 {
MrBedfordVan 0:b9164b348919 211 uint32_t row_data = 0x01 << (matrixMap.rowStart + strobeRow);
MrBedfordVan 0:b9164b348919 212 uint32_t col_data = 0;
MrBedfordVan 0:b9164b348919 213
MrBedfordVan 0:b9164b348919 214 // Calculate the bitpattern to write.
MrBedfordVan 0:b9164b348919 215 for (int i = 0; i < matrixMap.columns; i++)
MrBedfordVan 0:b9164b348919 216 {
MrBedfordVan 0:b9164b348919 217 int index = (i * matrixMap.rows) + strobeRow;
MrBedfordVan 0:b9164b348919 218
MrBedfordVan 0:b9164b348919 219 int x = matrixMap.map[index].x;
MrBedfordVan 0:b9164b348919 220 int y = matrixMap.map[index].y;
MrBedfordVan 0:b9164b348919 221 int t = x;
MrBedfordVan 0:b9164b348919 222
MrBedfordVan 0:b9164b348919 223 if(rotation == MICROBIT_DISPLAY_ROTATION_90)
MrBedfordVan 0:b9164b348919 224 {
MrBedfordVan 0:b9164b348919 225 x = width - 1 - y;
MrBedfordVan 0:b9164b348919 226 y = t;
MrBedfordVan 0:b9164b348919 227 }
MrBedfordVan 0:b9164b348919 228
MrBedfordVan 0:b9164b348919 229 if(rotation == MICROBIT_DISPLAY_ROTATION_180)
MrBedfordVan 0:b9164b348919 230 {
MrBedfordVan 0:b9164b348919 231 x = width - 1 - x;
MrBedfordVan 0:b9164b348919 232 y = height - 1 - y;
MrBedfordVan 0:b9164b348919 233 }
MrBedfordVan 0:b9164b348919 234
MrBedfordVan 0:b9164b348919 235 if(rotation == MICROBIT_DISPLAY_ROTATION_270)
MrBedfordVan 0:b9164b348919 236 {
MrBedfordVan 0:b9164b348919 237 x = y;
MrBedfordVan 0:b9164b348919 238 y = height - 1 - t;
MrBedfordVan 0:b9164b348919 239 }
MrBedfordVan 0:b9164b348919 240
MrBedfordVan 0:b9164b348919 241 if(min(image.getBitmap()[y * (width * 2) + x],brightness) & greyscaleBitMsk)
MrBedfordVan 0:b9164b348919 242 col_data |= (1 << i);
MrBedfordVan 0:b9164b348919 243 }
MrBedfordVan 0:b9164b348919 244
MrBedfordVan 0:b9164b348919 245 // Invert column bits (as we're sinking not sourcing power), and mask off any unused bits.
MrBedfordVan 0:b9164b348919 246 col_data = ~col_data << matrixMap.columnStart & col_mask;
MrBedfordVan 0:b9164b348919 247
MrBedfordVan 0:b9164b348919 248 // Write the new bit pattern
MrBedfordVan 0:b9164b348919 249 *LEDMatrix = col_data | row_data;
MrBedfordVan 0:b9164b348919 250
MrBedfordVan 0:b9164b348919 251 if(timingCount > MICROBIT_DISPLAY_GREYSCALE_BIT_DEPTH-1)
MrBedfordVan 0:b9164b348919 252 return;
MrBedfordVan 0:b9164b348919 253
MrBedfordVan 0:b9164b348919 254 greyscaleBitMsk <<= 1;
MrBedfordVan 0:b9164b348919 255
MrBedfordVan 0:b9164b348919 256 if(timingCount < 3)
MrBedfordVan 0:b9164b348919 257 {
MrBedfordVan 0:b9164b348919 258 wait_us(greyScaleTimings[timingCount++]);
MrBedfordVan 0:b9164b348919 259 renderGreyscale();
MrBedfordVan 0:b9164b348919 260 return;
MrBedfordVan 0:b9164b348919 261 }
MrBedfordVan 0:b9164b348919 262 renderTimer.attach_us(this,&MicroBitDisplay::renderGreyscale, greyScaleTimings[timingCount++]);
MrBedfordVan 0:b9164b348919 263 }
MrBedfordVan 0:b9164b348919 264
MrBedfordVan 0:b9164b348919 265 /**
MrBedfordVan 0:b9164b348919 266 * Periodic callback, that we use to perform any animations we have running.
MrBedfordVan 0:b9164b348919 267 */
MrBedfordVan 0:b9164b348919 268 void
MrBedfordVan 0:b9164b348919 269 MicroBitDisplay::animationUpdate()
MrBedfordVan 0:b9164b348919 270 {
MrBedfordVan 0:b9164b348919 271 // If there's no ongoing animation, then nothing to do.
MrBedfordVan 0:b9164b348919 272 if (animationMode == ANIMATION_MODE_NONE)
MrBedfordVan 0:b9164b348919 273 return;
MrBedfordVan 0:b9164b348919 274
MrBedfordVan 0:b9164b348919 275 animationTick += system_timer_get_period();
MrBedfordVan 0:b9164b348919 276
MrBedfordVan 0:b9164b348919 277 if(animationTick >= animationDelay)
MrBedfordVan 0:b9164b348919 278 {
MrBedfordVan 0:b9164b348919 279 animationTick = 0;
MrBedfordVan 0:b9164b348919 280
MrBedfordVan 0:b9164b348919 281 if (animationMode == ANIMATION_MODE_SCROLL_TEXT)
MrBedfordVan 0:b9164b348919 282 this->updateScrollText();
MrBedfordVan 0:b9164b348919 283
MrBedfordVan 0:b9164b348919 284 if (animationMode == ANIMATION_MODE_PRINT_TEXT)
MrBedfordVan 0:b9164b348919 285 this->updatePrintText();
MrBedfordVan 0:b9164b348919 286
MrBedfordVan 0:b9164b348919 287 if (animationMode == ANIMATION_MODE_SCROLL_IMAGE)
MrBedfordVan 0:b9164b348919 288 this->updateScrollImage();
MrBedfordVan 0:b9164b348919 289
MrBedfordVan 0:b9164b348919 290 if (animationMode == ANIMATION_MODE_ANIMATE_IMAGE || animationMode == ANIMATION_MODE_ANIMATE_IMAGE_WITH_CLEAR)
MrBedfordVan 0:b9164b348919 291 this->updateAnimateImage();
MrBedfordVan 0:b9164b348919 292
MrBedfordVan 0:b9164b348919 293 if(animationMode == ANIMATION_MODE_PRINT_CHARACTER)
MrBedfordVan 0:b9164b348919 294 {
MrBedfordVan 0:b9164b348919 295 animationMode = ANIMATION_MODE_NONE;
MrBedfordVan 0:b9164b348919 296 this->sendAnimationCompleteEvent();
MrBedfordVan 0:b9164b348919 297 }
MrBedfordVan 0:b9164b348919 298 }
MrBedfordVan 0:b9164b348919 299 }
MrBedfordVan 0:b9164b348919 300
MrBedfordVan 0:b9164b348919 301 /**
MrBedfordVan 0:b9164b348919 302 * Broadcasts an event onto the defult EventModel indicating that the
MrBedfordVan 0:b9164b348919 303 * current animation has completed.
MrBedfordVan 0:b9164b348919 304 */
MrBedfordVan 0:b9164b348919 305 void MicroBitDisplay::sendAnimationCompleteEvent()
MrBedfordVan 0:b9164b348919 306 {
MrBedfordVan 0:b9164b348919 307 // Signal that we've completed an animation.
MrBedfordVan 0:b9164b348919 308 MicroBitEvent(id,MICROBIT_DISPLAY_EVT_ANIMATION_COMPLETE);
MrBedfordVan 0:b9164b348919 309
MrBedfordVan 0:b9164b348919 310 // Wake up a fiber that was blocked on the animation (if any).
MrBedfordVan 0:b9164b348919 311 MicroBitEvent(MICROBIT_ID_NOTIFY_ONE, MICROBIT_DISPLAY_EVT_FREE);
MrBedfordVan 0:b9164b348919 312 }
MrBedfordVan 0:b9164b348919 313
MrBedfordVan 0:b9164b348919 314 /**
MrBedfordVan 0:b9164b348919 315 * Internal scrollText update method.
MrBedfordVan 0:b9164b348919 316 * Shift the screen image by one pixel to the left. If necessary, paste in the next char.
MrBedfordVan 0:b9164b348919 317 */
MrBedfordVan 0:b9164b348919 318 void MicroBitDisplay::updateScrollText()
MrBedfordVan 0:b9164b348919 319 {
MrBedfordVan 0:b9164b348919 320 image.shiftLeft(1);
MrBedfordVan 0:b9164b348919 321 scrollingPosition++;
MrBedfordVan 0:b9164b348919 322
MrBedfordVan 0:b9164b348919 323 if (scrollingPosition == width + MICROBIT_DISPLAY_SPACING)
MrBedfordVan 0:b9164b348919 324 {
MrBedfordVan 0:b9164b348919 325 scrollingPosition = 0;
MrBedfordVan 0:b9164b348919 326
MrBedfordVan 0:b9164b348919 327 image.print(scrollingChar < scrollingText.length() ? scrollingText.charAt(scrollingChar) : ' ',width,0);
MrBedfordVan 0:b9164b348919 328
MrBedfordVan 0:b9164b348919 329 if (scrollingChar > scrollingText.length())
MrBedfordVan 0:b9164b348919 330 {
MrBedfordVan 0:b9164b348919 331 animationMode = ANIMATION_MODE_NONE;
MrBedfordVan 0:b9164b348919 332 this->sendAnimationCompleteEvent();
MrBedfordVan 0:b9164b348919 333 return;
MrBedfordVan 0:b9164b348919 334 }
MrBedfordVan 0:b9164b348919 335 scrollingChar++;
MrBedfordVan 0:b9164b348919 336 }
MrBedfordVan 0:b9164b348919 337 }
MrBedfordVan 0:b9164b348919 338
MrBedfordVan 0:b9164b348919 339 /**
MrBedfordVan 0:b9164b348919 340 * Internal printText update method.
MrBedfordVan 0:b9164b348919 341 * Paste the next character in the string.
MrBedfordVan 0:b9164b348919 342 */
MrBedfordVan 0:b9164b348919 343 void MicroBitDisplay::updatePrintText()
MrBedfordVan 0:b9164b348919 344 {
MrBedfordVan 0:b9164b348919 345 image.print(printingChar < printingText.length() ? printingText.charAt(printingChar) : ' ',0,0);
MrBedfordVan 0:b9164b348919 346
MrBedfordVan 0:b9164b348919 347 if (printingChar > printingText.length())
MrBedfordVan 0:b9164b348919 348 {
MrBedfordVan 0:b9164b348919 349 animationMode = ANIMATION_MODE_NONE;
MrBedfordVan 0:b9164b348919 350
MrBedfordVan 0:b9164b348919 351 this->sendAnimationCompleteEvent();
MrBedfordVan 0:b9164b348919 352 return;
MrBedfordVan 0:b9164b348919 353 }
MrBedfordVan 0:b9164b348919 354
MrBedfordVan 0:b9164b348919 355 printingChar++;
MrBedfordVan 0:b9164b348919 356 }
MrBedfordVan 0:b9164b348919 357
MrBedfordVan 0:b9164b348919 358 /**
MrBedfordVan 0:b9164b348919 359 * Internal scrollImage update method.
MrBedfordVan 0:b9164b348919 360 * Paste the stored bitmap at the appropriate point.
MrBedfordVan 0:b9164b348919 361 */
MrBedfordVan 0:b9164b348919 362 void MicroBitDisplay::updateScrollImage()
MrBedfordVan 0:b9164b348919 363 {
MrBedfordVan 0:b9164b348919 364 image.clear();
MrBedfordVan 0:b9164b348919 365
MrBedfordVan 0:b9164b348919 366 if (((image.paste(scrollingImage, scrollingImagePosition, 0, 0) == 0) && scrollingImageRendered) || scrollingImageStride == 0)
MrBedfordVan 0:b9164b348919 367 {
MrBedfordVan 0:b9164b348919 368 animationMode = ANIMATION_MODE_NONE;
MrBedfordVan 0:b9164b348919 369 this->sendAnimationCompleteEvent();
MrBedfordVan 0:b9164b348919 370
MrBedfordVan 0:b9164b348919 371 return;
MrBedfordVan 0:b9164b348919 372 }
MrBedfordVan 0:b9164b348919 373
MrBedfordVan 0:b9164b348919 374 scrollingImagePosition += scrollingImageStride;
MrBedfordVan 0:b9164b348919 375 scrollingImageRendered = true;
MrBedfordVan 0:b9164b348919 376 }
MrBedfordVan 0:b9164b348919 377
MrBedfordVan 0:b9164b348919 378 /**
MrBedfordVan 0:b9164b348919 379 * Internal animateImage update method.
MrBedfordVan 0:b9164b348919 380 * Paste the stored bitmap at the appropriate point and stop on the last frame.
MrBedfordVan 0:b9164b348919 381 */
MrBedfordVan 0:b9164b348919 382 void MicroBitDisplay::updateAnimateImage()
MrBedfordVan 0:b9164b348919 383 {
MrBedfordVan 0:b9164b348919 384 //wait until we have rendered the last position to give a continuous animation.
MrBedfordVan 0:b9164b348919 385 if (scrollingImagePosition <= -scrollingImage.getWidth() + (MICROBIT_DISPLAY_WIDTH + scrollingImageStride) && scrollingImageRendered)
MrBedfordVan 0:b9164b348919 386 {
MrBedfordVan 0:b9164b348919 387 if (animationMode == ANIMATION_MODE_ANIMATE_IMAGE_WITH_CLEAR)
MrBedfordVan 0:b9164b348919 388 this->clear();
MrBedfordVan 0:b9164b348919 389
MrBedfordVan 0:b9164b348919 390 animationMode = ANIMATION_MODE_NONE;
MrBedfordVan 0:b9164b348919 391
MrBedfordVan 0:b9164b348919 392 this->sendAnimationCompleteEvent();
MrBedfordVan 0:b9164b348919 393 return;
MrBedfordVan 0:b9164b348919 394 }
MrBedfordVan 0:b9164b348919 395
MrBedfordVan 0:b9164b348919 396 if(scrollingImagePosition > 0)
MrBedfordVan 0:b9164b348919 397 image.shiftLeft(-scrollingImageStride);
MrBedfordVan 0:b9164b348919 398
MrBedfordVan 0:b9164b348919 399 image.paste(scrollingImage, scrollingImagePosition, 0, 0);
MrBedfordVan 0:b9164b348919 400
MrBedfordVan 0:b9164b348919 401 if(scrollingImageStride == 0)
MrBedfordVan 0:b9164b348919 402 {
MrBedfordVan 0:b9164b348919 403 animationMode = ANIMATION_MODE_NONE;
MrBedfordVan 0:b9164b348919 404 this->sendAnimationCompleteEvent();
MrBedfordVan 0:b9164b348919 405 }
MrBedfordVan 0:b9164b348919 406
MrBedfordVan 0:b9164b348919 407 scrollingImageRendered = true;
MrBedfordVan 0:b9164b348919 408
MrBedfordVan 0:b9164b348919 409 scrollingImagePosition += scrollingImageStride;
MrBedfordVan 0:b9164b348919 410 }
MrBedfordVan 0:b9164b348919 411
MrBedfordVan 0:b9164b348919 412 /**
MrBedfordVan 0:b9164b348919 413 * Resets the current given animation.
MrBedfordVan 0:b9164b348919 414 */
MrBedfordVan 0:b9164b348919 415 void MicroBitDisplay::stopAnimation()
MrBedfordVan 0:b9164b348919 416 {
MrBedfordVan 0:b9164b348919 417 // Reset any ongoing animation.
MrBedfordVan 0:b9164b348919 418 if (animationMode != ANIMATION_MODE_NONE)
MrBedfordVan 0:b9164b348919 419 {
MrBedfordVan 0:b9164b348919 420 animationMode = ANIMATION_MODE_NONE;
MrBedfordVan 0:b9164b348919 421
MrBedfordVan 0:b9164b348919 422 // Indicate that we've completed an animation.
MrBedfordVan 0:b9164b348919 423 MicroBitEvent(id,MICROBIT_DISPLAY_EVT_ANIMATION_COMPLETE);
MrBedfordVan 0:b9164b348919 424
MrBedfordVan 0:b9164b348919 425 // Wake up aall fibers that may blocked on the animation (if any).
MrBedfordVan 0:b9164b348919 426 MicroBitEvent(MICROBIT_ID_NOTIFY, MICROBIT_DISPLAY_EVT_FREE);
MrBedfordVan 0:b9164b348919 427 }
MrBedfordVan 0:b9164b348919 428
MrBedfordVan 0:b9164b348919 429 // Clear the display and setup the animation timers.
MrBedfordVan 0:b9164b348919 430 this->image.clear();
MrBedfordVan 0:b9164b348919 431 }
MrBedfordVan 0:b9164b348919 432
MrBedfordVan 0:b9164b348919 433 /**
MrBedfordVan 0:b9164b348919 434 * Blocks the current fiber until the display is available (i.e. does not effect is being displayed).
MrBedfordVan 0:b9164b348919 435 * Animations are queued until their time to display.
MrBedfordVan 0:b9164b348919 436 */
MrBedfordVan 0:b9164b348919 437 void MicroBitDisplay::waitForFreeDisplay()
MrBedfordVan 0:b9164b348919 438 {
MrBedfordVan 0:b9164b348919 439 // If there's an ongoing animation, wait for our turn to display.
MrBedfordVan 0:b9164b348919 440 if (animationMode != ANIMATION_MODE_NONE && animationMode != ANIMATION_MODE_STOPPED)
MrBedfordVan 0:b9164b348919 441 fiber_wait_for_event(MICROBIT_ID_NOTIFY, MICROBIT_DISPLAY_EVT_FREE);
MrBedfordVan 0:b9164b348919 442 }
MrBedfordVan 0:b9164b348919 443
MrBedfordVan 0:b9164b348919 444 /**
MrBedfordVan 0:b9164b348919 445 * Blocks the current fiber until the current animation has finished.
MrBedfordVan 0:b9164b348919 446 * If the scheduler is not running, this call will essentially perform a spinning wait.
MrBedfordVan 0:b9164b348919 447 */
MrBedfordVan 0:b9164b348919 448 void MicroBitDisplay::fiberWait()
MrBedfordVan 0:b9164b348919 449 {
MrBedfordVan 0:b9164b348919 450 if (fiber_wait_for_event(MICROBIT_ID_DISPLAY, MICROBIT_DISPLAY_EVT_ANIMATION_COMPLETE) == MICROBIT_NOT_SUPPORTED)
MrBedfordVan 0:b9164b348919 451 while(animationMode != ANIMATION_MODE_NONE && animationMode != ANIMATION_MODE_STOPPED)
MrBedfordVan 0:b9164b348919 452 __WFE();
MrBedfordVan 0:b9164b348919 453 }
MrBedfordVan 0:b9164b348919 454
MrBedfordVan 0:b9164b348919 455 /**
MrBedfordVan 0:b9164b348919 456 * Prints the given character to the display, if it is not in use.
MrBedfordVan 0:b9164b348919 457 *
MrBedfordVan 0:b9164b348919 458 * @param c The character to display.
MrBedfordVan 0:b9164b348919 459 *
MrBedfordVan 0:b9164b348919 460 * @param delay Optional parameter - the time for which to show the character. Zero displays the character forever,
MrBedfordVan 0:b9164b348919 461 * or until the Displays next use.
MrBedfordVan 0:b9164b348919 462 *
MrBedfordVan 0:b9164b348919 463 * @return MICROBIT_OK, MICROBIT_BUSY is the screen is in use, or MICROBIT_INVALID_PARAMETER.
MrBedfordVan 0:b9164b348919 464 *
MrBedfordVan 0:b9164b348919 465 * @code
MrBedfordVan 0:b9164b348919 466 * display.printAsync('p');
MrBedfordVan 0:b9164b348919 467 * display.printAsync('p',100);
MrBedfordVan 0:b9164b348919 468 * @endcode
MrBedfordVan 0:b9164b348919 469 */
MrBedfordVan 0:b9164b348919 470 int MicroBitDisplay::printCharAsync(char c, int delay)
MrBedfordVan 0:b9164b348919 471 {
MrBedfordVan 0:b9164b348919 472 //sanitise this value
MrBedfordVan 0:b9164b348919 473 if(delay < 0)
MrBedfordVan 0:b9164b348919 474 return MICROBIT_INVALID_PARAMETER;
MrBedfordVan 0:b9164b348919 475
MrBedfordVan 0:b9164b348919 476 // If the display is free, it's our turn to display.
MrBedfordVan 0:b9164b348919 477 if (animationMode == ANIMATION_MODE_NONE || animationMode == ANIMATION_MODE_STOPPED)
MrBedfordVan 0:b9164b348919 478 {
MrBedfordVan 0:b9164b348919 479 image.print(c, 0, 0);
MrBedfordVan 0:b9164b348919 480
MrBedfordVan 0:b9164b348919 481 if (delay > 0)
MrBedfordVan 0:b9164b348919 482 {
MrBedfordVan 0:b9164b348919 483 animationDelay = delay;
MrBedfordVan 0:b9164b348919 484 animationTick = 0;
MrBedfordVan 0:b9164b348919 485 animationMode = ANIMATION_MODE_PRINT_CHARACTER;
MrBedfordVan 0:b9164b348919 486 }
MrBedfordVan 0:b9164b348919 487 }
MrBedfordVan 0:b9164b348919 488 else
MrBedfordVan 0:b9164b348919 489 {
MrBedfordVan 0:b9164b348919 490 return MICROBIT_BUSY;
MrBedfordVan 0:b9164b348919 491 }
MrBedfordVan 0:b9164b348919 492
MrBedfordVan 0:b9164b348919 493 return MICROBIT_OK;
MrBedfordVan 0:b9164b348919 494 }
MrBedfordVan 0:b9164b348919 495
MrBedfordVan 0:b9164b348919 496 /**
MrBedfordVan 0:b9164b348919 497 * Prints the given ManagedString to the display, one character at a time.
MrBedfordVan 0:b9164b348919 498 * Returns immediately, and executes the animation asynchronously.
MrBedfordVan 0:b9164b348919 499 *
MrBedfordVan 0:b9164b348919 500 * @param s The string to display.
MrBedfordVan 0:b9164b348919 501 *
MrBedfordVan 0:b9164b348919 502 * @param delay The time to delay between characters, in milliseconds. Must be > 0.
MrBedfordVan 0:b9164b348919 503 * Defaults to: MICROBIT_DEFAULT_PRINT_SPEED.
MrBedfordVan 0:b9164b348919 504 *
MrBedfordVan 0:b9164b348919 505 * @return MICROBIT_OK, or MICROBIT_INVALID_PARAMETER.
MrBedfordVan 0:b9164b348919 506 *
MrBedfordVan 0:b9164b348919 507 * @code
MrBedfordVan 0:b9164b348919 508 * display.printAsync("abc123",400);
MrBedfordVan 0:b9164b348919 509 * @endcode
MrBedfordVan 0:b9164b348919 510 */
MrBedfordVan 0:b9164b348919 511 int MicroBitDisplay::printAsync(ManagedString s, int delay)
MrBedfordVan 0:b9164b348919 512 {
MrBedfordVan 0:b9164b348919 513 if (s.length() == 1)
MrBedfordVan 0:b9164b348919 514 return printCharAsync(s.charAt(0));
MrBedfordVan 0:b9164b348919 515
MrBedfordVan 0:b9164b348919 516 //sanitise this value
MrBedfordVan 0:b9164b348919 517 if (delay <= 0 )
MrBedfordVan 0:b9164b348919 518 return MICROBIT_INVALID_PARAMETER;
MrBedfordVan 0:b9164b348919 519
MrBedfordVan 0:b9164b348919 520 if (animationMode == ANIMATION_MODE_NONE || animationMode == ANIMATION_MODE_STOPPED)
MrBedfordVan 0:b9164b348919 521 {
MrBedfordVan 0:b9164b348919 522 printingChar = 0;
MrBedfordVan 0:b9164b348919 523 printingText = s;
MrBedfordVan 0:b9164b348919 524 animationDelay = delay;
MrBedfordVan 0:b9164b348919 525 animationTick = 0;
MrBedfordVan 0:b9164b348919 526
MrBedfordVan 0:b9164b348919 527 animationMode = ANIMATION_MODE_PRINT_TEXT;
MrBedfordVan 0:b9164b348919 528 }
MrBedfordVan 0:b9164b348919 529 else
MrBedfordVan 0:b9164b348919 530 {
MrBedfordVan 0:b9164b348919 531 return MICROBIT_BUSY;
MrBedfordVan 0:b9164b348919 532 }
MrBedfordVan 0:b9164b348919 533
MrBedfordVan 0:b9164b348919 534 return MICROBIT_OK;
MrBedfordVan 0:b9164b348919 535 }
MrBedfordVan 0:b9164b348919 536
MrBedfordVan 0:b9164b348919 537 /**
MrBedfordVan 0:b9164b348919 538 * Prints the given image to the display, if the display is not in use.
MrBedfordVan 0:b9164b348919 539 * Returns immediately, and executes the animation asynchronously.
MrBedfordVan 0:b9164b348919 540 *
MrBedfordVan 0:b9164b348919 541 * @param i The image to display.
MrBedfordVan 0:b9164b348919 542 *
MrBedfordVan 0:b9164b348919 543 * @param x The horizontal position on the screen to display the image. Defaults to 0.
MrBedfordVan 0:b9164b348919 544 *
MrBedfordVan 0:b9164b348919 545 * @param y The vertical position on the screen to display the image. Defaults to 0.
MrBedfordVan 0:b9164b348919 546 *
MrBedfordVan 0:b9164b348919 547 * @param alpha Treats the brightness level '0' as transparent. Defaults to 0.
MrBedfordVan 0:b9164b348919 548 *
MrBedfordVan 0:b9164b348919 549 * @param delay The time to delay between characters, in milliseconds. Defaults to 0.
MrBedfordVan 0:b9164b348919 550 *
MrBedfordVan 0:b9164b348919 551 * @code
MrBedfordVan 0:b9164b348919 552 * MicrobitImage i("1,1,1,1,1\n1,1,1,1,1\n");
MrBedfordVan 0:b9164b348919 553 * display.print(i,400);
MrBedfordVan 0:b9164b348919 554 * @endcode
MrBedfordVan 0:b9164b348919 555 */
MrBedfordVan 0:b9164b348919 556 int MicroBitDisplay::printAsync(MicroBitImage i, int x, int y, int alpha, int delay)
MrBedfordVan 0:b9164b348919 557 {
MrBedfordVan 0:b9164b348919 558 if(delay < 0)
MrBedfordVan 0:b9164b348919 559 return MICROBIT_INVALID_PARAMETER;
MrBedfordVan 0:b9164b348919 560
MrBedfordVan 0:b9164b348919 561 if (animationMode == ANIMATION_MODE_NONE || animationMode == ANIMATION_MODE_STOPPED)
MrBedfordVan 0:b9164b348919 562 {
MrBedfordVan 0:b9164b348919 563 image.paste(i, x, y, alpha);
MrBedfordVan 0:b9164b348919 564
MrBedfordVan 0:b9164b348919 565 if(delay > 0)
MrBedfordVan 0:b9164b348919 566 {
MrBedfordVan 0:b9164b348919 567 animationDelay = delay;
MrBedfordVan 0:b9164b348919 568 animationTick = 0;
MrBedfordVan 0:b9164b348919 569 animationMode = ANIMATION_MODE_PRINT_CHARACTER;
MrBedfordVan 0:b9164b348919 570 }
MrBedfordVan 0:b9164b348919 571 }
MrBedfordVan 0:b9164b348919 572 else
MrBedfordVan 0:b9164b348919 573 {
MrBedfordVan 0:b9164b348919 574 return MICROBIT_BUSY;
MrBedfordVan 0:b9164b348919 575 }
MrBedfordVan 0:b9164b348919 576
MrBedfordVan 0:b9164b348919 577 return MICROBIT_OK;
MrBedfordVan 0:b9164b348919 578 }
MrBedfordVan 0:b9164b348919 579
MrBedfordVan 0:b9164b348919 580 /**
MrBedfordVan 0:b9164b348919 581 * Prints the given character to the display.
MrBedfordVan 0:b9164b348919 582 *
MrBedfordVan 0:b9164b348919 583 * @param c The character to display.
MrBedfordVan 0:b9164b348919 584 *
MrBedfordVan 0:b9164b348919 585 * @param delay Optional parameter - the time for which to show the character. Zero displays the character forever,
MrBedfordVan 0:b9164b348919 586 * or until the Displays next use.
MrBedfordVan 0:b9164b348919 587 *
MrBedfordVan 0:b9164b348919 588 * @return MICROBIT_OK, MICROBIT_CANCELLED or MICROBIT_INVALID_PARAMETER.
MrBedfordVan 0:b9164b348919 589 *
MrBedfordVan 0:b9164b348919 590 * @code
MrBedfordVan 0:b9164b348919 591 * display.printAsync('p');
MrBedfordVan 0:b9164b348919 592 * display.printAsync('p',100);
MrBedfordVan 0:b9164b348919 593 * @endcode
MrBedfordVan 0:b9164b348919 594 */
MrBedfordVan 0:b9164b348919 595 int MicroBitDisplay::printChar(char c, int delay)
MrBedfordVan 0:b9164b348919 596 {
MrBedfordVan 0:b9164b348919 597 if (delay < 0)
MrBedfordVan 0:b9164b348919 598 return MICROBIT_INVALID_PARAMETER;
MrBedfordVan 0:b9164b348919 599
MrBedfordVan 0:b9164b348919 600 // If there's an ongoing animation, wait for our turn to display.
MrBedfordVan 0:b9164b348919 601 this->waitForFreeDisplay();
MrBedfordVan 0:b9164b348919 602
MrBedfordVan 0:b9164b348919 603 // If the display is free, it's our turn to display.
MrBedfordVan 0:b9164b348919 604 // If someone called stopAnimation(), then we simply skip...
MrBedfordVan 0:b9164b348919 605 if (animationMode == ANIMATION_MODE_NONE)
MrBedfordVan 0:b9164b348919 606 {
MrBedfordVan 0:b9164b348919 607 this->printCharAsync(c, delay);
MrBedfordVan 0:b9164b348919 608
MrBedfordVan 0:b9164b348919 609 if (delay > 0)
MrBedfordVan 0:b9164b348919 610 fiberWait();
MrBedfordVan 0:b9164b348919 611 }
MrBedfordVan 0:b9164b348919 612 else
MrBedfordVan 0:b9164b348919 613 {
MrBedfordVan 0:b9164b348919 614 return MICROBIT_CANCELLED;
MrBedfordVan 0:b9164b348919 615 }
MrBedfordVan 0:b9164b348919 616
MrBedfordVan 0:b9164b348919 617 return MICROBIT_OK;
MrBedfordVan 0:b9164b348919 618 }
MrBedfordVan 0:b9164b348919 619
MrBedfordVan 0:b9164b348919 620 /**
MrBedfordVan 0:b9164b348919 621 * Prints the given string to the display, one character at a time.
MrBedfordVan 0:b9164b348919 622 *
MrBedfordVan 0:b9164b348919 623 * Blocks the calling thread until all the text has been displayed.
MrBedfordVan 0:b9164b348919 624 *
MrBedfordVan 0:b9164b348919 625 * @param s The string to display.
MrBedfordVan 0:b9164b348919 626 *
MrBedfordVan 0:b9164b348919 627 * @param delay The time to delay between characters, in milliseconds. Defaults
MrBedfordVan 0:b9164b348919 628 * to: MICROBIT_DEFAULT_PRINT_SPEED.
MrBedfordVan 0:b9164b348919 629 *
MrBedfordVan 0:b9164b348919 630 * @return MICROBIT_OK, MICROBIT_CANCELLED or MICROBIT_INVALID_PARAMETER.
MrBedfordVan 0:b9164b348919 631 *
MrBedfordVan 0:b9164b348919 632 * @code
MrBedfordVan 0:b9164b348919 633 * display.print("abc123",400);
MrBedfordVan 0:b9164b348919 634 * @endcode
MrBedfordVan 0:b9164b348919 635 */
MrBedfordVan 0:b9164b348919 636 int MicroBitDisplay::print(ManagedString s, int delay)
MrBedfordVan 0:b9164b348919 637 {
MrBedfordVan 0:b9164b348919 638 //sanitise this value
MrBedfordVan 0:b9164b348919 639 if(delay <= 0 )
MrBedfordVan 0:b9164b348919 640 return MICROBIT_INVALID_PARAMETER;
MrBedfordVan 0:b9164b348919 641
MrBedfordVan 0:b9164b348919 642 // If there's an ongoing animation, wait for our turn to display.
MrBedfordVan 0:b9164b348919 643 this->waitForFreeDisplay();
MrBedfordVan 0:b9164b348919 644
MrBedfordVan 0:b9164b348919 645 // If the display is free, it's our turn to display.
MrBedfordVan 0:b9164b348919 646 // If someone called stopAnimation(), then we simply skip...
MrBedfordVan 0:b9164b348919 647 if (animationMode == ANIMATION_MODE_NONE)
MrBedfordVan 0:b9164b348919 648 {
MrBedfordVan 0:b9164b348919 649 if (s.length() == 1)
MrBedfordVan 0:b9164b348919 650 {
MrBedfordVan 0:b9164b348919 651 return printCharAsync(s.charAt(0));
MrBedfordVan 0:b9164b348919 652 }
MrBedfordVan 0:b9164b348919 653 else
MrBedfordVan 0:b9164b348919 654 {
MrBedfordVan 0:b9164b348919 655 this->printAsync(s, delay);
MrBedfordVan 0:b9164b348919 656 fiberWait();
MrBedfordVan 0:b9164b348919 657 }
MrBedfordVan 0:b9164b348919 658 }
MrBedfordVan 0:b9164b348919 659 else
MrBedfordVan 0:b9164b348919 660 {
MrBedfordVan 0:b9164b348919 661 return MICROBIT_CANCELLED;
MrBedfordVan 0:b9164b348919 662 }
MrBedfordVan 0:b9164b348919 663
MrBedfordVan 0:b9164b348919 664 return MICROBIT_OK;
MrBedfordVan 0:b9164b348919 665 }
MrBedfordVan 0:b9164b348919 666
MrBedfordVan 0:b9164b348919 667 /**
MrBedfordVan 0:b9164b348919 668 * Prints the given image to the display.
MrBedfordVan 0:b9164b348919 669 * Blocks the calling thread until all the image has been displayed.
MrBedfordVan 0:b9164b348919 670 *
MrBedfordVan 0:b9164b348919 671 * @param i The image to display.
MrBedfordVan 0:b9164b348919 672 *
MrBedfordVan 0:b9164b348919 673 * @param x The horizontal position on the screen to display the image. Defaults to 0.
MrBedfordVan 0:b9164b348919 674 *
MrBedfordVan 0:b9164b348919 675 * @param y The vertical position on the screen to display the image. Defaults to 0.
MrBedfordVan 0:b9164b348919 676 *
MrBedfordVan 0:b9164b348919 677 * @param alpha Treats the brightness level '0' as transparent. Defaults to 0.
MrBedfordVan 0:b9164b348919 678 *
MrBedfordVan 0:b9164b348919 679 * @param delay The time to display the image for, or zero to show the image forever. Defaults to 0.
MrBedfordVan 0:b9164b348919 680 *
MrBedfordVan 0:b9164b348919 681 * @return MICROBIT_OK, MICROBIT_BUSY if the display is already in use, or MICROBIT_INVALID_PARAMETER.
MrBedfordVan 0:b9164b348919 682 *
MrBedfordVan 0:b9164b348919 683 * @code
MrBedfordVan 0:b9164b348919 684 * MicrobitImage i("1,1,1,1,1\n1,1,1,1,1\n");
MrBedfordVan 0:b9164b348919 685 * display.print(i,400);
MrBedfordVan 0:b9164b348919 686 * @endcode
MrBedfordVan 0:b9164b348919 687 */
MrBedfordVan 0:b9164b348919 688 int MicroBitDisplay::print(MicroBitImage i, int x, int y, int alpha, int delay)
MrBedfordVan 0:b9164b348919 689 {
MrBedfordVan 0:b9164b348919 690 if(delay < 0)
MrBedfordVan 0:b9164b348919 691 return MICROBIT_INVALID_PARAMETER;
MrBedfordVan 0:b9164b348919 692
MrBedfordVan 0:b9164b348919 693 // If there's an ongoing animation, wait for our turn to display.
MrBedfordVan 0:b9164b348919 694 this->waitForFreeDisplay();
MrBedfordVan 0:b9164b348919 695
MrBedfordVan 0:b9164b348919 696 // If the display is free, it's our turn to display.
MrBedfordVan 0:b9164b348919 697 // If someone called stopAnimation(), then we simply skip...
MrBedfordVan 0:b9164b348919 698 if (animationMode == ANIMATION_MODE_NONE)
MrBedfordVan 0:b9164b348919 699 {
MrBedfordVan 0:b9164b348919 700 this->printAsync(i, x, y, alpha, delay);
MrBedfordVan 0:b9164b348919 701
MrBedfordVan 0:b9164b348919 702 if (delay > 0)
MrBedfordVan 0:b9164b348919 703 fiberWait();
MrBedfordVan 0:b9164b348919 704 }
MrBedfordVan 0:b9164b348919 705 else
MrBedfordVan 0:b9164b348919 706 {
MrBedfordVan 0:b9164b348919 707 return MICROBIT_CANCELLED;
MrBedfordVan 0:b9164b348919 708 }
MrBedfordVan 0:b9164b348919 709
MrBedfordVan 0:b9164b348919 710 return MICROBIT_OK;
MrBedfordVan 0:b9164b348919 711 }
MrBedfordVan 0:b9164b348919 712
MrBedfordVan 0:b9164b348919 713 /**
MrBedfordVan 0:b9164b348919 714 * Scrolls the given string to the display, from right to left.
MrBedfordVan 0:b9164b348919 715 * Returns immediately, and executes the animation asynchronously.
MrBedfordVan 0:b9164b348919 716 *
MrBedfordVan 0:b9164b348919 717 * @param s The string to display.
MrBedfordVan 0:b9164b348919 718 *
MrBedfordVan 0:b9164b348919 719 * @param delay The time to delay between characters, in milliseconds. Defaults
MrBedfordVan 0:b9164b348919 720 * to: MICROBIT_DEFAULT_SCROLL_SPEED.
MrBedfordVan 0:b9164b348919 721 *
MrBedfordVan 0:b9164b348919 722 * @return MICROBIT_OK, MICROBIT_BUSY if the display is already in use, or MICROBIT_INVALID_PARAMETER.
MrBedfordVan 0:b9164b348919 723 *
MrBedfordVan 0:b9164b348919 724 * @code
MrBedfordVan 0:b9164b348919 725 * display.scrollAsync("abc123",100);
MrBedfordVan 0:b9164b348919 726 * @endcode
MrBedfordVan 0:b9164b348919 727 */
MrBedfordVan 0:b9164b348919 728 int MicroBitDisplay::scrollAsync(ManagedString s, int delay)
MrBedfordVan 0:b9164b348919 729 {
MrBedfordVan 0:b9164b348919 730 //sanitise this value
MrBedfordVan 0:b9164b348919 731 if(delay <= 0)
MrBedfordVan 0:b9164b348919 732 return MICROBIT_INVALID_PARAMETER;
MrBedfordVan 0:b9164b348919 733
MrBedfordVan 0:b9164b348919 734 // If the display is free, it's our turn to display.
MrBedfordVan 0:b9164b348919 735 if (animationMode == ANIMATION_MODE_NONE || animationMode == ANIMATION_MODE_STOPPED)
MrBedfordVan 0:b9164b348919 736 {
MrBedfordVan 0:b9164b348919 737 scrollingPosition = width-1;
MrBedfordVan 0:b9164b348919 738 scrollingChar = 0;
MrBedfordVan 0:b9164b348919 739 scrollingText = s;
MrBedfordVan 0:b9164b348919 740
MrBedfordVan 0:b9164b348919 741 animationDelay = delay;
MrBedfordVan 0:b9164b348919 742 animationTick = 0;
MrBedfordVan 0:b9164b348919 743 animationMode = ANIMATION_MODE_SCROLL_TEXT;
MrBedfordVan 0:b9164b348919 744 }
MrBedfordVan 0:b9164b348919 745 else
MrBedfordVan 0:b9164b348919 746 {
MrBedfordVan 0:b9164b348919 747 return MICROBIT_BUSY;
MrBedfordVan 0:b9164b348919 748 }
MrBedfordVan 0:b9164b348919 749
MrBedfordVan 0:b9164b348919 750 return MICROBIT_OK;
MrBedfordVan 0:b9164b348919 751 }
MrBedfordVan 0:b9164b348919 752
MrBedfordVan 0:b9164b348919 753 /**
MrBedfordVan 0:b9164b348919 754 * Scrolls the given image across the display, from right to left.
MrBedfordVan 0:b9164b348919 755 * Returns immediately, and executes the animation asynchronously.
MrBedfordVan 0:b9164b348919 756 *
MrBedfordVan 0:b9164b348919 757 * @param image The image to display.
MrBedfordVan 0:b9164b348919 758 *
MrBedfordVan 0:b9164b348919 759 * @param delay The time between updates, in milliseconds. Defaults
MrBedfordVan 0:b9164b348919 760 * to: MICROBIT_DEFAULT_SCROLL_SPEED.
MrBedfordVan 0:b9164b348919 761 *
MrBedfordVan 0:b9164b348919 762 * @param stride The number of pixels to shift by in each update. Defaults to MICROBIT_DEFAULT_SCROLL_STRIDE.
MrBedfordVan 0:b9164b348919 763 *
MrBedfordVan 0:b9164b348919 764 * @return MICROBIT_OK, MICROBIT_BUSY if the display is already in use, or MICROBIT_INVALID_PARAMETER.
MrBedfordVan 0:b9164b348919 765 *
MrBedfordVan 0:b9164b348919 766 * @code
MrBedfordVan 0:b9164b348919 767 * MicrobitImage i("1,1,1,1,1\n1,1,1,1,1\n");
MrBedfordVan 0:b9164b348919 768 * display.scrollAsync(i,100,1);
MrBedfordVan 0:b9164b348919 769 * @endcode
MrBedfordVan 0:b9164b348919 770 */
MrBedfordVan 0:b9164b348919 771 int MicroBitDisplay::scrollAsync(MicroBitImage image, int delay, int stride)
MrBedfordVan 0:b9164b348919 772 {
MrBedfordVan 0:b9164b348919 773 //sanitise the delay value
MrBedfordVan 0:b9164b348919 774 if(delay <= 0)
MrBedfordVan 0:b9164b348919 775 return MICROBIT_INVALID_PARAMETER;
MrBedfordVan 0:b9164b348919 776
MrBedfordVan 0:b9164b348919 777 // If the display is free, it's our turn to display.
MrBedfordVan 0:b9164b348919 778 if (animationMode == ANIMATION_MODE_NONE || animationMode == ANIMATION_MODE_STOPPED)
MrBedfordVan 0:b9164b348919 779 {
MrBedfordVan 0:b9164b348919 780 scrollingImagePosition = stride < 0 ? width : -image.getWidth();
MrBedfordVan 0:b9164b348919 781 scrollingImageStride = stride;
MrBedfordVan 0:b9164b348919 782 scrollingImage = image;
MrBedfordVan 0:b9164b348919 783 scrollingImageRendered = false;
MrBedfordVan 0:b9164b348919 784
MrBedfordVan 0:b9164b348919 785 animationDelay = stride == 0 ? 0 : delay;
MrBedfordVan 0:b9164b348919 786 animationTick = 0;
MrBedfordVan 0:b9164b348919 787 animationMode = ANIMATION_MODE_SCROLL_IMAGE;
MrBedfordVan 0:b9164b348919 788 }
MrBedfordVan 0:b9164b348919 789 else
MrBedfordVan 0:b9164b348919 790 {
MrBedfordVan 0:b9164b348919 791 return MICROBIT_BUSY;
MrBedfordVan 0:b9164b348919 792 }
MrBedfordVan 0:b9164b348919 793
MrBedfordVan 0:b9164b348919 794 return MICROBIT_OK;
MrBedfordVan 0:b9164b348919 795 }
MrBedfordVan 0:b9164b348919 796
MrBedfordVan 0:b9164b348919 797 /**
MrBedfordVan 0:b9164b348919 798 * Scrolls the given string across the display, from right to left.
MrBedfordVan 0:b9164b348919 799 * Blocks the calling thread until all text has been displayed.
MrBedfordVan 0:b9164b348919 800 *
MrBedfordVan 0:b9164b348919 801 * @param s The string to display.
MrBedfordVan 0:b9164b348919 802 *
MrBedfordVan 0:b9164b348919 803 * @param delay The time to delay between characters, in milliseconds. Defaults
MrBedfordVan 0:b9164b348919 804 * to: MICROBIT_DEFAULT_SCROLL_SPEED.
MrBedfordVan 0:b9164b348919 805 *
MrBedfordVan 0:b9164b348919 806 * @return MICROBIT_OK, MICROBIT_CANCELLED or MICROBIT_INVALID_PARAMETER.
MrBedfordVan 0:b9164b348919 807 *
MrBedfordVan 0:b9164b348919 808 * @code
MrBedfordVan 0:b9164b348919 809 * display.scroll("abc123",100);
MrBedfordVan 0:b9164b348919 810 * @endcode
MrBedfordVan 0:b9164b348919 811 */
MrBedfordVan 0:b9164b348919 812 int MicroBitDisplay::scroll(ManagedString s, int delay)
MrBedfordVan 0:b9164b348919 813 {
MrBedfordVan 0:b9164b348919 814 //sanitise this value
MrBedfordVan 0:b9164b348919 815 if(delay <= 0)
MrBedfordVan 0:b9164b348919 816 return MICROBIT_INVALID_PARAMETER;
MrBedfordVan 0:b9164b348919 817
MrBedfordVan 0:b9164b348919 818 // If there's an ongoing animation, wait for our turn to display.
MrBedfordVan 0:b9164b348919 819 this->waitForFreeDisplay();
MrBedfordVan 0:b9164b348919 820
MrBedfordVan 0:b9164b348919 821 // If the display is free, it's our turn to display.
MrBedfordVan 0:b9164b348919 822 // If someone called stopAnimation(), then we simply skip...
MrBedfordVan 0:b9164b348919 823 if (animationMode == ANIMATION_MODE_NONE)
MrBedfordVan 0:b9164b348919 824 {
MrBedfordVan 0:b9164b348919 825 // Start the effect.
MrBedfordVan 0:b9164b348919 826 this->scrollAsync(s, delay);
MrBedfordVan 0:b9164b348919 827
MrBedfordVan 0:b9164b348919 828 // Wait for completion.
MrBedfordVan 0:b9164b348919 829 fiberWait();
MrBedfordVan 0:b9164b348919 830 }
MrBedfordVan 0:b9164b348919 831 else
MrBedfordVan 0:b9164b348919 832 {
MrBedfordVan 0:b9164b348919 833 return MICROBIT_CANCELLED;
MrBedfordVan 0:b9164b348919 834 }
MrBedfordVan 0:b9164b348919 835
MrBedfordVan 0:b9164b348919 836 return MICROBIT_OK;
MrBedfordVan 0:b9164b348919 837 }
MrBedfordVan 0:b9164b348919 838
MrBedfordVan 0:b9164b348919 839 /**
MrBedfordVan 0:b9164b348919 840 * Scrolls the given image across the display, from right to left.
MrBedfordVan 0:b9164b348919 841 * Blocks the calling thread until all the text has been displayed.
MrBedfordVan 0:b9164b348919 842 *
MrBedfordVan 0:b9164b348919 843 * @param image The image to display.
MrBedfordVan 0:b9164b348919 844 *
MrBedfordVan 0:b9164b348919 845 * @param delay The time between updates, in milliseconds. Defaults
MrBedfordVan 0:b9164b348919 846 * to: MICROBIT_DEFAULT_SCROLL_SPEED.
MrBedfordVan 0:b9164b348919 847 *
MrBedfordVan 0:b9164b348919 848 * @param stride The number of pixels to shift by in each update. Defaults to MICROBIT_DEFAULT_SCROLL_STRIDE.
MrBedfordVan 0:b9164b348919 849 *
MrBedfordVan 0:b9164b348919 850 * @return MICROBIT_OK, MICROBIT_CANCELLED or MICROBIT_INVALID_PARAMETER.
MrBedfordVan 0:b9164b348919 851 *
MrBedfordVan 0:b9164b348919 852 * @code
MrBedfordVan 0:b9164b348919 853 * MicrobitImage i("1,1,1,1,1\n1,1,1,1,1\n");
MrBedfordVan 0:b9164b348919 854 * display.scroll(i,100,1);
MrBedfordVan 0:b9164b348919 855 * @endcode
MrBedfordVan 0:b9164b348919 856 */
MrBedfordVan 0:b9164b348919 857 int MicroBitDisplay::scroll(MicroBitImage image, int delay, int stride)
MrBedfordVan 0:b9164b348919 858 {
MrBedfordVan 0:b9164b348919 859 //sanitise the delay value
MrBedfordVan 0:b9164b348919 860 if(delay <= 0)
MrBedfordVan 0:b9164b348919 861 return MICROBIT_INVALID_PARAMETER;
MrBedfordVan 0:b9164b348919 862
MrBedfordVan 0:b9164b348919 863 // If there's an ongoing animation, wait for our turn to display.
MrBedfordVan 0:b9164b348919 864 this->waitForFreeDisplay();
MrBedfordVan 0:b9164b348919 865
MrBedfordVan 0:b9164b348919 866 // If the display is free, it's our turn to display.
MrBedfordVan 0:b9164b348919 867 // If someone called stopAnimation(), then we simply skip...
MrBedfordVan 0:b9164b348919 868 if (animationMode == ANIMATION_MODE_NONE)
MrBedfordVan 0:b9164b348919 869 {
MrBedfordVan 0:b9164b348919 870 // Start the effect.
MrBedfordVan 0:b9164b348919 871 this->scrollAsync(image, delay, stride);
MrBedfordVan 0:b9164b348919 872
MrBedfordVan 0:b9164b348919 873 // Wait for completion.
MrBedfordVan 0:b9164b348919 874 fiberWait();
MrBedfordVan 0:b9164b348919 875 }
MrBedfordVan 0:b9164b348919 876 else
MrBedfordVan 0:b9164b348919 877 {
MrBedfordVan 0:b9164b348919 878 return MICROBIT_CANCELLED;
MrBedfordVan 0:b9164b348919 879 }
MrBedfordVan 0:b9164b348919 880
MrBedfordVan 0:b9164b348919 881 return MICROBIT_OK;
MrBedfordVan 0:b9164b348919 882 }
MrBedfordVan 0:b9164b348919 883
MrBedfordVan 0:b9164b348919 884 /**
MrBedfordVan 0:b9164b348919 885 * "Animates" the current image across the display with a given stride, finishing on the last frame of the animation.
MrBedfordVan 0:b9164b348919 886 * Returns immediately.
MrBedfordVan 0:b9164b348919 887 *
MrBedfordVan 0:b9164b348919 888 * @param image The image to display.
MrBedfordVan 0:b9164b348919 889 *
MrBedfordVan 0:b9164b348919 890 * @param delay The time to delay between each update of the display, in milliseconds.
MrBedfordVan 0:b9164b348919 891 *
MrBedfordVan 0:b9164b348919 892 * @param stride The number of pixels to shift by in each update.
MrBedfordVan 0:b9164b348919 893 *
MrBedfordVan 0:b9164b348919 894 * @param startingPosition the starting position on the display for the animation
MrBedfordVan 0:b9164b348919 895 * to begin at. Defaults to MICROBIT_DISPLAY_ANIMATE_DEFAULT_POS.
MrBedfordVan 0:b9164b348919 896 *
MrBedfordVan 0:b9164b348919 897 * @param autoClear defines whether or not the display is automatically cleared once the animation is complete. By default, the display is cleared. Set this parameter to zero to disable the autoClear operation.
MrBedfordVan 0:b9164b348919 898 *
MrBedfordVan 0:b9164b348919 899 * @return MICROBIT_OK, MICROBIT_BUSY if the screen is in use, or MICROBIT_INVALID_PARAMETER.
MrBedfordVan 0:b9164b348919 900 *
MrBedfordVan 0:b9164b348919 901 * @code
MrBedfordVan 0:b9164b348919 902 * const int heart_w = 10;
MrBedfordVan 0:b9164b348919 903 * const int heart_h = 5;
MrBedfordVan 0:b9164b348919 904 * 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, };
MrBedfordVan 0:b9164b348919 905 *
MrBedfordVan 0:b9164b348919 906 * MicroBitImage i(heart_w,heart_h,heart);
MrBedfordVan 0:b9164b348919 907 * display.animateAsync(i,100,5);
MrBedfordVan 0:b9164b348919 908 * @endcode
MrBedfordVan 0:b9164b348919 909 */
MrBedfordVan 0:b9164b348919 910 int MicroBitDisplay::animateAsync(MicroBitImage image, int delay, int stride, int startingPosition, int autoClear)
MrBedfordVan 0:b9164b348919 911 {
MrBedfordVan 0:b9164b348919 912 //sanitise the delay value
MrBedfordVan 0:b9164b348919 913 if(delay <= 0)
MrBedfordVan 0:b9164b348919 914 return MICROBIT_INVALID_PARAMETER;
MrBedfordVan 0:b9164b348919 915
MrBedfordVan 0:b9164b348919 916 // If the display is free, we can display.
MrBedfordVan 0:b9164b348919 917 if (animationMode == ANIMATION_MODE_NONE || animationMode == ANIMATION_MODE_STOPPED)
MrBedfordVan 0:b9164b348919 918 {
MrBedfordVan 0:b9164b348919 919 // Assume right to left functionality, to align with scrollString()
MrBedfordVan 0:b9164b348919 920 stride = -stride;
MrBedfordVan 0:b9164b348919 921
MrBedfordVan 0:b9164b348919 922 //calculate starting position which is offset by the stride
MrBedfordVan 0:b9164b348919 923 scrollingImagePosition = (startingPosition == MICROBIT_DISPLAY_ANIMATE_DEFAULT_POS) ? MICROBIT_DISPLAY_WIDTH + stride : startingPosition;
MrBedfordVan 0:b9164b348919 924 scrollingImageStride = stride;
MrBedfordVan 0:b9164b348919 925 scrollingImage = image;
MrBedfordVan 0:b9164b348919 926 scrollingImageRendered = false;
MrBedfordVan 0:b9164b348919 927
MrBedfordVan 0:b9164b348919 928 animationDelay = stride == 0 ? 0 : delay;
MrBedfordVan 0:b9164b348919 929 animationTick = delay-1;
MrBedfordVan 0:b9164b348919 930 animationMode = autoClear ? ANIMATION_MODE_ANIMATE_IMAGE_WITH_CLEAR : ANIMATION_MODE_ANIMATE_IMAGE;
MrBedfordVan 0:b9164b348919 931 }
MrBedfordVan 0:b9164b348919 932 else
MrBedfordVan 0:b9164b348919 933 {
MrBedfordVan 0:b9164b348919 934 return MICROBIT_BUSY;
MrBedfordVan 0:b9164b348919 935 }
MrBedfordVan 0:b9164b348919 936
MrBedfordVan 0:b9164b348919 937 return MICROBIT_OK;
MrBedfordVan 0:b9164b348919 938 }
MrBedfordVan 0:b9164b348919 939
MrBedfordVan 0:b9164b348919 940 /**
MrBedfordVan 0:b9164b348919 941 * "Animates" the current image across the display with a given stride, finishing on the last frame of the animation.
MrBedfordVan 0:b9164b348919 942 * Blocks the calling thread until the animation is complete.
MrBedfordVan 0:b9164b348919 943 *
MrBedfordVan 0:b9164b348919 944 *
MrBedfordVan 0:b9164b348919 945 * @param delay The time to delay between each update of the display, in milliseconds.
MrBedfordVan 0:b9164b348919 946 *
MrBedfordVan 0:b9164b348919 947 * @param stride The number of pixels to shift by in each update.
MrBedfordVan 0:b9164b348919 948 *
MrBedfordVan 0:b9164b348919 949 * @param startingPosition the starting position on the display for the animation
MrBedfordVan 0:b9164b348919 950 * to begin at. Defaults to MICROBIT_DISPLAY_ANIMATE_DEFAULT_POS.
MrBedfordVan 0:b9164b348919 951 *
MrBedfordVan 0:b9164b348919 952 * @param autoClear defines whether or not the display is automatically cleared once the animation is complete. By default, the display is cleared. Set this parameter to zero to disable the autoClear operation.
MrBedfordVan 0:b9164b348919 953 *
MrBedfordVan 0:b9164b348919 954 * @return MICROBIT_OK, MICROBIT_CANCELLED or MICROBIT_INVALID_PARAMETER.
MrBedfordVan 0:b9164b348919 955 *
MrBedfordVan 0:b9164b348919 956 * @code
MrBedfordVan 0:b9164b348919 957 * const int heart_w = 10;
MrBedfordVan 0:b9164b348919 958 * const int heart_h = 5;
MrBedfordVan 0:b9164b348919 959 * 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, };
MrBedfordVan 0:b9164b348919 960 *
MrBedfordVan 0:b9164b348919 961 * MicroBitImage i(heart_w,heart_h,heart);
MrBedfordVan 0:b9164b348919 962 * display.animate(i,100,5);
MrBedfordVan 0:b9164b348919 963 * @endcode
MrBedfordVan 0:b9164b348919 964 */
MrBedfordVan 0:b9164b348919 965 int MicroBitDisplay::animate(MicroBitImage image, int delay, int stride, int startingPosition, int autoClear)
MrBedfordVan 0:b9164b348919 966 {
MrBedfordVan 0:b9164b348919 967 //sanitise the delay value
MrBedfordVan 0:b9164b348919 968 if(delay <= 0)
MrBedfordVan 0:b9164b348919 969 return MICROBIT_INVALID_PARAMETER;
MrBedfordVan 0:b9164b348919 970
MrBedfordVan 0:b9164b348919 971 // If there's an ongoing animation, wait for our turn to display.
MrBedfordVan 0:b9164b348919 972 this->waitForFreeDisplay();
MrBedfordVan 0:b9164b348919 973
MrBedfordVan 0:b9164b348919 974 // If the display is free, it's our turn to display.
MrBedfordVan 0:b9164b348919 975 // If someone called stopAnimation(), then we simply skip...
MrBedfordVan 0:b9164b348919 976 if (animationMode == ANIMATION_MODE_NONE)
MrBedfordVan 0:b9164b348919 977 {
MrBedfordVan 0:b9164b348919 978 // Start the effect.
MrBedfordVan 0:b9164b348919 979 this->animateAsync(image, delay, stride, startingPosition, autoClear);
MrBedfordVan 0:b9164b348919 980
MrBedfordVan 0:b9164b348919 981 // Wait for completion.
MrBedfordVan 0:b9164b348919 982 //TODO: Put this in when we merge tight-validation
MrBedfordVan 0:b9164b348919 983 //if (delay > 0)
MrBedfordVan 0:b9164b348919 984 fiberWait();
MrBedfordVan 0:b9164b348919 985 }
MrBedfordVan 0:b9164b348919 986 else
MrBedfordVan 0:b9164b348919 987 {
MrBedfordVan 0:b9164b348919 988 return MICROBIT_CANCELLED;
MrBedfordVan 0:b9164b348919 989 }
MrBedfordVan 0:b9164b348919 990
MrBedfordVan 0:b9164b348919 991 return MICROBIT_OK;
MrBedfordVan 0:b9164b348919 992 }
MrBedfordVan 0:b9164b348919 993
MrBedfordVan 0:b9164b348919 994
MrBedfordVan 0:b9164b348919 995 /**
MrBedfordVan 0:b9164b348919 996 * Configures the brightness of the display.
MrBedfordVan 0:b9164b348919 997 *
MrBedfordVan 0:b9164b348919 998 * @param b The brightness to set the brightness to, in the range 0 - 255.
MrBedfordVan 0:b9164b348919 999 *
MrBedfordVan 0:b9164b348919 1000 * @return MICROBIT_OK, or MICROBIT_INVALID_PARAMETER
MrBedfordVan 0:b9164b348919 1001 *
MrBedfordVan 0:b9164b348919 1002 * @code
MrBedfordVan 0:b9164b348919 1003 * display.setBrightness(255); //max brightness
MrBedfordVan 0:b9164b348919 1004 * @endcode
MrBedfordVan 0:b9164b348919 1005 */
MrBedfordVan 0:b9164b348919 1006 int MicroBitDisplay::setBrightness(int b)
MrBedfordVan 0:b9164b348919 1007 {
MrBedfordVan 0:b9164b348919 1008 //sanitise the brightness level
MrBedfordVan 0:b9164b348919 1009 if(b < 0 || b > 255)
MrBedfordVan 0:b9164b348919 1010 return MICROBIT_INVALID_PARAMETER;
MrBedfordVan 0:b9164b348919 1011
MrBedfordVan 0:b9164b348919 1012 this->brightness = b;
MrBedfordVan 0:b9164b348919 1013
MrBedfordVan 0:b9164b348919 1014 return MICROBIT_OK;
MrBedfordVan 0:b9164b348919 1015 }
MrBedfordVan 0:b9164b348919 1016
MrBedfordVan 0:b9164b348919 1017 /**
MrBedfordVan 0:b9164b348919 1018 * Configures the mode of the display.
MrBedfordVan 0:b9164b348919 1019 *
MrBedfordVan 0:b9164b348919 1020 * @param mode The mode to swap the display into. One of: DISPLAY_MODE_GREYSCALE,
MrBedfordVan 0:b9164b348919 1021 * DISPLAY_MODE_BLACK_AND_WHITE, DISPLAY_MODE_BLACK_AND_WHITE_LIGHT_SENSE
MrBedfordVan 0:b9164b348919 1022 *
MrBedfordVan 0:b9164b348919 1023 * @code
MrBedfordVan 0:b9164b348919 1024 * display.setDisplayMode(DISPLAY_MODE_GREYSCALE); //per pixel brightness
MrBedfordVan 0:b9164b348919 1025 * @endcode
MrBedfordVan 0:b9164b348919 1026 */
MrBedfordVan 0:b9164b348919 1027 void MicroBitDisplay::setDisplayMode(DisplayMode mode)
MrBedfordVan 0:b9164b348919 1028 {
MrBedfordVan 0:b9164b348919 1029 if(mode == DISPLAY_MODE_BLACK_AND_WHITE_LIGHT_SENSE)
MrBedfordVan 0:b9164b348919 1030 {
MrBedfordVan 0:b9164b348919 1031 //to reduce the artifacts on the display - increase the tick
MrBedfordVan 0:b9164b348919 1032 if(system_timer_get_period() != MICROBIT_LIGHT_SENSOR_TICK_PERIOD)
MrBedfordVan 0:b9164b348919 1033 system_timer_set_period(MICROBIT_LIGHT_SENSOR_TICK_PERIOD);
MrBedfordVan 0:b9164b348919 1034 }
MrBedfordVan 0:b9164b348919 1035
MrBedfordVan 0:b9164b348919 1036 if(this->mode == DISPLAY_MODE_BLACK_AND_WHITE_LIGHT_SENSE && mode != DISPLAY_MODE_BLACK_AND_WHITE_LIGHT_SENSE)
MrBedfordVan 0:b9164b348919 1037 {
MrBedfordVan 0:b9164b348919 1038 delete this->lightSensor;
MrBedfordVan 0:b9164b348919 1039
MrBedfordVan 0:b9164b348919 1040 this->lightSensor = NULL;
MrBedfordVan 0:b9164b348919 1041 }
MrBedfordVan 0:b9164b348919 1042
MrBedfordVan 0:b9164b348919 1043 this->mode = mode;
MrBedfordVan 0:b9164b348919 1044 }
MrBedfordVan 0:b9164b348919 1045
MrBedfordVan 0:b9164b348919 1046 /**
MrBedfordVan 0:b9164b348919 1047 * Retrieves the mode of the display.
MrBedfordVan 0:b9164b348919 1048 *
MrBedfordVan 0:b9164b348919 1049 * @return the current mode of the display
MrBedfordVan 0:b9164b348919 1050 */
MrBedfordVan 0:b9164b348919 1051 int MicroBitDisplay::getDisplayMode()
MrBedfordVan 0:b9164b348919 1052 {
MrBedfordVan 0:b9164b348919 1053 return this->mode;
MrBedfordVan 0:b9164b348919 1054 }
MrBedfordVan 0:b9164b348919 1055
MrBedfordVan 0:b9164b348919 1056 /**
MrBedfordVan 0:b9164b348919 1057 * Fetches the current brightness of this display.
MrBedfordVan 0:b9164b348919 1058 *
MrBedfordVan 0:b9164b348919 1059 * @return the brightness of this display, in the range 0..255.
MrBedfordVan 0:b9164b348919 1060 *
MrBedfordVan 0:b9164b348919 1061 * @code
MrBedfordVan 0:b9164b348919 1062 * display.getBrightness(); //the current brightness
MrBedfordVan 0:b9164b348919 1063 * @endcode
MrBedfordVan 0:b9164b348919 1064 */
MrBedfordVan 0:b9164b348919 1065 int MicroBitDisplay::getBrightness()
MrBedfordVan 0:b9164b348919 1066 {
MrBedfordVan 0:b9164b348919 1067 return this->brightness;
MrBedfordVan 0:b9164b348919 1068 }
MrBedfordVan 0:b9164b348919 1069
MrBedfordVan 0:b9164b348919 1070 /**
MrBedfordVan 0:b9164b348919 1071 * Rotates the display to the given position.
MrBedfordVan 0:b9164b348919 1072 *
MrBedfordVan 0:b9164b348919 1073 * Axis aligned values only.
MrBedfordVan 0:b9164b348919 1074 *
MrBedfordVan 0:b9164b348919 1075 * @code
MrBedfordVan 0:b9164b348919 1076 * display.rotateTo(MICROBIT_DISPLAY_ROTATION_180); //rotates 180 degrees from original orientation
MrBedfordVan 0:b9164b348919 1077 * @endcode
MrBedfordVan 0:b9164b348919 1078 */
MrBedfordVan 0:b9164b348919 1079 void MicroBitDisplay::rotateTo(DisplayRotation rotation)
MrBedfordVan 0:b9164b348919 1080 {
MrBedfordVan 0:b9164b348919 1081 this->rotation = rotation;
MrBedfordVan 0:b9164b348919 1082 }
MrBedfordVan 0:b9164b348919 1083
MrBedfordVan 0:b9164b348919 1084 /**
MrBedfordVan 0:b9164b348919 1085 * Enables or disables the display entirely, and releases the pins for other uses.
MrBedfordVan 0:b9164b348919 1086 *
MrBedfordVan 0:b9164b348919 1087 * @param enableDisplay true to enabled the display, or false to disable it.
MrBedfordVan 0:b9164b348919 1088 */
MrBedfordVan 0:b9164b348919 1089 void MicroBitDisplay::setEnable(bool enableDisplay)
MrBedfordVan 0:b9164b348919 1090 {
MrBedfordVan 0:b9164b348919 1091 // If we're already in the correct state, then there's nothing to do.
MrBedfordVan 0:b9164b348919 1092 if(((status & MICROBIT_COMPONENT_RUNNING) && enableDisplay) || (!(status & MICROBIT_COMPONENT_RUNNING) && !enableDisplay))
MrBedfordVan 0:b9164b348919 1093 return;
MrBedfordVan 0:b9164b348919 1094
MrBedfordVan 0:b9164b348919 1095 uint32_t rmask = 0;
MrBedfordVan 0:b9164b348919 1096 uint32_t cmask = 0;
MrBedfordVan 0:b9164b348919 1097
MrBedfordVan 0:b9164b348919 1098 for (int i = matrixMap.rowStart; i < matrixMap.rowStart + matrixMap.rows; i++)
MrBedfordVan 0:b9164b348919 1099 rmask |= 0x01 << i;
MrBedfordVan 0:b9164b348919 1100
MrBedfordVan 0:b9164b348919 1101 for (int i = matrixMap.columnStart; i < matrixMap.columnStart + matrixMap.columns; i++)
MrBedfordVan 0:b9164b348919 1102 cmask |= 0x01 << i;
MrBedfordVan 0:b9164b348919 1103
MrBedfordVan 0:b9164b348919 1104 if (enableDisplay)
MrBedfordVan 0:b9164b348919 1105 {
MrBedfordVan 0:b9164b348919 1106 PortOut p(Port0, rmask | cmask);
MrBedfordVan 0:b9164b348919 1107 status |= MICROBIT_COMPONENT_RUNNING;
MrBedfordVan 0:b9164b348919 1108 }
MrBedfordVan 0:b9164b348919 1109 else
MrBedfordVan 0:b9164b348919 1110 {
MrBedfordVan 0:b9164b348919 1111 PortIn p(Port0, rmask | cmask);
MrBedfordVan 0:b9164b348919 1112 p.mode(PullNone);
MrBedfordVan 0:b9164b348919 1113 status &= ~MICROBIT_COMPONENT_RUNNING;
MrBedfordVan 0:b9164b348919 1114 }
MrBedfordVan 0:b9164b348919 1115 }
MrBedfordVan 0:b9164b348919 1116
MrBedfordVan 0:b9164b348919 1117 /**
MrBedfordVan 0:b9164b348919 1118 * Enables the display, should only be called if the display is disabled.
MrBedfordVan 0:b9164b348919 1119 *
MrBedfordVan 0:b9164b348919 1120 * @code
MrBedfordVan 0:b9164b348919 1121 * display.enable(); //Enables the display mechanics
MrBedfordVan 0:b9164b348919 1122 * @endcode
MrBedfordVan 0:b9164b348919 1123 *
MrBedfordVan 0:b9164b348919 1124 * @note Only enables the display if the display is currently disabled.
MrBedfordVan 0:b9164b348919 1125 */
MrBedfordVan 0:b9164b348919 1126 void MicroBitDisplay::enable()
MrBedfordVan 0:b9164b348919 1127 {
MrBedfordVan 0:b9164b348919 1128 setEnable(true);
MrBedfordVan 0:b9164b348919 1129 }
MrBedfordVan 0:b9164b348919 1130
MrBedfordVan 0:b9164b348919 1131 /**
MrBedfordVan 0:b9164b348919 1132 * Disables the display, which releases control of the GPIO pins used by the display,
MrBedfordVan 0:b9164b348919 1133 * which are exposed on the edge connector.
MrBedfordVan 0:b9164b348919 1134 *
MrBedfordVan 0:b9164b348919 1135 * @code
MrBedfordVan 0:b9164b348919 1136 * display.disable(); //disables the display
MrBedfordVan 0:b9164b348919 1137 * @endcode
MrBedfordVan 0:b9164b348919 1138 *
MrBedfordVan 0:b9164b348919 1139 * @note Only disables the display if the display is currently enabled.
MrBedfordVan 0:b9164b348919 1140 */
MrBedfordVan 0:b9164b348919 1141 void MicroBitDisplay::disable()
MrBedfordVan 0:b9164b348919 1142 {
MrBedfordVan 0:b9164b348919 1143 setEnable(false);
MrBedfordVan 0:b9164b348919 1144 }
MrBedfordVan 0:b9164b348919 1145
MrBedfordVan 0:b9164b348919 1146 /**
MrBedfordVan 0:b9164b348919 1147 * Clears the display of any remaining pixels.
MrBedfordVan 0:b9164b348919 1148 *
MrBedfordVan 0:b9164b348919 1149 * `display.image.clear()` can also be used!
MrBedfordVan 0:b9164b348919 1150 *
MrBedfordVan 0:b9164b348919 1151 * @code
MrBedfordVan 0:b9164b348919 1152 * display.clear(); //clears the display
MrBedfordVan 0:b9164b348919 1153 * @endcode
MrBedfordVan 0:b9164b348919 1154 */
MrBedfordVan 0:b9164b348919 1155 void MicroBitDisplay::clear()
MrBedfordVan 0:b9164b348919 1156 {
MrBedfordVan 0:b9164b348919 1157 image.clear();
MrBedfordVan 0:b9164b348919 1158 }
MrBedfordVan 0:b9164b348919 1159
MrBedfordVan 0:b9164b348919 1160 /**
MrBedfordVan 0:b9164b348919 1161 * Updates the font that will be used for display operations.
MrBedfordVan 0:b9164b348919 1162 *
MrBedfordVan 0:b9164b348919 1163 * @param font the new font that will be used to render characters.
MrBedfordVan 0:b9164b348919 1164 *
MrBedfordVan 0:b9164b348919 1165 * @note DEPRECATED! Please use MicroBitFont::setSystemFont() instead.
MrBedfordVan 0:b9164b348919 1166 */
MrBedfordVan 0:b9164b348919 1167 void MicroBitDisplay::setFont(MicroBitFont font)
MrBedfordVan 0:b9164b348919 1168 {
MrBedfordVan 0:b9164b348919 1169 MicroBitFont::setSystemFont(font);
MrBedfordVan 0:b9164b348919 1170 }
MrBedfordVan 0:b9164b348919 1171
MrBedfordVan 0:b9164b348919 1172 /**
MrBedfordVan 0:b9164b348919 1173 * Retrieves the font object used for rendering characters on the display.
MrBedfordVan 0:b9164b348919 1174 *
MrBedfordVan 0:b9164b348919 1175 * @note DEPRECATED! Please use MicroBitFont::getSystemFont() instead.
MrBedfordVan 0:b9164b348919 1176 */
MrBedfordVan 0:b9164b348919 1177 MicroBitFont MicroBitDisplay::getFont()
MrBedfordVan 0:b9164b348919 1178 {
MrBedfordVan 0:b9164b348919 1179 return MicroBitFont::getSystemFont();
MrBedfordVan 0:b9164b348919 1180 }
MrBedfordVan 0:b9164b348919 1181
MrBedfordVan 0:b9164b348919 1182 /**
MrBedfordVan 0:b9164b348919 1183 * Captures the bitmap currently being rendered on the display.
MrBedfordVan 0:b9164b348919 1184 *
MrBedfordVan 0:b9164b348919 1185 * @return a MicroBitImage containing the captured data.
MrBedfordVan 0:b9164b348919 1186 */
MrBedfordVan 0:b9164b348919 1187 MicroBitImage MicroBitDisplay::screenShot()
MrBedfordVan 0:b9164b348919 1188 {
MrBedfordVan 0:b9164b348919 1189 return image.crop(0,0,MICROBIT_DISPLAY_WIDTH,MICROBIT_DISPLAY_HEIGHT);
MrBedfordVan 0:b9164b348919 1190 }
MrBedfordVan 0:b9164b348919 1191
MrBedfordVan 0:b9164b348919 1192 /**
MrBedfordVan 0:b9164b348919 1193 * Gives a representative figure of the light level in the current environment
MrBedfordVan 0:b9164b348919 1194 * where are micro:bit is situated.
MrBedfordVan 0:b9164b348919 1195 *
MrBedfordVan 0:b9164b348919 1196 * Internally, it constructs an instance of a MicroBitLightSensor if not already configured
MrBedfordVan 0:b9164b348919 1197 * and sets the display mode to DISPLAY_MODE_BLACK_AND_WHITE_LIGHT_SENSE.
MrBedfordVan 0:b9164b348919 1198 *
MrBedfordVan 0:b9164b348919 1199 * This also changes the tickPeriod to MICROBIT_LIGHT_SENSOR_TICK_SPEED so
MrBedfordVan 0:b9164b348919 1200 * that the display does not suffer from artifacts.
MrBedfordVan 0:b9164b348919 1201 *
MrBedfordVan 0:b9164b348919 1202 * @return an indicative light level in the range 0 - 255.
MrBedfordVan 0:b9164b348919 1203 *
MrBedfordVan 0:b9164b348919 1204 * @note this will return 0 on the first call to this method, a light reading
MrBedfordVan 0:b9164b348919 1205 * will be available after the display has activated the light sensor for the
MrBedfordVan 0:b9164b348919 1206 * first time.
MrBedfordVan 0:b9164b348919 1207 */
MrBedfordVan 0:b9164b348919 1208 int MicroBitDisplay::readLightLevel()
MrBedfordVan 0:b9164b348919 1209 {
MrBedfordVan 0:b9164b348919 1210 if(mode != DISPLAY_MODE_BLACK_AND_WHITE_LIGHT_SENSE)
MrBedfordVan 0:b9164b348919 1211 {
MrBedfordVan 0:b9164b348919 1212 setDisplayMode(DISPLAY_MODE_BLACK_AND_WHITE_LIGHT_SENSE);
MrBedfordVan 0:b9164b348919 1213 this->lightSensor = new MicroBitLightSensor(matrixMap);
MrBedfordVan 0:b9164b348919 1214 }
MrBedfordVan 0:b9164b348919 1215
MrBedfordVan 0:b9164b348919 1216 return this->lightSensor->read();
MrBedfordVan 0:b9164b348919 1217 }
MrBedfordVan 0:b9164b348919 1218
MrBedfordVan 0:b9164b348919 1219 /**
MrBedfordVan 0:b9164b348919 1220 * Destructor for MicroBitDisplay, where we deregister this instance from the array of system components.
MrBedfordVan 0:b9164b348919 1221 */
MrBedfordVan 0:b9164b348919 1222 MicroBitDisplay::~MicroBitDisplay()
MrBedfordVan 0:b9164b348919 1223 {
MrBedfordVan 0:b9164b348919 1224 system_timer_remove_component(this);
MrBedfordVan 0:b9164b348919 1225 }