00001 #include <tcl.h>
00002 #include <tk.h>
00003 #include <sys/types.h>
00004 #include <sys/stat.h>
00005 #include <sys/time.h>
00006 #include <fcntl.h>
00007 #include <termios.h>
00008 #include <stdio.h>
00009
00010 #define MAXBUF 256
00011 #define MAXSTATBUF 16
00012
00013 #define BUSY 66
00014 #define NOTBUSY 98
00015
00016 void printios(struct termios* ios);
00017 int checkstatus(int fd);
00018
00019
00020 int fd;
00021 int err = 0;
00022 struct termios ttyios;
00023 unsigned char ibuf[MAXBUF];
00024 unsigned char obuf[MAXBUF];
00025
00026 int FocusMotion_Init(Tcl_Interp*);
00027
00028
00029
00030 int FocusMotion_Open_Cmd(ClientData client_data, Tcl_Interp* interp, int argc, char *argv[])
00031 {
00032
00033 fd = open("/dev/ttya", O_RDWR | O_NOCTTY);
00034 if (fd < 0) {
00035 perror("Couldn't open terminal");
00036 return (fd);
00037 }
00038 err = tcgetattr(fd, &ttyios);
00039 if (err) {
00040 perror("Couldn't get attributes");
00041 return (TCL_ERROR);
00042 }
00043 printios(&ttyios);
00044 ttyios.c_iflag = BRKINT;
00045 ttyios.c_oflag = 0;
00046 ttyios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | CSTOPB;
00047 ttyios.c_lflag = 0;
00048 ttyios.c_cc[VMIN] = 1;
00049 ttyios.c_cc[VTIME] = 0;
00050 err = tcsetattr(fd, TCSANOW, &ttyios);
00051 if (err) {
00052 perror("Couldn't set attributes");
00053 return (TCL_ERROR);
00054 }
00055 err = tcgetattr(fd, &ttyios);
00056 if (err) {
00057 perror("Couldn't get attributes after setting");
00058 return (TCL_ERROR);
00059 }
00060 printios(&ttyios);
00061 while ((err = checkstatus(fd)) == BUSY) {};
00062 if (err < 0) return (TCL_ERROR);
00063 obuf[0] = 3; obuf[1] = 65; obuf[2] = 3; obuf[3] = 0; obuf[4] = 0;
00064 obuf[5] = 0; obuf[6] = 58;
00065 err = write(fd, &obuf, 7);
00066 if (err != 7) {
00067 perror("Couldn't set initial position");
00068 return (TCL_ERROR);
00069 }
00070 fprintf(stderr, "Set initial position\n");
00071 while ((err = checkstatus(fd)) == BUSY) {};
00072
00073 if (err < 0) {
00074 return TCL_ERROR;
00075 } else {
00076 return TCL_OK;
00077 }
00078 }
00079
00080
00081
00082
00083 int FocusMotion_MoveUp_Cmd(ClientData client_data, Tcl_Interp* interp, int argc,char *argv[])
00084 {
00085 int increment;
00086 err = 0;
00087
00088
00089 if( argc <= 1 ) {
00090 return TCL_ERROR;
00091 }
00092
00093
00094 if( Tcl_GetInt (interp, argv[1], &increment) != TCL_OK ) {
00095 return TCL_ERROR;
00096 }
00097 if( (increment < 0) || (increment > 255) ) {
00098 return TCL_ERROR;
00099 }
00100
00101
00102 while ((err = checkstatus(fd)) == BUSY) {};
00103 if (err < 0) return (TCL_ERROR);
00104 obuf[0] = 3; obuf[1] = 68; obuf[2] = 3; obuf[3] = 0; obuf[4] = (unsigned char) increment;
00105 obuf[5] = 0; obuf[6] = 58;
00106 err = write(fd, &obuf, 7);
00107 if (err != 7) {
00108 perror("Couldn't write motion increment");
00109 return (TCL_ERROR);
00110 }
00111
00112 while ((err = checkstatus(fd)) == BUSY) {};
00113 if (err < 0) return (TCL_ERROR);
00114 obuf[0] = 3; obuf[1] = 43; obuf[2] = 0; obuf[3] = 58;
00115 err = write(fd, &obuf, 4);
00116 if (err != 4) {
00117 perror("Couldn't write motion up command");
00118 return (TCL_ERROR);
00119 }
00120
00121 while ((err = checkstatus(fd)) == BUSY) {};
00122
00123
00124 if (err < 0) {
00125 return TCL_ERROR;
00126 } else {
00127 return TCL_OK;
00128 }
00129 }
00130
00131
00132
00133 int FocusMotion_MoveDown_Cmd(ClientData client_data, Tcl_Interp* interp, int argc,char *argv[])
00134 {
00135 int increment;
00136 err = 0;
00137
00138
00139 if( argc <= 1 ) {
00140 return TCL_ERROR;
00141 }
00142
00143
00144 if( Tcl_GetInt (interp, argv[1], &increment) != TCL_OK ) {
00145 return TCL_ERROR;
00146 }
00147 if( (increment < 0) || (increment > 255) ) {
00148 return TCL_ERROR;
00149 }
00150
00151
00152 while ((err = checkstatus(fd)) == BUSY) {};
00153 if (err < 0) return (TCL_ERROR);
00154 obuf[0] = 3; obuf[1] = 68; obuf[2] = 3; obuf[3] = 0; obuf[4] = (unsigned char) increment;
00155 obuf[5] = 0; obuf[6] = 58;
00156 err = write(fd, &obuf, 7);
00157 if (err != 7) {
00158 perror("Couldn't write motion increment");
00159 return (TCL_ERROR);
00160 }
00161
00162 while ((err = checkstatus(fd)) == BUSY) {};
00163 if (err < 0) return (TCL_ERROR);
00164 obuf[0] = 3; obuf[1] = 45; obuf[2] = 0; obuf[3] = 58;
00165 err = write(fd, &obuf, 4);
00166 if (err != 4) {
00167 perror("Couldn't write motion down command");
00168 return (TCL_ERROR);
00169 }
00170
00171 while ((err = checkstatus(fd)) == BUSY) {};
00172
00173
00174 if (err < 0) {
00175 return TCL_ERROR;
00176 } else {
00177 return TCL_OK;
00178 }
00179 }
00180
00181
00182 int checkstatus(int fd)
00183 {
00184 unsigned char c_ibuf[MAXSTATBUF];
00185 unsigned char c_obuf[MAXSTATBUF];
00186 const struct timespec moment = { 0, 10000000 };
00187 int rcode;
00188
00189
00190 if (rcode = nanosleep(&moment, NULL)) {
00191 fprintf(stderr, "Status code (interrupted sleep) %d.\n", rcode);
00192 return (-1);
00193 }
00194 if (tcflush(fd, TCIOFLUSH)) {
00195 perror("Couldn't flush input/output data");
00196 return (-1);
00197 }
00198 c_obuf[0] = 3; c_obuf[1] = 63; c_obuf[2] = 58;
00199 if (write(fd, &c_obuf, 3) != 3) {
00200 perror("Couldn't write request");
00201 return (-1);
00202 }
00203
00204 if (read(fd, &c_ibuf, 1) != 1) {
00205 perror("Couldn't read status");
00206 return (-1);
00207 }
00208 switch (*c_ibuf) {
00209 case BUSY:
00210
00211 break;
00212 case NOTBUSY:
00213
00214 break;
00215 default:
00216 fprintf(stderr, "?? unknown status %d\n", *c_ibuf);
00217 }
00218 return (*c_ibuf);
00219 }
00220
00221 void printios(struct termios* ios)
00222 {
00223 speed_t ospeed;
00224
00225 fprintf(stderr, "\ninput modes = %x\n", ios->c_iflag);
00226 if (ios->c_iflag & IGNBRK)
00227 fprintf(stderr, "IGNBRK\n");
00228 if (ios->c_iflag & BRKINT)
00229 fprintf(stderr, "BRKINT\n");
00230 if (ios->c_iflag & IGNPAR)
00231 fprintf(stderr, "IGNPAR\n");
00232 if (ios->c_iflag & PARMRK)
00233 fprintf(stderr, "PARMRK\n");
00234 if (ios->c_iflag & INPCK)
00235 fprintf(stderr, "INPCK\n");
00236 if (ios->c_iflag & ISTRIP)
00237 fprintf(stderr, "ISTRIP\n");
00238 if (ios->c_iflag & INLCR)
00239 fprintf(stderr, "INLCR\n");
00240 if (ios->c_iflag & IGNCR)
00241 fprintf(stderr, "IGNCR\n");
00242 if (ios->c_iflag & ICRNL)
00243 fprintf(stderr, "ICRNL\n");
00244 if (ios->c_iflag & IUCLC)
00245 fprintf(stderr, "IUCLC\n");
00246 if (ios->c_iflag & IXON)
00247 fprintf(stderr, "IXON\n");
00248 if (ios->c_iflag & IXANY)
00249 fprintf(stderr, "IXANY\n");
00250 if (ios->c_iflag & IXOFF)
00251 fprintf(stderr, "IXOFF\n");
00252 if (ios->c_iflag & IMAXBEL)
00253 fprintf(stderr, "IMAXBEL\n");
00254 if (ios->c_iflag & DOSMODE)
00255 fprintf(stderr, "DOSMODE\n");
00256 fprintf(stderr, "\noutput modes = %x\n", ios->c_oflag);
00257 if (ios->c_oflag & OPOST)
00258 fprintf(stderr, "OPOST\n");
00259 if (ios->c_oflag & OLCUC)
00260 fprintf(stderr, "OLCUC\n");
00261 if (ios->c_oflag & ONLCR)
00262 fprintf(stderr, "ONLCR\n");
00263 if (ios->c_oflag & OCRNL)
00264 fprintf(stderr, "OCRNL\n");
00265 if (ios->c_oflag & ONOCR)
00266 fprintf(stderr, "ONOCR\n");
00267 if (ios->c_oflag & ONLRET)
00268 fprintf(stderr, "ONLRET\n");
00269 if (ios->c_oflag & OFILL)
00270 fprintf(stderr, "OFILL\n");
00271 if (ios->c_oflag & OFDEL)
00272 fprintf(stderr, "OFDEL\n");
00273 if (ios->c_oflag & NLDLY)
00274 fprintf(stderr, "NL1, NLDLY\n");
00275 if ((ios->c_oflag & CRDLY) == CRDLY)
00276 fprintf(stderr, "CR3, CRDLY\n");
00277 if (ios->c_oflag & CR1)
00278 fprintf(stderr, "CR1\n");
00279 if (ios->c_oflag & CR2)
00280 fprintf(stderr, "CR2\n");
00281 if ((ios->c_oflag & TABDLY) == TABDLY)
00282 fprintf(stderr, "TAB3, TABDLY, XTABS\n");
00283 if (ios->c_oflag & TAB1)
00284 fprintf(stderr, "TAB1\n");
00285 if (ios->c_oflag & TAB2)
00286 fprintf(stderr, "TAB2\n");
00287 if (ios->c_oflag & BS1)
00288 fprintf(stderr, "BS1, BSDLY\n");
00289 if (ios->c_oflag & VT1)
00290 fprintf(stderr, "VT1, VTDLY\n");
00291 if (ios->c_oflag & FF1)
00292 fprintf(stderr, "FF1, FFDLY\n");
00293 if (ios->c_oflag & PAGEOUT)
00294 fprintf(stderr, "PAGEOUT\n");
00295 if (ios->c_oflag & WRAP)
00296 fprintf(stderr, "WRAP\n");
00297 fprintf(stderr, "\ncontrol modes = %x\n", ios->c_cflag);
00298 if ((ios->c_cflag & CS8) == CS8)
00299 fprintf(stderr, "CS8, CSIZE\n");
00300 if (ios->c_cflag & CS6)
00301 fprintf(stderr, "CS6\n");
00302 if (ios->c_cflag & CS7)
00303 fprintf(stderr, "CS7\n");
00304 if (ios->c_cflag & CSTOPB)
00305 fprintf(stderr, "CSTOPB\n");
00306 if (ios->c_cflag & CREAD)
00307 fprintf(stderr, "CREAD\n");
00308 if (ios->c_cflag & PARENB)
00309 fprintf(stderr, "PARENB\n");
00310 if (ios->c_cflag & PARODD)
00311 fprintf(stderr, "PARODD\n");
00312 if (ios->c_cflag & HUPCL)
00313 fprintf(stderr, "HUPCL\n");
00314 if (ios->c_cflag & CLOCAL)
00315 fprintf(stderr, "CLOCAL\n");
00316 if (ios->c_cflag & RCV1EN)
00317 fprintf(stderr, "RCV1EN\n");
00318 if (ios->c_cflag & XMT1EN)
00319 fprintf(stderr, "XMT1EN\n");
00320 if (ios->c_cflag & LOBLK)
00321 fprintf(stderr, "LOBLK\n");
00322 if (ios->c_cflag & XCLUDE)
00323 fprintf(stderr, "XCLUDE\n");
00324 if (ios->c_cflag & CRTSXOFF)
00325 fprintf(stderr, "CRTSXOFF\n");
00326 if (ios->c_cflag & CRTSCTS)
00327 fprintf(stderr, "CRTSCTS\n");
00328 if (ios->c_cflag & PAREXT)
00329 fprintf(stderr, "PAREXT\n");
00330 if (ios->c_cflag & CBAUDEXT)
00331 fprintf(stderr, "CBAUDEXT\n");
00332 if (ios->c_cflag & CIBAUDEXT)
00333 fprintf(stderr, "CIBAUDEXT\n");
00334 if (ios->c_cflag & CRTS_IFLOW)
00335 fprintf(stderr, "CRTS_IFLOW\n");
00336 if (ios->c_cflag & CCTS_OFLOW)
00337 fprintf(stderr, "CCTS_OFLOW\n");
00338 ospeed = (ios->c_cflag & CBAUDEXT) ? (ios->c_cflag & CBAUD) + CBAUD + 1
00339 : ios->c_cflag & CBAUD;
00340 switch (ospeed) {
00341 case B0: fprintf(stderr, "B0\n"); break;
00342 case B50: fprintf(stderr, "B50\n"); break;
00343 case B75: fprintf(stderr, "B75\n"); break;
00344 case B110: fprintf(stderr, "B110\n"); break;
00345 case B134: fprintf(stderr, "B134\n"); break;
00346 case B150: fprintf(stderr, "B150\n"); break;
00347 case B200: fprintf(stderr, "B200\n"); break;
00348 case B300: fprintf(stderr, "B300\n"); break;
00349 case B600: fprintf(stderr, "B600\n"); break;
00350 case B1200: fprintf(stderr, "B1200\n"); break;
00351 case B1800: fprintf(stderr, "B1800\n"); break;
00352 case B2400: fprintf(stderr, "B2400\n"); break;
00353 case B4800: fprintf(stderr, "B4800\n"); break;
00354 case B9600: fprintf(stderr, "B9600\n"); break;
00355 case B19200: fprintf(stderr, "B19200\n"); break;
00356 case B38400: fprintf(stderr, "B38400\n"); break;
00357 case B57600: fprintf(stderr, "B57600\n"); break;
00358 case B76800: fprintf(stderr, "B76800\n"); break;
00359 case B115200: fprintf(stderr, "B115200\n"); break;
00360 case B153600: fprintf(stderr, "B153600\n"); break;
00361 case B230400: fprintf(stderr, "B230400\n"); break;
00362 case B307200: fprintf(stderr, "B307200\n"); break;
00363 case B460800: fprintf(stderr, "B460800\n"); break;
00364 default: fprintf(stderr, "? Baud rate code %d\n", ospeed);
00365 }
00366 fprintf(stderr, "\nline dis. modes = %x\n", ios->c_lflag);
00367 if (ios->c_lflag & ISIG)
00368 fprintf(stderr, "ISIG\n");
00369 if (ios->c_lflag & ICANON)
00370 fprintf(stderr, "ICANON\n");
00371 if (ios->c_lflag & XCASE)
00372 fprintf(stderr, "XCASE\n");
00373 if (ios->c_lflag & ECHO)
00374 fprintf(stderr, "ECHO\n");
00375 if (ios->c_lflag & ECHOE)
00376 fprintf(stderr, "ECHOE\n");
00377 if (ios->c_lflag & ECHOK)
00378 fprintf(stderr, "ECHOK\n");
00379 if (ios->c_lflag & ECHONL)
00380 fprintf(stderr, "ECHONL\n");
00381 if (ios->c_lflag & NOFLSH)
00382 fprintf(stderr, "NOFLSH\n");
00383 if (ios->c_lflag & ECHOCTL)
00384 fprintf(stderr, "ECHOCTL\n");
00385 if (ios->c_lflag & ECHOPRT)
00386 fprintf(stderr, "ECHOPRT\n");
00387 if (ios->c_lflag & ECHOKE)
00388 fprintf(stderr, "ECHOKE\n");
00389 if (ios->c_lflag & DEFECHO)
00390 fprintf(stderr, "DEFECHO\n");
00391 if (ios->c_lflag & FLUSHO)
00392 fprintf(stderr, "FLUSHO\n");
00393 if (ios->c_lflag & PENDIN)
00394 fprintf(stderr, "PENDIN\n");
00395 if (ios->c_lflag & IEXTEN)
00396 fprintf(stderr, "IEXTEN\n");
00397
00398 }
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410 int FocusMotion_Init(Tcl_Interp *interp) {
00411 Tcl_CreateCommand(interp, "FocusMotion_Open", FocusMotion_Open_Cmd,
00412 (ClientData) NULL, NULL);
00413 Tcl_CreateCommand(interp, "FocusMotion_MoveUp", FocusMotion_MoveUp_Cmd,
00414 (ClientData) NULL, NULL);
00415 Tcl_CreateCommand(interp, "FocusMotion_MoveDown", FocusMotion_MoveDown_Cmd,
00416 (ClientData) NULL, NULL);
00417
00418 return TCL_OK;
00419 }