           COP8 Pulse counter and 2-way LCD multiplex drive
                           demo board








Author: Volker Soffel


Version:  1.1


Date:     30.Nov. 1990

Abstract

The COP8 Pulse counter demo board  demonstrates the capability of 
the  COP8's versatile 16bit timer to perform precise  pulse  time 
measurements as well as the ability to drive a 2 way  multiplexed 
LCD without the need for a dedicated LCD driver. This demo board is 
on the Application note AN-673 "2 way Multiplexed LCD drive..." and
uses the same software, except that a different type of LCD is used
and as such a different look-up table for the LCD data is implemented.
The frequency measurement routine has been improved over the version
printed in the app note.
 

Introduction

Two small demo software routines have been implemented:
One  is  a BCD downcounter routine which is selected  as  default 
after power-up.  By pressing the left push button (T1) the second 
routine,  which does a period time measurement, is activated. The 
board  contains  a square wave generator,  with the  square  wave 
period time adustable between approximately 134us and 280us.  The 
output  is connected to the COP8's timer input. The COP8 performs 
a time period  measurement every 500ms and displays the result on 
a  3 1/2 digit 2-way multiplexed LCD.  For comparison the  square 
wave  generator's pulse time can also be monitored by  connecting 
an external period counter to the BNC connector on the board. 

Hardware description

The  hardware  of  the  demo board  consists  of  a  square  wave 
generator,  a 3 1/2 digit 2 way multiplex LCD, the COP820C and a 
few passive components.

The  square  wave generator on the demo board is  built  using  a 
LMC555 timer in the astable mode.

The output frequency f of the 555 is determined by the formula:

                       f= 1.44/((Ra + 2Rb)*C)            

        The output high time is given by:

                       t1= 0.693* (Ra+Rb)*C

        The output low time is given by:

                       t2= 0.693* Rb* C

        The total time period is:

                       T= t1+t2 = 0.693* (Ra+ 2Rb)* C


The time period of the square wave generator can be varied in the 
range  of  134us  to 280us as the resistor Rb is  realized  as  a 
series combination of a fixed value (220k) and a potentiometer of 
250k.    

The  output  of  the square wave generator is  connected  to  the 
COP8's  timer input (TIO) as well as to a  BNC   connector,  thus 
providing  the  possibility to connect an  external  period  time 
counter and compare its result with the time period  measured  by 
the COP8.  


BCD down counter

The  BCD  downcounter routine presets  a  16-bit  binary  counter 
composed  of  two  RAM registers (BCNTL,BCNTH)  with  the  binary 
equivalent  of 3999 decimal.  This counter is  decremented  every 
1/10s.  The LCD drive subroutine does a binary to BCD  conversion 
of  the actual counter value and updates the display  with  every 
new value.  After the counter has reached 0000 it is preset  with 
3999 again. 


Time period measurement

The  COP8 16-bit timer is ideally suited for precise period  time 
measurements with minimal software overhead. This timer has three 
programmable  operating modes.  The "input capture" mode is  used 
for the time period measurement.  Associated with the timer is  a 
16 bit "autoload/capture" register.  The G3-I/O-pin serves as the 
timer  input  (TIO).  In the "input capture" mode  the  timer  is 
decremented  with  the instruction  cycle  frequency  (tc).  Each 
positive going edge at TIO (also neg.  edge programmable)  causes 
the  timer  value  to  be  copied  automatically  to  the   auto-
load/capture  register without stopping the timer  or  destroying 
its contents. The "timer pending" flag (TPND) in the PSW-register 
is  set  to indicate that a capture has occurred,  and  if  timer 
interrupt is enabled,  an interrupt is created.  The time  period  
measurement  routine listed below executes the  following  opera-
tions  (refer to the RAM/register definition file listed  at  the 
beginning for symbolic names used in the routines).

The timer is preset with FFFFh and is started by setting the TRUN 
bit,  after  which  the software checks the TPND flag in  a  loop 
(timer  interrupt  is disabled).  When the TPND flag is  set  the 
first time,  the contents of the capture register is saved to RAM 
locations STALO and STAHI (start value).  The TPND flag now  must 
be reset by the software.  Then,  another 20 positive going edges 
are counted (equal to 20 pulses) before the timer is stopped  and 
the  "input capture mode" is disabled to prevent overwriting  the 
capture register with the next positive going edge.
The contents of the capture register (end value) is now  subtrac-
ted  from  the  start value and the result  is  restored  in  RAM 
locations STALO,STAHI.  This value can then be used to  calculate 
the  time  period of the frequency applied to TIO(G3)  by  multi-
plying it with the tc-time and dividing the result by the  number 
of pulses measured (N=20).

        T= (startvalue- endvalue)*tc/N

The result is the time period  (in us) which is displayed on a  2 
way multiplexed LCD.
In  this demo board application first a period time  measurement, 
during  which  the  LCD is off is made and  then  the  result  is 
displayed  for  500ms on the LCD.  Then the LCD is  switched  off 
again and the COP8 makes a new measurement. As the time needed to 
complete one measurement cycle is very short the LCD seems to  be 
on all the time.
Note,  that  in this mode  a slight flickering of a 500ms  period 
can be seen if the LCD is viewed from a slight side angle.


The  shortest  time  period  which  can  be  measured  equals  13 
instruction  cycles.  This number is calculated out of the  worst 
case number of instruction cycles the time period routine has  to 
execute  between successive pulses.  A maximum of 26  instruction 
cycles  are executed between the occurence of the first  positive 
going edge (label L1:) and the next reset of the TPND flag (label 
DECOU:).  Obviously  that the TPND flag has to be cleared  before 
the  third  positive edge occurs to ensure that a  pulse  is  not 
lost.  Thus  the  minimum  time  duration  for  2  pulses  is  26 
instruction  cycles  which gives a time period (1  pulse)  of  13 
instruction cycles.  The maximum frequency which can be  measured 
is calculated as:

               fmax = 1/(13 * tc)

Running the COP800 at 5MHz (tc=2us),  fmax= 38.46kHz and  running 
at the maximum clock speed of 10MHz, fmax= 76.92kHz. 

2 way-multiplexed LCD drive

Today  a wide variety of LCDs,  ranging from static to  multiplex 
rates of 1:64 are available on the market.  The multiplex rate of 
a LCD can be determined by the number of its backplanes (segment-
common plate).  The higher the multiplex rate the more individual 
segments can be controlled using only one line. E.g. a static LCD 
only has one backplane;   only one segment can be controlled with 
one  line.  A two way-multiplexed LCD has two backplanes and  two 
segments can be controlled with one line, etc.
Common  to  all kind of LCDs is the fact that the  drive  voltage 
applied  to the backplane(s) and segments has to be  alternating. 
DC-components  higher than 100mV can cause electrochemical  reac-
tions (refer to manufacturer's spec) which reduce the reliability 
and lifetime of the display.

If  the  multiplex  ratio  of the LCD is  N  and  the  amount  of 
available outputs is M, the number of segments that can be driven 
is:

        S = (M-N) * N

So  the maximum number of a 2way -mux LCD's segments that can  be 
driven  with  a COP8 in a 28-pin package (if all outputs  can  be 
used to drive the LCD) is:

        S = (18-2) * 2 = 32

        
 
During  one LCD refresh cycle tx (typical values for 1/tx=fx  are 
in the range 30 ... 60 Hz), three different voltage levels - Vop, 
0.5*Vop  and 0 volts - have to be generated.  The  "off"  voltage 
across a segment is not 0 volts as with static LCDs and also  the 
"on" voltage is not Vop,  but only a fraction of it. The ratio of 
"on" to "off" r.m.s-voltage (discrimination) is determined by the 
multiplex  ratio and the number of voltage levels  involved.  The 
most  desirable  discrimination ratio is one that  maximises  the 
ratio  of Von to Voff,  allowing the maximum  voltage  difference 
between  activated  and  non-activated  states.  In  general  the 
maximum  achievable ratio for any particular value of N is  given 
by:

        (Von/Voff)max = SQR((SQR(N)+1)/(SQR(N)-1))
    
        SQR= square root

Using  this  formula the maximum achievable discrimination  ratio 
for a 2-way multiplex LCD is 2.41, however it is also possible to 
order  a customized display with a smaller ratio.  Because it  is 
easier for the designer, most LCD drivers use equal voltage steps 
(0V,0.5*Vop,Vop).  Thus a discrimination ratio of 2.24 is  achie-
ved.  When  using the COP8 to drive a 2-way multiplexed  LCD  the 
only  external  hardware required to achieve  the  three  voltage 
steps are 4 equal resistors that form two voltage dividers -  one 
for each backplane (see fig.  1). The procedure is to set G4 & G5 
to  "0"  for 0V,  to HI-Z (Tri-State) for 0.5*Vop and to  "1"  in 
order to establish Vop at the backplane electrodes.

With  the  COP800 each  I/0-Pin can be set individually  to  Tri-
state,"1"  or  "0",  so this procedure can be   implemented  very 
easily.
The  current consumption of typical LCDs is in the range of  3  - 
4uA  (at Vop=4.5V,  refresh rate 60Hz ) per square centimetre  of 
activated area,  thus the backplane and segment terminals can  be 
treated  as  Hi-Z loads.  At high refresh rates the  LCD  current 
consumption increases dramatically,  a reason why many LCD  manu-
facturers  recommend not to use a refresh frequency  higher  than 
60Hz.
 
Timing considerations

As  shown  in  figures  2 and 3,  one LCD  refresh  cycle  tx  is 
subdivided into four equally distant time sections  ta,tb,tc  and 
td  during which the backplane and segment terminals have  to  be 
updated  in  order  to  switch a  specific  segment  on  or  off. 
Considering  a refresh frequency of 50 Hz (tx=20ms) ta,tb,tc  and 
td  are equal to 5ms;  a COP8 running from an external  clock  of 
2Mhz has an internal instruction cycle time of 5us and a  typical 
current  consumption  of  less than 350uA  (at  Vcc=3V  and  room 
temperature),  thus meeting both the requirements of low  current 
consumption and additional computing power between LCD refreshes.
The timing is done using the COP8's 16 bit timer in the  autoload 
mode.  The  timer  and the assigned 16bit autoload  register  are 
preset  with the appropriate value.  By setting the TRUN-flag  in 
the  CNTRL-register the timer is decremented at each  instruction 
cycle,  setting  a  flag (TPND) at  underflow  and  automatically 
reloading with the value stored in the  autoload-register.  Timer 
underflow can also be programmed to create an interrupt. 

Segment control

Figure  2  shows the voltage-waveforms applied to the  two  back-
plane-electrodes (a) and the waveform at a segment-electrode (b), 
which  is needed to switch segment A on and segment B   off.  The 
resulting voltage over the segments (c&d) is achieved by subtrac-
ting waveform (b) from BP1 (segment A) and waveform (b) from  BP2 
(segment B).           

Figure  3  shows  the  four different  waveforms  which  must  be 
generated  to  meet  all possible combinations  of  two  segments 
connected to the same driving terminal (off-off,on-off,off-on,on-
on).

Figure 4 shows the internal segment and backplane connections for 
a typical 2way-mux LCD. 


LCD drive subroutine

The  LCD  drive subroutine DISPL  converts a binary  16bit  value 
into a 24bit BCD-value for easier display data fetch.  The  drive 
subroutine  itself  is  built  up of a  main  routine  doing  the 
backplane  refresh and 7 subroutines  (SEG0,  SEG1,  SEG2,  SEG3, 
SEGOUT,  TTPND,  DISPD). The subroutines SEG0 to SEG3 are used to 
get  the  LCD  segment  data from a  look-up  table  in  ROM  for 
timephases ta,tb,tc and td respectively. Subroutine SEGOUT writes 
the  segment  data  for each timephase to  the  according  output 
ports. One timephase takes 5ms, giving a total refresh cycle time 
of  20ms  (50Hz).  The exact timing is done by using  the  COP8's 
16bit  timer  in the autoload mode.  In that mode  the  timer  is 
reloaded with the value stored in the autoload register on  every 
timer underflow.  At the same time the timer pending flag is set. 
The  subroutine TTPND checks this flag in a loop.  If  the  timer 
pending flag is set, this subroutine resets it and returns to the 
calling  program.  Thus  a 5ms time delay is created  before  the 
segment  and backplane data for the next timephase is written  to 
the  ouput ports.  The subroutine DISPD  switches off the LCD  by 
setting the backplane and segment connections to "0".  

;***************************************************** 
;*       NATIONAL SEMICONDUCTOR CORPORATION          * 
;*        Microcontroller Application Lab            * 
;*                                                   * 
;*         COP800  Microcontroller Family            * 
;*                                                   * 
;* Programm Name: PULS34V2                           * 
;* Source File  : PULS34V2.ASM                       * 
;*                                                   * 
;* Operation    : BCD DOWN COUNTER AND               * 
;*              : FREQUENCY PERIOD-TIME MEASUREMENT  * 
;*              :                                    * 
;*              : TIME IS DISPLAYED ON A 2-WAY       * 
;*              : MULTIPLEXED DISPLAY DIRECTLY       * 
;*              : DRIVEN BY THE COP8                 * 
;*                                                   * 
;* Input Param. : SQUARE WAVE FREQUENCY AT TIO (G3)- * 
;*              : INPUT                              * 
;*                                                   * 
;* Results      : PERIOD TIME IN us                  * 
;*              : Tmin =  366us  (=27.7kHz)          * 
;*              : Tmax = 399.9us (=2500Hz)           * 
;*                                                   * 
;* Programmer   :  VOLKER SOFFEL                     * 
;* Date         :  08.11.1990                        * 
;*                                                   * 
;***************************************************** 
; 
;COP8 CLOCK FREQUENCY = 5MHz (INSTRUCTION CYCLE TIME 
; = 2us) 
;Tmin IS DETERMINED BY THE MAX. TIME THE ROUTINE NEEDS 
;     TO CHECK THE TPND FLAG (=13 INSTRUCTION CYCLES 
;     WORST CASE) 
;Tmax IS ONLY LIMITED BY THE NUMBER OF LCD DIGITS 
;     AVAILABLE AND THE TIME UNTIL TIMER UNDERFLOW

 
     .INCLD COP820C.INC    ;COP REGISTER DEFINITION FILE 
     .CHIP 820 
;****           RAM-DEFINITIONS     *****

        BCDLO    = 000  ;MEASURED PERIOD TIME IN BCD 
                        ;LOW BYTE 
;                  001  ;BCD 2ND BYTE 
        BCDHI    = 002  ;MEASURED PERIOD TIME IN BCD 
                        ;MOST  SIGNIFICANT BYTE 
        MWBUF0   = 003  ;7SEGMENT DATA FOR LCD DISPL 
                        ;L-PORT 
        MWBUF1   = 004  ;D-PORT 
        MWBUF2   = 005  ;G-PORT 
        OFF1     = 006  ;OFFSET REGISTERS FOR 
        OFF2     = 007  ;7 SEGMENT CODE TABLE 
        OFF3     = 008  ; 
        STALO    = 009  ;START VALUE,LOW BYTE 
        STAHI    = 00A  ;START VALUE,HIGH BYTE

        ;STATUS REGISTER FLAGS 
        STATUS   = 00D  ;STATUS REGISTER 
        MODE     = 000  ;MODUS FLAG, TOGGLES BETWEEN 
                        ;2 OPERATION MODES (BCD COUNTER, 
                        ;(PULSE COUNTER)

       ;02C.. 02F RESERVED FOR STACK

;****           REGISTER DEFINITIONS      ****

        COUNT  = 0F0    ;COUNT REGISTERS FOR DISPL 
        COUNT2 = 0F1    ;ROUTINE 
        BCNTL  = 0F2    ;BINARY COUNTER LOW BYTE 
        BCNTH  = 0F3    ;BINARY COUNTER HIGH BYTE

;*****       G-PORT BIT DEFINITIONS         *****

        BP1  = 05       ;BACKPLANE 1 
        BP2  = 04       ;BACKPLANE 2

        NMP = 9           ;NUMBER OF PULSES TO 
                           ;MEASURE := NMP+1=20

 
        LD      SP,#02F    ;INITIALIZE STACK POINTER 
BINIT: 
        JSR     DISPD      ;DEFINE PORT CONFIGURATIONS 
                           ;SWITCH DISPLAY OFF 
        IFBIT   0,PORTI    ;IF KEY RELEASED 
        JP      OK1        ;THEN OK 
        JP      BINIT      ;ELSE WAIT

OK1: 
        LD      B,#STATUS 
        RBIT    MODE,[B]

        LD      BCNTH,#00F ;SET COUNTER TO 3999 DECIMAL 
        LD      BCNTL,#09F 
BLOOP: 
        LD      B,#BCNTL 
        LD      X,#STALO 
        JSR     COPY        ;PASS BINARY COUNTER VALUE 
                            ;OVER TO DISPLAY SUBROUTINE 
                            ;VIA STALO,STAHI REGISTERS

        LD      COUNT2,#001 ;DISPLAY TIME= 100MS 
        JSR     DISPL 
BLOOP2: 
        LD      B,#STATUS 
        IFBIT   MODE,[B]    ;IF MODE TOGGLED 
        JP      FMEAS       ;THEN EXECUTE FREQUENCY 
                            ;MEASUREMENT ROUTINE 
        DRSZ    BCNTL       ;DECREMENT BINARY COUNTER 
                            ;LOW BYTE 
        JP      BLOOP       ;DISPLAY NEW VALUE 
                            ;IF BINARY COUNTER LOW BYTE 
                            ;= 0 
        LD      B,#BCNTL    ;THEN DISPLAY 
        LD      X,#STALO 
        JSR     COPY 
        LD      COUNT2,#001 
        JSR     DISPL       ;DISPLAY FOR 100ms

        DRSZ    BCNTH       ;DECREMENT BINARY COUNTER 
        NOP                 ;HIGH BYTE 
        LD      A,BCNTH 
        IFEQ    A,#0FF      ;IF HIGH BYTE<0 
        JP      BINIT       ;THEN INIT COUNTER TO 3999 DEC 
        JP      BLOOP2      ;ELSE CONTINUE TO DISPLAY

 
FMEAS:                      ;FREQUENCY MEASURE ROUTINE 
                            ;PERIOD TIME= 
                            ;(START-ENDVALUE)*tc/(NMP+1) 
        JSR     DISPD       ;DEFINE PORT CONFIGURATIONS 
                            ;SWITCH DISPLAY OFF 
        IFBIT   0,PORTI     ;IF KEY RELEASED 
        JP      OK2         ;THEN OK 
        JP      FMEAS       ;ELSE WAIT 
OK2: 
        LD      B,#STATUS 
        RBIT    MODE,[B] 
FM2: 
        LD      COUNT,#NMP   ;LOAD PULSE COUNTER 
        LD      B,#TMRLO 
        LD      [B+],#0FF   ;PRESET TIMER WITH FFFFh 
        LD      [B],#0FF 
        LD      B,#CNTRL 
        LD      [B+],#0D0   ;CNTRL-REG.: TIMER CAPTURE 
                            ;MODE,TIO POS. TRIGGERED, 
                            ;START TIMER 
                            ;B-POINT TO PSW REGISTER 
        LD      X,#TAULO    ;X-POINT TO AUTO REG. LOW BYTE 
        RBIT    #TPND,[B]   ;RESET TIMER PENDING FLAG 
L1: 
        IFBIT   #TPND,[B]   ;POSITIVE EDGE DETECTED? 
        JP      SSTORE      ;YES,STORE TIMER VALUE 
        JP      L1          ;YES, LOOP 
SSTORE:                     ;STORE START VALUE 
        RBIT    #TPND,[B] 
        LD      A,[X+]      ;LOAD TIMER AUTOLOAD REG. 
                            ;LOW BYTE 
        X       A,STALO     ;SAVE IN STALO 
        LD      A,[X-]      ;LOAD HIGH BYTE AUTOLOAD, 
                            ;POINT TO LOW BYTE AUTOLOAD 
                            ;18 instr. cycles 
        X       A,STAHI     ;SAVE IN STAHI 
L2: 
        IFBIT   #TPND,[B] 
        JP      DCOU 
        JP      L2 
DCOU:   RBIT    #TPND,[B]   ;RESET TIMER PENDING FLAG 
        DRSZ    COUNT       ;DECREMENT PULSE COUNTER 
                            ;COUNTER = 0 ? 
        JP      L2          ;NO,LOOP 'TIL 9 PULSES 
                            ;HAVE BEEN MEASURED 
L3: 
        IFBIT   #TPND,[B] 
        JP      ESTORE 
        JP      L3 
ESTORE:                     ;STORE END VALUE 
        LD      CNTRL,#00   ;STOP TIMER, DISABLE TIMER CAPTURE 
                            ;MODE 
        LD      B,#STALO    ;POINT TO START VALUE LOW BYTE 
        LD      A,[X+]      ;LOAD AUTOLOAD LOW BYTE 
        X       A,[B]       ;EXCHANGE END VALUE WITH START 
                            ;VALUE LOW BYTE 
        SC 
        SUBC    A,[B]       ;SUBTRACT ENDVALUE LOW BYTE 
                            ;FROM START VALUE LOW BYTE 
        X       A,[B+]      ;STORE RESULT IN STALO 
        LD      A,[X] 
        X       A,[B] 
        SUBC    A,[B]       ;SUBTRACT ENDVALUE HIGH BYTE 
                            ;FROM START VALUE HIGH BYTE 
        X       A,[B]       ;STORE RESULT IN STAHI



        LD      COUNT2,#5 
        JSR     DISPL      ;DISPLAY MEASURED PERIOD TIME 
                           ;FOR 0.5 SEC 
        JSR     DISPD      ;SWITCH DISPLAY OFF 
        IFBIT   MODE,STATUS 
        JP      BINIT 
        JP      FMEAS      ;DO NEW MEASUREMENT

 
        . = X'200         ;START OF LCD LOOKUP-TABLE

 
        ;TIMEPHASE Ta 7 SEGMENT DATA 
        .BYTE   008     ;"0" AND ".0" 
        .BYTE   00E     ;"1" AND ".1" 
        .BYTE   004     ;"2" AND ".2" 
        .BYTE   004     ;"3" AND ".3" 
        .BYTE   002     ;"4" AND ".4" 
        .BYTE   001     ;"5" AND ".5" 
        .BYTE   001     ;"6" AND ".6" 
        .BYTE   00C     ;"7" AND ".7" 
        .BYTE   000     ;"8" AND ".8" 
        .BYTE   000     ;"9" AND ".9" 
        .BYTE   00F     ;" " AND ". "

 
        . = X'210 
        ;TIMEPHASE Tb 7 SEGMENT DATA 
        .BYTE   004     ;"0" 
        .BYTE   00E     ;"1" 
        .BYTE   005     ;"2" 
        .BYTE   00C     ;"3" 
        .BYTE   00E     ;"4" 
        .BYTE   00C     ;"5" 
        .BYTE   004     ;"6" 
        .BYTE   00E     ;"7" 
        .BYTE   004     ;"8" 
        .BYTE   00C     ;"9" 
        .BYTE   00F     ;" " 
        .BYTE   000     ;".0" 
        .BYTE   00A     ;".1" 
        .BYTE   001     ;".2" 
        .BYTE   008     ;".3" 
        .BYTE   00A     ;".4" 
        .BYTE   008     ;".5" 
        .BYTE   000     ;".6" 
        .BYTE   00A     ;".7" 
        .BYTE   000     ;".8" 
        .BYTE   008     ;".9" 
        .BYTE   00B     ;". "

        . = X'230 
        ;TIMEPHASE Tc 7 SEGMENT DATA 
        .BYTE   007     ;"0" AND ".0" 
        .BYTE   001     ;"1" AND ".1" 
        .BYTE   00B     ;"2" AND ".2" 
        .BYTE   00B     ;"3" AND ".3" 
        .BYTE   00D     ;"4" AND ".4" 
        .BYTE   00E     ;"5" AND ".5" 
        .BYTE   00E     ;"6" AND ".6" 
        .BYTE   003     ;"7" AND ".7" 
        .BYTE   00F     ;"8" AND ".8" 
        .BYTE   00F     ;"9" AND ".9" 
        .BYTE   000     ;" " AND ". "

        .LOCAL

        . = X'240 
        ;TIMEPHASE Td 7 SEGMENT DATA 
        .BYTE   00B     ;"0" 
        .BYTE   001     ;"1" 
        .BYTE   00A     ;"2" 
        .BYTE   003     ;"3" 
        .BYTE   001     ;"4" 
        .BYTE   003     ;"5" 
        .BYTE   00B     ;"6" 
        .BYTE   001     ;"7" 
        .BYTE   00B     ;"8" 
        .BYTE   003     ;"9" 
        .BYTE   000     ;" " 
        .BYTE   00F     ;".0" 
        .BYTE   005     ;".1" 
        .BYTE   00E     ;".2" 
        .BYTE   007     ;".3" 
        .BYTE   005     ;".4" 
        .BYTE   007     ;".5" 
        .BYTE   00F     ;".6" 
        .BYTE   005     ;".7" 
        .BYTE   00F     ;".8" 
        .BYTE   007     ;".9" 
        .BYTE   004     ;". " 
        . = X'260 
        ;DIGIT 3  CODES 
        .BYTE   007     ;TA"  " 
        .BYTE   006     ;TA"1" 
        .BYTE   004     ;TA"2" 
        .BYTE   004     ;TA"3"

        .BYTE   007     ;TB"  " 
        .BYTE   006     ;TB"1" 
        .BYTE   005     ;TB"2" 
        .BYTE   006     ;TB"3"

        .BYTE   000     ;TC"  " 
        .BYTE   001     ;TC"1" 
        .BYTE   003     ;TC"2" 
        .BYTE   003     ;TC"3"

        .BYTE   000     ;TD"  " 
        .BYTE   001     ;TD"1" 
        .BYTE   002     ;TD"2" 
        .BYTE   001     ;TD"3"

        .LOCAL 
TTPND: 
        LD      B,#PSW 
$LOOP: 
        IFBIT   #TPND,[B] 
        JP      $END 
        JP      $LOOP 
$END: 
        RBIT    #TPND,[B] 
        LD      B,#PORTGD 
        RET 
        .LOCAL 
COPY:                       ;COPY 2BYTES POINTED TO 
                            ;BY B AND B+1 TO RAM 
                            ;POINTED TO BY X AND X+1 
        LD      A,[B+] 
        X       A,[X+] 
        LD      A,[B+] 
        X       A,[X+] 
        RET

 
;DISPL:

;LCD DRIVE ROUTINE FOR LCD TYPE 3420 (Electronic Assembly) 2 WAY MULTIPLEX 
;LCD 
;ROUTINE CONVERTS BCD DATA STORED IN RAM LOCATIONS 
;BCDLO, BCDHI INTO LCD OUTPUT DATA STORED AT 
;MWBUF0 = LPORT DATA 
;MWBUF1 = DPORT DATA 
;MWBUF2 = G-PORT DATA (G0,G1 ONLY, OTHER BITS 
;                      STAY UNCHANGED) 
;SUBROUTINES INCLUDED: 
;SEG0: GETS LCD SEGMENT DATA FOR TIMEPHASE TA 
;SEG1: GETS LCD SEGMENT DATA FOR TIMEPHASE TB 
;SEG2: GETS LCD SEGMENT DATA FOR TIMEPHASE TC 
;SEG3: GETS LCD SEGMENT DATA FOR TIMEPHASE TD 
;DISPLD: SWITCHES THE DISPLAY OFF AND 
;        CONFIGURES G-,L- AND D-PORTS 
;TTPND:  CHECKS TIMER PENDING FLAG (REFRESH 
;        RATE GENERATION) 
;        ROUTINE IS CONTAINED IN THE LCD3420.TBL 
;        FILE 
;SEGOUT: OUTPUTS LCD SEGMENT AND BACKPLANE DATA

        .LOCAL

SEG0: 
        LD      B,#OFF1  ;POINT TO OFFSET 1 REG. 
        LD      [B+],#000 
        LD      [B+],#000 
        LD      A,#060 
$LPORT: 
        X       A,[B]   ;SAVE OFFSET DIGIT 3 DATA 
        LD      X,#BCDLO 
        LD      B,#MWBUF0 
        LD      A,[X] 
        AND     A,#00F  ;ELIMINATE  DIGIT1 BITS 
        ADD     A,OFF1 
        LAID            ;GET DIGIT0 DATA 
        X       A,[B]   ;SAVE DIGIT 0 DATA 
                        ;IN MWBUF0 
        LD      A,[X+] 
        AND     A,#0F0  ;ELIMINATE DIGIT0 BITS 
        SWAP    A 
        ADD     A,OFF2 
        LAID            ;GET DIGIT1 DATA 
        SWAP    A 
        OR      A,[B]   ;STORE DIGIT0 AND 
        X       A,[B+]  ;DIGIT1 DATA IN MWBUF0 
$DPORT: 
        LD      A,[X] 
        AND     A,#00F  ;ELIMINATE DIGIT3 BITS 
        ADD     A,OFF2 
        LAID            ;GET DIGIT2 DATA 
        X       A,[B+]  ;STORE DIGIT2 DATA IN 
                        ;MWBUF1 
$GPORT: 
        LD      A,[X] 
        AND     A,#0F0  ;ELIMINATE DIGIT2 BITS 
        SWAP    A 
        ADD     A,OFF3 
        LAID            ;GET DIGIT3 DATA 
        OR      A,#0F8  ;SET BITS 3... 7 TO 1 
        X       A,[B]   ;SAVE DIGIT3 DATA IN MWBUF2 
        RET 
SEG1: 
        LD      B,#OFF1 
        LD      [B+],#01B 
        LD      [B+],#010 
        LD      A,#064 
        JP      $LPORT 
SEG2: 
        LD      B,#OFF1 
        LD      [B+],#030 
        LD      [B+],#030 
        LD      A,#068 
        JP      $LPORT 
SEG3: 
        LD      B,#OFF1 
        LD      [B+],#04B 
        LD      [B+],#040 
        LD      A,#06C 
        JP      $LPORT 
        .LOCAL

DISPL: 
        JSR     BINBCD16 
        LD      COUNT,#5 
        LD      B,#TMRLO 
        LD      [B+],#0C4 ;LOAD TIMER WITH 2500(09C4h) 
        LD      [B+],#009 ;(=50 Hz LCD REFRESH) 
        LD      [B+],#0C4 ;LOAD AUTOREG. WITH 1000 
        LD      [B+],#009 
        LD      [B+],#090 ;CNTRL-REG.:AUTORELOAD MODE, 
                          ;START TIMER 
        LD      [B],#010  ;RESET TIMER PENDING FLAG 
DISP1: 
        JSR     SEG0      ;GET 7-SEGM. DATA FOR REFRESH 
                          ;TIMEPHASE Ta 
        JSR     TTPND     ;TEST TIMER PENDING FLAG 
TP0:                      ;BACKPLANE REFRESH Ta 
        SBIT    #BP1,[B] 
        LD      A,[B+]    ;POINT TO G-CONFIG.-REG. 
        RBIT    #BP2,[B] 
        SBIT    #BP1,[B] 
        LD      A,[B-]    ;POINT TO G-DATA REG. 
        RBIT    #BP2,[B] 
        JSR     SEGOUT    ;SEGMENT DATA OUT 
        JSR     SEG1      ;GET 7-SEG. DATA FOR Tb 
        JSR     TTPND 
TP1: 
        SBIT    #BP2,[B] 
        LD      A,[B+]    ;POINT TO G-CONF.-REG. 
        RBIT    #BP1,[B] 
        SBIT    #BP2,[B] 
        LD      A,[B-]    ;POINT TO G-DATA REG. 
        RBIT    #BP1,[B] 
        JSR     SEGOUT 
        JSR     SEG2      ;GET 7-SEGM. DATA FOR Tc 
        JSR     TTPND 
TP2: 
        RBIT    #BP1,[B] 
        LD      A,[B+]    ;POINT TO G-CONFIG.-REG. 
        RBIT    #BP2,[B] 
        SBIT    #BP1,[B] 
        LD      A,[B-]    ;POINT TO G-DATA-REG. 
        RBIT    #BP2,[B] 
        JSR     SEGOUT 
        JSR     SEG3 
        JSR     TTPND 
TP3: 
        RBIT    #BP1,[B] 
        RBIT    #BP2,[B] 
        LD      A,[B+] 
        RBIT    #BP1,[B] 
        SBIT    #BP2,[B] 
        JSR     SEGOUT 
        JSR     BUTTON    ;TEST PUSH BUTTON 
        DRSZ    COUNT 
        JP      DISP1 
        LD      COUNT,#5 
        DRSZ    COUNT2 
        JP      DISP1 
        RET

SEGOUT: 
        LD      B,#MWBUF0 
        LD      A,[B+]    ;POINT TO MWBUF1 
        X       A,PORTLD  ;OUTPUT 7 SEG. DATA IN 
                          ;MWBUF0 TO L-PORT 
        LD      A,[B+]    ;POINT TO MWBUF2 
        X       A,PORTD   ;OUTPUT MWBUF1 TO D-PORT 
        LD      X,#PORTGD 
        LD      A,[X] 
        AND     A,[B]     ;AND MWBUF2 WITH PORTGD 
        X       A,[B]     ;STORE RESULT (A')IN 
                          ;MWBUF2,LOAD A WITH 
                          ;ORIGINAL MWBUF2 VALUE 
        AND     A,#007    ;AND 007 WITH ORIGINAL 
                          ;MWBUF2 (A'') 
        OR      A,[B]     ;OR  A' WITH A'' 
        X       A,[X]     ;OUTPUT RESULT TO G-PORT 
        RET 
DISPD:                     ;SWITCH DISPLAY OFF 
        LD      B,#PORTLD 
        LD      [B+],#000  ;OUTPUT 0 TO L PORT 
        LD      [B+],#0FF  ;L-PORT = OUTPUT PORT 
        LD      B,#PORTGD 
        LD      [B+],#000  ;OUTPUT 0 TO G OUTPUTS 
        LD      [B+],#037  ;G0..G2,G4,G5=OUTPUTS 
        LD      PORTD,#000 ;OUTPUT 0 TO D-PORT 
        RET

BUTTON: 
        IFBIT   0,PORTI    ;IF BUTTON NOT PRESSED 
        RET                ;THEN RETURN 
        SBIT    MODE,STATUS ;ELSE SET MODE TOGGLE FLAG 
        RET



        BINLO = STALO 
;***************************************************** 
;*       NATIONAL SEMICONDUCTOR CORPORATION          * 
;*        Microcontroller Application Lab            * 
;*        Fuerstenfeldbruck, West Germany            * 
;*                                                   * 
;*         COP800  Microcontroller Family            * 
;*                                                   * 
;* Programm Name: BINBCD16                           * 
;* Source File  : BINBCD16.MAC                       * 
;*                                                   * 
;* Operation    : 16 BIT BINARY TO BCD CONVERSION    * 
;*                                                   * 
;* Input Param. : BINLO: RAM ADRESS BINARY LOW BYTE  * 
;*              : BCDLO: RAM ADRESS BCD LOW BYTE     * 
;*              : COUNT: RAM ADRESS SHIFT COUNTER    * 
;*              :        (0F0...0FB,0FF)             * 
;*                                                   * 
;* Results      : BCD NUMBER IN BCDLO,BCDLO+1,BCDLO+2* 
;*                                                   * 
;* Programmer   : VOLKER SOFFEL                      * 
;* Date         : 27.01.89                           * 
;*                                                   * 
;***************************************************** 
; 
;THE MEMORY ASSIGNMEMTS ARE AS FOLLOWS: 
; 
;MEMORY ADRESS        M(BINLO+1)  M(BINLO) 
;DATA                 BINARY HB   BINARY LOW BYTE 
; 
;MEMORY ADRESS        M(BCDLO+2)  M(BCDLO+1)  M(BCDLO) 
;DATA                 BCD HB      BCD         BCD LOW BYTE 
;



        .LOCAL 
        $BCDT = (BCDLO + 3) & 0F 
        $BINT = (BINLO + 2) & 0F 
BINBCD: 
        LD      COUNT,#16 ;LOAD CONTROL REGISTER WITH 
                          ;NUMBER OF LEFTSHIFTS TO 
                          ;EXECUTE 
        LD      B,#BCDLO  ;LOAD BCD-NUMBER LOWEST BYTE 
                          ;ADRESS

$CBCD:                    ;CLEAR BCD RAM-REGISTERS 
        LD      [B+],#00 
        IFBNE   #$BCDT 
        JP      $CBCD 
$LSH:                     ;LEFTSHIFT BINARY NUMBER 
        LD      B,#BINLO 
        RC 
$LSHFT: 
        LD      A,[B] 
        ADC     A,[B]     ;IF MSB IS SET, SET CARRY 
        X       A,[B+] 
        IFBNE   #$BINT 
        JP      $LSHFT 
        LD      B,#BCDLO 
$BCDADD: 
        LD      A,[B] 
        ADD     A,#066    ;ADD CORRECTION FACTOR 
        ADC     A,[B]     ;LEFTSHIFT BCD NUMBER 
                          ;(BCD=2**WEIGHT OF 
                          ;BINARY BIT(=CARRY BIT)) 
        DCOR    A         ;DECIMAL CORRECT ADDITION 
        X       A,[B+] 
        IFBNE   #$BCDT 
        JP      $BCDADD 
        DRSZ    COUNT     ;DECREMENT SHIFT COUNTER 
        JP      $LSH 
        RET 
        .LOCAL 
        .END 

