The QBasic Forum     RULES     Other Subforums, Links and Downloads

  
--

 Return to Index  

Latest and best revision of LED program.

September 17 2005 at 2:38 PM
Solitaire  (Login Solitaire1)
S


Response to Greatly modified and improved version of LED program.

 
I added several more features, fixed a couple of hidden bugs, tweaked the code to remove unneeded variables and INKEY$s, added lots of comments.

I spent many long hours on this program, neglecting other work that needed to be done. Thanks again to Michael Calkins for suggestions, some of which I used in the Binshow and Counter subs, although I had already revised most of the code before I saw his comments. I hope this version is good to go so I can get back to my other chores.

==========================================================

' by Solitaire (c) 2005
DECLARE SUB Binshow ()
DECLARE SUB Counter ()
DECLARE SUB Decshow ()
DECLARE SUB Display ()
DECLARE SUB Eraser ()
DECLARE SUB Finish (B AS STRING, col AS INTEGER)
DECLARE SUB Hexshow ()
DECLARE SUB Hextog ()
DECLARE SUB LEDtint ()
DECLARE SUB ResetLED (dec AS INTEGER)
DECLARE SUB Setup ()
DECLARE SUB ShowVal (dec AS INTEGER, bin AS STRING, bas AS STRING)

DECLARE FUNCTION BINTODEC% (bin AS STRING)
DECLARE FUNCTION DECTOBIN$ (dec AS INTEGER)
DECLARE FUNCTION HEXTODEC% (hux AS STRING)

DIM SHARED Tabset(1 TO 12) AS INTEGER
DIM SHARED Fkey(1 TO 12) AS INTEGER
DIM SHARED binval(1 TO 12) AS INTEGER
DIM SHARED hx AS INTEGER, tint AS INTEGER, H AS STRING

DIM dec AS INTEGER, fin AS INTEGER
DIM E AS STRING, B AS STRING

CALL Setup  'initializes Tabset and Fkey arrays
tint = 9    'default LED color is Blue
hx = 0: H$ = "ON"    'default Hex display is on
CALL Finish(B$, 26) 'opening screen

DO
    CALL Display   'prints LED bulbs and place values
    DO
        fin = 0
        VIEW PRINT 1 TO 10
        CLS : PRINT TAB(10); "BINARY LED COUNTER AND CONVERTER ---- ";
        PRINT "Enter your choice:"
        PRINT : PRINT TAB(20); "C = Binary Counter"
        PRINT TAB(20); "D = Decimal to Binary Converter"
        PRINT TAB(20); "B = Binary to Decimal Converter"
        PRINT TAB(20); "H = Hexadecimal to Binary Converter"
        PRINT TAB(20); "L = Change LED Color ";
        COLOR tint: PRINT CHR$(176): COLOR 7
        PRINT TAB(20); "X = Toggle Hexadecimal Display ";
        COLOR 8: PRINT "["; H$; "]": COLOR 7
        PRINT TAB(20); "E = Exit ";
        COLOR 8: PRINT "(or press Esc)": COLOR 7
        E$ = INPUT$(1)
        SELECT CASE UCASE$(E$)
            CASE "C"
                CALL Counter
            CASE "D"
                CALL Decshow
            CASE "B"
                CALL Binshow
            CASE "H"
                CALL Hexshow
            CASE "L"
                CALL LEDtint
            CASE "X"
                CALL Hextog
            CASE "E", CHR$(27)
                CALL Finish(B$, 12)
                fin = 1
            CASE ELSE
        END SELECT
        CALL ResetLED(dec)  'turns off LED lights
    LOOP UNTIL fin = 1
    CLS  'clears only top 10 lines
    VIEW PRINT
LOOP WHILE B$ = CHR$(8)
SYSTEM

SUB Binshow
DIM x AS INTEGER, y AS INTEGER, dec AS INTEGER, auto AS INTEGER, cl AS INTEGER
DIM bin AS STRING, C AS STRING
DIM recall(1 TO 12) AS INTEGER
DIM previous(1 TO 12) AS INTEGER

CLS
VIEW PRINT 1 TO 10
PRINT TAB(25); "BINARY TO DECIMAL CONVERTER"
PRINT
PRINT "Use the F keys across the top of your keyboard to toggle LED lights on or off."
PRINT TAB(5); "Press Enter to display results when done, or A for auto keypress."
PRINT TAB(5); "Press spacebar to clear and reset to 0."
PRINT TAB(5); "Press R to recall the last non-zero number entered."
PRINT TAB(5); "Press L to change LED color."
PRINT TAB(5); "Press X to toggle Hex display."
PRINT TAB(5); "Press M or Esc to return to the menu."
VIEW PRINT

auto = 0    'default Enter to display results; toggle -1 for instant display
LOCATE 14
y = 0
FOR x = 1 TO 12             'print the F-key keypress display
    IF x >= 10 THEN y = 1
    PRINT TAB(Tabset(x) - y); "F" + LTRIM$(STR$(x));
NEXT x

DO
    DO
        C$ = UCASE$(INKEY$)
    LOOP UNTIL C$ <> ""
    ent = 0
    IF C$ <> "L" THEN cl = 0
    SELECT CASE C$
        CASE "M", CHR$(27)      'Escape to menu
            EXIT DO

        CASE " "        'clears display
            FOR x = 1 TO 12
                binval(x) = 0
            NEXT x
            ent = -1
            cl = 1
            IF auto = -1 THEN
                LOCATE 5, 46: COLOR 8
                PRINT "Enter to display.": COLOR 7
            END IF

        CASE "X"        'toggles hex display
            CALL Hextog
            LOCATE 22, 1
            PRINT SPACE$(80)
            PRINT SPACE$(20)
            ent = -1
       
        CASE "L"        'changes LED color
            CALL LEDtint
            IF cl = 1 THEN  'will not display if spacebar was just pressed
                ent = 0
            ELSE
                ent = -1
            END IF

        CASE "R"        'recalls previous number from array
            FOR x = 1 TO 12
                LOCATE 18, Tabset(x)
                binval(x) = recall(x)
                IF binval(x) = 0 THEN
                        COLOR 7: PRINT CHR$(176)   'hollow gray - light off
                ELSE
                        COLOR tint: PRINT CHR$(219)   'solid color - light on
                END IF
            NEXT x
            COLOR 7
            ent = -1

        CASE "A"        'display F-key presses either instantly or after Enter
            auto = NOT auto     'toggle between 0 and -1
            ent = auto
            IF auto = 0 THEN
                LOCATE 4, 5
                PRINT "Press Enter to display results when done, or A for auto keypress."
                LOCATE 12, 1: PRINT SPACE$(80)
                LOCATE 22: PRINT SPACE$(80)
                PRINT SPACE$(20)
                LOCATE 12, 20: COLOR 8
                PRINT "Press Enter to refresh display"
                LOCATE 5, 46: PRINT SPACE$(30)
                COLOR 7
            ELSE
                LOCATE 4, 1: PRINT SPACE$(80)
                LOCATE 4, 5: PRINT "Auto keypress is on.  Press A to turn it off."
            END IF
            COLOR 7

        CASE CHR$(13)       'Enter to display when auto is off
            ent = -1
            LOCATE 5, 46: PRINT SPACE$(30)

        CASE ELSE       'user presses F-keys to toggle LED on or off
            IF LEN(C$) = 2 THEN
                FOR x = 1 TO 12
                    IF C$ = CHR$(0) + CHR$(Fkey(x)) THEN
                        binval(x) = NOT binval(x)   'toggle between 0 and -1
                        IF binval(x) <> previous(x) THEN  'user changes LED values
                            LOCATE 12, 1: PRINT SPACE$(80)
                            LOCATE 22: PRINT SPACE$(80)
                            PRINT SPACE$(20)
                        END IF
                        LOCATE 18, Tabset(x)
                        IF binval(x) = 0 THEN
                                COLOR 7: PRINT CHR$(176)   'hollow gray - light off
                        ELSE
                                COLOR tint: PRINT CHR$(219)   'solid color - light on
                        END IF
                        IF auto = 0 THEN
                            LOCATE 12, 1: PRINT SPACE$(80)
                            LOCATE 12, 20: COLOR 8
                            PRINT "Press Enter to display when done."
                        END IF
                        COLOR 7
                        ent = auto
                    END IF
                NEXT x
            END IF
            LOCATE 5, 46: PRINT SPACE$(30)
    END SELECT

    IF ent THEN
         FOR x = 1 TO 12     'concatenate binary digits
             bin$ = bin$ + LTRIM$(STR$(ABS(binval(x))))
             previous(x) = binval(x)     'save previous number to local array
         NEXT x
         CALL ShowVal(dec, bin$, "bin")
         IF C$ = " " THEN CALL Eraser
         bin$ = ""
         IF dec > 0 THEN
              FOR x = 1 TO 12     'saves previous non-0 number to array
                  recall(x) = binval(x)
              NEXT x
         END IF
    END IF
LOOP
LOCATE 14, 1: PRINT SPACE$(80)
CALL Eraser
END SUB

FUNCTION BINTODEC% (bin AS STRING)
DIM p AS INTEGER, x AS INTEGER, B AS INTEGER, d AS INTEGER, dig AS STRING
p = 0
FOR x = 12 TO 1 STEP -1
    dig$ = MID$(bin$, x, 1)
    B = VAL(dig$)
    d = B * (2 ^ p)
    dec = dec + d
    p = p + 1
NEXT x
BINTODEC% = dec
END FUNCTION

SUB Counter
DIM dec AS INTEGER, cnum AS INTEGER, start AS INTEGER, sp AS INTEGER
DIM rate AS SINGLE, pres AS SINGLE, t AS LONG, dnum AS DOUBLE
DIM C AS STRING, K AS STRING, snum AS STRING, st1 AS STRING, st2 AS STRING
CLS
VIEW PRINT 1 TO 10
PRINT TAB(30); "BINARY COUNTER"
PRINT
PRINT "Press Enter to begin after starting number.  After count begins:"
PRINT TAB(5); "Press Enter or spacebar to clear and stop."
PRINT TAB(5); "Press 1-9 to adjust speed (fast-slow).  ";
COLOR 8: PRINT "[5]"
COLOR 7
PRINT TAB(5); "Press 0 to freeze counter, any key to continue."
PRINT TAB(5); "R = reset counter to starting number: ";
COLOR 8: PRINT "0      ": COLOR 7
PRINT TAB(5); "Press L to change LED color; X to toggle Hex display."
PRINT TAB(5); "Press M or Esc to return to the menu.  ";
COLOR 8: PRINT "Counter will recycle to 0 after 4095."
COLOR 7
VIEW PRINT
rate = 1.5           'default speed (about 5)
DO
    K$ = INKEY$
    IF cnum > 0 THEN
        st1$ = ", C to continue at"
        st2$ = STR$(cnum) + ","
    ELSE
        LOCATE 7, 50: PRINT SPACE$(81 - POS(0))
    END IF
    LOCATE 12, 1: PRINT SPACE$(80)
    LOCATE 12, 1
    PRINT "Enter a starting number"; st1$;
    COLOR 8: PRINT st2$;
    COLOR 7: PRINT " or nothing to begin with 0";
    INPUT ": ", snum$
    snum$ = UCASE$(snum$)
    dnum = ABS(INT(VAL(snum$)))
    IF dnum > 4095 THEN dnum = 4095
    IF snum$ = "M" THEN EXIT DO
    IF snum$ = "R" THEN dnum = start    'resets counter to starting number
    IF snum$ = "C" THEN
        dnum = cnum   'saves last number before Enter or spacebar was pressed
        IF dnum > 0 THEN
            LOCATE 7, 50
            PRINT "T = reset to last number:";
            COLOR 8: PRINT dnum: COLOR 7
        ELSE
            LOCATE 7, 50: PRINT SPACE$(81 - POS(0))
        END IF
    ELSE
        start = dnum   'saves new number input or 0 to start
    END IF
    IF dnum = 0 THEN LOCATE 7, 50: PRINT SPACE$(81 - POS(0))
    sp = 5 - LEN(STR$(start))
    LOCATE 7, 42: COLOR 8
    PRINT start; SPACE$(sp): COLOR 7
    dec = dnum
    DO
        C$ = UCASE$(INKEY$)     'options while counter is changing
        SELECT CASE C$
            CASE CHR$(27), CHR$(13), "M", " "     'Escape to menu
                EXIT DO
            CASE "L"        'change LED color
                CALL LEDtint
                dec = dec - 1   'save number in display
            CASE "X"        'toggle hex display
                CALL Hextog
            CASE "R"        'restart counter from first input
                dec = start
            CASE "T"        'restart counter from last input
                dec = dnum
            CASE "0"
                C$ = INPUT$(1)  'freeze counter
                dec = dec - 1
            CASE ELSE
                pres = VAL(C$)
                IF pres <> 0 THEN      'change speed 1-9
                    rate = ((pres + 1) * 2) / 6
                    LOCATE 5, 46: COLOR 8
                    PRINT C$: COLOR 7
                END IF
        END SELECT
        CALL ShowVal(dec, bin$, "dec")    'show decimal and LED
        t = TIMER              'speed of counter
        DO WHILE t + rate >= TIMER: LOOP
        dec = dec + 1          'increment counter
        IF dec = 4096 THEN dec = 0      'recycle counter
        cnum = dec - 1    'save last number in count
    LOOP UNTIL C$ = CHR$(13) OR C$ = " " OR C$ = CHR$(27)
    LOCATE 7, 50: PRINT SPACE$(81 - POS(0))
    CALL ResetLED(dec)  'clear and reset to 0
LOOP UNTIL C$ = "M" OR C$ = CHR$(27) OR K$ = CHR$(27)
LOCATE 12, 1: PRINT SPACE$(80)
END SUB

SUB Decshow
DIM dec AS INTEGER, C AS STRING, K AS STRING, snum AS STRING
DIM previous AS INTEGER, dnum AS DOUBLE
CLS
VIEW PRINT 1 TO 10
PRINT TAB(25); "DECIMAL TO BINARY CONVERTER"
PRINT
PRINT "Input a number or R to recall previous non-zero number.  Press Enter to begin."
PRINT TAB(10); "After display shows:"
PRINT TAB(5); "Press Enter (or any key) to clear for a new number."
PRINT TAB(5); "Press L to change LED color."
PRINT TAB(5); "Press X to toggle Hex display."
PRINT TAB(5); "Press M or Esc to return to the menu."
VIEW PRINT
DO
    LOCATE 12, 1: PRINT SPACE$(80)
    LOCATE 12, 6
    INPUT "Enter a positive decimal integer up to 4095:  ", snum$
    snum$ = UCASE$(snum$)
    IF snum$ = "M" THEN EXIT DO
    dnum = ABS(INT(VAL(snum$)))
    IF dnum > 4095 THEN dec = 4095 ELSE dec = dnum
    IF snum$ = "R" THEN dec = previous
    CALL ShowVal(dec, bin$, "dec")   'show decimal value
    IF dec > 0 THEN previous = dec
    DO
        C$ = UCASE$(INPUT$(1))
        IF C$ = CHR$(27) THEN EXIT DO
        IF C$ = "L" THEN CALL LEDtint
        IF C$ = "X" THEN CALL Hextog
        IF C$ = "L" OR C$ = "X" THEN
            CALL ShowVal(dec, bin$, "dec")
        ELSE
            CALL ResetLED(dec)
        END IF
     LOOP WHILE C$ = "L" OR C$ = "X"
LOOP UNTIL C$ = "M" OR C$ = CHR$(27)
CALL Eraser
END SUB

FUNCTION DECTOBIN$ (dec AS INTEGER)
DIM p AS INTEGER, x AS INTEGER, bin AS STRING
p = 1  'place value
FOR x = 1 TO 12
    IF (dec AND p) = 0 THEN
        bin$ = "0" + bin$    'concatenate the string
    ELSE
        bin$ = "1" + bin$
    END IF
    p = p + p      'double the place value
NEXT x
DECTOBIN$ = bin$
END FUNCTION

SUB Display
DIM x AS INTEGER
LOCATE 11, 1: COLOR 8   'print gray line separating instructions from display
PRINT STRING$(80, CHR$(196)): COLOR 7

LOCATE 16
FOR x = 1 TO 12              'print the place values
    PRINT TAB(Tabset(x) - 1); 2 ^ (12 - x);
NEXT x

LOCATE 17
FOR x = 1 TO 12              'print the hollow LED (off) light bulbs
    PRINT TAB(Tabset(x)); CHR$(176);
NEXT x


END SUB

SUB Eraser
LOCATE 12, 1: PRINT SPACE$(80)  'clear decimal display
LOCATE 22: PRINT SPACE$(80)     'clear hex display
PRINT SPACE$(20)
END SUB

SUB Finish (B AS STRING, col AS INTEGER)
VIEW PRINT
CLS : LOCATE 2, 22 
PRINT "BINARY LED COUNTER AND CONVERTER"
LOCATE 10, 28: PRINT "-- by Solitaire --"
LOCATE 19, 32: PRINT "(c) 2005)"
COLOR 8
LOCATE 25, col 
IF col = 12 THEN
PRINT "Press any key to end or Backspace to return to program";
ELSE
PRINT "Press any key to begin";
END IF
COLOR 7
B$ = INPUT$(1)
CLS
END SUB

SUB Hexshow
DIM dec AS INTEGER, previous AS INTEGER, dnum AS DOUBLE
DIM C AS STRING, snum AS STRING, ch AS STRING, hux AS STRING
DIM N AS INTEGER, wrong AS INTEGER
CLS
hx = 0: H$ = "ON"
VIEW PRINT 1 TO 10
PRINT TAB(25); "HEXADECIMAL TO BINARY CONVERTER"
PRINT
PRINT "Input a hexadecimal number or R to recall previous non-zero number. "
COLOR 8: PRINT TAB(5); "Digits include numerals 0-9 and A-F.  ";
COLOR 7: PRINT "Press Enter to begin."
PRINT TAB(10); "After display shows:"
PRINT TAB(5); "Press Enter (or any key) to clear for a new number."
PRINT TAB(5); "Press L to change LED color."
PRINT TAB(5); "Press M or Esc to return to the menu."
VIEW PRINT
DO
    DO
        wrong = 0
        LOCATE 12, 1: PRINT SPACE$(80)
        LOCATE 12, 6
        INPUT "Enter a hexadecimal number up to 3 hex digits:  ", hux$
        hux$ = UCASE$(hux$)
        IF hux$ = "M" THEN EXIT DO
        N = LEN(hux$)
        IF N < 1 THEN hux$ = "0"  'nothing input
        IF N > 3 THEN wrong = 1
        FOR x = 1 TO N      'test each character for hex digit
            ch$ = MID$(hux$, x, 1)
            IF (ch$ < "0" OR ch$ > "F") OR (ch$ > "9" AND ch$ < "A") THEN wrong = 1
        NEXT x
        IF hux$ = "R" THEN wrong = 0    'input to recall previous number is ok
        IF wrong = 1 THEN
            LOCATE 12, 6: COLOR 8
            PRINT SPACE$(6);
            PRINT "Wrong input.  Try again or press M to return to menu.";
            PRINT SPACE$(81 - POS(0))
            PRINT SPACE$(80)
            SLEEP 2
            COLOR 7
        END IF
    LOOP UNTIL wrong = 0
    IF hux$ = "M" THEN EXIT DO
    IF hux$ = "R" THEN
        dec = previous  'recalls previous number
    ELSE
        dec = HEXTODEC(hux$)
    END IF
    CALL ShowVal(dec, bin$, "dec")   'show decimal & binary value
    DO
        C$ = UCASE$(INPUT$(1))
        IF C$ = CHR$(27) THEN EXIT DO
        IF C$ = "L" THEN
            CALL LEDtint
            CALL ShowVal(dec, bin$, "dec")
        ELSE
            IF dec > 0 THEN previous = dec  'saves last non-0 number
            CALL ResetLED(dec)
        END IF
     LOOP WHILE C$ = "L"
LOOP UNTIL C$ = "M" OR C$ = CHR$(27)
CALL Eraser
END SUB

FUNCTION HEXTODEC% (hux AS STRING)
DIM dec AS INTEGER, N AS INTEGER, x AS INTEGER, y AS INTEGER, ch AS STRING
N = LEN(hux$)
y = 0
FOR x = N TO 1 STEP -1
    ch$ = MID$(hux$, x, 1)
    IF ch$ >= "0" AND ch$ <= "9" THEN
        dec = dec + VAL(ch$) * 16 ^ y
    ELSE
        dec = dec + (ASC(ch$) - 55) * 16 ^ y
    END IF
    y = y + 1
NEXT x
HEXTODEC% = dec
END FUNCTION

SUB Hextog
hx = NOT hx
IF hx = 0 THEN H$ = "ON" ELSE H$ = "OFF"
END SUB

SUB LEDtint
DIM L AS STRING
VIEW PRINT
LOCATE 12, 1: PRINT SPACE$(80)
LOCATE 12, 15: PRINT "Select R ";
COLOR 12: PRINT CHR$(219);
COLOR 7: PRINT " (Red), G ";
COLOR 10: PRINT CHR$(219);
COLOR 7: PRINT " (Green), or B ";
COLOR 9: PRINT CHR$(219);
COLOR 7: PRINT " (Blue)"
L$ = UCASE$(INPUT$(1))
IF L$ = "R" THEN
    tint = 12    'Red
ELSEIF L$ = "G" THEN
    tint = 10    'Green
ELSE
    tint = 9     'Blue is the default color
END IF
LOCATE 12, 1: PRINT SPACE$(80)
END SUB

SUB ResetLED (dec AS INTEGER)
DIM x AS INTEGER
VIEW PRINT
FOR x = 1 TO 12    'set all binary values to 0
    binval(x) = 0
    LOCATE 18, Tabset(x) 'turn off all the LED lights
    PRINT CHR$(176)
NEXT x
CALL Eraser
END SUB

SUB Setup
FOR x = 1 TO 10              'set the scan values for the F keys
    Fkey(x) = x + 58
NEXT x
Fkey(11) = 133
Fkey(12) = 134

y = 0
FOR x = 6 TO 72 STEP 6      'locations for the LED lights
    y = y + 1
    Tabset(y) = x
NEXT x

END SUB

SUB ShowVal (dec AS INTEGER, bin AS STRING, bas$)
DIM shownum AS STRING, ch  AS STRING, hux AS STRING, x AS INTEGER
IF bas$ = "bin" THEN
    dec = BINTODEC(bin$)   'convert binary number to decimal
ELSEIF bas$ = "dec" THEN
    bin$ = DECTOBIN(dec)   'convert decimal number to binary
END IF
shownum$ = LEFT$(bin$, 4) + " " + MID$(bin$, 5, 4) + " " + RIGHT$(bin$, 4)
LOCATE 12, 1: PRINT SPACE$(14); "The binary value of decimal";
COLOR 15: PRINT dec;    'displays binary number in groups of 4
COLOR 7: PRINT "is  "; shownum$; SPACE$(81 - POS(0))
PRINT SPACE$(80)
FOR x = 1 TO 12
    ch$ = MID$(bin$, x, 1)
    LOCATE 18, Tabset(x)
    IF ch$ = "1" THEN
        COLOR tint: PRINT CHR$(219)    'turn solid light on
    ELSE
        COLOR 7: PRINT CHR$(176)    'turn hollow light off
    END IF
NEXT x
COLOR 7
IF hx = 0 THEN      'display hex value
    hux$ = HEX$(dec)
    hux$ = STRING$(3 - LEN(hux$), "0") + hux$
    LOCATE 22
    PRINT "Hexadecimal:"; TAB(Tabset(4)); LEFT$(hux$, 1);
    PRINT TAB(Tabset(8)); MID$(hux$, 2, 1); TAB(Tabset(12)); RIGHT$(hux$, 1)
    PRINT TAB(5); HEX$(dec); "  "
ELSE        'clear hex display
    LOCATE 22: PRINT SPACE$(80)
    PRINT SPACE$(20)
END IF
END SUB



    
This message has been edited by Solitaire1 on Sep 18, 2005 5:49 PM
This message has been edited by Solitaire1 on Sep 18, 2005 9:47 AM
This message has been edited by Solitaire1 on Sep 18, 2005 9:01 AM
This message has been edited by Solitaire1 on Sep 18, 2005 8:05 AM


 
 Respond to this message   
Responses

 Copyright © 1999-2008 Network54. All rights reserved.   Terms of Use   Privacy Statement