8 DECADE COUNTER/ODOMETER Commented Code

General discussion on mikroBasic.
Post Reply
Author
Message
xor
Posts: 5465
Joined: 18 May 2005 00:59
Location: NYC
Contact:

8 DECADE COUNTER/ODOMETER Commented Code

#1 Post by xor » 08 Dec 2005 05:02

I have had a few requests to explain the operation of the Odometer style 8 Decade Counter for the LCD that I posted a couple days ago here. Explaining in great detail would require several pages...but prefacing and commenting the code should help. Also, a couple things have been adjusted in this code that make this a fascinating visual display that runs on a regular LCD. It has a lot of potential for certain applications.

To get the most of this demonstration adjust your LCD contrast pot to where the characters just turn dark. Enjoy.

Code: Select all

program ODOMETER

'***********************************************************************************
'*        Tested on 16F877A @ 8MHz....8 DECADE COUNTER....ODOMETER STYLE           *
'*             Program by W. Schroeder alias "xor" on Dec. 5, 2005                 *
'*                                                                                 *
'*            Written and compiled successfully with mikroBASIC 2.2                *
'*     mikroBASIC libraries and utilites are implemented to work easily with       *
'*   the mikroElektronika EasyPIC development board with a 16x2 Character LCD      *
'*                                                                                 *
'* This is a demonstration program for the Character LCD that can be adapted for   *
'* real-world applications such as a KWh Meter, BTU Meter, Liquid Flow Meter, etc. *
'* The visual effect of an older mechanical odometer is possible by using the LCD  *
'* controller's user-RAM area, where the user can place up to 8 custom characters  *
'* of 8 bytes each.  In this program a table was created, "char5x7", that "byte-   *
'* maps" the numbers 0 to 9.  Through a series of table offsets you can build new  *
'* characters that include part of one and part of the next.  This is how the      *
'* rolling effect is created and generated.                                        *
'*                                                                                 *
'* The code is built in a modular style to allow a user to find his way to add or  *
'* subtract from the 8 Decade Digits that are used for this demonstration.  This   *
'* counter will count to 99,999,999 before rolling over to zeroes. You can enter a *
'* manual starting point by setting the digit values and the LCD_OUT value to      *
'* match these values.  The decimal in the display is arbitrary...... Enjoy!       *
'***********************************************************************************

const char5x7 as byte[88] = (14, 17, 19, 21, 25, 17, 14, 0,          ' "0"
                             4, 12, 4, 4, 4, 4, 14, 0,               ' "1"
                             14, 17, 1, 2, 4, 8, 31, 0,              ' "2"
                             31, 2, 4, 2, 1, 17, 14, 0,              ' "3"
                             2, 6, 10, 18, 31, 2, 2, 0,              ' "4"
                             31, 16, 30, 1, 1, 17, 14, 0,            ' "5"
                             6, 8, 16, 30, 17, 17, 14, 0,            ' "6"
                             31, 1, 2, 4, 8, 8, 8, 0,                ' "7"
                             14, 17, 17, 14, 17, 17, 14, 0,          ' "8"
                             14, 17, 17, 15, 1, 2, 12, 0,            ' "9"
                             14, 17, 19, 21, 25, 17, 14, 0)          ' "0"

const choffset as byte[10] = (0, 8, 16, 24, 32, 40, 48, 56, 64, 72)  ' character table offset values
const chpos as byte[8] = (64, 72, 80, 88, 96, 104, 112, 120)         ' user-ram character addresses
dim digit0 as byte
dim digit1 as byte
dim digit2 as byte
dim digit3 as byte
dim digit4 as byte
dim digit5 as byte
dim digit6 as byte
dim digit7 as byte
dim dig1flag as byte
dim dig2flag as byte
dim dig3flag as byte
dim dig4flag as byte
dim dig5flag as byte
dim dig6flag as byte
dim dig7flag as byte
dim aa as byte

sub procedure sgl_char(dim dig, offset, pos as byte)     ' routine loads characters into CGRAM (user-RAM)
  dim counter as byte
      dig = choffset[dig] + offset                       ' digit value and offset
      LCD_CMD(chpos[pos])                                ' starting CGRAM address for this character
      For counter = dig to dig + 7                       ' load 8 bytes into CGRAM
         LCD_CHR_CP(char5x7[counter])
      Next counter
end sub

main:

  PORTB = 0                                              ' initialize ports and variables
  TRISB = 0
  LCD_INIT(PORTB)                                        ' initialize LCD
  LCD_CMD(LCD_CLEAR)
  LCD_CMD(LCD_CURSOR_OFF)
  LCD_OUT(1, 1, "8 DIGIT ODOMETER")                      ' print to LCD first
  LCD_OUT(2, 4,"0000000.0")
  digit0 = 0
  digit1 = 0
  digit2 = 0
  digit3 = 0
  digit4 = 0
  digit5 = 0
  digit6 = 0
  digit7 = 0
  dig1flag = 0
  dig2flag = 0
  dig3flag = 0
  dig4flag = 0
  dig5flag = 0
  dig6flag = 0
  dig7flag = 0

      While true                                         ' start an endless loop
         For aa = 0 to 7                                 ' set up character byte offsets
            delay_ms(40)                                 ' delay can be adjusted to speed or slow demo
            sgl_char(digit0,aa,0)                        ' send digit0 to be processed
            LCD_CHR(2,12,0)                              ' print digit0 located at user-ram 0
            If dig1flag = 1 Then                         ' check to see if digit1 is also moving
               sgl_char(digit1,aa,1)                     ' if so then process and display
               LCD_CHR(2,10,1)                           ' print digit1 located at user-ram 1
            End If
            If dig2flag = 1 Then                         ' check to see if digit2 is also moving
               sgl_char(digit2,aa,2)                     ' if so then process and display
               LCD_CHR(2,9,2)                            ' print digit1 located at user-ram 2
            End If
            If dig3flag = 1 Then                         ' check to see if digit3 is also moving
               sgl_char(digit3,aa,3)                     ' if so then process and display
               LCD_CHR(2,8,3)                            ' print digit3 located at user-ram 3
            End If
            If dig4flag = 1 Then                         ' check to see if digit4 is also moving
               sgl_char(digit4,aa,4)                     ' if so then process and display
               LCD_CHR(2,7,4)                            ' print digit4 located at user-ram 4
            End If
            If dig5flag = 1 Then                         ' check to see if digit5 is also moving
               sgl_char(digit5,aa,5)                     ' if so then process and display
               LCD_CHR(2,6,5)                            ' print digit5 located at user-ram 5
            End If
            If dig6flag = 1 Then                         ' check to see if digit6 is also moving
               sgl_char(digit6,aa,6)                     ' if so then process and display
               LCD_CHR(2,5,6)                            ' print digit6 located at user-ram 6
            End If
            If dig7flag = 1 Then                         ' check to see if digit7 is also moving
               sgl_char(digit7,aa,7)                     ' if so then process and display
               LCD_CHR(2,4,7)                            ' print digit7 located at user-ram 7
            End If
         Next aa                                         ' cycle through all phases of digit movement
         If dig1flag = 1 Then                            ' housekeeping for recently moved digit1
               sgl_char(digit1, 8, 1)                    ' bump digit1 up 1 more byte...snap into place
               LCD_CHR(2,10,1)                           ' print
               dig1flag = 0                              ' reset flag until next required advance
               inc(digit1)                               ' get next value ready for next move
               If digit1 = 10 Then digit1 = 0 End If     ' rollover to zero if over 9
         End If
         If dig2flag = 1 Then                            ' housekeeping for recently moved digit2
               sgl_char(digit2, 8, 2)
               LCD_CHR(2,9,2)
               dig2flag = 0
               inc(digit2)
               If digit2 = 10 Then digit2 = 0 End If
         End If
         If dig3flag = 1 Then                            ' housekeeping for recently moved digit3
               sgl_char(digit3, 8, 3)
               LCD_CHR(2,8,3)
               dig3flag = 0
               inc(digit3)
               If digit3 = 10 Then digit3 = 0 End If
         End If
         If dig4flag = 1 Then                            ' housekeeping for recently moved digit4
               sgl_char(digit4, 8, 4)
               LCD_CHR(2,7,4)
               dig4flag = 0
               inc(digit4)
               If digit4 = 10 Then digit4 = 0 End If
         End If
         If dig5flag = 1 Then                            ' housekeeping for recently moved digit5
               sgl_char(digit5, 8, 5)
               LCD_CHR(2,6,5)
               dig5flag = 0
               inc(digit5)
               If digit5 = 10 Then digit5 = 0 End If
         End If
         If dig6flag = 1 Then                            ' housekeeping for recently moved digit6
               sgl_char(digit6, 8, 6)
               LCD_CHR(2,5,6)
               dig6flag = 0
               inc(digit6)
               If digit6 = 10 Then digit6 = 0 End If
         End If
         If dig7flag = 1 Then                            ' housekeeping for recently moved digit7
               sgl_char(digit7, 8, 7)
               LCD_CHR(2,4,7)
               dig7flag = 0
               inc(digit7)
               If digit7 = 10 Then digit7 = 0 End If
         End If
         inc(digit0)                                     ' housekeeping for recently moved digit0
         If digit0 = 10 Then  digit0 = 0 End If
         If digit0 = 9 Then dig1flag = 1 End If             ' Advance the next higher digit?
         If digit1 + dig1flag = 10 Then dig2flag = 1 End If ' Advance the next higher digit?
         If digit2 + dig2flag = 10 Then dig3flag = 1 End If ' Advance the next higher digit?
         If digit3 + dig3flag = 10 Then dig4flag = 1 End If ' Advance the next higher digit?
         If digit4 + dig4flag = 10 Then dig5flag = 1 End If ' Advance the next higher digit?
         If digit5 + dig5flag = 10 Then dig6flag = 1 End If ' Advance the next higher digit?
         If digit6 + dig6flag = 10 Then dig7flag = 1 End If ' Advance the next higher digit?
      Wend                                                  ' do it all again
end.
[color=darkred][b]xor[/b][/color]
[url=http://circuit-ed.com]CircuitED -[/url]

xor
Posts: 5465
Joined: 18 May 2005 00:59
Location: NYC
Contact:

#2 Post by xor » 11 Nov 2007 21:23

I have now posted a video demonstration of this cool program I wrote nearly 2 years ago in mikroBasic. The following code will compile for PIC16 and PIC18 and uses the LCD4 library functions (you can find those here: LCD4 Optimized Code Library). Using LCD4 functions reduces the size of code to enable compiling using the free demo version of mikroBasic. Here's the code:

Code: Select all

program ODOMETER_R1

'***********************************************************************************
'*        Tested on 18F452 @ 40MHz....8 DECADE COUNTER....ODOMETER STYLE           *
'*             Program by W. Schroeder alias "xor" on Dec. 5, 2005                 *
'*      Updated implementation of LCD4 to reduce code size... Nov 11, 2007         *
'*            Written and compiled successfully with mikroBASIC 6.0                *
'*                                                                                 *
'***********************************************************************************

include "lcd4"

const char5x7 as byte[88] = (14, 17, 19, 21, 25, 17, 14, 0,          ' "0"
                             4, 12, 4, 4, 4, 4, 14, 0,               ' "1"
                             14, 17, 1, 2, 4, 8, 31, 0,              ' "2"
                             31, 2, 4, 2, 1, 17, 14, 0,              ' "3"
                             2, 6, 10, 18, 31, 2, 2, 0,              ' "4"
                             31, 16, 30, 1, 1, 17, 14, 0,            ' "5"
                             6, 8, 16, 30, 17, 17, 14, 0,            ' "6"
                             31, 1, 2, 4, 8, 8, 8, 0,                ' "7"
                             14, 17, 17, 14, 17, 17, 14, 0,          ' "8"
                             14, 17, 17, 15, 1, 2, 12, 0,            ' "9"
                             14, 17, 19, 21, 25, 17, 14, 0)          ' "0"

const choffset as byte[10] = (0, 8, 16, 24, 32, 40, 48, 56, 64, 72)  ' character table offset values
const chpos as byte[8] = (64, 72, 80, 88, 96, 104, 112, 120)         ' user-ram character addresses
dim digit0 as byte
dim digit1 as byte
dim digit2 as byte
dim digit3 as byte
dim digit4 as byte
dim digit5 as byte
dim digit6 as byte
dim digit7 as byte
dim dig1flag as byte
dim dig2flag as byte
dim dig3flag as byte
dim dig4flag as byte
dim dig5flag as byte
dim dig6flag as byte
dim dig7flag as byte
dim aa as byte

sub procedure sgl_char(dim dig, offset, pos as byte)     ' routine loads characters into CGRAM (user-RAM)
  dim counter as byte
      dig = choffset[dig] + offset                       ' digit value and offset
      LCD4_CMD(chpos[pos])                               ' starting CGRAM address for this character
      For counter = dig to dig + 7                       ' load 8 bytes into CGRAM
         LCD4_CHR(char5x7[counter])
      Next counter
end sub

main:

  PORTB = 0                                              ' initialize ports and variables
  TRISB = 0
  LCD4_INIT                                              ' initialize LCD
  LCD4_CMD(130)
  LCD4_OUT("8 DIGIT ODOMETER")
  LCD4_CMD(197)                                          ' print to LCD first
  LCD4_OUT("9999990.0")
  digit0 = 0
  digit1 = 0
  digit2 = 9
  digit3 = 9
  digit4 = 9
  digit5 = 9
  digit6 = 9
  digit7 = 9
  dig1flag = 0
  dig2flag = 0
  dig3flag = 0
  dig4flag = 0
  dig5flag = 0
  dig6flag = 0
  dig7flag = 0

      While true                                         ' start an endless loop
         For aa = 0 to 7                                 ' set up character byte offsets
            delay_ms(35)                                 ' delay can be adjusted to speed or slow display
            sgl_char(digit0,aa,0)                        ' send digit0 to be processed
            LCD4_CMD(205)
            LCD4_CHR(0)                                  ' print digit0 located at user-ram 0
            If dig1flag = 1 Then                         ' check to see if digit1 is also moving
               sgl_char(digit1,aa,1)                     ' if so then process and display
               LCD4_CMD(203)
               LCD4_CHR(1)                                ' print digit1 located at user-ram 1
            End If
            If dig2flag = 1 Then                         ' check to see if digit2 is also moving
               sgl_char(digit2,aa,2)                     ' if so then process and display
               LCD4_CMD(202)
               LCD4_CHR(2)                               ' print digit1 located at user-ram 2
            End If
            If dig3flag = 1 Then                         ' check to see if digit3 is also moving
               sgl_char(digit3,aa,3)                     ' if so then process and display
               LCD4_CMD(201)
               LCD4_CHR(3)                               ' print digit3 located at user-ram 3
            End If
            If dig4flag = 1 Then                         ' check to see if digit4 is also moving
               sgl_char(digit4,aa,4)                     ' if so then process and display
               LCD4_CMD(200)
               LCD4_CHR(4)                               ' print digit4 located at user-ram 4
            End If
            If dig5flag = 1 Then                         ' check to see if digit5 is also moving
               sgl_char(digit5,aa,5)                     ' if so then process and display
               LCD4_CMD(199)
               LCD4_CHR(5)                               ' print digit5 located at user-ram 5
            End If
            If dig6flag = 1 Then                         ' check to see if digit6 is also moving
               sgl_char(digit6,aa,6)                     ' if so then process and display
               LCD4_CMD(198)
               LCD4_CHR(6)                               ' print digit6 located at user-ram 6
            End If
            If dig7flag = 1 Then                         ' check to see if digit7 is also moving
               sgl_char(digit7,aa,7)                     ' if so then process and display
               LCD4_CMD(197)
               LCD4_CHR(7)                               ' print digit7 located at user-ram 7
            End If
         Next aa                                         ' cycle through all phases of digit movement
         If dig1flag = 1 Then                            ' housekeeping for recently moved digit1
               sgl_char(digit1, 8, 1)                    ' bump digit1 up 1 more byte...snap into place
               LCD4_CMD(203)
               LCD4_CHR(1)                               ' print
               dig1flag = 0                              ' reset flag until next required advance
               inc(digit1)                               ' get next value ready for next move
               If digit1 = 10 Then digit1 = 0 End If     ' rollover to zero if over 9
         End If
         If dig2flag = 1 Then                            ' housekeeping for recently moved digit2
               sgl_char(digit2, 8, 2)
               LCD4_CMD(202)
               LCD4_CHR(2)
               dig2flag = 0
               inc(digit2)
               If digit2 = 10 Then digit2 = 0 End If
         End If
         If dig3flag = 1 Then                            ' housekeeping for recently moved digit3
               sgl_char(digit3, 8, 3)
               LCD4_CMD(201)
               LCD4_CHR(3)
               dig3flag = 0
               inc(digit3)
               If digit3 = 10 Then digit3 = 0 End If
         End If
         If dig4flag = 1 Then                            ' housekeeping for recently moved digit4
               sgl_char(digit4, 8, 4)
               LCD4_CMD(200)
               LCD4_CHR(4)
               dig4flag = 0
               inc(digit4)
               If digit4 = 10 Then digit4 = 0 End If
         End If
         If dig5flag = 1 Then                            ' housekeeping for recently moved digit5
               sgl_char(digit5, 8, 5)
               LCD4_CMD(199)
               LCD4_CHR(5)
               dig5flag = 0
               inc(digit5)
               If digit5 = 10 Then digit5 = 0 End If
         End If
         If dig6flag = 1 Then                            ' housekeeping for recently moved digit6
               sgl_char(digit6, 8, 6)
               LCD4_CMD(198)
               LCD4_CHR(6)
               dig6flag = 0
               inc(digit6)
               If digit6 = 10 Then digit6 = 0 End If
         End If
         If dig7flag = 1 Then                            ' housekeeping for recently moved digit7
               sgl_char(digit7, 8, 7)
               LCD4_CMD(197)
               LCD4_CHR(7)
               dig7flag = 0
               inc(digit7)
               If digit7 = 10 Then digit7 = 0 End If
         End If
         inc(digit0)                                     ' housekeeping for recently moved digit0
         If digit0 = 10 Then  digit0 = 0 End If
         If digit0 = 9 Then dig1flag = 1 End If             ' Advance the next higher digit?
         If digit1 + dig1flag = 10 Then dig2flag = 1 End If ' Advance the next higher digit?
         If digit2 + dig2flag = 10 Then dig3flag = 1 End If ' Advance the next higher digit?
         If digit3 + dig3flag = 10 Then dig4flag = 1 End If ' Advance the next higher digit?
         If digit4 + dig4flag = 10 Then dig5flag = 1 End If ' Advance the next higher digit?
         If digit5 + dig5flag = 10 Then dig6flag = 1 End If ' Advance the next higher digit?
         If digit6 + dig6flag = 10 Then dig7flag = 1 End If ' Advance the next higher digit?
      Wend                                                  ' do it all again
end.
[color=darkred][b]xor[/b][/color]
[url=http://circuit-ed.com]CircuitED -[/url]

Post Reply

Return to “mikroBasic General”