Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- .INCLUDE "m128def.inc"
- ;==========================================================STUDENT DIRECTIVES====================================================
- .equ addresLineOne = 0x0100
- .equ addresLineTwo = 0x0200
- ;===================================================================MACROS==========================================================================
- ;Macro operations to increase the readibility of the code and avoid repetition
- ;This is an operation for initializing Z register with an address where the data for LCD_Line_One is coming from
- .MACRO initZforLineOne
- ldi ZH, high(addresLineOne)
- ldi ZL, low(addresLineOne)
- .ENDMACRO
- ;This is an operation for initializing Z register with an address where the data for LCD_Line_Two is coming from
- .MACRO initZforLineTwo
- ldi ZH, high(addresLineTwo)
- ldi ZL, low(addresLineTwo)
- .ENDMACRO
- ;This is an operation for storing giving register values in binary by using ascii code of one and zero so that LCD can print data in the right format
- ;It also includes a null character at the end of the string to ensure that printing operation will terminate
- .MACRO storeRegisterForLCD
- ;convert the number to ascii and store in address text
- ldi r17, '1'
- sbrs @0, 7
- ldi r17, '0'
- st Z+, r17
- ldi r17, '1'
- sbrs @0, 6
- ldi r17, '0'
- st Z+, r17
- ldi r17, '1'
- sbrs @0, 5
- ldi r17, '0'
- st Z+, r17
- ldi r17, '1'
- sbrs @0, 4
- ldi r17, '0'
- st Z+, r17
- ldi r17, '1'
- sbrs @0, 3
- ldi r17, '0'
- st Z+, r17
- ldi r17, '1'
- sbrs @0, 2
- ldi r17, '0'
- st Z+, r17
- ldi r17, '1'
- sbrs @0, 1
- ldi r17, '0'
- st Z+, r17
- ldi r17, '1'
- sbrs @0, 0
- ldi r17, '0'
- st Z+, r17
- call nullToZLast
- .ENDMACRO
- ;This is an operation for calculating the parity bit of first number which is coming from PIND.
- ;It also appends the calculated parity bit to the memory adress stored in Z register and adds null character next to it for terminating printing operation to LCD
- .MACRO contParitywithStore
- sbic pind, 0
- inc @0
- sbic pind, 1
- inc @0
- sbic pind, 2
- inc @0
- sbic pind, 3
- inc @0
- sbic pind, 4
- inc @0
- sbic pind, 5
- inc @0
- sbic pind, 6
- inc @0
- sbic pind, 7
- inc @0
- ldi r17, '0'
- SBRC @0, 0
- ldi r17, '1'
- st Z+, r17
- call nullToZLast
- .ENDMACRO
- ;=============================================================LCD DIRECTIVES===================================================
- ;Majority of the directives come from LCD inferface yet there are two in the beginning of to code for address stored in Z register
- .equ fclk = 8000000 ; system clock frequency (for delays)
- ; register usage
- .def temp = R16 ; temporary storage
- ; LCD interface
- .equ lcd_D7_port = PORTC ; lcd D7 connection
- .equ lcd_D7_bit = PORTC7
- .equ lcd_D7_ddr = DDRC
- .equ lcd_D6_port = PORTC ; lcd D6 connection
- .equ lcd_D6_bit = PORTC6
- .equ lcd_D6_ddr = DDRC
- .equ lcd_D5_port = PORTC ; lcd D5 connection
- .equ lcd_D5_bit = PORTC5
- .equ lcd_D5_ddr = DDRC
- .equ lcd_D4_port = PORTC ; lcd D4 connection
- .equ lcd_D4_bit = PORTC4
- .equ lcd_D4_ddr = DDRC
- .equ lcd_E_port = PORTB ; lcd Enable pin
- .equ lcd_E_bit = PORTB5
- .equ lcd_E_ddr = DDRB
- .equ lcd_RS_port = PORTB ; lcd Register Select pin
- .equ lcd_RS_bit = PORTB2
- .equ lcd_RS_ddr = DDRB
- ; LCD module Lines
- .equ lcd_LineOne = 0x00 ; line 1
- .equ lcd_LineTwo = 0x40 ; line 2
- ; LCD Defined instructions
- .equ lcd_Clear = 0b00000001 ; ASCII 'space' for all characters
- .equ lcd_Home = 0b00000010 ; first position on first line
- .equ lcd_EntryMode = 0b00000110 ; shift cursor from left to right on read/write
- .equ lcd_DisplayOff = 0b00001000 ; turn display off
- .equ lcd_DisplayOn = 0b00001100 ; display on, cursor off, don't blink character
- .equ lcd_FunctionReset = 0b00110000 ; reset the LCD
- .equ lcd_FunctionSet4bit = 0b00101000 ; 4-bit data, 2-line display, 5 x 7 font
- .equ lcd_SetCursor = 0b10000000 ; set cursor position
- ; ****************************** Reset Vector *******************************
- .org 0x0000
- jmp start ; jump over Interrupt Vectors, Program ID etc.
- ;******************************* Program ID *********************************
- .org INT_VECTORS_SIZE
- ; ****************************** Main Program Code **************************
- start:
- ; initialize the stack pointer to the highest RAM address
- ldi temp,low(RAMEND)
- out SPL,temp
- ldi temp,high(RAMEND)
- out SPH,temp
- ; configure the microprocessor pins for the data lines
- sbi lcd_D7_ddr, lcd_D7_bit ; 4 data lines - output
- sbi lcd_D6_ddr, lcd_D6_bit
- sbi lcd_D5_ddr, lcd_D5_bit
- sbi lcd_D4_ddr, lcd_D4_bit
- ; configure the microprocessor pins for the control lines
- sbi lcd_E_ddr, lcd_E_bit ; E line - output
- sbi lcd_RS_ddr, lcd_RS_bit ; RS line - output
- ; initialize the LCD controller
- call lcd_init_4d ; initialize the LCD display for a 4-bit interface
- ldi r20, 0x00
- out ddra, r20
- out ddrd, r20
- out ddre, r20
- jmp READ
- READ: ;start of each capture iteration
- call clearLcdMemoryAddresses
- in r20, pind
- in r17, pine
- in R21, pina
- andi R21,0x03
- CPI R21,0x00
- BREQ PROCESS_ZERO
- CPI R21,0x01
- BREQ PROCESS_ONE
- CPI R21,0x10
- BREQ PROCESS_TWO
- CPI R21,0x11
- BREQ PROCESS_THREE
- PROCESS_ZERO:
- CALL mode00
- jmp printToLCD
- JMP READ
- PROCESS_ONE:
- CALL mode01
- jmp printToLCD
- JMP READ
- PROCESS_TWO:
- ;CALL mode00
- JMP READ
- PROCESS_THREE:
- ;CALL mode00
- JMP READ
- mode01: ;print first number and an even parity bit
- initZforLineOne
- storeRegisterForLCD r20
- ldi r18, 0; some odd number
- contParitywithStore r18
- call nullToZLast
- jmp printToLcd
- mode00: ;print first number and an odd parity bit
- initZforLineOne
- storeRegisterForLCD r20
- ldi r18, 1;some even number
- contParitywithStore r18
- call nullToZLast
- jmp printToLcd
- mode11:
- mov r18, r17
- sub r17, r20
- brmi logicisfalse
- mov r18, r17
- call printHex
- initZforLineOne
- storeRegisterForLCD r18
- jmp printToLcd
- logicisfalse:
- sub r20, r18
- mov r18, r20
- call printHex
- initZforLineOne
- storeRegisterForLCD r18
- jmp printToLcd
- mode10:
- mov r18, r17
- sub r18, r20
- breq equal
- mov r18, r17
- sub r18, r20
- brmi less
- mov r18, r17
- call printHex
- jmp printToLcd
- equal:
- initZforLineTwo
- ldi r19, 'E'
- st Z+, r19
- ldi r19, 'Q'
- st Z+, r19
- jmp printToLcd
- less:
- mov r18, r20
- call printHex
- jmp printToLcd
- ;====================================================================STUDENT WRITTEN FUNCTIONS====================================================
- printHex:
- initZforLineTwo
- mov r19, r18
- swap r19
- andi r19, 0x0F
- cpi r19, 0x0A
- brlt lessThanAR
- subi r19, 9
- ori r19, 0x40
- st Z+, r19
- jmp secondHex
- lessThanAR:
- ori r19,0x30
- st Z+, r19
- secondHex:
- mov r19, r18
- andi r19, 0x0F
- cpi r19, 0x0A
- brlt lessThanAL
- subi r19, 9
- ori r19, 0x40
- st Z+, r19
- ret
- lessThanAL:
- ori r19,0x30
- st Z+, r19
- ret
- printToLcd:
- in R16, PINB;
- ; display the first line of information
- ldi ZH, high(addresLineOne) ; point to the information that is to be displayed
- ldi ZL, low(addresLineOne)
- ldi temp, lcd_LineOne ; point to where the information should be displayed
- call lcd_write_string_4d
- ; display the second line of information
- ldi ZH, high(addresLineTwo) ; point to the information that is to be displayed
- ldi ZL, low(addresLineTwo)
- ldi temp, lcd_LineTwo ; point to where the information should be displayed
- call lcd_write_string_4d
- rjmp READ
- nullToZLast:
- ldi r17, 0x00
- st Z, r17
- ret
- fillZWithEmptySpaces:
- ldi r17, lcd_Clear
- st Z+, r17
- st Z+, r17
- st Z+, r17
- st Z+, r17
- st Z+, r17
- st Z+, r17
- st Z+, r17
- st Z+, r17
- st Z+, r17
- st Z+, r17
- st Z+, r17
- st Z+, r17
- st Z+, r17
- st Z+, r17
- st Z+, r17
- st Z+, r17
- st Z+, r17
- call nullToZLast
- ret
- clearLcdMemoryAddresses:
- initZforLineOne
- call fillZWithEmptySpaces
- initZforLineTwo
- call fillZWithEmptySpaces
- ret
- ; ****************************** End of Main Program Code *******************
- ; ****************************** LCD Code **************************
- initializeLCD:
- ; initialize the stack pointer to the highest RAM address
- ldi temp,low(RAMEND)
- out SPL,temp
- ldi temp,high(RAMEND)
- out SPH,temp
- ; configure the microprocessor pins for the data lines
- sbi lcd_D7_ddr, lcd_D7_bit ; 4 data lines - output
- sbi lcd_D6_ddr, lcd_D6_bit
- sbi lcd_D5_ddr, lcd_D5_bit
- sbi lcd_D4_ddr, lcd_D4_bit
- ; configure the microprocessor pins for the control lines
- sbi lcd_E_ddr, lcd_E_bit ; E line - output
- sbi lcd_RS_ddr, lcd_RS_bit ; RS line - output
- ; initialize the LCD controller
- call lcd_init_4d ; initialize the LCD display for a 4-bit interface
- jmp start
- ; ============================== 4-bit LCD Function Calls ======================
- ; Name: lcd_init_4d -- initialize the LCD module for a 4-bit data interface
- lcd_init_4d:
- ; Power-up delay
- ldi temp, 100 ; initial 40 mSec delay
- call delayTx1mS
- ; IMPORTANT - At this point the LCD module is in the 8-bit mode and it is expecting to receive
- ; 8 bits of data, one bit on each of its 8 data lines, each time the 'E' line is pulsed.
- ;
- ; Since the LCD module is wired for the 4-bit mode, only the upper four data lines are connected to
- ; the microprocessor and the lower four data lines are typically left open. Therefore, when
- ; the 'E' line is pulsed, the LCD controller will read whatever data has been set up on the upper
- ; four data lines and the lower four data lines will be high (due to internal pull-up circuitry).
- ;
- ; Fortunately the 'FunctionReset' instruction does not care about what is on the lower four bits so
- ; this instruction can be sent on just the four available data lines and it will be interpreted
- ; properly by the LCD controller. The 'lcd_write_4' subroutine will accomplish this if the
- ; control lines have previously been configured properly.
- ; Set up the RS and E lines for the 'lcd_write_4' subroutine.
- cbi lcd_RS_port, lcd_RS_bit ; select the Instruction Register (RS low)
- cbi lcd_E_port, lcd_E_bit ; make sure E is initially low
- ; Reset the LCD controller.
- ldi temp, lcd_FunctionReset ; first part of reset sequence
- call lcd_write_4
- ldi temp, 10 ; 4.1 mS delay (min)
- call delayTx1mS
- ldi temp, lcd_FunctionReset ; second part of reset sequence
- call lcd_write_4
- ldi temp, 200 ; 100 uS delay (min)
- call delayTx1uS
- ldi temp, lcd_FunctionReset ; third part of reset sequence
- call lcd_write_4
- ldi temp, 200 ; this delay is omitted in the data sheet call
- call delayTx1uS
- ; Preliminary Function Set instruction - used only to set the 4-bit mode.
- ; The number of lines or the font cannot be set at this time since the controller is still in the
- ; 8-bit mode, but the data transfer mode can be changed since this parameter is determined by one
- ; of the upper four bits of the instruction.
- ldi temp, lcd_FunctionSet4bit ; set 4-bit mode
- call lcd_write_4
- ldi temp, 80 ; 40 uS delay (min)
- call delayTx1uS
- ; Function Set instruction
- ldi temp, lcd_FunctionSet4bit ; set mode, lines, and font
- call lcd_write_instruction_4d
- ldi temp, 80 ; 40 uS delay (min)
- call delayTx1uS
- ; The next three instructions are specified in the data sheet as part of the initialization routine,
- ; so it is a good idea (but probably not necessary) to do them just as specified and then redo them
- ; later if the application requires a different configuration.
- ; Display On/Off Control instruction
- ldi temp, lcd_DisplayOff ; turn display OFF
- call lcd_write_instruction_4d
- ldi temp, 80 ; 40 uS delay (min)
- call delayTx1uS
- ; Clear Display instruction
- ldi temp, lcd_Clear ; clear display RAM
- call lcd_write_instruction_4d
- ldi temp, 4 ; 1.64 mS delay (min)
- call delayTx1mS
- ; Entry Mode Set instruction
- ldi temp, lcd_EntryMode ; set desired shift characteristics
- call lcd_write_instruction_4d
- ldi temp, 80 ; 40 uS delay (min)
- call delayTx1uS
- ; This is the end of the LCD controller initialization as specified in the data sheet, but the display
- ; has been left in the OFF condition. This is a good time to turn the display back ON.
- ; Display On/Off Control instruction
- ldi temp, lcd_DisplayOn ; turn the display ON
- call lcd_write_instruction_4d
- ldi temp, 80 ; 40 uS delay (min)
- call delayTx1uS
- ret
- ; ---------------------------------------------------------------------------
- ; Name: lcd_write_string_4d ; Purpose: display a string of characters on the LCD
- ; Entry: ZH and ZL pointing to the start of the string
- ; (temp) contains the desired DDRAM address at which to start the display
- ; Exit: no parameters
- ; Notes: the string must end with a null (0)
- ; uses time delays instead of checking the busy flag
- lcd_write_string_4d:
- ; preserve registers
- push ZH ; preserve pointer registers
- push ZL
- ; set up the initial DDRAM address
- ori temp, lcd_SetCursor ; convert the plain address to a set cursor instruction
- call lcd_write_instruction_4d ; set up the first DDRAM address
- ldi temp, 80
- call delayTx1uS
- ; write the string of characters
- lcd_write_string_4d_01:
- ld temp, Z+ ; get a character
- cpi temp, 0 ; check for end of string
- breq lcd_write_string_4d_02 ; done
- ; arrive here if this is a valid character
- call lcd_write_character_4d ; display the character
- ldi temp, 80
- call delayTx1uS
- rjmp lcd_write_string_4d_01 ; not done, send another character
- ; arrive here when all characters in the message have been sent to the LCD module
- lcd_write_string_4d_02:
- pop ZL ; restore pointer registers
- pop ZH
- ret
- ; ---------------------------------------------------------------------------
- ; Name: lcd_write_character_4d
- ; Purpose: send a byte of information to the LCD data register
- ; Entry: (temp) contains the data byte ; Exit: no parameters
- ; Notes: does not deal with RW (busy flag is not implemented)
- lcd_write_character_4d:
- sbi lcd_RS_port, lcd_RS_bit ; select the Data Register (RS high)
- cbi lcd_E_port, lcd_E_bit ; make sure E is initially low
- call lcd_write_4 ; write the upper 4-bits of the data
- swap temp ; swap high and low nibbles
- call lcd_write_4 ; write the lower 4-bits of the data
- ret
- ; ---------------------------------------------------------------------------
- ; Name: lcd_write_instruction_4d -- Send a byte of information to the LCD instruction register
- lcd_write_instruction_4d:
- cbi lcd_RS_port, lcd_RS_bit ; select the Instruction Register (RS low)
- cbi lcd_E_port, lcd_E_bit ; make sure E is initially low
- call lcd_write_4 ; write the upper 4-bits of the instruction
- swap temp ; swap high and low nibbles
- call lcd_write_4 ; write the lower 4-bits of the instruction
- ret
- ; ---------------------------------------------------------------------------
- ; Name: lcd_write_4 Send 4-bits of information to the LCD module
- ; Entry: (temp) contains a byte of data with the desired 4-bits in the upper nibble
- ; (RS) is configured for the desired LCD register
- ; (E) is low
- ; (RW) is low
- lcd_write_4:
- ; set up D7
- sbi lcd_D7_port, lcd_D7_bit ; assume that the D7 data is '1'
- sbrs temp, 7 ; check the actual data value
- cbi lcd_D7_port, lcd_D7_bit ; arrive here only if the data was actually '0'
- ; set up D6
- sbi lcd_D6_port, lcd_D6_bit ; repeat for each data bit
- sbrs temp, 6
- cbi lcd_D6_port, lcd_D6_bit
- ; set up D5
- sbi lcd_D5_port, lcd_D5_bit
- sbrs temp, 5
- cbi lcd_D5_port, lcd_D5_bit
- ; set up D4
- sbi lcd_D4_port, lcd_D4_bit
- sbrs temp, 4
- cbi lcd_D4_port, lcd_D4_bit
- ; write the data
- ; 'Address set-up time' (40 nS)
- sbi lcd_E_port, lcd_E_bit ; Enable pin high
- call delay1uS ; implement 'Data set-up time' (80 nS) and 'Enable pulse width' (230 nS)
- cbi lcd_E_port, lcd_E_bit ; Enable pin low
- call delay1uS ; implement 'Data hold time' (10 nS) and 'Enable cycle time' (500 nS)
- ret
- ; ============================== End of 4-bit LCD Subroutines ===============
- ; ============================== Time Delay Subroutines =====================
- ; Name: delayYx1mS Delay of (YH:YL) x 1 mS
- delayYx1mS:
- call delay1mS ; delay for 1 mS
- sbiw YH:YL, 1 ; update the the delay counter
- brne delayYx1mS ; counter is not zero
- ; arrive here when delay counter is zero (total delay period is finished)
- ret
- ; ---------------------------------------------------------------------------
- ; Name: delayTx1mS Provide a delay of (temp) x 1 mS
- delayTx1mS:
- call delay1mS ; delay for 1 mS
- dec temp ; update the delay counter
- brne delayTx1mS ; counter is not zero
- ; arrive here when delay counter is zero (total delay period is finished)
- ret
- ; ---------------------------------------------------------------------------
- ; Name: delay1mS -- Delay of 1 mS
- delay1mS:
- push YL ; [2] preserve registers
- push YH ; [2]
- ldi YL, low (((fclk/1000)-18)/4) ; [1] delay counter
- ldi YH, high(((fclk/1000)-18)/4) ; [1]
- delay1mS_01:
- sbiw YH:YL, 1 ; [2] update the the delay counter
- brne delay1mS_01 ; [2] delay counter is not zero
- ; arrive here when delay counter is zero
- pop YH ; [2] restore registers
- pop YL ; [2]
- ret
- ; ---------------------------------------------------------------------------
- ; Name: delayTx1uS Delay of (temp) x 1 uS with a 8 MHz clock frequency
- delayTx1uS:
- call delay1uS ; delay for 1 uS
- dec temp ; decrement the delay counter
- brne delayTx1uS ; counter is not zero
- ; arrive here when delay counter is zero (total delay period is finished)
- ret
- ; ---------------------------------------------------------------------------
- ; Name: delay1uS
- ; Purpose: Delay of 1 uS with a 8 MHz clock frequency
- delay1uS:
- push temp ; [2] Consume clock cycles
- pop temp ; [2]
- ret
- ; ============================== End of Time Delay Subroutines ==============
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement