/***************************************************************************
 *   Copyright (C) 30.06.2004                                              *
 *   Matthias Kranz (matthias.kranz@ifi.lmu.de)                            *
 *   Paul Holleis (paul.holleis@ifi.lmu.de)                                *
 *                                                                         *
 *   header file for the display GLK122323-25-SM                           *
 *   Last modified: 21.10.2004                                             *
 *                                                                         *
 *   This program 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 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program 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 this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 **************************************************************************/
#ifndef __STD
  #include <std.h>
#endif

#ifndef GLK_RX_PIN
  /// SmartITs standard pin for reading from the glk122323-25-SM
  #define GLK_RX_PIN PIN_B2
#endif 

#ifndef GLK_TX_PIN
  /// SmartITs standard pin for writing to the glk122323-25-SM
  #define GLK_TX_PIN PIN_B1
#endif

/// SmartITs standard speed setting for reading/writing from/to the glk12232-25-SM, see manual section 7.1.10
#define GLKSTREAM_SPEED 19200

/// define serial interface to LCD (see PICC compiler manual)
#use rs232(baud=GLKSTREAM_SPEED,xmit=GLK_RX_PIN,rcv=GLK_TX_PIN, STREAM=GLKSTREAM)

/// the glk122323 built-in standard font uses17 chars per line
#define GLK_STD_FONT_CHARS_PER_LINE 17

/******************************************************************************
 * structures
 *****************************************************************************/
/// Structure for saving display related data.
struct metrics{
	int8 left_margin;
	int8 top_margin;
	int8 x_space;
	int8 y_space;
	int8 scroll_row;
};

/******************************************************************************
 * function signatures
 *****************************************************************************/
// MISCELLANEOUS
void clear_display();

// LIGHTNING AND CONTRAST
void set_contrast(int8 contrast);
void set_default_contrast(int8 contrast);
void set_backlight_on(int8 minutes);
void set_backlight_off();

// INFORMATION GATHERING
int8 get_module_type();
char* module_type_to_text(int8 type);
void set_serial(int8 serialnumber1, int8 serialnumber2);
int16 get_serial();
int8 get_version();

// SPEED & TRANSFER
void set_rs232_portspeed(int8 speed);
void enter_flowcontrol(int8 full_mark, int8 empty_mark);
void exit_flowcontrol();

// TEXT FUNCTIONS
void set_autoscroll(int1 on);
void set_textinsertionpoint(int8 row, int8 col);
void set_textinsertionpoint_topleft();

// FONT FUNCTIONS
void set_currentfont(int8 fontid);
void set_fontmetrics(struct metrics fontmetrics);

// GRAPHICS FUNCTIONS
void set_drawingcolor(int8 color);
void draw_line(int8 x1, int8 y1, int8 x2, int8 y2);
void continue_line(int8 x, int8 y);
void draw_pixel(int8 x, int8 y);
void draw_rectangle_outlined(int8 color, int8 x1, int8 y1, int8 x2, int8 y2);
void draw_rectangle_filled(int8 color, int8 x1, int8 y1, int8 x2, int8 y2);

// BARGRAPH FUNCTIONS
void bargraph_init(int8 ref, int8 type, int8 x1, int8 y1, int8 x2, int8 y2);
void bargraph_write(int8 ref, int8 value);

// BITMAP FUNCTIONS
void display_bitmap(int8 ref, int8 x, int8 y);

// FILE SYSTEM AND MEMORY FUNCTIONS
void erase_file(int8 type, int8 ref);
void purge_memory();
void upload_bitmap(int8 ref, int16 size, char* data_ptr);
void upload_font(int8 ref, int16 size, char *data_ptr);

/******************************************************************************
 * Code
 *****************************************************************************/

/**
 * Clears the whole display.
 */
void clear_display()
{
  fprintf(GLKSTREAM, "%c%c", 254, 88);
}

/**
 * Sets display contrast.
 * \param contrast must be between 0 and 255; larger means darker.
 */
void set_contrast(int8 contrast)
{
  fprintf(GLKSTREAM, "%c%c%c", 254, 80, contrast);
}

/**
 * Sets display contrast and saves it as default.
 * \param contrast must be between 0 and 255; larger means darker.
 */
void set_default_contrast(int8 contrast)
{
  fprintf(GLKSTREAM, "%c%c%c", 254, 91, contrast);
}

/**
 * Switch the backlight on for [minutes]. Zero (0) means that backlight stays 
 * on forever.
 */
void set_backlight_on(int8 minutes)
{
  fprintf(GLKSTREAM, "%c%c%c", 254, 66, minutes);
}

/**
 * Switch the backlight off.
 */
void set_backlight_off()
{
  fprintf(GLKSTREAM, "%c%c", 254, 70);
}

/**
 * Reads the module type.
 * \return module type or zero (0) on error.
 */
int8 get_module_type()
{
  int8 modtype;
  modtype = 0;
  
  fprintf(GLKSTREAM, "%c%c", 254, 55);
  if (kbhit())
  {
    modtype = getc();
  }

  return modtype;
}

/**
 * Set rs232 port speed.
 * \param speed is either 0x20 (9600 baud), 0x0F (19200 baud, default), 0x95 
 * (57600 baud), 0x03 (76800 baud) or 0x8A (115200 - attention, according to 
 * the glk12232-25-sm manual, section 7.1.10, the speed is 115000 and not 115200!)
 * If speed is unknown, the standard speed is used.
 */
void set_rs232_portspeed(int8 speed)
{
	int8 recognized_speed = 0x0F;
	switch(speed) {
		// 9600 baud
		case 0x20: recognized_speed = 0x20; break; 
		// 19200 baud
		case 0x0f: recognized_speed = 0x0f; break;
		// 57600 baud
		case 0x95: recognized_speed = 0x95; break;
		// 76800 baud
		case 0x03: recognized_speed = 0x03; break;
		// 115200 baud ?
		case 0x8A: recognized_speed = 0x8A; break;
		default: 
		{
			// failsafe default
		  	recognized_speed = 0x0f;
		}	
	}
	// sets the new speed
	fprintf(GLKSTREAM, "%c%c%c", 254, 57, recognized_speed);
	// defines the new stream

	switch(recognized_speed) {
		// 9600 baud
		case 0x20:
		{
		  #use rs232(baud=9600,xmit=GLK_RX_PIN,rcv=GLK_TX_PIN, STREAM=GLKSTREAM)			
			break; 	
		}
		// 19200 baud
		case 0x0f: 
		{
		  #use rs232(baud=19200,xmit=GLK_RX_PIN,rcv=GLK_TX_PIN, STREAM=GLKSTREAM)			
			break; 	
		}
		// 57600 baud
		case 0x95: 
		{
		  #use rs232(baud=57600,xmit=GLK_RX_PIN,rcv=GLK_TX_PIN, STREAM=GLKSTREAM)			
			break; 	
		}
		// 76800 baud
		case 0x03:
		{
		  #use rs232(baud=76800,xmit=GLK_RX_PIN,rcv=GLK_TX_PIN, STREAM=GLKSTREAM)			
			break; 	
		}
		// 115200 baud ?
		case 0x8A:
		{
		  #use rs232(baud=115200,xmit=GLK_RX_PIN,rcv=GLK_TX_PIN, STREAM=GLKSTREAM)			
			break; 	
		}
		default: 
		{
		  #use rs232(baud=19200,xmit=GLK_RX_PIN,rcv=GLK_TX_PIN, STREAM=GLKSTREAM)			
		}	
	}	
}

/**
 * Switches to flow control mode. By default, the flow control mode is off.
 * \param full_mark full mark for the display buffer. When buffer reaches 
 * [full_mark] the display will return 0xFE to the host.
 * \param empty_mark empty mark for the display buffer. When buffer reaches
 * [empty_mark] the display will return 0xFF to the host.
 */
void enter_flowcontrol(int8 full_mark, int8 empty_mark)
{
  fprintf(GLKSTREAM, "%c%c", full_mark, empty_mark);
}

/**
 * Switch off flow control mode (this is the default).
 */
void exit_flowcontrol()
{
  fprintf(GLKSTREAM, "%c%c", 254, 59);
}

/**
 * Sets the serial number. This is a one-time-use-function.
 * It has no effect if the serial number is already set. Some modules
 * ship with no serial number set.
 * \param serialnumber1 first byte of the two byte serial number
 * \param serialnumber2 second byte of the two byte serial number
 */
void set_serial(int8 serialnumber1, int8 serialnumber2)
{
  fprintf(GLKSTREAM, "%c%c%c%c", 254, 34, serialnumber1, serialnumber2);
}

/**
 * Returns the serial number of the module
 * \return the 16bit value contains the first byte of the serial number in the
 * upper 8 bits and the second byte of the serial number in the lower 8 bits.
 * Make sure to split the returned 16bit int correctly in two 8 bit ints.
 * int8 high,low; high=low=0; high = (returned_value >> 8) || high;
 * low = returned_value || low;
 */
int16 get_serial()
{
	int8 serialnumber1; 
	int8 serialnumber2; 
	int16 serialnumber;
	serialnumber1 = 0;
	serialnumber2 = 0;
	serialnumber = 0;
  fprintf(GLKSTREAM, "%c%c", 254, 70);
  if (kbhit())
  {
    serialnumber1 = getc();
  }
  if (kbhit())
  {
    serialnumber2 = getc();
  }
	serialnumber = ( (serialnumber || serialnumber1) << 8) || serialnumber2;
	return serialnumber;
}

/**
 * Reads the firmware type.
 * \return firmware version or zero (0) on error.
 */
int8 get_version()
{
  int8 version;
  version = 0;
  
  fprintf(GLKSTREAM, "%c%c", 254, 54);
  if (kbhit())
  {
    version = getc();
  }

  return version;
}

/**
 * Reads the firmware type.
 * \param on sets autoscrolling property of the display, if on = 1 (true), then
 * autoscrolling is enabled (default state), if on = 0 (false), then 
 * autoscrolling is disabled. if on != 1 && on != 0 -> on = 1
 */
void set_autoscroll(int1 on)
{
	if (on == 1) 
	{
		fprintf(GLKSTREAM, "%c%c", 254, 81);
	}
	else if (on == 0)
	{
		fprintf(GLKSTREAM, "%c%c", 254, 82);
	}
	else
	{
		fprintf(GLKSTREAM, "%c%c", 254, 81);
	}	
}

/**
 * Sets the text insertion point according to the currently used font.
 * \param col column to set the insertion point to, the standard font has a width of 17 
 * \param row row to set the insertion point to
 */
void set_textinsertionpoint(int8 row, int8 col)
{
  fprintf(GLKSTREAM, "%c%c%c%c", 254, 71, row, col);	
}

/**
 * Sets the text insertion point to the top left corner.
 */
void set_textinsertionpoint_topleft()
{
	fprintf(GLKSTREAM, "%c%c", 254, 72);	
}

/**
 * Sets the font to be used. The standard font (unless overwritten) has id = 1.
 * The standard font has 5x7 pixels.
 * \param fontid id of the font to be used. font id = fontid has to be in the 
 * glk12232-sm-25 memory!
 */
void set_currentfont(int8 fontid)
{
	fprintf(GLKSTREAM, "%c%c%c", 254, 49, fontid);	
}	
	
/**
 * Sets the font metrics to be used. 
 * \param fontmetrics metrics structure
 */
void set_fontmetrics(struct metrics fontmetrics)
{
	/*
	struct metrics{
	int8 left_margin;
	int8 top_margin;
	int8 x_space;
	int8 y_space;
	int8 scroll_row;
	};
	*/
	fprintf(GLKSTREAM, "%c%c%c%c%c%c%c", 254, 50,
	 fontmetrics.left_margin,
	 fontmetrics.top_margin,
	 fontmetrics.x_space,
	 fontmetrics.y_space,
 	 fontmetrics.scroll_row);
}	

/**
 * Sets the drawing color (in grey scale).
 * \param color 0 = white, 255 = black
 */
void set_drawingcolor(int8 color)
{
	fprintf(GLKSTREAM, "%c%c%c", 254, 99, color);		
}

/**
 * Draws a line from coordinate (x1,y1) to (x2,y2).
 * x values are in [0;31], y values are in [0;121]. Both values are decimal.
 * \param x1 x coordinate of the originating point.
 * \param y1 y coordinate of the originating point.
 * \param x2 x coordinate of the target point.
 * \param y2 y coordinate of the target point.
 */
void draw_line(int8 x1, int8 y1, int8 x2, int8 y2)
{
	fprintf(GLKSTREAM, "%c%c%c%c%c%c", 254, 108, x1,y1,x2,y2);		
}

/**
 * Draws a line from coordinate the last coordinate to (x,y).
 * x values are in [0;31], y values are in [0;121]. Both values are decimal.
 * \param x x coordinate of the target point.
 * \param y y coordinate of the target point.
 */
void continue_line(int8 x, int8 y)
{
	fprintf(GLKSTREAM, "%c%c%c%c", 254, 108, x,y);		
}

/**
 * Draws a pixel at (x,y).
 * x values are in [0;31], y values are in [0;121]. Both values are decimal.
 * \param x x coordinate of the pixel.
 * \param y y coordinate of the pixel.
 */
void draw_pixel(int8 x, int8 y)
{
	fprintf(GLKSTREAM, "%c%c%c%c", 254, 112, x,y);		
}

/**
 * Draws an outlined rectangle from coordinate (x1,y1) (upper left edge) to 
 * (x2,y2) (lower right edge) using color = color.
 * x values are in [0;31], y values are in [0;121]. Both values are decimal.
 * \param color 0 = white, 255 = black.
 * \param x1 x coordinate of the originating point.
 * \param y1 y coordinate of the originating point.
 * \param x2 x coordinate of the target point.
 * \param y2 y coordinate of the target point.
 */
void draw_rectangle_outlined(int8 color, int8 x1, int8 y1, int8 x2, int8 y2)
{
	fprintf(GLKSTREAM, "%c%c%c%c%c%c%c", 254, 114, color, x1,y1,x2,y2);		
}

/**
 * Draws a filled rectangle from coordinate (x1,y1) (upper left edge) to 
 * (x2,y2) (lower right edge) using color = color.
 * x values are in [0;31], y values are in [0;121]. Both values are decimal.
 * \param color 0 = white, 255 = black.
 * \param x1 x coordinate of the originating point.
 * \param y1 y coordinate of the originating point.
 * \param x2 x coordinate of the target point.
 * \param y2 y coordinate of the target point.
 */
void draw_rectangle_filled(int8 color, int8 x1, int8 y1, int8 x2, int8 y2)
{
	fprintf(GLKSTREAM, "%c%c%c%c%c%c%c", 254, 120, color, x1,y1,x2,y2);		
}

/**
 * Sets aside space for a bar graph.
 * x values are in [0;31], y values are in [0;121]. Both values are decimal.
 * \param ref reference number (0-15) for use by the bargraph_write function
 * \param type one of 0 (vertical, starting at bottom), 1 (horizontal, starting 
 *        from left), 2 (vertical, starting from top), 3 (horizontal, starting
 *        from right)
 * \param x1 x coordinate of the originating point.
 * \param y1 y coordinate of the originating point.
 * \param x2 x coordinate of the target point.
 * \param y2 y coordinate of the target point.
 */
void bargraph_init(int8 ref, int8 type, int8 x1, int8 y1, int8 x2, int8 y2)
{
	fprintf(GLKSTREAM, "%c%c%c%c%c%c%c%c", 254, 103, ref, type, x1, y1, x2, y2);		
}

/**
 * Fills the bar graph.
 * x values are in [0;31], y values are in [0;121]. Both values are decimal.
 * \param ref reference number (0-15) for use by the bargraph_write function
 * \param value bar graph is filled from start to value (in pixels)
 */
void bargraph_write(int8 ref, int8 value)
{
	fprintf(GLKSTREAM, "%c%c%c%c", 254, 105, ref, value);		
}

/**
 * Displays the bitmap [ref] with its top left corner starting at [x][y].
 * x values are in [0;31], y values are in [0;121]. Both values are decimal.
 * \param ref reference number of the bitmap
 * \param x x-coordinate of the upper left point of the bitmap
 * \param y y-coordinate of the upper left point of the bitmap
 */
void display_bitmap(int8 ref, int8 x, int8 y)
{
	fprintf(GLKSTREAM, "%c%c%c%c%c", 254, 98, ref, x,y);		
}

/**
 * Erases referenced file from memory.
 * \param type type of the file (1 = font, 5 = bitmap)
 * \param ref reference number of the file.
 */
void erase_file(int8 type, int8 ref)
{
	fprintf(GLKSTREAM, "%c%c%c%c", 254, 45, type, ref);		
}

/**
 * Purges complete memory. All fonts, font metrics, bitmaps and settings are
 * removed. So be very careful, without a font, no text will be displayed!
 * Be sure to have a working (own) font BEFORE you do use this.
 */
void purge_memory()
{
	fprintf(GLKSTREAM, "%c%c%c%c", 254, 33, 89, 33);		
}

/**
 * Uploads a bitmap into memory to be stored there permanently.
 * On [ref]=1 lies the standard image which is displayed on power-up.
 *
 * ATTENTION: bitmap size > 255 byte do currently not work.
 *
 * \param ref reference number of the file.
 * \param size of the file.
 * \param data_ptr pointer to char array containing the bitmap data.
 */
void upload_bitmap(int8 ref, int16 size, char* data_ptr)
{
	int16 lower_byte, higher_byte;
	int16 bitmask1, bitmask2; //fontfilesize

  // bitmask for clearing the high byte 
  bitmask1 = 0x00FF;
  bitmask2 = 0xFF00;
  lower_byte = (size & bitmask1);
  higher_byte = (size & bitmask2);
	
  set_currentfont(1);
	
	fprintf(GLKSTREAM, "%c%c%c", 254,94,ref);
	// read confirmation byte for reference
  ref = fgetc(GLKSTREAM); 
  // send confirmation byte for correct received reference
  fprintf(GLKSTREAM, "%c", 0x01); 
	// send low size in16 (lower byte of file size)
  fprintf(GLKSTREAM, "%c", lower_byte);// 27 im testbeispiel
	// read confirmation byte for lower byte size
  ref = fgetc(GLKSTREAM); 
  // send confirmation byte for correct received lower byte size
  fprintf(GLKSTREAM, "%c", 0x01); 
	// send high size int16 ( higher byte of file size)
  fprintf(GLKSTREAM, "%c", higher_byte); // 0x00 im testbeispiel
	// read confirmation byte for higher byte size
  ref = fgetc(GLKSTREAM); 
	
	// read confirmation byte for "file fits into memory"
	ref = fgetc(GLKSTREAM); 
  // if file fits, ref = 0x01, else ref = 0x08

	for (lower_byte=0; lower_byte < size; lower_byte++) 
	{
		// transmit one byte
		fprintf(GLKSTREAM, "%c", data_ptr[lower_byte]);
		// confirm correct transmission of one sent byte
		ref = fgetc(GLKSTREAM); 
		// confirm confirmation
		fprintf(GLKSTREAM, "%c", 0x01);
	}
	
}

/**
 * Uploads a font definition into memory. Be aware of the fact, that only these
 * characters will be displayed which have been uploaded before. Others will 
 * simply not be printed!
 *
 * ATTENTION: font size>255 byte do currently not work.
 *
 * \param ref reference number of the font.
 * \param size of the file.
 * \param data_ptr pointer to char array containing the font data.
 */
void upload_font(int8 ref, int16 size, char *data_ptr)
{
	int16 lower_byte, higher_byte;
	int16 bitmask1, bitmask2; //fontfilesize

  // bitmask for clearing the high byte 
  bitmask1 = 0x00FF;
  bitmask2 = 0xFF00;
  lower_byte = (size & bitmask1);
  higher_byte = (size & bitmask2);
	
  set_currentfont(1);
	
	fprintf(GLKSTREAM, "%c%c%c", 254,36,ref);
	// read confirmation byte for reference
  ref = fgetc(GLKSTREAM); 
  // send confirmation byte for correct received reference
  fprintf(GLKSTREAM, "%c", 0x01); 
	// send low size in16 (lower byte of file size)
  fprintf(GLKSTREAM, "%c", lower_byte);// 27 im testbeispiel
	// read confirmation byte for lower byte size
  ref = fgetc(GLKSTREAM); 
  // send confirmation byte for correct received lower byte size
  fprintf(GLKSTREAM, "%c", 0x01); 
	// send high size int16 ( higher byte of file size)
  fprintf(GLKSTREAM, "%c", higher_byte); // 0x00 im testbeispiel
	// read confirmation byte for higher byte size
  ref = fgetc(GLKSTREAM); 
	
	// read confirmation byte for "file fits into memory"
	ref = fgetc(GLKSTREAM); 
  // if file fits, ref = 0x01, else ref = 0x08

	for (lower_byte=0; lower_byte < size; lower_byte++) 
	{
		// transmit one byte
		fprintf(GLKSTREAM, "%c", data_ptr[lower_byte]);
		// confirm correct transmission of one sent byte
		ref = fgetc(GLKSTREAM); 
		// confirm confirmation
		fprintf(GLKSTREAM, "%c", 0x01);
	}
	
}

/**
 * Translates the module type returned by get_moduletype() into plain text.
 * \param type module type to be translated into plain text
 */
char* module_type_to_text(int8 type)
{
	char module_name[];
	char unknown[] = "unknown";
	char *names[28];
	char name1[] = "LCD0821";
	char name2[] = "LCD2021";
	char name3[] = "LCD1641";
	char name4[] = "LCD2041";
	char name5[] = "LCD4021";
	char name6[] = "LCD4041";
	char name7[] = "LK202-25";
	char name8[] = "LK204-25";
	char name9[] = "LK404-55";
	char name10[] = "VFD2021";
	char name11[] = "VFD2041";
	char name12[] = "VFD4021";
	char name13[] = "VK202-25";
	char name14[] = "VK204-25";
	char name15[] = "GLC12232";
	char name16[] = "GLC12864";
	char name17[] = "GLC128128";
	char name18[] = "GLC24064";
	char name19[] = "GLK12864-25";
	char name20[] = "GLK24064-25";
	char name21[] = "GLK128128-25";
	char name22[] = "GLK12232-25";
	char name23[] = "LK404-AT";
	char name24[] = "VFD1621";
	char name25[] = "LK402-12";
	char name26[] = "LK162-12";
	char name27[] = "LK204-25PC";
	char name28[] = "GLK12232-25-SM";

	names[0] = name1;
	names[1] = name2;
	names[2] = name3;
	names[3] = name4;
	names[4] = name5;
	names[5] = name6;
	names[6] = name7;
	names[7] = name8;
	names[8] = name9;
	names[9] = name10;
	names[10] = name11;
	names[11] = name12;
	names[12] = name13;
	names[13] = name14;
	names[14] = name15;
	names[15] = name16;
	names[16] = name17;
	names[17] = name18;
	names[18] = name19;																
	names[19] = name20;
	names[20] = name21;
	names[21] = name22;
	names[22] = name23;
	names[23] = name24;
	names[24] = name25;
	names[25] = name26;
	names[26] = name27;
	names[27] = name28;


	switch (type)
	{
		case 0x01:{				module_name = name1;		}
		case 0x03:{				module_name = name2;		}
		case 0x04:{ 			module_name = name3;		}
		case 0x05:{				module_name = name4;		}
		case 0x06:{  			module_name = name5;		}
		case 0x07:{ 			module_name = name6;		}
		case 0x08:{ 			module_name = name7;		}
		case 0x09:{				module_name = name8;  	}
		case 0x0A:{				module_name = name9;		}
		case 0x0B:{				module_name = name10;		}
		case 0x0C:{				module_name = name11;		}
		case 0x0D:{				module_name = name12;		}
		case 0x0E:{ 			module_name = name13;		}
		case 0x0F:{ 			module_name = name14;		}
		case 0x10:{				module_name = name15;		}
		case 0x11:{				module_name = name16;		}
		case 0x12:{ 			module_name = name17;		}
		case 0x13:{				module_name = name18;		}
		case 0x14:{				module_name = name19;		}
		case 0x15:{				module_name = name20;		}
		case 0x21:{				module_name = name21;		}
		case 0x22:{				module_name = name22;		}
		case 0x31:{				module_name = name23;		}
		case 0x32:{				module_name = name24;		}
		case 0x33:{				module_name = name25;		}
		case 0x34:{				module_name = name26;		}
		case 0x35:{				module_name = name27;		}
  	case 0x24:{				module_name = name28;		}
		default:
		{
			module_name = unknown;
		}
	}
	return(module_name);
}

