Advertisement
Guest User

Untitled

a guest
Apr 19th, 2017
138
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. .INCLUDE "m128def.inc"
  2. ;==========================================================STUDENT DIRECTIVES====================================================
  3. .equ addresLineOne = 0x0100
  4. .equ addresLineTwo = 0x0200
  5. ;===================================================================MACROS==========================================================================
  6.  
  7. ;Macro operations to increase the readibility of the code and avoid repetition
  8. ;This is an operation for initializing Z register with an address where the data for LCD_Line_One is coming from
  9. .MACRO initZforLineOne
  10.     ldi ZH, high(addresLineOne)
  11.     ldi ZL, low(addresLineOne)
  12. .ENDMACRO
  13. ;This is an operation for initializing Z register with an address where the data for LCD_Line_Two is coming from
  14. .MACRO initZforLineTwo
  15.     ldi ZH, high(addresLineTwo)
  16.     ldi ZL, low(addresLineTwo)
  17. .ENDMACRO
  18. ;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
  19. ;It also includes a null character at the end of the string to ensure that printing operation will terminate
  20. .MACRO storeRegisterForLCD
  21.     ;convert the number to ascii and store in address text
  22.     ldi r17, '1'
  23.     sbrs @0, 7
  24.     ldi r17, '0'
  25.     st Z+, r17
  26.     ldi r17, '1'
  27.     sbrs @0, 6
  28.     ldi r17, '0'
  29.     st Z+, r17
  30.     ldi r17, '1'
  31.     sbrs @0, 5
  32.     ldi r17, '0'
  33.     st Z+, r17
  34.     ldi r17, '1'
  35.     sbrs @0, 4
  36.     ldi r17, '0'
  37.     st Z+, r17
  38.     ldi r17, '1'
  39.     sbrs @0, 3
  40.     ldi r17, '0'
  41.     st Z+, r17
  42.     ldi r17, '1'
  43.     sbrs @0, 2
  44.     ldi r17, '0'
  45.     st Z+, r17
  46.     ldi r17, '1'
  47.     sbrs @0, 1
  48.     ldi r17, '0'
  49.     st Z+, r17
  50.     ldi r17, '1'
  51.     sbrs @0, 0
  52.     ldi r17, '0'
  53.     st Z+, r17
  54.     call nullToZLast
  55. .ENDMACRO
  56. ;This is an operation for calculating the parity bit of first number which is coming from PIND.
  57. ;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
  58. .MACRO contParitywithStore
  59.     sbic pind, 0
  60.     inc @0
  61.     sbic pind, 1
  62.     inc @0
  63.     sbic pind, 2
  64.     inc @0
  65.     sbic pind, 3
  66.     inc @0
  67.     sbic pind, 4
  68.     inc @0
  69.     sbic pind, 5
  70.     inc @0
  71.     sbic pind, 6
  72.     inc @0
  73.     sbic pind, 7
  74.     inc @0
  75.  
  76.     ldi r17, '0'
  77.     SBRC @0, 0
  78.     ldi r17, '1'
  79.     st Z+, r17
  80.     call nullToZLast
  81. .ENDMACRO
  82. ;=============================================================LCD DIRECTIVES===================================================
  83. ;Majority of the directives come from LCD inferface yet there are two in the beginning of to code for address stored in Z register
  84. .equ fclk = 8000000 ; system clock frequency (for delays)
  85. ; register usage
  86. .def temp = R16 ; temporary storage
  87. ; LCD interface
  88. .equ lcd_D7_port = PORTC ; lcd D7 connection
  89. .equ lcd_D7_bit = PORTC7
  90. .equ lcd_D7_ddr = DDRC
  91. .equ lcd_D6_port = PORTC ; lcd D6 connection
  92. .equ lcd_D6_bit = PORTC6
  93. .equ lcd_D6_ddr = DDRC
  94. .equ lcd_D5_port = PORTC ; lcd D5 connection
  95. .equ lcd_D5_bit = PORTC5
  96. .equ lcd_D5_ddr = DDRC
  97. .equ lcd_D4_port = PORTC ; lcd D4 connection
  98. .equ lcd_D4_bit = PORTC4
  99. .equ lcd_D4_ddr = DDRC
  100. .equ lcd_E_port = PORTB ; lcd Enable pin
  101. .equ lcd_E_bit = PORTB5
  102. .equ lcd_E_ddr = DDRB
  103. .equ lcd_RS_port = PORTB ; lcd Register Select pin
  104. .equ lcd_RS_bit = PORTB2
  105. .equ lcd_RS_ddr = DDRB
  106. ; LCD module Lines
  107. .equ lcd_LineOne = 0x00 ; line 1
  108. .equ lcd_LineTwo = 0x40 ; line 2
  109. ; LCD Defined instructions
  110. .equ lcd_Clear = 0b00000001 ; ASCII 'space' for all characters
  111. .equ lcd_Home = 0b00000010 ; first position on first line
  112. .equ lcd_EntryMode = 0b00000110 ; shift cursor from left to right on read/write
  113. .equ lcd_DisplayOff = 0b00001000 ; turn display off
  114. .equ lcd_DisplayOn = 0b00001100 ; display on, cursor off, don't blink character
  115. .equ lcd_FunctionReset = 0b00110000 ; reset the LCD
  116. .equ lcd_FunctionSet4bit = 0b00101000 ; 4-bit data, 2-line display, 5 x 7 font
  117. .equ lcd_SetCursor = 0b10000000 ; set cursor position
  118.  
  119. ; ****************************** Reset Vector *******************************
  120. .org 0x0000
  121.  jmp start ; jump over Interrupt Vectors, Program ID etc.
  122. ;******************************* Program ID *********************************
  123. .org INT_VECTORS_SIZE
  124. ; ****************************** Main Program Code **************************
  125. start:
  126. ; initialize the stack pointer to the highest RAM address
  127.  ldi temp,low(RAMEND)
  128.  out SPL,temp
  129.  ldi temp,high(RAMEND)
  130.  out SPH,temp
  131. ; configure the microprocessor pins for the data lines
  132.  sbi lcd_D7_ddr, lcd_D7_bit ; 4 data lines - output
  133.  sbi lcd_D6_ddr, lcd_D6_bit
  134.  sbi lcd_D5_ddr, lcd_D5_bit
  135.  sbi lcd_D4_ddr, lcd_D4_bit
  136. ; configure the microprocessor pins for the control lines
  137.  sbi lcd_E_ddr, lcd_E_bit ; E line - output
  138.  sbi lcd_RS_ddr, lcd_RS_bit ; RS line - output
  139. ; initialize the LCD controller
  140.  call lcd_init_4d ; initialize the LCD display for a 4-bit interface
  141.  
  142.  ldi r20, 0x00
  143.  out ddra, r20
  144.  out ddrd, r20
  145.  out ddre, r20
  146.  jmp READ
  147.  
  148. READ: ;start of each capture iteration
  149.     call clearLcdMemoryAddresses
  150.     in r20, pind
  151.     in r17, pine
  152.     in R21, pina
  153.     andi R21,0x03
  154.     CPI R21,0x00
  155.     BREQ PROCESS_ZERO
  156.     CPI R21,0x01
  157.     BREQ PROCESS_ONE
  158.     CPI R21,0x10
  159.     BREQ PROCESS_TWO
  160.     CPI R21,0x11
  161.     BREQ PROCESS_THREE
  162.  
  163. PROCESS_ZERO:
  164.     CALL mode00
  165.     jmp printToLCD
  166.     JMP READ
  167. PROCESS_ONE:
  168.     CALL mode01
  169.     jmp printToLCD
  170.     JMP READ
  171. PROCESS_TWO:
  172.     ;CALL mode00
  173.     JMP READ
  174. PROCESS_THREE:
  175.     ;CALL mode00
  176.     JMP READ
  177.  
  178. mode01: ;print first number and an even parity bit
  179.     initZforLineOne
  180.     storeRegisterForLCD r20
  181.  
  182.     ldi r18, 0; some odd number
  183.     contParitywithStore r18
  184.     call nullToZLast
  185.    
  186.     jmp printToLcd
  187.  
  188. mode00: ;print first number and an odd parity bit
  189.     initZforLineOne
  190.     storeRegisterForLCD r20
  191.  
  192.     ldi r18, 1;some even number
  193.     contParitywithStore r18
  194.     call nullToZLast
  195.    
  196.     jmp printToLcd
  197. mode11:
  198.     mov r18, r17
  199.     sub r17, r20
  200.     brmi logicisfalse
  201.     mov r18, r17
  202.     call printHex
  203.     initZforLineOne
  204.     storeRegisterForLCD r18
  205.     jmp printToLcd
  206.     logicisfalse:
  207.         sub r20, r18
  208.         mov r18, r20
  209.         call printHex
  210.         initZforLineOne
  211.         storeRegisterForLCD r18
  212.         jmp printToLcd
  213.  
  214. mode10:
  215.     mov r18, r17
  216.     sub r18, r20
  217.     breq equal
  218.     mov r18, r17
  219.     sub r18, r20
  220.     brmi less      
  221.         mov r18, r17
  222.         call printHex
  223.         jmp printToLcd
  224.     equal:
  225.         initZforLineTwo
  226.         ldi r19, 'E'
  227.         st Z+, r19
  228.         ldi r19, 'Q'
  229.         st Z+, r19
  230.         jmp printToLcd
  231.     less:
  232.         mov r18, r20
  233.         call printHex
  234.         jmp printToLcd
  235.  
  236. ;====================================================================STUDENT WRITTEN FUNCTIONS====================================================
  237. printHex:
  238.     initZforLineTwo
  239.     mov r19, r18
  240.     swap r19
  241.     andi r19, 0x0F
  242.     cpi r19, 0x0A
  243.     brlt lessThanAR
  244.     subi r19, 9
  245.     ori r19, 0x40
  246.     st Z+, r19
  247.     jmp secondHex
  248.     lessThanAR:
  249.     ori r19,0x30
  250.     st Z+, r19
  251.     secondHex:
  252.     mov r19, r18
  253.     andi r19, 0x0F
  254.     cpi r19, 0x0A
  255.     brlt lessThanAL
  256.     subi r19, 9
  257.     ori r19, 0x40
  258.     st Z+, r19
  259.     ret
  260.     lessThanAL:
  261.     ori r19,0x30
  262.     st Z+, r19
  263.     ret
  264.  
  265.  
  266.  
  267. printToLcd:
  268. in R16, PINB;
  269. ; display the first line of information
  270.  ldi ZH, high(addresLineOne) ; point to the information that is to be displayed
  271.  ldi ZL, low(addresLineOne)
  272. ldi temp, lcd_LineOne ; point to where the information should be displayed
  273. call lcd_write_string_4d
  274. ; display the second line of information
  275.  ldi ZH, high(addresLineTwo) ; point to the information that is to be displayed
  276.  ldi ZL, low(addresLineTwo)
  277. ldi temp, lcd_LineTwo ; point to where the information should be displayed
  278. call lcd_write_string_4d
  279.  
  280. rjmp READ
  281.  nullToZLast:
  282.     ldi r17, 0x00
  283.     st Z, r17
  284.     ret
  285.  
  286. fillZWithEmptySpaces:
  287.     ldi r17, lcd_Clear
  288.     st Z+, r17
  289.     st Z+, r17
  290.     st Z+, r17
  291.     st Z+, r17
  292.     st Z+, r17
  293.     st Z+, r17
  294.     st Z+, r17
  295.     st Z+, r17
  296.     st Z+, r17
  297.     st Z+, r17
  298.     st Z+, r17
  299.     st Z+, r17
  300.     st Z+, r17
  301.     st Z+, r17
  302.     st Z+, r17
  303.     st Z+, r17
  304.     st Z+, r17
  305.     call nullToZLast
  306.     ret
  307.  
  308. clearLcdMemoryAddresses:
  309.     initZforLineOne
  310.     call fillZWithEmptySpaces
  311.    
  312.     initZforLineTwo
  313.     call fillZWithEmptySpaces
  314.     ret
  315. ; ****************************** End of Main Program Code *******************
  316.  
  317.  
  318.  
  319.  
  320. ; ****************************** LCD Code **************************
  321. initializeLCD:
  322. ; initialize the stack pointer to the highest RAM address
  323.     ldi temp,low(RAMEND)
  324.     out SPL,temp
  325.     ldi temp,high(RAMEND)
  326.     out SPH,temp
  327.  
  328. ; configure the microprocessor pins for the data lines
  329.     sbi lcd_D7_ddr, lcd_D7_bit ; 4 data lines - output
  330.     sbi lcd_D6_ddr, lcd_D6_bit
  331.     sbi lcd_D5_ddr, lcd_D5_bit
  332.     sbi lcd_D4_ddr, lcd_D4_bit
  333.  
  334. ; configure the microprocessor pins for the control lines
  335.     sbi lcd_E_ddr, lcd_E_bit ; E line - output
  336.     sbi lcd_RS_ddr, lcd_RS_bit ; RS line - output
  337.  
  338. ; initialize the LCD controller
  339.     call lcd_init_4d ; initialize the LCD display for a 4-bit interface
  340.  
  341.     jmp start
  342.  
  343.  
  344.  
  345. ; ============================== 4-bit LCD Function Calls ======================
  346. ; Name: lcd_init_4d -- initialize the LCD module for a 4-bit data interface
  347.  
  348. lcd_init_4d:
  349. ; Power-up delay
  350.     ldi temp, 100 ; initial 40 mSec delay
  351.     call delayTx1mS
  352.  
  353. ; IMPORTANT - At this point the LCD module is in the 8-bit mode and it is expecting to receive
  354. ; 8 bits of data, one bit on each of its 8 data lines, each time the 'E' line is pulsed.
  355. ;
  356. ; Since the LCD module is wired for the 4-bit mode, only the upper four data lines are connected to
  357. ; the microprocessor and the lower four data lines are typically left open. Therefore, when
  358. ; the 'E' line is pulsed, the LCD controller will read whatever data has been set up on the upper
  359. ; four data lines and the lower four data lines will be high (due to internal pull-up circuitry).
  360. ;
  361. ; Fortunately the 'FunctionReset' instruction does not care about what is on the lower four bits so
  362. ; this instruction can be sent on just the four available data lines and it will be interpreted
  363. ; properly by the LCD controller. The 'lcd_write_4' subroutine will accomplish this if the
  364. ; control lines have previously been configured properly.
  365.  
  366. ; Set up the RS and E lines for the 'lcd_write_4' subroutine.
  367.     cbi lcd_RS_port, lcd_RS_bit ; select the Instruction Register (RS low)
  368.     cbi lcd_E_port, lcd_E_bit ; make sure E is initially low
  369.  
  370. ; Reset the LCD controller.
  371.     ldi temp, lcd_FunctionReset ; first part of reset sequence
  372.     call lcd_write_4
  373.     ldi temp, 10 ; 4.1 mS delay (min)
  374.     call delayTx1mS
  375.  
  376.     ldi temp, lcd_FunctionReset ; second part of reset sequence
  377.     call lcd_write_4
  378.     ldi temp, 200 ; 100 uS delay (min)
  379.     call delayTx1uS
  380.  
  381.     ldi temp, lcd_FunctionReset ; third part of reset sequence
  382.     call lcd_write_4
  383.     ldi temp, 200 ; this delay is omitted in the data sheet call
  384.     call delayTx1uS
  385.  
  386. ; Preliminary Function Set instruction - used only to set the 4-bit mode.
  387. ; The number of lines or the font cannot be set at this time since the controller is still in the
  388. ; 8-bit mode, but the data transfer mode can be changed since this parameter is determined by one
  389. ; of the upper four bits of the instruction.
  390.  
  391.     ldi temp, lcd_FunctionSet4bit ; set 4-bit mode
  392.     call lcd_write_4
  393.     ldi temp, 80 ; 40 uS delay (min)
  394.     call delayTx1uS
  395.  
  396. ; Function Set instruction
  397.     ldi temp, lcd_FunctionSet4bit ; set mode, lines, and font
  398.     call lcd_write_instruction_4d
  399.     ldi temp, 80 ; 40 uS delay (min)
  400.     call delayTx1uS
  401.  
  402. ; The next three instructions are specified in the data sheet as part of the initialization routine,
  403. ; so it is a good idea (but probably not necessary) to do them just as specified and then redo them
  404. ; later if the application requires a different configuration.
  405.  
  406. ; Display On/Off Control instruction
  407.     ldi temp, lcd_DisplayOff ; turn display OFF
  408.     call lcd_write_instruction_4d
  409.     ldi temp, 80 ; 40 uS delay (min)
  410.     call delayTx1uS
  411.  
  412. ; Clear Display instruction
  413.     ldi temp, lcd_Clear ; clear display RAM
  414.     call lcd_write_instruction_4d
  415.     ldi temp, 4 ; 1.64 mS delay (min)
  416.     call delayTx1mS
  417.  
  418. ; Entry Mode Set instruction
  419.     ldi temp, lcd_EntryMode ; set desired shift characteristics
  420.     call lcd_write_instruction_4d
  421.     ldi temp, 80 ; 40 uS delay (min)
  422.     call delayTx1uS
  423.  
  424. ; This is the end of the LCD controller initialization as specified in the data sheet, but the display
  425. ; has been left in the OFF condition. This is a good time to turn the display back ON.
  426.  
  427. ; Display On/Off Control instruction
  428.     ldi temp, lcd_DisplayOn ; turn the display ON
  429.     call lcd_write_instruction_4d
  430.     ldi temp, 80 ; 40 uS delay (min)
  431.     call delayTx1uS
  432.     ret
  433.  
  434. ; ---------------------------------------------------------------------------
  435. ; Name: lcd_write_string_4d ; Purpose: display a string of characters on the LCD
  436. ; Entry: ZH and ZL pointing to the start of the string
  437. ; (temp) contains the desired DDRAM address at which to start the display
  438. ; Exit: no parameters
  439. ; Notes: the string must end with a null (0)
  440. ; uses time delays instead of checking the busy flag
  441.  
  442. lcd_write_string_4d:
  443. ; preserve registers
  444.     push ZH ; preserve pointer registers
  445.     push ZL
  446.  
  447. ; set up the initial DDRAM address
  448.     ori temp, lcd_SetCursor ; convert the plain address to a set cursor instruction
  449.     call lcd_write_instruction_4d ; set up the first DDRAM address
  450.     ldi temp, 80
  451.     call delayTx1uS
  452.  
  453. ; write the string of characters
  454. lcd_write_string_4d_01:
  455.     ld temp, Z+ ; get a character
  456.     cpi temp, 0 ; check for end of string
  457.     breq lcd_write_string_4d_02 ; done
  458.  
  459. ; arrive here if this is a valid character
  460.     call lcd_write_character_4d ; display the character
  461.     ldi temp, 80
  462.     call delayTx1uS
  463.     rjmp lcd_write_string_4d_01 ; not done, send another character
  464.  
  465. ; arrive here when all characters in the message have been sent to the LCD module
  466. lcd_write_string_4d_02:
  467.     pop ZL ; restore pointer registers
  468.     pop ZH
  469.     ret
  470.  
  471. ; ---------------------------------------------------------------------------
  472. ; Name: lcd_write_character_4d
  473. ; Purpose: send a byte of information to the LCD data register
  474. ; Entry: (temp) contains the data byte ; Exit: no parameters
  475. ; Notes: does not deal with RW (busy flag is not implemented)
  476.  
  477. lcd_write_character_4d:
  478.     sbi lcd_RS_port, lcd_RS_bit ; select the Data Register (RS high)
  479.     cbi lcd_E_port, lcd_E_bit ; make sure E is initially low
  480.     call lcd_write_4 ; write the upper 4-bits of the data
  481.     swap temp ; swap high and low nibbles
  482.     call lcd_write_4 ; write the lower 4-bits of the data
  483.     ret
  484.  
  485. ; ---------------------------------------------------------------------------
  486. ; Name: lcd_write_instruction_4d -- Send a byte of information to the LCD instruction register
  487. lcd_write_instruction_4d:
  488.     cbi lcd_RS_port, lcd_RS_bit ; select the Instruction Register (RS low)
  489.     cbi lcd_E_port, lcd_E_bit ; make sure E is initially low
  490.     call lcd_write_4 ; write the upper 4-bits of the instruction
  491.     swap temp ; swap high and low nibbles
  492.     call lcd_write_4 ; write the lower 4-bits of the instruction
  493.     ret
  494.  
  495. ; ---------------------------------------------------------------------------
  496. ; Name: lcd_write_4 Send 4-bits of information to the LCD module
  497. ; Entry: (temp) contains a byte of data with the desired 4-bits in the upper nibble
  498. ; (RS) is configured for the desired LCD register
  499. ; (E) is low
  500. ; (RW) is low
  501. lcd_write_4:
  502. ; set up D7
  503.     sbi lcd_D7_port, lcd_D7_bit ; assume that the D7 data is '1'
  504.     sbrs temp, 7 ; check the actual data value
  505.     cbi lcd_D7_port, lcd_D7_bit ; arrive here only if the data was actually '0'
  506.  
  507. ; set up D6
  508.     sbi lcd_D6_port, lcd_D6_bit ; repeat for each data bit
  509.     sbrs temp, 6
  510.     cbi lcd_D6_port, lcd_D6_bit
  511.  
  512. ; set up D5
  513.     sbi lcd_D5_port, lcd_D5_bit
  514.     sbrs temp, 5
  515.     cbi lcd_D5_port, lcd_D5_bit
  516.  
  517. ; set up D4
  518.     sbi lcd_D4_port, lcd_D4_bit
  519.     sbrs temp, 4
  520.     cbi lcd_D4_port, lcd_D4_bit
  521.  
  522. ; write the data
  523. ; 'Address set-up time' (40 nS)
  524.     sbi lcd_E_port, lcd_E_bit ; Enable pin high
  525.     call delay1uS ; implement 'Data set-up time' (80 nS) and 'Enable pulse width' (230 nS)
  526.     cbi lcd_E_port, lcd_E_bit ; Enable pin low
  527.     call delay1uS ; implement 'Data hold time' (10 nS) and 'Enable cycle time' (500 nS)
  528.     ret
  529.  
  530. ; ============================== End of 4-bit LCD Subroutines ===============
  531.  
  532. ; ============================== Time Delay Subroutines =====================
  533. ; Name: delayYx1mS Delay of (YH:YL) x 1 mS
  534.  
  535. delayYx1mS:
  536.     call delay1mS ; delay for 1 mS
  537.     sbiw YH:YL, 1 ; update the the delay counter
  538.     brne delayYx1mS ; counter is not zero
  539.  
  540. ; arrive here when delay counter is zero (total delay period is finished)
  541.     ret
  542.  
  543. ; ---------------------------------------------------------------------------
  544. ; Name: delayTx1mS Provide a delay of (temp) x 1 mS
  545. delayTx1mS:
  546.     call delay1mS ; delay for 1 mS
  547.     dec temp ; update the delay counter
  548.     brne delayTx1mS ; counter is not zero
  549.  
  550. ; arrive here when delay counter is zero (total delay period is finished)
  551.     ret
  552.  
  553. ; ---------------------------------------------------------------------------
  554. ; Name: delay1mS -- Delay of 1 mS
  555. delay1mS:
  556.     push YL ; [2] preserve registers
  557.     push YH ; [2]
  558.     ldi YL, low (((fclk/1000)-18)/4) ; [1] delay counter
  559.     ldi YH, high(((fclk/1000)-18)/4) ; [1]
  560.  
  561. delay1mS_01:
  562.     sbiw YH:YL, 1 ; [2] update the the delay counter
  563.     brne delay1mS_01 ; [2] delay counter is not zero
  564. ; arrive here when delay counter is zero
  565.     pop YH ; [2] restore registers
  566.     pop YL ; [2]
  567.     ret
  568. ; ---------------------------------------------------------------------------
  569. ; Name: delayTx1uS Delay of (temp) x 1 uS with a 8 MHz clock frequency
  570. delayTx1uS:
  571.     call delay1uS ; delay for 1 uS
  572.     dec temp ; decrement the delay counter
  573.     brne delayTx1uS ; counter is not zero
  574. ; arrive here when delay counter is zero (total delay period is finished)
  575.     ret
  576. ; ---------------------------------------------------------------------------
  577. ; Name: delay1uS
  578. ; Purpose: Delay of 1 uS with a 8 MHz clock frequency
  579. delay1uS:
  580.     push temp ; [2] Consume clock cycles
  581.     pop temp ; [2]
  582.     ret
  583. ; ============================== End of Time Delay Subroutines ==============
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement