Add palette scale with min/max temp (seems a bit off),

change buttons to stock theme buttons,
add saving a shot as PNG
This commit is contained in:
Nicole Faerber 2021-01-17 16:55:19 +01:00
parent ee02eafe83
commit bd4ebe3c59
4 changed files with 311 additions and 101 deletions

View file

@ -26,3 +26,62 @@ unsigned char * cairo_image_surface_get_data (cairo_surface_t *surfac
get pointer to imag data for inspection _and_ manipulation 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;

View file

@ -34,6 +34,9 @@ extern unsigned char *color_palette;
#include <stdlib.h> #include <stdlib.h>
#include <libusb.h> #include <libusb.h>
#include <time.h> #include <time.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <assert.h>
#include <fcntl.h> #include <fcntl.h>
#include <math.h> #include <math.h>
@ -46,60 +49,6 @@ extern unsigned char *color_palette;
// #include "jpeglib.h" // #include "jpeglib.h"
// -- define v4l2 ---------------
// #include <linux/videodev2.h>
#include <sys/ioctl.h>
#include <string.h>
#include <fcntl.h>
#include <assert.h>
#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 VENDOR_ID 0x09cb
#define PRODUCT_ID 0x1996 #define PRODUCT_ID 0x1996
@ -108,6 +57,11 @@ int filecount=0;
struct timeval t1, t2; struct timeval t1, t2;
long long fps_t; long long fps_t;
double t_min = 0.0;
double t_max = 0.0;
double t_center = 0.0;
int FFC = 0; // detect FFC int FFC = 0; // detect FFC
// -- buffer for EP 0x85 chunks --------------- // -- 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 // 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 // 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 (y = 0; y < 120; ++y) {
for (x = 0; x < 160; ++x) { for (x = 0; x < 160; ++x) {
if (x<80) 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) if (v < min)
min = v; min = v;
if (v > max) { if (v > max) {
max = v; maxx = x; maxy = y; max = v; //maxx = x; maxy = y;
} }
rms += v * v; 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 st1[100];
char st2[100]; //char st2[100];
struct tm *loctime; //struct tm *loctime;
// Convert it to local time and Print it out in a nice format. // Convert it to local time and Print it out in a nice format.
loctime = localtime (&now1); //loctime = localtime (&now1);
strftime (st1, 60, "%H:%M:%S", loctime); //strftime (st1, 60, "%H:%M:%S", loctime);
// calc medium of 2x2 center pixels // 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; 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 t_min = raw2temperature(min);
strncpy(st2, st1, MAXC); 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 !! // write zero to string !!
st2[MAXC-1] = '\0'; //st2[MAXC-1] = '\0';
fprintf(stderr,"%s\r",st2); //fprintf(stderr,"%s\r",st2);
// font_write(fb_proc, 1, 120, st2); // font_write(fb_proc, 1, 120, st2);
// show crosshairs, remove if required // show crosshairs, remove if required
// font_write(fb_proc, 80-2, 60-3, "+"); // font_write(fb_proc, 80-2, 60-3, "+");
maxx -= 4; //maxx -= 4;
maxy -= 4; //maxy -= 4;
if (maxx < 0) //if (maxx < 0)
maxx = 0; // maxx = 0;
if (maxy < 0) //if (maxy < 0)
maxy = 0; // maxy = 0;
if (maxx > 150) //if (maxx > 150)
maxx = 150; // maxx = 150;
if (maxy > 110) //if (maxy > 110)
maxy = 110; // maxy = 110;
// font_write(fb_proc, 160-6, maxy, "<"); // font_write(fb_proc, 160-6, maxy, "<");
// font_write(fb_proc, maxx, 120-8, "|"); // 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] = 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)+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)+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 // copy whole 32bit words hor/vert
p1 = (unsigned int *)&fbdata[16*y * 640 + x*16]; p1 = (unsigned int *)&fbdata[16*y * 640 + x*16];

107
flirgtk.c
View file

@ -36,13 +36,17 @@ static cairo_surface_t *surface = NULL;
// internal frame buffer with 640x480 pixels of 4 byte each, // internal frame buffer with 640x480 pixels of 4 byte each,
// first byte unused, R, G, B 0x00RRGGBB // first byte unused, R, G, B 0x00RRGGBB
unsigned char fbuffer[640*480*4]; unsigned char fbuffer[640*500*4];
unsigned char *fbdata; unsigned char *fbdata;
unsigned char *color_palette; unsigned char *color_palette;
gboolean flir_run = FALSE; gboolean flir_run = FALSE;
gpointer cam_thread_main(gpointer user_data); gpointer cam_thread_main(gpointer user_data);
extern double t_min, t_max, t_center;
void draw_palette(void);
static gboolean static gboolean
configure_event (GtkWidget *widget, configure_event (GtkWidget *widget,
@ -56,16 +60,16 @@ int stride;
cairo_surface_destroy (surface); cairo_surface_destroy (surface);
gtk_widget_get_allocation (widget, &allocation); 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); stride = cairo_format_stride_for_width (CAIRO_FORMAT_RGB24, 640);
// g_printerr("stride %d\n", stride); // g_printerr("stride %d\n", stride);
surface = cairo_image_surface_create_for_data (fbuffer, surface = cairo_image_surface_create_for_data (fbuffer,
CAIRO_FORMAT_RGB24, CAIRO_FORMAT_RGB24,
640, 640,
480, 500,
stride); stride);
fbdata = cairo_image_surface_get_data(surface); fbdata = cairo_image_surface_get_data(surface);
draw_palette();
g_printerr("configure event %d x %d\n", allocation.width, allocation.height);
/* We've handled the configure event, no need for further processing. */ /* We've handled the configure event, no need for further processing. */
return TRUE; return TRUE;
@ -85,26 +89,48 @@ draw_event (GtkWidget *widget,
return FALSE; 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 void
update_fb(void) update_fb(void)
{ {
#if 0 char tstr[16];
unsigned int x,y;
unsigned int *pdata;
static unsigned char cnt=0;
cnt+=0x0f; // g_printerr("min %.1f center %.1f max %.1f\r", t_min, t_center, t_max);
// g_printerr("cnt=%d\n", cnt);
for (y=0; y<480; y++) { snprintf(tstr, 16, "%.1f", t_min);
for (x=0; x<640; x++) { font_write(fbdata, 140, 486, tstr);
pdata = (unsigned int *)&fbdata[(y*640*4)+(x*4)]; snprintf(tstr, 16, "%.1f", t_max);
*pdata = (cnt << 16) | (x << 9) | y; font_write(fbdata, 440, 486, tstr);
}
}
#endif
gtk_widget_queue_draw(image_darea); gtk_widget_queue_draw(image_darea);
} }
void
store_shot_clicked(GtkWidget *button, gpointer user_data)
{
cairo_surface_write_to_png (surface, "shot.png");
}
void void
start_clicked(GtkWidget *button, gpointer user_data) start_clicked(GtkWidget *button, gpointer user_data)
{ {
@ -134,6 +160,28 @@ handle_timeout (gpointer user_data)
return TRUE; 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 void
palette_changed (GtkComboBox *widget, gpointer user_data) palette_changed (GtkComboBox *widget, gpointer user_data)
{ {
@ -153,6 +201,7 @@ int act;
if (act == 7) color_palette = palette_Iron2; if (act == 7) color_palette = palette_Iron2;
if (act == 8) color_palette = palette_Iron_Black; if (act == 8) color_palette = palette_Iron_Black;
if (act == 9) color_palette = palette_Rainbow; if (act == 9) color_palette = palette_Rainbow;
draw_palette();
}; };
} }
@ -165,6 +214,9 @@ GtkWidget *hbox;
GtkWidget *w; GtkWidget *w;
// GtkWidget *da; // GtkWidget *da;
// default color palette
color_palette = palette_Rainbow;
if (!window) { if (!window) {
window = gtk_window_new (GTK_WINDOW_TOPLEVEL); window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "FLIR One"); gtk_window_set_title (GTK_WINDOW (window), "FLIR One");
@ -178,13 +230,19 @@ GtkWidget *w;
hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 4); hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 4);
gtk_container_add (GTK_CONTAINER (box), hbox); 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); gtk_container_add (GTK_CONTAINER (hbox), w);
g_signal_connect (w, "clicked", g_signal_connect (w, "clicked",
G_CALLBACK (start_clicked), NULL); 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); gtk_container_add (GTK_CONTAINER (hbox), w);
g_signal_connect (w, "clicked", 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_text_append (GTK_COMBO_BOX_TEXT(w), NULL, "Rainbow");
gtk_combo_box_set_active (GTK_COMBO_BOX(w), 9); gtk_combo_box_set_active (GTK_COMBO_BOX(w), 9);
gtk_container_add (GTK_CONTAINER (hbox), w); gtk_container_add (GTK_CONTAINER (hbox), w);
color_palette = palette_Rainbow;
g_signal_connect (w, "changed", g_signal_connect (w, "changed",
G_CALLBACK (palette_changed), NULL); G_CALLBACK (palette_changed), NULL);
image_darea = gtk_drawing_area_new (); image_darea = gtk_drawing_area_new ();
/* set a minimum size */ /* 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); gtk_container_add (GTK_CONTAINER (box), image_darea);
@ -219,6 +276,14 @@ GtkWidget *w;
g_signal_connect (image_darea,"configure-event", g_signal_connect (image_darea,"configure-event",
G_CALLBACK (configure_event), NULL); 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); // g_timeout_add_seconds(1, handle_timeout, NULL);
gtk_widget_show_all(window); gtk_widget_show_all(window);

128
font5x7.h Normal file
View file

@ -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}, // <-
};