Saltar al contenido principal

Módulo Bytes

El módulo Bytes proporciona un buffer de memoria de bytes de tamaño fijo, optimizado para trabajar con datos binarios de bajo nivel. Es especialmente útil en comunicaciones con hardware, construcción de tramas de protocolo, manipulación de datos de imagen o cualquier operación que requiera acceso directo a memoria por posición.

Uso

use Bytes

Arquitectura del módulo

El módulo tiene dos niveles:

  • Funciones del móduloBytes.new() y Bytes.clone() para crear buffers.
  • Métodos del objeto — operaciones sobre el buffer creado (read, write, fill, size, etc.).
use Bytes

var buf = Bytes.new(16) // Crear buffer de 16 bytes
buf.write(0, 0xFF) // Escribir en posición 0
var valor = buf.read(0) // Leer desde posición 0
println(valor) // 255

Funciones del módulo

new

Crea un nuevo buffer de bytes de tamaño fijo.

var buf = Bytes.new(tamaño)

Parámetros:

ParámetroTipoDescripción
tamañointegerNúmero de bytes a reservar

Retorna: Un objeto buffer de bytes listo para usar.

Ejemplo:

use Bytes

var buf = Bytes.new(64) // Buffer de 64 bytes
buf.fill(0) // Inicializar a cero
println(buf.size()) // 64
info

El contenido inicial del buffer no está garantizado. Usa fill(0) para inicializarlo a cero antes de operar con él.


clone

Crea una copia independiente de un buffer de bytes existente.

var copia = Bytes.clone(buf)

Parámetros:

ParámetroTipoDescripción
bufBytesBuffer de bytes a clonar

Retorna: Un nuevo objeto bytes con el mismo tamaño y contenido que el original. Modificar la copia no afecta al original.

Ejemplo:

use Bytes

var original = Bytes.new(4)
original.write(0, 0xAB)
original.write(1, 0xCD)

var copia = Bytes.clone(original)
copia.write(0, 0x00) // No afecta a original

println(original.read(0)) // 171 (0xAB)
println(copia.read(0)) // 0

Métodos del objeto Bytes

fill

Rellena todos los bytes del buffer con un mismo valor.

buf.fill(valor)

Parámetros:

ParámetroTipoDescripción
valorintegerValor entre 0 y 255 con el que rellenar

Ejemplo:

use Bytes

var buf = Bytes.new(8)
buf.fill(0xFF) // Todos los bytes a 255
buf.fill(0) // Limpiar el buffer

size

Devuelve el tamaño del buffer en bytes.

var n = buf.size()

Retorna: Un entero con el número de bytes del buffer.

Ejemplo:

use Bytes

var buf = Bytes.new(32)
println(buf.size()) // 32

read

Lee un byte en la posición indicada.

var valor = buf.read(pos)

Parámetros:

ParámetroTipoDescripción
posintegerÍndice del byte (0-based)

Retorna: Un entero entre 0 y 255. Lanza una excepción si el índice está fuera de rango.

Ejemplo:

use Bytes

var buf = Bytes.new(4)
buf.write(2, 0x42)
println(buf.read(2)) // 66 (0x42)

write

Escribe un byte en la posición indicada.

buf.write(pos, valor)

Parámetros:

ParámetroTipoDescripción
posintegerÍndice del byte (0-based)
valorintegerValor entre 0 y 255

Lanza una excepción si el índice está fuera de rango.

Ejemplo:

use Bytes

var buf = Bytes.new(4)
buf.write(0, 0xDE)
buf.write(1, 0xAD)
buf.write(2, 0xBE)
buf.write(3, 0xEF)
precaución

Solo se almacena el byte bajo del valor. Si el valor supera 255, los bits superiores se descartan.


read16

Lee un valor de 16 bits (2 bytes) en el índice indicado. El índice se expresa en unidades de 16 bits, no en bytes.

var valor = buf.read16(indice)

Parámetros:

ParámetroTipoDescripción
indiceintegerPosición en unidades de 16 bits (0-based)

Retorna: Un entero entre 0 y 65535. Lanza una excepción si el índice está fuera de rango.

Ejemplo:

use Bytes

var buf = Bytes.new(4)
buf.write16(0, 0x1234) // Bytes 0-1
buf.write16(1, 0xABCD) // Bytes 2-3

println(buf.read16(0)) // 4660 (0x1234)
println(buf.read16(1)) // 43981 (0xABCD)
Índice en unidades de 16 bits

read16(1) accede a los bytes 2-3, no al byte 1. Para un buffer de N bytes, el rango de índices válido es 0 a (N/2) - 1.


write16

Escribe un valor de 16 bits (2 bytes) en el índice indicado. El índice se expresa en unidades de 16 bits.

buf.write16(indice, valor)

Parámetros:

ParámetroTipoDescripción
indiceintegerPosición en unidades de 16 bits (0-based)
valorintegerValor entre 0 y 65535

Lanza una excepción si el índice está fuera de rango.

Ejemplo:

use Bytes

var buf = Bytes.new(8)
buf.write16(0, 0x0102)
buf.write16(1, 0x0304)
buf.write16(2, 0x0506)
buf.write16(3, 0x0708)
precaución

Solo se almacenan los 16 bits bajos del valor. Si el valor supera 65535, los bits superiores se descartan.


read32

Lee un valor de 32 bits (4 bytes) en el índice indicado. El índice se expresa en unidades de 32 bits.

var valor = buf.read32(indice)

Parámetros:

ParámetroTipoDescripción
indiceintegerPosición en unidades de 32 bits (0-based)

Retorna: Un entero de 32 bits sin signo. Lanza una excepción si el índice está fuera de rango.

Ejemplo:

use Bytes

var buf = Bytes.new(8)
buf.write32(0, 0xDEADBEEF)
buf.write32(1, 0x12345678)

println(buf.read32(0)) // 3735928559 (0xDEADBEEF)
println(buf.read32(1)) // 305419896 (0x12345678)
Índice en unidades de 32 bits

read32(1) accede a los bytes 4-7, no al byte 1. Para un buffer de N bytes, el rango de índices válido es 0 a (N/4) - 1.


write32

Escribe un valor de 32 bits (4 bytes) en el índice indicado. El índice se expresa en unidades de 32 bits.

buf.write32(indice, valor)

Parámetros:

ParámetroTipoDescripción
indiceintegerPosición en unidades de 32 bits (0-based)
valorintegerValor entre 0 y 4294967295 (0x00000000 a 0xFFFFFFFF)

Lanza una excepción si el índice está fuera de rango.

Ejemplo:

use Bytes

var buf = Bytes.new(16)
buf.write32(0, 0x00FF00FF)
buf.write32(1, 0xFF00FF00)

Resumen de índices

La diferencia clave entre los métodos de lectura/escritura es la unidad del índice:

MétodoUnidad del índiceBytes accedidosRango válido (buffer de N bytes)
read / write1 byte1 byte0 a N-1
read16 / write162 bytes2 bytes0 a (N/2)-1
read32 / write324 bytes4 bytes0 a (N/4)-1

Plataformas soportadas

PlataformaSoporte
Windows
ESP32
Web (Emscripten)

Ejemplo completo: Construir una trama de protocolo

use Bytes

// Trama: [cabecera 2B][longitud 2B][dato0 1B][dato1 1B][checksum 4B]
var trama = Bytes.new(10)
trama.fill(0)

// Escribir cabecera 0xAA55 en posición 0 (16 bits)
trama.write16(0, 0xAA55)

// Escribir longitud = 2 en posición 1 (16 bits → bytes 2-3)
trama.write16(1, 2)

// Escribir datos en bytes 4 y 5
trama.write(4, 0x2A)
trama.write(5, 0x7F)

// Escribir checksum en posición 1 (32 bits → bytes 4-7... ojo al solapamiento)
// Usar posición 1 de 32 bits = bytes 4-7 solo si el diseño de trama lo permite
// En este ejemplo lo ponemos al final (bytes 6-9)
// Para bytes 6-9 sería índice 32bit = 1 (offset 4 bytes desde el inicio, no aplica)
// Mejor calcularlo byte a byte:
var checksum = 0xAA55 + 2 + 0x2A + 0x7F
trama.write(6, checksum % 256)
trama.write(7, (checksum / 256) % 256)

// Verificar
println("Cabecera: ", trama.read16(0)) // 43605 (0xAA55)
println("Longitud: ", trama.read16(1)) // 2
println("Dato 0: ", trama.read(4)) // 42 (0x2A)
println("Dato 1: ", trama.read(5)) // 127 (0x7F)
println("Tamaño: ", trama.size()) // 10

Ejemplo: Buffer de píxeles para Display

use Bytes
use Display

var display = Display
var draw = display.draw

var ancho = 320
var alto = 240

display.open(ancho, alto)

var buf = Bytes.new(ancho * alto)
var palette[256]

// Escala de rojo
for (var i = 0;i < 256;i++)
palette[i] = i << 16
end

for (var y = 0;y < alto;y++)
for (var x = 0;x < ancho;x++)
var c = int((x * 255) / (ancho - 1))
buf.write((y * ancho) + x, c)
end
end

while (true)
draw.bytes(0, 0, ancho, alto, buf, palette)
display.update()
pause(32)
end