updates
Dependencies: BLE_API mbed-dev-bin nRF51822
Fork of microbit-dal-eddystone by
source/core/MicroBitDevice.cpp@61:b597fb218f84, 2016-07-13 (annotated)
- Committer:
- LancasterUniversity
- Date:
- Wed Jul 13 12:18:40 2016 +0100
- Revision:
- 61:b597fb218f84
- Parent:
- 57:290a35cb9981
- Child:
- 65:f7ebabf23e15
Synchronized with git rev 64042e4a
Author: James Devine
microbit-dal: BUGFIX cast in MicroBitSerial from int to char
There was an unnecessary cast in MicroBitSerial.read that meant error
codes would never be returned to the user application, this has now
been removed.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Jonathan Austin |
1:8aa5cdb4ab67 | 1 | /* |
Jonathan Austin |
1:8aa5cdb4ab67 | 2 | The MIT License (MIT) |
Jonathan Austin |
1:8aa5cdb4ab67 | 3 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 4 | Copyright (c) 2016 British Broadcasting Corporation. |
Jonathan Austin |
1:8aa5cdb4ab67 | 5 | This software is provided by Lancaster University by arrangement with the BBC. |
Jonathan Austin |
1:8aa5cdb4ab67 | 6 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 7 | Permission is hereby granted, free of charge, to any person obtaining a |
Jonathan Austin |
1:8aa5cdb4ab67 | 8 | copy of this software and associated documentation files (the "Software"), |
Jonathan Austin |
1:8aa5cdb4ab67 | 9 | to deal in the Software without restriction, including without limitation |
Jonathan Austin |
1:8aa5cdb4ab67 | 10 | the rights to use, copy, modify, merge, publish, distribute, sublicense, |
Jonathan Austin |
1:8aa5cdb4ab67 | 11 | and/or sell copies of the Software, and to permit persons to whom the |
Jonathan Austin |
1:8aa5cdb4ab67 | 12 | Software is furnished to do so, subject to the following conditions: |
Jonathan Austin |
1:8aa5cdb4ab67 | 13 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 14 | The above copyright notice and this permission notice shall be included in |
Jonathan Austin |
1:8aa5cdb4ab67 | 15 | all copies or substantial portions of the Software. |
Jonathan Austin |
1:8aa5cdb4ab67 | 16 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
Jonathan Austin |
1:8aa5cdb4ab67 | 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
Jonathan Austin |
1:8aa5cdb4ab67 | 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
Jonathan Austin |
1:8aa5cdb4ab67 | 20 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
Jonathan Austin |
1:8aa5cdb4ab67 | 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
Jonathan Austin |
1:8aa5cdb4ab67 | 22 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
Jonathan Austin |
1:8aa5cdb4ab67 | 23 | DEALINGS IN THE SOFTWARE. |
Jonathan Austin |
1:8aa5cdb4ab67 | 24 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 25 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 26 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 27 | * Compatibility / portability funcitons and constants for the MicroBit DAL. |
Jonathan Austin |
1:8aa5cdb4ab67 | 28 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 29 | #include "MicroBitConfig.h" |
Jonathan Austin |
1:8aa5cdb4ab67 | 30 | #include "MicroBitButton.h" |
Jonathan Austin |
1:8aa5cdb4ab67 | 31 | #include "MicroBitDevice.h" |
Jonathan Austin |
1:8aa5cdb4ab67 | 32 | #include "MicroBitFont.h" |
Jonathan Austin |
1:8aa5cdb4ab67 | 33 | #include "mbed.h" |
Jonathan Austin |
1:8aa5cdb4ab67 | 34 | #include "ErrorNo.h" |
Jonathan Austin |
1:8aa5cdb4ab67 | 35 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 36 | /* |
Jonathan Austin |
1:8aa5cdb4ab67 | 37 | * The underlying Nordic libraries that support BLE do not compile cleanly with the stringent GCC settings we employ |
Jonathan Austin |
1:8aa5cdb4ab67 | 38 | * If we're compiling under GCC, then we suppress any warnings generated from this code (but not the rest of the DAL) |
Jonathan Austin |
1:8aa5cdb4ab67 | 39 | * The ARM cc compiler is more tolerant. We don't test __GNUC__ here to detect GCC as ARMCC also typically sets this |
Jonathan Austin |
1:8aa5cdb4ab67 | 40 | * as a compatability option, but does not support the options used... |
Jonathan Austin |
1:8aa5cdb4ab67 | 41 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 42 | #if !defined(__arm) |
Jonathan Austin |
1:8aa5cdb4ab67 | 43 | #pragma GCC diagnostic ignored "-Wunused-function" |
Jonathan Austin |
1:8aa5cdb4ab67 | 44 | #pragma GCC diagnostic push |
Jonathan Austin |
1:8aa5cdb4ab67 | 45 | #pragma GCC diagnostic ignored "-Wunused-parameter" |
Jonathan Austin |
1:8aa5cdb4ab67 | 46 | #endif |
Jonathan Austin |
1:8aa5cdb4ab67 | 47 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 48 | #include "nrf_soc.h" |
Jonathan Austin |
1:8aa5cdb4ab67 | 49 | #include "nrf_sdm.h" |
Jonathan Austin |
1:8aa5cdb4ab67 | 50 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 51 | /* |
Jonathan Austin |
1:8aa5cdb4ab67 | 52 | * Return to our predefined compiler settings. |
Jonathan Austin |
1:8aa5cdb4ab67 | 53 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 54 | #if !defined(__arm) |
Jonathan Austin |
1:8aa5cdb4ab67 | 55 | #pragma GCC diagnostic pop |
Jonathan Austin |
1:8aa5cdb4ab67 | 56 | #endif |
Jonathan Austin |
1:8aa5cdb4ab67 | 57 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 58 | static char friendly_name[MICROBIT_NAME_LENGTH+1]; |
Jonathan Austin |
1:8aa5cdb4ab67 | 59 | static const uint8_t panicFace[5] = {0x1B, 0x1B,0x0,0x0E,0x11}; |
Jonathan Austin |
1:8aa5cdb4ab67 | 60 | static int panic_timeout = 0; |
Jonathan Austin |
1:8aa5cdb4ab67 | 61 | static uint32_t random_value = 0; |
Jonathan Austin |
1:8aa5cdb4ab67 | 62 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 63 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 64 | * Determines if a BLE stack is currently running. |
Jonathan Austin |
1:8aa5cdb4ab67 | 65 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 66 | * @return true is a bluetooth stack is operational, false otherwise. |
Jonathan Austin |
1:8aa5cdb4ab67 | 67 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 68 | bool ble_running() |
Jonathan Austin |
1:8aa5cdb4ab67 | 69 | { |
LancasterUniversity | 57:290a35cb9981 | 70 | uint8_t t = 0; |
LancasterUniversity | 57:290a35cb9981 | 71 | |
LancasterUniversity | 57:290a35cb9981 | 72 | #if CONFIG_ENABLED(MICROBIT_BLE_ENABLED) || CONFIG_ENABLED(MICROBIT_BLE_PAIRING_MODE) |
Jonathan Austin |
1:8aa5cdb4ab67 | 73 | sd_softdevice_is_enabled(&t); |
LancasterUniversity | 57:290a35cb9981 | 74 | #endif |
LancasterUniversity | 57:290a35cb9981 | 75 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 76 | return t==1; |
Jonathan Austin |
1:8aa5cdb4ab67 | 77 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 78 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 79 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 80 | * Derived a unique, consistent serial number of this device from internal data. |
Jonathan Austin |
1:8aa5cdb4ab67 | 81 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 82 | * @return the serial number of this device. |
Jonathan Austin |
1:8aa5cdb4ab67 | 83 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 84 | uint32_t microbit_serial_number() |
Jonathan Austin |
1:8aa5cdb4ab67 | 85 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 86 | return NRF_FICR->DEVICEID[1]; |
Jonathan Austin |
1:8aa5cdb4ab67 | 87 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 88 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 89 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 90 | * Derive the friendly name for this device, based on its serial number. |
Jonathan Austin |
1:8aa5cdb4ab67 | 91 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 92 | * @return the serial number of this device. |
Jonathan Austin |
1:8aa5cdb4ab67 | 93 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 94 | char* microbit_friendly_name() |
Jonathan Austin |
1:8aa5cdb4ab67 | 95 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 96 | const uint8_t codebook[MICROBIT_NAME_LENGTH][MICROBIT_NAME_CODE_LETTERS] = |
Jonathan Austin |
1:8aa5cdb4ab67 | 97 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 98 | {'z', 'v', 'g', 'p', 't'}, |
Jonathan Austin |
1:8aa5cdb4ab67 | 99 | {'u', 'o', 'i', 'e', 'a'}, |
Jonathan Austin |
1:8aa5cdb4ab67 | 100 | {'z', 'v', 'g', 'p', 't'}, |
Jonathan Austin |
1:8aa5cdb4ab67 | 101 | {'u', 'o', 'i', 'e', 'a'}, |
Jonathan Austin |
1:8aa5cdb4ab67 | 102 | {'z', 'v', 'g', 'p', 't'} |
Jonathan Austin |
1:8aa5cdb4ab67 | 103 | }; |
Jonathan Austin |
1:8aa5cdb4ab67 | 104 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 105 | // We count right to left, so create a pointer to the end of the buffer. |
Jonathan Austin |
1:8aa5cdb4ab67 | 106 | char *name = friendly_name; |
Jonathan Austin |
1:8aa5cdb4ab67 | 107 | name += MICROBIT_NAME_LENGTH; |
Jonathan Austin |
1:8aa5cdb4ab67 | 108 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 109 | // Terminate the string. |
Jonathan Austin |
1:8aa5cdb4ab67 | 110 | *name = 0; |
Jonathan Austin |
1:8aa5cdb4ab67 | 111 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 112 | // Derive our name from the nrf51822's unique ID. |
Jonathan Austin |
1:8aa5cdb4ab67 | 113 | uint32_t n = microbit_serial_number(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 114 | int ld = 1; |
Jonathan Austin |
1:8aa5cdb4ab67 | 115 | int d = MICROBIT_NAME_CODE_LETTERS; |
Jonathan Austin |
1:8aa5cdb4ab67 | 116 | int h; |
Jonathan Austin |
1:8aa5cdb4ab67 | 117 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 118 | for (int i=0; i<MICROBIT_NAME_LENGTH; i++) |
Jonathan Austin |
1:8aa5cdb4ab67 | 119 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 120 | h = (n % d) / ld; |
Jonathan Austin |
1:8aa5cdb4ab67 | 121 | n -= h; |
Jonathan Austin |
1:8aa5cdb4ab67 | 122 | d *= MICROBIT_NAME_CODE_LETTERS; |
Jonathan Austin |
1:8aa5cdb4ab67 | 123 | ld *= MICROBIT_NAME_CODE_LETTERS; |
Jonathan Austin |
1:8aa5cdb4ab67 | 124 | *--name = codebook[i][h]; |
Jonathan Austin |
1:8aa5cdb4ab67 | 125 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 126 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 127 | return friendly_name; |
Jonathan Austin |
1:8aa5cdb4ab67 | 128 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 129 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 130 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 131 | * Perform a hard reset of the micro:bit. |
Jonathan Austin |
1:8aa5cdb4ab67 | 132 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 133 | void |
Jonathan Austin |
1:8aa5cdb4ab67 | 134 | microbit_reset() |
Jonathan Austin |
1:8aa5cdb4ab67 | 135 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 136 | NVIC_SystemReset(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 137 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 138 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 139 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 140 | * Determine the version of microbit-dal currently running. |
Jonathan Austin |
1:8aa5cdb4ab67 | 141 | * @return a pointer to a character buffer containing a representation of the semantic version number. |
Jonathan Austin |
1:8aa5cdb4ab67 | 142 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 143 | const char * |
Jonathan Austin |
1:8aa5cdb4ab67 | 144 | microbit_dal_version() |
Jonathan Austin |
1:8aa5cdb4ab67 | 145 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 146 | return MICROBIT_DAL_VERSION; |
Jonathan Austin |
1:8aa5cdb4ab67 | 147 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 148 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 149 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 150 | * Defines the length of time that the device will remain in a error state before resetting. |
Jonathan Austin |
1:8aa5cdb4ab67 | 151 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 152 | * @param iteration The number of times the error code will be displayed before resetting. Set to zero to remain in error state forever. |
Jonathan Austin |
1:8aa5cdb4ab67 | 153 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 154 | * @code |
Jonathan Austin |
1:8aa5cdb4ab67 | 155 | * microbit_panic_timeout(4); |
Jonathan Austin |
1:8aa5cdb4ab67 | 156 | * @endcode |
Jonathan Austin |
1:8aa5cdb4ab67 | 157 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 158 | void microbit_panic_timeout(int iterations) |
Jonathan Austin |
1:8aa5cdb4ab67 | 159 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 160 | panic_timeout = iterations; |
Jonathan Austin |
1:8aa5cdb4ab67 | 161 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 162 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 163 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 164 | * Disables all interrupts and user processing. |
Jonathan Austin |
1:8aa5cdb4ab67 | 165 | * Displays "=(" and an accompanying status code on the default display. |
LancasterUniversity | 47:69f452b1a5c9 | 166 | * @param statusCode the appropriate status code, must be in the range 0-999. |
Jonathan Austin |
1:8aa5cdb4ab67 | 167 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 168 | * @code |
Jonathan Austin |
1:8aa5cdb4ab67 | 169 | * microbit_panic(20); |
Jonathan Austin |
1:8aa5cdb4ab67 | 170 | * @endcode |
Jonathan Austin |
1:8aa5cdb4ab67 | 171 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 172 | void microbit_panic(int statusCode) |
Jonathan Austin |
1:8aa5cdb4ab67 | 173 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 174 | DigitalIn resetButton(MICROBIT_PIN_BUTTON_RESET); |
Jonathan Austin |
1:8aa5cdb4ab67 | 175 | resetButton.mode(PullUp); |
Jonathan Austin |
1:8aa5cdb4ab67 | 176 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 177 | uint32_t row_mask = 0; |
Jonathan Austin |
1:8aa5cdb4ab67 | 178 | uint32_t col_mask = 0; |
Jonathan Austin |
1:8aa5cdb4ab67 | 179 | uint32_t row_reset = 0x01 << microbitMatrixMap.rowStart; |
Jonathan Austin |
1:8aa5cdb4ab67 | 180 | uint32_t row_data = row_reset; |
Jonathan Austin |
1:8aa5cdb4ab67 | 181 | uint8_t count = panic_timeout ? panic_timeout : 1; |
Jonathan Austin |
1:8aa5cdb4ab67 | 182 | uint8_t strobeRow = 0; |
Jonathan Austin |
1:8aa5cdb4ab67 | 183 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 184 | row_mask = 0; |
Jonathan Austin |
1:8aa5cdb4ab67 | 185 | for (int i = microbitMatrixMap.rowStart; i < microbitMatrixMap.rowStart + microbitMatrixMap.rows; i++) |
Jonathan Austin |
1:8aa5cdb4ab67 | 186 | row_mask |= 0x01 << i; |
Jonathan Austin |
1:8aa5cdb4ab67 | 187 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 188 | for (int i = microbitMatrixMap.columnStart; i < microbitMatrixMap.columnStart + microbitMatrixMap.columns; i++) |
Jonathan Austin |
1:8aa5cdb4ab67 | 189 | col_mask |= 0x01 << i; |
Jonathan Austin |
1:8aa5cdb4ab67 | 190 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 191 | PortOut LEDMatrix(Port0, row_mask | col_mask); |
Jonathan Austin |
1:8aa5cdb4ab67 | 192 | |
LancasterUniversity | 47:69f452b1a5c9 | 193 | if(statusCode < 0 || statusCode > 999) |
Jonathan Austin |
1:8aa5cdb4ab67 | 194 | statusCode = 0; |
Jonathan Austin |
1:8aa5cdb4ab67 | 195 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 196 | __disable_irq(); //stop ALL interrupts |
Jonathan Austin |
1:8aa5cdb4ab67 | 197 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 198 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 199 | //point to the font stored in Flash |
LancasterUniversity | 47:69f452b1a5c9 | 200 | const unsigned char* fontLocation = MicroBitFont::defaultFont; |
Jonathan Austin |
1:8aa5cdb4ab67 | 201 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 202 | //get individual digits of status code, and place it into a single array/ |
Jonathan Austin |
1:8aa5cdb4ab67 | 203 | const uint8_t* chars[MICROBIT_PANIC_ERROR_CHARS] = { panicFace, fontLocation+((((statusCode/100 % 10)+48)-MICROBIT_FONT_ASCII_START) * 5), fontLocation+((((statusCode/10 % 10)+48)-MICROBIT_FONT_ASCII_START) * 5), fontLocation+((((statusCode % 10)+48)-MICROBIT_FONT_ASCII_START) * 5)}; |
Jonathan Austin |
1:8aa5cdb4ab67 | 204 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 205 | while(count) |
Jonathan Austin |
1:8aa5cdb4ab67 | 206 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 207 | //iterate through our chars :) |
Jonathan Austin |
1:8aa5cdb4ab67 | 208 | for(int characterCount = 0; characterCount < MICROBIT_PANIC_ERROR_CHARS; characterCount++) |
Jonathan Austin |
1:8aa5cdb4ab67 | 209 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 210 | int outerCount = 0; |
Jonathan Austin |
1:8aa5cdb4ab67 | 211 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 212 | //display the current character |
Jonathan Austin |
1:8aa5cdb4ab67 | 213 | while(outerCount < 500) |
Jonathan Austin |
1:8aa5cdb4ab67 | 214 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 215 | uint32_t col_data = 0; |
Jonathan Austin |
1:8aa5cdb4ab67 | 216 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 217 | int i = 0; |
Jonathan Austin |
1:8aa5cdb4ab67 | 218 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 219 | //if we have hit the row limit - reset both the bit mask and the row variable |
Jonathan Austin |
1:8aa5cdb4ab67 | 220 | if(strobeRow == microbitMatrixMap.rows) |
Jonathan Austin |
1:8aa5cdb4ab67 | 221 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 222 | strobeRow = 0; |
Jonathan Austin |
1:8aa5cdb4ab67 | 223 | row_data = row_reset; |
Jonathan Austin |
1:8aa5cdb4ab67 | 224 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 225 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 226 | // Calculate the bitpattern to write. |
Jonathan Austin |
1:8aa5cdb4ab67 | 227 | for (i = 0; i < microbitMatrixMap.columns; i++) |
Jonathan Austin |
1:8aa5cdb4ab67 | 228 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 229 | int index = (i * microbitMatrixMap.rows) + strobeRow; |
Jonathan Austin |
1:8aa5cdb4ab67 | 230 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 231 | int bitMsk = 0x10 >> microbitMatrixMap.map[index].x; //chars are right aligned but read left to right |
Jonathan Austin |
1:8aa5cdb4ab67 | 232 | int y = microbitMatrixMap.map[index].y; |
Jonathan Austin |
1:8aa5cdb4ab67 | 233 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 234 | if(chars[characterCount][y] & bitMsk) |
Jonathan Austin |
1:8aa5cdb4ab67 | 235 | col_data |= (1 << i); |
Jonathan Austin |
1:8aa5cdb4ab67 | 236 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 237 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 238 | col_data = ~col_data << microbitMatrixMap.columnStart & col_mask; |
Jonathan Austin |
1:8aa5cdb4ab67 | 239 | |
LancasterUniversity | 47:69f452b1a5c9 | 240 | if(chars[characterCount] == chars[(characterCount - 1) % MICROBIT_PANIC_ERROR_CHARS] && outerCount < 50) |
LancasterUniversity | 47:69f452b1a5c9 | 241 | LEDMatrix = 0; |
LancasterUniversity | 47:69f452b1a5c9 | 242 | else |
LancasterUniversity | 47:69f452b1a5c9 | 243 | LEDMatrix = col_data | row_data; |
Jonathan Austin |
1:8aa5cdb4ab67 | 244 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 245 | //burn cycles |
LancasterUniversity | 47:69f452b1a5c9 | 246 | i = 2000; |
Jonathan Austin |
1:8aa5cdb4ab67 | 247 | while(i>0) |
Jonathan Austin |
1:8aa5cdb4ab67 | 248 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 249 | // Check if the reset button has been pressed. Interrupts are disabled, so the normal method can't be relied upon... |
Jonathan Austin |
1:8aa5cdb4ab67 | 250 | if (resetButton == 0) |
Jonathan Austin |
1:8aa5cdb4ab67 | 251 | microbit_reset(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 252 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 253 | i--; |
Jonathan Austin |
1:8aa5cdb4ab67 | 254 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 255 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 256 | //update the bit mask and row count |
Jonathan Austin |
1:8aa5cdb4ab67 | 257 | row_data <<= 1; |
Jonathan Austin |
1:8aa5cdb4ab67 | 258 | strobeRow++; |
Jonathan Austin |
1:8aa5cdb4ab67 | 259 | outerCount++; |
Jonathan Austin |
1:8aa5cdb4ab67 | 260 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 261 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 262 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 263 | if (panic_timeout) |
Jonathan Austin |
1:8aa5cdb4ab67 | 264 | count--; |
Jonathan Austin |
1:8aa5cdb4ab67 | 265 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 266 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 267 | microbit_reset(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 268 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 269 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 270 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 271 | * Generate a random number in the given range. |
Jonathan Austin |
1:8aa5cdb4ab67 | 272 | * We use a simple Galois LFSR random number generator here, |
Jonathan Austin |
1:8aa5cdb4ab67 | 273 | * as a Galois LFSR is sufficient for our applications, and much more lightweight |
Jonathan Austin |
1:8aa5cdb4ab67 | 274 | * than the hardware random number generator built int the processor, which takes |
Jonathan Austin |
1:8aa5cdb4ab67 | 275 | * a long time and uses a lot of energy. |
Jonathan Austin |
1:8aa5cdb4ab67 | 276 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 277 | * KIDS: You shouldn't use this is the real world to generte cryptographic keys though... |
Jonathan Austin |
1:8aa5cdb4ab67 | 278 | * have a think why not. :-) |
Jonathan Austin |
1:8aa5cdb4ab67 | 279 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 280 | * @param max the upper range to generate a number for. This number cannot be negative. |
Jonathan Austin |
1:8aa5cdb4ab67 | 281 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 282 | * @return A random, natural number between 0 and the max-1. Or MICROBIT_INVALID_VALUE if max is <= 0. |
Jonathan Austin |
1:8aa5cdb4ab67 | 283 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 284 | * @code |
Jonathan Austin |
1:8aa5cdb4ab67 | 285 | * microbit_random(200); //a number between 0 and 199 |
Jonathan Austin |
1:8aa5cdb4ab67 | 286 | * @endcode |
Jonathan Austin |
1:8aa5cdb4ab67 | 287 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 288 | int microbit_random(int max) |
Jonathan Austin |
1:8aa5cdb4ab67 | 289 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 290 | uint32_t m, result; |
Jonathan Austin |
1:8aa5cdb4ab67 | 291 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 292 | if(max <= 0) |
Jonathan Austin |
1:8aa5cdb4ab67 | 293 | return MICROBIT_INVALID_PARAMETER; |
Jonathan Austin |
1:8aa5cdb4ab67 | 294 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 295 | // Our maximum return value is actually one less than passed |
Jonathan Austin |
1:8aa5cdb4ab67 | 296 | max--; |
Jonathan Austin |
1:8aa5cdb4ab67 | 297 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 298 | do { |
Jonathan Austin |
1:8aa5cdb4ab67 | 299 | m = (uint32_t)max; |
Jonathan Austin |
1:8aa5cdb4ab67 | 300 | result = 0; |
Jonathan Austin |
1:8aa5cdb4ab67 | 301 | do { |
Jonathan Austin |
1:8aa5cdb4ab67 | 302 | // Cycle the LFSR (Linear Feedback Shift Register). |
Jonathan Austin |
1:8aa5cdb4ab67 | 303 | // We use an optimal sequence with a period of 2^32-1, as defined by Bruce Schneier here (a true legend in the field!), |
Jonathan Austin |
1:8aa5cdb4ab67 | 304 | // For those interested, it's documented in his paper: |
Jonathan Austin |
1:8aa5cdb4ab67 | 305 | // "Pseudo-Random Sequence Generator for 32-Bit CPUs: A fast, machine-independent generator for 32-bit Microprocessors" |
Jonathan Austin |
1:8aa5cdb4ab67 | 306 | // https://www.schneier.com/paper-pseudorandom-sequence.html |
Jonathan Austin |
1:8aa5cdb4ab67 | 307 | uint32_t rnd = random_value; |
Jonathan Austin |
1:8aa5cdb4ab67 | 308 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 309 | rnd = ((((rnd >> 31) |
Jonathan Austin |
1:8aa5cdb4ab67 | 310 | ^ (rnd >> 6) |
Jonathan Austin |
1:8aa5cdb4ab67 | 311 | ^ (rnd >> 4) |
Jonathan Austin |
1:8aa5cdb4ab67 | 312 | ^ (rnd >> 2) |
Jonathan Austin |
1:8aa5cdb4ab67 | 313 | ^ (rnd >> 1) |
Jonathan Austin |
1:8aa5cdb4ab67 | 314 | ^ rnd) |
Jonathan Austin |
1:8aa5cdb4ab67 | 315 | & 0x0000001) |
Jonathan Austin |
1:8aa5cdb4ab67 | 316 | << 31 ) |
Jonathan Austin |
1:8aa5cdb4ab67 | 317 | | (rnd >> 1); |
Jonathan Austin |
1:8aa5cdb4ab67 | 318 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 319 | random_value = rnd; |
Jonathan Austin |
1:8aa5cdb4ab67 | 320 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 321 | result = ((result << 1) | (rnd & 0x00000001)); |
Jonathan Austin |
1:8aa5cdb4ab67 | 322 | } while(m >>= 1); |
Jonathan Austin |
1:8aa5cdb4ab67 | 323 | } while (result > (uint32_t)max); |
Jonathan Austin |
1:8aa5cdb4ab67 | 324 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 325 | return result; |
Jonathan Austin |
1:8aa5cdb4ab67 | 326 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 327 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 328 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 329 | * Seed the random number generator (RNG). |
Jonathan Austin |
1:8aa5cdb4ab67 | 330 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 331 | * This function uses the NRF51822's in built cryptographic random number generator to seed a Galois LFSR. |
Jonathan Austin |
1:8aa5cdb4ab67 | 332 | * We do this as the hardware RNG is relatively high power, and is locked out by the BLE stack internally, |
Jonathan Austin |
1:8aa5cdb4ab67 | 333 | * with a less than optimal application interface. A Galois LFSR is sufficient for our |
Jonathan Austin |
1:8aa5cdb4ab67 | 334 | * applications, and much more lightweight. |
Jonathan Austin |
1:8aa5cdb4ab67 | 335 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 336 | void microbit_seed_random() |
Jonathan Austin |
1:8aa5cdb4ab67 | 337 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 338 | random_value = 0; |
Jonathan Austin |
1:8aa5cdb4ab67 | 339 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 340 | if(ble_running()) |
Jonathan Austin |
1:8aa5cdb4ab67 | 341 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 342 | // If Bluetooth is enabled, we need to go through the Nordic software to safely do this. |
Jonathan Austin |
1:8aa5cdb4ab67 | 343 | uint32_t result = sd_rand_application_vector_get((uint8_t*)&random_value, sizeof(random_value)); |
Jonathan Austin |
1:8aa5cdb4ab67 | 344 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 345 | // If we couldn't get the random bytes then at least make the seed non-zero. |
Jonathan Austin |
1:8aa5cdb4ab67 | 346 | if (result != NRF_SUCCESS) |
Jonathan Austin |
1:8aa5cdb4ab67 | 347 | random_value = 0xBBC5EED; |
Jonathan Austin |
1:8aa5cdb4ab67 | 348 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 349 | else |
Jonathan Austin |
1:8aa5cdb4ab67 | 350 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 351 | // Othwerwise we can access the hardware RNG directly. |
Jonathan Austin |
1:8aa5cdb4ab67 | 352 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 353 | // Start the Random number generator. No need to leave it running... I hope. :-) |
Jonathan Austin |
1:8aa5cdb4ab67 | 354 | NRF_RNG->TASKS_START = 1; |
Jonathan Austin |
1:8aa5cdb4ab67 | 355 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 356 | for(int i = 0; i < 4; i++) |
Jonathan Austin |
1:8aa5cdb4ab67 | 357 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 358 | // Clear the VALRDY EVENT |
Jonathan Austin |
1:8aa5cdb4ab67 | 359 | NRF_RNG->EVENTS_VALRDY = 0; |
Jonathan Austin |
1:8aa5cdb4ab67 | 360 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 361 | // Wait for a number ot be generated. |
Jonathan Austin |
1:8aa5cdb4ab67 | 362 | while(NRF_RNG->EVENTS_VALRDY == 0); |
Jonathan Austin |
1:8aa5cdb4ab67 | 363 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 364 | random_value = (random_value << 8) | ((int) NRF_RNG->VALUE); |
Jonathan Austin |
1:8aa5cdb4ab67 | 365 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 366 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 367 | // Disable the generator to save power. |
Jonathan Austin |
1:8aa5cdb4ab67 | 368 | NRF_RNG->TASKS_STOP = 1; |
Jonathan Austin |
1:8aa5cdb4ab67 | 369 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 370 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 371 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 372 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 373 | * Seed the pseudo random number generator (RNG) using the given 32-bit value. |
Jonathan Austin |
1:8aa5cdb4ab67 | 374 | * This function does not use the NRF51822's in built cryptographic random number generator. |
Jonathan Austin |
1:8aa5cdb4ab67 | 375 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 376 | * @param seed The value to use as a seed. |
Jonathan Austin |
1:8aa5cdb4ab67 | 377 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 378 | void microbit_seed_random(uint32_t seed) |
Jonathan Austin |
1:8aa5cdb4ab67 | 379 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 380 | random_value = seed; |
LancasterUniversity | 47:69f452b1a5c9 | 381 | } |