/** * Takes a stream of bytes and builds a ScripterMsg from it */ ScripterMsg* bytes_to_message( uint_least8_t* msg_bytes, int total_size ) { ScripterMsg* msg = malloc(sizeof(ScripterMsg)); // ID first if ( total_size >= 3 ) { msg->id = msg_bytes[0]<<8 | msg_bytes[1]; // Third byte gives me param count msg->param_count = msg_bytes[2]; } else { send_debug_msg("Received less than 3 bytes. Can't create message."); free(msg); return NULL; } // now we parse parameters int i; int idx; // used to traverse msg_bytes. Starts after the header, 4th byte MsgParam* previous = NULL; for( i=0, idx=3; i<msg->param_count; i++ ) { uint32_t size; if ( total_size >= idx+3 ) { // Three bytes for the size size = msg_bytes[idx]<<16 | msg_bytes[idx+1]<<8 | msg_bytes[idx+2]; idx += 3; } else { send_debug_msg("Received less than %d bytes. Can't create message",idx+3); free(msg); return NULL; } if ( idx+(int)size > total_size ) { send_debug_msg("Received %d bytes, but need at least %d for this message.", total_size, idx+size); free(msg); return NULL; } uint_least8_t* data = malloc(size); // now the content int j; for( j=0; j<(int)size; j++ ) { *(data+j) = msg_bytes[idx++]; } MsgParam* param = create_msg_param(data,size); // link the parameters if ( previous == NULL ) { // this is the first parameter we parsed msg->parameters = param; } else { previous->next_param = param; } previous = param; } return msg; }
/** * Installs Lua byte code by creating a file on the MMC/SD card. * This code will be executed in a loop if the camera is started * the next time in standalone mode. */ void install_lua( uint_least8_t* bytecode, size_t size ) { FILE *f = fopen(BYTECODE_PERM_FILE, "w"); if ( f == NULL ) { send_debug_msg("Unable to install bytecode. Could not open file on MMC card. Is the MMC card installed?"); return; } size_t i; for(i=0; i<size; i++) { fputc(bytecode[i],f); } fclose(f); send_debug_msg("LUA bytecode installed successfully!"); }
/** * Get a new track packet as a full userdata. Returns a track * packet. */ int tracker_new(lua_State *_l) { cc3_track_pkt_t *pkt; uint8_t minred, mingreen, minblue, maxred, maxgreen, maxblue; pkt = (cc3_track_pkt_t*) lua_newuserdata(_l, sizeof(cc3_track_pkt_t)); if (pkt == NULL) { send_debug_msg("Error allocating memory for the new tracker."); } minred = luaL_checknumber(_l, 1); mingreen = luaL_checknumber(_l, 2); minblue = luaL_checknumber(_l, 3); maxred = luaL_checknumber(_l, 4); maxgreen = luaL_checknumber(_l, 5); maxblue = luaL_checknumber(_l, 6); pkt->lower_bound.channel[0] = minred; pkt->lower_bound.channel[1] = mingreen; pkt->lower_bound.channel[2] = minblue; pkt->upper_bound.channel[0] = maxred; pkt->upper_bound.channel[1] = maxgreen; pkt->upper_bound.channel[2] = maxblue; pkt->x0 = pkt->x1 = pkt->y0 = pkt->y1 = pkt->scratch_x = pkt->scratch_y = 0; pkt->centroid_x = pkt->centroid_y = 0; pkt->num_pixels = pkt->int_density = 0; pkt->noise_filter = 2; // default in cmucam2, duplicating pkt->track_invert = false; pkt->binary_scanline[0] = 0; luaL_getmetatable(_l, "scripter.tracker"); lua_setmetatable(L, -2); return 1; }
/** * Get a new image struct. Returns a pointer to a cc3_image_t */ int image_new(lua_State *_l) { cc3_image_t *i; int num_bytes; uint16_t width, height; uint32_t pixsize; width = luaL_checknumber(_l, 1); height = luaL_checknumber(_l, 2); pixsize = width*height; num_bytes = sizeof(cc3_image_t); i = (cc3_image_t*) lua_newuserdata(_l, num_bytes); i->width = width; i->height = height; i->pix = malloc(pixsize); if (i->pix == NULL) { send_debug_msg("Error allocating memory for the images's pix"); } i->channels = CC3_CHANNEL_ALL; luaL_getmetatable(_l, "scripter.image"); lua_setmetatable(L, -2); return 1; // new userdata is already on the lua stack }
/** * Sends Lua error message */ void show_error (lua_State *_l, int status) { const char *msg; msg = lua_tostring(_l, -1); if (msg == NULL) msg = "(error with no message)"; send_debug_msg("Error executing Lua!\nError code=%d, %s\n", status, msg); }
/** * Implementation of Lua's print function */ int print(lua_State *_l) { if (debug_on) { int n=lua_gettop(_l); int i; for (i=1; i<=n; i++) { if (lua_isstring(_l,i)) { send_debug_msg("%s",lua_tostring(_l,i)); } else if (lua_isnil(_l,i)==2) { send_debug_msg("%s","nil"); } else if (lua_isboolean(_l,i)) { send_debug_msg("%s",lua_toboolean(_l,i) ? "true" : "false"); } else { send_debug_msg("%s:%p",luaL_typename(_l,i),lua_topointer(_l,i)); } } } return 0; }
/** * Execute Lua byte code by first creating a file on the MMC/SD card and then * passing that file to Lua interpreter. */ void execute_lua( uint_least8_t* bytecode, size_t size ) { FILE *f = fopen(BYTECODE_TMP_FILE, "w"); if ( f == NULL ) { send_debug_msg("Unable to execute bytecode. Could not open tmp file on MMC card. Is the MMC card installed?"); return; } int status; size_t i; for(i=0; i<size; i++) { fputc(bytecode[i],f); } fclose(f); // execute the lua file, and show any errors send_debug_msg("Executing Lua code..."); status = lualib_dofile(BYTECODE_TMP_FILE); if (status) { show_error(L, i); } else { send_debug_msg("Lua execution finished!"); } }
/** * Get a new frame diff packet as a full userdata. Returns a frame diff * packet with the previous and current templates set to template_width * * template_height size. */ int framediff_new(lua_State *_l) { cc3_frame_diff_pkt_t *pkt; uint16_t tw, th; int template_size; tw = luaL_checknumber(_l, 1); th = luaL_checknumber(_l, 2); template_size = tw * th * sizeof(uint32_t); pkt = (cc3_frame_diff_pkt_t*) lua_newuserdata(_l, sizeof(cc3_frame_diff_pkt_t)); if (pkt == NULL) { send_debug_msg("Error allocating memory for the new framediff."); } pkt->template_width = tw; pkt->template_height = th; pkt->current_template = (uint32_t*) malloc(template_size); if (pkt->current_template == NULL) { send_debug_msg("Error allocating memory for the framediff's current template"); } pkt->previous_template = (uint32_t*) malloc(template_size); if (pkt->previous_template == NULL) { send_debug_msg("Error allocating memory for the framediff's previous template"); } // initialize all other fields pkt->x0 = pkt->x1 = pkt->y0 = pkt->y1 = 0; pkt->centroid_x = pkt->centroid_y = 0; pkt->int_density = pkt->total_x = pkt->total_y = 0; pkt->num_pixels = pkt->threshold = 0; pkt->load_frame = false; pkt->coi = CC3_CHANNEL_ALL; luaL_getmetatable(_l, "scripter.framediff"); lua_setmetatable(L, -2); return 1; // pkt's already on the stack, thanks to the newuserdata call }
/** * Get and send information about the specified point in the pixbuf. * Look at the 5x5 rectangle within two pixels of x, y, and send back: * R, G, B at (x, y) * average R, G, B */ void send_image_info(int x, int y) { int BUFFER = 2; cc3_image_t img; cc3_pixel_t pixel; image_info_pkt_t* info_pkt = malloc(sizeof(image_info_pkt_t)); info_pkt->x = x; info_pkt->y = y; // make sure we got legal values if (x > cc3_g_pixbuf_frame.width || y > cc3_g_pixbuf_frame.height) { send_debug_msg("(%d, %d) is outside the bounds of the pixbuf.", x, y); return; } info_pkt->x = x; info_pkt->y = y; info_pkt->avg_r = info_pkt->avg_g = info_pkt->avg_b = 0; // get mins and maxes, in case we're near the edge of an image int y_min = y - BUFFER; if (y_min < 0) { y_min = 0; } int y_max = y + BUFFER; if (y_max > cc3_g_pixbuf_frame.height) { y_max = cc3_g_pixbuf_frame.height; } int x_min = x - BUFFER; if (x_min < 0) { x_min = 0; } int x_max = x + BUFFER; if (x_max > cc3_g_pixbuf_frame.width) { x_max = cc3_g_pixbuf_frame.width; } // get to the min row first cc3_pixbuf_rewind(); img.pix = cc3_malloc_rows(1); int idx = 0; while (idx < y_min) { cc3_pixbuf_read_rows(img.pix, 1); idx++; } int num_pix = 0; for (; idx < y_max+1; idx++) { cc3_pixbuf_read_rows(img.pix, 1); for (int j = x_min; j < x_max+1; j++) { cc3_get_pixel(&img, j, 0, &pixel); info_pkt->avg_r += pixel.channel[0]; info_pkt->avg_g += pixel.channel[1]; info_pkt->avg_b += pixel.channel[2]; if (idx == y && j == x) { info_pkt->r = pixel.channel[0]; info_pkt->g = pixel.channel[1]; info_pkt->b = pixel.channel[2]; } num_pix++; } } info_pkt->avg_r = info_pkt->avg_r / num_pix; info_pkt->avg_g = info_pkt->avg_g / num_pix; info_pkt->avg_b = info_pkt->avg_b / num_pix; free(img.pix); // free img.pix info_pkt gets freed in send_image_info_msg send_image_info_msg(info_pkt); }