;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;
; The driver file for the Oscilloscope (driver.asm)
;
; Initializes everything, and goes to
; Main loop
;::::::::::::::::::::::::::::::::::::::::::
;Revision History
;-4/21/02 Initial Revision, with keypad operational
;-5/13/02 Analog Section added
;-5/18/02 Analog Section functional
;-5/22/02 Added VRAM sections of initialization
;-6/13/02 Added Initialization code, double buffering
;Author: Yiyang Gong
NAME tester
CGROUP GROUP CODE
DGROUP GROUP DATA, STACK
EXTRN InitCS:NEAR ;initialize MMCS, PCS values
;From initial.asm
EXTRN InitKeypadTimer:NEAR ;initialize the timer for keypad (timer2)
;From keypad.asm
EXTRN InstallKeypadHandler:Near ;initialize the keypad interrupt handler (from
;timer2)
;From keypad.asm
EXTRN ClrIRQVectors:NEAR ;clear the Interrupt vectors, for boot
;From initial.asm
EXTRN InitializeKeypadCounts:NEAR ;initialize the counts for the keypad
;From keypad.asm
EXTRN InstallTriggerHandlers:NEAR ;initializes the trigger interrupt handlers
;(from int0, timer0)
;From trigger.asm
EXTRN InitTriggerTimer:NEAR ;initialize the trigger delay timer
;and the sampling timer (timer0, timer1)
;From trigger.asm
EXTRN InitTriggerValues:NEAR ;initialize the first trigger value
;and all the counts of the trigger handlers
;From trigger.asm
EXTRN Main:Near ;the mainloop from C functions
;From main.c
EXTRN LScope:NEAR ;Easter Egg - the boot screen
;From lcd.asm
EXTRN InitBuffer:NEAR ;Initiates the double buffer positions
;From lcd.asm
$include(maininit.inc)
CODE SEGMENT PUBLIC 'CODE'
ASSUME CS:CGROUP, DS:DGROUP, SS:DGROUP
;Pseudo Code
;Initialize the 80188 selects ;call InitCS
;Clear interrupt vectors ;call ClrIRQVectors
;Clear Digit
;Clear Segment
;Install Interrupt handler ;Call InstallHandler
;Initialize times ;Call InitTimer
;Enable interrupts
;CALL the main loop
;END
START LABEL FAR
CLI
27
MOV DX, LMCSReg ;set up the RAM chip select
MOV AX, LMCSVal
OUT DX, AL
MOV AX, STACK ;initialize the stack pointer
MOV SS, AX
MOV SP, OFFSET(DGROUP:TopOfStack)
MOV AX, DGROUP ;initialize the data segment
MOV DS, AX
MOV AX, DGROUP ;initialize the ES pointer
MOV ES, AX
CALL InitCS ;initialize the 80188 chip selects
; assumes LCS and UCS already setup
CALL ClrIRQVectors ;clear (initialize) interrupt vector table
CALL InstallKeypadHandler ;install the event handler
; ALWAYS install handlers before
; allowing the hardware to interrupt.
CALL InitKeypadTimer ;initialize the keypad timer (timer 2)
CALL InitializeKeypadCounts ;Initialize the keypad counts
CALL InstallTriggerHandlers ;initialize the trigger interrupt handlers
;from int0 and timer0
CALL InitTriggerTimer ;initialize the trigger delay counter (timer0)
;and the trigger sampling counter (timer1)
CALL InitTriggerValues ;initialize all the trigger counters, as well
;as give an initial trigger value/slope
CALL InitBuffer ;initialize the buffer positions
STI ;and finally allow interrupts.
LOOPER:
CALL LScope ;Easter Egg - boot screen
;exited from with a keypress
CALL Main ;the main loop that never returns
Looper1:
;should never reach here
JMP Looper1
CODE ENDS
ASSUME CS:POWER_ON ;the initial code to run
;when the power is turned on
POWER_ON SEGMENT
MOV DX, UMCS_REG ;setup the UMCS register
MOV AX, UMCS_VAL ;for access to the ROM
OUT DX, AL
JMP START ;JMP to the start of the code
POWER_ON ENDS
;the data segment
DATA SEGMENT PUBLIC 'DATA'
28
DATA ENDS
;the stack
STACK SEGMENT STACK 'STACK'
DB 80 DUP ('Stack ') ;240 words
TopOfStack LABEL WORD
STACK ENDS
END
29
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;
; Initialization constants (maininit.inc)
; sets up ROM and RAM in memory
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Revision History
;-6/13/02 Added constants for UMCS, LMCS initialization
;
;
UMCS_REG EQU 0FFA0H ;the address of the UCS controller
UMCS_VAL EQU 03000H ;sets up UCS from F0000H to FFFFFH, no wait states
LMCSReg EQU 0FFA2H ;the address of the UCS controller
LMCSVal EQU 007C0H ;set up LCS from 00000H to 0FFFFH, no wait states
30
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;
; The initialization CS (init.asm)
;
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Table of Contents
;-InitCS() –
; This function will initializes the PCS select lines (for trigger delay
; control, trigger value writes, and double buffer selects)
; and the MCS select for the VRAM read and writes
;-ClrIRQVectors –
; Clear the interrupt vector by filling with the illegal event handler
;-IllegalEventHandler –
; A function that should never be reached. But if it is reached,
; it sends a Non-specific EOI to clear the most significant interrupt.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Revision History (difference from Glen George code)
;-4/20/02 Initial revision after EE51, added comments
;-5/27/02 Added MMCS values for VRAM
;Author: Yiyang Gong
NAME Initialization ;Yiyang Gong
CGROUP GROUP CODE
$INCLUDE(init.INC)
CODE SEGMENT PUBLIC 'CODE'
ASSUME CS:CGROUP
; InitCS
;
; Description: Initialize the Peripheral Chip Selects on the 80188.
;
; Arguments: None.
; Return Value: None.
;
; Local Variables: None.
; Shared Variables: None.
; Global Variables: None.
;
; Input: None.
; Output: None.
;
; Error Handling: None.
;
; Algorithms: None.
; Data Structures: None.
;
; Registers Used: AX, DX
;
;Author: Yiyang Gong
; Copied from Glen George InitCS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Pseudo Code
;Setup write to PACS
;Write to PACS register the number of wait states and base
;Setup write to MPCS register
;Write to MPCS register the number of wait states and I/O space
;END
;Revision History
;-10/29/97 Glen George Final revision
;-5/27/02 Added MMCS values for VRAM
InitCS PROC NEAR
31
public InitCS
PUSH DX ;save registers
PUSH AX
MOV DX, PACSreg ;setup to write to PACS register
MOV AX, PACSval
OUT DX, AL ;write PACSval to PACS (base at 0, 0 wait states)
MOV DX, MPCSreg ;setup to write to MPCS register
MOV AX, MPCSval
OUT DX, AL ;write MPCSval to MPCS (I/O space, 0 wait states)
MOV DX, MMCSreg ;setup to write to MMCS register
MOV AX, MMCSval
OUT DX, AL ;write MMCSval to MMCS (base at 4000H, 0 wait states)
POP AX ;restore registers
POP DX
RET ;done so return
InitCS ENDP
; ClrIRQVectors
;
; Description: This functions installs the IllegalEventHandler for all
; interrupt vectors in the interrupt vector table. Note
; that all 256 vectors are initialized so the code must be
; located above 400H. The initialization skips the first
; RESERVED_VECS vectors.
;
; Arguments: None.
; Return Value: None.
;
; Local Variables: CX - vector counter.
; ES:SI - pointer to vector table.
; Shared Variables: None.
; Global Variables: None.
;
; Input: None.
; Output: None.
;
; Error Handling: None.
;
; Algorithms: None.
; Data Structures: None.
;
; Registers Used: flags, AX, CX, SI, ES
;
;Pseudo Code
;
;Clear ES
;Initialize SI to skip reserved vectors (4 bytes)
;Initialize rest of interrupt vectors
;Set start address
;REPEAT
; Current vector (at start address) = address of illegal event handler
; Move start address to next vector
;UNTIL start address > interrupt vector + vector size
;
;END
;Revision History
;-1/28/02 Glen George Final Revision
;-4/20/02 Yiyang Gong Added comments
ClrIRQVectors PROC NEAR
PUBLIC CLRIRQVECTORS
PUSH AX ;save registers
32
PUSH CX
PUSH ES
PUSH SI
InitClrVectorLoop:
XOR AX, AX ;clear ES (interrupt vectors are in segment 0)
MOV ES, AX
MOV SI, 4 * RESERVED_VECS ;initialize SI to skip RESERVED_VECS (4 bytes
;each)
MOV CX, 256 - RESERVED_VECS ;up to 256 vectors to initialize
ClrVectorLoop: ;loop clearing each vector
;store the vector
MOV ES: WORD PTR [SI], OFFSET(IllegalEventHandler)
MOV ES: WORD PTR [SI + 2], SEG(IllegalEventHandler)
ADD SI, 4 ;update pointer to next vector
LOOP ClrVectorLoop ;loop until have cleared all vectors
;JMP EndClrIRQVectors;and all done
EndClrIRQVectors:
POP SI ;restore registers
POP ES
POP CX
POP AX
RET ;all done, return
ClrIRQVectors ENDP
; IllegalEventHandler
;
; Description: This procedure is the event handler for illegal
; (uninitialized) interrupts. It does nothing - it just
; returns after sending a non-specific EOI.
;
; Arguments: None.
; Return Value: None.
;
; Local Variables: None.
; Shared Variables: None.
; Global Variables: None.
;
; Input: None.
; Output: None.
;
; Error Handling: None.
;
; Algorithms: None.
; Data Structures: None.
;
; Registers Used: None
;
;Pseudo Code
;
;Send non-specific EOI
;END
;Revision History
;-12/25/00 Glen George Final Revision
;-4/20/02 Yiyang Gong added comments
;
IllegalEventHandler PROC NEAR
33
PUBLIC ILLEGALEVENTHANDLER
PUSH AX ;save the registers
PUSH DX
MOV DX, INTCtrlrEOI ;send a non-sepecific EOI to the
MOV AX, NonSpecEOI ; interrupt controller to clear out
OUT DX, AX ; the interrupt that got us here
POP DX ;restore the registers
POP AX
IRET ;and return
IllegalEventHandler ENDP
CODE ENDS
END
34
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Init.INC
; Include File for initialization of CPU
;
; CS and interrupts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;This file is for the initialization of keypad timers and keypad counts
; Revision History:
; 5/5/02 - Initial revision
; Interrupt Controller Definitions
; Addresses
INTCtrlrCtrl EQU 0FF32H ;address of interrupt controller for timer
INTCtrlrEOI EQU 0FF22H ;address of interrupt controller EOI
; Chip Select Unit Definitions
; Addresses
PACSreg EQU 0FFA4H ;address of PACS register
MPCSreg EQU 0FFA8H ;address of MPCS register
MMCSreg EQU 0FFA6H ;address of MMCS register
NonSpecEOI EQU 08000H ;Non-specific EOI command
; Control Register Values
PACSval EQU 00000H ;PCS base at 0, 0 wait states
MPCSval EQU 02080H ;PCS in I/O space, use PCS5/6, 0 wait states
MMCSval EQU 04000H ;01000000-------- MCS starting address is 40000H with 256K address
;-------------000 no wait states
;General Definitions
RESERVED_VECS EQU 0 ;vectors reserved for debugger
35
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; KeyPad (keypad.asm)
; file for handling the keypad debouncing, autorepeating
; based on timer2 interrupts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;KeypadEventHandler() -
; The event handler from timer2. It will call the scandebounce
; function from the keypad file.
;InitKeypadTimer() -
; Initializes the keypad timer (timer 2) for counting milliseconds
; and thus scanning for a keypress every millisecond
;InstallKeypadHandler() -
; Install the keypad handler in the interrupt vector (at
; position for timer2)
;InitializeKeypadCounts() -
; The function initializes the counts for the keypad and the timer
; for keypad scanning
;GetKey() -
; The function calls keyavailable() to see if a key is debounced
; and then converts the debounced key to a keycode. The key code is then
; returned in AX.
;KeyAvailable() -
; The function checks if a key is available by checking the debounce flag.
; The function will then return the status in AL.
;ScanDebounce() -
; The function is called with every timer2 interrupt.
; The function first checks if a key is scanned in on the keypad. Then
; the key is either registered as a new, or debounced. If the key was already
; debounced, then the key is autorepeated at some rate.
;Author: Yiyang Gong
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Revision History
;-2/14/02 initial revision with timer event handler, added all commments
;-2/24/02 initial revision with scandebounce and functioning keypad
;-3/15/02 changed keycodes to 0-11
;-4/21/02 changed keycode to 0-5 for the oscilloscope, by changing the
; key table values, and deleting test cases for three ports
; (as the new "keypad"
NAME KeyPad
CGROUP GROUP CODE
DGROUP GROUP DATA
$INCLUDE(keypad.INC)
$INCLUDE(init.inc)
CODE SEGMENT PUBLIC 'CODE'
ASSUME CS:CGROUP, DS:DGROUP
;InitializeKeypadCounts()
;Description:
; Initializes all the counts and flags used by the keypad program
;Arguments: None
;Return Value: None
;Local Variables: None
;Shared Variables: CurrentKey - the current key scanned in by scandebounce()
; DebounceFlag - the flag status of a key being debounced
; AutoRepeatCount - Once the keypad starts autorepeating
; this count is used
; DebounceCount - When the keypad is debouncing a key,
; this count is used
; MaxCount - the count to count to, for either
; debouncing or autorepeating
; Keycode - the code to return for any key
;Global Variables: None
36
;Input: None
;Output: None
;Error Handling: None
;Algorithms: None
;Data Structures: None
;Registers Used: None
;Pseudo Code
; Start the key count at zero
; Set the debounce flag to false
; Set repeat count, autorepeatcount to zero
; Establish the max count
; Set the initial keycode
;END
;Revision History
;2/14/02 Yiyang Gong Initial Revision
InitializeKeypadCounts PROC NEAR
Public InitializeKeyPadCounts
MOV CurrentKey, EmptyKey ;no key has been scanned
MOV DebounceFlag, False ;no key has been debounced
MOV AutoRepeatCount, 0
MOV DebounceCount, 0 ;start counts at zero when begin counting
MOV MaxCount, MaxDebounceCount ;in debounce mode, use debounce maximum
MOV KeyCode, EmptyKey ;empties keycode
RET
InitializeKeypadCounts ENDP
;KeypadEventHandler
;Description: This function takes care of scanning for a keypress and
; debouncing the key. In the event handler, the scandebounce function
; is called. This abstraction allows for other functions to be on
; the same timer.
;Arguments: None
;Return Value: None
;Local Variables: None
;Shared Variables: None
;Global Variables: None
;Input: A key pressed
;Output: None
;Error Handling: None
;Algorithms: None
;Data Structures: None
;Registers Used: AX, DX
;Pseudo Code
;CALL scandebounce
;Send EOI
;END
;Revision History
;2/24/02 Yiyang Gong added ScanDebounce
KeypadEventHandler PROC NEAR
Public KeypadEventHandler
PUSH DX
PUSH AX
CALL ScanDebounce ;call to see if a key has been found
;or is being debounced
EndTimerEventHandler: ;done taking care of the timer
MOV DX, INTCtrlrEOI ;send the EOI to the interrupt controller
MOV AX, Timer0EOI
OUT DX, AL
POP AX ;restore the registers
POP DX
IRET
37
KeypadEventHandler ENDP
; InitKeypadTimer
;
; Description: Initialize the 80188 Timer2. The timer2 are initialized
; to generate a count every millisecond. The
; interrupt controller is initialized to allow the
; timer2 interrupts.
;
; Arguments: None.
; Return Value: None.
;
; Local Variables: None.
; Shared Variables: None.
; Global Variables: None.
;
; Input: None.
; Output: None.
;
; Error Handling: None.
;
; Algorithms: None.
; Data Structures: None.
;
; Registers Used: AX, DX
;
;Pseudo Code
;count register = 0
;initialize timer #2 for a constant interval between timer interrupt
;send to interrupt controller
;setup max count per second
;send to interrupt controller
;reset interrupts, sets control register
;send to interrupt controller
;send EOI
;END
;Revision History
;10/29/97 Glen George Final revision
;2/14/02 Yiyang Gong revision to work with keypad and 16Mhz clock
;4/20/02 Yiyang Gong revision, no need for interrupts
InitKeypadTimer PROC NEAR
Public InitKeypadTimer
PUSH DX
PUSH AX
;initialize Timer #2 as a prescalar
MOV DX, Tmr2Count ;initialize the count register to 0
XOR AX, AX
OUT DX, AL
MOV DX, Tmr2MaxCnt ;setup max count for 1ms counts
MOV AX, COUNTS_PER_MS
OUT DX, AL
MOV DX, Tmr2Ctrl ;setup the control register, no interrupts
MOV AX, Tmr2CtrlVal
OUT DX, AL
MOV DX, INTCtrlrCtrl ;setup the interrupt control register
MOV AX, INTCtrlrCVal
OUT DX, AL
MOV DX, INTCtrlrEOI ;send a non-specific EOI (to clear out controller)
MOV AX, NonSpecEOI
OUT DX, AL
POP AX
38
POP DX
RET ;done so return
InitKeypadTimer ENDP
; InstallKeypadHandler
;
; Description: Install the event handler for the timer interrupt.
;
; Arguments: None.
; Return Value: None.
;
; Local Variables: None.
; Shared Variables: None.
; Global Variables: None.
;
; Input: None.
; Output: None.
;
; Error Handling: None.
;
; Algorithms: None.
; Data Structures: None.
;
; Registers Used: AX, ES
;
;Pseudo Code
;
;Clear interrupt vector
;Store start vector address (of timerEventHandler)
;Initialize all values of the vector
;END
;Revision History
; 1/28/02 Glen George Final Revision
; 2/14/02 Yiyang Gong Added comments
;
InstallKeypadHandler PROC NEAR
PUBLIC InstallKeypadHandler
PUSH ES ;save registers
PUSH AX
XOR AX, AX ;clear ES (interrupt vectors are in segment 0)
MOV ES, AX
;store the vector
MOV ES: WORD PTR (4 * Tmr2Vec), OFFSET(KeypadEventHandler)
MOV ES: WORD PTR (4 * Tmr2Vec + 2), SEG(KeypadEventHandler)
POP AX ;restore registers
POP ES
RET ;all done, return
InstallKeypadHandler ENDP
;GetKey()
;Description: This function is called with no arguments and returns with the code
;for the key pressed on the keypad in register AL. The procedure should only return fully
;debounced key presses. The routine returns with the key code after the key has been
;pressed and debounced, but not necessarily released. The procedure does not return until
;a key has been pressed.
;
;Arguments: none
;Return value: Keycode in AL
;Local Variables: None
39
;Shared Variables: Keycode – the actual key(s) pressed
; DebounceCount – the count used during debouncing to find
; a key
; DebounceFlag – the flag for the status of the debounced key
;Global Variables: None
;Input: Key pressed, but not necessarily released
;Output: None
;Error Handling: None
;Registers used: flags, AX, BX, CX
;Algorithms: None
;Data Structures: None
;Known bugs: None
;Limitation: Doesn’t know when key is released
;
;Pseudo Code
;
;Repeat
; Key_Available()
;Until zero flag = reset
;
; AL = keycode
; Table lookup AL to convert to keycode
; AL = value from table
; Reset to scan for a new key
;END
;Revision History
;2/14/02 Yiyang Gong initial revision
;2/24/02 Yiyang Gong fixed bug of setting flags
;4/12/02 Yiyang Gong changed table lookup method
; to return the keycode
GetKey PROC NEAR
Public GetKey
PUSH BX ;save registers
PUSH CX
PUSH DX
BLOCKERLOOP:
CALL Key_Available ;blocker function
BLOCKERCHECK:
CMP AL, False
JZ BLOCKERLOOP ;check zeroflag
;JNZ CONVERTKEY
;IF there is a key THEN
MOV BX, OFFSET(KeyTable) ;BX points at table
MOV CX, Offset(KeyTable) ;save the position of the table
DEC BX ;start table lookup loop
CONVERTKEY:
INC BX ;move to the next position of table
MOV AL, KeyCode ;move in the keycode
AND AL, EmptyKey ;only use low 5 bits of AL
MOV DL, CS:[BX] ;make sure that the key is valid
CMP DL, Key_Scan_Illegal ;IF Key is Valid THEN
JE ENDGETKEY
;JNE continue
CMP AL, CS:[BX] ;Check if the current position
JNE CONVERTKEY ;has the correct key
;JE ENDGETKEY ;If so THEN get the keycode
;ELSE loop back to converkey
ENDGETKEY:
SUB BX, CX ;get the position from the table lookup
MOV AL, BL ;put the position in the return value
XOR AH, AH ;clear AH, as return value is AX
MOV DebounceCount, Reset ;return debounce count to 0
MOV DebounceFlag, False ;stop getting the key
40
POP DX ;restore registers
POP CX
POP BX
RET
GetKey ENDP
;KeyAvailable()
;Description:
;The function is called with no arguments and returns with the AX reset
;if there is a key available and the zero flag set otherwise. In other words, if
;KeyAvailable() returns with the AX reset that means GetKey would return
;immediately if called because there is a key available (it won't need to wait
;for a key to be pressed). This function does not affect whether or not a key
;is available.
;Arguments: None
;Return value: AX set or reset
;Local Variables: None
;Shared Variables: None
;Global Variables: DebounceFlag - if a key has been debounced
; KeyCode - the data of the key pressed
;Input: Key pressed, but not necessarily released
;Output: None
;Error Handling: None
;Registers used: AX, flags
;Algorithms: None
;Data Structures: None
;Known bugs: None
;Limitation: None
;
;Pseudo Code
;ScanDebounce()
;If DebounceFlag = set THEN
; set AX to false
;Else
; set AX to true
;ENDIF
;END
;Revision History
;2/24/02 Yiyang Gong Initial revision
;4/20/02 Yiyang Gong changed the function to return
; the flag in AX instead of the zero flag
Key_Available PROC NEAR
Public Key_Available
CMP DebounceFlag, False ;IF the Key is ready THEN
JE NoKeyAvailable
;JNE KeyIsAvailable
KeyIsAvailable: ;Set AX to be True
MOV AX, True
JMP KeyAvailableEnd
NoKeyAvailable:
MOV AX, False ;Set AX to be False
;JMP KeyAvailableEnd
KeyAvailableEnd: ;ENDIF
RET
Key_Available ENDP
41
;ScanDebounce()
;Description: If a key is available, then checks to debounce the key. It then auto
;repeats (checks with a longer interval) to make sure key is pressed. If a key is not
;available, scan the keypad for keys pressed.
;Arguments: None
;Return value: Zero flag set or reset
;Local Variables: NewKey – the key scanned in one loop
;Shared Variables: CurrentKey – the key to be compared to for debouncing
; DebounceCount – the count that increments with the key that is being
; debounced
; AutoRepeatCount – the count that increments with the key that is
; autorepeated
; DebounceFlag – if a key has been debounced
; KeyCode – the data of the key pressed
; MaxCount – Once DebounceCount reaches this constant, the key will be
; debounced.
;Global Variables: None
;Input: Key pressed, but not necessarily released
;Output: None
;Error Handling: None
;Registers used: flags, AX, BX, CX, DX
;Algorithms: None
;Data Structures: None
;Known bugs: None
;Limitation: None
;
;Pseudo Code
;CurrentKey initialized to zero
;If CurrentKey = EmptyKey THEN
; Inc. I
; Scan keyport(I)
; Currentkey = scanned value
;ELSE
; IF DebounceFlag = set THEN
; Scan keyport(I)
; IF scanned value = Currentkey THEN
; Inc AutoRepeatCount
; ELSE
; DebounceFlag = reset
; Count = 0
; MaxCount = MaxDebounceCount
; ENDIF
; ELSE
; Scan Keyport(I)
; IF currentkey = scanned value THEN
; Inc DebounceCount
; Else
; DebounceCount = 0
; ENDIF
; ENDIF
;ENDIF
;
;IF DebounceCount = MaxCount THEN
; KeyCode = currentKey
; DebounceFlag = set
; MaxCount = MaxAutoCount
; DebounceCount = zero
;ENDIF
;
;IF AutoRepeatCount = MaxCount THEN
; KeyCode = currentKey
; DebounceFlag = set
; AutoRepeatCount = 0
;ENDIF
;END
;Revision History
;-2/14/02 final revision from EE51
;-4/20/02 deleted all tests for different ports
; as the port is all the base PCS select with only
; five keys
42
ScanDebounce PROC NEAR
Public ScanDebounce
PUSH AX ;save registers
PUSH BX
PUSH CX
PUSH DX
CMP CurrentKey, EmptyKey
JNE DEBOUNCESTATE
;JE SCANSTATE
SCANSTATE:
GETTHEKEY:
XOR DX, DX ;set up DX for keypad ports
MOV DL, PortNumber ;DX = keyport
IN AL, DX ;take in the value of the key
AND AL, EmptyKey
MOV CurrentKey, AL ;put value in current key
MOV AutoRepeatCount, Reset ;reset the counts for debouncing/autorepeating
MOV DebounceCount, Reset
MOV AX, MaxDebounceCount ;Maxcount = MaxDebounceCount (in debounce mode)
MOV MaxCount, AX ;through the AX register - no memory
;to memory access
JMP ENDSCANDEBOUNCE
DEBOUNCESTATE:
CMP DebounceFlag, True ;IF DebounceFlag = set THEN
JNE DEBOUNCING
;JE AUTOREPEATING
AUTOREPEATING:
XOR DX, DX ;prep DX for portnumber
MOV DL, PortNumber ;move in DX for keypad port
IN AL, DX ;take in value from port
AND AL, EmptyKey
MOV BL, CurrentKey ;prepare to compare CurrentKey and scanned key
CMP AL, BL
JNE RESETEVERYTHING ;IF CurrentKey = scannedkey
;JE CONTINUEREPEAT
CONTINUEREPEAT:
INC AutoRepeatCount ;AutoRepeatCount is incremented (as autorepeat
condition is met)
JMP ENDAUTOREPEAT
RESETEVERYTHING:
MOV DebounceFlag, False ;ELSE
MOV AutoRepeatCount, Reset ;reset all counts and debouncestate flags
MOV DebounceCount, Reset ;the new key requires new counts for
;debouncing and autorepeating
MOV AX, MaxDebounceCount ;in debounce mode, so used the
MOV MaxCount, AX ;max count that is for debouncing
MOV CurrentKey, EmptyKey ;make the current
;JMP ENDAUTOREPEAT
ENDAUTOREPEAT:
JMP ENDDEBOUNCESTATE ;ENDIF
DEBOUNCING:
XOR DX, DX ;prep DX for portnumber
MOV DL, PortNumber ;put in port number
IN AL, DX ;get value from keypad
AND AL, EmptyKey
MOV BL, CurrentKey ;prep BL to compare currentkey and scannedkey
CMP AL, BL
JNE RESETEVERYTHING1 ;IF currentkey = scannedkey
;JE CONTINUEDEBOUNCE
43
CONTINUEDEBOUNCE:
INC DebounceCount ;THEN
JMP ENDDEBOUNCING ;Increment Debounce count, as debounce condition is
;met
RESETEVERYTHING1:
MOV DebounceFlag, False ;ELSE
MOV DebounceCount, Reset ;reset debounce count (as it's in debounce mode)
MOV CurrentKey, EmptyKey ;so there there is no debounced key, and
;JMP ENDDEBOUNCING ;no key being pressed (or acknowledged)
ENDDEBOUNCING: ;ENDIF (for the debounce check)
;JMP ENDDEBOUNCESTATE
ENDDEBOUNCESTATE: ;ENDIF (for the debounce state)
;JMP ENDSCANDEBOUNCE
ENDSCANDEBOUNCE: ;ENDIF (for checking if a new key should
;be scanned for, or the current key
;be debounced)
CHECKDEBOUNCED:
MOV AX, MaxCount ;move MaxCount to be compared
MOV BX, DebounceCount ;move DebounceCount to be compared
CMP AX, BX
JNE CHECKAUTOREPEAT ;IF MaxCount = DebounceCount
;JE SETDEBOUNCED
SETDEBOUNCED:
MOV AL, CurrentKey ;key is debounced
MOV KeyCode, AL ;set keycode
MOV DebounceFlag, True ;set debounce flag to start autorepeating
MOV AX, MaxAutoCount ;MaxCount = MaxAutoCount
MOV MaxCount, AX
;JMP CHECKAUTOREPEAT ;ENDIF
CHECKAUTOREPEAT:
MOV AX, MaxCount ;move MaxCount to be compared
MOV BX, AutoRepeatCount ;move AutoRepeatCount to be compared
CMP AX, BX
JNE ENDALL ;IF MaxCount = AutoRepeatCount THEN
;JE SETREPEATED
SETREPEATED:
MOV AL, CurrentKey ;KeyCode = CurrentKey
MOV KeyCode, AL
MOV DebounceFlag, True ;reset DebounceFlag, AutoRepeatCount
MOV AutoRepeatCount, 0
;JMP ENDALL
ENDALL:
POP DX ;restore registers
POP CX
POP BX
POP AX
RET
SCANDEBOUNCE ENDP
;Table - KeyTable
;The position of the various key names determines the keycode given
;to each key
;4/20/02 Yiyang Gong Initial Revision
KeyTable LABEL BYTE
44
DB Key_Scan_Up ;key code 0
DB Key_Scan_Down ;key code 1
DB Key_Scan_Left ;key code 2
DB Key_Scan_Right ;key code 3
DB Key_Scan_Menu ;key code 4
DB Key_Scan_Illegal ;key code 5
;By the positions of the table setup in keypad.asm
;the keycode of the 5 key system is:
;Key_Up EQU 0
;Key_Down EQU 1
;Key_Left EQU 2
;Key_Right EQU 3
;Key_Menu EQU 4
;Key_Illegal EQU 5
CODE ENDS
;Data segment
DATA SEGMENT PUBLIC 'DATA'
CurrentKey DB ‘?’ ;The current key being scanned for
DebounceFlag DB ‘?’ ;the flag of the status of a key being
debounced
AutoRepeatCount DW ‘?’ ;the count during autorepeating
;to reach the maxcount
DebounceCount DW ‘?’ ;the count during debouncing a key
;to reach the maxcount
MaxCount DW ‘?’ ;the maximum count to reach for debouncing
;or autorepeating
KeyCode DB ‘?’ ;the code to be returned after it is
debouced
;or autorepeated
DATA ENDS
END
45
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; Keypad (keypad.inc) ;
; Keypad Handler ;
; Include File ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;Revision History
;-2/14/02 Initial Revision
;-5/6/02 Revised to work with 5 key system in Oscilloscope
;
MaxDebounceCount EQU 20 ;the number of milliseconds for debouncing a key
MaxAutoCount EQU 300 ;the number of milliseconds to wait for
;autorepeating a key
EmptyKey EQU 01FH ;the empty key (none of the 5 keys pressed - 11111B)
True EQU 1
False EQU 0
Reset EQU 0
Key_Scan_Up EQU 00FH ;the codes for each key pressed
Key_Scan_Down EQU 017H
Key_Scan_Left EQU 01BH
Key_Scan_Right EQU 01DH
Key_Scan_Menu EQU 01EH
Key_Scan_Illegal EQU 000H
;By the positions of the table setup in keypad.asm
;the keycode of the 5 key system is:
;Key_Up EQU 0
;Key_Down EQU 1
;Key_Left EQU 2
;Key_Right EQU 3
;Key_Menu EQU 4
;Key_Illegal EQU 5
PortNumber EQU 0H ;the port to read key presses from
; Timer Defintions
; Addresses
Tmr2Ctrl EQU 0FF66H ;address of Timer 2 Control Register
Tmr2MaxCnt EQU 0FF62H ;address of Timer 2 Max Count A Register
Tmr2Count EQU 0FF60H ;address of Timer 2 Count Register
; Control Register Values
Tmr2CtrlVal EQU 0E021H ;value to write to Timer 2 Control Register
;1--------------- enable timer
;-1-------------- write to control
;--1------------- interrupts
;----------1----- max counts
;---------------1 continuous mode
; Interrupt Vectors
Tmr2Vec EQU 19 ;interrupt vector for Timer 2
; Register Values
INTCtrlrCVal EQU 00001H ;set priority for timers to 1 and enable
Timer0EOI EQU 00008H ;Timer EOI command (same for all timers)
; Timing Definitions
COUNTS_PER_MS EQU 2000 ;number of timer counts per 1 ms
46
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;
; The file for handling putting
; pixels on the LCD (lcd.asm)
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Clear_Display()
; -This function clears the display (makes all pixels white) by cycling
; through the rows and columns in the appropriate addresses in VRAM and
; writing the clear pixel function
;
;Plot_pixel(x, y, pixel_color)
; - This function plots a specific pixel a specific color. First the function
; finds the appropriate address of VRAM to write to by normalizing everything
; to the first quadrant. At the same time, it finds the required number of
; shifts to shift the pixel value; this pixel value will then be written VRAM
; maintaining the state for the rest of the quad of pixels.
;SwapBuffer()
; - This functions swaps the buffer being displayed and the buffer being written
; to in memory. The two buffer should never be the same block of memory
; at any time.
;ModifyBuffer()
; - This function only changes the buffer being displayed. This function is a
; fix to the problem in one-shot mode where the one-shot trace, as well
; as the one-shot menu is displayed on the hidden buffer. This fix shows
; the hidden buffer
;InitBuffer()
; - This function initializes the position of the buffer to be written to,
; which is not the buffer being displayed
;Author: Yiyang Gong
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Revision History
;- 6/7/02 Initial revision
;- 6/10/02 Added double buffering through the Swapbuffer and ModifyBuffer functions
Name LCD
CGROUP GROUP CODE
DGROUP GROUP DATA
$include(lcd.inc)
EXTRN Key_Available:NEAR
CODE SEGMENT PUBLIC 'CODE'
ASSUME CS:CGROUP, DS:DGROUP
;InitBuffer()
;Description:
; The function clears the LCD display by filling the appropriate
; rows of the VRAM with empty bits (0's).
;Arguments: None
;Return Value: None
;Local Variables: None
;Shared Variables: BaseAddress - the address of the buffer to write to
;Global Variables: None
;Input: None
;Output: None
;Error Handling: None
;Algorithms: None
;Data Structures: None
;Registers Used: None
;Pseudo Code
;BaseAddress is the alternate address
;END
;Revision History
;6/10/02 Yiyang Gong Initial Revision
;Note that this function assumes that the buffer displayed intially
;is the lower block of memory at row 0. This assumption is correct,
47
;as the lattice code starts with the lower block displayed.
InitBuffer PROC NEAR
Public InitBuffer
MOV BaseAddress, AltAddress
RET
InitBuffer ENDP
;void Clear_Display(void)
;Description:
; The function clears the LCD display by filling the appropriate
; rows of the VRAM with empty bits (0's).
;Arguments: None
;Return Value: None
;Local Variables: DX - the row address
; BX - the column address
;Shared Variables: None
;Global Variables: None
;Input: None
;Output: A cleared LCD display
;Error Handling: None
;Algorithms: None
;Data Structures: None
;Registers Used: AX, BX, ES, DI, flags
;Pseudo Code
;Row = 0
;Col = 0
;FOR Col = 0 to 239
;FOR ROW = 0 to 63
; Clear pixel (in all four quadrants)
;ENDFOR
;ENDFOR
;END
;Revision History
;6/7/02 Yiyang Gong Initial Revision
Clear_Display PROC NEAR
Public Clear_Display
PUSH AX ;save the registers
PUSH BX
PUSH ES
PUSH DI
MOV DI, VRAMStartAddr ;use ES as the segment address
MOV ES, DI
XOR AX, AX ;clear AX to use as empty pixel
XOR DI, DI ;BX as column, and DI as row
XOR BX, BX
RowLoop:
MOV ES:[BX+DI], AL ;clear all 4 quadrants
INC DI ;mov to next row
CMP DI, NumRows ;IF DI = 64 THEN
JGE BottomQuads ;pixel is in the bottom quads
JL TopQuads
49
BottomQuads:
SUB AX, NumRows ;adjust the row to be in the top quad
INC CL ;one shift is needed between top and bottom quads
;JMP TopQuads
TopQuads: ;ELSE do nothing ENDIF
CMP BX, NumCols ;IF BX >= 240 THEN
JGE RightQuads ;pixel is in the right quads
JL LeftQuads
RightQuads:
SUB BX, NumCols ;adjust the row to be in the left quad
INC CL ;two shifts are needed between the left and right quads
INC CL
LeftQuads:
ROL BX, OneByte ;Make BX the physical column address (upper byte)
ADD BX, AX ;now make BX the physical RAM address (both bytes)
MOV AX, VRAMStartAddr ;Setup ES as the segment address
MOV ES, AX
CMP DX, Pixel_Black ;If the pixel should be written white
JE PlotThePixel
;JNE CLearThePixel
ClearThePixel: ;THEN
ROL DX, CL ;rotate the clear pixel to the correct position
;(1st-4th bits)
XOR AH, AH ;clear AH for and command later
MOV AL, ES:[BX] ;take in the current quad of pixels
AND AX, DX ;clear the appropriate pixel
MOV ES:[BX], AL ;write back out the quad of pixels
JMP EndPlotPixel
PlotThePixel: ;ELSE
ROL DX, CL ;rotate the black pixel to the correct position
;(1st-4th bits)
XOR AH, AH ;clear AH for and command later
MOV AL, ES:[BX] ;take in the current quad of pixels
OR AX, DX ;make black the appropriate pixel
MOV ES:[BX], AL ;write back out the quad of pixels
;ENDIF
EndPlotPixel:
POP ES ;restore the registers
POP DX
POP CX
POP BX
POP AX
POP BP
RET
Plot_Pixel ENDP
;swapbuffer()
;Description: This functions swaps the buffer being displayed and the buffer being
;written to in memory. The two buffer should never be the same block of memory
;at any time.
;Arguments: None
;Return Value: None
;Local Variables: None
;Shared Variables: BaseAddress - the address block (starting at row 0, or
; row 64) to write to. This assumes that the baseaddresses
; begins at rows 0 and 64
;Global Variables: None
;Input: None
;Output: PCS4, the chip select to swap the buffer to be displayed
; going through the lattice chip
;Error Handling: None
;Algorithms: None
;Data Structures: None
;Registers Used: AX, DX
50
;Known Bugs: There is an error associated with double buffering. When the mainloop goes
;to one-shot mode, the mainloop plots the trace, but never ends the traces. Thus, the
;trace and the menu are both in the hidden buffer during the one-shot mode; the one-shot
;trace is never displayed.
;Pseudo Code
;Change the base address to write to the other block
;(0 to 64, or 64 to 0)
;switch to the other buffer to display
;END
;Revision History
;6/10/02 Yiyang Gong Initial Revision
SwapBuffer PROC NEAR
Public SwapBuffer
PUSH DX ;save registers
PUSH AX
MOV DX, ChangeBufferPort ;set up a command giving PCS4
IN AL, DX ;activate PCS for a read cycle
XOR BaseAddress, AltAddress ;change the base address to be written to
;from 0 to 64 or 64 to 0
POP AX ;restore registers
POP DX
RET
SwapBuffer ENDP
;ModifyBuffer()
;Description: This function only changes the buffer beign displayed. This function is a
; fix to the problem in one-shot mode where the one-shot trace, as well
; as the one-shot menu is displayed on the hidden buffer. This fix shows
; the hidden buffer.
;Arguments: None
;Return Value: None
;Local Variables: None
;Shared Variables: None
;Global Variables: None
;Input: None
;Output: PCS4, the chip select to swap the buffer to be displayed
; going through the lattice chip
;Error Handling: None
;Algorithms: None
;Data Structures: None
;Registers Used: AX, DX
;Known Bugs: This function attempts to resolve the error created by the
;swapbuffer function during double buffering. However, now the error is not drawing the
;one-shot trace. Although the menu is displayed, the plot_trace() function still draws
;the trace to the hidden buffer, and the one-shot trace is displayed after the scope
;returns to normal mode.
;Pseudo Code
;switch to the other buffer to display
;END
;Revision History
;6/10/02 Yiyang Gong Initial Revision
ModifyBuffer PROC NEAR
Public ModifyBuffer
PUSH DX ;save registers
PUSH AX
MOV DX, ChangeBufferPort ;set up a command giving PCS4
IN AL, DX ;activate PCS4 for a read cycle
POP AX ;restore registers
POP DX
51
RET
ModifyBuffer ENDP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Boot-up Screen
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;The boot up screen requires a main function LScope(), and a helper function
;PlotBox(). However, it's code will not be given as it was written in assembly
;(should not reverse the abstraction and call Plot_line), and required many constants.
;(aka ugly code). Suffice it to say that the function draws a line in on the screen in
;the shape of "LScope" and draws a box around the line for the fill in effect
CODE ENDS
DATA SEGMENT PUBLIC 'DATA'
BaseAddress DW '?' ;the base address for which buffer in memory is
displayed
DATA ENDS
END
52
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Include file (lcd.inc)
; for the LCD functions
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;Revision History
;-6/7/02 initial revision
;
NumRows EQU 64 ;the number of rows per quadrant
NumCols EQU 240 ;the number of columns per quadrant
;Note that by adding 1, these are also the number of rows and columns
;occupied by the screen in VRAM
Pixel_Black EQU 00001H ;The 1 in the first place will be
;rotated left to plot a pixel black
Pixel_White EQU 0FFFEH ;The 0 in the first place will be
;rotated left to plot a pixel white
VRAMStartAddr EQU 4000H ;the starting address of the VRAM
;set by the MMCS value
OneByte EQU 8 ;A one byte shift/rotate is
;equal to a 8 bit shift/rotate
AltAddress EQU 64 ;the starting address of the alternate
;address block (either starting with 0 rows
;or with 64 rows)
ChangeBufferPort EQU 200H ;the PCS4 select line to change the row transfer
;address from the lower block of the buffer
;to the upper block of the buffer
53
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;
; File that handles all the trigger (trigger.asm)
; trigger delays, and subsequent sample transfers
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;InstallTriggerHandlers()
; The function installs the interrupt handlers for the trigger delay
; (timer0) and the sample transfer (int0) in the interrupt vectors.
;InitTriggerValues()
; Initializes all the trigger variables to their proper
; values. This starts the sample buffer at position 0, resets the
; SampleDoneFlag, and initially masks the interrupt for the sample
; data transfer.
;TriggerDelayHandler()
; This function handles the trigger delay. After
; this timer0 reaches its max count, the interrupt unmasks
; int0 (the data transfer interrupt), to allow data to be transfered
; from the FIFO to memory. This function will also turn the
; timer0 interrupt off (so that not a another delay is recorded
; for the one call to start_sample).
;SampleDataHandler()
; This function will take in the samples from the FIFO
; after its interrupt is enabled. The interrupt is from the empty
; pin of the FIFO; when the FIFO is not empty, the interrupt
; will occur.
;;InitTriggerTimer()
; This function will take in the samples from the FIFO
; after its interrupt is enabled. The interrupt is from the empty
; pin of the FIFO; when the FIFO is not empty, the interrupt
; will occur.
;void Start_Sample(void)
; This function will immediately start taking samples.
; Because of the PLD design, the trigger value must be put out to the
; PLD before taking any sample. Thus, the saved current trigger (given
; by the last call to set_trigger()) will be given, and then the timer0
; that handles the trigger delay will be enabled to count the
; number of samples needed to delay by, once the sample is triggered.
;;void Set_Sample_Rate(long int number_of_samples)
; This function set the sample rate (i.e. the frequency of timer 1) of the scope.
; It will do so by converting the require number of samples to a count on timer 1.
;unsigned char far *sample_done(void)
; If the current sample is done, then return a far pointer to the
; where the sample is (in the sample buffer) in DX|AX. If the current sample
; is not done, return NULL in DX|AX.
;void set_trigger(int level, int slope)
; The function sets the trigger level by converting the level and
; slope into a single number and outputting that number to the PLD.
; The PLD will then remember trigger for one sample. The function will also
; save the current trigger (the last trigger to the call of set_trigger()).
;void set_delay(long int number_of_samples)
; The function will set the delay (in number of samples) for the trigger.
; The number of samples will be directly written to the timer0 maxcount,
; as timer1 counts the number samples to delay by.
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Revision History
;-5/23/02 Initial revision of all functions
;-5/24/02 Started using the interrupt mask register to mask Int0
;-5/25/02 fixed error with set sample rate with minimun sample delay as 0
; this means that the minimum sample rate is actually 65535
;-6/1/02 turn off the sample timer when attempting to find the trigger
; in calling start_sample() to get a more accurate trigger
;
Name TriggerHandler
CGROUP GROUP CODE
DGROUP GROUP DATA
$include(trigger.inc)
54
CODE SEGMENT PUBLIC 'CODE'
ASSUME CS:CGROUP, DS:DGROUP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;InstallTriggerhandlers
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Description: Installs the interrupt handlers for the triggerdelay (timer0) and
; the sample transfer (int0) from the FIFO.
;Arguments: None
;Return value: None
;Local Variables: None
;Shared Variables: None
;Global Variables: None
;Input: None
;Output: None
;Error Handling: None
;Registers used: AX, ES
;Algorithms: None
;Data Structures: None
;Known bugs: None
;Limitations: None
;Pseudo code
;Put Handler for SampleTransfer in Int0 vector
;Put Handler for TriggerDelay in Timer0
;END
;Revision History
; -5/23/02 Initial Revision
InstallTriggerHandlers PROC NEAR
Public InstallTriggerHandlers
PUSH ES ;save registers
PUSH AX
XOR AX, AX ;clear ES (interrupt vectors are in segment 0)
MOV ES, AX
;store the vector for the 2 interrupts used
MOV ES: WORD PTR (4 * Int0Vec), OFFSET(SampleDataHandler)
;int0 - sample transfer
MOV ES: WORD PTR (4 * Int0Vec + 2), SEG(SampleDataHandler)
MOV ES: WORD PTR (4 * Tmr0Vec), OFFSET(TriggerDelayHandler)
;timer0 - sample delay
MOV ES: WORD PTR (4 * Tmr0Vec + 2), SEG(TriggerDelayHandler)
POP AX ;restore registers
POP ES
RET ;all done, return
InstallTriggerHandlers ENDP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;InitTriggerValues()
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Description: Initializes all the trigger variables to their proper
; values. This starts the sample buffer at position 0, resets the
; SampleDoneFlag, and initially masks the interrupt for the sample
; data transfer.
;Arguments: None
;Return value: None
;Local Variables: None
;Shared Variables: BufferPosition - the position to write to in the buffer
; SampleDoneFlag – the status for finished taking in a sample
;Global Variables: None
;Input: None
55
;Output: None
;Error Handling: None
;Registers used: AX, DX
;Algorithms: None
;Data Structures: None
;Known bugs: None
;Limitations: None
;Pseudo code
;Start buffer at position 0
;reset the sampledone flag
;mask int0 (the sample transfer interrupt)
;END
;Revision History
; -5/23/02 Yiyang Gong Initial Revision
; -5/24/02 Yiyang Gong Used interrupt mask register
InitTriggerValues PROC NEAR
Public InitTriggerValues
PUSH AX ;save registers
PUSH DX
MOV BufferPosition, Start ;start the buffer at position 0
MOV SampleDoneFlag, Null ;reset the sampledoneflag
MOV DX, Int0CtrlAddr ;initializes the sample
MOV AX, Int0CtrlVal ;transfer interrupts
OUT DX, AL
MOV DX, IntMaskAddr ;start with Int0 masked
IN AL, DX ;by setting the bit for int0
OR AL, StopInt0 ;in the interrupt mask register
OUT DX, AL
MOV DX, FIFOResetPort ;reset the fifo
IN AL, DX
POP DX ;restore Registers
POP AX
RET
InitTriggerValues ENDP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;TriggerDelayHandler()
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Description: This function handles the trigger delay. After
; this timer reaches its max count, the interrupt unmasks
; int0 (the data transfer interrupt), to allow data to be transfered
; from the FIFO to memory. This function will also turn the
; timer0 interrupt off (so that not a another delay is recorded
; for the one call to start_sample).
;Arguments: None
;Return value: None
;Local Variables: None
;Shared Variables: None
;Global Variables: None
;Input: None
;Output: None
;Error Handling: None
;Registers used: AX, DX
;Algorithms: None
;Data Structures: None
;Known bugs: None
;Limitations: None
;Pseudo code
; Allow int0 interrupts (start the data transfers)
; Disable timer0
; Send EOI
; END
;Revision History
56
; -5/23/02 Yiyang Gong Initial Revision
TriggerDelayHandler PROC NEAR ;FOR Timer0, after the trigger
Public TriggerDelayHandler
PUSH AX ;save registers
PUSH DX
MOV DX, IntMaskAddr ;after the trigger, the int0 (from FIFO)
IN AL, DX ;is enabled to take the data
AND AL, AllowInt0 ;by unmasking the interrupt
OUT DX, AL
MOV DX, Tmr0CtrlAddr ;the timer0 interrupt is then
IN AX, DX ;disable by reseting the
OR AX, WriteEnableTmr0 ;enable write to timer 0 register
AND AX, DisableTmr0 ;disable timer0 to stop all trigger delays\
;after this
OUT DX, AL
MOV DX, INTCtrlEOI ;send the EOI to the interrupt controller
MOV AX, Timer0EOI
OUT DX, AL
POP DX ;restore registers
POP AX
IRET
TriggerDelayHandler ENDP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;SampleDataHandler()
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Description: This function will take in the samples from the FIFO
; after its interrupt is enabled. The interrupt is from the empty
; pin of the FIFO; when the FIFO is not empty, the interrupt
; will occur.
;Arguments: None
;Return value: None
;Local Variables: None
;Shared Variables: BufferPosition - The current position of the sample buffer
;Global Variables: None
;Input: None
;Output: None
;Error Handling: None
;Registers used: AX, BX, DX, flags
;Algorithms: None
;Data Structures: None
;Known bugs: None
;Limitations: None
;Pseudo code
;Take in sample from the FIFO
;move sample to sample buffer
;move to next buffer position
;IF Enough Samples have been taken THEN
;turn off INT0 by masking it
;ELSE do nothing
;ENDIF
;send EOI
;END
;Revision History
; -5/23/02 Yiyang Gong Initial Revision
SampleDataHandler PROC NEAR ;From EF of FIFO
Public SampleDataHandler
PUSH AX ;save registers
PUSH BX
PUSH DX
MOV DX, FIFOPort ;move the to get the data from
57
IN AL, DX ;get the data from the FIFO
MOV BX, Offset(SampleBuffer) ;move the pointer to the
ADD BX, BufferPosition ;correct position in the samplebuffer
MOV [BX], AL ;transfer the data into the samplebuffer
INC BufferPosition ;move the bufferposition into the next place
CMP BufferPosition, SampleLength ;check if enough samples have been collected
JNE NoMoreSamplesTaken ;IF not enough THEN end handler
;JE StopRecognizingSamples
StopRecognizingSamples: ;ELSE
MOV DX, IntMaskAddr ;turn off Int0
IN AL, DX ;by masking the int0 bit in the IntMask
register
OR AX, StopInt0
OUT DX, AL
MOV SampleDoneFlag, NOT(Null) ;also set the sampledone flag
;JMP NoMoreSamplesTaken
NoMoreSamplesTaken: ;ENDIF
MOV DX, IntCtrlEOI ;send the EOI to the interrupt controller
MOV AX, Int0EOI
OUT DX, AL
POP DX ;restore registers
POP BX
POP AX
IRET
SampleDataHandler ENDP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;InitTriggerTimer()
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Description: This function will take in the samples from the FIFO
; after its interrupt is enabled. The interrupt is from the empty
; pin of the FIFO; when the FIFO is not empty, the interrupt
; will occur.
;Arguments: None
;Return value: None
;Local Variables: None
;Shared Variables: None
;Global Variables: None
;Input: None
;Output: None
;Error Handling: None
;Registers used: AX, DX
;Algorithms: None
;Data Structures: None
;Known bugs: None
;Limitations: None
;Pseudo code
;Setup timer0, for the number of sample delays
;Setup timer0, for no initial interrupts
;Setup timer1, for sampling frequency
;Setup timer1, for no interrupts (ever), running continuously
;Setup timerinterrupt priorities
;END
;Revision History
; -5/23/02 Yiyang Gong Initial Revision
InitTriggerTimer PROC NEAR
Public InitTriggerTimer
58
PUSH DX ;save registers
PUSH AX
MOV DX, Tmr0CountAddr ;initialize the count register to 0
XOR AX, AX
OUT DX, AL
MOV DX, Tmr0MaxCountAddr ;setup max count for number of sample delays
MOV AX, Tmr0MaxCountVal
OUT DX, AL
MOV DX, Tmr0CtrlAddr ;setup the control register, no interrupts
MOV AX, Tmr0CtrlVal ;single run mode
OUT DX, AL
MOV DX, Tmr1Count ;initialize the count register to 0
XOR AX, AX
OUT DX, AL
MOV DX, Tmr1MaxCountAddr ;setup max count for 1ms counts
MOV AX, Tmr1MaxCountVal
OUT DX, AL
MOV DX, Tmr1CtrlAddr ;setup the control register, no interrupts
MOV AX, Tmr1CtrlVal ;continuously running
OUT DX, AL
MOV DX, INTTmrCtrlAddr ;setup the interrupt control register
MOV AX, INTTmrCtrlVal ;timers are set to 1 as priority
OUT DX, AL
MOV DX, INTCtrlEOI ;send a non-specific EOI (to clear out controller)
MOV AX, NonSpecEOI
OUT DX, AL
POP AX ;restore registers
POP DX
RET ;done so return
InitTriggerTimer ENDP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;void Start_Sample(void)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Description: This function will immediately start taking samples.
; Because of the PLD design, the trigger value must be put out to the
; PLD before taking any sample. Thus, the saved current trigger (given
; by the last call to set_trigger()) will be given, and then the timer0
; that handles the trigger delay will be enabled to count the
; number of samples needed to delay by, once the sample is triggered.
;Arguments: None
;Return value: None
;Local Variables: None
;Shared Variables: CurrentTrigger - The current trigger value to be outputted
; the PLD
;Global Variables: None
;Input: None
;Output: None
;Error Handling: None
;Registers used: AX, DX
;Algorithms: None
;Data Structures: None
;Known bugs: None
;Limitations: None
;Pseudo code
;turn off timer1 to stop any sample from triggering
59
;give trigger value
;enable timer0
;enable timer1 to let a trigger be found
;END
;Revision History
;-5/23/02 Yiyang Gong Initial Revision
;-6/1/02 Yiyang Gong disabled timer1 when finding a trigger - gets a more
; accurate trigger (close to trigger value)
Start_Sample PROC NEAR
Public Start_Sample
PUSH AX ;save registers
PUSH DX
MOV DX, Tmr1CtrlAddr ;look at timer1 controller
IN AL, DX
AND AX, TurnOffTmr1 ;turn off the timer1
OR AX, EnableWriteTmr1 ;and its interrupt
OUT DX, AL
MOV AL, CurrentTrigger ;get the current trigger value
MOV DX, TriggerValuePort ;and output it again
OUT DX, AL
MOV DX, Tmr0CtrlAddr ;mov in the timer0 control address to enable it
IN AL, DX ;take in current state of timer0
OR AX, EnableTmr0 ;enable the timer
OUT DX, AL ;write the enable value back out
MOV DX, Tmr1CtrlAddr ;take the timer1 controller
IN AL, DX ;turn on the timer
OR AX, TurnOnTmr1 ;with interrupts off
AND AX, Tmr1IntOff ;to allow for a trigger to be found
OUT DX, AL ;by the lattice
POP DX ;restore registers
POP AX
RET
Start_Sample ENDP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;int Set_Sample_Rate(long int number_of_samples)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Description: This function set the sample rate (i.e. the frequency of timer 1) of the
;scope. It will do so by converting the require number of samples to a count on timer 1.
;Arguments: None
;Return value: samples (AX) - the number of samples that will be taken at that
; sample rate
;Local Variables: None
;Shared Variables: None
;Global Variables: None
;Input: None
;Output: None
;Error Handling: None
;Registers used: AX, BX, DX, BP
;Algorithms: None
;Data Structures: None
;Known bugs: None
;Limitations: None
;Pseudo code
;divide 1 Megahertz by the number of samples required per second
;the number * 2 is the number counts needed
;write the number of counts to the timer1 max counts
;return the appropriate number of samples that will be taken
;END
;Revision History
; -5/23/02 Yiyang Gong Initial Revision
60
;where the long int is located on the stack
RateHighAddr EQU 6
RateLowAddr EQU 4
Set_Sample_Rate PROC NEAR
Public Set_Sample_Rate
PUSH BP
MOV BP, SP
PUSH BX ;save registers
PUSH DX
MOV AX, [BP+RateLowAddr] ;retrieve the low word of the rate
MOV DX, [BP+RateHighAddr] ;retrieve the high word of the rate
Scaler:
MOV BX, Scaler50 ;move 50 as a scaler into BX
DIV BX ;divide the number of samples by 50
MOV BX, AX
;the formula is:
;1*10^6/x = (1*10^6/50)/(x/50)
;as x is a minimum of 50 at 20ms
XOR DX, DX ;clear DX for second division
MOV AX, OneMegScale50 ;divide with the 1MHz value also scaled down by 50
DIV BX ;get the counts in Ax
ADD AX, AX ;Doubles the number of samples
;(for internal 2 MHz clock)
MOV BX, AX ;saves number of samples
MOV DX, Tmr1MaxCountAddr ;Actually sets the frequency
OUT DX, AL
MOV AX, SampleLength ;returns number of samples to be taken
;(always constant)
POP DX
POP BX
POP BP
RET
Set_Sample_Rate ENDP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;unsigned char far *sample_done(void)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Description: If the current sample is done, then return a far pointer to the
; where the sample is (in the sample buffer) in DX|AX. If the current sample
; is not done, return NULL in DX|AX.
;Arguments: None
;Return value: a 32-bit pointer in DX|AX
;Local Variables: None
;Shared Variables: SampleDoneFlag - If set, the sample is done
; if reset, the sample is not done
; BufferPosition – is reset to the start with new sample
;Global Variables: None
;Input: None
;Output: None
;Error Handling: None
;Registers used: AX, DX
;Algorithms: None
;Data Structures: None
;Known bugs: None
;Limitations: None
;Pseudo code
;IF SampleDoneFlag = set THEN
; mov samplebuffer address into DX|AX
61
; reset sampledoneflag
; reset samplebuffer, bufferposition
;ELSE
; mov Null into DX|AX
;ENDIF
;END
;Revision History
; -5/23/02 Yiyang Gong Initial Revision
Sample_Done PROC NEAR
Public Sample_Done
CMP SampleDoneFlag, Null ;IF SampleDone = set THEN
JE SampleNotYetDone
;JNE SampleIsDone
SampleIsDone: ;THEN
MOV AX, Offset(SampleBuffer) ;mov samplebuffer address into DX|AX
MOV DX, Seg(SampleBuffer)
MOV BufferPosition, Start ;reset bufferposition
MOV SampleDoneFlag, Null ;sampledone is acknowledged and reset
JMP SampleDoneEnd
SampleNotYetDone: ;ELSE
MOV AX, Null ;mov NULL into DX|AX
MOV DX, Null
;JMP SampleDoneEnd ;ENDIF
SampleDoneEnd:
RET
Sample_Done ENDP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;void set_trigger(int level, int slope)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Description: The function sets the trigger level by converting the level and
; slope into a single number and outputting that number to the PLD.
; The PLD will then remember trigger for one sample. The function will also
; save the current trigger (the last trigger to the call of set_trigger()).
;Arguments: level - the level at which the sample triggers (0 - 127)
; slope - + or - slope to trigger on
; both are passed on the stack
;Return value: None
;Local Variables: None
;Shared Variables: CurrentTrigger – this variable is saved with every
; call to this function
;Global Variables: None
;Input: None
;Output: None
;Error Handling: None
;Registers used: AX, BX, DX, BP
;Algorithms: None
;Data Structures: trigger - the upper 7 bits are the level
; the lower bit is the slope (0 is positive slope, 1 is negative)
;Known bugs: None
;Limitations: None
;Pseudo code
;get the level and the slope
;convert the level and slope into one number
;output the number to the PLD
;END
;Revision History
; -5/23/02 Yiyang Gong Initial Revision
;where on the stack the arguements are located
LevelAddr EQU 4
SlopeAddr EQU 6
;void set_trigger(int level, int slope)
62
Set_Trigger PROC NEAR
Public Set_Trigger
PUSH BP ;save BP
MOV BP, SP ;use BP to retrieve arguments off the stack
PUSH AX ;save registers
PUSH BX
PUSH DX
MOV AX, [BP+LevelAddr] ;AX = slope
MOV BX, [BP+SlopeAddr] ;BX = level
SHL AX, 1 ;because slope is only 7 bits, shift to the
;upper seven bits
OR AX, BX ;let the level occupied the last bit
MOV CurrentTrigger, AL ;save the current trigger for
;multiple samples later samples
MOV DX, TriggerValuePort ;write the value to the PLD
OUT DX, AL
POP DX ;restore registers
POP BX
POP AX
POP BP
RET
Set_Trigger ENDP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;void set_delay(long int number_of_samples)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Description: The function will set the delay (in number of samples) for the trigger.
; The number of samples will be directly written to the timer0 maxcount,
; as timer1 counts the number samples to delay by.
;Arguments: number_of_samples - 32-bits passed on the stack
;Return value: None
;Local Variables: None
;Shared Variables: None
;Global Variables: None
;Input: None
;Output: None
;Error Handling: None
;Registers used: AX, DX, BP
;Algorithms: None
;Data Structures: None
;Known bugs: None
;Limitations: None
;Pseudo code
;Write delay into timer0 maxcount
;END
;Revision History
; -5/23/02 Yiyang Gong Initial Revision
;where the arguments are located on the stack
DelayLowAddr EQU 4
DelayHighAddr EQU 6
Set_Delay PROC NEAR
Public Set_Delay
PUSH BP ;save BP
MOV BP, SP ;use BP to retrieve arguments on stack
PUSH AX ;save registers
PUSH DX
;Assume that the trigger delay is 0
or key is pressed for a menu item. Also included are the functions
for displaying the current menu option selection. The functions included
are:
display_mode - display trigger mode
display_scale - display the scale type
display_sweep - display the sweep rate
display_trg_delay - display the tigger delay
display_trg_level - display the trigger level
display_trg_slope - display the trigger slope
mode_toggle - toggle the mode between "Normal" and "One-Shot"
no_display - nothing to display for option setting
no_menu_action - no action to perform for or key
scale_toggle - toggle the scale type
set_scale - set the scale type
set_sweep - set the sweep rate
set_trg_delay - set the tigger delay
set_trg_level - set the trigger level
set_trg_slope - set the trigger slope
set_trigger_mode - set the trigger mode
sweep_down - decrease the sweep rate
sweep_up - increase the sweep rate
trg_delay_down - decrease the trigger delay
trg_delay_up - increase the trigger delay
trg_level_down - decrease the trigger level
trg_level_up - increase the trigger level
trg_slope_toggle - toggle the trigger slope between "+" and "-"
The local functions included are:
adjust_trg_delay - adjust the trigger delay for a new sweep rate
cvt_num_field - converts a numeric field value to a string
The locally global variable definitions included are:
delay - current trigger delay
level - current trigger level
scale - current display scale type
slope - current trigger slope
sweep - current sweep rate
sweep_rates - table of information on possible sweep rates
trigger_mode - current triggering mode
Revision History
3/8/94 Glen George Initial revision.
3/13/94 Glen George Updated comments.
3/13/94 Glen George Changed all arrays of constant strings to be
static so compiler generates correct code.
3/13/94 Glen George Changed scale to type enum scale_type and
output the selection as "None" or "Axes".
This will allow for easier future expansion.
3/13/94 Glen George Changed name of set_axes function (in
tracutil.c) to set_display_scale.
3/10/95 Glen George Changed calculation of displayed trigger
level to use constants MIN_TRG_LEVEL_SET and
MAX_TRG_LEVEL_SET to get the trigger level
range.
3/17/97 Glen George Updated comments.
6/13/02 Yiyang Gong Changed the mode_toggle() function, so that
double buffering shows at least the menu
in one-shot mode. Also added 1us sampling
67
in the sweep rates
*/
/* library include files */
/* none */
/* local include files */
#include "interfac.h"
#include "scopedef.h"
#include "lcdout.h"
#include "menuact.h"
#include "tracutil.h"
/* local function declarations */
void adjust_trg_delay(int, int); /* adjust the trigger delay for new sweep */
void cvt_num_field(long int, char *); /* convert a number to a string */
/* locally global variables
/* trace parameters */
static enum trigger_type trigger_mode; /* current triggering mode */
static enum scale_type scale; /* current scale type */
static int sweep; /* sweep rate index */
static int level; /* current trigger level */
static enum slope_type slope; /* current trigger slope */
static long int delay; /* current trigger delay */
/* sweep rate information */
static const struct sweep_info sweep_rates[] =
{ {1000000L, " 1 \004s "}, /* added for 1Mhz sampling*/
{ 500000L, " 2 \004s " },
{ 200000L, " 5 \004s " },
{ 100000L, " 10 \004s " },
{ 50000L, " 20 \004s " },
{ 20000L, " 50 \004s " },
{ 10000L, " 100 \004s" },
{ 5000L, " 200 \004s" },
{ 2000L, " 500 \004s" },
{ 1000L, " 1 ms " },
{ 500L, " 2 ms " },
{ 200L, " 5 ms " },
{ 100L, " 10 ms " },
{ 50L, " 20 ms " } };
/*
no_menu_action
Description: This function handles a menu action when there is nothing
to be done. It just returns.
Arguments: None.
Return Value: None.
Input: None.
Output: None.
Error Handling: None.
Algorithms: None.
Data Structures: None.
68
Global Variables: None.
Author: Glen George
Last Modified: Mar. 8, 1994
*/
void no_menu_action()
{
/* variables */
/* none */
/* nothing to do - return */
return;
}
/*
no_display
Description: This function handles displaying a menu option's setting
when there is nothing to display. It just returns,
ignoring all arguments.
Arguments: x_pos (int) - x position (in character cells) at which to
display the menu option (not used).
y_pos (int) - y position (in character cells) at which to
display the menu option (not used).
style (int) - style with which to display the menu option
(not used).
Return Value: None.
Input: None.
Output: None.
Error Handling: None.
Algorithms: None.
Data Structures: None.
Global Variables: None.
Author: Glen George
Last Modified: Mar. 8, 1994
*/
void no_display(int x_pos, int y_pos, int style)
{
/* variables */
/* none */
/* nothing to do - return */
return;
}
/*
set_trigger_mode
69
Description: This function sets the triggering mode to the passed
value.
Arguments: m (enum trigger_type) - mode to which to set the
triggering mode.
Return Value: None.
Input: None.
Output: None.
Error Handling: None.
Algorithms: None.
Data Structures: None.
Global Variables: trigger_mode - initialized to the passed value.
Author: Glen George
Last Modified: Mar. 8, 1994
*/
void set_trigger_mode(enum trigger_type m)
{
/* variables */
/* none */
/* set the trigger mode */
trigger_mode = m;
/* set the new mode */
set_mode(trigger_mode);
/* all done setting the trigger mode - return */
return;
}
/*
mode_toggle
Description: This function handles toggling (and setting) the current
triggering mode.
Arguments: None.
Return Value: None.
Input: None.
Output: None.
Error Handling: None.
Algorithms: None.
Data Structures: None.
Global Variables: trigger_mode - toggled.
Author: Glen George, Yiyang Gong
Last Modified: 6/13/02 - Changed to allow double
buffering to show a workable menu
in one shot mode
*/
void mode_toggle()
70
{
/* variables */
/* none */
/* toggle the trigger mode */
if (trigger_mode == NORMAL_TRIGGER)
trigger_mode = ONESHOT_TRIGGER;
else
trigger_mode = NORMAL_TRIGGER;
modifybuffer();
/* set the new mode */
set_mode(trigger_mode); /* change to the modified buffer
to show a working menu during
one-shot mode. When the mode returns
to normal, the correct buffer is
then switched back */
/* all done with the trigger mode - return */
return;
}
/*
display_mode
Description: This function displays the current triggering mode at the
passed position, in the passed style.
Arguments: x_pos (int) - x position (in character cells) at which to
display the trigger mode.
y_pos (int) - y position (in character cells) at which to
display the trigger mode.
style (int) - style with which to display the trigger
mode.
Return Value: None.
Input: None.
Output: The trigger mode is displayed at the passed position on
the screen.
Error Handling: None.
Algorithms: None.
Data Structures: None.
Global Variables: trigger_mode - determines which string is displayed.
Author: Glen George
Last Modified: Mar. 13, 1994
*/
void display_mode(int x_pos, int y_pos, int style)
{
/* variables */
/* the mode strings (must match enumerated type) */
const static char * const modes[] = { " Normal ", " One-Shot" };
/* display the trigger mode */
plot_string(x_pos, y_pos, modes[trigger_mode], style);
71
/* all done displaying the trigger mode - return */
return;
}
/*
set_scale
Description: This function sets the scale type to the passed value.
Arguments: s (enum scale_type) - scale type to which to initialize
the scale status.
Return Value: None.
Input: None.
Output: The new trace display is updated with the new scale.
Error Handling: None.
Algorithms: None.
Data Structures: None.
Global Variables: scale - initialized to the passed value.
Author: Glen George
Last Modified: Mar. 13, 1994
*/
void set_scale(enum scale_type s)
{
/* variables */
/* none */
/* set the scale type */
scale = s;
/* output the scale appropriately */
set_display_scale(scale);
/* all done setting the scale type - return */
return;
}
/*
scale_toggle
Description: This function handles toggling (and setting) the current
scale type.
Arguments: None.
Return Value: None.
Input: None.
Output: The new scale is output to the trace display.
Error Handling: None.
Algorithms: None.
72
Data Structures: None.
Global Variables: scale - toggled.
Author: Glen George
Last Modified: Mar. 13, 1994
*/
void scale_toggle()
{
/* variables */
/* none */
/* toggle the scale status */
if (scale == SCALE_NONE)
scale = SCALE_AXES;
else
scale = SCALE_NONE;
/* set the scale type */
set_display_scale(scale);
/* all done with toggling the scale type - return */
return;
}
/*
display_scale
Description: This function displays the current scale type at the
passed position, in the passed style.
Arguments: x_pos (int) - x position (in character cells) at which to
display the scale type.
y_pos (int) - y position (in character cells) at which to
display the scale type.
style (int) - style with which to display the scale type.
Return Value: None.
Input: None.
Output: The scale type is displayed at the passed position on the
display.
Error Handling: None.
Algorithms: None.
Data Structures: None.
Global Variables: scale - determines which string is displayed.
Author: Glen George
Last Modified: Mar. 13, 1994
*/
void display_scale(int x_pos, int y_pos, int style)
{
/* variables */
/* the scale type strings (must match enumerated type) */
const static char * const scale_stat[] = { " None", " Axes" };
73
/* display the scale status */
plot_string(x_pos, y_pos, scale_stat[scale], style);
/* all done displaying the scale status - return */
return;
}
/*
set_sweep
Description: This function sets the sweep rate to the passed value.
The passed value gives the sweep rate to choose from the
list of sweep rates (it gives the list index).
Arguments: s (int) - index into the list of sweep rates to which to
set the current sweep rate.
Return Value: None.
Input: None.
Output: None.
Error Handling: The passed index is not checked for validity.
Algorithms: None.
Data Structures: None.
Global Variables: sweep - initialized to the passed value.
Author: Glen George
Last Modified: Mar. 8, 1994
*/
void set_sweep(int s)
{
/* variables */
int sample_size; /* sample size for this sweep rate */
/* set the new sweep rate */
sweep = s;
/* set the sweep rate for the hardware */
sample_size = set_sample_rate(sweep_rates[sweep].sample_rate);
/* also set the sample size for the trace capture */
set_trace_size(sample_size);
/* all done initializing the sweep rate - return */
return;
}
/*
sweep_down
Description: This function handles decreasing the current sweep rate.
The new sweep rate (and sample size) is sent to the
hardware (and trace routines). If an attempt is made to
lower the sweep rate below the minimum value it is not
changed. This routine also updates the sweep delay based
74
on the new sweep rate (to keep the delay time constant).
Arguments: None.
Return Value: None.
Input: None.
Output: None.
Error Handling: None.
Algorithms: None.
Data Structures: None.
Global Variables: sweep - decremented if not already 0.
delay - increased to keep delay time constant.
Known Bugs: The updated delay time is not displayed. Since the time
is typically only rounded to the new sample rate, this is
not a major problem.
Author: Glen George
Last Modified: Mar. 8, 1994
*/
void sweep_down()
{
/* variables */
int sample_size; /* sample size for the new sweep rate */
/* decrease the sweep rate, if not already the minimum */
if (sweep > 0) {
/* not at minimum, adjust delay for new sweep */
adjust_trg_delay(sweep, (sweep - 1));
/* now set new sweep rate */
sweep--;
}
/* set the sweep rate for the hardware */
sample_size = set_sample_rate(sweep_rates[sweep].sample_rate);
/* also set the sample size for the trace capture */
set_trace_size(sample_size);
/* all done with lowering the sweep rate - return */
return;
}
/*
sweep_up
Description: This function handles increasing the current sweep rate.
The new sweep rate (and sample size) is sent to the
hardware (and trace routines). If an attempt is made to
raise the sweep rate above the maximum value it is not
changed. This routine also updates the sweep delay based
on the new sweep rate (to keep the delay time constant).
Arguments: None.
Return Value: None.
Input: None.
Output: None.
Error Handling: None.
75
Algorithms: None.
Data Structures: None.
Global Variables: sweep - incremented if not already the maximum value.
delay - decreased to keep delay time constant.
Known Bugs: The updated delay time is not displayed. Since the time
is typically only rounded to the new sample rate, this is
not a major problem.
Author: Glen George
Last Modified: Mar. 8, 1994
*/
void sweep_up()
{
/* variables */
int sample_size; /* sample size for the new sweep rate */
/* increase the sweep rate, if not already the maximum */
if (sweep MIN_TRG_LEVEL_SET)
level--;
/* set the trigger level for the hardware */
set_trigger(level, slope);
/* all done with lowering the trigger level - return */
return;
}
/*
trg_level_up
Description: This function handles increasing the current trigger
level. The new trigger level is sent to the hardware.
If an attempt is made to raise the trigger level above
the maximum value it is not changed.
Arguments: None.
Return Value: None.
Input: None.
Output: None.
Error Handling: None.
Algorithms: None.
Data Structures: None.
Global Variables: level - incremented if not already the maximum value.
Author: Glen George
Last Modified: Mar. 8, 1994
*/
78
void trg_level_up()
{
/* variables */
/* none */
/* increase the trigger level, if not already the maximum */
if (level MIN_DELAY)
delay--;
/* set the trigger delay for the hardware */
set_delay(delay);
/* all done with lowering the trigger delay - return */
return;
}
/*
trg_delay_up
Description: This function handles increasing the current trigger
delay. The new trigger delay is sent to the hardware.
If an attempt is made to raise the trigger delay above
the maximum value it is not changed.
Arguments: None.
Return Value: None.
Input: None.
Output: None.
Error Handling: None.
Algorithms: None.
Data Structures: None.
Global Variables: delay - incremented if not already the maximum value.
Author: Glen George
Last Modified: Mar. 8, 1994
*/
void trg_delay_up()
{
/* variables */
/* none */
83
/* increase the trigger delay, if not already the maximum */
if (delay MAX_DELAY)
/* delay is too large - set to maximum */
84
delay = MAX_DELAY;
if (delay -1000000)) {
/* delay is in milliseconds */
delay_str[7] = 'm';
delay_str[8] = 's';
}
else if ((d -1000000000)) {
/* delay is in seconds */
delay_str[7] = 's';
85
}
else {
/* delay is in kiloseconds */
delay_str[7] = 'k';
delay_str[8] = 's';
}
/* now actually display the trigger delay */
plot_string(x_pos, y_pos, delay_str, style);
/* all done displaying the trigger delay - return */
return;
}
/*
cvt_num_field
Description: This function converts the passed number (numeric field
value) to a string and returns that in the passed string
reference. The number may be signed, and a sign (+ or -)
is always generated. The number is assumed to have three
digits to the right of the decimal point. Only the four
most significant digits of the number are displayed and
the decimal point is shifted appropriately. (Four digits
are always generated by the function).
Arguments: n (long int) - numeric field value to convert.
s (char *) - pointer to string in which to return the
converted field value.
Return Value: None.
Input: None.
Output: None.
Error Handling: None.
Algorithms: The algorithm used assumes four (4) digits are being
converted.
Data Structures: None.
Global Variables: None.
Known Bugs: If the passed long int is the largest negative long int,
the function will display garbage.
Author: Glen George
Last Modified: Mar. 8, 1994
*/
static void cvt_num_field(long int n, char *s)
{
/* variables */
int dp = 3; /* digits to right of decimal point */
int d; /* digit weight (power of 10) */
int i = 0; /* string index */
/* first get the sign (and make n positive for conversion) */
if (n 9999) {
/* have more than 4 digits - get rid of one */
n /= 10;
/* adjust the decimal point */
dp--;
}
/* if decimal point is non-positive, make positive */
/* (assume will take care of adjustment with output units in this case) */
while (dp 0; d /= 10) {
/* check if need decimal the decimal point now */
if (dp-- == 0)
/* time for decimal point */
s[i++] = '.';
/* get and convert this digit */
s[i++] = (n / d) + '0';
/* remove this digit from n */
n %= d;
}
/* all done converting the number, return */
return;
}
87
/****************************************************************************/
/* */
/* TRACUTIL (tracutil.c) */
/* Trace Utility Functions */
/* Digital Oscilloscope Project */
/* EE/CS 52 */
/* */
/****************************************************************************/
/*
This file contains the utility functions for handling traces (capturing
and displaying data) for the Digital Oscilloscope project. The functions
included are:
clear_saved_areas - clear all the save areas
do_trace - start a trace
init_trace - initialize the trace routines
plot_trace - plot a trace (sampled data)
restore_menu_trace - restore the saved area under the menus
restore_trace - restore the saved area of a trace
set_display_scale - set the type of displayed scale (and display it)
set_mode - set the triggering mode
set_save_area - determine an area of a trace to save
set_trace_size - set the number of samples in a trace
trace_done - inform this module that a trace has been completed
trace_rdy - determine if system is ready to start another trace
trace_rearm - re-enable tracing (in one-shot triggering mode)
The local functions included are:
none
The locally global variable definitions included are:
cur_scale - current scale type
normal_trg - the current triggering mode (TRUE: normal triggering)
sample_size - the size of the sample for the trace
sampling - currently doing a sample
saved_area - saved trace under a specified area
saved_axis_x - saved trace under the x-axis
saved_axis_y - saved trace under the y-axis
saved_menu - saved trace under the menu
saved_pos_x - starting position (x coorindate) of area to save
saved_pos_y - starting position (y coorindate) of area to save
saved_end_x - ending position (x coorindate) of area to save
saved_end_y - ending position (y coorindate) of area to save
trace_status - whether or not ready to start another trace
Revision History
3/8/94 Glen George Initial revision.
3/13/94 Glen George Updated comments.
3/13/94 Glen George Fixed inversion of signal in plot_trace.
3/13/94 Glen George Added sampling flag and changed the functions
init_trace, do_trace and trace_done to update
the flag. Also the function trace_rdy now
uses it. The function set_mode was updated
to always say a trace is ready for normal
triggering.
3/13/94 Glen George Fixed bug in trace restoring due to operator
misuse (&& instead of &) in the functions
set_axes, restore_menu_trace, and
restore_trace.
3/13/94 Glen George Fixed bug in trace restoring due to the clear
function (clear_saved_areas) not clearing all
of the menu area.
3/13/94 Glen George Fixed comparison bug when saving traces in
plot_trace.
3/13/94 Glen George Changed name of set_axes to set_display_scale
and the name of axes_state to cur_scale to
more accurately reflect the function/variable
use (especially if add scale display types).
3/17/97 Glen George Updated comments.
3/17/97 Glen George Changed set_display_scale to use plot_hline
88
and plot_vline functions to output axes.
6/11/02 Yiyang Gong placed a swapbuffer function at the end of plot trace
so that every time a trace is completed, the buffer
to be displayed is switched, allowing double
buffering.
*/
/* library include files */
/* none */
/* local include files */
#include "scopedef.h"
#include "lcdout.h"
#include "menu.h"
#include "menuact.h"
#include "tracutil.h"
/* locally global variables */
static int normal_trg; /* TRUE for normal triggering */
static int trace_status; /* ready to start another trace */
static int sampling; /* currently sampling data */
static int sample_size; /* number of data points in a sample */
static enum scale_type cur_scale; /* current display scale type */
/* traces (sampled data) saved under the axes */
static unsigned char saved_axis_x[SIZE_X/8]; /* saved trace under x-axis */
static unsigned char saved_axis_y[SIZE_Y/8]; /* saved trace under y-axis */
/* traces (sampled data) saved under the menu */
static unsigned char saved_menu[MENU_SIZE_Y][(MENU_SIZE_X + 7)/8];
/* traces (sampled data) saved under any area */
static unsigned char saved_area[SAVE_SIZE_Y][SAVE_SIZE_X/8]; /* saved trace under any
area */
static int saved_pos_x; /* starting x position of saved area */
static int saved_pos_y; /* starting y position of saved area */
static int saved_end_x; /* ending x position of saved area */
static int saved_end_y; /* ending y position of saved area */
/*
init_trace
Description: This function initializes all of the locally global
variables used by these routines. The saved areas are
set to non-existant with cleared saved data. Normal
normal triggering is set, the system is ready for a
trace, the scale is turned off and the sample size is set
to the screen size.
Arguments: None.
Return Value: None.
Input: None.
Output: None.
Error Handling: None.
Algorithms: None.
Data Structures: None.
89
Global Variables: normal_trg - set to TRUE.
trace_status - set to TRUE.
sampling - set to FALSE.
cur_scale - set to SCALE_NONE (no displayed scale).
sample_size - set to screen size (SIZE_X).
saved_axis_x - cleared.
saved_axis_y - cleared.
saved_menu - cleared.
saved_area - cleared.
saved_pos_x - set to off-screen.
saved_pos_y - set to off-screen.
saved_end_x - set to off-screen.
saved_end_y - set to off-screen.
Author: Glen George
Last Modified: Mar. 13, 1994
*/
void init_trace()
{
/* variables */
/* none */
/* initialize system status variables */
/* turn on normal triggering */
normal_trg = TRUE;
/* ready for a trace */
trace_status = TRUE;
/* not currently sampling data */
sampling = FALSE;
/* turn off the displayed scale */
cur_scale = SCALE_NONE;
/* sample size is the screen size */
sample_size = SIZE_X;
/* clear save areas */
clear_saved_areas();
/* also clear the general saved area location variables (off-screen) */
saved_pos_x = SIZE_X + 1;
saved_pos_y = SIZE_Y + 1;
saved_end_x = SIZE_X + 1;
saved_end_y = SIZE_Y + 1;
/* done initializing, return */
return;
}
/*
set_mode
Description: This function sets the locally global triggering mode
based on the passed value (TRUE for normal triggering,
FALSE otherwise). The triggering mode is used to
determine when the system is ready for another trace.
90
Arguments: trigger_mode (enum trigger_type) - the mode with which to
set the triggering.
Return Value: None.
Input: None.
Output: None.
Error Handling: None.
Algorithms: None.
Data Structures: None.
Global Variables: normal_trg - set based on passed argument.
trace_status - set to TRUE if normal triggering.
Author: Glen George
Last Modified: Mar. 13, 1994
*/
void set_mode(enum trigger_type trigger_mode)
{
/* variables */
/* none */
/* set the locally global normal trigger flag based on the passed mode */
normal_trg = (trigger_mode == NORMAL_TRIGGER);
/* if normal triggering - ready for trace too */
trace_status = normal_trg;
/* all done, return */
return;
}
/*
trace_rdy
Description: This function determines whether the system is ready to
start another trace. This is determined by whether or
not the system is still sampling (sampling flag) and if
it is ready for another trace (trace_status flag).
Arguments: None.
Return Value: (int) - the current trace status (TRUE if ready to do
another trace, FALSE otherwise).
Input: None.
Output: None.
Error Handling: None.
Algorithms: None.
Data Structures: None.
Global Variables: sampling - determines if ready for another trace.
trace_status - determines if ready for another trace.
Author: Glen George
Last Modified: Mar. 13, 1994
*/
int trace_rdy()
91
{
/* variables */
/* none */
/* ready for another trace if not sampling and trace is ready */
return (!sampling && trace_status);
}
/*
trace_done
Description: This function is called to indicate a trace has been
completed. If in normal triggering mode this means the
system is ready for another trace.
Arguments: None.
Return Value: None.
Input: None.
Output: None.
Error Handling: None.
Algorithms: None.
Data Structures: None.
Global Variables: trace_status - may be set to TRUE.
sampling - set to FALSE.
normal_trg - determines if trace_status is changed.
Author: Glen George
Last Modified: Mar. 13, 1994
*/
void trace_done()
{
/* variables */
/* none */
/* done with a trace - if normal triggering, ready for another one */
if (normal_trg)
/* normal triggering mode - set trace_status to TRUE (ready) */
trace_status = TRUE;
/* done sampling now */
sampling = FALSE;
/* done so return */
return;
}
/*
trace_rearm
Description: This function is called to rearm the trace. It sets the
trace status to ready (TRUE). It is used to rearm the
trigger in one-shot mode.
92
Arguments: None.
Return Value: None.
Input: None.
Output: None.
Error Handling: None.
Algorithms: None.
Data Structures: None.
Global Variables: trace_status - set to TRUE.
Author: Glen George
Last Modified: Mar. 8, 1994
*/
void trace_rearm()
{
/* variables */
/* none */
/* rearm the trace - set status to ready (TRUE) */
trace_status = TRUE;
/* all done - return */
return;
}
/*
set_trace_size
Description: This function sets the locally global sample size to the
passed value. This is used to scale the data when
plotting a trace.
Arguments: size (int) - the trace sample size.
Return Value: None.
Input: None.
Output: None.
Error Handling: None.
Algorithms: None.
Data Structures: None.
Global Variables: sample_size - set to the passed value.
Author: Glen George
Last Modified: Mar. 8, 1994
*/
void set_trace_size(int size)
{
/* variables */
/* none */
/* set the locally global sample size */
93
sample_size = size;
/* all done, return */
return;
}
/*
set_display_scale
Description: This function sets the displayed scale type to the passed
argument. If the scale is turned on, it draws it. If it
is turned off (SCALE_NONE), it restores the saved trace
under the scale.
Arguments: scale (scale_type) - new scale type.
Return Value: None.
Input: None.
Output: Either a scale is output or the trace under the old scale
is restored.
Error Handling: None.
Algorithms: None.
Data Structures: None.
Global Variables: cur_scale - set to the passed value.
saved_axis_x - used to restore trace data under x-axis.
saved_axis_y - used to restore trace data under y-axis.
Author: Glen George
Last Modified: Mar. 17, 1997
*/
void set_display_scale(enum scale_type scale)
{
/* variables */
int i; /* loop index */
/* handle the scale type appropriately */
switch (scale) {
case SCALE_AXES: /* axes for the scale */
/* first draw them */
/* draw the x-axis */
plot_hline(X_AXIS_START, X_AXIS_POS, (X_AXIS_END -
X_AXIS_START));
/* draw the y-axis */
plot_vline(Y_AXIS_POS, Y_AXIS_START, (Y_AXIS_END -
Y_AXIS_START));
/* done with the axes */
break;
case SCALE_NONE: /* there is no scale */
/* restore trace information under old scale */
/* restore the trace under the x-axis */
for (i = X_AXIS_START; i > (i % 8))) == 0)
/* saved pixel is off */
plot_pixel(i, X_AXIS_POS, PIXEL_WHITE);
else
/* saved pixel is on */
plot_pixel(i, X_AXIS_POS, PIXEL_BLACK);
}
/* restore the trace under the y-axis */
for (i = Y_AXIS_START; i > (i % 8))) == 0)
/* saved pixel is off */
plot_pixel(Y_AXIS_POS, i, PIXEL_WHITE);
else
/* saved pixel is on */
plot_pixel(Y_AXIS_POS, i, PIXEL_BLACK);
}
}
/* now remember the scale type */
cur_scale = scale;
/* scale is taken care of, return */
return;
}
/*
clear_saved_areas
Description: This function clears all the saved areas (for saving the
trace under the axes, menus, and general areas).
Arguments: None.
Return Value: None.
Input: None.
Output: None.
Error Handling: None.
Algorithms: None.
Data Structures: None.
Global Variables: saved_axis_x - cleared.
saved_axis_y - cleared.
saved_menu - cleared.
saved_area - cleared.
Author: Glen George
Last Modified: Mar. 13, 1994
*/
void clear_saved_areas()
{
/* variables */
int i; /* loop indices */
int j;
/* clear x-axis and y-axis save areas */
for (i = 0; i >= 1;
/* check if moving to next byte */
if (bit_position == 0) {
/* now on high bit of next byte */
bit_position = 0x80;
bit_offset++;
}
}
}
/* restored menu area - return */
return;
}
/*
set_save_area
Description: This function sets the position and size of the area to
be saved when traces are drawn. It also clears any data
currently saved.
Arguments: pos_x (int) - x position of upper left corner of the
saved area.
pos_y (int) - y position of upper left corner of the
saved area.
size_x (int) - horizontal size of the saved area.
size_y (int) - vertical size of the saved area.
Return Value: None.
Input: None.
Output: None.
Error Handling: None.
Algorithms: None.
Data Structures: None.
Global Variables: saved_area - cleared.
saved_pos_x - set to passed value.
saved_pos_y - set to passed value.
saved_end_x - computed from passed values.
saved_end_y - computed from passed values.
Author: Glen George
Last Modified: Mar. 8, 1994
*/
void set_save_area(int pos_x, int pos_y, int size_x, int size_y)
{
/* variables */
int x; /* loop indices */
int y;
/* just setup all the locally global variables from the passed values */
saved_pos_x = pos_x;
saved_pos_y = pos_y;
saved_end_x = pos_x + size_x;
saved_end_y = pos_y + size_y;
97
/* clear the save area */
for (y = 0; y >= 1;
/* check if moving to next byte */
if (bit_position == 0) {
/* now on high bit of next byte */
bit_position = 0x80;
bit_offset++;
}
}
}
/* restored the saved area - return */
return;
}
/*
do_trace
Description: This function starts a trace. It starts the hardware
sampling data (via a function call) and sets the trace
ready flag (trace_status) to FALSE and the sampling flag
(sampling) to TRUE.
Arguments: None.
Return Value: None.
Input: None.
Output: None.
Error Handling: None.
Algorithms: None.
Data Structures: None.
Global Variables: trace_status - set to FALSE (not ready for another trace).
sampling - set to TRUE (doing a sample now).
Author: Glen George
Last Modified: Mar. 13, 1994
*/
void do_trace()
{
/* variables */
/* none */
/* start up the trace */
start_sample();
/* now not ready for another trace (currently doing one) */
trace_status = FALSE;
/* and are currently sampling data */
sampling = TRUE;
/* trace is going, return */
return;
99
}
/*
plot_trace
Description: This function plots the passed trace. The trace is
assumed to contain sample_size points of sampled data.
Any points falling within any of the save areas are also
saved by this routine. The data is also scaled to be
within the range of the entire screen (divided by
Y_SCALE_FACTOR).
Arguments: sample (unsigned char far *) - sample to plot.
Return Value: None.
Input: None.
Output: The sample is plotted on the screen.
Error Handling: None.
Algorithms: If there are more sample points than screen width the
sample is plotted with multiple points per horizontal
position.
Data Structures: None.
Global Variables: cur_scale - determines type of scale to plot.
sample_size - determines size of passed sample.
saved_axis_x - stores trace under x-axis.
saved_axis_y - stores trace under y-axis.
saved_menu - stores trace under the menu.
saved_area - stores trace under the saved area.
saved_pos_x - determines location of saved area.
saved_pos_y - determines location of saved area.
saved_end_x - determines location of saved area.
saved_end_y - determines location of saved area.
Author: Glen George, Yiyang Gong
Last Modified: 6/11/02 - added a swapbuffer function at the end of function
When a new trace is completely drawn, the buffer
switches to the other buffer, and is displayed.
The writes then happens to the other buffer (or
block of memory).
*/
void plot_trace(unsigned char far *sample)
{
/* variables */
int x = 0; /* current x position to plot */
int x_pos = (PLOT_SIZE_X / 2); /* "fine" x position for multiple point plotting */
int y; /* y position of point to plot */
int i; /* loop index */
/* first, clear the display to get rid of old plots */
clear_display();
/* clear the saved areas too */
clear_saved_areas();
/* re-display the menu (if it was on) */
refresh_menu();
/* plot the sample */
100
for (i = 0; i = X_AXIS_START) && (x > (x % 8));
if ((x == Y_AXIS_POS) && (y >= Y_AXIS_START) && (y > (y % 8));
if ((x >= MENU_UL_X) && (x = MENU_UL_Y) && (y > ((x - MENU_UL_X) %
8));
if ((x >= saved_pos_x) && (x = saved_pos_y) && (y > ((x -
saved_pos_x) % 8));
/* update x position */
x_pos += PLOT_SIZE_X;
/* check if at next horizontal position */
if (x_pos >= sample_size) {
/* at next position - update positions */
x++;
x_pos -= sample_size;
}
}
/* finally, output the scale if need be */
set_display_scale(cur_scale);
swapbuffer(); /* when the plot trace is done
swap the buffer to be displayed
and swap the display to be written
to in memory*/
/* done with plot, return */
return;
}
101
/****************************************************************************/
/* */
/* INTERFAC.H */
/* Interface Definitions */
/* Include File */
/* Digital Oscilloscope Project */
/* EE/CS 52 */
/* */
/****************************************************************************/
/*
This file contains the constants for interfacing between the C code and
the assembly code/hardware for the Digital Oscilloscope project. This is
a sample interface file to allow compilation of the .c files.
Revision History:
3/8/94 Glen George Initial revision.
3/13/94 Glen George Updated comments.
3/17/97 Glen George Added constant MAX_SAMPLE_SIZE and removed
KEY_UNUSED.
6/10/02 Yiyang Gong changed the keypad values to match the ones
written in the keypad file. Also changed the
minimum sample to one (as the timer requires a
count to 1, whereas the 0 count counts as
FFFFH + 1. Changed the maximum and minimum
sampled voltages, to fit with the MAX153 bipolar
mode. Finally, changed to pixel_white value
to the required value for the plot_pixel function
*/
#ifndef __INTERFAC_H__
#define __INTERFAC_H__
/* library include files */
/* none */
/* local include files */
/* none */
/* constants */
/* keypad constants */
#define KEY_MENU 4 /* */
#define KEY_UP 0 /* */
#define KEY_DOWN 1 /* */
#define KEY_LEFT 2 /* */
#define KEY_RIGHT 3 /* */
#define KEY_ILLEGAL 5 /* illegal key */
/* display constants */
#define SIZE_X 480 /* size in the x dimension */
#define SIZE_Y 128 /* size in the y dimension */
#define PIXEL_WHITE -2 /* pixel off - a value of FFFEH is required
by the plot_pixel function*/
#define PIXEL_BLACK 1 /* pixel on */
/* scope parameters */
#define MIN_DELAY 1 /* minimum trigger delay */
#define MAX_DELAY 65535 /* maximum trigger delay */
#define MIN_LEVEL -2500 /* minimum trigger level (in mV) */
#define MAX_LEVEL 2500 /* maximum trigger level (in mV) */
/* sampling parameters */
#define MAX_SAMPLE_SIZE 2400 /* maximum size of a sample (in samples) */
#endif
102
/****************************************************************************/
/* */
/* SCOPEDEF.H */
/* General Definitions */
/* Include File */
/* Digital Oscilloscope Project */
/* EE/CS 52 */
/* */
/****************************************************************************/
/*
This file contains the general definitions for the Digital Oscilloscope
project. This includes constant and structure definitions along with the
function declarations for the assembly language functions.
Revision History:
3/8/94 Glen George Initial revision.
3/13/94 Glen George Updated comments.
3/17/97 Glen George Removed KEYCODE_UNUSED (no longer used).
6/10/02 Yiyang Gong Added the functions swapbuffer() and
modifybuffer() to be called within the
the plot_trace function as well as
the mode_toggle function. Allows for correct
double buffering
*/
#ifndef __SCOPEDEF_H__
#define __SCOPEDEF_H__
/* library include files */
/* none */
/* local include files */
#include "interfac.h"
#include "lcdout.h"
/* constants */
/* general constants */
#define FALSE 0
#define TRUE !FALSE
#define NULL (void *) 0
/* display size (in characters) */
#define LCD_WIDTH (SIZE_X / HORIZ_SIZE)
#define LCD_HEIGHT (SIZE_Y / VERT_SIZE)
/* structures, unions, and typedefs */
/* program states */
enum status { MENU_ON, /* menu is displayed with the cursor in it */
MENU_OFF, /* menu is not displayed - no cursor */
NUM_STATES /* number of states */
};
/* key codes */
enum keycode { KEYCODE_MENU, /* */
KEYCODE_UP, /* */
KEYCODE_DOWN, /* */
KEYCODE_LEFT, /* */
KEYCODE_RIGHT, /* */
103
KEYCODE_ILLEGAL, /* other keys */
NUM_KEYCODES /* number of key codes */
};
/* function declarations */
/* keypad functions */
unsigned char key_available(void); /* key is available */
int getkey(void); /* get a key */
/* display functions */
void clear_display(void); /* clear the display */
void plot_pixel(unsigned int, unsigned int, int); /* output a pixel */
void swapbuffer(void);
void modifybuffer(void);
/* sampling parameter functions */
int set_sample_rate(long int); /* set the sample rate */
void set_trigger(int, int); /* set trigger level and slope */
void set_delay(long int); /* set the trigger delay time */
/* sampling functions */
void start_sample(void); /* capture a sample */
unsigned char far *sample_done(void); /* sample captured status */
#endif
104