diff --git a/libs/microbit/buffer.cpp b/libs/microbit/buffer.cpp index 5abba58f..0dcdd860 100644 --- a/libs/microbit/buffer.cpp +++ b/libs/microbit/buffer.cpp @@ -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) { diff --git a/libs/microbit/enums.d.ts b/libs/microbit/enums.d.ts index 9737d884..e1fc28f2 100644 --- a/libs/microbit/enums.d.ts +++ b/libs/microbit/enums.d.ts @@ -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. diff --git a/libs/microbit/kind.json b/libs/microbit/kind.json index 9f9986a8..b675ddda 100644 --- a/libs/microbit/kind.json +++ b/libs/microbit/kind.json @@ -22,6 +22,7 @@ "led.ts", "music.ts", "pins.cpp", + "pins.ts", "serial.cpp", "serial.ts", "buffer.cpp" diff --git a/libs/microbit/pins.cpp b/libs/microbit/pins.cpp index 1cfa092b..2c960c88 100644 --- a/libs/microbit/pins.cpp +++ b/libs/microbit/pins.cpp @@ -195,25 +195,24 @@ namespace pins { { return ManagedBuffer(size).leakData(); } + + /** + * Read `size` bytes from a 7-bit I2C `address`. + */ + //% repeat.defl=0 + Buffer i2cReadBuffer(int address, int size, bool repeat) + { + 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`. + */ + //% repeat.defl=0 + void i2cWriteBuffer(int address, Buffer buf, bool repeat) { - 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); } } diff --git a/libs/microbit/pins.ts b/libs/microbit/pins.ts index f631d1df..e333bed8 100644 --- a/libs/microbit/pins.ts +++ b/libs/microbit/pins.ts @@ -13,4 +13,43 @@ 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), false) + 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, false) + } + + /** + * 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; + } } diff --git a/libs/microbit/shims.d.ts b/libs/microbit/shims.d.ts index fb28059e..f9cae3aa 100644 --- a/libs/microbit/shims.d.ts +++ b/libs/microbit/shims.d.ts @@ -541,6 +541,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 +589,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;