Leer y decodificar archivo .led

Estoy trabajando en una pantalla LED flexible que consta de 20 metros de tira de LED RGB digital con IC WS2811 para cada LED.

Quiero controlar esto usando Arduino, lo cual no es un problema usando FastSPI. Mi problema es que quiero crear diferentes programas LED (por ejemplo, usando LedEdit 2013) que luego se pueden exportar a archivos * .led.

Esto en sí mismo no es un problema, ya que ya he generado estos archivos. El problema es cómo leer y decodificar el archivo *.led. Por lo que he podido leer en Internet (buscando un par de horas ahora), los archivos consisten en algún tipo de encabezado seguido de información codificada en base64 sobre la posición x e y de los LED que deben encenderse y de qué color deben ser (valor RGB 0-255, supongo). No estoy del todo seguro de cómo exactamente voy a decodificar esta señal y sacar algo realmente útil de ella.

Si puedo obtener información útil, seguramente puedo programar mi salida si la implemento con la biblioteca FastSPI para Arduino.

EDITAR:

He creado dos archivos de ejemplo simples que tal vez podrían ser más fáciles de ver para ustedes.

Ambos están compuestos por una sencilla configuración de leds de 10 x 10, ambos de una sola escena; uno todo negro y otro todo blanco.

Negro: http://www.codesmith.dk/black.led y Blanco: http://www.codesmith.dk/white.led

¿El archivo LED de ejemplo que ha publicado solo muestra un patrón para el primer cuadro y en blanco para los otros 19 por casualidad?
@PeterJ Accidentalmente cambié el archivo de ejemplo en mi servidor. Cambié la publicación anterior para tener ahora dos archivos de ejemplo: uno de una escena LED negra y otro de una escena LED blanca. Lo que he llegado a concluir hasta ahora: cada línea tiene exactamente 1024 caracteres; La primera línea tiene 512 "cosas aleatorias" y 512 caracteres de lo que parece ser información de la escena; Cuando la escena es uniforme (blanca o negra), la información del archivo parece ser información de color uniforme que se va a enviar. Todavía tengo problemas para entender esto como código binario o código decimal, incluso usando la decodificación base64 ...
¡Listo, ahora quiero algunos LED negros! Oh, espera, tengo algunos diodos emisores de luz negra , los UV.
A mí me parecen datos binarios directos, solo le di una buena oportunidad y comencé a escribir una respuesta acerca de que era un flujo de bits porque los valores 0/1 están determinados por anchos de pulso variables (no es SPI normal) pero algunas cosas no Tampoco sumo allí cuando miré los patrones de bits. De todos modos, no tendría la oportunidad durante unos días, pero si no obtiene una respuesta, envíeme un ping y escribiré una respuesta con una forma diferente de hacerlo sin usar LedEdit (aunque será pseudocódigo C no probado ).
Anindo Ghosh: que?? @PeterJ: ayer empezó a tener un poco de sentido para mí, pero de repente ya no. Estaba pensando si lo que estaba viendo era un flujo de bits de 0/1, pero luego, de nuevo, para obtener blanco, me imagino que todo es solo 1 y obtener negro solo 0, lo cual no es el caso. También parece que los caracteres utilizados en el archivo son diferentes cada vez que realizo una exportación de prueba. Ayer hice una escena RGBWB simple (una escena de cada una) que dio un patrón interesante, pero aún así nada útil.
@PeterJ Algún pseudocódigo C sería absolutamente increíble, tal vez podría ayudarme en la dirección correcta.
@PeterJ ¿Alguna noticia sobre el pseudocódigo? Lo he dejado por un tiempo, pero todavía no tiene ningún sentido en mi cabeza, desafortunadamente...
@Simon, estuve ocupado durante unos días y luego me olvidé, tendré la oportunidad de echar un vistazo mañana. Se está haciendo tarde aquí, pero tomé nota y debería tener algo publicado antes de esta hora mañana.

Respuestas (1)

También tuve problemas para interpretar la estructura del archivo .LED; sin embargo, otro método sería crear sus propios mapas de bits. Creé una imagen LED usando Microsoft Paint, debajo File | Propertiesconfiguré el ancho y la altura en 10 píxeles seguidos de una File | Save Asy seleccioné 24-bit Bitmapcomo tipo. Si hace zoom al máximo, es fácil seleccionar píxeles individualmente y Linux y Mac OSX tienen muchas aplicaciones que pueden escribir mapas de bits de Windows si está usando un sistema operativo diferente.

Luego creé la siguiente aplicación de línea de comandos de Visual C++ para leer el mapa de bits y crear una definición de matriz constante. Escribe el código en stdout, por lo que, por ejemplo, puede invocarlo usando bitmapconvert test.bmp > test.h. Tenga en cuenta que hace varias suposiciones con respecto al tamaño del mapa de bits y la profundidad de bits, por lo que de ninguna manera es un "código de producción", por lo que en algún momento es posible que desee profundizar en el formato del archivo de mapa de bits.

#include "stdafx.h"
#include <stdio.h>
#include <stdint.h>

#define BITMAP_WIDTH 10
#define BITMAP_HEIGHT 10

#pragma pack (1)
struct PIXEL_DEF {
    uint8_t B, G, R;
} pixels[BITMAP_HEIGHT][BITMAP_WIDTH];

void read_bitmap_data(FILE *bmp)
{
    uint32_t data_offset, curx = 0, cury = 0;

    fseek(bmp, 10, SEEK_SET); // Skip to offset to bitmap bits
    fread(&data_offset, sizeof(data_offset), 1, bmp);
    fseek(bmp, data_offset, SEEK_SET); // Move to start of bits
    while (fread(&pixels[cury][curx], sizeof(PIXEL_DEF), 1, bmp))
    {
        curx++;
        if (curx >= BITMAP_WIDTH)
        {
            // Rows padded to 4 bytes, so we may need to skip some data
            fseek(bmp, 32 - curx * sizeof(PIXEL_DEF) % 32, SEEK_CUR);
            curx = 0;
            cury++;
        }
    }
    fclose(bmp);
}

// Following assumes top-left to bottom-right order, you may need to change
void dump_bitmap()
{
    int x, y;

    printf("const uint8_t bitmap_data[] = {\n");
    for (y=0; y < BITMAP_HEIGHT; y++)
    {
        for (x=0; x < BITMAP_WIDTH; x++)
        {
            if (x == 0)
                printf("\t");
            else
                printf(",");
            printf("0x%02X,0x%02X,0x%02X", pixels[y][x].R, pixels[y][x].G, pixels[y][x].B);
        }
        if (y < BITMAP_HEIGHT)
            printf(",");
        printf("\n");
    }
    printf("};\n");
}

int _tmain(int argc, TCHAR* argv[])
{
    FILE *bmp;

    if (argc != 2)
        printf("Usage: BitMapConvert infile.bmp");
    else {
        if (bmp = _wfopen(argv[1], _T("rb")))
        {
            read_bitmap_data(bmp);
            dump_bitmap();
        }
    }
    return 0;
}

El mapa de 24 bits de 10 x 10 que utilicé para las pruebas tiene el siguiente patrón.

Patrón de prueba

La salida generada por el programa anterior se ha incluido al comienzo del siguiente pseudocódigo, que es mi interpretación de la hoja de datos de cómo se deben enviar los datos al dispositivo. Los siguientes retrasos son para el modo de baja velocidad, use la mitad de los valores para alta velocidad (aunque el restablecimiento puede permanecer igual). El pin 7 está conectado a VDD para baja velocidad y se deja desconectado para alta velocidad, por lo que deberá verificar cómo está configurado su hardware. Si es posible a baja velocidad será más fácil.

const uint8_t bitmap_data[] = {
    0x00,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0xFF,0xFF,
    0xFF,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0xFF,
    0xFF,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,
    0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,
    0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,
    0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,
    0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,
    0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0xFF,
    0xFF,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,
    0xFF,0xFF,0xFF,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,
};

void send_zero()
{
    set_DI_high();
    delay_us(0.5);
    set_DI_low();
    delay_us(2);
}

void send_one()
{
    set_DI_high();
    delay_us(1.2);
    set_DI_low();
    delay_us(1.3);
}

void send_reset()
{
    set_DI_low();
    delay_us(50);
    set_DI_high();
}

void send_image()
{
    uint8_t i;

    send_reset();
    for (i=0; i < sizeof(bitmap_data); i++)
    {
        if (bitmap_data[i] & 0x80) send_one() else send_zero();
        if (bitmap_data[i] & 0x40) send_one() else send_zero();
        if (bitmap_data[i] & 0x20) send_one() else send_zero();
        if (bitmap_data[i] & 0x10) send_one() else send_zero();
        if (bitmap_data[i] & 0x08) send_one() else send_zero();
        if (bitmap_data[i] & 0x04) send_one() else send_zero();
        if (bitmap_data[i] & 0x02) send_one() else send_zero();
        if (bitmap_data[i] & 0x01) send_one() else send_zero();
    }
}

Como puede ver, el protocolo no es SPI y un desafío será obtener la sincronización correcta dentro de los +/- 150 nS especificados en la hoja de datos, que es aproximadamente 1 ciclo a 8 MHz. En lugar de usar cualquier forma de, delay_usprobablemente tendrá que usar nopinstrucciones y tener en cuenta los retrasos de tiempo causados ​​​​por la configuración de los puertos y las llamadas a funciones, etc. A veces, examinar la salida del ensamblador del compilador puede ser útil en ese sentido y un alcance siempre es útil para verificarlo. La hoja de datos parece mostrar el mismo valor de 150 nS para los modos de baja y alta velocidad. Puede estar en modo de baja velocidad, es un poco menos crítico en la práctica.

Habiendo dicho eso, acabo de mirar la biblioteca FastSPI que mencionaste y menciona soporte para ese dispositivo. Parece usar el canal SPI de una manera no estándar (no es que haya ningún problema con eso) para ayudar a aliviar las limitaciones de tiempo. Entonces, un buen punto de partida sería intentar usarlo en combinación con la tabla de mapa de bits anterior.

Quizás no sea la solución perfecta, pero me ha dado algunas ideas de un enfoque diferente usando imágenes en lugar de usar un software estándar como LedEdit para hacer los archivos. ¡Muchas gracias por tu tiempo y ayuda!