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 #include "MicroBitConfig.h"
MrBedfordVan 0:b9164b348919 27 #include "MicroBitThermometer.h"
MrBedfordVan 0:b9164b348919 28 #include "MicroBitSystemTimer.h"
MrBedfordVan 0:b9164b348919 29 #include "MicroBitFiber.h"
MrBedfordVan 0:b9164b348919 30
MrBedfordVan 0:b9164b348919 31 /*
MrBedfordVan 0:b9164b348919 32 * The underlying Nordic libraries that support BLE do not compile cleanly with the stringent GCC settings we employ
MrBedfordVan 0:b9164b348919 33 * If we're compiling under GCC, then we suppress any warnings generated from this code (but not the rest of the DAL)
MrBedfordVan 0:b9164b348919 34 * The ARM cc compiler is more tolerant. We don't test __GNUC__ here to detect GCC as ARMCC also typically sets this
MrBedfordVan 0:b9164b348919 35 * as a compatability option, but does not support the options used...
MrBedfordVan 0:b9164b348919 36 */
MrBedfordVan 0:b9164b348919 37 #if !defined(__arm)
MrBedfordVan 0:b9164b348919 38 #pragma GCC diagnostic ignored "-Wunused-function"
MrBedfordVan 0:b9164b348919 39 #pragma GCC diagnostic push
MrBedfordVan 0:b9164b348919 40 #pragma GCC diagnostic ignored "-Wunused-parameter"
MrBedfordVan 0:b9164b348919 41 #endif
MrBedfordVan 0:b9164b348919 42
MrBedfordVan 0:b9164b348919 43 #include "nrf_soc.h"
MrBedfordVan 0:b9164b348919 44 #include "nrf_sdm.h"
MrBedfordVan 0:b9164b348919 45
MrBedfordVan 0:b9164b348919 46 /*
MrBedfordVan 0:b9164b348919 47 * Return to our predefined compiler settings.
MrBedfordVan 0:b9164b348919 48 */
MrBedfordVan 0:b9164b348919 49 #if !defined(__arm)
MrBedfordVan 0:b9164b348919 50 #pragma GCC diagnostic pop
MrBedfordVan 0:b9164b348919 51 #endif
MrBedfordVan 0:b9164b348919 52
MrBedfordVan 0:b9164b348919 53 /**
MrBedfordVan 0:b9164b348919 54 * Constructor.
MrBedfordVan 0:b9164b348919 55 * Create new MicroBitThermometer that gives an indication of the current temperature.
MrBedfordVan 0:b9164b348919 56 *
MrBedfordVan 0:b9164b348919 57 * @param _storage an instance of MicroBitStorage used to persist temperature offset data
MrBedfordVan 0:b9164b348919 58 *
MrBedfordVan 0:b9164b348919 59 * @param id the unique EventModel id of this component. Defaults to MICROBIT_ID_THERMOMETER.
MrBedfordVan 0:b9164b348919 60 *
MrBedfordVan 0:b9164b348919 61 * @code
MrBedfordVan 0:b9164b348919 62 * MicroBitStorage storage;
MrBedfordVan 0:b9164b348919 63 * MicroBitThermometer thermometer(storage);
MrBedfordVan 0:b9164b348919 64 * @endcode
MrBedfordVan 0:b9164b348919 65 */
MrBedfordVan 0:b9164b348919 66 MicroBitThermometer::MicroBitThermometer(MicroBitStorage& _storage, uint16_t id) :
MrBedfordVan 0:b9164b348919 67 storage(&_storage)
MrBedfordVan 0:b9164b348919 68 {
MrBedfordVan 0:b9164b348919 69 this->id = id;
MrBedfordVan 0:b9164b348919 70 this->samplePeriod = MICROBIT_THERMOMETER_PERIOD;
MrBedfordVan 0:b9164b348919 71 this->sampleTime = 0;
MrBedfordVan 0:b9164b348919 72 this->offset = 0;
MrBedfordVan 0:b9164b348919 73
MrBedfordVan 0:b9164b348919 74 KeyValuePair *tempCalibration = storage->get("tempCal");
MrBedfordVan 0:b9164b348919 75
MrBedfordVan 0:b9164b348919 76 if(tempCalibration != NULL)
MrBedfordVan 0:b9164b348919 77 {
MrBedfordVan 0:b9164b348919 78 memcpy(&offset, tempCalibration->value, sizeof(int16_t));
MrBedfordVan 0:b9164b348919 79 delete tempCalibration;
MrBedfordVan 0:b9164b348919 80 }
MrBedfordVan 0:b9164b348919 81 }
MrBedfordVan 0:b9164b348919 82
MrBedfordVan 0:b9164b348919 83 /**
MrBedfordVan 0:b9164b348919 84 * Constructor.
MrBedfordVan 0:b9164b348919 85 * Create new MicroBitThermometer that gives an indication of the current temperature.
MrBedfordVan 0:b9164b348919 86 *
MrBedfordVan 0:b9164b348919 87 * @param id the unique EventModel id of this component. Defaults to MICROBIT_ID_THERMOMETER.
MrBedfordVan 0:b9164b348919 88 *
MrBedfordVan 0:b9164b348919 89 * @code
MrBedfordVan 0:b9164b348919 90 * MicroBitThermometer thermometer;
MrBedfordVan 0:b9164b348919 91 * @endcode
MrBedfordVan 0:b9164b348919 92 */
MrBedfordVan 0:b9164b348919 93 MicroBitThermometer::MicroBitThermometer(uint16_t id) :
MrBedfordVan 0:b9164b348919 94 storage(NULL)
MrBedfordVan 0:b9164b348919 95 {
MrBedfordVan 0:b9164b348919 96 this->id = id;
MrBedfordVan 0:b9164b348919 97 this->samplePeriod = MICROBIT_THERMOMETER_PERIOD;
MrBedfordVan 0:b9164b348919 98 this->sampleTime = 0;
MrBedfordVan 0:b9164b348919 99 this->offset = 0;
MrBedfordVan 0:b9164b348919 100 }
MrBedfordVan 0:b9164b348919 101
MrBedfordVan 0:b9164b348919 102 /**
MrBedfordVan 0:b9164b348919 103 * Gets the current temperature of the microbit.
MrBedfordVan 0:b9164b348919 104 *
MrBedfordVan 0:b9164b348919 105 * @return the current temperature, in degrees celsius.
MrBedfordVan 0:b9164b348919 106 *
MrBedfordVan 0:b9164b348919 107 * @code
MrBedfordVan 0:b9164b348919 108 * thermometer.getTemperature();
MrBedfordVan 0:b9164b348919 109 * @endcode
MrBedfordVan 0:b9164b348919 110 */
MrBedfordVan 0:b9164b348919 111 int MicroBitThermometer::getTemperature()
MrBedfordVan 0:b9164b348919 112 {
MrBedfordVan 0:b9164b348919 113 updateSample();
MrBedfordVan 0:b9164b348919 114 return temperature - offset;
MrBedfordVan 0:b9164b348919 115 }
MrBedfordVan 0:b9164b348919 116
MrBedfordVan 0:b9164b348919 117
MrBedfordVan 0:b9164b348919 118 /**
MrBedfordVan 0:b9164b348919 119 * Updates the temperature sample of this instance of MicroBitThermometer
MrBedfordVan 0:b9164b348919 120 * only if isSampleNeeded() indicates that an update is required.
MrBedfordVan 0:b9164b348919 121 *
MrBedfordVan 0:b9164b348919 122 * This call also will add the thermometer to fiber components to receive
MrBedfordVan 0:b9164b348919 123 * periodic callbacks.
MrBedfordVan 0:b9164b348919 124 *
MrBedfordVan 0:b9164b348919 125 * @return MICROBIT_OK on success.
MrBedfordVan 0:b9164b348919 126 */
MrBedfordVan 0:b9164b348919 127 int MicroBitThermometer::updateSample()
MrBedfordVan 0:b9164b348919 128 {
MrBedfordVan 0:b9164b348919 129 if(!(status & MICROBIT_THERMOMETER_ADDED_TO_IDLE))
MrBedfordVan 0:b9164b348919 130 {
MrBedfordVan 0:b9164b348919 131 // If we're running under a fiber scheduer, register ourselves for a periodic callback to keep our data up to date.
MrBedfordVan 0:b9164b348919 132 // Otherwise, we do just do this on demand, when polled through our read() interface.
MrBedfordVan 0:b9164b348919 133 fiber_add_idle_component(this);
MrBedfordVan 0:b9164b348919 134 status |= MICROBIT_THERMOMETER_ADDED_TO_IDLE;
MrBedfordVan 0:b9164b348919 135 }
MrBedfordVan 0:b9164b348919 136
MrBedfordVan 0:b9164b348919 137 // check if we need to update our sample...
MrBedfordVan 0:b9164b348919 138 if(isSampleNeeded())
MrBedfordVan 0:b9164b348919 139 {
MrBedfordVan 0:b9164b348919 140 int32_t processorTemperature;
MrBedfordVan 0:b9164b348919 141 uint8_t sd_enabled;
MrBedfordVan 0:b9164b348919 142
MrBedfordVan 0:b9164b348919 143 // For now, we just rely on the nrf senesor to be the most accurate.
MrBedfordVan 0:b9164b348919 144 // The compass module also has a temperature sensor, and has the lowest power consumption, so will run the cooler...
MrBedfordVan 0:b9164b348919 145 // ...however it isn't trimmed for accuracy during manufacture, so requires calibration.
MrBedfordVan 0:b9164b348919 146
MrBedfordVan 0:b9164b348919 147 sd_softdevice_is_enabled(&sd_enabled);
MrBedfordVan 0:b9164b348919 148
MrBedfordVan 0:b9164b348919 149 if (sd_enabled)
MrBedfordVan 0:b9164b348919 150 {
MrBedfordVan 0:b9164b348919 151 // If Bluetooth is enabled, we need to go through the Nordic software to safely do this
MrBedfordVan 0:b9164b348919 152 sd_temp_get(&processorTemperature);
MrBedfordVan 0:b9164b348919 153 }
MrBedfordVan 0:b9164b348919 154 else
MrBedfordVan 0:b9164b348919 155 {
MrBedfordVan 0:b9164b348919 156 // Othwerwise, we access the information directly...
MrBedfordVan 0:b9164b348919 157 uint32_t *TEMP = (uint32_t *)0x4000C508;
MrBedfordVan 0:b9164b348919 158
MrBedfordVan 0:b9164b348919 159 NRF_TEMP->TASKS_START = 1;
MrBedfordVan 0:b9164b348919 160
MrBedfordVan 0:b9164b348919 161 while (NRF_TEMP->EVENTS_DATARDY == 0);
MrBedfordVan 0:b9164b348919 162
MrBedfordVan 0:b9164b348919 163 NRF_TEMP->EVENTS_DATARDY = 0;
MrBedfordVan 0:b9164b348919 164
MrBedfordVan 0:b9164b348919 165 processorTemperature = *TEMP;
MrBedfordVan 0:b9164b348919 166
MrBedfordVan 0:b9164b348919 167 NRF_TEMP->TASKS_STOP = 1;
MrBedfordVan 0:b9164b348919 168 }
MrBedfordVan 0:b9164b348919 169
MrBedfordVan 0:b9164b348919 170
MrBedfordVan 0:b9164b348919 171 // Record our reading...
MrBedfordVan 0:b9164b348919 172 temperature = processorTemperature / 4;
MrBedfordVan 0:b9164b348919 173
MrBedfordVan 0:b9164b348919 174 // Schedule our next sample.
MrBedfordVan 0:b9164b348919 175 sampleTime = system_timer_current_time() + samplePeriod;
MrBedfordVan 0:b9164b348919 176
MrBedfordVan 0:b9164b348919 177 // Send an event to indicate that we'e updated our temperature.
MrBedfordVan 0:b9164b348919 178 MicroBitEvent e(id, MICROBIT_THERMOMETER_EVT_UPDATE);
MrBedfordVan 0:b9164b348919 179 }
MrBedfordVan 0:b9164b348919 180
MrBedfordVan 0:b9164b348919 181 return MICROBIT_OK;
MrBedfordVan 0:b9164b348919 182 };
MrBedfordVan 0:b9164b348919 183
MrBedfordVan 0:b9164b348919 184 /**
MrBedfordVan 0:b9164b348919 185 * Periodic callback from MicroBit idle thread.
MrBedfordVan 0:b9164b348919 186 */
MrBedfordVan 0:b9164b348919 187 void MicroBitThermometer::idleTick()
MrBedfordVan 0:b9164b348919 188 {
MrBedfordVan 0:b9164b348919 189 updateSample();
MrBedfordVan 0:b9164b348919 190 }
MrBedfordVan 0:b9164b348919 191
MrBedfordVan 0:b9164b348919 192 /**
MrBedfordVan 0:b9164b348919 193 * Determines if we're due to take another temperature reading
MrBedfordVan 0:b9164b348919 194 *
MrBedfordVan 0:b9164b348919 195 * @return 1 if we're due to take a temperature reading, 0 otherwise.
MrBedfordVan 0:b9164b348919 196 */
MrBedfordVan 0:b9164b348919 197 int MicroBitThermometer::isSampleNeeded()
MrBedfordVan 0:b9164b348919 198 {
MrBedfordVan 0:b9164b348919 199 return system_timer_current_time() >= sampleTime;
MrBedfordVan 0:b9164b348919 200 }
MrBedfordVan 0:b9164b348919 201
MrBedfordVan 0:b9164b348919 202 /**
MrBedfordVan 0:b9164b348919 203 * Set the sample rate at which the temperatureis read (in ms).
MrBedfordVan 0:b9164b348919 204 *
MrBedfordVan 0:b9164b348919 205 * The default sample period is 1 second.
MrBedfordVan 0:b9164b348919 206 *
MrBedfordVan 0:b9164b348919 207 * @param period the requested time between samples, in milliseconds.
MrBedfordVan 0:b9164b348919 208 *
MrBedfordVan 0:b9164b348919 209 * @note the temperature is always read in the background, and is only updated
MrBedfordVan 0:b9164b348919 210 * when the processor is idle, or when the temperature is explicitly read.
MrBedfordVan 0:b9164b348919 211 */
MrBedfordVan 0:b9164b348919 212 void MicroBitThermometer::setPeriod(int period)
MrBedfordVan 0:b9164b348919 213 {
MrBedfordVan 0:b9164b348919 214 updateSample();
MrBedfordVan 0:b9164b348919 215 samplePeriod = period;
MrBedfordVan 0:b9164b348919 216 }
MrBedfordVan 0:b9164b348919 217
MrBedfordVan 0:b9164b348919 218 /**
MrBedfordVan 0:b9164b348919 219 * Reads the currently configured sample rate of the thermometer.
MrBedfordVan 0:b9164b348919 220 *
MrBedfordVan 0:b9164b348919 221 * @return The time between samples, in milliseconds.
MrBedfordVan 0:b9164b348919 222 */
MrBedfordVan 0:b9164b348919 223 int MicroBitThermometer::getPeriod()
MrBedfordVan 0:b9164b348919 224 {
MrBedfordVan 0:b9164b348919 225 return samplePeriod;
MrBedfordVan 0:b9164b348919 226 }
MrBedfordVan 0:b9164b348919 227
MrBedfordVan 0:b9164b348919 228 /**
MrBedfordVan 0:b9164b348919 229 * Set the value that is used to offset the raw silicon temperature.
MrBedfordVan 0:b9164b348919 230 *
MrBedfordVan 0:b9164b348919 231 * @param offset the offset for the silicon temperature
MrBedfordVan 0:b9164b348919 232 *
MrBedfordVan 0:b9164b348919 233 * @return MICROBIT_OK on success
MrBedfordVan 0:b9164b348919 234 */
MrBedfordVan 0:b9164b348919 235 int MicroBitThermometer::setOffset(int offset)
MrBedfordVan 0:b9164b348919 236 {
MrBedfordVan 0:b9164b348919 237 if(this->storage != NULL)
MrBedfordVan 0:b9164b348919 238 this->storage->put(ManagedString("tempCal"), (uint8_t *)&offset, sizeof(int));
MrBedfordVan 0:b9164b348919 239
MrBedfordVan 0:b9164b348919 240 this->offset = offset;
MrBedfordVan 0:b9164b348919 241
MrBedfordVan 0:b9164b348919 242 return MICROBIT_OK;
MrBedfordVan 0:b9164b348919 243 }
MrBedfordVan 0:b9164b348919 244
MrBedfordVan 0:b9164b348919 245 /**
MrBedfordVan 0:b9164b348919 246 * Retreive the value that is used to offset the raw silicon temperature.
MrBedfordVan 0:b9164b348919 247 *
MrBedfordVan 0:b9164b348919 248 * @return the current offset.
MrBedfordVan 0:b9164b348919 249 */
MrBedfordVan 0:b9164b348919 250 int MicroBitThermometer::getOffset()
MrBedfordVan 0:b9164b348919 251 {
MrBedfordVan 0:b9164b348919 252 return offset;
MrBedfordVan 0:b9164b348919 253 }
MrBedfordVan 0:b9164b348919 254
MrBedfordVan 0:b9164b348919 255 /**
MrBedfordVan 0:b9164b348919 256 * This member function fetches the raw silicon temperature, and calculates
MrBedfordVan 0:b9164b348919 257 * the value used to offset the raw silicon temperature based on a given temperature.
MrBedfordVan 0:b9164b348919 258 *
MrBedfordVan 0:b9164b348919 259 * @param calibrationTemp the temperature used to calculate the raw silicon temperature
MrBedfordVan 0:b9164b348919 260 * offset.
MrBedfordVan 0:b9164b348919 261 *
MrBedfordVan 0:b9164b348919 262 * @return MICROBIT_OK on success
MrBedfordVan 0:b9164b348919 263 */
MrBedfordVan 0:b9164b348919 264 int MicroBitThermometer::setCalibration(int calibrationTemp)
MrBedfordVan 0:b9164b348919 265 {
MrBedfordVan 0:b9164b348919 266 updateSample();
MrBedfordVan 0:b9164b348919 267 return setOffset(temperature - calibrationTemp);
MrBedfordVan 0:b9164b348919 268 }