diff --git a/NOTES.txt b/NOTES.txt index 96a7ffa..4ea453d 100644 --- a/NOTES.txt +++ b/NOTES.txt @@ -26,3 +26,62 @@ unsigned char * cairo_image_surface_get_data (cairo_surface_t *surfac get pointer to imag data for inspection _and_ manipulation + + +first disable Auto FFC (autoFFC:false) +Code: [Select] + + //--------- write string: {"type":"setOption","data":{"option":"autoFFC","value":false}} + length = 16; + unsigned char my_string4[16]={0xcc,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x3f,0x00,0x00,0x00,0x57,0x64,0x17,0x8b}; + printf("\nEP 0x02 to be sent Hexcode: %i Bytes[",length); + for (i = 0; i < length; i++) { + printf(" %02x", my_string4[i]); + + } + printf(" ]\n"); + + r = libusb_bulk_transfer(devh, 2, my_string4, length, &transferred, 0); + if(r == 0 && transferred == length) + { + printf("\nWrite successful!"); + } + else + printf("\nError in write! res = %d and transferred = %d\n", r, transferred); + + strcpy( my_string,"{\"type\":\"setOption\",\"data\":{\"option\":\"autoFFC\",\"value\":false}}"); + length = strlen(my_string)+1; + printf("\nEP 0x02 to be sent %i Bytes: %s", length, my_string); + + // avoid error: invalid conversion from ‘char*’ to ‘unsigned char*’ [-fpermissive] + my_string1 = (unsigned char*)my_string; + + r = libusb_bulk_transfer(devh, 2, my_string1, length, &transferred, 0); + if(r == 0 && transferred == length) + { + printf("\nWrite successful!"); + printf("\nSent %d bytes with string: %s\n", transferred, my_string); + } + else + printf("\nError in write! res = %d and transferred = %d\n", r, transferred); + + +and trigger if required a manual FCC (doFFC:true) +Code: [Select] + + unsigned char my_string2[16]={0xcc,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,0xb9,0xcb,0xa2,0x99}; + + r = libusb_bulk_transfer(devh, 2, my_string2, length, &transferred, 0); + if(r == 0 && transferred == length) + printf("\nWrite successful!"); + else + printf("\nError in write! res = %d and transferred = %d\n", r, transferred); + + char my_string[128]; + transferred = 0; + + strcpy(my_string, "{\"type\":\"setOption\",\"data\":{\"option\":\"doFFC\",\"value\":true}}"); + length = strlen(my_string)+1; + + unsigned char *my_string1 = (unsigned char*)my_string; + diff --git a/cam-thread.c b/cam-thread.c index ca244c0..6f759b0 100644 --- a/cam-thread.c +++ b/cam-thread.c @@ -34,6 +34,9 @@ extern unsigned char *color_palette; #include #include #include +#include +#include +#include #include #include @@ -46,60 +49,6 @@ extern unsigned char *color_palette; // #include "jpeglib.h" - -// -- define v4l2 --------------- -// #include -#include -#include -#include -#include - -#if 0 -#define VIDEO_DEVICE0 "/dev/video1" // gray scale thermal image -#define FRAME_WIDTH0 160 -#define FRAME_HEIGHT0 120 - -#define VIDEO_DEVICE1 "/dev/video2" // color visible image -#define FRAME_WIDTH1 640 -#define FRAME_HEIGHT1 480 - -#define VIDEO_DEVICE2 "/dev/video3" // colorized thermal image -#define FRAME_WIDTH2 160 -#define FRAME_HEIGHT2 128 - -#define FRAME_FORMAT0 V4L2_PIX_FMT_GREY -#define FRAME_FORMAT1 V4L2_PIX_FMT_MJPEG -#define FRAME_FORMAT2 V4L2_PIX_FMT_RGB24 - -struct v4l2_capability vid_caps0; -struct v4l2_capability vid_caps1; -struct v4l2_capability vid_caps2; - -struct v4l2_format vid_format0; -struct v4l2_format vid_format1; -struct v4l2_format vid_format2; - -size_t framesize0; -size_t linewidth0; - -size_t framesize1; -size_t linewidth1; - -size_t framesize2; -size_t linewidth2; - - -const char *video_device0=VIDEO_DEVICE0; -const char *video_device1=VIDEO_DEVICE1; -const char *video_device2=VIDEO_DEVICE2; - -int fdwr0 = 0; -int fdwr1 = 0; -int fdwr2 = 0; - -// -- end define v4l2 --------------- -#endif - #define VENDOR_ID 0x09cb #define PRODUCT_ID 0x1996 @@ -107,7 +56,12 @@ static struct libusb_device_handle *devh = NULL; int filecount=0; struct timeval t1, t2; long long fps_t; - + +double t_min = 0.0; +double t_max = 0.0; +double t_center = 0.0; + + int FFC = 0; // detect FFC // -- buffer for EP 0x85 chunks --------------- @@ -210,7 +164,7 @@ void vframe(char ep[],char EP_error[], int r, int actual_length, unsigned char b // Make a unsigned short array from what comes from the thermal frame // find the max, min and RMS (not used yet) values of the array - int maxx, maxy; + //int maxx, maxy; for (y = 0; y < 120; ++y) { for (x = 0; x < 160; ++x) { if (x<80) @@ -222,7 +176,7 @@ void vframe(char ep[],char EP_error[], int r, int actual_length, unsigned char b if (v < min) min = v; if (v > max) { - max = v; maxx = x; maxy = y; + max = v; //maxx = x; maxy = y; } rms += v * v; } @@ -247,39 +201,43 @@ void vframe(char ep[],char EP_error[], int r, int actual_length, unsigned char b } } - char st1[100]; - char st2[100]; - struct tm *loctime; + //char st1[100]; + //char st2[100]; + //struct tm *loctime; // Convert it to local time and Print it out in a nice format. - loctime = localtime (&now1); - strftime (st1, 60, "%H:%M:%S", loctime); - + //loctime = localtime (&now1); + //strftime (st1, 60, "%H:%M:%S", loctime); + // calc medium of 2x2 center pixels int med = (pix[59 * 160 + 79]+pix[59 * 160 + 80]+pix[60 * 160 + 79]+pix[60 * 160 + 80])/4; - sprintf(st2," %.1f/%.1f/%.1f'C", raw2temperature(min),raw2temperature(med),raw2temperature(max)); - strcat(st1, st2); - #define MAXC 26 // max chars in line 160/6=26,6 - strncpy(st2, st1, MAXC); + t_min = raw2temperature(min); + t_max = raw2temperature(max); + t_center = raw2temperature(med); + // sprintf(st2," %.1f/%.1f/%.1f'C", raw2temperature(min), raw2temperature(med), raw2temperature(max)); + //strcat(st1, st2); + + //#define MAXC 26 // max chars in line 160/6=26,6 + //strncpy(st2, st1, MAXC); // write zero to string !! - st2[MAXC-1] = '\0'; - fprintf(stderr,"%s\r",st2); + //st2[MAXC-1] = '\0'; + //fprintf(stderr,"%s\r",st2); // font_write(fb_proc, 1, 120, st2); // show crosshairs, remove if required // font_write(fb_proc, 80-2, 60-3, "+"); - maxx -= 4; - maxy -= 4; + //maxx -= 4; + //maxy -= 4; - if (maxx < 0) - maxx = 0; - if (maxy < 0) - maxy = 0; - if (maxx > 150) - maxx = 150; - if (maxy > 110) - maxy = 110; + //if (maxx < 0) + // maxx = 0; + //if (maxy < 0) + // maxy = 0; + //if (maxx > 150) + // maxx = 150; + //if (maxy > 110) + // maxy = 110; // font_write(fb_proc, 160-6, maxy, "<"); // font_write(fb_proc, maxx, 120-8, "|"); @@ -304,7 +262,7 @@ void vframe(char ep[],char EP_error[], int r, int actual_length, unsigned char b fbdata[16*y * 640 + x*16] = color_palette[3 * v + 2]; // B fbdata[(16*y * 640 + x*16)+1] = color_palette[3 * v + 1]; // G fbdata[(16*y * 640 + x*16)+2] = color_palette[3 * v]; // R - fbdata[(16*y * 640 + x*16)+3] = 0x00; // empty + // fbdata[(16*y * 640 + x*16)+3] = 0x00; // empty // copy whole 32bit words hor/vert p1 = (unsigned int *)&fbdata[16*y * 640 + x*16]; diff --git a/flirgtk.c b/flirgtk.c index f2c5034..c053a0b 100644 --- a/flirgtk.c +++ b/flirgtk.c @@ -36,13 +36,17 @@ static cairo_surface_t *surface = NULL; // internal frame buffer with 640x480 pixels of 4 byte each, // first byte unused, R, G, B 0x00RRGGBB -unsigned char fbuffer[640*480*4]; +unsigned char fbuffer[640*500*4]; unsigned char *fbdata; unsigned char *color_palette; gboolean flir_run = FALSE; gpointer cam_thread_main(gpointer user_data); +extern double t_min, t_max, t_center; + +void draw_palette(void); + static gboolean configure_event (GtkWidget *widget, @@ -56,16 +60,16 @@ int stride; cairo_surface_destroy (surface); gtk_widget_get_allocation (widget, &allocation); + // g_printerr("configure event %d x %d\n", allocation.width, allocation.height); stride = cairo_format_stride_for_width (CAIRO_FORMAT_RGB24, 640); // g_printerr("stride %d\n", stride); surface = cairo_image_surface_create_for_data (fbuffer, CAIRO_FORMAT_RGB24, 640, - 480, + 500, stride); fbdata = cairo_image_surface_get_data(surface); - - g_printerr("configure event %d x %d\n", allocation.width, allocation.height); + draw_palette(); /* We've handled the configure event, no need for further processing. */ return TRUE; @@ -85,26 +89,48 @@ draw_event (GtkWidget *widget, return FALSE; } +#include "font5x7.h" +void font_write(unsigned char *fb, int x, int y, const char *string) +{ +int rx, ry, v; + + while (*string) { + for (ry = 0; ry < 5; ++ry) { + for (rx = 0; rx < 7; ++rx) { + v = (font5x7_basic[((*string) & 0x7F) - CHAR_OFFSET][ry] >> (rx)) & 1; + // fb[(y+ry) * 160 + (x + rx)] = v ? 0 : 0xFF; // black / white + fb[((y+rx)*4) * 640 + (x + ry)*4] = v ? 0xff : 0x00; // black / white + fb[((y+rx)*4) * 640 + (x + ry)*4 +1] = v ? 0xff : 0x00; // black / white + fb[((y+rx)*4) * 640 + (x + ry)*4 +2] = v ? 0xff : 0x00; // black / white + // fb[(y+rx) * 160 + (x + ry)] = v ? 0 : fb[(y+rx) * 160 + (x + ry)]; // transparent + } + } + string++; + x += 6; + } +} + void update_fb(void) { -#if 0 -unsigned int x,y; -unsigned int *pdata; -static unsigned char cnt=0; +char tstr[16]; - cnt+=0x0f; - // g_printerr("cnt=%d\n", cnt); - for (y=0; y<480; y++) { - for (x=0; x<640; x++) { - pdata = (unsigned int *)&fbdata[(y*640*4)+(x*4)]; - *pdata = (cnt << 16) | (x << 9) | y; - } - } -#endif + // g_printerr("min %.1f center %.1f max %.1f\r", t_min, t_center, t_max); + + snprintf(tstr, 16, "%.1f", t_min); + font_write(fbdata, 140, 486, tstr); + snprintf(tstr, 16, "%.1f", t_max); + font_write(fbdata, 440, 486, tstr); gtk_widget_queue_draw(image_darea); } +void +store_shot_clicked(GtkWidget *button, gpointer user_data) +{ + + cairo_surface_write_to_png (surface, "shot.png"); +} + void start_clicked(GtkWidget *button, gpointer user_data) { @@ -134,6 +160,28 @@ handle_timeout (gpointer user_data) return TRUE; } +// 256 colors (8bit), two hor pixel per color +// piture width = 640, center scale, i.e. start at 64 +void +draw_palette(void) +{ +unsigned int *p1, *pc; +int x,y; + + y=481; // leave one line blank/black + for (x=0; x<256; x++) { + fbdata[4*y * 640 + (x+174)*4] = color_palette[3 * x + 2]; // B + fbdata[(4*y * 640 + (x+174)*4)+1] = color_palette[3 * x + 1]; // G + fbdata[(4*y * 640 + (x+174)*4)+2] = color_palette[3 * x]; // R + } + y=481; + p1 = (unsigned int *)&fbdata[4*y * 640]; // pointer to start of line + for (y=482; y<500; y++) { + pc = (unsigned int *)&fbdata[4*y * 640]; // pointer to start of copy line + memcpy(pc,p1,640*4); + } +} + void palette_changed (GtkComboBox *widget, gpointer user_data) { @@ -153,6 +201,7 @@ int act; if (act == 7) color_palette = palette_Iron2; if (act == 8) color_palette = palette_Iron_Black; if (act == 9) color_palette = palette_Rainbow; + draw_palette(); }; } @@ -165,6 +214,9 @@ GtkWidget *hbox; GtkWidget *w; // GtkWidget *da; + // default color palette + color_palette = palette_Rainbow; + if (!window) { window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_window_set_title (GTK_WINDOW (window), "FLIR One"); @@ -178,13 +230,19 @@ GtkWidget *w; hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 4); gtk_container_add (GTK_CONTAINER (box), hbox); - w = gtk_button_new_with_label("Start"); + // 48 GTK_ICON_SIZE_DIALOG + // 32 GTK_ICON_SIZE_DND + // media-playback-start + // w = gtk_button_new_with_label("Start"); + w = gtk_button_new_from_icon_name("media-playback-start", GTK_ICON_SIZE_DND); gtk_container_add (GTK_CONTAINER (hbox), w); g_signal_connect (w, "clicked", G_CALLBACK (start_clicked), NULL); - w = gtk_button_new_with_label("Stop"); + // media-playback-stop + // w = gtk_button_new_with_label("Stop"); + w = gtk_button_new_from_icon_name("media-playback-stop", GTK_ICON_SIZE_DND); gtk_container_add (GTK_CONTAINER (hbox), w); g_signal_connect (w, "clicked", @@ -204,13 +262,12 @@ GtkWidget *w; gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT(w), NULL, "Rainbow"); gtk_combo_box_set_active (GTK_COMBO_BOX(w), 9); gtk_container_add (GTK_CONTAINER (hbox), w); - color_palette = palette_Rainbow; g_signal_connect (w, "changed", G_CALLBACK (palette_changed), NULL); image_darea = gtk_drawing_area_new (); /* set a minimum size */ - gtk_widget_set_size_request (image_darea, 640, 480); + gtk_widget_set_size_request (image_darea, 640, 500); gtk_container_add (GTK_CONTAINER (box), image_darea); @@ -219,6 +276,14 @@ GtkWidget *w; g_signal_connect (image_darea,"configure-event", G_CALLBACK (configure_event), NULL); + // camera-photo + // w = gtk_button_new_with_label("Shot"); + w = gtk_button_new_from_icon_name("camera-photo", GTK_ICON_SIZE_DND); + gtk_container_add (GTK_CONTAINER (box), w); + + g_signal_connect (w, "clicked", + G_CALLBACK (store_shot_clicked), NULL); + // g_timeout_add_seconds(1, handle_timeout, NULL); gtk_widget_show_all(window); diff --git a/font5x7.h b/font5x7.h new file mode 100644 index 0000000..b123de3 --- /dev/null +++ b/font5x7.h @@ -0,0 +1,128 @@ +/* From https://ccrma.stanford.edu/courses/250a-fall-2003/docs/avrlib-new/ */ + +/* Original header: */ + +/*! \file font5x7.h \brief Graphic LCD Font (Ascii Characters). */ +//***************************************************************************** +// +// File Name: 'font5x7.h' +// Title: Graphic LCD Font (Ascii Charaters) +// Author: Pascal Stang +// Date: 10/19/2001 +// Revised: 10/19/2001 +// Version: 0.1 +// Target MCU: Atmel AVR +// Editor Tabs: 4 +// +//***************************************************************************** + +/* Original license in cmdline.c: */ + +// This code is distributed under the GNU Public License +// which can be found at http://www.gnu.org/licenses/gpl.txt + +/* Since the original license does not specify the GPL version it is safe */ +/* to assume that it can be distributed under GPL version 1 or any later */ +/* version. */ + +#define MAX_CHARS 96 +#define CHAR_OFFSET 0x20 + +unsigned char font5x7_basic[MAX_CHARS][5] = { + {0x00, 0x00, 0x00, 0x00, 0x00}, // (space) + {0x00, 0x00, 0x5F, 0x00, 0x00}, // ! + {0x00, 0x07, 0x00, 0x07, 0x00}, // " + {0x14, 0x7F, 0x14, 0x7F, 0x14}, // # + {0x24, 0x2A, 0x7F, 0x2A, 0x12}, // $ + {0x23, 0x13, 0x08, 0x64, 0x62}, // % + {0x36, 0x49, 0x55, 0x22, 0x50}, // & + {0x00, 0x05, 0x03, 0x00, 0x00}, // ' + {0x00, 0x1C, 0x22, 0x41, 0x00}, // ( + {0x00, 0x41, 0x22, 0x1C, 0x00}, // ) + {0x08, 0x2A, 0x1C, 0x2A, 0x08}, // * + {0x08, 0x08, 0x63, 0x08, 0x08}, // + {0x08, 0x08, 0x3E, 0x08, 0x08} + {0x00, 0x50, 0x30, 0x00, 0x00}, // , + {0x08, 0x08, 0x08, 0x08, 0x08}, // - + {0x00, 0x60, 0x60, 0x00, 0x00}, // . + {0x20, 0x10, 0x08, 0x04, 0x02}, // / + {0x3E, 0x51, 0x49, 0x45, 0x3E}, // 0 + {0x00, 0x42, 0x7F, 0x40, 0x00}, // 1 + {0x42, 0x61, 0x51, 0x49, 0x46}, // 2 + {0x21, 0x41, 0x45, 0x4B, 0x31}, // 3 + {0x18, 0x14, 0x12, 0x7F, 0x10}, // 4 + {0x27, 0x45, 0x45, 0x45, 0x39}, // 5 + {0x3C, 0x4A, 0x49, 0x49, 0x30}, // 6 + {0x01, 0x71, 0x09, 0x05, 0x03}, // 7 + {0x36, 0x49, 0x49, 0x49, 0x36}, // 8 + {0x06, 0x49, 0x49, 0x29, 0x1E}, // 9 + {0x00, 0x36, 0x36, 0x00, 0x00}, // : + {0x00, 0x56, 0x36, 0x00, 0x00}, // ; + {0x00, 0x08, 0x14, 0x22, 0x41}, // < + {0x14, 0x14, 0x14, 0x14, 0x14}, // = + {0x41, 0x22, 0x14, 0x08, 0x00}, // > + {0x02, 0x01, 0x51, 0x09, 0x06}, // ? + {0x32, 0x49, 0x79, 0x41, 0x3E}, // @ + {0x7E, 0x11, 0x11, 0x11, 0x7E}, // A + {0x7F, 0x49, 0x49, 0x49, 0x36}, // B + {0x3E, 0x41, 0x41, 0x41, 0x22}, // C + {0x7F, 0x41, 0x41, 0x22, 0x1C}, // D + {0x7F, 0x49, 0x49, 0x49, 0x41}, // E + {0x7F, 0x09, 0x09, 0x01, 0x01}, // F + {0x3E, 0x41, 0x41, 0x51, 0x32}, // G + {0x7F, 0x08, 0x08, 0x08, 0x7F}, // H + {0x00, 0x41, 0x7F, 0x41, 0x00}, // I + {0x20, 0x40, 0x41, 0x3F, 0x01}, // J + {0x7F, 0x08, 0x14, 0x22, 0x41}, // K + {0x7F, 0x40, 0x40, 0x40, 0x40}, // L + {0x7F, 0x02, 0x04, 0x02, 0x7F}, // M + {0x7F, 0x04, 0x08, 0x10, 0x7F}, // N + {0x3E, 0x41, 0x41, 0x41, 0x3E}, // O + {0x7F, 0x09, 0x09, 0x09, 0x06}, // P + {0x3E, 0x41, 0x51, 0x21, 0x5E}, // Q + {0x7F, 0x09, 0x19, 0x29, 0x46}, // R + {0x46, 0x49, 0x49, 0x49, 0x31}, // S + {0x01, 0x01, 0x7F, 0x01, 0x01}, // T + {0x3F, 0x40, 0x40, 0x40, 0x3F}, // U + {0x1F, 0x20, 0x40, 0x20, 0x1F}, // V + {0x7F, 0x20, 0x18, 0x20, 0x7F}, // W + {0x63, 0x14, 0x08, 0x14, 0x63}, // X + {0x03, 0x04, 0x78, 0x04, 0x03}, // Y + {0x61, 0x51, 0x49, 0x45, 0x43}, // Z + {0x00, 0x00, 0x7F, 0x41, 0x41}, // [ + {0x02, 0x04, 0x08, 0x10, 0x20}, // "\" + {0x41, 0x41, 0x7F, 0x00, 0x00}, // ] + {0x04, 0x02, 0x01, 0x02, 0x04}, // ^ + {0x40, 0x40, 0x40, 0x40, 0x40}, // _ + {0x00, 0x01, 0x02, 0x04, 0x00}, // ` + {0x20, 0x54, 0x54, 0x54, 0x78}, // a + {0x7F, 0x48, 0x44, 0x44, 0x38}, // b + {0x38, 0x44, 0x44, 0x44, 0x20}, // c + {0x38, 0x44, 0x44, 0x48, 0x7F}, // d + {0x38, 0x54, 0x54, 0x54, 0x18}, // e + {0x08, 0x7E, 0x09, 0x01, 0x02}, // f + {0x08, 0x14, 0x54, 0x54, 0x3C}, // g + {0x7F, 0x08, 0x04, 0x04, 0x78}, // h + {0x00, 0x44, 0x7D, 0x40, 0x00}, // i + {0x20, 0x40, 0x44, 0x3D, 0x00}, // j + {0x00, 0x7F, 0x10, 0x28, 0x44}, // k + {0x00, 0x41, 0x7F, 0x40, 0x00}, // l + {0x7C, 0x04, 0x18, 0x04, 0x78}, // m + {0x7C, 0x08, 0x04, 0x04, 0x78}, // n + {0x38, 0x44, 0x44, 0x44, 0x38}, // o + {0x7C, 0x14, 0x14, 0x14, 0x08}, // p + {0x08, 0x14, 0x14, 0x18, 0x7C}, // q + {0x7C, 0x08, 0x04, 0x04, 0x08}, // r + {0x48, 0x54, 0x54, 0x54, 0x20}, // s + {0x04, 0x3F, 0x44, 0x40, 0x20}, // t + {0x3C, 0x40, 0x40, 0x20, 0x7C}, // u + {0x1C, 0x20, 0x40, 0x20, 0x1C}, // v + {0x3C, 0x40, 0x30, 0x40, 0x3C}, // w + {0x44, 0x28, 0x10, 0x28, 0x44}, // x + {0x0C, 0x50, 0x50, 0x50, 0x3C}, // y + {0x44, 0x64, 0x54, 0x4C, 0x44}, // z + {0x00, 0x08, 0x36, 0x41, 0x00}, // { + {0x00, 0x00, 0x7F, 0x00, 0x00}, // | + {0x00, 0x41, 0x36, 0x08, 0x00}, // } + {0x08, 0x08, 0x2A, 0x1C, 0x08}, // -> + {0x08, 0x1C, 0x2A, 0x08, 0x08}, // <- +};