tools/picctldisplaytest/src/picctldisplaytest.cpp
changeset 2 2f55e5dd591d
child 31 4567e7bc404c
equal deleted inserted replaced
1:f08135942074 2:2f55e5dd591d
       
     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 <signal.h>
       
    36 #include <fcntl.h>
       
    37 #include "picctldisplaytest.h"
       
    38 
       
    39 using namespace std;
       
    40 config myconfig;
       
    41 runtime_flags myflags;
       
    42 int fd;
       
    43 
       
    44 int main(int argc, char *argv[])
       
    45 {
       
    46 	bool kill_flag = false;
       
    47 	struct termios options;
       
    48 	struct sigaction saio;
       
    49 	char key;
       
    50 		
       
    51 	cout << "** picctldisplaytest - simple test utility for picctl lcd displays **" << endl
       
    52 		<< ">";
       
    53 	
       
    54 	// setting defaults
       
    55 	myconfig.debug = false;
       
    56 	myconfig.verbosity = 0;
       
    57 	myconfig.modem_device = "/dev/ttyACM0";
       
    58 	myflags.parse_return_clockram = false;
       
    59 	
       
    60 	// parsing arguments
       
    61 	for (int i = 1; i < argc; i++) {
       
    62 		if (*argv[i] == 'd') {
       
    63 			i++;
       
    64 			myconfig.modem_device = argv[i];
       
    65 		}
       
    66 		else if (*argv[i] == 'v') {
       
    67 			i++;
       
    68 			myconfig.verbosity = atoi(argv[i]);
       
    69 		}
       
    70 		else if (*argv[i] == 'D') {
       
    71 			myconfig.debug =true;
       
    72 		}
       
    73 	}
       
    74 	
       
    75 	if (myconfig.verbosity > 0 || myconfig.debug) {
       
    76 		cout << "picctldisplaytest called with\n"
       
    77 			<< "device: " << myconfig.modem_device << endl
       
    78 			<< "verbosity: " << myconfig.verbosity << endl
       
    79 			<< "debug mode:" << boolalpha << myconfig.debug << endl;
       
    80 	}
       
    81 	
       
    82 	/* open the device to be non-blocking (read will return immediatly) */
       
    83 	fd = open(myconfig.modem_device, O_RDWR | O_NOCTTY | O_NONBLOCK);
       
    84 	if (fd <0) {perror(myconfig.modem_device); exit(-1); }
       
    85 
       
    86 	/* install the signal handler before making the device asynchronous */
       
    87 	saio.sa_handler = signal_handler_IO;
       
    88 	sigemptyset (&saio.sa_mask);
       
    89 	saio.sa_flags = 0;
       
    90 	saio.sa_restorer = NULL;
       
    91 	sigaction(SIGIO,&saio,NULL);
       
    92    // allow the process to receive SIGIO
       
    93 	fcntl(fd, F_SETOWN, getpid());
       
    94    // Make the file descriptor asynchronous
       
    95 	fcntl(fd, F_SETFL, FASYNC);
       
    96 
       
    97 	tcgetattr(fd, &options);
       
    98 
       
    99 	cfsetispeed(&options, BAUDRATE);
       
   100 	cfsetospeed(&options, BAUDRATE);
       
   101 
       
   102 	options.c_cflag &= ~PARENB;
       
   103 	options.c_cflag &= ~CSTOPB;
       
   104 	options.c_cflag &= ~CSIZE;
       
   105 	options.c_cflag |= CS8;
       
   106 
       
   107 	options.c_cflag &= ~CRTSCTS;
       
   108 	options.c_cflag |= (CLOCAL | CREAD);
       
   109 	options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
       
   110 	options.c_iflag &= ~(IXON | IXOFF | IXANY);
       
   111 	options.c_oflag &= ~OPOST;
       
   112 	tcsetattr(fd, TCSANOW, &options);
       
   113 
       
   114 	if (myconfig.debug || myconfig.verbosity > 0) print_help();
       
   115 
       
   116 	while ( cin.get(key)) {
       
   117 		switch(key) {
       
   118 			case 'q':
       
   119 				cout << "Exiting." << endl;
       
   120 				return EXIT_SUCCESS;
       
   121 				break;
       
   122 			case 'u':
       
   123 				cout << "Switching to unmanaged mode..." << endl;
       
   124 				send_data(CMD_SET_MODE_UNMANAGED,(sizeof(CMD_SET_MODE_UNMANAGED)/sizeof(char)));
       
   125 				break;
       
   126 			case 'm':
       
   127 				cout << "Switching to managed mode..." << endl;
       
   128 				send_data(CMD_SET_MODE_MANAGED,(sizeof(CMD_SET_MODE_MANAGED)/sizeof(char)));
       
   129 				break;		 
       
   130 			case 'c':
       
   131 				cout << "Sending Clear Display..." << endl;
       
   132 				send_data(CMD_DISP_CLEAR_SCREEN,(sizeof(CMD_DISP_CLEAR_SCREEN)/sizeof(char)));
       
   133 				break;
       
   134 			case 'h':
       
   135 				print_help();
       
   136 				break;
       
   137 			case 'j':
       
   138 				print_cli_options();
       
   139 				break;
       
   140 			case '1':
       
   141 				cout << "Display CG ROM charset..." << endl;
       
   142 				send_data(TEST_STRING_1,(sizeof(TEST_STRING_1)/sizeof(char)));
       
   143 				send_data(TEST_STRING_2,(sizeof(TEST_STRING_2)/sizeof(char)));
       
   144 				send_data(TEST_STRING_3,(sizeof(TEST_STRING_3)/sizeof(char)));
       
   145 				break;
       
   146 			case '2':
       
   147 				cout << "Filling the Display with CG ROM charset..." << endl;
       
   148 				send_data(TEST_STRING_1,(sizeof(TEST_STRING_1)/sizeof(char)));
       
   149 				send_data(TEST_STRING_2,(sizeof(TEST_STRING_2)/sizeof(char)));
       
   150 				send_data(TEST_STRING_3,(sizeof(TEST_STRING_3)/sizeof(char)));
       
   151 				send_data(TEST_STRING_4,(sizeof(TEST_STRING_4)/sizeof(char)));
       
   152 				send_data(TEST_STRING_5,(sizeof(TEST_STRING_5)/sizeof(char)));
       
   153 				break;
       
   154 			case '3': {
       
   155 				cout << "Sending Test String... one line per packet, 8 lines of 30 chars" << endl;
       
   156 				for (int j = 0; j < 8; j++) {
       
   157 					const unsigned char cmd[] = {0xAA,0x14,0x00,32,((j*30)),0x08,
       
   158 						16,17,18,19,20,21,22,23,24,25,
       
   159 						16,17,18,19,20,21,22,23,24,25,
       
   160 						16,17,18,19,20,21,22,23,24,25};
       
   161 					send_data(cmd,(sizeof(cmd)/sizeof(char)));
       
   162 				}
       
   163 		}
       
   164 				break;
       
   165 			case '4':
       
   166 				cout << "Sending Test String.. one char per packet,8 lines of 30 chars" << endl;
       
   167 				for (int j = 0; j < 8; j++) {
       
   168 					for (int k = 0; k < 30; k++) {
       
   169 						const unsigned char cmd[] = {0xAA,0x14,0x00,3,k+(j*30),0x08,
       
   170 							(16+k)};
       
   171 							send_data(cmd,(sizeof(cmd)/sizeof(char)));
       
   172 					}
       
   173 				}
       
   174 				break;
       
   175 			
       
   176 			case 'a':
       
   177 				cout << "Set PWM1 0%..." << endl;
       
   178 				CMD_SET_PWM1[4] = 0x00;
       
   179 				send_data(CMD_SET_PWM1,(sizeof(CMD_SET_PWM1)/sizeof(char)));
       
   180 				break;
       
   181 			case 's':
       
   182 				cout << "SetPWM1 25%..." << endl;
       
   183 				CMD_SET_PWM1[4] = 0x40;
       
   184 				send_data(CMD_SET_PWM1,(sizeof(CMD_SET_PWM1)/sizeof(char)));
       
   185 				break;
       
   186 			case 'd':
       
   187 				cout << "Set PWM1 50%..." << endl;
       
   188 				CMD_SET_PWM1[4] = 0x80;
       
   189 				send_data(CMD_SET_PWM1,(sizeof(CMD_SET_PWM1)/sizeof(char)));
       
   190 				break;
       
   191 			case 'f':
       
   192 				cout << "Set PWM1 75%..." << endl;
       
   193 				CMD_SET_PWM1[4] = 0xC0;
       
   194 				send_data(CMD_SET_PWM1,(sizeof(CMD_SET_PWM1)/sizeof(char)));
       
   195 				break;
       
   196 			case 'g':
       
   197 				cout << "Set PWM1 100%..." << endl;
       
   198 				CMD_SET_PWM1[4] = 0xFF;
       
   199 				send_data(CMD_SET_PWM1,(sizeof(CMD_SET_PWM1)/sizeof(char)));
       
   200 				break;
       
   201 			case 'A':
       
   202 				cout << "Set PWM2 0%..." << endl;
       
   203 				CMD_SET_PWM2[4] = 0x00;
       
   204 				send_data(CMD_SET_PWM2,(sizeof(CMD_SET_PWM2)/sizeof(char)));
       
   205 				break;
       
   206 			case 'S':
       
   207 				cout << "SetPWM2 25%..." << endl;
       
   208 				CMD_SET_PWM2[4] = 0x40;
       
   209 				send_data(CMD_SET_PWM2,(sizeof(CMD_SET_PWM2)/sizeof(char)));
       
   210 				break;
       
   211 			case 'D':
       
   212 				cout << "Set PWM2 50%..." << endl;
       
   213 				CMD_SET_PWM2[4] = 0x80;
       
   214 				send_data(CMD_SET_PWM2,(sizeof(CMD_SET_PWM2)/sizeof(char)));
       
   215 				break;
       
   216 			case 'F':
       
   217 				cout << "Set PWM2 75%..." << endl;
       
   218 				CMD_SET_PWM2[4] = 0xC0;
       
   219 				send_data(CMD_SET_PWM2,(sizeof(CMD_SET_PWM2)/sizeof(char)));
       
   220 				break;
       
   221 			case 'G':
       
   222 				cout << "Set PWM2 100%..." << endl;
       
   223 				CMD_SET_PWM2[4] = 0xFF;
       
   224 				send_data(CMD_SET_PWM2,(sizeof(CMD_SET_PWM2)/sizeof(char)));
       
   225 				break;
       
   226 			case 'T': {
       
   227 				cout << "Setting pcf8583 clock memory..." << endl;	
       
   228 				time_t mytime = time(NULL);
       
   229 				tm * myltime = localtime( &mytime);
       
   230 				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;
       
   231 				const unsigned char tcmd[] = {0xAA,0x41,0x00,0x10,
       
   232 					0x04,0x00,dec2bcd(myltime->tm_sec),dec2bcd(myltime->tm_min),dec2bcd(myltime->tm_hour),dec2bcd(myltime->tm_mday),
       
   233 					(dec2bcd(myltime->tm_mon+1)),0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
       
   234 					send_data(tcmd,(sizeof(tcmd)/sizeof(char)));
       
   235 				}
       
   236 				break;
       
   237 			case 't' : {
       
   238 				cout << "Dumping pcf8583 clock memory..." << endl;
       
   239 				int oldverbosity = myconfig.verbosity;
       
   240 				myflags.parse_return_clockram = true;
       
   241 				if (myconfig.verbosity < 2) {
       
   242 					myconfig.verbosity = 2;
       
   243 				}
       
   244 				send_data(CMD_GET_CLOCK_MEMORY,(sizeof(CMD_GET_CLOCK_MEMORY)/sizeof(char)));
       
   245 				myconfig.verbosity  = oldverbosity;
       
   246 				myflags.parse_return_clockram = false;
       
   247 				}
       
   248 				break;
       
   249 			case '5': {
       
   250 				cout << "Showing test picture 1..."<< endl;
       
   251 				write_gfx_ram( TEST_PICTURE_1,(sizeof(TEST_PICTURE_1)/sizeof(char)));
       
   252 			}
       
   253 				break;
       
   254 			case '6': {
       
   255 				cout << "Showing test picture 2 - horizontal lines..."<< endl;
       
   256 				unsigned char mycmd[36] = {0xAA,0x14,0x00,0x20,0x00,0x00,
       
   257 					0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
       
   258 					0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
       
   259 					0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
       
   260 				} ;
       
   261 				for (int i = 0; i <64;i+=2) {
       
   262 					mycmd[5] = (i*30) / 256;
       
   263 					mycmd[4] = (i*30) - (256 * mycmd[5]);
       
   264 					send_data(mycmd, (sizeof(mycmd)/sizeof(char)));
       
   265 				}
       
   266 			}
       
   267 				break;
       
   268 			case '7': {
       
   269 				cout << "Showing test picture 3 - vertical lines..."<< endl;
       
   270 				unsigned char mycmd[36] = {0xAA,0x14,0x00,0x20,0x00,0x00,
       
   271 					0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
       
   272 					0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
       
   273 					0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
       
   274 				} ;
       
   275 				for (int i = 0; i <64;i++) {
       
   276 					mycmd[5] = (i*30) / 256;
       
   277 					mycmd[4] = (i*30) - (256 * mycmd[5]);
       
   278 					send_data(mycmd, (sizeof(mycmd)/sizeof(char)));
       
   279 				}
       
   280 			}
       
   281 				break;
       
   282 			case '8': {
       
   283 				cout << "Showing test picture 4...Boxes"<< endl;
       
   284 				write_gfx_ram(TEST_PICTURE_2,(sizeof(TEST_PICTURE_2)/sizeof(char)));
       
   285 			}
       
   286 				break;
       
   287 			case '9': {
       
   288 				cout << "Showing test picture 5 - outline + center cross..."<< endl;
       
   289 				unsigned char mycmd_1[36] = {0xAA,0x14,0x00,0x20,0x00,0x00,
       
   290 					0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
       
   291 					0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
       
   292 					0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
       
   293 				} ;
       
   294 				unsigned char mycmd_2[36] = {0xAA,0x14,0x00,0x20,0x00,0x00,
       
   295 					0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
       
   296 					0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,
       
   297 					0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01
       
   298 				} ;
       
   299 				int i = 1;
       
   300 				for (int j = 0;j<2;j++) {
       
   301 					send_data(mycmd_1, (sizeof(mycmd_1)/sizeof(char)));
       
   302 					for ( i = 1; i <31;i++) {
       
   303 						mycmd_2[5] = ((i*30) + (j*960)) / 256;
       
   304 						mycmd_2[4] = ((i*30) + (j*960))  - (256 * mycmd_2[5]);
       
   305 						send_data(mycmd_2, (sizeof(mycmd_2)/sizeof(char)));
       
   306 					}
       
   307 					mycmd_1[5] = ((i*30) + (j*960)) / 256;
       
   308 					mycmd_1[4] = ((i*30) + (j*960))  - (256 * mycmd_1[5]);
       
   309 				}
       
   310 				send_data(mycmd_1, (sizeof(mycmd_1)/sizeof(char)));
       
   311 			}
       
   312 				break;
       
   313 
       
   314 			default:
       
   315 				break;
       
   316 		}
       
   317 		sleep(1);
       
   318 		if (key != 0x13 && key != '\n') cout << ">";
       
   319 	}
       
   320 	close(fd);
       
   321 	return EXIT_SUCCESS;
       
   322 }
       
   323 
       
   324 unsigned char bitendian (unsigned char in)
       
   325 {
       
   326 	unsigned char ret = 0x00;
       
   327 	if (in & 0x01) ret+=0x80;
       
   328 	if (in & 0x02) ret+=0x40;
       
   329 	if (in & 0x04) ret+=0x20;
       
   330 	if (in & 0x08) ret+=0x10;
       
   331 	if (in & 0x10) ret+=0x08;
       
   332 	if (in & 0x20) ret+=0x04;
       
   333 	if (in & 0x40) ret+=0x02;
       
   334 	if (in & 0x80) ret+=0x01;
       
   335 
       
   336 	return (ret);
       
   337 }
       
   338 
       
   339 
       
   340 bool write_gfx_ram(const unsigned char * buffer, int numbytes) {
       
   341 	if (numbytes > 1920) {
       
   342 		cout << "Too much data for gfx RAM, ignoring..." << endl;
       
   343 		return false;
       
   344 	}
       
   345 	int i = 0, offset = 6, memaddr = 0;
       
   346 	bool all_sent = false;
       
   347 	unsigned char mycmd[63] = {0xAA,0x14,0x00,0x02,0x00,0x00};
       
   348 	while (i <numbytes) {
       
   349 		all_sent = false;
       
   350 		mycmd[offset] = bitendian(buffer[i]);
       
   351 		i++;	
       
   352 		offset++;
       
   353 		if (offset == 63) {
       
   354 			mycmd[3] = 59;
       
   355 			send_data(mycmd,63);
       
   356 			memaddr += 57;
       
   357 			mycmd[5] = (memaddr / 256);
       
   358 			mycmd[4] = (memaddr - (mycmd[5]*256));
       
   359 			offset = 6;
       
   360 			all_sent = true;
       
   361 		}
       
   362 	}
       
   363 	if (!all_sent) {
       
   364 		mycmd[3] = (offset-4);
       
   365 		send_data(mycmd,offset);
       
   366 	}
       
   367 	return true;
       
   368 }
       
   369 
       
   370 /*! \brief sends size bytes of buffer data to the display
       
   371 
       
   372 \warning send_data doesn't check if buffer really is numbytes big. Expect all kind of weirdness if abused.
       
   373 \param buffer pointer to a char buffer conatining the data
       
   374 \param numbytes Number of bytes in buffer
       
   375 */
       
   376 bool send_data(const unsigned char * buffer, int numbytes) {
       
   377 	if (numbytes > 64 ) {
       
   378 		cout << "Buffer size exceeds 64 Bytes, send_data aborted." << endl;
       
   379 		return false;
       
   380 	}
       
   381 	write(fd,buffer,numbytes);
       
   382 	if (myconfig.debug || myconfig.verbosity > 0) cout << numbytes <<" bytes sent.";
       
   383 	if (myconfig.debug || myconfig.verbosity > 1) {
       
   384 		cout <<" Data: " << endl ;
       
   385 		for ( int i = 0; i <numbytes; i++) {
       
   386 			cout << " 0x" << ((int) buffer[i] < 10 ? "0" : "") << hex << (int) buffer[i] << dec;
       
   387 			if (i > 0 && ((i-3)%8 ==0 || i == 3)) cout << endl;
       
   388 		}
       
   389 	}
       
   390 	if (myconfig.debug || myconfig.verbosity > 0) cout <<   endl;
       
   391 	usleep(100000);
       
   392 	return true;
       
   393 }
       
   394 
       
   395 /*! \brief prints some help
       
   396 */
       
   397 void print_help() {
       
   398 	cout << endl;
       
   399 	cout << "Usage:" << endl;
       
   400 	cout << "u\tset unmanaged mode" << endl;
       
   401 	cout << "m\tset managed mode" << endl;
       
   402 	cout << endl;
       
   403 	cout << "T\tset pcf8583 clock to system time" << endl;
       
   404 	cout << "t\tdump pcf8583 clock memory" << endl;
       
   405 	cout << endl;
       
   406 	cout << "Set PWM:" << endl;
       
   407 	cout << "PWM1\ta 0%\ts 25%\td 50%\tf 75%\tg 100%" << endl;
       
   408 	cout << "PWM2\tA 0%\tS 25%\tD 50%\tF 75%\tG 100%" << endl;
       
   409 	cout << endl;
       
   410 	cout << "1\tshow ROM charset" << endl;
       
   411 	cout << "2\tfill Text area with ROM charset" << endl;
       
   412 	cout << "3\tfill Text area (8 lines / 30 chars, one line per packet)" << endl;
       
   413 	cout << "4\tfill Text area (8 lines / 30 chars, one char per packet)" << endl;
       
   414 	cout << endl;
       
   415 	cout << "5\tshow test picture 1 (240x64px)" << endl;
       
   416 	cout << "6\tshow test picture 2 - horizontal lines (240x64px)" << endl;
       
   417 	cout << "7\tshow test picture 3 - vertical lines (240x64px)" << endl;
       
   418 	cout << "8\tshow test picture 4 - Boxes (240x64px)" << endl;
       
   419 	cout << "9\tshow test picture 5 - outline + center cross (240x64px)" << endl;
       
   420 	cout << endl;
       
   421 	cout << "c\tclear display" << endl;
       
   422 	cout << endl;
       
   423 	cout << "h\tprint this help" << endl;
       
   424 	cout << "j\tprint command line options" << endl;
       
   425 	cout << "q\tquit" << endl;
       
   426 	cout << ">";
       
   427 }
       
   428 
       
   429 /*! \brief prints command line options
       
   430 */
       
   431 void print_cli_options() {
       
   432 	cout << endl 
       
   433 		<< " Command line options:\n"
       
   434 		<< endl;
       
   435 	cout << "d DEVICE\n"
       
   436 		<< "\tSets the display device to DEVICE, default value is /dev/ttyACM0\n"
       
   437 		<< "\tExample:\n"
       
   438 		<< "\tpicctldisplaytest d /dev/ttyACM0\n"
       
   439 		<< endl;
       
   440 	cout << "v VERBOSITY\n"
       
   441 			<< "\tSets verbosity to level VERBOSITY ( Range: 0-2, default 0 )\n"
       
   442 			<< "\tExample:\n"
       
   443 			<< "\tpicctldisplaytest v 1\n"
       
   444 			<< endl;
       
   445 	cout << "D\n"
       
   446 			<< "\tRun in debugging mode (aka. very verbose)\n"
       
   447 			<< "\tExample:\n"
       
   448 			<< "\tpicctldisplaytest D\n"
       
   449 			<< endl;
       
   450 	cout << "Combining command line options\n"
       
   451 			<< "\tAll command line options can be combined (though some combinations might not prove useful).\n"
       
   452 			<< "\tExample:\n"
       
   453 			<< "\tpicctldisplaytest D d /dev/ttyACM0\n"
       
   454 			<< endl;
       
   455 }
       
   456 
       
   457 /*! \brief encodes an integer to a BCD value
       
   458  */
       
   459 int dec2bcd(int decimal) {
       
   460 	return  (decimal > 99 ?  false : ((decimal/10)<<4)+(decimal%10));
       
   461 }
       
   462 
       
   463 /*! \brief decodes a BCD value and returns it as integer
       
   464  */
       
   465 int bcd2dec(int bcd) {
       
   466 	return (((bcd>>4)*10)+bcd%16);
       
   467 }
       
   468 
       
   469 /*! \brief handles SIGIO
       
   470  */
       
   471 void signal_handler_IO (int status) {
       
   472 	
       
   473 	unsigned char buf[255];
       
   474 	int res = read(fd,buf,255);
       
   475 	
       
   476 	if (myconfig.debug || myconfig.verbosity > 0) {
       
   477 		//cout << "Received Data\n";
       
   478 		if (buf[0] == 0x55) {
       
   479 			switch (buf[1]) {
       
   480 				case 0x01:
       
   481 					cout << "Received an ACK packet, payload: " << (int) buf[3] << " bytes." << endl;
       
   482 					break;
       
   483 				case 0x02:
       
   484 					cout << "Received a NACK packet." << endl;
       
   485 					break;
       
   486 				case 0xFF:
       
   487 					cout << "Received COMMAND NOT IMPLEMENTED." << endl;
       
   488 					break;
       
   489 				case 0x10:
       
   490 					cout << "Received IR/Key data." << endl;
       
   491 					break;
       
   492 				default:
       
   493 					cout <<"Unknown Response code 0x" << hex << buf[1] << endl;
       
   494 					break;	
       
   495 			}
       
   496 		}
       
   497 		
       
   498 	}
       
   499 	if (myflags.parse_return_clockram || myconfig.debug || myconfig.verbosity > 1) {
       
   500 		for (int i=0; i<res; i++) {
       
   501 			cout << "0x" << ((int) buf[i] < 10 ? "0" : "") << hex << (int) buf[i] << " ";
       
   502 			if (myflags.parse_return_clockram && i > 3) { 
       
   503 				switch (i) {
       
   504 					case 4:
       
   505 						cout << "(ctrl: " << dec << bcd2dec((int) buf[i]) << ") ";
       
   506 						break;
       
   507 					case 5:
       
   508 						cout << "(1/100s: " << dec << bcd2dec((int) buf[i]) << ") ";
       
   509 						break;
       
   510 					case 6:
       
   511 						cout << "(sec: " << dec << bcd2dec((int) buf[i]) << ") ";
       
   512 						break;
       
   513 					case 7:
       
   514 						cout << "(min: " << dec << bcd2dec((int) buf[i]) << ") ";
       
   515 						break;
       
   516 					case 8:
       
   517 						cout << "(hours: " << dec << bcd2dec((int) buf[i]) << ") ";
       
   518 						break;
       
   519 					case 9:
       
   520 						cout << "(year/date: " << dec << bcd2dec((int) buf[i]) << ") ";
       
   521 						break;
       
   522 					case 10:
       
   523 						cout << "(wday/month: " << dec << bcd2dec((int) buf[i]) << ") ";
       
   524 						break;
       
   525 					case 11:
       
   526 						cout << "(timer day: " << dec << bcd2dec((int) buf[i]) << ") ";
       
   527 						break;
       
   528 					case 12:
       
   529 						cout << "(alarm ctrl: " << dec << bcd2dec((int) buf[i]) << ") ";
       
   530 						break;
       
   531 					default:
       
   532 						cout << "(bcd2int: " << dec << bcd2dec((int) buf[i]) << ") ";
       
   533 						break;
       
   534 				}
       
   535 			}
       
   536 			if (i == 3 || (i+3)%8==0) cout << endl;
       
   537 		}
       
   538 		cout << endl;
       
   539 	}
       
   540 	if (myconfig.debug || myconfig.verbosity > 0) cout <<  dec << res << " bytes received.\n";
       
   541 }