tools/picctldisplaytest/src/picctldisplaytest.cpp
changeset 2 2f55e5dd591d
child 31 4567e7bc404c
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/tools/picctldisplaytest/src/picctldisplaytest.cpp	Tue Jan 29 22:31:52 2008 +0100
     1.3 @@ -0,0 +1,541 @@
     1.4 +/***************************************************************************
     1.5 + *   Copyright (C) 2008 by Peter Marquardt   *
     1.6 + *   p_marquardt@users.sourceforge.net   *
     1.7 + *   code base Copyright (C) 2007 by Carsten Presser   *
     1.8 + *                                                                         *
     1.9 + *   This program is free software; you can redistribute it and/or modify  *
    1.10 + *   it under the terms of the GNU General Public License as published by  *
    1.11 + *   the Free Software Foundation; either version 2 of the License, or     *
    1.12 + *   (at your option) any later version.                                   *
    1.13 + *                                                                         *
    1.14 + *   This program is distributed in the hope that it will be useful,       *
    1.15 + *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
    1.16 + *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
    1.17 + *   GNU General Public License for more details.                          *
    1.18 + *                                                                         *
    1.19 + *   You should have received a copy of the GNU General Public License     *
    1.20 + *   along with this program; if not, write to the                         *
    1.21 + *   Free Software Foundation, Inc.,                                       *
    1.22 + *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
    1.23 + ***************************************************************************/
    1.24 +
    1.25 +/*! \file pcctldisplaytest.cpp
    1.26 +\brief A utility to test the picctl lcd display and interface
    1.27 +\author Peter Marquardt p_marquardt@users.sourceforge.net
    1.28 +\author Carsten Presser
    1.29 +\todo sanitize command line argument parsing
    1.30 +*/
    1.31 +
    1.32 +#ifdef HAVE_CONFIG_H
    1.33 +#include <config.h>
    1.34 +#endif
    1.35 +#include <iostream>
    1.36 +#include <cstdlib>
    1.37 +#include <termios.h>
    1.38 +#include <signal.h>
    1.39 +#include <fcntl.h>
    1.40 +#include "picctldisplaytest.h"
    1.41 +
    1.42 +using namespace std;
    1.43 +config myconfig;
    1.44 +runtime_flags myflags;
    1.45 +int fd;
    1.46 +
    1.47 +int main(int argc, char *argv[])
    1.48 +{
    1.49 +	bool kill_flag = false;
    1.50 +	struct termios options;
    1.51 +	struct sigaction saio;
    1.52 +	char key;
    1.53 +		
    1.54 +	cout << "** picctldisplaytest - simple test utility for picctl lcd displays **" << endl
    1.55 +		<< ">";
    1.56 +	
    1.57 +	// setting defaults
    1.58 +	myconfig.debug = false;
    1.59 +	myconfig.verbosity = 0;
    1.60 +	myconfig.modem_device = "/dev/ttyACM0";
    1.61 +	myflags.parse_return_clockram = false;
    1.62 +	
    1.63 +	// parsing arguments
    1.64 +	for (int i = 1; i < argc; i++) {
    1.65 +		if (*argv[i] == 'd') {
    1.66 +			i++;
    1.67 +			myconfig.modem_device = argv[i];
    1.68 +		}
    1.69 +		else if (*argv[i] == 'v') {
    1.70 +			i++;
    1.71 +			myconfig.verbosity = atoi(argv[i]);
    1.72 +		}
    1.73 +		else if (*argv[i] == 'D') {
    1.74 +			myconfig.debug =true;
    1.75 +		}
    1.76 +	}
    1.77 +	
    1.78 +	if (myconfig.verbosity > 0 || myconfig.debug) {
    1.79 +		cout << "picctldisplaytest called with\n"
    1.80 +			<< "device: " << myconfig.modem_device << endl
    1.81 +			<< "verbosity: " << myconfig.verbosity << endl
    1.82 +			<< "debug mode:" << boolalpha << myconfig.debug << endl;
    1.83 +	}
    1.84 +	
    1.85 +	/* open the device to be non-blocking (read will return immediatly) */
    1.86 +	fd = open(myconfig.modem_device, O_RDWR | O_NOCTTY | O_NONBLOCK);
    1.87 +	if (fd <0) {perror(myconfig.modem_device); exit(-1); }
    1.88 +
    1.89 +	/* install the signal handler before making the device asynchronous */
    1.90 +	saio.sa_handler = signal_handler_IO;
    1.91 +	sigemptyset (&saio.sa_mask);
    1.92 +	saio.sa_flags = 0;
    1.93 +	saio.sa_restorer = NULL;
    1.94 +	sigaction(SIGIO,&saio,NULL);
    1.95 +   // allow the process to receive SIGIO
    1.96 +	fcntl(fd, F_SETOWN, getpid());
    1.97 +   // Make the file descriptor asynchronous
    1.98 +	fcntl(fd, F_SETFL, FASYNC);
    1.99 +
   1.100 +	tcgetattr(fd, &options);
   1.101 +
   1.102 +	cfsetispeed(&options, BAUDRATE);
   1.103 +	cfsetospeed(&options, BAUDRATE);
   1.104 +
   1.105 +	options.c_cflag &= ~PARENB;
   1.106 +	options.c_cflag &= ~CSTOPB;
   1.107 +	options.c_cflag &= ~CSIZE;
   1.108 +	options.c_cflag |= CS8;
   1.109 +
   1.110 +	options.c_cflag &= ~CRTSCTS;
   1.111 +	options.c_cflag |= (CLOCAL | CREAD);
   1.112 +	options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
   1.113 +	options.c_iflag &= ~(IXON | IXOFF | IXANY);
   1.114 +	options.c_oflag &= ~OPOST;
   1.115 +	tcsetattr(fd, TCSANOW, &options);
   1.116 +
   1.117 +	if (myconfig.debug || myconfig.verbosity > 0) print_help();
   1.118 +
   1.119 +	while ( cin.get(key)) {
   1.120 +		switch(key) {
   1.121 +			case 'q':
   1.122 +				cout << "Exiting." << endl;
   1.123 +				return EXIT_SUCCESS;
   1.124 +				break;
   1.125 +			case 'u':
   1.126 +				cout << "Switching to unmanaged mode..." << endl;
   1.127 +				send_data(CMD_SET_MODE_UNMANAGED,(sizeof(CMD_SET_MODE_UNMANAGED)/sizeof(char)));
   1.128 +				break;
   1.129 +			case 'm':
   1.130 +				cout << "Switching to managed mode..." << endl;
   1.131 +				send_data(CMD_SET_MODE_MANAGED,(sizeof(CMD_SET_MODE_MANAGED)/sizeof(char)));
   1.132 +				break;		 
   1.133 +			case 'c':
   1.134 +				cout << "Sending Clear Display..." << endl;
   1.135 +				send_data(CMD_DISP_CLEAR_SCREEN,(sizeof(CMD_DISP_CLEAR_SCREEN)/sizeof(char)));
   1.136 +				break;
   1.137 +			case 'h':
   1.138 +				print_help();
   1.139 +				break;
   1.140 +			case 'j':
   1.141 +				print_cli_options();
   1.142 +				break;
   1.143 +			case '1':
   1.144 +				cout << "Display CG ROM charset..." << endl;
   1.145 +				send_data(TEST_STRING_1,(sizeof(TEST_STRING_1)/sizeof(char)));
   1.146 +				send_data(TEST_STRING_2,(sizeof(TEST_STRING_2)/sizeof(char)));
   1.147 +				send_data(TEST_STRING_3,(sizeof(TEST_STRING_3)/sizeof(char)));
   1.148 +				break;
   1.149 +			case '2':
   1.150 +				cout << "Filling the Display with CG ROM charset..." << endl;
   1.151 +				send_data(TEST_STRING_1,(sizeof(TEST_STRING_1)/sizeof(char)));
   1.152 +				send_data(TEST_STRING_2,(sizeof(TEST_STRING_2)/sizeof(char)));
   1.153 +				send_data(TEST_STRING_3,(sizeof(TEST_STRING_3)/sizeof(char)));
   1.154 +				send_data(TEST_STRING_4,(sizeof(TEST_STRING_4)/sizeof(char)));
   1.155 +				send_data(TEST_STRING_5,(sizeof(TEST_STRING_5)/sizeof(char)));
   1.156 +				break;
   1.157 +			case '3': {
   1.158 +				cout << "Sending Test String... one line per packet, 8 lines of 30 chars" << endl;
   1.159 +				for (int j = 0; j < 8; j++) {
   1.160 +					const unsigned char cmd[] = {0xAA,0x14,0x00,32,((j*30)),0x08,
   1.161 +						16,17,18,19,20,21,22,23,24,25,
   1.162 +						16,17,18,19,20,21,22,23,24,25,
   1.163 +						16,17,18,19,20,21,22,23,24,25};
   1.164 +					send_data(cmd,(sizeof(cmd)/sizeof(char)));
   1.165 +				}
   1.166 +		}
   1.167 +				break;
   1.168 +			case '4':
   1.169 +				cout << "Sending Test String.. one char per packet,8 lines of 30 chars" << endl;
   1.170 +				for (int j = 0; j < 8; j++) {
   1.171 +					for (int k = 0; k < 30; k++) {
   1.172 +						const unsigned char cmd[] = {0xAA,0x14,0x00,3,k+(j*30),0x08,
   1.173 +							(16+k)};
   1.174 +							send_data(cmd,(sizeof(cmd)/sizeof(char)));
   1.175 +					}
   1.176 +				}
   1.177 +				break;
   1.178 +			
   1.179 +			case 'a':
   1.180 +				cout << "Set PWM1 0%..." << endl;
   1.181 +				CMD_SET_PWM1[4] = 0x00;
   1.182 +				send_data(CMD_SET_PWM1,(sizeof(CMD_SET_PWM1)/sizeof(char)));
   1.183 +				break;
   1.184 +			case 's':
   1.185 +				cout << "SetPWM1 25%..." << endl;
   1.186 +				CMD_SET_PWM1[4] = 0x40;
   1.187 +				send_data(CMD_SET_PWM1,(sizeof(CMD_SET_PWM1)/sizeof(char)));
   1.188 +				break;
   1.189 +			case 'd':
   1.190 +				cout << "Set PWM1 50%..." << endl;
   1.191 +				CMD_SET_PWM1[4] = 0x80;
   1.192 +				send_data(CMD_SET_PWM1,(sizeof(CMD_SET_PWM1)/sizeof(char)));
   1.193 +				break;
   1.194 +			case 'f':
   1.195 +				cout << "Set PWM1 75%..." << endl;
   1.196 +				CMD_SET_PWM1[4] = 0xC0;
   1.197 +				send_data(CMD_SET_PWM1,(sizeof(CMD_SET_PWM1)/sizeof(char)));
   1.198 +				break;
   1.199 +			case 'g':
   1.200 +				cout << "Set PWM1 100%..." << endl;
   1.201 +				CMD_SET_PWM1[4] = 0xFF;
   1.202 +				send_data(CMD_SET_PWM1,(sizeof(CMD_SET_PWM1)/sizeof(char)));
   1.203 +				break;
   1.204 +			case 'A':
   1.205 +				cout << "Set PWM2 0%..." << endl;
   1.206 +				CMD_SET_PWM2[4] = 0x00;
   1.207 +				send_data(CMD_SET_PWM2,(sizeof(CMD_SET_PWM2)/sizeof(char)));
   1.208 +				break;
   1.209 +			case 'S':
   1.210 +				cout << "SetPWM2 25%..." << endl;
   1.211 +				CMD_SET_PWM2[4] = 0x40;
   1.212 +				send_data(CMD_SET_PWM2,(sizeof(CMD_SET_PWM2)/sizeof(char)));
   1.213 +				break;
   1.214 +			case 'D':
   1.215 +				cout << "Set PWM2 50%..." << endl;
   1.216 +				CMD_SET_PWM2[4] = 0x80;
   1.217 +				send_data(CMD_SET_PWM2,(sizeof(CMD_SET_PWM2)/sizeof(char)));
   1.218 +				break;
   1.219 +			case 'F':
   1.220 +				cout << "Set PWM2 75%..." << endl;
   1.221 +				CMD_SET_PWM2[4] = 0xC0;
   1.222 +				send_data(CMD_SET_PWM2,(sizeof(CMD_SET_PWM2)/sizeof(char)));
   1.223 +				break;
   1.224 +			case 'G':
   1.225 +				cout << "Set PWM2 100%..." << endl;
   1.226 +				CMD_SET_PWM2[4] = 0xFF;
   1.227 +				send_data(CMD_SET_PWM2,(sizeof(CMD_SET_PWM2)/sizeof(char)));
   1.228 +				break;
   1.229 +			case 'T': {
   1.230 +				cout << "Setting pcf8583 clock memory..." << endl;	
   1.231 +				time_t mytime = time(NULL);
   1.232 +				tm * myltime = localtime( &mytime);
   1.233 +				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;
   1.234 +				const unsigned char tcmd[] = {0xAA,0x41,0x00,0x10,
   1.235 +					0x04,0x00,dec2bcd(myltime->tm_sec),dec2bcd(myltime->tm_min),dec2bcd(myltime->tm_hour),dec2bcd(myltime->tm_mday),
   1.236 +					(dec2bcd(myltime->tm_mon+1)),0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
   1.237 +					send_data(tcmd,(sizeof(tcmd)/sizeof(char)));
   1.238 +				}
   1.239 +				break;
   1.240 +			case 't' : {
   1.241 +				cout << "Dumping pcf8583 clock memory..." << endl;
   1.242 +				int oldverbosity = myconfig.verbosity;
   1.243 +				myflags.parse_return_clockram = true;
   1.244 +				if (myconfig.verbosity < 2) {
   1.245 +					myconfig.verbosity = 2;
   1.246 +				}
   1.247 +				send_data(CMD_GET_CLOCK_MEMORY,(sizeof(CMD_GET_CLOCK_MEMORY)/sizeof(char)));
   1.248 +				myconfig.verbosity  = oldverbosity;
   1.249 +				myflags.parse_return_clockram = false;
   1.250 +				}
   1.251 +				break;
   1.252 +			case '5': {
   1.253 +				cout << "Showing test picture 1..."<< endl;
   1.254 +				write_gfx_ram( TEST_PICTURE_1,(sizeof(TEST_PICTURE_1)/sizeof(char)));
   1.255 +			}
   1.256 +				break;
   1.257 +			case '6': {
   1.258 +				cout << "Showing test picture 2 - horizontal lines..."<< endl;
   1.259 +				unsigned char mycmd[36] = {0xAA,0x14,0x00,0x20,0x00,0x00,
   1.260 +					0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
   1.261 +					0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
   1.262 +					0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
   1.263 +				} ;
   1.264 +				for (int i = 0; i <64;i+=2) {
   1.265 +					mycmd[5] = (i*30) / 256;
   1.266 +					mycmd[4] = (i*30) - (256 * mycmd[5]);
   1.267 +					send_data(mycmd, (sizeof(mycmd)/sizeof(char)));
   1.268 +				}
   1.269 +			}
   1.270 +				break;
   1.271 +			case '7': {
   1.272 +				cout << "Showing test picture 3 - vertical lines..."<< endl;
   1.273 +				unsigned char mycmd[36] = {0xAA,0x14,0x00,0x20,0x00,0x00,
   1.274 +					0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
   1.275 +					0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
   1.276 +					0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
   1.277 +				} ;
   1.278 +				for (int i = 0; i <64;i++) {
   1.279 +					mycmd[5] = (i*30) / 256;
   1.280 +					mycmd[4] = (i*30) - (256 * mycmd[5]);
   1.281 +					send_data(mycmd, (sizeof(mycmd)/sizeof(char)));
   1.282 +				}
   1.283 +			}
   1.284 +				break;
   1.285 +			case '8': {
   1.286 +				cout << "Showing test picture 4...Boxes"<< endl;
   1.287 +				write_gfx_ram(TEST_PICTURE_2,(sizeof(TEST_PICTURE_2)/sizeof(char)));
   1.288 +			}
   1.289 +				break;
   1.290 +			case '9': {
   1.291 +				cout << "Showing test picture 5 - outline + center cross..."<< endl;
   1.292 +				unsigned char mycmd_1[36] = {0xAA,0x14,0x00,0x20,0x00,0x00,
   1.293 +					0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
   1.294 +					0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
   1.295 +					0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
   1.296 +				} ;
   1.297 +				unsigned char mycmd_2[36] = {0xAA,0x14,0x00,0x20,0x00,0x00,
   1.298 +					0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
   1.299 +					0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,
   1.300 +					0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01
   1.301 +				} ;
   1.302 +				int i = 1;
   1.303 +				for (int j = 0;j<2;j++) {
   1.304 +					send_data(mycmd_1, (sizeof(mycmd_1)/sizeof(char)));
   1.305 +					for ( i = 1; i <31;i++) {
   1.306 +						mycmd_2[5] = ((i*30) + (j*960)) / 256;
   1.307 +						mycmd_2[4] = ((i*30) + (j*960))  - (256 * mycmd_2[5]);
   1.308 +						send_data(mycmd_2, (sizeof(mycmd_2)/sizeof(char)));
   1.309 +					}
   1.310 +					mycmd_1[5] = ((i*30) + (j*960)) / 256;
   1.311 +					mycmd_1[4] = ((i*30) + (j*960))  - (256 * mycmd_1[5]);
   1.312 +				}
   1.313 +				send_data(mycmd_1, (sizeof(mycmd_1)/sizeof(char)));
   1.314 +			}
   1.315 +				break;
   1.316 +
   1.317 +			default:
   1.318 +				break;
   1.319 +		}
   1.320 +		sleep(1);
   1.321 +		if (key != 0x13 && key != '\n') cout << ">";
   1.322 +	}
   1.323 +	close(fd);
   1.324 +	return EXIT_SUCCESS;
   1.325 +}
   1.326 +
   1.327 +unsigned char bitendian (unsigned char in)
   1.328 +{
   1.329 +	unsigned char ret = 0x00;
   1.330 +	if (in & 0x01) ret+=0x80;
   1.331 +	if (in & 0x02) ret+=0x40;
   1.332 +	if (in & 0x04) ret+=0x20;
   1.333 +	if (in & 0x08) ret+=0x10;
   1.334 +	if (in & 0x10) ret+=0x08;
   1.335 +	if (in & 0x20) ret+=0x04;
   1.336 +	if (in & 0x40) ret+=0x02;
   1.337 +	if (in & 0x80) ret+=0x01;
   1.338 +
   1.339 +	return (ret);
   1.340 +}
   1.341 +
   1.342 +
   1.343 +bool write_gfx_ram(const unsigned char * buffer, int numbytes) {
   1.344 +	if (numbytes > 1920) {
   1.345 +		cout << "Too much data for gfx RAM, ignoring..." << endl;
   1.346 +		return false;
   1.347 +	}
   1.348 +	int i = 0, offset = 6, memaddr = 0;
   1.349 +	bool all_sent = false;
   1.350 +	unsigned char mycmd[63] = {0xAA,0x14,0x00,0x02,0x00,0x00};
   1.351 +	while (i <numbytes) {
   1.352 +		all_sent = false;
   1.353 +		mycmd[offset] = bitendian(buffer[i]);
   1.354 +		i++;	
   1.355 +		offset++;
   1.356 +		if (offset == 63) {
   1.357 +			mycmd[3] = 59;
   1.358 +			send_data(mycmd,63);
   1.359 +			memaddr += 57;
   1.360 +			mycmd[5] = (memaddr / 256);
   1.361 +			mycmd[4] = (memaddr - (mycmd[5]*256));
   1.362 +			offset = 6;
   1.363 +			all_sent = true;
   1.364 +		}
   1.365 +	}
   1.366 +	if (!all_sent) {
   1.367 +		mycmd[3] = (offset-4);
   1.368 +		send_data(mycmd,offset);
   1.369 +	}
   1.370 +	return true;
   1.371 +}
   1.372 +
   1.373 +/*! \brief sends size bytes of buffer data to the display
   1.374 +
   1.375 +\warning send_data doesn't check if buffer really is numbytes big. Expect all kind of weirdness if abused.
   1.376 +\param buffer pointer to a char buffer conatining the data
   1.377 +\param numbytes Number of bytes in buffer
   1.378 +*/
   1.379 +bool send_data(const unsigned char * buffer, int numbytes) {
   1.380 +	if (numbytes > 64 ) {
   1.381 +		cout << "Buffer size exceeds 64 Bytes, send_data aborted." << endl;
   1.382 +		return false;
   1.383 +	}
   1.384 +	write(fd,buffer,numbytes);
   1.385 +	if (myconfig.debug || myconfig.verbosity > 0) cout << numbytes <<" bytes sent.";
   1.386 +	if (myconfig.debug || myconfig.verbosity > 1) {
   1.387 +		cout <<" Data: " << endl ;
   1.388 +		for ( int i = 0; i <numbytes; i++) {
   1.389 +			cout << " 0x" << ((int) buffer[i] < 10 ? "0" : "") << hex << (int) buffer[i] << dec;
   1.390 +			if (i > 0 && ((i-3)%8 ==0 || i == 3)) cout << endl;
   1.391 +		}
   1.392 +	}
   1.393 +	if (myconfig.debug || myconfig.verbosity > 0) cout <<   endl;
   1.394 +	usleep(100000);
   1.395 +	return true;
   1.396 +}
   1.397 +
   1.398 +/*! \brief prints some help
   1.399 +*/
   1.400 +void print_help() {
   1.401 +	cout << endl;
   1.402 +	cout << "Usage:" << endl;
   1.403 +	cout << "u\tset unmanaged mode" << endl;
   1.404 +	cout << "m\tset managed mode" << endl;
   1.405 +	cout << endl;
   1.406 +	cout << "T\tset pcf8583 clock to system time" << endl;
   1.407 +	cout << "t\tdump pcf8583 clock memory" << endl;
   1.408 +	cout << endl;
   1.409 +	cout << "Set PWM:" << endl;
   1.410 +	cout << "PWM1\ta 0%\ts 25%\td 50%\tf 75%\tg 100%" << endl;
   1.411 +	cout << "PWM2\tA 0%\tS 25%\tD 50%\tF 75%\tG 100%" << endl;
   1.412 +	cout << endl;
   1.413 +	cout << "1\tshow ROM charset" << endl;
   1.414 +	cout << "2\tfill Text area with ROM charset" << endl;
   1.415 +	cout << "3\tfill Text area (8 lines / 30 chars, one line per packet)" << endl;
   1.416 +	cout << "4\tfill Text area (8 lines / 30 chars, one char per packet)" << endl;
   1.417 +	cout << endl;
   1.418 +	cout << "5\tshow test picture 1 (240x64px)" << endl;
   1.419 +	cout << "6\tshow test picture 2 - horizontal lines (240x64px)" << endl;
   1.420 +	cout << "7\tshow test picture 3 - vertical lines (240x64px)" << endl;
   1.421 +	cout << "8\tshow test picture 4 - Boxes (240x64px)" << endl;
   1.422 +	cout << "9\tshow test picture 5 - outline + center cross (240x64px)" << endl;
   1.423 +	cout << endl;
   1.424 +	cout << "c\tclear display" << endl;
   1.425 +	cout << endl;
   1.426 +	cout << "h\tprint this help" << endl;
   1.427 +	cout << "j\tprint command line options" << endl;
   1.428 +	cout << "q\tquit" << endl;
   1.429 +	cout << ">";
   1.430 +}
   1.431 +
   1.432 +/*! \brief prints command line options
   1.433 +*/
   1.434 +void print_cli_options() {
   1.435 +	cout << endl 
   1.436 +		<< " Command line options:\n"
   1.437 +		<< endl;
   1.438 +	cout << "d DEVICE\n"
   1.439 +		<< "\tSets the display device to DEVICE, default value is /dev/ttyACM0\n"
   1.440 +		<< "\tExample:\n"
   1.441 +		<< "\tpicctldisplaytest d /dev/ttyACM0\n"
   1.442 +		<< endl;
   1.443 +	cout << "v VERBOSITY\n"
   1.444 +			<< "\tSets verbosity to level VERBOSITY ( Range: 0-2, default 0 )\n"
   1.445 +			<< "\tExample:\n"
   1.446 +			<< "\tpicctldisplaytest v 1\n"
   1.447 +			<< endl;
   1.448 +	cout << "D\n"
   1.449 +			<< "\tRun in debugging mode (aka. very verbose)\n"
   1.450 +			<< "\tExample:\n"
   1.451 +			<< "\tpicctldisplaytest D\n"
   1.452 +			<< endl;
   1.453 +	cout << "Combining command line options\n"
   1.454 +			<< "\tAll command line options can be combined (though some combinations might not prove useful).\n"
   1.455 +			<< "\tExample:\n"
   1.456 +			<< "\tpicctldisplaytest D d /dev/ttyACM0\n"
   1.457 +			<< endl;
   1.458 +}
   1.459 +
   1.460 +/*! \brief encodes an integer to a BCD value
   1.461 + */
   1.462 +int dec2bcd(int decimal) {
   1.463 +	return  (decimal > 99 ?  false : ((decimal/10)<<4)+(decimal%10));
   1.464 +}
   1.465 +
   1.466 +/*! \brief decodes a BCD value and returns it as integer
   1.467 + */
   1.468 +int bcd2dec(int bcd) {
   1.469 +	return (((bcd>>4)*10)+bcd%16);
   1.470 +}
   1.471 +
   1.472 +/*! \brief handles SIGIO
   1.473 + */
   1.474 +void signal_handler_IO (int status) {
   1.475 +	
   1.476 +	unsigned char buf[255];
   1.477 +	int res = read(fd,buf,255);
   1.478 +	
   1.479 +	if (myconfig.debug || myconfig.verbosity > 0) {
   1.480 +		//cout << "Received Data\n";
   1.481 +		if (buf[0] == 0x55) {
   1.482 +			switch (buf[1]) {
   1.483 +				case 0x01:
   1.484 +					cout << "Received an ACK packet, payload: " << (int) buf[3] << " bytes." << endl;
   1.485 +					break;
   1.486 +				case 0x02:
   1.487 +					cout << "Received a NACK packet." << endl;
   1.488 +					break;
   1.489 +				case 0xFF:
   1.490 +					cout << "Received COMMAND NOT IMPLEMENTED." << endl;
   1.491 +					break;
   1.492 +				case 0x10:
   1.493 +					cout << "Received IR/Key data." << endl;
   1.494 +					break;
   1.495 +				default:
   1.496 +					cout <<"Unknown Response code 0x" << hex << buf[1] << endl;
   1.497 +					break;	
   1.498 +			}
   1.499 +		}
   1.500 +		
   1.501 +	}
   1.502 +	if (myflags.parse_return_clockram || myconfig.debug || myconfig.verbosity > 1) {
   1.503 +		for (int i=0; i<res; i++) {
   1.504 +			cout << "0x" << ((int) buf[i] < 10 ? "0" : "") << hex << (int) buf[i] << " ";
   1.505 +			if (myflags.parse_return_clockram && i > 3) { 
   1.506 +				switch (i) {
   1.507 +					case 4:
   1.508 +						cout << "(ctrl: " << dec << bcd2dec((int) buf[i]) << ") ";
   1.509 +						break;
   1.510 +					case 5:
   1.511 +						cout << "(1/100s: " << dec << bcd2dec((int) buf[i]) << ") ";
   1.512 +						break;
   1.513 +					case 6:
   1.514 +						cout << "(sec: " << dec << bcd2dec((int) buf[i]) << ") ";
   1.515 +						break;
   1.516 +					case 7:
   1.517 +						cout << "(min: " << dec << bcd2dec((int) buf[i]) << ") ";
   1.518 +						break;
   1.519 +					case 8:
   1.520 +						cout << "(hours: " << dec << bcd2dec((int) buf[i]) << ") ";
   1.521 +						break;
   1.522 +					case 9:
   1.523 +						cout << "(year/date: " << dec << bcd2dec((int) buf[i]) << ") ";
   1.524 +						break;
   1.525 +					case 10:
   1.526 +						cout << "(wday/month: " << dec << bcd2dec((int) buf[i]) << ") ";
   1.527 +						break;
   1.528 +					case 11:
   1.529 +						cout << "(timer day: " << dec << bcd2dec((int) buf[i]) << ") ";
   1.530 +						break;
   1.531 +					case 12:
   1.532 +						cout << "(alarm ctrl: " << dec << bcd2dec((int) buf[i]) << ") ";
   1.533 +						break;
   1.534 +					default:
   1.535 +						cout << "(bcd2int: " << dec << bcd2dec((int) buf[i]) << ") ";
   1.536 +						break;
   1.537 +				}
   1.538 +			}
   1.539 +			if (i == 3 || (i+3)%8==0) cout << endl;
   1.540 +		}
   1.541 +		cout << endl;
   1.542 +	}
   1.543 +	if (myconfig.debug || myconfig.verbosity > 0) cout <<  dec << res << " bytes received.\n";
   1.544 +}