;---====================== Start Software License ======================--- ;--== ==-- ;--== This license governs the use of this software, and your use of ==-- ;--== this software constitutes acceptance of this license. Agreement ==-- ;--== with all points is required to use this software. ==-- ;--== ==-- ;--== 1. You may use this software freely for personal use. ==-- ;--== ==-- ;--== 2. You may use this software freely to determine feasibility for ==-- ;--== commercial use. ==-- ;--== ==-- ;--== 3. You may use this software for commercial use if the author ==-- ;--== has given you written consent. ==-- ;--== ==-- ;--== 4. You may modify this software provided you do not remove the ==-- ;--== license and copyright notice. ==-- ;--== ==-- ;--== 5. You may distribute this software and derivative works to ==-- ;--== personal friends and work colleagues only. ==-- ;--== ==-- ;--== 6. You agree that this software comes “as-is” and with no ==-- ;--== warranty whatsoever, either expressed or implied, including, ==-- ;--== but not limited to, warranties of merchantability or fitness ==-- ;--== for a particular purpose. ==-- ;--== ==-- ;--== 7. You agree that the author will not be liable for any damages ==-- ;--== relating from the use of this software, including direct, ==-- ;--== indirect, consequential or incidental. This software is used ==-- ;--== entirely at your own risk and should it prove defective, you ==-- ;--== will assume full responsibility for all costs associated with ==-- ;--== servicing, repair or correction. ==-- ;--== ==-- ;--== Your rights under this license are terminated immediately if you ==-- ;--== breach it in any way. ==-- ;--== ==-- ;---======================= End Software License =======================--- ;---====================== Start Copyright Notice ======================--- ;--== ==-- ;--== Filename ..... asm_4bit_lcd.txt ==-- ;--== Download ..... http://www.spacewire.co.uk ==-- ;--== Author ....... Steve Haywood (steve.haywood@ukonline.co.uk) ==-- ;--== Copyright .... Copyright (c) 2004 Steve Haywood ==-- ;--== Project ...... Raptor-16 ==-- ;--== Version ...... 1.00 ==-- ;--== Conception ... 27 July 2004 ==-- ;--== Modified ..... N/A ==-- ;--== ==-- ;---======================= End Copyright Notice =======================--- ;---========================= Start Description ========================--- ;--== ==-- ;--== This code demonstrates how to display a moving string of text on ==-- ;--== a 20x4 LCD Display. The text moves around the outside of the LCD ==-- ;--== display, firsty going from left to right across the top, then ==-- ;--== top to bottom on the right edge, then right to left across the ==-- ;--== bottom line and finally bottom to top on the left edge. This ==-- ;--== sequence is then repeated indefinately. ==-- ;--== ==-- ;--== The source should work with any LCD that uses the HD44780 and ==-- ;--== be easily changed to get the moving text on any LCD module. ==-- ;--== ==-- ;--== Tested on a Powertip PC 2004A with the following wiring:- ==-- ;--== ==-- ;--== lcd_rs ..... Port 0 Bit 0 ==-- ;--== lcd_en ..... Port 0 Bit 1 ==-- ;--== lcd_rw ..... Port 0 Bit 2 ==-- ;--== lcd_data ... Port 0 Bits 6:3 (4-bit Interface) ==-- ;--== ==-- ;--== Source assembles into 144 words (288 bytes). ==-- ;--== ==-- ;--== Be careful when modifying this source as it is highly optimized ==-- ;--== and uses the scratch register philosophy extensively. ==-- ;--== ==-- ;---========================== End Description =========================--- Start Move #2048,SP ; Set Stack Pointer to Top of Memory ; ; Initialization Sequence for HD44780 running in 4-bit mode. ; LoadQ #16,D0 ; D0 = 16 (16ms) BsrQ MSDelay ; Wait for more than 15ms MoveQ #%0011,D0 ; D0 = Function Set BsrQ WrCtrl ; Interface is 8-bits long LoadQ #5,D0 ; D0 = 5 (5ms) BsrQ MSDelay ; Wait for more than 4.1ms MoveQ #%0011,D0 ; D0 = Function Set BsrQ WrCtrl ; Interface is 8-bits long LoadQ #1,D0 ; D0 = 1 (1ms) BsrQ MSDelay ; Wait for more than 100us MoveQ #%0011,D0 ; D0 = Function Set BsrQ WrCtrl ; Interface is 8-bits long MoveQ #%0010,D0 ; D0 = Function Set BsrQ WrCtrl ; Interface is 4-bits long LoadQ #%00101000,D0 ; D0 = Function Set BsrQ WrDCtrl ; Send Control Character to LCD LoadQ #%00001100,D0 ; D0 = Display On/Off Control BsrQ WrDCtrl ; Send Control Character to LCD LoadQ #%00000001,D0 ; D0 = Clear Display BsrQ WrDCtrl ; Send Control Character to LCD LoadQ #%00000110,D0 ; D0 = Entry Mode Set BsrQ WrDCtrl ; Send Control Character to LCD ; ; LCD Scroller Loop. ; Loopy LoadQ #String,A0 ; A0 = Pointer to String LoadQ #PosPtr,A1 ; A1 = Pointer to Position BsrQ EdgeString ; Display String at Position Move #150,D0 ; D0 = 150 (150ms) BsrQ MSDelay ; Wait for 150ms BraQ Loopy ; Loop Back ; -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ; WrDCtrl ...... Send a Control Character to the LCD. ; Inputs ....... D0.lsb = Control ; Output ....... None ; Scratch ...... D0 & D1 WrDCtrl Move D0,D1 ; Save Control ShrQ #4,D0 ; D0.nibble = Upper 4-bits of Control BsrQ WrCtrl ; Write Control Nibble Move D1,D0 ; D0.nibble = Lower 4-bits of Control BsrQ WrCtrl ; Write Control Nibble CmpQ #3,D1 ; Check Control Rts ugt ; Return if Control > 3 LoadQ #2,D0 ; D0 = 2 (2ms) ; No Need ;BsrQ MSDelay ; Wait for more than 1.64ms ; Sub Below ;Rts ; Rts ; -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ; MSDelay ...... Delay for X Milliseconds. ; Inputs ....... D0 = X (Number of Milliseconds) ; Output ....... None ; Scratch ...... D0 & D1 MSDelay BraQ MSOuter ; Branch to Outer Loop MSInit Move #4165,D1 ; Set Delay Loop Count MSInner SubQ #1,D1 ; Decrement Delay Loop Count BraQ uoc,MSInner ; Branch if New Delay Loop Count >= 0 MSOuter SubQ #1,D0 ; Decrement 1ms Loop Count BraQ uoc,MSInit ; Branch if New 1ms Loop Count >= 0 MSEnd Rts ; Return ; -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ; WrCtrl ....... Send a Control (Nibble) to the LCD. ; Inputs ....... D0.nibble = Control Nibble ; Output ....... None ; Scratch ...... D0 WrCtrl MoveQ #$0000,P0 ; lcd_data="0000", lcd_rw='0', lcd_en='0', lcd_rs='0' BraQ WrCharI ; Branch to WrChar Sequence ; -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ; WrPosChar .... Send an ASCII Character to the LCD at a specified position. ; Inputs ....... D0.lsb = Position ; D1.lsb = Character ; Output ....... None ; Scratch ...... D0, D1 & A0 WrPosChar Move D1,A0 ; Save Character Or #$80,D0 ; DD RAM Address Set BsrQ WrDCtrl ; Move Cursor Move A0,D0 ; D0 = Character ; No Need ;BsrQ WrDChar ; Display ASCII Character ; Sub Below ;Rts ; Return ; -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ; WrDChar ...... Send an ASCII Character to the LCD. ; Inputs ....... D0.byte = Character ; Output ....... None ; Scratch ...... D0 & D1 WrDChar Move D0,D1 ; Save Control Byte ShrQ #4,D0 ; D0.nibble = Upper 4-bits of Character BsrQ WrChar ; Write Character Nibble Move D1,D0 ; D0.nibble = Lower 4-bits of Character ; No Need ;BsrQ WrChar ; Write Character Nibble ; Sub Below ;Rts ; Return ; -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ; WrChar ....... Send an ASCII Character (Nibble) to the LCD. ; Inputs ....... D0.nibble = Character Nibble ; Output ....... None ; Scratch ...... D0 WrChar MoveQ #$0001,P0 ; lcd_data="0000", lcd_rw='0', lcd_en='0', lcd_rs='1' WrCharI ShlQ #3,D0 ; D0 = "000000000" Nibble & "000" Or D0,P0 ; lcd_data=Nibble OrQ #$0002,P0 ; lcd_en='1' Nop ; Stall for 80 ns Nop ; Stall for 80 ns Nop ; Stall for 80 ns Nop ; Stall for 80 ns Nop ; Stall for 80 ns AndQ #$FFFD,P0 ; lcd_en='0' Move #200,D0 ; Delay Count (D0) = 40us min WHLoop SubQ #1,D0 ; Delay Count := Delay Count - 1 BraQ neq,WHLoop ; Branch Back if Delay Count > 0 Rts ; Return ; -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ; EdgeString ... Display a String on the LCD Starting at Position and ; proceeding around the edge of the LCD. ; Inputs ....... A0 = Pointer to String ; A1 = Pointer to String Index (Will be Updated by EdgeString) ; Output ....... None ; Scratch ...... D0,D1,A0,A1 EdgeString PushL D2,D3,A0,A2 ; Save D2, D3, A0 & A2 StartStr Move A0,A2 ; A2 = Character Pair Pointer MoveQ #0,D2 ; D2 = String Index = 0 Move (A1),D3 ; D3 = Position Index GetChar Move D2,D0 ; GB : D0 = Index Move A2,A0 ; GB : A0 = Byte Array BsrQ GetByte ; GB : Get Byte from Byte Array ; ; GB : D0 = Byte CmpQ #0,D0 ; Check Character BraQ zrs,ESRts ; Branch if not at End of String Move D0,D1 ; D1 = Character AddQ #1,D2 ; String Index = String Index + 1 GetPos Move D3,D0 ; GB : D0 = Index LoadQ #PosDat,A0 ; GB : A0 = Byte Array BsrQ GetByte ; GB : Get Byte from Byte Array ; ; GB : D0 = Byte AddQ #1,D3 ; Position Index := Position Index + 1 Cmp #$00FF,D0 ; Check Position BraQ neq,WrChars ; Branch if Position is not -1 MoveQ #0,D3 ; D3 = Position Index = 0 BraQ GetPos ; Branch Back to Get Position WrChars CmpQ #1,D2 ; Check String Index BraQ neq,NoUpdate ; Branch if String Index <> 1 Move D3,(A1) ; Update Position Index NoUpdate BsrQ WrPosChar ; WPC : Display ASCII Character at Position BraQ GetChar ; Branch Back for Next Character ESRts PopL D2,D3,A0,A2 ; Restore D2, D3, A0 & A2 Rts ; Return ; -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ; GetByte ...... Return a byte from a byte array. ; Inputs ....... D0 = Index in Byte Array ; A0 = Address of Byte Array ; Output ....... D0 = "00000000" & Byte ; Scratch ...... None (All Register Preserved) GetByte Move A1,-(SP) ; Save A1 Move D0,A1 ; A1 = Index ShrQ #1,A1 ; A1 = Index Div 2 Add A0,A1 ; A1 = ^Array + Index Div 2 Move (A1),A1 ; A1 = Byte Pair (Even/Odd) AndQ #$0001,D0 ; Check Index for Even or Odd Value BraQ zrc,GBVOdd ; Branch if Index is Odd ShrQ #8,A1 ; A1 = "00000000" & Even Byte GBVOdd And #$00FF,A1 ; A1 = "00000000" & Odd Byte Move A1,D0 ; D0 = "00000000" & Byte Move (SP)+,A1 ; Restore A1 Rts ; Return ; -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- PosPtr Words 0 String Bytes " Hello World!",0 ; -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ; Character Positions for around the edge of a 16x2 LCD Display. PosDat Bytes $00,$01,$02,$03,$04,$05,$06,$07,$08,$09 Bytes $0A,$0B,$0C,$0D,$0E,$0F,$4F,$4E,$4D,$4C Bytes $4B,$4A,$49,$48,$47,$46,$45,$44,$43,$42 Bytes $41,$40,-1,0 ; Character Positions for around the edge of a 20x2 LCD Display. ;PosDat Bytes $00,$01,$02,$03,$04,$05,$06,$07,$08,$09 ; Bytes $0A,$0B,$0C,$0D,$0E,$0F,$10,$11,$12,$13 ; Bytes $53,$52,$51,$50,$4F,$4E,$4D,$4C,$4B,$4A ; Bytes $49,$48,$47,$46,$45,$44,$43,$42,$41,$40 ; Bytes -1,0 ; Character Positions for around the edge of a 20x4 LCD Display. ;PosDat Bytes $00,$01,$02,$03,$04,$05,$06,$07,$08,$09 ; Bytes $0A,$0B,$0C,$0D,$0E,$0F,$10,$11,$12,$13 ; Bytes $53,$27,$67,$66,$65,$64,$63,$62,$61,$60 ; Bytes $5F,$5E,$5D,$5C,$5B,$5A,$59,$58,$57,$56 ; Bytes $55,$54,$14,$40,-1,0 ; -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-