Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Initial commit

  • Loading branch information...
commit 828d54be7958c33edcca1add51577f86e733aba7 0 parents
@mythmon authored
561 LCDDriver.asm
@@ -0,0 +1,561 @@
+;***********************************************************
+;*
+;* LCDDriver.asm - V2.0
+;*
+;* Contains the neccessary functions to display text to a
+;* 2 x 16 character LCD Display. Additional functions
+;* include a conversion routine from an unsigned 8-bit
+;* binary number to and ASCII text string.
+;*
+;* Version 2.0 - Added support for accessing the LCD
+;* Display via the serial port. See version 1.0 for
+;* accessing a memory mapped LCD display.
+;*
+;***********************************************************
+;*
+;* Author: David Zier
+;* Date: March 17, 2003
+;* Company: TekBots(TM), Oregon State University - EECS
+;* Version: 2.0
+;*
+;***********************************************************
+;* Rev Date Name Description
+;*----------------------------------------------------------
+;* - 8/20/02 Zier Initial Creation of Version 1.0
+;* A 3/7/03 Zier V2.0 - Updated for USART LCD
+;*
+;*
+;***********************************************************
+
+;***********************************************************
+;* Internal Register Definitions and Constants
+;* NOTE: A register MUST be named 'mpr' in the Main Code
+;* It is recomended to use register r16.
+;* WARNING: Register r17-r22 are reserved and cannot be
+;* renamed outside of the LCD Driver functions. Doing
+;* so will damage the functionality of the LCD Driver
+;***********************************************************
+.def wait = r17 ; Wait Loop Register
+.def count = r18 ; Character Counter
+.def line = r19 ; Line Select Register
+.def type = r20 ; LCD data type: Command or Text
+.def q = r21 ; Quotient for div10
+.def r = r22 ; Remander for div10
+
+.equ LCDLine1 = $80 ; LCD Line 1 select command
+.equ LCDLine2 = $c0 ; LCD Line 2 select command
+.equ LCDClear = $01 ; LCD Clear Command
+.equ LCDHome = $02 ; LCD Set Cursor Home Command
+.equ LCDPulse = $08 ; LCD Pulse signal, used to simulate
+ ; write signal
+
+.equ LCDCmd = $00 ; Constant used to write a command
+.equ LCDTxt = $01 ; Constant used to write a text character
+
+.equ LCDMaxCnt = 16 ; Maximum number of characters per line
+.equ LCDLn1Addr = $0100 ; Beginning address for Line 1 data
+.equ LCDLn2Addr = $0110 ; Beginning address for Line 2 data
+
+;-----------------------------------------------------------
+;***********************************************************
+;* Public LCD Driver Suboutines and Functions
+;* These functions and subroutines can be called safely
+;* from within any program
+;***********************************************************
+;-----------------------------------------------------------
+
+
+;*******************************************************
+;* SubRt: LCDInit
+;* Desc: Initialize the Serial Port and the Hitachi
+;* Display 8 Bit inc DD-RAM
+;* Pointer with no features
+;* - 2 LInes with 16 characters
+;*******************************************************
+LCDInit:
+ push mpr ; Save the state of machine
+ in mpr, SREG ; Save the SREG
+ push mpr ;
+ push wait ; Save wait
+
+ ; Setup the Communication Ports
+ ; Port B: Output
+ ; Port D: Input w/ internal pullup resistors
+ ; Port F: Output on Pin 3
+ ldi mpr, $00 ; Initialize Port B for outputs
+ out PORTB, mpr ; Port B outputs high
+ ldi mpr, $ff ; except for any overrides
+ out DDRB, mpr ;
+ ldi mpr, $00 ; Initialize Port D for inputs
+ out PORTD, mpr ; with Tri-State
+ ldi mpr, $00 ; except for any overrides
+ out DDRD, mpr ;
+ ldi mpr, $00 ; Initialize Port F Pin 3 to
+ sts PORTF, mpr ; output inorder to twiddle the
+ ldi mpr, (1<<DDF3) ; LCD interface
+ sts DDRF, mpr ; Must NOT override this port
+
+ ; Setup the Serial Functionality
+ ; SPI Type: Master
+ ; SPI Clock Rate: 2*1000.000 kHz
+ ; SPI Clock Phase: Cycle Half
+ ; SPI Clock Polarity: Low
+ ; SPI Data Order: MSB First
+ ldi mpr, (1<<SPE|1<<MSTR)
+ out SPCR, mpr ; Set Serial Port Control Register
+ ldi mpr, (1<<SPI2X)
+ out SPSR, mpr ; Set Serial Port Status Register
+
+ ; Setup External SRAM configuration
+ ; $0460 - $7FFF / $8000 - $FFFF
+ ; Lower page wait state(s): None
+ ; Uppoer page wait state(s): 2r/w
+ ldi mpr, (1<<SRE) ;
+ out MCUCR, mpr ; Initialize MCUCR
+ ldi mpr, (1<<SRL2|1<<SRW11)
+ sts XMCRA, mpr ; Initialize XMCRA
+ ldi mpr, (1<<XMBK) ;
+ sts XMCRB, mpr ; Initialize XMCRB
+
+ ; Initialize USART0
+ ; Communication Parameter: 8 bit, 1 stop, No Parity
+ ; USART0 Rx: On
+ ; USART0 Tx: On
+ ; USART0 Mode: Asynchronous
+ ; USART0 Baudrate: 9600
+ ldi mpr, $00 ;
+ out UCSR0A, mpr ; Init UCSR0A
+ ldi mpr, (1<<RXEN0|1<<TXEN0)
+ out UCSR0B, mpr ; Init UCSR0B
+ ldi mpr, (1<<UCSZ01|1<<UCSZ00)
+ sts UCSR0C, mpr ; Init UCSR0C
+ ldi mpr, $00 ;
+ sts UBRR0H, mpr ; Init UBRR0H
+ ldi mpr, $67 ;
+ out UBRR0L, mpr ; Init UBRR0L
+
+ ; Initialize the LCD Display
+ ldi mpr, 6 ;
+LCDINIT_L1:
+ ldi wait, 250 ; 15ms of Display
+ rcall LCDWait ; Bootup wait
+ dec mpr ;
+ brne LCDINIT_L1 ;
+
+ ldi mpr, $38 ; Display Mode set
+ rcall LCDWriteCmd ;
+ ldi mpr, $08 ; Display Off
+ rcall LCDWriteCmd ;
+ ldi mpr, $01 ; Display Clear
+ rcall LCDWriteCmd ;
+ ldi mpr, $06 ; Entry mode set
+ rcall LCDWriteCmd ;
+ ldi mpr, $0c ; Display on
+ rcall LCDWriteCmd ;
+ rcall LCDClr ; Clear display
+
+ pop wait ; Restore wait
+ pop mpr ; Restore SREG
+ out SREG, mpr ;
+ pop mpr ; Restore mpr
+ ret ; Return from subroutine
+
+;*******************************************************
+;* Func: LCDWrite
+;* Desc: Generic Write Function that writes both lines
+;* of text out to the LCD
+;* - Line 1 data is in address space $0100-$010F
+;* - Line 2 data is in address space $0110-$010F
+;*******************************************************
+LCDWrite:
+ rcall LCDWrLn1 ; Write Line 1
+ rcall LCDWrLn2 ; Write Line 2
+ ret ; Return from function
+
+;*******************************************************
+;* Func: LCDWrLn1
+;* Desc: This function will write the first line of
+;* data to the first line of the LCD Display
+;*******************************************************
+LCDWrLn1:
+ push mpr ; Save mpr
+ push ZL ; Save Z pointer
+ push ZH ;
+ push count ; Save the count register
+ push line ; Save the line register
+
+ ldi ZL, low(LCDLn1Addr)
+ ldi ZH, high(LCDLn1Addr)
+ ldi line, LCDLine1 ; Set LCD line to Line 1
+ rcall LCDSetLine ; Restart at the beginning of line 1
+ rcall LCDWriteLine ; Write the line of text
+
+ pop line
+ pop count ; Restore the counter
+ pop ZH ; Restore Z pointer
+ pop ZL ;
+ pop mpr ; Restore mpr
+ ret ; Return from function
+
+;*******************************************************
+;* Func: LCDWrLn2
+;* Desc: This function will write the second line of
+;* data to the second line of the LCD Display
+;*******************************************************
+LCDWrLn2:
+ push mpr ; Save mpr
+ push ZL ; Save Z pointer
+ push ZH ;
+ push count ; Save the count register
+ push line ; Save the line register
+
+ ldi ZL, low(LCDLn2Addr)
+ ldi ZH, high(LCDLn2Addr)
+ ldi line, LCDLine2 ; Set LCD line to Line 2
+ rcall LCDSetLine ; Restart at the beginning of line 2
+ rcall LCDWriteLine ; Write the line of text
+
+ pop line
+ pop count ; Restore the counter
+ pop ZH ; Restore Z pointer
+ pop ZL ;
+ pop mpr ; Restore mpr
+ ret ; Return from function
+
+;*******************************************************
+;* Func: LCDClr
+;* Desc: Generic Clear Subroutine that clears both
+;* lines of the LCD and Data Memory storage area
+;*******************************************************
+LCDClr:
+ rcall LCDClrLn1 ; Clear Line 1
+ rcall LCDClrLn2 ; Clear Line 2
+ ret ; Return from Subroutine
+
+;*******************************************************
+;* Func: LCDClrLn1
+;* Desc: This subroutine will clear the first line of
+;* the data and the first line of the LCD Display
+;*******************************************************
+LCDClrLn1:
+ push mpr ; Save mpr
+ push line ; Save line register
+ push count ; Save the count register
+ push ZL ; Save Z pointer
+ push ZH ;
+
+ ldi line, LCDline1 ; Set Access to Line 1 of LCD
+ rcall LCDSetLine ; Set Z pointer to address of line 1 data
+ ldi ZL, low(LCDLn1Addr)
+ ldi ZH, high(LCDLn1Addr)
+ rcall LCDClrLine ; Call the Clear Line function
+
+ pop ZH ; Restore Z pointer
+ pop ZL ;
+ pop count ; Restore the count register
+ pop line ; Restore line register
+ pop mpr ; Restore mpr
+ ret ; Return from Subroutine
+
+;*******************************************************
+;* Func: LCDClrLn2
+;* Desc: This subroutine will clear the second line of
+;* the data and the second line of the LCD Display
+;*******************************************************
+LCDClrLn2:
+ push mpr ; Save mpr
+ push line ; Save line register
+ push count ; Save the count register
+ push ZL ; Save Z pointer
+ push ZH ;
+
+ ldi line, LCDline2 ; Set Access to Line 2 of LCD
+ rcall LCDSetLine ; Set Z pointer to address of line 2 data
+ ldi ZL, low(LCDLn2Addr)
+ ldi ZH, high(LCDLn2Addr)
+ rcall LCDClrLine ; Call the Clear Line function
+
+ pop ZH ; Restore Z pointer
+ pop ZL ;
+ pop count ; Restore the count register
+ pop line ; Restore line register
+ pop mpr ; Restore mpr
+ ret ; Return from Subroutine
+
+;*******************************************************
+;* Func: LCDWriteByte
+;* Desc: This is a complex and low level function that
+;* allows any program to write any ASCII character
+;* (Byte) anywhere in the LCD Display. There
+;* are several things that need to be initialized
+;* before this function is called:
+;* count - Holds the index value of the line to where
+;* the char is written, 0-15(39). i.e. if
+;* count has the value of 3, then the char is
+;* going to be written to the third element of
+;* the line.
+;* line - Holds the line number that the char is going
+;* to be written to, (1 or 2).
+;* mpr - Contains the value of the ASCII character to
+;* be written (0-255)
+;*********************************************************
+LCDWriteByte:
+ push mpr ; Save the mpr
+ push line ; Save the line
+ push count ; Save the count
+ ; Preform sanity checks on count and line
+ cpi count, 40 ; Make sure count is within range
+ brsh LCDWriteByte_3 ; Do nothing and exit function
+ cpi line, 1 ; If (line == 1)
+ brne LCDWriteByte_1 ;
+ ldi line, LCDLine1 ; Load line 1 base LCD Address
+ rjmp LCDWriteByte_2 ; Continue on with function
+LCDWriteByte_1:
+ cpi line, 2 ; If (line == 2)
+ brne LCDWriteByte_3 ; Do nothing and exit function
+ ldi line, LCDLine2 ; Load line 2 base LCD Address
+
+LCDWriteByte_2: ; Write char to LCD
+ add line, count ; Set the correct LCD address
+ rcall LCDSetLine ; Set the line address to LCD
+ rcall LCDWriteChar ; Write Char to LCD Display
+
+LCDWriteByte_3: ; Exit Function
+ pop count ; Restore the count
+ pop line ; Restore the line
+ pop mpr ; Restore the mpr
+ ret ; Return from function
+
+;*******************************************************
+;* Func: Bin2ASCII
+;* Desc: Converts a binary number into an ASCII
+;* text string equivalent.
+;* - The binary number needs to be in the mpr
+;* - The Start Address of where the text will
+;* be placed needs to be in the X Register
+;* - The count of the characters created are
+;* added to the count register
+;*******************************************************
+Bin2ASCII:
+ push mpr ; save mpr
+ push r ; save r
+ push q ; save q
+ push XH ; save X-pointer
+ push XL ;
+
+ ; Determine the range of mpr
+ cpi mpr, 100 ; is mpr >= 100
+ brlo B2A_1 ; goto next check
+ ldi count, 3 ; Three chars are written
+ adiw XL, 3 ; Increment X 3 address spaces
+ rjmp B2A_3 ; Continue with program
+B2A_1: cpi mpr, 10 ; is mpr >= 10
+ brlo B2A_2 ; Continue with program
+ ldi count, 2 ; Two chars are written
+ adiw XL, 2 ; Increment X 2 address spaces
+ rjmp B2A_3 ; Continue with program
+B2A_2: adiw XL, 1 ; Increment X 1 address space
+ ldi count, 1 ; One char is written
+
+B2A_3: ;Do-While statement that converts Binary to ASCII
+ rcall div10 ; Call the div10 function
+ ldi mpr, '0' ; Set the base ASCII integer value
+ add mpr, r ; Create the ASCII integer value
+ st -X, mpr ; Load ASCII value to memory
+ mov mpr, q ; Set mpr to quotiant value
+ cpi mpr, 0 ; does mpr == 0
+ brne B2A_3 ; do while (mpr != 0)
+
+ pop XL ; restore X-pointer
+ pop XH ;
+ pop q ; restore q
+ pop r ; restore r
+ pop mpr ; restore mpr
+ ret ; return from function
+
+;-------------------------------------------------------
+;*******************************************************
+;* Private LCD Driver Functions and Subroutines
+;* NOTE: It is not recommended to call these functions
+;* or subroutines, only call the Public ones.
+;*******************************************************
+;-------------------------------------------------------
+
+;*******************************************************
+;* Func: LCDSetLine
+;* Desc: Change line to be written to
+;*******************************************************
+LCDSetLine:
+ push mpr ; Save mpr
+ mov mpr,line ; Copy Command Data to mpr
+ rcall LCDWriteCmd ; Write the Command
+ pop mpr ; Restore the mpr
+ ret ; Return from function
+
+;*******************************************************
+;* Func: LCDClrLine
+;* Desc: Manually clears a single line within an LCD
+;* Display and Data Memory by writing 16
+;* consecutive ASCII spaces $20 to both the LCD
+;* and the memory. The line to be cleared must
+;* first be set in the LCD and the Z pointer is
+;* pointing the first element in Data Memory
+;*******************************************************
+LCDClrLine:
+ ldi mpr, ' ' ; The space char to be written
+ ldi count, LCDMaxCnt; The character count
+LCDClrLine_1:
+ st Z+, mpr ; Clear data memory element
+ rcall LCDWriteChar ; Clear LCD memory element
+ dec count ; Decrement the count
+ brne LCDClrLine_1 ; Continue untill all elements are cleared
+ ret ; Return from function
+
+;*******************************************************
+;* Func: LCDWriteLine
+;* Desc: Writes a line of text to the LCD Display.
+;* This routine takes a data element pointed to
+;* by the Z-pointer and copies it to the LCD
+;* Display for the duration of the line. The
+;* line the Z-pointer must be set prior to the
+;* function call.
+;*******************************************************
+LCDWriteLine:
+ ldi count, LCDMaxCnt; The character count
+LCDWriteLine_1:
+ ld mpr, Z+ ; Get the data element
+ rcall LCDWriteChar ; Write element to LCD Display
+ dec count ; Decrement the count
+ brne LCDWriteLine_1 ; Continue untill all elements are written
+ ret ; Return from function
+
+;*******************************************************
+;* Func: LCDWriteCmd
+;* Desc: Write command that is in the mpr to LCD
+;*******************************************************
+LCDWriteCmd:
+ push type ; Save type register
+ push wait ; Save wait register
+ ldi type, LCDCmd ; Set type to Command data
+ rcall LCDWriteData ; Write data to LCD
+ push mpr ; Save mpr register
+ ldi mpr, 2 ; Wait approx. 4.1 ms
+LCDWC_L1:
+ ldi wait, 205 ; Wait 2050 us
+ rcall LCDWait ;
+ dec mpr ; The wait loop cont.
+ brne LCDWC_L1 ;
+ pop mpr ; Restore mpr
+ pop wait ; Restore wait register
+ pop type ; Restore type register
+ ret ; Return from function
+
+;*******************************************************
+;* Func: LCDWriteChar
+;* Desc: Write character data that is in the mpr
+;*******************************************************
+LCDWriteChar:
+ push type ; Save type register
+ push wait ; Save the wait register
+ ldi type, LCDTxt ; Set type to Text data
+ rcall LCDWriteData ; Write data to LCD
+ ldi wait, 16 ; Delay 160 us
+ rcall LCDWait ;
+ pop wait ; Restore wait register
+ pop type ; Restore type register
+ ret ; Return from function
+
+;*******************************************************
+;* Func: LCDWriteData
+;* Desc: Write data or command to LCD
+;*******************************************************
+LCDWriteData:
+ out SPDR, type ; Send type to SP
+ ldi wait, 2 ; Wait 2 us
+ rcall LCDWait ; Call Wait function
+ out SPDR,mpr ; Send data to serial port
+ ldi wait, 2 ; Wait 2 us
+ rcall LCDWait ; Call Wait function
+ ldi wait, LCDPulse ; Use wait temporarially to
+ sts PORTF, wait ; to send write pulse to LCD
+ ldi wait, $00 ;
+ sts PORTF, wait ;
+ ret ; Return from function
+
+;*******************************************************
+;* Func: LCDWait
+;* Desc: A wait loop that is 10 + 159*wait cycles or
+;* roughly wait*10us. Just initialize wait
+;* for the specific amount of time in 10us
+;* intervals.
+;*******************************************************
+LCDWait:push mpr ; Save mpr
+LCDW_L1:ldi mpr, $49 ; Load with a 10us value
+LCDW_L2:dec mpr ; Inner Wait Loop
+ brne LCDW_L2
+ dec wait ; Outer Wait Loop
+ brne LCDW_L1
+ pop mpr ; Restore mpr
+ ret ; Return from Wait Function
+
+;*******************************************************
+;* Bin2ASCII routines that can be used as a psuedo-
+;* printf function to convert an 8-bit binary
+;* number into the unigned decimal ASCII text
+;*******************************************************
+
+;***********************************************************
+;* Func: div10
+;* Desc: Divides the value in the mpr by 10 and
+;* puts the remander in the 'r' register and
+;* and the quotiant in the 'q' register.
+;* DO NOT modify this function, trust me, it does
+;* divide by 10 :) ~DZ
+;***********************************************************
+div10:
+ push r0 ; Save register
+
+ ; q = mpr / 10 = mpr * 0.000110011001101b
+ mov q, mpr ; q = mpr * 1.0b
+ lsr q ; q >> 2
+ lsr q ; q = mpr * 0.01b
+ add q, mpr ; q = (q + mpr) >> 1
+ lsr q ; q = mpr * 0.101b
+ add q, mpr ; q = (q + mpr) >> 3
+ lsr q
+ lsr q
+ lsr q ; q = mpr * 0.001101b
+ add q, mpr ; q = (q + mpr) >> 1
+ lsr q ; q = mpr * 0.1001101b
+ add q, mpr ; q = (q + mpr) >> 3
+ lsr q
+ lsr q
+ lsr q ; q = mpr * 0.0011001101b
+ add q, mpr ; q = (q + mpr) >> 1
+ lsr q ; q = mpr * 0.10011001101b
+ add q, mpr ; q = (q + mpr) >> 4
+ lsr q
+ lsr q
+ lsr q
+ lsr q ; q = mpr * 0.000110011001101b
+
+ ; compute the remainder as r = i - 10 * q
+ ; calculate r = q * 10 = q * 1010b
+ mov r, q ; r = q * 1
+ lsl r ; r << 2
+ lsl r ; r = q * 100b
+ add r, q ; r = (r + q) << 1
+ lsl r ; r = q * 1010b
+ mov r0, r ; r0 = 10 * q
+ mov r, mpr ; r = mpr
+ sub r, r0 ; r = mpr - 10 * q
+
+ ; Fix any errors that occur
+div10_1:cpi r, 10 ; Compare with 10
+ brlo div10_2 ; do nothing if r < 10
+ inc q ; fix qoutient
+ subi r, 10 ; fix remainder
+ rjmp div10_1 ; Continue until error is corrected
+
+div10_2:pop r0 ; Restore registers
+ ret ; Return from function
15 Makefile
@@ -0,0 +1,15 @@
+main: clean story-data.asm
+ avra hellodave.asm
+
+clean:
+ rm -f hellodave.hex
+ rm -f hellodave.eep.hex
+ rm -f hellodave.obj
+ rm -f storydata.asm
+ rm -f hellodave.cof
+
+story-data.asm:
+ ./data-to-asm.py
+
+install: main
+ sudo avrdude -p m128 -c osuisp2 -U flash:w:hellodave.hex
42 data-to-asm.py
@@ -0,0 +1,42 @@
+#!/usr/bin/python
+
+import re
+
+data_path = 'data.txt'
+blocks = []
+
+try:
+ data_file = open(data_path)
+ for line in data_file:
+ if line.strip() == '':
+ continue
+ block = {}
+ block['name'] = line.strip()
+ line1 = data_file.readline()[:-1]
+ line2 = data_file.readline()[:-1]
+
+ # 0x7E and 0x7F are right/left arrows on the microcontroller.
+ if line1[0] == '<':
+ line1 = chr(0x7F) + line1[1:]
+ if line2[0] == '>':
+ line2 = chr(0x7E) + line2[1:]
+
+ block['line1'] = line1.ljust(16)
+ block['line2'] = line2.ljust(16)
+ block['opt1'], block['opt2'] = [x.strip() for x in data_file.readline().split(',')]
+ blocks.append(block)
+finally:
+ data_file.close()
+
+try:
+ output = open('storydata.asm', 'w')
+
+ for block in blocks:
+ output.write('{0[name]}:\n'.format(block))
+ output.write('.DB "{0[line1]}"\n'.format(block))
+ output.write('.DB "{0[line2]}"\n'.format(block))
+ output.write('.DW {0[opt1]} << 1\n'.format(block))
+ output.write('.DW {0[opt2]} << 1\n'.format(block))
+ output.write('\n')
+finally:
+ output.close()
149 data.txt
@@ -0,0 +1,149 @@
+story0
+ Greetings
+ Dave
+opt0,opt0
+
+story1
+Would you like
+to play a game?
+opt1, opt1
+
+story2
+A battle of wits
+if I win you die
+opt2, opt2
+
+story3
+ To forfeit
+ is to die
+opt3, opt3
+
+story4
+First clue:
+A porcelain duck
+opt4, opt4
+
+story5
+ A small paper
+ falls out
+opt5, opt5
+
+story6
+Theres a hole
+with paper in it
+opt6, opt6
+
+story7
+ A secret
+message appears
+story8, story8
+
+story8
+ Beware the
+ Octopus!
+opt8, opt8
+
+story9
+Behind you a
+ door opens...
+story10, story10
+
+story10
+ You hear
+someone come in
+opt10, opt10
+
+story11
+Is that you
+Dave?
+opt11, opt11
+
+story12
+Your heart is
+hammering
+story13, story13
+
+story13
+You run into
+ a broom closet
+opt14, opt14
+
+story14
+You arm yourself
+with a broom
+opt14, opt14
+
+opt0
+< Im not Dave
+> Hello
+NONE, story1
+
+opt1
+< No
+> What game?
+GAMEOVER, story2
+
+opt2
+< No thanks
+> Sure
+story3, story4
+
+opt3
+< Oh Well
+> Fine Ill play
+GAMEOVER, story4
+
+opt4
+< Smash it!
+> Look under it
+story5, story6
+
+opt5
+< Pick it up
+> Burn it
+POISON, story7
+
+opt6
+< Pull paper out
+> Smash duck!
+POISON, story5
+
+opt8
+< Write it down
+> Memorize it
+story9, NONE
+
+opt10
+< Say 'Hi Sam'
+> Stay silent
+NONE, story11
+
+opt11
+< Say 'Yes'
+> Run away
+NONE, story12
+
+opt13
+> Grab something
+< Listen outside
+story14, NONE
+
+opt14
+> Run out&attack
+< Sneak out
+NONE, NONE
+
+POISON
+You have been
+poisoned
+GAMEOVER, GAMEOVER
+
+GAMEOVER
+ G A M E
+ O V E R
+story0, story0
+
+NONE
+Oops! No one has
+written this yet
+story0, story0
194 hellodave.asm
@@ -0,0 +1,194 @@
+;***********************************************************
+;*
+;* Enter Name of file here
+;*
+;* Enter the description of the program here
+;*
+;* This is the skeleton file Lab 3 of ECE 375
+;*
+;***********************************************************
+;*
+;* Author: Enter your name
+;* Date: Enter Date
+;*
+;***********************************************************
+
+.include "m128def.inc" ; Include definition file
+
+;***********************************************************
+;* Internal Register Definitions and Constants
+;***********************************************************
+.def mpr = r16 ; Multipurpose register required for LCD Driver
+.def olcnt = r23 ; Used as the outer loop counter
+.def ilcnt = r24 ; Used as the inner loop counter
+.def waitcnt = r25 ; Used in the wait loop counter
+
+.equ BTN_RIGHT = 15 ; Buttons on the right side of the board
+.equ BTN_LEFT = 240 ; Buttons on the left side
+
+;***********************************************************
+;* Start of Code Segment
+;***********************************************************
+.cseg ; Beginning of code segment
+
+;-----------------------------------------------------------
+; Interrupt Vectors
+;-----------------------------------------------------------
+.org $0000 ; Beginning of IVs
+ rjmp INIT ; Reset interrupt
+
+.org $0046 ; End of Interrupt Vectors
+
+;-----------------------------------------------------------
+; Program Initialization
+;-----------------------------------------------------------
+INIT: ; The initialization routine
+ ; Initialize Stack Pointer
+ ldi mpr, HIGH(RAMEND)
+ out SPH, mpr
+ ldi mpr, LOW(RAMEND)
+ out SPL, mpr
+
+ ; Initialize LCD Display
+ rcall LCDInit
+
+ ; Initialize Port D for inputs
+ ldi mpr, $FF ; Initialize Port D for inputs
+ out PORTD, mpr ; with Tri-State
+ ldi mpr, $00 ; Set Port D Directional Register
+ out DDRD, mpr ; for inputs
+
+;-----------------------------------------------------------
+; Main Program
+;-----------------------------------------------------------
+MAIN:
+ ; Move to the first data block
+ ldi ZL, low(START<<1)
+ ldi ZH, high(START<<1)
+ ldi YL, low(LCDLn1Addr)
+ ldi YH, high(LCDLn1Addr)
+
+GAME:
+ ; Draw the text to the screen
+ rcall SubDrawScreen
+
+ ldi olcnt, 32
+
+ adiw ZH:ZL, 32 ; Move past the game text.
+
+ ldi waitcnt, 25
+ rcall SubWait
+ rjmp INPUT ; Wait for user input
+
+INPUT: ; Get user input and move the story appropriately
+ ; TODO: This should be done with interrupts.
+busywait: ; Wait for a button press
+ in mpr, PIND ; Note: active low
+ com mpr ; Flip the input
+ andi mpr, BTN_RIGHT ; Check for the right buttons
+ brne RIGHT_PRESS ; Branch if any button pressed
+
+ in mpr, PIND ; Note: active low
+ com mpr ; Flip the input
+ andi mpr, BTN_LEFT ; Check for the left buttons
+ brne LEFT_PRESS ; Branch if any button pressed
+
+ rjmp busywait ; Wait for input
+
+RIGHT_PRESS:
+ lpm XL, Z+
+ lpm XH, Z+
+ rjmp MOVE_ON
+
+LEFT_PRESS:
+ rjmp MOVE_ON
+
+MOVE_ON:
+ ; Load the next-block pointer from the end of the current block and
+ ; make Z point to the next block.
+ lpm XL, Z+
+ lpm XH, Z+
+
+ movw ZH:ZL, XH:XL
+
+ rjmp GAME ; Game Loop
+
+;***********************************************************
+;* Functions and Subroutines
+;***********************************************************
+
+;----------------------------------------------------------------
+; Sub: SubDrawScreen
+; Desc: Writes the page in program memory pointed to by the Z
+; register to the LCD.
+;----------------------------------------------------------------
+SubDrawScreen:
+ ; Save registers on the stack
+ push mpr
+ push ZH
+ push ZL
+ push YH
+ push YL
+ push olcnt
+
+ ; Point the Y register to the LCD memory.
+ ldi YL, low(LCDLn1Addr)
+ ldi YH, high(LCDLn1Addr)
+
+ ldi olcnt, 32 ; The number of chars on the screen
+LOAD_TEXT:
+ lpm mpr, Z+ ; Get the character
+ st Y+, mpr ; Put it in the LCD memory
+ dec olcnt ; One less character
+ brne LOAD_TEXT ; Are we done yet?
+
+ rcall LCDWrite ; Put it on the screen.
+
+ ; Restore registers from the stack
+ pop olcnt
+ pop YL
+ pop YH
+ pop ZL
+ pop ZH
+ pop mpr
+
+ ret
+
+;----------------------------------------------------------------
+; Sub: SubWait
+; Desc: A wait loop that is 16 + 159975*waitcnt cycles or roughly
+; waitcnt*10ms. Just initialize wait for the specific amount
+; of time in 10ms intervals. Here is the general eqaution
+; for the number of clock cycles in the wait loop:
+; ((3 * ilcnt + 3) * olcnt + 3) * waitcnt + 13 + call
+;----------------------------------------------------------------
+SubWait:
+ push waitcnt ; Save wait register
+ push ilcnt ; Save ilcnt register
+ push olcnt ; Save olcnt register
+
+Loop: ldi olcnt, 224 ; load olcnt register
+OLoop: ldi ilcnt, 237 ; load ilcnt register
+ILoop: dec ilcnt ; decrement ilcnt
+ brne ILoop ; Continue Inner Loop
+ dec olcnt ; decrement olcnt
+ brne OLoop ; Continue Outer Loop
+ dec waitcnt ; Decrement wait
+ brne Loop ; Continue Wait loop
+
+ pop olcnt ; Restore olcnt register
+ pop ilcnt ; Restore ilcnt register
+ pop waitcnt ; Restore wait register
+ ret ; Return from subroutine
+
+;***********************************************************
+;* Stored Program Data
+;***********************************************************
+
+START:
+.include "storydata.asm"
+
+;***********************************************************
+;* Additional Program Includes
+;***********************************************************
+.include "LCDDriver.asm" ; Include the LCD Driver
1  m128def.inc
Please sign in to comment.
Something went wrong with that request. Please try again.