Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Loading pattern broken? #35

Open
jezdez opened this issue Aug 2, 2019 · 7 comments
Open

Loading pattern broken? #35

jezdez opened this issue Aug 2, 2019 · 7 comments
Labels

Comments

@jezdez
Copy link

jezdez commented Aug 2, 2019

Hey there! Maybe I'm missing something but trying the following on a Keybow mini didn't load the patterns as expected:

keybow.load_pattern("rainbow.png")
keybow.load_pattern("patterns/rainbow.png")
keybow.load_pattern("patterns/rainbow")
local pattern = require "patterns/rainbow.png"
keybow.load_pattern(pattern)

Could someone explain what the correct syntax is for this please?

@Gadgetoid
Copy link
Member

Near as I can tell, there's nothing wrong with what you're attempting and a cursory check over the code doesn't yield any obvious problems. I'll try and run a debug build and see if I can replicate.

@jezdez
Copy link
Author

jezdez commented Aug 20, 2019

But to clarify, it's supposed to be keybow.load_pattern("patterns/rainbow.png") right?

@Gadgetoid
Copy link
Member

Gadgetoid commented Aug 20, 2019

Ooof, lack of documentation hurts here- it should be:

keybow.load_pattern("patterns/rainbow")

The png part is, for better or worse, added automatically.

A quick local test shows this is at least not failing. Whereas if I try to load patterns/rainbow.png I get the expected:

[read_png_file] File patterns/rainbow.png.png could not be opened for reading

@FleaRex
Copy link

FleaRex commented Aug 21, 2019

Hi both!

This is my minimal working version:

require "keybow"

function handle_key_00(pressed)
    if pressed then
        load_new_pattern()
    end
end

function handle_key_01(pressed)
    if pressed then
        load_new_pattern()
    end
end

function handle_key_02(pressed)
    if pressed then
        load_new_pattern()
    end
end

function handle_key_03(pressed)
    if pressed then
        load_new_pattern()
    end
end

function handle_key_04(pressed)
    if pressed then
        load_new_pattern()
    end
end

function handle_key_05(pressed)
    if pressed then
        load_new_pattern()
    end
end

function handle_key_06(pressed)
    if pressed then
        load_new_pattern()
    end
end

function handle_key_07(pressed)
    if pressed then
        load_new_pattern()
    end
end

function handle_key_08(pressed)
    if pressed then
        load_new_pattern()
    end
end

function handle_key_09(pressed)
    if pressed then
        load_new_pattern()
    end
end

function handle_key_10(pressed)
    if pressed then
        load_new_pattern()
    end
end

function handle_key_11(pressed)
    if pressed then
        load_new_pattern()
    end
end

function load_new_pattern()
    keybow.load_pattern('patterns/rainbow')
end

It seemed like keybow.auto_lights(false) was doing something different to what I thought and wouldn't allow load_pattern after getting called.

Two quick Qs

  1. Would you like a pull request to add this as an example?
  2. It seems like patterns/tropical.png isn't right in the most recent release. Is it worth doing a new release?

@Gadgetoid
Copy link
Member

Clearly we need some comprehensive documentation on this functionality-

keybow.auto_lights(false) completely disables the image-based animation sequencing and light patterns in favour of setting individual LEDs manually.

@FleaRex
Copy link

FleaRex commented Aug 28, 2019

Thanks for confirming! Is the C code that the lua code calls around anywhere? It would be interesting to see what keybow.load_pattern and keybow.auto_lights really do. Either way I'm loving it and now that I know what I'm doing it's working really well.

@Gadgetoid
Copy link
Member

Absolutely- all the C source is here to browse: https://github.com/pimoroni/keybow-firmware/tree/master/keybow

Here's what keybow.load_pattern boils down to:

static int l_load_pattern(lua_State *L) {
int nargs = lua_gettop(L);
size_t length;
const char *pattern = luaL_checklstring(L, 1, &length);
lua_pop(L, nargs);
char filename[length + 10];
sprintf(filename, "%s.png", pattern);
pthread_mutex_lock(&lights_mutex);
int result = read_png_file(filename);
pthread_mutex_unlock(&lights_mutex);
lua_pushboolean(L, result == 0);
return 1;
}

Which, in turn, calls read_png_file in C:

int read_png_file(char* file_name)
{
unsigned char header[8]; // 8 is the maximum size that can be checked
/* open file and test for it being a png */
FILE *fp = fopen(file_name, "rb");
if (!fp) {
abort_("[read_png_file] File %s could not be opened for reading", file_name);
return 1;
}
fread(header, 1, 8, fp);
if (png_sig_cmp(header, 0, 8)) {
abort_("[read_png_file] File %s is not recognized as a PNG file", file_name);
return 1;
}
/* initialize stuff */
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr) {
abort_("[read_png_file] png_create_read_struct failed");
return 1;
}
info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr) {
abort_("[read_png_file] png_create_info_struct failed");
return 1;
}
if (setjmp(png_jmpbuf(png_ptr))) {
abort_("[read_png_file] Error during init_io");
return 1;
}
png_init_io(png_ptr, fp);
png_set_sig_bytes(png_ptr, 8);
png_read_info(png_ptr, info_ptr);
width = png_get_image_width(png_ptr, info_ptr);
height = png_get_image_height(png_ptr, info_ptr);
color_type = png_get_color_type(png_ptr, info_ptr);
bit_depth = png_get_bit_depth(png_ptr, info_ptr);
color_channels = png_get_channels(png_ptr, info_ptr);
number_of_passes = png_set_interlace_handling(png_ptr);
png_read_update_info(png_ptr, info_ptr);
/* read file */
if (setjmp(png_jmpbuf(png_ptr))) {
abort_("[read_png_file] Error during read_image");
return 1;
}
row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * height);
for (y=0; y<height; y++)
row_pointers[y] = (png_byte*) malloc(png_get_rowbytes(png_ptr,info_ptr));
png_read_image(png_ptr, row_pointers);
fclose(fp);
return 0;
}

And keybow.auto_lights:

static int l_auto_lights(lua_State *L) {
int nargs = lua_gettop(L);
unsigned short state = lua_toboolean(L, 1);
lua_pop(L, nargs);
lights_auto = state;
return 0;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants