bladabuska

lcd8d.asm

Apr 29th, 2016
89
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ; ------------------------------------------------------------------------------
  2. ; Project:  16x2 Character Liquid Crystal Display Controller
  3. ; File:     lcd8d.asm
  4. ; Author:   Leandro Schwarz
  5. ; Created:  2015-11-02
  6. ; Modified: 2015-11-02
  7. ; Version:  1.0
  8. ; Notes:    LCD controller, 8 bits interface, delay driven (no busy flag)
  9. ; ------------------------------------------------------------------------------
  10.  
  11. ; ------------------------------------------------------------------------------
  12. ; Include files
  13. ; ------------------------------------------------------------------------------
  14. .include "m328pdef.inc"
  15.  
  16. ; ------------------------------------------------------------------------------
  17. ; Register definitions
  18. ; ------------------------------------------------------------------------------
  19. .def    bcd0                = R13       ; BCD value digits 1 and 0
  20. .def    bcd1                = R14       ; BCD value digits 3 and 2
  21. .def    bcd2                = R15       ; BCD value digit 4
  22. .def    binL                = R16       ; binary value Low byte
  23. .def    binH                = R17       ; binary value High byte
  24. .def    bin2BCDcounter      = R18       ; loop counter
  25. .def    bin2BCDtemp         = R19       ; temporary value
  26. .def    lcdTmp              = R20       ; LCD temporary register
  27.  
  28. ; ------------------------------------------------------------------------------
  29. ; Constant definitions
  30. ; ------------------------------------------------------------------------------
  31. .equ    LCD_DATA_DDR        = DDRD          ; LCD data lines
  32. .equ    LCD_DATA_PORT       = PORTD
  33. .equ    LCD_CONTROL_DDR     = DDRB          ; LCD control lines
  34. .equ    LCD_CONTROL_PORT    = PORTB
  35. .equ    LCD_CONTROL_E       = PB0
  36. .equ    LCD_CONTROL_RS      = PB1
  37. .equ    LCD_FIRST_LINE      = 0x00          ; LCD DDRAM address
  38. .equ    LCD_SECOND_LINE     = 0x40
  39. .equ    LCD_CLEAR_SCREEN    = 0x01          ; LCD commands
  40. .equ    LCD_CURSOR_HOME     = 0x02
  41. .equ    LCD_ENTRY_MODE      = 0x06
  42. .equ    LCD_DISPLAY_OFF     = 0x08
  43. .equ    LCD_DISPLAY_ON      = 0x0C
  44. .equ    LCD_RESET           = 0x30
  45. .equ    LCD_FUNCTION_SET_8  = 0x38
  46. .equ    LCD_CURSOR_MOVE     = 0x80
  47. .equ    AtBCD0              = 13        ; address of bcd0
  48. .equ    AtBCD2              = 15        ; address of bcd1
  49.  
  50. ; ------------------------------------------------------------------------------
  51. ; Subroutine:   lcdInit
  52. ; Purpose:      initialize the LCD module using 8 data lines and delays
  53. ; Notes:        no register is changed
  54. ; ------------------------------------------------------------------------------
  55. lcdInit:
  56.     PUSH    lcdTmp                          ; Pushing registers
  57.     LDI     lcdTmp, 0x00                    ; I/O configuration
  58.     OUT     LCD_DATA_PORT, lcdTmp
  59.     LDI     lcdTmp, 0xFF
  60.     OUT     LCD_DATA_DDR, lcdTmp
  61.     CBI     LCD_CONTROL_PORT, LCD_CONTROL_E
  62.     SBI     LCD_CONTROL_DDR, LCD_CONTROL_E
  63.     CBI     LCD_CONTROL_PORT, LCD_CONTROL_RS
  64.     SBI     LCD_CONTROL_DDR, LCD_CONTROL_RS
  65.     LDI     lcdTmp, LCD_RESET               ; Reset the LCD controller.
  66.     CALL    lcdWriteCommand
  67.     LDI     lcdTmp, 5
  68.     CALL    lcdDelayXms
  69.     LDI     lcdTmp, LCD_RESET
  70.     CALL    lcdWriteCommand
  71.     LDI     lcdTmp, 100
  72.     CALL    lcdDelayXus
  73.     LDI     lcdTmp, LCD_RESET
  74.     CALL    lcdWriteCommand
  75.     LDI     lcdTmp, 200
  76.     CALL    lcdDelayXus
  77.     LDI     lcdTmp, LCD_FUNCTION_SET_8      ; LCD function mode set
  78.     CALL    lcdWriteCommand
  79.     LDI     lcdTmp, 40
  80.     CALL    lcdDelayXus
  81.     LDI     lcdTmp, LCD_DISPLAY_OFF         ; Turns display off
  82.     CALL    lcdWriteCommand
  83.     LDI     lcdTmp, 40
  84.     CALL    lcdDelayXus
  85.     LDI     lcdTmp, LCD_CLEAR_SCREEN        ; Clears LCD screen
  86.     CALL    lcdWriteCommand
  87.     LDI     lcdTmp, 2
  88.     CALL    lcdDelayXms
  89.     LDI     lcdTmp, LCD_ENTRY_MODE          ; LCD entry mode set
  90.     CALL    lcdWriteCommand
  91.     LDI     lcdTmp, 40
  92.     CALL    lcdDelayXus
  93.     LDI     lcdTmp, LCD_DISPLAY_ON          ; Turns display on
  94.     CALL    lcdWriteCommand
  95.     LDI     lcdTmp, 40
  96.     CALL    lcdDelayXus
  97.     POP     lcdTmp                          ; Popping registers back
  98.     RET
  99.  
  100. ; ------------------------------------------------------------------------------
  101. ; Subroutine:   lcdWriteData
  102. ; Purpose:      writes a data byte at the LCD
  103. ; Notes:        the data byte must be written in lcdTmp before calling the
  104. ;               subroutine
  105. ; ------------------------------------------------------------------------------
  106. lcdWriteData:
  107.     SBI     LCD_CONTROL_PORT, LCD_CONTROL_RS
  108.     CBI     LCD_CONTROL_PORT, LCD_CONTROL_E
  109.     OUT     LCD_DATA_PORT, lcdTmp
  110.     SBI     LCD_CONTROL_PORT, LCD_CONTROL_E
  111.     CALL    lcdDelay1us
  112.     CBI     LCD_CONTROL_PORT, LCD_CONTROL_E
  113.     CALL    lcdDelay1us
  114.     RET
  115.  
  116. ; ------------------------------------------------------------------------------
  117. ; Subroutine:   lcdWriteCommand
  118. ; Purpose:      writes a command byte at the LCD
  119. ; Notes:        the command byte must be written in lcdTmp before calling the
  120. ;               subroutine
  121. ; ------------------------------------------------------------------------------
  122. lcdWriteCommand:
  123.     CBI     LCD_CONTROL_PORT, LCD_CONTROL_RS
  124.     CBI     LCD_CONTROL_PORT, LCD_CONTROL_E
  125.     OUT     LCD_DATA_PORT, lcdTmp
  126.     SBI     LCD_CONTROL_PORT, LCD_CONTROL_E
  127.     CALL    lcdDelay1us
  128.     CBI     LCD_CONTROL_PORT, LCD_CONTROL_E
  129.     CALL    lcdDelay1us
  130.     RET
  131.  
  132. ; ------------------------------------------------------------------------------
  133. ; Subroutine:   lcdWriteString
  134. ; Purpose:      writes a string at the LCD
  135. ; Notes:        the string address must be loaded into the Z register and the
  136. ;               DDRAM address must be loaded into lcdTmp register before calling
  137. ;               the subroutine. The string must end with a NULL character 0
  138. ; ------------------------------------------------------------------------------
  139. lcdWriteString:
  140.     PUSH    ZH                              ; Pushing registers
  141.     PUSH    ZL
  142.     LSL     ZL                              ; shift the pointer one bit left for the lpm instruction
  143.     ROL     ZH
  144.     ORI     lcdTmp, LCD_CURSOR_MOVE         ; Configures the DDRAM address
  145.     CALL    lcdWriteCommand
  146.     LDI     lcdTmp, 40
  147.     CALL    lcdDelayXus
  148. lcdWriteStringLoop:                         ; Write string
  149.     LPM     lcdTmp, Z+
  150.     CPI     lcdTmp, 0
  151.     BREQ    lcdWriteStringEnd
  152.     CALL    lcdWriteData
  153.     LDI     lcdTmp, 40
  154.     CALL    lcdDelayXus
  155.     JMP     lcdWriteStringLoop
  156. lcdWriteStringEnd:
  157.     POP     ZL                              ; Popping registers back
  158.     POP     ZH
  159.     RET
  160.  
  161. ; ------------------------------------------------------------------------------
  162. ; Subroutine:   lcdWriteInt16
  163. ; Purpose:      writes a 16 bit integer at the LCD
  164. ; Notes:        the number must be loaded into lcdTemp register before calling
  165. ;               the subroutine
  166. ; ------------------------------------------------------------------------------
  167. lcdWriteInt16:
  168.     MOV     lcdTmp, bcd2                    ; BCD Digit 4
  169.     ANDI    lcdTmp, 0x0F
  170.     CALL    lcdWriteNumber
  171.     MOV     lcdTmp, bcd1                    ; BCD Digit 3
  172.     LSR lcdTmp
  173.     LSR lcdTmp
  174.     LSR lcdTmp
  175.     LSR lcdTmp
  176.     ANDI    lcdTmp, 0x0F
  177.     CALL    lcdWriteNumber
  178.     MOV     lcdTmp, bcd1                    ; BCD Digit 2
  179.     ANDI    lcdTmp, 0x0F
  180.     CALL    lcdWriteNumber
  181.     MOV     lcdTmp, bcd0                    ; BCD Digit 1
  182.     LSR lcdTmp
  183.     LSR lcdTmp
  184.     LSR lcdTmp
  185.     LSR lcdTmp
  186.     ANDI    lcdTmp, 0x0F
  187.     CALL    lcdWriteNumber
  188.     MOV     lcdTmp, bcd0                    ; BCD Digit 0
  189.     ANDI    lcdTmp, 0x0F
  190.     CALL    lcdWriteNumber
  191.     RET
  192.  
  193. ; ------------------------------------------------------------------------------
  194. ; Subroutine:   lcdWriteNumber
  195. ; Purpose:      writes a number at the LCD
  196. ; Notes:        the number must be loaded into lcdTemp register before calling
  197. ;               the subroutine
  198. ; ------------------------------------------------------------------------------
  199. lcdWriteNumber:
  200.     PUSH    R19                             ; Pushing registers
  201.     ANDI    lcdTmp, 0x0F
  202.     LDI     R19, 0x30
  203.     ADD     lcdTmp, R19
  204.     CALL    lcdWriteData
  205.     LDI     lcdTmp, 40
  206.     CALL    lcdDelayXus
  207.     POP     R19                             ; Popping registers back
  208.     RET
  209.  
  210. ; ------------------------------------------------------------------------------
  211. ; Subroutine:   lcdSetDdramAddress
  212. ; Purpose:      sets the LCD DDRAM address
  213. ; Notes:        the address must be loaded into lcdTemp register before calling
  214. ;               the subroutine
  215. ; ------------------------------------------------------------------------------
  216. lcdSetDdramAddress:
  217.     ORI     lcdTmp, LCD_CURSOR_MOVE
  218.     CALL    lcdWriteCommand
  219.     LDI     lcdTmp, 40
  220.     CALL    lcdDelayXus
  221.     RET
  222.  
  223.     ; ------------------------------------------------------------------------------
  224. ; Subroutine:   lcdClearScreen
  225. ; Purpose:      clears the LCD screen
  226. ; Notes:        no register is changed
  227. ; ------------------------------------------------------------------------------
  228. lcdClearScreen:
  229.     PUSH    lcdTmp
  230.     LDI     lcdTmp, LCD_CLEAR_SCREEN        ; Clears LCD screen
  231.     CALL    lcdWriteCommand
  232.     LDI     lcdTmp, 2
  233.     CALL    lcdDelayXms
  234.     POP     lcdTmp
  235.     RET
  236.  
  237. ; ------------------------------------------------------------------------------
  238. ; Subroutine:   lcdDelayXms
  239. ; Purpose:      generate a variable delay duration loop in milliseconds
  240. ; Notes:        makes successive calls of function lcdDelay1ms using lcdTmp as
  241. ;               counter variable
  242. ; ------------------------------------------------------------------------------
  243. lcdDelayXms:
  244.     CALL    lcdDelay1ms
  245.     DEC     lcdTmp
  246.     BRNE    lcdDelayXms
  247.     RET
  248.  
  249. ; ------------------------------------------------------------------------------
  250. ; Subroutine:   lcdDelayXus
  251. ; Purpose:      generate a variable delay duration loop in microseconds
  252. ; Notes:        makes successive calls of function lcdDelay1us using lcdTmp as
  253. ;               counter variable
  254. ; ------------------------------------------------------------------------------
  255. lcdDelayXus:
  256.     CALL    lcdDelay1us
  257.     DEC     lcdTmp
  258.     BRNE    lcdDelayXus
  259.     RET
  260.  
  261. ; ------------------------------------------------------------------------------
  262. ; Subroutine:   lcdDelay1ms
  263. ; Purpose:      1ms delay in 16MHz
  264. ; Notes:        no register is changed
  265. ; ------------------------------------------------------------------------------
  266. lcdDelay1ms:
  267.     PUSH    R18
  268.     PUSH    R19
  269.     LDI     R18, 21
  270.     LDI     R19, 193
  271. lcdDelay1msLoop:
  272.     DEC     R19
  273.     BRNE    lcdDelay1msLoop
  274.     DEC     R18
  275.     BRNE    lcdDelay1msLoop
  276.     POP     R19
  277.     POP     R18
  278.     NOP
  279.     NOP
  280.     RET
  281.  
  282. ; ------------------------------------------------------------------------------
  283. ; Subroutine:   lcdDelay1us
  284. ; Purpose:      1us delay in 16MHz
  285. ; Notes:        no register is changed
  286. ; ------------------------------------------------------------------------------
  287. lcdDelay1us:
  288.     PUSH    lcdTmp
  289.     POP     lcdTmp
  290.     PUSH    lcdTmp
  291.     POP     lcdTmp
  292.     RET
  293.  
  294. ; ------------------------------------------------------------------------------
  295. ; Subroutine:   bin2BCD16
  296. ; Purpose:      converts a 16-bit Binary to 3 bytes BCD (6 nibbles)
  297. ; Notes:        the binary number must be loaded into (binH:binL) and the result
  298. ;               is stored into (bcd2:bcd1:bcd0), with the MSD of the BCD code in
  299. ;               the lowermost nibble of bcd2.
  300. ; ------------------------------------------------------------------------------
  301. bin2BCD16:
  302.     PUSH    bin2BCDcounter
  303.     PUSH    bin2BCDtemp
  304.     PUSH    ZH
  305.     PUSH    ZL
  306.     LDI     bin2BCDcounter, 16              ; Initializes loop counter
  307.     CLR     bcd2                            ; Clear result registers
  308.     CLR     bcd1
  309.     CLR     bcd0
  310.     CLR     ZH
  311. bBCDx_1:
  312.     LSL     binL                            ; shift input value
  313.     ROL     binH                            ; through all bytes
  314.     ROL     bcd0                            ;
  315.     ROL     bcd1
  316.     ROL     bcd2
  317.     DEC     bin2BCDcounter                  ; decrement loop counter
  318.     BRNE    bBCDx_2                         ; if counter not zero
  319.     POP     ZL
  320.     POP     ZH
  321.     POP     bin2BCDtemp
  322.     POP     bin2BCDcounter
  323.     RET                                     ; return
  324. bBCDx_2:
  325.     LDI     R30, AtBCD2+1                   ; Z points to result MSB + 1
  326. bBCDx_3:
  327.     LD      bin2BCDtemp, -Z                 ; get (Z) with pre-decrement
  328.     SUBI    bin2BCDtemp, -$03               ; add 0x03
  329.     SBRC    bin2BCDtemp, 3                  ; if bit 3 not clear
  330.     ST      Z, bin2BCDtemp                  ; store back
  331.     LD      bin2BCDtemp, Z                  ; get (Z)
  332.     SUBI    bin2BCDtemp, -$30               ; add 0x30
  333.     SBRC    bin2BCDtemp, 7                  ; if bit 7 not clear
  334.     ST      Z, bin2BCDtemp                  ; store back
  335.     CPI     ZL, AtBCD0                      ; done all three?
  336.     BRNE    bBCDx_3                         ; loop again if not
  337.     RJMP    bBCDx_1
Advertisement
Add Comment
Please, Sign In to add comment