merging pxt-microbit-core into the target

This commit is contained in:
Peli de Halleux 2016-11-29 15:06:34 -08:00
parent 23f83df6df
commit f046f0e50c
7 changed files with 1502 additions and 61 deletions

373
libs/core/ManagedBuffer.cpp Normal file
View File

@ -0,0 +1,373 @@
#include "MicroBit.h"
#include "ManagedBuffer.h"
#include <limits.h>
static const char empty[] __attribute__ ((aligned (4))) = "\xff\xff\0\0\0";
/**
* Internal constructor helper.
* Configures this ManagedBuffer to refer to the static empty buffer.
*/
void ManagedBuffer::initEmpty()
{
ptr = (BufferData*)(void*)empty;
}
/**
* Default Constructor.
* Creates an empty ManagedBuffer.
*
* Example:
* @code
* ManagedBuffer p();
* @endcode
*/
ManagedBuffer::ManagedBuffer()
{
initEmpty();
}
/**
* Constructor.
* Creates an empty ManagedBuffer of the given size.
*
* @param length The length of the buffer to create.
*
* Example:
* @code
* ManagedBuffer p(16); // Creates a ManagedBuffer 16 bytes long.
* @endcode
*/
ManagedBuffer::ManagedBuffer(int length)
{
this->init(NULL, length);
}
/**
* Constructor.
* Creates a new ManagedBuffer of the given size,
* and fills it with the data provided.
*
* @param data The data with which to fill the buffer.
* @param length The length of the buffer to create.
*
* Example:
* @code
* uint8_t buf = {13,5,2};
* ManagedBuffer p(buf, 3); // Creates a ManagedBuffer 3 bytes long.
* @endcode
*/
ManagedBuffer::ManagedBuffer(uint8_t *data, int length)
{
this->init(data, length);
}
/**
* Copy Constructor.
* Add ourselves as a reference to an existing ManagedBuffer.
*
* @param buffer The ManagedBuffer to reference.
*
* Example:
* @code
* ManagedBuffer p();
* ManagedBuffer p2(i); // Refers to the same buffer as p.
* @endcode
*/
ManagedBuffer::ManagedBuffer(const ManagedBuffer &buffer)
{
ptr = buffer.ptr;
ptr->incr();
}
/**
* Constructor.
* Create a buffer from a raw BufferData pointer. It will ptr->incr(). This is to be used by specialized runtimes.
*
* @param p The pointer to use.
*/
ManagedBuffer::ManagedBuffer(BufferData *p)
{
ptr = p;
ptr->incr();
}
/**
* Internal constructor-initialiser.
*
* @param data The data with which to fill the buffer.
* @param length The length of the buffer to create.
*
*/
void ManagedBuffer::init(uint8_t *data, int length)
{
if (length <= 0) {
initEmpty();
return;
}
ptr = (BufferData *) malloc(sizeof(BufferData) + length);
ptr->init();
ptr->length = length;
// Copy in the data buffer, if provided.
if (data)
memcpy(ptr->payload, data, length);
else
memset(ptr->payload, 0, length);
}
/**
* Destructor.
* Removes buffer resources held by the instance.
*/
ManagedBuffer::~ManagedBuffer()
{
ptr->decr();
}
/**
* Copy assign operation.
*
* Called when one ManagedBuffer is assigned the value of another using the '=' operator.
* Decrements our reference count and free up the buffer as necessary.
* Then, update our buffer to refer to that of the supplied ManagedBuffer,
* and increase its reference count.
*
* @param p The ManagedBuffer to reference.
*
* Example:
* @code
* uint8_t buf = {13,5,2};
* ManagedBuffer p1(16);
* ManagedBuffer p2(buf, 3);
*
* p1 = p2;
* @endcode
*/
ManagedBuffer& ManagedBuffer::operator = (const ManagedBuffer &p)
{
if(ptr == p.ptr)
return *this;
ptr->decr();
ptr = p.ptr;
ptr->incr();
return *this;
}
/**
* Equality operation.
*
* Called when one ManagedBuffer is tested to be equal to another using the '==' operator.
*
* @param p The ManagedBuffer to test ourselves against.
* @return true if this ManagedBuffer is identical to the one supplied, false otherwise.
*
* Example:
* @code
*
* uint8_t buf = {13,5,2};
* ManagedBuffer p1(16);
* ManagedBuffer p2(buf, 3);
*
* if(p1 == p2) // will be true
* uBit.display.scroll("same!");
* @endcode
*/
bool ManagedBuffer::operator== (const ManagedBuffer& p)
{
if (ptr == p.ptr)
return true;
else
return (ptr->length == p.ptr->length && (memcmp(ptr->payload, p.ptr->payload, ptr->length)==0));
}
/**
* Sets the byte at the given index to value provided.
* @param position The index of the byte to change.
* @param value The new value of the byte (0-255).
* @return MICROBIT_OK, or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
* ManagedBuffer p1(16);
* p1.setByte(0,255); // Sets the firts byte in the buffer to the value 255.
* @endcode
*/
int ManagedBuffer::setByte(int position, uint8_t value)
{
if (0 <= position && position < ptr->length)
{
ptr->payload[position] = value;
return MICROBIT_OK;
}
else
{
return MICROBIT_INVALID_PARAMETER;
}
}
/**
* Determines the value of the given byte in the buffer.
*
* @param position The index of the byte to read.
* @return The value of the byte at the given position, or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
* ManagedBuffer p1(16);
* p1.setByte(0,255); // Sets the firts byte in the buffer to the value 255.
* p1.getByte(0); // Returns 255.
* @endcode
*/
int ManagedBuffer::getByte(int position)
{
if (0 <= position && position < ptr->length)
return ptr->payload[position];
else
return MICROBIT_INVALID_PARAMETER;
}
/**
* Get current ptr, do not decr() it, and set the current instance to an empty buffer.
* This is to be used by specialized runtimes which pass BufferData around.
*/
BufferData *ManagedBuffer::leakData()
{
BufferData* res = ptr;
initEmpty();
return res;
}
int ManagedBuffer::fill(uint8_t value, int offset, int length)
{
if (offset < 0 || offset > ptr->length)
return MICROBIT_INVALID_PARAMETER;
if (length < 0)
length = ptr->length;
length = min(length, ptr->length - offset);
memset(ptr->payload + offset, value, length);
return MICROBIT_OK;
}
ManagedBuffer ManagedBuffer::slice(int offset, int length) const
{
offset = min(ptr->length, offset);
if (length < 0)
length = ptr->length;
length = min(length, ptr->length - offset);
return ManagedBuffer(ptr->payload + offset, length);
}
void ManagedBuffer::shift(int offset, int start, int len)
{
if (len < 0) len = ptr->length - start;
if (start < 0 || start + len > ptr->length || start + len < start
|| len == 0 || offset == 0 || offset == INT_MIN) return;
if (offset <= -len || offset >= len) {
fill(0);
return;
}
uint8_t *data = ptr->payload + start;
if (offset < 0) {
offset = -offset;
memmove(data + offset, data, len - offset);
memset(data, 0, offset);
} else {
len = len - offset;
memmove(data, data + offset, len);
memset(data + len, 0, offset);
}
}
void ManagedBuffer::rotate(int offset, int start, int len)
{
if (len < 0) len = ptr->length - start;
if (start < 0 || start + len > ptr-> length || start + len < start
|| len == 0 || offset == 0 || offset == INT_MIN) return;
if (offset < 0)
offset += len << 8; // try to make it positive
offset %= len;
if (offset < 0)
offset += len;
uint8_t *data = ptr->payload + start;
uint8_t *n_first = data + offset;
uint8_t *first = data;
uint8_t *next = n_first;
uint8_t *last = data + len;
while (first != next) {
uint8_t tmp = *first;
*first++ = *next;
*next++ = tmp;
if (next == last) {
next = n_first;
} else if (first == n_first) {
n_first = next;
}
}
}
int ManagedBuffer::writeBuffer(int dstOffset, const ManagedBuffer &src, int srcOffset, int length)
{
if (length < 0)
length = src.length();
if (srcOffset < 0 || dstOffset < 0 || dstOffset > ptr->length)
return MICROBIT_INVALID_PARAMETER;
length = min(src.length() - srcOffset, ptr->length - dstOffset);
if (length < 0)
return MICROBIT_INVALID_PARAMETER;
if (ptr == src.ptr) {
memmove(getBytes() + dstOffset, src.ptr->payload + srcOffset, length);
} else {
memcpy(getBytes() + dstOffset, src.ptr->payload + srcOffset, length);
}
return MICROBIT_OK;
}
int ManagedBuffer::writeBytes(int offset, uint8_t *src, int length, bool swapBytes)
{
if (offset < 0 || length < 0 || offset + length > ptr->length)
return MICROBIT_INVALID_PARAMETER;
if (swapBytes) {
uint8_t *p = ptr->payload + offset + length;
for (int i = 0; i < length; ++i)
*--p = src[i];
} else {
memcpy(ptr->payload + offset, src, length);
}
return MICROBIT_OK;
}
int ManagedBuffer::readBytes(uint8_t *dst, int offset, int length, bool swapBytes) const
{
if (offset < 0 || length < 0 || offset + length > ptr->length)
return MICROBIT_INVALID_PARAMETER;
if (swapBytes) {
uint8_t *p = ptr->payload + offset + length;
for (int i = 0; i < length; ++i)
dst[i] = *--p;
} else {
memcpy(dst, ptr->payload + offset, length);
}
return MICROBIT_OK;
}

257
libs/core/ManagedBuffer.h Normal file
View File

@ -0,0 +1,257 @@
#ifndef MICROBIT_MANAGED_BUFFER_H
#define MICROBIT_MANAGED_BUFFER_H
#include "mbed.h"
#include "RefCounted.h"
struct BufferData : RefCounted
{
uint16_t length; // The length of the payload in bytes
uint8_t payload[0]; // ManagedBuffer data
};
/**
* Class definition for a ManagedBuffer.
* A ManagedBuffer holds a series of bytes, used with MicroBitRadio channels and in other places.
* n.b. This is a mutable, managed type.
*/
class ManagedBuffer
{
BufferData *ptr; // Pointer to payload data
public:
/**
* Default Constructor.
* Creates an empty ManagedBuffer. The 'ptr' field in all empty buffers is shared.
*
* Example:
* @code
* ManagedBuffer p();
* @endcode
*/
ManagedBuffer();
/**
* Constructor.
* Creates a new ManagedBuffer of the given size.
*
* @param length The length of the buffer to create.
*
* Example:
* @code
* ManagedBuffer p(16); // Creates a ManagedBuffer 16 bytes long.
* @endcode
*/
ManagedBuffer(int length);
/**
* Constructor.
* Creates an empty ManagedBuffer of the given size,
* and fills it with the data provided.
*
* @param data The data with which to fill the buffer.
* @param length The length of the buffer to create.
*
* Example:
* @code
* uint8_t buf[] = {13,5,2};
* ManagedBuffer p(buf, 3); // Creates a ManagedBuffer 3 bytes long.
* @endcode
*/
ManagedBuffer(uint8_t *data, int length);
/**
* Copy Constructor.
* Add ourselves as a reference to an existing ManagedBuffer.
*
* @param buffer The ManagedBuffer to reference.
*
* Example:
* @code
* ManagedBuffer p();
* ManagedBuffer p2(i); // Refers to the same buffer as p.
* @endcode
*/
ManagedBuffer(const ManagedBuffer &buffer);
/**
* Constructor.
* Create a buffer from a raw BufferData pointer. It will ptr->incr(). This is to be used by specialized runtimes.
*
* @param p The pointer to use.
*/
ManagedBuffer(BufferData *p);
/**
* Internal constructor helper.
* Configures this ManagedBuffer to refer to the static empty buffer.
*/
void initEmpty();
/**
* Internal constructor-initialiser.
*
* @param data The data with which to fill the buffer.
* @param length The length of the buffer to create.
*
*/
void init(uint8_t *data, int length);
/**
* Destructor.
* Removes buffer resources held by the instance.
*/
~ManagedBuffer();
/**
* Provide an array containing the buffer data.
* @return The contents of this buffer, as an array of bytes.
*/
uint8_t *getBytes()
{
return ptr->payload;
}
/**
* Get current ptr, do not decr() it, and set the current instance to an empty buffer.
* This is to be used by specialized runtimes which pass BufferData around.
*/
BufferData *leakData();
/**
* Copy assign operation.
*
* Called when one ManagedBuffer is assigned the value of another using the '=' operator.
* Decrements our reference count and free up the buffer as necessary.
* Then, update our buffer to refer to that of the supplied ManagedBuffer,
* and increase its reference count.
*
* @param p The ManagedBuffer to reference.
*
* Example:
* @code
* uint8_t buf = {13,5,2};
* ManagedBuffer p1(16);
* ManagedBuffer p2(buf, 3);
*
* p1 = p2;
* @endcode
*/
ManagedBuffer& operator = (const ManagedBuffer& p);
/**
* Array access operation (read).
*
* Called when a ManagedBuffer is dereferenced with a [] operation.
* Transparently map this through to the underlying payload for elegance of programming.
*
* Example:
* @code
* ManagedBuffer p1(16);
* uint8_t data = p1[0];
* @endcode
*/
uint8_t operator [] (int i) const
{
return ptr->payload[i];
}
/**
* Array access operation (modify).
*
* Called when a ManagedBuffer is dereferenced with a [] operation.
* Transparently map this through to the underlying payload for elegance of programming.
*
* Example:
* @code
* ManagedBuffer p1(16);
* p1[0] = 42;
* @endcode
*/
uint8_t& operator [] (int i)
{
return ptr->payload[i];
}
/**
* Equality operation.
*
* Called when one ManagedBuffer is tested to be equal to another using the '==' operator.
*
* @param p The ManagedBuffer to test ourselves against.
* @return true if this ManagedBuffer is identical to the one supplied, false otherwise.
*
* Example:
* @code
*
* uint8_t buf = {13,5,2};
* ManagedBuffer p1(16);
* ManagedBuffer p2(buf, 3);
*
* if(p1 == p2) // will be true
* uBit.display.scroll("same!");
* @endcode
*/
bool operator== (const ManagedBuffer& p);
/**
* Sets the byte at the given index to value provided.
* @param position The index of the byte to change.
* @param value The new value of the byte (0-255).
* @return MICROBIT_OK, or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
* ManagedBuffer p1(16);
* p1.setByte(0,255); // Sets the first byte in the buffer to the value 255.
* @endcode
*/
int setByte(int position, uint8_t value);
/**
* Determines the value of the given byte in the buffer.
*
* @param position The index of the byte to read.
* @return The value of the byte at the given position, or MICROBIT_INVALID_PARAMETER.
*
* Example:
* @code
* ManagedBuffer p1(16);
* p1.setByte(0,255); // Sets the first byte in the buffer to the value 255.
* p1.getByte(0); // Returns 255.
* @endcode
*/
int getByte(int position);
/**
* Gets number of bytes in this buffer
* @return The size of the buffer in bytes.
*
* Example:
* @code
* ManagedBuffer p1(16);
* p1.length(); // Returns 16.
* @endcode
*/
int length() const { return ptr->length; }
int fill(uint8_t value, int offset = 0, int length = -1);
ManagedBuffer slice(int offset = 0, int length = -1) const;
void shift(int offset, int start = 0, int length = -1);
void rotate(int offset, int start = 0, int length = -1);
int readBytes(uint8_t *dst, int offset, int length, bool swapBytes = false) const;
int writeBytes(int dstOffset, uint8_t *src, int length, bool swapBytes = false);
int writeBuffer(int dstOffset, const ManagedBuffer &src, int srcOffset = 0, int length = -1);
bool isReadOnly() const { return ptr->isReadOnly(); }
};
#endif

116
libs/core/dal.d.ts vendored
View File

@ -1,11 +1,11 @@
// Auto-generated. Do not edit. // Auto-generated. Do not edit.
declare const enum DAL { declare const enum DAL {
// built\yt\yotta_modules\microbit-dal\inc\bluetooth\ExternalEvents.h // built/yt/yotta_modules/microbit-dal/inc/bluetooth/ExternalEvents.h
MICROBIT_ID_BLE = 1000, MICROBIT_ID_BLE = 1000,
MICROBIT_ID_BLE_UART = 1200, MICROBIT_ID_BLE_UART = 1200,
MICROBIT_BLE_EVT_CONNECTED = 1, MICROBIT_BLE_EVT_CONNECTED = 1,
MICROBIT_BLE_EVT_DISCONNECTED = 2, MICROBIT_BLE_EVT_DISCONNECTED = 2,
// built\yt\yotta_modules\microbit-dal\inc\bluetooth\MESEvents.h // built/yt/yotta_modules/microbit-dal/inc/bluetooth/MESEvents.h
MES_REMOTE_CONTROL_ID = 1001, MES_REMOTE_CONTROL_ID = 1001,
MES_REMOTE_CONTROL_EVT_PLAY = 1, MES_REMOTE_CONTROL_EVT_PLAY = 1,
MES_REMOTE_CONTROL_EVT_PAUSE = 2, MES_REMOTE_CONTROL_EVT_PAUSE = 2,
@ -70,8 +70,8 @@ declare const enum DAL {
MES_DPAD_BUTTON_4_DOWN = 15, MES_DPAD_BUTTON_4_DOWN = 15,
MES_DPAD_BUTTON_4_UP = 16, MES_DPAD_BUTTON_4_UP = 16,
MES_BROADCAST_GENERAL_ID = 2000, MES_BROADCAST_GENERAL_ID = 2000,
// built\yt\yotta_modules\microbit-dal\inc\bluetooth\MicroBitAccelerometerService.h // built/yt/yotta_modules/microbit-dal/inc/bluetooth/MicroBitAccelerometerService.h
// built\yt\yotta_modules\microbit-dal\inc\bluetooth\MicroBitBLEManager.h // built/yt/yotta_modules/microbit-dal/inc/bluetooth/MicroBitBLEManager.h
MICROBIT_BLE_PAIR_REQUEST = 0x01, MICROBIT_BLE_PAIR_REQUEST = 0x01,
MICROBIT_BLE_PAIR_COMPLETE = 0x02, MICROBIT_BLE_PAIR_COMPLETE = 0x02,
MICROBIT_BLE_PAIR_PASSCODE = 0x04, MICROBIT_BLE_PAIR_PASSCODE = 0x04,
@ -79,27 +79,29 @@ declare const enum DAL {
MICROBIT_BLE_PAIRING_TIMEOUT = 90, MICROBIT_BLE_PAIRING_TIMEOUT = 90,
MICROBIT_BLE_POWER_LEVELS = 8, MICROBIT_BLE_POWER_LEVELS = 8,
MICROBIT_BLE_MAXIMUM_BONDS = 4, MICROBIT_BLE_MAXIMUM_BONDS = 4,
MICROBIT_BLE_EDDYSTONE_URL_ADV_INTERVAL = 400, MICROBIT_BLE_EDDYSTONE_ADV_INTERVAL = 400,
// built\yt\yotta_modules\microbit-dal\inc\bluetooth\MicroBitButtonService.h // built/yt/yotta_modules/microbit-dal/inc/bluetooth/MicroBitButtonService.h
// built\yt\yotta_modules\microbit-dal\inc\bluetooth\MicroBitDFUService.h // built/yt/yotta_modules/microbit-dal/inc/bluetooth/MicroBitDFUService.h
MICROBIT_DFU_OPCODE_START_DFU = 1, MICROBIT_DFU_OPCODE_START_DFU = 1,
MICROBIT_DFU_HISTOGRAM_WIDTH = 5, MICROBIT_DFU_HISTOGRAM_WIDTH = 5,
MICROBIT_DFU_HISTOGRAM_HEIGHT = 5, MICROBIT_DFU_HISTOGRAM_HEIGHT = 5,
// built\yt\yotta_modules\microbit-dal\inc\bluetooth\MicroBitEventService.h // built/yt/yotta_modules/microbit-dal/inc/bluetooth/MicroBitEddystone.h
// built\yt\yotta_modules\microbit-dal\inc\bluetooth\MicroBitIOPinService.h MICROBIT_BLE_EDDYSTONE_URL_ADV_INTERVAL = 400,
// built/yt/yotta_modules/microbit-dal/inc/bluetooth/MicroBitEventService.h
// built/yt/yotta_modules/microbit-dal/inc/bluetooth/MicroBitIOPinService.h
MICROBIT_IO_PIN_SERVICE_PINCOUNT = 19, MICROBIT_IO_PIN_SERVICE_PINCOUNT = 19,
MICROBIT_IO_PIN_SERVICE_DATA_SIZE = 10, MICROBIT_IO_PIN_SERVICE_DATA_SIZE = 10,
MICROBIT_PWM_PIN_SERVICE_DATA_SIZE = 2, MICROBIT_PWM_PIN_SERVICE_DATA_SIZE = 2,
// built\yt\yotta_modules\microbit-dal\inc\bluetooth\MicroBitLEDService.h // built/yt/yotta_modules/microbit-dal/inc/bluetooth/MicroBitLEDService.h
MICROBIT_BLE_MAXIMUM_SCROLLTEXT = 20, MICROBIT_BLE_MAXIMUM_SCROLLTEXT = 20,
// built\yt\yotta_modules\microbit-dal\inc\bluetooth\MicroBitMagnetometerService.h // built/yt/yotta_modules/microbit-dal/inc/bluetooth/MicroBitMagnetometerService.h
// built\yt\yotta_modules\microbit-dal\inc\bluetooth\MicroBitTemperatureService.h // built/yt/yotta_modules/microbit-dal/inc/bluetooth/MicroBitTemperatureService.h
// built\yt\yotta_modules\microbit-dal\inc\bluetooth\MicroBitUARTService.h // built/yt/yotta_modules/microbit-dal/inc/bluetooth/MicroBitUARTService.h
MICROBIT_UART_S_DEFAULT_BUF_SIZE = 20, MICROBIT_UART_S_DEFAULT_BUF_SIZE = 20,
MICROBIT_UART_S_EVT_DELIM_MATCH = 1, MICROBIT_UART_S_EVT_DELIM_MATCH = 1,
MICROBIT_UART_S_EVT_HEAD_MATCH = 2, MICROBIT_UART_S_EVT_HEAD_MATCH = 2,
MICROBIT_UART_S_EVT_RX_FULL = 3, MICROBIT_UART_S_EVT_RX_FULL = 3,
// built\yt\yotta_modules\microbit-dal\inc\core\ErrorNo.h // built/yt/yotta_modules/microbit-dal/inc/core/ErrorNo.h
MICROBIT_OK = 0, MICROBIT_OK = 0,
MICROBIT_INVALID_PARAMETER = -1001, MICROBIT_INVALID_PARAMETER = -1001,
MICROBIT_NOT_SUPPORTED = -1002, MICROBIT_NOT_SUPPORTED = -1002,
@ -114,10 +116,10 @@ declare const enum DAL {
MICROBIT_OOM = 20, MICROBIT_OOM = 20,
MICROBIT_HEAP_ERROR = 30, MICROBIT_HEAP_ERROR = 30,
MICROBIT_NULL_DEREFERENCE = 40, MICROBIT_NULL_DEREFERENCE = 40,
// built\yt\yotta_modules\microbit-dal\inc\core\EventModel.h // built/yt/yotta_modules/microbit-dal/inc/core/EventModel.h
// built\yt\yotta_modules\microbit-dal\inc\core\MemberFunctionCallback.h // built/yt/yotta_modules/microbit-dal/inc/core/MemberFunctionCallback.h
// built\yt\yotta_modules\microbit-dal\inc\core\MicroBitCompat.h // built/yt/yotta_modules/microbit-dal/inc/core/MicroBitCompat.h
// built\yt\yotta_modules\microbit-dal\inc\core\MicroBitComponent.h // built/yt/yotta_modules/microbit-dal/inc/core/MicroBitComponent.h
MICROBIT_ID_BUTTON_A = 1, MICROBIT_ID_BUTTON_A = 1,
MICROBIT_ID_BUTTON_B = 2, MICROBIT_ID_BUTTON_B = 2,
MICROBIT_ID_BUTTON_RESET = 3, MICROBIT_ID_BUTTON_RESET = 3,
@ -155,25 +157,25 @@ declare const enum DAL {
MICROBIT_ID_NOTIFY_ONE = 1022, MICROBIT_ID_NOTIFY_ONE = 1022,
MICROBIT_ID_NOTIFY = 1023, MICROBIT_ID_NOTIFY = 1023,
MICROBIT_COMPONENT_RUNNING = 0x01, MICROBIT_COMPONENT_RUNNING = 0x01,
// built\yt\yotta_modules\microbit-dal\inc\core\MicroBitDevice.h // built/yt/yotta_modules/microbit-dal/inc/core/MicroBitDevice.h
MICROBIT_NAME_LENGTH = 5, MICROBIT_NAME_LENGTH = 5,
MICROBIT_NAME_CODE_LETTERS = 5, MICROBIT_NAME_CODE_LETTERS = 5,
MICROBIT_PANIC_ERROR_CHARS = 4, MICROBIT_PANIC_ERROR_CHARS = 4,
// built\yt\yotta_modules\microbit-dal\inc\core\MicroBitFiber.h // built/yt/yotta_modules/microbit-dal/inc/core/MicroBitFiber.h
MICROBIT_SCHEDULER_RUNNING = 0x01, MICROBIT_SCHEDULER_RUNNING = 0x01,
MICROBIT_FIBER_FLAG_FOB = 0x01, MICROBIT_FIBER_FLAG_FOB = 0x01,
MICROBIT_FIBER_FLAG_PARENT = 0x02, MICROBIT_FIBER_FLAG_PARENT = 0x02,
MICROBIT_FIBER_FLAG_CHILD = 0x04, MICROBIT_FIBER_FLAG_CHILD = 0x04,
MICROBIT_FIBER_FLAG_DO_NOT_PAGE = 0x08, MICROBIT_FIBER_FLAG_DO_NOT_PAGE = 0x08,
// built\yt\yotta_modules\microbit-dal\inc\core\MicroBitFont.h // built/yt/yotta_modules/microbit-dal/inc/core/MicroBitFont.h
MICROBIT_FONT_WIDTH = 5, MICROBIT_FONT_WIDTH = 5,
MICROBIT_FONT_HEIGHT = 5, MICROBIT_FONT_HEIGHT = 5,
MICROBIT_FONT_ASCII_START = 32, MICROBIT_FONT_ASCII_START = 32,
MICROBIT_FONT_ASCII_END = 126, MICROBIT_FONT_ASCII_END = 126,
// built\yt\yotta_modules\microbit-dal\inc\core\MicroBitHeapAllocator.h // built/yt/yotta_modules/microbit-dal/inc/core/MicroBitHeapAllocator.h
MICROBIT_MAXIMUM_HEAPS = 2, MICROBIT_MAXIMUM_HEAPS = 2,
MICROBIT_HEAP_BLOCK_FREE = 0x80000000, MICROBIT_HEAP_BLOCK_FREE = 0x80000000,
// built\yt\yotta_modules\microbit-dal\inc\core\MicroBitListener.h // built/yt/yotta_modules/microbit-dal/inc/core/MicroBitListener.h
MESSAGE_BUS_LISTENER_PARAMETERISED = 0x0001, MESSAGE_BUS_LISTENER_PARAMETERISED = 0x0001,
MESSAGE_BUS_LISTENER_METHOD = 0x0002, MESSAGE_BUS_LISTENER_METHOD = 0x0002,
MESSAGE_BUS_LISTENER_BUSY = 0x0004, MESSAGE_BUS_LISTENER_BUSY = 0x0004,
@ -183,17 +185,17 @@ declare const enum DAL {
MESSAGE_BUS_LISTENER_NONBLOCKING = 0x0040, MESSAGE_BUS_LISTENER_NONBLOCKING = 0x0040,
MESSAGE_BUS_LISTENER_URGENT = 0x0080, MESSAGE_BUS_LISTENER_URGENT = 0x0080,
MESSAGE_BUS_LISTENER_DELETING = 0x8000, MESSAGE_BUS_LISTENER_DELETING = 0x8000,
// built\yt\yotta_modules\microbit-dal\inc\core\MicroBitSystemTimer.h // built/yt/yotta_modules/microbit-dal/inc/core/MicroBitSystemTimer.h
// built\yt\yotta_modules\microbit-dal\inc\core\NotifyEvents.h // built/yt/yotta_modules/microbit-dal/inc/core/NotifyEvents.h
MICROBIT_DISPLAY_EVT_FREE = 1, MICROBIT_DISPLAY_EVT_FREE = 1,
MICROBIT_SERIAL_EVT_TX_EMPTY = 2, MICROBIT_SERIAL_EVT_TX_EMPTY = 2,
MICROBIT_UART_S_EVT_TX_EMPTY = 3, MICROBIT_UART_S_EVT_TX_EMPTY = 3,
// built\yt\yotta_modules\microbit-dal\inc\drivers\DynamicPwm.h // built/yt/yotta_modules/microbit-dal/inc/drivers/DynamicPwm.h
NO_PWMS = 3, NO_PWMS = 3,
MICROBIT_DEFAULT_PWM_PERIOD = 20000, MICROBIT_DEFAULT_PWM_PERIOD = 20000,
PWM_PERSISTENCE_TRANSIENT = 1, PWM_PERSISTENCE_TRANSIENT = 1,
PWM_PERSISTENCE_PERSISTENT = 2, PWM_PERSISTENCE_PERSISTENT = 2,
// built\yt\yotta_modules\microbit-dal\inc\drivers\MicroBitAccelerometer.h // built/yt/yotta_modules/microbit-dal/inc/drivers/MicroBitAccelerometer.h
MICROBIT_ACCEL_PITCH_ROLL_VALID = 0x02, MICROBIT_ACCEL_PITCH_ROLL_VALID = 0x02,
MICROBIT_ACCEL_ADDED_TO_IDLE = 0x04, MICROBIT_ACCEL_ADDED_TO_IDLE = 0x04,
MMA8653_DEFAULT_ADDR = 0x3A, MMA8653_DEFAULT_ADDR = 0x3A,
@ -233,7 +235,7 @@ declare const enum DAL {
MICROBIT_ACCELEROMETER_SHAKE_DAMPING = 10, MICROBIT_ACCELEROMETER_SHAKE_DAMPING = 10,
MICROBIT_ACCELEROMETER_SHAKE_RTX = 30, MICROBIT_ACCELEROMETER_SHAKE_RTX = 30,
MICROBIT_ACCELEROMETER_SHAKE_COUNT_THRESHOLD = 4, MICROBIT_ACCELEROMETER_SHAKE_COUNT_THRESHOLD = 4,
// built\yt\yotta_modules\microbit-dal\inc\drivers\MicroBitButton.h // built/yt/yotta_modules/microbit-dal/inc/drivers/MicroBitButton.h
MICROBIT_BUTTON_EVT_DOWN = 1, MICROBIT_BUTTON_EVT_DOWN = 1,
MICROBIT_BUTTON_EVT_UP = 2, MICROBIT_BUTTON_EVT_UP = 2,
MICROBIT_BUTTON_EVT_CLICK = 3, MICROBIT_BUTTON_EVT_CLICK = 3,
@ -253,7 +255,7 @@ declare const enum DAL {
MICROBIT_BUTTON_DOUBLE_CLICK_THRESH = 50, MICROBIT_BUTTON_DOUBLE_CLICK_THRESH = 50,
MICROBIT_BUTTON_SIMPLE_EVENTS = 0, MICROBIT_BUTTON_SIMPLE_EVENTS = 0,
MICROBIT_BUTTON_ALL_EVENTS = 1, MICROBIT_BUTTON_ALL_EVENTS = 1,
// built\yt\yotta_modules\microbit-dal\inc\drivers\MicroBitCompass.h // built/yt/yotta_modules/microbit-dal/inc/drivers/MicroBitCompass.h
MAG3110_DEFAULT_ADDR = 0x1D, MAG3110_DEFAULT_ADDR = 0x1D,
MAG_DR_STATUS = 0x00, MAG_DR_STATUS = 0x00,
MAG_OUT_X_MSB = 0x01, MAG_OUT_X_MSB = 0x01,
@ -284,8 +286,8 @@ declare const enum DAL {
MICROBIT_COMPASS_STATUS_CALIBRATING = 4, MICROBIT_COMPASS_STATUS_CALIBRATING = 4,
MICROBIT_COMPASS_STATUS_ADDED_TO_IDLE = 8, MICROBIT_COMPASS_STATUS_ADDED_TO_IDLE = 8,
MAG3110_WHOAMI_VAL = 0xC4, MAG3110_WHOAMI_VAL = 0xC4,
// built\yt\yotta_modules\microbit-dal\inc\drivers\MicroBitCompassCalibrator.h // built/yt/yotta_modules/microbit-dal/inc/drivers/MicroBitCompassCalibrator.h
// built\yt\yotta_modules\microbit-dal\inc\drivers\MicroBitDisplay.h // built/yt/yotta_modules/microbit-dal/inc/drivers/MicroBitDisplay.h
MICROBIT_DISPLAY_EVT_ANIMATION_COMPLETE = 1, MICROBIT_DISPLAY_EVT_ANIMATION_COMPLETE = 1,
MICROBIT_DISPLAY_EVT_LIGHT_SENSE = 2, MICROBIT_DISPLAY_EVT_LIGHT_SENSE = 2,
MICROBIT_DISPLAY_DEFAULT_AUTOCLEAR = 1, MICROBIT_DISPLAY_DEFAULT_AUTOCLEAR = 1,
@ -307,8 +309,8 @@ declare const enum DAL {
MICROBIT_DISPLAY_ROTATION_90 = 1, MICROBIT_DISPLAY_ROTATION_90 = 1,
MICROBIT_DISPLAY_ROTATION_180 = 2, MICROBIT_DISPLAY_ROTATION_180 = 2,
MICROBIT_DISPLAY_ROTATION_270 = 3, MICROBIT_DISPLAY_ROTATION_270 = 3,
// built\yt\yotta_modules\microbit-dal\inc\drivers\MicroBitFile.h // built/yt/yotta_modules/microbit-dal/inc/drivers/MicroBitFile.h
// built\yt\yotta_modules\microbit-dal\inc\drivers\MicroBitFileSystem.h // built/yt/yotta_modules/microbit-dal/inc/drivers/MicroBitFileSystem.h
MBFS_FILENAME_LENGTH = 16, MBFS_FILENAME_LENGTH = 16,
MB_READ = 0x01, MB_READ = 0x01,
MB_WRITE = 0x02, MB_WRITE = 0x02,
@ -329,23 +331,23 @@ declare const enum DAL {
MBFS_BLOCK_TYPE_FILE = 1, MBFS_BLOCK_TYPE_FILE = 1,
MBFS_BLOCK_TYPE_DIRECTORY = 2, MBFS_BLOCK_TYPE_DIRECTORY = 2,
MBFS_BLOCK_TYPE_FILETABLE = 3, MBFS_BLOCK_TYPE_FILETABLE = 3,
// built\yt\yotta_modules\microbit-dal\inc\drivers\MicroBitFlash.h // built/yt/yotta_modules/microbit-dal/inc/drivers/MicroBitFlash.h
PAGE_SIZE = 1024, PAGE_SIZE = 1024,
// built\yt\yotta_modules\microbit-dal\inc\drivers\MicroBitI2C.h // built/yt/yotta_modules/microbit-dal/inc/drivers/MicroBitI2C.h
MICROBIT_I2C_MAX_RETRIES = 9, MICROBIT_I2C_MAX_RETRIES = 9,
// built\yt\yotta_modules\microbit-dal\inc\drivers\MicroBitIO.h // built/yt/yotta_modules/microbit-dal/inc/drivers/MicroBitIO.h
// built\yt\yotta_modules\microbit-dal\inc\drivers\MicroBitLightSensor.h // built/yt/yotta_modules/microbit-dal/inc/drivers/MicroBitLightSensor.h
MICROBIT_LIGHT_SENSOR_CHAN_NUM = 3, MICROBIT_LIGHT_SENSOR_CHAN_NUM = 3,
MICROBIT_LIGHT_SENSOR_AN_SET_TIME = 4000, MICROBIT_LIGHT_SENSOR_AN_SET_TIME = 4000,
MICROBIT_LIGHT_SENSOR_TICK_PERIOD = 5, MICROBIT_LIGHT_SENSOR_TICK_PERIOD = 5,
MICROBIT_LIGHT_SENSOR_MAX_VALUE = 338, MICROBIT_LIGHT_SENSOR_MAX_VALUE = 338,
MICROBIT_LIGHT_SENSOR_MIN_VALUE = 75, MICROBIT_LIGHT_SENSOR_MIN_VALUE = 75,
// built\yt\yotta_modules\microbit-dal\inc\drivers\MicroBitMatrixMaps.h // built/yt/yotta_modules/microbit-dal/inc/drivers/MicroBitMatrixMaps.h
NO_CONN = 0, NO_CONN = 0,
MICROBIT_DISPLAY_WIDTH = 5, MICROBIT_DISPLAY_WIDTH = 5,
MICROBIT_DISPLAY_HEIGHT = 5, MICROBIT_DISPLAY_HEIGHT = 5,
// built\yt\yotta_modules\microbit-dal\inc\drivers\MicroBitMessageBus.h // built/yt/yotta_modules/microbit-dal/inc/drivers/MicroBitMessageBus.h
// built\yt\yotta_modules\microbit-dal\inc\drivers\MicroBitMultiButton.h // built/yt/yotta_modules/microbit-dal/inc/drivers/MicroBitMultiButton.h
MICROBIT_MULTI_BUTTON_STATE_1 = 0x01, MICROBIT_MULTI_BUTTON_STATE_1 = 0x01,
MICROBIT_MULTI_BUTTON_STATE_2 = 0x02, MICROBIT_MULTI_BUTTON_STATE_2 = 0x02,
MICROBIT_MULTI_BUTTON_HOLD_TRIGGERED_1 = 0x04, MICROBIT_MULTI_BUTTON_HOLD_TRIGGERED_1 = 0x04,
@ -353,7 +355,7 @@ declare const enum DAL {
MICROBIT_MULTI_BUTTON_SUPRESSED_1 = 0X10, MICROBIT_MULTI_BUTTON_SUPRESSED_1 = 0X10,
MICROBIT_MULTI_BUTTON_SUPRESSED_2 = 0x20, MICROBIT_MULTI_BUTTON_SUPRESSED_2 = 0x20,
MICROBIT_MULTI_BUTTON_ATTACHED = 0x40, MICROBIT_MULTI_BUTTON_ATTACHED = 0x40,
// built\yt\yotta_modules\microbit-dal\inc\drivers\MicroBitPin.h // built/yt/yotta_modules/microbit-dal/inc/drivers/MicroBitPin.h
IO_STATUS_DIGITAL_IN = 0x01, IO_STATUS_DIGITAL_IN = 0x01,
IO_STATUS_DIGITAL_OUT = 0x02, IO_STATUS_DIGITAL_OUT = 0x02,
IO_STATUS_ANALOG_IN = 0x04, IO_STATUS_ANALOG_IN = 0x04,
@ -375,7 +377,7 @@ declare const enum DAL {
MICROBIT_PIN_EVT_PULSE_LO = 5, MICROBIT_PIN_EVT_PULSE_LO = 5,
PIN_CAPABILITY_DIGITAL = 0x01, PIN_CAPABILITY_DIGITAL = 0x01,
PIN_CAPABILITY_ANALOG = 0x02, PIN_CAPABILITY_ANALOG = 0x02,
// built\yt\yotta_modules\microbit-dal\inc\drivers\MicroBitRadio.h // built/yt/yotta_modules/microbit-dal/inc/drivers/MicroBitRadio.h
MICROBIT_RADIO_STATUS_INITIALISED = 0x0001, MICROBIT_RADIO_STATUS_INITIALISED = 0x0001,
MICROBIT_RADIO_BASE_ADDRESS = 0x75626974, MICROBIT_RADIO_BASE_ADDRESS = 0x75626974,
MICROBIT_RADIO_DEFAULT_GROUP = 0, MICROBIT_RADIO_DEFAULT_GROUP = 0,
@ -387,9 +389,9 @@ declare const enum DAL {
MICROBIT_RADIO_PROTOCOL_DATAGRAM = 1, MICROBIT_RADIO_PROTOCOL_DATAGRAM = 1,
MICROBIT_RADIO_PROTOCOL_EVENTBUS = 2, MICROBIT_RADIO_PROTOCOL_EVENTBUS = 2,
MICROBIT_RADIO_EVT_DATAGRAM = 1, MICROBIT_RADIO_EVT_DATAGRAM = 1,
// built\yt\yotta_modules\microbit-dal\inc\drivers\MicroBitRadioDatagram.h // built/yt/yotta_modules/microbit-dal/inc/drivers/MicroBitRadioDatagram.h
// built\yt\yotta_modules\microbit-dal\inc\drivers\MicroBitRadioEvent.h // built/yt/yotta_modules/microbit-dal/inc/drivers/MicroBitRadioEvent.h
// built\yt\yotta_modules\microbit-dal\inc\drivers\MicroBitSerial.h // built/yt/yotta_modules/microbit-dal/inc/drivers/MicroBitSerial.h
MICROBIT_SERIAL_DEFAULT_BAUD_RATE = 115200, MICROBIT_SERIAL_DEFAULT_BAUD_RATE = 115200,
MICROBIT_SERIAL_DEFAULT_BUFFER_SIZE = 20, MICROBIT_SERIAL_DEFAULT_BUFFER_SIZE = 20,
MICROBIT_SERIAL_EVT_DELIM_MATCH = 1, MICROBIT_SERIAL_EVT_DELIM_MATCH = 1,
@ -402,31 +404,31 @@ declare const enum DAL {
ASYNC = 0, ASYNC = 0,
SYNC_SPINWAIT = 1, SYNC_SPINWAIT = 1,
SYNC_SLEEP = 2, SYNC_SLEEP = 2,
// built\yt\yotta_modules\microbit-dal\inc\drivers\MicroBitStorage.h // built/yt/yotta_modules/microbit-dal/inc/drivers/MicroBitStorage.h
MICROBIT_STORAGE_MAGIC = 0xCAFE, MICROBIT_STORAGE_MAGIC = 0xCAFE,
MICROBIT_STORAGE_BLOCK_SIZE = 48, MICROBIT_STORAGE_BLOCK_SIZE = 48,
MICROBIT_STORAGE_KEY_SIZE = 16, MICROBIT_STORAGE_KEY_SIZE = 16,
MICROBIT_STORAGE_STORE_PAGE_OFFSET = 17, MICROBIT_STORAGE_STORE_PAGE_OFFSET = 17,
MICROBIT_STORAGE_SCRATCH_PAGE_OFFSET = 19, MICROBIT_STORAGE_SCRATCH_PAGE_OFFSET = 19,
// built\yt\yotta_modules\microbit-dal\inc\drivers\MicroBitThermometer.h // built/yt/yotta_modules/microbit-dal/inc/drivers/MicroBitThermometer.h
MICROBIT_THERMOMETER_PERIOD = 1000, MICROBIT_THERMOMETER_PERIOD = 1000,
MICROBIT_THERMOMETER_EVT_UPDATE = 1, MICROBIT_THERMOMETER_EVT_UPDATE = 1,
MICROBIT_THERMOMETER_ADDED_TO_IDLE = 2, MICROBIT_THERMOMETER_ADDED_TO_IDLE = 2,
// built\yt\yotta_modules\microbit-dal\inc\drivers\TimedInterruptIn.h // built/yt/yotta_modules/microbit-dal/inc/drivers/TimedInterruptIn.h
// built\yt\yotta_modules\microbit-dal\inc\platform\yotta_cfg_mappings.h // built/yt/yotta_modules/microbit-dal/inc/platform/yotta_cfg_mappings.h
// built\yt\yotta_modules\microbit-dal\inc\types\ManagedString.h // built/yt/yotta_modules/microbit-dal/inc/types/ManagedString.h
// built\yt\yotta_modules\microbit-dal\inc\types\ManagedType.h // built/yt/yotta_modules/microbit-dal/inc/types/ManagedType.h
// built\yt\yotta_modules\microbit-dal\inc\types\Matrix4.h // built/yt/yotta_modules/microbit-dal/inc/types/Matrix4.h
// built\yt\yotta_modules\microbit-dal\inc\types\MicroBitCoordinateSystem.h // built/yt/yotta_modules/microbit-dal/inc/types/MicroBitCoordinateSystem.h
RAW = 0, RAW = 0,
SIMPLE_CARTESIAN = 1, SIMPLE_CARTESIAN = 1,
NORTH_EAST_DOWN = 2, NORTH_EAST_DOWN = 2,
// built\yt\yotta_modules\microbit-dal\inc\types\MicroBitEvent.h // built/yt/yotta_modules/microbit-dal/inc/types/MicroBitEvent.h
MICROBIT_ID_ANY = 0, MICROBIT_ID_ANY = 0,
MICROBIT_EVT_ANY = 0, MICROBIT_EVT_ANY = 0,
CREATE_ONLY = 0, CREATE_ONLY = 0,
CREATE_AND_FIRE = 1, CREATE_AND_FIRE = 1,
// built\yt\yotta_modules\microbit-dal\inc\types\MicroBitImage.h // built/yt/yotta_modules/microbit-dal/inc/types/MicroBitImage.h
// built\yt\yotta_modules\microbit-dal\inc\types\PacketBuffer.h // built/yt/yotta_modules/microbit-dal/inc/types/PacketBuffer.h
// built\yt\yotta_modules\microbit-dal\inc\types\RefCounted.h // built/yt/yotta_modules/microbit-dal/inc/types/RefCounted.h
} }

472
libs/core/pxt.cpp Normal file
View File

@ -0,0 +1,472 @@
#include "pxt.h"
#include <map>
MicroBit uBit;
namespace pxt {
int incr(uint32_t e)
{
if (e) {
if (hasVTable(e))
((RefObject*)e)->ref();
else
((RefCounted*)e)->incr();
}
return e;
}
void decr(uint32_t e)
{
if (e) {
if (hasVTable(e))
((RefObject*)e)->unref();
else
((RefCounted*)e)->decr();
}
}
Action mkAction(int reflen, int totallen, int startptr)
{
check(0 <= reflen && reflen <= totallen, ERR_SIZE, 1);
check(reflen <= totallen && totallen <= 255, ERR_SIZE, 2);
check(bytecode[startptr] == 0xffff, ERR_INVALID_BINARY_HEADER, 3);
check(bytecode[startptr + 1] == 0, ERR_INVALID_BINARY_HEADER, 4);
uint32_t tmp = (uint32_t)&bytecode[startptr];
if (totallen == 0) {
return tmp; // no closure needed
}
void *ptr = ::operator new(sizeof(RefAction) + totallen * sizeof(uint32_t));
RefAction *r = new (ptr) RefAction();
r->len = totallen;
r->reflen = reflen;
r->func = (ActionCB)((tmp + 4) | 1);
memset(r->fields, 0, r->len * sizeof(uint32_t));
return (Action)r;
}
uint32_t runAction3(Action a, int arg0, int arg1, int arg2)
{
if (hasVTable(a))
return ((RefAction*)a)->runCore(arg0, arg1, arg2);
else {
check(*(uint16_t*)a == 0xffff, ERR_INVALID_BINARY_HEADER, 4);
return ((ActionCB)((a + 4) | 1))(NULL, arg0, arg1, arg2);
}
}
uint32_t runAction2(Action a, int arg0, int arg1)
{
return runAction3(a, arg0, arg1, 0);
}
uint32_t runAction1(Action a, int arg0)
{
return runAction3(a, arg0, 0, 0);
}
uint32_t runAction0(Action a)
{
return runAction3(a, 0, 0, 0);
}
RefRecord* mkClassInstance(int vtableOffset)
{
VTable *vtable = (VTable*)&bytecode[vtableOffset];
intcheck(vtable->methods[0] == &RefRecord_destroy, ERR_SIZE, 3);
intcheck(vtable->methods[1] == &RefRecord_print, ERR_SIZE, 4);
void *ptr = ::operator new(vtable->numbytes);
RefRecord *r = new (ptr) RefRecord(PXT_VTABLE_TO_INT(vtable));
memset(r->fields, 0, vtable->numbytes - sizeof(RefRecord));
return r;
}
uint32_t RefRecord::ld(int idx)
{
//intcheck((reflen == 255 ? 0 : reflen) <= idx && idx < len, ERR_OUT_OF_BOUNDS, 1);
return fields[idx];
}
uint32_t RefRecord::ldref(int idx)
{
//printf("LD %p len=%d reflen=%d idx=%d\n", this, len, reflen, idx);
//intcheck(0 <= idx && idx < reflen, ERR_OUT_OF_BOUNDS, 2);
uint32_t tmp = fields[idx];
incr(tmp);
return tmp;
}
void RefRecord::st(int idx, uint32_t v)
{
//intcheck((reflen == 255 ? 0 : reflen) <= idx && idx < len, ERR_OUT_OF_BOUNDS, 3);
fields[idx] = v;
}
void RefRecord::stref(int idx, uint32_t v)
{
//printf("ST %p len=%d reflen=%d idx=%d\n", this, len, reflen, idx);
//intcheck(0 <= idx && idx < reflen, ERR_OUT_OF_BOUNDS, 4);
decr(fields[idx]);
fields[idx] = v;
}
void RefObject::destroy() {
((RefObjectMethod)getVTable()->methods[0])(this);
delete this;
}
void RefObject::print() {
((RefObjectMethod)getVTable()->methods[1])(this);
}
void RefRecord_destroy(RefRecord *r) {
auto tbl = r->getVTable();
uint8_t *refmask = (uint8_t*)&tbl->methods[tbl->userdata & 0xff];
int len = (tbl->numbytes >> 2) - 1;
for (int i = 0; i < len; ++i) {
if (refmask[i]) decr(r->fields[i]);
r->fields[i] = 0;
}
}
void RefRecord_print(RefRecord *r)
{
printf("RefRecord %p r=%d size=%d bytes\n", r, r->refcnt, r->getVTable()->numbytes);
}
void RefCollection::push(uint32_t x) {
if (isRef()) incr(x);
data.push_back(x);
}
uint32_t RefCollection::getAt(int x) {
if (in_range(x)) {
uint32_t tmp = data.at(x);
if (isRef()) incr(tmp);
return tmp;
}
else {
error(ERR_OUT_OF_BOUNDS);
return 0;
}
}
void RefCollection::removeAt(int x) {
if (!in_range(x))
return;
if (isRef()) decr(data.at(x));
data.erase(data.begin()+x);
}
void RefCollection::setAt(int x, uint32_t y) {
if (!in_range(x))
return;
if (isRef()) {
decr(data.at(x));
incr(y);
}
data.at(x) = y;
}
int RefCollection::indexOf(uint32_t x, int start) {
if (!in_range(start))
return -1;
if (isString()) {
StringData *xx = (StringData*)x;
for (uint32_t i = start; i < data.size(); ++i) {
StringData *ee = (StringData*)data.at(i);
if (xx->len == ee->len && memcmp(xx->data, ee->data, xx->len) == 0)
return (int)i;
}
} else {
for (uint32_t i = start; i < data.size(); ++i)
if (data.at(i) == x)
return (int)i;
}
return -1;
}
int RefCollection::removeElement(uint32_t x) {
int idx = indexOf(x, 0);
if (idx >= 0) {
removeAt(idx);
return 1;
}
return 0;
}
namespace Coll0 {
PXT_VTABLE_BEGIN(RefCollection, 0, 0)
PXT_VTABLE_END
}
namespace Coll1 {
PXT_VTABLE_BEGIN(RefCollection, 1, 0)
PXT_VTABLE_END
}
namespace Coll3 {
PXT_VTABLE_BEGIN(RefCollection, 3, 0)
PXT_VTABLE_END
}
RefCollection::RefCollection(uint16_t flags) : RefObject(0) {
switch (flags) {
case 0:
vtable = PXT_VTABLE_TO_INT(&Coll0::RefCollection_vtable);
break;
case 1:
vtable = PXT_VTABLE_TO_INT(&Coll1::RefCollection_vtable);
break;
case 3:
vtable = PXT_VTABLE_TO_INT(&Coll3::RefCollection_vtable);
break;
default:
error(ERR_SIZE);
break;
}
}
void RefCollection::destroy()
{
if (this->isRef())
for (uint32_t i = 0; i < this->data.size(); ++i) {
decr(this->data[i]);
this->data[i] = 0;
}
this->data.resize(0);
}
void RefCollection::print()
{
printf("RefCollection %p r=%d flags=%d size=%d [%p, ...]\n", this, refcnt, getFlags(), data.size(), data.size() > 0 ? data[0] : 0);
}
PXT_VTABLE_CTOR(RefAction) {}
// fields[] contain captured locals
void RefAction::destroy()
{
for (int i = 0; i < this->reflen; ++i) {
decr(fields[i]);
fields[i] = 0;
}
}
void RefAction::print()
{
printf("RefAction %p r=%d pc=0x%lx size=%d (%d refs)\n", this, refcnt, (const uint8_t*)func - (const uint8_t*)bytecode, len, reflen);
}
void RefLocal::print()
{
printf("RefLocal %p r=%d v=%d\n", this, refcnt, v);
}
void RefLocal::destroy()
{
}
PXT_VTABLE_CTOR(RefLocal) {
v = 0;
}
PXT_VTABLE_CTOR(RefRefLocal) {
v = 0;
}
void RefRefLocal::print()
{
printf("RefRefLocal %p r=%d v=%p\n", this, refcnt, (void*)v);
}
void RefRefLocal::destroy()
{
decr(v);
}
PXT_VTABLE_BEGIN(RefMap, 0, RefMapMarker)
PXT_VTABLE_END
RefMap::RefMap() : PXT_VTABLE_INIT(RefMap) {}
void RefMap::destroy() {
for (unsigned i = 0; i < data.size(); ++i) {
if (data[i].key & 1) {
decr(data[i].val);
}
data[i].val = 0;
}
data.resize(0);
}
int RefMap::findIdx(uint32_t key) {
for (unsigned i = 0; i < data.size(); ++i) {
if (data[i].key >> 1 == key)
return i;
}
return -1;
}
void RefMap::print()
{
printf("RefMap %p r=%d size=%d\n", this, refcnt, data.size());
}
#ifdef DEBUG_MEMLEAKS
std::set<RefObject*> allptrs;
void debugMemLeaks()
{
printf("LIVE POINTERS:\n");
for(std::set<RefObject*>::iterator itr = allptrs.begin();itr!=allptrs.end();itr++)
{
(*itr)->print();
}
printf("\n");
}
#else
void debugMemLeaks() {}
#endif
// ---------------------------------------------------------------------------
// An adapter for the API expected by the run-time.
// ---------------------------------------------------------------------------
map<pair<int, int>, Action> handlersMap;
MicroBitEvent lastEvent;
// We have the invariant that if [dispatchEvent] is registered against the DAL
// for a given event, then [handlersMap] contains a valid entry for that
// event.
void dispatchEvent(MicroBitEvent e) {
lastEvent = e;
Action curr = handlersMap[{ e.source, e.value }];
if (curr)
runAction1(curr, e.value);
curr = handlersMap[{ e.source, MICROBIT_EVT_ANY }];
if (curr)
runAction1(curr, e.value);
}
void registerWithDal(int id, int event, Action a) {
Action prev = handlersMap[{ id, event }];
if (prev)
decr(prev);
else
uBit.messageBus.listen(id, event, dispatchEvent);
incr(a);
handlersMap[{ id, event }] = a;
}
void fiberDone(void *a)
{
decr((Action)a);
release_fiber();
}
void runInBackground(Action a) {
if (a != 0) {
incr(a);
create_fiber((void(*)(void*))runAction0, (void*)a, fiberDone);
}
}
void error(ERROR code, int subcode)
{
printf("Error: %d [%d]\n", code, subcode);
uBit.panic(42);
}
uint16_t *bytecode;
uint32_t *globals;
int numGlobals;
uint32_t *allocate(uint16_t sz)
{
uint32_t *arr = new uint32_t[sz];
memset(arr, 0, sz * 4);
return arr;
}
void checkStr(bool cond, const char *msg)
{
if (!cond) {
while (true) {
uBit.display.scroll(msg, 100);
uBit.sleep(100);
}
}
}
int templateHash()
{
return ((int*)bytecode)[4];
}
int programHash()
{
return ((int*)bytecode)[6];
}
int getNumGlobals()
{
return bytecode[16];
}
void exec_binary(int32_t *pc)
{
// XXX re-enable once the calibration code is fixed and [editor/embedded.ts]
// properly prepends a call to [internal_main].
// ::touch_develop::internal_main();
// unique group for radio based on source hash
// ::touch_develop::micro_bit::radioDefaultGroup = programHash();
// repeat error 4 times and restart as needed
microbit_panic_timeout(4);
int32_t ver = *pc++;
checkStr(ver == 0x4209, ":( Bad runtime version");
bytecode = *((uint16_t**)pc++); // the actual bytecode is here
globals = allocate(getNumGlobals());
// just compare the first word
checkStr(((uint32_t*)bytecode)[0] == 0x923B8E70 &&
templateHash() == *pc,
":( Failed partial flash");
uint32_t startptr = (uint32_t)bytecode;
startptr += 48; // header
startptr |= 1; // Thumb state
((uint32_t (*)())startptr)();
#ifdef DEBUG_MEMLEAKS
pxt::debugMemLeaks();
#endif
return;
}
void start()
{
exec_binary((int32_t*)functionsAndBytecode);
}
}
// vim: ts=2 sw=2 expandtab

333
libs/core/pxt.h Normal file
View File

@ -0,0 +1,333 @@
#ifndef __PXT_H
#define __PXT_H
// #define DEBUG_MEMLEAKS 1
#pragma GCC diagnostic ignored "-Wunused-parameter"
#include "MicroBit.h"
#include "MicroBitImage.h"
#include "ManagedString.h"
#include "ManagedType.h"
#define printf(...) uBit.serial.printf(__VA_ARGS__)
// #define printf(...)
#define intcheck(...) check(__VA_ARGS__)
//#define intcheck(...) do {} while (0)
#include <stdio.h>
#include <string.h>
#include <vector>
#include <stdint.h>
#ifdef DEBUG_MEMLEAKS
#include <set>
#endif
extern MicroBit uBit;
namespace pxt {
typedef uint32_t Action;
typedef uint32_t ImageLiteral;
typedef enum {
ERR_INVALID_BINARY_HEADER = 5,
ERR_OUT_OF_BOUNDS = 8,
ERR_REF_DELETED = 7,
ERR_SIZE = 9,
} ERROR;
extern const uint32_t functionsAndBytecode[];
extern uint32_t *globals;
extern uint16_t *bytecode;
class RefRecord;
// Utility functions
extern MicroBitEvent lastEvent;
void registerWithDal(int id, int event, Action a);
void runInBackground(Action a);
uint32_t runAction3(Action a, int arg0, int arg1, int arg2);
uint32_t runAction2(Action a, int arg0, int arg1);
uint32_t runAction1(Action a, int arg0);
uint32_t runAction0(Action a);
Action mkAction(int reflen, int totallen, int startptr);
void error(ERROR code, int subcode = 0);
void exec_binary(uint16_t *pc);
void start();
void debugMemLeaks();
// allocate [sz] words and clear them
uint32_t *allocate(uint16_t sz);
int templateHash();
int programHash();
int getNumGlobals();
RefRecord* mkClassInstance(int vtableOffset);
// The standard calling convention is:
// - when a pointer is loaded from a local/global/field etc, and incr()ed
// (in other words, its presence on stack counts as a reference)
// - after a function call, all pointers are popped off the stack and decr()ed
// This does not apply to the RefRecord and st/ld(ref) methods - they unref()
// the RefRecord* this.
int incr(uint32_t e);
void decr(uint32_t e);
inline void *ptrOfLiteral(int offset)
{
return &bytecode[offset];
}
inline ImageData* imageBytes(int offset)
{
return (ImageData*)(void*)&bytecode[offset];
}
// Checks if object has a VTable, or if its RefCounted* from the runtime.
inline bool hasVTable(uint32_t e)
{
return (*((uint32_t*)e) & 1) == 0;
}
inline void check(int cond, ERROR code, int subcode = 0)
{
if (!cond) error(code, subcode);
}
class RefObject;
#ifdef DEBUG_MEMLEAKS
extern std::set<RefObject*> allptrs;
#endif
typedef void (*RefObjectMethod)(RefObject *self);
typedef void *PVoid;
typedef void **PPVoid;
const PPVoid RefMapMarker = (PPVoid)(void*)43;
struct VTable {
uint16_t numbytes; // in the entire object, including the vtable pointer
uint16_t userdata;
PVoid *ifaceTable;
PVoid methods[2]; // we only use up to two methods here; pxt will generate more
// refmask sits at &methods[nummethods]
};
const int vtableShift = 2;
// A base abstract class for ref-counted objects.
class RefObject
{
public:
uint16_t refcnt;
uint16_t vtable;
RefObject(uint16_t vt)
{
refcnt = 2;
vtable = vt;
#ifdef DEBUG_MEMLEAKS
allptrs.insert(this);
#endif
}
inline VTable *getVTable() {
return (VTable*)(vtable << vtableShift);
}
void destroy();
void print();
// Call to disable pointer tracking on the current instance (in destructor or some other hack)
inline void untrack() {
#ifdef DEBUG_MEMLEAKS
allptrs.erase(this);
#endif
}
// Increment/decrement the ref-count. Decrementing to zero deletes the current object.
inline void ref()
{
check(refcnt > 0, ERR_REF_DELETED);
//printf("INCR "); this->print();
refcnt += 2;
}
inline void unref()
{
//printf("DECR "); this->print();
refcnt -= 2;
if (refcnt == 0) {
destroy();
}
}
};
// A ref-counted collection of either primitive or ref-counted objects (String, Image,
// user-defined record, another collection)
class RefCollection
: public RefObject
{
public:
// 1 - collection of refs (need decr)
// 2 - collection of strings (in fact we always have 3, never 2 alone)
inline uint32_t getFlags() { return getVTable()->userdata; }
inline bool isRef() { return getFlags() & 1; }
inline bool isString() { return getFlags() & 2; }
std::vector<uint32_t> data;
RefCollection(uint16_t f);
inline bool in_range(int x) {
return (0 <= x && x < (int)data.size());
}
inline int length() { return data.size(); }
void destroy();
void print();
void push(uint32_t x);
uint32_t getAt(int x);
void removeAt(int x);
void setAt(int x, uint32_t y);
int indexOf(uint32_t x, int start);
int removeElement(uint32_t x);
};
struct MapEntry {
uint32_t key;
uint32_t val;
};
class RefMap
: public RefObject
{
public:
std::vector<MapEntry> data;
RefMap();
void destroy();
void print();
int findIdx(uint32_t key);
};
// A ref-counted, user-defined JS object.
class RefRecord
: public RefObject
{
public:
// The object is allocated, so that there is space at the end for the fields.
uint32_t fields[];
RefRecord(uint16_t v) : RefObject(v) {}
uint32_t ld(int idx);
uint32_t ldref(int idx);
void st(int idx, uint32_t v);
void stref(int idx, uint32_t v);
};
// these are needed when constructing vtables for user-defined classes
void RefRecord_destroy(RefRecord *r);
void RefRecord_print(RefRecord *r);
class RefAction;
typedef uint32_t (*ActionCB)(uint32_t *captured, uint32_t arg0, uint32_t arg1, uint32_t arg2);
// Ref-counted function pointer. It's currently always a ()=>void procedure pointer.
class RefAction
: public RefObject
{
public:
// This is the same as for RefRecord.
uint8_t len;
uint8_t reflen;
ActionCB func; // The function pointer
// fields[] contain captured locals
uint32_t fields[];
void destroy();
void print();
RefAction();
inline void stCore(int idx, uint32_t v)
{
//printf("ST [%d] = %d ", idx, v); this->print();
intcheck(0 <= idx && idx < len, ERR_OUT_OF_BOUNDS, 10);
intcheck(fields[idx] == 0, ERR_OUT_OF_BOUNDS, 11); // only one assignment permitted
fields[idx] = v;
}
inline uint32_t runCore(int arg0, int arg1, int arg2) // internal; use runAction*() functions
{
this->ref();
uint32_t r = this->func(&this->fields[0], arg0, arg1, arg2);
this->unref();
return r;
}
};
// These two are used to represent locals written from inside inline functions
class RefLocal
: public RefObject
{
public:
uint32_t v;
void destroy();
void print();
RefLocal();
};
class RefRefLocal
: public RefObject
{
public:
uint32_t v;
void destroy();
void print();
RefRefLocal();
};
}
// The ARM Thumb generator in the JavaScript code is parsing
// the hex file and looks for the magic numbers as present here.
//
// Then it fetches function pointer addresses from there.
#define PXT_SHIMS_BEGIN \
namespace pxt { \
const uint32_t functionsAndBytecode[] __attribute__((aligned(0x20))) = { \
0x08010801, 0x42424242, 0x08010801, 0x8de9d83e,
#define PXT_SHIMS_END }; }
#pragma GCC diagnostic ignored "-Wpmf-conversions"
#define PXT_VTABLE_TO_INT(vt) ((uint32_t)(vt) >> vtableShift)
#define PXT_VTABLE_BEGIN(classname, flags, iface) \
const VTable classname ## _vtable \
__attribute__((aligned(1 << vtableShift))) \
= { \
sizeof(classname), \
flags, \
iface, \
{ \
(void*)&classname::destroy, \
(void*)&classname::print,
#define PXT_VTABLE_END } };
#define PXT_VTABLE_INIT(classname) \
RefObject(PXT_VTABLE_TO_INT(&classname ## _vtable))
#define PXT_VTABLE_CTOR(classname) \
PXT_VTABLE_BEGIN(classname, 0, 0) PXT_VTABLE_END \
classname::classname() : PXT_VTABLE_INIT(classname)
#endif
// vim: ts=2 sw=2 expandtab

View File

@ -4,6 +4,10 @@
"installedVersion": "tsmdvf", "installedVersion": "tsmdvf",
"files": [ "files": [
"README.md", "README.md",
"ManagedBuffer.cpp",
"ManagedBuffer.h",
"pxt.cpp",
"pxt.h",
"dal.d.ts", "dal.d.ts",
"enums.d.ts", "enums.d.ts",
"shims.d.ts", "shims.d.ts",

View File

@ -160,10 +160,10 @@
}, },
"compileService": { "compileService": {
"yottaTarget": "bbc-microbit-classic-gcc", "yottaTarget": "bbc-microbit-classic-gcc",
"yottaCorePackage": "pxt-microbit-core", "yottaCorePackage": "microbit",
"githubCorePackage": "microsoft/pxt-microbit-core", "githubCorePackage": "lancaster-university/microbit",
"gittag": "v0.5.1", "gittag": "v2.0.0-rc6",
"serviceId": "ws" "serviceId": "microbit"
}, },
"serial": { "serial": {
"manufacturerFilter": "^mbed$", "manufacturerFilter": "^mbed$",