Commit da77ed14ee19be9f3cf0fabe1eb1efb0085bcf04
authorMichel Pollet <buserror@gmail.com>
Mon, 21 Feb 2011 18:05:44 +0000 (18:05 +0000)
committerMichel Pollet <buserror@gmail.com>
Mon, 21 Feb 2011 18:05:44 +0000 (18:05 +0000)
Emulated a complete HD44780 LCd screen, and uses a standard
AVR driver to write on it.

Signed-off-by: Michel Pollet <buserror@gmail.com>
31 files changed:
examples/board_charlcd/Makefile [deleted file]
examples/board_charlcd/ac_input.c [deleted file]
examples/board_charlcd/ac_input.h [deleted file]
examples/board_charlcd/atmega48_charlcd.c [deleted file]
examples/board_charlcd/atmega48_lcd.c [deleted file]
examples/board_charlcd/atmega48_lcd.h [deleted file]
examples/board_charlcd/charlcd.c [deleted file]
examples/board_charlcd/data/blu.tiff [deleted file]
examples/board_charlcd/data/processblu.py [deleted file]
examples/board_charlcd/font.tiff [deleted file]
examples/board_charlcd/hd44780.c [deleted file]
examples/board_charlcd/hd44780.h [deleted file]
examples/board_charlcd/hd44780_glut.c [deleted file]
examples/board_charlcd/hd44780_glut.h [deleted file]
examples/board_hd77480/Makefile [new file with mode: 0644]
examples/board_hd77480/README [new file with mode: 0644]
examples/board_hd77480/atmega48_charlcd.c [new file with mode: 0644]
examples/board_hd77480/avr_hd44780.c [new file with mode: 0644]
examples/board_hd77480/avr_hd44780.h [new file with mode: 0644]
examples/board_hd77480/avr_hd44780_conf.h [new file with mode: 0644]
examples/board_hd77480/charlcd.c [new file with mode: 0644]
examples/board_hd77480/data/blu.tiff [new file with mode: 0644]
examples/board_hd77480/data/font.tiff [new file with mode: 0644]
examples/board_hd77480/data/processblu.py [new file with mode: 0644]
examples/board_hd77480/font.h [new file with mode: 0644]
examples/parts/ac_input.c [new file with mode: 0644]
examples/parts/ac_input.h [new file with mode: 0644]
examples/parts/hd44780.c [new file with mode: 0644]
examples/parts/hd44780.h [new file with mode: 0644]
examples/parts/hd44780_glut.c [new file with mode: 0644]
examples/parts/hd44780_glut.h [new file with mode: 0644]

diff --git a/examples/board_charlcd/Makefile b/examples/board_charlcd/Makefile
deleted file mode 100644 (file)
index 8da9583..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-# 
-#      Copyright 2008, 2009 Michel Pollet <buserror@gmail.com>
-#
-#      This file is part of simavr.
-#
-#      simavr is free software: you can redistribute it and/or modify
-#      it under the terms of the GNU General Public License as published by
-#      the Free Software Foundation, either version 3 of the License, or
-#      (at your option) any later version.
-#
-#      simavr is distributed in the hope that it will be useful,
-#      but WITHOUT ANY WARRANTY; without even the implied warranty of
-#      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#      GNU General Public License for more details.
-#
-#      You should have received a copy of the GNU General Public License
-#      along with simavr.  If not, see <http://www.gnu.org/licenses/>.
-
-board= charlcd
-firm_src = ${wildcard at*${board}.c}
-firmware = ${firm_src:.c=.axf}
-simavr = ../../
-
-SHELL   = /bin/bash
-
-IPATH = .
-IPATH += ../parts
-IPATH += ${simavr}/include
-IPATH += ${simavr}/simavr/sim
-
-VPATH = .
-VPATH += ../parts
-
-LDFLAGS += -lpthread
-LDFLAGS += -lGLU
-LDFLAGS += -lGL
-LDFLAGS += `sdl-config --libs`
-LDFLAGS += -lSDL_image
-
-CFLAGS = `sdl-config --cflags`
-#ifneq (${shell uname}, Darwin)
-#else
-#LDFLAGS += -framework GLUT -framework OpenGL 
-#endif
-all: obj atmega48_charlcd.axf ${board} 
-
-atmega48_charlcd.axf: atmega48_charlcd.c atmega48_lcd.c atmega48_lcd.h
-       @echo AVR-CC ${<}
-       ${AVR}gcc -Wall -gdwarf-2 -Os -std=gnu99 \
-                       -mmcu=atmega48 \
-                       -DF_CPU=8000000 \
-                       -fno-inline-small-functions \
-                       -ffunction-sections -fdata-sections \
-                       -Wl,--relax,--gc-sections \
-                       -Wl,--undefined=_mmcu,--section-start=.mmcu=0x910000 \
-                       -I../include -I../../include \
-                       atmega48_charlcd.c atmega48_lcd.c -o atmega48_charlcd.axf
-       @${AVR}size ${@}|sed '1d'
-
-include ${simavr}/Makefile.common
-
-${board} : ${OBJ}/ac_input.o
-${board} : ${OBJ}/hd44780.o
-${board} : ${OBJ}/hd44780_glut.o
-${board} : ${OBJ}/${board}.o
-       @echo LD $@
-       @gcc -MD ${CFLAGS}  ${LFLAGS} -o $@ $^ $(LDFLAGS) ${simavr}/simavr/libsimavr.a
-
-clean:
-       rm -rf obj *.hex *.a *.axf ${board} *.vcd .*.swo .*.swp .*.swm .*.swn
diff --git a/examples/board_charlcd/ac_input.c b/examples/board_charlcd/ac_input.c
deleted file mode 100644 (file)
index 29447f5..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-
-#include "sim_avr.h"
-#include "ac_input.h"
-#include "stdio.h"
-
-static avr_cycle_count_t switch_auto( struct avr_t * avr, avr_cycle_count_t when, void * param){
-    ac_input_t * b = (ac_input_t *)param;
-    b->value = b->value == 0 ? 1 : 0;
-    avr_raise_irq( b->irq + IRQ_AC_OUT, b->value );
-    return when + avr_usec_to_cycles(avr,10000);
-}
-
-void ac_input_init(struct avr_t *avr, ac_input_t *b){
-    b->irq = avr_alloc_irq(0,IRQ_AC_COUNT);
-    b->avr = avr;
-    b->value = 0;
-    avr_cycle_timer_register_usec(avr, 10000, switch_auto, b);
-}
diff --git a/examples/board_charlcd/ac_input.h b/examples/board_charlcd/ac_input.h
deleted file mode 100644 (file)
index 07c2c4b..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef __AC_INPUT_H__
-#define __AC_INPUT_H__
-
-#include "sim_irq.h"
-
-/*
- * Simulates a 50hz changing signal
- */
-
-enum {
-    IRQ_AC_OUT = 0,
-    IRQ_AC_COUNT
-};
-
-typedef struct ac_input_t {
-    avr_irq_t * irq;
-    struct avr_t * avr;
-    uint8_t value;
-} ac_input_t;
-
-void ac_input_init(struct avr_t * avr, ac_input_t * b);
-
-#endif
diff --git a/examples/board_charlcd/atmega48_charlcd.c b/examples/board_charlcd/atmega48_charlcd.c
deleted file mode 100644 (file)
index 993190a..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-#include <avr/io.h>
-#include <avr/interrupt.h>
-#include <util/delay.h>
-#include "stdlib.h"
-#include "string.h"
-
-#include "atmega48_lcd.h"
-
-#include "avr_mcu_section.h"
-AVR_MCU(F_CPU, "atmega48");
-
-static uint8_t subsecct = 0;
-static uint8_t hour = 0;
-static uint8_t minute = 0;
-static uint8_t second = 0;
-static volatile uint8_t update_needed = 0;
-
-ISR( INT0_vect ){
-    /* External interrupt on pin D2 */
-    subsecct++;
-    if( subsecct == 50 ){
-        second++;
-        update_needed = 1;
-        if(second ==60){
-            minute++;
-            second = 0;
-            if(minute==60){
-                minute =0;
-                hour++;
-                if(hour==24) hour =0;
-            }
-        }
-    }
-}
-
-int main(){
-    lcd_init();
-   
-
-    EICRA = (1<<ISC00);
-    EIMSK = (1<<INT0);
-    sei();
-
-    while(1)
-    {
-          while(!update_needed);
-          update_needed = 0;
-          char buffer[16];
-          lcd_clear();
-          set_cursor(4,1);
-          itoa(hour,buffer,10);
-          lcd_string(buffer);
-          lcd_data(':');
-          itoa(minute,buffer,10);
-          lcd_string(buffer);
-          lcd_data(':');
-          itoa(second,buffer,10);
-          lcd_string(buffer);
-    }
-
-}
diff --git a/examples/board_charlcd/atmega48_lcd.c b/examples/board_charlcd/atmega48_lcd.c
deleted file mode 100644 (file)
index 9822188..0000000
+++ /dev/null
@@ -1,146 +0,0 @@
-// Ansteuerung eines HD44780 kompatiblen LCD im 4-Bit-Interfacemodus\r
-// http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/LCD-Ansteuerung\r
-//\r
-// Die Pinbelegung ist über defines in lcd-routines.h einstellbar\r
\r
-#include <avr/io.h>\r
-#include "atmega48_lcd.h"\r
-#include <util/delay.h>\r
\r
-// sendet ein Datenbyte an das LCD\r
\r
-void lcd_data(unsigned char temp1)\r
-{\r
-   unsigned char temp2 = temp1;\r
\r
-   LCD_PORT |= (1<<LCD_RS);        // RS auf 1 setzen\r
\r
-   temp1 = temp1 >> 4;\r
-   temp1 = temp1 & 0x0F;\r
-   LCD_PORT &= 0xF0;\r
-   LCD_PORT |= temp1;               // setzen\r
-   lcd_enable();\r
\r
-   temp2 = temp2 & 0x0F;\r
-   LCD_PORT &= 0xF0;\r
-   LCD_PORT |= temp2;               // setzen\r
-   lcd_enable();\r
-   \r
-   _delay_us(42);\r
-}\r
\r
-// sendet einen Befehl an das LCD\r
\r
-void lcd_command(unsigned char temp1)\r
-{\r
-   unsigned char temp2 = temp1;\r
\r
-   LCD_PORT &= ~(1<<LCD_RS);        // RS auf 0 setzen\r
\r
-   temp1 = temp1 >> 4;              // oberes Nibble holen\r
-   temp1 = temp1 & 0x0F;            // maskieren\r
-   LCD_PORT &= 0xF0;\r
-   LCD_PORT |= temp1;               // setzen\r
-   lcd_enable();\r
\r
-   temp2 = temp2 & 0x0F;            // unteres Nibble holen und maskieren\r
-   LCD_PORT &= 0xF0;\r
-   LCD_PORT |= temp2;               // setzen\r
-   lcd_enable();\r
-   \r
-   _delay_us(42);\r
-}\r
\r
-// erzeugt den Enable-Puls\r
-void lcd_enable(void)\r
-{\r
-   // Bei Problemen ggf. Pause gemäß Datenblatt des LCD Controllers einfügen\r
-   // http://www.mikrocontroller.net/topic/81974#685882\r
-   LCD_PORT |= (1<<LCD_EN);\r
-    _delay_us(1);                   // kurze Pause\r
-   // Bei Problemen ggf. Pause gemäß Datenblatt des LCD Controllers verlängern\r
-   // http://www.mikrocontroller.net/topic/80900\r
-   LCD_PORT &= ~(1<<LCD_EN);\r
-}\r
\r
-// Initialisierung: \r
-// Muss ganz am Anfang des Programms aufgerufen werden.\r
\r
-void lcd_init(void)\r
-{\r
-   LCD_DDR = LCD_DDR | 0x0F | (1<<LCD_RS) | (1<<LCD_EN);   // Port auf Ausgang schalten\r
\r
-   // muss 3mal hintereinander gesendet werden zur Initialisierung\r
\r
-   _delay_ms(15);\r
-   LCD_PORT &= 0xF0;\r
-   LCD_PORT |= 0x03;            \r
-   LCD_PORT &= ~(1<<LCD_RS);      // RS auf 0\r
-   lcd_enable();\r
\r
-   _delay_ms(5);\r
-   lcd_enable();\r
\r
-   _delay_ms(1);\r
-   lcd_enable();\r
-   _delay_ms(1);\r
\r
-   // 4 Bit Modus aktivieren \r
-   LCD_PORT &= 0xF0;\r
-   LCD_PORT |= 0x02;\r
-   lcd_enable();\r
-   _delay_ms(1);\r
\r
-   // 4Bit / 2 Zeilen / 5x7\r
-   lcd_command(0x28);\r
-    \r
-   // Display ein / Cursor aus / kein Blinken\r
-   lcd_command(0x0C); \r
\r
-   // inkrement / kein Scrollen\r
-   lcd_command(0x06);\r
\r
-   lcd_clear();\r
-}\r
\r
-// Sendet den Befehl zur Löschung des Displays\r
\r
-void lcd_clear(void)\r
-{\r
-   lcd_command(CLEAR_DISPLAY);\r
-   _delay_ms(5);\r
-}\r
\r
-// Sendet den Befehl: Cursor Home\r
\r
-void lcd_home(void)\r
-{\r
-   lcd_command(CURSOR_HOME);\r
-   _delay_ms(5);\r
-}\r
\r
-// setzt den Cursor in Zeile y (1..4) Spalte x (0..15)\r
\r
-void set_cursor(uint8_t x, uint8_t y)\r
-{\r
-  uint8_t tmp;\r
\r
-  switch (y) {\r
-    case 1: tmp=0x80+0x00+x; break;    // 1. Zeile\r
-    case 2: tmp=0x80+0x40+x; break;    // 2. Zeile\r
-    case 3: tmp=0x80+0x10+x; break;    // 3. Zeile\r
-    case 4: tmp=0x80+0x50+x; break;    // 4. Zeile\r
-    default: return;                   // für den Fall einer falschen Zeile\r
-  }\r
-  lcd_command(tmp);\r
-}\r
\r
-// Schreibt einen String auf das LCD\r
\r
-void lcd_string(char *data)\r
-{\r
-    while(*data) {\r
-        lcd_data(*data);\r
-        data++;\r
-    }\r
-}\r
diff --git a/examples/board_charlcd/atmega48_lcd.h b/examples/board_charlcd/atmega48_lcd.h
deleted file mode 100644 (file)
index ebb6909..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-#ifndef LCD_H\r
-#define LCD_H\r
-\r
-// Ansteuerung eines HD44780 kompatiblen LCD im 4-Bit-Interfacemodus\r
-// http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/LCD-Ansteuerung\r
-//\r
-void lcd_data(unsigned char temp1);\r
-void lcd_string(char *data);\r
-void lcd_command(unsigned char temp1);\r
-void lcd_enable(void);\r
-void lcd_init(void);\r
-void lcd_home(void);\r
-void lcd_clear(void);\r
-void set_cursor(uint8_t x, uint8_t y);\r
\r
-// Hier die verwendete Taktfrequenz in Hz eintragen, wichtig!\r
\r
-#define F_CPU 8000000\r
\r
-// LCD Befehle\r
\r
-#define CLEAR_DISPLAY 0x01\r
-#define CURSOR_HOME   0x02\r
\r
-// Pinbelegung für das LCD, an verwendete Pins anpassen\r
\r
-#define LCD_PORT      PORTB\r
-#define LCD_DDR       DDRB\r
-#define LCD_RS        PB4\r
-#define LCD_EN        PB5\r
-// DB4 bis DB7 des LCD sind mit PD0 bis PD3 des AVR verbunden\r
-\r
-#endif //LCD_H\r
diff --git a/examples/board_charlcd/charlcd.c b/examples/board_charlcd/charlcd.c
deleted file mode 100644 (file)
index 3692754..0000000
+++ /dev/null
@@ -1,228 +0,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-#include <libgen.h>
-
-#include "sim_avr.h"
-#include "avr_ioport.h"
-#include "sim_elf.h"
-#include "sim_gdb.h"
-#include "sim_vcd_file.h"
-
-#include <GL/gl.h>
-#include <GL/glu.h>
-#include <pthread.h>
-
-#include "SDL.h"
-#include "SDL_image.h"
-
-#include "ac_input.h"
-#include "hd44780.h"
-#include "hd44780_glut.h"
-
-/* screen width, height, and bit depth */
-#define SCREEN_WIDTH  800
-#define SCREEN_HEIGHT 600
-#define SCREEN_BPP     16
-
-int window;
-avr_t * avr = NULL;
-avr_vcd_t vcd_file;
-ac_input_t ac_input;
-hd44780_t hd44780;
-
-SDL_Surface *surface;
-
-static void * avr_run_thread( ){
-    while(1){
-        avr_run(avr);
-    }
-}
-
-void Quit( int returnCode )
-{
-    SDL_Quit( );
-    exit( returnCode );
-}
-
-int resizeWindow( int width, int height )
-{
-    if ( height == 0 ) height = 1;
-    glViewport( 0, 0, ( GLsizei )width, ( GLsizei )height );
-    glMatrixMode( GL_PROJECTION );
-    glLoadIdentity( );
-       glOrtho(0, 800, 0, 600, 0, 10);
-
-    glMatrixMode( GL_MODELVIEW );
-    glLoadIdentity( );
-
-    return 1;
-}
-
-void handleKeyPress( SDL_keysym *keysym )
-{
-    switch ( keysym->sym )
-       {
-       case SDLK_ESCAPE:
-           Quit( 0 );
-           break;
-       case SDLK_F1:
-           SDL_WM_ToggleFullScreen( surface );
-           break;
-       default:
-           break;
-       }
-}
-
-int initGL( GLvoid )
-{
-    glEnable( GL_TEXTURE_2D );
-    glShadeModel( GL_SMOOTH );
-
-    glClearColor( 0.8f, 0.8f, 0.8f, 1.0f );
-    glColor4f( 1.0f,1.0f,1.0f,1.0f);
-    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
-    glEnable( GL_BLEND);
-
-    glClearDepth( 1.0f );
-
-    glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
-
-    hd44780_gl_init();
-
-    return 1;
-}
-
-int drawGLScene( GLvoid )
-{
-    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
-       glMatrixMode(GL_MODELVIEW); // Select modelview matrix
-    glPushMatrix();
-       glLoadIdentity(); // Start with an identity matrix
-    glScalef(3,3,1);
-    glTranslatef( 89.66f,150,0);
-    hd44780_gl_draw( &hd44780 );
-    glPopMatrix();
-    SDL_GL_SwapBuffers();
-    return 1;
-}
-
-
-int main(int argc, char *argv[])
-{
-       elf_firmware_t f;
-       const char * fname =  "atmega48_charlcd.axf";
-       char path[256];
-       sprintf(path, "%s/%s", dirname(argv[0]), fname);
-       printf("Firmware pathname is %s\n", path);
-       elf_read_firmware(path, &f);
-
-       printf("firmware %s f=%d mmcu=%s\n", fname, (int)f.frequency, f.mmcu);
-
-       avr = avr_make_mcu_by_name(f.mmcu);
-       if (!avr) {
-               fprintf(stderr, "%s: AVR '%s' now known\n", argv[0], f.mmcu);
-               exit(1);
-       }
-
-    avr_init(avr);
-    avr_load_firmware(avr,&f);
-    ac_input_init(avr, &ac_input);
-    avr_connect_irq(
-        ac_input.irq + IRQ_AC_OUT,
-        avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('D'),2));
-
-    hd44780_init(avr, &hd44780);
-/*    hd44780_print2x16(&hd44780); */
-
-    /* Connect Data Lines to Port B, 0-3 */
-    for( int i =0; i<4;i++){ 
-        avr_irq_register_notify(
-            avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('B'), i),
-            hd44780_data_changed_hook,
-            &hd44780);
-    }
-    /* Connect Cmd Lines */
-    for( int i =4; i<7;i++){ 
-        avr_irq_register_notify(
-            avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('B'), i),
-            hd44780_cmd_changed_hook,
-            &hd44780);
-    }
-
-       avr_vcd_init(avr, "gtkwave_output.vcd", &vcd_file, 100 /* usec */);
-       avr_vcd_add_signal(&vcd_file, 
-               avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('B'), IOPORT_IRQ_PIN_ALL), 8 /* bits */ ,
-               "portb" );
-
-    avr_vcd_add_signal(&vcd_file,
-        ac_input.irq + IRQ_AC_OUT, 1, "ac_input");
-
-    avr_vcd_start(&vcd_file);
-
-    //avr_gdb_init(avr);
-    //avr->state = cpu_Stopped;
-
-
-    avr_vcd_stop(&vcd_file);
-
-
-    if ( SDL_Init( SDL_INIT_VIDEO ) < 0 ) {
-           fprintf( stderr, "Video initialization failed: %s\n",SDL_GetError( ) );
-           Quit( 1 );
-       }
-    int done =0, isActive=1;
-    SDL_Event event;
-    int videoFlags = SDL_OPENGL | SDL_GL_DOUBLEBUFFER | SDL_HWPALETTE | SDL_RESIZABLE | SDL_HWSURFACE | SDL_HWACCEL;
-    SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
-    surface = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, videoFlags );
-    SDL_WM_SetCaption("HD44780 Simulation","");
-    if( !surface ) {
-        fprintf( stderr,  "Video mode set failed: %s\n", SDL_GetError( ) );
-           Quit( 1 );
-       }
-    initGL( );
-    resizeWindow( SCREEN_WIDTH, SCREEN_HEIGHT);
-
-    pthread_t run;
-    pthread_create(&run, NULL, avr_run_thread, NULL);
-
-    while(!done){
-           while ( SDL_PollEvent( &event ) )
-               {
-                   switch( event.type )
-                       {
-                       case SDL_ACTIVEEVENT:
-                           if ( event.active.gain == 0 )
-                               isActive = 0;
-                           else
-                               isActive = 1;
-                           break;                          
-                       case SDL_VIDEORESIZE:
-                           /* handle resize event */
-                           surface = SDL_SetVideoMode( event.resize.w,
-                                                       event.resize.h,
-                                                       16, videoFlags );
-                           if ( !surface )
-                               {
-                                   fprintf( stderr, "Could not get a surface after resize: %s\n", SDL_GetError( ) );
-                                   Quit( 1 );
-                               }
-                           resizeWindow( event.resize.w, event.resize.h );
-                           break;
-                       case SDL_KEYDOWN:
-                           /* handle key presses */
-                           handleKeyPress( &event.key.keysym );
-                           break;
-                       case SDL_QUIT:
-                           /* handle quit requests */
-                           done = 1;
-                           break;
-                       default:
-                           break;
-                       }
-               }
-        drawGLScene();
-    }
-    return 0;
-
-}
diff --git a/examples/board_charlcd/data/blu.tiff b/examples/board_charlcd/data/blu.tiff
deleted file mode 100644 (file)
index 0db74e2..0000000
Binary files a/examples/board_charlcd/data/blu.tiff and /dev/null differ
diff --git a/examples/board_charlcd/data/processblu.py b/examples/board_charlcd/data/processblu.py
deleted file mode 100644 (file)
index 17f89f6..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-import Image,struct
-img = Image.open('blu.tiff')
-
-class CharData(object):
-    def __init__(self, data):
-        if data is None:
-            self.data = [ [] for y in range(7) ]
-        else:
-            self.data = data
-
-    def concat( self, other ):
-        for y in range(7):
-            self.data[y] += other.data[y]
-
-    def get_bindata(self):
-        ll = len(self.data[0])
-        ret=''
-        for y in reversed(range(7)):
-            for x in self.data[y]:
-                ret += struct.pack('BBBB',*x)
-        return ret
-            
-
-    def save_as(self, name):
-        height = 7
-        width = len(self.data[0])
-        outimg = Image.frombuffer( "RGBA", (width, height),
-            self.get_bindata())
-        outimg.save(name)
-            
-
-def char_at(char_x,char_y):
-    """
-    char_x specifies, zero based, the x position of the character
-    """
-    start_x = 1+char_x+ 14*char_x+2
-    start_y = 1+char_y*22+1
-    print "Starting at %i,%i" %( start_x,start_y)
-    return CharData([[ img.getpixel( (start_x+2*x,start_y+2*y) ) for x in range(5)] for y in range(7)])
-
-
-chardata = CharData(None)
-for x in range(16): #0x00 - 0x0F
-    chardata.concat( char_at(0,x) )
-for x in range(16): #0x10 - 0x1F
-    chardata.concat( char_at(0,x) )
-for x in range(16): #0x20 - 0x2F
-    chardata.concat( char_at(1,x) )
-for x in range(16): #0x30 - 0x3F
-    chardata.concat( char_at(2,x) )
-for x in range(16): #0x40 - 0x4F
-    chardata.concat( char_at(3,x) )
-for x in range(16): #0x50 - 0x5F
-    chardata.concat( char_at(4,x) )
-for x in range(16): #0x60 - 0x6F
-    chardata.concat( char_at(5,x) )
-for x in range(16): #0x70 - 0x7F
-    chardata.concat( char_at(6,x) )
-for x in range(16): #0x80 - 0x8F
-    chardata.concat( char_at(0,x) )
-for x in range(16): #0x90 - 0x9F
-    chardata.concat( char_at(0,x) )
-for x in range(16): #0xA0 - 0xAF
-    chardata.concat( char_at(7,x) )
-for x in range(16): #0xB0 - 0xBF
-    chardata.concat( char_at(8,x) )
-for x in range(16): #0xC0 - 0xCF
-    chardata.concat( char_at(9,x) )
-for x in range(16): #0xD0 - 0xDF
-    chardata.concat( char_at(10,x) )
-for x in range(16): #0xE0 - 0xEF
-    chardata.concat( char_at(11,x) )
-for x in range(16): #0xF0 - 0xFF
-    chardata.concat( char_at(12,x) )
-print chardata.save_as('7x5font.tiff')
diff --git a/examples/board_charlcd/font.tiff b/examples/board_charlcd/font.tiff
deleted file mode 100644 (file)
index d5a146e..0000000
Binary files a/examples/board_charlcd/font.tiff and /dev/null differ
diff --git a/examples/board_charlcd/hd44780.c b/examples/board_charlcd/hd44780.c
deleted file mode 100644 (file)
index 46178e8..0000000
+++ /dev/null
@@ -1,185 +0,0 @@
-#include "hd44780.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdarg.h>
-
-void debug_print( const char* format, ... ) {
-
-    va_list args;
-    va_start( args, format );
-    #ifdef HD44780_DEBUG
-    vprintf( format, args );
-    #endif
-    va_end( args );
-}
-
-int check_flag( hd44780_t *b, int flag){
-    return (b->flags>>flag)&1;
-}
-
-void reset_cursor( hd44780_t *b){
-    b->cursor = b->ddram;
-}
-
-void clear_screen( hd44780_t *b){
-    memset(b->ddram,' ',80);
-}
-
-void handle_function_8bit( hd44780_t *b, int realportstate ){
-    debug_print("handle_function_8bit  realportstate 0x%x\n",realportstate);
-    /*
-    if( realportstate == 0x22){
-        debug_print("Activating 4Bit Mode\n");
-        b->mode_4bit = 1;
-    }
-    */
-    if( realportstate == 1) {
-        clear_screen(b);
-        debug_print("Clear Screen\n");
-    }
-    if( realportstate >> 1 == 1) {
-        debug_print("Move Cursor to startpos\n");
-        reset_cursor(b);
-    }
-    if( realportstate >> 2 == 1) {
-        debug_print("Setting I/S mode\n");
-        b->flags &= ~(3<<HD44780_FLAG_S); //Clear S, I/D bits
-        b->flags |= (realportstate & 3)<<HD44780_FLAG_S;
-    }
-    if( realportstate >> 3 == 1) {
-        debug_print("Setting Display/Cursor Mode\n");
-        b->flags &= ~(7<<HD44780_FLAG_B); //Clear B,C,D bits
-        b->flags |= realportstate&7 << HD44780_FLAG_B; // Set B,C,D bits
-    }
-    if( realportstate >> 4 == 1) {
-        debug_print("Moving Display/Cursor Mode\n");
-        b->flags &= ~(3<<HD44780_FLAG_R_L); //Clear R/L,S/C
-        b->flags |= (realportstate & 3)<<HD44780_FLAG_R_L;
-    }
-    if( realportstate >> 5 == 1) {
-        debug_print("Functions\n");
-        b->flags &= ~(7<<HD44780_FLAG_F); //Clear F,N,DL bits
-        b->flags |= (realportstate>>2)&7 << HD44780_FLAG_F; // Set F,N,DL bits
-        if( !check_flag(b, HD44780_FLAG_D_L) ){
-            debug_print("Enabling 4Bit Mode\n");
-            b->mode_4bit = 1;  
-        }
-    }
-    if( realportstate >> 6 == 1) printf("Set CGRAM Address\n");
-    if( realportstate >> 7 == 1) {
-        debug_print("Set DDRAM Address\n");
-        b->cursor = b->ddram + (realportstate & 0x7f);
-    }
-    debug_print("Flags are 0x%x\n",b->flags);
-}
-
-void handle_data_8bit( hd44780_t *b, int realportstate ){
-    /* printf("handle_data_8bit realportstate 0x%x\n",realportstate); */
-    *(b->cursor) = realportstate & 0xff;
-    if( !check_flag(b, HD44780_FLAG_S_C) ){
-        // Move Cursor
-        if( check_flag(b, HD44780_FLAG_I_D) ){
-            b->cursor++;
-        }
-        else{
-            b->cursor--;
-        }
-    }
-    else {
-        printf("!! NOT IMPLEMENTED\n");
-        // Move Display
-        if( check_flag(b, HD44780_FLAG_R_L) ){
-            //Move right
-            
-        }
-        else {
-            // Move left
-        }
-    }
-    if( b->cursor < b->ddram || b->cursor > b->ddram+80){
-        debug_print("Cursor out of range!\n");
-        reset_cursor(b);
-    }
-    #ifdef HD44780_DEBUG
-    hd44780_print2x16( b );
-    #endif 
-}
-
-void hd44780_init( struct avr_t *avr, struct hd44780_t * b) {
-    b->irq = avr_alloc_irq(0,IRQ_HD44780_COUNT);
-    b->portstate = 0x00;
-    b->mode_4bit = 0;
-    b->four_bit_cache = 0;
-    b->inits_recv = 0;
-    b->flags = 0;
-    reset_cursor(b);
-    clear_screen(b);
-}
-
-void hd44780_print2x16( struct hd44780_t *b){
-    printf("/******************\\\n| ");
-    fwrite( b->ddram, 1, 16, stdout);
-    printf(" |\n| ");
-//    fputc('\n',stdout);
-    fwrite( b->ddram + 0x40, 1, 16, stdout);
-    printf(" |\n\\******************/\n");
-}
-
-void hd44780_data_changed_hook( struct avr_irq_t * irq, uint32_t value, void *param){
-    hd44780_t *b = (hd44780_t *)param;
-    int datapos = -1;
-    if( irq->irq == DATA_PIN_0) datapos = 0;
-    if( irq->irq == DATA_PIN_1) datapos = 1;
-    if( irq->irq == DATA_PIN_2) datapos = 2;
-    if( irq->irq == DATA_PIN_3) datapos = 3;
-    if( irq->irq == DATA_PIN_4) datapos = 4;
-    if( irq->irq == DATA_PIN_5) datapos = 5;
-    if( irq->irq == DATA_PIN_6) datapos = 6;
-    if( irq->irq == DATA_PIN_7) datapos = 7;
-    if( datapos >= 0){
-        if( value == 1) b->portstate |= 1<<datapos;
-        else b->portstate &= ~(1<<datapos);
-    }
-}
-
-
-void hd44780_cmd_changed_hook( struct avr_irq_t * irq, uint32_t value, void *param){
-    hd44780_t *b = (hd44780_t *)param;
-    if( irq->irq == RS_PIN){
-        b->rs=value;
-    }
-    if( irq->irq == RW_PIN){
-        b->rw=value;
-    }
-    if( irq->irq == ENABLE_PIN && value == 0){
-        debug_print("enable pulse! portstate 0x%x\n", b->portstate);
-        if( b->inits_recv < 3 ){
-            if( b->portstate == 0x30 ){
-                debug_print("Init received\n");
-                b->inits_recv++;
-            }
-            else debug_print("Uuups, received command before fully initialized?\n");
-        }
-        else {
-            int realportstate=0;
-            int received = 1;
-            if( b->mode_4bit == 1) b->four_bit_cache = b->portstate, b->mode_4bit++,received=0;
-            else if( b->mode_4bit == 2) {
-                realportstate = (b->four_bit_cache&0xf0) | (b->portstate&0xf0)>>4;
-                b->mode_4bit=1;
-            }
-            else realportstate = b->portstate;
-            debug_print("four bit cache is 0x%x\n",b->four_bit_cache);
-
-            if(received){
-                if( !b->rs ) handle_function_8bit( b, realportstate );
-                else handle_data_8bit( b, realportstate );
-            }
-        }
-    }
-//    printf("pin %i is now %i, portstate 0x%x\n", irq->irq, value, b->portstate);
-}
-
-
-
diff --git a/examples/board_charlcd/hd44780.h b/examples/board_charlcd/hd44780.h
deleted file mode 100644 (file)
index 4b4ce12..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-#ifndef __HD44780_H__
-#define __HD44780_H__
-
-#include "sim_irq.h"
-
-/******************
- * Simulates a HD44780 controlled character LED.
- * All the Data Pins have to be on the same Port.
- * All the Cmd Pins have to be on the same Port. In 4 Bit mode,
- * they can share one Port.
- * For output of the display contents, use hd44780_print2x16 or a opengl function.
- ******************/
-
-#define ENABLE_PIN 5
-#define RW_PIN 6
-#define RS_PIN 4
-/* Use -1 for not connected */
-#define DATA_PIN_0 -1
-#define DATA_PIN_1 -1
-#define DATA_PIN_2 -1
-#define DATA_PIN_3 -1
-#define DATA_PIN_4 0
-#define DATA_PIN_5 1
-#define DATA_PIN_6 2
-#define DATA_PIN_7 3
-
-/* #define HD44780_DEBUG */
-
-enum {
-    HD44780_FLAG_F = 0,         //5x7 Font, 5x10 Font
-    HD44780_FLAG_N,             //1-zeiliges Display, 2/4-zeiliges Display
-    HD44780_FLAG_D_L,           //4-Bit Interface, 8-Bit Interface
-    HD44780_FLAG_R_L,           // Nach links schieben,Nach rechts schieben
-    HD44780_FLAG_S_C,           //Cursor bewegen, Displayinhalt schieben
-    HD44780_FLAG_B,             //Cursor blinkt nicht, Cursor blinkt
-    HD44780_FLAG_C,             //Cursor aus,Cursor an
-    HD44780_FLAG_D,             //Display aus,Display an
-    HD44780_FLAG_S,             //Displayinhalt fest, Displayinhalt weiterschieben
-    HD44780_FLAG_I_D 
-};
-
-enum {
-    IRQ_HD44780_IN = 0,
-    IRQ_HD44780_COUNT
-};
-
-
-typedef struct hd44780_t {
-    avr_irq_t * irq;
-    struct avr_t * avr;
-    char *cursor;
-    char ddram[80];
-    char cgram[64];
-    uint32_t rw;            /* R/W pin */
-    uint32_t rs;            /* RS pin */
-    int portstate;
-    char mode_4bit;     /* 0=disabled, 1=waitingforfirstnibble, 2=waitingforsecondnibble */
-    uint32_t flags;
-    int four_bit_cache;
-    char inits_recv;    /* num of init sequences received */
-} hd44780_t;
-
-void hd44780_init( struct avr_t *avr, struct hd44780_t * b);
-void hd44780_print2x16( struct hd44780_t *b);
-
-void hd44780_data_changed_hook( struct avr_irq_t * irq, uint32_t value, void *param);
-void hd44780_cmd_changed_hook( struct avr_irq_t * irq, uint32_t value, void *param);
-
-#endif 
diff --git a/examples/board_charlcd/hd44780_glut.c b/examples/board_charlcd/hd44780_glut.c
deleted file mode 100644 (file)
index 4f9dee8..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-#include "hd44780_glut.h"
-
-#include "SDL.h"
-#include "SDL_image.h"
-#include <GL/gl.h>
-#include <GL/glu.h>
-
-static GLuint font_texture;
-static int charwidth = 5;
-static int charheight = 7;
-
-void hd44780_gl_init(){
-    SDL_Surface *image;
-    image = IMG_Load("font.tiff");
-    if( !image) {
-        printf("Problem loading texture\n");
-        return;
-    }
-    glGenTextures(1,&font_texture);
-    glBindTexture(GL_TEXTURE_2D, font_texture);
-/*    printf("imagew %i, imageh %i, bytesperpixel %i\n", image->w, image->h, image->format->BytesPerPixel); */
-    glTexImage2D( GL_TEXTURE_2D, 0, 4, image->w, image->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, image->pixels);
-       glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-       glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-
-    glMatrixMode(GL_TEXTURE);
-    glLoadIdentity();
-    glScalef( 1.0f/(GLfloat)image->w, 1.0f/(GLfloat)image->h,1.0f);
-
-    SDL_FreeSurface(image);
-    glMatrixMode(GL_MODELVIEW);
-}
-
-void glputchar(char c){
-    int index = c;
-    int left = index * charwidth;
-    int right = index*charwidth+charwidth;
-    int top = 0;
-    int bottom =7;
-    
-    glDisable(GL_TEXTURE_2D);
-    glColor3f( 0.0f, 1.0f, 0.0f);
-    glBegin( GL_QUADS);
-       glVertex3i(  5, 7, 0 ); 
-       glVertex3i(  0, 7, 0 ); 
-       glVertex3i(  0, 0, 0 ); 
-      glVertex3i(   5, 0, 0 ); 
-    glEnd( );                           
-
-    glEnable(GL_TEXTURE_2D);
-    glColor3f( 1.0f, 1.0f, 1.0f);
-    glBindTexture(GL_TEXTURE_2D, font_texture);
-    glBegin( GL_QUADS);
-      glTexCoord2i(right,top);      glVertex3i(  5, 7, 0 ); 
-      glTexCoord2i(left, top);      glVertex3i(  0, 7, 0 ); 
-      glTexCoord2i(left, bottom);   glVertex3i(  0, 0, 0 ); 
-      glTexCoord2i(right,bottom);  glVertex3i(   5, 0, 0 ); 
-    glEnd( );                           
-
-}
-
-void glputstr( char *str){
-    while( *(++str) != 0 ){
-        glputchar(*str);
-        glTranslatef(6,0,0);
-    }
-}
-
-void hd44780_gl_draw( hd44780_t *b){
-    int rows = 16;
-    int lines = 2;
-    int border = 3;
-    glDisable(GL_TEXTURE_2D);
-    glColor3f(0.0f,0.4f,0.0f);
-    glTranslatef(0,-8,0);
-    glBegin(GL_QUADS);
-        glVertex3f( rows*charwidth + (rows-1) + border, -border,0);
-        glVertex3f( - border, -border,0);
-        glVertex3f( - border, lines*charheight + (lines-1)+border,0);
-        glVertex3f( rows*charwidth + (rows-1) + border, lines*charheight + (lines-1)+border,0);
-    glEnd();
-    glTranslatef(0,8,0);
-    glColor3f(1.0f,1.0f,1.0f);
-    for( int i=0; i<16; i++) {
-        glputchar( b->ddram[i] );
-        glTranslatef(6,0,0);
-    }
-    glTranslatef(-96,-8,0);
-    for( int i=0; i<16; i++) {
-        glputchar( b->ddram[i+0x40] );
-        glTranslatef(6,0,0);
-    }
-    
-}
diff --git a/examples/board_charlcd/hd44780_glut.h b/examples/board_charlcd/hd44780_glut.h
deleted file mode 100644 (file)
index 53d9403..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef __HD44780_GLUT_H__
-#define __HD44780_GLUT_H__
-
-#include "hd44780.h"
-
-void hd44780_gl_draw( hd44780_t *b);
-
-void hd44780_gl_init();
-
-#endif
diff --git a/examples/board_hd77480/Makefile b/examples/board_hd77480/Makefile
new file mode 100644 (file)
index 0000000..04a18d5
--- /dev/null
@@ -0,0 +1,55 @@
+# 
+#      Copyright 2008-2011 Michel Pollet <buserror@gmail.com>
+#
+#      This file is part of simavr.
+#
+#      simavr is free software: you can redistribute it and/or modify
+#      it under the terms of the GNU General Public License as published by
+#      the Free Software Foundation, either version 3 of the License, or
+#      (at your option) any later version.
+#
+#      simavr is distributed in the hope that it will be useful,
+#      but WITHOUT ANY WARRANTY; without even the implied warranty of
+#      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#      GNU General Public License for more details.
+#
+#      You should have received a copy of the GNU General Public License
+#      along with simavr.  If not, see <http://www.gnu.org/licenses/>.
+
+board= charlcd
+firm_src = ${wildcard at*${board}.c}
+firmware = ${firm_src:.c=.axf}
+simavr = ../../
+
+SHELL   = /bin/bash
+
+IPATH = .
+IPATH += ../parts
+IPATH += ${simavr}/include
+IPATH += ${simavr}/simavr/sim
+
+VPATH = .
+VPATH += ../parts
+
+LDFLAGS += -lpthread
+ifneq (${shell uname}, Darwin)
+LDFLAGS += -lGL -lglut
+else
+LDFLAGS += -framework GLUT -framework OpenGL 
+endif
+
+all: obj atmega48_charlcd.axf ${board} 
+
+atmega48_charlcd.axf: atmega48_charlcd.c
+
+include ${simavr}/Makefile.common
+
+${board} : ${OBJ}/ac_input.o
+${board} : ${OBJ}/hd44780.o
+${board} : ${OBJ}/hd44780_glut.o
+${board} : ${OBJ}/${board}.o
+       @echo LD $@
+       @gcc -MD ${CFLAGS}  ${LFLAGS} -o $@ $^ $(LDFLAGS) ${simavr}/simavr/libsimavr.a
+
+clean:
+       rm -rf obj *.hex *.a *.axf ${board} *.vcd .*.swo .*.swp .*.swm .*.swn
diff --git a/examples/board_hd77480/README b/examples/board_hd77480/README
new file mode 100644 (file)
index 0000000..0ef3b59
--- /dev/null
@@ -0,0 +1,21 @@
+board_hd44780
+
+(C) 2011 Michel Pollet <buserror@gmail.com>
+With thanks to Luki <humbell@ethz.ch>
+
+This sample code is derivated from a patch sent by Luki, however it was mostly
+in german, and was usinf the SDL library. Also the implementation of the LCD
+itself had several shortcomings.
+
+Therefore it was almost entirely rewritten from scratch the LCD was extended
+and made as compliant as it is practical, and the sample code itself was
+stripped of SDL. Also the german AVR LCD driver was replaced with the 
+avr-libc one, a much more complete one.
+
+This example demonstrated how to write a "part' that provide both a way to
+visualize what your code is doing, but also provide extra data you can
+visualize in gtkwave; so the LCD "part" exports quite a few IRQs that can
+be used to help you trace and debug your own code.
+
+Make sure to run this program and visualize the pretty curves.
\ No newline at end of file
diff --git a/examples/board_hd77480/atmega48_charlcd.c b/examples/board_hd77480/atmega48_charlcd.c
new file mode 100644 (file)
index 0000000..95c1e96
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+       atmega48_charlcd.c
+
+       Copyright Luki <humbell@ethz.ch>
+       Copyright 2011 Michel Pollet <buserror@gmail.com>
+
+       This file is part of simavr.
+
+       simavr is free software: you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation, either version 3 of the License, or
+       (at your option) any later version.
+
+       simavr is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with simavr.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#undef F_CPU
+#define F_CPU 10000000
+
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <util/delay.h>
+#include <avr/sleep.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+//#include "avr_defines.h"
+
+#include "avr_mcu_section.h"
+AVR_MCU(F_CPU, "atmega48");
+
+static uint8_t subsecct = 0;
+static uint8_t hour = 0;
+static uint8_t minute = 0;
+static uint8_t second = 0;
+static volatile uint8_t update_needed = 0;
+
+#include "avr_hd44780.c"
+
+ISR( INT0_vect )
+{
+       /* External interrupt on pin D2 */
+       subsecct++;
+       if (subsecct == 50) {
+               second++;
+               subsecct = 0;
+               update_needed = 1;
+               if (second == 60) {
+                       minute++;
+                       second = 0;
+                       if (minute == 60) {
+                               minute = 0;
+                               hour++;
+                               if (hour == 24)
+                                       hour = 0;
+                       }
+               }
+       }
+}
+
+int main()
+{
+       hd44780_init();
+       /*
+        * Clear the display.
+        */
+       hd44780_outcmd(HD44780_CLR);
+       hd44780_wait_ready(1); // long wait
+
+       /*
+        * Entry mode: auto-increment address counter, no display shift in
+        * effect.
+        */
+       hd44780_outcmd(HD44780_ENTMODE(1, 0));
+       hd44780_wait_ready(0);
+
+       /*
+        * Enable display, activate non-blinking cursor.
+        */
+       hd44780_outcmd(HD44780_DISPCTL(1, 1, 0));
+       hd44780_wait_ready(0);
+
+       EICRA = (1 << ISC00);
+       EIMSK = (1 << INT0);
+
+       sei();
+
+       while (1) {
+               while (!update_needed)
+                       sleep_mode();
+               update_needed = 0;
+               char buffer[16];
+
+               hd44780_outcmd(HD44780_CLR);
+               hd44780_wait_ready(1); // long wait
+               hd44780_outcmd(HD44780_DDADDR(4));
+               hd44780_wait_ready(0);
+               sprintf(buffer, "%2d:%02d:%02d", hour, minute, second);
+
+               char *s = buffer;
+               while (*s) {
+                       hd44780_outdata(*s++);
+                       hd44780_wait_ready(0);
+               }
+       }
+
+}
diff --git a/examples/board_hd77480/avr_hd44780.c b/examples/board_hd77480/avr_hd44780.c
new file mode 100644 (file)
index 0000000..7901fa5
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+ * ----------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * <joerg@FreeBSD.ORG> wrote this file.  As long as you retain this notice you
+ * can do whatever you want with this stuff. If we meet some day, and you think
+ * this stuff is worth it, you can buy me a beer in return.        Joerg Wunsch
+ * ----------------------------------------------------------------------------
+ *
+ * HD44780 LCD display driver
+ *
+ * The LCD controller is used in 4-bit mode with a full bi-directional
+ * interface (i.e. R/~W is connected) so the busy flag can be read.
+ *
+ * $Id: hd44780.c 2002 2009-06-25 20:21:16Z joerg_wunsch $
+ */
+
+#include "avr_hd44780_conf.h"
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <avr/io.h>
+#include <util/delay.h>
+
+#include "avr_hd44780.h"
+
+#define GLUE(a, b)     a##b
+
+/* single-bit macros, used for control bits */
+#define SET_(what, p, m) GLUE(what, p) |= (1 << (m))
+#define CLR_(what, p, m) GLUE(what, p) &= ~(1 << (m))
+#define GET_(/* PIN, */ p, m) GLUE(PIN, p) & (1 << (m))
+#define SET(what, x) SET_(what, x)
+#define CLR(what, x) CLR_(what, x)
+#define GET(/* PIN, */ x) GET_(x)
+
+/* nibble macros, used for data path */
+#define ASSIGN_(what, p, m, v) GLUE(what, p) = (GLUE(what, p) & \
+                                               ~((1 << (m)) | (1 << ((m) + 1)) | \
+                                                 (1 << ((m) + 2)) | (1 << ((m) + 3)))) | \
+                                               ((v) << (m))
+#define READ_(what, p, m) (GLUE(what, p) & ((1 << (m)) | (1 << ((m) + 1)) | \
+                                           (1 << ((m) + 2)) | (1 << ((m) + 3)))) >> (m)
+#define ASSIGN(what, x, v) ASSIGN_(what, x, v)
+#define READ(what, x) READ_(what, x)
+
+#define HD44780_BUSYFLAG 0x80
+
+/*
+ * Send one pulse to the E signal (enable).  Mind the timing
+ * constraints.  If readback is set to true, read the HD44780 data
+ * pins right before the falling edge of E, and return that value.
+ */
+static inline uint8_t
+hd44780_pulse_e(bool readback) __attribute__((always_inline));
+
+static inline uint8_t
+hd44780_pulse_e(bool readback)
+{
+  uint8_t x;
+
+  SET(PORT, HD44780_E);
+  /*
+   * Guarantee at least 500 ns of pulse width.  For high CPU
+   * frequencies, a delay loop is used.  For lower frequencies, NOPs
+   * are used, and at or below 1 MHz, the native pulse width will
+   * already be 1 us or more so no additional delays are needed.
+   */
+#if F_CPU > 4000000UL
+  _delay_us(0.5);
+#else
+  /*
+   * When reading back, we need one additional NOP, as the value read
+   * back from the input pin is sampled close to the beginning of a
+   * CPU clock cycle, while the previous edge on the output pin is
+   * generated towards the end of a CPU clock cycle.
+   */
+  if (readback)
+    __asm__ volatile("nop");
+#  if F_CPU > 1000000UL
+  __asm__ volatile("nop");
+#    if F_CPU > 2000000UL
+  __asm__ volatile("nop");
+  __asm__ volatile("nop");
+#    endif /* F_CPU > 2000000UL */
+#  endif /* F_CPU > 1000000UL */
+#endif
+  if (readback)
+    x = READ(PIN, HD44780_D4);
+  else
+    x = 0;
+  CLR(PORT, HD44780_E);
+
+  return x;
+}
+
+/*
+ * Send one nibble out to the LCD controller.
+ */
+static void
+hd44780_outnibble(uint8_t n, uint8_t rs)
+{
+  CLR(PORT, HD44780_RW);
+  if (rs)
+    SET(PORT, HD44780_RS);
+  else
+    CLR(PORT, HD44780_RS);
+  ASSIGN(PORT, HD44780_D4, n);
+  (void)hd44780_pulse_e(false);
+}
+
+/*
+ * Send one byte to the LCD controller.  As we are in 4-bit mode, we
+ * have to send two nibbles.
+ */
+void
+hd44780_outbyte(uint8_t b, uint8_t rs)
+{
+  hd44780_outnibble(b >> 4, rs);
+  hd44780_outnibble(b & 0xf, rs);
+}
+
+/*
+ * Read one nibble from the LCD controller.
+ */
+static uint8_t
+hd44780_innibble(uint8_t rs)
+{
+  uint8_t x;
+
+  SET(PORT, HD44780_RW);
+  ASSIGN(DDR, HD44780_D4, 0x00);
+  if (rs)
+    SET(PORT, HD44780_RS);
+  else
+    CLR(PORT, HD44780_RS);
+  x = hd44780_pulse_e(true);
+  ASSIGN(DDR, HD44780_D4, 0x0F);
+  CLR(PORT, HD44780_RW);
+
+  return x;
+}
+
+/*
+ * Read one byte (i.e. two nibbles) from the LCD controller.
+ */
+uint8_t
+hd44780_inbyte(uint8_t rs)
+{
+  uint8_t x;
+
+  x = hd44780_innibble(rs) << 4;
+  x |= hd44780_innibble(rs);
+
+  return x;
+}
+
+/*
+ * Wait until the busy flag is cleared.
+ */
+void
+hd44780_wait_ready(bool longwait)
+{
+#if USE_BUSY_BIT
+  while (hd44780_incmd() & HD44780_BUSYFLAG) ;
+#else
+  if (longwait)
+    _delay_ms(1.52);
+  else
+    _delay_us(37);
+#endif
+}
+
+/*
+ * Initialize the LCD controller.
+ *
+ * The initialization sequence has a mandatory timing so the
+ * controller can safely recognize the type of interface desired.
+ * This is the only area where timed waits are really needed as
+ * the busy flag cannot be probed initially.
+ */
+void
+hd44780_init(void)
+{
+  SET(DDR, HD44780_RS);
+  SET(DDR, HD44780_RW);
+  SET(DDR, HD44780_E);
+  ASSIGN(DDR, HD44780_D4, 0x0F);
+
+  _delay_ms(15);               /* 40 ms needed for Vcc = 2.7 V */
+  hd44780_outnibble(HD44780_FNSET(1, 0, 0) >> 4, 0);
+  _delay_ms(4.1);
+  hd44780_outnibble(HD44780_FNSET(1, 0, 0) >> 4, 0);
+  _delay_ms(0.1);
+  hd44780_outnibble(HD44780_FNSET(1, 0, 0) >> 4, 0);
+  _delay_us(40); /* 37 is too short */
+
+  hd44780_outnibble(HD44780_FNSET(0, 1, 0) >> 4, 0);
+  hd44780_wait_ready(false);
+  hd44780_outcmd(HD44780_FNSET(0, 1, 0));
+  hd44780_wait_ready(false);
+  hd44780_outcmd(HD44780_DISPCTL(0, 0, 0));
+  hd44780_wait_ready(false);
+}
+
+/*
+ * Prepare the LCD controller pins for powerdown.
+ */
+void
+hd44780_powerdown(void)
+{
+  ASSIGN(PORT, HD44780_D4, 0);
+  CLR(PORT, HD44780_RS);
+  CLR(PORT, HD44780_RW);
+  CLR(PORT, HD44780_E);
+}
diff --git a/examples/board_hd77480/avr_hd44780.h b/examples/board_hd77480/avr_hd44780.h
new file mode 100644 (file)
index 0000000..6d3d978
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * ----------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * <joerg@FreeBSD.ORG> wrote this file.  As long as you retain this notice you
+ * can do whatever you want with this stuff. If we meet some day, and you think
+ * this stuff is worth it, you can buy me a beer in return.        Joerg Wunsch
+ * ----------------------------------------------------------------------------
+ *
+ * HD44780 LCD display driver
+ *
+ * $Id: hd44780.h 2002 2009-06-25 20:21:16Z joerg_wunsch $
+ */
+
+/*
+ * Send byte b to the LCD.  rs is the RS signal (register select), 0
+ * selects instruction register, 1 selects the data register.
+ */
+void   hd44780_outbyte(uint8_t b, uint8_t rs);
+
+/*
+ * Read one byte from the LCD controller.  rs is the RS signal, 0
+ * selects busy flag (bit 7) and address counter, 1 selects the data
+ * register.
+ */
+uint8_t        hd44780_inbyte(uint8_t rs);
+
+/*
+ * Wait for the busy flag to clear.
+ */
+void   hd44780_wait_ready(bool islong);
+
+/*
+ * Initialize the LCD controller hardware.
+ */
+void   hd44780_init(void);
+
+/*
+ * Prepare the LCD controller pins for powerdown.
+ */
+void   hd44780_powerdown(void);
+
+
+/* Send a command to the LCD controller. */
+#define hd44780_outcmd(n)      hd44780_outbyte((n), 0)
+
+/* Send a data byte to the LCD controller. */
+#define hd44780_outdata(n)     hd44780_outbyte((n), 1)
+
+/* Read the address counter and busy flag from the LCD. */
+#define hd44780_incmd()                hd44780_inbyte(0)
+
+/* Read the current data byte from the LCD. */
+#define hd44780_indata()       hd44780_inbyte(1)
+
+
+/* Clear LCD display command. */
+#define HD44780_CLR \
+       0x01
+
+/* Home cursor command. */
+#define HD44780_HOME \
+       0x02
+
+/*
+ * Select the entry mode.  inc determines whether the address counter
+ * auto-increments, shift selects an automatic display shift.
+ */
+#define HD44780_ENTMODE(inc, shift) \
+       (0x04 | ((inc)? 0x02: 0) | ((shift)? 1: 0))
+
+/*
+ * Selects disp[lay] on/off, cursor on/off, cursor blink[ing]
+ * on/off.
+ */
+#define HD44780_DISPCTL(disp, cursor, blink) \
+       (0x08 | ((disp)? 0x04: 0) | ((cursor)? 0x02: 0) | ((blink)? 1: 0))
+
+/*
+ * With shift = 1, shift display right or left.
+ * With shift = 0, move cursor right or left.
+ */
+#define HD44780_SHIFT(shift, right) \
+       (0x10 | ((shift)? 0x08: 0) | ((right)? 0x04: 0))
+
+/*
+ * Function set.  if8bit selects an 8-bit data path, twoline arranges
+ * for a two-line display, font5x10 selects the 5x10 dot font (5x8
+ * dots if clear).
+ */
+#define HD44780_FNSET(if8bit, twoline, font5x10) \
+       (0x20 | ((if8bit)? 0x10: 0) | ((twoline)? 0x08: 0) | \
+               ((font5x10)? 0x04: 0))
+
+/*
+ * Set the next character generator address to addr.
+ */
+#define HD44780_CGADDR(addr) \
+       (0x40 | ((addr) & 0x3f))
+
+/*
+ * Set the next display address to addr.
+ */
+#define HD44780_DDADDR(addr) \
+       (0x80 | ((addr) & 0x7f))
+
diff --git a/examples/board_hd77480/avr_hd44780_conf.h b/examples/board_hd77480/avr_hd44780_conf.h
new file mode 100644 (file)
index 0000000..b01bc7d
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * ----------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * <joerg@FreeBSD.ORG> wrote this file.  As long as you retain this notice you
+ * can do whatever you want with this stuff. If we meet some day, and you think
+ * this stuff is worth it, you can buy me a beer in return.        Joerg Wunsch
+ * ----------------------------------------------------------------------------
+ *
+ * General stdiodemo defines
+ *
+ * $Id: defines.h 2186 2010-09-22 10:25:15Z aboyapati $
+ */
+
+/* HD44780 LCD port connections */
+#define HD44780_RW B, 6
+#define HD44780_E  B, 5
+#define HD44780_RS B, 4
+/* The data bits have to be not only in ascending order but also consecutive. */
+#define HD44780_D4 B, 0
+
+/* Whether to read the busy flag, or fall back to
+   worst-time delays. */
+#define USE_BUSY_BIT 1
diff --git a/examples/board_hd77480/charlcd.c b/examples/board_hd77480/charlcd.c
new file mode 100644 (file)
index 0000000..a7c118d
--- /dev/null
@@ -0,0 +1,246 @@
+/*
+       charlcd.c
+
+       Copyright Luki <humbell@ethz.ch>
+       Copyright 2011 Michel Pollet <buserror@gmail.com>
+
+       This file is part of simavr.
+
+       simavr is free software: you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation, either version 3 of the License, or
+       (at your option) any later version.
+
+       simavr is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with simavr.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <libgen.h>
+
+#include "sim_avr.h"
+#include "avr_ioport.h"
+#include "sim_elf.h"
+#include "sim_gdb.h"
+#include "sim_vcd_file.h"
+
+#if __APPLE__
+#include <GLUT/glut.h>
+#else
+#include <GL/glut.h>
+#endif
+#include <pthread.h>
+
+#include "ac_input.h"
+#include "hd44780_glut.h"
+
+
+//float pixsize = 16;
+int window;
+
+avr_t * avr = NULL;
+avr_vcd_t vcd_file;
+ac_input_t ac_input;
+hd44780_t hd44780;
+
+int color = 0;
+uint32_t colors[][4] = {
+               { 0x00aa00ff, 0x00cc00ff, 0x000000ff, 0x00000055 },     // fluo green
+               { 0xaa0000ff, 0xcc0000ff, 0x000000ff, 0x00000055 },     // red
+};
+
+static void *
+avr_run_thread(
+               void * ignore)
+{
+       while (1) {
+               avr_run(avr);
+       }
+}
+
+void keyCB(
+               unsigned char key, int x, int y)        /* called on key press */
+{
+       switch (key) {
+               case 'q':
+                       avr_vcd_stop(&vcd_file);
+                       exit(0);
+                       break;
+               case 'r':
+                       printf("Starting VCD trace; press 's' to stop\n");
+                       avr_vcd_start(&vcd_file);
+                       break;
+               case 's':
+                       printf("Stopping VCD trace\n");
+                       avr_vcd_stop(&vcd_file);
+                       break;
+       }
+}
+
+
+void displayCB(void)           /* function called whenever redisplay needed */
+{
+       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+       glMatrixMode(GL_MODELVIEW); // Select modelview matrix
+       glPushMatrix();
+       glLoadIdentity(); // Start with an identity matrix
+       glScalef(3, 3, 1);
+
+       hd44780_gl_draw(
+               &hd44780,
+                       colors[color][0], /* background */
+                       colors[color][1], /* character background */
+                       colors[color][2], /* text */
+                       colors[color][3] /* shadow */ );
+       glPopMatrix();
+    glutSwapBuffers();
+}
+
+// gl timer. if the lcd is dirty, refresh display
+void timerCB(int i)
+{
+       static int oldstate = -1;
+       // restart timer
+       glutTimerFunc(1000/64, timerCB, 0);
+       glutPostRedisplay();
+}
+
+int
+initGL(int w, int h)
+{
+       // Set up projection matrix
+       glMatrixMode(GL_PROJECTION); // Select projection matrix
+       glLoadIdentity(); // Start with an identity matrix
+       glOrtho(0, w, 0, h, 0, 10);
+       glScalef(1,-1,1);
+       glTranslatef(0, -1 * h, 0);
+
+       glutDisplayFunc(displayCB);             /* set window's display callback */
+       glutKeyboardFunc(keyCB);                /* set window's key callback */
+       glutTimerFunc(1000 / 24, timerCB, 0);
+
+       glEnable(GL_TEXTURE_2D);
+       glShadeModel(GL_SMOOTH);
+
+       glClearColor(0.8f, 0.8f, 0.8f, 1.0f);
+       glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+
+       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+       glEnable(GL_BLEND);
+
+       hd44780_gl_init();
+
+       return 1;
+}
+
+int
+main(
+               int argc,
+               char *argv[])
+{
+       elf_firmware_t f;
+       const char * fname = "atmega48_charlcd.axf";
+       char path[256];
+       sprintf(path, "%s/%s", dirname(argv[0]), fname);
+       printf("Firmware pathname is %s\n", path);
+       elf_read_firmware(path, &f);
+
+       printf("firmware %s f=%d mmcu=%s\n", fname, (int) f.frequency, f.mmcu);
+
+       avr = avr_make_mcu_by_name(f.mmcu);
+       if (!avr) {
+               fprintf(stderr, "%s: AVR '%s' now known\n", argv[0], f.mmcu);
+               exit(1);
+       }
+
+       avr_init(avr);
+       avr_load_firmware(avr, &f);
+       ac_input_init(avr, &ac_input);
+       avr_connect_irq(ac_input.irq + IRQ_AC_OUT, avr_io_getirq(avr,
+               AVR_IOCTL_IOPORT_GETIRQ('D'), 2));
+
+       hd44780_init(avr, &hd44780, 20, 4);
+
+       /* Connect Data Lines to Port B, 0-3 */
+       /* These are bidirectional too */
+       for (int i = 0; i < 4; i++) {
+               avr_irq_t * iavr = avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('B'), i);
+               avr_irq_t * ilcd = hd44780.irq + IRQ_HD44780_D4 + i;
+               // AVR -> LCD
+               avr_connect_irq(iavr, ilcd);
+               // LCD -> AVR
+               avr_connect_irq(ilcd, iavr);
+       }
+       avr_connect_irq(
+                       avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('B'), 4),
+                       hd44780.irq + IRQ_HD44780_RS);
+       avr_connect_irq(
+                       avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('B'), 5),
+                       hd44780.irq + IRQ_HD44780_E);
+       avr_connect_irq(
+                       avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('B'), 6),
+                       hd44780.irq + IRQ_HD44780_RW);
+
+
+       avr_vcd_init(avr, "gtkwave_output.vcd", &vcd_file, 10 /* usec */);
+       avr_vcd_add_signal(&vcd_file,
+                       avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('B'), IOPORT_IRQ_PIN_ALL),
+                       4 /* bits */, "D4-D7");
+       avr_vcd_add_signal(&vcd_file,
+                       avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('B'), 4),
+                       1 /* bits */, "RS");
+       avr_vcd_add_signal(&vcd_file,
+                       avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('B'), 5),
+                       1 /* bits */, "E");
+       avr_vcd_add_signal(&vcd_file,
+                       avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('B'), 6),
+                       1 /* bits */, "RW");
+       avr_vcd_add_signal(&vcd_file,
+                       hd44780.irq + IRQ_HD44780_BUSY,
+                       1 /* bits */, "LCD_BUSY");
+       avr_vcd_add_signal(&vcd_file,
+                       hd44780.irq + IRQ_HD44780_ADDR,
+                       7 /* bits */, "LCD_ADDR");
+       avr_vcd_add_signal(&vcd_file,
+                       hd44780.irq + IRQ_HD44780_DATA_IN,
+                       8 /* bits */, "LCD_DATA_IN");
+       avr_vcd_add_signal(&vcd_file,
+                       hd44780.irq + IRQ_HD44780_DATA_OUT,
+                       8 /* bits */, "LCD_DATA_OUT");
+
+       avr_vcd_add_signal(&vcd_file, ac_input.irq + IRQ_AC_OUT, 1, "ac_input");
+
+       avr_vcd_start(&vcd_file);
+
+       printf( "Demo : This is HD44780 LCD demo\n"
+                       "   You can configure the width&height of the LCD in the code\n"
+                       "   Press 'r' to start recording a 'wave' file - with a LOT of data\n"
+                       "   Press 's' to stop recording\n"
+                       );
+
+       /*
+        * OpenGL init, can be ignored
+        */
+       glutInit(&argc, argv);          /* initialize GLUT system */
+
+       int w = 5 + hd44780.w * 6;
+       int h = 5 + hd44780.h * 8;
+       int pixsize = 3;
+
+       glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
+       glutInitWindowSize(w * pixsize, h * pixsize);           /* width=400pixels height=500pixels */
+       window = glutCreateWindow("Press 'q' to quit"); /* create window */
+
+       initGL(w * pixsize, h * pixsize);
+
+       pthread_t run;
+       pthread_create(&run, NULL, avr_run_thread, NULL);
+
+       glutMainLoop();
+}
diff --git a/examples/board_hd77480/data/blu.tiff b/examples/board_hd77480/data/blu.tiff
new file mode 100644 (file)
index 0000000..0db74e2
Binary files /dev/null and b/examples/board_hd77480/data/blu.tiff differ
diff --git a/examples/board_hd77480/data/font.tiff b/examples/board_hd77480/data/font.tiff
new file mode 100644 (file)
index 0000000..d5a146e
Binary files /dev/null and b/examples/board_hd77480/data/font.tiff differ
diff --git a/examples/board_hd77480/data/processblu.py b/examples/board_hd77480/data/processblu.py
new file mode 100644 (file)
index 0000000..17f89f6
--- /dev/null
@@ -0,0 +1,75 @@
+import Image,struct
+img = Image.open('blu.tiff')
+
+class CharData(object):
+    def __init__(self, data):
+        if data is None:
+            self.data = [ [] for y in range(7) ]
+        else:
+            self.data = data
+
+    def concat( self, other ):
+        for y in range(7):
+            self.data[y] += other.data[y]
+
+    def get_bindata(self):
+        ll = len(self.data[0])
+        ret=''
+        for y in reversed(range(7)):
+            for x in self.data[y]:
+                ret += struct.pack('BBBB',*x)
+        return ret
+            
+
+    def save_as(self, name):
+        height = 7
+        width = len(self.data[0])
+        outimg = Image.frombuffer( "RGBA", (width, height),
+            self.get_bindata())
+        outimg.save(name)
+            
+
+def char_at(char_x,char_y):
+    """
+    char_x specifies, zero based, the x position of the character
+    """
+    start_x = 1+char_x+ 14*char_x+2
+    start_y = 1+char_y*22+1
+    print "Starting at %i,%i" %( start_x,start_y)
+    return CharData([[ img.getpixel( (start_x+2*x,start_y+2*y) ) for x in range(5)] for y in range(7)])
+
+
+chardata = CharData(None)
+for x in range(16): #0x00 - 0x0F
+    chardata.concat( char_at(0,x) )
+for x in range(16): #0x10 - 0x1F
+    chardata.concat( char_at(0,x) )
+for x in range(16): #0x20 - 0x2F
+    chardata.concat( char_at(1,x) )
+for x in range(16): #0x30 - 0x3F
+    chardata.concat( char_at(2,x) )
+for x in range(16): #0x40 - 0x4F
+    chardata.concat( char_at(3,x) )
+for x in range(16): #0x50 - 0x5F
+    chardata.concat( char_at(4,x) )
+for x in range(16): #0x60 - 0x6F
+    chardata.concat( char_at(5,x) )
+for x in range(16): #0x70 - 0x7F
+    chardata.concat( char_at(6,x) )
+for x in range(16): #0x80 - 0x8F
+    chardata.concat( char_at(0,x) )
+for x in range(16): #0x90 - 0x9F
+    chardata.concat( char_at(0,x) )
+for x in range(16): #0xA0 - 0xAF
+    chardata.concat( char_at(7,x) )
+for x in range(16): #0xB0 - 0xBF
+    chardata.concat( char_at(8,x) )
+for x in range(16): #0xC0 - 0xCF
+    chardata.concat( char_at(9,x) )
+for x in range(16): #0xD0 - 0xDF
+    chardata.concat( char_at(10,x) )
+for x in range(16): #0xE0 - 0xEF
+    chardata.concat( char_at(11,x) )
+for x in range(16): #0xF0 - 0xFF
+    chardata.concat( char_at(12,x) )
+print chardata.save_as('7x5font.tiff')
diff --git a/examples/board_hd77480/font.h b/examples/board_hd77480/font.h
new file mode 100644 (file)
index 0000000..7384839
--- /dev/null
@@ -0,0 +1,1070 @@
+/* GIMP RGBA C-Source image dump (font.c) */
+
+static const struct {
+  unsigned int          width;
+  unsigned int          height;
+  unsigned int          bytes_per_pixel; /* 3:RGB, 4:RGBA */ 
+  char                 *comment;
+  unsigned char         pixel_data[1280 * 7 * 4 + 1];
+} lcd_font = {
+  1280, 7, 4,
+  "generated with gimp from font,tiff",
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377"
+  "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0"
+  "\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0"
+  "\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0"
+  "\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377"
+  "\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0"
+  "\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377"
+  "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0"
+  "\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0"
+  "\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0"
+  "\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0"
+  "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0"
+  "\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0"
+  "\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0"
+  "\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0"
+  "\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0"
+  "\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0"
+  "\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0"
+  "\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0"
+  "\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377"
+  "\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0"
+  "\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0"
+  "\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0"
+  "\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377"
+  "\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0"
+  "\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0"
+  "\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0"
+  "\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0"
+  "\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0"
+  "\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0"
+  "\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0"
+  "\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0"
+  "\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0"
+  "\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0"
+  "\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0"
+  "\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377"
+  "\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377"
+  "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0"
+  "\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377"
+  "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0"
+  "\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377"
+  "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0"
+  "\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377"
+  "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0"
+  "\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0"
+  "\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0"
+  "\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0"
+  "\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377"
+  "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0"
+  "\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377"
+  "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0"
+  "\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0"
+  "\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0"
+  "\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0"
+  "\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0"
+  "\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377"
+  "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0"
+  "\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0"
+  "\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0"
+  "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0"
+  "\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0"
+  "\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377"
+  "\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0"
+  "\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0"
+  "\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0"
+  "\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0"
+  "\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0"
+  "\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0"
+  "\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0"
+  "\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0"
+  "\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0"
+  "\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0"
+  "\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0"
+  "\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0"
+  "\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0"
+  "\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0"
+  "\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0"
+  "\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0"
+  "\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0"
+  "\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0"
+  "\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0"
+  "\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0"
+  "\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0"
+  "\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0"
+  "\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0"
+  "\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0"
+  "\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0"
+  "\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0"
+  "\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0"
+  "\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0"
+  "\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0"
+  "\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0"
+  "\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0"
+  "\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0"
+  "\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0"
+  "\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0"
+  "\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0"
+  "\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0"
+  "\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0"
+  "\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377"
+  "\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0"
+  "\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0"
+  "\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0"
+  "\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0"
+  "\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0"
+  "\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0"
+  "\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0"
+  "\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0"
+  "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0"
+  "\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0"
+  "\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0"
+  "\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0"
+  "\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0"
+  "\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0"
+  "\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0"
+  "\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0"
+  "\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0"
+  "\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0"
+  "\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377"
+  "\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0"
+  "\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0"
+  "\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0"
+  "\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0"
+  "\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377"
+  "\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0"
+  "\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0"
+  "\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0"
+  "\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0"
+  "\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0"
+  "\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0"
+  "\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0"
+  "\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377"
+  "\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0"
+  "\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0"
+  "\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0"
+  "\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0"
+  "\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0"
+  "\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377"
+  "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0"
+  "\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0"
+  "\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0"
+  "\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0"
+  "\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377"
+  "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0"
+  "\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377"
+  "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0"
+  "\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0"
+  "\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377"
+  "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377"
+  "\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0"
+  "\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377"
+  "\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0"
+  "\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0"
+  "\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0"
+  "\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0"
+  "\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0"
+  "\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377"
+  "\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0"
+  "\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0"
+  "\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377"
+  "\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0"
+  "\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0"
+  "\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0"
+  "\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0"
+  "\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377"
+  "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0"
+  "\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0"
+  "\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0"
+  "\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0"
+  "\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0"
+  "\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0"
+  "\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377"
+  "\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0"
+  "\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0"
+  "\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0"
+  "\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0"
+  "\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0"
+  "\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0"
+  "\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0"
+  "\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0"
+  "\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0"
+  "\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0"
+  "\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377"
+  "\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0"
+  "\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0"
+  "\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0"
+  "\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0"
+  "\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0"
+  "\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0"
+  "\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0"
+  "\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0"
+  "\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0"
+  "\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0"
+  "\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0"
+  "\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0"
+  "\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0"
+  "\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0"
+  "\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0"
+  "\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377"
+  "\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0"
+  "\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0"
+  "\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0"
+  "\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0"
+  "\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0"
+  "\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0"
+  "\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0"
+  "\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0"
+  "\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0"
+  "\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0"
+  "\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0"
+  "\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0"
+  "\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0"
+  "\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0"
+  "\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0"
+  "\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0"
+  "\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0"
+  "\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0"
+  "\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0"
+  "\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0"
+  "\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0"
+  "\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0"
+  "\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0"
+  "\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0"
+  "\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0"
+  "\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377"
+  "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0"
+  "\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0"
+  "\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377"
+  "\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377"
+  "\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0"
+  "\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0"
+  "\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0"
+  "\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0"
+  "\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0"
+  "\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0"
+  "\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377"
+  "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377"
+  "\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0"
+  "\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0"
+  "\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377"
+  "\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0"
+  "\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0"
+  "\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0"
+  "\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0"
+  "\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0"
+  "\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0"
+  "\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0"
+  "\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0"
+  "\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377"
+  "\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0"
+  "\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0"
+  "\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377"
+  "\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0"
+  "\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0"
+  "\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0"
+  "\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0"
+  "\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0"
+  "\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0"
+  "\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0"
+  "\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0"
+  "\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0"
+  "\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0"
+  "\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0"
+  "\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0"
+  "\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0"
+  "\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0"
+  "\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0"
+  "\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0"
+  "\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0"
+  "\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0"
+  "\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0"
+  "\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0"
+  "\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0"
+  "\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377"
+  "\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377"
+  "\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377"
+  "\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0"
+  "\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0"
+  "\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0"
+  "\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377"
+  "\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0"
+  "\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0"
+  "\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0"
+  "\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377",
+};
+
diff --git a/examples/parts/ac_input.c b/examples/parts/ac_input.c
new file mode 100644 (file)
index 0000000..a363f6b
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+       ac_input.c
+
+       Copyright Luki <humbell@ethz.ch>
+       Copyright 2011 Michel Pollet <buserror@gmail.com>
+
+       This file is part of simavr.
+
+       simavr is free software: you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation, either version 3 of the License, or
+       (at your option) any later version.
+
+       simavr is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with simavr.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "sim_avr.h"
+#include "ac_input.h"
+#include "stdio.h"
+
+static avr_cycle_count_t
+switch_auto(struct avr_t * avr,
+        avr_cycle_count_t when, void * param)
+{
+       ac_input_t * b = (ac_input_t *) param;
+       b->value = !b->value;
+       avr_raise_irq(b->irq + IRQ_AC_OUT, b->value);
+       return when + avr_usec_to_cycles(avr, 100000 / 50);
+}
+
+void ac_input_init(struct avr_t *avr, ac_input_t *b)
+{
+       b->irq = avr_alloc_irq(0, IRQ_AC_COUNT);
+       b->avr = avr;
+       b->value = 0;
+       avr_cycle_timer_register_usec(avr, 100000 / 50, switch_auto, b);
+       printf("ac_input_init period %duS or %d cycles\n",
+                       100000 / 50, avr_usec_to_cycles(avr, 100000 / 50));
+}
diff --git a/examples/parts/ac_input.h b/examples/parts/ac_input.h
new file mode 100644 (file)
index 0000000..1a8b3a5
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+       ac_input.h
+
+       Copyright Luki <humbell@ethz.ch>
+       Copyright 2011 Michel Pollet <buserror@gmail.com>
+
+       This file is part of simavr.
+
+       simavr is free software: you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation, either version 3 of the License, or
+       (at your option) any later version.
+
+       simavr is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with simavr.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * Simulates a 50hz changing signal
+ */
+
+#ifndef __AC_INPUT_H__
+#define __AC_INPUT_H__
+
+#include "sim_irq.h"
+
+
+enum {
+    IRQ_AC_OUT = 0,
+    IRQ_AC_COUNT
+};
+
+typedef struct ac_input_t {
+    avr_irq_t * irq;
+    struct avr_t * avr;
+    uint8_t value;
+} ac_input_t;
+
+void
+ac_input_init(
+                       struct avr_t * avr,
+                       ac_input_t * b);
+
+#endif
diff --git a/examples/parts/hd44780.c b/examples/parts/hd44780.c
new file mode 100644 (file)
index 0000000..f5ed19b
--- /dev/null
@@ -0,0 +1,374 @@
+/*
+       hd44780.c
+
+       Copyright Luki <humbell@ethz.ch>
+       Copyright 2011 Michel Pollet <buserror@gmail.com>
+
+       This file is part of simavr.
+
+       simavr is free software: you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation, either version 3 of the License, or
+       (at your option) any later version.
+
+       simavr is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with simavr.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "sim_cycle_timers.h"
+
+#include "hd44780.h"
+
+void
+hd44780_print(
+               hd44780_t *b)
+{
+       printf("/******************\\\n");
+       const uint8_t offset[] = { 0, 0x40, 0x20, 0x60 };
+       for (int i = 0; i < b->h; i++) {
+               printf("| ");
+               fwrite(b->vram + offset[i], 1, b->w, stdout);
+               printf(" |\n");
+       }
+       printf("\\******************/\n");
+}
+
+
+static void
+_hd44780_reset_cursor(
+               hd44780_t *b)
+{
+       b->cursor = 0;
+       hd44780_set_flag(b, HD44780_FLAG_DIRTY, 1);
+       avr_raise_irq(b->irq + IRQ_HD44780_ADDR, b->cursor);
+}
+
+static void
+_hd44780_clear_screen(
+               hd44780_t *b)
+{
+       memset(b->vram, ' ', 80);
+       hd44780_set_flag(b, HD44780_FLAG_DIRTY, 1);
+       avr_raise_irq(b->irq + IRQ_HD44780_ADDR, b->cursor);
+}
+
+
+
+/*
+ * This is called when the delay between operation is triggered
+ * without the AVR firmware 'reading' the status byte. It
+ * automatically clears the BUSY flag for the next command
+ */
+static avr_cycle_count_t
+_hd44780_busy_timer(
+               struct avr_t * avr,
+        avr_cycle_count_t when, void * param)
+{
+       hd44780_t *b = (hd44780_t *) param;
+//     printf("%s called\n", __FUNCTION__);
+       hd44780_set_flag(b, HD44780_FLAG_BUSY, 0);
+       avr_raise_irq(b->irq + IRQ_HD44780_BUSY, 0);
+       return 0;
+}
+
+static void
+hd44780_kick_cursor(
+       hd44780_t *b)
+{
+       if (hd44780_get_flag(b, HD44780_FLAG_I_D)) {
+               if (b->cursor < 79)
+                       b->cursor++;
+               else if (b->cursor < 80+64-1)
+                       b->cursor++;
+       } else {
+               if (b->cursor < 80 && b->cursor)
+                       b->cursor--;
+               else if (b->cursor > 80)
+                       b->cursor--;
+               hd44780_set_flag(b, HD44780_FLAG_DIRTY, 1);
+               avr_raise_irq(b->irq + IRQ_HD44780_ADDR, b->cursor);
+       }
+}
+
+/*
+ * current data byte is ready in b->datapins
+ */
+static uint32_t
+hd44780_write_data(
+               hd44780_t *b)
+{
+       uint32_t delay = 37; // uS
+       b->vram[b->cursor] = b->datapins;
+       printf("hd44780_write_data %02x\n", b->datapins);
+       if (hd44780_get_flag(b, HD44780_FLAG_S_C)) {    // display shift ?
+               // TODO display shift
+       } else {
+               hd44780_kick_cursor(b);
+       }
+       hd44780_set_flag(b, HD44780_FLAG_DIRTY, 1);
+       return delay;
+}
+
+/*
+ * current command is ready in b->datapins
+ */
+static uint32_t
+hd44780_write_command(
+               hd44780_t *b)
+{
+       uint32_t delay = 37; // uS
+       int top = 7;    // get highest bit set'm
+       while (top)
+               if (b->datapins & (1 << top))
+                       break;
+               else top--;
+       printf("hd44780_write_command %02x\n", b->datapins);
+
+       switch (top) {
+               // Set  DDRAM address
+               case 7:         // 1 ADD ADD ADD ADD ADD ADD ADD
+                       b->cursor = b->datapins & 0x7f;
+                       break;
+               // Set  CGRAM address
+               case 6:         // 0 1 ADD ADD ADD ADD ADD ADD ADD
+                       b->cursor = 64 + (b->datapins & 0x3f);
+                       break;
+               // Function     set
+               case 5: {       // 0 0 1 DL N F x x
+                       int four = !hd44780_get_flag(b, HD44780_FLAG_D_L);
+                       hd44780_set_flag(b, HD44780_FLAG_D_L, b->datapins & 16);
+                       hd44780_set_flag(b, HD44780_FLAG_N, b->datapins & 8);
+                       hd44780_set_flag(b, HD44780_FLAG_F, b->datapins & 4);
+                       if (!four && !hd44780_get_flag(b, HD44780_FLAG_D_L)) {
+                               printf("%s activating 4 bits mode\n", __FUNCTION__);
+                               hd44780_set_flag(b, HD44780_FLAG_LOWNIBBLE, 0);
+                       }
+               }       break;
+               // Cursor display shift
+               case 4:         // 0 0 0 1 S/C R/L x x
+                       hd44780_set_flag(b, HD44780_FLAG_S_C, b->datapins & 8);
+                       hd44780_set_flag(b, HD44780_FLAG_R_L, b->datapins & 4);
+                       break;
+               // Display on/off control
+               case 3:         // 0 0 0 0 1 D C B
+                       hd44780_set_flag(b, HD44780_FLAG_D, b->datapins & 4);
+                       hd44780_set_flag(b, HD44780_FLAG_C, b->datapins & 2);
+                       hd44780_set_flag(b, HD44780_FLAG_B, b->datapins & 1);
+                       hd44780_set_flag(b, HD44780_FLAG_DIRTY, 1);
+                       break;
+               // Entry mode set
+               case 2:         // 0 0 0 0 0 1 I/D S
+                       hd44780_set_flag(b, HD44780_FLAG_I_D, b->datapins & 2);
+                       hd44780_set_flag(b, HD44780_FLAG_S, b->datapins & 1);
+                       break;
+               // Return home
+               case 1:         // 0 0 0 0 0 0 1 x
+                       _hd44780_reset_cursor(b);
+                       delay = 1520;
+                       break;
+               // Clear display
+               case 0:         // 0 0 0 0 0 0 0 1
+                       _hd44780_clear_screen(b);
+                       break;
+       }
+       return delay;
+}
+
+/*
+ * the E pin went low, and it's a write
+ */
+static uint32_t
+hd44780_process_write(
+               hd44780_t *b )
+{
+       uint32_t delay = 0; // uS
+       int four = !hd44780_get_flag(b, HD44780_FLAG_D_L);
+       int comp = four && hd44780_get_flag(b, HD44780_FLAG_LOWNIBBLE);
+       int write = 0;
+
+       if (four) { // 4 bits !
+               if (comp)
+                       b->datapins = (b->datapins & 0xf0) | ((b->pinstate >>  IRQ_HD44780_D4) & 0xf);
+               else
+                       b->datapins = (b->datapins & 0xf) | ((b->pinstate >>  IRQ_HD44780_D4-4) & 0xf0);
+               write = comp;
+               b->flags ^= (1 << HD44780_FLAG_LOWNIBBLE);
+       } else {        // 8 bits
+               b->datapins = (b->pinstate >>  IRQ_HD44780_D0) & 0xff;
+               write++;
+       }
+       avr_raise_irq(b->irq + IRQ_HD44780_DATA_IN, b->datapins);
+
+       // write has 8 bits to process
+       if (write) {
+               if (hd44780_get_flag(b, HD44780_FLAG_BUSY)) {
+                       printf("%s command %02x write when still BUSY\n", __FUNCTION__, b->datapins);
+               }
+               if (b->pinstate & (1 << IRQ_HD44780_RS))        // write data
+                       delay = hd44780_write_data(b);
+               else                                                                            // write command
+                       delay = hd44780_write_command(b);
+       }
+       return delay;
+}
+
+static uint32_t
+hd44780_process_read(
+               hd44780_t *b )
+{
+       uint32_t delay = 0; // uS
+       int four = !hd44780_get_flag(b, HD44780_FLAG_D_L);
+       int comp = four && hd44780_get_flag(b, HD44780_FLAG_LOWNIBBLE);
+       int done = 0;   // has something on the datapin we want
+
+       if (comp) {
+               // ready the 4 final bits on the 'actual' lcd pins
+               b->readpins <<= 4;
+               done++;
+               b->flags ^= (1 << HD44780_FLAG_LOWNIBBLE);
+       }
+
+       if (!done) { // new read
+
+               if (b->pinstate & (1 << IRQ_HD44780_RS)) {      // read data
+                       delay = 37;
+                       b->readpins = b->vram[b->cursor];
+                       hd44780_kick_cursor(b);
+               } else {        // read 'command' ie status register
+                       delay = 0;      // no raising busy when reading busy !
+
+                       // low bits are the current cursor
+                       b->readpins = b->cursor < 80 ? b->cursor : b->cursor-64;
+                       int busy = hd44780_get_flag(b, HD44780_FLAG_BUSY);
+                       b->readpins |= busy ? 0x80 : 0;
+
+               //      if (busy) printf("Good boy, guy's reading status byte\n");
+                       // now that we're read the busy flag, clear it and clear
+                       // the timer too
+                       hd44780_set_flag(b, HD44780_FLAG_BUSY, 0);
+                       avr_raise_irq(b->irq + IRQ_HD44780_BUSY, 0);
+                       avr_cycle_timer_cancel(b->avr, _hd44780_busy_timer, b);
+               }
+               avr_raise_irq(b->irq + IRQ_HD44780_DATA_OUT, b->readpins);
+
+               done++;
+               if (four)
+                       b->flags |= (1 << HD44780_FLAG_LOWNIBBLE); // for next read
+       }
+
+       // now send the prepared output pins to send as IRQs
+       if (done) {
+               avr_raise_irq(b->irq + IRQ_HD44780_ALL, b->readpins >> 4);
+               for (int i = four ? 4 : 0; i < 8; i++)
+                       avr_raise_irq(b->irq + IRQ_HD44780_D0 + i, (b->readpins >> i) & 1);
+       }
+       return delay;
+}
+
+static avr_cycle_count_t
+_hd44780_process_e_pinchange(
+               struct avr_t * avr,
+        avr_cycle_count_t when, void * param)
+{
+       hd44780_t *b = (hd44780_t *) param;
+
+       hd44780_set_flag(b, HD44780_FLAG_REENTRANT, 1);
+
+#if 0
+       uint16_t touch = b->oldstate ^ b->pinstate;
+       printf("LCD: %04x %04x %c %c %c %c\n", b->pinstate, touch,
+                       b->pinstate & (1 << IRQ_HD44780_RW) ? 'R' : 'W',
+                       b->pinstate & (1 << IRQ_HD44780_RS) ? 'D' : 'C',
+                       hd44780_get_flag(b, HD44780_FLAG_LOWNIBBLE) ? 'L' : 'H',
+                       hd44780_get_flag(b, HD44780_FLAG_BUSY) ? 'B' : ' ');
+#endif
+       int delay = 0; // in uS
+
+       if (b->pinstate & (1 << IRQ_HD44780_RW))        // read !?!
+               delay = hd44780_process_read(b);
+       else                                                                            // write
+               delay = hd44780_process_write(b);
+
+       if (delay) {
+               hd44780_set_flag(b, HD44780_FLAG_BUSY, 1);
+               avr_raise_irq(b->irq + IRQ_HD44780_BUSY, 1);
+               avr_cycle_timer_register_usec(b->avr, delay,
+                       _hd44780_busy_timer, b);
+       }
+//     b->oldstate = b->pinstate;
+       hd44780_set_flag(b, HD44780_FLAG_REENTRANT, 0);
+       return 0;
+}
+
+static void
+hd44780_pin_changed_hook(
+               struct avr_irq_t * irq,
+               uint32_t value,
+        void *param)
+{
+       hd44780_t *b = (hd44780_t *) param;
+
+       uint16_t old = b->pinstate;
+
+       switch (irq->irq) {
+               /*
+                * Update all the pins in one go by calling ourselves
+                * This is a shortcut for firmware that respects the conventions
+                */
+               case IRQ_HD44780_ALL:
+                       for (int i = 0; i < 4; i++)
+                               hd44780_pin_changed_hook(b->irq + IRQ_HD44780_D4 + i,
+                                               ((value >> i) & 1), param);
+                       hd44780_pin_changed_hook(b->irq + IRQ_HD44780_RS, (value >> 4), param);
+                       hd44780_pin_changed_hook(b->irq + IRQ_HD44780_E, (value >> 5), param);
+                       hd44780_pin_changed_hook(b->irq + IRQ_HD44780_RW, (value >> 6), param);
+                       return; // job already done!
+               case IRQ_HD44780_D0 ... IRQ_HD44780_D7:
+                       // don't update these pins in read mode
+                       if (hd44780_get_flag(b, HD44780_FLAG_REENTRANT))
+                               return;
+                       break;
+       }
+       b->pinstate = (b->pinstate & ~(1 << irq->irq)) | (value << irq->irq);
+       int eo = old & (1 << IRQ_HD44780_E);
+       int e = b->pinstate & (1 << IRQ_HD44780_E);
+       // on the E pin rising edge, do stuff otherwise just exit
+       if (!eo && e)
+               avr_cycle_timer_register(b->avr, 1, _hd44780_process_e_pinchange, b);
+}
+
+void
+hd44780_init(
+               struct avr_t *avr,
+               struct hd44780_t * b,
+               int width,
+               int height )
+{
+       memset(b, 0, sizeof(*b));
+       b->avr = avr;
+       b->w = width;
+       b->h = height;
+       /*
+        * Register callbacks on all our IRQs
+        */
+       b->irq = avr_alloc_irq(0, IRQ_HD44780_COUNT);
+       for (int i = 0; i < IRQ_HD44780_INPUT_COUNT; i++)
+               avr_irq_register_notify(b->irq + i, hd44780_pin_changed_hook, b);
+
+       _hd44780_reset_cursor(b);
+       _hd44780_clear_screen(b);
+
+       printf("LCD: %duS is %d cycles for your AVR\n",
+                       37, (int)avr_usec_to_cycles(avr, 37));
+       printf("LCD: %duS is %d cycles for your AVR\n",
+                       1, (int)avr_usec_to_cycles(avr, 1));
+}
+
diff --git a/examples/parts/hd44780.h b/examples/parts/hd44780.h
new file mode 100644 (file)
index 0000000..e3f1dd0
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+       hd44780.h
+
+       Copyright 2011 Michel Pollet <buserror@gmail.com>
+
+       This file is part of simavr.
+
+       simavr is free software: you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation, either version 3 of the License, or
+       (at your option) any later version.
+
+       simavr is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with simavr.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * This "Part" simulates the business end of a HD44780 LCD display
+ * It supports from 8x1 to 20x4 or even 40x4 (not sure that exists)
+ *
+ * It works both in 4 bits and 8 bits mode and supports a "quicky" method
+ * of driving that is commonly used on AVR, namely
+ * (msb) RW:E:RS:D7:D6:D5:D4 (lsb)
+ *
+ * + As usual, the "RW" pin is optional if you are willing to wait for the
+ *   specific number of cycles as per the datasheet (37uS between operations)
+ * + If you decide to use the RW pin, the "busy" flag is supported and will
+ *   be automaticly cleared on the second read, to exercisee the code a bit.
+ * + Cursor is supported, but now "display shift"
+ * + The Character RAM is supported, but is not currently drawn.
+ *
+ * To interface this part, you can use the "INPUT" IRQs and hook them to the
+ * simavr instance, if you use the RW pins or read back frim the display, you
+ * can hook the data pins /back/ to the AVR too.
+ *
+ * The "part" also provides various IRQs that are there to be placed in a VCD file
+ * to show what is sent, and some of the internal status.
+ *
+ * This part has been tested with two different implementation of an AVR driver
+ * for the hd44780. The one shipped in this directory is straight out of the
+ * avr-libc example code.
+ */
+#ifndef __HD44780_H__
+#define __HD44780_H__
+
+#include "sim_irq.h"
+
+enum {
+    IRQ_HD44780_ALL = 0,       // Only if (msb) RW:E:RS:D7:D6:D5:D4 (lsb)  configured
+    IRQ_HD44780_RS,
+    IRQ_HD44780_RW,
+    IRQ_HD44780_E,
+    // bidirectional
+    IRQ_HD44780_D0,IRQ_HD44780_D1,IRQ_HD44780_D2,IRQ_HD44780_D3,
+    IRQ_HD44780_D4,IRQ_HD44780_D5,IRQ_HD44780_D6,IRQ_HD44780_D7,
+    IRQ_HD44780_INPUT_COUNT,
+
+    IRQ_HD44780_BUSY,  // for VCD traces sake...
+    IRQ_HD44780_ADDR,
+    IRQ_HD44780_DATA_IN,
+    IRQ_HD44780_DATA_OUT,
+    IRQ_HD44780_COUNT
+};
+
+enum {
+    HD44780_FLAG_F = 0,         // 1: 5x10 Font, 0: 5x7 Font
+    HD44780_FLAG_N,             // 1: 2/4-lines Display, 0: 1-line Display,
+    HD44780_FLAG_D_L,           // 1: 4-Bit Interface, 0: 8-Bit Interface
+    HD44780_FLAG_R_L,           // 1: Shift right, 0: shift left
+    HD44780_FLAG_S_C,           // 1: Display shift, 0: Cursor move
+    HD44780_FLAG_B,             // 1: Cursor Blink
+    HD44780_FLAG_C,             // 1: Cursor on
+    HD44780_FLAG_D,             // 1: Set Entire Display memory (for clear)
+    HD44780_FLAG_S,             // 1: Follow display shift
+    HD44780_FLAG_I_D,                  // 1: Increment, 0: Decrement
+
+    /*
+     * Internal flags, not HD44780
+     */
+    HD44780_FLAG_LOWNIBBLE,            // 1: 4 bits mode, write/read low nibble
+    HD44780_FLAG_BUSY,                 // 1: Busy between instruction, 0: ready
+    HD44780_FLAG_REENTRANT,            // 1: Do not update pins
+
+    HD44780_FLAG_DIRTY,                        // 1: needs redisplay...
+    HD44780_FLAG_CRAM_DIRTY,   // 1: Character memory has changed
+};
+
+
+typedef struct hd44780_t
+{
+       avr_irq_t * irq;
+       struct avr_t * avr;
+       int             w, h;                           // width and height of the LCD
+
+       uint16_t cursor;                        // offset in vram
+       uint8_t  vram[80 + 64];
+
+       uint16_t pinstate;                      // 'actual' LCd data pins (IRQ bit field)
+       // uint16_t oldstate;                   /// previous pins
+       uint8_t  datapins;                      // composite of 4 high bits, or 8 bits
+       uint8_t  readpins;
+
+       uint16_t flags;                         // LCD flags ( HD44780_FLAG_*)
+} hd44780_t;
+
+void
+hd44780_init(
+               struct avr_t *avr,
+               struct hd44780_t * b,
+               int width,
+               int height );
+void
+hd44780_print(
+               struct hd44780_t *b);
+
+static inline int
+hd44780_set_flag(
+               hd44780_t *b, uint16_t bit, int val)
+{
+       int old = b->flags &  (1 << bit);
+       b->flags = (b->flags & ~(1 << bit)) | (val ? (1 << bit) : 0);
+       return old != 0;
+}
+
+static inline int
+hd44780_get_flag(
+               hd44780_t *b, uint16_t bit)
+{
+       return (b->flags &  (1 << bit)) != 0;
+}
+
+#endif 
diff --git a/examples/parts/hd44780_glut.c b/examples/parts/hd44780_glut.c
new file mode 100644 (file)
index 0000000..56940f5
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+       hd44780_glut.c
+
+       Copyright Luki <humbell@ethz.ch>
+       Copyright 2011 Michel Pollet <buserror@gmail.com>
+
+       This file is part of simavr.
+
+       simavr is free software: you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation, either version 3 of the License, or
+       (at your option) any later version.
+
+       simavr is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with simavr.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "hd44780_glut.h"
+
+#include <GL/gl.h>
+#include <GL/glu.h>
+
+#include "font.h"      // generated with gimp
+
+static GLuint font_texture;
+static int charwidth = 5;
+static int charheight = 7;
+
+void
+hd44780_gl_init()
+{
+       glGenTextures(1, &font_texture);
+       glBindTexture(GL_TEXTURE_2D, font_texture);
+       glTexImage2D(GL_TEXTURE_2D, 0, 4,
+                       lcd_font.width,
+                       lcd_font.height, 0, GL_RGBA,
+               GL_UNSIGNED_BYTE,
+               lcd_font.pixel_data);
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+       glMatrixMode(GL_TEXTURE);
+       glLoadIdentity();
+       glScalef(1.0f / (GLfloat) lcd_font.width, 1.0f / (GLfloat) lcd_font.height, 1.0f);
+
+       glMatrixMode(GL_MODELVIEW);
+}
+
+static inline void
+glColor32U(uint32_t color)
+{
+       glColor4f(
+                       (float)((color >> 24) & 0xff) / 255.0f,
+                       (float)((color >> 16) & 0xff) / 255.0f,
+                       (float)((color >> 8) & 0xff) / 255.0f,
+                       (float)((color) & 0xff) / 255.0f );
+}
+
+void
+glputchar(char c,
+               uint32_t character,
+               uint32_t text,
+               uint32_t shadow)
+{
+       int index = c;
+       int left = index * charwidth;
+       int right = index * charwidth + charwidth;
+       int top = 0;
+       int bottom = 7;
+
+       glEnable(GL_BLEND);
+       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+       glDisable(GL_TEXTURE_2D);
+       glColor32U(character);
+       glBegin(GL_QUADS);
+       glVertex3i(5, 7, 0);
+       glVertex3i(0, 7, 0);
+       glVertex3i(0, 0, 0);
+       glVertex3i(5, 0, 0);
+       glEnd();
+
+       glEnable(GL_BLEND);
+       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+       glEnable(GL_TEXTURE_2D);
+       glBindTexture(GL_TEXTURE_2D, font_texture);
+       if (shadow) {
+               glColor32U(shadow);
+               glPushMatrix();
+               glTranslatef(.2f, .2f, 0);
+               glBegin(GL_QUADS);
+               glTexCoord2i(right, top);               glVertex3i(5, 0, 0);
+               glTexCoord2i(left, top);                glVertex3i(0, 0, 0);
+               glTexCoord2i(left, bottom);             glVertex3i(0, 7, 0);
+               glTexCoord2i(right, bottom);    glVertex3i(5, 7, 0);
+               glEnd();
+               glPopMatrix();
+       }
+       glColor32U(text);
+       glBegin(GL_QUADS);
+       glTexCoord2i(right, top);               glVertex3i(5, 0, 0);
+       glTexCoord2i(left, top);                glVertex3i(0, 0, 0);
+       glTexCoord2i(left, bottom);             glVertex3i(0, 7, 0);
+       glTexCoord2i(right, bottom);    glVertex3i(5, 7, 0);
+       glEnd();
+
+}
+
+void
+hd44780_gl_draw(
+               hd44780_t *b,
+               uint32_t background,
+               uint32_t character,
+               uint32_t text,
+               uint32_t shadow)
+{
+       int rows = b->w;
+       int lines = b->h;
+       int border = 3;
+
+       glDisable(GL_TEXTURE_2D);
+       glDisable(GL_BLEND);
+       glColor32U(background);
+       glTranslatef(border, border, 0);
+       glBegin(GL_QUADS);
+       glVertex3f(rows * charwidth + (rows - 1) + border, -border, 0);
+       glVertex3f(-border, -border, 0);
+       glVertex3f(-border, lines * charheight + (lines - 1) + border, 0);
+       glVertex3f(rows * charwidth + (rows - 1) + border, lines * charheight
+               + (lines - 1) + border, 0);
+       glEnd();
+
+       glColor3f(1.0f, 1.0f, 1.0f);
+       const uint8_t offset[] = { 0, 0x40, 0x20, 0x60 };
+       for (int v = 0 ; v < b->h; v++) {
+               glPushMatrix();
+               for (int i = 0; i < b->w; i++) {
+                       glputchar(b->vram[offset[v] + i], character, text, shadow);
+                       glTranslatef(6, 0, 0);
+               }
+               glPopMatrix();
+               glTranslatef(0, 8, 0);
+       }
+       hd44780_set_flag(b, HD44780_FLAG_DIRTY, 0);
+}
diff --git a/examples/parts/hd44780_glut.h b/examples/parts/hd44780_glut.h
new file mode 100644 (file)
index 0000000..15b8717
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+       hd44780_glut.h
+
+       Copyright Luki <humbell@ethz.ch>
+       Copyright 2011 Michel Pollet <buserror@gmail.com>
+
+       This file is part of simavr.
+
+       simavr is free software: you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation, either version 3 of the License, or
+       (at your option) any later version.
+
+       simavr is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with simavr.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __HD44780_GLUT_H__
+#define __HD44780_GLUT_H__
+
+#include "hd44780.h"
+
+void
+hd44780_gl_draw(
+               hd44780_t *b,
+               uint32_t background,
+               uint32_t character,
+               uint32_t text,
+               uint32_t shadow);
+
+void
+hd44780_gl_init();
+
+#endif