'O2 CELL DATA LOGGING PROGRAM
'BY ROBERT GLATTS 9-7-94

'THIS PROGRAM RUNS A MOCKUP OF THE MICROPROFILER AND LOGS DATA FROM A BANK
'OF SAYLES OXYGEN CELLS.  THE MICROPROFILER SECTION HAS A SUBROUTINE FOR MANUAL
'POSITIONING OF THE RACK.  ONCE THE RACK IS POSITIONED, YOU CAN START
'A DATA LOGGING CYCLE WHERE THE RACK WILL MOVE DOWN 1/4mm AND THEN RECORD
'THE OXYGEN CELL OUTPUT CURRENTS. THE SAYLES OXYGEN CELL LOGGING SECTION IS
'INTENDED TO RUN SOMEWHAT IN THE BACKGROUND AND CAN BE STARTED AND STOPPED
'WHENEVER THE MICROPROFILER IS NOT IN A DATA AQUISITION CYCLE.

'THE NEXT LINE SETS UP THE BASE ADDRESS OF THE ADA520.
'THE ADDRESS IN VARIABLE "BA" MUST MATCH THE SWITCH SETTINGS(S1) ON THE BOARD.

  
START:
   DIM CV(16) 'Channel Voltage array
   DIM CHGAIN(16) 'Channel Gain array
   CHGAIN(0) = 1
   CHGAIN(1) = 1          '0 = X1 GAIN
   CHGAIN(2) = 1          '1 = X10 GAIN
   CHGAIN(3) = 1          '2 = X100 GAIN
   CHGAIN(4) = 1          '3 = X1000 GAIN
   CHGAIN(5) = 1
   CHGAIN(6) = 1
   CHGAIN(7) = 1
   CHGAIN(8) = 1
   CHGAIN(9) = 1
   CHGAIN(10) = 1
   CHGAIN(11) = 1
   CHGAIN(12) = 0
   CHGAIN(13) = 0
   CHGAIN(14) = 0
   CHGAIN(15) = 0
  
   BA = 768   'BASE ADDRESS
  
'THIS SECTION OF THE PROGRAM SETS UP THE COMPUTER SCREEN

   CLS                                       'CLEAR SCREEN
  

'THE NEXT SECTION SETS UP THE ADDRESSES FOR THE ADA520 REGISTERS.

        PA = BA + 0                               'ADDRESS FOR 8255 PORT A
        PB = BA + 1                               'ADDRESS FOR 8255 PORT B
        PC = BA + 2                               'ADDRESS FOR 8255 PORT C
        CW = BA + 3                               'ADDRESS FOR 8255 CONTROL WORD
        DIR = BA + 4                              'DIRECTION REGISTER FOR DIGITAL I/O LINES
        IOA = BA + 5                              'DIGITAL I/O PORT A
        IOB = BA + 6                              'DIGITAL I/O PORT B
        IOC = BA + 7                              'DIGITAL I/O PORT C
        TA = BA + 8                               'ADDRESS FOR 8254 TIMER A
        TB = BA + 9                               'ADDRESS FOR 8254 TIMER B
        TC = BA + 10                              'ADDRESS FOR 8254 TIMER C
        TCW = BA + 11                             'ADDRESS FOR 8254 CONTROL WORD
        DA1LSB = BA + 12                          'ADDRESS FOR D/A 1 LSB
        DA1MSB = BA + 13                          'ADDRESS FOR D/A 1 MSB
        DA2LSB = BA + 14                          'ADDRESS FOR D/A 2 LSB
        DA2MSB = BA + 15                          'ADDRESS FOR D/A 2 MSB
        UPDATE = BA + 12                          'ADDRESS TO UPDATE DAC OUTPUTS
        STAT = BA + 13                            'ADDRESS TO READ STATUS BYTE

'THE NEXT LINE PROGRAMS THE BOARD FOR PORT A OUTPUT, PORT B INPUT, PORT C INPUT,
'PPI PORT B OUTPUT

'THIS SECTION INITIALIZES THE BOARD FOR OPERATION


   OUT DIR, 1                  'PORT A OUT, PORT B IN, PORT C IN
   OUT CW, &H92                'PPI PORT A IN, POT B OUT, PORT C OUT
   OUT PC, 0                   'SELECT CHANNEL 1, GAIN = 1
  

'THE NEXT SECTION IS THE BIT VALUES FOR EACH MICROPROFILER CONTROL FUNCTION

        MOTSTOP = 0
        MOTUPFAST = 3
        MOTUPSLOW = 7
        MOTDOWNFAST = 1
        MOTDOWNSLOW = 5

'********************************************************************
' BEGINNING OF MAIN PROGRAM
'********************************************************************

MAIN:
        ON ERROR GOTO ERRORHANDLER
        TIMER ON
        KEY(6) ON
        ON KEY(6) GOSUB O2STOP
        ON TIMER(1) GOSUB CLOCKTICK  'Update various timers once a second
        O2FLAG = 0
        GOSUB MAINMENU
       
'The program spends most of its time in this loop waiting for something
'to happen. A keypress puts the program into various modes while the
'clock counters in CLOCKTICK initiate the data logging.
        
MAINLOOP:
        KEYPRESSED$ = INKEY$
          IF KEYPRESSED$ = "6" THEN
            GOSUB O2START
            GOSUB MAINMENU
          ELSEIF KEYPRESSED$ = "9" THEN
            GOSUB QUIT
        END IF
       
        GOTO MAINLOOP:


'Print the main menu

MAINMENU:
        CLS
        LOCATE 1, 1
        PRINT "        O2 LOGGING PROGRAM V1.0"
        PRINT "6/F6 -- START/STOP O2 ELECTRODE DATA CYCLE"
        PRINT "9    -- QUIT"
        RETURN


'This subroutine updates a set of counters once a second.
'

CLOCKTICK:
        O2CLOCK = O2CLOCK - 1
        IF O2CLOCK <= 0 AND O2FLAG = 1 THEN
          O2CLOCK = O2INTERVAL
          GOSUB READO2DATA
        END IF
        DELAYCLOCK = DELAYCLOCK - 1
        RETURN


'********************************************************************
' O2 DATA ACQUISITION SECTION
'********************************************************************

       
O2START:
        IF O2FLAG = 1 THEN RETURN
        CLS
        INPUT "ENTER OUTPUT FILENAME PREFIX: "; O2FILE$  'Record data in this file
        DAY% = 1
        LASTDAY$ = DATE$     'Keep track of day so we can open a new file each day
        GOSUB OPENO2FILE
        INPUT "ENTER MINUTES BETWEEN SAMPLE SETS: "; O2INTERVAL
        O2INTERVAL = O2INTERVAL * 60     'Change minutes to seconds
        O2FLAG = 1      'Enable O2 logging
        RETURN

O2STOP:
        LOCATE 5, 1
        INPUT "DO YOU WANT TO STOP LOGGING O2 DATA Y/N? ", YESNO$
        IF YESNO$ = "Y" OR YESNO$ = "y" THEN
          O2FLAG = 0                          'Disable logging
          CLOSE #1                            'Close O2 log file
          LOCATE 5, 1
          PRINT "                                                     "
          RETURN
          ELSE
            LOCATE 5, 1
            PRINT "                                                    "
            RETURN  'GO BACK TO LOGGING O2
        END IF

READO2DATA:
        IF O2FLAG = 1 THEN
          GOSUB SCANCHANNELS          'Get some data
          THISDAY$ = DATE$            'What day is it?
          IF LASTDAY$ <> THISDAY$ THEN   'Is it a new day?
             CLOSE #1                    'If so, close the old file and open a new one
             DAY% = DAY% + 1
             GOSUB OPENO2FILE
             LASTDAY$ = THISDAY$
             END IF
          GOSUB PRINTO2DAT
          GOSUB STOREO2DAT             'Now store the data collected previously
          LOCATE 23, 1
          PRINT "                                                  "
          LOCATE 23, 1
          PRINT "LAST UPDATE:"; TIME$, DATE$, O2OUTPUTFILE$
          RETURN
            ELSE RETURN
          END IF


PRINTO2DAT:
'THIS SECTION PRINTS THE A/D DATA ON THE COMPUTER SCREEN.

        LOCATE 6, 1
        PRINT USING "CHANNEL  1: ######.# pA"; CV(0)
        PRINT USING "CHANNEL  2: ######.# pA"; CV(1)
        PRINT USING "CHANNEL  3: ######.# pA"; CV(2)
        PRINT USING "CHANNEL  4: ######.# pA"; CV(3)
        PRINT USING "CHANNEL  5: ######.# pA"; CV(4)
        PRINT USING "CHANNEL  6: ######.# pA"; CV(5)
        PRINT USING "CHANNEL  7: ######.# pA"; CV(6)
        PRINT USING "CHANNEL  8: ######.# pA"; CV(7)
        PRINT USING "CHANNEL  9: ######.# pA"; CV(8)
        PRINT USING "CHANNEL 10: ######.# pA"; CV(9)
        PRINT USING "CHANNEL 11: ######.# pA"; CV(10)
        PRINT USING "CHANNEL 12: ######.# pA"; CV(11)
        PRINT USING "CHANNEL 13: ######.# pA"; CV(12)
        PRINT USING "CHANNEL 14: ######.# pA"; CV(13)
        PRINT USING "CHANNEL 15: ######.# pA"; CV(14)
        PRINT USING "CHANNEL 16: ######.# pA"; CV(15)
        RETURN


OPENO2FILE:
        O2OUTPUTFILE$ = O2FILE$ + "." + LTRIM$(STR$(DAY%))
        OPEN O2OUTPUTFILE$ FOR OUTPUT AS #1
        RETURN

STOREO2DAT:
        IF O2FLAG = 1 THEN
          SAMPLEHOUR = VAL(MID$(SAMPLETIME$, 1, 2))
          SAMPLEMIN = VAL(MID$(SAMPLETIME$, 4, 2))
          SAMPLESEC = VAL(MID$(SAMPLETIME$, 7, 2))
          WRITE #1, SAMPLEHOUR, SAMPLEMIN, SAMPLESEC, CV(0), CV(1), CV(2), CV(3), CV(4), CV(5), CV(6), CV(7), CV(8), CV(9), CV(10), CV(11), CV(12), CV(13), CV(14), CV(15)
          RETURN
          ELSE RETURN
          END IF

'****************************************************************************
'  COMMON SUBROUTINES
'****************************************************************************



SCANCHANNELS:
        SAMPLETIME$ = TIME$             'STORE SAMPLE TIME
        FOR CHANNEL = 0 TO 15             'CHANNELS TO SCAN (1 TO 16)
        OUT PC, (CHGAIN(CHANNEL) * 16) + CHANNEL 'SELECT GAIN AND CHANNEL
        FOR D = 1 TO 10: NEXT D           'OPTIONAL DELAY FOR INPUT SETTLING TIME (DEPENDENT ON CPU SPEED)
        OUT CW, 13                        'START CONVERSION (SET PC6 = 1)
        GOSUB EOCHI                       'WAIT TILL STATUS = 1
        OUT CW, 12                        'STOP CONVERSION (SET PC6 = 0)
        GOSUB EOCLO                       'WAIT TILL STATUS = 0
        GOSUB READDAT                     'READ A/D DATA
        VOLT = RESULT * (5 / 4096)        'Convert to volts
        PICOAMP = VOLT * 1000             'Convert to picoamps
        CV(CHANNEL) = PICOAMP             'Store the voltage readings in an array
        NEXT CHANNEL
        RETURN



EOCHI:
        DONE = INP(STAT) AND 1            'CHECK TO SEE IF STATUS = 1
        IF DONE <> 1 GOTO EOCHI             'WAIT TILL STATUS = 1
        RETURN

EOCLO:
        DONE = INP(STAT) AND 1            'CHECK TO SEE IF STATUS = 0
        IF DONE <> 0 GOTO EOCLO           'WAIT TILL STATUS = 0
        RETURN


READDAT:
        OUT CW, 14                        'POINT TO MSB (PC7 = 0)
        MSB = INP(PA)                     'READ MSB
        POL = MSB AND 128                 'CHECK POLARITY BIT
        MSB = MSB AND 15                  'MASK OFF TOP 4 BITS
        MSB = MSB * 256                   'SCALE MSB
        OUT CW, 15                        'POINT TO LSB (PC7 = 1)
        LSB = INP(PA)                     'READ LSB
        RESULT = MSB + LSB                'COMBINE LSB AND MSB
        IF POL < 128 THEN RESULT = RESULT * -1  'ADJUST FINAL RESULT FOR POLARITY
        RETURN

ERRORHANDLER:
        IF ERR >= 52 AND ERR <= 76 THEN
          LOCATE 5, 1
          PRINT "FILE ERROR, PLEASE TRY AGAIN"
          PRINT "PRESS ANY KEY TO CONTINUE"
            WHILE INKEY$ = ""
            WEND
          GOSUB MAINMENU
          RESUME MAINLOOP
          ELSE
            CLS
            LOCATE 5, 1
            PRINT "UNRECOVERABLE ERROR, FILES CLOSED AND PROGRAM RESTARTED"
            PRINT "PRESS ANY KEY TO CONTINUE"
            CLOSE #1
            CLOSE #2
            WHILE INKEY$ = ""
            WEND
            RESUME START
        END IF


QUIT:
        LOCATE 5, 1
        INPUT "ARE YOU SURE YOU WANT TO QUIT ENTIRE PROGRAM"; YESNO$
        IF YESNO$ = "Y" OR YESNO$ = "y" THEN
          CLOSE #1
          CLOSE #2
          TIMER OFF
          ELSE
          LOCATE 5, 1
          PRINT "                                                "
          RETURN
        END IF
        END



