2.1.28, initiation update to PXT v5.28.24 (#54)
@@ -1,62 +1,4 @@
|
||||
<xml xmlns="http://www.w3.org/1999/xhtml">
|
||||
<block type="device_forever">
|
||||
<statement name="HANDLER">
|
||||
<block type="device_show_leds">
|
||||
<field name="LED00">FALSE</field>
|
||||
<field name="LED10">FALSE</field>
|
||||
<field name="LED20">FALSE</field>
|
||||
<field name="LED30">FALSE</field>
|
||||
<field name="LED40">FALSE</field>
|
||||
<field name="LED01">FALSE</field>
|
||||
<field name="LED11">TRUE</field>
|
||||
<field name="LED21">FALSE</field>
|
||||
<field name="LED31">TRUE</field>
|
||||
<field name="LED41">FALSE</field>
|
||||
<field name="LED02">FALSE</field>
|
||||
<field name="LED12">FALSE</field>
|
||||
<field name="LED22">FALSE</field>
|
||||
<field name="LED32">FALSE</field>
|
||||
<field name="LED42">FALSE</field>
|
||||
<field name="LED03">TRUE</field>
|
||||
<field name="LED13">FALSE</field>
|
||||
<field name="LED23">FALSE</field>
|
||||
<field name="LED33">FALSE</field>
|
||||
<field name="LED43">TRUE</field>
|
||||
<field name="LED04">FALSE</field>
|
||||
<field name="LED14">TRUE</field>
|
||||
<field name="LED24">TRUE</field>
|
||||
<field name="LED34">TRUE</field>
|
||||
<field name="LED44">FALSE</field>
|
||||
<next>
|
||||
<block type="device_show_leds">
|
||||
<field name="LED00">FALSE</field>
|
||||
<field name="LED10">FALSE</field>
|
||||
<field name="LED20">FALSE</field>
|
||||
<field name="LED30">FALSE</field>
|
||||
<field name="LED40">FALSE</field>
|
||||
<field name="LED01">FALSE</field>
|
||||
<field name="LED11">FALSE</field>
|
||||
<field name="LED21">FALSE</field>
|
||||
<field name="LED31">FALSE</field>
|
||||
<field name="LED41">FALSE</field>
|
||||
<field name="LED02">FALSE</field>
|
||||
<field name="LED12">FALSE</field>
|
||||
<field name="LED22">FALSE</field>
|
||||
<field name="LED32">FALSE</field>
|
||||
<field name="LED42">FALSE</field>
|
||||
<field name="LED03">FALSE</field>
|
||||
<field name="LED13">FALSE</field>
|
||||
<field name="LED23">FALSE</field>
|
||||
<field name="LED33">FALSE</field>
|
||||
<field name="LED43">FALSE</field>
|
||||
<field name="LED04">FALSE</field>
|
||||
<field name="LED14">FALSE</field>
|
||||
<field name="LED24">FALSE</field>
|
||||
<field name="LED34">FALSE</field>
|
||||
<field name="LED44">FALSE</field>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</statement>
|
||||
</block>
|
||||
<block type="pxt-on-start"></block>
|
||||
<block type="device_forever"></block>
|
||||
</xml>
|
||||
@@ -1,16 +1 @@
|
||||
basic.forever(() => {
|
||||
basic.showLeds(`
|
||||
. # . # .
|
||||
# . # . #
|
||||
# . . . #
|
||||
. # . # .
|
||||
. . # . .
|
||||
`)
|
||||
basic.showLeds(`
|
||||
. . . . .
|
||||
. . . . .
|
||||
. . . . .
|
||||
. . . . .
|
||||
. . . . .
|
||||
`)
|
||||
})
|
||||
|
||||
|
||||
50
libs/bluetooth/BLEHF2Service.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
#include "MicroBitConfig.h"
|
||||
#include "ble/UUID.h"
|
||||
#include "BLEHF2Service.h"
|
||||
#include "MicroBitEvent.h"
|
||||
|
||||
BLEHF2Service::BLEHF2Service(BLEDevice &_ble) :
|
||||
ble(_ble)
|
||||
{
|
||||
GattCharacteristic txCharacteristic(BLEHF2TxCharacteristicUUID, (uint8_t *)&txCharacteristicMessage, 0,
|
||||
sizeof(txCharacteristicMessage), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
|
||||
|
||||
// Initialise our characteristic values.
|
||||
memset(&txCharacteristicMessage, 0, sizeof(txCharacteristicMessage));
|
||||
|
||||
// Set default security requirements
|
||||
txCharacteristic.requireSecurity(SecurityManager::MICROBIT_BLE_SECURITY_LEVEL);
|
||||
|
||||
// setup GATT table
|
||||
GattCharacteristic *characteristics[] = {&txCharacteristic};
|
||||
GattService service(BLEHF2ServiceUUID, characteristics, sizeof(characteristics) / sizeof(GattCharacteristic *));
|
||||
ble.addService(service);
|
||||
|
||||
// retreive handles
|
||||
txCharacteristicHandle = txCharacteristic.getValueHandle();
|
||||
|
||||
// initialize data
|
||||
ble.gattServer().write(txCharacteristicHandle,(uint8_t *)&txCharacteristicMessage, sizeof(txCharacteristicMessage));
|
||||
}
|
||||
|
||||
void BLEHF2Service::sendSerial(const char *data, int len, bool isError) {
|
||||
if (ble.getGapState().connected)
|
||||
{
|
||||
int32_t sent = 0;
|
||||
while(sent < len) {
|
||||
int32_t n = min(BLEHF2_DATA_LENGTH, len - sent);
|
||||
txCharacteristicMessage.command = (isError ? BLEHF2_FLAG_SERIAL_OUT : BLEHF2_FLAG_SERIAL_ERR) | n;
|
||||
memcpy(&txCharacteristicMessage.data, data + sent, n);
|
||||
ble.gattServer().notify(txCharacteristicHandle,(uint8_t *)&txCharacteristicMessage, sizeof(txCharacteristicMessage));
|
||||
sent += n;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const uint8_t BLEHF2ServiceUUID[] = {
|
||||
0xb1,0x12,0xf5,0xe6,0x26,0x79,0x30,0xda,0xa2,0x6e,0x02,0x73,0xb6,0x04,0x38,0x49
|
||||
};
|
||||
|
||||
const uint8_t BLEHF2TxCharacteristicUUID[] = {
|
||||
0xb1,0x12,0xf5,0xe6,0x26,0x79,0x30,0xda,0xa2,0x6e,0x02,0x73,0xb6,0x04,0x38,0x4a
|
||||
};
|
||||
54
libs/bluetooth/BLEHF2Service.h
Normal file
@@ -0,0 +1,54 @@
|
||||
#ifndef BLE_HF2_SERVICE_H
|
||||
#define BLE_HF2_SERVICE_H
|
||||
|
||||
#include "MicroBitConfig.h"
|
||||
#include "ble/BLE.h"
|
||||
#include "MicroBitThermometer.h"
|
||||
#include "EventModel.h"
|
||||
#include "pxt.h"
|
||||
|
||||
#define HF2_ID 9501
|
||||
|
||||
#define BLEHF2_FLAG_SERIAL_OUT 0x80
|
||||
#define BLEHF2_FLAG_SERIAL_ERR 0xC0
|
||||
#define BLEHF2_DATA_LENGTH 19
|
||||
|
||||
// UUIDs for our service and characteristics
|
||||
extern const uint8_t BLEHF2ServiceUUID[];
|
||||
extern const uint8_t BLEHF2TxCharacteristicUUID[];
|
||||
|
||||
struct BLEHF2Packet {
|
||||
uint8_t command;
|
||||
uint8_t data[BLEHF2_DATA_LENGTH];
|
||||
};
|
||||
|
||||
class BLEHF2Service
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* Create a representation of the TemperatureService
|
||||
* @param _ble The instance of a BLE device that we're running on.
|
||||
*/
|
||||
BLEHF2Service(BLEDevice &_ble);
|
||||
|
||||
/**
|
||||
* Sends text
|
||||
*/
|
||||
void sendSerial(const char *data, int len, bool isError);
|
||||
|
||||
private:
|
||||
|
||||
// Bluetooth stack we're running on.
|
||||
BLEDevice &ble;
|
||||
|
||||
// memory for buffers.
|
||||
BLEHF2Packet txCharacteristicMessage;
|
||||
|
||||
// Handles to access each characteristic when they are held by Soft Device.
|
||||
GattAttribute::Handle_t txCharacteristicHandle;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -29,7 +29,10 @@
|
||||
"bluetooth.startTemperatureService": "Starts the Bluetooth temperature service",
|
||||
"bluetooth.startUartService": "Starts the Bluetooth UART service",
|
||||
"bluetooth.stopAdvertising": "Stops advertising Eddystone end points",
|
||||
"bluetooth.uartReadBuffer": "Reads buffered UART data into a buffer",
|
||||
"bluetooth.uartReadUntil": "Reads from the Bluetooth UART service buffer, returning its contents when the specified delimiter character is encountered.",
|
||||
"bluetooth.uartWriteBuffer": "Sends a buffer of data via Bluetooth UART",
|
||||
"bluetooth.uartWriteLine": "Writes to the Bluetooth UART service buffer. From there the data is transmitted over Bluetooth to a connected device.",
|
||||
"bluetooth.uartWriteNumber": "Prints a numeric value to the serial",
|
||||
"bluetooth.uartWriteString": "Writes to the Bluetooth UART service buffer. From there the data is transmitted over Bluetooth to a connected device.",
|
||||
"bluetooth.uartWriteValue": "Writes a ``name: value`` pair line to the serial.",
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
"bluetooth.startUartService|block": "bluetooth uart service",
|
||||
"bluetooth.stopAdvertising|block": "bluetooth stop advertising",
|
||||
"bluetooth.uartReadUntil|block": "bluetooth uart|read until %del=serial_delimiter_conv",
|
||||
"bluetooth.uartWriteLine|block": "bluetooth uart|write line %data",
|
||||
"bluetooth.uartWriteNumber|block": "bluetooth uart|write number %value",
|
||||
"bluetooth.uartWriteString|block": "bluetooth uart|write string %data",
|
||||
"bluetooth.uartWriteValue|block": "bluetooth uart|write value %name|= %value",
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"bluetooth": "Unterstützung für zusätzliche Bluetooth-Dienste.",
|
||||
"bluetooth.onBluetoothConnected|param|body": "Code, der ausgeführt wird, wenn eine Bluetooth-Verbindung aufgebaut wurde",
|
||||
"bluetooth.uartWriteNumber": "Gibt einen numerischen Wert an die serielle",
|
||||
"bluetooth.uartWriteValue": "Schreibt ein ``Namen: Wert`` Wertepaar auf die serielle Schnittstelle.",
|
||||
"bluetooth.uartWriteValue|param|name": "Name des Wertestreams, z.B.: x",
|
||||
"bluetooth.uartWriteValue|param|value": "Schreiben"
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "pxt.h"
|
||||
#include "MESEvents.h"
|
||||
#include "MicroBitUARTService.h"
|
||||
#include "BLEHF2Service.h"
|
||||
|
||||
using namespace pxt;
|
||||
|
||||
@@ -10,7 +11,14 @@ using namespace pxt;
|
||||
//% color=#0082FB weight=96 icon="\uf294"
|
||||
namespace bluetooth {
|
||||
MicroBitUARTService *uart = NULL;
|
||||
BLEHF2Service* pHF2 = NULL;
|
||||
|
||||
//%
|
||||
void __log(String msg) {
|
||||
if (NULL == pHF2)
|
||||
pHF2 = new BLEHF2Service(*uBit.ble);
|
||||
pHF2->sendSerial(msg->getUTF8Data(), msg->getUTF8Size(), false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the Bluetooth accelerometer service
|
||||
@@ -88,26 +96,59 @@ namespace bluetooth {
|
||||
}
|
||||
|
||||
//%
|
||||
void uartWriteString(StringData *data) {
|
||||
void uartWriteString(String data) {
|
||||
startUartService();
|
||||
uart->send(ManagedString(data));
|
||||
uart->send(MSTR(data));
|
||||
}
|
||||
|
||||
//%
|
||||
StringData* uartReadUntil(StringData *del) {
|
||||
String uartReadUntil(String del) {
|
||||
startUartService();
|
||||
return uart->readUntil(ManagedString(del)).leakData();
|
||||
return PSTR(uart->readUntil(MSTR(del)));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sends a buffer of data via Bluetooth UART
|
||||
*/
|
||||
//%
|
||||
void uartWriteBuffer(Buffer buffer) {
|
||||
startUartService();
|
||||
uart->send(buffer->data, buffer->length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads buffered UART data into a buffer
|
||||
*/
|
||||
//%
|
||||
Buffer uartReadBuffer() {
|
||||
startUartService();
|
||||
int bytes = uart->rxBufferedSize();
|
||||
auto buffer = mkBuffer(NULL, bytes);
|
||||
int read = uart->read(buffer->data, buffer->length);
|
||||
// read failed
|
||||
if (read < 0) {
|
||||
decrRC(buffer);
|
||||
return mkBuffer(NULL, 0);
|
||||
}
|
||||
// could not fill the buffer
|
||||
if (read != buffer->length) {
|
||||
auto tmp = mkBuffer(buffer->data, read);
|
||||
decrRC(buffer);
|
||||
buffer = tmp;
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers an event to be fired when one of the delimiter is matched.
|
||||
* @param delimiters the characters to match received characters against.
|
||||
*/
|
||||
//% help=bluetooth/on-uart-data-received
|
||||
//% weight=18 blockId=bluetooth_on_data_received block="bluetooth|on data received %delimiters=serial_delimiter_conv"
|
||||
void onUartDataReceived(StringData* delimiters, Action body) {
|
||||
void onUartDataReceived(String delimiters, Action body) {
|
||||
startUartService();
|
||||
uart->eventOn(ManagedString(delimiters));
|
||||
uart->eventOn(MSTR(delimiters));
|
||||
registerWithDal(MICROBIT_ID_BLE_UART, MICROBIT_UART_S_EVT_DELIM_MATCH, body);
|
||||
}
|
||||
|
||||
@@ -131,7 +172,7 @@ namespace bluetooth {
|
||||
//% parts="bluetooth"
|
||||
void onBluetoothDisconnected(Action body) {
|
||||
registerWithDal(MICROBIT_ID_BLE, MICROBIT_BLE_EVT_DISCONNECTED, body);
|
||||
}
|
||||
}
|
||||
|
||||
const int8_t CALIBRATED_POWERS[] = {-49, -37, -33, -28, -25, -20, -15, -10};
|
||||
/**
|
||||
@@ -143,11 +184,13 @@ namespace bluetooth {
|
||||
//% blockId=eddystone_advertise_url block="bluetooth advertise url %url|with power %power|connectable %connectable"
|
||||
//% parts=bluetooth weight=11 blockGap=8
|
||||
//% help=bluetooth/advertise-url blockExternalInputs=1
|
||||
void advertiseUrl(StringData* url, int power, bool connectable) {
|
||||
void advertiseUrl(String url, int power, bool connectable) {
|
||||
#if CONFIG_ENABLED(MICROBIT_BLE_EDDYSTONE_URL)
|
||||
power = min(MICROBIT_BLE_POWER_LEVELS-1, max(0, power));
|
||||
int8_t level = CALIBRATED_POWERS[power];
|
||||
uBit.bleManager.advertiseEddystoneUrl(ManagedString(url), level, connectable);
|
||||
uBit.bleManager.advertiseEddystoneUrl(MSTR(url), level, connectable);
|
||||
uBit.bleManager.setTransmitPower(power);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -158,14 +201,14 @@ namespace bluetooth {
|
||||
*/
|
||||
//% parts=bluetooth weight=12 advanced=true
|
||||
void advertiseUidBuffer(Buffer nsAndInstance, int power, bool connectable) {
|
||||
ManagedBuffer buf(nsAndInstance);
|
||||
if (buf.length() != 16) return;
|
||||
#if CONFIG_ENABLED(MICROBIT_BLE_EDDYSTONE_UID)
|
||||
auto buf = nsAndInstance;
|
||||
if (buf->length != 16) return;
|
||||
|
||||
power = min(MICROBIT_BLE_POWER_LEVELS-1, max(0, power));
|
||||
int8_t level = CALIBRATED_POWERS[power];
|
||||
uint8_t uidNs[10]; buf.readBytes(uidNs, 0, 10);
|
||||
uint8_t uidInst[6]; buf.readBytes(uidInst, 10, 6);
|
||||
uBit.bleManager.advertiseEddystoneUid((const char*)uidNs, (const char*)uidInst, level, connectable);
|
||||
uBit.bleManager.advertiseEddystoneUid((const char*)buf->data, (const char*)buf->data + 10, level, connectable);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -186,5 +229,5 @@ namespace bluetooth {
|
||||
//% help=bluetooth/stop-advertising advanced=true
|
||||
void stopAdvertising() {
|
||||
uBit.bleManager.stopAdvertising();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,20 @@
|
||||
/// <reference no-default-lib="true"/>
|
||||
/**
|
||||
* Support for additional Bluetooth services.
|
||||
*/
|
||||
//% color=#0082FB weight=96 icon="\uf294"
|
||||
namespace bluetooth {
|
||||
export let NEW_LINE = "\r\n";
|
||||
|
||||
/**
|
||||
* Internal use
|
||||
*/
|
||||
//% shim=bluetooth::__log
|
||||
export function __log(msg: string) {
|
||||
return;
|
||||
}
|
||||
console.addListener(function (msg) { __log(msg) });
|
||||
|
||||
/**
|
||||
* Writes to the Bluetooth UART service buffer. From there the data is transmitted over Bluetooth to a connected device.
|
||||
*/
|
||||
@@ -10,8 +22,17 @@ namespace bluetooth {
|
||||
//% blockId=bluetooth_uart_write block="bluetooth uart|write string %data" blockGap=8
|
||||
//% parts="bluetooth" shim=bluetooth::uartWriteString advanced=true
|
||||
export function uartWriteString(data: string): void {
|
||||
// dummy implementation for simulator
|
||||
console.log("UART Write: " + data)
|
||||
console.log(data)
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes to the Bluetooth UART service buffer. From there the data is transmitted over Bluetooth to a connected device.
|
||||
*/
|
||||
//% help=bluetooth/uart-write-line weight=79
|
||||
//% blockId=bluetooth_uart_line block="bluetooth uart|write line %data" blockGap=8
|
||||
//% parts="bluetooth" advanced=true
|
||||
export function uartWriteLine(data: string): void {
|
||||
uartWriteString(data + serial.NEW_LINE);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -33,7 +54,7 @@ namespace bluetooth {
|
||||
//% help=bluetooth/uart-write-value advanced=true
|
||||
//% blockId=bluetooth_uart_writevalue block="bluetooth uart|write value %name|= %value"
|
||||
export function uartWriteValue(name: string, value: number): void {
|
||||
uartWriteString(name + ":" + value + "\r\n");
|
||||
uartWriteString((name ? name + ":" : "") + value + NEW_LINE);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -44,7 +65,7 @@ namespace bluetooth {
|
||||
//% parts="bluetooth" shim=bluetooth::uartReadUntil advanced=true
|
||||
export function uartReadUntil(del: string): string {
|
||||
// dummy implementation for simulator
|
||||
return "???"
|
||||
return ""
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,8 +7,10 @@
|
||||
"shims.d.ts",
|
||||
"bluetooth.ts",
|
||||
"bluetooth.cpp",
|
||||
"_locales/de/bluetooth-jsdoc-strings.json"
|
||||
"BLEHF2Service.h",
|
||||
"BLEHF2Service.cpp"
|
||||
],
|
||||
"icon": "./static/packages/bluetooth/icon.png",
|
||||
"public": true,
|
||||
"dependencies": {
|
||||
"core": "file:../core"
|
||||
@@ -23,50 +25,10 @@
|
||||
},
|
||||
"optionalConfig": {
|
||||
"microbit-dal": {
|
||||
"stack_size": 1280,
|
||||
"gatt_table_size": "0x700"
|
||||
}
|
||||
},
|
||||
"userConfigs": [
|
||||
{
|
||||
"description": "No Pairing Required: Anyone can connect via Bluetooth.",
|
||||
"config": {
|
||||
"microbit-dal": {
|
||||
"bluetooth": {
|
||||
"open": 1,
|
||||
"pairing_mode": 0,
|
||||
"whitelist": 0,
|
||||
"security_level": null
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "JustWorks pairing (default): Pairing is automatic once the pairing is initiated.",
|
||||
"config": {
|
||||
"microbit-dal": {
|
||||
"bluetooth": {
|
||||
"open": null,
|
||||
"pairing_mode": null,
|
||||
"whitelist": null,
|
||||
"security_level": null
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Passkey pairing: Pairing requires 6 digit key to pair.",
|
||||
"config": {
|
||||
"microbit-dal": {
|
||||
"bluetooth": {
|
||||
"open": 0,
|
||||
"pairing_mode": 1,
|
||||
"whitelist": 1,
|
||||
"security_level": "SECURITY_MODE_ENCRYPTION_WITH_MITM"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"installedVersion": "vzlhfd"
|
||||
}
|
||||
18
libs/bluetooth/shims.d.ts
vendored
@@ -63,6 +63,18 @@ declare namespace bluetooth {
|
||||
//% parts="bluetooth" advanced=true shim=bluetooth::startUartService
|
||||
function startUartService(): void;
|
||||
|
||||
/**
|
||||
* Sends a buffer of data via Bluetooth UART
|
||||
*/
|
||||
//% shim=bluetooth::uartWriteBuffer
|
||||
function uartWriteBuffer(buffer: Buffer): void;
|
||||
|
||||
/**
|
||||
* Reads buffered UART data into a buffer
|
||||
*/
|
||||
//% shim=bluetooth::uartReadBuffer
|
||||
function uartReadBuffer(): Buffer;
|
||||
|
||||
/**
|
||||
* Registers an event to be fired when one of the delimiter is matched.
|
||||
* @param delimiters the characters to match received characters against.
|
||||
@@ -98,7 +110,7 @@ declare namespace bluetooth {
|
||||
//% blockId=eddystone_advertise_url block="bluetooth advertise url %url|with power %power|connectable %connectable"
|
||||
//% parts=bluetooth weight=11 blockGap=8
|
||||
//% help=bluetooth/advertise-url blockExternalInputs=1 shim=bluetooth::advertiseUrl
|
||||
function advertiseUrl(url: string, power: number, connectable: boolean): void;
|
||||
function advertiseUrl(url: string, power: int32, connectable: boolean): void;
|
||||
|
||||
/**
|
||||
* Advertise an Eddystone UID
|
||||
@@ -107,7 +119,7 @@ declare namespace bluetooth {
|
||||
* @param connectable true to keep bluetooth connectable for other services, false otherwise.
|
||||
*/
|
||||
//% parts=bluetooth weight=12 advanced=true shim=bluetooth::advertiseUidBuffer
|
||||
function advertiseUidBuffer(nsAndInstance: Buffer, power: number, connectable: boolean): void;
|
||||
function advertiseUidBuffer(nsAndInstance: Buffer, power: int32, connectable: boolean): void;
|
||||
|
||||
/**
|
||||
* Sets the bluetooth transmit power between 0 (minimal) and 7 (maximum).
|
||||
@@ -115,7 +127,7 @@ declare namespace bluetooth {
|
||||
*/
|
||||
//% parts=bluetooth weight=5 help=bluetooth/set-transmit-power advanced=true
|
||||
//% blockId=bluetooth_settransmitpower block="bluetooth set transmit power %power" shim=bluetooth::setTransmitPower
|
||||
function setTransmitPower(power: number): void;
|
||||
function setTransmitPower(power: int32): void;
|
||||
|
||||
/**
|
||||
* Stops advertising Eddystone end points
|
||||
|
||||
@@ -1,62 +1,3 @@
|
||||
<xml xmlns="http://www.w3.org/1999/xhtml">
|
||||
<block type="device_forever">
|
||||
<statement name="HANDLER">
|
||||
<block type="device_show_leds">
|
||||
<field name="LED00">FALSE</field>
|
||||
<field name="LED10">FALSE</field>
|
||||
<field name="LED20">FALSE</field>
|
||||
<field name="LED30">FALSE</field>
|
||||
<field name="LED40">FALSE</field>
|
||||
<field name="LED01">FALSE</field>
|
||||
<field name="LED11">TRUE</field>
|
||||
<field name="LED21">FALSE</field>
|
||||
<field name="LED31">TRUE</field>
|
||||
<field name="LED41">FALSE</field>
|
||||
<field name="LED02">FALSE</field>
|
||||
<field name="LED12">FALSE</field>
|
||||
<field name="LED22">FALSE</field>
|
||||
<field name="LED32">FALSE</field>
|
||||
<field name="LED42">FALSE</field>
|
||||
<field name="LED03">TRUE</field>
|
||||
<field name="LED13">FALSE</field>
|
||||
<field name="LED23">FALSE</field>
|
||||
<field name="LED33">FALSE</field>
|
||||
<field name="LED43">TRUE</field>
|
||||
<field name="LED04">FALSE</field>
|
||||
<field name="LED14">TRUE</field>
|
||||
<field name="LED24">TRUE</field>
|
||||
<field name="LED34">TRUE</field>
|
||||
<field name="LED44">FALSE</field>
|
||||
<next>
|
||||
<block type="device_show_leds">
|
||||
<field name="LED00">FALSE</field>
|
||||
<field name="LED10">FALSE</field>
|
||||
<field name="LED20">FALSE</field>
|
||||
<field name="LED30">FALSE</field>
|
||||
<field name="LED40">FALSE</field>
|
||||
<field name="LED01">FALSE</field>
|
||||
<field name="LED11">FALSE</field>
|
||||
<field name="LED21">FALSE</field>
|
||||
<field name="LED31">FALSE</field>
|
||||
<field name="LED41">FALSE</field>
|
||||
<field name="LED02">FALSE</field>
|
||||
<field name="LED12">FALSE</field>
|
||||
<field name="LED22">FALSE</field>
|
||||
<field name="LED32">FALSE</field>
|
||||
<field name="LED42">FALSE</field>
|
||||
<field name="LED03">FALSE</field>
|
||||
<field name="LED13">FALSE</field>
|
||||
<field name="LED23">FALSE</field>
|
||||
<field name="LED33">FALSE</field>
|
||||
<field name="LED43">FALSE</field>
|
||||
<field name="LED04">FALSE</field>
|
||||
<field name="LED14">FALSE</field>
|
||||
<field name="LED24">FALSE</field>
|
||||
<field name="LED34">FALSE</field>
|
||||
<field name="LED44">FALSE</field>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</statement>
|
||||
</block>
|
||||
<block type="pxt-on-start"></block>
|
||||
</xml>
|
||||
@@ -1,16 +1 @@
|
||||
basic.forever(() => {
|
||||
basic.showLeds(`
|
||||
. # . # .
|
||||
# . # . #
|
||||
# . . . #
|
||||
. # . # .
|
||||
. . # . .
|
||||
`)
|
||||
basic.showLeds(`
|
||||
. . . . .
|
||||
. . . . .
|
||||
. . . . .
|
||||
. . . . .
|
||||
. . . . .
|
||||
`)
|
||||
})
|
||||
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
import rgbw = basic.rgbw;
|
||||
serial.writeLine("I2C");
|
||||
// send to 0x44, register 0x00, value 0x46 (RESET ISL29125)
|
||||
pins.i2cWriteNumber(0x44, 0x0046, NumberFormat.UInt16BE);
|
||||
// send to 0x44, register 0x01, value 0x05 (GRB SAMPLING)
|
||||
pins.i2cWriteNumber(0x44, 0x0105, NumberFormat.UInt16BE);
|
||||
basic.forever(() => {
|
||||
serial.writeString("[");
|
||||
pins.i2cWriteNumber(0x44, 0x0A, NumberFormat.Int8BE);
|
||||
let g = pins.i2cReadNumber(0x44, NumberFormat.UInt8BE);
|
||||
serial.writeNumber(r);
|
||||
serial.writeString(",");
|
||||
pins.i2cWriteNumber(0x44, 0x0C, NumberFormat.UInt8BE);
|
||||
let r = pins.i2cReadNumber(0x44, NumberFormat.UInt8BE);
|
||||
serial.writeNumber(g);
|
||||
serial.writeString(",");
|
||||
pins.i2cWriteNumber(0x44, 0x0E, NumberFormat.UInt8BE);
|
||||
let b = pins.i2cReadNumber(0x44, NumberFormat.UInt8LE);
|
||||
serial.writeNumber(b);
|
||||
serial.writeLine("]");
|
||||
basic.setLedColor(basic.rgbw(r,g,b, 0));
|
||||
basic.pause(1000);
|
||||
});
|
||||
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"name": "calliope-i2c",
|
||||
"description": "Calliope I2C test",
|
||||
"files": [
|
||||
"i2c.ts"
|
||||
],
|
||||
"public": true,
|
||||
"dependencies": {
|
||||
"core": "file:../core"
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
serial.redirect(
|
||||
SerialPin.P0,
|
||||
SerialPin.P1,
|
||||
31250
|
||||
);
|
||||
|
||||
basic.forever(() => {
|
||||
for (let note = 0; note <= 90 - 1; note++) {
|
||||
// Note on channel 1 (0x90), some note value (note),
|
||||
// middle velocity (0x45):
|
||||
serial.writeString(String.fromCharCode(144));
|
||||
serial.writeString(String.fromCharCode(note));
|
||||
serial.writeString(String.fromCharCode(69));
|
||||
basic.pause(100);
|
||||
// Note on channel 1 (0x90), some note value (note),
|
||||
// silent velocity (0x00):
|
||||
serial.writeString(String.fromCharCode(144));
|
||||
serial.writeString(String.fromCharCode(note));
|
||||
serial.writeString("\0");
|
||||
basic.pause(100);
|
||||
basic.pause(1000);
|
||||
}
|
||||
});
|
||||
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"name": "midi",
|
||||
"description": "MIDI Example via Serial",
|
||||
"files": [
|
||||
"midi.ts"
|
||||
],
|
||||
"public": true,
|
||||
"dependencies": {
|
||||
"core": "file:../core"
|
||||
}
|
||||
}
|
||||
@@ -1,173 +0,0 @@
|
||||
basic.showString("RGB");
|
||||
basic.setLedColor(Colors.Blue);
|
||||
basic.pause(500);
|
||||
basic.setLedColor(Colors.Red);
|
||||
basic.pause(500);
|
||||
basic.setLedColor(Colors.Green);
|
||||
basic.pause(500);
|
||||
basic.setLedColor(Colors.Violet);
|
||||
basic.pause(500);
|
||||
basic.setLedColor(0);
|
||||
basic.showString("Gesten");
|
||||
input.onGesture(Gesture.Shake, () => {
|
||||
basic.showString("S")
|
||||
});
|
||||
input.onGesture(Gesture.LogoUp, () => {
|
||||
basic.showString("U")
|
||||
});
|
||||
input.onGesture(Gesture.LogoDown, () => {
|
||||
basic.showString("D")
|
||||
});
|
||||
input.onGesture(Gesture.ScreenUp, () => {
|
||||
basic.showString("+")
|
||||
});
|
||||
input.onGesture(Gesture.TiltRight, () => {
|
||||
basic.showString("R")
|
||||
});
|
||||
input.onGesture(Gesture.FreeFall, () => {
|
||||
basic.showString("F")
|
||||
});
|
||||
input.onGesture(Gesture.ScreenDown, () => {
|
||||
basic.showString("-")
|
||||
});
|
||||
input.onGesture(Gesture.TiltLeft, () => {
|
||||
basic.showString("L")
|
||||
});
|
||||
input.onGesture(Gesture.ThreeG, () => {
|
||||
basic.showString("3")
|
||||
});
|
||||
input.onGesture(Gesture.SixG, () => {
|
||||
basic.showString("6")
|
||||
});
|
||||
input.onPinPressed(TouchPin.P0, () => {
|
||||
basic.showNumber(0)
|
||||
});
|
||||
input.onPinPressed(TouchPin.P1, () => {
|
||||
basic.showNumber(1)
|
||||
});
|
||||
input.onPinPressed(TouchPin.P2, () => {
|
||||
basic.showNumber(2)
|
||||
});
|
||||
input.onPinPressed(TouchPin.P3, () => {
|
||||
basic.showNumber(3)
|
||||
});
|
||||
|
||||
basic.showString("Sound");
|
||||
music.setTempo(150);
|
||||
let whole = music.beat(BeatFraction.Whole);
|
||||
function note(n: Note, l: BeatFraction): number[] {
|
||||
return [music.noteFrequency(n), music.beat(l)];
|
||||
}
|
||||
|
||||
function getNoteName(frequency: number): string {
|
||||
switch (frequency) {
|
||||
case 262:
|
||||
return "C";
|
||||
case 277:
|
||||
return "CSharp";
|
||||
case 294:
|
||||
return "D";
|
||||
case 311:
|
||||
return "Eb";
|
||||
case 330:
|
||||
return "E";
|
||||
case 349:
|
||||
return "F";
|
||||
case 370:
|
||||
return "FSharp";
|
||||
case 392:
|
||||
return "G";
|
||||
case 415:
|
||||
return "GSharp";
|
||||
case 440:
|
||||
return "A";
|
||||
case 466:
|
||||
return "Bb";
|
||||
case 494:
|
||||
return "B";
|
||||
case 131:
|
||||
return "C3";
|
||||
case 139:
|
||||
return "CSharp3";
|
||||
case 147:
|
||||
return "D3";
|
||||
case 156:
|
||||
return "Eb3";
|
||||
case 165:
|
||||
return "E3";
|
||||
case 175:
|
||||
return "F3";
|
||||
case 185:
|
||||
return "FSharp3";
|
||||
case 196:
|
||||
return "G3";
|
||||
case 208:
|
||||
return "GSharp3";
|
||||
case 220:
|
||||
return "A3";
|
||||
case 233:
|
||||
return "Bb3";
|
||||
case 247:
|
||||
return "B3";
|
||||
case 523:
|
||||
return "C5";
|
||||
case 555:
|
||||
return "CSharp5";
|
||||
case 587:
|
||||
return "D5";
|
||||
case 622:
|
||||
return "Eb5";
|
||||
case 659:
|
||||
return "E5";
|
||||
case 698:
|
||||
return "F5";
|
||||
case 740:
|
||||
return "FSharp5";
|
||||
case 784:
|
||||
return "G5";
|
||||
case 831:
|
||||
return "GSharp5";
|
||||
case 880:
|
||||
return "A5";
|
||||
case 932:
|
||||
return "Bb5";
|
||||
case 989:
|
||||
return "B5";
|
||||
default:
|
||||
return "?";
|
||||
}
|
||||
}
|
||||
|
||||
let notes = [
|
||||
note(Note.E, BeatFraction.Quarter), note(Note.E, BeatFraction.Quarter), note(Note.F, BeatFraction.Quarter),
|
||||
note(Note.G, BeatFraction.Quarter), note(Note.G, BeatFraction.Quarter), note(Note.F, BeatFraction.Quarter),
|
||||
note(Note.E, BeatFraction.Quarter), note(Note.D, BeatFraction.Quarter), note(Note.C, BeatFraction.Quarter),
|
||||
note(Note.C, BeatFraction.Quarter), note(Note.D, BeatFraction.Quarter), note(Note.E, BeatFraction.Quarter),
|
||||
note(Note.E, BeatFraction.Quarter + BeatFraction.Eighth),
|
||||
note(Note.D, BeatFraction.Eighth), note(Note.D, BeatFraction.Half),
|
||||
note(Note.E, BeatFraction.Quarter), note(Note.E, BeatFraction.Quarter), note(Note.F, BeatFraction.Quarter),
|
||||
note(Note.G, BeatFraction.Quarter), note(Note.G, BeatFraction.Quarter), note(Note.F, BeatFraction.Quarter),
|
||||
note(Note.E, BeatFraction.Quarter), note(Note.D, BeatFraction.Quarter), note(Note.C, BeatFraction.Quarter),
|
||||
note(Note.C, BeatFraction.Quarter), note(Note.D, BeatFraction.Quarter), note(Note.E, BeatFraction.Quarter),
|
||||
note(Note.D, BeatFraction.Quarter + BeatFraction.Eighth),
|
||||
note(Note.C, BeatFraction.Eighth), note(Note.C, BeatFraction.Half),
|
||||
note(Note.D, BeatFraction.Quarter), note(Note.D, BeatFraction.Quarter), note(Note.E, BeatFraction.Quarter),
|
||||
note(Note.C, BeatFraction.Quarter), note(Note.D, BeatFraction.Quarter),
|
||||
note(Note.E, BeatFraction.Eighth), note(Note.F, BeatFraction.Eighth),
|
||||
note(Note.E, BeatFraction.Quarter), note(Note.C, BeatFraction.Quarter), note(Note.D, BeatFraction.Quarter),
|
||||
note(Note.E, BeatFraction.Eighth), note(Note.F, BeatFraction.Eighth),
|
||||
note(Note.E, BeatFraction.Quarter), note(Note.D, BeatFraction.Quarter), note(Note.C, BeatFraction.Quarter),
|
||||
note(Note.D, BeatFraction.Quarter), note(Note.G3, BeatFraction.Quarter), note(Note.E, BeatFraction.Half),
|
||||
note(Note.E, BeatFraction.Quarter), note(Note.F, BeatFraction.Quarter), note(Note.G, BeatFraction.Quarter),
|
||||
note(Note.G, BeatFraction.Quarter), note(Note.F, BeatFraction.Quarter), note(Note.E, BeatFraction.Quarter),
|
||||
note(Note.E, BeatFraction.Eighth), note(Note.F, BeatFraction.Eighth),
|
||||
note(Note.C, BeatFraction.Quarter), note(Note.C, BeatFraction.Quarter), note(Note.D, BeatFraction.Quarter),
|
||||
note(Note.E, BeatFraction.Quarter), note(Note.D, BeatFraction.Quarter + BeatFraction.Eighth),
|
||||
note(Note.C, BeatFraction.Eighth), note(Note.C, BeatFraction.Half)
|
||||
];
|
||||
|
||||
for (let t = 0; t < notes.length; t++) {
|
||||
music.playTone(notes[t][0], notes[t][1]);
|
||||
basic.showString(getNoteName(notes[t][0]));
|
||||
music.rest(whole - notes[t][1]);
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"name": "calliope",
|
||||
"description": "Test of Calliope Parts",
|
||||
"files": [
|
||||
"calliope.ts"
|
||||
],
|
||||
"public": true,
|
||||
"dependencies": {
|
||||
"core": "file:../core"
|
||||
}
|
||||
}
|
||||
@@ -1,373 +0,0 @@
|
||||
#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;
|
||||
}
|
||||
@@ -1,257 +0,0 @@
|
||||
#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
|
||||
|
||||
@@ -3,37 +3,39 @@
|
||||
"AcceleratorRange.FourG": "The accelerator measures forces up to 4 gravity",
|
||||
"AcceleratorRange.OneG": "The accelerator measures forces up to 1 gravity",
|
||||
"AcceleratorRange.TwoG": "The accelerator measures forces up to 2 gravity",
|
||||
"Array": "Add, remove, and replace items in lists.\n\nAdd, remove, and replace items in lists.",
|
||||
"Array": "Add, remove, and replace items in lists.",
|
||||
"Array.concat": "Concatenates the values with another array.",
|
||||
"Array.concat|param|arr": "The other array that is being concatenated with",
|
||||
"Array.every": "Tests whether all elements in the array pass the test implemented by the provided function.",
|
||||
"Array.every|param|callbackfn": "A function that accepts up to two arguments. The some method calls the callbackfn function one time for each element in the array.",
|
||||
"Array.every|param|callbackfn": "A function that accepts up to two arguments. The every method calls the callbackfn function one time for each element in the array.",
|
||||
"Array.fill": "Fills all the elements of an array from a start index to an end index with a static value. The end index is not included.",
|
||||
"Array.filter": "Return the elements of an array that meet the condition specified in a callback function.",
|
||||
"Array.filter|param|callbackfn": "A function that accepts up to two arguments. The filter method calls the callbackfn function one time for each element in the array.",
|
||||
"Array.find": "Returns the value of the first element in the array that satisfies the provided testing function. Otherwise undefined is returned.",
|
||||
"Array.forEach": "Call a defined callback function on each element of an array.",
|
||||
"Array.forEach|param|callbackfn": "A function that accepts up to two arguments. The forEach method calls the callbackfn function one time for each element in the array.",
|
||||
"Array.get": "Get the value at a particular index.",
|
||||
"Array.get": "Get the value at a particular index",
|
||||
"Array.get|param|index": "the zero-based position in the list of the item, eg: 0",
|
||||
"Array.indexOf": "Return the index of the first occurrence of a value in an array.",
|
||||
"Array.indexOf|param|fromIndex": "The array index at which to begin the search. If fromIndex is omitted, the search starts at index 0.",
|
||||
"Array.indexOf|param|item": "The value to locate in the array.",
|
||||
"Array.insertAt": "Insert the value at a particular index, increase the array length by 1.",
|
||||
"Array.insertAt": "Insert the value at a particular index, increases length by 1",
|
||||
"Array.insertAt|param|index": "the zero-based position in the list to insert the value, eg: 0",
|
||||
"Array.insertAt|param|value": "to insert, eg: 0",
|
||||
"Array.isArray": "Check if a given object is an array.",
|
||||
"Array.join": "joins all elements of an array into a string and returns this string.",
|
||||
"Array.join|param|sep": "the string separator",
|
||||
"Array.length": "Gets or sets the length of the array. This is a number one higher than the highest element defined in an array.",
|
||||
"Array.length": "Get or set the length of an array. This number is one more than the index of the last element the array.",
|
||||
"Array.map": "Call a defined callback function on each element of an array, and return an array containing the results.",
|
||||
"Array.map|param|callbackfn": "A function that accepts up to two arguments. The map method calls the callbackfn function one time for each element in the array.",
|
||||
"Array.pop": "Remove the last element from an array and return it.",
|
||||
"Array.push": "Append a new elements to an array.",
|
||||
"Array.push|param|item": "to append to the Array.",
|
||||
"Array.push": "Append a new element to an array.",
|
||||
"Array.reduce": "Call the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.",
|
||||
"Array.reduce|param|callbackfn": "A function that accepts up to three arguments. The reduce method calls the callbackfn function one time for each element in the array.",
|
||||
"Array.reduce|param|initialValue": "Initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.",
|
||||
"Array.removeAt": "Remove the element at a certain index.",
|
||||
"Array.removeAt|param|index": "the zero-based position in the list to remove the value from, eg: 0",
|
||||
"Array.removeElement": "Remove the first occurence of an object. Return true if removed.",
|
||||
"Array.removeElement": "Remove the first occurence of an object. Returns true if removed.",
|
||||
"Array.reverse": "Reverse the elements in an array. The first array element becomes the last, and the last array element becomes the first.",
|
||||
"Array.set": "Store a value at a particular index.",
|
||||
"Array.set": "Store a value at a particular index",
|
||||
"Array.set|param|index": "the zero-based position in the list to store the value, eg: 0",
|
||||
"Array.shift": "Remove the first element from an array and return it. This method changes the length of the array.",
|
||||
"Array.slice": "Return a section of an array.",
|
||||
@@ -46,21 +48,27 @@
|
||||
"Array.splice|param|deleteCount": "The number of elements to remove. eg: 0",
|
||||
"Array.splice|param|start": "The zero-based location in the array from which to start removing elements. eg: 0",
|
||||
"Array.unshift": "Add one element to the beginning of an array and return the new length of the array.",
|
||||
"Array.unshift|param|value": "to insert at the start of the Array.",
|
||||
"Array@type": "Add, remove, and replace items in lists.",
|
||||
"Boolean.toString": "Returns a string representation of an object.",
|
||||
"Buffer.concat": "Return concatenation of current buffer and the given buffer",
|
||||
"Buffer.fill": "Fill (a fragment) of the buffer with given value.",
|
||||
"Buffer.getNumber": "Read a number in specified format from the buffer.",
|
||||
"Buffer.getUint8": "Reads an unsigned byte at a particular location",
|
||||
"Buffer.indexOf": "Return position of other buffer in current buffer",
|
||||
"Buffer.length": "Returns the length of a Buffer object.",
|
||||
"Buffer.rotate": "Rotate buffer left in place.",
|
||||
"Buffer.rotate|param|length": "number of elements in buffer. If negative, length is set as the buffer length minus start. eg: -1",
|
||||
"Buffer.rotate": "Rotate buffer left in place.\n\n\n\nstart. eg: -1",
|
||||
"Buffer.rotate|param|length": "number of elements in buffer. If negative, length is set as the buffer length minus",
|
||||
"Buffer.rotate|param|offset": "number of bytes to shift; use negative value to shift right",
|
||||
"Buffer.rotate|param|start": "start offset in buffer. Default is 0.",
|
||||
"Buffer.setNumber": "Write a number in specified format in the buffer.",
|
||||
"Buffer.shift": "Shift buffer left in place, with zero padding.",
|
||||
"Buffer.shift|param|length": "number of elements in buffer. If negative, length is set as the buffer length minus start. eg: -1",
|
||||
"Buffer.setUint8": "Writes an unsigned byte at a particular location",
|
||||
"Buffer.shift": "Shift buffer left in place, with zero padding.\n\n\n\nstart. eg: -1",
|
||||
"Buffer.shift|param|length": "number of elements in buffer. If negative, length is set as the buffer length minus",
|
||||
"Buffer.shift|param|offset": "number of bytes to shift; use negative value to shift right",
|
||||
"Buffer.shift|param|start": "start offset in buffer. Default is 0.",
|
||||
"Buffer.slice": "Return a copy of a fragment of a buffer.",
|
||||
"Buffer.toHex": "Convert a buffer to its hexadecimal representation.",
|
||||
"Buffer.toString": "Convert a buffer to string assuming UTF8 encoding",
|
||||
"Buffer.write": "Write contents of `src` at `dstOffset` in current buffer.",
|
||||
"Colors": "Well known colors",
|
||||
"EventCreationMode": "How to create the event.",
|
||||
@@ -81,8 +89,8 @@
|
||||
"Image.height": "Gets the height in rows (always 5)",
|
||||
"Image.pixel": "Get the pixel state at position ``(x,y)``",
|
||||
"Image.pixelBrightness": "Gets the pixel brightness ([0..255]) at a given position",
|
||||
"Image.pixel|param|x": "TODO",
|
||||
"Image.pixel|param|y": "TODO",
|
||||
"Image.pixel|param|x": "pixel column",
|
||||
"Image.pixel|param|y": "pixel row",
|
||||
"Image.plotFrame": "Draws the ``index``-th frame of the image on the screen.",
|
||||
"Image.plotFrame|param|xOffset": "column index to start displaying the image",
|
||||
"Image.plotImage": "Plots the image at a given column to the screen",
|
||||
@@ -91,59 +99,112 @@
|
||||
"Image.scrollImage|param|interval": "time between each animation step in milli seconds, eg: 200",
|
||||
"Image.setPixel": "Set a pixel state at position ``(x,y)``",
|
||||
"Image.setPixelBrightness": "Sets a specific pixel brightness at a given position",
|
||||
"Image.setPixel|param|value": "TODO",
|
||||
"Image.setPixel|param|x": "TODO",
|
||||
"Image.setPixel|param|y": "TODO",
|
||||
"Image.showFrame": "Shows a particular frame of the image strip.",
|
||||
"Image.showFrame|param|frame": "TODO",
|
||||
"Image.setPixel|param|value": "pixel state",
|
||||
"Image.setPixel|param|x": "pixel column",
|
||||
"Image.setPixel|param|y": "pixel row",
|
||||
"Image.showFrame": "Show a particular frame of the image strip.",
|
||||
"Image.showFrame|param|frame": "image frame to show",
|
||||
"Image.showImage": "Shows an frame from the image at offset ``x offset``.",
|
||||
"Image.showImage|param|xOffset": "column index to start displaying the image",
|
||||
"Image.width": "Gets the width in columns",
|
||||
"Infinity": "Constant representing positive infinity.",
|
||||
"Math": "More complex operations with numbers.",
|
||||
"Math.abs": "Returns the absolute value of a number (the value without regard to whether it is positive or negative).\nFor example, the absolute value of -5 is the same as the absolute value of 5.",
|
||||
"Math.abs|param|x": "A numeric expression for which the absolute value is needed.",
|
||||
"Math.acos": "Returns the arccosine (in radians) of a number",
|
||||
"Math.acos|param|x": "A number",
|
||||
"Math.asin": "Returns the arcsine (in radians) of a number",
|
||||
"Math.asin|param|x": "A number",
|
||||
"Math.atan": "Returns the arctangent (in radians) of a number",
|
||||
"Math.atan2": "Returns the arctangent of the quotient of its arguments.",
|
||||
"Math.atan2|param|x": "A number",
|
||||
"Math.atan2|param|y": "A number",
|
||||
"Math.atan|param|x": "A number",
|
||||
"Math.ceil": "Returns the smallest number greater than or equal to its numeric argument.",
|
||||
"Math.ceil|param|x": "A numeric expression.",
|
||||
"Math.constrain": "Constrains a number to be within a range",
|
||||
"Math.cos": "Returns the cosine of a number.",
|
||||
"Math.cos|param|x": "An angle in radians",
|
||||
"Math.exp": "Returns returns ``e^x``.",
|
||||
"Math.exp|param|x": "A number",
|
||||
"Math.floor": "Returns the greatest number less than or equal to its numeric argument.",
|
||||
"Math.floor|param|x": "A numeric expression.",
|
||||
"Math.icos": "Returns the cosine of an input angle. This is an 8-bit approximation.",
|
||||
"Math.icos|param|theta": "input angle from 0-255",
|
||||
"Math.idiv": "Returns the value of integer signed 32 bit division of two numbers.",
|
||||
"Math.idiv|param|x": "The first number",
|
||||
"Math.idiv|param|y": "The second number",
|
||||
"Math.imul": "Returns the value of integer signed 32 bit multiplication of two numbers.",
|
||||
"Math.imul|param|x": "The first number",
|
||||
"Math.imul|param|y": "The second number",
|
||||
"Math.isin": "Returns the sine of an input angle. This is an 8-bit approximation.",
|
||||
"Math.isin|param|theta": "input angle from 0-255",
|
||||
"Math.log": "Returns the natural logarithm (base e) of a number.",
|
||||
"Math.log|param|x": "A number",
|
||||
"Math.map": "Re-maps a number from one range to another. That is, a value of ``from low`` would get mapped to ``to low``, a value of ``from high`` to ``to high``, values in-between to values in-between, etc.",
|
||||
"Math.map|param|fromHigh": "the upper bound of the value's current range, eg: 1023",
|
||||
"Math.map|param|fromLow": "the lower bound of the value's current range",
|
||||
"Math.map|param|toHigh": "the upper bound of the value's target range, eg: 4",
|
||||
"Math.map|param|toLow": "the lower bound of the value's target range",
|
||||
"Math.map|param|value": "value to map in ranges",
|
||||
"Math.max": "Returns the larger of two supplied numeric expressions.",
|
||||
"Math.min": "Returns the smaller of two supplied numeric expressions.",
|
||||
"Math.pow": "Return the value of a base expression taken to a specified power.",
|
||||
"Math.pow": "Returns the value of a base expression taken to a specified power.",
|
||||
"Math.pow|param|x": "The base value of the expression.",
|
||||
"Math.pow|param|y": "The exponent value of the expression.",
|
||||
"Math.random": "Return a pseudorandom number between 0 and `limit`.",
|
||||
"Math.random": "Returns a pseudorandom number between 0 and 1.",
|
||||
"Math.randomBoolean": "Generates a `true` or `false` value randomly, just like flipping a coin.",
|
||||
"Math.random|param|limit": "the upper bound of the number generated, eg: 4",
|
||||
"Math.randomRange": "Returns a pseudorandom number between min and max included.\nIf both numbers are integral, the result is integral.",
|
||||
"Math.randomRange|param|max": "the upper inclusive bound, eg: 10",
|
||||
"Math.randomRange|param|min": "the lower inclusive bound, eg: 0",
|
||||
"Math.round": "Returns a supplied numeric expression rounded to the nearest number.",
|
||||
"Math.roundWithPrecision": "Rounds ``x`` to a number with the given number of ``digits``",
|
||||
"Math.roundWithPrecision|param|digits": "the number of resulting digits",
|
||||
"Math.roundWithPrecision|param|x": "the number to round",
|
||||
"Math.round|param|x": "The value to be rounded to the nearest number.",
|
||||
"Math.sign": "Returns the sign of the x, indicating whether x is positive, negative or zero.",
|
||||
"Math.sign|param|x": "The numeric expression to test",
|
||||
"Math.sqrt": "Return the square root of a number.",
|
||||
"Math.sin": "Returns the sine of a number.",
|
||||
"Math.sin|param|x": "An angle in radians",
|
||||
"Math.sqrt": "Returns the square root of a number.",
|
||||
"Math.sqrt|param|x": "A numeric expression.",
|
||||
"Math.tan": "Returns the tangent of a number.",
|
||||
"Math.tan|param|x": "An angle in radians",
|
||||
"Math.trunc": "Returns the number with the decimal part truncated.",
|
||||
"Math.trunc|param|x": "A numeric expression.",
|
||||
"Number.toString": "Return a string representation of a number.",
|
||||
"String": "Combine, split, and search text strings.\n\nCombine, split, and search text strings.",
|
||||
"NaN": "Constant representing Not-A-Number.",
|
||||
"Number.isNaN": "Check if a given value is of type Number and it is a NaN.",
|
||||
"Number.toString": "Returns a string representation of a number.",
|
||||
"Object.keys": "Return the field names in an object.",
|
||||
"String": "Combine, split, and search text strings.",
|
||||
"String.charAt": "Return the character at the specified index.",
|
||||
"String.charAt|param|index": "The zero-based index of the desired character, eg: 0",
|
||||
"String.charAt|param|index": "The zero-based index of the desired character.",
|
||||
"String.charCodeAt": "Return the Unicode value of the character at the specified location.",
|
||||
"String.charCodeAt|param|index": "The zero-based index of the desired character. If there is no character at the specified index, NaN is returned.",
|
||||
"String.compare": "See how the order of characters in two strings is different (in ASCII encoding).",
|
||||
"String.compare|param|that": "String to compare to target string",
|
||||
"String.concat": "Returns a string that contains the concatenation of two or more strings.",
|
||||
"String.concat|param|other": "The string to append to the end of the string, eg: \"add me!\"",
|
||||
"String.concat|param|other": "The string to append to the end of the string.",
|
||||
"String.fromCharCode": "Make a string from the given ASCII character code.",
|
||||
"String.includes": "Determines whether a string contains the characters of a specified string.",
|
||||
"String.includes|param|searchValue": "the text to find",
|
||||
"String.includes|param|start": "optional start index for the search",
|
||||
"String.indexOf": "Returns the position of the first occurrence of a specified value in a string.",
|
||||
"String.indexOf|param|searchValue": "the text to find",
|
||||
"String.indexOf|param|start": "optional start index for the search",
|
||||
"String.isEmpty": "Returns a value indicating if the string is empty",
|
||||
"String.length": "Return the length of a String object.",
|
||||
"String.length": "Returns the length of a String object.",
|
||||
"String.slice": "Return a substring of the current string.",
|
||||
"String.slice|param|end": "one-past-last character index",
|
||||
"String.slice|param|start": "first character index; can be negative from counting from the end, eg:0",
|
||||
"String.split": "Splits the string according to the separators",
|
||||
"String.split|param|separator": "@param limit ",
|
||||
"String.substr": "Return a substring of the current string.",
|
||||
"String.substr|param|length": "number of characters to extract, eg: 3",
|
||||
"String.substr|param|start": "first character index; can be negative from counting from the end, eg: 0",
|
||||
"String.substr|param|length": "number of characters to extract",
|
||||
"String.substr|param|start": "first character index; can be negative from counting from the end, eg:0",
|
||||
"String.toLowerCase": "Converts the string to lower case characters.",
|
||||
"String@type": "Combine, split, and search text strings.",
|
||||
"StringMap": "A dictionary from string key to string values",
|
||||
"basic": "Provides access to basic micro:bit functionality.\n\nProvides access to basic micro:bit functionality.",
|
||||
"basic.clearScreen": "Turn off all LEDs",
|
||||
"basic.color": "Converts the color name to a number",
|
||||
@@ -161,11 +222,11 @@
|
||||
"basic.showAnimation": "Shows a sequence of LED screens as an animation.",
|
||||
"basic.showAnimation|param|interval": "time in milliseconds between each redraw",
|
||||
"basic.showAnimation|param|leds": "pattern of LEDs to turn on/off",
|
||||
"basic.showArrow": "Shows an arrow on screent",
|
||||
"basic.showArrow": "Draws an arrow on the LED screen",
|
||||
"basic.showArrow|param|direction": "the direction of the arrow",
|
||||
"basic.showArrow|param|interval": "the amount of time (milliseconds) to show the icon. Default is 600.",
|
||||
"basic.showIcon": "Draws the selected icon on the LED screen",
|
||||
"basic.showIcon|param|icon": "the predifined icon id",
|
||||
"basic.showIcon|param|icon": "the predefined icon id",
|
||||
"basic.showIcon|param|interval": "the amount of time (milliseconds) to show the icon. Default is 600.",
|
||||
"basic.showLeds": "Draws an image on the LED screen.",
|
||||
"basic.showLeds|param|interval": "time in milliseconds to pause after drawing",
|
||||
@@ -174,17 +235,28 @@
|
||||
"basic.showNumber|param|interval": "speed of scroll; eg: 150, 100, 200, -100",
|
||||
"basic.showString": "Display text on the display, one character at a time. If the string fits on the screen (i.e. is one letter), does not scroll.",
|
||||
"basic.showString|param|interval": "how fast to shift characters; eg: 150, 100, 200, -100",
|
||||
"basic.showString|param|text": "the text to scroll on the screen, eg: \"Hello!\"",
|
||||
"basic.showString|param|text": "the text to scroll on the screen, eg: \"hi!\"",
|
||||
"basic.turnRgbLedOff": "Sets the color on the build-in LED. Set to 0 to turn off.",
|
||||
"console": "Reading and writing data to the console output.",
|
||||
"console.addListener": "Adds a listener for the log messages",
|
||||
"console.log": "Write a line of text to the console output.",
|
||||
"console.logValue": "Write a name:value pair as a line of text to the console output.",
|
||||
"console.logValue|param|name": "name of the value stream, eg: \"x\"",
|
||||
"console.logValue|param|value": "to write",
|
||||
"control": "Runtime and event utilities.",
|
||||
"control.assert": "If the condition is false, display msg on serial console, and panic with code 098.",
|
||||
"control.deviceName": "Gets a friendly name for the device derived from the its serial number",
|
||||
"control.createBuffer": "Create a new zero-initialized buffer.",
|
||||
"control.createBufferFromUTF8": "Create a new buffer with UTF8-encoded string",
|
||||
"control.createBufferFromUTF8|param|str": "the string to put in the buffer",
|
||||
"control.createBuffer|param|size": "number of bytes in the buffer",
|
||||
"control.deviceName": "Make a friendly name for the device based on its serial number",
|
||||
"control.deviceSerialNumber": "Derive a unique, consistent serial number of this device from internal data.",
|
||||
"control.eventSourceId": "Returns the value of a C++ runtime constant",
|
||||
"control.eventTimestamp": "Gets the timestamp of the last event executed on the bus",
|
||||
"control.eventValue": "Gets the value of the last event executed on the bus",
|
||||
"control.eventValueId": "Returns the value of a C++ runtime constant",
|
||||
"control.inBackground": "Schedules code that run in the background.",
|
||||
"control.onEvent": "Raises an event in the event bus.",
|
||||
"control.onEvent": "Registers an event handler.",
|
||||
"control.panic": "Display specified error code and stop the program.",
|
||||
"control.raiseEvent": "Raises an event in the event bus.",
|
||||
"control.raiseEvent|param|mode": "optional definition of how the event should be processed after construction (default is CREATE_AND_FIRE).",
|
||||
@@ -194,6 +266,8 @@
|
||||
"control.runtimeWarning": "Display warning in the simulator.",
|
||||
"control.waitMicros": "Blocks the current fiber for the given microseconds",
|
||||
"control.waitMicros|param|micros": "number of micro-seconds to wait. eg: 4",
|
||||
"convertToText": "Convert any value to text",
|
||||
"convertToText|param|value": "value to be converted to text",
|
||||
"game": "A single-LED sprite game engine",
|
||||
"game.LedSprite": "A game sprite rendered as a single LED",
|
||||
"game.LedSprite.blink": "Reports the ``blink`` duration of a sprite",
|
||||
@@ -219,9 +293,10 @@
|
||||
"game.LedSprite.goTo|param|x": "TODO",
|
||||
"game.LedSprite.goTo|param|y": "TODO",
|
||||
"game.LedSprite.ifOnEdgeBounce": "If touching the edge of the stage and facing towards it, then turn away.",
|
||||
"game.LedSprite.isDeleted": "Reports whether the sprite has been deleted from the game engine.",
|
||||
"game.LedSprite.isTouching": "Reports true if sprite has the same position as specified sprite",
|
||||
"game.LedSprite.isTouchingEdge": "Reports true if sprite is touching an edge",
|
||||
"game.LedSprite.isTouching|param|other": "TODO",
|
||||
"game.LedSprite.isTouching|param|other": "the other sprite to check overlap or touch",
|
||||
"game.LedSprite.move": "Move a certain number of LEDs in the current direction",
|
||||
"game.LedSprite.move|param|leds": "number of leds to move, eg: 1, -1",
|
||||
"game.LedSprite.off": "Turns off the sprite (on by default)",
|
||||
@@ -232,7 +307,7 @@
|
||||
"game.LedSprite.setBrightness": "Set the ``brightness`` of a sprite",
|
||||
"game.LedSprite.setBrightness|param|brightness": "the brightness from 0 (off) to 255 (on), eg: 255.",
|
||||
"game.LedSprite.setDirection": "Set the direction of the current sprite, rounded to the nearest multiple of 45",
|
||||
"game.LedSprite.setDirection|param|degrees": "TODO",
|
||||
"game.LedSprite.setDirection|param|degrees": "new direction in degrees",
|
||||
"game.LedSprite.setX": "Set the ``x`` position of a sprite",
|
||||
"game.LedSprite.setX|param|x": "TODO",
|
||||
"game.LedSprite.setY": "Set the ``y`` position of a sprite",
|
||||
@@ -247,8 +322,8 @@
|
||||
"game.LedSprite.turn|param|direction": "left or right",
|
||||
"game.LedSprite.x": "Reports the ``x`` position of a sprite on the LED screen",
|
||||
"game.LedSprite.y": "Reports the ``y`` position of a sprite on the LED screen",
|
||||
"game.addLife": "Adds life points to the current life",
|
||||
"game.addLife|param|lives": "TODO",
|
||||
"game.addLife": "Add life points to the current life amount",
|
||||
"game.addLife|param|lives": "amount of lives to add",
|
||||
"game.addScore": "Adds points to the current score and shows an animation",
|
||||
"game.addScore|param|points": "amount of points to change, eg: 1",
|
||||
"game.createSprite": "Creates a new LED sprite pointing to the right.",
|
||||
@@ -257,38 +332,42 @@
|
||||
"game.currentTime": "Gets the remaining time (since `start countdown`) or current time (since the device started or `start stopwatch`) in milliseconds.",
|
||||
"game.gameOver": "Displays a game over animation and the score.",
|
||||
"game.invalidSprite": "Gets an invalid sprite; used to initialize locals.",
|
||||
"game.isGameOver": "Indicates if the game is display the game over sequence.",
|
||||
"game.isGameOver": "Indicates if the game is over and displaying the game over sequence.",
|
||||
"game.isPaused": "Indicates if the game rendering is paused to allow other animations",
|
||||
"game.isRunning": "Gets a value indicating if the game is still running. Returns `false` if game over.",
|
||||
"game.isRunning": "Indicates if the game is still running. Returns `false` if the game is over or paused.",
|
||||
"game.level": "Gets the current level",
|
||||
"game.levelUp": "Increments the level and display a message.",
|
||||
"game.life": "Gets the current life",
|
||||
"game.pause": "Pauses the game rendering engine to allow other animations",
|
||||
"game.removeLife": "Removes some life",
|
||||
"game.removeLife|param|life": "TODO",
|
||||
"game.removeLife": "Remove some life",
|
||||
"game.removeLife|param|life": "amount of life to remove",
|
||||
"game.resume": "Resumes the game rendering engine",
|
||||
"game.score": "Gets the current score",
|
||||
"game.setLife": "Sets the current life value",
|
||||
"game.setLife|param|value": "TODO",
|
||||
"game.setLife|param|value": "current life value",
|
||||
"game.setScore": "Sets the current score value",
|
||||
"game.setScore|param|value": "new score value.",
|
||||
"game.showScore": "Displays the score on the screen.",
|
||||
"game.startCountdown": "Shows an animation, then starts a game countdown timer, which causes Game Over when it reaches 0",
|
||||
"game.startCountdown|param|ms": "countdown duration in milliseconds, eg: 10000",
|
||||
"game.startStopwatch": "Starts a stopwatch timer. `current time` will return the elapsed time.",
|
||||
"hex": "Tagged hex literal converter",
|
||||
"images": "Creation, manipulation and display of LED images.",
|
||||
"images.createBigImage": "Creates an image with 2 frames.",
|
||||
"images.createImage": "Creates an image that fits on the LED screen.",
|
||||
"input": "Events and data from sensors",
|
||||
"input.acceleration": "Get the acceleration value in milli-gravitys (when the board is laying flat with the screen up, x=0, y=0 and z=-1024)",
|
||||
"input.acceleration|param|dimension": "TODO",
|
||||
"input.acceleration|param|dimension": "x, y, or z dimension, eg: Dimension.X",
|
||||
"input.buttonIsPressed": "Get the button state (pressed or not) for ``A`` and ``B``.",
|
||||
"input.buttonIsPressed|param|button": "the button to query the request, eg: Button.A",
|
||||
"input.calibrate": "Obsolete, use input.calibrateCompass instead.",
|
||||
"input.calibrateCompass": "Obsolete, compass calibration is automatic.",
|
||||
"input.compassHeading": "Get the current compass heading in degrees.",
|
||||
"input.isGesture": "Tests if a gesture is currently detected.",
|
||||
"input.isGesture|param|gesture": "the type of gesture to detect, eg: Gesture.Shake",
|
||||
"input.lightLevel": "Reads the light level applied to the LED screen in a range from ``0`` (dark) to ``255`` bright.",
|
||||
"input.magneticForce": "Get the magnetic force value in ``micro-Teslas`` (``µT``). This function is not supported in the simulator.",
|
||||
"input.magneticForce|param|dimension": "TODO",
|
||||
"input.magneticForce|param|dimension": "the x, y, or z dimension, eg: Dimension.X",
|
||||
"input.onButtonPressed": "Do something when a button (A, B or both A+B) is pushed down and released again.",
|
||||
"input.onButtonPressed|param|body": "code to run when event is raised",
|
||||
"input.onButtonPressed|param|button": "the button that needs to be pressed",
|
||||
@@ -314,7 +393,7 @@
|
||||
"input.pinIsPressed": "Get the pin state (pressed or not). Requires to hold the ground to close the circuit.",
|
||||
"input.pinIsPressed|param|name": "pin used to detect the touch, eg: TouchPin.P0",
|
||||
"input.rotation": "The pitch or roll of the device, rotation along the ``x-axis`` or ``y-axis``, in degrees.",
|
||||
"input.rotation|param|kind": "TODO",
|
||||
"input.rotation|param|kind": "pitch or roll",
|
||||
"input.runningTime": "Gets the number of milliseconds elapsed since power on.",
|
||||
"input.runningTimeMicros": "Gets the number of microseconds elapsed since power on.",
|
||||
"input.setAccelerometerRange": "Sets the accelerometer sample range in gravities.",
|
||||
@@ -325,9 +404,9 @@
|
||||
"led.displayMode": "Gets the current display mode",
|
||||
"led.enable": "Turns on or off the display",
|
||||
"led.fadeIn": "Fades in the screen display.",
|
||||
"led.fadeIn|param|ms": "TODO",
|
||||
"led.fadeIn|param|ms": "fade time in milleseconds",
|
||||
"led.fadeOut": "Fades out the screen brightness.",
|
||||
"led.fadeOut|param|ms": "TODO",
|
||||
"led.fadeOut|param|ms": "fade time in milliseconds",
|
||||
"led.plot": "Turn on the specified LED using x, y coordinates (x is horizontal, y is vertical). (0,0) is upper left.",
|
||||
"led.plotAll": "Turns all LEDS on",
|
||||
"led.plotBarGraph": "Displays a vertical bar graph based on the `value` and `high` value.\nIf `high` is 0, the chart gets adjusted automatically.",
|
||||
@@ -340,8 +419,8 @@
|
||||
"led.plot|param|x": "the horizontal coordinate of the LED starting at 0",
|
||||
"led.plot|param|y": "the vertical coordinate of the LED starting at 0",
|
||||
"led.point": "Get the on/off state of the specified LED using x, y coordinates. (0,0) is upper left.",
|
||||
"led.point|param|x": "TODO",
|
||||
"led.point|param|y": "TODO",
|
||||
"led.point|param|x": "the horizontal coordinate of the LED",
|
||||
"led.point|param|y": "the vertical coordinate of the LED",
|
||||
"led.screenshot": "Takes a screenshot of the LED screen and returns an image.",
|
||||
"led.setBrightness": "Set the screen brightness from 0 (off) to 255 (full bright).",
|
||||
"led.setBrightness|param|value": "the brightness value, eg:255, 127, 0",
|
||||
@@ -350,57 +429,65 @@
|
||||
"led.stopAnimation": "Cancels the current animation and clears other pending animations.",
|
||||
"led.toggle": "Toggles a particular pixel",
|
||||
"led.toggleAll": "Inverts the current LED display",
|
||||
"led.toggle|param|x": "TODO",
|
||||
"led.toggle|param|y": "TODO",
|
||||
"led.toggle|param|x": "pixel column",
|
||||
"led.toggle|param|y": "pixel row",
|
||||
"led.unplot": "Turn off the specified LED using x, y coordinates (x is horizontal, y is vertical). (0,0) is upper left.",
|
||||
"led.unplot|param|x": "TODO",
|
||||
"led.unplot|param|y": "TODO",
|
||||
"led.unplot|param|x": "the horizontal coordinate of the LED",
|
||||
"led.unplot|param|y": "the vertical coordinate of the LED",
|
||||
"motors": "Blocks to control the onboard motors",
|
||||
"motors.dualMotorPower": "Controls two motors attached to the board. Switches to dual-motor mode!",
|
||||
"motors.motorCommand": "Send break, coast or sleep commands to the motor. Has no effect in dual-motor mode.",
|
||||
"motors.motorPower": "Turns on the motor at a certain percent of power. Switches to single motor mode!",
|
||||
"motors.motorPower|param|power": "%percent of power sent to the motor. Negative power goes backward. eg: 50",
|
||||
"msgpack.packNumberArray": "Pack a number array into a buffer.",
|
||||
"msgpack.packNumberArray|param|nums": "the numbers to be packed",
|
||||
"msgpack.unpackNumberArray": "Unpacks a buffer into a number array.",
|
||||
"music": "Generation of music tones.",
|
||||
"music.beat": "Returns the duration of a beat in milli-seconds",
|
||||
"music.beginMelody": "Starts playing a melody.\nNotes are expressed as a string of characters with this format: NOTE[octave][:duration]",
|
||||
"music.beginMelody|param|melodyArray": "the melody array to play, eg: ['g5:1']",
|
||||
"music.beginMelody|param|melodyArray": "the melody array to play",
|
||||
"music.beginMelody|param|options": "melody options, once / forever, in the foreground / background",
|
||||
"music.builtInMelody": "Gets the melody array of a built-in melody.",
|
||||
"music.changeTempoBy": "Change the tempo by the specified amount",
|
||||
"music.changeTempoBy|param|bpm": "The change in beats per minute to the tempo, eg: 20",
|
||||
"music.noteFrequency": "Gets the frequency of a note.",
|
||||
"music.noteFrequency": "Get the frequency of a note.",
|
||||
"music.noteFrequency|param|name": "the note name, eg: Note.C",
|
||||
"music.onEvent": "Registers code to run on various melody events",
|
||||
"music.playTone": "Plays a tone through pin ``P0`` for the given duration.",
|
||||
"music.playTone|param|frequency": "pitch of the tone to play in Hertz (Hz)",
|
||||
"music.playTone|param|frequency": "pitch of the tone to play in Hertz (Hz), eg: Note.C",
|
||||
"music.playTone|param|ms": "tone duration in milliseconds (ms)",
|
||||
"music.rest": "Rests (plays nothing) for a specified time through pin ``P0``.",
|
||||
"music.rest|param|ms": "rest duration in milliseconds (ms)",
|
||||
"music.ringTone": "Plays a tone through pin ``P0``.",
|
||||
"music.ringTone|param|frequency": "pitch of the tone to play in Hertz (Hz)",
|
||||
"music.ringTone|param|frequency": "pitch of the tone to play in Hertz (Hz), eg: Note.C",
|
||||
"music.setPlayTone": "Sets a custom playTone function for playing melodies",
|
||||
"music.setTempo": "Sets the tempo to the specified amount",
|
||||
"music.setTempo|param|bpm": "The new tempo in beats per minute, eg: 120",
|
||||
"music.speakerPlayTone": "Plays a tone through ``speaker`` for the given duration.",
|
||||
"music.speakerPlayTone|param|frequency": "pitch of the tone to play in Hertz (Hz)",
|
||||
"music.speakerPlayTone|param|ms": "tone duration in milliseconds (ms)",
|
||||
"music.stopMelody": "Stops the melodies",
|
||||
"music.stopMelody|param|options": "which melody to stop",
|
||||
"music.tempo": "Returns the tempo in beats per minute. Tempo is the speed (bpm = beats per minute) at which notes play. The larger the tempo value, the faster the notes will play.",
|
||||
"parseFloat": "Convert a string to a number.",
|
||||
"parseInt": "Convert a string to an integer.",
|
||||
"pins": "Control currents in Pins for analog/digital signals, servos, i2c, ...",
|
||||
"pins.analogPitch": "Emits a Pulse-width modulation (PWM) signal to the current pitch pin. Use `analog set pitch pin` to define the pitch pin.",
|
||||
"pins.analogPitch": "Emit a plse-width modulation (PWM) signal to the current pitch pin. Use `analog set pitch pin` to define the pitch pin.",
|
||||
"pins.analogPitch|param|frequency": "frequency to modulate in Hz.",
|
||||
"pins.analogPitch|param|ms": "duration of the pitch in milli seconds.",
|
||||
"pins.analogReadPin": "Read the connector value as analog, that is, as a value comprised between 0 and 1023.",
|
||||
"pins.analogReadPin|param|name": "pin to write to, eg: AnalogPin.P0",
|
||||
"pins.analogSetPeriod": "Configures the Pulse-width modulation (PWM) of the analog output to the given value in **microseconds** or `1/1000` milliseconds.\nIf this pin is not configured as an analog output (using `analog write pin`), the operation has no effect.",
|
||||
"pins.analogSetPeriod": "Configure the pulse-width modulation (PWM) period of the analog output in microseconds.\nIf this pin is not configured as an analog output (using `analog write pin`), the operation has no effect.",
|
||||
"pins.analogSetPeriod|param|micros": "period in micro seconds. eg:20000",
|
||||
"pins.analogSetPeriod|param|name": "analog pin to set period to, eg: AnalogPin.P0",
|
||||
"pins.analogSetPitchPin": "Sets the pin used when using `analog pitch` or music.",
|
||||
"pins.analogSetPitchPin": "Set the pin used when using analog pitch or music.",
|
||||
"pins.analogSetPitchPin|param|name": "pin to modulate pitch from",
|
||||
"pins.analogWritePin": "Set the connector value as analog. Value must be comprised between 0 and 1023.",
|
||||
"pins.analogWritePin|param|name": "pin name to write to, eg: AnalogPin.P0",
|
||||
"pins.analogWritePin|param|value": "value to write to the pin between ``0`` and ``1023``. eg:1023,0",
|
||||
"pins.createBuffer": "Create a new zero-initialized buffer.",
|
||||
"pins.createBufferFromArray": "Create a new buffer initalized to bytes from given array.",
|
||||
"pins.createBufferFromArray|param|bytes": "data to initalize with",
|
||||
"pins.createBuffer|param|size": "number of bytes in the buffer",
|
||||
"pins.digitalReadPin": "Read the specified pin or connector as either 0 or 1",
|
||||
"pins.digitalReadPin|param|name": "pin to read from, eg: DigitalPin.P0",
|
||||
@@ -411,56 +498,68 @@
|
||||
"pins.i2cReadNumber": "Read one number from 7-bit I2C address.",
|
||||
"pins.i2cWriteBuffer": "Write bytes to a 7-bit I2C `address`.",
|
||||
"pins.i2cWriteNumber": "Write one number to a 7-bit I2C address.",
|
||||
"pins.map": "Re-maps a number from one range to another. That is, a value of ``from low`` would get mapped to ``to low``, a value of ``from high`` to ``to high``, values in-between to values in-between, etc.",
|
||||
"pins.map": "Map a number from one range to another. That is, a value of ``from low`` would get mapped to ``to low``, a value of ``from high`` to ``to high``, values in-between to values in-between, etc.",
|
||||
"pins.map|param|fromHigh": "the upper bound of the value's current range, eg: 1023",
|
||||
"pins.map|param|fromLow": "the lower bound of the value's current range",
|
||||
"pins.map|param|toHigh": "the upper bound of the value's target range, eg: 4",
|
||||
"pins.map|param|toLow": "the lower bound of the value's target range",
|
||||
"pins.map|param|value": "value to map in ranges",
|
||||
"pins.onPulsed": "Configures this pin to a digital input, and generates events where the timestamp is the duration that this pin was either ``high`` or ``low``.",
|
||||
"pins.onPulsed": "Configure the pin as a digital input and generate an event when the pin is pulsed either high or low.",
|
||||
"pins.onPulsed|param|name": "digital pin to register to, eg: DigitalPin.P0",
|
||||
"pins.onPulsed|param|pulse": "the value of the pulse, eg: PulseValue.High",
|
||||
"pins.pulseDuration": "Gets the duration of the last pulse in micro-seconds. This function should be called from a ``onPulsed`` handler.",
|
||||
"pins.pulseIn": "Returns the duration of a pulse in microseconds",
|
||||
"pins.pulseDuration": "Get the duration of the last pulse in microseconds. This function should be called from a ``onPulsed`` handler.",
|
||||
"pins.pulseIn": "Return the duration of a pulse at a pin in microseconds.",
|
||||
"pins.pulseIn|param|name": "the pin which measures the pulse, eg: DigitalPin.P0",
|
||||
"pins.pulseIn|param|value": "the value of the pulse, eg: PulseValue.High",
|
||||
"pins.servoSetPulse": "Configures this IO pin as an analog/pwm output, configures the period to be 20 ms, and sets the pulse width, based on the value it is given **microseconds** or `1/1000` milliseconds.",
|
||||
"pins.servoSetPulse": "Configure the IO pin as an analog/pwm output and set a pulse width. The period is 20 ms period and the pulse width is set based on the value given in **microseconds** or `1/1000` milliseconds.",
|
||||
"pins.servoSetPulse|param|micros": "pulse duration in micro seconds, eg:1500",
|
||||
"pins.servoSetPulse|param|name": "pin name",
|
||||
"pins.servoWritePin": "Writes a value to the servo, controlling the shaft accordingly. On a standard servo, this will set the angle of the shaft (in degrees), moving the shaft to that orientation. On a continuous rotation servo, this will set the speed of the servo (with ``0`` being full-speed in one direction, ``180`` being full speed in the other, and a value near ``90`` being no movement).",
|
||||
"pins.servoWritePin": "Write a value to the servo, controlling the shaft accordingly. On a standard servo, this will set the angle of the shaft (in degrees), moving the shaft to that orientation. On a continuous rotation servo, this will set the speed of the servo (with ``0`` being full-speed in one direction, ``180`` being full speed in the other, and a value near ``90`` being no movement).",
|
||||
"pins.servoWritePin|param|name": "pin to write to, eg: AnalogPin.P0",
|
||||
"pins.servoWritePin|param|value": "angle or rotation speed, eg:180,90,0",
|
||||
"pins.setEvents": "Configures the events emitted by this pin. Events can be subscribed to\nusing ``control.onEvent()``.",
|
||||
"pins.setEvents": "Configure the events emitted by this pin. Events can be subscribed to\nusing ``control.onEvent()``.",
|
||||
"pins.setEvents|param|name": "pin to set the event mode on, eg: DigitalPin.P0",
|
||||
"pins.setEvents|param|type": "the type of events for this pin to emit, eg: PinEventType.Edge",
|
||||
"pins.setPull": "Configures the pull of this pin.",
|
||||
"pins.setPull": "Configure the pull directiion of of a pin.",
|
||||
"pins.setPull|param|name": "pin to set the pull mode on, eg: DigitalPin.P0",
|
||||
"pins.setPull|param|pull": "one of the mbed pull configurations, eg: PinPullMode.PullUp",
|
||||
"pins.sizeOf": "Get the size in bytes of specified number format.",
|
||||
"pins.spiFormat": "Sets the SPI bits and mode",
|
||||
"pins.spiFormat": "Set the SPI bits and mode",
|
||||
"pins.spiFormat|param|bits": "the number of bits, eg: 8",
|
||||
"pins.spiFormat|param|mode": "the mode, eg: 3",
|
||||
"pins.spiFrequency": "Sets the SPI frequency",
|
||||
"pins.spiFrequency": "Set the SPI frequency",
|
||||
"pins.spiFrequency|param|frequency": "the clock frequency, eg: 1000000",
|
||||
"pins.spiPins": "Sets the MOSI, MISO, SCK pins used by the SPI instance",
|
||||
"pins.spiPins": "Set the MOSI, MISO, SCK pins used by the SPI connection",
|
||||
"pins.spiWrite": "Write to the SPI slave and return the response",
|
||||
"pins.spiWrite|param|value": "Data to be sent to the SPI slave",
|
||||
"serial": "Reading and writing data over a serial connection.",
|
||||
"serial.delimiters": "Returns the delimiter corresponding string",
|
||||
"serial.onDataReceived": "Registers an event to be fired when one of the delimiter is matched.",
|
||||
"serial.NEW_LINE": "The string used to mark a new line, default is \\r\\n",
|
||||
"serial.delimiters": "Return the corresponding delimiter string",
|
||||
"serial.onDataReceived": "Register an event to be fired when one of the delimiter is matched.",
|
||||
"serial.onDataReceived|param|delimiters": "the characters to match received characters against.",
|
||||
"serial.readLine": "Reads a line of text from the serial port.",
|
||||
"serial.readString": "Reads the buffered received data as a string",
|
||||
"serial.readUntil": "Reads a line of text from the serial port and returns the buffer when the delimiter is met.",
|
||||
"serial.readBuffer": "Read multiple characters from the receive buffer. Pause until enough characters are present.",
|
||||
"serial.readBuffer|param|length": "default buffer length, eg: 64",
|
||||
"serial.readLine": "Read a line of text from the serial port.",
|
||||
"serial.readString": "Read the buffered received data as a string",
|
||||
"serial.readUntil": "Read a line of text from the serial port and return the buffer when the delimiter is met.",
|
||||
"serial.readUntil|param|delimiter": "text delimiter that separates each text chunk",
|
||||
"serial.redirect": "Dynamically configuring the serial instance to use pins other than USBTX and USBRX.",
|
||||
"serial.redirect": "Set the serial input and output to use pins instead of the USB connection.",
|
||||
"serial.redirectToUSB": "Direct the serial input and output to use the USB connection.",
|
||||
"serial.redirect|param|rate": "the new baud rate. eg: 115200",
|
||||
"serial.redirect|param|rx": "the new reception pin, eg: SerialPin.P1",
|
||||
"serial.redirect|param|tx": "the new transmission pins, eg: SerialPin.P0",
|
||||
"serial.writeLine": "Prints a line of text to the serial",
|
||||
"serial.writeNumber": "Prints a numeric value to the serial",
|
||||
"serial.writeString": "Sends a piece of text through Serial connection.",
|
||||
"serial.writeValue": "Writes a ``name: value`` pair line to the serial.",
|
||||
"serial.redirect|param|tx": "the new transmission pin, eg: SerialPin.P0",
|
||||
"serial.setRxBufferSize": "Sets the size of the RX buffer in bytes",
|
||||
"serial.setRxBufferSize|param|size": "length of the rx buffer in bytes, eg: 32",
|
||||
"serial.setTxBufferSize": "Sets the size of the TX buffer in bytes",
|
||||
"serial.setTxBufferSize|param|size": "length of the tx buffer in bytes, eg: 32",
|
||||
"serial.setWriteLinePadding": "Sets the padding length for lines sent with \"write line\".",
|
||||
"serial.setWriteLinePadding|param|length": "the number of bytes alignment, eg: 0",
|
||||
"serial.writeBuffer": "Send a buffer through serial connection",
|
||||
"serial.writeLine": "Print a line of text to the serial port",
|
||||
"serial.writeNumber": "Print a numeric value to the serial port",
|
||||
"serial.writeNumbers": "Print an array of numeric values as CSV to the serial port",
|
||||
"serial.writeString": "Send a piece of text through the serial connection.",
|
||||
"serial.writeValue": "Write a name:value pair as a line to the serial port.",
|
||||
"serial.writeValue|param|name": "name of the value stream, eg: x",
|
||||
"serial.writeValue|param|value": "to write"
|
||||
}
|
||||
@@ -26,7 +26,15 @@
|
||||
"ArrowNames.South|block": "South",
|
||||
"ArrowNames.West|block": "West",
|
||||
"BaudRate.BaudRate115200|block": "115200",
|
||||
"BaudRate.BaudRate56700|block": "57600",
|
||||
"BaudRate.BaudRate1200|block": "1200",
|
||||
"BaudRate.BaudRate14400|block": "14400",
|
||||
"BaudRate.BaudRate19200|block": "19200",
|
||||
"BaudRate.BaudRate2400|block": "2400",
|
||||
"BaudRate.BaudRate28800|block": "28800",
|
||||
"BaudRate.BaudRate31250|block": "31250",
|
||||
"BaudRate.BaudRate38400|block": "38400",
|
||||
"BaudRate.BaudRate4800|block": "4800",
|
||||
"BaudRate.BaudRate57600|block": "57600",
|
||||
"BaudRate.BaudRate9600|block": "9600",
|
||||
"BeatFraction.Breve|block": "4",
|
||||
"BeatFraction.Double|block": "2",
|
||||
@@ -39,6 +47,7 @@
|
||||
"Colors.Blue|block": "blue",
|
||||
"Colors.Green|block": "green",
|
||||
"Colors.Indigo|block": "indigo",
|
||||
"Colors.Off|block": "off",
|
||||
"Colors.Orange|block": "orange",
|
||||
"Colors.Purple|block": "purple",
|
||||
"Colors.Red|block": "red",
|
||||
@@ -57,7 +66,7 @@
|
||||
"Dimension.Z|block": "z",
|
||||
"Direction.Left|block": "left",
|
||||
"Direction.Right|block": "right",
|
||||
"DisplayMode.BackAndWhite|block": "black and white",
|
||||
"DisplayMode.BlackAndWhite|block": "black and white",
|
||||
"DisplayMode.Greyscale|block": "greyscale",
|
||||
"EventCreationMode.CreateAndFire": "MicroBitEvent is initialised, and its event handlers are immediately fired (not suitable for use in interrupts!).",
|
||||
"EventCreationMode.CreateOnly": "MicroBitEvent is initialised, and no further processing takes place.",
|
||||
@@ -123,15 +132,17 @@
|
||||
"IconNames.Triangle|block": "triangle",
|
||||
"IconNames.Umbrella|block": "umbrella",
|
||||
"IconNames.Yes|block": "yes",
|
||||
"Image.scrollImage|block": "scroll image %sprite|with offset %frameoffset|and interval (ms) %delay",
|
||||
"Image.showImage|block": "show image %sprite|at offset %offset",
|
||||
"Image.scrollImage|block": "scroll image %sprite(myImage)|with offset %frameoffset|and interval (ms) %delay",
|
||||
"Image.showImage|block": "show image %sprite(myImage)|at offset %offset",
|
||||
"LedSpriteProperty.Blink|block": "blink",
|
||||
"LedSpriteProperty.Brightness|block": "brightness",
|
||||
"LedSpriteProperty.Direction|block": "direction",
|
||||
"LedSpriteProperty.X|block": "x",
|
||||
"LedSpriteProperty.Y|block": "y",
|
||||
"Math.constrain|block": "constrain %value|between %low|and %high",
|
||||
"Math.map|block": "map %value|from low %fromLow|high %fromHigh|to low %toLow|high %toHigh",
|
||||
"Math.randomBoolean|block": "pick random true or false",
|
||||
"Math.random|block": "pick random 0 to %limit",
|
||||
"Math.randomRange|block": "pick random %min|to %limit",
|
||||
"Math|block": "Math",
|
||||
"Melodies.BaDing|block": "ba ding",
|
||||
"Melodies.Baddy|block": "baddy",
|
||||
@@ -157,6 +168,9 @@
|
||||
"MelodyOptions.Forever|block": "forever",
|
||||
"MelodyOptions.OnceInBackground|block": "once in background",
|
||||
"MelodyOptions.Once|block": "once",
|
||||
"MelodyStopOptions.All|block": "all",
|
||||
"MelodyStopOptions.Background|block": "background",
|
||||
"MelodyStopOptions.Foreground|block": "foreground",
|
||||
"MesDpadButtonInfo.ADown|block": "A down",
|
||||
"MesDpadButtonInfo.AUp|block": "A up",
|
||||
"MesDpadButtonInfo.BDown|block": "B down",
|
||||
@@ -199,6 +213,8 @@
|
||||
"Note.GSharp4|block": "G#4",
|
||||
"Note.GSharp5|block": "G#5",
|
||||
"Note.GSharp|block": "G#",
|
||||
"Number|block": "Number",
|
||||
"Object|block": "Object",
|
||||
"PinEventType.Edge|block": "edge",
|
||||
"PinEventType.None|block": "none",
|
||||
"PinEventType.Pulse|block": "pulse",
|
||||
@@ -206,12 +222,18 @@
|
||||
"PinPullMode.PullDown|block": "down",
|
||||
"PinPullMode.PullNone|block": "none",
|
||||
"PinPullMode.PullUp|block": "up",
|
||||
"PulseValue.High|block": "high",
|
||||
"PulseValue.Low|block": "low",
|
||||
"Rotation.Pitch|block": "pitch",
|
||||
"Rotation.Roll|block": "roll",
|
||||
"String.charAt|block": "char from %this=text|at %pos",
|
||||
"String.compare|block": "compare %this=text| to %that",
|
||||
"String.fromCharCode|block": "text from char code %code",
|
||||
"String.includes|block": "%this=text|includes %searchValue",
|
||||
"String.indexOf|block": "%this=text|find index of %searchValue",
|
||||
"String.isEmpty|block": "%this=text| is empty",
|
||||
"String.length|block": "length of %VALUE",
|
||||
"String.split|block": "split %this=text|at %separator",
|
||||
"String.substr|block": "substring of %this=text|from %start|of length %length",
|
||||
"String|block": "String",
|
||||
"basic.clearScreen|block": "clear screen",
|
||||
@@ -219,13 +241,15 @@
|
||||
"basic.forever|block": "forever",
|
||||
"basic.pause|block": "pause (ms) %pause",
|
||||
"basic.rgbw|block": "red %red|green %green|blue %blue|white %white",
|
||||
"basic.setLedColor|block": "set led to %color=color_id",
|
||||
"basic.setLedColor|block": "set led to %color=colorNumberPicker",
|
||||
"basic.showArrow|block": "show arrow %i=device_arrow",
|
||||
"basic.showIcon|block": "show icon %i",
|
||||
"basic.showLeds|block": "show leds",
|
||||
"basic.showNumber|block": "show|number %number",
|
||||
"basic.showString|block": "show|string %text",
|
||||
"basic.turnRgbLedOff|block": "turn build-in LED off",
|
||||
"basic|block": "basic",
|
||||
"console|block": "console",
|
||||
"control.deviceName|block": "device name",
|
||||
"control.deviceSerialNumber|block": "device serial number",
|
||||
"control.eventSourceId|block": "%id",
|
||||
@@ -238,21 +262,29 @@
|
||||
"control.reset|block": "reset",
|
||||
"control.waitMicros|block": "wait (µs)%micros",
|
||||
"control|block": "control",
|
||||
"convertToText|block": "convert $value=math_number to text",
|
||||
"game.LedSprite.change|block": "%sprite|change %property|by %value",
|
||||
"game.LedSprite.delete|block": "delete %this",
|
||||
"game.LedSprite.delete|block": "delete %this(sprite)",
|
||||
"game.LedSprite.get|block": "%sprite|%property",
|
||||
"game.LedSprite.ifOnEdgeBounce|block": "%sprite|if on edge, bounce",
|
||||
"game.LedSprite.isTouchingEdge|block": "%sprite|touching edge?",
|
||||
"game.LedSprite.isTouching|block": "%sprite|touching %other|?",
|
||||
"game.LedSprite.isDeleted|block": "is %sprite|deleted",
|
||||
"game.LedSprite.isTouchingEdge|block": "is %sprite|touching edge",
|
||||
"game.LedSprite.isTouching|block": "is %sprite|touching %other",
|
||||
"game.LedSprite.move|block": "%sprite|move by %leds",
|
||||
"game.LedSprite.set|block": "%sprite|set %property|to %value",
|
||||
"game.LedSprite.turn|block": "%sprite|turn %direction|by (°) %degrees",
|
||||
"game.addLife|block": "add life %lives",
|
||||
"game.addScore|block": "change score by|%points",
|
||||
"game.createSprite|block": "create sprite at|x: %x|y: %y",
|
||||
"game.gameOver|block": "game over",
|
||||
"game.isGameOver|block": "is game over",
|
||||
"game.isPaused|block": "is paused",
|
||||
"game.isRunning|block": "is running",
|
||||
"game.pause|block": "pause",
|
||||
"game.removeLife|block": "remove life %life",
|
||||
"game.resume|block": "resume",
|
||||
"game.score|block": "score",
|
||||
"game.setLife|block": "set life %value",
|
||||
"game.setScore|block": "set score %points",
|
||||
"game.startCountdown|block": "start countdown|(ms) %duration",
|
||||
"game|block": "game",
|
||||
@@ -266,6 +298,7 @@
|
||||
"input.buttonIsPressed|block": "button|%NAME|is pressed",
|
||||
"input.calibrateCompass|block": "calibrate compass",
|
||||
"input.compassHeading|block": "compass heading (°)",
|
||||
"input.isGesture|block": "is %gesture gesture",
|
||||
"input.lightLevel|block": "light level",
|
||||
"input.magneticForce|block": "magnetic force (µT)|%NAME",
|
||||
"input.onButtonPressed|block": "on button|%NAME|pressed",
|
||||
@@ -281,11 +314,12 @@
|
||||
"input|block": "input",
|
||||
"led.brightness|block": "brightness",
|
||||
"led.enable|block": "led enable %on",
|
||||
"led.plotBarGraph|block": "plot bar graph of %value |up to %high",
|
||||
"led.plotBarGraph|block": "plot bar graph of %value up to %high",
|
||||
"led.plotBrightness|block": "plot|x %x|y %y|brightness %brightness",
|
||||
"led.plot|block": "plot|x %x|y %y",
|
||||
"led.point|block": "point|x %x|y %y",
|
||||
"led.setBrightness|block": "set brightness %value",
|
||||
"led.setDisplayMode|block": "set display mode $mode",
|
||||
"led.stopAnimation|block": "stop animation",
|
||||
"led.toggle|block": "toggle|x %x|y %y",
|
||||
"led.unplot|block": "unplot|x %x|y %y",
|
||||
@@ -294,18 +328,21 @@
|
||||
"motors.motorCommand|block": "motor %command",
|
||||
"motors.motorPower|block": "motor on at %percent",
|
||||
"motors|block": "motors",
|
||||
"msgpack|block": "msgpack",
|
||||
"music.beat|block": "%fraction|beat",
|
||||
"music.beginMelody|block": "start melody %melody=device_builtin_melody| repeating %options",
|
||||
"music.builtInMelody|block": "%melody",
|
||||
"music.changeTempoBy|block": "change tempo by (bpm)|%value",
|
||||
"music.noteFrequency|block": "%note",
|
||||
"music.noteFrequency|block": "%name",
|
||||
"music.onEvent|block": "music on %value",
|
||||
"music.playTone|block": "play|tone %note=device_note|for %duration=device_beat",
|
||||
"music.rest|block": "rest(ms)|%duration=device_beat",
|
||||
"music.ringTone|block": "ring tone (Hz)|%note=device_note",
|
||||
"music.setTempo|block": "set tempo to (bpm)|%value",
|
||||
"music.stopMelody|block": "stop melody $options",
|
||||
"music.tempo|block": "tempo (bpm)",
|
||||
"music|block": "music",
|
||||
"parseFloat|block": "parse to number %text",
|
||||
"parseInt|block": "parse to integer %text",
|
||||
"pins.analogPitch|block": "analog pitch %frequency|for (ms) %ms",
|
||||
"pins.analogReadPin|block": "analog read|pin %name",
|
||||
@@ -314,8 +351,8 @@
|
||||
"pins.analogWritePin|block": "analog write|pin %name|to %value",
|
||||
"pins.digitalReadPin|block": "digital read|pin %name",
|
||||
"pins.digitalWritePin|block": "digital write|pin %name|to %value",
|
||||
"pins.i2cReadNumber|block": "i2c read number|at address %address|of format %format=i2c_sizeof|repeat %repeat",
|
||||
"pins.i2cWriteNumber|block": "i2c write number|at address %address|with value %value|of format %format=i2c_sizeof|repeat %repeat",
|
||||
"pins.i2cReadNumber|block": "i2c read number|at address %address|of format %format|repeated %repeat",
|
||||
"pins.i2cWriteNumber|block": "i2c write number|at address %address|with value %value|of format %format|repeated %repeat",
|
||||
"pins.map|block": "map %value|from low %fromLow|from high %fromHigh|to low %toLow|to high %toHigh",
|
||||
"pins.onPulsed|block": "on|pin %pin|pulsed %pulse",
|
||||
"pins.pulseDuration|block": "pulse duration (µs)",
|
||||
@@ -331,11 +368,18 @@
|
||||
"pins|block": "pins",
|
||||
"serial.delimiters|block": "%del",
|
||||
"serial.onDataReceived|block": "serial|on data received %delimiters=serial_delimiter_conv",
|
||||
"serial.readBuffer|block": "serial|read buffer %length",
|
||||
"serial.readLine|block": "serial|read line",
|
||||
"serial.readString|block": "serial|read string",
|
||||
"serial.readUntil|block": "serial|read until %delimiter=serial_delimiter_conv",
|
||||
"serial.redirectToUSB|block": "serial|redirect to USB",
|
||||
"serial.redirect|block": "serial|redirect to|TX %tx|RX %rx|at baud rate %rate",
|
||||
"serial.setRxBufferSize|block": "serial set rx buffer size to $size",
|
||||
"serial.setTxBufferSize|block": "serial set tx buffer size to $size",
|
||||
"serial.setWriteLinePadding|block": "serial set write line padding to $length",
|
||||
"serial.writeBuffer|block": "serial|write buffer %buffer=serial_readbuffer",
|
||||
"serial.writeLine|block": "serial|write line %text",
|
||||
"serial.writeNumbers|block": "serial|write numbers %values",
|
||||
"serial.writeNumber|block": "serial|write number %value",
|
||||
"serial.writeString|block": "serial|write string %text",
|
||||
"serial.writeValue|block": "serial|write value %name|= %value",
|
||||
@@ -347,6 +391,8 @@
|
||||
"{id:category}Buffer": "Buffer",
|
||||
"{id:category}Console": "Console",
|
||||
"{id:category}Control": "Control",
|
||||
"{id:category}Fx": "Fx",
|
||||
"{id:category}Fx8": "Fx8",
|
||||
"{id:category}Game": "Game",
|
||||
"{id:category}Helpers": "Helpers",
|
||||
"{id:category}Image": "Image",
|
||||
@@ -355,8 +401,10 @@
|
||||
"{id:category}Led": "Led",
|
||||
"{id:category}Math": "Math",
|
||||
"{id:category}Motors": "Motors",
|
||||
"{id:category}Msgpack": "Msgpack",
|
||||
"{id:category}Music": "Music",
|
||||
"{id:category}Number": "Number",
|
||||
"{id:category}Object": "Object",
|
||||
"{id:category}Pins": "Pins",
|
||||
"{id:category}Serial": "Serial",
|
||||
"{id:category}String": "String",
|
||||
|
||||
@@ -4,12 +4,13 @@
|
||||
/**
|
||||
* Provides access to basic micro:bit functionality.
|
||||
*/
|
||||
//% color=#54C9C9 weight=100 icon="\uf00a"
|
||||
//% color=#1E90FF weight=116 icon="\uf00a"
|
||||
namespace basic {
|
||||
/**
|
||||
* Sets the color on the build-in LED. Set to 0 to turn off.
|
||||
*/
|
||||
//% blockId=device_set_led_color block="set led to %color=color_id"
|
||||
//% blockId=device_set_led_color
|
||||
//% block="set led to %color=colorNumberPicker"
|
||||
//% weight=50
|
||||
void setLedColor(int color) {
|
||||
if (!color) {
|
||||
@@ -25,24 +26,14 @@ namespace basic {
|
||||
uBit.rgb.setColour(r,g,b,w);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Scroll a number on the screen. If the number fits on the screen (i.e. is a single digit), do not scroll.
|
||||
* @param interval speed of scroll; eg: 150, 100, 200, -100
|
||||
*/
|
||||
//% help=basic/show-number
|
||||
//% weight=96
|
||||
//% blockId=device_show_number block="show|number %number" blockGap=8
|
||||
//% async
|
||||
//% parts="ledmatrix"
|
||||
void showNumber(int value, int interval = 150) {
|
||||
if (interval <= 0)
|
||||
interval = 1;
|
||||
ManagedString t(value);
|
||||
if (value < 0 || value >= 10) {
|
||||
uBit.display.scroll(t, interval);
|
||||
} else {
|
||||
uBit.display.printChar(t.charAt(0), interval * 5);
|
||||
}
|
||||
* Sets the color on the build-in LED. Set to 0 to turn off.
|
||||
*/
|
||||
//% blockId=device_turn_rgb_led_off block="turn build-in LED off"
|
||||
//% weight=50
|
||||
void turnRgbLedOff() {
|
||||
uBit.rgb.off();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -56,33 +47,33 @@ namespace basic {
|
||||
//% blockId=device_show_leds
|
||||
//% block="show leds" icon="\uf00a"
|
||||
//% parts="ledmatrix"
|
||||
void showLeds(ImageLiteral leds, int interval = 400) {
|
||||
void showLeds(ImageLiteral_ leds, int interval = 400) {
|
||||
uBit.display.print(MicroBitImage(imageBytes(leds)), 0, 0, 0, interval);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display text on the display, one character at a time. If the string fits on the screen (i.e. is one letter), does not scroll.
|
||||
* @param text the text to scroll on the screen, eg: "Hello!"
|
||||
* @param text the text to scroll on the screen, eg: "hi!"
|
||||
* @param interval how fast to shift characters; eg: 150, 100, 200, -100
|
||||
*/
|
||||
//% help=basic/show-string
|
||||
//% weight=87 blockGap=8
|
||||
//% weight=87 blockGap=16
|
||||
//% block="show|string %text"
|
||||
//% async
|
||||
//% blockId=device_print_message
|
||||
//% parts="ledmatrix"
|
||||
void showString(StringData *text, int interval = 150) {
|
||||
//% text.shadowOptions.toString=true
|
||||
void showString(String text, int interval = 150) {
|
||||
if (interval <= 0)
|
||||
interval = 1;
|
||||
ManagedString s(text);
|
||||
int l = s.length();
|
||||
int l = text ? text->getUTF8Size() : 0;
|
||||
if (l == 0) {
|
||||
uBit.display.clear();
|
||||
fiber_sleep(interval * 5);
|
||||
} else if (l > 1) {
|
||||
uBit.display.scroll(s, interval);
|
||||
uBit.display.scroll(MSTR(text), interval);
|
||||
} else {
|
||||
uBit.display.print(s.charAt(0), interval * 5);
|
||||
uBit.display.printChar(text->getUTF8Data()[0], interval * 5);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,7 +95,7 @@ namespace basic {
|
||||
*/
|
||||
//% help=basic/show-animation imageLiteral=1 async
|
||||
//% parts="ledmatrix"
|
||||
void showAnimation(ImageLiteral leds, int interval = 400) {
|
||||
void showAnimation(ImageLiteral_ leds, int interval = 400) {
|
||||
uBit.display.animate(MicroBitImage(imageBytes(leds)), interval, 5, 0, 0);
|
||||
}
|
||||
|
||||
@@ -114,29 +105,19 @@ namespace basic {
|
||||
*/
|
||||
//% help=basic/plot-leds weight=80
|
||||
//% parts="ledmatrix"
|
||||
void plotLeds(ImageLiteral leds) {
|
||||
void plotLeds(ImageLiteral_ leds) {
|
||||
MicroBitImage i(imageBytes(leds));
|
||||
uBit.display.print(i, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
void forever_stub(void *a) {
|
||||
while (true) {
|
||||
runAction0((Action)a);
|
||||
fiber_sleep(20);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Repeats the code forever in the background. On each iteration, allows other codes to run.
|
||||
* @param body code to execute
|
||||
*/
|
||||
//% help=basic/forever weight=55 blockGap=8 blockAllowMultiple=1 afterOnStart=true
|
||||
//% help=basic/forever weight=55 blockGap=16 blockAllowMultiple=1 afterOnStart=true
|
||||
//% blockId=device_forever block="forever" icon="\uf01e"
|
||||
void forever(Action a) {
|
||||
if (a != 0) {
|
||||
incr(a);
|
||||
create_fiber(forever_stub, (void*)a);
|
||||
}
|
||||
runForever(a);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -144,8 +125,9 @@ namespace basic {
|
||||
* @param ms how long to pause for, eg: 100, 200, 500, 1000, 2000
|
||||
*/
|
||||
//% help=basic/pause weight=54
|
||||
//% async block="pause (ms) %pause"
|
||||
//% async block="pause (ms) %pause" blockGap=16
|
||||
//% blockId=device_pause icon="\uf110"
|
||||
//% pause.shadow=timePicker
|
||||
void pause(int ms) {
|
||||
fiber_sleep(ms);
|
||||
}
|
||||
|
||||
@@ -28,7 +28,10 @@ enum Colors {
|
||||
Purple = 0x00FF00FF,
|
||||
//% blockIdentity=basic.color
|
||||
//% block=white
|
||||
White = 0xFF00000
|
||||
White = 0xFFFFFFFF,
|
||||
//% blockIdentity=basic.color
|
||||
//% block=off
|
||||
Off = 0x00000000,
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -36,6 +39,7 @@ enum Colors {
|
||||
*/
|
||||
//% color=#54C9C9 weight=100
|
||||
namespace basic {
|
||||
|
||||
/**
|
||||
* Converts the color name to a number
|
||||
*/
|
||||
@@ -56,4 +60,17 @@ namespace basic {
|
||||
export function rgbw(red: number, green: number, blue: number, white:number): number {
|
||||
return ((white & 0xFF) << 24) | ((red & 0xFF) << 16) | ((green & 0xFF) << 8) | (blue & 0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scroll a number on the screen. If the number fits on the screen (i.e. is a single digit), do not scroll.
|
||||
* @param interval speed of scroll; eg: 150, 100, 200, -100
|
||||
*/
|
||||
//% help=basic/show-number
|
||||
//% weight=96
|
||||
//% blockId=device_show_number block="show|number %number" blockGap=8
|
||||
//% async
|
||||
//% parts="ledmatrix" interval.defl=150
|
||||
export function showNumber(value: number, interval?: number) {
|
||||
showString(Math.roundWithPrecision(value, 2).toString(), interval);
|
||||
}
|
||||
}
|
||||
|
||||
53
libs/core/blocks-test/basic.blocks
Normal file
@@ -0,0 +1,53 @@
|
||||
<xml xmlns="http://www.w3.org/1999/xhtml">
|
||||
<variables>
|
||||
<variable type="" id="PGGhch1kuMF##st8~wFr">receivedNumber</variable>
|
||||
</variables>
|
||||
<block type="pxt-on-start" x="77" y="38">
|
||||
<statement name="HANDLER">
|
||||
<block type="device_show_number">
|
||||
<value name="number">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">12</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<next>
|
||||
<block type="basic_show_icon">
|
||||
<field name="i">IconNames.Umbrella</field>
|
||||
<next>
|
||||
<block type="device_print_message">
|
||||
<value name="text">
|
||||
<shadow type="text">
|
||||
<field name="TEXT">hi!</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<next>
|
||||
<block type="device_pause">
|
||||
<value name="pause">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">100</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<next>
|
||||
<block type="device_clear_display">
|
||||
<next>
|
||||
<block type="basic_show_arrow">
|
||||
<value name="i">
|
||||
<shadow type="device_arrow">
|
||||
<field name="arrow">ArrowNames.South</field>
|
||||
</shadow>
|
||||
</value>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</statement>
|
||||
</block>
|
||||
<block type="device_forever" x="418" y="25"></block>
|
||||
</xml>
|
||||
66
libs/core/blocks-test/control.blocks
Normal file
@@ -0,0 +1,66 @@
|
||||
<xml xmlns="http://www.w3.org/1999/xhtml">
|
||||
<variables>
|
||||
<variable type="" id="tgDN]qF_Ah1Z*?=|+?^Y">item</variable>
|
||||
</variables>
|
||||
<block type="control_in_background" x="-13" y="175">
|
||||
<statement name="HANDLER">
|
||||
<block type="control_reset">
|
||||
<next>
|
||||
<block type="control_wait_us">
|
||||
<value name="micros">
|
||||
<shadow type="math_number" id="w]G5E,EGl+SOB?91N4SV">
|
||||
<field name="NUM">4</field>
|
||||
</shadow>
|
||||
<block type="control_event_timestamp""></block>
|
||||
</value>
|
||||
<next>
|
||||
<block type="control_raise_event">
|
||||
<value name="src">
|
||||
<shadow type="control_event_source_id" id="~$#[A%Y{}%ZvxA7_z/6+">
|
||||
<field name="id">EventBusSource.MICROBIT_ID_BUTTON_A</field>
|
||||
</shadow>
|
||||
<block type="control_event_value""></block>
|
||||
</value>
|
||||
<value name="value">
|
||||
<shadow type="control_event_value_id" id="=OWyqW(E=RBE^i;;QC0$">
|
||||
<field name="id">EventBusValue.MICROBIT_EVT_ANY</field>
|
||||
</shadow>
|
||||
<block type="control_device_serial_number"></block>
|
||||
</value>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</statement>
|
||||
</block>
|
||||
<block type="control_on_event" x="-58" y="393">
|
||||
<value name="src">
|
||||
<shadow type="control_event_source_id" id="o,i-zrB1+%JG/,EC.6zB">
|
||||
<field name="id">EventBusSource.MICROBIT_ID_BUTTON_A</field>
|
||||
</shadow>
|
||||
<block type="control_event_value_id">
|
||||
<field name="id">EventBusValue.MES_DPAD_BUTTON_C_UP</field>
|
||||
</block>
|
||||
</value>
|
||||
<value name="value">
|
||||
<shadow type="control_event_value_id" id="n2s(-M;{|izma6OZGq:F">
|
||||
<field name="id">EventBusValue.MICROBIT_EVT_ANY</field>
|
||||
</shadow>
|
||||
<block type="control_event_value_id">
|
||||
<field name="id">EventBusValue.MES_REMOTE_CONTROL_EVT_PLAY</field>
|
||||
</block>
|
||||
</value>
|
||||
<statement name="HANDLER">
|
||||
<block type="variables_set">
|
||||
<field name="VAR" id="tgDN]qF_Ah1Z*?=|+?^Y" variabletype="">item</field>
|
||||
<value name="VALUE">
|
||||
<shadow type="math_number" id="$3|;#yTHhAwO-r1Bsk:B">
|
||||
<field name="NUM">0</field>
|
||||
</shadow>
|
||||
<block type="control_device_name"></block>
|
||||
</value>
|
||||
</block>
|
||||
</statement>
|
||||
</block>
|
||||
</xml>
|
||||
183
libs/core/blocks-test/game.blocks
Normal file
@@ -0,0 +1,183 @@
|
||||
<xml xmlns="http://www.w3.org/1999/xhtml">
|
||||
<variables>
|
||||
<variable type="" id="B{fp`0m8viO6.2a3):}D">item</variable>
|
||||
<variable type="" id=")IrU.C_Qui4E3llvPl7H">gdfgsdfg</variable>
|
||||
</variables>
|
||||
<block type="pxt-on-start" x="246" y="25">
|
||||
<statement name="HANDLER">
|
||||
<block type="game_delete_sprite">
|
||||
<value name="this">
|
||||
<block type="game_create_sprite">
|
||||
<value name="x">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">2</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<value name="y">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">2</field>
|
||||
</shadow>
|
||||
</value>
|
||||
</block>
|
||||
</value>
|
||||
<next>
|
||||
<block type="game_move_sprite">
|
||||
<value name="sprite">
|
||||
<block type="variables_get">
|
||||
<field name="VAR" id="B{fp`0m8viO6.2a3):}D" variabletype="">item</field>
|
||||
</block>
|
||||
</value>
|
||||
<value name="leds">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">1</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<next>
|
||||
<block type="game_turn_sprite">
|
||||
<field name="direction">Direction.Right</field>
|
||||
<value name="sprite">
|
||||
<block type="variables_get">
|
||||
<field name="VAR" id="B{fp`0m8viO6.2a3):}D" variabletype="">item</field>
|
||||
</block>
|
||||
</value>
|
||||
<value name="degrees">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">45</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<next>
|
||||
<block type="game_sprite_change_xy">
|
||||
<field name="property">LedSpriteProperty.X</field>
|
||||
<value name="sprite">
|
||||
<block type="variables_get">
|
||||
<field name="VAR" id="B{fp`0m8viO6.2a3):}D" variabletype="">item</field>
|
||||
</block>
|
||||
</value>
|
||||
<value name="value">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">1</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<next>
|
||||
<block type="game_sprite_set_property">
|
||||
<field name="property">LedSpriteProperty.X</field>
|
||||
<value name="sprite">
|
||||
<block type="variables_get">
|
||||
<field name="VAR" id="B{fp`0m8viO6.2a3):}D" variabletype="">item</field>
|
||||
</block>
|
||||
</value>
|
||||
<value name="value">
|
||||
<shadow type="math_number" id="sRSKKdl8vYSc1rPg4mA2">
|
||||
<field name="NUM">0</field>
|
||||
</shadow>
|
||||
<block type="game_sprite_property">
|
||||
<field name="property">LedSpriteProperty.X</field>
|
||||
<value name="sprite">
|
||||
<block type="variables_get">
|
||||
<field name="VAR" id="B{fp`0m8viO6.2a3):}D" variabletype="">item</field>
|
||||
</block>
|
||||
</value>
|
||||
</block>
|
||||
</value>
|
||||
<next>
|
||||
<block type="variables_set">
|
||||
<field name="VAR" id=")IrU.C_Qui4E3llvPl7H" variabletype="">gdfgsdfg</field>
|
||||
<value name="VALUE">
|
||||
<shadow type="math_number" id="}{^7O7X5I9`!f`OhoEk1">
|
||||
<field name="NUM">0</field>
|
||||
</shadow>
|
||||
<block type="game_sprite_touching_sprite">
|
||||
<value name="sprite">
|
||||
<block type="variables_get">
|
||||
<field name="VAR" id="B{fp`0m8viO6.2a3):}D" variabletype="">item</field>
|
||||
</block>
|
||||
</value>
|
||||
<value name="other">
|
||||
<block type="variables_get">
|
||||
<field name="VAR" id="B{fp`0m8viO6.2a3):}D" variabletype="">item</field>
|
||||
</block>
|
||||
</value>
|
||||
</block>
|
||||
</value>
|
||||
<next>
|
||||
<block type="variables_set">
|
||||
<field name="VAR" id=")IrU.C_Qui4E3llvPl7H" variabletype="">gdfgsdfg</field>
|
||||
<value name="VALUE">
|
||||
<shadow type="math_number" id="}{^7O7X5I9`!f`OhoEk1">
|
||||
<field name="NUM">0</field>
|
||||
</shadow>
|
||||
<block type="game_sprite_touching_edge">
|
||||
<value name="sprite">
|
||||
<block type="variables_get">
|
||||
<field name="VAR" id="B{fp`0m8viO6.2a3):}D" variabletype="">item</field>
|
||||
</block>
|
||||
</value>
|
||||
</block>
|
||||
</value>
|
||||
<next>
|
||||
<block type="game_sprite_bounce">
|
||||
<value name="sprite">
|
||||
<block type="variables_get">
|
||||
<field name="VAR" id="B{fp`0m8viO6.2a3):}D" variabletype="">item</field>
|
||||
</block>
|
||||
</value>
|
||||
<next>
|
||||
<block type="game_add_score">
|
||||
<value name="points">
|
||||
<shadow type="math_number" id="Z8k_T^n:89Tv{RiBQP!$">
|
||||
<field name="NUM">1</field>
|
||||
</shadow>
|
||||
<block type="game_score"></block>
|
||||
</value>
|
||||
<next>
|
||||
<block type="game_set_score">
|
||||
<value name="points">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">0</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<next>
|
||||
<block type="game_start_countdown">
|
||||
<value name="duration">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">10000</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<next>
|
||||
<block type="game_game_over"></block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</statement>
|
||||
</block>
|
||||
<block type="variables_set" disabled="true" x="-76" y="44">
|
||||
<field name="VAR" id="B{fp`0m8viO6.2a3):}D" variabletype="">item</field>
|
||||
<value name="VALUE">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">0</field>
|
||||
</shadow>
|
||||
</value>
|
||||
</block>
|
||||
<block type="variables_get" disabled="true" x="-92" y="111">
|
||||
<field name="VAR" id="B{fp`0m8viO6.2a3):}D" variabletype="">item</field>
|
||||
</block>
|
||||
</xml>
|
||||
46
libs/core/blocks-test/image.blocks
Normal file
@@ -0,0 +1,46 @@
|
||||
<xml xmlns="http://www.w3.org/1999/xhtml">
|
||||
<variables>
|
||||
<variable type="" id="tgDN]qF_Ah1Z*?=|+?^Y">item</variable>
|
||||
</variables>
|
||||
<block type="pxt-on-start" x="-29" y="116">
|
||||
<statement name="HANDLER">
|
||||
<block type="device_show_image_offset">
|
||||
<value name="sprite">
|
||||
<block type="builtin_image">
|
||||
<field name="i">IconNames.Heart</field>
|
||||
</block>
|
||||
</value>
|
||||
<value name="offset">
|
||||
<shadow type="math_number" id="KX(1%=^vQUd=Q`UHhD*n">
|
||||
<field name="NUM">0</field>
|
||||
</shadow>
|
||||
<block type="device_arrow">
|
||||
<field name="arrow">ArrowNames.South</field>
|
||||
</block>
|
||||
</value>
|
||||
<next>
|
||||
<block type="device_scroll_image">
|
||||
<value name="sprite">
|
||||
<block type="builtin_arrow_image">
|
||||
<field name="i">ArrowNames.SouthWest</field>
|
||||
</block>
|
||||
</value>
|
||||
<value name="frameoffset">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">1</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<value name="delay">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">200</field>
|
||||
</shadow>
|
||||
</value>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</statement>
|
||||
</block>
|
||||
<block type="variables_get" disabled="true" x="145" y="168">
|
||||
<field name="VAR" id="tgDN]qF_Ah1Z*?=|+?^Y" variabletype="">item</field>
|
||||
</block>
|
||||
</xml>
|
||||
132
libs/core/blocks-test/input.blocks
Normal file
@@ -0,0 +1,132 @@
|
||||
<xml xmlns="http://www.w3.org/1999/xhtml">
|
||||
<variables>
|
||||
<variable type="" id="wUkGVHoc@p^mter~Rc7h">item</variable>
|
||||
<variable type="" id=")f$ml.CVl6|1^?sPWl:;">sdfsadf</variable>
|
||||
</variables>
|
||||
<block type="device_button_event" x="-6" y="17">
|
||||
<field name="NAME">Button.AB</field>
|
||||
<statement name="HANDLER">
|
||||
<block type="variables_set">
|
||||
<field name="VAR" id="wUkGVHoc@p^mter~Rc7h" variabletype="">item</field>
|
||||
<value name="VALUE">
|
||||
<shadow type="math_number" id="*jGI?[NsA.f}=qk0RHHf">
|
||||
<field name="NUM">0</field>
|
||||
</shadow>
|
||||
<block type="device_get_button2">
|
||||
<field name="NAME">Button.B</field>
|
||||
</block>
|
||||
</value>
|
||||
<next>
|
||||
<block type="variables_set">
|
||||
<field name="VAR" id="wUkGVHoc@p^mter~Rc7h" variabletype="">item</field>
|
||||
<value name="VALUE">
|
||||
<shadow type="math_number" id="*jGI?[NsA.f}=qk0RHHf">
|
||||
<field name="NUM">0</field>
|
||||
</shadow>
|
||||
<block type="device_pin_is_pressed">
|
||||
<field name="NAME">TouchPin.P1</field>
|
||||
</block>
|
||||
</value>
|
||||
<next>
|
||||
<block type="variables_set">
|
||||
<field name="VAR" id=")f$ml.CVl6|1^?sPWl:;" variabletype="">sdfsadf</field>
|
||||
<value name="VALUE">
|
||||
<shadow type="math_number" id="bZBPUCLiZ6#D@e_[Y`:0">
|
||||
<field name="NUM">0</field>
|
||||
</shadow>
|
||||
<block type="device_acceleration">
|
||||
<field name="NAME">Dimension.Y</field>
|
||||
</block>
|
||||
</value>
|
||||
<next>
|
||||
<block type="variables_set">
|
||||
<field name="VAR" id=")f$ml.CVl6|1^?sPWl:;" variabletype="">sdfsadf</field>
|
||||
<value name="VALUE">
|
||||
<shadow type="math_number" id="bZBPUCLiZ6#D@e_[Y`:0">
|
||||
<field name="NUM">0</field>
|
||||
</shadow>
|
||||
<block type="device_get_light_level"></block>
|
||||
</value>
|
||||
<next>
|
||||
<block type="variables_set">
|
||||
<field name="VAR" id=")f$ml.CVl6|1^?sPWl:;" variabletype="">sdfsadf</field>
|
||||
<value name="VALUE">
|
||||
<shadow type="math_number" id="bZBPUCLiZ6#D@e_[Y`:0">
|
||||
<field name="NUM">0</field>
|
||||
</shadow>
|
||||
<block type="device_heading"></block>
|
||||
</value>
|
||||
<next>
|
||||
<block type="variables_set">
|
||||
<field name="VAR" id=")f$ml.CVl6|1^?sPWl:;" variabletype="">sdfsadf</field>
|
||||
<value name="VALUE">
|
||||
<shadow type="math_number" id="bZBPUCLiZ6#D@e_[Y`:0">
|
||||
<field name="NUM">0</field>
|
||||
</shadow>
|
||||
<block type="device_temperature"></block>
|
||||
</value>
|
||||
<next>
|
||||
<block type="variables_set">
|
||||
<field name="VAR" id=")f$ml.CVl6|1^?sPWl:;" variabletype="">sdfsadf</field>
|
||||
<value name="VALUE">
|
||||
<shadow type="math_number" id="o~k},FK*r@[O2)Cy!lM}">
|
||||
<field name="NUM">0</field>
|
||||
</shadow>
|
||||
<block type="device_get_rotation">
|
||||
<field name="NAME">Rotation.Roll</field>
|
||||
</block>
|
||||
</value>
|
||||
<next>
|
||||
<block type="variables_set">
|
||||
<field name="VAR" id=")f$ml.CVl6|1^?sPWl:;" variabletype="">sdfsadf</field>
|
||||
<value name="VALUE">
|
||||
<shadow type="math_number" id="Uu,ZpYs7!BzIpX`%V_^!">
|
||||
<field name="NUM">0</field>
|
||||
</shadow>
|
||||
<block type="device_get_magnetic_force">
|
||||
<field name="NAME">Dimension.Z</field>
|
||||
</block>
|
||||
</value>
|
||||
<next>
|
||||
<block type="variables_set">
|
||||
<field name="VAR" id=")f$ml.CVl6|1^?sPWl:;" variabletype="">sdfsadf</field>
|
||||
<value name="VALUE">
|
||||
<shadow type="math_number" id="s{USu#UBc84Ao*jy(EQC">
|
||||
<field name="NUM">0</field>
|
||||
</shadow>
|
||||
<block type="device_get_running_time"></block>
|
||||
</value>
|
||||
<next>
|
||||
<block type="device_set_accelerometer_range">
|
||||
<field name="range">AcceleratorRange.TwoG</field>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</statement>
|
||||
</block>
|
||||
<block type="device_gesture_event" x="472" y="-8">
|
||||
<field name="NAME">Gesture.SixG</field>
|
||||
</block>
|
||||
<block type="device_pin_event" x="555" y="96">
|
||||
<field name="name">TouchPin.P2</field>
|
||||
</block>
|
||||
<block type="device_pin_released" x="188" y="435">
|
||||
<field name="NAME">TouchPin.P2</field>
|
||||
</block>
|
||||
</xml>
|
||||
114
libs/core/blocks-test/led.blocks
Normal file
@@ -0,0 +1,114 @@
|
||||
<xml xmlns="http://www.w3.org/1999/xhtml">
|
||||
<block type="pxt-on-start" x="20" y="20">
|
||||
<statement name="HANDLER">
|
||||
<block type="device_plot">
|
||||
<value name="x">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">5</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<value name="y">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">5</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<next>
|
||||
<block type="device_unplot">
|
||||
<value name="x">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">5</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<value name="y">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">5</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<next>
|
||||
<block type="device_led_toggle">
|
||||
<value name="x">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">5</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<value name="y">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">5</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<next>
|
||||
<block type="device_plot_bar_graph">
|
||||
<value name="value">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">0</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<value name="high">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">0</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<next>
|
||||
<block type="device_plot_brightness">
|
||||
<value name="x">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">5</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<value name="y">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">5</field>
|
||||
</shadow>
|
||||
<block type="device_get_brightness"></block>
|
||||
</value>
|
||||
<value name="brightness">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">5</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<next>
|
||||
<block type="device_set_brightness">
|
||||
<value name="value">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">5</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<next>
|
||||
<block type="device_stop_animation">
|
||||
<next>
|
||||
<block type="device_led_enable">
|
||||
<value name="on">
|
||||
<shadow type="logic_boolean" id="F!|?!lo8YkE4p2I@MDy?">
|
||||
<field name="BOOL">FALSE</field>
|
||||
</shadow>
|
||||
<block type="device_point">
|
||||
<value name="x">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">5</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<value name="y">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">5</field>
|
||||
</shadow>
|
||||
</value>
|
||||
</block>
|
||||
</value>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</statement>
|
||||
</block>
|
||||
</xml>
|
||||
95
libs/core/blocks-test/music.blocks
Normal file
@@ -0,0 +1,95 @@
|
||||
<xml xmlns="http://www.w3.org/1999/xhtml">
|
||||
<variables>
|
||||
<variable type="" id="I3xB5Q]ehg#-~(sq{[|E">item</variable>
|
||||
</variables>
|
||||
<block type="melody_on_event" x="-27" y="128">
|
||||
<field name="value">MusicEvent.BackgroundMelodyStarted</field>
|
||||
<statement name="HANDLER">
|
||||
<block type="device_play_note">
|
||||
<value name="note">
|
||||
<shadow type="device_note">
|
||||
<field name="name">175</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<value name="duration">
|
||||
<shadow type="device_beat">
|
||||
<field name="fraction">BeatFraction.Sixteenth</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<next>
|
||||
<block type="device_ring">
|
||||
<value name="note">
|
||||
<shadow type="device_note">
|
||||
<field name="name">147</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<next>
|
||||
<block type="device_rest">
|
||||
<value name="duration">
|
||||
<shadow type="device_beat">
|
||||
<field name="fraction">BeatFraction.Sixteenth</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<next>
|
||||
<block type="variables_set">
|
||||
<field name="VAR" id="I3xB5Q]ehg#-~(sq{[|E" variabletype="">item</field>
|
||||
<value name="VALUE">
|
||||
<shadow type="math_number" id="8/Ht9pG0DuL-0~sPe},^">
|
||||
<field name="NUM">0</field>
|
||||
</shadow>
|
||||
<block type="device_note">
|
||||
<field name="name">466</field>
|
||||
</block>
|
||||
</value>
|
||||
<next>
|
||||
<block type="variables_set">
|
||||
<field name="VAR" id="I3xB5Q]ehg#-~(sq{[|E" variabletype="">item</field>
|
||||
<value name="VALUE">
|
||||
<shadow type="math_number" id="8/Ht9pG0DuL-0~sPe},^">
|
||||
<field name="NUM">0</field>
|
||||
</shadow>
|
||||
<block type="device_beat">
|
||||
<field name="fraction">BeatFraction.Sixteenth</field>
|
||||
</block>
|
||||
</value>
|
||||
<next>
|
||||
<block type="variables_set">
|
||||
<field name="VAR" id="I3xB5Q]ehg#-~(sq{[|E" variabletype="">item</field>
|
||||
<value name="VALUE">
|
||||
<shadow type="math_number" id="8/Ht9pG0DuL-0~sPe},^">
|
||||
<field name="NUM">0</field>
|
||||
</shadow>
|
||||
<block type="device_tempo"></block>
|
||||
</value>
|
||||
<next>
|
||||
<block type="device_change_tempo">
|
||||
<value name="value">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">1242</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<next>
|
||||
<block type="device_set_tempo">
|
||||
<value name="value">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">5</field>
|
||||
</shadow>
|
||||
</value>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</statement>
|
||||
</block>
|
||||
</xml>
|
||||
209
libs/core/blocks-test/pins.blocks
Normal file
@@ -0,0 +1,209 @@
|
||||
<xml xmlns="http://www.w3.org/1999/xhtml">
|
||||
<block type="pins_on_pulsed" x="-157" y="130">
|
||||
<field name="pin">DigitalPin.P5</field>
|
||||
<field name="pulse">PulseValue.Low</field>
|
||||
<statement name="HANDLER">
|
||||
<block type="device_set_analog_pin">
|
||||
<field name="name">AnalogPin.P9</field>
|
||||
<value name="value">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">5</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<next>
|
||||
<block type="device_set_analog_period">
|
||||
<field name="pin">AnalogPin.P10</field>
|
||||
<value name="micros">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">20000</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<next>
|
||||
<block type="device_set_digital_pin">
|
||||
<field name="name">DigitalPin.P6</field>
|
||||
<value name="value">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">5</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<next>
|
||||
<block type="device_set_servo_pin">
|
||||
<field name="name">AnalogPin.P13</field>
|
||||
<value name="value">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">5</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<next>
|
||||
<block type="device_set_servo_pulse">
|
||||
<field name="value">AnalogPin.P8</field>
|
||||
<value name="micros">
|
||||
<shadow type="math_number" id="Hx4bpmg|8KSH=b_`+XtP">
|
||||
<field name="NUM">1500</field>
|
||||
</shadow>
|
||||
<block type="math_map">
|
||||
<value name="value">
|
||||
<shadow type="math_number" id="J%8`=~h4-?O{fY59%(_{">
|
||||
<field name="NUM">0</field>
|
||||
</shadow>
|
||||
<block type="pins_i2c_readnumber">
|
||||
<field name="format">NumberFormat.Int8BE</field>
|
||||
<value name="address">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">0</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<value name="repeat">
|
||||
<shadow type="logic_boolean">
|
||||
<field name="BOOL">FALSE</field>
|
||||
</shadow>
|
||||
</value>
|
||||
</block>
|
||||
</value>
|
||||
<value name="fromLow">
|
||||
<shadow type="math_number" id="kp(!mScnCVWI/1_X|ar#">
|
||||
<field name="NUM">0</field>
|
||||
</shadow>
|
||||
<block type="pins_pulse_in">
|
||||
<field name="name">DigitalPin.P9</field>
|
||||
<field name="value">PulseValue.Low</field>
|
||||
</block>
|
||||
</value>
|
||||
<value name="fromHigh">
|
||||
<shadow type="math_number" id="]@F=`[ZuxAk,=05Yyn[{">
|
||||
<field name="NUM">1023</field>
|
||||
</shadow>
|
||||
<block type="pins_pulse_duration"></block>
|
||||
</value>
|
||||
<value name="toLow">
|
||||
<shadow type="math_number" id="sJDL?hoabUE)cDdBJWO=">
|
||||
<field name="NUM">0</field>
|
||||
</shadow>
|
||||
<block type="spi_write">
|
||||
<value name="value">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">0</field>
|
||||
</shadow>
|
||||
</value>
|
||||
</block>
|
||||
</value>
|
||||
<value name="toHigh">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">4</field>
|
||||
</shadow>
|
||||
</value>
|
||||
</block>
|
||||
</value>
|
||||
<next>
|
||||
<block type="i2c_writenumber">
|
||||
<field name="format">NumberFormat.Int16BE</field>
|
||||
<value name="address">
|
||||
<shadow type="math_number" id="RjJ{^G_#*rwUqER:]i-L">
|
||||
<field name="NUM">0</field>
|
||||
</shadow>
|
||||
<block type="device_get_digital_pin">
|
||||
<field name="name">DigitalPin.P9</field>
|
||||
</block>
|
||||
</value>
|
||||
<value name="value">
|
||||
<shadow type="math_number" id="CCl{zdVU/!(bR}aUfG,G">
|
||||
<field name="NUM">0</field>
|
||||
</shadow>
|
||||
<block type="device_get_analog_pin">
|
||||
<field name="name">AnalogPin.P9</field>
|
||||
</block>
|
||||
</value>
|
||||
<value name="repeat">
|
||||
<shadow type="logic_boolean">
|
||||
<field name="BOOL">FALSE</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<next>
|
||||
<block type="spi_pins">
|
||||
<field name="mosi">DigitalPin.P11</field>
|
||||
<field name="miso">DigitalPin.P9</field>
|
||||
<field name="sck">DigitalPin.P10</field>
|
||||
<next>
|
||||
<block type="device_set_pull">
|
||||
<field name="pin">DigitalPin.P9</field>
|
||||
<field name="pull">PinPullMode.PullDown</field>
|
||||
<next>
|
||||
<block type="device_analog_pitch">
|
||||
<value name="frequency">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">0</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<value name="ms">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">0</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<next>
|
||||
<block type="device_set_pin_events">
|
||||
<field name="pin">DigitalPin.P8</field>
|
||||
<field name="type">PinEventType.Touch</field>
|
||||
<next>
|
||||
<block type="device_analog_set_pitch_pin">
|
||||
<field name="name">AnalogPin.P9</field>
|
||||
<next>
|
||||
<block type="spi_format">
|
||||
<value name="bits">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">8</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<value name="mode">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">3</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<next>
|
||||
<block type="spi_format">
|
||||
<value name="bits">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">8</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<value name="mode">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">3</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<next>
|
||||
<block type="spi_frequency">
|
||||
<value name="frequency">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">1000000</field>
|
||||
</shadow>
|
||||
</value>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</statement>
|
||||
</block>
|
||||
</xml>
|
||||
94
libs/core/blocks-test/serial.blocks
Normal file
@@ -0,0 +1,94 @@
|
||||
<xml xmlns="http://www.w3.org/1999/xhtml">
|
||||
<variables>
|
||||
<variable type="" id="3ch~y{k6dWI;q}kA]3pa">item</variable>
|
||||
</variables>
|
||||
<block type="serial_on_data_received" x="79" y="287">
|
||||
<value name="delimiters">
|
||||
<shadow type="serial_delimiter_conv" id="Rgi{j+glSZt}8nIn!+08">
|
||||
<field name="del">Delimiters.Colon</field>
|
||||
</shadow>
|
||||
<block type="serial_read_buffer"></block>
|
||||
</value>
|
||||
<statement name="HANDLER">
|
||||
<block type="serial_writeline">
|
||||
<value name="text">
|
||||
<shadow type="text" id="re1R]taer}HU[ed30FDZ">
|
||||
<field name="TEXT"></field>
|
||||
</shadow>
|
||||
<block type="serial_read_line"></block>
|
||||
</value>
|
||||
<next>
|
||||
<block type="serial_writenumber">
|
||||
<value name="value">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">0</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<next>
|
||||
<block type="serial_writevalue">
|
||||
<value name="name">
|
||||
<shadow type="text" id="Y9NXoV7DPB{.(T=w:ei^">
|
||||
<field name="TEXT">x</field>
|
||||
</shadow>
|
||||
<block type="serial_read_until">
|
||||
<value name="delimiter">
|
||||
<shadow type="serial_delimiter_conv">
|
||||
<field name="del">Delimiters.Colon</field>
|
||||
</shadow>
|
||||
</value>
|
||||
</block>
|
||||
</value>
|
||||
<value name="value">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">0</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<next>
|
||||
<block type="serial_writestring">
|
||||
<value name="text">
|
||||
<shadow type="text">
|
||||
<field name="TEXT"></field>
|
||||
</shadow>
|
||||
</value>
|
||||
<next>
|
||||
<block type="serial_writenumbers">
|
||||
<value name="values">
|
||||
<block type="variables_get">
|
||||
<field name="VAR" id="3ch~y{k6dWI;q}kA]3pa" variabletype="">item</field>
|
||||
</block>
|
||||
</value>
|
||||
<next>
|
||||
<block type="serial_redirect">
|
||||
<field name="tx">SerialPin.P12</field>
|
||||
<field name="rx">SerialPin.P13</field>
|
||||
<field name="rate">BaudRate.BaudRate28800</field>
|
||||
<next>
|
||||
<block type="serial_writebuffer">
|
||||
<value name="buffer">
|
||||
<block type="serial_readbuffer">
|
||||
<value name="length">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">64</field>
|
||||
</shadow>
|
||||
</value>
|
||||
</block>
|
||||
</value>
|
||||
<next>
|
||||
<block type="serial_redirect_to_usb"></block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</statement>
|
||||
</block>
|
||||
</xml>
|
||||
677
libs/core/blocks-test/test.blocks
Normal file
@@ -0,0 +1,677 @@
|
||||
<xml xmlns="http://www.w3.org/1999/xhtml">
|
||||
<variables>
|
||||
<variable type="" id="2w47B[B-y%SK,+8+DQGz">booltest</variable>
|
||||
<variable type="" id="Uv6@%!N7Ts}XI7t+j[zB">myImage</variable>
|
||||
<variable type="" id="7BPQp@}m*I210zEM4S=3">strtest</variable>
|
||||
</variables>
|
||||
<block type="pxt-on-start" x="481" y="68">
|
||||
<statement name="HANDLER">
|
||||
<block type="device_show_number">
|
||||
<value name="number">
|
||||
<shadow type="math_number" id=")RB0,?b3RM|TO|?[ZPG6">
|
||||
<field name="NUM">123</field>
|
||||
</shadow>
|
||||
<block type="control_event_value""></block>
|
||||
</value>
|
||||
<next>
|
||||
<block type="device_show_leds">
|
||||
<field name="LEDS">`
|
||||
# . . # .
|
||||
# . . # .
|
||||
. # . . .
|
||||
. # # . .
|
||||
. . . . .
|
||||
`
|
||||
</field>
|
||||
<next>
|
||||
<block type="basic_show_icon">
|
||||
<field name="i">IconNames.Heart</field>
|
||||
<next>
|
||||
<block type="device_pause">
|
||||
<value name="pause">
|
||||
<shadow type="timePicker">
|
||||
<field name="ms">500</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<next>
|
||||
<block type="device_clear_display">
|
||||
<next>
|
||||
<block type="basic_show_arrow">
|
||||
<value name="i">
|
||||
<shadow type="device_arrow">
|
||||
<field name="arrow">ArrowNames.SouthEast</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<next>
|
||||
<block type="device_show_image_offset">
|
||||
<value name="sprite">
|
||||
<block type="variables_get">
|
||||
<field name="VAR" id="Uv6@%!N7Ts}XI7t+j[zB" variabletype="">myImage</field>
|
||||
</block>
|
||||
</value>
|
||||
<value name="offset">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">0</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<next>
|
||||
<block type="device_scroll_image">
|
||||
<value name="sprite">
|
||||
<block type="variables_get">
|
||||
<field name="VAR" id="Uv6@%!N7Ts}XI7t+j[zB" variabletype="">myImage</field>
|
||||
</block>
|
||||
</value>
|
||||
<value name="frameoffset">
|
||||
<shadow type="math_number" id="xu?]Tdz!8RfpHlMjG)~B">
|
||||
<field name="NUM">1</field>
|
||||
</shadow>
|
||||
<block type="control_device_serial_number"></block>
|
||||
</value>
|
||||
<value name="delay">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">200</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<next>
|
||||
<block type="variables_set">
|
||||
<field name="VAR" id="7BPQp@}m*I210zEM4S=3" variabletype="">strtest</field>
|
||||
<value name="VALUE">
|
||||
<shadow type="math_number" id="W]w@ImzxKDQ=.w+$$f4a">
|
||||
<field name="NUM">0</field>
|
||||
</shadow>
|
||||
<block type="serial_read_until">
|
||||
<value name="delimiter">
|
||||
<shadow type="serial_delimiter_conv">
|
||||
<field name="del">Delimiters.Hash</field>
|
||||
</shadow>
|
||||
</value>
|
||||
</block>
|
||||
</value>
|
||||
<next>
|
||||
<block type="variables_set">
|
||||
<field name="VAR" id="7BPQp@}m*I210zEM4S=3" variabletype="">strtest</field>
|
||||
<value name="VALUE">
|
||||
<shadow type="math_number" id="W]w@ImzxKDQ=.w+$$f4a">
|
||||
<field name="NUM">0</field>
|
||||
</shadow>
|
||||
<block type="serial_read_buffer"></block>
|
||||
</value>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</statement>
|
||||
</block>
|
||||
<block type="device_pin_event" x="2407" y="0">
|
||||
<field name="name">TouchPin.P2</field>
|
||||
<statement name="HANDLER">
|
||||
<block type="device_led_toggle">
|
||||
<value name="x">
|
||||
<shadow type="math_number_minmax">
|
||||
<mutation min="0" max="4" label="X" precision="1"></mutation>
|
||||
<field name="SLIDER">1</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<value name="y">
|
||||
<shadow type="math_number_minmax">
|
||||
<mutation min="0" max="4" label="Y" precision="1"></mutation>
|
||||
<field name="SLIDER">2</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<next>
|
||||
<block type="device_plot_bar_graph">
|
||||
<value name="value">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">5</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<value name="high">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">45</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<next>
|
||||
<block type="led_set_display_mode">
|
||||
<field name="mode">DisplayMode.Greyscale</field>
|
||||
<next>
|
||||
<block type="device_set_analog_pin">
|
||||
<field name="name">AnalogPin.P4</field>
|
||||
<value name="value">
|
||||
<shadow type="math_number_minmax" id=",:%8N*FL3wa-zFQ[+^$9">
|
||||
<mutation min="0" max="1023" label="Value"></mutation>
|
||||
<field name="SLIDER">1023</field>
|
||||
</shadow>
|
||||
<block type="device_get_analog_pin">
|
||||
<field name="name">AnalogPin.P13</field>
|
||||
</block>
|
||||
</value>
|
||||
<next>
|
||||
<block type="device_set_digital_pin">
|
||||
<field name="name">DigitalPin.P10</field>
|
||||
<value name="value">
|
||||
<shadow type="math_number_minmax" id="W~pvdj%jFEj?EHmT{81Z">
|
||||
<mutation min="0" max="1" label="Value"></mutation>
|
||||
<field name="SLIDER">0</field>
|
||||
</shadow>
|
||||
<block type="device_get_digital_pin">
|
||||
<field name="name">DigitalPin.P15</field>
|
||||
</block>
|
||||
</value>
|
||||
<next>
|
||||
<block type="device_set_analog_period">
|
||||
<field name="pin">AnalogPin.P9</field>
|
||||
<value name="micros">
|
||||
<shadow type="math_number" id="4a@.1MdG`n=p;34mQOpC">
|
||||
<field name="NUM">1234</field>
|
||||
</shadow>
|
||||
<block type="pin_map">
|
||||
<value name="value">
|
||||
<shadow type="math_number" id="lTWI!)d`ZkwvZW))3X(F">
|
||||
<field name="NUM">0</field>
|
||||
</shadow>
|
||||
<block type="device_temperature"></block>
|
||||
</value>
|
||||
<value name="fromLow">
|
||||
<shadow type="math_number" id="2n.VJ_pD7wFdcjM:FToF">
|
||||
<field name="NUM">0</field>
|
||||
</shadow>
|
||||
<block type="device_heading"></block>
|
||||
</value>
|
||||
<value name="fromHigh">
|
||||
<shadow type="math_number" id="-c^:x{=$`RLP5RW9}{6a">
|
||||
<field name="NUM">1023</field>
|
||||
</shadow>
|
||||
<block type="device_get_rotation">
|
||||
<field name="NAME">Rotation.Roll</field>
|
||||
</block>
|
||||
</value>
|
||||
<value name="toLow">
|
||||
<shadow type="math_number" id="#1@Uxq:nFqe!(pHawH9H">
|
||||
<field name="NUM">0</field>
|
||||
</shadow>
|
||||
<block type="device_get_magnetic_force">
|
||||
<field name="NAME">Dimension.Y</field>
|
||||
</block>
|
||||
</value>
|
||||
<value name="toHigh">
|
||||
<shadow type="math_number" id="?%tD/NB|a$cg#TU0/C02">
|
||||
<field name="NUM">4</field>
|
||||
</shadow>
|
||||
<block type="device_get_running_time"></block>
|
||||
</value>
|
||||
</block>
|
||||
</value>
|
||||
<next>
|
||||
<block type="device_set_servo_pin">
|
||||
<field name="name">AnalogPin.P20</field>
|
||||
<value name="value">
|
||||
<shadow type="math_number_minmax" id="xC9lYf`{!gA-A8R+#~L.">
|
||||
<mutation min="0" max="180" label="Value"></mutation>
|
||||
<field name="SLIDER">180</field>
|
||||
</shadow>
|
||||
<block type="device_acceleration">
|
||||
<field name="NAME">Dimension.Z</field>
|
||||
</block>
|
||||
</value>
|
||||
<next>
|
||||
<block type="device_set_servo_pulse">
|
||||
<field name="value">AnalogPin.P14</field>
|
||||
<value name="micros">
|
||||
<shadow type="math_number" id="@*C3kzJkeeUQ@s$N5?K}">
|
||||
<field name="NUM">1500</field>
|
||||
</shadow>
|
||||
<block type="device_get_light_level"></block>
|
||||
</value>
|
||||
<next>
|
||||
<block type="device_play_note">
|
||||
<value name="note">
|
||||
<shadow type="device_note">
|
||||
<field name="name">220</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<value name="duration">
|
||||
<shadow type="device_beat">
|
||||
<field name="fraction">BeatFraction.Sixteenth</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<next>
|
||||
<block type="device_ring">
|
||||
<value name="note">
|
||||
<shadow type="device_note">
|
||||
<field name="name">659</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<next>
|
||||
<block type="device_rest">
|
||||
<value name="duration">
|
||||
<shadow type="device_beat">
|
||||
<field name="fraction">BeatFraction.Double</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<next>
|
||||
<block type="device_start_melody">
|
||||
<field name="options">MelodyOptions.ForeverInBackground</field>
|
||||
<value name="melody">
|
||||
<shadow type="device_builtin_melody">
|
||||
<field name="melody">Melodies.Ringtone</field>
|
||||
</shadow>
|
||||
</value>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</statement>
|
||||
</block>
|
||||
<block type="device_gesture_event" x="1570" y="56">
|
||||
<field name="NAME">Gesture.TiltLeft</field>
|
||||
<statement name="HANDLER">
|
||||
<block type="device_unplot">
|
||||
<value name="x">
|
||||
<shadow type="math_number_minmax" id="|}V%t{K/j77J}J54FX]r">
|
||||
<mutation min="0" max="4" label="X" precision="1"></mutation>
|
||||
<field name="SLIDER">1</field>
|
||||
</shadow>
|
||||
<block type="control_event_value_id">
|
||||
<field name="id">EventBusValue.MICROBIT_PIN_EVT_PULSE_HI</field>
|
||||
</block>
|
||||
</value>
|
||||
<value name="y">
|
||||
<shadow type="math_number_minmax">
|
||||
<mutation min="0" max="4" label="Y" precision="1"></mutation>
|
||||
<field name="SLIDER">2</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<next>
|
||||
<block type="serial_writebuffer">
|
||||
<value name="buffer">
|
||||
<shadow type="serial_readbuffer">
|
||||
<value name="length">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">64</field>
|
||||
</shadow>
|
||||
</value>
|
||||
</shadow>
|
||||
</value>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</statement>
|
||||
</block>
|
||||
<block type="device_forever" x="1172" y="242">
|
||||
<statement name="HANDLER">
|
||||
<block type="variables_set">
|
||||
<field name="VAR" id="2w47B[B-y%SK,+8+DQGz" variabletype="">booltest</field>
|
||||
<value name="VALUE">
|
||||
<shadow type="math_number" id="RP?w4vFS1wB4I0nNyldb">
|
||||
<field name="NUM">0</field>
|
||||
</shadow>
|
||||
<block type="device_get_button2">
|
||||
<field name="NAME">Button.B</field>
|
||||
</block>
|
||||
</value>
|
||||
<next>
|
||||
<block type="variables_set">
|
||||
<field name="VAR" id="2w47B[B-y%SK,+8+DQGz" variabletype="">booltest</field>
|
||||
<value name="VALUE">
|
||||
<shadow type="math_number" id="RP?w4vFS1wB4I0nNyldb">
|
||||
<field name="NUM">0</field>
|
||||
</shadow>
|
||||
<block type="device_pin_is_pressed">
|
||||
<field name="NAME">TouchPin.P2</field>
|
||||
</block>
|
||||
</value>
|
||||
<next>
|
||||
<block type="variables_set">
|
||||
<field name="VAR" id="2w47B[B-y%SK,+8+DQGz" variabletype="">booltest</field>
|
||||
<value name="VALUE">
|
||||
<shadow type="math_number" id="RP?w4vFS1wB4I0nNyldb">
|
||||
<field name="NUM">0</field>
|
||||
</shadow>
|
||||
<block type="device_point">
|
||||
<value name="x">
|
||||
<shadow type="math_number_minmax">
|
||||
<mutation min="0" max="4" label="X" precision="1"></mutation>
|
||||
<field name="SLIDER">3</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<value name="y">
|
||||
<shadow type="math_number_minmax">
|
||||
<mutation min="0" max="4" label="Y" precision="1"></mutation>
|
||||
<field name="SLIDER">4</field>
|
||||
</shadow>
|
||||
</value>
|
||||
</block>
|
||||
</value>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</statement>
|
||||
</block>
|
||||
<block type="device_button_event" x="1294" y="513">
|
||||
<field name="NAME">Button.AB</field>
|
||||
<statement name="HANDLER">
|
||||
<block type="device_plot">
|
||||
<value name="x">
|
||||
<shadow type="math_number_minmax" id="Z[BsF}r)3:FoNWE|X5}s">
|
||||
<mutation min="0" max="4" label="X" precision="1"></mutation>
|
||||
<field name="SLIDER">1</field>
|
||||
</shadow>
|
||||
<block type="device_beat">
|
||||
<field name="fraction">BeatFraction.Sixteenth</field>
|
||||
</block>
|
||||
</value>
|
||||
<value name="y">
|
||||
<shadow type="math_number_minmax">
|
||||
<mutation min="0" max="4" label="Y" precision="1"></mutation>
|
||||
<field name="SLIDER">2</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<next>
|
||||
<block type="device_plot_brightness">
|
||||
<value name="x">
|
||||
<shadow type="math_number_minmax" id="2we6or2Y|vhAl!^BAYtl">
|
||||
<mutation min="0" max="4" label="X" precision="1"></mutation>
|
||||
<field name="SLIDER">3</field>
|
||||
</shadow>
|
||||
<block type="device_tempo"></block>
|
||||
</value>
|
||||
<value name="y">
|
||||
<shadow type="math_number_minmax">
|
||||
<mutation min="0" max="4" label="Y" precision="1"></mutation>
|
||||
<field name="SLIDER">5</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<value name="brightness">
|
||||
<shadow type="math_number_minmax" id="IjJTgf5z!,K`qd`~pCB3">
|
||||
<mutation min="0" max="255" label="Brightness"></mutation>
|
||||
<field name="SLIDER">255</field>
|
||||
</shadow>
|
||||
<block type="device_get_brightness"></block>
|
||||
</value>
|
||||
<next>
|
||||
<block type="device_set_brightness">
|
||||
<value name="value">
|
||||
<shadow type="math_number_minmax" id="WAUzdT@1z{%:UNn!_dU(">
|
||||
<mutation min="0" max="255" label="Value"></mutation>
|
||||
<field name="SLIDER">255</field>
|
||||
</shadow>
|
||||
<block type="device_note">
|
||||
<field name="name">440</field>
|
||||
</block>
|
||||
</value>
|
||||
<next>
|
||||
<block type="device_stop_animation">
|
||||
<next>
|
||||
<block type="device_led_enable">
|
||||
<value name="on">
|
||||
<shadow type="logic_boolean">
|
||||
<field name="BOOL">TRUE</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<next>
|
||||
<block type="input_compass_calibrate"></block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</statement>
|
||||
</block>
|
||||
<block type="control_in_background" x="0" y="635">
|
||||
<statement name="HANDLER">
|
||||
<block type="control_wait_us">
|
||||
<value name="micros">
|
||||
<shadow type="math_number" id="^!;AKS(vo=ly}ykm1~Z|">
|
||||
<field name="NUM">4</field>
|
||||
</shadow>
|
||||
<block type="control_event_timestamp""></block>
|
||||
</value>
|
||||
<next>
|
||||
<block type="control_raise_event">
|
||||
<value name="src">
|
||||
<shadow type="control_event_source_id">
|
||||
<field name="id">EventBusSource.MICROBIT_ID_IO_P0</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<value name="value">
|
||||
<shadow type="control_event_value_id">
|
||||
<field name="id">EventBusValue.MES_ALERT_EVT_ALARM1</field>
|
||||
</shadow>
|
||||
</value>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</statement>
|
||||
</block>
|
||||
<block type="device_pin_released" x="942" y="723">
|
||||
<field name="NAME">TouchPin.P2</field>
|
||||
<statement name="HANDLER">
|
||||
<block type="device_set_accelerometer_range">
|
||||
<field name="range">AcceleratorRange.EightG</field>
|
||||
</block>
|
||||
</statement>
|
||||
</block>
|
||||
<block type="serial_on_data_received" x="419" y="933">
|
||||
<value name="delimiters">
|
||||
<shadow type="serial_delimiter_conv">
|
||||
<field name="del">Delimiters.Colon</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<statement name="HANDLER">
|
||||
<block type="serial_redirect">
|
||||
<field name="tx">SerialPin.P12</field>
|
||||
<field name="rx">SerialPin.P14</field>
|
||||
<field name="rate">BaudRate.BaudRate19200</field>
|
||||
<next>
|
||||
<block type="serial_redirect_to_usb"></block>
|
||||
</next>
|
||||
</block>
|
||||
</statement>
|
||||
</block>
|
||||
<block type="pins_on_pulsed" x="1538" y="929">
|
||||
<field name="pin">DigitalPin.P10</field>
|
||||
<field name="pulse">PulseValue.Low</field>
|
||||
<statement name="HANDLER">
|
||||
<block type="i2c_writenumber">
|
||||
<field name="format">NumberFormat.UInt8BE</field>
|
||||
<value name="address">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">0</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<value name="value">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">0</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<value name="repeat">
|
||||
<shadow type="logic_boolean">
|
||||
<field name="BOOL">FALSE</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<next>
|
||||
<block type="device_analog_pitch">
|
||||
<value name="frequency">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">0</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<value name="ms">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">0</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<next>
|
||||
<block type="device_set_pin_events">
|
||||
<field name="pin">DigitalPin.P0</field>
|
||||
<field name="type">PinEventType.Touch</field>
|
||||
<next>
|
||||
<block type="spi_frequency">
|
||||
<value name="frequency">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">1000000</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<next>
|
||||
<block type="device_analog_set_pitch_pin">
|
||||
<field name="name">AnalogPin.P2</field>
|
||||
<next>
|
||||
<block type="device_set_pull">
|
||||
<field name="pin">DigitalPin.P2</field>
|
||||
<field name="pull">PinPullMode.PullDown</field>
|
||||
<next>
|
||||
<block type="spi_format">
|
||||
<value name="bits">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">8</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<value name="mode">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">3</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<next>
|
||||
<block type="spi_pins">
|
||||
<field name="mosi">DigitalPin.P9</field>
|
||||
<field name="miso">DigitalPin.P14</field>
|
||||
<field name="sck">DigitalPin.P16</field>
|
||||
<next>
|
||||
<block type="control_reset"></block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</statement>
|
||||
</block>
|
||||
<block type="melody_on_event" x="859" y="1002">
|
||||
<field name="value">MusicEvent.BackgroundMelodyNotePlayed</field>
|
||||
<statement name="HANDLER">
|
||||
<block type="device_change_tempo">
|
||||
<value name="value">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">123</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<next>
|
||||
<block type="device_set_tempo">
|
||||
<value name="value">
|
||||
<shadow type="math_number_minmax">
|
||||
<mutation min="4" max="400" label="Bpm" precision="0"></mutation>
|
||||
<field name="SLIDER">12312312</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<next>
|
||||
<block type="serial_writeline">
|
||||
<value name="text">
|
||||
<shadow type="text" id="SYl:x9lxu0KI{YcmomQz">
|
||||
<field name="TEXT"></field>
|
||||
</shadow>
|
||||
<block type="serial_read_line"></block>
|
||||
</value>
|
||||
<next>
|
||||
<block type="serial_writenumber">
|
||||
<value name="value">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">0</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<next>
|
||||
<block type="serial_writevalue">
|
||||
<value name="name">
|
||||
<shadow type="text">
|
||||
<field name="TEXT">x</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<value name="value">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">0</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<next>
|
||||
<block type="serial_writestring">
|
||||
<value name="text">
|
||||
<shadow type="text" id="_gp`6rz8ZI+em9ILvR~6">
|
||||
<field name="TEXT"></field>
|
||||
</shadow>
|
||||
<block type="control_device_name"></block>
|
||||
</value>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</next>
|
||||
</block>
|
||||
</statement>
|
||||
</block>
|
||||
<block type="control_on_event" x="24" y="1406">
|
||||
<value name="src">
|
||||
<shadow type="control_event_source_id">
|
||||
<field name="id">EventBusSource.MICROBIT_ID_IO_P1</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<value name="value">
|
||||
<shadow type="control_event_value_id">
|
||||
<field name="id">EventBusValue.MES_ALERT_EVT_ALARM2</field>
|
||||
</shadow>
|
||||
</value>
|
||||
</block>
|
||||
</xml>
|
||||
@@ -1,160 +0,0 @@
|
||||
#include "pxt.h"
|
||||
|
||||
// keep in sync with github/pxt/pxtsim/libgeneric.ts
|
||||
enum class NumberFormat {
|
||||
Int8LE = 1,
|
||||
UInt8LE,
|
||||
Int16LE,
|
||||
UInt16LE,
|
||||
Int32LE,
|
||||
Int8BE,
|
||||
UInt8BE,
|
||||
Int16BE,
|
||||
UInt16BE,
|
||||
Int32BE,
|
||||
// UInt32,
|
||||
};
|
||||
|
||||
//% indexerGet=BufferMethods::getByte indexerSet=BufferMethods::setByte
|
||||
namespace BufferMethods {
|
||||
//%
|
||||
int getByte(Buffer buf, int off) {
|
||||
return max(ManagedBuffer(buf).getByte(off), 0);
|
||||
}
|
||||
|
||||
//%
|
||||
void setByte(Buffer buf, int off, int v) {
|
||||
ManagedBuffer(buf).setByte(off, v);
|
||||
}
|
||||
|
||||
//%
|
||||
uint8_t *getBytes(Buffer buf) {
|
||||
return buf->payload;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a number in specified format in the buffer.
|
||||
*/
|
||||
//%
|
||||
void setNumber(Buffer buf, NumberFormat format, int offset, int value)
|
||||
{
|
||||
int8_t i8;
|
||||
uint8_t u8;
|
||||
int16_t i16;
|
||||
uint16_t u16;
|
||||
int32_t i32;
|
||||
|
||||
ManagedBuffer b(buf);
|
||||
|
||||
// Assume little endian
|
||||
#define WRITEBYTES(isz, swap) isz = value; b.writeBytes(offset, (uint8_t*)&isz, sizeof(isz), swap); break
|
||||
|
||||
switch (format) {
|
||||
case NumberFormat::Int8LE: WRITEBYTES(i8, false);
|
||||
case NumberFormat::UInt8LE: WRITEBYTES(u8, false);
|
||||
case NumberFormat::Int16LE: WRITEBYTES(i16, false);
|
||||
case NumberFormat::UInt16LE: WRITEBYTES(u16, false);
|
||||
case NumberFormat::Int32LE: WRITEBYTES(i32, false);
|
||||
case NumberFormat::Int8BE: WRITEBYTES(i8, true);
|
||||
case NumberFormat::UInt8BE: WRITEBYTES(u8, true);
|
||||
case NumberFormat::Int16BE: WRITEBYTES(i16, true);
|
||||
case NumberFormat::UInt16BE: WRITEBYTES(u16, true);
|
||||
case NumberFormat::Int32BE: WRITEBYTES(i32, true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a number in specified format from the buffer.
|
||||
*/
|
||||
//%
|
||||
int getNumber(Buffer buf, NumberFormat format, int offset)
|
||||
{
|
||||
int8_t i8;
|
||||
uint8_t u8;
|
||||
int16_t i16;
|
||||
uint16_t u16;
|
||||
int32_t i32;
|
||||
|
||||
ManagedBuffer b(buf);
|
||||
|
||||
// Assume little endian
|
||||
#define READBYTES(isz, swap) b.readBytes((uint8_t*)&isz, offset, sizeof(isz), swap); return isz
|
||||
|
||||
switch (format) {
|
||||
case NumberFormat::Int8LE: READBYTES(i8, false);
|
||||
case NumberFormat::UInt8LE: READBYTES(u8, false);
|
||||
case NumberFormat::Int16LE: READBYTES(i16, false);
|
||||
case NumberFormat::UInt16LE: READBYTES(u16, false);
|
||||
case NumberFormat::Int32LE: READBYTES(i32, false);
|
||||
case NumberFormat::Int8BE: READBYTES(i8, true);
|
||||
case NumberFormat::UInt8BE: READBYTES(u8, true);
|
||||
case NumberFormat::Int16BE: READBYTES(i16, true);
|
||||
case NumberFormat::UInt16BE: READBYTES(u16, true);
|
||||
case NumberFormat::Int32BE: READBYTES(i32, true);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Returns the length of a Buffer object. */
|
||||
//% property
|
||||
int length(Buffer s) {
|
||||
return s->length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill (a fragment) of the buffer with given value.
|
||||
*/
|
||||
//%
|
||||
void fill(Buffer buf, int value, int offset = 0, int length = -1)
|
||||
{
|
||||
ManagedBuffer(buf).fill(value, offset, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a copy of a fragment of a buffer.
|
||||
*/
|
||||
//%
|
||||
Buffer slice(Buffer buf, int offset = 0, int length = -1)
|
||||
{
|
||||
return ManagedBuffer(buf).slice(offset, length).leakData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Shift buffer left in place, with zero padding.
|
||||
* @param offset number of bytes to shift; use negative value to shift right
|
||||
* @param start start offset in buffer. Default is 0.
|
||||
* @param length number of elements in buffer. If negative, length is set as the buffer length minus start. eg: -1
|
||||
*/
|
||||
//%
|
||||
void shift(Buffer buf, int offset, int start = 0, int length = -1)
|
||||
{
|
||||
ManagedBuffer(buf).shift(offset, start, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotate buffer left in place.
|
||||
* @param offset number of bytes to shift; use negative value to shift right
|
||||
* @param start start offset in buffer. Default is 0.
|
||||
* @param length number of elements in buffer. If negative, length is set as the buffer length minus start. eg: -1
|
||||
*/
|
||||
//%
|
||||
void rotate(Buffer buf, int offset, int start = 0, int length = -1)
|
||||
{
|
||||
ManagedBuffer(buf).rotate(offset, start, length);
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
/**
|
||||
* Write contents of `src` at `dstOffset` in current buffer.
|
||||
*/
|
||||
//%
|
||||
void write(Buffer buf, int dstOffset, Buffer src)
|
||||
{
|
||||
//Not supported, we only do up to 4 args :/
|
||||
//void write(Buffer buf, int dstOffset, Buffer src, int srcOffset = 0, int length = -1)
|
||||
ManagedBuffer(buf).writeBuffer(dstOffset, ManagedBuffer(src), 0, -1);
|
||||
}
|
||||
}
|
||||
280
libs/core/codal.cpp
Normal file
@@ -0,0 +1,280 @@
|
||||
#include "pxt.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
PXT_ABI(__aeabi_dadd)
|
||||
PXT_ABI(__aeabi_dcmplt)
|
||||
PXT_ABI(__aeabi_dcmpgt)
|
||||
PXT_ABI(__aeabi_dsub)
|
||||
PXT_ABI(__aeabi_ddiv)
|
||||
PXT_ABI(__aeabi_dmul)
|
||||
|
||||
extern "C" void target_panic(int error_code) {
|
||||
// wait for serial to flush
|
||||
wait_us(300000);
|
||||
microbit_panic(error_code);
|
||||
}
|
||||
|
||||
extern "C" void target_reset() {
|
||||
microbit_reset();
|
||||
}
|
||||
|
||||
uint32_t device_heap_size(uint8_t heap_index); // defined in microbit-dal
|
||||
|
||||
namespace pxt {
|
||||
|
||||
MicroBit uBit;
|
||||
MicroBitEvent lastEvent;
|
||||
|
||||
void platform_init() {
|
||||
microbit_seed_random();
|
||||
seedRandom(microbit_random(0x7fffffff));
|
||||
}
|
||||
|
||||
void initMicrobitGC() {
|
||||
if (device_heap_size(1) > NON_GC_HEAP_RESERVATION + 4)
|
||||
gcPreAllocateBlock(device_heap_size(1) - NON_GC_HEAP_RESERVATION);
|
||||
}
|
||||
|
||||
void platform_init();
|
||||
void usb_init();
|
||||
|
||||
struct FreeList {
|
||||
FreeList *next;
|
||||
};
|
||||
|
||||
static void initCodal() {
|
||||
|
||||
uBit.init();
|
||||
|
||||
// repeat error 4 times and restart as needed
|
||||
microbit_panic_timeout(4);
|
||||
}
|
||||
|
||||
void dumpDmesg() {}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// An adapter for the API expected by the run-time.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// 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;
|
||||
|
||||
auto curr = findBinding(e.source, e.value);
|
||||
auto value = fromInt(e.value);
|
||||
if (curr)
|
||||
runAction1(curr->action, value);
|
||||
|
||||
curr = findBinding(e.source, DEVICE_EVT_ANY);
|
||||
if (curr)
|
||||
runAction1(curr->action, value);
|
||||
}
|
||||
|
||||
void registerWithDal(int id, int event, Action a, int flags) {
|
||||
// first time?
|
||||
if (!findBinding(id, event))
|
||||
uBit.messageBus.listen(id, event, dispatchEvent, flags);
|
||||
setBinding(id, event, a);
|
||||
}
|
||||
|
||||
void fiberDone(void *a) {
|
||||
decr((Action)a);
|
||||
unregisterGCPtr((Action)a);
|
||||
release_fiber();
|
||||
}
|
||||
|
||||
void releaseFiber() {
|
||||
release_fiber();
|
||||
}
|
||||
|
||||
void sleep_ms(unsigned ms) {
|
||||
fiber_sleep(ms);
|
||||
}
|
||||
|
||||
void sleep_us(uint64_t us) {
|
||||
wait_us(us);
|
||||
}
|
||||
|
||||
void forever_stub(void *a) {
|
||||
while (true) {
|
||||
runAction0((Action)a);
|
||||
fiber_sleep(20);
|
||||
}
|
||||
}
|
||||
|
||||
void runForever(Action a) {
|
||||
if (a != 0) {
|
||||
incr(a);
|
||||
registerGCPtr(a);
|
||||
create_fiber(forever_stub, (void *)a);
|
||||
}
|
||||
}
|
||||
|
||||
void runInParallel(Action a) {
|
||||
if (a != 0) {
|
||||
incr(a);
|
||||
registerGCPtr(a);
|
||||
create_fiber((void (*)(void *))runAction0, (void *)a, fiberDone);
|
||||
}
|
||||
}
|
||||
|
||||
void waitForEvent(int id, int event) {
|
||||
fiber_wait_for_event(id, event);
|
||||
}
|
||||
|
||||
void initRuntime() {
|
||||
initCodal();
|
||||
platform_init();
|
||||
}
|
||||
|
||||
//%
|
||||
unsigned afterProgramPage() {
|
||||
unsigned ptr = (unsigned)&bytecode[0];
|
||||
ptr += programSize();
|
||||
ptr = (ptr + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
int current_time_ms() {
|
||||
return system_timer_current_time();
|
||||
}
|
||||
|
||||
static void logwriten(const char *msg, int l) {
|
||||
uBit.serial.send((uint8_t *)msg, l);
|
||||
}
|
||||
|
||||
static void logwrite(const char *msg) {
|
||||
logwriten(msg, strlen(msg));
|
||||
}
|
||||
|
||||
static void writeNum(char *buf, uint32_t n, bool full) {
|
||||
int i = 0;
|
||||
int sh = 28;
|
||||
while (sh >= 0) {
|
||||
int d = (n >> sh) & 0xf;
|
||||
if (full || d || sh == 0 || i) {
|
||||
buf[i++] = d > 9 ? 'A' + d - 10 : '0' + d;
|
||||
}
|
||||
sh -= 4;
|
||||
}
|
||||
buf[i] = 0;
|
||||
}
|
||||
|
||||
static void logwritenum(uint32_t n, bool full, bool hex) {
|
||||
char buff[20];
|
||||
|
||||
if (hex) {
|
||||
writeNum(buff, n, full);
|
||||
logwrite("0x");
|
||||
} else {
|
||||
itoa(n, buff);
|
||||
}
|
||||
|
||||
logwrite(buff);
|
||||
}
|
||||
|
||||
void vdebuglog(const char *format, va_list ap) {
|
||||
const char *end = format;
|
||||
|
||||
while (*end) {
|
||||
if (*end++ == '%') {
|
||||
logwriten(format, end - format - 1);
|
||||
uint32_t val = va_arg(ap, uint32_t);
|
||||
switch (*end++) {
|
||||
case 'c':
|
||||
logwriten((const char *)&val, 1);
|
||||
break;
|
||||
case 'd':
|
||||
logwritenum(val, false, false);
|
||||
break;
|
||||
case 'x':
|
||||
logwritenum(val, false, true);
|
||||
break;
|
||||
case 'p':
|
||||
case 'X':
|
||||
logwritenum(val, true, true);
|
||||
break;
|
||||
case 's':
|
||||
logwrite((char *)(void *)val);
|
||||
break;
|
||||
case '%':
|
||||
logwrite("%");
|
||||
break;
|
||||
default:
|
||||
logwrite("???");
|
||||
break;
|
||||
}
|
||||
format = end;
|
||||
}
|
||||
}
|
||||
logwriten(format, end - format);
|
||||
logwrite("\n");
|
||||
}
|
||||
|
||||
void debuglog(const char *format, ...) {
|
||||
va_list arg;
|
||||
va_start(arg, format);
|
||||
vdebuglog(format, arg);
|
||||
va_end(arg);
|
||||
}
|
||||
|
||||
void sendSerial(const char *data, int len) {
|
||||
logwriten(data, len);
|
||||
}
|
||||
|
||||
#ifdef PXT_GC
|
||||
ThreadContext *getThreadContext() {
|
||||
if (!currentFiber)
|
||||
return NULL;
|
||||
return (ThreadContext *)currentFiber->user_data;
|
||||
}
|
||||
|
||||
void setThreadContext(ThreadContext *ctx) {
|
||||
currentFiber->user_data = ctx;
|
||||
}
|
||||
|
||||
static void *threadAddressFor(Fiber *fib, void *sp) {
|
||||
if (fib == currentFiber)
|
||||
return sp;
|
||||
return (uint8_t *)sp + ((uint8_t *)fib->stack_top - (uint8_t *)fib->tcb.stack_base);
|
||||
}
|
||||
|
||||
void gcProcessStacks(int flags) {
|
||||
// check scheduler is initialized
|
||||
if (!currentFiber) {
|
||||
// make sure we allocate something to at least initalize the memory allocator
|
||||
void * volatile p = xmalloc(1);
|
||||
xfree(p);
|
||||
return;
|
||||
}
|
||||
|
||||
int numFibers = list_fibers(NULL);
|
||||
Fiber **fibers = (Fiber **)xmalloc(sizeof(Fiber *) * numFibers);
|
||||
int num2 = list_fibers(fibers);
|
||||
if (numFibers != num2)
|
||||
oops(12);
|
||||
int cnt = 0;
|
||||
|
||||
for (int i = 0; i < numFibers; ++i) {
|
||||
auto fib = fibers[i];
|
||||
auto ctx = (ThreadContext *)fib->user_data;
|
||||
if (!ctx)
|
||||
continue;
|
||||
for (auto seg = &ctx->stack; seg; seg = seg->next) {
|
||||
auto ptr = (TValue *)threadAddressFor(fib, seg->top);
|
||||
auto end = (TValue *)threadAddressFor(fib, seg->bottom);
|
||||
if (flags & 2)
|
||||
DMESG("RS%d:%p/%d", cnt++, ptr, end - ptr);
|
||||
// VLOG("mark: %p - %p", ptr, end);
|
||||
while (ptr < end) {
|
||||
gcProcess(*ptr++);
|
||||
}
|
||||
}
|
||||
}
|
||||
xfree(fibers);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace pxt
|
||||
53
libs/core/console.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
/// <reference no-default-lib="true"/>
|
||||
|
||||
/**
|
||||
* Reading and writing data to the console output.
|
||||
*/
|
||||
//% weight=12 color=#002050 icon="\uf120"
|
||||
//% advanced=true
|
||||
namespace console {
|
||||
type Listener = (text: string) => void;
|
||||
|
||||
//% whenUsed
|
||||
let listeners: Listener[] = undefined;
|
||||
|
||||
/**
|
||||
* Write a line of text to the console output.
|
||||
* @param value to send
|
||||
*/
|
||||
//% weight=90
|
||||
//% help=console/log blockGap=8
|
||||
//% text.shadowOptions.toString=true
|
||||
export function log(text: string): void {
|
||||
// pad text on the 32byte boundar
|
||||
text += "\r\n";
|
||||
control.__log(text);
|
||||
// send to listeners
|
||||
if (listeners)
|
||||
for (let i = 0; i < listeners.length; ++i)
|
||||
listeners[i](text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a name:value pair as a line of text to the console output.
|
||||
* @param name name of the value stream, eg: "x"
|
||||
* @param value to write
|
||||
*/
|
||||
//% weight=88 blockGap=8
|
||||
//% help=console/log-value
|
||||
export function logValue(name: string, value: number): void {
|
||||
log(name ? `${name}: ${value}` : `${value}`)
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a listener for the log messages
|
||||
* @param listener
|
||||
*/
|
||||
//%
|
||||
export function addListener(listener: (text: string) => void) {
|
||||
if (!listener) return;
|
||||
if (!listeners)
|
||||
listeners = [];
|
||||
listeners.push(listener);
|
||||
}
|
||||
}
|
||||
@@ -71,8 +71,6 @@ enum EventBusSource {
|
||||
//% blockIdentity="control.eventSourceId"
|
||||
MICROBIT_ID_IO_P20_ = MICROBIT_ID_IO_P20,
|
||||
//% blockIdentity="control.eventSourceId"
|
||||
MICROBIT_ID_IO_P21_ = MICROBIT_ID_IO_P21,
|
||||
//% blockIdentity="control.eventSourceId"
|
||||
MES_DEVICE_INFO_ID_ = MES_DEVICE_INFO_ID,
|
||||
//% blockIdentity="control.eventSourceId"
|
||||
MES_SIGNAL_STRENGTH_ID_ = MES_SIGNAL_STRENGTH_ID,
|
||||
@@ -207,6 +205,15 @@ enum EventBusValue {
|
||||
MES_REMOTE_CONTROL_EVT_VOLUMEUP_ = MES_REMOTE_CONTROL_EVT_VOLUMEUP,
|
||||
};
|
||||
|
||||
enum EventFlags {
|
||||
//%
|
||||
QueueIfBusy = MESSAGE_BUS_LISTENER_QUEUE_IF_BUSY,
|
||||
//%
|
||||
DropIfBusy = MESSAGE_BUS_LISTENER_DROP_IF_BUSY,
|
||||
//%
|
||||
Reentrant = MESSAGE_BUS_LISTENER_REENTRANT
|
||||
};
|
||||
|
||||
//% weight=1 color="#333333"
|
||||
//% advanced=true
|
||||
namespace control {
|
||||
@@ -222,7 +229,7 @@ namespace control {
|
||||
//% help=control/in-background blockAllowMultiple=1 afterOnStart=true
|
||||
//% blockId="control_in_background" block="run in background" blockGap=8
|
||||
void inBackground(Action a) {
|
||||
runInBackground(a);
|
||||
runInParallel(a);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -258,13 +265,14 @@ namespace control {
|
||||
}
|
||||
|
||||
/**
|
||||
* Raises an event in the event bus.
|
||||
* Registers an event handler.
|
||||
*/
|
||||
//% weight=20 blockGap=8 blockId="control_on_event" block="on event|from %src=control_event_source_id|with value %value=control_event_value_id"
|
||||
//% help=control/on-event
|
||||
//% blockExternalInputs=1
|
||||
void onEvent(int src, int value, Action handler) {
|
||||
registerWithDal(src, value, handler);
|
||||
void onEvent(int src, int value, Action handler, int flags = 0) {
|
||||
if (!flags) flags = EventFlags::QueueIfBusy;
|
||||
registerWithDal(src, value, handler, (int)flags);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -288,12 +296,12 @@ namespace control {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a friendly name for the device derived from the its serial number
|
||||
* Make a friendly name for the device based on its serial number
|
||||
*/
|
||||
//% blockId="control_device_name" block="device name" weight=10 blockGap=8
|
||||
//% advanced=true
|
||||
StringData* deviceName() {
|
||||
return ManagedString(microbit_friendly_name()).leakData();
|
||||
String deviceName() {
|
||||
return mkString(microbit_friendly_name(), -1);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -304,4 +312,22 @@ namespace control {
|
||||
int deviceSerialNumber() {
|
||||
return microbit_serial_number();
|
||||
}
|
||||
|
||||
/**
|
||||
* Informs simulator/runtime of a MIDI message
|
||||
* Internal function to support the simulator.
|
||||
*/
|
||||
//% part=midioutput blockHidden=1
|
||||
void __midiSend(Buffer buffer) {
|
||||
// this is a stub to support the simulator
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
//%
|
||||
void __log(String text) {
|
||||
if (NULL == text) return;
|
||||
pxt::sendSerial(text->getUTF8Data(), text->getUTF8Size());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,47 +4,63 @@
|
||||
//% weight=1 color="#42495F" icon="\uf233"
|
||||
//% advanced=true
|
||||
namespace control {
|
||||
|
||||
/**
|
||||
* Returns the value of a C++ runtime constant
|
||||
*/
|
||||
//% weight=2 weight=19 blockId="control_event_source_id" block="%id" blockGap=8
|
||||
//% shim=TD_ID advanced=true
|
||||
export function eventSourceId(id: EventBusSource): number {
|
||||
return id;
|
||||
}
|
||||
/**
|
||||
* Returns the value of a C++ runtime constant
|
||||
*/
|
||||
//% weight=1 weight=19 blockId="control_event_value_id" block="%id"
|
||||
//% shim=TD_ID advanced=true
|
||||
export function eventValueId(id: EventBusValue): number {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display specified error code and stop the program.
|
||||
*/
|
||||
//% shim=pxtrt::panic
|
||||
export function panic(code: number) { }
|
||||
|
||||
/**
|
||||
* If the condition is false, display msg on serial console, and panic with code 098.
|
||||
*/
|
||||
export function assert(condition: boolean, msg?: string) {
|
||||
if (!condition) {
|
||||
console.log("ASSERTION FAILED")
|
||||
if (msg != null) {
|
||||
console.log(msg)
|
||||
}
|
||||
panic(98)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display warning in the simulator.
|
||||
*/
|
||||
//% shim=pxtrt::runtimeWarning
|
||||
export function runtimeWarning(message: string) { }
|
||||
|
||||
/**
|
||||
* Returns the value of a C++ runtime constant
|
||||
*/
|
||||
//% weight=2 weight=19 blockId="control_event_source_id" block="%id" blockGap=8
|
||||
//% shim=TD_ID advanced=true
|
||||
export function eventSourceId(id: EventBusSource): number {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of a C++ runtime constant
|
||||
*/
|
||||
//% weight=1 weight=19 blockId="control_event_value_id" block="%id"
|
||||
//% shim=TD_ID advanced=true
|
||||
export function eventValueId(id: EventBusValue): number {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display specified error code and stop the program.
|
||||
*/
|
||||
//% shim=pxtrt::panic
|
||||
export function panic(code: number) { }
|
||||
|
||||
/**
|
||||
* If the condition is false, display msg on serial console, and panic with code 098.
|
||||
*/
|
||||
export function assert(condition: boolean, msg?: string) {
|
||||
if (!condition) {
|
||||
console.log("ASSERTION FAILED")
|
||||
if (msg != null) {
|
||||
console.log(msg)
|
||||
}
|
||||
panic(98)
|
||||
}
|
||||
}
|
||||
|
||||
export function fail(message: string) {
|
||||
console.log("Fatal failure: ")
|
||||
console.log(message)
|
||||
panic(108)
|
||||
}
|
||||
|
||||
/**
|
||||
* Display warning in the simulator.
|
||||
*/
|
||||
//% shim=pxtrt::runtimeWarning
|
||||
export function runtimeWarning(message: string) { }
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert any value to text
|
||||
* @param value value to be converted to text
|
||||
*/
|
||||
//% help=text/convert-to-text weight=1
|
||||
//% block="convert $value=math_number to text"
|
||||
//% blockId=variable_to_text blockNamespace="text"
|
||||
function convertToText(value: any): string {
|
||||
return "" + value;
|
||||
}
|
||||
|
||||
@@ -1,436 +0,0 @@
|
||||
#include "pxt.h"
|
||||
#include <limits.h>
|
||||
|
||||
|
||||
namespace String_ {
|
||||
//%
|
||||
StringData *charAt(StringData *s, int pos) {
|
||||
return ManagedString((char)ManagedString(s).charAt(pos)).leakData();
|
||||
}
|
||||
|
||||
//%
|
||||
int charCodeAt(StringData *s, int index) {
|
||||
return ManagedString(s).charAt(index);
|
||||
}
|
||||
|
||||
//%
|
||||
StringData *concat(StringData *s, StringData *other) {
|
||||
ManagedString a(s), b(other);
|
||||
return (a + b).leakData();
|
||||
}
|
||||
|
||||
//%
|
||||
int compare(StringData *s, StringData *that) {
|
||||
int compareResult = strcmp(s->data, that->data);
|
||||
if (compareResult < 0)
|
||||
return -1;
|
||||
else if (compareResult > 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//%
|
||||
int compareDecr(StringData *s, StringData *that) {
|
||||
int r = compare(s, that);
|
||||
if (r == 0)
|
||||
decr((uint32_t)that);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
//%
|
||||
int length(StringData *s) { return s->len; }
|
||||
|
||||
//%
|
||||
StringData *fromCharCode(int code)
|
||||
{
|
||||
return ManagedString((char)code).leakData();
|
||||
}
|
||||
|
||||
//%
|
||||
int toNumber(StringData *s) {
|
||||
return atoi(s->data);
|
||||
}
|
||||
|
||||
//%
|
||||
StringData *mkEmpty()
|
||||
{
|
||||
return ManagedString::EmptyString.leakData();
|
||||
}
|
||||
|
||||
//%
|
||||
StringData *substr(StringData *s, int start, int length)
|
||||
{
|
||||
if (length <= 0)
|
||||
return mkEmpty();
|
||||
if (start < 0)
|
||||
start = max(s->len + start, 0);
|
||||
length = min(length, s->len - start);
|
||||
ManagedString x(s);
|
||||
return x.substring(start, length).leakData();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace Boolean_ {
|
||||
// Cache the string literals "true" and "false" when used.
|
||||
// Note that the representation of booleans stays the usual C-one.
|
||||
|
||||
static const char sTrue[] __attribute__ ((aligned (4))) = "\xff\xff\x04\x00" "true\0";
|
||||
static const char sFalse[] __attribute__ ((aligned (4))) = "\xff\xff\x05\x00" "false\0";
|
||||
|
||||
//%
|
||||
StringData* toString(bool v)
|
||||
{
|
||||
if (v) {
|
||||
return (StringData*)(void*)sTrue;
|
||||
} else {
|
||||
return (StringData*)(void*)sFalse;
|
||||
}
|
||||
}
|
||||
|
||||
//%
|
||||
bool bang(int v) { return v == 0; }
|
||||
}
|
||||
|
||||
namespace Number_ {
|
||||
//%
|
||||
StringData* toString(int n)
|
||||
{
|
||||
return ManagedString(n).leakData();
|
||||
}
|
||||
|
||||
// +, - and friends are handled directly by assembly instructions
|
||||
// The comparisons are here as they are more code-size efficient
|
||||
|
||||
//%
|
||||
bool lt(int x, int y) { return x < y; }
|
||||
//%
|
||||
bool le(int x, int y) { return x <= y; }
|
||||
//%
|
||||
bool neq(int x, int y) { return x != y; }
|
||||
//%
|
||||
bool eq(int x, int y) { return x == y; }
|
||||
//%
|
||||
bool gt(int x, int y) { return x > y; }
|
||||
//%
|
||||
bool ge(int x, int y) { return x >= y; }
|
||||
|
||||
// These in fact call into C runtime on Cortex-M0
|
||||
//%
|
||||
int div(int x, int y) { return x / y; }
|
||||
//%
|
||||
int mod(int x, int y) { return x % y; }
|
||||
|
||||
//%
|
||||
bool eqDecr(int x, int y) {
|
||||
if(x == y) {
|
||||
decr(y);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
namespace Math_ {
|
||||
//%
|
||||
int pow(int x, int y)
|
||||
{
|
||||
if (y < 0)
|
||||
return 0;
|
||||
int r = 1;
|
||||
while (y) {
|
||||
if (y & 1)
|
||||
r *= x;
|
||||
y >>= 1;
|
||||
x *= x;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
//%
|
||||
int random(int max) {
|
||||
if (max == INT_MIN)
|
||||
return -microbit_random(INT_MAX);
|
||||
else if (max < 0)
|
||||
return -microbit_random(-max);
|
||||
else if (max == 0)
|
||||
return 0;
|
||||
else
|
||||
return microbit_random(max);
|
||||
}
|
||||
|
||||
//%
|
||||
int sqrt(int x)
|
||||
{
|
||||
return ::sqrt(x);
|
||||
}
|
||||
}
|
||||
|
||||
namespace Array_ {
|
||||
//%
|
||||
RefCollection *mk(uint32_t flags)
|
||||
{
|
||||
return new RefCollection(flags);
|
||||
}
|
||||
//%
|
||||
int length(RefCollection *c) { return c->length(); }
|
||||
//%
|
||||
void setLength(RefCollection *c, int newLength) { c->setLength(newLength); }
|
||||
//%
|
||||
void push(RefCollection *c, uint32_t x) { c->push(x); }
|
||||
//%
|
||||
uint32_t pop(RefCollection *c) { return c->pop(); }
|
||||
//%
|
||||
uint32_t getAt(RefCollection *c, int x) { return c->getAt(x); }
|
||||
//%
|
||||
void setAt(RefCollection *c, int x, uint32_t y) { c->setAt(x, y); }
|
||||
//%
|
||||
uint32_t removeAt(RefCollection *c, int x) { return c->removeAt(x); }
|
||||
//%
|
||||
void insertAt(RefCollection *c, int x, uint32_t value) { c->insertAt(x, value); }
|
||||
//%
|
||||
int indexOf(RefCollection *c, uint32_t x, int start) { return c->indexOf(x, start); }
|
||||
//%
|
||||
int removeElement(RefCollection *c, uint32_t x) { return c->removeElement(x); }
|
||||
}
|
||||
|
||||
|
||||
// Import some stuff directly
|
||||
namespace pxt {
|
||||
//%
|
||||
void registerWithDal(int id, int event, 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);
|
||||
//%
|
||||
RefRecord* mkClassInstance(int offset);
|
||||
//%
|
||||
void RefRecord_destroy(RefRecord *r);
|
||||
//%
|
||||
void RefRecord_print(RefRecord *r);
|
||||
//%
|
||||
void debugMemLeaks();
|
||||
//%
|
||||
int incr(uint32_t e);
|
||||
//%
|
||||
void decr(uint32_t e);
|
||||
//%
|
||||
uint32_t *allocate(uint16_t sz);
|
||||
//%
|
||||
int templateHash();
|
||||
//%
|
||||
int programHash();
|
||||
//%
|
||||
void *ptrOfLiteral(int offset);
|
||||
//%
|
||||
int getNumGlobals();
|
||||
|
||||
//%
|
||||
uint32_t programSize() {
|
||||
return bytecode[17] * 2;
|
||||
}
|
||||
|
||||
//%
|
||||
uint32_t afterProgramPage() {
|
||||
uint32_t ptr = (uint32_t)&bytecode[0];
|
||||
ptr += programSize();
|
||||
if (ptr % PAGE_SIZE != 0)
|
||||
ptr = (ptr & ~(PAGE_SIZE-1)) + PAGE_SIZE;
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
|
||||
namespace pxtrt {
|
||||
//%
|
||||
uint32_t ldloc(RefLocal *r) {
|
||||
return r->v;
|
||||
}
|
||||
|
||||
//%
|
||||
uint32_t ldlocRef(RefRefLocal *r) {
|
||||
uint32_t tmp = r->v;
|
||||
incr(tmp);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
//%
|
||||
void stloc(RefLocal *r, uint32_t v) {
|
||||
r->v = v;
|
||||
}
|
||||
|
||||
//%
|
||||
void stlocRef(RefRefLocal *r, uint32_t v) {
|
||||
decr(r->v);
|
||||
r->v = v;
|
||||
}
|
||||
|
||||
//%
|
||||
RefLocal *mkloc() {
|
||||
return new RefLocal();
|
||||
}
|
||||
|
||||
//%
|
||||
RefRefLocal *mklocRef() {
|
||||
return new RefRefLocal();
|
||||
}
|
||||
|
||||
// All of the functions below unref() self. This is for performance reasons -
|
||||
// the code emitter will not emit the unrefs for them.
|
||||
|
||||
//%
|
||||
uint32_t ldfld(RefRecord *r, int idx) {
|
||||
auto tmp = r->ld(idx);
|
||||
r->unref();
|
||||
return tmp;
|
||||
}
|
||||
|
||||
//%
|
||||
uint32_t ldfldRef(RefRecord *r, int idx) {
|
||||
auto tmp = r->ldref(idx);
|
||||
r->unref();
|
||||
return tmp;
|
||||
}
|
||||
|
||||
//%
|
||||
void stfld(RefRecord *r, int idx, uint32_t val) {
|
||||
r->st(idx, val);
|
||||
r->unref();
|
||||
}
|
||||
|
||||
//%
|
||||
void stfldRef(RefRecord *r, int idx, uint32_t val) {
|
||||
r->stref(idx, val);
|
||||
r->unref();
|
||||
}
|
||||
|
||||
// Store a captured local in a closure. It returns the action, so it can be chained.
|
||||
//%
|
||||
RefAction *stclo(RefAction *a, int idx, uint32_t v)
|
||||
{
|
||||
//DBG("STCLO "); a->print(); DBG("@%d = %p\n", idx, (void*)v);
|
||||
a->stCore(idx, v);
|
||||
return a;
|
||||
}
|
||||
|
||||
//%
|
||||
void panic(int code)
|
||||
{
|
||||
microbit_panic(code);
|
||||
}
|
||||
|
||||
//%
|
||||
int stringToBool(StringData *s) {
|
||||
if (s == NULL) return 0;
|
||||
if (s->len == 0) {
|
||||
s->decr();
|
||||
return 0;
|
||||
}
|
||||
s->decr();
|
||||
return 1;
|
||||
}
|
||||
|
||||
//%
|
||||
StringData* emptyToNull(StringData *s) {
|
||||
if (!s || s->len == 0)
|
||||
return NULL;
|
||||
return s;
|
||||
}
|
||||
|
||||
//%
|
||||
int ptrToBool(uint32_t p) {
|
||||
if (p) {
|
||||
decr(p);
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
//%
|
||||
RefMap *mkMap() {
|
||||
return new RefMap();
|
||||
}
|
||||
|
||||
//%
|
||||
uint32_t mapGet(RefMap *map, uint32_t key) {
|
||||
int i = map->findIdx(key);
|
||||
if (i < 0) {
|
||||
map->unref();
|
||||
return 0;
|
||||
}
|
||||
uint32_t r = map->data[i].val;
|
||||
map->unref();
|
||||
return r;
|
||||
}
|
||||
|
||||
//%
|
||||
uint32_t mapGetRef(RefMap *map, uint32_t key) {
|
||||
int i = map->findIdx(key);
|
||||
if (i < 0) {
|
||||
map->unref();
|
||||
return 0;
|
||||
}
|
||||
uint32_t r = incr(map->data[i].val);
|
||||
map->unref();
|
||||
return r;
|
||||
}
|
||||
|
||||
//%
|
||||
void mapSet(RefMap *map, uint32_t key, uint32_t val) {
|
||||
int i = map->findIdx(key);
|
||||
if (i < 0) {
|
||||
map->data.push_back({
|
||||
key << 1,
|
||||
val
|
||||
});
|
||||
} else {
|
||||
if (map->data[i].key & 1) {
|
||||
decr(map->data[i].val);
|
||||
map->data[i].key = key << 1;
|
||||
}
|
||||
map->data[i].val = val;
|
||||
}
|
||||
map->unref();
|
||||
}
|
||||
|
||||
//%
|
||||
void mapSetRef(RefMap *map, uint32_t key, uint32_t val) {
|
||||
int i = map->findIdx(key);
|
||||
if (i < 0) {
|
||||
map->data.push_back({
|
||||
(key << 1) | 1,
|
||||
val
|
||||
});
|
||||
} else {
|
||||
if (map->data[i].key & 1) {
|
||||
decr(map->data[i].val);
|
||||
} else {
|
||||
map->data[i].key = (key << 1) | 1;
|
||||
}
|
||||
map->data[i].val = val;
|
||||
}
|
||||
map->unref();
|
||||
}
|
||||
|
||||
//
|
||||
// Debugger
|
||||
//
|
||||
|
||||
//%
|
||||
void* getGlobalsPtr() {
|
||||
return globals;
|
||||
}
|
||||
|
||||
//%
|
||||
void runtimeWarning(StringData *s) {
|
||||
// noop for now
|
||||
}
|
||||
}
|
||||
12
libs/core/dal.d.ts
vendored
@@ -420,11 +420,11 @@ declare const enum DAL {
|
||||
MICROBIT_ACCELEROMETER_EVT_FACE_UP = 5,
|
||||
MICROBIT_ACCELEROMETER_EVT_FACE_DOWN = 6,
|
||||
MICROBIT_ACCELEROMETER_EVT_FREEFALL = 7,
|
||||
MICROBIT_ACCELEROMETER_EVT_2G = 8,
|
||||
MICROBIT_ACCELEROMETER_EVT_3G = 9,
|
||||
MICROBIT_ACCELEROMETER_EVT_6G = 10,
|
||||
MICROBIT_ACCELEROMETER_EVT_8G = 11,
|
||||
MICROBIT_ACCELEROMETER_EVT_SHAKE = 12,
|
||||
// MICROBIT_ACCELEROMETER_EVT_2G = 8,
|
||||
MICROBIT_ACCELEROMETER_EVT_3G = 8,
|
||||
MICROBIT_ACCELEROMETER_EVT_6G = 9,
|
||||
MICROBIT_ACCELEROMETER_EVT_8G = 10,
|
||||
MICROBIT_ACCELEROMETER_EVT_SHAKE = 11,
|
||||
MICROBIT_ACCELEROMETER_REST_TOLERANCE = 200,
|
||||
MICROBIT_ACCELEROMETER_TILT_TOLERANCE = 200,
|
||||
MICROBIT_ACCELEROMETER_FREEFALL_TOLERANCE = 400,
|
||||
@@ -641,4 +641,4 @@ declare const enum DAL {
|
||||
// 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
|
||||
}
|
||||
}
|
||||
111
libs/core/enums.d.ts
vendored
@@ -1,4 +1,30 @@
|
||||
// Auto-generated. Do not edit.
|
||||
|
||||
|
||||
declare const enum NumberFormat {
|
||||
Int8LE = 1,
|
||||
UInt8LE = 2,
|
||||
Int16LE = 3,
|
||||
UInt16LE = 4,
|
||||
Int32LE = 5,
|
||||
Int8BE = 6,
|
||||
UInt8BE = 7,
|
||||
Int16BE = 8,
|
||||
UInt16BE = 9,
|
||||
Int32BE = 10,
|
||||
|
||||
UInt32LE = 11,
|
||||
UInt32BE = 12,
|
||||
Float32LE = 13,
|
||||
Float64LE = 14,
|
||||
Float32BE = 15,
|
||||
Float64BE = 16,
|
||||
}
|
||||
|
||||
|
||||
declare const enum PerfCounters {
|
||||
GC = 0,
|
||||
}
|
||||
declare namespace images {
|
||||
}
|
||||
declare namespace basic {
|
||||
@@ -70,57 +96,68 @@ declare namespace basic {
|
||||
* Raised when shaken
|
||||
*/
|
||||
//% block=shake
|
||||
Shake = 12, // MICROBIT_ACCELEROMETER_EVT_SHAKE
|
||||
//% jres=gestures.shake
|
||||
Shake = 11, // MICROBIT_ACCELEROMETER_EVT_SHAKE
|
||||
/**
|
||||
* Raised when the logo is upward and the screen is vertical
|
||||
*/
|
||||
//% block="logo up"
|
||||
//% jres=gestures.tiltforward
|
||||
LogoUp = 1, // MICROBIT_ACCELEROMETER_EVT_TILT_UP
|
||||
/**
|
||||
* Raised when the logo is downward and the screen is vertical
|
||||
*/
|
||||
//% block="logo down"
|
||||
//% jres=gestures.tiltbackwards
|
||||
LogoDown = 2, // MICROBIT_ACCELEROMETER_EVT_TILT_DOWN
|
||||
/**
|
||||
* Raised when the screen is pointing down and the board is horizontal
|
||||
*/
|
||||
//% block="screen up"
|
||||
//% jres=gestures.frontsideup
|
||||
ScreenUp = 5, // MICROBIT_ACCELEROMETER_EVT_FACE_UP
|
||||
/**
|
||||
* Raised when the screen is pointing up and the board is horizontal
|
||||
*/
|
||||
//% block="screen down"
|
||||
//% jres=gestures.backsideup
|
||||
ScreenDown = 6, // MICROBIT_ACCELEROMETER_EVT_FACE_DOWN
|
||||
/**
|
||||
* Raised when the screen is pointing left
|
||||
*/
|
||||
//% block="tilt left"
|
||||
//% jres=gestures.tiltleft
|
||||
TiltLeft = 3, // MICROBIT_ACCELEROMETER_EVT_TILT_LEFT
|
||||
/**
|
||||
* Raised when the screen is pointing right
|
||||
*/
|
||||
//% block="tilt right"
|
||||
//% jres=gestures.tiltright
|
||||
TiltRight = 4, // MICROBIT_ACCELEROMETER_EVT_TILT_RIGHT
|
||||
/**
|
||||
* Raised when the board is falling!
|
||||
*/
|
||||
//% block="free fall"
|
||||
//% jres=gestures.freefall
|
||||
FreeFall = 7, // MICROBIT_ACCELEROMETER_EVT_FREEFALL
|
||||
/**
|
||||
* Raised when a 3G shock is detected
|
||||
*/
|
||||
//% block="3g"
|
||||
ThreeG = 9, // MICROBIT_ACCELEROMETER_EVT_3G
|
||||
//% jres=gestures.impact3g
|
||||
ThreeG = 8, // MICROBIT_ACCELEROMETER_EVT_3G
|
||||
/**
|
||||
* Raised when a 6G shock is detected
|
||||
*/
|
||||
//% block="6g"
|
||||
SixG = 10, // MICROBIT_ACCELEROMETER_EVT_6G
|
||||
//% jres=gestures.impact6g
|
||||
SixG = 9, // MICROBIT_ACCELEROMETER_EVT_6G
|
||||
/**
|
||||
* Raised when a 8G shock is detected
|
||||
*/
|
||||
//% block="8g"
|
||||
EightG = 11, // MICROBIT_ACCELEROMETER_EVT_8G
|
||||
//% jres=gestures.impact8g
|
||||
EightG = 10, // MICROBIT_ACCELEROMETER_EVT_8G
|
||||
}
|
||||
|
||||
|
||||
@@ -230,8 +267,6 @@ declare namespace input {
|
||||
//% blockIdentity="control.eventSourceId"
|
||||
MICROBIT_ID_IO_P20 = 25, // MICROBIT_ID_IO_P20
|
||||
//% blockIdentity="control.eventSourceId"
|
||||
MICROBIT_ID_IO_P21 = 50, // MICROBIT_ID_IO_P21
|
||||
//% blockIdentity="control.eventSourceId"
|
||||
MES_DEVICE_INFO_ID = 1103, // MES_DEVICE_INFO_ID
|
||||
//% blockIdentity="control.eventSourceId"
|
||||
MES_SIGNAL_STRENGTH_ID = 1101, // MES_SIGNAL_STRENGTH_ID
|
||||
@@ -366,12 +401,24 @@ declare namespace input {
|
||||
//% blockIdentity="control.eventValueId"
|
||||
MES_REMOTE_CONTROL_EVT_VOLUMEUP = 8, // MES_REMOTE_CONTROL_EVT_VOLUMEUP
|
||||
}
|
||||
|
||||
|
||||
declare const enum EventFlags {
|
||||
//%
|
||||
QueueIfBusy = 0x0010, // MESSAGE_BUS_LISTENER_QUEUE_IF_BUSY
|
||||
//%
|
||||
DropIfBusy = 0x0020, // MESSAGE_BUS_LISTENER_DROP_IF_BUSY
|
||||
//%
|
||||
Reentrant = 0x0008, // MESSAGE_BUS_LISTENER_REENTRANT
|
||||
}
|
||||
declare namespace control {
|
||||
}
|
||||
|
||||
|
||||
declare const enum DisplayMode {
|
||||
//% block="black and white"
|
||||
BlackAndWhite = 0, // DISPLAY_MODE_BLACK_AND_WHITE
|
||||
//% blockHidden=true
|
||||
BackAndWhite = 0, // DISPLAY_MODE_BLACK_AND_WHITE
|
||||
//% block="greyscale"
|
||||
Greyscale = 1, // DISPLAY_MODE_GREYSCALE
|
||||
@@ -435,7 +482,9 @@ declare namespace motors {
|
||||
|
||||
|
||||
declare const enum PulseValue {
|
||||
//% block=high
|
||||
High = 4, // MICROBIT_PIN_EVT_PULSE_HI
|
||||
//% block=low
|
||||
Low = 5, // MICROBIT_PIN_EVT_PULSE_LO
|
||||
}
|
||||
|
||||
@@ -463,12 +512,17 @@ declare namespace motors {
|
||||
|
||||
|
||||
declare const enum SerialPin {
|
||||
C16 = 9, // MICROBIT_ID_IO_P2
|
||||
C17 = 15, // MICROBIT_ID_IO_P8
|
||||
P0 = 19, // MICROBIT_ID_IO_P12
|
||||
P1 = 7, // MICROBIT_ID_IO_P0
|
||||
P2 = 8, // MICROBIT_ID_IO_P1
|
||||
P3 = 23, // MICROBIT_ID_IO_P16
|
||||
P0 = 7, // MICROBIT_ID_IO_P0
|
||||
P1 = 8, // MICROBIT_ID_IO_P1
|
||||
P2 = 9, // MICROBIT_ID_IO_P2
|
||||
P8 = 15, // MICROBIT_ID_IO_P8
|
||||
P12 = 19, // MICROBIT_ID_IO_P12
|
||||
P13 = 20, // MICROBIT_ID_IO_P13
|
||||
P14 = 21, // MICROBIT_ID_IO_P14
|
||||
P15 = 22, // MICROBIT_ID_IO_P15
|
||||
P16 = 23, // MICROBIT_ID_IO_P16
|
||||
USB_TX = 1001,
|
||||
USB_RX = 1002,
|
||||
}
|
||||
|
||||
|
||||
@@ -476,9 +530,25 @@ declare namespace motors {
|
||||
//% block=115200
|
||||
BaudRate115200 = 115200,
|
||||
//% block=57600
|
||||
BaudRate56700 = 57600,
|
||||
BaudRate57600 = 57600,
|
||||
//% block=38400
|
||||
BaudRate38400 = 38400,
|
||||
//% block=31250
|
||||
BaudRate31250 = 31250,
|
||||
//% block=28800
|
||||
BaudRate28800 = 28800,
|
||||
//% block=19200
|
||||
BaudRate19200 = 19200,
|
||||
//% block=14400
|
||||
BaudRate14400 = 14400,
|
||||
//% block=9600
|
||||
BaudRate9600 = 9600,
|
||||
//% block=4800
|
||||
BaudRate4800 = 4800,
|
||||
//% block=2400
|
||||
BaudRate2400 = 2400,
|
||||
//% block=1200
|
||||
BaudRate1200 = 1200,
|
||||
}
|
||||
|
||||
|
||||
@@ -499,19 +569,4 @@ declare namespace motors {
|
||||
declare namespace serial {
|
||||
}
|
||||
|
||||
|
||||
declare const enum NumberFormat {
|
||||
Int8LE = 1,
|
||||
UInt8LE = 2,
|
||||
Int16LE = 3,
|
||||
UInt16LE = 4,
|
||||
Int32LE = 5,
|
||||
Int8BE = 6,
|
||||
UInt8BE = 7,
|
||||
Int16BE = 8,
|
||||
UInt16BE = 9,
|
||||
Int32BE = 10,
|
||||
// UInt32,
|
||||
}
|
||||
|
||||
// Auto-generated. Do not edit. Really.
|
||||
|
||||
@@ -168,9 +168,10 @@ namespace game {
|
||||
|
||||
/**
|
||||
* Sets the current life value
|
||||
* @param value TODO
|
||||
* @param value current life value
|
||||
*/
|
||||
//% weight=10
|
||||
//% weight=10 help=game/set-life
|
||||
//% blockId=game_set_life block="set life %value" blockGap=8
|
||||
export function setLife(value: number): void {
|
||||
_life = Math.max(0, value);
|
||||
if (_life <= 0) {
|
||||
@@ -179,10 +180,11 @@ namespace game {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds life points to the current life
|
||||
* @param lives TODO
|
||||
* Add life points to the current life amount
|
||||
* @param lives amount of lives to add
|
||||
*/
|
||||
//% weight=10
|
||||
//% weight=10 help=game/add-life
|
||||
//% blockId=game_add_life block="add life %lives" blockGap=8
|
||||
export function addLife(lives: number): void {
|
||||
setLife(_life + lives);
|
||||
}
|
||||
@@ -200,14 +202,16 @@ namespace game {
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes some life
|
||||
* @param life TODO
|
||||
* Remove some life
|
||||
* @param life amount of life to remove
|
||||
*/
|
||||
//% weight=10
|
||||
//% weight=10 help=game/remove-life
|
||||
//% parts="ledmatrix"
|
||||
//% blockId=game_remove_life block="remove life %life" blockGap=8
|
||||
export function removeLife(life: number): void {
|
||||
setLife(_life - life);
|
||||
if (!_paused)
|
||||
if (!_paused && !_backgroundAnimation) {
|
||||
_backgroundAnimation = true;
|
||||
control.inBackground(() => {
|
||||
led.stopAnimation();
|
||||
basic.showAnimation(`1 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0
|
||||
@@ -215,7 +219,9 @@ namespace game {
|
||||
0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
|
||||
0 1 0 1 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0
|
||||
1 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0`, 40);
|
||||
_backgroundAnimation = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -247,12 +253,12 @@ namespace game {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a value indicating if the game is still running. Returns `false` if game over.
|
||||
* Indicates if the game is still running. Returns `false` if the game is over or paused.
|
||||
*/
|
||||
//% weight=10
|
||||
//% weight=5 help=game/is-running
|
||||
//% blockId=game_isrunning block="is running" blockGap=8
|
||||
export function isRunning(): boolean {
|
||||
let running: boolean;
|
||||
return !_isGameOver;
|
||||
return !_isGameOver && !_paused && !!_img;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -267,8 +273,10 @@ namespace game {
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the game is display the game over sequence.
|
||||
* Indicates if the game is over and displaying the game over sequence.
|
||||
*/
|
||||
//% weight=7 help=game/is-game-over
|
||||
//% blockId=game_isgameover block="is game over" blockGap=8
|
||||
export function isGameOver(): boolean {
|
||||
return _isGameOver;
|
||||
}
|
||||
@@ -276,7 +284,8 @@ namespace game {
|
||||
/**
|
||||
* Indicates if the game rendering is paused to allow other animations
|
||||
*/
|
||||
//%
|
||||
//% weight=6 help=game/is-paused
|
||||
//% blockId=game_ispaused block="is paused" blockGap=8
|
||||
export function isPaused(): boolean {
|
||||
return _paused;
|
||||
}
|
||||
@@ -396,7 +405,7 @@ namespace game {
|
||||
|
||||
/**
|
||||
* If touching the edge of the stage and facing towards it, then turn away.
|
||||
* @param this TODO
|
||||
* @param this the sprite to check for bounce
|
||||
*/
|
||||
//% weight=18 help=game/if-on-edge-bounce
|
||||
//% blockId=game_sprite_bounce block="%sprite|if on edge, bounce"
|
||||
@@ -448,7 +457,7 @@ namespace game {
|
||||
|
||||
/**
|
||||
* Turn the sprite
|
||||
* @param this TODO
|
||||
* @param this the sprite to trun
|
||||
* @param direction left or right
|
||||
* @param degrees angle in degrees to turn, eg: 45, 90, 180, 135
|
||||
*/
|
||||
@@ -463,7 +472,7 @@ namespace game {
|
||||
|
||||
/**
|
||||
* Turn to the right (clockwise)
|
||||
* @param this TODO
|
||||
* @param this the sprite to turn
|
||||
* @param degrees TODO
|
||||
*/
|
||||
public turnRight(degrees: number): void {
|
||||
@@ -472,7 +481,7 @@ namespace game {
|
||||
|
||||
/**
|
||||
* Turn to the left (counter-clockwise)
|
||||
* @param this TODO
|
||||
* @param this the sprite to turn
|
||||
* @param degrees TODO
|
||||
*/
|
||||
public turnLeft(degrees: number): void {
|
||||
@@ -532,12 +541,12 @@ namespace game {
|
||||
|
||||
/**
|
||||
* Set the direction of the current sprite, rounded to the nearest multiple of 45
|
||||
* @param this TODO
|
||||
* @param degrees TODO
|
||||
* @param this the sprite to set direction for
|
||||
* @param degrees new direction in degrees
|
||||
*/
|
||||
//% parts="ledmatrix"
|
||||
public setDirection(degrees: number): void {
|
||||
this._dir = ((degrees / 45) % 8) * 45;
|
||||
this._dir = (Math.floor(degrees / 45) % 8) * 45;
|
||||
if (this._dir <= -180) {
|
||||
this._dir = this._dir + 360;
|
||||
} else if (this._dir > 180) {
|
||||
@@ -608,23 +617,23 @@ namespace game {
|
||||
|
||||
/**
|
||||
* Reports true if sprite has the same position as specified sprite
|
||||
* @param this TODO
|
||||
* @param other TODO
|
||||
* @param this the sprite to check overlap or touch
|
||||
* @param other the other sprite to check overlap or touch
|
||||
*/
|
||||
//% weight=20 help=game/is-touching
|
||||
//% blockId=game_sprite_touching_sprite block="%sprite|touching %other|?" blockGap=8
|
||||
//% blockId=game_sprite_touching_sprite block="is %sprite|touching %other" blockGap=8
|
||||
public isTouching(other: LedSprite): boolean {
|
||||
return this._enabled && other._enabled && this._x == other._x && this._y == other._y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports true if sprite is touching an edge
|
||||
* @param this TODO
|
||||
* @param this the sprite to check for an edge contact
|
||||
*/
|
||||
//% weight=19 help=game/is-touching-edge
|
||||
//% blockId=game_sprite_touching_edge block="%sprite|touching edge?" blockGap=8
|
||||
//% blockId=game_sprite_touching_edge block="is %sprite|touching edge" blockGap=8
|
||||
public isTouchingEdge(): boolean {
|
||||
return this._x == 0 || this._x == 4 || this._y == 0 || this._y == 4;
|
||||
return this._enabled && (this._x == 0 || this._x == 4 || this._y == 0 || this._y == 4);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -686,14 +695,23 @@ namespace game {
|
||||
* Deletes the sprite from the game engine. The sprite will no longer appear on the screen or interact with other sprites.
|
||||
* @param this sprite to delete
|
||||
*/
|
||||
//% weight=59 help=game/delete
|
||||
//% blockId="game_delete_sprite" block="delete %this"
|
||||
//% weight=59 blockGap=8 help=game/delete
|
||||
//% blockId="game_delete_sprite" block="delete %this(sprite)"
|
||||
public delete(): void {
|
||||
this._enabled = false;
|
||||
if (_sprites.removeElement(this))
|
||||
plot();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports whether the sprite has been deleted from the game engine.
|
||||
*/
|
||||
//% weight=58 help=game/is-deleted
|
||||
//% blockId="game_sprite_is_deleted" block="is %sprite|deleted"
|
||||
public isDeleted(): boolean {
|
||||
return !this._enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the blink duration interval in millisecond.
|
||||
* @param sprite TODO
|
||||
@@ -717,7 +735,6 @@ namespace game {
|
||||
* @param this TODO
|
||||
*/
|
||||
public blink(): number {
|
||||
let r: number;
|
||||
return this._blink;
|
||||
}
|
||||
|
||||
@@ -728,7 +745,7 @@ namespace game {
|
||||
if (ps._brightness > 0) {
|
||||
let r = 0;
|
||||
if (ps._blink > 0) {
|
||||
r = (now / ps._blink) % 2;
|
||||
r = Math.floor(now / ps._blink) % 2;
|
||||
}
|
||||
if (r == 0) {
|
||||
_img.setPixelBrightness(ps._x, ps._y, _img.pixelBrightness(ps._x, ps._y) + ps._brightness);
|
||||
@@ -766,7 +783,7 @@ namespace game {
|
||||
}
|
||||
// ensure greyscale mode
|
||||
const dm = led.displayMode();
|
||||
if (dm != DisplayMode.Greyscale)
|
||||
if (dm != DisplayMode.Greyscale)
|
||||
led.setDisplayMode(DisplayMode.Greyscale);
|
||||
// render sprites
|
||||
const now = input.runningTime();
|
||||
@@ -775,9 +792,6 @@ namespace game {
|
||||
_sprites[i]._plot(now);
|
||||
}
|
||||
_img.plotImage(0);
|
||||
// restore previous display mode
|
||||
if (dm != DisplayMode.Greyscale)
|
||||
led.setDisplayMode(dm);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -789,3 +803,4 @@ namespace game {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
39
libs/core/gestures.jres
Normal file
@@ -1,17 +1,10 @@
|
||||
namespace console {
|
||||
export function log(msg: string) {
|
||||
serial.writeString(msg);
|
||||
serial.writeString("\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
namespace Math {
|
||||
/**
|
||||
* Generates a `true` or `false` value randomly, just like flipping a coin.
|
||||
*/
|
||||
//% blockId=logic_random block="pick random true or false"
|
||||
//% help=math/random-boolean color=230
|
||||
//% help=math/random-boolean weight=0 color=712672
|
||||
export function randomBoolean(): boolean {
|
||||
return Math.random(2) == 0;
|
||||
return Math.randomRange(0, 1) === 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
126
libs/core/icons.jres
Normal file
@@ -0,0 +1,126 @@
|
||||
{
|
||||
"*": {
|
||||
"namespace": "icons",
|
||||
"dataEncoding": "base64"
|
||||
},
|
||||
"heart": {
|
||||
"icon": "data:image/png;base64,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"
|
||||
},
|
||||
"smallheart": {
|
||||
"icon": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAsTAAALEwEAmpwYAAAE5ElEQVR4nO3dMY5URxQF0NdGTtAQY3sB3gALsNgTJBapneA9WXbOBryAARIiRABBO5i2Ru2hLv9P9W9V9ZyT8nveVfXcgZGaelUAAADAEHbf+POrqnpaVY+r6vsTz/5SVZ+q6n1Vfbzn15BPvvtalC8V5Ieq+unEoVquq+rdytfId0u+Ps183zVecFXnC1eHWVcrnpfvmHx9mvlaBXm6XZamNTPl65sp38KZrYI83jBIy5qZ8vXNlG/hzFZBTv0L0RJrZsrXN1O+hTNbBQFKQSBSEAgUBAIFgUBBIFAQCBQEAgWBQEEgUBAIFAQCBYFAQSBQEAgUBAIFgUBBIFAQCFoF+XLWFOtnytc3U76FM1sF+bRhkJY1M+XrmynfwpmtgrzfMEjLmpny9c2Ub+HMR42HP1fVvqqebBbn2HVVfVjxvHzH5OvTzOfy6jb5+jyEfAAAAAAAAADwwEz9UZP9fv9LVb2sqmd1szb4lN5V1Zuqer3b7f6659dwfpOf37R70vf7/a9V9ds2cY5HVdWr3W73+8rXOb/DqJr4/FoFuaqqnzeL83X/1MKfhIeffH/Wt/8GPJV9VT1f8ZPQ+f1vZE16frPuSX9Z53tz6zDrxYrnnd+xac9v1j3pzzZLcZqZzq9v5jDnN+ue9FP/QrnEjyuedX53TXl+bjWBQEEgUBAIFAQCBYFAQSBQEAgUBAIFgUBBIFAQCBQEAgWBQEEgUBAIFAQCBYFAQSBQEAhm3ZO+6g6oE3m74lnnd9eU5zfrnvQ3m6U4zUzn1zdzmPObdU/667q5jOxc9oeZSzm/Y9OeX6sgH+vmOsZzua4V98sebuh7Ved5k/+7OvPvFa9xfremPr9LuLz6Rd1cSrbm3qUl3tbNPwv+mPny5cT52ZMOAAAAAAAAAOtcwkdNht3zLZ896adycXu+5bsdVfakn8TF7PmW7+7Isie92yXt+ZbvmD3pJ3BJe77l65s5zPefPenLrfn/EvLdZU86XBoFgUBBIFAQCBQEAgWBQEEgUBAIFAQCBYFAQSBQEAgUBAIFgUBBIFAQCBQEAgWBQEEgsCd9uTV7vuW7y570Tpe051u+vpnDfP/Zk77M2j3f8h2zJ73TRe35lu+IPen3dPF7vuWzJx0AAAAAAAAALsvUHzWpwfPZQz7/+zvtnvQaPJ895EemfX+n3JNeg+ezh/yrpnx/Z92TPno+e8j7Zg6Tb9Y96aPns4e8b+Yw+Wbdkz56PnvI+2YOk8+tJhAoCAQKAoGCQKAgECgIBAoCgYJAoCAQKAgECgKBgkCgIBAoCAQKAoGCQKAgECgIBAoCwax70kfPZw9538xh8s26J330fPaQ980cJt+se9JHz2cPed/MYfJNuSe9Bs9nD/kd076/Lq9uu/g97jX4+dX4+QAAAAAAAADggfFRkzb5+lxEPnvSl5Gvz7T5Wp/mvarzhavDrKsVz8t3TL4+zXz2pG8zU76+mcPksyd9m5ny9c0cJp896dvMlK9v5jD53GoCgYJAoCAQKAgECgKBgkCgIBAoCAQKAoGCQKAgECgIBAoCgYJAoCAQKAgECgKBgkCgIBDYk77NTPn6Zg6Tz570bWbK1zdzmHz2pG8zU76+mcPke9R4+HPd7N9+slmcY9dV9WHF8/Idk69PM5/Lq9vk6/MQ8gEAAADn8i9uSXT/dv6GSgAAAABJRU5ErkJggg=="
|
||||
},
|
||||
"yes": {
|
||||
"icon": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFHUlEQVR4nO3dQY5UZRQF4FsaJ6Qdoy7ADbAA455gYpjqBPdkdM4GXADCxBFhIINy0G2k0u+efsVfr/ir+L4h3e09eckRiOU7VQAAAMAUdg98/aaqHlfVo6r66sS331fVu6p6U1VvP/KfIZ98H2tVvlSQb6rquxOH6ryqqtdH/ox8/5NvTJvvi+YHbup84eru1s0R3y/fIfnGtPm6gjzeLkvrmJvyjd2Ub+XNriCPNgzSOeamfGM35Vt5syvIqf9CtMYxN+UbuynfyptdQYBSEIgUBAIFgUBBIFAQCBQEAgWBQEEgUBAIFAQCBYFAQSBQEAgUBAIFgUBBIFAQCBQEgq4g78+a4vib8o3dlG/lza4g7zYM0jnmpnxjN+VbebMryJsNg3SOuSnf2E35Vt78svnmf6pqX1Vfbxbn0Kuq+vuI75fvkHxj2nxeXt2Tb8znkA8AAAAAAAAAPjM+atKTb8xwvv1+/0NVPauqJ3U7C31Kr6vqZVW92O12v3ffZCd9HfnGHJ1vv9//VFU/bxPn8FRVPd/tdr8sfbEryE1Vfb9ZpGV/1vp/08h339Xku/ud47d6+E84p7Kvqh+Xfiexk77NTfnGbj6r85Wj7m49XfqCnfRtbso3dvPJZimOvGknfZub8o3dPPVfyNf4dukXvdUEAgWBQEEgUBAIFAQCBYFAQSBQEAgUBAIFgUBBIFAQCBQEAgWBQEEgUBAIFAQCBYFAQSCwk77NTfnGbh77jq9T+GvpF+2kb3NTvrGbLzdLceRNO+nb3JRv7OaLun2Z27ns727e0xXkbd2+LvJcXtVx72+V79BV5bt7w+HzOk9J/nv16B+LWR744alfblzyXXW+u1eQPq3bl7otvrdqwF91+8eqX9PLqwEAAAAAAACAD/moSe/q882wQ/6AT/787KSvc3X5ZtkhD6Z4fnbS17uafDPtkDemeX520re5OXu+aXbIG9M8Pzvp29ycPd80O+SNaZ6fnfRtbs6eb5od8sY0z89bTSBQEAgUBAIFgUBBIFAQCBQEAgWBQEEgUBAIFAQCBYFAQSBQEAgUBAIFgUBBIFAQCBQEAjvp29ycPd80O+SNaZ6fnfRtbs6eb5od8sY0z89O+jY3Z883zQ55Y5rnZyd9navKN9MOeWOa5+fl1b2rz3cBO+RTPz8AAAAAAAAA+PzEj5rY0bZDPuAqPqrTFsSO9gE75GMudmd+sSB2tBfZIR9zkTvz3cfd7WiP3fT8xm5Ok68riB3tsZue39jNafJ1BbGjPXbT8xu7OU0+bzWBQEEgUBAIFAQCBYFAQSBQEAgUBAIFgUBBIFAQCBQEAgWBQEEgUBAIFAQCBYFAQSBQEAi6gtjRHrvp+Y3dnCZfVxA72mM3Pb+xm9Pk6wpiR3vspuc3dnOafIsFsaN9jx3yMRe7M7/m5dV2tO2Qf4yreHk1AAAAAAAAAPChh4Ymp/5P/XbIr/6jHJ88XyrIFDvVHTvkBy52hzyYIl9XkGl2qpfYIV90kTvkjWnydf8/yDQ71Q075GM35Vt5syvINDvVDTvkYzflW3mzK8g0O9UNO+RjN+VbedNbTSBQEAgUBAIFgUBBIFAQCBQEAgWBQEEgUBAIFAQCBYFAQSBQEAgUBAIFgUBBIFAQCBQEgq4g0+xUN+yQj92Ub+XNriDT7FQ37JCP3ZRv5c2uINPsVDfskI/dlG/lza4g0+xUL7FDfs/F7pA3psl3DS+vtkN+wS+HfsDs+QAAAIBz+RdDw2v5jDe3GQAAAABJRU5ErkJggg=="
|
||||
},
|
||||
"no": {
|
||||
"icon": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFCElEQVR4nO3dMY5URxQF0NeWnCBysBfgDbAAy3uCxCK1E7wny87ZgBcAJkckBO1g2sJN/7r+f6p7VPXnnJQZ3lNNXRBSU7cKAAAAGMIh/eLxePyxql5V1Yuqen7l2X9X1duqenM4HP645+/xtKqeVdWTqvr2WoudfK6qT1X1oao+3vP3sF/HfiPcv2ZAjsfjz1X1y5WXWhxVVa8Ph8OvG7/veVV9f4N9lryruwPdwn5fbN5vlPu3GJBTcn9v/foNHKvqpw1/kzytqh9uuM+Sv2r9n4T2u7R6v5Hu3zeNb3hVD7dcnWa93PD1z261yJVm2q9v5jD3rxWQF7fbpWnLzCc32+I6M+3XN3OY+9cKyLX/QbTGdxu+9tr/oLz2TPv1zRzm/rUCApSAQCQgEAgIBAICgYBAICAQCAgEAgKBgEAgIBAICAQCAoGAQCAgEAgIBAICgYBAICAQtAKy9Y2la3i/4Ws/32yL68y0X9/MYe5fKyBvb7hIy5aZn262xXVm2q9v5jD3rxWQN3X3mNZDOZ5mrvXhVotcaab9+mYOc/8WA3J6Ye51PcyS/z79+OeG7/lYd89ZPpR3te19Wfud27TfSPdvzePVL+vuUa0t71at8b7u/lr7zePV97L7/Sa4fwAAAAAAAADwyPxfUeIMH0XQ4+787mPV+aWA6NE+jaod9rg7vzPN82sFRI/2VyNrRz3uzm/R4vm1/j+IHu1ze+txd34rZ7YCoke7b6bz65s5zPm1AqJH+9Keetyd38qZXjWBQEAgEBAIBAQCAYFAQCAQEAgEBAIBgUBAIBAQCAQEAgGBQEAgEBAIBAQCAYFAQCAQEAhaAdGjfWlPPe7Ob+XMVkD0aPfNdH59M4c5v1ZA9Gif21uPu/NbObMVED3aX+yux935XWie3x4erx65R9v57fj8AAAAAAAAAODxmfqjJjX4fnrI5//5TtuTXoPvp4f8zLQ/3yl70mvw/fSQL5ry5ztrT/ro++kh75s5zH6z9qSPvp8e8r6Zw+w3a0/66PvpIe+bOcx+XjWBQEAgEBAIBAQCAYFAQCAQEAgEBAIBgUBAIBAQCAQEAgGBQEAgEBAIBAQCAYFAQCAQEAhm7UkffT895H0zh9lv1p700ffTQ943c5j9Zu1JH30/PeR9M4fZb8qe9Bp8Pz3kF6b9+Xq8uk0PeZ/d/3wBAAAAAAAA4PGZ+qMmesidX4d996TrIT/j/PrsqyddD/ki59dnVz3pesj7Zjq/lTNn7UnXQ9430/mtnDlrT7oe8r6Zzm/lTK+aQCAgEAgIBAICgYBAICAQCAgEAgKBgEAgIBAICAQCAoGAQCAgEAgIBAICgYBAICAQCAgEs/ak6yHvm+n8Vs6ctSddD3nfTOe3cuasPel6yPtmOr+VM6fsSddDfsH59dlnT7oecufXQU86AAAAAAAAAGwWP2qiR7v7owj2m7zHvRkQPdpnNveQl/3+a9oe98WA6NFetLqHvOy3ZMoe99bH3fVo9820X9/MYe5fKyB6tPtm2q9v5jD3rxUQPdp9M+3XN3OY++dVEwgEBAIBgUBAIBAQCAQEAgGBQEAgEBAIBAQCAYFAQCAQEAgEBAIBgUBAIBAQCAQEAgGBoBUQPdp9M+3XN3OY+9cKiB7tvpn265s5zP1rBUSPdt9M+/XNHOb+LQZEj/aFTT3kZb+vTdvjvubxaj3aO30cugbfb4L7BwAAADyUfwDmcbblze7mOAAAAABJRU5ErkJggg=="
|
||||
},
|
||||
"happy": {
|
||||
"icon": "data:image/png;base64,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"
|
||||
},
|
||||
"sad": {
|
||||
"icon": "data:image/png;base64,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"
|
||||
},
|
||||
"confused": {
|
||||
"icon": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFd0lEQVR4nO3dMW5TWxAG4N8PvQaFmsdbABvIAhB7ShqUFpqwJwR9NsACAjRUiAKK+wob8UxyhntzbMuHfF/LdWY01u8QyZpJAAAAgKOw+s2/nyR5nORhkr93XPt7kq9JPiX5csefoT/93dWs/qqA/JPk3x031XKd5OPC1+jvJ/31afb3V+MFJzlcc9nUOlnwvP626a9Ps79WQB7vr5emJTX111dTfzNrtgLycI+NtCypqb++mvqbWbMVkF3/QTTHkpr666upv5k1WwEBIiBQEhAoCAgUBAQKAgIFAYGCgEBBQKAgIFAQECgICBQEBAoCAgUBgYKAQEFAoCAgUBAQKLQC8v2gXSyvqb++mvqbWbMVkK97bKRlSU399dXU38yarYB82mMjLUtq6q+vpv5m1nzQePhbkinJo721s+06yecFz+tvm/76NPuzvLpNf33uQ38AAAAAAAAAcM8M/VWTaZqeJTlPcpr12eBd+pjkKsnlarV6e8efYX6Dz2/YO+nTNL1I8nI/7WyXSnKxWq1eLXyd+W1KZeD5tQJykuTp3tq53fvM/CTcfPK9ye9/A+7KlOT5gk9C8/ulZAad36h30s9zuDc3m1pnC543v23Dzm/UO+mne+tiNzXNr6/m0cxv1Dvpu/6Dco4nC541v5uGnJ+tJlAQECgICBQEBAoCAgUBgYKAQEFAoCAgUBAQKAgIFAQECgICBQGBgoBAQUCgICBQEBAoCAgURr2TvmgH1I58WPCs+d005PxGvZN+tbcudlPT/PpqHs38Rr2Tfpn1MrJDmTY15zK/bcPOrxWQL1mvYzyU6yzYL7vZ0HeRw7zJP1ZnvlvwGvP7aej5/QnLq8+yXkq2ZO/SHB+y/m/B65GXL1fMz510AAAAAAAAAFhm6K+aRH/6u7s/+0569Pd/+uvT7K/1bd6THK65bGqdLHhef9v016fZ36h30vXXV1N/M2uOeiddf3019Tez5qh30vXXV1N/M2vaagIFAYGCgEBBQKAgIFAQECgICBQEBAoCAgUBgYKAQEFAoCAgUBAQKAgIFAQECgICBQGBgoBAYdQ76frrq6m/mTVHvZOuv76a+ptZc9Q76frrq6m/mTUfNB7+lvV960d7a2fbdZLPC57X3zb99Wn2Z3l1m/763If+AAAAAAAAAOCeGfqrJtM0PUtynuQ067PBu/QxyVWSy9Vq9faOP8P8Bp/fsHfSp2l6keTlftrZLpXkYrVavVr4OvPblMrA82sF5CTJ0721c7v3mflJuPnke5Pf/wbclSnJ8wWfhOb3S8kMOr9R76Sf53Bvbja1zhY8b37bhp3fqHfST/fWxW5qml9fzaOZ36h30nf9B+UcTxY8a343DTk/W02gICBQEBAoCAgUBAQKAgIFAYGCgEBBQKAgIFAQECgICBQEBAoCAgUBgYKAQEFAoCAgUBAQKIx6J33RDqgd+bDgWfO7acj5jXon/WpvXeympvn11Tya+Y16J/0y62VkhzJtas5lftuGnV8rIF+yXsd4KNdZsF92s6HvIod5k3+szny34DXm99PQ8/sTllefZb2UbMnepTk+ZP3fgtcjL1+umJ876QAAAAAAAACwTPlVE3e03SHv8EfMrxkQd7S3uEPeZ9j53RoQd7Rv5Q55nyHn1/q6uzvafTXNr6/m0cyvFRB3tPtqml9fzaOZXysg7mj31TS/vppHMz9bTaAgIFAQECgICBQEBAoCAgUBgYKAQEFAoCAgUBAQKAgIFAQECgICBQGBgoBAQUCgICBQEBAotALijnZfTfPrq3k082sFxB3tvprm11fzaObXCog72n01za+v5tHM79aAuKN9gzvkfYad35zl1e5ou0N+F/dhfgAAAMCh/AecHIXJK5h09QAAAABJRU5ErkJggg=="
|
||||
},
|
||||
"angry": {
|
||||
"icon": "data:image/png;base64,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"
|
||||
},
|
||||
"asleep": {
|
||||
"icon": "data:image/png;base64,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"
|
||||
},
|
||||
"surprised": {
|
||||
"icon": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFc0lEQVR4nO3dP25UVxQG8G8SpUFODWQBbMALiNiT3SC30Jg9Iei9ARbAnyYVogjFpJhBycR+h/d8543uNb9fmzHn07E+EyTrngQAAADowuYH//0syeMkj5L8duTZ35J8TfI5yZf7/AHb7fbPJJdJzpM8OV60JMmnJDdJrjebzdt7/hn2N/j+qoI8SfLHkUNN+ZDdQmfbbrcvkrxcJ87hqCRXm83m1cKvs7/9qAy8v6mCnCV5tlqcu73PzJ+E+598b/LjvwGPZZvk+YKfhPb3v5EZdH+/THz48bpZmmde5nTf3OxnXSz4vP0dGnZ/UwV5tGKQKUtmnq+W4jgz7a9tZjf7myrIsf9BNMeSmcf+B+UcTxd81v5uG3J/UwUBoiBQUhAoKAgUFAQKCgIFBYGCgkBBQaCgIFBQECgoCBQUBAoKAgUFgYKCQEFBoKAgUFAQKEwV5NtJUyyfuegNqCP5uOCz9nfbkPubKsjXFYNMWTLzZrUUx5lpf20zu9nfVEE+rxhkypKZ19k9RnYq2/3Muezv0LD7myrIl+yeYzyVD1nwvuz+hb6rnOab/P3pzHcLvsb+/jX0/h7C49UX2T1KtuTdpTk+Zve/Ba9Hfny5Yn9t+wMAAAAAAACAn8/Qv2oS+eS7v4d9Jz3y/Zd8bSbzTf0271lOFy77WWcLPi/fIfnaTOYb9U66fG0z5Zs5c9Q76fK1zZRv5sxR76TL1zZTvpkzvWoCBQWBgoJAQUGgoCBQUBAoKAgUFAQKCgIFBYGCgkBBQaCgIFBQECgoCBQUBAoKAgUFgYKCQGHUO+nytc2Ub+bMUe+ky9c2U76ZM0e9ky5f20z5Zs78deLDf2d33/r31eIc+pDkrwWfl++QfG0m83m8epp8bX6GfAAAAAAAAADwk/GrJtOa82232z+TXCY5z+6s8TF9SnKT5Hqz2by955/R9f7SQT530udZnG+73b5I8nKdOIejklxtNptXC7+u6/2lk3xTBTlL8my1OHd7n/k/abrOt/+b401+/Df0sWyTPF/wN0nX+0tH+dxJX2fmZU5XjuxnXSz4fO/76yafO+nrzDxfLcVxZva+v27yuZO+zsxj/4N8jqcLPtv7/rrJ51UTKCgIFBQECgoCBQWBgoJAQUGgoCBQUBAoKAgUFAQKCgIFBYGCgkBBQaCgIFBQECgoCBQUBArupK8zc+kbUMfwccFne99fN/ncSV9n5s1qKY4zs/f9dZPPnfR1Zl5n95jbqWz3M+fqfX/d5JsqyJfsnmM8lQ9Z9n5r1/n2Lxxe5TQl+f706LsFX9P1/tJRPo9XTzvW49UX2T3qtuTdqjk+Zve/Va89Xn0v7qQDAAAAAAAAwGJD/6qJO+T21+Bh30l3h/yA/bV5WHfS3SG/k/21eVB30t0hb5tpfzNnjnon3R3ytpn2N3PmqHfS3SFvm2l/M2d61QQKCgIFBYGCgkBBQaCgIFBQECgoCBQUBAoKAgUFgYKCQEFBoKAgUFAQKCgIFBQECgoCBQWBwqh30t0hb5tpfzNnjnon3R3ytpn2N3PmqHfS3SFvm2l/M2cOeSfdHfJb7K/Nw7yT7g65/TVwJx0AAAAAAAAAFhv6V03SeT53yMf//g57Jz2d53OH/MCw398h76Sn83zukN9pyO/vqHfSe8/nDnnbzG7yjXonvfd87pC3zewm36h30nvP5w5528xu8nnVBAoKAgUFgYKCQEFBoKAgUFAQKCgIFBQECgoCBQWBgoJAQUGgoCBQUBAoKAgUFAQKCgIFBYHCqHfSe8/nDnnbzG7yjXonvfd87pC3zewm36h30nvP5w5528xu8g15Jz2d53OH/JZhv78er57mDnmbB//9BQAAAE7oHzt4fMP9uDtRAAAAAElFTkSuQmCC"
|
||||
},
|
||||
"silly": {
|
||||
"icon": "data:image/png;base64,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"
|
||||
},
|
||||
"fabulous": {
|
||||
"icon": "data:image/png;base64,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"
|
||||
},
|
||||
"meh": {
|
||||
"icon": "data:image/png;base64,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"
|
||||
},
|
||||
"tshirt": {
|
||||
"icon": "data:image/png;base64,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"
|
||||
},
|
||||
"rollerskate": {
|
||||
"icon": "data:image/png;base64,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"
|
||||
},
|
||||
"duck": {
|
||||
"icon": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFW0lEQVR4nO3dMXIcVRQF0DdQJC4R27AAFoAXQLEnO6GcQmL2REFuFsACZJwQuRzgYAhGYKZm/tP/+t1Tr0fnpG7p36ruK1tlqW8EAAAAUMLunj+/iYinEfEkIr5Y+OyPEfEhIt5FxPuHfIL9fv9dRLyMiOcR8Wy5aBER8WdEvImI17vd7teHfILq+aL4/Y0C+bKCPIuIrxcO1XIbhxvebb/f/xARP64T5/ioiHi12+1+Gvqg4vmi+P2NIvlaBbmJiG9Wi3PeH9H5lebuK/Mvcf/fgEvZR8T3vV+pq+eL4vc3CuX7rHHx03WzTJ/5Mi738MXdWS8Grq+er/r9LZOvVZAnKwZpGTnz+Wopljmzer7q97dMvlZBlv6GqMfImUt/w9vjq4Frq+erfn/L5GsVBAgFgZSCQEJBIKEgkFAQSCgIJBQEEgoCCQWBhIJAQkEgoSCQUBBIKAgkFAQSCgIJBYGEgkCiVZCPF00xfuboO5aW8Hbg2ur5qt/fMvlaBfmwYpCWkTPfrJZimTOr56t+f8vkaxXk3YpBWkbOfB2Hl6Vdyv7uzF7V81W/v2XytQryPg6vY7yU2xh4f+vdGwRfxWUewn9f7flb7wdUzxfF728UyncNL69+EYeXpo28F6rH2zj8s+XnyZdXl80Xxe9v1M8HAAAAAAAAAI9M+qMm1Xe+5bOTPmFuJ736zrd8n44KO+mzxnbSq+98y3d6ZNhJnzW0k15951u+Y3bS5w3tpFff+ZZv7swyO+QLXLuUoZ306jvf8p2ykz7HTjqMUhBIKAgkFAQSCgIJBYGEgkBCQSChIJBQEEgoCCQUBBIKAgkFgYSCQEJBIKEgkFAQSCgIJFoFqb7zLd8pO+lzhnbSq+98yzd3Zpkd8gWuXcrQTnr1nW/5jtlJn9e/k15951u+I3bS5z1sJ736zrd8dtIn2EkHAAAAAAAAgGH3DU2W/q/+6jvk8m0/X1aQEjvVLdV3yOX7dFRsOF+rIGV2qs+pvkMu3+mRsdF8rd8HKbNT3VB9h1y+Y5vN1ypImZ3qhuo75PLNnVkmX6ul364YJPN7z0X7/f6Sv633n91u1/VVTb7ztpjPW00goSCQUBBIKAgkFAQSCgIJBYGEgkBCQSChIJBQEEgoCCQUBBIKAgkFgYSCQEJBIKEgkFAQSLQKUmanuqH6Drl8pzaZr1WQMjvVDdV3yOWbO7NMvlZByuxUN1TfIZfv2GbztQpSZqf6nOo75PId2XS+a3h5ddkdcvmuOx8AAAAAAAAAPD7X8KMmdr6vNF8UeP7spHccFRve+W5+UPF8UeT5s5PeZ7M732cvLp4vCj1/dtL7bHbnu6F6vjLPn530dc6Ub+7MMs9fqyBLf0PUY+TMpb+h7DHy+wjynRrJV+b581YTSCgIJBQEEgoCCQWBhIJAQkEgoSCQUBBIKAgkFAQSCgIJBYGEgkBCQSChIJBQEEgoCCQUBBJ20vttcue7oXq+Ms+fnfR1zpRv7swyz5+d9D6b3fluqJ6vzPNnJ/1+m975Pqd6vij0/F3Dy6vL7mjLN71DXvr5AwAAAAAAAIDHZ9M/ahLyyfdw172THvL9n3xzmvlaP817E5cLF3dn3QxcL98x+eY08211J12+uTPl6zxzqzvp8s2dKV/nmVvdSZdv7kz5Os/0VhNIKAgkFAQSCgIJBYGEgkBCQSChIJBQEEgoCCQUBBIKAgkFgYSCQEJBIKEgkFAQSCgIJBQEElvdSZdv7kz5Os/c6k66fHNnytd55lZ30uWbO1O+zjM/b1z8dxz2rb9cLc6x24j4a+B6+Y7JN6eZz8ur2+Sb8xjyAQAAAJfyD92s8bBtlgWFAAAAAElFTkSuQmCC"
|
||||
},
|
||||
"house": {
|
||||
"icon": "data:image/png;base64,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"
|
||||
},
|
||||
"tortoise": {
|
||||
"icon": "data:image/png;base64,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"
|
||||
},
|
||||
"butterfly": {
|
||||
"icon": "data:image/png;base64,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"
|
||||
},
|
||||
"stickfigure": {
|
||||
"icon": "data:image/png;base64,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"
|
||||
},
|
||||
"ghost": {
|
||||
"icon": "data:image/png;base64,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"
|
||||
},
|
||||
"sword": {
|
||||
"icon": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAsTAAALEwEAmpwYAAAE40lEQVR4nO3dMY4UVxQF0NeWnCBysBfgDbAAy3uCBJHaCd6TZedswAsAkyMSgnYwY1mjoS5V86ta7/eckzLwrrq4HiON6lYBAAAALZy+8etPq+pZVT2pqu93vv2lqj5X1ceq+vTAP6N1vvP5/HNVvaqqF1X1fL9oVVX1T1W9q6q3p9Ppzwf+Ga0/v2qQLxXkeVX9uHOoJe/r5oFv0Trf+Xx+XVW/HhPn7qmqenM6nX7b+Ptaf37VJN9SQZ5W1U+Hxfm6v2v9f2la57v9zvFHffs79F7OVfXLhu8krT+/apTvu4UvfnZsluGb3fO9qsuVo25vvdzw9d0/vzb5lgry5MAgS7bc7J7vxWEp9rnZ/fNrk2+pIHv/g2iNLTe759v7H+Rr/LDha7t/fm3yLRUEKAWBSEEgUBAIFAQCBYFAQSBQEAgUBAIFgUBBIFAQCBQEAgWBQEEgUBAIFAQCBYFAQSBYKsiXi6bYfrN7vq3vgNrDhw1f2/3za5NvqSCfDwyyZMvN7vneHZZin5vdP782+ZYK8vHAIEu23Oye723dvMztUs63N9fq/vm1ybdUkE918zrGS3lf297f2jrf7RsO39RlSvLfq0f/2vB7Wn9+1Sifl1cv2+vl1S/r5qVuW95btcaHuvnfqt+9vPpB9sgHAAAAAAAAAI+MHzVZZid9zFU8Xzvp69hJHzPt87WTvp6d9DFTPl876cfctJM+drNNPjvpx9y0kz52s00+O+nH3LSTPnazTT5vNYFAQSBQEAgUBAIFgUBBIFAQCBQEAgWBQEEgUBAIFAQCBYFAQSBQEAgUBAIFgUBBIFAQCOykH3PTTvrYzTb57KQfc9NO+tjNNvnspB9z00762M02+eykr2Mnfcy0z9fLq5fZSR9z9c8XAAAAAAAAAB4fP2qyzE76mKt4vnbS17GTPmba52snfT076WOmfL520o+5aSd97GabfHbSj7lpJ33sZpt8dtKPuWknfexmm3zeagKBgkCgIBAoCAQKAoGCQKAgECgIBAoCgYJAoCAQKAgECgKBgkCgIBAoCAQKAoGCQKAgENhJP+amnfSxm23y2Uk/5qad9LGbbfLZST/mpp30sZtt8tlJX8dO+phpn6+XVy+zkz7m6p8vAAAAAAAAADw+U/+oSfcdcvnm33Gfdie9+w65fP+fqol33KfcSe++Qy7f/ZM16Y77rDvp3XfI5btr2h33WXfSu++Qyzd2s83fv1l30rvvkMt335Q77t5qAoGCQKAgECgIBAoCgYJAoCAQKAgECgKBgkCgIBAoCAQKAoGCQKAgECgIBAoCgYJAoCAQzLqT3n2HXL77ptxxn3UnvfsOuXxjN9v8/Zt1J737Drl8d0274z7lTnr3HXL57ph6x/0aXl7ddodcvqvfcQcAAAAAAACAR2bqHzWp5vnskM//fKfdSa/m+eyQ3zHt851yJ72a57ND/lVTPt9Zd9K757NDPnazTb5Zd9K757NDPnazTb5Zd9K757NDPnazTT5vNYFAQSBQEAgUBAIFgUBBIFAQCBQEAgWBQEEgUBAIFAQCBYFAQSBQEAgUBAIFgUBBIFAQCGbdSe+ezw752M02+WbdSe+ezw752M02+WbdSe+ezw752M02+abcSa/m+eyQ3zPt8/Xy6mVXv+NezT+/6p8PAAAAuJR/ATEXlVHvyECcAAAAAElFTkSuQmCC"
|
||||
},
|
||||
"giraffe": {
|
||||
"icon": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAsTAAALEwEAmpwYAAAE+UlEQVR4nO3dPY4cVRQF4NtIJBY5PwtgA14AYk92gpxCYvaEIPcGWICNc+TEQRP0IGs09U6/mqqy3+v5vtRj36PSnBEW7TpVAAAAwBBO6RfP5/NPVfWyqp5X1Xc73/6nqt5U1evT6fTnY/6A0fNV1TdV9W1VPauqr/cKdudjVX2oqvdV9e8j/wz5ruRrFuR8Pv9SVb/uHGrxVFW9Op1Ov636TYPnq0thfzggz5K3dSn0GvJ90sy3WJC7n8x/tH79AOeq+rn3J/Xo+eryk+/HA/Ms+bv6f1LL99Bivq8aX/yyPt83X93derHi60fP9+1RQXa6KV/nzVZBnh8YpGXNzdHzPTssxT435eu82SrI3n/h7fH9iq8dPd/ef6Hc+6Z8nTdbBQFKQSBSEAgUBAIFgUBBIFAQCBQEAgWBQEEgUBAIFAQCBYFAQSBQEAgUBAIFgUBBIFAQCFoFWfsOoz28W/G1o+f7eFiKfW7K13mzVZA3BwZpWXNz9HwfDkuxz035Om+2CvK6Li9L+1zOdzd7jZ7v/VFBdropX+fNxYLcvUHwVX2eb8L/X+35V+9vGD1fXd7Q9/agPEve1rr338p3XzNfz8urX9TlpWlr3gvV411d/rPl940vrx42Xw3w8uUr5NuWDwAAAAAAAACemGtDmEP/r3476Tf/UY4vni8VZIid6hY76fdMu0MeDJGvVZBhdqqX2ElfNOUOecMw+Vr/HmSYneoGO+nbbsrXebNVkGF2qhvspG+7KV/nzVZBhtmpbrCTvu2mfJ03vdUEAgWBQEEgUBAIFAQCBYFAQSBQEAgUBAIFgUBBIFAQCBQEAgWBQEEgUBAIFAQCBYFAQSBoFWSYneoGO+nbbsrXebNVkGF2qhvspG+7KV/nzVZBhtmpbrCTvu2mfJ03WwUZZqd6iZ30B6bdIW8YJt8tvLzaTvrEL4e+YvR8AAAAAAAAAPDE3MJHTeyk3+5HOb54PjvpHafKTvpW0+azk97HTvp2U+azk97HTvp2U+azk37MzdGfn3ydN+2k97OTvs2U+bzVBAIFgUBBIFAQCBQEAgWBQEEgUBAIFAQCBYFAQSBQEAgUBAIFgUBBIFAQCBQEAgWBQEEgsJPez076NlPms5N+zM3Rn598nTftpPexk77dlPnspF9nJ327afPdwsur7aRP/HLoK0bPBwAAAAAAAABPzC181GTYnXT55t+Zt5PecaoesZMu36dTNfHOvJ30Pqt20uV7eLIm3Zm3k95n7U66fPdNuzNvJ/2Ym/JtuznM95+d9H5r/r2JfA9NuTPvrSYQKAgECgKBgkCgIBAoCAQKAoGCQKAgECgIBAoCgYJAoCAQKAgECgKBgkCgIBAoCAQKAoGd9H5rdtLle2jKnXk76cfclG/bzWG+/+yk91m7ky7ffdPuzNtJv271Trp890y9M38LL68ediddvpvfmQcAAAAAAACAJ+YWPmpi59vzeww76TuZeue7xfO7x076RtPufC/x/BbZSd9g2p3vBs+v86ad9GNuen7bbg7z/Oyk95ty57vB8+u86a0mECgIBAoCgYJAoCAQKAgECgKBgkCgIBAoCAQKAoGCQKAgECgIBAoCgYJAoCAQKAgECgKBnfR+U+58N3h+nTftpB9z0/PbdnOY52cnvc+0O98Nnl/nTTvp1029873E83vATvoj3PzOt+dnJx0AAACm8R/nWLbllDXkpAAAAABJRU5ErkJggg=="
|
||||
},
|
||||
"skull": {
|
||||
"icon": "data:image/png;base64,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"
|
||||
},
|
||||
"umbrella": {
|
||||
"icon": "data:image/png;base64,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"
|
||||
},
|
||||
"snake": {
|
||||
"icon": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFE0lEQVR4nO3dMY5bVRQG4GMQTTTUARbAAsgCIvaUNCgtNGFPCPqwABYwIQ1VlCIpTGHDYOx75r6571nnvfm+djxzfl35t8aSfU8EAAAAUMIu++F+v38eES8j4llEfDXz7D8j4k1EvN7tdr8+5A9UzxcRNxHxNCKeRMQXcwU7+hQRHyLiXUS8f+DfkO+efM2C7Pf7HyLix5lDXRwVEa92u91Pk36peL44FPabBfJcchuHQk8h351mvosFOb4y/9L6+QL2EfF97yt19XxxeOX7dsE8l/wR/a/U8p27mO+zxoNfxvWefHGc9WLC46vne7pUkJlmytc5s1WQZwsGaZkys3q+J4ulmGemfJ0zWwWZ+w1vj68nPLZ6vrnfUM49U77Oma2CAKEgkFIQSCgIJBQEEgoCCQWBhIJAQkEgoSCQUBBIKAgkFAQSCgIJBYGEgkBCQSChIJBQEEi0CjL1DqM5vJ3w2Or5Pi2WYp6Z8nXObBXkzYJBWqbMrJ7vw2Ip5pkpX+fMVkFex+GytGvZH2f2qp7v3VJBZpopX+fMiwU53iD4Kq7zJPznas/fen+her443NB3u1CeS25j2v238p1q5uu5vPpFHC5Nm3IvVI+3cfi35efBy6vL5osCly/fQ76xfAAAAAAAAADwyNiT3rb5PenVz69CPnvSO0bFBvekVz+/KvnsSe+zqT3p1c+vUj570vtsbU969fMrk8+e9GVmltnz3VD9/Mrka/2Ldc1v6/1rt9t1vWpUzxcR3y0apO33ngdVP79K+dxqAgkFgYSCQEJBIKEgkFAQSCgIJBQEEgoCCQWBhIJAQkEgoSCQUBBIKAgkFAQSCgIJBYGEgkDCnvR+W9qTXv38yuSzJ32ZmWX2fDdUP78y+exJ77O1PenVz69MPnvS77e5PenVz69SPnvS2za/J736+VXPBwAAAAAAAACPz30rsdbwUYmye77D+a3+/LKC2PN9HBX2pI9Y9fm1CmLP9/9Ghj3pI1Z7fq3vg9jzfcqe9DGrPb9WQez5Hpvp/MZmljm/VkHmfkPUY8rMud9Q9pjyfQTnd26V5+dWE0goCCQUBBIKAgkFgYSCQEJBIKEgkFAQSCgIJBQEEgoCCQWBhIJAQkEgoSCQUBBIKAgkFAQSrYLY833OnvQxqzy/VkHs+R6b6fzGZpY5v1ZB7Pk+ZU/6mNWeX6sg9nzfsSd9zKrPbwuXV1feo+38Nnx+AAAAAAAAAPD4bOGjJmX3fMtnT/pcNrfnW767UWFP+iw2s+dbvvORYU/6sC3t+ZbvlD3pM9jSnm/5xmaWef7Zk95vyvcl5DtnTzpsjYJAQkEgoSCQUBBIKAgkFAQSCgIJBYGEgkBCQSChIJBQEEgoCCQUBBIKAgkFgYSCQEJBIGFPer8pe77lO2dP+qAt7fmWb2xmmeefPel9pu75lu+UPemDNrXnW74T9qQ/0Ob3fMtnTzoAAAAAAAAAbMuqP2oS8sn3cNvekx7y/Zd8Y5r5Wp/mvYnrhYvjrJsJj5fvlHxjmvnWuiddvrGZ8nXOXOuedPnGZsrXOXOte9LlG5spX+dMt5pAQkEgoSCQUBBIKAgkFAQSCgIJBYGEgkBCQSChIJBQEEgoCCQUBBIKAgkFgYSCQEJBIKEgkFjrnnT5xmbK1zlzrXvS5RubKV/nzLXuSZdvbKZ8nTM/bzz4Yxz2W3+5WJxTtxHx14THy3dKvjHNfC6vbpNvzGPIBwAAAFzL3/Yj4OZvgj/VAAAAAElFTkSuQmCC"
|
||||
},
|
||||
"rabbit": {
|
||||
"icon": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAsTAAALEwEAmpwYAAAE50lEQVR4nO3dTW4UVxQF4FuRMkHMIVlAFgALiLInmERMkwnZU5TMYQFZAD9zxIRBZ2AH3O5+J1V+Va3Xpe8bGtv36prTsiW7ThUAAAAwhCn94+Fw+LmqXlbV86p6uvLsD1X1pqpeT9P01wM/x+OqelJVj6rq+7UWu/Wlqj5X1ceq+vSQT+B+fferAfZrBuRwOPxaVb+tvNTZUVX1apqm3xd+3NOq+nGDfc55Vzf/IWdzvyOL71eD7Hc2ILevfH+2/n0Dh6r6ZcEr4eOq+mnDfc75p2a+ErrfWbPvVwPt913jnV/W5b64dTvrxYL3f7LVIivNdL++mcPs1wrI8w0XaVky89FmW6wz0/36Zg6zXysga/9AOccPC9537R/Y1p7pfn0zh9mvFRCgBAQiAYFAQCAQEAgEBAIBgUBAIBAQCAQEAgGBQEAgEBAIBAQCAYFAQCAQEAgEBAIBgaAVkKXPMFrD+wXv+2WzLdaZ6X59M4fZrxWQNxsu0rJk5ufNtlhnpvv1zRxmv1ZAXtfNw8gu5XA7c66PWy2y0kz365s5zH5nA3L7hL5XdZkv8n+Pzvx7wcd8qpvHRV7Ku1rwfFn3O7HofjXQfnMeXv2ibh5KtuS5S3O8r5tvC/7Y68OX3e/6H14NAAAAAAAAANylJ71NT3qfXfyqiZ70efSk99GT3mlXPd/ud5ae9A576/l2v76Zw+ynJ32bme7XN3OY/fSkbzPT/fpmDrOfp5pAICAQCAgEAgKBgEAgIBAICAQCAoGAQCAgEAgIBAICgYBAICAQCAgEAgKBgEAgIBAICAR60reZ6X59M4fZT0/6NjPdr2/mMPvpSd9mpvv1zRxmPz3p8+hJ76Mn/QF23/Ptftf/8GoAAAAAAAAA4K6r7km33773qwF+1eRqe9Lt921U7XC/0pN+PLIW9Hzb73Rk7Wi/0pN+YmnPt/2O7W0/PemdM+3XN3P0/YbpSW99i3XJv4b7apqmWa9q9jtvL/tV1bNNF2l7e/8NnmoCgYBAICAQCAgEAgKBgEAgIBAICAQCAoGAQCAgEAgIBAICgYBAICAQCAgEAgKBgEAgIBBca0+6/U7taT896Z0z7dc3c/T99KTfs7Tn237H9rafnvQ7Fvd82+/I7vYrPelVtULPt/32vV8N8PBqAAAAAAAAAOAuPeltu+j5TtxPT/oarrrnu8X9juhJ73S1Pd/nuN9ZetI7XG3Pd4P7zZypJ32bmcP0fDe438yZrYCs/QPbHEv+HmH0/db+gXLtme43c6anmkAgIBAICAQCAoGAQCAgEAgIBAICgYBAICAQCAgEAgKBgEAgIBAICAQCAoGAQCAgEAgIBHrS57vKnu8G95s5U0/6NjOH6flucL+ZM/Wkz3O1Pd8N7jdzpp70/3fVPd/nuN8JPekPsPueb/fTkw4AAAAAAAAAy+hJb7NfHz3pK9llT7r9vo0qPenddtWTbr/TkaUnvcveetLtd0xP+gr21JNuv76Zw/Skt77FuuRfm301TdOsVzX7nbeX/arq2aaLtL29/wZPNYFAQCAQEAgEBAIBgUBAIBAQCAQEAgGBQEAgEBAIBAQCAYFAQCAQEAgEBAIBgUBAIBAQCPSkz2e/PnrSO+2pJ91+fTP1pN+zt550+x3Tk95hdz3p9juiJ/2Bdt+Tbj896QAAAMBK/gVsdTwSu+HRwQAAAABJRU5ErkJggg=="
|
||||
},
|
||||
"cow": {
|
||||
"icon": "data:image/png;base64,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"
|
||||
},
|
||||
"quarternote": {
|
||||
"icon": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAsTAAALEwEAmpwYAAAE8ElEQVR4nO3dQY4VZRQF4PtMnBDmoAtwAyzAuCeYEKY6wT0ZnbMBFwAyJ0wYPAfdxnTaOl3V/1/P+4rvm1pwT97LAUk6daoAAACAFk4P/PenVfWsqp5U1beTb3+pqs9V9bGqPj3y92id73w+/1hVr6rqRVU9nxetqqr+qqp3VfX2dDr9/sjfo/XnVw3ypYI8r6rvJ4da8r5uvvAtWuc7n8+vq+rnfeLcPVVVb06n0y8bf13rz6+a5FsqyNOq+mG3OP/tz1r/J03rfLd/c/xWD/8NPcu5qn7a8DdJ68+vGuX7ZuHhZ/tmGb7ZPd+rulw56vbWyw3Pd//82uRbKsiTHYMs2XKze74Xu6WYc7P759cm31JBZv+DaI0tN7vnm/0P8jW+2/Bs98+vTb6lggClIBApCAQKAoGCQKAgECgIBAoCgYJAoCAQKAgECgKBgkCgIBAoCAQKAoGCQKAgECgIBEsF+XLRFNtvds+39R1QM3zY8Gz3z69NvqWCfN4xyJItN7vne7dbijk3u39+bfItFeTjjkGWbLnZPd/bunmZ26Wcb2+u1f3za5NvqSCf6uZ1jJfyvra9v7V1vts3HL6py5Tkn1eP/rHh17T+/KpRPi+vXjbr5dUv6+alblveW7XGh7r536pfvbz6UWbkAwAAAAAAAICvjB81WWYnfcwhvl876evYSR9ztd+vnfT17KSPucrv1076PjftpI/dbJPPTvo+N+2kj91sk89O+j437aSP3WyTz1tNIFAQCBQEAgWBQEEgUBAIFAQCBYFAQSBQEAgUBAIFgUBBIFAQCBQEAgWBQEEgUBAIFAQCO+n73LSTPnazTT476fvctJM+drNNPjvp+9y0kz52s00+O+nr2Ekfc7Xfr5dXL7OTPubw3y8AAAAAAAAAfH38qMkyO+ljDvH92klfx076mKv9fu2kr2cnfcxVfr920ve5aSd97GabfHbS97lpJ33sZpt8dtL3uWknfexmm3zeagKBgkCgIBAoCAQKAoGCQKAgECgIBAoCgYJAoCAQKAgECgKBgkCgIBAoCAQKAoGCQKAgENhJ3+emnfSxm23y2Unf56ad9LGbbfLZSd/npp30sZtt8tlJX8dO+pir/X69vHqZnfQxh/9+AQAAAAAAAODrE3/UpPvOt3x20geM7aR33/mW799TZSd91Lad9O473/LdP1l20kdt2knvvvMt31120sdt2knvvvMt39jNNjvkE56dZdNOevedb/nus5M+xk46bKUgECgIBAoCgYJAoCAQKAgECgKBgkCgIBAoCAQKAoGCQKAgECgIBAoCgYJAoCAQKAgESwXpvvMt33120sds2knvvvMt39jNNjvkE56dZdNOevedb/nuspM+bv1Oevedb/nusJM+7nE76d13vuWzkz7ATjoAAAAAAAAAbGYnfdnh81X/H+X43/PZSV9xqg6Yr5rskAct8tlJX+dQ+arRDvmCNvnspK9ztHxtdsgnPDuLnfRBR8rXZod8wrOz2EkfdKR8bXbIJzw7i5102EpBIFAQCBQEAgWBQEEgUBAIFAQCBYFAQSBQEAgUBAIFgUBBIFAQCBQEAgWBQEEgUBAI7KSvd6R8bXbIJzw7i530QUfK12aHfMKzs9hJH3C0fG12yCc8O4ud9Ec6XL5qtEO+oE0+O+nLDp+vGrwc+gHd8wEAAACX8jdzZLbl0C/0iwAAAABJRU5ErkJggg=="
|
||||
},
|
||||
"eigthnote": {
|
||||
"icon": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFM0lEQVR4nO3dQY4VVRgF4P+ZOCHMQRfgBliAcU8wMUx1gnsyOmcDLgBkTpgweA66JXa6799V/W61J5fvm1pwT27lgCSdOlUAAABAhNM9//1pVT2rqidV9e3ksz9X1aeq+lBVHx/4e0TnO5/PP1bVq6p6UVXP50Wrqqq/q+ptVb05nU5/PPD3iL6/CsjXFeR5VX0/OdTIu7p64XtE5zufzz9X1S/HxLl5VFW9Pp1Ov+78ddH3VyH5RgV5WlU/HBbnbn/V9j9povNd/83xe93/N/Qs56r6acffJNH3V0H5vhk8/OzYLBefmZ7vVT1eOer6rJc7nk+/v5h8o4I8OTDIyJ4z0/O9OCzFnDPT7y8m36ggs/9BtMWeM9Pzzf4H+Rbf7Xg2/f5i8o0KApSCQEtBoKEg0FAQaCgINBQEGgoCDQWBhoJAQ0GgoSDQUBBoKAg0FAQaCgINBYGGgkBDQaAxKsjnR02x/8z0fHu/ATXD+x3Ppt9fTL5RQT4dGGRkz5np+d4elmLOmen3F5NvVJAPBwYZ2XNmer43dfUxt8dyvj5zq/T7i8k3KsjHuvoc42N5V/u+3xqd7/oLh6/rcUry76dH/9zxa6Lvr4Ly+Xj12KyPV7+sq4+67flu1Rbv6+p/q37z8eoHmZEPAAAAAAAAAL4yftRkbPmd9PR8FfB+7aRvs9xOenq+Cnm/dtK3W2YnPT1fBb1fO+nHnJm+k56eL+b92kk/5sz0nfT0fDHv1076MWem76Sn54t5v75qAg0FgYaCQENBoKEg0FAQaCgINBQEGgoCDQWBhoJAQ0GgoSDQUBBoKAg0FAQaCgINBYGGgkDDTvoxZ6bvpKfni3m/dtKPOTN9Jz09X8z7tZN+zJnpO+np+WLer530bZbaSU/PV0Hv18erx5bfSU/PV+HvFwAAAAAAAAC+Pn7UZGz5nfRyf/fen530bZbbSS/39+Woau7PTvp2y+ykl/u7dWQN7s9O+jFn2iG/7MyY+7OTfsyZdsgvOzPm/uykH3OmHfLLzoy5P181gYaCQENBoKEg0FAQaCgINBQEGgoCDQWBhoJAQ0GgoSDQUBBoKAg0FAQaCgINBYGGgkBDQaBhJ/2YM+2QX3ZmzP3ZST/mTDvkl50Zc3920o850w75ZWfG3J+d9G2W2kkv9/df7f35ePXY8jvp5f4uvT8AAAAAAAAA+Mq0P2qSsFPdkW/tnfQKyDcsSMpO9fAXyfflqFpwJ71C8t1ZkKSd6jsflu/WkbXQTnoF5Rv9uHvMTvWAfDettpMek29UkJid6gnPzrJSvvSd9Jh8o4LE7FQPyHfbSjvpMfl81QQaCgINBYGGgkBDQaChINBQEGgoCDQUBBoKAg0FgYaCQENBoKEg0FAQaCgINBQEGgoCDQWBxqggMTvVA/LdttJOeky+UUFidqonPDvLSvnSd9Jj8o0KErNTPSDfTavtpMfku7MgSTvVd5HvhuV20iso35aPV8fuVMu39k565ecDAAAAAAAAgK+MnfSx5fNV/o9y/O/57KRvOKoWzFchO+SNiHx20rdZKl8F7ZAPxOSzk77NavlidsgnPDuLnfQLrZQvZod8wrOz2Em/0Er5YnbIJzw7i5102EtBoKEg0FAQaCgINBQEGgoCDQWBhoJAQ0GgoSDQUBBoKAg0FAQaCgINBYGGgkBDQaChINCwk77dSvlidsgnPDuLnfQLrZQvZod8wrOz2Em/wGr5YnbIJzw7i530B1ouXwXtkA/E5LOTPrZ8vgr4OPQ90vMBAAAAj+Uf73PYeRwCFc4AAAAASUVORK5CYII="
|
||||
},
|
||||
"pitchfork": {
|
||||
"icon": "data:image/png;base64,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"
|
||||
},
|
||||
"target": {
|
||||
"icon": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFeElEQVR4nO3dMY5bVRgF4N9INFH6BBbAAsgCEHtKGpQWmrAnBH1YAAtISB+lSWGKGYiMff/xm/dsnTvzfW08uUfP72QykuedKgAAACDC7o4/f1pVz6rqSVV9vfHZn6vqU1V9qKqP9/w7ovPt9/sfqupVVb2oqufbRauqqr+r6m1Vvdntdr/f8++Ivn4VkK8ryPOq+nbjUCPv6uYNXyI6336//6mqfr5MnMOjqur1brf7ZeHXRV+/Csk3KsjTqvruYnFO+6vO/5cmOt/td47f6u7v0FvZV9WPC76TRF+/Csr31eDFzy6bZfWZ6fle1fXKUbdnvVzw+vTrF5NvVJAnFwwysuTM9HwvLpZimzPTr19MvlFBtv6B6BxLzkzPt/UP5Of4ZsFr069fTL5RQYBSEGgpCDQUBBoKAg0FgYaCQENBoKEg0FAQaCgINBQEGgoCDQWBhoJAQ0GgoSDQUBBoKAg0RgX5fNUUy89Mz7f0GVBbeL/gtenXLybfqCCfLhhkZMmZ6fneXizFNmemX7+YfKOCfLhgkJElZ6bne1M3D3O7lv3tmedKv34x+UYF+Vg3j2O8lne17Pmt0flun3D4uq5Tkn8fPfrHgq+Jvn4VlM/Dq8e2enj1y7p5qNuS51ad433d/LfqVw+vvpct8gEAAAAAAADAIzP1R03Sd8jlm3/Hfdqd9PQdcvm+HFUT77hPuZOevkMu3/GRNemO+6w76ek75PIdmnbHfdad9PQdcvnWnRlz/826k56+Qy7fsSl33D3VBBoKAg0FgYaCQENBoKEg0FAQaCgINBQEGgoCDQWBhoJAQ0GgoSDQUBBoKAg0FAQaCgINBYHGrDvp6Tvk8h2bcsd91p309B1y+dadGXP/zbqTnr5DLt+haXfcp9xJT98hl+/A1DvuD+Hh1bE75PI9+B13AAAAAAAAAHhk2o+apO9op+er8I9KpF+/hHzDgqTvaKfnq5Cd75H065eS72RB0ne00/NV0M73KenXLynf6OPu6Tva6flidr4H0q9fTL5RQdJ3tNPzxex8D6Rfv5h8o/9iXfO3zf6z2+3O+lcjPV9VfX/RIGN/nvOi9OuXlM9TTaChINBQEGgoCDQUBBoKAg0FgYaCQENBoKEg0FAQaCgINBQEGgoCDQWBhoJAQ0GgoSDQUBBojAqSvqOdni9m53sg/frF5BsVJH1HOz1fzM73QPr1i8k3Kkj6jnZ6vpid74H06xeT72RB0ne00/NV0M73KenXLynfOQ+vjt3RTs9Xczy8Ovb6pecDAAAAAAAAgMfnrkmsGT4qYef7geargPuvK4id79ujauKd7+EXheerkPtvVBA73/87sibd+T754vB8FXT/jX4fxM73oWl3vgfS88Xcf6OC2Pled6Z8686Muf9GBdn6B6JzLDlz6x8oz7Hk9xHkO7YkX8z956km0FAQaCgINBQEGgoCDQWBhoJAQ0GgoSDQUBBoKAg0FAQaCgINBYGGgkBDQaChINBQEGgoCDRGBbHzfWzKne+B9Hwx99+oIHa+150p37ozY+6/UUHsfB+adud7ID1fzP03Koid7y+m3vk+JT1fBd1/D+Hh1bE72vI97J15AAAAAAAAAHh8pv6oSYXns0M+//s77U56heezQ35g2vd3yp30Cs9nh/ykKd/fWXfS0/PZIV93Zky+WXfS0/PZIV93Zky+WXfS0/PZIV93Zkw+TzWBhoJAQ0GgoSDQUBBoKAg0FAQaCgINBYGGgkBDQaChINBQEGgoCDQUBBoKAg0FgYaCQENBoDHrTnp6Pjvk686MyTfrTnp6Pjvk686MyTfrTnp6Pjvk686MyTflTnqF57NDfmTa99fDq8ce/I57hV+/ys8HAAAAXMs/4tr5dC58svsAAAAASUVORK5CYII="
|
||||
},
|
||||
"triangle": {
|
||||
"icon": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFX0lEQVR4nO3dsW5URxQG4LNBNJapTXiAvAAPYOWdoEG0SUPeJumjpOcF8gA2bqiQCywxKXYBrfAcZjz3LrP297Xc3fNrpN+LpfWcCAAAAGAKm+/8+2lEnEXESUQ8Xnj2TURcR8RVRHy443vIJ99dNeXLCvI0Ip4tHKrmIiLedb5Gvq/kG1PN91PlBadxuHCxm3Xa8bx8++QbU81XK8jZelmqembKNzZTvsaZtYKcrBikpmemfGMz5WucWSvI0r8QteiZKd/YTPkaZ9YKAoSCQEpBIKEgkFAQSCgIJBQEEgoCCQWBhIJAQkEgoSCQUBBIKAgkFAQSCgIJBYGEgkBCQSBRK8jNQVP0z5RvbKZ8jTNrBbleMUhNz0z5xmbK1zizVpCrFYPU9MyUb2ymfI0zH1Ue/hgRJSKerBZn30VEvO94Xr598o2p5nN5dZ18Yx5CPgAAAAAAAAB4YHzVpG44XynlPCJeRsTz2K41XtK7iHgbEW82m80/d3yPqc8vJshnT3qb7nyllFcR8ds6cfZHRcTrzWbze+frpj6/mCRfrSCnEfHLanFu91+0/6SZOt/uk+Pv+P4n9FJKRPza8Uky9fnFRPnsSV9n5ss4XDliN+tFx/Ozn980+exJX2fm89VSLDNz9vObJp896evMXPoX8hY/dzw7+/lNk8+tJpBQEEgoCCQUBBIKAgkFgYSCQEJBIKEgkFAQSCgIJBQEEgoCCQWBhIJAQkEgoSCQUBBIKAgk7ElfZ2bvHVBLuOx4dvbzmyafPenrzHy7WoplZs5+ftPksyd9nZlvYnuZ26GU3cxWs5/fNPlqBfkQ2+sYD+Ui+u5vnTrf7obD13GYkny+evTfjtdMfX4xUT6XV9ctdXn1i9he6tZzb1WLy9j+t+oPl1ffiT3pAAAAAAAAANDtqL9qYg+58xtwv/ek20O+x/mNuV970u0hv5XzG3Ov9qTbQz420/k1zjzWPen2kI/NdH6NM491T7o95GMznV/jTLeaQEJBIKEgkFAQSCgIJBQEEgoCCQWBhIJAQkEgoSCQUBBIKAgkFAQSCgIJBYGEgkBCQSChIJA41j3p9pCPzXR+jTOPdU+6PeRjM51f48xj3ZNuD/nYTOfXOPMo96TbQ/4N5zfmfu5Jt4fc+Q2wJx0AAAAAAAAAllVKOS+l/FVKuSzLu9y997l88h1dvlLKqxVC3eZT2e7slk++48hXts39dKCAn0M2N1k++Q6Vr/Z199n3aMu3T74x1Xy1gsy+R1u+sZnyNc68taWllEP+tdkXm82m6aeGfLeTb8xt+dxqAgkFgYSCQEJBIKEgkFAQSCgIJBQEEgoCCQWBhIJAQkEgoSCQUBBIKAgkFAQSCgIJBYGEgkCiVpDZ92jL9y35xtyar1aQ2fdoyzc2U77GmbWCzL5HW7598o3pzffl6sdD3G43cjWlfPL9kHyfQ56XUv4spVysEOxi996jlxvLJ98PyQcAAAAAAAAAD8/3VmKdRsRZRJxExOOFZ99ExHVEXEXEhzu+h3zy3VVTvqwgTyPi2cKhai6i/28A5PtKvjHVfLWvu5/G4cLFbtZpx/Py7ZNvTDVfrSBn62Wp6pkp39hM+Rpn1gpysmKQmp6Z8o3NlK9xZq0gS/9C1KJnpnxjM+VrnOlWE0goCCQUBBIKAgkFgYSCQEJBIKEgkFAQSCgIJBQEEgoCCQWBhIJAQkEgoSCQUBBIKAgkFAQStYLcHDRF/0z5xmbK1zizVpDrFYPU9MyUb2ymfI0zawW5WjFITc9M+cZmytc481Hl4Y+xXa7+ZLU4+y4i4n3H8/Ltk29MNZ/Lq+vkG/MQ8gEAAACH8j9qsKYdhQgxPgAAAABJRU5ErkJggg=="
|
||||
},
|
||||
"lefttriangle": {
|
||||
"icon": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFGklEQVR4nO3dPY4UVxQG0NuWnCBysBfgDbCAkfcECSK1E7wbO7fsnA14ATOQIxIknoPuAY+m6rpq6lVzX3NOOtV9P1Xpmx+p590IAAAAoIRD9sXW2lVEvIiIZxHxtPPstxHxJiJeHw6Hvx74Ho8j4klEPIqI73sFO/kYER8i4l1EvH/ge8g3eL7ZgrTWXkbEL51DTY6KiFeHw+HXla97GhE/7pBnynUcC72GfF8Mm2+yIKefHH/OfX0HLSJ+XvGT5HFE/LRjnin/xPLvhPLdN2S+72YufhHnK0ecZj1fcf2TvYJ0minftpll8s0V5NmOQeasmflotxR9Zsq3bWaZfHMF6f0H+RI/rLi29x9svWfKt21mmXxzBQFCQSClIJBQEEgoCCQUBBIKAgkFgYSCQEJBIKEgkFAQSCgIJBQEEgoCCQWBhIJAQkEgoSCQmCvI2jOMerhZce3H3VL0mSnftpll8s0V5M2OQeasmflhtxR9Zsq3bWaZfHMFeR3Hw9zOpZ1mLvVuryCdZsq3bWaZfJMFOZ1w+CrOU5Lbo0f/XvGa93E8LvJcrmPd+bLy3TVsviWHVz+P46Fua86tWuImjr9W/ebw6geRb5se+QAAAAAAAADgGzP0nvTq+aL+RyXku9Q96dXzRZE93wn5vrisPenV80WhPd8z5LvvovakV89XZs93h2t7GTLfqHvSq+crs+e7w7W9DJlv1D3p1fOV2fPd4dpehsznVBNIKAgkFAQSCgIJBYGEgkBCQSChIJBQEEgoCCQUBBIKAgkFgYSCQEJBIKEgkFAQSCgIJBQEEqPuSa+er8ye7w7X9jJkvlH3pFfPV2bPd4drexky36h70qvnK7Pnu8O1vQyZb8g96dXzRaE93zPku+sy96RXzxcFDl/+H/LZkw4AAAAAAAAAKwy9Jz2KfxTB/Rv/oybD7kmPInu057h/d9iTvtFF7SF3/ybZk77Bpe0hd/+2zSyTb9Q96WX2aM9w/7bNLJNv1D3pZfZoz3D/ts0sk8+pJpBQEEgoCCQUBBIKAgkFgYSCQEJBIKEgkFAQSCgIJBQEEgoCCQWBhIJAQkEgoSCQUBBIKAgkRt2TXmaP9gz3b9vMMvlG3ZNeZo/2DPdv28wy+Ubdk15mj/YM92/bzDL5htyTHoX2aE9x/+6xJ/0BLn4Pufs3/uHVAAAAAAAAAMB/2ZM+7+I/KuH52pPey7B7vud4vnfYk97BkHu+p3i+k+xJ32jIPd8zPN+FM+1J32dm9Xye78KZ9qTvM7N6Ps934UynmkBCQSChIJBQEEgoCCQUBBIKAgkFgYSCQEJBIKEgkFAQSCgIJBQEEgoCCQWBhIJAQkEgoSCQsCd9n5nV83m+C2fak77PzOr5PN+FM+1J32dm9Xye78KZ9qQvM+ye7yme7z32pD/At3J4tedrTzoAAAAAAAAA9NBau2qt/dFau2n93Zze+0o++YbL11p7uUOoKZ/acWe3fPKNka8dm/vpTAFvQy5usnzynSvfqHvS5btLvm1m8426J12+bTPlWzhzsqWttXP+t9lnh8Nh0XcN+abJt81UPqeaQEJBIKEgkFAQSCgIJBQEEgoCCQWBhIJAQkEgoSCQUBBIKAgkFAQSCgIJBYGEgkBCQSChIJAYdU+6fPfJt81kvlH3pMu3baZ8C2eOuiddvrvk22Ztvs9HP57jdLstR1PKJ99XyXcb8qq19ntr7XqHYNen9956uLF88n2VfAAAAMAZ/QsAIPjNRI6mtwAAAABJRU5ErkJggg=="
|
||||
},
|
||||
"chessboard": {
|
||||
"icon": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAsTAAALEwEAmpwYAAAE7klEQVR4nO3dMY5TZxQF4OtIaRA9JAvIBlhAlD1BE9EmDdlTlPRsIAuA0CMaCqcYRyNj/2f85trW+z3f1zJwnw46A0jmnSoAAABgFTYP/PjzqnpRVc+q6vsz3/5aVV+q6lNVfX7ML7Ddbn+uqjdV9aqqXp7v0aqq6t+qel9V7zabzV+P/DXkN3l+qSAvq+rHMz/UyIe6C/Rk2+3216r67TKPs3+qqt5uNpvfF/48+e1O1cT5jQryvKp+utjjHPdPnfidcPed7896+E/Ac9lW1S8LvhPK75uTNWl+3w2++MVln6V9801d7ze3drdeL/h6+e2bNr9RQZ5d8EFGltx8dbGnOM9N+fVuria/UUHO/Q+iUyy5ee5/UJ7ihwVfK79DU+Y3KghQCgKRgkCgIBAoCAQKAoGCQKAgECgIBAoCgYJAoCAQKAgECgKBgkCgIBAoCAQKAoGCQDAqyNerPsXym4veAXUmHxd8rfwOTZnfqCBfLvggI0tuvr/YU5znpvx6N1eT36ggny74ICNLbr6ru5eRXct2d/NU8ts3bX6jgnyuu9cxXsuHWvB+2d0b+t7WdX6T/3915t8Lfo787k2d3y28vPp13b2UbMl7l07xse7+WvDHzC9fTuTXyw8AAAAAAAAAnp74URM72nbIG24iv2FB7GjvsUPeM21+RwtiR/soO+Q9U+Y3+ri7He3eTfn1bq4mv1FB7Gj3bsqvd3M1+Y0KYke7d1N+vZuryc9bTSBQEAgUBAIFgUBBIFAQCBQEAgWBQEEgUBAIFAQCBYFAQSBQEAgUBAIFgUBBIFAQCBQEglFB7Gj3bsqvd3M1+Y0KYke7d1N+vZuryW9UEDvavZvy691cTX5HC2JH+4Ad8p5p8zvl5dV2tO2QP8ZTyA8AAAAAAAAAnpiHhhJn+CiCHXL5PcZJ+aWC2NHenSo75B1T5zcqiB3tb06WHfKOafMb/X8QO9r77JD3TJvfqCB2tHs35de7uZr8RgWxo33IDnnPlPl5qwkECgKBgkCgIBAoCAQKAoGCQKAgECgIBAoCgYJAoCAQKAgECgKBgkCgIBAoCAQKAoGCQDAqiB3tQ3bIe6bMb1QQO9q9m/Lr3VxNfqOC2NHeZ4e8Z9r8RgWxo33PDnnP1Pndwsur17yjLb8bzg8AAAAAAAAAnp74URM72nbIG24iv2FB7GjvsUPeM21+RwtiR/soO+Q9U+Y3+ri7He3eTfn1bq4mv1FB7Gj3bsqvd3M1+Y0KYke7d1N+vZuryc9bTSBQEAgUBAIFgUBBIFAQCBQEAgWBQEEgUBAIFAQCBYFAQSBQEAgUBAIFgUBBIFAQCBQEglFB7Gj3bsqvd3M1+Y0KYke7d1N+vZuryW9UEDvavZvy691cTX5HC2JH+4Ad8p5p8zvl5dV2tO2QP8ZTyA8AAAAAAAAAnpiHhhJn+CiCHXL5PcZJ+aWC2NHenSo75B1T5zcqiB3tb06WHfKOafMb/X8QO9r77JD3TJvfqCB2tHs35de7uZr8RgWxo33IDnnPlPl5qwkECgKBgkCgIBAoCAQKAoGCQKAgECgIBAoCgYJAoCAQKAgECgKBgkCgIBAoCAQKAoGCQDAqiB3tQ3bIe6bMb1QQO9q9m/Lr3VxNfqOC2NHeZ4e8Z9r8RgWxo33PDnnP1Pndwsur17yjLb8bzg8AAAC4ov8AwGjpQ+5xFXQAAAAASUVORK5CYII="
|
||||
},
|
||||
"diamond": {
|
||||
"icon": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFF0lEQVR4nO3dMY4UZxAF4BpLThA52AfwBTiA5TtBYpHaCb6TZedcwAcAkyMSgnGwa9nDzv+2e/+ZVXXzfSm7VKlmHgvS0K8KAAAAaOFwz68/rapnVfWkqr698OzPVfWpqj5U1ccH/h6t9zsejz9W1auqelFVzy+3WlVV/V1Vb6vqzeFw+OOBv0fr+1WD/VJAnlfV9xdeauRd3bzga7Te73g8/lxVv1xnndNRVfX6cDj8uvL7Wt+vmuw3CsjTqvrhauuc91ct/5Om9X63Pzl+r/t/Ql/Ksap+WvGTpPX9qtF+3wy++Nl1d5me2X2/V/V44ajbWS9XfH33+7XZbxSQJ1dcZGTNzO77vbjaFpeZ2f1+bfYbBeTS/yBaYs3M7vtd+h/kS3y34mu736/NfqOAACUgEAkIBAICgYBAICAQCAgEAgKBgEAgIBAICAQCAoGAQCAgEAgIBAICgYBAICAQCAgEo4B8ftQt1s/svt/aZ0BdwvsVX9v9fm32GwXk0xUXGVkzs/t+b6+2xWVmdr9fm/1GAflwxUVG1szsvt+bunmY22M53s5cqvv92uw3CsjHunkc42N5V+ue39p6v9snHL6uxwnJv48e/XPF97S+XzXaz8Orxy718OqXdfNQtzXPrVrifd38teo3D69+kEvsBwAAAAAAAABfmU1/1EQPuftN2HdPuh7yE+43Z1896XrIz3K/ObvqSddDPjfT/RbO3GpPuh7yuZnut3DmVnvS9ZDPzXS/hTM91QQCAYFAQCAQEAgEBAIBgUBAIBAQCAQEAgGBQEAgEBAIBAQCAYFAQCAQEAgEBAIBgUBAINhqT7oe8rmZ7rdw5lZ70vWQz810v4Uzt9qTrod8bqb7LZy5yZ50PeR3uN+cffak6yF3vwl60gEAAAAAAABgtfhREz3a0x9FsN/Ge9yHAdGjfWJ1D3nZ7/822+N+NiB6tM9a3ENe9jtnkz3uo4+769Gem2m/uZlt3n+jgOjRnptpv7mZbd5/o4Do0Z6bab+5mW3ef55qAoGAQCAgEAgIBAICgYBAICAQCAgEAgKBgEAgIBAICAQCAoGAQCAgEAgIBAICgYBAICAQjAKiR3tupv3mZrZ5/40Cokd7bqb95ma2ef+NAqJHe26m/eZmtnn/nQ2IHu07VvWQl/2+tNke9yUPr9ajvdOHQ1fz/Tbw/gMAAAAAAACAr8x9RYlb+CiCHnf3e4hF90sB0aN9O6p22OPufieG9xsFRI/2FyNrRz3u7nfW2fuN/j+IHu1Te+txd7+FM0cB0aM9N9P95ma2ud8oIHq079pTj7v7LZzpqSYQCAgEAgKBgEAgIBAICAQCAoGAQCAgEAgIBAICgYBAICAQCAgEAgKBgEAgIBAICAQCAsEoIHq079pTj7v7LZw5Coge7bmZ7jc3s839RgHRo31qbz3u7rdw5iggerT/s7sed/e7Y3i/PTy8unOPtvvt+H4AAAAAAAAA8PXZ9EdNqvl+esi3//putie9mu+nh/zEZl/fTfakV/P99JCftcnXd6s96d3300M+N7PNflvtSe++nx7yuZlt9ttqT3r3/fSQz81ss5+nmkAgIBAICAQCAoGAQCAgEAgIBAICgYBAICAQCAgEAgKBgEAgIBAICAQCAoGAQCAgEAgIBFvtSe++nx7yuZlt9ttqT3r3/fSQz81ss99We9K776eHfG5mm/022ZNezffTQ37HZl9fD68e00M+Z/evLwAAAPCI/gFIfqYbRE+aDAAAAABJRU5ErkJggg=="
|
||||
},
|
||||
"smalldiamond": {
|
||||
"icon": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAsTAAALEwEAmpwYAAAE7ElEQVR4nO3dMY5TVxQG4OOgNGioSbKAbIAFROwJmog2acieoqRnA1nAAA0VooDCKewospj78+5cP+s+z/e1PM/5da1/zEjWPVUAAADAFHbf+PebqnpaVY+r6vszz/5SVZ+q6n1Vfbznz5BPvvtalC8V5Ieq+unMoVpuq+pd52vk+598Y5r5vmu84KYuF66Os246npfvlHxjmvlaBXm6Xpamnpnyjc2Ub+HMVkEerxikpWemfGMz5Vs4s1WQc/9BtETPTPnGZsq3cGarIEApCEQKAoGCQKAgECgIBAoCgYJAoCAQKAgECgKBgkCgIBAoCAQKAoGCQKAgECgIBAoCQasgXy6aon+mfGMz5Vs4s1WQTysGaemZKd/YTPkWzmwV5P2KQVp6Zso3NlO+hTMfNR7+XFX7qnqyWpxTt1X1oeN5+U7JN6aZz+XVbfKNeQj5AAAAAAAAAOCB8VWTtuF8+/3+l6p6WVXP6rDW+JzeVdWbqnq92+3+uufPmPr8aoJ89qQv051vv9//WlW/rRPndFRVvdrtdr93vm7q86tJ8rUKclNVP68W527/1PLfNFPnO35y/Fnf/oQ+l31VPe/4JJn6/GqifPakrzPzZV2uHHWc9aLj+dnPb5p89qSvM/PZainOM3P285smnz3p68w89x/kS/zY8ezs5zdNPreaQKAgECgIBAoCgYJAoCAQKAgECgKBgkCgIBAoCAQKAoGCQKAgECgIBAoCgYJAoCAQKAgE9qSvM7P3DqhzeNvx7OznN00+e9LXmflmtRTnmTn7+U2Tz570dWa+rsNlbpeyP85cavbzmyZfqyAf63Ad46XcVt/9rVPnO95w+KouU5L/rh79u+M1U59fTZTP5dVt57q8+kUdLnXrubdqibd1+G/VHy6vvhd70gEAAAAAAACg26a/amIPufMbcN170u0hP+H8xlzXnnR7yO/k/MZc1Z50e8jHZjq/hTO3uifdHvKxmc5v4cyt7km3h3xspvNbONOtJhAoCAQKAoGCQKAgECgIBAoCgYJAoCAQKAgECgKBgkCgIBAoCAQKAoGCQKAgECgIBAoCwVb3pNtDPjbT+S2cudU96faQj810fgtnbnVPuj3kYzOd38KZm9yTbg/5V5zfmOvck24PufMbYE86AAAAAAAAAHTb9FdNavJ89pBv//3d7J70mjyfPeQnNvv+bnJPek2ezx7yO23y/d3qnvTZ89lDPjZzmnxb3ZM+ez57yMdmTpNvq3vSZ89nD/nYzGnyudUEAgWBQEEgUBAIFAQCBYFAQSBQEAgUBAIFgUBBIFAQCBQEAgWBQEEgUBAIFAQCBYFAQSDY6p702fPZQz42c5p8W92TPns+e8jHZk6Tb6t70mfPZw/52Mxp8m1yT3pNns8e8q9s9v11eXWbPeRjrv79BQAAAAAAAICHx1dN2uQbcxX57ElfRr4xm83X+jbvTV0uXB1n3XQ8L98p+cY089mTvs5M+cZmTpPPnvR1Zso3NnOafPakrzNTvrGZ0+RzqwkECgKBgkCgIBAoCAQKAoGCQKAgECgIBAoCgYJAoCAQKAgECgKBgkCgIBAoCAQKAoGCQGBP+joz5RubOU0+e9LXmSnf2Mxp8tmTvs5M+cZmTpPvUePhz3XYv/1ktTinbqvqQ8fz8p2Sb0wzn8ur2+Qb8xDyAQAAAJfyL3WaU2vK5kXFAAAAAElFTkSuQmCC"
|
||||
},
|
||||
"square": {
|
||||
"icon": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFJElEQVR4nO3dQW4UVxAG4OpI2SD2kBwgF8gBRrkTbCy2yYbcBvZRss8FcgAb9ogNkiuLGRtZ7i5187rHr4fv2wamfqT6baGYVxEAAABA/zLzkJnvM/Mm13dz+uyDfPLtLl9mXm0QasxtZl7JJ99u8uWxubdnCngXcnaT5ZPvXPl+mMj4OiKGuX+gFQwR8WrBr5fvIfnaTOabKsiv22WZtGSmfG0z5Zs5c7SlmZnbZhk3DMOsrxryjZOvzVi+qe8gQCgIlBQECgoCBQWBgoJAQUGgoCBQUBAoKAgUFAQKCgIFBYGCgkBBQaCgIFBQECgoCBQUBApTBflw1hRHNwt+rXyPyddmNN9UQf7dMMiUJTPla5sp38yZUwV5GxHnfFkiTzPnku8h+doszXf/9OM5XrdreZpSPvmeJN9dyENmvsvM6w2CXZ8+u/VxY/nke5J8AAAAAAAAAPD9KU9inf43/Os43m97ufLsD3H8Ccq3wzD8/Y2f8TwiXkTEs4j4ca1gJ18i4nNEfIyIT9/4GfI15Oth/yYLkscf4Pp95VCjoyLizTAMfyz8fS8j4ucN8oy5juX/RkG+rxbn62X/po54HiLir6n/voGMiN8WfCd5HhG/bJhnzH8x/yuhfI/NztfT/u31TvqLrYKsNFO+tpnd7N9e76Q/2yzFOjPla5vZzf5NFWTtvxDN8dOCX7v2XyjXnilf28xu9s+rJlBQECgoCBQUBAoKAgUFgYKCQEFBoKAgUFAQKCgIFBQECgoCBQWBgoJAQUGgoCBQUBAoKAgU9non/ctmKdaZKV/bzG72b6930j9vlmKdmfK1zexm//Z6J/3jVkFWmilf28xu9m+0IKcX5t7EeULePf34z4Lf8ymOz1mey3Use19WvocW5etp/+Y8Xv0qjo9qLXm3ao6bOH5b+9Pj1d/k4vPtYP8AAAAAAAAA4DvjTvq0i/9Rjug8Xw/75076PBd3hzw6z9fL/rmTPt/F3CGPzvP1tH/upG8zU762md3snzvp28yUr21mN/vnTvo2M+Vrm9nN/nnVBAoKAgUFgYKCQEFBoKAgUFAQKCgIFBQECgoCBQWBgoJAQUGgoCBQUBAoKAgUFAQKCgIFBYGCO+nbzJSvbWY3++dO+jYz5Wub2c3+uZO+zUz52mZ2s3/upM9zUXfIo/N8Pe2fO+nTLv5x6Og83w72DwAAAAAAAAC+M+6kT7v4H+WIzvP1sH/upM9zcXfIo/N8veyfO+nzXcwd8ug8X0/75076NjPla5vZzf65k77NTPnaZnazf+6kbzNTvraZ3eyfV02goCBQUBAoKAgUFAQKCgIFBYGCgkBBQaCgIFBQECgoCBQUBAoKAgUFgYKCQEFBoKAgUFAQKLiTvs1M+dpmdrN/7qRvM1O+tpnd7J876dvMlK9tZjf75076PBd1hzw6z9fT/rmTPu3iH4eOzvPtYP8AAAAAAAAAgK8y85CZ7zPzJtd3c/rsg3zy7S5fZl5tEGrMbR5vYssn3z7y5bG5t2cKeBdydpPlk+9c+fZ6J12+h+Rrc3F30uVrmynfzJmjLc3Mc/5rrnvDMMz6qiHfOPnajOXzqgkUFAQKCgIFBYGCgkBBQaCgIFBQECgoCBQUBAoKAgUFgYKCQEFBoKAgUFAQKCgIFBQECgoChb3eSZfvMfnaXNSddPnaZso3c+Ze76TL95B8bZbmu3/68Ryv27U8TSmffE+S7y7kITPfZeb1BsGuT5/d+rixfPI9ST4AAADgjP4Hm2pLjkVf1VMAAAAASUVORK5CYII="
|
||||
},
|
||||
"smallsquare": {
|
||||
"icon": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAsTAAALEwEAmpwYAAAE6ElEQVR4nO3dP44URxQH4DdGTtAQY3wAX4ADWNwJEkRqEnwny865gA+wQEKECCAYghkbWrP1tmqqe9TV+33p9uz7qbd/+0earRcBAAAArMLujo/vI+JxRDyMiJ9nnv01Ij5HxIeI+HTh55BPvktV5csK8ktE/DpzqJKbiHjf+Br5vpOvTzHfT4UX7ON64eI0a99wvXxT8vUp5isV5PFyWYpaZsrXN1O+ypmlgjxcMEhJy0z5+mbKVzmzVJC5/yCq0TJTvr6Z8lXOLBUECAWBlIJAQkEgoSCQUBBIKAgkFAQSCgIJBYGEgkBCQSChIJBQEEgoCCQUBBIKAgkFgYSCQKJUkK9XTdE+U76+mfJVziwV5POCQUpaZsrXN1O+ypmlgnxYMEhJy0z5+mbKVznzQeHiLxFxiIhHi8WZuomIjw3XyzclX59iPodXl8nX5z7kAwAAAAAAAIB7Zui3mhwOh98j4kVEPI3j2uA5vY+ItxHxZrfb/X3JJ5CvL1+s4Pkbdk/64XB4GRF/LBNnOioiXu12u9dNL5Lv/1FxQb5YyfNXKsg+In5bLM7t/o3KnySn73x/xd0/AedyiIhntd8J5TsfGQ35YkXP36h70l/E9b64cZr1vOF6+aZa863m+Rt1T/rTxVLMM1O+vpmref5G3ZM+9x+UNZ40XCvfuZZ8q3n+nGoCCQWBhIJAQkEgoSCQUBBIKAgkFAQSCgIJBYGEgkBCQSChIJBQEEgoCCQUBBIKAgkFgYSCQGLUPelNZ2jN5F3DtfKda8m3mudv1D3pbxdLMc9M+fpmrub5G3VP+ps4HkZ2LYfTzFryTbXmW83zVyrIpzgex3gtN9FwPu/phL5XcZ0v8n9HZ/5T+wL5JprzxYqevy0cXv08joeStZy7VONdHH8t+LPzcGj5Bj68GgAAAAAAAAD40RbeamLPt/t3CXvSZzL0nu8S92/CnvROw+75vo37dyt70jsMu+e7wP2rnGlP+jIz3b++mau5f/ak1xtyz3eB+1c506kmkFAQSCgIJBQEEgoCCQWBhIJAQkEgoSCQUBBIKAgkFAQSCgIJBYGEgkBCQSChIJBQEEgoCCTsSa835J7vAvevcqY96cvMdP/6Zq7m/tmTXmfYPd8F7l/lTHvS7zb0nu/buH9n7Em/wOb3fLt/9qQDAAAAAAAAQJstvNVktXu+5bMnfS6b2/Mt3/dRYU/6LDaz51u+85FhT3q3Le35lm/KnvQZbGnPt3x9M1fz/NmTXq/l/yXkO2dPOmyNgkBCQSChIJBQEEgoCCQUBBIKAgkFgYSCQEJBIKEgkFAQSCgIJBQEEgoCCQWBhIJAQkEgYU96vZY93/Kdsye905b2fMvXN3M1z5896XVa93zLN2VPeqdN7fmWb8Ke9Attfs+3fPakAwAAAAAAAMC2DP1Wk5BPvstte096yPcj+foU85XezbuP64WL06x9w/XyTcnXp5hv1D3p8vXNlK9y5qh70uXrmylf5cxR96TL1zdTvsqZTjWBhIJAQkEgoSCQUBBIKAgkFAQSCgIJBYGEgkBCQSChIJBQEEgoCCQUBBIKAgkFgYSCQEJBIDHqnnT5+mbKVzlz1D3p8vXNlK9y5qh70uXrmylf5cwHhYu/xHG/9aPF4kzdRMTHhuvlm5KvTzGfw6vL5OtzH/IBAAAA1/IN7YSWk669SX0AAAAASUVORK5CYII="
|
||||
},
|
||||
"scissors": {
|
||||
"icon": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFUUlEQVR4nO3dMW6cRRgG4G+RaCL6AAfgAjkA4k5Jg9JCE+6EoM8FOEBC+ihNiqVYU0TZeT3rnd/6/vXztB57Ps3odWTFnrcKAAAAaOGQPng8Hn+uqldV9aKqvl+8979V9baq3hwOh78e8gW6z1dV31XV86p6VlXfrhrszueq+lRVH6rq4wO/Ruv5OtzvMCDH4/HXqvpt8VBnt6qq14fD4feLPqn5fHW60B83mOecd3W68Eu0nq/L/Z4NyF1y/xx9fAPHqvpl9jt19/nq9J35pw3nOeefmv9O3Xq+Tvf7zeATXtXjDVd3e728YH33+Z5vNciiPbvP1+Z+RwF5sd0sQ5fs2X2+Z5tNsWbP7vO1ud9RQFb/QDTjhwvWdp9v9Q+8q/fsPl+b+x0FBCgBgUhAIBAQCAQEAgGBQEAgEBAIBAQCAYFAQCAQEAgEBAIBgUBAIBAQCAQEAgGBQEAgGAXk0jeWVnh/wdru833ebIo1e3afr839jgLydsNBRi7Zs/t8nzabYs2e3edrc7+jgLyp02Naj+V4t+es7vN92GqQRXt2n6/N/Z4NyN0Lc6/rcYb8/+nHv2c/oft8dXpB8N1G85zzri57/7b1fJ3ud+bx6pd1elTrknehZryv0z9rf1z5eHXb+ar549DVfL4d3C8AAAAAAAAAPDF60sduvifd+d1/fnrSJ7aqG+xJd35fGJ6fnvQ5N9WT7vzOOnt+etLn3FpPuvOb3FNP+jZ76iG/bs8256cnfd4t9aQ7v8k9vWoCgYBAICAQCAgEAgKBgEAgIBAICAQCAoGAQCAgEAgIBAICgYBAICAQCAgEAgKBgEAgIBDoSZ93Sz3pzm9yTz3p2+yph/y6Pducn570ObfWk+78JvfUk36/m+tJd35fGZ6fnvSxm+9Jd35X98wDAAAAAAAAwBNzX5Fj9//qbz2fHvL9328KSIue6qD1fHrIv7Db+x0FpE1P9UDr+fSQn7XL+x39PUibnuoFa1fRQ36dXd7vKCBteqoXrF1FD/l1dnm/o4C06alesHYVPeTX2eX9etUEAgGBQEAgEBAIBAQCAYFAQCAQEAgEBAIBgUBAIBAQCAQEAgGBQEAgEBAIBAQCAYFAQCAYBaRNT/WCtavoIb/OLu93FJA2PdUL1q6ih/w6u7zfUUDa9FQvWLuKHvLr7PJ+RwFp01M90Ho+PeRf2e39erx6TA/5dW7+fgEAAAAAAADg6Ym/atK957v7fNX8VyWc3xU96d17vrvPV016vkec3xcu60nv3vPdfb5q1PN9jvM766Ke9O49393na9PzPeD8JvccBaR7z3f3+dr0fA84v8k9RwHp3vPdfb42Pd8Dzm9yT6+aQCAgEAgIBAICgYBAICAQCAgEAgKBgEAgIBAICAQCAoGAQCAgEAgIBAICgYBAICAQCAgEo4B07/nuPl+bnu8B5ze55ygg3Xu+u8/Xpud7wPlN7jkKSPee7+7zten5HnB+k3ueDUj3nu/u81Wjnu9znN9XHtaT3r3nu/t81eDx5cT56UkHAAAAAAAAgMvoSR+7iZ7ve7Ser8P96kmf2Kp23PMdtJ6vy/3qSZ+z257vgdbzdbpfPelzdtvzvWDtKrvscdeTvs2ebXq+F6xdZZc97nrS5+2y53vB2lV22ePuVRMIBAQCAYFAQCAQEAgEBAIBgUBAIBAQCAQEAgGBQEAgEBAIBAQCAYFAQCAQEAgEBAIBgUBP+rxd9nwvWLvKLnvc9aRvs2ebnu8Fa1fZZY+7nvQ5u+35XrB2lV32uOtJv9+ue74HWs/X6X71pI89hZ7v1vPt4H4BAACAx/IfV5v6DSxvZ+4AAAAASUVORK5CYII="
|
||||
}
|
||||
}
|
||||
@@ -27,124 +27,124 @@ THE SOFTWARE.
|
||||
|
||||
enum IconNames {
|
||||
//% block="heart"
|
||||
//% blockImage=1
|
||||
//% jres=icons.heart
|
||||
Heart = 0,
|
||||
//% block="small heart"
|
||||
//% blockImage=1
|
||||
//% jres=icons.smallheart
|
||||
SmallHeart,
|
||||
//% block="yes"
|
||||
//% blockImage=1
|
||||
//% jres=icons.yes
|
||||
Yes,
|
||||
//% block="no"
|
||||
//% blockImage=1
|
||||
//% jres=icons.no
|
||||
No,
|
||||
//% block="happy"
|
||||
//% blockImage=1
|
||||
//% jres=icons.happy
|
||||
Happy,
|
||||
//% block="sad"
|
||||
//% blockImage=1
|
||||
//% jres=icons.sad
|
||||
Sad,
|
||||
//% block="confused"
|
||||
//% blockImage=1
|
||||
//% jres=icons.confused
|
||||
Confused,
|
||||
//% block="angry"
|
||||
//% blockImage=1
|
||||
//% jres=icons.angry
|
||||
Angry,
|
||||
//% block="asleep"
|
||||
//% blockImage=1
|
||||
//% jres=icons.asleep
|
||||
Asleep,
|
||||
//% block="surprised"
|
||||
//% blockImage=1
|
||||
//% jres=icons.surprised
|
||||
Surprised,
|
||||
//% block="silly"
|
||||
//% blockImage=1
|
||||
//% jres=icons.silly
|
||||
Silly,
|
||||
//% block="fabulous"
|
||||
//% blockImage=1
|
||||
//% jres=icons.fabulous
|
||||
Fabulous,
|
||||
//% block="meh"
|
||||
//% blockImage=1
|
||||
//% jres=icons.meh
|
||||
Meh,
|
||||
//% block="t-shirt"
|
||||
//% blockImage=1
|
||||
//% jres=icons.tshirt
|
||||
TShirt,
|
||||
//% block="roller skate"
|
||||
//% blockImage=1
|
||||
//% jres=icons.rollerskate
|
||||
Rollerskate,
|
||||
//% block="duck"
|
||||
//% blockImage=1
|
||||
//% jres=icons.duck
|
||||
Duck,
|
||||
//% block="house"
|
||||
//% blockImage=1
|
||||
//% jres=icons.house
|
||||
House,
|
||||
//% block="tortoise"
|
||||
//% blockImage=1
|
||||
//% jres=icons.tortoise
|
||||
Tortoise,
|
||||
//% block="butterfly"
|
||||
//% blockImage=1
|
||||
//% jres=icons.butterfly
|
||||
Butterfly,
|
||||
//% block="stick figure"
|
||||
//% blockImage=1
|
||||
//% jres=icons.stickfigure
|
||||
StickFigure,
|
||||
//% block="ghost"
|
||||
//% blockImage=1
|
||||
//% jres=icons.ghost
|
||||
Ghost,
|
||||
//% block="sword"
|
||||
//% blockImage=1
|
||||
//% jres=icons.sword
|
||||
Sword,
|
||||
//% block="giraffe"
|
||||
//% blockImage=1
|
||||
//% jres=icons.giraffe
|
||||
Giraffe,
|
||||
//% block="skull"
|
||||
//% blockImage=1
|
||||
//% jres=icons.skull
|
||||
Skull,
|
||||
//% block="umbrella"
|
||||
//% blockImage=1
|
||||
//% jres=icons.umbrella
|
||||
Umbrella,
|
||||
//% block="snake"
|
||||
//% blockImage=1
|
||||
//% jres=icons.snake
|
||||
Snake,
|
||||
//% block="rabbit"
|
||||
//% blockImage=1
|
||||
//% jres=icons.rabbit
|
||||
Rabbit,
|
||||
//% block="cow"
|
||||
//% blockImage=1
|
||||
//% jres=icons.cow
|
||||
Cow,
|
||||
//% block="quarter note"
|
||||
//% blockImage=1
|
||||
//% jres=icons.quarternote
|
||||
QuarterNote,
|
||||
//% block="eigth note"
|
||||
//% blockImage=1
|
||||
//% jres=icons.eigthnote
|
||||
EigthNote,
|
||||
//% block="pitchfork"
|
||||
//% blockImage=1
|
||||
//% jres=icons.pitchfork
|
||||
Pitchfork,
|
||||
//% block="target"
|
||||
//% blockImage=1
|
||||
//% jres=icons.target
|
||||
Target,
|
||||
//% block="triangle"
|
||||
//% blockImage=1
|
||||
//% jres=icons.triangle
|
||||
Triangle,
|
||||
//% block="left triangle"
|
||||
//% blockImage=1
|
||||
//% jres=icons.lefttriangle
|
||||
LeftTriangle,
|
||||
//% block="chess board"
|
||||
//% blockImage=1
|
||||
//% jres=icons.chessboard
|
||||
Chessboard,
|
||||
//% block="diamond"
|
||||
//% blockImage=1
|
||||
//% jres=icons.diamond
|
||||
Diamond,
|
||||
//% block="small diamond"
|
||||
//% blockImage=1
|
||||
//% jres=icons.smalldiamond
|
||||
SmallDiamond,
|
||||
//% block="square"
|
||||
//% blockImage=1
|
||||
//% jres=icons.square
|
||||
Square,
|
||||
//% block="small square"
|
||||
//% blockImage=1
|
||||
//% jres=icons.smallsquare
|
||||
SmallSquare,
|
||||
//% block="scissors"
|
||||
//% blockImage=1
|
||||
//% jres=icons.scissors
|
||||
Scissors
|
||||
}
|
||||
|
||||
@@ -171,7 +171,7 @@ namespace basic {
|
||||
|
||||
/**
|
||||
* Draws the selected icon on the LED screen
|
||||
* @param icon the predifined icon id
|
||||
* @param icon the predefined icon id
|
||||
* @param interval the amount of time (milliseconds) to show the icon. Default is 600.
|
||||
*/
|
||||
//% weight=90 blockGap=8
|
||||
@@ -179,16 +179,17 @@ namespace basic {
|
||||
//% block="show icon %i" icon="\uf00a"
|
||||
//% parts="ledmatrix"
|
||||
//% help=basic/show-icon
|
||||
//% i.fieldEditor="gridpicker"
|
||||
//% i.fieldOptions.width="400" i.fieldOptions.columns="5"
|
||||
//% i.fieldOptions.itemColour="black" i.fieldOptions.tooltips="true"
|
||||
//% icon.fieldEditor="imagedropdown"
|
||||
//% icon.fieldOptions.columns="5"
|
||||
//% icon.fieldOptions.width="380"
|
||||
//% icon.fieldOptions.maxRows=4
|
||||
export function showIcon(icon: IconNames, interval = 600) {
|
||||
let res = images.iconImage(icon)
|
||||
res.showImage(0, interval)
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows an arrow on screent
|
||||
* Draws an arrow on the LED screen
|
||||
* @param direction the direction of the arrow
|
||||
* @param interval the amount of time (milliseconds) to show the icon. Default is 600.
|
||||
*/
|
||||
@@ -213,49 +214,49 @@ namespace images {
|
||||
export function arrowImage(i: ArrowNames): Image {
|
||||
switch (i) {
|
||||
// compass directions
|
||||
case ArrowNames.North: return images.createImage(`
|
||||
case ArrowNames.North: return images.createImage(`
|
||||
. . # . .
|
||||
. # # # .
|
||||
# . # . #
|
||||
. . # . .
|
||||
. . # . .`);
|
||||
case ArrowNames.NorthEast: return images.createImage(`
|
||||
case ArrowNames.NorthEast: return images.createImage(`
|
||||
. . # # #
|
||||
. . . # #
|
||||
. . # . #
|
||||
. # . . .
|
||||
# . . . .`);
|
||||
case ArrowNames.East: return images.createImage(`
|
||||
case ArrowNames.East: return images.createImage(`
|
||||
. . # . .
|
||||
. . . # .
|
||||
# # # # #
|
||||
. . . # .
|
||||
. . # . .`);
|
||||
case ArrowNames.SouthEast: return images.createImage(`
|
||||
case ArrowNames.SouthEast: return images.createImage(`
|
||||
# . . . .
|
||||
. # . . .
|
||||
. . # . #
|
||||
. . . # #
|
||||
. . # # #`);
|
||||
case ArrowNames.South: return images.createImage(`
|
||||
case ArrowNames.South: return images.createImage(`
|
||||
. . # . .
|
||||
. . # . .
|
||||
# . # . #
|
||||
. # # # .
|
||||
. . # . .`);
|
||||
case ArrowNames.SouthWest: return images.createImage(`
|
||||
case ArrowNames.SouthWest: return images.createImage(`
|
||||
. . . . #
|
||||
. . . # .
|
||||
# . # . .
|
||||
# # . . .
|
||||
# # # . .`);
|
||||
case ArrowNames.West: return images.createImage(`
|
||||
case ArrowNames.West: return images.createImage(`
|
||||
. . # . .
|
||||
. # . . .
|
||||
# # # # #
|
||||
. # . . .
|
||||
. . # . .`);
|
||||
case ArrowNames.NorthWest: return images.createImage(`
|
||||
case ArrowNames.NorthWest: return images.createImage(`
|
||||
# # # . .
|
||||
# # . . .
|
||||
# . # . .
|
||||
@@ -274,9 +275,10 @@ namespace images {
|
||||
//% weight=50 blockGap=8
|
||||
//% help=images/icon-image
|
||||
//% blockId=builtin_image block="icon image %i"
|
||||
//% i.fieldEditor="gridpicker"
|
||||
//% i.fieldOptions.width="400" i.fieldOptions.columns="5"
|
||||
//% i.fieldOptions.itemColour="black" i.fieldOptions.tooltips="true"
|
||||
//% i.fieldEditor="imagedropdown"
|
||||
//% i.fieldOptions.columns="5"
|
||||
//% i.fieldOptions.width="380"
|
||||
//% i.fieldOptions.maxRows=4
|
||||
export function iconImage(i: IconNames): Image {
|
||||
switch (i) {
|
||||
case IconNames.Heart: return images.createImage(`
|
||||
|
||||
@@ -1,156 +1,183 @@
|
||||
#include "pxt.h"
|
||||
|
||||
PXT_VTABLE(RefMImage, ValType::Object)
|
||||
|
||||
RefMImage::RefMImage(ImageData *d) : PXT_VTABLE_INIT(RefMImage), img(d) {
|
||||
img->incr();
|
||||
}
|
||||
|
||||
void RefMImage::destroy(RefMImage *t) {
|
||||
t->img->decr();
|
||||
}
|
||||
|
||||
void RefMImage::print(RefMImage *t) {
|
||||
DMESG("RefMImage %p r=%d size=%d x %d", t, t->refcnt, img->width, img->height);
|
||||
}
|
||||
|
||||
void RefMImage::makeWritable() {
|
||||
if (img->isReadOnly()) {
|
||||
MicroBitImage i(img);
|
||||
img = i.clone().leakData();
|
||||
}
|
||||
}
|
||||
|
||||
void RefMImage::scan(RefMImage *t) {}
|
||||
|
||||
unsigned RefMImage::gcsize(RefMImage *t) {
|
||||
return (sizeof(*t) + 3) >> 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creation, manipulation and display of LED images.
|
||||
*/
|
||||
//% color=#5C2D91 weight=31 icon="\uf03e"
|
||||
* Creation, manipulation and display of LED images.
|
||||
*/
|
||||
//% color=#7600A8 weight=31 icon="\uf03e"
|
||||
//% advanced=true
|
||||
namespace images {
|
||||
/**
|
||||
* Creates an image that fits on the LED screen.
|
||||
*/
|
||||
//% weight=75 help=images/create-image
|
||||
//% blockId=device_build_image block="create image"
|
||||
//% parts="ledmatrix"
|
||||
Image createImage(ImageLiteral leds) {
|
||||
return MicroBitImage(imageBytes(leds)).clone().leakData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an image with 2 frames.
|
||||
*/
|
||||
//% weight=74 help=images/create-big-image
|
||||
//% blockId=device_build_big_image block="create big image" imageLiteral=2
|
||||
//% parts="ledmatrix"
|
||||
Image createBigImage(ImageLiteral leds) {
|
||||
return createImage(leds);
|
||||
}
|
||||
/**
|
||||
* Creates an image that fits on the LED screen.
|
||||
*/
|
||||
//% weight=75 help=images/create-image
|
||||
//% blockId=device_build_image block="create image"
|
||||
//% parts="ledmatrix"
|
||||
Image createImage(ImageLiteral_ leds) {
|
||||
return NEW_GC(RefMImage, imageBytes(leds));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an image with 2 frames.
|
||||
*/
|
||||
//% weight=74 help=images/create-big-image
|
||||
//% blockId=device_build_big_image block="create big image" imageLiteral=2
|
||||
//% parts="ledmatrix"
|
||||
Image createBigImage(ImageLiteral_ leds) {
|
||||
return createImage(leds);
|
||||
}
|
||||
} // namespace images
|
||||
|
||||
namespace ImageMethods {
|
||||
/**
|
||||
* Plots the image at a given column to the screen
|
||||
*/
|
||||
//% help=images/plot-image
|
||||
//% parts="ledmatrix"
|
||||
void plotImage(Image i, int xOffset = 0) {
|
||||
uBit.display.print(MicroBitImage(i), -xOffset, 0, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows an frame from the image at offset ``x offset``.
|
||||
* @param xOffset column index to start displaying the image
|
||||
*/
|
||||
//% help=images/show-image weight=80 blockNamespace=images
|
||||
//% blockId=device_show_image_offset block="show image %sprite|at offset %offset" blockGap=8
|
||||
//% parts="ledmatrix" async
|
||||
void showImage(Image sprite, int xOffset, int interval = 400) {
|
||||
uBit.display.print(MicroBitImage(sprite), -xOffset, 0, 0, interval);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws the ``index``-th frame of the image on the screen.
|
||||
* @param xOffset column index to start displaying the image
|
||||
*/
|
||||
//% help=images/plot-frame weight=80
|
||||
//% parts="ledmatrix"
|
||||
void plotFrame(Image i, int xOffset) {
|
||||
// TODO showImage() used in original implementation
|
||||
plotImage(i, xOffset * 5);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scrolls an image .
|
||||
* @param frameOffset x offset moved on each animation step, eg: 1, 2, 5
|
||||
* @param interval time between each animation step in milli seconds, eg: 200
|
||||
*/
|
||||
//% help=images/scroll-image weight=79 async blockNamespace=images
|
||||
//% blockId=device_scroll_image block="scroll image %sprite|with offset %frameoffset|and interval (ms) %delay" blockGap=8
|
||||
//% parts="ledmatrix"
|
||||
void scrollImage(Image id, int frameOffset, int interval) {
|
||||
MicroBitImage i(id);
|
||||
uBit.display.animate(i, interval, frameOffset, MICROBIT_DISPLAY_ANIMATE_DEFAULT_POS, 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets all pixels off.
|
||||
*/
|
||||
//% help=images/clear
|
||||
//% parts="ledmatrix"
|
||||
void clear(Image i) {
|
||||
MicroBitImage(i).clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a specific pixel brightness at a given position
|
||||
*/
|
||||
//%
|
||||
//% parts="ledmatrix"
|
||||
void setPixelBrightness(Image i, int x, int y, int value) {
|
||||
MicroBitImage(i).setPixelValue(x, y, value);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the pixel brightness ([0..255]) at a given position
|
||||
*/
|
||||
//%
|
||||
//% parts="ledmatrix"
|
||||
int pixelBrightness(Image i, int x, int y) {
|
||||
int pix = MicroBitImage(i).getPixelValue(x, y);
|
||||
if (pix < 0) return 0;
|
||||
return pix;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the width in columns
|
||||
*/
|
||||
//% help=functions/width
|
||||
int width(Image i) {
|
||||
return i->width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the height in rows (always 5)
|
||||
*/
|
||||
//%
|
||||
int height(Image i) {
|
||||
return i->height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a pixel state at position ``(x,y)``
|
||||
* @param x TODO
|
||||
* @param y TODO
|
||||
* @param value TODO
|
||||
*/
|
||||
//% help=images/set-pixel
|
||||
//% parts="ledmatrix"
|
||||
void setPixel(Image i, int x, int y, bool value) {
|
||||
setPixelBrightness(i, x, y, value ? 255 : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the pixel state at position ``(x,y)``
|
||||
* @param x TODO
|
||||
* @param y TODO
|
||||
*/
|
||||
//% help=images/pixel
|
||||
//% parts="ledmatrix"
|
||||
bool pixel(Image i, int x, int y) {
|
||||
return pixelBrightness(i, x, y) > 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Shows a particular frame of the image strip.
|
||||
* @param frame TODO
|
||||
*/
|
||||
//% weight=70 help=images/show-frame
|
||||
//% parts="ledmatrix"
|
||||
void showFrame(Image i, int frame, int interval = 400) {
|
||||
showImage(i, frame * 5, interval);
|
||||
}
|
||||
/**
|
||||
* Plots the image at a given column to the screen
|
||||
*/
|
||||
//% help=images/plot-image
|
||||
//% parts="ledmatrix"
|
||||
void plotImage(Image i, int xOffset = 0) {
|
||||
uBit.display.print(MicroBitImage(i->img), -xOffset, 0, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows an frame from the image at offset ``x offset``.
|
||||
* @param xOffset column index to start displaying the image
|
||||
*/
|
||||
//% help=images/show-image weight=80 blockNamespace=images
|
||||
//% blockId=device_show_image_offset block="show image %sprite(myImage)|at offset %offset"
|
||||
//% blockGap=8 parts="ledmatrix" async
|
||||
void showImage(Image sprite, int xOffset, int interval = 400) {
|
||||
uBit.display.print(MicroBitImage(sprite->img), -xOffset, 0, 0, interval);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws the ``index``-th frame of the image on the screen.
|
||||
* @param xOffset column index to start displaying the image
|
||||
*/
|
||||
//% help=images/plot-frame weight=80
|
||||
//% parts="ledmatrix"
|
||||
void plotFrame(Image i, int xOffset) {
|
||||
// TODO showImage() used in original implementation
|
||||
plotImage(i, xOffset * 5);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scrolls an image .
|
||||
* @param frameOffset x offset moved on each animation step, eg: 1, 2, 5
|
||||
* @param interval time between each animation step in milli seconds, eg: 200
|
||||
*/
|
||||
//% help=images/scroll-image weight=79 async blockNamespace=images
|
||||
//% blockId=device_scroll_image
|
||||
//% block="scroll image %sprite(myImage)|with offset %frameoffset|and interval (ms) %delay"
|
||||
//% blockGap=8 parts="ledmatrix"
|
||||
void scrollImage(Image id, int frameOffset, int interval) {
|
||||
MicroBitImage i(id->img);
|
||||
uBit.display.animate(i, interval, frameOffset, MICROBIT_DISPLAY_ANIMATE_DEFAULT_POS, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets all pixels off.
|
||||
*/
|
||||
//% help=images/clear
|
||||
//% parts="ledmatrix"
|
||||
void clear(Image i) {
|
||||
i->makeWritable();
|
||||
MicroBitImage(i->img).clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a specific pixel brightness at a given position
|
||||
*/
|
||||
//%
|
||||
//% parts="ledmatrix"
|
||||
void setPixelBrightness(Image i, int x, int y, int value) {
|
||||
i->makeWritable();
|
||||
MicroBitImage(i->img).setPixelValue(x, y, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the pixel brightness ([0..255]) at a given position
|
||||
*/
|
||||
//%
|
||||
//% parts="ledmatrix"
|
||||
int pixelBrightness(Image i, int x, int y) {
|
||||
int pix = MicroBitImage(i->img).getPixelValue(x, y);
|
||||
if (pix < 0)
|
||||
return 0;
|
||||
return pix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the width in columns
|
||||
*/
|
||||
//% help=functions/width
|
||||
int width(Image i) {
|
||||
return i->img->width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the height in rows (always 5)
|
||||
*/
|
||||
//%
|
||||
int height(Image i) {
|
||||
return i->img->height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a pixel state at position ``(x,y)``
|
||||
* @param x pixel column
|
||||
* @param y pixel row
|
||||
* @param value pixel state
|
||||
*/
|
||||
//% help=images/set-pixel
|
||||
//% parts="ledmatrix"
|
||||
void setPixel(Image i, int x, int y, bool value) {
|
||||
setPixelBrightness(i, x, y, value ? 255 : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the pixel state at position ``(x,y)``
|
||||
* @param x pixel column
|
||||
* @param y pixel row
|
||||
*/
|
||||
//% help=images/pixel
|
||||
//% parts="ledmatrix"
|
||||
bool pixel(Image i, int x, int y) {
|
||||
return pixelBrightness(i, x, y) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a particular frame of the image strip.
|
||||
* @param frame image frame to show
|
||||
*/
|
||||
//% weight=70 help=images/show-frame
|
||||
//% parts="ledmatrix"
|
||||
void showFrame(Image i, int frame, int interval = 400) {
|
||||
showImage(i, frame * 5, interval);
|
||||
}
|
||||
} // namespace ImageMethods
|
||||
@@ -60,56 +60,67 @@ enum class Gesture {
|
||||
* Raised when shaken
|
||||
*/
|
||||
//% block=shake
|
||||
//% jres=gestures.shake
|
||||
Shake = MICROBIT_ACCELEROMETER_EVT_SHAKE,
|
||||
/**
|
||||
* Raised when the logo is upward and the screen is vertical
|
||||
*/
|
||||
//% block="logo up"
|
||||
//% jres=gestures.tiltforward
|
||||
LogoUp = MICROBIT_ACCELEROMETER_EVT_TILT_UP,
|
||||
/**
|
||||
* Raised when the logo is downward and the screen is vertical
|
||||
*/
|
||||
//% block="logo down"
|
||||
//% jres=gestures.tiltbackwards
|
||||
LogoDown = MICROBIT_ACCELEROMETER_EVT_TILT_DOWN,
|
||||
/**
|
||||
* Raised when the screen is pointing down and the board is horizontal
|
||||
*/
|
||||
//% block="screen up"
|
||||
//% jres=gestures.frontsideup
|
||||
ScreenUp = MICROBIT_ACCELEROMETER_EVT_FACE_UP,
|
||||
/**
|
||||
* Raised when the screen is pointing up and the board is horizontal
|
||||
*/
|
||||
//% block="screen down"
|
||||
//% jres=gestures.backsideup
|
||||
ScreenDown = MICROBIT_ACCELEROMETER_EVT_FACE_DOWN,
|
||||
/**
|
||||
* Raised when the screen is pointing left
|
||||
*/
|
||||
//% block="tilt left"
|
||||
//% jres=gestures.tiltleft
|
||||
TiltLeft = MICROBIT_ACCELEROMETER_EVT_TILT_LEFT,
|
||||
/**
|
||||
* Raised when the screen is pointing right
|
||||
*/
|
||||
//% block="tilt right"
|
||||
//% jres=gestures.tiltright
|
||||
TiltRight = MICROBIT_ACCELEROMETER_EVT_TILT_RIGHT,
|
||||
/**
|
||||
* Raised when the board is falling!
|
||||
*/
|
||||
//% block="free fall"
|
||||
//% jres=gestures.freefall
|
||||
FreeFall = MICROBIT_ACCELEROMETER_EVT_FREEFALL,
|
||||
/**
|
||||
* Raised when a 3G shock is detected
|
||||
*/
|
||||
//% block="3g"
|
||||
//% jres=gestures.impact3g
|
||||
ThreeG = MICROBIT_ACCELEROMETER_EVT_3G,
|
||||
/**
|
||||
* Raised when a 6G shock is detected
|
||||
*/
|
||||
//% block="6g"
|
||||
//% jres=gestures.impact6g
|
||||
SixG = MICROBIT_ACCELEROMETER_EVT_6G,
|
||||
/**
|
||||
* Raised when a 8G shock is detected
|
||||
*/
|
||||
//% block="8g"
|
||||
//% jres=gestures.impact8g
|
||||
EightG = MICROBIT_ACCELEROMETER_EVT_8G
|
||||
};
|
||||
|
||||
@@ -155,7 +166,7 @@ namespace input {
|
||||
* @param button the button that needs to be pressed
|
||||
* @param body code to run when event is raised
|
||||
*/
|
||||
//% help=input/on-button-pressed weight=85 blockGap=8
|
||||
//% help=input/on-button-pressed weight=85 blockGap=16
|
||||
//% blockId=device_button_event block="on button|%NAME|pressed"
|
||||
//% parts="buttonpair"
|
||||
void onButtonPressed(Button button, Action body) {
|
||||
@@ -167,10 +178,10 @@ namespace input {
|
||||
* @param gesture the type of gesture to track, eg: Gesture.Shake
|
||||
* @param body code to run when gesture is raised
|
||||
*/
|
||||
//% help=input/on-gesture weight=84 blockGap=8
|
||||
//% help=input/on-gesture weight=84 blockGap=16
|
||||
//% blockId=device_gesture_event block="on |%NAME"
|
||||
//% parts="accelerometer"
|
||||
//% NAME.fieldEditor="gridpicker" NAME.fieldOptions.columns=4
|
||||
//% NAME.fieldEditor="gestures" NAME.fieldOptions.columns=4
|
||||
void onGesture(Gesture gesture, Action body) {
|
||||
int gi = (int)gesture;
|
||||
if (gi == MICROBIT_ACCELEROMETER_EVT_3G && uBit.accelerometer.getRange() < 3)
|
||||
@@ -180,12 +191,27 @@ namespace input {
|
||||
registerWithDal(MICROBIT_ID_GESTURE, gi, body);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if a gesture is currently detected.
|
||||
* @param gesture the type of gesture to detect, eg: Gesture.Shake
|
||||
*/
|
||||
//% help=input/is-gesture weight=10 blockGap=8
|
||||
//% blockId=deviceisgesture block="is %gesture gesture"
|
||||
//% parts="accelerometer"
|
||||
//% gesture.fieldEditor="gestures" gesture.fieldOptions.columns=4
|
||||
bool isGesture(Gesture gesture) {
|
||||
// turn on acceleration
|
||||
uBit.accelerometer.getX();
|
||||
int gi = (int)gesture;
|
||||
return uBit.accelerometer.getGesture() == gi;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do something when a pin is touched and released again (while also touching the GND pin).
|
||||
* @param name the pin that needs to be pressed, eg: TouchPin.P0
|
||||
* @param body the code to run when the pin is pressed
|
||||
*/
|
||||
//% help=input/on-pin-pressed weight=83
|
||||
//% help=input/on-pin-pressed weight=83 blockGap=32
|
||||
//% blockId=device_pin_event block="on pin %name|pressed"
|
||||
void onPinPressed(TouchPin name, Action body) {
|
||||
auto pin = getPin((int)name);
|
||||
@@ -201,7 +227,7 @@ namespace input {
|
||||
* @param name the pin that needs to be released, eg: TouchPin.P0
|
||||
* @param body the code to run when the pin is released
|
||||
*/
|
||||
//% help=input/on-pin-released weight=6 blockGap=8
|
||||
//% help=input/on-pin-released weight=6 blockGap=16
|
||||
//% blockId=device_pin_released block="on pin %NAME|released"
|
||||
//% advanced=true
|
||||
void onPinReleased(TouchPin name, Action body) {
|
||||
@@ -220,7 +246,7 @@ namespace input {
|
||||
//% help=input/button-is-pressed weight=60
|
||||
//% block="button|%NAME|is pressed"
|
||||
//% blockId=device_get_button2
|
||||
//% blockGap=8
|
||||
//% icon="\uf192" blockGap=8
|
||||
//% parts="buttonpair"
|
||||
bool buttonIsPressed(Button button) {
|
||||
if (button == Button::A)
|
||||
@@ -253,7 +279,7 @@ namespace input {
|
||||
|
||||
/**
|
||||
* Get the acceleration value in milli-gravitys (when the board is laying flat with the screen up, x=0, y=0 and z=-1024)
|
||||
* @param dimension TODO
|
||||
* @param dimension x, y, or z dimension, eg: Dimension.X
|
||||
*/
|
||||
//% help=input/acceleration weight=58
|
||||
//% blockId=device_acceleration block="acceleration (mg)|%NAME" blockGap=8
|
||||
@@ -303,7 +329,7 @@ namespace input {
|
||||
|
||||
/**
|
||||
* The pitch or roll of the device, rotation along the ``x-axis`` or ``y-axis``, in degrees.
|
||||
* @param kind TODO
|
||||
* @param kind pitch or roll
|
||||
*/
|
||||
//% help=input/rotation weight=52
|
||||
//% blockId=device_get_rotation block="rotation (°)|%NAME" blockGap=8
|
||||
@@ -318,7 +344,7 @@ namespace input {
|
||||
|
||||
/**
|
||||
* Get the magnetic force value in ``micro-Teslas`` (``µT``). This function is not supported in the simulator.
|
||||
* @param dimension TODO
|
||||
* @param dimension the x, y, or z dimension, eg: Dimension.X
|
||||
*/
|
||||
//% help=input/magnetic-force weight=51
|
||||
//% blockId=device_get_magnetic_force block="magnetic force (µT)|%NAME" blockGap=8
|
||||
@@ -362,8 +388,9 @@ namespace input {
|
||||
*/
|
||||
//% help=input/calibrate-compass advanced=true
|
||||
//% blockId="input_compass_calibrate" block="calibrate compass"
|
||||
void calibrateCompass() {
|
||||
uBit.compass.calibrate();
|
||||
//% weight=45
|
||||
void calibrateCompass() {
|
||||
uBit.compass.calibrate();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace input {
|
||||
* @param body TODO
|
||||
*/
|
||||
//% help=input/on-screen-up
|
||||
export function onScreenUp(body: Action): void {
|
||||
export function onScreenUp(body: () => void): void {
|
||||
onGesture(Gesture.ScreenUp, body);
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace input {
|
||||
* @param body TODO
|
||||
*/
|
||||
//% help=input/on-screen-down
|
||||
export function onScreenDown(body: Action): void {
|
||||
export function onScreenDown(body: () => void): void {
|
||||
onGesture(Gesture.ScreenDown, body);
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace input {
|
||||
* @param body TODO
|
||||
*/
|
||||
//% help=input/on-shake
|
||||
export function onShake(body: Action): void {
|
||||
export function onShake(body: () => void): void {
|
||||
onGesture(Gesture.Shake, body);
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace input {
|
||||
* @param body TODO
|
||||
*/
|
||||
//% help=input/on-logo-up
|
||||
export function onLogoUp(body: Action): void {
|
||||
export function onLogoUp(body: () => void): void {
|
||||
onGesture(Gesture.LogoUp, body);
|
||||
}
|
||||
|
||||
@@ -44,7 +44,15 @@ namespace input {
|
||||
* @param body TODO
|
||||
*/
|
||||
//% help=input/on-logo-down
|
||||
export function onLogoDown(body: Action): void {
|
||||
export function onLogoDown(body: () => void): void {
|
||||
onGesture(Gesture.LogoDown, body);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obsolete, use input.calibrateCompass instead.
|
||||
*/
|
||||
//% weight=0 help=input/calibrate-compass
|
||||
export function calibrate() {
|
||||
input.calibrateCompass();
|
||||
}
|
||||
}
|
||||
|
||||
BIN
libs/core/jres/gestures/backsideup-icon.png
Normal file
|
After Width: | Height: | Size: 699 B |
BIN
libs/core/jres/gestures/freefall-icon.png
Normal file
|
After Width: | Height: | Size: 1014 B |
BIN
libs/core/jres/gestures/frontsideup-icon.png
Normal file
|
After Width: | Height: | Size: 919 B |
BIN
libs/core/jres/gestures/impact3g-icon.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
libs/core/jres/gestures/impact6g-icon.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
libs/core/jres/gestures/impact8g-icon.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
libs/core/jres/gestures/shake-icon.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
libs/core/jres/gestures/tiltforward-icon.png
Normal file
|
After Width: | Height: | Size: 808 B |
BIN
libs/core/jres/gestures/tiltleft-icon.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
libs/core/jres/gestures/tiltright-icon.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
libs/core/jres/icons/angry-icon.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
libs/core/jres/icons/asleep-icon.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
libs/core/jres/icons/butterfly-icon.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
libs/core/jres/icons/chessboard-icon.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
libs/core/jres/icons/confused-icon.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
libs/core/jres/icons/cow-icon.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
libs/core/jres/icons/diamond-icon.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
libs/core/jres/icons/duck-icon.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
libs/core/jres/icons/eigthnote-icon.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
libs/core/jres/icons/fabulous-icon.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
libs/core/jres/icons/ghost-icon.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
libs/core/jres/icons/giraffe-icon.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
libs/core/jres/icons/happy-icon.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
libs/core/jres/icons/heart-icon.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
libs/core/jres/icons/house-icon.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
libs/core/jres/icons/lefttriangle-icon.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
libs/core/jres/icons/meh-icon.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
libs/core/jres/icons/no-icon.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
libs/core/jres/icons/pitchfork-icon.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
libs/core/jres/icons/quarternote-icon.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
libs/core/jres/icons/rabbit-icon.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
libs/core/jres/icons/rollerskate-icon.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
libs/core/jres/icons/sad-icon.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
libs/core/jres/icons/scissors-icon.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
libs/core/jres/icons/silly-icon.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
libs/core/jres/icons/skull-icon.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
libs/core/jres/icons/smalldiamond-icon.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
libs/core/jres/icons/smallheart-icon.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
libs/core/jres/icons/smallsquare-icon.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
libs/core/jres/icons/snake-icon.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
libs/core/jres/icons/square-icon.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
libs/core/jres/icons/stickfigure-icon.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
libs/core/jres/icons/surprised-icon.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
libs/core/jres/icons/sword-icon.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
libs/core/jres/icons/target-icon.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
libs/core/jres/icons/tortoise-icon.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
libs/core/jres/icons/triangle-icon.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
libs/core/jres/icons/tshirt-icon.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
libs/core/jres/icons/umbrella-icon.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |