tools/picctldisplaytest/src/picctldisplaytest.cpp
author root@rika
Thu, 23 Apr 2009 20:22:04 +0200
changeset 31 4567e7bc404c
parent 2 2f55e5dd591d
child 32 00a9c2c2f33f
permissions -rw-r--r--
added bootloader command
reworked input-handling
     1 /***************************************************************************
     2  *   Copyright (C) 2008 by Peter Marquardt   *
     3  *   p_marquardt@users.sourceforge.net   *
     4  *   code base Copyright (C) 2007 by Carsten Presser   *
     5  *                                                                         *
     6  *   This program is free software; you can redistribute it and/or modify  *
     7  *   it under the terms of the GNU General Public License as published by  *
     8  *   the Free Software Foundation; either version 2 of the License, or     *
     9  *   (at your option) any later version.                                   *
    10  *                                                                         *
    11  *   This program is distributed in the hope that it will be useful,       *
    12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
    13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
    14  *   GNU General Public License for more details.                          *
    15  *                                                                         *
    16  *   You should have received a copy of the GNU General Public License     *
    17  *   along with this program; if not, write to the                         *
    18  *   Free Software Foundation, Inc.,                                       *
    19  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
    20  ***************************************************************************/
    21 
    22 /*! \file pcctldisplaytest.cpp
    23 \brief A utility to test the picctl lcd display and interface
    24 \author Peter Marquardt p_marquardt@users.sourceforge.net
    25 \author Carsten Presser
    26 \todo sanitize command line argument parsing
    27 */
    28 
    29 #ifdef HAVE_CONFIG_H
    30 #include <config.h>
    31 #endif
    32 #include <iostream>
    33 #include <cstdlib>
    34 #include <termios.h>
    35 #include <fcntl.h>
    36 #include "picctldisplaytest.h"
    37 
    38 using namespace std;
    39 config myconfig;
    40 runtime_flags myflags;
    41 int fd;
    42 
    43 bool ack_flag;
    44 uint8_t buf[255];
    45 uint8_t buf_pos;
    46 uint8_t buf_cmd_start;
    47 bool buf_flag_escape;
    48 
    49 
    50 int main(int argc, char *argv[])
    51 {
    52 	bool kill_flag = false;
    53 	struct termios options;
    54 	char key;
    55 
    56 	buf_pos = 0;
    57 	ack_flag = false;
    58 	buf_cmd_start = 255;
    59 	buf_flag_escape = false;
    60 		
    61 	cout << "** picctldisplaytest - simple test utility for picctl lcd displays **" << endl
    62 		<< ">";
    63 	
    64 	// setting defaults
    65 	myconfig.debug = false;
    66 	myconfig.verbosity = 0;
    67 	myconfig.modem_device = "/dev/ttyACM0";
    68 	myflags.parse_return_clockram = false;
    69 	
    70 	// parsing arguments
    71 	for (int i = 1; i < argc; i++) {
    72 		if (*argv[i] == 'd') {
    73 			i++;
    74 			myconfig.modem_device = argv[i];
    75 		}
    76 		else if (*argv[i] == 'v') {
    77 			i++;
    78 			myconfig.verbosity = atoi(argv[i]);
    79 		}
    80 		else if (*argv[i] == 'D') {
    81 			myconfig.debug =true;
    82 		}
    83 	}
    84 	
    85 	if (myconfig.verbosity > 0 || myconfig.debug) {
    86 		cout << "picctldisplaytest called with\n"
    87 			<< "device: " << myconfig.modem_device << endl
    88 			<< "verbosity: " << myconfig.verbosity << endl
    89 			<< "debug mode:" << boolalpha << myconfig.debug << endl;
    90 	}
    91 	
    92 	/* open the device to be non-blocking (read will return immediatly) */
    93 	fd = open(myconfig.modem_device, O_RDWR | O_NOCTTY | O_NONBLOCK);
    94 	if (fd <0) {perror(myconfig.modem_device); exit(-1); }
    95 
    96 	cfsetispeed(&options, BAUDRATE);
    97 	cfsetospeed(&options, BAUDRATE);
    98 
    99 	options.c_cflag &= ~PARENB;
   100 	options.c_cflag &= ~CSTOPB;
   101 	options.c_cflag &= ~CSIZE;
   102 	options.c_cflag |= CS8;
   103 
   104 	options.c_cflag &= ~CRTSCTS;
   105 	options.c_cflag |= (CLOCAL | CREAD);
   106 	options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
   107 	options.c_iflag &= ~(IXON | IXOFF | IXANY);
   108 	options.c_oflag &= ~OPOST;
   109 	tcsetattr(fd, TCSANOW, &options);
   110 
   111 	if (myconfig.debug || myconfig.verbosity > 0) print_help();
   112 
   113 	while ( cin.get(key)) {
   114 		switch(key) {
   115 			case 'q':
   116 				cout << "Exiting." << endl;
   117 				return EXIT_SUCCESS;
   118 				break;
   119 			case 'u':
   120 				cout << "Switching to unmanaged mode..." << endl;
   121 				send_data(CMD_SET_MODE_UNMANAGED,(sizeof(CMD_SET_MODE_UNMANAGED)/sizeof(char)));
   122 				break;
   123 			case 'm':
   124 				cout << "Switching to managed mode..." << endl;
   125 				send_data(CMD_SET_MODE_MANAGED,(sizeof(CMD_SET_MODE_MANAGED)/sizeof(char)));
   126 				break;		 
   127 			case 'c':
   128 				cout << "Sending Clear Display..." << endl;
   129 				send_data(CMD_DISP_CLEAR_SCREEN,(sizeof(CMD_DISP_CLEAR_SCREEN)/sizeof(char)));
   130 				break;
   131 			case 'b':
   132 				cout << "Sending Bootload Start..." << endl;
   133 				send_data(CMD_BOOT,(sizeof(CMD_BOOT)/sizeof(char)));
   134 				break;
   135 			case 'h':
   136 				print_help();
   137 				break;
   138 			case 'j':
   139 				print_cli_options();
   140 				break;
   141 			case '1':
   142 				cout << "Display CG ROM charset..." << endl;
   143 				send_data(TEST_STRING_1,(sizeof(TEST_STRING_1)/sizeof(char)));
   144 				send_data(TEST_STRING_2,(sizeof(TEST_STRING_2)/sizeof(char)));
   145 				send_data(TEST_STRING_3,(sizeof(TEST_STRING_3)/sizeof(char)));
   146 				break;
   147 			case '2':
   148 				cout << "Filling the Display with CG ROM charset..." << endl;
   149 				send_data(TEST_STRING_1,(sizeof(TEST_STRING_1)/sizeof(char)));
   150 				send_data(TEST_STRING_2,(sizeof(TEST_STRING_2)/sizeof(char)));
   151 				send_data(TEST_STRING_3,(sizeof(TEST_STRING_3)/sizeof(char)));
   152 				send_data(TEST_STRING_4,(sizeof(TEST_STRING_4)/sizeof(char)));
   153 				send_data(TEST_STRING_5,(sizeof(TEST_STRING_5)/sizeof(char)));
   154 				break;
   155 			case '3': {
   156 				cout << "Sending Test String... one line per packet, 8 lines of 30 chars" << endl;
   157 				for (int j = 0; j < 8; j++) {
   158 					const unsigned char cmd[] = {0xAA,0x14,0x00,32,((j*30)),0x08,
   159 						16,17,18,19,20,21,22,23,24,25,
   160 						16,17,18,19,20,21,22,23,24,25,
   161 						16,17,18,19,20,21,22,23,24,25};
   162 					send_data(cmd,(sizeof(cmd)/sizeof(char)));
   163 				}
   164 		}
   165 				break;
   166 			case '4':
   167 				cout << "Sending Test String.. one char per packet,8 lines of 30 chars" << endl;
   168 				for (int j = 0; j < 8; j++) {
   169 					for (int k = 0; k < 30; k++) {
   170 						const unsigned char cmd[] = {0xAA,0x14,0x00,3,k+(j*30),0x08,
   171 							(16+k)};
   172 							send_data(cmd,(sizeof(cmd)/sizeof(char)));
   173 					}
   174 				}
   175 				break;
   176 			
   177 			case 'a':
   178 				cout << "Set PWM1 0%..." << endl;
   179 				CMD_SET_PWM1[4] = 0x00;
   180 				send_data(CMD_SET_PWM1,(sizeof(CMD_SET_PWM1)/sizeof(char)));
   181 				break;
   182 			case 's':
   183 				cout << "SetPWM1 25%..." << endl;
   184 				CMD_SET_PWM1[4] = 0x40;
   185 				send_data(CMD_SET_PWM1,(sizeof(CMD_SET_PWM1)/sizeof(char)));
   186 				break;
   187 			case 'd':
   188 				cout << "Set PWM1 50%..." << endl;
   189 				CMD_SET_PWM1[4] = 0x80;
   190 				send_data(CMD_SET_PWM1,(sizeof(CMD_SET_PWM1)/sizeof(char)));
   191 				break;
   192 			case 'f':
   193 				cout << "Set PWM1 75%..." << endl;
   194 				CMD_SET_PWM1[4] = 0xC0;
   195 				send_data(CMD_SET_PWM1,(sizeof(CMD_SET_PWM1)/sizeof(char)));
   196 				break;
   197 			case 'g':
   198 				cout << "Set PWM1 100%..." << endl;
   199 				CMD_SET_PWM1[4] = 0xFF;
   200 				send_data(CMD_SET_PWM1,(sizeof(CMD_SET_PWM1)/sizeof(char)));
   201 				break;
   202 			case 'A':
   203 				cout << "Set PWM2 0%..." << endl;
   204 				CMD_SET_PWM2[4] = 0x00;
   205 				send_data(CMD_SET_PWM2,(sizeof(CMD_SET_PWM2)/sizeof(char)));
   206 				break;
   207 			case 'S':
   208 				cout << "SetPWM2 25%..." << endl;
   209 				CMD_SET_PWM2[4] = 0x40;
   210 				send_data(CMD_SET_PWM2,(sizeof(CMD_SET_PWM2)/sizeof(char)));
   211 				break;
   212 			case 'D':
   213 				cout << "Set PWM2 50%..." << endl;
   214 				CMD_SET_PWM2[4] = 0x80;
   215 				send_data(CMD_SET_PWM2,(sizeof(CMD_SET_PWM2)/sizeof(char)));
   216 				break;
   217 			case 'F':
   218 				cout << "Set PWM2 75%..." << endl;
   219 				CMD_SET_PWM2[4] = 0xC0;
   220 				send_data(CMD_SET_PWM2,(sizeof(CMD_SET_PWM2)/sizeof(char)));
   221 				break;
   222 			case 'G':
   223 				cout << "Set PWM2 100%..." << endl;
   224 				CMD_SET_PWM2[4] = 0xFF;
   225 				send_data(CMD_SET_PWM2,(sizeof(CMD_SET_PWM2)/sizeof(char)));
   226 				break;
   227 			case 'T': {
   228 				cout << "Setting pcf8583 clock memory..." << endl;	
   229 				time_t mytime = time(NULL);
   230 				tm * myltime = localtime( &mytime);
   231 				if (myconfig.debug || myconfig.verbosity > 0) cout << "Local Time is: " << myltime->tm_hour << ":" << myltime->tm_min << ":" << myltime->tm_sec << " " << myltime->tm_mday << "." << myltime->tm_mon+1 << endl;
   232 				const unsigned char tcmd[] = {0xAA,0x41,0x00,0x10,
   233 					0x04,0x00,dec2bcd(myltime->tm_sec),dec2bcd(myltime->tm_min),dec2bcd(myltime->tm_hour),dec2bcd(myltime->tm_mday),
   234 					(dec2bcd(myltime->tm_mon+1)),0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
   235 					send_data(tcmd,(sizeof(tcmd)/sizeof(char)));
   236 				}
   237 				break;
   238 			case 't' : {
   239 				cout << "Dumping pcf8583 clock memory..." << endl;
   240 				int oldverbosity = myconfig.verbosity;
   241 				myflags.parse_return_clockram = true;
   242 				if (myconfig.verbosity < 2) {
   243 					myconfig.verbosity = 2;
   244 				}
   245 				send_data(CMD_GET_CLOCK_MEMORY,(sizeof(CMD_GET_CLOCK_MEMORY)/sizeof(char)));
   246 				myconfig.verbosity  = oldverbosity;
   247 				myflags.parse_return_clockram = false;
   248 				}
   249 				break;
   250 			case '5': {
   251 				cout << "Showing test picture 1..."<< endl;
   252 				write_gfx_ram( TEST_PICTURE_1,(sizeof(TEST_PICTURE_1)/sizeof(char)));
   253 			}
   254 				break;
   255 			case '6': {
   256 				cout << "Showing test picture 2 - horizontal lines..."<< endl;
   257 				unsigned char mycmd[36] = {0xAA,0x14,0x00,0x20,0x00,0x00,
   258 					0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
   259 					0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
   260 					0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
   261 				} ;
   262 				for (int i = 0; i <64;i+=2) {
   263 					mycmd[5] = (i*30) / 256;
   264 					mycmd[4] = (i*30) - (256 * mycmd[5]);
   265 					send_data(mycmd, (sizeof(mycmd)/sizeof(char)));
   266 				}
   267 			}
   268 				break;
   269 			case '7': {
   270 				cout << "Showing test picture 3 - vertical lines..."<< endl;
   271 				unsigned char mycmd[36] = {0xAA,0x14,0x00,0x20,0x00,0x00,
   272 					0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
   273 					0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
   274 					0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
   275 				} ;
   276 				for (int i = 0; i <64;i++) {
   277 					mycmd[5] = (i*30) / 256;
   278 					mycmd[4] = (i*30) - (256 * mycmd[5]);
   279 					send_data(mycmd, (sizeof(mycmd)/sizeof(char)));
   280 				}
   281 			}
   282 				break;
   283 			case '8': {
   284 				cout << "Showing test picture 4...Boxes"<< endl;
   285 				write_gfx_ram(TEST_PICTURE_2,(sizeof(TEST_PICTURE_2)/sizeof(char)));
   286 			}
   287 				break;
   288 			case '9': {
   289 				cout << "Showing test picture 5 - outline + center cross..."<< endl;
   290 				unsigned char mycmd_1[36] = {0xAA,0x14,0x00,0x20,0x00,0x00,
   291 					0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
   292 					0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
   293 					0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
   294 				} ;
   295 				unsigned char mycmd_2[36] = {0xAA,0x14,0x00,0x20,0x00,0x00,
   296 					0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
   297 					0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,
   298 					0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01
   299 				} ;
   300 				int i = 1;
   301 				for (int j = 0;j<2;j++) {
   302 					send_data(mycmd_1, (sizeof(mycmd_1)/sizeof(char)));
   303 					for ( i = 1; i <31;i++) {
   304 						mycmd_2[5] = ((i*30) + (j*960)) / 256;
   305 						mycmd_2[4] = ((i*30) + (j*960))  - (256 * mycmd_2[5]);
   306 						send_data(mycmd_2, (sizeof(mycmd_2)/sizeof(char)));
   307 					}
   308 					mycmd_1[5] = ((i*30) + (j*960)) / 256;
   309 					mycmd_1[4] = ((i*30) + (j*960))  - (256 * mycmd_1[5]);
   310 				}
   311 				send_data(mycmd_1, (sizeof(mycmd_1)/sizeof(char)));
   312 			}
   313 				break;
   314 
   315 			default:
   316 				break;
   317 		}
   318 		//sleep(1);
   319 		if (key != 0x13 && key != '\n') cout << ">";
   320 	}
   321 	close(fd);
   322 	return EXIT_SUCCESS;
   323 }
   324 
   325 unsigned char bitendian (unsigned char in)
   326 {
   327 	unsigned char ret = 0x00;
   328 	if (in & 0x01) ret+=0x80;
   329 	if (in & 0x02) ret+=0x40;
   330 	if (in & 0x04) ret+=0x20;
   331 	if (in & 0x08) ret+=0x10;
   332 	if (in & 0x10) ret+=0x08;
   333 	if (in & 0x20) ret+=0x04;
   334 	if (in & 0x40) ret+=0x02;
   335 	if (in & 0x80) ret+=0x01;
   336 
   337 	return (ret);
   338 }
   339 
   340 
   341 bool write_gfx_ram(const unsigned char * buffer, int numbytes) {
   342 	if (numbytes > 1920) {
   343 		cout << "Too much data for gfx RAM, ignoring..." << endl;
   344 		return false;
   345 	}
   346 	int i = 0, offset = 6, memaddr = 0;
   347 	bool all_sent = false;
   348 	unsigned char mycmd[63] = {0xAA,0x14,0x00,0x02,0x00,0x00};
   349 	while (i <numbytes) {
   350 		all_sent = false;
   351 		mycmd[offset] = bitendian(buffer[i]);
   352 		i++;	
   353 		offset++;
   354 		if (offset == 63) {
   355 			mycmd[3] = 59;
   356 			send_data(mycmd,63);
   357 			memaddr += 57;
   358 			mycmd[5] = (memaddr / 256);
   359 			mycmd[4] = (memaddr - (mycmd[5]*256));
   360 			offset = 6;
   361 			all_sent = true;
   362 		}
   363 	}
   364 	if (!all_sent) {
   365 		mycmd[3] = (offset-4);
   366 		send_data(mycmd,offset);
   367 	}
   368 	return true;
   369 }
   370 
   371 
   372 void read_data()
   373 {
   374     // read all available data (always get single bytes...)
   375     while (read(fd,&buf[buf_pos],1) > 0)
   376     {
   377         // search for SYNC byte
   378         if ((buf[buf_pos] == CMD_SYNC_RECV) && (!buf_flag_escape))
   379 	{
   380 	    if (buf_cmd_start != 255)
   381 	    {
   382 	    	#ifdef DEBUG
   383     		uint8_t i;
   384 		printf("Damaged Packet: ");
   385 	        for (i=buf_cmd_start; i<buf_pos; i++)
   386 		{
   387 		  printf("0x%02x ",buf[i]);
   388 		}
   389 		printf("; buf_pos = %d, buf_cmd_start = %d\n",buf_pos,buf_cmd_start);
   390 		#endif
   391 
   392 		buf_pos = 0;
   393 		buf[buf_pos] = CMD_SYNC_RECV;
   394 	    }
   395  	    buf_cmd_start = buf_pos;
   396 	}
   397 
   398 
   399 	// escaping is not used so far...
   400 /*        if ((buf[buf_pos] == CMD_ESCAPE_BYTE) && (!buf_flag_escape))
   401 	{
   402 	    // this byte was for masking only.. ignore it! 
   403 	    buf_flag_escape = true;
   404 	    continue;
   405 	} 
   406         buf_flag_escape = false;*/
   407 
   408 	buf_pos++;
   409 
   410         // we need to check for a valid packet...
   411 	if ((buf_pos - buf_cmd_start) >= CMD_DATA_START)
   412 	{
   413             // if we recieved a valid packet: start decoding
   414 	    if (buf[buf_cmd_start + CMD_HDR_LENGTH+1] == (buf_pos - buf_cmd_start - CMD_DATA_START))
   415 	    {
   416 	        DecodeCMD();
   417 		buf_pos = 0;
   418 		buf_cmd_start = 255;
   419 	    }
   420 	}
   421     }
   422 }
   423 
   424 
   425 
   426 /*! \brief prints some help
   427 */
   428 void print_help() {
   429 	cout << endl;
   430 	cout << "Usage:" << endl;
   431 	cout << "u\tset unmanaged mode" << endl;
   432 	cout << "m\tset managed mode" << endl;
   433 	cout << endl;
   434 	cout << "T\tset pcf8583 clock to system time" << endl;
   435 	cout << "t\tdump pcf8583 clock memory" << endl;
   436 	cout << endl;
   437 	cout << "Set PWM:" << endl;
   438 	cout << "PWM1\ta 0%\ts 25%\td 50%\tf 75%\tg 100%" << endl;
   439 	cout << "PWM2\tA 0%\tS 25%\tD 50%\tF 75%\tG 100%" << endl;
   440 	cout << endl;
   441 	cout << "1\tshow ROM charset" << endl;
   442 	cout << "2\tfill Text area with ROM charset" << endl;
   443 	cout << "3\tfill Text area (8 lines / 30 chars, one line per packet)" << endl;
   444 	cout << "4\tfill Text area (8 lines / 30 chars, one char per packet)" << endl;
   445 	cout << endl;
   446 	cout << "5\tshow test picture 1 (240x64px)" << endl;
   447 	cout << "6\tshow test picture 2 - horizontal lines (240x64px)" << endl;
   448 	cout << "7\tshow test picture 3 - vertical lines (240x64px)" << endl;
   449 	cout << "8\tshow test picture 4 - Boxes (240x64px)" << endl;
   450 	cout << "9\tshow test picture 5 - outline + center cross (240x64px)" << endl;
   451 	cout << endl;
   452 	cout << "c\tclear display" << endl;
   453 	cout << endl;
   454 	cout << "b\tenter bootload mode" << endl;
   455 	cout << endl;
   456 	cout << "h\tprint this help" << endl;
   457 	cout << "j\tprint command line options" << endl;
   458 	cout << "q\tquit" << endl;
   459 	cout << ">";
   460 }
   461 
   462 /*! \brief prints command line options
   463 */
   464 void print_cli_options() {
   465 	cout << endl 
   466 		<< " Command line options:\n"
   467 		<< endl;
   468 	cout << "d DEVICE\n"
   469 		<< "\tSets the display device to DEVICE, default value is /dev/ttyACM0\n"
   470 		<< "\tExample:\n"
   471 		<< "\tpicctldisplaytest d /dev/ttyACM0\n"
   472 		<< endl;
   473 	cout << "v VERBOSITY\n"
   474 			<< "\tSets verbosity to level VERBOSITY ( Range: 0-2, default 0 )\n"
   475 			<< "\tExample:\n"
   476 			<< "\tpicctldisplaytest v 1\n"
   477 			<< endl;
   478 	cout << "D\n"
   479 			<< "\tRun in debugging mode (aka. very verbose)\n"
   480 			<< "\tExample:\n"
   481 			<< "\tpicctldisplaytest D\n"
   482 			<< endl;
   483 	cout << "Combining command line options\n"
   484 			<< "\tAll command line options can be combined (though some combinations might not prove useful).\n"
   485 			<< "\tExample:\n"
   486 			<< "\tpicctldisplaytest D d /dev/ttyACM0\n"
   487 			<< endl;
   488 }
   489 
   490 /*! \brief encodes an integer to a BCD value
   491  */
   492 int dec2bcd(int decimal) {
   493 	return  (decimal > 99 ?  false : ((decimal/10)<<4)+(decimal%10));
   494 }
   495 
   496 /*! \brief decodes a BCD value and returns it as integer
   497  */
   498 int bcd2dec(int bcd) {
   499 	return (((bcd>>4)*10)+bcd%16);
   500 }
   501 
   502 /*! \brief handles SIGIO
   503  */
   504 void DecodeCMD() {
   505 	if (myconfig.debug || myconfig.verbosity > 0) {
   506 		//cout << "Received Data\n";
   507 		if (buf[buf_cmd_start] == CMD_SYNC_RECV) {
   508 			switch (buf[buf_cmd_start + 1]) {
   509 				case 0x01:
   510 					cout << "Received an ACK packet, payload: " << (int) buf[3] << " bytes." << endl;
   511 					ack_flag = true;
   512 					break;
   513 				case 0x02:
   514 					cout << "Received a NACK packet." << endl;
   515 					break;
   516 				case 0xFF:
   517 					cout << "Received COMMAND NOT IMPLEMENTED." << endl;
   518 					break;
   519 				case 0x10:
   520 					cout << "Received IR/Key data." << endl;
   521 					break;
   522 				default:
   523 					cout <<"Unknown Response code 0x" << hex << buf[1] << endl;
   524 					break;	
   525 			}
   526 		}
   527 		
   528 	}
   529 	if (myflags.parse_return_clockram || myconfig.debug || myconfig.verbosity > 1) {
   530 		for (int i=buf_cmd_start; i<buf_pos; i++) {
   531 			cout << "0x" << ((int) buf[i] < 10 ? "0" : "") << hex << (int) buf[i] << " ";
   532 			if (myflags.parse_return_clockram && i > 3) { 
   533 				switch (i) {
   534 					case 4:
   535 						cout << "(ctrl: " << dec << bcd2dec((int) buf[i]) << ") ";
   536 						break;
   537 					case 5:
   538 						cout << "(1/100s: " << dec << bcd2dec((int) buf[i]) << ") ";
   539 						break;
   540 					case 6:
   541 						cout << "(sec: " << dec << bcd2dec((int) buf[i]) << ") ";
   542 						break;
   543 					case 7:
   544 						cout << "(min: " << dec << bcd2dec((int) buf[i]) << ") ";
   545 						break;
   546 					case 8:
   547 						cout << "(hours: " << dec << bcd2dec((int) buf[i]) << ") ";
   548 						break;
   549 					case 9:
   550 						cout << "(year/date: " << dec << bcd2dec((int) buf[i]) << ") ";
   551 						break;
   552 					case 10:
   553 						cout << "(wday/month: " << dec << bcd2dec((int) buf[i]) << ") ";
   554 						break;
   555 					case 11:
   556 						cout << "(timer day: " << dec << bcd2dec((int) buf[i]) << ") ";
   557 						break;
   558 					case 12:
   559 						cout << "(alarm ctrl: " << dec << bcd2dec((int) buf[i]) << ") ";
   560 						break;
   561 					default:
   562 						cout << "(bcd2int: " << dec << bcd2dec((int) buf[i]) << ") ";
   563 						break;
   564 				}
   565 			}
   566 			if (i == 3 || (i+3)%8==0) cout << endl;
   567 		}
   568 		cout << endl;
   569 	}
   570 	if (myconfig.debug || myconfig.verbosity > 0) cout <<  dec << (buf_pos - buf_cmd_start) << " bytes received.\n";
   571 }
   572 
   573 /*! \brief sends size bytes of buffer data to the display
   574 
   575 \warning send_data doesn't check if buffer really is numbytes big. Expect all kind of weirdness if abused.
   576 \param buffer pointer to a char buffer conatining the data
   577 \param numbytes Number of bytes in buffer
   578 */
   579 bool send_data(const unsigned char * buffer, int numbytes) {
   580 	
   581 	int tout = 0;
   582 
   583 	if (numbytes > 64 ) {
   584 		cout << "Buffer size exceeds 64 Bytes, send_data aborted." << endl;
   585 		return false;
   586 	}
   587 	write(fd,buffer,numbytes);
   588 	if (myconfig.debug || myconfig.verbosity > 0) cout << numbytes <<" bytes sent.";
   589 	if (myconfig.debug || myconfig.verbosity > 1) {
   590 		cout <<" Data: " << endl ;
   591 		for ( int i = 0; i <numbytes; i++) {
   592 			cout << " 0x" << ((int) buffer[i] < 10 ? "0" : "") << hex << (int) buffer[i] << dec;
   593 			if (i > 0 && ((i-3)%8 ==0 || i == 3)) cout << endl;
   594 		}
   595 	}
   596 	if (myconfig.debug || myconfig.verbosity > 0) cout <<   endl;
   597 
   598 	ack_flag = false;
   599 
   600 	while (!ack_flag && tout < 1000) {
   601 		tout++;
   602 		read_data();
   603 		usleep(100);
   604 	}
   605 
   606 	return ack_flag;
   607 }