blob: c147353033c68c6c917c0b274f7918f8436a05b0 [file] [log] [blame]
wdenkf5300ab2003-09-12 15:35:15 +00001/*
2 * (C) Copyright 2003
3 * Martin Krause, TQ-Systems GmbH, martin.krause@tqs.de
4 *
5 * See file CREDITS for list of people who contributed to this
6 * project.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21 * MA 02111-1307 USA
22 */
23
24#define DEBUG
25
26#include <common.h>
27#include <exports.h>
28#include <s3c2400.h>
29#include "tsc2000.h"
30#include "rs485.h"
31
32/* assignment of CPU internal ADC channels with TRAB hardware */
33#define VCC5V 2
34#define VCC12V 3
35
36/* CPLD-Register for controlling TRAB hardware functions */
37#define CPLD_BUTTONS ((volatile unsigned long *)0x04020000)
38#define CPLD_FILL_LEVEL ((volatile unsigned long *)0x04008000)
39#define CPLD_ROTARY_SWITCH ((volatile unsigned long *)0x04018000)
40#define CPLD_RS485_RE ((volatile unsigned long *)0x04028000)
41
42/* timer configuration bits for buzzer and PWM */
43#define START2 (1 << 12)
44#define UPDATE2 (1 << 13)
45#define INVERT2 (1 << 14)
46#define RELOAD2 (1 << 15)
47#define START3 (1 << 16)
48#define UPDATE3 (1 << 17)
49#define INVERT3 (1 << 18)
50#define RELOAD3 (1 << 19)
51
52#define PCLK 66000000
53#define BUZZER_FREQ 1000 /* frequency in Hz */
54#define BUZZER_TIME 1000000 /* time in us */
55#define PWM_FREQ 500
56
57
58/* definitions of I2C EEPROM device address */
59#define I2C_EEPROM_DEV_ADDR 0x54
60
61/* definition for touch panel calibration points */
62#define CALIB_TL 0 /* calibration point in (T)op (L)eft corner */
63#define CALIB_DR 1 /* calibration point in (D)own (R)ight corner */
64
65/* EEPROM addresse map */
66#define SERIAL_NUMBER 8
67#define TOUCH_X0 52
68#define TOUCH_Y0 54
69#define TOUCH_X1 56
70#define TOUCH_Y1 58
71#define CRC16 60
72
73/* EEPROM stuff */
74#define EEPROM_MAX_CRC_BUF 64
75
76/* RS485 stuff */
77#define RS485_MAX_RECEIVE_BUF_LEN 100
78
79/* Bit definitions for ADCCON */
80#define ADC_ENABLE_START 0x1
81#define ADC_READ_START 0x2
82#define ADC_STDBM 0x4
83#define ADC_INP_AIN0 (0x0 << 3)
84#define ADC_INP_AIN1 (0x1 << 3)
85#define ADC_INP_AIN2 (0x2 << 3)
86#define ADC_INP_AIN3 (0x3 << 3)
87#define ADC_INP_AIN4 (0x4 << 3)
88#define ADC_INP_AIN5 (0x5 << 3)
89#define ADC_INP_AIN6 (0x6 << 3)
90#define ADC_INP_AIN7 (0x7 << 3)
91#define ADC_PRSCEN 0x4000
92#define ADC_ECFLG 0x8000
93
94/* function test functions */
95int do_dip (void);
96int do_info (void);
97int do_vcc5v (void);
98int do_vcc12v (void);
99int do_buttons (void);
100int do_fill_level (void);
101int do_rotary_switch (void);
102int do_pressure (void);
103int do_v_bat (void);
104int do_vfd_id (void);
105int do_buzzer (void);
106int do_led (char **);
107int do_full_bridge (char **);
108int do_dac (char **);
109int do_motor_contact (void);
110int do_motor (char **);
111int do_pwm (char **);
112int do_thermo (char **);
113int do_touch (char **);
114int do_rs485 (char **);
115int do_serial_number (char **);
116int do_crc16 (void);
117
118/* helper functions */
119static void adc_init (void);
120static int adc_read (unsigned int channel);
121static void print_identifier (void);
122static void touch_wait_pressed (void);
123static void touch_read_x_y (int *x, int *y);
124static int touch_write_clibration_values (int calib_point, int x, int y);
125static int rs485_send_line (const char *data);
126static int rs485_receive_chars (char *data, int timeout);
127static unsigned short updcrc(unsigned short icrc, unsigned char *icp,
128 unsigned int icnt);
129
130
131/*
132 * TRAB board specific commands. Especially commands for burn-in and function
133 * test.
134 */
135
136int trab_fkt (int argc, char *argv[])
137{
138 int i;
139
140 app_startup(argv);
141 if (get_version () != XF_VERSION) {
142 printf ("Wrong XF_VERSION. Please re-compile with actual "
143 "u-boot sources\n");
144 printf ("Example expects ABI version %d\n", XF_VERSION);
145 printf ("Actual U-Boot ABI version %d\n", (int)get_version());
146 return 1;
147 }
148
149 debug ("argc = %d\n", argc);
150
151 for (i=0; i<=argc; ++i) {
152 debug ("argv[%d] = \"%s\"\n", i, argv[i] ? argv[i] : "<NULL>");
153 }
154
155 adc_init ();
156
157 switch (argc) {
158
159 case 0:
160 case 1:
161 break;
162
163 case 2:
164 if (strcmp (argv[1], "info") == 0) {
165 return (do_info ());
166 }
167 if (strcmp (argv[1], "dip") == 0) {
168 return (do_dip ());
169 }
170 if (strcmp (argv[1], "vcc5v") == 0) {
171 return (do_vcc5v ());
172 }
173 if (strcmp (argv[1], "vcc12v") == 0) {
174 return (do_vcc12v ());
175 }
176 if (strcmp (argv[1], "buttons") == 0) {
177 return (do_buttons ());
178 }
179 if (strcmp (argv[1], "fill_level") == 0) {
180 return (do_fill_level ());
181 }
182 if (strcmp (argv[1], "rotary_switch") == 0) {
183 return (do_rotary_switch ());
184 }
185 if (strcmp (argv[1], "pressure") == 0) {
186 return (do_pressure ());
187 }
188 if (strcmp (argv[1], "v_bat") == 0) {
189 return (do_v_bat ());
190 }
191 if (strcmp (argv[1], "vfd_id") == 0) {
192 return (do_vfd_id ());
193 }
194 if (strcmp (argv[1], "buzzer") == 0) {
195 return (do_buzzer ());
196 }
197 if (strcmp (argv[1], "motor_contact") == 0) {
198 return (do_motor_contact ());
199 }
200 if (strcmp (argv[1], "crc16") == 0) {
201 return (do_crc16 ());
202 }
203 break;
204
205 case 3:
206 if (strcmp (argv[1], "full_bridge") == 0) {
207 return (do_full_bridge (argv));
208 }
209 if (strcmp (argv[1], "dac") == 0) {
210 return (do_dac (argv));
211 }
212 if (strcmp (argv[1], "motor") == 0) {
213 return (do_motor (argv));
214 }
215 if (strcmp (argv[1], "pwm") == 0) {
216 return (do_pwm (argv));
217 }
218 if (strcmp (argv[1], "thermo") == 0) {
219 return (do_thermo (argv));
220 }
221 if (strcmp (argv[1], "touch") == 0) {
222 return (do_touch (argv));
223 }
224 if (strcmp (argv[1], "serial_number") == 0) {
225 return (do_serial_number (argv));
226 }
227 break;
228
229 case 4:
230 if (strcmp (argv[1], "led") == 0) {
231 return (do_led (argv));
232 }
233 if (strcmp (argv[1], "rs485") == 0) {
234 return (do_rs485 (argv));
235 }
236 if (strcmp (argv[1], "serial_number") == 0) {
237 return (do_serial_number (argv));
238 }
239 break;
240
241 default:
242 break;
243 }
244
245 printf ("Usage:\n<command> <parameter1> <parameter2> ...\n");
246 return 1;
247}
248
249int do_info (void)
250{
251 printf ("Stand-alone application for TRAB board function test\n");
252 printf ("Built: %s at %s\n", __DATE__ , __TIME__ );
253
254 return 0;
255}
256
257int do_dip (void)
258{
259 unsigned int result = 0;
260 int adc_val;
261 int i;
262
263 /***********************************************************
264 DIP switch connection (according to wa4-cpu.sp.301.pdf, page 3):
265 SW1 - AIN4
266 SW2 - AIN5
267 SW3 - AIN6
268 SW4 - AIN7
269
270 "On" DIP switch position short-circuits the voltage from
271 the input channel (i.e. '0' conversion result means "on").
272 *************************************************************/
273
274 for (i = 7; i > 3; i--) {
275
276 if ((adc_val = adc_read (i)) == -1) {
277 printf ("Channel %d could not be read\n", i);
278 return 1;
279 }
280
281 /*
282 * Input voltage (switch open) is 1.8 V.
283 * (Vin_High/VRef)*adc_res = (1,8V/2,5V)*1023) = 736
284 * Set trigger at halve that value.
285 */
286 if (adc_val < 368)
287 result |= (1 << (i-4));
288 }
289
290 /* print result to console */
291 print_identifier ();
292 for (i = 0; i < 4; i++) {
293 if ((result & (1 << i)) == 0)
294 printf("0");
295 else
296 printf("1");
297 }
298 printf("\n");
299
300 return 0;
301}
302
303
304int do_vcc5v (void)
305{
306 int result;
307
308 /* VCC5V is connected to channel 2 */
309
310 if ((result = adc_read (VCC5V)) == -1) {
311 printf ("VCC5V could not be read\n");
312 return 1;
313 }
314
315 /*
316 * Calculate voltage value. Split in two parts because there is no
317 * floating point support. VCC5V is connected over an resistor divider:
318 * VCC5V=ADCval*2,5V/1023*(10K+30K)/10K.
319 */
320 print_identifier ();
321 printf ("%d", (result & 0x3FF)* 10 / 1023);
322 printf (".%d", ((result & 0x3FF)* 10 % 1023)* 10 / 1023);
323 printf ("%d V\n", (((result & 0x3FF) * 10 % 1023 ) * 10 % 1023)
324 * 10 / 1024);
325
326 return 0;
327}
328
329
330int do_vcc12v (void)
331{
332 int result;
333
334 if ((result = adc_read (VCC12V)) == -1) {
335 printf ("VCC12V could not be read\n");
336 return 1;
337 }
338
339 /*
340 * Calculate voltage value. Split in two parts because there is no
341 * floating point support. VCC5V is connected over an resistor divider:
342 * VCC12V=ADCval*2,5V/1023*(30K+270K)/30K.
343 */
344 print_identifier ();
345 printf ("%d", (result & 0x3FF)* 25 / 1023);
346 printf (".%d V\n", ((result & 0x3FF)* 25 % 1023) * 10 / 1023);
347
348 return 0;
349}
350
351static int adc_read (unsigned int channel)
352{
353 int j = 1000; /* timeout value for wait loop in us */
354 S3C2400_ADC *padc;
355
356 padc = S3C2400_GetBase_ADC();
357 channel &= 0x7;
358
359 debug ("%s: adccon %#x\n", __FUNCTION__, padc->ADCCON);
360
361 padc->ADCCON &= ~ADC_STDBM; /* select normal mode */
362 padc->ADCCON &= ~(0x7 << 3); /* clear the channel bits */
363 padc->ADCCON |= ((channel << 3) | ADC_ENABLE_START);
364
365 debug ("%s: reading ch %d, addcon %#x\n", __FUNCTION__,
366 (padc->ADCCON >> 3) & 0x7, padc->ADCCON);
367
368 while (j--) {
369 if ((padc->ADCCON & ADC_ENABLE_START) == 0)
370 break;
371 udelay (1);
372 }
373
374 if (j == 0) {
375 printf("%s: ADC timeout\n", __FUNCTION__);
376 padc->ADCCON |= ADC_STDBM; /* select standby mode */
377 return -1;
378 }
379
380 padc->ADCCON |= ADC_STDBM; /* select standby mode */
381
382 debug ("%s: return %#x, adccon %#x\n", __FUNCTION__, padc->ADCDAT & 0x3FF,
383 padc->ADCCON);
384
385 return (padc->ADCDAT & 0x3FF);
386}
387
388
389static void adc_init (void)
390{
391 S3C2400_ADC *padc;
392
393 padc = S3C2400_GetBase_ADC();
394
395 debug ("%s: adccon %#x\n", __FUNCTION__, padc->ADCCON);
396
397 padc->ADCCON &= ~(0xff << 6); /* clear prescaler bits */
398 padc->ADCCON |= ((65 << 6) | ADC_PRSCEN); /* set prescaler */
399
400 debug ("%s: init completed: adccon %#x\n", __FUNCTION__, padc->ADCCON);
401 return;
402}
403
404
405int do_buttons (void)
406{
407 int result;
408 int i;
409
410 result = *CPLD_BUTTONS; /* read CPLD */
411 debug ("%s: cpld_taster (32 bit) %#x\n", __FUNCTION__, result);
412
413 /* print result to console */
414 print_identifier ();
415 for (i = 16; i <= 19; i++) {
416 if ((result & (1 << i)) == 0)
417 printf("0");
418 else
419 printf("1");
420 }
421 printf("\n");
422 return 0;
423}
424
425
426int do_fill_level (void)
427{
428 int result;
429
430 result = *CPLD_FILL_LEVEL; /* read CPLD */
431 debug ("%s: cpld_fuellstand (32 bit) %#x\n", __FUNCTION__, result);
432
433 /* print result to console */
434 print_identifier ();
435 if ((result & (1 << 16)) == 0)
436 printf("0\n");
437 else
438 printf("1\n");
439 return 0;
440}
441
442
443int do_rotary_switch (void)
444{
445 int result;
446
447 result = *CPLD_ROTARY_SWITCH; /* read CPLD */
448 debug ("%s: cpld_inc (32 bit) %#x\n", __FUNCTION__, result);
449
450 *CPLD_ROTARY_SWITCH |= (3 << 16); /* clear direction bits in CPLD */
451
452 /* print result to console */
453 print_identifier ();
454 if ((result & (1 << 16)) == (1 << 16))
455 printf("R");
456 if ((result & (1 << 17)) == (1 << 17))
457 printf("L");
458 if (((result & (1 << 16)) == 0) && ((result & (1 << 17)) == 0))
459 printf("0");
460 if ((result & (1 << 18)) == 0)
461 printf("0\n");
462 else
463 printf("1\n");
464 return 0;
465}
466
467
468int do_vfd_id (void)
469{
470 int i;
471 long int pcup_old, pccon_old;
472 int vfd_board_id;
473 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
474
475 /* try to red vfd board id from the value defined by pull-ups */
476
477 pcup_old = gpio->PCUP;
478 pccon_old = gpio->PCCON;
479
480 gpio->PCUP = (gpio->PCUP & 0xFFF0); /* activate GPC0...GPC3 pull-ups */
481 gpio->PCCON = (gpio->PCCON & 0xFFFFFF00); /* configure GPC0...GPC3 as
482 * inputs */
483 udelay (10); /* allow signals to settle */
484 vfd_board_id = (~gpio->PCDAT) & 0x000F; /* read GPC0...GPC3 port pins */
485
486 gpio->PCCON = pccon_old;
487 gpio->PCUP = pcup_old;
488
489 /* print vfd_board_id to console */
490 print_identifier ();
491 for (i = 0; i < 4; i++) {
492 if ((vfd_board_id & (1 << i)) == 0)
493 printf("0");
494 else
495 printf("1");
496 }
497 printf("\n");
498 return 0;
499}
500
501int do_buzzer (void)
502{
503 int counter;
504
505 S3C24X0_TIMERS * const timers = S3C24X0_GetBase_TIMERS();
506 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
507
508 /* configure pin GPD7 as TOUT2 */
509 gpio->PDCON &= ~0xC000;
510 gpio->PDCON |= 0x8000;
511
512 /* set prescaler for timer 2, 3 and 4 */
513 timers->TCFG0 &= ~0xFF00;
514 timers->TCFG0 |= 0x0F00;
515
516 /* set divider for timer 2 */
517 timers->TCFG1 &= ~0xF00;
518 timers->TCFG1 |= 0x300;
519
520 /* set frequency */
521 counter = (PCLK / BUZZER_FREQ) >> 9;
522 timers->ch[2].TCNTB = counter;
523 timers->ch[2].TCMPB = counter / 2;
524
525 debug ("%s: frequency: %d, duration: %d\n", __FUNCTION__, BUZZER_FREQ,
526 BUZZER_TIME);
527
528 /* start */
529 timers->TCON = (timers->TCON | UPDATE2 | RELOAD2) & ~INVERT2;
530 timers->TCON = (timers->TCON | START2) & ~UPDATE2;
531
532 udelay (BUZZER_TIME);
533
534 /* stop */
535 timers->TCON &= ~(START2 | RELOAD2);
536
537 /* port pin configuration */
538 gpio->PDCON &= ~0xC000;
539 gpio->PDCON |= 0x4000;
540 gpio->PDDAT &= ~0x80;
541 return 0;
542}
543
544
545int do_led (char **argv)
546{
547 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
548
549 /* configure PC14 and PC15 as output */
550 gpio->PCCON &= ~(0xF << 28);
551 gpio->PCCON |= (0x5 << 28);
552
553 /* configure PD0 and PD4 as output */
554 gpio->PDCON &= ~((0x3 << 8) | 0x3);
555 gpio->PDCON |= ((0x1 << 8) | 0x1);
556
557 switch (simple_strtoul(argv[2], NULL, 10)) {
558
559 case 0:
560 case 1:
561 break;
562
563 case 2:
564 if (strcmp (argv[3], "on") == 0)
565 gpio->PCDAT |= (1 << 14);
566 else
567 gpio->PCDAT &= ~(1 << 14);
568 return 0;
569
570 case 3:
571 if (strcmp (argv[3], "on") == 0)
572 gpio->PCDAT |= (1 << 15);
573 else
574 gpio->PCDAT &= ~(1 << 15);
575 return 0;
576
577 case 4:
578 if (strcmp (argv[3], "on") == 0)
579 gpio->PDDAT |= (1 << 0);
580 else
581 gpio->PDDAT &= ~(1 << 0);
582 return 0;
583
584 case 5:
585 if (strcmp (argv[3], "on") == 0)
586 gpio->PDDAT |= (1 << 4);
587 else
588 gpio->PDDAT &= ~(1 << 4);
589 return 0;
590
591 default:
592 break;
593
594 }
595 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
596 return 1;
597}
598
599
600int do_full_bridge (char **argv)
601{
602 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
603
604 /* configure PD5 and PD6 as output */
605 gpio->PDCON &= ~((0x3 << 5*2) | (0x3 << 6*2));
606 gpio->PDCON |= ((0x1 << 5*2) | (0x1 << 6*2));
607
608 if (strcmp (argv[2], "+") == 0) {
609 gpio->PDDAT |= (1 << 5);
610 gpio->PDDAT |= (1 << 6);
611 return 0;
612 }
613 else if (strcmp (argv[2], "-") == 0) {
614 gpio->PDDAT &= ~(1 << 5);
615 gpio->PDDAT |= (1 << 6);
616 return 0;
617 }
618 else if (strcmp (argv[2], "off") == 0) {
619 gpio->PDDAT &= ~(1 << 5);
620 gpio->PDDAT &= ~(1 << 6);
621 return 0;
622 }
623 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
624 return 1;
625}
626
627/* val must be in [0, 4095] */
628static inline unsigned long tsc2000_to_uv (u16 val)
629{
630 return ((250000 * val) / 4096) * 10;
631}
632
633
634int do_dac (char **argv)
635{
636 int brightness;
637
638 /* initialize SPI */
639 spi_init ();
640
641 if (((brightness = simple_strtoul (argv[2], NULL, 10)) < 0) ||
642 (brightness > 255)) {
643 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
644 return 1;
645 }
646 tsc2000_write(TSC2000_REG_DACCTL, 0x0); /* Power up DAC */
647 tsc2000_write(TSC2000_REG_DAC, brightness & 0xff);
648
649 return 0;
650}
651
652
653int do_v_bat (void)
654{
655 unsigned long ret, res;
656
657 /* initialize SPI */
658 spi_init ();
659
660 tsc2000_write(TSC2000_REG_ADC, 0x1836);
661
662 /* now wait for data available */
663 adc_wait_conversion_done();
664
665 ret = tsc2000_read(TSC2000_REG_BAT1);
666 res = (tsc2000_to_uv(ret) + 1250) / 2500;
667 res += (ERROR_BATTERY * res) / 1000;
668
669 print_identifier ();
670 printf ("%ld", (res / 100));
671 printf (".%ld", ((res % 100) / 10));
672 printf ("%ld V\n", (res % 10));
673 return 0;
674}
675
676
677int do_pressure (void)
678{
679 /* initialize SPI */
680 spi_init ();
681
682 tsc2000_write(TSC2000_REG_ADC, 0x2436);
683
684 /* now wait for data available */
685 adc_wait_conversion_done();
686
687 print_identifier ();
688 printf ("%d\n", tsc2000_read(TSC2000_REG_AUX2));
689 return 0;
690}
691
692
693int do_motor_contact (void)
694{
695 int result;
696
697 result = *CPLD_FILL_LEVEL; /* read CPLD */
698 debug ("%s: cpld_fuellstand (32 bit) %#x\n", __FUNCTION__, result);
699
700 /* print result to console */
701 print_identifier ();
702 if ((result & (1 << 17)) == 0)
703 printf("0\n");
704 else
705 printf("1\n");
706 return 0;
707}
708
709int do_motor (char **argv)
710{
711 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
712
713 /* Configure I/O port */
714 gpio->PGCON &= ~(0x3 << 0);
715 gpio->PGCON |= (0x1 << 0);
716
717 if (strcmp (argv[2], "on") == 0) {
718 gpio->PGDAT &= ~(1 << 0);
719 return 0;
720 }
721 if (strcmp (argv[2], "off") == 0) {
722 gpio->PGDAT |= (1 << 0);
723 return 0;
724 }
725 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
726 return 1;
727}
728
729static void print_identifier (void)
730{
731 printf ("## FKT: ");
732}
733
734int do_pwm (char **argv)
735{
736 int counter;
737 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
738 S3C24X0_TIMERS * const timers = S3C24X0_GetBase_TIMERS();
739
740 if (strcmp (argv[2], "on") == 0) {
741 /* configure pin GPD8 as TOUT3 */
742 gpio->PDCON &= ~(0x3 << 8*2);
743 gpio->PDCON |= (0x2 << 8*2);
744
745 /* set prescaler for timer 2, 3 and 4 */
746 timers->TCFG0 &= ~0xFF00;
747 timers->TCFG0 |= 0x0F00;
748
749 /* set divider for timer 3 */
750 timers->TCFG1 &= ~(0xf << 12);
751 timers->TCFG1 |= (0x3 << 12);
752
753 /* set frequency */
754 counter = (PCLK / PWM_FREQ) >> 9;
755 timers->ch[3].TCNTB = counter;
756 timers->ch[3].TCMPB = counter / 2;
757
758 /* start timer */
759 timers->TCON = (timers->TCON | UPDATE3 | RELOAD3) & ~INVERT3;
760 timers->TCON = (timers->TCON | START3) & ~UPDATE3;
761 return 0;
762 }
763 if (strcmp (argv[2], "off") == 0) {
764
765 /* stop timer */
766 timers->TCON &= ~(START2 | RELOAD2);
767
768 /* configure pin GPD8 as output and set to 0 */
769 gpio->PDCON &= ~(0x3 << 8*2);
770 gpio->PDCON |= (0x1 << 8*2);
771 gpio->PDDAT &= ~(1 << 8);
772 return 0;
773 }
774 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
775 return 1;
776}
777
778
779int do_thermo (char **argv)
780{
781 int channel, res;
782
783 tsc2000_reg_init ();
784 tsc2000_set_range (3);
785
786 if (strcmp (argv[2], "all") == 0) {
787 int i;
788 for (i=0; i <= 15; i++) {
789 res = tsc2000_read_channel(i);
790 print_identifier ();
791 printf ("c%d: %d\n", i, res);
792 }
793 return 0;
794 }
795 channel = simple_strtoul (argv[2], NULL, 10);
796 res = tsc2000_read_channel(channel);
797 print_identifier ();
798 printf ("%d\n", res);
799 return 0; /* return OK */
800}
801
802
803
804int do_touch (char **argv)
805{
806 int x, y;
807
808 if (strcmp (argv[2], "tl") == 0) {
809 touch_wait_pressed();
810 touch_read_x_y (&x, &y);
811
812 print_identifier ();
813 printf ("x=%d y=%d\n", x, y);
814 return touch_write_clibration_values (CALIB_TL, x, y);
815 }
816 else if (strcmp (argv[2], "dr") == 0) {
817 touch_wait_pressed();
818 touch_read_x_y (&x, &y);
819
820 print_identifier ();
821 printf ("x=%d y=%d\n", x, y);
822
823 return touch_write_clibration_values (CALIB_DR, x, y);
824 }
825 return 1; /* return error */
826}
827
828
829static void touch_wait_pressed (void)
830{
831 while (!(tsc2000_read(TSC2000_REG_ADC) & TC_PSM));
832}
833
834
835static int touch_write_clibration_values (int calib_point, int x, int y)
836{
837#if (CONFIG_COMMANDS & CFG_CMD_I2C)
838 tsc2000_reg_init ();
839
840 if (calib_point == CALIB_TL) {
841 if (i2c_write (I2C_EEPROM_DEV_ADDR, TOUCH_X0, 1,
842 (char *)&x, 2)) {
843 printf ("could not write to eeprom\n");
844 return 1;
845 }
846 udelay(11000);
847 if (i2c_write (I2C_EEPROM_DEV_ADDR, TOUCH_Y0, 1,
848 (char *)&y, 2)) {
849 printf ("could not write to eeprom\n");
850 return 1;
851 }
852 udelay(11000);
853 return 0;
854 }
855 else if (calib_point == CALIB_DR) {
856 if (i2c_write (I2C_EEPROM_DEV_ADDR, TOUCH_X1, 1,
857 (char *)&x, 2)) {
858 printf ("could not write to eeprom\n");
859 return 1;
860 }
861 udelay(11000);
862 if (i2c_write (I2C_EEPROM_DEV_ADDR, TOUCH_Y1, 1,
863 (char *)&y, 2)) {
864 printf ("could not write to eeprom\n");
865 return 1;
866 }
867 udelay(11000);
868 return 0;
869 }
870 return 1;
871#else
872 printf ("No I2C support enabled (CFG_CMD_I2C), could not write "
873 "to EEPROM\n");
874 return (1);
875#endif /* CFG_CMD_I2C */
876}
877
878
879static void touch_read_x_y (int *px, int *py)
880{
881 tsc2000_write(TSC2000_REG_ADC, DEFAULT_ADC | TC_AD0 | TC_AD1);
882 adc_wait_conversion_done();
883 *px = tsc2000_read(TSC2000_REG_X);
884
885 tsc2000_write(TSC2000_REG_ADC, DEFAULT_ADC | TC_AD2);
886 adc_wait_conversion_done();
887 *py = tsc2000_read(TSC2000_REG_Y);
888}
889
890
891
892int do_rs485 (char **argv)
893{
894 int timeout;
895 char data[RS485_MAX_RECEIVE_BUF_LEN];
896
897 if (strcmp (argv[2], "send") == 0) {
898 return (rs485_send_line (argv[3]));
899 }
900 else if (strcmp (argv[2], "receive") == 0) {
901 timeout = simple_strtoul(argv[3], NULL, 10);
902 if (rs485_receive_chars (data, timeout) != 0) {
903 print_identifier ();
904 printf ("## nothing received\n");
905 return (1);
906 }
907 else {
908 print_identifier ();
909 printf ("%s\n", data);
910 return (0);
911 }
912 }
913 printf ("%s: unknown command %s\n", __FUNCTION__, argv[2]);
914 return (1); /* unknown command, return error */
915}
916
917
918static int rs485_send_line (const char *data)
919{
920 rs485_init ();
921 trab_rs485_enable_tx ();
922 rs485_puts (data);
923 rs485_putc ('\n');
924
925 return (0);
926}
927
928
929static int rs485_receive_chars (char *data, int timeout)
930{
931 int i;
932 int receive_count = 0;
933
934 rs485_init ();
935 trab_rs485_enable_rx ();
936
937 /* test every 1 ms for received characters to avoid a receive FIFO
938 * overrun (@ 38.400 Baud) */
939 for (i = 0; i < (timeout * 1000); i++) {
940 while (rs485_tstc ()) {
941 if (receive_count >= RS485_MAX_RECEIVE_BUF_LEN-1)
942 break;
943 *data++ = rs485_getc ();
944 receive_count++;
945 }
946 udelay (1000); /* pause 1 ms */
947 }
948 *data = '\0'; /* terminate string */
949
950 if (receive_count == 0)
951 return (1);
952 else
953 return (0);
954}
955
956
957int do_serial_number (char **argv)
958{
959#if (CONFIG_COMMANDS & CFG_CMD_I2C)
960 unsigned int serial_number;
961
962 if (strcmp (argv[2], "read") == 0) {
963 if (i2c_read (I2C_EEPROM_DEV_ADDR, SERIAL_NUMBER, 1,
964 (char *)&serial_number, 4)) {
965 printf ("could not read from eeprom\n");
966 return (1);
967 }
968 print_identifier ();
969 printf ("%08d\n", serial_number);
970 return (0);
971 }
972 else if (strcmp (argv[2], "write") == 0) {
973 serial_number = simple_strtoul(argv[3], NULL, 10);
974 if (i2c_write (I2C_EEPROM_DEV_ADDR, SERIAL_NUMBER, 1,
975 (char *)&serial_number, 4)) {
976 printf ("could not write to eeprom\n");
977 return (1);
978 }
979 return (0);
980 }
981 printf ("%s: unknown command %s\n", __FUNCTION__, argv[2]);
982 return (1); /* unknown command, return error */
983#else
984 printf ("No I2C support enabled (CFG_CMD_I2C), could not write "
985 "to EEPROM\n");
986 return (1);
987#endif /* CFG_CMD_I2C */
988}
989
990
991int do_crc16 (void)
992{
993#if (CONFIG_COMMANDS & CFG_CMD_I2C)
994 int crc;
995 char buf[EEPROM_MAX_CRC_BUF];
996
997 if (i2c_read (I2C_EEPROM_DEV_ADDR, 0, 1, buf, 60)) {
998 printf ("could not read from eeprom\n");
999 return (1);
1000 }
1001 crc = 0; /* start value of crc calculation */
1002 crc = updcrc (crc, buf, 60);
1003
1004 print_identifier ();
1005 printf ("crc16=%#04x\n", crc);
1006
1007 if (i2c_write (I2C_EEPROM_DEV_ADDR, CRC16, 1, (char *)&crc,
1008 sizeof (crc))) {
1009 printf ("could not read from eeprom\n");
1010 return (1);
1011 }
1012 return (0);
1013#else
1014 printf ("No I2C support enabled (CFG_CMD_I2C), could not write "
1015 "to EEPROM\n");
1016 return (1);
1017#endif /* CFG_CMD_I2C */
1018}
1019
1020
1021/*
1022 * Calculate, intelligently, the CRC of a dataset incrementally given a
1023 * buffer full at a time.
1024 * Initialize crc to 0 for XMODEM, -1 for CCITT.
1025 *
1026 * Usage:
1027 * newcrc = updcrc( oldcrc, bufadr, buflen )
1028 * unsigned int oldcrc, buflen;
1029 * char *bufadr;
1030 *
1031 * Compile with -DTEST to generate program that prints CRC of stdin to stdout.
1032 * Compile with -DMAKETAB to print values for crctab to stdout
1033 */
1034
1035 /* the CRC polynomial. This is used by XMODEM (almost CCITT).
1036 * If you change P, you must change crctab[]'s initial value to what is
1037 * printed by initcrctab()
1038 */
1039#define P 0x1021
1040
1041 /* number of bits in CRC: don't change it. */
1042#define W 16
1043
1044 /* this the number of bits per char: don't change it. */
1045#define B 8
1046
1047static unsigned short crctab[1<<B] = { /* as calculated by initcrctab() */
1048 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
1049 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
1050 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
1051 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
1052 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
1053 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
1054 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
1055 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
1056 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
1057 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
1058 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
1059 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
1060 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
1061 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
1062 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
1063 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
1064 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
1065 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
1066 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
1067 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
1068 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
1069 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
1070 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
1071 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
1072 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
1073 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
1074 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
1075 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
1076 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
1077 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
1078 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
1079 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
1080 };
1081
1082static unsigned short updcrc(unsigned short icrc, unsigned char *icp,
1083 unsigned int icnt )
1084{
1085 register unsigned short crc = icrc;
1086 register unsigned char *cp = icp;
1087 register unsigned int cnt = icnt;
1088
1089 while (cnt--)
1090 crc = (crc<<B) ^ crctab[(crc>>(W-B)) ^ *cp++];
1091
1092 return (crc);
1093}