radio double support (#1540)
* support for doubles in radio * fix typos * more docs * more support * fix build * handle serial * fix length * fixing buffer allocation * use same notation * using decrRC
This commit is contained in:
		@@ -10,6 +10,45 @@ A packet that was received by the radio.
 | 
			
		||||
* `serial` - The serial number of the @boardname@ that sent this packet or `0` if the @boardname@ did not include its serial number.
 | 
			
		||||
* `signal` - How strong the radio signal is. The exact range of values varies, but it goes approximately from `-128` dB (weak) to `-42` dB (strong).
 | 
			
		||||
 | 
			
		||||
## Packet layout
 | 
			
		||||
 | 
			
		||||
This section documents the data layout of the packet if you need to interpret the data outside of MakeCode.
 | 
			
		||||
 | 
			
		||||
    Packet byte layout
 | 
			
		||||
    | 0              | 1 ... 4       | 5 ... 8           | 9 ... 28
 | 
			
		||||
    ----------------------------------------------------------------
 | 
			
		||||
    | packet type    | system time   | serial number     | payload
 | 
			
		||||
 | 
			
		||||
* Serial number defaults to 0 unless enabled by user
 | 
			
		||||
* system time is milli-seconds since started, it will wrap around after a month or so
 | 
			
		||||
 | 
			
		||||
### Packet types
 | 
			
		||||
 | 
			
		||||
* PACKET_TYPE_NUMBER 0
 | 
			
		||||
 | 
			
		||||
    payload: number (9 ... 12)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
* PACKET_TYPE_VALUE 1
 | 
			
		||||
 | 
			
		||||
    payload: number (9 ... 12), name length (13), name (14 ... 26)
 | 
			
		||||
 | 
			
		||||
* PACKET_TYPE_STRING 2
 | 
			
		||||
 | 
			
		||||
    payload: string length (9), string (10 ... 28)
 | 
			
		||||
 | 
			
		||||
* PACKET_TYPE_BUFFER 3
 | 
			
		||||
 | 
			
		||||
    payload: buffer length (9), buffer (10 ... 28)
 | 
			
		||||
 | 
			
		||||
* PACKET_TYPE_DOUBLE 4
 | 
			
		||||
 | 
			
		||||
    payload: number (9 ... 16)
 | 
			
		||||
 | 
			
		||||
* PACKET_TYPE_DOUBLE_VALUE 5
 | 
			
		||||
 | 
			
		||||
    payload: number (9 ... 16), name length (17), name (18 ... 26)
 | 
			
		||||
 | 
			
		||||
## See also
 | 
			
		||||
 | 
			
		||||
[on data packet received](/reference/radio/on-data-packet-received),
 | 
			
		||||
 
 | 
			
		||||
@@ -3,9 +3,11 @@
 | 
			
		||||
using namespace pxt;
 | 
			
		||||
 | 
			
		||||
#define MAX_FIELD_NAME_LENGTH 12
 | 
			
		||||
#define MAX_FIELD_DOUBLE_NAME_LENGTH 8
 | 
			
		||||
#define MAX_PAYLOAD_LENGTH 20
 | 
			
		||||
#define PACKET_PREFIX_LENGTH 9
 | 
			
		||||
#define VALUE_PACKET_NAME_LEN_OFFSET 13
 | 
			
		||||
#define DOUBLE_VALUE_PACKET_NAME_LEN_OFFSET 17
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Packet Spec:
 | 
			
		||||
@@ -27,6 +29,12 @@ using namespace pxt;
 | 
			
		||||
// payload: buffer length (9), buffer (10 ... 28)
 | 
			
		||||
#define PACKET_TYPE_BUFFER 3
 | 
			
		||||
 | 
			
		||||
// payload: number (9 ... 16)
 | 
			
		||||
#define PACKET_TYPE_DOUBLE 4
 | 
			
		||||
 | 
			
		||||
// payload: number (9 ... 16), name length (17), name (18 ... 26)
 | 
			
		||||
#define PACKET_TYPE_DOUBLE_VALUE 5
 | 
			
		||||
 | 
			
		||||
//% color=#E3008C weight=96 icon="\uf012"
 | 
			
		||||
namespace radio {
 | 
			
		||||
 | 
			
		||||
@@ -41,7 +49,8 @@ namespace radio {
 | 
			
		||||
    uint8_t type;
 | 
			
		||||
    uint32_t time;
 | 
			
		||||
    uint32_t serial;
 | 
			
		||||
    int value;
 | 
			
		||||
    int ivalue;
 | 
			
		||||
    double dvalue;
 | 
			
		||||
    String msg; // may be NULL before first packet
 | 
			
		||||
    Buffer bufMsg; // may be NULL before first packet
 | 
			
		||||
 | 
			
		||||
@@ -118,7 +127,7 @@ namespace radio {
 | 
			
		||||
        return mkBuffer(buf + 1, len);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void writePacketAsJSON(uint8_t tp, int v, int s, int t, String m, Buffer b) {
 | 
			
		||||
    void writePacketAsJSON(uint8_t tp, int iv, double dv, int s, int t, String m, Buffer b) {
 | 
			
		||||
        // Convert the packet to JSON and send over serial
 | 
			
		||||
        uBit.serial.send("{");
 | 
			
		||||
        uBit.serial.send("\"t\":");
 | 
			
		||||
@@ -138,7 +147,13 @@ namespace radio {
 | 
			
		||||
        }
 | 
			
		||||
        if (tp == PACKET_TYPE_NUMBER || tp == PACKET_TYPE_VALUE) {
 | 
			
		||||
            uBit.serial.send(",\"v\":");
 | 
			
		||||
            uBit.serial.send(v);
 | 
			
		||||
            uBit.serial.send(iv);
 | 
			
		||||
        } else if (tp == PACKET_TYPE_DOUBLE || tp == PACKET_TYPE_DOUBLE_VALUE) {
 | 
			
		||||
            uBit.serial.send(",\"v\":");
 | 
			
		||||
            TNumber td = fromDouble(dv);
 | 
			
		||||
            String sd = numops::toString(td);
 | 
			
		||||
            uBit.serial.send((uint8_t*)sd->data, sd->length);
 | 
			
		||||
            decrRC(sd);
 | 
			
		||||
        }
 | 
			
		||||
        uBit.serial.send("}\r\n");
 | 
			
		||||
    }
 | 
			
		||||
@@ -155,7 +170,8 @@ namespace radio {
 | 
			
		||||
        uint8_t tp;
 | 
			
		||||
        int t;
 | 
			
		||||
        int s;
 | 
			
		||||
        int v = 0;
 | 
			
		||||
        int iv = 0;
 | 
			
		||||
        double dv = 0;
 | 
			
		||||
        String m = NULL;
 | 
			
		||||
        Buffer b = NULL;
 | 
			
		||||
 | 
			
		||||
@@ -163,17 +179,29 @@ namespace radio {
 | 
			
		||||
        memcpy(&t, buf + 1, 4);
 | 
			
		||||
        memcpy(&s, buf + 5, 4);
 | 
			
		||||
 | 
			
		||||
        if (tp == PACKET_TYPE_STRING) {
 | 
			
		||||
            m = getStringValue(buf + PACKET_PREFIX_LENGTH, MAX_PAYLOAD_LENGTH - 1);
 | 
			
		||||
        }
 | 
			
		||||
        else if (tp == PACKET_TYPE_BUFFER) {
 | 
			
		||||
            b = getBufferValue(buf + PACKET_PREFIX_LENGTH, MAX_PAYLOAD_LENGTH - 1);
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            memcpy(&v, buf + 9, 4);
 | 
			
		||||
            if (tp == PACKET_TYPE_VALUE) {
 | 
			
		||||
                m = getStringValue(buf + VALUE_PACKET_NAME_LEN_OFFSET, MAX_FIELD_NAME_LENGTH);
 | 
			
		||||
            }
 | 
			
		||||
        switch(tp) {
 | 
			
		||||
            case PACKET_TYPE_STRING:
 | 
			
		||||
                m = getStringValue(buf + PACKET_PREFIX_LENGTH, MAX_PAYLOAD_LENGTH - 1);
 | 
			
		||||
                break;
 | 
			
		||||
            case PACKET_TYPE_BUFFER:
 | 
			
		||||
                b = getBufferValue(buf + PACKET_PREFIX_LENGTH, MAX_PAYLOAD_LENGTH - 1);
 | 
			
		||||
                break;
 | 
			
		||||
            case PACKET_TYPE_DOUBLE:
 | 
			
		||||
            case PACKET_TYPE_DOUBLE_VALUE:
 | 
			
		||||
                memcpy(&dv, buf + PACKET_PREFIX_LENGTH, sizeof(double));
 | 
			
		||||
                if (tp == PACKET_TYPE_DOUBLE_VALUE) {
 | 
			
		||||
                    m = getStringValue(buf + DOUBLE_VALUE_PACKET_NAME_LEN_OFFSET, MAX_FIELD_DOUBLE_NAME_LENGTH);
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            case PACKET_TYPE_NUMBER:
 | 
			
		||||
            case PACKET_TYPE_VALUE:
 | 
			
		||||
                memcpy(&iv, buf + PACKET_PREFIX_LENGTH, sizeof(int));
 | 
			
		||||
                if (tp == PACKET_TYPE_VALUE) {
 | 
			
		||||
                    m = getStringValue(buf + VALUE_PACKET_NAME_LEN_OFFSET, MAX_FIELD_NAME_LENGTH);
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            default: // unknown packet
 | 
			
		||||
                return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (NULL == m)
 | 
			
		||||
@@ -187,14 +215,15 @@ namespace radio {
 | 
			
		||||
            type = tp;
 | 
			
		||||
            time = t;
 | 
			
		||||
            serial = s;
 | 
			
		||||
            value = v;
 | 
			
		||||
            ivalue = iv;
 | 
			
		||||
            dvalue = dv;
 | 
			
		||||
            decrRC(msg);
 | 
			
		||||
            decrRC(bufMsg);
 | 
			
		||||
            msg = m;
 | 
			
		||||
            bufMsg = b;
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            writePacketAsJSON(tp, v, s, t, m, b);
 | 
			
		||||
            writePacketAsJSON(tp, iv, dv, s, t, m, b);
 | 
			
		||||
            decrRC(m);
 | 
			
		||||
            decrRC(b);
 | 
			
		||||
        }
 | 
			
		||||
@@ -206,16 +235,26 @@ namespace radio {
 | 
			
		||||
    //% help=radio/send-number
 | 
			
		||||
    //% weight=60
 | 
			
		||||
    //% blockId=radio_datagram_send block="radio send number %value" blockGap=8
 | 
			
		||||
    void sendNumber(int value) {
 | 
			
		||||
    void sendNumber(TNumber value) {
 | 
			
		||||
        if (radioEnable() != MICROBIT_OK) return;
 | 
			
		||||
        uint8_t length = PACKET_PREFIX_LENGTH + sizeof(uint32_t);
 | 
			
		||||
        uint8_t buf[length];
 | 
			
		||||
        memset(buf, 0, length);
 | 
			
		||||
 | 
			
		||||
        setPacketPrefix(buf, PACKET_TYPE_NUMBER);
 | 
			
		||||
        memcpy(buf + PACKET_PREFIX_LENGTH, &value, 4);
 | 
			
		||||
 | 
			
		||||
        uBit.radio.datagram.send(buf, length);
 | 
			
		||||
        int iv = toInt(value);
 | 
			
		||||
        double dv = toDouble(value);
 | 
			
		||||
        if (iv == dv) {
 | 
			
		||||
            uint8_t length = PACKET_PREFIX_LENGTH + sizeof(int);
 | 
			
		||||
            uint8_t buf[length];
 | 
			
		||||
            memset(buf, 0, length);
 | 
			
		||||
            setPacketPrefix(buf, PACKET_TYPE_NUMBER);
 | 
			
		||||
            memcpy(buf + PACKET_PREFIX_LENGTH, &iv, sizeof(int));
 | 
			
		||||
            uBit.radio.datagram.send(buf, length);
 | 
			
		||||
        } else {
 | 
			
		||||
            uint8_t length = PACKET_PREFIX_LENGTH + sizeof(double);
 | 
			
		||||
            uint8_t buf[length];
 | 
			
		||||
            memset(buf, 0, length);
 | 
			
		||||
            setPacketPrefix(buf, PACKET_TYPE_DOUBLE);
 | 
			
		||||
            memcpy(buf + PACKET_PREFIX_LENGTH, &dv, sizeof(double));
 | 
			
		||||
            uBit.radio.datagram.send(buf, length);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -227,18 +266,27 @@ namespace radio {
 | 
			
		||||
    //% help=radio/send-value
 | 
			
		||||
    //% weight=59
 | 
			
		||||
    //% blockId=radio_datagram_send_value block="radio send|value %name|= %value" blockGap=8
 | 
			
		||||
    void sendValue(String name, int value) {
 | 
			
		||||
    void sendValue(String name, TNumber value) {
 | 
			
		||||
        if (radioEnable() != MICROBIT_OK) return;
 | 
			
		||||
 | 
			
		||||
        uint8_t buf[32];
 | 
			
		||||
        memset(buf, 0, 32);
 | 
			
		||||
 | 
			
		||||
        setPacketPrefix(buf, PACKET_TYPE_VALUE);
 | 
			
		||||
        memcpy(buf + PACKET_PREFIX_LENGTH, &value, 4);
 | 
			
		||||
        int iv = toInt(value);
 | 
			
		||||
        double dv = toDouble(value);
 | 
			
		||||
        if (iv == dv) {
 | 
			
		||||
            setPacketPrefix(buf, PACKET_TYPE_VALUE);
 | 
			
		||||
            memcpy(buf + PACKET_PREFIX_LENGTH, &iv, sizeof(int));
 | 
			
		||||
 | 
			
		||||
        int stringLen = copyStringValue(buf + VALUE_PACKET_NAME_LEN_OFFSET, name, MAX_FIELD_NAME_LENGTH);
 | 
			
		||||
            int stringLen = copyStringValue(buf + VALUE_PACKET_NAME_LEN_OFFSET, name, MAX_FIELD_DOUBLE_NAME_LENGTH);
 | 
			
		||||
            uBit.radio.datagram.send(buf, VALUE_PACKET_NAME_LEN_OFFSET + stringLen);
 | 
			
		||||
        } else {
 | 
			
		||||
            setPacketPrefix(buf, PACKET_TYPE_DOUBLE_VALUE);
 | 
			
		||||
            memcpy(buf + PACKET_PREFIX_LENGTH, &dv, sizeof(double));
 | 
			
		||||
 | 
			
		||||
        uBit.radio.datagram.send(buf, VALUE_PACKET_NAME_LEN_OFFSET + stringLen);
 | 
			
		||||
            int stringLen = copyStringValue(buf + DOUBLE_VALUE_PACKET_NAME_LEN_OFFSET, name, MAX_FIELD_NAME_LENGTH);
 | 
			
		||||
            uBit.radio.datagram.send(buf, DOUBLE_VALUE_PACKET_NAME_LEN_OFFSET + stringLen);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -304,7 +352,16 @@ namespace radio {
 | 
			
		||||
    //% advanced=true
 | 
			
		||||
    void writeReceivedPacketToSerial() {
 | 
			
		||||
        if (radioEnable() != MICROBIT_OK) return;
 | 
			
		||||
        writePacketAsJSON(type, value, (int) serial, (int) time, msg, bufMsg);
 | 
			
		||||
        writePacketAsJSON(type, ivalue, dvalue, (int) serial, (int) time, msg, bufMsg);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    TNumber readNumber() {
 | 
			
		||||
        if (type == PACKET_TYPE_NUMBER || type == PACKET_TYPE_VALUE)
 | 
			
		||||
            return fromInt(ivalue);
 | 
			
		||||
        else if (type == PACKET_TYPE_DOUBLE || type == PACKET_TYPE_DOUBLE_VALUE)
 | 
			
		||||
            return fromDouble(dvalue);
 | 
			
		||||
        else 
 | 
			
		||||
            return fromInt(0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -315,11 +372,11 @@ namespace radio {
 | 
			
		||||
    //% weight=46
 | 
			
		||||
    //% blockId=radio_datagram_receive block="radio receive number" blockGap=8
 | 
			
		||||
    //% deprecated=true
 | 
			
		||||
    int receiveNumber()
 | 
			
		||||
    TNumber receiveNumber()
 | 
			
		||||
    {
 | 
			
		||||
        if (radioEnable() != MICROBIT_OK) return 0;
 | 
			
		||||
        receivePacket(false);
 | 
			
		||||
        return value;
 | 
			
		||||
        return readNumber();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -333,7 +390,7 @@ namespace radio {
 | 
			
		||||
        if (radioEnable() != MICROBIT_OK) return;
 | 
			
		||||
        registerWithDal(MICROBIT_ID_RADIO, MICROBIT_RADIO_EVT_DATAGRAM, body);
 | 
			
		||||
        // make sure the receive buffer has a free spot
 | 
			
		||||
        receiveNumber();
 | 
			
		||||
        receivePacket(false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -411,9 +468,9 @@ namespace radio {
 | 
			
		||||
     * contain a number.
 | 
			
		||||
     */
 | 
			
		||||
    //% help=radio/received-number
 | 
			
		||||
    int receivedNumber() {
 | 
			
		||||
    TNumber receivedNumber() {
 | 
			
		||||
        if (radioEnable() != MICROBIT_OK) return 0;
 | 
			
		||||
        return value;
 | 
			
		||||
        return readNumber();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										8
									
								
								libs/radio/shims.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								libs/radio/shims.d.ts
									
									
									
									
										vendored
									
									
								
							@@ -21,7 +21,7 @@ declare namespace radio {
 | 
			
		||||
    //% help=radio/send-number
 | 
			
		||||
    //% weight=60
 | 
			
		||||
    //% blockId=radio_datagram_send block="radio send number %value" blockGap=8 shim=radio::sendNumber
 | 
			
		||||
    function sendNumber(value: int32): void;
 | 
			
		||||
    function sendNumber(value: number): void;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Broadcasts a name / value pair along with the device serial number
 | 
			
		||||
@@ -32,7 +32,7 @@ declare namespace radio {
 | 
			
		||||
    //% help=radio/send-value
 | 
			
		||||
    //% weight=59
 | 
			
		||||
    //% blockId=radio_datagram_send_value block="radio send|value %name|= %value" blockGap=8 shim=radio::sendValue
 | 
			
		||||
    function sendValue(name: string, value: int32): void;
 | 
			
		||||
    function sendValue(name: string, value: number): void;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Broadcasts a string along with the device serial number
 | 
			
		||||
@@ -81,7 +81,7 @@ declare namespace radio {
 | 
			
		||||
    //% weight=46
 | 
			
		||||
    //% blockId=radio_datagram_receive block="radio receive number" blockGap=8
 | 
			
		||||
    //% deprecated=true shim=radio::receiveNumber
 | 
			
		||||
    function receiveNumber(): int32;
 | 
			
		||||
    function receiveNumber(): number;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Registers code to run when a packet is received over radio.
 | 
			
		||||
@@ -150,7 +150,7 @@ declare namespace radio {
 | 
			
		||||
     * contain a number.
 | 
			
		||||
     */
 | 
			
		||||
    //% help=radio/received-number shim=radio::receivedNumber
 | 
			
		||||
    function receivedNumber(): int32;
 | 
			
		||||
    function receivedNumber(): number;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns the serial number of the sender micro:bit from the last packet taken
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user