microbit: First cut at updates to provide tight validation within the runtime code, with a view to moving

NOP/clamping behaviour out of teh micro:bit runtime and into the glue layers of higher level
languages.

 - Updates to many functions to provide explicut return codes.
 - Updates to many functions to remove heuristic calidation (NOP/clamping/defaults)
 - Updates to ErrorNo.h to provide clearer return values, and place return values in a better scope
 - Updates to MicroBitDisplay to use enums where appropriate.
This commit is contained in:
Joe Finney 2015-10-25 21:51:33 +00:00
parent bfe1b4db53
commit 823a956d68
24 changed files with 783 additions and 440 deletions

View File

@ -3,20 +3,37 @@
/**
* Error codes used in the micro:bit runtime.
* These may be returned from functions implemented in the micro:bit runtime.
*/
enum Error{
// Invalid parameter given.
MICROBIT_INVALID_VALUE = -1,
enum ErrorCode{
// Invalid I/O operation requested.
MICROBIT_IO_OP_NA = -2,
// No error occurred.
MICROBIT_OK = 0,
// Invalid parameter given.
MICROBIT_INVALID_PARAMETER = -1001,
// Requested operation is unspupported.
MICROBIT_NOT_SUPPORTED = -1002,
// Device calibration errors
MICROBIT_COMPASS_IS_CALIBRATING = -3,
MICROBIT_COMPASS_CALIBRATE_REQUIRED = -4,
MICROBIT_CALIBRATION_IN_PROGRESS = -1003,
MICROBIT_CALIBRATION_REQUIRED = -1004,
// The requested operation could not be performed as the device has run out of some essential resource (e.g. allocated memory)
MICROBIT_NO_RESOURCES = -1005,
// I2C Communication error occured (typically I2C module on processor has locked up.)
MICROBIT_I2C_LOCKUP = 10,
MICROBIT_I2C_ERROR = -1010
};
/**
* Error codes used in the micro:bit runtime.
*/
enum PanicCode{
// PANIC Codes. These are not return codes, but are terminal conditions.
// These induce a panic operation, where all code stops executing, and a panic state is
// entered where the panic code is diplayed.
// Out out memory error. Heap storage was requested, but is not available.
MICROBIT_OOM = 20,

View File

@ -191,13 +191,14 @@ class MicroBit
* @note Values of 6 and below tend to lose resolution - do you really need to sleep for this short amount of time?
*
* @param milliseconds the amount of time, in ms, to wait for. This number cannot be negative.
* @return MICROBIT_OK on success, MICROBIT_INVALID_PARAMETER milliseconds is less than zero.
*
* Example:
* @code
* uBit.sleep(20); //sleep for 20ms
* @endcode
*/
void sleep(int milliseconds);
int sleep(int milliseconds);
/**
* Generate a random number in the given range.
@ -205,7 +206,7 @@ class MicroBit
* TODO: Determine if we want to, given its relatively high power consumption!
*
* @param max the upper range to generate a number for. This number cannot be negative
* @return A random, natural number between 0 and the max-1. Or MICROBIT_INVALID_VALUE (defined in ErrorNo.h) if max is <= 0.
* @return A random, natural number between 0 and the max-1. Or MICROBIT_INVALID_PARAMETER if max is <= 0.
*
* Example:
* @code
@ -227,24 +228,33 @@ class MicroBit
/**
* add a component to the array of system components which invocate the systemTick member function during a systemTick
*
* @param component The component to add.
* @return MICROBIT_OK on success. MICROBIT_NO_RESOURCES is returned if further components cannot be supported.
*/
void addSystemComponent(MicroBitComponent *component);
int addSystemComponent(MicroBitComponent *component);
/**
* remove a component from the array of system components
* @param component The component to remove.
* @return MICROBIT_OK on success. MICROBIT_INVALID_PARAMETER is returned if the given component has not been previous added.
*/
void removeSystemComponent(MicroBitComponent *component);
int removeSystemComponent(MicroBitComponent *component);
/**
* add a component to the array of of idle thread components.
* isIdleCallbackNeeded is polled during a systemTick to determine if the idle thread should jump to the front of the queue
* @param component The component to add.
* @return MICROBIT_OK on success. MICROBIT_NO_RESOURCES is returned if further components cannot be supported.
*/
void addIdleComponent(MicroBitComponent *component);
int addIdleComponent(MicroBitComponent *component);
/**
* remove a component from the array of idle thread components
* @param component The component to remove.
* @return MICROBIT_OK on success. MICROBIT_INVALID_PARAMETER is returned if the given component has not been previous added.
*/
void removeIdleComponent(MicroBitComponent *component);
int removeIdleComponent(MicroBitComponent *component);
/**
* Determine the time since this MicroBit was last reset.

View File

@ -102,22 +102,27 @@ class MicroBitAccelerometer : public MicroBitComponent
* in this object. The nearest values are chosen to those defined
* that are supported by the hardware. The instance variables are then
* updated to reflect reality.
*
* @return MICROBIT_OK on success, MICROBIT_I2C_ERROR if the accelerometer could not be configured.
*/
void configure();
int configure();
/**
* Reads the acceleration data from the accelerometer, and stores it in our buffer.
* This is called by the tick() member function, if the interrupt is set!
* This is called by the tick() member function, if the interrupt is set.
*
* @return MICROBIT_OK on success, MICROBIT_I2C_ERROR is the read request fails.
*/
void update();
int update();
/**
* Attempts to set the sample rate of the accelerometer to the specified value (in ms).
* n.b. the requested rate may not be possible on the hardware. In this case, the
* nearest lower rate is chosen.
* @param period the requested time between samples, in milliseconds.
* @return MICROBIT_OK on success, MICROBIT_I2C_ERROR is the request fails.
*/
void setPeriod(int period);
int setPeriod(int period);
/**
* Reads the currently configured sample rate of the accelerometer.
@ -130,8 +135,9 @@ class MicroBitAccelerometer : public MicroBitComponent
* n.b. the requested range may not be possible on the hardware. In this case, the
* nearest lower rate is chosen.
* @param range The requested sample range of samples, in g.
* @return MICROBIT_OK on success, MICROBIT_I2C_ERROR is the request fails.
*/
void setRange(int range);
int setRange(int range);
/**
* Reads the currently configured sample range of the accelerometer.
@ -141,7 +147,7 @@ class MicroBitAccelerometer : public MicroBitComponent
/**
* Attempts to determine the 8 bit ID from the accelerometer.
* @return the 8 bit ID returned by the accelerometer
* @return the 8 bit ID returned by the accelerometer, or MICROBIT_I2C_ERROR if the request fails.
*
* Example:
* @code
@ -204,8 +210,9 @@ class MicroBitAccelerometer : public MicroBitComponent
*
* @param reg The address of the register to write to.
* @param value The value to write.
* @return MICROBIT_OK on success, MICROBIT_I2C_ERROR if the the write request failed.
*/
void writeCommand(uint8_t reg, uint8_t value);
int writeCommand(uint8_t reg, uint8_t value);
/**
* Issues a read command into the specified buffer.
@ -214,8 +221,9 @@ class MicroBitAccelerometer : public MicroBitComponent
* @param reg The address of the register to access.
* @param buffer Memory area to read the data into.
* @param length The number of bytes to read.
* @return MICROBIT_OK on success, MICROBIT_INVALID_PARAMETER or MICROBIT_I2C_ERROR if the the read request failed.
*/
void readCommand(uint8_t reg, uint8_t* buffer, int length);
int readCommand(uint8_t reg, uint8_t* buffer, int length);
};
#endif

View File

@ -137,16 +137,18 @@ class MicroBitCompass : public MicroBitComponent
* in this object. The nearest values are chosen to those defined
* that are supported by the hardware. The instance variables are then
* updated to reflect reality.
* @return MICROBIT_OK or MICROBIT_I2C_ERROR if the magnetometer could not be configured.
*/
void configure();
int configure();
/**
* Attempts to set the sample rate of the compass to the specified value (in ms).
* n.b. the requested rate may not be possible on the hardware. In this case, the
* nearest lower rate is chosen.
* @param period the requested time between samples, in milliseconds.
* @return MICROBIT_OK or MICROBIT_I2C_ERROR if the magnetometer could not be updated.
*/
void setPeriod(int period);
int setPeriod(int period);
/**
* Reads the currently configured sample rate of the compass.
@ -156,7 +158,8 @@ class MicroBitCompass : public MicroBitComponent
/**
* Gets the current heading of the device, relative to magnetic north.
* @return the current heading, in degrees.
* @return the current heading, in degrees. Or MICROBIT_COMPASS_IS_CALIBRATING if the compass is calibrating.
* Or MICROBIT_COMPASS_CALIBRATE_REQUIRED if the compass requires calibration.
*
* Example:
* @code
@ -167,7 +170,7 @@ class MicroBitCompass : public MicroBitComponent
/**
* Attempts to determine the 8 bit ID from the magnetometer.
* @return the id of the compass (magnetometer)
* @return the id of the compass (magnetometer), or MICROBIT_I2C_ERROR if the magnetometer could not be updated.
*
* Example:
* @code
@ -211,13 +214,14 @@ class MicroBitCompass : public MicroBitComponent
/**
* Reads the currently die temperature of the compass.
* @return The temperature, in degrees celsius.
* @return the temperature in degrees celsius, or MICROBIT_I2C_ERROR if the magnetometer could not be updated.
*/
int readTemperature();
/**
* Perform the asynchronous calibration of the compass.
* This will fire MICROBIT_COMPASS_EVT_CAL_START and MICROBIT_COMPASS_EVT_CAL_END when finished.
* @return MICROBIT_OK, or MICROBIT_I2C_ERROR if the magnetometer could not be accessed.
* @note THIS MUST BE CALLED TO GAIN RELIABLE VALUES FROM THE COMPASS
*/
void calibrateAsync();
@ -227,7 +231,7 @@ class MicroBitCompass : public MicroBitComponent
* This will fire MICROBIT_COMPASS_EVT_CAL_START.
* @note THIS MUST BE CALLED TO GAIN RELIABLE VALUES FROM THE COMPASS
*/
void calibrateStart();
int calibrateStart();
/**
* Complete the calibration of the compass.
@ -270,8 +274,9 @@ class MicroBitCompass : public MicroBitComponent
*
* @param reg The address of the register to write to.
* @param value The value to write.
* @return MICROBIT_OK on success, MICROBIT_I2C_ERROR if the magnetometer could not be accessed.
*/
void writeCommand(uint8_t reg, uint8_t value);
int writeCommand(uint8_t reg, uint8_t value);
/**
* Issues a read command into the specified buffer.
@ -280,17 +285,18 @@ class MicroBitCompass : public MicroBitComponent
* @param reg The address of the register to access.
* @param buffer Memory area to read the data into.
* @param length The number of bytes to read.
* @return MICROBIT_OK on success, MICROBIT_INVALID_PARAMETER or MICROBIT_I2C_ERROR if the magnetometer could not be accessed.
*/
void readCommand(uint8_t reg, uint8_t* buffer, int length);
int readCommand(uint8_t reg, uint8_t* buffer, int length);
/**
* Issues a read of a given address, and returns the value.
* Blocks the calling thread until complete.
*
* @param reg The based address of the 16 bit register to access.
* @return The register value, interpreted as a 16 but signed value.
* @return The register value, interpreted as a 16 but signed value, or MICROBIT_I2C_ERROR if the magnetometer could not be accessed.
*/
int16_t read16(uint8_t reg);
int read16(uint8_t reg);
/**
@ -298,9 +304,9 @@ class MicroBitCompass : public MicroBitComponent
* Blocks the calling thread until complete.
*
* @param reg The based address of the 16 bit register to access.
* @return The register value, interpreted as a 8 bi signed value.
* @return The register value, interpreted as a 8 bit unsigned value, or MICROBIT_I2C_ERROR if the magnetometer could not be accessed.
*/
uint8_t read8(uint8_t reg);
int read8(uint8_t reg);
};
#endif

View File

@ -5,67 +5,65 @@
#ifndef MICROBIT_COMPAT_H
#define MICROBIT_COMPAT_H
#include "ErrorNo.h"
#define PI 3.14159265359
/*! \
\brief Utility functions.
Included here often to reduce the need to import a whole library for simple opertations.
This helps to minimize our SRAM footprint.
*/
/*!
\brief returns the smallest of the two numbers
\param a the first number
\param b the number to compare against a
\return whichever value is the smallest
/**
* Determines the smallest of the two numbers
* @param a the first number
* @param b the second number
* @return The value of a or b that is the smallest
*/
inline int min(int a, int b)
{
return (a < b ? a : b);
}
/*!
\brief returns the biggest of the two numbers
\param a the first number
\param b the number to compare against a
\return whichever value is the biggest
/**
* Determines the largest of the two numbers
* @param a the first number
* @param b the second number
* @return The value of a or b that is the largest
*/
inline int max(int a, int b)
{
return (a > b ? a : b);
}
/*!
\brief clears b number of bytes given the pointer a
\param a the pointer to the beginning of the memory to clear
\param b the number of bytes to clear.
/**
* Sets a given area of memory to zero.
*
* @param a the pointer to the beginning of the memory to clear
* @param b the number of bytes to clear.
*/
inline void *memclr(void *a, size_t b)
{
return memset(a,0,b);
}
/*!
\brief returns true if the character c lies between ascii values 48 and 57 inclusive.
\param c the character to check
\return a bool, true if it is a digit, false otherwise
/**
* Determines if the given character is a printable ASCII/UTF8 decimal digit (0..9).
* @param c the character to check
* @return true if the character is a digit, false otherwise.
*/
inline bool isdigit(char c)
{
return (c > 47 && c < 58);
}
/*!
\brief Performs an in buffer reverse of a given char array
\param s the char* to reverse.
\return the reversed char*
/**
* Performs an in buffer reverse of a given char array
* @param s the string to reverse.
* @return MICROBIT_OK, or MICROBIT_INVALID_PARAMETER.
*/
void string_reverse(char *s);
int string_reverse(char *s);
/*!
\briefConverts a given integer into a base 10 ASCII equivalent.
\param n The number to convert.
\param s Pointer to a buffer in which to store the resulting string.
/**
* Converts a given integer into a string representation.
* @param n The number to convert.
* @param s A pointer to the buffer in which to store the resulting string.
* @return MICROBIT_OK, or MICROBIT_INVALID_PARAMETER.
*/
void itoa(int n, char *s);

View File

@ -1,14 +1,6 @@
#ifndef MICROBIT_DISPLAY_H
#define MICROBIT_DISPLAY_H
/**
* User definable constants
*/
#define MICROBIT_DISPLAY_ROTATION_0 0
#define MICROBIT_DISPLAY_ROTATION_90 1
#define MICROBIT_DISPLAY_ROTATION_180 2
#define MICROBIT_DISPLAY_ROTATION_270 3
/**
* Core Configuration settings.
@ -82,6 +74,13 @@ enum DisplayMode {
DISPLAY_MODE_GREYSCALE
};
enum DisplayRotation {
MICROBIT_DISPLAY_ROTATION_0,
MICROBIT_DISPLAY_ROTATION_90,
MICROBIT_DISPLAY_ROTATION_180,
MICROBIT_DISPLAY_ROTATION_270
};
struct MatrixPoint {
uint8_t x;
uint8_t y;
@ -115,10 +114,10 @@ class MicroBitDisplay : public MicroBitComponent
// The animation mode that's currently running (if any)
AnimationMode animationMode;
// The time (in ticks) between each frame update.
// The time in milliseconds between each frame update.
uint16_t animationDelay;
// The time (in ticks) since the frame update.
// The time in milliseconds since the frame update.
uint16_t animationTick;
// Stop playback of any animations
@ -243,9 +242,10 @@ public:
/**
* Resets the current given animation.
* @param delay the delay after which the animation is reset.
* @param delay the delay after which the animation is reset. Must be > 0.
* @return MICROBIT_OK, or MICROBIT_INVALID_PARAMETER.
*/
void resetAnimation(uint16_t delay);
int resetAnimation(uint16_t delay);
/**
* Frame update method, invoked periodically to strobe the display.
@ -258,26 +258,29 @@ public:
* Returns immediately, and executes the animation asynchronously.
*
* @param s The string to display.
* @param delay The time to delay between characters, in timer ticks.
* @param delay The time to delay between characters, in milliseconds. Must be > 0.
* @return MICROBIT_OK, or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
* uBit.display.printAsync("abc123",400);
* @endcode
*/
void printAsync(ManagedString s, int delay = MICROBIT_DEFAULT_PRINT_SPEED);
int printAsync(ManagedString s, int delay = MICROBIT_DEFAULT_PRINT_SPEED);
/**
* Prints the given character to the display.
*
* @param c The character to display.
* @param delay The time to delay between characters, in milliseconds. Must be > 0.
* @return MICROBIT_OK, or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
* uBit.display.print('p');
* @endcode
*/
void print(char c, int delay = 0);
int print(char c, int delay = 0);
/**
* Prints the given string to the display, one character at a time.
@ -285,21 +288,23 @@ public:
* Blocks the calling thread until all the text has been displayed.
*
* @param s The string to display.
* @param delay The time to delay between characters, in timer ticks.
* @param delay The time to delay between characters, in milliseconds. Must be > 0.
* @return MICROBIT_OK, or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
* uBit.display.print("abc123",400);
* @endcode
*/
void print(ManagedString s, int delay = MICROBIT_DEFAULT_PRINT_SPEED);
int print(ManagedString s, int delay = MICROBIT_DEFAULT_PRINT_SPEED);
/**
* Prints the given image to the display.
* Blocks the calling thread until all the text has been displayed.
*
* @param i The image to display.
* @param delay The time to delay between characters, in timer ticks.
* @param delay The time to display the image for, or zero to show the image forever. Must be >= 0.
* @return MICROBIT_OK, or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
@ -307,7 +312,7 @@ public:
* uBit.display.print(i,400);
* @endcode
*/
void print(MicroBitImage i, int x, int y, int alpha, int delay = MICROBIT_DEFAULT_PRINT_SPEED);
int print(MicroBitImage i, int x, int y, int alpha, int delay = MICROBIT_DEFAULT_PRINT_SPEED);
/**
* Scrolls the given string to the display, from right to left.
@ -315,21 +320,24 @@ public:
* Returns immediately, and executes the animation asynchronously.
*
* @param s The string to display.
* @param delay The time to delay between characters, in timer ticks.
* @param delay The time to delay between each update to the display, in milliseconds. Must be > 0.
* @return MICROBIT_OK, or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
* uBit.display.scrollAsync("abc123",100);
* @endcode
*/
void scrollAsync(ManagedString s, int delay = MICROBIT_DEFAULT_SCROLL_SPEED);
int scrollAsync(ManagedString s, int delay = MICROBIT_DEFAULT_SCROLL_SPEED);
/**
* Scrolls the given image across the display, from right to left.
* Returns immediately, and executes the animation asynchronously.
*
* @param image The image to display.
* @param delay The time to delay between each scroll update, in timer ticks. Has a default.
* @param stride The number of pixels to move in each quantum. Has a default.
* @param delay The time to delay between each update to the display, in milliseconds. Must be > 0.
* @param stride The number of pixels to move in each update. Default value is the screen width.
* @return MICROBIT_OK, or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
@ -337,7 +345,7 @@ public:
* uBit.display.scrollAsync(i,100,1);
* @endcode
*/
void scrollAsync(MicroBitImage image, int delay = MICROBIT_DEFAULT_SCROLL_SPEED, int stride = MICROBIT_DEFAULT_SCROLL_STRIDE);
int scrollAsync(MicroBitImage image, int delay = MICROBIT_DEFAULT_SCROLL_SPEED, int stride = MICROBIT_DEFAULT_SCROLL_STRIDE);
/**
* Scrolls the given string to the display, from right to left.
@ -345,22 +353,24 @@ public:
* Blocks the calling thread until all the text has been displayed.
*
* @param s The string to display.
* @param delay The time to delay between characters, in timer ticks.
* @param delay The time to delay between each update to the display, in milliseconds. Must be > 0.
* @return MICROBIT_OK, or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
* uBit.display.scroll("abc123",100);
* @endcode
*/
void scroll(ManagedString s, int delay = MICROBIT_DEFAULT_SCROLL_SPEED);
int scroll(ManagedString s, int delay = MICROBIT_DEFAULT_SCROLL_SPEED);
/**
* Scrolls the given image across the display, from right to left.
* Blocks the calling thread until all the text has been displayed.
*
* @param image The image to display.
* @param delay The time to delay between each scroll update, in timer ticks. Has a default.
* @param stride The number of pixels to move in each quantum. Has a default.
* @param delay The time to delay between each update to the display, in milliseconds. Must be > 0.
* @param stride The number of pixels to move in each update. Default value is the screen width.
* @return MICROBIT_OK, or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
@ -368,15 +378,16 @@ public:
* uBit.display.scroll(i,100,1);
* @endcode
*/
void scroll(MicroBitImage image, int delay = MICROBIT_DEFAULT_SCROLL_SPEED, int stride = MICROBIT_DEFAULT_SCROLL_STRIDE);
int scroll(MicroBitImage image, int delay = MICROBIT_DEFAULT_SCROLL_SPEED, int stride = MICROBIT_DEFAULT_SCROLL_STRIDE);
/**
* "Animates" the current image across the display with a given stride, finishing on the last frame of the animation.
* Returns immediately.
*
* @param image The image to display.
* @param delay The time to delay between each animation update, in timer ticks. Has a default.
* @param stride The number of pixels to move in each quantum. Has a default.
* @param delay The time to delay between each update to the display, in milliseconds. Must be > 0.
* @param stride The number of pixels to move in each update. Default value is the screen width.
* @return MICROBIT_OK, or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
@ -388,15 +399,16 @@ public:
* uBit.display.animateAsync(i,100,5);
* @endcode
*/
void animateAsync(MicroBitImage image, int delay, int stride, int startingPosition = MICROBIT_DISPLAY_ANIMATE_DEFAULT_POS);
int animateAsync(MicroBitImage image, int delay, int stride, int startingPosition = MICROBIT_DISPLAY_ANIMATE_DEFAULT_POS);
/**
* "Animates" the current image across the display with a given stride, finishing on the last frame of the animation.
* Blocks the calling thread until the animation is complete.
*
* @param image The image to display.
* @param delay The time to delay between each animation update, in timer ticks. Has a default.
* @param stride The number of pixels to move in each quantum. Has a default.
* @param delay The time to delay between each update to the display, in milliseconds. Must be > 0.
* @param stride The number of pixels to move in each update. Default value is the screen width.
* @return MICROBIT_OK, or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
@ -408,19 +420,19 @@ public:
* uBit.display.animate(i,100,5);
* @endcode
*/
void animate(MicroBitImage image, int delay, int stride, int startingPosition = MICROBIT_DISPLAY_ANIMATE_DEFAULT_POS);
int animate(MicroBitImage image, int delay, int stride, int startingPosition = MICROBIT_DISPLAY_ANIMATE_DEFAULT_POS);
/**
* Sets the display brightness to the specified level.
* @param b The brightness to set the brightness to, in the range 0..255.
* @return MICROBIT_OK, or MICROBIT_INVALID_PARAMETER
*
* Example:
* @code
* uBit.display.setBrightness(255); //max brightness
* @endcode
*/
void setBrightness(int b);
int setBrightness(int b);
/**
* Sets the mode of the display.
@ -453,7 +465,7 @@ public:
* uBit.display.rotateTo(MICROBIT_DISPLAY_ROTATION_180); //rotates 180 degrees from original orientation
* @endcode
*/
void rotateTo(uint8_t position);
void rotateTo(DisplayRotation position);
/**
* Enables the display, should only be called if the display is disabled.

View File

@ -170,8 +170,9 @@ void fiber_wait_for_event(uint16_t id, uint16_t value);
* We only create an additional fiber if that function performs a block operation.
*
* @param entry_fn The function to execute.
* @return MICROBIT_OK, or MICROBIT_INVALID_PARAMETER.
*/
void invoke(void (*entry_fn)(void));
int invoke(void (*entry_fn)(void));
/**
* Executes the given function asynchronously if necessary.
@ -183,9 +184,10 @@ void invoke(void (*entry_fn)(void));
* We only create an additional fiber if that function performs a block operation.
*
* @param entry_fn The function to execute.
* @param param an untyped parameter passed into the entry_fn anf completion_fn.
* @param param an untyped parameter passed into the entry_fn and completion_fn.
* @return MICROBIT_OK, or MICROBIT_INVALID_PARAMETER.
*/
void invoke(void (*entry_fn)(void *), void *param);
int invoke(void (*entry_fn)(void *), void *param);
/**
* Resizes the stack allocation of the current fiber if necessary to hold the system stack.

View File

@ -35,8 +35,29 @@
// Flag to indicate that a given block is FREE/USED
#define MICROBIT_HEAP_BLOCK_FREE 0x80000000
/**
* Initialise the microbit heap according to the parameters defined in MicroBitConfig.h
* After this is called, any future calls to malloc, new, free or delete will use the new heap.
* n.b. only code that #includes MicroBitHeapAllocator.h will use this heap. This includes all micro:bit runtime
* code, and user code targetting the runtime. External code can choose to include this file, or
* simply use the standard mbed heap.
*
* @return MICROBIT_OK on success, or MICROBIT_NO_RESOURCES if the heap could not be allocted.
*/
int microbit_heap_init();
/**
* Attempt to allocate a given amount of memory from any of our configured heap areas.
* @param size The amount of memory, in bytes, to allocate.
* @return A pointer to the allocated memory, or NULL if insufficient memory is available.
*/
void *microbit_malloc(size_t size);
/**
* Release a given area of memory from the heap.
* @param mem The memory area to release.
*/
void microbit_free(void *mem);
/*

View File

@ -8,11 +8,11 @@
/**
* Class definition for MicroBitI2C.
*
* Represents a wrapped mbed call to hopefully fix silicon issues once and for all.
* Presents a wrapped mbed call to capture failed I2C operations caused by a known silicon bug in the nrf51822.
* Attempts to automatically reset and restart the I2C hardware if this case is detected.
*/
class MicroBitI2C : public I2C
{
uint8_t retries;
public:
@ -29,9 +29,29 @@ class MicroBitI2C : public I2C
* @note this should prevent i2c lockups as well.
*/
MicroBitI2C(PinName sda, PinName scl);
/**
* Performs a complete read transaction. The bottom bit of the address is forced to 1 to indicate a read.
*
* @address 8-bit I2C slave address [ addr | 1 ]
* @data Pointer to the byte-array to read data in to
* @length Number of bytes to read
* @repeated Repeated start, true - don't send stop at end.
*
* @return MICROBIT_OK on success, MICROBIT_I2C_ERROR if an unresolved read failure is detected.
*/
int read(int address, char *data, int length, bool repeated = false);
/**
* Performs a complete write transaction. The bottom bit of the address is forced to 0 to indicate a write.
*
* @address 8-bit I2C slave address [ addr | 0 ]
* @data Pointer to the byte-arraycontaining the data to write
* @length Number of bytes to write
* @repeated Repeated start, true - don't send stop at end.
*
* @return MICROBIT_OK on success, MICROBIT_I2C_ERROR if an unresolved write failure is detected.
*/
int write(int address, const char *data, int length, bool repeated = false);
};

View File

@ -173,6 +173,7 @@ class MicroBitImage
* @param x The co-ordinate of the pixel to change w.r.t. top left origin.
* @param y The co-ordinate of the pixel to change w.r.t. top left origin.
* @param value The new value of the pixel (the brightness level 0-255)
* @return MICROBIT_OK, or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
@ -180,11 +181,14 @@ class MicroBitImage
* i.setPixelValue(0,0,255);
* @endcode
*/
void setPixelValue(int16_t x , int16_t y, uint8_t value);
int setPixelValue(int16_t x , int16_t y, uint8_t value);
/**
* Determines the value of a given pixel.
* @return The value assigned to the given pixel location (the brightness level 0-255)
* Determines the value of a given pixel.
*
* @param x The x co-ordinate of the pixel to read. Must be within the dimensions of the image.
* @param y The y co-ordinate of the pixel to read. Must be within the dimensions of the image.
* @return The value assigned to the given pixel location (the brightness level 0-255), or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
@ -199,9 +203,10 @@ class MicroBitImage
* 2D array representing the image.
* Origin is in the top left corner of the image.
*
* @param x the width of the image.
* @param y the height of the image.
* @param x the width of the image. Must be within the dimensions of the image.
* @param y the width of the image. Must be within the dimensions of the image.
* @param bitmap a 2D array representing the image.
* @return MICROBIT_OK on success, or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
@ -210,7 +215,7 @@ class MicroBitImage
* i.printImage(0,0,heart);
* @endcode
*/
void printImage(int16_t x, int16_t y, const uint8_t *bitmap);
int printImage(int16_t x, int16_t y, const uint8_t *bitmap);
/**
* Pastes a given bitmap at the given co-ordinates.
@ -220,7 +225,7 @@ class MicroBitImage
* @param x The leftmost X co-ordinate in this image where the given image should be pasted.
* @param y The uppermost Y co-ordinate in this image where the given image should be pasted.
* @param alpha set to 1 if transparency clear pixels in given image should be treated as transparent. Set to 0 otherwise.
* @return The number of pixels written.
* @return The number of pixels written, or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
@ -237,6 +242,7 @@ class MicroBitImage
* @param c The character to display.
* @param x The x co-ordinate of on the image to place the top left of the character
* @param y The y co-ordinate of on the image to place the top left of the character
* @return MICROBIT_OK on success, or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
@ -244,12 +250,13 @@ class MicroBitImage
* i.print('a',0,0);
* @endcode
*/
void print(char c, int16_t x, int16_t y);
int print(char c, int16_t x, int16_t y);
/**
* Shifts the pixels in this Image a given number of pixels to the Left.
*
* @param n The number of pixels to shift.
* @return MICROBIT_OK on success, or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
@ -258,12 +265,13 @@ class MicroBitImage
* i.shiftLeft(5); //displays a small heart :)
* @endcode
*/
void shiftLeft(int16_t n);
int shiftLeft(int16_t n);
/**
* Shifts the pixels in this Image a given number of pixels to the Right.
*
* @param n The number of pixels to shift.
* @return MICROBIT_OK on success, or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
@ -273,12 +281,13 @@ class MicroBitImage
* i.shiftRight(5); //displays a big heart :)
* @endcode
*/
void shiftRight(int16_t n);
int shiftRight(int16_t n);
/**
* Shifts the pixels in this Image a given number of pixels to Upward.
*
* @param n The number of pixels to shift.
* @return MICROBIT_OK on success, or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
@ -287,12 +296,13 @@ class MicroBitImage
* i.shiftUp(1);
* @endcode
*/
void shiftUp(int16_t n);
int shiftUp(int16_t n);
/**
* Shifts the pixels in this Image a given number of pixels to Downward.
*
* @param n The number of pixels to shift.
* @return MICROBIT_OK on success, or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
@ -301,7 +311,7 @@ class MicroBitImage
* i.shiftDown(1);
* @endcode
*/
void shiftDown(int16_t n);
int shiftDown(int16_t n);
/**
* Gets the width of this image.

View File

@ -78,7 +78,9 @@ class MicroBitMessageBus : public MicroBitComponent
* @param value The value of messages to listen for. Events with any other values will be filtered.
* Use MICROBIT_EVT_ANY to receive events of any value.
*
* @param hander The function to call when an event is received.
* @param handler The function to call when an event is received.
*
* @return MICROBIT_OK on success MICROBIT_INVALID_PARAMETER
*
* Example:
* @code
@ -89,7 +91,7 @@ class MicroBitMessageBus : public MicroBitComponent
* uBit.MessageBus.listen(MICROBIT_ID_BUTTON_B, MICROBIT_BUTTON_EVT_CLICK, onButtonBClick); // call function when ever a click event is detected.
* @endcode
*/
void listen(int id, int value, void (*handler)(MicroBitEvent), uint16_t flags = MESSAGE_BUS_LISTENER_DEFAULT_FLAGS);
int listen(int id, int value, void (*handler)(MicroBitEvent), uint16_t flags = MESSAGE_BUS_LISTENER_DEFAULT_FLAGS);
/**
* Register a listener function.
@ -101,6 +103,8 @@ class MicroBitMessageBus : public MicroBitComponent
* Use MICROBIT_EVT_ANY to receive events of any value.
*
* @param hander The function to call when an event is received.
*
* @return MICROBIT_OK on success MICROBIT_INVALID_PARAMETER
*
* Example:
* @code
@ -111,7 +115,7 @@ class MicroBitMessageBus : public MicroBitComponent
* uBit.MessageBus.listen(MICROBIT_ID_BUTTON_B, MICROBIT_BUTTON_EVT_CLICK, onButtonBClick); // call function when ever a click event is detected.
* @endcode
*/
void listen(int id, int value, void (*handler)(MicroBitEvent, void*), void* arg, uint16_t flags = MESSAGE_BUS_LISTENER_DEFAULT_FLAGS);
int listen(int id, int value, void (*handler)(MicroBitEvent, void*), void* arg, uint16_t flags = MESSAGE_BUS_LISTENER_DEFAULT_FLAGS);
/**
* Register a listener function.
@ -123,6 +127,8 @@ class MicroBitMessageBus : public MicroBitComponent
* Use MICROBIT_EVT_ANY to receive events of any value.
*
* @param hander The function to call when an event is received.
*
* @return MICROBIT_OK on success MICROBIT_INVALID_PARAMETER
*
* Example:
* @code
@ -136,7 +142,7 @@ class MicroBitMessageBus : public MicroBitComponent
* @endcode
*/
template <typename T>
void listen(uint16_t id, uint16_t value, T* object, void (T::*handler)(MicroBitEvent), uint16_t flags = MESSAGE_BUS_LISTENER_DEFAULT_FLAGS);
int listen(uint16_t id, uint16_t value, T* object, void (T::*handler)(MicroBitEvent), uint16_t flags = MESSAGE_BUS_LISTENER_DEFAULT_FLAGS);
/**
@ -146,6 +152,8 @@ class MicroBitMessageBus : public MicroBitComponent
* @param id The Event ID used to register the listener.
* @param value The Event VALUE used to register the listener.
* @param handler The function used to register the listener.
*
* @return MICROBIT_OK on success MICROBIT_INVALID_PARAMETER
*
*
* Example:
@ -158,7 +166,7 @@ class MicroBitMessageBus : public MicroBitComponent
* uBit.MessageBus.ignore(MICROBIT_ID_BUTTON_B, MICROBIT_BUTTON_EVT_CLICK, onButtonBClick);
* @endcode
*/
void ignore(int id, int value, void (*handler)(MicroBitEvent));
int ignore(int id, int value, void (*handler)(MicroBitEvent));
/**
* Unregister a listener function.
@ -168,6 +176,7 @@ class MicroBitMessageBus : public MicroBitComponent
* @param value The Event VALUE used to register the listener.
* @param handler The function used to register the listener.
*
* @return MICROBIT_OK on success MICROBIT_INVALID_PARAMETER
*
* Example:
* @code
@ -179,7 +188,7 @@ class MicroBitMessageBus : public MicroBitComponent
* uBit.MessageBus.ignore(MICROBIT_ID_BUTTON_B, MICROBIT_BUTTON_EVT_CLICK, onButtonBClick);
* @endcode
*/
void ignore(int id, int value, void (*handler)(MicroBitEvent, void*));
int ignore(int id, int value, void (*handler)(MicroBitEvent, void*));
/**
* Unregister a listener function.
@ -189,6 +198,7 @@ class MicroBitMessageBus : public MicroBitComponent
* @param value The Event VALUE used to register the listener.
* @param handler The function used to register the listener.
*
* @return MICROBIT_OK on success MICROBIT_INVALID_PARAMETER
*
* Example:
* @code
@ -203,7 +213,7 @@ class MicroBitMessageBus : public MicroBitComponent
* @endcode
*/
template <typename T>
void ignore(uint16_t id, uint16_t value, T* object, void (T::*handler)(MicroBitEvent));
int ignore(uint16_t id, uint16_t value, T* object, void (T::*handler)(MicroBitEvent));
/**
* Returns the microBitListener with the given position in our list.
@ -221,10 +231,16 @@ class MicroBitMessageBus : public MicroBitComponent
/**
* Add the given MicroBitListener to the list of event handlers, unconditionally.
* @param listener The MicroBitListener to validate.
* @return 1 if the listener is valid, 0 otherwise.
* @param listener The MicroBitListener to add.
* @return MICROBIT_OK if the listener is valid, MICROBIT_INVALID_PARAMETER otherwise.
*/
int add(MicroBitListener *newListener);
/**
* Remove the given MicroBitListener from the list of event handlers.
* @param listener The MicroBitListener to remove.
* @return MICROBIT_OK if the listener is valid, MICROBIT_INVALID_PARAMETER otherwise.
*/
int remove(MicroBitListener *newListener);
MicroBitListener *listeners; // Chain of active listeners.
@ -250,18 +266,22 @@ class MicroBitMessageBus : public MicroBitComponent
* Use MICROBIT_EVT_ANY to receive events of any value.
*
* @param object The object on which the method should be invoked.
* @param hander The method to call when an event is received.
* @param handler The method to call when an event is received.
*
* @return MICROBIT_OK on success MICROBIT_INVALID_PARAMETER
*/
template <typename T>
void MicroBitMessageBus::listen(uint16_t id, uint16_t value, T* object, void (T::*handler)(MicroBitEvent), uint16_t flags)
int MicroBitMessageBus::listen(uint16_t id, uint16_t value, T* object, void (T::*handler)(MicroBitEvent), uint16_t flags)
{
if (object == NULL || handler == NULL)
return;
return MICROBIT_INVALID_PARAMETER;
MicroBitListener *newListener = new MicroBitListener(id, value, object, handler, flags);
if(!add(newListener))
delete newListener;
return MICROBIT_OK;
}
/**
@ -272,6 +292,7 @@ void MicroBitMessageBus::listen(uint16_t id, uint16_t value, T* object, void (T:
* @param value The Event VALUE used to register the listener.
* @param handler The function used to register the listener.
*
* @return MICROBIT_OK on success MICROBIT_INVALID_PARAMETER
*
* Example:
* @code
@ -284,13 +305,15 @@ void MicroBitMessageBus::listen(uint16_t id, uint16_t value, T* object, void (T:
* @endcode
*/
template <typename T>
void MicroBitMessageBus::ignore(uint16_t id, uint16_t value, T* object, void (T::*handler)(MicroBitEvent))
int MicroBitMessageBus::ignore(uint16_t id, uint16_t value, T* object, void (T::*handler)(MicroBitEvent))
{
if (handler == NULL)
return;
return MICROBIT_INVALID_PARAMETER;
MicroBitListener listener(id, value, object, handler);
remove(&listener);
return MICROBIT_OK;
}

View File

@ -77,7 +77,7 @@ class MicroBitPin : public MicroBitComponent
* Create a Button representation with the given ID.
* @param id the ID of the new Pin object.
* @param name the pin name for this MicroBitPin instance to represent
* @param capability the capability of this pin, can it only be digital? can it only be analog? can it be both?
* @param capability the capability of this pin.
*
* Example:
* @code
@ -89,18 +89,20 @@ class MicroBitPin : public MicroBitComponent
/**
* Configures this IO pin as a digital output (if necessary) and sets the pin to 'value'.
* @param value 0 (LO) or 1 (HI)
* @return MICROBIT_OK on success, MICROBIT_INVALID_PARAMETER if value is out of range, or MICROBIT_NOT_SUPPORTED
* if the given pin does not have digital capability.
*
* Example:
* @code
* MicroBitPin P0(MICROBIT_ID_IO_P0, MICROBIT_PIN_P0, PIN_CAPABILITY_BOTH);
* P0.setDigitalValue(1); // P0 is now HI!
* P0.setDigitalValue(1); // P0 is now HI
* @endcode
*/
void setDigitalValue(int value);
int 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 otherwise.
* @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.
*
* Example:
* @code
@ -111,22 +113,22 @@ class MicroBitPin : public MicroBitComponent
int getDigitalValue();
/**
* Configures this IO pin as an analogue output (if necessary and possible).
* Change the DAC value to the given level.
* @param value the level to set on the output pin, in the range 0..???
* @note NOT IN USE, but may exist in the future if we do some clever rejigging! :)
* Configures this IO pin as an analog/pwm output, and change the output value to the given level.
* @param value the level to set on the output pin, in the range 0 - 1024
* @return MICROBIT_OK on success, MICROBIT_INVALID_PARAMETER if value is out of range, or MICROBIT_NOT_SUPPORTED
* if the given pin does not have analog capability.
*/
void setAnalogValue(int value);
int setAnalogValue(int value);
/**
* Configures this IO pin as an analogue input (if necessary and possible).
* @return the current analogue level on the pin, in the range 0-0xFFFF
* @return the current analogue level on the pin, in the range 0 - 1024, or MICROBIT_NOT_SUPPORTED if the given pin does not have analog capability.
*
* Example:
* @code
* MicroBitPin P0(MICROBIT_ID_IO_P0, MICROBIT_PIN_P0, PIN_CAPABILITY_BOTH);
* P0.getAnalogValue(); // P0 is a value in the range of 0 - 0xFFFF
* P0.getAnalogValue(); // P0 is a value in the range of 0 - 1024
* @endcode
*/
int getAnalogValue();
@ -157,7 +159,7 @@ class MicroBitPin : public MicroBitComponent
/**
* Configures this IO pin as a makey makey style touch sensor (if necessary) and tests its current debounced state.
* @return 1 if pin is touched, 0 otherwise.
* @return 1 if pin is touched, 0 if not, or MICROBIT_NOT_SUPPORTED if this pin does not support touch capability.
*
* Example:
* @code
@ -170,19 +172,23 @@ class MicroBitPin : public MicroBitComponent
*/
int isTouched();
/**
* Configures the PWM period of the analog output to the given value.
* If this pin is not configured as an analog output, the operation
* has no effect.
*
* @param period The new period for the analog output in milliseconds.
*/
void setAnalogPeriod(int period);
/**
* Configures the PWM period of the analog output to the given value.
*
* @param period The new period for the analog output in milliseconds.
* @return MICROBIT_OK on success, or MICROBIT_NOT_SUPPORTED if the
* given pin is not configured as an analog output.
*/
int setAnalogPeriod(int period);
/**
* Same thing as setAnalogPeriodUs, but with microseconds.
*/
void setAnalogPeriodUs(int period);
* Configures the PWM period of the analog output to the given value.
*
* @param period The new period for the analog output in microseconds.
* @return MICROBIT_OK on success, or MICROBIT_NOT_SUPPORTED if the
* given pin is not configured as an analog output.
*/
int setAnalogPeriodUs(int period);
};
#endif

View File

@ -252,9 +252,10 @@ void MicroBit::reset()
* If the scheduler is disabled or we're running in an interrupt context, this
* will revert to a busy wait.
*
* @note Values of 6 and below tend to lose resolution - do you really need to sleep for this short amount of time?
* @note Values of below below the scheduling period (typical 6ms) tend to lose resolution.
*
* @param milliseconds the amount of time, in ms, to wait for. This number cannot be negative.
* @return MICROBIT_OK on success, MICROBIT_INVALID_PARAMETER milliseconds is less than zero.
*
* Example:
* @code
@ -271,6 +272,8 @@ int MicroBit::sleep(int milliseconds)
fiber_sleep(milliseconds);
else
wait_ms(milliseconds);
return MICROBIT_OK;
}
@ -376,9 +379,11 @@ void MicroBit::systemTasks()
/**
* add a component to the array of components which invocate the systemTick member function during a systemTick
* @param component The component to add.
* @return MICROBIT_OK on success. MICROBIT_NO_RESOURCES is returned if further components cannot be supported.
* @note this will be converted into a dynamic list of components
*/
void MicroBit::addSystemComponent(MicroBitComponent *component)
int MicroBit::addSystemComponent(MicroBitComponent *component)
{
int i = 0;
@ -386,16 +391,19 @@ void MicroBit::addSystemComponent(MicroBitComponent *component)
i++;
if(i == MICROBIT_SYSTEM_COMPONENTS)
return;
return MICROBIT_NO_RESOURCES;
systemTickComponents[i] = component;
return MICROBIT_OK;
}
/**
* remove a component from the array of components
* @param component The component to remove.
* @return MICROBIT_OK on success. MICROBIT_INVALID_PARAMTER is returned if the given component has not been previous added.
* @note this will be converted into a dynamic list of components
*/
void MicroBit::removeSystemComponent(MicroBitComponent *component)
int MicroBit::removeSystemComponent(MicroBitComponent *component)
{
int i = 0;
@ -403,16 +411,20 @@ void MicroBit::removeSystemComponent(MicroBitComponent *component)
i++;
if(i == MICROBIT_SYSTEM_COMPONENTS)
return;
return MICROBIT_INVALID_PARAMETER;
systemTickComponents[i] = NULL;
return MICROBIT_OK;
}
/**
* add a component to the array of components which invocate the systemTick member function during a systemTick
* @param component The component to add.
* @return MICROBIT_OK on success. MICROBIT_NO_RESOURCES is returned if further components cannot be supported.
* @note this will be converted into a dynamic list of components
*/
void MicroBit::addIdleComponent(MicroBitComponent *component)
int MicroBit::addIdleComponent(MicroBitComponent *component)
{
int i = 0;
@ -420,16 +432,20 @@ void MicroBit::addIdleComponent(MicroBitComponent *component)
i++;
if(i == MICROBIT_IDLE_COMPONENTS)
return;
return MICROBIT_NO_RESOURCES;
idleThreadComponents[i] = component;
return MICROBIT_OK;
}
/**
* remove a component from the array of components
* @param component The component to remove.
* @return MICROBIT_OK on success. MICROBIT_INVALID_PARAMTER is returned if the given component has not been previous added.
* @note this will be converted into a dynamic list of components
*/
void MicroBit::removeIdleComponent(MicroBitComponent *component)
int MicroBit::removeIdleComponent(MicroBitComponent *component)
{
int i = 0;
@ -437,9 +453,11 @@ void MicroBit::removeIdleComponent(MicroBitComponent *component)
i++;
if(i == MICROBIT_IDLE_COMPONENTS)
return;
return MICROBIT_INVALID_PARAMETER;
idleThreadComponents[i] = NULL;
return MICROBIT_OK;
}
/**

View File

@ -12,11 +12,14 @@
* in this object. The nearest values are chosen to those defined
* that are supported by the hardware. The instance variables are then
* updated to reflect reality.
*
* @return MICROBIT_OK on success, MICROBIT_I2C_ERROR if the accelerometer could not be configured.
*/
void MicroBitAccelerometer::configure()
int MicroBitAccelerometer::configure()
{
const MMA8653SampleRangeConfig *actualSampleRange;
const MMA8653SampleRateConfig *actualSampleRate;
int result;
// First find the nearest sample rate to that specified.
actualSampleRate = &MMA8653SampleRate[MMA8653_SAMPLE_RATES-1];
@ -44,22 +47,36 @@ void MicroBitAccelerometer::configure()
// Now configure the accelerometer accordingly.
// First place the device into standby mode, so it can be configured.
writeCommand(MMA8653_CTRL_REG1, 0x00);
result = writeCommand(MMA8653_CTRL_REG1, 0x00);
if (result != 0)
return MICROBIT_I2C_ERROR;
// Enable high precisiosn mode. This consumes a bit more power, but still only 184 uA!
writeCommand(MMA8653_CTRL_REG2, 0x10);
result = writeCommand(MMA8653_CTRL_REG2, 0x10);
if (result != 0)
return MICROBIT_I2C_ERROR;
// Enable the INT1 interrupt pin.
writeCommand(MMA8653_CTRL_REG4, 0x01);
result = writeCommand(MMA8653_CTRL_REG4, 0x01);
if (result != 0)
return MICROBIT_I2C_ERROR;
// Select the DATA_READY event source to be routed to INT1
writeCommand(MMA8653_CTRL_REG5, 0x01);
result = writeCommand(MMA8653_CTRL_REG5, 0x01);
if (result != 0)
return MICROBIT_I2C_ERROR;
// Configure for the selected g range.
writeCommand(MMA8653_XYZ_DATA_CFG, actualSampleRange->xyz_data_cfg);
result = writeCommand(MMA8653_XYZ_DATA_CFG, actualSampleRange->xyz_data_cfg);
if (result != 0)
return MICROBIT_I2C_ERROR;
// Bring the device back online, with 10bit wide samples at the requested frequency.
writeCommand(MMA8653_CTRL_REG1, actualSampleRate->ctrl_reg1 | 0x01);
result = writeCommand(MMA8653_CTRL_REG1, actualSampleRate->ctrl_reg1 | 0x01);
if (result != 0)
return MICROBIT_I2C_ERROR;
return MICROBIT_OK;
}
/**
@ -68,14 +85,15 @@ void MicroBitAccelerometer::configure()
*
* @param reg The address of the register to write to.
* @param value The value to write.
* @return MICROBIT_OK on success, MICROBIT_I2C_ERROR if the the write request failed.
*/
void MicroBitAccelerometer::writeCommand(uint8_t reg, uint8_t value)
int MicroBitAccelerometer::writeCommand(uint8_t reg, uint8_t value)
{
uint8_t command[2];
command[0] = reg;
command[1] = value;
uBit.i2c.write(address, (const char *)command, 2);
return uBit.i2c.write(address, (const char *)command, 2);
}
/**
@ -85,11 +103,24 @@ void MicroBitAccelerometer::writeCommand(uint8_t reg, uint8_t value)
* @param reg The address of the register to access.
* @param buffer Memory area to read the data into.
* @param length The number of bytes to read.
* @return MICROBIT_OK on success, MICROBIT_INVALID_PARAMETER or MICROBIT_I2C_ERROR if the the read request failed.
*/
void MicroBitAccelerometer::readCommand(uint8_t reg, uint8_t* buffer, int length)
int MicroBitAccelerometer::readCommand(uint8_t reg, uint8_t* buffer, int length)
{
uBit.i2c.write(address, (const char *)&reg, 1, true);
uBit.i2c.read(address, (char *)buffer, length);
int result;
if (buffer == NULL || length <= 0 )
return MICROBIT_INVALID_PARAMETER;
result = uBit.i2c.write(address, (const char *)&reg, 1, true);
if (result !=0)
return MICROBIT_I2C_ERROR;
result = uBit.i2c.read(address, (char *)buffer, length);
if (result !=0)
return MICROBIT_I2C_ERROR;
return MICROBIT_OK;
}
/**
@ -114,15 +145,13 @@ MicroBitAccelerometer::MicroBitAccelerometer(uint16_t id, uint16_t address) : sa
this->sampleRange = 2;
// Configure and enable the accelerometer.
this->configure();
// indicate that we're ready to receive tick callbacks.
uBit.flags |= MICROBIT_FLAG_ACCELEROMETER_RUNNING;
if (this->configure() == MICROBIT_OK)
uBit.flags |= MICROBIT_FLAG_ACCELEROMETER_RUNNING;
}
/**
* Attempts to determine the 8 bit ID from the accelerometer.
* @return the 8 bit ID returned by the accelerometer
* @return the 8 bit ID returned by the accelerometer, or MICROBIT_I2C_ERROR if the request fails.
*
* Example:
* @code
@ -132,20 +161,29 @@ MicroBitAccelerometer::MicroBitAccelerometer(uint16_t id, uint16_t address) : sa
int MicroBitAccelerometer::whoAmI()
{
uint8_t data;
int result;
result = readCommand(MMA8653_WHOAMI, &data, 1);
if (result !=0)
return MICROBIT_I2C_ERROR;
readCommand(MMA8653_WHOAMI, &data, 1);
return (int)data;
}
/**
* Reads the acceleration data from the accelerometer, and stores it in our buffer.
* This is called by the tick() member function, if the interrupt is set!
*
* @return MICROBIT_OK on success, MICROBIT_I2C_ERROR is the read request fails.
*/
void MicroBitAccelerometer::update()
int MicroBitAccelerometer::update()
{
int8_t data[6];
int result;
readCommand(MMA8653_OUT_X_MSB, (uint8_t *)data, 6);
result = readCommand(MMA8653_OUT_X_MSB, (uint8_t *)data, 6);
if (result !=0)
return MICROBIT_I2C_ERROR;
// read MSB values...
sample.x = data[0];
@ -175,6 +213,8 @@ void MicroBitAccelerometer::update()
// Indicate that a new sample is available
MicroBitEvent e(id, MICROBIT_ACCELEROMETER_EVT_DATA_UPDATE);
return MICROBIT_OK;
};
/**
@ -182,11 +222,12 @@ void MicroBitAccelerometer::update()
* n.b. the requested rate may not be possible on the hardware. In this case, the
* nearest lower rate is chosen.
* @param period the requested time between samples, in milliseconds.
* @return MICROBIT_OK on success, MICROBIT_I2C_ERROR is the request fails.
*/
void MicroBitAccelerometer::setPeriod(int period)
int MicroBitAccelerometer::setPeriod(int period)
{
this->samplePeriod = period;
this->configure();
return this->configure();
}
/**
@ -203,11 +244,12 @@ int MicroBitAccelerometer::getPeriod()
* n.b. the requested range may not be possible on the hardware. In this case, the
* nearest lower rate is chosen.
* @param range The requested sample range of samples, in g.
* @return MICROBIT_OK on success, MICROBIT_I2C_ERROR is the request fails.
*/
void MicroBitAccelerometer::setRange(int range)
int MicroBitAccelerometer::setRange(int range)
{
this->sampleRange = range;
this->configure();
return this->configure();
}
/**

View File

@ -38,7 +38,7 @@ MicroBitButton::MicroBitButton(uint16_t id, PinName name, PinMode mode) : pin(na
*/
void MicroBitButton::systemTick()
{
//
//
// If the pin is pulled low (touched), increment our culumative counter.
// otherwise, decrement it. We're essentially building a lazy follower here.
// This makes the output debounced for buttons, and desensitizes touch sensors

View File

@ -33,13 +33,7 @@ MicroBitCompass::MicroBitCompass(uint16_t id, uint16_t address) : average(), sam
this->samplePeriod = 100;
this->configure();
//fetch our previous average values
average.x = read16(MAG_OFF_X_MSB);
average.y = read16(MAG_OFF_Y_MSB);
average.z = read16(MAG_OFF_Z_MSB);
if(average.x == 0 && average.y == 0 && average.z == 0)
status &= ~MICROBIT_COMPASS_STATUS_CALIBRATED;
status &= ~MICROBIT_COMPASS_STATUS_CALIBRATED;
// Indicate that we're up and running.
uBit.flags |= MICROBIT_FLAG_COMPASS_RUNNING;
@ -51,14 +45,15 @@ MicroBitCompass::MicroBitCompass(uint16_t id, uint16_t address) : average(), sam
*
* @param reg The address of the register to write to.
* @param value The value to write.
* @return MICROBIT_OK on success, MICROBIT_I2C_ERROR if the magnetometer could not be accessed.
*/
void MicroBitCompass::writeCommand(uint8_t reg, uint8_t value)
int MicroBitCompass::writeCommand(uint8_t reg, uint8_t value)
{
uint8_t command[2];
command[0] = reg;
command[1] = value;
uBit.i2c.write(address, (const char *)command, 2);
return uBit.i2c.write(address, (const char *)command, 2);
}
/**
@ -69,10 +64,22 @@ void MicroBitCompass::writeCommand(uint8_t reg, uint8_t value)
* @param buffer Memory area to read the data into.
* @param length The number of bytes to read.
*/
void MicroBitCompass::readCommand(uint8_t reg, uint8_t* buffer, int length)
int MicroBitCompass::readCommand(uint8_t reg, uint8_t* buffer, int length)
{
uBit.i2c.write(address, (const char *)&reg, 1, true);
uBit.i2c.read(address, (char *)buffer, length);
int result;
if (buffer == NULL || length <= 0)
return MICROBIT_INVALID_PARAMETER;
result = uBit.i2c.write(address, (const char *)&reg, 1, true);
if (result !=0)
return MICROBIT_I2C_ERROR;
result = uBit.i2c.read(address, (char *)buffer, length);
if (result !=0)
return MICROBIT_I2C_ERROR;
return MICROBIT_OK;
}
@ -81,19 +88,25 @@ void MicroBitCompass::readCommand(uint8_t reg, uint8_t* buffer, int length)
* Blocks the calling thread until complete.
*
* @param reg The based address of the 16 bit register to access.
* @return The register value, interpreted as a 16 but signed value.
* @return The register value, interpreted as a 16 but signed value, or MICROBIT_I2C_ERROR if the magnetometer could not be accessed.
*/
int16_t MicroBitCompass::read16(uint8_t reg)
int MicroBitCompass::read16(uint8_t reg)
{
uint8_t cmd[2];
int result;
cmd[0] = reg;
uBit.i2c.write(address, (const char *)cmd, 1);
result = uBit.i2c.write(address, (const char *)cmd, 1);
if (result !=0)
return MICROBIT_I2C_ERROR;
cmd[0] = 0x00;
cmd[1] = 0x00;
uBit.i2c.read(address, (char *)cmd, 2);
result = uBit.i2c.read(address, (char *)cmd, 2);
if (result !=0)
return MICROBIT_I2C_ERROR;
return (int16_t) ((cmd[1] | (cmd[0] << 8))); //concatenate the MSB and LSB
}
@ -102,14 +115,17 @@ int16_t MicroBitCompass::read16(uint8_t reg)
* Blocks the calling thread until complete.
*
* @param reg The based address of the 16 bit register to access.
* @return The register value, interpreted as a 8 bi signed value.
* @return The register value, interpreted as a 8 bit unsigned value, or MICROBIT_I2C_ERROR if the magnetometer could not be accessed.
*/
uint8_t MicroBitCompass::read8(uint8_t reg)
int MicroBitCompass::read8(uint8_t reg)
{
uint8_t data;
int result;
data = 0;
readCommand(reg, (uint8_t*) &data, 1);
result = readCommand(reg, (uint8_t*) &data, 1);
if (result != MICROBIT_OK)
return MICROBIT_I2C_ERROR;
return data;
}
@ -128,12 +144,12 @@ uint8_t MicroBitCompass::read8(uint8_t reg)
int MicroBitCompass::heading()
{
if(status & MICROBIT_COMPASS_STATUS_CALIBRATING)
return MICROBIT_COMPASS_IS_CALIBRATING;
return MICROBIT_CALIBRATION_IN_PROGRESS;
else if(!(status & MICROBIT_COMPASS_STATUS_CALIBRATED))
{
MicroBitEvent(id, MICROBIT_COMPASS_EVT_CAL_REQUIRED);
return MICROBIT_COMPASS_CALIBRATE_REQUIRED;
return MICROBIT_CALIBRATION_REQUIRED;
}
float bearing = (atan2((double)(sample.y - average.y),(double)(sample.x - average.x)))*180/PI;
@ -154,9 +170,9 @@ void MicroBitCompass::idleTick()
// Active HI. Interrupt is cleared in data read of MAG_OUT_X_MSB.
if(int1)
{
sample.x = read16(MAG_OUT_X_MSB);
sample.y = read16(MAG_OUT_Y_MSB);
sample.z = read16(MAG_OUT_Z_MSB);
sample.x = (int16_t) read16(MAG_OUT_X_MSB);
sample.y = (int16_t) read16(MAG_OUT_Y_MSB);
sample.z = (int16_t) read16(MAG_OUT_Z_MSB);
if (status & MICROBIT_COMPASS_STATUS_CALIBRATING)
{
@ -230,17 +246,34 @@ int MicroBitCompass::getZ()
* in this object. The nearest values are chosen to those defined
* that are supported by the hardware. The instance variables are then
* updated to reflect reality.
* @return MICROBIT_OK or MICROBIT_I2C_ERROR if the magnetometer could not be configured.
*/
void MicroBitCompass::configure()
int MicroBitCompass::configure()
{
const MAG3110SampleRateConfig *actualSampleRate;
int result;
// First, take the device offline, so it can be configured.
writeCommand(MAG_CTRL_REG1, 0x00);
result = writeCommand(MAG_CTRL_REG1, 0x00);
if (result != MICROBIT_OK)
return MICROBIT_I2C_ERROR;
// Wait for the part to enter standby mode...
while(this->read8(MAG_SYSMOD) & 0x03)
while(1)
{
// Read the status of the part...
// If we can't communicate with it over I2C, pass on the error.
result = this->read8(MAG_SYSMOD);
if (result == MICROBIT_I2C_ERROR)
return MICROBIT_I2C_ERROR;
// if the part in in standby, we're good to carry on.
if((result & 0x03) == 0)
break;
// Perform a power efficient sleep...
uBit.sleep(100);
}
// Find the nearest sample rate to that specified.
actualSampleRate = &MAG3110SampleRate[MAG3110_SAMPLE_RATES-1];
@ -256,10 +289,17 @@ void MicroBitCompass::configure()
this->samplePeriod = actualSampleRate->sample_period / 1000;
// Enable automatic reset after each sample;
writeCommand(MAG_CTRL_REG2, 0xA0);
result = writeCommand(MAG_CTRL_REG2, 0xA0);
if (result != MICROBIT_OK)
return MICROBIT_I2C_ERROR;
// Bring the device online, with the requested sample frequency.
writeCommand(MAG_CTRL_REG1, actualSampleRate->ctrl_reg1 | 0x01);
result = writeCommand(MAG_CTRL_REG1, actualSampleRate->ctrl_reg1 | 0x01);
if (result != MICROBIT_OK)
return MICROBIT_I2C_ERROR;
return MICROBIT_OK;
}
/**
@ -267,11 +307,12 @@ void MicroBitCompass::configure()
* n.b. the requested rate may not be possible on the hardware. In this case, the
* nearest lower rate is chosen.
* @param period the requested time between samples, in milliseconds.
* @return MICROBIT_OK or MICROBIT_I2C_ERROR if the magnetometer could not be updated.
*/
void MicroBitCompass::setPeriod(int period)
int MicroBitCompass::setPeriod(int period)
{
this->samplePeriod = period;
this->configure();
return this->configure();
}
/**
@ -286,7 +327,7 @@ int MicroBitCompass::getPeriod()
/**
* Attempts to determine the 8 bit ID from the magnetometer.
* @return the id of the compass (magnetometer)
* @return the id of the compass (magnetometer), or MICROBIT_I2C_ERROR if the magnetometer could not be updated.
*
* Example:
* @code
@ -296,19 +337,27 @@ int MicroBitCompass::getPeriod()
int MicroBitCompass::whoAmI()
{
uint8_t data;
int result;
result = readCommand(MAG_WHOAMI, &data, 1);
if (result != MICROBIT_OK)
return MICROBIT_I2C_ERROR;
readCommand(MAG_WHOAMI, &data, 1);
return (int)data;
}
/**
* Reads the currently die temperature of the compass.
* @return The temperature, in degrees celsius.
* @return the temperature in degrees celsius, or MICROBIT_I2C_ERROR if the magnetometer could not be updated.
*/
int MicroBitCompass::readTemperature()
{
int8_t temperature;
readCommand(MAG_DIE_TEMP, (uint8_t *)&temperature, 1);
int result;
result = readCommand(MAG_DIE_TEMP, (uint8_t *)&temperature, 1);
if (result != MICROBIT_OK)
return MICROBIT_I2C_ERROR;
return temperature;
}
@ -316,12 +365,13 @@ int MicroBitCompass::readTemperature()
/**
* Perform a calibration of the compass.
* This will fire MICROBIT_COMPASS_EVT_CAL_START.
* @return MICROBIT_OK, or MICROBIT_I2C_ERROR if the magnetometer could not be accessed.
* @note THIS MUST BE CALLED TO GAIN RELIABLE VALUES FROM THE COMPASS
*/
void MicroBitCompass::calibrateStart()
int MicroBitCompass::calibrateStart()
{
if(this->isCalibrating())
return;
return MICROBIT_CALIBRATION_IN_PROGRESS;
status |= MICROBIT_COMPASS_STATUS_CALIBRATING;
@ -330,6 +380,8 @@ void MicroBitCompass::calibrateStart()
maxSample = sample;
MicroBitEvent(id, MICROBIT_COMPASS_EVT_CAL_START);
return MICROBIT_OK;
}
@ -358,16 +410,6 @@ void MicroBitCompass::calibrateEnd()
status &= ~MICROBIT_COMPASS_STATUS_CALIBRATING;
status |= MICROBIT_COMPASS_STATUS_CALIBRATED;
//Store x, y and z values in persistent storage on the MAG3110
writeCommand(MAG_OFF_X_LSB, (uint8_t)average.x);
writeCommand(MAG_OFF_X_MSB, (uint8_t)(average.x >> 8));
writeCommand(MAG_OFF_Y_LSB, (uint8_t)average.y);
writeCommand(MAG_OFF_Y_MSB, (uint8_t)(average.y >> 8));
writeCommand(MAG_OFF_Z_LSB, (uint8_t)average.z);
writeCommand(MAG_OFF_Z_MSB, (uint8_t)(average.z >> 8));
MicroBitEvent(id, MICROBIT_COMPASS_EVT_CAL_END);
}
@ -392,15 +434,6 @@ int MicroBitCompass::isCalibrating()
*/
void MicroBitCompass::clearCalibration()
{
writeCommand(MAG_OFF_X_LSB, 0);
writeCommand(MAG_OFF_X_MSB, 0);
writeCommand(MAG_OFF_Y_LSB, 0);
writeCommand(MAG_OFF_Y_MSB, 0);
writeCommand(MAG_OFF_Z_LSB, 0);
writeCommand(MAG_OFF_Z_MSB, 0);
status &= ~MICROBIT_COMPASS_STATUS_CALIBRATED;
}

View File

@ -2,18 +2,19 @@
* Compatibility / portability funcitons and constants for the MicroBit DAL.
*/
#include "mbed.h"
#include "ErrorNo.h"
/**
* Performs an in buffer reverse of a given char array
* @param s the char* to reverse.
* @return the reversed char*
* @return MICROBIT_OK, or MICROBIT_INVALID_PARAMETER.
*/
void string_reverse(char *s)
int string_reverse(char *s)
{
//sanity check...
if(s == NULL)
return;
return MICROBIT_INVALID_PARAMETER;
char *j;
int c;
@ -26,6 +27,8 @@ void string_reverse(char *s)
*s++ = *j;
*j-- = c;
}
return MICROBIT_OK;
}
/**
@ -33,12 +36,16 @@ void string_reverse(char *s)
*
* @param n The number to convert.
* @param s Pointer to a buffer in which to store the resulting string.
* @return MICROBIT_OK, or MICROBIT_INVALID_PARAMETER.
*/
void itoa(int n, char *s)
int itoa(int n, char *s)
{
int i = 0;
int positive = (n >= 0);
if (s == NULL)
return MICROBIT_INVALID_PARAMETER;
// Record the sign of the number,
// Ensure our working value is positive.
if (positive)
@ -58,5 +65,7 @@ void itoa(int n, char *s)
// Flip the order.
string_reverse(s);
return MICROBIT_OK;
}

View File

@ -95,6 +95,7 @@ void MicroBitDisplay::renderFinish()
void MicroBitDisplay::render()
{
// Simple optimisation. If display is at zero brightness, there's nothign to do.
if(brightness == 0)
return;
@ -198,6 +199,7 @@ void MicroBitDisplay::renderGreyscale()
void
MicroBitDisplay::animationUpdate()
{
// If there's no ongoing animation, then nothing to do.
if (animationMode == ANIMATION_MODE_NONE)
return;
@ -331,13 +333,14 @@ void MicroBitDisplay::updateAnimateImage()
/**
* Resets the current given animation.
* @param delay the delay after which the animation is reset.
* @param delay the delay after which the animation is reset. Must be > 0.
* @return MICROBIT_OK, or MICROBIT_INVALID_PARAMETER.
*/
void MicroBitDisplay::resetAnimation(uint16_t delay)
int MicroBitDisplay::resetAnimation(uint16_t delay)
{
//sanitise this value
if(delay <= 0 )
delay = MICROBIT_DEFAULT_SCROLL_SPEED;
return MICROBIT_INVALID_PARAMETER;
// Reset any ongoing animation.
if (animationMode != ANIMATION_MODE_NONE)
@ -350,6 +353,8 @@ void MicroBitDisplay::resetAnimation(uint16_t delay)
this->image.clear();
this->animationDelay = delay;
this->animationTick = delay-1;
return MICROBIT_OK;
}
/**
@ -358,18 +363,19 @@ void MicroBitDisplay::resetAnimation(uint16_t delay)
* Returns immediately, and executes the animation asynchronously.
*
* @param s The string to display.
* @param delay The time to delay between characters, in timer ticks.
* @param delay The time to delay between characters, in milliseconds. Must be > 0.
* @return MICROBIT_OK, or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
* uBit.display.printAsync("abc123",400);
* @endcode
*/
void MicroBitDisplay::printAsync(ManagedString s, int delay)
int MicroBitDisplay::printAsync(ManagedString s, int delay)
{
//sanitise this value
if(delay <= 0 )
delay = MICROBIT_DEFAULT_SCROLL_SPEED;
return MICROBIT_INVALID_PARAMETER;
this->resetAnimation(delay);
@ -377,24 +383,30 @@ void MicroBitDisplay::printAsync(ManagedString s, int delay)
this->printingText = s;
animationMode = ANIMATION_MODE_PRINT_TEXT;
return MICROBIT_OK;
}
/**
* Prints the given character to the display.
*
* @param c The character to display.
* @param delay The time to delay between characters, in milliseconds. Must be > 0.
* @return MICROBIT_OK, or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
* uBit.display.print('p');
* @endcode
*/
void MicroBitDisplay::print(char c, int delay)
int MicroBitDisplay::print(char c, int delay)
{
if (delay < 0)
return MICROBIT_INVALID_PARAMETER;
image.print(c, 0, 0);
if(delay <= 0)
return;
if (delay == 0)
return MICROBIT_OK;
this->animationDelay = delay;
animationMode = ANIMATION_MODE_PRINT_CHARACTER;
@ -402,6 +414,8 @@ void MicroBitDisplay::print(char c, int delay)
// Wait for completion.
nonce = uBit.MessageBus.nonce();
fiber_wait_for_event(MICROBIT_ID_ALERT, nonce);
return MICROBIT_OK;
}
/**
@ -410,18 +424,19 @@ void MicroBitDisplay::print(char c, int delay)
* Blocks the calling thread until all the text has been displayed.
*
* @param s The string to display.
* @param delay The time to delay between characters, in timer ticks.
* @param delay The time to delay between characters, in milliseconds. Must be > 0.
* @return MICROBIT_OK, or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
* uBit.display.print("abc123",400);
* @endcode
*/
void MicroBitDisplay::print(ManagedString s, int delay)
int MicroBitDisplay::print(ManagedString s, int delay)
{
//sanitise this value
if(delay <= 0 )
delay = MICROBIT_DEFAULT_SCROLL_SPEED;
return MICROBIT_INVALID_PARAMETER;
// Start the effect.
this->printAsync(s, delay);
@ -429,6 +444,8 @@ void MicroBitDisplay::print(ManagedString s, int delay)
// Wait for completion.
nonce = uBit.MessageBus.nonce();
fiber_wait_for_event(MICROBIT_ID_ALERT, nonce);
return MICROBIT_OK;
}
/**
@ -436,7 +453,8 @@ void MicroBitDisplay::print(ManagedString s, int delay)
* Blocks the calling thread until all the text has been displayed.
*
* @param i The image to display.
* @param delay The time to delay between characters, in timer ticks.
* @param delay The time to display the image for, or zero to show the image forever. Must be >= 0.
* @return MICROBIT_OK, or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
@ -444,12 +462,15 @@ void MicroBitDisplay::print(ManagedString s, int delay)
* uBit.display.print(i,400);
* @endcode
*/
void MicroBitDisplay::print(MicroBitImage i, int x, int y, int alpha, int delay)
int MicroBitDisplay::print(MicroBitImage i, int x, int y, int alpha, int delay)
{
if(delay < 0)
return MICROBIT_INVALID_PARAMETER;
image.paste(i, x, y, alpha);
if(delay <= 0)
return;
if(delay == 0)
return MICROBIT_OK;
this->animationDelay = delay;
animationMode = ANIMATION_MODE_PRINT_CHARACTER;
@ -457,6 +478,8 @@ void MicroBitDisplay::print(MicroBitImage i, int x, int y, int alpha, int delay)
// Wait for completion.
nonce = uBit.MessageBus.nonce();
fiber_wait_for_event(MICROBIT_ID_ALERT, nonce);
return MICROBIT_OK;
}
/**
@ -465,18 +488,19 @@ void MicroBitDisplay::print(MicroBitImage i, int x, int y, int alpha, int delay)
* Returns immediately, and executes the animation asynchronously.
*
* @param s The string to display.
* @param delay The time to delay between characters, in timer ticks.
* @param delay The time to delay between each update to the display, in milliseconds. Must be > 0.
* @return MICROBIT_OK, or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
* uBit.display.scrollAsync("abc123",100);
* @endcode
*/
void MicroBitDisplay::scrollAsync(ManagedString s, int delay)
int MicroBitDisplay::scrollAsync(ManagedString s, int delay)
{
//sanitise this value
if(delay <= 0 )
delay = MICROBIT_DEFAULT_SCROLL_SPEED;
if(delay <= 0)
return MICROBIT_INVALID_PARAMETER;
this->resetAnimation(delay);
@ -485,14 +509,18 @@ void MicroBitDisplay::scrollAsync(ManagedString s, int delay)
this->scrollingText = s;
animationMode = ANIMATION_MODE_SCROLL_TEXT;
return MICROBIT_OK;
}
/**
* Scrolls the given image across the display, from right to left.
* Returns immediately, and executes the animation asynchronously.
*
* @param image The image to display.
* @param delay The time to delay between each scroll update, in timer ticks. Has a default.
* @param stride The number of pixels to move in each quantum. Has a default.
* @param delay The time to delay between each update to the display, in milliseconds. Must be > 0.
* @param stride The number of pixels to move in each update. Default value is the screen width.
* @return MICROBIT_OK, or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
@ -500,11 +528,11 @@ void MicroBitDisplay::scrollAsync(ManagedString s, int delay)
* uBit.display.scrollAsync(i,100,1);
* @endcode
*/
void MicroBitDisplay::scrollAsync(MicroBitImage image, int delay, int stride)
int MicroBitDisplay::scrollAsync(MicroBitImage image, int delay, int stride)
{
//sanitise the delay value
if(delay <= 0 )
delay = MICROBIT_DEFAULT_SCROLL_SPEED;
if(delay <= 0)
return MICROBIT_INVALID_PARAMETER;
this->resetAnimation(delay);
@ -514,6 +542,8 @@ void MicroBitDisplay::scrollAsync(MicroBitImage image, int delay, int stride)
this->scrollingImageRendered = false;
animationMode = ANIMATION_MODE_SCROLL_IMAGE;
return MICROBIT_OK;
}
/**
@ -522,18 +552,19 @@ void MicroBitDisplay::scrollAsync(MicroBitImage image, int delay, int stride)
* Blocks the calling thread until all the text has been displayed.
*
* @param s The string to display.
* @param delay The time to delay between characters, in timer ticks.
* @param delay The time to delay between each update to the display, in milliseconds. Must be > 0.
* @return MICROBIT_OK, or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
* uBit.display.scrollString("abc123",100);
* @endcode
*/
void MicroBitDisplay::scroll(ManagedString s, int delay)
int MicroBitDisplay::scroll(ManagedString s, int delay)
{
//sanitise this value
if(delay <= 0 )
delay = MICROBIT_DEFAULT_SCROLL_SPEED;
if(delay <= 0)
return MICROBIT_INVALID_PARAMETER;
// Start the effect.
this->scrollAsync(s, delay);
@ -541,6 +572,8 @@ void MicroBitDisplay::scroll(ManagedString s, int delay)
// Wait for completion.
nonce = uBit.MessageBus.nonce();
fiber_wait_for_event(MICROBIT_ID_ALERT, nonce);
return MICROBIT_OK;
}
/**
@ -548,8 +581,9 @@ void MicroBitDisplay::scroll(ManagedString s, int delay)
* Blocks the calling thread until all the text has been displayed.
*
* @param image The image to display.
* @param delay The time to delay between each scroll update, in timer ticks. Has a default.
* @param stride The number of pixels to move in each quantum. Has a default.
* @param delay The time to delay between each update to the display, in milliseconds. Must be > 0.
* @param stride The number of pixels to move in each update. Default value is the screen width.
* @return MICROBIT_OK, or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
@ -557,11 +591,11 @@ void MicroBitDisplay::scroll(ManagedString s, int delay)
* uBit.display.scroll(i,100,1);
* @endcode
*/
void MicroBitDisplay::scroll(MicroBitImage image, int delay, int stride)
int MicroBitDisplay::scroll(MicroBitImage image, int delay, int stride)
{
//sanitise the delay value
if(delay <= 0 )
delay = MICROBIT_DEFAULT_SCROLL_SPEED;
if(delay <= 0)
return MICROBIT_INVALID_PARAMETER;
// Start the effect.
this->scrollAsync(image, delay, stride);
@ -569,6 +603,8 @@ void MicroBitDisplay::scroll(MicroBitImage image, int delay, int stride)
// Wait for completion.
nonce = uBit.MessageBus.nonce();
fiber_wait_for_event(MICROBIT_ID_ALERT, nonce);
return MICROBIT_OK;
}
/**
@ -576,8 +612,9 @@ void MicroBitDisplay::scroll(MicroBitImage image, int delay, int stride)
* Returns immediately.
*
* @param image The image to display.
* @param delay The time to delay between each animation update, in timer ticks. Has a default.
* @param stride The number of pixels to move in each quantum. Has a default.
* @param delay The time to delay between each update to the display, in milliseconds. Must be > 0.
* @param stride The number of pixels to move in each update. Default value is the screen width.
* @return MICROBIT_OK, or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
@ -589,15 +626,15 @@ void MicroBitDisplay::scroll(MicroBitImage image, int delay, int stride)
* uBit.display.animateAsync(i,100,5);
* @endcode
*/
void MicroBitDisplay::animateAsync(MicroBitImage image, int delay, int stride, int startingPosition)
int MicroBitDisplay::animateAsync(MicroBitImage image, int delay, int stride, int startingPosition)
{
//sanitise the delay value
if(delay <= 0)
return MICROBIT_INVALID_PARAMETER;
// Assume right to left functionality, to align with scrollString()
stride = -stride;
//sanitise the delay value
if(delay <= 0 )
delay = MICROBIT_DEFAULT_SCROLL_SPEED;
// Reset any ongoing animation.
if (animationMode != ANIMATION_MODE_NONE)
{
@ -615,6 +652,8 @@ void MicroBitDisplay::animateAsync(MicroBitImage image, int delay, int stride, i
this->scrollingImageRendered = false;
animationMode = ANIMATION_MODE_ANIMATE_IMAGE;
return MICROBIT_OK;
}
/**
@ -622,8 +661,9 @@ void MicroBitDisplay::animateAsync(MicroBitImage image, int delay, int stride, i
* Blocks the calling thread until the animation is complete.
*
* @param image The image to display.
* @param delay The time to delay between each animation update, in timer ticks. Has a default.
* @param stride The number of pixels to move in each quantum. Has a default.
* @param delay The time to delay between each update to the display, in milliseconds. Must be > 0.
* @param stride The number of pixels to move in each update. Default value is the screen width.
* @return MICROBIT_OK, or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
@ -635,11 +675,11 @@ void MicroBitDisplay::animateAsync(MicroBitImage image, int delay, int stride, i
* uBit.display.animate(i,100,5);
* @endcode
*/
void MicroBitDisplay::animate(MicroBitImage image, int delay, int stride, int startingPosition)
int MicroBitDisplay::animate(MicroBitImage image, int delay, int stride, int startingPosition)
{
//sanitise the delay value
if(delay <= 0 )
delay = MICROBIT_DEFAULT_SCROLL_SPEED;
if(delay <= 0)
return MICROBIT_INVALID_PARAMETER;
// Start the effect.
this->animateAsync(image, delay, stride, startingPosition);
@ -647,29 +687,32 @@ void MicroBitDisplay::animate(MicroBitImage image, int delay, int stride, int st
// Wait for completion.
nonce = uBit.MessageBus.nonce();
fiber_wait_for_event(MICROBIT_ID_ALERT, nonce);
return MICROBIT_OK;
}
/**
* Sets the display brightness to the specified level.
* @param b The brightness to set the brightness to, in the range 0..255.
* @return MICROBIT_OK, or MICROBIT_INVALID_PARAMETER
*
* Example:
* @code
* uBit.display.setBrightness(255); //max brightness
* @endcode
*/
void MicroBitDisplay::setBrightness(int b)
int MicroBitDisplay::setBrightness(int b)
{
//sanitise the brightness level
if(b < 0 || b > 255)
return;
return MICROBIT_INVALID_PARAMETER;
this->brightness = b;
return MICROBIT_OK;
}
/**
* Sets the mode of the display.
* @param mode The mode to swap the display into. (can be either DISPLAY_MODE_GREYSCALE, or DISPLAY_MODE_NORMAL)
@ -707,23 +750,9 @@ int MicroBitDisplay::getBrightness()
* uBit.display.rotateTo(MICROBIT_DISPLAY_ROTATION_180); //rotates 180 degrees from original orientation
* @endcode
*/
void MicroBitDisplay::rotateTo(uint8_t position)
void MicroBitDisplay::rotateTo(DisplayRotation rotation)
{
//perform a switch on position to restrict range to distinct values
switch(position){
case MICROBIT_DISPLAY_ROTATION_0:
this->rotation = MICROBIT_DISPLAY_ROTATION_0;
break;
case MICROBIT_DISPLAY_ROTATION_90:
this->rotation = MICROBIT_DISPLAY_ROTATION_90;
break;
case MICROBIT_DISPLAY_ROTATION_180:
this->rotation = MICROBIT_DISPLAY_ROTATION_180;
break;
case MICROBIT_DISPLAY_ROTATION_270:
this->rotation = MICROBIT_DISPLAY_ROTATION_270;
break;
}
this->rotation = rotation;
}
/**

View File

@ -83,7 +83,6 @@ void queue_fiber(Fiber *f, Fiber **queue)
*/
void dequeue_fiber(Fiber *f)
{
// If this fiber is already dequeued, nothing the there's nothing to do.
if (f->queue == NULL)
return;
@ -248,7 +247,7 @@ void fiber_sleep(unsigned long t)
// it's time to spawn a new fiber...
if (currentFiber->flags & MICROBIT_FIBER_FLAG_FOB)
{
// Allocate a TCB from the new fiber. This will come from the tread pool if availiable,
// Allocate a new fiber. This will come from the fiber pool if availiable,
// else a new one will be allocated on the heap.
forkedFiber = getFiberContext();
@ -326,19 +325,20 @@ void fiber_wait_for_event(uint16_t id, uint16_t value)
* We only create an additional fiber if that function performs a block operation.
*
* @param entry_fn The function to execute.
* @return MICROBIT_OK, or MICROBIT_INVALID_PARAMETER.
*/
void invoke(void (*entry_fn)(void))
int invoke(void (*entry_fn)(void))
{
// Validate our parameters.
if (entry_fn == NULL)
return;
return MICROBIT_INVALID_PARAMETER;
if (currentFiber->flags & MICROBIT_FIBER_FLAG_FOB)
{
// If we attempt a fork on block whilst already in fork n block context,
// simply launch a fiber to deal with the request and we're done.
create_fiber(entry_fn);
return;
return MICROBIT_OK;
}
// Snapshot current context, but also update the Link Register to
@ -354,7 +354,7 @@ void invoke(void (*entry_fn)(void))
{
currentFiber->flags &= ~MICROBIT_FIBER_FLAG_FOB;
currentFiber->flags &= ~MICROBIT_FIBER_FLAG_PARENT;
return;
return MICROBIT_OK;
}
// Otherwise, we're here for the first time. Enter FORK ON BLOCK mode, and
@ -368,6 +368,8 @@ void invoke(void (*entry_fn)(void))
// The fiber will then re-enter the scheduler, so no need for further cleanup.
if (currentFiber->flags & MICROBIT_FIBER_FLAG_CHILD)
release_fiber();
return MICROBIT_OK;
}
/**
@ -381,19 +383,20 @@ void invoke(void (*entry_fn)(void))
*
* @param entry_fn The function to execute.
* @param param an untyped parameter passed into the entry_fn.
* @return MICROBIT_OK, or MICROBIT_INVALID_PARAMETER.
*/
void invoke(void (*entry_fn)(void *), void *param)
int invoke(void (*entry_fn)(void *), void *param)
{
// Validate our parameters.
if (entry_fn == NULL)
return;
return MICROBIT_INVALID_PARAMETER;
if (currentFiber->flags & (MICROBIT_FIBER_FLAG_FOB | MICROBIT_FIBER_FLAG_PARENT | MICROBIT_FIBER_FLAG_CHILD))
{
// If we attempt a fork on block whilst already in a fork on block context,
// simply launch a fiber to deal with the request and we're done.
create_fiber(entry_fn, param);
return;
return MICROBIT_OK;
}
// Snapshot current context, but also update the Link Register to
@ -409,7 +412,7 @@ void invoke(void (*entry_fn)(void *), void *param)
{
currentFiber->flags &= ~MICROBIT_FIBER_FLAG_FOB;
currentFiber->flags &= ~MICROBIT_FIBER_FLAG_PARENT;
return;
return MICROBIT_OK;
}
// Otherwise, we're here for the first time. Enter FORK ON BLOCK mode, and
@ -423,6 +426,8 @@ void invoke(void (*entry_fn)(void *), void *param)
// The fiber will then re-enter the scheduler, so no need for further cleanup.
if (currentFiber->flags & MICROBIT_FIBER_FLAG_CHILD)
release_fiber(param);
return MICROBIT_OK;
}
void launch_new_fiber(void (*ep)(void), void (*cp)(void))

View File

@ -137,9 +137,9 @@ microbit_create_sd_heap(HeapDefinition &heap)
#endif
microbit_initialise_heap(heap);
return 1;
return MICROBIT_OK;
#else
return 0;
return MICROBIT_NOT_SUPPORTED;
#endif
}
@ -151,7 +151,7 @@ microbit_create_nested_heap(HeapDefinition &heap)
// Ensure we're configured to use this heap at all. If not, we can safely return.
if (MICROBIT_HEAP_SIZE <= 0)
return 0;
return MICROBIT_INVALID_PARAMETER;
// Snapshot something at the top of the main heap.
p = native_malloc(sizeof(uint32_t));
@ -173,14 +173,14 @@ microbit_create_nested_heap(HeapDefinition &heap)
{
mb_heap_max -= 32;
if (mb_heap_max <= 0)
return 0;
return MICROBIT_NO_RESOURCES;
}
}
heap.heap_end = heap.heap_start + mb_heap_max / MICROBIT_HEAP_BLOCK_SIZE;
microbit_initialise_heap(heap);
return 1;
return MICROBIT_OK;
}
/**
@ -188,18 +188,29 @@ microbit_create_nested_heap(HeapDefinition &heap)
* After this is called, any future calls to malloc, new, free or delete will use the new heap.
* n.b. only code that #includes MicroBitHeapAllocator.h will use this heap. This includes all micro:bit runtime
* code, and user code targetting the runtime. External code can choose to include this file, or
* simply use the strandard mbed heap.
* simply use the standard mbed heap.
*/
int
microbit_heap_init()
{
int r = 0;
int result;
// Disable IRQ temporarily to ensure no race conditions!
__disable_irq();
r += microbit_create_nested_heap(heap[0]);
r += microbit_create_sd_heap(heap[1]);
result = microbit_create_nested_heap(heap[0]);
if (result != MICROBIT_OK)
{
__enable_irq();
return MICROBIT_NO_RESOURCES;
}
result = microbit_create_sd_heap(heap[1]);
if (result != MICROBIT_OK)
{
__enable_irq();
return MICROBIT_NO_RESOURCES;
}
// Enable Interrupts
__enable_irq();
@ -207,7 +218,8 @@ microbit_heap_init()
#if CONFIG_ENABLED(MICROBIT_DBG) && CONFIG_ENABLED(MICROBIT_HEAP_DBG)
microbit_heap_print();
#endif
return r;
return MICROBIT_OK;
}
/**

View File

@ -19,7 +19,16 @@ MicroBitI2C::MicroBitI2C(PinName sda, PinName scl) : I2C(sda,scl)
this->retries = 0;
}
/**
* Performs a complete read transaction. The bottom bit of the address is forced to 1 to indicate a read.
*
* @address 8-bit I2C slave address [ addr | 1 ]
* @data Pointer to the byte-array to read data in to
* @length Number of bytes to read
* @repeated Repeated start, true - don't send stop at end.
*
* @return MICROBIT_OK on success, MICROBIT_I2C_ERROR if an unresolved read failure is detected.
*/
int MicroBitI2C::read(int address, char *data, int length, bool repeated)
{
int result = I2C::read(address,data,length,repeated);
@ -38,18 +47,25 @@ int MicroBitI2C::read(int address, char *data, int length, bool repeated)
retries++;
}
if(retries == MICROBIT_I2C_MAX_RETRIES - 1)
uBit.panic(MICROBIT_I2C_LOCKUP);
retries = 0;
return result;
if(result != 0)
return MICROBIT_I2C_ERROR;
retries = 0;
return MICROBIT_OK;
}
/**
* Performs a complete write transaction. The bottom bit of the address is forced to 0 to indicate a write.
*
* @address 8-bit I2C slave address [ addr | 0 ]
* @data Pointer to the byte-arraycontaining the data to write
* @length Number of bytes to write
* @repeated Repeated start, true - don't send stop at end.
*
* @return MICROBIT_OK on success, MICROBIT_I2C_ERROR if an unresolved write failure is detected.
*/
int MicroBitI2C::write(int address, const char *data, int length, bool repeated)
{
int result = I2C::write(address,data,length,repeated);
//0 indicates a success, presume failure
@ -67,10 +83,9 @@ int MicroBitI2C::write(int address, const char *data, int length, bool repeated)
retries++;
}
if(retries == MICROBIT_I2C_MAX_RETRIES - 1)
uBit.panic(MICROBIT_I2C_LOCKUP);
if(result != 0)
return MICROBIT_I2C_ERROR;
retries = 0;
return result;
retries = 0;
return MICROBIT_OK;
}

View File

@ -335,6 +335,7 @@ void MicroBitImage::clear()
* @param x The co-ordinate of the pixel to change w.r.t. top left origin.
* @param y The co-ordinate of the pixel to change w.r.t. top left origin.
* @param value The new value of the pixel (the brightness level 0-255)
* @return MICROBIT_OK, or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
@ -342,18 +343,22 @@ void MicroBitImage::clear()
* i.setPixelValue(0,0,255);
* @endcode
*/
void MicroBitImage::setPixelValue(int16_t x , int16_t y, uint8_t value)
int MicroBitImage::setPixelValue(int16_t x , int16_t y, uint8_t value)
{
//sanity check
if(x >= width || y >= height || x < 0 || y < 0)
return;
return MICROBIT_INVALID_PARAMETER;
this->bitmap[y*width+x] = value;
return MICROBIT_OK;
}
/**
* Determines the value of a given pixel.
* @return The value assigned to the given pixel location (the brightness level 0-255)
*
* @param x The x co-ordinate of the pixel to read. Must be within the dimensions of the image.
* @param y The y co-ordinate of the pixel to read. Must be within the dimensions of the image.
* @return The value assigned to the given pixel location (the brightness level 0-255), or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
@ -365,7 +370,7 @@ int MicroBitImage::getPixelValue(int16_t x , int16_t y)
{
//sanity check
if(x >= width || y >= height || x < 0 || y < 0)
return MICROBIT_INVALID_VALUE;
return MICROBIT_INVALID_PARAMETER;
return this->bitmap[y*width+x];
}
@ -375,9 +380,10 @@ int MicroBitImage::getPixelValue(int16_t x , int16_t y)
* 2D array representing the image.
* Origin is in the top left corner of the image.
*
* @param x the width of the image.
* @param y the height of the image.
* @param x the width of the image. Must be within the dimensions of the image.
* @param y the width of the image. Must be within the dimensions of the image.
* @param bitmap a 2D array representing the image.
* @return MICROBIT_OK on success, or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
@ -386,7 +392,7 @@ int MicroBitImage::getPixelValue(int16_t x , int16_t y)
* i.printImage(0,0,heart);
* @endcode
*/
void MicroBitImage::printImage(int16_t width, int16_t height, const uint8_t *bitmap)
int MicroBitImage::printImage(int16_t width, int16_t height, const uint8_t *bitmap)
{
const uint8_t *pIn;
uint8_t *pOut;
@ -394,7 +400,7 @@ void MicroBitImage::printImage(int16_t width, int16_t height, const uint8_t *bit
// Sanity check.
if (width <= 0 || width <= 0 || bitmap == NULL)
return;
return MICROBIT_INVALID_PARAMETER;
// Calcualte sane start pointer.
pixelsToCopyX = min(width,this->width);
@ -410,6 +416,8 @@ void MicroBitImage::printImage(int16_t width, int16_t height, const uint8_t *bit
pIn += width;
pOut += this->width;
}
return MICROBIT_OK;
}
/**
@ -444,7 +452,7 @@ int MicroBitImage::paste(const MicroBitImage &image, int16_t x, int16_t y, uint8
cx = x < 0 ? min(image.width + x, width) : min(image.width, width - x);
cy = y < 0 ? min(image.height + y, height) : min(image.height, height - y);
// Calcualte sane start pointer.
// Calculate sane start pointer.
pIn = image.bitmap;
pIn += (x < 0) ? -x : 0;
pIn += (y < 0) ? -image.width*y : 0;
@ -495,6 +503,7 @@ int MicroBitImage::paste(const MicroBitImage &image, int16_t x, int16_t y, uint8
* @param c The character to display.
* @param x The x co-ordinate of on the image to place the top left of the character
* @param y The y co-ordinate of on the image to place the top left of the character
* @return MICROBIT_OK on success, or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
@ -502,7 +511,7 @@ int MicroBitImage::paste(const MicroBitImage &image, int16_t x, int16_t y, uint8
* i.print('a',0,0);
* @endcode
*/
void MicroBitImage::print(char c, int16_t x, int16_t y)
int MicroBitImage::print(char c, int16_t x, int16_t y)
{
unsigned char v;
int x1, y1;
@ -511,7 +520,7 @@ void MicroBitImage::print(char c, int16_t x, int16_t y)
// Sanity check. Silently ignore anything out of bounds.
if (x >= width || y >= height || c < MICROBIT_FONT_ASCII_START || c > font.asciiEnd)
return;
return MICROBIT_INVALID_PARAMETER;
// Paste.
int offset = (c-MICROBIT_FONT_ASCII_START) * 5;
@ -534,6 +543,8 @@ void MicroBitImage::print(char c, int16_t x, int16_t y)
this->bitmap[y1*width+x1] = (v & (0x10 >> col)) ? 255 : 0;
}
}
return MICROBIT_OK;
}
@ -541,6 +552,7 @@ void MicroBitImage::print(char c, int16_t x, int16_t y)
* Shifts the pixels in this Image a given number of pixels to the Left.
*
* @param n The number of pixels to shift.
* @return MICROBIT_OK on success, or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
@ -549,18 +561,18 @@ void MicroBitImage::print(char c, int16_t x, int16_t y)
* i.shiftLeft(5); //displays a small heart :)
* @endcode
*/
void MicroBitImage::shiftLeft(int16_t n)
int MicroBitImage::shiftLeft(int16_t n)
{
uint8_t *p = bitmap;
int pixels = width-n;
if (n <= 0 )
return;
return MICROBIT_INVALID_PARAMETER;
if(n >= width)
{
clear();
return;
return MICROBIT_OK;
}
for (int y = 0; y < height; y++)
@ -570,12 +582,15 @@ void MicroBitImage::shiftLeft(int16_t n)
memclr(p+pixels, n);
p += width;
}
return MICROBIT_OK;
}
/**
* Shifts the pixels in this Image a given number of pixels to the Right.
*
* @param n The number of pixels to shift.
* @return MICROBIT_OK on success, or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
@ -585,18 +600,18 @@ void MicroBitImage::shiftLeft(int16_t n)
* i.shiftRight(5); //displays a big heart :)
* @endcode
*/
void MicroBitImage::shiftRight(int16_t n)
int MicroBitImage::shiftRight(int16_t n)
{
uint8_t *p = bitmap;
int pixels = width-n;
if (n <= 0)
return;
return MICROBIT_INVALID_PARAMETER;
if(n >= width)
{
clear();
return;
return MICROBIT_OK;
}
for (int y = 0; y < height; y++)
@ -606,6 +621,8 @@ void MicroBitImage::shiftRight(int16_t n)
memclr(p, n);
p += width;
}
return MICROBIT_OK;
}
@ -613,6 +630,7 @@ void MicroBitImage::shiftRight(int16_t n)
* Shifts the pixels in this Image a given number of pixels to Upward.
*
* @param n The number of pixels to shift.
* @return MICROBIT_OK on success, or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
@ -621,17 +639,17 @@ void MicroBitImage::shiftRight(int16_t n)
* i.shiftUp(1);
* @endcode
*/
void MicroBitImage::shiftUp(int16_t n)
int MicroBitImage::shiftUp(int16_t n)
{
uint8_t *pOut, *pIn;
if (n <= 0 )
return;
return MICROBIT_INVALID_PARAMETER;
if(n >= height)
{
clear();
return;
return MICROBIT_OK;
}
pOut = bitmap;
@ -648,6 +666,8 @@ void MicroBitImage::shiftUp(int16_t n)
pIn += width;
pOut += width;
}
return MICROBIT_OK;
}
@ -655,6 +675,7 @@ void MicroBitImage::shiftUp(int16_t n)
* Shifts the pixels in this Image a given number of pixels to Downward.
*
* @param n The number of pixels to shift.
* @return MICROBIT_OK on success, or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
@ -663,17 +684,17 @@ void MicroBitImage::shiftUp(int16_t n)
* i.shiftDown(1);
* @endcode
*/
void MicroBitImage::shiftDown(int16_t n)
int MicroBitImage::shiftDown(int16_t n)
{
uint8_t *pOut, *pIn;
if (n <= 0 )
return;
return MICROBIT_INVALID_PARAMETER;
if(n >= height)
{
clear();
return;
return MICROBIT_OK;
}
pOut = bitmap + width*(height-1);
@ -690,6 +711,8 @@ void MicroBitImage::shiftDown(int16_t n)
pIn -= width;
pOut -= width;
}
return MICROBIT_OK;
}
/**

View File

@ -210,9 +210,7 @@ void MicroBitMessageBus::send(MicroBitEvent evt)
// We simply queue processing of the event until we're scheduled in normal thread context.
// We do this to avoid the possibility of executing event handler code in IRQ context, which may bring
// hidden race conditions to kids code. Queuing all events ensures causal ordering (total ordering in fact).
this->queueEvent(evt);
return;
}
/*
@ -269,7 +267,9 @@ int MicroBitMessageBus::process(MicroBitEvent &evt, uint32_t mask)
* @param value The value of messages to listen for. Events with any other values will be filtered.
* Use MICROBIT_VALUE_ANY to receive events of any value.
*
* @param hander The function to call when an event is received.
* @param handler The function to call when an event is received.
*
* @return MICROBIT_OK on success MICROBIT_INVALID_PARAMETER
*
* Example:
* @code
@ -281,26 +281,30 @@ int MicroBitMessageBus::process(MicroBitEvent &evt, uint32_t mask)
* @endcode
*/
void MicroBitMessageBus::listen(int id, int value, void (*handler)(MicroBitEvent), uint16_t flags)
int MicroBitMessageBus::listen(int id, int value, void (*handler)(MicroBitEvent), uint16_t flags)
{
if (handler == NULL)
return;
return MICROBIT_INVALID_PARAMETER;
MicroBitListener *newListener = new MicroBitListener(id, value, handler, flags);
if(!add(newListener))
if(add(newListener) != MICROBIT_OK)
delete newListener;
return MICROBIT_OK;
}
void MicroBitMessageBus::listen(int id, int value, void (*handler)(MicroBitEvent, void*), void* arg, uint16_t flags)
int MicroBitMessageBus::listen(int id, int value, void (*handler)(MicroBitEvent, void*), void* arg, uint16_t flags)
{
if (handler == NULL)
return;
return MICROBIT_INVALID_PARAMETER;
MicroBitListener *newListener = new MicroBitListener(id, value, handler, arg, flags);
if(!add(newListener))
if(add(newListener) != MICROBIT_OK)
delete newListener;
return MICROBIT_OK;
}
/**
@ -322,13 +326,15 @@ void MicroBitMessageBus::listen(int id, int value, void (*handler)(MicroBitEvent
* uBit.MessageBus.ignore(MICROBIT_ID_BUTTON_B, MICROBIT_BUTTON_EVT_CLICK, onButtonBClick);
* @endcode
*/
void MicroBitMessageBus::ignore(int id, int value, void (*handler)(MicroBitEvent))
int MicroBitMessageBus::ignore(int id, int value, void (*handler)(MicroBitEvent))
{
if (handler == NULL)
return;
return MICROBIT_INVALID_PARAMETER;
MicroBitListener listener(id, value, handler);
remove(&listener);
return MICROBIT_OK;
}
/**
@ -350,14 +356,16 @@ void MicroBitMessageBus::ignore(int id, int value, void (*handler)(MicroBitEvent
* uBit.MessageBus.ignore(MICROBIT_ID_BUTTON_B, MICROBIT_BUTTON_EVT_CLICK, onButtonBClick);
* @endcode
*/
void MicroBitMessageBus::ignore(int id, int value, void (*handler)(MicroBitEvent, void*))
int MicroBitMessageBus::ignore(int id, int value, void (*handler)(MicroBitEvent, void*))
{
if (handler == NULL)
return;
return MICROBIT_INVALID_PARAMETER;
// The remove function is not comparing the [arg] anyhow.
MicroBitListener listener(id, value, handler, NULL);
remove(&listener);
return MICROBIT_OK;
}
@ -373,7 +381,7 @@ int MicroBitMessageBus::add(MicroBitListener *newListener)
//handler can't be NULL!
if (newListener == NULL)
return 0;
return MICROBIT_INVALID_PARAMETER;
l = listeners;
@ -387,7 +395,7 @@ int MicroBitMessageBus::add(MicroBitListener *newListener)
methodCallback = (newListener->flags & MESSAGE_BUS_LISTENER_METHOD) && (l->flags & MESSAGE_BUS_LISTENER_METHOD);
if (l->id == newListener->id && l->value == newListener->value && (methodCallback ? *l->cb_method == *newListener->cb_method : l->cb == newListener->cb))
return 0;
return MICROBIT_NOT_SUPPORTED;
l = l->next;
}
@ -397,7 +405,7 @@ int MicroBitMessageBus::add(MicroBitListener *newListener)
if (listeners == NULL)
{
listeners = newListener;
return 1;
return MICROBIT_OK;
}
// We maintain an ordered list of listeners.
@ -436,14 +444,14 @@ int MicroBitMessageBus::add(MicroBitListener *newListener)
p->next = newListener;
}
return 1;
return MICROBIT_OK;
}
/**
* Remove a MicroBitListener from the list that matches the given listener.
* @param listener The MicroBitListener to validate.
* @return The number of listeners removed from the list.
*/
* Remove the given MicroBitListener from the list of event handlers.
* @param listener The MicroBitListener to remove.
* @return MICROBIT_OK if the listener is valid, MICROBIT_INVALID_PARAMETER otherwise.
*/
int MicroBitMessageBus::remove(MicroBitListener *listener)
{
MicroBitListener *l, *p;
@ -451,7 +459,7 @@ int MicroBitMessageBus::remove(MicroBitListener *listener)
//handler can't be NULL!
if (listener == NULL)
return 0;
return MICROBIT_INVALID_PARAMETER;
l = listeners;
p = NULL;
@ -488,7 +496,7 @@ int MicroBitMessageBus::remove(MicroBitListener *listener)
l = l->next;
}
return removed;
return MICROBIT_OK;
}
/**

View File

@ -66,14 +66,20 @@ void MicroBitPin::disconnect()
* Example:
* @code
* MicroBitPin P0(MICROBIT_ID_IO_P0, MICROBIT_PIN_P0, PIN_CAPABILITY_BOTH);
* P0.setDigitalValue(1); // P0 is now HI!
* P0.setDigitalValue(1); // P0 is now HI
* @return MICROBIT_OK on success, MICROBIT_INVALID_PARAMETER if value is out of range, or MICROBIT_NOT_SUPPORTED
* if the given pin does not have digital capability.
* @endcode
*/
void MicroBitPin::setDigitalValue(int value)
int MicroBitPin::setDigitalValue(int value)
{
//check if this pin has a digital mode...
if(!(PIN_CAPABILITY_DIGITAL & capability) || value < 0 || value > 1)
return;
// Check if this pin has a digital mode...
if(!(PIN_CAPABILITY_DIGITAL & capability))
return MICROBIT_NOT_SUPPORTED;
// Ensure we have a valid value.
if (value < 0 || value > 1)
return MICROBIT_INVALID_PARAMETER;
// Move into a Digital input state if necessary.
if (!(status & IO_STATUS_DIGITAL_OUT)){
@ -82,13 +88,15 @@ void MicroBitPin::setDigitalValue(int value)
status |= IO_STATUS_DIGITAL_OUT;
}
//write the value!
// Write the value.
((DigitalOut *)pin)->write(value);
return MICROBIT_OK;
}
/**
* Configures this IO pin as a digital input (if necessary) and tests its current value.
* @return 1 if this input is high, 0 otherwise.
* @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.
*
* Example:
* @code
@ -100,12 +108,12 @@ int MicroBitPin::getDigitalValue()
{
//check if this pin has a digital mode...
if(!(PIN_CAPABILITY_DIGITAL & capability))
return MICROBIT_IO_OP_NA;
return MICROBIT_NOT_SUPPORTED;
// Move into a Digital input state if necessary.
if (!(status & IO_STATUS_DIGITAL_IN)){
disconnect();
pin = new DigitalIn(name,PullDown); //pull down!
pin = new DigitalIn(name,PullDown);
status |= IO_STATUS_DIGITAL_IN;
}
@ -113,20 +121,20 @@ int MicroBitPin::getDigitalValue()
}
/**
* Configures this IO pin as an analogue output (if necessary and possible).
* Change the DAC value to the given level.
* @param value the level to set on the output pin, in the range 0..255
* @note We have a maximum of 3 PWM channels for this device - one is reserved for the display... the other two are reconfigured dynamically when they are required.
*/
void MicroBitPin::setAnalogValue(int value)
* Configures this IO pin as an analog/pwm output, and change the output value to the given level.
* @param value the level to set on the output pin, in the range 0 - 1024
* @return MICROBIT_OK on success, MICROBIT_INVALID_PARAMETER if value is out of range, or MICROBIT_NOT_SUPPORTED
* if the given pin does not have analog capability.
*/
int MicroBitPin::setAnalogValue(int value)
{
//check if this pin has an analogue mode...
if(!(PIN_CAPABILITY_ANALOG & capability))
return;
return MICROBIT_NOT_SUPPORTED;
//sanitise the brightness level
if(value < 0 || value > MICROBIT_PIN_MAX_OUTPUT)
return;
return MICROBIT_INVALID_PARAMETER;
float level = (float)value / float(MICROBIT_PIN_MAX_OUTPUT);
@ -140,25 +148,26 @@ void MicroBitPin::setAnalogValue(int value)
//perform a write with an extra check! :)
if(((DynamicPwm *)pin)->getPinName() == name)
((DynamicPwm *)pin)->write(level);
return MICROBIT_OK;
}
/**
* Configures this IO pin as an analogue input (if necessary and possible).
* @return the current analogue level on the pin, in the range 0-0xFFFF
*
* Example:
* @code
* MicroBitPin P0(MICROBIT_ID_IO_P0, MICROBIT_PIN_P0, PIN_CAPABILITY_BOTH);
* P0.getAnalogValue(); // P0 is a value in the range of 0 - 0xFFFF
* @endcode
*/
* Configures this IO pin as an analogue input (if necessary and possible).
* @return the current analogue level on the pin, in the range 0 - 1024, or MICROBIT_NOT_SUPPORTED if the given pin does not have analog capability.
*
* Example:
* @code
* MicroBitPin P0(MICROBIT_ID_IO_P0, MICROBIT_PIN_P0, PIN_CAPABILITY_BOTH);
* P0.getAnalogValue(); // P0 is a value in the range of 0 - 1024
* @endcode
*/
int MicroBitPin::getAnalogValue()
{
//check if this pin has an analogue mode...
if(!(PIN_CAPABILITY_ANALOG & capability))
return MICROBIT_IO_OP_NA;
return MICROBIT_NOT_SUPPORTED;
// Move into an analogue input state if necessary.
if (!(status & IO_STATUS_ANALOG_IN)){
@ -209,7 +218,7 @@ int MicroBitPin::isAnalog()
/**
* Configures this IO pin as a makey makey style touch sensor (if necessary) and tests its current debounced state.
* @return 1 if pin is touched, 0 otherwise.
* @return 1 if pin is touched, 0 if not, or MICROBIT_NOT_SUPPORTED if this pin does not support touch capability.
*
* Example:
* @code
@ -224,7 +233,7 @@ int MicroBitPin::isTouched()
{
//check if this pin has a touch mode...
if(!(PIN_CAPABILITY_TOUCH & capability))
return MICROBIT_IO_OP_NA;
return MICROBIT_NOT_SUPPORTED;
// Move into a touch input state if necessary.
if (!(status & IO_STATUS_TOUCH_IN)){
@ -238,21 +247,28 @@ int MicroBitPin::isTouched()
/**
* Configures the PWM period of the analog output to the given value.
* If this pin is not configured as an analog output, the operation
* has no effect.
*
* @param period The new period for the analog output in microseconds.
* @return MICROBIT_OK on success, or MICROBIT_NOT_SUPPORTED if the
* given pin is not configured as an analog output.
*/
void MicroBitPin::setAnalogPeriodUs(int period)
int MicroBitPin::setAnalogPeriodUs(int period)
{
if (status & IO_STATUS_ANALOG_OUT)
((DynamicPwm *)pin)->setPeriodUs(period);
if (!(status & IO_STATUS_ANALOG_OUT))
return MICROBIT_NOT_SUPPORTED;
((DynamicPwm *)pin)->setPeriodUs(period);
return MICROBIT_OK;
}
/**
* Same thing as setAnalogPeriodUs, but with milliseconds.
*/
void MicroBitPin::setAnalogPeriod(int period)
* Configures the PWM period of the analog output to the given value.
*
* @param period The new period for the analog output in microseconds.
* @return MICROBIT_OK on success, or MICROBIT_NOT_SUPPORTED if the
* given pin is not configured as an analog output.
*/
int MicroBitPin::setAnalogPeriod(int period)
{
setAnalogPeriodUs(period*1000);
return setAnalogPeriodUs(period*1000);
}