Compare commits
16 Commits
Author | SHA1 | Date | |
---|---|---|---|
46d42e5300 | |||
ffabb9b16d | |||
d62c10d278 | |||
e2b2aa7ff1 | |||
664c8dcd35 | |||
bd7430b642 | |||
61fd28d840 | |||
c33df897d5 | |||
3bb0bd2a9f | |||
7751061b51 | |||
88a7fa5038 | |||
3c8a62df54 | |||
c661fd0eca | |||
8a124812b6 | |||
02c41b59bd | |||
b003af6eae |
@ -3,7 +3,7 @@ node_js:
|
|||||||
- "5.7.0"
|
- "5.7.0"
|
||||||
script:
|
script:
|
||||||
- "node node_modules/kindscript/built/kind.js travis"
|
- "node node_modules/kindscript/built/kind.js travis"
|
||||||
- "cd libs/lang-test0; node ../../node_modules/kindscript/built/kind.js run"
|
- "(cd libs/lang-test0; node ../../node_modules/kindscript/built/kind.js run)"
|
||||||
- "node node_modules/kindscript/built/kind.js uploaddoc"
|
- "node node_modules/kindscript/built/kind.js uploaddoc"
|
||||||
sudo: false
|
sudo: false
|
||||||
notifications:
|
notifications:
|
||||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -6,6 +6,7 @@
|
|||||||
],
|
],
|
||||||
"public": true,
|
"public": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"microbit": "file:../microbit"
|
"microbit": "file:../microbit",
|
||||||
|
"microbit-radio": "file:../microbit-radio"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,6 +59,7 @@ testMemoryFreeHOF();
|
|||||||
postPreFix()
|
postPreFix()
|
||||||
eqOp()
|
eqOp()
|
||||||
testEnums()
|
testEnums()
|
||||||
|
testBuffer()
|
||||||
|
|
||||||
// test some top-level code
|
// test some top-level code
|
||||||
let xsum = 0;
|
let xsum = 0;
|
||||||
@ -722,3 +723,52 @@ function switchB(e: En) {
|
|||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function bufferIs(b:Buffer, a:number[]) {
|
||||||
|
assert(b.length == a.length, "bis-len")
|
||||||
|
for (let i = 0; i < a.length; ++i) {
|
||||||
|
if (a[i] != b[i]) {
|
||||||
|
assert(false, `bufferIs: buf[${i}]:${b[i]} != ${a[i]}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function testBuffer() {
|
||||||
|
let b = pins.createBuffer(3);
|
||||||
|
assert(b[0] == 0, "buf0");
|
||||||
|
assert(b[1] == 0, "buf0");
|
||||||
|
assert(b[2] == 0, "buf0");
|
||||||
|
assert(b[-100000] == 0, "bufM");
|
||||||
|
assert(b[100000] == 0, "bufM");
|
||||||
|
|
||||||
|
b[0] = 42;
|
||||||
|
bufferIs(b, [42, 0, 0]);
|
||||||
|
b[2] = 41;
|
||||||
|
bufferIs(b, [42, 0, 41]);
|
||||||
|
|
||||||
|
b.rotate(1)
|
||||||
|
bufferIs(b, [0, 41, 42]);
|
||||||
|
b.rotate(-2)
|
||||||
|
bufferIs(b, [41, 42, 0]);
|
||||||
|
b.shift(1)
|
||||||
|
bufferIs(b, [42, 0, 0]);
|
||||||
|
b.rotate(9)
|
||||||
|
bufferIs(b, [42, 0, 0]);
|
||||||
|
b.rotate(-9)
|
||||||
|
bufferIs(b, [42, 0, 0]);
|
||||||
|
|
||||||
|
b.fill(4);
|
||||||
|
bufferIs(b, [4, 4, 4]);
|
||||||
|
|
||||||
|
b.fill(12, 1, 1);
|
||||||
|
bufferIs(b, [4, 12, 4]);
|
||||||
|
|
||||||
|
b.fill(13, 1, -1);
|
||||||
|
bufferIs(b, [4, 13, 13]);
|
||||||
|
|
||||||
|
b.fill(100, -1, -1);
|
||||||
|
bufferIs(b, [4, 13, 13]);
|
||||||
|
|
||||||
|
b.shift(-1)
|
||||||
|
bufferIs(b, [0, 4, 13]);
|
||||||
|
}
|
||||||
|
155
libs/microbit/buffer.cpp
Normal file
155
libs/microbit/buffer.cpp
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
#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 {
|
||||||
|
//%
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
//%
|
||||||
|
void shift(Buffer buf, int offset)
|
||||||
|
{
|
||||||
|
ManagedBuffer(buf).shift(offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rotate buffer left in place.
|
||||||
|
* @param offset number of bytes to shift; use negative value to shift right
|
||||||
|
*/
|
||||||
|
//%
|
||||||
|
void rotate(Buffer buf, int offset)
|
||||||
|
{
|
||||||
|
ManagedBuffer(buf).rotate(offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
@ -324,7 +324,7 @@ namespace ksrt {
|
|||||||
RefAction *stclo(RefAction *a, int idx, uint32_t v)
|
RefAction *stclo(RefAction *a, int idx, uint32_t v)
|
||||||
{
|
{
|
||||||
//DBG("STCLO "); a->print(); DBG("@%d = %p\n", idx, (void*)v);
|
//DBG("STCLO "); a->print(); DBG("@%d = %p\n", idx, (void*)v);
|
||||||
a->st(idx, v);
|
a->stCore(idx, v);
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -334,65 +334,3 @@ namespace ksrt {
|
|||||||
uBit.panic(code);
|
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
5
libs/microbit/core.d.ts
vendored
5
libs/microbit/core.d.ts
vendored
@ -82,6 +82,10 @@ interface String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
interface Buffer {
|
||||||
|
[index: number]: number;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts A string to an integer.
|
* Converts A string to an integer.
|
||||||
* @param s A string to convert into a number.
|
* @param s A string to convert into a number.
|
||||||
@ -93,4 +97,3 @@ interface Object {}
|
|||||||
interface Function {}
|
interface Function {}
|
||||||
interface IArguments {}
|
interface IArguments {}
|
||||||
interface RegExp {}
|
interface RegExp {}
|
||||||
|
|
||||||
|
15
libs/microbit/enums.d.ts
vendored
15
libs/microbit/enums.d.ts
vendored
@ -271,4 +271,19 @@ declare namespace pins {
|
|||||||
declare namespace serial {
|
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.
|
// Auto-generated. Do not edit. Really.
|
||||||
|
@ -22,8 +22,10 @@
|
|||||||
"led.ts",
|
"led.ts",
|
||||||
"music.ts",
|
"music.ts",
|
||||||
"pins.cpp",
|
"pins.cpp",
|
||||||
|
"pins.ts",
|
||||||
"serial.cpp",
|
"serial.cpp",
|
||||||
"serial.ts"
|
"serial.ts",
|
||||||
|
"buffer.cpp"
|
||||||
],
|
],
|
||||||
"public": true,
|
"public": true,
|
||||||
"dependencies": {},
|
"dependencies": {},
|
||||||
@ -31,69 +33,5 @@
|
|||||||
"config": {
|
"config": {
|
||||||
"MESSAGE_BUS_LISTENER_DEFAULT_FLAGS": "MESSAGE_BUS_LISTENER_QUEUE_IF_BUSY"
|
"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.2",
|
|
||||||
"serviceId": "ws"
|
|
||||||
},
|
|
||||||
"serial": {
|
|
||||||
"manufacturerFilter": "^mbed$",
|
|
||||||
"log": true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#include "kindscript.h"
|
#include "kindscript.h"
|
||||||
|
#include "ManagedBuffer.h"
|
||||||
|
|
||||||
using namespace kindscript;
|
using namespace kindscript;
|
||||||
MicroBitPin *getPin(int id);
|
MicroBitPin *getPin(int id);
|
||||||
typedef ImageData* Image;
|
typedef ImageData* Image;
|
||||||
|
typedef BufferData* Buffer;
|
||||||
|
|
||||||
|
@ -69,6 +69,13 @@ namespace pins {
|
|||||||
if (!pin) return 0; \
|
if (!pin) return 0; \
|
||||||
return pin->op
|
return pin->op
|
||||||
|
|
||||||
|
|
||||||
|
//%
|
||||||
|
MicroBitPin *getPinAddress(int id) {
|
||||||
|
return getPin(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read the specified pin or connector as either 0 or 1
|
* Read the specified pin or connector as either 0 or 1
|
||||||
* @param name pin to read from
|
* @param name pin to read from
|
||||||
@ -179,24 +186,33 @@ namespace pins {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO:
|
/**
|
||||||
void i2cReadBuffer(int address, RefBuffer *buf)
|
* Create a new zero-initialized buffer.
|
||||||
|
* @param size number of bytes in the buffer
|
||||||
|
*/
|
||||||
|
//%
|
||||||
|
Buffer createBuffer(int size)
|
||||||
{
|
{
|
||||||
uBit.i2c.read(address << 1, buf->cptr(), buf->size());
|
return ManagedBuffer(size).leakData();
|
||||||
}
|
}
|
||||||
|
|
||||||
void i2cWriteBuffer(int address, RefBuffer *buf)
|
/**
|
||||||
|
* Read `size` bytes from a 7-bit I2C `address`.
|
||||||
|
*/
|
||||||
|
//%
|
||||||
|
Buffer i2cReadBuffer(int address, int size, bool repeat = false)
|
||||||
{
|
{
|
||||||
uBit.i2c.write(address << 1, buf->cptr(), buf->size());
|
Buffer buf = createBuffer(size);
|
||||||
|
uBit.i2c.read(address << 1, (char*)buf->payload, size, repeat);
|
||||||
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
int i2cReadRaw(int address, char *data, int length, int repeated)
|
/**
|
||||||
|
* Write bytes to a 7-bit I2C `address`.
|
||||||
|
*/
|
||||||
|
//%
|
||||||
|
void i2cWriteBuffer(int address, Buffer buf, bool repeat = false)
|
||||||
{
|
{
|
||||||
return uBit.i2c.read(address, data, length, repeated);
|
uBit.i2c.write(address << 1, (char*)buf->payload, buf->length, repeat);
|
||||||
}
|
|
||||||
|
|
||||||
int i2cWriteRaw(int address, const char *data, int length, int repeated)
|
|
||||||
{
|
|
||||||
return uBit.i2c.write(address, data, length, repeated);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,4 +13,43 @@ namespace pins {
|
|||||||
export function map(value: number, fromLow: number, fromHigh: number, toLow: number, toHigh: number): number {
|
export function map(value: number, fromLow: number, fromHigh: number, toLow: number, toHigh: number): number {
|
||||||
return ((value - fromLow) * (toHigh - toLow)) / (fromHigh - fromLow) + toLow;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
76
libs/microbit/shims.d.ts
vendored
76
libs/microbit/shims.d.ts
vendored
@ -374,8 +374,8 @@ declare namespace control {
|
|||||||
* @param mode optional definition of how the event should be processed after construction (default is CREATE_AND_QUEUE).
|
* @param mode optional definition of how the event should be processed after construction (default is CREATE_AND_QUEUE).
|
||||||
*/
|
*/
|
||||||
//% 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
|
//% 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
|
//% 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.
|
* Raises an event in the event bus.
|
||||||
@ -534,6 +534,25 @@ declare namespace pins {
|
|||||||
*/
|
*/
|
||||||
//% help=pins/analog-pitch weight=14 async shim=pins::analogPitch
|
//% help=pins/analog-pitch weight=14 async shim=pins::analogPitch
|
||||||
function analogPitch(frequency: number, ms: number): void;
|
function analogPitch(frequency: number, ms: number): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new zero-initialized buffer.
|
||||||
|
* @param size number of bytes in the buffer
|
||||||
|
*/
|
||||||
|
//% 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -566,4 +585,57 @@ declare namespace serial {
|
|||||||
function readScreen(): void;
|
function readScreen(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//% 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fill (a fragment) of the buffer with given value.
|
||||||
|
*/
|
||||||
|
//% offset.defl=0 length.defl=-1 shim=BufferMethods::fill
|
||||||
|
fill(value: number, offset?: number, length?: number): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a copy of a fragment of a buffer.
|
||||||
|
*/
|
||||||
|
//% offset.defl=0 length.defl=-1 shim=BufferMethods::slice
|
||||||
|
slice(offset?: number, length?: number): Buffer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shift buffer left in place, with zero padding.
|
||||||
|
* @param offset number of bytes to shift; use negative value to shift right
|
||||||
|
*/
|
||||||
|
//% shim=BufferMethods::shift
|
||||||
|
shift(offset: number): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rotate buffer left in place.
|
||||||
|
* @param offset number of bytes to shift; use negative value to shift right
|
||||||
|
*/
|
||||||
|
//% shim=BufferMethods::rotate
|
||||||
|
rotate(offset: number): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write contents of `src` at `dstOffset` in current buffer.
|
||||||
|
*/
|
||||||
|
//% shim=BufferMethods::write
|
||||||
|
write(dstOffset: number, src: Buffer): void;
|
||||||
|
}
|
||||||
|
|
||||||
// Auto-generated. Do not edit. Really.
|
// Auto-generated. Do not edit. Really.
|
||||||
|
20
libs/neopixel/kind.json
Normal file
20
libs/neopixel/kind.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"name": "neppixel",
|
||||||
|
"description": "AdaFruit NeoPixel driver for micro:bit",
|
||||||
|
"files": [
|
||||||
|
"neopixel.ts",
|
||||||
|
"sendbuffer.asm"
|
||||||
|
],
|
||||||
|
"testFiles": [
|
||||||
|
"neotest.ts"
|
||||||
|
],
|
||||||
|
"microbit": {
|
||||||
|
"config": {
|
||||||
|
"MICROBIT_BLE_ENABLED": "0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"public": true,
|
||||||
|
"dependencies": {
|
||||||
|
"microbit": "file:../microbit"
|
||||||
|
}
|
||||||
|
}
|
88
libs/neopixel/neopixel.ts
Normal file
88
libs/neopixel/neopixel.ts
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
namespace neopixel {
|
||||||
|
|
||||||
|
//% shim=sendBufferAsm
|
||||||
|
function sendBuffer(buf: Buffer, pin: DigitalPin) {
|
||||||
|
}
|
||||||
|
|
||||||
|
class Strip {
|
||||||
|
buf: Buffer;
|
||||||
|
pin: DigitalPin;
|
||||||
|
brightness: number;
|
||||||
|
|
||||||
|
length() {
|
||||||
|
return this.buf.length / 3
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the brightness of the strip, 0-255.
|
||||||
|
*/
|
||||||
|
setBrigthness(brightness: number): void {
|
||||||
|
this.brightness = brightness;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the pin where the neopixel is connected, defaults to P0.
|
||||||
|
*/
|
||||||
|
setPin(pin: DigitalPin): void {
|
||||||
|
this.pin = pin;
|
||||||
|
pins.digitalWritePin(this.pin, 0)
|
||||||
|
basic.pause(50)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turn off all LEDs.
|
||||||
|
*/
|
||||||
|
clear(): void {
|
||||||
|
this.buf.fill(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shift LEDs forward.
|
||||||
|
*/
|
||||||
|
shift(off: number): void {
|
||||||
|
this.buf.shift(-off * 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shift LEDs forward.
|
||||||
|
*/
|
||||||
|
rotate(): void {
|
||||||
|
this.buf.rotate(-3)
|
||||||
|
}
|
||||||
|
|
||||||
|
display() {
|
||||||
|
basic.pause(1)
|
||||||
|
sendBuffer(this.buf, this.pin);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set give LED to a given color (range 0-255 for r, g, b)
|
||||||
|
*/
|
||||||
|
setPix(ledoff: number, r: number, g: number, b: number): void {
|
||||||
|
ledoff = ledoff * 3;
|
||||||
|
let br = this.brightness;
|
||||||
|
if (br < 255) {
|
||||||
|
r = (Math.clamp(0, 255, r) * br) >> 8;
|
||||||
|
g = (Math.clamp(0, 255, b) * br) >> 8;
|
||||||
|
b = (Math.clamp(0, 255, b) * br) >> 8;
|
||||||
|
}
|
||||||
|
let buf = this.buf;
|
||||||
|
buf[ledoff + 0] = Math.clamp(0, 255, g);
|
||||||
|
buf[ledoff + 1] = Math.clamp(0, 255, r);
|
||||||
|
buf[ledoff + 2] = Math.clamp(0, 255, b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new NeoPixel driver for `numleds` LEDs.
|
||||||
|
* @params numleds number of leds in the strip, eg: 24,30,60,64
|
||||||
|
*/
|
||||||
|
export function create(numleds: number): Strip {
|
||||||
|
let strip = new Strip();
|
||||||
|
strip.buf = pins.createBuffer(numleds * 3);
|
||||||
|
strip.setBrigthness(255)
|
||||||
|
strip.setPin(DigitalPin.P0)
|
||||||
|
return strip;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
92
libs/neopixel/neotest.ts
Normal file
92
libs/neopixel/neotest.ts
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
basic.showLeds(`
|
||||||
|
# . . . .
|
||||||
|
. . . . .
|
||||||
|
. . # . .
|
||||||
|
. . . . .
|
||||||
|
. . . . #
|
||||||
|
`)
|
||||||
|
console.log("Start")
|
||||||
|
|
||||||
|
// Create a NeoPixel driver - specify the number of LEDs:
|
||||||
|
let strip = neopixel.create(7);
|
||||||
|
|
||||||
|
// If your strip is not at P0, specify the pin.
|
||||||
|
strip.setPin(DigitalPin.P0)
|
||||||
|
|
||||||
|
// Brightness defaults to 255 (very bright); 0 is completely off.
|
||||||
|
strip.setBrigthness(20)
|
||||||
|
|
||||||
|
// Set pixels - pixel number, followed by red, green and blue values, between 0 and 255.
|
||||||
|
strip.setPix(0, 255, 255, 255);
|
||||||
|
strip.setPix(1, 0, 255, 255);
|
||||||
|
strip.setPix(2, 255, 0, 255);
|
||||||
|
strip.setPix(3, 255, 255, 0);
|
||||||
|
|
||||||
|
console.log("Send!")
|
||||||
|
|
||||||
|
// Send the image to the strip.
|
||||||
|
strip.display();
|
||||||
|
basic.pause(500);
|
||||||
|
|
||||||
|
console.log("Sent!")
|
||||||
|
|
||||||
|
// Green light travelling the strip:
|
||||||
|
for (let l = 0; l < strip.length(); l++) {
|
||||||
|
strip.clear();
|
||||||
|
strip.setPix(l, 0, 255, 0);
|
||||||
|
strip.display();
|
||||||
|
basic.pause(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
let special = false;
|
||||||
|
let numcol = 0;
|
||||||
|
input.onButtonPressed(Button.A, () => {
|
||||||
|
special = true;
|
||||||
|
let r = 0;
|
||||||
|
let g = 0;
|
||||||
|
let b = 0;
|
||||||
|
if (numcol == 0) {
|
||||||
|
r = 255;
|
||||||
|
g = 255;
|
||||||
|
b = 255;
|
||||||
|
} else if (numcol == 1) {
|
||||||
|
r = 255;
|
||||||
|
} else if (numcol == 2) {
|
||||||
|
b = 255;
|
||||||
|
} else if (numcol == 3) {
|
||||||
|
r = 255;
|
||||||
|
g = 255;
|
||||||
|
} else if (numcol == 4) {
|
||||||
|
r = 10;
|
||||||
|
g = 10;
|
||||||
|
b = 10;
|
||||||
|
}
|
||||||
|
numcol = (numcol + 1) % 5;
|
||||||
|
for (let k = 0; k < 7; k++) {
|
||||||
|
strip.setPix(k, r, g, b);
|
||||||
|
}
|
||||||
|
strip.display();
|
||||||
|
});
|
||||||
|
|
||||||
|
control.inBackground(() => {
|
||||||
|
for (let j = 0; j < 2000000; j++) {
|
||||||
|
if (special) {
|
||||||
|
basic.pause(100);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let r1 = (0 + j * 2) & 63;
|
||||||
|
let g1 = (20 + j * 1) & 63;
|
||||||
|
let b1 = (30 + j * 3) & 63;
|
||||||
|
for (let i = 0; i < strip.length(); i++) {
|
||||||
|
strip.setPix(i, (r1 - i) * 20, (g1 - i) * 20, (b1 - i) * 20);
|
||||||
|
}
|
||||||
|
strip.display()
|
||||||
|
basic.pause(60);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
control.inBackground(() => {
|
||||||
|
while (true) {
|
||||||
|
basic.showString("XMAS!", 150);
|
||||||
|
}
|
||||||
|
});
|
67
libs/neopixel/sendbuffer.asm
Normal file
67
libs/neopixel/sendbuffer.asm
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
sendBufferAsm:
|
||||||
|
|
||||||
|
push {r4,r5,r6,r7,lr}
|
||||||
|
|
||||||
|
mov r4, r0 ; save buff
|
||||||
|
mov r6, r1 ; save pin
|
||||||
|
|
||||||
|
mov r0, r4
|
||||||
|
bl BufferMethods::length
|
||||||
|
mov r5, r0
|
||||||
|
|
||||||
|
mov r0, r4
|
||||||
|
bl BufferMethods::getBytes
|
||||||
|
mov r4, r0
|
||||||
|
|
||||||
|
; setup pin as digital
|
||||||
|
mov r0, r6
|
||||||
|
movs r1, #0
|
||||||
|
bl pins::digitalWritePin
|
||||||
|
|
||||||
|
; load pin address
|
||||||
|
mov r0, r6
|
||||||
|
bl pins::getPinAddress
|
||||||
|
|
||||||
|
ldr r0, [r0, #8] ; get mbed DigitalOut from MicroBitPin
|
||||||
|
ldr r1, [r0, #4] ; r1-mask for this pin
|
||||||
|
ldr r2, [r0, #16] ; r2-clraddr
|
||||||
|
ldr r3, [r0, #12] ; r3-setaddr
|
||||||
|
|
||||||
|
cpsid i ; disable irq
|
||||||
|
|
||||||
|
b .start
|
||||||
|
|
||||||
|
.nextbit: ; C0
|
||||||
|
str r1, [r3, #0] ; pin := hi C2
|
||||||
|
tst r6, r0 ; C3
|
||||||
|
bne .islate ; C4
|
||||||
|
str r1, [r2, #0] ; pin := lo C6
|
||||||
|
.islate:
|
||||||
|
lsrs r6, r6, #1 ; r6 >>= 1 C7
|
||||||
|
bne .justbit ; C8
|
||||||
|
|
||||||
|
; not just a bit - need new byte
|
||||||
|
adds r4, #1 ; r4++ C9
|
||||||
|
subs r5, #1 ; r5-- C10
|
||||||
|
bcc .stop ; if (r5<0) goto .stop C11
|
||||||
|
.start:
|
||||||
|
movs r6, #0x80 ; reset mask C12
|
||||||
|
nop ; C13
|
||||||
|
|
||||||
|
.common: ; C13
|
||||||
|
str r1, [r2, #0] ; pin := lo C15
|
||||||
|
; always re-load byte - it just fits with the cycles better this way
|
||||||
|
ldrb r0, [r4, #0] ; r0 := *r4 C17
|
||||||
|
b .nextbit ; C20
|
||||||
|
|
||||||
|
.justbit: ; C10
|
||||||
|
; no nops, branch taken is already 3 cycles
|
||||||
|
b .common ; C13
|
||||||
|
|
||||||
|
.stop:
|
||||||
|
str r1, [r2, #0] ; pin := lo
|
||||||
|
cpsie i ; enable irq
|
||||||
|
|
||||||
|
pop {r4,r5,r6,r7,pc}
|
||||||
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "kindscript-microbit",
|
"name": "kindscript-microbit",
|
||||||
"version": "0.2.13",
|
"version": "0.2.17",
|
||||||
"description": "BBC micro:bit target for KindScript",
|
"description": "BBC micro:bit target for KindScript",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"JavaScript",
|
"JavaScript",
|
||||||
@ -17,7 +17,6 @@
|
|||||||
"files": [
|
"files": [
|
||||||
"README.md",
|
"README.md",
|
||||||
"kindtarget.json",
|
"kindtarget.json",
|
||||||
"kindtheme.json",
|
|
||||||
"built/*.js",
|
"built/*.js",
|
||||||
"built/*.json",
|
"built/*.json",
|
||||||
"built/*.d.ts",
|
"built/*.d.ts",
|
||||||
@ -30,6 +29,6 @@
|
|||||||
"typescript": "^1.8.7"
|
"typescript": "^1.8.7"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"kindscript": "0.2.15"
|
"kindscript": "0.2.19"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -527,4 +527,4 @@ namespace ks.rt.ImageMethods {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO ...
|
// TODO ...
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user