{"id":964,"date":"2020-01-26T15:26:37","date_gmt":"2020-01-26T15:26:37","guid":{"rendered":"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/?p=964"},"modified":"2024-05-14T16:34:47","modified_gmt":"2024-05-14T15:34:47","slug":"68008-sbc-lcd-control","status":"publish","type":"post","link":"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/?p=964","title":{"rendered":"68008 SBC LCD Control"},"content":{"rendered":"\n<h2>68008 SBC LCD Control<\/h2>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" width=\"1024\" height=\"768\" src=\"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/wp-content\/uploads\/2020\/01\/ThisIsA68008-1024x768.jpg\" alt=\"\" class=\"wp-image-974\" srcset=\"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/wp-content\/uploads\/2020\/01\/ThisIsA68008-1024x768.jpg 1024w, https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/wp-content\/uploads\/2020\/01\/ThisIsA68008-300x225.jpg 300w, https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/wp-content\/uploads\/2020\/01\/ThisIsA68008-1536x1152.jpg 1536w, https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/wp-content\/uploads\/2020\/01\/ThisIsA68008.jpg 2048w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>The following is my first attempt at controlling the LCD on my <a href=\"http:\/\/kswichit.net\/68008\/68008.htm\">Wichit Sirichote<\/a> (URL updated 2024 to new website) Single Board Computer. Please forgive any terrible programming as I&#8217;m not very familiar with assembly language, and even less so with 68k assembly language programming. I&#8217;ve tried to make the code a little modular so the subroutines can be re-used. I previously described the software setup I&#8217;m using to program the board from Linux <a href=\"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/?p=927\">here<\/a>. There are two versions of the same program (almost) in this post, the second of which animates the little stickman using interrupts for timing.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>; Hardware Locations in Memory\ngpio1\t\tequ\t$f0000\t\t; LED PORT\nlcdcw\t\tequ\t$60000\t\t; LCD command WR\nlcddw\t\tequ\t$60001\t\t; LCD data WR\nlcdcr\t\tequ\t$60002\t\t; LCD command RD\nlcddr\t\tequ\t$60003\t\t; LCD data RD\n\n; LCD Commands\nlcdbsy\t\tequ\t$80\t\t; LCD BUSY\nlcd8bt\t\tequ\t$38\t\t; Select 8 bits interface\nlcdinc\t\tequ\t$06\t\t; Entry Mode - Increment\nlcddcb\t\tequ\t$0E\t\t; Display On, Cursor On, Blink OFF\nlcddnc\t\tequ\t$0C\t\t; Display On, Cursor Off, Blink Off\nlcdoff\t\tequ\t$08\t\t; Display Off, Cursor Off\nlcdclr\t\tequ\t$01\t\t; Clear Display\nlcd1st\t\tequ\t$80\t\t; Set first line start\nlcd2nd\t\tequ \t$C0\t\t; Set second line start\n\n; Program location in memory\n\t\torg \t$400\t\t; start of program\n\nSTART\n\t\tmove.l\t#stack,a7\t; sure\n\t\tmove.w\t#$2100,sr\t; what these do\n\t\tbsr \tsubinit\t\t; initialise LCD\n\t\tbsr \tsubcust\t\t; send little man\n\t\tbsr \tsubclr\t\t; clear screen\n\t\tbsr \tsubrow1\t\t; go to home address\n;send text\n\t\tlea\ttext1,A2\t; get address of text string\n\t\tbsr \tsubsend\t\t; send the text located at A2\n\t\tbsr \tsubrow2\t\t; go to second line\n\t\tlea \ttext2,A2\t; next line text address\n\t\tbsr \tsubsend\t\t; send it\nloop\t\tjmp\tloop\t\t; forever\n\n; ---------------------------------------------------\n\nsublcdr\t; wait for lcd ready\n\t\tmovem.l\tD0-D1,-(sp)\n\t\tmove.w\t#$ffff,D1\nlcd_bu0\n\t\tmove.b\t(lcdcr),D0\n\t\tandi.b\t#lcdbsy,D0\n\t\tbeq.s\tlcd_bu1\n\t\tdbra\tD1,lcd_bu0\n\t\tmoveq\t#1,D1\nlcd_bu1\n\t\tmovem.l\t(sp)+,D0-D1\n\t\trts\n\nsubinit ; set up the display\n\t\tmove.b\t#lcd8bt,(lcdcw)\t; write command $38 - 8 bit mode\n\t\tmove.b\t#lcd8bt,(lcdcw)\n\t\tmove.b\t#lcd8bt,(lcdcw)\n\t\tbsr\tsublcdr\t\t; wait for ready\n\t\tmove.b\t#lcdinc,(lcdcw)\t; write command $06 increment cursor\n\t\tbsr\tsublcdr\n\t\tmove.b\t#lcddnc,(lcdcw)\t; display on, cursor off, blink off\n\t\trts\n\nsubclr\t; clear the display\n\t\tbsr\tsublcdr\t\t; wait for ready\n\t\tmove.b\t#lcdclr,(lcdcw)\t; write command $01, clear display\n\t\trts\n\nsubrow1\t; go to first line\n\t\tbsr\tsublcdr\n\t\tmove.b\t#lcd1st,(lcdcw)\t; write command $80, first line start\n\t\trts\n\t\nsubrow2\t; go to second line\n\t\tbsr\tsublcdr\n\t\tmove.b\t#lcd2nd,(lcdcw)\t; write command $C0, first line start\n\t\trts\n\t\nsubsend\t; send string that starts at A2, and ends with zero\n\t\tmovem.l\tD0,-(sp)\nss1\t\tbsr\tsublcdr\n\t\tmove.b\t(A2)+,D0\n\t\tbeq.s\tsenddone\n\t\tbsr\tsublcdr\n\t\tmove.b\tD0,(lcddw)\n\t\tbra ss1\t\t\t; blt next\nsenddone\n\t\tmovem.l\t(sp)+,D0\n\t\trts\n\nsubcust\t; create and send a custom character\n\t\t\tbsr\tsublcdr\n\t\t\tmove.b\t#$48,(lcdcw)\t; custom char 0 edit\n\t\t\tlea man,A2\t\t; send data for man (note, can't have 0 in data)\n\t\t\tbsr\tsubsend\n\t\t\trts\n\n; string to display, terminating with zero\ntext1\t\tdc.b\t'This is a M68008',0\ntext2\t\tdc.b\t1,' Doing Stuff! ',1,0\t; 1 gives special char 1. (a little man)\nman\t\t\tdc.b\t%01110,%01110,%00100,%01110,%10101,%00100,%01010,%01010,0\n\nram\tds.b\t32\t\t; not sure\nstack\t\tequ\t*\t; what these do\n<\/code><\/pre>\n\n\n\n<p>This second version uses interrupts for timing a simple animation, but there is more code that I do not understand in it, so please forgive me if there are non-critical errors. The code isn&#8217;t very efficient in its use of data registers.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>; Hardware Locations in Memory\ngpio1\t\tequ\t$f0000\t\t\t; LED PORT\nlcdcw\t\tequ\t$60000\t\t\t; LCD command WR\nlcddw\t\tequ\t$60001\t\t\t; LCD data WR\nlcdcr\t\tequ\t$60002\t\t\t; LCD command RD\nlcddr\t\tequ\t$60003\t\t\t; LCD data RD\n\n; LCD Commands\nlcdbsy\t\tequ\t$80\t\t\t; LCD BUSY\nlcd8bt\t\tequ\t$38\t\t\t; Select 8 bits interface\nlcdinc\t\tequ\t$06\t\t\t; Entry Mode - Increment\nlcddcb\t\tequ\t$0E\t\t\t; Display On, Cursor On, Blink OFF\nlcddnc\t\tequ\t$0C\t\t\t; Display On, Cursor Off, Blink Off\nlcdoff\t\tequ\t$08\t\t\t; Display Off, Cursor Off\nlcdclr\t\tequ\t$01\t\t\t; Clear Display\nlcd1st\t\tequ\t$80\t\t\t; Set first line start\nlcd2nd\t\tequ \t$C0\t\t\t; Set second line start\n\n; Program location in memory\n\t\torg \t$400\t\t\t; start of program\n\nSTART\n\t\tmove.l\t#service_level2,$68\t; not\n\t\tmove.l\t#stack,a7\t\t; sure\n\t\tmove.w\t#$2100,sr\t\t; what these do\n\t\tmove.b\t#$0,d2\n\t\tmove.b\t#$0,d3\n\t\tmove.b\t#0,d4\n\t\tbsr \tsubinit\t\t\t; initialise LCD\n\t\tbsr \tsubcust\t\t\t; set up little man in char 1 &amp; 2\n\t\tbsr \tsubclr\t\t\t; clear screen\n\t\tbsr \tsubrow1\t\t\t; go to home address\n;send text\n\t\tlea\ttext1,A2\t\t; get address of text string\n\t\tbsr \tsubsend\t\t\t; send the text located at A2\nloop\t\tcmpi.b\t#1,d4\t\t\t; Don't re-send if you've already done so\n\t\tbge\tloop\t\t\t; loop if already shown\n\t\tbsr\tsubrow2\t\t\t; pre-move to the start of the second line\n\t\tcmpi.b\t#1,d3\t\t\n\t\tblt\talt\t\t\t; go to alt if d3&lt;1\n\t\tlea \ttext2,A2\t\t; send text2\n\t\tbsr \tsubsend\t\t\t; send it\n\t\tmove.b\t#1,d4\n\t\tbra\tloop\nalt\t\tlea\ttext3,A2\t\t; send text3\n\t\tbsr\tsubsend\n\t\tmove.b\t#1,d4\n\t\tbra\tloop\t\t\t; forever - note jmp is an absolute address, bra is rel\n\n; ---------------------------------------------------\n\nservice_level2\n\t\taddi.b\t#1,d2\t\t; increment d2\n\t\tcmpi.b\t#50,d2\t\t; check if d2 is 50 or more\n\t\tblt\tskip\t\t; rte if not 50\n\t\tclr.b\td2\t\t; reset d2 to 0\n\t\tmove.b\td3,gpio1\t; debug code - shows status on leds\n\t\tclr.b\td4\t\t; reset \"don't send again\" value\n\t\taddi.b\t#1,d3\t\t; increase d3 (which line 2 to send)\n\t\tcmpi.b\t#2,d3\t\t; check if d3 is too big\n\t\tblt\t\tskip\t; if it isn't, finish\n\t\tclr.b\td3\t\t; if it is, make it = 0\nskip\t\trte\t\t\t; return\n\nsublcdr\t; wait for lcd ready\n\t\tmovem.l\tD0-D1,-(sp)\n\t\tmove.w\t#$ffff,D1\nlcd_bu0\n\t\tmove.b\t(lcdcr),D0\n\t\tandi.b\t#lcdbsy,D0\t; check if the lcd is busy\n\t\tbeq.s\tlcd_bu1\n\t\tdbra\tD1,lcd_bu0\n\t\tmoveq\t#1,D1\nlcd_bu1\n\t\tmovem.l\t(sp)+,D0-D1\n\t\trts\n\nsubinit ; set up the display\n\t\tmove.b\t#lcd8bt,(lcdcw)\t; write command $38 - 8 bit mode\n\t\tmove.b\t#lcd8bt,(lcdcw)\n\t\tmove.b\t#lcd8bt,(lcdcw)\n\t\tbsr\tsublcdr\t\t\t\t; wait for ready\n\t\tmove.b\t#lcdinc,(lcdcw)\t; write command $06 increment cursor\n\t\tbsr\tsublcdr\n\t\tmove.b\t#lcddnc,(lcdcw)\t; display on, cursor off, blink off\n\t\trts\n\nsubclr\t; clear the display\n\t\tbsr\tsublcdr\t\t\t\t; wait for ready\n\t\tmove.b\t#lcdclr,(lcdcw)\t; write command $01, clear display\n\t\trts\n\nsubrow1\t; go to first line\n\t\tbsr\tsublcdr\n\t\tmove.b\t#lcd1st,(lcdcw)\t; write command $80, first line start\n\t\trts\n\t\nsubrow2\t; go to second line\n\t\tbsr\tsublcdr\n\t\tmove.b\t#lcd2nd,(lcdcw)\t; write command $C0, first line start\n\t\trts\n\t\nsubsend\t; send string that starts at A2, and ends with zero\n\t\tmovem.l\tD0,-(sp)\nss1\t\tbsr\tsublcdr\n\t\tmove.b\t(A2)+,D0\n\t\tbeq.s\tsenddone\n\t\tbsr\tsublcdr\n\t\tmove.b\tD0,(lcddw)\n\t\tbra \tss1\t\t\t\t\t; blt next\nsenddone\n\t\tmovem.l\t(sp)+,D0\n\t\trts\n\nsubcust\t; create and send a custom character\n\t\tbsr\tsublcdr\n\t\tmove.b\t#$48,(lcdcw)\t; custom char 0 edit\n\t\tlea \tman,A2\t\t; send data for man (note, can't have 0 in data)\n\t\tbsr \tsubsend\n\t\trts\n\n; --------------------------------------------------------\n\n\n; string to display, terminating with zero\ntext1\t\tdc.b\t'This is a M68008',0\ntext2\t\tdc.b\t2,' Doing Stuff! ',1,0\t; 1 gives special char 1. (a little man)\ntext3\t\tdc.b\t1,' Doing Stuff! ',2,0\t; 2 gives special char 2. (a little man arms up)\nman\t\t\tdc.b\t%01110,%01110,%00100,%01110,%10101,%00100,%01010,%01010,%01110,%01110,%10101,%01110,%00100,%00100,%01010,%01010,0\n\nram\tds.b\t32\t\t; not sure\nstack\t\tequ\t*\t; what these do\n<\/code><\/pre>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>68008 SBC LCD Control The following is my first attempt at controlling the LCD on my Wichit Sirichote (URL updated 2024 to new website) Single Board Computer. Please forgive any terrible programming as I&#8217;m not very familiar with assembly language, and even less so with 68k assembly language programming. I&#8217;ve tried to make the code [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":960,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"spay_email":"","jetpack_publicize_message":"","jetpack_is_tweetstorm":false},"categories":[13,42,12,152],"tags":[39,240,239,244,246,245,242],"jetpack_featured_media_url":"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/wp-content\/uploads\/2020\/01\/68008_Board_3.jpg","jetpack_publicize_connections":[],"jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p7g9vY-fy","_links":{"self":[{"href":"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/index.php?rest_route=\/wp\/v2\/posts\/964"}],"collection":[{"href":"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=964"}],"version-history":[{"count":16,"href":"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/index.php?rest_route=\/wp\/v2\/posts\/964\/revisions"}],"predecessor-version":[{"id":2171,"href":"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/index.php?rest_route=\/wp\/v2\/posts\/964\/revisions\/2171"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/index.php?rest_route=\/wp\/v2\/media\/960"}],"wp:attachment":[{"href":"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=964"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=964"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=964"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}