;------------------------------------------------------------------- ;ENSC 151 Sample File ;------------------------------------------------------------------- ;AUTHOR(S): Bill De Vries ;VERSION: 1.0 Module Created 99-01-20 (Bill De Vries) ;VERSION: 1.1 Comments added 00-01-22 (Veljko Jovanovic) ;VERSION: 2.0 IRQ Capabilities added 00-01-28 (Rob Trost) ;VERSION: 3.0 Random Number generator added 00-01-28 (Rob Trost) ;------------------------------------------------------------------- ; DESCRIPTION: ; ~~~~~~~~~~~~ ; This program is the sample code to show how to use interrupts ; and generate random numbers using the TCNT free running counter. ;------------------------------------------------------------------- ;------------------------------------------------------------------- ; LOCAL DEFINITIONS ;------------------------------------------------------------------- PORTA: equ $00 ;Port A Data Register PORTB: equ $01 ;Port B Data Register DDRA: equ $02 ;Port A Data Direction Register DDRB: equ $03 ;Port B Data Direction Register PORTC: equ $04 ;Port C Data Register DDRC: equ $06 ;Port C Data Direction Register PORTE: equ $08 ;Port E Data Register DDRE: equ $09 ;Port E Data Direction Register PEAR: equ $0A ;Port E Assigment Register MODE: equ $0B ;Mode Register PUCR: equ $0C ;Pull Up Control Register RDRIV: equ $0D ;Reduced Drive of I/O Lines Register INITRM: equ $10 ;Initialization of Internal RAM Position Register INITRG: equ $11 ;Initialization of Internal Register Position Register INTCR: equ $001E ; Interrupt Control Register TSCR: equ $0086 ; Timer System Control Register INITEE: equ $12 ;Inittaps TCNTH: equ $83 ;Higher 8 bits of free running timer counter TCNTL: equ $84 ;Lower 8 bits of free running timer counter IRQVEC: equ $0B32 ;Address of IRQ jump vector TOFVEC: equ $0B1E ; TOF Jump vector location ;------------------------------------------------------------------- ; LOCAL DEFINITIONS ;------------------------------------------------------------------- EDGE: equ %11100000 ; Set IRQ to be edge sensitive TEN: equ %10000000 ; Timer Enable STROBE: equ $04 ;Bit 2 for LCD Enable (Strobing in Data) CMDREG: equ $00 ;Bit 0 is RS, Bit 1 is R/W (write instructions to the LCD) DATAREG: equ $01 ;Bit 0 is RS, Bit 1 is R/W (write data to the LCD CG or DD RAM) ;------------------------------------------------------------------- ;------------------------------------------------------------------- ; INITIALIZATION CODE ;------------------------------------------------------------------- ; DESCRIPTION: ; ~~~~~~~~~~~~ ; This section of the code initializes the LCD display and sets up ; all of the sub functions required for proper operation. This ; includes the WRITE_LCD subroutine and specific delay ; counters. ;------------------------------------------------------------------- ***************** Main Program ***************** ORG $0800 ; beginning of RAM ldaa #%00000111 ; Set lower 3 bits of Port A staa DDRA ; to output mode ldaa #%11111111 ; Set all bits of Port B staa DDRB ; to output mode jsr LCD_INIT ; Initialize the LCD ;------------------------------------------------------------------- ; INITIALISE INTERRUPTS ;------------------------------------------------------------------- ; DESCRIPTION: ; ~~~~~~~~~~~~ ; This section of the code initializes the interrupts. IRQ_PROC ; is the procedure to handle all IRQ interrupts, and TOF_PROC is ; used to handle the TOF interrupts. The IRQ is also set to be edge ; sensitive. The timer and TOF are enabled, and set with a prescaler ; value of 1. Finally the TOF flag is reset and the interrupts are enabled. ;------------------------------------------------------------------- INIT movw #IRQ_PROC,IRQVEC ; install IRQ procedure address in jump vector table. movb #EDGE,INTCR ; Set IRQ edge sensitive movb #TEN,TSCR ; Enable timer circuitry ldaa #CMDREG ldab #$80 ; Set cursor to line 1 jsr WRITE_LCD ldx #PROMPT ; Prompt user to push button jsr WRITE_MSG cli ; enable the interrupt. IDLE bra IDLE ; Do nothing ********************* End Main Program ********************* ;------------------------------------------------------------------- ; IRQ INTERUPT PROCEDURE ;------------------------------------------------------------------- ; DESCRIPTION: ; ~~~~~~~~~~~~ ; When a button is pressed, the IRQ_PROC will take the value of ; TCNTL, the lower 8-bits of the timer's free running counter, ; and display that value to the screen as "Random # is: ". ;------------------------------------------------------------------- IRQ_PROC ldaa #CMDREG ldab #$80 ; Set cursor to line 1 jsr WRITE_LCD ldx #OUTPUT ; Write output text jsr WRITE_MSG ldab TCNTL ; Take random value from counter jsr WRITE_NUMBER ; Display value rti ;------------------------------------------------------------------- ; PROCEDURE: WRITE_NUMBER ;------------------------------------------------------------------- ; DESCRIPTION: ; ~~~~~~~~~~~~ ; Accepts a 1-byte hex value in Accumulator B and displays it to the ; the LCD as a 3-digit decimal value. ;------------------------------------------------------------------- WRITE_NUMBER clra ; Clear MSBs of accumulator D ldx #100 idiv ; Divide value by 100 pshb ; Store remainder tfr X,D addb #'0' ; Display 100's digit ldaa #DATAREG jsr WRITE_LCD clra pulb ; Get remainder ldx #10 ; Divide remainder by 10 idiv pshb ; Store new remainder tfr X,D addb #'0' ; Display 10's digit ldaa #DATAREG jsr WRITE_LCD pulb ; Get remainder/1's digit addb #'0' ldaa #DATAREG ; Display 1's digit jsr WRITE_LCD rts ;------------------------------------------------------------------- ; PROCEDURE: WRITE_LCD ;------------------------------------------------------------------- ; DESCRIPTION: ; ~~~~~~~~~~~~ ; Strobes the correct control lines to write an instruction or data ; into the LCD. The insturcion or data must be stored in ACCB before ; executing. The appropriate values of the RS, R/W and Enable bits ; must be stored in ACCA (RS = 0/1 if writing instruction/data, ; R/W = 0 since we are writing, E = 0 to start). ;------------------------------------------------------------------- WRITE_LCD ; Assume data/instruction in ACCB stab PORTB ; Write data to Port B staa PORTA ; Write RS, R/W, E to Port A jsr PAUSE eora #STROBE ; Set the Enable bit staa PORTA ; Strobe the instruction/data jsr PAUSE ; into the LCD. eora #STROBE ; Clear the Enable bit staa PORTA jsr PAUSE rts ;------------------------------------------------------------------- ; PROCEDURE: WRITE_MESSAGE ;------------------------------------------------------------------- ; DESCRIPTION: ; ~~~~~~~~~~~~ ; Writes a message (a string of characters) to the LCD. ;------------------------------------------------------------------- WRITE_MSG ldaa #DATAREG ; Set RS bit (write data) NEXT_CHAR ldab 0,X ; Load string into ACCB cmpb #$00 ; Check for the end of the string beq END_MSG jsr WRITE_LCD inx ; Increment string pointer bra NEXT_CHAR END_MSG rts ;------------------------------------------------------------------- ; PROCEDURE: LCD_INIT ;------------------------------------------------------------------- ; DESCRIPTION: ; ~~~~~~~~~~~~ ; Initializes the LCD display for required operation (2x16 mode) ;------------------------------------------------------------------- LCD_INIT ldaa #CMDREG ; Clear RS bit (write instruction) ldab #$30 ; Set Data Interface Length to 8bits jsr WRITE_LCD ldab #15 jsr LONGPAUSE ldab #$38 ; Set Number of Display Lines to 2 jsr WRITE_LCD ldab #$08 ; Turn Off Display, Cursor & Blink jsr WRITE_LCD ldab #$01 ; Clear Display jsr WRITE_LCD ldab #4 jsr LONGPAUSE ldab #$06 ; Set Cursor Move Direction - jsr WRITE_LCD ; Increment After Each Byte Written ldab #$0C ; Turn On Display jsr WRITE_LCD rts ;------------------------------------------------------------------- ; PROCEDURE: Delays ;------------------------------------------------------------------- ; DESCRIPTION: ; ~~~~~~~~~~~~ ; Delay functions for proper timing interface with the LCD. ;------------------------------------------------------------------- LONGPAUSE ; Executes the PAUSE subroutine as stab COUNTER ; many times as the value in ACCB LOOK tst COUNTER ; indicates. beq FINISH ; Delay = ~COUNT value * 0.2msec dec COUNTER jsr PAUSE bra LOOK FINISH rts PAUSE ldy #$00FF ; Delay for ~0.2msec AGAIN dey ; Counts down the contents of the cpy #$0000 ; Y index register. bne AGAIN ; Delay = #counts/processing speed. rts ;------------------------------------------------------------------- ***************** User Data ***************** COUNTER RMB 1 ; Counter for timing long pauses PROMPT DB "Push a button!" FCB $00 OUTPUT DB "Random # is: " FCB $00