updated radio apis to support key/value pair

This commit is contained in:
Peli de Halleux 2016-05-10 21:13:16 -07:00
parent 7d0101af25
commit a62f2b00b4
5 changed files with 114 additions and 86 deletions

View File

@ -2,7 +2,7 @@
using namespace pxt; using namespace pxt;
#define RADIO_VALUE_PACKET_TYPE 24641622 #define MAX_FIELD_NAME_LENGTH 12
//% color=270 weight=34 //% color=270 weight=34
namespace radio { namespace radio {
@ -11,6 +11,8 @@ namespace radio {
// Radio // Radio
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
bool radioEnabled = false; bool radioEnabled = false;
bool transmitSerialNumber = false;
PacketBuffer packet; PacketBuffer packet;
int radioEnable() { int radioEnable() {
@ -36,83 +38,84 @@ namespace radio {
registerWithDal(MES_BROADCAST_GENERAL_ID, message, f); registerWithDal(MES_BROADCAST_GENERAL_ID, message, f);
} }
/** /**
* 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 //% help=radio/send-number
//% weight=59 debug=true //% weight=60
//% blockId=radio_datagram_send_numbers block="send numbers|0: %VALUE0|1: %VALUE1|2: %VALUE2|3: %VALUE3" //% blockId=radio_datagram_send block="send number %MESSAGE" blockGap=8
void sendNumbers(int value_0, int value_1, int value_2, int value_3) { void sendNumber(int value) {
if (radioEnable() != MICROBIT_OK) return; if (radioEnable() != MICROBIT_OK) return;
int buf[] = { value_0, value_1, value_2, value_3 }; uint32_t t = system_timer_current_time();
uBit.radio.datagram.send((uint8_t*)buf, 4*sizeof(int)); 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 * Broadcasts a name / value pair along with the device serial number
* and running time to any connected BBC micro:bit in the group. * and running time to any connected BBC micro:bit in the group.
* @param name the field name (max 12 characters), eg: "data" * @param name the field name (max 12 characters), eg: "data"
* @param the numberic value * @param value the numberic value
*/ */
//% help=radio/send-value //% help=radio/send-value
//% weight=4 debug=true //% weight=59
//% blockId=radio_datagram_send_value block="send|value %name|= %value" //% 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; 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]; uint8_t buf[32];
uint32_t* buf32 = (uint32_t*)buf; uint32_t* buf32 = (uint32_t*)buf;
memset(buf, 32, 0); memset(buf, 32, 0);
buf32[0] = number; // 4 bytes: value buf32[0] = value; // 4 bytes: value
buf32[1] = microbit_serial_number(); // 4 bytes: serial number buf32[1] = t; // 4 bytes: running time
buf32[2] = system_timer_current_time(); // 4 bytes: running time buf32[2] = sn; // 4 bytes: serial number
memcpy(buf + 12, n.toCharArray(), min(12, n.length())); // 12-24: field name uint8_t len = min(MAX_FIELD_NAME_LENGTH, n.length()); // 1 byte: string length
buf32[7] = RADIO_VALUE_PACKET_TYPE; // last 4 bytes: magic number of package type if (len > 0) {
uBit.radio.datagram.send(buf, 32); 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 * Reads a value sent with `stream value` and writes it
* to the serial stream as JSON * to the serial stream as JSON
*/ */
//% help=radio/read-value-to-serial //% help=radio/write-value-to-serial
//% weight=3 debug=true //% weight=3
void readValueToSerial() { //% blockId=radio_write_value_serial block="write value to serial"
void writeValueToSerial() {
if (radioEnable() != MICROBIT_OK) return; if (radioEnable() != MICROBIT_OK) return;
PacketBuffer p = uBit.radio.datagram.recv(); PacketBuffer p = uBit.radio.datagram.recv();
int length = p.length(); int length = p.length();
if (length < 32) {
return;
}
uint8_t* bytes = p.getBytes(); 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 value;
int serial;
int time;
char name[12+1]; memset(name, 0, 13 * sizeof(char));
uBit.serial.send("{");
if (length >= 4) {
memcpy(&value, bytes, 4); memcpy(&value, bytes, 4);
memcpy(&serial, bytes + 4, 4); uBit.serial.send("v:"); uBit.serial.send(value);
memcpy(&time, bytes + 8, 4); if(length >= 8) {
memcpy(&name, bytes + 12, 12); memcpy(&value, bytes + 4, 4);
uBit.serial.send(",t:"); uBit.serial.send(value);
uBit.serial.send("{s:"); uBit.serial.send(serial); if (length >= 12) {
uBit.serial.send(",t:"); uBit.serial.send(time); memcpy(&value, bytes + 8, 4);
uBit.serial.send(",v:"); uBit.serial.send(value); uBit.serial.send(",s:"); uBit.serial.send(value);
uBit.serial.send(",n:\""); uBit.serial.send(name); if (length >= 13) {
uBit.serial.send("\"}\r\n"); 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; if (radioEnable() != MICROBIT_OK) return;
uBit.radio.setTransmitPower(power); 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;
}
} }

View File

@ -3,13 +3,4 @@
*/ */
//% color=270 weight=34 //% color=270 weight=34
namespace radio { 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);
}
} }

View File

@ -6,31 +6,32 @@
declare namespace radio { 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 //% help=radio/send-number
//% weight=59 debug=true //% weight=60
//% blockId=radio_datagram_send_numbers block="send numbers|0: %VALUE0|1: %VALUE1|2: %VALUE2|3: %VALUE3" shim=radio::sendNumbers //% blockId=radio_datagram_send block="send number %MESSAGE" blockGap=8 shim=radio::sendNumber
function sendNumbers(value_0: number, value_1: number, value_2: number, value_3: number): void; function sendNumber(value: number): void;
/** /**
* Broadcasts a name / value pair along with the device serial number * Broadcasts a name / value pair along with the device serial number
* and running time to any connected BBC micro:bit in the group. * and running time to any connected BBC micro:bit in the group.
* @param name the field name (max 12 characters), eg: "data" * @param name the field name (max 12 characters), eg: "data"
* @param the numberic value * @param value the numberic value
*/ */
//% help=radio/send-value //% help=radio/send-value
//% weight=4 debug=true //% weight=59
//% blockId=radio_datagram_send_value block="send|value %name|= %value" shim=radio::sendValue //% 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 * Reads a value sent with `stream value` and writes it
* to the serial stream as JSON * to the serial stream as JSON
*/ */
//% help=radio/read-value-to-serial //% help=radio/write-value-to-serial
//% weight=3 debug=true shim=radio::readValueToSerial //% weight=3
function readValueToSerial(): void; //% 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. * Registers code to run when a packet is received over radio.
@ -83,6 +84,14 @@ declare namespace radio {
//% weight=9 //% weight=9
//% blockId=radio_set_transmit_power block="set transmit power %power" shim=radio::setTransmitPower //% blockId=radio_set_transmit_power block="set transmit power %power" shim=radio::setTransmitPower
function setTransmitPower(power: number): void; 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. // Auto-generated. Do not edit. Really.

View File

@ -449,11 +449,21 @@ namespace pxsim.radio {
board().radio.setTransmitPower(power); board().radio.setTransmitPower(power);
} }
export function sendNumbers(value0: number, value1: number, value2: number, value3: number): void { export function setTransmitSerialNumber(transmit: boolean): void {
board().radio.datagram.send([value0, value1, value2, value3]); 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]); board().radio.datagram.send([value]);
} }

View File

@ -85,7 +85,7 @@ namespace pxsim {
} }
recv(): PacketBuffer { recv(): PacketBuffer {
var r = this.datagram.shift(); let r = this.datagram.shift();
if (!r) r = { if (!r) r = {
data: [0, 0, 0, 0], data: [0, 0, 0, 0],
rssi: -1 rssi: -1
@ -98,6 +98,7 @@ namespace pxsim {
// uint8_t radioDefaultGroup = MICROBIT_RADIO_DEFAULT_GROUP; // uint8_t radioDefaultGroup = MICROBIT_RADIO_DEFAULT_GROUP;
groupId = 0; // todo groupId = 0; // todo
power = 0; power = 0;
transmitSerialNumber = false;
datagram: RadioDatagram; datagram: RadioDatagram;
constructor(private runtime: Runtime) { constructor(private runtime: Runtime) {
@ -112,6 +113,10 @@ namespace pxsim {
this.power = Math.max(0, Math.min(7, power)); this.power = Math.max(0, Math.min(7, power));
} }
setTransmitSerialNumber(sn: boolean) {
this.transmitSerialNumber = !!sn;
}
broadcast(msg: number) { broadcast(msg: number) {
Runtime.postMessage(<SimulatorEventBusMessage>{ Runtime.postMessage(<SimulatorEventBusMessage>{
type: 'eventbus', type: 'eventbus',
@ -647,7 +652,7 @@ namespace pxsim {
} }
public clear(): void { 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; this.data[i] = 0;
} }
} }
@ -683,11 +688,11 @@ namespace pxsim {
} }
export function createFont(): Image { 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 nb = data.length;
let n = nb / 5; let n = nb / 5;
var font = createImage(nb); let font = createImage(nb);
for (let c = 0; c < n; c++) { for (let c = 0; c < n; c++) {
for (let row = 0; row < 5; row++) { for (let row = 0; row < 5; row++) {
let char = data[c * 5 + row]; let char = data[c * 5 + row];