diff --git a/libs/microbit-radio/radio.cpp b/libs/microbit-radio/radio.cpp index 836b9a7e..f1731994 100644 --- a/libs/microbit-radio/radio.cpp +++ b/libs/microbit-radio/radio.cpp @@ -2,7 +2,7 @@ using namespace pxt; -#define RADIO_VALUE_PACKET_TYPE 24641622 +#define MAX_FIELD_NAME_LENGTH 12 //% color=270 weight=34 namespace radio { @@ -11,6 +11,8 @@ namespace radio { // Radio // ------------------------------------------------------------------------- bool radioEnabled = false; + bool transmitSerialNumber = false; + PacketBuffer packet; int radioEnable() { @@ -36,83 +38,84 @@ namespace radio { registerWithDal(MES_BROADCAST_GENERAL_ID, message, f); } - /** - * Broadcasts 4 numbers over radio to any connected micro:bit in the group. - */ - //% help=radio/send-numbers - //% weight=59 debug=true - //% blockId=radio_datagram_send_numbers block="send numbers|0: %VALUE0|1: %VALUE1|2: %VALUE2|3: %VALUE3" - void sendNumbers(int value_0, int value_1, int value_2, int value_3) { - if (radioEnable() != MICROBIT_OK) return; - int buf[] = { value_0, value_1, value_2, value_3 }; - uBit.radio.datagram.send((uint8_t*)buf, 4*sizeof(int)); + * Broadcasts a number over radio to any connected micro:bit in the group. + */ + //% help=radio/send-number + //% weight=60 + //% blockId=radio_datagram_send block="send number %MESSAGE" blockGap=8 + void sendNumber(int value) { + if (radioEnable() != MICROBIT_OK) return; + uint32_t t = system_timer_current_time(); + uint32_t sn = transmitSerialNumber ? microbit_serial_number() : 0; + uint32_t buf[] = { (uint32_t)value, t, sn }; + uBit.radio.datagram.send((uint8_t*)buf, 3*sizeof(uint32_t)); } /** * Broadcasts a name / value pair along with the device serial number * and running time to any connected BBC micro:bit in the group. * @param name the field name (max 12 characters), eg: "data" - * @param the numberic value + * @param value the numberic value */ //% help=radio/send-value - //% weight=4 debug=true + //% weight=59 //% blockId=radio_datagram_send_value block="send|value %name|= %value" - void sendValue(StringData* name, int number) { + void sendValue(StringData* name, int value) { if (radioEnable() != MICROBIT_OK) return; - ManagedString n(name); + ManagedString n(name); + uint32_t t = system_timer_current_time(); + uint32_t sn = transmitSerialNumber ? microbit_serial_number() : 0; uint8_t buf[32]; uint32_t* buf32 = (uint32_t*)buf; memset(buf, 32, 0); - buf32[0] = number; // 4 bytes: value - buf32[1] = microbit_serial_number(); // 4 bytes: serial number - buf32[2] = system_timer_current_time(); // 4 bytes: running time - memcpy(buf + 12, n.toCharArray(), min(12, n.length())); // 12-24: field name - buf32[7] = RADIO_VALUE_PACKET_TYPE; // last 4 bytes: magic number of package type - uBit.radio.datagram.send(buf, 32); + buf32[0] = value; // 4 bytes: value + buf32[1] = t; // 4 bytes: running time + buf32[2] = sn; // 4 bytes: serial number + uint8_t len = min(MAX_FIELD_NAME_LENGTH, n.length()); // 1 byte: string length + if (len > 0) { + buf[12] = len; // + memcpy(buf + 13, n.toCharArray(), len); // 13-25: field name + } + uBit.radio.datagram.send(buf, 13 + len); } /** * Reads a value sent with `stream value` and writes it * to the serial stream as JSON */ - //% help=radio/read-value-to-serial - //% weight=3 debug=true - void readValueToSerial() { + //% help=radio/write-value-to-serial + //% weight=3 + //% blockId=radio_write_value_serial block="write value to serial" + void writeValueToSerial() { if (radioEnable() != MICROBIT_OK) return; PacketBuffer p = uBit.radio.datagram.recv(); int length = p.length(); - if (length < 32) { - return; - } - uint8_t* bytes = p.getBytes(); - //uint32_t* buf32 = (uint32_t*)bytes; - //uint32_t type = buf32[7]; - //if (type != RADIO_VALUE_PACKET_TYPE) - //{ - // uBit.serial.send("type: "); - // uBit.serial.send(type); - // uBit.serial.send("\r\n"); - // return; - //} - int value; - int serial; - int time; - char name[12+1]; memset(name, 0, 13 * sizeof(char)); - memcpy(&value, bytes, 4); - memcpy(&serial, bytes + 4, 4); - memcpy(&time, bytes + 8, 4); - memcpy(&name, bytes + 12, 12); - - uBit.serial.send("{s:"); uBit.serial.send(serial); - uBit.serial.send(",t:"); uBit.serial.send(time); - uBit.serial.send(",v:"); uBit.serial.send(value); - uBit.serial.send(",n:\""); uBit.serial.send(name); - uBit.serial.send("\"}\r\n"); + uBit.serial.send("{"); + if (length >= 4) { + memcpy(&value, bytes, 4); + uBit.serial.send("v:"); uBit.serial.send(value); + if(length >= 8) { + memcpy(&value, bytes + 4, 4); + uBit.serial.send(",t:"); uBit.serial.send(value); + if (length >= 12) { + memcpy(&value, bytes + 8, 4); + uBit.serial.send(",s:"); uBit.serial.send(value); + if (length >= 13) { + char name[MAX_FIELD_NAME_LENGTH+1]; + uint8_t len = min(MAX_FIELD_NAME_LENGTH, bytes[12]); + memcpy(name, bytes + 13, len); + name[len] = 0; + uBit.serial.send(",n:\""); uBit.serial.send(name); uBit.serial.send("\""); + } + } + } + } + uBit.serial.send("}\r\n"); } /** @@ -192,4 +195,14 @@ namespace radio { if (radioEnable() != MICROBIT_OK) return; uBit.radio.setTransmitPower(power); } + + /** + * Set the radio to transmit the serial number in each message. + */ + //% help=radio/set-transmit-serial-number + //% weight=8 + //% block=radio_set_transmit_serial_number block="set tranmist serial number %transmit" + void setTransmitSerialNumber(bool transmit) { + transmitSerialNumber = transmit; + } } diff --git a/libs/microbit-radio/radio.ts b/libs/microbit-radio/radio.ts index 4106ca2c..942ca022 100644 --- a/libs/microbit-radio/radio.ts +++ b/libs/microbit-radio/radio.ts @@ -3,13 +3,4 @@ */ //% color=270 weight=34 namespace radio { - /** - * Broadcasts a number over radio to any connected micro:bit in the group. - */ - //% help=radio/send-number - //% weight=60 - //% blockId=radio_datagram_send block="send number %MESSAGE" blockGap=8 - export function sendNumber(value: number) : void { - sendNumbers(value, 0, 0, 0); - } } diff --git a/libs/microbit-radio/shims.d.ts b/libs/microbit-radio/shims.d.ts index 02ce7354..2887f967 100644 --- a/libs/microbit-radio/shims.d.ts +++ b/libs/microbit-radio/shims.d.ts @@ -6,31 +6,32 @@ declare namespace radio { /** - * Broadcasts 4 numbers over radio to any connected micro:bit in the group. + * Broadcasts a number over radio to any connected micro:bit in the group. */ - //% help=radio/send-numbers - //% weight=59 debug=true - //% blockId=radio_datagram_send_numbers block="send numbers|0: %VALUE0|1: %VALUE1|2: %VALUE2|3: %VALUE3" shim=radio::sendNumbers - function sendNumbers(value_0: number, value_1: number, value_2: number, value_3: number): void; + //% help=radio/send-number + //% weight=60 + //% blockId=radio_datagram_send block="send number %MESSAGE" blockGap=8 shim=radio::sendNumber + function sendNumber(value: number): void; /** * Broadcasts a name / value pair along with the device serial number * and running time to any connected BBC micro:bit in the group. * @param name the field name (max 12 characters), eg: "data" - * @param the numberic value + * @param value the numberic value */ //% help=radio/send-value - //% weight=4 debug=true + //% weight=59 //% blockId=radio_datagram_send_value block="send|value %name|= %value" shim=radio::sendValue - function sendValue(name: string, number: number): void; + function sendValue(name: string, value: number): void; /** * Reads a value sent with `stream value` and writes it * to the serial stream as JSON */ - //% help=radio/read-value-to-serial - //% weight=3 debug=true shim=radio::readValueToSerial - function readValueToSerial(): void; + //% help=radio/write-value-to-serial + //% weight=3 + //% blockId=radio_write_value_serial block="write value to serial" shim=radio::writeValueToSerial + function writeValueToSerial(): void; /** * Registers code to run when a packet is received over radio. @@ -83,6 +84,14 @@ declare namespace radio { //% weight=9 //% blockId=radio_set_transmit_power block="set transmit power %power" shim=radio::setTransmitPower function setTransmitPower(power: number): void; + + /** + * Set the radio to transmit the serial number in each message. + */ + //% help=radio/set-transmit-serial-number + //% weight=8 + //% block=radio_set_transmit_serial_number block="set tranmist serial number %transmit" shim=radio::setTransmitSerialNumber + function setTransmitSerialNumber(transmit: boolean): void; } // Auto-generated. Do not edit. Really. diff --git a/sim/libmbit.ts b/sim/libmbit.ts index fbe0557f..d0d7d19c 100644 --- a/sim/libmbit.ts +++ b/sim/libmbit.ts @@ -449,11 +449,21 @@ namespace pxsim.radio { board().radio.setTransmitPower(power); } - export function sendNumbers(value0: number, value1: number, value2: number, value3: number): void { - board().radio.datagram.send([value0, value1, value2, value3]); + export function setTransmitSerialNumber(transmit: boolean): void { + board().radio.setTransmitSerialNumber(transmit); } - export function streamValue(name: string, value: number) { + export function sendNumber(value: number): void { + board().radio.datagram.send([value]); + } + + export function writeValueToSerial(): void { + let b = board(); + let v = b.radio.datagram.recv().data[0]; + b.writeSerial(`{v:${v}}`); + } + + export function sendValue(name: string, value: number) { board().radio.datagram.send([value]); } diff --git a/sim/state.ts b/sim/state.ts index e639534e..e1452e48 100644 --- a/sim/state.ts +++ b/sim/state.ts @@ -85,7 +85,7 @@ namespace pxsim { } recv(): PacketBuffer { - var r = this.datagram.shift(); + let r = this.datagram.shift(); if (!r) r = { data: [0, 0, 0, 0], rssi: -1 @@ -98,6 +98,7 @@ namespace pxsim { // uint8_t radioDefaultGroup = MICROBIT_RADIO_DEFAULT_GROUP; groupId = 0; // todo power = 0; + transmitSerialNumber = false; datagram: RadioDatagram; constructor(private runtime: Runtime) { @@ -112,6 +113,10 @@ namespace pxsim { this.power = Math.max(0, Math.min(7, power)); } + setTransmitSerialNumber(sn: boolean) { + this.transmitSerialNumber = !!sn; + } + broadcast(msg: number) { Runtime.postMessage({ type: 'eventbus', @@ -511,7 +516,7 @@ namespace pxsim { constructor() { super() - this.id = "b" +Math_.random(2147483647); + this.id = "b" + Math_.random(2147483647); this.animationQ = new AnimationQueue(runtime); this.bus = new EventBus(runtime); this.radio = new RadioBus(runtime); @@ -598,13 +603,13 @@ namespace pxsim { let c = s[i]; this.serialOutBuffer += c; if (c == '\n') { - Runtime.postMessage({ - type: 'serial', - data: this.serialOutBuffer, - id: runtime.id - }) - this.serialOutBuffer = '' - break; + Runtime.postMessage({ + type: 'serial', + data: this.serialOutBuffer, + id: runtime.id + }) + this.serialOutBuffer = '' + break; } } } @@ -647,7 +652,7 @@ namespace pxsim { } public clear(): void { - for (var i = 0; i < this.data.length; ++i) + for (let i = 0; i < this.data.length; ++i) this.data[i] = 0; } } @@ -683,11 +688,11 @@ namespace pxsim { } export function createFont(): Image { - var data = [0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0x8, 0xa, 0x4a, 0x40, 0x0, 0x0, 0xa, 0x5f, 0xea, 0x5f, 0xea, 0xe, 0xd9, 0x2e, 0xd3, 0x6e, 0x19, 0x32, 0x44, 0x89, 0x33, 0xc, 0x92, 0x4c, 0x92, 0x4d, 0x8, 0x8, 0x0, 0x0, 0x0, 0x4, 0x88, 0x8, 0x8, 0x4, 0x8, 0x4, 0x84, 0x84, 0x88, 0x0, 0xa, 0x44, 0x8a, 0x40, 0x0, 0x4, 0x8e, 0xc4, 0x80, 0x0, 0x0, 0x0, 0x4, 0x88, 0x0, 0x0, 0xe, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x0, 0x1, 0x22, 0x44, 0x88, 0x10, 0xc, 0x92, 0x52, 0x52, 0x4c, 0x4, 0x8c, 0x84, 0x84, 0x8e, 0x1c, 0x82, 0x4c, 0x90, 0x1e, 0x1e, 0xc2, 0x44, 0x92, 0x4c, 0x6, 0xca, 0x52, 0x5f, 0xe2, 0x1f, 0xf0, 0x1e, 0xc1, 0x3e, 0x2, 0x44, 0x8e, 0xd1, 0x2e, 0x1f, 0xe2, 0x44, 0x88, 0x10, 0xe, 0xd1, 0x2e, 0xd1, 0x2e, 0xe, 0xd1, 0x2e, 0xc4, 0x88, 0x0, 0x8, 0x0, 0x8, 0x0, 0x0, 0x4, 0x80, 0x4, 0x88, 0x2, 0x44, 0x88, 0x4, 0x82, 0x0, 0xe, 0xc0, 0xe, 0xc0, 0x8, 0x4, 0x82, 0x44, 0x88, 0xe, 0xd1, 0x26, 0xc0, 0x4, 0xe, 0xd1, 0x35, 0xb3, 0x6c, 0xc, 0x92, 0x5e, 0xd2, 0x52, 0x1c, 0x92, 0x5c, 0x92, 0x5c, 0xe, 0xd0, 0x10, 0x10, 0xe, 0x1c, 0x92, 0x52, 0x52, 0x5c, 0x1e, 0xd0, 0x1c, 0x90, 0x1e, 0x1e, 0xd0, 0x1c, 0x90, 0x10, 0xe, 0xd0, 0x13, 0x71, 0x2e, 0x12, 0x52, 0x5e, 0xd2, 0x52, 0x1c, 0x88, 0x8, 0x8, 0x1c, 0x1f, 0xe2, 0x42, 0x52, 0x4c, 0x12, 0x54, 0x98, 0x14, 0x92, 0x10, 0x10, 0x10, 0x10, 0x1e, 0x11, 0x3b, 0x75, 0xb1, 0x31, 0x11, 0x39, 0x35, 0xb3, 0x71, 0xc, 0x92, 0x52, 0x52, 0x4c, 0x1c, 0x92, 0x5c, 0x90, 0x10, 0xc, 0x92, 0x52, 0x4c, 0x86, 0x1c, 0x92, 0x5c, 0x92, 0x51, 0xe, 0xd0, 0xc, 0x82, 0x5c, 0x1f, 0xe4, 0x84, 0x84, 0x84, 0x12, 0x52, 0x52, 0x52, 0x4c, 0x11, 0x31, 0x31, 0x2a, 0x44, 0x11, 0x31, 0x35, 0xbb, 0x71, 0x12, 0x52, 0x4c, 0x92, 0x52, 0x11, 0x2a, 0x44, 0x84, 0x84, 0x1e, 0xc4, 0x88, 0x10, 0x1e, 0xe, 0xc8, 0x8, 0x8, 0xe, 0x10, 0x8, 0x4, 0x82, 0x41, 0xe, 0xc2, 0x42, 0x42, 0x4e, 0x4, 0x8a, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0x8, 0x4, 0x80, 0x0, 0x0, 0x0, 0xe, 0xd2, 0x52, 0x4f, 0x10, 0x10, 0x1c, 0x92, 0x5c, 0x0, 0xe, 0xd0, 0x10, 0xe, 0x2, 0x42, 0x4e, 0xd2, 0x4e, 0xc, 0x92, 0x5c, 0x90, 0xe, 0x6, 0xc8, 0x1c, 0x88, 0x8, 0xe, 0xd2, 0x4e, 0xc2, 0x4c, 0x10, 0x10, 0x1c, 0x92, 0x52, 0x8, 0x0, 0x8, 0x8, 0x8, 0x2, 0x40, 0x2, 0x42, 0x4c, 0x10, 0x14, 0x98, 0x14, 0x92, 0x8, 0x8, 0x8, 0x8, 0x6, 0x0, 0x1b, 0x75, 0xb1, 0x31, 0x0, 0x1c, 0x92, 0x52, 0x52, 0x0, 0xc, 0x92, 0x52, 0x4c, 0x0, 0x1c, 0x92, 0x5c, 0x90, 0x0, 0xe, 0xd2, 0x4e, 0xc2, 0x0, 0xe, 0xd0, 0x10, 0x10, 0x0, 0x6, 0xc8, 0x4, 0x98, 0x8, 0x8, 0xe, 0xc8, 0x7, 0x0, 0x12, 0x52, 0x52, 0x4f, 0x0, 0x11, 0x31, 0x2a, 0x44, 0x0, 0x11, 0x31, 0x35, 0xbb, 0x0, 0x12, 0x4c, 0x8c, 0x92, 0x0, 0x11, 0x2a, 0x44, 0x98, 0x0, 0x1e, 0xc4, 0x88, 0x1e, 0x6, 0xc4, 0x8c, 0x84, 0x86, 0x8, 0x8, 0x8, 0x8, 0x8, 0x18, 0x8, 0xc, 0x88, 0x18, 0x0, 0x0, 0xc, 0x83, 0x60]; + const data = [0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0x8, 0xa, 0x4a, 0x40, 0x0, 0x0, 0xa, 0x5f, 0xea, 0x5f, 0xea, 0xe, 0xd9, 0x2e, 0xd3, 0x6e, 0x19, 0x32, 0x44, 0x89, 0x33, 0xc, 0x92, 0x4c, 0x92, 0x4d, 0x8, 0x8, 0x0, 0x0, 0x0, 0x4, 0x88, 0x8, 0x8, 0x4, 0x8, 0x4, 0x84, 0x84, 0x88, 0x0, 0xa, 0x44, 0x8a, 0x40, 0x0, 0x4, 0x8e, 0xc4, 0x80, 0x0, 0x0, 0x0, 0x4, 0x88, 0x0, 0x0, 0xe, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x0, 0x1, 0x22, 0x44, 0x88, 0x10, 0xc, 0x92, 0x52, 0x52, 0x4c, 0x4, 0x8c, 0x84, 0x84, 0x8e, 0x1c, 0x82, 0x4c, 0x90, 0x1e, 0x1e, 0xc2, 0x44, 0x92, 0x4c, 0x6, 0xca, 0x52, 0x5f, 0xe2, 0x1f, 0xf0, 0x1e, 0xc1, 0x3e, 0x2, 0x44, 0x8e, 0xd1, 0x2e, 0x1f, 0xe2, 0x44, 0x88, 0x10, 0xe, 0xd1, 0x2e, 0xd1, 0x2e, 0xe, 0xd1, 0x2e, 0xc4, 0x88, 0x0, 0x8, 0x0, 0x8, 0x0, 0x0, 0x4, 0x80, 0x4, 0x88, 0x2, 0x44, 0x88, 0x4, 0x82, 0x0, 0xe, 0xc0, 0xe, 0xc0, 0x8, 0x4, 0x82, 0x44, 0x88, 0xe, 0xd1, 0x26, 0xc0, 0x4, 0xe, 0xd1, 0x35, 0xb3, 0x6c, 0xc, 0x92, 0x5e, 0xd2, 0x52, 0x1c, 0x92, 0x5c, 0x92, 0x5c, 0xe, 0xd0, 0x10, 0x10, 0xe, 0x1c, 0x92, 0x52, 0x52, 0x5c, 0x1e, 0xd0, 0x1c, 0x90, 0x1e, 0x1e, 0xd0, 0x1c, 0x90, 0x10, 0xe, 0xd0, 0x13, 0x71, 0x2e, 0x12, 0x52, 0x5e, 0xd2, 0x52, 0x1c, 0x88, 0x8, 0x8, 0x1c, 0x1f, 0xe2, 0x42, 0x52, 0x4c, 0x12, 0x54, 0x98, 0x14, 0x92, 0x10, 0x10, 0x10, 0x10, 0x1e, 0x11, 0x3b, 0x75, 0xb1, 0x31, 0x11, 0x39, 0x35, 0xb3, 0x71, 0xc, 0x92, 0x52, 0x52, 0x4c, 0x1c, 0x92, 0x5c, 0x90, 0x10, 0xc, 0x92, 0x52, 0x4c, 0x86, 0x1c, 0x92, 0x5c, 0x92, 0x51, 0xe, 0xd0, 0xc, 0x82, 0x5c, 0x1f, 0xe4, 0x84, 0x84, 0x84, 0x12, 0x52, 0x52, 0x52, 0x4c, 0x11, 0x31, 0x31, 0x2a, 0x44, 0x11, 0x31, 0x35, 0xbb, 0x71, 0x12, 0x52, 0x4c, 0x92, 0x52, 0x11, 0x2a, 0x44, 0x84, 0x84, 0x1e, 0xc4, 0x88, 0x10, 0x1e, 0xe, 0xc8, 0x8, 0x8, 0xe, 0x10, 0x8, 0x4, 0x82, 0x41, 0xe, 0xc2, 0x42, 0x42, 0x4e, 0x4, 0x8a, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0x8, 0x4, 0x80, 0x0, 0x0, 0x0, 0xe, 0xd2, 0x52, 0x4f, 0x10, 0x10, 0x1c, 0x92, 0x5c, 0x0, 0xe, 0xd0, 0x10, 0xe, 0x2, 0x42, 0x4e, 0xd2, 0x4e, 0xc, 0x92, 0x5c, 0x90, 0xe, 0x6, 0xc8, 0x1c, 0x88, 0x8, 0xe, 0xd2, 0x4e, 0xc2, 0x4c, 0x10, 0x10, 0x1c, 0x92, 0x52, 0x8, 0x0, 0x8, 0x8, 0x8, 0x2, 0x40, 0x2, 0x42, 0x4c, 0x10, 0x14, 0x98, 0x14, 0x92, 0x8, 0x8, 0x8, 0x8, 0x6, 0x0, 0x1b, 0x75, 0xb1, 0x31, 0x0, 0x1c, 0x92, 0x52, 0x52, 0x0, 0xc, 0x92, 0x52, 0x4c, 0x0, 0x1c, 0x92, 0x5c, 0x90, 0x0, 0xe, 0xd2, 0x4e, 0xc2, 0x0, 0xe, 0xd0, 0x10, 0x10, 0x0, 0x6, 0xc8, 0x4, 0x98, 0x8, 0x8, 0xe, 0xc8, 0x7, 0x0, 0x12, 0x52, 0x52, 0x4f, 0x0, 0x11, 0x31, 0x2a, 0x44, 0x0, 0x11, 0x31, 0x35, 0xbb, 0x0, 0x12, 0x4c, 0x8c, 0x92, 0x0, 0x11, 0x2a, 0x44, 0x98, 0x0, 0x1e, 0xc4, 0x88, 0x1e, 0x6, 0xc4, 0x8c, 0x84, 0x86, 0x8, 0x8, 0x8, 0x8, 0x8, 0x18, 0x8, 0xc, 0x88, 0x18, 0x0, 0x0, 0xc, 0x83, 0x60]; let nb = data.length; let n = nb / 5; - var font = createImage(nb); + let font = createImage(nb); for (let c = 0; c < n; c++) { for (let row = 0; row < 5; row++) { let char = data[c * 5 + row];