PROGRAM "Simple-DVM" ; ================================================================================ ; ; ================================================================================ TO init MAKE AI0 Analogue(40) ; 0.35 + val*0.0315 Analog Input 0 - PSU MAKE AI1 Analogue(41) ; * 0.0197 Analog Input 1 - 0-20V AI1 MAKE AI2 Analogue(42) ; * 0.0197 Analog Input 2 - 0-20V AI2 MAKE AI3 Analogue(43) ; * 0.00488 Analog Input 3 - MAIN Board ID MAKE AI4 Analogue(44) ; * 0.00488 Analog Input 4 - Interface Board ID MAKE AI5 Analogue(45) ; * 0.00488 Analog Input 5 - Expansion Board ID MAKE AO0 Analogue(46) ; * 0.00488 Analog In / * 0.0195 Output 0 MAKE AO1 Analogue(47) ; * 0.00488 Analog In / * 0.0195 Output 1 MAKE backlight PulseWidthOut (19,100,1,1,0) MAKE LCD GraphicsLCD(28) MAKE KP Digital (136,143) ; Keypad MAKE kpmap ARRAY( 8,8, 1,2,3,4,8,7,6,5 ) MAKE DIN Digital(152,155) ; Digital IO IN MAKE DOUT Digital(156,159) ; Digital IO OUT MAKE YLED Digital (145) MAKE GLED Digital (144) MAKE USB Digital (16) LED.Off LCD.value(1,$81) LCD.value(1) := 24 LCD.value(1) := $A6 ; Invert Display backlight.On backlight.Width := 50 wALL := LCD.Window (0, 0, 128, 64, 0) ;All END ; ================================================================================ ; ; ================================================================================ TO main Pval := 0 Achan := 0 PBtn := 0 LCD.FontData (10) := mono5x3fnt.Address START PERIODIC_Handler ;Handle PERIODIC Events MAKE GTitle String(64) PRINT TO GTitle, "ADC CH",Achan:0," GRAPH" TGraph ( GTitle, 250, 10, 15, @GValue, @GCtrl ) END ; ================================================================================ ; PERIODIC_Handler - Handle medium async activities ; ================================================================================ TO PERIODIC_Handler () LOCAL LCDCount WAIT 10 LCDCount := 0 EVERY 50 [ If LCDcount = 2 [ LCD.Update LCDcount := 0 ] ELSE[ LCDcount := LCDcount + 1 ] ] END ; ================================================================================ ; GValue - User Callback function called from TGraph to get the current display value ; ================================================================================ TO GValue() LOCAL val ; val := VCI_AnlgIn ( Achan ) ; val := 0.7 * val + 0.3 * Pval ; Pval := val ; Return val RETURN VCI_AnlgIn ( Achan ) END ; ================================================================================ ; GCtrl - User Callback function called from TGraph to provide 'control functions' ; ================================================================================ TO GCtrl( title, interval, min, max ) LOCAL Btn Btn := Button(0) IF (Btn > 0) AND (PBtn = 0) [ PBtn := Btn IF Btn <= 4 [ Achan := Btn - 1 (!Title).Empty PRINT TO (!Title), "ADC CH",Achan:0," GRAPH" RETURN 1 ] IF (Btn = 5) AND (!interval > 125) [ !interval := !interval DIV 2 RETURN 1 ] IF (Btn = 6) AND (!interval < 20000) [ !interval := !interval*2 RETURN 1 ] IF (Btn=8) RETURN 2 ] PBtn := Btn RETURN 0 END ; ================================================================================ ; TGraph - Displays a graph ; ================================================================================ TO TGraph ( title, interval, min, max, datafunc, Ctrlfunc ) AUTODESTRUCT LOCAL PB, mdl, range LOCAL va, ptr, v, wg, x, y LOCAL rn, rbase LOCAL Gval, CtrlVal LOCAL tickTime := NEW Timer(interval) LCD.fontdata(10) := mono5x3fnt.Address wg := LCD.Window(21, 21, 121, 61, 0) va := new Array( 16, 25 ) REPEAT 25 va.(INDEX0) := 0 ptr := 1 FOREVER [ PRINT To WaLL, cls wAll.Graticule (20,20,0,100,5,2,2,1) wAll.Graticule (20,20,2,40,5,2,2,1) range := max - min If range < 4 REPEAT 5 PRINT TO wAll, FONT 10, RIGHT, GOTOXY( 15, 17+(INDEX0*10) ), (min+INDEX0*range/4):1:1 ELSE REPEAT 5 PRINT TO wAll, FONT 10, RIGHT, GOTOXY( 15, 17+(INDEX0*10) ), (min+INDEX0*range/4):1:0 IF interval >= 500 IF interval >= 5000 REPEAT 6 PRINT TO wAll, FONT 10, CENTRE, GOTOXY( 20+(INDEX0*20), 9 ), INDEX0*interval/250:1:0 ELSE REPEAT 11 PRINT TO wAll, FONT 10, CENTRE, GOTOXY( 20+(INDEX0*10), 9 ), INDEX0*interval/500:1:0 ELSE REPEAT 6 PRINT TO wAll, FONT 10, CENTRE, GOTOXY( 20+(INDEX0*20), 9 ), INDEX0*interval/250:1:1 PRINT TO wAll, FONT 10, CR, CENTRE, title range := 40/range tickTime.Period := interval CtrlVal := 0 FOREVER [ tickTime.go Gval := (!datafunc)() va.(ptr) := (((Gval-min)*range)-0.5) AS INT LCD.Lock PRINT TO wg, CLS REPEAT 24 [ x := (23-INDEX0)*4 y := ptr + INDEX wg.Line (x, va.((y+1) MOD 25), x+4, va.(y MOD 25)) ] ptr := ( ptr + 1 ) MOD 25 PRINT TO wAll, RIGHT, GOTOXY(128,3), Gval:6:1 LCD.Update LCD.UnLock DO [ CtrlVal := (!Ctrlfunc)(@title, @interval, @min, @max) IF CtrlVal <> 0 [ SELECT CASE CtrlVal CASE 3 RETURN 0 CASE 2 [ REPEAT 25 va.(INDEX0) := 0 ptr := 1 CtrlVal := 1 BREAK ] CASE 1 BREAK ] IF tickTime.Asserted WAIT 10 ] UNTIL tickTime.Done IF CtrlVal = 1 BREAK ] ] END ; ================================================================================ ; Button - ; ================================================================================ TO Button( w ) LOCAL kpinput if w [ AWAIT KP.Value = 255 AWAIT KP.Value <> 255 ] kpinput := KP.Value if kpinput = 255 RETURN 0 REPEAT 8 [ IF (kpinput AND 1) = 0 RETURN KPmap.(INDEX0) kpinput := kpinput DIV 2 ] RETURN 0 END ; ================================================================================ ; ================================================================================ ; ; Low Level Routines ; ; ================================================================================ ; ================================================================================ ; ================================================================================ ; readADC - ; ================================================================================ TO readADC ( Pchan, samps ) LOCAL val, chan chan := !Pchan REPEAT 3 val := chan.value val := 0 REPEAT samps val := val + chan.value val := val DIV samps RETURN val END ; ================================================================================ ; VCI_AnlgIn - Read Analogue Inputs ; ================================================================================ TO VCI_AnlgIn( chan ) LOCAL ioData SELECT CASE chan CASE 0 [ ioData := 0.35 + readADC( @AI0, 10 ) * 0.0315 ; 32.33 / 1024 ;If ioData > 9 ioData := ioData + 0.35 ] CASE 1 ioData := readADC( @AI1, 10 ) * 0.0197 ; 20.185 / 1024 CASE 2 ioData := readADC( @AI2, 10 ) * 0.0197 CASE 3 ioData := readADC( @AI3, 10 ) * 0.00488 ; 5 / 1024 CASE 4 ioData := readADC( @AI4, 10 ) * 0.00488 CASE 5 ioData := readADC( @AI5, 10 ) * 0.00488 CASE 6 ioData := readADC( @AO0, 10 ) * 0.00488 CASE 7 ioData := readADC( @AO1, 10 ) * 0.00488 return ioData END ; ================================================================================ ; VCI_AnlgOut - Set Analogue Outputs ; ================================================================================ TO VCI_AnlgOut( chan, IOvalue ) If chan = 0 THEN AO0.Value := IOvalue * 0.0195 ; 5 / 256 ELSE AO1.Value := IOvalue * 0.0195 END ; ============================================================================ TO VCI_DigIn ; DIN.Asserted return (NOT DIN.Value AND $0F) END ; ============================================================================ TO VCI_DigOut( IOvalue, mask ) LOCAL ioData If (mask AND $0F) <> 0 THEN [ ioData := DOUT.Value mask := (mask AND $0F) IOvalue := (IOvalue AND $0F) DOUT.Value := ((ioData AND NOT mask) OR (NOT IOvalue AND mask)) ] return (NOT DOUT.Value AND $0F) END ; ================================================================================ ; ================================================================================ ; ; Font, Image & Sprite Data ; ; ================================================================================ ; ================================================================================ ; ================================================================================ ; mono5x3fnt - ARRAY mono5x3fnt (8, 480) 0 3 5 '!' '~' 5 1 4 1 0 $40 $40 $40 $00 $40; ! $A0 $A0 $00 $00 $00; " $A0 $E0 $A0 $E0 $A0; # $40 $E0 $E0 $E0 $40; $ $80 $20 $40 $80 $20; % $40 $C0 $60 $E0 $40; & $40 $40 $00 $00 $00; ' $20 $40 $40 $40 $20; ( $80 $40 $40 $40 $80; ) $A0 $40 $A0 $00 $00; * $00 $40 $E0 $40 $00; + $00 $00 $00 $40 $80; , $00 $00 $E0 $00 $00; - $00 $00 $00 $00 $40; . $00 $20 $40 $80 $00; / $E0 $A0 $A0 $A0 $E0; 0 $40 $C0 $40 $40 $E0; 1 $E0 $A0 $20 $40 $E0; 2 $E0 $20 $40 $20 $E0; 3 $80 $C0 $E0 $40 $40; 4 $E0 $80 $E0 $20 $C0; 5 $60 $80 $E0 $A0 $E0; 6 $E0 $20 $40 $80 $80; 7 $E0 $A0 $E0 $A0 $E0; 8 $E0 $A0 $E0 $20 $C0; 9 $00 $40 $00 $40 $00; : $00 $40 $00 $40 $80; ; $20 $40 $80 $40 $20; < $00 $E0 $00 $E0 $00; = $80 $40 $20 $40 $80; > $40 $A0 $20 $40 $40; ? $E0 $A0 $E0 $80 $E0; @ $40 $A0 $E0 $A0 $A0; A $C0 $A0 $C0 $A0 $C0; B $60 $80 $80 $80 $60; C $C0 $A0 $A0 $A0 $C0; D $E0 $80 $E0 $80 $E0; E $E0 $80 $E0 $80 $80; F $E0 $A0 $80 $E0 $E0; G $A0 $A0 $E0 $A0 $A0; H $E0 $40 $40 $40 $E0; I $E0 $40 $40 $40 $80; J $A0 $C0 $80 $C0 $A0; K $80 $80 $80 $80 $E0; L $A0 $E0 $E0 $A0 $A0; M $A0 $E0 $E0 $E0 $A0; N $E0 $A0 $A0 $A0 $E0; O $E0 $A0 $E0 $80 $80; P $E0 $A0 $A0 $C0 $20; Q $E0 $A0 $C0 $A0 $A0; R $E0 $80 $E0 $20 $E0; S $E0 $40 $40 $40 $40; T $A0 $A0 $A0 $A0 $E0; U $A0 $A0 $A0 $A0 $40; V $A0 $A0 $E0 $E0 $E0; W $A0 $E0 $40 $E0 $A0; X $A0 $A0 $E0 $40 $40; Y $E0 $20 $40 $80 $E0; Z $60 $40 $40 $40 $60; [ $00 $80 $40 $20 $00; \ $C0 $40 $40 $40 $C0; ] $40 $A0 $00 $00 $00; ^ $00 $00 $00 $00 $E0; _ $80 $40 $00 $00 $00; ` $00 $00 $40 $A0 $60; a $80 $80 $C0 $A0 $C0; b $00 $00 $60 $80 $60; c $20 $20 $60 $A0 $60; d $00 $00 $E0 $E0 $C0; e $40 $80 $C0 $80 $80; f $00 $E0 $A0 $60 $E0; g $80 $80 $C0 $A0 $A0; h $40 $00 $C0 $40 $E0; i $20 $00 $20 $A0 $40; j $80 $80 $A0 $C0 $A0; k $C0 $40 $40 $40 $E0; l $00 $00 $A0 $E0 $E0; m $00 $00 $C0 $A0 $A0; n $00 $00 $E0 $A0 $E0; o $00 $C0 $A0 $C0 $80; p $00 $60 $A0 $60 $20; q $00 $00 $60 $80 $80; r $00 $E0 $80 $60 $E0; s $80 $E0 $80 $80 $60; t $00 $00 $A0 $A0 $E0; u $00 $00 $A0 $A0 $40; v $00 $00 $A0 $E0 $E0; w $00 $00 $A0 $40 $A0; x $00 $A0 $E0 $20 $C0; y $00 $E0 $20 $C0 $E0; z $20 $40 $C0 $40 $20; { $40 $40 $40 $40 $40; | $20 $40 $C0 $40 $20; } $00 $20 $E0 $80 $00; ~ END PROGRAM END