2015-09-28 20:40:44 +00:00
|
|
|
#include "MicroBit.h"
|
2015-10-30 20:20:51 +00:00
|
|
|
|
|
|
|
/**
|
2015-11-18 23:13:57 +00:00
|
|
|
* Turn off warnings under gcc -Wall. We turn off unused-function for the
|
|
|
|
* entire compilation unit as the compiler can't tell if a function is
|
|
|
|
* unused until the end of the unit. The macro expansion for SVCALL()
|
|
|
|
* in nrf_soc.h and nrf_srv.h tries to leave unused-function turned off,
|
|
|
|
* but we restore the state from before the include with our diagnostics
|
|
|
|
* pop.
|
|
|
|
* It might be cleaner to add
|
2015-10-30 20:20:51 +00:00
|
|
|
* #pragram GCC system header
|
|
|
|
* as the first line of nrf_soc.h, but that's a different
|
|
|
|
* module ...
|
|
|
|
*/
|
2015-11-08 18:04:17 +00:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The underlying Nordic libraries that support BLE do not compile cleanly with the stringent GCC settings we employ
|
|
|
|
* If we're compiling under GCC, then we suppress any warnings generated from this code (but not the rest of the DAL)
|
|
|
|
* The ARM cc compiler is more tolerant. We don't test __GNUC__ here to detect GCC as ARMCC also typically sets this
|
|
|
|
* as a compatability option, but does not support the options used...
|
|
|
|
*/
|
|
|
|
#if !defined(__arm)
|
2015-11-01 19:23:47 +00:00
|
|
|
#pragma GCC diagnostic ignored "-Wunused-function"
|
|
|
|
#pragma GCC diagnostic push
|
2015-10-30 20:20:51 +00:00
|
|
|
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
2015-11-08 18:04:17 +00:00
|
|
|
#endif
|
|
|
|
|
2015-09-28 20:40:44 +00:00
|
|
|
#include "nrf_soc.h"
|
2015-11-23 19:46:20 +00:00
|
|
|
#include "nrf_sdm.h"
|
2015-11-08 18:04:17 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Return to our predefined compiler settings.
|
|
|
|
*/
|
|
|
|
#if !defined(__arm)
|
2015-11-01 19:23:47 +00:00
|
|
|
#pragma GCC diagnostic pop
|
2015-11-08 18:04:17 +00:00
|
|
|
#endif
|
2015-09-28 20:40:44 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructor.
|
|
|
|
* Create new object that can sense temperature.
|
|
|
|
* @param id the ID of the new MicroBitThermometer object.
|
|
|
|
*
|
|
|
|
* Example:
|
|
|
|
* @code
|
|
|
|
* thermometer(MICROBIT_ID_THERMOMETER);
|
|
|
|
* @endcode
|
|
|
|
*
|
|
|
|
* Possible Events:
|
|
|
|
* @code
|
|
|
|
* MICROBIT_THERMOMETER_EVT_CHANGED
|
|
|
|
* @endcode
|
|
|
|
*/
|
|
|
|
MicroBitThermometer::MicroBitThermometer(uint16_t id)
|
|
|
|
{
|
|
|
|
this->id = id;
|
|
|
|
this->samplePeriod = MICROBIT_THERMOMETER_PERIOD;
|
|
|
|
this->sampleTime = 0;
|
|
|
|
|
2015-11-23 19:46:20 +00:00
|
|
|
// If we're running under a fiber scheduer, register ourselves for a periodic callback to keep our data up to date.
|
|
|
|
// Otherwise, we do just do this on demand, when polled through our read() interface.
|
|
|
|
fiber_add_idle_component(this);
|
2015-09-28 20:40:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets the current temperature of the microbit.
|
|
|
|
* @return the current temperature, in degrees celsius.
|
|
|
|
*
|
|
|
|
* Example:
|
|
|
|
* @code
|
|
|
|
* uBit.thermometer.getTemperature();
|
|
|
|
* @endcode
|
|
|
|
*/
|
|
|
|
int MicroBitThermometer::getTemperature()
|
|
|
|
{
|
|
|
|
if (isSampleNeeded())
|
|
|
|
updateTemperature();
|
|
|
|
|
|
|
|
return temperature;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Indicates if we'd like some processor time to sense the temperature. 0 means we're not due to read the tmeperature yet.
|
|
|
|
* @returns 1 if we'd like some processor time, 0 otherwise.
|
|
|
|
*/
|
|
|
|
int MicroBitThermometer::isIdleCallbackNeeded()
|
|
|
|
{
|
|
|
|
return isSampleNeeded();
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
* periodic callback.
|
|
|
|
* Check once every second or so for a new temperature reading.
|
|
|
|
*/
|
|
|
|
void MicroBitThermometer::idleTick()
|
|
|
|
{
|
|
|
|
if (isSampleNeeded())
|
|
|
|
updateTemperature();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2016-03-10 17:01:17 +00:00
|
|
|
* Determines if we're due to take another temperature reading
|
2015-09-28 20:40:44 +00:00
|
|
|
* @return 1 if we're due to take a temperature reading, 0 otherwise.
|
|
|
|
*/
|
|
|
|
int MicroBitThermometer::isSampleNeeded()
|
|
|
|
{
|
2016-03-10 17:01:17 +00:00
|
|
|
return system_timer_current_time() >= sampleTime;
|
2015-09-28 20:40:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the sample rate at which the temperatureis read (in ms).
|
|
|
|
* n.b. the temperature is alwasy read in the background, so wis only updated
|
|
|
|
* when the processor is idle, or when the temperature is explicitly read.
|
|
|
|
* The default sample period is 1 second.
|
|
|
|
* @param period the requested time between samples, in milliseconds.
|
|
|
|
*/
|
|
|
|
void MicroBitThermometer::setPeriod(int period)
|
|
|
|
{
|
|
|
|
samplePeriod = period;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Reads the currently configured sample rate of the thermometer.
|
|
|
|
* @return The time between samples, in milliseconds.
|
|
|
|
*/
|
|
|
|
int MicroBitThermometer::getPeriod()
|
|
|
|
{
|
|
|
|
return samplePeriod;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Updates our recorded temperature from the many sensors on the micro:bit!
|
|
|
|
*/
|
|
|
|
void MicroBitThermometer::updateTemperature()
|
|
|
|
{
|
|
|
|
int32_t processorTemperature;
|
2015-11-23 19:46:20 +00:00
|
|
|
uint8_t sd_enabled;
|
2015-09-28 20:40:44 +00:00
|
|
|
|
|
|
|
// For now, we just rely on the nrf senesor to be the most accurate.
|
|
|
|
// The compass module also has a temperature sensor, and has the lowest power consumption, so will run the cooler...
|
|
|
|
// ...however it isn't trimmed for accuracy during manufacture, so requires calibration.
|
|
|
|
|
2015-11-23 19:46:20 +00:00
|
|
|
sd_softdevice_is_enabled(&sd_enabled);
|
|
|
|
|
|
|
|
if (sd_enabled)
|
2015-09-28 20:40:44 +00:00
|
|
|
{
|
|
|
|
// If Bluetooth is enabled, we need to go through the Nordic software to safely do this
|
|
|
|
sd_temp_get(&processorTemperature);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Othwerwise, we access the information directly...
|
|
|
|
uint32_t *TEMP = (uint32_t *)0x4000C508;
|
|
|
|
|
|
|
|
NRF_TEMP->TASKS_START = 1;
|
|
|
|
|
|
|
|
while (NRF_TEMP->EVENTS_DATARDY == 0);
|
|
|
|
|
|
|
|
NRF_TEMP->EVENTS_DATARDY = 0;
|
|
|
|
|
|
|
|
processorTemperature = *TEMP;
|
|
|
|
|
|
|
|
NRF_TEMP->TASKS_STOP = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Record our reading...
|
|
|
|
temperature = processorTemperature / 4;
|
|
|
|
|
|
|
|
// Schedule our next sample.
|
2016-03-10 17:01:17 +00:00
|
|
|
sampleTime = system_timer_current_time() + samplePeriod;
|
2015-09-28 20:40:44 +00:00
|
|
|
|
|
|
|
// Send an event to indicate that we'e updated our temperature.
|
|
|
|
MicroBitEvent e(id, MICROBIT_THERMOMETER_EVT_UPDATE);
|
|
|
|
}
|
|
|
|
|
|
|
|
|