Read and decode .led file
I also had problems interpreting the structure of the .LED file however another method would be to create your own bitmaps. I created a LED image using Microsoft Paint, under File | Properties I set the width and height both to 10 pixels followed by a File | Save As and selecting 24-bit Bitmap as the type. If you zoom in to maximum it's easy to select pixels individually and Linux and Mac OSX have plenty of applications that can write Windows bitmaps if you're using a different O/S.

Then I created the following Visual C++ command line application to read the bitmap and create a constant array definition. It writes the code to stdout so for example you can invoke it using bitmapconvert test.bmp &gt; test.h. Note that it makes various assumptions regarding the bitmap size and bit depth so in no way is 'production code' so at some stage you may want to look further into the bitmap file format.

#include "stdafx.h"
#include &lt;stdio.h&gt;
#include &lt;stdint.h&gt;

#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(&amp;data_offset, sizeof(data_offset), 1, bmp);
    fseek(bmp, data_offset, SEEK_SET); // Move to start of bits
    while (fread(&amp;pixels[cury][curx], sizeof(PIXEL_DEF), 1, bmp))
    {
        curx++;
        if (curx &gt;= 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 &lt; BITMAP_HEIGHT; y++)
    {
        for (x=0; x &lt; 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 &lt; 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;
}


The 10 x 10 24-bitmap I used for testing has the following pattern.



The output generated from the above program has been included at the start of following pseudocode that is my interpretation from the datasheet of how data should be sent to the device. The following delays are fow low speed mode, use half the values for high speed (although reset can remain the same). Pin 7 is connected to VDD for low speed, and left disconnected for high-speed so you'll need to check how your hardware is configured. If possible low speed will be easier.

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 &lt; sizeof(bitmap_data); i++)
    {
        if (bitmap_data[i] &amp; 0x80) send_one() else send_zero();
        if (bitmap_data[i] &amp; 0x40) send_one() else send_zero();
        if (bitmap_data[i] &amp; 0x20) send_one() else send_zero();
        if (bitmap_data[i] &amp; 0x10) send_one() else send_zero();
        if (bitmap_data[i] &amp; 0x08) send_one() else send_zero();
        if (bitmap_data[i] &amp; 0x04) send_one() else send_zero();
        if (bitmap_data[i] &amp; 0x02) send_one() else send_zero();
        if (bitmap_data[i] &amp; 0x01) send_one() else send_zero();
    }
}


As you can see the protocol is not SPI and one challenge you will have getting the timing right within the +/- 150nS specified by the datasheet which is about 1 cycle at 8MHz. Rather than using any form of delay_us you'll probably have to use nop instructions and take into account timing delays caused by setting the ports and function calls etc. Sometimes examining the assembler output of the compiler can be useful in that regard and a scope is always useful to verify it. The datasheet appears to show the same 150nS value for both low and high speed modes. It may be in low speed mode it's a little less critical in practice.

Having said that I just looked at the FastSPI library you mentioned and it does mention support for that device. It appears to use the SPI channel in a non-standard way (not that there's any problem with that) to help alleviate the timing constraints. So a good starting point would be try using that in combination with the above bitmap table.