Merge pull request #310 from Microsoft/coregone
merging pxt-microbit-core into the target
This commit is contained in:
		
							
								
								
									
										373
									
								
								libs/core/ManagedBuffer.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										373
									
								
								libs/core/ManagedBuffer.cpp
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										257
									
								
								libs/core/ManagedBuffer.h
									
									
									
									
									
										Normal 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
									
									
								
							
							
						
						
									
										116
									
								
								libs/core/dal.d.ts
									
									
									
									
										vendored
									
									
								
							@@ -1,11 +1,11 @@
 | 
			
		||||
// Auto-generated. Do not edit.
 | 
			
		||||
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_UART = 1200,
 | 
			
		||||
    MICROBIT_BLE_EVT_CONNECTED = 1,
 | 
			
		||||
    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_EVT_PLAY = 1,
 | 
			
		||||
    MES_REMOTE_CONTROL_EVT_PAUSE = 2,
 | 
			
		||||
@@ -70,8 +70,8 @@ declare const enum DAL {
 | 
			
		||||
    MES_DPAD_BUTTON_4_DOWN = 15,
 | 
			
		||||
    MES_DPAD_BUTTON_4_UP = 16,
 | 
			
		||||
    MES_BROADCAST_GENERAL_ID = 2000,
 | 
			
		||||
    // 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/MicroBitAccelerometerService.h
 | 
			
		||||
    // built/yt/yotta_modules/microbit-dal/inc/bluetooth/MicroBitBLEManager.h
 | 
			
		||||
    MICROBIT_BLE_PAIR_REQUEST = 0x01,
 | 
			
		||||
    MICROBIT_BLE_PAIR_COMPLETE = 0x02,
 | 
			
		||||
    MICROBIT_BLE_PAIR_PASSCODE = 0x04,
 | 
			
		||||
@@ -79,27 +79,29 @@ declare const enum DAL {
 | 
			
		||||
    MICROBIT_BLE_PAIRING_TIMEOUT = 90,
 | 
			
		||||
    MICROBIT_BLE_POWER_LEVELS = 8,
 | 
			
		||||
    MICROBIT_BLE_MAXIMUM_BONDS = 4,
 | 
			
		||||
    MICROBIT_BLE_EDDYSTONE_URL_ADV_INTERVAL = 400,
 | 
			
		||||
    // built\yt\yotta_modules\microbit-dal\inc\bluetooth\MicroBitButtonService.h
 | 
			
		||||
    // built\yt\yotta_modules\microbit-dal\inc\bluetooth\MicroBitDFUService.h
 | 
			
		||||
    MICROBIT_BLE_EDDYSTONE_ADV_INTERVAL = 400,
 | 
			
		||||
    // built/yt/yotta_modules/microbit-dal/inc/bluetooth/MicroBitButtonService.h
 | 
			
		||||
    // built/yt/yotta_modules/microbit-dal/inc/bluetooth/MicroBitDFUService.h
 | 
			
		||||
    MICROBIT_DFU_OPCODE_START_DFU = 1,
 | 
			
		||||
    MICROBIT_DFU_HISTOGRAM_WIDTH = 5,
 | 
			
		||||
    MICROBIT_DFU_HISTOGRAM_HEIGHT = 5,
 | 
			
		||||
    // built\yt\yotta_modules\microbit-dal\inc\bluetooth\MicroBitEventService.h
 | 
			
		||||
    // built\yt\yotta_modules\microbit-dal\inc\bluetooth\MicroBitIOPinService.h
 | 
			
		||||
    // built/yt/yotta_modules/microbit-dal/inc/bluetooth/MicroBitEddystone.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_DATA_SIZE = 10,
 | 
			
		||||
    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,
 | 
			
		||||
    // 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\MicroBitUARTService.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/MicroBitUARTService.h
 | 
			
		||||
    MICROBIT_UART_S_DEFAULT_BUF_SIZE = 20,
 | 
			
		||||
    MICROBIT_UART_S_EVT_DELIM_MATCH = 1,
 | 
			
		||||
    MICROBIT_UART_S_EVT_HEAD_MATCH = 2,
 | 
			
		||||
    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_INVALID_PARAMETER = -1001,
 | 
			
		||||
    MICROBIT_NOT_SUPPORTED = -1002,
 | 
			
		||||
@@ -114,10 +116,10 @@ declare const enum DAL {
 | 
			
		||||
    MICROBIT_OOM = 20,
 | 
			
		||||
    MICROBIT_HEAP_ERROR = 30,
 | 
			
		||||
    MICROBIT_NULL_DEREFERENCE = 40,
 | 
			
		||||
    // 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\MicroBitCompat.h
 | 
			
		||||
    // built\yt\yotta_modules\microbit-dal\inc\core\MicroBitComponent.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/MicroBitCompat.h
 | 
			
		||||
    // built/yt/yotta_modules/microbit-dal/inc/core/MicroBitComponent.h
 | 
			
		||||
    MICROBIT_ID_BUTTON_A = 1,
 | 
			
		||||
    MICROBIT_ID_BUTTON_B = 2,
 | 
			
		||||
    MICROBIT_ID_BUTTON_RESET = 3,
 | 
			
		||||
@@ -155,25 +157,25 @@ declare const enum DAL {
 | 
			
		||||
    MICROBIT_ID_NOTIFY_ONE = 1022,
 | 
			
		||||
    MICROBIT_ID_NOTIFY = 1023,
 | 
			
		||||
    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_CODE_LETTERS = 5,
 | 
			
		||||
    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_FIBER_FLAG_FOB = 0x01,
 | 
			
		||||
    MICROBIT_FIBER_FLAG_PARENT = 0x02,
 | 
			
		||||
    MICROBIT_FIBER_FLAG_CHILD = 0x04,
 | 
			
		||||
    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_HEIGHT = 5,
 | 
			
		||||
    MICROBIT_FONT_ASCII_START = 32,
 | 
			
		||||
    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_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_METHOD = 0x0002,
 | 
			
		||||
    MESSAGE_BUS_LISTENER_BUSY = 0x0004,
 | 
			
		||||
@@ -183,17 +185,17 @@ declare const enum DAL {
 | 
			
		||||
    MESSAGE_BUS_LISTENER_NONBLOCKING = 0x0040,
 | 
			
		||||
    MESSAGE_BUS_LISTENER_URGENT = 0x0080,
 | 
			
		||||
    MESSAGE_BUS_LISTENER_DELETING = 0x8000,
 | 
			
		||||
    // 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/MicroBitSystemTimer.h
 | 
			
		||||
    // built/yt/yotta_modules/microbit-dal/inc/core/NotifyEvents.h
 | 
			
		||||
    MICROBIT_DISPLAY_EVT_FREE = 1,
 | 
			
		||||
    MICROBIT_SERIAL_EVT_TX_EMPTY = 2,
 | 
			
		||||
    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,
 | 
			
		||||
    MICROBIT_DEFAULT_PWM_PERIOD = 20000,
 | 
			
		||||
    PWM_PERSISTENCE_TRANSIENT = 1,
 | 
			
		||||
    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_ADDED_TO_IDLE = 0x04,
 | 
			
		||||
    MMA8653_DEFAULT_ADDR = 0x3A,
 | 
			
		||||
@@ -233,7 +235,7 @@ declare const enum DAL {
 | 
			
		||||
    MICROBIT_ACCELEROMETER_SHAKE_DAMPING = 10,
 | 
			
		||||
    MICROBIT_ACCELEROMETER_SHAKE_RTX = 30,
 | 
			
		||||
    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_UP = 2,
 | 
			
		||||
    MICROBIT_BUTTON_EVT_CLICK = 3,
 | 
			
		||||
@@ -253,7 +255,7 @@ declare const enum DAL {
 | 
			
		||||
    MICROBIT_BUTTON_DOUBLE_CLICK_THRESH = 50,
 | 
			
		||||
    MICROBIT_BUTTON_SIMPLE_EVENTS = 0,
 | 
			
		||||
    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,
 | 
			
		||||
    MAG_DR_STATUS = 0x00,
 | 
			
		||||
    MAG_OUT_X_MSB = 0x01,
 | 
			
		||||
@@ -284,8 +286,8 @@ declare const enum DAL {
 | 
			
		||||
    MICROBIT_COMPASS_STATUS_CALIBRATING = 4,
 | 
			
		||||
    MICROBIT_COMPASS_STATUS_ADDED_TO_IDLE = 8,
 | 
			
		||||
    MAG3110_WHOAMI_VAL = 0xC4,
 | 
			
		||||
    // 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/MicroBitCompassCalibrator.h
 | 
			
		||||
    // built/yt/yotta_modules/microbit-dal/inc/drivers/MicroBitDisplay.h
 | 
			
		||||
    MICROBIT_DISPLAY_EVT_ANIMATION_COMPLETE = 1,
 | 
			
		||||
    MICROBIT_DISPLAY_EVT_LIGHT_SENSE = 2,
 | 
			
		||||
    MICROBIT_DISPLAY_DEFAULT_AUTOCLEAR = 1,
 | 
			
		||||
@@ -307,8 +309,8 @@ declare const enum DAL {
 | 
			
		||||
    MICROBIT_DISPLAY_ROTATION_90 = 1,
 | 
			
		||||
    MICROBIT_DISPLAY_ROTATION_180 = 2,
 | 
			
		||||
    MICROBIT_DISPLAY_ROTATION_270 = 3,
 | 
			
		||||
    // 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/MicroBitFile.h
 | 
			
		||||
    // built/yt/yotta_modules/microbit-dal/inc/drivers/MicroBitFileSystem.h
 | 
			
		||||
    MBFS_FILENAME_LENGTH = 16,
 | 
			
		||||
    MB_READ = 0x01,
 | 
			
		||||
    MB_WRITE = 0x02,
 | 
			
		||||
@@ -329,23 +331,23 @@ declare const enum DAL {
 | 
			
		||||
    MBFS_BLOCK_TYPE_FILE = 1,
 | 
			
		||||
    MBFS_BLOCK_TYPE_DIRECTORY = 2,
 | 
			
		||||
    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,
 | 
			
		||||
    // 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,
 | 
			
		||||
    // 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/MicroBitIO.h
 | 
			
		||||
    // built/yt/yotta_modules/microbit-dal/inc/drivers/MicroBitLightSensor.h
 | 
			
		||||
    MICROBIT_LIGHT_SENSOR_CHAN_NUM = 3,
 | 
			
		||||
    MICROBIT_LIGHT_SENSOR_AN_SET_TIME = 4000,
 | 
			
		||||
    MICROBIT_LIGHT_SENSOR_TICK_PERIOD = 5,
 | 
			
		||||
    MICROBIT_LIGHT_SENSOR_MAX_VALUE = 338,
 | 
			
		||||
    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,
 | 
			
		||||
    MICROBIT_DISPLAY_WIDTH = 5,
 | 
			
		||||
    MICROBIT_DISPLAY_HEIGHT = 5,
 | 
			
		||||
    // 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/MicroBitMessageBus.h
 | 
			
		||||
    // built/yt/yotta_modules/microbit-dal/inc/drivers/MicroBitMultiButton.h
 | 
			
		||||
    MICROBIT_MULTI_BUTTON_STATE_1 = 0x01,
 | 
			
		||||
    MICROBIT_MULTI_BUTTON_STATE_2 = 0x02,
 | 
			
		||||
    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_2 = 0x20,
 | 
			
		||||
    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_OUT = 0x02,
 | 
			
		||||
    IO_STATUS_ANALOG_IN = 0x04,
 | 
			
		||||
@@ -375,7 +377,7 @@ declare const enum DAL {
 | 
			
		||||
    MICROBIT_PIN_EVT_PULSE_LO = 5,
 | 
			
		||||
    PIN_CAPABILITY_DIGITAL = 0x01,
 | 
			
		||||
    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_BASE_ADDRESS = 0x75626974,
 | 
			
		||||
    MICROBIT_RADIO_DEFAULT_GROUP = 0,
 | 
			
		||||
@@ -387,9 +389,9 @@ declare const enum DAL {
 | 
			
		||||
    MICROBIT_RADIO_PROTOCOL_DATAGRAM = 1,
 | 
			
		||||
    MICROBIT_RADIO_PROTOCOL_EVENTBUS = 2,
 | 
			
		||||
    MICROBIT_RADIO_EVT_DATAGRAM = 1,
 | 
			
		||||
    // 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\MicroBitSerial.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/MicroBitSerial.h
 | 
			
		||||
    MICROBIT_SERIAL_DEFAULT_BAUD_RATE = 115200,
 | 
			
		||||
    MICROBIT_SERIAL_DEFAULT_BUFFER_SIZE = 20,
 | 
			
		||||
    MICROBIT_SERIAL_EVT_DELIM_MATCH = 1,
 | 
			
		||||
@@ -402,31 +404,31 @@ declare const enum DAL {
 | 
			
		||||
    ASYNC = 0,
 | 
			
		||||
    SYNC_SPINWAIT = 1,
 | 
			
		||||
    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_BLOCK_SIZE = 48,
 | 
			
		||||
    MICROBIT_STORAGE_KEY_SIZE = 16,
 | 
			
		||||
    MICROBIT_STORAGE_STORE_PAGE_OFFSET = 17,
 | 
			
		||||
    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_EVT_UPDATE = 1,
 | 
			
		||||
    MICROBIT_THERMOMETER_ADDED_TO_IDLE = 2,
 | 
			
		||||
    // 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\types\ManagedString.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\MicroBitCoordinateSystem.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/types/ManagedString.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/MicroBitCoordinateSystem.h
 | 
			
		||||
    RAW = 0,
 | 
			
		||||
    SIMPLE_CARTESIAN = 1,
 | 
			
		||||
    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_EVT_ANY = 0,
 | 
			
		||||
    CREATE_ONLY = 0,
 | 
			
		||||
    CREATE_AND_FIRE = 1,
 | 
			
		||||
    // 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\RefCounted.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/RefCounted.h
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,3 @@ MicroBitPin *getPin(int id);
 | 
			
		||||
typedef ImageData* Image;
 | 
			
		||||
typedef BufferData* Buffer;
 | 
			
		||||
 | 
			
		||||
namespace pxt {
 | 
			
		||||
  uint32_t programSize();
 | 
			
		||||
  uint32_t afterProgramPage();    
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										472
									
								
								libs/core/pxt.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										472
									
								
								libs/core/pxt.cpp
									
									
									
									
									
										Normal 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
 | 
			
		||||
							
								
								
									
										335
									
								
								libs/core/pxt.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										335
									
								
								libs/core/pxt.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,335 @@
 | 
			
		||||
#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();
 | 
			
		||||
  uint32_t programSize();
 | 
			
		||||
  uint32_t afterProgramPage();     
 | 
			
		||||
  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
 | 
			
		||||
@@ -4,6 +4,10 @@
 | 
			
		||||
    "installedVersion": "tsmdvf",
 | 
			
		||||
    "files": [
 | 
			
		||||
        "README.md",
 | 
			
		||||
        "ManagedBuffer.cpp",
 | 
			
		||||
        "ManagedBuffer.h",
 | 
			
		||||
        "pxt.cpp",
 | 
			
		||||
        "pxt.h",
 | 
			
		||||
        "dal.d.ts",
 | 
			
		||||
        "enums.d.ts",
 | 
			
		||||
        "shims.d.ts",
 | 
			
		||||
 
 | 
			
		||||
@@ -160,10 +160,10 @@
 | 
			
		||||
    },
 | 
			
		||||
    "compileService": {
 | 
			
		||||
        "yottaTarget": "bbc-microbit-classic-gcc",
 | 
			
		||||
        "yottaCorePackage": "pxt-microbit-core",
 | 
			
		||||
        "githubCorePackage": "microsoft/pxt-microbit-core",
 | 
			
		||||
        "gittag": "v0.5.1",
 | 
			
		||||
        "serviceId": "ws"
 | 
			
		||||
        "yottaCorePackage": "microbit",
 | 
			
		||||
        "githubCorePackage": "lancaster-university/microbit",
 | 
			
		||||
        "gittag": "v2.0.0-rc6",
 | 
			
		||||
        "serviceId": "microbit"
 | 
			
		||||
    },
 | 
			
		||||
    "serial": {
 | 
			
		||||
        "manufacturerFilter": "^mbed$",
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user