' FUNCGEN1.FRM -- ARB/FN Function Generator Prog Main Module V1.2
' Written by Jim Rowe, Electronics Australia Dec 96/Jan 97
'
'$FORM Setwave
'$FORM Setport

' $INCLUDE: 'CONSTANT.BI'                   'For control pan. definitions

DECLARE SUB StopnResetGen ()
DECLARE SUB MakeWave ()
DECLARE SUB SendWave ()
DECLARE SUB LoadConfig ()
DECLARE SUB SaveConfig ()
DECLARE SUB GrowString ()

COMMON SHARED BaseAddress%, NewWave%    'Port Addr, New Wfm code

DIM SHARED FileLen%                'Length of waveform
DIM SHARED FreqOutput!             'Actual output freq
DIM SHARED WaveSample$             'Waveform storage string
DIM SHARED Sample%                 'Sample for passing
DIM SHARED RunFlag%                'Run status flag
DIM SHARED DutyCycle!              'Duty cycle
DIM SHARED CurrentWave%            'Current Waveform code
DIM SHARED ClkSel%                 'Clock select (6=HI,0=MED,2=LO)
DIM SHARED NewFreq!                'Next frequency





SUB ChangeFreq_Click ()
    SHARED FileLen%, ClkSel%, NewFreq!
    DIM FreqInput AS SINGLE
    Prompt$ = "Give desired frequency in Hz" + CHR$(13) + CHR$(10)
    Prompt$ = Prompt$ + "Min 0.24Hz, Max 1MHz)"
    DO
        WantedFreq$ = INPUTBOX$(Prompt$, "Frequency Input", "1000")
        FreqInput = VAL(WantedFreq$)
        IF FreqInput >= .24 AND FreqInput <= 1000000! THEN EXIT DO
        IF FreqInput = 0 THEN EXIT SUB
        MSGBOX "Sorry -- outside range (0.24Hz - 1MHz)"
    LOOP
    SELECT CASE FreqInput
        CASE 63! TO 1000000!
            ClkSel% = 6
            FileLen% = INT(2000000! / FreqInput)
            NewFreq! = 2000000! / FileLen%
        CASE 16! TO 62.999
            ClkSel% = 0
            FileLen% = INT(250000 / FreqInput)
            NewFreq! = 250000 / FileLen%
        CASE .24 TO 15.999
            ClkSel% = 2
            FileLen% = INT(7812.5 / FreqInput)
            NewFreq! = 7812.5 / FileLen%
    END SELECT
    NewFreq$ = FORMAT$(NewFreq!, "#,#.000")
    NewFreqDisplay.CAPTION = SPACE$(15 - LEN(NewFreq$)) + NewFreq$ + " Hz"
    CALL MakeWave
END SUB

SUB Form_Load ()
    SHARED FileLen%, NewFreq!, BaseAddress%
    SHARED NewWave%, RunFlag%, ClkSel%

    SCREEN.ControlPanel(ACTIVE_BORDER_BACKCOLOR) = 7
    SCREEN.ControlPanel(ACTIVE_BORDER_FORECOLOR) = 0
    SCREEN.ControlPanel(TITLEBAR_BACKCOLOR) = 5
    SCREEN.ControlPanel(TITLEBAR_FORECOLOR) = 15
    WindowState = 2              'Maximise form

    FileLen% = 2000              'Setting up defaults...
    NewFreq! = 1000              '1000Hz
    BaseAddress% = &H3BC         'Guess primary printer port
    NewWave% = 1                 'Sine wave
    RunFlag% = 0                 'Stopped
    ClkSel% = 6                  'Generator hi clock freq
    
    PRINT "Loading & setting up -- please wait"
    CALL LoadConfig              'Load config file, if there is one
    CALL MakeWave                'Restore waveform array in case needed

    NewFreq$ = FORMAT$(NewFreq!, "#,#.000")
    NewFreqDisplay.CAPTION = SPACE$(15 - LEN(NewFreq$)) + NewFreq$ + " Hz"

    PortAddr.CAPTION = "Gen at " + HEX$(BaseAddress%)

    IF RunFlag% = 1 THEN         'Show run status
        RunInd.CAPTION = "RUNNING"
    ELSE RunInd.CAPTION = "STOPPED"
    END IF

END SUB

SUB GrowString ()
    SHARED Sample%, WaveSample$

    Sample% = Sample% AND 255             'Mask off hi byte
    NewChar$ = CHR$(Sample%)              'Convert to char
    WaveSample$ = WaveSample$ + NewChar$  '& add to string

END SUB

SUB LoadConfig ()
    SHARED FileLen%, NewFreq!, BaseAddress%, NewWave%
    SHARED DutyCycle!, RunFlag%, ClkSel%
    DIM X AS INTEGER

    ON LOCAL ERROR GOTO ErrHandler
    ErrorFlag = 0
    IF LEN(COMMAND$) > 0 THEN
        CurrentConfig$ = COMMAND$
        auto = 1
        ELSE CurrentConfig$ = "FUNCTGEN.CFG"
    END IF

    OPEN CurrentConfig$ FOR INPUT AS #2
    IF ErrorFlag = 0 THEN
        FOR X = 1 TO 5      'Ignore header
            LINE INPUT #2, A$
        NEXT X
        INPUT #2, A$: FileLen% = VAL(A$)   '& Read in params
        INPUT #2, A$: NewFreq! = VAL(A$)
        INPUT #2, A$: BaseAddress% = VAL("&H" + A$)
        INPUT #2, A$: NewWave% = VAL(A$)
        INPUT #2, A$: DutyCycle! = VAL(A$)
        INPUT #2, A$: RunFlag% = VAL(A$)
        INPUT #2, A$: ClkSel% = VAL(A$)
        CLOSE #2
    END IF
ErrHandler:
ErrorFlag = 1
RESUME NEXT

END SUB

SUB LoadGen_Click ()
    SHARED BaseAddress%, RunFlag%, ClkSel%

    CALL StopnResetGen
    OUT BaseAddress% + 2, 8      'Set for loading
    LoadInd.CAPTION = "Loading"
    CALL SendWave                'Go download waveform
    OUT BaseAddress% + 2, 14      'Then reset gen again
    OUT BaseAddress% + 2, 8
    LoadInd.CAPTION = ""
    OUT BaseAddress% + 2, ClkSel%   'Then send clk code
    RunInd.CAPTION = "RUNNING"      '& show user it's going
    RunFlag% = 1                    'Also set flag
END SUB

SUB MakeWave ()
    SHARED NewWave%, FileLen%, Sample%, DutyCycle!, WaveSample$
    DIM X AS INTEGER

    LoadInd.CAPTION = "Calculating -- Wait"
    NewWaveDisplay.CAPTION = ""
    MidWave% = FileLen% / 2
    WaveSample$ = ""
    SELECT CASE NewWave%
        CASE 1
            FOR X = 1 TO FileLen%
            Sample% = INT(127 + 127 * SIN((X / FileLen%) * 6.2831853#))
            CALL GrowString
            NEXT X
            NewWaveDisplay.CAPTION = "SINEWAVE"
        CASE 2
            FOR X = 1 TO MidWave%
                Sample% = 0
                CALL GrowString
            NEXT X
            FOR X = MidWave% + 1 TO FileLen%
                Sample% = 254
                CALL GrowString
            NEXT X
            NewWaveDisplay.CAPTION = "SQUARE WAVE"
        CASE 3
            FOR X = 1 TO MidWave%
                Sample% = INT(254 * (1 - (X / MidWave%)))
                CALL GrowString
            NEXT X
            FOR X = MidWave% + 1 TO FileLen%
                Sample% = INT((X - MidWave%) / (FileLen% - MidWave%) * 254)
                CALL GrowString
            NEXT X
            NewWaveDisplay.CAPTION = "TRIANGLE"
        CASE 4
            FOR X = 1 TO FileLen%
                Sample% = INT((X / FileLen%) * 254)
                CALL GrowString
            NEXT X
            NewWaveDisplay.CAPTION = "SAWTOOTH RISING"
        CASE 5
            FOR X = 1 TO FileLen%
                Sample% = INT(254 - (X / FileLen%) * 254)
                CALL GrowString
                NEXT X
            NewWaveDisplay.CAPTION = "SAWTOOTH FALLING"
        CASE 6
            FOR X = 1 TO FileLen% - (FileLen% * DutyCycle!)
                Sample% = 0
                CALL GrowString
            NEXT X
            FOR X = (FileLen% - (FileLen% * DutyCycle!) + 1) TO FileLen%
                Sample% = 254
                CALL GrowString
            NEXT X
            CR$ = CHR$(13) + CHR$(10)
            DutyText$ = "(" + STR$(DutyCycle! * 100) + "%)"
            NewWaveDisplay.CAPTION = "RECTANGLE" + CR$ + DutyText$
    END SELECT
    LoadInd.CAPTION = ""
END SUB

SUB Quit_Click ()
    CALL SaveConfig
    CLS
    SYSTEM
    END
END SUB

SUB RunGen_Click ()
    SHARED RunFlag%, BaseAddress%, ClkSel%

    IF RunFlag% = 0 THEN               'Was stopped, so now go
        RunFlag% = 1
        OUT BaseAddress% + 2, 14        'By resetting first, then
        OUT BaseAddress% + 2, 8
        OUT BaseAddress% + 2, ClkSel%  'Sending current clk code
        RunInd.CAPTION = "RUNNING"     'Then show user it's going
    ELSE RunFlag% = 0                  'Was going, so stop
        CALL StopnResetGen
    END IF

END SUB

SUB SaveConfig ()
    SHARED FileLen%, FreqOutput!, BaseAddress%, CurrentWave%
    SHARED DutyCycle!, RunFlag%, ClkSel%

    OPEN "FUNCTGEN.CFG" FOR OUTPUT AS #2
    PRINT #2, "Configuration file for EA PC-Based Arb/Fn Generator"
    PRINT #2, "Numbers in brackets are parameter default values"
    PRINT #2, "Order of parameter lines is fixed -- don't change!"
    PRINT #2, "Line after next is first value actually read in..."
    PRINT #2, "--- Written by Jim Rowe @ Electronics Australia ---"
    PRINT #2, FileLen%; "Length of current wfm array (2000)"
    PRINT #2, FreqOutput!; "Current o/p frequency (1000)"
    PRINT #2, HEX$(BaseAddress%); " Port addr for Generator (3BC)"
    PRINT #2, CurrentWave%; "Current waveform code (1 = Sine wave)"
    PRINT #2, DutyCycle!; "Duty cycle for rect wfm (0.5)"
    PRINT #2, RunFlag%; "Run status flag (0 = stopped)"
    PRINT #2, ClkSel%; "Run clock select code (6 = high)"
    CLOSE #2
END SUB

SUB SelectWaveform_Click ()
    SHARED NewWave%, DutyCycle!

    Setwave.SHOW 1              'Display dialog box

    IF NewWave% = 6 THEN
        Prompt$ = "Give Duty Cycle (%)"
        DO
        DutyInput$ = INPUTBOX$(Prompt$, "Duty Cycle Input", "50")
        DutyCycle! = VAL(DutyInput$)
        IF DutyCycle! >= 1 AND DutyCycle! <= 99 THEN EXIT DO
        LOOP
        DutyCycle! = DutyCycle! / 100
    END IF
    CALL MakeWave
END SUB

SUB SendWave ()
    SHARED FileLen%, WaveSample$, BaseAddress%, FreqOutput!
    SHARED NewFreq!, NewWave%, CurrentWave%
    DIM X AS INTEGER, Z AS INTEGER

    FOR X = 1 TO FileLen%
        Sample$ = MID$(WaveSample$, X, 1)        'Get data byte from string
        ThisSample% = ASC(Sample$)
        OUT BaseAddress%, ThisSample%            '& send it
        OUT BaseAddress% + 2, 9                  'with strobe pulse
        OUT BaseAddress% + 2, 8
        DO
            Z = INP(BaseAddress% + 1) AND &H80   'Then check for busy
        LOOP UNTIL Z = 128
        OUT BaseAddress% + 2, 12                 'Increment counter
        OUT BaseAddress% + 2, 8
    NEXT X
    OUT BaseAddress%, 255                        'Send EOR byte
    OUT BaseAddress% + 2, 9                      '& its strobe
    OUT BaseAddress% + 2, 8
    DO
        Z = INP(BaseAddress% + 1) AND &H80
    LOOP UNTIL Z = 128
    OUT BaseAddress% + 2, 12                    'Finally increm counter
    OUT BaseAddress% + 2, 8
    OUT BaseAddress%, 0                         '& send zero to end
    OUT BaseAddress% + 2, 9
    OUT BaseAddress% + 2, 8
    DO
        Z = INP(BaseAddress% + 1) AND &H80
    LOOP UNTIL Z = 128
    FreqOutput! = NewFreq!
    OutFreqDisplay.CAPTION = NewFreqDisplay.CAPTION
    CurrentWave% = NewWave%
    WaveformMode.CAPTION = NewWaveDisplay.CAPTION
END SUB

SUB SetIOAddress_Click ()
    SHARED BaseAddress%

    Setport.SHOW 1                  'Display dialog box

    PortAddr.CAPTION = "Gen at " + HEX$(BaseAddress%)
END SUB

SUB StopnResetGen ()
    SHARED BaseAddress%, RunFlag%

    OUT BaseAddress% + 2, 14      'Stop generator
    OUT BaseAddress% + 2, 8
    RunFlag% = 0                  'Reset run flag
    RunInd.CAPTION = "STOPPED"    '& show user
END SUB



