Examples Index

' =========================================================================
'
'   File...... TIMER.SXB
'   Purpose... Dual-Mode digital timer
'   Author.... (c) Parallax, Inc. -- All Rights Reserved
'   E-mail.... support@parallax.com
'   Started...
'   Updated... 05 JUL 2006
'
' =========================================================================

' -------------------------------------------------------------------------
' Program Description
' -------------------------------------------------------------------------
'
' Displays running clock/timer on multiplexed 7-segment display.  The
' four-digit display is multiplexed through a "virtual" driver which is
' handled in the INTERRUPT routine.

' -------------------------------------------------------------------------
' Device Settings
' -------------------------------------------------------------------------

DEVICE          SX28, OSCXT2, TURBO, STACKX, OPTIONX
FREQ            4_000_000
ID              "TIMER"

' -------------------------------------------------------------------------
' IO Pins
' -------------------------------------------------------------------------

DigCtrl         VAR     RA                      ' digit control (cathodes)
Segs            VAR     RB                      ' display segments (anodes)
TmrMode         VAR     RC.6                    ' mode: 0 = mmss, 1 = hhmm
TmrEnable       VAR     RC.7                    ' enable input, 1 = run

' -------------------------------------------------------------------------
' Constants
' -------------------------------------------------------------------------

Yes             CON     1
No              CON     0

MaxDigit        CON     4                       ' 4-digit display
DecPnt          CON     %10000000               ' decimal point mask

TmrMMSS         CON     1                       ' show MM.SS (no blink)
TmrHHMM         CON     0                       ' show HH.MM (blink DP)
TmrRun          CON     1                       ' run timer
TmrHold         CON     0                       ' hold timer

MaxHr           CON     24                      ' 0 .. 23 (clock mode)
                                                ' make 100 for 0 .. 99

' -------------------------------------------------------------------------
' Variables
' -------------------------------------------------------------------------

ms              VAR     Word                    ' milliseconds
clock           VAR     Byte(3)                 ' clock array
secs            VAR     clock(0)                ' seconds
mins            VAR     clock(1)                ' minutes
hrs             VAR     clock(2)

blink           VAR     secs.0                  ' DP blink control bit

display         VAR     Byte(MaxDigit)          ' multiplexed segments
digPntr         VAR     Byte                    ' digit pointer

tmpB1           VAR     Byte
tmpB2           VAR     Byte

' -------------------------------------------------------------------------
  INTERRUPT 1000
' -------------------------------------------------------------------------

' The ISR is called every millisecond using the Rate parameter of the
' INTERRUPT instruction.  With a 4 MHz clock, the prescaler will be set
' 1:16 and the ISR will run every 250 RTCC cycles.
'
' If the timer is enabled (TmrEnable pin = 1), the timer values will be
' updated every millisecond, otherwise only the display will be refreshed
' (one digit per interrupt).

ISR_Start:
  IF TmrEnable = TmrHold THEN Next_Digit        ' skip clock update if 0

Update_Timer:
  INC ms                                        ' update ms counter
  IF ms = 1000 THEN                             ' check for 1 second
    ms = 0
    INC secs
    IF secs = 60 THEN                           ' check for new minute
      secs = 0
      INC mins
      IF mins = 60 THEN                         ' check for new hour
        mins = 0
        INC hrs
        IF hrs = MaxHr THEN
          hrs = 0
        ENDIF
      ENDIF
    ENDIF
  ENDIF

Next_Digit:
  INC digPntr                                   ' point to next digit
  IF digPntr = MaxDigit THEN                    ' check pointer
    digPntr = 0                                 ' wrap if needed
  ENDIF

Update_Segs:
  Segs = %00000000                              ' blank segments
  READ DigMap + digPntr, DigCtrl                ' update digit control
  Segs = display(digPntr)                       ' output new segments

ISR_Exit:
  RETURNINT

' =========================================================================
  PROGRAM Start
' =========================================================================

' -------------------------------------------------------------------------
' Subroutine Declarations
' -------------------------------------------------------------------------

CLOCK_MMSS      SUB     0                       ' show mins & secs
CLOCK_HHMM      SUB     0                       ' show hrs & mins

' -------------------------------------------------------------------------
' Program Code
' -------------------------------------------------------------------------

Start:
  DigCtrl = %1111                               ' disable all digits
  TRIS_A = %0000                                ' make dig pins outputs
  Segs = %00000000                              ' clear seg drivers
  TRIS_B = %00000000                            ' make seg pins outputs
  PLP_C = %11000000                             ' pull-up unused pins

Main:
  DO
    PAUSE 50
    IF TmrMode = TmrHHMM THEN                   ' check mode
      CLOCK_HHMM
    ELSE
      CLOCK_MMSS
    ENDIF
  LOOP

' -------------------------------------------------------------------------
' Subroutine Code
' -------------------------------------------------------------------------

' Display timer in MM.SS (00.00 .. 59.59) format with solid DP

CLOCK_MMSS:                                     ' display mins & secs
  tmpB1 = mins / 10                             ' get 10's digit
  tmpB2 = __REMAINDER                           ' save 1's digit
  READ SegMap + tmpB1, display(3)
  READ SegMap + tmpB2, display(2)
  display(2) = display(2) | DecPnt              ' add DP to hr01 digit
  tmpB1 = secs / 10
  tmpB2 = __REMAINDER
  READ SegMap + tmpB1, display(1)
  READ SegMap + tmpB2, display(0)
  RETURN

' -------------------------------------------------------------------------

' Display timer in HH.MM (00.00 .. 23.59) format with blinking DP

CLOCK_HHMM:                                     ' display hours & mins
  tmpB1 = hrs / 10
  tmpB2 = __REMAINDER
  READ SegMap + tmpB1, display(3)
  READ SegMap + tmpB2, display(2)
  IF blink = Yes THEN
    display(2) = display(2) | DecPnt            ' blink DP on hr01 digit
  ENDIF
  tmpB1 = mins / 10
  tmpB2 = __REMAINDER
  READ SegMap + tmpB1, display(1)
  READ SegMap + tmpB2, display(0)
  RETURN

' =========================================================================
' User Data
' =========================================================================

SegMap:                                         ' segments maps
'        .gfedcba
  DATA  %00111111                               ' 0
  DATA  %00000110                               ' 1
  DATA  %01011011                               ' 2
  DATA  %01001111                               ' 3
  DATA  %01100110                               ' 4
  DATA  %01101101                               ' 5
  DATA  %01111101                               ' 6
  DATA  %00000111                               ' 7
  DATA  %01111111                               ' 8
  DATA  %01100111                               ' 9

DigMap:                                         ' digit select map
  DATA  %11111110
  DATA  %11111101
  DATA  %11111011
  DATA  %11110111