Merge branch 'master' of https://www.github.com/lancaster-university/microbit-dal
This commit is contained in:
commit
3d9283b947
|
@ -76,7 +76,7 @@ const char * microbit_dal_version();
|
|||
/**
|
||||
* Disables all interrupts and user processing.
|
||||
* Displays "=(" and an accompanying status code on the default display.
|
||||
* @param statusCode the appropriate status code - 0 means no code will be displayed. Status codes must be in the range 0-255.
|
||||
* @param statusCode the appropriate status code, must be in the range 0-999.
|
||||
*
|
||||
* @code
|
||||
* microbit_panic(20);
|
||||
|
|
|
@ -43,7 +43,7 @@ DEALINGS IN THE SOFTWARE.
|
|||
#include "MicroBitComponent.h"
|
||||
|
||||
/**
|
||||
* Initialises the system wide timer.
|
||||
* Initialises a system wide timer, used to drive the various components used in the runtime.
|
||||
*
|
||||
* This must be called before any components register to receive periodic periodic callbacks.
|
||||
*
|
||||
|
@ -69,12 +69,27 @@ int system_timer_set_period(int period);
|
|||
*/
|
||||
int system_timer_get_period();
|
||||
|
||||
/**
|
||||
* Updates the current time in microseconds, since power on.
|
||||
*
|
||||
* If the mbed Timer hasn't been initialised, it will be initialised
|
||||
* on the first call to this function.
|
||||
*/
|
||||
inline void update_time();
|
||||
|
||||
/**
|
||||
* Determines the time since the device was powered on.
|
||||
*
|
||||
* @return the current time since power on in milliseconds
|
||||
*/
|
||||
unsigned long system_timer_current_time();
|
||||
uint64_t system_timer_current_time();
|
||||
|
||||
/**
|
||||
* Determines the time since the device was powered on.
|
||||
*
|
||||
* @return the current time since power on in microseconds
|
||||
*/
|
||||
uint64_t system_timer_current_time_us();
|
||||
|
||||
/**
|
||||
* Timer callback. Called from interrupt context, once per period.
|
||||
|
|
|
@ -35,7 +35,8 @@ DEALINGS IN THE SOFTWARE.
|
|||
#define IO_STATUS_ANALOG_IN 0x04 // Pin is Analog in
|
||||
#define IO_STATUS_ANALOG_OUT 0x08 // Pin is Analog out
|
||||
#define IO_STATUS_TOUCH_IN 0x10 // Pin is a makey-makey style touch sensor
|
||||
#define IO_STATUS_EVENTBUS_ENABLED 0x80 // Pin is will generate events on change
|
||||
#define IO_STATUS_EVENT_ON_EDGE 0x20 // Pin will generate events on pin change
|
||||
#define IO_STATUS_EVENT_PULSE_ON_EDGE 0x40 // Pin will generate events on pin change
|
||||
|
||||
//#defines for each edge connector pin
|
||||
#define MICROBIT_PIN_P0 P0_3 //P0 is the left most pad (ANALOG/DIGITAL) used to be P0_3 on green board
|
||||
|
@ -64,6 +65,15 @@ DEALINGS IN THE SOFTWARE.
|
|||
#define MICROBIT_PIN_DEFAULT_SERVO_RANGE 2000
|
||||
#define MICROBIT_PIN_DEFAULT_SERVO_CENTER 1500
|
||||
|
||||
#define MICROBIT_PIN_EVENT_NONE 0
|
||||
#define MICROBIT_PIN_EVENT_ON_EDGE 1
|
||||
#define MICROBIT_PIN_EVENT_ON_PULSE 2
|
||||
#define MICROBIT_PIN_EVENT_ON_TOUCH 3
|
||||
|
||||
#define MICROBIT_PIN_EVT_RISE 2
|
||||
#define MICROBIT_PIN_EVT_FALL 3
|
||||
#define MICROBIT_PIN_EVT_PULSE_HI 4
|
||||
#define MICROBIT_PIN_EVT_PULSE_LO 5
|
||||
|
||||
/**
|
||||
* Pin capabilities enum.
|
||||
|
@ -72,10 +82,8 @@ DEALINGS IN THE SOFTWARE.
|
|||
enum PinCapability{
|
||||
PIN_CAPABILITY_DIGITAL = 0x01,
|
||||
PIN_CAPABILITY_ANALOG = 0x02,
|
||||
PIN_CAPABILITY_TOUCH = 0x04,
|
||||
PIN_CAPABILITY_AD = PIN_CAPABILITY_DIGITAL | PIN_CAPABILITY_ANALOG,
|
||||
PIN_CAPABILITY_ALL = PIN_CAPABILITY_DIGITAL | PIN_CAPABILITY_ANALOG | PIN_CAPABILITY_TOUCH
|
||||
|
||||
PIN_CAPABILITY_ALL = PIN_CAPABILITY_DIGITAL | PIN_CAPABILITY_ANALOG
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -103,6 +111,43 @@ class MicroBitPin : public MicroBitComponent
|
|||
*/
|
||||
int obtainAnalogChannel();
|
||||
|
||||
/**
|
||||
* Interrupt handler for when an rise interrupt is triggered.
|
||||
*/
|
||||
void onRise();
|
||||
|
||||
/**
|
||||
* Interrupt handler for when an fall interrupt is triggered.
|
||||
*/
|
||||
void onFall();
|
||||
|
||||
/**
|
||||
* This member function manages the calculation of the timestamp of a pulse detected
|
||||
* on a pin whilst in IO_STATUS_EVENT_PULSE_ON_EDGE or IO_STATUS_EVENT_ON_EDGE modes.
|
||||
*
|
||||
* @param eventValue the event value to distribute onto the message bus.
|
||||
*/
|
||||
void pulseWidthEvent(int eventValue);
|
||||
|
||||
/**
|
||||
* This member function will construct an TimedInterruptIn instance, and configure
|
||||
* interrupts for rise and fall.
|
||||
*
|
||||
* @param eventType the specific mode used in interrupt context to determine how an
|
||||
* edge/rise is processed.
|
||||
*
|
||||
* @return MICROBIT_OK on success
|
||||
*/
|
||||
int enableRiseFallEvents(int eventType);
|
||||
|
||||
/**
|
||||
* If this pin is in a mode where the pin is generating events, it will destruct
|
||||
* the current instance attached to this MicroBitPin instance.
|
||||
*
|
||||
* @return MICROBIT_OK on success.
|
||||
*/
|
||||
int disableEvents();
|
||||
|
||||
public:
|
||||
|
||||
// mbed PinName of this pin.
|
||||
|
@ -117,7 +162,7 @@ class MicroBitPin : public MicroBitComponent
|
|||
* @param name the mbed PinName for this MicroBitPin instance.
|
||||
*
|
||||
* @param capability the capabilities this MicroBitPin instance should have.
|
||||
* (PIN_CAPABILITY_DIGITAL, PIN_CAPABILITY_ANALOG, PIN_CAPABILITY_TOUCH, PIN_CAPABILITY_AD, PIN_CAPABILITY_ALL)
|
||||
* (PIN_CAPABILITY_DIGITAL, PIN_CAPABILITY_ANALOG, PIN_CAPABILITY_AD, PIN_CAPABILITY_ALL)
|
||||
*
|
||||
* @code
|
||||
* MicroBitPin P0(MICROBIT_ID_IO_P0, MICROBIT_PIN_P0, PIN_CAPABILITY_ALL);
|
||||
|
@ -143,8 +188,9 @@ class MicroBitPin : public MicroBitComponent
|
|||
/**
|
||||
* Configures this IO pin as a digital input (if necessary) and tests its current value.
|
||||
*
|
||||
*
|
||||
* @return 1 if this input is high, 0 if input is LO, or MICROBIT_NOT_SUPPORTED
|
||||
* if the given pin does not have analog capability.
|
||||
* if the given pin does not have digital capability.
|
||||
*
|
||||
* @code
|
||||
* MicroBitPin P0(MICROBIT_ID_IO_P0, MICROBIT_PIN_P0, PIN_CAPABILITY_BOTH);
|
||||
|
@ -292,6 +338,47 @@ class MicroBitPin : public MicroBitComponent
|
|||
* given pin is not configured as an analog output.
|
||||
*/
|
||||
int getAnalogPeriod();
|
||||
|
||||
/**
|
||||
* Configures the pull of this pin.
|
||||
*
|
||||
* @param pull one of the mbed pull configurations: PullUp, PullDown, PullNone
|
||||
*
|
||||
* @return MICROBIT_NOT_SUPPORTED if the current pin configuration is anything other
|
||||
* than a digital input, otherwise MICROBIT_OK.
|
||||
*/
|
||||
int setPull(PinMode pull);
|
||||
|
||||
/**
|
||||
* Configures the events generated by this MicroBitPin instance.
|
||||
*
|
||||
* MICROBIT_PIN_EVENT_ON_EDGE - Configures this pin to a digital input, and generates events whenever a rise/fall is detected on this pin. (MICROBIT_PIN_EVT_RISE, MICROBIT_PIN_EVT_FALL)
|
||||
* MICROBIT_PIN_EVENT_ON_PULSE - Configures this pin to a digital input, and generates events where the timestamp is the duration that this pin was either HI or LO. (MICROBIT_PIN_EVT_PULSE_HI, MICROBIT_PIN_EVT_PULSE_LO)
|
||||
* MICROBIT_PIN_EVENT_ON_TOUCH - Configures this pin as a makey makey style touch sensor, in the form of a MicroBitButton. Normal button events will be generated using the ID of this pin.
|
||||
* MICROBIT_PIN_EVENT_NONE - Disables events for this pin.
|
||||
*
|
||||
* @param eventType One of: MICROBIT_PIN_EVENT_ON_EDGE, MICROBIT_PIN_EVENT_ON_PULSE, MICROBIT_PIN_EVENT_ON_TOUCH, MICROBIT_PIN_EVENT_NONE
|
||||
*
|
||||
* @code
|
||||
* MicroBitMessageBus bus;
|
||||
*
|
||||
* MicroBitPin P0(MICROBIT_ID_IO_P0, MICROBIT_PIN_P0, PIN_CAPABILITY_BOTH);
|
||||
* P0.eventOn(MICROBIT_PIN_EVENT_ON_PULSE);
|
||||
*
|
||||
* void onPulse(MicroBitEvent evt)
|
||||
* {
|
||||
* int duration = evt.timestamp;
|
||||
* }
|
||||
*
|
||||
* bus.listen(MICROBIT_ID_IO_P0, MICROBIT_PIN_EVT_PULSE_HI, onPulse, MESSAGE_BUS_LISTENER_IMMEDIATE)
|
||||
* @endcode
|
||||
*
|
||||
* @return MICROBIT_OK on success, or MICROBIT_INVALID_PARAMETER if the given eventype does not match
|
||||
*
|
||||
* @note In the MICROBIT_PIN_EVENT_ON_PULSE mode, the smallest pulse that was reliably detected was 85us, around 5khz. If more precision is required,
|
||||
* please use the InterruptIn class supplied by ARM mbed.
|
||||
*/
|
||||
int eventOn(int eventType);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Lancaster University, UK.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef TIMED_INTERRUPT_H
|
||||
#define TIMED_INTERRUPT_H
|
||||
|
||||
#include "mbed.h"
|
||||
#include "MicroBitConfig.h"
|
||||
|
||||
class TimedInterruptIn : public InterruptIn
|
||||
{
|
||||
uint64_t timestamp;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* Create an instance of TimedInterruptIn that has an additional timestamp field.
|
||||
*/
|
||||
TimedInterruptIn(PinName name);
|
||||
|
||||
/**
|
||||
* Stores the given timestamp for this instance of TimedInterruptIn.
|
||||
*
|
||||
* @param timestamp the timestamp to retain.
|
||||
*/
|
||||
void setTimestamp(uint64_t timestamp);
|
||||
|
||||
/**
|
||||
* Retrieves the retained timestamp for this instance of TimedInterruptIn.
|
||||
*
|
||||
* @return the timestamp held by this instance.
|
||||
*/
|
||||
uint64_t getTimestamp();
|
||||
};
|
||||
|
||||
#endif
|
|
@ -300,9 +300,10 @@ class ManagedString
|
|||
ManagedString substring(int16_t start, int16_t length);
|
||||
|
||||
/**
|
||||
* Concatenates this string with the one provided.
|
||||
* Concatenates two strings.
|
||||
*
|
||||
* @param s The ManagedString to concatenate.
|
||||
* @param lhs The first ManagedString to concatenate.
|
||||
* @param rhs The second ManagedString to concatenate.
|
||||
*
|
||||
* @return a new ManagedString representing the joined strings.
|
||||
*
|
||||
|
@ -314,7 +315,7 @@ class ManagedString
|
|||
* display.scroll(s + p) // scrolls "abcdefgh"
|
||||
* @endcode
|
||||
*/
|
||||
ManagedString operator+ (ManagedString& s);
|
||||
friend ManagedString operator+ (const ManagedString& lhs, const ManagedString& rhs);
|
||||
|
||||
/**
|
||||
* Provides a character value at a given position in the string, indexed from zero.
|
||||
|
|
|
@ -52,7 +52,7 @@ class MicroBitEvent
|
|||
|
||||
uint16_t source; // ID of the MicroBit Component that generated the event e.g. MICROBIT_ID_BUTTON_A.
|
||||
uint16_t value; // Component specific code indicating the cause of the event.
|
||||
uint32_t timestamp; // Time at which the event was generated. ms since power on.
|
||||
uint64_t timestamp; // Time at which the event was generated. us since power on.
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "microbit-dal",
|
||||
"version": "2.0.0-rc2",
|
||||
"version": "2.0.0-rc3",
|
||||
"license": "MIT",
|
||||
"description": "The runtime library for the BBC micro:bit, developed by Lancaster University",
|
||||
"keywords": [
|
||||
|
|
|
@ -40,6 +40,7 @@ set(YOTTA_AUTO_MICROBIT-DAL_CPP_FILES
|
|||
"drivers/MicroBitSerial.cpp"
|
||||
"drivers/MicroBitStorage.cpp"
|
||||
"drivers/MicroBitThermometer.cpp"
|
||||
"drivers/TimedInterruptIn.cpp"
|
||||
|
||||
"bluetooth/MicroBitAccelerometerService.cpp"
|
||||
"bluetooth/MicroBitBLEManager.cpp"
|
||||
|
|
|
@ -159,7 +159,7 @@ void microbit_panic_timeout(int iterations)
|
|||
/**
|
||||
* Disables all interrupts and user processing.
|
||||
* Displays "=(" and an accompanying status code on the default display.
|
||||
* @param statusCode the appropriate status code - 0 means no code will be displayed. Status codes must be in the range 0-255.
|
||||
* @param statusCode the appropriate status code, must be in the range 0-999.
|
||||
*
|
||||
* @code
|
||||
* microbit_panic(20);
|
||||
|
@ -186,19 +186,18 @@ void microbit_panic(int statusCode)
|
|||
|
||||
PortOut LEDMatrix(Port0, row_mask | col_mask);
|
||||
|
||||
if(statusCode < 0 || statusCode > 255)
|
||||
if(statusCode < 0 || statusCode > 999)
|
||||
statusCode = 0;
|
||||
|
||||
__disable_irq(); //stop ALL interrupts
|
||||
|
||||
|
||||
//point to the font stored in Flash
|
||||
const unsigned char * fontLocation = MicroBitFont::defaultFont;
|
||||
const unsigned char* fontLocation = MicroBitFont::defaultFont;
|
||||
|
||||
//get individual digits of status code, and place it into a single array/
|
||||
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)};
|
||||
|
||||
//enter infinite loop.
|
||||
while(count)
|
||||
{
|
||||
//iterate through our chars :)
|
||||
|
@ -234,10 +233,13 @@ void microbit_panic(int statusCode)
|
|||
|
||||
col_data = ~col_data << microbitMatrixMap.columnStart & col_mask;
|
||||
|
||||
LEDMatrix = col_data | row_data;
|
||||
if(chars[characterCount] == chars[(characterCount - 1) % MICROBIT_PANIC_ERROR_CHARS] && outerCount < 50)
|
||||
LEDMatrix = 0;
|
||||
else
|
||||
LEDMatrix = col_data | row_data;
|
||||
|
||||
//burn cycles
|
||||
i = 1000;
|
||||
i = 2000;
|
||||
while(i>0)
|
||||
{
|
||||
// Check if the reset button has been pressed. Interrupts are disabled, so the normal method can't be relied upon...
|
||||
|
|
|
@ -42,18 +42,21 @@ DEALINGS IN THE SOFTWARE.
|
|||
* Time since power on. Measured in milliseconds.
|
||||
* When stored as an unsigned long, this gives us approx 50 days between rollover, which is ample. :-)
|
||||
*/
|
||||
static unsigned long ticks = 0;
|
||||
static uint64_t time_us = 0;
|
||||
static unsigned int tick_period = 0;
|
||||
|
||||
// Array of components which are iterated during a system tick
|
||||
static MicroBitComponent* systemTickComponents[MICROBIT_SYSTEM_COMPONENTS];
|
||||
|
||||
// Periodic callback interrupt
|
||||
static Ticker *timer = NULL;
|
||||
static Ticker *ticker = NULL;
|
||||
|
||||
// System timer.
|
||||
static Timer *timer = NULL;
|
||||
|
||||
|
||||
/**
|
||||
* Initialises the system wide timer.
|
||||
* Initialises a system wide timer, used to drive the various components used in the runtime.
|
||||
*
|
||||
* This must be called before any components register to receive periodic periodic callbacks.
|
||||
*
|
||||
|
@ -63,8 +66,14 @@ static Ticker *timer = NULL;
|
|||
*/
|
||||
int system_timer_init(int period)
|
||||
{
|
||||
if (ticker == NULL)
|
||||
ticker = new Ticker();
|
||||
|
||||
if (timer == NULL)
|
||||
timer = new Ticker();
|
||||
{
|
||||
timer = new Timer();
|
||||
timer->start();
|
||||
}
|
||||
|
||||
return system_timer_set_period(period);
|
||||
}
|
||||
|
@ -83,11 +92,11 @@ int system_timer_set_period(int period)
|
|||
|
||||
// If a timer is already running, ensure it is disabled before reconfiguring.
|
||||
if (tick_period)
|
||||
timer->detach();
|
||||
ticker->detach();
|
||||
|
||||
// register a period callback to drive the scheduler and any other registered components.
|
||||
tick_period = period;
|
||||
timer->attach_us(system_timer_tick, period * 1000);
|
||||
ticker->attach_us(system_timer_tick, period * 1000);
|
||||
|
||||
return MICROBIT_OK;
|
||||
}
|
||||
|
@ -102,14 +111,41 @@ int system_timer_get_period()
|
|||
return tick_period;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the current time in microseconds, since power on.
|
||||
*
|
||||
* If the mbed Timer hasn't been initialised, it will be initialised
|
||||
* on the first call to this function.
|
||||
*/
|
||||
void update_time()
|
||||
{
|
||||
// If we haven't been initialized, bring up the timer with the default period.
|
||||
if (timer == NULL || ticker == NULL)
|
||||
system_timer_init(SYSTEM_TICK_PERIOD_MS);
|
||||
|
||||
time_us += timer->read_us();
|
||||
timer->reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the time since the device was powered on.
|
||||
*
|
||||
* @return the current time since power on in milliseconds
|
||||
*/
|
||||
unsigned long system_timer_current_time()
|
||||
uint64_t system_timer_current_time()
|
||||
{
|
||||
return ticks;
|
||||
return system_timer_current_time_us() / 1000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the time since the device was powered on.
|
||||
*
|
||||
* @return the current time since power on in microseconds
|
||||
*/
|
||||
uint64_t system_timer_current_time_us()
|
||||
{
|
||||
update_time();
|
||||
return time_us;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -120,8 +156,7 @@ unsigned long system_timer_current_time()
|
|||
*/
|
||||
void system_timer_tick()
|
||||
{
|
||||
// increment our real-time counter.
|
||||
ticks += system_timer_get_period();
|
||||
update_time();
|
||||
|
||||
// Update any components registered for a callback
|
||||
for(int i = 0; i < MICROBIT_SYSTEM_COMPONENTS; i++)
|
||||
|
@ -144,7 +179,7 @@ int system_timer_add_component(MicroBitComponent *component)
|
|||
int i = 0;
|
||||
|
||||
// If we haven't been initialized, bring up the timer with the default period.
|
||||
if (timer == NULL)
|
||||
if (timer == NULL || ticker == NULL)
|
||||
system_timer_init(SYSTEM_TICK_PERIOD_MS);
|
||||
|
||||
while(systemTickComponents[i] != NULL && i < MICROBIT_SYSTEM_COMPONENTS)
|
||||
|
|
|
@ -31,6 +31,8 @@ DEALINGS IN THE SOFTWARE.
|
|||
#include "MicroBitConfig.h"
|
||||
#include "MicroBitPin.h"
|
||||
#include "MicroBitButton.h"
|
||||
#include "MicroBitSystemTimer.h"
|
||||
#include "TimedInterruptIn.h"
|
||||
#include "DynamicPwm.h"
|
||||
#include "ErrorNo.h"
|
||||
|
||||
|
@ -43,7 +45,7 @@ DEALINGS IN THE SOFTWARE.
|
|||
* @param name the mbed PinName for this MicroBitPin instance.
|
||||
*
|
||||
* @param capability the capabilities this MicroBitPin instance should have.
|
||||
* (PIN_CAPABILITY_DIGITAL, PIN_CAPABILITY_ANALOG, PIN_CAPABILITY_TOUCH, PIN_CAPABILITY_AD, PIN_CAPABILITY_ALL)
|
||||
* (PIN_CAPABILITY_DIGITAL, PIN_CAPABILITY_ANALOG, PIN_CAPABILITY_AD, PIN_CAPABILITY_ALL)
|
||||
*
|
||||
* @code
|
||||
* MicroBitPin P0(MICROBIT_ID_IO_P0, MICROBIT_PIN_P0, PIN_CAPABILITY_ALL);
|
||||
|
@ -92,8 +94,11 @@ void MicroBitPin::disconnect()
|
|||
if (status & IO_STATUS_TOUCH_IN)
|
||||
delete ((MicroBitButton *)pin);
|
||||
|
||||
if ((status & IO_STATUS_EVENT_ON_EDGE) || (status & IO_STATUS_EVENT_PULSE_ON_EDGE))
|
||||
delete ((TimedInterruptIn *)pin);
|
||||
|
||||
this->pin = NULL;
|
||||
this->status = status & IO_STATUS_EVENTBUS_ENABLED; //retain event bus status
|
||||
this->status = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -135,8 +140,9 @@ int MicroBitPin::setDigitalValue(int value)
|
|||
/**
|
||||
* Configures this IO pin as a digital input (if necessary) and tests its current value.
|
||||
*
|
||||
*
|
||||
* @return 1 if this input is high, 0 if input is LO, or MICROBIT_NOT_SUPPORTED
|
||||
* if the given pin does not have analog capability.
|
||||
* if the given pin does not have digital capability.
|
||||
*
|
||||
* @code
|
||||
* MicroBitPin P0(MICROBIT_ID_IO_P0, MICROBIT_PIN_P0, PIN_CAPABILITY_BOTH);
|
||||
|
@ -150,12 +156,16 @@ int MicroBitPin::getDigitalValue()
|
|||
return MICROBIT_NOT_SUPPORTED;
|
||||
|
||||
// Move into a Digital input state if necessary.
|
||||
if (!(status & IO_STATUS_DIGITAL_IN)){
|
||||
if (!(status & (IO_STATUS_DIGITAL_IN | IO_STATUS_EVENT_ON_EDGE | IO_STATUS_EVENT_PULSE_ON_EDGE)))
|
||||
{
|
||||
disconnect();
|
||||
pin = new DigitalIn(name,PullDown);
|
||||
status |= IO_STATUS_DIGITAL_IN;
|
||||
}
|
||||
|
||||
if(status & (IO_STATUS_EVENT_ON_EDGE | IO_STATUS_EVENT_PULSE_ON_EDGE))
|
||||
return ((TimedInterruptIn *)pin)->read();
|
||||
|
||||
return ((DigitalIn *)pin)->read();
|
||||
}
|
||||
|
||||
|
@ -332,7 +342,7 @@ int MicroBitPin::isAnalog()
|
|||
int MicroBitPin::isTouched()
|
||||
{
|
||||
//check if this pin has a touch mode...
|
||||
if(!(PIN_CAPABILITY_TOUCH & capability))
|
||||
if(!(PIN_CAPABILITY_DIGITAL & capability))
|
||||
return MICROBIT_NOT_SUPPORTED;
|
||||
|
||||
// Move into a touch input state if necessary.
|
||||
|
@ -430,3 +440,173 @@ int MicroBitPin::getAnalogPeriod()
|
|||
{
|
||||
return getAnalogPeriodUs()/1000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the pull of this pin.
|
||||
*
|
||||
* @param pull one of the mbed pull configurations: PullUp, PullDown, PullNone
|
||||
*
|
||||
* @return MICROBIT_NOT_SUPPORTED if the current pin configuration is anything other
|
||||
* than a digital input, otherwise MICROBIT_OK.
|
||||
*/
|
||||
int MicroBitPin::setPull(PinMode pull)
|
||||
{
|
||||
if ((status & IO_STATUS_DIGITAL_IN))
|
||||
{
|
||||
((DigitalIn *)pin)->mode(pull);
|
||||
return MICROBIT_OK;
|
||||
}
|
||||
|
||||
if((status & IO_STATUS_EVENT_ON_EDGE) || (status & IO_STATUS_EVENT_PULSE_ON_EDGE))
|
||||
{
|
||||
((TimedInterruptIn *)pin)->mode(pull);
|
||||
return MICROBIT_OK;
|
||||
}
|
||||
|
||||
return MICROBIT_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* This member function manages the calculation of the timestamp of a pulse detected
|
||||
* on a pin whilst in IO_STATUS_EVENT_PULSE_ON_EDGE or IO_STATUS_EVENT_ON_EDGE modes.
|
||||
*
|
||||
* @param eventValue the event value to distribute onto the message bus.
|
||||
*/
|
||||
void MicroBitPin::pulseWidthEvent(int eventValue)
|
||||
{
|
||||
MicroBitEvent evt(id, eventValue, CREATE_ONLY);
|
||||
uint64_t now = evt.timestamp;
|
||||
uint64_t previous = ((TimedInterruptIn *)pin)->getTimestamp();
|
||||
|
||||
if (previous != 0)
|
||||
{
|
||||
evt.timestamp -= previous;
|
||||
evt.fire();
|
||||
}
|
||||
|
||||
((TimedInterruptIn *)pin)->setTimestamp(now);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interrupt handler for when an rise interrupt is triggered.
|
||||
*/
|
||||
void MicroBitPin::onRise()
|
||||
{
|
||||
if(status & IO_STATUS_EVENT_PULSE_ON_EDGE)
|
||||
pulseWidthEvent(MICROBIT_PIN_EVT_PULSE_LO);
|
||||
|
||||
if(status & IO_STATUS_EVENT_ON_EDGE)
|
||||
MicroBitEvent(id, MICROBIT_PIN_EVT_RISE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interrupt handler for when an fall interrupt is triggered.
|
||||
*/
|
||||
void MicroBitPin::onFall()
|
||||
{
|
||||
if(status & IO_STATUS_EVENT_PULSE_ON_EDGE)
|
||||
pulseWidthEvent(MICROBIT_PIN_EVT_PULSE_HI);
|
||||
|
||||
if(status & IO_STATUS_EVENT_ON_EDGE)
|
||||
MicroBitEvent(id, MICROBIT_PIN_EVT_FALL);
|
||||
}
|
||||
|
||||
/**
|
||||
* This member function will construct an TimedInterruptIn instance, and configure
|
||||
* interrupts for rise and fall.
|
||||
*
|
||||
* @param eventType the specific mode used in interrupt context to determine how an
|
||||
* edge/rise is processed.
|
||||
*
|
||||
* @return MICROBIT_OK on success
|
||||
*/
|
||||
int MicroBitPin::enableRiseFallEvents(int eventType)
|
||||
{
|
||||
// if we are in neither of the two modes, configure pin as a TimedInterruptIn.
|
||||
if (!(status & (IO_STATUS_EVENT_ON_EDGE | IO_STATUS_EVENT_PULSE_ON_EDGE)))
|
||||
{
|
||||
disconnect();
|
||||
pin = new TimedInterruptIn(name);
|
||||
|
||||
((TimedInterruptIn *)pin)->mode(PullDown);
|
||||
((TimedInterruptIn *)pin)->rise(this, &MicroBitPin::onRise);
|
||||
((TimedInterruptIn *)pin)->fall(this, &MicroBitPin::onFall);
|
||||
}
|
||||
|
||||
status &= ~(IO_STATUS_EVENT_ON_EDGE | IO_STATUS_EVENT_PULSE_ON_EDGE);
|
||||
|
||||
// set our status bits accordingly.
|
||||
if(eventType == MICROBIT_PIN_EVENT_ON_EDGE)
|
||||
status |= IO_STATUS_EVENT_ON_EDGE;
|
||||
else if(eventType == MICROBIT_PIN_EVENT_ON_PULSE)
|
||||
status |= IO_STATUS_EVENT_PULSE_ON_EDGE;
|
||||
|
||||
return MICROBIT_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* If this pin is in a mode where the pin is generating events, it will destruct
|
||||
* the current instance attached to this MicroBitPin instance.
|
||||
*
|
||||
* @return MICROBIT_OK on success.
|
||||
*/
|
||||
int MicroBitPin::disableEvents()
|
||||
{
|
||||
if (status & (IO_STATUS_EVENT_ON_EDGE | IO_STATUS_EVENT_PULSE_ON_EDGE | IO_STATUS_TOUCH_IN))
|
||||
disconnect();
|
||||
|
||||
return MICROBIT_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the events generated by this MicroBitPin instance.
|
||||
*
|
||||
* MICROBIT_PIN_EVENT_ON_EDGE - Configures this pin to a digital input, and generates events whenever a rise/fall is detected on this pin. (MICROBIT_PIN_EVT_RISE, MICROBIT_PIN_EVT_FALL)
|
||||
* MICROBIT_PIN_EVENT_ON_PULSE - Configures this pin to a digital input, and generates events where the timestamp is the duration that this pin was either HI or LO. (MICROBIT_PIN_EVT_PULSE_HI, MICROBIT_PIN_EVT_PULSE_LO)
|
||||
* MICROBIT_PIN_EVENT_ON_TOUCH - Configures this pin as a makey makey style touch sensor, in the form of a MicroBitButton. Normal button events will be generated using the ID of this pin.
|
||||
* MICROBIT_PIN_EVENT_NONE - Disables events for this pin.
|
||||
*
|
||||
* @param eventType One of: MICROBIT_PIN_EVENT_ON_EDGE, MICROBIT_PIN_EVENT_ON_PULSE, MICROBIT_PIN_EVENT_ON_TOUCH, MICROBIT_PIN_EVENT_NONE
|
||||
*
|
||||
* @code
|
||||
* MicroBitMessageBus bus;
|
||||
*
|
||||
* MicroBitPin P0(MICROBIT_ID_IO_P0, MICROBIT_PIN_P0, PIN_CAPABILITY_BOTH);
|
||||
* P0.eventOn(MICROBIT_PIN_EVENT_ON_PULSE);
|
||||
*
|
||||
* void onPulse(MicroBitEvent evt)
|
||||
* {
|
||||
* int duration = evt.timestamp;
|
||||
* }
|
||||
*
|
||||
* bus.listen(MICROBIT_ID_IO_P0, MICROBIT_PIN_EVT_PULSE_HI, onPulse, MESSAGE_BUS_LISTENER_IMMEDIATE)
|
||||
* @endcode
|
||||
*
|
||||
* @return MICROBIT_OK on success, or MICROBIT_INVALID_PARAMETER if the given eventype does not match
|
||||
*
|
||||
* @note In the MICROBIT_PIN_EVENT_ON_PULSE mode, the smallest pulse that was reliably detected was 85us, around 5khz. If more precision is required,
|
||||
* please use the InterruptIn class supplied by ARM mbed.
|
||||
*/
|
||||
int MicroBitPin::eventOn(int eventType)
|
||||
{
|
||||
switch(eventType)
|
||||
{
|
||||
case MICROBIT_PIN_EVENT_ON_EDGE:
|
||||
case MICROBIT_PIN_EVENT_ON_PULSE:
|
||||
enableRiseFallEvents(eventType);
|
||||
break;
|
||||
|
||||
case MICROBIT_PIN_EVENT_ON_TOUCH:
|
||||
isTouched();
|
||||
break;
|
||||
|
||||
case MICROBIT_PIN_EVENT_NONE:
|
||||
disableEvents();
|
||||
break;
|
||||
|
||||
default:
|
||||
return MICROBIT_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
return MICROBIT_OK;
|
||||
}
|
||||
|
|
|
@ -489,9 +489,17 @@ int MicroBitSerial::send(uint8_t *buffer, int bufferLen, MicroBitSerialMode mode
|
|||
return result;
|
||||
}
|
||||
|
||||
int bytesWritten = setTxInterrupt(buffer, bufferLen, mode);
|
||||
bool complete = false;
|
||||
int bytesWritten = 0;
|
||||
|
||||
send(mode);
|
||||
while(!complete)
|
||||
{
|
||||
bytesWritten += setTxInterrupt(buffer + bytesWritten, bufferLen - bytesWritten, mode);
|
||||
send(mode);
|
||||
|
||||
if(mode == ASYNC || bytesWritten >= bufferLen)
|
||||
complete = true;
|
||||
}
|
||||
|
||||
unlockTx();
|
||||
|
||||
|
|
|
@ -223,6 +223,16 @@ int MicroBitStorage::put(const char *key, uint8_t *data, int dataSize)
|
|||
if(keySize > (int)sizeof(pair.key) || dataSize > (int)sizeof(pair.value) || dataSize < 0)
|
||||
return MICROBIT_INVALID_PARAMETER;
|
||||
|
||||
KeyValuePair *currentValue = get(key);
|
||||
|
||||
int upToDate = currentValue && (memcmp(currentValue->value, data, dataSize) == 0);
|
||||
|
||||
if(currentValue)
|
||||
delete currentValue;
|
||||
|
||||
if(upToDate)
|
||||
return MICROBIT_OK;
|
||||
|
||||
memcpy(pair.key, key, keySize);
|
||||
memcpy(pair.value, data, dataSize);
|
||||
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Lancaster University, UK.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "MicroBitConfig.h"
|
||||
#include "TimedInterruptIn.h"
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* Create an instance of TimedInterruptIn that has an additional timestamp field.
|
||||
*/
|
||||
TimedInterruptIn::TimedInterruptIn(PinName name) : InterruptIn(name)
|
||||
{
|
||||
timestamp = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the given timestamp for this instance of TimedInterruptIn.
|
||||
*
|
||||
* @param timestamp the timestamp to retain.
|
||||
*/
|
||||
void TimedInterruptIn::setTimestamp(uint64_t timestamp)
|
||||
{
|
||||
this->timestamp = timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the retained timestamp for this instance of TimedInterruptIn.
|
||||
*
|
||||
* @return the timestamp held by this instance.
|
||||
*/
|
||||
uint64_t TimedInterruptIn::getTimestamp()
|
||||
{
|
||||
return timestamp;
|
||||
}
|
|
@ -437,9 +437,10 @@ ManagedString ManagedString::substring(int16_t start, int16_t length)
|
|||
}
|
||||
|
||||
/**
|
||||
* Concatenates this string with the one provided.
|
||||
* Concatenates two strings.
|
||||
*
|
||||
* @param s The ManagedString to concatenate.
|
||||
* @param lhs The first ManagedString to concatenate.
|
||||
* @param rhs The second ManagedString to concatenate.
|
||||
*
|
||||
* @return a new ManagedString representing the joined strings.
|
||||
*
|
||||
|
@ -451,16 +452,17 @@ ManagedString ManagedString::substring(int16_t start, int16_t length)
|
|||
* display.scroll(s + p) // scrolls "abcdefgh"
|
||||
* @endcode
|
||||
*/
|
||||
ManagedString ManagedString::operator+ (ManagedString& s)
|
||||
ManagedString operator+ (const ManagedString& lhs, const ManagedString& rhs)
|
||||
{
|
||||
// If the other string is empty, nothing to do!
|
||||
if(s.length() == 0)
|
||||
return *this;
|
||||
|
||||
if (length() == 0)
|
||||
return s;
|
||||
// If the either string is empty, nothing to do!
|
||||
if (rhs.length() == 0)
|
||||
return lhs;
|
||||
|
||||
return ManagedString(*this, s);
|
||||
if (lhs.length() == 0)
|
||||
return rhs;
|
||||
|
||||
return ManagedString(lhs, rhs);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ MicroBitEvent::MicroBitEvent(uint16_t source, uint16_t value, MicroBitEventLaunc
|
|||
{
|
||||
this->source = source;
|
||||
this->value = value;
|
||||
this->timestamp = system_timer_current_time();
|
||||
this->timestamp = system_timer_current_time_us();
|
||||
|
||||
if(mode != CREATE_ONLY)
|
||||
this->fire();
|
||||
|
@ -71,7 +71,7 @@ MicroBitEvent::MicroBitEvent()
|
|||
{
|
||||
this->source = 0;
|
||||
this->value = 0;
|
||||
this->timestamp = system_timer_current_time();
|
||||
this->timestamp = system_timer_current_time_us();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue