Compare commits

...

18 Commits

Author SHA1 Message Date
9c09a427c9 0.2.19 2016-04-04 22:17:12 -07:00
4b35f0f751 Bump kindscript to 0.2.22 2016-04-04 22:17:10 -07:00
bb03cc4357 static microbit image (svg) 2016-04-04 22:15:52 -07:00
6f8b17e4ba 0.2.18 2016-04-04 21:52:10 -07:00
60c5dfc539 Bump kindscript to 0.2.21 2016-04-04 21:52:09 -07:00
bca5839b49 Forever moved to common sim 2016-04-04 21:52:03 -07:00
47e3737245 Use common helpers/core 2016-04-04 21:18:16 -07:00
b8d5ec853e Prep for moving common stuff out to main ks 2016-04-04 20:28:08 -07:00
46d42e5300 0.2.17 2016-04-04 19:13:35 -07:00
ffabb9b16d Bump kindscript to 0.2.19 2016-04-04 19:13:34 -07:00
d62c10d278 Use the improved default parameters 2016-04-04 19:11:33 -07:00
e2b2aa7ff1 0.2.16 2016-04-04 19:04:04 -07:00
664c8dcd35 Bump kindscript to 0.2.18 2016-04-04 19:04:03 -07:00
bd7430b642 Add Buffer.get/setNumber and i2c methods 2016-04-04 19:02:40 -07:00
61fd28d840 Move all target stuff to kindtarget.json 2016-04-04 18:03:52 -07:00
c33df897d5 Remove unused code 2016-04-04 12:56:57 -07:00
3bb0bd2a9f 0.2.15 2016-04-04 09:50:05 -07:00
7751061b51 Bump kindscript to 0.2.17 2016-04-04 09:50:04 -07:00
15 changed files with 498 additions and 412 deletions

94
docs/static/microbitheart.svg vendored Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 26 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,19 @@
#include "ksbit.h"
enum class NumberFormat {
Int8LE = 1,
UInt8LE,
Int16LE,
UInt16LE,
Int32LE,
Int8BE,
UInt8BE,
Int16BE,
UInt16BE,
Int32BE,
// UInt32,
};
//% indexerGet=BufferMethods::getByte indexerSet=BufferMethods::setByte
namespace BufferMethods {
//%
@ -17,6 +31,70 @@ namespace BufferMethods {
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) {

View File

@ -1,81 +1,31 @@
#include "ksbit.h"
#include <limits.h>
namespace StringMethods {
/**
* Returns the character at the specified index.
* @param pos The zero-based index of the desired character.
*/
namespace String_ {
//%
StringData *charAt(StringData *s, int pos) {
return ManagedString((char)ManagedString(s).charAt(pos)).leakData();
}
/**
* Returns the Unicode value of the character at the specified location.
* @param index The zero-based index of the desired character. If there is no character at the specified index, NaN is returned.
*/
//%
int charCodeAt(StringData *s, int index) {
return ManagedString(s).charAt(index);
return ManagedString(s).charAt(index);
}
/**
* Returns a string that contains the concatenation of two or more strings.
* @param other The string to append to the end of the string.
*/
//%
StringData *concat(StringData *s, StringData *other) {
ManagedString a(s), b(other);
return (a + b).leakData();
}
/**
* Determines whether relative order of two strings (in ASCII encoding).
* @param that String to compare to target string
*/
//%
int compare(StringData *s, StringData *that) {
return strcmp(s->data, that->data);
}
/** Returns the length of a String object. */
//% property
int length(StringData *s) {
return s->len;
}
}
namespace BooleanMethods {
// 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";
/**
* Returns a string representation of an object.
*/
//%
StringData* toString(bool v)
{
if (v) {
return (StringData*)(void*)sTrue;
} else {
return (StringData*)(void*)sFalse;
}
}
int length(StringData *s) { return s->len; }
//%
bool bang(bool v) { return !v; }
}
namespace String_ {
/**
* Make a string from the given ASCII character code.
*/
//%
StringData *fromCharCode(int code)
{
@ -94,18 +44,35 @@ namespace String_ {
}
}
namespace NumberMethods {
/**
* Returns a string representation of a number.
*/
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(bool v) { return !v; }
}
namespace Number_ {
//%
StringData* toString(int n)
{
return ManagedString(n).leakData();
}
}
namespace NumberImpl {
// +, - and friends are handled directly by assembly instructions
// The comparisons are here as they are more code-size efficient
@ -130,11 +97,6 @@ namespace NumberImpl {
}
namespace Math_ {
/**
* Returns the value of a base expression taken to a specified power.
* @param x The base value of the expression.
* @param y The exponent value of the expression.
*/
//%
int pow(int x, int y)
{
@ -150,9 +112,6 @@ namespace Math_ {
return r;
}
/**
* Returns a pseudorandom number between 0 and `max`.
*/
//%
int random(int max) {
if (max == INT_MIN)
@ -165,10 +124,6 @@ namespace Math_ {
return uBit.random(max);
}
/**
* Returns the square root of a number.
* @param x A numeric expression.
*/
//%
int sqrt(int x)
{
@ -176,7 +131,7 @@ namespace Math_ {
}
}
namespace ArrayImpl {
namespace Array_ {
//%
RefCollection *mk(uint32_t flags)
{
@ -334,65 +289,3 @@ namespace ksrt {
uBit.panic(code);
}
}
namespace buffer {
RefBuffer *mk(uint32_t size)
{
RefBuffer *r = new RefBuffer();
r->data.resize(size);
return r;
}
char *cptr(RefBuffer *c)
{
return (char*)&c->data[0];
}
int count(RefBuffer *c) { return c->data.size(); }
void fill(RefBuffer *c, int v)
{
memset(cptr(c), v, count(c));
}
void fill_random(RefBuffer *c)
{
int len = count(c);
for (int i = 0; i < len; ++i)
c->data[i] = uBit.random(0x100);
}
void add(RefBuffer *c, uint32_t x) {
c->data.push_back(x);
}
inline bool in_range(RefBuffer *c, int x) {
return (0 <= x && x < (int)c->data.size());
}
uint32_t at(RefBuffer *c, int x) {
if (in_range(c, x)) {
return c->data[x];
}
else {
error(ERR_OUT_OF_BOUNDS);
return 0;
}
}
void set(RefBuffer *c, int x, uint32_t y) {
if (!in_range(c, x))
return;
c->data[x] = y;
}
}
namespace bitvm_bits {
RefBuffer *create_buffer(int size)
{
return buffer::mk(size);
}
}

View File

@ -4,14 +4,14 @@ interface Array<T> {
/**
* Gets or sets the length of the array. This is a number one higher than the highest element defined in an array.
*/
//% shim=ArrayImpl::length
//% shim=Array_::length
length: number;
/**
* Appends new elements to an array.
* @param items New elements of the Array.
*/
//% shim=ArrayImpl::push
//% shim=Array_::push
push(item: T): void;
/**
@ -41,11 +41,11 @@ interface Array<T> {
slice(start: number, end: number): T[];
/** Removes the first occurence of an object. Returns true if removed. */
//% shim=ArrayImpl::removeElement
//% shim=Array_::removeElement
removeElement(element:T) : boolean;
/** Removes the object at position index. */
//% shim=ArrayImpl::removeAt
//% shim=Array_::removeAt
removeAt(idx:number) : void;
@ -69,31 +69,110 @@ interface Array<T> {
* @param searchElement The value to locate in the array.
* @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the search starts at index 0.
*/
//% shim=ArrayImpl::indexOf
//% shim=Array_::indexOf
indexOf(searchElement: T, fromIndex?: number): number;
[n: number]: T;
}
declare interface String {
/**
* Returns the character at the specified index.
* @param pos The zero-based index of the desired character.
*/
//% shim=String_::charAt
charAt(pos: number): string;
/**
* Returns the Unicode value of the character at the specified location.
* @param index The zero-based index of the desired character. If there is no character at the specified index, NaN is returned.
*/
//% shim=String_::charCodeAt
charCodeAt(index: number): number;
/**
* Returns a string that contains the concatenation of two or more strings.
* @param other The string to append to the end of the string.
*/
//% shim=String_::concat
concat(other: string): string;
/**
* Determines whether relative order of two strings (in ASCII encoding).
* @param that String to compare to target string
*/
//% shim=String_::compare
compare(that: string): number;
/** Returns the length of a String object. */
//% property shim=String_::length
length: number;
interface String {
[index: number]: string;
}
interface Buffer {
[index: number]: number;
}
/**
* Converts A string to an integer.
* @param s A string to convert into a number.
*/
//% shim=String_::toNumber
//% shim=String_::toNumber
declare function parseInt(s: string): number;
interface Object {}
interface Function {}
interface IArguments {}
interface RegExp {}
declare interface Boolean {
/**
* Returns a string representation of an object.
*/
//% shim=Boolean_::toString
toString(): string;
}
declare namespace String {
/**
* Make a string from the given ASCII character code.
*/
//% shim=String_::fromCharCode
function fromCharCode(code: number): string;
}
declare interface Number {
/**
* Returns a string representation of a number.
*/
//% shim=Number_::toString
toString(): string;
}
declare namespace Math {
/**
* Returns the value of a base expression taken to a specified power.
* @param x The base value of the expression.
* @param y The exponent value of the expression.
*/
//% shim=Math_::pow
function pow(x: number, y: number): number;
/**
* Returns a pseudorandom number between 0 and `max`.
*/
//% shim=Math_::random
function random(max: number): number;
/**
* Returns the square root of a number.
* @param x A numeric expression.
*/
//% shim=Math_::sqrt
function sqrt(x: number): number;
}

View File

@ -271,4 +271,19 @@ declare namespace pins {
declare namespace serial {
}
declare 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.

6
libs/microbit/helpers.ts Normal file
View File

@ -0,0 +1,6 @@
namespace console {
export function log(msg: string) {
serial.writeString(msg);
serial.writeString("\r\n");
}
}

View File

@ -7,10 +7,11 @@
"dal.d.ts",
"enums.d.ts",
"shims.d.ts",
"core.d.ts",
"ks-core.d.ts",
"ksbit.h",
"core.cpp",
"mbit.ts",
"ks-helpers.ts",
"helpers.ts",
"images.cpp",
"basic.cpp",
"input.cpp",
@ -22,6 +23,7 @@
"led.ts",
"music.ts",
"pins.cpp",
"pins.ts",
"serial.cpp",
"serial.ts",
"buffer.cpp"
@ -32,69 +34,5 @@
"config": {
"MESSAGE_BUS_LISTENER_DEFAULT_FLAGS": "MESSAGE_BUS_LISTENER_QUEUE_IF_BUSY"
}
},
"target": {
"id": "microbit",
"name": "BBC micro:bit",
"title": "JavaScript for BBC micro:bit",
"cloud": {
"workspace": false,
"packages": true
},
"blocksprj": {
"id": "blocksprj",
"config": {
"name": "{0} block",
"dependencies": {
"microbit": "*",
"microbit-radio": "*"
},
"description": "",
"files": [
"main.blocks",
"main.blocks.ts",
"README.md"
]
},
"files": {
"main.blocks": "<xml xmlns=\"http://www.w3.org/1999/xhtml\"><block type=\"device_print_message\"><value name=\"text\"><shadow type=\"text\"><field name=\"TEXT\">Hello!</field></shadow></value></block></xml>",
"main.blocks.ts": "\n",
"README.md": "Describe your project here!"
}
},
"tsprj": {
"id": "tsprj",
"config": {
"name": "{0} bit",
"dependencies": {
"microbit": "*",
"microbit-radio": "*"
},
"description": "",
"files": [
"main.ts",
"README.md"
]
},
"files": {
"main.ts": "basic.showString('Hello!')\n",
"README.md": "Describe your project here!"
}
},
"compile": {
"isNative": false,
"hasHex": true
},
"simulator": {
"autoRun": true
},
"compileService": {
"gittag": "v0.1.5",
"serviceId": "ws"
},
"serial": {
"manufacturerFilter": "^mbed$",
"log": true
}
}
}

View File

@ -1,64 +0,0 @@
type Action = () => void;
namespace helpers {
export function arraySplice<T>(arr: T[], start: number, len: number) {
if (start < 0) {
return;
}
for (let i = 0; i < len; ++i) {
arr.removeAt(start)
}
}
}
namespace console {
export function log(msg: string) {
serial.writeString(msg);
serial.writeString("\r\n");
}
}
namespace Math {
export function clamp(min: number, max:number, value:number): number {
return Math.min(max, Math.max(min, value));
}
/**
* Returns the absolute value of a number (the value without regard to whether it is positive or negative).
* For example, the absolute value of -5 is the same as the absolute value of 5.
* @param x A numeric expression for which the absolute value is needed.
*/
export function abs(x: number): number
{
return x < 0 ? -x : x;
}
/**
* Returns the sign of the x, indicating whether x is positive, negative or zero.
* @param x The numeric expression to test
*/
export function sign(x: number): number
{
if (x == 0) return 0;
if (x > 0) return 1;
return -1;
}
/**
* Returns the larger of two supplied numeric expressions.
*/
export function max(a:number, b:number): number
{
if (a >= b) return a;
return b;
}
/**
* Returns the smaller of two supplied numeric expressions.
*/
export function min(a:number, b:number): number
{
if (a <= b) return a;
return b;
}
}

View File

@ -195,25 +195,24 @@ namespace pins {
{
return ManagedBuffer(size).leakData();
}
/**
* Read `size` bytes from a 7-bit I2C `address`.
*/
//%
Buffer i2cReadBuffer(int address, int size, bool repeat = false)
{
Buffer buf = createBuffer(size);
uBit.i2c.read(address << 1, (char*)buf->payload, size, repeat);
return buf;
}
// TODO:
void i2cReadBuffer(int address, RefBuffer *buf)
/**
* Write bytes to a 7-bit I2C `address`.
*/
//%
void i2cWriteBuffer(int address, Buffer buf, bool repeat = false)
{
uBit.i2c.read(address << 1, buf->cptr(), buf->size());
}
void i2cWriteBuffer(int address, RefBuffer *buf)
{
uBit.i2c.write(address << 1, buf->cptr(), buf->size());
}
int i2cReadRaw(int address, char *data, int length, int repeated)
{
return uBit.i2c.read(address, data, length, repeated);
}
int i2cWriteRaw(int address, const char *data, int length, int repeated)
{
return uBit.i2c.write(address, data, length, repeated);
uBit.i2c.write(address << 1, (char*)buf->payload, buf->length, repeat);
}
}

View File

@ -13,4 +13,49 @@ namespace pins {
export function map(value: number, fromLow: number, fromHigh: number, toLow: number, toHigh: number): number {
return ((value - fromLow) * (toHigh - toLow)) / (fromHigh - fromLow) + toLow;
}
/**
* Read one number from 7-bit I2C address.
*/
export function i2cReadNumber(address: number, format: NumberFormat): number {
let buf = pins.i2cReadBuffer(address, pins.sizeOf(format))
return buf.getNumber(format, 0)
}
/**
* Write one number to a 7-bit I2C address.
*/
export function i2cWriteNumber(address: number, value: number, format: NumberFormat): void {
let buf = createBuffer(pins.sizeOf(format))
buf.setNumber(format, 0, value)
pins.i2cWriteBuffer(address, buf)
}
/**
* Get the size in bytes of specified number format.
*/
export function sizeOf(format: NumberFormat) {
switch (format) {
case NumberFormat.Int8LE:
case NumberFormat.UInt8LE:
case NumberFormat.Int8BE:
case NumberFormat.UInt8BE:
return 1;
case NumberFormat.Int16LE:
case NumberFormat.UInt16LE:
case NumberFormat.Int16BE:
case NumberFormat.UInt16BE:
return 2;
case NumberFormat.Int32LE:
case NumberFormat.Int32BE:
return 4;
}
return 0;
}
}
interface Buffer {
[index: number]: number;
// rest defined in buffer.cpp
}

View File

@ -1,90 +1,6 @@
// Auto-generated. Do not edit.
declare interface String {
/**
* Returns the character at the specified index.
* @param pos The zero-based index of the desired character.
*/
//% shim=StringMethods::charAt
charAt(pos: number): string;
/**
* Returns the Unicode value of the character at the specified location.
* @param index The zero-based index of the desired character. If there is no character at the specified index, NaN is returned.
*/
//% shim=StringMethods::charCodeAt
charCodeAt(index: number): number;
/**
* Returns a string that contains the concatenation of two or more strings.
* @param other The string to append to the end of the string.
*/
//% shim=StringMethods::concat
concat(other: string): string;
/**
* Determines whether relative order of two strings (in ASCII encoding).
* @param that String to compare to target string
*/
//% shim=StringMethods::compare
compare(that: string): number;
/** Returns the length of a String object. */
//% property shim=StringMethods::length
length: number;
}
declare interface Boolean {
/**
* Returns a string representation of an object.
*/
//% shim=BooleanMethods::toString
toString(): string;
}
declare namespace String {
/**
* Make a string from the given ASCII character code.
*/
//% shim=String_::fromCharCode
function fromCharCode(code: number): string;
}
declare interface Number {
/**
* Returns a string representation of a number.
*/
//% shim=NumberMethods::toString
toString(): string;
}
declare namespace Math {
/**
* Returns the value of a base expression taken to a specified power.
* @param x The base value of the expression.
* @param y The exponent value of the expression.
*/
//% shim=Math_::pow
function pow(x: number, y: number): number;
/**
* Returns a pseudorandom number between 0 and `max`.
*/
//% shim=Math_::random
function random(max: number): number;
/**
* Returns the square root of a number.
* @param x A numeric expression.
*/
//% shim=Math_::sqrt
function sqrt(x: number): number;
}
//% color=45 weight=31
declare namespace images {
@ -375,7 +291,7 @@ declare namespace control {
*/
//% weight=21 blockGap=12 blockId="control_raise_event" block="raise event|from source %src=control_event_source|with value %value=control_event_value" blockExternalInputs=1
//% mode.defl=1 shim=control::raiseEvent
function raiseEvent(src: number, value: number, mode: EventCreationMode): void;
function raiseEvent(src: number, value: number, mode?: EventCreationMode): void;
/**
* Raises an event in the event bus.
@ -541,6 +457,18 @@ declare namespace pins {
*/
//% shim=pins::createBuffer
function createBuffer(size: number): Buffer;
/**
* Read `size` bytes from a 7-bit I2C `address`.
*/
//% repeat.defl=0 shim=pins::i2cReadBuffer
function i2cReadBuffer(address: number, size: number, repeat?: boolean): Buffer;
/**
* Write bytes to a 7-bit I2C `address`.
*/
//% repeat.defl=0 shim=pins::i2cWriteBuffer
function i2cWriteBuffer(address: number, buf: Buffer, repeat?: boolean): void;
}
@ -577,6 +505,18 @@ declare namespace serial {
//% indexerGet=BufferMethods::getByte indexerSet=BufferMethods::setByte
declare interface Buffer {
/**
* Write a number in specified format in the buffer.
*/
//% shim=BufferMethods::setNumber
setNumber(format: NumberFormat, offset: number, value: number): void;
/**
* Read a number in specified format from the buffer.
*/
//% shim=BufferMethods::getNumber
getNumber(format: NumberFormat, offset: number): number;
/** Returns the length of a Buffer object. */
//% property shim=BufferMethods::length
length: number;

View File

@ -1,6 +1,6 @@
{
"name": "kindscript-microbit",
"version": "0.2.14",
"version": "0.2.19",
"description": "BBC micro:bit target for KindScript",
"keywords": [
"JavaScript",
@ -17,7 +17,6 @@
"files": [
"README.md",
"kindtarget.json",
"kindtheme.json",
"built/*.js",
"built/*.json",
"built/*.d.ts",
@ -30,6 +29,6 @@
"typescript": "^1.8.7"
},
"dependencies": {
"kindscript": "0.2.16"
"kindscript": "0.2.22"
}
}

View File

@ -145,6 +145,7 @@ namespace ks.rt {
namespace ks.rt.basic {
export var pause = thread.pause;
export var forever = thread.forever;
export function showNumber(x: number, interval: number) {
if (interval < 0) return;
@ -198,17 +199,6 @@ namespace ks.rt.basic {
scrollImage(leds, interval, 5);
}
export function forever(a: RefAction) {
function loop() {
runtime.runFiberAsync(a)
.then(() => Promise.delay(20))
.then(loop)
.done()
}
incr(a)
loop()
}
export function plotLeds(leds: Image): void {
leds.copyTo(0, 5, board().image, 0)
runtime.queueDisplayUpdate()