It is currently Wed May 22, 2013 9:46 am

All times are UTC + 10 hours




Post new topic Reply to topic  [ 13 posts ] 
Author Message
 Post subject: A simple LCD based numbers game
PostPosted: Sat Jun 19, 2010 11:48 pm 
Offline
Site Admin
Site Admin
User avatar

Joined: Fri Mar 26, 2010 10:30 pm
Posts: 1860
Today I sat down and wanted to see how long it would take me to make a very simple numbers game on one of those 2x16 LCD displays. All up from initial concept to the finished code was about 1 hour. I really couldn't tell you how long it would have taken me to code in assembly - but it would certainly have been ALOT longer!

I had already made up the LCD circuit with push buttons in a handy hobby box for another project I was working on, so all I needed was the code.

The game is very simple, you have a single digit at the top left of screen which can be any number between 0 and 9 inclusive. you can change this number by pressing either the up or down buttons. To the top right of screen is a random number (also between 0 and 9 inclusive) this number will scroll towards you (leaving a trail of the same number). You need to use the up/down arrows to change your number so that it matches the random number coming towards you.

If you match the number by the time it hits you, then you get a point. If you do not match it, then it is game over and the high score is displayed on the screen. You then press a button to play again.

Here's a couple of photos:
Image

Image


For those interested, here's the code:
Code:
    Device = 18F4685
    Clock = 8                           // This is used to tell the compiler what clock we are using
    Config OSC = IRCIO67                // We want to use the internal oscillator.


// some LCD options...
#option LCD_DATA = PORTD.4              // Assign the LCD connections
#option LCD_EN = PORTD.3                //
#option LCD_RS = PORTD.2                //

// import library's
Include "LCD.bas"
Include "convert.bas"

// port setup
Dim button_down As PORTA.0 
Dim button_up As PORTA.1
Dim button_select As PORTA.2
Dim button_menu As PORTA.3

Dim random_number As Byte
Dim random_number_saved As Byte
Dim incoming_number As Byte
Dim number_position As Word
Dim your_number As Byte
Dim score As Byte
Dim button_debounce As Byte
Dim number_speed As Byte
Dim high_score As Byte

Sub draw_screen()
    LCD.WriteAt(1,(number_position),Convert.DecToStr(incoming_number,1))
    LCD.WriteAt(1,1,Convert.DecToStr(your_number,1))
    LCD.WriteAt(2,1,"Your Score =")
    LCD.WriteAt(2,14,Convert.DecToStr(score,3))
End Sub

Sub check_buttons()
    If button_down = 1 Then
        random_number_saved = random_number
    EndIf
    If button_up = 1 Then
        random_number_saved = random_number
    EndIf
    If button_up = 1 And button_debounce = 0 And your_number < 9 Then
        Inc(your_number)
        button_debounce = 50
    EndIf
    If button_down = 1 And button_debounce = 0 And your_number > 0  Then
        Dec(your_number)
        button_debounce = 50
    EndIf
End Sub

Sub debounce_buttons()
    If button_debounce <> 0 Then
        Dec(button_debounce)
    EndIf
End Sub

Sub update_incoming_number()
    If number_position = 1 And your_number = incoming_number Then
        If random_number_saved = incoming_number Then
            Inc(random_number_saved)
        EndIf
        Inc(score)
        LCD.Cls
        incoming_number = random_number_saved
        number_position = 16
    EndIf
End Sub

Sub check_if_game_over()
    If number_position = 1 And your_number <> incoming_number Then
        If score > high_score Then
            high_score = score
        EndIf
        LCD.WriteAt(1,1,"** GAME  OVER **")
        LCD.WriteAt(2,1,"High Score = ")
        LCD.WriteAt(2,14,Convert.DecToStr(high_score,3))         
        Repeat Until button_select = 1
        incoming_number = random_number
        number_position = 16
        score = 0
        LCD.Cls
    EndIf   
End Sub

Sub move_number()
    If number_speed = 0 And number_position > 1 Then
        Dec(number_position)
        number_speed = 50
    EndIf   
End Sub

Sub update_number_speed()
    If number_speed <> 0 Then
        Dec(number_speed)
    EndIf
End Sub

Sub update_random_number()
    Inc(random_number)
    If random_number = 10 Then random_number = 0
    EndIf   
End Sub


// Start Of Program...
OSCCON = %01111111                  // Sets the internal oscillator for 8Mhz
TRISD = %00000000                   // Makes PORTD all outputs
TRISA = %00001111                   // PORTA 0-3 inputs and 4-7 outputs

number_position = 16
random_number = 9
your_number = 0
incoming_number = 7
button_debounce = 50
number_speed = 50
score = 0
high_score = 0


DelayMS(150)                            // Let the LCD warm up

While true
     draw_screen
     check_buttons
     debounce_buttons
     update_incoming_number
     check_if_game_over
     move_number
     update_number_speed
     update_random_number
Wend


Attachments:
gameplay.jpg
gameplay.jpg [ 37.59 KiB | Viewed 1701 times ]
game_over.jpg
game_over.jpg [ 37.55 KiB | Viewed 1701 times ]
Top
 Profile  
 
 Post subject:
PostPosted: Sun Jun 20, 2010 6:07 am 
Offline
Moderator
Moderator
User avatar

Joined: Sun Mar 28, 2010 9:03 pm
Posts: 699
Location: United Kingdom
Wow that is a great idea for a project Brad :)

This is a 16bit counter on a LCD display I made up.

Image


And heres the souce code to give people an example of how much different the programs are :D

Code:
   LIST   p=16F628a  ;tell assembler what chip we are using
   include "P16F628a.inc"   ;include the defaults for the chip
   ERRORLEVEL   0,   -302   ;suppress bank selection messages
   __config 0x3D18   ;sets the configuration settings (oscillator type etc.)




   cblock   0x20  ;start of general purpose registers
         count   ;used in looping routines
         count1   ;used in delay routine
         counta   ;used in delay routine
         countb   ;used in delay routine
         tmp1   ;temporary storage
         tmp2
         templcd   ;temp store for 4 bit mode
         templcd2

           NumL   ;Binary inputs for decimal convert routine
   NumH   

              TenK   ;Decimal outputs from convert routine
              Thou   
              Hund   
              Tens   
              Ones   
      endc

LCD_PORT   Equ   PORTA
LCD_TRIS   Equ   TRISA
LCD_RS      Equ   0x04   ;LCD handshake lines
LCD_RW      Equ   0x06
LCD_E      Equ   0x07

      org   0x0000

      movlw   0x07
    movwf      CMCON ;turn comparators off (make it like a 16F84)

Initialise   clrf   count
      clrf   PORTA
      clrf   PORTB
      clrf   NumL
      clrf   NumH



SetPorts   bsf    STATUS,      RP0 ;select bank 1
      movlw   0x00   ;make all pins outputs
      movwf   LCD_TRIS
      bcf    STATUS,   RP0  ;select bank 0

      call   LCD_Init      ;setup LCD


      clrf   count    ;set counter register to zero
Message      movf   count, w   ;put counter value in W
      call   Text ;get a character from the text table
      xorlw   0x00   ;is it a zero?
      btfsc   STATUS, Z
      goto   NextMessage
      call   LCD_Char
      incf   count, f
      goto   Message

NextMessage   call   LCD_Line2      ;move to 2nd row, first column
   
      call   Convert         ;convert to decimal
      movf   TenK,   w      ;display decimal characters
      call   LCD_CharD      ;using LCD_CharD to convert to ASCII
      movf   Thou,   w
      call   LCD_CharD
      movf   Hund,   w
      call   LCD_CharD      
      movf   Tens,   w
      call   LCD_CharD
      movf   Ones,   w
      call   LCD_CharD
      movlw   ' '         ;display a 'space'
      call   LCD_Char
      movf   NumH,   w      ;and counter in hexadecimal
      call   LCD_HEX
      movf   NumL,   w
      call   LCD_HEX
      incfsz   NumL,    f
      goto   Next
      incf   NumH,   f
Next      call   Delay255      ;wait so you can see the digits change
      goto   NextMessage


;Subroutines and text tables

;LCD routines

;Initialise LCD
LCD_Init   call   Delay100      ;wait for LCD to settle

      movlw   0x20   ;Set 4 bit mod
      call   LCD_Cmd

      movlw   0x28   ;Set display shift
      call   LCD_Cmd

      movlw   0x06   ;Set display character mode
      call   LCD_Cmd

   movlw   0x0c ;Set display on/off and cursor command
      call   LCD_Cmd    ;Set cursor off

      call   LCD_Clr   ;clear display

      retlw   0x00

; command set routine
LCD_Cmd      movwf   templcd
      swapf   templcd,   w   ;send upper nibble
      andlw   0x0f   ;clear upper 4 bits of W
      movwf   LCD_PORT
      bcf   LCD_PORT, LCD_RS   ;RS line to 0
      call   Pulse_e   ;Pulse the E line high

      movf   templcd,   w   ;send lower nibble
      andlw   0x0f   ;clear upper 4 bits of W
      movwf   LCD_PORT
      bcf   LCD_PORT, LCD_RS   ;RS line to 0
      call   Pulse_e   ;Pulse the E line high
      call    Delay5
      retlw   0x00

LCD_CharD   addlw   0x30 ;add 0x30 to convert to ASCII
LCD_Char   movwf   templcd
      swapf   templcd,   w   ;send upper nibble
      andlw   0x0f   ;clear upper 4 bits of W
      movwf   LCD_PORT
      bsf   LCD_PORT, LCD_RS   ;RS line to 1
      call   Pulse_e   ;Pulse the E line high

      movf   templcd,   w  ;send lower nibble
      andlw   0x0f   ;clear upper 4 bits of W
      movwf   LCD_PORT
      bsf   LCD_PORT, LCD_RS   ;RS line to 1
      call   Pulse_e   ;Pulse the E line high
      call    Delay5
      retlw   0x00

LCD_Line1   movlw   0x80   ;move to 1st row, first column
      call   LCD_Cmd
      retlw   0x00

LCD_Line2   movlw   0xc0   ;move to 2nd row, first column
      call   LCD_Cmd
      retlw   0x00

LCD_Line1W   addlw   0x80   ;move to 1st row, column W
      call   LCD_Cmd
      retlw   0x00

LCD_Line2W   addlw   0xc0   ;move to 2nd row, column W
      call   LCD_Cmd
      retlw   0x00

LCD_CurOn   movlw   0x0d   ;Set display on/off and cursor command
      call   LCD_Cmd
      retlw   0x00

LCD_CurOff   movlw   0x0c   ;Set display on/off and cursor command
      call   LCD_Cmd
      retlw   0x00

LCD_Clr      movlw   0x01      ;Clear display
      call   LCD_Cmd
      retlw   0x00

LCD_HEX      movwf   tmp1
      swapf   tmp1,   w
      andlw   0x0f
      call   HEX_Table
      call   LCD_Char
      movf   tmp1, w
      andlw   0x0f
      call   HEX_Table
      call   LCD_Char
      retlw   0x00

Delay255   movlw   0xff      ;delay 255 mS
      goto   d0
Delay100   movlw   d'100'      ;delay 100mS
      goto   d0
Delay50      movlw   d'50'   ;delay 50mS
      goto   d0
Delay20      movlw   d'20'   ;delay 20mS
      goto   d0
Delay5      movlw   0x05   ;delay 5.000 ms
d0      movwf   count1
d1      movlw   0xC7   ;delay 1mS
      movwf   counta
      movlw   0x01
      movwf   countb
Delay_0
      decfsz   counta, f
      goto   $+2
      decfsz   countb, f
      goto   Delay_0

      decfsz   count1   ,f
      goto   d1
      retlw   0x00

Pulse_e      bsf   LCD_PORT, LCD_E
      nop
      bcf   LCD_PORT, LCD_E
      retlw   0x00

;end of LCD routines

HEX_Table     ADDWF   PCL       , f
               RETLW   0x30
               RETLW   0x31
               RETLW   0x32
               RETLW   0x33
               RETLW   0x34
               RETLW   0x35
               RETLW   0x36
               RETLW   0x37
               RETLW   0x38
               RETLW   0x39
               RETLW   0x41
               RETLW   0x42
               RETLW   0x43
               RETLW   0x44
               RETLW   0x45
               RETLW   0x46

Text      addwf   PCL, f
      retlw   '1'
      retlw   '6'
      retlw   ' '
      retlw   'B'
      retlw   'i'
      retlw   't'
      retlw   ' '
      retlw   'C'
      retlw   'o'
      retlw   'u'
      retlw   'n'
      retlw   't'
      retlw   'e'
      retlw   'r'
      retlw   '.'
      retlw   0x00

Convert:               
        swapf   NumH, w
        iorlw     B'11110000'
        movwf   Thou
        addwf   Thou,f
        addlw   0XE2
        movwf   Hund
        addlw   0X32
        movwf   Ones

        movf    NumH,w
        andlw   0X0F
        addwf   Hund,f
        addwf   Hund,f
        addwf   Ones,f
        addlw   0XE9
        movwf   Tens
        addwf   Tens,f
        addwf   Tens,f

        swapf   NumL,w
        andlw   0X0F
        addwf   Tens,f
        addwf   Ones,f

        rlf     Tens,f
        rlf     Ones,f
        comf    Ones,f
        rlf     Ones,f

        movf    NumL,w
        andlw   0X0F
        addwf   Ones,f
        rlf     Thou,f

        movlw   0X07
        movwf   TenK

        movlw   0X0A            ; Ten
Lb1:
        addwf   Ones,f
        decf    Tens,f
        btfss   3,0
        goto   Lb1
Lb2:
        addwf   Tens,f
        decf    Hund,f
        btfss   3,0
        goto   Lb2
Lb3:
        addwf   Hund,f
        decf    Thou,f
        btfss   3,0
        goto   Lb3
Lb4:
        addwf   Thou,f
        decf    TenK,f
        btfss   3,0
        goto   Lb4

        retlw   0x00


      end 


Attachments:
16bitcounter.jpg
16bitcounter.jpg [ 72.21 KiB | Viewed 1690 times ]
Top
 Profile  
 
 Post subject:
PostPosted: Sun Jun 20, 2010 8:52 am 
Offline
Site Admin
Site Admin
User avatar

Joined: Fri Mar 26, 2010 10:30 pm
Posts: 1860
Very nice indeed! Thanks for posting that.

i am not sure what those extra numbers to the right of screen are, but here is my version of the 16 bit counter, it just increments by one each second.

Image

Here is the code:
Code:
Device = 18F4685
Clock = 8                           // This is used to tell the compiler what clock we are using
Config OSC = IRCIO67                // We want to use the internal oscillator.


// some LCD options...
#option LCD_DATA = PORTD.4              // Assign the LCD connections
#option LCD_EN = PORTD.3                //
#option LCD_RS = PORTD.2                //

// import library's
Include "LCD.bas"
Include "convert.bas"

// variable declaration
Dim counter as word

// Start Of Program...
OSCCON = %01111111                  // Sets the internal oscillator for 8Mhz
TRISD = %00000000                   // Makes PORTD all outputs except for pin 0

counter = 0                         // set the start point for the count

DelayMS(150)                     // Let the LCD warm up

While true
    LCD.WriteAt(1,1,"16 Bit Counter.")
    LCD.WriteAt(2,3,Convert.DecToStr(counter,5))
    delaymS(1000)
    inc(counter)
Wend


Attachments:
16_bit_counter.png
16_bit_counter.png [ 331.67 KiB | Viewed 1685 times ]
Top
 Profile  
 
 Post subject:
PostPosted: Sun Jun 20, 2010 8:57 am 
Offline
Moderator
Moderator
User avatar

Joined: Sun Mar 28, 2010 9:03 pm
Posts: 699
Location: United Kingdom
The numbers to the bottom right of the screen are the hexadecimal numbers.. :) they count up aswell as the 16bit counter


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jun 20, 2010 9:00 am 
Offline
Site Admin
Site Admin
User avatar

Joined: Fri Mar 26, 2010 10:30 pm
Posts: 1860
bitfogav wrote:
The numbers to the bottom right of the screen are the hexadecimal numbers.. :) they count up aswell as the 16bit counter


Here's my ammended code, I have added the line:

Code:
LCD.WriteAt(2,9,convert.hextostr(counter,4))


Code:
Device = 18F4685
Clock = 8                           // This is used to tell the compiler what clock we are using
Config OSC = IRCIO67                // We want to use the internal oscillator.


// some LCD options...
#option LCD_DATA = PORTD.4              // Assign the LCD connections
#option LCD_EN = PORTD.3                //
#option LCD_RS = PORTD.2                //

// import library's
Include "LCD.bas"
Include "convert.bas"

// variable declaration
Dim counter as word

// Start Of Program...
OSCCON = %01111111                  // Sets the internal oscillator for 8Mhz
TRISD = %00000000                   // Makes PORTD all outputs except for pin 0

counter = 0                         // set the start point for the count

DelayMS(150)                     // Let the LCD warm up

While true
    LCD.WriteAt(1,1,"16 Bit Counter.")
    LCD.WriteAt(2,3,Convert.DecToStr(counter,5))
    LCD.WriteAt(2,9,convert.hextostr(counter,4))
    delaymS(1000)
    inc(counter)
Wend


Image


Attachments:
counter_with_hex.png
counter_with_hex.png [ 361.79 KiB | Viewed 1673 times ]
16_bit_with_hex.jpg
16_bit_with_hex.jpg [ 101.49 KiB | Viewed 1675 times ]
Top
 Profile  
 
 Post subject:
PostPosted: Mon Jun 21, 2010 11:00 pm 
Offline
Moderator
Moderator
User avatar

Joined: Sun Mar 28, 2010 9:03 pm
Posts: 699
Location: United Kingdom
Yeah it looks easier doing it in basic. :)

Brad do you know how to make the lcd scroll in asm?, Im having a problems? it will probably be very easy in basic with just a few lines?.

I can make text scroll from left to right and vise versa but only doing it in software by addressing the lcd display, but is there not a way that the LCD will do it basically for you?

For example: looking at the datasheet for a lcd 16x2 it says theres a command for Display/Cursor Shift I have tried setting the Display shift but it dont work? Or isn't this a scroll function and just a shift function, I just can't get my head around it hehe! having one of those days hehe!, anyway I just wondered if you knew or had any ideas? :)


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jun 22, 2010 6:31 am 
Offline
Site Admin
Site Admin
User avatar

Joined: Fri Mar 26, 2010 10:30 pm
Posts: 1860
Unfortunately I am not sure, I haven't ever used these displays with ASM before...

I think it would be great to have scrolling text, I'll have to check the data sheet to see if I can figure it out in Basic. then I guess I can have a look at the ASM file that basic spits out once compiled.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jun 22, 2010 6:38 am 
Offline
Moderator
Moderator
User avatar

Joined: Sun Mar 28, 2010 9:03 pm
Posts: 699
Location: United Kingdom
Thats aright Brad thank you :)

I have been working on it quite abit and think I have sorted it..

Heres the ASM if you want to have a look

http://www.bradsprojects.com/phpBB2/uploads/lcd_scroller_3_147.rar

It writes Hello on the LCD screen at the top left and then scrolls it to the right, gets to the end of the LCD screen and then goes down to the 2nd line and then scrolls back to the left.. :)

PLEASE NOTE that this is not a finished asm, so some comments might be wrong or incomplete.


Attachments:
LCD Scroller 3.rar [1.93 KiB]
Downloaded 85 times
Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 23, 2010 6:47 am 
Offline
Site Admin
Site Admin
User avatar

Joined: Fri Mar 26, 2010 10:30 pm
Posts: 1860
Sounds like a nifty little lcd screensaver :D


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jun 24, 2010 8:55 am 
Offline
Moderator
Moderator
User avatar

Joined: Sun Mar 28, 2010 9:03 pm
Posts: 699
Location: United Kingdom
hehe yeah thats all it is really :)

Your enjoy making your own user graphics, its a little tricky to program but once you crack it then its fun making them :)

you can draw faces, to battery symbols and even speakers :)


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jul 04, 2010 9:09 pm 
Offline
decided to stick around...
decided to stick around...

Joined: Sun Jul 04, 2010 10:44 am
Posts: 35
Location: Australia
bitfogav wrote:
Your enjoy making your own user graphics, its a little tricky to program but once you crack it then its fun making them :)

They come in really handy and add the finishing touch in most cases!

Swordfish has a LCD Character plugin which makes the whole process a breeze.

Image

I did a small write up about the plugin, and have used it several times over the last year or so -- the first time was for a temperature logger which displayed "°C" (I couldn't settle for the text "Deg C")


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jul 04, 2010 10:22 pm 
Offline
Moderator
Moderator
User avatar

Joined: Sun Mar 28, 2010 9:03 pm
Posts: 699
Location: United Kingdom
Thats really cool :)

heres the website that ive been using to draw my user graphics, as it gives you your user graphics in dec, hex and binary :)

http://www.quinapalus.com/hd44780udg.html


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 05, 2010 8:02 pm 
Offline
Site Admin
Site Admin
User avatar

Joined: Fri Mar 26, 2010 10:30 pm
Posts: 1860
I had no idea that was built into swordfish!

And as for that site, that's brilliant :)

There are so many handy resources out there, it's just a matter of being able to find them I guess.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 13 posts ] 

All times are UTC + 10 hours


Who is online

Users browsing this forum: No registered users and 0 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Theme made by Keenen Wheeler